Merge from Chromium at DEPS revision r210036

This commit was generated by merge_to_master.py.

Change-Id: Ib0e33a83ad5dfa541481e83d7acfc6970e68f471
diff --git a/chrome/OWNERS b/chrome/OWNERS
index db459f4..51e026c 100644
--- a/chrome/OWNERS
+++ b/chrome/OWNERS
@@ -29,7 +29,6 @@
 per-file chrome_android.gypi=aruslan@chromium.org
 per-file chrome_android.gypi=bulach@chromium.org
 per-file chrome_android.gypi=dtrainor@chromium.org
-per-file chrome_android.gypi=nileshagrawal@chromium.org
 per-file chrome_android.gypi=tedchoc@chromium.org
 per-file chrome_android.gypi=yfriedman@chromium.org
 
diff --git a/chrome/VERSION b/chrome/VERSION
index 07be3e0..4ba63ae 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
-MAJOR=29
+MAJOR=30
 MINOR=0
-BUILD=1543
+BUILD=1556
 PATCH=0
diff --git a/chrome/android/OWNERS b/chrome/android/OWNERS
index 4927e8c..1f9608a 100644
--- a/chrome/android/OWNERS
+++ b/chrome/android/OWNERS
@@ -1,6 +1,5 @@
 aruslan@chromium.org
 bulach@chromium.org
 dtrainor@chromium.org
-nileshagrawal@chromium.org
 tedchoc@chromium.org
 yfriedman@chromium.org
diff --git a/chrome/android/java/res/drawable-xhdpi/infobar_insecure.png b/chrome/android/java/res/drawable-xhdpi/infobar_insecure.png
deleted file mode 100644
index aa8335d..0000000
--- a/chrome/android/java/res/drawable-xhdpi/infobar_insecure.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable/infobar_insecure.png b/chrome/android/java/res/drawable/infobar_insecure.png
deleted file mode 100644
index c8fbccd..0000000
--- a/chrome/android/java/res/drawable/infobar_insecure.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/layout/autofill_text.xml b/chrome/android/java/res/layout/autofill_text.xml
deleted file mode 100644
index 08aede0..0000000
--- a/chrome/android/java/res/layout/autofill_text.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (c) 2012 The Chromium Authors. All rights reserved.
-
-     Use of this source code is governed by a BSD-style license that can be
-     found in the LICENSE file.
--->
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                android:layout_height="fill_parent"
-                android:layout_width="fill_parent"
-                android:background="#FFF"
-                android:orientation="horizontal">
-  <TextView android:id="@+id/autofill_label"
-            android:layout_alignParentEnd="true"
-            android:layout_width="wrap_content"
-            android:layout_height="fill_parent"
-            android:padding="5dp"
-            android:textSize="18sp"
-            android:textColor="#CCC"
-            android:ellipsize="end"
-            android:singleLine="true"/>
-  <TextView android:id="@+id/autofill_name"
-            android:layout_alignParentStart="true"
-            android:layout_width="wrap_content"
-            android:layout_height="fill_parent"
-            android:padding="5dp"
-            android:background="#FFF"
-            android:textSize="18sp"
-            android:textColor="#000"
-            android:ellipsize="end"
-            android:singleLine="true"/>
-</RelativeLayout>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/DevToolsServer.java b/chrome/android/java/src/org/chromium/chrome/browser/DevToolsServer.java
index f5777aa..37f943d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/DevToolsServer.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/DevToolsServer.java
@@ -11,9 +11,8 @@
 
     private int mNativeDevToolsServer = 0;
 
-    public DevToolsServer(boolean useBundledFrontendResources,
-                          String socketName) {
-        mNativeDevToolsServer = nativeInitRemoteDebugging(useBundledFrontendResources, socketName);
+    public DevToolsServer(String socketNamePrefix) {
+        mNativeDevToolsServer = nativeInitRemoteDebugging(socketNamePrefix);
     }
 
     public void destroy() {
@@ -29,8 +28,7 @@
         nativeSetRemoteDebuggingEnabled(mNativeDevToolsServer, enabled);
     }
 
-    private native int nativeInitRemoteDebugging(boolean useBundledFrontendResources,
-            String socketName);
+    private native int nativeInitRemoteDebugging(String socketNamePrefix);
     private native void nativeDestroyRemoteDebugging(int devToolsServer);
     private native boolean nativeIsRemoteDebuggingEnabled(int devToolsServer);
     private native void nativeSetRemoteDebuggingEnabled(int devToolsServer, boolean enabled);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillDialog.java
index 29b207e..fa5cd66 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillDialog.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillDialog.java
@@ -202,11 +202,6 @@
         public String getLegalDocumentsText();
 
         /**
-         * @return The progress bar label.
-         */
-        public String getProgressBarText();
-
-        /**
          * @param section The section.
          * @param position The index of an item.
          * @return Whether an item is the "Add..." item.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillDialogGlue.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillDialogGlue.java
index 0c25f26..a62f872 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillDialogGlue.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillDialogGlue.java
@@ -312,11 +312,6 @@
     }
 
     @Override
-    public String getProgressBarText() {
-        return nativeGetProgressBarText(mNativeDialogPopup);
-    }
-
-    @Override
     public boolean isTheAddItem(int section, int position) {
         return nativeIsTheAddItem(mNativeDialogPopup, section, position);
     }
@@ -439,7 +434,6 @@
             int dialogButtonId);
     private native String nativeGetSaveLocallyText(int nativeAutofillDialogViewAndroid);
     private native String nativeGetLegalDocumentsText(int nativeAutofillDialogViewAndroid);
-    private native String nativeGetProgressBarText(int nativeAutofillDialogViewAndroid);
     private native boolean nativeIsTheAddItem(
             int nativeAutofillDialogViewAndroid, int section, int index);
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillListAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillListAdapter.java
deleted file mode 100644
index 123db1a..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillListAdapter.java
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.autofill;
-
-import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.TextView;
-
-import org.chromium.chrome.R;
-
-import java.util.ArrayList;
-
-/**
- * Autofill suggestion adapter for AutofillWindow.
- */
-public class AutofillListAdapter extends ArrayAdapter<AutofillSuggestion> {
-    private Context mContext;
-
-    AutofillListAdapter(Context context, ArrayList<AutofillSuggestion> objects) {
-        super(context, R.layout.autofill_text, objects);
-        mContext = context;
-    }
-
-    @Override
-    public View getView(int position, View convertView, ViewGroup parent) {
-        View layout = convertView;
-        if (convertView == null) {
-            LayoutInflater inflater =
-                    (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-            layout = inflater.inflate(R.layout.autofill_text, null);
-        }
-        TextView nameView = (TextView) layout.findViewById(R.id.autofill_name);
-        nameView.setText(getItem(position).mName);
-        TextView labelView = (TextView) layout.findViewById(R.id.autofill_label);
-        labelView.setText(getItem(position).mLabel);
-
-        return layout;
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillPopup.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillPopup.java
deleted file mode 100644
index c1b5d9a..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillPopup.java
+++ /dev/null
@@ -1,202 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.autofill;
-
-import android.content.Context;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnLayoutChangeListener;
-import android.widget.AdapterView;
-import android.widget.ListPopupWindow;
-import android.widget.TextView;
-
-import java.util.ArrayList;
-
-import org.chromium.chrome.R;
-import org.chromium.ui.ViewAndroidDelegate;
-
-/**
- * The Autofill suggestion popup that lists relevant suggestions.
- */
-public class AutofillPopup extends ListPopupWindow implements AdapterView.OnItemClickListener {
-
-    /**
-     * Constants defining types of Autofill suggestion entries.
-     * Has to be kept in sync with enum in WebAutofillClient.h
-     *
-     * Not supported: MenuItemIDWarningMessage, MenuItemIDSeparator, MenuItemIDClearForm, and
-     * MenuItemIDAutofillOptions.
-     */
-    private static final int ITEM_ID_AUTOCOMPLETE_ENTRY = 0;
-    private static final int ITEM_ID_PASSWORD_ENTRY = -2;
-    private static final int ITEM_ID_DATA_LIST_ENTRY = -6;
-
-    private static final int TEXT_PADDING_DP = 40;
-
-    private final AutofillPopupDelegate mAutofillCallback;
-    private final Context mContext;
-    private final ViewAndroidDelegate mViewAndroidDelegate;
-    private View mAnchorView;
-    private float mAnchorWidth;
-    private float mAnchorHeight;
-    private float mAnchorX;
-    private float mAnchorY;
-    private Paint mNameViewPaint;
-    private Paint mLabelViewPaint;
-    private OnLayoutChangeListener mLayoutChangeListener;
-
-    /**
-     * An interface to handle the touch interaction with an AutofillPopup object.
-     */
-    public interface AutofillPopupDelegate {
-        /**
-         * Requests the controller to hide AutofillPopup.
-         */
-        public void requestHide();
-
-        /**
-         * Handles the selection of an Autofill suggestion from an AutofillPopup.
-         * @param listIndex The index of the selected Autofill suggestion.
-         */
-        public void suggestionSelected(int listIndex);
-    }
-
-    /**
-     * Creates an AutofillWindow with specified parameters.
-     * @param context Application context.
-     * @param viewAndroidDelegate View delegate used to add and remove views.
-     * @param autofillCallback A object that handles the calls to the native AutofillPopupView.
-     */
-    public AutofillPopup(Context context, ViewAndroidDelegate viewAndroidDelegate,
-            AutofillPopupDelegate autofillCallback) {
-        super(context);
-        mContext = context;
-        mViewAndroidDelegate = viewAndroidDelegate ;
-        mAutofillCallback = autofillCallback;
-
-        setOnItemClickListener(this);
-
-        mAnchorView = mViewAndroidDelegate.acquireAnchorView();
-        mViewAndroidDelegate.setAnchorViewPosition(mAnchorView, mAnchorX, mAnchorY, mAnchorWidth,
-                mAnchorHeight);
-
-        mLayoutChangeListener = new OnLayoutChangeListener() {
-            @Override
-            public void onLayoutChange(View v, int left, int top, int right, int bottom,
-                    int oldLeft, int oldTop, int oldRight, int oldBottom) {
-                if (v == mAnchorView) AutofillPopup.this.show();
-            }
-        };
-
-        mAnchorView.addOnLayoutChangeListener(mLayoutChangeListener);
-        setAnchorView(mAnchorView);
-    }
-
-    /**
-     * Sets the location and the size of the anchor view that the AutofillPopup will use to attach
-     * itself.
-     * @param x X coordinate of the top left corner of the anchor view.
-     * @param y Y coordinate of the top left corner of the anchor view.
-     * @param width The width of the anchor view.
-     * @param height The height of the anchor view.
-     */
-    public void setAnchorRect(float x, float y, float width, float height) {
-        mAnchorWidth = width;
-        mAnchorHeight = height;
-        mAnchorX = x;
-        mAnchorY = y;
-        if (mAnchorView != null) {
-            mViewAndroidDelegate.setAnchorViewPosition(mAnchorView, mAnchorX, mAnchorY,
-                    mAnchorWidth, mAnchorHeight);
-        }
-    }
-
-    /**
-     * Sets the Autofill suggestions to display in the popup and shows the popup.
-     * @param suggestions Autofill suggestion data.
-     */
-    public void show(AutofillSuggestion[] suggestions) {
-        // Remove the AutofillSuggestions with IDs that are not supported by Android
-        ArrayList<AutofillSuggestion> cleanedData = new ArrayList<AutofillSuggestion>();
-        for (int i = 0; i < suggestions.length; i++) {
-            int itemId = suggestions[i].mUniqueId;
-            if (itemId > 0 || itemId == ITEM_ID_AUTOCOMPLETE_ENTRY ||
-                    itemId == ITEM_ID_PASSWORD_ENTRY || itemId == ITEM_ID_DATA_LIST_ENTRY) {
-                cleanedData.add(suggestions[i]);
-            }
-        }
-        setAdapter(new AutofillListAdapter(mContext, cleanedData));
-        // Once the mAnchorRect is resized and placed correctly, it will show the Autofill popup.
-        mAnchorWidth = Math.max(getDesiredWidth(suggestions), mAnchorWidth);
-        mViewAndroidDelegate.setAnchorViewPosition(mAnchorView, mAnchorX, mAnchorY, mAnchorWidth,
-                mAnchorHeight);
-    }
-
-    /**
-     * Overrides the default dismiss behavior to request the controller to dismiss the view.
-     */
-    @Override
-    public void dismiss() {
-        mAutofillCallback.requestHide();
-    }
-
-    /**
-     * Hides the popup and removes the anchor view from the ContainerView.
-     */
-    public void hide() {
-        super.dismiss();
-        mAnchorView.removeOnLayoutChangeListener(mLayoutChangeListener);
-        mViewAndroidDelegate.releaseAnchorView(mAnchorView);
-    }
-
-    /**
-     * Get desired popup window width by calculating the maximum text length from Autofill data.
-     * @param data Autofill suggestion data.
-     * @return The popup window width in DIP.
-     */
-    private float getDesiredWidth(AutofillSuggestion[] data) {
-        if (mNameViewPaint == null || mLabelViewPaint == null) {
-            LayoutInflater inflater =
-                    (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-            View layout = inflater.inflate(R.layout.autofill_text, null);
-            TextView nameView = (TextView) layout.findViewById(R.id.autofill_name);
-            mNameViewPaint = nameView.getPaint();
-            TextView labelView = (TextView) layout.findViewById(R.id.autofill_label);
-            mLabelViewPaint = labelView.getPaint();
-        }
-
-        float maxTextWidth = 0;
-        Rect bounds = new Rect();
-        for (int i = 0; i < data.length; ++i) {
-            bounds.setEmpty();
-            String name = data[i].mName;
-            float width = 0;
-            if (name.length() > 0) {
-                mNameViewPaint.getTextBounds(name, 0, name.length(), bounds);
-            }
-            width += bounds.width();
-
-            bounds.setEmpty();
-            String label = data[i].mLabel;
-            if (label.length() > 0) {
-                mLabelViewPaint.getTextBounds(label, 0, label.length(), bounds);
-            }
-            width += bounds.width();
-            maxTextWidth = Math.max(width, maxTextWidth);
-        }
-        // Scale it down to make it unscaled by screen density.
-        maxTextWidth = maxTextWidth / mContext.getResources().getDisplayMetrics().density;
-        // Adding padding.
-        return maxTextWidth + TEXT_PADDING_DP;
-    }
-
-    @Override
-    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
-        mAutofillCallback.suggestionSelected(position);
-    }
-
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillPopupGlue.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillPopupGlue.java
index b22434d..fc8f4ed 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillPopupGlue.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillPopupGlue.java
@@ -6,10 +6,12 @@
 
 import org.chromium.base.CalledByNative;
 import org.chromium.base.JNINamespace;
-import org.chromium.chrome.browser.autofill.AutofillPopup.AutofillPopupDelegate;
 import org.chromium.ui.ViewAndroid;
 import org.chromium.ui.ViewAndroidDelegate;
 import org.chromium.ui.WindowAndroid;
+import org.chromium.ui.autofill.AutofillPopup;
+import org.chromium.ui.autofill.AutofillPopup.AutofillPopupDelegate;
+import org.chromium.ui.autofill.AutofillSuggestion;
 
 /**
 * JNI call glue for AutofillExternalDelagate C++ and Java objects.
@@ -81,14 +83,14 @@
     /**
      * @param array AutofillSuggestion array that should get a new suggestion added.
      * @param index Index in the array where to place a new suggestion.
-     * @param name Name of the suggestion.
-     * @param label Label of the suggestion.
+     * @param label First line of the suggestion.
+     * @param sublabel Second line of the suggestion.
      * @param uniqueId Unique suggestion id.
      */
     @CalledByNative
     private static void addToAutofillSuggestionArray(AutofillSuggestion[] array, int index,
-            String name, String label, int uniqueId) {
-        array[index] = new AutofillSuggestion(name, label, uniqueId);
+            String label, String sublabel, int uniqueId) {
+        array[index] = new AutofillSuggestion(label, sublabel, uniqueId);
     }
 
     private native void nativeRequestHide(int nativeAutofillPopupViewAndroid);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillSuggestion.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillSuggestion.java
deleted file mode 100644
index adfd0f9..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillSuggestion.java
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.autofill;
-
-/**
- * Autofill suggestion container used to store information needed for each Autofill popup entry.
- */
-public class AutofillSuggestion {
-    public final String mName;
-    public final String mLabel;
-    public final int mUniqueId;
-
-    /**
-     * Constructs a Autofill suggestion container.
-     * @param name The name of the Autofill suggestion.
-     * @param label The describing label of the Autofill suggestion.
-     * @param uniqueId The unique id used to identify the Autofill suggestion.
-     */
-    public AutofillSuggestion(String name, String label, int uniqueId) {
-        mName = name;
-        mLabel = label;
-        mUniqueId = uniqueId;
-    }
-}
\ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/favicon/FaviconHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/favicon/FaviconHelper.java
new file mode 100644
index 0000000..fc82dd1
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/favicon/FaviconHelper.java
@@ -0,0 +1,90 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.favicon;
+
+import android.graphics.Bitmap;
+
+import org.chromium.base.CalledByNative;
+import org.chromium.chrome.browser.profiles.Profile;
+
+/**
+ * This is a helper class to use favicon_service.cc's functionality.
+ *
+ * You can request a favicon image by web page URL. Note that an instance of this class should be
+ * created & used & destroyed (by destroy()) in the same thread due to the C++ CancelableTaskTracker
+ * class requirement.
+ */
+public class FaviconHelper {
+
+    // Please keep in sync with favicon_types.h's IconType.
+    public static final int INVALID_ICON = 0;
+    public static final int FAVICON = 1 << 0;
+    public static final int TOUCH_ICON = 1 << 1;
+    public static final int TOUCH_PRECOMPOSED_ICON = 1 << 2;
+
+    private int mNativeFaviconHelper;
+
+    /**
+     * Callback interface for getting the result from getFaviconImageForURL method.
+     */
+    public interface FaviconImageCallback {
+        /**
+         * This method will be called when the result favicon is ready.
+         * @param image   Favicon image.
+         * @param iconUrl Favicon image's icon url.
+         */
+        @CalledByNative("FaviconImageCallback")
+        public void onFaviconAvailable(Bitmap image, String iconUrl);
+    }
+
+    /**
+     * Allocate and initialize the C++ side of this class.
+     */
+    public FaviconHelper() {
+        mNativeFaviconHelper = nativeInit();
+    }
+
+    /**
+     * Clean up the C++ side of this class. After the call, this class instance shouldn't be used.
+     */
+    public void destroy() {
+        nativeDestroy(mNativeFaviconHelper);
+        mNativeFaviconHelper = 0;
+    }
+
+    @Override
+    protected void finalize() {
+        // It is not O.K. to call nativeDestroy() here because garbage collection can be
+        // performed in another thread, and CancelableTaskTrack should be destroyed in the
+        // same thread where it was created. So we just make sure that destroy() is called before
+        // garbage collection picks up by the following assertion.
+        assert mNativeFaviconHelper == 0;
+    }
+
+    /**
+     * Get Favicon bitmap for the requested arguments.
+     * @param profile               Profile used for the FaviconService construction.
+     * @param pageUrl               The target Page URL to get the favicon.
+     * @param iconTypes             One of the IconType class values.
+     * @param desiredSizeInDip      The size of the favicon in dip we want to get.
+     * @param faviconImageCallback  A method to be called back when the result is available.
+     *                              Note that this callback is not called if this method returns
+     *                              false.
+     * @return                      True if we GetFaviconImageForURL is successfully called.
+     */
+    public boolean getFaviconImageForURL(
+            Profile profile, String pageUrl, int iconTypes,
+            int desiredSizeInDip, FaviconImageCallback faviconImageCallback) {
+        assert mNativeFaviconHelper != 0;
+        return nativeGetFaviconImageForURL(mNativeFaviconHelper, profile, pageUrl, iconTypes,
+                desiredSizeInDip, faviconImageCallback);
+    }
+
+    private static native int nativeInit();
+    private static native void nativeDestroy(int nativeFaviconHelper);
+    private static native boolean nativeGetFaviconImageForURL(int nativeFaviconHelper,
+            Profile profile, String pageUrl, int iconTypes, int desiredSizeInDip,
+            FaviconImageCallback faviconImageCallback);
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/profiles/MostVisitedSites.java b/chrome/android/java/src/org/chromium/chrome/browser/profiles/MostVisitedSites.java
new file mode 100644
index 0000000..77c0f93
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/profiles/MostVisitedSites.java
@@ -0,0 +1,77 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.profiles;
+
+import android.graphics.Bitmap;
+
+import org.chromium.base.CalledByNative;
+
+/**
+ * Methods to bridge into native history to provide most recent urls, titles and thumbnails.
+ */
+public class MostVisitedSites {
+    private Profile mProfile;
+
+    /**
+     * Interface for callback object for fetching most visisted urls.
+     */
+    public interface MostVisitedURLsCallback {
+        /**
+         * Callback method for fetching most visited URLs.
+         * Parameters guaranteed to be non-null.
+         *
+         * @param titles Array of most visited url page titles.
+         * @param urls Array of most visited urls.
+         */
+        @CalledByNative("MostVisitedURLsCallback")
+        public void onMostVisitedURLsAvailable(String[] titles, String[] urls);
+    }
+
+    public interface ThumbnailCallback {
+        /**
+         * Callback method for fetching thumbnail of a most visited URL.
+         * Parameter may be null.
+         *
+         * @param Bitmap thumbnail Bitmap.
+         */
+        @CalledByNative("ThumbnailCallback")
+        public void onMostVisitedURLsThumbnailAvailable(Bitmap thumbnail);
+    }
+
+    /**
+     * MostVisitedSites constructor requires a valid user profile object.
+     *
+     * @param profile A valid user profile object.
+     */
+    public MostVisitedSites(Profile profile) {
+        mProfile = profile;
+    }
+
+    /**
+     * Asynchronous method that fetches most visited urls and their page titles.
+     *
+     * @param callback Instance of a callback object.
+     * @param numResults Maximum number of results to return.
+     */
+    public void getMostVisitedURLs(MostVisitedURLsCallback callback, int numResults) {
+        nativeGetMostVisitedURLs(mProfile, callback, numResults);
+    }
+
+    /**
+     * Fetches thumbnail bitmap for a url returned by getMostVisitedURLs.
+     *
+     * @param url String representation of url.
+     * @param callback Instance of a callback object.
+     * @return Bitmap Thumbnail image for specified url.
+     */
+    public void getURLThumbnail(String url, ThumbnailCallback callback) {
+        nativeGetURLThumbnail(mProfile, url, callback);
+    }
+
+    private static native void nativeGetMostVisitedURLs(
+            Profile profile, MostVisitedURLsCallback callback, int numResults);
+    private static native void nativeGetURLThumbnail(
+            Profile profile, String url, ThumbnailCallback callback);
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/search_engines/TemplateUrlService.java b/chrome/android/java/src/org/chromium/chrome/browser/search_engines/TemplateUrlService.java
index f2a513f..b8aa5a9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/search_engines/TemplateUrlService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/search_engines/TemplateUrlService.java
@@ -125,6 +125,9 @@
         nativeSetDefaultSearchProvider(mNativeTemplateUrlServiceAndroid, selectedIndex);
     }
 
+    public boolean isSearchProviderManaged() {
+        return nativeIsSearchProviderManaged(mNativeTemplateUrlServiceAndroid);
+    }
     /**
      * Registers a listener for the TEMPLATE_URL_SERVICE_LOADED notification.
      */
@@ -152,4 +155,5 @@
     private native void nativeSetDefaultSearchProvider(int nativeTemplateUrlServiceAndroid,
             int selectedIndex);
     private native int nativeGetDefaultSearchProvider(int nativeTemplateUrlServiceAndroid);
+    private native boolean nativeIsSearchProviderManaged(int nativeTemplateUrlServiceAndroid);
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillTest.java
index d324b9f..94d2b53 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillTest.java
@@ -7,9 +7,6 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import org.chromium.base.test.util.Feature;
-import org.chromium.chrome.browser.autofill.AutofillPopup;
-import org.chromium.chrome.browser.autofill.AutofillPopup.AutofillPopupDelegate;
-import org.chromium.chrome.browser.autofill.AutofillSuggestion;
 import org.chromium.chrome.testshell.ChromiumTestShellActivity;
 import org.chromium.chrome.testshell.ChromiumTestShellTestBase;
 import org.chromium.content.browser.test.util.TouchCommon;
@@ -18,6 +15,9 @@
 import org.chromium.content.browser.test.util.CriteriaHelper;
 import org.chromium.ui.ViewAndroidDelegate;
 import org.chromium.ui.WindowAndroid;
+import org.chromium.ui.autofill.AutofillPopup;
+import org.chromium.ui.autofill.AutofillPopup.AutofillPopupDelegate;
+import org.chromium.ui.autofill.AutofillSuggestion;
 
 import java.util.concurrent.atomic.AtomicBoolean;
 
diff --git a/chrome/android/testshell/java/AndroidManifest.xml b/chrome/android/testshell/java/AndroidManifest.xml
index a0cac7a..7b2ef86 100644
--- a/chrome/android/testshell/java/AndroidManifest.xml
+++ b/chrome/android/testshell/java/AndroidManifest.xml
@@ -60,6 +60,41 @@
                  android:permission="org.chromium.content_shell.permission.SANDBOX"
                  android:isolatedProcess="true"
                  android:exported="false" />
+        <service android:name="org.chromium.content.app.SandboxedProcessService6"
+                 android:process=":sandboxed_process6"
+                 android:permission="org.chromium.content_shell.permission.SANDBOX"
+                 android:isolatedProcess="true"
+                 android:exported="false" />
+        <service android:name="org.chromium.content.app.SandboxedProcessService7"
+                 android:process=":sandboxed_process7"
+                 android:permission="org.chromium.content_shell.permission.SANDBOX"
+                 android:isolatedProcess="true"
+                 android:exported="false" />
+        <service android:name="org.chromium.content.app.SandboxedProcessService8"
+                 android:process=":sandboxed_process8"
+                 android:permission="org.chromium.content_shell.permission.SANDBOX"
+                 android:isolatedProcess="true"
+                 android:exported="false" />
+        <service android:name="org.chromium.content.app.SandboxedProcessService9"
+                 android:process=":sandboxed_process9"
+                 android:permission="org.chromium.content_shell.permission.SANDBOX"
+                 android:isolatedProcess="true"
+                 android:exported="false" />
+        <service android:name="org.chromium.content.app.SandboxedProcessService10"
+                 android:process=":sandboxed_process10"
+                 android:permission="org.chromium.content_shell.permission.SANDBOX"
+                 android:isolatedProcess="true"
+                 android:exported="false" />
+        <service android:name="org.chromium.content.app.SandboxedProcessService11"
+                 android:process=":sandboxed_process11"
+                 android:permission="org.chromium.content_shell.permission.SANDBOX"
+                 android:isolatedProcess="true"
+                 android:exported="false" />
+        <service android:name="org.chromium.content.app.SandboxedProcessService12"
+                 android:process=":sandboxed_process12"
+                 android:permission="org.chromium.content_shell.permission.SANDBOX"
+                 android:isolatedProcess="true"
+                 android:exported="false" />
 
         <!-- Name of the class implementing the invalidation client, for sync notifications. -->
         <meta-data android:name="org.chromium.sync.notifier.IMPLEMENTING_CLASS_NAME"
diff --git a/chrome/android/testshell/java/src/org/chromium/chrome/testshell/ChromiumTestShellActivity.java b/chrome/android/testshell/java/src/org/chromium/chrome/testshell/ChromiumTestShellActivity.java
index 0675d1f..f67833e 100644
--- a/chrome/android/testshell/java/src/org/chromium/chrome/testshell/ChromiumTestShellActivity.java
+++ b/chrome/android/testshell/java/src/org/chromium/chrome/testshell/ChromiumTestShellActivity.java
@@ -12,6 +12,7 @@
 import android.view.KeyEvent;
 
 import org.chromium.base.ChromiumActivity;
+import org.chromium.base.MemoryPressureListener;
 import org.chromium.chrome.browser.DevToolsServer;
 import org.chromium.content.browser.ActivityContentVideoViewClient;
 import org.chromium.content.browser.AndroidBrowserProcess;
@@ -31,6 +32,19 @@
     private static final String TAG = ChromiumTestShellActivity.class.getCanonicalName();
     private static final String COMMAND_LINE_FILE =
             "/data/local/tmp/chromium-testshell-command-line";
+    /**
+     * Sending an intent with this action will simulate a memory pressure signal
+     * at a critical level.
+     */
+    private static final String ACTION_LOW_MEMORY =
+            "org.chromium.chrome_test_shell.action.ACTION_LOW_MEMORY";
+
+    /**
+     * Sending an intent with this action will simulate a memory pressure signal
+     * at a moderate level.
+     */
+    private static final String ACTION_TRIM_MEMORY_MODERATE =
+            "org.chromium.chrome_test_shell.action.ACTION_TRIM_MEMORY_MODERATE";
 
     private WindowAndroid mWindow;
     private TabManager mTabManager;
@@ -45,7 +59,7 @@
 
         DeviceUtils.addDeviceSpecificUserAgentSwitch(this);
         try {
-            AndroidBrowserProcess.init(this, AndroidBrowserProcess.MAX_RENDERERS_AUTOMATIC);
+            AndroidBrowserProcess.init(this, AndroidBrowserProcess.MAX_RENDERERS_LIMIT);
         } catch (ProcessInitException e) {
             Log.e(TAG, "Chromium browser process initialization failed", e);
             finish();
@@ -61,7 +75,7 @@
         mWindow.restoreInstanceState(savedInstanceState);
         mTabManager.setWindow(mWindow);
 
-        mDevToolsServer = new DevToolsServer(true, "chromium_testshell_devtools_remote");
+        mDevToolsServer = new DevToolsServer("chromium_testshell");
         mDevToolsServer.setRemoteDebuggingEnabled(true);
     }
 
@@ -94,6 +108,14 @@
 
     @Override
     protected void onNewIntent(Intent intent) {
+        if (ACTION_LOW_MEMORY.equals(intent.getAction())) {
+            MemoryPressureListener.simulateMemoryPressureSignal(TRIM_MEMORY_COMPLETE);
+            return;
+        } else if (ACTION_TRIM_MEMORY_MODERATE.equals(intent.getAction())) {
+            MemoryPressureListener.simulateMemoryPressureSignal(TRIM_MEMORY_MODERATE);
+            return;
+        }
+
         String url = getUrlFromIntent(intent);
         if (!TextUtils.isEmpty(url)) {
             TestShellTab tab = getActiveTab();
diff --git a/chrome/android/testshell/java/src/org/chromium/chrome/testshell/ChromiumTestShellApplication.java b/chrome/android/testshell/java/src/org/chromium/chrome/testshell/ChromiumTestShellApplication.java
index e0b8d50..afdb3e5 100644
--- a/chrome/android/testshell/java/src/org/chromium/chrome/testshell/ChromiumTestShellApplication.java
+++ b/chrome/android/testshell/java/src/org/chromium/chrome/testshell/ChromiumTestShellApplication.java
@@ -22,7 +22,6 @@
         "en-US.pak",
         "resources.pak",
         "chrome_100_percent.pak",
-        "devtools_resources.pak",
     };
 
     @Override
diff --git a/chrome/android/testshell/testshell_stubs.cc b/chrome/android/testshell/testshell_stubs.cc
index b969a72..b271b31 100644
--- a/chrome/android/testshell/testshell_stubs.cc
+++ b/chrome/android/testshell/testshell_stubs.cc
@@ -2,17 +2,58 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/logging.h"
+#include "base/strings/string16.h"
 #include "chrome/browser/android/tab_android.h"
 #include "chrome/browser/infobars/confirm_infobar_delegate.h"
+#include "chrome/browser/translate/translate_infobar_delegate.h"
+#include "chrome/browser/ui/auto_login_infobar_delegate.h"
+#include "chrome/browser/ui/auto_login_infobar_delegate_android.h"
 
 // This file contains temporary stubs to allow the libtestshell target to
 // compile. They will be removed once real implementations are
 // written/upstreamed, or once other code is refactored to eliminate the
 // need for them.
 
+class InfoBarService;
+
 // static
 TabAndroid* TabAndroid::FromWebContents(content::WebContents* web_contents) {
   return NULL;
 }
 
+// AutoLoginInfoBarDelegatAndroid empty implementation for test_shell
+// TODO(miguelg) remove once the AutoLoginInfoBar is upstreamed.
+AutoLoginInfoBarDelegateAndroid::AutoLoginInfoBarDelegateAndroid(
+    InfoBarService* owner,
+    const AutoLoginInfoBarDelegate::Params& params)
+    : AutoLoginInfoBarDelegate(owner, params) {}
+
+AutoLoginInfoBarDelegateAndroid::~AutoLoginInfoBarDelegateAndroid() {}
+
+bool AutoLoginInfoBarDelegateAndroid::Accept() {
+  return false;
+}
+
+bool AutoLoginInfoBarDelegateAndroid::Cancel() {
+  return false;
+}
+
+base::string16 AutoLoginInfoBarDelegateAndroid::GetMessageText() const {
+  return base::string16();
+}
+
+// static
+bool AutoLoginInfoBarDelegateAndroid::Register(JNIEnv* env) {
+  return false;
+}
+
+// static
+InfoBar* ConfirmInfoBarDelegate::CreateInfoBar(InfoBarService* owner) {
+  NOTREACHED() << "ConfirmInfoBar: InfoBarFactory should be used on Android";
+  return NULL;
+}
+
+// static
+InfoBar* TranslateInfoBarDelegate::CreateInfoBar(InfoBarService* owner) {
+  return NULL;
+}
diff --git a/chrome/app/DEPS b/chrome/app/DEPS
index 37cd670..f8154fa 100644
--- a/chrome/app/DEPS
+++ b/chrome/app/DEPS
@@ -7,7 +7,7 @@
   "+chrome/renderer/chrome_content_renderer_client.h",
   "+chrome/utility/chrome_content_utility_client.h",
   "+chromeos/chromeos_paths.h",
-  "+components/breakpad/common/breakpad_paths.h",
+  "+components/nacl/common",
   "+content/public/app",
   "+content/public/browser/browser_main_runner.h",
   "+content/public/browser/render_process_host.h",
diff --git a/chrome/app/android/OWNERS b/chrome/app/android/OWNERS
index c505c89..8935337 100644
--- a/chrome/app/android/OWNERS
+++ b/chrome/app/android/OWNERS
@@ -1,5 +1,4 @@
 dtrainor@chromium.org
 michaelbai@chromium.org
-nileshagrawal@chromium.org
 yfriedman@chromium.org
 
diff --git a/chrome/app/bookmarks_strings.grdp b/chrome/app/bookmarks_strings.grdp
index c679e17..030dc98 100644
--- a/chrome/app/bookmarks_strings.grdp
+++ b/chrome/app/bookmarks_strings.grdp
@@ -183,18 +183,18 @@
   <message name="IDS_BOOKMARK_BUBBLE_PAGE_BOOKMARK" desc="Title of the bubble when re-clicking on a bookmark">
     Bookmark
   </message>
-  <message name="IDS_BOOKMARK_BUBBLE_OPTIONS" desc="Title of the link the user can click to edit details of the bookmark">
-    Edit...
-  </message>
-  <message name="IDS_BOOKMARK_BUBBLE_REMOVE_BOOKMARK" desc="Link for removing the bookmark">
-    Remove
-  </message>
   <message name="IDS_BOOKMARK_BUBBLE_TITLE_TEXT" desc="Text preceding the title of the page that was bookmarked">
     Name:
   </message>
   <message name="IDS_BOOKMARK_BUBBLE_FOLDER_TEXT" desc="Text preceding the folder selector">
     Folder:
   </message>
+  <message name="IDS_BOOKMARK_BUBBLE_REMOVE_BOOKMARK" desc="Title of the button for removing the bookmark">
+    Remove
+  </message>
+  <message name="IDS_BOOKMARK_BUBBLE_OPTIONS" desc="Title of the button the user can click to edit details of the bookmark">
+    Edit...
+  </message>
   <if expr="not pp_ifdef('use_titlecase')">
     <message name="IDS_BOOKMARK_BUBBLE_CHOOSER_ANOTHER_FOLDER" desc="Text in the combobox allowing the user to choose another folder (by bringing up th editor).">
       Choose another folder...
diff --git a/chrome/app/breakpad_linux.cc b/chrome/app/breakpad_linux.cc
index 938d5a2..bd6018d 100644
--- a/chrome/app/breakpad_linux.cc
+++ b/chrome/app/breakpad_linux.cc
@@ -39,13 +39,13 @@
 #include "chrome/app/breakpad_linux_impl.h"
 #include "chrome/browser/crash_upload_list.h"
 #include "chrome/common/child_process_logging.h"
+#include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/chrome_version_info_posix.h"
 #include "chrome/common/crash_keys.h"
 #include "chrome/common/dump_without_crashing.h"
 #include "chrome/common/env_vars.h"
 #include "chrome/common/logging_chrome.h"
-#include "components/breakpad/common/breakpad_paths.h"
 #include "content/public/common/content_descriptors.h"
 
 #if defined(OS_ANDROID)
@@ -533,7 +533,7 @@
   PathService::Get(base::DIR_TEMP, &tmp_path);
 
   base::FilePath dumps_path(tmp_path);
-  if (PathService::Get(breakpad::DIR_CRASH_DUMPS, &dumps_path)) {
+  if (PathService::Get(chrome::DIR_CRASH_DUMPS, &dumps_path)) {
     base::FilePath logfile =
         dumps_path.AppendASCII(CrashUploadList::kReporterLogFilename);
     std::string logfile_str = logfile.value();
@@ -1465,7 +1465,7 @@
     base::FilePath alternate_minidump_location_path(
         alternate_minidump_location);
     PathService::Override(
-        breakpad::DIR_CRASH_DUMPS,
+        chrome::DIR_CRASH_DUMPS,
         base::FilePath(alternate_minidump_location));
   }
 
diff --git a/chrome/app/breakpad_mac.mm b/chrome/app/breakpad_mac.mm
index 1a39ad5..0793bfe 100644
--- a/chrome/app/breakpad_mac.mm
+++ b/chrome/app/breakpad_mac.mm
@@ -25,13 +25,14 @@
 #include "base/threading/thread_restrictions.h"
 #import "breakpad/src/client/mac/Framework/Breakpad.h"
 #include "chrome/common/child_process_logging.h"
+#include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/crash_keys.h"
 #include "chrome/common/dump_without_crashing.h"
 #include "chrome/common/env_vars.h"
 #include "chrome/common/logging_chrome.h"
 #include "chrome/installer/util/google_update_settings.h"
-#include "components/breakpad/common/breakpad_paths.h"
+#include "components/nacl/common/nacl_switches.h"
 #include "native_client/src/trusted/service_runtime/osx/crash_filter.h"
 #include "policy/policy_constants.h"
 
@@ -182,7 +183,7 @@
   if (is_browser) {
     // Since the configuration management infrastructure is possibly not
     // initialized when this code runs, read the policy preference directly.
-    base::mac::ScopedCFTypeRef<CFStringRef> key(
+    base::ScopedCFTypeRef<CFStringRef> key(
         base::SysUTF8ToCFStringRef(policy::key::kMetricsReportingEnabled));
     Boolean key_valid;
     Boolean metrics_reporting_enabled = CFPreferencesGetAppBooleanValue(key,
@@ -249,7 +250,7 @@
           " doesn't exist";
     } else {
       PathService::Override(
-          breakpad::DIR_CRASH_DUMPS,
+          chrome::DIR_CRASH_DUMPS,
           base::FilePath(alternate_minidump_location));
       if (is_browser) {
         // Print out confirmation message to the stdout, but only print
@@ -261,7 +262,7 @@
   }
 
   base::FilePath dir_crash_dumps;
-  PathService::Get(breakpad::DIR_CRASH_DUMPS, &dir_crash_dumps);
+  PathService::Get(chrome::DIR_CRASH_DUMPS, &dir_crash_dumps);
   [breakpad_config setObject:base::SysUTF8ToNSString(dir_crash_dumps.value())
                       forKey:@BREAKPAD_DUMP_DIRECTORY];
 
diff --git a/chrome/app/cf_resources.rc b/chrome/app/cf_resources.rc
index f6e9d85..a989d1a 100644
--- a/chrome/app/cf_resources.rc
+++ b/chrome/app/cf_resources.rc
@@ -50,3 +50,13 @@
     DEFPUSHBUTTON   "Enable",IDACTIVATE,280,2,50,12
     PUSHBUTTON      "Ignore",IDNEVER,340,2,50,12
 END
+
+IDD_CHROME_FRAME_TURNDOWN_PROMPT DIALOGEX 0, 0, 393, 14
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
+FONT 8, "MS Shell Dlg", 400, 0, 0x0
+BEGIN
+    LTEXT           "This site is using the Chrome Frame plug-in which will soon be unsupported. Please uninstall it and upgrade to a modern browser.",IDC_TD_PROMPT_MESSAGE,3,3,414,8
+    LTEXT           "Learn more.",IDC_TD_PROMPT_LINK,238,3,42,8
+    PUSHBUTTON      "Uninstall",IDUNINSTALL,285,2,50,12
+    DEFPUSHBUTTON   "Dismiss",IDDISMISS,340,2,50,12
+END
diff --git a/chrome/app/chrome_command_ids.h b/chrome/app/chrome_command_ids.h
index ec6725c..6f7e563 100644
--- a/chrome/app/chrome_command_ids.h
+++ b/chrome/app/chrome_command_ids.h
@@ -179,7 +179,6 @@
 #define IDC_DEV_TOOLS_INSPECT           40023
 #define IDC_UPGRADE_DIALOG              40024
 #define IDC_VIEW_INCOMPATIBILITIES      40025
-#define IDC_VIEW_BACKGROUND_PAGES       40026
 #define IDC_SHOW_KEYBOARD_OVERLAY       40027
 #define IDC_PROFILING_ENABLED           40028
 #define IDC_BOOKMARKS_MENU              40029
diff --git a/chrome/app/chrome_dll.rc b/chrome/app/chrome_dll.rc
index 65e5caf..d284cb8 100644
--- a/chrome/app/chrome_dll.rc
+++ b/chrome/app/chrome_dll.rc
@@ -226,17 +226,6 @@
     PUSHBUTTON      "None",IDC_MessagesNone,121,7,56,13
 END
 
-IDD_SCREEN_CAPTURE_NOTIFICATION DIALOGEX 0, 0, 145, 24
-STYLE DS_SETFONT | WS_POPUP
-EXSTYLE WS_EX_TOPMOST | WS_EX_TOOLWINDOW
-FONT 9, "Microsoft Sans Serif", 400, 0, 0x0
-BEGIN
-    DEFPUSHBUTTON   "kDisconnectButton",IDC_SCREEN_CAPTURE_STOP,68,5,70,14
-    LTEXT           "kSharingWith",IDC_SCREEN_CAPTURE_TEXT,18,7,43,8
-    CONTROL         "",IDC_STATIC,"Static",SS_ETCHEDVERT,6,6,1,12
-    CONTROL         "",IDC_STATIC,"Static",SS_ETCHEDVERT,8,6,1,12
-END
-
 
 /////////////////////////////////////////////////////////////////////////////
 //
diff --git a/chrome/app/chrome_dll_resource.h b/chrome/app/chrome_dll_resource.h
index 0354bbd..1a0975b 100644
--- a/chrome/app/chrome_dll_resource.h
+++ b/chrome/app/chrome_dll_resource.h
@@ -34,11 +34,3 @@
 // Values around 1600 are used by installer/setup/build/
 
 #define IDD_IPC_SETTINGS                3000
-
-#define IDD_SCREEN_CAPTURE_NOTIFICATION 3100
-#define IDC_SCREEN_CAPTURE_STOP         3101
-#define IDC_SCREEN_CAPTURE_TEXT         3102
-
-#ifndef IDC_STATIC
-#define IDC_STATIC                -1
-#endif
diff --git a/chrome/app/chrome_exe_main_gtk.cc b/chrome/app/chrome_exe_main_gtk.cc
index 1ad83fd..5c14959 100644
--- a/chrome/app/chrome_exe_main_gtk.cc
+++ b/chrome/app/chrome_exe_main_gtk.cc
@@ -19,7 +19,11 @@
 //    ASan for each malloc/free) to 5. These stack traces tend to accumulate
 //    very fast in applications using JIT (v8 in Chrome's case), see
 //    https://code.google.com/p/address-sanitizer/issues/detail?id=177
-const char *kAsanDefaultOptions = "malloc_context_size=5 strict_memcmp=0";
+//  - disable the in-process symbolization, which isn't 100% compatible with
+//    the existing sandboxes and doesn't make much sense for stripped official
+//    binaries.
+const char *kAsanDefaultOptions =
+    "malloc_context_size=5 strict_memcmp=0 symbolize=false";
 
 // Override the default ASan options for the Google Chrome executable.
 // __asan_default_options should not be instrumented, because it is called
diff --git a/chrome/app/chrome_exe_main_win.cc b/chrome/app/chrome_exe_main_win.cc
index abba672..bffca3b 100644
--- a/chrome/app/chrome_exe_main_win.cc
+++ b/chrome/app/chrome_exe_main_win.cc
@@ -83,8 +83,10 @@
   policy::path_parser::CheckUserDataDirPolicy(&user_data_dir);
 
   HWND chrome = chrome::FindRunningChromeWindow(user_data_dir);
-  return chrome &&
-      chrome::AttemptToNotifyRunningChrome(chrome) == chrome::NOTIFY_SUCCESS;
+  if (!chrome)
+    return false;
+  return chrome::AttemptToNotifyRunningChrome(chrome, true) ==
+      chrome::NOTIFY_SUCCESS;
 }
 
 }  // namespace
diff --git a/chrome/app/chrome_main_app_mode_mac.mm b/chrome/app/chrome_main_app_mode_mac.mm
index 0f0af85..ab97041 100644
--- a/chrome/app/chrome_main_app_mode_mac.mm
+++ b/chrome/app/chrome_main_app_mode_mac.mm
@@ -17,7 +17,7 @@
 #include "base/mac/mac_logging.h"
 #include "base/mac/mac_util.h"
 #include "base/mac/scoped_nsautorelease_pool.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/message_loop.h"
 #include "base/path_service.h"
 #include "base/strings/sys_string_conversions.h"
@@ -47,7 +47,10 @@
 }
 
 - (id)initWithController:(AppShimController*)controller;
-
+- (BOOL)applicationOpenUntitledFile:(NSApplication *)app;
+- (void)applicationWillBecomeActive:(NSNotification*)notification;
+- (void)applicationWillHide:(NSNotification*)notification;
+- (void)applicationWillUnhide:(NSNotification*)notification;
 - (void)terminateNow;
 
 @end
@@ -61,8 +64,13 @@
   // Connects to Chrome and sends a LaunchApp message.
   void Init();
 
-  // Sends a QuitApp message to Chrome.
-  void QuitApp();
+  void SendSetAppHidden(bool hidden);
+
+  void SendQuitApp();
+
+  // Called when the app is activated, either by the user clicking on it in the
+  // dock or by Cmd+Tabbing to it.
+  void ActivateApp(bool is_reopen);
 
  private:
   // IPC::Listener implemetation.
@@ -73,20 +81,19 @@
   // shim process should die.
   void OnLaunchAppDone(bool success);
 
-  // Called when the app is activated, either by the user clicking on it in the
-  // dock or by Cmd+Tabbing to it.
-  void OnDidActivateApplication();
 
   // Terminates the app shim process.
   void Close();
 
   IPC::ChannelProxy* channel_;
-  scoped_nsobject<AppShimDelegate> nsapp_delegate_;
+  base::scoped_nsobject<AppShimDelegate> nsapp_delegate_;
+  bool launch_app_done_;
 
   DISALLOW_COPY_AND_ASSIGN(AppShimController);
 };
 
-AppShimController::AppShimController() : channel_(NULL) {}
+AppShimController::AppShimController() : channel_(NULL),
+                                         launch_app_done_(false) {}
 
 void AppShimController::Init() {
   DCHECK(g_io_thread);
@@ -104,7 +111,7 @@
       user_data_dir.Append(app_mode::kAppShimSocketName);
   IPC::ChannelHandle handle(socket_path.value());
   channel_ = new IPC::ChannelProxy(handle, IPC::Channel::MODE_NAMED_CLIENT,
-      this, g_io_thread->message_loop_proxy());
+      this, g_io_thread->message_loop_proxy().get());
 
   channel_->Send(new AppShimHostMsg_LaunchApp(
       g_info->profile_dir, g_info->app_mode_id,
@@ -116,7 +123,7 @@
   [NSApp setDelegate:nsapp_delegate_];
 }
 
-void AppShimController::QuitApp() {
+void AppShimController::SendQuitApp() {
   channel_->Send(new AppShimHostMsg_QuitApp);
 }
 
@@ -140,24 +147,22 @@
     return;
   }
 
-  [[[NSWorkspace sharedWorkspace] notificationCenter]
-      addObserverForName:NSWorkspaceDidActivateApplicationNotification
-                  object:nil
-                   queue:nil
-              usingBlock:^(NSNotification* notification) {
-      NSRunningApplication* activated_app =
-          [[notification userInfo] objectForKey:NSWorkspaceApplicationKey];
-      if ([activated_app isEqual:[NSRunningApplication currentApplication]])
-        OnDidActivateApplication();
-  }];
+  launch_app_done_ = true;
 }
 
 void AppShimController::Close() {
   [nsapp_delegate_ terminateNow];
 }
 
-void AppShimController::OnDidActivateApplication() {
-  channel_->Send(new AppShimHostMsg_FocusApp);
+void AppShimController::ActivateApp(bool is_reopen) {
+  if (launch_app_done_) {
+    channel_->Send(new AppShimHostMsg_FocusApp(
+        is_reopen ? apps::APP_SHIM_FOCUS_REOPEN : apps::APP_SHIM_FOCUS_NORMAL));
+  }
+}
+
+void AppShimController::SendSetAppHidden(bool hidden) {
+  channel_->Send(new AppShimHostMsg_SetAppHidden(hidden));
 }
 
 @implementation AppShimDelegate
@@ -169,17 +174,34 @@
   return self;
 }
 
+- (BOOL)applicationOpenUntitledFile:(NSApplication *)app {
+  appShimController_->ActivateApp(true);
+  return YES;
+}
+
+- (void)applicationWillBecomeActive:(NSNotification*)notification {
+  appShimController_->ActivateApp(false);
+}
+
 - (NSApplicationTerminateReply)
     applicationShouldTerminate:(NSApplication*)sender {
   if (terminateNow_)
     return NSTerminateNow;
 
-  appShimController_->QuitApp();
+  appShimController_->SendQuitApp();
   // Wait for the channel to close before terminating.
   terminateRequested_ = YES;
   return NSTerminateLater;
 }
 
+- (void)applicationWillHide:(NSNotification*)notification {
+  appShimController_->SendSetAppHidden(true);
+}
+
+- (void)applicationWillUnhide:(NSNotification*)notification {
+  appShimController_->SendSetAppHidden(false);
+}
+
 - (void)terminateNow {
   if (terminateRequested_) {
     [NSApp replyToApplicationShouldTerminate:NSTerminateNow];
diff --git a/chrome/app/chrome_main_delegate.cc b/chrome/app/chrome_main_delegate.cc
index 06f8c17..6c05f37 100644
--- a/chrome/app/chrome_main_delegate.cc
+++ b/chrome/app/chrome_main_delegate.cc
@@ -30,6 +30,7 @@
 #include "chrome/plugin/chrome_content_plugin_client.h"
 #include "chrome/renderer/chrome_content_renderer_client.h"
 #include "chrome/utility/chrome_content_utility_client.h"
+#include "components/nacl/common/nacl_switches.h"
 #include "content/public/common/content_client.h"
 #include "content/public/common/content_paths.h"
 #include "ui/base/ui_base_switches.h"
@@ -62,8 +63,9 @@
 #include <signal.h>
 #endif
 
-#if defined(OS_POSIX) && !defined(OS_MACOSX)
+#if !defined(DISABLE_NACL) && defined(OS_LINUX)
 #include "chrome/app/nacl_fork_delegate_linux.h"
+#include "chrome/common/nacl_paths.h"
 #endif
 
 #if defined(OS_CHROMEOS)
@@ -474,6 +476,9 @@
 #if defined(OS_CHROMEOS)
   chromeos::RegisterPathProvider();
 #endif
+#if !defined(DISABLE_NACL) && defined(OS_LINUX)
+  nacl::RegisterPathProvider();
+#endif
 
 #if defined(OS_MACOSX)
   // On the Mac, the child executable lives at a predefined location within
@@ -528,12 +533,20 @@
     // Initialize ResourceBundle which handles files loaded from external
     // sources.  The language should have been passed in to us from the
     // browser process as a command line flag.
+#if defined(DISABLE_NACL)
+    DCHECK(command_line.HasSwitch(switches::kLang) ||
+           process_type == switches::kZygoteProcess ||
+           process_type == switches::kGpuProcess ||
+           process_type == switches::kPpapiBrokerProcess ||
+           process_type == switches::kPpapiPluginProcess);
+#else
     DCHECK(command_line.HasSwitch(switches::kLang) ||
            process_type == switches::kZygoteProcess ||
            process_type == switches::kGpuProcess ||
            process_type == switches::kNaClLoaderProcess ||
            process_type == switches::kPpapiBrokerProcess ||
            process_type == switches::kPpapiPluginProcess);
+#endif
 
     // TODO(markusheintz): The command line flag --lang is actually processed
     // by the CommandLinePrefStore, and made available through the PrefService
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index 9e33044..14195d5 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -335,11 +335,11 @@
   <message name="IDS_OOBE_SPOKEN_FEEDBACK_OPTION" desc="Spoken feedback option shown on OOBE screens accessibility menu.">
     Spoken feedback
   </message>
-  <message name="IDS_OOBE_LARGE_CURSOR_OPTION" desc="Large cursor option shown on OOBE screens accessibility menu.">
-    Large cursor
+  <message name="IDS_OOBE_LARGE_CURSOR_OPTION" desc="Large mouse cursor option shown on OOBE screens accessibility menu.">
+    Large mouse cursor
   </message>
   <message name="IDS_OOBE_HIGH_CONTRAST_MODE_OPTION" desc="High contrast mode option shown on OOBE screens accessibility menu.">
-    High contrast
+    High contrast mode
   </message>
   <message name="IDS_OOBE_SCREEN_MAGNIFIER_OPTION" desc="Screen magnifier option shown on OOBE screens accessibility menu.">
     Screen magnifier
@@ -462,166 +462,157 @@
   <message name="IDS_BROWSE_WITHOUT_SIGNING_IN_HTML" desc="Text shown on side of Google sign-in UI.">
     You may also skip signing in and <ph name="LINK_START">$1<ex>&gt;a&lt;</ex></ph>browse as Guest<ph name="LINK_END">$2<ex>&gt;/a&lt;</ex></ph>.
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_FEATURE_NAME" desc="Title close to icon shown on side of Google sign-in UI to create a locally managed user.">
-    Locally managed user
+  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_FEATURE_NAME" desc="Title close to icon shown on side of Google sign-in UI to create a supervised user.">
+    Supervised user
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_INTRO_TEXT_1" desc="Managed user dialog, intro page, first paragraph">
-    Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum.
-    As a manager of a managed user on this Chromebook, you can:
+    <message name="IDS_CREATE_LOCALLY_MANAGED_USER_HTML" desc="Text with actual link shown on side of Google sign-in UI to create a supervised user.">
+      <ph name="LINK_START">$1<ex>&gt;a&lt;</ex></ph>Create a supervised user<ph name="LINK_END">$2<ex>&gt;/a&lt;</ex></ph> for this device.
+    </message>
+  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_NO_MANAGER_TEXT" desc="Text shown when supervised user can be created, but no users that can be manager exist.">
+    At least one account must exist on this device before creating a supervised user.
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_INTRO_MANAGER_ITEM_1" desc="Managed user dialog, intro page, options available to manager">
-    Review the limited user’s visited websites
+  <message name="IDS_CREATE_LOCALLY_MANAGED_INTRO_TEXT_1" desc="Supervised user dialog, intro page, first paragraph">
+    A supervised user can explore the web with your guidance. As the manager of a supervised user in Chrome, you can:
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_INTRO_MANAGER_ITEM_2" desc="Managed user dialog, intro page, options available to manager">
-    Determine sites you wish to allow or restrict, and
+  <message name="IDS_CREATE_LOCALLY_MANAGED_INTRO_MANAGER_ITEM_1" desc="Supervised user dialog, intro page, options available to manager">
+    allow or prohibit certain websites,
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_INTRO_MANAGER_ITEM_3" desc="Managed user dialog, intro page, options available to manager">
-    Manage other settings
+  <message name="IDS_CREATE_LOCALLY_MANAGED_INTRO_MANAGER_ITEM_2" desc="Supervised user dialog, intro page, options available to manager">
+    review websites the supervised user has visited, and
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_INTRO_TEXT_2" desc="Managed user dialog, intro page, second paragraph">
-  A managed user is not a Google account, and applies only to this device.
+  <message name="IDS_CREATE_LOCALLY_MANAGED_INTRO_MANAGER_ITEM_3" desc="Supervised user dialog, intro page, options available to manager">
+    manage other settings
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_INTRO_TEXT_3" desc="Managed user dialog, intro page, third paragraph">
-  After you create a new locally managed users, you can manage the settings at any time from any device at <ph name="MANAGEMENT_URL">$1<ex>www.example.com</ex></ph>.
+  <message name="IDS_CREATE_LOCALLY_MANAGED_INTRO_TEXT_2" desc="Supervised user dialog, intro page, second paragraph">
+    Creating a supervised user does not create a Google Account, and their settings
+    and data will not follow them to other devices with Chrome Sync. Currently,
+    a supervised user applies only to this installation of Chrome, on this device.
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_PICK_MANAGER_TITLE" desc="Managed user dialog, manager selection page, title of the page">
-    Choose the manager for this user
+  <message name="IDS_CREATE_LOCALLY_MANAGED_INTRO_TEXT_3" desc="Supervised user dialog, intro page, third paragraph">
+    After you create a new supervised user, you can manage the settings at any time from any device at <ph name="MANAGEMENT_URL">$1<ex>www.example.com</ex></ph>.
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_PICK_MANAGER_EXPLANATION" desc="Managed user dialog, manager selection page, explanation of the page">
-    The manager will be able to configure restrictions and settings for this managed user at <ph name="MANAGEMENT_URL">$1<ex>www.example.com</ex></ph>.
+  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_PICK_MANAGER_TITLE" desc="Supervised user dialog, manager selection page, title of the page">
+    Choose the manager for this supervised user
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_MANAGER_PASSWORD_HINT" desc="Managed user dialog, manager selection page, text shown as a hint in the user password field.">
+  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_PICK_MANAGER_EXPLANATION" desc="Supervised user dialog, manager selection page, explanation of the page">
+    The manager will be able to configure restrictions and settings for this supervised user at <ph name="MANAGEMENT_URL">$1<ex>www.example.com</ex></ph>.
+  </message>
+  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_MANAGER_PASSWORD_HINT" desc="Supervised user dialog, manager selection page, text shown as a hint in the user password field.">
     Enter password
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_NO_MANAGER_TEXT" desc="Text shown when managed user can be created, but no users that can be manager exist.">
-    At least one account must exist on this device before creating a Locally managed user.
-  </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_HTML" desc="Text with actual name shown on side of Google sign-in UI to create a locally managed user.">
-    <ph name="LINK_START">$1<ex>&gt;a&lt;</ex></ph>Create managed user<ph name="LINK_END">$2<ex>&gt;/a&lt;</ex></ph> for this device.
-  </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_ACCOUNT_NAME_TITLE" desc="Managed user dialog, new user page, title for name of new user">
+  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_ACCOUNT_NAME_TITLE" desc="Supervised user dialog, new user page, title for name of new user">
     Create an name -
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_ACCOUNT_NAME_EXPLANATION" desc="Managed user dialog, new user page, explanation for name of new user">
-    This account will be managed by <ph name="MANAGER_EMAIL">$1<ex>john.doe@example.com</ex></ph>.
+  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_ACCOUNT_NAME_EXPLANATION" desc="Supervised user dialog, new user page, explanation for name of new user">
+    This supervised user will be managed by <ph name="MANAGER_EMAIL">$1<ex>john.doe@example.com</ex></ph>.
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_PASSWORD_TITLE" desc="Managed user dialog, new user page, title for password for new user.">
+  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_PASSWORD_TITLE" desc="Supervised user dialog, new user page, title for password for new user.">
     Create a password -
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_PASSWORD_EXPLANATION" desc="Managed user dialog, new user page, explanation for password for new user.">
-    The managed user will need to use this password to sign in, so choose a safe password and rememeber to discuss it with the managed user.
+  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_PASSWORD_EXPLANATION" desc="Supervised user dialog, new user page, explanation for password for new user.">
+    The supervised user will need to use this password to sign in, so choose a safe password and remember to discuss it with the supervised user.
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_PASSWORD_HINT" desc="Text shown as a hint in the password field in locally managed user creation dialog.">
+  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_PASSWORD_HINT" desc="Text shown as a hint in the password field in supervised user creation dialog.">
     Enter password
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_PASSWORD_CONFIRM_HINT" desc="Text shown as a hint in the password confirmation field in locally managed user creation dialog.">
+  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_PASSWORD_CONFIRM_HINT" desc="Text shown as a hint in the password confirmation field in supervised user creation dialog.">
     Confirm password
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_CONTINUE_BUTTON_TEXT" desc="Text shown on continue button in locally managed user creation dialog.">
+  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_CONTINUE_BUTTON_TEXT" desc="Text shown on continue button in supervised user creation dialog.">
     Continue
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_START_BUTTON_TEXT" desc="Text shown on start button in locally managed user creation dialog.">
-    Create locally managed user.
+  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_START_BUTTON_TEXT" desc="Text shown on start button in supervised user creation dialog.">
+    Create supervised user.
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_NEXT_BUTTON_TEXT" desc="Text shown on next button in locally managed user creation dialog.">
+  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_NEXT_BUTTON_TEXT" desc="Text shown on next button in supervised user creation dialog.">
     Next
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_PREVIOUS_BUTTON_TEXT" desc="Text shown on previous button in locally managed user creation dialog.">
+  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_PREVIOUS_BUTTON_TEXT" desc="Text shown on previous button in supervised user creation dialog.">
     Previous
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATED_1_TEXT_1" desc="Managed user dialog, getting started page 1, paragraph 1">
-    A mananged user named <ph name="USER_DISPLAY_NAME">$1<ex>John</ex></ph> has been created.
+  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATED_1_TEXT_1" desc="Supervised user dialog, getting started page 1, paragraph 1">
+    A supervised user named <ph name="USER_DISPLAY_NAME">$1<ex>John</ex></ph> has been created.
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATED_1_TEXT_2" desc="Managed user dialog, getting started page 1, paragraph 2">
-    This locally managed user can now sign in and browse all sites on web
+  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATED_1_TEXT_2" desc="Supervised user dialog, getting started page 1, paragraph 2">
+    To set which websites the supervised user can view, you can configure restrictions
+    and settings by visiting <ph name="MANAGEMENT_URL">$1<ex>www.example.com</ex></ph>.
+    If you do not change the default settings, <ph name="USER_DISPLAY_NAME">$2<ex>John</ex></ph>
+    can browse all sites on the web.
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATED_1_TEXT_3" desc="Managed user dialog, getting started page 1, paragraph 3">
-    To configure restrictions for this locally managed user, please check your email at <ph name="BEGIN_BOLD">&lt;strong&gt;</ph><ph name="MANAGER_EMAIL">$1<ex>john.doe@example.com</ex></ph><ph name="END_BOLD">&lt;/strong&gt;</ph> for further instructions.
+  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATED_1_TEXT_3" desc="Supervised user dialog, getting started page 1, paragraph 3">
+    Please check your email at <ph name="BEGIN_BOLD">&lt;strong&gt;</ph><ph name="MANAGER_EMAIL">$1<ex>john.doe@example.com</ex></ph><ph name="END_BOLD">&lt;/strong&gt;</ph> for further instructions.
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATED_2_TEXT_1" desc="Managed user dialog, getting started page 2, paragraph 1">
-    You will see the locally managed users on your Chromebook's sign-in screen.
-  </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATED_2_TEXT_2" desc="Managed user dialog, getting started page 2, paragraph 2">
-    Lorem ipsum lorem ipsum lorem ipsum lorem ipsum.
-  </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATED_3_TEXT_1" desc="Managed user dialog, getting started page 3, paragraph 1">
-    Manage your locally managed user's activity
-  </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATED_3_TEXT_2" desc="Managed user dialog, getting started page 3, paragraph 2">
-    As a manager of this locally managed user, you can review the locally managed user's visited web sites, determine sites you wish to allow or restrict, and configure other settings
-    by visiting <ph name="BEGIN_BOLD">&lt;strong&gt;</ph><ph name="MANAGEMENT_URL">$1<ex>www.example.com</ex></ph><ph name="END_BOLD">&lt;/strong&gt;</ph> and signing in as
-    <ph name="BEGIN_BOLD">&lt;strong&gt;</ph><ph name="MANAGER_EMAIL">$2<ex>john.doe@example.com</ex></ph><ph name="END_BOLD">&lt;/strong&gt;</ph>.
-  </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATED_3_TEXT_3" desc="Managed user dialog, getting started page 3, paragraph 3">
-    For help, please check your email at <ph name="BEGIN_BOLD">&lt;strong&gt;</ph><ph name="MANAGER_EMAIL">$1<ex>john.doe@example.com</ex></ph><ph name="END_BOLD">&lt;/strong&gt;</ph> for further instructions.
-  </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATION_GOT_IT_BUTTON_TITLE" desc="Text for button on a screen with successful locally managed user creation text">
+  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATION_GOT_IT_BUTTON_TITLE" desc="Text for button on a screen with successful supervised user creation text">
     Got it!
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_HANDLE_ERROR_BUTTON_TEXT" desc="Text for button on an error screen that closes locally managed user creation dialog">
+  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_HANDLE_ERROR_BUTTON_TEXT" desc="Text for button on an error screen that closes supervised user creation dialog">
     Okay
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_USERNAME_ALREADY_EXISTS" desc="Error text shown in locally managed user creation dialog when local account with suggested name already exists on a device.">
+  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_USERNAME_ALREADY_EXISTS" desc="Error text shown in supervised user creation dialog when local account with suggested name already exists on a device.">
     Whoops, this name is already in use!
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_PASSWORD_MISMATCH_ERROR" desc="Error text shown in locally managed user creation dialog when typed passwords does not match.">
+  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_PASSWORD_MISMATCH_ERROR" desc="Error text shown in supervised user creation dialog when typed passwords does not match.">
     Whoops, passwords do not match!
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_PASSWORD_TOO_SHORT" desc="Error text shown in locally managed user creation dialog when typed password is too short.">
+  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_PASSWORD_TOO_SHORT" desc="Error text shown in supervised user creation dialog when typed password is too short.">
     Password is too short.
   </message>
   <message name="IDS_CREATE_LOCALLY_MANAGED_USER_MANAGER_PASSWORD_ERROR" desc="Error text shown in locally managed user creation dialog when manager password is incorrect.">
-    Incorrect manager password.
+    Incorrect password.
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_MANAGER_INCONSISTENT_STATE_TITLE" desc="Managed user dialog, error page, manager account is in inconsistent state, title">
-    Something went wrong while signing in as manager.
+  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_MANAGER_INCONSISTENT_STATE_TITLE" desc="Supervised user dialog, error page, manager account is in inconsistent state, title">
+    Oops, something went wrong
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_MANAGER_INCONSISTENT_STATE" desc="Managed user dialog, error page, manager account is in inconsistent state, text">
-    Manager account is in inconsistent state. Please log in to manager account first and then try creating locally managed user again.
+  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_MANAGER_INCONSISTENT_STATE" desc="Supervised user dialog, error page, manager account is in inconsistent state, text">
+    To recover from this error, you will need to sign into your Google Account
+    from the sign-in screen. You can then sign out of your Google Account and
+    try creating a supervised user again.
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_MANAGER_INCONSISTENT_STATE_BUTTON" desc="Managed user dialog, error page, manager account is in inconsistent state, button title">
-    Take me back to sign-in screen
+  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_MANAGER_INCONSISTENT_STATE_BUTTON" desc="Supervised user dialog, error page, manager account is in inconsistent state, button title">
+    OK, Take me back to sign-in screen
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_TPM_ERROR_TITLE" desc="Managed user dialog, error page, tpm error during creation, title">
+  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_TPM_ERROR_TITLE" desc="Supervised user dialog, error page, tpm error during creation, title">
     Oops, TPM error.
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_TPM_ERROR" desc="Managed user dialog, error page, tpm error during creation, text">
-    Something is wrong with device. Reboot an try again.
+  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_TPM_ERROR" desc="Supervised user dialog, error page, tpm error during creation, text">
+    Something is wrong with device.  To recover from this error you will need to reboot device and try again.
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_TPM_ERROR_BUTTON" desc="Managed user dialog, error page, tpm error during creation, button title">
+  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_TPM_ERROR_BUTTON" desc="Supervised user dialog, error page, tpm error during creation, button title">
     OK
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR_TITLE" desc="Managed user dialog, error page, generic error during creation, title">
-    Oops, something went wrong with creating a locally managed user.
+  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR_TITLE" desc="Supervised user dialog, error page, generic error during creation, title">
+    Oops, something went wrong
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR" desc="Managed user dialog, error page, generic error during creation, text">
-    Due to an error, a locally managed user was not created. Please try again later.
+  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR" desc="Supervised user dialog, error page, generic error during creation, text">
+    Due to an error, a supervised user was not created. Please try again later.
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR_BUTTON" desc="Managed user dialog, error page, generic error during creation, button title">
+  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR_BUTTON" desc="Supervised user dialog, error page, generic error during creation, button title">
     OK
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATION_ERROR_CANCEL_BUTTON_TITLE" desc="Text for button on an error reporting screen for locally managed user creation, that is used to abort whole operation">
+  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATION_ERROR_CANCEL_BUTTON_TITLE" desc="Text for button on an error reporting screen for supervised user creation, that is used to abort whole operation">
     Cancel
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATION_ERROR_RETRY_BUTTON_TITLE" desc="Text for button on an error reporting screen for locally managed user creation, that is used to retry failed operation">
+  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATION_ERROR_RETRY_BUTTON_TITLE" desc="Text for button on an error reporting screen for supervised user creation, that is used to retry failed operation">
     Retry
   </message>
   <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATION_AUTH_PROGRESS_MESSAGE" desc="Text shown next to progress indicator upon manager authentication.">
     Authenticating...
   </message>
-  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATION_CREATION_PROGRESS_MESSAGE" desc="Text shown next to progress indicator upon managed user creation.">
+  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATION_CREATION_PROGRESS_MESSAGE" desc="Text shown next to progress indicator upon supervised user creation.">
     Creating profile...
   </message>
   <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATION_CREATION_TIMEOUT_MESSAGE" desc="Text shown at the place of progess indicator if creation takes too long and should be cancelled.">
     Profile takes too long to create. You may want to cancel process and retry later.
   </message>
   <message name="IDS_USER_IS_LOCALLY_MANAGED_BY_NOTICE" desc="Text for notifications showing that this user is locally managed">
-    This user is managed by <ph name="MANAGER_EMAIL">$1<ex>john.doe@example.com</ex></ph>. Device usage and history may be tracked.
+    This supervised user is managed by <ph name="USER_DISPLAY_NAME">$1<ex>John</ex></ph>. Usage and browsing history can be viewed by the manager.
   </message>
-  <message name="IDS_USER_IS_LOCALLY_MANAGED_REMOVE_WARNING" desc="Text shown as a warning when attempting to remove locally managed user.">
-    All files and local data will be permanently deleted once this managed user is removed. However, any synced history will still be viewable in the manager's settings for this user.
+  <message name="IDS_USER_IS_LOCALLY_MANAGED_REMOVE_WARNING" desc="Text shown as a warning when attempting to remove supervised user.">
+    All files and local data associated with the supervised user will be permanently
+    deleted once this supervised user is removed. Visited websites and settings
+    for this supervised user may still be visible by the manager at <ph name="MANAGEMENT_URL">$1<ex>www.example.com</ex></ph>.
   </message>
-  <message name="IDS_USER_IS_LOCALLY_MANAGED_REMOVE_WARNING_BUTTON" desc="Text shown on a button that confirms removal of locally managed user.">
+  <message name="IDS_USER_IS_LOCALLY_MANAGED_REMOVE_WARNING_BUTTON" desc="Text shown on a button that confirms removal of supervised user.">
     Remove this user
   </message>
   <message name="IDS_OFFLINE_LOGIN_HTML" desc="Text which suggests enter as an existing user when valid network isn't presented.">
@@ -912,14 +903,14 @@
   <message name="IDS_OPTIONS_SETTINGS_ACCESSIBILITY_EXPLANATION" desc="In the settings tab, this text explains the accessibiliy features.">
     Enable accessibility features to make your device easier to use.
   </message>
-  <message name="IDS_OPTIONS_SETTINGS_ACCESSIBILITY_LARGE_CURSOR_DESCRIPTION" desc="In the settings tab, the text next to the checkbox for the large cursor.">
-    Enable large cursor
+  <message name="IDS_OPTIONS_SETTINGS_ACCESSIBILITY_LARGE_CURSOR_DESCRIPTION" desc="In the settings tab, the text next to the checkbox for the large mouse cursor.">
+    Show large mouse cursor
   </message>
   <message name="IDS_OPTIONS_SETTINGS_ACCESSIBILITY_SPOKEN_FEEDBACK_DESCRIPTION" desc="In the settings tab, the text next to the checkbox for spoken feedback.">
     Enable spoken feedback
   </message>
   <message name="IDS_OPTIONS_SETTINGS_ACCESSIBILITY_HIGH_CONTRAST_DESCRIPTION" desc="In the settings tab, the text next to the checkbox for high contrast mode.">
-    Enable high contrast
+    Use high contrast mode
   </message>
   <message name="IDS_OPTIONS_SETTINGS_ACCESSIBILITY_SCREEN_MAGNIFIER_DESCRIPTION" desc="In the settings tab, the text next to the dropdown for screen magnifier.">
     Enable screen magnifier
@@ -1068,6 +1059,9 @@
   <message name="IDS_OPTIONS_ACCOUNTS_ALLOW_BWSI_DESCRIPTION" desc="In the Accounts settings tab, the text on the checkbox to allow browse without signing in.">
     Enable Guest browsing
   </message>
+  <message name="IDS_OPTIONS_ACCOUNTS_ENABLE_SUPERVISED_USERS" desc="In the Users settings dialog, the text on the checkbox to allow creation and sign-in of supervised users.">
+    Enable supervised users
+  </message>
   <message name="IDS_OPTIONS_ACCOUNTS_USE_WHITELIST_DESCRIPTION" desc="In the Accounts settings tab, the text on the checkbox to restrict allowed user to a whitelist.">
     Restrict sign-in to the following users:
   </message>
@@ -2833,45 +2827,6 @@
   <message name="IDS_KEYBOARD_OVERLAY_INSTRUCTIONS_HIDE" desc="The instruction for hiding the keyboard overlay.">
     Type Ctrl+Alt+/ or Escape to hide
   </message>
-  <message name="IDS_KEYBOARD_OVERLAY_F1" desc="The text in the keyboard overlay to explain the shortcut.">
-    F1
-  </message>
-  <message name="IDS_KEYBOARD_OVERLAY_F2" desc="The text in the keyboard overlay to explain the shortcut.">
-    F2
-  </message>
-  <message name="IDS_KEYBOARD_OVERLAY_F3" desc="The text in the keyboard overlay to explain the shortcut.">
-    F3
-  </message>
-  <message name="IDS_KEYBOARD_OVERLAY_F4" desc="The text in the keyboard overlay to explain the shortcut.">
-    F4
-  </message>
-  <message name="IDS_KEYBOARD_OVERLAY_F5" desc="The text in the keyboard overlay to explain the shortcut.">
-    F5
-  </message>
-  <message name="IDS_KEYBOARD_OVERLAY_F6" desc="The text in the keyboard overlay to explain the shortcut.">
-    F6
-  </message>
-  <message name="IDS_KEYBOARD_OVERLAY_F7" desc="The text in the keyboard overlay to explain the shortcut.">
-    F7
-  </message>
-  <message name="IDS_KEYBOARD_OVERLAY_F8" desc="The text in the keyboard overlay to explain the shortcut.">
-    F8
-  </message>
-  <message name="IDS_KEYBOARD_OVERLAY_F9" desc="The text in the keyboard overlay to explain the shortcut.">
-    F9
-  </message>
-  <message name="IDS_KEYBOARD_OVERLAY_F10" desc="The text in the keyboard overlay to explain the shortcut.">
-    F10
-  </message>
-  <message name="IDS_KEYBOARD_OVERLAY_F11" desc="The text in the keyboard overlay to explain the shortcut.">
-    F11
-  </message>
-  <message name="IDS_KEYBOARD_OVERLAY_F12" desc="The text in the keyboard overlay to explain the shortcut.">
-    F12
-  </message>
-  <message name="IDS_KEYBOARD_OVERLAY_INSERT" desc="The text in the keyboard overlay to explain the shortcut.">
-    Insert
-  </message>
   <!-- BEGIN GENERATED KEYBOARD OVERLAY STRINGS -->
   <message name="IDS_KEYBOARD_OVERLAY_ACTIVATE_LAST_LAUNCHER_ITEM" desc="The text in the keyboard overlay to explain the shortcut (Open the last launcher item).">
     Activate last launcher item
@@ -2969,7 +2924,7 @@
   <message name="IDS_KEYBOARD_OVERLAY_DECREASE_KEY_BRIGHTNESS" desc="The text in the keyboard overlay to explain the shortcut (decrease the keyboard brightness).">
     Decrease key brightness
   </message>
-  <message name="IDS_KEYBOARD_OVERLAY_DELETE" desc="The text in the keyboard overlay to explain the shortcut.">
+  <message name="IDS_KEYBOARD_OVERLAY_DELETE" desc="The text in the keyboard overlay to explain the shortcut (Delete).">
     Delete
   </message>
   <message name="IDS_KEYBOARD_OVERLAY_DELETE_WORD" desc="The text in the keyboard overlay to explain the shortcut.">
@@ -2990,9 +2945,45 @@
   <message name="IDS_KEYBOARD_OVERLAY_DOWNLOADS" desc="The text in the keyboard overlay to explain the shortcut.">
     Downloads
   </message>
-  <message name="IDS_KEYBOARD_OVERLAY_END" desc="The text in the keyboard overlay to explain the shortcut.">
+  <message name="IDS_KEYBOARD_OVERLAY_END" desc="The text in the keyboard overlay to explain the shortcut (End).">
     End
   </message>
+  <message name="IDS_KEYBOARD_OVERLAY_F1" desc="The text in the keyboard overlay to explain the shortcut (F1).">
+    F1
+  </message>
+  <message name="IDS_KEYBOARD_OVERLAY_F10" desc="The text in the keyboard overlay to explain the shortcut (F10).">
+    F10
+  </message>
+  <message name="IDS_KEYBOARD_OVERLAY_F11" desc="The text in the keyboard overlay to explain the shortcut (F11).">
+    F11
+  </message>
+  <message name="IDS_KEYBOARD_OVERLAY_F12" desc="The text in the keyboard overlay to explain the shortcut (F12).">
+    F12
+  </message>
+  <message name="IDS_KEYBOARD_OVERLAY_F2" desc="The text in the keyboard overlay to explain the shortcut (F2).">
+    F2
+  </message>
+  <message name="IDS_KEYBOARD_OVERLAY_F3" desc="The text in the keyboard overlay to explain the shortcut (F3).">
+    F3
+  </message>
+  <message name="IDS_KEYBOARD_OVERLAY_F4" desc="The text in the keyboard overlay to explain the shortcut (F4).">
+    F4
+  </message>
+  <message name="IDS_KEYBOARD_OVERLAY_F5" desc="The text in the keyboard overlay to explain the shortcut (F5).">
+    F5
+  </message>
+  <message name="IDS_KEYBOARD_OVERLAY_F6" desc="The text in the keyboard overlay to explain the shortcut (F6).">
+    F6
+  </message>
+  <message name="IDS_KEYBOARD_OVERLAY_F7" desc="The text in the keyboard overlay to explain the shortcut (F7).">
+    F7
+  </message>
+  <message name="IDS_KEYBOARD_OVERLAY_F8" desc="The text in the keyboard overlay to explain the shortcut (F8).">
+    F8
+  </message>
+  <message name="IDS_KEYBOARD_OVERLAY_F9" desc="The text in the keyboard overlay to explain the shortcut (F9).">
+    F9
+  </message>
   <message name="IDS_KEYBOARD_OVERLAY_FIND_PREVIOUS_TEXT" desc="The text in the keyboard overlay to explain the shortcut.">
     Find previous text
   </message>
@@ -3038,7 +3029,7 @@
   <message name="IDS_KEYBOARD_OVERLAY_HISTORY" desc="The text in the keyboard overlay to explain the shortcut.">
     History
   </message>
-  <message name="IDS_KEYBOARD_OVERLAY_HOME" desc="The text in the keyboard overlay to explain the shortcut.">
+  <message name="IDS_KEYBOARD_OVERLAY_HOME" desc="The text in the keyboard overlay to explain the shortcut (Home).">
     Home
   </message>
   <message name="IDS_KEYBOARD_OVERLAY_INCREASE_KEY_BRIGHTNESS" desc="The text in the keyboard overlay to explain the shortcut (Increase the keyboard brightness).">
@@ -3047,6 +3038,9 @@
   <message name="IDS_KEYBOARD_OVERLAY_INPUT_UNICODE_CHARACTERS" desc="The text in the keyboard overlay to explain the shortcut.">
     Input Unicode characters
   </message>
+  <message name="IDS_KEYBOARD_OVERLAY_INSERT" desc="The text in the keyboard overlay to explain the shortcut (Insert).">
+    Insert
+  </message>
   <message name="IDS_KEYBOARD_OVERLAY_JAVASCRIPT_CONSOLE" desc="The text in the keyboard overlay to explain the shortcut.">
     JavaScript console
   </message>
@@ -3095,13 +3089,13 @@
   <message name="IDS_KEYBOARD_OVERLAY_OPEN_ADDRESS_IN_NEW_TAB" desc="The text in the keyboard overlay to explain the shortcut.">
     Open address in new tab
   </message>
-  <message name="IDS_KEYBOARD_OVERLAY_OPEN_FILE_MANAGER" desc="The text in the keyboard overlay to explain the shortcut.">
+  <message name="IDS_KEYBOARD_OVERLAY_OPEN_FILE_MANAGER" desc="The text in the keyboard overlay to explain the shortcut (Open the file manager).">
     Open file manager
   </message>
-  <message name="IDS_KEYBOARD_OVERLAY_PAGE_DOWN" desc="The text in the keyboard overlay to explain the shortcut.">
+  <message name="IDS_KEYBOARD_OVERLAY_PAGE_DOWN" desc="The text in the keyboard overlay to explain the shortcut (Page down).">
     Page down
   </message>
-  <message name="IDS_KEYBOARD_OVERLAY_PAGE_UP" desc="The text in the keyboard overlay to explain the shortcut.">
+  <message name="IDS_KEYBOARD_OVERLAY_PAGE_UP" desc="The text in the keyboard overlay to explain the shortcut (Page up).">
     Page up
   </message>
   <message name="IDS_KEYBOARD_OVERLAY_PASTE" desc="The text in the keyboard overlay to explain the shortcut.">
diff --git a/chrome/app/chromium_strings.grd b/chrome/app/chromium_strings.grd
index be65b81..d409ab2 100644
--- a/chrome/app/chromium_strings.grd
+++ b/chrome/app/chromium_strings.grd
@@ -268,6 +268,15 @@
         <message name="IDS_CHROME_FRAME_READY_MODE_LEARN_MORE_URL" desc="Link to knowledge-base article about Chromium Frame Ready Mode">
           http://www.google.com/support/chrome/bin/answer.py?hl=[GRITLANGCODE]&amp;answer=161796
         </message>
+        <message name="IDS_CHROME_FRAME_TURNDOWN_LEARN_MORE_URL" desc="Link to knowledge-base article about Chromium Frame's turndown">
+          http://support.google.com/chrome/?p=ib_chromeframe
+        </message>
+        <message name="IDS_CHROME_FRAME_TURNDOWN_TEXT_IE_OLDER" desc="Text of Chromium Frame turndown prompt for IE 6, 7, and 8">
+          This site is using the Chromium Frame plug-in which will soon be unsupported. Please uninstall it and upgrade to a modern browser.
+	</message>
+        <message name="IDS_CHROME_FRAME_TURNDOWN_TEXT_IE_NEWER" desc="Text of Chromium Frame turndown prompt for IE 9 and 10">
+          This site is using the Chromium Frame plug-in that will soon be unsupported. Please uninstall it and download a compatible browser.
+	</message>
         <message name="IDS_SHORTCUT_NEW_WINDOW" desc="The text label of the New window shortcut context menu entry as of Windows 8">
           New window
         </message>
@@ -715,6 +724,11 @@
           Nearly up-to-date! Restart your device to finish updating.
         </message>
       </if>
+      <if expr="pp_ifdef('chromeos')">
+        <message name="IDS_UPGRADE_SUCCESSFUL_CHANNEL_SWITCH" desc="Status label: Channel was successfully switched on Chromium OS">
+          Channel changed. Restart your device to apply changes.
+        </message>
+      </if>
       <if expr="not pp_ifdef('chromeos')">
         <message name="IDS_UPGRADE_UP_TO_DATE" desc="Status label: Already up to date (Chromium)">
           Chromium is up to date.
@@ -735,6 +749,11 @@
           Updating your device...
         </message>
       </if>
+      <if expr="pp_ifdef('chromeos')">
+        <message name="IDS_UPGRADE_UPDATING_CHANNEL_SWITCH" desc="Status label: Updating Chromium OS to a specified channel">
+          Updating your device to <ph name="CHANNEL_NAME">$1<ex>stable</ex></ph> channel...
+        </message>
+      </if>
 
       <!-- iOS Upgrade available info bar-->
       <if expr="pp_ifdef('ios')">
@@ -869,7 +888,7 @@
       <!-- Enterprise sign-in dialog (new-style) -->
       <!-- TODO(dconnelly): remove "new-style" once the old dialog is gone. -->
       <message name="IDS_ENTERPRISE_SIGNIN_TITLE_NEW_STYLE" desc="The title of the dialog to confirm linking the browser profile with the signed-in enterprise account">
-        Save your Chromium data to this account?
+        Link your Chromium data to this account?
       </message>
       <message name="IDS_ENTERPRISE_SIGNIN_EXPLANATION_WITHOUT_PROFILE_CREATION_NEW_STYLE" desc="The warning message displayed to an enterprise user about to link their profile to their Google account. This message is followed by a 'Learn more' link.">
         You are signing in with a managed account and giving its administrator control over your Chromium profile. Your Chromium data, such as your apps, bookmarks, history, passwords, and other settings will become permanently tied to <ph name="USER_NAME">$1<ex>pat@example.com</ex></ph>. You will be able to delete this data via the Google Accounts Dashboard, but you will not be able to associate this data with another account. <ph name="LEARN_MORE">$2<ex>Learn more</ex></ph>
@@ -977,6 +996,16 @@
           <ph name="DOMAIN">$1<ex>example.com</ex></ph> requires that you read and accept the following Terms of Service before using this device. These terms do not expand, modify or limit the Chromium OS Terms.
         </message>
       </if>
+
+      <!-- Chrome Notifications center -->
+      <if expr="is_win">
+        <message name="IDS_MESSAGE_CENTER_BALLOON_TITLE" desc="Title of the first run notification ballon describing the notification center.">
+          Chromium Notification Center
+        </message>
+        <message name="IDS_MESSAGE_CENTER_BALLOON_TEXT" desc="Body text for the the first run notification ballon describing the notification center.">
+          You can see all your notifications from Chromium apps, extensions, and websites here.
+        </message>
+      </if>
     </messages>
   </release>
 </grit>
diff --git a/chrome/app/client_util.cc b/chrome/app/client_util.cc
index 38412e7..7a6f179 100644
--- a/chrome/app/client_util.cc
+++ b/chrome/app/client_util.cc
@@ -16,7 +16,6 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/version.h"
-#include "base/win/registry.h"
 #include "chrome/app/breakpad_win.h"
 #include "chrome/app/client_util.h"
 #include "chrome/common/chrome_constants.h"
@@ -36,32 +35,6 @@
 
 typedef void (*RelaunchChromeBrowserWithNewCommandLineIfNeededFunc)();
 
-// Gets chrome version according to the load path. |exe_path| must be the
-// backslash terminated directory of the current chrome.exe.
-// TODO(cpu): This is now only used to support metro_driver, remove it.
-bool GetChromeVersion(const wchar_t* exe_dir, const wchar_t* key_path,
-                      string16* version) {
-  HKEY reg_root = InstallUtil::IsPerUserInstall(exe_dir) ? HKEY_CURRENT_USER :
-                                                           HKEY_LOCAL_MACHINE;
-  bool success = false;
-
-  base::win::RegKey key(reg_root, key_path, KEY_QUERY_VALUE);
-  if (key.Valid()) {
-    string16 new_chrome_exe(exe_dir);
-    new_chrome_exe.append(installer::kChromeNewExe);
-    if (::PathFileExistsW(new_chrome_exe.c_str()) &&
-        key.ReadValue(google_update::kRegOldVersionField,
-                      version) == ERROR_SUCCESS) {
-      success = true;
-    } else {
-      success = (key.ReadValue(google_update::kRegVersionField,
-                               version) == ERROR_SUCCESS);
-    }
-  }
-
-  return success;
-}
-
 // Expects that |dir| has a trailing backslash. |dir| is modified so it
 // contains the full path that was tried. Caller must check for the return
 // value not being null to determine if this path contains a valid dll.
@@ -106,6 +79,17 @@
   return exe_path.append(1, L'\\');
 }
 
+string16 GetCurrentModuleVersion() {
+  scoped_ptr<FileVersionInfo> file_version_info(
+      FileVersionInfo::CreateFileVersionInfoForCurrentModule());
+  if (file_version_info.get()) {
+    string16 version_string(file_version_info->file_version());
+    if (Version(WideToASCII(version_string)).IsValid())
+      return version_string;
+  }
+  return string16();
+}
+
 //=============================================================================
 
 MainDllLoader::MainDllLoader() : dll_(NULL) {
@@ -117,13 +101,12 @@
 // Loading chrome is an interesting affair. First we try loading from the
 // current directory to support run-what-you-compile and other development
 // scenarios.
-// If that fails then we look at the --chrome-version command line flag followed
-// by the 'CHROME_VERSION' env variable to determine if we should stick with an
-// older dll version even if a new one is available to support upgrade-in-place
-// scenarios.
-// If that fails then finally we look at the registry which should point us
-// to the latest version. This is the expected path for the first chrome.exe
-// browser instance in an installed build.
+// If that fails then we look at the --chrome-version command line flag to
+// determine if we should stick with an older dll version even if a new one is
+// available to support upgrade-in-place scenarios.
+// If that fails then finally we look at the version resource in the current
+// module. This is the expected path for chrome.exe browser instances in an
+// installed build.
 HMODULE MainDllLoader::Load(string16* out_version, string16* out_file) {
   const CommandLine& cmd_line = *CommandLine::ForCurrentProcess();
   const string16 dir(GetExecutablePath());
@@ -132,13 +115,11 @@
   if (!dll) {
     // Loading from same directory (for developers) failed.
     string16 version_string;
-    Version version;
     if (cmd_line.HasSwitch(switches::kChromeVersion)) {
       // This is used to support Chrome Frame, see http://crbug.com/88589.
       version_string = cmd_line.GetSwitchValueNative(switches::kChromeVersion);
-      version = Version(WideToASCII(version_string));
 
-      if (!version.IsValid()) {
+      if (!Version(WideToASCII(version_string)).IsValid()) {
         // If a bogus command line flag was given, then abort.
         LOG(ERROR) << "Invalid command line version: " << version_string;
         return NULL;
@@ -147,16 +128,10 @@
 
     // If no version on the command line, then look at the version resource in
     // the current module and try loading that.
-    if (!version.IsValid()) {
-      scoped_ptr<FileVersionInfo> file_version_info(
-          FileVersionInfo::CreateFileVersionInfoForCurrentModule());
-      if (file_version_info.get()) {
-        version_string = file_version_info->file_version();
-        version = Version(WideToASCII(version_string));
-      }
-    }
+    if (version_string.empty())
+      version_string = GetCurrentModuleVersion();
 
-    if (!version.IsValid()) {
+    if (version_string.empty()) {
       LOG(ERROR) << "No valid Chrome version found";
       return NULL;
     }
@@ -166,11 +141,13 @@
     out_file->append(*out_version).append(1, L'\\');
     dll = LoadChromeWithDirectory(out_file);
     if (!dll) {
-      LOG(ERROR) << "Failed to load Chrome DLL from " << *out_file;
+      PLOG(ERROR) << "Failed to load Chrome DLL from " << *out_file;
       return NULL;
     }
   }
 
+  DCHECK(dll);
+
 #if defined(CHROME_SPLIT_DLL)
   // In split dlls mode, we need to manually initialize both DLLs because
   // the circular dependencies between them make the loader not call the
@@ -211,15 +188,6 @@
   return OnBeforeExit(rc, file);
 }
 
-string16 MainDllLoader::GetVersion() {
-  string16 reg_path(GetRegistryPath());
-  string16 version_string;
-  string16 dir(GetExecutablePath());
-  if (!GetChromeVersion(dir.c_str(), reg_path.c_str(), &version_string))
-    return string16();
-  return version_string;
-}
-
 void MainDllLoader::RelaunchChromeBrowserWithNewCommandLineIfNeeded() {
   RelaunchChromeBrowserWithNewCommandLineIfNeededFunc relaunch_function =
       reinterpret_cast<RelaunchChromeBrowserWithNewCommandLineIfNeededFunc>(
diff --git a/chrome/app/client_util.h b/chrome/app/client_util.h
index 2efe026..faefc0d 100644
--- a/chrome/app/client_util.h
+++ b/chrome/app/client_util.h
@@ -19,6 +19,10 @@
 // Gets the path of the current exe with a trailing backslash.
 string16 GetExecutablePath();
 
+// Returns the version in the current module's version resource or the empty
+// string if none found.
+string16 GetCurrentModuleVersion();
+
 // Implements the common aspects of loading chrome.dll for both chrome and
 // chromium scenarios, which are in charge of implementing two abstract
 // methods: GetRegistryPath() and OnBeforeLaunch().
@@ -34,9 +38,6 @@
   // upon termination.
   int Launch(HINSTANCE instance, sandbox::SandboxInterfaceInfo* sbox_info);
 
-  // Look into the registry to find the latest version.
-  string16 GetVersion();
-
   // Launches a new instance of the browser if the current instance in
   // persistent mode an upgrade is detected.
   void RelaunchChromeBrowserWithNewCommandLineIfNeeded();
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 8188e03..17fae23 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -1458,9 +1458,6 @@
         <message name="IDS_VIEW_INCOMPATIBILITIES" desc="The text label of the View incompatibilities menu item">
           Software incompatibility: Learn more
         </message>
-        <message name="IDS_VIEW_BACKGROUND_PAGES" desc="The text label of the View background pages menu item">
-          View background pages (<ph name="NUM_BACKGROUND_APPS">$1<ex>3</ex></ph>)
-        </message>
         <message name="IDS_EXIT" desc="The text label of the Exit menu item">
           E&amp;xit
         </message>
@@ -1499,9 +1496,6 @@
         <message name="IDS_VIEW_INCOMPATIBILITIES" desc="The text label of the View incompatibilities menu item">
           Software Incompatibility: Learn More
         </message>
-        <message name="IDS_VIEW_BACKGROUND_PAGES" desc="The text label of the View background pages menu item">
-          View Background Pages (<ph name="NUM_BACKGROUND_APPS">$1<ex>3</ex></ph>)
-        </message>
         <message name="IDS_EXIT" desc="In Title Case: The text label of the Exit menu item">
           E&amp;xit
         </message>
@@ -5125,11 +5119,11 @@
       <message name="IDS_EXTENSION_PROMPT_WARNING_USB" desc="Permission string for access to USB devices.">
         Access USB devices
       </message>
-      <message name="IDS_EXTENSION_PROMPT_WARNING_BLUETOOTH" desc="Permission string for access to the Bluetooth API.">
-        Access Bluetooth on your system
+      <message name="IDS_EXTENSION_PROMPT_WARNING_BLUETOOTH" desc="Permission string for general access to the Bluetooth API.">
+        Access information about Bluetooth devices paired with your system.
       </message>
-      <message name="IDS_EXTENSION_PROMPT_WARNING_BLUETOOTH_DEVICE" desc="Permission string for access to a specific Bluetooth device.">
-        Access the Bluetooth device "<ph name="DEVICE_NAME">$1<ex>Galaxy Nexus</ex></ph>".
+      <message name="IDS_EXTENSION_PROMPT_WARNING_BLUETOOTH_DEVICES" desc="Permission string for implementing Bluetooth profiles.">
+        Access Bluetooth devices paired with your system.
       </message>
       <message name="IDS_EXTENSION_PROMPT_WARNING_USB_DEVICE" desc="Permission string for access to a specific USB device.">
         Access the USB device <ph name="PRODUCT_NAME">$1<ex>SoundKnob</ex></ph> from <ph name="VENDOR_NAME">$2<ex>Griffin Technology</ex></ph>.
@@ -5611,8 +5605,8 @@
       <message name="IDS_EXTENSIONS_POLICY_CONTROLLED" desc="The text in the extensions UI informing the user that an extension is policy controlled">
         (This extension is managed and cannot be removed or disabled.)
       </message>
-      <message name="IDS_EXTENSIONS_LOCKED_MANAGED_MODE" desc="The error message (either shown in the extensions UI or logged) informing the user that extensions are controlled by managed mode">
-        Extensions cannot be modified by managed users.
+      <message name="IDS_EXTENSIONS_LOCKED_MANAGED_USER" desc="The error message (either shown in the extensions UI or logged) informing a supervised user that extensions cannot be changed.">
+        Extensions cannot be modified by supervised users.
       </message>
       <message name="IDS_GET_MORE_EXTENSIONS" desc="The text for getting more extensions. Displayed at bottom of extension management page when there is at least one extension installed.">
         Get more extensions
@@ -6289,18 +6283,18 @@
       <message name="IDS_FLAGS_SAVE_PAGE_AS_MHTML_DESCRIPTION" desc="Description of the 'Save Page as MHTML' lab.">
         Disables saving pages as HTML-only or HTML Complete; enables saving pages only as MHTML: a single text file containing HTML and all sub-resources.
       </message>
-      <message name="IDS_FLAGS_ENABLE_DEVICE_DISCOVERY_NAME" desc="Title of the enable 'device discovery' flag.">
-        Device Discovery
-      </message>
-      <message name="IDS_FLAGS_ENABLE_DEVICE_DISCOVERY_DESCRIPTION" desc="Description for 'device discovery' flag.">
-        Enables experimental device discovery on local network.
-      </message>
       <message name="IDS_FLAGS_TOUCH_OPTIMIZED_UI_NAME" desc="Title of the touch-optimized UI flag." >
         Touch Optimized UI
       </message>
       <message name="IDS_FLAGS_TOUCH_OPTIMIZED_UI_DESCRIPTION" desc="Description of the touch-optimized UI flag.">
         Enables experimental layout refinements to improve user experience with touch screens.
       </message>
+      <message name="IDS_FLAGS_ENABLE_SCROLL_PREDICTION_NAME" desc="Title of the flag which enables scroll prediction.">
+        Enable scroll prediction
+      </message>
+      <message name="IDS_FLAGS_ENABLE_SCROLL_PREDICTION_DESCRIPTION" desc="Description of the flag to enable scroll prediction.">
+        Predicts the finger's future position during scrolls allowing time to render the frame before the finger is there.
+      </message>
       <message name="IDS_TOUCH_EVENTS_NAME" desc="Title of the touch-events flag." >
         Enable touch events
       </message>
@@ -6446,6 +6440,12 @@
       <message name="IDS_FLAGS_EXTENSIONS_ON_CHROME_URLS_DESCRIPTION" desc="Description of the 'Extensions on chrome:// URLs' lab">
         Enables running extensions on chrome:// URLs, where extensions explicitly request this permission.
       </message>
+      <message name="IDS_FLAGS_ENABLE_FAST_UNLOAD_DESCRIPTION" desc="Description of the 'Fast Unload' lab.">
+        Enables fast tab/window closing - runs a tab's onunload js handler independently of the GUI.
+      </message>
+      <message name="IDS_FLAGS_ENABLE_FAST_UNLOAD_NAME" desc="Name of the 'Extensions on chrome:// URLs' lab">
+        Enable fast tab/window close
+      </message>
       <message name="IDS_FLAGS_ENABLE_ADVIEW_NAME" desc="Name of the 'Enable 'adview' element' lab.">
         Enable 'adview' element
       </message>
@@ -6458,6 +6458,12 @@
       <message name="IDS_FLAGS_ENABLE_ADVIEW_SRC_ATTRIBUTE_DESCRIPTION" desc="Description of the 'Enable specifying 'src' attribute on 'adview' elements' element' lab.">
         Enables specifying 'src' attribute on 'adview' elements, as well as arbitrary 'ad-network' names.
       </message>
+      <message name="IDS_FLAGS_ENABLE_APP_WINDOW_CONTROLS_NAME" desc="Name of the 'Enable 'window-controls' element' lab.">
+        Enable 'window-controls' element
+      </message>
+      <message name="IDS_FLAGS_ENABLE_APP_WINDOW_CONTROLS_DESCRIPTION" desc="Description of the 'Enable 'window-controls' element' lab.">
+        Enables using 'window-controls' HTML elements in packaged apps.
+      </message>
       <message name="IDS_FLAGS_ACTION_BOX_NAME" desc="Name of the 'Action Box' lab.">
         Action box
       </message>
@@ -6525,12 +6531,6 @@
       <message name="IDS_FLAGS_ENABLE_INSTANT_EXTENDED_API_DESCRIPTION" desc="Description for the flag to enable the Instant extended API.">
         Enables the Instant Extended API which provides a deeper integration with your default search provider, including a renovated New Tab Page, extracting search query terms in the omnibox, a spruced-up omnibox dropdown and Instant previews of search results as you type in the omnibox.
       </message>
-      <message name="IDS_FLAGS_ENABLE_LOCAL_ONLY_INSTANT_EXTENDED_API" desc="Title for the flag to enable the local-only Instant extended API.">
-        Enable local-only Instant Extended API
-      </message>
-      <message name="IDS_FLAGS_ENABLE_LOCAL_ONLY_INSTANT_EXTENDED_API_DESCRIPTION" desc="Description for the flag to enable the Instant extended API.">
-        Enables the Instant Extended API using only local resources, including a renovated New Tab Page and a spruced-up omnibox dropdown, but without search query terms extraction or Instant search results.
-      </message>
       <message name="IDS_FLAGS_ENABLE_LOCAL_FIRST_LOAD_NTP" desc="Title for the flag to enable the local first load NTP.">
         Enable local first-load NTP in Instant Extended.
       </message>
@@ -6552,6 +6552,9 @@
       <message name="IDS_FLAGS_ENABLE_AUTOLOGIN_NAME" desc="Title for the flag to auto-login the user">
         Enable auto-login
       </message>
+      <message desc="Message to display when auto-login fails. [CHAR-LIMIT=64]" name="IDS_AUTO_LOGIN_FAILED">
+        Automatic sign in failed
+      </message>
       <message name="IDS_FLAGS_ENABLE_AUTOLOGIN_DESCRIPTION" desc="Description for the flag to pre-login the user">
         When enabled, visiting a Google account login page will trigger an infobar allowing easy sign in with the Google account connected to the profile.
         Auto-login is always disabled if the profile is not connected to an account, regardless of this flag.
@@ -6749,6 +6752,12 @@
       <message name="IDS_FLAGS_ENABLE_QUIC_DESCRIPTION" desc="Description for the flag to enable QUIC.">
         Enable experimental QUIC protocol support.
       </message>
+      <message name="IDS_FLAGS_ENABLE_SPDY4A2_NAME" desc="Title for the flag to enable SPDY/4 alpha 2">
+        Enable SPDY/4 alpha 2
+      </message>
+      <message name="IDS_FLAGS_ENABLE_SPDY4A2_DESCRIPTION" desc="Description for the flag to enable SPDY/4 alpha 2.">
+        Enable experimental SPDY/4 alpha 2.
+      </message>
       <message name="IDS_FLAGS_ENABLE_ASYNC_DNS_NAME" desc="Title for the flag to enable asynchronous DNS client.">
         Built-in Asynchronous DNS
       </message>
@@ -6783,6 +6792,12 @@
       <message name="IDS_FLAGS_DISABLE_PREFIXED_ENCRYPTED_MEDIA_DESCRIPTION" desc="Description for the flag to disable the prefixed Encrypted Media Extensions APIs (e.g. webkitGenerateKeyRequest()).">
         Disable the experimental version of Encrypted Media Extensions on video and audio elements.
       </message>
+      <message name="IDS_FLAGS_ENCRYPTED_MEDIA_CANPLAYTYPE_OVERRIDE_NAME" desc="Title for the flag to override suppressed affirmative responses to canPlayType().">
+        Enable suppressed canPlayType() responses.
+      </message>
+      <message name="IDS_FLAGS_ENCRYPTED_MEDIA_CANPLAYTYPE_OVERRIDE_DESCRIPTION" desc="Description for the flag to override suppressed affirmative responses to canPlayType().">
+        Enable appropriate responses to canPlayType() for key systems that return the empty string by default.
+      </message>
       <message name="IDS_FLAGS_ENABLE_OPUS_PLAYBACK_NAME" desc="Title for the flag to enable Opus playback in &lt;video&gt; elements.">
         Enable Opus playback in &lt;video&gt; elements.
       </message>
@@ -6880,10 +6895,10 @@
       <message name="IDS_FLAGS_ASH_AUDIO_DEVICE_MENU_DESCRIPTION" desc="Description for a flag for audio switching.">
         Modifies the volume item in the status tray to add a menu allowing choosing a specific audio input and output device. Requires "Enable new audio handler" flag.
       </message>
-      <message name="IDS_FLAGS_ENABLE_LOCALLY_MANAGED_USERS_NAME" desc="Title for the flag to enable locally managed users.">
-        Enable locally managed users
+      <message name="IDS_FLAGS_ENABLE_LOCALLY_MANAGED_USERS_NAME" desc="Title for the flag to enable supervised users.">
+        Enable supervised users
       </message>
-      <message name="IDS_FLAGS_ENABLE_LOCALLY_MANAGED_USERS_DESCRIPTION" desc="Description for the flag to enable locally managed users.">
+      <message name="IDS_FLAGS_ENABLE_LOCALLY_MANAGED_USERS_DESCRIPTION" desc="Description for the flag to enable supervised users.">
         Enables support for user profiles that are managed by another user and can have restrictions applied.
       </message>
       <message name="IDS_FLAGS_ENABLE_NATIVE_FRAMES_FOR_APPS_NAME" desc="Title for the flag to enable native style frames for apps.">
@@ -6892,12 +6907,6 @@
       <message name="IDS_FLAGS_ENABLE_NATIVE_FRAMES_FOR_APPS_DESCRIPTION" desc="Description for the flag to enable native style frames for apps.">
         Use native-style window decorations for packaged app windows.
       </message>
-      <message name="IDS_FLAGS_ENABLE_WEBP_IN_ACCEPT_HEADER_NAME" desc="Title for the flag to enable 'image/webp' in accept header.">
-        Enable 'image/webp' accept header
-      </message>
-      <message name="IDS_FLAGS_ENABLE_WEBP_IN_ACCEPT_HEADER_DESCRIPTION" desc="Description for the flag to enable 'image/webp' in accept header.">
-        Enables 'image/webp' accept header in HTTP requests for images, to denote WebP image support.
-      </message>
       <message name="IDS_FLAGS_ENABLE_RESET_PROFILE_SETTINGS_NAME" desc="Title for the flag to enable a feature to reset profile settings that are often modified by malware.">
         Enable reset profile settings
       </message>
@@ -7154,6 +7163,12 @@
       <message name="IDS_FLAGS_ENABLE_PASSWORD_GENERATION_DESCRIPTION" desc="Description of flag to enable password generation.">
         Allow the user to have Chrome generate passwords when it detects account creation pages.
       </message>
+      <message name="IDS_FLAGS_ENABLE_PASSWORD_AUTOFILL_PUBLIC_SUFFIX_DOMAIN_MATCHING_NAME" desc="Name of the flag to enable public suffix domain matching for autofill of passwords.">
+        Enable public suffix domain matching for autofill of passwords.
+      </message>
+      <message name="IDS_FLAGS_ENABLE_PASSWORD_AUTOFILL_PUBLIC_SUFFIX_DOMAIN_MATCHING_DESCRIPTION" desc="Description of flag to enable public suffix domain matching for autofill of passwords.">
+        Allow the user to select username/password combinations for domains that match the same public suffix registry domain.
+      </message>
       <message name="IDS_FLAGS_PERFORMANCE_MONITOR_GATHERING_NAME" desc="Name for the flag to enable Performance Monitor.">
         Enable performance monitoring
       </message>
@@ -7294,13 +7309,6 @@
       <message name="IDS_FLAGS_ENABLE_SYNC_DIRECTORY_OPERATION_DESCRIPTION" desc="Description of the flag to enable syncfs directory support.">
         Enables directory support for sync filesystem.
       </message>
-      <message name="IDS_FLAGS_ENABLE_DRAGGABLE_MENU_BUTTON_NAME" desc="Title for the flag to enable draggable menu button.">
-        Enable draggable menu button.
-      </message>
-      <message name="IDS_FLAGS_ENABLE_DRAGGABLE_MENU_BUTTON_DESCRIPTION" desc="Description for the flag to enable draggable menu button.">
-        Make the menu button touch-draggable so that users can execute a menu item (e.g., New Tab, Settings,...) by a single touch.
-        If the popup list is too long to display at once, touch-dragging at the top or the bottom scrolls the list.
-      </message>
       <if expr="is_macosx">
         <message name="IDS_FLAGS_ENABLE_APP_LIST_SHIM_NAME" desc="Name of the flag to enable the app launcher app bundle.">
           Enable App Launcher OSX app bundle.
@@ -7327,6 +7335,12 @@
       <message name="IDS_FLAGS_ENABLE_TRANSLATE_SETTINGS_DESCRIPTION" desc="Description of the flag to translate setting.">
         Enable Translate settings in chrome://settings/languages where the user can configure which language should be translated.
       </message>
+      <message name="IDS_FLAGS_DISABLE_APP_LIST_NAME" desc="Name of the flag to disable the app list on startup.">
+        Disable the app launcher on startup.
+      </message>
+      <message name="IDS_FLAGS_DISABLE_APP_LIST_DESCRIPTION" desc="Description of the flag to disable the app list on startup.">
+        Disable the app launcher on startup. While this flag is set the launcher will be disabled every time Chrome starts. This is used for testing the app launcher install flow.
+      </message>
 
       <!-- Crashes -->
       <message name="IDS_CRASHES_TITLE" desc="Title for the chrome://crashes page.">
@@ -7357,6 +7371,32 @@
         If enabled, application size and layout will adapt to the operating system's DPI settings.
       </message>
 
+      <!-- WebRTC logs -->
+      <message name="IDS_WEBRTC_LOGS_TITLE" desc="Title for the chrome://webrtc-logs page.">
+        Uploaded WebRTC logs
+      </message>
+      <message name="IDS_WEBRTC_LOGS_LOG_COUNT_BANNER_FORMAT" desc="Format for WebRTC log count banner on chrome://webrtc-logs">
+        Uploaded WebRTC logs (<ph name="WEBRTC_LOG_COUNT">$1<ex>3</ex></ph>)
+      </message>
+      <message name="IDS_WEBRTC_LOGS_LOG_HEADER_FORMAT" desc="Format for uploaded log entry headings on chrome://webrtc-logs">
+        WebRTC log ID <ph name="WEBRTC_LOG_ID">$1<ex>8fa95dbb6f2ec862</ex></ph>
+      </message>
+      <message name="IDS_WEBRTC_LOGS_LOG_TIME_FORMAT" desc="Format for uploaded log entry upload time on chrome://webrtc-logs">
+        Uploaded <ph name="WEBRTC_LOG_TIME">$1<ex>Tuesday, January 25, 2011 2:58:02 PM</ex></ph>
+      </message>
+      <message name="IDS_WEBRTC_LOGS_BUG_LINK_LABEL" desc="Link text for filing a bug on chrome://webrtc-logs">
+        File bug
+      </message>
+      <message name="IDS_WEBRTC_LOGS_NO_LOGS_MESSAGE" desc="The explanatory message for chrome://webrtc-logs when there are no uploaded logs">
+        You have no recently uploaded WebRTC logs.
+      </message>
+      <message name="IDS_WEBRTC_LOGS_DISABLED_HEADER" desc="The header for chrome://webrtc-logs when uploading is disabled">
+        Log capturing and uploading is disabled.
+      </message>
+      <message name="IDS_WEBRTC_LOGS_DISABLED_MESSAGE" desc="The explanatory message for chrome://webrtc-logs when uploading is disabled">
+        This page only shows information on your recently uploaded WebRTC logs if you <ph name="BEGIN_LINK">&lt;a href="https://www.google.com/support/chrome/bin/answer.py?answer=96817"&gt;</ph>enable crash reporting<ph name="END_LINK">&lt;/a&gt;</ph>.
+      </message>
+
       <!-- Custom dictionary page -->
       <message name="IDS_LANGUAGE_DICTIONARY_OVERLAY_TITLE" desc="Title for the chrome://settings/editDictionary page, where a user can add and remove words in the dictionary used for spelling">
         Custom spelling dictionary
@@ -7384,9 +7424,6 @@
       <message name="IDS_INSTANT_CHECKBOX_NO_EXTENDED_API" desc="Description of a preference that's disabled because the Instant Extended API is disabled.">
         Display Instant results (Instant Extended is disabled).
       </message>
-      <message name="IDS_INSTANT_CHECKBOX_LOCAL_ONLY_EXTENDED_API" desc="Description of a preference that's disabled because the Instant Extended API is enabled in local-only mode.">
-        Display Instant results (Instant Extended is local-only).
-      </message>
       <message name="IDS_INSTANT_CHECKBOX_NO_DEFAULT_SEARCH_PROVIDER" desc="Description of a preference that's disabled because there's no default search engine.">
         Display Instant results (no default search engine).
       </message>
@@ -8108,9 +8145,6 @@
       <message name="IDS_IMPORT_FROM_ICEWEASEL" desc="browser combo box: Iceweasel">
         Iceweasel
       </message>
-      <message name="IDS_IMPORT_FROM_GOOGLE_TOOLBAR" desc="browser combo box: Google Toolbar">
-        Google Toolbar
-      </message>
       <message name="IDS_IMPORT_FROM_SAFARI" desc="browser combo box: Safari">
         Safari
       </message>
@@ -8354,28 +8388,28 @@
       </message>
 
       <!-- Managed User Avatar Menu -->
-      <message name="IDS_MANAGED_USER_INFO" desc="A text which explains that the user is managed by a custodian.">
-        This user is managed by <ph name="CUSTODIAN_NAME">$1<ex>custodian@gmail.com</ex></ph>. Usage and history from this user may be viewed by the manager.
+      <message name="IDS_MANAGED_USER_INFO" desc="Text which explains that a supervised user is managed by a custodian.">
+        This user is supervised by <ph name="CUSTODIAN_NAME">$1<ex>Jane Doe</ex></ph>. Usage and history from this user may be viewed by the manager.
       </message>
-      <message name="IDS_MANAGED_USER_AVATAR_LABEL" desc="A label for the managed user which is used in the avatar menu and as a label in the titlebar.">
-        Limited user
+      <message name="IDS_MANAGED_USER_AVATAR_LABEL" desc="A label for the supervised user which is used in the avatar menu and as a label in the titlebar.">
+        Supervised user
       </message>
 
-      <!-- Managed Mode Block Interstitial data -->
-      <message name="IDS_BLOCK_INTERSTITIAL_TITLE" desc="A title for the managed mode block interstitial page.">
+      <!-- Supervised User Block Interstitial data -->
+      <message name="IDS_BLOCK_INTERSTITIAL_TITLE" desc="A title for the supervised-user block interstitial page.">
         Page blocked
       </message>
-      <message name="IDS_BLOCK_INTERSTITIAL_MESSAGE" desc="A message for the user when they attempt to visit a site outside of any content pack.">
-        This page has been blocked.
+      <message name="IDS_BLOCK_INTERSTITIAL_MESSAGE" desc="A message for the supervised user when they attempt to visit a site that is not permitted by the manager.">
+        Oops, looks like you need permission from <ph name="NAME">$1<ex>John Doe</ex></ph> to access this page.
       </message>
       <message name="IDS_BACK_BUTTON" desc="A button for going back to the last safe url after being blocked.">
         Go back
       </message>
       <message name="IDS_BLOCK_INTERSTITIAL_REQUEST_ACCESS_BUTTON" desc="A button for requesting access to blocked sites.">
-        Request access
+        Request permission
       </message>
-      <message name="IDS_BLOCK_INTERSTITIAL_REQUEST_SENT_MESSAGE" desc="The text that tells the user that a request has been sent. This is followed by the manager's name">
-        A request to access this site has been sent to <ph name="NAME">$1<ex>John Doe</ex></ph>.
+      <message name="IDS_BLOCK_INTERSTITIAL_REQUEST_SENT_MESSAGE" desc="The text that tells the supervised user that a request has been sent.">
+        Your request to access this site has been sent to <ph name="NAME">$1<ex>John Doe</ex></ph>.
       </message>
 
       <!-- Content Settings dialog data -->
@@ -8736,6 +8770,9 @@
       <message name="IDS_UPGRADE_DISABLED_BY_POLICY" desc="Status label: Upgrades disabled by policy">
         Updates are disabled by the administrator
       </message>
+      <message name="IDS_UPGRADE_DISABLED_BY_POLICY_MANUAL" desc="Status label: Manual upgrades disabled by policy, automatic upgrades ok">
+        Manual updates are disabled by the administrator.  Automatic updates are enabled.
+      </message>
       <message name="IDS_REPORT_AN_ISSUE" desc="Text of the button which allows the user to report an issue with Chrome.">
         Report an issue
       </message>
@@ -8785,46 +8822,6 @@
       <message name="IDS_CLOUD_PRINT_CHROMEOS_OPTION_BUTTON" desc="Text on a button to go to the cloud print home page from the Chrome OS advanced options dialog.">
         Open <ph name="CLOUD_PRINT_NAME">$1<ex>Google Cloud Print</ex></ph>
       </message>
-      <message name="IDS_CLOUD_PRINT_SETUP_DIALOG_TITLE" desc="Title of the cloud print setup dialog.">
-        Set up <ph name="CLOUD_PRINT_NAME">$1<ex>Google Cloud Print</ex></ph>
-      </message>
-      <message name="IDS_CLOUD_PRINT_SETUP_HEADER" desc="Intro line of the cloud print setup dialog.">
-        Access and share your printers online with <ph name="CLOUD_PRINT_NAME">$1<ex>Google Cloud Print</ex></ph>
-      </message>
-      <message name="IDS_CLOUD_PRINT_SETUP_EXPLAIN" desc="Explanation of the cloud print setup dialog.">
-        <ph name="CLOUD_PRINT_NAME">$1<ex>Google Cloud Print</ex></ph> is built on the idea that printing can be more intuitive, accessible, and useful. Using <ph name="CLOUD_PRINT_NAME">&lt;span jscontent="googleCloudPrint"&gt;&lt;/span&gt;<ex>Google Cloud Print</ex></ph> you can make your printers available to you from any <ph name="CLOUD_PRINT_NAME">&lt;span jscontent="googleCloudPrint"&gt;&lt;/span&gt;<ex>Google Cloud Print</ex></ph> enabled web or mobile app.
-      </message>
-      <message name="IDS_CLOUD_PRINT_SETUP_ANYWHERE_HEADER" desc="Intro line about printing from anywhere.">
-        Print from anywhere
-      </message>
-      <message name="IDS_CLOUD_PRINT_SETUP_ANYWHERE_EXPLAIN" desc="Explanation about printing from anywhere.">
-        Access your printers from any computer or smart phone. <ph name="BEGIN_LINK">&lt;a href="#" onclick="cloudprint.learnMore()"&gt;</ph>Learn more<ph name="END_LINK">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph>
-      </message>
-      <message name="IDS_CLOUD_PRINT_SETUP_PRINTER_HEADER" desc="Intro line about printer management.">
-        Manage your printer
-      </message>
-      <message name="IDS_CLOUD_PRINT_SETUP_PRINTER_EXPLAIN" desc="Explanation about printer management.">
-        Review your print jobs and printer status online.
-      </message>
-      <message name="IDS_CLOUD_PRINT_SETUP_SHARING_HEADER" desc="Intro line about printer management.">
-        Shared access
-      </message>
-      <message name="IDS_CLOUD_PRINT_SETUP_SHARING_EXPLAIN" desc="Explanation about printer management.">
-        Share and control access to your printers with any Google account.
-      </message>
-      <if expr="is_android">
-        <message name="IDS_CLOUD_PRINT_SETUP_DONE" desc="Mobile: Message on completed set up of cloud print.">
-          <ph name="CLOUD_PRINT_NAME">$1<ex>Google Cloud Print</ex></ph> has registered the printers on this device with &lt;b&gt;<ph name="EMAIL_ADDRESSES">$2<ex>foo@example.com</ex></ph>&lt;/b&gt;.  You can now print to your printers from any <ph name="CLOUD_PRINT_NAME">$1<ex>Google Cloud Print</ex></ph> enabled web or mobile app!
-        </message>
-      </if>
-      <if expr="not is_android">
-        <message name="IDS_CLOUD_PRINT_SETUP_DONE" desc="Message on completed set up of cloud print.">
-          <ph name="CLOUD_PRINT_NAME">$1<ex>Google Cloud Print</ex></ph> has registered the printers on this machine with &lt;b&gt;<ph name="EMAIL_ADDRESSES">$2<ex>foo@example.com</ex></ph>&lt;/b&gt;.  You can now print to your printers from any <ph name="CLOUD_PRINT_NAME">$1<ex>Google Cloud Print</ex></ph> enabled web or mobile app!
-        </message>
-      </if>
-      <message name="IDS_CLOUD_PRINT_SETUP_TEST_PAGE" desc="Label on button for printing a test page.">
-        Print a Test Page
-      </message>
       <message name="IDS_CLOUD_PRINT_REGISTER_PRINTER_FAILED" desc="Status message to be sent to the server when we failed to retrieve information about a printer to register.">
         An error occurred while retrieving printer capabilities for printer <ph name="PRINTER_NAME">$1<ex>HP Laserjet 7900</ex></ph>. This printer could not be registered with <ph name="CLOUD_PRINT_NAME">$2<ex>Google Cloud Print</ex></ph>.
       </message>
@@ -8837,51 +8834,9 @@
       <message name="IDS_CLOUD_PRINT_ENUM_FAILED" desc="Status message to be sent to the Cloud Print server when enumerating printers failed.">
         There was a problem listing printers. Some of your printers may not have registered successfully with <ph name="CLOUD_PRINT_NAME">$1<ex>Google Cloud Print</ex></ph>.
       </message>
-      <message name="IDS_CLOUD_PRINT_GAIA_CAPTCHA_INSTRUCTIONS" desc="Explanatory message shown when the user must type letters shown in a captcha image to reauthenticate.">
-        Enter the letters above
-      </message>
-      <message name="IDS_CLOUD_PRINT_LOGIN_EMAIL_SAME_LINE" desc="The user Email address of the Google account. This label appears on the same line as the text field.">
-        Email:
-      </message>
-      <message name="IDS_CLOUD_PRINT_LOGIN_PASSWORD_SAME_LINE" desc="The user password of the Google account. This labe appears on the same line as the text field.">
-        Password:
-      </message>
-      <message name="IDS_CLOUD_PRINT_SIGNIN" desc="The label of the button to log to your Google account">
-        Sign in
-      </message>
-      <message name="IDS_CLOUD_PRINT_CANNOT_ACCESS_ACCOUNT" desc="The text of a hyperlink">
-        Can't access your account?
-      </message>
-      <message name="IDS_CLOUD_PRINT_CREATE_ACCOUNT" desc="The text of a hyperlink to create a Google account">
-        Create a Google Account
-      </message>
-      <message name="IDS_CLOUD_PRINT_CANNOT_BE_BLANK" desc="The input error message when the user hasn't entered a username or password">
-        Required field cannot be left blank
-      </message>
-      <message name="IDS_CLOUD_PRINT_LOGIN_COULD_NOT_CONNECT" desc="The connect error message">
-        Could not connect to the server
-      </message>
-      <message name="IDS_CLOUD_PRINT_ACCESS_CODE_HELP_LABEL" desc="A help link message for users who don't know what an application-specific password (aka access code) is">
-        What's this?
-      </message>
-      <message name="IDS_CLOUD_PRINT_INVALID_ACCESS_CODE_LABEL" desc="A message telling the user the application-specific password (aka access code) they entered is invalid.">
-        Invalid application-specific password.
-      </message>
       <message name="IDS_SERVICE_CRASH_RECOVERY_CONTENT" desc="Text content telling the user the service process has crashed.">
         The <ph name="CLOUD_PRINT_NAME">$1<ex>Google Cloud Print</ex></ph> connector process has crashed. Restart?
       </message>
-      <message name="IDS_CLOUD_PRINT_SETUP_OK_BUTTON_LABEL" desc="The button label on the 'OK' button displayed at the end sign in.">
-        OK
-      </message>
-      <message name="IDS_CLOUD_PRINT_LOGIN_SIGNIN_PREFIX" desc="The first part of the sentence that is displayed after the login info">
-        Sign in with your
-      </message>
-      <message name="IDS_CLOUD_PRINT_LOGIN_SIGNIN_SUFFIX" desc="The second part of the sentence. Google will be replaced by the Google logo. The translation of 'Account' will be display in bold">
-        Google Account
-      </message>
-      <message name="IDS_CLOUD_PRINT_ENTER_ACCESS_CODE_LABEL" desc="A message asking the user to enter an application-specific password (aka access code).">
-        Enter your application-specific password:
-      </message>
 
       <!-- Print Preview -->
       <message name="IDS_PRINT_PREVIEW_TITLE" desc="Fallback title for print preview page.">
@@ -10044,10 +9999,10 @@
         Screen capture - <ph name="APP_NAME">$1<ex>Sharing App</ex></ph>
       </message>
       <message name="IDS_MEDIA_SCREEN_CAPTURE_NOTIFICATION_TEXT" desc="label used in screen capture notification UI to show the screen sharing status">
-        <ph name="APP_NAME">$1<ex>Google Cast</ex></ph> is sharing your screen
+        <ph name="APP_NAME">$1<ex>Google Cast</ex></ph> is sharing your screen.
       </message>
       <message name="IDS_MEDIA_SCREEN_CAPTURE_NOTIFICATION_STOP" desc="Text shown on the button that stops screen capture.">
-        Stop
+        Stop sharing
       </message>
 
       <!-- SSL Blocking Page -->
@@ -10401,11 +10356,17 @@
         <message name="IDS_RELAUNCH_BUTTON" desc="Titlecase: The label for the relaunch button that relaunches the browser once update is complete">
           Restart
         </message>
+        <message name="IDS_RELAUNCH_AND_POWERWASH_BUTTON" desc="Titlecase: The label for the  button that relaunches and powerwashes the browser once update is complete">
+          Relaunch and Powerwash
+        </message>
       </if>
       <if expr="pp_ifdef('chromeos') and not pp_ifdef('use_titlecase')">
         <message name="IDS_RELAUNCH_BUTTON" desc="The label for the relaunch button that relaunches the browser once update is complete">
           Restart
         </message>
+        <message name="IDS_RELAUNCH_AND_POWERWASH_BUTTON" desc="Titlecase: The label for the  button that relaunches and powerwashes the browser once update is complete">
+          Relaunch and Powerwash
+        </message>
       </if>
       <if expr="pp_ifdef('chromeos')">
         <message name="IDS_ABOUT_PRODUCT_DESCRIPTION" desc="The text label describing Chrome OS">
@@ -10436,11 +10397,59 @@
         Beta
       </message>
       <message name="IDS_ABOUT_PAGE_CHANNEL_DEVELOPMENT" desc="The development option in the channel select.">
-        Dev - Unstable
+        Developer - unstable
       </message>
       <message name="IDS_ABOUT_PAGE_CHANNEL_CHANGED" desc="The message to confirm that channel has changed.">
         You have switched to the <ph name="CHANNEL_NAME">$1<ex>Stable</ex></ph> channel.
       </message>
+      <message name="IDS_ABOUT_PAGE_CURRENT_CHANNEL_STABLE" desc="The stable label in the message about current channel.">
+        stable
+      </message>
+      <message name="IDS_ABOUT_PAGE_CURRENT_CHANNEL_BETA" desc="The beta label in the message about current channel.">
+        beta
+      </message>
+      <message name="IDS_ABOUT_PAGE_CURRENT_CHANNEL_DEV" desc="The dev label in the message about current channel.">
+        dev
+      </message>
+      <message name="IDS_ABOUT_PAGE_CURRENT_CHANNEL" desc="The message about current channel.">
+        Currently on <ph name="CHANNEL_NAME">$1<ex>Stable</ex></ph> channel.
+      </message>
+      <message name="IDS_ABOUT_PAGE_CHANNEL_CHANGE_BUTTON" desc="The label for the button for channel change.">
+        Change channel...
+      </message>
+      <message name="IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_TITLE" desc="The title of the window for channel change.">
+        Change channel
+      </message>
+      <message name="IDS_ABOUT_PAGE_CHANNEL_CHANGE_DISALLOWED_MESSAGE" desc="The error message that is displayed when non-owner tries to switch channel.">
+        This setting is enforced by your administrator.
+      </message>
+      <message name="IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_POWERWASH_TITLE" desc="The title for the message that warns user about powerwash.">
+        Powerwash required on next reboot
+      </message>
+      <message name="IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_POWERWASH_MESSAGE" desc="Message that warns user about powerwash.">
+        This will remove all local users, files, data, and other settings after your next restart. All users will need to sign in again.
+      </message>
+      <message name="IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_DELAYED_CHANGE_TITLE" desc="The title for the message that notifies user that channel change will be applied later.">
+        Channel change will be applied later.
+      </message>
+      <message name="IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_DELAYED_CHANGE_MESSAGE" desc="Message that notifies user that channel change will be applied later.">
+        You are changing to a channel with an older version of <ph name="PRODUCT_NAME">$1<ex>Chrome OS</ex></ph>. The channel change will be applied when the channel version matches the version currently installed on your device.
+      </message>
+      <message name="IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_UNSTABLE_TITLE" desc="The title for the message that warns user about switching to developer (unstable) channel.">
+        Warning: you are switching to developer channel
+      </message>
+      <message name="IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_UNSTABLE_MESSAGE" desc="Message that warns user about switching to developer (unstable) channel.">
+        You are updating to an unstable version of <ph name="PRODUCT_NAME">$1<ex>Chrome OS</ex></ph> which contains features that are in progress. Crashes and unexpected bugs will occur. Please proceed with caution.
+      </message>
+      <message name="IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_POWERWASH_BUTTON" desc="The label for the button for channel switch and powerwash.">
+        Change channel and Powerwash
+      </message>
+      <message name="IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_CHANGE_BUTTON" desc="The label for the button for channel switch.">
+        Change channel
+      </message>
+      <message name="IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_CANCEL_BUTTON" desc="The label for the button for cancelling channel change.">
+        Cancel
+      </message>
 
       <!-- chrome://network -->
       <message name="IDS_ABOUT_AUTO_REFRESH" desc="The message to indicate that the page is auto refreshing.">
@@ -10810,6 +10819,56 @@
         Google Wallet has encounted an unknown error.
       </message>
 
+      <!-- Autofill dialog: step progress -->
+      <message name="IDS_AUTOFILL_STEP_SHIPPING_DETAILS_UNSTARTED" desc="Text describing the task of filling out shipping details in an Autocheckout flow.">
+        Shipping details
+      </message>
+      <message name="IDS_AUTOFILL_STEP_SHIPPING_DETAILS_STARTED" desc="Text describing that the task of filling out shipping details in an Autocheckout flow is in progress.">
+        Submitting shipping details
+      </message>
+      <message name="IDS_AUTOFILL_STEP_SHIPPING_DETAILS_COMPLETE" desc="Text describing that the task of filling out shipping details in an Autocheckout flow is complete.">
+        Shipping details submitted
+      </message>
+      <message name="IDS_AUTOFILL_STEP_SHIPPING_DETAILS_FAILED" desc="Text describing that the task of filling out shipping details in an Autocheckout flow has failed.">
+        Error filling shipping details
+      </message>
+      <message name="IDS_AUTOFILL_STEP_DELIVERY_DETAILS_UNSTARTED" desc="Text describing the task of filling out delivery details in an Autocheckout flow.">
+        Delivery details
+      </message>
+      <message name="IDS_AUTOFILL_STEP_DELIVERY_DETAILS_STARTED" desc="Text describing that the task of filling out delivery details in an Autocheckout flow is in progress.">
+        Submitting delivery details
+      </message>
+      <message name="IDS_AUTOFILL_STEP_DELIVERY_DETAILS_COMPLETE" desc="Text describing that the task of filling out delivery details in an Autocheckout flow is complete.">
+        Delivery details submitted
+      </message>
+      <message name="IDS_AUTOFILL_STEP_DELIVERY_DETAILS_FAILED" desc="Text describing that the task of filling out delivery details in an Autocheckout flow has failed.">
+        Error filling delivery details
+      </message>
+      <message name="IDS_AUTOFILL_STEP_BILLING_DETAILS_UNSTARTED" desc="Text describing the task of filling out billing details in an Autocheckout flow.">
+        Billing details
+      </message>
+      <message name="IDS_AUTOFILL_STEP_BILLING_DETAILS_STARTED" desc="Text describing that the task of filling out billing details in an Autocheckout flow is in progress.">
+        Submitting billing details
+      </message>
+      <message name="IDS_AUTOFILL_STEP_BILLING_DETAILS_COMPLETE" desc="Text describing that the task of filling out billing details in an Autocheckout flow is complete.">
+        Billing details submitted
+      </message>
+      <message name="IDS_AUTOFILL_STEP_BILLING_DETAILS_FAILED" desc="Text describing that the task of filling out billing details in an Autocheckout flow has failed.">
+        Error filling billing details
+      </message>
+      <message name="IDS_AUTOFILL_STEP_PROXY_CARD_UNSTARTED" desc="Text describing the task of generating a proxy card in an Autocheckout flow.">
+        Google Google Wallet Virtual OneTime Card
+      </message>
+      <message name="IDS_AUTOFILL_STEP_PROXY_CARD_STARTED" desc="Text describing that the task of generating a proxy card in an Autocheckout flow is in progress.">
+        Generating Google Wallet Virtual OneTime Card
+      </message>
+      <message name="IDS_AUTOFILL_STEP_PROXY_CARD_COMPLETE" desc="Text describing that the task of generating a proxy card in an Autocheckout flow is complete.">
+        Google Wallet Virtual OneTime Card generated
+      </message>
+      <message name="IDS_AUTOFILL_STEP_PROXY_CARD_FAILED" desc="Text describing that the task of generating a proxy card in an Autocheckout flow has failed.">
+        Error generating Google Wallet Virtual OneTime Card
+      </message>
+
       <!-- Autofill dialog: detail section -->
       <message name="IDS_AUTOFILL_DIALOG_EDIT" desc="Text of link in autofill dialog which allows user to edit address + payment info.">
         Edit
@@ -10836,7 +10895,7 @@
         Continue
       </message>
       <message name="IDS_AUTOFILL_DIALOG_SUBMIT_BUTTON" desc="Button text for confirmation of user details.">
-        Submit
+        Continue
       </message>
       <message name="IDS_AUTOFILL_DIALOG_VERIFY_BUTTON" desc="Button text for verifying user details.">
         Verify
@@ -10882,16 +10941,16 @@
 
       <!-- Autofill dialog: legal documents -->
       <message name="IDS_AUTOFILL_DIALOG_LEGAL_LINKS_NEW_2" desc="Label at the bottom of the autofill dialog that is shown when a user needs to accept updated legal documents (ex: Privacy Policy, Terms Of Service).">
-        By clicking Submit you agree to the <ph name="LEGAL_DOC_LINK_TEXT_1">$1<ex>Google Wallet Terms Of Service</ex></ph> and <ph name="LEGAL_DOC_LINK_TEXT_2">$2<ex>Privacy Policy</ex></ph>. To protect you from fraud, information about your computer (including its location) will be shared with Google Wallet.
+        By clicking Continue you agree to the <ph name="LEGAL_DOC_LINK_TEXT_1">$1<ex>Google Wallet Terms Of Service</ex></ph> and <ph name="LEGAL_DOC_LINK_TEXT_2">$2<ex>Privacy Policy</ex></ph>. To protect you from fraud, information about your computer (including its location) will be shared with Google Wallet.
       </message>
       <message name="IDS_AUTOFILL_DIALOG_LEGAL_LINKS_NEW_3" desc="Label at the bottom of the autofill dialog that is shown when a user needs to accept updated legal documents (ex: Privacy Policy, Terms Of Service).">
-        By clicking Submit you agree to the <ph name="LEGAL_DOC_LINK_TEXT_1">$1<ex>Google Wallet Terms Of Service</ex></ph>, <ph name="LEGAL_DOC_LINK_TEXT_2">$2<ex>Virtual Card Notice</ex></ph>, and <ph name="LEGAL_DOC_LINK_TEXT_3">$3<ex>Terms Of Use</ex></ph>. To protect you from fraud, information about your computer (including its location) will be shared with Google Wallet.
+        By clicking Continue you agree to the <ph name="LEGAL_DOC_LINK_TEXT_1">$1<ex>Google Wallet Terms Of Service</ex></ph>, <ph name="LEGAL_DOC_LINK_TEXT_2">$2<ex>Virtual Card Notice</ex></ph>, and <ph name="LEGAL_DOC_LINK_TEXT_3">$3<ex>Terms Of Use</ex></ph>. To protect you from fraud, information about your computer (including its location) will be shared with Google Wallet.
       </message>
       <message name="IDS_AUTOFILL_DIALOG_LEGAL_LINKS_UPDATED_2" desc="Label at the bottom of the autofill dialog that is shown when a user needs to accept updated legal documents (ex: Privacy Policy, Terms Of Service).">
-        The <ph name="LEGAL_DOC_LINK_TEXT_1">$1<ex>Google Wallet Terms Of Service</ex></ph> and <ph name="LEGAL_DOC_LINK_TEXT_2">$2<ex>Privacy Policy</ex></ph> have been updated. By clicking Submit you verify that you accept these changes. To protect you from fraud, information about your computer (including its location) will be shared with Google Wallet.
+        The <ph name="LEGAL_DOC_LINK_TEXT_1">$1<ex>Google Wallet Terms Of Service</ex></ph> and <ph name="LEGAL_DOC_LINK_TEXT_2">$2<ex>Privacy Policy</ex></ph> have been updated. By clicking Continue you verify that you accept these changes. To protect you from fraud, information about your computer (including its location) will be shared with Google Wallet.
       </message>
       <message name="IDS_AUTOFILL_DIALOG_LEGAL_LINKS_UPDATED_3" desc="Label at the bottom of the autofill dialog that is shown when a user needs to accept updated legal documents (ex: Privacy Policy, Terms Of Service).">
-        The <ph name="LEGAL_DOC_LINK_TEXT_1">$1<ex>Google Wallet Terms Of Service</ex></ph>, <ph name="LEGAL_DOC_LINK_TEXT_2">$2<ex>Privacy Policy</ex></ph>, and <ph name="LEGAL_DOC_LINK_TEXT_3">$3<ex>Terms Of Use</ex></ph> have been updated. By clicking Submit you verify that you accept these changes. To protect you from fraud, information about your computer (including its location) will be shared with Google Wallet.
+        The <ph name="LEGAL_DOC_LINK_TEXT_1">$1<ex>Google Wallet Terms Of Service</ex></ph>, <ph name="LEGAL_DOC_LINK_TEXT_2">$2<ex>Privacy Policy</ex></ph>, and <ph name="LEGAL_DOC_LINK_TEXT_3">$3<ex>Terms Of Use</ex></ph> have been updated. By clicking Continue you verify that you accept these changes. To protect you from fraud, information about your computer (including its location) will be shared with Google Wallet.
       </message>
 
       <!-- Autofill dialog: validation messages -->
@@ -10925,10 +10984,10 @@
 
       <!-- Autocheckout bubble -->
       <message name="IDS_AUTOCHECKOUT_BUBBLE_PROMPT_SIGNED_IN" desc="Text for prompting a Google user to start an Autocheckout flow.">
-        Do you want to use your Google account to fast forward and skip typing these forms?
+        Fast forward through this checkout form with your Google account?
       </message>
       <message name="IDS_AUTOCHECKOUT_BUBBLE_PROMPT_NOT_SIGNED_IN" desc="Text for prompting a non-Google user to start an Autocheckout flow.">
-        Do you want to automatically fast forward through this checkout?
+        Fast forward through this checkout form?
       </message>
       <message name="IDS_AUTOCHECKOUT_BUBBLE_ACCEPT" desc="Label for the button a user clicks to start an Autocheckout flow.">
         Yes
@@ -11228,13 +11287,14 @@
       <!-- Enterprise sign-in profile linking -->
       <!-- TODO(dconnelly): remove "new-style" once the old dialog is gone. -->
       <message name="IDS_ENTERPRISE_SIGNIN_CREATE_NEW_PROFILE_NEW_STYLE" desc="Text of the button to create a new profile after enterprise account signin">
-        Create new profile
+        No, create new profile
       </message>
       <message name="IDS_ENTERPRISE_SIGNIN_CONTINUE_NEW_STYLE" desc="Text of the button to link the current profile with the signed-in enterprise account">
-        Continue
+        Yes, link my data
       </message>
+
       <message name="IDS_ENTERPRISE_SIGNIN_ALERT_NEW_STYLE" desc="The text of the prompt to create a new profile after signing into an enterprise account">
-        <ph name="USER_NAME">$1<ex>pat@example.com</ex></ph> is managed by <ph name="DOMAIN">$2<ex>example.com</ex></ph>
+        This account is managed by <ph name="DOMAIN">$1<ex>example.com</ex></ph>
       </message>
 
       <!-- Cookies Window -->
@@ -11779,9 +11839,16 @@
           Add New User
         </message>
       </if>
-      <message name="IDS_PROFILES_SWITCH_PROFILE_LINK" desc="Link in the managed user bubble view to switch to a different profile.">
-        Switch Users
-      </message>
+      <if expr="not pp_ifdef('use_titlecase')">
+        <message name="IDS_PROFILES_SWITCH_PROFILE_LINK" desc="Link in the supervised user bubble view to switch to a different profile.">
+          Switch users
+        </message>
+      </if>
+      <if expr="pp_ifdef('use_titlecase')">
+        <message name="IDS_PROFILES_SWITCH_PROFILE_LINK" desc="In title case. Link in the supervised user bubble view to switch to a different profile.">
+          Switch Users
+        </message>
+      </if>
       <message name="IDS_PROFILES_CREATE_NEW_PROFILE_LINK" desc="Link in the avatar menu bubble view to create a new profile.">
         New user
       </message>
@@ -12417,11 +12484,17 @@
       </message>
 
       <!-- File Manager -->
-      <message name="IDS_FLAGS_FILE_MANAGER_NO_CHECKBOXES_NAME" desc="Name of the about:flag option to hide the selecting checkboxes to in the Files app.">
-        No selecting checkboxes
+      <message name="IDS_FLAGS_FILE_MANAGER_SHOW_CHECKBOXES_NAME" desc="Name of the about:flag option to show the selecting checkboxes to the Files app.">
+        Show selecting checkboxes
       </message>
-      <message name="IDS_FLAGS_FILE_MANAGER_NO_CHECKBOXES_DESCRIPTION" desc="Description of the about:flag option to hide the selecting checkboxes to in the Files app.">
-        Hide selecting checkboxes in the Files.app.
+      <message name="IDS_FLAGS_FILE_MANAGER_SHOW_CHECKBOXES_DESCRIPTION" desc="Description of the about:flag option to show the selecting checkboxes to the Files app.">
+        Show selecting checkboxes in the Files.app.
+      </message>
+      <message name="IDS_FLAGS_FILE_MANAGER_ENABLE_SHARING_NAME" desc="Name of the about:flag option to hide the selecting checkboxes to in the Files app.">
+        Sharing in Files.app.
+      </message>
+      <message name="IDS_FLAGS_FILE_MANAGER_ENABLE_SHARING_DESCRIPTION" desc="Description of the about:flag option to show the sharing option in Files app.">
+        Enables the sharing dialog in Files app under the context menu.
       </message>
       <message name="IDS_FILE_BROWSER_ROOT_DIRECTORY_LABEL" desc="Root directory label.">
         Files
@@ -12638,6 +12711,9 @@
       <message name="IDS_FILE_BROWSER_GALLERY_EDIT" desc="In the Gallery, the title on the button shows/hides editing buttons.">
         Edit
       </message>
+      <message name="IDS_FILE_BROWSER_GALLERY_PRINT" desc="In the Gallery, the title on the button showing the print dialog for the current image or video.">
+        Print
+      </message>
       <message name="IDS_FILE_BROWSER_GALLERY_SHARE" desc="In the Gallery, the title on the button that lets the user share a photo.">
         Share
       </message>
@@ -12704,6 +12780,9 @@
       <message name="IDS_FILE_BROWSER_GALLERY_VIDEO_DECODING_ERROR" desc="In the Gallery, message informing that an error occured while playing the movie.">
         An error occurred. Click to restart from the beginning.
       </message>
+      <message name="IDS_FILE_BROWSER_GALLERY_VIDEO_LOOPED_MODE" desc="In the Gallery, message informing that the movie will be played in a loop.">
+        This video will keep playing until the cows come home.
+      </message>
       <message name="IDS_FILE_BROWSER_AUDIO_ERROR" desc="In the Audio Player, message informing that the file could not be played.">
         This file could not be played.
       </message>
@@ -12841,21 +12920,21 @@
       <message name="IDS_FILE_BROWSER_PASTE_BUTTON_LABEL" desc="Button Label.">
         Paste
       </message>
-
       <message name="IDS_FILE_BROWSER_COPY_BUTTON_LABEL" desc="Button Label.">
         Copy
       </message>
       <message name="IDS_FILE_BROWSER_CUT_BUTTON_LABEL" desc="Button Label.">
         Cut
       </message>
-
-      <message name="IDS_FILE_BROWSER_OPEN_WITH_BUTTON_LABEL" desc="Menu item label, showing dialog to choose application to open selected files">
+      <message name="IDS_FILE_BROWSER_OPEN_WITH_BUTTON_LABEL" desc="Menu item label, showing dialog to choose application to open selected files.">
         Open with...
       </message>
-
-      <message name="IDS_FILE_BROWSER_ZIP_SELECTION_BUTTON_LABEL" desc="Menu item label, showing dialog to create zip file for selected files">
+      <message name="IDS_FILE_BROWSER_ZIP_SELECTION_BUTTON_LABEL" desc="Menu item label, showing dialog to create zip file for selected files.">
         Zip selection
       </message>
+      <message name="IDS_FILE_BROWSER_SHARE_BUTTON_LABEL" desc="Menu item label, showing dialog to share the selected file.">
+        Share
+      </message>
 
       <message name="IDS_FILE_BROWSER_TRANSFER_ITEMS_REMAINING" desc="File Manager status message. 'Item' is used here as a generic term for file or directory. 'Transferring' is used in the sense 'copying or moving files'.">
         Transferring $1 items.
@@ -13115,6 +13194,10 @@
         This file type is not supported. Please visit the <ph name="BEGIN_LINK">&lt;a target='_blank' href='$1'&gt;<ex>&lt;a target='_blank' href='$1'&gt;</ex></ph>Chrome Web Store<ph name="END_LINK">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph> to find an app that can open this type of file.
         <ph name="BEGIN_LINK_HELP">&lt;a target='_blank' href='$2'&gt;<ex>&lt;a target='_blank' href='$2'&gt;</ex></ph>Learn More<ph name="END_LINK_HELP">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph>
       </message>
+      <message name="IDS_FILE_BROWSER_NO_ACTION_FOR_EXECUTABLE" desc="Message shown when user tries to open a windows executable file, which we can't handle.">
+        This file type is not supported. Please visit the <ph name="BEGIN_LINK">&lt;a target='_blank' href='$1'&gt;<ex>&lt;a target='_blank' href='$1'&gt;</ex></ph>Chrome Web Store<ph name="END_LINK">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph> to find a similar app.
+        <ph name="BEGIN_LINK_HELP">&lt;a target='_blank' href='$2'&gt;<ex>&lt;a target='_blank' href='$2'&gt;</ex></ph>Learn More<ph name="END_LINK_HELP">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph>
+      </message>
       <message name="IDS_FILE_BROWSER_ID3_ALBUM" desc="Album">
         Album
       </message>
@@ -13428,9 +13511,7 @@
         Signed in as <ph name="USER_EMAIL_ADDRESS">$1<ex>foo@gmail.com</ex></ph>. Sync is disabled by your administrator.
       </message>
       <message name="IDS_SIGNED_IN_WITH_SYNC_SUPPRESSED" desc="The message that appears in the options dialog indicating that user is signed in with the given email address, but sync has been stopped.">
-        Signed in as <ph name="USER_EMAIL_ADDRESS">$1<ex>foo@gmail.com</ex></ph>.
-        <ph name="LINE_BREAK">&lt;br /&gt;<ex>&lt;br /&gt;</ex></ph>
-        Sync has been stopped on this device. Manage your synced data on <ph name="BEGIN_LINK">&lt;a href="$2" target=&quot;_blank&quot;&gt;<ex>&lt;a href="$2" target=&quot;_blank&quot;&gt;</ex></ph>Google Dashboard<ph name="END_LINK">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph>.
+        Signed in as <ph name="USER_EMAIL_ADDRESS">$1<ex>foo@gmail.com</ex></ph>. Sync has been stopped via the Google Dashboard.
       </message>
       <message name="IDS_SYNC_ACCOUNT_SYNCING_TO_USER" desc="The message that appears in the options dialog indicating that account is syncing to a user with the given email address.">
         Signed in as <ph name="USER_EMAIL_ADDRESS">$1<ex>foo@gmail.com</ex></ph>.
@@ -14990,6 +15071,9 @@
         Are you sure you want to delete "<ph name="PROFILE_NAME">$1<ex>New User</ex></ph>" and all the data associated with it from this computer? This cannot be undone!
       </message>
     </if>
+    <message name="IDS_PROFILES_DELETE_MANAGED_ADDENDUM" desc="Additional message shown in the same dialog following the IDS_PROFILES_DELETE_MESSAGE, explaining to the user what will happen if they delete the profile of a supervised user.">
+      Visited websites and settings for this supervised user may still be visible by the manager at <ph name="BEGIN_LINK">&lt;a target="_blank" href="https://www.chrome.com/manage"&gt;</ph>www.chrome.com/manage<ph name="END_LINK">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph>.
+    </message>
     <message name="IDS_PROFILES_LIST_ITEM_CURRENT" desc="Text to display in the multi-profiles list when this profile is the current profile">
       <ph name="PROFILE_NAME">$1<ex>New User</ex></ph> (current)
     </message>
@@ -15008,19 +15092,19 @@
       Create
     </message>
     <message name="IDS_PROFILES_CREATE_LOCAL_ERROR" desc="Message shown when a local error (for example, a disk error) occurs during profile creation.">
-      Oops! The new profile couldn't be created. Please check your hard drive space and permissions and try again.
+      Oops! The new user couldn't be created. Please check your hard drive space and permissions and try again.
     </message>
-    <message name="IDS_PROFILES_CREATE_REMOTE_ERROR" desc="Message shown when a remote error (for example, a network error) occurs during profile creation.">
-      Oops! The new profile couldn't be created. Please check your network connection and try again later.
+    <message name="IDS_PROFILES_CREATE_REMOTE_ERROR" desc="Message shown when a remote error (for example, a network error) occurs during creation of a new supervised user.">
+      Oops! The new supervised user couldn't be created. Please check your network connection and try again later.
     </message>
-    <message name="IDS_PROFILES_CREATE_LIMITED_SIGNED_IN_LABEL" desc="Label for the 'Limited user' checkbox in the create-profile dialog when the current user is signed in. This will be followed by a 'Learn more' link.">
-      This is a limited user managed by <ph name="CUSTODIAN_EMAIL">$1<ex>user@gmail.com</ex>.</ph>
+    <message name="IDS_PROFILES_CREATE_MANAGED_SIGNED_IN_LABEL" desc="Label for the 'Supervised user' checkbox in the create-profile dialog when the current user is signed in. This will be followed by a 'Learn more' link.">
+      This is a supervised user managed by <ph name="CUSTODIAN_EMAIL">$1<ex>user@gmail.com</ex>.</ph>
     </message>
-    <message name="IDS_PROFILES_CREATE_LIMITED_NOT_SIGNED_IN_LABEL" desc="Label for the (disabled) 'Limited user' checkbox in the create-profile dialog when the current user is not signed in. This will be followed by a 'Sign in now' link.">
-      This is a limited user who will be managed by another user.
+    <message name="IDS_PROFILES_CREATE_MANAGED_NOT_SIGNED_IN_LABEL" desc="Label for the (disabled) 'Supervised user' checkbox in the create-profile dialog when the current user is not signed in. This will be followed by a 'Sign in now' link.">
+      This is a supervised user who will be managed by you.
 You need to be signed in to use this feature.
     </message>
-    <message name="IDS_PROFILES_CREATE_LIMITED_NOT_SIGNED_IN_LINK" desc="Text for the sign-in promo link, shown after the (disabled) 'Limited user' checkbox in the create-profile dialog when the current user is not signed in.">
+    <message name="IDS_PROFILES_CREATE_MANAGED_NOT_SIGNED_IN_LINK" desc="Text for the sign-in promo link, shown after the (disabled) 'Supervised user' checkbox in the create-profile dialog when the current user is not signed in.">
       Sign in now
     </message>
     <message name="IDS_PROFILES_CREATE_SHORTCUT_CHECKBOX" desc="Create Shortcut checkbox when creating a new profile">
@@ -15033,36 +15117,36 @@
       Remove desktop shortcut
     </message>
 
-    <!-- Limited-user creation wizard dialogs -->
-    <message name="IDS_NEW_LIMITED_USER_LEARN_MORE_TITLE" desc="Title for the 'Learn more' dialog for the limited user feature.">
-      What is a limited user?
+    <!-- Supervised-user creation wizard dialogs -->
+    <message name="IDS_NEW_MANAGED_USER_LEARN_MORE_TITLE" desc="Title for the 'Learn more' dialog for the supervised user feature.">
+      What is a supervised user?
     </message>
-    <message name="IDS_NEW_LIMITED_USER_LEARN_MORE_TEXT" desc="Informative text describing the 'limited user' feature in detail, shown when the 'Learn more' link is clicked in the 'Create User' dialog.">
-      By creating a limited user, you can provide a managed environment for another user to explore the web.
+    <message name="IDS_NEW_MANAGED_USER_LEARN_MORE_TEXT" desc="Informative text describing the 'supervised user' feature in detail, shown when the 'Learn more' link is clicked in the 'Create User' dialog. The HTML entities at the starts of the lines are a non-breaking space, a bullet, and another non-breaking space.">
+      A supervised user can explore the web with your guidance. As the manager of a supervised user in Chrome, you can
 
-As the manager of a limited user in Chrome on this device, you can determine the sites you wish to allow or restrict, review past visits, and manage other settings. A limited user is not a Google account &#8212; it applies only to this device.
+&#160;&#8226;&#160;allow or prohibit certain websites,
+&#160;&#8226;&#160;review websites the supervised user has visited, and
+&#160;&#8226;&#160;manage other settings.
+
+Creating a supervised user does not create a Google Account, and their settings and data will not follow them to other devices with Chrome Sync. Currently, a supervised user applies only to this installation of Chrome, on this device.
+
+After you create a new supervised user, you can manage their settings at any time, from any device, at www.chrome.com/manage.
     </message>
-    <message name="IDS_NEW_LIMITED_USER_LEARN_MORE_DONE_BUTTON" desc="Text for the 'OK' button on the 'Learn more' dialog for the limited user feature.">
+    <message name="IDS_NEW_MANAGED_USER_LEARN_MORE_DONE_BUTTON" desc="Text for the 'OK' button on the 'Learn more' dialog for the supervised user feature.">
       OK, got it!
     </message>
-    <message name="IDS_NEW_LIMITED_USER_SUCCESS_TITLE" desc="Title for the confirmation dialog that appears after a limited user has been created.">
-      <ph name="NEW_PROFILE_NAME">$1<ex>New User</ex></ph> has been created as a limited user!
+    <message name="IDS_NEW_MANAGED_USER_CREATED_TITLE" desc="Title for the confirmation dialog that appears after a supervised user has been created.">
+      <ph name="NEW_PROFILE_NAME">$1<ex>New User</ex></ph> has been created as a supervised user!
     </message>
-    <message name="IDS_NEW_LIMITED_USER_SUCCESS_TEXT_SLIDE_1" desc="Informative text for the confirmation dialog that appears after a limited user has been created. Slide 1.">
-      This limited user can currently browse all sites on the web.
-    </message>
-    <message name="IDS_NEW_LIMITED_USER_SUCCESS_TEXT_SLIDE_2" desc="Informative text for the confirmation dialog that appears after a limited user has been created. Slide 2.">
-      Your limited user can access their environment at any time from the user menu.
-    </message>
-    <message name="IDS_NEW_LIMITED_USER_SUCCESS_TEXT_SLIDE_3" desc="Informative text for the confirmation dialog that appears after a limited user has been created. Slide 3.">
-      As the manager of this limited user, you can configure settings for this user.
+    <message name="IDS_NEW_MANAGED_USER_CREATED_TEXT" desc="Informative text for the confirmation dialog that appears after a supervised user has been created.">
+      A supervised user named <ph name="NEW_PROFILE_NAME">$1<ex>New User</ex></ph> has been created. To set which websites this supervised user can view, you can configure restrictions and settings by visiting <ph name="BEGIN_LINK">&lt;a target="_blank" href="https://www.chrome.com/manage"&gt;</ph>www.chrome.com/manage<ph name="END_LINK">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph>. If you do not change the default settings, <ph name="NEW_PROFILE_NAME">$1<ex>New User</ex></ph> can browse all sites on the web.
 
-For help, please visit our help center.
+Please check your email at <ph name="ACCOUNT_EMAIL">$2<ex>jane.doe@gmail.com</ex></ph> for these and further instructions.
     </message>
-    <message name="IDS_NEW_LIMITED_USER_SUCCESS_DONE_BUTTON" desc="Text for the button that closes the dialog without making any additional changes, on the limited user creation confirmation dialog.">
+    <message name="IDS_NEW_MANAGED_USER_CREATED_DONE_BUTTON" desc="Text for the button that closes the dialog without making any additional changes, on the supervised user creation confirmation dialog.">
       Got it
     </message>
-    <message name="IDS_NEW_LIMITED_USER_SUCCESS_SWITCH_BUTTON" desc="Text forthe button that opens a window for the new limited user, on the limited user creation confirmation dialog.">
+    <message name="IDS_NEW_MANAGED_USER_CREATED_SWITCH_BUTTON" desc="Text for the button that opens a window for the new supervised user, on the supervised user creation confirmation dialog.">
       Switch to <ph name="NEW_PROFILE_NAME">$1<ex>New User</ex></ph>
     </message>
 
@@ -15095,6 +15179,21 @@
       <message name="IDS_GTALK_SCREEN_SHARE_DIALOG_TITLE" desc="Title of the dialog box asking user's permission to share their screen">
         Google Talk Screen Sharing Request
       </message>
+      <message name="IDS_GTALK_REMOTING_DIALOG_TITLE" desc="Title of the dialog box asking user's permission to start Hangouts Remote Desktop">
+        Google+ Hangouts
+      </message>
+      <message name="IDS_GTALK_REMOTING_DIALOG_MESSAGE" desc="Message of the dialog box asking user's permission to start Hangouts Remote Desktop">
+        A participant in this hangout has offered to help you by controlling your computer. If you accept:
+
+  &#8226; Everyone in this hangout can see your screen
+  &#8226; The person helping you will be able to control your mouse and keyboard
+  &#8226; You can end at any time
+
+Do you accept?
+      </message>
+      <message name="IDS_GTALK_REMOTING_CONTINUE_DIALOG_MESSAGE" desc="Message of the dialog box asking user's permission to continue Hangouts Remote Desktop">
+        You are being helped. Do you want to continue?
+      </message>
       <message name="IDS_OPEN_ASH_DESKTOP" desc="The text label of the Open Ash desktop menu item">
         Open Ash desktop
       </message>
@@ -15137,7 +15236,18 @@
     <message name="IDS_FLAGS_DESKTOP_GUEST_MODE_DESCRIPTION" desc="Description of about:flags option to turn on desktop guest mode">
       When enabled, a guest user will be available in desktop Chrome.
     </message>
-
+    <message name="IDS_FLAGS_ENABLE_NEW_PROFILE_MANAGEMENT_NAME" desc="Title for the flag to enable the new profile management.">
+      Enable new profile management system
+    </message>
+    <message name="IDS_FLAGS_ENABLE_NEW_PROFILE_MANAGEMENT_DESCRIPTION" desc="Description for the flag to enable the new profile management">
+      Enables the new profile management system, including profile sign-out and the new avatar menu UI.
+    </message>
+    <message name="IDS_FLAGS_ENABLE_GAIA_PROFILE_INFO_NAME" desc="Title for the flag to enable the gaia profile information">
+      Enable GAIA profile name and icon
+    </message>
+    <message name="IDS_FLAGS_ENABLE_GAIA_PROFILE_INFO_DESCRIPTION" desc="Description for the flag to enable the gaia profile information">
+      Enables using GAIA information to populate the profile name and icon in the avatar menu.
+    </message>
     <message name="IDS_FLAGS_ENABLE_GOOGLE_NOW_INTEGRATION_NAME" desc="Name of about:flags option to turn on Google Now integration">
       Google Now
     </message>
@@ -15174,6 +15284,16 @@
       Send user feedback to spelling service. For example, if spelling service marks a misspelled word, but the user adds it to the custom dictionary, then Chrome will send a feedback message to spelling service. Spelling service uses this feedback to improve spelling suggestions.
     </message>
 
+    <!-- Web MIDI API. -->
+    <message name="IDS_FLAGS_ENABLE_WEB_MIDI_NAME"
+             desc="Name of about:flag option to turn on Web MIDI API">
+      Enable Web MIDI API
+    </message>
+    <message name="IDS_FLAGS_ENABLE_WEB_MIDI_DESCRIPTION"
+             desc="Description of about:flag option to turn on Web MIDI API">
+      Enable Web MIDI API experimental support.
+    </message>
+
     <!-- Toast experiment. -->
     <message name="IDS_TRY_TOAST_SET_DEFAULT" desc="Text of the checkbox to make chrome the default browser">
       Make it my default browser
@@ -15241,9 +15361,12 @@
     <message name="IDS_MEDIA_GALLERIES_DIALOG_HEADER" desc="Header for media gallery permissions dialog.">
       Access Settings
     </message>
-    <message name="IDS_MEDIA_GALLERIES_DIALOG_SUBTEXT" desc="Explanatory text for the media gallery access permission. Indicates than the specified (by name) extension has access to the listed folders.">
+    <message name="IDS_MEDIA_GALLERIES_DIALOG_SUBTEXT_READ_WRITE" desc="Explanatory text for the media gallery access permission. Indicates than the specified (by name) extension has read and write access to the listed folders.">
       <ph name="EXTENSION">$1<ex>PhotoEditor</ex></ph> can access and change media in these locations.
     </message>
+    <message name="IDS_MEDIA_GALLERIES_DIALOG_SUBTEXT_READ_ONLY" desc="Explanatory text for the media gallery access permission. Indicates than the specified (by name) extension has read-only access to the listed folders.">
+      <ph name="EXTENSION">$1<ex>PhotoEditor</ex></ph> can access media in these locations.
+    </message>
     <message name="IDS_MEDIA_GALLERIES_UNATTACHED_LOCATIONS" desc="Header for media gallery permissions to locations not currently attached, i.e. removable devices which aren't plugged in">
       Unattached locations
     </message>
@@ -15438,11 +15561,11 @@
       Reload
     </message>
 
-    <!-- Managed Mode -->
-    <message name="IDS_MANAGED_MODE_WARNING_MESSAGE" desc="Infobar message when browsing outside of the content pack whitelist.">
-      You're browsing on a site that is not in any installed content pack.
+    <!-- Supervised User Warning Infobar -->
+    <message name="IDS_MANAGED_USER_WARN_INFOBAR_MESSAGE" desc="Infobar message when browsing a site that is not explicitly permitted by a whitelist or manual exception.">
+      You're browsing on a site that may not be something you really want to see.
     </message>
-    <message name="IDS_MANAGED_MODE_GO_BACK_ACTION" desc="Label for the button that goes back to a 'safe' page.">
+    <message name="IDS_MANAGED_USER_WARN_INFOBAR_GO_BACK" desc="Label for the button that goes back to a 'safe' page.">
       Take me back!
     </message>
 
@@ -15475,8 +15598,8 @@
     <message name="IDS_IDENTITY_INTERNALS_TOKEN_CACHE_TEXT" desc="The title of the token cache of the Identity API.">
       Identity API Token Cache
     </message>
-    <message name="IDS_IDENTITY_INTERNALS_TOKEN_ID" desc="Label of the row containing the token id.">
-      Token Id
+    <message name="IDS_IDENTITY_INTERNALS_ACCESS_TOKEN" desc="Label of the row containing the access token.">
+      Access Token
     </message>
     <message name="IDS_IDENTITY_INTERNALS_EXTENSION_NAME" desc="Label of the row containing a name of an extension related to the identity token.">
       Extension Name
@@ -15511,6 +15634,8 @@
       </structure>
       <structure name="IDD_CHROME_FRAME_READY_PROMPT" file="cf_resources.rc" type="dialog" >
       </structure>
+      <structure name="IDD_CHROME_FRAME_TURNDOWN_PROMPT" file="cf_resources.rc" type="dialog" >
+      </structure>
     </structures>
   </release>
 </grit>
diff --git a/chrome/app/google_chrome_strings.grd b/chrome/app/google_chrome_strings.grd
index 9ee5956..eb892d3 100644
--- a/chrome/app/google_chrome_strings.grd
+++ b/chrome/app/google_chrome_strings.grd
@@ -191,6 +191,15 @@
         <message name="IDS_CHROME_FRAME_READY_MODE_LEARN_MORE_URL" desc="Link to knowledge-base article about Chrome Frame Ready Mode">
           http://www.google.com/support/chrome/bin/answer.py?hl=[GRITLANGCODE]&amp;answer=161796
         </message>
+        <message name="IDS_CHROME_FRAME_TURNDOWN_LEARN_MORE_URL" desc="Link to knowledge-base article about Chrome Frame turndown">
+          http://support.google.com/chrome/?p=ib_chromeframe
+        </message>
+        <message name="IDS_CHROME_FRAME_TURNDOWN_TEXT_IE_OLDER" desc="Text of Chrome Frame turndown prompt for IE 6, 7, and 8">
+          This site is using the Chrome Frame plug-in which will soon be unsupported. Please uninstall it and upgrade to a modern browser.
+	</message>
+        <message name="IDS_CHROME_FRAME_TURNDOWN_TEXT_IE_NEWER" desc="Text of Chrome Frame turndown prompt for IE 9 and 10">
+          This site is using the Chrome Frame plug-in that will soon be unsupported. Please uninstall it and download a compatible browser.
+	</message>
         <message name="IDS_SHORTCUT_NEW_WINDOW" desc="The text label of the New window shortcut context menu entry as of Windows 8">
           New window
         </message>
@@ -639,6 +648,11 @@
           Nearly up-to-date! Restart your device to finish updating.
         </message>
       </if>
+      <if expr="pp_ifdef('chromeos')">
+        <message name="IDS_UPGRADE_SUCCESSFUL_CHANNEL_SWITCH" desc="Status label: Channel was successfully switched on Chrome OS">
+          Channel changed. Restart your device to apply changes.
+        </message>
+      </if>
       <if expr="not pp_ifdef('chromeos')">
         <message name="IDS_UPGRADE_UP_TO_DATE" desc="Status label: Already up to date (Google Chrome)">
           Google Chrome is up to date.
@@ -659,6 +673,11 @@
           Updating your device...
         </message>
       </if>
+      <if expr="pp_ifdef('chromeos')">
+        <message name="IDS_UPGRADE_UPDATING_CHANNEL_SWITCH" desc="Status label: Updating Chrome OS to a specified channel">
+          Updating your device to <ph name="CHANNEL_NAME">$1<ex>stable</ex></ph> channel...
+        </message>
+      </if>
 
       <!-- iOS Upgrade available info bar-->
       <if expr="pp_ifdef('ios')">
@@ -793,7 +812,7 @@
       <!-- Enterprise sign-in dialog (new-style) -->
       <!-- TODO(dconnelly): remove "new-style" once the old dialog is gone. -->
       <message name="IDS_ENTERPRISE_SIGNIN_TITLE_NEW_STYLE" desc="The title of the dialog to confirm linking the browser profile with the signed-in enterprise account">
-        Save your Chrome data to this account?
+        Link your Chrome data to this account?
       </message>
       <message name="IDS_ENTERPRISE_SIGNIN_EXPLANATION_WITHOUT_PROFILE_CREATION_NEW_STYLE" desc="The warning message displayed to an enterprise user about to link their profile to their Google account. This message is followed by a 'Learn more' link.">
         You are signing in with a managed account and giving its administrator control over your Google Chrome profile. Your Chrome data, such as your apps, bookmarks, history, passwords, and other settings will become permanently tied to <ph name="USER_NAME">$1<ex>pat@example.com</ex></ph>. You will be able to delete this data via the Google Accounts Dashboard, but you will not be able to associate this data with another account. <ph name="LEARN_MORE">$2<ex>Learn more</ex></ph>
@@ -901,6 +920,16 @@
           <ph name="DOMAIN">$1<ex>example.com</ex></ph> requires that you read and accept the following Terms of Service before using this device. These terms do not expand, modify or limit the Google Chrome OS Terms.
         </message>
       </if>
+
+      <!-- Chrome Notifications center -->
+      <if expr="is_win">
+        <message name="IDS_MESSAGE_CENTER_BALLOON_TITLE" desc="Title of the first run notification ballon describing the notification center.">
+          Chrome Notification Center
+        </message>
+        <message name="IDS_MESSAGE_CENTER_BALLOON_TEXT" desc="Body text for the the first run notification ballon describing the notification center.">
+          You can see all your notifications from Chrome apps, extensions, and websites here.
+        </message>
+      </if>
     </messages>
   </release>
 </grit>
diff --git a/chrome/app/metro_driver_win.cc b/chrome/app/metro_driver_win.cc
index 66bf3e8..a562711 100644
--- a/chrome/app/metro_driver_win.cc
+++ b/chrome/app/metro_driver_win.cc
@@ -46,9 +46,7 @@
     // It is not next to the build output, so this must be an actual deployment
     // and in that case we need the mainloader to find the current version
     // directory.
-    MainDllLoader* loader = MakeMainDllLoader();
-    std::wstring version = loader->GetVersion();
-    delete loader;
+    string16 version(GetCurrentModuleVersion());
     if (!version.empty()) {
       std::wstring exe_path(GetExecutablePath());
       exe_path.append(version).append(L"\\").append(chrome::kMetroDriverDll);
diff --git a/chrome/app/nacl_fork_delegate_linux.cc b/chrome/app/nacl_fork_delegate_linux.cc
index c16603d..6f797cc 100644
--- a/chrome/app/nacl_fork_delegate_linux.cc
+++ b/chrome/app/nacl_fork_delegate_linux.cc
@@ -21,8 +21,9 @@
 #include "base/process_util.h"
 #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
 #include "chrome/common/chrome_paths.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/nacl_helper_linux.h"
+#include "chrome/common/nacl_paths.h"
+#include "components/nacl/common/nacl_switches.h"
 
 NaClForkDelegate::NaClForkDelegate()
     : status_(kNaClHelperUnused),
@@ -50,9 +51,9 @@
   status_ = kNaClHelperUnused;
   base::FilePath helper_exe;
   base::FilePath helper_bootstrap_exe;
-  if (!PathService::Get(chrome::FILE_NACL_HELPER, &helper_exe)) {
+  if (!PathService::Get(nacl::FILE_NACL_HELPER, &helper_exe)) {
     status_ = kNaClHelperMissing;
-  } else if (!PathService::Get(chrome::FILE_NACL_HELPER_BOOTSTRAP,
+  } else if (!PathService::Get(nacl::FILE_NACL_HELPER_BOOTSTRAP,
                                &helper_bootstrap_exe)) {
     status_ = kNaClHelperBootstrapMissing;
   } else if (RunningOnValgrind()) {
diff --git a/chrome/app/nibs/Panel.xib b/chrome/app/nibs/Panel.xib
index aeba727..fa2ac6e 100644
--- a/chrome/app/nibs/Panel.xib
+++ b/chrome/app/nibs/Panel.xib
@@ -1,14 +1,14 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
 	<data>
-		<int key="IBDocument.SystemTarget">1070</int>
-		<string key="IBDocument.SystemVersion">12B19</string>
-		<string key="IBDocument.InterfaceBuilderVersion">2549</string>
-		<string key="IBDocument.AppKitVersion">1187</string>
-		<string key="IBDocument.HIToolboxVersion">624.00</string>
+		<int key="IBDocument.SystemTarget">1060</int>
+		<string key="IBDocument.SystemVersion">12D78</string>
+		<string key="IBDocument.InterfaceBuilderVersion">3084</string>
+		<string key="IBDocument.AppKitVersion">1187.37</string>
+		<string key="IBDocument.HIToolboxVersion">626.00</string>
 		<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
 			<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
-			<string key="NS.object.0">2549</string>
+			<string key="NS.object.0">3084</string>
 		</object>
 		<object class="NSArray" key="IBDocument.IntegratedClassDependencies">
 			<bool key="EncodedWithXMLCoder">YES</bool>
@@ -43,7 +43,7 @@
 				<string key="NSClassName">NSApplication</string>
 			</object>
 			<object class="NSWindowTemplate" id="1005">
-				<int key="NSWindowStyleMask">259</int>
+				<int key="NSWindowStyleMask">263</int>
 				<int key="NSWindowBacking">2</int>
 				<string key="NSWindowRect">{{196, 240}, {480, 270}}</string>
 				<int key="NSWTFlags">544736256</int>
diff --git a/chrome/app/nibs/Toolbar.xib b/chrome/app/nibs/Toolbar.xib
index f93f386..1a912be 100644
--- a/chrome/app/nibs/Toolbar.xib
+++ b/chrome/app/nibs/Toolbar.xib
@@ -2,13 +2,13 @@
 <archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
 	<data>
 		<int key="IBDocument.SystemTarget">1050</int>
-		<string key="IBDocument.SystemVersion">12C3012</string>
-		<string key="IBDocument.InterfaceBuilderVersion">2844</string>
-		<string key="IBDocument.AppKitVersion">1187.34</string>
-		<string key="IBDocument.HIToolboxVersion">625.00</string>
+		<string key="IBDocument.SystemVersion">12D78</string>
+		<string key="IBDocument.InterfaceBuilderVersion">3084</string>
+		<string key="IBDocument.AppKitVersion">1187.37</string>
+		<string key="IBDocument.HIToolboxVersion">626.00</string>
 		<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
 			<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
-			<string key="NS.object.0">2844</string>
+			<string key="NS.object.0">3084</string>
 		</object>
 		<object class="NSArray" key="IBDocument.IntegratedClassDependencies">
 			<bool key="EncodedWithXMLCoder">YES</bool>
@@ -47,7 +47,7 @@
 					<object class="NSCustomView" id="421615633">
 						<reference key="NSNextResponder" ref="928520650"/>
 						<int key="NSvFlags">-2147483383</int>
-						<string key="NSFrame">{{572, -2}, {2, 35}}</string>
+						<string key="NSFrame">{{572, -1}, {2, 35}}</string>
 						<reference key="NSSuperview" ref="928520650"/>
 						<reference key="NSWindow"/>
 						<reference key="NSNextKeyView" ref="602421009"/>
@@ -56,7 +56,7 @@
 					<object class="NSTextField" id="535508469">
 						<reference key="NSNextResponder" ref="928520650"/>
 						<int key="NSvFlags">266</int>
-						<string key="NSFrame">{{119, 4}, {454, 27}}</string>
+						<string key="NSFrame">{{119, 4}, {454, 29}}</string>
 						<reference key="NSSuperview" ref="928520650"/>
 						<reference key="NSWindow"/>
 						<reference key="NSNextKeyView" ref="421615633"/>
@@ -97,7 +97,7 @@
 					<object class="NSButton" id="368496192">
 						<reference key="NSNextResponder" ref="928520650"/>
 						<int key="NSvFlags">268</int>
-						<string key="NSFrame">{{87, 3}, {29, 29}}</string>
+						<string key="NSFrame">{{87, 4}, {29, 29}}</string>
 						<reference key="NSSuperview" ref="928520650"/>
 						<reference key="NSWindow"/>
 						<reference key="NSNextKeyView" ref="535508469"/>
@@ -125,7 +125,7 @@
 					<object class="NSButton" id="458854861">
 						<reference key="NSNextResponder" ref="928520650"/>
 						<int key="NSvFlags">268</int>
-						<string key="NSFrame">{{59, 3}, {29, 29}}</string>
+						<string key="NSFrame">{{59, 4}, {29, 29}}</string>
 						<reference key="NSSuperview" ref="928520650"/>
 						<reference key="NSWindow"/>
 						<reference key="NSNextKeyView" ref="368496192"/>
@@ -149,7 +149,7 @@
 					<object class="NSButton" id="781044416">
 						<reference key="NSNextResponder" ref="928520650"/>
 						<int key="NSvFlags">268</int>
-						<string key="NSFrame">{{31, 3}, {29, 29}}</string>
+						<string key="NSFrame">{{31, 4}, {29, 29}}</string>
 						<reference key="NSSuperview" ref="928520650"/>
 						<reference key="NSWindow"/>
 						<reference key="NSNextKeyView" ref="458854861"/>
@@ -173,7 +173,7 @@
 					<object class="NSButton" id="634265909">
 						<reference key="NSNextResponder" ref="928520650"/>
 						<int key="NSvFlags">268</int>
-						<string key="NSFrame">{{3, 3}, {29, 29}}</string>
+						<string key="NSFrame">{{3, 4}, {29, 29}}</string>
 						<reference key="NSSuperview" ref="928520650"/>
 						<reference key="NSWindow"/>
 						<reference key="NSNextKeyView" ref="781044416"/>
@@ -197,9 +197,10 @@
 					<object class="NSButton" id="602421009">
 						<reference key="NSNextResponder" ref="928520650"/>
 						<int key="NSvFlags">265</int>
-						<string key="NSFrame">{{576, 3}, {29, 29}}</string>
+						<string key="NSFrame">{{576, 4}, {29, 29}}</string>
 						<reference key="NSSuperview" ref="928520650"/>
 						<reference key="NSWindow"/>
+						<reference key="NSNextKeyView"/>
 						<bool key="NSEnabled">YES</bool>
 						<object class="NSButtonCell" key="NSCell" id="204555298">
 							<int key="NSCellFlags">67108864</int>
@@ -217,7 +218,7 @@
 						<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
 					</object>
 				</object>
-				<string key="NSFrameSize">{608, 34}</string>
+				<string key="NSFrameSize">{608, 35}</string>
 				<reference key="NSSuperview"/>
 				<reference key="NSWindow"/>
 				<reference key="NSNextKeyView" ref="634265909"/>
@@ -917,10 +918,6 @@
 			<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.macosx</string>
 			<integer value="1050" key="NS.object.0"/>
 		</object>
-		<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults">
-			<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.macosx</string>
-			<real value="1070" key="NS.object.0"/>
-		</object>
 		<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
 			<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string>
 			<integer value="3000" key="NS.object.0"/>
diff --git a/chrome/app/policy/policy_templates.json b/chrome/app/policy/policy_templates.json
index fbd4a5b..e06157a 100644
--- a/chrome/app/policy/policy_templates.json
+++ b/chrome/app/policy/policy_templates.json
@@ -112,7 +112,7 @@
 #   persistent IDs for all fields (but not for groups!) are needed. These are
 #   specified by the 'id' keys of each policy. NEVER CHANGE EXISTING IDs,
 #   because doing so would break the deployed wire format!
-#   For your editing convenience: highest ID currently used: 214
+#   For your editing convenience: highest ID currently used: 223
 #
 # Placeholders:
 #   The following placeholder strings are automatically substituted:
@@ -4247,7 +4247,7 @@
           The policy value should be specified in milliseconds.''',
         },
         {
-          'name': 'IdleAction',
+          'name': 'IdleActionAC',
           'type': 'int-enum',
           'schema': {
             'type': 'integer',
@@ -4262,7 +4262,7 @@
             {
               'name': 'IdleActionLogout',
               'value': 1,
-              'caption': '''Log out the user''',
+              'caption': '''Log the user out''',
             },
             {
               'name': 'IdleActionShutdown',
@@ -4275,15 +4275,60 @@
               'caption': '''Do nothing''',
             },
           ],
-          'supported_on': ['chrome_os:26-'],
+          'supported_on': ['chrome_os:30-'],
           'features': {
             'dynamic_refresh': True,
             'per_profile': False,
           },
           'example_value': 0,
           'id': 180,
-          'caption': '''Action to take when the idle delay is reached''',
-          'desc': '''Specify the action to take when the idle delay is reached.
+          'caption': '''Action to take when the idle delay is reached while running on AC power''',
+          'desc': '''Specify the action to take when the idle delay is reached while running on AC power.
+
+          When this policy is set, it specifies the action that <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> takes when the user remains idle for the length of time given by the idle delay, which can be configured separately.
+
+          When this policy is unset, the default action is taken, which is suspend.
+
+          If the action is suspend, <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> can separately be configured to either lock or not lock the screen before suspending.''',
+        },
+        {
+          'name': 'IdleActionBattery',
+          'type': 'int-enum',
+          'schema': {
+            'type': 'integer',
+            'enum': [ 0, 1, 2, 3 ],
+          },
+          'items': [
+            {
+              'name': 'IdleActionSuspend',
+              'value': 0,
+              'caption': '''Suspend''',
+            },
+            {
+              'name': 'IdleActionLogout',
+              'value': 1,
+              'caption': '''Log the user out''',
+            },
+            {
+              'name': 'IdleActionShutdown',
+              'value': 2,
+              'caption': '''Shut down''',
+            },
+            {
+              'name': 'IdleActionDoNothing',
+              'value': 3,
+              'caption': '''Do nothing''',
+            },
+          ],
+          'supported_on': ['chrome_os:30-'],
+          'features': {
+            'dynamic_refresh': True,
+            'per_profile': False,
+          },
+          'example_value': 0,
+          'id': 222,
+          'caption': '''Action to take when the idle delay is reached while running on battery power''',
+          'desc': '''Specify the action to take when the idle delay is reached while running on battery power.
 
           When this policy is set, it specifies the action that <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> takes when the user remains idle for the length of time given by the idle delay, which can be configured separately.
 
@@ -4307,7 +4352,7 @@
             {
               'name': 'LidCloseActionLogout',
               'value': 1,
-              'caption': '''Log out the user''',
+              'caption': '''Log the user out''',
             },
             {
               'name': 'LidCloseActionShutdown',
@@ -4376,21 +4421,36 @@
           'name': 'PresentationIdleDelayScale',
           'type': 'int',
           'schema': { 'type': 'integer' },
-          'supported_on': ['chrome_os:26-'],
+          'supported_on': ['chrome_os:26-28'],
+          'features': {
+            'dynamic_refresh': True,
+            'per_profile': False,
+          },
+          'deprecated': True,
+          'example_value': 200,
+          'id': 184,
+          'caption': '''Percentage by which to scale the idle delay in presentation mode (deprecated)''',
+          'desc': '''This policy has been retired as of <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> version 29. Please use the PresentationScreenDimDelayScale policy instead.''',
+        },
+        {
+          'name': 'PresentationScreenDimDelayScale',
+          'type': 'int',
+          'schema': { 'type': 'integer' },
+          'supported_on': ['chrome_os:29-'],
           'features': {
             'dynamic_refresh': True,
             'per_profile': False,
           },
           'example_value': 200,
-          'id': 184,
-          'caption': '''Percentage by which to scale the idle delay in presentation mode''',
-          'desc': '''Specifies the percentage by which the idle delay is scaled when the device is in presentation mode.
+          'id': 220,
+          'caption': '''Percentage by which to scale the screen dim delay in presentation mode''',
+          'desc': '''Specifies the percentage by which the screen dim delay is scaled when the device is in presentation mode.
 
-          If this policy is set, it specifies the percentage by which the idle delay is scaled when the device is in presentation mode. When the idle delay is scaled, the screen dimming, screen off and screen lock delays get adjusted to maintain the same distances from the idle delay as originally configured.
+          If this policy is set, it specifies the percentage by which the screen dim delay is scaled when the device is in presentation mode. When the screen dim delay is scaled, the screen off, screen lock and idle delays get adjusted to maintain the same distances from the screen dim delay as originally configured.
 
           If this policy is unset, a default scale factor is used.
 
-          The scale factor must be 100% or more. Values that would make the idle delay in presentation mode shorter than the regular idle delay are not allowed.''',
+          The scale factor must be 100% or more. Values that would make the screen dim delay in presentation mode shorter than the regular screen dim delay are not allowed.''',
         },
         {
           'name': 'AllowScreenWakeLocks',
@@ -4604,6 +4664,107 @@
 
           If this policy is left unset, the screen magnifier is disabled initially but can be enabled by the user anytime.''',
         },
+        {
+          'name': 'DeviceLoginScreenDefaultLargeCursorEnabled',
+          'type': 'main',
+          'schema': { 'type': 'boolean' },
+          'supported_on': ['chrome_os:29-'],
+          'device_only': True,
+          'features': {
+            'dynamic_refresh': True,
+          },
+          'example_value': True,
+          'id': 215,
+          'caption': '''Set default state of the large cursor on the login screen''',
+          'desc': '''Set the default state of the large cursor accessibility feature on the login screen.
+
+          If this policy is set to true, the large cursor will be enabled when the login screen is shown.
+
+          If this policy is set to false, the large cursor will be disabled when the login screen is shown.
+
+          If you set this policy, users can temporarily override it by enabling or disabling the large cursor. However, the user's choice is not persistent and the default is restored whenever the login screen is shown anew or the user remains idle on the login screen for a minute.
+
+          If this policy is left unset, the large cursor is disabled when the login screen is first shown. Users can enable or disable the large cursor anytime and its status on the login screen is persisted between users.''',
+        },
+        {
+          'name': 'DeviceLoginScreenDefaultSpokenFeedbackEnabled',
+          'type': 'main',
+          'schema': { 'type': 'boolean' },
+          'supported_on': ['chrome_os:29-'],
+          'device_only': True,
+          'features': {
+            'dynamic_refresh': True,
+          },
+          'example_value': True,
+          'id': 216,
+          'caption': '''Set the default state of spoken feedback on the login screen''',
+          'desc': '''Set the default state of the spoken feedback accessibility feature on the login screen.
+
+          If this policy is set to true, spoken feedback will be enabled when the login screen is shown.
+
+          If this policy is set to false, spoken feedback will be disabled when the login screen is shown.
+
+          If you set this policy, users can temporarily override it by enabling or disabling spoken feedback. However, the user's choice is not persistent and the default is restored whenever the login screen is shown anew or the user remains idle on the login screen for a minute.
+
+          If this policy is left unset, spoken feedback is disabled when the login screen is first shown. Users can enable or disable spoken feedback anytime and its status on the login screen is persisted between users.''',
+        },
+        {
+          'name': 'DeviceLoginScreenDefaultHighContrastEnabled',
+          'type': 'main',
+          'schema': { 'type': 'boolean' },
+          'supported_on': ['chrome_os:29-'],
+          'device_only': True,
+          'features': {
+            'dynamic_refresh': True,
+          },
+          'example_value': True,
+          'id': 217,
+          'caption': '''Set the default state of high contrast mode on the login screen''',
+          'desc': '''Set the default state of the high contrast mode accessibility feature on the login screen.
+
+          If this policy is set to true, high contrast mode will be enabled when the login screen is shown.
+
+          If this policy is set to false, high contrast mode will be disabled when the login screen is shown.
+
+          If you set this policy, users can temporarily override it by enabling or disabling high contrast mode. However, the user's choice is not persistent and the default is restored whenever the login screen is shown anew or the user remains idle on the login screen for a minute.
+
+          If this policy is left unset, high contrast mode is disabled when the login screen is first shown. Users can enable or disable high contrast mode anytime and its status on the login screen is persisted between users.''',
+        },
+        {
+          'name': 'DeviceLoginScreenDefaultScreenMagnifierType',
+          'type': 'int-enum',
+          'schema': {
+            'type': 'integer',
+            'enum': [ 0, 1 ],
+          },
+          'items': [
+            {
+              'name': 'None',
+              'value': 0,
+              'caption': '''Screen magnifier disabled''',
+            },
+            {
+              'name': 'Full-screen',
+              'value': 1,
+              'caption': '''Full-screen magnifier enabled''',
+            },
+          ],
+          'supported_on': ['chrome_os:29-'],
+          'device_only': True,
+          'features': {
+            'dynamic_refresh': True,
+          },
+          'example_value': 1,
+          'id': 218,
+          'caption': '''Set the default screen magnifier type enabled on the login screen''',
+          'desc': '''Set the default type of screen magnifier that is enabled on the login screen.
+
+          If this policy is set, it controls the type of screen magnifier that is enabled when the login screen is shown. Setting the policy to "None" disables the screen magnifier.
+
+          If you set this policy, users can temporarily override it by enabling or disabling the screen magnifier. However, the user's choice is not persistent and the default is restored whenever the login screen is shown anew or the user remains idle on the login screen for a minute.
+
+          If this policy is left unset, the screen magnifier is disabled when the login screen is first shown. Users can enable or disable the screen magnifier anytime and its status on the login screen is persisted between users.''',
+        },
       ],
     },
     {
@@ -4789,6 +4950,19 @@
       ],
     },
     {
+      'name': 'SuppressChromeFrameTurndownPrompt',
+      'caption': '''Suppress the <ph name="PRODUCT_FRAME_NAME">$3<ex>Google Chrome Frame</ex></ph> turndown prompt''',
+      'desc': '''Suppresses the turndown prompt that appears when a site is rendered by <ph name="PRODUCT_FRAME_NAME">$3<ex>Google Chrome Frame</ex></ph>.''',
+      'type': 'main',
+      'schema': { 'type': 'boolean' },
+      'supported_on': ['chrome_frame:29-'],
+      'features': {
+        'dynamic_refresh': False,
+      },
+      'example_value': True,
+      'id': 221,
+    },
+    {
       'name': 'LocallyManagedUsers',
       'type': 'group',
       'caption': '''Locally managed users settings''',
@@ -4881,6 +5055,40 @@
 
           This policy is for internal use by Chrome itself.''',
         },
+        {
+          'name': 'SupervisedUsersEnabled',
+          'type': 'main',
+          'schema': { 'type': 'boolean' },
+          'supported_on': ['chrome_os:29-'],
+          'device_only': True,
+          'features': {
+            'dynamic_refresh': False,
+          },
+          'example_value': True,
+          'id': 219,
+          'caption': '''Enable supervised users.''',
+          'desc': '''If set to true, supervised users can be created and used.
+
+          If set to false or not configured, supervised-user creation and login will be disabled. All existing supervised users will be hidden.
+
+          NOTE: The default behavior for consumer and enterprise devices differs: on consumer devices supervised users are enabled by default, but on enterprise devices they are disabled by default.'''
+        },
+        {
+          'name': 'SupervisedUserCreationEnabled',
+          'type': 'main',
+          'schema': { 'type': 'boolean' },
+          'supported_on': ['chrome.*:29-'],
+          'features': {
+            'dynamic_refresh': True,
+            'per_profile': True,
+          },
+          'example_value': True,
+          'id': 223,
+          'caption': '''Enable creation of supervised users.''',
+          'desc': '''If set to false, supervised-user creation by this user will be disabled. Any existing supervised users will still be available.
+
+          If set to true or not configured, supervised users can be created and managed by this user.'''
+        },
       ],
     },
   ],
diff --git a/chrome/app/resources/locale_settings.grd b/chrome/app/resources/locale_settings.grd
index e251c72..d5b3d39 100644
--- a/chrome/app/resources/locale_settings.grd
+++ b/chrome/app/resources/locale_settings.grd
@@ -384,34 +384,6 @@
         https://www.google.com/support/chrome/bin/answer.py?answer=1181420
       </message>
 
-      <!-- The width of the cloud print setup wizard / login dialog in -->
-      <!-- characters. -->
-      <message name="IDS_CLOUD_PRINT_SETUP_WIZARD_WIDTH_CHARS" 
-               use_name_for_id="true">
-        76
-      </message>
-
-      <!-- The height of the cloud print setup wizard / login dialog in -->
-      <!-- characters. -->
-      <message name="IDS_CLOUD_PRINT_SETUP_WIZARD_HEIGHT_LINES"
-               use_name_for_id="true">
-        15
-      </message>
-
-      <!-- The width of the cloud print setup wizard / login dialog in -->
-      <!-- characters when showing done. -->
-      <message name="IDS_CLOUD_PRINT_SETUP_WIZARD_DONE_WIDTH_CHARS" 
-               use_name_for_id="true">
-        46
-      </message>
-
-      <!-- The height of the cloud print setup wizard / login dialog in -->
-      <!-- characters when showing done. -->
-      <message name="IDS_CLOUD_PRINT_SETUP_WIZARD_DONE_HEIGHT_LINES"
-               use_name_for_id="true">
-        15
-      </message>
-
       <!-- The width for the "create application shortcuts" dialog in characters. -->
       <message name="IDS_CREATE_SHORTCUTS_DIALOG_WIDTH_CHARS" use_name_for_id="true">
         65
diff --git a/chrome/app/resources/manpage.1.in b/chrome/app/resources/manpage.1.in
index 695cc1f..aae705c 100644
--- a/chrome/app/resources/manpage.1.in
+++ b/chrome/app/resources/manpage.1.in
@@ -62,7 +62,7 @@
   --proxy-server="socks://foobar:1080"
       Use the SOCKS v5 proxy "foobar:1080" to load all URLs.
 
-  --proxy-server="sock4://foobar:1080"
+  --proxy-server="socks4://foobar:1080"
       Use the SOCKS v4 proxy "foobar:1080" to load all URLs.
 
   --proxy-server="socks5://foobar:66"
diff --git a/chrome/app/theme/default_100_percent/allowed_mic_only.png b/chrome/app/theme/default_100_percent/allowed_mic_only.png
deleted file mode 100644
index 8852a37..0000000
--- a/chrome/app/theme/default_100_percent/allowed_mic_only.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/autofill_dialog_menu_button_disabled.png b/chrome/app/theme/default_100_percent/autofill_dialog_menu_button_disabled.png
index 03d5678..1afa0ec 100644
--- a/chrome/app/theme/default_100_percent/autofill_dialog_menu_button_disabled.png
+++ b/chrome/app/theme/default_100_percent/autofill_dialog_menu_button_disabled.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/autofill_dialog_menu_button_hover.png b/chrome/app/theme/default_100_percent/autofill_dialog_menu_button_hover.png
index c72f9bd..9ee71b5 100644
--- a/chrome/app/theme/default_100_percent/autofill_dialog_menu_button_hover.png
+++ b/chrome/app/theme/default_100_percent/autofill_dialog_menu_button_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/autofill_dialog_menu_button_normal.png b/chrome/app/theme/default_100_percent/autofill_dialog_menu_button_normal.png
index 54d9e58..ac8209a 100644
--- a/chrome/app/theme/default_100_percent/autofill_dialog_menu_button_normal.png
+++ b/chrome/app/theme/default_100_percent/autofill_dialog_menu_button_normal.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/autofill_dialog_menu_button_pressed.png b/chrome/app/theme/default_100_percent/autofill_dialog_menu_button_pressed.png
index b3c5e0a..864debb 100644
--- a/chrome/app/theme/default_100_percent/autofill_dialog_menu_button_pressed.png
+++ b/chrome/app/theme/default_100_percent/autofill_dialog_menu_button_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/blocked_cookies.png b/chrome/app/theme/default_100_percent/blocked_cookies.png
deleted file mode 100644
index 325e71e..0000000
--- a/chrome/app/theme/default_100_percent/blocked_cookies.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/blocked_images.png b/chrome/app/theme/default_100_percent/blocked_images.png
deleted file mode 100644
index 83194c5..0000000
--- a/chrome/app/theme/default_100_percent/blocked_images.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/blocked_mic_only.png b/chrome/app/theme/default_100_percent/blocked_mic_only.png
deleted file mode 100644
index 29ae00c..0000000
--- a/chrome/app/theme/default_100_percent/blocked_mic_only.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/blocked_mixed_content.png b/chrome/app/theme/default_100_percent/blocked_mixed_content.png
deleted file mode 100644
index 41bcc11..0000000
--- a/chrome/app/theme/default_100_percent/blocked_mixed_content.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/blocked_plugins.png b/chrome/app/theme/default_100_percent/blocked_plugins.png
deleted file mode 100644
index 9514691..0000000
--- a/chrome/app/theme/default_100_percent/blocked_plugins.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/blocked_popups.png b/chrome/app/theme/default_100_percent/blocked_popups.png
deleted file mode 100644
index de9abd3..0000000
--- a/chrome/app/theme/default_100_percent/blocked_popups.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/blocked_script.png b/chrome/app/theme/default_100_percent/blocked_script.png
deleted file mode 100644
index 4f3f44d..0000000
--- a/chrome/app/theme/default_100_percent/blocked_script.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/chromium/app_list_48.png b/chrome/app/theme/default_100_percent/chromium/app_list_48.png
index e0dad5b..5ac69ec 100644
--- a/chrome/app/theme/default_100_percent/chromium/app_list_48.png
+++ b/chrome/app/theme/default_100_percent/chromium/app_list_48.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/chromium/product_logo_name_48.png b/chrome/app/theme/default_100_percent/chromium/product_logo_name_48.png
new file mode 100644
index 0000000..49ee8fb
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/chromium/product_logo_name_48.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/action_box_button_hover.png b/chrome/app/theme/default_100_percent/common/action_box_button_hover.png
index ae969ae..02492f3 100644
--- a/chrome/app/theme/default_100_percent/common/action_box_button_hover.png
+++ b/chrome/app/theme/default_100_percent/common/action_box_button_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/action_box_button_normal.png b/chrome/app/theme/default_100_percent/common/action_box_button_normal.png
index 2113545..6cd4d54 100644
--- a/chrome/app/theme/default_100_percent/common/action_box_button_normal.png
+++ b/chrome/app/theme/default_100_percent/common/action_box_button_normal.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/action_box_button_pressed.png b/chrome/app/theme/default_100_percent/common/action_box_button_pressed.png
index 1603b66..a83051f 100644
--- a/chrome/app/theme/default_100_percent/common/action_box_button_pressed.png
+++ b/chrome/app/theme/default_100_percent/common/action_box_button_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/allowed_downloads.png b/chrome/app/theme/default_100_percent/common/allowed_downloads.png
new file mode 100644
index 0000000..631cce5
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/common/allowed_downloads.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/allowed_fullscreen.png b/chrome/app/theme/default_100_percent/common/allowed_fullscreen.png
similarity index 100%
rename from chrome/app/theme/default_100_percent/allowed_fullscreen.png
rename to chrome/app/theme/default_100_percent/common/allowed_fullscreen.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/allowed_images.png b/chrome/app/theme/default_100_percent/common/allowed_images.png
similarity index 100%
rename from chrome/app/theme/default_100_percent/allowed_images.png
rename to chrome/app/theme/default_100_percent/common/allowed_images.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/allowed_location.png b/chrome/app/theme/default_100_percent/common/allowed_location.png
similarity index 100%
rename from chrome/app/theme/default_100_percent/allowed_location.png
rename to chrome/app/theme/default_100_percent/common/allowed_location.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/allowed_mic_only.png b/chrome/app/theme/default_100_percent/common/allowed_mic_only.png
new file mode 100644
index 0000000..e0218ae
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/common/allowed_mic_only.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/allowed_mouse_cursor.png b/chrome/app/theme/default_100_percent/common/allowed_mouse_cursor.png
similarity index 100%
rename from chrome/app/theme/default_100_percent/allowed_mouse_cursor.png
rename to chrome/app/theme/default_100_percent/common/allowed_mouse_cursor.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/allowed_notifications.png b/chrome/app/theme/default_100_percent/common/allowed_notifications.png
similarity index 100%
rename from chrome/app/theme/default_100_percent/allowed_notifications.png
rename to chrome/app/theme/default_100_percent/common/allowed_notifications.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/allowed_plugins.png b/chrome/app/theme/default_100_percent/common/allowed_plugins.png
similarity index 100%
rename from chrome/app/theme/default_100_percent/allowed_plugins.png
rename to chrome/app/theme/default_100_percent/common/allowed_plugins.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/allowed_popups.png b/chrome/app/theme/default_100_percent/common/allowed_popups.png
similarity index 100%
rename from chrome/app/theme/default_100_percent/allowed_popups.png
rename to chrome/app/theme/default_100_percent/common/allowed_popups.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/allowed_script.png b/chrome/app/theme/default_100_percent/common/allowed_script.png
similarity index 100%
rename from chrome/app/theme/default_100_percent/allowed_script.png
rename to chrome/app/theme/default_100_percent/common/allowed_script.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/app_list_v1_overlay.png b/chrome/app/theme/default_100_percent/common/app_list_v1_overlay.png
index b740314..8476557 100644
--- a/chrome/app/theme/default_100_percent/common/app_list_v1_overlay.png
+++ b/chrome/app/theme/default_100_percent/common/app_list_v1_overlay.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/apps_bookmark_bar_icon.png b/chrome/app/theme/default_100_percent/common/apps_bookmark_bar_icon.png
index 7129667..fbeffff 100644
--- a/chrome/app/theme/default_100_percent/common/apps_bookmark_bar_icon.png
+++ b/chrome/app/theme/default_100_percent/common/apps_bookmark_bar_icon.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/audio_equalizer_column.png b/chrome/app/theme/default_100_percent/common/audio_equalizer_column.png
index 1dbd743..3de14dd 100644
--- a/chrome/app/theme/default_100_percent/common/audio_equalizer_column.png
+++ b/chrome/app/theme/default_100_percent/common/audio_equalizer_column.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/blocked_downloads.png b/chrome/app/theme/default_100_percent/common/blocked_downloads.png
new file mode 100644
index 0000000..360a1cc
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/common/blocked_downloads.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/blocked_fullscreen.png b/chrome/app/theme/default_100_percent/common/blocked_fullscreen.png
similarity index 100%
rename from chrome/app/theme/default_100_percent/blocked_fullscreen.png
rename to chrome/app/theme/default_100_percent/common/blocked_fullscreen.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/blocked_location.png b/chrome/app/theme/default_100_percent/common/blocked_location.png
similarity index 100%
rename from chrome/app/theme/default_100_percent/blocked_location.png
rename to chrome/app/theme/default_100_percent/common/blocked_location.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/blocked_media.png b/chrome/app/theme/default_100_percent/common/blocked_media.png
similarity index 100%
rename from chrome/app/theme/default_100_percent/blocked_media.png
rename to chrome/app/theme/default_100_percent/common/blocked_media.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/blocked_mic_only.png b/chrome/app/theme/default_100_percent/common/blocked_mic_only.png
new file mode 100644
index 0000000..5f8bb1c
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/common/blocked_mic_only.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/blocked_mouse_cursor.png b/chrome/app/theme/default_100_percent/common/blocked_mouse_cursor.png
similarity index 100%
rename from chrome/app/theme/default_100_percent/blocked_mouse_cursor.png
rename to chrome/app/theme/default_100_percent/common/blocked_mouse_cursor.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/blocked_notifications.png b/chrome/app/theme/default_100_percent/common/blocked_notifications.png
similarity index 100%
rename from chrome/app/theme/default_100_percent/blocked_notifications.png
rename to chrome/app/theme/default_100_percent/common/blocked_notifications.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/pepper_broker.png b/chrome/app/theme/default_100_percent/common/blocked_pepper_broker.png
similarity index 100%
rename from chrome/app/theme/default_100_percent/pepper_broker.png
rename to chrome/app/theme/default_100_percent/common/blocked_pepper_broker.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/browser_action_normal.png b/chrome/app/theme/default_100_percent/common/browser_action_normal.png
index ef57dbf..73f7fe7 100644
--- a/chrome/app/theme/default_100_percent/common/browser_action_normal.png
+++ b/chrome/app/theme/default_100_percent/common/browser_action_normal.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/browser_actions_overflow_normal.png b/chrome/app/theme/default_100_percent/common/browser_actions_overflow_normal.png
index 1fd9d98..763b2fa 100644
--- a/chrome/app/theme/default_100_percent/common/browser_actions_overflow_normal.png
+++ b/chrome/app/theme/default_100_percent/common/browser_actions_overflow_normal.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/browser_actions_overflow_pressed.png b/chrome/app/theme/default_100_percent/common/browser_actions_overflow_pressed.png
index 1f4f2bd..71dddab 100644
--- a/chrome/app/theme/default_100_percent/common/browser_actions_overflow_pressed.png
+++ b/chrome/app/theme/default_100_percent/common/browser_actions_overflow_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/browser_back_normal.png b/chrome/app/theme/default_100_percent/common/browser_back_normal.png
index e9bb539..0c21a4d 100644
--- a/chrome/app/theme/default_100_percent/common/browser_back_normal.png
+++ b/chrome/app/theme/default_100_percent/common/browser_back_normal.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/browser_forward_normal.png b/chrome/app/theme/default_100_percent/common/browser_forward_normal.png
index e0f46ba..811bc92 100644
--- a/chrome/app/theme/default_100_percent/common/browser_forward_normal.png
+++ b/chrome/app/theme/default_100_percent/common/browser_forward_normal.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/browser_reload_dimmed.png b/chrome/app/theme/default_100_percent/common/browser_reload_dimmed.png
index 33bdc9f..c9221ce 100644
--- a/chrome/app/theme/default_100_percent/common/browser_reload_dimmed.png
+++ b/chrome/app/theme/default_100_percent/common/browser_reload_dimmed.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/browser_reload_normal.png b/chrome/app/theme/default_100_percent/common/browser_reload_normal.png
index 059fec6..4c2c309 100644
--- a/chrome/app/theme/default_100_percent/common/browser_reload_normal.png
+++ b/chrome/app/theme/default_100_percent/common/browser_reload_normal.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/browser_stop_normal.png b/chrome/app/theme/default_100_percent/common/browser_stop_normal.png
index d9fe6d4..f4d74fe 100644
--- a/chrome/app/theme/default_100_percent/common/browser_stop_normal.png
+++ b/chrome/app/theme/default_100_percent/common/browser_stop_normal.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/browser_toolbar_bezel_hover.png b/chrome/app/theme/default_100_percent/common/browser_toolbar_bezel_hover.png
index 52d26ab..61e12b1 100644
--- a/chrome/app/theme/default_100_percent/common/browser_toolbar_bezel_hover.png
+++ b/chrome/app/theme/default_100_percent/common/browser_toolbar_bezel_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/browser_toolbar_bezel_pressed.png b/chrome/app/theme/default_100_percent/common/browser_toolbar_bezel_pressed.png
index b464f4c..d1320a2 100644
--- a/chrome/app/theme/default_100_percent/common/browser_toolbar_bezel_pressed.png
+++ b/chrome/app/theme/default_100_percent/common/browser_toolbar_bezel_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/browser_tools_badge_ash.png b/chrome/app/theme/default_100_percent/common/browser_tools_badge_ash.png
index d06fd20..42a7d5b 100644
--- a/chrome/app/theme/default_100_percent/common/browser_tools_badge_ash.png
+++ b/chrome/app/theme/default_100_percent/common/browser_tools_badge_ash.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/browser_tools_bar.png b/chrome/app/theme/default_100_percent/common/browser_tools_bar.png
index 9c823eb..b190709 100644
--- a/chrome/app/theme/default_100_percent/common/browser_tools_bar.png
+++ b/chrome/app/theme/default_100_percent/common/browser_tools_bar.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/browser_tools_bar_medium.png b/chrome/app/theme/default_100_percent/common/browser_tools_bar_medium.png
index c6961e5..399fdaa 100644
--- a/chrome/app/theme/default_100_percent/common/browser_tools_bar_medium.png
+++ b/chrome/app/theme/default_100_percent/common/browser_tools_bar_medium.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/browser_tools_normal.png b/chrome/app/theme/default_100_percent/common/browser_tools_normal.png
index d4199f7..99b300e 100644
--- a/chrome/app/theme/default_100_percent/common/browser_tools_normal.png
+++ b/chrome/app/theme/default_100_percent/common/browser_tools_normal.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/close_1.png b/chrome/app/theme/default_100_percent/common/close_1.png
index 902a7dc..fe1d9bd 100644
--- a/chrome/app/theme/default_100_percent/common/close_1.png
+++ b/chrome/app/theme/default_100_percent/common/close_1.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/download_button_center_bottom_hover.png b/chrome/app/theme/default_100_percent/common/download_button_center_bottom_hover.png
index 3ffccbb..f827b3b 100644
--- a/chrome/app/theme/default_100_percent/common/download_button_center_bottom_hover.png
+++ b/chrome/app/theme/default_100_percent/common/download_button_center_bottom_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/download_button_center_top.png b/chrome/app/theme/default_100_percent/common/download_button_center_top.png
index 5446b23..b11d2a6 100644
--- a/chrome/app/theme/default_100_percent/common/download_button_center_top.png
+++ b/chrome/app/theme/default_100_percent/common/download_button_center_top.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/download_button_center_top_hover.png b/chrome/app/theme/default_100_percent/common/download_button_center_top_hover.png
index 18ba5d2..750f3b8 100644
--- a/chrome/app/theme/default_100_percent/common/download_button_center_top_hover.png
+++ b/chrome/app/theme/default_100_percent/common/download_button_center_top_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/download_button_center_top_pressed.png b/chrome/app/theme/default_100_percent/common/download_button_center_top_pressed.png
index 6d20b7e..32036a0 100644
--- a/chrome/app/theme/default_100_percent/common/download_button_center_top_pressed.png
+++ b/chrome/app/theme/default_100_percent/common/download_button_center_top_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/download_button_menu_top_pressed.png b/chrome/app/theme/default_100_percent/common/download_button_menu_top_pressed.png
index 1412048..afa5a16 100644
--- a/chrome/app/theme/default_100_percent/common/download_button_menu_top_pressed.png
+++ b/chrome/app/theme/default_100_percent/common/download_button_menu_top_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/download_button_right_bottom_hover.png b/chrome/app/theme/default_100_percent/common/download_button_right_bottom_hover.png
index 6f411b1..fe32d5c 100644
--- a/chrome/app/theme/default_100_percent/common/download_button_right_bottom_hover.png
+++ b/chrome/app/theme/default_100_percent/common/download_button_right_bottom_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/download_button_right_top.png b/chrome/app/theme/default_100_percent/common/download_button_right_top.png
index 931c60a..c533eed 100644
--- a/chrome/app/theme/default_100_percent/common/download_button_right_top.png
+++ b/chrome/app/theme/default_100_percent/common/download_button_right_top.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/error_managed_mode_blocked_page.png b/chrome/app/theme/default_100_percent/common/error_managed_mode_blocked_page.png
index d1833a5..20e89c0 100644
--- a/chrome/app/theme/default_100_percent/common/error_managed_mode_blocked_page.png
+++ b/chrome/app/theme/default_100_percent/common/error_managed_mode_blocked_page.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/error_network_generic.png b/chrome/app/theme/default_100_percent/common/error_network_generic.png
index e3263ed..67fc216 100644
--- a/chrome/app/theme/default_100_percent/common/error_network_generic.png
+++ b/chrome/app/theme/default_100_percent/common/error_network_generic.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/favicon_conflicts.png b/chrome/app/theme/default_100_percent/common/favicon_conflicts.png
index 8675272..7eda2c1 100644
--- a/chrome/app/theme/default_100_percent/common/favicon_conflicts.png
+++ b/chrome/app/theme/default_100_percent/common/favicon_conflicts.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/favicon_downloads.png b/chrome/app/theme/default_100_percent/common/favicon_downloads.png
index 0efc0b9..06ef0ee 100644
--- a/chrome/app/theme/default_100_percent/common/favicon_downloads.png
+++ b/chrome/app/theme/default_100_percent/common/favicon_downloads.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/find_box_bg_left.png b/chrome/app/theme/default_100_percent/common/find_box_bg_left.png
index 3acfe03..0222f99 100644
--- a/chrome/app/theme/default_100_percent/common/find_box_bg_left.png
+++ b/chrome/app/theme/default_100_percent/common/find_box_bg_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/icon_add_user24.png b/chrome/app/theme/default_100_percent/common/icon_add_user24.png
index 15c06c9..f8edc5d 100644
--- a/chrome/app/theme/default_100_percent/common/icon_add_user24.png
+++ b/chrome/app/theme/default_100_percent/common/icon_add_user24.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/icon_add_user24_white.png b/chrome/app/theme/default_100_percent/common/icon_add_user24_white.png
index 1805b0b..8c72cf6 100644
--- a/chrome/app/theme/default_100_percent/common/icon_add_user24_white.png
+++ b/chrome/app/theme/default_100_percent/common/icon_add_user24_white.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/infobar_insecure.png b/chrome/app/theme/default_100_percent/common/infobar_insecure.png
deleted file mode 100644
index c8fbccd..0000000
--- a/chrome/app/theme/default_100_percent/common/infobar_insecure.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/input_good.png b/chrome/app/theme/default_100_percent/common/input_good.png
index eb2c347..1bcab80 100644
--- a/chrome/app/theme/default_100_percent/common/input_good.png
+++ b/chrome/app/theme/default_100_percent/common/input_good.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/limited_user.png b/chrome/app/theme/default_100_percent/common/limited_user.png
index 53719a6..9ec4e7d 100644
--- a/chrome/app/theme/default_100_percent/common/limited_user.png
+++ b/chrome/app/theme/default_100_percent/common/limited_user.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/managed_user_theme/label_bg_bottom.png b/chrome/app/theme/default_100_percent/common/managed_user_theme/label_bg_bottom.png
new file mode 100644
index 0000000..c7cc9db
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/common/managed_user_theme/label_bg_bottom.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/managed_user_theme/label_bg_bottom_left.png b/chrome/app/theme/default_100_percent/common/managed_user_theme/label_bg_bottom_left.png
new file mode 100644
index 0000000..8ab2ec4
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/common/managed_user_theme/label_bg_bottom_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/managed_user_theme/label_bg_bottom_right.png b/chrome/app/theme/default_100_percent/common/managed_user_theme/label_bg_bottom_right.png
new file mode 100644
index 0000000..7096371
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/common/managed_user_theme/label_bg_bottom_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/managed_user_theme/label_bg_center.png b/chrome/app/theme/default_100_percent/common/managed_user_theme/label_bg_center.png
new file mode 100644
index 0000000..be7eb77
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/common/managed_user_theme/label_bg_center.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/managed_user_theme/label_bg_left.png b/chrome/app/theme/default_100_percent/common/managed_user_theme/label_bg_left.png
new file mode 100644
index 0000000..fa2855b
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/common/managed_user_theme/label_bg_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/managed_user_theme/label_bg_right.png b/chrome/app/theme/default_100_percent/common/managed_user_theme/label_bg_right.png
new file mode 100644
index 0000000..881c609
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/common/managed_user_theme/label_bg_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/managed_user_theme/label_bg_top.png b/chrome/app/theme/default_100_percent/common/managed_user_theme/label_bg_top.png
new file mode 100644
index 0000000..cf95f7a
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/common/managed_user_theme/label_bg_top.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/managed_user_theme/label_bg_top_left.png b/chrome/app/theme/default_100_percent/common/managed_user_theme/label_bg_top_left.png
new file mode 100644
index 0000000..1edbc16
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/common/managed_user_theme/label_bg_top_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/managed_user_theme/label_bg_top_right.png b/chrome/app/theme/default_100_percent/common/managed_user_theme/label_bg_top_right.png
new file mode 100644
index 0000000..ad9760b
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/common/managed_user_theme/label_bg_top_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/managed_user_theme/theme_frame_supervised.png b/chrome/app/theme/default_100_percent/common/managed_user_theme/theme_frame_supervised.png
new file mode 100644
index 0000000..4683d2f
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/common/managed_user_theme/theme_frame_supervised.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/managed_user_theme/theme_frame_supervised_inactive.png b/chrome/app/theme/default_100_percent/common/managed_user_theme/theme_frame_supervised_inactive.png
new file mode 100644
index 0000000..f84da6f
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/common/managed_user_theme/theme_frame_supervised_inactive.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/managed_user_theme/theme_tab_background_supervised.png b/chrome/app/theme/default_100_percent/common/managed_user_theme/theme_tab_background_supervised.png
new file mode 100644
index 0000000..a6c3acf
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/common/managed_user_theme/theme_tab_background_supervised.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/omnibox_http_selected.png b/chrome/app/theme/default_100_percent/common/omnibox_http_selected.png
index 42f8da8..0a1873c 100644
--- a/chrome/app/theme/default_100_percent/common/omnibox_http_selected.png
+++ b/chrome/app/theme/default_100_percent/common/omnibox_http_selected.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/omnibox_https_policy_warning.png b/chrome/app/theme/default_100_percent/common/omnibox_https_policy_warning.png
index 0e527af..0081e7c 100644
--- a/chrome/app/theme/default_100_percent/common/omnibox_https_policy_warning.png
+++ b/chrome/app/theme/default_100_percent/common/omnibox_https_policy_warning.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/omnibox_mic_search.png b/chrome/app/theme/default_100_percent/common/omnibox_mic_search.png
new file mode 100644
index 0000000..90b98f1
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/common/omnibox_mic_search.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/payment_checkmark.png b/chrome/app/theme/default_100_percent/common/payment_checkmark.png
new file mode 100644
index 0000000..680bc10
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/common/payment_checkmark.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/tab_active_center.png b/chrome/app/theme/default_100_percent/common/tab_active_center.png
index 62df3fd..2915b57 100644
--- a/chrome/app/theme/default_100_percent/common/tab_active_center.png
+++ b/chrome/app/theme/default_100_percent/common/tab_active_center.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/tab_recording_mask.png b/chrome/app/theme/default_100_percent/common/tab_recording_mask.png
index d576327..2fed3f5 100644
--- a/chrome/app/theme/default_100_percent/common/tab_recording_mask.png
+++ b/chrome/app/theme/default_100_percent/common/tab_recording_mask.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/update_failed.png b/chrome/app/theme/default_100_percent/common/update_failed.png
index 1e47a46..582dee8 100644
--- a/chrome/app/theme/default_100_percent/common/update_failed.png
+++ b/chrome/app/theme/default_100_percent/common/update_failed.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/update_uptodate.png b/chrome/app/theme/default_100_percent/common/update_uptodate.png
index f0e2c61..db26297 100644
--- a/chrome/app/theme/default_100_percent/common/update_uptodate.png
+++ b/chrome/app/theme/default_100_percent/common/update_uptodate.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/credit_card_cvc_hint.png b/chrome/app/theme/default_100_percent/credit_card_cvc_hint.png
index b0a73c5..684709a 100644
--- a/chrome/app/theme/default_100_percent/credit_card_cvc_hint.png
+++ b/chrome/app/theme/default_100_percent/credit_card_cvc_hint.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/cros/file_types/folder.png b/chrome/app/theme/default_100_percent/cros/file_types/folder.png
index b529bd0..97509bd 100644
--- a/chrome/app/theme/default_100_percent/cros/file_types/folder.png
+++ b/chrome/app/theme/default_100_percent/cros/file_types/folder.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/cros/file_types/thumbnails/folder.png b/chrome/app/theme/default_100_percent/cros/file_types/thumbnails/folder.png
index 1777930..52b8e2b 100644
--- a/chrome/app/theme/default_100_percent/cros/file_types/thumbnails/folder.png
+++ b/chrome/app/theme/default_100_percent/cros/file_types/thumbnails/folder.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/cros/file_types/thumbnails/generic.png b/chrome/app/theme/default_100_percent/cros/file_types/thumbnails/generic.png
index 1192d60..0dc005f 100644
--- a/chrome/app/theme/default_100_percent/cros/file_types/thumbnails/generic.png
+++ b/chrome/app/theme/default_100_percent/cros/file_types/thumbnails/generic.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/cros/file_types/thumbnails/video.png b/chrome/app/theme/default_100_percent/cros/file_types/thumbnails/video.png
index 59c4046..4dcff67 100644
--- a/chrome/app/theme/default_100_percent/cros/file_types/thumbnails/video.png
+++ b/chrome/app/theme/default_100_percent/cros/file_types/thumbnails/video.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/cros/managed_mode_icon.png b/chrome/app/theme/default_100_percent/cros/managed_mode_icon.png
index b38f8f5..9ec4e7d 100644
--- a/chrome/app/theme/default_100_percent/cros/managed_mode_icon.png
+++ b/chrome/app/theme/default_100_percent/cros/managed_mode_icon.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/cros/network_hide_password.png b/chrome/app/theme/default_100_percent/cros/network_hide_password.png
index 3bc3a49..0134510 100644
--- a/chrome/app/theme/default_100_percent/cros/network_hide_password.png
+++ b/chrome/app/theme/default_100_percent/cros/network_hide_password.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/cros/network_hide_password_hover.png b/chrome/app/theme/default_100_percent/cros/network_hide_password_hover.png
index d31d678..b0ba542 100644
--- a/chrome/app/theme/default_100_percent/cros/network_hide_password_hover.png
+++ b/chrome/app/theme/default_100_percent/cros/network_hide_password_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/cros/network_show_password.png b/chrome/app/theme/default_100_percent/cros/network_show_password.png
index 43592d9..b9cd69e 100644
--- a/chrome/app/theme/default_100_percent/cros/network_show_password.png
+++ b/chrome/app/theme/default_100_percent/cros/network_show_password.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/cros/network_show_password_hover.png b/chrome/app/theme/default_100_percent/cros/network_show_password_hover.png
index 4024f32..f9a65b7 100644
--- a/chrome/app/theme/default_100_percent/cros/network_show_password_hover.png
+++ b/chrome/app/theme/default_100_percent/cros/network_show_password_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/cros/notification_peripheral_battery_low.png b/chrome/app/theme/default_100_percent/cros/notification_peripheral_battery_low.png
index 50d289a..67d366c 100644
--- a/chrome/app/theme/default_100_percent/cros/notification_peripheral_battery_low.png
+++ b/chrome/app/theme/default_100_percent/cros/notification_peripheral_battery_low.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/cros/supervised_illsutration_done.png b/chrome/app/theme/default_100_percent/cros/supervised_illsutration_done.png
new file mode 100644
index 0000000..19ac2b4
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/cros/supervised_illsutration_done.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/cros/supervised_illustration_start.png b/chrome/app/theme/default_100_percent/cros/supervised_illustration_start.png
new file mode 100644
index 0000000..c8f10be
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/cros/supervised_illustration_start.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/cros/technical_error.png b/chrome/app/theme/default_100_percent/cros/technical_error.png
new file mode 100644
index 0000000..df0ba11
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/cros/technical_error.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/cros/theme_frame_active.png b/chrome/app/theme/default_100_percent/cros/theme_frame_active.png
index 63aacba..00186f2 100644
--- a/chrome/app/theme/default_100_percent/cros/theme_frame_active.png
+++ b/chrome/app/theme/default_100_percent/cros/theme_frame_active.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/cros/theme_frame_inactive.png b/chrome/app/theme/default_100_percent/cros/theme_frame_inactive.png
index f3f8a7c..997ed29 100644
--- a/chrome/app/theme/default_100_percent/cros/theme_frame_inactive.png
+++ b/chrome/app/theme/default_100_percent/cros/theme_frame_inactive.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/cros/theme_frame_incognito_active.png b/chrome/app/theme/default_100_percent/cros/theme_frame_incognito_active.png
index 1d50b92..be88fc3 100644
--- a/chrome/app/theme/default_100_percent/cros/theme_frame_incognito_active.png
+++ b/chrome/app/theme/default_100_percent/cros/theme_frame_incognito_active.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/cros/theme_frame_incognito_inactive.png b/chrome/app/theme/default_100_percent/cros/theme_frame_incognito_inactive.png
index efd2018..ae1b534 100644
--- a/chrome/app/theme/default_100_percent/cros/theme_frame_incognito_inactive.png
+++ b/chrome/app/theme/default_100_percent/cros/theme_frame_incognito_inactive.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/icon_add_user24.png b/chrome/app/theme/default_100_percent/icon_add_user24.png
index 15c06c9..f8edc5d 100644
--- a/chrome/app/theme/default_100_percent/icon_add_user24.png
+++ b/chrome/app/theme/default_100_percent/icon_add_user24.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobar_insecure.png b/chrome/app/theme/default_100_percent/infobar_insecure.png
deleted file mode 100644
index c8fbccd..0000000
--- a/chrome/app/theme/default_100_percent/infobar_insecure.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobar_warning.png b/chrome/app/theme/default_100_percent/infobar_warning.png
deleted file mode 100644
index c8fbccd..0000000
--- a/chrome/app/theme/default_100_percent/infobar_warning.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/managed_user.png b/chrome/app/theme/default_100_percent/managed_user.png
index e2ab494..48eddb2 100644
--- a/chrome/app/theme/default_100_percent/managed_user.png
+++ b/chrome/app/theme/default_100_percent/managed_user.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/screen_capture_notification_grip.png b/chrome/app/theme/default_100_percent/screen_capture_notification_grip.png
new file mode 100644
index 0000000..3e1c828
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/screen_capture_notification_grip.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/settings_app_icon_128.png b/chrome/app/theme/default_100_percent/settings_app_icon_128.png
index 18cfcd7..5526907 100644
--- a/chrome/app/theme/default_100_percent/settings_app_icon_128.png
+++ b/chrome/app/theme/default_100_percent/settings_app_icon_128.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/tab_recording.png b/chrome/app/theme/default_100_percent/tab_recording.png
index 8472157..a722411 100644
--- a/chrome/app/theme/default_100_percent/tab_recording.png
+++ b/chrome/app/theme/default_100_percent/tab_recording.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/tools.png b/chrome/app/theme/default_100_percent/tools.png
index 159e632..60c2316 100644
--- a/chrome/app/theme/default_100_percent/tools.png
+++ b/chrome/app/theme/default_100_percent/tools.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/wallet.png b/chrome/app/theme/default_100_percent/wallet.png
index 62d46eb..882f8c4 100644
--- a/chrome/app/theme/default_100_percent/wallet.png
+++ b/chrome/app/theme/default_100_percent/wallet.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/webrtc_macosx_webcam.png b/chrome/app/theme/default_100_percent/webrtc_macosx_webcam.png
index ffcfcf6..6f06b66 100644
--- a/chrome/app/theme/default_100_percent/webrtc_macosx_webcam.png
+++ b/chrome/app/theme/default_100_percent/webrtc_macosx_webcam.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/website_settings_tab_left2.png b/chrome/app/theme/default_100_percent/website_settings_tab_left2.png
index 06217da..f05e8fd 100644
--- a/chrome/app/theme/default_100_percent/website_settings_tab_left2.png
+++ b/chrome/app/theme/default_100_percent/website_settings_tab_left2.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/app_window_close.png b/chrome/app/theme/default_100_percent/win/app_window_close.png
index f6a80c0..4987710 100644
--- a/chrome/app/theme/default_100_percent/win/app_window_close.png
+++ b/chrome/app/theme/default_100_percent/win/app_window_close.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/app_window_close_active.png b/chrome/app/theme/default_100_percent/win/app_window_close_active.png
index 95052e9..fea8179 100644
--- a/chrome/app/theme/default_100_percent/win/app_window_close_active.png
+++ b/chrome/app/theme/default_100_percent/win/app_window_close_active.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/app_window_close_hover.png b/chrome/app/theme/default_100_percent/win/app_window_close_hover.png
index e1a461f..f3615d0 100644
--- a/chrome/app/theme/default_100_percent/win/app_window_close_hover.png
+++ b/chrome/app/theme/default_100_percent/win/app_window_close_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/app_window_close_unfocused.png b/chrome/app/theme/default_100_percent/win/app_window_close_unfocused.png
index 3d99de6..e36a8c8 100644
--- a/chrome/app/theme/default_100_percent/win/app_window_close_unfocused.png
+++ b/chrome/app/theme/default_100_percent/win/app_window_close_unfocused.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/app_window_maximize.png b/chrome/app/theme/default_100_percent/win/app_window_maximize.png
index cc33d24..ce5c5c1 100644
--- a/chrome/app/theme/default_100_percent/win/app_window_maximize.png
+++ b/chrome/app/theme/default_100_percent/win/app_window_maximize.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/app_window_maximize_disabled.png b/chrome/app/theme/default_100_percent/win/app_window_maximize_disabled.png
index fb15e05..f490708 100644
--- a/chrome/app/theme/default_100_percent/win/app_window_maximize_disabled.png
+++ b/chrome/app/theme/default_100_percent/win/app_window_maximize_disabled.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/app_window_restore_active.png b/chrome/app/theme/default_100_percent/win/app_window_restore_active.png
index 56ddfc3..56c4e72 100644
--- a/chrome/app/theme/default_100_percent/win/app_window_restore_active.png
+++ b/chrome/app/theme/default_100_percent/win/app_window_restore_active.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/app_window_restore_hover.png b/chrome/app/theme/default_100_percent/win/app_window_restore_hover.png
index 39d0eb2..8d396fc 100644
--- a/chrome/app/theme/default_100_percent/win/app_window_restore_hover.png
+++ b/chrome/app/theme/default_100_percent/win/app_window_restore_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/notification_tray_empty.png b/chrome/app/theme/default_100_percent/win/notification_tray_empty.png
index 19313c7..bdb2be9 100644
--- a/chrome/app/theme/default_100_percent/win/notification_tray_empty.png
+++ b/chrome/app/theme/default_100_percent/win/notification_tray_empty.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/notification_tray_numbers.png b/chrome/app/theme/default_100_percent/win/notification_tray_numbers.png
index 20df53c..45ea409 100644
--- a/chrome/app/theme/default_100_percent/win/notification_tray_numbers.png
+++ b/chrome/app/theme/default_100_percent/win/notification_tray_numbers.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/zoom_minus.png b/chrome/app/theme/default_100_percent/zoom_minus.png
index 4c58ffe..8a72755 100644
--- a/chrome/app/theme/default_100_percent/zoom_minus.png
+++ b/chrome/app/theme/default_100_percent/zoom_minus.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/zoom_plus.png b/chrome/app/theme/default_100_percent/zoom_plus.png
index 73b726f..da56efb 100644
--- a/chrome/app/theme/default_100_percent/zoom_plus.png
+++ b/chrome/app/theme/default_100_percent/zoom_plus.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/zoom_reset.png b/chrome/app/theme/default_100_percent/zoom_reset.png
index 45a9559..06deb9a 100644
--- a/chrome/app/theme/default_100_percent/zoom_reset.png
+++ b/chrome/app/theme/default_100_percent/zoom_reset.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/allowed_mic_only.png b/chrome/app/theme/default_200_percent/allowed_mic_only.png
deleted file mode 100644
index b5dda545..0000000
--- a/chrome/app/theme/default_200_percent/allowed_mic_only.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/app_list_tab_overlay.png b/chrome/app/theme/default_200_percent/app_list_tab_overlay.png
index ee0ce21..1fc54a7 100644
--- a/chrome/app/theme/default_200_percent/app_list_tab_overlay.png
+++ b/chrome/app/theme/default_200_percent/app_list_tab_overlay.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/autofill_dialog_menu_button_disabled.png b/chrome/app/theme/default_200_percent/autofill_dialog_menu_button_disabled.png
index e508b5b..6d85d8d 100644
--- a/chrome/app/theme/default_200_percent/autofill_dialog_menu_button_disabled.png
+++ b/chrome/app/theme/default_200_percent/autofill_dialog_menu_button_disabled.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/autofill_dialog_menu_button_hover.png b/chrome/app/theme/default_200_percent/autofill_dialog_menu_button_hover.png
index 11335a9..cbedeff 100644
--- a/chrome/app/theme/default_200_percent/autofill_dialog_menu_button_hover.png
+++ b/chrome/app/theme/default_200_percent/autofill_dialog_menu_button_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/autofill_dialog_menu_button_normal.png b/chrome/app/theme/default_200_percent/autofill_dialog_menu_button_normal.png
index 05467c4..8bc3607 100644
--- a/chrome/app/theme/default_200_percent/autofill_dialog_menu_button_normal.png
+++ b/chrome/app/theme/default_200_percent/autofill_dialog_menu_button_normal.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/autofill_dialog_menu_button_pressed.png b/chrome/app/theme/default_200_percent/autofill_dialog_menu_button_pressed.png
index 26c5478..0ecaf2e 100644
--- a/chrome/app/theme/default_200_percent/autofill_dialog_menu_button_pressed.png
+++ b/chrome/app/theme/default_200_percent/autofill_dialog_menu_button_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/blocked_cookies.png b/chrome/app/theme/default_200_percent/blocked_cookies.png
deleted file mode 100644
index acdb997..0000000
--- a/chrome/app/theme/default_200_percent/blocked_cookies.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/blocked_images.png b/chrome/app/theme/default_200_percent/blocked_images.png
deleted file mode 100644
index 0749c19..0000000
--- a/chrome/app/theme/default_200_percent/blocked_images.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/blocked_mic_only.png b/chrome/app/theme/default_200_percent/blocked_mic_only.png
deleted file mode 100644
index b369a98..0000000
--- a/chrome/app/theme/default_200_percent/blocked_mic_only.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/blocked_mixed_content.png b/chrome/app/theme/default_200_percent/blocked_mixed_content.png
deleted file mode 100644
index 4cfc135..0000000
--- a/chrome/app/theme/default_200_percent/blocked_mixed_content.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/blocked_plugins.png b/chrome/app/theme/default_200_percent/blocked_plugins.png
deleted file mode 100644
index 38df82f..0000000
--- a/chrome/app/theme/default_200_percent/blocked_plugins.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/blocked_popups.png b/chrome/app/theme/default_200_percent/blocked_popups.png
deleted file mode 100644
index ff8ab86..0000000
--- a/chrome/app/theme/default_200_percent/blocked_popups.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/blocked_script.png b/chrome/app/theme/default_200_percent/blocked_script.png
deleted file mode 100644
index 5e037be..0000000
--- a/chrome/app/theme/default_200_percent/blocked_script.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/chromium/product_logo_name_48.png b/chrome/app/theme/default_200_percent/chromium/product_logo_name_48.png
new file mode 100644
index 0000000..79c2200
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/chromium/product_logo_name_48.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/action_box_button_hover.png b/chrome/app/theme/default_200_percent/common/action_box_button_hover.png
index 7a1ed2f..bb1f380 100644
--- a/chrome/app/theme/default_200_percent/common/action_box_button_hover.png
+++ b/chrome/app/theme/default_200_percent/common/action_box_button_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/action_box_button_normal.png b/chrome/app/theme/default_200_percent/common/action_box_button_normal.png
index a8e5453..f351037 100644
--- a/chrome/app/theme/default_200_percent/common/action_box_button_normal.png
+++ b/chrome/app/theme/default_200_percent/common/action_box_button_normal.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/action_box_button_pressed.png b/chrome/app/theme/default_200_percent/common/action_box_button_pressed.png
index 86aef9f..8b5be81 100644
--- a/chrome/app/theme/default_200_percent/common/action_box_button_pressed.png
+++ b/chrome/app/theme/default_200_percent/common/action_box_button_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/allowed_downloads.png b/chrome/app/theme/default_200_percent/common/allowed_downloads.png
new file mode 100644
index 0000000..95191cd
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/allowed_downloads.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/allowed_fullscreen.png b/chrome/app/theme/default_200_percent/common/allowed_fullscreen.png
similarity index 100%
rename from chrome/app/theme/default_200_percent/allowed_fullscreen.png
rename to chrome/app/theme/default_200_percent/common/allowed_fullscreen.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/allowed_images.png b/chrome/app/theme/default_200_percent/common/allowed_images.png
similarity index 100%
rename from chrome/app/theme/default_200_percent/allowed_images.png
rename to chrome/app/theme/default_200_percent/common/allowed_images.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/allowed_location.png b/chrome/app/theme/default_200_percent/common/allowed_location.png
similarity index 100%
rename from chrome/app/theme/default_200_percent/allowed_location.png
rename to chrome/app/theme/default_200_percent/common/allowed_location.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/allowed_mic_only.png b/chrome/app/theme/default_200_percent/common/allowed_mic_only.png
new file mode 100644
index 0000000..ea21269
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/allowed_mic_only.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/allowed_mouse_cursor.png b/chrome/app/theme/default_200_percent/common/allowed_mouse_cursor.png
similarity index 100%
rename from chrome/app/theme/default_200_percent/allowed_mouse_cursor.png
rename to chrome/app/theme/default_200_percent/common/allowed_mouse_cursor.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/allowed_notifications.png b/chrome/app/theme/default_200_percent/common/allowed_notifications.png
similarity index 100%
rename from chrome/app/theme/default_200_percent/allowed_notifications.png
rename to chrome/app/theme/default_200_percent/common/allowed_notifications.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/allowed_plugins.png b/chrome/app/theme/default_200_percent/common/allowed_plugins.png
similarity index 100%
rename from chrome/app/theme/default_200_percent/allowed_plugins.png
rename to chrome/app/theme/default_200_percent/common/allowed_plugins.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/allowed_popups.png b/chrome/app/theme/default_200_percent/common/allowed_popups.png
similarity index 100%
rename from chrome/app/theme/default_200_percent/allowed_popups.png
rename to chrome/app/theme/default_200_percent/common/allowed_popups.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/allowed_script.png b/chrome/app/theme/default_200_percent/common/allowed_script.png
similarity index 100%
rename from chrome/app/theme/default_200_percent/allowed_script.png
rename to chrome/app/theme/default_200_percent/common/allowed_script.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/app_list_v1_overlay.png b/chrome/app/theme/default_200_percent/common/app_list_v1_overlay.png
index 5dbb5af..83f65da 100644
--- a/chrome/app/theme/default_200_percent/common/app_list_v1_overlay.png
+++ b/chrome/app/theme/default_200_percent/common/app_list_v1_overlay.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/apps_bookmark_bar_icon.png b/chrome/app/theme/default_200_percent/common/apps_bookmark_bar_icon.png
index e46e522..6569f70 100644
--- a/chrome/app/theme/default_200_percent/common/apps_bookmark_bar_icon.png
+++ b/chrome/app/theme/default_200_percent/common/apps_bookmark_bar_icon.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/audio_equalizer_column.png b/chrome/app/theme/default_200_percent/common/audio_equalizer_column.png
index 4e8d2df..cd3af2b 100644
--- a/chrome/app/theme/default_200_percent/common/audio_equalizer_column.png
+++ b/chrome/app/theme/default_200_percent/common/audio_equalizer_column.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/blocked_downloads.png b/chrome/app/theme/default_200_percent/common/blocked_downloads.png
new file mode 100644
index 0000000..71c1a00
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/blocked_downloads.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/blocked_fullscreen.png b/chrome/app/theme/default_200_percent/common/blocked_fullscreen.png
similarity index 100%
rename from chrome/app/theme/default_200_percent/blocked_fullscreen.png
rename to chrome/app/theme/default_200_percent/common/blocked_fullscreen.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/blocked_location.png b/chrome/app/theme/default_200_percent/common/blocked_location.png
similarity index 100%
rename from chrome/app/theme/default_200_percent/blocked_location.png
rename to chrome/app/theme/default_200_percent/common/blocked_location.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/blocked_media.png b/chrome/app/theme/default_200_percent/common/blocked_media.png
similarity index 100%
rename from chrome/app/theme/default_200_percent/blocked_media.png
rename to chrome/app/theme/default_200_percent/common/blocked_media.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/blocked_mic_only.png b/chrome/app/theme/default_200_percent/common/blocked_mic_only.png
new file mode 100644
index 0000000..f81858c
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/blocked_mic_only.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/blocked_mouse_cursor.png b/chrome/app/theme/default_200_percent/common/blocked_mouse_cursor.png
similarity index 100%
rename from chrome/app/theme/default_200_percent/blocked_mouse_cursor.png
rename to chrome/app/theme/default_200_percent/common/blocked_mouse_cursor.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/blocked_notifications.png b/chrome/app/theme/default_200_percent/common/blocked_notifications.png
similarity index 100%
rename from chrome/app/theme/default_200_percent/blocked_notifications.png
rename to chrome/app/theme/default_200_percent/common/blocked_notifications.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/pepper_broker.png b/chrome/app/theme/default_200_percent/common/blocked_pepper_broker.png
similarity index 100%
rename from chrome/app/theme/default_200_percent/pepper_broker.png
rename to chrome/app/theme/default_200_percent/common/blocked_pepper_broker.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/browser_action_pressed.png b/chrome/app/theme/default_200_percent/common/browser_action_pressed.png
index 8b4e57d..61f460d 100644
--- a/chrome/app/theme/default_200_percent/common/browser_action_pressed.png
+++ b/chrome/app/theme/default_200_percent/common/browser_action_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/browser_actions_overflow_normal.png b/chrome/app/theme/default_200_percent/common/browser_actions_overflow_normal.png
index b2c3bc4..7adf02f 100644
--- a/chrome/app/theme/default_200_percent/common/browser_actions_overflow_normal.png
+++ b/chrome/app/theme/default_200_percent/common/browser_actions_overflow_normal.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/browser_back_hover.png b/chrome/app/theme/default_200_percent/common/browser_back_hover.png
index 5800299..d51b318 100644
--- a/chrome/app/theme/default_200_percent/common/browser_back_hover.png
+++ b/chrome/app/theme/default_200_percent/common/browser_back_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/browser_back_pressed.png b/chrome/app/theme/default_200_percent/common/browser_back_pressed.png
index 645e119..20e6698 100644
--- a/chrome/app/theme/default_200_percent/common/browser_back_pressed.png
+++ b/chrome/app/theme/default_200_percent/common/browser_back_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/browser_forward_hover.png b/chrome/app/theme/default_200_percent/common/browser_forward_hover.png
index a672fe1..d0a10ae 100644
--- a/chrome/app/theme/default_200_percent/common/browser_forward_hover.png
+++ b/chrome/app/theme/default_200_percent/common/browser_forward_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/browser_home_hover.png b/chrome/app/theme/default_200_percent/common/browser_home_hover.png
index 254e14b..1a4be77 100644
--- a/chrome/app/theme/default_200_percent/common/browser_home_hover.png
+++ b/chrome/app/theme/default_200_percent/common/browser_home_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/browser_home_pressed.png b/chrome/app/theme/default_200_percent/common/browser_home_pressed.png
index ce765b5..3e18760 100644
--- a/chrome/app/theme/default_200_percent/common/browser_home_pressed.png
+++ b/chrome/app/theme/default_200_percent/common/browser_home_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/browser_reload_hover.png b/chrome/app/theme/default_200_percent/common/browser_reload_hover.png
index d1bf76e..8a0d79b 100644
--- a/chrome/app/theme/default_200_percent/common/browser_reload_hover.png
+++ b/chrome/app/theme/default_200_percent/common/browser_reload_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/browser_stop_hover.png b/chrome/app/theme/default_200_percent/common/browser_stop_hover.png
index cd31302..736f172 100644
--- a/chrome/app/theme/default_200_percent/common/browser_stop_hover.png
+++ b/chrome/app/theme/default_200_percent/common/browser_stop_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/browser_toolbar_bezel_hover.png b/chrome/app/theme/default_200_percent/common/browser_toolbar_bezel_hover.png
index 4ac4d85..df79bdc 100644
--- a/chrome/app/theme/default_200_percent/common/browser_toolbar_bezel_hover.png
+++ b/chrome/app/theme/default_200_percent/common/browser_toolbar_bezel_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/browser_toolbar_bezel_pressed.png b/chrome/app/theme/default_200_percent/common/browser_toolbar_bezel_pressed.png
index 4136878..61f460d 100644
--- a/chrome/app/theme/default_200_percent/common/browser_toolbar_bezel_pressed.png
+++ b/chrome/app/theme/default_200_percent/common/browser_toolbar_bezel_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/browser_tools_badge_ash.png b/chrome/app/theme/default_200_percent/common/browser_tools_badge_ash.png
index bf8c23b..1078549 100644
--- a/chrome/app/theme/default_200_percent/common/browser_tools_badge_ash.png
+++ b/chrome/app/theme/default_200_percent/common/browser_tools_badge_ash.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/browser_tools_bar.png b/chrome/app/theme/default_200_percent/common/browser_tools_bar.png
index e50acfc..3c0c0a9 100644
--- a/chrome/app/theme/default_200_percent/common/browser_tools_bar.png
+++ b/chrome/app/theme/default_200_percent/common/browser_tools_bar.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/browser_tools_hover.png b/chrome/app/theme/default_200_percent/common/browser_tools_hover.png
index 57f1e6a..091a2a7 100644
--- a/chrome/app/theme/default_200_percent/common/browser_tools_hover.png
+++ b/chrome/app/theme/default_200_percent/common/browser_tools_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/browser_tools_pressed.png b/chrome/app/theme/default_200_percent/common/browser_tools_pressed.png
index 4c7ac3c..f6302b5 100644
--- a/chrome/app/theme/default_200_percent/common/browser_tools_pressed.png
+++ b/chrome/app/theme/default_200_percent/common/browser_tools_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/cws_star_half.png b/chrome/app/theme/default_200_percent/common/cws_star_half.png
index 9f49c3c..6a7cb6f 100644
--- a/chrome/app/theme/default_200_percent/common/cws_star_half.png
+++ b/chrome/app/theme/default_200_percent/common/cws_star_half.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/discard_wide.png b/chrome/app/theme/default_200_percent/common/discard_wide.png
index c024fa8..666351a 100644
--- a/chrome/app/theme/default_200_percent/common/discard_wide.png
+++ b/chrome/app/theme/default_200_percent/common/discard_wide.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/download_button_center_bottom.png b/chrome/app/theme/default_200_percent/common/download_button_center_bottom.png
index c4db14a..2e4ec42 100644
--- a/chrome/app/theme/default_200_percent/common/download_button_center_bottom.png
+++ b/chrome/app/theme/default_200_percent/common/download_button_center_bottom.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/download_button_center_bottom_hover.png b/chrome/app/theme/default_200_percent/common/download_button_center_bottom_hover.png
index 04b9549..e90556f 100644
--- a/chrome/app/theme/default_200_percent/common/download_button_center_bottom_hover.png
+++ b/chrome/app/theme/default_200_percent/common/download_button_center_bottom_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/download_button_center_top_hover.png b/chrome/app/theme/default_200_percent/common/download_button_center_top_hover.png
index d449aa2..b637558 100644
--- a/chrome/app/theme/default_200_percent/common/download_button_center_top_hover.png
+++ b/chrome/app/theme/default_200_percent/common/download_button_center_top_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/download_button_left_bottom_pressed.png b/chrome/app/theme/default_200_percent/common/download_button_left_bottom_pressed.png
index 0143a46..f1088cf 100644
--- a/chrome/app/theme/default_200_percent/common/download_button_left_bottom_pressed.png
+++ b/chrome/app/theme/default_200_percent/common/download_button_left_bottom_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/download_button_left_middle.png b/chrome/app/theme/default_200_percent/common/download_button_left_middle.png
index d2dd138..2e6a48a 100644
--- a/chrome/app/theme/default_200_percent/common/download_button_left_middle.png
+++ b/chrome/app/theme/default_200_percent/common/download_button_left_middle.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/download_button_menu_bottom_pressed.png b/chrome/app/theme/default_200_percent/common/download_button_menu_bottom_pressed.png
index 628820e..5d67139 100644
--- a/chrome/app/theme/default_200_percent/common/download_button_menu_bottom_pressed.png
+++ b/chrome/app/theme/default_200_percent/common/download_button_menu_bottom_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/download_button_menu_top_pressed.png b/chrome/app/theme/default_200_percent/common/download_button_menu_top_pressed.png
index bb6db22..7f043a3 100644
--- a/chrome/app/theme/default_200_percent/common/download_button_menu_top_pressed.png
+++ b/chrome/app/theme/default_200_percent/common/download_button_menu_top_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/download_button_right_bottom.png b/chrome/app/theme/default_200_percent/common/download_button_right_bottom.png
index e75d497..5129018 100644
--- a/chrome/app/theme/default_200_percent/common/download_button_right_bottom.png
+++ b/chrome/app/theme/default_200_percent/common/download_button_right_bottom.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/download_button_right_bottom_hover.png b/chrome/app/theme/default_200_percent/common/download_button_right_bottom_hover.png
index 97c963a..5a5681a 100644
--- a/chrome/app/theme/default_200_percent/common/download_button_right_bottom_hover.png
+++ b/chrome/app/theme/default_200_percent/common/download_button_right_bottom_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/download_button_right_bottom_pressed.png b/chrome/app/theme/default_200_percent/common/download_button_right_bottom_pressed.png
index 06fe6d8..a23edb4 100644
--- a/chrome/app/theme/default_200_percent/common/download_button_right_bottom_pressed.png
+++ b/chrome/app/theme/default_200_percent/common/download_button_right_bottom_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/download_button_right_top.png b/chrome/app/theme/default_200_percent/common/download_button_right_top.png
index 9896426..2e467d0 100644
--- a/chrome/app/theme/default_200_percent/common/download_button_right_top.png
+++ b/chrome/app/theme/default_200_percent/common/download_button_right_top.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/download_button_right_top_hover.png b/chrome/app/theme/default_200_percent/common/download_button_right_top_hover.png
index d5659bd..0585f40 100644
--- a/chrome/app/theme/default_200_percent/common/download_button_right_top_hover.png
+++ b/chrome/app/theme/default_200_percent/common/download_button_right_top_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/download_button_right_top_no_dd.png b/chrome/app/theme/default_200_percent/common/download_button_right_top_no_dd.png
index 2d2c34e..adff1d1 100644
--- a/chrome/app/theme/default_200_percent/common/download_button_right_top_no_dd.png
+++ b/chrome/app/theme/default_200_percent/common/download_button_right_top_no_dd.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/download_button_right_top_pressed.png b/chrome/app/theme/default_200_percent/common/download_button_right_top_pressed.png
index 0db15db..4399b53 100644
--- a/chrome/app/theme/default_200_percent/common/download_button_right_top_pressed.png
+++ b/chrome/app/theme/default_200_percent/common/download_button_right_top_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/error_managed_mode_blocked_page.png b/chrome/app/theme/default_200_percent/common/error_managed_mode_blocked_page.png
index 1ab3d44..274d872 100644
--- a/chrome/app/theme/default_200_percent/common/error_managed_mode_blocked_page.png
+++ b/chrome/app/theme/default_200_percent/common/error_managed_mode_blocked_page.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/error_network_generic.png b/chrome/app/theme/default_200_percent/common/error_network_generic.png
index 1741040..0d72086 100644
--- a/chrome/app/theme/default_200_percent/common/error_network_generic.png
+++ b/chrome/app/theme/default_200_percent/common/error_network_generic.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/favicon_bookmarks.png b/chrome/app/theme/default_200_percent/common/favicon_bookmarks.png
index 524dd10..7abe310 100644
--- a/chrome/app/theme/default_200_percent/common/favicon_bookmarks.png
+++ b/chrome/app/theme/default_200_percent/common/favicon_bookmarks.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/favicon_downloads.png b/chrome/app/theme/default_200_percent/common/favicon_downloads.png
index 752b314..4a795e6 100644
--- a/chrome/app/theme/default_200_percent/common/favicon_downloads.png
+++ b/chrome/app/theme/default_200_percent/common/favicon_downloads.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/favicon_extensions.png b/chrome/app/theme/default_200_percent/common/favicon_extensions.png
index 67a0e5f..8b0f9e9 100644
--- a/chrome/app/theme/default_200_percent/common/favicon_extensions.png
+++ b/chrome/app/theme/default_200_percent/common/favicon_extensions.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/favicon_settings.png b/chrome/app/theme/default_200_percent/common/favicon_settings.png
index 863272f..6ff8aab 100644
--- a/chrome/app/theme/default_200_percent/common/favicon_settings.png
+++ b/chrome/app/theme/default_200_percent/common/favicon_settings.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/find_box_bg.png b/chrome/app/theme/default_200_percent/common/find_box_bg.png
index b3336c0..e7ea397 100644
--- a/chrome/app/theme/default_200_percent/common/find_box_bg.png
+++ b/chrome/app/theme/default_200_percent/common/find_box_bg.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/infobar_insecure.png b/chrome/app/theme/default_200_percent/common/infobar_insecure.png
deleted file mode 100644
index aa8335d..0000000
--- a/chrome/app/theme/default_200_percent/common/infobar_insecure.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/input_alert.png b/chrome/app/theme/default_200_percent/common/input_alert.png
index 7055e0a..8bf24fc 100644
--- a/chrome/app/theme/default_200_percent/common/input_alert.png
+++ b/chrome/app/theme/default_200_percent/common/input_alert.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/input_alert_menu.png b/chrome/app/theme/default_200_percent/common/input_alert_menu.png
index 6f2c9cc..56dac17 100644
--- a/chrome/app/theme/default_200_percent/common/input_alert_menu.png
+++ b/chrome/app/theme/default_200_percent/common/input_alert_menu.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/input_good.png b/chrome/app/theme/default_200_percent/common/input_good.png
index 06d38bb..8b23b52 100644
--- a/chrome/app/theme/default_200_percent/common/input_good.png
+++ b/chrome/app/theme/default_200_percent/common/input_good.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/limited_user.png b/chrome/app/theme/default_200_percent/common/limited_user.png
index d1e8f93..6f12c30 100644
--- a/chrome/app/theme/default_200_percent/common/limited_user.png
+++ b/chrome/app/theme/default_200_percent/common/limited_user.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/managed_user_theme/label_bg_bottom.png b/chrome/app/theme/default_200_percent/common/managed_user_theme/label_bg_bottom.png
new file mode 100644
index 0000000..f3811b7
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/managed_user_theme/label_bg_bottom.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/managed_user_theme/label_bg_bottom_left.png b/chrome/app/theme/default_200_percent/common/managed_user_theme/label_bg_bottom_left.png
new file mode 100644
index 0000000..a2a3d06
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/managed_user_theme/label_bg_bottom_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/managed_user_theme/label_bg_bottom_right.png b/chrome/app/theme/default_200_percent/common/managed_user_theme/label_bg_bottom_right.png
new file mode 100644
index 0000000..4c42bd9
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/managed_user_theme/label_bg_bottom_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/managed_user_theme/label_bg_center.png b/chrome/app/theme/default_200_percent/common/managed_user_theme/label_bg_center.png
new file mode 100644
index 0000000..7208905
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/managed_user_theme/label_bg_center.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/managed_user_theme/label_bg_left.png b/chrome/app/theme/default_200_percent/common/managed_user_theme/label_bg_left.png
new file mode 100644
index 0000000..3e81416
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/managed_user_theme/label_bg_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/managed_user_theme/label_bg_right.png b/chrome/app/theme/default_200_percent/common/managed_user_theme/label_bg_right.png
new file mode 100644
index 0000000..c7ccf29
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/managed_user_theme/label_bg_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/managed_user_theme/label_bg_top.png b/chrome/app/theme/default_200_percent/common/managed_user_theme/label_bg_top.png
new file mode 100644
index 0000000..057479f
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/managed_user_theme/label_bg_top.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/managed_user_theme/label_bg_top_left.png b/chrome/app/theme/default_200_percent/common/managed_user_theme/label_bg_top_left.png
new file mode 100644
index 0000000..b1691f2
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/managed_user_theme/label_bg_top_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/managed_user_theme/label_bg_top_right.png b/chrome/app/theme/default_200_percent/common/managed_user_theme/label_bg_top_right.png
new file mode 100644
index 0000000..a4b5727
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/managed_user_theme/label_bg_top_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/managed_user_theme/theme_frame_supervised.png b/chrome/app/theme/default_200_percent/common/managed_user_theme/theme_frame_supervised.png
new file mode 100644
index 0000000..2a617c2
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/managed_user_theme/theme_frame_supervised.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/managed_user_theme/theme_frame_supervised_inactive.png b/chrome/app/theme/default_200_percent/common/managed_user_theme/theme_frame_supervised_inactive.png
new file mode 100644
index 0000000..1fed54d
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/managed_user_theme/theme_frame_supervised_inactive.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/managed_user_theme/theme_tab_background_supervised.png b/chrome/app/theme/default_200_percent/common/managed_user_theme/theme_tab_background_supervised.png
new file mode 100644
index 0000000..35d97b8
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/managed_user_theme/theme_tab_background_supervised.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/nub.png b/chrome/app/theme/default_200_percent/common/nub.png
index 6983f07..bd19d76 100644
--- a/chrome/app/theme/default_200_percent/common/nub.png
+++ b/chrome/app/theme/default_200_percent/common/nub.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/omnibox_https_policy_warning.png b/chrome/app/theme/default_200_percent/common/omnibox_https_policy_warning.png
index e9d7818..b6b75f2 100644
--- a/chrome/app/theme/default_200_percent/common/omnibox_https_policy_warning.png
+++ b/chrome/app/theme/default_200_percent/common/omnibox_https_policy_warning.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/omnibox_mic_search.png b/chrome/app/theme/default_200_percent/common/omnibox_mic_search.png
new file mode 100644
index 0000000..31ea0fd
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/omnibox_mic_search.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/payment_checkmark.png b/chrome/app/theme/default_200_percent/common/payment_checkmark.png
new file mode 100644
index 0000000..012c5fb
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/payment_checkmark.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/tab_inactive_center.png b/chrome/app/theme/default_200_percent/common/tab_inactive_center.png
index 06ab023..5baf17a 100644
--- a/chrome/app/theme/default_200_percent/common/tab_inactive_center.png
+++ b/chrome/app/theme/default_200_percent/common/tab_inactive_center.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/tab_recording_mask.png b/chrome/app/theme/default_200_percent/common/tab_recording_mask.png
index 7a8059d..c04537d 100644
--- a/chrome/app/theme/default_200_percent/common/tab_recording_mask.png
+++ b/chrome/app/theme/default_200_percent/common/tab_recording_mask.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/update_failed.png b/chrome/app/theme/default_200_percent/common/update_failed.png
index ddead51..5a46ab6 100644
--- a/chrome/app/theme/default_200_percent/common/update_failed.png
+++ b/chrome/app/theme/default_200_percent/common/update_failed.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/update_menu_severity_high.png b/chrome/app/theme/default_200_percent/common/update_menu_severity_high.png
index 30b4257..248f46a 100644
--- a/chrome/app/theme/default_200_percent/common/update_menu_severity_high.png
+++ b/chrome/app/theme/default_200_percent/common/update_menu_severity_high.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/update_menu_severity_low.png b/chrome/app/theme/default_200_percent/common/update_menu_severity_low.png
index ace746f..2374b69 100644
--- a/chrome/app/theme/default_200_percent/common/update_menu_severity_low.png
+++ b/chrome/app/theme/default_200_percent/common/update_menu_severity_low.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/update_menu_severity_medium.png b/chrome/app/theme/default_200_percent/common/update_menu_severity_medium.png
index b2997f0..10c14f4 100644
--- a/chrome/app/theme/default_200_percent/common/update_menu_severity_medium.png
+++ b/chrome/app/theme/default_200_percent/common/update_menu_severity_medium.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/update_uptodate.png b/chrome/app/theme/default_200_percent/common/update_uptodate.png
index eaad969..ad8ace8 100644
--- a/chrome/app/theme/default_200_percent/common/update_uptodate.png
+++ b/chrome/app/theme/default_200_percent/common/update_uptodate.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/cros/fatal_error.png b/chrome/app/theme/default_200_percent/cros/fatal_error.png
index a22c432..6340771 100644
--- a/chrome/app/theme/default_200_percent/cros/fatal_error.png
+++ b/chrome/app/theme/default_200_percent/cros/fatal_error.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/cros/file_types/archive.png b/chrome/app/theme/default_200_percent/cros/file_types/archive.png
index 000d91d..fd567ec 100644
--- a/chrome/app/theme/default_200_percent/cros/file_types/archive.png
+++ b/chrome/app/theme/default_200_percent/cros/file_types/archive.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/cros/managed_mode_icon.png b/chrome/app/theme/default_200_percent/cros/managed_mode_icon.png
index 02066e5..6f12c30 100644
--- a/chrome/app/theme/default_200_percent/cros/managed_mode_icon.png
+++ b/chrome/app/theme/default_200_percent/cros/managed_mode_icon.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/cros/notification_peripheral_battery_low.png b/chrome/app/theme/default_200_percent/cros/notification_peripheral_battery_low.png
index be63b0f..19d64a1 100644
--- a/chrome/app/theme/default_200_percent/cros/notification_peripheral_battery_low.png
+++ b/chrome/app/theme/default_200_percent/cros/notification_peripheral_battery_low.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/cros/supervised_illsutration_done.png b/chrome/app/theme/default_200_percent/cros/supervised_illsutration_done.png
new file mode 100644
index 0000000..78e32b6
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/cros/supervised_illsutration_done.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/cros/supervised_illustration_start.png b/chrome/app/theme/default_200_percent/cros/supervised_illustration_start.png
new file mode 100644
index 0000000..212a8ee
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/cros/supervised_illustration_start.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/cros/technical_error.png b/chrome/app/theme/default_200_percent/cros/technical_error.png
new file mode 100644
index 0000000..e4d118b
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/cros/technical_error.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/cws_star_half.png b/chrome/app/theme/default_200_percent/cws_star_half.png
index 9f49c3c..6a7cb6f 100644
--- a/chrome/app/theme/default_200_percent/cws_star_half.png
+++ b/chrome/app/theme/default_200_percent/cws_star_half.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/discard_wide.png b/chrome/app/theme/default_200_percent/discard_wide.png
index c024fa8..666351a 100644
--- a/chrome/app/theme/default_200_percent/discard_wide.png
+++ b/chrome/app/theme/default_200_percent/discard_wide.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/infobar_insecure.png b/chrome/app/theme/default_200_percent/infobar_insecure.png
deleted file mode 100644
index aa8335d..0000000
--- a/chrome/app/theme/default_200_percent/infobar_insecure.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/infobar_warning.png b/chrome/app/theme/default_200_percent/infobar_warning.png
deleted file mode 100644
index aa8335d..0000000
--- a/chrome/app/theme/default_200_percent/infobar_warning.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/managed_user.png b/chrome/app/theme/default_200_percent/managed_user.png
index 2826f94..e1cf8d8 100644
--- a/chrome/app/theme/default_200_percent/managed_user.png
+++ b/chrome/app/theme/default_200_percent/managed_user.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/panel_minimize.png b/chrome/app/theme/default_200_percent/panel_minimize.png
index 04a7206..4d710d7 100644
--- a/chrome/app/theme/default_200_percent/panel_minimize.png
+++ b/chrome/app/theme/default_200_percent/panel_minimize.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/panel_restore.png b/chrome/app/theme/default_200_percent/panel_restore.png
index 3b80ae3..b8b7a08 100644
--- a/chrome/app/theme/default_200_percent/panel_restore.png
+++ b/chrome/app/theme/default_200_percent/panel_restore.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/screen_capture_notification_grip.png b/chrome/app/theme/default_200_percent/screen_capture_notification_grip.png
new file mode 100644
index 0000000..a2ceea3
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/screen_capture_notification_grip.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/settings_app_icon_48.png b/chrome/app/theme/default_200_percent/settings_app_icon_48.png
index 15c14cf..55b6726 100644
--- a/chrome/app/theme/default_200_percent/settings_app_icon_48.png
+++ b/chrome/app/theme/default_200_percent/settings_app_icon_48.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/tab_capture.png b/chrome/app/theme/default_200_percent/tab_capture.png
index 18b9854..e7f397b 100644
--- a/chrome/app/theme/default_200_percent/tab_capture.png
+++ b/chrome/app/theme/default_200_percent/tab_capture.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/tab_recording.png b/chrome/app/theme/default_200_percent/tab_recording.png
index 9f9dc13..13cdf2f 100644
--- a/chrome/app/theme/default_200_percent/tab_recording.png
+++ b/chrome/app/theme/default_200_percent/tab_recording.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/tools_hover.png b/chrome/app/theme/default_200_percent/tools_hover.png
index e3a134d..22cfcb2 100644
--- a/chrome/app/theme/default_200_percent/tools_hover.png
+++ b/chrome/app/theme/default_200_percent/tools_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/website_settings_tab_center2.png b/chrome/app/theme/default_200_percent/website_settings_tab_center2.png
index ebe4a49..071daef 100644
--- a/chrome/app/theme/default_200_percent/website_settings_tab_center2.png
+++ b/chrome/app/theme/default_200_percent/website_settings_tab_center2.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/zoom_minus.png b/chrome/app/theme/default_200_percent/zoom_minus.png
index 0c32da8..bc9e6de 100644
--- a/chrome/app/theme/default_200_percent/zoom_minus.png
+++ b/chrome/app/theme/default_200_percent/zoom_minus.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/zoom_plus.png b/chrome/app/theme/default_200_percent/zoom_plus.png
index 8926cda..5c46a0d 100644
--- a/chrome/app/theme/default_200_percent/zoom_plus.png
+++ b/chrome/app/theme/default_200_percent/zoom_plus.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/zoom_reset.png b/chrome/app/theme/default_200_percent/zoom_reset.png
index b9f7393..c25b103 100644
--- a/chrome/app/theme/default_200_percent/zoom_reset.png
+++ b/chrome/app/theme/default_200_percent/zoom_reset.png
Binary files differ
diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd
index ec9a0ad..e48a7b0 100644
--- a/chrome/app/theme/theme_resources.grd
+++ b/chrome/app/theme/theme_resources.grd
@@ -31,15 +31,15 @@
       <structure type="chrome_scaled_image" name="IDR_ACTION_BOX_BUTTON_HOVER" file="common/action_box_button_hover.png" />
       <structure type="chrome_scaled_image" name="IDR_ACTION_BOX_BUTTON_NORMAL" file="common/action_box_button_normal.png" />
       <structure type="chrome_scaled_image" name="IDR_ACTION_BOX_BUTTON_PRESSED" file="common/action_box_button_pressed.png" />
-      <structure type="chrome_scaled_image" name="IDR_ALLOWED_FULLSCREEN" file="allowed_fullscreen.png" />
-      <structure type="chrome_scaled_image" name="IDR_ALLOWED_IMAGES" file="allowed_images.png" />
-      <structure type="chrome_scaled_image" name="IDR_ALLOWED_LOCATION" file="allowed_location.png" />
-      <structure type="chrome_scaled_image" name="IDR_ALLOWED_MICROPHONE" file="allowed_mic_only.png" />
-      <structure type="chrome_scaled_image" name="IDR_ALLOWED_MOUSE_CURSOR" file="allowed_mouse_cursor.png" />
-      <structure type="chrome_scaled_image" name="IDR_ALLOWED_NOTIFICATION" file="allowed_notifications.png" />
-      <structure type="chrome_scaled_image" name="IDR_ALLOWED_POPUPS" file="allowed_popups.png" />
-      <structure type="chrome_scaled_image" name="IDR_ALLOWED_PLUGINS" file="allowed_plugins.png" />
-      <structure type="chrome_scaled_image" name="IDR_ALLOWED_JAVASCRIPT" file="allowed_script.png" />
+      <structure type="chrome_scaled_image" name="IDR_ALLOWED_FULLSCREEN" file="common/allowed_fullscreen.png" />
+      <structure type="chrome_scaled_image" name="IDR_ALLOWED_IMAGES" file="common/allowed_images.png" />
+      <structure type="chrome_scaled_image" name="IDR_ALLOWED_LOCATION" file="common/allowed_location.png" />
+      <structure type="chrome_scaled_image" name="IDR_ALLOWED_MICROPHONE" file="common/allowed_mic_only.png" />
+      <structure type="chrome_scaled_image" name="IDR_ALLOWED_MOUSE_CURSOR" file="common/allowed_mouse_cursor.png" />
+      <structure type="chrome_scaled_image" name="IDR_ALLOWED_NOTIFICATION" file="common/allowed_notifications.png" />
+      <structure type="chrome_scaled_image" name="IDR_ALLOWED_PLUGINS" file="common/allowed_plugins.png" />
+      <structure type="chrome_scaled_image" name="IDR_ALLOWED_POPUPS" file="common/allowed_popups.png" />
+      <structure type="chrome_scaled_image" name="IDR_ALLOWED_JAVASCRIPT" file="common/allowed_script.png" />
       <structure type="chrome_scaled_image" name="IDR_APP_DEFAULT_ICON" file="app_default_icon.png" />
       <structure type="chrome_scaled_image" name="IDR_APP_DROPARROW" file="app_droparrow.png" />
       <if expr="pp_ifdef('enable_app_list') and is_win and not pp_ifdef('_google_chrome')">
@@ -91,19 +91,19 @@
       <structure type="chrome_scaled_image" name="IDR_BALLOON_WRENCH" file="notification_wrench.png" />
       <structure type="chrome_scaled_image" name="IDR_BALLOON_WRENCH_H" file="notification_wrench_hover.png" />
       <structure type="chrome_scaled_image" name="IDR_BALLOON_WRENCH_P" file="notification_wrench_pressed.png" />
-      <structure type="chrome_scaled_image" name="IDR_BLOCKED_COOKIES" file="blocked_cookies.png" />
-      <structure type="chrome_scaled_image" name="IDR_BLOCKED_FULLSCREEN" file="blocked_fullscreen.png" />
-      <structure type="chrome_scaled_image" name="IDR_BLOCKED_IMAGES" file="blocked_images.png" />
-      <structure type="chrome_scaled_image" name="IDR_BLOCKED_JAVASCRIPT" file="blocked_script.png" />
-      <structure type="chrome_scaled_image" name="IDR_BLOCKED_LOCATION" file="blocked_location.png" />
-      <structure type="chrome_scaled_image" name="IDR_BLOCKED_MEDIA" file="blocked_media.png" />
-      <structure type="chrome_scaled_image" name="IDR_BLOCKED_MICROPHONE" file="blocked_mic_only.png" />
-      <structure type="chrome_scaled_image" name="IDR_BLOCKED_MOUSE_CURSOR" file="blocked_mouse_cursor.png" />
-      <structure type="chrome_scaled_image" name="IDR_BLOCKED_MIXED_CONTENT" file="blocked_mixed_content.png" />
-      <structure type="chrome_scaled_image" name="IDR_BLOCKED_NOTIFICATION" file="blocked_notifications.png" />
-      <structure type="chrome_scaled_image" name="IDR_BLOCKED_PLUGINS" file="blocked_plugins.png" />
-      <structure type="chrome_scaled_image" name="IDR_BLOCKED_POPUPS" file="blocked_popups.png" />
-      <structure type="chrome_scaled_image" name="IDR_BLOCKED_PPAPI_BROKER" file="pepper_broker.png" />
+      <structure type="chrome_scaled_image" name="IDR_BLOCKED_COOKIES" file="common/blocked_cookies.png" />
+      <structure type="chrome_scaled_image" name="IDR_BLOCKED_FULLSCREEN" file="common/blocked_fullscreen.png" />
+      <structure type="chrome_scaled_image" name="IDR_BLOCKED_IMAGES" file="common/blocked_images.png" />
+      <structure type="chrome_scaled_image" name="IDR_BLOCKED_JAVASCRIPT" file="common/blocked_script.png" />
+      <structure type="chrome_scaled_image" name="IDR_BLOCKED_LOCATION" file="common/blocked_location.png" />
+      <structure type="chrome_scaled_image" name="IDR_BLOCKED_MEDIA" file="common/blocked_media.png" />
+      <structure type="chrome_scaled_image" name="IDR_BLOCKED_MICROPHONE" file="common/blocked_mic_only.png" />
+      <structure type="chrome_scaled_image" name="IDR_BLOCKED_MOUSE_CURSOR" file="common/blocked_mouse_cursor.png" />
+      <structure type="chrome_scaled_image" name="IDR_BLOCKED_MIXED_CONTENT" file="common/blocked_mixed_content.png" />
+      <structure type="chrome_scaled_image" name="IDR_BLOCKED_NOTIFICATION" file="common/blocked_notifications.png" />
+      <structure type="chrome_scaled_image" name="IDR_BLOCKED_PLUGINS" file="common/blocked_plugins.png" />
+      <structure type="chrome_scaled_image" name="IDR_BLOCKED_POPUPS" file="common/blocked_popups.png" />
+      <structure type="chrome_scaled_image" name="IDR_BLOCKED_PPAPI_BROKER" file="common/blocked_pepper_broker.png" />
       <structure type="chrome_scaled_image" name="IDR_BOOKMARKS_FAVICON" file="common/favicon_bookmarks.png" />
       <structure type="chrome_scaled_image" name="IDR_BOOKMARK_BAR_CHEVRONS" file="common/chevron.png" />
       <if expr="is_macosx">
@@ -399,9 +399,9 @@
       <structure type="chrome_scaled_image" name="IDR_INFOBAR_PLUGIN_INSTALL" file="infobar_plugin.png" />
       <structure type="chrome_scaled_image" name="IDR_INFOBAR_RESTORE_SESSION" file="infobar_restore.png" />
       <structure type="chrome_scaled_image" name="IDR_INFOBAR_SAVE_PASSWORD" file="infobar_savepassword.png" />
-      <structure type="chrome_scaled_image" name="IDR_INFOBAR_SSL_WARNING" file="infobar_insecure.png" />
       <structure type="chrome_scaled_image" name="IDR_INFOBAR_THEME" file="infobar_theme.png" />
       <structure type="chrome_scaled_image" name="IDR_INFOBAR_TRANSLATE" file="infobar_translate.png" />
+      <structure type="chrome_scaled_image" name="IDR_INFOBAR_WARNING" file="common/infobar_warning.png" />
       <structure type="chrome_scaled_image" name="IDR_INPUT_ALERT" file="common/input_alert.png" />
       <structure type="chrome_scaled_image" name="IDR_INPUT_ALERT_MENU" file="common/input_alert_menu.png" />
       <structure type="chrome_scaled_image" name="IDR_INPUT_GOOD" file="common/input_good.png" />
@@ -453,6 +453,9 @@
         <structure type="chrome_scaled_image" name="IDR_MANAGED_MODE_ICON" file="cros/managed_mode_icon.png" />
       </if>
       <structure type="chrome_scaled_image" name="IDR_MANAGED_USER_ICON" file="common/limited_user.png" />
+      <structure type="chrome_scaled_image" name="IDR_MANAGED_USER_THEME_FRAME" file="common/managed_user_theme/theme_frame_supervised.png" />
+      <structure type="chrome_scaled_image" name="IDR_MANAGED_USER_THEME_FRAME_INACTIVE" file="common/managed_user_theme/theme_frame_supervised_inactive.png" />
+      <structure type="chrome_scaled_image" name="IDR_MANAGED_USER_THEME_TAB_BACKGROUND" file="common/managed_user_theme/theme_tab_background_supervised.png" />
       <structure type="chrome_scaled_image" name="IDR_MAXIMIZE_BUTTON_MASK" file="maximize_button_mask.png" />
       <structure type="chrome_scaled_image" name="IDR_MINIMIZE_BUTTON_MASK" file="minimize_button_mask.png" />
       <if expr="pp_ifdef('chromeos')">
@@ -547,6 +550,7 @@
       <if expr="not is_macosx">
         <structure type="chrome_scaled_image" name="IDR_OMNIBOX_KEYWORD_HINT_TAB" file="common/omnibox_keyword_hint_tab.png" />
       </if>
+      <structure type="chrome_scaled_image" name="IDR_OMNIBOX_MIC_SEARCH" file="common/omnibox_mic_search.png" />
       <structure type="chrome_scaled_image" name="IDR_OMNIBOX_PDF_ICON" file="pdf.png" />
       <structure type="chrome_scaled_image" name="IDR_OMNIBOX_POPUP_BORDER_BOTTOM" file="common/omnibox_popup_border_bottom.png" />
       <structure type="chrome_scaled_image" name="IDR_OMNIBOX_POPUP_BORDER_BOTTOM_LEFT" file="common/omnibox_popup_border_bottom_left.png" />
@@ -622,6 +626,7 @@
         <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_16" file="chromium/product_logo_16.png" />
         <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_26" file="chromium/product_logo_26.png" />
         <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_32" file="chromium/product_logo_32.png" />
+        <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_NAME_48" file="chromium/product_logo_name_48.png" />
         <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_WHITE" file="chromium/product_logo_white.png" />
       </if>
       <if expr="pp_ifdef('_google_chrome')">
@@ -629,6 +634,7 @@
         <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_16" file="google_chrome/product_logo_16.png" />
         <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_26" file="google_chrome/product_logo_26.png" />
         <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_32" file="google_chrome/product_logo_32.png" />
+        <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_NAME_48" file="google_chrome/product_logo_name_48.png" />
         <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_WHITE" file="google_chrome/product_logo_white.png" />
       </if>
       <if expr="is_macosx">
@@ -710,6 +716,7 @@
       <structure type="chrome_scaled_image" name="IDR_SAD_FAVICON" file="common/favicon_sad_tab.png" />
       <structure type="chrome_scaled_image" name="IDR_SAD_TAB" file="sadtab.png" />
       <structure type="chrome_scaled_image" name="IDR_SAFEBROWSING_WARNING" file="safebrowsing_warning.png" />
+      <structure type="chrome_scaled_image" name="IDR_SCREEN_CAPTURE_NOTIFICATION_GRIP" file="screen_capture_notification_grip.png" />
       <structure type="chrome_scaled_image" name="IDR_SCREENSHOT_NOTIFICATION_ICON" file="common/notification_screenshot_icon.png" />
       <structure type="chrome_scaled_image" name="IDR_SCRIPT_BUBBLE" file="common/favicon_extensions.png" />
       <if expr="pp_ifdef('enable_settings_app')">
@@ -754,6 +761,10 @@
         <structure type="chrome_scaled_image" name="IDR_STOP_H" file="common/browser_stop_hover.png" />
         <structure type="chrome_scaled_image" name="IDR_STOP_P" file="common/browser_stop_pressed.png" />
       </if>
+      <if expr="pp_ifdef('chromeos')">
+        <structure type="chrome_scaled_image" name="IDR_SUPERVISED_ILLUSTRATION_START" file="cros/supervised_illustration_start.png" />
+        <structure type="chrome_scaled_image" name="IDR_SUPERVISED_ILLUSTRATION_DONE" file="cros/supervised_illsutration_done.png" />
+      </if>
       <if expr="not pp_ifdef('toolkit_views') and not is_macosx">
         <structure type="chrome_scaled_image" name="IDR_TAB_ACTIVE_CENTER" file="tab_active_center.png" />
         <structure type="chrome_scaled_image" name="IDR_TAB_ACTIVE_LEFT" file="tab_active_left.png" />
@@ -809,6 +820,9 @@
         <structure type="chrome_scaled_image" name="IDR_TAB_INACTIVE_RIGHT" file="mac/tab_inactive_right.png" />
       </if>
       <structure type="chrome_scaled_image" name="IDR_TABLET_FAVICON" file="common/favicon_tablet.png" />
+      <if expr="pp_ifdef('chromeos')">
+        <structure type="chrome_scaled_image" name="IDR_TECHNICAL_ERROR" file="cros/technical_error.png" />
+      </if>
       <structure type="chrome_scaled_image" name="IDR_THEME_BUTTON_BACKGROUND" file="notused.png" />
       <if expr="not pp_ifdef('use_ash')">
         <structure type="chrome_scaled_image" name="IDR_THEME_FRAME" file="theme_frame.png" />
@@ -930,6 +944,7 @@
         <structure type="chrome_scaled_image" name="IDR_USER_IMAGE_RECYCLE" file="discard_wide.png" />
       </if>
       <structure type="chrome_scaled_image" name="IDR_WALLET_ICON" file="wallet.png" />
+      <structure type="chrome_scaled_image" name="IDR_WALLET_STEP_CHECK" file="common/payment_checkmark.png" />
       <structure type="chrome_scaled_image" name="IDR_WARNING" file="alert_small.png" />
       <structure type="chrome_scaled_image" name="IDR_WEB_INTENT_PROGRESS_BACKGROUND" file="common/web_intent_progress_background.png" />
       <structure type="chrome_scaled_image" name="IDR_WEB_INTENT_PROGRESS_FOREGROUND" file="common/web_intent_progress_foreground.png" />
diff --git a/chrome/app/theme/touch_100_percent/common/omnibox_mic_search.png b/chrome/app/theme/touch_100_percent/common/omnibox_mic_search.png
new file mode 100644
index 0000000..74bd7eb
--- /dev/null
+++ b/chrome/app/theme/touch_100_percent/common/omnibox_mic_search.png
Binary files differ
diff --git a/chrome/app/theme/touch_100_percent/infobar_insecure.png b/chrome/app/theme/touch_100_percent/infobar_insecure.png
deleted file mode 100644
index 01238f8..0000000
--- a/chrome/app/theme/touch_100_percent/infobar_insecure.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/touch_140_percent/common/omnibox_mic_search.png b/chrome/app/theme/touch_140_percent/common/omnibox_mic_search.png
new file mode 100644
index 0000000..8e2a323
--- /dev/null
+++ b/chrome/app/theme/touch_140_percent/common/omnibox_mic_search.png
Binary files differ
diff --git a/chrome/app/theme/touch_180_percent/common/omnibox_mic_search.png b/chrome/app/theme/touch_180_percent/common/omnibox_mic_search.png
new file mode 100644
index 0000000..9d47e4c
--- /dev/null
+++ b/chrome/app/theme/touch_180_percent/common/omnibox_mic_search.png
Binary files differ
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS
index b9c6a71..632d192 100644
--- a/chrome/browser/DEPS
+++ b/chrome/browser/DEPS
@@ -5,12 +5,12 @@
   "+chrome/installer",
   "+chrome/tools/profiles",  # For history unit tests.
   "+chromeos",
-  "+components/autofill/browser",
   "+components/autofill/content/browser",
+  "+components/autofill/core/browser",
   "+components/autofill/core/common",
   "+components/auto_login_parser",
-  "+components/breakpad",
   "+components/browser_context_keyed_service",
+  "+components/nacl/common",
   "+components/navigation_interception",
   "+components/user_prefs",
   "+components/visitedlink/browser",
@@ -52,9 +52,6 @@
   # TODO(stuartmorgan): Remove these by refactoring necessary code out of
   # webkit/. See crbug.com/146251
   # DO NOT ADD ANY MORE ITEMS TO THE LIST BELOW!
-  "+webkit/base/origin_url_conversions.h",
-  "+webkit/common/cursors/webcursor.h",
-  "+webkit/dom_storage/dom_storage_types.h",
   "+webkit/plugins",  # Defines some types that are marshalled over IPC.
 
   # TODO(kinuko): Remove all other webkit/* dependencies after we cleaned
@@ -62,12 +59,14 @@
   "+webkit/browser",
   "+webkit/common",
 
+  # TODO(ananta): remove me when
+  # bug https://code.google.com/p/chromium/issues/detail?id=237249 is fixed.
+  "!content/public/child/image_decoder_utils.h",
+
   # webkit/glue files are listed individually since they aren't conceptually
   # grouped like the other webkit/ files, and can therefore be tackled one at
   # a time.
-  "+webkit/glue/image_decoder.h",
   "+webkit/glue/resource_type.h",
-  "+webkit/glue/webkit_glue.h",
   # DO NOT ADD ANY MORE ITEMS TO THE ABOVE LIST!
 
   "-chrome/browser/ui/views",
@@ -89,4 +88,32 @@
   "+third_party/re2",
   "+third_party/sqlite",
   "+third_party/undoview",
+
+  # No inclusion of WebKit from the browser, other than strictly enum/POD,
+  # header-only types, and some selected common code.
+  "-third_party/WebKit",
+  "+third_party/WebKit/public/platform/WebCString.h",
+  "+third_party/WebKit/public/platform/WebRect.h",
+  "+third_party/WebKit/public/platform/WebReferrerPolicy.h",
+  "+third_party/WebKit/public/platform/WebScreenInfo.h",
+  "+third_party/WebKit/public/platform/WebString.h",
+  "+third_party/WebKit/public/platform/WebURL.h",
+  "+third_party/WebKit/public/web/WebAutofillClient.h",
+  "+third_party/WebKit/public/web/WebCache.h",
+  "+third_party/WebKit/public/web/WebContextMenuData.h",
+  "+third_party/WebKit/public/web/WebCursorInfo.h",
+  "+third_party/WebKit/public/web/WebDevToolsAgent.h",
+  "+third_party/WebKit/public/web/WebFindOptions.h",
+  "+third_party/WebKit/public/web/WebInputEvent.h",
+  "+third_party/WebKit/public/web/WebMediaPlayerAction.h",
+  "+third_party/WebKit/public/web/WebNotificationPresenter.h",
+  "+third_party/WebKit/public/web/WebPluginAction.h",
+  "+third_party/WebKit/public/web/WebScreenInfo.h",
+  "+third_party/WebKit/public/web/WebTextDirection.h",
+
+  # These should be burned down. http://crbug.com/237267
+  "!third_party/WebKit/public/web/WebKit.h",
+  "!third_party/WebKit/public/web/WebSecurityOrigin.h",
+  "!third_party/WebKit/public/web/WebSecurityPolicy.h",
+  "!third_party/WebKit/public/web/WebView.h",
 ]
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 1479406..7099dbd 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -19,6 +19,7 @@
 #include "chrome/browser/flags_storage.h"
 #include "chrome/common/chrome_content_client.h"
 #include "chrome/common/chrome_switches.h"
+#include "components/nacl/common/nacl_switches.h"
 #include "content/public/browser/user_metrics.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
@@ -540,6 +541,13 @@
     SINGLE_VALUE_TYPE(switches::kExtensionsOnChromeURLs)
   },
   {
+    "enable-fast-unload",
+    IDS_FLAGS_ENABLE_FAST_UNLOAD_NAME,
+    IDS_FLAGS_ENABLE_FAST_UNLOAD_DESCRIPTION,
+    kOsAll,
+    SINGLE_VALUE_TYPE(switches::kEnableFastUnload)
+  },
+  {
     "enable-adview",
     IDS_FLAGS_ENABLE_ADVIEW_NAME,
     IDS_FLAGS_ENABLE_ADVIEW_DESCRIPTION,
@@ -554,6 +562,13 @@
     SINGLE_VALUE_TYPE(switches::kEnableAdviewSrcAttribute)
   },
   {
+    "enable-app-window-controls",
+    IDS_FLAGS_ENABLE_APP_WINDOW_CONTROLS_NAME,
+    IDS_FLAGS_ENABLE_APP_WINDOW_CONTROLS_DESCRIPTION,
+    kOsDesktop,
+    SINGLE_VALUE_TYPE(switches::kEnableAppWindowControls)
+  },
+  {
     "action-box",
     IDS_FLAGS_ACTION_BOX_NAME,
     IDS_FLAGS_ACTION_BOX_DESCRIPTION,
@@ -621,14 +636,6 @@
                               switches::kDisableLocalFirstLoadNTP)
   },
   {
-    "enable-local-only-instant-extended-api",
-    IDS_FLAGS_ENABLE_LOCAL_ONLY_INSTANT_EXTENDED_API,
-    IDS_FLAGS_ENABLE_LOCAL_ONLY_INSTANT_EXTENDED_API_DESCRIPTION,
-    kOsMac | kOsWin | kOsCrOS,
-    ENABLE_DISABLE_VALUE_TYPE(switches::kEnableLocalOnlyInstantExtendedAPI,
-                              switches::kDisableLocalOnlyInstantExtendedAPI)
-  },
-  {
     "static-ip-config",
     IDS_FLAGS_STATIC_IP_CONFIG_NAME,
     IDS_FLAGS_STATIC_IP_CONFIG_DESCRIPTION,
@@ -655,13 +662,6 @@
     SINGLE_VALUE_TYPE(switches::kEnableSyncFavicons)
   },
   {
-    "sync-keystore-encryption",
-    IDS_FLAGS_SYNC_KEYSTORE_ENCRYPTION_NAME,
-    IDS_FLAGS_SYNC_KEYSTORE_ENCRYPTION_DESCRIPTION,
-    kOsAll,
-    SINGLE_VALUE_TYPE(switches::kSyncKeystoreEncryption)
-  },
-  {
     "enable-gesture-tap-highlight",
     IDS_FLAGS_ENABLE_GESTURE_TAP_HIGHLIGHTING_NAME,
     IDS_FLAGS_ENABLE_GESTURE_TAP_HIGHLIGHTING_DESCRIPTION,
@@ -723,6 +723,13 @@
                               switches::kDisableQuic)
   },
   {
+    "enable-spdy4a2",
+    IDS_FLAGS_ENABLE_SPDY4A2_NAME,
+    IDS_FLAGS_ENABLE_SPDY4A2_DESCRIPTION,
+    kOsAll,
+    SINGLE_VALUE_TYPE(switches::kEnableSpdy4a2)
+  },
+  {
     "enable-async-dns",
     IDS_FLAGS_ENABLE_ASYNC_DNS_NAME,
     IDS_FLAGS_ENABLE_ASYNC_DNS_DESCRIPTION,
@@ -762,6 +769,13 @@
     SINGLE_VALUE_TYPE(switches::kDisableLegacyEncryptedMedia)
   },
   {
+    "override-encrypted-media-canplaytype",
+    IDS_FLAGS_ENCRYPTED_MEDIA_CANPLAYTYPE_OVERRIDE_NAME,
+    IDS_FLAGS_ENCRYPTED_MEDIA_CANPLAYTYPE_OVERRIDE_DESCRIPTION,
+    kOsMac | kOsWin,
+    SINGLE_VALUE_TYPE(switches::kOverrideEncryptedMediaCanPlayType)
+  },
+  {
     "enable-opus-playback",
     IDS_FLAGS_ENABLE_OPUS_PLAYBACK_NAME,
     IDS_FLAGS_ENABLE_OPUS_PLAYBACK_DESCRIPTION,
@@ -779,7 +793,7 @@
     "enable-managed-users",
     IDS_FLAGS_ENABLE_LOCALLY_MANAGED_USERS_NAME,
     IDS_FLAGS_ENABLE_LOCALLY_MANAGED_USERS_DESCRIPTION,
-    kOsMac | kOsWin | kOsLinux | kOsAndroid | kOsCrOSOwnerOnly,
+    kOsMac | kOsWin | kOsLinux | kOsCrOSOwnerOnly,
     SINGLE_VALUE_TYPE(switches::kEnableManagedUsers)
   },
 #if defined(USE_ASH)
@@ -903,6 +917,13 @@
     SINGLE_VALUE_TYPE(switches::kEnableSpellingAutoCorrect)
   },
   {
+    "enable-scroll-prediction",
+    IDS_FLAGS_ENABLE_SCROLL_PREDICTION_NAME,
+    IDS_FLAGS_ENABLE_SCROLL_PREDICTION_DESCRIPTION,
+    kOsDesktop,
+    SINGLE_VALUE_TYPE(switches::kEnableScrollPrediction)
+  },
+  {
     "touch-events",
     IDS_TOUCH_EVENTS_NAME,
     IDS_TOUCH_EVENTS_DESCRIPTION,
@@ -933,7 +954,7 @@
   },
 #if defined(OS_CHROMEOS)
   {
-      "ash-use-alt-shelf",
+      "ash-use-alternate-shelf",
       IDS_FLAGS_ALTERNATE_SHELF_LAYOUT_NAME,
       IDS_FLAGS_ALTERNATE_SHELF_LAYOUT_DESCRIPTION,
       kOsCrOS,
@@ -1079,11 +1100,18 @@
     SINGLE_VALUE_TYPE(ash::switches::kAshDisableNewLockAnimations),
   },
   {
-    "file-manager-no-checkboxes",
-    IDS_FLAGS_FILE_MANAGER_NO_CHECKBOXES_NAME,
-    IDS_FLAGS_FILE_MANAGER_NO_CHECKBOXES_DESCRIPTION,
+    "file-manager-show-checkboxes",
+    IDS_FLAGS_FILE_MANAGER_SHOW_CHECKBOXES_NAME,
+    IDS_FLAGS_FILE_MANAGER_SHOW_CHECKBOXES_DESCRIPTION,
     kOsCrOS,
-    SINGLE_VALUE_TYPE(chromeos::switches::kFileManagerNoCheckboxes)
+    SINGLE_VALUE_TYPE(chromeos::switches::kFileManagerShowCheckboxes)
+  },
+  {
+    "file-manager-enable-sharing",
+    IDS_FLAGS_FILE_MANAGER_ENABLE_SHARING_NAME,
+    IDS_FLAGS_FILE_MANAGER_ENABLE_SHARING_DESCRIPTION,
+    kOsCrOS,
+    SINGLE_VALUE_TYPE(chromeos::switches::kFileManagerEnableSharing)
   },
   {
     "disable-app-mode",
@@ -1243,6 +1271,14 @@
     SINGLE_VALUE_TYPE(switches::kEnablePasswordGeneration)
   },
   {
+    "enable-password-autofill-public-suffix-domain-matching",
+    IDS_FLAGS_ENABLE_PASSWORD_AUTOFILL_PUBLIC_SUFFIX_DOMAIN_MATCHING_NAME,
+    IDS_FLAGS_ENABLE_PASSWORD_AUTOFILL_PUBLIC_SUFFIX_DOMAIN_MATCHING_DESCRIPTION,
+    kOsAndroid,
+    SINGLE_VALUE_TYPE(
+        switches::kEnablePasswordAutofillPublicSuffixDomainMatching)
+  },
+  {
     "enable-deferred-image-decoding",
     IDS_FLAGS_ENABLE_DEFERRED_IMAGE_DECODING_NAME,
     IDS_FLAGS_ENABLE_DEFERRED_IMAGE_DECODING_DESCRIPTION,
@@ -1257,13 +1293,6 @@
     SINGLE_VALUE_TYPE(switches::kPerformanceMonitorGathering)
   },
   {
-    "disable-native-autofill-ui",
-    IDS_FLAGS_DISABLE_NATIVE_AUTOFILL_UI_NAME,
-    IDS_FLAGS_DISABLE_NATIVE_AUTOFILL_UI_DESCRIPTION,
-    kOsDesktop,
-    SINGLE_VALUE_TYPE(switches::kDisableNativeAutofillUi)
-  },
-  {
     "enable-experimental-form-filling",
     IDS_FLAGS_ENABLE_EXPERIMENTAL_FORM_FILLING_NAME,
     IDS_FLAGS_ENABLE_EXPERIMENTAL_FORM_FILLING_DESCRIPTION,
@@ -1317,7 +1346,7 @@
     "enable-rich-notifications",
     IDS_FLAGS_ENABLE_RICH_NOTIFICATIONS_NAME,
     IDS_FLAGS_ENABLE_RICH_NOTIFICATIONS_DESCRIPTION,
-    kOsWin | kOsCrOS | kOsMac,
+    kOsWin | kOsMac,
     ENABLE_DISABLE_VALUE_TYPE(
         message_center::switches::kEnableRichNotifications,
         message_center::switches::kDisableRichNotifications)
@@ -1445,13 +1474,6 @@
     SINGLE_VALUE_TYPE(switches::kEnableTcpFastOpen)
   },
   {
-    "enable-webp-in-accept-header",
-    IDS_FLAGS_ENABLE_WEBP_IN_ACCEPT_HEADER_NAME,
-    IDS_FLAGS_ENABLE_WEBP_IN_ACCEPT_HEADER_DESCRIPTION,
-    kOsAll,
-    SINGLE_VALUE_TYPE(switches::kEnableWebPInAcceptHeader)
-  },
-  {
     "apps-use-native-frame",
     IDS_FLAGS_ENABLE_NATIVE_FRAMES_FOR_APPS_NAME,
     IDS_FLAGS_ENABLE_NATIVE_FRAMES_FOR_APPS_DESCRIPTION,
@@ -1466,26 +1488,12 @@
     SINGLE_VALUE_TYPE(switches::kSyncfsEnableDirectoryOperation),
   },
   {
-    "enable-draggable-menu-button",
-    IDS_FLAGS_ENABLE_DRAGGABLE_MENU_BUTTON_NAME,
-    IDS_FLAGS_ENABLE_DRAGGABLE_MENU_BUTTON_DESCRIPTION,
-    kOsAndroid,
-    SINGLE_VALUE_TYPE(switches::kEnableDraggableMenuButton)
-  },
-  {
     "enable-reset-profile-settings",
     IDS_FLAGS_ENABLE_RESET_PROFILE_SETTINGS_NAME,
     IDS_FLAGS_ENABLE_RESET_PROFILE_SETTINGS_DESCRIPTION,
     kOsAll,
     SINGLE_VALUE_TYPE(switches::kEnableResetProfileSettings)
   },
-  {
-    "enable-device-discovery",
-    IDS_FLAGS_ENABLE_DEVICE_DISCOVERY_NAME,
-    IDS_FLAGS_ENABLE_DEVICE_DISCOVERY_DESCRIPTION,
-    kOsDesktop,
-    SINGLE_VALUE_TYPE(switches::kEnableDeviceDiscovery)
-  },
 #if defined(OS_MACOSX)
   {
     "enable-app-list-shim",
@@ -1572,6 +1580,36 @@
     kOsAll,
     SINGLE_VALUE_TYPE(switches::kEnableTranslateSettings)
   },
+  {
+    "enable-web-midi",
+    IDS_FLAGS_ENABLE_WEB_MIDI_NAME,
+    IDS_FLAGS_ENABLE_WEB_MIDI_DESCRIPTION,
+    kOsMac,
+    SINGLE_VALUE_TYPE(switches::kEnableWebMIDI)
+  },
+  {
+    "enable-new-profile-management",
+    IDS_FLAGS_ENABLE_NEW_PROFILE_MANAGEMENT_NAME,
+    IDS_FLAGS_ENABLE_NEW_PROFILE_MANAGEMENT_DESCRIPTION,
+    kOsWin,
+    SINGLE_VALUE_TYPE(switches::kNewProfileManagement)
+  },
+  {
+    "enable-gaia-profile-info",
+    IDS_FLAGS_ENABLE_GAIA_PROFILE_INFO_NAME,
+    IDS_FLAGS_ENABLE_GAIA_PROFILE_INFO_DESCRIPTION,
+    kOsMac | kOsWin,
+    SINGLE_VALUE_TYPE(switches::kGaiaProfileInfo)
+  },
+#if defined(OS_WIN)
+  {
+    "disable-app-launcher",
+    IDS_FLAGS_DISABLE_APP_LIST_NAME,
+    IDS_FLAGS_DISABLE_APP_LIST_DESCRIPTION,
+    kOsAll,
+    SINGLE_VALUE_TYPE(switches::kDisableAppList)
+  },
+#endif
 };
 
 const Experiment* experiments = kExperiments;
diff --git a/chrome/browser/android/OWNERS b/chrome/browser/android/OWNERS
index ac80525..29d0acf 100644
--- a/chrome/browser/android/OWNERS
+++ b/chrome/browser/android/OWNERS
@@ -1,5 +1,3 @@
 bulach@chromium.org
-jcivelli@chromium.org
-nileshagrawal@chromium.org
 tedchoc@chromium.org
 yfriedman@chromium.org
diff --git a/chrome/browser/android/chrome_jni_registrar.cc b/chrome/browser/android/chrome_jni_registrar.cc
index b388f5a..379c23d 100644
--- a/chrome/browser/android/chrome_jni_registrar.cc
+++ b/chrome/browser/android/chrome_jni_registrar.cc
@@ -10,7 +10,9 @@
 #include "chrome/browser/android/chrome_web_contents_delegate_android.h"
 #include "chrome/browser/android/content_view_util.h"
 #include "chrome/browser/android/dev_tools_server.h"
+#include "chrome/browser/android/favicon_helper.h"
 #include "chrome/browser/android/intent_helper.h"
+#include "chrome/browser/android/most_visited_sites.h"
 #include "chrome/browser/android/provider/chrome_browser_provider.h"
 #include "chrome/browser/android/tab_android.h"
 #include "chrome/browser/autofill/android/personal_data_manager_android.h"
@@ -28,7 +30,7 @@
 #include "chrome/browser/ui/android/ssl_client_certificate_request.h"
 #include "chrome/browser/ui/android/validation_message_bubble_android.h"
 #include "chrome/browser/ui/android/website_settings_popup_android.h"
-#include "components/autofill/browser/android/component_jni_registrar.h"
+#include "components/autofill/core/browser/android/component_jni_registrar.h"
 #include "components/navigation_interception/component_jni_registrar.h"
 #include "components/web_contents_delegate_android/component_jni_registrar.h"
 
@@ -59,9 +61,11 @@
     RegisterChromeWebContentsDelegateAndroid },
   { "ContentViewUtil", RegisterContentViewUtil },
   { "DevToolsServer", RegisterDevToolsServer },
+  { "FaviconHelper", FaviconHelper::RegisterFaviconHelper },
   { "IntentHelper", RegisterIntentHelper },
   { "JavascriptAppModalDialog",
     JavascriptAppModalDialogAndroid::RegisterJavascriptAppModalDialog },
+  { "MostVisitedSites", RegisterMostVisitedSites },
   { "NavigationPopup", NavigationPopup::RegisterNavigationPopup },
   { "PersonalDataManagerAndroid",
     autofill::PersonalDataManagerAndroid::Register },
@@ -84,5 +88,5 @@
                                arraysize(kChromeRegisteredMethods));
 }
 
-} // namespace android
-} // namespace chrome
+}  // namespace android
+}  // namespace chrome
diff --git a/chrome/browser/android/chrome_web_contents_delegate_android.h b/chrome/browser/android/chrome_web_contents_delegate_android.h
index dbfb535..d86c89f 100644
--- a/chrome/browser/android/chrome_web_contents_delegate_android.h
+++ b/chrome/browser/android/chrome_web_contents_delegate_android.h
@@ -8,7 +8,7 @@
 #include <jni.h>
 
 #include "base/files/file_path.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "components/web_contents_delegate_android/web_contents_delegate_android.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
diff --git a/chrome/browser/android/crash_dump_manager.cc b/chrome/browser/android/crash_dump_manager.cc
index 07e0881..6ee4e04 100644
--- a/chrome/browser/android/crash_dump_manager.cc
+++ b/chrome/browser/android/crash_dump_manager.cc
@@ -14,8 +14,8 @@
 #include "base/rand_util.h"
 #include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
+#include "chrome/common/chrome_paths.h"
 #include "chrome/common/descriptors_android.h"
-#include "components/breakpad/common/breakpad_paths.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/child_process_data.h"
 #include "content/public/browser/file_descriptor_info.h"
@@ -91,7 +91,7 @@
 
   if (file_size == 0) {
     // Empty minidump, this process did not crash. Just remove the file.
-    r = file_util::Delete(minidump_path, false);
+    r = base::Delete(minidump_path, false);
     DCHECK(r) << "Failed to delete temporary minidump file "
               << minidump_path.value();
     return;
@@ -100,7 +100,7 @@
   // We are dealing with a valid minidump. Copy it to the crash report
   // directory from where Java code will upload it later on.
   base::FilePath crash_dump_dir;
-  r = PathService::Get(breakpad::DIR_CRASH_DUMPS, &crash_dump_dir);
+  r = PathService::Get(chrome::DIR_CRASH_DUMPS, &crash_dump_dir);
   if (!r) {
     NOTREACHED() << "Failed to retrieve the crash dump directory.";
     return;
@@ -111,11 +111,11 @@
       base::StringPrintf("chromium-renderer-minidump-%016" PRIx64 ".dmp%d",
                          rand, pid);
   base::FilePath dest_path = crash_dump_dir.Append(filename);
-  r = file_util::Move(minidump_path, dest_path);
+  r = base::Move(minidump_path, dest_path);
   if (!r) {
     LOG(ERROR) << "Failed to move crash dump from " << minidump_path.value()
                << " to " << dest_path.value();
-    file_util::Delete(minidump_path, false);
+    base::Delete(minidump_path, false);
     return;
   }
   LOG(INFO) << "Crash minidump successfully generated: " <<
diff --git a/chrome/browser/android/dev_tools_server.cc b/chrome/browser/android/dev_tools_server.cc
index 8602490..d7f9617 100644
--- a/chrome/browser/android/dev_tools_server.cc
+++ b/chrome/browser/android/dev_tools_server.cc
@@ -16,11 +16,11 @@
 #include "base/logging.h"
 #include "base/strings/stringprintf.h"
 #include "chrome/browser/browser_process.h"
+#include "chrome/browser/devtools/devtools_adb_bridge.h"
 #include "chrome/browser/history/top_sites.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/android/tab_model/tab_model.h"
 #include "chrome/browser/ui/android/tab_model/tab_model_list.h"
-#include "chrome/common/chrome_version_info.h"
 #include "content/public/browser/android/devtools_auth.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/devtools_http_handler.h"
@@ -33,21 +33,21 @@
 #include "net/socket/unix_domain_socket_posix.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "ui/base/resource/resource_bundle.h"
+#include "webkit/common/user_agent/user_agent_util.h"
 
 namespace {
 
 const char kFrontEndURL[] =
-    "http://chrome-devtools-frontend.appspot.com/static/%s/devtools.html";
-const char kDefaultSocketName[] = "chrome_devtools_remote";
+    "http://chrome-devtools-frontend.appspot.com/serve_rev/%s/devtools.html";
+const char kDefaultSocketNamePrefix[] = "chrome";
 const char kTetheringSocketName[] = "chrome_devtools_tethering_%d_%d";
 
 // Delegate implementation for the devtools http handler on android. A new
 // instance of this gets created each time devtools is enabled.
 class DevToolsServerDelegate : public content::DevToolsHttpHandlerDelegate {
  public:
-  explicit DevToolsServerDelegate(bool use_bundled_frontend_resources)
-      : use_bundled_frontend_resources_(use_bundled_frontend_resources),
-        last_tethering_socket_(0) {
+  DevToolsServerDelegate()
+      : last_tethering_socket_(0) {
   }
 
   virtual std::string GetDiscoveryPageHTML() OVERRIDE {
@@ -62,7 +62,7 @@
   }
 
   virtual bool BundlesFrontendResources() OVERRIDE {
-    return use_bundled_frontend_resources_;
+    return false;
   }
 
   virtual base::FilePath GetDebugFrontendDir() OVERRIDE {
@@ -124,7 +124,6 @@
       top_sites->SyncWithHistory();
   }
 
-  bool use_bundled_frontend_resources_;
   int last_tethering_socket_;
 
   DISALLOW_COPY_AND_ASSIGN(DevToolsServerDelegate);
@@ -133,8 +132,8 @@
 }  // namespace
 
 DevToolsServer::DevToolsServer()
-    : use_bundled_frontend_resources_(false),
-      socket_name_(kDefaultSocketName),
+    : socket_name_(base::StringPrintf(kDevToolsChannelNameFormat,
+                                      kDefaultSocketNamePrefix)),
       protocol_handler_(NULL) {
   // Override the default socket name if one is specified on the command line.
   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
@@ -144,10 +143,9 @@
   }
 }
 
-DevToolsServer::DevToolsServer(bool use_bundled_frontend_resources,
-                               const std::string& socket_name)
-    : use_bundled_frontend_resources_(use_bundled_frontend_resources),
-      socket_name_(socket_name),
+DevToolsServer::DevToolsServer(const std::string& socket_name_prefix)
+    : socket_name_(base::StringPrintf(kDevToolsChannelNameFormat,
+                                      socket_name_prefix.c_str())),
       protocol_handler_(NULL) {
 }
 
@@ -159,17 +157,14 @@
   if (protocol_handler_)
     return;
 
-  chrome::VersionInfo version_info;
-
   protocol_handler_ = content::DevToolsHttpHandler::Start(
       new net::UnixDomainSocketWithAbstractNamespaceFactory(
           socket_name_,
           base::StringPrintf("%s_%d", socket_name_.c_str(), getpid()),
           base::Bind(&content::CanUserConnectToDevTools)),
-      use_bundled_frontend_resources_ ?
-          "" :
-          base::StringPrintf(kFrontEndURL, version_info.Version().c_str()),
-      new DevToolsServerDelegate(use_bundled_frontend_resources_));
+      base::StringPrintf(kFrontEndURL,
+                         webkit_glue::GetWebKitRevision().c_str()),
+      new DevToolsServerDelegate());
 }
 
 void DevToolsServer::Stop() {
@@ -191,11 +186,9 @@
 
 static jint InitRemoteDebugging(JNIEnv* env,
                                 jobject obj,
-                                jboolean use_bundled_frontend_resources,
-                                jstring socketName) {
+                                jstring socket_name_prefix) {
   DevToolsServer* server = new DevToolsServer(
-      use_bundled_frontend_resources,
-      base::android::ConvertJavaStringToUTF8(env, socketName));
+      base::android::ConvertJavaStringToUTF8(env, socket_name_prefix));
   return reinterpret_cast<jint>(server);
 }
 
diff --git a/chrome/browser/android/dev_tools_server.h b/chrome/browser/android/dev_tools_server.h
index 775f0c0..72ddc89 100644
--- a/chrome/browser/android/dev_tools_server.h
+++ b/chrome/browser/android/dev_tools_server.h
@@ -17,8 +17,7 @@
 class DevToolsServer {
  public:
   DevToolsServer();
-  DevToolsServer(bool use_bundled_frontend_resources,
-                 const std::string& socket_name);
+  explicit DevToolsServer(const std::string& socket_name_prefix);
   ~DevToolsServer();
 
   // Opens linux abstract socket to be ready for remote debugging.
@@ -30,7 +29,6 @@
   bool IsStarted() const;
 
  private:
-  bool use_bundled_frontend_resources_;
   std::string socket_name_;
   content::DevToolsHttpHandler* protocol_handler_;
 
diff --git a/chrome/browser/android/favicon_helper.cc b/chrome/browser/android/favicon_helper.cc
new file mode 100644
index 0000000..03dc5d0
--- /dev/null
+++ b/chrome/browser/android/favicon_helper.cc
@@ -0,0 +1,101 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/android/favicon_helper.h"
+
+#include <jni.h>
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_string.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/bind.h"
+#include "chrome/browser/favicon/favicon_service.h"
+#include "chrome/browser/favicon/favicon_service_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_android.h"
+#include "jni/FaviconHelper_jni.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/android/java_bitmap.h"
+
+using base::android::ScopedJavaGlobalRef;
+using base::android::ScopedJavaLocalRef;
+using base::android::AttachCurrentThread;
+using base::android::ConvertJavaStringToUTF16;
+using base::android::ConvertUTF8ToJavaString;
+using base::android::MethodID;
+
+namespace {
+
+void FaviconImageCallback(
+    ScopedJavaGlobalRef<jobject>* java_favicon_image_callback,
+    const chrome::FaviconImageResult& favicon_image_result) {
+  JNIEnv* env = AttachCurrentThread();
+
+  // Convert favicon_image_result to java objects.
+  ScopedJavaLocalRef<jstring> java_icon_url = ConvertUTF8ToJavaString(
+      env, favicon_image_result.icon_url.spec());
+  SkBitmap favicon_bitmap = favicon_image_result.image.AsBitmap();
+  ScopedJavaLocalRef<jobject> java_favicon_bitmap = gfx::ConvertToJavaBitmap(
+      &favicon_bitmap);
+
+  // Call java side FaviconImageCallback method.
+  Java_FaviconImageCallback_onFaviconAvailable(
+      env, java_favicon_image_callback->obj(), java_favicon_bitmap.obj(),
+      java_icon_url.obj());
+}
+
+}  // namespace
+
+static jint Init(JNIEnv* env, jclass clazz) {
+  return reinterpret_cast<jint>(new FaviconHelper());
+}
+
+FaviconHelper::FaviconHelper() {
+  cancelable_task_tracker_.reset(new CancelableTaskTracker());
+}
+
+void FaviconHelper::Destroy(JNIEnv* env, jobject obj) {
+  delete this;
+}
+
+jboolean FaviconHelper::GetFaviconImageForURL(
+    JNIEnv* env, jobject obj, jobject jprofile, jstring page_url,
+    jint icon_types, jint desired_size_in_dip,
+    jobject java_favicon_image_callback) {
+  Profile* profile = ProfileAndroid::FromProfileAndroid(jprofile);
+  DCHECK(profile);
+  if (!profile)
+    return false;
+
+  FaviconService* favicon_service = FaviconServiceFactory::GetForProfile(
+      profile, Profile::EXPLICIT_ACCESS);
+  DCHECK(favicon_service);
+  if (!favicon_service)
+    return false;
+
+  FaviconService::FaviconForURLParams params(
+      profile, GURL(ConvertJavaStringToUTF16(env, page_url)),
+      static_cast<int>(icon_types), static_cast<int>(desired_size_in_dip));
+
+  ScopedJavaGlobalRef<jobject>* j_scoped_favicon_callback =
+      new ScopedJavaGlobalRef<jobject>();
+  j_scoped_favicon_callback->Reset(env, java_favicon_image_callback);
+
+  FaviconService::FaviconImageCallback callback_runner = base::Bind(
+      &FaviconImageCallback, base::Owned(j_scoped_favicon_callback));
+
+  favicon_service->GetFaviconImageForURL(
+      params, callback_runner,
+      cancelable_task_tracker_.get());
+
+  return true;
+}
+
+FaviconHelper::~FaviconHelper() {
+}
+
+// static
+bool FaviconHelper::RegisterFaviconHelper(JNIEnv* env) {
+  return RegisterNativesImpl(env);
+}
diff --git a/chrome/browser/android/favicon_helper.h b/chrome/browser/android/favicon_helper.h
new file mode 100644
index 0000000..a360995
--- /dev/null
+++ b/chrome/browser/android/favicon_helper.h
@@ -0,0 +1,30 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_ANDROID_FAVICON_HELPER_H_
+#define CHROME_BROWSER_ANDROID_FAVICON_HELPER_H_
+
+#include <jni.h>
+
+#include "base/memory/scoped_ptr.h"
+#include "chrome/common/cancelable_task_tracker.h"
+
+class FaviconHelper {
+ public:
+  FaviconHelper();
+  void Destroy(JNIEnv* env, jobject obj);
+  jboolean GetFaviconImageForURL(JNIEnv* env, jobject obj, jobject jprofile,
+                                 jstring page_url, jint icon_types,
+                                 jint desired_size_in_dip,
+                                 jobject java_favicon_image_callback);
+  static bool RegisterFaviconHelper(JNIEnv* env);
+ private:
+  scoped_ptr<CancelableTaskTracker> cancelable_task_tracker_;
+
+  virtual ~FaviconHelper();
+
+  DISALLOW_COPY_AND_ASSIGN(FaviconHelper);
+};
+
+#endif  // CHROME_BROWSER_ANDROID_FAVICON_HELPER_H_
diff --git a/chrome/browser/android/infobar_stubs.cc b/chrome/browser/android/infobar_stubs.cc
deleted file mode 100644
index 9316a7b..0000000
--- a/chrome/browser/android/infobar_stubs.cc
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/infobars/confirm_infobar_delegate.h"
-#include "chrome/browser/translate/translate_infobar_delegate.h"
-
-// Clank implementations of cross-platform API, never used
-// since infobars are created using the InfoBarFactory but we need
-// them implemented so the binary links both upstream and downstream.
-InfoBar* ConfirmInfoBarDelegate::CreateInfoBar(InfoBarService* owner) {
-  NOTREACHED() << "ConfirmInfoBar: InfoBarFactory should be used on Android";
-  return NULL;
-}
-
-InfoBar* TranslateInfoBarDelegate::CreateInfoBar(InfoBarService* owner) {
-  return NULL;
-}
diff --git a/chrome/browser/android/most_visited_sites.cc b/chrome/browser/android/most_visited_sites.cc
new file mode 100644
index 0000000..779fb55
--- /dev/null
+++ b/chrome/browser/android/most_visited_sites.cc
@@ -0,0 +1,183 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/android/most_visited_sites.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_array.h"
+#include "base/android/jni_string.h"
+#include "base/android/scoped_java_ref.h"
+#include "chrome/browser/history/history_types.h"
+#include "chrome/browser/history/top_sites.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_android.h"
+#include "content/public/browser/browser_thread.h"
+#include "jni/MostVisitedSites_jni.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/android/java_bitmap.h"
+#include "ui/gfx/codec/jpeg_codec.h"
+
+using base::android::AttachCurrentThread;
+using base::android::ConvertUTF8ToJavaString;
+using base::android::ConvertJavaStringToUTF8;
+using base::android::ScopedJavaGlobalRef;
+using base::android::ToJavaArrayOfStrings;
+using base::android::CheckException;
+using content::BrowserThread;
+using history::TopSites;
+
+namespace chrome {
+namespace android {
+
+bool RegisterMostVisitedSites(JNIEnv* env) {
+  return RegisterNativesImpl(env);
+}
+
+}  // namespace android
+}  // namespace chrome
+
+namespace {
+
+class NativeCallback : public base::RefCounted<NativeCallback> {
+ public:
+  NativeCallback(jobject j_callback_obj, int num_results)
+      : num_results_(num_results) {
+    JNIEnv* env = AttachCurrentThread();
+    j_callback_obj_.Reset(env, j_callback_obj);
+  }
+
+  void OnMostVisitedURLsAvailable(
+      const history::MostVisitedURLList& visited_list) {
+    std::vector<string16> titles;
+    std::vector<std::string> urls;
+    ExtractMostVisitedTitlesAndURLs(visited_list, &titles, &urls);
+
+    JNIEnv* env = AttachCurrentThread();
+    Java_MostVisitedURLsCallback_onMostVisitedURLsAvailable(
+        env,
+        j_callback_obj_.obj(),
+        ToJavaArrayOfStrings(env, titles).obj(),
+        ToJavaArrayOfStrings(env, urls).obj());
+  }
+
+ private:
+  friend class base::RefCounted<NativeCallback>;
+  ~NativeCallback() {}
+
+  void ExtractMostVisitedTitlesAndURLs(
+      const history::MostVisitedURLList& visited_list,
+      std::vector<string16>* titles,
+      std::vector<std::string>* urls) {
+    for (size_t i = 0; i < visited_list.size() && i < num_results_; ++i) {
+      const history::MostVisitedURL& visited = visited_list[i];
+
+      if (visited.url.is_empty())
+        break;  // This is the signal that there are no more real visited sites.
+
+      titles->push_back(visited.title);
+      urls->push_back(visited.url.spec());
+    }
+  }
+
+  ScopedJavaGlobalRef<jobject> j_callback_obj_;
+  size_t num_results_;
+};
+
+SkBitmap ExtractThumbnail(const base::RefCountedMemory& image_data) {
+  scoped_ptr<SkBitmap> image(gfx::JPEGCodec::Decode(
+      image_data.front(),
+      image_data.size()));
+  return image.get() ? *image : SkBitmap();
+}
+
+void OnObtainedThumbnail(
+    ScopedJavaGlobalRef<jobject>* bitmap,
+    ScopedJavaGlobalRef<jobject>* j_callback_ref) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  JNIEnv* env = AttachCurrentThread();
+  Java_ThumbnailCallback_onMostVisitedURLsThumbnailAvailable(
+      env, j_callback_ref->obj(), bitmap->obj());
+}
+
+void GetUrlThumbnailTask(
+    std::string url_string,
+    scoped_refptr<TopSites> top_sites,
+    ScopedJavaGlobalRef<jobject>* j_callback_ref) {
+  JNIEnv* env = AttachCurrentThread();
+
+  ScopedJavaGlobalRef<jobject>* j_bitmap_ref =
+      new ScopedJavaGlobalRef<jobject>();
+
+  GURL gurl(url_string);
+
+  scoped_refptr<base::RefCountedMemory> data;
+  if (top_sites->GetPageThumbnail(gurl, &data)) {
+    SkBitmap thumbnail_bitmap = ExtractThumbnail(*data.get());
+    if (!thumbnail_bitmap.empty()) {
+      j_bitmap_ref->Reset(
+          env,
+          gfx::ConvertToJavaBitmap(&thumbnail_bitmap).obj());
+    }
+  }
+
+  // Since j_callback_ref is owned by this callback,
+  // when the callback falls out of scope it will be deleted.
+  // We need to pass ownership to the next callback.
+  ScopedJavaGlobalRef<jobject>* j_callback_ref_pass =
+      new ScopedJavaGlobalRef<jobject>(*j_callback_ref);
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE,
+      base::Bind(
+          &OnObtainedThumbnail,
+          base::Owned(j_bitmap_ref),base::Owned(j_callback_ref_pass)));
+}
+
+}  // namespace
+
+void GetMostVisitedURLs(
+    JNIEnv* env,
+    jclass clazz,
+    jobject j_profile,
+    jobject j_callback_obj,
+    jint num_results) {
+  Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile);
+
+  DCHECK(profile);
+  if (!profile)
+    return;
+
+  TopSites* top_sites = profile->GetTopSites();
+
+  scoped_refptr<NativeCallback> native_callback =
+      new NativeCallback(j_callback_obj, static_cast<int>(num_results));
+  top_sites->GetMostVisitedURLs(
+      base::Bind(&NativeCallback::OnMostVisitedURLsAvailable,
+                 native_callback));
+}
+
+// May be called from any thread
+void GetURLThumbnail(
+    JNIEnv* env,
+    jclass clazz,
+    jobject j_profile,
+    jstring url,
+    jobject j_callback_obj) {
+  Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile);
+
+  DCHECK(profile);
+  if (!profile)
+    return;
+
+  ScopedJavaGlobalRef<jobject>* j_callback_ref =
+      new ScopedJavaGlobalRef<jobject>();
+  j_callback_ref->Reset(env, j_callback_obj);
+
+  std::string url_string = ConvertJavaStringToUTF8(env, url);
+  scoped_refptr<TopSites> top_sites(profile->GetTopSites());
+  BrowserThread::PostTask(
+      BrowserThread::DB, FROM_HERE, base::Bind(
+          &GetUrlThumbnailTask,
+          url_string,
+          top_sites, base::Owned(j_callback_ref)));
+}
diff --git a/chrome/browser/android/most_visited_sites.h b/chrome/browser/android/most_visited_sites.h
new file mode 100644
index 0000000..6b1c85d
--- /dev/null
+++ b/chrome/browser/android/most_visited_sites.h
@@ -0,0 +1,18 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_ANDROID_MOST_VISITED_SITES_H_
+#define CHROME_BROWSER_ANDROID_MOST_VISITED_SITES_H_
+
+#include <jni.h>
+
+namespace chrome {
+namespace android {
+
+bool RegisterMostVisitedSites(JNIEnv* env);
+
+}  // namespace android
+}  // namespace chrome
+
+#endif  // CHROME_BROWSER_ANDROID_MOST_VISITED_SITES_H_
diff --git a/chrome/browser/android/provider/chrome_browser_provider.cc b/chrome/browser/android/provider/chrome_browser_provider.cc
index 6353f44..71764ef 100644
--- a/chrome/browser/android/provider/chrome_browser_provider.cc
+++ b/chrome/browser/android/provider/chrome_browser_provider.cc
@@ -13,7 +13,7 @@
 #include "base/logging.h"
 #include "base/memory/ref_counted_memory.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/android/provider/blocking_ui_thread_async_request.h"
 #include "chrome/browser/android/provider/bookmark_model_observer_task.h"
 #include "chrome/browser/android/provider/run_on_ui_thread_blocking.h"
@@ -894,8 +894,9 @@
         template_service->GetDefaultSearchProvider();
     if (search_engine) {
       const TemplateURLRef* search_url = &search_engine->url_ref();
-      std::string url = search_url->ReplaceSearchTerms(
-                     TemplateURLRef::SearchTermsArgs(row->search_term()));
+      TemplateURLRef::SearchTermsArgs search_terms_args(row->search_term());
+      search_terms_args.append_extra_query_params = true;
+      std::string url = search_url->ReplaceSearchTerms(search_terms_args);
       if (!url.empty()) {
         row->set_url(GURL(url));
         row->set_template_url_id(search_engine->id());
diff --git a/chrome/browser/android/resource_id.h b/chrome/browser/android/resource_id.h
index 459754c..3393724 100644
--- a/chrome/browser/android/resource_id.h
+++ b/chrome/browser/android/resource_id.h
@@ -31,7 +31,7 @@
 DEFINE_RESOURCE_ID(IDR_INFOBAR_PLUGIN_INSTALL, R.drawable.infobar_plugin)
 DEFINE_RESOURCE_ID(IDR_INFOBAR_RESTORE_SESSION, R.drawable.infobar_restore)
 DEFINE_RESOURCE_ID(IDR_INFOBAR_SAVE_PASSWORD, R.drawable.infobar_savepassword)
-DEFINE_RESOURCE_ID(IDR_INFOBAR_SSL_WARNING, R.drawable.infobar_insecure)
+DEFINE_RESOURCE_ID(IDR_INFOBAR_WARNING, R.drawable.infobar_warning)
 DEFINE_RESOURCE_ID(IDR_INFOBAR_THEME, R.drawable.infobar_theme)
 DEFINE_RESOURCE_ID(IDR_INFOBAR_TRANSLATE, R.drawable.infobar_translate)
 
diff --git a/chrome/browser/android/tab_android.cc b/chrome/browser/android/tab_android.cc
index 010b376..3b5b2b1 100644
--- a/chrome/browser/android/tab_android.cc
+++ b/chrome/browser/android/tab_android.cc
@@ -65,8 +65,7 @@
       contents,
       autofill::TabAutofillManagerDelegate::FromWebContents(contents),
       g_browser_process->GetApplicationLocale(),
-      autofill::AutofillManager::ENABLE_AUTOFILL_DOWNLOAD_MANAGER,
-      true);
+      autofill::AutofillManager::ENABLE_AUTOFILL_DOWNLOAD_MANAGER);
   BlockedContentTabHelper::CreateForWebContents(contents);
   BookmarkTabHelper::CreateForWebContents(contents);
   CoreTabHelper::CreateForWebContents(contents);
diff --git a/chrome/browser/android/tab_android_test_stubs.cc b/chrome/browser/android/tab_android_test_stubs.cc
index edfd4cd..b26ae5f 100644
--- a/chrome/browser/android/tab_android_test_stubs.cc
+++ b/chrome/browser/android/tab_android_test_stubs.cc
@@ -6,6 +6,10 @@
 // needed to compile some tests.
 
 #include "chrome/browser/android/tab_android.h"
+#include "chrome/browser/infobars/confirm_infobar_delegate.h"
+#include "chrome/browser/translate/translate_infobar_delegate.h"
+#include "chrome/browser/ui/auto_login_infobar_delegate.h"
+#include "chrome/browser/ui/auto_login_infobar_delegate_android.h"
 
 // static
 TabAndroid* TabAndroid::FromWebContents(content::WebContents* web_contents) {
@@ -16,3 +20,40 @@
 TabAndroid* TabAndroid::GetNativeTab(JNIEnv* env, jobject obj) {
   return NULL;
 }
+
+// AutoLoginInfoBarDelegatAndroid empty implementation for test_shell.
+// TODO(miguelg) remove once the AutoLoginInfoBar is upstreamed.
+AutoLoginInfoBarDelegateAndroid::AutoLoginInfoBarDelegateAndroid(
+    InfoBarService* owner,
+    const AutoLoginInfoBarDelegate::Params& params)
+    : AutoLoginInfoBarDelegate(owner, params) {}
+
+AutoLoginInfoBarDelegateAndroid::~AutoLoginInfoBarDelegateAndroid() {}
+
+bool AutoLoginInfoBarDelegateAndroid::Accept() {
+  return false;
+}
+
+bool AutoLoginInfoBarDelegateAndroid::Cancel() {
+  return false;
+}
+
+base::string16 AutoLoginInfoBarDelegateAndroid::GetMessageText() const {
+  return base::string16();
+}
+
+// static
+bool AutoLoginInfoBarDelegateAndroid::Register(JNIEnv* env) {
+  return false;
+}
+
+// static
+InfoBar* ConfirmInfoBarDelegate::CreateInfoBar(InfoBarService* owner) {
+  NOTREACHED() << "ConfirmInfoBar: InfoBarFactory should be used on Android";
+  return NULL;
+}
+
+// static
+InfoBar* TranslateInfoBarDelegate::CreateInfoBar(InfoBarService* owner) {
+  return NULL;
+}
diff --git a/chrome/browser/app_controller_mac.h b/chrome/browser/app_controller_mac.h
index cea9bfd..46d8a05 100644
--- a/chrome/browser/app_controller_mac.h
+++ b/chrome/browser/app_controller_mac.h
@@ -10,12 +10,13 @@
 #import <Cocoa/Cocoa.h>
 #include <vector>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/observer_list.h"
 #include "base/prefs/pref_change_registrar.h"
 #include "ui/base/work_area_watcher_observer.h"
 
+class AppControllerProfileObserver;
 class BookmarkMenuBridge;
 class CommandUpdater;
 class GURL;
@@ -39,6 +40,10 @@
   // build the user-data specific main menu items.
   Profile* lastProfile_;
 
+  // The ProfileObserver observes the ProfileInfoCache and gets notified
+  // when a profile has been deleted.
+  scoped_ptr<AppControllerProfileObserver> profileInfoCacheObserver_;
+
   // Management of the bookmark menu which spans across all windows
   // (and Browser*s).
   scoped_ptr<BookmarkMenuBridge> bookmarkMenuBridge_;
@@ -46,7 +51,7 @@
 
   // The profile menu, which appears right before the Help menu. It is only
   // available when multiple profiles is enabled.
-  scoped_nsobject<ProfileMenuController> profileMenuController_;
+  base::scoped_nsobject<ProfileMenuController> profileMenuController_;
 
   // If we're told to open URLs (in particular, via |-application:openFiles:| by
   // Launch Services) before we've launched the browser, we queue them up in
@@ -101,7 +106,7 @@
 - (IBAction)showPreferences:(id)sender;
 
 // Redirect in the menu item from the expected target of "File's
-// Owner" (NSAppliation) for a Branded About Box
+// Owner" (NSApplication) for a Branded About Box
 - (IBAction)orderFrontStandardAboutPanel:(id)sender;
 
 // Toggles the "Confirm to Quit" preference.
diff --git a/chrome/browser/app_controller_mac.mm b/chrome/browser/app_controller_mac.mm
index 4aae313..3944238 100644
--- a/chrome/browser/app_controller_mac.mm
+++ b/chrome/browser/app_controller_mac.mm
@@ -28,6 +28,7 @@
 #include "chrome/browser/first_run/first_run.h"
 #include "chrome/browser/lifetime/application_lifetime.h"
 #include "chrome/browser/printing/print_dialog_cloud.h"
+#include "chrome/browser/profiles/profile_info_cache_observer.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/service/service_process_control.h"
 #include "chrome/browser/sessions/session_restore.h"
@@ -190,8 +191,57 @@
 - (BOOL)userWillWaitForInProgressDownloads:(int)downloadCount;
 - (BOOL)shouldQuitWithInProgressDownloads;
 - (void)executeApplication:(id)sender;
+- (void)profileWasRemoved:(const base::FilePath&)profilePath;
 @end
 
+class AppControllerProfileObserver : public ProfileInfoCacheObserver {
+ public:
+  AppControllerProfileObserver(
+      ProfileManager* profile_manager, AppController* app_controller)
+      : profile_manager_(profile_manager),
+        app_controller_(app_controller) {
+    DCHECK(profile_manager_);
+    DCHECK(app_controller_);
+    profile_manager_->GetProfileInfoCache().AddObserver(this);
+  }
+
+  virtual ~AppControllerProfileObserver() {
+    DCHECK(profile_manager_);
+    profile_manager_->GetProfileInfoCache().RemoveObserver(this);
+  }
+
+ private:
+  // ProfileInfoCacheObserver implementation:
+
+  virtual void OnProfileAdded(const base::FilePath& profile_path) OVERRIDE {
+  }
+
+  virtual void OnProfileWasRemoved(const base::FilePath& profile_path,
+                                   const string16& profile_name) OVERRIDE {
+    // When a profile is deleted we need to notify the AppController,
+    // so it can correctly update its pointer to the last used profile.
+    [app_controller_ profileWasRemoved:profile_path];
+  }
+
+  virtual void OnProfileWillBeRemoved(
+      const base::FilePath& profile_path) OVERRIDE {
+  }
+
+  virtual void OnProfileNameChanged(const base::FilePath& profile_path,
+                                    const string16& old_profile_name) OVERRIDE {
+  }
+
+  virtual void OnProfileAvatarChanged(
+      const base::FilePath& profile_path) OVERRIDE {
+  }
+
+  ProfileManager* profile_manager_;
+
+  AppController* app_controller_;  // Weak; owns us.
+
+  DISALLOW_COPY_AND_ASSIGN(AppControllerProfileObserver);
+};
+
 @implementation AppController
 
 @synthesize startupComplete = startupComplete_;
@@ -585,6 +635,11 @@
   EncodingMenuControllerDelegate::BuildEncodingMenu([self lastProfile],
                                                     encodingMenu);
 
+  // Instantiate the ProfileInfoCache observer so that we can get
+  // notified when a profile is deleted.
+  profileInfoCacheObserver_.reset(new AppControllerProfileObserver(
+      g_browser_process->profile_manager(), self));
+
   // Since Chrome is localized to more languages than the OS, tell Cocoa which
   // menu is the Help so it can add the search item to it.
   [NSApp setHelpMenu:helpMenu_];
@@ -659,8 +714,8 @@
       IDS_DOWNLOAD_REMOVE_CONFIRM_CANCEL_BUTTON_LABEL);
 
   // 'waitButton' is the default choice.
-  int choice = NSRunAlertPanel(titleText, explanationText,
-                               waitTitle, exitTitle, nil);
+  int choice = NSRunAlertPanel(titleText, @"%@",
+                               waitTitle, exitTitle, nil, explanationText);
   return choice == NSAlertDefaultReturn ? YES : NO;
 }
 
@@ -714,6 +769,18 @@
   return service && !service->entries().empty();
 }
 
+// Called from the AppControllerProfileObserver every time a profile is deleted.
+- (void)profileWasRemoved:(const base::FilePath&)profilePath {
+  Profile* lastProfile = [self lastProfile];
+
+  // If the lastProfile has been deleted, the profile manager has
+  // already loaded a new one, so the pointer needs to be updated;
+  // otherwise we will try to start up a browser window with a pointer
+  // to the old profile.
+  if (profilePath == lastProfile->GetPath())
+    lastProfile_ = g_browser_process->profile_manager()->GetLastUsedProfile();
+}
+
 // Returns true if there is a modal window (either window- or application-
 // modal) blocking the active browser. Note that tab modal dialogs (HTTP auth
 // sheets) will not count as blocking the browser. But things like open/save
@@ -928,7 +995,7 @@
       break;
     case IDC_TASK_MANAGER:
       content::RecordAction(UserMetricsAction("TaskManager"));
-      TaskManagerMac::Show(false);
+      TaskManagerMac::Show();
       break;
     case IDC_OPTIONS:
       [self showPreferences:sender];
@@ -1226,7 +1293,7 @@
     [dockMenu addItem:[NSMenuItem separatorItem]];
 
   NSString* titleStr = l10n_util::GetNSStringWithFixup(IDS_NEW_WINDOW_MAC);
-  scoped_nsobject<NSMenuItem> item(
+  base::scoped_nsobject<NSMenuItem> item(
       [[NSMenuItem alloc] initWithTitle:titleStr
                                  action:@selector(commandFromDock:)
                           keyEquivalent:@""]);
@@ -1255,31 +1322,23 @@
       int position = 0;
       NSString* menuStr =
           l10n_util::GetNSStringWithFixup(IDS_BACKGROUND_APPS_MAC);
-      scoped_nsobject<NSMenu> appMenu([[NSMenu alloc] initWithTitle:menuStr]);
+      base::scoped_nsobject<NSMenu> appMenu(
+          [[NSMenu alloc] initWithTitle:menuStr]);
       for (extensions::ExtensionList::const_iterator cursor =
                applications.begin();
            cursor != applications.end();
            ++cursor, ++position) {
-        DCHECK_EQ(applications.GetPosition(*cursor), position);
+        DCHECK_EQ(applications.GetPosition(cursor->get()), position);
         NSString* itemStr =
             base::SysUTF16ToNSString(UTF8ToUTF16((*cursor)->name()));
-        scoped_nsobject<NSMenuItem> appItem([[NSMenuItem alloc]
-            initWithTitle:itemStr
-                   action:@selector(executeApplication:)
-            keyEquivalent:@""]);
+        base::scoped_nsobject<NSMenuItem> appItem(
+            [[NSMenuItem alloc] initWithTitle:itemStr
+                                       action:@selector(executeApplication:)
+                                keyEquivalent:@""]);
         [appItem setTarget:self];
         [appItem setTag:position];
         [appMenu addItem:appItem];
       }
-
-      scoped_nsobject<NSMenuItem> appMenuItem([[NSMenuItem alloc]
-          initWithTitle:menuStr
-                 action:@selector(executeApplication:)
-          keyEquivalent:@""]);
-      [appMenuItem setTarget:self];
-      [appMenuItem setTag:IDC_VIEW_BACKGROUND_PAGES];
-      [appMenuItem setSubmenu:appMenu];
-      [dockMenu addItem:appMenuItem];
     }
   }
 
diff --git a/chrome/browser/app_controller_mac_browsertest.mm b/chrome/browser/app_controller_mac_browsertest.mm
index 62d2680..11f2c98 100644
--- a/chrome/browser/app_controller_mac_browsertest.mm
+++ b/chrome/browser/app_controller_mac_browsertest.mm
@@ -5,7 +5,7 @@
 #import <Cocoa/Cocoa.h>
 
 #include "base/command_line.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/app/chrome_command_ids.h"
 #import "chrome/browser/app_controller_mac.h"
 #include "chrome/browser/ui/browser.h"
@@ -22,8 +22,8 @@
 class AppControllerPlatformAppBrowserTest : public InProcessBrowserTest {
  protected:
   AppControllerPlatformAppBrowserTest()
-      : native_browser_list(BrowserList::GetInstance(
-                                chrome::HOST_DESKTOP_TYPE_NATIVE)) {
+      : active_browser_list_(BrowserList::GetInstance(
+                                chrome::GetActiveDesktop())) {
   }
 
   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
@@ -31,29 +31,28 @@
                                     "1234");
   }
 
-  // Mac only has the native desktop.
-  const BrowserList* native_browser_list;
+  const BrowserList* active_browser_list_;
 };
 
 // Test that if only a platform app window is open and no browser windows are
 // open then a reopen event does nothing.
 IN_PROC_BROWSER_TEST_F(AppControllerPlatformAppBrowserTest,
                        PlatformAppReopenWithWindows) {
-  scoped_nsobject<AppController> ac([[AppController alloc] init]);
+  base::scoped_nsobject<AppController> ac([[AppController alloc] init]);
   NSUInteger old_window_count = [[NSApp windows] count];
-  EXPECT_EQ(1u, native_browser_list->size());
+  EXPECT_EQ(1u, active_browser_list_->size());
   BOOL result = [ac applicationShouldHandleReopen:NSApp hasVisibleWindows:YES];
 
   EXPECT_TRUE(result);
   EXPECT_EQ(old_window_count, [[NSApp windows] count]);
-  EXPECT_EQ(1u, native_browser_list->size());
+  EXPECT_EQ(1u, active_browser_list_->size());
 }
 
 class AppControllerWebAppBrowserTest : public InProcessBrowserTest {
  protected:
   AppControllerWebAppBrowserTest()
-      : native_browser_list(BrowserList::GetInstance(
-                                chrome::HOST_DESKTOP_TYPE_NATIVE)) {
+      : active_browser_list_(BrowserList::GetInstance(
+                                chrome::GetActiveDesktop())) {
   }
 
   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
@@ -64,21 +63,20 @@
     return "http://example.com/";
   }
 
-  // Mac only has the native desktop.
-  const BrowserList* native_browser_list;
+  const BrowserList* active_browser_list_;
 };
 
 // Test that in web app mode a reopen event opens the app URL.
 IN_PROC_BROWSER_TEST_F(AppControllerWebAppBrowserTest,
                        WebAppReopenWithNoWindows) {
-  scoped_nsobject<AppController> ac([[AppController alloc] init]);
-  EXPECT_EQ(1u, native_browser_list->size());
+  base::scoped_nsobject<AppController> ac([[AppController alloc] init]);
+  EXPECT_EQ(1u, active_browser_list_->size());
   BOOL result = [ac applicationShouldHandleReopen:NSApp hasVisibleWindows:NO];
 
   EXPECT_FALSE(result);
-  EXPECT_EQ(2u, native_browser_list->size());
+  EXPECT_EQ(2u, active_browser_list_->size());
 
-  Browser* browser = native_browser_list->get(0);
+  Browser* browser = active_browser_list_->get(0);
   GURL current_url =
       browser->tab_strip_model()->GetActiveWebContents()->GetURL();
   EXPECT_EQ(GetAppURL(), current_url.spec());
diff --git a/chrome/browser/app_controller_mac_unittest.mm b/chrome/browser/app_controller_mac_unittest.mm
index b391fd7..ed9c813 100644
--- a/chrome/browser/app_controller_mac_unittest.mm
+++ b/chrome/browser/app_controller_mac_unittest.mm
@@ -4,16 +4,39 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/files/file_path.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/app/chrome_command_ids.h"
 #import "chrome/browser/app_controller_mac.h"
+#include "chrome/browser/ui/cocoa/cocoa_profile_test.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/base/testing_profile_manager.h"
+#include "chrome/test/base/ui_test_utils.h"
 #include "testing/platform_test.h"
 
 class AppControllerTest : public PlatformTest {
+ protected:
+  AppControllerTest()
+      : ui_thread_(content::BrowserThread::UI, &message_loop_),
+        db_thread_(content::BrowserThread::DB, &message_loop_),
+        file_thread_(content::BrowserThread::FILE, &message_loop_) {
+  }
+
+  virtual void TearDown() {
+    TestingBrowserProcess::GetGlobal()->SetProfileManager(NULL);
+    message_loop_.RunUntilIdle();
+  }
+
+  base::MessageLoopForUI message_loop_;
+  content::TestBrowserThread ui_thread_;
+  content::TestBrowserThread db_thread_;
+  content::TestBrowserThread file_thread_;
 };
 
 TEST_F(AppControllerTest, DockMenu) {
-  scoped_nsobject<AppController> ac([[AppController alloc] init]);
+  base::scoped_nsobject<AppController> ac([[AppController alloc] init]);
   NSMenu* menu = [ac applicationDockMenu:NSApp];
   NSMenuItem* item;
 
@@ -25,3 +48,30 @@
     EXPECT_EQ(@selector(commandFromDock:), [item action]);
   }
 }
+
+TEST_F(AppControllerTest, LastProfile) {
+  TestingProfileManager manager(TestingBrowserProcess::GetGlobal());
+  ASSERT_TRUE(manager.SetUp());
+
+  // Create two profiles.
+  base::FilePath dest_path1 =
+      manager.CreateTestingProfile("New Profile 1")->GetPath();
+  base::FilePath dest_path2 =
+      manager.CreateTestingProfile("New Profile 2")->GetPath();
+  ASSERT_EQ(2U, manager.profile_manager()->GetNumberOfProfiles());
+  ASSERT_EQ(2U, manager.profile_manager()->GetLoadedProfiles().size());
+
+  PrefService* local_state = g_browser_process->local_state();
+  local_state->SetString(prefs::kProfileLastUsed,
+                         dest_path1.BaseName().MaybeAsASCII());
+
+  base::scoped_nsobject<AppController> ac([[AppController alloc] init]);
+
+  // Delete the active profile.
+  manager.profile_manager()->ScheduleProfileForDeletion(
+      dest_path1, ProfileManager::CreateCallback());
+
+  message_loop_.RunUntilIdle();
+
+  EXPECT_EQ(dest_path2, [ac lastProfile]->GetPath());
+}
diff --git a/chrome/browser/autocomplete/autocomplete_browsertest.cc b/chrome/browser/autocomplete/autocomplete_browsertest.cc
index 510d82b..8161ce37 100644
--- a/chrome/browser/autocomplete/autocomplete_browsertest.cc
+++ b/chrome/browser/autocomplete/autocomplete_browsertest.cc
@@ -120,12 +120,12 @@
   AutocompleteController* autocomplete_controller = GetAutocompleteController();
 
   {
+    OmniboxView* location_entry = location_bar->GetLocationEntry();
+    location_entry->model()->SetInputInProgress(true);
     autocomplete_controller->Start(AutocompleteInput(
         ASCIIToUTF16("chrome"), string16::npos, string16(), GURL(), true, false,
         true, AutocompleteInput::SYNCHRONOUS_MATCHES));
 
-    OmniboxView* location_entry = location_bar->GetLocationEntry();
-
     EXPECT_TRUE(autocomplete_controller->done());
     EXPECT_TRUE(location_bar->GetInputString().empty());
     EXPECT_TRUE(location_entry->GetText().empty());
diff --git a/chrome/browser/autocomplete/autocomplete_classifier.cc b/chrome/browser/autocomplete/autocomplete_classifier.cc
index ed7d8ab..4eff86a 100644
--- a/chrome/browser/autocomplete/autocomplete_classifier.cc
+++ b/chrome/browser/autocomplete/autocomplete_classifier.cc
@@ -9,7 +9,7 @@
 #include "chrome/browser/autocomplete/autocomplete_input.h"
 #include "chrome/browser/autocomplete/autocomplete_match.h"
 #include "chrome/browser/autocomplete/autocomplete_provider.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 // static
 const int AutocompleteClassifier::kDefaultOmniboxProviders =
@@ -32,6 +32,7 @@
     // TODO: remove TYPE_SEARCH once it's no longer needed to pass
     // the Instant suggestion through via FinalizeInstantQuery.
     AutocompleteProvider::TYPE_SEARCH |
+    AutocompleteProvider::TYPE_SHORTCUTS |
     AutocompleteProvider::TYPE_ZERO_SUGGEST;
 
 AutocompleteClassifier::AutocompleteClassifier(Profile* profile)
diff --git a/chrome/browser/autocomplete/autocomplete_controller.cc b/chrome/browser/autocomplete/autocomplete_controller.cc
index 81921bf..3cc8a68 100644
--- a/chrome/browser/autocomplete/autocomplete_controller.cc
+++ b/chrome/browser/autocomplete/autocomplete_controller.cc
@@ -13,7 +13,7 @@
 #include "base/metrics/histogram.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/autocomplete/autocomplete_controller_delegate.h"
 #include "chrome/browser/autocomplete/bookmark_provider.h"
 #include "chrome/browser/autocomplete/builtin_provider.h"
@@ -310,12 +310,11 @@
 }
 
 void AutocompleteController::StartZeroSuggest(const GURL& url,
-                                              const string16& user_text,
                                               const string16& permanent_text) {
   if (zero_suggest_provider_ != NULL) {
     DCHECK(!in_start_);  // We should not be already running a query.
     in_zero_suggest_ = true;
-    zero_suggest_provider_->StartZeroSuggest(url, user_text, permanent_text);
+    zero_suggest_provider_->StartZeroSuggest(url, permanent_text);
   }
 }
 
@@ -377,6 +376,7 @@
   for (ACProviders::const_iterator i(providers_.begin()); i != providers_.end();
        ++i)
     (*i)->ResetSession();
+  in_zero_suggest_ = false;
 }
 
 void AutocompleteController::UpdateResult(
@@ -464,23 +464,23 @@
     string16 keyword(match->GetSubstitutingExplicitlyInvokedKeyword(profile_));
     if (!keyword.empty()) {
       keywords.insert(keyword);
+      continue;
+    }
+
+    // Only add the keyword if the match does not have a duplicate keyword with
+    // a more relevant match.
+    keyword = match->associated_keyword.get() ?
+        match->associated_keyword->keyword :
+        keyword_provider_->GetKeywordForText(match->fill_into_edit);
+    if (!keyword.empty() && !keywords.count(keyword)) {
+      keywords.insert(keyword);
+
+      if (!match->associated_keyword.get())
+        match->associated_keyword.reset(new AutocompleteMatch(
+            keyword_provider_->CreateAutocompleteMatch(match->fill_into_edit,
+                                                       keyword, input_)));
     } else {
-      string16 keyword = match->associated_keyword.get() ?
-          match->associated_keyword->keyword :
-          keyword_provider_->GetKeywordForText(match->fill_into_edit);
-
-      // Only add the keyword if the match does not have a duplicate keyword
-      // with a more relevant match.
-      if (!keyword.empty() && !keywords.count(keyword)) {
-        keywords.insert(keyword);
-
-        if (!match->associated_keyword.get())
-          match->associated_keyword.reset(new AutocompleteMatch(
-              keyword_provider_->CreateAutocompleteMatch(match->fill_into_edit,
-                  keyword, input_)));
-      } else {
-        match->associated_keyword.reset();
-      }
+      match->associated_keyword.reset();
     }
   }
 }
diff --git a/chrome/browser/autocomplete/autocomplete_controller.h b/chrome/browser/autocomplete/autocomplete_controller.h
index 38a658d..5b06749 100644
--- a/chrome/browser/autocomplete/autocomplete_controller.h
+++ b/chrome/browser/autocomplete/autocomplete_controller.h
@@ -9,8 +9,8 @@
 #include "base/compiler_specific.h"
 #include "base/gtest_prod_util.h"
 #include "base/strings/string16.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/autocomplete/autocomplete_input.h"
 #include "chrome/browser/autocomplete/autocomplete_provider.h"
 #include "chrome/browser/autocomplete/autocomplete_provider_listener.h"
@@ -80,11 +80,10 @@
   // Begin asynchronously fetching zero-suggest suggestions for |url|.
   // |user_text| is the text entered in the omnibox, which may be non-empty if
   // the user previously focused in the omnibox during this interaction.
-  // |permanent_text| is the text version of |url| displayed in the omnibox.
+  // |permanent_text| is the omnibox text for the current page.
   // TODO(jered): Rip out |user_text| once the first match is decoupled from
   // the current typing in the omnibox.
   void StartZeroSuggest(const GURL& url,
-                        const string16& user_text,
                         const string16& permanent_text);
 
   // Cancels any pending zero-suggest fetch.
diff --git a/chrome/browser/autocomplete/autocomplete_input.cc b/chrome/browser/autocomplete/autocomplete_input.cc
index cf2af6a..349e611 100644
--- a/chrome/browser/autocomplete/autocomplete_input.cc
+++ b/chrome/browser/autocomplete/autocomplete_input.cc
@@ -10,9 +10,9 @@
 #include "chrome/browser/net/url_fixer_upper.h"
 #include "chrome/browser/profiles/profile_io_data.h"
 #include "content/public/common/url_constants.h"
-#include "googleurl/src/url_canon_ip.h"
 #include "net/base/net_util.h"
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+#include "url/url_canon_ip.h"
 
 namespace {
 
diff --git a/chrome/browser/autocomplete/autocomplete_input.h b/chrome/browser/autocomplete/autocomplete_input.h
index 839d73f..d70a3af 100644
--- a/chrome/browser/autocomplete/autocomplete_input.h
+++ b/chrome/browser/autocomplete/autocomplete_input.h
@@ -9,8 +9,8 @@
 
 #include "base/basictypes.h"
 #include "base/strings/string16.h"
-#include "googleurl/src/gurl.h"
-#include "googleurl/src/url_parse.h"
+#include "url/gurl.h"
+#include "url/url_parse.h"
 
 // The user input for an autocomplete query.  Allows copying.
 class AutocompleteInput {
diff --git a/chrome/browser/autocomplete/autocomplete_input_unittest.cc b/chrome/browser/autocomplete/autocomplete_input_unittest.cc
index 1cdcc02..db7a1dd 100644
--- a/chrome/browser/autocomplete/autocomplete_input_unittest.cc
+++ b/chrome/browser/autocomplete/autocomplete_input_unittest.cc
@@ -8,8 +8,8 @@
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
-#include "googleurl/src/url_parse.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/url_parse.h"
 
 TEST(AutocompleteInputTest, InputType) {
   struct test_data {
diff --git a/chrome/browser/autocomplete/autocomplete_match.cc b/chrome/browser/autocomplete/autocomplete_match.cc
index 5eccdb7..fc6774c 100644
--- a/chrome/browser/autocomplete/autocomplete_match.cc
+++ b/chrome/browser/autocomplete/autocomplete_match.cc
@@ -9,9 +9,8 @@
 #include "base/strings/string16.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/autocomplete/autocomplete_provider.h"
 #include "chrome/browser/search_engines/template_url.h"
 #include "chrome/browser/search_engines/template_url_service.h"
@@ -421,14 +420,14 @@
 
 void AutocompleteMatch::RecordAdditionalInfo(const std::string& property,
                                              const std::string& value) {
-  DCHECK(property.size());
-  DCHECK(value.size());
+  DCHECK(!property.empty());
+  DCHECK(!value.empty());
   additional_info[property] = value;
 }
 
 void AutocompleteMatch::RecordAdditionalInfo(const std::string& property,
                                              int value) {
-  RecordAdditionalInfo(property, base::StringPrintf("%d", value));
+  RecordAdditionalInfo(property, base::IntToString(value));
 }
 
 void AutocompleteMatch::RecordAdditionalInfo(const std::string& property,
@@ -437,6 +436,12 @@
                        UTF16ToUTF8(base::TimeFormatShortDateAndTime(value)));
 }
 
+std::string AutocompleteMatch::GetAdditionalInfo(
+    const std::string& property) const {
+  AdditionalInfo::const_iterator i(additional_info.find(property));
+  return (i == additional_info.end()) ? std::string() : i->second;
+}
+
 #ifndef NDEBUG
 void AutocompleteMatch::Validate() const {
   ValidateClassifications(contents, contents_class);
diff --git a/chrome/browser/autocomplete/autocomplete_match.h b/chrome/browser/autocomplete/autocomplete_match.h
index 146586e..4d4ca47 100644
--- a/chrome/browser/autocomplete/autocomplete_match.h
+++ b/chrome/browser/autocomplete/autocomplete_match.h
@@ -13,7 +13,7 @@
 #include "chrome/browser/search_engines/template_url.h"
 #include "chrome/common/autocomplete_match_type.h"
 #include "content/public/common/page_transition_types.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 class AutocompleteProvider;
 class Profile;
@@ -214,6 +214,10 @@
   void RecordAdditionalInfo(const std::string& property,
                             const base::Time& value);
 
+  // Returns the value recorded for |property| in the |additional_info|
+  // dictionary.  Returns the empty string if no such value exists.
+  std::string GetAdditionalInfo(const std::string& property) const;
+
   // The provider of this match, used to remember which provider the user had
   // selected when the input changes. This may be NULL, in which case there is
   // no provider (or memory of the user's selection).
diff --git a/chrome/browser/autocomplete/autocomplete_provider.cc b/chrome/browser/autocomplete/autocomplete_provider.cc
index d71e075..873bbac 100644
--- a/chrome/browser/autocomplete/autocomplete_provider.cc
+++ b/chrome/browser/autocomplete/autocomplete_provider.cc
@@ -14,9 +14,9 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/pref_names.h"
 #include "content/public/common/url_constants.h"
-#include "googleurl/src/gurl.h"
-#include "googleurl/src/url_util.h"
 #include "net/base/net_util.h"
+#include "url/gurl.h"
+#include "url/url_util.h"
 
 // static
 const size_t AutocompleteProvider::kMaxMatches = 3;
diff --git a/chrome/browser/autocomplete/autocomplete_provider_unittest.cc b/chrome/browser/autocomplete/autocomplete_provider_unittest.cc
index fea4c84..d7342f5 100644
--- a/chrome/browser/autocomplete/autocomplete_provider_unittest.cc
+++ b/chrome/browser/autocomplete/autocomplete_provider_unittest.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/autocomplete/autocomplete_provider.h"
 
 #include "base/bind.h"
+#include "base/command_line.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/message_loop.h"
 #include "base/strings/string16.h"
@@ -21,6 +22,7 @@
 #include "chrome/browser/search_engines/template_url_service.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/common/chrome_notification_types.h"
+#include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/browser/notification_observer.h"
@@ -185,11 +187,13 @@
   void ResetControllerWithKeywordProvider();
   void RunExactKeymatchTest(bool allow_exact_keyword_match);
 
+  void CopyResults();
+
   AutocompleteResult result_;
   scoped_ptr<AutocompleteController> controller_;
 
  private:
-  // content::NotificationObserver
+  // content::NotificationObserver:
   virtual void Observe(int type,
                        const content::NotificationSource& source,
                        const content::NotificationDetails& details) OVERRIDE;
@@ -416,12 +420,16 @@
       controller_->result().default_match()->type);
 }
 
+void AutocompleteProviderTest::CopyResults() {
+  result_.CopyFrom(controller_->result());
+}
+
 void AutocompleteProviderTest::Observe(
     int type,
     const content::NotificationSource& source,
     const content::NotificationDetails& details) {
   if (controller_->done()) {
-    result_.CopyFrom(controller_->result());
+    CopyResults();
     base::MessageLoop::current()->Quit();
   }
 }
@@ -435,7 +443,7 @@
 
   // Make sure the default match gets set to the highest relevance match.  The
   // highest relevance matches should come from the second provider.
-  EXPECT_EQ(kResultsPerProvider * 2, result_.size());  // two providers
+  EXPECT_EQ(kResultsPerProvider * 2, result_.size());
   ASSERT_NE(result_.end(), result_.default_match());
   EXPECT_EQ(provider2, result_.default_match()->provider);
 }
@@ -445,7 +453,7 @@
   ResetControllerWithTestProviders(false, NULL, NULL);
   RunTest();
 
-  EXPECT_EQ(kResultsPerProvider * 2, result_.size());  // two providers
+  ASSERT_EQ(kResultsPerProvider * 2, result_.size());
 
   // Now, check the results from the second provider, as they should not have
   // assisted query stats set.
@@ -480,6 +488,21 @@
   RunExactKeymatchTest(false);
 }
 
+// Ensures matches from (only) the default search provider respect any extra
+// query params set on the command line.
+TEST_F(AutocompleteProviderTest, ExtraQueryParams) {
+  ResetControllerWithKeywordAndSearchProviders();
+  CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+      switches::kExtraSearchQueryParams, "a=b");
+  RunExactKeymatchTest(true);
+  CopyResults();
+  ASSERT_EQ(2U, result_.size());
+  EXPECT_EQ("http://keyword/test",
+            result_.match_at(0)->destination_url.possibly_invalid_spec());
+  EXPECT_EQ("http://defaultturl/k%20test?a=b",
+            result_.match_at(1)->destination_url.possibly_invalid_spec());
+}
+
 // Test that redundant associated keywords are removed.
 TEST_F(AutocompleteProviderTest, RedundantKeywordsIgnoredInResult) {
   ResetControllerWithKeywordProvider();
diff --git a/chrome/browser/autocomplete/autocomplete_result.cc b/chrome/browser/autocomplete/autocomplete_result.cc
index c723d3f..38a0edf 100644
--- a/chrome/browser/autocomplete/autocomplete_result.cc
+++ b/chrome/browser/autocomplete/autocomplete_result.cc
@@ -134,8 +134,8 @@
   default_match_ = begin();
 
   // Set the alternate nav URL.
-  alternate_nav_url_ = default_match_ == end() ? GURL() :
-      ComputeAlternateNavUrl(input, *default_match_);
+  alternate_nav_url_ = (default_match_ == end()) ?
+      GURL() : ComputeAlternateNavUrl(input, *default_match_);
 }
 
 bool AutocompleteResult::HasCopiedMatches() const {
@@ -207,10 +207,10 @@
 GURL AutocompleteResult::ComputeAlternateNavUrl(
     const AutocompleteInput& input,
     const AutocompleteMatch& match) {
-  return (input.type() == AutocompleteInput::UNKNOWN &&
-          AutocompleteMatch::IsSearchType(match.type) &&
-          match.transition != content::PAGE_TRANSITION_KEYWORD &&
-          input.canonicalized_url() != match.destination_url) ?
+  return ((input.type() == AutocompleteInput::UNKNOWN) &&
+          (AutocompleteMatch::IsSearchType(match.type)) &&
+          (match.transition != content::PAGE_TRANSITION_KEYWORD) &&
+          (input.canonicalized_url() != match.destination_url)) ?
       input.canonicalized_url() : GURL();
 }
 
diff --git a/chrome/browser/autocomplete/autocomplete_result.h b/chrome/browser/autocomplete/autocomplete_result.h
index 2da5320..57660f4 100644
--- a/chrome/browser/autocomplete/autocomplete_result.h
+++ b/chrome/browser/autocomplete/autocomplete_result.h
@@ -11,7 +11,7 @@
 
 #include "base/basictypes.h"
 #include "chrome/browser/autocomplete/autocomplete_match.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 class AutocompleteInput;
 class AutocompleteProvider;
@@ -120,7 +120,8 @@
 #endif
 
   // Compute the "alternate navigation URL" for a given match. This is obtained
-  // by interpreting the user input directly as a URL.
+  // by interpreting the user input directly as a URL. See comments on
+  // |alternate_nav_url_|.
   static GURL ComputeAlternateNavUrl(const AutocompleteInput& input,
                                      const AutocompleteMatch& match);
 
diff --git a/chrome/browser/autocomplete/bookmark_provider.cc b/chrome/browser/autocomplete/bookmark_provider.cc
index bee5367..3e8443f 100644
--- a/chrome/browser/autocomplete/bookmark_provider.cc
+++ b/chrome/browser/autocomplete/bookmark_provider.cc
@@ -10,7 +10,7 @@
 
 #include "base/metrics/histogram.h"
 #include "base/prefs/pref_service.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/autocomplete/autocomplete_result.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
@@ -188,7 +188,7 @@
   // use the sum to figure out a value between the base score and the maximum
   // score.
   //
-  // The factor for each term is calculated based on:
+  // The factor for each term is the product of:
   //
   //  1) how much of the bookmark's title has been matched by the term:
   //       (term length / title length).
@@ -209,8 +209,13 @@
   //     a partial factor of (14-6)/14 = 0.571 ).
   //
   // Once all term factors have been calculated they are summed. The resulting
-  // sum will never be greater than 1.0. This sum is then multiplied against
-  // the scoring range available, which is 299. The 299 is calculated by
+  // sum will never be greater than 1.0 because of the way the bookmark model
+  // matches and removes overlaps. (In particular, the bookmark model only
+  // matches terms to the beginning of words and it removes all overlapping
+  // matches, keeping only the longest. Together these mean that each
+  // character is included in at most one match. This property ensures the
+  // sum of factors is at most 1.) This sum is then multiplied against the
+  // scoring range available, which is 299. The 299 is calculated by
   // subtracting the minimum possible score, 900, from the maximum possible
   // score, 1199. This product, ranging from 0 to 299, is added to the minimum
   // possible score, 900, giving the preliminary score.
diff --git a/chrome/browser/autocomplete/builtin_provider_unittest.cc b/chrome/browser/autocomplete/builtin_provider_unittest.cc
index df80f56..bc524b5 100644
--- a/chrome/browser/autocomplete/builtin_provider_unittest.cc
+++ b/chrome/browser/autocomplete/builtin_provider_unittest.cc
@@ -11,8 +11,8 @@
 #include "chrome/browser/autocomplete/autocomplete_provider.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/base/testing_browser_process.h"
-#include "googleurl/src/gurl.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 class BuiltinProviderTest : public testing::Test {
  protected:
diff --git a/chrome/browser/autocomplete/history_provider.cc b/chrome/browser/autocomplete/history_provider.cc
index 6aa2fb1..d09b794 100644
--- a/chrome/browser/autocomplete/history_provider.cc
+++ b/chrome/browser/autocomplete/history_provider.cc
@@ -16,7 +16,7 @@
 #include "chrome/browser/net/url_fixer_upper.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/url_constants.h"
-#include "googleurl/src/url_util.h"
+#include "url/url_util.h"
 
 HistoryProvider::HistoryProvider(AutocompleteProviderListener* listener,
                                  Profile* profile,
diff --git a/chrome/browser/autocomplete/history_quick_provider.cc b/chrome/browser/autocomplete/history_quick_provider.cc
index 7be9e6a..1a5eb67 100644
--- a/chrome/browser/autocomplete/history_quick_provider.cc
+++ b/chrome/browser/autocomplete/history_quick_provider.cc
@@ -16,7 +16,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/autocomplete/autocomplete_result.h"
 #include "chrome/browser/autocomplete/history_url_provider.h"
 #include "chrome/browser/history/history_database.h"
@@ -39,11 +39,11 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_source.h"
 #include "content/public/browser/notification_types.h"
-#include "googleurl/src/url_parse.h"
-#include "googleurl/src/url_util.h"
 #include "net/base/escape.h"
 #include "net/base/net_util.h"
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+#include "url/url_parse.h"
+#include "url/url_util.h"
 
 using history::InMemoryURLIndex;
 using history::ScoredHistoryMatch;
diff --git a/chrome/browser/autocomplete/history_url_provider.cc b/chrome/browser/autocomplete/history_url_provider.cc
index fa9066f..e831193 100644
--- a/chrome/browser/autocomplete/history_url_provider.cc
+++ b/chrome/browser/autocomplete/history_url_provider.cc
@@ -29,11 +29,11 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
-#include "googleurl/src/gurl.h"
-#include "googleurl/src/url_parse.h"
-#include "googleurl/src/url_util.h"
 #include "net/base/net_util.h"
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+#include "url/gurl.h"
+#include "url/url_parse.h"
+#include "url/url_util.h"
 
 namespace {
 
diff --git a/chrome/browser/autocomplete/history_url_provider_unittest.cc b/chrome/browser/autocomplete/history_url_provider_unittest.cc
index 049bd7c..893402c 100644
--- a/chrome/browser/autocomplete/history_url_provider_unittest.cc
+++ b/chrome/browser/autocomplete/history_url_provider_unittest.cc
@@ -10,7 +10,7 @@
 #include "base/path_service.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/autocomplete/autocomplete_match.h"
 #include "chrome/browser/autocomplete/autocomplete_provider.h"
 #include "chrome/browser/autocomplete/autocomplete_provider_listener.h"
@@ -855,9 +855,8 @@
     AutocompleteInput input(ASCIIToUTF16(test_cases[i].input), string16::npos,
                             string16(), GURL("about:blank"),
                             false, false, true, AutocompleteInput::ALL_MATCHES);
-    AutocompleteMatch match =
-        HistoryURLProvider::SuggestExactInput(autocomplete_, input,
-                                              test_cases[i].trim_http);
+    AutocompleteMatch match = HistoryURLProvider::SuggestExactInput(
+        autocomplete_.get(), input, test_cases[i].trim_http);
     EXPECT_EQ(ASCIIToUTF16(test_cases[i].contents), match.contents);
     for (size_t match_index = 0; match_index < match.contents_class.size();
          ++match_index) {
diff --git a/chrome/browser/autocomplete/keyword_provider.cc b/chrome/browser/autocomplete/keyword_provider.cc
index 3726f8f..c2759dd 100644
--- a/chrome/browser/autocomplete/keyword_provider.cc
+++ b/chrome/browser/autocomplete/keyword_provider.cc
@@ -86,9 +86,8 @@
   // probably better rankings than the fraction of the keyword typed.  We should
   // always put any exact matches first no matter what, since the code in
   // Start() assumes this (and it makes sense).
-  bool operator()(const string16& keyword1,
-                  const string16& keyword2) const {
-    return keyword1.length() < keyword2.length();
+  bool operator()(const TemplateURL* t_url1, const TemplateURL* t_url2) const {
+    return t_url1->keyword().length() < t_url2->keyword().length();
   }
 };
 
@@ -216,8 +215,9 @@
     const string16& text,
     const string16& keyword,
     const AutocompleteInput& input) {
-  return CreateAutocompleteMatch(GetTemplateURLService(), keyword, input,
-      keyword.size(), SplitReplacementStringFromInput(text, true), 0);
+  return CreateAutocompleteMatch(
+      GetTemplateURLService()->GetTemplateURLForKeyword(keyword), input,
+      keyword.length(), SplitReplacementStringFromInput(text, true), 0);
 }
 
 void KeywordProvider::Start(const AutocompleteInput& input,
@@ -253,8 +253,6 @@
   if (!ExtractKeywordFromInput(input, &keyword, &remaining_input))
     return;
 
-  TemplateURLService* model = GetTemplateURLService();
-
   // Get the best matches for this keyword.
   //
   // NOTE: We could cache the previous keywords and reuse them here in the
@@ -265,27 +263,26 @@
   // TODO(pkasting): http://b/893701 We should remember the user's use of a
   // search query both from the autocomplete popup and from web pages
   // themselves.
-  std::vector<string16> keyword_matches;
-  model->FindMatchingKeywords(keyword,
-                              !remaining_input.empty(),
-                              &keyword_matches);
+  TemplateURLService::TemplateURLVector matches;
+  GetTemplateURLService()->FindMatchingKeywords(
+      keyword, !remaining_input.empty(), &matches);
 
-  for (std::vector<string16>::iterator i(keyword_matches.begin());
-       i != keyword_matches.end(); ) {
-    const TemplateURL* template_url = model->GetTemplateURLForKeyword(*i);
+  for (TemplateURLService::TemplateURLVector::iterator i(matches.begin());
+       i != matches.end(); ) {
+    const TemplateURL* template_url = *i;
 
     // Prune any extension keywords that are disallowed in incognito mode (if
     // we're incognito), or disabled.
     if (profile_ && template_url->IsExtensionKeyword()) {
       ExtensionService* service = extensions::ExtensionSystem::Get(profile_)->
           extension_service();
-      const extensions::Extension* extension = service->GetExtensionById(
-          template_url->GetExtensionId(), false);
+      const extensions::Extension* extension =
+          service->GetExtensionById(template_url->GetExtensionId(), false);
       bool enabled =
           extension && (!profile_->IsOffTheRecord() ||
                         service->IsIncognitoEnabled(extension->id()));
       if (!enabled) {
-        i = keyword_matches.erase(i);
+        i = matches.erase(i);
         continue;
       }
     }
@@ -293,22 +290,22 @@
     // Prune any substituting keywords if there is no substitution.
     if (template_url->SupportsReplacement() && remaining_input.empty() &&
         !input.allow_exact_keyword_match()) {
-      i = keyword_matches.erase(i);
+      i = matches.erase(i);
       continue;
     }
 
     ++i;
   }
-  if (keyword_matches.empty())
+  if (matches.empty())
     return;
-  std::sort(keyword_matches.begin(), keyword_matches.end(), CompareQuality());
+  std::sort(matches.begin(), matches.end(), CompareQuality());
 
   // Limit to one exact or three inexact matches, and mark them up for display
   // in the autocomplete popup.
   // Any exact match is going to be the highest quality match, and thus at the
   // front of our vector.
-  if (keyword_matches.front() == keyword) {
-    const TemplateURL* template_url = model->GetTemplateURLForKeyword(keyword);
+  if (matches.front()->keyword() == keyword) {
+    const TemplateURL* template_url = matches.front();
     const bool is_extension_keyword = template_url->IsExtensionKeyword();
 
     // Only create an exact match if |remaining_input| is empty or if
@@ -321,9 +318,8 @@
 
     // TODO(pkasting): We should probably check that if the user explicitly
     // typed a scheme, that scheme matches the one in |template_url|.
-    matches_.push_back(CreateAutocompleteMatch(model, keyword, input,
-                                               keyword.length(),
-                                               remaining_input, -1));
+    matches_.push_back(CreateAutocompleteMatch(
+        template_url, input, keyword.length(), remaining_input, -1));
 
     if (profile_ && is_extension_keyword) {
       if (input.matches_requested() == AutocompleteInput::ALL_MATCHES) {
@@ -364,15 +360,12 @@
       }
     }
   } else {
-    if (keyword_matches.size() > kMaxMatches) {
-      keyword_matches.erase(keyword_matches.begin() + kMaxMatches,
-                            keyword_matches.end());
-    }
-    for (std::vector<string16>::const_iterator i(keyword_matches.begin());
-         i != keyword_matches.end(); ++i) {
-      matches_.push_back(CreateAutocompleteMatch(model, *i,
-                                                 input, keyword.length(),
-                                                 remaining_input, -1));
+    if (matches.size() > kMaxMatches)
+      matches.erase(matches.begin() + kMaxMatches, matches.end());
+    for (TemplateURLService::TemplateURLVector::const_iterator i(
+         matches.begin()); i != matches.end(); ++i) {
+      matches_.push_back(CreateAutocompleteMatch(
+          *i, input, keyword.length(), remaining_input, -1));
     }
   }
 }
@@ -400,10 +393,79 @@
 }
 
 // static
-void KeywordProvider::FillInURLAndContents(
+int KeywordProvider::CalculateRelevance(AutocompleteInput::Type type,
+                                        bool complete,
+                                        bool supports_replacement,
+                                        bool prefer_keyword,
+                                        bool allow_exact_keyword_match) {
+  // This function is responsible for scoring suggestions of keywords
+  // themselves and the suggestion of the verbatim query on an
+  // extension keyword.  SearchProvider::CalculateRelevanceForKeywordVerbatim()
+  // scores verbatim query suggestions for non-extension keywords.
+  // These two functions are currently in sync, but there's no reason
+  // we couldn't decide in the future to score verbatim matches
+  // differently for extension and non-extension keywords.  If you
+  // make such a change, however, you should update this comment to
+  // describe it, so it's clear why the functions diverge.
+  if (!complete)
+    return (type == AutocompleteInput::URL) ? 700 : 450;
+  if (!supports_replacement || (allow_exact_keyword_match && prefer_keyword))
+    return 1500;
+  return (allow_exact_keyword_match && (type == AutocompleteInput::QUERY)) ?
+      1450 : 1100;
+}
+
+AutocompleteMatch KeywordProvider::CreateAutocompleteMatch(
+    const TemplateURL* template_url,
+    const AutocompleteInput& input,
+    size_t prefix_length,
     const string16& remaining_input,
-    const TemplateURL* element,
-    AutocompleteMatch* match) {
+    int relevance) {
+  DCHECK(template_url);
+  const bool supports_replacement =
+      template_url->url_ref().SupportsReplacement();
+
+  // Create an edit entry of "[keyword] [remaining input]".  This is helpful
+  // even when [remaining input] is empty, as the user can select the popup
+  // choice and immediately begin typing in query input.
+  const string16& keyword = template_url->keyword();
+  const bool keyword_complete = (prefix_length == keyword.length());
+  if (relevance < 0) {
+    relevance =
+        CalculateRelevance(input.type(), keyword_complete,
+                           // When the user wants keyword matches to take
+                           // preference, score them highly regardless of
+                           // whether the input provides query text.
+                           supports_replacement, input.prefer_keyword(),
+                           input.allow_exact_keyword_match());
+  }
+  AutocompleteMatch match(this, relevance, false,
+      supports_replacement ? AutocompleteMatchType::SEARCH_OTHER_ENGINE :
+                             AutocompleteMatchType::HISTORY_KEYWORD);
+  match.fill_into_edit = keyword;
+  if (!remaining_input.empty() || !keyword_complete || supports_replacement)
+    match.fill_into_edit.push_back(L' ');
+  match.fill_into_edit.append(remaining_input);
+  // If we wanted to set |result.inline_autocomplete_offset| correctly, we'd
+  // need CleanUserInputKeyword() to return the amount of adjustment it's made
+  // to the user's input.  Because right now inexact keyword matches can't score
+  // more highly than a "what you typed" match from one of the other providers,
+  // we just don't bother to do this, and leave inline autocompletion off.
+  match.inline_autocomplete_offset = string16::npos;
+
+  // Create destination URL and popup entry content by substituting user input
+  // into keyword templates.
+  FillInURLAndContents(remaining_input, template_url, &match);
+
+  match.keyword = keyword;
+  match.transition = content::PAGE_TRANSITION_KEYWORD;
+
+  return match;
+}
+
+void KeywordProvider::FillInURLAndContents(const string16& remaining_input,
+                                           const TemplateURL* element,
+                                           AutocompleteMatch* match) const {
   DCHECK(!element->short_name().empty());
   const TemplateURLRef& element_ref = element->url_ref();
   DCHECK(element_ref.IsValid());
@@ -435,97 +497,23 @@
     // input, but we rely on later canonicalization functions to do more
     // fixup to make the URL valid if necessary.
     DCHECK(element_ref.SupportsReplacement());
-    match->destination_url = GURL(element_ref.ReplaceSearchTerms(
-        TemplateURLRef::SearchTermsArgs(remaining_input)));
+    TemplateURLRef::SearchTermsArgs search_terms_args(remaining_input);
+    search_terms_args.append_extra_query_params =
+        element == GetTemplateURLService()->GetDefaultSearchProvider();
+    match->destination_url =
+        GURL(element_ref.ReplaceSearchTerms(search_terms_args));
     std::vector<size_t> content_param_offsets;
     match->contents.assign(l10n_util::GetStringFUTF16(message_id,
                                                       element->short_name(),
                                                       remaining_input,
                                                       &content_param_offsets));
-    if (content_param_offsets.size() == 2) {
-      AutocompleteMatch::ClassifyLocationInString(content_param_offsets[1],
-          remaining_input.length(), match->contents.length(),
-          ACMatchClassification::NONE, &match->contents_class);
-    } else {
-      // See comments on an identical NOTREACHED() in search_provider.cc.
-      NOTREACHED();
-    }
+    DCHECK_EQ(2U, content_param_offsets.size());
+    AutocompleteMatch::ClassifyLocationInString(content_param_offsets[1],
+        remaining_input.length(), match->contents.length(),
+        ACMatchClassification::NONE, &match->contents_class);
   }
 }
 
-// static
-int KeywordProvider::CalculateRelevance(AutocompleteInput::Type type,
-                                        bool complete,
-                                        bool supports_replacement,
-                                        bool prefer_keyword,
-                                        bool allow_exact_keyword_match) {
-  // This function is responsible for scoring suggestions of keywords
-  // themselves and the suggestion of the verbatim query on an
-  // extension keyword.  SearchProvider::CalculateRelevanceForKeywordVerbatim()
-  // scores verbatim query suggestions for non-extension keywords.
-  // These two functions are currently in sync, but there's no reason
-  // we couldn't decide in the future to score verbatim matches
-  // differently for extension and non-extension keywords.  If you
-  // make such a change, however, you should update this comment to
-  // describe it, so it's clear why the functions diverge.
-  if (!complete)
-    return (type == AutocompleteInput::URL) ? 700 : 450;
-  if (!supports_replacement || (allow_exact_keyword_match && prefer_keyword))
-    return 1500;
-  return (allow_exact_keyword_match && (type == AutocompleteInput::QUERY)) ?
-      1450 : 1100;
-}
-
-AutocompleteMatch KeywordProvider::CreateAutocompleteMatch(
-    TemplateURLService* model,
-    const string16& keyword,
-    const AutocompleteInput& input,
-    size_t prefix_length,
-    const string16& remaining_input,
-    int relevance) {
-  DCHECK(model);
-  // Get keyword data from data store.
-  TemplateURL* element = model->GetTemplateURLForKeyword(keyword);
-  DCHECK(element);
-  const bool supports_replacement = element->url_ref().SupportsReplacement();
-
-  // Create an edit entry of "[keyword] [remaining input]".  This is helpful
-  // even when [remaining input] is empty, as the user can select the popup
-  // choice and immediately begin typing in query input.
-  const bool keyword_complete = (prefix_length == keyword.length());
-  if (relevance < 0) {
-    relevance =
-        CalculateRelevance(input.type(), keyword_complete,
-                           // When the user wants keyword matches to take
-                           // preference, score them highly regardless of
-                           // whether the input provides query text.
-                           supports_replacement, input.prefer_keyword(),
-                           input.allow_exact_keyword_match());
-  }
-  AutocompleteMatch match(this, relevance, false,
-      supports_replacement ? AutocompleteMatchType::SEARCH_OTHER_ENGINE :
-                             AutocompleteMatchType::HISTORY_KEYWORD);
-  match.fill_into_edit.assign(keyword);
-  if (!remaining_input.empty() || !keyword_complete || supports_replacement)
-    match.fill_into_edit.push_back(L' ');
-  match.fill_into_edit.append(remaining_input);
-  // If we wanted to set |result.inline_autocomplete_offset| correctly, we'd
-  // need CleanUserInputKeyword() to return the amount of adjustment it's made
-  // to the user's input.  Because right now inexact keyword matches can't score
-  // more highly than a "what you typed" match from one of the other providers,
-  // we just don't bother to do this, and leave inline autocompletion off.
-  match.inline_autocomplete_offset = string16::npos;
-
-  // Create destination URL and popup entry content by substituting user input
-  // into keyword templates.
-  FillInURLAndContents(remaining_input, element, &match);
-
-  match.keyword = keyword;
-  match.transition = content::PAGE_TRANSITION_KEYWORD;
-
-  return match;
-}
-
 void KeywordProvider::Observe(int type,
                               const content::NotificationSource& source,
                               const content::NotificationDetails& details) {
@@ -567,10 +555,10 @@
         return;  // This is an old result. Just ignore.
 
       string16 keyword, remaining_input;
-      if (!ExtractKeywordFromInput(input, &keyword, &remaining_input)) {
-        NOTREACHED();
-        return;
-      }
+      bool result = ExtractKeywordFromInput(input, &keyword, &remaining_input);
+      DCHECK(result);
+      const TemplateURL* template_url =
+          model->GetTemplateURLForKeyword(keyword);
 
       // TODO(mpcomplete): consider clamping the number of suggestions to
       // AutocompleteProvider::kMaxMatches.
@@ -585,7 +573,7 @@
         int first_relevance = CalculateRelevance(input.type(), true, true,
             input.prefer_keyword(), input.allow_exact_keyword_match());
         extension_suggest_matches_.push_back(CreateAutocompleteMatch(
-            model, keyword, input, keyword.length(),
+            template_url, input, keyword.length(),
             UTF8ToUTF16(suggestion.content), first_relevance - (i + 1)));
 
         AutocompleteMatch* match = &extension_suggest_matches_.back();
diff --git a/chrome/browser/autocomplete/keyword_provider.h b/chrome/browser/autocomplete/keyword_provider.h
index c9caba1..7e582b4 100644
--- a/chrome/browser/autocomplete/keyword_provider.h
+++ b/chrome/browser/autocomplete/keyword_provider.h
@@ -110,12 +110,6 @@
                                       string16* keyword,
                                       string16* remaining_input);
 
-  // Fills in the "destination_url" and "contents" fields of |match| with the
-  // provided user input and keyword data.
-  static void FillInURLAndContents(const string16& remaining_input,
-                                   const TemplateURL* element,
-                                   AutocompleteMatch* match);
-
   // Determines the relevance for some input, given its type, whether the user
   // typed the complete keyword, and whether the user is in "prefer keyword
   // matches" mode, and whether the keyword supports replacement.
@@ -129,13 +123,18 @@
 
   // Creates a fully marked-up AutocompleteMatch from the user's input.
   // If |relevance| is negative, calculate a relevance based on heuristics.
-  AutocompleteMatch CreateAutocompleteMatch(TemplateURLService* model,
-                                            const string16& keyword,
+  AutocompleteMatch CreateAutocompleteMatch(const TemplateURL* template_url,
                                             const AutocompleteInput& input,
                                             size_t prefix_length,
                                             const string16& remaining_input,
                                             int relevance);
 
+  // Fills in the "destination_url" and "contents" fields of |match| with the
+  // provided user input and keyword data.
+  void FillInURLAndContents(const string16& remaining_input,
+                            const TemplateURL* element,
+                            AutocompleteMatch* match) const;
+
   void EnterExtensionKeywordMode(const std::string& extension_id);
   void MaybeEndExtensionKeywordMode();
 
diff --git a/chrome/browser/autocomplete/keyword_provider_unittest.cc b/chrome/browser/autocomplete/keyword_provider_unittest.cc
index 5dec594..45b5ac9 100644
--- a/chrome/browser/autocomplete/keyword_provider_unittest.cc
+++ b/chrome/browser/autocomplete/keyword_provider_unittest.cc
@@ -2,15 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/command_line.h"
 #include "base/message_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/autocomplete/autocomplete_match.h"
 #include "chrome/browser/autocomplete/keyword_provider.h"
 #include "chrome/browser/search_engines/template_url.h"
 #include "chrome/browser/search_engines/template_url_service.h"
+#include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/testing_browser_process.h"
-#include "googleurl/src/gurl.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 class KeywordProviderTest : public testing::Test {
  protected:
@@ -33,23 +35,25 @@
                ResultType AutocompleteMatch::* member);
 
  protected:
+  static const TemplateURLService::Initializer kTestData[];
+
   scoped_refptr<KeywordProvider> kw_provider_;
   scoped_ptr<TemplateURLService> model_;
 };
 
-void KeywordProviderTest::SetUp() {
-  static const TemplateURLService::Initializer kTestKeywordData[] = {
-    { "aa", "aa.com?foo=%s", "aa" },
-    { "aaaa", "http://aaaa/?aaaa=1&b=%s&c", "aaaa" },
-    { "aaaaa", "%s", "aaaaa" },
-    { "ab", "bogus URL %s", "ab" },
-    { "weasel", "weasel%sweasel", "weasel" },
-    { "www", " +%2B?=%sfoo ", "www" },
-    { "z", "%s=z", "z" },
-  };
+// static
+const TemplateURLService::Initializer KeywordProviderTest::kTestData[] = {
+  { "aa", "aa.com?foo=%s", "aa" },
+  { "aaaa", "http://aaaa/?aaaa=1&b=%s&c", "aaaa" },
+  { "aaaaa", "%s", "aaaaa" },
+  { "ab", "bogus URL %s", "ab" },
+  { "weasel", "weasel%sweasel", "weasel" },
+  { "www", " +%2B?=%sfoo ", "www" },
+  { "z", "%s=z", "z" },
+};
 
-  model_.reset(new TemplateURLService(kTestKeywordData,
-                                    arraysize(kTestKeywordData)));
+void KeywordProviderTest::SetUp() {
+  model_.reset(new TemplateURLService(kTestData, arraysize(kTestData)));
   kw_provider_ = new KeywordProvider(NULL, model_.get());
 }
 
@@ -134,22 +138,22 @@
 TEST_F(KeywordProviderTest, URL) {
   test_data<GURL> url_cases[] = {
     // No query input -> empty destination URL.
-    {ASCIIToUTF16("z"),               1, {GURL()}},
-    {ASCIIToUTF16("z    \t"),         1, {GURL()}},
+    {ASCIIToUTF16("z"),           1, {GURL()}},
+    {ASCIIToUTF16("z    \t"),     1, {GURL()}},
 
     // Check that tokenization only collapses whitespace between first tokens
     // and query input, but not rest of URL, is escaped.
-    {ASCIIToUTF16("w  bar +baz"),     2, {GURL(" +%2B?=bar+%2Bbazfoo "),
-                                          GURL("bar+%2Bbaz=z")}},
+    {ASCIIToUTF16("w  bar +baz"), 2, {GURL(" +%2B?=bar+%2Bbazfoo "),
+                                      GURL("bar+%2Bbaz=z")}},
 
     // Substitution should work with various locations of the "%s".
-    {ASCIIToUTF16("aaa 1a2b"),        2, {GURL("http://aaaa/?aaaa=1&b=1a2b&c"),
-                                          GURL("1a2b")}},
-    {ASCIIToUTF16("a 1 2 3"),         3, {GURL("aa.com?foo=1+2+3"),
-                                          GURL("bogus URL 1+2+3"),
-                                        GURL("http://aaaa/?aaaa=1&b=1+2+3&c")}},
-    {ASCIIToUTF16("www.w w"),         2, {GURL(" +%2B?=wfoo "),
-                                          GURL("weaselwweasel")}},
+    {ASCIIToUTF16("aaa 1a2b"),    2, {GURL("http://aaaa/?aaaa=1&b=1a2b&c"),
+                                      GURL("1a2b")}},
+    {ASCIIToUTF16("a 1 2 3"),     3, {GURL("aa.com?foo=1+2+3"),
+                                      GURL("bogus URL 1+2+3"),
+                                      GURL("http://aaaa/?aaaa=1&b=1+2+3&c")}},
+    {ASCIIToUTF16("www.w w"),     2, {GURL(" +%2B?=wfoo "),
+                                      GURL("weaselwweasel")}},
   };
 
   RunTest<GURL>(url_cases, arraysize(url_cases),
@@ -189,27 +193,7 @@
   };
 
   RunTest<string16>(contents_cases, arraysize(contents_cases),
-                        &AutocompleteMatch::contents);
-}
-
-TEST_F(KeywordProviderTest, DISABLED_Description) {
-  test_data<string16> description_cases[] = {
-    // Whole keyword should be returned for both exact and inexact matches.
-    {ASCIIToUTF16("z foo"),           1, {ASCIIToUTF16("(Keyword: z)")}},
-    {ASCIIToUTF16("a foo"),           3, {ASCIIToUTF16("(Keyword: aa)"),
-                                          ASCIIToUTF16("(Keyword: ab)"),
-                                          ASCIIToUTF16("(Keyword: aaaa)")}},
-    {ASCIIToUTF16("ftp://www.www w"), 0, {}},
-    {ASCIIToUTF16("http://www.ab w"), 1, {ASCIIToUTF16("(Keyword: ab)")}},
-
-    // Keyword should be returned regardless of query input.
-    {ASCIIToUTF16("z"),               1, {ASCIIToUTF16("(Keyword: z)")}},
-    {ASCIIToUTF16("z    \t"),         1, {ASCIIToUTF16("(Keyword: z)")}},
-    {ASCIIToUTF16("z   a   b   c++"), 1, {ASCIIToUTF16("(Keyword: z)")}},
-  };
-
-  RunTest<string16>(description_cases, arraysize(description_cases),
-                        &AutocompleteMatch::description);
+                    &AutocompleteMatch::contents);
 }
 
 TEST_F(KeywordProviderTest, AddKeyword) {
@@ -294,3 +278,19 @@
     EXPECT_EQ(cases[i].updated_cursor_position, input.cursor_position());
   }
 }
+
+// If extra query params are specified on the command line, they should be
+// reflected (only) in the default search provider's destination URL.
+TEST_F(KeywordProviderTest, ExtraQueryParams) {
+  CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+      switches::kExtraSearchQueryParams, "a=b");
+
+  test_data<GURL> url_cases[] = {
+    {ASCIIToUTF16("a 1 2 3"), 3, {GURL("aa.com?a=b&foo=1+2+3"),
+                                  GURL("bogus URL 1+2+3"),
+                                  GURL("http://aaaa/?aaaa=1&b=1+2+3&c")}},
+  };
+
+  RunTest<GURL>(url_cases, arraysize(url_cases),
+                &AutocompleteMatch::destination_url);
+}
diff --git a/chrome/browser/autocomplete/search_provider.cc b/chrome/browser/autocomplete/search_provider.cc
index 93f68ff..c5861c4 100644
--- a/chrome/browser/autocomplete/search_provider.cc
+++ b/chrome/browser/autocomplete/search_provider.cc
@@ -7,7 +7,6 @@
 #include <algorithm>
 #include <cmath>
 
-#include "base/auto_reset.h"
 #include "base/callback.h"
 #include "base/i18n/break_iterator.h"
 #include "base/i18n/case_conversion.h"
@@ -40,7 +39,6 @@
 #include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
-#include "googleurl/src/url_util.h"
 #include "grit/generated_resources.h"
 #include "net/base/escape.h"
 #include "net/base/load_flags.h"
@@ -50,9 +48,10 @@
 #include "net/url_request/url_fetcher.h"
 #include "net/url_request/url_request_status.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "url/url_util.h"
 
-using base::Time;
-using base::TimeDelta;
+
+// Helpers --------------------------------------------------------------------
 
 namespace {
 
@@ -115,35 +114,164 @@
 }
 
 
+// SearchProvider::Result -----------------------------------------------------
+
+SearchProvider::Result::Result(bool from_keyword_provider,
+                               int relevance,
+                               bool relevance_from_server)
+    : from_keyword_provider_(from_keyword_provider),
+      relevance_(relevance),
+      relevance_from_server_(relevance_from_server) {
+}
+
+SearchProvider::Result::~Result() {
+}
+
+
+// SearchProvider::SuggestResult ----------------------------------------------
+
+SearchProvider::SuggestResult::SuggestResult(const string16& suggestion,
+                                             bool from_keyword_provider,
+                                             int relevance,
+                                             bool relevance_from_server)
+    : Result(from_keyword_provider, relevance, relevance_from_server),
+      suggestion_(suggestion) {
+}
+
+SearchProvider::SuggestResult::~SuggestResult() {
+}
+
+bool SearchProvider::SuggestResult::IsInlineable(const string16& input) const {
+  return StartsWith(suggestion_, input, false);
+}
+
+int SearchProvider::SuggestResult::CalculateRelevance(
+    const AutocompleteInput& input,
+    bool keyword_provider_requested) const {
+  if (!from_keyword_provider_ && keyword_provider_requested)
+    return 100;
+  return ((input.type() == AutocompleteInput::URL) ? 300 : 600);
+}
+
+
+// SearchProvider::NavigationResult -------------------------------------------
+
+SearchProvider::NavigationResult::NavigationResult(
+    const AutocompleteProvider& provider,
+    const GURL& url,
+    const string16& description,
+    bool from_keyword_provider,
+    int relevance,
+    bool relevance_from_server)
+    : Result(from_keyword_provider, relevance, relevance_from_server),
+      url_(url),
+      formatted_url_(AutocompleteInput::FormattedStringWithEquivalentMeaning(
+          url, provider.StringForURLDisplay(url, true, false))),
+      description_(description) {
+  DCHECK(url_.is_valid());
+}
+
+SearchProvider::NavigationResult::~NavigationResult() {
+}
+
+bool SearchProvider::NavigationResult::IsInlineable(
+    const string16& input) const {
+  return URLPrefix::BestURLPrefix(formatted_url_, input) != NULL;
+}
+
+int SearchProvider::NavigationResult::CalculateRelevance(
+    const AutocompleteInput& input,
+    bool keyword_provider_requested) const {
+  return (from_keyword_provider_ || !keyword_provider_requested) ? 800 : 150;
+}
+
+
+// SearchProvider::CompareScoredResults ---------------------------------------
+
+class SearchProvider::CompareScoredResults {
+ public:
+  bool operator()(const Result& a, const Result& b) {
+    // Sort in descending relevance order.
+    return a.relevance() > b.relevance();
+  }
+};
+
+
+// SearchProvider::Results ----------------------------------------------------
+
+SearchProvider::Results::Results() : verbatim_relevance(-1) {
+}
+
+SearchProvider::Results::~Results() {
+}
+
+void SearchProvider::Results::Clear() {
+  suggest_results.clear();
+  navigation_results.clear();
+  verbatim_relevance = -1;
+}
+
+bool SearchProvider::Results::HasServerProvidedScores() const {
+  if (verbatim_relevance >= 0)
+    return true;
+
+  // Right now either all results of one type will be server-scored or they will
+  // all be locally scored, but in case we change this later, we'll just check
+  // them all.
+  for (SuggestResults::const_iterator i(suggest_results.begin());
+       i != suggest_results.end(); ++i) {
+    if (i->relevance_from_server())
+      return true;
+  }
+  for (NavigationResults::const_iterator i(navigation_results.begin());
+       i != navigation_results.end(); ++i) {
+    if (i->relevance_from_server())
+      return true;
+  }
+
+  return false;
+}
+
+
 // SearchProvider -------------------------------------------------------------
 
 // static
 const int SearchProvider::kDefaultProviderURLFetcherID = 1;
-// static
 const int SearchProvider::kKeywordProviderURLFetcherID = 2;
-// static
 int SearchProvider::kMinimumTimeBetweenSuggestQueriesMs = 100;
+const char SearchProvider::kRelevanceFromServerKey[] = "relevance_from_server";
+const char SearchProvider::kTrue[] = "true";
+const char SearchProvider::kFalse[] = "false";
+
+SearchProvider::SearchProvider(AutocompleteProviderListener* listener,
+                               Profile* profile)
+    : AutocompleteProvider(listener, profile,
+          AutocompleteProvider::TYPE_SEARCH),
+      providers_(TemplateURLServiceFactory::GetForProfile(profile)),
+      suggest_results_pending_(0),
+      field_trial_triggered_(false),
+      field_trial_triggered_in_session_(false),
+      omnibox_start_margin_(-1) {
+}
 
 // static
 AutocompleteMatch SearchProvider::CreateSearchSuggestion(
-    Profile* profile,
     AutocompleteProvider* autocomplete_provider,
-    const AutocompleteInput& input,
-    const string16& query_string,
-    const string16& input_text,
     int relevance,
     AutocompleteMatch::Type type,
-    int accepted_suggestion,
+    const TemplateURL* template_url,
+    const string16& query_string,
+    const string16& input_text,
+    const AutocompleteInput& input,
     bool is_keyword,
-    const string16& keyword,
-    int omnibox_start_margin) {
+    int accepted_suggestion,
+    int omnibox_start_margin,
+    bool append_extra_query_params) {
   AutocompleteMatch match(autocomplete_provider, relevance, false, type);
 
-  // Bail out now if we don't actually have a valid provider.
-  match.keyword = keyword;
-  const TemplateURL* provider_url = match.GetTemplateURL(profile, false);
-  if (provider_url == NULL)
+  if (!template_url)
     return match;
+  match.keyword = template_url->keyword();
 
   match.contents.assign(query_string);
   // We do intra-string highlighting for suggestions - the suggested segment
@@ -199,13 +327,15 @@
   }
   match.fill_into_edit.append(query_string);
 
-  const TemplateURLRef& search_url = provider_url->url_ref();
+  const TemplateURLRef& search_url = template_url->url_ref();
   DCHECK(search_url.SupportsReplacement());
   match.search_terms_args.reset(
       new TemplateURLRef::SearchTermsArgs(query_string));
   match.search_terms_args->original_query = input_text;
   match.search_terms_args->accepted_suggestion = accepted_suggestion;
   match.search_terms_args->omnibox_start_margin = omnibox_start_margin;
+  match.search_terms_args->append_extra_query_params =
+      append_extra_query_params;
   // This is the destination URL sans assisted query stats.  This must be set
   // so the AutocompleteController can properly de-dupe; the controller will
   // eventually overwrite it before it reaches the user.
@@ -219,113 +349,108 @@
   return match;
 }
 
-SearchProvider::SearchProvider(AutocompleteProviderListener* listener,
-                               Profile* profile)
-    : AutocompleteProvider(listener, profile,
-          AutocompleteProvider::TYPE_SEARCH),
-      providers_(TemplateURLServiceFactory::GetForProfile(profile)),
-      suggest_results_pending_(0),
-      instant_finalized_(false),
-      field_trial_triggered_(false),
-      field_trial_triggered_in_session_(false),
-      suppress_search_suggestions_(false),
-      omnibox_start_margin_(-1) {
-}
-
-void SearchProvider::FinalizeInstantQuery(const string16& input_text,
-                                          const InstantSuggestion& suggestion) {
-  if (done_ || instant_finalized_)
-    return;
-
-  instant_finalized_ = true;
-  UpdateDone();
-
-  if (input_text.empty()) {
-    // We only need to update the listener if we're actually done.
-    if (done_)
-      listener_->OnProviderUpdate(false);
-    return;
-  }
-
-  default_provider_suggestion_ = suggestion;
-
-  string16 adjusted_input_text(input_text);
-  AutocompleteInput::RemoveForcedQueryStringIfNecessary(input_.type(),
-                                                        &adjusted_input_text);
-
-  const string16 text = adjusted_input_text + suggestion.text;
-  bool results_updated = false;
-  // Remove any matches that are identical to |text|. We don't use the
-  // destination_url for comparison as it varies depending upon the index passed
-  // to TemplateURL::ReplaceSearchTerms.
-  for (ACMatches::iterator i = matches_.begin(); i != matches_.end();) {
-    if (((i->type == AutocompleteMatchType::SEARCH_HISTORY) ||
-         (i->type == AutocompleteMatchType::SEARCH_SUGGEST)) &&
-        (i->fill_into_edit == text)) {
-      i = matches_.erase(i);
-      results_updated = true;
-    } else {
-      ++i;
+void SearchProvider::AddProviderInfo(ProvidersInfo* provider_info) const {
+  provider_info->push_back(metrics::OmniboxEventProto_ProviderInfo());
+  metrics::OmniboxEventProto_ProviderInfo& new_entry = provider_info->back();
+  new_entry.set_provider(AsOmniboxEventProviderType());
+  new_entry.set_provider_done(done_);
+  std::vector<uint32> field_trial_hashes;
+  OmniboxFieldTrial::GetActiveSuggestFieldTrialHashes(&field_trial_hashes);
+  for (size_t i = 0; i < field_trial_hashes.size(); ++i) {
+    if (field_trial_triggered_)
+      new_entry.mutable_field_trial_triggered()->Add(field_trial_hashes[i]);
+    if (field_trial_triggered_in_session_) {
+      new_entry.mutable_field_trial_triggered_in_session()->Add(
+          field_trial_hashes[i]);
     }
   }
-
-  // Add the new Instant suggest result.
-  if (suggestion.type == INSTANT_SUGGESTION_SEARCH) {
-    // Instant has a query suggestion. Rank it higher than SEARCH_WHAT_YOU_TYPED
-    // so that it gets autocompleted.
-    const int verbatim_relevance = GetVerbatimRelevance();
-    int did_not_accept_default_suggestion =
-        default_results_.suggest_results.empty() ?
-        TemplateURLRef::NO_SUGGESTIONS_AVAILABLE :
-        TemplateURLRef::NO_SUGGESTION_CHOSEN;
-    MatchMap match_map;
-    AddMatchToMap(text, adjusted_input_text, verbatim_relevance + 1,
-                  AutocompleteMatchType::SEARCH_SUGGEST,
-                  did_not_accept_default_suggestion, false, &match_map);
-    if (!match_map.empty()) {
-      matches_.push_back(match_map.begin()->second);
-      results_updated = true;
-    }
-  } else {
-    // Instant has a URL suggestion. Rank it higher than URL_WHAT_YOU_TYPED so
-    // it gets autocompleted; use kNonURLVerbatimRelevance rather than
-    // verbatim_relevance so that the score does not change if the user keeps
-    // typing and the input changes from type UNKNOWN to URL.
-    matches_.push_back(NavigationToMatch(
-        NavigationResult(*this,
-                         GURL(UTF16ToUTF8(suggestion.text)),
-                         string16(),
-                         false,
-                         kNonURLVerbatimRelevance + 1)));
-    results_updated = true;
-  }
-
-  if (results_updated || done_)
-    listener_->OnProviderUpdate(results_updated);
 }
 
-void SearchProvider::ClearInstantSuggestion() {
-  default_provider_suggestion_ = InstantSuggestion();
-  if (done_ || instant_finalized_)
-    return;
-  instant_finalized_ = true;
-  UpdateMatches();
-  listener_->OnProviderUpdate(true);
-}
-
-void SearchProvider::SuppressSearchSuggestions() {
-  suppress_search_suggestions_ = true;
+void SearchProvider::ResetSession() {
+  field_trial_triggered_in_session_ = false;
 }
 
 void SearchProvider::SetOmniboxStartMargin(int omnibox_start_margin) {
   omnibox_start_margin_ = omnibox_start_margin;
 }
 
+SearchProvider::~SearchProvider() {
+}
+
+// static
+void SearchProvider::RemoveStaleResults(const string16& input,
+                                        int verbatim_relevance,
+                                        SuggestResults* suggest_results,
+                                        NavigationResults* navigation_results) {
+  DCHECK_GE(verbatim_relevance, 0);
+  // Keep pointers to the head of (the highest scoring elements of)
+  // |suggest_results| and |navigation_results|.  Iterate down the lists
+  // removing non-inlineable results in order of decreasing relevance
+  // scores.  Stop when the highest scoring element among those remaining
+  // is inlineable or the element is less than |verbatim_relevance|.
+  // This allows non-inlineable lower-scoring results to remain
+  // because (i) they are guaranteed to not be inlined and (ii)
+  // letting them remain reduces visual jank.  For instance, as the
+  // user types the mis-spelled query "fpobar" (for foobar), the
+  // suggestion "foobar" will be suggested on every keystroke.  If the
+  // SearchProvider always removes all non-inlineable results, the user will
+  // see visual jitter/jank as the result disappears and re-appears moments
+  // later as the suggest server returns results.
+  SuggestResults::iterator sug_it = suggest_results->begin();
+  NavigationResults::iterator nav_it = navigation_results->begin();
+  while ((sug_it != suggest_results->end()) ||
+         (nav_it != navigation_results->end())) {
+    const int sug_rel =
+        (sug_it != suggest_results->end()) ? sug_it->relevance() : -1;
+    const int nav_rel =
+        (nav_it != navigation_results->end()) ? nav_it->relevance() : -1;
+    if (std::max(sug_rel, nav_rel) < verbatim_relevance)
+      break;
+    if (sug_rel > nav_rel) {
+      // The current top result is a search suggestion.
+      if (sug_it->IsInlineable(input))
+        break;
+      sug_it = suggest_results->erase(sug_it);
+    } else if (sug_rel == nav_rel) {
+      // Have both results and they're tied.
+      const bool sug_inlineable = sug_it->IsInlineable(input);
+      const bool nav_inlineable = nav_it->IsInlineable(input);
+      if (!sug_inlineable)
+        sug_it = suggest_results->erase(sug_it);
+      if (!nav_inlineable)
+        nav_it = navigation_results->erase(nav_it);
+      if (sug_inlineable || nav_inlineable)
+        break;
+    } else {
+      // The current top result is a navigational suggestion.
+      if (nav_it->IsInlineable(input))
+        break;
+      nav_it = navigation_results->erase(nav_it);
+    }
+  }
+}
+
+// static
+int SearchProvider::CalculateRelevanceForKeywordVerbatim(
+    AutocompleteInput::Type type,
+    bool prefer_keyword) {
+  // This function is responsible for scoring verbatim query matches
+  // for non-extension keywords.  KeywordProvider::CalculateRelevance()
+  // scores verbatim query matches for extension keywords, as well as
+  // for keyword matches (i.e., suggestions of a keyword itself, not a
+  // suggestion of a query on a keyword search engine).  These two
+  // functions are currently in sync, but there's no reason we
+  // couldn't decide in the future to score verbatim matches
+  // differently for extension and non-extension keywords.  If you
+  // make such a change, however, you should update this comment to
+  // describe it, so it's clear why the functions diverge.
+  if (prefer_keyword)
+    return 1500;
+  return (type == AutocompleteInput::QUERY) ? 1450 : 1100;
+}
+
 void SearchProvider::Start(const AutocompleteInput& input,
                            bool minimal_changes) {
-  const bool suppress_search_suggestions = suppress_search_suggestions_;
-  suppress_search_suggestions_ = false;
-
   // Do our best to load the model as early as possible.  This will reduce
   // odds of having the model not ready when really needed (a non-empty input).
   TemplateURLService* model = providers_.template_url_service();
@@ -335,9 +460,6 @@
   matches_.clear();
   field_trial_triggered_ = false;
 
-  instant_finalized_ =
-      (input.matches_requested() != AutocompleteInput::ALL_MATCHES);
-
   // Can't return search/suggest results for bogus input or without a profile.
   if (!profile_ || (input.type() == AutocompleteInput::INVALID)) {
     Stop(false);
@@ -374,23 +496,9 @@
       keyword_provider->keyword() : string16());
   if (!minimal_changes ||
       !providers_.equal(default_provider_keyword, keyword_provider_keyword)) {
-    // If Instant has not come back with a suggestion, adjust the previous
-    // suggestion if possible. If |instant_finalized| is true, we are looking
-    // for synchronous matches only, so the suggestion is cleared.
-    if (instant_finalized_)
-      default_provider_suggestion_ = InstantSuggestion();
-    else
-      AdjustDefaultProviderSuggestion(input_.text(), input.text());
-
     // Cancel any in-flight suggest requests.
-    if (!done_) {
-      // The Stop(false) call below clears |default_provider_suggestion_|, but
-      // in this instance we do not want to clear cached results, so we
-      // restore it.
-      base::AutoReset<InstantSuggestion> reset(&default_provider_suggestion_,
-                                               InstantSuggestion());
+    if (!done_)
       Stop(false);
-    }
   }
 
   providers_.set(default_provider_keyword, keyword_provider_keyword);
@@ -413,141 +521,19 @@
 
   input_ = input;
 
-  if (!suppress_search_suggestions) {
-    DoHistoryQuery(minimal_changes);
-    StartOrStopSuggestQuery(minimal_changes);
-  }
+  DoHistoryQuery(minimal_changes);
+  StartOrStopSuggestQuery(minimal_changes);
   UpdateMatches();
 }
 
-SearchProvider::Result::Result(bool from_keyword_provider, int relevance)
-    : from_keyword_provider_(from_keyword_provider),
-      relevance_(relevance) {
-}
-
-SearchProvider::Result::~Result() {}
-
-SearchProvider::SuggestResult::SuggestResult(const string16& suggestion,
-                                             bool from_keyword_provider,
-                                             int relevance)
-    : Result(from_keyword_provider, relevance),
-      suggestion_(suggestion) {
-}
-
-SearchProvider::SuggestResult::~SuggestResult() {}
-
-bool SearchProvider::SuggestResult::IsInlineable(const string16& input) const {
-  return StartsWith(suggestion_, input, false);
-}
-
-int SearchProvider::SuggestResult::CalculateRelevance(
-    const AutocompleteInput& input,
-    bool keyword_provider_requested) const {
-  if (!from_keyword_provider_ && keyword_provider_requested)
-    return 100;
-  return ((input.type() == AutocompleteInput::URL) ? 300 : 600);
-}
-
-SearchProvider::NavigationResult::NavigationResult(
-    const AutocompleteProvider& provider,
-    const GURL& url,
-    const string16& description,
-    bool from_keyword_provider,
-    int relevance)
-    : Result(from_keyword_provider, relevance),
-      url_(url),
-      formatted_url_(AutocompleteInput::FormattedStringWithEquivalentMeaning(
-          url, provider.StringForURLDisplay(url, true, false))),
-      description_(description) {
-  DCHECK(url_.is_valid());
-}
-
-SearchProvider::NavigationResult::~NavigationResult() {}
-
-bool SearchProvider::NavigationResult::IsInlineable(
-    const string16& input) const {
-  return URLPrefix::BestURLPrefix(formatted_url_, input) != NULL;
-}
-
-int SearchProvider::NavigationResult::CalculateRelevance(
-    const AutocompleteInput& input,
-    bool keyword_provider_requested) const {
-  return (from_keyword_provider_ || !keyword_provider_requested) ? 800 : 150;
-}
-
-SearchProvider::Results::Results()
-    : has_suggested_relevance(false),
-      verbatim_relevance(-1) {
-}
-
-SearchProvider::Results::~Results() {
-}
-
-void SearchProvider::Results::Clear() {
-  suggest_results.clear();
-  navigation_results.clear();
-  has_suggested_relevance = false;
-  verbatim_relevance = -1;
-}
-
-class SearchProvider::CompareScoredResults {
- public:
-  bool operator()(const Result& a, const Result& b) {
-    // Sort in descending relevance order.
-    return a.relevance() > b.relevance();
-  }
-};
-
-void SearchProvider::Run() {
-  // Start a new request with the current input.
-  suggest_results_pending_ = 0;
-  time_suggest_request_sent_ = base::TimeTicks::Now();
-
-  default_fetcher_.reset(CreateSuggestFetcher(kDefaultProviderURLFetcherID,
-      providers_.GetDefaultProviderURL(), input_));
-  keyword_fetcher_.reset(CreateSuggestFetcher(kKeywordProviderURLFetcherID,
-      providers_.GetKeywordProviderURL(), keyword_input_));
-
-  // Both the above can fail if the providers have been modified or deleted
-  // since the query began.
-  if (suggest_results_pending_ == 0) {
-    UpdateDone();
-    // We only need to update the listener if we're actually done.
-    if (done_)
-      listener_->OnProviderUpdate(false);
-  }
-}
-
 void SearchProvider::Stop(bool clear_cached_results) {
   StopSuggest();
   done_ = true;
-  default_provider_suggestion_ = InstantSuggestion();
 
   if (clear_cached_results)
     ClearAllResults();
 }
 
-void SearchProvider::AddProviderInfo(ProvidersInfo* provider_info) const {
-  provider_info->push_back(metrics::OmniboxEventProto_ProviderInfo());
-  metrics::OmniboxEventProto_ProviderInfo& new_entry = provider_info->back();
-  new_entry.set_provider(AsOmniboxEventProviderType());
-  new_entry.set_provider_done(done_);
-  std::vector<uint32> field_trial_hashes;
-  OmniboxFieldTrial::GetActiveSuggestFieldTrialHashes(&field_trial_hashes);
-  for (size_t i = 0; i < field_trial_hashes.size(); ++i) {
-    if (field_trial_triggered_)
-      new_entry.mutable_field_trial_triggered()->Add(field_trial_hashes[i]);
-    if (field_trial_triggered_in_session_) {
-      new_entry.mutable_field_trial_triggered_in_session()->Add(
-          field_trial_hashes[i]);
-    }
-  }
-}
-
-void SearchProvider::ResetSession() {
-  field_trial_triggered_in_session_ = false;
-}
-
 void SearchProvider::OnURLFetchComplete(const net::URLFetcher* source) {
   DCHECK(!done_);
   suggest_results_pending_--;
@@ -576,9 +562,10 @@
   // Ensure the request succeeded and that the provider used is still available.
   // A verbatim match cannot be generated without this provider, causing errors.
   const bool request_succeeded =
-      source->GetStatus().is_success() && source->GetResponseCode() == 200 &&
-      ((is_keyword && providers_.GetKeywordProviderURL()) ||
-       (!is_keyword && providers_.GetDefaultProviderURL()));
+      source->GetStatus().is_success() && (source->GetResponseCode() == 200) &&
+      (is_keyword ?
+          providers_.GetKeywordProviderURL() :
+          providers_.GetDefaultProviderURL());
 
   // Record response time for suggest requests sent to Google.  We care
   // only about the common case: the Google default provider used in
@@ -587,7 +574,7 @@
   if (!is_keyword && default_url &&
       (TemplateURLPrepopulateData::GetEngineType(default_url->url()) ==
        SEARCH_ENGINE_GOOGLE)) {
-    const TimeDelta elapsed_time =
+    const base::TimeDelta elapsed_time =
         base::TimeTicks::Now() - time_suggest_request_sent_;
     if (request_succeeded) {
       UMA_HISTOGRAM_TIMES("Omnibox.SuggestRequest.Success.GoogleResponseTime",
@@ -611,11 +598,24 @@
     listener_->OnProviderUpdate(results_updated);
 }
 
-bool SearchProvider::IsNonInstantSearchDone() const {
-  return !timer_.IsRunning() && (suggest_results_pending_ == 0);
-}
+void SearchProvider::Run() {
+  // Start a new request with the current input.
+  suggest_results_pending_ = 0;
+  time_suggest_request_sent_ = base::TimeTicks::Now();
 
-SearchProvider::~SearchProvider() {
+  default_fetcher_.reset(CreateSuggestFetcher(kDefaultProviderURLFetcherID,
+      providers_.GetDefaultProviderURL(), input_));
+  keyword_fetcher_.reset(CreateSuggestFetcher(kKeywordProviderURLFetcherID,
+      providers_.GetKeywordProviderURL(), keyword_input_));
+
+  // Both the above can fail if the providers have been modified or deleted
+  // since the query began.
+  if (suggest_results_pending_ == 0) {
+    UpdateDone();
+    // We only need to update the listener if we're actually done.
+    if (done_)
+      listener_->OnProviderUpdate(false);
+  }
 }
 
 void SearchProvider::DoHistoryQuery(bool minimal_changes) {
@@ -688,7 +688,7 @@
   // To avoid flooding the suggest server, don't send a query until at
   // least 100 ms since the last query.
   base::TimeTicks next_suggest_time(time_suggest_request_sent_ +
-      TimeDelta::FromMilliseconds(kMinimumTimeBetweenSuggestQueriesMs));
+      base::TimeDelta::FromMilliseconds(kMinimumTimeBetweenSuggestQueriesMs));
   base::TimeTicks now(base::TimeTicks::Now());
   if (now >= next_suggest_time) {
     Run();
@@ -777,11 +777,11 @@
   // and ease in reasoning about the invariants involved, this code
   // removes stales results from the keyword provider and default
   // provider independently.
-  RemoveStaleResults(input_.text(), GetVerbatimRelevance(),
+  RemoveStaleResults(input_.text(), GetVerbatimRelevance(NULL),
                      &default_results_.suggest_results,
                      &default_results_.navigation_results);
   if (!keyword_input_.text().empty()) {
-    RemoveStaleResults(keyword_input_.text(), GetKeywordVerbatimRelevance(),
+    RemoveStaleResults(keyword_input_.text(), GetKeywordVerbatimRelevance(NULL),
                        &keyword_results_.suggest_results,
                        &keyword_results_.navigation_results);
   } else {
@@ -791,102 +791,11 @@
   }
 }
 
-// static
-void SearchProvider::RemoveStaleResults(const string16& input,
-                                        int verbatim_relevance,
-                                        SuggestResults* suggest_results,
-                                        NavigationResults* navigation_results) {
-  DCHECK_GE(verbatim_relevance, 0);
-  // Keep pointers to the head of (the highest scoring elements of)
-  // |suggest_results| and |navigation_results|.  Iterate down the lists
-  // removing non-inlineable results in order of decreasing relevance
-  // scores.  Stop when the highest scoring element among those remaining
-  // is inlineable or the element is less than |verbatim_relevance|.
-  // This allows non-inlineable lower-scoring results to remain
-  // because (i) they are guaranteed to not be inlined and (ii)
-  // letting them remain reduces visual jank.  For instance, as the
-  // user types the mis-spelled query "fpobar" (for foobar), the
-  // suggestion "foobar" will be suggested on every keystroke.  If the
-  // SearchProvider always removes all non-inlineable results, the user will
-  // see visual jitter/jank as the result disappears and re-appears moments
-  // later as the suggest server returns results.
-  SuggestResults::iterator sug_it = suggest_results->begin();
-  NavigationResults::iterator nav_it = navigation_results->begin();
-  while ((sug_it != suggest_results->end()) ||
-         (nav_it != navigation_results->end())) {
-    const int sug_rel =
-        (sug_it != suggest_results->end()) ? sug_it->relevance() : -1;
-    const int nav_rel =
-        (nav_it != navigation_results->end()) ? nav_it->relevance() : -1;
-    if (std::max(sug_rel, nav_rel) < verbatim_relevance)
-      break;
-    if (sug_rel > nav_rel) {
-      // The current top result is a search suggestion.
-      if (sug_it->IsInlineable(input))
-        break;
-      sug_it = suggest_results->erase(sug_it);
-    } else if (sug_rel == nav_rel) {
-      // Have both results and they're tied.
-      const bool sug_inlineable = sug_it->IsInlineable(input);
-      const bool nav_inlineable = nav_it->IsInlineable(input);
-      if (!sug_inlineable)
-        sug_it = suggest_results->erase(sug_it);
-      if (!nav_inlineable)
-        nav_it = navigation_results->erase(nav_it);
-      if (sug_inlineable || nav_inlineable)
-        break;
-    } else {
-      // The current top result is a navigational suggestion.
-      if (nav_it->IsInlineable(input))
-        break;
-      nav_it = navigation_results->erase(nav_it);
-    }
-  }
-}
-
-void SearchProvider::AdjustDefaultProviderSuggestion(
-    const string16& previous_input,
-    const string16& current_input) {
-  if (default_provider_suggestion_.type == INSTANT_SUGGESTION_URL) {
-    // Description and relevance do not matter in the check for staleness.
-    NavigationResult result(*this,
-                            GURL(default_provider_suggestion_.text),
-                            string16(),
-                            false,
-                            100);
-    // If navigation suggestion is stale, clear |default_provider_suggestion_|.
-    if (!result.IsInlineable(current_input))
-      default_provider_suggestion_ = InstantSuggestion();
-  } else {
-    DCHECK(default_provider_suggestion_.type == INSTANT_SUGGESTION_SEARCH);
-    // InstantSuggestion of type SEARCH contain only the suggested text, and not
-    // the full text of the query. This looks at the current and previous input
-    // to determine if the user is typing forward, and if the new input is
-    // contained in |default_provider_suggestion_|. If so, the suggestion is
-    // adjusted and can be kept. Otherwise, it is reset.
-    if (!previous_input.empty() &&
-        StartsWith(current_input, previous_input, false)) {
-      // User is typing forward; verify if new input is part of the suggestion.
-      const string16 new_text = string16(current_input, previous_input.size());
-      if (StartsWith(default_provider_suggestion_.text, new_text, false)) {
-        // New input is a prefix to the previous suggestion, adjust the
-        // suggestion to strip the prefix.
-        default_provider_suggestion_.text.erase(0, new_text.size());
-        return;
-      }
-    }
-    // If we are here, the search suggestion is stale; reset it.
-    default_provider_suggestion_ = InstantSuggestion();
-  }
-}
-
 void SearchProvider::ApplyCalculatedRelevance() {
   ApplyCalculatedSuggestRelevance(&keyword_results_.suggest_results);
   ApplyCalculatedSuggestRelevance(&default_results_.suggest_results);
   ApplyCalculatedNavigationRelevance(&keyword_results_.navigation_results);
   ApplyCalculatedNavigationRelevance(&default_results_.navigation_results);
-  default_results_.has_suggested_relevance = false;
-  keyword_results_.has_suggested_relevance = false;
   default_results_.verbatim_relevance = -1;
   keyword_results_.verbatim_relevance = -1;
 }
@@ -897,6 +806,7 @@
     result.set_relevance(
         result.CalculateRelevance(input_, providers_.has_keyword_provider()) +
         (list->size() - i - 1));
+    result.set_relevance_from_server(false);
   }
 }
 
@@ -907,6 +817,7 @@
     result.set_relevance(
         result.CalculateRelevance(input_, providers_.has_keyword_provider()) +
         (list->size() - i - 1));
+    result.set_relevance_from_server(false);
   }
 }
 
@@ -959,7 +870,6 @@
 
   // Reset suggested relevance information from the default provider.
   Results* results = is_keyword ? &keyword_results_ : &default_results_;
-  results->has_suggested_relevance = false;
   results->verbatim_relevance = -1;
 
   // 5th element: Optional key-value pairs from the Suggest server.
@@ -1006,13 +916,13 @@
       if (url.is_valid()) {
         if (descriptions != NULL)
           descriptions->GetString(index, &title);
-        results->navigation_results.push_back(
-            NavigationResult(*this, url, title, is_keyword, relevance));
+        results->navigation_results.push_back(NavigationResult(
+            *this, url, title, is_keyword, relevance, true));
       }
     } else {
       // TODO(kochi): Improve calculator result presentation.
       results->suggest_results.push_back(
-          SuggestResult(result, is_keyword, relevance));
+          SuggestResult(result, is_keyword, relevance, true));
     }
   }
 
@@ -1020,8 +930,6 @@
   if (relevances == NULL) {
     ApplyCalculatedSuggestRelevance(&results->suggest_results);
     ApplyCalculatedNavigationRelevance(&results->navigation_results);
-  } else {
-    results->has_suggested_relevance = true;
   }
   // Keep the result lists sorted.
   const CompareScoredResults comparator = CompareScoredResults();
@@ -1038,19 +946,21 @@
   // Convert all the results to matches and add them to a map, so we can keep
   // the most relevant match for each result.
   MatchMap map;
-  const Time no_time;
+  const base::Time no_time;
   int did_not_accept_keyword_suggestion =
       keyword_results_.suggest_results.empty() ?
       TemplateURLRef::NO_SUGGESTIONS_AVAILABLE :
       TemplateURLRef::NO_SUGGESTION_CHOSEN;
 
-  int verbatim_relevance = GetVerbatimRelevance();
+  bool relevance_from_server;
+  int verbatim_relevance = GetVerbatimRelevance(&relevance_from_server);
   int did_not_accept_default_suggestion =
       default_results_.suggest_results.empty() ?
       TemplateURLRef::NO_SUGGESTIONS_AVAILABLE :
       TemplateURLRef::NO_SUGGESTION_CHOSEN;
   if (verbatim_relevance > 0) {
     AddMatchToMap(input_.text(), input_.text(), verbatim_relevance,
+                  relevance_from_server,
                   AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,
                   did_not_accept_default_suggestion, false, &map);
   }
@@ -1063,24 +973,17 @@
     // to the keyword verbatim search query.  Do not create other matches
     // of type SEARCH_OTHER_ENGINE.
     if (keyword_url && !keyword_url->IsExtensionKeyword()) {
-      const int keyword_verbatim_relevance = GetKeywordVerbatimRelevance();
+      bool keyword_relevance_from_server;
+      const int keyword_verbatim_relevance =
+          GetKeywordVerbatimRelevance(&keyword_relevance_from_server);
       if (keyword_verbatim_relevance > 0) {
         AddMatchToMap(keyword_input_.text(), keyword_input_.text(),
-                      keyword_verbatim_relevance,
+                      keyword_verbatim_relevance, keyword_relevance_from_server,
                       AutocompleteMatchType::SEARCH_OTHER_ENGINE,
                       did_not_accept_keyword_suggestion, true, &map);
       }
     }
   }
-  const size_t verbatim_matches_size = map.size();
-  if (!default_provider_suggestion_.text.empty() &&
-      default_provider_suggestion_.type == INSTANT_SUGGESTION_SEARCH &&
-      !input_.prevent_inline_autocomplete())
-    AddMatchToMap(input_.text() + default_provider_suggestion_.text,
-                  input_.text(), verbatim_relevance + 1,
-                  AutocompleteMatchType::SEARCH_SUGGEST,
-                  did_not_accept_default_suggestion, false, &map);
-
   AddHistoryResultsToMap(keyword_history_results_, true,
                          did_not_accept_keyword_suggestion, &map);
   AddHistoryResultsToMap(default_history_results_, false,
@@ -1089,34 +992,49 @@
   AddSuggestResultsToMap(keyword_results_.suggest_results, &map);
   AddSuggestResultsToMap(default_results_.suggest_results, &map);
 
-  // Now add the most relevant matches from the map to |matches_|.
-  matches_.clear();
+  ACMatches matches;
   for (MatchMap::const_iterator i(map.begin()); i != map.end(); ++i)
-    matches_.push_back(i->second);
+    matches.push_back(i->second);
 
-  if (!default_provider_suggestion_.text.empty() &&
-      default_provider_suggestion_.type == INSTANT_SUGGESTION_URL &&
-      !input_.prevent_inline_autocomplete()) {
-    // See comment in FinalizeInstantQuery() for why we don't use
-    // |verbatim_relevance| here.
-    matches_.push_back(NavigationToMatch(
-        NavigationResult(*this,
-                         GURL(UTF16ToUTF8(default_provider_suggestion_.text)),
-                         string16(),
-                         false,
-                         kNonURLVerbatimRelevance + 1)));
+  AddNavigationResultsToMatches(keyword_results_.navigation_results, &matches);
+  AddNavigationResultsToMatches(default_results_.navigation_results, &matches);
+
+  // Now add the most relevant matches to |matches_|.  We take up to kMaxMatches
+  // suggest/navsuggest matches, regardless of origin.  If Instant Extended is
+  // enabled and we have server-provided (and thus hopefully more accurate)
+  // scores for some suggestions, we allow more of those, until we reach
+  // AutocompleteResult::kMaxMatches total matches (that is, enough to fill the
+  // whole popup).
+  //
+  // We will always return any verbatim matches, no matter how we obtained their
+  // scores, unless we have already accepted AutocompleteResult::kMaxMatches
+  // higher-scoring matches under the conditions above.
+  std::sort(matches.begin(), matches.end(), &AutocompleteMatch::MoreRelevant);
+  matches_.clear();
+
+  size_t num_suggestions = 0;
+  for (ACMatches::const_iterator i(matches.begin());
+       (i != matches.end()) &&
+           (matches_.size() < AutocompleteResult::kMaxMatches);
+       ++i) {
+    // SEARCH_OTHER_ENGINE is only used in the SearchProvider for the keyword
+    // verbatim result, so this condition basically means "if this match is a
+    // suggestion of some sort".
+    if ((i->type != AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED) &&
+        (i->type != AutocompleteMatchType::SEARCH_OTHER_ENGINE)) {
+      // If we've already hit the limit on non-server-scored suggestions, and
+      // this isn't a server-scored suggestion we can add, skip it.
+      if ((num_suggestions >= kMaxMatches) &&
+          (!chrome::IsInstantExtendedAPIEnabled() ||
+           (i->GetAdditionalInfo(kRelevanceFromServerKey) != kTrue))) {
+        continue;
+      }
+
+      ++num_suggestions;
+    }
+
+    matches_.push_back(*i);
   }
-  AddNavigationResultsToMatches(keyword_results_.navigation_results, true);
-  AddNavigationResultsToMatches(default_results_.navigation_results, false);
-
-  // Allow additional match(es) for verbatim results if present.
-  const size_t max_total_matches = kMaxMatches + verbatim_matches_size;
-  std::partial_sort(matches_.begin(),
-      matches_.begin() + std::min(max_total_matches, matches_.size()),
-      matches_.end(), &AutocompleteMatch::MoreRelevant);
-
-  if (matches_.size() > max_total_matches)
-    matches_.resize(max_total_matches);
 }
 
 bool SearchProvider::IsTopMatchNavigationInKeywordMode() const {
@@ -1153,7 +1071,6 @@
   // not create any other match of type SEARCH_OTHER_ENGINE.
   return
       matches_.front().type != AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED &&
-      matches_.front().type != AutocompleteMatchType::URL_WHAT_YOU_TYPED &&
       matches_.front().type != AutocompleteMatchType::SEARCH_OTHER_ENGINE &&
       matches_.front().inline_autocomplete_offset == string16::npos &&
       matches_.front().fill_into_edit != input_.text();
@@ -1164,10 +1081,8 @@
 
   // Check constraints that may be violated by suggested relevances.
   if (!matches_.empty() &&
-      (default_results_.has_suggested_relevance ||
-       default_results_.verbatim_relevance >= 0 ||
-       keyword_results_.has_suggested_relevance ||
-       keyword_results_.verbatim_relevance >= 0)) {
+      (default_results_.HasServerProvidedScores() ||
+       keyword_results_.HasServerProvidedScores())) {
     // These blocks attempt to repair undesirable behavior by suggested
     // relevances with minimal impact, preserving other suggested relevances.
     if (IsTopMatchNavigationInKeywordMode()) {
@@ -1204,11 +1119,10 @@
       ConvertResultsToAutocompleteMatches();
     }
     if (IsTopMatchNotInlinable()) {
-      // Disregard suggested relevances if the top match is not a verbatim
-      // match, inlinable, or URL_WHAT_YOU_TYPED (which may be top match
-      // regardless of inlining).  For example, input "foo" should not
-      // invoke a search for "bar", which would happen if the "bar" search
-      // match outranked all other matches.
+      // Disregard suggested relevances if the top match is not a verbatim match
+      // or inlinable.  For example, input "foo" should not invoke a search for
+      // "bar", which would happen if the "bar" search match outranked all other
+      // matches.
       ApplyCalculatedRelevance();
       ConvertResultsToAutocompleteMatches();
     }
@@ -1224,22 +1138,14 @@
 
 void SearchProvider::AddNavigationResultsToMatches(
     const NavigationResults& navigation_results,
-    bool is_keyword) {
-  if (navigation_results.empty())
-    return;
-
-  if (is_keyword ?
-          keyword_results_.has_suggested_relevance :
-          default_results_.has_suggested_relevance) {
-    for (NavigationResults::const_iterator it = navigation_results.begin();
-         it != navigation_results.end(); ++it)
-      matches_.push_back(NavigationToMatch(*it));
-  } else {
-    // Pick the highest-scoring element only in absence of the
-    // suggested relevance scores.  (The results are already sorted.)
-    // TODO(kochi|msw): Add more navigational results if they get more
-    //                  meaningful relevance values; see http://b/1170574.
-    matches_.push_back(NavigationToMatch(navigation_results.front()));
+    ACMatches* matches) {
+  for (NavigationResults::const_iterator it = navigation_results.begin();
+        it != navigation_results.end(); ++it) {
+    matches->push_back(NavigationToMatch(*it));
+    // In the absence of suggested relevance scores, use only the single
+    // highest-scoring result.  (The results are already sorted by relevance.)
+    if (!it->relevance_from_server())
+      return;
   }
 }
 
@@ -1278,7 +1184,7 @@
                                          is_keyword);
   for (SuggestResults::const_iterator i(scored_results.begin());
        i != scored_results.end(); ++i) {
-    AddMatchToMap(i->suggestion(), input_text, i->relevance(),
+    AddMatchToMap(i->suggestion(), input_text, i->relevance(), false,
                   AutocompleteMatchType::SEARCH_HISTORY,
                   did_not_accept_suggestion,
                   is_keyword, map);
@@ -1323,7 +1229,8 @@
 
     int relevance = CalculateRelevanceForHistory(i->time, is_keyword,
                                                  prevent_inline_autocomplete);
-    scored_results.push_back(SuggestResult(i->term, is_keyword, relevance));
+    scored_results.push_back(
+        SuggestResult(i->term, is_keyword, relevance, false));
   }
 
   // History returns results sorted for us.  However, we may have docked some
@@ -1350,11 +1257,12 @@
     const bool is_keyword = results[i].from_keyword_provider();
     const string16& input = is_keyword ? keyword_input_.text() : input_.text();
     AddMatchToMap(results[i].suggestion(), input, results[i].relevance(),
+                  results[i].relevance_from_server(),
                   AutocompleteMatchType::SEARCH_SUGGEST, i, is_keyword, map);
   }
 }
 
-int SearchProvider::GetVerbatimRelevance() const {
+int SearchProvider::GetVerbatimRelevance(bool* relevance_from_server) const {
   // Use the suggested verbatim relevance score if it is non-negative (valid),
   // if inline autocomplete isn't prevented (always show verbatim on backspace),
   // and if it won't suppress verbatim, leaving no default provider matches.
@@ -1363,14 +1271,16 @@
   // left unable to search using their default provider from the omnibox.
   // Check for results on each verbatim calculation, as results from older
   // queries (on previous input) may be trimmed for failing to inline new input.
-  if (default_results_.verbatim_relevance >= 0 &&
+  bool use_server_relevance =
+      (default_results_.verbatim_relevance >= 0) &&
       !input_.prevent_inline_autocomplete() &&
-      (default_results_.verbatim_relevance > 0 ||
+      ((default_results_.verbatim_relevance > 0) ||
        !default_results_.suggest_results.empty() ||
-       !default_results_.navigation_results.empty())) {
-    return default_results_.verbatim_relevance;
-  }
-  return CalculateRelevanceForVerbatim();
+       !default_results_.navigation_results.empty());
+  if (relevance_from_server)
+    *relevance_from_server = use_server_relevance;
+  return use_server_relevance ?
+      default_results_.verbatim_relevance : CalculateRelevanceForVerbatim();
 }
 
 int SearchProvider::CalculateRelevanceForVerbatim() const {
@@ -1396,7 +1306,8 @@
   }
 }
 
-int SearchProvider::GetKeywordVerbatimRelevance() const {
+int SearchProvider::GetKeywordVerbatimRelevance(
+    bool* relevance_from_server) const {
   // Use the suggested verbatim relevance score if it is non-negative (valid),
   // if inline autocomplete isn't prevented (always show verbatim on backspace),
   // and if it won't suppress verbatim, leaving no keyword provider matches.
@@ -1405,38 +1316,22 @@
   // left unable to search using their keyword provider from the omnibox.
   // Check for results on each verbatim calculation, as results from older
   // queries (on previous input) may be trimmed for failing to inline new input.
-  if (keyword_results_.verbatim_relevance >= 0 &&
+  bool use_server_relevance =
+      (keyword_results_.verbatim_relevance >= 0) &&
       !input_.prevent_inline_autocomplete() &&
-      (keyword_results_.verbatim_relevance > 0 ||
+      ((keyword_results_.verbatim_relevance > 0) ||
        !keyword_results_.suggest_results.empty() ||
-       !keyword_results_.navigation_results.empty())) {
-    return keyword_results_.verbatim_relevance;
-  }
-  return CalculateRelevanceForKeywordVerbatim(
-      keyword_input_.type(), keyword_input_.prefer_keyword());
-}
-
-// static
-int SearchProvider::CalculateRelevanceForKeywordVerbatim(
-    AutocompleteInput::Type type,
-    bool prefer_keyword) {
-  // This function is responsible for scoring verbatim query matches
-  // for non-extension keywords.  KeywordProvider::CalculateRelevance()
-  // scores verbatim query matches for extension keywords, as well as
-  // for keyword matches (i.e., suggestions of a keyword itself, not a
-  // suggestion of a query on a keyword search engine).  These two
-  // functions are currently in sync, but there's no reason we
-  // couldn't decide in the future to score verbatim matches
-  // differently for extension and non-extension keywords.  If you
-  // make such a change, however, you should update this comment to
-  // describe it, so it's clear why the functions diverge.
-  if (prefer_keyword)
-    return 1500;
-  return (type == AutocompleteInput::QUERY) ? 1450 : 1100;
+       !keyword_results_.navigation_results.empty());
+  if (relevance_from_server)
+    *relevance_from_server = use_server_relevance;
+  return use_server_relevance ?
+      keyword_results_.verbatim_relevance :
+      CalculateRelevanceForKeywordVerbatim(keyword_input_.type(),
+                                           keyword_input_.prefer_keyword());
 }
 
 int SearchProvider::CalculateRelevanceForHistory(
-    const Time& time,
+    const base::Time& time,
     bool is_keyword,
     bool prevent_inline_autocomplete) const {
   // The relevance of past searches falls off over time. There are two distinct
@@ -1445,7 +1340,7 @@
   // falls to 1300. If the second equation is used the relevance of a search 15
   // minutes ago is discounted 50 points, while the relevance of a search two
   // weeks ago is discounted 450 points.
-  double elapsed_time = std::max((Time::Now() - time).InSecondsF(), 0.);
+  double elapsed_time = std::max((base::Time::Now() - time).InSecondsF(), 0.0);
   bool is_primary_provider = is_keyword || !providers_.has_keyword_provider();
   if (is_primary_provider && !prevent_inline_autocomplete) {
     // Searches with the past two days get a different curve.
@@ -1473,34 +1368,27 @@
 void SearchProvider::AddMatchToMap(const string16& query_string,
                                    const string16& input_text,
                                    int relevance,
+                                   bool relevance_from_server,
                                    AutocompleteMatch::Type type,
                                    int accepted_suggestion,
                                    bool is_keyword,
                                    MatchMap* map) {
-  // With Instant Extended, we never want to inline autocomplete search queries
-  // -- they should always use grey text if they are to autocomplete at all. So
-  // we clamp non-verbatim results to just below the verbatim score to ensure
-  // that none of them are inline autocompleted.
-  if (type != AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED &&
-      type != AutocompleteMatchType::SEARCH_OTHER_ENGINE &&
-      chrome::IsInstantExtendedAPIEnabled()) {
-    relevance = std::min(kNonURLVerbatimRelevance - 1, relevance);
-  }
-
-  const string16& keyword = is_keyword ?
-      providers_.keyword_provider() : providers_.default_provider();
-  AutocompleteMatch match = CreateSearchSuggestion(profile_, this, input_,
-      query_string, input_text, relevance, type, accepted_suggestion,
-      is_keyword, keyword, omnibox_start_margin_);
+  const TemplateURL* template_url = is_keyword ?
+      providers_.GetKeywordProviderURL() : providers_.GetDefaultProviderURL();
+  AutocompleteMatch match = CreateSearchSuggestion(this, relevance, type,
+      template_url, query_string, input_text, input_, is_keyword,
+      accepted_suggestion, omnibox_start_margin_,
+      !is_keyword || providers_.default_provider().empty());
   if (!match.destination_url.is_valid())
     return;
+  match.RecordAdditionalInfo(kRelevanceFromServerKey,
+                             relevance_from_server ? kTrue : kFalse);
 
   // Try to add |match| to |map|.  If a match for |query_string| is already in
   // |map|, replace it if |match| is more relevant.
   // NOTE: Keep this ToLower() call in sync with url_database.cc.
-  const std::pair<MatchMap::iterator, bool> i = map->insert(
-      std::pair<string16, AutocompleteMatch>(
-          base::i18n::ToLower(query_string), match));
+  const std::pair<MatchMap::iterator, bool> i(
+      map->insert(std::make_pair(base::i18n::ToLower(query_string), match)));
   // NOTE: We purposefully do a direct relevance comparison here instead of
   // using AutocompleteMatch::MoreRelevant(), so that we'll prefer "items added
   // first" rather than "items alphabetically first" when the scores are equal.
@@ -1570,17 +1458,28 @@
   match.description = navigation.description();
   AutocompleteMatch::ClassifyMatchInString(input, match.description,
       ACMatchClassification::NONE, &match.description_class);
+
+  match.RecordAdditionalInfo(
+      kRelevanceFromServerKey,
+      navigation.relevance_from_server() ? kTrue : kFalse);
+
   return match;
 }
 
 void SearchProvider::DemoteKeywordNavigationMatchesPastTopQuery() {
   // First, determine the maximum score of any keyword query match (verbatim or
   // query suggestion).
-  int max_query_relevance = GetKeywordVerbatimRelevance();
+  bool relevance_from_server;
+  int max_query_relevance = GetKeywordVerbatimRelevance(&relevance_from_server);
   if (!keyword_results_.suggest_results.empty()) {
-    max_query_relevance =
-        std::max(keyword_results_.suggest_results.front().relevance(),
-                 max_query_relevance);
+    const SuggestResult& top_keyword = keyword_results_.suggest_results.front();
+    const int suggest_relevance = top_keyword.relevance();
+    if (suggest_relevance > max_query_relevance) {
+      max_query_relevance = suggest_relevance;
+      relevance_from_server = top_keyword.relevance_from_server();
+    } else if (suggest_relevance == max_query_relevance) {
+      relevance_from_server |= top_keyword.relevance_from_server();
+    }
   }
   // If no query is supposed to appear, then navigational matches cannot
   // be demoted past it.  Get rid of suggested relevance scores for
@@ -1604,12 +1503,12 @@
       return;
     max_query_relevance = std::max(max_query_relevance - 1, 0);
     it->set_relevance(max_query_relevance);
+    it->set_relevance_from_server(relevance_from_server);
   }
 }
 
 void SearchProvider::UpdateDone() {
   // We're done when the timer isn't running, there are no suggest queries
   // pending, and we're not waiting on Instant.
-  done_ = IsNonInstantSearchDone() &&
-      (instant_finalized_ || !chrome::IsInstantEnabled(profile_));
+  done_ = !timer_.IsRunning() && (suggest_results_pending_ == 0);
 }
diff --git a/chrome/browser/autocomplete/search_provider.h b/chrome/browser/autocomplete/search_provider.h
index 1251402..531825d 100644
--- a/chrome/browser/autocomplete/search_provider.h
+++ b/chrome/browser/autocomplete/search_provider.h
@@ -18,14 +18,13 @@
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/autocomplete/autocomplete_input.h"
 #include "chrome/browser/autocomplete/autocomplete_match.h"
 #include "chrome/browser/autocomplete/autocomplete_provider.h"
 #include "chrome/browser/history/history_types.h"
 #include "chrome/browser/search_engines/template_url.h"
-#include "chrome/common/instant_types.h"
 #include "net/url_request/url_fetcher_delegate.h"
 
 class Profile;
@@ -59,69 +58,45 @@
   // ID used in creating URLFetcher for keyword provider's suggest results.
   static const int kKeywordProviderURLFetcherID;
 
-  // Returns an AutocompleteMatch representing a search for |query_string|
-  // using the provider identified by |keyword|. |is_keyword| should be true if
-  // |input| represents a keyword search (even if it's for the default search
-  // provider). |input_text| (the original input text) and |accepted_suggestion|
-  // are used to generate Assisted Query Stats.
-  // Returns a match with an invalid destination_url in case of any errors.
-  static AutocompleteMatch CreateSearchSuggestion(
-      Profile* profile,
-      AutocompleteProvider* autocomplete_provider,
-      const AutocompleteInput& input,
-      const string16& query_string,
-      const string16& input_text,
-      int relevance,
-      AutocompleteMatch::Type type,
-      int accepted_suggestion,
-      bool is_keyword,
-      const string16& keyword,
-      int omnibox_start_margin);
-
   SearchProvider(AutocompleteProviderListener* listener, Profile* profile);
 
-  // Marks the instant query as done. If |input_text| is non-empty this changes
-  // the 'search what you typed' results text to |input_text| +
-  // |suggestion.text|. |input_text| is the text the user input into the edit.
-  // |input_text| differs from |input_.text()| if the input contained
-  // whitespace.
+  // Returns an AutocompleteMatch with the given |autocomplete_provider|,
+  // |relevance|, and |type|, which represents a search via |template_url| for
+  // |query_string|.  If |template_url| is NULL, returns a match with an invalid
+  // destination URL.
   //
-  // This method also marks the search provider as no longer needing to wait for
-  // the instant result.
-  void FinalizeInstantQuery(const string16& input_text,
-                            const InstantSuggestion& suggestion);
-  void ClearInstantSuggestion();
+  // |input_text| is the original user input, which may differ from
+  // |query_string|; e.g. the user typed "foo" and got a search suggestion of
+  // "food", which we're now marking up.  This is used to highlight portions of
+  // the match contents to distinguish locally-typed text from suggested text.
+  //
+  // |input| and |is_keyword| are necessary for various other details, like
+  // whether we should allow inline autocompletion and what the transition type
+  // should be.  |accepted_suggestion| and |omnibox_start_margin| are used along
+  // with |input_text| to generate Assisted Query Stats.
+  // |append_extra_query_params| should be set if |template_url| is the default
+  // search engine, so the destination URL will contain any
+  // command-line-specified query params.
+  static AutocompleteMatch CreateSearchSuggestion(
+      AutocompleteProvider* autocomplete_provider,
+      int relevance,
+      AutocompleteMatch::Type type,
+      const TemplateURL* template_url,
+      const string16& query_string,
+      const string16& input_text,
+      const AutocompleteInput& input,
+      bool is_keyword,
+      int accepted_suggestion,
+      int omnibox_start_margin,
+      bool append_extra_query_params);
 
-  // If called, SearchProvider will not fetch any search suggestions for the
-  // next call to Start(). Used with InstantExtended where Instant fetches its
-  // own search suggestions.
-  //
-  // Note that this only applies to the next call to Start() and so this must be
-  // called repeatedly before Start() if you wish to continually suppress search
-  // suggestions.
-  void SuppressSearchSuggestions();
+  // AutocompleteProvider:
+  virtual void AddProviderInfo(ProvidersInfo* provider_info) const OVERRIDE;
+  virtual void ResetSession() OVERRIDE;
 
   // Update the omnibox start margin used to generate search suggestion URLs.
   void SetOmniboxStartMargin(int omnibox_start_margin);
 
-  // AutocompleteProvider:
-  virtual void Start(const AutocompleteInput& input,
-                     bool minimal_changes) OVERRIDE;
-  virtual void Stop(bool clear_cached_results) OVERRIDE;
-
-  // Adds search-provider-specific information to omnibox event logs.
-  virtual void AddProviderInfo(ProvidersInfo* provider_info) const OVERRIDE;
-
-  // Sets |field_trial_triggered_in_session_| to false.
-  virtual void ResetSession() OVERRIDE;
-
-  // net::URLFetcherDelegate
-  virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
-
-  // Returns whether the provider is done processing the query with the
-  // exception of waiting for Instant to finish.
-  bool IsNonInstantSearchDone() const;
-
   bool field_trial_triggered_in_session() const {
     return field_trial_triggered_in_session_;
   }
@@ -138,12 +113,6 @@
   FRIEND_TEST_ALL_PREFIXES(SearchProviderTest, SuggestRelevanceExperiment);
   FRIEND_TEST_ALL_PREFIXES(AutocompleteProviderTest, GetDestinationURL);
 
-  // The amount of time to wait before sending a new suggest request after
-  // the previous one.
-  static int kMinimumTimeBetweenSuggestQueriesMs;
-
-  virtual ~SearchProvider();
-
   // Manages the providers (TemplateURLs) used by SearchProvider. Two providers
   // may be used:
   // . The default provider. This corresponds to the user's default search
@@ -200,9 +169,9 @@
   //           highly fragmented SearchProvider logic for each Result type.
   class Result {
    public:
-    // Takes whether the result is from the keyword provider and its
-    // assigned relevance score.
-    explicit Result(bool from_keyword_provider, int relevance);
+    Result(bool from_keyword_provider,
+           int relevance,
+           bool relevance_from_server);
     virtual ~Result();
 
     bool from_keyword_provider() const { return from_keyword_provider_; }
@@ -210,6 +179,11 @@
     int relevance() const { return relevance_; }
     void set_relevance(int relevance) { relevance_ = relevance; }
 
+    bool relevance_from_server() const { return relevance_from_server_; }
+    void set_relevance_from_server(bool relevance_from_server) {
+      relevance_from_server_ = relevance_from_server;
+    }
+
     // Returns if this result is inlineable against the current input |input|.
     // Non-inlineable results are stale.
     virtual bool IsInlineable(const string16& input) const = 0;
@@ -227,13 +201,22 @@
 
     // The relevance score.
     int relevance_;
+
+   private:
+    // Whether this result's relevance score was fully or partly calculated
+    // based on server information, and thus is assumed to be more accurate.
+    // This is ultimately used in
+    // SearchProvider::ConvertResultsToAutocompleteMatches(), see comments
+    // there.
+    bool relevance_from_server_;
   };
 
   class SuggestResult : public Result {
    public:
     SuggestResult(const string16& suggestion,
                   bool from_keyword_provider,
-                  int relevance);
+                  int relevance,
+                  bool relevance_from_server);
     virtual ~SuggestResult();
 
     const string16& suggestion() const { return suggestion_; }
@@ -257,14 +240,13 @@
                      const GURL& url,
                      const string16& description,
                      bool from_keyword_provider,
-                     int relevance);
+                     int relevance,
+                     bool relevance_from_server);
     virtual ~NavigationResult();
 
     const GURL& url() const { return url_; }
     const string16& description() const { return description_; }
-    const string16& formatted_url() const {
-      return formatted_url_;
-    }
+    const string16& formatted_url() const { return formatted_url_; }
 
     // Result:
     virtual bool IsInlineable(const string16& input) const OVERRIDE;
@@ -284,30 +266,36 @@
     string16 description_;
   };
 
+  class CompareScoredResults;
+
   typedef std::vector<SuggestResult> SuggestResults;
   typedef std::vector<NavigationResult> NavigationResults;
+  typedef std::vector<history::KeywordSearchTermVisit> HistoryResults;
+  typedef std::map<string16, AutocompleteMatch> MatchMap;
 
   // A simple structure bundling most of the information (including
   // both SuggestResults and NavigationResults) returned by a call to
   // the suggest server.
+  //
+  // This has to be declared after the typedefs since it relies on some of them.
   struct Results {
     Results();
     ~Results();
 
     // Clears |suggest_results| and |navigation_results| and resets
-    // |has_suggested_relevance| and |verbatim_relevance| to default
-    // values (false and -1 (implies unset), respectively).
+    // |verbatim_relevance| to -1 (implies unset).
     void Clear();
 
+    // Returns whether any of the results (including verbatim) have
+    // server-provided scores.
+    bool HasServerProvidedScores() const;
+
     // Query suggestions sorted by relevance score.
     SuggestResults suggest_results;
 
     // Navigational suggestions sorted by relevance score.
     NavigationResults navigation_results;
 
-    // Flag indicating server supplied relevance score.
-    bool has_suggested_relevance;
-
     // The server supplied verbatim relevance scores. Negative values
     // indicate that there is no suggested score; a value of 0
     // suppresses the verbatim result.
@@ -317,10 +305,27 @@
     DISALLOW_COPY_AND_ASSIGN(Results);
   };
 
-  typedef std::vector<history::KeywordSearchTermVisit> HistoryResults;
-  typedef std::map<string16, AutocompleteMatch> MatchMap;
+  virtual ~SearchProvider();
 
-  class CompareScoredResults;
+  // Removes non-inlineable results until either the top result can inline
+  // autocomplete the current input or verbatim outscores the top result.
+  static void RemoveStaleResults(const string16& input,
+                                 int verbatim_relevance,
+                                 SuggestResults* suggest_results,
+                                 NavigationResults* navigation_results);
+
+  // Calculates the relevance score for the keyword verbatim result (if the
+  // input matches one of the profile's keyword).
+  static int CalculateRelevanceForKeywordVerbatim(AutocompleteInput::Type type,
+                                                  bool prefer_keyword);
+
+  // AutocompleteProvider:
+  virtual void Start(const AutocompleteInput& input,
+                     bool minimal_changes) OVERRIDE;
+  virtual void Stop(bool clear_cached_results) OVERRIDE;
+
+  // net::URLFetcherDelegate:
+  virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
 
   // Called when timer_ expires.
   void Run();
@@ -346,19 +351,9 @@
   // Clears the current results.
   void ClearAllResults();
 
-  // Removes non-inlineable results until either the top result can inline
-  // autocomplete the current input or verbatim outscores the top result.
+  // Removes stale results for both default and keyword providers.  See comments
+  // on RemoveStaleResults().
   void RemoveAllStaleResults();
-  static void RemoveStaleResults(const string16& input,
-                                 int verbatim_relevance,
-                                 SuggestResults* suggest_results,
-                                 NavigationResults* navigation_results);
-
-  // If |default_provider_suggestion_| (which was suggested for
-  // |previous_input|) is still applicable given the |current_input|, adjusts it
-  // so it can be reused. Otherwise, clears it.
-  void AdjustDefaultProviderSuggestion(const string16& previous_input,
-                                       const string16& current_input);
 
   // Apply calculated relevance scores to the current results.
   void ApplyCalculatedRelevance();
@@ -390,12 +385,11 @@
   // if suggested relevances cause undesriable behavior. Updates |done_|.
   void UpdateMatches();
 
-  // Converts the top navigation result in |navigation_results| to an
-  // AutocompleteMatch and adds it to |matches_|. |is_keyword| must be true if
-  // the results come from the keyword provider.
+  // Converts an appropriate number of navigation results in
+  // |navigation_results| to matches and adds them to |matches|.
   void AddNavigationResultsToMatches(
       const NavigationResults& navigation_results,
-      bool is_keyword);
+      ACMatches* matches);
 
   // Adds a match for each result in |results| to |map|. |is_keyword| indicates
   // whether the results correspond to the keyword provider or default provider.
@@ -414,30 +408,31 @@
   // Adds matches for |results| to |map|.
   void AddSuggestResultsToMap(const SuggestResults& results, MatchMap* map);
 
-  // Gets the relevance score for the verbatim result; this value may be
-  // provided by the suggest server; otherwise it is calculated locally.
-  int GetVerbatimRelevance() const;
+  // Gets the relevance score for the verbatim result.  This value may be
+  // provided by the suggest server or calculated locally; if
+  // |relevance_from_server| is non-NULL, it will be set to indicate which of
+  // those is true.
+  int GetVerbatimRelevance(bool* relevance_from_server) const;
+
   // Calculates the relevance score for the verbatim result from the
   // default search engine.  This version takes into account context:
   // i.e., whether the user has entered a keyword-based search or not.
   int CalculateRelevanceForVerbatim() const;
+
   // Calculates the relevance score for the verbatim result from the default
   // search engine *ignoring* whether the input is a keyword-based search
   // or not.  This function should only be used to determine the minimum
   // relevance score that the best result from this provider should have.
   // For normal use, prefer the above function.
   int CalculateRelevanceForVerbatimIgnoringKeywordModeState() const;
-  // Gets the relevance score for the keyword verbatim result; this
-  // value may be provided by the suggest server; otherwise it is
-  // calculated locally.
+
+  // Gets the relevance score for the keyword verbatim result.
+  // |relevance_from_server| is handled as in GetVerbatimRelevance().
   // TODO(mpearson): Refactor so this duplication isn't necesary or
   // restructure so one static function takes all the parameters it needs
   // (rather than looking at internal state).
-  int GetKeywordVerbatimRelevance() const;
-  // Calculates the relevance score for the keyword verbatim result (if the
-  // input matches one of the profile's keyword).
-  static int CalculateRelevanceForKeywordVerbatim(AutocompleteInput::Type type,
-                                                  bool prefer_keyword);
+  int GetKeywordVerbatimRelevance(bool* relevance_from_server) const;
+
   // |time| is the time at which this query was last seen.  |is_keyword|
   // indicates whether the results correspond to the keyword provider or default
   // provider. |prevent_inline_autocomplete| is true if we should not inline
@@ -452,6 +447,7 @@
   void AddMatchToMap(const string16& query_string,
                      const string16& input_text,
                      int relevance,
+                     bool relevance_from_server,
                      AutocompleteMatch::Type type,
                      int accepted_suggestion,
                      bool is_keyword,
@@ -473,6 +469,17 @@
   // Updates the value of |done_| from the internal state.
   void UpdateDone();
 
+  // The amount of time to wait before sending a new suggest request after the
+  // previous one.  Non-const because some unittests modify this value.
+  static int kMinimumTimeBetweenSuggestQueriesMs;
+
+  // We annotate our AutocompleteMatches with whether their relevance scores
+  // were server-provided using this key in the |additional_info| field.
+  static const char kRelevanceFromServerKey[];
+  // These are the values we record with the above key.
+  static const char kTrue[];
+  static const char kFalse[];
+
   // Maintains the TemplateURLs used.
   Providers providers_;
 
@@ -505,12 +512,6 @@
   Results default_results_;
   Results keyword_results_;
 
-  // Has FinalizeInstantQuery been invoked since the last |Start|?
-  bool instant_finalized_;
-
-  // The |suggestion| parameter passed to FinalizeInstantQuery.
-  InstantSuggestion default_provider_suggestion_;
-
   // Whether a field trial, if any, has triggered in the most recent
   // autocomplete query.  This field is set to false in Start() and may be set
   // to true if either the default provider or keyword provider has completed
@@ -523,10 +524,6 @@
   // session.
   bool field_trial_triggered_in_session_;
 
-  // If true, suppress search suggestions. Reset to false in Start().
-  // See comments for SuppressSearchSuggestions().
-  bool suppress_search_suggestions_;
-
   // Start margin of the omnibox. Used to construct search URLs.
   int omnibox_start_margin_;
 
diff --git a/chrome/browser/autocomplete/search_provider_unittest.cc b/chrome/browser/autocomplete/search_provider_unittest.cc
index 88edef6..2551ca2 100644
--- a/chrome/browser/autocomplete/search_provider_unittest.cc
+++ b/chrome/browser/autocomplete/search_provider_unittest.cc
@@ -4,12 +4,13 @@
 
 #include "chrome/browser/autocomplete/search_provider.h"
 
+#include "base/command_line.h"
 #include "base/metrics/field_trial.h"
 #include "base/prefs/pref_service.h"
 #include "base/run_loop.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "build/build_config.h"
 #include "chrome/browser/autocomplete/autocomplete_classifier_factory.h"
 #include "chrome/browser/autocomplete/autocomplete_controller.h"
@@ -25,7 +26,7 @@
 #include "chrome/browser/search_engines/template_url.h"
 #include "chrome/browser/search_engines/template_url_service.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
-#include "chrome/common/instant_types.h"
+#include "chrome/common/chrome_switches.h"
 #include "chrome/common/metrics/entropy_provider.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_browser_process.h"
@@ -35,7 +36,8 @@
 #include "net/url_request/url_request_status.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-using content::BrowserThread;
+
+// SearchProviderTest ---------------------------------------------------------
 
 // The following environment is configured for these tests:
 // . The TemplateURL default_t_url_ is set as the default provider.
@@ -49,26 +51,6 @@
 class SearchProviderTest : public testing::Test,
                            public AutocompleteProviderListener {
  public:
-  SearchProviderTest()
-      : default_t_url_(NULL),
-        term1_(UTF8ToUTF16("term1")),
-        keyword_t_url_(NULL),
-        keyword_term_(UTF8ToUTF16("keyword")),
-        ui_thread_(BrowserThread::UI, &message_loop_),
-        io_thread_(BrowserThread::IO),
-        quit_when_done_(false) {
-    io_thread_.Start();
-  }
-
-  static void SetUpTestCase();
-
-  static void TearDownTestCase();
-
-  // See description above class for what this registers.
-  virtual void SetUp();
-
-  virtual void TearDown();
-
   struct ResultInfo {
     ResultInfo() : result_type(AutocompleteMatchType::NUM_TYPES) {
     }
@@ -79,16 +61,36 @@
         result_type(result_type),
         fill_into_edit(fill_into_edit) {
     }
+
     const GURL gurl;
     const AutocompleteMatch::Type result_type;
     const string16 fill_into_edit;
   };
+
   struct TestData {
     const string16 input;
     const size_t num_results;
     const ResultInfo output[3];
   };
 
+  SearchProviderTest()
+      : default_t_url_(NULL),
+        term1_(ASCIIToUTF16("term1")),
+        keyword_t_url_(NULL),
+        keyword_term_(ASCIIToUTF16("keyword")),
+        ui_thread_(content::BrowserThread::UI, &message_loop_),
+        io_thread_(content::BrowserThread::IO),
+        quit_when_done_(false) {
+    io_thread_.Start();
+  }
+
+  static void SetUpTestCase();
+  static void TearDownTestCase();
+
+  // See description above class for what this registers.
+  virtual void SetUp() OVERRIDE;
+  virtual void TearDown() OVERRIDE;
+
   void RunTest(TestData* cases, int num_cases, bool prefer_keyword);
 
  protected:
@@ -166,8 +168,6 @@
 
 // static
 base::FieldTrialList* SearchProviderTest::field_trial_list_ = NULL;
-
-// static
 const std::string SearchProviderTest::kNotApplicable = "Not Applicable";
 
 // static
@@ -237,6 +237,41 @@
   provider_->kMinimumTimeBetweenSuggestQueriesMs = 0;
 }
 
+void SearchProviderTest::TearDown() {
+  message_loop_.RunUntilIdle();
+
+  // Shutdown the provider before the profile.
+  provider_ = NULL;
+}
+
+void SearchProviderTest::RunTest(TestData* cases,
+                                 int num_cases,
+                                 bool prefer_keyword) {
+  ACMatches matches;
+  for (int i = 0; i < num_cases; ++i) {
+    AutocompleteInput input(cases[i].input, string16::npos, string16(), GURL(),
+                            false, prefer_keyword, true,
+                            AutocompleteInput::ALL_MATCHES);
+    provider_->Start(input, false);
+    matches = provider_->matches();
+    string16 diagnostic_details = ASCIIToUTF16("Input was: ") + cases[i].input +
+        ASCIIToUTF16("; prefer_keyword was: ") +
+        (prefer_keyword ? ASCIIToUTF16("true") : ASCIIToUTF16("false"));
+    EXPECT_EQ(cases[i].num_results, matches.size()) << diagnostic_details;
+    if (matches.size() == cases[i].num_results) {
+      for (size_t j = 0; j < cases[i].num_results; ++j) {
+        EXPECT_EQ(cases[i].output[j].gurl, matches[j].destination_url) <<
+            diagnostic_details;
+        EXPECT_EQ(cases[i].output[j].result_type, matches[j].type) <<
+            diagnostic_details;
+        EXPECT_EQ(cases[i].output[j].fill_into_edit,
+                  matches[j].fill_into_edit) <<
+            diagnostic_details;
+      }
+    }
+  }
+}
+
 void SearchProviderTest::OnProviderUpdate(bool updated_matches) {
   if (quit_when_done_ && provider_->done()) {
     quit_when_done_ = false;
@@ -286,7 +321,6 @@
   QueryForInput(text, false, false);
   profile_.BlockUntilHistoryProcessesPendingRequests();
   ASSERT_NO_FATAL_FAILURE(FinishDefaultSuggestQuery());
-  EXPECT_NE(chrome::IsInstantExtendedAPIEnabled(), provider_->done());
   if (!wyt_match)
     return;
   ASSERT_GE(provider_->matches().size(), 1u);
@@ -296,41 +330,6 @@
       wyt_match));
 }
 
-void SearchProviderTest::TearDown() {
-  message_loop_.RunUntilIdle();
-
-  // Shutdown the provider before the profile.
-  provider_ = NULL;
-}
-
-void SearchProviderTest::RunTest(TestData* cases,
-                                 int num_cases,
-                                 bool prefer_keyword) {
-  ACMatches matches;
-  for (int i = 0; i < num_cases; ++i) {
-    AutocompleteInput input(cases[i].input, string16::npos, string16(), GURL(),
-                            false, prefer_keyword, true,
-                            AutocompleteInput::ALL_MATCHES);
-    provider_->Start(input, false);
-    matches = provider_->matches();
-    string16 diagnostic_details = ASCIIToUTF16("Input was: ") + cases[i].input +
-        ASCIIToUTF16("; prefer_keyword was: ") +
-        (prefer_keyword ? ASCIIToUTF16("true") : ASCIIToUTF16("false"));
-    EXPECT_EQ(cases[i].num_results, matches.size()) << diagnostic_details;
-    if (matches.size() == cases[i].num_results) {
-      for (size_t j = 0; j < cases[i].num_results; ++j) {
-        EXPECT_EQ(cases[i].output[j].gurl, matches[j].destination_url) <<
-            diagnostic_details;
-        EXPECT_EQ(cases[i].output[j].result_type, matches[j].type) <<
-            diagnostic_details;
-        EXPECT_EQ(cases[i].output[j].fill_into_edit,
-                  matches[j].fill_into_edit) <<
-            diagnostic_details;
-      }
-    }
-  }
-}
-
 GURL SearchProviderTest::AddSearchToHistory(TemplateURL* t_url,
                                             string16 term,
                                             int visit_count) {
@@ -382,7 +381,8 @@
   default_fetcher->delegate()->OnURLFetchComplete(default_fetcher);
 }
 
-// Tests -----------------------------------------------------------------------
+
+// Actual Tests ---------------------------------------------------------------
 
 // Make sure we query history for the default provider and a URLFetcher is
 // created for the default provider suggest results.
@@ -438,7 +438,7 @@
 // is queried as well as URLFetchers getting created.
 TEST_F(SearchProviderTest, QueryKeywordProvider) {
   string16 term = keyword_term_.substr(0, keyword_term_.length() - 1);
-  QueryForInput(keyword_t_url_->keyword() + UTF8ToUTF16(" ") + term,
+  QueryForInput(keyword_t_url_->keyword() + ASCIIToUTF16(" ") + term,
                 false,
                 false);
 
@@ -510,191 +510,6 @@
   }
 }
 
-// Make sure FinalizeInstantQuery works.
-TEST_F(SearchProviderTest, FinalizeInstantQuery) {
-  chrome::EnableInstantExtendedAPIForTesting();
-
-  ASSERT_NO_FATAL_FAILURE(QueryForInputAndSetWYTMatch(ASCIIToUTF16("foo"),
-                                                      NULL));
-
-  // Tell the provider Instant is done.
-  provider_->FinalizeInstantQuery(ASCIIToUTF16("foo"),
-                                  InstantSuggestion(ASCIIToUTF16("bar"),
-                                                    INSTANT_COMPLETE_NOW,
-                                                    INSTANT_SUGGESTION_SEARCH,
-                                                    string16(),
-                                                    kNoMatchIndex));
-
-  // The provider should now be done.
-  EXPECT_TRUE(provider_->done());
-
-  // There should be two matches, one for what you typed, the other for
-  // 'foobar'.
-  EXPECT_EQ(2u, provider_->matches().size());
-  GURL instant_url(default_t_url_->url_ref().ReplaceSearchTerms(
-      TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("foobar"))));
-  AutocompleteMatch instant_match;
-  EXPECT_TRUE(FindMatchWithDestination(instant_url, &instant_match));
-
-  // And the 'foobar' match should not have a description, it'll be set later.
-  EXPECT_TRUE(instant_match.description.empty());
-
-  // Make sure the what you typed match has no description.
-  AutocompleteMatch wyt_match;
-  EXPECT_TRUE(FindMatchWithDestination(
-      GURL(default_t_url_->url_ref().ReplaceSearchTerms(
-          TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("foo")))),
-          &wyt_match));
-  EXPECT_TRUE(wyt_match.description.empty());
-
-  // Instant search suggestions are never inline autocompleted, so they should
-  // score less than the WYT match.
-  EXPECT_LT(instant_match.relevance, wyt_match.relevance);
-}
-
-// Make sure FinalizeInstantQuery works with URL suggestions.
-TEST_F(SearchProviderTest, FinalizeInstantURL) {
-  chrome::EnableInstantExtendedAPIForTesting();
-
-  ASSERT_NO_FATAL_FAILURE(QueryForInputAndSetWYTMatch(ASCIIToUTF16("ex"),
-                                                      NULL));
-
-  // Tell the provider Instant is done.
-  provider_->FinalizeInstantQuery(ASCIIToUTF16("ex"),
-                                  InstantSuggestion(
-                                      ASCIIToUTF16("http://example.com/"),
-                                      INSTANT_COMPLETE_NOW,
-                                      INSTANT_SUGGESTION_URL,
-                                      string16(),
-                                      kNoMatchIndex));
-
-  // The provider should now be done.
-  EXPECT_TRUE(provider_->done());
-
-  // There should be two matches, one for what you typed, the other for
-  // "http://example.com/".
-  EXPECT_EQ(2u, provider_->matches().size());
-  GURL instant_url("http://example.com");
-  AutocompleteMatch instant_match;
-  EXPECT_TRUE(FindMatchWithDestination(instant_url, &instant_match));
-
-  // The Instant match should not have a description, it'll be set later.
-  EXPECT_TRUE(instant_match.description.empty());
-
-  // Make sure the what you typed match has no description.
-  AutocompleteMatch wyt_match;
-  EXPECT_TRUE(FindMatchWithDestination(
-      GURL(default_t_url_->url_ref().ReplaceSearchTerms(
-          TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("ex")))),
-          &wyt_match));
-  EXPECT_TRUE(wyt_match.description.empty());
-
-  // The Instant URL should be more relevant.
-  EXPECT_GT(instant_match.relevance, wyt_match.relevance);
-}
-
-// An Instant URL suggestion should behave the same way whether the input text
-// is classified as UNKNOWN or as an URL. Otherwise if the user types
-// "example.co" url-what-you-typed will displace the Instant suggestion for
-// "example.com".
-TEST_F(SearchProviderTest, FinalizeInstantURLWithURLText) {
-  chrome::EnableInstantExtendedAPIForTesting();
-
-  ASSERT_NO_FATAL_FAILURE(QueryForInputAndSetWYTMatch(
-      ASCIIToUTF16("example.co"), NULL));
-
-  // Tell the provider Instant is done.
-  provider_->FinalizeInstantQuery(ASCIIToUTF16("example.co"),
-                                  InstantSuggestion(
-                                      ASCIIToUTF16("http://example.com/"),
-                                      INSTANT_COMPLETE_NOW,
-                                      INSTANT_SUGGESTION_URL,
-                                      string16(),
-                                      kNoMatchIndex));
-
-  // The provider should now be done.
-  EXPECT_TRUE(provider_->done());
-
-  // There should be two matches, one for what you typed, the other for
-  // "http://example.com/".
-  EXPECT_EQ(2u, provider_->matches().size());
-  GURL instant_url("http://example.com");
-  AutocompleteMatch instant_match;
-  EXPECT_TRUE(FindMatchWithDestination(instant_url, &instant_match));
-
-  // The Instant match should not have a description, it'll be set later.
-  EXPECT_TRUE(instant_match.description.empty());
-
-  // The Instant URL should be more relevant than a URL_WHAT_YOU_TYPED match.
-  EXPECT_GT(instant_match.relevance,
-            HistoryURLProvider::kScoreForWhatYouTypedResult);
-}
-
-// Make sure that if FinalizeInstantQuery is invoked before suggest results
-// return, the suggest text from FinalizeInstantQuery is remembered.
-TEST_F(SearchProviderTest, RememberInstantQuery) {
-  chrome::EnableInstantExtendedAPIForTesting();
-
-  QueryForInput(ASCIIToUTF16("foo"), false, false);
-
-  // Finalize the Instant query immediately.
-  provider_->FinalizeInstantQuery(ASCIIToUTF16("foo"),
-                                  InstantSuggestion(ASCIIToUTF16("bar"),
-                                                    INSTANT_COMPLETE_NOW,
-                                                    INSTANT_SUGGESTION_SEARCH,
-                                                    string16(),
-                                                    kNoMatchIndex));
-
-  // There should be two matches, one for what you typed, the other for
-  // 'foobar'.
-  EXPECT_EQ(2u, provider_->matches().size());
-  GURL instant_url(default_t_url_->url_ref().ReplaceSearchTerms(
-      TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("foobar"))));
-  AutocompleteMatch instant_match;
-  EXPECT_TRUE(FindMatchWithDestination(instant_url, &instant_match));
-
-  // Wait until history and the suggest query complete.
-  profile_.BlockUntilHistoryProcessesPendingRequests();
-  ASSERT_NO_FATAL_FAILURE(FinishDefaultSuggestQuery());
-
-  // Provider should be done.
-  EXPECT_TRUE(provider_->done());
-
-  // There should be two matches, one for what you typed, the other for
-  // 'foobar'.
-  EXPECT_EQ(2u, provider_->matches().size());
-  EXPECT_TRUE(FindMatchWithDestination(instant_url, &instant_match));
-
-  // And the 'foobar' match should not have a description, it'll be set later.
-  EXPECT_TRUE(instant_match.description.empty());
-}
-
-// Make sure that if trailing whitespace is added to the text supplied to
-// AutocompleteInput the default suggest text is cleared.
-TEST_F(SearchProviderTest, DifferingText) {
-  chrome::EnableInstantExtendedAPIForTesting();
-
-  ASSERT_NO_FATAL_FAILURE(QueryForInputAndSetWYTMatch(ASCIIToUTF16("foo"),
-                                                      NULL));
-
-  // Finalize the Instant query immediately.
-  provider_->FinalizeInstantQuery(ASCIIToUTF16("foo"),
-                                  InstantSuggestion(ASCIIToUTF16("bar"),
-                                                    INSTANT_COMPLETE_NOW,
-                                                    INSTANT_SUGGESTION_SEARCH,
-                                                    string16(),
-                                                    kNoMatchIndex));
-
-  // Query with the same input text, but trailing whitespace.
-  AutocompleteMatch instant_match;
-  ASSERT_NO_FATAL_FAILURE(QueryForInputAndSetWYTMatch(ASCIIToUTF16("foo "),
-                                                      &instant_match));
-
-  // There should only one match, for what you typed.
-  EXPECT_EQ(1u, provider_->matches().size());
-  EXPECT_FALSE(instant_match.destination_url.is_empty());
-}
-
 TEST_F(SearchProviderTest, DontAutocompleteURLLikeTerms) {
   AutocompleteClassifierFactory::GetInstance()->SetTestingFactoryAndUse(
       &profile_, &AutocompleteClassifierFactory::BuildInstanceFor);
@@ -981,6 +796,38 @@
   RunTest(cases, arraysize(cases), true);
 }
 
+// Ensures command-line flags are reflected in the URLs the search provider
+// generates.
+TEST_F(SearchProviderTest, CommandLineOverrides) {
+  TemplateURLService* turl_model =
+      TemplateURLServiceFactory::GetForProfile(&profile_);
+
+  TemplateURLData data;
+  data.short_name = ASCIIToUTF16("default");
+  data.SetKeyword(data.short_name);
+  data.SetURL("{google:baseURL}{searchTerms}");
+  default_t_url_ = new TemplateURL(&profile_, data);
+  turl_model->Add(default_t_url_);
+  turl_model->SetDefaultSearchProvider(default_t_url_);
+
+  CommandLine::ForCurrentProcess()->AppendSwitchASCII(switches::kGoogleBaseURL,
+                                                      "http://www.bar.com/");
+  CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+      switches::kExtraSearchQueryParams, "a=b");
+
+  TestData cases[] = {
+    { ASCIIToUTF16("k a"), 2,
+      { ResultInfo(GURL("http://keyword/a"),
+                   AutocompleteMatchType::SEARCH_OTHER_ENGINE,
+                   ASCIIToUTF16("k a")),
+        ResultInfo(GURL("http://www.bar.com/k%20a?a=b"),
+                   AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,
+                   ASCIIToUTF16("k a")) } },
+  };
+
+  RunTest(cases, arraysize(cases), false);
+}
+
 // Verifies Navsuggest results don't set a TemplateURL, which Instant relies on.
 // Also verifies that just the *first* navigational result is listed as a match
 // if suggested relevance scores were not sent.
@@ -1201,9 +1048,10 @@
     fetcher->delegate()->OnURLFetchComplete(fetcher);
     RunTillProviderDone();
 
-   const std::string description = "for input with json=" + cases[i].json;
+    const std::string description = "for input with json=" + cases[i].json;
     const ACMatches& matches = provider_->matches();
     // The top match must inline and score as highly as calculated verbatim.
+    ASSERT_FALSE(matches.empty());
     EXPECT_NE(string16::npos, matches[0].inline_autocomplete_offset) <<
         description;
     EXPECT_GE(matches[0].relevance, 1300) << description;
@@ -1567,21 +1415,20 @@
         { "k a", false },
         { kNotApplicable, false } } },
     // Check when there is neither verbatim nor a query suggestion that,
-    // because we can demote navsuggestions below a query suggestion,
+    // because we can't demote navsuggestions below a query suggestion,
     // we abandon suggested relevance scores entirely.  One consequence is
     // that this means we restore the keyword verbatim match.  Note
     // that in this case of abandoning suggested relevance scores, we still
-    // keep the navsuggestions in order by their original scores (just
-    // not at their original scores), and continue to allow multiple
-    // navsuggestions to appear.
+    // keep the navsuggestions in the same order, but we revert to only allowing
+    // one navigation to appear because the scores are completely local.
     { "[\"a\",[\"http://a1.com\", \"http://a2.com\"],[],[],"
        "{\"google:suggesttype\":[\"NAVIGATION\", \"NAVIGATION\"],"
         "\"google:verbatimrelevance\":0,"
         "\"google:suggestrelevance\":[9998, 9999]}]",
       { { "a", true },
         { "a2.com", false },
-        { "a1.com", false },
         { "k a", false },
+        { kNotApplicable, false },
         { kNotApplicable, false } } },
     { "[\"a\",[\"http://a1.com\", \"http://a2.com\"],[],[],"
        "{\"google:suggesttype\":[\"NAVIGATION\", \"NAVIGATION\"],"
@@ -1589,8 +1436,8 @@
         "\"google:suggestrelevance\":[9999, 9998]}]",
       { { "a", true },
         { "a1.com", false },
-        { "a2.com", false },
         { "k a", false },
+        { kNotApplicable, false },
         { kNotApplicable, false } } },
     // More checks that everything works when it's not necessary to demote.
     { "[\"a\",[\"http://a1.com\", \"http://a2.com\", \"a3\"],[],[],"
@@ -1637,6 +1484,7 @@
     const std::string description = "for input with json=" + cases[i].json;
     const ACMatches& matches = provider_->matches();
     // The top match must inline and score as highly as calculated verbatim.
+    ASSERT_FALSE(matches.empty());
     EXPECT_NE(string16::npos, matches[0].inline_autocomplete_offset) <<
         description;
     EXPECT_GE(matches[0].relevance, 1300) << description;
@@ -1656,6 +1504,112 @@
   }
 }
 
+TEST_F(SearchProviderTest, LocalAndRemoteRelevances) {
+  // Enable Instant Extended in order to allow an increased number of
+  // suggestions.
+  chrome::EnableInstantExtendedAPIForTesting();
+
+  // We hardcode the string "term1" below, so ensure that the search term that
+  // got added to history already is that string.
+  ASSERT_EQ(ASCIIToUTF16("term1"), term1_);
+  string16 term = term1_.substr(0, term1_.length() - 1);
+
+  AddSearchToHistory(default_t_url_, term + ASCIIToUTF16("2"), 2);
+  profile_.BlockUntilHistoryProcessesPendingRequests();
+
+  struct {
+    const string16 input;
+    const std::string json;
+    const std::string matches[6];
+  } cases[] = {
+    // The history results outscore the default verbatim score.  term2 has more
+    // visits so it outscores term1.  The suggestions are still returned since
+    // they're server-scored.
+    { term,
+      "[\"term\",[\"a1\", \"a2\", \"a3\"],[],[],"
+       "{\"google:suggesttype\":[\"QUERY\", \"QUERY\", \"QUERY\"],"
+        "\"google:suggestrelevance\":[1, 2, 3]}]",
+      { "term2", "term1", "term", "a3", "a2", "a1" } },
+    // Because we already have three suggestions by the time we see the history
+    // results, they don't get returned.
+    { term,
+      "[\"term\",[\"a1\", \"a2\", \"a3\"],[],[],"
+       "{\"google:suggesttype\":[\"QUERY\", \"QUERY\", \"QUERY\"],"
+        "\"google:verbatimrelevance\":1450,"
+        "\"google:suggestrelevance\":[1440, 1430, 1420]}]",
+      { "term", "a1", "a2", "a3", kNotApplicable, kNotApplicable } },
+    // If we only have two suggestions, we have room for a history result.
+    { term,
+      "[\"term\",[\"a1\", \"a2\"],[],[],"
+       "{\"google:suggesttype\":[\"QUERY\", \"QUERY\"],"
+        "\"google:verbatimrelevance\":1450,"
+        "\"google:suggestrelevance\":[1430, 1410]}]",
+      { "term", "a1", "a2", "term2", kNotApplicable, kNotApplicable } },
+    // If we have more than three suggestions, they should all be returned as
+    // long as we have enough total space for them.
+    { term,
+      "[\"term\",[\"a1\", \"a2\", \"a3\", \"a4\"],[],[],"
+       "{\"google:suggesttype\":[\"QUERY\", \"QUERY\", \"QUERY\", \"QUERY\"],"
+        "\"google:verbatimrelevance\":1450,"
+        "\"google:suggestrelevance\":[1440, 1430, 1420, 1410]}]",
+      { "term", "a1", "a2", "a3", "a4", kNotApplicable } },
+    { term,
+      "[\"term\",[\"a1\", \"a2\", \"a3\", \"a4\", \"a5\", \"a6\"],[],[],"
+       "{\"google:suggesttype\":[\"QUERY\", \"QUERY\", \"QUERY\", \"QUERY\","
+                                "\"QUERY\", \"QUERY\"],"
+        "\"google:verbatimrelevance\":1450,"
+        "\"google:suggestrelevance\":[1440, 1430, 1420, 1410, 1400, 1390]}]",
+      { "term", "a1", "a2", "a3", "a4", "a5" } },
+    { term,
+      "[\"term\",[\"a1\", \"a2\", \"a3\", \"a4\"],[],[],"
+       "{\"google:suggesttype\":[\"QUERY\", \"QUERY\", \"QUERY\", \"QUERY\"],"
+        "\"google:verbatimrelevance\":1450,"
+        "\"google:suggestrelevance\":[1430, 1410, 1390, 1370]}]",
+      { "term", "a1", "a2", "term2", "a3", "a4" } },
+    // When the input looks like a URL, we disallow having a query as the
+    // highest-ranking result.  If the query was provided by a suggestion, we
+    // reset the suggest scores to enforce this (see
+    // SearchProvider::UpdateMatches()).  Even if we reset the suggest scores,
+    // however, we should still allow navsuggestions to be treated as
+    // server-provided.
+    { ASCIIToUTF16("a.com"),
+      "[\"a.com\",[\"a1\", \"a2\", \"a.com/1\", \"a.com/2\"],[],[],"
+       "{\"google:suggesttype\":[\"QUERY\", \"QUERY\", \"NAVIGATION\","
+                                "\"NAVIGATION\"],"
+        // A verbatim query for URL-like input scores 850, so the navigation
+        // scores here should bracket it.
+        "\"google:suggestrelevance\":[9999, 9998, 900, 800]}]",
+      { "a.com/1", "a.com", "a.com/2", "a1", kNotApplicable, kNotApplicable } },
+  };
+
+  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) {
+    QueryForInput(cases[i].input, false, false);
+    net::TestURLFetcher* fetcher = WaitUntilURLFetcherIsReady(
+        SearchProvider::kDefaultProviderURLFetcherID);
+    ASSERT_TRUE(fetcher);
+    fetcher->set_response_code(200);
+    fetcher->SetResponseString(cases[i].json);
+    fetcher->delegate()->OnURLFetchComplete(fetcher);
+    RunTillProviderDone();
+
+    const std::string description = "for input with json=" + cases[i].json;
+    const ACMatches& matches = provider_->matches();
+
+    // Ensure no extra matches are present.
+    ASSERT_LE(matches.size(), 6U);
+
+    size_t j = 0;
+    // Ensure that the returned matches equal the expectations.
+    for (; j < matches.size(); ++j)
+      EXPECT_EQ(ASCIIToUTF16(cases[i].matches[j]),
+                matches[j].contents) << description;
+    // Ensure that no expected matches are missing.
+    for (; j < ARRAYSIZE_UNSAFE(cases[i].matches); ++j)
+      EXPECT_EQ(kNotApplicable, cases[i].matches[j]) <<
+          "Case # " << i << " " << description;
+  }
+}
+
 // Verifies suggest relevance behavior for URL input.
 TEST_F(SearchProviderTest, DefaultProviderSuggestRelevanceScoringUrlInput) {
   struct {
@@ -1928,9 +1882,10 @@
 
   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) {
     QueryForInput(ASCIIToUTF16(cases[i].input), false, false);
-    SearchProvider::NavigationResult result(
-        *provider_.get(), GURL(cases[i].url), string16(), false, 0);
-    AutocompleteMatch match(provider_->NavigationToMatch(result));
+    AutocompleteMatch match(
+        provider_->NavigationToMatch(SearchProvider::NavigationResult(
+            *provider_.get(), GURL(cases[i].url), string16(), false, 0,
+            false)));
     EXPECT_EQ(cases[i].inline_offset, match.inline_autocomplete_offset);
     EXPECT_EQ(ASCIIToUTF16(cases[i].fill_into_edit), match.fill_into_edit);
   }
@@ -1941,7 +1896,7 @@
   const string16 input(ASCIIToUTF16("ht"));
   const string16 url(ASCIIToUTF16("http://a.com"));
   const SearchProvider::NavigationResult result(
-      *provider_.get(), GURL(url), string16(), false, 0);
+      *provider_.get(), GURL(url), string16(), false, 0, false);
 
   // Check the offset and strings when inline autocompletion is allowed.
   QueryForInput(input, false, false);
@@ -1961,10 +1916,10 @@
 // Verifies that input "w" marks a more significant domain label than "www.".
 TEST_F(SearchProviderTest, NavigationInlineDomainClassify) {
   QueryForInput(ASCIIToUTF16("w"), false, false);
-  const GURL url("http://www.wow.com");
-  const SearchProvider::NavigationResult result(
-      *provider_.get(), url, string16(), false, 0);
-  AutocompleteMatch match(provider_->NavigationToMatch(result));
+  AutocompleteMatch match(
+      provider_->NavigationToMatch(SearchProvider::NavigationResult(
+          *provider_.get(), GURL("http://www.wow.com"), string16(), false, 0,
+          false)));
   EXPECT_EQ(5U, match.inline_autocomplete_offset);
   EXPECT_EQ(ASCIIToUTF16("www.wow.com"), match.fill_into_edit);
   EXPECT_EQ(ASCIIToUTF16("www.wow.com"), match.contents);
@@ -2124,15 +2079,14 @@
         break;
       if (cases[i].results[j].is_navigation_result) {
         provider_->default_results_.navigation_results.push_back(
-            SearchProvider::NavigationResult(*provider_.get(),
-                                             GURL(suggestion),
-                                             string16(),
-                                             false,
-                                             cases[i].results[j].relevance));
+            SearchProvider::NavigationResult(
+                *provider_.get(), GURL(suggestion), string16(), false,
+                cases[i].results[j].relevance, false));
       } else {
         provider_->default_results_.suggest_results.push_back(
             SearchProvider::SuggestResult(ASCIIToUTF16(suggestion), false,
-                                          cases[i].results[j].relevance));
+                                          cases[i].results[j].relevance,
+                                          false));
       }
     }
 
diff --git a/chrome/browser/autocomplete/shortcuts_provider.cc b/chrome/browser/autocomplete/shortcuts_provider.cc
index ae59d8e..cf121be 100644
--- a/chrome/browser/autocomplete/shortcuts_provider.cc
+++ b/chrome/browser/autocomplete/shortcuts_provider.cc
@@ -17,7 +17,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/autocomplete/autocomplete_input.h"
 #include "chrome/browser/autocomplete/autocomplete_provider_listener.h"
 #include "chrome/browser/autocomplete/autocomplete_result.h"
@@ -25,10 +25,11 @@
 #include "chrome/browser/history/history_service.h"
 #include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/history/shortcuts_backend_factory.h"
+#include "chrome/browser/omnibox/omnibox_field_trial.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
-#include "googleurl/src/url_parse.h"
+#include "url/url_parse.h"
 
 namespace {
 
@@ -53,7 +54,8 @@
     : AutocompleteProvider(listener, profile,
           AutocompleteProvider::TYPE_SHORTCUTS),
       languages_(profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)),
-      initialized_(false) {
+      initialized_(false),
+      max_relevance_(AutocompleteResult::kLowestDefaultScore - 1) {
   scoped_refptr<history::ShortcutsBackend> backend =
       ShortcutsBackendFactory::GetForProfile(profile_);
   if (backend.get()) {
@@ -61,6 +63,9 @@
     if (backend->initialized())
       initialized_ = true;
   }
+  int max_relevance;
+  if (OmniboxFieldTrial::ShortcutsScoringMaxRelevance(&max_relevance))
+    max_relevance_ = max_relevance;
 }
 
 void ShortcutsProvider::Start(const AutocompleteInput& input,
@@ -169,6 +174,16 @@
     matches_.erase(matches_.begin() + AutocompleteProvider::kMaxMatches,
                    matches_.end());
   }
+  // Reset relevance scores to guarantee no results are given an
+  // inlineable score and all scores are decreasing (but not do assign
+  // any scores below 1).
+  int max_relevance = AutocompleteResult::kLowestDefaultScore - 1;
+  for (ACMatches::iterator it = matches_.begin(); it != matches_.end(); ++it) {
+    max_relevance = std::min(max_relevance, it->relevance);
+    it->relevance = max_relevance;
+    if (max_relevance > 1)
+      --max_relevance;
+  }
 }
 
 AutocompleteMatch ShortcutsProvider::ShortcutToACMatch(
@@ -185,6 +200,9 @@
   match.contents_class = shortcut.contents_class;
   match.description = shortcut.description;
   match.description_class = shortcut.description_class;
+  match.RecordAdditionalInfo("number of hits", shortcut.number_of_hits);
+  match.RecordAdditionalInfo("last access time", shortcut.last_access_time);
+  match.RecordAdditionalInfo("original input text", UTF16ToUTF8(shortcut.text));
 
   // Try to mark pieces of the contents and description as matches if they
   // appear in |term_string|.
@@ -318,7 +336,6 @@
     backend->shortcuts_map().end();
 }
 
-// static
 int ShortcutsProvider::CalculateScore(
     const string16& terms,
     const history::ShortcutsBackend::Shortcut& shortcut) {
@@ -331,7 +348,7 @@
   // directly. This makes sense since the first characters typed are much more
   // important for determining how likely it is a user wants a particular
   // shortcut than are the remaining continued characters.
-  double base_score = (AutocompleteResult::kLowestDefaultScore - 1) *
+  double base_score = max_relevance_ *
       sqrt(static_cast<double>(terms.length()) / shortcut.text.length());
 
   // Then we decay this by half each week.
diff --git a/chrome/browser/autocomplete/shortcuts_provider.h b/chrome/browser/autocomplete/shortcuts_provider.h
index b4b0fc9..11f0b0a 100644
--- a/chrome/browser/autocomplete/shortcuts_provider.h
+++ b/chrome/browser/autocomplete/shortcuts_provider.h
@@ -94,12 +94,19 @@
       const string16& keyword,
       history::ShortcutsBackend* backend);
 
-  static int CalculateScore(
+  int CalculateScore(
       const string16& terms,
       const history::ShortcutsBackend::Shortcut& shortcut);
 
   std::string languages_;
   bool initialized_;
+
+  // The maximum relevance that can be assigned in CalculateScore().
+  // Note that if the final assigned relevance is at least
+  // AutocompleteResult::kLowestDefaultScore, the relevance will be
+  // demoted to less than that number because ShortcutsProvider isn't
+  // allowed to inline.
+  int max_relevance_;
 };
 
 #endif  // CHROME_BROWSER_AUTOCOMPLETE_SHORTCUTS_PROVIDER_H_
diff --git a/chrome/browser/autocomplete/shortcuts_provider_unittest.cc b/chrome/browser/autocomplete/shortcuts_provider_unittest.cc
index bc1034c..9b2b4e4 100644
--- a/chrome/browser/autocomplete/shortcuts_provider_unittest.cc
+++ b/chrome/browser/autocomplete/shortcuts_provider_unittest.cc
@@ -573,37 +573,37 @@
       spans_description, base::Time::Now(), 1);
 
   // Maximal score.
-  const int kMaxScore = ShortcutsProvider::CalculateScore(
+  const int kMaxScore = provider_->CalculateScore(
       ASCIIToUTF16("test"), shortcut);
 
   // Score decreases as percent of the match is decreased.
   int score_three_quarters =
-      ShortcutsProvider::CalculateScore(ASCIIToUTF16("tes"), shortcut);
+      provider_->CalculateScore(ASCIIToUTF16("tes"), shortcut);
   EXPECT_LT(score_three_quarters, kMaxScore);
   int score_one_half =
-      ShortcutsProvider::CalculateScore(ASCIIToUTF16("te"), shortcut);
+      provider_->CalculateScore(ASCIIToUTF16("te"), shortcut);
   EXPECT_LT(score_one_half, score_three_quarters);
   int score_one_quarter =
-      ShortcutsProvider::CalculateScore(ASCIIToUTF16("t"), shortcut);
+      provider_->CalculateScore(ASCIIToUTF16("t"), shortcut);
   EXPECT_LT(score_one_quarter, score_one_half);
 
   // Should decay with time - one week.
   shortcut.last_access_time = base::Time::Now() - base::TimeDelta::FromDays(7);
   int score_week_old =
-      ShortcutsProvider::CalculateScore(ASCIIToUTF16("test"), shortcut);
+      provider_->CalculateScore(ASCIIToUTF16("test"), shortcut);
   EXPECT_LT(score_week_old, kMaxScore);
 
   // Should decay more in two weeks.
   shortcut.last_access_time = base::Time::Now() - base::TimeDelta::FromDays(14);
   int score_two_weeks_old =
-      ShortcutsProvider::CalculateScore(ASCIIToUTF16("test"), shortcut);
+      provider_->CalculateScore(ASCIIToUTF16("test"), shortcut);
   EXPECT_LT(score_two_weeks_old, score_week_old);
 
   // But not if it was activly clicked on. 2 hits slow decaying power.
   shortcut.number_of_hits = 2;
   shortcut.last_access_time = base::Time::Now() - base::TimeDelta::FromDays(14);
   int score_popular_two_weeks_old =
-      ShortcutsProvider::CalculateScore(ASCIIToUTF16("test"), shortcut);
+      provider_->CalculateScore(ASCIIToUTF16("test"), shortcut);
   EXPECT_LT(score_two_weeks_old, score_popular_two_weeks_old);
   // But still decayed.
   EXPECT_LT(score_popular_two_weeks_old, kMaxScore);
@@ -612,7 +612,7 @@
   shortcut.number_of_hits = 3;
   shortcut.last_access_time = base::Time::Now() - base::TimeDelta::FromDays(14);
   int score_more_popular_two_weeks_old =
-      ShortcutsProvider::CalculateScore(ASCIIToUTF16("test"), shortcut);
+      provider_->CalculateScore(ASCIIToUTF16("test"), shortcut);
   EXPECT_LT(score_two_weeks_old, score_more_popular_two_weeks_old);
   EXPECT_LT(score_popular_two_weeks_old, score_more_popular_two_weeks_old);
   // But still decayed.
diff --git a/chrome/browser/autocomplete/zero_suggest_provider.cc b/chrome/browser/autocomplete/zero_suggest_provider.cc
index b210f5a..77c0e1f 100644
--- a/chrome/browser/autocomplete/zero_suggest_provider.cc
+++ b/chrome/browser/autocomplete/zero_suggest_provider.cc
@@ -12,7 +12,7 @@
 #include "base/strings/string16.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/autocomplete/autocomplete_input.h"
 #include "chrome/browser/autocomplete/autocomplete_match.h"
 #include "chrome/browser/autocomplete/autocomplete_provider_listener.h"
@@ -30,7 +30,6 @@
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/escape.h"
 #include "net/base/load_flags.h"
 #include "net/base/net_util.h"
@@ -38,6 +37,7 @@
 #include "net/http/http_response_headers.h"
 #include "net/url_request/url_fetcher.h"
 #include "net/url_request/url_request_status.h"
+#include "url/gurl.h"
 
 namespace {
 
@@ -80,13 +80,6 @@
 
 void ZeroSuggestProvider::Start(const AutocompleteInput& input,
                                 bool /*minimal_changes*/) {
-  CheckIfTextModfied(input.text());
-  // Clear results only if the user text was modified.
-  Stop(user_text_modified_);
-  ConvertResultsToAutocompleteMatches(input.text(), false);
-  // listener_->OnProviderUpdate() does not need to be called because this
-  // function is only called in the synchronous pass when a user has performed
-  // an action (such as typing a character in the omnobox).
 }
 
 void ZeroSuggestProvider::Stop(bool clear_cached_results) {
@@ -125,6 +118,7 @@
   // |field_trial_triggered_in_session_| unchanged and set
   // |field_trial_triggered_| to false since zero suggest is inactive now.
   field_trial_triggered_ = false;
+  Stop(true);
 }
 
 void ZeroSuggestProvider::OnURLFetchComplete(const net::URLFetcher* source) {
@@ -150,13 +144,12 @@
   done_ = true;
 
   if (have_results) {
-    ConvertResultsToAutocompleteMatches(original_user_text_, true);
+    ConvertResultsToAutocompleteMatches();
     listener_->OnProviderUpdate(true);
   }
 }
 
 void ZeroSuggestProvider::StartZeroSuggest(const GURL& url,
-                                           const string16& user_text,
                                            const string16& permanent_text) {
   Stop(true);
   field_trial_triggered_ = false;
@@ -165,11 +158,9 @@
     return;
   verbatim_relevance_ = kDefaultVerbatimZeroSuggestRelevance;
   done_ = false;
-  original_user_text_ = user_text;
   permanent_text_ = permanent_text;
   current_query_ = url.spec();
   current_url_match_ = MatchForCurrentURL();
-  user_text_modified_ = false;
   // TODO(jered): Consider adding locally-sourced zero-suggestions here too.
   // These may be useful on the NTP or more relevant to the user than server
   // suggestions, if based on local browsing history.
@@ -182,7 +173,6 @@
     : AutocompleteProvider(listener, profile,
           AutocompleteProvider::TYPE_ZERO_SUGGEST),
       template_url_service_(TemplateURLServiceFactory::GetForProfile(profile)),
-      user_text_modified_(false),
       have_pending_request_(false),
       verbatim_relevance_(kDefaultVerbatimZeroSuggestRelevance),
       field_trial_triggered_(false),
@@ -295,49 +285,45 @@
         if (descriptions != NULL)
           descriptions->GetString(index, &title);
         navigation_results->push_back(SearchProvider::NavigationResult(
-            *this, url, title, false, relevance));
+            *this, url, title, false, relevance, relevances != NULL));
       }
     } else {
       suggest_results->push_back(SearchProvider::SuggestResult(
-          result, false, relevance));
+          result, false, relevance, relevances != NULL));
     }
   }
 }
 
 void ZeroSuggestProvider::AddSuggestResultsToMap(
     const SearchProvider::SuggestResults& results,
-    const string16& provider_keyword,
+    const TemplateURL* template_url,
     SearchProvider::MatchMap* map) {
   for (size_t i = 0; i < results.size(); ++i) {
-    AddMatchToMap(results[i].suggestion(),
-                  provider_keyword,
-                  results[i].relevance(),
-                  AutocompleteMatchType::SEARCH_SUGGEST, i, map);
+    AddMatchToMap(results[i].relevance(), AutocompleteMatchType::SEARCH_SUGGEST,
+                  template_url, results[i].suggestion(), i, map);
   }
 }
 
-void ZeroSuggestProvider::AddMatchToMap(const string16& query_string,
-                                        const string16& provider_keyword,
-                                        int relevance,
+void ZeroSuggestProvider::AddMatchToMap(int relevance,
                                         AutocompleteMatch::Type type,
+                                        const TemplateURL* template_url,
+                                        const string16& query_string,
                                         int accepted_suggestion,
                                         SearchProvider::MatchMap* map) {
   // Pass in query_string as the input_text since we don't want any bolding.
   // TODO(samarth|melevin): use the actual omnibox margin here as well instead
   // of passing in -1.
   AutocompleteMatch match = SearchProvider::CreateSearchSuggestion(
-      profile_, this, AutocompleteInput(),
-      query_string, query_string, relevance, type, accepted_suggestion,
-      false, provider_keyword, -1);
+      this, relevance, type, template_url, query_string, query_string,
+      AutocompleteInput(), false, accepted_suggestion, -1, true);
   if (!match.destination_url.is_valid())
     return;
 
   // Try to add |match| to |map|.  If a match for |query_string| is already in
   // |map|, replace it if |match| is more relevant.
   // NOTE: Keep this ToLower() call in sync with url_database.cc.
-  const std::pair<SearchProvider::MatchMap::iterator, bool> i = map->insert(
-      std::pair<string16, AutocompleteMatch>(
-          base::i18n::ToLower(query_string), match));
+  const std::pair<SearchProvider::MatchMap::iterator, bool> i(map->insert(
+      std::make_pair(base::i18n::ToLower(query_string), match)));
   // NOTE: We purposefully do a direct relevance comparison here instead of
   // using AutocompleteMatch::MoreRelevant(), so that we'll prefer "items added
   // first" rather than "items alphabetically first" when the scores are equal.
@@ -368,7 +354,12 @@
   AutocompleteMatch::ClassifyLocationInString(string16::npos, 0,
       match.contents.length(), ACMatchClassification::URL,
       &match.contents_class);
-  match.description = navigation.description();
+
+  match.description =
+      AutocompleteMatch::SanitizeString(navigation.description());
+  AutocompleteMatch::ClassifyLocationInString(string16::npos, 0,
+      match.description.length(), ACMatchClassification::NONE,
+      &match.description_class);
   return match;
 }
 
@@ -415,25 +406,18 @@
   LogOmniboxZeroSuggestRequest(ZERO_SUGGEST_REQUEST_SENT);
 }
 
-void ZeroSuggestProvider::CheckIfTextModfied(const string16& user_text) {
-  if (!user_text.empty() && user_text != permanent_text_)
-    user_text_modified_ = true;
-}
-
 void ZeroSuggestProvider::ParseSuggestResults(const Value& root_val) {
   SearchProvider::SuggestResults suggest_results;
   FillResults(root_val, &verbatim_relevance_,
               &suggest_results, &navigation_results_);
 
   query_matches_map_.clear();
-  const TemplateURL* default_provider =
-     template_url_service_->GetDefaultSearchProvider();
-  AddSuggestResultsToMap(suggest_results, default_provider->keyword(),
+  AddSuggestResultsToMap(suggest_results,
+                         template_url_service_->GetDefaultSearchProvider(),
                          &query_matches_map_);
 }
 
-void ZeroSuggestProvider::ConvertResultsToAutocompleteMatches(
-    string16 user_text, bool update_histograms) {
+void ZeroSuggestProvider::ConvertResultsToAutocompleteMatches() {
   matches_.clear();
 
   const TemplateURL* default_provider =
@@ -445,33 +429,24 @@
   const int num_query_results = query_matches_map_.size();
   const int num_nav_results = navigation_results_.size();
   const int num_results = num_query_results + num_nav_results;
-  if (update_histograms) {
-    UMA_HISTOGRAM_COUNTS("ZeroSuggest.QueryResults", num_query_results);
-    UMA_HISTOGRAM_COUNTS("ZeroSuggest.URLResults",  num_nav_results);
-    UMA_HISTOGRAM_COUNTS("ZeroSuggest.AllResults", num_results);
-  }
+  UMA_HISTOGRAM_COUNTS("ZeroSuggest.QueryResults", num_query_results);
+  UMA_HISTOGRAM_COUNTS("ZeroSuggest.URLResults",  num_nav_results);
+  UMA_HISTOGRAM_COUNTS("ZeroSuggest.AllResults", num_results);
 
-  if (num_results == 0 || user_text_modified_)
+  if (num_results == 0)
     return;
 
   // TODO(jered): Rip this out once the first match is decoupled from the
   // current typing in the omnibox.
-  // If the user text is empty, we can autocomplete to the URL.  Otherwise,
-  // don't modify the omnibox text.
-  current_url_match_.inline_autocomplete_offset = user_text.empty() ?
-      0 : string16::npos;
   matches_.push_back(current_url_match_);
 
-  for (SearchProvider::MatchMap::const_iterator it = query_matches_map_.begin();
-       it != query_matches_map_.end(); ++it) {
+  for (SearchProvider::MatchMap::const_iterator it(query_matches_map_.begin());
+       it != query_matches_map_.end(); ++it)
     matches_.push_back(it->second);
-  }
 
-  for (SearchProvider::NavigationResults::const_iterator it =
-           navigation_results_.begin();
-       it != navigation_results_.end(); ++it) {
+  for (SearchProvider::NavigationResults::const_iterator it(
+       navigation_results_.begin()); it != navigation_results_.end(); ++it)
     matches_.push_back(NavigationToMatch(*it));
-  }
 }
 
 AutocompleteMatch ZeroSuggestProvider::MatchForCurrentURL() {
@@ -483,6 +458,7 @@
       HistoryURLProvider::SuggestExactInput(this, input,
                                             !HasHTTPScheme(input.text())));
   match.is_history_what_you_typed_match = false;
+  match.inline_autocomplete_offset = string16::npos;
 
   // The placeholder suggestion for the current URL has high relevance so
   // that it is in the first suggestion slot and inline autocompleted. It
diff --git a/chrome/browser/autocomplete/zero_suggest_provider.h b/chrome/browser/autocomplete/zero_suggest_provider.h
index 155f0af..3d83a35 100644
--- a/chrome/browser/autocomplete/zero_suggest_provider.h
+++ b/chrome/browser/autocomplete/zero_suggest_provider.h
@@ -70,14 +70,13 @@
   // net::URLFetcherDelegate
   virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
 
-  // Initiates a new fetch for the given |url|, limiting suggestions to those
-  // matching |user_text|. |user_text| may be non-empty if the user previously
-  // interacted with zero-suggest suggestions and then unfocused the omnibox.
-  // |permanent_text| is the text version of |url| displayed in the omnibox.
+  // Initiates a new fetch for the given |url|. |user_text| is the user input
+  // and may be non-empty if the user previously interacted with
+  // zero-suggest suggestions and then unfocused the omnibox. |permanent_text|
+  // is the omnibox text for the current page.
   // TODO(jered): Rip out |user_text| once the first match is decoupled from
   // the current typing in the omnibox.
   void StartZeroSuggest(const GURL& url,
-                        const string16& user_text,
                         const string16& permanent_text);
 
  private:
@@ -102,21 +101,22 @@
                    SearchProvider::SuggestResults* suggest_results,
                    SearchProvider::NavigationResults* navigation_results);
 
-  // Creates AutocompleteMatches for "Search |provider_keyword| for
-  // <suggestion>" for all suggestions in |results|, and adds them to |map|.
+  // Creates AutocompleteMatches to search |template_url| for "<suggestion>" for
+  // all suggestions in |results|, and adds them to |map|.
   void AddSuggestResultsToMap(const SearchProvider::SuggestResults& results,
-                              const string16& provider_keyword,
+                              const TemplateURL* template_url,
                               SearchProvider::MatchMap* map);
 
-  // Creates an AutocompleteMatch for "Search |provider_keyword| for
-  // |query_string|".  The supplied |relevance| and |type| and
-  // |accepted_suggestion| will also be used to create the AutocompleteMatch.
+  // Creates an AutocompleteMatch with the provided |relevance| and |type| to
+  // search |template_url| for |query_string|.  |accepted_suggestion| will be
+  // used to generate Assisted Query Stats.
+  //
   // Adds this match to |map|; if such a match already exists, whichever one
   // has lower relevance is eliminated.
-  void AddMatchToMap(const string16& query_string,
-                     const string16& provider_keyword,
-                     int relevance,
+  void AddMatchToMap(int relevance,
                      AutocompleteMatch::Type type,
+                     const TemplateURL* template_url,
+                     const string16& query_string,
                      int accepted_suggestion,
                      SearchProvider::MatchMap* map);
 
@@ -124,21 +124,16 @@
   AutocompleteMatch NavigationToMatch(
       const SearchProvider::NavigationResult& navigation);
 
-  // Sets |user_text_modified_| if the user has modified the omnibox text, based
-  // on the user input |user_text|.
-  void CheckIfTextModfied(const string16& user_text);
-
   // Fetches zero-suggest suggestions for |current_query_|.
   void Run();
 
   // Parses results from the zero-suggest server and updates results.
   void ParseSuggestResults(const base::Value& root_val);
 
-  // Converts the parsed results to a set of AutocompleteMatches, based on user
-  // input |user_text|, and adds them to |matches_|.  If |update_histograms| is
-  // true, also update the histograms for how many results were received.
-  void ConvertResultsToAutocompleteMatches(string16 user_text,
-                                           bool update_histograms);
+  // Converts the parsed results to a set of AutocompleteMatches and adds them
+  // to |matches_|.  Also update the histograms for how many results were
+  // received.
+  void ConvertResultsToAutocompleteMatches();
 
   // Returns an AutocompleteMatch for the current URL. The match should be in
   // the top position so that pressing enter has the effect of reloading the
@@ -151,12 +146,8 @@
   // The URL for which a suggestion fetch is pending.
   std::string current_query_;
 
-  // What the user has typed.
-  string16 original_user_text_;
   // Copy of OmniboxEditModel::permanent_text_.
   string16 permanent_text_;
-  // Whether the user has modified the omnibox since the zero suggest request.
-  bool user_text_modified_;
 
   // Fetcher used to retrieve results.
   scoped_ptr<net::URLFetcher> fetcher_;
diff --git a/chrome/browser/autofill/android/personal_data_manager_android.cc b/chrome/browser/autofill/android/personal_data_manager_android.cc
index 802dc41..a853f92 100644
--- a/chrome/browser/autofill/android/personal_data_manager_android.cc
+++ b/chrome/browser/autofill/android/personal_data_manager_android.cc
@@ -11,8 +11,8 @@
 #include "chrome/browser/autofill/personal_data_manager_factory.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/profile_manager.h"
-#include "components/autofill/browser/field_types.h"
-#include "components/autofill/browser/personal_data_manager.h"
+#include "components/autofill/core/browser/field_types.h"
+#include "components/autofill/core/browser/personal_data_manager.h"
 #include "jni/PersonalDataManager_jni.h"
 
 using base::android::ConvertJavaStringToUTF8;
diff --git a/chrome/browser/autofill/android/personal_data_manager_android.h b/chrome/browser/autofill/android/personal_data_manager_android.h
index 1809b07..6221f8a 100644
--- a/chrome/browser/autofill/android/personal_data_manager_android.h
+++ b/chrome/browser/autofill/android/personal_data_manager_android.h
@@ -7,8 +7,8 @@
 
 #include "base/android/jni_helper.h"
 #include "base/android/scoped_java_ref.h"
-#include "components/autofill/browser/personal_data_manager.h"
-#include "components/autofill/browser/personal_data_manager_observer.h"
+#include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/autofill/core/browser/personal_data_manager_observer.h"
 
 namespace autofill {
 
diff --git a/chrome/browser/autofill/autofill_browsertest.cc b/chrome/browser/autofill/autofill_browsertest.cc
index d2d213f..213e79d 100644
--- a/chrome/browser/autofill/autofill_browsertest.cc
+++ b/chrome/browser/autofill/autofill_browsertest.cc
@@ -13,7 +13,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/autofill/personal_data_manager_factory.h"
 #include "chrome/browser/infobars/confirm_infobar_delegate.h"
 #include "chrome/browser/infobars/infobar_service.h"
@@ -27,16 +27,16 @@
 #include "chrome/common/render_messages.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
-#include "components/autofill/browser/autofill_common_test.h"
-#include "components/autofill/browser/autofill_external_delegate.h"
-#include "components/autofill/browser/autofill_manager.h"
-#include "components/autofill/browser/autofill_manager_test_delegate.h"
-#include "components/autofill/browser/autofill_profile.h"
-#include "components/autofill/browser/credit_card.h"
-#include "components/autofill/browser/personal_data_manager.h"
-#include "components/autofill/browser/personal_data_manager_observer.h"
-#include "components/autofill/browser/validation.h"
 #include "components/autofill/content/browser/autofill_driver_impl.h"
+#include "components/autofill/core/browser/autofill_common_test.h"
+#include "components/autofill/core/browser/autofill_external_delegate.h"
+#include "components/autofill/core/browser/autofill_manager.h"
+#include "components/autofill/core/browser/autofill_manager_test_delegate.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/credit_card.h"
+#include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/autofill/core/browser/personal_data_manager_observer.h"
+#include "components/autofill/core/browser/validation.h"
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
@@ -232,11 +232,9 @@
     AutofillDriverImpl* autofill_driver =
         AutofillDriverImpl::FromWebContents(web_contents);
     AutofillManager* autofill_manager = autofill_driver->autofill_manager();
-    if (autofill_manager->IsNativeUiEnabled()) {
-      scoped_ptr<AutofillExternalDelegate> external_delegate(
-          new TestAutofillExternalDelegate(web_contents, autofill_manager));
-      autofill_driver->SetAutofillExternalDelegate(external_delegate.Pass());
-    }
+    scoped_ptr<AutofillExternalDelegate> external_delegate(
+        new TestAutofillExternalDelegate(web_contents, autofill_manager));
+    autofill_driver->SetAutofillExternalDelegate(external_delegate.Pass());
     autofill_manager->SetTestDelegate(&test_delegate_);
   }
 
@@ -471,14 +469,6 @@
   }
 
   void SendKeyToPopupAndWait(ui::KeyboardCode key) {
-    // TODO(isherman): Remove this condition once the WebKit popup UI code is
-    // removed.
-    if (!external_delegate()) {
-      // When testing the WebKit-based UI, route all keys to the page.
-      SendKeyToPageAndWait(key);
-      return;
-    }
-
     // When testing the native UI, route popup-targeted key presses via the
     // external delegate.
     content::NativeWebKeyboardEvent event;
diff --git a/chrome/browser/autofill/autofill_cc_infobar_delegate.cc b/chrome/browser/autofill/autofill_cc_infobar_delegate.cc
index 185b283..a55a4d0 100644
--- a/chrome/browser/autofill/autofill_cc_infobar_delegate.cc
+++ b/chrome/browser/autofill/autofill_cc_infobar_delegate.cc
@@ -6,8 +6,8 @@
 
 #include "base/logging.h"
 #include "chrome/browser/infobars/infobar_service.h"
-#include "components/autofill/browser/credit_card.h"
-#include "components/autofill/browser/personal_data_manager.h"
+#include "components/autofill/core/browser/credit_card.h"
+#include "components/autofill/core/browser/personal_data_manager.h"
 #include "components/autofill/core/common/autofill_constants.h"
 #include "content/public/browser/page_navigator.h"
 #include "content/public/browser/web_contents.h"
diff --git a/chrome/browser/autofill/autofill_cc_infobar_delegate.h b/chrome/browser/autofill/autofill_cc_infobar_delegate.h
index 14c959a..4941864 100644
--- a/chrome/browser/autofill/autofill_cc_infobar_delegate.h
+++ b/chrome/browser/autofill/autofill_cc_infobar_delegate.h
@@ -11,7 +11,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/string16.h"
 #include "chrome/browser/infobars/confirm_infobar_delegate.h"
-#include "components/autofill/browser/autofill_metrics.h"
+#include "components/autofill/core/browser/autofill_metrics.h"
 #include "ui/base/window_open_disposition.h"
 
 class CreditCard;
diff --git a/chrome/browser/autofill/autofill_driver_impl_browsertest.cc b/chrome/browser/autofill/autofill_driver_impl_browsertest.cc
new file mode 100644
index 0000000..fb3e6a7
--- /dev/null
+++ b/chrome/browser/autofill/autofill_driver_impl_browsertest.cc
@@ -0,0 +1,145 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/memory/scoped_ptr.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_tabstrip.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/url_constants.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/testing_pref_service_syncable.h"
+#include "components/autofill/content/browser/autofill_driver_impl.h"
+#include "components/autofill/core/browser/autofill_manager.h"
+#include "components/autofill/core/browser/test_autofill_manager_delegate.h"
+#include "content/public/browser/navigation_controller.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_types.h"
+#include "content/public/browser/page_navigator.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "content/public/common/url_constants.h"
+#include "content/public/test/test_utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/rect.h"
+
+namespace autofill {
+namespace {
+
+class MockAutofillManagerDelegate
+    : public autofill::TestAutofillManagerDelegate {
+ public:
+  MockAutofillManagerDelegate() {}
+  virtual ~MockAutofillManagerDelegate() {}
+
+  virtual PrefService* GetPrefs() { return &prefs_; }
+
+  user_prefs::PrefRegistrySyncable* GetPrefRegistry() {
+    return prefs_.registry();
+  }
+
+  MOCK_METHOD7(ShowAutofillPopup,
+               void(const gfx::RectF& element_bounds,
+                    base::i18n::TextDirection text_direction,
+                    const std::vector<string16>& values,
+                    const std::vector<string16>& labels,
+                    const std::vector<string16>& icons,
+                    const std::vector<int>& identifiers,
+                    base::WeakPtr<AutofillPopupDelegate> delegate));
+
+  MOCK_METHOD0(HideAutofillPopup, void());
+
+ private:
+  TestingPrefServiceSyncable prefs_;
+
+  DISALLOW_COPY_AND_ASSIGN(MockAutofillManagerDelegate);
+};
+
+// Subclass AutofillDriverImpl so we can create an AutofillDriverImpl instance.
+class TestAutofillDriverImpl : public AutofillDriverImpl {
+ public:
+  TestAutofillDriverImpl(content::WebContents* web_contents,
+                         AutofillManagerDelegate* delegate)
+      : AutofillDriverImpl(
+          web_contents,
+          delegate,
+          g_browser_process->GetApplicationLocale(),
+          AutofillManager::ENABLE_AUTOFILL_DOWNLOAD_MANAGER) {}
+  virtual ~TestAutofillDriverImpl() {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TestAutofillDriverImpl);
+};
+
+}  // namespace
+
+class AutofillDriverImplBrowserTest
+    : public InProcessBrowserTest,
+      public content::WebContentsObserver {
+ public:
+  AutofillDriverImplBrowserTest() {}
+  virtual ~AutofillDriverImplBrowserTest() {}
+
+  virtual void SetUpOnMainThread() OVERRIDE {
+    web_contents_ = browser()->tab_strip_model()->GetActiveWebContents();
+    ASSERT_TRUE(web_contents_ != NULL);
+    Observe(web_contents_);
+    AutofillManager::RegisterUserPrefs(manager_delegate_.GetPrefRegistry());
+
+    autofill_driver_.reset(new TestAutofillDriverImpl(web_contents_,
+                                                      &manager_delegate_));
+  }
+
+  // Normally the WebContents will automatically delete the driver, but here
+  // the driver is owned by this test, so we have to manually destroy.
+  virtual void WebContentsDestroyed(content::WebContents* web_contents)
+      OVERRIDE {
+    DCHECK_EQ(web_contents_, web_contents);
+    autofill_driver_.reset();
+  }
+
+ protected:
+  content::WebContents* web_contents_;
+
+  testing::NiceMock<MockAutofillManagerDelegate> manager_delegate_;
+  scoped_ptr<TestAutofillDriverImpl> autofill_driver_;
+};
+
+IN_PROC_BROWSER_TEST_F(AutofillDriverImplBrowserTest,
+                       SwitchTabAndHideAutofillPopup) {
+  // Notification is different on platforms. On linux this will be called twice,
+  // while on windows only once.
+  EXPECT_CALL(manager_delegate_, HideAutofillPopup())
+      .Times(testing::AtLeast(1));
+
+  content::WindowedNotificationObserver observer(
+      content::NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED,
+      content::Source<content::WebContents>(web_contents_));
+  chrome::AddSelectedTabWithURL(browser(), GURL(content::kAboutBlankURL),
+                                content::PAGE_TRANSITION_AUTO_TOPLEVEL);
+  observer.Wait();
+}
+
+IN_PROC_BROWSER_TEST_F(AutofillDriverImplBrowserTest,
+                       TestPageNavigationHidingAutofillPopup) {
+  // Notification is different on platforms. On linux this will be called twice,
+  // while on windows only once.
+  EXPECT_CALL(manager_delegate_, HideAutofillPopup())
+      .Times(testing::AtLeast(1));
+
+  content::WindowedNotificationObserver observer(
+      content::NOTIFICATION_NAV_ENTRY_COMMITTED,
+      content::Source<content::NavigationController>(
+          &(web_contents_->GetController())));
+  browser()->OpenURL(content::OpenURLParams(
+      GURL(chrome::kChromeUIBookmarksURL), content::Referrer(),
+      CURRENT_TAB, content::PAGE_TRANSITION_TYPED, false));
+  browser()->OpenURL(content::OpenURLParams(
+      GURL(chrome::kChromeUIAboutURL), content::Referrer(),
+      CURRENT_TAB, content::PAGE_TRANSITION_TYPED, false));
+  observer.Wait();
+}
+
+}  // namespace autofill
diff --git a/chrome/browser/autofill/autofill_external_delegate_browsertest.cc b/chrome/browser/autofill/autofill_external_delegate_browsertest.cc
deleted file mode 100644
index 16e7611..0000000
--- a/chrome/browser/autofill/autofill_external_delegate_browsertest.cc
+++ /dev/null
@@ -1,168 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/memory/scoped_ptr.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_tabstrip.h"
-#include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/common/url_constants.h"
-#include "chrome/test/base/in_process_browser_test.h"
-#include "chrome/test/base/testing_pref_service_syncable.h"
-#include "components/autofill/browser/autofill_manager.h"
-#include "components/autofill/browser/test_autofill_driver.h"
-#include "components/autofill/browser/test_autofill_external_delegate.h"
-#include "components/autofill/browser/test_autofill_manager_delegate.h"
-#include "content/public/browser/navigation_controller.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_types.h"
-#include "content/public/browser/page_navigator.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_observer.h"
-#include "content/public/common/url_constants.h"
-#include "content/public/test/test_utils.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gfx/rect.h"
-
-namespace autofill {
-namespace {
-
-class MockAutofillManagerDelegate
-    : public autofill::TestAutofillManagerDelegate {
- public:
-  MockAutofillManagerDelegate() {}
-  virtual ~MockAutofillManagerDelegate() {}
-
-  virtual PrefService* GetPrefs() { return &prefs_; }
-
-  user_prefs::PrefRegistrySyncable* GetPrefRegistry() {
-    return prefs_.registry();
-  }
-
-  MOCK_METHOD7(ShowAutofillPopup,
-               void(const gfx::RectF& element_bounds,
-                    base::i18n::TextDirection text_direction,
-                    const std::vector<string16>& values,
-                    const std::vector<string16>& labels,
-                    const std::vector<string16>& icons,
-                    const std::vector<int>& identifiers,
-                    base::WeakPtr<AutofillPopupDelegate> delegate));
-
-  MOCK_METHOD0(HideAutofillPopup, void());
-
- private:
-  TestingPrefServiceSyncable prefs_;
-
-  DISALLOW_COPY_AND_ASSIGN(MockAutofillManagerDelegate);
-};
-
-// Subclass AutofillManager so we can create AutofillManager instance.
-class TestAutofillManager : public AutofillManager {
- public:
-  TestAutofillManager(AutofillDriver* driver,
-                      autofill::AutofillManagerDelegate* delegate)
-      : AutofillManager(driver,
-                        delegate,
-                        g_browser_process->GetApplicationLocale(),
-                        AutofillManager::ENABLE_AUTOFILL_DOWNLOAD_MANAGER) {}
-  virtual ~TestAutofillManager() {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(TestAutofillManager);
-};
-
-// Subclass AutofillExternalDelegate so we can create an
-// AutofillExternalDelegate instance.
-class TestAutofillExternalDelegate : public AutofillExternalDelegate {
- public:
-  TestAutofillExternalDelegate(content::WebContents* web_contents,
-                               AutofillManager* autofill_manager)
-      : AutofillExternalDelegate(web_contents, autofill_manager) {}
-  virtual ~TestAutofillExternalDelegate() {}
-};
-
-}  // namespace
-
-class AutofillExternalDelegateBrowserTest
-    : public InProcessBrowserTest,
-      public content::WebContentsObserver {
- public:
-  AutofillExternalDelegateBrowserTest() {}
-  virtual ~AutofillExternalDelegateBrowserTest() {}
-
-  virtual void SetUpOnMainThread() OVERRIDE {
-    web_contents_ = browser()->tab_strip_model()->GetActiveWebContents();
-    ASSERT_TRUE(web_contents_ != NULL);
-    Observe(web_contents_);
-
-    AutofillManager::RegisterUserPrefs(manager_delegate_.GetPrefRegistry());
-
-    autofill_driver_.reset(new TestAutofillDriver(web_contents_));
-    autofill_manager_.reset(
-        new TestAutofillManager(autofill_driver_.get(), &manager_delegate_));
-    autofill_external_delegate_.reset(
-        new TestAutofillExternalDelegate(web_contents_,
-                                         autofill_manager_.get()));
-  }
-
-  // Normally the WebContents will automatically delete the delegate, but here
-  // the delegate is owned by this test, so we have to manually destroy.
-  virtual void WebContentsDestroyed(content::WebContents* web_contents)
-      OVERRIDE {
-    DCHECK_EQ(web_contents_, web_contents);
-    autofill_external_delegate_.reset();
-    autofill_manager_.reset();
-    autofill_driver_.reset();
-  }
-
- protected:
-  content::WebContents* web_contents_;
-
-  testing::NiceMock<MockAutofillManagerDelegate> manager_delegate_;
-  scoped_ptr<TestAutofillDriver> autofill_driver_;
-  scoped_ptr<TestAutofillManager> autofill_manager_;
-  scoped_ptr<TestAutofillExternalDelegate> autofill_external_delegate_;
-};
-
-IN_PROC_BROWSER_TEST_F(AutofillExternalDelegateBrowserTest,
-                       SwitchTabAndHideAutofillPopup) {
-  autofill::GenerateTestAutofillPopup(autofill_external_delegate_.get());
-
-  // Notification is different on platforms. On linux this will be called twice,
-  // while on windows only once.
-  EXPECT_CALL(manager_delegate_, HideAutofillPopup())
-      .Times(testing::AtLeast(1));
-
-  content::WindowedNotificationObserver observer(
-      content::NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED,
-      content::Source<content::WebContents>(web_contents_));
-  chrome::AddSelectedTabWithURL(browser(), GURL(content::kAboutBlankURL),
-                                content::PAGE_TRANSITION_AUTO_TOPLEVEL);
-  observer.Wait();
-}
-
-IN_PROC_BROWSER_TEST_F(AutofillExternalDelegateBrowserTest,
-                       TestPageNavigationHidingAutofillPopup) {
-  autofill::GenerateTestAutofillPopup(autofill_external_delegate_.get());
-
-  // Notification is different on platforms. On linux this will be called twice,
-  // while on windows only once.
-  EXPECT_CALL(manager_delegate_, HideAutofillPopup())
-      .Times(testing::AtLeast(1));
-
-  content::WindowedNotificationObserver observer(
-      content::NOTIFICATION_NAV_ENTRY_COMMITTED,
-      content::Source<content::NavigationController>(
-          &(web_contents_->GetController())));
-  browser()->OpenURL(content::OpenURLParams(
-      GURL(chrome::kChromeUIBookmarksURL), content::Referrer(),
-      CURRENT_TAB, content::PAGE_TRANSITION_TYPED, false));
-  browser()->OpenURL(content::OpenURLParams(
-      GURL(chrome::kChromeUIAboutURL), content::Referrer(),
-      CURRENT_TAB, content::PAGE_TRANSITION_TYPED, false));
-  observer.Wait();
-}
-
-}  // namespace autofill
diff --git a/chrome/browser/autofill/autofill_interactive_uitest.cc b/chrome/browser/autofill/autofill_interactive_uitest.cc
index 2199cb5..c040136 100644
--- a/chrome/browser/autofill/autofill_interactive_uitest.cc
+++ b/chrome/browser/autofill/autofill_interactive_uitest.cc
@@ -6,19 +6,20 @@
 #include "base/memory/scoped_ptr.h"
 #include "chrome/browser/autofill/personal_data_manager_factory.h"
 #include "chrome/browser/infobars/confirm_infobar_delegate.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
-#include "components/autofill/browser/autofill_common_test.h"
-#include "components/autofill/browser/autofill_external_delegate.h"
-#include "components/autofill/browser/autofill_manager.h"
-#include "components/autofill/browser/autofill_manager_test_delegate.h"
-#include "components/autofill/browser/autofill_profile.h"
-#include "components/autofill/browser/personal_data_manager.h"
-#include "components/autofill/browser/personal_data_manager_observer.h"
 #include "components/autofill/content/browser/autofill_driver_impl.h"
+#include "components/autofill/core/browser/autofill_common_test.h"
+#include "components/autofill/core/browser/autofill_external_delegate.h"
+#include "components/autofill/core/browser/autofill_manager.h"
+#include "components/autofill/core/browser/autofill_manager_test_delegate.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/autofill/core/browser/personal_data_manager_observer.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "content/public/browser/notification_service.h"
@@ -209,11 +210,9 @@
     AutofillDriverImpl* autofill_driver =
         AutofillDriverImpl::FromWebContents(web_contents);
     AutofillManager* autofill_manager = autofill_driver->autofill_manager();
-    if (autofill_manager->IsNativeUiEnabled()) {
-      scoped_ptr<AutofillExternalDelegate> external_delegate(
-          new TestAutofillExternalDelegate(web_contents, autofill_manager));
-      autofill_driver->SetAutofillExternalDelegate(external_delegate.Pass());
-    }
+    scoped_ptr<AutofillExternalDelegate> external_delegate(
+        new TestAutofillExternalDelegate(web_contents, autofill_manager));
+    autofill_driver->SetAutofillExternalDelegate(external_delegate.Pass());
     autofill_manager->SetTestDelegate(&test_delegate_);
   }
 
diff --git a/chrome/browser/autofill/form_structure_browsertest.cc b/chrome/browser/autofill/form_structure_browsertest.cc
index e4491ab..e6babac 100644
--- a/chrome/browser/autofill/form_structure_browsertest.cc
+++ b/chrome/browser/autofill/form_structure_browsertest.cc
@@ -11,11 +11,11 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
-#include "components/autofill/browser/autofill_manager.h"
-#include "components/autofill/browser/data_driven_test.h"
-#include "components/autofill/browser/form_structure.h"
 #include "components/autofill/content/browser/autofill_driver_impl.h"
-#include "googleurl/src/gurl.h"
+#include "components/autofill/core/browser/autofill_manager.h"
+#include "components/autofill/core/browser/data_driven_test.h"
+#include "components/autofill/core/browser/form_structure.h"
+#include "url/gurl.h"
 
 namespace autofill {
 namespace {
diff --git a/chrome/browser/autofill/personal_data_manager_factory.cc b/chrome/browser/autofill/personal_data_manager_factory.cc
index 5157fe2..17b234e 100644
--- a/chrome/browser/autofill/personal_data_manager_factory.cc
+++ b/chrome/browser/autofill/personal_data_manager_factory.cc
@@ -10,7 +10,7 @@
 #include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/webdata/web_data_service_factory.h"
-#include "components/autofill/browser/personal_data_manager.h"
+#include "components/autofill/core/browser/personal_data_manager.h"
 #include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
 
 namespace autofill {
diff --git a/chrome/browser/autofill/risk/fingerprint_browsertest.cc b/chrome/browser/autofill/risk/fingerprint_browsertest.cc
index 1a1a3f0..ec028a5 100644
--- a/chrome/browser/autofill/risk/fingerprint_browsertest.cc
+++ b/chrome/browser/autofill/risk/fingerprint_browsertest.cc
@@ -169,14 +169,8 @@
   base::MessageLoop message_loop_;
 };
 
-// This test is flaky on Windows. See http://crbug.com/178356.
-#if defined(OS_WIN)
-#define MAYBE_GetFingerprint DISABLED_GetFingerprint
-#else
-#define MAYBE_GetFingerprint GetFingerprint
-#endif
 // Test that getting a fingerprint works on some basic level.
-IN_PROC_BROWSER_TEST_F(AutofillRiskFingerprintTest, MAYBE_GetFingerprint) {
+IN_PROC_BROWSER_TEST_F(AutofillRiskFingerprintTest, GetFingerprint) {
   content::Geoposition position;
   position.latitude = kLatitude;
   position.longitude = kLongitude;
diff --git a/chrome/browser/automation/automation_provider.h b/chrome/browser/automation/automation_provider.h
index cd98c08..ac7ad28 100644
--- a/chrome/browser/automation/automation_provider.h
+++ b/chrome/browser/automation/automation_provider.h
@@ -26,7 +26,7 @@
 #include "chrome/browser/common/cancelable_request.h"
 #include "chrome/common/automation_constants.h"
 #include "chrome/common/content_settings.h"
-#include "components/autofill/browser/field_types.h"
+#include "components/autofill/core/browser/field_types.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/trace_subscriber.h"
diff --git a/chrome/browser/automation/automation_provider_observers.cc b/chrome/browser/automation/automation_provider_observers.cc
index 7a7823d..bd66049 100644
--- a/chrome/browser/automation/automation_provider_observers.cc
+++ b/chrome/browser/automation/automation_provider_observers.cc
@@ -79,9 +79,9 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/process_type.h"
 #include "extensions/common/view_type.h"
-#include "googleurl/src/gurl.h"
 #include "ui/gfx/codec/png_codec.h"
 #include "ui/gfx/rect.h"
+#include "url/gurl.h"
 
 using content::BrowserThread;
 using content::DomOperationNotificationDetails;
diff --git a/chrome/browser/automation/automation_provider_observers.h b/chrome/browser/automation/automation_provider_observers.h
index 9d7406d..a92bd5d 100644
--- a/chrome/browser/automation/automation_provider_observers.h
+++ b/chrome/browser/automation/automation_provider_observers.h
@@ -20,8 +20,8 @@
 #include "base/values.h"
 #include "chrome/browser/automation/automation_provider_json.h"
 #include "chrome/browser/bookmarks/bookmark_model_observer.h"
-#include "components/autofill/browser/personal_data_manager.h"
-#include "components/autofill/browser/personal_data_manager_observer.h"
+#include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/autofill/core/browser/personal_data_manager_observer.h"
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/cros/network_library.h"
 #include "chrome/browser/chromeos/login/enrollment/enrollment_screen.h"
@@ -33,7 +33,6 @@
 #include "chrome/browser/download/all_download_item_notifier.h"
 #include "chrome/browser/history/history_service.h"
 #include "chrome/browser/history/history_types.h"
-#include "chrome/browser/importer/importer_data_types.h"
 #include "chrome/browser/importer/importer_progress_observer.h"
 #include "chrome/browser/memory_details.h"
 #include "chrome/browser/password_manager/password_store_change.h"
@@ -42,6 +41,7 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/automation_constants.h"
 #include "chrome/common/extensions/extension_constants.h"
+#include "chrome/common/importer/importer_data_types.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/download_item.h"
 #include "content/public/browser/download_manager.h"
@@ -936,28 +936,6 @@
   DISALLOW_COPY_AND_ASSIGN(VirtualConnectObserver);
 };
 
-// Waits for enterprise device enrollment to complete and returns the status to
-// the automation provider.
-class EnrollmentObserver
-    : public chromeos::EnrollmentScreen::TestingObserver {
- public:
-  EnrollmentObserver(AutomationProvider* automation,
-                     IPC::Message* reply_message,
-                     chromeos::EnrollmentScreen* enrollment_screen);
-
-  virtual ~EnrollmentObserver();
-
-  // chromeos::EnrollmentScreen::Observer implementation.
-  virtual void OnEnrollmentComplete(bool succeeded);
-
- private:
-  base::WeakPtr<AutomationProvider> automation_;
-  scoped_ptr<IPC::Message> reply_message_;
-  chromeos::EnrollmentScreen* enrollment_screen_;
-
-  DISALLOW_COPY_AND_ASSIGN(EnrollmentObserver);
-};
-
 #endif  // defined(OS_CHROMEOS)
 
 // Waits for the bookmark model to load.
diff --git a/chrome/browser/automation/automation_provider_observers_chromeos.cc b/chrome/browser/automation/automation_provider_observers_chromeos.cc
index adb3dcd..621a9ba 100644
--- a/chrome/browser/automation/automation_provider_observers_chromeos.cc
+++ b/chrome/browser/automation/automation_provider_observers_chromeos.cc
@@ -425,30 +425,3 @@
   }
   return virt;
 }
-
-EnrollmentObserver::EnrollmentObserver(AutomationProvider* automation,
-    IPC::Message* reply_message,
-    chromeos::EnrollmentScreen* enrollment_screen)
-    : automation_(automation->AsWeakPtr()),
-      reply_message_(reply_message),
-      enrollment_screen_(enrollment_screen) {
-  enrollment_screen_->AddTestingObserver(this);
-}
-
-EnrollmentObserver::~EnrollmentObserver() {}
-
-void EnrollmentObserver::OnEnrollmentComplete(bool succeeded) {
-  enrollment_screen_->RemoveTestingObserver(this);
-  if (automation_) {
-    if (succeeded) {
-      AutomationJSONReply(automation_.get(), reply_message_.release())
-          .SendSuccess(NULL);
-    } else {
-      scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
-      return_value->SetString("error_string", "Enrollment failed.");
-      AutomationJSONReply(automation_.get(), reply_message_.release())
-          .SendSuccess(return_value.get());
-    }
-  }
-  delete this;
-}
diff --git a/chrome/browser/automation/automation_resource_message_filter.cc b/chrome/browser/automation/automation_resource_message_filter.cc
index fafded1..05ccab5 100644
--- a/chrome/browser/automation/automation_resource_message_filter.cc
+++ b/chrome/browser/automation/automation_resource_message_filter.cc
@@ -16,10 +16,10 @@
 #include "chrome/common/render_messages.h"
 #include "content/public/browser/browser_message_filter.h"
 #include "content/public/browser/browser_thread.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/net_errors.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_filter.h"
+#include "url/gurl.h"
 
 using content::BrowserMessageFilter;
 using content::BrowserThread;
diff --git a/chrome/browser/automation/automation_util.cc b/chrome/browser/automation/automation_util.cc
index ccfb056..f482544 100644
--- a/chrome/browser/automation/automation_util.cc
+++ b/chrome/browser/automation/automation_util.cc
@@ -13,7 +13,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/synchronization/waitable_event.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/automation/automation_provider.h"
 #include "chrome/browser/automation/automation_provider_json.h"
diff --git a/chrome/browser/automation/testing_automation_provider.cc b/chrome/browser/automation/testing_automation_provider.cc
index d59502f..b37e935 100644
--- a/chrome/browser/automation/testing_automation_provider.cc
+++ b/chrome/browser/automation/testing_automation_provider.cc
@@ -24,7 +24,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_restrictions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/autocomplete/autocomplete_controller.h"
 #include "chrome/browser/autocomplete/autocomplete_match.h"
@@ -61,8 +61,6 @@
 #include "chrome/browser/extensions/updater/extension_updater.h"
 #include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/history/top_sites.h"
-#include "chrome/browser/importer/importer_host.h"
-#include "chrome/browser/importer/importer_list.h"
 #include "chrome/browser/infobars/confirm_infobar_delegate.h"
 #include "chrome/browser/infobars/infobar_service.h"
 #include "chrome/browser/lifetime/application_lifetime.h"
@@ -112,6 +110,7 @@
 #include "chrome/common/automation_messages.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_notification_types.h"
+#include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/extensions/background_info.h"
 #include "chrome/common/extensions/extension.h"
@@ -120,7 +119,6 @@
 #include "chrome/common/extensions/permissions/permissions_data.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/render_messages.h"
-#include "components/breakpad/common/breakpad_paths.h"
 #include "content/public/browser/browser_child_process_host_iterator.h"
 #include "content/public/browser/child_process_data.h"
 #include "content/public/browser/favicon_status.h"
@@ -136,6 +134,7 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/child_process_host.h"
 #include "content/public/common/common_param_traits.h"
+#include "content/public/common/drop_data.h"
 #include "content/public/common/geoposition.h"
 #include "content/public/common/ssl_status.h"
 #include "extensions/browser/view_type_utils.h"
@@ -146,7 +145,6 @@
 #include "ui/base/events/event_constants.h"
 #include "ui/base/keycodes/keyboard_codes.h"
 #include "ui/base/ui_base_types.h"
-#include "webkit/common/webdropdata.h"
 #include "webkit/plugins/webplugininfo.h"
 
 #if defined(ENABLE_CONFIGURATION_POLICY)
@@ -249,11 +247,7 @@
 };
 
 TestingAutomationProvider::TestingAutomationProvider(Profile* profile)
-    : AutomationProvider(profile)
-#if defined(OS_CHROMEOS)
-      , power_manager_observer_(NULL)
-#endif
-      {
+    : AutomationProvider(profile) {
   BrowserList::AddObserver(this);
   registrar_.Add(this, chrome::NOTIFICATION_SESSION_END,
                  content::NotificationService::AllSources());
@@ -302,40 +296,6 @@
 #endif  // !defined(OS_CHROMEOS) && !defined(OS_MACOSX)
 }
 
-void TestingAutomationProvider::OnSourceProfilesLoaded() {
-  DCHECK_NE(static_cast<ImporterList*>(NULL), importer_list_.get());
-
-  // Get the correct profile based on the browser that the user provided.
-  importer::SourceProfile source_profile;
-  size_t i = 0;
-  size_t importers_count = importer_list_->count();
-  for ( ; i < importers_count; ++i) {
-    importer::SourceProfile profile = importer_list_->GetSourceProfileAt(i);
-    if (profile.importer_name == import_settings_data_.browser_name) {
-      source_profile = profile;
-      break;
-    }
-  }
-  // If we made it to the end of the loop, then the input was bad.
-  if (i == importers_count) {
-    AutomationJSONReply(this, import_settings_data_.reply_message)
-        .SendError("Invalid browser name string found.");
-    return;
-  }
-
-  // Deletes itself.
-  ImporterHost* importer_host = new ImporterHost;
-  importer_host->SetObserver(
-      new AutomationProviderImportSettingsObserver(
-          this, import_settings_data_.reply_message));
-
-  Profile* target_profile = import_settings_data_.browser->profile();
-  importer_host->StartImportSettings(source_profile,
-                                     target_profile,
-                                     import_settings_data_.import_items,
-                                     new ProfileWriter(target_profile));
-}
-
 void TestingAutomationProvider::Observe(
     int type,
     const content::NotificationSource& source,
@@ -943,7 +903,7 @@
   }
 
   // Emulate drag and drop to set the file paths to the file upload control.
-  WebDropData drop_data;
+  content::DropData drop_data;
   for (size_t path_index = 0; path_index < paths->GetSize(); ++path_index) {
     string16 path;
     if (!paths->GetString(path_index, &path)) {
@@ -953,7 +913,7 @@
     }
 
     drop_data.filenames.push_back(
-        WebDropData::FileInfo(path, string16()));
+        content::DropData::FileInfo(path, string16()));
   }
 
   const gfx::Point client(x, y);
@@ -1897,9 +1857,6 @@
   browser_handler_map_["SaveTabContents"] =
       &TestingAutomationProvider::SaveTabContents;
 
-  browser_handler_map_["ImportSettings"] =
-      &TestingAutomationProvider::ImportSettings;
-
   browser_handler_map_["AddSavedPassword"] =
       &TestingAutomationProvider::AddSavedPassword;
   browser_handler_map_["RemoveSavedPassword"] =
@@ -2238,7 +2195,7 @@
   properties->SetString("command_line_string",
       CommandLine::ForCurrentProcess()->GetCommandLineString());
   base::FilePath dumps_path;
-  PathService::Get(breakpad::DIR_CRASH_DUMPS, &dumps_path);
+  PathService::Get(chrome::DIR_CRASH_DUMPS, &dumps_path);
   properties->SetString("DIR_CRASH_DUMPS", dumps_path.value());
 #if defined(USE_AURA)
   properties->SetBoolean("aura", true);
@@ -3237,51 +3194,6 @@
       this, reply_message);
 }
 
-// Refer to ImportSettings() in chrome/test/pyautolib/pyauto.py for sample
-// json input.
-// Sample json output: "{}"
-void TestingAutomationProvider::ImportSettings(Browser* browser,
-                                               DictionaryValue* args,
-                                               IPC::Message* reply_message) {
-  // Map from the json string passed over to the import item masks.
-  std::map<std::string, importer::ImportItem> string_to_import_item;
-  string_to_import_item["HISTORY"] = importer::HISTORY;
-  string_to_import_item["FAVORITES"] = importer::FAVORITES;
-  string_to_import_item["COOKIES"] = importer::COOKIES;
-  string_to_import_item["PASSWORDS"] = importer::PASSWORDS;
-  string_to_import_item["SEARCH_ENGINES"] = importer::SEARCH_ENGINES;
-  string_to_import_item["HOME_PAGE"] = importer::HOME_PAGE;
-  string_to_import_item["ALL"] = importer::ALL;
-
-  ListValue* import_items_list = NULL;
-  if (!args->GetString("import_from", &import_settings_data_.browser_name) ||
-      !args->GetList("import_items", &import_items_list)) {
-    AutomationJSONReply(this, reply_message)
-        .SendError("Incorrect type for one or more of the arguments.");
-    return;
-  }
-
-  import_settings_data_.import_items = 0;
-  int num_items = import_items_list->GetSize();
-  for (int i = 0; i < num_items; i++) {
-    std::string item;
-    // If the provided string is not part of the map, error out.
-    if (!import_items_list->GetString(i, &item) ||
-        !ContainsKey(string_to_import_item, item)) {
-      AutomationJSONReply(this, reply_message)
-          .SendError("Invalid item string found in import_items.");
-      return;
-    }
-    import_settings_data_.import_items |= string_to_import_item[item];
-  }
-
-  import_settings_data_.browser = browser;
-  import_settings_data_.reply_message = reply_message;
-
-  importer_list_ = new ImporterList(NULL);
-  importer_list_->DetectSourceProfiles(this);
-}
-
 namespace {
 
 // Translates a dictionary password to a PasswordForm struct.
diff --git a/chrome/browser/automation/testing_automation_provider.h b/chrome/browser/automation/testing_automation_provider.h
index 7298c1d..df1fadb 100644
--- a/chrome/browser/automation/testing_automation_provider.h
+++ b/chrome/browser/automation/testing_automation_provider.h
@@ -17,7 +17,6 @@
 #include "chrome/browser/automation/automation_provider.h"
 #include "chrome/browser/automation/automation_provider_json.h"
 #include "chrome/browser/history/history_service.h"
-#include "chrome/browser/importer/importer_list_observer.h"
 #include "chrome/browser/ui/browser_list_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "content/public/common/page_type.h"
@@ -26,12 +25,11 @@
 #include "third_party/WebKit/public/web/WebInputEvent.h"
 
 #if defined(OS_CHROMEOS)
-// TODO(sque): move to a ChromeOS-specific class. See crosbug.com/22081.
-class PowerManagerClientObserverForTesting;
-#endif  // defined(OS_CHROMEOS)
+#include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
+#include "chromeos/dbus/power_manager_client.h"
+#endif
 
 class CreditCard;
-class ImporterList;
 
 namespace base {
 class DictionaryValue;
@@ -53,7 +51,9 @@
 // This is an automation provider containing testing calls.
 class TestingAutomationProvider : public AutomationProvider,
                                   public chrome::BrowserListObserver,
-                                  public importer::ImporterListObserver,
+#if defined(OS_CHROMEOS)
+                                  public chromeos::PowerManagerClient::Observer,
+#endif
                                   public content::NotificationObserver {
  public:
   explicit TestingAutomationProvider(Profile* profile);
@@ -65,28 +65,22 @@
   virtual void OnChannelError() OVERRIDE;
 
  private:
-  // Storage for ImportSettings() to resume operations after a callback.
-  struct ImportSettingsData {
-    string16 browser_name;
-    int import_items;
-    Browser* browser;
-    IPC::Message* reply_message;
-  };
-
   virtual ~TestingAutomationProvider();
 
   // chrome::BrowserListObserver:
   virtual void OnBrowserAdded(Browser* browser) OVERRIDE;
   virtual void OnBrowserRemoved(Browser* browser) OVERRIDE;
 
-  // importer::ImporterListObserver:
-  virtual void OnSourceProfilesLoaded() OVERRIDE;
-
   // content::NotificationObserver:
   virtual void Observe(int type,
                        const content::NotificationSource& source,
                        const content::NotificationDetails& details) OVERRIDE;
 
+#if defined(OS_CHROMEOS)
+  // chromeos::PowerManagerClient::Observer:
+  virtual void PowerChanged(const power_manager::PowerSupplyProperties& proto);
+#endif
+
   // IPC Message callbacks.
   void CloseBrowser(int handle, IPC::Message* reply_message);
   void ActivateTab(int handle, int at_index, int* status);
@@ -456,12 +450,6 @@
                        base::DictionaryValue* args,
                        IPC::Message* reply_message);
 
-  // Import the given settings from the given browser.
-  // Uses the JSON interface for input/output.
-  void ImportSettings(Browser* browser,
-                      base::DictionaryValue* args,
-                      IPC::Message* reply_message);
-
   // Add a new entry to the password store based on the password information
   // provided. This method can also be used to add a blacklisted site (which
   // will never fill in the password).
@@ -1443,9 +1431,7 @@
   void EnsureTabSelected(Browser* browser, content::WebContents* tab);
 
 #if defined(OS_CHROMEOS)
-  // Avoid scoped ptr here to avoid having to define it completely in the
-  // non-ChromeOS code.
-  PowerManagerClientObserverForTesting* power_manager_observer_;
+  power_manager::PowerSupplyProperties power_supply_properties_;
 #endif  // defined(OS_CHROMEOS)
 
   std::map<std::string, JsonHandler> handler_map_;
@@ -1453,12 +1439,6 @@
 
   content::NotificationRegistrar registrar_;
 
-  // Used to enumerate browser profiles.
-  scoped_refptr<ImporterList> importer_list_;
-
-  // The stored data for the ImportSettings operation.
-  ImportSettingsData import_settings_data_;
-
   // The automation event observer queue. It is lazily created when an observer
   // is added to avoid overhead when not needed.
   scoped_ptr<AutomationEventQueue> automation_event_queue_;
diff --git a/chrome/browser/automation/testing_automation_provider_chromeos.cc b/chrome/browser/automation/testing_automation_provider_chromeos.cc
index f14f594..0406ea6 100644
--- a/chrome/browser/automation/testing_automation_provider_chromeos.cc
+++ b/chrome/browser/automation/testing_automation_provider_chromeos.cc
@@ -12,7 +12,7 @@
 #include "base/prefs/pref_service.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/automation/automation_provider_json.h"
 #include "chrome/browser/automation/automation_provider_observers.h"
 #include "chrome/browser/automation/automation_util.h"
@@ -44,7 +44,6 @@
 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
 #include "chrome/common/pref_names.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/power_manager_client.h"
 #include "chromeos/dbus/session_manager_client.h"
 #include "chromeos/dbus/update_engine_client.h"
 #include "chromeos/network/network_state_handler.h"
@@ -156,21 +155,14 @@
   }
 }
 
-// Last reported power status.
-chromeos::PowerSupplyStatus global_power_status;
-
 }  // namespace
 
-class PowerManagerClientObserverForTesting
-    : public chromeos::PowerManagerClient::Observer {
- public:
-  virtual ~PowerManagerClientObserverForTesting() {}
-
-  virtual void PowerChanged(const chromeos::PowerSupplyStatus& status)
-      OVERRIDE {
-    global_power_status = status;
-  }
-};
+#if defined(OS_CHROMEOS)
+void TestingAutomationProvider::PowerChanged(
+    const power_manager::PowerSupplyProperties& proto) {
+  power_supply_properties_ = proto;
+}
+#endif
 
 void TestingAutomationProvider::AcceptOOBENetworkScreen(
     DictionaryValue* args,
@@ -502,20 +494,26 @@
                                                IPC::Message* reply_message) {
   scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
 
-  return_value->SetBoolean("battery_is_present",
-                           global_power_status.battery_is_present);
-  return_value->SetBoolean("line_power_on", global_power_status.line_power_on);
-  if (global_power_status.battery_is_present) {
-    return_value->SetBoolean("battery_fully_charged",
-                             global_power_status.battery_is_full);
+  const bool battery_is_present = power_supply_properties_.battery_state() !=
+      power_manager::PowerSupplyProperties_BatteryState_NOT_PRESENT;
+  const bool line_power_on = power_supply_properties_.external_power() !=
+      power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED;
+
+  return_value->SetBoolean("battery_is_present", battery_is_present);
+  return_value->SetBoolean("line_power_on", line_power_on);
+
+  if (battery_is_present) {
+    const bool battery_is_full = power_supply_properties_.battery_state() ==
+        power_manager::PowerSupplyProperties_BatteryState_FULL;
+    return_value->SetBoolean("battery_fully_charged", battery_is_full);
     return_value->SetDouble("battery_percentage",
-                            global_power_status.battery_percentage);
-    if (global_power_status.line_power_on) {
-      int64 time = global_power_status.battery_seconds_to_full;
-      if (time > 0 || global_power_status.battery_is_full)
+                            power_supply_properties_.battery_percent());
+    if (line_power_on) {
+      int64 time = power_supply_properties_.battery_time_to_full_sec();
+      if (time > 0 || battery_is_full)
         return_value->SetInteger("battery_seconds_to_full", time);
     } else {
-      int64 time = global_power_status.battery_seconds_to_empty;
+      int64 time = power_supply_properties_.battery_time_to_empty_sec();
       if (time > 0)
         return_value->SetInteger("battery_seconds_to_empty", time);
     }
@@ -1245,14 +1243,11 @@
 }
 
 void TestingAutomationProvider::AddChromeosObservers() {
-  power_manager_observer_ = new PowerManagerClientObserverForTesting;
   chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
-      AddObserver(power_manager_observer_);
+      AddObserver(this);
 }
 
 void TestingAutomationProvider::RemoveChromeosObservers() {
   chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
-      RemoveObserver(power_manager_observer_);
-  delete power_manager_observer_;
-  power_manager_observer_ = NULL;
+      RemoveObserver(this);
 }
diff --git a/chrome/browser/automation/url_request_automation_job.cc b/chrome/browser/automation/url_request_automation_job.cc
index bf3ed52..a815718 100644
--- a/chrome/browser/automation/url_request_automation_job.cc
+++ b/chrome/browser/automation/url_request_automation_job.cc
@@ -7,7 +7,7 @@
 #include "base/bind.h"
 #include "base/compiler_specific.h"
 #include "base/message_loop.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/automation/automation_resource_message_filter.h"
 #include "chrome/common/automation_messages.h"
 #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/background/background_application_list_model.cc b/chrome/browser/background/background_application_list_model.cc
index f16a3a6..c5d2538 100644
--- a/chrome/browser/background/background_application_list_model.cc
+++ b/chrome/browser/background/background_application_list_model.cc
@@ -43,7 +43,8 @@
 class ExtensionNameComparator {
  public:
   explicit ExtensionNameComparator(icu::Collator* collator);
-  bool operator()(const Extension* x, const Extension* y);
+  bool operator()(const scoped_refptr<const Extension>& x,
+                  const scoped_refptr<const Extension>& y);
 
  private:
   icu::Collator* collator_;
@@ -53,11 +54,11 @@
   : collator_(collator) {
 }
 
-bool ExtensionNameComparator::operator()(const Extension* x,
-                                         const Extension* y) {
+bool ExtensionNameComparator::operator()(
+    const scoped_refptr<const Extension>& x,
+    const scoped_refptr<const Extension>& y) {
   return l10n_util::StringComparator<string16>(collator_)(
-    UTF8ToUTF16(x->name()),
-    UTF8ToUTF16(y->name()));
+      UTF8ToUTF16(x->name()), UTF8ToUTF16(y->name()));
 }
 
 // Background application representation, private to the
diff --git a/chrome/browser/background/background_application_list_model_unittest.cc b/chrome/browser/background/background_application_list_model_unittest.cc
index de09c28..0ae8476 100644
--- a/chrome/browser/background/background_application_list_model_unittest.cc
+++ b/chrome/browser/background/background_application_list_model_unittest.cc
@@ -355,7 +355,7 @@
       new BackgroundApplicationListModel(profile_.get()));
   ASSERT_EQ(0U, model->size());
 
-  static const int kIterations = 500;
+  static const int kIterations = 20;
   ExtensionCollection extensions;
   size_t count = 0;
   size_t expected = 0;
diff --git a/chrome/browser/background/background_contents_service.h b/chrome/browser/background/background_contents_service.h
index 3cddb7d..50057cf 100644
--- a/chrome/browser/background/background_contents_service.h
+++ b/chrome/browser/background/background_contents_service.h
@@ -16,8 +16,8 @@
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "content/public/common/window_container_type.h"
-#include "googleurl/src/gurl.h"
 #include "ui/base/window_open_disposition.h"
+#include "url/gurl.h"
 
 class CommandLine;
 class PrefService;
diff --git a/chrome/browser/background/background_contents_service_unittest.cc b/chrome/browser/background/background_contents_service_unittest.cc
index 8d7d40a..6d3bb26 100644
--- a/chrome/browser/background/background_contents_service_unittest.cc
+++ b/chrome/browser/background/background_contents_service_unittest.cc
@@ -19,9 +19,9 @@
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/browser/notification_service.h"
-#include "googleurl/src/gurl.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
+#include "url/gurl.h"
 
 class BackgroundContentsServiceTest : public testing::Test {
  public:
diff --git a/chrome/browser/background/background_mode_manager.cc b/chrome/browser/background/background_mode_manager.cc
index e6a0b96..8bb5d71 100644
--- a/chrome/browser/background/background_mode_manager.cc
+++ b/chrome/browser/background/background_mode_manager.cc
@@ -309,7 +309,12 @@
           // treated as new installs.
           if (extensions::ExtensionSystem::Get(profile)->extension_service()->
                   is_ready()) {
-            OnBackgroundAppInstalled(extension);
+            bool is_being_reloaded = false;
+            CheckReloadStatus(extension, &is_being_reloaded);
+            // No need to show the notification if we showed to the user
+            // previously for this app.
+            if (!is_being_reloaded)
+              OnBackgroundAppInstalled(extension);
           }
         }
       }
@@ -487,7 +492,7 @@
       chrome::ShowAboutChrome(bmd->GetBrowserWindow());
       break;
     case IDC_TASK_MANAGER:
-      chrome::OpenTaskManager(bmd->GetBrowserWindow(), true);
+      chrome::OpenTaskManager(bmd->GetBrowserWindow());
       break;
     case IDC_EXIT:
       content::RecordAction(UserMetricsAction("Exit"));
@@ -623,8 +628,25 @@
   CreateStatusTrayIcon();
 
   // Notify the user that a background app has been installed.
-  if (extension)  // NULL when called by unit tests.
+  if (extension) {  // NULL when called by unit tests.
     DisplayAppInstalledNotification(extension);
+  }
+}
+
+void BackgroundModeManager::CheckReloadStatus(
+    const Extension* extension,
+    bool* is_being_reloaded) {
+    // Walk the BackgroundModeData for all profiles to see if one of their
+    // extensions is being reloaded.
+    for (BackgroundModeInfoMap::const_iterator it =
+             background_mode_data_.begin();
+         it != background_mode_data_.end();
+         ++it) {
+      Profile* profile = it->first;
+      // If the extension is being reloaded, no need to show a notification.
+      if (profile->GetExtensionService()->IsBeingReloaded(extension->id()))
+        *is_being_reloaded = true;
+    }
 }
 
 void BackgroundModeManager::CreateStatusTrayIcon() {
diff --git a/chrome/browser/background/background_mode_manager.h b/chrome/browser/background/background_mode_manager.h
index 1600cd1..e1c8051 100644
--- a/chrome/browser/background/background_mode_manager.h
+++ b/chrome/browser/background/background_mode_manager.h
@@ -85,6 +85,9 @@
                            ProfileInfoCacheStorage);
   FRIEND_TEST_ALL_PREFIXES(BackgroundModeManagerTest,
                            ProfileInfoCacheObserver);
+  FRIEND_TEST_ALL_PREFIXES(BackgroundAppBrowserTest,
+                           ReloadBackgroundApp);
+
   class BackgroundModeData : public ui::SimpleMenuModel::Delegate {
    public:
     explicit BackgroundModeData(
@@ -183,7 +186,15 @@
   // Invoked when an extension is installed so we can ensure that
   // launch-on-startup is enabled if appropriate. |extension| can be NULL when
   // called from unit tests.
-  void OnBackgroundAppInstalled(const extensions::Extension* extension);
+  void OnBackgroundAppInstalled(
+      const extensions::Extension* extension);
+
+  // Walk the list of profiles and see if an extension or app is being
+  // currently upgraded or reloaded by any profile.  If so, update the
+  // output variables appropriately.
+  void CheckReloadStatus(
+      const extensions::Extension* extension,
+      bool* is_being_reloaded);
 
   // Called to make sure that our launch-on-startup mode is properly set.
   // (virtual so we can override for tests).
@@ -191,7 +202,8 @@
 
   // Invoked when a background app is installed so we can display a
   // platform-specific notification to the user.
-  void DisplayAppInstalledNotification(const extensions::Extension* extension);
+  virtual void DisplayAppInstalledNotification(
+      const extensions::Extension* extension);
 
   // Invoked to put Chrome in KeepAlive mode - chrome runs in the background
   // and has a status bar icon.
diff --git a/chrome/browser/bookmarks/bookmark_codec.cc b/chrome/browser/bookmarks/bookmark_codec.cc
index c4d0c30..54116bf 100644
--- a/chrome/browser/bookmarks/bookmark_codec.cc
+++ b/chrome/browser/bookmarks/bookmark_codec.cc
@@ -10,9 +10,9 @@
 #include "base/strings/string_util.h"
 #include "base/values.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
-#include "googleurl/src/gurl.h"
 #include "grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "url/gurl.h"
 
 using base::Time;
 
diff --git a/chrome/browser/bookmarks/bookmark_editor.cc b/chrome/browser/bookmarks/bookmark_editor.cc
deleted file mode 100644
index 0cdb1af..0000000
--- a/chrome/browser/bookmarks/bookmark_editor.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/bookmarks/bookmark_editor.h"
-
-#include "grit/generated_resources.h"
-
-BookmarkEditor::EditDetails::EditDetails(Type node_type)
-    : type(node_type), existing_node(NULL), parent_node(NULL), index(-1) {
-}
-
-BookmarkNode::Type BookmarkEditor::EditDetails::GetNodeType() const {
-  BookmarkNode::Type node_type = BookmarkNode::URL;
-  switch (type) {
-    case EXISTING_NODE:
-      node_type = existing_node->type();
-      break;
-    case NEW_URL:
-      node_type = BookmarkNode::URL;
-      break;
-    case NEW_FOLDER:
-      node_type = BookmarkNode::FOLDER;
-      break;
-    default:
-      NOTREACHED();
-  }
-  return node_type;
-}
-
-int BookmarkEditor::EditDetails::GetWindowTitleId() const {
-  int dialog_title = IDS_BOOKMARK_EDITOR_TITLE;
-  switch (type) {
-    case EditDetails::EXISTING_NODE:
-    case EditDetails::NEW_URL:
-      dialog_title = (type == EditDetails::EXISTING_NODE &&
-                      existing_node->type() == BookmarkNode::FOLDER) ?
-          IDS_BOOKMARK_FOLDER_EDITOR_WINDOW_TITLE :
-          IDS_BOOKMARK_EDITOR_TITLE;
-      break;
-    case EditDetails::NEW_FOLDER:
-      dialog_title = urls.empty() ?
-          IDS_BOOKMARK_FOLDER_EDITOR_WINDOW_TITLE_NEW :
-          IDS_BOOKMARK_ALL_TABS_DIALOG_TITLE;
-      break;
-    default:
-      NOTREACHED();
-  }
-  return dialog_title;
-}
-
-BookmarkEditor::EditDetails BookmarkEditor::EditDetails::EditNode(
-    const BookmarkNode* node) {
-  EditDetails details(EXISTING_NODE);
-  details.existing_node = node;
-  if (node)
-    details.parent_node = node->parent();
-  return details;
-}
-
-BookmarkEditor::EditDetails BookmarkEditor::EditDetails::AddNodeInFolder(
-    const BookmarkNode* parent_node,
-    int index,
-    const GURL& url,
-    const string16& title) {
-  EditDetails details(NEW_URL);
-  details.parent_node = parent_node;
-  details.index = index;
-  details.url = url;
-  details.title = title;
-  return details;
-}
-
-BookmarkEditor::EditDetails BookmarkEditor::EditDetails::AddFolder(
-    const BookmarkNode* parent_node,
-    int index) {
-  EditDetails details(NEW_FOLDER);
-  details.parent_node = parent_node;
-  details.index = index;
-  return details;
-}
-
-BookmarkEditor::EditDetails::~EditDetails() {
-}
diff --git a/chrome/browser/bookmarks/bookmark_editor.h b/chrome/browser/bookmarks/bookmark_editor.h
deleted file mode 100644
index b398028..0000000
--- a/chrome/browser/bookmarks/bookmark_editor.h
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_BOOKMARKS_BOOKMARK_EDITOR_H_
-#define CHROME_BROWSER_BOOKMARKS_BOOKMARK_EDITOR_H_
-
-#include <utility>
-#include <vector>
-
-#include "base/strings/string16.h"
-#include "chrome/browser/bookmarks/bookmark_model.h"
-#include "ui/gfx/native_widget_types.h"
-
-class Browser;
-class GURL;
-class Profile;
-
-// Small, cross platform interface that shows the correct platform specific
-// bookmark editor dialog.
-class BookmarkEditor {
- public:
-  // An enumeration of the possible configurations offered.
-  enum Configuration {
-    SHOW_TREE,
-    NO_TREE
-  };
-
-  // Describes what the user is editing.
-  class EditDetails {
-   public:
-    // Returns the type of the existing or new node.
-    BookmarkNode::Type GetNodeType() const;
-
-    // Returns the resource id for the string resource to use on the window
-    // title for this edit operation.
-    int GetWindowTitleId() const;
-
-    // Returns an EditDetails instance for the user editing the given bookmark.
-    static EditDetails EditNode(const BookmarkNode* node);
-
-    // Returns an EditDetails instance for the user adding a bookmark within
-    // a given parent node with a specified index.
-    static EditDetails AddNodeInFolder(const BookmarkNode* parent_node,
-                                       int index,
-                                       const GURL& url,
-                                       const string16& title);
-
-    // Returns an EditDetails instance for the user adding a folder within a
-    // given parent node with a specified index.
-    static EditDetails AddFolder(const BookmarkNode* parent_node,
-                                 int index);
-
-    enum Type {
-      // The user is editing an existing node in the model. The node the user
-      // is editing is set in |existing_node|.
-      EXISTING_NODE,
-
-      // A new bookmark should be created if the user accepts the edit.
-      // |existing_node| is null in this case.
-      NEW_URL,
-
-      // A new folder bookmark should be created if the user accepts the edit.
-      // The contents of the folder should be that of |urls|.
-      // |existing_node| is null in this case.
-      NEW_FOLDER
-    };
-
-    ~EditDetails();
-
-    // See description of enum value for details.
-    const Type type;
-
-    // If type == EXISTING_NODE this gives the existing node.
-    const BookmarkNode* existing_node;
-
-    // If type == NEW_URL or type == NEW_FOLDER this gives the parent node
-    // to place the new node in.
-    const BookmarkNode* parent_node;
-
-    // If type == NEW_URL or type == NEW_FOLDER this gives the index to insert
-    // the new node at.
-    int index;
-
-    // If type == NEW_URL this gives the URL/title.
-    GURL url;
-    string16 title;
-
-    // If type == NEW_FOLDER, this is the urls/title pairs to add to the
-    // folder.
-    std::vector<std::pair<GURL, string16> > urls;
-
-   private:
-    explicit EditDetails(Type node_type);
-  };
-
-  // Shows the bookmark editor. If --use-more-webui is enabled use the bookmark
-  // manager to add or edit bookmarks. The bookmark editor allows editing an
-  // existing node or creating a new bookmark node (as determined by
-  // |details.type|). If |configuration| is SHOW_TREE, a tree is shown allowing
-  // the user to choose the parent of the node.
-  // |parent| gives the initial parent to select in the tree for the node.
-  // |parent| is only used if |details.existing_node| is null.
-  static void Show(gfx::NativeWindow parent_window,
-                   Profile* profile,
-                   const EditDetails& details,
-                   Configuration configuration);
-};
-
-#endif  // CHROME_BROWSER_BOOKMARKS_BOOKMARK_EDITOR_H_
diff --git a/chrome/browser/bookmarks/bookmark_expanded_state_tracker_unittest.cc b/chrome/browser/bookmarks/bookmark_expanded_state_tracker_unittest.cc
index 17ac4a1..4957290 100644
--- a/chrome/browser/bookmarks/bookmark_expanded_state_tracker_unittest.cc
+++ b/chrome/browser/bookmarks/bookmark_expanded_state_tracker_unittest.cc
@@ -9,11 +9,9 @@
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/ui_test_utils.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-using content::BrowserThread;
-
 class BookmarkExpandedStateTrackerTest : public testing::Test {
  public:
   BookmarkExpandedStateTrackerTest();
@@ -26,17 +24,12 @@
 
  private:
   scoped_ptr<TestingProfile> profile_;
-  base::MessageLoopForUI message_loop_;
-  content::TestBrowserThread ui_thread_;
-  content::TestBrowserThread file_thread_;
+  content::TestBrowserThreadBundle thread_bundle_;
 
   DISALLOW_COPY_AND_ASSIGN(BookmarkExpandedStateTrackerTest);
 };
 
-BookmarkExpandedStateTrackerTest::BookmarkExpandedStateTrackerTest()
-    : ui_thread_(BrowserThread::UI, &message_loop_),
-      file_thread_(BrowserThread::FILE, &message_loop_) {
-}
+BookmarkExpandedStateTrackerTest::BookmarkExpandedStateTrackerTest() {}
 
 void BookmarkExpandedStateTrackerTest::SetUp() {
   profile_.reset(new TestingProfile);
diff --git a/chrome/browser/bookmarks/bookmark_html_reader.cc b/chrome/browser/bookmarks/bookmark_html_reader.cc
deleted file mode 100644
index 8b2dcca..0000000
--- a/chrome/browser/bookmarks/bookmark_html_reader.cc
+++ /dev/null
@@ -1,432 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/bookmarks/bookmark_html_reader.h"
-
-#include "base/callback.h"
-#include "base/file_util.h"
-#include "base/i18n/icu_string_conversions.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/time.h"
-#include "chrome/browser/bookmarks/imported_bookmark_entry.h"
-#include "chrome/browser/favicon/favicon_util.h"
-#include "chrome/browser/favicon/imported_favicon_usage.h"
-#include "content/public/common/url_constants.h"
-#include "googleurl/src/gurl.h"
-#include "net/base/data_url.h"
-#include "net/base/escape.h"
-
-namespace {
-
-// Fetches the given |attribute| value from the |attribute_list|. Returns true
-// if successful, and |value| will contain the value.
-bool GetAttribute(const std::string& attribute_list,
-                  const std::string& attribute,
-                  std::string* value) {
-  const char kQuote[] = "\"";
-
-  size_t begin = attribute_list.find(attribute + "=" + kQuote);
-  if (begin == std::string::npos)
-    return false;  // Can't find the attribute.
-
-  begin += attribute.size() + 2;
-  size_t end = begin + 1;
-
-  while (end < attribute_list.size()) {
-    if (attribute_list[end] == '"' &&
-        attribute_list[end - 1] != '\\') {
-      break;
-    }
-    end++;
-  }
-
-  if (end == attribute_list.size())
-    return false;  // The value is not quoted.
-
-  *value = attribute_list.substr(begin, end - begin);
-  return true;
-}
-
-// Given the URL of a page and a favicon data URL, adds an appropriate record
-// to the given favicon usage vector.
-void DataURLToFaviconUsage(
-    const GURL& link_url,
-    const GURL& favicon_data,
-    std::vector<ImportedFaviconUsage>* favicons) {
-  if (!link_url.is_valid() || !favicon_data.is_valid() ||
-      !favicon_data.SchemeIs(chrome::kDataScheme))
-    return;
-
-  // Parse the data URL.
-  std::string mime_type, char_set, data;
-  if (!net::DataURL::Parse(favicon_data, &mime_type, &char_set, &data) ||
-      data.empty())
-    return;
-
-  ImportedFaviconUsage usage;
-  if (!FaviconUtil::ReencodeFavicon(
-          reinterpret_cast<const unsigned char*>(&data[0]),
-          data.size(), &usage.png_data))
-    return;  // Unable to decode.
-
-  // We need to make up a URL for the favicon. We use a version of the page's
-  // URL so that we can be sure it will not collide.
-  usage.favicon_url = GURL(std::string("made-up-favicon:") + link_url.spec());
-
-  // We only have one URL per favicon for Firefox 2 bookmarks.
-  usage.urls.insert(link_url);
-
-  favicons->push_back(usage);
-}
-
-}  // namespace
-
-namespace bookmark_html_reader {
-
-void ImportBookmarksFile(
-      const base::Callback<bool(void)>& cancellation_callback,
-      const base::Callback<bool(const GURL&)>& valid_url_callback,
-      const base::FilePath& file_path,
-      std::vector<ImportedBookmarkEntry>* bookmarks,
-      std::vector<ImportedFaviconUsage>* favicons) {
-  std::string content;
-  file_util::ReadFileToString(file_path, &content);
-  std::vector<std::string> lines;
-  base::SplitString(content, '\n', &lines);
-
-  base::string16 last_folder;
-  bool last_folder_on_toolbar = false;
-  bool last_folder_is_empty = true;
-  bool has_subfolder = false;
-  base::Time last_folder_add_date;
-  std::vector<base::string16> path;
-  size_t toolbar_folder_index = 0;
-  std::string charset;
-  for (size_t i = 0;
-       i < lines.size() &&
-           (cancellation_callback.is_null() || !cancellation_callback.Run());
-       ++i) {
-    std::string line;
-    TrimString(lines[i], " ", &line);
-
-    // Get the encoding of the bookmark file.
-    if (internal::ParseCharsetFromLine(line, &charset))
-      continue;
-
-    // Get the folder name.
-    if (internal::ParseFolderNameFromLine(line,
-                                          charset,
-                                          &last_folder,
-                                          &last_folder_on_toolbar,
-                                          &last_folder_add_date)) {
-      continue;
-    }
-
-    // Get the bookmark entry.
-    base::string16 title;
-    base::string16 shortcut;
-    GURL url, favicon;
-    base::Time add_date;
-    base::string16 post_data;
-    bool is_bookmark;
-    // TODO(jcampan): http://b/issue?id=1196285 we do not support POST based
-    //                keywords yet.
-    is_bookmark =
-        internal::ParseBookmarkFromLine(line, charset, &title,
-                                        &url, &favicon, &shortcut,
-                                        &add_date, &post_data) ||
-        internal::ParseMinimumBookmarkFromLine(line, charset, &title, &url);
-
-    if (is_bookmark)
-      last_folder_is_empty = false;
-
-    if (is_bookmark &&
-        post_data.empty() &&
-        (valid_url_callback.is_null() || valid_url_callback.Run(url))) {
-      if (toolbar_folder_index > path.size() && !path.empty()) {
-        NOTREACHED();  // error in parsing.
-        break;
-      }
-
-      ImportedBookmarkEntry entry;
-      entry.creation_time = add_date;
-      entry.url = url;
-      entry.title = title;
-
-      if (toolbar_folder_index) {
-        // The toolbar folder should be at the top level.
-        entry.in_toolbar = true;
-        entry.path.assign(path.begin() + toolbar_folder_index - 1, path.end());
-      } else {
-        // Add this bookmark to the list of |bookmarks|.
-        if (!has_subfolder && !last_folder.empty()) {
-          path.push_back(last_folder);
-          last_folder.clear();
-        }
-        entry.path.assign(path.begin(), path.end());
-      }
-      bookmarks->push_back(entry);
-
-      // Save the favicon. DataURLToFaviconUsage will handle the case where
-      // there is no favicon.
-      if (favicons)
-        DataURLToFaviconUsage(url, favicon, favicons);
-
-      continue;
-    }
-
-    // Bookmarks in sub-folder are encapsulated with <DL> tag.
-    if (StartsWithASCII(line, "<DL>", false)) {
-      has_subfolder = true;
-      if (!last_folder.empty()) {
-        path.push_back(last_folder);
-        last_folder.clear();
-      }
-      if (last_folder_on_toolbar && !toolbar_folder_index)
-        toolbar_folder_index = path.size();
-
-      // Mark next folder empty as initial state.
-      last_folder_is_empty = true;
-    } else if (StartsWithASCII(line, "</DL>", false)) {
-      if (path.empty())
-        break;  // Mismatch <DL>.
-
-      base::string16 folder_title = path.back();
-      path.pop_back();
-
-      if (last_folder_is_empty) {
-        // Empty folder should be added explicitly.
-        ImportedBookmarkEntry entry;
-        entry.is_folder = true;
-        entry.creation_time = last_folder_add_date;
-        entry.title = folder_title;
-        if (toolbar_folder_index) {
-          // The toolbar folder should be at the top level.
-          // Make sure we don't add the toolbar folder itself if it is empty.
-          if (toolbar_folder_index <= path.size()) {
-            entry.in_toolbar = true;
-            entry.path.assign(path.begin() + toolbar_folder_index - 1,
-                              path.end());
-            bookmarks->push_back(entry);
-          }
-        } else {
-          // Add this folder to the list of |bookmarks|.
-          entry.path.assign(path.begin(), path.end());
-          bookmarks->push_back(entry);
-        }
-
-        // Parent folder include current one, so it's not empty.
-        last_folder_is_empty = false;
-      }
-
-      if (toolbar_folder_index > path.size())
-        toolbar_folder_index = 0;
-    }
-  }
-}
-
-namespace internal {
-
-bool ParseCharsetFromLine(const std::string& line, std::string* charset) {
-  const char kCharset[] = "charset=";
-  if (StartsWithASCII(line, "<META", false) &&
-      (line.find("CONTENT=\"") != std::string::npos ||
-          line.find("content=\"") != std::string::npos)) {
-    size_t begin = line.find(kCharset);
-    if (begin == std::string::npos)
-      return false;
-    begin += std::string(kCharset).size();
-    size_t end = line.find_first_of('\"', begin);
-    *charset = line.substr(begin, end - begin);
-    return true;
-  }
-  return false;
-}
-
-bool ParseFolderNameFromLine(const std::string& line,
-                             const std::string& charset,
-                             base::string16* folder_name,
-                             bool* is_toolbar_folder,
-                             base::Time* add_date) {
-  const char kFolderOpen[] = "<DT><H3";
-  const char kFolderClose[] = "</H3>";
-  const char kToolbarFolderAttribute[] = "PERSONAL_TOOLBAR_FOLDER";
-  const char kAddDateAttribute[] = "ADD_DATE";
-
-  if (!StartsWithASCII(line, kFolderOpen, true))
-    return false;
-
-  size_t end = line.find(kFolderClose);
-  size_t tag_end = line.rfind('>', end) + 1;
-  // If no end tag or start tag is broken, we skip to find the folder name.
-  if (end == std::string::npos || tag_end < arraysize(kFolderOpen))
-    return false;
-
-  base::CodepageToUTF16(line.substr(tag_end, end - tag_end), charset.c_str(),
-                        base::OnStringConversionError::SKIP, folder_name);
-  *folder_name = net::UnescapeForHTML(*folder_name);
-
-  std::string attribute_list = line.substr(arraysize(kFolderOpen),
-      tag_end - arraysize(kFolderOpen) - 1);
-  std::string value;
-
-  // Add date
-  if (GetAttribute(attribute_list, kAddDateAttribute, &value)) {
-    int64 time;
-    base::StringToInt64(value, &time);
-    // Upper bound it at 32 bits.
-    if (0 < time && time < (1LL << 32))
-      *add_date = base::Time::FromTimeT(time);
-  }
-
-  if (GetAttribute(attribute_list, kToolbarFolderAttribute, &value) &&
-      LowerCaseEqualsASCII(value, "true"))
-    *is_toolbar_folder = true;
-  else
-    *is_toolbar_folder = false;
-
-  return true;
-}
-
-bool ParseBookmarkFromLine(const std::string& line,
-                           const std::string& charset,
-                           base::string16* title,
-                           GURL* url,
-                           GURL* favicon,
-                           base::string16* shortcut,
-                           base::Time* add_date,
-                           base::string16* post_data) {
-  const char kItemOpen[] = "<DT><A";
-  const char kItemClose[] = "</A>";
-  const char kFeedURLAttribute[] = "FEEDURL";
-  const char kHrefAttribute[] = "HREF";
-  const char kIconAttribute[] = "ICON";
-  const char kShortcutURLAttribute[] = "SHORTCUTURL";
-  const char kAddDateAttribute[] = "ADD_DATE";
-  const char kPostDataAttribute[] = "POST_DATA";
-
-  title->clear();
-  *url = GURL();
-  *favicon = GURL();
-  shortcut->clear();
-  post_data->clear();
-  *add_date = base::Time();
-
-  if (!StartsWithASCII(line, kItemOpen, true))
-    return false;
-
-  size_t end = line.find(kItemClose);
-  size_t tag_end = line.rfind('>', end) + 1;
-  if (end == std::string::npos || tag_end < arraysize(kItemOpen))
-    return false;  // No end tag or start tag is broken.
-
-  std::string attribute_list = line.substr(arraysize(kItemOpen),
-      tag_end - arraysize(kItemOpen) - 1);
-
-  // We don't import Live Bookmark folders, which is Firefox's RSS reading
-  // feature, since the user never necessarily bookmarked them and we don't
-  // have this feature to update their contents.
-  std::string value;
-  if (GetAttribute(attribute_list, kFeedURLAttribute, &value))
-    return false;
-
-  // Title
-  base::CodepageToUTF16(line.substr(tag_end, end - tag_end), charset.c_str(),
-                        base::OnStringConversionError::SKIP, title);
-  *title = net::UnescapeForHTML(*title);
-
-  // URL
-  if (GetAttribute(attribute_list, kHrefAttribute, &value)) {
-    base::string16 url16;
-    base::CodepageToUTF16(value, charset.c_str(),
-                          base::OnStringConversionError::SKIP, &url16);
-    url16 = net::UnescapeForHTML(url16);
-
-    *url = GURL(url16);
-  }
-
-  // Favicon
-  if (GetAttribute(attribute_list, kIconAttribute, &value))
-    *favicon = GURL(value);
-
-  // Keyword
-  if (GetAttribute(attribute_list, kShortcutURLAttribute, &value)) {
-    base::CodepageToUTF16(value, charset.c_str(),
-                          base::OnStringConversionError::SKIP, shortcut);
-    *shortcut = net::UnescapeForHTML(*shortcut);
-  }
-
-  // Add date
-  if (GetAttribute(attribute_list, kAddDateAttribute, &value)) {
-    int64 time;
-    base::StringToInt64(value, &time);
-    // Upper bound it at 32 bits.
-    if (0 < time && time < (1LL << 32))
-      *add_date = base::Time::FromTimeT(time);
-  }
-
-  // Post data.
-  if (GetAttribute(attribute_list, kPostDataAttribute, &value)) {
-    base::CodepageToUTF16(value, charset.c_str(),
-                          base::OnStringConversionError::SKIP, post_data);
-    *post_data = net::UnescapeForHTML(*post_data);
-  }
-
-  return true;
-}
-
-bool ParseMinimumBookmarkFromLine(const std::string& line,
-                                  const std::string& charset,
-                                  base::string16* title,
-                                  GURL* url) {
-  const char kItemOpen[] = "<DT><A";
-  const char kItemClose[] = "</";
-  const char kHrefAttributeUpper[] = "HREF";
-  const char kHrefAttributeLower[] = "href";
-
-  title->clear();
-  *url = GURL();
-
-  // Case-insensitive check of open tag.
-  if (!StartsWithASCII(line, kItemOpen, false))
-    return false;
-
-  // Find any close tag.
-  size_t end = line.find(kItemClose);
-  size_t tag_end = line.rfind('>', end) + 1;
-  if (end == std::string::npos || tag_end < arraysize(kItemOpen))
-    return false;  // No end tag or start tag is broken.
-
-  std::string attribute_list = line.substr(arraysize(kItemOpen),
-      tag_end - arraysize(kItemOpen) - 1);
-
-  // Title
-  base::CodepageToUTF16(line.substr(tag_end, end - tag_end), charset.c_str(),
-                        base::OnStringConversionError::SKIP, title);
-  *title = net::UnescapeForHTML(*title);
-
-  // URL
-  std::string value;
-  if (GetAttribute(attribute_list, kHrefAttributeUpper, &value) ||
-      GetAttribute(attribute_list, kHrefAttributeLower, &value)) {
-    if (charset.length() != 0) {
-      base::string16 url16;
-      base::CodepageToUTF16(value, charset.c_str(),
-                            base::OnStringConversionError::SKIP, &url16);
-      url16 = net::UnescapeForHTML(url16);
-
-      *url = GURL(url16);
-    } else {
-      *url = GURL(value);
-    }
-  }
-
-  return true;
-}
-
-}  // namespace internal
-
-}  // namespace bookmark_html_reader
diff --git a/chrome/browser/bookmarks/bookmark_html_reader.h b/chrome/browser/bookmarks/bookmark_html_reader.h
deleted file mode 100644
index 3fec412..0000000
--- a/chrome/browser/bookmarks/bookmark_html_reader.h
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_BOOKMARKS_BOOKMARK_HTML_READER_H_
-#define CHROME_BROWSER_BOOKMARKS_BOOKMARK_HTML_READER_H_
-
-#include <string>
-#include <vector>
-
-#include "base/callback_forward.h"
-#include "base/strings/string16.h"
-
-class GURL;
-struct ImportedBookmarkEntry;
-struct ImportedFaviconUsage;
-
-namespace base {
-class FilePath;
-class Time;
-}
-
-namespace bookmark_html_reader {
-
-// Imports the bookmarks from the specified file.
-//
-// |cancellation_callback| is polled to query if the import should be cancelled;
-// if it returns |true| at any time the import will be cancelled. If
-// |cancellation_callback| is a null callback the import will run to completion.
-//
-// |valid_url_callback| is called to determine if a specified URL is valid for
-// import; it returns |true| if it is. If |valid_url_callback| is a null
-// callback, all URLs are considered to be valid.
-//
-// |file_path| is the path of the file on disk to import.
-//
-// |bookmarks| is a pointer to a vector, which is filled with the imported
-// bookmarks. It may not be NULL.
-//
-// |favicons| is a pointer to a vector, which is filled with the favicons of
-// imported bookmarks. It may be NULL, in which case favicons are not imported.
-void ImportBookmarksFile(
-    const base::Callback<bool(void)>& cancellation_callback,
-    const base::Callback<bool(const GURL&)>& valid_url_callback,
-    const base::FilePath& file_path,
-    std::vector<ImportedBookmarkEntry>* bookmarks,
-    std::vector<ImportedFaviconUsage>* favicons);
-
-namespace internal {
-
-// The file format that BookmarkHTMLReader parses starts with a heading
-// tag, which contains its title. All bookmarks and sub-folders follow,
-// bracketed by a <DL> tag:
-//   <DT><H3 PERSONAL_TOOLBAR_FOLDER="true" ...>title</H3>
-//   <DL><p>
-//      ... container ...
-//   </DL><p>
-// And a bookmark is presented by a <A> tag:
-//   <DT><A HREF="url" SHORTCUTURL="shortcut" ADD_DATE="11213014"...>name</A>
-// Reference: http://kb.mozillazine.org/Bookmarks.html
-
-bool ParseCharsetFromLine(const std::string& line,
-                          std::string* charset);
-bool ParseFolderNameFromLine(const std::string& line,
-                             const std::string& charset,
-                             base::string16* folder_name,
-                             bool* is_toolbar_folder,
-                             base::Time* add_date);
-// See above, this will also put the data: URL of the favicon into |*favicon|
-// if there is a favicon given. |post_data| is set for POST base keywords to
-// the contents of the actual POST (with %s for the search term).
-bool ParseBookmarkFromLine(const std::string& line,
-                           const std::string& charset,
-                           base::string16* title,
-                           GURL* url,
-                           GURL* favicon,
-                           base::string16* shortcut,
-                           base::Time* add_date,
-                           base::string16* post_data);
-// Save bookmarks imported from browsers with Firefox 2 compatible bookmark
-// systems such as Epiphany. This bookmark format is the same as that of the
-// basic Firefox 2 bookmark, but it misses additional properties and uses
-// lower-case tag:
-//   ...<h1>Bookmarks</h1><dl>
-//   <dt><a href="url">name</a></dt>
-//   <dt><a href="url">name</a></dt>
-//   </dl>
-bool ParseMinimumBookmarkFromLine(const std::string& line,
-                                  const std::string& charset,
-                                  base::string16* title,
-                                  GURL* url);
-
-}  // namespace internal
-
-}  // namespace bookmark_html_reader
-
-#endif  // CHROME_BROWSER_BOOKMARKS_BOOKMARK_HTML_READER_H_
diff --git a/chrome/browser/bookmarks/bookmark_html_reader_unittest.cc b/chrome/browser/bookmarks/bookmark_html_reader_unittest.cc
deleted file mode 100644
index 5d5462a..0000000
--- a/chrome/browser/bookmarks/bookmark_html_reader_unittest.cc
+++ /dev/null
@@ -1,275 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/bookmarks/bookmark_html_reader.h"
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/callback.h"
-#include "base/files/file_path.h"
-#include "base/path_service.h"
-#include "base/strings/string16.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/bookmarks/imported_bookmark_entry.h"
-#include "chrome/common/chrome_paths.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace bookmark_html_reader {
-
-TEST(BookmarkHTMLReaderTest, ParseTests) {
-  bool result;
-
-  // Tests charset.
-  std::string charset;
-  result = internal::ParseCharsetFromLine(
-      "<META HTTP-EQUIV=\"Content-Type\" "
-      "CONTENT=\"text/html; charset=UTF-8\">",
-      &charset);
-  EXPECT_TRUE(result);
-  EXPECT_EQ("UTF-8", charset);
-
-  // Escaped characters in name.
-  base::string16 folder_name;
-  bool is_toolbar_folder;
-  base::Time folder_add_date;
-  result = internal::ParseFolderNameFromLine(
-      "<DT><H3 ADD_DATE=\"1207558707\" >&lt; &gt;"
-      " &amp; &quot; &#39; \\ /</H3>",
-      charset, &folder_name, &is_toolbar_folder, &folder_add_date);
-  EXPECT_TRUE(result);
-  EXPECT_EQ(ASCIIToUTF16("< > & \" ' \\ /"), folder_name);
-  EXPECT_FALSE(is_toolbar_folder);
-  EXPECT_TRUE(base::Time::FromTimeT(1207558707) == folder_add_date);
-
-  // Empty name and toolbar folder attribute.
-  result = internal::ParseFolderNameFromLine(
-      "<DT><H3 PERSONAL_TOOLBAR_FOLDER=\"true\"></H3>",
-      charset, &folder_name, &is_toolbar_folder, &folder_add_date);
-  EXPECT_TRUE(result);
-  EXPECT_EQ(base::string16(), folder_name);
-  EXPECT_TRUE(is_toolbar_folder);
-
-  // Unicode characters in title and shortcut.
-  base::string16 title;
-  GURL url, favicon;
-  base::string16 shortcut;
-  base::string16 post_data;
-  base::Time add_date;
-  result = internal::ParseBookmarkFromLine(
-      "<DT><A HREF=\"http://chinese.site.cn/path?query=1#ref\" "
-      "SHORTCUTURL=\"\xE4\xB8\xAD\">\xE4\xB8\xAD\xE6\x96\x87</A>",
-      charset, &title, &url, &favicon, &shortcut, &add_date, &post_data);
-  EXPECT_TRUE(result);
-  EXPECT_EQ(L"\x4E2D\x6587", UTF16ToWide(title));
-  EXPECT_EQ("http://chinese.site.cn/path?query=1#ref", url.spec());
-  EXPECT_EQ(L"\x4E2D", UTF16ToWide(shortcut));
-  EXPECT_EQ(base::string16(), post_data);
-  EXPECT_TRUE(base::Time() == add_date);
-
-  // No shortcut, and url contains %22 ('"' character).
-  result = internal::ParseBookmarkFromLine(
-      "<DT><A HREF=\"http://domain.com/?q=%22<>%22\">name</A>",
-      charset, &title, &url, &favicon, &shortcut, &add_date, &post_data);
-  EXPECT_TRUE(result);
-  EXPECT_EQ(ASCIIToUTF16("name"), title);
-  EXPECT_EQ("http://domain.com/?q=%22%3C%3E%22", url.spec());
-  EXPECT_EQ(base::string16(), shortcut);
-  EXPECT_EQ(base::string16(), post_data);
-  EXPECT_TRUE(base::Time() == add_date);
-
-  result = internal::ParseBookmarkFromLine(
-      "<DT><A HREF=\"http://domain.com/?g=&quot;\"\">name</A>",
-      charset, &title, &url, &favicon, &shortcut, &add_date, &post_data);
-  EXPECT_TRUE(result);
-  EXPECT_EQ(ASCIIToUTF16("name"), title);
-  EXPECT_EQ("http://domain.com/?g=%22", url.spec());
-  EXPECT_EQ(base::string16(), shortcut);
-  EXPECT_EQ(base::string16(), post_data);
-  EXPECT_TRUE(base::Time() == add_date);
-
-  // Creation date.
-  result = internal::ParseBookmarkFromLine(
-      "<DT><A HREF=\"http://site/\" ADD_DATE=\"1121301154\">name</A>",
-      charset, &title, &url, &favicon, &shortcut, &add_date, &post_data);
-  EXPECT_TRUE(result);
-  EXPECT_EQ(ASCIIToUTF16("name"), title);
-  EXPECT_EQ(GURL("http://site/"), url);
-  EXPECT_EQ(base::string16(), shortcut);
-  EXPECT_EQ(base::string16(), post_data);
-  EXPECT_TRUE(base::Time::FromTimeT(1121301154) == add_date);
-
-  // Post-data
-  result = internal::ParseBookmarkFromLine(
-      "<DT><A HREF=\"http://localhost:8080/test/hello.html\" ADD_DATE=\""
-      "1212447159\" LAST_VISIT=\"1212447251\" LAST_MODIFIED=\"1212447248\""
-      "SHORTCUTURL=\"post\" ICON=\"data:\" POST_DATA=\"lname%3D%25s\""
-      "LAST_CHARSET=\"UTF-8\" ID=\"rdf:#$weKaR3\">Test Post keyword</A>",
-      charset, &title, &url, &favicon, &shortcut, &add_date, &post_data);
-  EXPECT_TRUE(result);
-  EXPECT_EQ(ASCIIToUTF16("Test Post keyword"), title);
-  EXPECT_EQ("http://localhost:8080/test/hello.html", url.spec());
-  EXPECT_EQ(ASCIIToUTF16("post"), shortcut);
-  EXPECT_EQ(ASCIIToUTF16("lname%3D%25s"), post_data);
-  EXPECT_TRUE(base::Time::FromTimeT(1212447159) == add_date);
-
-  // Invalid case.
-  result = internal::ParseBookmarkFromLine(
-      "<DT><A HREF=\"http://domain.com/?q=%22",
-      charset, &title, &url, &favicon, &shortcut, &add_date, &post_data);
-  EXPECT_FALSE(result);
-  EXPECT_EQ(base::string16(), title);
-  EXPECT_EQ("", url.spec());
-  EXPECT_EQ(base::string16(), shortcut);
-  EXPECT_EQ(base::string16(), post_data);
-  EXPECT_TRUE(base::Time() == add_date);
-
-  // Epiphany format.
-  result = internal::ParseMinimumBookmarkFromLine(
-      "<dt><a href=\"http://www.google.com/\">Google</a></dt>",
-      charset, &title, &url);
-  EXPECT_TRUE(result);
-  EXPECT_EQ(ASCIIToUTF16("Google"), title);
-  EXPECT_EQ("http://www.google.com/", url.spec());
-}
-
-namespace {
-
-void ExpectFirstFirefox2Bookmark(const ImportedBookmarkEntry& entry) {
-  EXPECT_EQ(ASCIIToUTF16("Empty"), entry.title);
-  EXPECT_TRUE(entry.is_folder);
-  EXPECT_EQ(base::Time::FromTimeT(1295938143), entry.creation_time);
-  EXPECT_EQ(1U, entry.path.size());
-  if (entry.path.size() == 1)
-    EXPECT_EQ(ASCIIToUTF16("Empty's Parent"), entry.path.front());
-}
-
-void ExpectSecondFirefox2Bookmark(const ImportedBookmarkEntry& entry) {
-  EXPECT_EQ(ASCIIToUTF16("[Tamura Yukari.com]"), entry.title);
-  EXPECT_FALSE(entry.is_folder);
-  EXPECT_EQ(base::Time::FromTimeT(1234567890), entry.creation_time);
-  EXPECT_EQ(1U, entry.path.size());
-  if (entry.path.size() == 1)
-    EXPECT_EQ(ASCIIToUTF16("Not Empty"), entry.path.front());
-  EXPECT_EQ("http://www.tamurayukari.com/", entry.url.spec());
-}
-
-void ExpectThirdFirefox2Bookmark(const ImportedBookmarkEntry& entry) {
-  EXPECT_EQ(ASCIIToUTF16("Google"), entry.title);
-  EXPECT_FALSE(entry.is_folder);
-  EXPECT_EQ(base::Time::FromTimeT(0000000000), entry.creation_time);
-  EXPECT_EQ(1U, entry.path.size());
-  if (entry.path.size() == 1)
-    EXPECT_EQ(ASCIIToUTF16("Not Empty But Default"), entry.path.front());
-  EXPECT_EQ("http://www.google.com/", entry.url.spec());
-}
-
-void ExpectFirstEpiphanyBookmark(const ImportedBookmarkEntry& entry) {
-  EXPECT_EQ(ASCIIToUTF16("[Tamura Yukari.com]"), entry.title);
-  EXPECT_EQ("http://www.tamurayukari.com/", entry.url.spec());
-  EXPECT_EQ(0U, entry.path.size());
-}
-
-void ExpectSecondEpiphanyBookmark(const ImportedBookmarkEntry& entry) {
-  EXPECT_EQ(ASCIIToUTF16("Google"), entry.title);
-  EXPECT_EQ("http://www.google.com/", entry.url.spec());
-  EXPECT_EQ(0U, entry.path.size());
-}
-
-}  // namespace
-
-TEST(BookmarkHTMLReaderTest, Firefox2BookmarkFileImport) {
-  base::FilePath path;
-  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &path));
-  path = path.AppendASCII("bookmark_html_reader");
-  path = path.AppendASCII("firefox2.html");
-
-  std::vector<ImportedBookmarkEntry> bookmarks;
-  ImportBookmarksFile(base::Callback<bool(void)>(),
-                      base::Callback<bool(const GURL&)>(),
-                      path, &bookmarks, NULL);
-
-  ASSERT_EQ(3U, bookmarks.size());
-  ExpectFirstFirefox2Bookmark(bookmarks[0]);
-  ExpectSecondFirefox2Bookmark(bookmarks[1]);
-  ExpectThirdFirefox2Bookmark(bookmarks[2]);
-}
-
-TEST(BookmarkHTMLReaderTest, EpiphanyBookmarkFileImport) {
-  base::FilePath path;
-  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &path));
-  path = path.AppendASCII("bookmark_html_reader");
-  path = path.AppendASCII("epiphany.html");
-
-  std::vector<ImportedBookmarkEntry> bookmarks;
-  ImportBookmarksFile(base::Callback<bool(void)>(),
-                      base::Callback<bool(const GURL&)>(),
-                      path, &bookmarks, NULL);
-
-  ASSERT_EQ(2U, bookmarks.size());
-  ExpectFirstEpiphanyBookmark(bookmarks[0]);
-  ExpectSecondEpiphanyBookmark(bookmarks[1]);
-}
-
-namespace {
-
-class CancelAfterFifteenCalls {
-  int count;
- public:
-  CancelAfterFifteenCalls() : count(0) { }
-  bool ShouldCancel() {
-    return ++count > 16;
-  }
-};
-
-}  // namespace
-
-TEST(BookmarkHTMLReaderTest, CancellationCallback) {
-  base::FilePath path;
-  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &path));
-  path = path.AppendASCII("bookmark_html_reader");
-  // Use a file for testing that has multiple bookmarks.
-  path = path.AppendASCII("firefox2.html");
-
-  std::vector<ImportedBookmarkEntry> bookmarks;
-  CancelAfterFifteenCalls cancel_fifteen;
-  ImportBookmarksFile(base::Bind(&CancelAfterFifteenCalls::ShouldCancel,
-                                 base::Unretained(&cancel_fifteen)),
-                      base::Callback<bool(const GURL&)>(),
-                      path, &bookmarks, NULL);
-
-  // The cancellation callback is checked before each line is read, so fifteen
-  // lines are imported. The first fifteen lines of firefox2.html include only
-  // one bookmark.
-  ASSERT_EQ(1U, bookmarks.size());
-  ExpectFirstFirefox2Bookmark(bookmarks[0]);
-}
-
-namespace {
-
-bool IsURLValid(const GURL& url) {
-  // No offense to whomever owns this domain...
-  return !url.DomainIs("tamurayukari.com");
-}
-
-}  // namespace
-
-TEST(BookmarkHTMLReaderTest, ValidURLCallback) {
-  base::FilePath path;
-  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &path));
-  path = path.AppendASCII("bookmark_html_reader");
-  // Use a file for testing that has multiple bookmarks.
-  path = path.AppendASCII("firefox2.html");
-
-  std::vector<ImportedBookmarkEntry> bookmarks;
-  ImportBookmarksFile(base::Callback<bool(void)>(),
-                      base::Bind(&IsURLValid),
-                      path, &bookmarks, NULL);
-
-  ASSERT_EQ(2U, bookmarks.size());
-  ExpectFirstFirefox2Bookmark(bookmarks[0]);
-  ExpectThirdFirefox2Bookmark(bookmarks[1]);
-}
-
-}  // namespace bookmark_html_reader
diff --git a/chrome/browser/bookmarks/bookmark_html_writer.cc b/chrome/browser/bookmarks/bookmark_html_writer.cc
index 620628a..47eee0a 100644
--- a/chrome/browser/bookmarks/bookmark_html_writer.cc
+++ b/chrome/browser/bookmarks/bookmark_html_writer.cc
@@ -12,7 +12,7 @@
 #include "base/message_loop.h"
 #include "base/platform_file.h"
 #include "base/strings/string_number_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/bookmarks/bookmark_codec.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
diff --git a/chrome/browser/bookmarks/bookmark_html_writer_unittest.cc b/chrome/browser/bookmarks/bookmark_html_writer_unittest.cc
deleted file mode 100644
index e735369..0000000
--- a/chrome/browser/bookmarks/bookmark_html_writer_unittest.cc
+++ /dev/null
@@ -1,285 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/bookmarks/bookmark_html_writer.h"
-
-#include "base/files/scoped_temp_dir.h"
-#include "base/i18n/time_formatting.h"
-#include "base/message_loop.h"
-#include "base/path_service.h"
-#include "base/strings/string16.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
-#include "chrome/browser/bookmarks/bookmark_html_reader.h"
-#include "chrome/browser/bookmarks/bookmark_model.h"
-#include "chrome/browser/bookmarks/bookmark_model_factory.h"
-#include "chrome/browser/bookmarks/imported_bookmark_entry.h"
-#include "chrome/browser/favicon/favicon_service.h"
-#include "chrome/browser/favicon/favicon_service_factory.h"
-#include "chrome/browser/favicon/imported_favicon_usage.h"
-#include "chrome/browser/history/history_service.h"
-#include "chrome/browser/history/history_service_factory.h"
-#include "chrome/test/base/testing_profile.h"
-#include "chrome/test/base/ui_test_utils.h"
-#include "content/public/test/test_browser_thread.h"
-#include "grit/generated_resources.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/gfx/codec/png_codec.h"
-
-using content::BrowserThread;
-
-namespace {
-
-const int kIconWidth = 16;
-const int kIconHeight = 16;
-
-void MakeTestSkBitmap(int w, int h, SkBitmap* bmp) {
-  bmp->setConfig(SkBitmap::kARGB_8888_Config, w, h);
-  bmp->allocPixels();
-
-  uint32_t* src_data = bmp->getAddr32(0, 0);
-  for (int i = 0; i < w * h; i++) {
-    src_data[i] = SkPreMultiplyARGB(i % 255, i % 250, i % 245, i % 240);
-  }
-}
-
-}  // namespace
-
-class BookmarkHTMLWriterTest : public testing::Test {
- protected:
-  virtual void SetUp() {
-    testing::Test::SetUp();
-    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
-    path_ = temp_dir_.path().AppendASCII("bookmarks.html");
-  }
-
-  // Converts an ImportedBookmarkEntry to a string suitable for assertion
-  // testing.
-  string16 BookmarkEntryToString(const ImportedBookmarkEntry& entry) {
-    string16 result;
-    result.append(ASCIIToUTF16("on_toolbar="));
-    if (entry.in_toolbar)
-      result.append(ASCIIToUTF16("true"));
-    else
-      result.append(ASCIIToUTF16("false"));
-
-    result.append(ASCIIToUTF16(" url=") + UTF8ToUTF16(entry.url.spec()));
-
-    result.append(ASCIIToUTF16(" path="));
-    for (size_t i = 0; i < entry.path.size(); ++i) {
-      if (i != 0)
-        result.append(ASCIIToUTF16("/"));
-      result.append(entry.path[i]);
-    }
-
-    result.append(ASCIIToUTF16(" title="));
-    result.append(entry.title);
-
-    result.append(ASCIIToUTF16(" time="));
-    result.append(base::TimeFormatFriendlyDateAndTime(entry.creation_time));
-    return result;
-  }
-
-  // Creates a set of bookmark values to a string for assertion testing.
-  string16 BookmarkValuesToString(bool on_toolbar,
-                                  const GURL& url,
-                                  const string16& title,
-                                  base::Time creation_time,
-                                  const string16& f1,
-                                  const string16& f2,
-                                  const string16& f3) {
-    ImportedBookmarkEntry entry;
-    entry.in_toolbar = on_toolbar;
-    entry.url = url;
-    if (!f1.empty()) {
-      entry.path.push_back(f1);
-      if (!f2.empty()) {
-        entry.path.push_back(f2);
-        if (!f3.empty())
-          entry.path.push_back(f3);
-      }
-    }
-    entry.title = title;
-    entry.creation_time = creation_time;
-    return BookmarkEntryToString(entry);
-  }
-
-  void AssertBookmarkEntryEquals(const ImportedBookmarkEntry& entry,
-                                 bool on_toolbar,
-                                 const GURL& url,
-                                 const string16& title,
-                                 base::Time creation_time,
-                                 const string16& f1,
-                                 const string16& f2,
-                                 const string16& f3) {
-    EXPECT_EQ(BookmarkValuesToString(on_toolbar, url, title, creation_time,
-                                     f1, f2, f3),
-              BookmarkEntryToString(entry));
-  }
-
-  base::ScopedTempDir temp_dir_;
-  base::FilePath path_;
-};
-
-// Class that will notify message loop when file is written.
-class BookmarksObserver : public BookmarksExportObserver {
- public:
-  explicit BookmarksObserver(base::MessageLoop* loop) : loop_(loop) {
-    DCHECK(loop);
-  }
-
-  virtual void OnExportFinished() OVERRIDE {
-    loop_->Quit();
-  }
-
- private:
-  base::MessageLoop* loop_;
-  DISALLOW_COPY_AND_ASSIGN(BookmarksObserver);
-};
-
-// Tests bookmark_html_writer by populating a BookmarkModel, writing it out by
-// way of bookmark_html_writer, then using the importer to read it back in.
-TEST_F(BookmarkHTMLWriterTest, Test) {
-  base::MessageLoop message_loop;
-  content::TestBrowserThread fake_ui_thread(BrowserThread::UI, &message_loop);
-  content::TestBrowserThread fake_file_thread(BrowserThread::FILE,
-                                              &message_loop);
-
-  TestingProfile profile;
-  profile.CreateHistoryService(true, false);
-  profile.BlockUntilHistoryProcessesPendingRequests();
-  profile.CreateFaviconService();
-  profile.CreateBookmarkModel(true);
-
-  BookmarkModel* model = BookmarkModelFactory::GetForProfile(&profile);
-  ui_test_utils::WaitForBookmarkModelToLoad(model);
-
-  // Create test PNG representing favicon for url1.
-  SkBitmap bitmap;
-  MakeTestSkBitmap(kIconWidth, kIconHeight, &bitmap);
-  std::vector<unsigned char> icon_data;
-  gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &icon_data);
-
-  // Populate the BookmarkModel. This creates the following bookmark structure:
-  // Bookmarks bar
-  //   F1
-  //     url1
-  //     F2
-  //       url2
-  //   url3
-  //   url4
-  // Other
-  //   url1
-  //   url2
-  //   F3
-  //     F4
-  //       url1
-  // Mobile
-  //   url1
-  //   <bookmark without a title.>
-  string16 f1_title = ASCIIToUTF16("F\"&;<1\"");
-  string16 f2_title = ASCIIToUTF16("F2");
-  string16 f3_title = ASCIIToUTF16("F 3");
-  string16 f4_title = ASCIIToUTF16("F4");
-  string16 url1_title = ASCIIToUTF16("url 1");
-  string16 url2_title = ASCIIToUTF16("url&2");
-  string16 url3_title = ASCIIToUTF16("url\"3");
-  string16 url4_title = ASCIIToUTF16("url\"&;");
-  string16 unnamed_bookmark_title = ASCIIToUTF16("");
-  GURL url1("http://url1");
-  GURL url1_favicon("http://url1/icon.ico");
-  GURL url2("http://url2");
-  GURL url3("http://url3");
-  GURL url4("javascript:alert(\"Hello!\");");
-  GURL unnamed_bookmark_url("about:blank");
-  base::Time t1(base::Time::Now());
-  base::Time t2(t1 + base::TimeDelta::FromHours(1));
-  base::Time t3(t1 + base::TimeDelta::FromHours(1));
-  base::Time t4(t1 + base::TimeDelta::FromHours(1));
-  const BookmarkNode* f1 = model->AddFolder(
-      model->bookmark_bar_node(), 0, f1_title);
-  model->AddURLWithCreationTime(f1, 0, url1_title, url1, t1);
-  HistoryServiceFactory::GetForProfile(&profile, Profile::EXPLICIT_ACCESS)->
-      AddPage(url1, base::Time::Now(), history::SOURCE_BROWSED);
-  FaviconServiceFactory::GetForProfile(
-      &profile, Profile::EXPLICIT_ACCESS)->SetFavicons(
-          url1, url1_favicon, chrome::FAVICON,
-          gfx::Image::CreateFrom1xBitmap(bitmap));
-  message_loop.RunUntilIdle();
-  const BookmarkNode* f2 = model->AddFolder(f1, 1, f2_title);
-  model->AddURLWithCreationTime(f2, 0, url2_title, url2, t2);
-  model->AddURLWithCreationTime(model->bookmark_bar_node(),
-                                1, url3_title, url3, t3);
-
-  model->AddURLWithCreationTime(model->other_node(), 0, url1_title, url1, t1);
-  model->AddURLWithCreationTime(model->other_node(), 1, url2_title, url2, t2);
-  const BookmarkNode* f3 = model->AddFolder(model->other_node(), 2, f3_title);
-  const BookmarkNode* f4 = model->AddFolder(f3, 0, f4_title);
-  model->AddURLWithCreationTime(f4, 0, url1_title, url1, t1);
-  model->AddURLWithCreationTime(model->bookmark_bar_node(), 2, url4_title,
-                                url4, t4);
-  model->AddURLWithCreationTime(model->mobile_node(), 0, url1_title, url1, t1);
-  model->AddURLWithCreationTime(model->mobile_node(), 1, unnamed_bookmark_title,
-                                unnamed_bookmark_url, t2);
-
-  // Write to a temp file.
-  BookmarksObserver observer(&message_loop);
-  bookmark_html_writer::WriteBookmarks(&profile, path_, &observer);
-  message_loop.Run();
-
-  // Clear favicon so that it would be read from file.
-  FaviconServiceFactory::GetForProfile(
-      &profile, Profile::EXPLICIT_ACCESS)->SetFavicons(
-          url1, url1_favicon, chrome::FAVICON, gfx::Image());
-  message_loop.RunUntilIdle();
-
-  // Read the bookmarks back in.
-  std::vector<ImportedBookmarkEntry> parsed_bookmarks;
-  std::vector<ImportedFaviconUsage> favicons;
-  bookmark_html_reader::ImportBookmarksFile(base::Callback<bool(void)>(),
-                                            base::Callback<bool(const GURL&)>(),
-                                            path_,
-                                            &parsed_bookmarks,
-                                            &favicons);
-
-  // Check loaded favicon (url1 is represented by 4 separate bookmarks).
-  EXPECT_EQ(4U, favicons.size());
-  for (size_t i = 0; i < favicons.size(); i++) {
-    if (url1_favicon == favicons[i].favicon_url) {
-      EXPECT_EQ(1U, favicons[i].urls.size());
-      std::set<GURL>::const_iterator iter = favicons[i].urls.find(url1);
-      ASSERT_TRUE(iter != favicons[i].urls.end());
-      ASSERT_TRUE(*iter == url1);
-      ASSERT_TRUE(favicons[i].png_data == icon_data);
-    }
-  }
-
-  // Verify we got back what we wrote.
-  ASSERT_EQ(9U, parsed_bookmarks.size());
-  // Windows and ChromeOS builds use Sentence case.
-  string16 bookmark_folder_name =
-      l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_FOLDER_NAME);
-  AssertBookmarkEntryEquals(parsed_bookmarks[0], true, url1, url1_title, t1,
-                            bookmark_folder_name, f1_title, string16());
-  AssertBookmarkEntryEquals(parsed_bookmarks[1], true, url2, url2_title, t2,
-                            bookmark_folder_name, f1_title, f2_title);
-  AssertBookmarkEntryEquals(parsed_bookmarks[2], true, url3, url3_title, t3,
-                            bookmark_folder_name, string16(), string16());
-  AssertBookmarkEntryEquals(parsed_bookmarks[3], true, url4, url4_title, t4,
-                            bookmark_folder_name, string16(), string16());
-  AssertBookmarkEntryEquals(parsed_bookmarks[4], false, url1, url1_title, t1,
-                            string16(), string16(), string16());
-  AssertBookmarkEntryEquals(parsed_bookmarks[5], false, url2, url2_title, t2,
-                            string16(), string16(), string16());
-  AssertBookmarkEntryEquals(parsed_bookmarks[6], false, url1, url1_title, t1,
-                            f3_title, f4_title, string16());
-  AssertBookmarkEntryEquals(parsed_bookmarks[7], false, url1, url1_title, t1,
-                            string16(), string16(), string16());
-  AssertBookmarkEntryEquals(parsed_bookmarks[8], false, unnamed_bookmark_url,
-                            unnamed_bookmark_title, t2,
-                            string16(), string16(), string16());
-}
diff --git a/chrome/browser/bookmarks/bookmark_index.cc b/chrome/browser/bookmarks/bookmark_index.cc
index bc5150b..3af121e 100644
--- a/chrome/browser/bookmarks/bookmark_index.cc
+++ b/chrome/browser/bookmarks/bookmark_index.cc
@@ -258,11 +258,6 @@
 
 void BookmarkIndex::RegisterNode(const string16& term,
                                  const BookmarkNode* node) {
-  if (std::find(index_[term].begin(), index_[term].end(), node) !=
-      index_[term].end()) {
-    // We've already added node for term.
-    return;
-  }
   index_[term].insert(node);
 }
 
diff --git a/chrome/browser/bookmarks/bookmark_index_unittest.cc b/chrome/browser/bookmarks/bookmark_index_unittest.cc
index 48d1fd2..f2e4469 100644
--- a/chrome/browser/bookmarks/bookmark_index_unittest.cc
+++ b/chrome/browser/bookmarks/bookmark_index_unittest.cc
@@ -20,11 +20,9 @@
 #include "chrome/browser/history/url_database.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/ui_test_utils.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-using content::BrowserThread;
-
 class BookmarkIndexTest : public testing::Test {
  public:
   BookmarkIndexTest() : model_(new BookmarkModel(NULL)) {}
@@ -235,9 +233,7 @@
 TEST_F(BookmarkIndexTest, GetResultsSortedByTypedCount) {
   // This ensures MessageLoop::current() will exist, which is needed by
   // TestingProfile::BlockUntilHistoryProcessesPendingRequests().
-  base::MessageLoop loop(base::MessageLoop::TYPE_DEFAULT);
-  content::TestBrowserThread ui_thread(BrowserThread::UI, &loop);
-  content::TestBrowserThread file_thread(BrowserThread::FILE, &loop);
+  content::TestBrowserThreadBundle thread_bundle;
 
   TestingProfile profile;
   profile.CreateHistoryService(true, false);
diff --git a/chrome/browser/bookmarks/bookmark_model.cc b/chrome/browser/bookmarks/bookmark_model.cc
index df4ce6b..eff176e 100644
--- a/chrome/browser/bookmarks/bookmark_model.cc
+++ b/chrome/browser/bookmarks/bookmark_model.cc
@@ -46,6 +46,25 @@
   return const_cast<BookmarkNode*>(node);
 }
 
+// Helper to recursively determine if a Dictionary has any valid values.
+bool HasValues(const base::DictionaryValue& root) {
+  if (root.empty())
+    return false;
+  for (base::DictionaryValue::Iterator iter(root); !iter.IsAtEnd();
+       iter.Advance()) {
+    const base::Value& value = iter.value();
+    if (value.IsType(base::Value::TYPE_DICTIONARY)) {
+      const base::DictionaryValue* dict_value = NULL;
+      if (value.GetAsDictionary(&dict_value) && HasValues(*dict_value))
+        return true;
+    } else {
+      // A non dictionary type was encountered, assume it's a valid value.
+      return true;
+    }
+  }
+  return false;
+}
+
 // Whitespace characters to strip from bookmark titles.
 const char16 kInvalidChars[] = {
   '\n', '\r', '\t',
@@ -123,9 +142,8 @@
   JSONStringValueSerializer serializer(&meta_info_str_);
   scoped_ptr<DictionaryValue> meta_dict(
       static_cast<DictionaryValue*>(serializer.Deserialize(NULL, NULL)));
-  if (meta_dict.get() && meta_dict->HasKey(key)) {
-    meta_dict->Remove(key, NULL);
-    if (meta_dict->empty()) {
+  if (meta_dict.get() && meta_dict->Remove(key, NULL)) {
+    if (!HasValues(*meta_dict)) {
       meta_info_str_.clear();
     } else {
       serializer.Serialize(*meta_dict);
diff --git a/chrome/browser/bookmarks/bookmark_model.h b/chrome/browser/bookmarks/bookmark_model.h
index cfa1475..cc90532 100644
--- a/chrome/browser/bookmarks/bookmark_model.h
+++ b/chrome/browser/bookmarks/bookmark_model.h
@@ -21,9 +21,9 @@
 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
-#include "googleurl/src/gurl.h"
 #include "ui/base/models/tree_node_model.h"
 #include "ui/gfx/image/image.h"
+#include "url/gurl.h"
 
 class BookmarkExpandedStateTracker;
 class BookmarkIndex;
diff --git a/chrome/browser/bookmarks/bookmark_model_test_utils.cc b/chrome/browser/bookmarks/bookmark_model_test_utils.cc
index 15370d4..f04a6b5 100644
--- a/chrome/browser/bookmarks/bookmark_model_test_utils.cc
+++ b/chrome/browser/bookmarks/bookmark_model_test_utils.cc
@@ -4,13 +4,18 @@
 
 #include "chrome/browser/bookmarks/bookmark_model_test_utils.h"
 
+#include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
-// static
-void BookmarkModelTestUtils::AssertNodesEqual(const BookmarkNode* expected,
-                                              const BookmarkNode* actual,
-                                              bool check_ids) {
+namespace {
+
+// Helper to verify the two given bookmark nodes.
+// The IDs of the bookmark nodes are compared only if check_ids is true.
+void AssertNodesEqual(const BookmarkNode* expected,
+                      const BookmarkNode* actual,
+                      bool check_ids) {
   ASSERT_TRUE(expected);
   ASSERT_TRUE(actual);
   if (check_ids)
@@ -29,6 +34,51 @@
   }
 }
 
+// Helper function which does the actual work of creating the nodes for
+// a particular level in the hierarchy.
+std::string::size_type AddNodesFromString(BookmarkModel* model,
+                                          const BookmarkNode* node,
+                                          const std::string& model_string,
+                                          std::string::size_type start_pos) {
+  DCHECK(node);
+  int index = node->child_count();
+  static const std::string folder_tell(":[");
+  std::string::size_type end_pos = model_string.find(' ', start_pos);
+  while (end_pos != std::string::npos) {
+    std::string::size_type part_length = end_pos - start_pos;
+    std::string node_name = model_string.substr(start_pos, part_length);
+    // Are we at the end of a folder group?
+    if (node_name != "]") {
+      // No, is it a folder?
+      std::string tell;
+      if (part_length > 2)
+        tell = node_name.substr(part_length - 2, 2);
+      if (tell == folder_tell) {
+        node_name = node_name.substr(0, part_length - 2);
+        const BookmarkNode* new_node =
+            model->AddFolder(node, index, UTF8ToUTF16(node_name));
+        end_pos = AddNodesFromString(model, new_node, model_string,
+                                     end_pos + 1);
+      } else {
+        std::string url_string("http://");
+        url_string += std::string(node_name.begin(), node_name.end());
+        url_string += ".com";
+        model->AddURL(node, index, UTF8ToUTF16(node_name), GURL(url_string));
+        ++end_pos;
+      }
+      ++index;
+      start_pos = end_pos;
+      end_pos = model_string.find(' ', start_pos);
+    } else {
+      ++end_pos;
+      break;
+    }
+  }
+  return end_pos;
+}
+
+}  // namespace
+
 // static
 void BookmarkModelTestUtils::AssertModelsEqual(BookmarkModel* expected,
                                                BookmarkModel* actual,
@@ -36,10 +86,38 @@
   AssertNodesEqual(expected->bookmark_bar_node(),
                    actual->bookmark_bar_node(),
                    check_ids);
-  AssertNodesEqual(expected->other_node(),
-                   actual->other_node(),
-                   check_ids);
-  AssertNodesEqual(expected->mobile_node(),
-                   actual->mobile_node(),
-                   check_ids);
+  AssertNodesEqual(expected->other_node(), actual->other_node(), check_ids);
+  AssertNodesEqual(expected->mobile_node(), actual->mobile_node(), check_ids);
+}
+
+// static
+std::string BookmarkModelTestUtils::ModelStringFromNode(
+    const BookmarkNode* node) {
+  // Since the children of the node are not available as a vector,
+  // we'll just have to do it the hard way.
+  int child_count = node->child_count();
+  std::string child_string;
+  for (int i = 0; i < child_count; ++i) {
+    const BookmarkNode* child = node->GetChild(i);
+    if (child->is_folder()) {
+      child_string += UTF16ToUTF8(child->GetTitle()) + ":[ " +
+          ModelStringFromNode(child) + "] ";
+    } else {
+      child_string += UTF16ToUTF8(child->GetTitle()) + " ";
+    }
+  }
+  return child_string;
+}
+
+// static
+void BookmarkModelTestUtils::AddNodesFromModelString(
+    BookmarkModel* model,
+    const BookmarkNode* node,
+    const std::string& model_string) {
+  DCHECK(node);
+  const std::string folder_tell(":[");
+  std::string::size_type start_pos = 0;
+  std::string::size_type end_pos =
+      AddNodesFromString(model, node, model_string, start_pos);
+  DCHECK(end_pos == std::string::npos);
 }
diff --git a/chrome/browser/bookmarks/bookmark_model_test_utils.h b/chrome/browser/bookmarks/bookmark_model_test_utils.h
index e942bd6..fab44dc 100644
--- a/chrome/browser/bookmarks/bookmark_model_test_utils.h
+++ b/chrome/browser/bookmarks/bookmark_model_test_utils.h
@@ -5,6 +5,10 @@
 #ifndef CHROME_BROWSER_BOOKMARKS_BOOKMARK_MODEL_TEST_UTILS_H_
 #define CHROME_BROWSER_BOOKMARKS_BOOKMARK_MODEL_TEST_UTILS_H_
 
+#include <string>
+
+#include "base/basictypes.h"
+
 class BookmarkModel;
 class BookmarkNode;
 
@@ -16,12 +20,35 @@
   static void AssertModelsEqual(BookmarkModel* expected,
                                 BookmarkModel* actual,
                                 bool check_ids);
+
+  // Return the descendants of |node| as a string useful for verifying node
+  // modifications. The format of the resulting string is:
+  //
+  //           result = node " " , { node " " }
+  //             node = bookmark title | folder
+  //           folder = folder title ":[ " { node " " } "]"
+  //   bookmark title = (* string with no spaces *)
+  //     folder title = (* string with no spaces *)
+  //
+  // Example: "a f1:[ b d c ] d f2:[ e f g ] h "
+  //
+  // (Logically, we should use |string16|s, but it's more convenient for test
+  // purposes to use (UTF-8) |std::string|s.)
+  static std::string ModelStringFromNode(const BookmarkNode* node);
+
+  // Create and add the node hierarchy specified by |nodeString| to the
+  // bookmark node given by |node|. The string has the same format as
+  // specified for ModelStringFromNode. The new nodes added to |node|
+  // are appended to the end of node's existing subnodes, if any.
+  // |model| must be the model of which |node| is a member.
+  // NOTE: The string format is very rigid and easily broken if not followed
+  //       exactly (since we're using a very simple parser).
+  static void AddNodesFromModelString(BookmarkModel* model,
+                                      const BookmarkNode* node,
+                                      const std::string& model_string);
+
  private:
-  // Helper to verify the two given bookmark nodes.
-  // The IDs of the bookmark nodes are compared only if check_ids is true.
-  static void AssertNodesEqual(const BookmarkNode* expected,
-                               const BookmarkNode* actual,
-                               bool check_ids);
+  DISALLOW_IMPLICIT_CONSTRUCTORS(BookmarkModelTestUtils);
 };
 
 #endif  // CHROME_BROWSER_BOOKMARKS_BOOKMARK_MODEL_TEST_UTILS_H_
diff --git a/chrome/browser/bookmarks/bookmark_model_unittest.cc b/chrome/browser/bookmarks/bookmark_model_unittest.cc
index 2f8551c..06610d7 100644
--- a/chrome/browser/bookmarks/bookmark_model_unittest.cc
+++ b/chrome/browser/bookmarks/bookmark_model_unittest.cc
@@ -18,18 +18,18 @@
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/browser/bookmarks/bookmark_model_observer.h"
+#include "chrome/browser/bookmarks/bookmark_model_test_utils.h"
 #include "chrome/browser/bookmarks/bookmark_utils.h"
-#include "chrome/test/base/model_test_utils.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/ui_test_utils.h"
-#include "content/public/test/test_browser_thread.h"
-#include "googleurl/src/gurl.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/models/tree_node_iterator.h"
 #include "ui/base/models/tree_node_model.h"
+#include "url/gurl.h"
 
 using base::Time;
 using base::TimeDelta;
@@ -596,53 +596,54 @@
 TEST_F(BookmarkModelTest, Copy) {
   const BookmarkNode* root = model_.bookmark_bar_node();
   static const std::string model_string("a 1:[ b c ] d 2:[ e f g ] h ");
-  model_test_utils::AddNodesFromModelString(&model_, root, model_string);
+  BookmarkModelTestUtils::AddNodesFromModelString(&model_, root, model_string);
 
   // Validate initial model.
-  std::string actual_model_string = model_test_utils::ModelStringFromNode(root);
+  std::string actual_model_string =
+      BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ(model_string, actual_model_string);
 
   // Copy 'd' to be after '1:b': URL item from bar to folder.
-  const BookmarkNode* nodeToCopy = root->GetChild(2);
+  const BookmarkNode* node_to_copy = root->GetChild(2);
   const BookmarkNode* destination = root->GetChild(1);
-  model_.Copy(nodeToCopy, destination, 1);
-  actual_model_string = model_test_utils::ModelStringFromNode(root);
+  model_.Copy(node_to_copy, destination, 1);
+  actual_model_string = BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ("a 1:[ b d c ] d 2:[ e f g ] h ", actual_model_string);
 
   // Copy '1:d' to be after 'a': URL item from folder to bar.
   const BookmarkNode* folder = root->GetChild(1);
-  nodeToCopy = folder->GetChild(1);
-  model_.Copy(nodeToCopy, root, 1);
-  actual_model_string = model_test_utils::ModelStringFromNode(root);
+  node_to_copy = folder->GetChild(1);
+  model_.Copy(node_to_copy, root, 1);
+  actual_model_string = BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ("a d 1:[ b d c ] d 2:[ e f g ] h ", actual_model_string);
 
   // Copy '1' to be after '2:e': Folder from bar to folder.
-  nodeToCopy = root->GetChild(2);
+  node_to_copy = root->GetChild(2);
   destination = root->GetChild(4);
-  model_.Copy(nodeToCopy, destination, 1);
-  actual_model_string = model_test_utils::ModelStringFromNode(root);
+  model_.Copy(node_to_copy, destination, 1);
+  actual_model_string = BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ("a d 1:[ b d c ] d 2:[ e 1:[ b d c ] f g ] h ",
             actual_model_string);
 
   // Copy '2:1' to be after '2:f': Folder within same folder.
   folder = root->GetChild(4);
-  nodeToCopy = folder->GetChild(1);
-  model_.Copy(nodeToCopy, folder, 3);
-  actual_model_string = model_test_utils::ModelStringFromNode(root);
+  node_to_copy = folder->GetChild(1);
+  model_.Copy(node_to_copy, folder, 3);
+  actual_model_string = BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ("a d 1:[ b d c ] d 2:[ e 1:[ b d c ] f 1:[ b d c ] g ] h ",
             actual_model_string);
 
   // Copy first 'd' to be after 'h': URL item within the bar.
-  nodeToCopy = root->GetChild(1);
-  model_.Copy(nodeToCopy, root, 6);
-  actual_model_string = model_test_utils::ModelStringFromNode(root);
+  node_to_copy = root->GetChild(1);
+  model_.Copy(node_to_copy, root, 6);
+  actual_model_string = BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ("a d 1:[ b d c ] d 2:[ e 1:[ b d c ] f 1:[ b d c ] g ] h d ",
             actual_model_string);
 
   // Copy '2' to be after 'a': Folder within the bar.
-  nodeToCopy = root->GetChild(4);
-  model_.Copy(nodeToCopy, root, 1);
-  actual_model_string = model_test_utils::ModelStringFromNode(root);
+  node_to_copy = root->GetChild(4);
+  model_.Copy(node_to_copy, root, 1);
+  actual_model_string = BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ("a 2:[ e 1:[ b d c ] f 1:[ b d c ] g ] d 1:[ b d c ] "
             "d 2:[ e 1:[ b d c ] f 1:[ b d c ] g ] h d ",
             actual_model_string);
@@ -868,9 +869,7 @@
 class BookmarkModelTestWithProfile : public testing::Test {
  public:
   BookmarkModelTestWithProfile()
-      : bb_model_(NULL),
-        ui_thread_(BrowserThread::UI, &message_loop_),
-        file_thread_(BrowserThread::FILE, &message_loop_) {}
+      : bb_model_(NULL) {}
 
   // testing::Test:
   virtual void TearDown() OVERRIDE {
@@ -925,9 +924,7 @@
   BookmarkModel* bb_model_;
 
  private:
-  base::MessageLoopForUI message_loop_;
-  content::TestBrowserThread ui_thread_;
-  content::TestBrowserThread file_thread_;
+  content::TestBrowserThreadBundle thread_bundle_;
 };
 
 // Creates a set of nodes in the bookmark bar model, then recreates the
@@ -1114,16 +1111,24 @@
   EXPECT_EQ("value1", out_value);
   EXPECT_FALSE(node.SetMetaInfo("key1", "value1"));
 
-  EXPECT_FALSE(node.GetMetaInfo("key2", &out_value));
-  EXPECT_TRUE(node.SetMetaInfo("key2", "value2"));
-  EXPECT_TRUE(node.GetMetaInfo("key2", &out_value));
+  EXPECT_FALSE(node.GetMetaInfo("key2.subkey1", &out_value));
+  EXPECT_TRUE(node.SetMetaInfo("key2.subkey1", "value2"));
+  EXPECT_TRUE(node.GetMetaInfo("key2.subkey1", &out_value));
   EXPECT_EQ("value2", out_value);
 
+  EXPECT_FALSE(node.GetMetaInfo("key2.subkey2.leaf", &out_value));
+  EXPECT_TRUE(node.SetMetaInfo("key2.subkey2.leaf", ""));
+  EXPECT_TRUE(node.GetMetaInfo("key2.subkey2.leaf", &out_value));
+  EXPECT_EQ("", out_value);
+
   EXPECT_TRUE(node.DeleteMetaInfo("key1"));
-  EXPECT_TRUE(node.DeleteMetaInfo("key2"));
+  EXPECT_TRUE(node.DeleteMetaInfo("key2.subkey1"));
+  EXPECT_TRUE(node.DeleteMetaInfo("key2.subkey2.leaf"));
   EXPECT_FALSE(node.DeleteMetaInfo("key3"));
   EXPECT_FALSE(node.GetMetaInfo("key1", &out_value));
-  EXPECT_FALSE(node.GetMetaInfo("key2", &out_value));
+  EXPECT_FALSE(node.GetMetaInfo("key2.subkey1", &out_value));
+  EXPECT_FALSE(node.GetMetaInfo("key2.subkey2", &out_value));
+  EXPECT_FALSE(node.GetMetaInfo("key2.subkey2.leaf", &out_value));
   EXPECT_TRUE(node.meta_info_str().empty());
 }
 
diff --git a/chrome/browser/bookmarks/bookmark_node_data.h b/chrome/browser/bookmarks/bookmark_node_data.h
index 80e55f6..1401e70 100644
--- a/chrome/browser/bookmarks/bookmark_node_data.h
+++ b/chrome/browser/bookmarks/bookmark_node_data.h
@@ -9,7 +9,7 @@
 
 #include "base/files/file_path.h"
 #include "base/strings/string16.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 #if defined(TOOLKIT_VIEWS)
 #include "ui/base/dragdrop/os_exchange_data.h"
diff --git a/chrome/browser/bookmarks/bookmark_node_data_unittest.cc b/chrome/browser/bookmarks/bookmark_node_data_unittest.cc
index dff83cc..8e5c0e2 100644
--- a/chrome/browser/bookmarks/bookmark_node_data_unittest.cc
+++ b/chrome/browser/bookmarks/bookmark_node_data_unittest.cc
@@ -11,25 +11,18 @@
 #include "chrome/browser/bookmarks/bookmark_node_data.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/ui_test_utils.h"
-#include "content/public/test/test_browser_thread.h"
-#include "googleurl/src/gurl.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/dragdrop/os_exchange_data.h"
 #include "ui/base/dragdrop/os_exchange_data_provider_win.h"
-
-using content::BrowserThread;
+#include "url/gurl.h"
 
 class BookmarkNodeDataTest : public testing::Test {
  public:
-  BookmarkNodeDataTest()
-      : ui_thread_(BrowserThread::UI, &loop_),
-        file_thread_(BrowserThread::FILE, &loop_) {
-  }
+  BookmarkNodeDataTest() {}
 
  private:
-  base::MessageLoop loop_;
-  content::TestBrowserThread ui_thread_;
-  content::TestBrowserThread file_thread_;
+  content::TestBrowserThreadBundle thread_bundle_;
 };
 
 namespace {
diff --git a/chrome/browser/bookmarks/bookmark_service.h b/chrome/browser/bookmarks/bookmark_service.h
index 284fe4c..8233565 100644
--- a/chrome/browser/bookmarks/bookmark_service.h
+++ b/chrome/browser/bookmarks/bookmark_service.h
@@ -8,7 +8,7 @@
 #include <vector>
 
 #include "base/strings/string16.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 namespace content {
 class BrowserContext;
diff --git a/chrome/browser/bookmarks/bookmark_storage.cc b/chrome/browser/bookmarks/bookmark_storage.cc
index 431a6d1..b7b2ce1 100644
--- a/chrome/browser/bookmarks/bookmark_storage.cc
+++ b/chrome/browser/bookmarks/bookmark_storage.cc
@@ -11,7 +11,7 @@
 #include "base/json/json_file_value_serializer.h"
 #include "base/json/json_string_value_serializer.h"
 #include "base/metrics/histogram.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/bookmarks/bookmark_codec.h"
 #include "chrome/browser/bookmarks/bookmark_index.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
diff --git a/chrome/browser/bookmarks/bookmark_utils.cc b/chrome/browser/bookmarks/bookmark_utils.cc
index b72b22f..ea04f7f 100644
--- a/chrome/browser/bookmarks/bookmark_utils.cc
+++ b/chrome/browser/bookmarks/bookmark_utils.cc
@@ -14,7 +14,7 @@
 #include "base/prefs/pref_service.h"
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/bookmarks/bookmark_node_data.h"
 #include "chrome/browser/history/query_parser.h"
@@ -76,38 +76,6 @@
           net::UnescapeRule::NORMAL, NULL, NULL, NULL), words);
 }
 
-const BookmarkNode* CreateNewNode(BookmarkModel* model,
-                                  const BookmarkNode* parent,
-                                  const BookmarkEditor::EditDetails& details,
-                                  const string16& new_title,
-                                  const GURL& new_url) {
-  const BookmarkNode* node;
-  // When create the new one to right-clicked folder, add it to the next to the
-  // folder's position. Because |details.index| has a index of the folder when
-  // it was right-clicked, it might cause out of range exception when another
-  // bookmark manager edits contents of the folder.
-  // So we must check the range.
-  int child_count = parent->child_count();
-  int insert_index = (parent == details.parent_node && details.index >= 0 &&
-                      details.index <= child_count) ?
-                      details.index : child_count;
-  if (details.type == BookmarkEditor::EditDetails::NEW_URL) {
-    node = model->AddURL(parent, insert_index, new_title, new_url);
-  } else if (details.type == BookmarkEditor::EditDetails::NEW_FOLDER) {
-    node = model->AddFolder(parent, insert_index, new_title);
-    for (size_t i = 0; i < details.urls.size(); ++i) {
-      model->AddURL(node, node->child_count(), details.urls[i].second,
-                    details.urls[i].first);
-    }
-    model->SetDateFolderModified(parent, Time::Now());
-  } else {
-    NOTREACHED();
-    return NULL;
-  }
-
-  return node;
-}
-
 }  // namespace
 
 namespace bookmark_utils {
@@ -270,50 +238,6 @@
   return (node->is_url() && DoesBookmarkContainWords(node, words, languages));
 }
 
-const BookmarkNode* ApplyEditsWithNoFolderChange(
-    BookmarkModel* model,
-    const BookmarkNode* parent,
-    const BookmarkEditor::EditDetails& details,
-    const string16& new_title,
-    const GURL& new_url) {
-  if (details.type == BookmarkEditor::EditDetails::NEW_URL ||
-      details.type == BookmarkEditor::EditDetails::NEW_FOLDER) {
-    return CreateNewNode(model, parent, details, new_title, new_url);
-  }
-
-  const BookmarkNode* node = details.existing_node;
-  DCHECK(node);
-
-  if (node->is_url())
-    model->SetURL(node, new_url);
-  model->SetTitle(node, new_title);
-
-  return node;
-}
-
-const BookmarkNode* ApplyEditsWithPossibleFolderChange(
-    BookmarkModel* model,
-    const BookmarkNode* new_parent,
-    const BookmarkEditor::EditDetails& details,
-    const string16& new_title,
-    const GURL& new_url) {
-  if (details.type == BookmarkEditor::EditDetails::NEW_URL ||
-      details.type == BookmarkEditor::EditDetails::NEW_FOLDER) {
-    return CreateNewNode(model, new_parent, details, new_title, new_url);
-  }
-
-  const BookmarkNode* node = details.existing_node;
-  DCHECK(node);
-
-  if (new_parent != node->parent())
-    model->Move(node, new_parent, new_parent->child_count());
-  if (node->is_url())
-    model->SetURL(node, new_url);
-  model->SetTitle(node, new_title);
-
-  return node;
-}
-
 void RegisterUserPrefs(user_prefs::PrefRegistrySyncable* registry) {
   registry->RegisterBooleanPref(
       prefs::kShowBookmarkBar,
diff --git a/chrome/browser/bookmarks/bookmark_utils.h b/chrome/browser/bookmarks/bookmark_utils.h
index 1524f3f..a72e6d8 100644
--- a/chrome/browser/bookmarks/bookmark_utils.h
+++ b/chrome/browser/bookmarks/bookmark_utils.h
@@ -9,7 +9,6 @@
 #include <vector>
 
 #include "base/strings/string16.h"
-#include "chrome/browser/bookmarks/bookmark_editor.h"
 #include "chrome/browser/bookmarks/bookmark_node_data.h"
 
 class BookmarkModel;
@@ -76,28 +75,6 @@
                              const string16& text,
                              const std::string& languages);
 
-// Modifies a bookmark node (assuming that there's no magic that needs to be
-// done regarding moving from one folder to another).  If a new node is
-// explicitly being added, returns a pointer to the new node that was created.
-// Otherwise the return value is identically |node|.
-const BookmarkNode* ApplyEditsWithNoFolderChange(
-    BookmarkModel* model,
-    const BookmarkNode* parent,
-    const BookmarkEditor::EditDetails& details,
-    const string16& new_title,
-    const GURL& new_url);
-
-// Modifies a bookmark node assuming that the parent of the node may have
-// changed and the node will need to be removed and reinserted.  If a new node
-// is explicitly being added, returns a pointer to the new node that was
-// created.  Otherwise the return value is identically |node|.
-const BookmarkNode* ApplyEditsWithPossibleFolderChange(
-    BookmarkModel* model,
-    const BookmarkNode* new_parent,
-    const BookmarkEditor::EditDetails& details,
-    const string16& new_title,
-    const GURL& new_url);
-
 // Register user preferences for Bookmarks Bar.
 void RegisterUserPrefs(user_prefs::PrefRegistrySyncable* registry);
 
diff --git a/chrome/browser/bookmarks/bookmark_utils_unittest.cc b/chrome/browser/bookmarks/bookmark_utils_unittest.cc
index f3bd727..e96f3f7 100644
--- a/chrome/browser/bookmarks/bookmark_utils_unittest.cc
+++ b/chrome/browser/bookmarks/bookmark_utils_unittest.cc
@@ -6,7 +6,6 @@
 
 #include "base/message_loop.h"
 #include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/bookmarks/bookmark_editor.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/clipboard/clipboard.h"
@@ -157,44 +156,6 @@
   EXPECT_FALSE(CanPasteFromClipboard(model.bookmark_bar_node()));
 }
 
-TEST_F(BookmarkUtilsTest, ApplyEditsWithNoFolderChange) {
-  BookmarkModel model(NULL);
-  const BookmarkNode* bookmarkbar = model.bookmark_bar_node();
-  model.AddURL(bookmarkbar, 0, ASCIIToUTF16("url0"), GURL("chrome://newtab"));
-  model.AddURL(bookmarkbar, 1, ASCIIToUTF16("url1"), GURL("chrome://newtab"));
-
-  {
-    BookmarkEditor::EditDetails detail(
-        BookmarkEditor::EditDetails::AddFolder(bookmarkbar, 1));
-    ApplyEditsWithNoFolderChange(&model,
-                                 bookmarkbar,
-                                 detail,
-                                 ASCIIToUTF16("folder0"),
-                                 GURL(std::string()));
-    EXPECT_EQ(ASCIIToUTF16("folder0"), bookmarkbar->GetChild(1)->GetTitle());
-  }
-  {
-    BookmarkEditor::EditDetails detail(
-        BookmarkEditor::EditDetails::AddFolder(bookmarkbar, -1));
-    ApplyEditsWithNoFolderChange(&model,
-                                 bookmarkbar,
-                                 detail,
-                                 ASCIIToUTF16("folder1"),
-                                 GURL(std::string()));
-    EXPECT_EQ(ASCIIToUTF16("folder1"), bookmarkbar->GetChild(3)->GetTitle());
-  }
-  {
-    BookmarkEditor::EditDetails detail(
-        BookmarkEditor::EditDetails::AddFolder(bookmarkbar, 10));
-    ApplyEditsWithNoFolderChange(&model,
-                                 bookmarkbar,
-                                 detail,
-                                 ASCIIToUTF16("folder2"),
-                                 GURL(std::string()));
-    EXPECT_EQ(ASCIIToUTF16("folder2"), bookmarkbar->GetChild(4)->GetTitle());
-  }
-}
-
 TEST_F(BookmarkUtilsTest, GetParentForNewNodes) {
   BookmarkModel model(NULL);
   // This tests the case where selection contains one item and that item is a
diff --git a/chrome/browser/bookmarks/imported_bookmark_entry.cc b/chrome/browser/bookmarks/imported_bookmark_entry.cc
deleted file mode 100644
index f6a30a8..0000000
--- a/chrome/browser/bookmarks/imported_bookmark_entry.cc
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/bookmarks/imported_bookmark_entry.h"
-
-ImportedBookmarkEntry::ImportedBookmarkEntry()
-    : in_toolbar(false),
-      is_folder(false) {}
-
-ImportedBookmarkEntry::~ImportedBookmarkEntry() {}
-
-bool ImportedBookmarkEntry::operator==(
-    const ImportedBookmarkEntry& other) const {
-  return (in_toolbar == other.in_toolbar &&
-          is_folder == other.is_folder &&
-          url == other.url &&
-          path == other.path &&
-          title == other.title &&
-          creation_time == other.creation_time);
-}
diff --git a/chrome/browser/bookmarks/imported_bookmark_entry.h b/chrome/browser/bookmarks/imported_bookmark_entry.h
deleted file mode 100644
index 73bf0a9..0000000
--- a/chrome/browser/bookmarks/imported_bookmark_entry.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_BOOKMARKS_IMPORTED_BOOKMARK_ENTRY_H_
-#define CHROME_BROWSER_BOOKMARKS_IMPORTED_BOOKMARK_ENTRY_H_
-
-#include <vector>
-
-#include "base/strings/string16.h"
-#include "base/time.h"
-#include "googleurl/src/gurl.h"
-
-struct ImportedBookmarkEntry {
-  ImportedBookmarkEntry();
-  ~ImportedBookmarkEntry();
-
-  bool operator==(const ImportedBookmarkEntry& other) const;
-
-  bool in_toolbar;
-  bool is_folder;
-  GURL url;
-  std::vector<base::string16> path;
-  base::string16 title;
-  base::Time creation_time;
-};
-
-#endif  // CHROME_BROWSER_BOOKMARKS_IMPORTED_BOOKMARK_ENTRY_H_
diff --git a/chrome/browser/browser_about_handler.cc b/chrome/browser/browser_about_handler.cc
index 9dfcf1d..22c4f92 100644
--- a/chrome/browser/browser_about_handler.cc
+++ b/chrome/browser/browser_about_handler.cc
@@ -11,6 +11,7 @@
 #include "base/logging.h"
 #include "base/memory/singleton.h"
 #include "base/strings/string_util.h"
+#include "chrome/browser/lifetime/application_lifetime.h"
 #include "chrome/browser/net/url_fixer_upper.h"
 #include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/common/chrome_switches.h"
@@ -101,6 +102,9 @@
   content::kChromeUINetworkViewCacheHost,
   content::kChromeUITracingHost,
   content::kChromeUIWebRTCInternalsHost,
+#if defined(ENABLE_WEBRTC)
+  chrome::kChromeUIWebRtcLogsHost,
+#endif
 };
 
 }  // namespace
@@ -157,6 +161,11 @@
   } else if (host == chrome::kChromeUIHelpHost) {
     host = chrome::kChromeUIUberHost;
     path = chrome::kChromeUIHelpHost + url->path();
+  } else if (host == chrome::kChromeUIRestartHost) {
+    // Call AttemptRestart after chrome::Navigate() completes to avoid access of
+    // gtk objects after they are destoyed by BrowserWindowGtk::Close().
+    base::MessageLoop::current()->PostTask(FROM_HERE,
+        base::Bind(&chrome::AttemptRestart));
   }
   GURL::Replacements replacements;
   replacements.SetHostStr(host);
diff --git a/chrome/browser/browser_about_handler_unittest.cc b/chrome/browser/browser_about_handler_unittest.cc
index c21f2e4..0b6e9c4 100644
--- a/chrome/browser/browser_about_handler_unittest.cc
+++ b/chrome/browser/browser_about_handler_unittest.cc
@@ -9,8 +9,8 @@
 #include "chrome/common/url_constants.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/test/test_browser_thread.h"
-#include "googleurl/src/gurl.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 using content::BrowserThread;
 
diff --git a/chrome/browser/browser_keyevents_browsertest.cc b/chrome/browser/browser_keyevents_browsertest.cc
index 781d009..f27f00f 100644
--- a/chrome/browser/browser_keyevents_browsertest.cc
+++ b/chrome/browser/browser_keyevents_browsertest.cc
@@ -25,7 +25,7 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_view.h"
 #include "content/public/test/browser_test_utils.h"
-#include "net/test/spawned_test_server/spawned_test_server.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
 #include "ui/base/keycodes/keyboard_codes.h"
 #include "ui/views/controls/textfield/textfield.h"
 
@@ -40,7 +40,7 @@
 
 namespace {
 
-const char kTestingPage[] = "files/keyevents_test.html";
+const char kTestingPage[] = "/keyevents_test.html";
 const char kSuppressEventJS[] =
     "window.domAutomationController.send(setDefaultAction('%ls', %ls));";
 const char kGetResultJS[] =
@@ -368,10 +368,10 @@
         "U 65 0 false false false false" } },
   };
 
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-  GURL url = test_server()->GetURL(kTestingPage);
+  GURL url = embedded_test_server()->GetURL(kTestingPage);
   ui_test_utils::NavigateToURL(browser(), url);
 
   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
@@ -461,10 +461,10 @@
       "U 17 0 true false false false" }
   };
 
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-  GURL url = test_server()->GetURL(kTestingPage);
+  GURL url = embedded_test_server()->GetURL(kTestingPage);
   ui_test_utils::NavigateToURL(browser(), url);
 
   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
@@ -507,10 +507,10 @@
       "U 91 0 false false false true" }
   };
 
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-  GURL url = test_server()->GetURL(kTestingPage);
+  GURL url = embedded_test_server()->GetURL(kTestingPage);
   ui_test_utils::NavigateToURL(browser(), url);
 
   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
@@ -607,10 +607,10 @@
 #endif
 #endif
 
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-  GURL url = test_server()->GetURL(kTestingPage);
+  GURL url = embedded_test_server()->GetURL(kTestingPage);
   ui_test_utils::NavigateToURL(browser(), url);
 
   content::RunAllPendingInMessageLoop();
@@ -681,10 +681,10 @@
 #define MAYBE_ReservedAccelerators ReservedAccelerators
 #endif
 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, MAYBE_ReservedAccelerators) {
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-  GURL url = test_server()->GetURL(kTestingPage);
+  GURL url = embedded_test_server()->GetURL(kTestingPage);
   ui_test_utils::NavigateToURL(browser(), url);
 
   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
@@ -783,10 +783,10 @@
       "U 17 0 true false false false" }
   };
 
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-  GURL url = test_server()->GetURL(kTestingPage);
+  GURL url = embedded_test_server()->GetURL(kTestingPage);
   ui_test_utils::NavigateToURL(browser(), url);
 
   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
@@ -821,10 +821,10 @@
       "U 34 0 false false false false" }
   };
 
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-  GURL url = test_server()->GetURL(kTestingPage);
+  GURL url = embedded_test_server()->GetURL(kTestingPage);
   ui_test_utils::NavigateToURL(browser(), url);
 
   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
@@ -863,10 +863,10 @@
       "U 17 0 true false false false" }
   };
 
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-  GURL url = test_server()->GetURL(kTestingPage);
+  GURL url = embedded_test_server()->GetURL(kTestingPage);
   ui_test_utils::NavigateToURL(browser(), url);
 
   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
diff --git a/chrome/browser/browser_process.h b/chrome/browser/browser_process.h
index d6f8595..0824b1c 100644
--- a/chrome/browser/browser_process.h
+++ b/chrome/browser/browser_process.h
@@ -13,6 +13,7 @@
 #include <string>
 
 #include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
 #include "chrome/browser/browser_process_platform_part.h"
 #include "chrome/browser/ui/host_desktop.h"
 
@@ -175,6 +176,8 @@
 
   // Returns the object that manages background applications.
   virtual BackgroundModeManager* background_mode_manager() = 0;
+  virtual void set_background_mode_manager_for_test(
+      scoped_ptr<BackgroundModeManager> manager) = 0;
 
   // Returns the StatusTray, which provides an API for displaying status icons
   // in the system status tray. Returns NULL if status icons are not supported
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc
index 44bf2da..6673807 100644
--- a/chrome/browser/browser_process_impl.cc
+++ b/chrome/browser/browser_process_impl.cc
@@ -704,6 +704,11 @@
 #endif
 }
 
+void BrowserProcessImpl::set_background_mode_manager_for_test(
+    scoped_ptr<BackgroundModeManager> manager) {
+  background_mode_manager_ = manager.Pass();
+}
+
 StatusTray* BrowserProcessImpl::status_tray() {
   DCHECK(CalledOnValidThread());
   if (!status_tray_.get())
diff --git a/chrome/browser/browser_process_impl.h b/chrome/browser/browser_process_impl.h
index 201eb92..66191dc 100644
--- a/chrome/browser/browser_process_impl.h
+++ b/chrome/browser/browser_process_impl.h
@@ -18,7 +18,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/prefs/pref_change_registrar.h"
 #include "base/threading/non_thread_safe.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/browser_process.h"
 
 class ChromeNetLog;
@@ -110,6 +110,8 @@
   virtual DownloadStatusUpdater* download_status_updater() OVERRIDE;
   virtual DownloadRequestLimiter* download_request_limiter() OVERRIDE;
   virtual BackgroundModeManager* background_mode_manager() OVERRIDE;
+  virtual void set_background_mode_manager_for_test(
+      scoped_ptr<BackgroundModeManager> manager) OVERRIDE;
   virtual StatusTray* status_tray() OVERRIDE;
   virtual SafeBrowsingService* safe_browsing_service() OVERRIDE;
   virtual safe_browsing::ClientSideDetectionService*
diff --git a/chrome/browser/browser_process_platform_part_aurawin.cc b/chrome/browser/browser_process_platform_part_aurawin.cc
index e6be06d..34813a6 100644
--- a/chrome/browser/browser_process_platform_part_aurawin.cc
+++ b/chrome/browser/browser_process_platform_part_aurawin.cc
@@ -24,13 +24,23 @@
 
 void BrowserProcessPlatformPart::PlatformSpecificCommandLineProcessing(
     const CommandLine& command_line) {
-  if (base::win::GetVersion() >= base::win::VERSION_WIN8 &&
-      command_line.HasSwitch(switches::kViewerConnection) &&
-      !metro_viewer_process_host_.get()) {
-    // Tell the metro viewer process host to connect to the given IPC channel.
-    metro_viewer_process_host_.reset(
-        new ChromeMetroViewerProcessHost(
-            command_line.GetSwitchValueASCII(switches::kViewerConnection)));
+  // Check for Windows 8 specific commandlines requesting that this process
+  // either connect to an existing viewer or launch a new viewer and
+  // synchronously wait for it to connect.
+  if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
+    bool launch = command_line.HasSwitch(switches::kViewerLaunchViaAppId);
+    bool connect = (launch ||
+                    (command_line.HasSwitch(switches::kViewerConnect) &&
+                     !metro_viewer_process_host_.get()));
+    if (connect) {
+      // Create a host to connect to the Metro viewer process over IPC.
+      metro_viewer_process_host_.reset(new ChromeMetroViewerProcessHost());
+      if (launch) {
+        CHECK(metro_viewer_process_host_->LaunchViewerAndWaitForConnection(
+            command_line.GetSwitchValueNative(
+                switches::kViewerLaunchViaAppId)));
+      }
+    }
   }
 }
 
diff --git a/chrome/browser/browser_process_platform_part_chromeos.cc b/chrome/browser/browser_process_platform_part_chromeos.cc
index 11cacb3..1821785 100644
--- a/chrome/browser/browser_process_platform_part_chromeos.cc
+++ b/chrome/browser/browser_process_platform_part_chromeos.cc
@@ -4,8 +4,12 @@
 
 #include "chrome/browser/browser_process_platform_part_chromeos.h"
 
+#include "base/logging.h"
+#include "base/time/default_tick_clock.h"
+#include "base/time/tick_clock.h"
 #include "chrome/browser/chromeos/memory/oom_priority_manager.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chrome/browser/chromeos/system/automatic_reboot_manager.h"
 
 BrowserProcessPlatformPart::BrowserProcessPlatformPart()
     : created_profile_helper_(false) {
@@ -14,6 +18,17 @@
 BrowserProcessPlatformPart::~BrowserProcessPlatformPart() {
 }
 
+void BrowserProcessPlatformPart::InitializeAutomaticRebootManager() {
+  DCHECK(!automatic_reboot_manager_);
+
+  automatic_reboot_manager_.reset(new chromeos::system::AutomaticRebootManager(
+      scoped_ptr<base::TickClock>(new base::DefaultTickClock)));
+}
+
+void BrowserProcessPlatformPart::ShutdownAutomaticRebootManager() {
+  automatic_reboot_manager_.reset();
+}
+
 chromeos::OomPriorityManager*
     BrowserProcessPlatformPart::oom_priority_manager() {
   DCHECK(CalledOnValidThread());
diff --git a/chrome/browser/browser_process_platform_part_chromeos.h b/chrome/browser/browser_process_platform_part_chromeos.h
index 3eb1236..08dc683 100644
--- a/chrome/browser/browser_process_platform_part_chromeos.h
+++ b/chrome/browser/browser_process_platform_part_chromeos.h
@@ -15,12 +15,21 @@
 class ProfileHelper;
 }
 
+namespace chromeos {
+namespace system {
+class AutomaticRebootManager;
+}
+}
+
 class BrowserProcessPlatformPart : public BrowserProcessPlatformPartBase,
                                    public base::NonThreadSafe {
  public:
   BrowserProcessPlatformPart();
   virtual ~BrowserProcessPlatformPart();
 
+  void InitializeAutomaticRebootManager();
+  void ShutdownAutomaticRebootManager();
+
   // Returns the out-of-memory priority manager.
   virtual chromeos::OomPriorityManager* oom_priority_manager();
 
@@ -31,6 +40,10 @@
   // Overridden from BrowserProcessPlatformPartBase:
   virtual void StartTearDown() OVERRIDE;
 
+  chromeos::system::AutomaticRebootManager* automatic_reboot_manager() {
+    return automatic_reboot_manager_.get();
+  }
+
  protected:
   virtual void CreateProfileHelper();
 
@@ -40,6 +53,9 @@
  private:
   scoped_ptr<chromeos::OomPriorityManager> oom_priority_manager_;
 
+  scoped_ptr<chromeos::system::AutomaticRebootManager>
+      automatic_reboot_manager_;
+
   DISALLOW_COPY_AND_ASSIGN(BrowserProcessPlatformPart);
 };
 
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index 24678bd..749ac3a 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -35,6 +35,8 @@
       <structure name="IDR_EXTENSIONS_HTML" file="resources\extensions\extensions.html" flattenhtml="true" type="chrome_html" />
       <structure name="IDR_HELP_CSS" file="resources\help\help.css" flattenhtml="true" type="chrome_html" />
       <structure name="IDR_HELP_HTML" file="resources\help\help.html" flattenhtml="true" type="chrome_html" />
+      <structure name="IDR_HELP_CHANNEL_CHANGE_PAGE_CSS" file="resources\help\channel_change_page.css" flattenhtml="true" type="chrome_html" />
+      <structure name="IDR_HELP_CHANNEL_CHANGE_PAGE_HTML" file="resources\help\channel_change_page.html" flattenhtml="true" type="chrome_html" />
       <structure name="IDR_INCOGNITO_TAB_HTML" file="resources\incognito_tab.html" flattenhtml="true" type="chrome_html" />
       <if expr="pp_ifdef('chromeos')">
         <structure name="IDR_LOGIN_HTML" file="resources\chromeos\login\login.html" flattenhtml="true" type="chrome_html" variables="OOBE=login" expand_variables="true"/>
@@ -93,9 +95,6 @@
       </if>
       <if expr="pp_ifdef('enable_printing')">
         <include name="IDR_CLOUDPRINT_MANIFEST" file="resources\cloud_print_app\manifest.json" type="BINDATA" />
-        <include name="IDR_CLOUD_PRINT_SETUP_DONE_HTML" file="resources\cloud_print\cloud_print_setup_done.html" flattenhtml="true" type="BINDATA" />
-        <include name="IDR_CLOUD_PRINT_SETUP_FLOW_HTML" file="resources\cloud_print\cloud_print_setup_flow.html" flattenhtml="true" type="BINDATA" />
-        <include name="IDR_CLOUD_PRINT_SETUP_LOGIN_HTML" file="resources\cloud_print\cloud_print_setup_login.html" flattenhtml="true" type="BINDATA" />
       </if>
       <include name="IDR_CRASHES_HTML" file="resources\crashes.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
       <include name="IDR_CRASHES_JS" file="resources\crashes.js" type="BINDATA" />
@@ -120,10 +119,8 @@
       </if>
       <include name="IDR_FLAGS_HTML" file="resources\flags.html" flattenhtml="true" type="BINDATA" />
       <include name="IDR_FLAGS_JS" file="resources\flags.js" type="BINDATA" />
-      <if expr="not is_android">
-        <include name="IDR_GAIA_LOGIN_HTML" file="sync\resources\gaia_login.html" flattenhtml="true" type="BINDATA" />
-      </if>
       <include name="IDR_HELP_JS" file="resources\help\help.js" flattenhtml="true" type="BINDATA" />
+      <include name="IDR_CHANNEL_CHANGE_PAGE_JS" file="resources\help\channel_change_page.js" flattenhtml="true" type="BINDATA" />
       <include name="IDR_HISTORY_HTML" file="resources\history\history.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
       <include name="IDR_HISTORY_JS" file="resources\history\history.js" flattenhtml="true" type="BINDATA" />
       <include name="IDR_OTHER_DEVICES_JS" file="resources\history\other_devices.js" flattenhtml="true" type="BINDATA" />
@@ -158,9 +155,7 @@
       <include name="IDR_LOCAL_NTP_HTML" file="resources\local_ntp\local_ntp.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
       <include name="IDR_LOCAL_NTP_CSS" file="resources\local_ntp\local_ntp.css" type="BINDATA" />
       <include name="IDR_LOCAL_NTP_JS" file="resources\local_ntp\local_ntp.js" flattenhtml="true" type="BINDATA" />
-      <include name="IDR_LOCAL_NTP_IMAGES_LOGO_PNG" file="resources\local_ntp\images\ntp_google_logo.png" type="BINDATA" />
       <include name="IDR_LOCAL_NTP_IMAGES_2X_LOGO_PNG" file="resources\local_ntp\images\2x\ntp_google_logo.png" type="BINDATA" />
-      <include name="IDR_LOCAL_NTP_IMAGES_WHITE_LOGO_PNG" file="resources\local_ntp\images\ntp_white_google_logo.png" type="BINDATA" />
       <include name="IDR_LOCAL_NTP_IMAGES_2X_WHITE_LOGO_PNG" file="resources\local_ntp\images\2x\ntp_white_google_logo.png" type="BINDATA" />
       <include name="IDR_LOCAL_OMNIBOX_POPUP_IMAGES_HISTORY_ICON_PNG" file="resources\local_omnibox_popup\images\history_icon.png" type="BINDATA" />
       <include name="IDR_LOCAL_OMNIBOX_POPUP_IMAGES_2X_HISTORY_ICON_PNG" file="resources\local_omnibox_popup\images\2x\history_icon.png" type="BINDATA" />
@@ -259,6 +254,10 @@
       <include name="IDR_USER_ACTIONS_HTML" file="resources\user_actions\user_actions.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
       <include name="IDR_USER_ACTIONS_CSS" file="resources\user_actions\user_actions.css" type="BINDATA" />
       <include name="IDR_USER_ACTIONS_JS" file="resources\user_actions\user_actions.js" type="BINDATA" />
+      <if expr="pp_ifdef('enable_webrtc')">
+        <include name="IDR_WEBRTC_LOGS_HTML" file="resources\media\webrtc_logs.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
+        <include name="IDR_WEBRTC_LOGS_JS" file="resources\media\webrtc_logs.js" type="BINDATA" />
+      </if>
       <include name="IDR_WEBSTORE_MANIFEST" file="resources\webstore_app\manifest.json" type="BINDATA" />
       <if expr="pp_ifdef('use_ash')">
         <include name="IDR_TASK_MANAGER_HTML" file="resources\task_manager\main.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
@@ -274,7 +273,6 @@
       </if>
       <include name="IDR_GAIA_AUTH_MANIFEST" file="resources\gaia_auth\manifest.json" type="BINDATA" />
       <include name="IDR_GAIA_AUTH_KEYBOARD_MANIFEST" file="resources\gaia_auth\manifest_keyboard.json" type="BINDATA" />
-      <include name="IDR_GAIA_TEST_AUTH_MANIFEST" file="resources\gaia_auth\manifest_test.json" type="BINDATA" />
       <if expr="pp_ifdef('chromeos')">
         <include name="IDR_ABOUT_SYS_HTML" file="resources\chromeos\about_sys.html" flattenhtml="true" type="BINDATA" />
         <include name="IDR_BACKLOADER_MANIFEST" file="resources\backloader\manifest.json" type="BINDATA" />
@@ -341,6 +339,11 @@
         <include name="IDR_QUICKOFFICE_EDITOR_MANIFEST"
         file="resources\quick_office\manifest_experimental.json" type="BINDATA" />
       </if>
+      <if expr="pp_ifdef('chromeos')">
+        <include name="IDR_SALSA_CSS" file="resources\chromeos\salsa.css" type="BINDATA" />
+        <include name="IDR_SALSA_HTML" file="resources\chromeos\salsa.html" type="BINDATA" />
+        <include name="IDR_SALSA_JS" file="resources\chromeos\salsa.js" type="BINDATA" />
+      </if>
       <if expr="pp_ifdef('use_ash')">
         <include name="IDR_GESTURE_CONFIG_CSS" file="resources\gesture_config.css" type="BINDATA" />
         <include name="IDR_GESTURE_CONFIG_HTML" file="resources\gesture_config.html" type="BINDATA" />
diff --git a/chrome/browser/browser_shutdown.cc b/chrome/browser/browser_shutdown.cc
index e9f7a8a..9cc661b 100644
--- a/chrome/browser/browser_shutdown.cc
+++ b/chrome/browser/browser_shutdown.cc
@@ -20,7 +20,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_restrictions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "build/build_config.h"
 #include "chrome/browser/about_flags.h"
 #include "chrome/browser/browser_process.h"
@@ -267,7 +267,7 @@
   int64 shutdown_ms = 0;
   if (file_util::ReadFileToString(shutdown_ms_file, &shutdown_ms_str))
     base::StringToInt64(shutdown_ms_str, &shutdown_ms);
-  file_util::Delete(shutdown_ms_file, false);
+  base::Delete(shutdown_ms_file, false);
 
   if (type == NOT_VALID || shutdown_ms == 0 || num_procs == 0)
     return;
diff --git a/chrome/browser/browsing_data/browsing_data_appcache_helper.h b/chrome/browser/browsing_data/browsing_data_appcache_helper.h
index 46ea34e..6f3ac7a 100644
--- a/chrome/browser/browsing_data/browsing_data_appcache_helper.h
+++ b/chrome/browser/browsing_data/browsing_data_appcache_helper.h
@@ -7,8 +7,8 @@
 
 #include "base/callback.h"
 #include "base/memory/ref_counted.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/completion_callback.h"
+#include "url/gurl.h"
 #include "webkit/browser/appcache/appcache_service.h"
 
 class Profile;
diff --git a/chrome/browser/browsing_data/browsing_data_cookie_helper.cc b/chrome/browser/browsing_data/browsing_data_cookie_helper.cc
index f5819af..5551642 100644
--- a/chrome/browser/browsing_data/browsing_data_cookie_helper.cc
+++ b/chrome/browser/browsing_data/browsing_data_cookie_helper.cc
@@ -12,13 +12,13 @@
 #include "base/stl_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "content/public/browser/browser_thread.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
 #include "net/cookies/canonical_cookie.h"
 #include "net/cookies/cookie_util.h"
 #include "net/cookies/parsed_cookie.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_context_getter.h"
+#include "url/gurl.h"
 
 using content::BrowserThread;
 
diff --git a/chrome/browser/browsing_data/browsing_data_cookie_helper_unittest.cc b/chrome/browser/browsing_data/browsing_data_cookie_helper_unittest.cc
index a54b9bd..968a733 100644
--- a/chrome/browser/browsing_data/browsing_data_cookie_helper_unittest.cc
+++ b/chrome/browser/browsing_data/browsing_data_cookie_helper_unittest.cc
@@ -4,12 +4,11 @@
 
 #include "chrome/browser/browsing_data/browsing_data_cookie_helper.h"
 
-
 #include "base/bind.h"
 #include "base/message_loop.h"
-#include "base/synchronization/waitable_event.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "net/cookies/canonical_cookie.h"
 #include "net/cookies/parsed_cookie.h"
 #include "net/url_request/url_request_context_getter.h"
@@ -21,7 +20,7 @@
 
 class BrowsingDataCookieHelperTest : public testing::Test {
  public:
-  void SetUpOnIOThread(base::WaitableEvent* io_setup_complete) {
+  void SetUpOnIOThread() {
     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
     // This is a workaround for a bug in the TestingProfile.
     // The URLRequestContext will be created by GetCookieMonster on the UI
@@ -30,31 +29,21 @@
     // Force it to be created here.
     testing_profile_->CreateRequestContext();
     testing_profile_->GetRequestContext()->GetURLRequestContext();
-    io_setup_complete->Signal();
   }
 
   virtual void SetUp() {
-    ui_thread_.reset(new content::TestBrowserThread(BrowserThread::UI,
-                                                    &message_loop_));
-    // Note: we're starting a real IO thread because parts of the
-    // BrowsingDataCookieHelper expect to run on that thread.
-    io_thread_.reset(new content::TestBrowserThread(BrowserThread::IO));
-    ASSERT_TRUE(io_thread_->Start());
     testing_profile_.reset(new TestingProfile());
-    base::WaitableEvent io_setup_complete(true, false);
     BrowserThread::PostTask(
         BrowserThread::IO, FROM_HERE,
         base::Bind(&BrowsingDataCookieHelperTest::SetUpOnIOThread,
-                   base::Unretained(this), &io_setup_complete));
-    io_setup_complete.Wait();
+                   base::Unretained(this)));
+    base::MessageLoop::current()->RunUntilIdle();
   }
 
   virtual void TearDown() {
     // This must be reset before the IO thread stops, because the
     // URLRequestContextGetter forces its own deletion to occur on that thread.
     testing_profile_->ResetRequestContext();
-    io_thread_.reset();
-    ui_thread_.reset();
   }
 
   void CreateCookiesForTest() {
@@ -209,9 +198,7 @@
   }
 
  protected:
-  base::MessageLoop message_loop_;
-  scoped_ptr<content::TestBrowserThread> ui_thread_;
-  scoped_ptr<content::TestBrowserThread> io_thread_;
+  content::TestBrowserThreadBundle thread_bundle_;
   scoped_ptr<TestingProfile> testing_profile_;
 
   net::CookieList cookie_list_;
diff --git a/chrome/browser/browsing_data/browsing_data_database_helper.cc b/chrome/browser/browsing_data/browsing_data_database_helper.cc
index c010e10..f41705a 100644
--- a/chrome/browser/browsing_data/browsing_data_database_helper.cc
+++ b/chrome/browser/browsing_data/browsing_data_database_helper.cc
@@ -17,25 +17,21 @@
 #include "net/base/net_errors.h"
 #include "third_party/WebKit/public/platform/WebCString.h"
 #include "third_party/WebKit/public/platform/WebString.h"
-#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
+#include "webkit/common/database/database_identifier.h"
 
 using content::BrowserContext;
 using content::BrowserThread;
-using WebKit::WebSecurityOrigin;
+using webkit_database::DatabaseIdentifier;
 
 BrowsingDataDatabaseHelper::DatabaseInfo::DatabaseInfo(
-    const std::string& host,
+    const DatabaseIdentifier& identifier,
     const std::string& database_name,
-    const std::string& origin_identifier,
     const std::string& description,
-    const std::string& origin,
     int64 size,
     base::Time last_modified)
-    : host(host),
+    : identifier(identifier),
       database_name(database_name),
-      origin_identifier(origin_identifier),
       description(description),
-      origin(origin),
       size(size),
       last_modified(last_modified) {
 }
@@ -81,11 +77,9 @@
   if (tracker_.get() && tracker_->GetAllOriginsInfo(&origins_info)) {
     for (std::vector<webkit_database::OriginInfo>::const_iterator ori =
          origins_info.begin(); ori != origins_info.end(); ++ori) {
-      WebSecurityOrigin web_security_origin =
-          WebSecurityOrigin::createFromDatabaseIdentifier(
-              WebKit::WebString::fromUTF8(ori->GetOriginIdentifier()));
-      GURL origin_url(web_security_origin.toString().utf8());
-      if (!BrowsingDataHelper::HasWebScheme(origin_url)) {
+      DatabaseIdentifier identifier =
+          DatabaseIdentifier::Parse(ori->GetOriginIdentifier());
+      if (!BrowsingDataHelper::HasWebScheme(identifier.ToOrigin())) {
         // Non-websafe state is not considered browsing data.
         continue;
       }
@@ -98,11 +92,9 @@
         base::PlatformFileInfo file_info;
         if (file_util::GetFileInfo(file_path, &file_info)) {
           database_info_.push_back(DatabaseInfo(
-                web_security_origin.host().utf8(),
+                identifier,
                 UTF16ToUTF8(*db),
-                ori->GetOriginIdentifier(),
                 UTF16ToUTF8(ori->GetDatabaseDescription(*db)),
-                origin_url.spec(),
                 file_info.size,
                 file_info.last_modified));
         }
@@ -163,7 +155,6 @@
   CannedBrowsingDataDatabaseHelper* clone =
       new CannedBrowsingDataDatabaseHelper(profile_);
 
-  base::AutoLock auto_lock(lock_);
   clone->pending_database_info_ = pending_database_info_;
   return clone;
 }
@@ -173,7 +164,6 @@
     const std::string& name,
     const std::string& description) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  base::AutoLock auto_lock(lock_);
   if (BrowsingDataHelper::HasWebScheme(origin)) {
     pending_database_info_.insert(PendingDatabaseInfo(
           origin, name, description));
@@ -181,17 +171,17 @@
 }
 
 void CannedBrowsingDataDatabaseHelper::Reset() {
-  base::AutoLock auto_lock(lock_);
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   pending_database_info_.clear();
 }
 
 bool CannedBrowsingDataDatabaseHelper::empty() const {
-  base::AutoLock auto_lock(lock_);
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   return pending_database_info_.empty();
 }
 
 size_t CannedBrowsingDataDatabaseHelper::GetDatabaseCount() const {
-  base::AutoLock auto_lock(lock_);
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   return pending_database_info_.size();
 }
 
@@ -208,32 +198,18 @@
 
   is_fetching_ = true;
   completion_callback_ = callback;
-  BrowserThread::PostTask(
-      BrowserThread::WEBKIT_DEPRECATED, FROM_HERE,
-      base::Bind(&CannedBrowsingDataDatabaseHelper::ConvertInfoInWebKitThread,
-                 this));
-}
 
-CannedBrowsingDataDatabaseHelper::~CannedBrowsingDataDatabaseHelper() {}
-
-void CannedBrowsingDataDatabaseHelper::ConvertInfoInWebKitThread() {
-  base::AutoLock auto_lock(lock_);
   database_info_.clear();
   for (std::set<PendingDatabaseInfo>::const_iterator
        info = pending_database_info_.begin();
        info != pending_database_info_.end(); ++info) {
-    WebSecurityOrigin web_security_origin =
-        WebSecurityOrigin::createFromString(
-            UTF8ToUTF16(info->origin.spec()));
-    std::string origin_identifier =
-        web_security_origin.databaseIdentifier().utf8();
+    DatabaseIdentifier identifier =
+        DatabaseIdentifier::CreateFromOrigin(info->origin);
 
     database_info_.push_back(DatabaseInfo(
-        web_security_origin.host().utf8(),
+        identifier,
         info->name,
-        origin_identifier,
         info->description,
-        web_security_origin.toString().utf8(),
         0,
         base::Time()));
   }
@@ -242,3 +218,5 @@
       BrowserThread::UI, FROM_HERE,
       base::Bind(&CannedBrowsingDataDatabaseHelper::NotifyInUIThread, this));
 }
+
+CannedBrowsingDataDatabaseHelper::~CannedBrowsingDataDatabaseHelper() {}
diff --git a/chrome/browser/browsing_data/browsing_data_database_helper.h b/chrome/browser/browsing_data/browsing_data_database_helper.h
index 155653a..963f178 100644
--- a/chrome/browser/browsing_data/browsing_data_database_helper.h
+++ b/chrome/browser/browsing_data/browsing_data_database_helper.h
@@ -14,8 +14,9 @@
 #include "base/memory/ref_counted.h"
 #include "base/synchronization/lock.h"
 #include "chrome/common/url_constants.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 #include "webkit/browser/database/database_tracker.h"
+#include "webkit/common/database/database_identifier.h"
 
 class Profile;
 
@@ -29,20 +30,16 @@
  public:
   // Contains detailed information about a web database.
   struct DatabaseInfo {
-    DatabaseInfo(const std::string& host,
+    DatabaseInfo(const webkit_database::DatabaseIdentifier& identifier,
                  const std::string& database_name,
-                 const std::string& origin_identifier,
                  const std::string& description,
-                 const std::string& origin,
                  int64 size,
                  base::Time last_modified);
     ~DatabaseInfo();
 
-    std::string host;
+    webkit_database::DatabaseIdentifier identifier;
     std::string database_name;
-    std::string origin_identifier;
     std::string description;
-    std::string origin;
     int64 size;
     base::Time last_modified;
   };
@@ -57,7 +54,7 @@
 
   // Requests a single database to be deleted in the FILE thread. This must be
   // called in the UI thread.
-  virtual void DeleteDatabase(const std::string& origin,
+  virtual void DeleteDatabase(const std::string& origin_identifier,
                               const std::string& name);
 
  protected:
@@ -149,14 +146,6 @@
  private:
   virtual ~CannedBrowsingDataDatabaseHelper();
 
-  // Converts the pending database info structs to database info structs.
-  void ConvertInfoInWebKitThread();
-
-  // Used to protect access to pending_database_info_.
-  mutable base::Lock lock_;
-
-  // Access to |pending_database_info_| is protected by |lock_| since it may
-  // be accessed on the UI or the WEBKIT thread.
   std::set<PendingDatabaseInfo> pending_database_info_;
 
   Profile* profile_;
diff --git a/chrome/browser/browsing_data/browsing_data_database_helper_browsertest.cc b/chrome/browser/browsing_data/browsing_data_database_helper_browsertest.cc
index d8a9642..ab1ea67 100644
--- a/chrome/browser/browsing_data/browsing_data_database_helper_browsertest.cc
+++ b/chrome/browser/browsing_data/browsing_data_database_helper_browsertest.cc
@@ -71,7 +71,7 @@
     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     ASSERT_EQ(1UL, database_info_list.size());
     EXPECT_EQ(std::string(kTestIdentifier1),
-              database_info_list.begin()->origin_identifier);
+              database_info_list.begin()->identifier.ToString());
     base::MessageLoop::current()->Quit();
   }
 
@@ -117,13 +117,13 @@
   ASSERT_EQ(3u, result.size());
   std::list<BrowsingDataDatabaseHelper::DatabaseInfo>::iterator info =
       result.begin();
-  EXPECT_STREQ(origin_str1, info->origin_identifier.c_str());
+  EXPECT_EQ(origin_str1, info->identifier.ToString());
   EXPECT_STREQ(db1, info->database_name.c_str());
   info++;
-  EXPECT_STREQ(origin_str1, info->origin_identifier.c_str());
+  EXPECT_EQ(origin_str1, info->identifier.ToString());
   EXPECT_STREQ(db2, info->database_name.c_str());
   info++;
-  EXPECT_STREQ(origin_str2, info->origin_identifier.c_str());
+  EXPECT_EQ(origin_str2, info->identifier.ToString());
   EXPECT_STREQ(db3, info->database_name.c_str());
 }
 
@@ -146,7 +146,7 @@
       callback.result();
 
   ASSERT_EQ(1u, result.size());
-  EXPECT_STREQ(origin_str, result.begin()->origin_identifier.c_str());
+  EXPECT_EQ(origin_str, result.begin()->identifier.ToString());
   EXPECT_STREQ(db, result.begin()->database_name.c_str());
 }
 }  // namespace
diff --git a/chrome/browser/browsing_data/browsing_data_file_system_helper.cc b/chrome/browser/browsing_data/browsing_data_file_system_helper.cc
index b86cc2f..70a7155 100644
--- a/chrome/browser/browsing_data/browsing_data_file_system_helper.cc
+++ b/chrome/browser/browsing_data/browsing_data_file_system_helper.cc
@@ -122,41 +122,40 @@
 
 void BrowsingDataFileSystemHelperImpl::FetchFileSystemInfoInFileThread() {
   DCHECK(file_task_runner()->RunsTasksOnCurrentThread());
-  scoped_ptr<fileapi::SandboxMountPointProvider::OriginEnumerator>
-      origin_enumerator(filesystem_context_->
-          sandbox_provider()->CreateOriginEnumerator());
 
-  // We don't own this pointer; it's a magic singleton generated by the
-  // profile's FileSystemContext. Deleting it would be a bad idea.
-  fileapi::FileSystemQuotaUtil* quota_util =
-     filesystem_context_->GetQuotaUtil(fileapi::kFileSystemTypeTemporary);
+  // We check usage for these filesystem types.
+  const fileapi::FileSystemType types[] = {
+    fileapi::kFileSystemTypeTemporary,
+    fileapi::kFileSystemTypePersistent,
+    fileapi::kFileSystemTypeSyncable,
+  };
 
-  GURL current;
+  typedef std::map<GURL, FileSystemInfo> OriginInfoMap;
+  OriginInfoMap file_system_info_map;
+  for (size_t i = 0; i < arraysize(types); ++i) {
+    fileapi::FileSystemType type = types[i];
+    fileapi::FileSystemQuotaUtil* quota_util =
+      filesystem_context_->GetQuotaUtil(type);
+    DCHECK(quota_util);
+    std::set<GURL> origins;
+    quota_util->GetOriginsForTypeOnFileThread(type, &origins);
+    for (std::set<GURL>::iterator iter = origins.begin();
+        iter != origins.end(); ++iter) {
+      const GURL& current = *iter;
+      if (!BrowsingDataHelper::HasWebScheme(current))
+        continue;  // Non-websafe state is not considered browsing data.
+      int64 usage = quota_util->GetOriginUsageOnFileThread(
+          filesystem_context_.get(), current, type);
+      OriginInfoMap::iterator inserted =
+          file_system_info_map.insert(
+              std::make_pair(current, FileSystemInfo(current))).first;
+      inserted->second.usage_map[type] = usage;
+    }
+  }
 
-  while (!(current = origin_enumerator->Next()).is_empty()) {
-    if (!BrowsingDataHelper::HasWebScheme(current))
-      continue;  // Non-websafe state is not considered browsing data.
-
-    // We can call these synchronous methods as we've already verified that
-    // we're running on the file task runner.
-    int64 persistent_usage = quota_util->GetOriginUsageOnFileThread(
-        filesystem_context_.get(), current, fileapi::kFileSystemTypePersistent);
-    int64 temporary_usage = quota_util->GetOriginUsageOnFileThread(
-        filesystem_context_.get(), current, fileapi::kFileSystemTypeTemporary);
-    int64 syncable_usage = quota_util->GetOriginUsageOnFileThread(
-        filesystem_context_.get(), current, fileapi::kFileSystemTypeSyncable);
-    file_system_info_.push_back(
-        FileSystemInfo(
-            current,
-            origin_enumerator->HasFileSystemType(
-                fileapi::kFileSystemTypePersistent),
-            origin_enumerator->HasFileSystemType(
-                fileapi::kFileSystemTypeTemporary),
-            origin_enumerator->HasFileSystemType(
-                fileapi::kFileSystemTypeSyncable),
-            persistent_usage,
-            temporary_usage,
-            syncable_usage));
+  for (OriginInfoMap::iterator iter = file_system_info_map.begin();
+       iter != file_system_info_map.end(); ++iter) {
+    file_system_info_.push_back(iter->second);
   }
 
   BrowserThread::PostTask(
@@ -181,21 +180,7 @@
 }  // namespace
 
 BrowsingDataFileSystemHelper::FileSystemInfo::FileSystemInfo(
-    const GURL& origin,
-    bool has_persistent,
-    bool has_temporary,
-    bool has_syncable,
-    int64 usage_persistent,
-    int64 usage_temporary,
-    int64 usage_syncable)
-    : origin(origin),
-      has_persistent(has_persistent),
-      has_temporary(has_temporary),
-      has_syncable(has_syncable),
-      usage_persistent(usage_persistent),
-      usage_temporary(usage_temporary),
-      usage_syncable(usage_syncable) {
-}
+    const GURL& origin) : origin(origin) {}
 
 BrowsingDataFileSystemHelper::FileSystemInfo::~FileSystemInfo() {}
 
@@ -240,16 +225,7 @@
        file_system != file_system_info_.end();
        ++file_system) {
     if (file_system->origin == origin) {
-      if (type == fileapi::kFileSystemTypePersistent) {
-        file_system->has_persistent = true;
-        file_system->usage_persistent = size;
-      } else if (type == fileapi::kFileSystemTypeTemporary) {
-        file_system->has_temporary = true;
-        file_system->usage_temporary = size;
-      } else {
-        file_system->has_syncable = true;
-        file_system->usage_syncable = size;
-      }
+      file_system->usage_map[type] = size;
       duplicate_origin = true;
       break;
     }
@@ -260,14 +236,9 @@
   if (!BrowsingDataHelper::HasWebScheme(origin))
     return;  // Non-websafe state is not considered browsing data.
 
-  file_system_info_.push_back(FileSystemInfo(
-      origin,
-      (type == fileapi::kFileSystemTypePersistent),
-      (type == fileapi::kFileSystemTypeTemporary),
-      (type == fileapi::kFileSystemTypeSyncable),
-      (type == fileapi::kFileSystemTypePersistent) ? size : 0,
-      (type == fileapi::kFileSystemTypeTemporary) ? size : 0,
-      (type == fileapi::kFileSystemTypeSyncable) ? size : 0));
+  FileSystemInfo info(origin);
+  info.usage_map[type] = size;
+  file_system_info_.push_back(info);
 }
 
 void CannedBrowsingDataFileSystemHelper::Reset() {
diff --git a/chrome/browser/browsing_data/browsing_data_file_system_helper.h b/chrome/browser/browsing_data/browsing_data_file_system_helper.h
index 6b5dc4a..d0c1b6f 100644
--- a/chrome/browser/browsing_data/browsing_data_file_system_helper.h
+++ b/chrome/browser/browsing_data/browsing_data_file_system_helper.h
@@ -6,6 +6,7 @@
 #define CHROME_BROWSER_BROWSING_DATA_BROWSING_DATA_FILE_SYSTEM_HELPER_H_
 
 #include <list>
+#include <map>
 #include <string>
 
 #include "base/callback.h"
@@ -14,7 +15,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/synchronization/lock.h"
 #include "chrome/common/url_constants.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 #include "webkit/common/fileapi/file_system_types.h"
 
 namespace fileapi {
@@ -43,33 +44,15 @@
     : public base::RefCountedThreadSafe<BrowsingDataFileSystemHelper> {
  public:
   // Detailed information about a file system, including it's origin GURL,
-  // the presence or absence of persistent and temporary storage, and the
-  // amount of data (in bytes) each contains.
+  // the amount of data (in bytes) for each sandboxed filesystem type.
   struct FileSystemInfo {
-    FileSystemInfo(
-        const GURL& origin,
-        bool has_persistent,
-        bool has_temporary,
-        bool has_syncable,
-        int64 usage_persistent,
-        int64 usage_temporary,
-        int64 usage_syncable);
+    FileSystemInfo(const GURL& origin);
     ~FileSystemInfo();
 
     // The origin for which the information is relevant.
     GURL origin;
-    // True if the origin has a persistent file system.
-    bool has_persistent;
-    // True if the origin has a temporary file system.
-    bool has_temporary;
-    // True if the origin has a syncable file system.
-    bool has_syncable;
-    // Persistent file system usage, in bytes.
-    int64 usage_persistent;
-    // Temporary file system usage, in bytes.
-    int64 usage_temporary;
-    // Syncable file system usage, in bytes.
-    int64 usage_syncable;
+    // FileSystemType to usage (in bytes) map.
+    std::map<fileapi::FileSystemType, int64> usage_map;
   };
 
   // Creates a BrowsingDataFileSystemHelper instance for the file systems
diff --git a/chrome/browser/browsing_data/browsing_data_file_system_helper_unittest.cc b/chrome/browser/browsing_data/browsing_data_file_system_helper_unittest.cc
index ad756e4..3ac40a5 100644
--- a/chrome/browser/browsing_data/browsing_data_file_system_helper_unittest.cc
+++ b/chrome/browser/browsing_data/browsing_data_file_system_helper_unittest.cc
@@ -9,15 +9,16 @@
 #include "base/file_util.h"
 #include "base/message_loop.h"
 #include "base/platform_file.h"
+#include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/browsing_data/browsing_data_file_system_helper.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/browser/storage_partition.h"
 #include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "webkit/browser/fileapi/file_system_context.h"
 #include "webkit/browser/fileapi/file_system_url.h"
 #include "webkit/browser/fileapi/file_system_usage_cache.h"
-#include "webkit/browser/fileapi/sandbox_mount_point_provider.h"
 #include "webkit/common/fileapi/file_system_types.h"
 
 using content::BrowserContext;
@@ -62,26 +63,19 @@
 // point.
 class BrowsingDataFileSystemHelperTest : public testing::Test {
  public:
-  BrowsingDataFileSystemHelperTest()
-      : ui_thread_(BrowserThread::UI, &message_loop_),
-        db_thread_(BrowserThread::DB, &message_loop_),
-        webkit_thread_(BrowserThread::WEBKIT_DEPRECATED, &message_loop_),
-        file_thread_(BrowserThread::FILE, &message_loop_),
-        file_user_blocking_thread_(
-            BrowserThread::FILE_USER_BLOCKING, &message_loop_),
-        io_thread_(BrowserThread::IO, &message_loop_) {
+  BrowsingDataFileSystemHelperTest() {
     profile_.reset(new TestingProfile());
 
     helper_ = BrowsingDataFileSystemHelper::Create(
         BrowserContext::GetDefaultStoragePartition(profile_.get())->
             GetFileSystemContext());
-    message_loop_.RunUntilIdle();
+    base::MessageLoop::current()->RunUntilIdle();
     canned_helper_ = new CannedBrowsingDataFileSystemHelper(profile_.get());
   }
   virtual ~BrowsingDataFileSystemHelperTest() {
     // Avoid memory leaks.
     profile_.reset();
-    message_loop_.RunUntilIdle();
+    base::MessageLoop::current()->RunUntilIdle();
   }
 
   TestingProfile* GetProfile() {
@@ -100,26 +94,36 @@
   }
 
   // Callback that should be executed in response to
-  // fileapi::SandboxMountPointProvider::OpenFileSystem.
-  void OpenFileSystemCallback(base::PlatformFileError error) {
+  // fileapi::FileSystemContext::OpenFileSystem.
+  void OpenFileSystemCallback(base::PlatformFileError error,
+                              const std::string& name,
+                              const GURL& root) {
     open_file_system_result_ = error;
     Notify();
   }
 
-  // Calls fileapi::SandboxMountPointProvider::OpenFileSystem
+  bool OpenFileSystem(const GURL& origin,
+                      fileapi::FileSystemType type,
+                      fileapi::OpenFileSystemMode open_mode) {
+    BrowserContext::GetDefaultStoragePartition(profile_.get())->
+        GetFileSystemContext()->OpenFileSystem(
+            origin, type, open_mode,
+            base::Bind(
+                &BrowsingDataFileSystemHelperTest::OpenFileSystemCallback,
+                base::Unretained(this)));
+    BlockUntilNotified();
+    return open_file_system_result_ == base::PLATFORM_FILE_OK;
+  }
+
+  // Calls fileapi::FileSystemContext::OpenFileSystem with
+  // OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT flag
   // to verify the existence of a file system for a specified type and origin,
   // blocks until a response is available, then returns the result
   // synchronously to it's caller.
   bool FileSystemContainsOriginAndType(const GURL& origin,
                                        fileapi::FileSystemType type) {
-    sandbox_->OpenFileSystem(
-        origin, type,
-        fileapi::OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT,
-        base::Bind(
-            &BrowsingDataFileSystemHelperTest::OpenFileSystemCallback,
-            base::Unretained(this)));
-    BlockUntilNotified();
-    return open_file_system_result_ == base::PLATFORM_FILE_OK;
+    return OpenFileSystem(origin, type,
+                          fileapi::OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT);
   }
 
   // Callback that should be executed in response to StartFetching(), and stores
@@ -154,9 +158,6 @@
   // Sets up kOrigin1 with a temporary file system, kOrigin2 with a persistent
   // file system, and kOrigin3 with both.
   virtual void PopulateTestFileSystemData() {
-    sandbox_ = BrowserContext::GetDefaultStoragePartition(profile_.get())->
-        GetFileSystemContext()->sandbox_provider();
-
     CreateDirectoryForOriginAndType(kOrigin1, kTemporary);
     CreateDirectoryForOriginAndType(kOrigin2, kPersistent);
     CreateDirectoryForOriginAndType(kOrigin3, kTemporary);
@@ -170,13 +171,13 @@
     EXPECT_TRUE(FileSystemContainsOriginAndType(kOrigin3, kTemporary));
   }
 
-  // Uses the fileapi methods to create a filesystem of a given type for a
-  // specified origin.
+  // Calls OpenFileSystem with OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT
+  // to create a filesystem of a given type for a specified origin.
   void CreateDirectoryForOriginAndType(const GURL& origin,
                                        fileapi::FileSystemType type) {
-    base::FilePath target = sandbox_->GetBaseDirectoryForOriginAndType(
-        origin, type, true /* create */);
-    EXPECT_TRUE(file_util::DirectoryExists(target));
+    OpenFileSystem(origin, type,
+                   fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT);
+    EXPECT_EQ(base::PLATFORM_FILE_OK, open_file_system_result_);
   }
 
   // Returns a list of the FileSystemInfo objects gathered in the most recent
@@ -186,16 +187,7 @@
   }
 
  protected:
-  // message_loop_, as well as all the threads associated with it must be
-  // defined before profile_ to prevent explosions. The threads also must be
-  // defined in the order they're listed here. Oh how I love C++.
-  base::MessageLoopForUI message_loop_;
-  content::TestBrowserThread ui_thread_;
-  content::TestBrowserThread db_thread_;
-  content::TestBrowserThread webkit_thread_;
-  content::TestBrowserThread file_thread_;
-  content::TestBrowserThread file_user_blocking_thread_;
-  content::TestBrowserThread io_thread_;
+  content::TestBrowserThreadBundle thread_bundle_;
   scoped_ptr<TestingProfile> profile_;
 
   // Temporary storage to pass information back from callbacks.
@@ -205,9 +197,6 @@
   scoped_refptr<BrowsingDataFileSystemHelper> helper_;
   scoped_refptr<CannedBrowsingDataFileSystemHelper> canned_helper_;
 
-  // We don't own this pointer: don't delete it.
-  fileapi::SandboxMountPointProvider* sandbox_;
-
   DISALLOW_COPY_AND_ASSIGN(BrowsingDataFileSystemHelperTest);
 };
 
@@ -226,28 +215,27 @@
        file_system_info_list_->begin(); info != file_system_info_list_->end();
        ++info) {
     if (info->origin == kOrigin1) {
-        EXPECT_FALSE(test_hosts_found[0]);
-        test_hosts_found[0] = true;
-        EXPECT_FALSE(info->has_persistent);
-        EXPECT_TRUE(info->has_temporary);
-        EXPECT_EQ(0, info->usage_persistent);
-        EXPECT_EQ(kEmptyFileSystemSize, info->usage_temporary);
+      EXPECT_FALSE(test_hosts_found[0]);
+      test_hosts_found[0] = true;
+      EXPECT_FALSE(ContainsKey(info->usage_map, kPersistent));
+      EXPECT_TRUE(ContainsKey(info->usage_map, kTemporary));
+      EXPECT_EQ(kEmptyFileSystemSize,
+                info->usage_map[fileapi::kFileSystemTypeTemporary]);
     } else if (info->origin == kOrigin2) {
-        EXPECT_FALSE(test_hosts_found[1]);
-        test_hosts_found[1] = true;
-        EXPECT_TRUE(info->has_persistent);
-        EXPECT_FALSE(info->has_temporary);
-        EXPECT_EQ(kEmptyFileSystemSize, info->usage_persistent);
-        EXPECT_EQ(0, info->usage_temporary);
+      EXPECT_FALSE(test_hosts_found[1]);
+      test_hosts_found[1] = true;
+      EXPECT_TRUE(ContainsKey(info->usage_map, kPersistent));
+      EXPECT_FALSE(ContainsKey(info->usage_map, kTemporary));
+      EXPECT_EQ(kEmptyFileSystemSize, info->usage_map[kPersistent]);
     } else if (info->origin == kOrigin3) {
-        EXPECT_FALSE(test_hosts_found[2]);
-        test_hosts_found[2] = true;
-        EXPECT_TRUE(info->has_persistent);
-        EXPECT_TRUE(info->has_temporary);
-        EXPECT_EQ(kEmptyFileSystemSize, info->usage_persistent);
-        EXPECT_EQ(kEmptyFileSystemSize, info->usage_temporary);
+      EXPECT_FALSE(test_hosts_found[2]);
+      test_hosts_found[2] = true;
+      EXPECT_TRUE(ContainsKey(info->usage_map, kPersistent));
+      EXPECT_TRUE(ContainsKey(info->usage_map, kTemporary));
+      EXPECT_EQ(kEmptyFileSystemSize, info->usage_map[kPersistent]);
+      EXPECT_EQ(kEmptyFileSystemSize, info->usage_map[kTemporary]);
     } else {
-        ADD_FAILURE() << info->origin.spec() << " isn't an origin we added.";
+      ADD_FAILURE() << info->origin.spec() << " isn't an origin we added.";
     }
   }
   for (size_t i = 0; i < arraysize(test_hosts_found); i++) {
@@ -269,10 +257,10 @@
   BrowsingDataFileSystemHelper::FileSystemInfo info =
       *(file_system_info_list_->begin());
   EXPECT_EQ(kOrigin3, info.origin);
-  EXPECT_TRUE(info.has_persistent);
-  EXPECT_TRUE(info.has_temporary);
-  EXPECT_EQ(kEmptyFileSystemSize, info.usage_persistent);
-  EXPECT_EQ(kEmptyFileSystemSize, info.usage_temporary);
+  EXPECT_TRUE(ContainsKey(info.usage_map, kPersistent));
+  EXPECT_TRUE(ContainsKey(info.usage_map, kTemporary));
+  EXPECT_EQ(kEmptyFileSystemSize, info.usage_map[kPersistent]);
+  EXPECT_EQ(kEmptyFileSystemSize, info.usage_map[kTemporary]);
 }
 
 // Verifies that the CannedBrowsingDataFileSystemHelper correctly reports
@@ -297,17 +285,15 @@
   std::list<BrowsingDataFileSystemHelper::FileSystemInfo>::iterator info =
       file_system_info_list_->begin();
   EXPECT_EQ(kOrigin1, info->origin);
-  EXPECT_TRUE(info->has_persistent);
-  EXPECT_FALSE(info->has_temporary);
-  EXPECT_EQ(200, info->usage_persistent);
-  EXPECT_EQ(0, info->usage_temporary);
+  EXPECT_TRUE(ContainsKey(info->usage_map, kPersistent));
+  EXPECT_FALSE(ContainsKey(info->usage_map, kTemporary));
+  EXPECT_EQ(200, info->usage_map[kPersistent]);
 
   info++;
   EXPECT_EQ(kOrigin2, info->origin);
-  EXPECT_FALSE(info->has_persistent);
-  EXPECT_TRUE(info->has_temporary);
-  EXPECT_EQ(0, info->usage_persistent);
-  EXPECT_EQ(100, info->usage_temporary);
+  EXPECT_FALSE(ContainsKey(info->usage_map, kPersistent));
+  EXPECT_TRUE(ContainsKey(info->usage_map, kTemporary));
+  EXPECT_EQ(100, info->usage_map[kTemporary]);
 }
 
 // Verifies that the CannedBrowsingDataFileSystemHelper correctly ignores
diff --git a/chrome/browser/browsing_data/browsing_data_helper.cc b/chrome/browser/browsing_data/browsing_data_helper.cc
index 5a50ff0..0faf856 100644
--- a/chrome/browser/browsing_data/browsing_data_helper.cc
+++ b/chrome/browser/browsing_data/browsing_data_helper.cc
@@ -11,8 +11,8 @@
 #include "chrome/common/url_constants.h"
 #include "content/public/browser/child_process_security_policy.h"
 #include "extensions/common/constants.h"
-#include "googleurl/src/gurl.h"
 #include "third_party/WebKit/public/platform/WebString.h"
+#include "url/gurl.h"
 
 // Static
 bool BrowsingDataHelper::IsWebScheme(const std::string& scheme) {
diff --git a/chrome/browser/browsing_data/browsing_data_helper_unittest.cc b/chrome/browser/browsing_data/browsing_data_helper_unittest.cc
index fe3b476..e19b81a 100644
--- a/chrome/browser/browsing_data/browsing_data_helper_unittest.cc
+++ b/chrome/browser/browsing_data/browsing_data_helper_unittest.cc
@@ -9,9 +9,9 @@
 #include "chrome/common/url_constants.h"
 #include "content/public/common/url_constants.h"
 #include "extensions/common/constants.h"
-#include "googleurl/src/gurl.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/WebKit/public/platform/WebString.h"
+#include "url/gurl.h"
 
 namespace {
 
diff --git a/chrome/browser/browsing_data/browsing_data_indexed_db_helper.cc b/chrome/browser/browsing_data/browsing_data_indexed_db_helper.cc
index b517ee6..59e3625 100644
--- a/chrome/browser/browsing_data/browsing_data_indexed_db_helper.cc
+++ b/chrome/browser/browsing_data/browsing_data_indexed_db_helper.cc
@@ -16,12 +16,10 @@
 #include "chrome/browser/browsing_data/browsing_data_helper.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/indexed_db_context.h"
-#include "webkit/browser/database/database_util.h"
 
 using content::BrowserThread;
 using content::IndexedDBContext;
 using content::IndexedDBInfo;
-using webkit_database::DatabaseUtil;
 
 namespace {
 
@@ -38,12 +36,12 @@
  private:
   virtual ~BrowsingDataIndexedDBHelperImpl();
 
-  // Enumerates all indexed database files in the WEBKIT thread.
-  void FetchIndexedDBInfoInWebKitThread();
+  // Enumerates all indexed database files in the IndexedDB thread.
+  void FetchIndexedDBInfoInIndexedDBThread();
   // Notifies the completion callback in the UI thread.
   void NotifyInUIThread();
-  // Delete a single indexed database in the WEBKIT thread.
-  void DeleteIndexedDBInWebKitThread(const GURL& origin);
+  // Delete a single indexed database in the IndexedDB thread.
+  void DeleteIndexedDBInIndexedDBThread(const GURL& origin);
 
   scoped_refptr<IndexedDBContext> indexed_db_context_;
 
@@ -52,7 +50,7 @@
   // while |is_fetching_| is true. The flag |is_fetching_| is only accessed on
   // the UI thread.
   // In the context of this class |indexed_db_info_| is only accessed on the
-  // WEBKIT thread.
+  // context's IndexedDB thread.
   std::list<IndexedDBInfo> indexed_db_info_;
 
   // This only mutates on the UI thread.
@@ -85,25 +83,26 @@
 
   is_fetching_ = true;
   completion_callback_ = callback;
-  BrowserThread::PostTask(
-      BrowserThread::WEBKIT_DEPRECATED, FROM_HERE,
+  indexed_db_context_->TaskRunner()->PostTask(
+      FROM_HERE,
       base::Bind(
-          &BrowsingDataIndexedDBHelperImpl::FetchIndexedDBInfoInWebKitThread,
+          &BrowsingDataIndexedDBHelperImpl::FetchIndexedDBInfoInIndexedDBThread,
           this));
 }
 
 void BrowsingDataIndexedDBHelperImpl::DeleteIndexedDB(
     const GURL& origin) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  BrowserThread::PostTask(
-      BrowserThread::WEBKIT_DEPRECATED, FROM_HERE,
+  indexed_db_context_->TaskRunner()->PostTask(
+      FROM_HERE,
       base::Bind(
-          &BrowsingDataIndexedDBHelperImpl::DeleteIndexedDBInWebKitThread, this,
+          &BrowsingDataIndexedDBHelperImpl::DeleteIndexedDBInIndexedDBThread,
+          this,
           origin));
 }
 
-void BrowsingDataIndexedDBHelperImpl::FetchIndexedDBInfoInWebKitThread() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED));
+void BrowsingDataIndexedDBHelperImpl::FetchIndexedDBInfoInIndexedDBThread() {
+  DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
   std::vector<IndexedDBInfo> origins = indexed_db_context_->GetAllOriginsInfo();
   for (std::vector<IndexedDBInfo>::const_iterator iter = origins.begin();
        iter != origins.end(); ++iter) {
@@ -127,9 +126,9 @@
   is_fetching_ = false;
 }
 
-void BrowsingDataIndexedDBHelperImpl::DeleteIndexedDBInWebKitThread(
+void BrowsingDataIndexedDBHelperImpl::DeleteIndexedDBInIndexedDBThread(
     const GURL& origin) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED));
+  DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
   indexed_db_context_->DeleteForOrigin(origin);
 }
 
@@ -171,7 +170,6 @@
   CannedBrowsingDataIndexedDBHelper* clone =
       new CannedBrowsingDataIndexedDBHelper();
 
-  base::AutoLock auto_lock(lock_);
   clone->pending_indexed_db_info_ = pending_indexed_db_info_;
   clone->indexed_db_info_ = indexed_db_info_;
   return clone;
@@ -182,29 +180,24 @@
   if (!BrowsingDataHelper::HasWebScheme(origin))
     return;  // Non-websafe state is not considered browsing data.
 
-  base::AutoLock auto_lock(lock_);
   pending_indexed_db_info_.insert(PendingIndexedDBInfo(origin, name));
 }
 
 void CannedBrowsingDataIndexedDBHelper::Reset() {
-  base::AutoLock auto_lock(lock_);
   indexed_db_info_.clear();
   pending_indexed_db_info_.clear();
 }
 
 bool CannedBrowsingDataIndexedDBHelper::empty() const {
-  base::AutoLock auto_lock(lock_);
   return indexed_db_info_.empty() && pending_indexed_db_info_.empty();
 }
 
 size_t CannedBrowsingDataIndexedDBHelper::GetIndexedDBCount() const {
-  base::AutoLock auto_lock(lock_);
   return pending_indexed_db_info_.size();
 }
 
 const std::set<CannedBrowsingDataIndexedDBHelper::PendingIndexedDBInfo>&
 CannedBrowsingDataIndexedDBHelper::GetIndexedDBInfo() const  {
-  base::AutoLock auto_lock(lock_);
   return pending_indexed_db_info_;
 }
 
@@ -216,15 +209,17 @@
 
   is_fetching_ = true;
   completion_callback_ = callback;
-  BrowserThread::PostTask(
-      BrowserThread::WEBKIT_DEPRECATED, FROM_HERE,
-      base::Bind(
-          &CannedBrowsingDataIndexedDBHelper::ConvertPendingInfoInWebKitThread,
-          this));
+
+  // We post a task to emulate async fetching behavior.
+  base::MessageLoop::current()->PostTask(
+      FROM_HERE,
+      base::Bind(&CannedBrowsingDataIndexedDBHelper::
+                     ConvertPendingInfo,
+                 this));
 }
 
-void CannedBrowsingDataIndexedDBHelper::ConvertPendingInfoInWebKitThread() {
-  base::AutoLock auto_lock(lock_);
+void CannedBrowsingDataIndexedDBHelper::ConvertPendingInfo() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   indexed_db_info_.clear();
   for (std::set<PendingIndexedDBInfo>::const_iterator
        pending_info = pending_indexed_db_info_.begin();
@@ -233,15 +228,6 @@
     indexed_db_info_.push_back(info);
   }
 
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      base::Bind(&CannedBrowsingDataIndexedDBHelper::NotifyInUIThread, this));
-}
-
-void CannedBrowsingDataIndexedDBHelper::NotifyInUIThread() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  DCHECK(is_fetching_);
-
   completion_callback_.Run(indexed_db_info_);
   completion_callback_.Reset();
   is_fetching_ = false;
diff --git a/chrome/browser/browsing_data/browsing_data_indexed_db_helper.h b/chrome/browser/browsing_data/browsing_data_indexed_db_helper.h
index ee4e76f..bdcd036 100644
--- a/chrome/browser/browsing_data/browsing_data_indexed_db_helper.h
+++ b/chrome/browser/browsing_data/browsing_data_indexed_db_helper.h
@@ -14,9 +14,9 @@
 #include "base/files/file_path.h"
 #include "base/memory/ref_counted.h"
 #include "base/synchronization/lock.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "content/public/browser/indexed_db_context.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 class Profile;
 
@@ -39,7 +39,7 @@
   virtual void StartFetching(
       const base::Callback<void(const std::list<content::IndexedDBInfo>&)>&
           callback) = 0;
-  // Requests a single indexed database to be deleted in the WEBKIT thread.
+  // Requests a single indexed database to be deleted in the IndexedDB thread.
   virtual void DeleteIndexedDB(const GURL& origin) = 0;
 
  protected:
@@ -100,15 +100,8 @@
   virtual ~CannedBrowsingDataIndexedDBHelper();
 
   // Convert the pending indexed db info to indexed db info objects.
-  void ConvertPendingInfoInWebKitThread();
+  void ConvertPendingInfo();
 
-  void NotifyInUIThread();
-
-  // Lock to protect access to pending_indexed_db_info_;
-  mutable base::Lock lock_;
-
-  // Access to |pending_indexed_db_info_| is protected by |lock_| since it can
-  // be accessed on the UI and on the WEBKIT thread.
   std::set<PendingIndexedDBInfo> pending_indexed_db_info_;
 
   // Access to |indexed_db_info_| is triggered indirectly via the UI thread and
diff --git a/chrome/browser/browsing_data/browsing_data_local_storage_helper.h b/chrome/browser/browsing_data/browsing_data_local_storage_helper.h
index c41c7a7..80c55fd 100644
--- a/chrome/browser/browsing_data/browsing_data_local_storage_helper.h
+++ b/chrome/browser/browsing_data/browsing_data_local_storage_helper.h
@@ -14,10 +14,10 @@
 #include "base/files/file_path.h"
 #include "base/memory/ref_counted.h"
 #include "base/synchronization/lock.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/common/url_constants.h"
 #include "content/public/browser/dom_storage_context.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 class Profile;
 
diff --git a/chrome/browser/browsing_data/browsing_data_quota_helper_unittest.cc b/chrome/browser/browsing_data/browsing_data_quota_helper_unittest.cc
index ce0b511..095c631 100644
--- a/chrome/browser/browsing_data/browsing_data_quota_helper_unittest.cc
+++ b/chrome/browser/browsing_data/browsing_data_quota_helper_unittest.cc
@@ -8,10 +8,10 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/memory/weak_ptr.h"
 #include "base/message_loop.h"
-#include "base/message_loop.h"
 #include "base/message_loop/message_loop_proxy.h"
 #include "chrome/browser/browsing_data/browsing_data_quota_helper_impl.h"
 #include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "webkit/browser/quota/mock_storage_client.h"
 #include "webkit/browser/quota/quota_manager.h"
 
@@ -23,10 +23,7 @@
   typedef BrowsingDataQuotaHelper::QuotaInfoArray QuotaInfoArray;
 
   BrowsingDataQuotaHelperTest()
-      : ui_thread_(BrowserThread::UI, &message_loop_),
-        db_thread_(BrowserThread::DB, &message_loop_),
-        io_thread_(BrowserThread::IO, &message_loop_),
-        fetching_completed_(true),
+      : fetching_completed_(true),
         quota_(-1),
         weak_factory_(this) {}
 
@@ -114,10 +111,7 @@
     fetching_completed_ = true;
   }
 
-  base::MessageLoop message_loop_;
-  content::TestBrowserThread ui_thread_;
-  content::TestBrowserThread db_thread_;
-  content::TestBrowserThread io_thread_;
+  content::TestBrowserThreadBundle thread_bundle_;
   scoped_refptr<quota::QuotaManager> quota_manager_;
 
   base::ScopedTempDir dir_;
diff --git a/chrome/browser/browsing_data/browsing_data_remover.cc b/chrome/browser/browsing_data/browsing_data_remover.cc
index e0799e1..27e6eed 100644
--- a/chrome/browser/browsing_data/browsing_data_remover.cc
+++ b/chrome/browser/browsing_data/browsing_data_remover.cc
@@ -45,8 +45,8 @@
 #include "chrome/common/chrome_notification_types.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
-#include "components/autofill/browser/personal_data_manager.h"
-#include "components/autofill/browser/webdata/autofill_webdata_service.h"
+#include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/dom_storage_context.h"
 #include "content/public/browser/download_manager.h"
diff --git a/chrome/browser/browsing_data/browsing_data_remover.h b/chrome/browser/browsing_data/browsing_data_remover.h
index 9eb1597..e75735e 100644
--- a/chrome/browser/browsing_data/browsing_data_remover.h
+++ b/chrome/browser/browsing_data/browsing_data_remover.h
@@ -13,13 +13,13 @@
 #include "base/prefs/pref_member.h"
 #include "base/sequenced_task_runner_helpers.h"
 #include "base/synchronization/waitable_event_watcher.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/pepper_flash_settings_manager.h"
 #include "chrome/common/cancelable_task_tracker.h"
 #include "content/public/browser/dom_storage_context.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 #include "webkit/common/quota/quota_types.h"
 
 class ExtensionSpecialStoragePolicy;
diff --git a/chrome/browser/browsing_data/browsing_data_remover_unittest.cc b/chrome/browser/browsing_data/browsing_data_remover_unittest.cc
index 11021fc..43cce41 100644
--- a/chrome/browser/browsing_data/browsing_data_remover_unittest.cc
+++ b/chrome/browser/browsing_data/browsing_data_remover_unittest.cc
@@ -26,15 +26,16 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/autofill/browser/autofill_common_test.h"
-#include "components/autofill/browser/autofill_profile.h"
-#include "components/autofill/browser/credit_card.h"
-#include "components/autofill/browser/personal_data_manager.h"
-#include "components/autofill/browser/personal_data_manager_observer.h"
+#include "components/autofill/core/browser/autofill_common_test.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/credit_card.h"
+#include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/autofill/core/browser/personal_data_manager_observer.h"
 #include "content/public/browser/dom_storage_context.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/storage_partition.h"
 #include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "net/cookies/cookie_monster.h"
 #include "net/ssl/server_bound_cert_service.h"
 #include "net/ssl/server_bound_cert_store.h"
@@ -542,14 +543,7 @@
                                 public content::NotificationObserver {
  public:
   BrowsingDataRemoverTest()
-      : ui_thread_(BrowserThread::UI, &message_loop_),
-        db_thread_(BrowserThread::DB, &message_loop_),
-        webkit_thread_(BrowserThread::WEBKIT_DEPRECATED, &message_loop_),
-        file_thread_(BrowserThread::FILE, &message_loop_),
-        file_user_blocking_thread_(
-            BrowserThread::FILE_USER_BLOCKING, &message_loop_),
-        io_thread_(BrowserThread::IO, &message_loop_),
-        profile_(new TestingProfile()) {
+      : profile_(new TestingProfile()) {
     registrar_.Add(this, chrome::NOTIFICATION_BROWSING_DATA_REMOVED,
                    content::Source<Profile>(profile_.get()));
   }
@@ -564,7 +558,7 @@
     // the message loop is cleared out, before destroying the threads and loop.
     // Otherwise we leak memory.
     profile_.reset();
-    message_loop_.RunUntilIdle();
+    base::MessageLoop::current()->RunUntilIdle();
   }
 
   void BlockUntilBrowsingDataRemoved(BrowsingDataRemover::TimePeriod period,
@@ -652,15 +646,7 @@
   scoped_ptr<BrowsingDataRemover::NotificationDetails> called_with_details_;
   content::NotificationRegistrar registrar_;
 
-  // message_loop_, as well as all the threads associated with it must be
-  // defined before profile_ to prevent explosions. Oh how I love C++.
-  base::MessageLoopForUI message_loop_;
-  content::TestBrowserThread ui_thread_;
-  content::TestBrowserThread db_thread_;
-  content::TestBrowserThread webkit_thread_;
-  content::TestBrowserThread file_thread_;
-  content::TestBrowserThread file_user_blocking_thread_;
-  content::TestBrowserThread io_thread_;
+  content::TestBrowserThreadBundle thread_bundle_;
   scoped_ptr<TestingProfile> profile_;
   scoped_refptr<quota::MockQuotaManager> quota_manager_;
 
diff --git a/chrome/browser/browsing_data/cookies_tree_model.cc b/chrome/browser/browsing_data/cookies_tree_model.cc
index dcb4b25..58abc27 100644
--- a/chrome/browser/browsing_data/cookies_tree_model.cc
+++ b/chrome/browser/browsing_data/cookies_tree_model.cc
@@ -189,7 +189,7 @@
     const BrowsingDataDatabaseHelper::DatabaseInfo* database_info) {
   Init(TYPE_DATABASE);
   this->database_info = database_info;
-  origin = GURL(database_info->origin);
+  origin = database_info->identifier.ToOrigin();
   return *this;
 }
 
@@ -342,7 +342,7 @@
 
   if (container) {
     container->database_helper_->DeleteDatabase(
-        database_info_->origin_identifier, database_info_->database_name);
+        database_info_->identifier.ToString(), database_info_->database_name);
     container->database_info_list_.erase(database_info_);
   }
 }
@@ -1113,7 +1113,7 @@
            container->database_info_list_.begin();
        database_info != container->database_info_list_.end();
        ++database_info) {
-    GURL origin(database_info->origin);
+    GURL origin(database_info->identifier.ToOrigin());
 
     if (!filter.size() ||
         (CookieTreeHostNode::TitleForUrl(origin).find(filter) !=
diff --git a/chrome/browser/browsing_data/cookies_tree_model_unittest.cc b/chrome/browser/browsing_data/cookies_tree_model_unittest.cc
index 07fd27b..531b540 100644
--- a/chrome/browser/browsing_data/cookies_tree_model_unittest.cc
+++ b/chrome/browser/browsing_data/cookies_tree_model_unittest.cc
@@ -24,7 +24,7 @@
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_types.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -38,17 +38,11 @@
 
 class CookiesTreeModelTest : public testing::Test {
  public:
-  CookiesTreeModelTest()
-      : ui_thread_(BrowserThread::UI, &message_loop_),
-        file_user_blocking_(BrowserThread::FILE_USER_BLOCKING, &message_loop_),
-        io_thread_(BrowserThread::IO, &message_loop_) {
-  }
-
   virtual ~CookiesTreeModelTest() {
     // Avoid memory leaks.
     special_storage_policy_ = NULL;
     profile_.reset();
-    message_loop_.RunUntilIdle();
+    base::MessageLoop::current()->RunUntilIdle();
   }
 
   virtual void SetUp() OVERRIDE {
@@ -92,7 +86,7 @@
     mock_browsing_data_local_storage_helper_ = NULL;
     mock_browsing_data_database_helper_ = NULL;
     mock_browsing_data_flash_lso_helper_ = NULL;
-    message_loop_.RunUntilIdle();
+    base::MessageLoop::current()->RunUntilIdle();
   }
 
   scoped_ptr<CookiesTreeModel> CreateCookiesTreeModelWithInitialSample() {
@@ -339,11 +333,7 @@
   }
 
  protected:
-  base::MessageLoop message_loop_;
-  content::TestBrowserThread ui_thread_;
-  content::TestBrowserThread file_user_blocking_;
-  content::TestBrowserThread io_thread_;
-
+  content::TestBrowserThreadBundle thread_bundle_;
   scoped_ptr<TestingProfile> profile_;
   scoped_refptr<MockBrowsingDataCookieHelper>
       mock_browsing_data_cookie_helper_;
diff --git a/chrome/browser/browsing_data/mock_browsing_data_database_helper.cc b/chrome/browser/browsing_data/mock_browsing_data_database_helper.cc
index b6fbdb5..3db7ca9 100644
--- a/chrome/browser/browsing_data/mock_browsing_data_database_helper.cc
+++ b/chrome/browser/browsing_data/mock_browsing_data_database_helper.cc
@@ -30,13 +30,15 @@
 }
 
 void MockBrowsingDataDatabaseHelper::AddDatabaseSamples() {
+  webkit_database::DatabaseIdentifier id1 =
+      webkit_database::DatabaseIdentifier::Parse("http_gdbhost1_1");
   response_.push_back(BrowsingDataDatabaseHelper::DatabaseInfo(
-      "gdbhost1", "db1", "http_gdbhost1_1", "description 1",
-      "http://gdbhost1:1/", 1, base::Time()));
+      id1, "db1", "description 1", 1, base::Time()));
   databases_["http_gdbhost1_1:db1"] = true;
+  webkit_database::DatabaseIdentifier id2 =
+      webkit_database::DatabaseIdentifier::Parse("http_gdbhost2_2");
   response_.push_back(BrowsingDataDatabaseHelper::DatabaseInfo(
-      "gdbhost2", "db2", "http_gdbhost2_2", "description 2",
-      "http://gdbhost2:2/", 2, base::Time()));
+      id2, "db2", "description 2", 2, base::Time()));
   databases_["http_gdbhost2_2:db2"] = true;
 }
 
diff --git a/chrome/browser/browsing_data/mock_browsing_data_file_system_helper.cc b/chrome/browser/browsing_data/mock_browsing_data_file_system_helper.cc
index e650c48..26d8185 100644
--- a/chrome/browser/browsing_data/mock_browsing_data_file_system_helper.cc
+++ b/chrome/browser/browsing_data/mock_browsing_data_file_system_helper.cc
@@ -29,8 +29,14 @@
 void MockBrowsingDataFileSystemHelper::AddFileSystem(
     const GURL& origin, bool has_persistent, bool has_temporary,
     bool has_syncable) {
-  response_.push_back(BrowsingDataFileSystemHelper::FileSystemInfo(
-      origin, has_persistent, has_temporary, has_syncable, 0, 0, 0));
+  BrowsingDataFileSystemHelper::FileSystemInfo info(origin);
+  if (has_persistent)
+    info.usage_map[fileapi::kFileSystemTypePersistent] = 0;
+  if (has_temporary)
+    info.usage_map[fileapi::kFileSystemTypeTemporary] = 0;
+  if (has_syncable)
+    info.usage_map[fileapi::kFileSystemTypeSyncable] = 0;
+  response_.push_back(info);
   file_systems_[origin.spec()] = true;
 }
 
diff --git a/chrome/browser/captive_portal/captive_portal_detector.h b/chrome/browser/captive_portal/captive_portal_detector.h
index 7ecda27..162ae6e 100644
--- a/chrome/browser/captive_portal/captive_portal_detector.h
+++ b/chrome/browser/captive_portal/captive_portal_detector.h
@@ -11,7 +11,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/threading/non_thread_safe.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "net/url_request/url_fetcher.h"
 #include "net/url_request/url_fetcher_delegate.h"
 #include "net/url_request/url_request_context_getter.h"
diff --git a/chrome/browser/captive_portal/captive_portal_detector_unittest.cc b/chrome/browser/captive_portal/captive_portal_detector_unittest.cc
index c0c1806..44f4b3e 100644
--- a/chrome/browser/captive_portal/captive_portal_detector_unittest.cc
+++ b/chrome/browser/captive_portal/captive_portal_detector_unittest.cc
@@ -7,13 +7,13 @@
 #include "base/basictypes.h"
 #include "base/bind.h"
 #include "base/message_loop.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/captive_portal/testing_utils.h"
 #include "chrome/test/base/testing_profile.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/net_errors.h"
 #include "net/url_request/url_fetcher.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 namespace captive_portal {
 
diff --git a/chrome/browser/captive_portal/captive_portal_service.h b/chrome/browser/captive_portal/captive_portal_service.h
index f9c5b4a..c8b5970 100644
--- a/chrome/browser/captive_portal/captive_portal_service.h
+++ b/chrome/browser/captive_portal/captive_portal_service.h
@@ -9,12 +9,12 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/prefs/pref_member.h"
 #include "base/threading/non_thread_safe.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/captive_portal/captive_portal_detector.h"
 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/backoff_entry.h"
+#include "url/gurl.h"
 
 class Profile;
 
diff --git a/chrome/browser/captive_portal/captive_portal_tab_reloader.h b/chrome/browser/captive_portal/captive_portal_tab_reloader.h
index 212f520..83a7686 100644
--- a/chrome/browser/captive_portal/captive_portal_tab_reloader.h
+++ b/chrome/browser/captive_portal/captive_portal_tab_reloader.h
@@ -9,8 +9,8 @@
 #include "base/callback_forward.h"
 #include "base/compiler_specific.h"
 #include "base/memory/weak_ptr.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/captive_portal/captive_portal_service.h"
 
 class Profile;
diff --git a/chrome/browser/captive_portal/captive_portal_tab_reloader_unittest.cc b/chrome/browser/captive_portal/captive_portal_tab_reloader_unittest.cc
index 522adb8..feebe41 100644
--- a/chrome/browser/captive_portal/captive_portal_tab_reloader_unittest.cc
+++ b/chrome/browser/captive_portal/captive_portal_tab_reloader_unittest.cc
@@ -12,12 +12,12 @@
 #include "content/public/browser/interstitial_page.h"
 #include "content/public/browser/interstitial_page_delegate.h"
 #include "content/public/browser/web_contents.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/net_errors.h"
 #include "net/cert/cert_status_flags.h"
 #include "net/ssl/ssl_info.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 namespace captive_portal {
 
diff --git a/chrome/browser/chrome_browser_application_mac.h b/chrome/browser/chrome_browser_application_mac.h
index 5363942..136e448 100644
--- a/chrome/browser/chrome_browser_application_mac.h
+++ b/chrome/browser/chrome_browser_application_mac.h
@@ -12,7 +12,6 @@
 #include <vector>
 
 #import "base/mac/scoped_sending_event.h"
-#import "base/memory/scoped_nsobject.h"
 #import "base/message_loop/message_pump_mac.h"
 #include "base/synchronization/lock.h"
 
diff --git a/chrome/browser/chrome_browser_application_mac.mm b/chrome/browser/chrome_browser_application_mac.mm
index 74dd296..fba6506 100644
--- a/chrome/browser/chrome_browser_application_mac.mm
+++ b/chrome/browser/chrome_browser_application_mac.mm
@@ -9,7 +9,7 @@
 #include "base/debug/stack_trace.h"
 #import "base/logging.h"
 #import "base/mac/scoped_nsexception_enabler.h"
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #import "base/metrics/histogram.h"
 #include "base/strings/stringprintf.h"
 #import "base/strings/sys_string_conversions.h"
@@ -406,7 +406,7 @@
   }
 
   // Minimize the window by keeping this close to the super call.
-  scoped_ptr<base::mac::ScopedNSExceptionEnabler> enabler(NULL);
+  scoped_ptr<base::mac::ScopedNSExceptionEnabler> enabler;
   if (enableNSExceptions)
     enabler.reset(new base::mac::ScopedNSExceptionEnabler());
   return [super sendAction:anAction to:aTarget from:sender];
diff --git a/chrome/browser/chrome_browser_field_trials.cc b/chrome/browser/chrome_browser_field_trials.cc
index 5bab278..00256c7 100644
--- a/chrome/browser/chrome_browser_field_trials.cc
+++ b/chrome/browser/chrome_browser_field_trials.cc
@@ -10,7 +10,7 @@
 #include "base/metrics/field_trial.h"
 #include "base/prefs/pref_service.h"
 #include "base/strings/string_util.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/omnibox/omnibox_field_trial.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/chrome_version_info.h"
@@ -57,6 +57,9 @@
   base::FieldTrialList::FindValue("InstantDummy");
   base::FieldTrialList::FindValue("InstantChannel");
   base::FieldTrialList::FindValue("Test0PercentDefault");
+  // MouseEventPreconnect trial is used from renderer process.
+  // Mark here so it will be sync-ed.
+  base::FieldTrialList::FindValue("MouseEventPreconnect");
   // Activate the autocomplete dynamic field trials.
   OmniboxFieldTrial::ActivateDynamicTrials();
 }
diff --git a/chrome/browser/chrome_browser_field_trials_desktop.h b/chrome/browser/chrome_browser_field_trials_desktop.h
index 16358cd..2668e7e 100644
--- a/chrome/browser/chrome_browser_field_trials_desktop.h
+++ b/chrome/browser/chrome_browser_field_trials_desktop.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_CHROME_BROWSER_FIELD_TRIALS_DESKTOP_H_
 
 #include "base/basictypes.h"
-#include "base/time.h"
+#include "base/time/time.h"
 
 class CommandLine;
 class PrefService;
diff --git a/chrome/browser/chrome_browser_field_trials_mobile.h b/chrome/browser/chrome_browser_field_trials_mobile.h
index 4aca806..dac9603 100644
--- a/chrome/browser/chrome_browser_field_trials_mobile.h
+++ b/chrome/browser/chrome_browser_field_trials_mobile.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_CHROME_BROWSER_FIELD_TRIALS_MOBILE_H_
 
 #include "base/basictypes.h"
-#include "base/time.h"
+#include "base/time/time.h"
 
 class CommandLine;
 class PrefService;
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index 856e4f2..a959216 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -34,7 +34,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/sys_info.h"
 #include "base/threading/platform_thread.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "build/build_config.h"
 #include "chrome/browser/about_flags.h"
@@ -427,9 +427,15 @@
         command_line.GetSwitchValueASCII(switches::kOriginalProcessStartTime);
     int64 remote_start_time;
     if (base::StringToInt64(start_time_string, &remote_start_time)) {
-      UMA_HISTOGRAM_LONG_TIMES(
-          "Startup.WarmStartTimeFromRemoteProcessStart",
-          base::Time::Now() - base::Time::FromInternalValue(remote_start_time));
+      base::TimeDelta elapsed =
+          base::Time::Now() - base::Time::FromInternalValue(remote_start_time);
+      if (command_line.HasSwitch(switches::kFastStart)) {
+        UMA_HISTOGRAM_LONG_TIMES(
+            "Startup.WarmStartTimeFromRemoteProcessStartFast", elapsed);
+      } else {
+        UMA_HISTOGRAM_LONG_TIMES(
+            "Startup.WarmStartTimeFromRemoteProcessStart", elapsed);
+      }
     }
   }
 
@@ -610,11 +616,13 @@
   // Ensure any field trials specified on the command line are initialized.
   // Also stop the metrics service so that we don't pollute UMA.
   if (command_line->HasSwitch(switches::kForceFieldTrials)) {
-    std::string persistent = command_line->GetSwitchValueASCII(
-        switches::kForceFieldTrials);
-    bool ret = base::FieldTrialList::CreateTrialsFromString(persistent);
-    CHECK(ret) << "Invalid --" << switches::kForceFieldTrials <<
-                  " list specified.";
+    // Create field trials without activating them, so that this behaves in a
+    // consistent manner with field trials created from the server.
+    bool result = base::FieldTrialList::CreateTrialsFromString(
+        command_line->GetSwitchValueASCII(switches::kForceFieldTrials),
+        base::FieldTrialList::DONT_ACTIVATE_TRIALS);
+    CHECK(result) << "Invalid --" << switches::kForceFieldTrials
+                  << " list specified.";
   }
 
   chrome_variations::VariationsService* variations_service =
@@ -834,10 +842,13 @@
   chrome::UMABrowsingActivityObserver::Init();
 #endif
 
+#if !defined(OS_CHROMEOS)
   // Convert active labs into switches. This needs to be done before
   // ResourceBundle::InitSharedInstanceWithLocale as some loaded resources are
   // affected by experiment flags (--touch-optimized-ui in particular). Not
   // needed on Android as there aren't experimental flags.
+  // On ChromeOS system level flags are applied from the device settings from
+  // the session manager.
   {
     TRACE_EVENT0("startup",
         "ChromeBrowserMainParts::PreCreateThreadsImpl:ConvertFlags");
@@ -846,6 +857,7 @@
     about_flags::ConvertFlagsToSwitches(&flags_storage_,
                                         CommandLine::ForCurrentProcess());
   }
+#endif
 
   local_state_->UpdateCommandLinePrefStore(
       new CommandLinePrefStore(CommandLine::ForCurrentProcess()));
@@ -1069,10 +1081,8 @@
 #if !defined(OS_ANDROID)
 void ChromeBrowserMainParts::RunPageCycler() {
   CommandLine* command_line = CommandLine::ForCurrentProcess();
-  // We assume a native desktop for tests, but we will need to find a way to
-  // get the proper host desktop type once we start running these tests in ASH.
-  Browser* browser = chrome::FindBrowserWithProfile(
-      profile_, chrome::HOST_DESKTOP_TYPE_NATIVE);
+  Browser* browser = chrome::FindBrowserWithProfile(profile_,
+                                                    chrome::GetActiveDesktop());
   DCHECK(browser);
   PageCycler* page_cycler = NULL;
   base::FilePath input_file =
@@ -1554,14 +1564,10 @@
 #endif
       }
 
-#if !defined(OS_CHROMEOS)
-      // TODO(mad): Move this call in a proper place on CrOS.
-      // http://crosbug.com/17687
       if (translate_manager_ != NULL) {
         translate_manager_->FetchLanguageListFromTranslateServer(
             profile_->GetPrefs());
       }
-#endif
     }
 
     run_message_loop_ = true;
diff --git a/chrome/browser/chrome_browser_main_android.cc b/chrome/browser/chrome_browser_main_android.cc
index f08ce27..b83a09e 100644
--- a/chrome/browser/chrome_browser_main_android.cc
+++ b/chrome/browser/chrome_browser_main_android.cc
@@ -84,21 +84,6 @@
   ChromeBrowserMainParts::PreEarlyInitialization();
 }
 
-int ChromeBrowserMainPartsAndroid::PreCreateThreads() {
-  TRACE_EVENT0("startup", "ChromeBrowserMainPartsAndroid::PreCreateThreads")
-  // PreCreateThreads initializes ResourceBundle instance.
-  const int result = ChromeBrowserMainParts::PreCreateThreads();
-
-  // Add devtools_resources.pak which is used in Chromium TestShell.
-  base::FilePath paks_path;
-  PathService::Get(ui::DIR_RESOURCE_PAKS_ANDROID, &paks_path);
-  ResourceBundle::GetSharedInstance().AddOptionalDataPackFromPath(
-      paks_path.Append(FILE_PATH_LITERAL("devtools_resources.pak")),
-      ui::SCALE_FACTOR_NONE);
-
-  return result;
-}
-
 void ChromeBrowserMainPartsAndroid::ShowMissingLocaleMessageBox() {
   NOTREACHED();
 }
diff --git a/chrome/browser/chrome_browser_main_android.h b/chrome/browser/chrome_browser_main_android.h
index 1439ac2..b498db5 100644
--- a/chrome/browser/chrome_browser_main_android.h
+++ b/chrome/browser/chrome_browser_main_android.h
@@ -18,7 +18,6 @@
   // content::BrowserMainParts overrides.
   virtual void PreProfileInit() OVERRIDE;
   virtual void PreEarlyInitialization() OVERRIDE;
-  virtual int PreCreateThreads() OVERRIDE;
 
   // ChromeBrowserMainParts overrides.
   virtual void ShowMissingLocaleMessageBox() OVERRIDE;
diff --git a/chrome/browser/chrome_browser_main_mac.mm b/chrome/browser/chrome_browser_main_mac.mm
index b1b4989..156146b 100644
--- a/chrome/browser/chrome_browser_main_mac.mm
+++ b/chrome/browser/chrome_browser_main_mac.mm
@@ -12,7 +12,7 @@
 #include "base/files/file_path.h"
 #include "base/mac/bundle_locations.h"
 #include "base/mac/mac_util.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/metrics/histogram.h"
 #include "base/path_service.h"
 #include "chrome/app/breakpad_mac.h"
@@ -265,9 +265,9 @@
   }
 
   // Now load the nib (from the right bundle).
-  scoped_nsobject<NSNib>
-      nib([[NSNib alloc] initWithNibNamed:@"MainMenu"
-                                   bundle:base::mac::FrameworkBundle()]);
+  base::scoped_nsobject<NSNib> nib(
+      [[NSNib alloc] initWithNibNamed:@"MainMenu"
+                               bundle:base::mac::FrameworkBundle()]);
   // TODO(viettrungluu): crbug.com/20504 - This currently leaks, so if you
   // change this, you'll probably need to change the Valgrind suppression.
   [nib instantiateNibWithOwner:NSApp topLevelObjects:nil];
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 6aba761..f2a6ab4 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -44,6 +44,9 @@
 #include "chrome/browser/extensions/suggest_permission_util.h"
 #include "chrome/browser/geolocation/chrome_access_token_store.h"
 #include "chrome/browser/google/google_util.h"
+#include "chrome/browser/guestview/adview/adview_guest.h"
+#include "chrome/browser/guestview/guestview_constants.h"
+#include "chrome/browser/guestview/webview/webview_guest.h"
 #include "chrome/browser/media/media_capture_devices_dispatcher.h"
 #include "chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.h"
 #include "chrome/browser/nacl_host/nacl_host_message_filter.h"
@@ -78,13 +81,12 @@
 #include "chrome/browser/tab_contents/tab_util.h"
 #include "chrome/browser/toolkit_extra_parts.h"
 #include "chrome/browser/ui/chrome_select_file_policy.h"
+#include "chrome/browser/ui/sync/sync_promo_ui.h"
 #include "chrome/browser/ui/tab_contents/chrome_web_contents_view_delegate.h"
 #include "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h"
-#include "chrome/browser/ui/webui/sync_promo/sync_promo_ui.h"
 #include "chrome/browser/user_style_sheet_watcher.h"
 #include "chrome/browser/user_style_sheet_watcher_factory.h"
 #include "chrome/browser/validation_message_message_filter.h"
-#include "chrome/browser/webview/webview_guest.h"
 #include "chrome/common/child_process_logging.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_paths.h"
@@ -134,6 +136,7 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/message_center/message_center_util.h"
+#include "webkit/browser/fileapi/external_mount_points.h"
 #include "webkit/common/webpreferences.h"
 #include "webkit/plugins/plugin_switches.h"
 
@@ -145,6 +148,7 @@
 #include "chrome/browser/spellchecker/spellcheck_message_filter_mac.h"
 #elif defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/chrome_browser_main_chromeos.h"
+#include "chrome/browser/chromeos/fileapi/cros_mount_point_provider.h"
 #include "chrome/browser/chromeos/login/startup_utils.h"
 #include "chrome/browser/chromeos/login/user_manager.h"
 #include "chrome/browser/chromeos/system/statistics_provider.h"
@@ -232,6 +236,7 @@
   "ghbfeebgmiidnnmeobbbaiamklmpbpii",  // see crbug.com/134099
   "jdfhpkjeckflbbleddjlpimecpbjdeep",  // see crbug.com/142514
   "iabmpiboiopbgfabjmgeedhcmjenhbla",  // see crbug.com/165080
+  "B7CF8A292249681AF81771650BA4CEEAF19A4560", // see crbug.com/165080
   "6EAED1924DB611B6EEF2A664BD077BE7EAD33B8F", // see crbug.com/234789
   "7525AF4F66763A70A883C4700529F647B470E4D2", // see crbug.com/238084
   "0B549507088E1564D672F7942EB87CA4DAD73972", // see crbug.com/238084
@@ -693,28 +698,79 @@
   return extensions::ActivityLog::IsLogEnabledOnAnyProfile();
 }
 
+void ChromeContentBrowserClient::GuestWebContentsCreated(
+    WebContents* guest_web_contents,
+    WebContents* opener_web_contents,
+    scoped_ptr<base::DictionaryValue> extra_params) {
+  if (opener_web_contents) {
+    GuestView* guest = GuestView::FromWebContents(opener_web_contents);
+    if (!guest) {
+      NOTREACHED();
+      return;
+    }
+
+    switch (guest->GetViewType()) {
+      case GuestView::WEBVIEW: {
+        new WebViewGuest(guest_web_contents);
+        break;
+      }
+      case GuestView::ADVIEW: {
+        new AdViewGuest(guest_web_contents);
+        break;
+      }
+      default:
+        NOTREACHED();
+        break;
+    }
+    return;
+  }
+
+  if (!extra_params) {
+    NOTREACHED();
+    return;
+  }
+  std::string api_type;
+  extra_params->GetString(guestview::kAttributeApi, &api_type);
+
+  if (api_type == "adview") {
+    new AdViewGuest(guest_web_contents);
+  } else if (api_type == "webview") {
+    new WebViewGuest(guest_web_contents);
+  } else {
+    NOTREACHED();
+  }
+}
+
 void ChromeContentBrowserClient::GuestWebContentsAttached(
     WebContents* guest_web_contents,
     WebContents* embedder_web_contents,
-    int browser_plugin_instance_id) {
+    int browser_plugin_instance_id,
+    const base::DictionaryValue& extra_params) {
   Profile* profile = Profile::FromBrowserContext(
       embedder_web_contents->GetBrowserContext());
   ExtensionService* service =
       extensions::ExtensionSystem::Get(profile)->extension_service();
-  if (!service)
+  if (!service) {
+    NOTREACHED();
     return;
+  }
   const GURL& url = embedder_web_contents->GetSiteInstance()->GetSiteURL();
   const Extension* extension = service->extensions()->
       GetExtensionOrAppByURL(ExtensionURLInfo(url));
-  if (!extension)
+  if (!extension) {
+    NOTREACHED();
     return;
-  std::vector<ExtensionMsg_Loaded_Params> extensions;
-  extensions.push_back(ExtensionMsg_Loaded_Params(extension));
-  guest_web_contents->Send(new ExtensionMsg_Loaded(extensions));
-  new WebViewGuest(guest_web_contents,
-                   embedder_web_contents,
-                   extension->id(),
-                   browser_plugin_instance_id);
+  }
+
+  GuestView* guest = GuestView::FromWebContents(guest_web_contents);
+  if (!guest) {
+    NOTREACHED();
+    return;
+  }
+  guest->Attach(embedder_web_contents,
+                extension->id(),
+                browser_plugin_instance_id,
+                extra_params);
 }
 
 void ChromeContentBrowserClient::RenderProcessHostCreated(
@@ -748,8 +804,12 @@
   host->GetChannel()->AddFilter(new WebRtcLoggingHandlerHost());
 #endif
 #if !defined(DISABLE_NACL)
-  host->GetChannel()->AddFilter(new NaClHostMessageFilter(id, profile,
-    context));
+  ExtensionInfoMap* extension_info_map =
+      extensions::ExtensionSystem::Get(profile)->info_map();
+  host->GetChannel()->AddFilter(new NaClHostMessageFilter(
+      id, profile->IsOffTheRecord(),
+      profile->GetPath(), extension_info_map,
+      context));
 #endif
 
   host->Send(new ChromeViewMsg_SetIsIncognitoProcess(
@@ -1307,6 +1367,7 @@
       switches::kDisableScriptedPrintThrottling,
       switches::kEnableAdview,
       switches::kEnableAdviewSrcAttribute,
+      switches::kEnableAppWindowControls,
       switches::kEnableBenchmarking,
       switches::kEnableExperimentalExtensionApis,
       switches::kEnableIPCFuzzing,
@@ -1987,7 +2048,7 @@
       !chromeos::StartupUtils::IsOobeCompleted()) {
     bool keyboard_driven_oobe = false;
     chromeos::system::StatisticsProvider::GetInstance()->GetMachineFlag(
-        chromeos::kOemKeyboardDrivenOobeKey, &keyboard_driven_oobe);
+        chromeos::system::kOemKeyboardDrivenOobeKey, &keyboard_driven_oobe);
     if (keyboard_driven_oobe)
        web_prefs->password_echo_enabled = true;
   }
@@ -2236,6 +2297,8 @@
 
 void ChromeContentBrowserClient::GetAdditionalFileSystemMountPointProviders(
     const base::FilePath& storage_partition_path,
+    quota::SpecialStoragePolicy* special_storage_policy,
+    fileapi::ExternalMountPoints* external_mount_points,
     ScopedVector<fileapi::FileSystemMountPointProvider>* additional_providers) {
 #if !defined(OS_ANDROID)
   base::SequencedWorkerPool* pool = content::BrowserThread::GetBlockingPool();
@@ -2244,6 +2307,17 @@
       pool->GetSequencedTaskRunner(pool->GetNamedSequenceToken(
           MediaFileSystemMountPointProvider::kMediaTaskRunnerName)).get()));
 #endif
+#if defined(OS_CHROMEOS)
+  DCHECK(external_mount_points);
+  chromeos::CrosMountPointProvider* cros_mount_provider =
+      new chromeos::CrosMountPointProvider(
+          special_storage_policy,
+          external_mount_points,
+          fileapi::ExternalMountPoints::GetSystemInstance());
+  cros_mount_provider->AddSystemMountPoints();
+  DCHECK(cros_mount_provider->CanHandleType(fileapi::kFileSystemTypeExternal));
+  additional_providers->push_back(cros_mount_provider);
+#endif
 }
 
 #if defined(OS_POSIX) && !defined(OS_MACOSX)
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h
index 9d2a5e7..0996c6e 100644
--- a/chrome/browser/chrome_content_browser_client.h
+++ b/chrome/browser/chrome_content_browser_client.h
@@ -59,10 +59,15 @@
       bool* in_memory) OVERRIDE;
   virtual content::WebContentsViewDelegate* GetWebContentsViewDelegate(
       content::WebContents* web_contents) OVERRIDE;
+  virtual void GuestWebContentsCreated(
+      content::WebContents* guest_web_contents,
+      content::WebContents* opener_web_contents,
+      scoped_ptr<base::DictionaryValue> extra_params) OVERRIDE;
   virtual void GuestWebContentsAttached(
       content::WebContents* guest_web_contents,
       content::WebContents* embedder_web_contents,
-      int browser_plugin_instance_id) OVERRIDE;
+      int browser_plugin_instance_id,
+      const base::DictionaryValue& extra_params) OVERRIDE;
   virtual void RenderProcessHostCreated(
       content::RenderProcessHost* host) OVERRIDE;
   virtual bool ShouldUseProcessPerSite(content::BrowserContext* browser_context,
@@ -237,6 +242,8 @@
       std::vector<std::string>* additional_schemes) OVERRIDE;
   virtual void GetAdditionalFileSystemMountPointProviders(
       const base::FilePath& storage_partition_path,
+      quota::SpecialStoragePolicy* special_storage_policy,
+      fileapi::ExternalMountPoints* external_mount_points,
       ScopedVector<fileapi::FileSystemMountPointProvider>*
           additional_providers) OVERRIDE;
 
diff --git a/chrome/browser/chrome_content_browser_client_browsertest.cc b/chrome/browser/chrome_content_browser_client_browsertest.cc
index a8b6bbb..de24691 100644
--- a/chrome/browser/chrome_content_browser_client_browsertest.cc
+++ b/chrome/browser/chrome_content_browser_client_browsertest.cc
@@ -11,7 +11,7 @@
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_switches.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 namespace content {
 
diff --git a/chrome/browser/chrome_process_finder_win.cc b/chrome/browser/chrome_process_finder_win.cc
index c7a4985..34f6761 100644
--- a/chrome/browser/chrome_process_finder_win.cc
+++ b/chrome/browser/chrome_process_finder_win.cc
@@ -93,7 +93,7 @@
 
 // END COPY from net/base/escape.cc
 
-}
+}  // namespace
 
 namespace chrome {
 
@@ -102,7 +102,8 @@
                       user_data_dir.value().c_str());
 }
 
-NotifyChromeResult AttemptToNotifyRunningChrome(HWND remote_window) {
+NotifyChromeResult AttemptToNotifyRunningChrome(HWND remote_window,
+                                                bool fast_start) {
   DCHECK(remote_window);
   static const char kSearchUrl[] =
       "http://www.google.com/search?q=%s&sourceid=chrome&ie=UTF-8";
@@ -150,6 +151,9 @@
       base::Int64ToString(
           base::CurrentProcessInfo::CreationTime()->ToInternalValue()));
 
+  if (fast_start)
+    command_line.AppendSwitch(switches::kFastStart);
+
   // Send the command line to the remote chrome window.
   // Format is "START\0<<<current directory>>>\0<<<commandline>>>".
   std::wstring to_send(L"START\0", 6);  // want the NULL in the string.
diff --git a/chrome/browser/chrome_process_finder_win.h b/chrome/browser/chrome_process_finder_win.h
index 46c49ed..bc5c81f 100644
--- a/chrome/browser/chrome_process_finder_win.h
+++ b/chrome/browser/chrome_process_finder_win.h
@@ -25,7 +25,9 @@
 // Attempts to send the current command line to an already running instance of
 // Chrome via a WM_COPYDATA message.
 // Returns true if a running Chrome is found and successfully notified.
-NotifyChromeResult AttemptToNotifyRunningChrome(HWND remote_window);
+// |fast_start| is true when this is being called on the window fast start path.
+NotifyChromeResult AttemptToNotifyRunningChrome(HWND remote_window,
+                                                bool fast_start);
 
 }  // namespace chrome
 
diff --git a/chrome/browser/chrome_quota_permission_context.cc b/chrome/browser/chrome_quota_permission_context.cc
index 5c42180..3e3907b 100644
--- a/chrome/browser/chrome_quota_permission_context.cc
+++ b/chrome/browser/chrome_quota_permission_context.cc
@@ -17,11 +17,11 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/navigation_details.h"
 #include "content/public/browser/web_contents.h"
-#include "googleurl/src/gurl.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "net/base/net_util.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "url/gurl.h"
 #include "webkit/common/quota/quota_types.h"
 
 using content::BrowserThread;
diff --git a/chrome/browser/chrome_to_mobile_service.cc b/chrome/browser/chrome_to_mobile_service.cc
index 4233625..eebde18 100644
--- a/chrome/browser/chrome_to_mobile_service.cc
+++ b/chrome/browser/chrome_to_mobile_service.cc
@@ -15,12 +15,12 @@
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/chrome_to_mobile_service_factory.h"
+#include "chrome/browser/invalidation/invalidation_service.h"
+#include "chrome/browser/invalidation/invalidation_service_factory.h"
 #include "chrome/browser/printing/cloud_print/cloud_print_url.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/token_service.h"
 #include "chrome/browser/signin/token_service_factory.h"
-#include "chrome/browser/sync/profile_sync_service.h"
-#include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_command_controller.h"
 #include "chrome/browser/ui/browser_finder.h"
@@ -205,7 +205,7 @@
 // Call this as a BlockingPoolSequencedTask [after posting SubmitSnapshotFile].
 void DeleteSnapshotFile(const base::FilePath& snapshot) {
   DCHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-  bool success = file_util::Delete(snapshot, false);
+  bool success = base::Delete(snapshot, false);
   DCHECK(success);
 }
 
@@ -261,23 +261,24 @@
 ChromeToMobileService::ChromeToMobileService(Profile* profile)
     : weak_ptr_factory_(this),
       profile_(profile),
-      sync_invalidation_enabled_(false) {
+      invalidation_enabled_(false) {
   // TODO(msw): Unit tests do not provide profiles; see http://crbug.com/122183
-  ProfileSyncService* profile_sync_service =
-      profile_ ? ProfileSyncServiceFactory::GetForProfile(profile_) : NULL;
-  if (profile_sync_service) {
+
+  invalidation::InvalidationService* invalidation_service = profile_ ?
+      invalidation::InvalidationServiceFactory::GetForProfile(profile_) : NULL;
+  if (invalidation_service) {
     CloudPrintURL cloud_print_url(profile_);
     cloud_print_url_ = cloud_print_url.GetCloudPrintServiceURL();
-    sync_invalidation_enabled_ =
-        (profile_sync_service->GetInvalidatorState() ==
+    invalidation_enabled_ =
+        (invalidation_service->GetInvalidatorState() ==
          syncer::INVALIDATIONS_ENABLED);
     // Register for cloud print device list invalidation notifications.
-    profile_sync_service->RegisterInvalidationHandler(this);
+    invalidation_service->RegisterInvalidationHandler(this);
     syncer::ObjectIdSet ids;
     ids.insert(invalidation::ObjectId(
         ipc::invalidation::ObjectSource::CHROME_COMPONENTS,
         kSyncInvalidationObjectIdChromeToMobileDeviceList));
-    profile_sync_service->UpdateRegisteredInvalidationIds(this, ids);
+    invalidation_service->UpdateRegisteredInvalidationIds(this, ids);
   }
 }
 
@@ -292,7 +293,7 @@
 }
 
 const base::ListValue* ChromeToMobileService::GetMobiles() const {
-  return sync_invalidation_enabled_ ?
+  return invalidation_enabled_ ?
       profile_->GetPrefs()->GetList(prefs::kChromeToMobileDeviceList) : NULL;
 }
 
@@ -384,10 +385,10 @@
 void ChromeToMobileService::Shutdown() {
   // TODO(msw): Unit tests do not provide profiles; see http://crbug.com/122183
   // Unregister for cloud print device list invalidation notifications.
-  ProfileSyncService* profile_sync_service =
-      profile_ ? ProfileSyncServiceFactory::GetForProfile(profile_) : NULL;
-  if (profile_sync_service)
-    profile_sync_service->UnregisterInvalidationHandler(this);
+  invalidation::InvalidationService* invalidation_service = profile_ ?
+      invalidation::InvalidationServiceFactory::GetForProfile(profile_) : NULL;
+  if (invalidation_service)
+    invalidation_service->UnregisterInvalidationHandler(this);
 }
 
 void ChromeToMobileService::OnURLFetchComplete(const net::URLFetcher* source) {
@@ -472,7 +473,7 @@
 
 void ChromeToMobileService::OnInvalidatorStateChange(
     syncer::InvalidatorState state) {
-  sync_invalidation_enabled_ = (state == syncer::INVALIDATIONS_ENABLED);
+  invalidation_enabled_ = (state == syncer::INVALIDATIONS_ENABLED);
 }
 
 void ChromeToMobileService::OnIncomingInvalidation(
@@ -482,12 +483,12 @@
       ipc::invalidation::ObjectSource::CHROME_COMPONENTS,
       kSyncInvalidationObjectIdChromeToMobileDeviceList)));
   // TODO(msw): Unit tests do not provide profiles; see http://crbug.com/122183
-  ProfileSyncService* profile_sync_service =
-      profile_ ? ProfileSyncServiceFactory::GetForProfile(profile_) : NULL;
-  if (profile_sync_service) {
+  invalidation::InvalidationService* invalidation_service = profile_ ?
+      invalidation::InvalidationServiceFactory::GetForProfile(profile_) : NULL;
+  if (invalidation_service) {
     // TODO(dcheng): Only acknowledge the invalidation once the device search
     // has finished. http://crbug.com/156843.
-    profile_sync_service->AcknowledgeInvalidation(
+    invalidation_service->AcknowledgeInvalidation(
         invalidation_map.begin()->first,
         invalidation_map.begin()->second.ack_handle);
   }
diff --git a/chrome/browser/chrome_to_mobile_service.h b/chrome/browser/chrome_to_mobile_service.h
index 499d856..ee18dee 100644
--- a/chrome/browser/chrome_to_mobile_service.h
+++ b/chrome/browser/chrome_to_mobile_service.h
@@ -16,16 +16,16 @@
 #include "base/memory/scoped_vector.h"
 #include "base/memory/weak_ptr.h"
 #include "base/strings/string16.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "base/values.h"
 #include "chrome/browser/sessions/session_id.h"
 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "google_apis/gaia/oauth2_access_token_consumer.h"
-#include "googleurl/src/gurl.h"
 #include "net/url_request/url_fetcher_delegate.h"
 #include "sync/notifier/invalidation_handler.h"
+#include "url/gurl.h"
 
 class OAuth2AccessTokenFetcher;
 class Browser;
@@ -201,9 +201,9 @@
 
   Profile* profile_;
 
-  // Sync invalidation service state. Chrome To Mobile requires this service to
-  // to keep the mobile device list up to date and prevent page send failures.
-  bool sync_invalidation_enabled_;
+  // Invalidation service state. Chrome To Mobile requires this service to keep
+  // the mobile device list up to date and prevent page send failures.
+  bool invalidation_enabled_;
 
   // Used to recieve TokenService notifications for GaiaOAuth2LoginRefreshToken.
   content::NotificationRegistrar registrar_;
diff --git a/chrome/browser/chrome_to_mobile_service_factory.cc b/chrome/browser/chrome_to_mobile_service_factory.cc
index 3c1150a..8b1c0c4 100644
--- a/chrome/browser/chrome_to_mobile_service_factory.cc
+++ b/chrome/browser/chrome_to_mobile_service_factory.cc
@@ -5,9 +5,9 @@
 #include "chrome/browser/chrome_to_mobile_service_factory.h"
 
 #include "chrome/browser/chrome_to_mobile_service.h"
+#include "chrome/browser/invalidation/invalidation_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/token_service_factory.h"
-#include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
 
 // static
@@ -36,7 +36,7 @@
     : BrowserContextKeyedServiceFactory(
         "ChromeToMobileService",
         BrowserContextDependencyManager::GetInstance()) {
-  DependsOn(ProfileSyncServiceFactory::GetInstance());
+  DependsOn(invalidation::InvalidationServiceFactory::GetInstance());
   DependsOn(TokenServiceFactory::GetInstance());
   // TODO(msw): Uncomment this once it exists.
   // DependsOn(PrefServiceFactory::GetInstance());
diff --git a/chrome/browser/chrome_to_mobile_service_unittest.cc b/chrome/browser/chrome_to_mobile_service_unittest.cc
index 79635c8..3cc210ca 100644
--- a/chrome/browser/chrome_to_mobile_service_unittest.cc
+++ b/chrome/browser/chrome_to_mobile_service_unittest.cc
@@ -85,6 +85,10 @@
 // Test that GetMobiles and HasMobiles require Sync Invalidations being enabled.
 TEST_F(ChromeToMobileServiceTest, GetMobiles) {
   ChromeToMobileService* service = GetService();
+
+  // Send a fake notification that Sync Invalidations are disabled.
+  service->OnInvalidatorStateChange(syncer::TRANSIENT_INVALIDATION_ERROR);
+
   EXPECT_EQ(NULL, service->GetMobiles());
   EXPECT_FALSE(service->HasMobiles());
 
@@ -117,6 +121,9 @@
 
 // Test fulfilling the requirements to enable the feature.
 TEST_F(ChromeToMobileServiceTest, RequirementsToEnable) {
+  // Send a fake notification that Sync Invalidations are disabled.
+  GetService()->OnInvalidatorStateChange(syncer::TRANSIENT_INVALIDATION_ERROR);
+
   // Navigate to a page with a URL that is valid to send.
   AddTab(browser(), GURL("http://foo"));
   EXPECT_FALSE(UpdateAndGetVerifiedCommandState());
diff --git a/chrome/browser/chromeos/DEPS b/chrome/browser/chromeos/DEPS
index 8e9c86e..52ada1a 100644
--- a/chrome/browser/chromeos/DEPS
+++ b/chrome/browser/chromeos/DEPS
@@ -3,5 +3,4 @@
   "+dbus",
   "+device/bluetooth",
   "+media/base/media_switches.h",  # For media command line switches.
-  "+webkit/chromeos/fileapi",
 ]
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.cc b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
index e578328..f0617f7 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_manager.cc
+++ b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
@@ -7,6 +7,7 @@
 #include "ash/high_contrast/high_contrast_controller.h"
 #include "ash/shell.h"
 #include "ash/system/tray/system_tray_notifier.h"
+#include "ash/wm/event_rewriter_event_filter.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/singleton.h"
 #include "base/metrics/histogram.h"
@@ -32,9 +33,9 @@
 #include "chrome/common/extensions/manifest_handlers/content_scripts_handler.h"
 #include "chrome/common/pref_names.h"
 #include "content/public/browser/browser_accessibility_state.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
+#include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_source.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
@@ -161,6 +162,7 @@
 AccessibilityManager::AccessibilityManager()
     : profile_(NULL),
       large_cursor_enabled_(false),
+      sticky_keys_enabled_(false),
       spoken_feedback_enabled_(false),
       high_contrast_enabled_(false),
       spoken_feedback_notification_(ash::A11Y_NOTIFICATION_NONE) {
@@ -216,6 +218,35 @@
   return large_cursor_enabled_;
 }
 
+void AccessibilityManager::EnableStickyKeys(bool enabled) {
+  if (!profile_)
+    return;
+  PrefService* pref_service = profile_->GetPrefs();
+  pref_service->SetBoolean(prefs::kStickyKeysEnabled, enabled);
+  pref_service->CommitPendingWrite();
+}
+
+bool AccessibilityManager::IsStickyKeysEnabled() {
+  return sticky_keys_enabled_;
+}
+
+void AccessibilityManager::UpdateStickyKeysFromPref() {
+  if (!profile_)
+    return;
+
+  const bool enabled =
+      profile_->GetPrefs()->GetBoolean(prefs::kStickyKeysEnabled);
+
+  if (sticky_keys_enabled_ == enabled)
+    return;
+
+  sticky_keys_enabled_ = enabled;
+#if defined(USE_ASH)
+  // Sticky keys is implemented only in ash.
+  ash::Shell::GetInstance()->event_rewriter_filter()->EnableStickyKeys(enabled);
+#endif
+}
+
 void AccessibilityManager::EnableSpokenFeedback(
     bool enabled,
     ash::AccessibilityNotificationVisibility notify) {
@@ -418,6 +449,10 @@
         base::Bind(&AccessibilityManager::UpdateLargeCursorFromPref,
                    base::Unretained(this)));
     pref_change_registrar_->Add(
+        prefs::kStickyKeysEnabled,
+        base::Bind(&AccessibilityManager::UpdateStickyKeysFromPref,
+                   base::Unretained(this)));
+    pref_change_registrar_->Add(
         prefs::kSpokenFeedbackEnabled,
         base::Bind(&AccessibilityManager::UpdateSpokenFeedbackFromPref,
                    base::Unretained(this)));
@@ -441,6 +476,7 @@
 
   profile_ = profile;
   UpdateLargeCursorFromPref();
+  UpdateStickyKeysFromPref();
   UpdateSpokenFeedbackFromPref();
   UpdateHighContrastFromPref();
 }
@@ -479,10 +515,13 @@
     const content::NotificationSource& source,
     const content::NotificationDetails& details) {
   switch (type) {
-    case chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE:
+    case chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE: {
       // Update |profile_| when entering the login screen.
-      SetProfile(ProfileHelper::GetSigninProfile());
+      Profile* profile = ProfileManager::GetDefaultProfile();
+      if (ProfileHelper::IsSigninProfile(profile))
+        SetProfile(profile);
       break;
+    }
     case chrome::NOTIFICATION_SESSION_STARTED:
       // Update |profile_| when entering a session.
       SetProfile(ProfileManager::GetDefaultProfile());
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.h b/chrome/browser/chromeos/accessibility/accessibility_manager.h
index 5f87098..d181f01 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_manager.h
+++ b/chrome/browser/chromeos/accessibility/accessibility_manager.h
@@ -48,6 +48,12 @@
   // Returns true if the large cursor is enabled, or false if not.
   bool IsLargeCursorEnabled();
 
+  // Enables or disable Sticky Keys.
+  void EnableStickyKeys(bool enabled);
+
+  // Returns true if the Sticky Keys is enabled, or false if not.
+  bool IsStickyKeysEnabled();
+
   // Enables or disables spoken feedback. Enabling spoken feedback installs the
   // ChromeVox component extension.
   void EnableSpokenFeedback(bool enabled,
@@ -79,6 +85,7 @@
 
  private:
   void UpdateLargeCursorFromPref();
+  void UpdateStickyKeysFromPref();
   void UpdateSpokenFeedbackFromPref();
   void UpdateHighContrastFromPref();
   void LocalePrefChanged();
@@ -98,6 +105,7 @@
   scoped_ptr<PrefChangeRegistrar> local_state_pref_change_registrar_;
 
   bool large_cursor_enabled_;
+  bool sticky_keys_enabled_;
   bool spoken_feedback_enabled_;
   bool high_contrast_enabled_;
 
diff --git a/chrome/browser/chromeos/accessibility/magnification_manager.cc b/chrome/browser/chromeos/accessibility/magnification_manager.cc
index 875f12a..84cdc21 100644
--- a/chrome/browser/chromeos/accessibility/magnification_manager.cc
+++ b/chrome/browser/chromeos/accessibility/magnification_manager.cc
@@ -22,10 +22,11 @@
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "chrome/common/pref_names.h"
-#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_source.h"
 
 namespace chromeos {
 
@@ -102,9 +103,7 @@
 
  private:
   void SetProfile(Profile* profile) {
-    if (pref_change_registrar_) {
-      pref_change_registrar_.reset();
-    }
+    pref_change_registrar_.reset();
 
     if (profile) {
       pref_change_registrar_.reset(new PrefChangeRegistrar);
@@ -186,15 +185,18 @@
         content::Details<AccessibilityStatusEventDetails>(&details));
   }
 
-  // content::NotificationObserver implimentation:
+  // content::NotificationObserver implementation:
   virtual void Observe(int type,
                        const content::NotificationSource& source,
                        const content::NotificationDetails& details) OVERRIDE {
     switch (type) {
-      case chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE:
+      case chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE: {
         // Update |profile_| when entering the login screen.
-        SetProfile(ProfileHelper::GetSigninProfile());
+        Profile* profile = ProfileManager::GetDefaultProfile();
+        if (ProfileHelper::IsSigninProfile(profile))
+          SetProfile(profile);
         break;
+      }
       case chrome::NOTIFICATION_SESSION_STARTED:
         // Update |profile_| when entering a session.
         SetProfile(ProfileManager::GetDefaultProfile());
diff --git a/chrome/browser/chromeos/app_mode/app_session_lifetime.cc b/chrome/browser/chromeos/app_mode/app_session_lifetime.cc
index 3e4aadc..48514f0 100644
--- a/chrome/browser/chromeos/app_mode/app_session_lifetime.cc
+++ b/chrome/browser/chromeos/app_mode/app_session_lifetime.cc
@@ -36,9 +36,10 @@
 
  private:
   // extensions::ShellWindowRegistry::Observer overrides:
-  virtual void OnShellWindowAdded(ShellWindow* shell_window) OVERRIDE {}
-  virtual void OnShellWindowIconChanged(ShellWindow* shell_window) OVERRIDE {}
-  virtual void OnShellWindowRemoved(ShellWindow* shell_window) OVERRIDE {
+  virtual void OnShellWindowAdded(apps::ShellWindow* shell_window) OVERRIDE {}
+  virtual void OnShellWindowIconChanged(apps::ShellWindow* shell_window)
+    OVERRIDE {}
+  virtual void OnShellWindowRemoved(apps::ShellWindow* shell_window) OVERRIDE {
     if (window_registry_->shell_windows().empty()) {
       chrome::AttemptUserExit();
       window_registry_->RemoveObserver(this);
diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_data.cc b/chrome/browser/chromeos/app_mode/kiosk_app_data.cc
index 680ccc8..639d07f 100644
--- a/chrome/browser/chromeos/app_mode/kiosk_app_data.cc
+++ b/chrome/browser/chromeos/app_mode/kiosk_app_data.cc
@@ -277,7 +277,7 @@
   if (!icon_path_.empty()) {
     BrowserThread::PostBlockingPoolTask(
         FROM_HERE,
-        base::Bind(base::IgnoreResult(&file_util::Delete), icon_path_, false));
+        base::Bind(base::IgnoreResult(&base::Delete), icon_path_, false));
   }
 }
 
diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_update_service.cc b/chrome/browser/chromeos/app_mode/kiosk_app_update_service.cc
index 0b789f9..e9a0384 100644
--- a/chrome/browser/chromeos/app_mode/kiosk_app_update_service.cc
+++ b/chrome/browser/chromeos/app_mode/kiosk_app_update_service.cc
@@ -6,6 +6,10 @@
 
 #include "base/logging.h"
 #include "chrome/browser/app_mode/app_mode_utils.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/browser_process_platform_part_chromeos.h"
+#include "chrome/browser/chromeos/system/automatic_reboot_manager.h"
+#include "chrome/browser/extensions/api/runtime/runtime_api.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_system.h"
 #include "chrome/browser/extensions/extension_system_factory.h"
@@ -22,17 +26,39 @@
 
 }  // namespace
 
-KioskAppUpdateService::KioskAppUpdateService(Profile* profile)
-    : profile_(profile) {
+KioskAppUpdateService::KioskAppUpdateService(
+    Profile* profile,
+    system::AutomaticRebootManager* automatic_reboot_manager)
+    : profile_(profile),
+      automatic_reboot_manager_(automatic_reboot_manager) {
   ExtensionService* service =
       extensions::ExtensionSystem::Get(profile_)->extension_service();
   if (service)
     service->AddUpdateObserver(this);
+
+  if (automatic_reboot_manager_)
+    automatic_reboot_manager_->AddObserver(this);
 }
 
 KioskAppUpdateService::~KioskAppUpdateService() {
 }
 
+void KioskAppUpdateService::StartAppUpdateRestartTimer() {
+  if (restart_timer_.IsRunning())
+    return;
+
+  // Setup timer to force restart once the wait period expires.
+  restart_timer_.Start(
+      FROM_HERE, base::TimeDelta::FromMilliseconds(kForceRestartWaitTimeMs),
+      this, &KioskAppUpdateService::ForceAppUpdateRestart);
+}
+
+void KioskAppUpdateService::ForceAppUpdateRestart() {
+  // Force a chrome restart (not a logout or reboot) by closing all browsers.
+  LOG(WARNING) << "Force closing all browsers to update kiosk app.";
+  chrome::CloseAllBrowsers();
+}
+
 void KioskAppUpdateService::Shutdown() {
   ExtensionService* service = profile_->GetExtensionService();
   if (service)
@@ -44,23 +70,38 @@
   if (app_id != app_id_)
     return;
 
-  StartRestartTimer();
+  extensions::RuntimeEventRouter::DispatchOnRestartRequiredEvent(
+      profile_,
+      app_id_,
+      extensions::api::runtime::OnRestartRequired::REASON_APP_UPDATE);
+
+  StartAppUpdateRestartTimer();
 }
 
-void KioskAppUpdateService::StartRestartTimer() {
-  if (restart_timer_.IsRunning())
-    return;
+void KioskAppUpdateService::OnRebootScheduled(Reason reason) {
+  extensions::api::runtime::OnRestartRequired::Reason restart_reason =
+      extensions::api::runtime::OnRestartRequired::REASON_NONE;
+  switch (reason) {
+    case REBOOT_REASON_OS_UPDATE:
+      restart_reason =
+          extensions::api::runtime::OnRestartRequired::REASON_OS_UPDATE;
+      break;
+    case REBOOT_REASON_PERIODIC:
+      restart_reason =
+          extensions::api::runtime::OnRestartRequired::REASON_PERIODIC;
+      break;
+    default:
+      NOTREACHED() << "Unknown reboot reason=" << reason;
+      return;
+  }
 
-  // Setup timer to force restart once the wait period expires.
-  restart_timer_.Start(
-      FROM_HERE, base::TimeDelta::FromMilliseconds(kForceRestartWaitTimeMs),
-      this, &KioskAppUpdateService::ForceRestart);
+  extensions::RuntimeEventRouter::DispatchOnRestartRequiredEvent(
+      profile_, app_id_, restart_reason);
 }
 
-void KioskAppUpdateService::ForceRestart() {
-  // Force a chrome restart (not a logout or reboot) by closing all browsers.
-  LOG(WARNING) << "Force closing all browsers to update kiosk app.";
-  chrome::CloseAllBrowsers();
+void KioskAppUpdateService::WillDestroyAutomaticRebootManager() {
+  automatic_reboot_manager_->RemoveObserver(this);
+  automatic_reboot_manager_ = NULL;
 }
 
 KioskAppUpdateServiceFactory::KioskAppUpdateServiceFactory()
@@ -92,8 +133,10 @@
 
 BrowserContextKeyedService*
 KioskAppUpdateServiceFactory::BuildServiceInstanceFor(
-    content::BrowserContext* profile) const {
-  return new KioskAppUpdateService(static_cast<Profile*>(profile));
+    content::BrowserContext* context) const {
+  return new KioskAppUpdateService(
+      Profile::FromBrowserContext(context),
+      g_browser_process->platform_part()->automatic_reboot_manager());
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_update_service.h b/chrome/browser/chromeos/app_mode/kiosk_app_update_service.h
index 7421a81..8de4589 100644
--- a/chrome/browser/chromeos/app_mode/kiosk_app_update_service.h
+++ b/chrome/browser/chromeos/app_mode/kiosk_app_update_service.h
@@ -10,7 +10,8 @@
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "base/memory/singleton.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
+#include "chrome/browser/chromeos/system/automatic_reboot_manager_observer.h"
 #include "chrome/browser/extensions/update_observer.h"
 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
 #include "components/browser_context_keyed_service/browser_context_keyed_service_factory.h"
@@ -19,34 +20,48 @@
 
 namespace chromeos {
 
+namespace system {
+class AutomaticRebootManager;
+}
+
 // This class enforces automatic restart on app and Chrome updates in app mode.
 class KioskAppUpdateService : public BrowserContextKeyedService,
-                              public extensions::UpdateObserver {
+                              public extensions::UpdateObserver,
+                              public system::AutomaticRebootManagerObserver {
  public:
-  explicit KioskAppUpdateService(Profile* profile);
+  KioskAppUpdateService(
+      Profile* profile,
+      system::AutomaticRebootManager* automatic_reboot_manager);
   virtual ~KioskAppUpdateService();
 
   void set_app_id(const std::string& app_id) { app_id_ = app_id; }
   std::string get_app_id() const { return app_id_; }
 
  private:
-  void StartRestartTimer();
-  void ForceRestart();
+  friend class KioskAppUpdateServiceTest;
+
+  void StartAppUpdateRestartTimer();
+  void ForceAppUpdateRestart();
+
+  // BrowserContextKeyedService overrides:
+  virtual void Shutdown() OVERRIDE;
 
   // extensions::UpdateObserver overrides:
   virtual void OnAppUpdateAvailable(const std::string& app_id) OVERRIDE;
   virtual void OnChromeUpdateAvailable() OVERRIDE {}
 
-  // BrowserContextKeyedService overrides:
-  virtual void Shutdown() OVERRIDE;
+  // system::AutomaticRebootManagerObserver overrides:
+  virtual void OnRebootScheduled(Reason reason) OVERRIDE;
+  virtual void WillDestroyAutomaticRebootManager() OVERRIDE;
 
- private:
   Profile* profile_;
   std::string app_id_;
 
   // After we detect an upgrade we start a one-short timer to force restart.
   base::OneShotTimer<KioskAppUpdateService> restart_timer_;
 
+  system::AutomaticRebootManager* automatic_reboot_manager_;  // Not owned.
+
   DISALLOW_COPY_AND_ASSIGN(KioskAppUpdateService);
 };
 
diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_update_service_browsertest.cc b/chrome/browser/chromeos/app_mode/kiosk_app_update_service_browsertest.cc
new file mode 100644
index 0000000..f37386d
--- /dev/null
+++ b/chrome/browser/chromeos/app_mode/kiosk_app_update_service_browsertest.cc
@@ -0,0 +1,118 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/command_line.h"
+#include "base/compiler_specific.h"
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/path_service.h"
+#include "base/prefs/pref_service.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/test/scoped_path_override.h"
+#include "base/threading/sequenced_worker_pool.h"
+#include "base/time/time.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/browser_process_platform_part.h"
+#include "chrome/browser/chromeos/app_mode/kiosk_app_update_service.h"
+#include "chrome/browser/chromeos/system/automatic_reboot_manager.h"
+#include "chrome/browser/extensions/extension_test_message_listener.h"
+#include "chrome/browser/extensions/platform_app_browsertest_util.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/pref_names.h"
+#include "chromeos/chromeos_paths.h"
+#include "chromeos/dbus/update_engine_client.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/test/test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromeos {
+
+class KioskAppUpdateServiceTest : public extensions::PlatformAppBrowserTest {
+ public:
+  KioskAppUpdateServiceTest() : app_(NULL), update_service_(NULL) {}
+  virtual ~KioskAppUpdateServiceTest() {}
+
+  // extensions::PlatformAppBrowserTest overrides:
+  virtual void SetUpOnMainThread() OVERRIDE {
+    extensions::PlatformAppBrowserTest::SetUpOnMainThread();
+
+    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+    const base::FilePath& temp_dir = temp_dir_.path();
+
+    const base::TimeDelta uptime = base::TimeDelta::FromHours(1);
+    const std::string uptime_seconds =
+        base::DoubleToString(uptime.InSecondsF());
+    const base::FilePath uptime_file = temp_dir.Append("uptime");
+    ASSERT_EQ(static_cast<int>(uptime_seconds.size()),
+              file_util::WriteFile(
+                  uptime_file, uptime_seconds.c_str(), uptime_seconds.size()));
+    uptime_file_override_.reset(
+        new base::ScopedPathOverride(chromeos::FILE_UPTIME, uptime_file));
+
+    app_ = LoadExtension(
+        test_data_dir_.AppendASCII("api_test/runtime/on_restart_required"));
+
+    // Fake app mode command line.
+    CommandLine* command = CommandLine::ForCurrentProcess();
+    command->AppendSwitch(switches::kForceAppMode);
+    command->AppendSwitchASCII(switches::kAppId, app_->id());
+
+    update_service_ = KioskAppUpdateServiceFactory::GetForProfile(profile());
+    update_service_->set_app_id(app_->id());
+
+    content::BrowserThread::GetBlockingPool()->FlushForTesting();
+    content::RunAllPendingInMessageLoop();
+  }
+
+  void FireAppUpdateAvailable() {
+    update_service_->OnAppUpdateAvailable(app_->id());
+  }
+
+  void FireUpdatedNeedReboot() {
+    UpdateEngineClient::Status status;
+    status.status = UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT;
+    g_browser_process->platform_part()->automatic_reboot_manager()->
+        UpdateStatusChanged(status);
+  }
+
+ private:
+  base::ScopedTempDir temp_dir_;
+  scoped_ptr<base::ScopedPathOverride> uptime_file_override_;
+  const extensions::Extension* app_;  // Not owned.
+  KioskAppUpdateService* update_service_;  // Not owned.
+
+  DISALLOW_COPY_AND_ASSIGN(KioskAppUpdateServiceTest);
+};
+
+IN_PROC_BROWSER_TEST_F(KioskAppUpdateServiceTest, AppUpdate) {
+  FireAppUpdateAvailable();
+
+  ExtensionTestMessageListener listener("app_update", false);
+  listener.WaitUntilSatisfied();
+}
+
+IN_PROC_BROWSER_TEST_F(KioskAppUpdateServiceTest, OsUpdate) {
+  g_browser_process->local_state()->SetBoolean(prefs::kRebootAfterUpdate, true);
+  FireUpdatedNeedReboot();
+
+  ExtensionTestMessageListener listener("os_update", false);
+  listener.WaitUntilSatisfied();
+}
+
+IN_PROC_BROWSER_TEST_F(KioskAppUpdateServiceTest, Periodic) {
+  g_browser_process->local_state()->SetInteger(
+      prefs::kUptimeLimit, base::TimeDelta::FromMinutes(30).InSeconds());
+
+  ExtensionTestMessageListener listener("periodic", false);
+  listener.WaitUntilSatisfied();
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/app_mode/startup_app_launcher.cc b/chrome/browser/chromeos/app_mode/startup_app_launcher.cc
index 0dd80fe..b1d38b4 100644
--- a/chrome/browser/chromeos/app_mode/startup_app_launcher.cc
+++ b/chrome/browser/chromeos/app_mode/startup_app_launcher.cc
@@ -9,7 +9,7 @@
 #include "base/files/file_path.h"
 #include "base/json/json_file_value_serializer.h"
 #include "base/path_service.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/chromeos/app_mode/app_session_lifetime.h"
 #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
diff --git a/chrome/browser/chromeos/app_mode/startup_app_launcher.h b/chrome/browser/chromeos/app_mode/startup_app_launcher.h
index 8d63387..a4bc841 100644
--- a/chrome/browser/chromeos/app_mode/startup_app_launcher.h
+++ b/chrome/browser/chromeos/app_mode/startup_app_launcher.h
@@ -10,7 +10,7 @@
 #include "base/basictypes.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/chromeos/app_mode/kiosk_app_launch_error.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
diff --git a/chrome/browser/chromeos/attestation/attestation_policy_observer.cc b/chrome/browser/chromeos/attestation/attestation_policy_observer.cc
index 37a7a0b..7028f5c 100644
--- a/chrome/browser/chromeos/attestation/attestation_policy_observer.cc
+++ b/chrome/browser/chromeos/attestation/attestation_policy_observer.cc
@@ -9,7 +9,7 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/location.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/chromeos/attestation/attestation_ca_client.h"
 #include "chrome/browser/chromeos/attestation/attestation_key_payload.pb.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
@@ -35,6 +35,8 @@
 // been set large enough so that the majority of users will have gone through
 // a full sign-in during the period.
 const int kExpiryThresholdInDays = 30;
+const int kRetryDelay = 5;  // Seconds.
+const int kRetryLimit = 100;
 
 // A dbus callback which handles a boolean result.
 //
@@ -45,12 +47,15 @@
 //   value - The value returned by the dbus operation.
 void DBusBoolRedirectCallback(const base::Closure& on_true,
                               const base::Closure& on_false,
+                              const base::Closure& on_failure,
                               const tracked_objects::Location& from_here,
                               chromeos::DBusMethodCallStatus status,
                               bool value) {
   if (status != chromeos::DBUS_METHOD_CALL_SUCCESS) {
     LOG(ERROR) << "Cryptohome DBus method failed: " << from_here.ToString()
                << " - " << status;
+    if (!on_failure.is_null())
+      on_failure.Run();
     return;
   }
   const base::Closure& task = value ? on_true : on_false;
@@ -67,6 +72,7 @@
 //   data - The data returned by the dbus operation.
 void DBusStringCallback(
     const base::Callback<void(const std::string&)> on_success,
+    const base::Closure& on_failure,
     const tracked_objects::Location& from_here,
     chromeos::DBusMethodCallStatus status,
     bool result,
@@ -74,6 +80,8 @@
   if (status != chromeos::DBUS_METHOD_CALL_SUCCESS || !result) {
     LOG(ERROR) << "Cryptohome DBus method failed: " << from_here.ToString()
                << " - " << status << " - " << result;
+    if (!on_failure.is_null())
+      on_failure.Run();
     return;
   }
   on_success.Run(data);
@@ -90,6 +98,8 @@
       policy_client_(policy_client),
       cryptohome_client_(NULL),
       attestation_flow_(NULL),
+      num_retries_(0),
+      retry_delay_(kRetryDelay),
       weak_factory_(this) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
   cros_settings_->AddSettingsObserver(kDeviceAttestationEnabled, this);
@@ -104,6 +114,8 @@
       policy_client_(policy_client),
       cryptohome_client_(cryptohome_client),
       attestation_flow_(attestation_flow),
+      num_retries_(0),
+      retry_delay_(kRetryDelay),
       weak_factory_(this) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
   cros_settings_->AddSettingsObserver(kDeviceAttestationEnabled, this);
@@ -126,6 +138,7 @@
     LOG(WARNING) << "AttestationPolicyObserver: Unexpected event received.";
     return;
   }
+  num_retries_ = 0;
   Start();
 }
 
@@ -167,6 +180,8 @@
       base::Bind(DBusBoolRedirectCallback,
                  on_does_exist,
                  on_does_not_exist,
+                 base::Bind(&AttestationPolicyObserver::Reschedule,
+                            weak_factory_.GetWeakPtr()),
                  FROM_HERE));
 }
 
@@ -178,6 +193,8 @@
       base::Bind(DBusStringCallback,
                  base::Bind(&AttestationPolicyObserver::UploadCertificate,
                             weak_factory_.GetWeakPtr()),
+                 base::Bind(&AttestationPolicyObserver::Reschedule,
+                            weak_factory_.GetWeakPtr()),
                  FROM_HERE,
                  DBUS_METHOD_CALL_SUCCESS));
 }
@@ -189,6 +206,8 @@
       base::Bind(DBusStringCallback,
                  base::Bind(&AttestationPolicyObserver::CheckCertificateExpiry,
                             weak_factory_.GetWeakPtr()),
+                 base::Bind(&AttestationPolicyObserver::Reschedule,
+                            weak_factory_.GetWeakPtr()),
                  FROM_HERE));
 }
 
@@ -241,12 +260,17 @@
   cryptohome_client_->TpmAttestationGetKeyPayload(
       KEY_DEVICE,
       kEnterpriseMachineKey,
-      base::Bind(DBusStringCallback, callback, FROM_HERE));
+      base::Bind(DBusStringCallback,
+                 callback,
+                 base::Bind(&AttestationPolicyObserver::Reschedule,
+                            weak_factory_.GetWeakPtr()),
+                 FROM_HERE));
 }
 
 void AttestationPolicyObserver::OnUploadComplete(bool status) {
   if (!status)
     return;
+  LOG(INFO) << "Enterprise Machine Certificate uploaded to DMServer.";
   GetKeyPayload(base::Bind(&AttestationPolicyObserver::MarkAsUploaded,
                            weak_factory_.GetWeakPtr()));
 }
@@ -268,8 +292,21 @@
       base::Bind(DBusBoolRedirectCallback,
                  base::Closure(),
                  base::Closure(),
+                 base::Closure(),
                  FROM_HERE));
 }
 
+void AttestationPolicyObserver::Reschedule() {
+  if (++num_retries_ < kRetryLimit) {
+    content::BrowserThread::PostDelayedTask(
+        content::BrowserThread::UI, FROM_HERE,
+        base::Bind(&AttestationPolicyObserver::Start,
+                   weak_factory_.GetWeakPtr()),
+        base::TimeDelta::FromSeconds(retry_delay_));
+  } else {
+    LOG(WARNING) << "AttestationPolicyObserver: Retry limit exceeded.";
+  }
+}
+
 }  // namespace attestation
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/attestation/attestation_policy_observer.h b/chrome/browser/chromeos/attestation/attestation_policy_observer.h
index 1ae4e50..1f78971 100644
--- a/chrome/browser/chromeos/attestation/attestation_policy_observer.h
+++ b/chrome/browser/chromeos/attestation/attestation_policy_observer.h
@@ -50,6 +50,11 @@
                        const content::NotificationSource& source,
                        const content::NotificationDetails& details) OVERRIDE;
 
+  // Sets the retry delay in seconds; useful in testing.
+  void set_retry_delay(int retry_delay) {
+    retry_delay_ = retry_delay;
+  }
+
  private:
   // Checks attestation policy and starts any necessary work.
   void Start();
@@ -80,11 +85,18 @@
   // Marks a key as uploaded in the payload proto.
   void MarkAsUploaded(const std::string& key_payload);
 
+  // Reschedules a policy check (i.e. a call to Start) for a later time.
+  // TODO(dkrahn): A better solution would be to wait for a dbus signal which
+  // indicates the system is ready to process this task. See crbug.com/256845.
+  void Reschedule();
+
   CrosSettings* cros_settings_;
   policy::CloudPolicyClient* policy_client_;
   CryptohomeClient* cryptohome_client_;
   AttestationFlow* attestation_flow_;
   scoped_ptr<AttestationFlow> default_attestation_flow_;
+  int num_retries_;
+  int retry_delay_;
 
   // Note: This should remain the last member so it'll be destroyed and
   // invalidate the weak pointers before any other members are destroyed.
diff --git a/chrome/browser/chromeos/attestation/attestation_policy_observer_unittest.cc b/chrome/browser/chromeos/attestation/attestation_policy_observer_unittest.cc
index 19ef480..dd0a070 100644
--- a/chrome/browser/chromeos/attestation/attestation_policy_observer_unittest.cc
+++ b/chrome/browser/chromeos/attestation/attestation_policy_observer_unittest.cc
@@ -19,7 +19,7 @@
 #include "content/public/test/test_browser_thread.h"
 #include "crypto/rsa_private_key.h"
 #include "net/cert/x509_certificate.h"
-#include "net/cert/x509_util_nss.h"
+#include "net/cert/x509_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using testing::_;
@@ -75,6 +75,11 @@
       FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
 }
 
+void DBusCallbackError(const BoolDBusMethodCallback& callback) {
+  base::MessageLoop::current()->PostTask(
+      FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_FAILURE, false));
+}
+
 void CertCallbackSuccess(const AttestationFlow::CertificateCallback& callback) {
   base::MessageLoop::current()->PostTask(
       FROM_HERE, base::Bind(callback, true, "fake_cert"));
@@ -187,6 +192,7 @@
     AttestationPolicyObserver observer(&policy_client_,
                                        &cryptohome_client_,
                                        &attestation_flow_);
+    observer.set_retry_delay(0);
     base::RunLoop().RunUntilIdle();
   }
 
@@ -220,19 +226,12 @@
                                &kTestKeyData[arraysize(kTestKeyData)])));
     if (!test_key.get())
       return false;
-    net::X509Certificate::OSCertHandle handle =
-        net::x509_util::CreateSelfSignedCert(test_key->public_key(),
-                                             test_key->key(),
-                                             "CN=subject",
-                                             12345,
-                                             valid_start,
-                                             valid_expiry);
-
-    if (!handle)
-      return false;
-    bool result = net::X509Certificate::GetDEREncoded(handle, certificate);
-    net::X509Certificate::FreeOSCertHandle(handle);
-    return result;
+    return net::x509_util::CreateSelfSignedCert(test_key.get(),
+                                                "CN=subject",
+                                                12345,
+                                                valid_start,
+                                                valid_expiry,
+                                                certificate);
   }
 
   base::MessageLoop message_loop_;
@@ -295,5 +294,14 @@
   Run();
 }
 
+TEST_F(AttestationPolicyObserverTest, DBusFailureRetry) {
+  SetupMocks(MOCK_NEW_KEY, "");
+  // Simulate a DBus failure.
+  EXPECT_CALL(cryptohome_client_, TpmAttestationDoesKeyExist(_, _, _))
+      .WillOnce(WithArgs<2>(Invoke(DBusCallbackError)))
+      .WillRepeatedly(WithArgs<2>(Invoke(DBusCallbackFalse)));
+  Run();
+}
+
 }  // namespace attestation
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/audio/audio_devices_pref_handler_impl.cc b/chrome/browser/chromeos/audio/audio_devices_pref_handler_impl.cc
index 2fc83e3..b43afdb 100644
--- a/chrome/browser/chromeos/audio/audio_devices_pref_handler_impl.cc
+++ b/chrome/browser/chromeos/audio/audio_devices_pref_handler_impl.cc
@@ -15,15 +15,25 @@
 #include "chrome/browser/prefs/scoped_user_pref_update.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "chrome/common/pref_names.h"
+#include "chromeos/audio/audio_device.h"
 #include "chromeos/audio/cras_audio_handler.h"
 
+namespace {
+
+std::string GetDeviceIdString(const chromeos::AudioDevice& device) {
+  return device.display_name + " : " +
+         base::Uint64ToString(device.id & static_cast<uint64>(0xffffffff));
+}
+
+}
+
 namespace chromeos {
 
 double AudioDevicesPrefHandlerImpl::GetVolumeGainValue(
-    uint64 device_id) {
+    const AudioDevice& device) {
   UpdateDevicesVolumePref();
 
-  std::string device_id_str = base::Uint64ToString(device_id);
+  std::string device_id_str = GetDeviceIdString(device);
   if (!device_volume_settings_->HasKey(device_id_str))
     MigrateDeviceVolumeSettings(device_id_str);
 
@@ -34,17 +44,17 @@
 }
 
 void AudioDevicesPrefHandlerImpl::SetVolumeGainValue(
-    uint64 device_id, double value) {
+    const AudioDevice& device, double value) {
   value = std::min(std::max(value, 0.0), 100.0);
-  device_volume_settings_->SetDouble(base::Uint64ToString(device_id), value);
+  device_volume_settings_->SetDouble(GetDeviceIdString(device), value);
 
   SaveDevicesVolumePref();
 }
 
-bool AudioDevicesPrefHandlerImpl::GetMuteValue(uint64 device_id) {
+bool AudioDevicesPrefHandlerImpl::GetMuteValue(const AudioDevice& device) {
   UpdateDevicesMutePref();
 
-  std::string device_id_str = base::Uint64ToString(device_id);
+  std::string device_id_str = GetDeviceIdString(device);
   if (!device_mute_settings_->HasKey(device_id_str))
     MigrateDeviceMuteSettings(device_id_str);
 
@@ -54,9 +64,9 @@
   return (mute == kPrefMuteOn);
 }
 
-void AudioDevicesPrefHandlerImpl::SetMuteValue(uint64 device_id,
+void AudioDevicesPrefHandlerImpl::SetMuteValue(const AudioDevice& device,
                                                bool mute) {
-  device_mute_settings_->SetInteger(base::Uint64ToString(device_id),
+  device_mute_settings_->SetInteger(GetDeviceIdString(device),
                                     mute ? kPrefMuteOn : kPrefMuteOff);
   SaveDevicesMutePref();
 }
diff --git a/chrome/browser/chromeos/audio/audio_devices_pref_handler_impl.h b/chrome/browser/chromeos/audio/audio_devices_pref_handler_impl.h
index e596a1f..1a46dcf 100644
--- a/chrome/browser/chromeos/audio/audio_devices_pref_handler_impl.h
+++ b/chrome/browser/chromeos/audio/audio_devices_pref_handler_impl.h
@@ -22,11 +22,12 @@
   explicit AudioDevicesPrefHandlerImpl(PrefService* local_state);
 
   // Overridden from AudioDevicesPrefHandler.
-  virtual double GetVolumeGainValue(uint64 device_id) OVERRIDE;
-  virtual void SetVolumeGainValue(uint64 device_id, double value) OVERRIDE;
+  virtual double GetVolumeGainValue(const AudioDevice& device) OVERRIDE;
+  virtual void SetVolumeGainValue(const AudioDevice& device,
+                                  double value) OVERRIDE;
 
-  virtual bool GetMuteValue(uint64 device_id) OVERRIDE;
-  virtual void SetMuteValue(uint64 device_id, bool mute_on) OVERRIDE;
+  virtual bool GetMuteValue(const AudioDevice& device) OVERRIDE;
+  virtual void SetMuteValue(const AudioDevice& device, bool mute_on) OVERRIDE;
 
   virtual bool GetAudioCaptureAllowedValue() OVERRIDE;
   virtual bool GetAudioOutputAllowedValue() OVERRIDE;
diff --git a/chrome/browser/chromeos/boot_times_loader.cc b/chrome/browser/chromeos/boot_times_loader.cc
index 7522d61..a9919ae 100644
--- a/chrome/browser/chromeos/boot_times_loader.cc
+++ b/chrome/browser/chromeos/boot_times_loader.cc
@@ -21,7 +21,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_restrictions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/login/authentication_notification_details.h"
 #include "chrome/browser/ui/browser.h"
diff --git a/chrome/browser/chromeos/boot_times_loader.h b/chrome/browser/chromeos/boot_times_loader.h
index dc420e8..2312a57 100644
--- a/chrome/browser/chromeos/boot_times_loader.h
+++ b/chrome/browser/chromeos/boot_times_loader.h
@@ -11,7 +11,7 @@
 #include "base/atomic_sequence_num.h"
 #include "base/callback_forward.h"
 #include "base/compiler_specific.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/common/cancelable_task_tracker.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
index d34fd61..834916c 100644
--- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
+++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -21,8 +21,6 @@
 #include "base/prefs/pref_service.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
-#include "base/time/default_tick_clock.h"
-#include "base/time/tick_clock.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_process_platform_part_chromeos.h"
 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
@@ -72,7 +70,7 @@
 #include "chrome/browser/chromeos/settings/device_oauth2_token_service_factory.h"
 #include "chrome/browser/chromeos/settings/device_settings_service.h"
 #include "chrome/browser/chromeos/settings/owner_key_util.h"
-#include "chrome/browser/chromeos/system/automatic_reboot_manager.h"
+#include "chrome/browser/chromeos/swap_metrics.h"
 #include "chrome/browser/chromeos/system/device_change_handler.h"
 #include "chrome/browser/chromeos/system/statistics_provider.h"
 #include "chrome/browser/chromeos/system_key_event_listener.h"
@@ -101,7 +99,6 @@
 #include "chromeos/cryptohome/async_method_caller.h"
 #include "chromeos/cryptohome/cryptohome_library.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/power_manager_client.h"
 #include "chromeos/dbus/session_manager_client.h"
 #include "chromeos/disks/disk_mount_manager.h"
 #include "chromeos/ime/input_method_manager.h"
@@ -110,7 +107,6 @@
 #include "chromeos/network/network_change_notifier_chromeos.h"
 #include "chromeos/network/network_change_notifier_factory_chromeos.h"
 #include "chromeos/network/network_handler.h"
-#include "chromeos/power/power_manager_handler.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/power_save_blocker.h"
@@ -120,6 +116,11 @@
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_context_getter.h"
 
+// Exclude X11 dependents for ozone
+#if defined(USE_X11)
+#include "chrome/browser/chromeos/device_uma.h"
+#endif
+
 namespace chromeos {
 
 namespace {
@@ -385,6 +386,8 @@
   if (KioskModeSettings::Get()->IsKioskModeEnabled())
     ShutdownKioskModeScreensaver();
 
+  dbus_services_.reset();
+
   // To be precise, logout (browser shutdown) is not yet done, but the
   // remaining work is negligible, hence we say LogoutDone here.
   BootTimesLoader::Get()->AddLogoutTimeMarker("LogoutDone", false);
@@ -460,11 +463,6 @@
 // Threads are initialized between MainMessageLoopStart and MainMessageLoopRun.
 // about_flags settings are applied in ChromeBrowserMainParts::PreCreateThreads.
 void ChromeBrowserMainPartsChromeos::PreMainMessageLoopRun() {
-  // Set the crypto thread after the IO thread has been created/started.
-  NetworkHandler::Get()->cert_loader()->SetCryptoTaskRunner(
-      content::BrowserThread::GetMessageLoopProxyForThread(
-          content::BrowserThread::IO));
-
   if (ash::switches::UseNewAudioHandler()) {
     CrasAudioHandler::Initialize(
         AudioDevicesPrefHandler::Create(g_browser_process->local_state()));
@@ -473,8 +471,6 @@
        AudioPrefHandler::Create(g_browser_process->local_state()));
   }
 
-  PowerManagerHandler::Initialize();
-
   if (!StartupUtils::IsOobeCompleted())
     system::StatisticsProvider::GetInstance()->LoadOemManifest();
 
@@ -542,18 +538,10 @@
   //   2) if passed alone, to signal that the indicated user has already
   //      logged in and we should behave accordingly.
   // This handles case 2.
-  if (parsed_command_line().HasSwitch(switches::kLoginUser) &&
-      !parsed_command_line().HasSwitch(switches::kLoginPassword)) {
-    std::string username =
-        parsed_command_line().GetSwitchValueASCII(switches::kLoginUser);
-    UserManager* user_manager = UserManager::Get();
-    // In case of multi-profiles --login-profile will contain user_id_hash.
-    std::string username_hash =
-        parsed_command_line().GetSwitchValueASCII(switches::kLoginProfile);
-    user_manager->UserLoggedIn(username, username_hash, true);
-    VLOG(1) << "Relaunching browser for user: " << username
-            << " with hash: " << username_hash;
-
+  bool immediate_login =
+      parsed_command_line().HasSwitch(switches::kLoginUser) &&
+      !parsed_command_line().HasSwitch(switches::kLoginPassword);
+  if (immediate_login){
     // Redirects Chrome logging to the user data dir.
     logging::RedirectChromeLogging(parsed_command_line());
 
@@ -594,6 +582,18 @@
 
   // In Aura builds this will initialize ash::Shell.
   ChromeBrowserMainPartsLinux::PreProfileInit();
+
+  if (immediate_login) {
+    std::string username =
+        parsed_command_line().GetSwitchValueASCII(switches::kLoginUser);
+    UserManager* user_manager = UserManager::Get();
+    // In case of multi-profiles --login-profile will contain user_id_hash.
+    std::string username_hash =
+        parsed_command_line().GetSwitchValueASCII(switches::kLoginProfile);
+    user_manager->UserLoggedIn(username, username_hash, true);
+    VLOG(1) << "Relaunching browser for user: " << username
+            << " with hash: " << username_hash;
+  }
 }
 
 void ChromeBrowserMainPartsChromeos::PostProfileInit() {
@@ -632,11 +632,6 @@
     UserManager::Get()->RestoreActiveSessions();
   }
 
-  // Make sure the NetworkConfigurationUpdater is ready so that it pushes ONC
-  // configuration before login.
-  g_browser_process->browser_policy_connector()->
-      GetNetworkConfigurationUpdater();
-
   // Start loading the machine statistics. Note: if we start loading machine
   // statistics early in PreEarlyInitialization() then the crossystem tool
   // sometimes hangs for unknown reasons, see http://crbug.com/167671.
@@ -697,8 +692,7 @@
   display_configuration_observer_.reset(
       new DisplayConfigurationObserver());
 
-  automatic_reboot_manager_.reset(new system::AutomaticRebootManager(
-      scoped_ptr<base::TickClock>(new base::DefaultTickClock)));
+  g_browser_process->platform_part()->InitializeAutomaticRebootManager();
 
   // This observer cannot be created earlier because it requires the shell to be
   // available.
@@ -721,9 +715,18 @@
   // reasons, see http://crosbug.com/24833.
   XInputHierarchyChangedEventListener::GetInstance();
 
+#if defined(USE_X11)
+  // Start the CrOS input device UMA watcher
+  DeviceUMA::GetInstance();
+#endif
+
   // -- This used to be in ChromeBrowserMainParts::PreMainMessageLoopRun()
   // -- immediately after ChildProcess::WaitForDebugger().
 
+  // Swap metrics watcher must be installed before browser is activated.
+  if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoSwapMetrics))
+    swap_metrics_.reset(new SwapMetrics);
+
   // Start the out-of-memory priority manager here so that we give the most
   // amount of time for the other services to start up before we start
   // adjusting the oom priority.
@@ -748,6 +751,8 @@
 
   g_browser_process->platform_part()->oom_priority_manager()->Stop();
 
+  swap_metrics_.reset();
+
   // Stops LoginUtils background fetchers. This is needed because IO thread is
   // going to stop soon after this function. The pending background jobs could
   // cause it to crash during shutdown.
@@ -791,6 +796,10 @@
   // Singletons are finally destroyed in AtExitManager.
   XInputHierarchyChangedEventListener::GetInstance()->Stop();
 
+#if defined(USE_X11)
+  DeviceUMA::GetInstance()->Stop();
+#endif
+
   // SystemKeyEventListener::Shutdown() is always safe to call,
   // even if Initialize() wasn't called.
   SystemKeyEventListener::Shutdown();
@@ -801,8 +810,6 @@
     AudioHandler::Shutdown();
   }
 
-  PowerManagerHandler::Shutdown();
-
   WebSocketProxyController::Shutdown();
 
   // Let classes unregister themselves as observers of the ash::Shell singleton
@@ -830,7 +837,7 @@
 
   // Let the AutomaticRebootManager unregister itself as an observer of several
   // subsystems.
-  automatic_reboot_manager_.reset();
+  g_browser_process->platform_part()->ShutdownAutomaticRebootManager();
 
   // Clean up dependency on CrosSettings and stop pending data fetches.
   KioskAppManager::Shutdown();
@@ -845,62 +852,13 @@
 }
 
 void ChromeBrowserMainPartsChromeos::PostDestroyThreads() {
-  // Destroy DBus services immediately after threads are stopped.
-  dbus_services_.reset();
-
   ChromeBrowserMainPartsLinux::PostDestroyThreads();
-
   // Destroy DeviceSettingsService after g_browser_process.
   DeviceSettingsService::Shutdown();
 }
 
 void ChromeBrowserMainPartsChromeos::SetupPlatformFieldTrials() {
-  SetupZramFieldTrial();
   default_pinned_apps_field_trial::SetupTrial();
 }
 
-void ChromeBrowserMainPartsChromeos::SetupZramFieldTrial() {
-  // The dice for this experiment have been thrown at boot.  The selected group
-  // number is stored in a file.
-  const base::FilePath kZramGroupPath("/home/chronos/.swap_exp_enrolled");
-  std::string zram_file_content;
-  // If the file does not exist, the experiment has not started.
-  if (!file_util::ReadFileToString(kZramGroupPath, &zram_file_content))
-    return;
-  // The file contains a single significant character, possibly followed by
-  // newline.  "x" means the user has opted out.  "0" through "8" are the valid
-  // group names.  (See src/platform/init/swap-exp.conf in chromiumos repo for
-  // group meanings.)
-  if (zram_file_content.empty()) {
-    LOG(WARNING) << "zram field trial: " << kZramGroupPath.value()
-                 << " is empty";
-    return;
-  }
-  char zram_group = zram_file_content[0];
-  if (zram_group == 'x')
-    return;
-  if (zram_group < '0' || zram_group > '8') {
-    LOG(WARNING) << "zram field trial: invalid group \"" << zram_group << "\"";
-    return;
-  }
-  LOG(WARNING) << "zram field trial: group " << zram_group;
-  const base::FieldTrial::Probability kDivisor = 1;  // on/off only
-  scoped_refptr<base::FieldTrial> trial =
-      base::FieldTrialList::FactoryGetFieldTrial(
-          "ZRAM", kDivisor, "default", 2013, 12, 31, NULL);
-  // Assign probability of 1 to the group Chrome OS has picked.  Assign 0 to
-  // all other choices.
-  trial->AppendGroup("2GB_RAM_no_swap", zram_group == '0' ? 1 : 0);
-  trial->AppendGroup("2GB_RAM_2GB_swap", zram_group == '1' ? 1 : 0);
-  trial->AppendGroup("2GB_RAM_3GB_swap", zram_group == '2' ? 1 : 0);
-  trial->AppendGroup("4GB_RAM_no_swap", zram_group == '3' ? 1 : 0);
-  trial->AppendGroup("4GB_RAM_4GB_swap", zram_group == '4' ? 1 : 0);
-  trial->AppendGroup("4GB_RAM_6GB_swap", zram_group == '5' ? 1 : 0);
-  trial->AppendGroup("snow_no_swap", zram_group == '6' ? 1 : 0);
-  trial->AppendGroup("snow_1GB_swap", zram_group == '7' ? 1 : 0);
-  trial->AppendGroup("snow_2GB_swap", zram_group == '8' ? 1 : 0);
-  // This is necessary to start the experiment as a side effect.
-  trial->group();
-}
-
 }  //  namespace chromeos
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.h b/chrome/browser/chromeos/chrome_browser_main_chromeos.h
index 8739e44..fbcba38 100644
--- a/chrome/browser/chromeos/chrome_browser_main_chromeos.h
+++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.h
@@ -32,6 +32,7 @@
 class SessionManagerObserver;
 class StorageMonitorCros;
 class SuspendObserver;
+class SwapMetrics;
 class UserActivityNotifier;
 class VideoActivityNotifier;
 
@@ -44,7 +45,6 @@
 }
 
 namespace system {
-class AutomaticRebootManager;
 class DeviceChangeHandler;
 }
 
@@ -72,8 +72,6 @@
   virtual void SetupPlatformFieldTrials() OVERRIDE;
 
  private:
-  void SetupZramFieldTrial();
-
   scoped_ptr<contacts::ContactManager> contact_manager_;
   scoped_ptr<BrightnessObserver> brightness_observer_;
   scoped_ptr<DisplayConfigurationObserver> display_configuration_observer_;
@@ -88,9 +86,9 @@
   scoped_ptr<UserActivityNotifier> user_activity_notifier_;
   scoped_ptr<VideoActivityNotifier> video_activity_notifier_;
   scoped_ptr<StorageMonitorCros> storage_monitor_;
-  scoped_ptr<system::AutomaticRebootManager> automatic_reboot_manager_;
   scoped_ptr<IdleActionWarningObserver> idle_action_warning_observer_;
   scoped_ptr<system::DeviceChangeHandler> device_change_handler_;
+  scoped_ptr<SwapMetrics> swap_metrics_;
 
   scoped_ptr<internal::DBusServices> dbus_services_;
 
diff --git a/chrome/browser/chromeos/contacts/contact_database.cc b/chrome/browser/chromeos/contacts/contact_database.cc
index 0b1193f..cfff9b2 100644
--- a/chrome/browser/chromeos/contacts/contact_database.cc
+++ b/chrome/browser/chromeos/contacts/contact_database.cc
@@ -175,7 +175,7 @@
 
   VLOG(1) << "Opening " << database_dir.value();
   UMA_HISTOGRAM_MEMORY_KB("Contacts.DatabaseSizeBytes",
-                          file_util::ComputeDirectorySize(database_dir));
+                          base::ComputeDirectorySize(database_dir));
   *success = false;
   HistogramInitResult histogram_result = HISTOGRAM_INIT_RESULT_SUCCESS;
 
@@ -200,7 +200,7 @@
     // Delete the existing database and try again (just once, though).
     if (status.IsCorruption() && delete_and_retry_on_corruption) {
       LOG(WARNING) << "Deleting possibly-corrupt database";
-      file_util::Delete(database_dir, true);
+      base::Delete(database_dir, true);
       delete_and_retry_on_corruption = false;
       histogram_result = HISTOGRAM_INIT_RESULT_DELETED_CORRUPTED;
     } else {
diff --git a/chrome/browser/chromeos/contacts/contact_map.h b/chrome/browser/chromeos/contacts/contact_map.h
index 22de98e..66a8444 100644
--- a/chrome/browser/chromeos/contacts/contact_map.h
+++ b/chrome/browser/chromeos/contacts/contact_map.h
@@ -12,7 +12,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/scoped_vector.h"
 #include "base/stl_util.h"
-#include "base/time.h"
+#include "base/time/time.h"
 
 namespace contacts {
 
diff --git a/chrome/browser/chromeos/contacts/contact_map_unittest.cc b/chrome/browser/chromeos/contacts/contact_map_unittest.cc
index dc7bb96..ebd46e1 100644
--- a/chrome/browser/chromeos/contacts/contact_map_unittest.cc
+++ b/chrome/browser/chromeos/contacts/contact_map_unittest.cc
@@ -6,7 +6,7 @@
 
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/scoped_vector.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/chromeos/contacts/contact.pb.h"
 #include "chrome/browser/chromeos/contacts/contact_test_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/chromeos/contacts/contact_test_util.cc b/chrome/browser/chromeos/contacts/contact_test_util.cc
index 6ef76dc..071083a 100644
--- a/chrome/browser/chromeos/contacts/contact_test_util.cc
+++ b/chrome/browser/chromeos/contacts/contact_test_util.cc
@@ -11,7 +11,7 @@
 #include "base/logging.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/chromeos/contacts/contact_map.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkCanvas.h"
diff --git a/chrome/browser/chromeos/contacts/gdata_contacts_service.cc b/chrome/browser/chromeos/contacts/gdata_contacts_service.cc
index 0d614cb..12e4161 100644
--- a/chrome/browser/chromeos/contacts/gdata_contacts_service.cc
+++ b/chrome/browser/chromeos/contacts/gdata_contacts_service.cc
@@ -16,8 +16,8 @@
 #include "base/metrics/histogram.h"
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "base/values.h"
 #include "chrome/browser/chromeos/contacts/contact.pb.h"
 #include "chrome/browser/google_apis/gdata_contacts_requests.h"
@@ -436,14 +436,12 @@
  public:
   DownloadContactsRequest(
       GDataContactsService* service,
-      google_apis::RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
+      google_apis::RequestSender* sender,
       SuccessCallback success_callback,
       FailureCallback failure_callback,
       const base::Time& min_update_time)
       : service_(service),
-        sender_(runner),
-        url_request_context_getter_(url_request_context_getter),
+        sender_(sender),
         success_callback_(success_callback),
         failure_callback_(failure_callback),
         min_update_time_(min_update_time),
@@ -481,7 +479,6 @@
       google_apis::GetContactGroupsRequest* operation =
           new google_apis::GetContactGroupsRequest(
               sender_,
-              url_request_context_getter_,
               base::Bind(&DownloadContactsRequest::HandleGroupsFeedData,
                          weak_ptr_factory_.GetWeakPtr()));
       if (!service_->groups_feed_url_for_testing_.is_empty()) {
@@ -589,7 +586,6 @@
     google_apis::GetContactsRequest* operation =
         new google_apis::GetContactsRequest(
             sender_,
-            url_request_context_getter_,
             my_contacts_group_id_,
             min_update_time_,
             base::Bind(&DownloadContactsRequest::HandleContactsFeedData,
@@ -649,7 +645,7 @@
       return false;
     }
     const DictionaryValue* category_dict = NULL;
-    if (!category_list->GetSize() == 1 ||
+    if (category_list->GetSize() != 1 ||
         !category_list->GetDictionary(0, &category_dict)) {
       LOG(WARNING) << "Unable to get dictionary from category list of size "
                    << category_list->GetSize();
@@ -746,7 +742,6 @@
       sender_->StartRequestWithRetry(
           new google_apis::GetContactPhotoRequest(
               sender_,
-              url_request_context_getter_,
               GURL(url),
               base::Bind(&DownloadContactsRequest::HandlePhotoData,
                          weak_ptr_factory_.GetWeakPtr(),
@@ -803,7 +798,6 @@
 
   GDataContactsService* service_;  // not owned
   google_apis::RequestSender* sender_;  // not owned
-  net::URLRequestContextGetter* url_request_context_getter_;  // not owned
 
   SuccessCallback success_callback_;
   FailureCallback failure_callback_;
@@ -857,14 +851,13 @@
 GDataContactsService::GDataContactsService(
     net::URLRequestContextGetter* url_request_context_getter,
     Profile* profile)
-    : url_request_context_getter_(url_request_context_getter),
-      max_photo_downloads_per_second_(kMaxPhotoDownloadsPerSecond),
+    : max_photo_downloads_per_second_(kMaxPhotoDownloadsPerSecond),
       photo_download_timer_interval_(base::TimeDelta::FromSeconds(1)) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   std::vector<std::string> scopes;
   scopes.push_back(kContactsScope);
   sender_.reset(new google_apis::RequestSender(profile,
-                                               url_request_context_getter_,
+                                               url_request_context_getter,
                                                scopes,
                                                "" /* custom_user_agent */));
 }
@@ -891,7 +884,6 @@
   DownloadContactsRequest* request =
       new DownloadContactsRequest(this,
                                   sender_.get(),
-                                  url_request_context_getter_,
                                   success_callback,
                                   failure_callback,
                                   min_update_time);
diff --git a/chrome/browser/chromeos/contacts/gdata_contacts_service.h b/chrome/browser/chromeos/contacts/gdata_contacts_service.h
index 886f48a..47f30ef 100644
--- a/chrome/browser/chromeos/contacts/gdata_contacts_service.h
+++ b/chrome/browser/chromeos/contacts/gdata_contacts_service.h
@@ -13,7 +13,7 @@
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/scoped_vector.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "googleurl/src/gurl.h"
 
 class Profile;
@@ -109,8 +109,6 @@
   // unsuccessfully).
   void OnRequestComplete(DownloadContactsRequest* request);
 
-  net::URLRequestContextGetter* url_request_context_getter_;  // not owned
-
   scoped_ptr<google_apis::RequestSender> sender_;
 
   // Group ID for the "My Contacts" system contacts group.
diff --git a/chrome/browser/chromeos/contacts/gdata_contacts_service_stub.h b/chrome/browser/chromeos/contacts/gdata_contacts_service_stub.h
index bc23a69..0be0213 100644
--- a/chrome/browser/chromeos/contacts/gdata_contacts_service_stub.h
+++ b/chrome/browser/chromeos/contacts/gdata_contacts_service_stub.h
@@ -9,7 +9,7 @@
 
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
-#include "base/time.h"
+#include "base/time/time.h"
 
 namespace contacts {
 typedef std::vector<const contacts::Contact*> ContactPointers;
diff --git a/chrome/browser/chromeos/contacts/gdata_contacts_service_unittest.cc b/chrome/browser/chromeos/contacts/gdata_contacts_service_unittest.cc
index 0ffe075..ac43ff8 100644
--- a/chrome/browser/chromeos/contacts/gdata_contacts_service_unittest.cc
+++ b/chrome/browser/chromeos/contacts/gdata_contacts_service_unittest.cc
@@ -8,7 +8,7 @@
 #include "base/files/file_path.h"
 #include "base/message_loop.h"
 #include "base/strings/stringprintf.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/chromeos/contacts/contact.pb.h"
 #include "chrome/browser/chromeos/contacts/contact_test_util.h"
 #include "chrome/browser/google_apis/auth_service.h"
diff --git a/chrome/browser/chromeos/contacts/google_contact_store.h b/chrome/browser/chromeos/contacts/google_contact_store.h
index b880ea4..8773722 100644
--- a/chrome/browser/chromeos/contacts/google_contact_store.h
+++ b/chrome/browser/chromeos/contacts/google_contact_store.h
@@ -17,8 +17,8 @@
 #include "base/memory/scoped_vector.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/chromeos/contacts/contact_map.h"
 #include "net/base/network_change_notifier.h"
 
diff --git a/chrome/browser/chromeos/contacts/google_contact_store_unittest.cc b/chrome/browser/chromeos/contacts/google_contact_store_unittest.cc
index 377ce35..de42453 100644
--- a/chrome/browser/chromeos/contacts/google_contact_store_unittest.cc
+++ b/chrome/browser/chromeos/contacts/google_contact_store_unittest.cc
@@ -7,7 +7,7 @@
 #include "base/bind.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/message_loop.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/chromeos/contacts/contact.pb.h"
 #include "chrome/browser/chromeos/contacts/contact_store_observer.h"
 #include "chrome/browser/chromeos/contacts/contact_test_util.h"
diff --git a/chrome/browser/chromeos/cros/cert_library.cc b/chrome/browser/chromeos/cros/cert_library.cc
index 736d6cb..952f14f 100644
--- a/chrome/browser/chromeos/cros/cert_library.cc
+++ b/chrome/browser/chromeos/cros/cert_library.cc
@@ -19,6 +19,7 @@
 #include "chromeos/dbus/cryptohome_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/login/login_state.h"
+#include "chromeos/network/onc/onc_utils.h"
 #include "content/public/browser/browser_thread.h"
 #include "crypto/nss_util.h"
 #include "grit/generated_resources.h"
@@ -61,6 +62,16 @@
   }
 }
 
+std::string CertToPEM(const net::X509Certificate& cert) {
+  std::string pem_encoded_cert;
+  if (!net::X509Certificate::GetPEMEncoded(cert.os_cert_handle(),
+                                           &pem_encoded_cert)) {
+    LOG(ERROR) << "Couldn't PEM-encode certificate";
+    return std::string();
+  }
+  return pem_encoded_cert;
+}
+
 }  // namespace
 
 class CertNameComparator {
@@ -148,9 +159,8 @@
   return GetDisplayString(cert, hardware_backed);
 }
 
-std::string CertLibrary::GetCertNicknameAt(CertType type, int index) const {
-  net::X509Certificate* cert = GetCertificateAt(type, index);
-  return x509_certificate_model::GetNickname(cert->os_cert_handle());
+std::string CertLibrary::GetCertPEMAt(CertType type, int index) const {
+  return CertToPEM(*GetCertificateAt(type, index));
 }
 
 std::string CertLibrary::GetCertPkcs11IdAt(CertType type, int index) const {
@@ -168,17 +178,16 @@
       NetworkHandler::Get()->cert_loader()->tpm_token_name();
 }
 
-int CertLibrary::GetCertIndexByNickname(CertType type,
-                                        const std::string& nickname) const {
+int CertLibrary::GetCertIndexByPEM(CertType type,
+                                   const std::string& pem_encoded) const {
   int num_certs = NumCertificates(type);
   for (int index = 0; index < num_certs; ++index) {
     net::X509Certificate* cert = GetCertificateAt(type, index);
-    net::X509Certificate::OSCertHandle cert_handle = cert->os_cert_handle();
-    std::string nick = x509_certificate_model::GetNickname(cert_handle);
-    if (nick == nickname)
-      return index;
+    if (CertToPEM(*cert) != pem_encoded)
+      continue;
+    return index;
   }
-  return -1;  // Not found.
+  return -1;
 }
 
 int CertLibrary::GetCertIndexByPkcs11Id(CertType type,
@@ -272,4 +281,4 @@
   return certs_;
 }
 
-}  // chromeos
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/cros/cert_library.h b/chrome/browser/chromeos/cros/cert_library.h
index 46890cf..8d595b9 100644
--- a/chrome/browser/chromeos/cros/cert_library.h
+++ b/chrome/browser/chromeos/cros/cert_library.h
@@ -68,12 +68,16 @@
 
   // Retreives the certificate property for |type| at |index|.
   string16 GetCertDisplayStringAt(CertType type, int index) const;
-  std::string GetCertNicknameAt(CertType type, int index) const;
+  std::string GetCertPEMAt(CertType type, int index) const;
   std::string GetCertPkcs11IdAt(CertType type, int index) const;
   bool IsCertHardwareBackedAt(CertType type, int index) const;
 
-  // Returns the index of a Certificate matching |nickname| or -1 if none found.
-  int GetCertIndexByNickname(CertType type, const std::string& nickname) const;
+  // Returns the index of a Certificate matching |pem_encoded| or -1 if none
+  // found. This function may be slow depending on the number of stored
+  // certificates.
+  // TOOD(pneubeck): Either make this more efficient, asynchronous or get rid of
+  // it.
+  int GetCertIndexByPEM(CertType type, const std::string& pem_encoded) const;
   // Same as above but for a PKCS#11 id. TODO(stevenjb): Replace this with a
   // better mechanism for uniquely idientifying certificates, crbug.com/236978.
   int GetCertIndexByPkcs11Id(CertType type, const std::string& pkcs11_id) const;
diff --git a/chrome/browser/chromeos/cros/cros_mock.cc b/chrome/browser/chromeos/cros/cros_mock.cc
index 5386e3f..7e7f71d 100644
--- a/chrome/browser/chromeos/cros/cros_mock.cc
+++ b/chrome/browser/chromeos/cros/cros_mock.cc
@@ -6,7 +6,7 @@
 
 #include "base/memory/ref_counted.h"
 #include "base/message_loop.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/chromeos/cros/mock_network_library.h"
 #include "chrome/browser/chromeos/login/screens/wizard_screen.h"
 #include "chrome/browser/chromeos/login/wizard_controller.h"
diff --git a/chrome/browser/chromeos/cros/mock_network_library.h b/chrome/browser/chromeos/cros/mock_network_library.h
index d2c5192..d9144c5 100644
--- a/chrome/browser/chromeos/cros/mock_network_library.h
+++ b/chrome/browser/chromeos/cros/mock_network_library.h
@@ -167,10 +167,6 @@
   MOCK_METHOD3(GetIPConfigs, void(const std::string&,
                                   HardwareAddressFormat,
                                   const NetworkGetIPConfigsCallback&));
-  MOCK_METHOD3(GetIPConfigsAndBlock,
-               NetworkIPConfigVector(const std::string&,
-                                     std::string*,
-                                     HardwareAddressFormat));
   MOCK_METHOD6(SetIPParameters, void(const std::string&,
                                      const std::string&,
                                      const std::string&,
diff --git a/chrome/browser/chromeos/cros/native_network_parser.cc b/chrome/browser/chromeos/cros/native_network_parser.cc
index 4a7637e..fc729d7 100644
--- a/chrome/browser/chromeos/cros/native_network_parser.cc
+++ b/chrome/browser/chromeos/cros/native_network_parser.cc
@@ -6,12 +6,14 @@
 
 #include <string>
 
+#include "base/logging.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/values.h"
 #include "chrome/browser/chromeos/cros/native_network_constants.h"
 #include "chrome/browser/chromeos/cros/network_library.h"
 #include "chrome/browser/chromeos/login/user_manager.h"
+#include "chromeos/network/onc/onc_utils.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
 namespace chromeos {
@@ -48,8 +50,7 @@
   { flimflam::kEapAnonymousIdentityProperty,
     PROPERTY_INDEX_EAP_ANONYMOUS_IDENTITY },
   { flimflam::kEapCaCertIdProperty, PROPERTY_INDEX_EAP_CA_CERT_ID },
-  { flimflam::kEapCaCertNssProperty, PROPERTY_INDEX_EAP_CA_CERT_NSS },
-  { flimflam::kEapCaCertProperty, PROPERTY_INDEX_EAP_CA_CERT },
+  { shill::kEapCaCertPemProperty, PROPERTY_INDEX_EAP_CA_CERT_PEM },
   { flimflam::kEapCertIdProperty, PROPERTY_INDEX_EAP_CERT_ID },
   { flimflam::kEapClientCertNssProperty, PROPERTY_INDEX_EAP_CLIENT_CERT_NSS },
   { flimflam::kEapClientCertProperty, PROPERTY_INDEX_EAP_CLIENT_CERT },
@@ -82,8 +83,8 @@
   { flimflam::kIsActiveProperty, PROPERTY_INDEX_IS_ACTIVE },
   { flimflam::kL2tpIpsecAuthenticationType,
     PROPERTY_INDEX_IPSEC_AUTHENTICATIONTYPE },
-  { flimflam::kL2tpIpsecCaCertNssProperty,
-    PROPERTY_INDEX_L2TPIPSEC_CA_CERT_NSS },
+  { shill::kL2tpIpsecCaCertPemProperty,
+    PROPERTY_INDEX_L2TPIPSEC_CA_CERT_PEM },
   { flimflam::kL2tpIpsecClientCertIdProperty,
     PROPERTY_INDEX_L2TPIPSEC_CLIENT_CERT_ID },
   { flimflam::kL2tpIpsecClientCertSlotProp,
@@ -153,7 +154,7 @@
     PROPERTY_INDEX_OPEN_VPN_AUTHNOCACHE },
   { flimflam::kOpenVPNAuthUserPassProperty,
     PROPERTY_INDEX_OPEN_VPN_AUTHUSERPASS },
-  { flimflam::kOpenVPNCaCertNSSProperty, PROPERTY_INDEX_OPEN_VPN_CACERT },
+  { shill::kOpenVPNCaCertPemProperty, PROPERTY_INDEX_OPEN_VPN_CA_CERT_PEM },
   { flimflam::kOpenVPNClientCertSlotProperty,
     PROPERTY_INDEX_OPEN_VPN_CLIENT_CERT_SLOT },
   { flimflam::kOpenVPNCipherProperty, PROPERTY_INDEX_OPEN_VPN_CIPHER },
@@ -1237,12 +1238,11 @@
       wifi_network->set_eap_client_cert_pkcs11_id(eap_client_cert_pkcs11_id);
       return true;
     }
-    case PROPERTY_INDEX_EAP_CA_CERT_NSS: {
-      std::string eap_server_ca_cert_nss_nickname;
-      if (!value.GetAsString(&eap_server_ca_cert_nss_nickname))
+    case PROPERTY_INDEX_EAP_CA_CERT_PEM: {
+      std::string ca_cert_pem;
+      if (!value.GetAsString(&ca_cert_pem))
         break;
-      wifi_network->set_eap_server_ca_cert_nss_nickname(
-          eap_server_ca_cert_nss_nickname);
+      wifi_network->set_eap_server_ca_cert_pem(ca_cert_pem);
       return true;
     }
     case PROPERTY_INDEX_EAP_USE_SYSTEM_CAS: {
@@ -1259,13 +1259,6 @@
       wifi_network->set_eap_passphrase(eap_passphrase);
       return true;
     }
-    case PROPERTY_INDEX_EAP_CA_CERT: {
-      std::string eap_cert_nickname;
-      if (!value.GetAsString(&eap_cert_nickname))
-        break;
-      wifi_network->set_eap_server_ca_cert_nss_nickname(eap_cert_nickname);
-      return true;
-    }
     case PROPERTY_INDEX_WIFI_AUTH_MODE:
     case PROPERTY_INDEX_WIFI_PHY_MODE:
     case PROPERTY_INDEX_EAP_CLIENT_CERT:
@@ -1379,12 +1372,12 @@
       network->set_provider_type(ParseProviderType(provider_type_string));
       return true;
     }
-    case PROPERTY_INDEX_L2TPIPSEC_CA_CERT_NSS:
-    case PROPERTY_INDEX_OPEN_VPN_CACERT: {
-      std::string ca_cert_nss;
-      if (!value.GetAsString(&ca_cert_nss))
+    case PROPERTY_INDEX_L2TPIPSEC_CA_CERT_PEM:
+    case PROPERTY_INDEX_OPEN_VPN_CA_CERT_PEM: {
+      std::string ca_cert_pem;
+      if (!value.GetAsString(&ca_cert_pem))
         break;
-      network->set_ca_cert_nss(ca_cert_nss);
+      network->set_ca_cert_pem(ca_cert_pem);
       return true;
     }
     case PROPERTY_INDEX_L2TPIPSEC_PSK: {
diff --git a/chrome/browser/chromeos/cros/network_constants.h b/chrome/browser/chromeos/cros/network_constants.h
index 187d7d9..35f6ce6 100644
--- a/chrome/browser/chromeos/cros/network_constants.h
+++ b/chrome/browser/chromeos/cros/network_constants.h
@@ -32,9 +32,8 @@
   PROPERTY_INDEX_DEVICES,
   PROPERTY_INDEX_EAP,
   PROPERTY_INDEX_EAP_ANONYMOUS_IDENTITY,
-  PROPERTY_INDEX_EAP_CA_CERT,
   PROPERTY_INDEX_EAP_CA_CERT_ID,
-  PROPERTY_INDEX_EAP_CA_CERT_NSS,
+  PROPERTY_INDEX_EAP_CA_CERT_PEM,
   PROPERTY_INDEX_EAP_CERT_ID,
   PROPERTY_INDEX_EAP_CLIENT_CERT,
   PROPERTY_INDEX_EAP_CLIENT_CERT_NSS,
@@ -70,7 +69,7 @@
   PROPERTY_INDEX_ISSUER_SUBJECT_PATTERN_ORGANIZATION,
   PROPERTY_INDEX_ISSUER_SUBJECT_PATTERN_ORGANIZATIONAL_UNIT,
   PROPERTY_INDEX_IS_ACTIVE,
-  PROPERTY_INDEX_L2TPIPSEC_CA_CERT_NSS,
+  PROPERTY_INDEX_L2TPIPSEC_CA_CERT_PEM,
   PROPERTY_INDEX_L2TPIPSEC_CLIENT_CERT_ID,
   PROPERTY_INDEX_L2TPIPSEC_CLIENT_CERT_SLOT,
   PROPERTY_INDEX_L2TPIPSEC_GROUP_NAME,
@@ -95,7 +94,7 @@
   PROPERTY_INDEX_OPEN_VPN_AUTHNOCACHE,
   PROPERTY_INDEX_OPEN_VPN_AUTHRETRY,
   PROPERTY_INDEX_OPEN_VPN_AUTHUSERPASS,
-  PROPERTY_INDEX_OPEN_VPN_CACERT,
+  PROPERTY_INDEX_OPEN_VPN_CA_CERT_PEM,
   PROPERTY_INDEX_OPEN_VPN_CERT,
   PROPERTY_INDEX_OPEN_VPN_CIPHER,
   PROPERTY_INDEX_OPEN_VPN_CLIENT_CERT_ID,
diff --git a/chrome/browser/chromeos/cros/network_library.cc b/chrome/browser/chromeos/cros/network_library.cc
index 5076cdc..8db027b 100644
--- a/chrome/browser/chromeos/cros/network_library.cc
+++ b/chrome/browser/chromeos/cros/network_library.cc
@@ -16,10 +16,12 @@
 #include "chrome/browser/chromeos/cros/network_library_impl_cros.h"
 #include "chrome/browser/chromeos/cros/network_library_impl_stub.h"
 #include "chrome/common/net/x509_certificate_model.h"
+#include "chromeos/network/cert_loader.h"
 #include "chromeos/network/certificate_pattern.h"
 #include "chromeos/network/certificate_pattern_matcher.h"
 #include "chromeos/network/cros_network_functions.h"
 #include "chromeos/network/network_state_handler.h"
+#include "chromeos/network/onc/onc_utils.h"
 #include "content/public/browser/browser_thread.h"
 #include "grit/ash_strings.h"
 #include "grit/generated_resources.h"
@@ -591,7 +593,7 @@
 VirtualNetwork::~VirtualNetwork() {}
 
 void VirtualNetwork::EraseCredentials() {
-  WipeString(&ca_cert_nss_);
+  WipeString(&ca_cert_pem_);
   WipeString(&psk_passphrase_);
   WipeString(&client_cert_id_);
   WipeString(&user_passphrase_);
@@ -619,8 +621,8 @@
   VirtualNetwork* remembered_vpn = static_cast<VirtualNetwork*>(remembered);
   VLOG(1) << "Copy VPN credentials: " << name()
           << " username: " << remembered_vpn->username();
-  if (ca_cert_nss_.empty())
-    ca_cert_nss_ = remembered_vpn->ca_cert_nss();
+  if (ca_cert_pem_.empty())
+    ca_cert_pem_ = remembered_vpn->ca_cert_pem();
   if (psk_passphrase_.empty())
     psk_passphrase_ = remembered_vpn->psk_passphrase();
   if (client_cert_id_.empty())
@@ -711,13 +713,16 @@
   return user_passphrase_required_ && user_passphrase_.empty();
 }
 
-void VirtualNetwork::SetCACertNSS(const std::string& ca_cert_nss) {
+void VirtualNetwork::SetCACertPEM(const std::string& ca_cert_pem) {
+  VLOG(1) << "SetCACertPEM " << ca_cert_pem;
   if (provider_type_ == PROVIDER_TYPE_OPEN_VPN) {
-    SetStringProperty(
-        flimflam::kOpenVPNCaCertNSSProperty, ca_cert_nss, &ca_cert_nss_);
+    ca_cert_pem_ = ca_cert_pem;
+    base::ListValue pem_list;
+    pem_list.AppendString(ca_cert_pem_);
+    SetValueProperty(shill::kOpenVPNCaCertPemProperty, pem_list);
   } else {
     SetStringProperty(
-        flimflam::kL2tpIpsecCaCertNssProperty, ca_cert_nss, &ca_cert_nss_);
+        shill::kL2tpIpsecCaCertPemProperty, ca_cert_pem, &ca_cert_pem_);
   }
 }
 
@@ -1109,6 +1114,7 @@
 void WifiNetwork::EraseCredentials() {
   WipeString(&passphrase_);
   WipeString(&user_passphrase_);
+  WipeString(&eap_server_ca_cert_pem_);
   WipeString(&eap_client_cert_pkcs11_id_);
   WipeString(&eap_identity_);
   WipeString(&eap_anonymous_identity_);
@@ -1182,11 +1188,13 @@
   }
 }
 
-void WifiNetwork::SetEAPServerCaCertNssNickname(
-    const std::string& nss_nickname) {
-  VLOG(1) << "SetEAPServerCaCertNssNickname " << nss_nickname;
-  SetOrClearStringProperty(flimflam::kEapCaCertNssProperty,
-                           nss_nickname, &eap_server_ca_cert_nss_nickname_);
+void WifiNetwork::SetEAPServerCaCertPEM(
+    const std::string& ca_cert_pem) {
+  VLOG(1) << "SetEAPServerCaCertPEM " << ca_cert_pem;
+  eap_server_ca_cert_pem_ = ca_cert_pem;
+  base::ListValue pem_list;
+  pem_list.AppendString(ca_cert_pem);
+  SetValueProperty(shill::kEapCaCertPemProperty, pem_list);
 }
 
 void WifiNetwork::SetEAPClientCertPkcs11Id(const std::string& pkcs11_id) {
diff --git a/chrome/browser/chromeos/cros/network_library.h b/chrome/browser/chromeos/cros/network_library.h
index 8b4e2ba..f5cee29 100644
--- a/chrome/browser/chromeos/cros/network_library.h
+++ b/chrome/browser/chromeos/cros/network_library.h
@@ -9,13 +9,15 @@
 #include <string>
 #include <vector>
 
+#include "base/callback.h"
 #include "base/compiler_specific.h"
 #include "base/gtest_prod_util.h"
+#include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/singleton.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "base/values.h"
 #include "chrome/browser/chromeos/cros/network_constants.h"
 #include "chromeos/network/network_ip_config.h"
@@ -656,7 +658,7 @@
 
   const std::string& server_hostname() const { return server_hostname_; }
   ProviderType provider_type() const { return provider_type_; }
-  const std::string& ca_cert_nss() const { return ca_cert_nss_; }
+  const std::string& ca_cert_pem() const { return ca_cert_pem_; }
   const std::string& psk_passphrase() const { return psk_passphrase_; }
   bool psk_passphrase_required() const { return psk_passphrase_required_; }
   const std::string& client_cert_id() const { return client_cert_id_; }
@@ -683,7 +685,7 @@
   bool IsUserPassphraseRequired() const;
 
   // Public setters.
-  void SetCACertNSS(const std::string& ca_cert_nss);
+  void SetCACertPEM(const std::string& ca_cert_pem);
   void SetL2TPIPsecPSKCredentials(const std::string& psk_passphrase,
                                   const std::string& username,
                                   const std::string& user_passphrase,
@@ -720,8 +722,8 @@
   void set_provider_type(ProviderType provider_type) {
     provider_type_ = provider_type;
   }
-  void set_ca_cert_nss(const std::string& ca_cert_nss) {
-    ca_cert_nss_ = ca_cert_nss;
+  void set_ca_cert_pem(const std::string& ca_cert_pem) {
+    ca_cert_pem_ = ca_cert_pem;
   }
   void set_psk_passphrase(const std::string& psk_passphrase) {
     psk_passphrase_ = psk_passphrase;
@@ -761,8 +763,7 @@
 
   std::string server_hostname_;
   ProviderType provider_type_;
-  // NSS nickname for server CA certificate.
-  std::string ca_cert_nss_;
+  std::string ca_cert_pem_;
   std::string psk_passphrase_;
   bool psk_passphrase_required_;
   // PKCS#11 ID for client certificate.
@@ -995,8 +996,8 @@
 
   EAPMethod eap_method() const { return eap_method_; }
   EAPPhase2Auth eap_phase_2_auth() const { return eap_phase_2_auth_; }
-  const std::string& eap_server_ca_cert_nss_nickname() const {
-    return eap_server_ca_cert_nss_nickname_; }
+  const std::string& eap_server_ca_cert_pem() const {
+    return eap_server_ca_cert_pem_; }
   const std::string& eap_client_cert_pkcs11_id() const {
     return eap_client_cert_pkcs11_id_; }
   const bool eap_use_system_cas() const { return eap_use_system_cas_; }
@@ -1018,7 +1019,7 @@
   // 802.1x properties
   void SetEAPMethod(EAPMethod method);
   void SetEAPPhase2Auth(EAPPhase2Auth auth);
-  void SetEAPServerCaCertNssNickname(const std::string& nss_nickname);
+  void SetEAPServerCaCertPEM(const std::string& ca_cert_pem);
   void SetEAPClientCertPkcs11Id(const std::string& pkcs11_id);
   void SetEAPUseSystemCAs(bool use_system_cas);
   void SetEAPIdentity(const std::string& identity);
@@ -1079,9 +1080,8 @@
   void set_eap_phase_2_auth(EAPPhase2Auth eap_phase_2_auth) {
     eap_phase_2_auth_ = eap_phase_2_auth;
   }
-  void set_eap_server_ca_cert_nss_nickname(
-      const std::string& eap_server_ca_cert_nss_nickname) {
-    eap_server_ca_cert_nss_nickname_ = eap_server_ca_cert_nss_nickname;
+  void set_eap_server_ca_cert_pem(const std::string& eap_server_ca_cert_pem) {
+    eap_server_ca_cert_pem_ = eap_server_ca_cert_pem;
   }
   void set_eap_client_cert_pkcs11_id(
       const std::string& eap_client_cert_pkcs11_id) {
@@ -1126,7 +1126,7 @@
 
   EAPMethod eap_method_;
   EAPPhase2Auth eap_phase_2_auth_;
-  std::string eap_server_ca_cert_nss_nickname_;
+  std::string eap_server_ca_cert_pem_;
   std::string eap_client_cert_pkcs11_id_;
   bool eap_use_system_cas_;
   std::string eap_identity_;
@@ -1564,7 +1564,7 @@
     ~EAPConfigData();
     EAPMethod method;
     EAPPhase2Auth auth;
-    std::string server_ca_cert_nss_nickname;
+    std::string server_ca_cert_pem;
     bool use_system_cas;
     std::string client_cert_pkcs11_id;
     std::string identity;
@@ -1584,7 +1584,7 @@
     VPNConfigData();
     ~VPNConfigData();
     std::string psk;
-    std::string server_ca_cert_nss_nickname;
+    std::string server_ca_cert_pem;
     std::string client_cert_pkcs11_id;
     std::string username;
     std::string user_passphrase;
@@ -1628,16 +1628,6 @@
                             HardwareAddressFormat format,
                             const NetworkGetIPConfigsCallback& callback) = 0;
 
-  // DEPRECATED: DO NOT USE. Instead, use the asynchronous GetIPConfigs above.
-  // Fetches IP configs and hardware address for a given device_path. The
-  // hardware address is usually a MAC address like "0011AA22BB33".
-  // |hardware_address| will be an empty string, if no hardware address is
-  // found.
-  virtual NetworkIPConfigVector GetIPConfigsAndBlock(
-      const std::string& device_path,
-      std::string* hardware_address,
-      HardwareAddressFormat) = 0;
-
   // Sets the configuration of the IP parameters. This is called when user
   // changes IP settings from dhcp to static or vice versa or when user changes
   // the ip config info. If nothing is changed, this method does nothing.
@@ -1665,7 +1655,7 @@
   // changes.
   virtual void SwitchToPreferredNetwork() = 0;
 
-  // Load networks from an NetworkConfigurations list of ONC.
+  // Load networks from a list of NetworkConfigurations of ONC.
   virtual void LoadOncNetworks(const base::ListValue& network_configs,
                                onc::ONCSource source) = 0;
 
diff --git a/chrome/browser/chromeos/cros/network_library_impl_base.cc b/chrome/browser/chromeos/cros/network_library_impl_base.cc
index ede3904..22ca01b 100644
--- a/chrome/browser/chromeos/cros/network_library_impl_base.cc
+++ b/chrome/browser/chromeos/cros/network_library_impl_base.cc
@@ -304,10 +304,11 @@
   return remembered_virtual_networks_;
 }
 
+namespace {
+
 // Use shill's ordering of the services to determine which type of
 // network to return (i.e. don't assume priority of network types).
 // Note: This does not include any virtual networks.
-namespace {
 const Network* highest_priority(const Network* a, const Network*b) {
   if (!a)
     return b;
@@ -317,7 +318,8 @@
     return b;
   return a;
 }
-}
+
+}  // namespace
 
 const Network* NetworkLibraryImplBase::active_network() const {
   const Network* result = active_nonvirtual_network();
@@ -806,8 +808,7 @@
     connect_data_.service_name = ssid;
     connect_data_.eap_method = eap_config->method;
     connect_data_.eap_auth = eap_config->auth;
-    connect_data_.server_ca_cert_nss_nickname =
-        eap_config->server_ca_cert_nss_nickname;
+    connect_data_.server_ca_cert_pem = eap_config->server_ca_cert_pem;
     connect_data_.eap_use_system_cas = eap_config->use_system_cas;
     connect_data_.client_cert_pkcs11_id =
         eap_config->client_cert_pkcs11_id;
@@ -828,8 +829,7 @@
   connect_data_.service_name = service_name;
   connect_data_.server_hostname = server_hostname;
   connect_data_.psk_key = config.psk;
-  connect_data_.server_ca_cert_nss_nickname =
-      config.server_ca_cert_nss_nickname;
+  connect_data_.server_ca_cert_pem = config.server_ca_cert_pem;
   connect_data_.client_cert_pkcs11_id = config.client_cert_pkcs11_id;
   connect_data_.username = config.username;
   connect_data_.passphrase = config.user_passphrase;
@@ -867,7 +867,7 @@
     // Enterprise 802.1X EAP network.
     wifi->SetEAPMethod(data.eap_method);
     wifi->SetEAPPhase2Auth(data.eap_auth);
-    wifi->SetEAPServerCaCertNssNickname(data.server_ca_cert_nss_nickname);
+    wifi->SetEAPServerCaCertPEM(data.server_ca_cert_pem);
     wifi->SetEAPUseSystemCAs(data.eap_use_system_cas);
     wifi->SetEAPClientCertPkcs11Id(data.client_cert_pkcs11_id);
     wifi->SetEAPIdentity(data.eap_identity);
@@ -913,7 +913,7 @@
   if (!data.server_hostname.empty())
     vpn->set_server_hostname(data.server_hostname);
 
-  vpn->SetCACertNSS(data.server_ca_cert_nss_nickname);
+  vpn->SetCACertPEM(data.server_ca_cert_pem);
   switch (vpn->provider_type()) {
     case PROVIDER_TYPE_L2TP_IPSEC_PSK:
       vpn->SetL2TPIPsecPSKCredentials(
diff --git a/chrome/browser/chromeos/cros/network_library_impl_base.h b/chrome/browser/chromeos/cros/network_library_impl_base.h
index 999c001..75e9fac 100644
--- a/chrome/browser/chromeos/cros/network_library_impl_base.h
+++ b/chrome/browser/chromeos/cros/network_library_impl_base.h
@@ -263,7 +263,7 @@
     std::string otp;
     std::string group_name;
     std::string server_hostname;
-    std::string server_ca_cert_nss_nickname;
+    std::string server_ca_cert_pem;
     std::string client_cert_pkcs11_id;
     EAPMethod eap_method;
     EAPPhase2Auth eap_auth;
diff --git a/chrome/browser/chromeos/cros/network_library_impl_cros.cc b/chrome/browser/chromeos/cros/network_library_impl_cros.cc
index 6683bba..6109aa7 100644
--- a/chrome/browser/chromeos/cros/network_library_impl_cros.cc
+++ b/chrome/browser/chromeos/cros/network_library_impl_cros.cc
@@ -544,34 +544,6 @@
                                format));
 }
 
-NetworkIPConfigVector NetworkLibraryImplCros::GetIPConfigsAndBlock(
-    const std::string& device_path,
-    std::string* hardware_address,
-    HardwareAddressFormat format) {
-  NetworkIPConfigVector ipconfig_vector;
-  CrosListIPConfigsAndBlock(device_path,
-                            &ipconfig_vector,
-                            NULL,
-                            hardware_address);
-
-  for (size_t i = 0; i < hardware_address->size(); ++i)
-    (*hardware_address)[i] = toupper((*hardware_address)[i]);
-  if (format == FORMAT_COLON_SEPARATED_HEX) {
-    if (hardware_address->size() % 2 == 0) {
-      std::string output;
-      for (size_t i = 0; i < hardware_address->size(); ++i) {
-        if ((i != 0) && (i % 2 == 0))
-          output.push_back(':');
-        output.push_back((*hardware_address)[i]);
-      }
-      *hardware_address = output;
-    }
-  } else {
-    DCHECK_EQ(format, FORMAT_RAW_HEX);
-  }
-  return ipconfig_vector;
-}
-
 void NetworkLibraryImplCros::SetIPParameters(const std::string& service_path,
                                              const std::string& address,
                                              const std::string& netmask,
diff --git a/chrome/browser/chromeos/cros/network_library_impl_cros.h b/chrome/browser/chromeos/cros/network_library_impl_cros.h
index fa001af..c81c1c9 100644
--- a/chrome/browser/chromeos/cros/network_library_impl_cros.h
+++ b/chrome/browser/chromeos/cros/network_library_impl_cros.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_CHROMEOS_CROS_NETWORK_LIBRARY_IMPL_CROS_H_
 #define CHROME_BROWSER_CHROMEOS_CROS_NETWORK_LIBRARY_IMPL_CROS_H_
 
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/chromeos/cros/network_library_impl_base.h"
 
 namespace chromeos {
@@ -75,10 +75,6 @@
       const std::string& device_path,
       HardwareAddressFormat format,
       const NetworkGetIPConfigsCallback& callback) OVERRIDE;
-  virtual NetworkIPConfigVector GetIPConfigsAndBlock(
-      const std::string& device_path,
-      std::string* hardware_address,
-      HardwareAddressFormat format) OVERRIDE;
   virtual void SetIPParameters(const std::string& service_path,
                                const std::string& address,
                                const std::string& netmask,
diff --git a/chrome/browser/chromeos/cros/network_library_impl_stub.cc b/chrome/browser/chromeos/cros/network_library_impl_stub.cc
index bccfb1b..3df19fb 100644
--- a/chrome/browser/chromeos/cros/network_library_impl_stub.cc
+++ b/chrome/browser/chromeos/cros/network_library_impl_stub.cc
@@ -735,14 +735,6 @@
   callback.Run(ip_configs_, hardware_address_);
 }
 
-NetworkIPConfigVector NetworkLibraryImplStub::GetIPConfigsAndBlock(
-    const std::string& device_path,
-    std::string* hardware_address,
-    HardwareAddressFormat format) {
-  *hardware_address = hardware_address_;
-  return ip_configs_;
-}
-
 void NetworkLibraryImplStub::SetIPParameters(const std::string& service_path,
                                              const std::string& address,
                                              const std::string& netmask,
diff --git a/chrome/browser/chromeos/cros/network_library_impl_stub.h b/chrome/browser/chromeos/cros/network_library_impl_stub.h
index 2b456c9..3501a8b 100644
--- a/chrome/browser/chromeos/cros/network_library_impl_stub.h
+++ b/chrome/browser/chromeos/cros/network_library_impl_stub.h
@@ -75,10 +75,6 @@
       const std::string& device_path,
       HardwareAddressFormat format,
       const NetworkGetIPConfigsCallback& callback) OVERRIDE;
-  virtual NetworkIPConfigVector GetIPConfigsAndBlock(
-      const std::string& device_path,
-      std::string* hardware_address,
-      HardwareAddressFormat format) OVERRIDE;
   virtual void SetIPParameters(const std::string& service_path,
                                const std::string& address,
                                const std::string& netmask,
diff --git a/chrome/browser/chromeos/cros/network_library_unittest.cc b/chrome/browser/chromeos/cros/network_library_unittest.cc
index d601637..2ba7361 100644
--- a/chrome/browser/chromeos/cros/network_library_unittest.cc
+++ b/chrome/browser/chromeos/cros/network_library_unittest.cc
@@ -154,13 +154,15 @@
                                 std::string shill_json,
                                 onc::ONCSource source,
                                 bool expect_successful_import) {
-    MockUserManager* mock_user_manager = new MockUserManager;
+    MockUserManager* mock_user_manager =
+        new ::testing::StrictMock<MockUserManager>;
     // Takes ownership of |mock_user_manager|.
     ScopedUserManagerEnabler user_manager_enabler(mock_user_manager);
     mock_user_manager->SetActiveUser("madmax@my.domain.com");
     EXPECT_CALL(*mock_user_manager, IsUserLoggedIn())
         .Times(AnyNumber())
         .WillRepeatedly(Return(true));
+    EXPECT_CALL(*mock_user_manager, Shutdown());
 
     scoped_ptr<base::DictionaryValue> onc_blob =
         onc::test_utils::ReadTestDictionary(onc_file);
@@ -289,14 +291,14 @@
 
 TEST_F(NetworkLibraryStubTest, NetworkConnectWifiWithCertPattern) {
   scoped_ptr<base::DictionaryValue> onc_root =
-      onc::test_utils::ReadTestDictionary("toplevel_wifi_eap_clientcert.onc");
+      onc::test_utils::ReadTestDictionary("certificate-client.onc");
   base::ListValue* certificates;
   onc_root->GetListWithoutPathExpansion(onc::toplevel_config::kCertificates,
                                         &certificates);
 
   onc::CertificateImporter importer(true /* allow trust imports */);
   ASSERT_EQ(onc::CertificateImporter::IMPORT_OK,
-            importer.ParseAndStoreCertificates(*certificates, NULL));
+            importer.ParseAndStoreCertificates(*certificates, NULL, NULL));
 
   WifiNetwork* wifi = cros_->FindWifiNetworkByPath("wifi_cert_pattern");
 
@@ -318,14 +320,14 @@
 
 TEST_F(NetworkLibraryStubTest, NetworkConnectVPNWithCertPattern) {
   scoped_ptr<base::DictionaryValue> onc_root =
-      onc::test_utils::ReadTestDictionary("toplevel_openvpn_clientcert.onc");
+      onc::test_utils::ReadTestDictionary("certificate-client.onc");
   base::ListValue* certificates;
   onc_root->GetListWithoutPathExpansion(onc::toplevel_config::kCertificates,
                                         &certificates);
 
   onc::CertificateImporter importer(true /* allow trust imports */);
   ASSERT_EQ(onc::CertificateImporter::IMPORT_OK,
-            importer.ParseAndStoreCertificates(*certificates, NULL));
+            importer.ParseAndStoreCertificates(*certificates, NULL, NULL));
 
   VirtualNetwork* vpn = cros_->FindVirtualNetworkByPath("vpn_cert_pattern");
 
@@ -404,10 +406,10 @@
     LoadOncNetworksTest,
     LoadOncNetworksTest,
     ::testing::Values(
-         ImportParams("managed_toplevel1.onc",
+         ImportParams("managed_toplevel1_with_cert_pems.onc",
                       "chromeos/net/shill_for_managed_toplevel1.json",
                       onc::ONC_SOURCE_USER_POLICY),
-         ImportParams("managed_toplevel2.onc",
+         ImportParams("managed_toplevel2_with_cert_pems.onc",
                       "chromeos/net/shill_for_managed_toplevel2.json",
                       onc::ONC_SOURCE_USER_POLICY),
          ImportParams("managed_toplevel_l2tpipsec.onc",
@@ -429,10 +431,10 @@
                       "chromeos/net/shill_for_toplevel_wifi_leap.json",
                       onc::ONC_SOURCE_USER_POLICY),
          ImportParams(
-            "toplevel_wifi_eap_clientcert.onc",
+            "toplevel_wifi_eap_clientcert_with_cert_pems.onc",
             "chromeos/net/shill_for_toplevel_wifi_eap_clientcert.json",
             onc::ONC_SOURCE_USER_POLICY),
-         ImportParams("toplevel_openvpn_clientcert.onc",
+         ImportParams("toplevel_openvpn_clientcert_with_cert_pems.onc",
                       "chromeos/net/shill_for_toplevel_openvpn_clientcert.json",
                       onc::ONC_SOURCE_USER_POLICY),
          ImportParams("toplevel_wifi_remove.onc",
diff --git a/chrome/browser/chromeos/customization_document.cc b/chrome/browser/chromeos/customization_document.cc
index a5f551c..a625cd4 100644
--- a/chrome/browser/chromeos/customization_document.cc
+++ b/chrome/browser/chromeos/customization_document.cc
@@ -14,7 +14,7 @@
 #include "base/prefs/pref_service.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/login/wizard_controller.h"
 #include "chrome/browser/chromeos/system/statistics_provider.h"
@@ -47,8 +47,6 @@
 
 const char kAcceptedManifestVersion[] = "1.0";
 
-const char kHardwareClass[] = "hardware_class";
-
 // Path to OEM partner startup customization manifest.
 const char kStartupCustomizationManifestPath[] =
     "/opt/oem/etc/startup_manifest.json";
@@ -175,7 +173,8 @@
     root_->GetString(kRegistrationUrlAttr, &registration_url_);
 
     std::string hwid;
-    if (statistics_provider->GetMachineStatistic(kHardwareClass, &hwid)) {
+    if (statistics_provider->GetMachineStatistic(
+            chromeos::system::kHardwareClass, &hwid)) {
       ListValue* hwid_list = NULL;
       if (root_->GetList(kHwidMapAttr, &hwid_list)) {
         for (size_t i = 0; i < hwid_list->GetSize(); ++i) {
diff --git a/chrome/browser/chromeos/customization_document.h b/chrome/browser/chromeos/customization_document.h
index 81872e9..7f33edb 100644
--- a/chrome/browser/chromeos/customization_document.h
+++ b/chrome/browser/chromeos/customization_document.h
@@ -11,7 +11,7 @@
 #include "base/gtest_prod_util.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/singleton.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "base/values.h"
 #include "googleurl/src/gurl.h"
 #include "net/url_request/url_fetcher_delegate.h"
diff --git a/chrome/browser/chromeos/device_uma.cc b/chrome/browser/chromeos/device_uma.cc
new file mode 100644
index 0000000..2f852bb
--- /dev/null
+++ b/chrome/browser/chromeos/device_uma.cc
@@ -0,0 +1,111 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/device_uma.h"
+
+#include <X11/extensions/XInput.h>
+#include <X11/extensions/XInput2.h>
+
+#include "base/logging.h"
+#include "base/memory/singleton.h"
+#include "base/metrics/histogram.h"
+#include "ui/base/events/event_constants.h"
+#include "ui/base/events/event_utils.h"
+#include "ui/base/x/device_data_manager.h"
+
+// Enum type for CrOS gesture lib UMA
+enum UMACrosGestureMetricsType{
+  // To give an estimated number of all interested events.
+  UMA_CROS_GESTURE_METRICS_ALL_EVENTS,
+  UMA_CROS_GESTURE_METRICS_NOISY_GROUND,
+  // NOTE: Add states only immediately above this line. Make sure to
+  // update the enum list in tools/metrics/histograms/histograms.xml
+  // accordingly.
+  UMA_CROS_GESTURE_METRICS_COUNT
+};
+
+namespace chromeos {
+
+DeviceUMA* DeviceUMA::GetInstance() {
+  return Singleton<DeviceUMA>::get();
+}
+
+DeviceUMA::DeviceUMA()
+    :is_observing_(false) {
+  AddMessageLoopObserver();
+}
+
+DeviceUMA::~DeviceUMA() {
+  RemoveMessageLoopObserver();
+}
+
+void DeviceUMA::Stop() {
+  RemoveMessageLoopObserver();
+}
+
+void DeviceUMA::AddMessageLoopObserver() {
+  if (!is_observing_) {
+    base::MessageLoopForUI::current()->AddObserver(this);
+    is_observing_ = true;
+  }
+}
+
+void DeviceUMA::RemoveMessageLoopObserver() {
+  if (is_observing_) {
+    base::MessageLoopForUI::current()->RemoveObserver(this);
+    is_observing_ = false;
+  }
+}
+
+base::EventStatus DeviceUMA::WillProcessEvent(
+    const base::NativeEvent& event) {
+  CheckIncomingEvent(event);
+  return base::EVENT_CONTINUE;
+}
+
+void DeviceUMA::DidProcessEvent(
+    const base::NativeEvent& event) {
+}
+
+void DeviceUMA::CheckTouchpadEvent(const base::NativeEvent& native_event) {
+  XIDeviceEvent* xiev =
+      static_cast<XIDeviceEvent*>(native_event->xcookie.data);
+  // We take only the slave event since there is no need to count twice.
+  if (xiev->deviceid != xiev->sourceid)
+    return;
+  UMA_HISTOGRAM_ENUMERATION("Touchpad.Metrics",
+                            UMA_CROS_GESTURE_METRICS_ALL_EVENTS,
+                            UMA_CROS_GESTURE_METRICS_COUNT);
+
+  // Check for the CrOS touchpad metrics gesture
+  ui::DeviceDataManager *manager = ui::DeviceDataManager::GetInstance();
+  if (manager->IsCMTMetricsEvent(native_event)) {
+    ui::GestureMetricsType type;
+    float data1, data2;
+    manager->GetMetricsData(native_event, &type, &data1, &data2);
+
+    // We currently track only the noisy ground issue. Please see
+    // http://crbug.com/237683.
+    if (type == ui::kGestureMetricsTypeNoisyGround) {
+      UMA_HISTOGRAM_ENUMERATION("Touchpad.Metrics",
+                                UMA_CROS_GESTURE_METRICS_NOISY_GROUND,
+                                UMA_CROS_GESTURE_METRICS_COUNT);
+    }
+  }
+}
+
+void DeviceUMA::CheckIncomingEvent(const base::NativeEvent& event) {
+  switch (event->type) {
+    case GenericEvent: {
+      if (ui::IsTouchpadEvent(event))
+        CheckTouchpadEvent(event);
+      break;
+    }
+    default:
+      break;
+  }
+  return;
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/device_uma.h b/chrome/browser/chromeos/device_uma.h
new file mode 100644
index 0000000..77f7543
--- /dev/null
+++ b/chrome/browser/chromeos/device_uma.h
@@ -0,0 +1,53 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_DEVICE_UMA_H_
+#define CHROME_BROWSER_CHROMEOS_DEVICE_UMA_H_
+
+#include "base/basictypes.h"
+#include "base/event_types.h"
+#include "base/message_loop.h"
+
+template <typename T> struct DefaultSingletonTraits;
+
+namespace chromeos {
+
+// A class to record devices' input event details via the UMA system
+class DeviceUMA : public base::MessageLoopForUI::Observer {
+ public:
+  // Getting instance starts the class automatically if it hasn't been
+  // started before.
+  static DeviceUMA* GetInstance();
+
+  void Stop();
+
+ private:
+  friend struct DefaultSingletonTraits<DeviceUMA>;
+
+  DeviceUMA();
+  virtual ~DeviceUMA();
+
+  // Start and stop observing events.
+  void AddMessageLoopObserver();
+  void RemoveMessageLoopObserver();
+
+  // MessageLoopForUI::Observer overrides.
+  virtual base::EventStatus WillProcessEvent(
+      const base::NativeEvent& event) OVERRIDE;
+  virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE;
+
+  // Check CrOS touchpad events to see if the metrics gesture is present
+  void CheckTouchpadEvent(const base::NativeEvent& event);
+
+  // Check the incoming events for interesting patterns that we care about.
+  void CheckIncomingEvent(const base::NativeEvent& event);
+
+  bool is_observing_;
+
+  DISALLOW_COPY_AND_ASSIGN(DeviceUMA);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_DEVICE_UMA_H_
diff --git a/chrome/browser/chromeos/display/display_preferences.cc b/chrome/browser/chromeos/display/display_preferences.cc
index 707efcb..33c4581 100644
--- a/chrome/browser/chromeos/display/display_preferences.cc
+++ b/chrome/browser/chromeos/display/display_preferences.cc
@@ -84,12 +84,6 @@
   PrefService* local_state = g_browser_process->local_state();
   ash::DisplayController* display_controller = GetDisplayController();
 
-  ash::DisplayLayout default_layout = ash::DisplayLayout::FromInts(
-      local_state->GetInteger(prefs::kSecondaryDisplayLayout),
-      local_state->GetInteger(prefs::kSecondaryDisplayOffset));
-  default_layout.primary_id = local_state->GetInt64(prefs::kPrimaryDisplayID);
-  display_controller->SetDefaultDisplayLayout(default_layout);
-
   const base::DictionaryValue* layouts = local_state->GetDictionary(
       prefs::kSecondaryDisplays);
   for (DictionaryValue::Iterator it(*layouts); !it.IsAtEnd(); it.Advance()) {
@@ -111,13 +105,6 @@
         continue;
       }
       display_controller->RegisterLayoutForDisplayIdPair(id1, id2, layout);
-    } else {
-      int64 id = gfx::Display::kInvalidDisplayID;
-      if (!base::StringToInt64(it.key(), &id) ||
-          id == gfx::Display::kInvalidDisplayID) {
-        continue;
-      }
-      display_controller->RegisterLayoutForDisplayId(id, layout);
     }
   }
 }
@@ -202,7 +189,7 @@
     property_value->SetInteger("rotation", static_cast<int>(info.rotation()));
     property_value->SetInteger("ui-scale",
                                static_cast<int>(info.ui_scale() * 1000));
-    if (info.has_custom_overscan_insets())
+    if (!info.overscan_insets_in_dip().empty())
       InsetsToValue(info.overscan_insets_in_dip(), property_value.get());
     pref_data->Set(base::Int64ToString(id), property_value.release());
   }
@@ -246,20 +233,12 @@
 }  // namespace
 
 void RegisterDisplayLocalStatePrefs(PrefRegistrySimple* registry) {
-  // The default secondary display layout.
-  registry->RegisterIntegerPref(prefs::kSecondaryDisplayLayout,
-                                static_cast<int>(ash::DisplayLayout::RIGHT));
-  // The default offset of the secondary display position from the primary
-  // display.
-  registry->RegisterIntegerPref(prefs::kSecondaryDisplayOffset, 0);
   // Per-display preference.
   registry->RegisterDictionaryPref(prefs::kSecondaryDisplays);
   registry->RegisterDictionaryPref(prefs::kDisplayProperties);
   DisplayPowerStateToStringMap::const_iterator iter =
       GetDisplayPowerStateToStringMap()->find(chromeos::DISPLAY_POWER_ALL_ON);
   registry->RegisterStringPref(prefs::kDisplayPowerState, iter->second);
-  registry->RegisterInt64Pref(prefs::kPrimaryDisplayID,
-                              gfx::Display::kInvalidDisplayID);
 }
 
 void StoreDisplayPrefs() {
@@ -270,22 +249,9 @@
   StoreCurrentDisplayPowerState();
 }
 
-void SetCurrentAndDefaultDisplayLayout(const ash::DisplayLayout& layout) {
+void SetCurrentDisplayLayout(const ash::DisplayLayout& layout) {
   ash::DisplayController* display_controller = GetDisplayController();
   display_controller->SetLayoutForCurrentDisplays(layout);
-
-  if (IsValidUser()) {
-    PrefService* local_state = g_browser_process->local_state();
-    ash::DisplayIdPair pair = display_controller->GetCurrentDisplayIdPair();
-    // Use registered layout as the layout might have been inverted when
-    // the displays are swapped.
-    ash::DisplayLayout display_layout =
-        display_controller->GetRegisteredDisplayLayout(pair);
-    local_state->SetInteger(prefs::kSecondaryDisplayLayout,
-                            static_cast<int>(display_layout.position));
-    local_state->SetInteger(prefs::kSecondaryDisplayOffset,
-                            display_layout.offset);
-  }
 }
 
 void LoadDisplayPreferences(bool first_run_after_boot) {
diff --git a/chrome/browser/chromeos/display/display_preferences.h b/chrome/browser/chromeos/display/display_preferences.h
index 20058bd..c96e824 100644
--- a/chrome/browser/chromeos/display/display_preferences.h
+++ b/chrome/browser/chromeos/display/display_preferences.h
@@ -29,8 +29,8 @@
 // dispay layout).
 void StoreDisplayPrefs();
 
-// Sets the display layout for the current displays and default.
-void SetCurrentAndDefaultDisplayLayout(const ash::DisplayLayout& layout);
+// Sets the display layout for the current displays.
+void SetCurrentDisplayLayout(const ash::DisplayLayout& layout);
 
 // Load display preferences from Local Store. |first_run_after_boot| is used
 // determine if a certain preference should be applied at boot time or
diff --git a/chrome/browser/chromeos/display/display_preferences_unittest.cc b/chrome/browser/chromeos/display/display_preferences_unittest.cc
index 17136c9..a87a628 100644
--- a/chrome/browser/chromeos/display/display_preferences_unittest.cc
+++ b/chrome/browser/chromeos/display/display_preferences_unittest.cc
@@ -113,15 +113,6 @@
         base::Int64ToString(id), layout, offset, primary_id);
   }
 
-  void StoreDefaultLayoutPref(ash::DisplayLayout::Position layout,
-                              int offset,
-                              int64 primary_id) {
-    local_state_.SetInteger(prefs::kSecondaryDisplayLayout,
-                            static_cast<int>(layout));
-    local_state_.SetInteger(prefs::kSecondaryDisplayOffset, offset);
-    local_state_.SetInt64(prefs::kPrimaryDisplayID, primary_id);
-  }
-
   void StoreDisplayOverscan(int64 id, const gfx::Insets& insets) {
     DictionaryPrefUpdate update(&local_state_, prefs::kDisplayProperties);
     const std::string name = base::Int64ToString(id);
@@ -154,58 +145,6 @@
   DISALLOW_COPY_AND_ASSIGN(DisplayPreferencesTest);
 };
 
-TEST_F(DisplayPreferencesTest, DefaultLayout) {
-  ash::DisplayController* display_controller =
-      ash::Shell::GetInstance()->display_controller();
-
-  int64 id1 = gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id();
-  int64 id2 = id1 + 1;
-  StoreDefaultLayoutPref(ash::DisplayLayout::LEFT, 50, id2);
-  LoadDisplayPreferences(true);
-  EXPECT_EQ("left, 50",
-            display_controller->default_display_layout().ToString());
-
-  UpdateDisplay("100x100,200x200");
-  // Displays are swapped, so does the layout.
-  EXPECT_EQ("right, -50",
-            display_controller->GetCurrentDisplayLayout().ToString());
-  EXPECT_EQ(id2,
-            display_controller->GetCurrentDisplayLayout().primary_id);
-}
-
-TEST_F(DisplayPreferencesTest, OldInitialization) {
-  ash::DisplayController* display_controller =
-      ash::Shell::GetInstance()->display_controller();
-
-  int64 id1 = gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id();
-  int64 id2 = id1 + 1;
-  int64 dummy_id = id2 + 1;
-
-  StoreDisplayLayoutPrefForSecondary(id2, ash::DisplayLayout::BOTTOM, 20, id2);
-  StoreDisplayLayoutPrefForSecondary(
-      dummy_id, ash::DisplayLayout::TOP, -10, id1);
-  StoreDisplayOverscan(id1, gfx::Insets(10, 10, 10, 10));
-  StoreDisplayOverscan(id2, gfx::Insets(20, 20, 20, 20));
-
-  LoadDisplayPreferences(true);
-
-  UpdateDisplay("100x100,200x200");
-  EXPECT_EQ(id1, ash::ScreenAsh::GetSecondaryDisplay().id());
-
-  // Check if the layout settings are notified to the system properly.
-  gfx::Screen* screen = gfx::Screen::GetNativeScreen();
-  EXPECT_EQ(id2, screen->GetPrimaryDisplay().id());
-  // Display was swapped, so the layout was inverted.
-  EXPECT_EQ("top, -20",
-            display_controller->GetCurrentDisplayLayout().ToString());
-
-  EXPECT_EQ("bottom, 20", GetRegisteredDisplayLayoutStr(id1, id2));
-  EXPECT_EQ("top, -10", GetRegisteredDisplayLayoutStr(id1, dummy_id));
-  EXPECT_EQ("160x160", screen->GetPrimaryDisplay().bounds().size().ToString());
-  EXPECT_EQ("80x80",
-            ash::ScreenAsh::GetSecondaryDisplay().bounds().size().ToString());
-}
-
 TEST_F(DisplayPreferencesTest, PairedLayoutOverrides) {
   UpdateDisplay("100x100,200x200");
   int64 id1 = gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id();
@@ -215,7 +154,6 @@
 
   StoreDisplayLayoutPrefForPair(id1, id2, ash::DisplayLayout::TOP, 20);
   StoreDisplayLayoutPrefForPair(id1, dummy_id, ash::DisplayLayout::LEFT, 30);
-  StoreDefaultLayoutPref(ash::DisplayLayout::LEFT, 50, id2);
   StoreDisplayPowerStateForTest(
       chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON);
 
@@ -253,7 +191,7 @@
 
   LoggedInAsUser();
   ash::DisplayLayout layout(ash::DisplayLayout::TOP, 10);
-  SetCurrentAndDefaultDisplayLayout(layout);
+  SetCurrentDisplayLayout(layout);
   StoreDisplayLayoutPrefForTest(
       id1, dummy_id, ash::DisplayLayout(ash::DisplayLayout::LEFT, 20));
   // Can't switch to a display that does not exist.
@@ -281,12 +219,6 @@
   EXPECT_TRUE(layout_value->GetBoolean(kMirroredKey, &mirrored));
   EXPECT_FALSE(mirrored);
 
-  // The default value is set for the last call of
-  // SetCurrentAndDefaultDisplayLayout
-  EXPECT_EQ(ash::DisplayLayout::TOP,
-            local_state()->GetInteger(prefs::kSecondaryDisplayLayout));
-  EXPECT_EQ(10, local_state()->GetInteger(prefs::kSecondaryDisplayOffset));
-
   const base::DictionaryValue* properties =
       local_state()->GetDictionary(prefs::kDisplayProperties);
   const base::DictionaryValue* property = NULL;
@@ -336,17 +268,8 @@
   EXPECT_TRUE(layout_value->GetString(kPrimaryIdKey, &primary_id_str));
   EXPECT_EQ(base::Int64ToString(id2), primary_id_str);
 
-  // Default value should changte.
-  EXPECT_EQ(ash::DisplayLayout::TOP,
-            local_state()->GetInteger(prefs::kSecondaryDisplayLayout));
-  EXPECT_EQ(10, local_state()->GetInteger(prefs::kSecondaryDisplayOffset));
-
-  SetCurrentAndDefaultDisplayLayout(
+  SetCurrentDisplayLayout(
       ash::DisplayLayout(ash::DisplayLayout::BOTTOM, 20));
-  // Displays are swapped, so does the default layout.
-  EXPECT_EQ(ash::DisplayLayout::TOP,
-            local_state()->GetInteger(prefs::kSecondaryDisplayLayout));
-  EXPECT_EQ(-20, local_state()->GetInteger(prefs::kSecondaryDisplayOffset));
 
   UpdateDisplay("200x200*2,1+0-200x200");
   // Mirrored.
@@ -391,7 +314,7 @@
 
   LoggedInAsUser();
   ash::DisplayLayout layout(ash::DisplayLayout::TOP, 10);
-  SetCurrentAndDefaultDisplayLayout(layout);
+  SetCurrentDisplayLayout(layout);
   layout = layout.Invert();
 
   const base::DictionaryValue* displays =
@@ -427,7 +350,7 @@
   gfx::Display::SetInternalDisplayId(id1);
   int64 id2 = ash::ScreenAsh::GetSecondaryDisplay().id();
   ash::DisplayLayout layout(ash::DisplayLayout::TOP, 10);
-  SetCurrentAndDefaultDisplayLayout(layout);
+  SetCurrentDisplayLayout(layout);
   display_manager->SetDisplayUIScale(id1, 1.25f);
   display_controller->SetPrimaryDisplayId(id2);
   int64 new_primary =
@@ -441,10 +364,6 @@
   EXPECT_FALSE(local_state()->FindPreference(
       prefs::kSecondaryDisplays)->HasUserSetting());
   EXPECT_FALSE(local_state()->FindPreference(
-      prefs::kSecondaryDisplayLayout)->HasUserSetting());
-  EXPECT_FALSE(local_state()->FindPreference(
-      prefs::kSecondaryDisplayOffset)->HasUserSetting());
-  EXPECT_FALSE(local_state()->FindPreference(
       prefs::kDisplayProperties)->HasUserSetting());
 
   // Settings are still notified to the system.
diff --git a/chrome/browser/chromeos/display/overscan_calibrator.cc b/chrome/browser/chromeos/display/overscan_calibrator.cc
index 6eedc1a..1e8f37a 100644
--- a/chrome/browser/chromeos/display/overscan_calibrator.cc
+++ b/chrome/browser/chromeos/display/overscan_calibrator.cc
@@ -75,11 +75,6 @@
 
   ash::internal::DisplayInfo info = ash::Shell::GetInstance()->
       display_manager()->GetDisplayInfo(display_.id());
-  if (info.has_overscan()) {
-    info.clear_has_custom_overscan_insets();
-    info.UpdateDisplaySize();
-    native_insets_ = info.overscan_insets_in_dip();
-  }
 
   aura::RootWindow* root = ash::Shell::GetInstance()->display_controller()->
       GetRootWindowForDisplayId(display_.id());
@@ -103,22 +98,13 @@
 }
 
 void OverscanCalibrator::Commit() {
-  if (insets_ == native_insets_) {
-    ash::Shell::GetInstance()->display_controller()->ClearCustomOverscanInsets(
-        display_.id());
-  } else {
-    ash::Shell::GetInstance()->display_controller()->SetOverscanInsets(
-        display_.id(), insets_);
-  }
+  ash::Shell::GetInstance()->display_controller()->SetOverscanInsets(
+      display_.id(), insets_);
   committed_ = true;
 }
 
 void OverscanCalibrator::Reset() {
-  if (!native_insets_.empty())
-    insets_ = native_insets_;
-  else
-    insets_ = initial_insets_;
-
+  insets_ = initial_insets_;
   calibration_layer_->SchedulePaint(calibration_layer_->bounds());
 }
 
diff --git a/chrome/browser/chromeos/display/overscan_calibrator.h b/chrome/browser/chromeos/display/overscan_calibrator.h
index 66f0b0e..691d13d 100644
--- a/chrome/browser/chromeos/display/overscan_calibrator.h
+++ b/chrome/browser/chromeos/display/overscan_calibrator.h
@@ -54,9 +54,6 @@
   // The insets initially given. Stored so we can undo the insets later.
   gfx::Insets initial_insets_;
 
-  // The insets claimed by the display.
-  gfx::Insets native_insets_;
-
   // Whether the current insets are committed to the system or not.
   bool committed_;
 
diff --git a/chrome/browser/chromeos/drive/change_list_loader.cc b/chrome/browser/chromeos/drive/change_list_loader.cc
index 23eb52e..99548da 100644
--- a/chrome/browser/chromeos/drive/change_list_loader.cc
+++ b/chrome/browser/chromeos/drive/change_list_loader.cc
@@ -16,8 +16,8 @@
 #include "chrome/browser/chromeos/drive/job_scheduler.h"
 #include "chrome/browser/chromeos/drive/logging.h"
 #include "chrome/browser/chromeos/drive/resource_metadata.h"
+#include "chrome/browser/drive/drive_api_util.h"
 #include "chrome/browser/google_apis/drive_api_parser.h"
-#include "chrome/browser/google_apis/drive_api_util.h"
 #include "content/public/browser/browser_thread.h"
 #include "googleurl/src/gurl.h"
 
diff --git a/chrome/browser/chromeos/drive/change_list_loader.h b/chrome/browser/chromeos/drive/change_list_loader.h
index 6845a04..a476dff 100644
--- a/chrome/browser/chromeos/drive/change_list_loader.h
+++ b/chrome/browser/chromeos/drive/change_list_loader.h
@@ -14,7 +14,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/scoped_vector.h"
 #include "base/observer_list.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/chromeos/drive/file_errors.h"
 #include "chrome/browser/google_apis/gdata_errorcode.h"
 
diff --git a/chrome/browser/chromeos/drive/change_list_loader_unittest.cc b/chrome/browser/chromeos/drive/change_list_loader_unittest.cc
index d7c635b..303845d 100644
--- a/chrome/browser/chromeos/drive/change_list_loader_unittest.cc
+++ b/chrome/browser/chromeos/drive/change_list_loader_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/run_loop.h"
+#include "chrome/browser/chromeos/drive/change_list_loader_observer.h"
 #include "chrome/browser/chromeos/drive/file_cache.h"
 #include "chrome/browser/chromeos/drive/job_scheduler.h"
 #include "chrome/browser/chromeos/drive/resource_metadata.h"
@@ -20,24 +21,73 @@
 namespace drive {
 namespace internal {
 
+class TestChangeListLoaderObserver : public ChangeListLoaderObserver {
+ public:
+  explicit TestChangeListLoaderObserver(ChangeListLoader* loader)
+      : loader_(loader),
+        load_from_server_complete_count_(0),
+        initial_load_complete_count_(0) {
+    loader_->AddObserver(this);
+  }
+
+  virtual ~TestChangeListLoaderObserver() {
+    loader_->RemoveObserver(this);
+  }
+
+  const std::set<base::FilePath>& changed_directories() const {
+    return changed_directories_;
+  }
+  int load_from_server_complete_count() const {
+    return load_from_server_complete_count_;
+  }
+  int initial_load_complete_count() const {
+    return initial_load_complete_count_;
+  }
+
+  // ChageListObserver overrides:
+  virtual void OnDirectoryChanged(
+      const base::FilePath& directory_path) OVERRIDE {
+    changed_directories_.insert(directory_path);
+  }
+  virtual void OnLoadFromServerComplete() OVERRIDE {
+    ++load_from_server_complete_count_;
+  }
+  virtual void OnInitialLoadComplete() OVERRIDE {
+    ++initial_load_complete_count_;
+  }
+
+ private:
+  ChangeListLoader* loader_;
+  std::set<base::FilePath> changed_directories_;
+  int load_from_server_complete_count_;
+  int initial_load_complete_count_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestChangeListLoaderObserver);
+};
+
 class ChangeListLoaderTest : public testing::Test {
  protected:
   virtual void SetUp() OVERRIDE {
     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
     profile_.reset(new TestingProfile);
 
-    drive_service_.reset(new google_apis::FakeDriveService);
+    drive_service_.reset(new FakeDriveService);
     ASSERT_TRUE(drive_service_->LoadResourceListForWapi(
-        "chromeos/gdata/root_feed.json"));
+        "gdata/root_feed.json"));
     ASSERT_TRUE(drive_service_->LoadAccountMetadataForWapi(
-        "chromeos/gdata/account_metadata.json"));
+        "gdata/account_metadata.json"));
 
-    scheduler_.reset(new JobScheduler(profile_.get(), drive_service_.get()));
-    metadata_.reset(new ResourceMetadata(temp_dir_.path(),
+    scheduler_.reset(new JobScheduler(profile_.get(), drive_service_.get(),
+                                      base::MessageLoopProxy::current()));
+    metadata_storage_.reset(new ResourceMetadataStorage(
+        temp_dir_.path(), base::MessageLoopProxy::current()));
+    ASSERT_TRUE(metadata_storage_->Initialize());
+
+    metadata_.reset(new ResourceMetadata(metadata_storage_.get(),
                                          base::MessageLoopProxy::current()));
     ASSERT_EQ(FILE_ERROR_OK, metadata_->Initialize());
 
-    cache_.reset(new FileCache(temp_dir_.path(),
+    cache_.reset(new FileCache(metadata_storage_.get(),
                                temp_dir_.path(),
                                base::MessageLoopProxy::current(),
                                NULL /* free_disk_space_getter */));
@@ -50,8 +100,10 @@
   content::TestBrowserThreadBundle thread_bundle_;
   base::ScopedTempDir temp_dir_;
   scoped_ptr<TestingProfile> profile_;
-  scoped_ptr<google_apis::FakeDriveService> drive_service_;
+  scoped_ptr<FakeDriveService> drive_service_;
   scoped_ptr<JobScheduler> scheduler_;
+  scoped_ptr<ResourceMetadataStorage,
+             test_util::DestroyHelperForTests> metadata_storage_;
   scoped_ptr<ResourceMetadata, test_util::DestroyHelperForTests> metadata_;
   scoped_ptr<FileCache, test_util::DestroyHelperForTests> cache_;
   scoped_ptr<ChangeListLoader> change_list_loader_;
@@ -61,6 +113,8 @@
   EXPECT_FALSE(change_list_loader_->IsRefreshing());
 
   // Start initial load.
+  TestChangeListLoaderObserver observer(change_list_loader_.get());
+
   FileError error = FILE_ERROR_FAILED;
   change_list_loader_->LoadIfNeeded(
       DirectoryFetchInfo(),
@@ -72,6 +126,9 @@
   EXPECT_FALSE(change_list_loader_->IsRefreshing());
   EXPECT_LT(0, metadata_->GetLargestChangestamp());
   EXPECT_EQ(1, drive_service_->resource_list_load_count());
+  EXPECT_EQ(1, observer.initial_load_complete_count());
+  EXPECT_EQ(1, observer.load_from_server_complete_count());
+  EXPECT_TRUE(observer.changed_directories().empty());
 
   // Reload. This should result in no-op.
   int64 previous_changestamp = metadata_->GetLargestChangestamp();
diff --git a/chrome/browser/chromeos/drive/change_list_processor_unittest.cc b/chrome/browser/chromeos/drive/change_list_processor_unittest.cc
index 15affb8..1495563 100644
--- a/chrome/browser/chromeos/drive/change_list_processor_unittest.cc
+++ b/chrome/browser/chromeos/drive/change_list_processor_unittest.cc
@@ -23,7 +23,7 @@
 namespace {
 
 const int64 kBaseResourceListChangestamp = 123;
-const char kBaseResourceListFile[] = "chromeos/gdata/root_feed.json";
+const char kBaseResourceListFile[] = "gdata/root_feed.json";
 
 enum FileOrDirectory {
   FILE,
@@ -41,13 +41,14 @@
  protected:
   virtual void SetUp() OVERRIDE {
     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
-    metadata_.reset(new internal::ResourceMetadata(
-        temp_dir_.path(), base::MessageLoopProxy::current()));
-    ASSERT_EQ(FILE_ERROR_OK, metadata_->Initialize());
-  }
 
-  virtual void TearDown() OVERRIDE {
-    metadata_.reset();
+    metadata_storage_.reset(new ResourceMetadataStorage(
+        temp_dir_.path(), base::MessageLoopProxy::current()));
+    ASSERT_TRUE(metadata_storage_->Initialize());
+
+    metadata_.reset(new internal::ResourceMetadata(
+        metadata_storage_.get(), base::MessageLoopProxy::current()));
+    ASSERT_EQ(FILE_ERROR_OK, metadata_->Initialize());
   }
 
   // Parses a json file at |test_data_path| relative to Chrome test directory
@@ -98,8 +99,9 @@
 
   content::TestBrowserThreadBundle thread_bundle_;
   base::ScopedTempDir temp_dir_;
-  scoped_ptr<internal::ResourceMetadata, test_util::DestroyHelperForTests>
-      metadata_;
+  scoped_ptr<ResourceMetadataStorage,
+             test_util::DestroyHelperForTests> metadata_storage_;
+  scoped_ptr<ResourceMetadata, test_util::DestroyHelperForTests> metadata_;
 };
 
 }  // namespace
@@ -159,7 +161,7 @@
 
 TEST_F(ChangeListProcessorTest, DeltaFileAddedInNewDirectory) {
   const char kTestJson[] =
-      "chromeos/gdata/delta_file_added_in_new_directory.json";
+      "gdata/delta_file_added_in_new_directory.json";
 
   ChangeListProcessor::ResourceEntryMap entry_map;
   ChangeListProcessor::ConvertToMap(
@@ -200,7 +202,7 @@
 
 TEST_F(ChangeListProcessorTest, DeltaDirMovedFromRootToDirectory) {
   const char kTestJson[] =
-      "chromeos/gdata/delta_dir_moved_from_root_to_directory.json";
+      "gdata/delta_dir_moved_from_root_to_directory.json";
 
   ChangeListProcessor::ResourceEntryMap entry_map;
   ChangeListProcessor::ConvertToMap(
@@ -241,7 +243,7 @@
 
 TEST_F(ChangeListProcessorTest, DeltaFileMovedFromDirectoryToRoot) {
   const char kTestJson[] =
-      "chromeos/gdata/delta_file_moved_from_directory_to_root.json";
+      "gdata/delta_file_moved_from_directory_to_root.json";
 
   ChangeListProcessor::ResourceEntryMap entry_map;
   ChangeListProcessor::ConvertToMap(
@@ -277,7 +279,7 @@
 
 TEST_F(ChangeListProcessorTest, DeltaFileRenamedInDirectory) {
   const char kTestJson[] =
-      "chromeos/gdata/delta_file_renamed_in_directory.json";
+      "gdata/delta_file_renamed_in_directory.json";
 
   ChangeListProcessor::ResourceEntryMap entry_map;
   ChangeListProcessor::ConvertToMap(
@@ -315,9 +317,9 @@
 
 TEST_F(ChangeListProcessorTest, DeltaAddAndDeleteFileInRoot) {
   const char kTestJsonAdd[] =
-      "chromeos/gdata/delta_file_added_in_root.json";
+      "gdata/delta_file_added_in_root.json";
   const char kTestJsonDelete[] =
-      "chromeos/gdata/delta_file_deleted_in_root.json";
+      "gdata/delta_file_deleted_in_root.json";
 
   const std::string kParentId("fake_root");
   const std::string kFileId("document:added_in_root_id");
@@ -365,9 +367,9 @@
 
 TEST_F(ChangeListProcessorTest, DeltaAddAndDeleteFileFromExistingDirectory) {
   const char kTestJsonAdd[] =
-      "chromeos/gdata/delta_file_added_in_directory.json";
+      "gdata/delta_file_added_in_directory.json";
   const char kTestJsonDelete[] =
-      "chromeos/gdata/delta_file_deleted_in_directory.json";
+      "gdata/delta_file_deleted_in_directory.json";
 
   const std::string kParentId("folder:1_folder_resource_id");
   const std::string kFileId("document:added_in_root_id");
@@ -423,7 +425,7 @@
   // 2) but the new directory is marked "deleted" (i.e. moved to Trash)
   // Hence, the PDF file should be just ignored.
   const char kTestJson[] =
-      "chromeos/gdata/delta_file_added_in_new_but_deleted_directory.json";
+      "gdata/delta_file_added_in_new_but_deleted_directory.json";
 
   ChangeListProcessor::ResourceEntryMap entry_map;
   ChangeListProcessor::ConvertToMap(
diff --git a/chrome/browser/chromeos/drive/download_handler.cc b/chrome/browser/chromeos/drive/download_handler.cc
index 8e0bb33..850caf9 100644
--- a/chrome/browser/chromeos/drive/download_handler.cc
+++ b/chrome/browser/chromeos/drive/download_handler.cc
@@ -29,7 +29,7 @@
 class DriveUserData : public base::SupportsUserData::Data {
  public:
   explicit DriveUserData(const base::FilePath& path) : file_path_(path),
-                                                 is_complete_(false) {}
+                                                       is_complete_(false) {}
   virtual ~DriveUserData() {}
 
   const base::FilePath& file_path() const { return file_path_; }
@@ -72,7 +72,7 @@
                         const base::FilePath& dest_path) {
   if (error != FILE_ERROR_OK)
     return;
-  file_util::Move(downloaded_file, dest_path);
+  base::Move(downloaded_file, dest_path);
 }
 
 // Used to implement CheckForFileExistence().
diff --git a/chrome/browser/chromeos/drive/download_handler_unittest.cc b/chrome/browser/chromeos/drive/download_handler_unittest.cc
index 94a7e05..b828c1d 100644
--- a/chrome/browser/chromeos/drive/download_handler_unittest.cc
+++ b/chrome/browser/chromeos/drive/download_handler_unittest.cc
@@ -12,7 +12,6 @@
 #include "content/public/test/mock_download_item.h"
 #include "content/public/test/mock_download_manager.h"
 #include "content/public/test/test_browser_thread_bundle.h"
-#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace drive {
diff --git a/chrome/browser/chromeos/drive/drive.proto b/chrome/browser/chromeos/drive/drive.proto
index 56a0363..07ac169 100644
--- a/chrome/browser/chromeos/drive/drive.proto
+++ b/chrome/browser/chromeos/drive/drive.proto
@@ -45,6 +45,9 @@
   // True if the file is a hosted document (i.e. document hosted on
   // drive.google.com such as documents, spreadsheets, and presentations).
   optional bool is_hosted_document = 6;
+
+  // This URL points to a page containing Share UI for this document.
+  optional string share_url = 7;
 }
 
 // Directory specific info, which is a part of ResourceEntry.
diff --git a/chrome/browser/chromeos/drive/drive_app_registry.cc b/chrome/browser/chromeos/drive/drive_app_registry.cc
index 5cb9dc0..4171fd6 100644
--- a/chrome/browser/chromeos/drive/drive_app_registry.cc
+++ b/chrome/browser/chromeos/drive/drive_app_registry.cc
@@ -42,7 +42,6 @@
   return components[components.size() - 1];
 }
 
-// TODO(kochi): This is duplicate from gdata_wapi_parser.cc.
 bool SortBySize(const google_apis::InstalledApp::IconList::value_type& a,
                 const google_apis::InstalledApp::IconList::value_type& b) {
   return a.first < b.first;
diff --git a/chrome/browser/chromeos/drive/drive_app_registry_unittest.cc b/chrome/browser/chromeos/drive/drive_app_registry_unittest.cc
index f8bea09..941cc77 100644
--- a/chrome/browser/chromeos/drive/drive_app_registry_unittest.cc
+++ b/chrome/browser/chromeos/drive/drive_app_registry_unittest.cc
@@ -20,12 +20,11 @@
   virtual void SetUp() OVERRIDE {
     profile_.reset(new TestingProfile);
 
-    // The fake object will be manually deleted in TearDown().
-    fake_drive_service_.reset(new google_apis::FakeDriveService);
-    fake_drive_service_->LoadAppListForDriveApi("chromeos/drive/applist.json");
+    fake_drive_service_.reset(new FakeDriveService);
+    fake_drive_service_->LoadAppListForDriveApi("drive/applist.json");
 
-    scheduler_.reset(
-        new JobScheduler(profile_.get(), fake_drive_service_.get()));
+    scheduler_.reset(new JobScheduler(profile_.get(), fake_drive_service_.get(),
+                                      base::MessageLoopProxy::current()));
 
     web_apps_registry_.reset(new DriveAppRegistry(scheduler_.get()));
     web_apps_registry_->Update();
@@ -58,7 +57,7 @@
 
   content::TestBrowserThreadBundle thread_bundle_;
   scoped_ptr<TestingProfile> profile_;
-  scoped_ptr<google_apis::FakeDriveService> fake_drive_service_;
+  scoped_ptr<FakeDriveService> fake_drive_service_;
   scoped_ptr<JobScheduler> scheduler_;
   scoped_ptr<DriveAppRegistry> web_apps_registry_;
 };
diff --git a/chrome/browser/chromeos/drive/drive_file_stream_reader.cc b/chrome/browser/chromeos/drive/drive_file_stream_reader.cc
index 7117085..a8c8e66 100644
--- a/chrome/browser/chromeos/drive/drive_file_stream_reader.cc
+++ b/chrome/browser/chromeos/drive/drive_file_stream_reader.cc
@@ -29,6 +29,12 @@
   return net::PlatformFileErrorToNetError(FileErrorToPlatformError(error));
 }
 
+// Runs task on UI thread.
+void RunTaskOnUIThread(const base::Closure& task) {
+  google_apis::RunTaskOnThread(
+      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), task);
+}
+
 }  // namespace
 
 namespace internal {
@@ -372,8 +378,7 @@
     reader_proxy_.reset(
         new internal::NetworkReaderProxy(
             byte_range.first_byte_position(), range_length,
-            base::Bind(&google_apis::RunTaskOnUIThread,
-                       ui_cancel_download_closure)));
+            base::Bind(&RunTaskOnUIThread, ui_cancel_download_closure)));
     callback.Run(net::OK, entry.Pass());
     return;
   }
diff --git a/chrome/browser/chromeos/drive/drive_file_stream_reader_unittest.cc b/chrome/browser/chromeos/drive/drive_file_stream_reader_unittest.cc
index 72ade07..c0c3de1 100644
--- a/chrome/browser/chromeos/drive/drive_file_stream_reader_unittest.cc
+++ b/chrome/browser/chromeos/drive/drive_file_stream_reader_unittest.cc
@@ -9,16 +9,13 @@
 #include "base/bind.h"
 #include "base/files/file_path.h"
 #include "base/files/scoped_temp_dir.h"
-#include "base/message_loop.h"
-#include "base/rand_util.h"
-#include "base/sequenced_task_runner.h"
+#include "base/run_loop.h"
 #include "base/threading/thread.h"
 #include "chrome/browser/chromeos/drive/fake_file_system.h"
 #include "chrome/browser/chromeos/drive/file_system_util.h"
 #include "chrome/browser/chromeos/drive/local_file_reader.h"
 #include "chrome/browser/chromeos/drive/test_util.h"
 #include "chrome/browser/drive/fake_drive_service.h"
-#include "chrome/browser/google_apis/task_util.h"
 #include "chrome/browser/google_apis/test_util.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "net/base/io_buffer.h"
@@ -54,10 +51,6 @@
     ASSERT_TRUE(worker_thread_->Start());
   }
 
-  virtual void TearDown() OVERRIDE {
-    worker_thread_.reset();
-  }
-
   content::TestBrowserThreadBundle thread_bundle_;
 
   base::ScopedTempDir temp_dir_;
@@ -78,7 +71,7 @@
   // Test instance.
   LocalReaderProxy proxy(file_reader.Pass(), file_content_.size());
 
-  // Make sure the read contant is as same as the file.
+  // Make sure the read content is as same as the file.
   std::string content;
   ASSERT_EQ(net::OK, test_util::ReadAllData(&proxy, &content));
   EXPECT_EQ(file_content_, content);
@@ -99,7 +92,7 @@
   // Test instance.
   LocalReaderProxy proxy(file_reader.Pass(), expected_content.size());
 
-  // Make sure the read contant is as same as the file.
+  // Make sure the read content is as same as the file.
   std::string content;
   ASSERT_EQ(net::OK, test_util::ReadAllData(&proxy, &content));
   EXPECT_EQ(expected_content, content);
@@ -295,11 +288,11 @@
     ASSERT_TRUE(worker_thread_->Start());
 
     // Initialize FakeDriveService.
-    fake_drive_service_.reset(new google_apis::FakeDriveService);
+    fake_drive_service_.reset(new FakeDriveService);
     fake_drive_service_->LoadResourceListForWapi(
-        "chromeos/gdata/root_feed.json");
+        "gdata/root_feed.json");
     fake_drive_service_->LoadAccountMetadataForWapi(
-        "chromeos/gdata/account_metadata.json");
+        "gdata/account_metadata.json");
 
     // Create a testee instance.
     fake_file_system_.reset(
@@ -327,7 +320,7 @@
 
   scoped_ptr<base::Thread> worker_thread_;
 
-  scoped_ptr<google_apis::FakeDriveService> fake_drive_service_;
+  scoped_ptr<FakeDriveService> fake_drive_service_;
   scoped_ptr<test_util::FakeFileSystem> fake_file_system_;
 };
 
@@ -343,14 +336,16 @@
 
   int error = net::ERR_FAILED;
   scoped_ptr<ResourceEntry> entry;
-  reader->Initialize(
-      kDriveFile,
-      net::HttpByteRange(),
-      google_apis::CreateComposedCallback(
-          base::Bind(&google_apis::test_util::RunAndQuit),
-                     google_apis::test_util::CreateCopyResultCallback(
-                         &error, &entry)));
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    reader->Initialize(
+        kDriveFile,
+        net::HttpByteRange(),
+        google_apis::test_util::CreateQuitCallback(
+            &run_loop,
+            google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
+    run_loop.Run();
+  }
   EXPECT_EQ(net::OK, error);
   ASSERT_TRUE(entry);
   EXPECT_TRUE(reader->IsInitialized());
@@ -370,14 +365,16 @@
 
   error = net::ERR_FAILED;
   entry.reset();
-  reader->Initialize(
-      kDriveFile,
-      net::HttpByteRange(),
-      google_apis::CreateComposedCallback(
-          base::Bind(&google_apis::test_util::RunAndQuit),
-                     google_apis::test_util::CreateCopyResultCallback(
-                         &error, &entry)));
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    reader->Initialize(
+        kDriveFile,
+        net::HttpByteRange(),
+        google_apis::test_util::CreateQuitCallback(
+            &run_loop,
+            google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
+    run_loop.Run();
+  }
   EXPECT_EQ(net::OK, error);
   ASSERT_TRUE(entry);
   EXPECT_TRUE(reader->IsInitialized());
@@ -413,14 +410,16 @@
   byte_range.set_first_byte_position(kRangeOffset);
   // Last byte position is inclusive.
   byte_range.set_last_byte_position(kRangeOffset + kRangeLength - 1);
-  reader->Initialize(
-      kDriveFile,
-      byte_range,
-      google_apis::CreateComposedCallback(
-          base::Bind(&google_apis::test_util::RunAndQuit),
-                     google_apis::test_util::CreateCopyResultCallback(
-                         &error, &entry)));
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    reader->Initialize(
+        kDriveFile,
+        byte_range,
+        google_apis::test_util::CreateQuitCallback(
+            &run_loop,
+            google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
+    run_loop.Run();
+  }
   EXPECT_EQ(net::OK, error);
   ASSERT_TRUE(entry);
   EXPECT_TRUE(reader->IsInitialized());
@@ -441,14 +440,16 @@
 
   error = net::ERR_FAILED;
   entry.reset();
-  reader->Initialize(
-      kDriveFile,
-      byte_range,
-      google_apis::CreateComposedCallback(
-          base::Bind(&google_apis::test_util::RunAndQuit),
-                     google_apis::test_util::CreateCopyResultCallback(
-                         &error, &entry)));
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    reader->Initialize(
+        kDriveFile,
+        byte_range,
+        google_apis::test_util::CreateQuitCallback(
+            &run_loop,
+            google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
+    run_loop.Run();
+  }
   EXPECT_EQ(net::OK, error);
   ASSERT_TRUE(entry);
   EXPECT_TRUE(reader->IsInitialized());
@@ -480,14 +481,16 @@
   byte_range.set_first_byte_position(kRangeOffset);
   // Last byte position is inclusive.
   byte_range.set_last_byte_position(kRangeOffset + kRangeLength - 1);
-  reader->Initialize(
-      kDriveFile,
-      byte_range,
-      google_apis::CreateComposedCallback(
-          base::Bind(&google_apis::test_util::RunAndQuit),
-                     google_apis::test_util::CreateCopyResultCallback(
-                         &error, &entry)));
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    reader->Initialize(
+        kDriveFile,
+        byte_range,
+        google_apis::test_util::CreateQuitCallback(
+            &run_loop,
+            google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
+    run_loop.Run();
+  }
   EXPECT_EQ(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE, error);
   EXPECT_FALSE(entry);
 }
diff --git a/chrome/browser/chromeos/drive/drive_integration_service.cc b/chrome/browser/chromeos/drive/drive_integration_service.cc
index b9f6b57..7978b72 100644
--- a/chrome/browser/chromeos/drive/drive_integration_service.cc
+++ b/chrome/browser/chromeos/drive/drive_integration_service.cc
@@ -19,15 +19,17 @@
 #include "chrome/browser/chromeos/drive/file_write_helper.h"
 #include "chrome/browser/chromeos/drive/job_scheduler.h"
 #include "chrome/browser/chromeos/drive/logging.h"
+#include "chrome/browser/chromeos/drive/resource_metadata.h"
+#include "chrome/browser/chromeos/drive/resource_metadata_storage.h"
 #include "chrome/browser/download/download_service.h"
 #include "chrome/browser/download/download_service_factory.h"
 #include "chrome/browser/download/download_util.h"
 #include "chrome/browser/drive/drive_api_service.h"
+#include "chrome/browser/drive/drive_api_util.h"
 #include "chrome/browser/drive/drive_notification_manager.h"
 #include "chrome/browser/drive/drive_notification_manager_factory.h"
 #include "chrome/browser/drive/gdata_wapi_service.h"
 #include "chrome/browser/google_apis/auth_service.h"
-#include "chrome/browser/google_apis/drive_api_util.h"
 #include "chrome/browser/google_apis/gdata_wapi_url_generator.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/chrome_version_info.h"
@@ -91,9 +93,11 @@
 
 // Initializes FileCache and ResourceMetadata.
 // Must be run on the same task runner used by |cache| and |resource_metadata|.
-FileError InitializeMetadata(const base::FilePath& cache_root_directory,
-                             internal::FileCache* cache,
-                             internal::ResourceMetadata* resource_metadata) {
+FileError InitializeMetadata(
+    const base::FilePath& cache_root_directory,
+    internal::ResourceMetadataStorage* metadata_storage,
+    internal::FileCache* cache,
+    internal::ResourceMetadata* resource_metadata) {
   if (!file_util::CreateDirectory(cache_root_directory.Append(
           util::kMetadataDirectory)) ||
       !file_util::CreateDirectory(cache_root_directory.Append(
@@ -114,6 +118,11 @@
 
   util::MigrateCacheFilesFromOldDirectories(cache_root_directory);
 
+  if (!metadata_storage->Initialize()) {
+    LOG(WARNING) << "Failed to initialize the metadata storage.";
+    return FILE_ERROR_FAILED;
+  }
+
   if (!cache->Initialize()) {
     LOG(WARNING) << "Failed to initialize the cache.";
     return FILE_ERROR_FAILED;
@@ -129,7 +138,7 @@
 
 DriveIntegrationService::DriveIntegrationService(
     Profile* profile,
-    google_apis::DriveServiceInterface* test_drive_service,
+    DriveServiceInterface* test_drive_service,
     const base::FilePath& test_cache_root,
     FileSystemInterface* test_file_system)
     : profile_(profile),
@@ -145,28 +154,35 @@
 
   if (test_drive_service) {
     drive_service_.reset(test_drive_service);
-  } else if (google_apis::util::IsDriveV2ApiEnabled()) {
-    drive_service_.reset(new google_apis::DriveAPIService(
+  } else if (util::IsDriveV2ApiEnabled()) {
+    drive_service_.reset(new DriveAPIService(
         g_browser_process->system_request_context(),
+        blocking_task_runner_,
         GURL(google_apis::DriveApiUrlGenerator::kBaseUrlForProduction),
+        GURL(google_apis::DriveApiUrlGenerator::kBaseDownloadUrlForProduction),
         GetDriveUserAgent()));
   } else {
-    drive_service_.reset(new google_apis::GDataWapiService(
+    drive_service_.reset(new GDataWapiService(
         g_browser_process->system_request_context(),
+        blocking_task_runner_,
         GURL(google_apis::GDataWapiUrlGenerator::kBaseUrlForProduction),
+        GURL(google_apis::GDataWapiUrlGenerator::kBaseDownloadUrlForProduction),
         GetDriveUserAgent()));
   }
-  scheduler_.reset(new JobScheduler(profile_, drive_service_.get()));
-  cache_.reset(new internal::FileCache(
+  scheduler_.reset(new JobScheduler(
+      profile_, drive_service_.get(), blocking_task_runner_.get()));
+  metadata_storage_.reset(new internal::ResourceMetadataStorage(
       cache_root_directory_.Append(util::kMetadataDirectory),
+      blocking_task_runner_.get()));
+  cache_.reset(new internal::FileCache(
+      metadata_storage_.get(),
       cache_root_directory_.Append(util::kCacheFileDirectory),
       blocking_task_runner_.get(),
       NULL /* free_disk_space_getter */));
   drive_app_registry_.reset(new DriveAppRegistry(scheduler_.get()));
 
   resource_metadata_.reset(new internal::ResourceMetadata(
-      cache_root_directory_.Append(util::kMetadataDirectory),
-      blocking_task_runner_));
+      metadata_storage_.get(), blocking_task_runner_));
 
   file_system_.reset(
       test_file_system ? test_file_system : new FileSystem(
@@ -198,6 +214,7 @@
       FROM_HERE,
       base::Bind(&InitializeMetadata,
                  cache_root_directory_,
+                 metadata_storage_.get(),
                  cache_.get(),
                  resource_metadata_.get()),
       base::Bind(&DriveIntegrationService::InitializeAfterMetadataInitialized,
@@ -207,8 +224,8 @@
 void DriveIntegrationService::Shutdown() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-  google_apis::DriveNotificationManager* drive_notification_manager =
-      google_apis::DriveNotificationManagerFactory::GetForProfile(profile_);
+  DriveNotificationManager* drive_notification_manager =
+      DriveNotificationManagerFactory::GetForProfile(profile_);
   if (drive_notification_manager)
     drive_notification_manager->RemoveObserver(this);
 
@@ -356,8 +373,8 @@
       cache_root_directory_.Append(util::kTemporaryFileDirectory));
 
   // Register for Google Drive invalidation notifications.
-  google_apis::DriveNotificationManager* drive_notification_manager =
-      google_apis::DriveNotificationManagerFactory::GetForProfile(profile_);
+  DriveNotificationManager* drive_notification_manager =
+      DriveNotificationManagerFactory::GetForProfile(profile_);
   if (drive_notification_manager) {
     drive_notification_manager->AddObserver(this);
     const bool registered =
@@ -437,7 +454,7 @@
     : BrowserContextKeyedServiceFactory(
         "DriveIntegrationService",
         BrowserContextDependencyManager::GetInstance()) {
-  DependsOn(google_apis::DriveNotificationManagerFactory::GetInstance());
+  DependsOn(DriveNotificationManagerFactory::GetInstance());
   DependsOn(DownloadServiceFactory::GetInstance());
 }
 
diff --git a/chrome/browser/chromeos/drive/drive_integration_service.h b/chrome/browser/chromeos/drive/drive_integration_service.h
index c302467..ef954d3 100644
--- a/chrome/browser/chromeos/drive/drive_integration_service.h
+++ b/chrome/browser/chromeos/drive/drive_integration_service.h
@@ -13,7 +13,7 @@
 #include "chrome/browser/chromeos/drive/file_errors.h"
 #include "chrome/browser/chromeos/drive/file_system_util.h"
 #include "chrome/browser/chromeos/drive/job_scheduler.h"
-#include "chrome/browser/google_apis/drive_notification_observer.h"
+#include "chrome/browser/drive/drive_notification_observer.h"
 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
 #include "components/browser_context_keyed_service/browser_context_keyed_service_factory.h"
 
@@ -22,15 +22,12 @@
 class SequencedTaskRunner;
 }
 
-namespace google_apis {
-class DriveServiceInterface;
-}
-
 namespace drive {
 
 class DebugInfoCollector;
 class DownloadHandler;
 class DriveAppRegistry;
+class DriveServiceInterface;
 class FileSystemInterface;
 class FileSystemProxy;
 class FileWriteHelper;
@@ -39,6 +36,7 @@
 namespace internal {
 class FileCache;
 class ResourceMetadata;
+class ResourceMetadataStorage;
 }  // namespace internal
 
 // Interface for classes that need to observe events from
@@ -67,14 +65,14 @@
 // created per-profile.
 class DriveIntegrationService
     : public BrowserContextKeyedService,
-      public google_apis::DriveNotificationObserver {
+      public DriveNotificationObserver {
  public:
   // test_drive_service, test_cache_root and test_file_system are used by tests
   // to inject customized instances.
   // Pass NULL or the empty value when not interested.
   DriveIntegrationService(
       Profile* profile,
-      google_apis::DriveServiceInterface* test_drive_service,
+      DriveServiceInterface* test_drive_service,
       const base::FilePath& test_cache_root,
       FileSystemInterface* test_file_system);
   virtual ~DriveIntegrationService();
@@ -90,11 +88,11 @@
   void AddObserver(DriveIntegrationServiceObserver* observer);
   void RemoveObserver(DriveIntegrationServiceObserver* observer);
 
-  // google_apis::DriveNotificationObserver implementation.
+  // DriveNotificationObserver implementation.
   virtual void OnNotificationReceived() OVERRIDE;
   virtual void OnPushNotificationEnabled(bool enabled) OVERRIDE;
 
-  google_apis::DriveServiceInterface* drive_service() {
+  DriveServiceInterface* drive_service() {
     return drive_service_.get();
   }
 
@@ -149,8 +147,10 @@
 
   base::FilePath cache_root_directory_;
   scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
+  scoped_ptr<internal::ResourceMetadataStorage,
+             util::DestroyHelper> metadata_storage_;
   scoped_ptr<internal::FileCache, util::DestroyHelper> cache_;
-  scoped_ptr<google_apis::DriveServiceInterface> drive_service_;
+  scoped_ptr<DriveServiceInterface> drive_service_;
   scoped_ptr<JobScheduler> scheduler_;
   scoped_ptr<DriveAppRegistry> drive_app_registry_;
   scoped_ptr<internal::ResourceMetadata,
diff --git a/chrome/browser/chromeos/drive/drive_integration_service_unittest.cc b/chrome/browser/chromeos/drive/drive_integration_service_unittest.cc
index d44281b..bc20801 100644
--- a/chrome/browser/chromeos/drive/drive_integration_service_unittest.cc
+++ b/chrome/browser/chromeos/drive/drive_integration_service_unittest.cc
@@ -19,17 +19,11 @@
     profile_.reset(new TestingProfile);
     integration_service_.reset(new DriveIntegrationService(
         profile_.get(),
-        new google_apis::DummyDriveService,
+        new DummyDriveService,
         base::FilePath(),
         new DummyFileSystem));
   }
 
-  virtual void TearDown() OVERRIDE {
-    integration_service_.reset();
-    google_apis::test_util::RunBlockingPoolTask();
-    profile_.reset();
-  }
-
  protected:
   content::TestBrowserThreadBundle thread_bundle_;
   scoped_ptr<TestingProfile> profile_;
diff --git a/chrome/browser/chromeos/drive/drive_url_request_job_unittest.cc b/chrome/browser/chromeos/drive/drive_url_request_job_unittest.cc
index 4093cc5..95dd8dc 100644
--- a/chrome/browser/chromeos/drive/drive_url_request_job_unittest.cc
+++ b/chrome/browser/chromeos/drive/drive_url_request_job_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/bind.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/run_loop.h"
 #include "base/sequenced_task_runner.h"
 #include "base/threading/sequenced_worker_pool.h"
 #include "base/threading/thread.h"
@@ -15,7 +16,6 @@
 #include "chrome/browser/chromeos/drive/file_system_util.h"
 #include "chrome/browser/chromeos/drive/test_util.h"
 #include "chrome/browser/drive/fake_drive_service.h"
-#include "chrome/browser/google_apis/task_util.h"
 #include "chrome/browser/google_apis/test_util.h"
 #include "chrome/common/url_constants.h"
 #include "content/public/browser/browser_thread.h"
@@ -104,11 +104,11 @@
 
   virtual void SetUp() OVERRIDE {
     // Initialize FakeDriveService.
-    fake_drive_service_.reset(new google_apis::FakeDriveService);
+    fake_drive_service_.reset(new FakeDriveService);
     ASSERT_TRUE(fake_drive_service_->LoadResourceListForWapi(
-        "chromeos/gdata/root_feed.json"));
+        "gdata/root_feed.json"));
     ASSERT_TRUE(fake_drive_service_->LoadAccountMetadataForWapi(
-        "chromeos/gdata/account_metadata.json"));
+        "gdata/account_metadata.json"));
 
     // Initialize FakeFileSystem.
     fake_file_system_.reset(
@@ -129,16 +129,6 @@
     test_delegate_.reset(new TestDelegate);
   }
 
-  virtual void TearDown() OVERRIDE {
-    test_delegate_.reset();
-    url_request_context_.reset();
-    test_url_request_job_factory_.reset();
-    test_network_delegate_.reset();
-
-    fake_file_system_.reset();
-    fake_drive_service_.reset();
-  }
-
   FileSystemInterface* GetFileSystem() {
     return fake_file_system_.get();
   }
@@ -156,14 +146,17 @@
         worker_thread->message_loop_proxy()));
     int error = net::ERR_FAILED;
     scoped_ptr<ResourceEntry> entry;
-    reader->Initialize(
-        file_path,
-        net::HttpByteRange(),
-        google_apis::CreateComposedCallback(
-            base::Bind(&google_apis::test_util::RunAndQuit),
-            google_apis::test_util::CreateCopyResultCallback(
-                &error, &entry)));
-    base::MessageLoop::current()->Run();
+    {
+      base::RunLoop run_loop;
+      reader->Initialize(
+          file_path,
+          net::HttpByteRange(),
+          google_apis::test_util::CreateQuitCallback(
+              &run_loop,
+              google_apis::test_util::CreateCopyResultCallback(
+                  &error, &entry)));
+      run_loop.Run();
+    }
     if (error != net::OK || !entry)
       return false;
 
@@ -181,7 +174,7 @@
 
   content::TestBrowserThreadBundle thread_bundle_;
 
-  scoped_ptr<google_apis::FakeDriveService> fake_drive_service_;
+  scoped_ptr<FakeDriveService> fake_drive_service_;
   scoped_ptr<test_util::FakeFileSystem> fake_file_system_;
 
   scoped_ptr<net::TestNetworkDelegate> test_network_delegate_;
@@ -197,7 +190,7 @@
   request.set_method("POST");  // Set non "GET" method.
   request.Start();
 
-  base::MessageLoop::current()->Run();
+  base::RunLoop().Run();
 
   EXPECT_EQ(net::URLRequestStatus::FAILED, request.status().status());
   EXPECT_EQ(net::ERR_METHOD_NOT_SUPPORTED, request.status().error());
@@ -214,7 +207,7 @@
         url_request_context_.get(), test_network_delegate_.get());
     request.Start();
 
-    base::MessageLoop::current()->Run();
+    base::RunLoop().Run();
 
     EXPECT_EQ(net::URLRequestStatus::SUCCESS, request.status().status());
     // It looks weird, but the mime type for the "File 1.txt" is "audio/mpeg"
@@ -239,7 +232,7 @@
         url_request_context_.get(), test_network_delegate_.get());
     request.Start();
 
-    base::MessageLoop::current()->Run();
+    base::RunLoop().Run();
 
     EXPECT_EQ(net::URLRequestStatus::SUCCESS, request.status().status());
     std::string mime_type;
@@ -261,7 +254,7 @@
       url_request_context_.get(), test_network_delegate_.get());
   request.Start();
 
-  base::MessageLoop::current()->Run();
+  base::RunLoop().Run();
 
   EXPECT_EQ(net::URLRequestStatus::SUCCESS, request.status().status());
   // Make sure that a hosted document triggers redirection.
@@ -276,7 +269,7 @@
       url_request_context_.get(), test_network_delegate_.get());
   request.Start();
 
-  base::MessageLoop::current()->Run();
+  base::RunLoop().Run();
 
   EXPECT_EQ(net::URLRequestStatus::FAILED, request.status().status());
   EXPECT_EQ(net::ERR_FAILED, request.status().error());
@@ -288,7 +281,7 @@
       url_request_context_.get(), test_network_delegate_.get());
   request.Start();
 
-  base::MessageLoop::current()->Run();
+  base::RunLoop().Run();
 
   EXPECT_EQ(net::URLRequestStatus::FAILED, request.status().status());
   EXPECT_EQ(net::ERR_FAILED, request.status().error());
@@ -300,7 +293,7 @@
       url_request_context_.get(), test_network_delegate_.get());
   request.Start();
 
-  base::MessageLoop::current()->Run();
+  base::RunLoop().Run();
 
   EXPECT_EQ(net::URLRequestStatus::FAILED, request.status().status());
   EXPECT_EQ(net::ERR_FILE_NOT_FOUND, request.status().error());
@@ -312,7 +305,7 @@
       url_request_context_.get(), test_network_delegate_.get());
   request.Start();
 
-  base::MessageLoop::current()->Run();
+  base::RunLoop().Run();
 
   EXPECT_EQ(net::URLRequestStatus::FAILED, request.status().status());
   EXPECT_EQ(net::ERR_INVALID_URL, request.status().error());
@@ -327,7 +320,7 @@
   request.Start();
   request.Cancel();
 
-  base::MessageLoop::current()->Run();
+  base::RunLoop().Run();
 
   EXPECT_EQ(net::URLRequestStatus::CANCELED, request.status().status());
 }
@@ -345,7 +338,7 @@
       "Range", "bytes=3-5", false /* overwrite */);
   request.Start();
 
-  base::MessageLoop::current()->Run();
+  base::RunLoop().Run();
 
   EXPECT_EQ(net::URLRequestStatus::SUCCESS, request.status().status());
 
@@ -368,7 +361,7 @@
       "Range", "Wrong Range Header Value", false /* overwrite */);
   request.Start();
 
-  base::MessageLoop::current()->Run();
+  base::RunLoop().Run();
 
   EXPECT_EQ(net::URLRequestStatus::FAILED, request.status().status());
   EXPECT_EQ(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE, request.status().error());
diff --git a/chrome/browser/chromeos/drive/dummy_file_system.h b/chrome/browser/chromeos/drive/dummy_file_system.h
index 3d13719..e9743a9 100644
--- a/chrome/browser/chromeos/drive/dummy_file_system.h
+++ b/chrome/browser/chromeos/drive/dummy_file_system.h
@@ -53,6 +53,9 @@
                          const base::Time& last_access_time,
                          const base::Time& last_modified_time,
                          const FileOperationCallback& callback) OVERRIDE {}
+  virtual void TruncateFile(const base::FilePath& file_path,
+                            int64 length,
+                            const FileOperationCallback& callback) OVERRIDE {}
   virtual void Pin(const base::FilePath& file_path,
                    const FileOperationCallback& callback) OVERRIDE {}
   virtual void Unpin(const base::FilePath& file_path,
@@ -78,7 +81,7 @@
       const GetResourceEntryCallback& callback) OVERRIDE {}
   virtual void ReadDirectoryByPath(
       const base::FilePath& file_path,
-      const ReadDirectoryWithSettingCallback& callback) OVERRIDE {}
+      const ReadDirectoryCallback& callback) OVERRIDE {}
   virtual void RefreshDirectory(
       const base::FilePath& file_path,
       const FileOperationCallback& callback) OVERRIDE {}
diff --git a/chrome/browser/chromeos/drive/fake_file_system.cc b/chrome/browser/chromeos/drive/fake_file_system.cc
index 701cf63..c477e98 100644
--- a/chrome/browser/chromeos/drive/fake_file_system.cc
+++ b/chrome/browser/chromeos/drive/fake_file_system.cc
@@ -24,8 +24,7 @@
 
 using content::BrowserThread;
 
-FakeFileSystem::FakeFileSystem(
-    google_apis::DriveServiceInterface* drive_service)
+FakeFileSystem::FakeFileSystem(DriveServiceInterface* drive_service)
     : drive_service_(drive_service),
       weak_ptr_factory_(this) {
 }
@@ -130,6 +129,12 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 }
 
+void FakeFileSystem::TruncateFile(const base::FilePath& file_path,
+                                  int64 length,
+                                  const FileOperationCallback& callback) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+}
+
 void FakeFileSystem::Pin(const base::FilePath& file_path,
                          const FileOperationCallback& callback) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -164,7 +169,7 @@
       file_path,
       base::Bind(&FakeFileSystem::GetFileContentByPathAfterGetResourceEntry,
                  weak_ptr_factory_.GetWeakPtr(),
-                 file_path, initialized_callback, get_content_callback,
+                 initialized_callback, get_content_callback,
                  completion_callback));
 }
 
@@ -201,7 +206,7 @@
 
 void FakeFileSystem::ReadDirectoryByPath(
     const base::FilePath& file_path,
-    const ReadDirectoryWithSettingCallback& callback) {
+    const ReadDirectoryCallback& callback) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 }
 
@@ -275,7 +280,6 @@
 
 // Implementation of GetFileContentByPath.
 void FakeFileSystem::GetFileContentByPathAfterGetResourceEntry(
-    const base::FilePath& file_path,
     const GetFileContentInitializedCallback& initialized_callback,
     const google_apis::GetContentCallback& get_content_callback,
     const FileOperationCallback& completion_callback,
@@ -301,14 +305,12 @@
       base::Bind(
           &FakeFileSystem::GetFileContentByPathAfterGetWapiResourceEntry,
           weak_ptr_factory_.GetWeakPtr(),
-          file_path,
           initialized_callback,
           get_content_callback,
           completion_callback));
 }
 
 void FakeFileSystem::GetFileContentByPathAfterGetWapiResourceEntry(
-    const base::FilePath& file_path,
     const GetFileContentInitializedCallback& initialized_callback,
     const google_apis::GetContentCallback& get_content_callback,
     const FileOperationCallback& completion_callback,
@@ -339,9 +341,8 @@
   initialized_callback.Run(FILE_ERROR_OK, entry.Pass(), base::FilePath(),
                            base::Bind(&base::DoNothing));
   drive_service_->DownloadFile(
-      file_path,
       cache_path,
-      GURL(gdata_entry->download_url()),
+      gdata_entry->resource_id(),
       base::Bind(&FakeFileSystem::GetFileContentByPathAfterDownloadFile,
                  weak_ptr_factory_.GetWeakPtr(),
                  completion_callback),
diff --git a/chrome/browser/chromeos/drive/fake_file_system.h b/chrome/browser/chromeos/drive/fake_file_system.h
index b61c55b..fc1c587 100644
--- a/chrome/browser/chromeos/drive/fake_file_system.h
+++ b/chrome/browser/chromeos/drive/fake_file_system.h
@@ -18,7 +18,6 @@
 namespace google_apis {
 
 class AboutResource;
-class DriveServiceInterface;
 class ResourceEntry;
 class ResourceList;
 
@@ -26,6 +25,7 @@
 
 namespace drive {
 
+class DriveServiceInterface;
 class FileSystemObserver;
 class ResourceEntry;
 
@@ -39,8 +39,7 @@
 // Currently most methods are empty (not implemented).
 class FakeFileSystem : public FileSystemInterface {
  public:
-  explicit FakeFileSystem(
-      google_apis::DriveServiceInterface* drive_service);
+  explicit FakeFileSystem(DriveServiceInterface* drive_service);
   virtual ~FakeFileSystem();
 
   // Initialization for testing. This can be called instead of Initialize
@@ -87,6 +86,9 @@
                          const base::Time& last_access_time,
                          const base::Time& last_modified_time,
                          const FileOperationCallback& callback) OVERRIDE;
+  virtual void TruncateFile(const base::FilePath& file_path,
+                            int64 length,
+                            const FileOperationCallback& callback) OVERRIDE;
   virtual void Pin(const base::FilePath& file_path,
                    const FileOperationCallback& callback) OVERRIDE;
   virtual void Unpin(const base::FilePath& file_path,
@@ -112,7 +114,7 @@
       const GetResourceEntryCallback& callback) OVERRIDE;
   virtual void ReadDirectoryByPath(
       const base::FilePath& file_path,
-      const ReadDirectoryWithSettingCallback& callback) OVERRIDE;
+      const ReadDirectoryCallback& callback) OVERRIDE;
   virtual void RefreshDirectory(
       const base::FilePath& file_path,
       const FileOperationCallback& callback) OVERRIDE;
@@ -153,14 +155,12 @@
   // 3) Otherwise start DownloadFile.
   // 4) Runs the |completion_callback| upon the download completion.
   void GetFileContentByPathAfterGetResourceEntry(
-      const base::FilePath& file_path,
       const GetFileContentInitializedCallback& initialized_callback,
       const google_apis::GetContentCallback& get_content_callback,
       const FileOperationCallback& completion_callback,
       FileError error,
       scoped_ptr<ResourceEntry> entry);
   void GetFileContentByPathAfterGetWapiResourceEntry(
-      const base::FilePath& file_path,
       const GetFileContentInitializedCallback& initialized_callback,
       const google_apis::GetContentCallback& get_content_callback,
       const FileOperationCallback& completion_callback,
@@ -197,7 +197,7 @@
       google_apis::GDataErrorCode gdata_error,
       scoped_ptr<google_apis::ResourceList> resource_list);
 
-  google_apis::DriveServiceInterface* drive_service_;  // Not owned.
+  DriveServiceInterface* drive_service_;  // Not owned.
   base::ScopedTempDir cache_dir_;
 
   // Note: This should remain the last member so it'll be destroyed and
diff --git a/chrome/browser/chromeos/drive/fake_file_system_unittest.cc b/chrome/browser/chromeos/drive/fake_file_system_unittest.cc
index cc46cc2..43011e3 100644
--- a/chrome/browser/chromeos/drive/fake_file_system_unittest.cc
+++ b/chrome/browser/chromeos/drive/fake_file_system_unittest.cc
@@ -19,11 +19,11 @@
  protected:
   virtual void SetUp() OVERRIDE {
     // Initialize FakeDriveService.
-    fake_drive_service_.reset(new google_apis::FakeDriveService);
+    fake_drive_service_.reset(new FakeDriveService);
     fake_drive_service_->LoadResourceListForWapi(
-        "chromeos/gdata/root_feed.json");
+        "gdata/root_feed.json");
     fake_drive_service_->LoadAccountMetadataForWapi(
-        "chromeos/gdata/account_metadata.json");
+        "gdata/account_metadata.json");
 
     // Create a testee instance.
     fake_file_system_.reset(new FakeFileSystem(fake_drive_service_.get()));
@@ -31,7 +31,7 @@
   }
 
   content::TestBrowserThreadBundle thread_bundle_;
-  scoped_ptr<google_apis::FakeDriveService> fake_drive_service_;
+  scoped_ptr<FakeDriveService> fake_drive_service_;
   scoped_ptr<FakeFileSystem> fake_file_system_;
 };
 
diff --git a/chrome/browser/chromeos/drive/file_cache.cc b/chrome/browser/chromeos/drive/file_cache.cc
index 1894aa6..2fbce21 100644
--- a/chrome/browser/chromeos/drive/file_cache.cc
+++ b/chrome/browser/chromeos/drive/file_cache.cc
@@ -16,6 +16,7 @@
 #include "chrome/browser/chromeos/drive/drive.pb.h"
 #include "chrome/browser/chromeos/drive/file_cache_metadata.h"
 #include "chrome/browser/chromeos/drive/file_system_util.h"
+#include "chrome/browser/chromeos/drive/resource_metadata_storage.h"
 #include "chrome/browser/google_apis/task_util.h"
 #include "chromeos/chromeos_constants.h"
 #include "content/public/browser/browser_thread.h"
@@ -80,7 +81,7 @@
 // Moves the file.
 bool MoveFile(const base::FilePath& source_path,
               const base::FilePath& dest_path) {
-  if (!file_util::Move(source_path, dest_path)) {
+  if (!base::Move(source_path, dest_path)) {
     LOG(ERROR) << "Failed to move " << source_path.value()
                << " to " << dest_path.value();
     return false;
@@ -122,7 +123,7 @@
     if (!path_to_keep.empty() && current == path_to_keep)
       continue;
 
-    success = file_util::Delete(current, false);
+    success = base::Delete(current, false);
     if (!success)
       DVLOG(1) << "Error deleting " << current.value();
     else
@@ -153,15 +154,27 @@
   callback.Run(success, *cache_entry);
 }
 
+// Calls |iteration_callback| with each entry in |cache|.
+void IterateCache(FileCache* cache,
+                  const CacheIterateCallback& iteration_callback) {
+  scoped_ptr<FileCache::Iterator> it = cache->GetIterator();
+  for (; !it->IsAtEnd(); it->Advance())
+    iteration_callback.Run(it->GetID(), it->GetValue());
+  DCHECK(!it->HasError());
+}
+
 }  // namespace
 
-FileCache::FileCache(const base::FilePath& metadata_directory,
+const base::FilePath::CharType FileCache::kOldCacheMetadataDBName[] =
+    FILE_PATH_LITERAL("cache_metadata.db");
+
+FileCache::FileCache(ResourceMetadataStorage* storage,
                      const base::FilePath& cache_file_directory,
                      base::SequencedTaskRunner* blocking_task_runner,
                      FreeDiskSpaceGetterInterface* free_disk_space_getter)
-    : metadata_directory_(metadata_directory),
-      cache_file_directory_(cache_file_directory),
+    : cache_file_directory_(cache_file_directory),
       blocking_task_runner_(blocking_task_runner),
+      storage_(storage),
       free_disk_space_getter_(free_disk_space_getter),
       weak_ptr_factory_(this) {
   DCHECK(blocking_task_runner_.get());
@@ -225,7 +238,7 @@
                               FileCacheEntry* entry) {
   DCHECK(entry);
   AssertOnSequencedWorkerPool();
-  return metadata_->GetCacheEntry(resource_id, entry) &&
+  return storage_->GetCacheEntry(resource_id, entry) &&
       CheckIfMd5Matches(md5, *entry);
 }
 
@@ -238,20 +251,15 @@
 
   blocking_task_runner_->PostTaskAndReply(
       FROM_HERE,
-      base::Bind(&FileCache::Iterate,
+      base::Bind(&IterateCache,
                  base::Unretained(this),
                  google_apis::CreateRelayCallback(iteration_callback)),
       completion_callback);
 }
 
-void FileCache::Iterate(const CacheIterateCallback& iteration_callback) {
+scoped_ptr<FileCache::Iterator> FileCache::GetIterator() {
   AssertOnSequencedWorkerPool();
-  DCHECK(!iteration_callback.is_null());
-
-  scoped_ptr<FileCacheMetadata::Iterator> it = metadata_->GetIterator();
-  for (; !it->IsAtEnd(); it->Advance())
-    iteration_callback.Run(it->GetKey(), it->GetValue());
-  DCHECK(!it->HasError());
+  return storage_->GetCacheEntryIterator();
 }
 
 void FileCache::FreeDiskSpaceIfNeededForOnUIThread(
@@ -280,13 +288,14 @@
   DVLOG(1) << "Freeing up disk space for " << num_bytes;
 
   // Remove all entries unless specially marked.
-  scoped_ptr<FileCacheMetadata::Iterator> it = metadata_->GetIterator();
+  scoped_ptr<ResourceMetadataStorage::CacheEntryIterator> it =
+      storage_->GetCacheEntryIterator();
   for (; !it->IsAtEnd(); it->Advance()) {
     const FileCacheEntry& entry = it->GetValue();
     if (!entry.is_pinned() &&
         !entry.is_dirty() &&
-        !mounted_files_.count(it->GetKey()))
-      metadata_->RemoveCacheEntry(it->GetKey());
+        !mounted_files_.count(it->GetID()))
+      storage_->RemoveCacheEntry(it->GetID());
   }
   DCHECK(!it->HasError());
 
@@ -301,7 +310,7 @@
        current = enumerator.Next()) {
     util::ParseCacheFilePath(current, &resource_id, &md5);
     if (!GetCacheEntry(resource_id, md5, &entry))
-      file_util::Delete(current, false /* recursive */);
+      base::Delete(current, false /* recursive */);
   }
 
   // Check the disk space again.
@@ -388,9 +397,9 @@
   AssertOnSequencedWorkerPool();
 
   FileCacheEntry cache_entry;
-  metadata_->GetCacheEntry(resource_id, &cache_entry);
+  storage_->GetCacheEntry(resource_id, &cache_entry);
   cache_entry.set_is_pinned(true);
-  metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry);
+  storage_->PutCacheEntry(resource_id, cache_entry);
   return FILE_ERROR_OK;
 }
 
@@ -411,16 +420,16 @@
 
   // Unpinning a file means its entry must exist in cache.
   FileCacheEntry cache_entry;
-  if (!metadata_->GetCacheEntry(resource_id, &cache_entry))
+  if (!storage_->GetCacheEntry(resource_id, &cache_entry))
     return FILE_ERROR_NOT_FOUND;
 
   // Now that file operations have completed, update metadata.
   if (cache_entry.is_present()) {
     cache_entry.set_is_pinned(false);
-    metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry);
+    storage_->PutCacheEntry(resource_id, cache_entry);
   } else {
     // Remove the existing entry if we are unpinning a non-present file.
-    metadata_->RemoveCacheEntry(resource_id);
+    storage_->RemoveCacheEntry(resource_id);
   }
 
   // Now it's a chance to free up space if needed.
@@ -487,7 +496,7 @@
   // Marking a file dirty means its entry and actual file blob must exist in
   // cache.
   FileCacheEntry cache_entry;
-  if (!metadata_->GetCacheEntry(resource_id, &cache_entry) ||
+  if (!storage_->GetCacheEntry(resource_id, &cache_entry) ||
       !cache_entry.is_present()) {
     LOG(WARNING) << "Can't mark dirty a file that wasn't cached: res_id="
                  << resource_id
@@ -511,7 +520,7 @@
   // Now that file operations have completed, update metadata.
   cache_entry.set_md5(md5);
   cache_entry.set_is_dirty(true);
-  metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry);
+  storage_->PutCacheEntry(resource_id, cache_entry);
   return FILE_ERROR_OK;
 }
 
@@ -525,7 +534,7 @@
 
   // Clearing a dirty file means its entry and actual file blob must exist in
   // cache.
-  if (!metadata_->GetCacheEntry(resource_id, &cache_entry) ||
+  if (!storage_->GetCacheEntry(resource_id, &cache_entry) ||
       !cache_entry.is_present()) {
     LOG(WARNING) << "Can't clear dirty state of a file that wasn't cached: "
                  << "res_id=" << resource_id
@@ -552,7 +561,7 @@
   // Now that file operations have completed, update metadata.
   cache_entry.set_md5(md5);
   cache_entry.set_is_dirty(false);
-  metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry);
+  storage_->PutCacheEntry(resource_id, cache_entry);
   return FILE_ERROR_OK;
 }
 
@@ -577,7 +586,7 @@
   FileCacheEntry cache_entry;
 
   // If entry doesn't exist, nothing to do.
-  if (!metadata_->GetCacheEntry(resource_id, &cache_entry))
+  if (!storage_->GetCacheEntry(resource_id, &cache_entry))
     return FILE_ERROR_OK;
 
   // Cannot delete a dirty or mounted file.
@@ -592,7 +601,7 @@
   DeleteFilesSelectively(path_to_delete, path_to_keep);
 
   // Now that all file operations have completed, remove from metadata.
-  metadata_->RemoveCacheEntry(resource_id);
+  storage_->RemoveCacheEntry(resource_id);
 
   return FILE_ERROR_OK;
 }
@@ -611,23 +620,14 @@
 bool FileCache::Initialize() {
   AssertOnSequencedWorkerPool();
 
-  metadata_.reset(new FileCacheMetadata(blocking_task_runner_.get()));
-
-  switch (metadata_->Initialize(metadata_directory_)) {
-    case FileCacheMetadata::INITIALIZE_FAILED:
-      return false;
-
-    case FileCacheMetadata::INITIALIZE_OPENED:  // Do nothing.
-      break;
-
-    case FileCacheMetadata::INITIALIZE_CREATED: {
-      CacheMap cache_map;
-      ScanCacheDirectory(cache_file_directory_, &cache_map);
-      for (CacheMap::const_iterator it = cache_map.begin();
-           it != cache_map.end(); ++it) {
-        metadata_->AddOrUpdateCacheEntry(it->first, it->second);
-      }
-      break;
+  if (!ImportOldDB(storage_->directory_path().Append(
+          kOldCacheMetadataDBName)) &&
+      !storage_->opened_existing_db()) {
+    CacheMap cache_map;
+    ScanCacheDirectory(cache_file_directory_, &cache_map);
+    for (CacheMap::const_iterator it = cache_map.begin();
+         it != cache_map.end(); ++it) {
+      storage_->PutCacheEntry(it->first, it->second);
     }
   }
   return true;
@@ -669,7 +669,7 @@
     return FILE_ERROR_NO_SPACE;
 
   FileCacheEntry cache_entry;
-  metadata_->GetCacheEntry(resource_id, &cache_entry);
+  storage_->GetCacheEntry(resource_id, &cache_entry);
 
   // If file is dirty or mounted, return error.
   if (cache_entry.is_dirty() || mounted_files_.count(resource_id))
@@ -716,7 +716,7 @@
     cache_entry.set_md5(md5);
     cache_entry.set_is_present(true);
     cache_entry.set_is_dirty(false);
-    metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry);
+    storage_->PutCacheEntry(resource_id, cache_entry);
   }
 
   return success ? FILE_ERROR_OK : FILE_ERROR_FAILED;
@@ -729,7 +729,7 @@
 
   // Get cache entry associated with the resource_id and md5
   FileCacheEntry cache_entry;
-  if (!metadata_->GetCacheEntry(resource_id, &cache_entry))
+  if (!storage_->GetCacheEntry(resource_id, &cache_entry))
     return FILE_ERROR_NOT_FOUND;
 
   if (mounted_files_.count(resource_id))
@@ -777,9 +777,10 @@
   AssertOnSequencedWorkerPool();
 
   // Remove entries on the metadata.
-  scoped_ptr<FileCacheMetadata::Iterator> it = metadata_->GetIterator();
+  scoped_ptr<ResourceMetadataStorage::CacheEntryIterator> it =
+      storage_->GetCacheEntryIterator();
   for (; !it->IsAtEnd(); it->Advance())
-    metadata_->RemoveCacheEntry(it->GetKey());
+    storage_->RemoveCacheEntry(it->GetID());
 
   if (it->HasError())
     return false;
@@ -790,7 +791,7 @@
                                   base::FileEnumerator::FILES);
   for (base::FilePath file = enumerator.Next(); !file.empty();
        file = enumerator.Next())
-    file_util::Delete(file, false /* recursive */);
+    base::Delete(file, false /* recursive */);
 
   return true;
 }
@@ -808,5 +809,32 @@
   return (free_space >= num_bytes);
 }
 
+bool FileCache::ImportOldDB(const base::FilePath& old_db_path) {
+  if (!file_util::PathExists(old_db_path))  // Old DB is not there, do nothing.
+    return false;
+
+  // Copy all entries stored in the old DB.
+  bool imported = false;
+  {
+    FileCacheMetadata old_data(blocking_task_runner_);
+    if (old_data.Initialize(old_db_path) ==
+        FileCacheMetadata::INITIALIZE_OPENED) {
+      scoped_ptr<FileCacheMetadata::Iterator> it = old_data.GetIterator();
+      for (; !it->IsAtEnd(); it->Advance()) {
+        FileCacheEntry entry;
+        if (storage_->GetCacheEntry(it->GetKey(), &entry))
+          continue;  // Do not overwrite.
+
+        storage_->PutCacheEntry(it->GetKey(), it->GetValue());
+      }
+      imported = true;
+    }
+  }
+
+  // Delete old DB.
+  base::Delete(old_db_path, true /* recursive */ );
+  return imported;
+}
+
 }  // namespace internal
 }  // namespace drive
diff --git a/chrome/browser/chromeos/drive/file_cache.h b/chrome/browser/chromeos/drive/file_cache.h
index be0ccff..398e193 100644
--- a/chrome/browser/chromeos/drive/file_cache.h
+++ b/chrome/browser/chromeos/drive/file_cache.h
@@ -14,6 +14,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/chromeos/drive/file_errors.h"
+#include "chrome/browser/chromeos/drive/resource_metadata_storage.h"
 
 class Profile;
 
@@ -41,8 +42,6 @@
 
 namespace internal {
 
-class FileCacheMetadata;
-
 // Callback for GetFileFromCache.
 typedef base::Callback<void(FileError error,
                             const base::FilePath& cache_file_path)>
@@ -74,8 +73,13 @@
     FILE_OPERATION_COPY,
   };
 
-  // |metadata_directory| stores the metadata and |cache_file_directory| stores
-  // cached files.
+  typedef ResourceMetadataStorage::CacheEntryIterator Iterator;
+
+  // Name of the cache metadata DB previously used.
+  // TODO(hashimoto): Remove this at some point.
+  static const base::FilePath::CharType kOldCacheMetadataDBName[];
+
+  // |cache_file_directory| stores cached files.
   //
   // |blocking_task_runner| is used to post a task to the blocking worker
   // pool for file operations. Must not be null.
@@ -84,7 +88,7 @@
   // getter for testing. NULL must be passed for production code.
   //
   // Must be called on the UI thread.
-  FileCache(const base::FilePath& metadata_directory,
+  FileCache(ResourceMetadataStorage* storage,
             const base::FilePath& cache_file_directory,
             base::SequencedTaskRunner* blocking_task_runner,
             FreeDiskSpaceGetterInterface* free_disk_space_getter);
@@ -117,10 +121,8 @@
   void IterateOnUIThread(const CacheIterateCallback& iteration_callback,
                          const base::Closure& completion_callback);
 
-  // Iterates all files in the cache and calls |iteration_callback| for each
-  // file. |completion_callback| is run upon completion.
-  // TODO(hashimoto): Stop using callbacks for this method. crbug.com/242818
-  void Iterate(const CacheIterateCallback& iteration_callback);
+  // Returns an object to iterate over entries.
+  scoped_ptr<Iterator> GetIterator();
 
 
   // Runs FreeDiskSpaceIfNeededFor() on |blocking_task_runner_|, and calls
@@ -293,13 +295,15 @@
   // bytes, while keeping kMinFreeSpace bytes on the disk.
   bool HasEnoughSpaceFor(int64 num_bytes, const base::FilePath& path);
 
-  const base::FilePath metadata_directory_;
+  // Imports old format DB from |old_db_path| and deletes it.
+  // TODO(hashimoto): Remove this method and FileCacheMetadata at some point.
+  bool ImportOldDB(const base::FilePath& old_db_path);
+
   const base::FilePath cache_file_directory_;
 
   scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
 
-  // The cache state data. This member must be access only on the blocking pool.
-  scoped_ptr<FileCacheMetadata> metadata_;
+  ResourceMetadataStorage* storage_;
 
   FreeDiskSpaceGetterInterface* free_disk_space_getter_;  // Not owned.
 
diff --git a/chrome/browser/chromeos/drive/file_cache_metadata.cc b/chrome/browser/chromeos/drive/file_cache_metadata.cc
index 03ca62e..b421b43 100644
--- a/chrome/browser/chromeos/drive/file_cache_metadata.cc
+++ b/chrome/browser/chromeos/drive/file_cache_metadata.cc
@@ -29,10 +29,6 @@
 
 }  // namespace
 
-// static
-const base::FilePath::CharType* FileCacheMetadata::kCacheMetadataDBPath =
-    FILE_PATH_LITERAL("cache_metadata.db");
-
 FileCacheMetadata::Iterator::Iterator(scoped_ptr<leveldb::Iterator> it)
     : it_(it.Pass()) {
   base::ThreadRestrictions::AssertIOAllowed();
@@ -96,12 +92,9 @@
 }
 
 FileCacheMetadata::InitializeResult FileCacheMetadata::Initialize(
-    const base::FilePath& db_directory_path) {
+    const base::FilePath& db_path) {
   AssertOnSequencedWorkerPool();
 
-  const base::FilePath db_path = db_directory_path.Append(kCacheMetadataDBPath);
-  DVLOG(1) << "db path=" << db_path.value();
-
   bool created = !file_util::PathExists(db_path);
 
   leveldb::DB* level_db = NULL;
@@ -117,7 +110,7 @@
     LOG(WARNING) << "Cache db failed to open: " << db_status.ToString();
     uma_status = db_status.IsCorruption() ?
         DB_OPEN_FAILURE_CORRUPTION : DB_OPEN_FAILURE_OTHER;
-    const bool deleted = file_util::Delete(db_path, true);
+    const bool deleted = base::Delete(db_path, true);
     DCHECK(deleted);
     db_status = leveldb::DB::Open(options, db_path.value(), &level_db);
     if (!db_status.ok()) {
diff --git a/chrome/browser/chromeos/drive/file_cache_metadata.h b/chrome/browser/chromeos/drive/file_cache_metadata.h
index e98158f..7baf395 100644
--- a/chrome/browser/chromeos/drive/file_cache_metadata.h
+++ b/chrome/browser/chromeos/drive/file_cache_metadata.h
@@ -28,11 +28,11 @@
 // FileCacheMetadata maintains metadata of FileCache's cached files.
 // This class only manages metadata. File operations are done by FileCache.
 // All member access including ctor and dtor must be made on the blocking pool.
+//
+// OBSOLETE: This class is maintained only for importing old data.
+// TODO(hashimoto): Remove this class at some point.
 class FileCacheMetadata {
  public:
-  // Database path.
-  static const base::FilePath::CharType* kCacheMetadataDBPath;
-
   // Result of Initialize().
   enum InitializeResult {
     INITIALIZE_FAILED,  // Could not open nor create DB.
@@ -79,7 +79,7 @@
   ~FileCacheMetadata();
 
   // Initialize the cache metadata store. Returns true on success.
-  InitializeResult Initialize(const base::FilePath& db_directory_path);
+  InitializeResult Initialize(const base::FilePath& db_path);
   // Adds a new cache entry corresponding to |resource_id| if it doesn't
   // exist, otherwise update the existing entry.
   void AddOrUpdateCacheEntry(const std::string& resource_id,
diff --git a/chrome/browser/chromeos/drive/file_cache_metadata_unittest.cc b/chrome/browser/chromeos/drive/file_cache_metadata_unittest.cc
index 4f80668..7ceadf6 100644
--- a/chrome/browser/chromeos/drive/file_cache_metadata_unittest.cc
+++ b/chrome/browser/chromeos/drive/file_cache_metadata_unittest.cc
@@ -17,18 +17,12 @@
 
 class FileCacheMetadataTest : public testing::Test {
  public:
-  FileCacheMetadataTest() {}
-
   virtual void SetUp() OVERRIDE {
     // Create cache directories.
     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
     metadata_.reset(new FileCacheMetadata(NULL));
   }
 
-  virtual void TearDown() OVERRIDE {
-    metadata_.reset();
-  }
-
  protected:
   base::ScopedTempDir temp_dir_;
   scoped_ptr<FileCacheMetadata> metadata_;
@@ -38,7 +32,7 @@
 // RemoveTemporaryFiles.
 TEST_F(FileCacheMetadataTest, CacheTest) {
   ASSERT_EQ(FileCacheMetadata::INITIALIZE_CREATED,
-            metadata_->Initialize(temp_dir_.path()));
+            metadata_->Initialize(temp_dir_.path().AppendASCII("test.db")));
 
   // Save an initial entry.
   std::string test_resource_id("test_resource_id");
@@ -108,22 +102,22 @@
 }
 
 TEST_F(FileCacheMetadataTest, Initialize) {
-  const base::FilePath db_path =
-      temp_dir_.path().Append(FileCacheMetadata::kCacheMetadataDBPath);
+  const base::FilePath db_path = temp_dir_.path().AppendASCII("test.db");
 
   // Try to open a bogus file.
   ASSERT_TRUE(
       google_apis::test_util::WriteStringToFile(db_path, "Hello world"));
   ASSERT_EQ(FileCacheMetadata::INITIALIZE_CREATED,
-            metadata_->Initialize(temp_dir_.path()));
+            metadata_->Initialize(db_path));
 
   // Open an existing DB.
   metadata_.reset(new FileCacheMetadata(NULL));
   EXPECT_EQ(FileCacheMetadata::INITIALIZE_OPENED,
-            metadata_->Initialize(temp_dir_.path()));
+            metadata_->Initialize(db_path));
 
   // Try to open a nonexistent path.
-  base::FilePath non_existent_path(FILE_PATH_LITERAL("/somewhere/nonexistent"));
+  base::FilePath non_existent_path(FILE_PATH_LITERAL(
+      "/somewhere/nonexistent/test.db"));
   metadata_.reset(new FileCacheMetadata(NULL));
   EXPECT_EQ(FileCacheMetadata::INITIALIZE_FAILED,
             metadata_->Initialize(non_existent_path));
diff --git a/chrome/browser/chromeos/drive/file_cache_unittest.cc b/chrome/browser/chromeos/drive/file_cache_unittest.cc
index c28d20e..8a8e37b 100644
--- a/chrome/browser/chromeos/drive/file_cache_unittest.cc
+++ b/chrome/browser/chromeos/drive/file_cache_unittest.cc
@@ -14,7 +14,9 @@
 #include "base/threading/sequenced_worker_pool.h"
 #include "chrome/browser/chromeos/drive/drive.pb.h"
 #include "chrome/browser/chromeos/drive/fake_free_disk_space_getter.h"
+#include "chrome/browser/chromeos/drive/file_cache_metadata.h"
 #include "chrome/browser/chromeos/drive/file_system_util.h"
+#include "chrome/browser/chromeos/drive/resource_metadata_storage.h"
 #include "chrome/browser/chromeos/drive/test_util.h"
 #include "chrome/browser/google_apis/test_util.h"
 #include "content/public/browser/browser_thread.h"
@@ -73,13 +75,27 @@
         content::BrowserThread::GetBlockingPool();
     blocking_task_runner_ =
         pool->GetSequencedTaskRunner(pool->GetSequenceToken());
+
+    metadata_storage_.reset(new ResourceMetadataStorage(
+        temp_dir_.path(), blocking_task_runner_));
+
+    bool success = false;
+    base::PostTaskAndReplyWithResult(
+        blocking_task_runner_,
+        FROM_HERE,
+        base::Bind(&ResourceMetadataStorage::Initialize,
+                   base::Unretained(metadata_storage_.get())),
+        google_apis::test_util::CreateCopyResultCallback(&success));
+    google_apis::test_util::RunBlockingPoolTask();
+    ASSERT_TRUE(success);
+
     cache_.reset(new FileCache(
-        temp_dir_.path().Append(util::kMetadataDirectory),
+        metadata_storage_.get(),
         temp_dir_.path().Append(util::kCacheFileDirectory),
         blocking_task_runner_.get(),
         fake_free_disk_space_getter_.get()));
 
-    bool success = false;
+    success = false;
     base::PostTaskAndReplyWithResult(
         blocking_task_runner_,
         FROM_HERE,
@@ -90,10 +106,6 @@
     ASSERT_TRUE(success);
   }
 
-  virtual void TearDown() OVERRIDE {
-    cache_.reset();
-  }
-
   void TestGetFileFromCacheByResourceIdAndMd5(
       const std::string& resource_id,
       const std::string& md5,
@@ -418,6 +430,8 @@
   base::ScopedTempDir temp_dir_;
   base::FilePath dummy_file_path_;
 
+  scoped_ptr<ResourceMetadataStorage, test_util::DestroyHelperForTests>
+      metadata_storage_;
   scoped_ptr<FileCache, test_util::DestroyHelperForTests> cache_;
   scoped_ptr<FakeFreeDiskSpaceGetter> fake_free_disk_space_getter_;
 
@@ -852,20 +866,6 @@
   EXPECT_EQ(0U, CountCacheFiles(resource_id, md5));
 }
 
-// Don't use TEST_F, as we don't want SetUp() and TearDown() for this test.
-TEST(FileCacheExtraTest, InitializationFailure) {
-  content::TestBrowserThreadBundle thread_bundle;
-
-  // Set the cache root to a non existent path, so the initialization fails.
-  scoped_ptr<FileCache, test_util::DestroyHelperForTests> cache(new FileCache(
-      base::FilePath::FromUTF8Unsafe("/somewhere/nonexistent/blah/meta"),
-      base::FilePath::FromUTF8Unsafe("/somewhere/nonexistent/blah/files"),
-      base::MessageLoopProxy::current(),
-      NULL /* free_disk_space_getter */));
-
-  EXPECT_FALSE(cache->Initialize());
-}
-
 TEST_F(FileCacheTestOnUIThread, UpdatePinnedCache) {
   std::string resource_id("pdf:1a2b");
   std::string md5("abcdef0123456789");
@@ -896,41 +896,58 @@
 
     fake_free_disk_space_getter_.reset(new FakeFreeDiskSpaceGetter);
 
-    cache_.reset(new FileCache(
+    metadata_storage_.reset(new ResourceMetadataStorage(
         temp_dir_.path().Append(util::kMetadataDirectory),
+        base::MessageLoopProxy::current()));
+    ASSERT_TRUE(metadata_storage_->Initialize());
+
+    cache_.reset(new FileCache(
+        metadata_storage_.get(),
         temp_dir_.path().Append(util::kCacheFileDirectory),
         base::MessageLoopProxy::current(),
         fake_free_disk_space_getter_.get()));
-
     ASSERT_TRUE(cache_->Initialize());
   }
 
-  virtual void TearDown() OVERRIDE {
-    cache_.reset();
+  static bool ImportOldDB(FileCache* cache, const base::FilePath& old_db_path) {
+    return cache->ImportOldDB(old_db_path);
   }
 
   content::TestBrowserThreadBundle thread_bundle_;
   base::ScopedTempDir temp_dir_;
 
+  scoped_ptr<ResourceMetadataStorage, test_util::DestroyHelperForTests>
+      metadata_storage_;
   scoped_ptr<FileCache, test_util::DestroyHelperForTests> cache_;
   scoped_ptr<FakeFreeDiskSpaceGetter> fake_free_disk_space_getter_;
 };
 
 TEST_F(FileCacheTest, ScanCacheFile) {
   // Set up files in the cache directory.
-  const base::FilePath directory =
+  const base::FilePath file_directory =
       temp_dir_.path().Append(util::kCacheFileDirectory);
   ASSERT_TRUE(google_apis::test_util::WriteStringToFile(
-      directory.AppendASCII("id_foo.md5foo"), "foo"));
+      file_directory.AppendASCII("id_foo.md5foo"), "foo"));
   ASSERT_TRUE(google_apis::test_util::WriteStringToFile(
-      directory.AppendASCII("id_bar.local"), "bar"));
+      file_directory.AppendASCII("id_bar.local"), "bar"));
 
   // Remove the existing DB.
-  ASSERT_TRUE(file_util::Delete(
-      temp_dir_.path().Append(util::kMetadataDirectory), true /* recursive */));
+  const base::FilePath metadata_directory =
+      temp_dir_.path().Append(util::kMetadataDirectory);
+  ASSERT_TRUE(base::Delete(metadata_directory, true /* recursive */));
+
+  // Put an empty file with the same name as old DB.
+  // This file cannot be opened by ImportOldDB() and will be dismissed.
+  ASSERT_TRUE(file_util::CreateDirectory(metadata_directory));
+  ASSERT_TRUE(google_apis::test_util::WriteStringToFile(
+      metadata_directory.Append(FileCache::kOldCacheMetadataDBName), ""));
 
   // Create a new cache and initialize it.
-  cache_.reset(new FileCache(temp_dir_.path().Append(util::kMetadataDirectory),
+  metadata_storage_.reset(new ResourceMetadataStorage(
+      metadata_directory, base::MessageLoopProxy::current()));
+  ASSERT_TRUE(metadata_storage_->Initialize());
+
+  cache_.reset(new FileCache(metadata_storage_.get(),
                              temp_dir_.path().Append(util::kCacheFileDirectory),
                              base::MessageLoopProxy::current(),
                              fake_free_disk_space_getter_.get()));
@@ -989,5 +1006,41 @@
   EXPECT_FALSE(cache_->FreeDiskSpaceIfNeededFor(kNeededBytes));
 }
 
+TEST_F(FileCacheTest, ImportOldDB) {
+  const base::FilePath old_db_path = temp_dir_.path().AppendASCII("old_db.db");
+
+  const std::string key1 = "key1";
+  const std::string md5_1 = "md5_1";
+  const std::string key2 = "key2";
+  const std::string md5_2 = "md5_2";
+
+  // Set up data to be imported.
+  {
+    FileCacheMetadata old_metadata(NULL);
+    ASSERT_TRUE(old_metadata.Initialize(old_db_path));
+
+    FileCacheEntry entry;
+    entry.set_md5(md5_1);
+    old_metadata.AddOrUpdateCacheEntry(key1, entry);
+
+    entry.set_md5(md5_2);
+    old_metadata.AddOrUpdateCacheEntry(key2, entry);
+  }
+  EXPECT_TRUE(file_util::PathExists(old_db_path));
+
+  // Do import.
+  EXPECT_TRUE(ImportOldDB(cache_.get(), old_db_path));
+
+  // Old DB should be removed.
+  EXPECT_FALSE(file_util::PathExists(old_db_path));
+
+  // Data is imported correctly.
+  FileCacheEntry entry;
+  EXPECT_TRUE(cache_->GetCacheEntry(key1, std::string(), &entry));
+  EXPECT_EQ(md5_1, entry.md5());
+  EXPECT_TRUE(cache_->GetCacheEntry(key2, std::string(), &entry));
+  EXPECT_EQ(md5_2, entry.md5());
+}
+
 }  // namespace internal
 }  // namespace drive
diff --git a/chrome/browser/chromeos/drive/file_change_unittest.cc b/chrome/browser/chromeos/drive/file_change_unittest.cc
index 619f37f..97eead4 100644
--- a/chrome/browser/chromeos/drive/file_change_unittest.cc
+++ b/chrome/browser/chromeos/drive/file_change_unittest.cc
@@ -3,7 +3,8 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/chromeos/drive/file_change.h"
-#include "testing/gmock/include/gmock/gmock.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
 
 namespace drive {
 
diff --git a/chrome/browser/chromeos/drive/file_system.cc b/chrome/browser/chromeos/drive/file_system.cc
index d24fbf6..53c2e9d 100644
--- a/chrome/browser/chromeos/drive/file_system.cc
+++ b/chrome/browser/chromeos/drive/file_system.cc
@@ -24,6 +24,7 @@
 #include "chrome/browser/chromeos/drive/file_system/remove_operation.h"
 #include "chrome/browser/chromeos/drive/file_system/search_operation.h"
 #include "chrome/browser/chromeos/drive/file_system/touch_operation.h"
+#include "chrome/browser/chromeos/drive/file_system/truncate_operation.h"
 #include "chrome/browser/chromeos/drive/file_system/update_operation.h"
 #include "chrome/browser/chromeos/drive/file_system_observer.h"
 #include "chrome/browser/chromeos/drive/file_system_util.h"
@@ -31,9 +32,9 @@
 #include "chrome/browser/chromeos/drive/remove_stale_cache_files.h"
 #include "chrome/browser/chromeos/drive/search_metadata.h"
 #include "chrome/browser/chromeos/drive/sync_client.h"
+#include "chrome/browser/drive/drive_api_util.h"
 #include "chrome/browser/drive/drive_service_interface.h"
 #include "chrome/browser/google_apis/drive_api_parser.h"
-#include "chrome/browser/google_apis/drive_api_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/pref_names.h"
 #include "content/public/browser/browser_thread.h"
@@ -72,7 +73,7 @@
 FileSystem::FileSystem(
     Profile* profile,
     internal::FileCache* cache,
-    google_apis::DriveServiceInterface* drive_service,
+    DriveServiceInterface* drive_service,
     JobScheduler* scheduler,
     internal::ResourceMetadata* resource_metadata,
     base::SequencedTaskRunner* blocking_task_runner,
@@ -129,6 +130,13 @@
                                        cache_));
   touch_operation_.reset(new file_system::TouchOperation(
       blocking_task_runner_.get(), observer, scheduler_, resource_metadata_));
+  truncate_operation_.reset(
+      new file_system::TruncateOperation(blocking_task_runner_.get(),
+                                         observer,
+                                         scheduler_,
+                                         resource_metadata_,
+                                         cache_,
+                                         temporary_file_directory_));
   download_operation_.reset(
       new file_system::DownloadOperation(blocking_task_runner_.get(),
                                          observer,
@@ -343,6 +351,14 @@
       file_path, last_access_time, last_modified_time, callback);
 }
 
+void FileSystem::TruncateFile(const base::FilePath& file_path,
+                              int64 length,
+                              const FileOperationCallback& callback) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(!callback.is_null());
+  truncate_operation_->Truncate(file_path, length, callback);
+}
+
 void FileSystem::Pin(const base::FilePath& file_path,
                      const FileOperationCallback& callback) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -564,7 +580,7 @@
 
 void FileSystem::ReadDirectoryByPath(
     const base::FilePath& directory_path,
-    const ReadDirectoryWithSettingCallback& callback) {
+    const ReadDirectoryCallback& callback) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(!callback.is_null());
 
@@ -624,17 +640,13 @@
 
 void FileSystem::ReadDirectoryByPathAfterLoad(
     const base::FilePath& directory_path,
-    const ReadDirectoryWithSettingCallback& callback,
+    const ReadDirectoryCallback& callback,
     FileError error) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(!callback.is_null());
 
-  if (error != FILE_ERROR_OK) {
-    callback.Run(error,
-                 hide_hosted_docs_,
-                 scoped_ptr<ResourceEntryVector>());
-    return;
-  }
+  DLOG_IF(INFO, error != FILE_ERROR_OK) << "LoadIfNeeded failed. "
+                                        << FileErrorToString(error);
 
   resource_metadata_->ReadDirectoryByPathOnUIThread(
       directory_path,
@@ -644,7 +656,7 @@
 }
 
 void FileSystem::ReadDirectoryByPathAfterRead(
-    const ReadDirectoryWithSettingCallback& callback,
+    const ReadDirectoryCallback& callback,
     FileError error,
     scoped_ptr<ResourceEntryVector> entries) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -652,13 +664,21 @@
 
   if (error != FILE_ERROR_OK) {
     callback.Run(error,
-                 hide_hosted_docs_,
                  scoped_ptr<ResourceEntryVector>());
     return;
   }
   DCHECK(entries.get());  // This is valid for empty directories too.
 
-  callback.Run(FILE_ERROR_OK, hide_hosted_docs_, entries.Pass());
+  // TODO(satorux): Stop handling hide_hosted_docs_ here. crbug.com/256520.
+  scoped_ptr<ResourceEntryVector> filtered(new ResourceEntryVector);
+  for (size_t i = 0; i < entries->size(); ++i) {
+    if (hide_hosted_docs_ &&
+        entries->at(i).file_specific_info().is_hosted_document()) {
+      continue;
+    }
+    filtered->push_back(entries->at(i));
+  }
+  callback.Run(FILE_ERROR_OK, filtered.Pass());
 }
 
 void FileSystem::RefreshDirectory(
diff --git a/chrome/browser/chromeos/drive/file_system.h b/chrome/browser/chromeos/drive/file_system.h
index d3f7c8d..6ed4e52 100644
--- a/chrome/browser/chromeos/drive/file_system.h
+++ b/chrome/browser/chromeos/drive/file_system.h
@@ -26,12 +26,12 @@
 
 namespace google_apis {
 class AboutResource;
-class DriveServiceInterface;
 class ResourceEntry;
 }
 
 namespace drive {
 
+class DriveServiceInterface;
 class FileCacheEntry;
 class FileSystemObserver;
 class JobScheduler;
@@ -52,6 +52,7 @@
 class RemoveOperation;
 class SearchOperation;
 class TouchOperation;
+class TruncateOperation;
 class UpdateOperation;
 }  // namespace file_system
 
@@ -62,7 +63,7 @@
  public:
   FileSystem(Profile* profile,
              internal::FileCache* cache,
-             google_apis::DriveServiceInterface* drive_service,
+             DriveServiceInterface* drive_service,
              JobScheduler* scheduler,
              internal::ResourceMetadata* resource_metadata,
              base::SequencedTaskRunner* blocking_task_runner,
@@ -116,6 +117,9 @@
                          const base::Time& last_access_time,
                          const base::Time& last_modified_time,
                          const FileOperationCallback& callback) OVERRIDE;
+  virtual void TruncateFile(const base::FilePath& file_path,
+                            int64 length,
+                            const FileOperationCallback& callback) OVERRIDE;
   virtual void Pin(const base::FilePath& file_path,
                    const FileOperationCallback& callback) OVERRIDE;
   virtual void Unpin(const base::FilePath& file_path,
@@ -141,7 +145,7 @@
       const GetResourceEntryCallback& callback) OVERRIDE;
   virtual void ReadDirectoryByPath(
       const base::FilePath& directory_path,
-      const ReadDirectoryWithSettingCallback& callback) OVERRIDE;
+      const ReadDirectoryCallback& callback) OVERRIDE;
   virtual void RefreshDirectory(
       const base::FilePath& directory_path,
       const FileOperationCallback& callback) OVERRIDE;
@@ -301,10 +305,10 @@
   // |callback| must not be null.
   void ReadDirectoryByPathAfterLoad(
       const base::FilePath& directory_path,
-      const ReadDirectoryWithSettingCallback& callback,
+      const ReadDirectoryCallback& callback,
       FileError error);
   void ReadDirectoryByPathAfterRead(
-      const ReadDirectoryWithSettingCallback& callback,
+      const ReadDirectoryCallback& callback,
       FileError error,
       scoped_ptr<ResourceEntryVector> entries);
 
@@ -358,7 +362,7 @@
 
   // Sub components owned by DriveIntegrationService.
   internal::FileCache* cache_;
-  google_apis::DriveServiceInterface* drive_service_;
+  DriveServiceInterface* drive_service_;
   JobScheduler* scheduler_;
   internal::ResourceMetadata* resource_metadata_;
 
@@ -394,13 +398,11 @@
   scoped_ptr<file_system::MoveOperation> move_operation_;
   scoped_ptr<file_system::RemoveOperation> remove_operation_;
   scoped_ptr<file_system::TouchOperation> touch_operation_;
+  scoped_ptr<file_system::TruncateOperation> truncate_operation_;
   scoped_ptr<file_system::DownloadOperation> download_operation_;
   scoped_ptr<file_system::UpdateOperation> update_operation_;
   scoped_ptr<file_system::SearchOperation> search_operation_;
 
-  // Polling interval for checking updates in seconds.
-  int polling_interval_sec_;
-
   // Note: This should remain the last member so it'll be destroyed and
   // invalidate the weak pointers before any other members are destroyed.
   base::WeakPtrFactory<FileSystem> weak_ptr_factory_;
diff --git a/chrome/browser/chromeos/drive/file_system/copy_operation.cc b/chrome/browser/chromeos/drive/file_system/copy_operation.cc
index 3c16ab1..72d6e07 100644
--- a/chrome/browser/chromeos/drive/file_system/copy_operation.cc
+++ b/chrome/browser/chromeos/drive/file_system/copy_operation.cc
@@ -17,7 +17,7 @@
 #include "chrome/browser/chromeos/drive/file_system_util.h"
 #include "chrome/browser/chromeos/drive/job_scheduler.h"
 #include "chrome/browser/chromeos/drive/resource_entry_conversion.h"
-#include "chrome/browser/google_apis/drive_api_util.h"
+#include "chrome/browser/drive/drive_api_util.h"
 #include "content/public/browser/browser_thread.h"
 
 using content::BrowserThread;
@@ -56,7 +56,7 @@
                              JobScheduler* scheduler,
                              internal::ResourceMetadata* metadata,
                              internal::FileCache* cache,
-                             google_apis::DriveServiceInterface* drive_service,
+                             DriveServiceInterface* drive_service,
                              const base::FilePath& temporary_file_directory)
   : blocking_task_runner_(blocking_task_runner),
     observer_(observer),
@@ -327,7 +327,7 @@
   }
 
   // If Drive API v2 is enabled, we can copy resources on server side.
-  if (google_apis::util::IsDriveV2ApiEnabled()) {
+  if (util::IsDriveV2ApiEnabled()) {
     base::FilePath new_name = dest_file_path.BaseName();
     if (src_file_proto->file_specific_info().is_hosted_document()) {
       // Drop the document extension, which should not be in the title.
diff --git a/chrome/browser/chromeos/drive/file_system/copy_operation.h b/chrome/browser/chromeos/drive/file_system/copy_operation.h
index b8db1c3..9ba481d 100644
--- a/chrome/browser/chromeos/drive/file_system/copy_operation.h
+++ b/chrome/browser/chromeos/drive/file_system/copy_operation.h
@@ -18,12 +18,12 @@
 }  // namespace base
 
 namespace google_apis {
-class DriveServiceInterface;
 class ResourceEntry;
 }  // namespace google_apis
 
 namespace drive {
 
+class DriveServiceInterface;
 class JobScheduler;
 class ResourceEntry;
 
@@ -48,7 +48,7 @@
                 JobScheduler* scheduler,
                 internal::ResourceMetadata* metadata,
                 internal::FileCache* cache,
-                google_apis::DriveServiceInterface* drive_service,
+                DriveServiceInterface* drive_service,
                 const base::FilePath& temporary_file_directory);
   ~CopyOperation();
 
@@ -179,7 +179,7 @@
   JobScheduler* scheduler_;
   internal::ResourceMetadata* metadata_;
   internal::FileCache* cache_;
-  google_apis::DriveServiceInterface* drive_service_;
+  DriveServiceInterface* drive_service_;
 
   // Uploading a new file is internally implemented by creating a dirty file.
   scoped_ptr<CreateFileOperation> create_file_operation_;
diff --git a/chrome/browser/chromeos/drive/file_system/create_directory_operation.cc b/chrome/browser/chromeos/drive/file_system/create_directory_operation.cc
index 7cd5a0d..89a7d60 100644
--- a/chrome/browser/chromeos/drive/file_system/create_directory_operation.cc
+++ b/chrome/browser/chromeos/drive/file_system/create_directory_operation.cc
@@ -239,7 +239,7 @@
     return;
   }
 
-  // Create descendent directories.
+  // Create descendant directories.
   CreateDirectoryRecursively(resource_id, remaining_path, callback);
 }
 
diff --git a/chrome/browser/chromeos/drive/file_system/download_operation.cc b/chrome/browser/chromeos/drive/file_system/download_operation.cc
index e787ec0..754bb46 100644
--- a/chrome/browser/chromeos/drive/file_system/download_operation.cc
+++ b/chrome/browser/chromeos/drive/file_system/download_operation.cc
@@ -14,7 +14,6 @@
 #include "chrome/browser/chromeos/drive/file_system/operation_observer.h"
 #include "chrome/browser/chromeos/drive/file_system_util.h"
 #include "chrome/browser/chromeos/drive/job_scheduler.h"
-#include "chrome/browser/chromeos/drive/resource_entry_conversion.h"
 #include "chrome/browser/chromeos/drive/resource_metadata.h"
 #include "chrome/browser/google_apis/gdata_errorcode.h"
 #include "content/public/browser/browser_thread.h"
@@ -97,15 +96,17 @@
 }
 
 // Calls CheckPreConditionForEnsureFileDownloaded() with the entry specified by
-// the given ID.
+// the given ID. Also fills |drive_file_path| with the path of the entry.
 FileError CheckPreConditionForEnsureFileDownloadedByResourceId(
     internal::ResourceMetadata* metadata,
     internal::FileCache* cache,
     const std::string& resource_id,
     const base::FilePath& temporary_file_directory,
+    base::FilePath* drive_file_path,
     base::FilePath* cache_file_path,
     ResourceEntry* entry) {
   FileError error = metadata->GetResourceEntryById(resource_id, entry);
+  *drive_file_path = metadata->GetFilePath(resource_id);
   if (error != FILE_ERROR_OK)
     return error;
   return CheckPreConditionForEnsureFileDownloaded(
@@ -145,44 +146,22 @@
       file_util::FILE_PERMISSION_READ_BY_OTHERS);
 }
 
-// Prepares for downloading the file. Given the |gdata_entry|, refreshes the
-// |metadata| and then allocates the enough space in the cache.
-// If succeeded, returns FILE_ERROR_OK with |entry| storing the ResourceEntry
-// of the resource, |drive_file_path| with storing the path of the entry,
-// and |temp_download_file| storing the path to the file in the cache.
-FileError PrepareForDownloadFile(
-    internal::ResourceMetadata* metadata,
-    internal::FileCache* cache,
-    scoped_ptr<google_apis::ResourceEntry> gdata_entry,
-    const base::FilePath& temporary_file_directory,
-    ResourceEntry* entry,
-    base::FilePath* drive_file_path,
-    base::FilePath* temp_download_file) {
-  DCHECK(metadata);
+// Prepares for downloading the file. Given the |resource_id|, allocates the
+// enough space for the file in the cache.
+// If succeeded, returns FILE_ERROR_OK with |temp_download_file| storing the
+// path to the file in the cache.
+FileError PrepareForDownloadFile(internal::FileCache* cache,
+                                 int64 expected_file_size,
+                                 const base::FilePath& temporary_file_directory,
+                                 base::FilePath* temp_download_file) {
   DCHECK(cache);
-  DCHECK(gdata_entry);
-  DCHECK(entry);
-  DCHECK(drive_file_path);
   DCHECK(temp_download_file);
 
-  *entry = ConvertToResourceEntry(*gdata_entry);
-  FileError error = metadata->RefreshEntry(*entry);
-  if (error != FILE_ERROR_OK)
-    return error;
-
-  error = metadata->GetResourceEntryById(entry->resource_id(), entry);
-  if (error != FILE_ERROR_OK)
-    return error;
-
-  *drive_file_path = metadata->GetFilePath(entry->resource_id());
-  if (drive_file_path->empty())
-    return FILE_ERROR_NOT_FOUND;
-
   // Ensure enough space in the cache.
-  if (!cache->FreeDiskSpaceIfNeededFor(entry->file_info().size()))
+  if (!cache->FreeDiskSpaceIfNeededFor(expected_file_size))
     return FILE_ERROR_NO_SPACE;
 
-  // Create the temporary file which will store the donwloaded content.
+  // Create the temporary file which will store the downloaded content.
   return CreateTemporaryReadableFileInDir(
       temporary_file_directory,
       temp_download_file) ? FILE_ERROR_OK : FILE_ERROR_FAILED;
@@ -203,7 +182,7 @@
 
   FileError error = util::GDataToFileError(gdata_error);
   if (error != FILE_ERROR_OK) {
-    file_util::Delete(downloaded_file_path, false /* recursive */);
+    base::Delete(downloaded_file_path, false /* recursive */);
     return error;
   }
 
@@ -211,7 +190,7 @@
   error = cache->Store(resource_id, md5, downloaded_file_path,
                        internal::FileCache::FILE_OPERATION_MOVE);
   if (error != FILE_ERROR_OK) {
-    file_util::Delete(downloaded_file_path, false /* recursive */);
+    base::Delete(downloaded_file_path, false /* recursive */);
     return error;
   }
 
@@ -275,21 +254,6 @@
   // This class is copiable.
 };
 
-struct DownloadOperation::DownloadParams {
-  DownloadParams(const ClientContext& context,
-                 const GURL& download_url)
-      : context(context),
-        download_url(download_url),
-        entry(new ResourceEntry) {
-  }
-
-  ClientContext context;
-  GURL download_url;
-  scoped_ptr<ResourceEntry> entry;
-  base::FilePath drive_file_path;
-  base::FilePath temp_download_file_path;
-};
-
 DownloadOperation::DownloadOperation(
     base::SequencedTaskRunner* blocking_task_runner,
     OperationObserver* observer,
@@ -321,8 +285,9 @@
   DownloadCallback callback(
       initialized_callback, get_content_callback, completion_callback);
 
-  ResourceEntry* entry = new ResourceEntry;
+  base::FilePath* drive_file_path = new base::FilePath;
   base::FilePath* cache_file_path = new base::FilePath;
+  ResourceEntry* entry = new ResourceEntry;
   base::PostTaskAndReplyWithResult(
       blocking_task_runner_.get(),
       FROM_HERE,
@@ -331,13 +296,15 @@
                  base::Unretained(cache_),
                  resource_id,
                  temporary_file_directory_,
+                 drive_file_path,
                  cache_file_path,
                  entry),
       base::Bind(&DownloadOperation::EnsureFileDownloadedAfterCheckPreCondition,
                  weak_ptr_factory_.GetWeakPtr(),
-                 context,
                  callback,
+                 context,
                  base::Passed(make_scoped_ptr(entry)),
+                 base::Owned(drive_file_path),
                  base::Owned(cache_file_path)));
 }
 
@@ -353,8 +320,9 @@
   DownloadCallback callback(
       initialized_callback, get_content_callback, completion_callback);
 
-  ResourceEntry* entry = new ResourceEntry;
+  base::FilePath* drive_file_path = new base::FilePath(file_path);
   base::FilePath* cache_file_path = new base::FilePath;
+  ResourceEntry* entry = new ResourceEntry;
   base::PostTaskAndReplyWithResult(
       blocking_task_runner_.get(),
       FROM_HERE,
@@ -367,20 +335,23 @@
                  entry),
       base::Bind(&DownloadOperation::EnsureFileDownloadedAfterCheckPreCondition,
                  weak_ptr_factory_.GetWeakPtr(),
-                 context,
                  callback,
+                 context,
                  base::Passed(make_scoped_ptr(entry)),
+                 base::Owned(drive_file_path),
                  base::Owned(cache_file_path)));
 }
 
 void DownloadOperation::EnsureFileDownloadedAfterCheckPreCondition(
-    const ClientContext& context,
     const DownloadCallback& callback,
+    const ClientContext& context,
     scoped_ptr<ResourceEntry> entry,
+    base::FilePath* drive_file_path,
     base::FilePath* cache_file_path,
     FileError error) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(entry);
+  DCHECK(drive_file_path);
   DCHECK(cache_file_path);
 
   if (error != FILE_ERROR_OK) {
@@ -397,94 +368,56 @@
   }
 
   // If cache file is not found, try to download the file from the server
-  // instead. This logic is rather complicated but here's how this works:
-  //
-  // Retrieve fresh file metadata from server. We will extract file size and
-  // download url from there. Note that the download url is transient.
-  //
-  // Check if we have enough space, based on the expected file size.
+  // instead. Check if we have enough space, based on the expected file size.
   // - if we don't have enough space, try to free up the disk space
   // - if we still don't have enough space, return "no space" error
   // - if we have enough space, start downloading the file from the server
-  scheduler_->GetResourceEntry(
-      entry->resource_id(),
-      context,
-      base::Bind(&DownloadOperation::EnsureFileDownloadedAfterGetResourceEntry,
-                 weak_ptr_factory_.GetWeakPtr(),
-                 context,
-                 callback));
-}
-
-void DownloadOperation::EnsureFileDownloadedAfterGetResourceEntry(
-    const ClientContext& context,
-    const DownloadCallback& callback,
-    google_apis::GDataErrorCode gdata_error,
-    scoped_ptr<google_apis::ResourceEntry> resource_entry) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  FileError error = util::GDataToFileError(gdata_error);
-  if (error != FILE_ERROR_OK) {
-    callback.OnError(error);
-    return;
-  }
-  DCHECK(resource_entry);
-
-  // The download URL is:
-  // 1) src attribute of content element, on GData WAPI.
-  // 2) the value of the key 'downloadUrl', on Drive API v2.
-  // In both cases, we can use ResourceEntry::download_url().
-  const GURL& download_url = resource_entry->download_url();
-
-  // The download URL can be empty for non-downloadable files (such as files
-  // shared from others with "prevent downloading by viewers" flag set.)
-  if (download_url.is_empty()) {
-    callback.OnError(FILE_ERROR_ACCESS_DENIED);
-    return;
-  }
-
-  // Before starting to download actually, refresh the metadata and allocate
-  // the cache space.
-  DownloadParams* params = new DownloadParams(context, download_url);
+  int64 size = entry->file_info().size();
+  base::FilePath* temp_download_file_path = new base::FilePath;
   base::PostTaskAndReplyWithResult(
       blocking_task_runner_.get(),
       FROM_HERE,
       base::Bind(&PrepareForDownloadFile,
-                 base::Unretained(metadata_),
                  base::Unretained(cache_),
-                 base::Passed(&resource_entry),
+                 size,
                  temporary_file_directory_,
-                 params->entry.get(),
-                 &params->drive_file_path,
-                 &params->temp_download_file_path),
+                 temp_download_file_path),
       base::Bind(
           &DownloadOperation::EnsureFileDownloadedAfterPrepareForDownloadFile,
           weak_ptr_factory_.GetWeakPtr(),
-          base::Owned(params),
-          callback));
+          callback,
+          context,
+          base::Passed(&entry),
+          *drive_file_path,
+          base::Owned(temp_download_file_path)));
 }
 
 void DownloadOperation::EnsureFileDownloadedAfterPrepareForDownloadFile(
-    DownloadParams* params,
     const DownloadCallback& callback,
+    const ClientContext& context,
+    scoped_ptr<ResourceEntry> entry,
+    const base::FilePath& drive_file_path,
+    base::FilePath* temp_download_file_path,
     FileError error) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  DCHECK(params);
+  DCHECK(entry);
+  DCHECK(temp_download_file_path);
 
   if (error != FILE_ERROR_OK) {
     callback.OnError(error);
     return;
   }
 
-  ResourceEntry* entry_ptr = params->entry.get();
+  ResourceEntry* entry_ptr = entry.get();
   JobID id = scheduler_->DownloadFile(
-      params->drive_file_path,
-      params->temp_download_file_path,
-      params->download_url,
-      params->context,
+      drive_file_path,
+      *temp_download_file_path,
+      entry_ptr->resource_id(),
+      context,
       base::Bind(&DownloadOperation::EnsureFileDownloadedAfterDownloadFile,
                  weak_ptr_factory_.GetWeakPtr(),
-                 params->drive_file_path,
-                 base::Passed(&params->entry),
+                 drive_file_path,
+                 base::Passed(&entry),
                  callback),
       callback.get_content_callback());
 
diff --git a/chrome/browser/chromeos/drive/file_system/download_operation.h b/chrome/browser/chromeos/drive/file_system/download_operation.h
index d102221..c95b809 100644
--- a/chrome/browser/chromeos/drive/file_system/download_operation.h
+++ b/chrome/browser/chromeos/drive/file_system/download_operation.h
@@ -81,31 +81,24 @@
   // Thin wrapper of Callbacks for EnsureFileDownloaded.
   class DownloadCallback;
 
-  // Parameters for JobScheduler::DownloadFile.
-  struct DownloadParams;
-
   // Part of EnsureFileDownloaded(). Called upon the completion of precondition
   // check.
   void EnsureFileDownloadedAfterCheckPreCondition(
-      const ClientContext& context,
       const DownloadCallback& callback,
+      const ClientContext& context,
       scoped_ptr<ResourceEntry> entry,
+      base::FilePath* drive_file_path,
       base::FilePath* cache_file_path,
       FileError error);
 
-  // Part of EnsureFileDownloaded(). Called upon the completion of fetching
-  // ResourceEntry from the server.
-  void EnsureFileDownloadedAfterGetResourceEntry(
-      const ClientContext& context,
-      const DownloadCallback& callback,
-      google_apis::GDataErrorCode gdata_error,
-      scoped_ptr<google_apis::ResourceEntry> resource_entry);
-
   // Part of EnsureFileDownloaded(). Called when it is ready to start
   // downloading the file.
   void EnsureFileDownloadedAfterPrepareForDownloadFile(
-      DownloadParams* params,
       const DownloadCallback& callback,
+      const ClientContext& context,
+      scoped_ptr<ResourceEntry> entry,
+      const base::FilePath& drive_file_path,
+      base::FilePath* temp_download_file_path,
       FileError error);
 
   // Part of EnsureFileDownloaded(). Called after the actual downloading.
diff --git a/chrome/browser/chromeos/drive/file_system/move_operation_unittest.cc b/chrome/browser/chromeos/drive/file_system/move_operation_unittest.cc
index a9b3cb6..22b6b62 100644
--- a/chrome/browser/chromeos/drive/file_system/move_operation_unittest.cc
+++ b/chrome/browser/chromeos/drive/file_system/move_operation_unittest.cc
@@ -18,11 +18,6 @@
    operation_.reset(new MoveOperation(observer(), scheduler(), metadata()));
  }
 
- virtual void TearDown() OVERRIDE {
-   operation_.reset();
-   OperationTestBase::TearDown();
- }
-
  scoped_ptr<MoveOperation> operation_;
 };
 
diff --git a/chrome/browser/chromeos/drive/file_system/operation_test_base.cc b/chrome/browser/chromeos/drive/file_system/operation_test_base.cc
index 43f2aae..91879c2 100644
--- a/chrome/browser/chromeos/drive/file_system/operation_test_base.cc
+++ b/chrome/browser/chromeos/drive/file_system/operation_test_base.cc
@@ -51,16 +51,28 @@
   profile_.reset(new TestingProfile);
   ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
 
-  fake_drive_service_.reset(new google_apis::FakeDriveService);
+  fake_drive_service_.reset(new FakeDriveService);
   fake_drive_service_->LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json");
+      "gdata/root_feed.json");
   fake_drive_service_->LoadAccountMetadataForWapi(
-      "chromeos/gdata/account_metadata.json");
+      "gdata/account_metadata.json");
 
-  scheduler_.reset(
-      new JobScheduler(profile_.get(), fake_drive_service_.get()));
+  scheduler_.reset(new JobScheduler(profile_.get(), fake_drive_service_.get(),
+                                    blocking_task_runner_));
 
-  metadata_.reset(new internal::ResourceMetadata(temp_dir_.path(),
+  metadata_storage_.reset(new internal::ResourceMetadataStorage(
+      temp_dir_.path(), blocking_task_runner_));
+  bool success = false;
+  base::PostTaskAndReplyWithResult(
+      blocking_task_runner_,
+      FROM_HERE,
+      base::Bind(&internal::ResourceMetadataStorage::Initialize,
+                 base::Unretained(metadata_storage_.get())),
+      google_apis::test_util::CreateCopyResultCallback(&success));
+  google_apis::test_util::RunBlockingPoolTask();
+  ASSERT_TRUE(success);
+
+  metadata_.reset(new internal::ResourceMetadata(metadata_storage_.get(),
                                                  blocking_task_runner_));
 
   FileError error = FILE_ERROR_FAILED;
@@ -74,11 +86,11 @@
   ASSERT_EQ(FILE_ERROR_OK, error);
 
   fake_free_disk_space_getter_.reset(new FakeFreeDiskSpaceGetter);
-  cache_.reset(new internal::FileCache(temp_dir_.path(),
+  cache_.reset(new internal::FileCache(metadata_storage_.get(),
                                        temp_dir_.path(),
                                        blocking_task_runner_.get(),
                                        fake_free_disk_space_getter_.get()));
-  bool success = false;
+  success = false;
   base::PostTaskAndReplyWithResult(
       blocking_task_runner_,
       FROM_HERE,
@@ -99,17 +111,6 @@
   ASSERT_EQ(FILE_ERROR_OK, error);
 }
 
-void OperationTestBase::TearDown() {
-  cache_.reset();
-  fake_free_disk_space_getter_.reset();
-  metadata_.reset();
-  scheduler_.reset();
-  fake_drive_service_.reset();
-  profile_.reset();
-
-  blocking_task_runner_ = NULL;
-}
-
 FileError OperationTestBase::GetLocalResourceEntry(const base::FilePath& path,
                                                    ResourceEntry* entry) {
   FileError error = FILE_ERROR_FAILED;
diff --git a/chrome/browser/chromeos/drive/file_system/operation_test_base.h b/chrome/browser/chromeos/drive/file_system/operation_test_base.h
index 026fae1..fd44a80 100644
--- a/chrome/browser/chromeos/drive/file_system/operation_test_base.h
+++ b/chrome/browser/chromeos/drive/file_system/operation_test_base.h
@@ -20,18 +20,16 @@
 class SequencedTaskRunner;
 }  // namespace base
 
-namespace google_apis {
-class FakeDriveService;
-}  // namespace google_apis
-
 namespace drive {
 
+class FakeDriveService;
 class FakeFreeDiskSpaceGetter;
 class JobScheduler;
 
 namespace internal {
 class FileCache;
 class ResourceMetadata;
+class ResourceMetadataStorage;
 }  // namespace internal
 
 namespace file_system {
@@ -73,7 +71,6 @@
 
   // testing::Test overrides.
   virtual void SetUp() OVERRIDE;
-  virtual void TearDown() OVERRIDE;
 
   // Returns the path of the temporary directory for putting test files.
   base::FilePath temp_dir() const { return temp_dir_.path(); }
@@ -84,7 +81,7 @@
                                   ResourceEntry* entry);
 
   // Accessors for the components.
-  google_apis::FakeDriveService* fake_service() {
+  FakeDriveService* fake_service() {
     return fake_drive_service_.get();
   }
   LoggingObserver* observer() { return &observer_; }
@@ -105,8 +102,10 @@
   base::ScopedTempDir temp_dir_;
 
   LoggingObserver observer_;
-  scoped_ptr<google_apis::FakeDriveService> fake_drive_service_;
+  scoped_ptr<FakeDriveService> fake_drive_service_;
   scoped_ptr<JobScheduler> scheduler_;
+  scoped_ptr<internal::ResourceMetadataStorage,
+             test_util::DestroyHelperForTests> metadata_storage_;
   scoped_ptr<internal::ResourceMetadata, test_util::DestroyHelperForTests>
       metadata_;
   scoped_ptr<FakeFreeDiskSpaceGetter> fake_free_disk_space_getter_;
diff --git a/chrome/browser/chromeos/drive/file_system/touch_operation.cc b/chrome/browser/chromeos/drive/file_system/touch_operation.cc
index 3226f16..2b3dff0 100644
--- a/chrome/browser/chromeos/drive/file_system/touch_operation.cc
+++ b/chrome/browser/chromeos/drive/file_system/touch_operation.cc
@@ -7,7 +7,7 @@
 #include "base/bind.h"
 #include "base/files/file_path.h"
 #include "base/sequenced_task_runner.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/chromeos/drive/file_errors.h"
 #include "chrome/browser/chromeos/drive/file_system/operation_observer.h"
 #include "chrome/browser/chromeos/drive/file_system_util.h"
diff --git a/chrome/browser/chromeos/drive/file_system/touch_operation_unittest.cc b/chrome/browser/chromeos/drive/file_system/touch_operation_unittest.cc
index 488bbb4..ff4380a 100644
--- a/chrome/browser/chromeos/drive/file_system/touch_operation_unittest.cc
+++ b/chrome/browser/chromeos/drive/file_system/touch_operation_unittest.cc
@@ -5,7 +5,7 @@
 #include "chrome/browser/chromeos/drive/file_system/touch_operation.h"
 
 #include "base/files/file_path.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/chromeos/drive/drive.pb.h"
 #include "chrome/browser/chromeos/drive/file_errors.h"
 #include "chrome/browser/chromeos/drive/file_system/operation_test_base.h"
diff --git a/chrome/browser/chromeos/drive/file_system/truncate_operation.cc b/chrome/browser/chromeos/drive/file_system/truncate_operation.cc
new file mode 100644
index 0000000..018d9a5
--- /dev/null
+++ b/chrome/browser/chromeos/drive/file_system/truncate_operation.cc
@@ -0,0 +1,169 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/drive/file_system/truncate_operation.h"
+
+#include "base/bind.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/platform_file.h"
+#include "base/sequenced_task_runner.h"
+#include "base/task_runner_util.h"
+#include "chrome/browser/chromeos/drive/drive.pb.h"
+#include "chrome/browser/chromeos/drive/file_cache.h"
+#include "chrome/browser/chromeos/drive/file_errors.h"
+#include "chrome/browser/chromeos/drive/file_system/download_operation.h"
+#include "chrome/browser/chromeos/drive/file_system/operation_observer.h"
+#include "content/public/browser/browser_thread.h"
+
+using content::BrowserThread;
+
+namespace drive {
+namespace file_system {
+namespace {
+
+// Automatically closes |platform_file| given via the constructor when
+// the instance is destroyed.
+class ScopedPlatformFileCloser {
+ public:
+  // |platform_file| must not be NULL.
+  explicit ScopedPlatformFileCloser(base::PlatformFile* platform_file)
+      : platform_file_(platform_file) {
+    DCHECK(platform_file_);
+  }
+
+  ~ScopedPlatformFileCloser() {
+    base::ClosePlatformFile(*platform_file_);
+  }
+
+ private:
+  base::PlatformFile* platform_file_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedPlatformFileCloser);
+};
+
+// Truncates the local file at |local_cache_path| to the |length| bytes,
+// then marks the resource is dirty on |cache|.
+FileError TruncateOnBlockingPool(internal::FileCache* cache,
+                                 const std::string& resource_id,
+                                 const std::string& md5,
+                                 const base::FilePath& local_cache_path,
+                                 int64 length) {
+  DCHECK(cache);
+
+  base::PlatformFileError result = base::PLATFORM_FILE_ERROR_FAILED;
+  base::PlatformFile file = base::CreatePlatformFile(
+      local_cache_path,
+      base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE,
+      NULL,
+      &result);
+  if (result != base::PLATFORM_FILE_OK)
+    return FILE_ERROR_FAILED;
+
+  DCHECK_NE(base::kInvalidPlatformFileValue, file);
+  ScopedPlatformFileCloser file_closer(&file);
+
+  if (!base::TruncatePlatformFile(file, length))
+    return FILE_ERROR_FAILED;
+
+  return cache->MarkDirty(resource_id, md5);
+}
+
+}  // namespace
+
+TruncateOperation::TruncateOperation(
+    base::SequencedTaskRunner* blocking_task_runner,
+    OperationObserver* observer,
+    JobScheduler* scheduler,
+    internal::ResourceMetadata* metadata,
+    internal::FileCache* cache,
+    const base::FilePath& temporary_file_directory)
+    : blocking_task_runner_(blocking_task_runner),
+      observer_(observer),
+      cache_(cache),
+      download_operation_(new DownloadOperation(blocking_task_runner,
+                                                observer,
+                                                scheduler,
+                                                metadata,
+                                                cache,
+                                                temporary_file_directory)),
+      weak_ptr_factory_(this) {
+}
+
+TruncateOperation::~TruncateOperation() {
+}
+
+void TruncateOperation::Truncate(const base::FilePath& file_path,
+                                 int64 length,
+                                 const FileOperationCallback& callback) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  if (length < 0) {
+    base::MessageLoopProxy::current()->PostTask(
+        FROM_HERE,
+        base::Bind(callback, FILE_ERROR_INVALID_OPERATION));
+    return;
+  }
+
+  // TODO(kinaba): http://crbug.com/132780.
+  // Optimize the cases for small |length|, at least for |length| == 0.
+  download_operation_->EnsureFileDownloadedByPath(
+      file_path,
+      ClientContext(USER_INITIATED),
+      GetFileContentInitializedCallback(),
+      google_apis::GetContentCallback(),
+      base::Bind(&TruncateOperation::TruncateAfterEnsureFileDownloadedByPath,
+                 weak_ptr_factory_.GetWeakPtr(), file_path, length, callback));
+}
+
+void TruncateOperation::TruncateAfterEnsureFileDownloadedByPath(
+    const base::FilePath& file_path,
+    int64 length,
+    const FileOperationCallback& callback,
+    FileError error,
+    const base::FilePath& local_file_path,
+    scoped_ptr<ResourceEntry> entry) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(!callback.is_null());
+
+  if (error != FILE_ERROR_OK) {
+    callback.Run(error);
+    return;
+  }
+  DCHECK(entry);
+  DCHECK(entry->has_file_specific_info());
+
+  if (entry->file_specific_info().is_hosted_document()) {
+    callback.Run(FILE_ERROR_INVALID_OPERATION);
+    return;
+  }
+
+  base::PostTaskAndReplyWithResult(
+      blocking_task_runner_.get(),
+      FROM_HERE,
+      base::Bind(&TruncateOnBlockingPool,
+                 base::Unretained(cache_),
+                 entry->resource_id(), entry->file_specific_info().md5(),
+                 local_file_path, length),
+      base::Bind(
+          &TruncateOperation::TruncateAfterTruncateOnBlockingPool,
+          weak_ptr_factory_.GetWeakPtr(), entry->resource_id(), callback));
+}
+
+void TruncateOperation::TruncateAfterTruncateOnBlockingPool(
+    const std::string& resource_id,
+    const FileOperationCallback& callback,
+    FileError error) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(!callback.is_null());
+
+  if (error == FILE_ERROR_OK)
+    observer_->OnCacheFileUploadNeededByOperation(resource_id);
+
+  callback.Run(error);
+}
+
+}  // namespace file_system
+}  // namespace drive
diff --git a/chrome/browser/chromeos/drive/file_system/truncate_operation.h b/chrome/browser/chromeos/drive/file_system/truncate_operation.h
new file mode 100644
index 0000000..39eba6b
--- /dev/null
+++ b/chrome/browser/chromeos/drive/file_system/truncate_operation.h
@@ -0,0 +1,85 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_DRIVE_FILE_SYSTEM_TRUNCATE_OPERATION_H_
+#define CHROME_BROWSER_CHROMEOS_DRIVE_FILE_SYSTEM_TRUNCATE_OPERATION_H_
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/chromeos/drive/file_errors.h"
+
+namespace base {
+class FilePath;
+class SequencedTaskRunner;
+}  // namespace base
+
+namespace drive {
+
+class JobScheduler;
+class ResourceEntry;
+
+namespace internal {
+class FileCache;
+class ResourceMetadata;
+}  // namespace internal
+
+namespace file_system {
+
+class OperationObserver;
+class DownloadOperation;
+
+// This class encapsulates the drive Truncate function. It is responsible for
+// fetching the content from the Drive server if necessary, truncating the
+// file content actually, and then notifying the file is locally modified and
+// that it is necessary to upload the file to the server.
+class TruncateOperation {
+ public:
+  TruncateOperation(base::SequencedTaskRunner* blocking_task_runner,
+                    OperationObserver* observer,
+                    JobScheduler* scheduler,
+                    internal::ResourceMetadata* metadata,
+                    internal::FileCache* cache,
+                    const base::FilePath& temporary_file_directory);
+  ~TruncateOperation();
+
+  // Performs the truncate operation on the file at drive path |file_path| to
+  // |length| bytes. Invokes |callback| when finished with the result of the
+  // operation. |callback| must not be null.
+  void Truncate(const base::FilePath& file_path,
+                int64 length,
+                const FileOperationCallback& callback);
+ private:
+  // Part of Truncate(). Called after EnsureFileDownloadedByPath() is complete.
+  void TruncateAfterEnsureFileDownloadedByPath(
+      const base::FilePath& file_path,
+      int64 length,
+      const FileOperationCallback& callback,
+      FileError error,
+      const base::FilePath& local_file_path,
+      scoped_ptr<ResourceEntry> resource_entry);
+
+  // Part of Truncate(). Called after TruncateOnBlockingPool() is complete.
+  void TruncateAfterTruncateOnBlockingPool(
+      const std::string& resource_id,
+      const FileOperationCallback& callback,
+      FileError error);
+
+  scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
+  OperationObserver* observer_;
+  internal::FileCache* cache_;
+
+  scoped_ptr<DownloadOperation> download_operation_;
+
+  // Note: This should remain the last member so it'll be destroyed and
+  // invalidate the weak pointers before any other members are destroyed.
+  base::WeakPtrFactory<TruncateOperation> weak_ptr_factory_;
+  DISALLOW_COPY_AND_ASSIGN(TruncateOperation);
+};
+
+}  // namespace file_system
+}  // namespace drive
+
+#endif  // CHROME_BROWSER_CHROMEOS_DRIVE_FILE_SYSTEM_TRUNCATE_OPERATION_H_
diff --git a/chrome/browser/chromeos/drive/file_system/truncate_operation_unittest.cc b/chrome/browser/chromeos/drive/file_system/truncate_operation_unittest.cc
new file mode 100644
index 0000000..47a7205
--- /dev/null
+++ b/chrome/browser/chromeos/drive/file_system/truncate_operation_unittest.cc
@@ -0,0 +1,125 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/drive/file_system/truncate_operation.h"
+
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "chrome/browser/chromeos/drive/drive.pb.h"
+#include "chrome/browser/chromeos/drive/fake_free_disk_space_getter.h"
+#include "chrome/browser/chromeos/drive/file_system/operation_test_base.h"
+#include "chrome/browser/google_apis/test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace drive {
+namespace file_system {
+
+class TruncateOperationTest : public OperationTestBase {
+ protected:
+  virtual void SetUp() {
+    OperationTestBase::SetUp();
+
+    operation_.reset(new TruncateOperation(
+        blocking_task_runner(), observer(), scheduler(),
+        metadata(), cache(), temp_dir()));
+  }
+
+  scoped_ptr<TruncateOperation> operation_;
+};
+
+TEST_F(TruncateOperationTest, Truncate) {
+  base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt"));
+  ResourceEntry src_entry;
+  ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(file_in_root, &src_entry));
+  const int64 file_size = src_entry.file_info().size();
+
+  // Make sure the file has at least 2 bytes.
+  ASSERT_GE(file_size, 2);
+
+  FileError error = FILE_ERROR_FAILED;
+  operation_->Truncate(
+      file_in_root,
+      1,  // Truncate to 1 byte.
+      google_apis::test_util::CreateCopyResultCallback(&error));
+  google_apis::test_util::RunBlockingPoolTask();
+  EXPECT_EQ(FILE_ERROR_OK, error);
+
+  base::FilePath local_path;
+  error = FILE_ERROR_FAILED;
+  cache()->GetFileOnUIThread(
+      src_entry.resource_id(), src_entry.file_specific_info().md5(),
+      google_apis::test_util::CreateCopyResultCallback(&error, &local_path));
+  google_apis::test_util::RunBlockingPoolTask();
+  ASSERT_EQ(FILE_ERROR_OK, error);
+
+  // The local file should be truncated.
+  int64 local_file_size = 0;
+  file_util::GetFileSize(local_path, &local_file_size);
+  EXPECT_EQ(1, local_file_size);
+}
+
+TEST_F(TruncateOperationTest, NegativeSize) {
+  base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt"));
+  ResourceEntry src_entry;
+  ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(file_in_root, &src_entry));
+  const int64 file_size = src_entry.file_info().size();
+
+  // Make sure the file has at least 2 bytes.
+  ASSERT_GE(file_size, 2);
+
+  FileError error = FILE_ERROR_FAILED;
+  operation_->Truncate(
+      file_in_root,
+      -1,  // Truncate to "-1" byte.
+      google_apis::test_util::CreateCopyResultCallback(&error));
+  google_apis::test_util::RunBlockingPoolTask();
+  EXPECT_EQ(FILE_ERROR_INVALID_OPERATION, error);
+}
+
+TEST_F(TruncateOperationTest, HostedDocument) {
+  base::FilePath file_in_root(FILE_PATH_LITERAL(
+      "drive/root/Document 1 excludeDir-test.gdoc"));
+
+  FileError error = FILE_ERROR_FAILED;
+  operation_->Truncate(
+      file_in_root,
+      1,  // Truncate to 1 byte.
+      google_apis::test_util::CreateCopyResultCallback(&error));
+  google_apis::test_util::RunBlockingPoolTask();
+  EXPECT_EQ(FILE_ERROR_INVALID_OPERATION, error);
+}
+
+TEST_F(TruncateOperationTest, Extend) {
+  base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt"));
+  ResourceEntry src_entry;
+  ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(file_in_root, &src_entry));
+  const int64 file_size = src_entry.file_info().size();
+
+  FileError error = FILE_ERROR_FAILED;
+  operation_->Truncate(
+      file_in_root,
+      file_size + 10,  // Extend to 10 bytes.
+      google_apis::test_util::CreateCopyResultCallback(&error));
+  google_apis::test_util::RunBlockingPoolTask();
+  EXPECT_EQ(FILE_ERROR_OK, error);
+
+  base::FilePath local_path;
+  error = FILE_ERROR_FAILED;
+  cache()->GetFileOnUIThread(
+      src_entry.resource_id(), src_entry.file_specific_info().md5(),
+      google_apis::test_util::CreateCopyResultCallback(&error, &local_path));
+  google_apis::test_util::RunBlockingPoolTask();
+  ASSERT_EQ(FILE_ERROR_OK, error);
+
+  // The local file should be truncated.
+  std::string content;
+  ASSERT_TRUE(file_util::ReadFileToString(local_path, &content));
+
+  EXPECT_EQ(file_size + 10, static_cast<int64>(content.size()));
+  // All trailing 10 bytes should be '\0'.
+  EXPECT_EQ(std::string(10, '\0'), content.substr(file_size));
+}
+
+}  // namespace file_system
+}  // namespace drive
diff --git a/chrome/browser/chromeos/drive/file_system/update_operation_unittest.cc b/chrome/browser/chromeos/drive/file_system/update_operation_unittest.cc
index e7517ec..58ba355 100644
--- a/chrome/browser/chromeos/drive/file_system/update_operation_unittest.cc
+++ b/chrome/browser/chromeos/drive/file_system/update_operation_unittest.cc
@@ -25,11 +25,6 @@
                                         cache()));
  }
 
- virtual void TearDown() OVERRIDE {
-   operation_.reset();
-   OperationTestBase::TearDown();
- }
-
  scoped_ptr<UpdateOperation> operation_;
 };
 
diff --git a/chrome/browser/chromeos/drive/file_system_interface.h b/chrome/browser/chromeos/drive/file_system_interface.h
index 562c4af..b7d61f8 100644
--- a/chrome/browser/chromeos/drive/file_system_interface.h
+++ b/chrome/browser/chromeos/drive/file_system_interface.h
@@ -81,16 +81,6 @@
                             const base::Closure& cancel_download_closure)>
     GetFileContentInitializedCallback;
 
-// Used to read a directory from the file system.
-// Similar to ReadDirectoryCallback but this one provides
-// |hide_hosted_documents|
-// If |error| is not FILE_ERROR_OK, |entries| is set to NULL.
-// |entries| are contents, both files and directories, of the directory.
-typedef base::Callback<void(FileError error,
-                            bool hide_hosted_documents,
-                            scoped_ptr<ResourceEntryVector> entries)>
-    ReadDirectoryWithSettingCallback;
-
 // Used to get drive content search results.
 // If |error| is not FILE_ERROR_OK, |result_paths| is empty.
 typedef base::Callback<void(
@@ -259,8 +249,6 @@
   // needs to be present in in-memory representation of the file system that
   // in order to be removed.
   //
-  // TODO(satorux): is_recursive is not supported yet. crbug.com/138282
-  //
   // |callback| must not be null.
   virtual void Remove(const base::FilePath& file_path,
                       bool is_recursive,
@@ -299,6 +287,13 @@
                          const base::Time& last_modified_time,
                          const FileOperationCallback& callback) = 0;
 
+  // Truncates the file content at |file_path| to the |length|.
+  //
+  // |callback| must not be null.
+  virtual void TruncateFile(const base::FilePath& file_path,
+                            int64 length,
+                            const FileOperationCallback& callback) = 0;
+
   // Pins a file at |file_path|.
   //
   // |callback| must not be null.
@@ -375,7 +370,7 @@
   // |callback| must not be null.
   virtual void ReadDirectoryByPath(
       const base::FilePath& file_path,
-      const ReadDirectoryWithSettingCallback& callback) = 0;
+      const ReadDirectoryCallback& callback) = 0;
 
   // Refreshes the directory pointed by |file_path| (i.e. fetches the latest
   // metadata of files in the target directory).
diff --git a/chrome/browser/chromeos/drive/file_system_metadata.h b/chrome/browser/chromeos/drive/file_system_metadata.h
index 76b5a9e..4ca0c87 100644
--- a/chrome/browser/chromeos/drive/file_system_metadata.h
+++ b/chrome/browser/chromeos/drive/file_system_metadata.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_CHROMEOS_DRIVE_FILE_SYSTEM_METADATA_H_
 
 #include "base/basictypes.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/chromeos/drive/file_errors.h"
 
 namespace drive {
diff --git a/chrome/browser/chromeos/drive/file_system_proxy.cc b/chrome/browser/chromeos/drive/file_system_proxy.cc
index d6bb3c7..37845ab 100644
--- a/chrome/browser/chromeos/drive/file_system_proxy.cc
+++ b/chrome/browser/chromeos/drive/file_system_proxy.cc
@@ -15,6 +15,7 @@
 #include "chrome/browser/chromeos/drive/drive.pb.h"
 #include "chrome/browser/chromeos/drive/file_system_interface.h"
 #include "chrome/browser/chromeos/drive/file_system_util.h"
+#include "chrome/browser/chromeos/drive/fileapi_worker.h"
 #include "chrome/browser/chromeos/drive/webkit_file_stream_reader_impl.h"
 #include "chrome/browser/google_apis/task_util.h"
 #include "chrome/browser/google_apis/time_util.h"
@@ -36,147 +37,51 @@
 
 namespace {
 
-typedef fileapi::RemoteFileSystemProxyInterface::OpenFileCallback
-    OpenFileCallback;
-
-// Helper function to run reply on results of base::CreatePlatformFile() on
-// IO thread.
-void OnPlatformFileOpened(
-    const OpenFileCallback& callback,
+// Runs |callback| with |error|, |file| and |peer_handle|.
+void RunOpenFileCallback(
     base::ProcessHandle peer_handle,
-    base::PlatformFileError* open_error,
-    base::PlatformFile platform_file) {
-  callback.Run(*open_error, platform_file, peer_handle);
+    const fileapi::RemoteFileSystemProxyInterface::OpenFileCallback& callback,
+    base::PlatformFileError error,
+    base::PlatformFile file) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+  callback.Run(error, file, peer_handle);
 }
 
-// Helper function to run OpenFileCallback from
-// FileSystemProxy::OpenFile().
-void OnGetFileByPathForOpen(
-    const OpenFileCallback& callback,
-    int file_flags,
-    base::ProcessHandle peer_handle,
-    FileError file_error,
-    const base::FilePath& local_path,
-    scoped_ptr<ResourceEntry> entry) {
-  base::PlatformFileError error =
-      FileErrorToPlatformError(file_error);
-  if (error != base::PLATFORM_FILE_OK) {
-    callback.Run(error, base::kInvalidPlatformFileValue, peer_handle);
-    return;
-  }
-
-  base::PlatformFileError* open_error =
-      new base::PlatformFileError(base::PLATFORM_FILE_ERROR_FAILED);
-  base::PostTaskAndReplyWithResult(
-      BrowserThread::GetBlockingPool(),
-      FROM_HERE,
-      base::Bind(&base::CreatePlatformFile,
-                 local_path,
-                 file_flags,
-                 static_cast<bool*>(NULL),
-                 open_error),
-      base::Bind(&OnPlatformFileOpened,
-                 callback,
-                 peer_handle,
-                 base::Owned(open_error)));
-}
-
-// Helper function to run SnapshotFileCallback from
-// FileSystemProxy::CreateSnapshotFile().
-void CallSnapshotFileCallback(
-    const FileSystemOperation::SnapshotFileCallback& callback,
+// Runs |callback| with the arguments based on the given arguments.
+void RunSnapshotFileCallback(
+    const fileapi::FileSystemOperation::SnapshotFileCallback& callback,
+    base::PlatformFileError error,
     const base::PlatformFileInfo& file_info,
-    FileError file_error,
     const base::FilePath& local_path,
-    scoped_ptr<ResourceEntry> entry) {
-  scoped_refptr<ShareableFileReference> file_ref;
-  base::PlatformFileError error =
-      FileErrorToPlatformError(file_error);
+    webkit_blob::ScopedFile::ScopeOutPolicy scope_out_policy) {
+  // ShareableFileReference is thread *unsafe* class. So it is necessary to
+  // create the instance (by invoking GetOrCreate) on IO thread, though
+  // most drive file system related operations run on UI thread.
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 
-  // If the file is a hosted document, a temporary JSON file is created to
-  // represent the document. The JSON file is not cached and its lifetime
-  // is managed by ShareableFileReference.
-  if (error == base::PLATFORM_FILE_OK &&
-      entry && entry->file_specific_info().is_hosted_document()) {
-    file_ref = ShareableFileReference::GetOrCreate(
-        local_path, ShareableFileReference::DELETE_ON_FINAL_RELEASE,
-        BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE));
-  }
-
-  // When reading file, last modified time specified in file info will be
-  // compared to the last modified time of the local version of the drive file.
-  // Since those two values don't generally match (last modification time on the
-  // drive server vs. last modification time of the local, downloaded file), so
-  // we have to opt out from this check. We do this by unsetting last_modified
-  // value in the file info passed to the CreateSnapshot caller.
-  base::PlatformFileInfo final_file_info(file_info);
-  final_file_info.last_modified = base::Time();
-
-  callback.Run(error, final_file_info, local_path, file_ref);
-}
-
-// Emits debug log when FileSystem::CloseFile() is complete.
-void EmitDebugLogForCloseFile(const base::FilePath& local_path,
-                              FileError file_error) {
-  DVLOG(1) << "Closed: " << local_path.AsUTF8Unsafe() << ": " << file_error;
-}
-
-base::PlatformFileError DoTruncateOnBlockingPool(
-    const base::FilePath& local_cache_path,
-    int64 length) {
-  base::PlatformFileError result = base::PLATFORM_FILE_ERROR_FAILED;
-
-  base::PlatformFile file = base::CreatePlatformFile(
-      local_cache_path,
-      base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE,
-      NULL,
-      &result);
-  if (result == base::PLATFORM_FILE_OK) {
-    DCHECK_NE(base::kInvalidPlatformFileValue, file);
-    if (!base::TruncatePlatformFile(file, length))
-      result = base::PLATFORM_FILE_ERROR_FAILED;
-    base::ClosePlatformFile(file);
-  }
-  return result;
-}
-
-void DidCloseFileForTruncate(
-    const FileSystemOperation::StatusCallback& callback,
-    base::PlatformFileError truncate_result,
-    FileError close_result) {
-  // Reports the first error.
-  callback.Run(truncate_result == base::PLATFORM_FILE_OK ?
-               FileErrorToPlatformError(close_result) :
-               truncate_result);
+  scoped_refptr<webkit_blob::ShareableFileReference> file_reference =
+      webkit_blob::ShareableFileReference::GetOrCreate(
+          webkit_blob::ScopedFile(
+              local_path, scope_out_policy,
+              BrowserThread::GetMessageLoopProxyForThread(
+                  BrowserThread::FILE)));
+  callback.Run(error, file_info, local_path, file_reference);
 }
 
 }  // namespace
 
-DirectoryEntry ResourceEntryToDirectoryEntry(
-    const ResourceEntry& resource_entry) {
-  base::PlatformFileInfo file_info;
-  util::ConvertResourceEntryToPlatformFileInfo(
-      resource_entry.file_info(), &file_info);
-
-  DirectoryEntry entry;
-  entry.name = resource_entry.base_name();
-  entry.is_directory = file_info.is_directory;
-  entry.size = file_info.size;
-  entry.last_modified_time = file_info.last_modified;
-  return entry;
-}
-
-// FileSystemProxy class implementation.
-
 FileSystemProxy::FileSystemProxy(
     FileSystemInterface* file_system)
-    : file_system_(file_system) {
+    : file_system_(file_system),
+      worker_(new internal::FileApiWorker(file_system)) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 }
 
 void FileSystemProxy::DetachFromFileSystem() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   file_system_ = NULL;
+  worker_.reset();
 }
 
 void FileSystemProxy::GetFileInfo(
@@ -194,13 +99,9 @@
   }
 
   CallFileSystemMethodOnUIThread(
-      base::Bind(&FileSystemInterface::GetResourceEntryByPath,
-                 base::Unretained(file_system_),
-                 file_path,
-                 google_apis::CreateRelayCallback(
-                     base::Bind(&FileSystemProxy::OnGetMetadata,
-                                this,
-                                callback))));
+      base::Bind(&internal::FileApiWorker::GetFileInfo,
+                 base::Unretained(worker_.get()),
+                 file_path, google_apis::CreateRelayCallback(callback)));
 }
 
 void FileSystemProxy::Copy(
@@ -219,14 +120,10 @@
   }
 
   CallFileSystemMethodOnUIThread(
-      base::Bind(&FileSystemInterface::Copy,
-                 base::Unretained(file_system_),
-                 src_file_path,
-                 dest_file_path,
-                 google_apis::CreateRelayCallback(
-                     base::Bind(&FileSystemProxy::OnStatusCallback,
-                                this,
-                                callback))));
+      base::Bind(&internal::FileApiWorker::Copy,
+                 base::Unretained(worker_.get()),
+                 src_file_path, dest_file_path,
+                 google_apis::CreateRelayCallback(callback)));
 }
 
 void FileSystemProxy::Move(
@@ -245,14 +142,10 @@
   }
 
   CallFileSystemMethodOnUIThread(
-      base::Bind(&FileSystemInterface::Move,
-                 base::Unretained(file_system_),
-                 src_file_path,
-                 dest_file_path,
-                 google_apis::CreateRelayCallback(
-                     base::Bind(&FileSystemProxy::OnStatusCallback,
-                                this,
-                                callback))));
+      base::Bind(&internal::FileApiWorker::Move,
+                 base::Unretained(worker_.get()),
+                 src_file_path, dest_file_path,
+                 google_apis::CreateRelayCallback(callback)));
 }
 
 void FileSystemProxy::ReadDirectory(
@@ -272,13 +165,9 @@
   }
 
   CallFileSystemMethodOnUIThread(
-      base::Bind(&FileSystemInterface::ReadDirectoryByPath,
-                 base::Unretained(file_system_),
-                 file_path,
-                 google_apis::CreateRelayCallback(
-                     base::Bind(&FileSystemProxy::OnReadDirectory,
-                                this,
-                                callback))));
+      base::Bind(&internal::FileApiWorker::ReadDirectory,
+                 base::Unretained(worker_.get()),
+                 file_path, google_apis::CreateRelayCallback(callback)));
 }
 
 void FileSystemProxy::Remove(
@@ -296,14 +185,10 @@
   }
 
   CallFileSystemMethodOnUIThread(
-      base::Bind(&FileSystemInterface::Remove,
-                 base::Unretained(file_system_),
-                 file_path,
-                 recursive,
-                 google_apis::CreateRelayCallback(
-                     base::Bind(&FileSystemProxy::OnStatusCallback,
-                                this,
-                                callback))));
+      base::Bind(&internal::FileApiWorker::Remove,
+                 base::Unretained(worker_.get()),
+                 file_path, recursive,
+                 google_apis::CreateRelayCallback(callback)));
 }
 
 void FileSystemProxy::CreateDirectory(
@@ -322,15 +207,10 @@
   }
 
   CallFileSystemMethodOnUIThread(
-      base::Bind(&FileSystemInterface::CreateDirectory,
-                 base::Unretained(file_system_),
-                 file_path,
-                 exclusive,
-                 recursive,
-                 google_apis::CreateRelayCallback(
-                     base::Bind(&FileSystemProxy::OnStatusCallback,
-                                this,
-                                callback))));
+      base::Bind(&internal::FileApiWorker::CreateDirectory,
+                 base::Unretained(worker_.get()),
+                 file_path, exclusive, recursive,
+                 google_apis::CreateRelayCallback(callback)));
 }
 
 void FileSystemProxy::CreateFile(
@@ -348,14 +228,10 @@
   }
 
   CallFileSystemMethodOnUIThread(
-      base::Bind(&FileSystemInterface::CreateFile,
-                 base::Unretained(file_system_),
-                 file_path,
-                 exclusive,
-                 google_apis::CreateRelayCallback(
-                     base::Bind(&FileSystemProxy::OnStatusCallback,
-                                this,
-                                callback))));
+      base::Bind(&internal::FileApiWorker::CreateFile,
+                 base::Unretained(worker_.get()),
+                 file_path, exclusive,
+                 google_apis::CreateRelayCallback(callback)));
 }
 
 void FileSystemProxy::Truncate(
@@ -364,13 +240,6 @@
     const FileSystemOperation::StatusCallback& callback) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 
-  if (length < 0) {
-    MessageLoopProxy::current()->PostTask(
-        FROM_HERE,
-        base::Bind(callback, base::PLATFORM_FILE_ERROR_INVALID_OPERATION));
-    return;
-  }
-
   base::FilePath file_path;
   if (!ValidateUrl(file_url, &file_path)) {
     MessageLoopProxy::current()->PostTask(
@@ -379,133 +248,11 @@
     return;
   }
 
-  // TODO(kinaba): http://crbug.com/132780.
-  // Optimize the cases for small |length|, at least for |length| == 0.
-  // CreateWritableSnapshotFile downloads the whole content unnecessarily.
   CallFileSystemMethodOnUIThread(
-      base::Bind(&FileSystemInterface::OpenFile,
-                 base::Unretained(file_system_),
-                 file_path,
-                 google_apis::CreateRelayCallback(
-                     base::Bind(&FileSystemProxy::OnFileOpenedForTruncate,
-                                this,
-                                file_path,
-                                length,
-                                callback))));
-}
-
-void FileSystemProxy::OnOpenFileForWriting(
-    int file_flags,
-    base::ProcessHandle peer_handle,
-    const OpenFileCallback& callback,
-    FileError file_error,
-    const base::FilePath& local_cache_path) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
-  base::PlatformFileError error =
-      FileErrorToPlatformError(file_error);
-
-  if (error != base::PLATFORM_FILE_OK) {
-    callback.Run(error, base::kInvalidPlatformFileValue, peer_handle);
-    return;
-  }
-
-  // Cache file prepared for modification is available. Truncate it.
-  base::PlatformFileError* result =
-      new base::PlatformFileError(base::PLATFORM_FILE_ERROR_FAILED);
-  bool posted = base::PostTaskAndReplyWithResult(
-      BrowserThread::GetBlockingPool(), FROM_HERE,
-      base::Bind(&base::CreatePlatformFile,
-                 local_cache_path,
-                 file_flags,
-                 static_cast<bool*>(NULL),
-                 result),
-      base::Bind(&OnPlatformFileOpened,
-                 callback,
-                 peer_handle,
-                 base::Owned(result)));
-  DCHECK(posted);
-}
-
-void FileSystemProxy::OnCreateFileForOpen(
-    const base::FilePath& file_path,
-    int file_flags,
-    base::ProcessHandle peer_handle,
-    const OpenFileCallback& callback,
-    FileError file_error) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-  base::PlatformFileError create_result =
-      FileErrorToPlatformError(file_error);
-
-  if ((create_result == base::PLATFORM_FILE_OK) ||
-      ((create_result == base::PLATFORM_FILE_ERROR_EXISTS) &&
-       (file_flags & base::PLATFORM_FILE_CREATE_ALWAYS))) {
-    // If we are trying to always create an existing file, then
-    // if it really exists open it as truncated.
-    file_flags &= ~base::PLATFORM_FILE_CREATE;
-    file_flags &= ~base::PLATFORM_FILE_CREATE_ALWAYS;
-    file_flags |= base::PLATFORM_FILE_OPEN_TRUNCATED;
-  } else {
-    callback.Run(create_result, base::kInvalidPlatformFileValue, peer_handle);
-    return;
-  }
-
-  // Open created (or existing) file for writing.
-  CallFileSystemMethodOnUIThread(
-      base::Bind(&FileSystemInterface::OpenFile,
-                 base::Unretained(file_system_),
-                 file_path,
-                 google_apis::CreateRelayCallback(
-                     base::Bind(&FileSystemProxy::OnOpenFileForWriting,
-                                this,
-                                file_flags,
-                                peer_handle,
-                                callback))));
-}
-
-void FileSystemProxy::OnFileOpenedForTruncate(
-    const base::FilePath& virtual_path,
-    int64 length,
-    const fileapi::FileSystemOperation::StatusCallback& callback,
-    FileError open_result,
-    const base::FilePath& local_cache_path) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
-  if (open_result != FILE_ERROR_OK) {
-    callback.Run(FileErrorToPlatformError(open_result));
-    return;
-  }
-
-  // Cache file prepared for modification is available. Truncate it.
-  bool posted = base::PostTaskAndReplyWithResult(
-      BrowserThread::GetBlockingPool(),
-      FROM_HERE,
-      base::Bind(&DoTruncateOnBlockingPool,
-                 local_cache_path,
-                 length),
-      base::Bind(&FileSystemProxy::DidTruncate,
-                 this,
-                 virtual_path,
-                 callback));
-  DCHECK(posted);
-}
-
-void FileSystemProxy::DidTruncate(
-    const base::FilePath& virtual_path,
-    const FileSystemOperation::StatusCallback& callback,
-    base::PlatformFileError truncate_result) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
-  // Truncation finished. We must close the file no matter |truncate_result|
-  // indicates an error or not.
-  CallFileSystemMethodOnUIThread(
-      base::Bind(&FileSystemInterface::CloseFile,
-                 base::Unretained(file_system_),
-                 virtual_path,
-                 google_apis::CreateRelayCallback(
-                     base::Bind(&DidCloseFileForTruncate,
-                                callback,
-                                truncate_result))));
+      base::Bind(&internal::FileApiWorker::Truncate,
+                 base::Unretained(worker_.get()),
+                 file_path, length,
+                 google_apis::CreateRelayCallback(callback)));
 }
 
 void FileSystemProxy::OpenFile(
@@ -526,73 +273,12 @@
     return;
   }
 
-  // TODO(zelidrag): Wire all other file open operations.
-  if ((file_flags & base::PLATFORM_FILE_DELETE_ON_CLOSE)) {
-    NOTIMPLEMENTED() << "File create/write operations not yet supported "
-                     << file_path.value();
-    MessageLoopProxy::current()->PostTask(
-        FROM_HERE,
-        base::Bind(callback,
-                   base::PLATFORM_FILE_ERROR_FAILED,
-                   base::kInvalidPlatformFileValue,
-                   peer_handle));
-    return;
-  }
-
-  if ((file_flags & base::PLATFORM_FILE_OPEN) ||
-      (file_flags & base::PLATFORM_FILE_OPEN_ALWAYS) ||
-      (file_flags & base::PLATFORM_FILE_OPEN_TRUNCATED)) {
-    if ((file_flags & base::PLATFORM_FILE_OPEN_TRUNCATED) ||
-        (file_flags & base::PLATFORM_FILE_OPEN_ALWAYS) ||
-        (file_flags & base::PLATFORM_FILE_WRITE) ||
-        (file_flags & base::PLATFORM_FILE_EXCLUSIVE_WRITE)) {
-      // Open existing file for writing.
-      CallFileSystemMethodOnUIThread(
-          base::Bind(&FileSystemInterface::OpenFile,
-                     base::Unretained(file_system_),
-                     file_path,
-                     google_apis::CreateRelayCallback(
-                         base::Bind(&FileSystemProxy::OnOpenFileForWriting,
-                                    this,
-                                    file_flags,
-                                    peer_handle,
-                                    callback))));
-    } else {
-      // Read-only file open.
-      CallFileSystemMethodOnUIThread(
-          base::Bind(&FileSystemInterface::GetFileByPath,
-                     base::Unretained(file_system_),
-                     file_path,
-                     google_apis::CreateRelayCallback(
-                         base::Bind(&OnGetFileByPathForOpen,
-                                    callback,
-                                    file_flags,
-                                    peer_handle))));
-    }
-  } else if ((file_flags & base::PLATFORM_FILE_CREATE) ||
-             (file_flags & base::PLATFORM_FILE_CREATE_ALWAYS)) {
-    // Open existing file for writing.
-    CallFileSystemMethodOnUIThread(
-        base::Bind(&FileSystemInterface::CreateFile,
-                   base::Unretained(file_system_),
-                   file_path,
-                   file_flags & base::PLATFORM_FILE_EXCLUSIVE_WRITE,
-                   google_apis::CreateRelayCallback(
-                       base::Bind(&FileSystemProxy::OnCreateFileForOpen,
-                                  this,
-                                  file_path,
-                                  file_flags,
-                                  peer_handle,
-                                  callback))));
-  } else {
-    NOTREACHED() << "Unhandled file flags combination " << file_flags;
-    MessageLoopProxy::current()->PostTask(
-        FROM_HERE,
-        base::Bind(callback,
-                   base::PLATFORM_FILE_ERROR_FAILED,
-                   base::kInvalidPlatformFileValue,
-                   peer_handle));
-  }
+  CallFileSystemMethodOnUIThread(
+      base::Bind(&internal::FileApiWorker::OpenFile,
+                 base::Unretained(worker_.get()),
+                 file_path, file_flags,
+                 google_apis::CreateRelayCallback(
+                     base::Bind(&RunOpenFileCallback, peer_handle, callback))));
 }
 
 void FileSystemProxy::NotifyCloseFile(const FileSystemURL& url) {
@@ -601,12 +287,8 @@
     return;
 
   CallFileSystemMethodOnUIThread(
-      base::Bind(&FileSystemInterface::CloseFile,
-                 base::Unretained(file_system_),
-                 file_path,
-                 google_apis::CreateRelayCallback(
-                     base::Bind(&EmitDebugLogForCloseFile,
-                                file_path))));
+      base::Bind(&internal::FileApiWorker::CloseFile,
+                 base::Unretained(worker_.get()), file_path));
 }
 
 void FileSystemProxy::TouchFile(
@@ -621,13 +303,10 @@
     return;
 
   CallFileSystemMethodOnUIThread(
-      base::Bind(&FileSystemInterface::TouchFile,
-                 base::Unretained(file_system_),
+      base::Bind(&internal::FileApiWorker::TouchFile,
+                 base::Unretained(worker_.get()),
                  file_path, last_access_time, last_modified_time,
-                 google_apis::CreateRelayCallback(
-                     base::Bind(&FileSystemProxy::OnStatusCallback,
-                                this,
-                                callback))));
+                 google_apis::CreateRelayCallback(callback)));
 }
 
 void FileSystemProxy::CreateSnapshotFile(
@@ -643,47 +322,15 @@
                    base::PLATFORM_FILE_ERROR_NOT_FOUND,
                    base::PlatformFileInfo(),
                    base::FilePath(),
-                   scoped_refptr<ShareableFileReference>(NULL)));
+                   scoped_refptr<ShareableFileReference>()));
     return;
   }
 
   CallFileSystemMethodOnUIThread(
-      base::Bind(&FileSystemInterface::GetResourceEntryByPath,
-                 base::Unretained(file_system_),
-                 file_path,
+      base::Bind(&internal::FileApiWorker::CreateSnapshotFile,
+                 base::Unretained(worker_.get()), file_path,
                  google_apis::CreateRelayCallback(
-                     base::Bind(&FileSystemProxy::OnGetResourceEntryByPath,
-                                this,
-                                file_path,
-                                callback))));
-}
-
-void FileSystemProxy::OnGetResourceEntryByPath(
-    const base::FilePath& entry_path,
-    const FileSystemOperation::SnapshotFileCallback& callback,
-    FileError error,
-    scoped_ptr<ResourceEntry> entry) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
-  if (error != FILE_ERROR_OK || !entry.get()) {
-    callback.Run(base::PLATFORM_FILE_ERROR_NOT_FOUND,
-                 base::PlatformFileInfo(),
-                 base::FilePath(),
-                 scoped_refptr<ShareableFileReference>(NULL));
-    return;
-  }
-
-  base::PlatformFileInfo file_info;
-  util::ConvertResourceEntryToPlatformFileInfo(entry->file_info(), &file_info);
-
-  CallFileSystemMethodOnUIThread(
-      base::Bind(&FileSystemInterface::GetFileByPath,
-                 base::Unretained(file_system_),
-                 entry_path,
-                 google_apis::CreateRelayCallback(
-                     base::Bind(&CallSnapshotFileCallback,
-                                callback,
-                                file_info))));
+                     base::Bind(&RunSnapshotFileCallback, callback))));
 }
 
 void FileSystemProxy::CreateWritableSnapshotFile(
@@ -767,62 +414,6 @@
     method_call.Run();
 }
 
-void FileSystemProxy::OnStatusCallback(
-    const fileapi::FileSystemOperation::StatusCallback& callback,
-    FileError error) {
-  callback.Run(FileErrorToPlatformError(error));
-}
-
-void FileSystemProxy::OnGetMetadata(
-    const FileSystemOperation::GetMetadataCallback& callback,
-    FileError error,
-    scoped_ptr<ResourceEntry> entry) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
-  if (error != FILE_ERROR_OK) {
-    callback.Run(FileErrorToPlatformError(error),
-                 base::PlatformFileInfo());
-    return;
-  }
-  DCHECK(entry.get());
-
-  base::PlatformFileInfo file_info;
-  util::ConvertResourceEntryToPlatformFileInfo(entry->file_info(), &file_info);
-
-  callback.Run(base::PLATFORM_FILE_OK, file_info);
-}
-
-void FileSystemProxy::OnReadDirectory(
-    const FileSystemOperation::ReadDirectoryCallback&
-    callback,
-    FileError error,
-    bool hide_hosted_documents,
-    scoped_ptr<ResourceEntryVector> resource_entries) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
-  if (error != FILE_ERROR_OK) {
-    callback.Run(FileErrorToPlatformError(error),
-                 std::vector<DirectoryEntry>(),
-                 false);
-    return;
-  }
-  DCHECK(resource_entries.get());
-
-  std::vector<DirectoryEntry> entries;
-  // Convert Drive files to something File API stack can understand.
-  for (size_t i = 0; i < resource_entries->size(); ++i) {
-    const ResourceEntry& resource_entry = (*resource_entries)[i];
-    if (resource_entry.has_file_specific_info() &&
-        resource_entry.file_specific_info().is_hosted_document() &&
-        hide_hosted_documents) {
-      continue;
-    }
-    entries.push_back(ResourceEntryToDirectoryEntry(resource_entry));
-  }
-
-  callback.Run(base::PLATFORM_FILE_OK, entries, false);
-}
-
 void FileSystemProxy::OnCreateWritableSnapshotFile(
     const base::FilePath& virtual_path,
     const fileapi::WritableSnapshotFile& callback,
@@ -852,12 +443,8 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 
   CallFileSystemMethodOnUIThread(
-      base::Bind(&FileSystemInterface::CloseFile,
-                 base::Unretained(file_system_),
-                 virtual_path,
-                 google_apis::CreateRelayCallback(
-                     base::Bind(&EmitDebugLogForCloseFile,
-                                virtual_path))));
+      base::Bind(&internal::FileApiWorker::CloseFile,
+                 base::Unretained(worker_.get()), virtual_path));
 }
 
 FileSystemInterface* FileSystemProxy::GetFileSystemOnUIThread() {
diff --git a/chrome/browser/chromeos/drive/file_system_proxy.h b/chrome/browser/chromeos/drive/file_system_proxy.h
index 0d674f4..f4dcaca 100644
--- a/chrome/browser/chromeos/drive/file_system_proxy.h
+++ b/chrome/browser/chromeos/drive/file_system_proxy.h
@@ -10,7 +10,7 @@
 
 namespace fileapi {
 class FileSystemURL;
-}
+}  // namespace fileapi
 
 namespace drive {
 
@@ -19,6 +19,10 @@
 
 typedef std::vector<ResourceEntry> ResourceEntryVector;
 
+namespace internal {
+class FileApiWorker;
+}  // namespace internal
+
 // Implementation of File API's remote file system proxy for Drive-backed
 // file system.
 class FileSystemProxy : public fileapi::RemoteFileSystemProxyInterface {
@@ -113,38 +117,6 @@
   void CallFileSystemMethodOnUIThreadInternal(
       const base::Closure& method_call);
 
-  // Helper callback for relaying reply for status callbacks to the
-  // calling thread.
-  void OnStatusCallback(
-      const fileapi::FileSystemOperation::StatusCallback& callback,
-      FileError error);
-
-  // Helper callback for relaying reply for metadata retrieval request to the
-  // calling thread.
-  void OnGetMetadata(
-      const fileapi::FileSystemOperation::GetMetadataCallback&
-          callback,
-      FileError error,
-      scoped_ptr<ResourceEntry> entry);
-
-  // Helper callback for relaying reply for GetResourceEntryByPath() to the
-  // calling thread.
-  void OnGetResourceEntryByPath(
-      const base::FilePath& entry_path,
-      const fileapi::FileSystemOperation::SnapshotFileCallback&
-          callback,
-      FileError error,
-      scoped_ptr<ResourceEntry> entry);
-
-  // Helper callback for relaying reply for ReadDirectory() to the calling
-  // thread.
-  void OnReadDirectory(
-      const fileapi::FileSystemOperation::ReadDirectoryCallback&
-          callback,
-      FileError error,
-      bool hide_hosted_documents,
-      scoped_ptr<ResourceEntryVector> resource_entries);
-
   // Helper callback for relaying reply for CreateWritableSnapshotFile() to
   // the calling thread.
   void OnCreateWritableSnapshotFile(
@@ -160,53 +132,13 @@
       const base::FilePath& virtual_path,
       const base::FilePath& local_path);
 
-  // Invoked during Truncate() operation. This is called when a local modifiable
-  // cache is ready for truncation.
-  void OnFileOpenedForTruncate(
-      const base::FilePath& virtual_path,
-      int64 length,
-      const fileapi::FileSystemOperation::StatusCallback& callback,
-      FileError open_result,
-      const base::FilePath& local_cache_path);
-
-  // Invoked during Truncate() operation. This is called when the truncation of
-  // a local cache file is finished on FILE thread.
-  void DidTruncate(
-      const base::FilePath& virtual_path,
-      const fileapi::FileSystemOperation::StatusCallback& callback,
-      base::PlatformFileError truncate_result);
-
-  // Invoked during OpenFile() operation when truncate or write flags are set.
-  // This is called when a local modifiable cached file is ready for such
-  // operation.
-  void OnOpenFileForWriting(
-      int file_flags,
-      base::ProcessHandle peer_handle,
-      const OpenFileCallback& callback,
-      FileError file_error,
-      const base::FilePath& local_cache_path);
-
-  // Invoked during OpenFile() operation when file create flags are set.
-  void OnCreateFileForOpen(
-      const base::FilePath& file_path,
-      int file_flags,
-      base::ProcessHandle peer_handle,
-      const OpenFileCallback& callback,
-      FileError file_error);
-
-  // Invoked during OpenFile() operation when base::PLATFORM_FILE_OPEN_TRUNCATED
-  // flag is set. This is called when the truncation of a local cache file is
-  // finished on FILE thread.
-  void OnOpenAndTruncate(
-      base::ProcessHandle peer_handle,
-      const OpenFileCallback& callback,
-      base::PlatformFile* platform_file,
-      base::PlatformFileError* truncate_result);
-
   // Returns |file_system_| on UI thread.
   FileSystemInterface* GetFileSystemOnUIThread();
 
+  // TODO(hidehiko): Remove |file_system_| when all the core implementation
+  // is moved to FileApiWorker.
   FileSystemInterface* file_system_;
+  scoped_ptr<internal::FileApiWorker> worker_;
 };
 
 }  // namespace drive
diff --git a/chrome/browser/chromeos/drive/file_system_unittest.cc b/chrome/browser/chromeos/drive/file_system_unittest.cc
index 63bb0cb..430539b 100644
--- a/chrome/browser/chromeos/drive/file_system_unittest.cc
+++ b/chrome/browser/chromeos/drive/file_system_unittest.cc
@@ -17,9 +17,9 @@
 #include "chrome/browser/chromeos/drive/change_list_loader.h"
 #include "chrome/browser/chromeos/drive/drive.pb.h"
 #include "chrome/browser/chromeos/drive/fake_free_disk_space_getter.h"
+#include "chrome/browser/chromeos/drive/file_system_observer.h"
 #include "chrome/browser/chromeos/drive/file_system_util.h"
 #include "chrome/browser/chromeos/drive/job_scheduler.h"
-#include "chrome/browser/chromeos/drive/mock_directory_change_observer.h"
 #include "chrome/browser/chromeos/drive/sync_client.h"
 #include "chrome/browser/chromeos/drive/test_util.h"
 #include "chrome/browser/drive/fake_drive_service.h"
@@ -27,14 +27,8 @@
 #include "chrome/browser/google_apis/test_util.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/test/test_browser_thread_bundle.h"
-#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-using ::testing::AtLeast;
-using ::testing::Eq;
-using ::testing::StrictMock;
-using ::testing::_;
-
 namespace drive {
 namespace {
 
@@ -58,6 +52,27 @@
     quit.Run();
 }
 
+// This class is used to record directory changes and examine them later.
+class MockDirectoryChangeObserver : public FileSystemObserver {
+ public:
+  MockDirectoryChangeObserver() {}
+  virtual ~MockDirectoryChangeObserver() {}
+
+  // FileSystemObserver overrides.
+  virtual void OnDirectoryChanged(
+      const base::FilePath& directory_path) OVERRIDE {
+    changed_directories_.push_back(directory_path);
+  }
+
+  const std::vector<base::FilePath>& changed_directories() const {
+    return changed_directories_;
+  }
+
+ private:
+  std::vector<base::FilePath> changed_directories_;
+  DISALLOW_COPY_AND_ASSIGN(MockDirectoryChangeObserver);
+};
+
 }  // namespace
 
 class FileSystemTest : public testing::Test {
@@ -65,17 +80,20 @@
   virtual void SetUp() OVERRIDE {
     profile_.reset(new TestingProfile);
 
-    // The fake object will be manually deleted in TearDown().
-    fake_drive_service_.reset(new google_apis::FakeDriveService);
+    fake_network_change_notifier_.reset(
+        new test_util::FakeNetworkChangeNotifier);
+
+    fake_drive_service_.reset(new FakeDriveService);
     fake_drive_service_->LoadResourceListForWapi(
-        "chromeos/gdata/root_feed.json");
+        "gdata/root_feed.json");
     fake_drive_service_->LoadAccountMetadataForWapi(
-        "chromeos/gdata/account_metadata.json");
+        "gdata/account_metadata.json");
 
     fake_free_disk_space_getter_.reset(new FakeFreeDiskSpaceGetter);
 
     scheduler_.reset(new JobScheduler(profile_.get(),
-                                      fake_drive_service_.get()));
+                                      fake_drive_service_.get(),
+                                      base::MessageLoopProxy::current()));
 
     ASSERT_TRUE(file_util::CreateDirectory(util::GetCacheRootPath(
         profile_.get()).Append(util::kMetadataDirectory)));
@@ -84,24 +102,27 @@
     ASSERT_TRUE(file_util::CreateDirectory(util::GetCacheRootPath(
         profile_.get()).Append(util::kTemporaryFileDirectory)));
 
-    cache_.reset(new internal::FileCache(
-        util::GetCacheRootPath(profile_.get()).Append(util::kMetadataDirectory),
-        util::GetCacheRootPath(profile_.get()).Append(
-            util::kCacheFileDirectory),
-        base::MessageLoopProxy::current(),
-        fake_free_disk_space_getter_.get()));
-
-    mock_directory_observer_.reset(new StrictMock<MockDirectoryChangeObserver>);
-
-    ASSERT_TRUE(cache_->Initialize());
+    mock_directory_observer_.reset(new MockDirectoryChangeObserver);
 
     SetUpResourceMetadataAndFileSystem();
   }
 
   void SetUpResourceMetadataAndFileSystem() {
-    resource_metadata_.reset(new internal::ResourceMetadata(
+    metadata_storage_.reset(new internal::ResourceMetadataStorage(
         util::GetCacheRootPath(profile_.get()).Append(util::kMetadataDirectory),
         base::MessageLoopProxy::current()));
+    ASSERT_TRUE(metadata_storage_->Initialize());
+
+    cache_.reset(new internal::FileCache(
+        metadata_storage_.get(),
+        util::GetCacheRootPath(profile_.get()).Append(
+            util::kCacheFileDirectory),
+        base::MessageLoopProxy::current(),
+        fake_free_disk_space_getter_.get()));
+    ASSERT_TRUE(cache_->Initialize());
+
+    resource_metadata_.reset(new internal::ResourceMetadata(
+        metadata_storage_.get(), base::MessageLoopProxy::current()));
 
     file_system_.reset(new FileSystem(
         profile_.get(),
@@ -122,15 +143,6 @@
     ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->Initialize());
   }
 
-  virtual void TearDown() OVERRIDE {
-    ASSERT_TRUE(file_system_);
-    file_system_.reset();
-    scheduler_.reset();
-    fake_drive_service_.reset();
-    cache_.reset();
-    profile_.reset(NULL);
-  }
-
   // Loads the full resource list via FakeDriveService.
   bool LoadFullResourceList() {
     FileError error = FILE_ERROR_FAILED;
@@ -158,12 +170,11 @@
   scoped_ptr<ResourceEntryVector> ReadDirectoryByPathSync(
       const base::FilePath& file_path) {
     FileError error = FILE_ERROR_FAILED;
-    bool unused_hide_hosted_documents;
     scoped_ptr<ResourceEntryVector> entries;
     file_system_->ReadDirectoryByPath(
         file_path,
         google_apis::test_util::CreateCopyResultCallback(
-            &error, &unused_hide_hosted_documents, &entries));
+            &error, &entries));
     google_apis::test_util::RunBlockingPoolTask();
 
     return entries.Pass();
@@ -199,13 +210,16 @@
     // Destroy the existing resource metadata to close DB.
     resource_metadata_.reset();
 
-    const std::string root_resource_id =
-        fake_drive_service_->GetRootResourceId();
+    base::FilePath metadata_directory =
+        util::GetCacheRootPath(profile_.get()).Append(util::kMetadataDirectory);
+    scoped_ptr<internal::ResourceMetadataStorage,
+               test_util::DestroyHelperForTests> metadata_storage(
+                   new internal::ResourceMetadataStorage(
+                       metadata_directory, base::MessageLoopProxy::current()));
+
     scoped_ptr<internal::ResourceMetadata, test_util::DestroyHelperForTests>
         resource_metadata(new internal::ResourceMetadata(
-            util::GetCacheRootPath(profile_.get()).Append(
-                util::kMetadataDirectory),
-            base::MessageLoopProxy::current()));
+            metadata_storage_.get(), base::MessageLoopProxy::current()));
 
     if (resource_metadata->Initialize() != FILE_ERROR_OK)
       return false;
@@ -215,6 +229,8 @@
       return false;
 
     // drive/root
+    const std::string root_resource_id =
+        fake_drive_service_->GetRootResourceId();
     if (resource_metadata->AddEntry(util::CreateMyDriveRootEntry(
             root_resource_id)) != FILE_ERROR_OK)
       return false;
@@ -278,22 +294,23 @@
 
   content::TestBrowserThreadBundle thread_bundle_;
   scoped_ptr<TestingProfile> profile_;
+  scoped_ptr<test_util::FakeNetworkChangeNotifier>
+      fake_network_change_notifier_;
 
-  scoped_ptr<internal::FileCache, test_util::DestroyHelperForTests> cache_;
-  scoped_ptr<FileSystem> file_system_;
-  scoped_ptr<google_apis::FakeDriveService> fake_drive_service_;
+  scoped_ptr<FakeDriveService> fake_drive_service_;
+  scoped_ptr<FakeFreeDiskSpaceGetter> fake_free_disk_space_getter_;
   scoped_ptr<JobScheduler> scheduler_;
+  scoped_ptr<MockDirectoryChangeObserver> mock_directory_observer_;
+
+  scoped_ptr<internal::ResourceMetadataStorage,
+             test_util::DestroyHelperForTests> metadata_storage_;
+  scoped_ptr<internal::FileCache, test_util::DestroyHelperForTests> cache_;
   scoped_ptr<internal::ResourceMetadata, test_util::DestroyHelperForTests>
       resource_metadata_;
-  scoped_ptr<FakeFreeDiskSpaceGetter> fake_free_disk_space_getter_;
-  scoped_ptr<StrictMock<MockDirectoryChangeObserver> > mock_directory_observer_;
+  scoped_ptr<FileSystem> file_system_;
 };
 
 TEST_F(FileSystemTest, DuplicatedAsyncInitialization) {
-  // "Fast fetch" will fire an OnirectoryChanged event.
-  EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
-      Eq(base::FilePath(FILE_PATH_LITERAL("drive"))))).Times(1);
-
   base::RunLoop loop;
 
   int counter = 0;
@@ -313,6 +330,11 @@
   EXPECT_EQ(1, fake_drive_service_->resource_list_load_count());
   // See the comment in GetMyDriveRoot test case why this is 2.
   EXPECT_EQ(2, fake_drive_service_->about_resource_load_count());
+
+  // "Fast fetch" will fire an OnirectoryChanged event.
+  ASSERT_EQ(1u, mock_directory_observer_->changed_directories().size());
+  EXPECT_EQ(base::FilePath(FILE_PATH_LITERAL("drive")),
+            mock_directory_observer_->changed_directories()[0]);
 }
 
 TEST_F(FileSystemTest, GetGrandRootEntry) {
@@ -339,10 +361,6 @@
 }
 
 TEST_F(FileSystemTest, GetMyDriveRoot) {
-  // "Fast fetch" will fire an OnirectoryChanged event.
-  EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
-      Eq(base::FilePath(FILE_PATH_LITERAL("drive"))))).Times(1);
-
   const base::FilePath kFilePath(FILE_PATH_LITERAL("drive/root"));
   scoped_ptr<ResourceEntry> entry = GetResourceEntryByPathSync(kFilePath);
   ASSERT_TRUE(entry);
@@ -359,6 +377,11 @@
 
   // After "fast fetch" is done, full resource list is fetched.
   EXPECT_EQ(1, fake_drive_service_->resource_list_load_count());
+
+  // "Fast fetch" will fire an OnirectoryChanged event.
+  ASSERT_EQ(1u, mock_directory_observer_->changed_directories().size());
+  EXPECT_EQ(base::FilePath(FILE_PATH_LITERAL("drive")),
+            mock_directory_observer_->changed_directories()[0]);
 }
 
 TEST_F(FileSystemTest, GetExistingFile) {
@@ -413,7 +436,7 @@
   const std::string resource_id1 = entry->resource_id();
 
   const base::FilePath kFilePath2(
-      FILE_PATH_LITERAL("drive/root/Duplicate Name (2).txt"));
+      FILE_PATH_LITERAL("drive/root/Duplicate Name (1).txt"));
   entry = GetResourceEntryByPathSync(kFilePath2);
   ASSERT_TRUE(entry);
   const std::string resource_id2 = entry->resource_id();
@@ -457,9 +480,6 @@
 }
 
 TEST_F(FileSystemTest, ReadDirectoryByPath_Root) {
-  EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
-      Eq(base::FilePath(FILE_PATH_LITERAL("drive"))))).Times(1);
-
   // ReadDirectoryByPath() should kick off the resource list loading.
   scoped_ptr<ResourceEntryVector> entries(
       ReadDirectoryByPathSync(base::FilePath::FromUTF8Unsafe("drive")));
@@ -482,6 +502,10 @@
 
   EXPECT_TRUE(found_other);
   EXPECT_TRUE(found_my_drive);
+
+  ASSERT_EQ(1u, mock_directory_observer_->changed_directories().size());
+  EXPECT_EQ(base::FilePath(FILE_PATH_LITERAL("drive")),
+            mock_directory_observer_->changed_directories()[0]);
 }
 
 TEST_F(FileSystemTest, ReadDirectoryByPath_NonRootDirectory) {
@@ -522,13 +546,19 @@
   // Make GetResourceList fail for simulating offline situation. This will
   // leave the file system "loaded from cache, but not synced with server"
   // state.
+  fake_network_change_notifier_->SetConnectionType(
+      net::NetworkChangeNotifier::CONNECTION_NONE);
   fake_drive_service_->set_offline(true);
 
-  // Kicks loading of cached file system and query for server update.
-  EXPECT_TRUE(ReadDirectoryByPathSync(util::GetDriveMyDriveRootPath()));
+  // Load the root.
+  EXPECT_TRUE(ReadDirectoryByPathSync(util::GetDriveGrandRootPath()));
   // Loading of about resource should not happen as it's offline.
   EXPECT_EQ(0, fake_drive_service_->about_resource_load_count());
 
+  // Load "My Drive".
+  EXPECT_TRUE(ReadDirectoryByPathSync(util::GetDriveMyDriveRootPath()));
+  EXPECT_EQ(0, fake_drive_service_->about_resource_load_count());
+
   // Tests that cached data can be loaded even if the server is not reachable.
   EXPECT_TRUE(EntryExists(base::FilePath(
       FILE_PATH_LITERAL("drive/root/File1"))));
@@ -545,21 +575,20 @@
   // the file system should be able to start periodic refresh.
   // To test it, call CheckForUpdates and verify it does try to check
   // updates, which will cause directory changes.
+  fake_network_change_notifier_->SetConnectionType(
+      net::NetworkChangeNotifier::CONNECTION_WIFI);
   fake_drive_service_->set_offline(false);
 
   file_system_->CheckForUpdates();
-  EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(_))
-      .Times(AtLeast(1));
 
   google_apis::test_util::RunBlockingPoolTask();
   EXPECT_EQ(1, fake_drive_service_->about_resource_load_count());
   EXPECT_EQ(1, fake_drive_service_->change_list_load_count());
+
+  ASSERT_LE(1u, mock_directory_observer_->changed_directories().size());
 }
 
 TEST_F(FileSystemTest, ReadDirectoryWhileRefreshing) {
-  EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(_))
-      .Times(AtLeast(1));
-
   // Enter the "refreshing" state so the fast fetch will be performed.
   ASSERT_TRUE(SetUpTestFileSystem(USE_OLD_TIMESTAMP));
   file_system_->CheckForUpdates();
@@ -568,6 +597,8 @@
   EXPECT_TRUE(ReadDirectoryByPathSync(base::FilePath(
       FILE_PATH_LITERAL("drive/root/Dir1"))));
   EXPECT_EQ(1, fake_drive_service_->directory_load_count());
+
+  ASSERT_LE(1u, mock_directory_observer_->changed_directories().size());
 }
 
 TEST_F(FileSystemTest, GetResourceEntryExistingWhileRefreshing) {
@@ -582,9 +613,6 @@
 }
 
 TEST_F(FileSystemTest, GetResourceEntryNonExistentWhileRefreshing) {
-  EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(_))
-      .Times(AtLeast(1));
-
   // Enter the "refreshing" state so the fast fetch will be performed.
   ASSERT_TRUE(SetUpTestFileSystem(USE_OLD_TIMESTAMP));
   file_system_->CheckForUpdates();
@@ -593,6 +621,8 @@
   EXPECT_FALSE(GetResourceEntryByPathSync(base::FilePath(
       FILE_PATH_LITERAL("drive/root/Dir1/NonExistentFile"))));
   EXPECT_EQ(1, fake_drive_service_->directory_load_count());
+
+  ASSERT_LE(1u, mock_directory_observer_->changed_directories().size());
 }
 
 TEST_F(FileSystemTest, CreateDirectoryByImplicitLoad) {
@@ -614,10 +644,6 @@
 }
 
 TEST_F(FileSystemTest, PinAndUnpin) {
-  // Pinned file gets synced and it results in entry state changes.
-  EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
-      Eq(base::FilePath(FILE_PATH_LITERAL("drive/root"))))).Times(AtLeast(1));
-
   ASSERT_TRUE(LoadFullResourceList());
 
   base::FilePath file_path(FILE_PATH_LITERAL("drive/root/File 1.txt"));
@@ -649,6 +675,11 @@
   EXPECT_TRUE(cache_->GetCacheEntry(
       entry->resource_id(), std::string(), &cache_entry));
   EXPECT_FALSE(cache_entry.is_pinned());
+
+  // Pinned file gets synced and it results in entry state changes.
+  ASSERT_EQ(1u, mock_directory_observer_->changed_directories().size());
+  EXPECT_EQ(base::FilePath(FILE_PATH_LITERAL("drive/root")),
+            mock_directory_observer_->changed_directories()[0]);
 }
 
 TEST_F(FileSystemTest, PinAndUnpin_NotSynced) {
@@ -696,26 +727,22 @@
 TEST_F(FileSystemTest, RefreshDirectory) {
   ASSERT_TRUE(LoadFullResourceList());
 
-  // We'll notify the directory change to the observer.
-  EXPECT_CALL(*mock_directory_observer_,
-              OnDirectoryChanged(Eq(util::GetDriveMyDriveRootPath()))).Times(1);
-
   FileError error = FILE_ERROR_FAILED;
   file_system_->RefreshDirectory(
       util::GetDriveMyDriveRootPath(),
       google_apis::test_util::CreateCopyResultCallback(&error));
   google_apis::test_util::RunBlockingPoolTask();
   EXPECT_EQ(FILE_ERROR_OK, error);
+
+  // We'll notify the directory change to the observer.
+  ASSERT_EQ(1u, mock_directory_observer_->changed_directories().size());
+  EXPECT_EQ(util::GetDriveMyDriveRootPath(),
+            mock_directory_observer_->changed_directories()[0]);
 }
 
 TEST_F(FileSystemTest, OpenAndCloseFile) {
   ASSERT_TRUE(LoadFullResourceList());
 
-  // The transfered file is cached and the change of "offline available"
-  // attribute is notified.
-  EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
-      Eq(base::FilePath(FILE_PATH_LITERAL("drive/root"))))).Times(AtLeast(1));
-
   const base::FilePath kFileInRoot(FILE_PATH_LITERAL("drive/root/File 1.txt"));
   scoped_ptr<ResourceEntry> entry(GetResourceEntryByPathSync(kFileInRoot));
   const std::string& file_resource_id = entry->resource_id();
@@ -733,6 +760,13 @@
   // Verify that the file was properly opened.
   EXPECT_EQ(FILE_ERROR_OK, error);
 
+  // The opened file is downloaded, which means the file is available
+  // offline. The directory change should be notified so Files.app can change
+  // the offline availability status of the file.
+  ASSERT_EQ(1u, mock_directory_observer_->changed_directories().size());
+  EXPECT_EQ(base::FilePath(FILE_PATH_LITERAL("drive/root")),
+            mock_directory_observer_->changed_directories()[0]);
+
   // Try to open the already opened file.
   file_system_->OpenFile(
       kFileInRoot,
@@ -784,6 +818,12 @@
   ASSERT_TRUE(gdata_entry);
   EXPECT_EQ(static_cast<int>(kNewContent.size()), gdata_entry->file_size());
 
+  // The modified file is uploaded. The directory change should be notified
+  // so Files.app can show new metadata of the modified file.
+  ASSERT_EQ(2u, mock_directory_observer_->changed_directories().size());
+  EXPECT_EQ(base::FilePath(FILE_PATH_LITERAL("drive/root")),
+            mock_directory_observer_->changed_directories()[1]);
+
   // Try to close the same file twice.
   file_system_->CloseFile(
       kFileInRoot,
@@ -792,6 +832,8 @@
 
   // It must fail.
   EXPECT_EQ(FILE_ERROR_NOT_FOUND, error);
+  // There should be no new directory change.
+  ASSERT_EQ(2u, mock_directory_observer_->changed_directories().size());
 }
 
 TEST_F(FileSystemTest, MarkCacheFileAsMountedAndUnmounted) {
@@ -805,7 +847,7 @@
   ASSERT_EQ(FILE_ERROR_OK, cache_->Store(
       entry->resource_id(),
       entry->file_specific_info().md5(),
-      google_apis::test_util::GetTestFilePath("chromeos/gdata/root_feed.json"),
+      google_apis::test_util::GetTestFilePath("gdata/root_feed.json"),
       internal::FileCache::FILE_OPERATION_COPY));
 
   // Test for mounting.
diff --git a/chrome/browser/chromeos/drive/file_system_util.cc b/chrome/browser/chromeos/drive/file_system_util.cc
index 9d3ebd2..704450c 100644
--- a/chrome/browser/chromeos/drive/file_system_util.cc
+++ b/chrome/browser/chromeos/drive/file_system_util.cc
@@ -114,7 +114,7 @@
        file_from = enumerator.Next()) {
     const base::FilePath file_to = directory_to.Append(file_from.BaseName());
     if (!file_util::PathExists(file_to))  // Do not overwrite existing files.
-      file_util::Move(file_from, file_to);
+      base::Move(file_from, file_to);
   }
 }
 
@@ -323,7 +323,7 @@
 
   // Move all files inside "persistent" to "files".
   MoveAllFilesFromDirectory(persistent_directory, cache_file_directory);
-  file_util::Delete(persistent_directory,  true /* recursive */);
+  base::Delete(persistent_directory,  true /* recursive */);
 
   // Move all files inside "tmp" to "files".
   MoveAllFilesFromDirectory(tmp_directory, cache_file_directory);
diff --git a/chrome/browser/chromeos/drive/file_system_util.h b/chrome/browser/chromeos/drive/file_system_util.h
index ffde7bc..e57c695 100644
--- a/chrome/browser/chromeos/drive/file_system_util.h
+++ b/chrome/browser/chromeos/drive/file_system_util.h
@@ -179,7 +179,7 @@
 // If |directory| is not a Drive path, it won't check the existence and just
 // runs |callback|.
 //
-// Must be called from UI/IO thread.
+// Must be called from UI thread.
 void EnsureDirectoryExists(Profile* profile,
                            const base::FilePath& directory,
                            const FileOperationCallback& callback);
diff --git a/chrome/browser/chromeos/drive/file_task_executor.cc b/chrome/browser/chromeos/drive/file_task_executor.cc
index 038ea5c..a42f71c 100644
--- a/chrome/browser/chromeos/drive/file_task_executor.cc
+++ b/chrome/browser/chromeos/drive/file_task_executor.cc
@@ -82,7 +82,7 @@
     return;
   }
 
-  google_apis::DriveServiceInterface* drive_service =
+  DriveServiceInterface* drive_service =
       integration_service->drive_service();
 
   // Send off a request for the drive service to authorize the apps for the
diff --git a/chrome/browser/chromeos/drive/fileapi_worker.cc b/chrome/browser/chromeos/drive/fileapi_worker.cc
new file mode 100644
index 0000000..e69a386
--- /dev/null
+++ b/chrome/browser/chromeos/drive/fileapi_worker.cc
@@ -0,0 +1,346 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/drive/fileapi_worker.h"
+
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/task_runner_util.h"
+#include "base/threading/sequenced_worker_pool.h"
+#include "chrome/browser/chromeos/drive/drive.pb.h"
+#include "chrome/browser/chromeos/drive/file_errors.h"
+#include "chrome/browser/chromeos/drive/file_system_interface.h"
+#include "chrome/browser/chromeos/drive/file_system_util.h"
+#include "content/public/browser/browser_thread.h"
+#include "webkit/common/fileapi/directory_entry.h"
+
+using content::BrowserThread;
+
+namespace drive {
+namespace internal {
+namespace {
+
+// Runs |callback| with the PlatformFileError converted from |error|.
+void RunStatusCallbackByFileError(
+    const FileApiWorker::StatusCallback& callback,
+    FileError error) {
+  callback.Run(FileErrorToPlatformError(error));
+}
+
+// Runs |callback| with arguments converted from |error| and |entry|.
+void RunGetFileInfoCallback(const FileApiWorker::GetFileInfoCallback& callback,
+                            FileError error,
+                            scoped_ptr<ResourceEntry> entry) {
+  if (error != FILE_ERROR_OK) {
+    callback.Run(FileErrorToPlatformError(error), base::PlatformFileInfo());
+    return;
+  }
+
+  DCHECK(entry);
+  base::PlatformFileInfo file_info;
+  util::ConvertResourceEntryToPlatformFileInfo(entry->file_info(), &file_info);
+  callback.Run(base::PLATFORM_FILE_OK, file_info);
+}
+
+// Runs |callback| with arguments converted from |error| and |resource_entries|.
+void RunReadDirectoryCallback(
+    const FileApiWorker::ReadDirectoryCallback& callback,
+    FileError error,
+    scoped_ptr<ResourceEntryVector> resource_entries) {
+  if (error != FILE_ERROR_OK) {
+    callback.Run(FileErrorToPlatformError(error),
+                 std::vector<fileapi::DirectoryEntry>(), false);
+    return;
+  }
+
+  DCHECK(resource_entries);
+
+  std::vector<fileapi::DirectoryEntry> entries;
+  // Convert drive files to File API's directory entry.
+  entries.reserve(resource_entries->size());
+  for (size_t i = 0; i < resource_entries->size(); ++i) {
+    const ResourceEntry& resource_entry = (*resource_entries)[i];
+    fileapi::DirectoryEntry entry;
+    entry.name = resource_entry.base_name();
+
+    const PlatformFileInfoProto& file_info = resource_entry.file_info();
+    entry.is_directory = file_info.is_directory();
+    entry.size = file_info.size();
+    entry.last_modified_time =
+        base::Time::FromInternalValue(file_info.last_modified());
+    entries.push_back(entry);
+  }
+
+  callback.Run(base::PLATFORM_FILE_OK, entries, false);
+}
+
+// Runs |callback| with arguments based on |error|, |local_path| and |entry|.
+void RunCreateSnapshotFileCallback(
+    const FileApiWorker::CreateSnapshotFileCallback& callback,
+    FileError error,
+    const base::FilePath& local_path,
+    scoped_ptr<ResourceEntry> entry) {
+  if (error != FILE_ERROR_OK) {
+    callback.Run(
+        FileErrorToPlatformError(error),
+        base::PlatformFileInfo(), base::FilePath(),
+        webkit_blob::ScopedFile::ScopeOutPolicy());
+    return;
+  }
+
+  DCHECK(entry);
+
+  // When reading file, last modified time specified in file info will be
+  // compared to the last modified time of the local version of the drive file.
+  // Since those two values don't generally match (last modification time on the
+  // drive server vs. last modification time of the local, downloaded file), so
+  // we have to opt out from this check. We do this by unsetting last_modified
+  // value in the file info passed to the CreateSnapshot caller.
+  base::PlatformFileInfo file_info;
+  util::ConvertResourceEntryToPlatformFileInfo(entry->file_info(), &file_info);
+  file_info.last_modified = base::Time();
+
+  // If the file is a hosted document, a temporary JSON file is created to
+  // represent the document. The JSON file is not cached and its lifetime
+  // is managed by ShareableFileReference.
+  webkit_blob::ScopedFile::ScopeOutPolicy scope_out_policy =
+      entry->file_specific_info().is_hosted_document() ?
+      webkit_blob::ScopedFile::DELETE_ON_SCOPE_OUT :
+      webkit_blob::ScopedFile::DONT_DELETE_ON_SCOPE_OUT;
+
+  callback.Run(base::PLATFORM_FILE_OK, file_info, local_path, scope_out_policy);
+}
+
+// Runs |callback| with |error| and |platform_file|.
+void RunOpenFileCallback(
+    const FileApiWorker::OpenFileCallback& callback,
+    base::PlatformFileError* error,
+    base::PlatformFile platform_file) {
+  callback.Run(*error, platform_file);
+}
+
+// Part of FileApiWorker::OpenFile(). Called after FileSystem::OpenFile().
+void OpenFileAfterFileSystemOpenFile(
+    int file_flags,
+    const FileApiWorker::OpenFileCallback& callback,
+    FileError error,
+    const base::FilePath& local_path) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  if (error != FILE_ERROR_OK) {
+    callback.Run(FileErrorToPlatformError(error),
+                 base::kInvalidPlatformFileValue);
+    return;
+  }
+
+  // Cache file prepared for modification is available. Open it locally.
+  base::PlatformFileError* result =
+      new base::PlatformFileError(base::PLATFORM_FILE_ERROR_FAILED);
+  bool posted = base::PostTaskAndReplyWithResult(
+      BrowserThread::GetBlockingPool(), FROM_HERE,
+      base::Bind(&base::CreatePlatformFile,
+                 local_path, file_flags, static_cast<bool*>(NULL), result),
+      base::Bind(&RunOpenFileCallback, callback, base::Owned(result)));
+  DCHECK(posted);
+}
+
+// Part of FileApiWorker::OpenFile(). Called after FileSystem::GetFileByPath().
+void OpenFileAfterGetFileByPath(int file_flags,
+                                const FileApiWorker::OpenFileCallback& callback,
+                                FileError error,
+                                const base::FilePath& local_path,
+                                scoped_ptr<ResourceEntry> entry) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  // Just redirect to OpenFileAfterFileSystemOpenFile() with ignoring |entry|.
+  OpenFileAfterFileSystemOpenFile(file_flags, callback, error, local_path);
+}
+
+// Emits debug log when FileSystem::CloseFile() is complete.
+void EmitDebugLogForCloseFile(const base::FilePath& local_path,
+                              FileError file_error) {
+  DVLOG(1) << "Closed: " << local_path.AsUTF8Unsafe() << ": " << file_error;
+}
+
+}  // namespace
+
+FileApiWorker::FileApiWorker(FileSystemInterface* file_system)
+    : file_system_(file_system),
+      weak_ptr_factory_(this) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(file_system);
+}
+
+FileApiWorker::~FileApiWorker() {
+}
+
+void FileApiWorker::GetFileInfo(const base::FilePath& file_path,
+                                const GetFileInfoCallback& callback) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  file_system_->GetResourceEntryByPath(
+      file_path,
+      base::Bind(&RunGetFileInfoCallback, callback));
+}
+
+void FileApiWorker::Copy(const base::FilePath& src_file_path,
+                         const base::FilePath& dest_file_path,
+                         const StatusCallback& callback) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  file_system_->Copy(src_file_path, dest_file_path,
+                     base::Bind(&RunStatusCallbackByFileError, callback));
+}
+
+void FileApiWorker::Move(const base::FilePath& src_file_path,
+                         const base::FilePath& dest_file_path,
+                         const StatusCallback& callback) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  file_system_->Move(src_file_path, dest_file_path,
+                     base::Bind(&RunStatusCallbackByFileError, callback));
+}
+
+void FileApiWorker::ReadDirectory(const base::FilePath& file_path,
+                                  const ReadDirectoryCallback& callback) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  file_system_->ReadDirectoryByPath(
+      file_path,
+      base::Bind(&RunReadDirectoryCallback, callback));
+}
+
+void FileApiWorker::Remove(const base::FilePath& file_path,
+                           bool is_recursive,
+                           const StatusCallback& callback) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  file_system_->Remove(file_path, is_recursive,
+                       base::Bind(&RunStatusCallbackByFileError, callback));
+}
+
+void FileApiWorker::CreateDirectory(const base::FilePath& file_path,
+                                    bool is_exclusive,
+                                    bool is_recursive,
+                                    const StatusCallback& callback) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  file_system_->CreateDirectory(
+      file_path, is_exclusive, is_recursive,
+      base::Bind(&RunStatusCallbackByFileError, callback));
+}
+
+void FileApiWorker::CreateFile(const base::FilePath& file_path,
+                               bool is_exclusive,
+                               const StatusCallback& callback) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  file_system_->CreateFile(file_path, is_exclusive,
+                           base::Bind(&RunStatusCallbackByFileError, callback));
+}
+
+void FileApiWorker::Truncate(const base::FilePath& file_path,
+                             int64 length,
+                             const StatusCallback& callback) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  file_system_->TruncateFile(
+      file_path, length,
+      base::Bind(&RunStatusCallbackByFileError, callback));
+}
+
+void FileApiWorker::CreateSnapshotFile(
+    const base::FilePath& file_path,
+    const CreateSnapshotFileCallback& callback) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  file_system_->GetFileByPath(
+      file_path,
+      base::Bind(&RunCreateSnapshotFileCallback, callback));
+}
+
+void FileApiWorker::OpenFile(const base::FilePath& file_path,
+                             int file_flags,
+                             const OpenFileCallback& callback) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  // TODO(zelidrag): Wire all other file open operations.
+  if (file_flags & base::PLATFORM_FILE_DELETE_ON_CLOSE) {
+    NOTIMPLEMENTED() << "File create/write operations not yet supported "
+                     << file_path.value();
+    callback.Run(base::PLATFORM_FILE_ERROR_FAILED,
+                 base::kInvalidPlatformFileValue);
+    return;
+  }
+
+  // TODO(hidehiko): The opening logic should be moved to FileSystem.
+  //   crbug.com/256583.
+  if (file_flags & (base::PLATFORM_FILE_OPEN |
+                    base::PLATFORM_FILE_OPEN_ALWAYS |
+                    base::PLATFORM_FILE_OPEN_TRUNCATED)) {
+    if (file_flags & (base::PLATFORM_FILE_OPEN_TRUNCATED |
+                      base::PLATFORM_FILE_OPEN_ALWAYS |
+                      base::PLATFORM_FILE_WRITE |
+                      base::PLATFORM_FILE_EXCLUSIVE_WRITE)) {
+      // Open existing file for writing.
+      file_system_->OpenFile(
+          file_path,
+          base::Bind(&OpenFileAfterFileSystemOpenFile, file_flags, callback));
+    } else {
+      // Read-only file open.
+      file_system_->GetFileByPath(
+          file_path,
+          base::Bind(&OpenFileAfterGetFileByPath, file_flags, callback));
+    }
+  } else if (file_flags & (base::PLATFORM_FILE_CREATE |
+                           base::PLATFORM_FILE_CREATE_ALWAYS)) {
+    // Create a new file.
+    file_system_->CreateFile(
+        file_path,
+        file_flags & base::PLATFORM_FILE_EXCLUSIVE_WRITE,
+        base::Bind(&FileApiWorker::OpenFileAfterCreateFile,
+                   weak_ptr_factory_.GetWeakPtr(),
+                   file_path, file_flags, callback));
+  } else {
+    NOTREACHED() << "Unhandled file flags combination " << file_flags;
+    callback.Run(base::PLATFORM_FILE_ERROR_FAILED,
+                 base::kInvalidPlatformFileValue);
+    return;
+  }
+}
+
+void FileApiWorker::CloseFile(const base::FilePath& file_path) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  file_system_->CloseFile(file_path,
+                          base::Bind(&EmitDebugLogForCloseFile, file_path));
+}
+
+void FileApiWorker::TouchFile(const base::FilePath& file_path,
+                              const base::Time& last_access_time,
+                              const base::Time& last_modified_time,
+                              const StatusCallback& callback) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  file_system_->TouchFile(file_path, last_access_time, last_modified_time,
+                          base::Bind(&RunStatusCallbackByFileError, callback));
+
+}
+
+void FileApiWorker::OpenFileAfterCreateFile(const base::FilePath& file_path,
+                                            int file_flags,
+                                            const OpenFileCallback& callback,
+                                            FileError error) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  if (error != FILE_ERROR_OK &&
+      (error != FILE_ERROR_EXISTS ||
+       (file_flags & base::PLATFORM_FILE_CREATE))) {
+    callback.Run(FileErrorToPlatformError(error),
+                 base::kInvalidPlatformFileValue);
+    return;
+  }
+
+  // If we are trying to always create an existing file, then
+  // if it really exists open it as truncated.
+  file_flags &=
+      ~(base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_CREATE_ALWAYS);
+  file_flags |= base::PLATFORM_FILE_OPEN_TRUNCATED;
+
+  // Open created (or existing) file for writing.
+  file_system_->OpenFile(
+      file_path,
+      base::Bind(&OpenFileAfterFileSystemOpenFile, file_flags, callback));
+}
+
+}  // namespace internal
+}  // namespace drive
diff --git a/chrome/browser/chromeos/drive/fileapi_worker.h b/chrome/browser/chromeos/drive/fileapi_worker.h
new file mode 100644
index 0000000..caac16c
--- /dev/null
+++ b/chrome/browser/chromeos/drive/fileapi_worker.h
@@ -0,0 +1,149 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_DRIVE_FILEAPI_WORKER_H_
+#define CHROME_BROWSER_CHROMEOS_DRIVE_FILEAPI_WORKER_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/callback_forward.h"
+#include "base/memory/weak_ptr.h"
+#include "base/platform_file.h"
+#include "chrome/browser/chromeos/drive/file_errors.h"
+#include "webkit/common/blob/scoped_file.h"
+
+namespace base {
+class FilePath;
+}  // namespace base
+
+namespace fileapi {
+struct DirectoryEntry;
+}  // namespace fileapi
+
+namespace drive {
+
+class FileSystemInterface;
+
+namespace internal {
+
+// This provides the core implementation of the methods for fileapi.
+// This class lives on UI thread. Note that most method invocation of fileapi
+// is done on IO thread. The gap is filled by FileSystemProxy.
+class FileApiWorker {
+ public:
+  typedef base::Callback<
+      void(base::PlatformFileError result)> StatusCallback;
+  typedef base::Callback<
+      void(base::PlatformFileError result,
+           const base::PlatformFileInfo& file_info)> GetFileInfoCallback;
+  typedef base::Callback<
+      void(base::PlatformFileError result,
+           const std::vector<fileapi::DirectoryEntry>& file_list,
+           bool has_more)> ReadDirectoryCallback;
+  typedef base::Callback<
+      void(base::PlatformFileError result,
+           const base::PlatformFileInfo& file_info,
+           const base::FilePath& snapshot_file_path,
+           webkit_blob::ScopedFile::ScopeOutPolicy scope_out_policy)>
+      CreateSnapshotFileCallback;
+  typedef base::Callback<
+      void(base::PlatformFileError result,
+           base::PlatformFile platform_file)> OpenFileCallback;
+
+  // |file_system| must not be NULL.
+  explicit FileApiWorker(FileSystemInterface* file_system);
+  ~FileApiWorker();
+
+  FileSystemInterface* file_system() { return file_system_; }
+
+  // Returns the metadata info of the file at |file_path|.
+  // Called from FileSystemProxy::GetFileInfo().
+  void GetFileInfo(const base::FilePath& file_path,
+                   const GetFileInfoCallback& callback);
+
+  // Copies a file from |src_file_path| to |dest_file_path|.
+  // Called from FileSystemProxy::Copy().
+  void Copy(const base::FilePath& src_file_path,
+            const base::FilePath& dest_file_path,
+            const StatusCallback& callback);
+
+  // Moves a file from |src_file_path| to |dest_file_path|.
+  // Called from FileSystemProxy::Move().
+  void Move(const base::FilePath& src_file_path,
+            const base::FilePath& dest_file_path,
+            const StatusCallback& callback);
+
+  // Reads the contents of the directory at |file_path|.
+  // Called from FileSystemProxy::ReadDirectory().
+  void ReadDirectory(const base::FilePath& file_path,
+                     const ReadDirectoryCallback& callback);
+
+  // Removes a file at |file_path|. Called from FileSystemProxy::Remove().
+  void Remove(const base::FilePath& file_path,
+              bool is_recursive,
+              const StatusCallback& callback);
+
+  // Creates a new directory at |file_path|.
+  // Called from FileSystemProxy::CreateDirectory().
+  void CreateDirectory(const base::FilePath& file_path,
+                       bool is_exclusive,
+                       bool is_recursive,
+                       const StatusCallback& callback);
+
+  // Creates a new file at |file_path|.
+  // Called from FileSystemProxy::CreateFile().
+  void CreateFile(const base::FilePath& file_path,
+                  bool is_exclusive,
+                  const StatusCallback& callback);
+
+  // Truncates the file at |file_path| to |length| bytes.
+  // Called from FileSystemProxy::Truncate().
+  void Truncate(const base::FilePath& file_path,
+                int64 length,
+                const StatusCallback& callback);
+
+  // Creates a snapshot for the file at |file_path|.
+  // Called from FileSystemProxy::CreateSnapshotFile().
+  void CreateSnapshotFile(const base::FilePath& file_path,
+                          const CreateSnapshotFileCallback& callback);
+
+  // Opens the file at |file_path| with options |file_flags|.
+  // Called from FileSystemProxy::OpenFile.
+  void OpenFile(const base::FilePath& file_path,
+                int file_flags,
+                const OpenFileCallback& callback);
+
+  // Closes the file at |file_path|.
+  // Called from FileSystemProxy::NotifyCloseFile and
+  // FileSystemProxy::CloseWRitableSnapshotFile.
+  void CloseFile(const base::FilePath& file_path);
+
+  // Changes timestamp of the file at |file_path| to |last_access_time| and
+  // |last_modified_time|. Called from FileSystemProxy::TouchFile().
+  void TouchFile(const base::FilePath& file_path,
+                 const base::Time& last_access_time,
+                 const base::Time& last_modified_time,
+                 const StatusCallback& callback);
+
+ private:
+  // Part of OpenFile(). Called after FileSystem::CreateFile().
+  void OpenFileAfterCreateFile(const base::FilePath& file_path,
+                               int file_flags,
+                               const OpenFileCallback& callback,
+                               FileError error);
+
+  FileSystemInterface* file_system_;
+
+  // Note: This should remain the last member so it'll be destroyed and
+  // invalidate the weak pointers before any other members are destroyed.
+  base::WeakPtrFactory<FileApiWorker> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(FileApiWorker);
+};
+
+}  // namespace internal
+}  // namespace drive
+
+#endif  // CHROME_BROWSER_CHROMEOS_DRIVE_FILEAPI_WORKER_H_
diff --git a/chrome/browser/chromeos/drive/job_queue.cc b/chrome/browser/chromeos/drive/job_queue.cc
index 40a9ed6..a142556 100644
--- a/chrome/browser/chromeos/drive/job_queue.cc
+++ b/chrome/browser/chromeos/drive/job_queue.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/chromeos/drive/job_queue.h"
 
+#include <algorithm>
+
 #include "base/logging.h"
 #include "base/strings/stringprintf.h"
 
@@ -37,6 +39,12 @@
   return false;
 }
 
+void JobQueue::GetQueuedJobs(int priority, std::vector<JobID>* jobs) const {
+  DCHECK_LT(priority, static_cast<int>(queue_.size()));
+
+  jobs->assign(queue_[priority].begin(), queue_[priority].end());
+}
+
 void JobQueue::Push(JobID id, int priority) {
   DCHECK_LT(priority, static_cast<int>(queue_.size()));
 
@@ -64,4 +72,15 @@
   return count;
 }
 
+void JobQueue::Remove(JobID id) {
+  for (size_t i = 0; i < queue_.size(); ++i) {
+    std::deque<JobID>::iterator iter =
+        std::find(queue_[i].begin(), queue_[i].end(), id);
+    if (iter != queue_[i].end()) {
+      queue_[i].erase(iter);
+      break;
+    }
+  }
+}
+
 }  // namespace drive
diff --git a/chrome/browser/chromeos/drive/job_queue.h b/chrome/browser/chromeos/drive/job_queue.h
index 0659ce9..20d8969 100644
--- a/chrome/browser/chromeos/drive/job_queue.h
+++ b/chrome/browser/chromeos/drive/job_queue.h
@@ -36,6 +36,9 @@
   // priority 1 in the queue is picked.
   bool PopForRun(int accepted_priority, JobID* id);
 
+  // Gets queued jobs with the given priority.
+  void GetQueuedJobs(int priority, std::vector<JobID>* jobs) const;
+
   // Marks a running job |id| as finished running. This decreases the count
   // of running parallel jobs and makes room for other jobs to be popped.
   void MarkFinished(JobID id);
@@ -46,6 +49,9 @@
   // Gets the total number of jobs in the queue.
   size_t GetNumberOfJobs() const;
 
+  // Removes the job from the queue.
+  void Remove(JobID id);
+
  private:
   size_t num_max_concurrent_jobs_;
   std::vector<std::deque<JobID> > queue_;
diff --git a/chrome/browser/chromeos/drive/job_queue_unittest.cc b/chrome/browser/chromeos/drive/job_queue_unittest.cc
index d02a31d..08d2ced 100644
--- a/chrome/browser/chromeos/drive/job_queue_unittest.cc
+++ b/chrome/browser/chromeos/drive/job_queue_unittest.cc
@@ -66,4 +66,39 @@
   EXPECT_EQ(105, id);
 }
 
+TEST(JobQueueTest, JobQueueRemove) {
+  const int kNumMaxConcurrentJobs = 3;
+  const int kNumPriorityLevels = 2;
+  enum {HIGH_PRIORITY, LOW_PRIORITY};
+
+  // Create a queue. Number of jobs are initially zero.
+  JobQueue queue(kNumMaxConcurrentJobs, kNumPriorityLevels);
+  EXPECT_EQ(0U, queue.GetNumberOfJobs());
+
+  // Push 4 jobs.
+  queue.Push(101, LOW_PRIORITY);
+  queue.Push(102, HIGH_PRIORITY);
+  queue.Push(103, LOW_PRIORITY);
+  queue.Push(104, HIGH_PRIORITY);
+  EXPECT_EQ(4U, queue.GetNumberOfJobs());
+
+  // Remove 2.
+  queue.Remove(101);
+  queue.Remove(104);
+  EXPECT_EQ(2U, queue.GetNumberOfJobs());
+
+  // Pop the 2 jobs.
+  JobID id;
+  EXPECT_TRUE(queue.PopForRun(LOW_PRIORITY, &id));
+  EXPECT_EQ(102, id);
+  EXPECT_TRUE(queue.PopForRun(LOW_PRIORITY, &id));
+  EXPECT_EQ(103, id);
+  queue.MarkFinished(102);
+  queue.MarkFinished(103);
+
+  // 0 job left.
+  EXPECT_EQ(0U, queue.GetNumberOfJobs());
+  EXPECT_FALSE(queue.PopForRun(LOW_PRIORITY, &id));
+}
+
 }  // namespace drive
diff --git a/chrome/browser/chromeos/drive/job_scheduler.cc b/chrome/browser/chromeos/drive/job_scheduler.cc
index 4de6477..621021e 100644
--- a/chrome/browser/chromeos/drive/job_scheduler.cc
+++ b/chrome/browser/chromeos/drive/job_scheduler.cc
@@ -4,8 +4,6 @@
 
 #include "chrome/browser/chromeos/drive/job_scheduler.h"
 
-#include <math.h>
-
 #include "base/message_loop.h"
 #include "base/prefs/pref_service.h"
 #include "base/rand_util.h"
@@ -30,20 +28,18 @@
 // Parameter struct for RunUploadNewFile.
 struct UploadNewFileParams {
   std::string parent_resource_id;
-  base::FilePath drive_file_path;
   base::FilePath local_file_path;
   std::string title;
   std::string content_type;
-  google_apis::UploadCompletionCallback callback;
+  UploadCompletionCallback callback;
   google_apis::ProgressCallback progress_callback;
 };
 
 // Helper function to work around the arity limitation of base::Bind.
 google_apis::CancelCallback RunUploadNewFile(
-    google_apis::DriveUploaderInterface* uploader,
+    DriveUploaderInterface* uploader,
     const UploadNewFileParams& params) {
   return uploader->UploadNewFile(params.parent_resource_id,
-                                 params.drive_file_path,
                                  params.local_file_path,
                                  params.title,
                                  params.content_type,
@@ -54,20 +50,18 @@
 // Parameter struct for RunUploadExistingFile.
 struct UploadExistingFileParams {
   std::string resource_id;
-  base::FilePath drive_file_path;
   base::FilePath local_file_path;
   std::string content_type;
   std::string etag;
-  google_apis::UploadCompletionCallback callback;
+  UploadCompletionCallback callback;
   google_apis::ProgressCallback progress_callback;
 };
 
 // Helper function to work around the arity limitation of base::Bind.
 google_apis::CancelCallback RunUploadExistingFile(
-    google_apis::DriveUploaderInterface* uploader,
+    DriveUploaderInterface* uploader,
     const UploadExistingFileParams& params) {
   return uploader->UploadExistingFile(params.resource_id,
-                                      params.drive_file_path,
                                       params.local_file_path,
                                       params.content_type,
                                       params.etag,
@@ -78,25 +72,51 @@
 // Parameter struct for RunResumeUploadFile.
 struct ResumeUploadFileParams {
   GURL upload_location;
-  base::FilePath drive_file_path;
   base::FilePath local_file_path;
   std::string content_type;
-  google_apis::UploadCompletionCallback callback;
+  UploadCompletionCallback callback;
   google_apis::ProgressCallback progress_callback;
 };
 
 // Helper function to adjust the return type.
 google_apis::CancelCallback RunResumeUploadFile(
-    google_apis::DriveUploaderInterface* uploader,
+    DriveUploaderInterface* uploader,
     const ResumeUploadFileParams& params) {
   return uploader->ResumeUploadFile(params.upload_location,
-                                    params.drive_file_path,
                                     params.local_file_path,
                                     params.content_type,
                                     params.callback,
                                     params.progress_callback);
 }
 
+// Helper for CreateErrorRunCallback.
+template<typename P1>
+struct CreateErrorRunCallbackHelper {
+  static void Run(
+      const base::Callback<void(google_apis::GDataErrorCode, P1)>& callback,
+      google_apis::GDataErrorCode error) {
+    callback.Run(error, P1());
+  }
+};
+
+template<typename P1>
+struct CreateErrorRunCallbackHelper<const P1&> {
+  static void Run(
+      const base::Callback<void(google_apis::GDataErrorCode,
+                                const P1&)>& callback,
+      google_apis::GDataErrorCode error) {
+    callback.Run(error, P1());
+  }
+};
+
+// Returns a callback with the tail parameter bound to its default value.
+// In other words, returned_callback.Run(error) runs callback.Run(error, T()).
+template<typename P1>
+base::Callback<void(google_apis::GDataErrorCode)> CreateErrorRunCallback(
+    const base::Callback<void(google_apis::GDataErrorCode, P1)>& callback) {
+  return base::Bind(&CreateErrorRunCallbackHelper<P1>::Run, callback);
+}
+
 }  // namespace
 
 const int JobScheduler::kMaxJobCount[] = {
@@ -123,11 +143,12 @@
 
 JobScheduler::JobScheduler(
     Profile* profile,
-    google_apis::DriveServiceInterface* drive_service)
+    DriveServiceInterface* drive_service,
+    base::SequencedTaskRunner* blocking_task_runner)
     : throttle_count_(0),
       disable_throttling_(false),
       drive_service_(drive_service),
-      uploader_(new google_apis::DriveUploader(drive_service)),
+      uploader_(new DriveUploader(drive_service, blocking_task_runner)),
       profile_(profile),
       weak_ptr_factory_(this) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -171,9 +192,15 @@
 
   JobEntry* job = job_map_.Lookup(job_id);
   if (job) {
-    // TODO(kinaba): crbug.com/251116 Support cancelling jobs not yet started.
-    if (!job->cancel_callback.is_null())
-      job->cancel_callback.Run();
+    if (job->job_info.state == STATE_RUNNING) {
+      // If the job is running an HTTP request, cancel it via |cancel_callback|
+      // returned from the request, and wait for termination in the normal
+      // callback handler, OnJobDone.
+      if (!job->cancel_callback.is_null())
+        job->cancel_callback.Run();
+    } else {
+      AbortNotRunningJob(job, google_apis::GDATA_CANCELLED);
+    }
   }
 }
 
@@ -193,12 +220,13 @@
 
   JobEntry* new_job = CreateNewJob(TYPE_GET_ABOUT_RESOURCE);
   new_job->task = base::Bind(
-      &google_apis::DriveServiceInterface::GetAboutResource,
+      &DriveServiceInterface::GetAboutResource,
       base::Unretained(drive_service_),
       base::Bind(&JobScheduler::OnGetAboutResourceJobDone,
                  weak_ptr_factory_.GetWeakPtr(),
                  new_job->job_info.job_id,
                  callback));
+  new_job->abort_callback = CreateErrorRunCallback(callback);
   StartJob(new_job);
 }
 
@@ -209,12 +237,13 @@
 
   JobEntry* new_job = CreateNewJob(TYPE_GET_APP_LIST);
   new_job->task = base::Bind(
-      &google_apis::DriveServiceInterface::GetAppList,
+      &DriveServiceInterface::GetAppList,
       base::Unretained(drive_service_),
       base::Bind(&JobScheduler::OnGetAppListJobDone,
                  weak_ptr_factory_.GetWeakPtr(),
                  new_job->job_info.job_id,
                  callback));
+  new_job->abort_callback = CreateErrorRunCallback(callback);
   StartJob(new_job);
 }
 
@@ -225,12 +254,13 @@
 
   JobEntry* new_job = CreateNewJob(TYPE_GET_ALL_RESOURCE_LIST);
   new_job->task = base::Bind(
-      &google_apis::DriveServiceInterface::GetAllResourceList,
+      &DriveServiceInterface::GetAllResourceList,
       base::Unretained(drive_service_),
       base::Bind(&JobScheduler::OnGetResourceListJobDone,
                  weak_ptr_factory_.GetWeakPtr(),
                  new_job->job_info.job_id,
                  callback));
+  new_job->abort_callback = CreateErrorRunCallback(callback);
   StartJob(new_job);
 }
 
@@ -243,13 +273,14 @@
   JobEntry* new_job = CreateNewJob(
       TYPE_GET_RESOURCE_LIST_IN_DIRECTORY);
   new_job->task = base::Bind(
-      &google_apis::DriveServiceInterface::GetResourceListInDirectory,
+      &DriveServiceInterface::GetResourceListInDirectory,
       base::Unretained(drive_service_),
       directory_resource_id,
       base::Bind(&JobScheduler::OnGetResourceListJobDone,
                  weak_ptr_factory_.GetWeakPtr(),
                  new_job->job_info.job_id,
                  callback));
+  new_job->abort_callback = CreateErrorRunCallback(callback);
   StartJob(new_job);
 }
 
@@ -261,13 +292,14 @@
 
   JobEntry* new_job = CreateNewJob(TYPE_SEARCH);
   new_job->task = base::Bind(
-      &google_apis::DriveServiceInterface::Search,
+      &DriveServiceInterface::Search,
       base::Unretained(drive_service_),
       search_query,
       base::Bind(&JobScheduler::OnGetResourceListJobDone,
                  weak_ptr_factory_.GetWeakPtr(),
                  new_job->job_info.job_id,
                  callback));
+  new_job->abort_callback = CreateErrorRunCallback(callback);
   StartJob(new_job);
 }
 
@@ -279,13 +311,14 @@
 
   JobEntry* new_job = CreateNewJob(TYPE_GET_CHANGE_LIST);
   new_job->task = base::Bind(
-      &google_apis::DriveServiceInterface::GetChangeList,
+      &DriveServiceInterface::GetChangeList,
       base::Unretained(drive_service_),
       start_changestamp,
       base::Bind(&JobScheduler::OnGetResourceListJobDone,
                  weak_ptr_factory_.GetWeakPtr(),
                  new_job->job_info.job_id,
                  callback));
+  new_job->abort_callback = CreateErrorRunCallback(callback);
   StartJob(new_job);
 }
 
@@ -297,13 +330,14 @@
 
   JobEntry* new_job = CreateNewJob(TYPE_CONTINUE_GET_RESOURCE_LIST);
   new_job->task = base::Bind(
-      &google_apis::DriveServiceInterface::ContinueGetResourceList,
+      &DriveServiceInterface::ContinueGetResourceList,
       base::Unretained(drive_service_),
       next_url,
       base::Bind(&JobScheduler::OnGetResourceListJobDone,
                  weak_ptr_factory_.GetWeakPtr(),
                  new_job->job_info.job_id,
                  callback));
+  new_job->abort_callback = CreateErrorRunCallback(callback);
   StartJob(new_job);
 }
 
@@ -317,13 +351,14 @@
   JobEntry* new_job = CreateNewJob(TYPE_GET_RESOURCE_ENTRY);
   new_job->context = context;
   new_job->task = base::Bind(
-      &google_apis::DriveServiceInterface::GetResourceEntry,
+      &DriveServiceInterface::GetResourceEntry,
       base::Unretained(drive_service_),
       resource_id,
       base::Bind(&JobScheduler::OnGetResourceEntryJobDone,
                  weak_ptr_factory_.GetWeakPtr(),
                  new_job->job_info.job_id,
                  callback));
+  new_job->abort_callback = CreateErrorRunCallback(callback);
   StartJob(new_job);
 }
 
@@ -335,7 +370,7 @@
 
   JobEntry* new_job = CreateNewJob(TYPE_DELETE_RESOURCE);
   new_job->task = base::Bind(
-      &google_apis::DriveServiceInterface::DeleteResource,
+      &DriveServiceInterface::DeleteResource,
       base::Unretained(drive_service_),
       resource_id,
       "",  // etag
@@ -343,6 +378,7 @@
                  weak_ptr_factory_.GetWeakPtr(),
                  new_job->job_info.job_id,
                  callback));
+  new_job->abort_callback = callback;
   StartJob(new_job);
 }
 
@@ -356,7 +392,7 @@
 
   JobEntry* new_job = CreateNewJob(TYPE_COPY_RESOURCE);
   new_job->task = base::Bind(
-      &google_apis::DriveServiceInterface::CopyResource,
+      &DriveServiceInterface::CopyResource,
       base::Unretained(drive_service_),
       resource_id,
       parent_resource_id,
@@ -365,6 +401,7 @@
                  weak_ptr_factory_.GetWeakPtr(),
                  new_job->job_info.job_id,
                  callback));
+  new_job->abort_callback = CreateErrorRunCallback(callback);
   StartJob(new_job);
 }
 
@@ -377,7 +414,7 @@
 
   JobEntry* new_job = CreateNewJob(TYPE_COPY_HOSTED_DOCUMENT);
   new_job->task = base::Bind(
-      &google_apis::DriveServiceInterface::CopyHostedDocument,
+      &DriveServiceInterface::CopyHostedDocument,
       base::Unretained(drive_service_),
       resource_id,
       new_name,
@@ -385,6 +422,7 @@
                  weak_ptr_factory_.GetWeakPtr(),
                  new_job->job_info.job_id,
                  callback));
+  new_job->abort_callback = CreateErrorRunCallback(callback);
   StartJob(new_job);
 }
 
@@ -397,7 +435,7 @@
 
   JobEntry* new_job = CreateNewJob(TYPE_RENAME_RESOURCE);
   new_job->task = base::Bind(
-      &google_apis::DriveServiceInterface::RenameResource,
+      &DriveServiceInterface::RenameResource,
       base::Unretained(drive_service_),
       resource_id,
       new_name,
@@ -405,6 +443,7 @@
                  weak_ptr_factory_.GetWeakPtr(),
                  new_job->job_info.job_id,
                  callback));
+  new_job->abort_callback = callback;
   StartJob(new_job);
 }
 
@@ -418,7 +457,7 @@
 
   JobEntry* new_job = CreateNewJob(TYPE_TOUCH_RESOURCE);
   new_job->task = base::Bind(
-      &google_apis::DriveServiceInterface::TouchResource,
+      &DriveServiceInterface::TouchResource,
       base::Unretained(drive_service_),
       resource_id,
       modified_date,
@@ -427,6 +466,7 @@
                  weak_ptr_factory_.GetWeakPtr(),
                  new_job->job_info.job_id,
                  callback));
+  new_job->abort_callback = CreateErrorRunCallback(callback);
   StartJob(new_job);
 }
 
@@ -439,7 +479,7 @@
 
   JobEntry* new_job = CreateNewJob(TYPE_ADD_RESOURCE_TO_DIRECTORY);
   new_job->task = base::Bind(
-      &google_apis::DriveServiceInterface::AddResourceToDirectory,
+      &DriveServiceInterface::AddResourceToDirectory,
       base::Unretained(drive_service_),
       parent_resource_id,
       resource_id,
@@ -447,6 +487,7 @@
                  weak_ptr_factory_.GetWeakPtr(),
                  new_job->job_info.job_id,
                  callback));
+  new_job->abort_callback = callback;
   StartJob(new_job);
 }
 
@@ -458,7 +499,7 @@
 
   JobEntry* new_job = CreateNewJob(TYPE_REMOVE_RESOURCE_FROM_DIRECTORY);
   new_job->task = base::Bind(
-      &google_apis::DriveServiceInterface::RemoveResourceFromDirectory,
+      &DriveServiceInterface::RemoveResourceFromDirectory,
       base::Unretained(drive_service_),
       parent_resource_id,
       resource_id,
@@ -466,6 +507,7 @@
                  weak_ptr_factory_.GetWeakPtr(),
                  new_job->job_info.job_id,
                  callback));
+  new_job->abort_callback = callback;
   StartJob(new_job);
 }
 
@@ -477,7 +519,7 @@
 
   JobEntry* new_job = CreateNewJob(TYPE_ADD_NEW_DIRECTORY);
   new_job->task = base::Bind(
-      &google_apis::DriveServiceInterface::AddNewDirectory,
+      &DriveServiceInterface::AddNewDirectory,
       base::Unretained(drive_service_),
       parent_resource_id,
       directory_name,
@@ -485,13 +527,14 @@
                  weak_ptr_factory_.GetWeakPtr(),
                  new_job->job_info.job_id,
                  callback));
+  new_job->abort_callback = CreateErrorRunCallback(callback);
   StartJob(new_job);
 }
 
 JobID JobScheduler::DownloadFile(
     const base::FilePath& virtual_path,
     const base::FilePath& local_cache_path,
-    const GURL& download_url,
+    const std::string& resource_id,
     const ClientContext& context,
     const google_apis::DownloadActionCallback& download_action_callback,
     const google_apis::GetContentCallback& get_content_callback) {
@@ -501,11 +544,10 @@
   new_job->job_info.file_path = virtual_path;
   new_job->context = context;
   new_job->task = base::Bind(
-      &google_apis::DriveServiceInterface::DownloadFile,
+      &DriveServiceInterface::DownloadFile,
       base::Unretained(drive_service_),
-      virtual_path,
       local_cache_path,
-      download_url,
+      resource_id,
       base::Bind(&JobScheduler::OnDownloadActionJobDone,
                  weak_ptr_factory_.GetWeakPtr(),
                  new_job->job_info.job_id,
@@ -514,7 +556,7 @@
       base::Bind(&JobScheduler::UpdateProgress,
                  weak_ptr_factory_.GetWeakPtr(),
                  new_job->job_info.job_id));
-
+  new_job->abort_callback = CreateErrorRunCallback(download_action_callback);
   StartJob(new_job);
   return new_job->job_info.job_id;
 }
@@ -535,13 +577,11 @@
 
   UploadNewFileParams params;
   params.parent_resource_id = parent_resource_id;
-  params.drive_file_path = drive_file_path;
   params.local_file_path = local_file_path;
   params.title = title;
   params.content_type = content_type;
 
   ResumeUploadParams resume_params;
-  resume_params.drive_file_path = params.drive_file_path;
   resume_params.local_file_path = params.local_file_path;
   resume_params.content_type = params.content_type;
 
@@ -554,7 +594,7 @@
                                         weak_ptr_factory_.GetWeakPtr(),
                                         new_job->job_info.job_id);
   new_job->task = base::Bind(&RunUploadNewFile, uploader_.get(), params);
-
+  new_job->abort_callback = CreateErrorRunCallback(callback);
   StartJob(new_job);
 }
 
@@ -574,13 +614,11 @@
 
   UploadExistingFileParams params;
   params.resource_id = resource_id;
-  params.drive_file_path = drive_file_path;
   params.local_file_path = local_file_path;
   params.content_type = content_type;
   params.etag = etag;
 
   ResumeUploadParams resume_params;
-  resume_params.drive_file_path = params.drive_file_path;
   resume_params.local_file_path = params.local_file_path;
   resume_params.content_type = params.content_type;
 
@@ -593,7 +631,7 @@
                                         weak_ptr_factory_.GetWeakPtr(),
                                         new_job->job_info.job_id);
   new_job->task = base::Bind(&RunUploadExistingFile, uploader_.get(), params);
-
+  new_job->abort_callback = CreateErrorRunCallback(callback);
   StartJob(new_job);
 }
 
@@ -614,13 +652,11 @@
 
   UploadNewFileParams params;
   params.parent_resource_id = parent_resource_id;
-  params.drive_file_path = drive_file_path;
   params.local_file_path = kDevNull;  // Upload an empty file.
   params.title = title;
   params.content_type = content_type;
 
   ResumeUploadParams resume_params;
-  resume_params.drive_file_path = params.drive_file_path;
   resume_params.local_file_path = params.local_file_path;
   resume_params.content_type = params.content_type;
 
@@ -632,7 +668,7 @@
   params.progress_callback = google_apis::ProgressCallback();
 
   new_job->task = base::Bind(&RunUploadNewFile, uploader_.get(), params);
-
+  new_job->abort_callback = CreateErrorRunCallback(callback);
   StartJob(new_job);
 }
 
@@ -667,12 +703,24 @@
 void JobScheduler::DoJobLoop(QueueType queue_type) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-  JobID job_id = -1;
-  if (!queue_[queue_type]->PopForRun(GetCurrentAcceptedPriority(queue_type),
-                                     &job_id)) {
-    return;
+  const int accepted_priority = GetCurrentAcceptedPriority(queue_type);
+
+  // Abort all USER_INITAITED jobs when not accepted.
+  if (accepted_priority < USER_INITIATED) {
+    std::vector<JobID> jobs;
+    queue_[queue_type]->GetQueuedJobs(USER_INITIATED, &jobs);
+    for (size_t i = 0; i < jobs.size(); ++i) {
+      JobEntry* job = job_map_.Lookup(jobs[i]);
+      DCHECK(job);
+      AbortNotRunningJob(job, google_apis::GDATA_NO_CONNECTION);
+    }
   }
 
+  // Run the job with the highest priority in the queue.
+  JobID job_id = -1;
+  if (!queue_[queue_type]->PopForRun(accepted_priority, &job_id))
+    return;
+
   JobEntry* entry = job_map_.Lookup(job_id);
   DCHECK(entry);
 
@@ -693,8 +741,7 @@
 
   const int kNoJobShouldRun = -1;
 
-  // Should stop if the gdata feature was disabled while running the fetch
-  // loop.
+  // Should stop if Drive was disabled while running the fetch loop.
   if (profile_->GetPrefs()->GetBoolean(prefs::kDisableDrive))
     return kNoJobShouldRun;
 
@@ -724,8 +771,9 @@
   if (disable_throttling_) {
     delay = base::TimeDelta::FromSeconds(0);
   } else {
+    // Exponential backoff: https://developers.google.com/drive/handle-errors.
     delay =
-      base::TimeDelta::FromSeconds(pow(2, throttle_count_ - 1)) +
+      base::TimeDelta::FromSeconds(1 << (throttle_count_ - 1)) +
       base::TimeDelta::FromMilliseconds(base::RandInt(0, 1000));
   }
   VLOG(1) << "Throttling for " << delay.InMillisecondsF();
@@ -785,7 +833,7 @@
   } else {
     NotifyJobDone(*job_info, error);
     // The job has finished, no retry will happen in the scheduler. Now we can
-    // remove the job info from the map. This is the only place of the removal.
+    // remove the job info from the map.
     job_map_.Remove(job_id);
 
     ResetThrottleAndContinueJobLoop(queue_type);
@@ -884,7 +932,6 @@
 
     ResumeUploadFileParams params;
     params.upload_location = upload_location;
-    params.drive_file_path = resume_params.drive_file_path;
     params.local_file_path = resume_params.local_file_path;
     params.content_type = resume_params.content_type;
     params.callback = base::Bind(&JobScheduler::OnUploadCompletionJobDone,
@@ -915,14 +962,11 @@
     net::NetworkChangeNotifier::ConnectionType type) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-  // Resume the job loop if the network is back online. Note that we don't
-  // need to check the type of the network as it will be checked in
-  // ShouldStopJobLoop() as soon as the loop is resumed.
-  if (!net::NetworkChangeNotifier::IsOffline()) {
-    for (int i = METADATA_QUEUE; i < NUM_QUEUES; ++i) {
-      DoJobLoop(static_cast<QueueType>(i));
-    }
-  }
+  // Resume the job loop.
+  // Note that we don't need to check the network connection status as it will
+  // be checked in GetCurrentAcceptedPriority().
+  for (int i = METADATA_QUEUE; i < NUM_QUEUES; ++i)
+    DoJobLoop(static_cast<QueueType>(i));
 }
 
 JobScheduler::QueueType JobScheduler::GetJobQueueType(JobType type) {
@@ -955,6 +999,26 @@
   return FILE_QUEUE;
 }
 
+void JobScheduler::AbortNotRunningJob(JobEntry* job,
+                                      google_apis::GDataErrorCode error) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  const base::TimeDelta elapsed = base::Time::Now() - job->job_info.start_time;
+  const QueueType queue_type = GetJobQueueType(job->job_info.job_type);
+  util::Log("Job aborted: %s => %s (elapsed time: %sms) - %s",
+            job->job_info.ToString().c_str(),
+            GDataErrorCodeToString(error).c_str(),
+            base::Int64ToString(elapsed.InMilliseconds()).c_str(),
+            GetQueueInfo(queue_type).c_str());
+
+  base::Callback<void(google_apis::GDataErrorCode)> callback =
+      job->abort_callback;
+  queue_[GetJobQueueType(job->job_info.job_type)]->Remove(job->job_info.job_id);
+  job_map_.Remove(job->job_info.job_id);
+  base::MessageLoopProxy::current()->PostTask(FROM_HERE,
+                                              base::Bind(callback, error));
+}
+
 void JobScheduler::NotifyJobAdded(const JobInfo& job_info) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   FOR_EACH_OBSERVER(JobListObserver, observer_list_, OnJobAdded(job_info));
diff --git a/chrome/browser/chromeos/drive/job_scheduler.h b/chrome/browser/chromeos/drive/job_scheduler.h
index 55bd7bc..d0388fd 100644
--- a/chrome/browser/chromeos/drive/job_scheduler.h
+++ b/chrome/browser/chromeos/drive/job_scheduler.h
@@ -19,6 +19,10 @@
 
 class Profile;
 
+namespace base {
+class SeqencedTaskRunner;
+}
+
 namespace drive {
 
 // The JobScheduler is responsible for queuing and scheduling drive
@@ -48,7 +52,8 @@
       public JobListInterface {
  public:
   JobScheduler(Profile* profile,
-               google_apis::DriveServiceInterface* drive_service);
+               DriveServiceInterface* drive_service,
+               base::SequencedTaskRunner* blocking_task_runner);
   virtual ~JobScheduler();
 
   // JobListInterface overrides.
@@ -146,7 +151,7 @@
   JobID DownloadFile(
       const base::FilePath& virtual_path,
       const base::FilePath& local_cache_path,
-      const GURL& download_url,
+      const std::string& resource_id,
       const ClientContext& context,
       const google_apis::DownloadActionCallback& download_action_callback,
       const google_apis::GetContentCallback& get_content_callback);
@@ -208,6 +213,10 @@
 
     // The callback to cancel the running job. It is returned from task.Run().
     google_apis::CancelCallback cancel_callback;
+
+    // The callback to notify an error to the client of JobScheduler.
+    // This is used to notify cancel of a job that is not running yet.
+    base::Callback<void(google_apis::GDataErrorCode)> abort_callback;
   };
 
   // Parameters for DriveUploader::ResumeUploadFile.
@@ -302,6 +311,9 @@
   // For testing only.  Disables throttling so that testing is faster.
   void SetDisableThrottling(bool disable) { disable_throttling_ = disable; }
 
+  // Aborts a job which is not in STATE_RUNNING.
+  void AbortNotRunningJob(JobEntry* job, google_apis::GDataErrorCode error);
+
   // Notifies updates to observers.
   void NotifyJobAdded(const JobInfo& job_info);
   void NotifyJobDone(const JobInfo& job_info,
@@ -332,8 +344,8 @@
   // The list of observers for the scheduler.
   ObserverList<JobListObserver> observer_list_;
 
-  google_apis::DriveServiceInterface* drive_service_;
-  scoped_ptr<google_apis::DriveUploaderInterface> uploader_;
+  DriveServiceInterface* drive_service_;
+  scoped_ptr<DriveUploaderInterface> uploader_;
 
   Profile* profile_;
 
diff --git a/chrome/browser/chromeos/drive/job_scheduler_unittest.cc b/chrome/browser/chromeos/drive/job_scheduler_unittest.cc
index 6bb720a..57f3dbe 100644
--- a/chrome/browser/chromeos/drive/job_scheduler_unittest.cc
+++ b/chrome/browser/chromeos/drive/job_scheduler_unittest.cc
@@ -9,12 +9,13 @@
 #include "base/bind.h"
 #include "base/file_util.h"
 #include "base/prefs/pref_service.h"
+#include "base/run_loop.h"
 #include "base/stl_util.h"
-#include "base/threading/sequenced_worker_pool.h"
 #include "chrome/browser/chromeos/drive/test_util.h"
 #include "chrome/browser/drive/fake_drive_service.h"
 #include "chrome/browser/google_apis/drive_api_parser.h"
 #include "chrome/browser/google_apis/gdata_wapi_parser.h"
+#include "chrome/browser/google_apis/test_util.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/test/test_browser_thread_bundle.h"
@@ -24,20 +25,6 @@
 
 namespace {
 
-class FakeNetworkChangeNotifier : public net::NetworkChangeNotifier {
- public:
-  FakeNetworkChangeNotifier() : type_(CONNECTION_NONE) {}
-
-  void set_connection_type(ConnectionType type) { type_ = type; }
-
-  virtual ConnectionType GetCurrentConnectionType() const OVERRIDE {
-    return type_;
-  }
-
- private:
-  net::NetworkChangeNotifier::ConnectionType type_;
-};
-
 void CopyResourceIdFromGetResourceEntryCallback(
     std::vector<std::string>* id_list_out,
     const std::string& requested_id,
@@ -105,39 +92,28 @@
   }
 
   virtual void SetUp() OVERRIDE {
-    fake_network_change_notifier_.reset(new FakeNetworkChangeNotifier);
+    fake_network_change_notifier_.reset(
+        new test_util::FakeNetworkChangeNotifier);
 
-    fake_drive_service_.reset(new google_apis::FakeDriveService());
+    fake_drive_service_.reset(new FakeDriveService());
     fake_drive_service_->LoadResourceListForWapi(
-        "chromeos/gdata/root_feed.json");
+        "gdata/root_feed.json");
     fake_drive_service_->LoadAccountMetadataForWapi(
-        "chromeos/gdata/account_metadata.json");
+        "gdata/account_metadata.json");
     fake_drive_service_->LoadAppListForDriveApi(
-        "chromeos/drive/applist.json");
+        "drive/applist.json");
 
     scheduler_.reset(new JobScheduler(profile_.get(),
-                                      fake_drive_service_.get()));
+                                      fake_drive_service_.get(),
+                                      base::MessageLoopProxy::current()));
     scheduler_->SetDisableThrottling(true);
   }
 
-  virtual void TearDown() OVERRIDE {
-    // The scheduler should be deleted before NetworkLibrary, as it
-    // registers itself as observer of NetworkLibrary.
-    scheduler_.reset();
-    google_apis::test_util::RunBlockingPoolTask();
-    fake_drive_service_.reset();
-    fake_network_change_notifier_.reset();
-  }
-
  protected:
   // Sets up FakeNetworkChangeNotifier as if it's connected to a network with
   // the specified connection type.
   void ChangeConnectionType(net::NetworkChangeNotifier::ConnectionType type) {
-    fake_network_change_notifier_->set_connection_type(type);
-    // Notify the sync client that the network is changed. This is done via
-    // NetworkChangeNotifier in production, but here, we simulate the behavior
-    // by directly calling OnConnectionTypeChanged().
-    scheduler_->OnConnectionTypeChanged(type);
+    fake_network_change_notifier_->SetConnectionType(type);
   }
 
   // Sets up FakeNetworkChangeNotifier as if it's connected to wifi network.
@@ -160,11 +136,16 @@
     ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_NONE);
   }
 
+  static int GetMetadataQueueMaxJobCount() {
+    return JobScheduler::kMaxJobCount[JobScheduler::METADATA_QUEUE];
+  }
+
   content::TestBrowserThreadBundle thread_bundle_;
   scoped_ptr<TestingProfile> profile_;
+  scoped_ptr<test_util::FakeNetworkChangeNotifier>
+      fake_network_change_notifier_;
+  scoped_ptr<FakeDriveService> fake_drive_service_;
   scoped_ptr<JobScheduler> scheduler_;
-  scoped_ptr<FakeNetworkChangeNotifier> fake_network_change_notifier_;
-  scoped_ptr<google_apis::FakeDriveService> fake_drive_service_;
 };
 
 TEST_F(JobSchedulerTest, GetAboutResource) {
@@ -175,7 +156,7 @@
   scheduler_->GetAboutResource(
       google_apis::test_util::CreateCopyResultCallback(
           &error, &about_resource));
-  google_apis::test_util::RunBlockingPoolTask();
+  base::RunLoop().RunUntilIdle();
   ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
   ASSERT_TRUE(about_resource);
 }
@@ -188,7 +169,7 @@
 
   scheduler_->GetAppList(
       google_apis::test_util::CreateCopyResultCallback(&error, &app_list));
-  google_apis::test_util::RunBlockingPoolTask();
+  base::RunLoop().RunUntilIdle();
 
   ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
   ASSERT_TRUE(app_list);
@@ -203,7 +184,7 @@
   scheduler_->GetAllResourceList(
       google_apis::test_util::CreateCopyResultCallback(
           &error, &resource_list));
-  google_apis::test_util::RunBlockingPoolTask();
+  base::RunLoop().RunUntilIdle();
 
   ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
   ASSERT_TRUE(resource_list);
@@ -219,7 +200,7 @@
       fake_drive_service_->GetRootResourceId(),
       google_apis::test_util::CreateCopyResultCallback(
           &error, &resource_list));
-  google_apis::test_util::RunBlockingPoolTask();
+  base::RunLoop().RunUntilIdle();
 
   ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
   ASSERT_TRUE(resource_list);
@@ -235,7 +216,7 @@
       "File",  // search query
       google_apis::test_util::CreateCopyResultCallback(
           &error, &resource_list));
-  google_apis::test_util::RunBlockingPoolTask();
+  base::RunLoop().RunUntilIdle();
 
   ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
   ASSERT_TRUE(resource_list);
@@ -256,7 +237,7 @@
         "new directory",
         google_apis::test_util::CreateCopyResultCallback(
             &error, &resource_entry));
-    google_apis::test_util::RunBlockingPoolTask();
+    base::RunLoop().RunUntilIdle();
     ASSERT_EQ(google_apis::HTTP_CREATED, error);
   }
 
@@ -266,7 +247,7 @@
       654321 + 1,  // start_changestamp
       google_apis::test_util::CreateCopyResultCallback(
           &error, &resource_list));
-  google_apis::test_util::RunBlockingPoolTask();
+  base::RunLoop().RunUntilIdle();
 
   ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
   ASSERT_TRUE(resource_list);
@@ -282,7 +263,7 @@
   scheduler_->GetAllResourceList(
       google_apis::test_util::CreateCopyResultCallback(
           &error, &resource_list));
-  google_apis::test_util::RunBlockingPoolTask();
+  base::RunLoop().RunUntilIdle();
 
   ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
   ASSERT_TRUE(resource_list);
@@ -300,7 +281,7 @@
       next_url,
       google_apis::test_util::CreateCopyResultCallback(
           &error, &resource_list));
-  google_apis::test_util::RunBlockingPoolTask();
+  base::RunLoop().RunUntilIdle();
 
   ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
   ASSERT_TRUE(resource_list);
@@ -316,7 +297,7 @@
       "file:2_file_resource_id",  // resource ID
       ClientContext(USER_INITIATED),
       google_apis::test_util::CreateCopyResultCallback(&error, &entry));
-  google_apis::test_util::RunBlockingPoolTask();
+  base::RunLoop().RunUntilIdle();
 
   ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
   ASSERT_TRUE(entry);
@@ -330,7 +311,7 @@
   scheduler_->DeleteResource(
       "file:2_file_resource_id",
       google_apis::test_util::CreateCopyResultCallback(&error));
-  google_apis::test_util::RunBlockingPoolTask();
+  base::RunLoop().RunUntilIdle();
 
   ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
 }
@@ -346,7 +327,7 @@
       "folder:1_folder_resource_id",  // parent resource ID
       "New Document",  // new name
       google_apis::test_util::CreateCopyResultCallback(&error, &entry));
-  google_apis::test_util::RunBlockingPoolTask();
+  base::RunLoop().RunUntilIdle();
 
   ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
   ASSERT_TRUE(entry);
@@ -362,7 +343,7 @@
       "document:5_document_resource_id",  // resource ID
       "New Document",  // new name
       google_apis::test_util::CreateCopyResultCallback(&error, &entry));
-  google_apis::test_util::RunBlockingPoolTask();
+  base::RunLoop().RunUntilIdle();
 
   ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
   ASSERT_TRUE(entry);
@@ -377,7 +358,7 @@
       "file:2_file_resource_id",
       "New Name",
       google_apis::test_util::CreateCopyResultCallback(&error));
-  google_apis::test_util::RunBlockingPoolTask();
+  base::RunLoop().RunUntilIdle();
 
   ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
 }
@@ -391,7 +372,7 @@
       "folder:1_folder_resource_id",
       "file:2_file_resource_id",
       google_apis::test_util::CreateCopyResultCallback(&error));
-  google_apis::test_util::RunBlockingPoolTask();
+  base::RunLoop().RunUntilIdle();
 
   ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
 }
@@ -405,7 +386,7 @@
       "folder:1_folder_resource_id",
       "file:subdirectory_file_1_id",  // resource ID
       google_apis::test_util::CreateCopyResultCallback(&error));
-  google_apis::test_util::RunBlockingPoolTask();
+  base::RunLoop().RunUntilIdle();
 
   ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
 }
@@ -420,16 +401,26 @@
       fake_drive_service_->GetRootResourceId(),  // Root directory.
       "New Directory",
       google_apis::test_util::CreateCopyResultCallback(&error, &entry));
-  google_apis::test_util::RunBlockingPoolTask();
+  base::RunLoop().RunUntilIdle();
 
   ASSERT_EQ(google_apis::HTTP_CREATED, error);
   ASSERT_TRUE(entry);
 }
 
 TEST_F(JobSchedulerTest, GetResourceEntryPriority) {
-  // Disconnect from the network to prevent jobs from starting.
-  ConnectToNone();
+  // Saturate the metadata job queue with uninteresting jobs to prevent
+  // following jobs from starting.
+  google_apis::GDataErrorCode error_dontcare = google_apis::GDATA_OTHER_ERROR;
+  scoped_ptr<google_apis::ResourceEntry> entry_dontcare;
+  for (int i = 0; i < GetMetadataQueueMaxJobCount(); ++i) {
+    scheduler_->GetResourceEntry(
+        "uninteresting_resource_id",
+        ClientContext(USER_INITIATED),
+        google_apis::test_util::CreateCopyResultCallback(&error_dontcare,
+                                                         &entry_dontcare));
+  }
 
+  // Start jobs with different priorities.
   std::string resource_1("file:1_file_resource_id");
   std::string resource_2("file:2_file_resource_id");
   std::string resource_3("file:3_file_resource_id");
@@ -461,40 +452,54 @@
                  &resource_ids,
                  resource_4));
 
-  // Reconnect to the network to start all jobs.
-  ConnectToWifi();
-  google_apis::test_util::RunBlockingPoolTask();
+  base::RunLoop().RunUntilIdle();
 
   ASSERT_EQ(resource_ids.size(), 4ul);
-  ASSERT_EQ(resource_ids[0], resource_1);
-  ASSERT_EQ(resource_ids[1], resource_4);
-  ASSERT_EQ(resource_ids[2], resource_2);
-  ASSERT_EQ(resource_ids[3], resource_3);
+  EXPECT_EQ(resource_ids[0], resource_1);
+  EXPECT_EQ(resource_ids[1], resource_4);
+  EXPECT_EQ(resource_ids[2], resource_2);
+  EXPECT_EQ(resource_ids[3], resource_3);
 }
 
-TEST_F(JobSchedulerTest, GetResourceEntryNoConnection) {
+TEST_F(JobSchedulerTest, GetResourceEntryNoConnectionUserInitiated) {
   ConnectToNone();
 
-  std::string resource("file:1_file_resource_id");
-  std::vector<std::string> resource_ids;
+  std::string resource_id("file:2_file_resource_id");
 
+  google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
+  scoped_ptr<google_apis::ResourceEntry> entry;
   scheduler_->GetResourceEntry(
-      resource,  // resource ID
-      ClientContext(BACKGROUND),
-      base::Bind(&CopyResourceIdFromGetResourceEntryCallback,
-                 &resource_ids,
-                 resource));
-  google_apis::test_util::RunBlockingPoolTask();
+      resource_id,
+      ClientContext(USER_INITIATED),
+      google_apis::test_util::CreateCopyResultCallback(&error, &entry));
+  base::RunLoop().RunUntilIdle();
 
-  ASSERT_EQ(resource_ids.size(), 0ul);
+  EXPECT_EQ(google_apis::GDATA_NO_CONNECTION, error);
+}
+
+TEST_F(JobSchedulerTest, GetResourceEntryNoConnectionBackground) {
+  ConnectToNone();
+
+  std::string resource_id("file:2_file_resource_id");
+
+  google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
+  scoped_ptr<google_apis::ResourceEntry> entry;
+  scheduler_->GetResourceEntry(
+      resource_id,
+      ClientContext(BACKGROUND),
+      google_apis::test_util::CreateCopyResultCallback(&error, &entry));
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_FALSE(entry);
 
   // Reconnect to the net.
   ConnectToWifi();
 
-  google_apis::test_util::RunBlockingPoolTask();
+  base::RunLoop().RunUntilIdle();
 
-  ASSERT_EQ(resource_ids.size(), 1ul);
-  ASSERT_EQ(resource_ids[0], resource);
+  EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
+  ASSERT_TRUE(entry);
+  EXPECT_EQ(resource_id, entry->resource_id());
 }
 
 TEST_F(JobSchedulerTest, DownloadFileCellularDisabled) {
@@ -507,7 +512,6 @@
   base::ScopedTempDir temp_dir;
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
 
-  const GURL kContentUrl("https://file_content_url/");
   const base::FilePath kOutputFilePath =
       temp_dir.path().AppendASCII("whatever.txt");
   google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR;
@@ -515,7 +519,7 @@
   scheduler_->DownloadFile(
       base::FilePath::FromUTF8Unsafe("drive/whatever.txt"),  // virtual path
       kOutputFilePath,
-      kContentUrl,
+      "file:2_file_resource_id",
       ClientContext(BACKGROUND),
       google_apis::test_util::CreateCopyResultCallback(
           &download_error, &output_file_path),
@@ -528,7 +532,7 @@
   scheduler_->GetAboutResource(
       google_apis::test_util::CreateCopyResultCallback(
           &metadata_error, &about_resource));
-  google_apis::test_util::RunBlockingPoolTask();
+  base::RunLoop().RunUntilIdle();
 
   // Check the metadata
   ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error);
@@ -540,7 +544,7 @@
   // Switch to a Wifi connection
   ConnectToWifi();
 
-  google_apis::test_util::RunBlockingPoolTask();
+  base::RunLoop().RunUntilIdle();
 
   // Check the download again
   EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error);
@@ -560,7 +564,6 @@
   base::ScopedTempDir temp_dir;
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
 
-  const GURL kContentUrl("https://file_content_url/");
   const base::FilePath kOutputFilePath =
       temp_dir.path().AppendASCII("whatever.txt");
   google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR;
@@ -568,7 +571,7 @@
   scheduler_->DownloadFile(
       base::FilePath::FromUTF8Unsafe("drive/whatever.txt"),  // virtual path
       kOutputFilePath,
-      kContentUrl,
+      "file:2_file_resource_id",
       ClientContext(BACKGROUND),
       google_apis::test_util::CreateCopyResultCallback(
           &download_error, &output_file_path),
@@ -581,7 +584,7 @@
   scheduler_->GetAboutResource(
       google_apis::test_util::CreateCopyResultCallback(
           &metadata_error, &about_resource));
-  google_apis::test_util::RunBlockingPoolTask();
+  base::RunLoop().RunUntilIdle();
 
   // Check the metadata
   ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error);
@@ -593,7 +596,7 @@
   // Switch to a Wifi connection
   ConnectToWifi();
 
-  google_apis::test_util::RunBlockingPoolTask();
+  base::RunLoop().RunUntilIdle();
 
   // Check the download again
   EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error);
@@ -613,7 +616,6 @@
   base::ScopedTempDir temp_dir;
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
 
-  const GURL kContentUrl("https://file_content_url/");
   const base::FilePath kOutputFilePath =
       temp_dir.path().AppendASCII("whatever.txt");
   google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR;
@@ -621,7 +623,7 @@
   scheduler_->DownloadFile(
       base::FilePath::FromUTF8Unsafe("drive/whatever.txt"),  // virtual path
       kOutputFilePath,
-      kContentUrl,
+      "file:2_file_resource_id",
       ClientContext(BACKGROUND),
       google_apis::test_util::CreateCopyResultCallback(
           &download_error, &output_file_path),
@@ -634,7 +636,7 @@
   scheduler_->GetAboutResource(
       google_apis::test_util::CreateCopyResultCallback(
           &metadata_error, &about_resource));
-  google_apis::test_util::RunBlockingPoolTask();
+  base::RunLoop().RunUntilIdle();
 
   // Check the metadata
   ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error);
@@ -658,7 +660,6 @@
   base::ScopedTempDir temp_dir;
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
 
-  const GURL kContentUrl("https://file_content_url/");
   const base::FilePath kOutputFilePath =
       temp_dir.path().AppendASCII("whatever.txt");
   google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR;
@@ -666,7 +667,7 @@
   scheduler_->DownloadFile(
       base::FilePath::FromUTF8Unsafe("drive/whatever.txt"),  // virtual path
       kOutputFilePath,
-      kContentUrl,
+      "file:2_file_resource_id",
       ClientContext(BACKGROUND),
       google_apis::test_util::CreateCopyResultCallback(
           &download_error, &output_file_path),
@@ -679,7 +680,7 @@
   scheduler_->GetAboutResource(
       google_apis::test_util::CreateCopyResultCallback(
           &metadata_error, &about_resource));
-  google_apis::test_util::RunBlockingPoolTask();
+  base::RunLoop().RunUntilIdle();
 
   // Check the metadata
   ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error);
@@ -730,7 +731,7 @@
   scheduler_->DownloadFile(
       base::FilePath::FromUTF8Unsafe("drive/whatever.txt"),  // virtual path
       temp_dir.path().AppendASCII("whatever.txt"),
-      GURL("https://file_content_url/"),
+      "file:2_file_resource_id",
       ClientContext(BACKGROUND),
       google_apis::test_util::CreateCopyResultCallback(&error, &path),
       google_apis::GetContentCallback());
@@ -775,7 +776,7 @@
   EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_COPY_HOSTED_DOCUMENT));
 
   // Run the jobs.
-  google_apis::test_util::RunBlockingPoolTask();
+  base::RunLoop().RunUntilIdle();
 
   // All jobs except the BACKGROUND job should have started running (UPDATED)
   // and then finished (DONE).
@@ -800,7 +801,7 @@
 
   // Run the background downloading job as well.
   ConnectToWifi();
-  google_apis::test_util::RunBlockingPoolTask();
+  base::RunLoop().RunUntilIdle();
 
   // All jobs should have finished.
   EXPECT_EQ(0U, scheduler_->GetJobInfoList().size());
@@ -825,11 +826,11 @@
   scheduler_->DownloadFile(
       base::FilePath::FromUTF8Unsafe("drive/whatever.txt"),  // virtual path
       temp_dir.path().AppendASCII("whatever.txt"),
-      GURL("https://file_content_url/"),
+      "file:2_file_resource_id",
       ClientContext(BACKGROUND),
       google_apis::test_util::CreateCopyResultCallback(&error, &path),
       google_apis::GetContentCallback());
-  google_apis::test_util::RunBlockingPoolTask();
+  base::RunLoop().RunUntilIdle();
 
   std::vector<int64> download_progress;
   logger.GetProgressInfo(TYPE_DOWNLOAD_FILE, &download_progress);
@@ -853,7 +854,7 @@
       "plain/plain",
       ClientContext(BACKGROUND),
       google_apis::test_util::CreateCopyResultCallback(&upload_error, &entry));
-  google_apis::test_util::RunBlockingPoolTask();
+  base::RunLoop().RunUntilIdle();
 
   std::vector<int64> upload_progress;
   logger.GetProgressInfo(TYPE_UPLOAD_NEW_FILE, &upload_progress);
diff --git a/chrome/browser/chromeos/drive/local_file_reader_unittest.cc b/chrome/browser/chromeos/drive/local_file_reader_unittest.cc
index dd8acf4..0af9c0a 100644
--- a/chrome/browser/chromeos/drive/local_file_reader_unittest.cc
+++ b/chrome/browser/chromeos/drive/local_file_reader_unittest.cc
@@ -44,9 +44,6 @@
 
 class LocalFileReaderTest : public ::testing::Test {
  protected:
-  LocalFileReaderTest() {
-  }
-
   virtual void SetUp() OVERRIDE {
     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
     worker_thread_.reset(new base::Thread("LocalFileReaderTest"));
@@ -55,11 +52,6 @@
         new LocalFileReader(worker_thread_->message_loop_proxy()));
   }
 
-  virtual void TearDown() OVERRIDE {
-    file_reader_.reset();
-    worker_thread_.reset();
-  }
-
   base::MessageLoop message_loop_;
   base::ScopedTempDir temp_dir_;
   scoped_ptr<base::Thread> worker_thread_;
diff --git a/chrome/browser/chromeos/drive/logging.cc b/chrome/browser/chromeos/drive/logging.cc
index 8370957..48702a1 100644
--- a/chrome/browser/chromeos/drive/logging.cc
+++ b/chrome/browser/chromeos/drive/logging.cc
@@ -6,13 +6,13 @@
 
 #include "base/lazy_instance.h"
 #include "base/strings/stringprintf.h"
-#include "chrome/browser/google_apis/event_logger.h"
+#include "chrome/browser/drive/event_logger.h"
 
 namespace drive {
 namespace util {
 namespace {
 
-static base::LazyInstance<google_apis::EventLogger> g_logger =
+static base::LazyInstance<EventLogger> g_logger =
     LAZY_INSTANCE_INITIALIZER;
 
 }  // namespace
@@ -27,12 +27,12 @@
 
   // On thread-safety: LazyInstance guarantees thread-safety for the object
   // creation. EventLogger::Log() internally maintains the lock.
-  google_apis::EventLogger* ptr = g_logger.Pointer();
+  EventLogger* ptr = g_logger.Pointer();
   ptr->Log("%s", what.c_str());
 }
 
-std::vector<google_apis::EventLogger::Event> GetLogHistory() {
-  google_apis::EventLogger* ptr = g_logger.Pointer();
+std::vector<EventLogger::Event> GetLogHistory() {
+  EventLogger* ptr = g_logger.Pointer();
   return ptr->GetHistory();
 }
 
diff --git a/chrome/browser/chromeos/drive/logging.h b/chrome/browser/chromeos/drive/logging.h
index 1c679be..a2e4625 100644
--- a/chrome/browser/chromeos/drive/logging.h
+++ b/chrome/browser/chromeos/drive/logging.h
@@ -8,7 +8,7 @@
 #include <string>
 #include <vector>
 
-#include "chrome/browser/google_apis/event_logger.h"
+#include "chrome/browser/drive/event_logger.h"
 
 namespace drive {
 // Originally wanted to use 'logging' here, but it conflicts with
@@ -21,7 +21,7 @@
 
 // Returns the log history.
 // This function can be called from any thread.
-std::vector<google_apis::EventLogger::Event> GetLogHistory();
+std::vector<EventLogger::Event> GetLogHistory();
 
 }  // namespace util
 }  // namespace drive
diff --git a/chrome/browser/chromeos/drive/mock_directory_change_observer.cc b/chrome/browser/chromeos/drive/mock_directory_change_observer.cc
deleted file mode 100644
index 1331ab5..0000000
--- a/chrome/browser/chromeos/drive/mock_directory_change_observer.cc
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/chromeos/drive/mock_directory_change_observer.h"
-
-namespace drive {
-
-MockDirectoryChangeObserver::MockDirectoryChangeObserver() {
-}
-
-MockDirectoryChangeObserver::~MockDirectoryChangeObserver() {
-}
-
-}  // namespace drive
diff --git a/chrome/browser/chromeos/drive/mock_directory_change_observer.h b/chrome/browser/chromeos/drive/mock_directory_change_observer.h
deleted file mode 100644
index b503a70..0000000
--- a/chrome/browser/chromeos/drive/mock_directory_change_observer.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_CHROMEOS_DRIVE_MOCK_DIRECTORY_CHANGE_OBSERVER_H_
-#define CHROME_BROWSER_CHROMEOS_DRIVE_MOCK_DIRECTORY_CHANGE_OBSERVER_H_
-
-#include "base/files/file_path.h"
-#include "chrome/browser/chromeos/drive/file_system_observer.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-namespace drive {
-
-// Mock for FileSystemObserver::OnDirectoryChanged().
-class MockDirectoryChangeObserver : public FileSystemObserver {
- public:
-  MockDirectoryChangeObserver();
-  virtual ~MockDirectoryChangeObserver();
-
-  // FileSystemObserver overrides.
-  MOCK_METHOD1(OnDirectoryChanged, void(const base::FilePath& directory_path));
-};
-
-}  // namespace drive
-
-#endif  // CHROME_BROWSER_CHROMEOS_DRIVE_MOCK_DIRECTORY_CHANGE_OBSERVER_H_
diff --git a/chrome/browser/chromeos/drive/remove_stale_cache_files.cc b/chrome/browser/chromeos/drive/remove_stale_cache_files.cc
index c013fdf..798a559 100644
--- a/chrome/browser/chromeos/drive/remove_stale_cache_files.cc
+++ b/chrome/browser/chromeos/drive/remove_stale_cache_files.cc
@@ -16,38 +16,23 @@
 namespace drive {
 namespace internal {
 
-namespace {
-
-// Collects resource IDs of stale cache files.
-void CollectStaleCacheFiles(
-    ResourceMetadata* resource_metadata,
-    std::vector<std::string>* out_resource_ids_to_be_removed,
-    const std::string& resource_id,
-    const FileCacheEntry& cache_entry) {
-  ResourceEntry entry;
-  FileError error = resource_metadata->GetResourceEntryById(
-      resource_id, &entry);
-
-  // The entry is not found or the MD5 does not match.
-  if (error != FILE_ERROR_OK ||
-      cache_entry.md5() != entry.file_specific_info().md5())
-    out_resource_ids_to_be_removed->push_back(resource_id);
-}
-
-}  // namespace
-
 void RemoveStaleCacheFiles(FileCache* cache,
                            ResourceMetadata* resource_metadata) {
   std::vector<std::string> resource_ids_to_be_removed;
-  cache->Iterate(base::Bind(&CollectStaleCacheFiles,
-                            resource_metadata,
-                            &resource_ids_to_be_removed));
 
-  for (size_t i = 0; i < resource_ids_to_be_removed.size(); ++i) {
-    const std::string& resource_id = resource_ids_to_be_removed[i];
-    FileError error = cache->Remove(resource_id);
-    LOG_IF(WARNING, error != FILE_ERROR_OK)
-        << "Failed to remove a stale cache file. resource_id: " << resource_id;
+  scoped_ptr<FileCache::Iterator> it = cache->GetIterator();
+  for (; !it->IsAtEnd(); it->Advance()) {
+    ResourceEntry entry;
+    FileError error = resource_metadata->GetResourceEntryById(it->GetID(),
+                                                              &entry);
+    // The entry is not found or the MD5 does not match.
+    if (error != FILE_ERROR_OK ||
+        it->GetValue().md5() != entry.file_specific_info().md5()) {
+      FileError error = cache->Remove(it->GetID());
+      LOG_IF(WARNING, error != FILE_ERROR_OK)
+          << "Failed to remove a stale cache file. resource_id: "
+          << it->GetID();
+    }
   }
 }
 
diff --git a/chrome/browser/chromeos/drive/remove_stale_cache_files_unittest.cc b/chrome/browser/chromeos/drive/remove_stale_cache_files_unittest.cc
index a0e4c89..f99c6f1 100644
--- a/chrome/browser/chromeos/drive/remove_stale_cache_files_unittest.cc
+++ b/chrome/browser/chromeos/drive/remove_stale_cache_files_unittest.cc
@@ -28,14 +28,18 @@
 
     fake_free_disk_space_getter_.reset(new FakeFreeDiskSpaceGetter);
 
-    cache_.reset(new FileCache(temp_dir_.path(),
+    metadata_storage_.reset(new ResourceMetadataStorage(
+        temp_dir_.path(), base::MessageLoopProxy::current()));
+
+    cache_.reset(new FileCache(metadata_storage_.get(),
                                temp_dir_.path(),
                                base::MessageLoopProxy::current(),
                                fake_free_disk_space_getter_.get()));
 
     resource_metadata_.reset(new ResourceMetadata(
-        temp_dir_.path(), base::MessageLoopProxy::current()));
+        metadata_storage_.get(), base::MessageLoopProxy::current()));
 
+    ASSERT_TRUE(metadata_storage_->Initialize());
     ASSERT_TRUE(cache_->Initialize());
     ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->Initialize());
   }
@@ -43,6 +47,8 @@
   content::TestBrowserThreadBundle thread_bundle_;
   base::ScopedTempDir temp_dir_;
 
+  scoped_ptr<ResourceMetadataStorage,
+             test_util::DestroyHelperForTests> metadata_storage_;
   scoped_ptr<FileCache, test_util::DestroyHelperForTests> cache_;
   scoped_ptr<ResourceMetadata, test_util::DestroyHelperForTests>
       resource_metadata_;
diff --git a/chrome/browser/chromeos/drive/resource_entry_conversion.cc b/chrome/browser/chromeos/drive/resource_entry_conversion.cc
index 08d0eac..9ba85ad 100644
--- a/chrome/browser/chromeos/drive/resource_entry_conversion.cc
+++ b/chrome/browser/chromeos/drive/resource_entry_conversion.cc
@@ -12,7 +12,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/chromeos/drive/drive.pb.h"
 #include "chrome/browser/chromeos/drive/file_system_util.h"
-#include "chrome/browser/google_apis/drive_api_util.h"
+#include "chrome/browser/drive/drive_api_util.h"
 #include "chrome/browser/google_apis/gdata_wapi_parser.h"
 #include "googleurl/src/gurl.h"
 #include "net/base/escape.h"
@@ -54,9 +54,8 @@
   const google_apis::Link* parent_link =
       input.GetLinkByType(google_apis::Link::LINK_PARENT);
   if (parent_link) {
-    output.set_parent_resource_id(
-        google_apis::drive::util::ExtractResourceIdFromUrl(
-            parent_link->href()));
+    output.set_parent_resource_id(util::ExtractResourceIdFromUrl(
+        parent_link->href()));
   }
   // Apply mapping from an empty parent to the special dummy directory.
   if (output.parent_resource_id().empty())
@@ -108,6 +107,11 @@
         input.GetLinkByType(google_apis::Link::LINK_ALTERNATE);
     if (alternate_link)
       file_specific_info->set_alternate_url(alternate_link->href().spec());
+
+    const google_apis::Link* share_link =
+        input.GetLinkByType(google_apis::Link::LINK_SHARE);
+    if (share_link)
+      file_specific_info->set_share_url(share_link->href().spec());
   } else if (input.is_folder()) {
     file_info->set_is_directory(true);
   } else {
diff --git a/chrome/browser/chromeos/drive/resource_entry_conversion_unittest.cc b/chrome/browser/chromeos/drive/resource_entry_conversion_unittest.cc
index 0c7b06c..619d5d1 100644
--- a/chrome/browser/chromeos/drive/resource_entry_conversion_unittest.cc
+++ b/chrome/browser/chromeos/drive/resource_entry_conversion_unittest.cc
@@ -17,7 +17,7 @@
 
 TEST(ResourceEntryConversionTest, ConvertToResourceEntry_File) {
   scoped_ptr<base::Value> value =
-      google_apis::test_util::LoadJSONFile("chromeos/gdata/file_entry.json");
+      google_apis::test_util::LoadJSONFile("gdata/file_entry.json");
   ASSERT_TRUE(value.get());
 
   scoped_ptr<google_apis::ResourceEntry> gdata_resource_entry(
@@ -81,6 +81,8 @@
             entry.file_specific_info().thumbnail_url());
   EXPECT_EQ("https://file_link_alternate/",
             entry.file_specific_info().alternate_url());
+  EXPECT_EQ("https://file_link_share/",
+            entry.file_specific_info().share_url());
 
   // Regular file specific fields.
   EXPECT_EQ(892721,  entry.file_info().size());
@@ -93,7 +95,7 @@
      ConvertToResourceEntry_HostedDocument) {
   scoped_ptr<base::Value> value =
       google_apis::test_util::LoadJSONFile(
-          "chromeos/gdata/hosted_document_entry.json");
+          "gdata/hosted_document_entry.json");
   ASSERT_TRUE(value.get());
 
   scoped_ptr<google_apis::ResourceEntry> gdata_resource_entry(
@@ -174,7 +176,7 @@
      ConvertToResourceEntry_Directory) {
   scoped_ptr<base::Value> value =
       google_apis::test_util::LoadJSONFile(
-          "chromeos/gdata/directory_entry.json");
+          "gdata/directory_entry.json");
   ASSERT_TRUE(value.get());
 
   scoped_ptr<google_apis::ResourceEntry> gdata_resource_entry(
@@ -245,7 +247,7 @@
      ConvertToResourceEntry_DeletedHostedDocument) {
   scoped_ptr<base::Value> value =
       google_apis::test_util::LoadJSONFile(
-          "chromeos/gdata/deleted_hosted_document_entry.json");
+          "gdata/deleted_hosted_document_entry.json");
   ASSERT_TRUE(value.get());
 
   scoped_ptr<google_apis::ResourceEntry> gdata_resource_entry(
@@ -315,6 +317,8 @@
             entry.file_specific_info().thumbnail_url());
   EXPECT_EQ("https://alternate/document%3Adeleted_in_root_id/edit",
             entry.file_specific_info().alternate_url());
+  EXPECT_EQ("",
+            entry.file_specific_info().share_url());
 
   // The size should be 0 for a hosted document.
   EXPECT_EQ(0,  entry.file_info().size());
@@ -323,7 +327,7 @@
 TEST(ResourceEntryConversionTest,
      ConvertToResourceEntry_SharedWithMeEntry) {
   scoped_ptr<base::Value> value = google_apis::test_util::LoadJSONFile(
-      "chromeos/gdata/shared_with_me_entry.json");
+      "gdata/shared_with_me_entry.json");
   ASSERT_TRUE(value.get());
 
   scoped_ptr<google_apis::ResourceEntry> gdata_resource_entry(
diff --git a/chrome/browser/chromeos/drive/resource_metadata.cc b/chrome/browser/chromeos/drive/resource_metadata.cc
index 69973e9..4e79a57 100644
--- a/chrome/browser/chromeos/drive/resource_metadata.cc
+++ b/chrome/browser/chromeos/drive/resource_metadata.cc
@@ -34,7 +34,7 @@
   return entry;
 }
 
-// Returns true if enough disk space is avilable for DB operation.
+// Returns true if enough disk space is available for DB operation.
 // TODO(hashimoto): Merge this with FileCache's FreeDiskSpaceGetterInterface.
 bool EnoughDiskSpaceIsAvailableForDBOperation(const base::FilePath& path) {
   const int64 kRequiredDiskSpaceInMB = 128;  // 128 MB seems to be large enough.
@@ -125,11 +125,10 @@
 namespace internal {
 
 ResourceMetadata::ResourceMetadata(
-    const base::FilePath& data_directory_path,
+    ResourceMetadataStorage* storage,
     scoped_refptr<base::SequencedTaskRunner> blocking_task_runner)
-    : data_directory_path_(data_directory_path),
-      blocking_task_runner_(blocking_task_runner),
-      storage_(new ResourceMetadataStorage(data_directory_path)),
+    : blocking_task_runner_(blocking_task_runner),
+      storage_(storage),
       weak_ptr_factory_(this) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 }
@@ -137,13 +136,9 @@
 FileError ResourceMetadata::Initialize() {
   DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
 
-  if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_))
+  if (!EnoughDiskSpaceIsAvailableForDBOperation(storage_->directory_path()))
     return FILE_ERROR_NO_SPACE;
 
-  // Initialize the storage.
-  if (!storage_->Initialize())
-    return FILE_ERROR_FAILED;
-
   if (!SetUpDefaultEntries())
     return FILE_ERROR_FAILED;
 
@@ -174,7 +169,7 @@
 FileError ResourceMetadata::Reset() {
   DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
 
-  if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_))
+  if (!EnoughDiskSpaceIsAvailableForDBOperation(storage_->directory_path()))
     return FILE_ERROR_NO_SPACE;
 
   if (!storage_->SetLargestChangestamp(0) ||
@@ -249,7 +244,7 @@
 FileError ResourceMetadata::SetLargestChangestamp(int64 value) {
   DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
 
-  if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_))
+  if (!EnoughDiskSpaceIsAvailableForDBOperation(storage_->directory_path()))
     return FILE_ERROR_NO_SPACE;
 
   storage_->SetLargestChangestamp(value);
@@ -270,7 +265,7 @@
 FileError ResourceMetadata::AddEntry(const ResourceEntry& entry) {
   DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
 
-  if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_))
+  if (!EnoughDiskSpaceIsAvailableForDBOperation(storage_->directory_path()))
     return FILE_ERROR_NO_SPACE;
 
   ResourceEntry existing_entry;
@@ -320,7 +315,7 @@
 FileError ResourceMetadata::RemoveEntry(const std::string& resource_id) {
   DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
 
-  if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_))
+  if (!EnoughDiskSpaceIsAvailableForDBOperation(storage_->directory_path()))
     return FILE_ERROR_NO_SPACE;
 
   // Disallow deletion of special entries "/drive" and "/drive/other".
@@ -438,7 +433,7 @@
 FileError ResourceMetadata::RefreshEntry(const ResourceEntry& entry) {
   DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
 
-  if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_))
+  if (!EnoughDiskSpaceIsAvailableForDBOperation(storage_->directory_path()))
     return FILE_ERROR_NO_SPACE;
 
   ResourceEntry old_entry;
@@ -529,7 +524,7 @@
   DCHECK(!file_path.empty());
   DCHECK(out_file_path);
 
-  if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_))
+  if (!EnoughDiskSpaceIsAvailableForDBOperation(storage_->directory_path()))
     return FILE_ERROR_NO_SPACE;
 
   ResourceEntry entry, destination;
@@ -558,7 +553,7 @@
 
   DVLOG(1) << "RenameEntry " << file_path.value() << " to " << new_name;
 
-  if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_))
+  if (!EnoughDiskSpaceIsAvailableForDBOperation(storage_->directory_path()))
     return FILE_ERROR_NO_SPACE;
 
   ResourceEntry entry;
@@ -631,7 +626,7 @@
   DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
   DCHECK(!directory_fetch_info.empty());
 
-  if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_))
+  if (!EnoughDiskSpaceIsAvailableForDBOperation(storage_->directory_path()))
     return FILE_ERROR_NO_SPACE;
 
   ResourceEntry directory;
@@ -649,7 +644,7 @@
   // entries in the loop. We'll process deleted entries afterwards.
   for (ResourceEntryMap::const_iterator it = entry_map.begin();
        it != entry_map.end(); ++it) {
-    if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_))
+    if (!EnoughDiskSpaceIsAvailableForDBOperation(storage_->directory_path()))
       return FILE_ERROR_NO_SPACE;
 
     const ResourceEntry& entry = it->second;
@@ -674,7 +669,7 @@
   std::vector<std::string> children;
   storage_->GetChildren(directory.resource_id(), &children);
   for (size_t i = 0; i < children.size(); ++i) {
-    if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_))
+    if (!EnoughDiskSpaceIsAvailableForDBOperation(storage_->directory_path()))
       return FILE_ERROR_NO_SPACE;
 
     if (entry_map.count(children[i]) == 0) {
@@ -751,7 +746,7 @@
 
   // Do file name de-duplication - Keep changing |entry|'s name until there is
   // no other entry with the same name under the parent.
-  int modifier = 1;
+  int modifier = 0;
   std::string new_base_name = updated_entry.base_name();
   while (true) {
     const std::string existing_entry_id =
@@ -764,7 +759,7 @@
     new_path =
         new_path.InsertBeforeExtension(base::StringPrintf(" (%d)", ++modifier));
     // The new filename must be different from the previous one.
-    DCHECK(new_base_name != new_path.AsUTF8Unsafe());
+    DCHECK_NE(new_base_name, new_path.AsUTF8Unsafe());
     new_base_name = new_path.AsUTF8Unsafe();
   }
   updated_entry.set_base_name(new_base_name);
diff --git a/chrome/browser/chromeos/drive/resource_metadata.h b/chrome/browser/chromeos/drive/resource_metadata.h
index 345e663..848c2b2 100644
--- a/chrome/browser/chromeos/drive/resource_metadata.h
+++ b/chrome/browser/chromeos/drive/resource_metadata.h
@@ -14,7 +14,7 @@
 #include "base/files/file_path.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/chromeos/drive/file_errors.h"
 #include "chrome/browser/chromeos/drive/resource_metadata_storage.h"
 
@@ -25,7 +25,6 @@
 namespace drive {
 
 class ResourceEntry;
-class ResourceMetadataStorage;
 
 typedef std::vector<ResourceEntry> ResourceEntryVector;
 typedef std::map<std::string /* resource_id */, ResourceEntry>
@@ -112,10 +111,8 @@
  public:
   typedef ResourceMetadataStorage::Iterator Iterator;
 
-  // |root_resource_id| is the resource id for the root directory.
-  // Must be called on the UI thread.
   ResourceMetadata(
-      const base::FilePath& data_directory_path,
+      ResourceMetadataStorage* storage,
       scoped_refptr<base::SequencedTaskRunner> blocking_task_runner);
 
   // Initializes this object.
@@ -304,11 +301,9 @@
   // Removes the entry and its descendants.
   bool RemoveEntryRecursively(const std::string& resource_id);
 
-  const base::FilePath data_directory_path_;
-
   scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
 
-  scoped_ptr<ResourceMetadataStorage> storage_;
+  ResourceMetadataStorage* storage_;
 
   // This should remain the last member so it'll be destroyed first and
   // invalidate its weak pointers before other members are destroyed.
diff --git a/chrome/browser/chromeos/drive/resource_metadata_storage.cc b/chrome/browser/chromeos/drive/resource_metadata_storage.cc
index 2cdf41e..b7a6264 100644
--- a/chrome/browser/chromeos/drive/resource_metadata_storage.cc
+++ b/chrome/browser/chromeos/drive/resource_metadata_storage.cc
@@ -4,15 +4,19 @@
 
 #include "chrome/browser/chromeos/drive/resource_metadata_storage.h"
 
+#include "base/bind.h"
 #include "base/file_util.h"
+#include "base/location.h"
 #include "base/logging.h"
 #include "base/metrics/histogram.h"
+#include "base/sequenced_task_runner.h"
 #include "base/threading/thread_restrictions.h"
 #include "chrome/browser/chromeos/drive/drive.pb.h"
 #include "third_party/leveldatabase/src/include/leveldb/db.h"
 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
 
 namespace drive {
+namespace internal {
 
 namespace {
 
@@ -36,6 +40,9 @@
 // Meant to be a character which never happen to be in real resource IDs.
 const char kDBKeyDelimeter = '\0';
 
+// String used as a suffix of a key for a cache entry.
+const char kCacheEntryKeySuffix[] = "CACHE";
+
 // Returns a string to be used as the key for the header.
 std::string GetHeaderDBKey() {
   std::string key;
@@ -49,6 +56,28 @@
   return !key.empty() && key[key.size() - 1] == kDBKeyDelimeter;
 }
 
+// Returns a string to be used as a key for a cache entry.
+std::string GetCacheEntryKey(const std::string& resource_id) {
+  std::string key(resource_id);
+  key.push_back(kDBKeyDelimeter);
+  key.append(kCacheEntryKeySuffix);
+  return key;
+}
+
+// Returns true if |key| is a key for a cache entry.
+bool IsCacheEntryKey(const leveldb::Slice& key) {
+  // A cache entry key should end with |kDBKeyDelimeter + kCacheEntryKeySuffix|.
+  const leveldb::Slice expected_suffix(kCacheEntryKeySuffix,
+                                       arraysize(kCacheEntryKeySuffix) - 1);
+  if (key.size() < 1 + expected_suffix.size() ||
+      key[key.size() - expected_suffix.size() - 1] != kDBKeyDelimeter)
+    return false;
+
+  const leveldb::Slice key_substring(
+      key.data() + key.size() - expected_suffix.size(), expected_suffix.size());
+  return key_substring.compare(expected_suffix) == 0;
+}
+
 // Converts leveldb::Status to DBInitStatus.
 DBInitStatus LevelDBStatusToDBInitStatus(const leveldb::Status status) {
   if (status.ok())
@@ -98,6 +127,7 @@
 
   for (it_->Next() ; it_->Valid(); it_->Next()) {
     if (!IsChildEntryKey(it_->key()) &&
+        !IsCacheEntryKey(it_->key()) &&
         entry_.ParseFromArray(it_->value().data(), it_->value().size()))
       break;
   }
@@ -108,21 +138,86 @@
   return !it_->status().ok();
 }
 
-ResourceMetadataStorage::ResourceMetadataStorage(
-    const base::FilePath& directory_path)
-    : directory_path_(directory_path) {
+ResourceMetadataStorage::CacheEntryIterator::CacheEntryIterator(
+    scoped_ptr<leveldb::Iterator> it) : it_(it.Pass()) {
+  base::ThreadRestrictions::AssertIOAllowed();
+  DCHECK(it_);
+
+  it_->SeekToFirst();
+  AdvanceInternal();
 }
 
-ResourceMetadataStorage::~ResourceMetadataStorage() {
+ResourceMetadataStorage::CacheEntryIterator::~CacheEntryIterator() {
   base::ThreadRestrictions::AssertIOAllowed();
 }
 
+bool ResourceMetadataStorage::CacheEntryIterator::IsAtEnd() const {
+  base::ThreadRestrictions::AssertIOAllowed();
+  return !it_->Valid();
+}
+
+const std::string& ResourceMetadataStorage::CacheEntryIterator::GetID() const {
+  base::ThreadRestrictions::AssertIOAllowed();
+  DCHECK(!IsAtEnd());
+  return resource_id_;
+}
+
+const FileCacheEntry&
+ResourceMetadataStorage::CacheEntryIterator::GetValue() const {
+  base::ThreadRestrictions::AssertIOAllowed();
+  DCHECK(!IsAtEnd());
+  return entry_;
+}
+
+void ResourceMetadataStorage::CacheEntryIterator::Advance() {
+  base::ThreadRestrictions::AssertIOAllowed();
+  DCHECK(!IsAtEnd());
+
+  it_->Next();
+  AdvanceInternal();
+}
+
+bool ResourceMetadataStorage::CacheEntryIterator::HasError() const {
+  base::ThreadRestrictions::AssertIOAllowed();
+  return !it_->status().ok();
+}
+
+void ResourceMetadataStorage::CacheEntryIterator::AdvanceInternal() {
+  for (; it_->Valid(); it_->Next()) {
+    // Skip unparsable broken entries.
+    // TODO(hashimoto): Broken entries should be cleaned up at some point.
+    if (IsCacheEntryKey(it_->key()) &&
+        entry_.ParseFromArray(it_->value().data(), it_->value().size())) {
+      // Drop the suffix |kDBKeyDelimeter + kCacheEntryKeySuffix| from the key.
+      const size_t kSuffixLength = arraysize(kCacheEntryKeySuffix) - 1;
+      const int id_length = it_->key().size() - 1 - kSuffixLength;
+      resource_id_.assign(it_->key().data(), id_length);
+      break;
+    }
+  }
+}
+
+ResourceMetadataStorage::ResourceMetadataStorage(
+    const base::FilePath& directory_path,
+    base::SequencedTaskRunner* blocking_task_runner)
+    : directory_path_(directory_path),
+      opened_existing_db_(false),
+      blocking_task_runner_(blocking_task_runner) {
+}
+
+void ResourceMetadataStorage::Destroy() {
+  blocking_task_runner_->PostTask(
+      FROM_HERE,
+      base::Bind(&ResourceMetadataStorage::DestroyOnBlockingPool,
+                 base::Unretained(this)));
+}
+
 bool ResourceMetadataStorage::Initialize() {
   base::ThreadRestrictions::AssertIOAllowed();
 
   // Remove unused child map DB.
   const base::FilePath child_map_path = directory_path_.Append(kChildMapDBName);
-  file_util::Delete(child_map_path, true /* recursive */);
+  base::Delete(child_map_path, true /* recursive */);
 
   resource_map_.reset();
 
@@ -145,8 +240,8 @@
     resource_map_.reset(db);
 
     // Check the validity of existing DB.
-    scoped_ptr<ResourceMetadataHeader> header = GetHeader();
-    if (!header || header->version() != kDBVersion) {
+    ResourceMetadataHeader header;
+    if (!GetHeader(&header) || header.version() != kDBVersion) {
       open_existing_result = DB_INIT_INCOMPATIBLE;
       LOG(INFO) << "Reject incompatible DB.";
     } else if (!CheckValidity()) {
@@ -154,7 +249,9 @@
       LOG(ERROR) << "Reject invalid DB.";
     }
 
-    if (open_existing_result != DB_INIT_SUCCESS)
+    if (open_existing_result == DB_INIT_SUCCESS)
+      opened_existing_db_ = true;
+    else
       resource_map_.reset();
   }
 
@@ -170,7 +267,7 @@
 
     // Clean up the destination.
     const bool kRecursive = true;
-    file_util::Delete(resource_map_path, kRecursive);
+    base::Delete(resource_map_path, kRecursive);
 
     // Create DB.
     options.create_if_missing = true;
@@ -203,23 +300,23 @@
     int64 largest_changestamp) {
   base::ThreadRestrictions::AssertIOAllowed();
 
-  scoped_ptr<ResourceMetadataHeader> header = GetHeader();
-  if (!header) {
+  ResourceMetadataHeader header;
+  if (!GetHeader(&header)) {
     DLOG(ERROR) << "Failed to get the header.";
     return false;
   }
-  header->set_largest_changestamp(largest_changestamp);
-  return PutHeader(*header);
+  header.set_largest_changestamp(largest_changestamp);
+  return PutHeader(header);
 }
 
 int64 ResourceMetadataStorage::GetLargestChangestamp() {
   base::ThreadRestrictions::AssertIOAllowed();
-  scoped_ptr<ResourceMetadataHeader> header = GetHeader();
-  if (!header) {
+  ResourceMetadataHeader header;
+  if (!GetHeader(&header)) {
     DLOG(ERROR) << "Failed to get the header.";
     return 0;
   }
-  return header->largest_changestamp();
+  return header.largest_changestamp();
 }
 
 bool ResourceMetadataStorage::PutEntry(const ResourceEntry& entry) {
@@ -313,9 +410,8 @@
   return child_resource_id;
 }
 
-void ResourceMetadataStorage::GetChildren(
-    const std::string& parent_resource_id,
-    std::vector<std::string>* children) {
+void ResourceMetadataStorage::GetChildren(const std::string& parent_resource_id,
+                                          std::vector<std::string>* children) {
   base::ThreadRestrictions::AssertIOAllowed();
 
   // Iterate over all entries with keys starting with |parent_resource_id|.
@@ -330,6 +426,64 @@
   DCHECK(it->status().ok());
 }
 
+bool ResourceMetadataStorage::PutCacheEntry(const std::string& resource_id,
+                                            const FileCacheEntry& entry) {
+  base::ThreadRestrictions::AssertIOAllowed();
+  DCHECK(!resource_id.empty());
+
+  std::string serialized_entry;
+  if (!entry.SerializeToString(&serialized_entry)) {
+    DLOG(ERROR) << "Failed to serialize the entry.";
+    return false;
+  }
+
+  const leveldb::Status status = resource_map_->Put(
+      leveldb::WriteOptions(),
+      leveldb::Slice(GetCacheEntryKey(resource_id)),
+      leveldb::Slice(serialized_entry));
+  return status.ok();
+}
+
+bool ResourceMetadataStorage::GetCacheEntry(const std::string& resource_id,
+                                            FileCacheEntry* out_entry) {
+  base::ThreadRestrictions::AssertIOAllowed();
+  DCHECK(!resource_id.empty());
+
+  std::string serialized_entry;
+  const leveldb::Status status = resource_map_->Get(
+      leveldb::ReadOptions(),
+      leveldb::Slice(GetCacheEntryKey(resource_id)),
+      &serialized_entry);
+  return status.ok() && out_entry->ParseFromString(serialized_entry);
+}
+
+bool ResourceMetadataStorage::RemoveCacheEntry(const std::string& resource_id) {
+  base::ThreadRestrictions::AssertIOAllowed();
+  DCHECK(!resource_id.empty());
+
+  const leveldb::Status status = resource_map_->Delete(
+      leveldb::WriteOptions(),
+      leveldb::Slice(GetCacheEntryKey(resource_id)));
+  return status.ok();
+}
+
+scoped_ptr<ResourceMetadataStorage::CacheEntryIterator>
+ResourceMetadataStorage::GetCacheEntryIterator() {
+  base::ThreadRestrictions::AssertIOAllowed();
+
+  scoped_ptr<leveldb::Iterator> it(
+      resource_map_->NewIterator(leveldb::ReadOptions()));
+  return make_scoped_ptr(new CacheEntryIterator(it.Pass()));
+}
+
+ResourceMetadataStorage::~ResourceMetadataStorage() {
+  base::ThreadRestrictions::AssertIOAllowed();
+}
+
+void ResourceMetadataStorage::DestroyOnBlockingPool() {
+  delete this;
+}
+
 // static
 std::string ResourceMetadataStorage::GetChildEntryKey(
     const std::string& parent_resource_id,
@@ -358,8 +512,7 @@
   return status.ok();
 }
 
-scoped_ptr<ResourceMetadataHeader>
-ResourceMetadataStorage::GetHeader() {
+bool ResourceMetadataStorage::GetHeader(ResourceMetadataHeader* header) {
   base::ThreadRestrictions::AssertIOAllowed();
 
   std::string serialized_header;
@@ -367,14 +520,7 @@
       leveldb::ReadOptions(),
       leveldb::Slice(GetHeaderDBKey()),
       &serialized_header);
-  if (!status.ok())
-    return scoped_ptr<ResourceMetadataHeader>();
-
-  scoped_ptr<ResourceMetadataHeader> header(
-      new ResourceMetadataHeader);
-  if (!header->ParseFromString(serialized_header))
-    return scoped_ptr<ResourceMetadataHeader>();
-  return header.Pass();
+  return status.ok() && header->ParseFromString(serialized_header);
 }
 
 bool ResourceMetadataStorage::CheckValidity() {
@@ -387,6 +533,20 @@
   scoped_ptr<leveldb::Iterator> it(resource_map_->NewIterator(options));
   it->SeekToFirst();
 
+  // DB is organized like this:
+  //
+  // <key>                          : <value>
+  // "\0HEADER"                     : ResourceMetadataHeader
+  // "|ID of A|"                    : ResourceEntry for entry A.
+  // "|ID of A|\0CACHE"             : FileCacheEntry for entry A.
+  // "|ID of A|\0|child name 1|\0"  : ID of the 1st child entry of entry A.
+  // "|ID of A|\0|child name 2|\0"  : ID of the 2nd child entry of entry A.
+  // ...
+  // "|ID of A|\0|child name n|\0"  : ID of the nth child entry of entry A.
+  // "|ID of B|"                    : ResourceEntry for entry B.
+  // "|ID of B|\0CACHE"             : FileCacheEntry for entry B.
+  // ...
+
   // Check the header.
   ResourceMetadataHeader header;
   if (!it->Valid() ||
@@ -410,6 +570,10 @@
       continue;
     }
 
+    // Ignore cache entries.
+    if (IsCacheEntryKey(it->key()))
+      continue;
+
     // Check if stored data is broken.
     if (!entry.ParseFromArray(it->value().data(), it->value().size()) ||
         entry.resource_id() != it->key()) {
@@ -449,4 +613,5 @@
   return true;
 }
 
+}  // namespace internal
 }  // namespace drive
diff --git a/chrome/browser/chromeos/drive/resource_metadata_storage.h b/chrome/browser/chromeos/drive/resource_metadata_storage.h
index a2b4532..adac420 100644
--- a/chrome/browser/chromeos/drive/resource_metadata_storage.h
+++ b/chrome/browser/chromeos/drive/resource_metadata_storage.h
@@ -10,9 +10,14 @@
 
 #include "base/basictypes.h"
 #include "base/files/file_path.h"
+#include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "chrome/browser/chromeos/drive/drive.pb.h"
 
+namespace base {
+class SequencedTaskRunner;
+}
+
 namespace leveldb {
 class DB;
 class Iterator;
@@ -23,20 +28,24 @@
 class ResourceEntry;
 class ResourceMetadataHeader;
 
+namespace internal {
+
 // Storage for ResourceMetadata which is responsible to manage resource
 // entries and child-parent relationships between entries.
 class ResourceMetadataStorage {
  public:
   // This should be incremented when incompatibility change is made to DB
   // format.
-  static const int kDBVersion = 6;
+  static const int kDBVersion = 7;
 
+  // Object to iterate over entries stored in this storage.
   class Iterator {
    public:
     explicit Iterator(scoped_ptr<leveldb::Iterator> it);
     ~Iterator();
 
-    // Returns true if this iterator cannot advance any more.
+    // Returns true if this iterator cannot advance any more and does not point
+    // to a valid entry. Get() and Advance() should not be called in such cases.
     bool IsAtEnd() const;
 
     // Returns the entry currently pointed by this object.
@@ -55,8 +64,51 @@
     DISALLOW_COPY_AND_ASSIGN(Iterator);
   };
 
-  explicit ResourceMetadataStorage(const base::FilePath& directory_path);
-  virtual ~ResourceMetadataStorage();
+  // Object to iterate over cache entries stored in this storage.
+  class CacheEntryIterator {
+   public:
+    explicit CacheEntryIterator(scoped_ptr<leveldb::Iterator> it);
+    ~CacheEntryIterator();
+
+    // Returns true if this iterator cannot advance any more and does not point
+    // to a valid entry. GetID(), GetValue() and Advance() should not be called
+    // in such cases.
+    bool IsAtEnd() const;
+
+    // Returns the ID of the entry currently pointed by this object.
+    const std::string& GetID() const;
+
+    // Returns the value of the entry currently pointed by this object.
+    const FileCacheEntry& GetValue() const;
+
+    // Advances to the next entry.
+    void Advance();
+
+    // Returns true if this object has encountered any error.
+    bool HasError() const;
+
+   private:
+    // Used to implement Advance().
+    void AdvanceInternal();
+
+    scoped_ptr<leveldb::Iterator> it_;
+    std::string resource_id_;
+    FileCacheEntry entry_;
+
+    DISALLOW_COPY_AND_ASSIGN(CacheEntryIterator);
+  };
+
+  ResourceMetadataStorage(const base::FilePath& directory_path,
+                          base::SequencedTaskRunner* blocking_task_runner);
+
+  const base::FilePath& directory_path() const { return directory_path_; }
+
+  // Returns true if the DB used by this storage was opened, not created, during
+  // Initialize().
+  bool opened_existing_db() const { return opened_existing_db_; }
+
+  // Destroys this object.
+  void Destroy();
 
   // Initializes this object.
   bool Initialize();
@@ -87,9 +139,28 @@
   void GetChildren(const std::string& parent_resource_id,
                    std::vector<std::string>* children);
 
+  // Puts the cache entry to this storage.
+  bool PutCacheEntry(const std::string& resource_id,
+                     const FileCacheEntry& entry);
+
+  // Gets a cache entry stored in this storage.
+  bool GetCacheEntry(const std::string& resource_id, FileCacheEntry* out_entry);
+
+  // Removes a cache entry from this storage.
+  bool RemoveCacheEntry(const std::string& resource_id);
+
+  // Returns an object to iterate over cache entries stored in this storage.
+  scoped_ptr<CacheEntryIterator> GetCacheEntryIterator();
+
  private:
   friend class ResourceMetadataStorageTest;
 
+  // To destruct this object, use Destroy().
+  ~ResourceMetadataStorage();
+
+  // Used to implement Destroy().
+  void DestroyOnBlockingPool();
+
   // Returns a string to be used as a key for child entry.
   static std::string GetChildEntryKey(const std::string& parent_resource_id,
                                       const std::string& child_name);
@@ -98,7 +169,7 @@
   bool PutHeader(const ResourceMetadataHeader& header);
 
   // Gets header.
-  scoped_ptr<ResourceMetadataHeader> GetHeader();
+  bool GetHeader(ResourceMetadataHeader* out_header);
 
   // Checks validity of the data.
   bool CheckValidity();
@@ -106,12 +177,17 @@
   // Path to the directory where the data is stored.
   base::FilePath directory_path_;
 
+  bool opened_existing_db_;
+
   // Entries stored in this storage.
   scoped_ptr<leveldb::DB> resource_map_;
 
+  scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
+
   DISALLOW_COPY_AND_ASSIGN(ResourceMetadataStorage);
 };
 
+}  // namespace internal
 }  // namespace drive
 
 #endif  // CHROME_BROWSER_CHROMEOS_DRIVE_RESOURCE_METADATA_STORAGE_H_
diff --git a/chrome/browser/chromeos/drive/resource_metadata_storage_unittest.cc b/chrome/browser/chromeos/drive/resource_metadata_storage_unittest.cc
index b384cca..4ab0acf 100644
--- a/chrome/browser/chromeos/drive/resource_metadata_storage_unittest.cc
+++ b/chrome/browser/chromeos/drive/resource_metadata_storage_unittest.cc
@@ -9,29 +9,30 @@
 #include "base/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "chrome/browser/chromeos/drive/drive.pb.h"
+#include "chrome/browser/chromeos/drive/test_util.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/leveldatabase/src/include/leveldb/db.h"
 
 namespace drive {
+namespace internal {
 
 class ResourceMetadataStorageTest : public testing::Test {
  protected:
   virtual void SetUp() OVERRIDE {
     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
 
-    storage_.reset(new ResourceMetadataStorage(temp_dir_.path()));
+    storage_.reset(new ResourceMetadataStorage(
+        temp_dir_.path(), base::MessageLoopProxy::current()));
     ASSERT_TRUE(storage_->Initialize());
   }
 
-  virtual void TearDown() OVERRIDE {
-  }
-
   // Overwrites |storage_|'s version.
   void SetDBVersion(int version) {
-    scoped_ptr<ResourceMetadataHeader> header = storage_->GetHeader();
-    ASSERT_TRUE(header);
-    header->set_version(version);
-    storage_->PutHeader(*header);
+    ResourceMetadataHeader header;
+    ASSERT_TRUE(storage_->GetHeader(&header));
+    header.set_version(version);
+    EXPECT_TRUE(storage_->PutHeader(header));
   }
 
   bool CheckValidity() {
@@ -58,8 +59,10 @@
                                                   child_base_name));
   }
 
+  content::TestBrowserThreadBundle thread_bundle_;
   base::ScopedTempDir temp_dir_;
-  scoped_ptr<ResourceMetadataStorage> storage_;
+  scoped_ptr<ResourceMetadataStorage,
+             test_util::DestroyHelperForTests> storage_;
 };
 
 TEST_F(ResourceMetadataStorageTest, LargestChangestamp) {
@@ -148,6 +151,11 @@
   for (size_t i = 0; i < entries.size(); ++i)
     EXPECT_TRUE(storage_->PutEntry(entries[i]));
 
+  // Insert some dummy cache entries.
+  FileCacheEntry cache_entry;
+  EXPECT_TRUE(storage_->PutCacheEntry(entries[0].resource_id(), cache_entry));
+  EXPECT_TRUE(storage_->PutCacheEntry(entries[1].resource_id(), cache_entry));
+
   // Iterate and check the result.
   std::map<std::string, ResourceEntry> result;
   scoped_ptr<ResourceMetadataStorage::Iterator> it = storage_->GetIterator();
@@ -163,6 +171,72 @@
     EXPECT_EQ(1U, result.count(entries[i].resource_id()));
 }
 
+TEST_F(ResourceMetadataStorageTest, PutCacheEntry) {
+  FileCacheEntry entry;
+  const std::string key1 = "abcdefg";
+  const std::string key2 = "abcd";
+  const std::string md5_1 = "foo";
+  const std::string md5_2 = "bar";
+
+  // Put cache entries.
+  entry.set_md5(md5_1);
+  EXPECT_TRUE(storage_->PutCacheEntry(key1, entry));
+  entry.set_md5(md5_2);
+  EXPECT_TRUE(storage_->PutCacheEntry(key2, entry));
+
+  // Get cache entires.
+  EXPECT_TRUE(storage_->GetCacheEntry(key1, &entry));
+  EXPECT_EQ(md5_1, entry.md5());
+  EXPECT_TRUE(storage_->GetCacheEntry(key2, &entry));
+  EXPECT_EQ(md5_2, entry.md5());
+
+  // Remove cache entries.
+  EXPECT_TRUE(storage_->RemoveCacheEntry(key1));
+  EXPECT_FALSE(storage_->GetCacheEntry(key1, &entry));
+
+  EXPECT_TRUE(storage_->RemoveCacheEntry(key2));
+  EXPECT_FALSE(storage_->GetCacheEntry(key2, &entry));
+}
+
+TEST_F(ResourceMetadataStorageTest, CacheEntryIterator) {
+  // Prepare data.
+  std::map<std::string, FileCacheEntry> entries;
+  FileCacheEntry cache_entry;
+
+  cache_entry.set_md5("aA");
+  entries["entry1"] = cache_entry;
+  cache_entry.set_md5("bB");
+  entries["entry2"] = cache_entry;
+  cache_entry.set_md5("cC");
+  entries["entry3"] = cache_entry;
+  cache_entry.set_md5("dD");
+  entries["entry4"] = cache_entry;
+
+  for (std::map<std::string, FileCacheEntry>::iterator it = entries.begin();
+       it != entries.end(); ++it)
+    EXPECT_TRUE(storage_->PutCacheEntry(it->first, it->second));
+
+  // Insert some dummy entries.
+  ResourceEntry entry;
+  entry.set_resource_id("entry1");
+  EXPECT_TRUE(storage_->PutEntry(entry));
+  entry.set_resource_id("entry2");
+  EXPECT_TRUE(storage_->PutEntry(entry));
+
+  // Iterate and check the result.
+  scoped_ptr<ResourceMetadataStorage::CacheEntryIterator> it =
+      storage_->GetCacheEntryIterator();
+  ASSERT_TRUE(it);
+  size_t num_entries = 0;
+  for (; !it->IsAtEnd(); it->Advance()) {
+    EXPECT_EQ(1U, entries.count(it->GetID()));
+    EXPECT_EQ(entries[it->GetID()].md5(), it->GetValue().md5());
+    ++num_entries;
+  }
+  EXPECT_FALSE(it->HasError());
+  EXPECT_EQ(entries.size(), num_entries);
+}
+
 TEST_F(ResourceMetadataStorageTest, GetChildren) {
   const std::string parents_id[] = { "mercury", "venus", "mars", "jupiter",
                                      "saturn" };
@@ -190,7 +264,7 @@
     EXPECT_TRUE(storage_->PutEntry(entry));
   }
 
-  // Put some data.
+  // Put children.
   for (size_t i = 0; i < children_name_id.size(); ++i) {
     for (size_t j = 0; j < children_name_id[i].size(); ++j) {
       ResourceEntry entry;
@@ -201,6 +275,12 @@
     }
   }
 
+  // Put some dummy cache entries.
+  for (size_t i = 0; i < arraysize(parents_id); ++i) {
+    FileCacheEntry cache_entry;
+    EXPECT_TRUE(storage_->PutCacheEntry(parents_id[i], cache_entry));
+  }
+
   // Try to get children.
   for (size_t i = 0; i < children_name_id.size(); ++i) {
     std::vector<std::string> children;
@@ -231,7 +311,8 @@
   EXPECT_TRUE(storage_->PutEntry(entry2));
 
   // Close DB and reopen.
-  storage_.reset(new ResourceMetadataStorage(temp_dir_.path()));
+  storage_.reset(new ResourceMetadataStorage(
+      temp_dir_.path(), base::MessageLoopProxy::current()));
   ASSERT_TRUE(storage_->Initialize());
 
   // Can read data.
@@ -262,7 +343,8 @@
 
   // Set incompatible version and reopen DB.
   SetDBVersion(ResourceMetadataStorage::kDBVersion - 1);
-  storage_.reset(new ResourceMetadataStorage(temp_dir_.path()));
+  storage_.reset(new ResourceMetadataStorage(
+      temp_dir_.path(), base::MessageLoopProxy::current()));
   ASSERT_TRUE(storage_->Initialize());
 
   // Data is erased because of the incompatible version.
@@ -275,7 +357,8 @@
   base::FilePath path;
   ASSERT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir_.path(), &path));
 
-  storage_.reset(new ResourceMetadataStorage(path));
+  storage_.reset(new ResourceMetadataStorage(
+      path, base::MessageLoopProxy::current()));
   // Cannot initialize DB beacause the path does not point a directory.
   ASSERT_FALSE(storage_->Initialize());
 }
@@ -335,6 +418,11 @@
   PutChild(key2, name3, key3);
   EXPECT_TRUE(CheckValidity());
 
+  // Add some cache entries.
+  FileCacheEntry cache_entry;
+  EXPECT_TRUE(storage_->PutCacheEntry(key1, cache_entry));
+  EXPECT_TRUE(storage_->PutCacheEntry(key2, cache_entry));
+
   // Remove key2.
   RemoveChild(key1, name2);
   EXPECT_FALSE(CheckValidity());
@@ -352,4 +440,5 @@
   EXPECT_TRUE(CheckValidity());
 }
 
+}  // namespace internal
 }  // namespace drive
diff --git a/chrome/browser/chromeos/drive/resource_metadata_unittest.cc b/chrome/browser/chromeos/drive/resource_metadata_unittest.cc
index 82801e8..27608c6 100644
--- a/chrome/browser/chromeos/drive/resource_metadata_unittest.cc
+++ b/chrome/browser/chromeos/drive/resource_metadata_unittest.cc
@@ -123,7 +123,20 @@
         content::BrowserThread::GetBlockingPool();
     blocking_task_runner_ =
         pool->GetSequencedTaskRunner(pool->GetSequenceToken());
-    resource_metadata_.reset(new ResourceMetadata(temp_dir_.path(),
+
+    metadata_storage_.reset(new ResourceMetadataStorage(
+        temp_dir_.path(), blocking_task_runner_));
+    bool success = false;
+    base::PostTaskAndReplyWithResult(
+        blocking_task_runner_,
+        FROM_HERE,
+        base::Bind(&ResourceMetadataStorage::Initialize,
+                   base::Unretained(metadata_storage_.get())),
+        google_apis::test_util::CreateCopyResultCallback(&success));
+    google_apis::test_util::RunBlockingPoolTask();
+    ASSERT_TRUE(success);
+
+    resource_metadata_.reset(new ResourceMetadata(metadata_storage_.get(),
                                                   blocking_task_runner_));
 
     FileError error = FILE_ERROR_FAILED;
@@ -144,6 +157,7 @@
   }
 
   virtual void TearDown() OVERRIDE {
+    metadata_storage_.reset();
     resource_metadata_.reset();
     base::ThreadRestrictions::SetIOAllowed(true);
   }
@@ -175,61 +189,36 @@
     return entries.Pass();
   }
 
+  content::TestBrowserThreadBundle thread_bundle_;
   base::ScopedTempDir temp_dir_;
   scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
+  scoped_ptr<ResourceMetadataStorage, test_util::DestroyHelperForTests>
+      metadata_storage_;
   scoped_ptr<ResourceMetadata, test_util::DestroyHelperForTests>
       resource_metadata_;
-
- private:
-  content::TestBrowserThreadBundle thread_bundle_;
 };
 
 TEST_F(ResourceMetadataTestOnUIThread, LargestChangestamp) {
-  scoped_ptr<ResourceMetadata, test_util::DestroyHelperForTests>
-      resource_metadata(new ResourceMetadata(temp_dir_.path(),
-                                             blocking_task_runner_));
   FileError error = FILE_ERROR_FAILED;
-  base::PostTaskAndReplyWithResult(
-      blocking_task_runner_,
-      FROM_HERE,
-      base::Bind(&ResourceMetadata::Initialize,
-                 base::Unretained(resource_metadata.get())),
-      google_apis::test_util::CreateCopyResultCallback(&error));
-  google_apis::test_util::RunBlockingPoolTask();
-  ASSERT_EQ(FILE_ERROR_OK, error);
-
   int64 in_changestamp = 123456;
-  resource_metadata->SetLargestChangestampOnUIThread(
+  resource_metadata_->SetLargestChangestampOnUIThread(
       in_changestamp,
       google_apis::test_util::CreateCopyResultCallback(&error));
   google_apis::test_util::RunBlockingPoolTask();
   EXPECT_EQ(FILE_ERROR_OK, error);
 
   int64 out_changestamp = 0;
-  resource_metadata->GetLargestChangestampOnUIThread(
+  resource_metadata_->GetLargestChangestampOnUIThread(
       google_apis::test_util::CreateCopyResultCallback(&out_changestamp));
   google_apis::test_util::RunBlockingPoolTask();
   DCHECK_EQ(in_changestamp, out_changestamp);
 }
 
 TEST_F(ResourceMetadataTestOnUIThread, GetResourceEntryById_RootDirectory) {
-  scoped_ptr<ResourceMetadata, test_util::DestroyHelperForTests>
-      resource_metadata(new ResourceMetadata(temp_dir_.path(),
-                                             blocking_task_runner_));
-  FileError error = FILE_ERROR_FAILED;
-  base::PostTaskAndReplyWithResult(
-      blocking_task_runner_,
-      FROM_HERE,
-      base::Bind(&ResourceMetadata::Initialize,
-                 base::Unretained(resource_metadata.get())),
-      google_apis::test_util::CreateCopyResultCallback(&error));
-  google_apis::test_util::RunBlockingPoolTask();
-  ASSERT_EQ(FILE_ERROR_OK, error);
-
-  scoped_ptr<ResourceEntry> entry;
-
   // Look up the root directory by its resource ID.
-  resource_metadata->GetResourceEntryByIdOnUIThread(
+  FileError error = FILE_ERROR_FAILED;
+  scoped_ptr<ResourceEntry> entry;
+  resource_metadata_->GetResourceEntryByIdOnUIThread(
       util::kDriveGrandRootSpecialResourceId,
       google_apis::test_util::CreateCopyResultCallback(&error, &entry));
   google_apis::test_util::RunBlockingPoolTask();
@@ -524,13 +513,13 @@
           &error, &drive_file_path));
   google_apis::test_util::RunBlockingPoolTask();
   EXPECT_EQ(FILE_ERROR_OK, error);
-  EXPECT_EQ(base::FilePath::FromUTF8Unsafe("drive/root/dir2/file7 (2)"),
+  EXPECT_EQ(base::FilePath::FromUTF8Unsafe("drive/root/dir2/file7 (1)"),
             drive_file_path);
 
   // Rename to same name. This should fail.
   resource_metadata_->RenameEntryOnUIThread(
-      base::FilePath::FromUTF8Unsafe("drive/root/dir2/file7 (2)"),
-      "file7 (2)",
+      base::FilePath::FromUTF8Unsafe("drive/root/dir2/file7 (1)"),
+      "file7 (1)",
       google_apis::test_util::CreateCopyResultCallback(
           &error, &drive_file_path));
   google_apis::test_util::RunBlockingPoolTask();
@@ -869,20 +858,22 @@
   virtual void SetUp() OVERRIDE {
     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
 
-    // Use the main thread as the blocking task runner.
-    resource_metadata_.reset(new ResourceMetadata(
+    metadata_storage_.reset(new ResourceMetadataStorage(
         temp_dir_.path(), base::MessageLoopProxy::current()));
+    ASSERT_TRUE(metadata_storage_->Initialize());
+
+    resource_metadata_.reset(new ResourceMetadata(
+        metadata_storage_.get(), base::MessageLoopProxy::current()));
 
     ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->Initialize());
 
     SetUpEntries(resource_metadata_.get());
   }
 
-  virtual void TearDown() OVERRIDE {
-  }
-
   base::ScopedTempDir temp_dir_;
   content::TestBrowserThreadBundle thread_bundle_;
+  scoped_ptr<ResourceMetadataStorage, test_util::DestroyHelperForTests>
+      metadata_storage_;
   scoped_ptr<ResourceMetadata, test_util::DestroyHelperForTests>
       resource_metadata_;
 };
diff --git a/chrome/browser/chromeos/drive/search_metadata.cc b/chrome/browser/chromeos/drive/search_metadata.cc
index 9df8abb..b0824f9 100644
--- a/chrome/browser/chromeos/drive/search_metadata.cc
+++ b/chrome/browser/chromeos/drive/search_metadata.cc
@@ -8,8 +8,7 @@
 #include <queue>
 
 #include "base/bind.h"
-#include "base/i18n/string_search.h"
-#include "base/strings/utf_string_conversions.h"
+#include "base/strings/string_util.h"
 #include "chrome/browser/chromeos/drive/file_cache.h"
 #include "chrome/browser/chromeos/drive/file_system_util.h"
 #include "content/public/browser/browser_thread.h"
@@ -177,7 +176,7 @@
     results->push_back(*result_candidates.top());
 
   // Reverse the order here because |result_candidates| puts the most
-  // uninterested candidate at the top.
+  // uninteresting candidate at the top.
   std::reverse(results->begin(), results->end());
 
   return results.Pass();
@@ -219,22 +218,21 @@
   if (query.empty())
     return true;
 
-  string16 text16 = base::UTF8ToUTF16(text);
-  string16 query16 = base::UTF8ToUTF16(query);
-  size_t match_start = 0;
-  size_t match_length = 0;
-  if (!base::i18n::StringSearchIgnoringCaseAndAccents(
-      query16, text16, &match_start, &match_length)) {
+  // TODO(kinaba): Should support non-ASCII characters.
+  std::string lower_text = StringToLowerASCII(text);
+  std::string lower_query = StringToLowerASCII(query);
+  std::string::size_type match_start = lower_text.find(lower_query);
+  if (match_start == std::string::npos)
     return false;
-  }
-  string16 pre = text16.substr(0, match_start);
-  string16 match = text16.substr(match_start, match_length);
-  string16 post = text16.substr(match_start + match_length);
-  highlighted_text->append(net::EscapeForHTML(UTF16ToUTF8(pre)));
+
+  std::string pre = text.substr(0, match_start);
+  std::string match = text.substr(match_start, query.size());
+  std::string post = text.substr(match_start + query.size());
+  highlighted_text->append(net::EscapeForHTML(pre));
   highlighted_text->append("<b>");
-  highlighted_text->append(net::EscapeForHTML(UTF16ToUTF8(match)));
+  highlighted_text->append(net::EscapeForHTML(match));
   highlighted_text->append("</b>");
-  highlighted_text->append(net::EscapeForHTML(UTF16ToUTF8(post)));
+  highlighted_text->append(net::EscapeForHTML(post));
   return true;
 }
 
diff --git a/chrome/browser/chromeos/drive/search_metadata.h b/chrome/browser/chromeos/drive/search_metadata.h
index 9a6d5bf..e250a09 100644
--- a/chrome/browser/chromeos/drive/search_metadata.h
+++ b/chrome/browser/chromeos/drive/search_metadata.h
@@ -37,7 +37,7 @@
 // Returns true if |query| is found. |highlighted_text| will have the original
 // text with matched portions highlighted with <b> tag (only the first match
 // is highlighted). Meta characters are escaped like &lt;. The original
-// contents of |highlighted| will be lost.
+// contents of |highlighted_text| will be lost.
 bool FindAndHighlight(const std::string& text,
                       const std::string& query,
                       std::string* highlighted_text);
diff --git a/chrome/browser/chromeos/drive/search_metadata_unittest.cc b/chrome/browser/chromeos/drive/search_metadata_unittest.cc
index 94c2074..645ccb5 100644
--- a/chrome/browser/chromeos/drive/search_metadata_unittest.cc
+++ b/chrome/browser/chromeos/drive/search_metadata_unittest.cc
@@ -67,14 +67,18 @@
     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
     fake_free_disk_space_getter_.reset(new FakeFreeDiskSpaceGetter);
 
-    cache_.reset(new internal::FileCache(temp_dir_.path(),
-                                         temp_dir_.path(),
-                                         base::MessageLoopProxy::current(),
-                                         fake_free_disk_space_getter_.get()));
+    metadata_storage_.reset(new ResourceMetadataStorage(
+        temp_dir_.path(), base::MessageLoopProxy::current()));
+    ASSERT_TRUE(metadata_storage_->Initialize());
+
+    cache_.reset(new FileCache(metadata_storage_.get(),
+                               temp_dir_.path(),
+                               base::MessageLoopProxy::current(),
+                               fake_free_disk_space_getter_.get()));
     ASSERT_TRUE(cache_->Initialize());
 
     resource_metadata_.reset(
-        new ResourceMetadata(temp_dir_.path(),
+        new ResourceMetadata(metadata_storage_.get(),
                              base::MessageLoopProxy::current()));
     ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->Initialize());
 
@@ -188,6 +192,8 @@
   content::TestBrowserThreadBundle thread_bundle_;
   base::ScopedTempDir temp_dir_;
   scoped_ptr<FakeFreeDiskSpaceGetter> fake_free_disk_space_getter_;
+  scoped_ptr<ResourceMetadataStorage,
+             test_util::DestroyHelperForTests> metadata_storage_;
   scoped_ptr<ResourceMetadata, test_util::DestroyHelperForTests>
       resource_metadata_;
   scoped_ptr<FileCache, test_util::DestroyHelperForTests> cache_;
@@ -552,28 +558,6 @@
   EXPECT_EQ("<b>HeLLo</b>", highlighted_text);
 }
 
-TEST(SearchMetadataSimpleTest, FindAndHighlight_IgnoreCaseNonASCII) {
-  std::string highlighted_text;
-
-  // Case and accent ignorance in Greek. Find "socra" in "Socra'tes".
-  EXPECT_TRUE(FindAndHighlight(
-      "\xCE\xA3\xCF\x89\xCE\xBA\xCF\x81\xCE\xAC\xCF\x84\xCE\xB7\xCF\x82",
-      "\xCF\x83\xCF\x89\xCE\xBA\xCF\x81\xCE\xB1", &highlighted_text));
-  EXPECT_EQ(
-      "<b>\xCE\xA3\xCF\x89\xCE\xBA\xCF\x81\xCE\xAC</b>\xCF\x84\xCE\xB7\xCF\x82",
-      highlighted_text);
-
-  // In Japanese characters.
-  // Find Hiragana "pi" + "(small)ya" in Katakana "hi" + semi-voiced-mark + "ya"
-  EXPECT_TRUE(FindAndHighlight(
-      "\xE3\x81\xB2\xE3\x82\x9A\xE3\x82\x83\xE3\x83\xBC",
-      "\xE3\x83\x94\xE3\x83\xA4",
-      &highlighted_text));
-  EXPECT_EQ(
-      "<b>\xE3\x81\xB2\xE3\x82\x9A\xE3\x82\x83</b>\xE3\x83\xBC",
-      highlighted_text);
-}
-
 TEST(SearchMetadataSimpleTest, FindAndHighlight_MetaChars) {
   std::string highlighted_text;
   EXPECT_TRUE(FindAndHighlight("<hello>", "hello", &highlighted_text));
diff --git a/chrome/browser/chromeos/drive/sync_client.cc b/chrome/browser/chromeos/drive/sync_client.cc
index 4d12ff3..fca455e 100644
--- a/chrome/browser/chromeos/drive/sync_client.cc
+++ b/chrome/browser/chromeos/drive/sync_client.cc
@@ -322,9 +322,15 @@
   if (error == FILE_ERROR_OK) {
     DVLOG(1) << "Uploaded " << resource_id;
   } else {
-    // TODO(satorux): We should re-queue if the error is recoverable.
-    LOG(WARNING) << "Failed to upload " << resource_id << ": "
-                 << FileErrorToString(error);
+    switch (error) {
+      case FILE_ERROR_NO_CONNECTION:
+        // Re-queue the task so that we'll retry once the connection is back.
+        AddTaskToQueue(UPLOAD, resource_id);
+        break;
+      default:
+        LOG(WARNING) << "Failed to upload " << resource_id << ": "
+                     << FileErrorToString(error);
+    }
   }
 }
 
diff --git a/chrome/browser/chromeos/drive/sync_client.h b/chrome/browser/chromeos/drive/sync_client.h
index a5a66e8..c9b6614 100644
--- a/chrome/browser/chromeos/drive/sync_client.h
+++ b/chrome/browser/chromeos/drive/sync_client.h
@@ -11,7 +11,7 @@
 
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/chromeos/drive/file_errors.h"
 
 namespace base {
diff --git a/chrome/browser/chromeos/drive/sync_client_unittest.cc b/chrome/browser/chromeos/drive/sync_client_unittest.cc
index 4aae520..ec76076 100644
--- a/chrome/browser/chromeos/drive/sync_client_unittest.cc
+++ b/chrome/browser/chromeos/drive/sync_client_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/test/test_timeouts.h"
 #include "chrome/browser/chromeos/drive/change_list_loader.h"
 #include "chrome/browser/chromeos/drive/drive.pb.h"
+#include "chrome/browser/chromeos/drive/fake_free_disk_space_getter.h"
 #include "chrome/browser/chromeos/drive/file_cache.h"
 #include "chrome/browser/chromeos/drive/file_system/operation_observer.h"
 #include "chrome/browser/chromeos/drive/job_scheduler.h"
@@ -29,7 +30,7 @@
 
 namespace {
 
-// The content of files iniitally stored in the cache.
+// The content of files initially stored in the cache.
 const char kLocalContent[] = "Hello!";
 
 // The content of files stored in the service.
@@ -37,22 +38,28 @@
 
 // SyncClientTestDriveService will return GDATA_CANCELLED when a request is
 // made with the specified resource ID.
-class SyncClientTestDriveService : public google_apis::FakeDriveService {
+class SyncClientTestDriveService : public ::drive::FakeDriveService {
  public:
   // FakeDriveService override:
-  virtual google_apis::CancelCallback GetResourceEntry(
+  virtual google_apis::CancelCallback DownloadFile(
+      const base::FilePath& local_cache_path,
       const std::string& resource_id,
-      const google_apis::GetResourceEntryCallback& callback) OVERRIDE {
+      const google_apis::DownloadActionCallback& download_action_callback,
+      const google_apis::GetContentCallback& get_content_callback,
+      const google_apis::ProgressCallback& progress_callback) OVERRIDE {
     if (resource_id == resource_id_to_be_cancelled_) {
-      scoped_ptr<google_apis::ResourceEntry> null;
       base::MessageLoopProxy::current()->PostTask(
           FROM_HERE,
-          base::Bind(callback,
+          base::Bind(download_action_callback,
                      google_apis::GDATA_CANCELLED,
-                     base::Passed(&null)));
+                     base::FilePath()));
       return google_apis::CancelCallback();
     }
-    return FakeDriveService::GetResourceEntry(resource_id, callback);
+    return FakeDriveService::DownloadFile(local_cache_path,
+                                          resource_id,
+                                          download_action_callback,
+                                          get_content_callback,
+                                          progress_callback);
   }
 
   void set_resource_id_to_be_cancelled(const std::string& resource_id) {
@@ -80,17 +87,26 @@
 
     profile_.reset(new TestingProfile);
 
-    drive_service_.reset(new SyncClientTestDriveService);
-    drive_service_->LoadResourceListForWapi("chromeos/gdata/empty_feed.json");
-    drive_service_->LoadAccountMetadataForWapi(
-        "chromeos/gdata/account_metadata.json");
+    fake_network_change_notifier_.reset(
+        new test_util::FakeNetworkChangeNotifier);
 
-    scheduler_.reset(new JobScheduler(profile_.get(), drive_service_.get()));
-    metadata_.reset(new internal::ResourceMetadata(
+    drive_service_.reset(new SyncClientTestDriveService);
+    drive_service_->LoadResourceListForWapi("gdata/empty_feed.json");
+    drive_service_->LoadAccountMetadataForWapi(
+        "gdata/account_metadata.json");
+
+    scheduler_.reset(new JobScheduler(profile_.get(), drive_service_.get(),
+                                      base::MessageLoopProxy::current()));
+
+    metadata_storage_.reset(new ResourceMetadataStorage(
         temp_dir_.path(), base::MessageLoopProxy::current()));
+    ASSERT_TRUE(metadata_storage_->Initialize());
+
+    metadata_.reset(new internal::ResourceMetadata(
+        metadata_storage_.get(), base::MessageLoopProxy::current()));
     ASSERT_EQ(FILE_ERROR_OK, metadata_->Initialize());
 
-    cache_.reset(new FileCache(temp_dir_.path(),
+    cache_.reset(new FileCache(metadata_storage_.get(),
                                temp_dir_.path(),
                                base::MessageLoopProxy::current(),
                                NULL /* free_disk_space_getter */));
@@ -109,12 +125,6 @@
     sync_client_->set_delay_for_testing(base::TimeDelta::FromSeconds(0));
   }
 
-  virtual void TearDown() OVERRIDE {
-    sync_client_.reset();
-    cache_.reset();
-    metadata_.reset();
-  }
-
   // Adds a file to the service root and |resource_ids_|.
   void AddFileEntry(const std::string& title) {
     google_apis::GDataErrorCode error = google_apis::GDATA_FILE_ERROR;
@@ -184,11 +194,14 @@
   content::TestBrowserThreadBundle thread_bundle_;
   base::ScopedTempDir temp_dir_;
   scoped_ptr<TestingProfile> profile_;
+  scoped_ptr<test_util::FakeNetworkChangeNotifier>
+      fake_network_change_notifier_;
   scoped_ptr<SyncClientTestDriveService> drive_service_;
   DummyOperationObserver observer_;
   scoped_ptr<JobScheduler> scheduler_;
-  scoped_ptr<internal::ResourceMetadata, test_util::DestroyHelperForTests>
-      metadata_;
+  scoped_ptr<ResourceMetadataStorage,
+             test_util::DestroyHelperForTests> metadata_storage_;
+  scoped_ptr<ResourceMetadata, test_util::DestroyHelperForTests> metadata_;
   scoped_ptr<FileCache, test_util::DestroyHelperForTests> cache_;
   scoped_ptr<SyncClient> sync_client_;
 
@@ -288,5 +301,48 @@
   EXPECT_EQ(kLocalContent, content);
 }
 
+TEST_F(SyncClientTest, RetryOnDisconnection) {
+  // Let the service go down.
+  drive_service_->set_offline(true);
+  // Change the network connection state after some delay, to test that
+  // FILE_ERROR_NO_CONNECTION is handled by SyncClient correctly.
+  // Without this delay, JobScheduler will keep the jobs unrun and SyncClient
+  // will receive no error.
+  base::MessageLoopProxy::current()->PostDelayedTask(
+      FROM_HERE,
+      base::Bind(&test_util::FakeNetworkChangeNotifier::SetConnectionType,
+                 base::Unretained(fake_network_change_notifier_.get()),
+                 net::NetworkChangeNotifier::CONNECTION_NONE),
+      TestTimeouts::tiny_timeout());
+
+  // Try fetch and upload.
+  sync_client_->AddFetchTask(resource_ids_["foo"]);
+  sync_client_->AddUploadTask(resource_ids_["dirty"]);
+  base::RunLoop().RunUntilIdle();
+
+  // Not yet fetched nor uploaded.
+  FileCacheEntry cache_entry;
+  EXPECT_TRUE(cache_->GetCacheEntry(resource_ids_["foo"], std::string(),
+                                    &cache_entry));
+  EXPECT_FALSE(cache_entry.is_present());
+  EXPECT_TRUE(cache_->GetCacheEntry(resource_ids_["dirty"], std::string(),
+                                    &cache_entry));
+  EXPECT_TRUE(cache_entry.is_dirty());
+
+  // Switch to online.
+  fake_network_change_notifier_->SetConnectionType(
+      net::NetworkChangeNotifier::CONNECTION_WIFI);
+  drive_service_->set_offline(false);
+  base::RunLoop().RunUntilIdle();
+
+  // Fetched and uploaded.
+  EXPECT_TRUE(cache_->GetCacheEntry(resource_ids_["foo"], std::string(),
+                                    &cache_entry));
+  EXPECT_TRUE(cache_entry.is_present());
+  EXPECT_TRUE(cache_->GetCacheEntry(resource_ids_["dirty"], std::string(),
+                                    &cache_entry));
+  EXPECT_FALSE(cache_entry.is_dirty());
+}
+
 }  // namespace internal
 }  // namespace drive
diff --git a/chrome/browser/chromeos/drive/test_util.cc b/chrome/browser/chromeos/drive/test_util.cc
index 93307a2..8caaa31 100644
--- a/chrome/browser/chromeos/drive/test_util.cc
+++ b/chrome/browser/chromeos/drive/test_util.cc
@@ -123,5 +123,19 @@
   return true;
 }
 
+FakeNetworkChangeNotifier::FakeNetworkChangeNotifier()
+    : type_(CONNECTION_WIFI) {
+}
+
+void FakeNetworkChangeNotifier::SetConnectionType(ConnectionType type) {
+  type_ = type;
+  NotifyObserversOfConnectionTypeChange();
+}
+
+net::NetworkChangeNotifier::ConnectionType
+FakeNetworkChangeNotifier::GetCurrentConnectionType() const {
+  return type_;
+}
+
 }  // namespace test_util
 }  // namespace drive
diff --git a/chrome/browser/chromeos/drive/test_util.h b/chrome/browser/chromeos/drive/test_util.h
index 3fa88b0..823ffd7 100644
--- a/chrome/browser/chromeos/drive/test_util.h
+++ b/chrome/browser/chromeos/drive/test_util.h
@@ -12,6 +12,7 @@
 #include "chrome/browser/google_apis/test_util.h"
 #include "net/base/completion_callback.h"
 #include "net/base/io_buffer.h"
+#include "net/base/network_change_notifier.h"
 #include "net/base/test_completion_callback.h"
 
 namespace net {
@@ -81,6 +82,20 @@
     internal::FileCache* cache,
     const std::vector<TestCacheResource>& resources);
 
+// Fake NetworkChangeNotifier implementation.
+class FakeNetworkChangeNotifier : public net::NetworkChangeNotifier {
+ public:
+  FakeNetworkChangeNotifier();
+
+  void SetConnectionType(ConnectionType type);
+
+  // NetworkChangeNotifier override.
+  virtual ConnectionType GetCurrentConnectionType() const OVERRIDE;
+
+ private:
+  net::NetworkChangeNotifier::ConnectionType type_;
+};
+
 }  // namespace test_util
 }  // namespace drive
 
diff --git a/chrome/browser/chromeos/drive/webkit_file_stream_reader_impl.h b/chrome/browser/chromeos/drive/webkit_file_stream_reader_impl.h
index 0f94eb7..f0a7c2f 100644
--- a/chrome/browser/chromeos/drive/webkit_file_stream_reader_impl.h
+++ b/chrome/browser/chromeos/drive/webkit_file_stream_reader_impl.h
@@ -10,7 +10,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/chromeos/drive/drive_file_stream_reader.h"
 #include "net/base/completion_callback.h"
 #include "webkit/browser/blob/file_stream_reader.h"
diff --git a/chrome/browser/chromeos/drive/webkit_file_stream_reader_impl_unittest.cc b/chrome/browser/chromeos/drive/webkit_file_stream_reader_impl_unittest.cc
index 48e8307..1392ac5 100644
--- a/chrome/browser/chromeos/drive/webkit_file_stream_reader_impl_unittest.cc
+++ b/chrome/browser/chromeos/drive/webkit_file_stream_reader_impl_unittest.cc
@@ -11,7 +11,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/message_loop.h"
 #include "base/threading/thread.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/chromeos/drive/fake_file_system.h"
 #include "chrome/browser/chromeos/drive/file_system_interface.h"
 #include "chrome/browser/chromeos/drive/file_system_util.h"
@@ -40,11 +40,11 @@
     ASSERT_TRUE(worker_thread_->Start());
 
     // Initialize FakeDriveService.
-    fake_drive_service_.reset(new google_apis::FakeDriveService);
+    fake_drive_service_.reset(new FakeDriveService);
     fake_drive_service_->LoadResourceListForWapi(
-        "chromeos/gdata/root_feed.json");
+        "gdata/root_feed.json");
     fake_drive_service_->LoadAccountMetadataForWapi(
-        "chromeos/gdata/account_metadata.json");
+        "gdata/account_metadata.json");
 
     // Create a testee instance.
     fake_file_system_.reset(
@@ -52,13 +52,6 @@
     fake_file_system_->Initialize();
   }
 
-  virtual void TearDown() OVERRIDE {
-    fake_file_system_.reset();
-    fake_drive_service_.reset();
-
-    worker_thread_.reset();
-  }
-
   FileSystemInterface* GetFileSystem() {
     return fake_file_system_.get();
   }
@@ -72,7 +65,7 @@
 
   scoped_ptr<base::Thread> worker_thread_;
 
-  scoped_ptr<google_apis::FakeDriveService> fake_drive_service_;
+  scoped_ptr<FakeDriveService> fake_drive_service_;
   scoped_ptr<test_util::FakeFileSystem> fake_file_system_;
 };
 
diff --git a/chrome/browser/chromeos/extensions/OWNERS b/chrome/browser/chromeos/extensions/OWNERS
index 838137a..d85d766 100644
--- a/chrome/browser/chromeos/extensions/OWNERS
+++ b/chrome/browser/chromeos/extensions/OWNERS
@@ -3,7 +3,6 @@
 benwells@chromium.org
 erikkay@chromium.org
 finnur@chromium.org
-jeremya@chromium.org
 jyasskin@chromium.org
 kalman@chromium.org
 koz@chromium.org
diff --git a/chrome/browser/chromeos/extensions/default_app_order.cc b/chrome/browser/chromeos/extensions/default_app_order.cc
index 7a8551e..4ffc078 100644
--- a/chrome/browser/chromeos/extensions/default_app_order.cc
+++ b/chrome/browser/chromeos/extensions/default_app_order.cc
@@ -10,7 +10,7 @@
 #include "base/files/file_path.h"
 #include "base/json/json_file_value_serializer.h"
 #include "base/path_service.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "chromeos/chromeos_paths.h"
 #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/chromeos/extensions/echo_private_api.cc b/chrome/browser/chromeos/extensions/echo_private_api.cc
index 5580cc2..edf3f6f 100644
--- a/chrome/browser/chromeos/extensions/echo_private_api.cc
+++ b/chrome/browser/chromeos/extensions/echo_private_api.cc
@@ -11,7 +11,7 @@
 #include "base/location.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
 #include "chrome/browser/chromeos/system/statistics_provider.h"
@@ -51,9 +51,7 @@
   }
   // Possible ECHO code type and corresponding key name in StatisticsProvider.
   const std::string kCouponType = "COUPON_CODE";
-  const std::string kCouponCodeKey = "ubind_attribute";
   const std::string kGroupType = "GROUP_CODE";
-  const std::string kGroupCodeKey = "gbind_attribute";
 
   chromeos::system::StatisticsProvider* provider =
       chromeos::system::StatisticsProvider::GetInstance();
@@ -61,10 +59,13 @@
   if (!chromeos::KioskModeSettings::Get()->IsKioskModeEnabled()) {
     // In Kiosk mode, we effectively disable the registration API
     // by always returning an empty code.
-    if (type == kCouponType)
-      provider->GetMachineStatistic(kCouponCodeKey, &result);
-    else if (type == kGroupType)
-      provider->GetMachineStatistic(kGroupCodeKey, &result);
+    if (type == kCouponType) {
+      provider->GetMachineStatistic(chromeos::system::kOffersCouponCodeKey,
+                                    &result);
+    } else if (type == kGroupType) {
+      provider->GetMachineStatistic(chromeos::system::kOffersGroupCodeKey,
+                                    &result);
+    }
   }
 
   results_ = echo_api::GetRegistrationCode::Results::Create(result);
diff --git a/chrome/browser/chromeos/extensions/file_manager/drive_test_util.cc b/chrome/browser/chromeos/extensions/file_manager/drive_test_util.cc
index 87aece5..4fe56ae 100644
--- a/chrome/browser/chromeos/extensions/file_manager/drive_test_util.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/drive_test_util.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/bind.h"
+#include "chrome/browser/chromeos/extensions/file_manager/drive_test_util.h"
+
 #include "base/files/file_path.h"
 #include "base/run_loop.h"
 #include "chrome/browser/chromeos/drive/drive_integration_service.h"
-#include "chrome/browser/chromeos/drive/file_system.h"
 #include "chrome/browser/profiles/profile.h"
 #include "content/public/browser/browser_context.h"
 #include "webkit/browser/fileapi/external_mount_points.h"
@@ -15,8 +15,6 @@
 
 namespace {
 
-const char kDriveMountPointName[] = "drive";
-
 // Helper class used to wait for |OnFileSystemMounted| event from a drive file
 // system.
 class DriveMountPointWaiter : public drive::DriveIntegrationServiceObserver {
@@ -65,16 +63,18 @@
           profile);
   DCHECK(integration_service);
 
-  DriveMountPointWaiter mount_point_waiter(integration_service);
-
+  const std::string drive_mount_point_name =
+      drive::util::GetDriveMountPointPath().BaseName().AsUTF8Unsafe();
   base::FilePath ignored;
   // GetRegisteredPath succeeds iff the mount point exists.
-  if (!content::BrowserContext::GetMountPoints(profile)->
-      GetRegisteredPath(kDriveMountPointName, &ignored)) {
-    LOG(WARNING) << "Waiting for drive mount point to get mounted.";
-    mount_point_waiter.Wait();
-    LOG(WARNING) << "Drive mount point found.";
-  }
+  if (content::BrowserContext::GetMountPoints(profile)->
+      GetRegisteredPath(drive_mount_point_name, &ignored))
+    return;
+
+  DriveMountPointWaiter mount_point_waiter(integration_service);
+  LOG(INFO) << "Waiting for drive mount point to get mounted.";
+  mount_point_waiter.Wait();
+  LOG(INFO) << "Drive mount point found.";
 }
 
 }  // namespace drive_test_util
diff --git a/chrome/browser/chromeos/extensions/file_manager/external_filesystem_apitest.cc b/chrome/browser/chromeos/extensions/file_manager/external_filesystem_apitest.cc
index 7e76626..ba56fda 100644
--- a/chrome/browser/chromeos/extensions/file_manager/external_filesystem_apitest.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/external_filesystem_apitest.cc
@@ -6,32 +6,15 @@
 #include "base/file_util.h"
 #include "base/files/file_path.h"
 #include "base/files/scoped_temp_dir.h"
-#include "base/json/json_file_value_serializer.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop_proxy.h"
-#include "base/path_service.h"
-#include "base/threading/worker_pool.h"
-#include "base/values.h"
 #include "chrome/browser/chromeos/drive/drive_integration_service.h"
-#include "chrome/browser/chromeos/drive/file_system.h"
 #include "chrome/browser/chromeos/extensions/file_manager/drive_test_util.h"
 #include "chrome/browser/drive/fake_drive_service.h"
-#include "chrome/browser/extensions/event_router.h"
 #include "chrome/browser/extensions/extension_apitest.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/extensions/extension_system.h"
-#include "chrome/browser/extensions/extension_test_message_listener.h"
-#include "chrome/browser/google_apis/gdata_wapi_parser.h"
 #include "chrome/browser/google_apis/test_util.h"
-#include "chrome/browser/google_apis/time_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/common/chrome_notification_types.h"
-#include "chrome/common/chrome_paths.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/browser_context.h"
-#include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/test/test_utils.h"
 #include "webkit/browser/fileapi/external_mount_points.h"
@@ -60,7 +43,6 @@
 // - Doing searches on drive file system from file browser extension (using
 //   fileBrowserPrivate API).
 
-using content::BrowserContext;
 using extensions::Extension;
 
 namespace {
@@ -94,15 +76,7 @@
 // All files except test_dir/empty_file.foo, which is empty, initially contain
 // kTestFileContent.
 const char kTestRootFeed[] =
-    "chromeos/gdata/remote_file_system_apitest_root_feed.json";
-
-// Creates a test file with predetermined content. Returns true on success.
-bool CreateFileWithContent(const base::FilePath& path,
-                           const std::string& content) {
-  int content_size = static_cast<int>(content.length());
-  int written = file_util::WriteFile(path, content.c_str(), content_size);
-  return written == content_size;
-}
+    "gdata/remote_file_system_apitest_root_feed.json";
 
 // Sets up the initial file system state for native local and restricted native
 // local file systems. The hierarchy is the same as for the drive file system.
@@ -111,16 +85,16 @@
   if (!tmp_dir->CreateUniqueTempDir())
     return false;
 
-  *mount_point_dir = tmp_dir->path().Append("mount");
+  *mount_point_dir = tmp_dir->path().AppendASCII("mount");
   // Create the mount point.
   if (!file_util::CreateDirectory(*mount_point_dir))
     return false;
 
-  base::FilePath test_dir = mount_point_dir->Append("test_dir");
+  base::FilePath test_dir = mount_point_dir->AppendASCII("test_dir");
   if (!file_util::CreateDirectory(test_dir))
     return false;
 
-  base::FilePath test_subdir = test_dir.Append("empty_test_dir");
+  base::FilePath test_subdir = test_dir.AppendASCII("empty_test_dir");
   if (!file_util::CreateDirectory(test_subdir))
     return false;
 
@@ -129,23 +103,23 @@
     return false;
 
   base::FilePath test_file = test_dir.AppendASCII("test_file.xul");
-  if (!CreateFileWithContent(test_file, kTestFileContent))
+  if (!google_apis::test_util::WriteStringToFile(test_file, kTestFileContent))
     return false;
 
   test_file = test_dir.AppendASCII("test_file.xul.foo");
-  if (!CreateFileWithContent(test_file, kTestFileContent))
+  if (!google_apis::test_util::WriteStringToFile(test_file, kTestFileContent))
     return false;
 
   test_file = test_dir.AppendASCII("test_file.tiff");
-  if (!CreateFileWithContent(test_file, kTestFileContent))
+  if (!google_apis::test_util::WriteStringToFile(test_file, kTestFileContent))
     return false;
 
   test_file = test_dir.AppendASCII("test_file.tiff.foo");
-  if (!CreateFileWithContent(test_file, kTestFileContent))
+  if (!google_apis::test_util::WriteStringToFile(test_file, kTestFileContent))
     return false;
 
   test_file = test_dir.AppendASCII("empty_test_file.foo");
-  if (!CreateFileWithContent(test_file, ""))
+  if (!google_apis::test_util::WriteStringToFile(test_file, ""))
     return false;
 
   return true;
@@ -273,8 +247,8 @@
   virtual void AddTestMountPoint() OVERRIDE {
     EXPECT_TRUE(content::BrowserContext::GetMountPoints(browser()->profile())->
         RegisterFileSystem(kLocalMountPointName,
-                            fileapi::kFileSystemTypeNativeLocal,
-                            mount_point_dir_));
+                           fileapi::kFileSystemTypeNativeLocal,
+                           mount_point_dir_));
   }
 
  private:
@@ -320,9 +294,7 @@
     // system service. This has to be done early on (before the browser is
     // created) because the system service instance is initialized very early
     // by FileManagerEventRouter.
-    base::FilePath tmp_dir_path;
-    PathService::Get(base::DIR_TEMP, &tmp_dir_path);
-    ASSERT_TRUE(test_cache_root_.CreateUniqueTempDirUnderPath(tmp_dir_path));
+    ASSERT_TRUE(test_cache_root_.CreateUniqueTempDir());
 
     drive::DriveIntegrationServiceFactory::SetFactoryForTest(
         base::Bind(
@@ -339,11 +311,11 @@
   // DriveIntegrationService factory function for this test.
   drive::DriveIntegrationService* CreateDriveIntegrationService(
       Profile* profile) {
-    fake_drive_service_ = new google_apis::FakeDriveService;
+    fake_drive_service_ = new drive::FakeDriveService;
     fake_drive_service_->LoadResourceListForWapi(kTestRootFeed);
     fake_drive_service_->LoadAccountMetadataForWapi(
-        "chromeos/gdata/account_metadata.json");
-    fake_drive_service_->LoadAppListForDriveApi("chromeos/drive/applist.json");
+        "gdata/account_metadata.json");
+    fake_drive_service_->LoadAppListForDriveApi("drive/applist.json");
 
     return new drive::DriveIntegrationService(profile,
                                               fake_drive_service_,
@@ -352,7 +324,7 @@
   }
 
   base::ScopedTempDir test_cache_root_;
-  google_apis::FakeDriveService* fake_drive_service_;
+  drive::FakeDriveService* fake_drive_service_;
 };
 
 //
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_browser_handler.cc b/chrome/browser/chromeos/extensions/file_manager/file_browser_handler.cc
index 715c0b6..ed894d3 100644
--- a/chrome/browser/chromeos/extensions/file_manager/file_browser_handler.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/file_browser_handler.cc
@@ -15,8 +15,6 @@
 #include "content/public/common/url_constants.h"
 #include "extensions/common/error_utils.h"
 #include "extensions/common/url_pattern.h"
-#include "googleurl/src/gurl.h"
-#include "googleurl/src/url_util.h"
 
 namespace keys = extension_manifest_keys;
 namespace errors = extension_manifest_errors;
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_browser_handler.h b/chrome/browser/chromeos/extensions/file_manager/file_browser_handler.h
index da1f4b2..7b9169c 100644
--- a/chrome/browser/chromeos/extensions/file_manager/file_browser_handler.h
+++ b/chrome/browser/chromeos/extensions/file_manager/file_browser_handler.h
@@ -5,7 +5,6 @@
 #ifndef CHROME_BROWSER_CHROMEOS_EXTENSIONS_FILE_MANAGER_FILE_BROWSER_HANDLER_H_
 #define CHROME_BROWSER_CHROMEOS_EXTENSIONS_FILE_MANAGER_FILE_BROWSER_HANDLER_H_
 
-#include <set>
 #include <string>
 #include <vector>
 
@@ -14,8 +13,8 @@
 #include "chrome/common/extensions/manifest_handler.h"
 #include "extensions/common/url_pattern.h"
 #include "extensions/common/url_pattern_set.h"
-#include "googleurl/src/gurl.h"
 
+class GURL;
 class URLPattern;
 
 // FileBrowserHandler encapsulates the state of a file browser action.
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_browser_handler_api.cc b/chrome/browser/chromeos/extensions/file_manager/file_browser_handler_api.cc
index 556f12a..cfe538b 100644
--- a/chrome/browser/chromeos/extensions/file_manager/file_browser_handler_api.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/file_browser_handler_api.cc
@@ -35,9 +35,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/message_loop/message_loop_proxy.h"
 #include "base/platform_file.h"
-#include "base/values.h"
 #include "chrome/browser/chromeos/extensions/file_manager/file_handler_util.h"
-#include "chrome/browser/chromeos/extensions/file_manager/file_manager_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_window.h"
@@ -49,7 +47,6 @@
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/storage_partition.h"
-#include "googleurl/src/gurl.h"
 #include "ui/shell_dialogs/select_file_dialog.h"
 #include "webkit/browser/fileapi/file_system_context.h"
 #include "webkit/browser/fileapi/file_system_mount_point_provider.h"
@@ -183,7 +180,7 @@
     // function.
     base::MessageLoopProxy::current()->PostTask(FROM_HERE,
         base::Bind(&FileSelectorImpl::FileSelectionCanceled,
-                   base::Unretained(this), reinterpret_cast<void*>(NULL)));
+                   base::Unretained(this), static_cast<void*>(NULL)));
   }
 }
 
@@ -401,7 +398,7 @@
     result->entry.reset(new FileEntryInfo());
     result->entry->file_system_name = file_system_name_;
     result->entry->file_system_root = file_system_root_.spec();
-    result->entry->file_full_path = "/" + virtual_path_.value();
+    result->entry->file_full_path = "/" + virtual_path_.AsUTF8Unsafe();
     result->entry->file_is_directory = false;
   }
 
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_browser_handler_api_test.cc b/chrome/browser/chromeos/extensions/file_manager/file_browser_handler_api_test.cc
index c330c7b..6f827f7 100644
--- a/chrome/browser/chromeos/extensions/file_manager/file_browser_handler_api_test.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/file_browser_handler_api_test.cc
@@ -10,12 +10,9 @@
 
 #include "base/bind.h"
 #include "base/files/scoped_temp_dir.h"
-#include "base/path_service.h"
 #include "base/values.h"
 #include "chrome/browser/extensions/extension_apitest.h"
 #include "chrome/browser/extensions/extension_function_test_utils.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/extensions/extension_system.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/common/extensions/extension.h"
@@ -137,7 +134,7 @@
   }
   virtual ~MockFileSelectorFactory() {}
 
-  // file_handler::FileSelectorFactory imaplementation.
+  // file_handler::FileSelectorFactory implementation.
   virtual file_handler::FileSelector* CreateFileSelector() const OVERRIDE {
     return new MockFileSelector(suggested_name_,
                                 allowed_extensions_,
@@ -165,9 +162,7 @@
     // Create mount point directory that will be used in the test.
     // Mount point will be called "tmp", and it will be located in a tmp
     // directory with an unique name.
-    base::FilePath tmp_dir_path;
-    PathService::Get(base::DIR_TEMP, &tmp_dir_path);
-    ASSERT_TRUE(scoped_tmp_dir_.CreateUniqueTempDirUnderPath(tmp_dir_path));
+    ASSERT_TRUE(scoped_tmp_dir_.CreateUniqueTempDir());
     tmp_mount_point_ = scoped_tmp_dir_.path().Append("tmp");
     file_util::CreateDirectory(tmp_mount_point_);
 
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_browser_private_api.cc b/chrome/browser/chromeos/extensions/file_manager/file_browser_private_api.cc
index f5bc671..fe15db1 100644
--- a/chrome/browser/chromeos/extensions/file_manager/file_browser_private_api.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/file_browser_private_api.cc
@@ -20,7 +20,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/sequenced_worker_pool.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/chromeos/drive/drive.pb.h"
 #include "chrome/browser/chromeos/drive/drive_app_registry.h"
@@ -35,6 +35,7 @@
 #include "chrome/browser/chromeos/extensions/file_manager/file_manager_event_router.h"
 #include "chrome/browser/chromeos/extensions/file_manager/file_manager_util.h"
 #include "chrome/browser/chromeos/extensions/file_manager/zip_file_creator.h"
+#include "chrome/browser/chromeos/fileapi/cros_mount_point_provider.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
 #include "chrome/browser/chromeos/system/statistics_provider.h"
 #include "chrome/browser/extensions/api/file_handlers/app_file_handler_util.h"
@@ -59,6 +60,7 @@
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/storage_partition.h"
+#include "content/public/common/page_zoom.h"
 #include "googleurl/src/gurl.h"
 #include "grit/app_locale_settings.h"
 #include "grit/generated_resources.h"
@@ -67,7 +69,6 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/shell_dialogs/selected_file_info.h"
 #include "ui/webui/web_ui_util.h"
-#include "webkit/browser/chromeos/fileapi/cros_mount_point_provider.h"
 #include "webkit/browser/fileapi/file_system_context.h"
 #include "webkit/browser/fileapi/file_system_file_util.h"
 #include "webkit/browser/fileapi/file_system_operation_context.h"
@@ -356,10 +357,9 @@
       entry_proto.file_specific_info();
 
   property_dict->SetString("thumbnailUrl", file_specific_info.thumbnail_url());
-
+  property_dict->SetString("shareUrl", file_specific_info.share_url());
   property_dict->SetBoolean("isHosted",
                             file_specific_info.is_hosted_document());
-
   property_dict->SetString("contentMimeType",
                            file_specific_info.content_mime_type());
 }
@@ -452,8 +452,7 @@
   registry->RegisterFunction<SetLastModifiedFunction>();
   registry->RegisterFunction<ZipSelectionFunction>();
   registry->RegisterFunction<ValidatePathNameLengthFunction>();
-  registry->RegisterFunction<OpenNewWindowFunction>();
-
+  registry->RegisterFunction<ZoomFunction>();
   event_router_->ObserveFileSystemEvents();
 }
 
@@ -1875,6 +1874,7 @@
   SET_STRING("GALLERY_SLIDESHOW", IDS_FILE_BROWSER_GALLERY_SLIDESHOW);
 
   SET_STRING("GALLERY_EDIT", IDS_FILE_BROWSER_GALLERY_EDIT);
+  SET_STRING("GALLERY_PRINT", IDS_FILE_BROWSER_GALLERY_PRINT);
   SET_STRING("GALLERY_SHARE", IDS_FILE_BROWSER_GALLERY_SHARE);
   SET_STRING("GALLERY_ENTER_WHEN_DONE",
              IDS_FILE_BROWSER_GALLERY_ENTER_WHEN_DONE);
@@ -1904,6 +1904,8 @@
   SET_STRING("GALLERY_VIDEO_ERROR", IDS_FILE_BROWSER_GALLERY_VIDEO_ERROR);
   SET_STRING("GALLERY_VIDEO_DECODING_ERROR",
              IDS_FILE_BROWSER_GALLERY_VIDEO_DECODING_ERROR);
+  SET_STRING("GALLERY_VIDEO_LOOPED_MODE",
+             IDS_FILE_BROWSER_GALLERY_VIDEO_LOOPED_MODE);
   SET_STRING("AUDIO_ERROR", IDS_FILE_BROWSER_AUDIO_ERROR);
   SET_STRING("GALLERY_IMAGE_OFFLINE", IDS_FILE_BROWSER_GALLERY_IMAGE_OFFLINE);
   SET_STRING("GALLERY_VIDEO_OFFLINE", IDS_FILE_BROWSER_GALLERY_VIDEO_OFFLINE);
@@ -1995,6 +1997,8 @@
   SET_STRING("CUT_BUTTON_LABEL", IDS_FILE_BROWSER_CUT_BUTTON_LABEL);
   SET_STRING("ZIP_SELECTION_BUTTON_LABEL",
              IDS_FILE_BROWSER_ZIP_SELECTION_BUTTON_LABEL);
+  SET_STRING("SHARE_BUTTON_LABEL",
+             IDS_FILE_BROWSER_SHARE_BUTTON_LABEL);
 
   SET_STRING("OPEN_WITH_BUTTON_LABEL", IDS_FILE_BROWSER_OPEN_WITH_BUTTON_LABEL);
 
@@ -2113,6 +2117,8 @@
   SET_STRING("DRIVE_WELCOME_CHECK_ELIGIBILITY",
              IDS_FILE_BROWSER_DRIVE_WELCOME_CHECK_ELIGIBILITY);
   SET_STRING("NO_ACTION_FOR_FILE", IDS_FILE_BROWSER_NO_ACTION_FOR_FILE);
+  SET_STRING("NO_ACTION_FOR_EXECUTABLE",
+             IDS_FILE_BROWSER_NO_ACTION_FOR_EXECUTABLE);
 
   // MP3 metadata extractor plugin
   SET_STRING("ID3_ALBUM", IDS_FILE_BROWSER_ID3_ALBUM);                // TALB
@@ -2255,13 +2261,13 @@
 #endif
 
   std::string board;
-  const char kMachineInfoBoard[] = "CHROMEOS_RELEASE_BOARD";
   chromeos::system::StatisticsProvider* provider =
       chromeos::system::StatisticsProvider::GetInstance();
-  if (!provider->GetMachineStatistic(kMachineInfoBoard, &board))
+  if (!provider->GetMachineStatistic(chromeos::system::kMachineInfoBoard,
+                                     &board)) {
     board = "unknown";
-  dict->SetString(kMachineInfoBoard, board);
-
+  }
+  dict->SetString(chromeos::system::kMachineInfoBoard, board);
   return true;
 }
 
@@ -3077,13 +3083,21 @@
   SendResponse(true);
 }
 
-OpenNewWindowFunction::OpenNewWindowFunction() {}
-
-OpenNewWindowFunction::~OpenNewWindowFunction() {}
-
-bool OpenNewWindowFunction::RunImpl() {
-  std::string url;
-  EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &url));
-  file_manager_util::OpenNewWindow(profile_, GURL(url));
+bool ZoomFunction::RunImpl() {
+  content::RenderViewHost* const view_host = render_view_host();
+  std::string operation;
+  args_->GetString(0, &operation);
+  content::PageZoom zoom_type;
+  if (operation == "in") {
+    zoom_type = content::PAGE_ZOOM_IN;
+  } else if (operation == "out") {
+    zoom_type = content::PAGE_ZOOM_OUT;
+  } else if (operation == "reset") {
+    zoom_type = content::PAGE_ZOOM_RESET;
+  } else {
+    NOTREACHED();
+    return false;
+  }
+  view_host->Zoom(zoom_type);
   return true;
 }
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_browser_private_api.h b/chrome/browser/chromeos/extensions/file_manager/file_browser_private_api.h
index 1d4f391..c408946 100644
--- a/chrome/browser/chromeos/extensions/file_manager/file_browser_private_api.h
+++ b/chrome/browser/chromeos/extensions/file_manager/file_browser_private_api.h
@@ -13,7 +13,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/platform_file.h"
 #include "base/prefs/pref_service.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/chromeos/drive/file_errors.h"
 #include "chrome/browser/chromeos/drive/file_system_interface.h"
 #include "chrome/browser/chromeos/extensions/file_manager/zip_file_creator.h"
@@ -782,18 +782,13 @@
   virtual bool RunImpl() OVERRIDE;
 };
 
-// Implements the chrome.fileBrowserPrivate.newWindow method.
-class OpenNewWindowFunction : public AsyncExtensionFunction {
+class ZoomFunction : public SyncExtensionFunction {
  public:
-  DECLARE_EXTENSION_FUNCTION("fileBrowserPrivate.openNewWindow",
-                             FILEBROWSERPRIVATE_OPENNEWWINDOW)
-
-  OpenNewWindowFunction();
+  DECLARE_EXTENSION_FUNCTION("fileBrowserPrivate.zoom",
+                             FILEBROWSERPRIVATE_ZOOM);
 
  protected:
-  virtual ~OpenNewWindowFunction();
-
-  // AsyncExtensionFunction overrides.
+  virtual ~ZoomFunction() {}
   virtual bool RunImpl() OVERRIDE;
 };
 
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_browser_private_apitest.cc b/chrome/browser/chromeos/extensions/file_manager/file_browser_private_apitest.cc
index 623abd6..7506110 100644
--- a/chrome/browser/chromeos/extensions/file_manager/file_browser_private_apitest.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/file_browser_private_apitest.cc
@@ -2,19 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <stdio.h>
-
 #include "base/stl_util.h"
 #include "chrome/browser/extensions/extension_apitest.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/test/base/ui_test_utils.h"
 #include "chromeos/dbus/cros_disks_client.h"
 #include "chromeos/disks/mock_disk_mount_manager.h"
-#include "content/public/browser/browser_context.h"
-#include "content/public/browser/storage_partition.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_mount_point_provider.h"
 
 using ::testing::_;
 using ::testing::ReturnRef;
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_handler_util.cc b/chrome/browser/chromeos/extensions/file_manager/file_handler_util.cc
index 85508c1..53815ab 100644
--- a/chrome/browser/chromeos/extensions/file_manager/file_handler_util.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/file_handler_util.cc
@@ -7,7 +7,6 @@
 #include "base/bind.h"
 #include "base/file_util.h"
 #include "base/i18n/case_conversion.h"
-#include "base/json/json_writer.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
@@ -15,6 +14,7 @@
 #include "chrome/browser/chromeos/drive/file_task_executor.h"
 #include "chrome/browser/chromeos/extensions/file_manager/file_browser_handler.h"
 #include "chrome/browser/chromeos/extensions/file_manager/file_manager_util.h"
+#include "chrome/browser/chromeos/fileapi/cros_mount_point_provider.h"
 #include "chrome/browser/extensions/event_router.h"
 #include "chrome/browser/extensions/extension_host.h"
 #include "chrome/browser/extensions/extension_service.h"
@@ -36,7 +36,6 @@
 #include "content/public/browser/storage_partition.h"
 #include "content/public/browser/web_contents.h"
 #include "net/base/escape.h"
-#include "webkit/browser/chromeos/fileapi/cros_mount_point_provider.h"
 #include "webkit/browser/fileapi/file_system_context.h"
 #include "webkit/browser/fileapi/file_system_url.h"
 #include "webkit/browser/fileapi/isolated_context.h"
@@ -172,6 +171,15 @@
   return true;
 }
 
+fileapi::FileSystemContext* GetFileSystemContextForExtension(
+    Profile* profile,
+    const std::string& extension_id) {
+  GURL site = extensions::ExtensionSystem::Get(profile)->
+      extension_service()->GetSiteForExtensionId(extension_id);
+  return BrowserContext::GetStoragePartitionForSite(profile, site)->
+      GetFileSystemContext();
+}
+
 // Checks if the file browser extension has permissions for the files in its
 // file system context.
 bool FileBrowserHasAccessPermissionForFiles(
@@ -179,12 +187,9 @@
     const GURL& source_url,
     const std::string& file_browser_id,
     const std::vector<FileSystemURL>& files) {
-  GURL site = extensions::ExtensionSystem::Get(profile)->extension_service()->
-      GetSiteForExtensionId(file_browser_id);
   fileapi::ExternalFileSystemMountPointProvider* external_provider =
-      BrowserContext::GetStoragePartitionForSite(profile, site)->
-          GetFileSystemContext()->external_provider();
-
+      GetFileSystemContextForExtension(profile, file_browser_id)->
+      external_provider();
   if (!external_provider)
     return false;
 
@@ -491,22 +496,19 @@
 }
 
 // ExtensionTaskExecutor executes tasks with kTaskFile type.
-// TODO(hashimoto): Make this non ref-counted. crbug.com/231173
-class ExtensionTaskExecutor
-    : public base::RefCountedThreadSafe<ExtensionTaskExecutor> {
+class ExtensionTaskExecutor {
  public:
   ExtensionTaskExecutor(Profile* profile,
                         const Extension* extension,
                         int32 tab_id,
                         const std::string& action_id);
 
-  // Executes the task for each file. When true is returned, |done| will be run
-  // with the execution result.
-  bool Execute(const std::vector<FileSystemURL>& file_urls,
+  // Executes the task for each file. |done| will be run with the result.
+  void Execute(const std::vector<FileSystemURL>& file_urls,
                const FileTaskFinishedCallback& done);
 
  private:
-  friend class base::RefCountedThreadSafe<ExtensionTaskExecutor>;
+  // This object is responsible to delete itself.
   virtual ~ExtensionTaskExecutor();
 
   struct FileDefinition {
@@ -519,13 +521,23 @@
   };
 
   typedef std::vector<FileDefinition> FileDefinitionList;
-  class ExecuteTasksFileSystemCallbackDispatcher;
+
+  // Checks legitimacy of file url and grants file RO access permissions from
+  // handler (target) extension and its renderer process.
+  static FileDefinitionList SetupFileAccessPermissions(
+      scoped_refptr<fileapi::FileSystemContext> file_system_context_handler,
+      const scoped_refptr<const Extension>& handler_extension,
+      const std::vector<FileSystemURL>& file_urls);
+
+  void DidOpenFileSystem(const std::vector<FileSystemURL>& file_urls,
+                         base::PlatformFileError result,
+                         const std::string& file_system_name,
+                         const GURL& file_system_root);
 
   void ExecuteDoneOnUIThread(bool success);
   void ExecuteFileActionsOnUIThread(const std::string& file_system_name,
                                     const GURL& file_system_root,
-                                    const FileDefinitionList& file_list,
-                                    int handler_pid);
+                                    const FileDefinitionList& file_list);
   void SetupPermissionsAndDispatchEvent(const std::string& file_system_name,
                                         const GURL& file_system_root,
                                         const FileDefinitionList& file_list,
@@ -544,6 +556,9 @@
   int32 tab_id_;
   const std::string action_id_;
   FileTaskFinishedCallback done_;
+  base::WeakPtrFactory<ExtensionTaskExecutor> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(ExtensionTaskExecutor);
 };
 
 bool ExecuteFileTask(Profile* profile,
@@ -578,9 +593,13 @@
 
   // Execute the task.
   if (task_type == kTaskFile) {
-    scoped_refptr<ExtensionTaskExecutor> executor(
-        new ExtensionTaskExecutor(profile, extension, tab_id, action_id));
-    return executor->Execute(file_urls, done);
+    // Forbid calling undeclared handlers.
+    if (!FindFileBrowserHandler(extension, action_id))
+      return false;
+
+    (new ExtensionTaskExecutor(
+        profile, extension, tab_id, action_id))->Execute(file_urls, done);
+    return true;
   } else if (task_type == kTaskApp) {
     for (size_t i = 0; i != file_urls.size(); ++i) {
       extensions::LaunchPlatformAppWithFileHandler(
@@ -601,99 +620,21 @@
 ExtensionTaskExecutor::FileDefinition::~FileDefinition() {
 }
 
-class ExtensionTaskExecutor::ExecuteTasksFileSystemCallbackDispatcher {
- public:
-  static fileapi::FileSystemContext::OpenFileSystemCallback CreateCallback(
-      ExtensionTaskExecutor* executor,
-      scoped_refptr<fileapi::FileSystemContext> file_system_context_handler,
-      scoped_refptr<const Extension> handler_extension,
-      int handler_pid,
-      const std::string& action_id,
-      const std::vector<FileSystemURL>& file_urls) {
-    return base::Bind(
-        &ExecuteTasksFileSystemCallbackDispatcher::DidOpenFileSystem,
-        base::Owned(new ExecuteTasksFileSystemCallbackDispatcher(
-            executor, file_system_context_handler, handler_extension,
-            handler_pid, action_id, file_urls)));
-  }
+// static
+ExtensionTaskExecutor::FileDefinitionList
+ExtensionTaskExecutor::SetupFileAccessPermissions(
+    scoped_refptr<fileapi::FileSystemContext> file_system_context_handler,
+    const scoped_refptr<const Extension>& handler_extension,
+    const std::vector<FileSystemURL>& file_urls) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK(handler_extension.get());
 
-  void DidOpenFileSystem(base::PlatformFileError result,
-                         const std::string& file_system_name,
-                         const GURL& file_system_root) {
-    if (result != base::PLATFORM_FILE_OK) {
-      DidFail(result);
-      return;
-    }
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-    ExtensionTaskExecutor::FileDefinitionList file_list;
-    for (std::vector<FileSystemURL>::iterator iter = urls_.begin();
-         iter != urls_.end();
-         ++iter) {
-      // Set up file permission access.
-      ExtensionTaskExecutor::FileDefinition file;
-      if (!SetupFileAccessPermissions(*iter, &file))
-        continue;
-      file_list.push_back(file);
-    }
-    if (file_list.empty()) {
-      BrowserThread::PostTask(
-          BrowserThread::UI, FROM_HERE,
-          base::Bind(
-              &ExtensionTaskExecutor::ExecuteDoneOnUIThread,
-              executor_,
-              false));
-      return;
-    }
+  fileapi::ExternalFileSystemMountPointProvider* external_provider_handler =
+      file_system_context_handler->external_provider();
 
-    BrowserThread::PostTask(
-        BrowserThread::UI, FROM_HERE,
-        base::Bind(
-            &ExtensionTaskExecutor::ExecuteFileActionsOnUIThread,
-            executor_,
-            file_system_name,
-            file_system_root,
-            file_list,
-            handler_pid_));
-  }
-
-  void DidFail(base::PlatformFileError error_code) {
-    BrowserThread::PostTask(
-        BrowserThread::UI, FROM_HERE,
-        base::Bind(
-            &ExtensionTaskExecutor::ExecuteDoneOnUIThread,
-            executor_,
-            false));
-  }
-
- private:
-  ExecuteTasksFileSystemCallbackDispatcher(
-      ExtensionTaskExecutor* executor,
-      scoped_refptr<fileapi::FileSystemContext> file_system_context_handler,
-      const scoped_refptr<const Extension>& handler_extension,
-      int handler_pid,
-      const std::string& action_id,
-      const std::vector<FileSystemURL>& file_urls)
-      : executor_(executor),
-        file_system_context_handler_(file_system_context_handler),
-        handler_extension_(handler_extension),
-        handler_pid_(handler_pid),
-        action_id_(action_id),
-        urls_(file_urls) {
-    DCHECK(executor_.get());
-  }
-
-  // Checks legitimacy of file url and grants file RO access permissions from
-  // handler (target) extension and its renderer process.
-  bool SetupFileAccessPermissions(const FileSystemURL& url,
-                                  FileDefinition* file) {
-    if (!handler_extension_.get())
-      return false;
-
-    if (handler_pid_ == 0)
-      return false;
-
-    fileapi::ExternalFileSystemMountPointProvider* external_provider_handler =
-        file_system_context_handler_->external_provider();
+  FileDefinitionList file_list;
+  for (size_t i = 0; i < file_urls.size(); ++i) {
+    const FileSystemURL& url = file_urls[i];
 
     // Check if this file system entry exists first.
     base::PlatformFileInfo file_info;
@@ -704,13 +645,13 @@
     bool is_drive_file = url.type() == fileapi::kFileSystemTypeDrive;
     DCHECK(!is_drive_file || drive::util::IsUnderDriveMountPoint(local_path));
 
-    // If the file is under gdata mount point, there is no actual file to be
+    // If the file is under drive mount point, there is no actual file to be
     // found on the url.path().
     if (!is_drive_file) {
       if (!file_util::PathExists(local_path) ||
           file_util::IsLink(local_path) ||
           !file_util::GetFileInfo(local_path, &file_info)) {
-        return false;
+        continue;
       }
     }
 
@@ -718,23 +659,17 @@
     // ensure that the target extension can access only this FS entry and
     // prevent from traversing FS hierarchy upward.
     external_provider_handler->GrantFileAccessToExtension(
-        handler_extension_->id(), virtual_path);
+        handler_extension->id(), virtual_path);
 
     // Output values.
-    file->virtual_path = virtual_path;
-    file->is_directory = file_info.is_directory;
-    file->absolute_path = local_path;
-    return true;
+    FileDefinition file;
+    file.virtual_path = virtual_path;
+    file.is_directory = file_info.is_directory;
+    file.absolute_path = local_path;
+    file_list.push_back(file);
   }
-
-  scoped_refptr<ExtensionTaskExecutor> executor_;
-  scoped_refptr<fileapi::FileSystemContext> file_system_context_handler_;
-  scoped_refptr<const Extension> handler_extension_;
-  int handler_pid_;
-  std::string action_id_;
-  std::vector<FileSystemURL> urls_;
-  DISALLOW_COPY_AND_ASSIGN(ExecuteTasksFileSystemCallbackDispatcher);
-};
+  return file_list;
+}
 
 ExtensionTaskExecutor::ExtensionTaskExecutor(
     Profile* profile,
@@ -744,66 +679,78 @@
     : profile_(profile),
       extension_(extension),
       tab_id_(tab_id),
-      action_id_(action_id) {
+      action_id_(action_id),
+      weak_ptr_factory_(this) {
 }
 
 ExtensionTaskExecutor::~ExtensionTaskExecutor() {}
 
-bool ExtensionTaskExecutor::Execute(const std::vector<FileSystemURL>& file_urls,
+void ExtensionTaskExecutor::Execute(const std::vector<FileSystemURL>& file_urls,
                                     const FileTaskFinishedCallback& done) {
-  // Forbid calling undeclared handlers.
-  if (!FindFileBrowserHandler(extension_, action_id_))
-    return false;
-
-  int extension_pid = ExtractProcessFromExtensionId(profile_, extension_->id());
-  if (extension_pid <= 0) {
-    if (!extensions::BackgroundInfo::HasLazyBackgroundPage(extension_))
-      return false;
-  }
-
   done_ = done;
 
   // Get file system context for the extension to which onExecute event will be
-  // send. The file access permissions will be granted to the extension in the
+  // sent. The file access permissions will be granted to the extension in the
   // file system context for the files in |file_urls|.
-  GURL site = extensions::ExtensionSystem::Get(profile_)->extension_service()->
-      GetSiteForExtensionId(extension_->id());
-  scoped_refptr<fileapi::FileSystemContext> file_system_context_handler =
-      BrowserContext::GetStoragePartitionForSite(profile_, site)->
-      GetFileSystemContext();
+  GetFileSystemContextForExtension(profile_, extension_->id())->OpenFileSystem(
+      Extension::GetBaseURLFromExtensionId(extension_->id()).GetOrigin(),
+      fileapi::kFileSystemTypeExternal,
+      fileapi::OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT,
+      base::Bind(&ExtensionTaskExecutor::DidOpenFileSystem,
+                 weak_ptr_factory_.GetWeakPtr(),
+                 file_urls));
+}
 
-  GURL origin_url =
-      Extension::GetBaseURLFromExtensionId(extension_->id()).GetOrigin();
-  BrowserThread::PostTask(
-      BrowserThread::FILE, FROM_HERE,
-      base::Bind(&fileapi::FileSystemContext::OpenFileSystem,
-                 file_system_context_handler,
-                 origin_url, fileapi::kFileSystemTypeExternal,
-                 fileapi::OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT,
-                 ExecuteTasksFileSystemCallbackDispatcher::CreateCallback(
-                     this,
-                     file_system_context_handler,
-                     extension_,
-                     extension_pid,
-                     action_id_,
-                     file_urls)));
-  return true;
+void ExtensionTaskExecutor::DidOpenFileSystem(
+    const std::vector<FileSystemURL>& file_urls,
+    base::PlatformFileError result,
+    const std::string& file_system_name,
+    const GURL& file_system_root) {
+  if (result != base::PLATFORM_FILE_OK) {
+    ExecuteDoneOnUIThread(false);
+    return;
+  }
+
+  scoped_refptr<fileapi::FileSystemContext> file_system_context(
+      GetFileSystemContextForExtension(profile_, extension_->id()));
+  BrowserThread::PostTaskAndReplyWithResult(
+      BrowserThread::FILE,
+      FROM_HERE,
+      base::Bind(&SetupFileAccessPermissions,
+                 file_system_context,
+                 extension_,
+                 file_urls),
+      base::Bind(&ExtensionTaskExecutor::ExecuteFileActionsOnUIThread,
+                 weak_ptr_factory_.GetWeakPtr(),
+                 file_system_name,
+                 file_system_root));
 }
 
 void ExtensionTaskExecutor::ExecuteDoneOnUIThread(bool success) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   if (!done_.is_null())
     done_.Run(success);
-  done_.Reset();
+  delete this;
 }
 
 void ExtensionTaskExecutor::ExecuteFileActionsOnUIThread(
     const std::string& file_system_name,
     const GURL& file_system_root,
-    const FileDefinitionList& file_list,
-    int handler_pid) {
+    const FileDefinitionList& file_list) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
+  if (file_list.empty()) {
+    ExecuteDoneOnUIThread(false);
+    return;
+  }
+
+  int handler_pid = ExtractProcessFromExtensionId(profile_, extension_->id());
+  if (handler_pid <= 0 &&
+      !extensions::BackgroundInfo::HasLazyBackgroundPage(extension_)) {
+    ExecuteDoneOnUIThread(false);
+    return;
+  }
+
   if (handler_pid > 0) {
     SetupPermissionsAndDispatchEvent(file_system_name, file_system_root,
         file_list, handler_pid, NULL);
@@ -819,7 +766,10 @@
     queue->AddPendingTask(
         profile_, extension_->id(),
         base::Bind(&ExtensionTaskExecutor::SetupPermissionsAndDispatchEvent,
-                   this, file_system_name, file_system_root, file_list,
+                   weak_ptr_factory_.GetWeakPtr(),
+                   file_system_name,
+                   file_system_root,
+                   file_list,
                    handler_pid));
   }
 }
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_handler_util.h b/chrome/browser/chromeos/extensions/file_manager/file_handler_util.h
index 72cf682..e994bfa 100644
--- a/chrome/browser/chromeos/extensions/file_manager/file_handler_util.h
+++ b/chrome/browser/chromeos/extensions/file_manager/file_handler_util.h
@@ -8,20 +8,15 @@
 #include <string>
 #include <vector>
 
-#include "base/callback.h"
+#include "base/callback_forward.h"
 #include "base/platform_file.h"
 #include "chrome/common/extensions/extension.h"
-#include "extensions/common/url_pattern_set.h"
 
 class Browser;
 class FileBrowserHandler;
 class GURL;
 class Profile;
 
-namespace extensions {
-class Extension;
-}  // namespace extensions
-
 namespace fileapi {
 class FileSystemURL;
 }
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_manager_browsertest.cc b/chrome/browser/chromeos/extensions/file_manager/file_manager_browsertest.cc
index ff09572..2072be6 100644
--- a/chrome/browser/chromeos/extensions/file_manager/file_manager_browsertest.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/file_manager_browsertest.cc
@@ -8,27 +8,32 @@
 //  - Selecting a file and copy-pasting it with the keyboard copies the file.
 //  - Selecting a file and pressing delete deletes it.
 
+#include <deque>
 #include <string>
 
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/file_util.h"
 #include "base/files/file_path.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/chromeos/drive/drive_integration_service.h"
 #include "chrome/browser/chromeos/drive/file_system_interface.h"
 #include "chrome/browser/chromeos/extensions/file_manager/drive_test_util.h"
 #include "chrome/browser/drive/fake_drive_service.h"
+#include "chrome/browser/extensions/api/test/test_api.h"
 #include "chrome/browser/extensions/component_loader.h"
 #include "chrome/browser/extensions/extension_apitest.h"
 #include "chrome/browser/extensions/extension_test_message_listener.h"
 #include "chrome/browser/google_apis/gdata_wapi_parser.h"
 #include "chrome/browser/google_apis/test_util.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/common/chrome_notification_types.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/extensions/extension.h"
 #include "chromeos/chromeos_switches.h"
 #include "content/public/browser/browser_context.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/test/test_utils.h"
 #include "webkit/browser/fileapi/external_mount_points.h"
 
 namespace {
@@ -251,12 +256,12 @@
 
   drive::DriveIntegrationService* CreateDriveIntegrationService(
       Profile* profile) {
-    fake_drive_service_ = new google_apis::FakeDriveService;
+    fake_drive_service_ = new drive::FakeDriveService;
     fake_drive_service_->LoadResourceListForWapi(
-        "chromeos/gdata/empty_feed.json");
+        "gdata/empty_feed.json");
     fake_drive_service_->LoadAccountMetadataForWapi(
-        "chromeos/gdata/account_metadata.json");
-    fake_drive_service_->LoadAppListForDriveApi("chromeos/drive/applist.json");
+        "gdata/account_metadata.json");
+    fake_drive_service_->LoadAppListForDriveApi("drive/applist.json");
     integration_service_ = new drive::DriveIntegrationService(
         profile,
         fake_drive_service_,
@@ -267,24 +272,72 @@
 
  private:
   base::ScopedTempDir test_cache_root_;
-  google_apis::FakeDriveService* fake_drive_service_;
+  drive::FakeDriveService* fake_drive_service_;
   drive::DriveIntegrationService* integration_service_;
 };
 
-// Parameter of FileManagerBrowserTestBase.
-// The second value is the case name of javascript.
+// Listener to obtain the test relative messages synchronously.
+class FileManagerTestListener : public content::NotificationObserver {
+ public:
+  struct Message {
+    int type;
+    std::string message;
+    extensions::TestSendMessageFunction* function;
+  };
+
+  FileManagerTestListener() {
+    registrar_.Add(this,
+                   chrome::NOTIFICATION_EXTENSION_TEST_PASSED,
+                   content::NotificationService::AllSources());
+    registrar_.Add(this,
+                   chrome::NOTIFICATION_EXTENSION_TEST_FAILED,
+                   content::NotificationService::AllSources());
+    registrar_.Add(this,
+                   chrome::NOTIFICATION_EXTENSION_TEST_MESSAGE,
+                   content::NotificationService::AllSources());
+  }
+
+  Message GetNextMessage() {
+    if (messages_.empty())
+      content::RunMessageLoop();
+    const Message entry = messages_.front();
+    messages_.pop_front();
+    return entry;
+  }
+
+  virtual void Observe(int type,
+                       const content::NotificationSource& source,
+                       const content::NotificationDetails& details) OVERRIDE {
+    Message entry;
+    entry.type = type;
+    entry.message = type != chrome::NOTIFICATION_EXTENSION_TEST_PASSED ?
+        *content::Details<std::string>(details).ptr() :
+        std::string();
+    entry.function = type == chrome::NOTIFICATION_EXTENSION_TEST_MESSAGE ?
+        content::Source<extensions::TestSendMessageFunction>(source).ptr() :
+        NULL;
+    messages_.push_back(entry);
+    base::MessageLoopForUI::current()->Quit();
+  }
+
+ private:
+  std::deque<Message> messages_;
+  content::NotificationRegistrar registrar_;
+};
+
+// Parameter of FileManagerBrowserTest.
+// The second value is the case name of JavaScript.
 typedef std::tr1::tuple<GuestMode, const char*> TestParameter;
 
 // The base test class.
-class FileManagerBrowserTestBase :
+class FileManagerBrowserTest :
       public ExtensionApiTest,
       public ::testing::WithParamInterface<TestParameter> {
  protected:
-  FileManagerBrowserTestBase() :
+  FileManagerBrowserTest() :
       local_volume_(new LocalTestVolume),
       drive_volume_(std::tr1::get<0>(GetParam()) != IN_GUEST_MODE ?
-                    new DriveTestVolume() : NULL),
-      guest_mode_(std::tr1::get<0>(GetParam())) {}
+                    new DriveTestVolume() : NULL) {}
 
   virtual void SetUpInProcessBrowserTestFixture() OVERRIDE;
 
@@ -297,22 +350,18 @@
   // test.
   void StartTest();
 
- protected:
   const scoped_ptr<LocalTestVolume> local_volume_;
   const scoped_ptr<DriveTestVolume> drive_volume_;
-
- private:
-  GuestMode guest_mode_;
 };
 
-void FileManagerBrowserTestBase::SetUpInProcessBrowserTestFixture() {
+void FileManagerBrowserTest::SetUpInProcessBrowserTestFixture() {
   ExtensionApiTest::SetUpInProcessBrowserTestFixture();
   extensions::ComponentLoader::EnableBackgroundExtensionsForTesting();
   if (drive_volume_)
     ASSERT_TRUE(drive_volume_->SetUp());
 }
 
-void FileManagerBrowserTestBase::SetUpOnMainThread() {
+void FileManagerBrowserTest::SetUpOnMainThread() {
   ExtensionApiTest::SetUpOnMainThread();
   ASSERT_TRUE(local_volume_->Mount(browser()->profile()));
 
@@ -332,8 +381,8 @@
   }
 }
 
-void FileManagerBrowserTestBase::SetUpCommandLine(CommandLine* command_line) {
-  if (guest_mode_ == IN_GUEST_MODE) {
+void FileManagerBrowserTest::SetUpCommandLine(CommandLine* command_line) {
+  if (std::tr1::get<0>(GetParam()) == IN_GUEST_MODE) {
     command_line->AppendSwitch(chromeos::switches::kGuestSession);
     command_line->AppendSwitchNative(chromeos::switches::kLoginUser, "");
     command_line->AppendSwitch(switches::kIncognito);
@@ -341,61 +390,59 @@
   ExtensionApiTest::SetUpCommandLine(command_line);
 }
 
-void FileManagerBrowserTestBase::StartTest() {
+IN_PROC_BROWSER_TEST_P(FileManagerBrowserTest, Test) {
+  // Launch the extension.
   base::FilePath path = test_data_dir_.AppendASCII("file_manager_browsertest");
   const extensions::Extension* extension = LoadExtensionAsComponent(path);
   ASSERT_TRUE(extension);
 
-  bool in_guest_mode = guest_mode_ == IN_GUEST_MODE;
-  ExtensionTestMessageListener listener(
-      in_guest_mode ? "which test guest" : "which test non-guest", true);
-  ASSERT_TRUE(listener.WaitUntilSatisfied());
-  listener.Reply(std::tr1::get<1>(GetParam()));
-}
-
-class FileManagerBrowserFileDisplayTest : public FileManagerBrowserTestBase {};
-
-IN_PROC_BROWSER_TEST_P(FileManagerBrowserFileDisplayTest, Test) {
-  ResultCatcher catcher;
-  ASSERT_NO_FATAL_FAILURE(StartTest());
-
-  ExtensionTestMessageListener listener("initial check done", true);
-  ASSERT_TRUE(listener.WaitUntilSatisfied());
-  const TestEntryInfo entry = {
-    FILE,
-    "music.ogg",  // Prototype file name.
-    "newly added file.ogg",  // Target file name.
-    "audio/ogg",
-    NONE,
-    "4 Sep 1998 00:00:00"
-  };
-  if (drive_volume_)
-    drive_volume_->CreateEntry(entry);
-  local_volume_->CreateEntry(entry);
-  listener.Reply("file added");
-
-  ASSERT_TRUE(catcher.GetNextResult()) << catcher.message();
+  // Handle the messages from JavaScript.
+  // The while loop is break when the test is passed or failed.
+  FileManagerTestListener listener;
+  while (true) {
+    FileManagerTestListener::Message entry = listener.GetNextMessage();
+    if (entry.type == chrome::NOTIFICATION_EXTENSION_TEST_PASSED) {
+      // Test succeed.
+      break;
+    } else if (entry.type == chrome::NOTIFICATION_EXTENSION_TEST_FAILED) {
+      // Test failed.
+      ADD_FAILURE() << entry.message;
+      break;
+    } else if (entry.message == "getTestName") {
+      // Pass the test case name.
+      entry.function->Reply(std::tr1::get<1>(GetParam()));
+    } else if (entry.message == "isInGuestMode") {
+      // Obtains whther the test is in guest mode or not.
+      entry.function->Reply(std::tr1::get<0>(GetParam()) ? "true" : "false");
+    } else if (entry.message == "addEntry") {
+      // Add the extra entry.
+      const TestEntryInfo file = {
+        FILE,
+        "music.ogg",  // Prototype file name.
+        "newly added file.ogg",  // Target file name.
+        "audio/ogg",
+        NONE,
+        "4 Sep 1998 00:00:00"
+      };
+      if (drive_volume_)
+        drive_volume_->CreateEntry(file);
+      local_volume_->CreateEntry(file);
+      entry.function->Reply("onEntryAdded");
+    }
+  }
 }
 
 INSTANTIATE_TEST_CASE_P(
-    AllTests,
-    FileManagerBrowserFileDisplayTest,
+    FileDisplay,
+    FileManagerBrowserTest,
     ::testing::Values(TestParameter(NOT_IN_GUEST_MODE, "fileDisplayDownloads"),
                       TestParameter(IN_GUEST_MODE, "fileDisplayDownloads"),
                       TestParameter(NOT_IN_GUEST_MODE, "fileDisplayDrive")));
 
-// A test class that just executes JavaScript unit test.
-class FileManagerBrowserSimpleTest : public FileManagerBrowserTestBase {};
-
-IN_PROC_BROWSER_TEST_P(FileManagerBrowserSimpleTest, Test) {
-  ResultCatcher catcher;
-  ASSERT_NO_FATAL_FAILURE(StartTest());
-  ASSERT_TRUE(catcher.GetNextResult()) << catcher.message();
-}
-
+// TODO(hirono): Fix this test. crbug.com/247299
 INSTANTIATE_TEST_CASE_P(
     DISABLED_OpenSpecialTypes,
-    FileManagerBrowserSimpleTest,
+    FileManagerBrowserTest,
     ::testing::Values(TestParameter(IN_GUEST_MODE, "videoOpenDownloads"),
                       TestParameter(NOT_IN_GUEST_MODE, "videoOpenDownloads"),
                       TestParameter(NOT_IN_GUEST_MODE, "videoOpenDrive"),
@@ -409,10 +456,9 @@
                       // ASAN Tests (2).  TODO(mtomasz): crbug.com/243611.
                       // TestParameter(NOT_IN_GUEST_MODE, "galleryOpenDrive")));
 
-// Test is flaky, see http://crbug.com/247299
 INSTANTIATE_TEST_CASE_P(
-    DISABLED_KeyboardOpeartions,
-    FileManagerBrowserSimpleTest,
+    KeyboardOpeartions,
+    FileManagerBrowserTest,
     ::testing::Values(TestParameter(IN_GUEST_MODE, "keyboardDeleteDownloads"),
                       TestParameter(NOT_IN_GUEST_MODE,
                                     "keyboardDeleteDownloads"),
@@ -423,7 +469,7 @@
 
 INSTANTIATE_TEST_CASE_P(
     DriveSpecific,
-    FileManagerBrowserSimpleTest,
+    FileManagerBrowserTest,
     ::testing::Values(TestParameter(NOT_IN_GUEST_MODE, "openSidebarRecent"),
                       TestParameter(NOT_IN_GUEST_MODE, "openSidebarOffline"),
                       TestParameter(NOT_IN_GUEST_MODE,
@@ -432,7 +478,7 @@
 
 INSTANTIATE_TEST_CASE_P(
     Transfer,
-    FileManagerBrowserSimpleTest,
+    FileManagerBrowserTest,
     ::testing::Values(TestParameter(NOT_IN_GUEST_MODE,
                                     "transferFromDriveToDownloads"),
                       TestParameter(NOT_IN_GUEST_MODE,
@@ -452,13 +498,13 @@
 
 INSTANTIATE_TEST_CASE_P(
      HideSearchBox,
-     FileManagerBrowserSimpleTest,
+     FileManagerBrowserTest,
      ::testing::Values(TestParameter(IN_GUEST_MODE, "hideSearchBox"),
                        TestParameter(NOT_IN_GUEST_MODE, "hideSearchBox")));
 
 INSTANTIATE_TEST_CASE_P(
     RestorePrefs,
-    FileManagerBrowserSimpleTest,
+    FileManagerBrowserTest,
     ::testing::Values(TestParameter(IN_GUEST_MODE, "restoreSortColumn"),
                       TestParameter(NOT_IN_GUEST_MODE, "restoreSortColumn"),
                       TestParameter(IN_GUEST_MODE, "restoreCurrentView"),
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_manager_event_router.h b/chrome/browser/chromeos/extensions/file_manager/file_manager_event_router.h
index 38e5340..db63487 100644
--- a/chrome/browser/chromeos/extensions/file_manager/file_manager_event_router.h
+++ b/chrome/browser/chromeos/extensions/file_manager/file_manager_event_router.h
@@ -29,7 +29,7 @@
       public drive::DriveIntegrationServiceObserver,
       public drive::FileSystemObserver,
       public drive::JobListObserver,
-      public google_apis::DriveServiceObserver {
+      public drive::DriveServiceObserver {
  public:
   // Interface that should keep track of the system state in regards to system
   // suspend and resume events.
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_manager_manifest_unittest.cc b/chrome/browser/chromeos/extensions/file_manager/file_manager_manifest_unittest.cc
index b088243..acc676e 100644
--- a/chrome/browser/chromeos/extensions/file_manager/file_manager_manifest_unittest.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/file_manager_manifest_unittest.cc
@@ -77,14 +77,14 @@
   FileBrowserHandler::List* handlers =
       FileBrowserHandler::GetHandlers(extension.get());
   ASSERT_TRUE(handlers != NULL);
-  ASSERT_EQ(handlers->size(), 1U);
+  ASSERT_EQ(1U, handlers->size());
   const FileBrowserHandler* action = handlers->at(0).get();
 
-  EXPECT_EQ(action->id(), "ExtremelyCoolAction");
-  EXPECT_EQ(action->title(), "Be Amazed");
-  EXPECT_EQ(action->icon_path(), "icon.png");
+  EXPECT_EQ("ExtremelyCoolAction", action->id());
+  EXPECT_EQ("Be Amazed", action->title());
+  EXPECT_EQ("icon.png", action->icon_path());
   const extensions::URLPatternSet& patterns = action->file_url_patterns();
-  ASSERT_EQ(patterns.patterns().size(), 1U);
+  ASSERT_EQ(1U, patterns.patterns().size());
   EXPECT_TRUE(action->MatchesURL(
       GURL("filesystem:chrome-extension://foo/local/test.txt")));
   EXPECT_FALSE(action->HasCreateAccessPermission());
@@ -113,11 +113,11 @@
   FileBrowserHandler::List* handlers =
       FileBrowserHandler::GetHandlers(extension.get());
   ASSERT_TRUE(handlers != NULL);
-  ASSERT_EQ(handlers->size(), 1U);
+  ASSERT_EQ(1U, handlers->size());
   const FileBrowserHandler* action = handlers->at(0).get();
 
   const extensions::URLPatternSet& patterns = action->file_url_patterns();
-  ASSERT_EQ(patterns.patterns().size(), 1U);
+  ASSERT_EQ(1U, patterns.patterns().size());
   EXPECT_TRUE(action->MatchesURL(
       GURL("filesystem:chrome-extension://foo/local/test.txt")));
 }
@@ -144,11 +144,11 @@
   FileBrowserHandler::List* handlers =
       FileBrowserHandler::GetHandlers(extension.get());
   ASSERT_TRUE(handlers != NULL);
-  ASSERT_EQ(handlers->size(), 1U);
+  ASSERT_EQ(1U, handlers->size());
   const FileBrowserHandler* action = handlers->at(0).get();
   const extensions::URLPatternSet& patterns = action->file_url_patterns();
 
-  EXPECT_EQ(patterns.patterns().size(), 0U);
+  EXPECT_EQ(0U, patterns.patterns().size());
   EXPECT_TRUE(action->HasCreateAccessPermission());
   EXPECT_FALSE(action->CanRead());
   EXPECT_FALSE(action->CanWrite());
@@ -164,11 +164,11 @@
               .Set("files", "main.html"))
       .Build();
 
-  // Non component extensions can't ovverride chrome://files/ URL.
+  // Non component extensions can't override chrome://files/ URL.
   LoadAndExpectError(Manifest(manifest_value.get(), "override_files"),
                      errors::kInvalidChromeURLOverrides);
 
-  // A component extention can override chrome://files/ URL.
+  // A component extension can override chrome://files/ URL.
   std::string error;
   LoadExtension(Manifest(manifest_value.get(), "override_files"),
                 &error, extensions::Manifest::COMPONENT, Extension::NO_FLAGS);
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_manager_notifications.cc b/chrome/browser/chromeos/extensions/file_manager/file_manager_notifications.cc
index e780c40..b28a217 100644
--- a/chrome/browser/chromeos/extensions/file_manager/file_manager_notifications.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/file_manager_notifications.cc
@@ -7,19 +7,14 @@
 #include "base/bind.h"
 #include "base/message_loop.h"
 #include "base/stl_util.h"
-#include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/chromeos/extensions/file_manager/file_manager_util.h"
 #include "chrome/browser/notifications/desktop_notification_service.h"
 #include "chrome/browser/notifications/notification_delegate.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_list.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
-#include "ui/webui/web_ui_util.h"
 
 namespace {
 
@@ -248,29 +243,32 @@
   if (it->second.fail_message_finalized)
     return;
 
-  int notification_message_id = 0;
-
   // Do we have a multi-partition device for which at least one mount failed.
   bool fail_on_multipartition_device =
       success ? it->second.non_parent_device_failed
               : it->second.mount_success_exists ||
                 it->second.non_parent_device_failed;
 
+  base::string16 message;
   if (fail_on_multipartition_device) {
     it->second.fail_message_finalized = true;
-    notification_message_id =
-        label.empty() ? IDS_MULTIPART_DEVICE_UNSUPPORTED_DEFAULT_MESSAGE
-                      : IDS_MULTIPART_DEVICE_UNSUPPORTED_MESSAGE;
+    message = label.empty() ?
+        l10n_util::GetStringUTF16(
+            IDS_MULTIPART_DEVICE_UNSUPPORTED_DEFAULT_MESSAGE) :
+        l10n_util::GetStringFUTF16(
+            IDS_MULTIPART_DEVICE_UNSUPPORTED_MESSAGE, UTF8ToUTF16(label));
   } else if (!success) {
     // First device failed.
     if (!is_unsupported) {
-      notification_message_id =
-          label.empty() ? IDS_DEVICE_UNKNOWN_DEFAULT_MESSAGE
-                        : IDS_DEVICE_UNKNOWN_MESSAGE;
+      message = label.empty() ?
+          l10n_util::GetStringUTF16(IDS_DEVICE_UNKNOWN_DEFAULT_MESSAGE) :
+          l10n_util::GetStringFUTF16(IDS_DEVICE_UNKNOWN_MESSAGE,
+                                     UTF8ToUTF16(label));
     } else {
-      notification_message_id =
-          label.empty() ? IDS_DEVICE_UNSUPPORTED_DEFAULT_MESSAGE
-                        : IDS_DEVICE_UNSUPPORTED_MESSAGE;
+      message = label.empty() ?
+          l10n_util::GetStringUTF16(IDS_DEVICE_UNSUPPORTED_DEFAULT_MESSAGE) :
+          l10n_util::GetStringFUTF16(IDS_DEVICE_UNSUPPORTED_MESSAGE,
+                                     UTF8ToUTF16(label));
     }
   }
 
@@ -280,7 +278,7 @@
     it->second.non_parent_device_failed |= !is_parent;
   }
 
-  if (notification_message_id == 0)
+  if (message.empty())
     return;
 
   if (it->second.fail_notification_shown) {
@@ -289,14 +287,7 @@
     it->second.fail_notification_shown = true;
   }
 
-  if (!label.empty()) {
-    ShowNotificationWithMessage(DEVICE_FAIL, system_path,
-        l10n_util::GetStringFUTF16(notification_message_id,
-                                   ASCIIToUTF16(label)));
-  } else {
-    ShowNotificationWithMessage(DEVICE_FAIL, system_path,
-        l10n_util::GetStringUTF16(notification_message_id));
-  }
+  ShowNotificationWithMessage(DEVICE_FAIL, system_path, message);
 }
 
 void FileManagerNotifications::ShowNotification(NotificationType type,
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_manager_notifications.h b/chrome/browser/chromeos/extensions/file_manager/file_manager_notifications.h
index 771ecaa..5325b50 100644
--- a/chrome/browser/chromeos/extensions/file_manager/file_manager_notifications.h
+++ b/chrome/browser/chromeos/extensions/file_manager/file_manager_notifications.h
@@ -12,7 +12,7 @@
 #include "base/basictypes.h"
 #include "base/memory/weak_ptr.h"
 #include "base/strings/string16.h"
-#include "base/time.h"
+#include "base/time/time.h"
 
 class Profile;
 
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_manager_notifications_unittest.cc b/chrome/browser/chromeos/extensions/file_manager/file_manager_notifications_unittest.cc
index b3df077..7a22c3b 100644
--- a/chrome/browser/chromeos/extensions/file_manager/file_manager_notifications_unittest.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/file_manager_notifications_unittest.cc
@@ -2,21 +2,20 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
+#include "chrome/browser/chromeos/extensions/file_manager/file_manager_notifications.h"
+
 #include <string>
 
+#include "base/memory/scoped_ptr.h"
 #include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/chromeos/extensions/file_manager/file_manager_notifications.h"
-#include "chrome/browser/ui/browser.h"
 #include "grit/generated_resources.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/l10n/l10n_util.h"
 
 using ::testing::_;
 using ::testing::InSequence;
-using ::testing::Return;
 using ::testing::StrEq;
-using ::testing::AnyNumber;
 
 namespace chromeos {
 
@@ -30,13 +29,13 @@
 
   virtual ~MockFileManagerNotificationsOnMount() {}
 
-  MOCK_METHOD3(ShowNotificationWithMessage, void(NotificationType,
-      const std::string&, const string16&));
+  MOCK_METHOD3(ShowNotificationWithMessage,
+               void(NotificationType, const std::string&, const string16&));
   MOCK_METHOD2(HideNotification, void(NotificationType, const std::string&));
 };
 
 MATCHER_P2(String16Equals, id, label, "") {
-  return arg == l10n_util::GetStringFUTF16(id, ASCIIToUTF16(label));
+  return arg == l10n_util::GetStringFUTF16(id, UTF8ToUTF16(label));
 }
 
 }  // namespace
@@ -182,6 +181,26 @@
       device_label, false, false, false);
 }
 
+TEST(FileManagerMountNotificationsTest, NonASCIILabel) {
+  MockFileManagerNotificationsOnMount* mocked_notifications =
+      new MockFileManagerNotificationsOnMount(NULL);
+  scoped_ptr<FileManagerNotifications> notifications(mocked_notifications);
+
+  std::string notification_path("system_path_prefix");
+  // "RA (U+30E9) BE (U+30D9) RU (U+30EB)" in Katakana letters.
+  std::string device_label("\xE3\x83\xA9\xE3\x83\x99\xE3\x83\xAB");
+
+  notifications->RegisterDevice(notification_path);
+  EXPECT_CALL(*mocked_notifications, HideNotification(
+              FileManagerNotifications::DEVICE, StrEq(notification_path)));
+  EXPECT_CALL(*mocked_notifications, ShowNotificationWithMessage(
+      FileManagerNotifications::DEVICE_FAIL, StrEq(notification_path),
+      String16Equals(IDS_DEVICE_UNKNOWN_MESSAGE, device_label)));
+
+  notifications->ManageNotificationsOnMountCompleted(notification_path,
+      device_label, false, false, false);
+}
+
 TEST(FileManagerMountNotificationsTest, MulitpleFail) {
   MockFileManagerNotificationsOnMount* mocked_notifications =
       new MockFileManagerNotificationsOnMount(NULL);
@@ -195,21 +214,21 @@
               FileManagerNotifications::DEVICE, StrEq(notification_path)));
   {
     InSequence s;
-      EXPECT_CALL(*mocked_notifications, ShowNotificationWithMessage(
-          FileManagerNotifications::DEVICE_FAIL, StrEq(notification_path),
-              String16Equals(IDS_DEVICE_UNKNOWN_MESSAGE, device_label)))
-          .RetiresOnSaturation();
-      EXPECT_CALL(*mocked_notifications, HideNotification(
-          FileManagerNotifications::DEVICE_FAIL, notification_path));
-      EXPECT_CALL(*mocked_notifications, ShowNotificationWithMessage(
-          FileManagerNotifications::DEVICE_FAIL, StrEq(notification_path),
-              String16Equals(IDS_DEVICE_UNKNOWN_MESSAGE, device_label)));
-      EXPECT_CALL(*mocked_notifications, HideNotification(
-          FileManagerNotifications::DEVICE_FAIL, notification_path));
-      EXPECT_CALL(*mocked_notifications, ShowNotificationWithMessage(
-          FileManagerNotifications::DEVICE_FAIL, StrEq(notification_path),
-              String16Equals(IDS_MULTIPART_DEVICE_UNSUPPORTED_MESSAGE,
-              device_label)));
+    EXPECT_CALL(*mocked_notifications, ShowNotificationWithMessage(
+        FileManagerNotifications::DEVICE_FAIL, StrEq(notification_path),
+        String16Equals(IDS_DEVICE_UNKNOWN_MESSAGE, device_label)))
+        .RetiresOnSaturation();
+    EXPECT_CALL(*mocked_notifications, HideNotification(
+        FileManagerNotifications::DEVICE_FAIL, notification_path));
+    EXPECT_CALL(*mocked_notifications, ShowNotificationWithMessage(
+        FileManagerNotifications::DEVICE_FAIL, StrEq(notification_path),
+        String16Equals(IDS_DEVICE_UNKNOWN_MESSAGE, device_label)));
+    EXPECT_CALL(*mocked_notifications, HideNotification(
+        FileManagerNotifications::DEVICE_FAIL, notification_path));
+    EXPECT_CALL(*mocked_notifications, ShowNotificationWithMessage(
+        FileManagerNotifications::DEVICE_FAIL, StrEq(notification_path),
+        String16Equals(IDS_MULTIPART_DEVICE_UNSUPPORTED_MESSAGE,
+                       device_label)));
   }
 
   notifications->ManageNotificationsOnMountCompleted(notification_path,
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_manager_util.h b/chrome/browser/chromeos/extensions/file_manager/file_manager_util.h
index abfc42e..e5549f8 100644
--- a/chrome/browser/chromeos/extensions/file_manager/file_manager_util.h
+++ b/chrome/browser/chromeos/extensions/file_manager/file_manager_util.h
@@ -8,16 +8,12 @@
 #include <string>
 
 #include "base/files/file_path.h"
-#include "googleurl/src/gurl.h"
 #include "ui/shell_dialogs/select_file_dialog.h"
 
 class Browser;
+class GURL;
 class Profile;
 
-namespace base {
-class ListValue;
-}
-
 extern const char kFileBrowserDomain[];
 extern const char kFileBrowserGalleryTaskId[];
 extern const char kFileBrowserWatchTaskId[];
diff --git a/chrome/browser/chromeos/extensions/file_manager/zip_file_creator.h b/chrome/browser/chromeos/extensions/file_manager/zip_file_creator.h
index 01bf2ad..bc9defb 100644
--- a/chrome/browser/chromeos/extensions/file_manager/zip_file_creator.h
+++ b/chrome/browser/chromeos/extensions/file_manager/zip_file_creator.h
@@ -48,7 +48,6 @@
   void Start();
 
  private:
-  class ProcessHostClient;
   friend class ProcessHostClient;
 
   virtual ~ZipFileCreator();
diff --git a/chrome/browser/chromeos/extensions/info_private_api.cc b/chrome/browser/chromeos/extensions/info_private_api.cc
index 872d790..8bd78aa 100644
--- a/chrome/browser/chromeos/extensions/info_private_api.cc
+++ b/chrome/browser/chromeos/extensions/info_private_api.cc
@@ -18,9 +18,6 @@
 
 namespace {
 
-// Name of machine statistic property with HWID.
-const char kHardwareClass[] = "hardware_class";
-
 // Key which corresponds to the HWID setting.
 const char kPropertyHWID[] = "hwid";
 
@@ -30,9 +27,6 @@
 // Key which corresponds to the initial_locale property.
 const char kPropertyInitialLocale[] = "initialLocale";
 
-// Name of machine statistic property with board.
-const char kPropertyReleaseBoard[] = "CHROMEOS_RELEASE_BOARD";
-
 // Key which corresponds to the board property in JS.
 const char kPropertyBoard[] = "board";
 
@@ -69,7 +63,7 @@
     std::string hwid;
     chromeos::system::StatisticsProvider* provider =
         chromeos::system::StatisticsProvider::GetInstance();
-    provider->GetMachineStatistic(kHardwareClass, &hwid);
+    provider->GetMachineStatistic(chromeos::system::kHardwareClass, &hwid);
     return new base::StringValue(hwid);
   } else if (property_name == kPropertyHomeProvider) {
     NetworkLibrary* netlib = CrosLibrary::Get()->GetNetworkLibrary();
@@ -81,7 +75,7 @@
     std::string board;
     chromeos::system::StatisticsProvider* provider =
         chromeos::system::StatisticsProvider::GetInstance();
-    provider->GetMachineStatistic(kPropertyReleaseBoard, &board);
+    provider->GetMachineStatistic(chromeos::system::kMachineInfoBoard, &board);
     return new base::StringValue(board);
   } else if (property_name == kPropertyOwner) {
     return Value::CreateBooleanValue(
diff --git a/chrome/browser/chromeos/extensions/install_limiter.h b/chrome/browser/chromeos/extensions/install_limiter.h
index c0fff26..2839c29 100644
--- a/chrome/browser/chromeos/extensions/install_limiter.h
+++ b/chrome/browser/chromeos/extensions/install_limiter.h
@@ -13,7 +13,7 @@
 #include "base/files/file_path.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/extensions/crx_installer.h"
 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
 #include "content/public/browser/notification_observer.h"
diff --git a/chrome/browser/chromeos/extensions/networking_private_apitest.cc b/chrome/browser/chromeos/extensions/networking_private_apitest.cc
index 8104cbf..0cb874a 100644
--- a/chrome/browser/chromeos/extensions/networking_private_apitest.cc
+++ b/chrome/browser/chromeos/extensions/networking_private_apitest.cc
@@ -6,7 +6,6 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/login/user.h"
 #include "chrome/browser/chromeos/login/user_manager.h"
-#include "chrome/browser/chromeos/policy/network_configuration_updater.h"
 #include "chrome/browser/extensions/extension_apitest.h"
 #include "chrome/browser/policy/browser_policy_connector.h"
 #include "chrome/browser/policy/mock_configuration_policy_provider.h"
@@ -119,20 +118,29 @@
                            flimflam::kTypeCellular, "stub_cellular_device1");
 
     const bool add_to_watchlist = true;
+    const bool add_to_visible = true;
     service_test->AddService("stub_ethernet", "eth0",
                              flimflam::kTypeEthernet, flimflam::kStateOnline,
-                             add_to_watchlist);
+                             add_to_visible, add_to_watchlist);
 
     service_test->AddService("stub_wifi1", "wifi1",
                              flimflam::kTypeWifi, flimflam::kStateOnline,
-                             add_to_watchlist);
+                             add_to_visible, add_to_watchlist);
     service_test->SetServiceProperty("stub_wifi1",
                                      flimflam::kSecurityProperty,
                                      base::StringValue(flimflam::kSecurityWep));
+    base::ListValue frequencies1;
+    frequencies1.AppendInteger(2400);
+    service_test->SetServiceProperty("stub_wifi1",
+                                     shill::kWifiFrequencyListProperty,
+                                     frequencies1);
+    service_test->SetServiceProperty("stub_wifi1",
+                                     flimflam::kWifiFrequency,
+                                     base::FundamentalValue(2400));
 
     service_test->AddService("stub_wifi2", "wifi2_PSK",
                              flimflam::kTypeWifi, flimflam::kStateIdle,
-                             add_to_watchlist);
+                             add_to_visible, add_to_watchlist);
     service_test->SetServiceProperty("stub_wifi2",
                                      flimflam::kGuidProperty,
                                      base::StringValue("stub_wifi2"));
@@ -142,14 +150,23 @@
     service_test->SetServiceProperty("stub_wifi2",
                                      flimflam::kSignalStrengthProperty,
                                      base::FundamentalValue(80));
+    base::ListValue frequencies2;
+    frequencies2.AppendInteger(2400);
+    frequencies2.AppendInteger(5000);
+    service_test->SetServiceProperty("stub_wifi2",
+                                     shill::kWifiFrequencyListProperty,
+                                     frequencies2);
+    service_test->SetServiceProperty("stub_wifi2",
+                                     flimflam::kWifiFrequency,
+                                     base::FundamentalValue(5000));
     service_test->SetServiceProperty("stub_wifi2",
                                      flimflam::kProfileProperty,
                                      base::StringValue(kUser1ProfilePath));
-    profile_test->AddService("stub_wifi2");
+    profile_test->AddService(kUser1ProfilePath, "stub_wifi2");
 
     service_test->AddService("stub_cellular1", "cellular1",
                              flimflam::kTypeCellular, flimflam::kStateIdle,
-                             add_to_watchlist);
+                             add_to_visible, add_to_watchlist);
     service_test->SetServiceProperty(
         "stub_cellular1",
         flimflam::kNetworkTechnologyProperty,
@@ -166,7 +183,7 @@
     service_test->AddService("stub_vpn1", "vpn1",
                              flimflam::kTypeVPN,
                              flimflam::kStateOnline,
-                             add_to_watchlist);
+                             add_to_visible, add_to_watchlist);
 
     content::RunAllPendingInMessageLoop();
   }
@@ -251,7 +268,7 @@
   ShillProfileClient::TestInterface* profile_test =
       DBusThreadManager::Get()->GetShillProfileClient()->GetTestInterface();
   // Update the profile entry.
-  profile_test->AddService("stub_wifi2");
+  profile_test->AddService(kUser1ProfilePath, "stub_wifi2");
 
   content::RunAllPendingInMessageLoop();
 
diff --git a/chrome/browser/chromeos/extensions/wallpaper_private_apitest.cc b/chrome/browser/chromeos/extensions/wallpaper_private_apitest.cc
index 20de42a..14f164f 100644
--- a/chrome/browser/chromeos/extensions/wallpaper_private_apitest.cc
+++ b/chrome/browser/chromeos/extensions/wallpaper_private_apitest.cc
@@ -7,6 +7,6 @@
 
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, WallpaperPicker) {
   host_resolver()->AddRule("a.com", "127.0.0.1");
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunComponentExtensionTest("wallpaper_manager")) << message_;
 }
diff --git a/chrome/browser/chromeos/external_metrics.cc b/chrome/browser/chromeos/external_metrics.cc
index fe24805..cabac24 100644
--- a/chrome/browser/chromeos/external_metrics.cc
+++ b/chrome/browser/chromeos/external_metrics.cc
@@ -13,16 +13,19 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <map>
 #include <string>
 
 #include "base/basictypes.h"
 #include "base/bind.h"
+#include "base/file_util.h"
 #include "base/metrics/histogram.h"
 #include "base/metrics/sparse_histogram.h"
 #include "base/metrics/statistics_recorder.h"
 #include "base/perftimer.h"
 #include "base/posix/eintr_wrapper.h"
-#include "base/time.h"
+#include "base/sys_info.h"
+#include "base/time/time.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/metrics/metrics_service.h"
 #include "content/public/browser/browser_thread.h"
@@ -53,6 +56,83 @@
   return CheckValues(name, 1, maximum, maximum + 1);
 }
 
+// Establishes field trial for wifi scanning in chromeos.  crbug.com/242733.
+void SetupProgressiveScanFieldTrial() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  const char name_of_experiment[] = "ProgressiveScan";
+  const char path_to_group_file[] = "/home/chronos/.progressive_scan_variation";
+  const base::FieldTrial::Probability kDivisor = 1000;
+  scoped_refptr<base::FieldTrial> trial =
+      base::FieldTrialList::FactoryGetFieldTrial(name_of_experiment,
+                                                 kDivisor,
+                                                 "Default",
+                                                 2013, 12, 31, NULL);
+  // Announce the groups with 0 percentage; the actual percentages come from
+  // the server configuration.
+  std::map<int, std::string> group_to_char;
+  group_to_char[trial->AppendGroup("FullScan", 0)] = "c";
+  group_to_char[trial->AppendGroup("33Percent_4MinMax", 0)] = "1";
+  group_to_char[trial->AppendGroup("50Percent_4MinMax", 0)] = "2";
+  group_to_char[trial->AppendGroup("50Percent_8MinMax", 0)] = "3";
+  group_to_char[trial->AppendGroup("100Percent_8MinMax", 0)] = "4";
+
+  // Announce the experiment to any listeners (especially important is the UMA
+  // software, which will append the group names to UMA statistics).
+  const int group_num = trial->group();
+  std::string group_char = "x";
+  if (ContainsKey(group_to_char, group_num))
+    group_char = group_to_char[group_num];
+
+  // Write the group to the file to be read by ChromeOS.
+  const base::FilePath kPathToGroupFile(path_to_group_file);
+
+  if (file_util::WriteFile(kPathToGroupFile, group_char.c_str(),
+                           group_char.length())) {
+    LOG(INFO) << "Configured in group '" << trial->group_name()
+              << "' ('" << group_char << "') for "
+              << name_of_experiment << " field trial";
+  } else {
+    LOG(ERROR) << "Couldn't write to " << path_to_group_file;
+  }
+}
+
+// Sets up field trial for measuring swap and CPU metrics after tab switch
+// and scroll events. crbug.com/253994
+void SetupSwapJankFieldTrial() {
+  const char name_of_experiment[] = "SwapJank64vs32";
+
+  // Determine if this is a 32 or 64 bit build of Chrome.
+  bool is_chrome_64 = sizeof(void*) == 8;
+
+  // Determine if this is a 32 or 64 bit kernel.
+  bool is_kernel_64 = base::SysInfo::OperatingSystemArchitecture() == "x86_64";
+
+  // A 32 bit kernel requires 32 bit Chrome.
+  DCHECK(is_kernel_64 || !is_chrome_64);
+
+  // All groups are either on or off.
+  const base::FieldTrial::Probability kTotalProbability = 1;
+  scoped_refptr<base::FieldTrial> trial =
+      base::FieldTrialList::FactoryGetFieldTrial(name_of_experiment,
+                                                 kTotalProbability,
+                                                 "default",
+                                                 2013, 12, 31, NULL);
+  // Assign probability of 1 to this Chrome's group.  Assign 0 to all other
+  // choices.
+  trial->AppendGroup("kernel_64_chrome_64",
+                     is_kernel_64 && is_chrome_64 ? kTotalProbability : 0);
+  trial->AppendGroup("kernel_64_chrome_32",
+                     is_kernel_64 && !is_chrome_64 ? kTotalProbability : 0);
+  trial->AppendGroup("kernel_32_chrome_32",
+                     !is_kernel_64 && !is_chrome_64 ? kTotalProbability : 0);
+
+  // Announce the experiment to any listeners (especially important is the UMA
+  // software, which will append the group names to UMA statistics).
+  trial->group();
+  DVLOG(1) << "Configured in group '" << trial->group_name() << "' for "
+           << name_of_experiment << " field trial";
+}
+
 }  // namespace
 
 // The interval between external metrics collections in seconds
@@ -72,7 +152,19 @@
   valid_user_actions_.insert("Updater.ServerCertificateChanged");
   valid_user_actions_.insert("Updater.ServerCertificateFailed");
 
-  ScheduleCollector();
+  // Initialize field trials that don't need to read from files.
+  SetupSwapJankFieldTrial();
+
+  // Initialize any chromeos field trials that need to read from a file (e.g.,
+  // those that have an upstart script determine their experimental group for
+  // them) then schedule the data collection.  All of this is done on the file
+  // thread.
+  bool task_posted = BrowserThread::PostTask(
+      BrowserThread::FILE,
+      FROM_HERE,
+      base::Bind(&chromeos::ExternalMetrics::SetupFieldTrialsOnFileThread,
+                 this));
+  DCHECK(task_posted);
 }
 
 void ExternalMetrics::RecordActionUI(std::string action_string) {
@@ -291,4 +383,13 @@
   DCHECK(result);
 }
 
+void ExternalMetrics::SetupFieldTrialsOnFileThread() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  // Field trials that do not read from files can be initialized in
+  // ExternalMetrics::Start() above.
+  SetupProgressiveScanFieldTrial();
+
+  ScheduleCollector();
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/external_metrics.h b/chrome/browser/chromeos/external_metrics.h
index c5894e5..5be9fc2 100644
--- a/chrome/browser/chromeos/external_metrics.h
+++ b/chrome/browser/chromeos/external_metrics.h
@@ -5,6 +5,8 @@
 #ifndef CHROME_BROWSER_CHROMEOS_EXTERNAL_METRICS_H_
 #define CHROME_BROWSER_CHROMEOS_EXTERNAL_METRICS_H_
 
+#include <string>
+
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "base/containers/hash_tables.h"
@@ -21,9 +23,6 @@
 // normal UMA mechanism. The file is then truncated to zero size. Chrome uses
 // flock() to synchronize accesses to the file.
 class ExternalMetrics : public base::RefCountedThreadSafe<ExternalMetrics> {
-  FRIEND_TEST_ALL_PREFIXES(ExternalMetricsTest, ParseExternalMetricsFile);
-  friend class base::RefCountedThreadSafe<ExternalMetrics>;
-
  public:
   ExternalMetrics();
 
@@ -33,6 +32,9 @@
   void Start();
 
  private:
+  friend class base::RefCountedThreadSafe<ExternalMetrics>;
+  FRIEND_TEST_ALL_PREFIXES(ExternalMetricsTest, ParseExternalMetricsFile);
+
   // There is one function with this type for each action.
   typedef void (*RecordFunctionType)();
 
@@ -78,6 +80,12 @@
   // Schedules a metrics event collection in the future.
   void ScheduleCollector();
 
+  // Calls setup methods for Chrome OS field trials that need to be initialized
+  // based on data from the file system.  They are setup here so that we can
+  // make absolutely sure that they are setup before we gather UMA statistics
+  // from ChromeOS.
+  void SetupFieldTrialsOnFileThread();
+
   // Maps histogram or action names to recorder structs.
   base::hash_map<std::string, RecordFunctionType> action_recorders_;
 
@@ -87,6 +95,7 @@
   // Used for testing only.
   RecorderType test_recorder_;
   base::FilePath test_path_;
+
   DISALLOW_COPY_AND_ASSIGN(ExternalMetrics);
 };
 
diff --git a/chrome/browser/chromeos/external_protocol_dialog.h b/chrome/browser/chromeos/external_protocol_dialog.h
index bf11eba..cee403e 100644
--- a/chrome/browser/chromeos/external_protocol_dialog.h
+++ b/chrome/browser/chromeos/external_protocol_dialog.h
@@ -8,7 +8,7 @@
 #include <string>
 
 #include "base/strings/string16.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "ui/views/window/dialog_delegate.h"
 
 class GURL;
diff --git a/chrome/browser/chromeos/fileapi/cros_mount_point_provider.cc b/chrome/browser/chromeos/fileapi/cros_mount_point_provider.cc
new file mode 100644
index 0000000..82da083
--- /dev/null
+++ b/chrome/browser/chromeos/fileapi/cros_mount_point_provider.cc
@@ -0,0 +1,354 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/fileapi/cros_mount_point_provider.h"
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop.h"
+#include "base/path_service.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/synchronization/lock.h"
+#include "chrome/browser/chromeos/fileapi/file_access_permissions.h"
+#include "chrome/browser/chromeos/fileapi/remote_file_stream_writer.h"
+#include "chrome/browser/chromeos/fileapi/remote_file_system_operation.h"
+#include "chromeos/dbus/cros_disks_client.h"
+#include "webkit/browser/fileapi/async_file_util_adapter.h"
+#include "webkit/browser/fileapi/copy_or_move_file_validator.h"
+#include "webkit/browser/fileapi/external_mount_points.h"
+#include "webkit/browser/fileapi/file_system_context.h"
+#include "webkit/browser/fileapi/file_system_file_stream_reader.h"
+#include "webkit/browser/fileapi/file_system_operation_context.h"
+#include "webkit/browser/fileapi/file_system_task_runners.h"
+#include "webkit/browser/fileapi/file_system_url.h"
+#include "webkit/browser/fileapi/isolated_context.h"
+#include "webkit/browser/fileapi/isolated_file_util.h"
+#include "webkit/browser/fileapi/local_file_stream_writer.h"
+#include "webkit/browser/fileapi/local_file_system_operation.h"
+
+namespace {
+
+const char kChromeUIScheme[] = "chrome";
+
+}  // namespace
+
+namespace chromeos {
+
+// static
+bool CrosMountPointProvider::CanHandleURL(const fileapi::FileSystemURL& url) {
+  if (!url.is_valid())
+    return false;
+  return url.type() == fileapi::kFileSystemTypeNativeLocal ||
+         url.type() == fileapi::kFileSystemTypeRestrictedNativeLocal ||
+         url.type() == fileapi::kFileSystemTypeDrive;
+}
+
+CrosMountPointProvider::CrosMountPointProvider(
+    scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy,
+    scoped_refptr<fileapi::ExternalMountPoints> mount_points,
+    fileapi::ExternalMountPoints* system_mount_points)
+    : special_storage_policy_(special_storage_policy),
+      file_access_permissions_(new FileAccessPermissions()),
+      local_file_util_(new fileapi::AsyncFileUtilAdapter(
+          new fileapi::IsolatedFileUtil())),
+      mount_points_(mount_points),
+      system_mount_points_(system_mount_points) {
+}
+
+CrosMountPointProvider::~CrosMountPointProvider() {
+}
+
+void CrosMountPointProvider::AddSystemMountPoints() {
+  // RegisterFileSystem() is no-op if the mount point with the same name
+  // already exists, hence it's safe to call without checking if a mount
+  // point already exists or not.
+
+  // TODO(satorux): "Downloads" directory should probably be per-profile. For
+  // this to be per-profile, a unique directory path should be chosen per
+  // profile, and the mount point should be added to
+  // mount_points_. crbug.com/247236
+  base::FilePath home_path;
+  if (PathService::Get(base::DIR_HOME, &home_path)) {
+    system_mount_points_->RegisterFileSystem(
+        "Downloads",
+        fileapi::kFileSystemTypeNativeLocal,
+        home_path.AppendASCII("Downloads"));
+  }
+
+  system_mount_points_->RegisterFileSystem(
+      "archive",
+      fileapi::kFileSystemTypeNativeLocal,
+      chromeos::CrosDisksClient::GetArchiveMountPoint());
+  system_mount_points_->RegisterFileSystem(
+      "removable",
+      fileapi::kFileSystemTypeNativeLocal,
+      chromeos::CrosDisksClient::GetRemovableDiskMountPoint());
+  system_mount_points_->RegisterFileSystem(
+      "oem",
+      fileapi::kFileSystemTypeRestrictedNativeLocal,
+      base::FilePath(FILE_PATH_LITERAL("/usr/share/oem")));
+}
+
+bool CrosMountPointProvider::CanHandleType(fileapi::FileSystemType type) const {
+  switch (type) {
+    case fileapi::kFileSystemTypeExternal:
+    case fileapi::kFileSystemTypeDrive:
+    case fileapi::kFileSystemTypeRestrictedNativeLocal:
+    case fileapi::kFileSystemTypeNativeLocal:
+    case fileapi::kFileSystemTypeNativeForPlatformApp:
+      return true;
+    default:
+      return false;
+  }
+}
+
+void CrosMountPointProvider::OpenFileSystem(
+    const GURL& origin_url,
+    fileapi::FileSystemType type,
+    fileapi::OpenFileSystemMode mode,
+    const OpenFileSystemCallback& callback) {
+  DCHECK(fileapi::IsolatedContext::IsIsolatedType(type));
+  // Nothing to validate for external filesystem.
+  callback.Run(base::PLATFORM_FILE_OK);
+}
+
+fileapi::FileSystemQuotaUtil* CrosMountPointProvider::GetQuotaUtil() {
+  // No quota support.
+  return NULL;
+}
+
+void CrosMountPointProvider::DeleteFileSystem(
+    const GURL& origin_url,
+    fileapi::FileSystemType type,
+    fileapi::FileSystemContext* context,
+    const DeleteFileSystemCallback& callback) {
+  NOTREACHED();
+  callback.Run(base::PLATFORM_FILE_ERROR_INVALID_OPERATION);
+}
+
+bool CrosMountPointProvider::IsAccessAllowed(
+    const fileapi::FileSystemURL& url) const {
+  if (!url.is_valid())
+    return false;
+
+  // Permit access to mount points from internal WebUI.
+  const GURL& origin_url = url.origin();
+  if (origin_url.SchemeIs(kChromeUIScheme))
+    return true;
+
+  // No extra check is needed for isolated file systems.
+  if (url.mount_type() == fileapi::kFileSystemTypeIsolated)
+    return true;
+
+  if (!CanHandleURL(url))
+    return false;
+
+  std::string extension_id = origin_url.host();
+  // Check first to make sure this extension has fileBrowserHander permissions.
+  if (!special_storage_policy_->IsFileHandler(extension_id))
+    return false;
+
+  return file_access_permissions_->HasAccessPermission(extension_id,
+                                                       url.virtual_path());
+}
+
+void CrosMountPointProvider::GrantFullAccessToExtension(
+    const std::string& extension_id) {
+  DCHECK(special_storage_policy_->IsFileHandler(extension_id));
+  if (!special_storage_policy_->IsFileHandler(extension_id))
+    return;
+
+  std::vector<fileapi::MountPoints::MountPointInfo> files;
+  mount_points_->AddMountPointInfosTo(&files);
+  system_mount_points_->AddMountPointInfosTo(&files);
+
+  for (size_t i = 0; i < files.size(); ++i) {
+    file_access_permissions_->GrantAccessPermission(
+        extension_id,
+        base::FilePath::FromUTF8Unsafe(files[i].name));
+  }
+}
+
+void CrosMountPointProvider::GrantFileAccessToExtension(
+    const std::string& extension_id, const base::FilePath& virtual_path) {
+  // All we care about here is access from extensions for now.
+  DCHECK(special_storage_policy_->IsFileHandler(extension_id));
+  if (!special_storage_policy_->IsFileHandler(extension_id))
+    return;
+
+  std::string id;
+  fileapi::FileSystemType type;
+  base::FilePath path;
+  if (!mount_points_->CrackVirtualPath(virtual_path, &id, &type, &path) &&
+      !system_mount_points_->CrackVirtualPath(virtual_path,
+                                              &id, &type, &path)) {
+    return;
+  }
+
+  if (type == fileapi::kFileSystemTypeRestrictedNativeLocal) {
+    LOG(ERROR) << "Can't grant access for restricted mount point";
+    return;
+  }
+
+  file_access_permissions_->GrantAccessPermission(extension_id, virtual_path);
+}
+
+void CrosMountPointProvider::RevokeAccessForExtension(
+      const std::string& extension_id) {
+  file_access_permissions_->RevokePermissions(extension_id);
+}
+
+std::vector<base::FilePath> CrosMountPointProvider::GetRootDirectories() const {
+  std::vector<fileapi::MountPoints::MountPointInfo> mount_points;
+  mount_points_->AddMountPointInfosTo(&mount_points);
+  system_mount_points_->AddMountPointInfosTo(&mount_points);
+
+  std::vector<base::FilePath> root_dirs;
+  for (size_t i = 0; i < mount_points.size(); ++i)
+    root_dirs.push_back(mount_points[i].path);
+  return root_dirs;
+}
+
+fileapi::FileSystemFileUtil* CrosMountPointProvider::GetFileUtil(
+    fileapi::FileSystemType type) {
+  DCHECK(type == fileapi::kFileSystemTypeNativeLocal ||
+         type == fileapi::kFileSystemTypeRestrictedNativeLocal);
+  return local_file_util_->sync_file_util();
+}
+
+fileapi::AsyncFileUtil* CrosMountPointProvider::GetAsyncFileUtil(
+    fileapi::FileSystemType type) {
+  DCHECK(type == fileapi::kFileSystemTypeNativeLocal ||
+         type == fileapi::kFileSystemTypeRestrictedNativeLocal);
+  return local_file_util_.get();
+}
+
+fileapi::CopyOrMoveFileValidatorFactory*
+CrosMountPointProvider::GetCopyOrMoveFileValidatorFactory(
+    fileapi::FileSystemType type, base::PlatformFileError* error_code) {
+  DCHECK(error_code);
+  *error_code = base::PLATFORM_FILE_OK;
+  return NULL;
+}
+
+fileapi::FileSystemOperation* CrosMountPointProvider::CreateFileSystemOperation(
+    const fileapi::FileSystemURL& url,
+    fileapi::FileSystemContext* context,
+    base::PlatformFileError* error_code) const {
+  DCHECK(url.is_valid());
+
+  if (!IsAccessAllowed(url)) {
+    *error_code = base::PLATFORM_FILE_ERROR_SECURITY;
+    return NULL;
+  }
+
+  if (url.type() == fileapi::kFileSystemTypeDrive) {
+    fileapi::RemoteFileSystemProxyInterface* remote_proxy =
+        GetRemoteProxy(url.filesystem_id());
+    if (!remote_proxy) {
+      *error_code = base::PLATFORM_FILE_ERROR_NOT_FOUND;
+      return NULL;
+    }
+    return new RemoteFileSystemOperation(remote_proxy);
+  }
+
+  DCHECK(url.type() == fileapi::kFileSystemTypeNativeLocal ||
+         url.type() == fileapi::kFileSystemTypeRestrictedNativeLocal);
+  scoped_ptr<fileapi::FileSystemOperationContext> operation_context(
+      new fileapi::FileSystemOperationContext(context));
+  operation_context->set_root_path(GetFileSystemRootPath(url));
+  return new fileapi::LocalFileSystemOperation(url, context,
+                                               operation_context.Pass());
+}
+
+scoped_ptr<webkit_blob::FileStreamReader>
+CrosMountPointProvider::CreateFileStreamReader(
+    const fileapi::FileSystemURL& url,
+    int64 offset,
+    const base::Time& expected_modification_time,
+    fileapi::FileSystemContext* context) const {
+  DCHECK(url.is_valid());
+
+  if (!IsAccessAllowed(url))
+    return scoped_ptr<webkit_blob::FileStreamReader>();
+
+  if (url.type() == fileapi::kFileSystemTypeDrive) {
+    fileapi::RemoteFileSystemProxyInterface* remote_proxy =
+        GetRemoteProxy(url.filesystem_id());
+    if (!remote_proxy)
+      return scoped_ptr<webkit_blob::FileStreamReader>();
+    return remote_proxy->CreateFileStreamReader(
+        context->task_runners()->file_task_runner(),
+        url, offset, expected_modification_time);
+  }
+
+  return scoped_ptr<webkit_blob::FileStreamReader>(
+      new fileapi::FileSystemFileStreamReader(
+          context, url, offset, expected_modification_time));
+}
+
+scoped_ptr<fileapi::FileStreamWriter>
+CrosMountPointProvider::CreateFileStreamWriter(
+    const fileapi::FileSystemURL& url,
+    int64 offset,
+    fileapi::FileSystemContext* context) const {
+  DCHECK(url.is_valid());
+
+  if (!IsAccessAllowed(url))
+    return scoped_ptr<fileapi::FileStreamWriter>();
+
+  if (url.type() == fileapi::kFileSystemTypeDrive) {
+    fileapi::RemoteFileSystemProxyInterface* remote_proxy =
+        GetRemoteProxy(url.filesystem_id());
+    if (!remote_proxy)
+      return scoped_ptr<fileapi::FileStreamWriter>();
+    return scoped_ptr<fileapi::FileStreamWriter>(
+        new RemoteFileStreamWriter(
+            remote_proxy, url, offset,
+            context->task_runners()->file_task_runner()));
+  }
+
+  if (url.type() == fileapi::kFileSystemTypeRestrictedNativeLocal)
+    return scoped_ptr<fileapi::FileStreamWriter>();
+
+  DCHECK(url.type() == fileapi::kFileSystemTypeNativeLocal);
+  return scoped_ptr<fileapi::FileStreamWriter>(
+      new fileapi::LocalFileStreamWriter(
+          context->task_runners()->file_task_runner(), url.path(), offset));
+}
+
+bool CrosMountPointProvider::GetVirtualPath(
+    const base::FilePath& filesystem_path,
+    base::FilePath* virtual_path) {
+  return mount_points_->GetVirtualPath(filesystem_path, virtual_path) ||
+         system_mount_points_->GetVirtualPath(filesystem_path, virtual_path);
+}
+
+fileapi::RemoteFileSystemProxyInterface* CrosMountPointProvider::GetRemoteProxy(
+    const std::string& mount_name) const {
+  fileapi::RemoteFileSystemProxyInterface* proxy =
+      mount_points_->GetRemoteFileSystemProxy(mount_name);
+  if (proxy)
+    return proxy;
+  return system_mount_points_->GetRemoteFileSystemProxy(mount_name);
+}
+
+base::FilePath CrosMountPointProvider::GetFileSystemRootPath(
+    const fileapi::FileSystemURL& url) const {
+  DCHECK(fileapi::IsolatedContext::IsIsolatedType(url.mount_type()));
+  if (!url.is_valid())
+    return base::FilePath();
+
+  base::FilePath root_path;
+  std::string mount_name = url.filesystem_id();
+  if (!mount_points_->GetRegisteredPath(mount_name, &root_path) &&
+      !system_mount_points_->GetRegisteredPath(mount_name, &root_path)) {
+    return base::FilePath();
+  }
+
+  return root_path.DirName();
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/fileapi/cros_mount_point_provider.h b/chrome/browser/chromeos/fileapi/cros_mount_point_provider.h
new file mode 100644
index 0000000..c68589d
--- /dev/null
+++ b/chrome/browser/chromeos/fileapi/cros_mount_point_provider.h
@@ -0,0 +1,170 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_FILEAPI_CROS_MOUNT_POINT_PROVIDER_H_
+#define CHROME_BROWSER_CHROMEOS_FILEAPI_CROS_MOUNT_POINT_PROVIDER_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "base/files/file_path.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/synchronization/lock.h"
+#include "webkit/browser/fileapi/file_system_mount_point_provider.h"
+#include "webkit/browser/quota/special_storage_policy.h"
+#include "webkit/browser/webkit_storage_browser_export.h"
+#include "webkit/common/fileapi/file_system_types.h"
+
+namespace fileapi {
+class AsyncFileUtilAdapter;
+class CopyOrMoveFileValidatorFactory;
+class ExternalMountPoints;
+class FileSystemFileUtil;
+class FileSystemURL;
+class IsolatedContext;
+}
+
+namespace chromeos {
+
+class FileAccessPermissions;
+
+// CrosMountPointProvider is a Chrome OS specific implementation of
+// ExternalFileSystemMountPointProvider. This class is responsible for a
+// number of things, including:
+//
+// - Add system mount points
+// - Grant/revoke/check file access permissions
+// - Create FileSystemOperation per file system type
+// - Create FileStreamReader/Writer per file system type
+//
+// Chrome OS specific mount points:
+//
+// "Downloads" is a mount point for user's Downloads directory on the local
+// disk, where downloaded files are stored by default.
+//
+// "archive" is a mount point for an archive file, such as a zip file. This
+// mount point exposes contents of an archive file via cros_disks and AVFS
+// <http://avf.sourceforge.net/>.
+//
+// "removable" is a mount point for removable media such as an SD card.
+// Insertion and removal of removable media are handled by cros_disks.
+//
+// "oem" is a read-only mount point for a directory containing OEM data.
+//
+// "drive" is a mount point for Google Drive. Drive is integrated with the
+// FileSystem API layer via drive::FileSystemProxy. This mount point is added
+// by drive::DriveIntegrationService.
+//
+// These mount points are placed under the "external" namespace, and file
+// system URLs for these mount points look like:
+//
+//   filesystem:<origin>/external/<mount_name>/...
+//
+class CrosMountPointProvider
+    : public fileapi::ExternalFileSystemMountPointProvider {
+ public:
+  using fileapi::FileSystemMountPointProvider::OpenFileSystemCallback;
+  using fileapi::FileSystemMountPointProvider::DeleteFileSystemCallback;
+
+  // CrosMountPointProvider will take an ownership of a |mount_points|
+  // reference. On the other hand, |system_mount_points| will be kept as a raw
+  // pointer and it should outlive CrosMountPointProvider instance.
+  CrosMountPointProvider(
+      scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy,
+      scoped_refptr<fileapi::ExternalMountPoints> mount_points,
+      fileapi::ExternalMountPoints* system_mount_points);
+  virtual ~CrosMountPointProvider();
+
+  // Adds system mount points, such as "archive", and "removable". This
+  // function is no-op if these mount points are already present.
+  void AddSystemMountPoints();
+
+  // Returns true if CrosMountpointProvider can handle |url|, i.e. its
+  // file system type matches with what this provider supports.
+  // This could be called on any threads.
+  static bool CanHandleURL(const fileapi::FileSystemURL& url);
+
+  // fileapi::FileSystemMountPointProvider overrides.
+  virtual bool CanHandleType(fileapi::FileSystemType type) const OVERRIDE;
+  virtual void OpenFileSystem(
+      const GURL& origin_url,
+      fileapi::FileSystemType type,
+      fileapi::OpenFileSystemMode mode,
+      const OpenFileSystemCallback& callback) OVERRIDE;
+  virtual fileapi::FileSystemFileUtil* GetFileUtil(
+      fileapi::FileSystemType type) OVERRIDE;
+  virtual fileapi::AsyncFileUtil* GetAsyncFileUtil(
+      fileapi::FileSystemType type) OVERRIDE;
+  virtual fileapi::CopyOrMoveFileValidatorFactory*
+      GetCopyOrMoveFileValidatorFactory(
+          fileapi::FileSystemType type,
+          base::PlatformFileError* error_code) OVERRIDE;
+  virtual fileapi::FileSystemOperation* CreateFileSystemOperation(
+      const fileapi::FileSystemURL& url,
+      fileapi::FileSystemContext* context,
+      base::PlatformFileError* error_code) const OVERRIDE;
+  virtual scoped_ptr<webkit_blob::FileStreamReader> CreateFileStreamReader(
+      const fileapi::FileSystemURL& path,
+      int64 offset,
+      const base::Time& expected_modification_time,
+      fileapi::FileSystemContext* context) const OVERRIDE;
+  virtual scoped_ptr<fileapi::FileStreamWriter> CreateFileStreamWriter(
+      const fileapi::FileSystemURL& url,
+      int64 offset,
+      fileapi::FileSystemContext* context) const OVERRIDE;
+  virtual fileapi::FileSystemQuotaUtil* GetQuotaUtil() OVERRIDE;
+  virtual void DeleteFileSystem(
+      const GURL& origin_url,
+      fileapi::FileSystemType type,
+      fileapi::FileSystemContext* context,
+      const DeleteFileSystemCallback& callback) OVERRIDE;
+
+  // fileapi::ExternalFileSystemMountPointProvider overrides.
+  virtual bool IsAccessAllowed(const fileapi::FileSystemURL& url)
+      const OVERRIDE;
+  virtual std::vector<base::FilePath> GetRootDirectories() const OVERRIDE;
+  virtual void GrantFullAccessToExtension(
+      const std::string& extension_id) OVERRIDE;
+  virtual void GrantFileAccessToExtension(
+      const std::string& extension_id,
+      const base::FilePath& virtual_path) OVERRIDE;
+  virtual void RevokeAccessForExtension(
+      const std::string& extension_id) OVERRIDE;
+  virtual bool GetVirtualPath(const base::FilePath& filesystem_path,
+                              base::FilePath* virtual_path) OVERRIDE;
+
+ private:
+  fileapi::RemoteFileSystemProxyInterface* GetRemoteProxy(
+      const std::string& mount_name) const;
+  base::FilePath GetFileSystemRootPath(const fileapi::FileSystemURL& url) const;
+
+  scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy_;
+  scoped_ptr<FileAccessPermissions> file_access_permissions_;
+  scoped_ptr<fileapi::AsyncFileUtilAdapter> local_file_util_;
+
+  // Mount points specific to the owning context (i.e. per-profile mount
+  // points).
+  //
+  // It is legal to have mount points with the same name as in
+  // system_mount_points_. Also, mount point paths may overlap with mount point
+  // paths in system_mount_points_. In both cases mount points in
+  // |mount_points_| will have a priority.
+  // E.g. if |mount_points_| map 'foo1' to '/foo/foo1' and
+  // |file_system_mount_points_| map 'xxx' to '/foo/foo1/xxx', |GetVirtualPaths|
+  // will resolve '/foo/foo1/xxx/yyy' as 'foo1/xxx/yyy' (i.e. the mapping from
+  // |mount_points_| will be used).
+  scoped_refptr<fileapi::ExternalMountPoints> mount_points_;
+
+  // Globally visible mount points. System MountPonts instance should outlive
+  // all CrosMountPointProvider instances, so raw pointer is safe.
+  fileapi::ExternalMountPoints* system_mount_points_;
+
+  DISALLOW_COPY_AND_ASSIGN(CrosMountPointProvider);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_FILEAPI_CROS_MOUNT_POINT_PROVIDER_H_
diff --git a/chrome/browser/chromeos/fileapi/cros_mount_point_provider_unittest.cc b/chrome/browser/chromeos/fileapi/cros_mount_point_provider_unittest.cc
new file mode 100644
index 0000000..b74bdf8
--- /dev/null
+++ b/chrome/browser/chromeos/fileapi/cros_mount_point_provider_unittest.cc
@@ -0,0 +1,268 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/fileapi/cros_mount_point_provider.h"
+
+#include <set>
+
+#include "base/files/file_path.h"
+#include "base/path_service.h"
+#include "chromeos/dbus/cros_disks_client.h"
+#include "googleurl/src/url_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/browser/fileapi/external_mount_points.h"
+#include "webkit/browser/fileapi/file_permission_policy.h"
+#include "webkit/browser/fileapi/file_system_url.h"
+#include "webkit/browser/fileapi/isolated_context.h"
+#include "webkit/browser/quota/mock_special_storage_policy.h"
+
+#define FPL(x) FILE_PATH_LITERAL(x)
+
+using fileapi::ExternalMountPoints;
+using fileapi::FileSystemURL;
+
+namespace {
+
+FileSystemURL CreateFileSystemURL(const std::string& extension,
+                                  const char* path,
+                                  ExternalMountPoints* mount_points) {
+  return mount_points->CreateCrackedFileSystemURL(
+      GURL("chrome-extension://" + extension + "/"),
+      fileapi::kFileSystemTypeExternal,
+      base::FilePath::FromUTF8Unsafe(path));
+}
+
+TEST(CrosMountPointProviderTest, DefaultMountPoints) {
+  scoped_refptr<quota::SpecialStoragePolicy> storage_policy =
+      new quota::MockSpecialStoragePolicy();
+  scoped_refptr<fileapi::ExternalMountPoints> mount_points(
+      fileapi::ExternalMountPoints::CreateRefCounted());
+  chromeos::CrosMountPointProvider provider(
+      storage_policy,
+      mount_points.get(),
+      fileapi::ExternalMountPoints::GetSystemInstance());
+  provider.AddSystemMountPoints();
+  std::vector<base::FilePath> root_dirs = provider.GetRootDirectories();
+  std::set<base::FilePath> root_dirs_set(root_dirs.begin(), root_dirs.end());
+
+  // By default there should be 4 mount points (in system mount points):
+  EXPECT_EQ(4u, root_dirs.size());
+  base::FilePath home_path;
+  ASSERT_TRUE(PathService::Get(base::DIR_HOME, &home_path));
+
+  EXPECT_TRUE(root_dirs_set.count(home_path.AppendASCII("Downloads")));
+  EXPECT_TRUE(root_dirs_set.count(
+      chromeos::CrosDisksClient::GetRemovableDiskMountPoint()));
+  EXPECT_TRUE(root_dirs_set.count(
+      chromeos::CrosDisksClient::GetArchiveMountPoint()));
+  EXPECT_TRUE(root_dirs_set.count(base::FilePath(FPL("/usr/share/oem"))));
+}
+
+TEST(CrosMountPointProviderTest, GetRootDirectories) {
+  scoped_refptr<quota::SpecialStoragePolicy> storage_policy =
+      new quota::MockSpecialStoragePolicy();
+  scoped_refptr<fileapi::ExternalMountPoints> mount_points(
+      fileapi::ExternalMountPoints::CreateRefCounted());
+
+  scoped_refptr<fileapi::ExternalMountPoints> system_mount_points(
+      fileapi::ExternalMountPoints::CreateRefCounted());
+
+  chromeos::CrosMountPointProvider provider(
+      storage_policy,
+      mount_points.get(),
+      system_mount_points.get());
+
+  const size_t initial_root_dirs_size = provider.GetRootDirectories().size();
+
+  // Register 'local' test mount points.
+  mount_points->RegisterFileSystem("c",
+                                   fileapi::kFileSystemTypeNativeLocal,
+                                   base::FilePath(FPL("/a/b/c")));
+  mount_points->RegisterFileSystem("d",
+                                   fileapi::kFileSystemTypeNativeLocal,
+                                   base::FilePath(FPL("/b/c/d")));
+
+  // Register system test mount points.
+  system_mount_points->RegisterFileSystem("d",
+                                          fileapi::kFileSystemTypeNativeLocal,
+                                          base::FilePath(FPL("/g/c/d")));
+  system_mount_points->RegisterFileSystem("e",
+                                          fileapi::kFileSystemTypeNativeLocal,
+                                          base::FilePath(FPL("/g/d/e")));
+
+  std::vector<base::FilePath> root_dirs = provider.GetRootDirectories();
+  std::set<base::FilePath> root_dirs_set(root_dirs.begin(), root_dirs.end());
+  EXPECT_EQ(initial_root_dirs_size + 4, root_dirs.size());
+  EXPECT_TRUE(root_dirs_set.count(base::FilePath(FPL("/a/b/c"))));
+  EXPECT_TRUE(root_dirs_set.count(base::FilePath(FPL("/b/c/d"))));
+  EXPECT_TRUE(root_dirs_set.count(base::FilePath(FPL("/g/c/d"))));
+  EXPECT_TRUE(root_dirs_set.count(base::FilePath(FPL("/g/d/e"))));
+}
+
+TEST(CrosMountPointProviderTest, AccessPermissions) {
+  url_util::AddStandardScheme("chrome-extension");
+
+  scoped_refptr<quota::MockSpecialStoragePolicy> storage_policy =
+      new quota::MockSpecialStoragePolicy();
+  scoped_refptr<fileapi::ExternalMountPoints> mount_points(
+      fileapi::ExternalMountPoints::CreateRefCounted());
+  scoped_refptr<fileapi::ExternalMountPoints> system_mount_points(
+      fileapi::ExternalMountPoints::CreateRefCounted());
+  chromeos::CrosMountPointProvider provider(
+      storage_policy,
+      mount_points.get(),
+      system_mount_points.get());
+
+  std::string extension("ddammdhioacbehjngdmkjcjbnfginlla");
+
+  storage_policy->AddFileHandler(extension);
+
+  // Initialize mount points.
+  ASSERT_TRUE(system_mount_points->RegisterFileSystem(
+      "system",
+      fileapi::kFileSystemTypeNativeLocal,
+      base::FilePath(FPL("/g/system"))));
+  ASSERT_TRUE(mount_points->RegisterFileSystem(
+      "removable",
+      fileapi::kFileSystemTypeNativeLocal,
+      base::FilePath(FPL("/media/removable"))));
+  ASSERT_TRUE(mount_points->RegisterFileSystem(
+      "oem",
+      fileapi::kFileSystemTypeRestrictedNativeLocal,
+      base::FilePath(FPL("/usr/share/oem"))));
+
+  // Provider specific mount point access.
+  EXPECT_FALSE(provider.IsAccessAllowed(
+      CreateFileSystemURL(extension, "removable/foo", mount_points.get())));
+
+  provider.GrantFileAccessToExtension(extension,
+                                      base::FilePath(FPL("removable/foo")));
+  EXPECT_TRUE(provider.IsAccessAllowed(
+      CreateFileSystemURL(extension, "removable/foo", mount_points.get())));
+  EXPECT_FALSE(provider.IsAccessAllowed(
+      CreateFileSystemURL(extension, "removable/foo1", mount_points.get())));
+
+  // System mount point access.
+  EXPECT_FALSE(provider.IsAccessAllowed(
+      CreateFileSystemURL(extension, "system/foo", system_mount_points.get())));
+
+  provider.GrantFileAccessToExtension(extension,
+                                      base::FilePath(FPL("system/foo")));
+  EXPECT_TRUE(provider.IsAccessAllowed(
+      CreateFileSystemURL(extension, "system/foo", system_mount_points.get())));
+  EXPECT_FALSE(provider.IsAccessAllowed(
+      CreateFileSystemURL(extension, "system/foo1",
+                          system_mount_points.get())));
+
+  // oem is restricted file system.
+  provider.GrantFileAccessToExtension(
+      extension, base::FilePath(FPL("oem/foo")));
+  // The extension should not be able to access the file even if
+  // GrantFileAccessToExtension was called.
+  EXPECT_FALSE(provider.IsAccessAllowed(
+      CreateFileSystemURL(extension, "oem/foo", mount_points.get())));
+
+  provider.GrantFullAccessToExtension(extension);
+  // The extension should be able to access restricted file system after it was
+  // granted full access.
+  EXPECT_TRUE(provider.IsAccessAllowed(
+      CreateFileSystemURL(extension, "oem/foo", mount_points.get())));
+  // The extension which was granted full access should be able to access any
+  // path on current file systems.
+  EXPECT_TRUE(provider.IsAccessAllowed(
+      CreateFileSystemURL(extension, "removable/foo1", mount_points.get())));
+  EXPECT_TRUE(provider.IsAccessAllowed(
+      CreateFileSystemURL(extension, "system/foo1",
+                          system_mount_points.get())));
+
+  // The extension cannot access new mount points.
+  // TODO(tbarzic): This should probably be changed.
+  ASSERT_TRUE(mount_points->RegisterFileSystem(
+      "test",
+      fileapi::kFileSystemTypeNativeLocal,
+      base::FilePath(FPL("/foo/test"))));
+  EXPECT_FALSE(provider.IsAccessAllowed(
+      CreateFileSystemURL(extension, "test_/foo", mount_points.get())));
+
+  provider.RevokeAccessForExtension(extension);
+  EXPECT_FALSE(provider.IsAccessAllowed(
+      CreateFileSystemURL(extension, "removable/foo", mount_points.get())));
+
+  fileapi::FileSystemURL internal_url = FileSystemURL::CreateForTest(
+      GURL("chrome://foo"),
+      fileapi::kFileSystemTypeExternal,
+      base::FilePath(FPL("removable/")));
+  // Internal WebUI should have full access.
+  EXPECT_TRUE(provider.IsAccessAllowed(internal_url));
+}
+
+TEST(CrosMountPointProvider, GetVirtualPathConflictWithSystemPoints) {
+  scoped_refptr<quota::MockSpecialStoragePolicy> storage_policy =
+      new quota::MockSpecialStoragePolicy();
+  scoped_refptr<fileapi::ExternalMountPoints> mount_points(
+      fileapi::ExternalMountPoints::CreateRefCounted());
+  scoped_refptr<fileapi::ExternalMountPoints> system_mount_points(
+      fileapi::ExternalMountPoints::CreateRefCounted());
+  chromeos::CrosMountPointProvider provider(storage_policy,
+      mount_points.get(),
+      system_mount_points.get());
+
+  const fileapi::FileSystemType type = fileapi::kFileSystemTypeNativeLocal;
+
+  // Provider specific mount points.
+  ASSERT_TRUE(
+      mount_points->RegisterFileSystem("b", type, base::FilePath(FPL("/a/b"))));
+  ASSERT_TRUE(
+      mount_points->RegisterFileSystem("y", type, base::FilePath(FPL("/z/y"))));
+  ASSERT_TRUE(
+      mount_points->RegisterFileSystem("n", type, base::FilePath(FPL("/m/n"))));
+
+  // System mount points
+  ASSERT_TRUE(system_mount_points->RegisterFileSystem(
+      "gb", type, base::FilePath(FPL("/a/b"))));
+  ASSERT_TRUE(
+      system_mount_points->RegisterFileSystem(
+          "gz", type, base::FilePath(FPL("/z"))));
+  ASSERT_TRUE(system_mount_points->RegisterFileSystem(
+       "gp", type, base::FilePath(FPL("/m/n/o/p"))));
+
+  struct TestCase {
+    const base::FilePath::CharType* const local_path;
+    bool success;
+    const base::FilePath::CharType* const virtual_path;
+  };
+
+  const TestCase kTestCases[] = {
+    // Same paths in both mount points.
+    { FPL("/a/b/c/d"), true, FPL("b/c/d") },
+    // System mount points path more specific.
+    { FPL("/m/n/o/p/r/s"), true, FPL("n/o/p/r/s") },
+    // System mount points path less specific.
+    { FPL("/z/y/x"), true, FPL("y/x") },
+    // Only system mount points path matches.
+    { FPL("/z/q/r/s"), true, FPL("gz/q/r/s") },
+    // No match.
+    { FPL("/foo/xxx"), false, FPL("") },
+  };
+
+  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) {
+    // Initialize virtual path with a value.
+    base::FilePath virtual_path(FPL("/mount"));
+    base::FilePath local_path(kTestCases[i].local_path);
+    EXPECT_EQ(kTestCases[i].success,
+              provider.GetVirtualPath(local_path, &virtual_path))
+        << "Resolving " << kTestCases[i].local_path;
+
+    // There are no guarantees for |virtual_path| value if |GetVirtualPath|
+    // fails.
+    if (!kTestCases[i].success)
+      continue;
+
+    base::FilePath expected_virtual_path(kTestCases[i].virtual_path);
+    EXPECT_EQ(expected_virtual_path, virtual_path)
+        << "Resolving " << kTestCases[i].local_path;
+  }
+}
+
+}  // namespace
diff --git a/chrome/browser/chromeos/fileapi/file_access_permissions.cc b/chrome/browser/chromeos/fileapi/file_access_permissions.cc
new file mode 100644
index 0000000..dba65b3
--- /dev/null
+++ b/chrome/browser/chromeos/fileapi/file_access_permissions.cc
@@ -0,0 +1,58 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/fileapi/file_access_permissions.h"
+
+#include "base/command_line.h"
+#include "base/logging.h"
+
+namespace chromeos {
+
+FileAccessPermissions::FileAccessPermissions() {}
+
+FileAccessPermissions::~FileAccessPermissions() {}
+
+
+void FileAccessPermissions::GrantAccessPermission(
+    const std::string& extension_id, const base::FilePath& path) {
+  base::AutoLock locker(lock_);
+  PathAccessMap::iterator path_map_iter = path_map_.find(extension_id);
+  if (path_map_iter == path_map_.end()) {
+    PathSet path_set;
+    path_set.insert(path);
+    path_map_.insert(PathAccessMap::value_type(extension_id, path_set));
+  } else {
+    if (path_map_iter->second.find(path) != path_map_iter->second.end())
+      return;
+    path_map_iter->second.insert(path);
+  }
+}
+
+bool FileAccessPermissions::HasAccessPermission(
+    const std::string& extension_id, const base::FilePath& path) const {
+  base::AutoLock locker(lock_);
+  PathAccessMap::const_iterator path_map_iter = path_map_.find(extension_id);
+  if (path_map_iter == path_map_.end())
+    return false;
+
+  // Check this file and walk up its directory tree to find if this extension
+  // has access to it.
+  base::FilePath current_path = path.StripTrailingSeparators();
+  base::FilePath last_path;
+  while (current_path != last_path) {
+    if (path_map_iter->second.find(current_path) != path_map_iter->second.end())
+      return true;
+    last_path = current_path;
+    current_path = current_path.DirName();
+  }
+  return false;
+}
+
+void FileAccessPermissions::RevokePermissions(
+    const std::string& extension_id) {
+  base::AutoLock locker(lock_);
+  path_map_.erase(extension_id);
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/fileapi/file_access_permissions.h b/chrome/browser/chromeos/fileapi/file_access_permissions.h
new file mode 100644
index 0000000..165ac27
--- /dev/null
+++ b/chrome/browser/chromeos/fileapi/file_access_permissions.h
@@ -0,0 +1,45 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_FILEAPI_FILE_ACCESS_PERMISSIONS_H_
+#define CHROME_BROWSER_CHROMEOS_FILEAPI_FILE_ACCESS_PERMISSIONS_H_
+
+#include <map>
+#include <set>
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/files/file_path.h"
+#include "base/synchronization/lock.h"
+#include "webkit/browser/webkit_storage_browser_export.h"
+
+namespace chromeos {
+
+class FileAccessPermissions {
+ public:
+  FileAccessPermissions();
+  virtual ~FileAccessPermissions();
+
+  // Grants |extension_id| access to |path|.
+  void GrantAccessPermission(const std::string& extension_id,
+                             const base::FilePath& path);
+  // Checks id |extension_id| has permission to access to |path|.
+  bool HasAccessPermission(const std::string& extension_id,
+                           const base::FilePath& path) const;
+  // Revokes all file permissions for |extension_id|.
+  void RevokePermissions(const std::string& extension_id);
+
+ private:
+  typedef std::set<base::FilePath> PathSet;
+  typedef std::map<std::string, PathSet> PathAccessMap;
+
+  mutable base::Lock lock_;  // Synchronize all access to path_map_.
+  PathAccessMap path_map_;
+
+  DISALLOW_COPY_AND_ASSIGN(FileAccessPermissions);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_FILEAPI_FILE_ACCESS_PERMISSIONS_H_
diff --git a/chrome/browser/chromeos/fileapi/file_access_permissions_unittest.cc b/chrome/browser/chromeos/fileapi/file_access_permissions_unittest.cc
new file mode 100644
index 0000000..f0f466c
--- /dev/null
+++ b/chrome/browser/chromeos/fileapi/file_access_permissions_unittest.cc
@@ -0,0 +1,62 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/fileapi/file_access_permissions.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromeos {
+
+TEST(FileAccessPermissionsTest, FileAccessChecks) {
+  base::FilePath good_dir(FILE_PATH_LITERAL("/root/dir"));
+  base::FilePath bad_dir(FILE_PATH_LITERAL("/root"));
+  base::FilePath good_file(FILE_PATH_LITERAL("/root/dir/good_file.txt"));
+  base::FilePath bad_file(FILE_PATH_LITERAL("/root/dir/bad_file.txt"));
+
+  std::string extension1("ddammdhioacbehjngdmkjcjbnfginlla");
+  std::string extension2("jkhdjkhkhsdkfhsdkhrterwmtermeter");
+
+  FileAccessPermissions permissions;
+  // By default extension have no access to any local file.
+  EXPECT_FALSE(permissions.HasAccessPermission(extension1, good_dir));
+  EXPECT_FALSE(permissions.HasAccessPermission(extension1, good_file));
+  EXPECT_FALSE(permissions.HasAccessPermission(extension1, bad_file));
+  EXPECT_FALSE(permissions.HasAccessPermission(extension2, good_dir));
+  EXPECT_FALSE(permissions.HasAccessPermission(extension2, good_file));
+  EXPECT_FALSE(permissions.HasAccessPermission(extension2, bad_file));
+
+  // After granting file access to the handler extension for a given file, it
+  // can only access that file an nothing else.
+  permissions.GrantAccessPermission(extension1, good_file);
+  EXPECT_FALSE(permissions.HasAccessPermission(extension1, good_dir));
+  EXPECT_TRUE(permissions.HasAccessPermission(extension1, good_file));
+  EXPECT_FALSE(permissions.HasAccessPermission(extension1, bad_file));
+  EXPECT_FALSE(permissions.HasAccessPermission(extension2, good_dir));
+  EXPECT_FALSE(permissions.HasAccessPermission(extension2, good_file));
+  EXPECT_FALSE(permissions.HasAccessPermission(extension2, bad_file));
+
+
+  // After granting file access to the handler extension for a given directory,
+  // it can access that directory and all files within it.
+  permissions.GrantAccessPermission(extension2, good_dir);
+  EXPECT_FALSE(permissions.HasAccessPermission(extension1, good_dir));
+  EXPECT_TRUE(permissions.HasAccessPermission(extension1, good_file));
+  EXPECT_FALSE(permissions.HasAccessPermission(extension1, bad_file));
+  EXPECT_TRUE(permissions.HasAccessPermission(extension2, good_dir));
+  EXPECT_TRUE(permissions.HasAccessPermission(extension2, good_file));
+  EXPECT_TRUE(permissions.HasAccessPermission(extension2, bad_file));
+
+  // After revoking rights for extensions, they should not be able to access
+  // any file system element anymore.
+  permissions.RevokePermissions(extension1);
+  permissions.RevokePermissions(extension2);
+  EXPECT_FALSE(permissions.HasAccessPermission(extension1, good_dir));
+  EXPECT_FALSE(permissions.HasAccessPermission(extension1, good_file));
+  EXPECT_FALSE(permissions.HasAccessPermission(extension1, bad_file));
+  EXPECT_FALSE(permissions.HasAccessPermission(extension2, good_dir));
+  EXPECT_FALSE(permissions.HasAccessPermission(extension2, good_file));
+  EXPECT_FALSE(permissions.HasAccessPermission(extension2, bad_file));
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/fileapi/remote_file_stream_writer.cc b/chrome/browser/chromeos/fileapi/remote_file_stream_writer.cc
new file mode 100644
index 0000000..5f2db47
--- /dev/null
+++ b/chrome/browser/chromeos/fileapi/remote_file_stream_writer.cc
@@ -0,0 +1,122 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/fileapi/remote_file_stream_writer.h"
+
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "webkit/browser/blob/local_file_stream_reader.h"
+#include "webkit/browser/fileapi/local_file_stream_writer.h"
+#include "webkit/browser/fileapi/remote_file_system_proxy.h"
+#include "webkit/common/blob/shareable_file_reference.h"
+
+namespace chromeos {
+
+RemoteFileStreamWriter::RemoteFileStreamWriter(
+    const scoped_refptr<fileapi::RemoteFileSystemProxyInterface>&
+        remote_filesystem,
+    const fileapi::FileSystemURL& url,
+    int64 offset,
+    base::TaskRunner *local_task_runner)
+    : remote_filesystem_(remote_filesystem),
+      local_task_runner_(local_task_runner),
+      url_(url),
+      initial_offset_(offset),
+      has_pending_create_snapshot_(false),
+      weak_factory_(this) {
+}
+
+RemoteFileStreamWriter::~RemoteFileStreamWriter() {
+}
+
+int RemoteFileStreamWriter::Write(net::IOBuffer* buf,
+                                  int buf_len,
+                                  const net::CompletionCallback& callback) {
+  DCHECK(!has_pending_create_snapshot_);
+  DCHECK(pending_cancel_callback_.is_null());
+
+  if (!local_file_writer_) {
+    has_pending_create_snapshot_ = true;
+    // In this RemoteFileStreamWriter, we only create snapshot file and don't
+    // have explicit close operation. This is ok, because close is automatically
+    // triggered by a refcounted |file_ref_| passed to OnFileOpened, from the
+    // destructor of RemoteFileStreamWriter.
+    remote_filesystem_->CreateWritableSnapshotFile(
+        url_,
+        base::Bind(&RemoteFileStreamWriter::OnFileOpened,
+                   weak_factory_.GetWeakPtr(),
+                   make_scoped_refptr(buf),
+                   buf_len,
+                   callback));
+    return net::ERR_IO_PENDING;
+  }
+  return local_file_writer_->Write(buf, buf_len, callback);
+}
+
+void RemoteFileStreamWriter::OnFileOpened(
+    net::IOBuffer* buf,
+    int buf_len,
+    const net::CompletionCallback& callback,
+    base::PlatformFileError open_result,
+    const base::FilePath& local_path,
+    const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) {
+  has_pending_create_snapshot_ = false;
+  if (!pending_cancel_callback_.is_null()) {
+    InvokePendingCancelCallback(net::OK);
+    return;
+  }
+
+  if (open_result != base::PLATFORM_FILE_OK) {
+    callback.Run(net::PlatformFileErrorToNetError(open_result));
+    return;
+  }
+
+  // Hold the reference to the file. Releasing the reference notifies the file
+  // system about to close file.
+  file_ref_ = file_ref;
+
+  DCHECK(!local_file_writer_.get());
+  local_file_writer_.reset(new fileapi::LocalFileStreamWriter(
+      local_task_runner_, local_path, initial_offset_));
+  int result = local_file_writer_->Write(buf, buf_len, callback);
+  if (result != net::ERR_IO_PENDING)
+    callback.Run(result);
+}
+
+int RemoteFileStreamWriter::Cancel(const net::CompletionCallback& callback) {
+  DCHECK(!callback.is_null());
+  DCHECK(pending_cancel_callback_.is_null());
+
+  // If file open operation is in-flight, wait for its completion and cancel
+  // further write operation in OnFileOpened.
+  if (has_pending_create_snapshot_) {
+    pending_cancel_callback_ = callback;
+    return net::ERR_IO_PENDING;
+  }
+
+  // If LocalFileWriter is already created, just delegate the cancel to it.
+  if (local_file_writer_) {
+    pending_cancel_callback_ = callback;
+    return local_file_writer_->Cancel(
+        base::Bind(&RemoteFileStreamWriter::InvokePendingCancelCallback,
+                   weak_factory_.GetWeakPtr()));
+  }
+
+  // Write() is not called yet.
+  return net::ERR_UNEXPECTED;
+}
+
+int RemoteFileStreamWriter::Flush(const net::CompletionCallback& callback) {
+  // For remote file writer, Flush() is a no-op. Synchronization to the remote
+  // server is not done until the file is closed.
+  return net::OK;
+}
+
+void RemoteFileStreamWriter::InvokePendingCancelCallback(int result) {
+  net::CompletionCallback callback = pending_cancel_callback_;
+  pending_cancel_callback_.Reset();
+  callback.Run(result);
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/fileapi/remote_file_stream_writer.h b/chrome/browser/chromeos/fileapi/remote_file_stream_writer.h
new file mode 100644
index 0000000..c1f3aff
--- /dev/null
+++ b/chrome/browser/chromeos/fileapi/remote_file_stream_writer.h
@@ -0,0 +1,82 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_FILEAPI_REMOTE_FILE_STREAM_WRITER_H_
+#define CHROME_BROWSER_CHROMEOS_FILEAPI_REMOTE_FILE_STREAM_WRITER_H_
+
+#include "base/basictypes.h"
+#include "base/files/file_path.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/platform_file.h"
+#include "webkit/browser/fileapi/file_stream_writer.h"
+#include "webkit/browser/fileapi/file_system_context.h"
+#include "webkit/browser/fileapi/file_system_url.h"
+
+namespace fileapi {
+class RemoteFileSystemProxyInterface;
+}
+
+namespace net {
+class IOBuffer;
+}
+
+namespace webkit_blob {
+class ShareableFileReference;
+}
+
+namespace chromeos {
+
+// FileStreamWriter interface for writing to a file on remote file system.
+class RemoteFileStreamWriter : public fileapi::FileStreamWriter {
+ public:
+  // Creates a writer for a file on |remote_filesystem| with path url |url|
+  // (like "filesystem:chrome-extension://id/external/drive/...") that
+  // starts writing from |offset|. When invalid parameters are set, the first
+  // call to Write() method fails.
+  // Uses |local_task_runner| for local file operations.
+  RemoteFileStreamWriter(
+      const scoped_refptr<fileapi::RemoteFileSystemProxyInterface>&
+          remote_filesystem,
+      const fileapi::FileSystemURL& url,
+      int64 offset,
+      base::TaskRunner* local_task_runner);
+  virtual ~RemoteFileStreamWriter();
+
+  // FileWriter override.
+  virtual int Write(net::IOBuffer* buf, int buf_len,
+                    const net::CompletionCallback& callback) OVERRIDE;
+  virtual int Cancel(const net::CompletionCallback& callback) OVERRIDE;
+  virtual int Flush(const net::CompletionCallback& callback) OVERRIDE;
+
+ private:
+  // Callback function to do the continuation of the work of the first Write()
+  // call, which tries to open the local copy of the file before writing.
+  void OnFileOpened(
+      net::IOBuffer* buf,
+      int buf_len,
+      const net::CompletionCallback& callback,
+      base::PlatformFileError open_result,
+      const base::FilePath& local_path,
+      const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref);
+  // Calls |pending_cancel_callback_|, assuming it is non-null.
+  void InvokePendingCancelCallback(int result);
+
+  scoped_refptr<fileapi::RemoteFileSystemProxyInterface> remote_filesystem_;
+  scoped_refptr<base::TaskRunner> local_task_runner_;
+  const fileapi::FileSystemURL url_;
+  const int64 initial_offset_;
+  scoped_ptr<fileapi::FileStreamWriter> local_file_writer_;
+  scoped_refptr<webkit_blob::ShareableFileReference> file_ref_;
+  bool has_pending_create_snapshot_;
+  net::CompletionCallback pending_cancel_callback_;
+
+  base::WeakPtrFactory<RemoteFileStreamWriter> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(RemoteFileStreamWriter);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_FILEAPI_REMOTE_FILE_STREAM_WRITER_H_
diff --git a/chrome/browser/chromeos/fileapi/remote_file_system_operation.cc b/chrome/browser/chromeos/fileapi/remote_file_system_operation.cc
new file mode 100644
index 0000000..2a036d2
--- /dev/null
+++ b/chrome/browser/chromeos/fileapi/remote_file_system_operation.cc
@@ -0,0 +1,245 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/fileapi/remote_file_system_operation.h"
+
+#include "base/bind.h"
+#include "base/platform_file.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/chromeos/fileapi/remote_file_stream_writer.h"
+#include "googleurl/src/gurl.h"
+#include "net/url_request/url_request.h"
+#include "webkit/browser/fileapi/file_system_url.h"
+#include "webkit/browser/fileapi/file_writer_delegate.h"
+
+using fileapi::FileSystemURL;
+
+namespace chromeos {
+
+RemoteFileSystemOperation::RemoteFileSystemOperation(
+    scoped_refptr<fileapi::RemoteFileSystemProxyInterface> remote_proxy)
+      : remote_proxy_(remote_proxy),
+        pending_operation_(kOperationNone) {
+}
+
+RemoteFileSystemOperation::~RemoteFileSystemOperation() {
+}
+
+void RemoteFileSystemOperation::GetMetadata(const FileSystemURL& url,
+    const GetMetadataCallback& callback) {
+  DCHECK(SetPendingOperationType(kOperationGetMetadata));
+  remote_proxy_->GetFileInfo(url, callback);
+}
+
+void RemoteFileSystemOperation::DirectoryExists(const FileSystemURL& url,
+    const StatusCallback& callback) {
+  DCHECK(SetPendingOperationType(kOperationDirectoryExists));
+  remote_proxy_->GetFileInfo(url,
+      base::Bind(&RemoteFileSystemOperation::DidDirectoryExists,
+                 AsWeakPtr(), callback));
+}
+
+void RemoteFileSystemOperation::FileExists(const FileSystemURL& url,
+    const StatusCallback& callback) {
+  DCHECK(SetPendingOperationType(kOperationFileExists));
+  remote_proxy_->GetFileInfo(url,
+      base::Bind(base::Bind(&RemoteFileSystemOperation::DidFileExists,
+                            AsWeakPtr(), callback)));
+}
+
+void RemoteFileSystemOperation::ReadDirectory(const FileSystemURL& url,
+    const ReadDirectoryCallback& callback) {
+  DCHECK(SetPendingOperationType(kOperationReadDirectory));
+  remote_proxy_->ReadDirectory(url, callback);
+}
+
+void RemoteFileSystemOperation::Remove(const FileSystemURL& url, bool recursive,
+                                       const StatusCallback& callback) {
+  DCHECK(SetPendingOperationType(kOperationRemove));
+  remote_proxy_->Remove(url, recursive,
+      base::Bind(&RemoteFileSystemOperation::DidFinishFileOperation,
+                 AsWeakPtr(), callback));
+}
+
+
+void RemoteFileSystemOperation::CreateDirectory(
+    const FileSystemURL& url, bool exclusive, bool recursive,
+    const StatusCallback& callback) {
+  DCHECK(SetPendingOperationType(kOperationCreateDirectory));
+  remote_proxy_->CreateDirectory(url, exclusive, recursive,
+      base::Bind(&RemoteFileSystemOperation::DidFinishFileOperation,
+                 AsWeakPtr(), callback));
+}
+
+void RemoteFileSystemOperation::CreateFile(const FileSystemURL& url,
+                                           bool exclusive,
+                                           const StatusCallback& callback) {
+  DCHECK(SetPendingOperationType(kOperationCreateFile));
+  remote_proxy_->CreateFile(url, exclusive,
+      base::Bind(&RemoteFileSystemOperation::DidFinishFileOperation,
+                 AsWeakPtr(), callback));
+}
+
+void RemoteFileSystemOperation::Copy(const FileSystemURL& src_url,
+                                     const FileSystemURL& dest_url,
+                                     const StatusCallback& callback) {
+  DCHECK(SetPendingOperationType(kOperationCopy));
+
+  remote_proxy_->Copy(src_url, dest_url,
+      base::Bind(&RemoteFileSystemOperation::DidFinishFileOperation,
+                 AsWeakPtr(), callback));
+}
+
+void RemoteFileSystemOperation::Move(const FileSystemURL& src_url,
+                                     const FileSystemURL& dest_url,
+                                     const StatusCallback& callback) {
+  DCHECK(SetPendingOperationType(kOperationMove));
+
+  remote_proxy_->Move(src_url, dest_url,
+      base::Bind(&RemoteFileSystemOperation::DidFinishFileOperation,
+                 AsWeakPtr(), callback));
+}
+
+void RemoteFileSystemOperation::Write(
+    const FileSystemURL& url,
+    scoped_ptr<fileapi::FileWriterDelegate> writer_delegate,
+    scoped_ptr<net::URLRequest> blob_request,
+    const WriteCallback& callback) {
+  DCHECK(SetPendingOperationType(kOperationWrite));
+  file_writer_delegate_ = writer_delegate.Pass();
+  file_writer_delegate_->Start(
+      blob_request.Pass(),
+      base::Bind(&RemoteFileSystemOperation::DidWrite, AsWeakPtr(), callback));
+}
+
+void RemoteFileSystemOperation::Truncate(const FileSystemURL& url,
+                                         int64 length,
+                                         const StatusCallback& callback) {
+  DCHECK(SetPendingOperationType(kOperationTruncate));
+
+  remote_proxy_->Truncate(url, length,
+      base::Bind(&RemoteFileSystemOperation::DidFinishFileOperation,
+                 AsWeakPtr(), callback));
+}
+
+void RemoteFileSystemOperation::Cancel(const StatusCallback& cancel_callback) {
+  DCHECK(cancel_callback_.is_null());
+  cancel_callback_ = cancel_callback;
+
+  if (file_writer_delegate_) {
+    DCHECK_EQ(kOperationWrite, pending_operation_);
+    // This will call DidWrite() with ABORT status code.
+    file_writer_delegate_->Cancel();
+  } else {
+    // For truncate we have no way to cancel the inflight operation (for now).
+    // Let it just run and dispatch cancel callback later.
+    DCHECK_EQ(kOperationTruncate, pending_operation_);
+  }
+}
+
+void RemoteFileSystemOperation::TouchFile(const FileSystemURL& url,
+                                          const base::Time& last_access_time,
+                                          const base::Time& last_modified_time,
+                                          const StatusCallback& callback) {
+  DCHECK(SetPendingOperationType(kOperationTouchFile));
+  remote_proxy_->TouchFile(
+      url,
+      last_access_time,
+      last_modified_time,
+      base::Bind(&RemoteFileSystemOperation::DidFinishFileOperation,
+                 AsWeakPtr(), callback));
+}
+
+void RemoteFileSystemOperation::OpenFile(const FileSystemURL& url,
+                                         int file_flags,
+                                         base::ProcessHandle peer_handle,
+                                         const OpenFileCallback& callback) {
+  DCHECK(SetPendingOperationType(kOperationOpenFile));
+  remote_proxy_->OpenFile(
+      url,
+      file_flags,
+      peer_handle,
+      base::Bind(&RemoteFileSystemOperation::DidOpenFile,
+                 AsWeakPtr(), url, callback));
+}
+
+fileapi::LocalFileSystemOperation*
+RemoteFileSystemOperation::AsLocalFileSystemOperation() {
+  NOTIMPLEMENTED();
+  return NULL;
+}
+
+void RemoteFileSystemOperation::CreateSnapshotFile(
+    const FileSystemURL& url,
+    const SnapshotFileCallback& callback) {
+  DCHECK(SetPendingOperationType(kOperationCreateSnapshotFile));
+  remote_proxy_->CreateSnapshotFile(url, callback);
+}
+
+bool RemoteFileSystemOperation::SetPendingOperationType(OperationType type) {
+  if (pending_operation_ != kOperationNone)
+    return false;
+  pending_operation_ = type;
+  return true;
+}
+
+void RemoteFileSystemOperation::DidDirectoryExists(
+    const StatusCallback& callback,
+    base::PlatformFileError rv,
+    const base::PlatformFileInfo& file_info) {
+  if (rv == base::PLATFORM_FILE_OK && !file_info.is_directory)
+    rv = base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY;
+  callback.Run(rv);
+}
+
+void RemoteFileSystemOperation::DidFileExists(
+    const StatusCallback& callback,
+    base::PlatformFileError rv,
+    const base::PlatformFileInfo& file_info) {
+  if (rv == base::PLATFORM_FILE_OK && file_info.is_directory)
+    rv = base::PLATFORM_FILE_ERROR_NOT_A_FILE;
+  callback.Run(rv);
+}
+
+void RemoteFileSystemOperation::DidWrite(
+    const WriteCallback& write_callback,
+    base::PlatformFileError rv,
+    int64 bytes,
+    FileWriterDelegate::WriteProgressStatus write_status) {
+  bool complete = (write_status != FileWriterDelegate::SUCCESS_IO_PENDING);
+  StatusCallback cancel_callback = cancel_callback_;
+  write_callback.Run(rv, bytes, complete);
+  if (!cancel_callback.is_null())
+    cancel_callback.Run(base::PLATFORM_FILE_OK);
+}
+
+void RemoteFileSystemOperation::DidFinishFileOperation(
+    const StatusCallback& callback,
+    base::PlatformFileError rv) {
+  if (!cancel_callback_.is_null()) {
+    DCHECK_EQ(kOperationTruncate, pending_operation_);
+
+    StatusCallback cancel_callback = cancel_callback_;
+    callback.Run(base::PLATFORM_FILE_ERROR_ABORT);
+    cancel_callback.Run(base::PLATFORM_FILE_OK);
+  } else {
+    callback.Run(rv);
+  }
+}
+
+void RemoteFileSystemOperation::DidOpenFile(
+    const fileapi::FileSystemURL& url,
+    const OpenFileCallback& callback,
+    base::PlatformFileError result,
+    base::PlatformFile file,
+    base::ProcessHandle peer_handle) {
+  callback.Run(
+      result, file,
+      base::Bind(&fileapi::RemoteFileSystemProxyInterface::NotifyCloseFile,
+                 remote_proxy_, url),
+      peer_handle);
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/fileapi/remote_file_system_operation.h b/chrome/browser/chromeos/fileapi/remote_file_system_operation.h
new file mode 100644
index 0000000..95f1142
--- /dev/null
+++ b/chrome/browser/chromeos/fileapi/remote_file_system_operation.h
@@ -0,0 +1,121 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_FILEAPI_REMOTE_FILE_SYSTEM_OPERATION_H_
+#define CHROME_BROWSER_CHROMEOS_FILEAPI_REMOTE_FILE_SYSTEM_OPERATION_H_
+
+#include "base/basictypes.h"
+#include "base/memory/weak_ptr.h"
+#include "webkit/browser/fileapi/file_system_operation.h"
+#include "webkit/browser/fileapi/file_writer_delegate.h"
+#include "webkit/browser/fileapi/remote_file_system_proxy.h"
+
+namespace base {
+class Value;
+}
+
+namespace fileapi {
+class FileWriterDelegate;
+class LocalFileSystemOperation;
+}
+
+namespace chromeos {
+
+// FileSystemOperation implementation for local file systems.
+class RemoteFileSystemOperation
+    : public fileapi::FileSystemOperation,
+      public base::SupportsWeakPtr<RemoteFileSystemOperation> {
+ public:
+  typedef fileapi::FileWriterDelegate FileWriterDelegate;
+  virtual ~RemoteFileSystemOperation();
+
+  // FileSystemOperation overrides.
+  virtual void CreateFile(const fileapi::FileSystemURL& url,
+                          bool exclusive,
+                          const StatusCallback& callback) OVERRIDE;
+  virtual void CreateDirectory(const fileapi::FileSystemURL& url,
+                               bool exclusive,
+                               bool recursive,
+                               const StatusCallback& callback) OVERRIDE;
+  virtual void Copy(const fileapi::FileSystemURL& src_url,
+                    const fileapi::FileSystemURL& dest_url,
+                    const StatusCallback& callback) OVERRIDE;
+  virtual void Move(const fileapi::FileSystemURL& src_url,
+                    const fileapi::FileSystemURL& dest_url,
+                    const StatusCallback& callback) OVERRIDE;
+  virtual void DirectoryExists(const fileapi::FileSystemURL& url,
+                               const StatusCallback& callback) OVERRIDE;
+  virtual void FileExists(const fileapi::FileSystemURL& url,
+                          const StatusCallback& callback) OVERRIDE;
+  virtual void GetMetadata(const fileapi::FileSystemURL& url,
+                           const GetMetadataCallback& callback) OVERRIDE;
+  virtual void ReadDirectory(const fileapi::FileSystemURL& url,
+                             const ReadDirectoryCallback& callback) OVERRIDE;
+  virtual void Remove(const fileapi::FileSystemURL& url, bool recursive,
+                      const StatusCallback& callback) OVERRIDE;
+  virtual void Write(const fileapi::FileSystemURL& url,
+                     scoped_ptr<fileapi::FileWriterDelegate> writer_delegate,
+                     scoped_ptr<net::URLRequest> blob_request,
+                     const WriteCallback& callback) OVERRIDE;
+  virtual void Truncate(const fileapi::FileSystemURL& url, int64 length,
+                        const StatusCallback& callback) OVERRIDE;
+  virtual void Cancel(const StatusCallback& cancel_callback) OVERRIDE;
+  virtual void TouchFile(const fileapi::FileSystemURL& url,
+                         const base::Time& last_access_time,
+                         const base::Time& last_modified_time,
+                         const StatusCallback& callback) OVERRIDE;
+  virtual void OpenFile(
+      const fileapi::FileSystemURL& url,
+      int file_flags,
+      base::ProcessHandle peer_handle,
+      const OpenFileCallback& callback) OVERRIDE;
+  virtual fileapi::LocalFileSystemOperation*
+      AsLocalFileSystemOperation() OVERRIDE;
+  virtual void CreateSnapshotFile(
+      const fileapi::FileSystemURL& url,
+      const SnapshotFileCallback& callback) OVERRIDE;
+
+ private:
+  friend class CrosMountPointProvider;
+
+  RemoteFileSystemOperation(
+      scoped_refptr<fileapi::RemoteFileSystemProxyInterface> remote_proxy);
+
+  // Used only for internal assertions.
+  // Returns false if there's another inflight pending operation.
+  bool SetPendingOperationType(OperationType type);
+
+  // Generic callback that translates platform errors to WebKit error codes.
+  void DidDirectoryExists(const StatusCallback& callback,
+                          base::PlatformFileError rv,
+                          const base::PlatformFileInfo& file_info);
+  void DidFileExists(const StatusCallback& callback,
+                     base::PlatformFileError rv,
+                     const base::PlatformFileInfo& file_info);
+  void DidWrite(const WriteCallback& write_callback,
+                base::PlatformFileError result,
+                int64 bytes,
+                FileWriterDelegate::WriteProgressStatus write_status);
+  void DidFinishFileOperation(const StatusCallback& callback,
+                              base::PlatformFileError rv);
+  void DidOpenFile(
+      const fileapi::FileSystemURL& url,
+      const OpenFileCallback& callback,
+      base::PlatformFileError result,
+      base::PlatformFile file,
+      base::ProcessHandle peer_handle);
+
+  scoped_refptr<fileapi::RemoteFileSystemProxyInterface> remote_proxy_;
+  // A flag to make sure we call operation only once per instance.
+  OperationType pending_operation_;
+  scoped_ptr<fileapi::FileWriterDelegate> file_writer_delegate_;
+
+  StatusCallback cancel_callback_;
+
+  DISALLOW_COPY_AND_ASSIGN(RemoteFileSystemOperation);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_FILEAPI_REMOTE_FILE_SYSTEM_OPERATION_H_
diff --git a/chrome/browser/chromeos/imageburner/burn_manager.cc b/chrome/browser/chromeos/imageburner/burn_manager.cc
index 9630131..9d3ab26 100644
--- a/chrome/browser/chromeos/imageburner/burn_manager.cc
+++ b/chrome/browser/chromeos/imageburner/burn_manager.cc
@@ -27,9 +27,6 @@
 
 namespace {
 
-// Name for hwid in machine statistics.
-const char kHwidStatistic[] = "hardware_class";
-
 const char kConfigFileUrl[] =
     "https://dl.google.com/dl/edgedl/chromeos/recovery/recovery.conf";
 const char kTempImageFolderName[] = "chromeos_image";
@@ -241,7 +238,7 @@
 
 BurnManager::~BurnManager() {
   if (image_dir_created_) {
-    file_util::Delete(image_dir_, true);
+    base::Delete(image_dir_, true);
   }
   if (NetworkHandler::IsInitialized()) {
     NetworkHandler::Get()->network_state_handler()->RemoveObserver(
@@ -559,7 +556,7 @@
   // Get image file name and image download URL.
   std::string hwid;
   if (fetched && system::StatisticsProvider::GetInstance()->
-      GetMachineStatistic(kHwidStatistic, &hwid)) {
+      GetMachineStatistic(system::kHardwareClass, &hwid)) {
     ConfigFile config_file(content);
     image_file_name_ = config_file.GetProperty(kFileName, hwid);
     image_download_url_ = GURL(config_file.GetProperty(kUrl, hwid));
diff --git a/chrome/browser/chromeos/imageburner/burn_manager.h b/chrome/browser/chromeos/imageburner/burn_manager.h
index 11cd281..b44a307 100644
--- a/chrome/browser/chromeos/imageburner/burn_manager.h
+++ b/chrome/browser/chromeos/imageburner/burn_manager.h
@@ -15,7 +15,7 @@
 #include "base/memory/ref_counted_memory.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/observer_list.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/chromeos/imageburner/burn_device_handler.h"
 #include "chromeos/disks/disk_mount_manager.h"
 #include "chromeos/network/network_state_handler_observer.h"
diff --git a/chrome/browser/chromeos/input_method/component_extension_ime_manager_impl.cc b/chrome/browser/chromeos/input_method/component_extension_ime_manager_impl.cc
index 913844d..f2c0292 100644
--- a/chrome/browser/chromeos/input_method/component_extension_ime_manager_impl.cc
+++ b/chrome/browser/chromeos/input_method/component_extension_ime_manager_impl.cc
@@ -26,6 +26,16 @@
   const char* id;
   const char* path;
 } whitelisted_component_extension[] = {
+  {
+    // ChromeOS Keyboards extension.
+    "jhffeifommiaekmbkkjlpmilogcfdohp",
+    "/usr/share/chromeos-assets/input_methods/keyboard_layouts",
+  },
+  {
+    // ChromeOS Hangul Input.
+    "bdgdidmhaijohebebipajioienkglgfo",
+    "/usr/share/chromeos-assets/input_methods/hangul",
+  },
 #if defined(OFFICIAL_BUILD)
   {
     // Official Google Japanese Input.
@@ -53,17 +63,27 @@
     "/usr/share/chromeos-assets/input_methods/wubi",
   },
   {
-    // Chromeos Keyboard Layouts.
-    "jhffeifommiaekmbkkjlpmilogcfdohp",
-    "/usr/share/chromeos-assets/input_methods/keyboard_layouts",
-  },
-  {
     // Google input tools.
     "gjaehgfemfahhmlgpdfknkhdnemmolop",
     "/usr/share/chromeos-assets/input_methods/input_tools",
   },
 #else
   {
+    // Open-sourced Pinyin Chinese Input Method.
+    "cpgalbafkoofkjmaeonnfijgpfennjjn",
+    "/usr/share/chromeos-assets/input_methods/pinyin",
+  },
+  {
+    // Open-sourced Zhuyin Chinese Input Method.
+    "ekbifjdfhkmdeeajnolmgdlmkllopefi",
+    "/usr/share/chromeos-assets/input_methods/zhuyin",
+  },
+  {
+    // Open-sourced Cangjie Chinese Input Method.
+    "aeebooiibjahgpgmhkeocbeekccfknbj",
+    "/usr/share/chromeos-assets/input_methods/cangjie",
+  },
+  {
     // Open-sourced Mozc Japanese Input.
     "bbaiamgfapehflhememkfglaehiobjnk",
     "/usr/share/chromeos-assets/input_methods/nacl_mozc",
diff --git a/chrome/browser/chromeos/input_method/delayable_widget.h b/chrome/browser/chromeos/input_method/delayable_widget.h
index aa18ff2..8b4846c 100644
--- a/chrome/browser/chromeos/input_method/delayable_widget.h
+++ b/chrome/browser/chromeos/input_method/delayable_widget.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_CHROMEOS_INPUT_METHOD_DELAYABLE_WIDGET_H_
 #define CHROME_BROWSER_CHROMEOS_INPUT_METHOD_DELAYABLE_WIDGET_H_
 
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "ui/views/widget/widget.h"
 
 namespace chromeos {
diff --git a/chrome/browser/chromeos/input_method/input_method_engine_ibus.cc b/chrome/browser/chromeos/input_method/input_method_engine_ibus.cc
index a7b5056..25c9d4e 100644
--- a/chrome/browser/chromeos/input_method/input_method_engine_ibus.cc
+++ b/chrome/browser/chromeos/input_method/input_method_engine_ibus.cc
@@ -201,7 +201,7 @@
   GetCurrentService()->UpdatePreedit(
       *preedit_text_.get(),
       0,
-      true,
+      false,
       chromeos::IBusEngineService::IBUS_ENGINE_PREEEDIT_FOCUS_OUT_MODE_COMMIT);
   return true;
 }
diff --git a/chrome/browser/chromeos/input_method/input_method_engine_ibus_browserttests.cc b/chrome/browser/chromeos/input_method/input_method_engine_ibus_browserttests.cc
index 92fbe75..cda8462 100644
--- a/chrome/browser/chromeos/input_method/input_method_engine_ibus_browserttests.cc
+++ b/chrome/browser/chromeos/input_method/input_method_engine_ibus_browserttests.cc
@@ -5,6 +5,7 @@
 #include "base/bind_helpers.h"
 #include "chrome/browser/extensions/extension_browsertest.h"
 #include "chrome/browser/extensions/extension_test_message_listener.h"
+#include "chrome/common/extensions/background_info.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/ibus/mock_ibus_client.h"
 #include "chromeos/dbus/ibus/mock_ibus_engine_factory_service.h"
@@ -12,6 +13,7 @@
 #include "chromeos/dbus/mock_dbus_thread_manager_without_gmock.h"
 #include "chromeos/ime/input_method_descriptor.h"
 #include "chromeos/ime/input_method_manager.h"
+#include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_utils.h"
 #include "dbus/mock_bus.h"
 
@@ -62,6 +64,7 @@
 
   virtual void TearDownInProcessBrowserTestFixture() OVERRIDE {
     DBusThreadManager::Shutdown();
+    extension_ = NULL;
   }
 
  protected:
@@ -73,7 +76,8 @@
     // This will load "chrome/test/data/extensions/input_ime"
     ExtensionTestMessageListener ime_ready_listener("ReadyToUseImeEvent",
                                                     false);
-    ASSERT_TRUE(LoadExtensionWithType("input_ime", GetParam()));
+    extension_ = LoadExtensionWithType("input_ime", GetParam());
+    ASSERT_TRUE(extension_);
     ASSERT_TRUE(ime_ready_listener.WaitUntilSatisfied());
 
     // The reason why not EXPECT_EQ is that extension will be reloaded in the
@@ -103,8 +107,8 @@
     EXPECT_EQ(3U, extension_imes.size());
   }
 
-  bool LoadExtensionWithType(const std::string& extension_name,
-                             TestType type) {
+  const extensions::Extension* LoadExtensionWithType(
+      const std::string& extension_name, TestType type) {
     switch (type) {
       case kTestTypeNormal:
         return LoadExtension(test_data_dir_.AppendASCII(extension_name));
@@ -116,9 +120,10 @@
             test_data_dir_.AppendASCII(extension_name));
     }
     NOTREACHED();
-    return false;
+    return NULL;
   }
 
+  const extensions::Extension* extension_;
   MockDBusThreadManagerWithoutGMock* mock_dbus_thread_manager_;
   scoped_refptr<dbus::MockBus> mock_bus_;
 };
@@ -244,6 +249,11 @@
   IBusEngineHandlerInterface* engine_handler = engine_service->GetEngine();
   ASSERT_TRUE(engine_handler);
 
+  extensions::ExtensionHost* host = FindHostWithPath(
+      extensions::ExtensionSystem::Get(profile())->process_manager(),
+      extensions::BackgroundInfo::GetBackgroundURL(extension_).path(),
+      1);
+
   engine_handler->Enable();
   engine_handler->FocusIn();
 
@@ -360,6 +370,377 @@
     callback.WaitUntilCalled();
   }
   // TODO(nona): Add browser tests for other API as well.
+  {
+    SCOPED_TRACE("commitText test");
+    const char commit_text_test_script[] =
+        "chrome.input.ime.commitText({"
+        "  contextID: engineBridge.getFocusedContextID().contextID,"
+        "  text:'COMMIT_TEXT'"
+        "});";
+
+    engine_service->Clear();
+    ASSERT_TRUE(content::ExecuteScript(host->host_contents(),
+                                       commit_text_test_script));
+    EXPECT_EQ(1, engine_service->commit_text_call_count());
+    EXPECT_EQ("COMMIT_TEXT", engine_service->last_commit_text());
+  }
+  {
+    SCOPED_TRACE("setComposition test");
+    const char set_composition_test_script[] =
+        "chrome.input.ime.setComposition({"
+        "  contextID: engineBridge.getFocusedContextID().contextID,"
+        "  text:'COMPOSITION_TEXT',"
+        "  cursor:4,"
+        "  segments : [{"
+        "    start: 0,"
+        "    end: 5,"
+        "    style: 'underline'"
+        "  },{"
+        "    start: 6,"
+        "    end: 10,"
+        "    style: 'doubleUnderline'"
+        "  }]"
+        "});";
+
+    engine_service->Clear();
+    ASSERT_TRUE(content::ExecuteScript(host->host_contents(),
+                                       set_composition_test_script));
+    EXPECT_EQ(1, engine_service->update_preedit_call_count());
+
+    EXPECT_EQ(4U, engine_service->last_update_preedit_arg().cursor_pos);
+    EXPECT_TRUE(engine_service->last_update_preedit_arg().is_visible);
+
+    const IBusText& ibus_text =
+        engine_service->last_update_preedit_arg().ibus_text;
+    EXPECT_EQ("COMPOSITION_TEXT", ibus_text.text());
+    const std::vector<IBusText::UnderlineAttribute>& underlines =
+        ibus_text.underline_attributes();
+
+    ASSERT_EQ(2U, underlines.size());
+    EXPECT_EQ(IBusText::IBUS_TEXT_UNDERLINE_SINGLE, underlines[0].type);
+    EXPECT_EQ(0U, underlines[0].start_index);
+    EXPECT_EQ(5U, underlines[0].end_index);
+
+    EXPECT_EQ(IBusText::IBUS_TEXT_UNDERLINE_DOUBLE, underlines[1].type);
+    EXPECT_EQ(6U, underlines[1].start_index);
+    EXPECT_EQ(10U, underlines[1].end_index);
+  }
+  {
+    SCOPED_TRACE("clearComposition test");
+    const char commite_text_test_script[] =
+        "chrome.input.ime.clearComposition({"
+        "  contextID: engineBridge.getFocusedContextID().contextID,"
+        "});";
+
+    engine_service->Clear();
+    ASSERT_TRUE(content::ExecuteScript(host->host_contents(),
+                                       commite_text_test_script));
+    EXPECT_EQ(1, engine_service->update_preedit_call_count());
+    EXPECT_FALSE(engine_service->last_update_preedit_arg().is_visible);
+    const IBusText& ibus_text =
+        engine_service->last_update_preedit_arg().ibus_text;
+    EXPECT_TRUE(ibus_text.text().empty());
+  }
+  {
+    SCOPED_TRACE("setCandidateWindowProperties:visibility test");
+    const char set_candidate_window_properties_test_script[] =
+        "chrome.input.ime.setCandidateWindowProperties({"
+        "  engineID: engineBridge.getActiveEngineID(),"
+        "  properties: {"
+        "    visible: true,"
+        "  }"
+        "});";
+    engine_service->Clear();
+    ASSERT_TRUE(content::ExecuteScript(
+        host->host_contents(),
+        set_candidate_window_properties_test_script));
+    EXPECT_EQ(1, engine_service->update_lookup_table_call_count());
+    EXPECT_TRUE(engine_service->last_update_lookup_table_arg().is_visible);
+  }
+  {
+    SCOPED_TRACE("setCandidateWindowProperties:cursor_visibility test");
+    const char set_candidate_window_properties_test_script[] =
+        "chrome.input.ime.setCandidateWindowProperties({"
+        "  engineID: engineBridge.getActiveEngineID(),"
+        "  properties: {"
+        "    cursorVisible: true,"
+        "  }"
+        "});";
+    engine_service->Clear();
+    ASSERT_TRUE(content::ExecuteScript(
+        host->host_contents(),
+        set_candidate_window_properties_test_script));
+    EXPECT_EQ(1, engine_service->update_lookup_table_call_count());
+
+    // window visibility is kept as before.
+    EXPECT_TRUE(engine_service->last_update_lookup_table_arg().is_visible);
+
+    const IBusLookupTable& table =
+        engine_service->last_update_lookup_table_arg().lookup_table;
+    EXPECT_TRUE(table.is_cursor_visible());
+  }
+  {
+    SCOPED_TRACE("setCandidateWindowProperties:vertical test");
+    const char set_candidate_window_properties_test_script[] =
+        "chrome.input.ime.setCandidateWindowProperties({"
+        "  engineID: engineBridge.getActiveEngineID(),"
+        "  properties: {"
+        "    vertical: true,"
+        "  }"
+        "});";
+    engine_service->Clear();
+    ASSERT_TRUE(content::ExecuteScript(
+        host->host_contents(),
+        set_candidate_window_properties_test_script));
+    EXPECT_EQ(1, engine_service->update_lookup_table_call_count());
+
+    // window visibility is kept as before.
+    EXPECT_TRUE(engine_service->last_update_lookup_table_arg().is_visible);
+
+    const IBusLookupTable& table =
+        engine_service->last_update_lookup_table_arg().lookup_table;
+
+    // cursor visibility is kept as before.
+    EXPECT_TRUE(table.is_cursor_visible());
+
+    EXPECT_EQ(IBusLookupTable::VERTICAL, table.orientation());
+  }
+  {
+    SCOPED_TRACE("setCandidateWindowProperties:pageSize test");
+    const char set_candidate_window_properties_test_script[] =
+        "chrome.input.ime.setCandidateWindowProperties({"
+        "  engineID: engineBridge.getActiveEngineID(),"
+        "  properties: {"
+        "    pageSize: 7,"
+        "  }"
+        "});";
+    engine_service->Clear();
+    ASSERT_TRUE(content::ExecuteScript(
+        host->host_contents(),
+        set_candidate_window_properties_test_script));
+    EXPECT_EQ(1, engine_service->update_lookup_table_call_count());
+
+    // window visibility is kept as before.
+    EXPECT_TRUE(engine_service->last_update_lookup_table_arg().is_visible);
+
+    const IBusLookupTable& table =
+        engine_service->last_update_lookup_table_arg().lookup_table;
+
+    // cursor visibility is kept as before.
+    EXPECT_TRUE(table.is_cursor_visible());
+
+    // oritantation is kept as before.
+    EXPECT_EQ(IBusLookupTable::VERTICAL, table.orientation());
+
+    EXPECT_EQ(7U, table.page_size());
+  }
+  {
+    SCOPED_TRACE("setCandidateWindowProperties:auxTextVisibility test");
+    const char set_candidate_window_properties_test_script[] =
+        "chrome.input.ime.setCandidateWindowProperties({"
+        "  engineID: engineBridge.getActiveEngineID(),"
+        "  properties: {"
+        "    auxiliaryTextVisible: true"
+        "  }"
+        "});";
+    engine_service->Clear();
+    ASSERT_TRUE(content::ExecuteScript(
+        host->host_contents(),
+        set_candidate_window_properties_test_script));
+    EXPECT_EQ(1, engine_service->update_auxiliary_text_call_count());
+    EXPECT_TRUE(engine_service->last_update_aux_text_arg().is_visible);
+  }
+  {
+    SCOPED_TRACE("setCandidateWindowProperties:auxText test");
+    const char set_candidate_window_properties_test_script[] =
+        "chrome.input.ime.setCandidateWindowProperties({"
+        "  engineID: engineBridge.getActiveEngineID(),"
+        "  properties: {"
+        "    auxiliaryText: 'AUXILIARY_TEXT'"
+        "  }"
+        "});";
+    engine_service->Clear();
+    ASSERT_TRUE(content::ExecuteScript(
+        host->host_contents(),
+        set_candidate_window_properties_test_script));
+    EXPECT_EQ(1, engine_service->update_auxiliary_text_call_count());
+
+    // aux text visibility is kept as before.
+    EXPECT_TRUE(engine_service->last_update_aux_text_arg().is_visible);
+
+    EXPECT_EQ("AUXILIARY_TEXT",
+              engine_service->last_update_aux_text_arg().ibus_text.text());
+  }
+  {
+    SCOPED_TRACE("setCandidates test");
+    const char set_candidates_test_script[] =
+        "chrome.input.ime.setCandidates({"
+        "  contextID: engineBridge.getFocusedContextID().contextID,"
+        "  candidates: [{"
+        "    candidate: 'CANDIDATE_1',"
+        "    id: 1,"
+        "    },{"
+        "    candidate: 'CANDIDATE_2',"
+        "    id: 2,"
+        "    label: 'LABEL_2',"
+        "    },{"
+        "    candidate: 'CANDIDATE_3',"
+        "    id: 3,"
+        "    label: 'LABEL_3',"
+        "    annotation: 'ANNOTACTION_3'"
+        "    },{"
+        "    candidate: 'CANDIDATE_4',"
+        "    id: 4,"
+        "    label: 'LABEL_4',"
+        "    annotation: 'ANNOTACTION_4',"
+        "    usage: {"
+        "      title: 'TITLE_4',"
+        "      body: 'BODY_4'"
+        "    }"
+        "  }]"
+        "});";
+    engine_service->Clear();
+    ASSERT_TRUE(content::ExecuteScript(host->host_contents(),
+                                       set_candidates_test_script));
+
+    // window visibility is kept as before.
+    EXPECT_TRUE(engine_service->last_update_lookup_table_arg().is_visible);
+
+    const IBusLookupTable& table =
+        engine_service->last_update_lookup_table_arg().lookup_table;
+
+    // cursor visibility is kept as before.
+    EXPECT_TRUE(table.is_cursor_visible());
+
+    // oritantation is kept as before.
+    EXPECT_EQ(IBusLookupTable::VERTICAL, table.orientation());
+
+    // page size is kept as before.
+    EXPECT_EQ(7U, table.page_size());
+
+    ASSERT_EQ(4U, table.candidates().size());
+
+    EXPECT_EQ("CANDIDATE_1", table.candidates().at(0).value);
+
+    EXPECT_EQ("CANDIDATE_2", table.candidates().at(1).value);
+    EXPECT_EQ("LABEL_2", table.candidates().at(1).label);
+
+    EXPECT_EQ("CANDIDATE_3", table.candidates().at(2).value);
+    EXPECT_EQ("LABEL_3", table.candidates().at(2).label);
+    EXPECT_EQ("ANNOTACTION_3", table.candidates().at(2).annotation);
+
+    EXPECT_EQ("CANDIDATE_4", table.candidates().at(3).value);
+    EXPECT_EQ("LABEL_4", table.candidates().at(3).label);
+    EXPECT_EQ("ANNOTACTION_4", table.candidates().at(3).annotation);
+    EXPECT_EQ("TITLE_4", table.candidates().at(3).description_title);
+    EXPECT_EQ("BODY_4", table.candidates().at(3).description_body);
+  }
+  {
+    SCOPED_TRACE("setCursorPosition test");
+    const char set_cursor_position_test_script[] =
+        "chrome.input.ime.setCursorPosition({"
+        "  contextID: engineBridge.getFocusedContextID().contextID,"
+        "  candidateID: 2"
+        "});";
+    engine_service->Clear();
+    ASSERT_TRUE(content::ExecuteScript(
+        host->host_contents(), set_cursor_position_test_script));
+    EXPECT_EQ(1, engine_service->update_lookup_table_call_count());
+
+    // window visibility is kept as before.
+    EXPECT_TRUE(engine_service->last_update_lookup_table_arg().is_visible);
+
+    const IBusLookupTable& table =
+        engine_service->last_update_lookup_table_arg().lookup_table;
+
+    // cursor visibility is kept as before.
+    EXPECT_TRUE(table.is_cursor_visible());
+
+    // oritantation is kept as before.
+    EXPECT_EQ(IBusLookupTable::VERTICAL, table.orientation());
+
+    // page size is kept as before.
+    EXPECT_EQ(7U, table.page_size());
+
+    // candidates are same as before.
+    ASSERT_EQ(4U, table.candidates().size());
+
+    // Candidate ID == 2 is 1 in index.
+    EXPECT_EQ(1U, table.cursor_position());
+  }
+  {
+    SCOPED_TRACE("setMenuItem test");
+    const char set_menu_item_test_script[] =
+        "chrome.input.ime.setMenuItems({"
+        "  engineID: engineBridge.getActiveEngineID(),"
+        "  items: [{"
+        "    id: 'ID0',"
+        "  },{"
+        "    id: 'ID1',"
+        "    label: 'LABEL1',"
+        "  },{"
+        "    id: 'ID2',"
+        "    label: 'LABEL2',"
+        "    style: 'radio',"
+        "  },{"
+        "    id: 'ID3',"
+        "    label: 'LABEL3',"
+        "    style: 'check',"
+        "    visible: true,"
+        "  },{"
+        "    id: 'ID4',"
+        "    label: 'LABEL4',"
+        "    style: 'separator',"
+        "    visible: true,"
+        "    checked: true"
+        "  }]"
+        "});";
+    engine_service->Clear();
+    ASSERT_TRUE(content::ExecuteScript(
+        host->host_contents(), set_menu_item_test_script));
+    EXPECT_EQ(1, engine_service->register_properties_call_count());
+
+    const IBusPropertyList& props =
+        engine_service->last_registered_properties();
+    ASSERT_EQ(5U, props.size());
+
+    EXPECT_EQ("ID0", props[0]->key());
+    EXPECT_EQ("ID1", props[1]->key());
+    EXPECT_EQ("ID2", props[2]->key());
+    EXPECT_EQ("ID3", props[3]->key());
+    EXPECT_EQ("ID4", props[4]->key());
+
+    EXPECT_EQ("LABEL1", props[1]->label());
+    EXPECT_EQ("LABEL2", props[2]->label());
+    EXPECT_EQ("LABEL3", props[3]->label());
+    EXPECT_EQ("LABEL4", props[4]->label());
+
+    EXPECT_EQ(IBusProperty::IBUS_PROPERTY_TYPE_RADIO, props[2]->type());
+    EXPECT_EQ(IBusProperty::IBUS_PROPERTY_TYPE_TOGGLE, props[3]->type());
+    EXPECT_EQ(IBusProperty::IBUS_PROPERTY_TYPE_SEPARATOR, props[4]->type());
+
+    EXPECT_TRUE(props[3]->visible());
+    EXPECT_TRUE(props[4]->visible());
+
+    EXPECT_TRUE(props[4]->checked());
+  }
+  {
+    SCOPED_TRACE("deleteSurroundingText test");
+    const char delete_surrounding_text_test_script[] =
+        "chrome.input.ime.deleteSurroundingText({"
+        "  engineID: engineBridge.getActiveEngineID(),"
+        "  contextID: engineBridge.getFocusedContextID().contextID,"
+        "  offset: 5,"
+        "  length: 3"
+        "});";
+    engine_service->Clear();
+    ASSERT_TRUE(content::ExecuteScript(
+        host->host_contents(), delete_surrounding_text_test_script));
+
+    EXPECT_EQ(1, engine_service->delete_surrounding_text_call_count());
+    EXPECT_EQ(5, engine_service->last_delete_surrounding_text_arg().offset);
+    EXPECT_EQ(3U, engine_service->last_delete_surrounding_text_arg().length);
+  }
 }
 
 }  // namespace
diff --git a/chrome/browser/chromeos/input_method/input_method_manager_impl.cc b/chrome/browser/chromeos/input_method/input_method_manager_impl.cc
index f2c5d8d..4f21a46 100644
--- a/chrome/browser/chromeos/input_method/input_method_manager_impl.cc
+++ b/chrome/browser/chromeos/input_method/input_method_manager_impl.cc
@@ -49,6 +49,63 @@
   { "mozc", "_comp_ime_fpfbhcjppmaeaijcidgiibchfbnhbeljnacl_mozc_us" },
   { "mozc-jp", "_comp_ime_fpfbhcjppmaeaijcidgiibchfbnhbeljnacl_mozc_jp" },
   { "mozc-dv", "_comp_ime_fpfbhcjppmaeaijcidgiibchfbnhbeljnacl_mozc_us" },
+  { "pinyin", "_comp_ime_nmblnjkfdkabgdofidlkienfnnbjhnabzh-t-i0-pinyin" },
+  { "pinyin-dv", "_comp_ime_nmblnjkfdkabgdofidlkienfnnbjhnabzh-t-i0-pinyin" },
+  { "mozc-chewing",
+    "_comp_ime_ekbifjdfhkmdeeajnolmgdlmkllopefizh-hant-t-i0-und "},
+  { "m17n:zh:cangjie",
+    "_comp_ime_gjhclobljhjhgoebiipblnmdodbmpdgdzh-hant-t-i0-cangjie-1987" },
+  // TODO(nona): Remove following migration map in M31.
+  { "m17n:ta:itrans",
+    "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_ta_itrans" },
+  { "m17n:ta:tamil99",
+    "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_ta_tamil99" },
+  { "m17n:ta:typewriter",
+    "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_ta_typewriter" },
+  { "m17n:ta:inscript",
+    "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_ta_phone" },
+  { "m17n:ta:phonetic",
+    "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_ta_inscript" },
+  { "m17n:th:pattachote",
+    "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_th_pattajoti" },
+  { "m17n:th:tis820", "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_th_tis" },
+  { "m17n:th:kesmanee",
+    "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_th" },
+  { "m17n:vi:tcvn", "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_vi_tcvn" },
+  { "m17n:vi:viqr", "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_vi_viqr" },
+  { "m17n:vi:telex",
+    "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_vi_telex" },
+  { "m17n:am:sera",
+    "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_ethi" },
+  { "m17n:bn:itrans",
+    "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_bn_phone" },
+  { "m17n:gu:itrans",
+    "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_gu_phone" },
+  { "m17n:hi:itrans",
+    "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_deva_phone" },
+  { "m17n:kn:itrans",
+    "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_kn_phone" },
+  { "m17n:ml:itrans",
+    "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_ml_phone" },
+  { "m17n:mr:itrans",
+    "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_deva_phone-" },
+  { "m17n:te:itrans",
+    "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_te_phone" },
+  { "m17n:fa:isiri", "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_fa" },
+  // TODO(nona): Remove following migration map in M32
+  { "m17n:zh:quick",
+    "_comp_ime_ekbifjdfhkmdeeajnolmgdlmkllopefizh-hant-t-i0-und" },
+};
+
+const struct MigrationHangulKeyboardToInputMethodID {
+  const char* keyboard_id;
+  const char* ime_id;
+} kMigrationHangulKeyboardToInputMethodID[] = {
+  { "2", "_comp_ime_bdgdidmhaijohebebipajioienkglgfohangul_2set" },
+  { "3f", "_comp_ime_bdgdidmhaijohebebipajioienkglgfohangul_3setfinal" },
+  { "39", "_comp_ime_bdgdidmhaijohebebipajioienkglgfohangul_3set390" },
+  { "3s", "_comp_ime_bdgdidmhaijohebebipajioienkglgfohangul_3setnoshift" },
+  { "ro", "_comp_ime_bdgdidmhaijohebebipajioienkglgfohangul_romaja" },
 };
 
 }  // namespace
@@ -261,6 +318,28 @@
   return rewritten;
 }
 
+bool InputMethodManagerImpl::MigrateKoreanKeyboard(
+    const std::string& keyboard_id,
+    std::vector<std::string>* input_method_ids) {
+  std::vector<std::string>::iterator it =
+      std::find(active_input_method_ids_.begin(),
+                active_input_method_ids_.end(),
+                "mozc-hangul");
+  if (it == active_input_method_ids_.end())
+    return false;
+
+  for (size_t i = 0;
+       i < ARRAYSIZE_UNSAFE(kMigrationHangulKeyboardToInputMethodID); ++i) {
+    if (kMigrationHangulKeyboardToInputMethodID[i].keyboard_id == keyboard_id) {
+      *it = kMigrationHangulKeyboardToInputMethodID[i].ime_id;
+      input_method_ids->assign(active_input_method_ids_.begin(),
+                               active_input_method_ids_.end());
+      return true;
+    }
+  }
+  return false;
+}
+
 bool InputMethodManagerImpl::SetInputMethodConfig(
     const std::string& section,
     const std::string& config_name,
@@ -270,6 +349,7 @@
 
   if (state_ == STATE_TERMINATING)
     return false;
+
   return ibus_controller_->SetInputMethodConfig(section, config_name, value);
 }
 
@@ -634,10 +714,6 @@
       input_method_ids_to_switch.push_back(nacl_mozc_jp_id);
       input_method_ids_to_switch.push_back("xkb:jp::jpn");
       break;
-    case ui::VKEY_HANGUL:  // Hangul (or right Alt) key on Korean keyboard
-      input_method_ids_to_switch.push_back("mozc-hangul");
-      input_method_ids_to_switch.push_back("xkb:kr:kr104:kor");
-      break;
     default:
       NOTREACHED();
       break;
diff --git a/chrome/browser/chromeos/input_method/input_method_manager_impl.h b/chrome/browser/chromeos/input_method/input_method_manager_impl.h
index c585b46..521e04a 100644
--- a/chrome/browser/chromeos/input_method/input_method_manager_impl.h
+++ b/chrome/browser/chromeos/input_method/input_method_manager_impl.h
@@ -65,6 +65,9 @@
       const std::vector<std::string>& new_active_input_method_ids) OVERRIDE;
   virtual bool MigrateOldInputMethods(
       std::vector<std::string>* input_method_ids) OVERRIDE;
+  virtual bool MigrateKoreanKeyboard(
+      const std::string& keyboard_id,
+      std::vector<std::string>* input_method_ids) OVERRIDE;
   virtual bool SetInputMethodConfig(
       const std::string& section,
       const std::string& config_name,
diff --git a/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc b/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc
index f08cbf9..29c35f9 100644
--- a/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc
+++ b/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc
@@ -98,7 +98,7 @@
     ime_list_.push_back(ext1);
 
     ComponentExtensionIME ext2;
-    ext2.id = "ext2_id";
+    ext2.id = "nmblnjkfdkabgdofidlkienfnnbjhnab";
     ext2.description = "ext2_description";
     ext2.path = base::FilePath("ext2_file_path");
 
@@ -109,6 +109,13 @@
     ext2_engine1.layouts.push_back("us");
     ext2.engines.push_back(ext2_engine1);
 
+    ComponentExtensionEngine ext2_engine2;
+    ext2_engine2.engine_id = "ext2_engine2_engine_id";
+    ext2_engine2.display_name = "ext2_engine_2_display_name";
+    ext2_engine2.language_code = "en";
+    ext2_engine2.layouts.push_back("us(dvorak)");
+    ext2.engines.push_back(ext2_engine2);
+
     ime_list_.push_back(ext2);
 
     mock_ibus_daemon_controller_->EmulateConnect();
@@ -271,6 +278,8 @@
 }
 
 TEST_F(InputMethodManagerImplTest, TestGetSupportedInputMethods) {
+  InitComponentExtension();
+  InitIBusBus();
   scoped_ptr<InputMethodDescriptors> methods(
       manager_->GetSupportedInputMethods());
   ASSERT_TRUE(methods.get());
@@ -280,9 +289,6 @@
       manager_->GetInputMethodUtil()->GetInputMethodDescriptorFromId(
           nacl_mozc_us_id);
   id_to_find = manager_->GetInputMethodUtil()->GetInputMethodDescriptorFromId(
-      "mozc-chewing");
-  EXPECT_TRUE(Contain(*methods.get(), *id_to_find));
-  id_to_find = manager_->GetInputMethodUtil()->GetInputMethodDescriptorFromId(
       "xkb:us::eng");
   EXPECT_TRUE(Contain(*methods.get(), *id_to_find));
   id_to_find = manager_->GetInputMethodUtil()->GetInputMethodDescriptorFromId(
@@ -332,7 +338,7 @@
 }
 
 TEST_F(InputMethodManagerImplTest, TestActiveInputMethods) {
-  manager_->EnableLayouts("ko", "");  // Korean
+  manager_->EnableLayouts("ja", "");  // Japanese
   EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
   scoped_ptr<InputMethodDescriptors> methods(
       manager_->GetActiveInputMethods());
@@ -343,7 +349,7 @@
           "xkb:us::eng");
   EXPECT_TRUE(Contain(*methods.get(), *id_to_find));
   id_to_find = manager_->GetInputMethodUtil()->GetInputMethodDescriptorFromId(
-      "xkb:kr:kr104:kor");
+      "xkb:jp::jpn");
   EXPECT_TRUE(Contain(*methods.get(), *id_to_find));
 }
 
@@ -499,7 +505,7 @@
   InitIBusBus();
   manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
   std::vector<std::string> ids;
-  ids.push_back("mozc-chewing");
+  ids.push_back("_comp_ime_nmblnjkfdkabgdofidlkienfnnbjhnabext2_engine1_engine_id");
   ids.push_back("mozc-dv");
   EXPECT_TRUE(manager_->EnableInputMethods(ids));
   EXPECT_EQ(1, mock_ibus_daemon_controller_->start_count());
@@ -567,7 +573,7 @@
   manager_->RemoveObserver(&observer);
 }
 
-TEST_F(InputMethodManagerImplTest, TestEnableLayoutAndImeThenLock) {
+TEST_F(InputMethodManagerImplTest, SwithchInputMethodTest) {
   // For http://crbug.com/19655#c11 - (15).
   TestObserver observer;
   manager_->AddObserver(&observer);
@@ -576,8 +582,8 @@
   manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
   std::vector<std::string> ids;
   ids.push_back("xkb:us:dvorak:eng");
-  ids.push_back("pinyin-dv");
-  ids.push_back("mozc-chewing");
+  ids.push_back("_comp_ime_nmblnjkfdkabgdofidlkienfnnbjhnabext2_engine2_engine_id");
+  ids.push_back("_comp_ime_nmblnjkfdkabgdofidlkienfnnbjhnabext2_engine1_engine_id");
   EXPECT_TRUE(manager_->EnableInputMethods(ids));
   EXPECT_EQ(3U, manager_->GetNumActiveInputMethods());
   EXPECT_EQ(1, observer.input_method_changed_count_);
@@ -700,7 +706,7 @@
   manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
   std::vector<std::string> ids;
   ids.push_back(nacl_mozc_us_id);  // Japanese
-  ids.push_back("mozc-chewing");  // T-Chinese
+  ids.push_back("_comp_ime_nmblnjkfdkabgdofidlkienfnnbjhnabext2_engine1_engine_id");  // T-Chinese
   EXPECT_TRUE(manager_->EnableInputMethods(ids));
   EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
   EXPECT_TRUE(manager_->GetCurrentInputMethodProperties().empty());
@@ -716,7 +722,7 @@
   ASSERT_EQ(1U, manager_->GetCurrentInputMethodProperties().size());
   EXPECT_EQ("key-mozc", manager_->GetCurrentInputMethodProperties().at(0).key);
 
-  manager_->ChangeInputMethod("mozc-chewing");
+  manager_->ChangeInputMethod("_comp_ime_nmblnjkfdkabgdofidlkienfnnbjhnabext2_engine1_engine_id");
   // Since the IME is changed, the property for mozc Japanese should be hidden.
   EXPECT_TRUE(manager_->GetCurrentInputMethodProperties().empty());
 
@@ -842,12 +848,6 @@
   EXPECT_EQ("xkb:us::eng", manager_->GetCurrentInputMethod().id());
   EXPECT_EQ("us", xkeyboard_->last_layout_);
 
-  // Do the same tests for Korean.
-  EXPECT_FALSE(manager_->SwitchInputMethod(
-      ui::Accelerator(ui::VKEY_HANGUL, ui::EF_NONE)));
-  EXPECT_EQ("xkb:us::eng", manager_->GetCurrentInputMethod().id());
-  EXPECT_EQ("us", xkeyboard_->last_layout_);
-
   manager_->RemoveObserver(&observer);
 }
 
@@ -879,27 +879,6 @@
   EXPECT_EQ("jp", xkeyboard_->last_layout_);
 }
 
-TEST_F(InputMethodManagerImplTest, TestSwitchInputMethodWithKoLayout) {
-  // Do the same tests for Korean.
-  InitComponentExtension();
-  InitIBusBus();
-  manager_->EnableLayouts("ko", "xkb:us::eng");
-  EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
-  EXPECT_EQ("xkb:us::eng", manager_->GetCurrentInputMethod().id());
-  EXPECT_EQ("us", xkeyboard_->last_layout_);
-  EXPECT_TRUE(manager_->SwitchInputMethod(
-      ui::Accelerator(ui::VKEY_HANGUL, ui::EF_NONE)));
-  EXPECT_EQ("xkb:kr:kr104:kor", manager_->GetCurrentInputMethod().id());
-  EXPECT_EQ("kr(kr104)", xkeyboard_->last_layout_);
-  manager_->SwitchToPreviousInputMethod();
-  EXPECT_EQ("xkb:us::eng", manager_->GetCurrentInputMethod().id());
-  EXPECT_EQ("us", xkeyboard_->last_layout_);
-  EXPECT_TRUE(manager_->SwitchInputMethod(
-      ui::Accelerator(ui::VKEY_HANGUL, ui::EF_NONE)));
-  EXPECT_EQ("xkb:kr:kr104:kor", manager_->GetCurrentInputMethod().id());
-  EXPECT_EQ("kr(kr104)", xkeyboard_->last_layout_);
-}
-
 TEST_F(InputMethodManagerImplTest, TestSwitchInputMethodWithJpIme) {
   InitComponentExtension();
   InitIBusBus();
@@ -950,40 +929,6 @@
   EXPECT_EQ("jp", xkeyboard_->last_layout_);
 }
 
-TEST_F(InputMethodManagerImplTest, TestSwitchInputMethodWithKoIme) {
-  InitComponentExtension();
-  InitIBusBus();
-  manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
-  std::vector<std::string> ids;
-  ids.push_back("xkb:kr:kr104:kor");
-  ids.push_back("mozc-hangul");
-  EXPECT_TRUE(manager_->EnableInputMethods(ids));
-  EXPECT_EQ("xkb:kr:kr104:kor", manager_->GetCurrentInputMethod().id());
-  EXPECT_EQ("kr(kr104)", xkeyboard_->last_layout_);
-  EXPECT_TRUE(manager_->SwitchInputMethod(
-      ui::Accelerator(ui::VKEY_HANGUL, ui::EF_NONE)));
-  EXPECT_EQ("mozc-hangul", manager_->GetCurrentInputMethod().id());
-  EXPECT_EQ("kr(kr104)", xkeyboard_->last_layout_);
-  EXPECT_TRUE(manager_->SwitchInputMethod(
-      ui::Accelerator(ui::VKEY_HANGUL, ui::EF_NONE)));
-  EXPECT_EQ("xkb:kr:kr104:kor", manager_->GetCurrentInputMethod().id());
-  EXPECT_EQ("kr(kr104)", xkeyboard_->last_layout_);
-
-  // Add Dvorak.
-  ids.push_back("xkb:us:dvorak:eng");
-  EXPECT_TRUE(manager_->EnableInputMethods(ids));
-  EXPECT_EQ("xkb:kr:kr104:kor", manager_->GetCurrentInputMethod().id());
-  EXPECT_EQ("kr(kr104)", xkeyboard_->last_layout_);
-  EXPECT_TRUE(manager_->SwitchInputMethod(
-      ui::Accelerator(ui::VKEY_HANGUL, ui::EF_NONE)));
-  EXPECT_EQ("mozc-hangul", manager_->GetCurrentInputMethod().id());
-  EXPECT_EQ("kr(kr104)", xkeyboard_->last_layout_);
-  EXPECT_TRUE(manager_->SwitchInputMethod(
-      ui::Accelerator(ui::VKEY_HANGUL, ui::EF_NONE)));
-  EXPECT_EQ("xkb:kr:kr104:kor", manager_->GetCurrentInputMethod().id());
-  EXPECT_EQ("kr(kr104)", xkeyboard_->last_layout_);
-}
-
 TEST_F(InputMethodManagerImplTest, TestAddRemoveExtensionInputMethods) {
   TestObserver observer;
   manager_->AddObserver(&observer);
@@ -1177,16 +1122,16 @@
   manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
   std::vector<std::string> ids;
   ids.push_back(nacl_mozc_us_id);
-  ids.push_back("m17n:kn:itrans");
+  ids.push_back(nacl_mozc_jp_id);
   EXPECT_TRUE(manager_->EnableInputMethods(ids));
   EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
   manager_->ChangeInputMethod(nacl_mozc_us_id);
-  manager_->ChangeInputMethod("m17n:kn:itrans");
+  manager_->ChangeInputMethod(nacl_mozc_jp_id);
 
   InitComponentExtension();
   InitIBusBus();
   EXPECT_EQ(1, mock_ibus_client_->set_global_engine_call_count());
-  EXPECT_EQ("m17n:kn:itrans", mock_ibus_client_->latest_global_engine_name());
+  EXPECT_EQ(nacl_mozc_jp_id, mock_ibus_client_->latest_global_engine_name());
 }
 
 TEST_F(InputMethodManagerImplTest,
@@ -1281,7 +1226,7 @@
   input_method_ids.push_back("mozc");
   input_method_ids.push_back("mozc-jp");
   input_method_ids.push_back("xkb:us::eng");
-  input_method_ids.push_back("mozc-hangul");
+  input_method_ids.push_back(nacl_mozc_us_id);
 
   manager_->MigrateOldInputMethods(&input_method_ids);
 
@@ -1297,14 +1242,14 @@
                       "xkb:us::eng"));
   EXPECT_NE(input_method_ids.end(),
             std::find(input_method_ids.begin(), input_method_ids.end(),
-                      "mozc-hangul"));
+                      nacl_mozc_us_id));
 
 }
 
 TEST_F(InputMethodManagerImplTest,
        AsyncComponentExtentionInitializeBeforeIBusDaemonConnection) {
   const std::string xkb_id = "xkb:cz::cze";
-  const std::string ime_id = "mozc-hangul";
+  const std::string ime_id = nacl_mozc_us_id;
   const std::string fallback_id = "xkb:us::eng";
   std::vector<std::string> ids;
   ids.push_back(xkb_id);
@@ -1336,7 +1281,7 @@
 TEST_F(InputMethodManagerImplTest,
        AsyncComponentExtentionInitializeAfterIBusDaemonConnection) {
   const std::string xkb_id = "xkb:cz::cze";
-  const std::string ime_id = "mozc-hangul";
+  const std::string ime_id = nacl_mozc_us_id;
   const std::string fallback_id = "xkb:us::eng";
   std::vector<std::string> ids;
   ids.push_back(xkb_id);
diff --git a/chrome/browser/chromeos/input_method/input_method_util.cc b/chrome/browser/chromeos/input_method/input_method_util.cc
index f70f0eb..3258cda 100644
--- a/chrome/browser/chromeos/input_method/input_method_util.cc
+++ b/chrome/browser/chromeos/input_method/input_method_util.cc
@@ -49,10 +49,24 @@
   { "_comp_ime_bbaiamgfapehflhememkfglaehiobjnknacl_mozc_jp", "\xe3\x81\x82" },
   // For simplified Chinese input methods
   { "pinyin", "\xe6\x8b\xbc" },  // U+62FC
+  { "_comp_ime_cpgalbafkoofkjmaeonnfijgpfennjjnzh-t-i0-pinyin",
+    "\xe6\x8b\xbc" },
+  { "_comp_ime_nmblnjkfdkabgdofidlkienfnnbjhnabzh-t-i0-pinyin",
+    "\xe6\x8b\xbc" },
+  { "_comp_ime_jcffnbbngddhenhcnebafkbdomehdhpdzh-t-i0-wubi-1986",
+    "\xe4\xba\x94" }, // U+4E94
   { "pinyin-dv", "\xe6\x8b\xbc" },
   // For traditional Chinese input methods
   { "mozc-chewing", "\xe9\x85\xb7" },  // U+9177
+  { "_comp_ime_ekbifjdfhkmdeeajnolmgdlmkllopefizh-hant-t-i0-und",
+    "\xe9\x85\xb7" },  // U+9177
+  { "_comp_ime_goedamlknlnjaengojinmfgpmdjmkooozh-hant-t-i0-und",
+    "\xe9\x85\xb7" },  // U+9177
   { "m17n:zh:cangjie", "\xe5\x80\x89" },  // U+5009
+  { "_comp_ime_aeebooiibjahgpgmhkeocbeekccfknbjzh-hant-t-i0-cangjie-1987",
+    "\xe5\x80\x89" },  // U+5009
+  { "_comp_ime_gjhclobljhjhgoebiipblnmdodbmpdgdzh-hant-t-i0-cangjie-1987",
+    "\xe5\x80\x89" },  // U+5009
   { "m17n:zh:quick", "\xe9\x80\x9f" },  // U+901F
   // For Hangul input method.
   { "mozc-hangul", "\xed\x95\x9c" },  // U+D55C
@@ -76,6 +90,20 @@
   { "mozc-hangul", IDS_LANGUAGES_MEDIUM_LEN_NAME_KOREAN },
   { "pinyin", IDS_LANGUAGES_MEDIUM_LEN_NAME_CHINESE_SIMPLIFIED },
   { "pinyin-dv", IDS_LANGUAGES_MEDIUM_LEN_NAME_CHINESE_SIMPLIFIED },
+  { "_comp_ime_cpgalbafkoofkjmaeonnfijgpfennjjnzh-t-i0-pinyin",
+    IDS_LANGUAGES_MEDIUM_LEN_NAME_CHINESE_SIMPLIFIED},
+  { "_comp_ime_nmblnjkfdkabgdofidlkienfnnbjhnabzh-t-i0-pinyin",
+    IDS_LANGUAGES_MEDIUM_LEN_NAME_CHINESE_SIMPLIFIED },
+  { "_comp_ime_jcffnbbngddhenhcnebafkbdomehdhpdzh-t-i0-wubi-1986",
+    IDS_LANGUAGES_MEDIUM_LEN_NAME_CHINESE_SIMPLIFIED },
+  { "_comp_ime_ekbifjdfhkmdeeajnolmgdlmkllopefizh-hant-t-i0-und",
+    IDS_LANGUAGES_MEDIUM_LEN_NAME_CHINESE_TRADITIONAL },
+  { "_comp_ime_goedamlknlnjaengojinmfgpmdjmkooozh-hant-t-i0-und",
+    IDS_LANGUAGES_MEDIUM_LEN_NAME_CHINESE_TRADITIONAL },
+  { "_comp_ime_aeebooiibjahgpgmhkeocbeekccfknbjzh-hant-t-i0-cangjie-1987",
+    IDS_LANGUAGES_MEDIUM_LEN_NAME_CHINESE_TRADITIONAL },
+  { "_comp_ime_gjhclobljhjhgoebiipblnmdodbmpdgdzh-hant-t-i0-cangjie-1987",
+    IDS_LANGUAGES_MEDIUM_LEN_NAME_CHINESE_TRADITIONAL },
 };
 const size_t kMappingImeIdToMediumLenNameResourceIdLen =
     ARRAYSIZE_UNSAFE(kMappingImeIdToMediumLenNameResourceId);
@@ -91,6 +119,12 @@
 } kDefaultInputMethodRecommendation[] = {
   { "ja", "us", "_comp_ime_fpfbhcjppmaeaijcidgiibchfbnhbeljnacl_mozc_us" },
   { "ja", "jp", "_comp_ime_fpfbhcjppmaeaijcidgiibchfbnhbeljnacl_mozc_jp" },
+  { "zh-CN", "us", "_comp_ime_nmblnjkfdkabgdofidlkienfnnbjhnabzh-t-i0-pinyin" },
+  { "zh-TW", "us",
+    "_comp_ime_goedamlknlnjaengojinmfgpmdjmkooozh-hant-t-i0-und" },
+  { "th", "us", "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_th" },
+  { "vi", "us", "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_vi_tcvn" },
+  { "vi", "us", "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_vi_tcvn" },
 };
 
 }  // namespace
diff --git a/chrome/browser/chromeos/input_method/input_method_util_unittest.cc b/chrome/browser/chromeos/input_method/input_method_util_unittest.cc
index 7a4a33f..74a16b9 100644
--- a/chrome/browser/chromeos/input_method/input_method_util_unittest.cc
+++ b/chrome/browser/chromeos/input_method/input_method_util_unittest.cc
@@ -24,6 +24,11 @@
 
 namespace {
 
+const char pinyin_ime_id[] =
+    "_comp_ime_nmblnjkfdkabgdofidlkienfnnbjhnabzh-t-i0-pinyin";
+const char zhuyin_ime_id[] =
+    "_comp_ime_goedamlknlnjaengojinmfgpmdjmkooozh-hant-t-i0-und";
+
 class TestableInputMethodUtil : public InputMethodUtil {
  public:
   explicit TestableInputMethodUtil(InputMethodDelegate* delegate,
@@ -49,6 +54,33 @@
         base::Bind(&InputMethodUtilTest::GetDisplayLanguageName));
   }
 
+  virtual void SetUp() OVERRIDE {
+    InputMethodDescriptors input_methods;
+
+    std::vector<std::string> layouts;
+    std::vector<std::string> languages;
+    layouts.push_back("us");
+    languages.push_back("zh-CN");
+
+    InputMethodDescriptor pinyin_ime(pinyin_ime_id,
+                                     "Pinyin input for testing",
+                                     layouts,
+                                     languages,
+                                     GURL(""));
+    input_methods.push_back(pinyin_ime);
+
+    languages.clear();
+    languages.push_back("zh-TW");
+    InputMethodDescriptor zhuyin_ime(zhuyin_ime_id,
+                                     "Zhuyin input for testing",
+                                     layouts,
+                                     languages,
+                                     GURL(""));
+    input_methods.push_back(zhuyin_ime);
+
+    util_.SetComponentExtensions(input_methods);
+  }
+
   InputMethodDescriptor GetDesc(const std::string& id,
                                 const std::string& raw_layout,
                                 const std::string& language_code) {
@@ -118,17 +150,12 @@
     EXPECT_EQ(ASCIIToUTF16("CAS"), util_.GetInputMethodShortName(desc));
   }
   {
-    InputMethodDescriptor desc = GetDesc("pinyin", "us", "zh-CN");
+    InputMethodDescriptor desc = GetDesc(pinyin_ime_id, "us", "zh-CN");
     EXPECT_EQ(UTF8ToUTF16("\xe6\x8b\xbc"),
               util_.GetInputMethodShortName(desc));
   }
   {
-    InputMethodDescriptor desc = GetDesc("pinyin-dv", "us(dvorak)", "zh-CN");
-    EXPECT_EQ(UTF8ToUTF16("\xe6\x8b\xbc"),
-              util_.GetInputMethodShortName(desc));
-  }
-  {
-    InputMethodDescriptor desc = GetDesc("mozc-chewing", "us", "zh-TW");
+    InputMethodDescriptor desc = GetDesc(zhuyin_ime_id, "us", "zh-TW");
     EXPECT_EQ(UTF8ToUTF16("\xe9\x85\xb7"),
               util_.GetInputMethodShortName(desc));
   }
@@ -170,12 +197,11 @@
     const char * input_method_id[] = {
       "m17n:zh:cangjie",
       "m17n:zh:quick",
-      "pinyin",
-      "mozc-chewing",
+      pinyin_ime_id,
+      zhuyin_ime_id,
       "mozc-hangul",
-      "pinyin",
-      "pinyin",
-      "pinyin-dv",
+      pinyin_ime_id,
+      pinyin_ime_id,
     };
     const int len = ARRAYSIZE_UNSAFE(input_method_id);
     for (int i=0; i<len; ++i) {
@@ -206,11 +232,6 @@
               util_.GetInputMethodLongName(desc));
   }
   {
-    InputMethodDescriptor desc = GetDesc("pinyin", "us", "ja");
-    EXPECT_EQ(ASCIIToUTF16("Pinyin input method"),
-              util_.GetInputMethodLongName(desc));
-  }
-  {
     InputMethodDescriptor desc = GetDesc("xkb:jp::jpn", "jp", "ja");
     EXPECT_EQ(ASCIIToUTF16("Japanese keyboard"),
               util_.GetInputMethodLongName(desc));
@@ -275,20 +296,15 @@
   }
 }
 
-TEST_F(InputMethodUtilTest, TestGetStringUTF8) {
-  EXPECT_EQ(UTF8ToUTF16("Pinyin input method"),
-            util_.TranslateString("pinyin"));
-}
-
 TEST_F(InputMethodUtilTest, TestIsValidInputMethodId) {
   EXPECT_TRUE(util_.IsValidInputMethodId("xkb:us:colemak:eng"));
-  EXPECT_TRUE(util_.IsValidInputMethodId("pinyin"));
+  EXPECT_TRUE(util_.IsValidInputMethodId(pinyin_ime_id));
   EXPECT_FALSE(util_.IsValidInputMethodId("unsupported-input-method"));
 }
 
 TEST_F(InputMethodUtilTest, TestIsKeyboardLayout) {
   EXPECT_TRUE(InputMethodUtil::IsKeyboardLayout("xkb:us::eng"));
-  EXPECT_FALSE(InputMethodUtil::IsKeyboardLayout("pinyin"));
+  EXPECT_FALSE(InputMethodUtil::IsKeyboardLayout(pinyin_ime_id));
 }
 
 TEST_F(InputMethodUtilTest, TestGetKeyboardLayoutName) {
@@ -296,9 +312,7 @@
   EXPECT_EQ("", util_.GetKeyboardLayoutName("UNSUPPORTED_ID"));
 
   // Supported cases (samples).
-  EXPECT_EQ("us", util_.GetKeyboardLayoutName("pinyin"));
-  EXPECT_EQ("us(dvorak)", util_.GetKeyboardLayoutName("pinyin-dv"));
-  EXPECT_EQ("us", util_.GetKeyboardLayoutName("m17n:ar:kbd"));
+  EXPECT_EQ("us", util_.GetKeyboardLayoutName(pinyin_ime_id));
   EXPECT_EQ("es", util_.GetKeyboardLayoutName("xkb:es::spa"));
   EXPECT_EQ("es(cat)", util_.GetKeyboardLayoutName("xkb:es:cat:cat"));
   EXPECT_EQ("gb(extd)", util_.GetKeyboardLayoutName("xkb:gb:extd:eng"));
@@ -310,12 +324,10 @@
 
 TEST_F(InputMethodUtilTest, TestGetLanguageCodeFromInputMethodId) {
   // Make sure that the -CN is added properly.
-  EXPECT_EQ("zh-CN", util_.GetLanguageCodeFromInputMethodId("pinyin"));
+  EXPECT_EQ("zh-CN", util_.GetLanguageCodeFromInputMethodId(pinyin_ime_id));
 }
 
 TEST_F(InputMethodUtilTest, TestGetInputMethodDisplayNameFromId) {
-  EXPECT_EQ("Pinyin input method",
-            util_.GetInputMethodDisplayNameFromId("pinyin"));
   EXPECT_EQ("US keyboard",
             util_.GetInputMethodDisplayNameFromId("xkb:us::eng"));
   EXPECT_EQ("", util_.GetInputMethodDisplayNameFromId("nonexistent"));
@@ -325,9 +337,9 @@
   EXPECT_EQ(NULL, util_.GetInputMethodDescriptorFromId("non_existent"));
 
   const InputMethodDescriptor* descriptor =
-      util_.GetInputMethodDescriptorFromId("pinyin");
+      util_.GetInputMethodDescriptorFromId(pinyin_ime_id);
   ASSERT_TRUE(NULL != descriptor);  // ASSERT_NE doesn't compile.
-  EXPECT_EQ("pinyin", descriptor->id());
+  EXPECT_EQ(pinyin_ime_id, descriptor->id());
   EXPECT_EQ("us", descriptor->GetPreferredKeyboardLayout());
   // This used to be "zh" but now we have "zh-CN" in input_methods.h,
   // hence this should be zh-CN now.
@@ -337,8 +349,8 @@
 
 TEST_F(InputMethodUtilTest, TestGetInputMethodIdsForLanguageCode) {
   std::multimap<std::string, std::string> language_code_to_ids_map;
-  language_code_to_ids_map.insert(std::make_pair("ja", "pinyin"));
-  language_code_to_ids_map.insert(std::make_pair("ja", "pinyin"));
+  language_code_to_ids_map.insert(std::make_pair("ja", pinyin_ime_id));
+  language_code_to_ids_map.insert(std::make_pair("ja", pinyin_ime_id));
   language_code_to_ids_map.insert(std::make_pair("ja", "xkb:jp:jpn"));
   language_code_to_ids_map.insert(std::make_pair("fr", "xkb:fr:fra"));
 
@@ -386,20 +398,7 @@
   util_.GetFirstLoginInputMethodIds("zh-CN", *descriptor, &input_method_ids);
   ASSERT_EQ(2U, input_method_ids.size());
   EXPECT_EQ("xkb:us::eng", input_method_ids[0]);
-  EXPECT_EQ("pinyin", input_method_ids[1]);  // Pinyin for US keybaord.
-}
-
-// Korean keyboard + Korean UI = Korean keyboard + mozc-hangul.
-TEST_F(InputMethodUtilTest, TestGetFirstLoginInputMethodIds_KR_And_Ko) {
-  // Korean keyboard
-  const InputMethodDescriptor* descriptor =
-      util_.GetInputMethodDescriptorFromId("xkb:kr:kr104:kor");
-  ASSERT_TRUE(NULL != descriptor);  // ASSERT_NE doesn't compile.
-  std::vector<std::string> input_method_ids;
-  util_.GetFirstLoginInputMethodIds("ko", *descriptor, &input_method_ids);
-  ASSERT_EQ(2U, input_method_ids.size());
-  EXPECT_EQ("xkb:kr:kr104:kor", input_method_ids[0]);
-  EXPECT_EQ("mozc-hangul", input_method_ids[1]);  // Mozc for JP keybaord.
+  EXPECT_EQ(pinyin_ime_id, input_method_ids[1]);  // Pinyin for US keybaord.
 }
 
 // US keyboard + Russian UI = US keyboard + Russsian keyboard
@@ -423,7 +422,7 @@
   util_.GetFirstLoginInputMethodIds("zh-TW", *descriptor, &input_method_ids);
   ASSERT_EQ(2U, input_method_ids.size());
   EXPECT_EQ("xkb:us::eng", input_method_ids[0]);
-  EXPECT_EQ("mozc-chewing", input_method_ids[1]);  // Chewing.
+  EXPECT_EQ(zhuyin_ime_id, input_method_ids[1]);  // Chewing.
 }
 
 // US keyboard + Thai = US keyboard + kesmanee.
@@ -435,7 +434,8 @@
   util_.GetFirstLoginInputMethodIds("th", *descriptor, &input_method_ids);
   ASSERT_EQ(2U, input_method_ids.size());
   EXPECT_EQ("xkb:us::eng", input_method_ids[0]);
-  EXPECT_EQ("m17n:th:kesmanee", input_method_ids[1]);  // Kesmanee.
+  EXPECT_EQ("_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_th",
+            input_method_ids[1]);  // Kesmanee.
 }
 
 // US keyboard + Vietnamese = US keyboard + TCVN6064.
@@ -447,14 +447,15 @@
   util_.GetFirstLoginInputMethodIds("vi", *descriptor, &input_method_ids);
   ASSERT_EQ(2U, input_method_ids.size());
   EXPECT_EQ("xkb:us::eng", input_method_ids[0]);
-  EXPECT_EQ("m17n:vi:tcvn", input_method_ids[1]);  // TCVN6064.
+  EXPECT_EQ("_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_vi_tcvn",
+            input_method_ids[1]);  // TCVN6064.
 }
 
 TEST_F(InputMethodUtilTest, TestGetLanguageCodesFromInputMethodIds) {
   std::vector<std::string> input_method_ids;
   input_method_ids.push_back("xkb:us::eng");  // English US.
   input_method_ids.push_back("xkb:us:dvorak:eng");  // English US Dvorak.
-  input_method_ids.push_back("pinyin");  // Pinyin
+  input_method_ids.push_back(pinyin_ime_id);  // Pinyin
   input_method_ids.push_back("xkb:fr::fra");  // French France.
   std::vector<std::string> language_codes;
   util_.GetLanguageCodesFromInputMethodIds(input_method_ids, &language_codes);
diff --git a/chrome/browser/chromeos/input_method/mock_input_method_manager.cc b/chrome/browser/chromeos/input_method/mock_input_method_manager.cc
index 9efe97f..ad18c70 100644
--- a/chrome/browser/chromeos/input_method/mock_input_method_manager.cc
+++ b/chrome/browser/chromeos/input_method/mock_input_method_manager.cc
@@ -68,6 +68,12 @@
   return false;
 }
 
+bool MockInputMethodManager::MigrateKoreanKeyboard(
+    const std::string& keyboard_id,
+    std::vector<std::string>* input_method_ids) {
+  return false;
+}
+
 bool MockInputMethodManager::SetInputMethodConfig(
     const std::string& section,
     const std::string& config_name,
diff --git a/chrome/browser/chromeos/input_method/mock_input_method_manager.h b/chrome/browser/chromeos/input_method/mock_input_method_manager.h
index 77d760d..e373707 100644
--- a/chrome/browser/chromeos/input_method/mock_input_method_manager.h
+++ b/chrome/browser/chromeos/input_method/mock_input_method_manager.h
@@ -38,6 +38,9 @@
       const std::vector<std::string>& new_active_input_method_ids) OVERRIDE;
   virtual bool MigrateOldInputMethods(
       std::vector<std::string>* input_method_ids) OVERRIDE;
+  virtual bool MigrateKoreanKeyboard(
+      const std::string& keyboard_id,
+      std::vector<std::string>* input_method_ids) OVERRIDE;
   virtual bool SetInputMethodConfig(
       const std::string& section,
       const std::string& config_name,
diff --git a/chrome/browser/chromeos/keyboard_driven_event_rewriter.cc b/chrome/browser/chromeos/keyboard_driven_event_rewriter.cc
new file mode 100644
index 0000000..7c451d2
--- /dev/null
+++ b/chrome/browser/chromeos/keyboard_driven_event_rewriter.cc
@@ -0,0 +1,72 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/keyboard_driven_event_rewriter.h"
+
+#include <X11/Xlib.h>
+
+#include "chrome/browser/chromeos/login/user_manager.h"
+#include "chrome/browser/chromeos/system/statistics_provider.h"
+#include "ui/base/events/event.h"
+
+namespace chromeos {
+
+namespace {
+
+const int kModifierMask = (ui::EF_CONTROL_DOWN |
+                           ui::EF_ALT_DOWN |
+                           ui::EF_SHIFT_DOWN);
+
+// Returns true if and only if it is on login screen (i.e. user is not logged
+// in) and the keyboard driven flag in the OEM manifest is on.
+bool ShouldStripModifiersForArrowKeysAndEnter() {
+  if (chromeos::UserManager::IsInitialized() &&
+      !chromeos::UserManager::Get()->IsUserLoggedIn()) {
+    bool keyboard_driven_oobe = false;
+    chromeos::system::StatisticsProvider::GetInstance()->GetMachineFlag(
+        chromeos::system::kOemKeyboardDrivenOobeKey, &keyboard_driven_oobe);
+    return keyboard_driven_oobe;
+  }
+
+  return false;
+}
+
+}  // namespace
+
+KeyboardDrivenEventRewriter::KeyboardDrivenEventRewriter() {}
+
+KeyboardDrivenEventRewriter::~KeyboardDrivenEventRewriter() {}
+
+void KeyboardDrivenEventRewriter::RewriteIfKeyboardDrivenOnLoginScreen(
+    ui::KeyEvent* event) {
+  if (!ShouldStripModifiersForArrowKeysAndEnter())
+    return;
+
+  RewriteEvent(event);
+}
+
+void KeyboardDrivenEventRewriter::RewriteForTesting(ui::KeyEvent* event) {
+  RewriteEvent(event);
+}
+
+void KeyboardDrivenEventRewriter::RewriteEvent(ui::KeyEvent* event) {
+  if ((event->flags() & kModifierMask) != kModifierMask)
+    return;
+
+  if (event->key_code() != ui::VKEY_LEFT &&
+      event->key_code() != ui::VKEY_RIGHT &&
+      event->key_code() != ui::VKEY_UP &&
+      event->key_code() != ui::VKEY_DOWN &&
+      event->key_code() != ui::VKEY_RETURN) {
+    return;
+  }
+
+  XEvent* xev = event->native_event();
+  XKeyEvent* xkey = &(xev->xkey);
+  xkey->state &= ~(ControlMask | Mod1Mask | ShiftMask);
+  event->set_flags(event->flags() & ~kModifierMask);
+  event->NormalizeFlags();
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/keyboard_driven_event_rewriter.h b/chrome/browser/chromeos/keyboard_driven_event_rewriter.h
new file mode 100644
index 0000000..be274c0
--- /dev/null
+++ b/chrome/browser/chromeos/keyboard_driven_event_rewriter.h
@@ -0,0 +1,40 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_KEYBOARD_DRIVEN_EVENT_REWRITER_H_
+#define CHROME_BROWSER_CHROMEOS_KEYBOARD_DRIVEN_EVENT_REWRITER_H_
+
+#include "base/basictypes.h"
+
+namespace ui {
+class KeyEvent;
+}
+
+namespace chromeos {
+
+// KeyboardDrivenEventRewriter removes the modifier flags from
+// Ctrl+Alt+Shift+<Arrow keys|Enter> key events. This mapping only happens
+// on login screen and only when the keyboard driven oobe flag is enabled in the
+// OEM manifest.
+class KeyboardDrivenEventRewriter {
+ public:
+  KeyboardDrivenEventRewriter();
+  ~KeyboardDrivenEventRewriter();
+
+  // Calls RewriteEvent to modify |event| if it is on login screen and the
+  // keyboard driven flag is enabled.
+  void RewriteIfKeyboardDrivenOnLoginScreen(ui::KeyEvent* event);
+
+  // Calls RewriteEvent for testing.
+  void RewriteForTesting(ui::KeyEvent* event);
+
+ private:
+  void RewriteEvent(ui::KeyEvent* event);
+
+  DISALLOW_COPY_AND_ASSIGN(KeyboardDrivenEventRewriter);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_KEYBOARD_DRIVEN_EVENT_REWRITER_H_
diff --git a/chrome/browser/chromeos/keyboard_driven_event_rewriter_unittest.cc b/chrome/browser/chromeos/keyboard_driven_event_rewriter_unittest.cc
new file mode 100644
index 0000000..fb32552
--- /dev/null
+++ b/chrome/browser/chromeos/keyboard_driven_event_rewriter_unittest.cc
@@ -0,0 +1,165 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/strings/stringprintf.h"
+#include "chrome/browser/chromeos/keyboard_driven_event_rewriter.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/events/event.h"
+#include "ui/base/x/x11_util.h"
+
+#include <X11/keysym.h>
+#include <X11/XF86keysym.h>
+#include <X11/Xlib.h>
+
+namespace chromeos {
+
+// Creates an XKeyEvent to initialize a ui::KeyEvent that is passed to
+// KeyboardDrivenEventRewriter for processing.
+void InitXKeyEvent(ui::KeyboardCode ui_keycode,
+                   int ui_flags,
+                   ui::EventType ui_type,
+                   KeyCode x_keycode,
+                   unsigned int x_state,
+                   XEvent* event) {
+  ui::InitXKeyEventForTesting(ui_type,
+                              ui_keycode,
+                              ui_flags,
+                              event);
+  event->xkey.keycode = x_keycode;
+  event->xkey.state = x_state;
+}
+
+class KeyboardDrivenEventRewriterTest : public testing::Test {
+ public:
+  KeyboardDrivenEventRewriterTest()
+      : display_(ui::GetXDisplay()),
+        keycode_a_(XKeysymToKeycode(display_, XK_a)),
+        keycode_up_(XKeysymToKeycode(display_, XK_Up)),
+        keycode_down_(XKeysymToKeycode(display_, XK_Down)),
+        keycode_left_(XKeysymToKeycode(display_, XK_Left)),
+        keycode_right_(XKeysymToKeycode(display_, XK_Right)),
+        keycode_return_(XKeysymToKeycode(display_, XK_Return)) {
+  }
+
+  virtual ~KeyboardDrivenEventRewriterTest() {}
+
+ protected:
+  std::string GetRewrittenEventAsString(ui::KeyboardCode ui_keycode,
+                                        int ui_flags,
+                                        ui::EventType ui_type,
+                                        KeyCode x_keycode,
+                                        unsigned int x_state) {
+    XEvent xev;
+    InitXKeyEvent(ui_keycode, ui_flags, ui_type, x_keycode, x_state, &xev);
+    ui::KeyEvent keyevent(&xev, false /* is_char */);
+    rewriter_.RewriteForTesting(&keyevent);
+    return base::StringPrintf(
+        "ui_flags=%d x_state=%u", keyevent.flags(), xev.xkey.state);
+  }
+
+  std::string GetExpectedResultAsString(int ui_flags, unsigned int x_state) {
+    return base::StringPrintf("ui_flags=%d x_state=%u", ui_flags, x_state);
+  }
+
+  Display* display_;
+  const KeyCode keycode_a_;
+  const KeyCode keycode_up_;
+  const KeyCode keycode_down_;
+  const KeyCode keycode_left_;
+  const KeyCode keycode_right_;
+  const KeyCode keycode_return_;
+
+  KeyboardDrivenEventRewriter rewriter_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(KeyboardDrivenEventRewriterTest);
+};
+
+TEST_F(KeyboardDrivenEventRewriterTest, PassThrough) {
+  struct {
+    ui::KeyboardCode ui_keycode;
+    int ui_flags;
+    KeyCode x_keycode;
+    unsigned int x_state;
+  } kTests[] = {
+    { ui::VKEY_A, ui::EF_NONE, keycode_a_, 0 },
+    { ui::VKEY_A, ui::EF_CONTROL_DOWN, keycode_a_, ControlMask },
+    { ui::VKEY_A, ui::EF_ALT_DOWN, keycode_a_, Mod1Mask },
+    { ui::VKEY_A, ui::EF_SHIFT_DOWN, keycode_a_, ShiftMask },
+    { ui::VKEY_A, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN,
+        keycode_a_, ControlMask | Mod1Mask },
+    { ui::VKEY_A, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN | ui::EF_SHIFT_DOWN,
+        keycode_a_, ControlMask | Mod1Mask | ShiftMask },
+
+    { ui::VKEY_LEFT, ui::EF_NONE, keycode_left_, 0 },
+    { ui::VKEY_LEFT, ui::EF_CONTROL_DOWN, keycode_left_, ControlMask },
+    { ui::VKEY_LEFT, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN,
+        keycode_left_, ControlMask | Mod1Mask },
+
+    { ui::VKEY_RIGHT, ui::EF_NONE, keycode_right_, 0 },
+    { ui::VKEY_RIGHT, ui::EF_CONTROL_DOWN, keycode_right_, ControlMask },
+    { ui::VKEY_RIGHT, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN,
+        keycode_right_, ControlMask | Mod1Mask },
+
+    { ui::VKEY_UP, ui::EF_NONE, keycode_up_, 0 },
+    { ui::VKEY_UP, ui::EF_CONTROL_DOWN, keycode_up_, ControlMask },
+    { ui::VKEY_UP, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN,
+        keycode_up_, ControlMask | Mod1Mask },
+
+    { ui::VKEY_DOWN, ui::EF_NONE, keycode_down_, 0 },
+    { ui::VKEY_DOWN, ui::EF_CONTROL_DOWN, keycode_down_, ControlMask },
+    { ui::VKEY_DOWN, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN,
+        keycode_down_, ControlMask | Mod1Mask },
+
+    { ui::VKEY_RETURN, ui::EF_NONE, keycode_return_, 0 },
+    { ui::VKEY_RETURN, ui::EF_CONTROL_DOWN, keycode_return_, ControlMask },
+    { ui::VKEY_RETURN, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN,
+        keycode_return_, ControlMask | Mod1Mask },
+  };
+
+  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTests); ++i) {
+    EXPECT_EQ(GetExpectedResultAsString(kTests[i].ui_flags,
+                                        kTests[i].x_state),
+              GetRewrittenEventAsString(kTests[i].ui_keycode,
+                                        kTests[i].ui_flags,
+                                        ui::ET_KEY_PRESSED,
+                                        kTests[i].x_keycode,
+                                        kTests[i].x_state))
+    << "Test case " << i;
+  }
+}
+
+TEST_F(KeyboardDrivenEventRewriterTest, Rewrite) {
+  const int kModifierMask = (ui::EF_CONTROL_DOWN |
+                             ui::EF_ALT_DOWN |
+                             ui::EF_SHIFT_DOWN);
+  const unsigned int kXState = (ControlMask | Mod1Mask | ShiftMask);
+
+  struct {
+    ui::KeyboardCode ui_keycode;
+    int ui_flags;
+    KeyCode x_keycode;
+    unsigned int x_state;
+  } kTests[] = {
+    { ui::VKEY_LEFT, kModifierMask, keycode_left_, kXState },
+    { ui::VKEY_RIGHT, kModifierMask, keycode_right_, kXState },
+    { ui::VKEY_UP, kModifierMask, keycode_up_, kXState },
+    { ui::VKEY_DOWN, kModifierMask, keycode_down_, kXState },
+    { ui::VKEY_RETURN, kModifierMask, keycode_return_, kXState },
+  };
+
+  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTests); ++i) {
+    EXPECT_EQ(GetExpectedResultAsString(ui::EF_NONE, 0),
+              GetRewrittenEventAsString(kTests[i].ui_keycode,
+                                        kTests[i].ui_flags,
+                                        ui::ET_KEY_PRESSED,
+                                        kTests[i].x_keycode,
+                                        kTests[i].x_state))
+    << "Test case " << i;
+  }
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/kiosk_mode/kiosk_mode_idle_logout.h b/chrome/browser/chromeos/kiosk_mode/kiosk_mode_idle_logout.h
index 02da2a1..51d0792 100644
--- a/chrome/browser/chromeos/kiosk_mode/kiosk_mode_idle_logout.h
+++ b/chrome/browser/chromeos/kiosk_mode/kiosk_mode_idle_logout.h
@@ -8,7 +8,7 @@
 #include "ash/wm/user_activity_observer.h"
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 
diff --git a/chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h b/chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h
index eb35c6a..7a90169 100644
--- a/chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h
+++ b/chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h
@@ -9,7 +9,7 @@
 
 #include "base/basictypes.h"
 #include "base/callback_forward.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/chromeos/policy/app_pack_updater.h"
 #include "chrome/browser/chromeos/settings/device_settings_service.h"
 
diff --git a/chrome/browser/chromeos/kiosk_mode/mock_kiosk_mode_settings.h b/chrome/browser/chromeos/kiosk_mode/mock_kiosk_mode_settings.h
index bd789d4..539fde7 100644
--- a/chrome/browser/chromeos/kiosk_mode/mock_kiosk_mode_settings.h
+++ b/chrome/browser/chromeos/kiosk_mode/mock_kiosk_mode_settings.h
@@ -12,7 +12,7 @@
 #include "base/basictypes.h"
 #include "base/callback_forward.h"
 #include "base/compiler_specific.h"
-#include "base/time.h"
+#include "base/time/time.h"
 
 namespace base {
 template <typename T> struct DefaultLazyInstanceTraits;
diff --git a/chrome/browser/chromeos/login/chrome_restart_request.cc b/chrome/browser/chromeos/login/chrome_restart_request.cc
index 8b7b35e..5096919 100644
--- a/chrome/browser/chromeos/login/chrome_restart_request.cc
+++ b/chrome/browser/chromeos/login/chrome_restart_request.cc
@@ -17,7 +17,7 @@
 #include "base/process_util.h"
 #include "base/strings/string_split.h"
 #include "base/strings/stringprintf.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "base/values.h"
 #include "cc/base/switches.h"
 #include "chrome/browser/browser_process.h"
@@ -90,6 +90,7 @@
       ::switches::kEnableBeginFrameScheduling,
       ::switches::kEnableBrowserInputController,
       ::switches::kEnableCompositingForFixedPosition,
+      ::switches::kEnableEncodedScreenCapture,
       ::switches::kEnableEncryptedMedia,
       ::switches::kEnableGestureTapHighlight,
       ::switches::kDisableGestureTapHighlight,
@@ -130,16 +131,20 @@
       ::switches::kUseExynosVda,
       ::switches::kV,
       ::switches::kEnableWebGLDraftExtensions,
-      ash::switches::kAshTouchHud,
-      ash::switches::kAuraLegacyPowerButton,
+      ash::switches::kAshDefaultGuestWallpaperLarge,
+      ash::switches::kAshDefaultGuestWallpaperSmall,
+      ash::switches::kAshDefaultWallpaperLarge,
+      ash::switches::kAshDefaultWallpaperSmall,
       ash::switches::kAshDisableNewAudioHandler,
       ash::switches::kAshEnableAudioDeviceMenu,
+      ash::switches::kAshHostWindowBounds,
+      ash::switches::kAshTouchHud,
+      ash::switches::kAuraLegacyPowerButton,
       // Please keep these in alphabetical order. Non-UI Compositor switches
       // here should also be added to
       // content/browser/renderer_host/render_process_host_impl.cc.
       cc::switches::kBackgroundColorInsteadOfCheckerboard,
       cc::switches::kCompositeToMailbox,
-      cc::switches::kDisableColorEstimator,
       cc::switches::kDisableImplSidePainting,
       cc::switches::kDisableThreadedAnimation,
       cc::switches::kEnableImplSidePainting,
@@ -153,7 +158,6 @@
       cc::switches::kMaxUnusedResourceMemoryUsagePercentage,
       cc::switches::kNumRasterThreads,
       cc::switches::kShowCompositedLayerBorders,
-      cc::switches::kShowCompositedLayerTree,
       cc::switches::kShowFPSCounter,
       cc::switches::kShowNonOccludingRects,
       cc::switches::kShowOccludingRects,
diff --git a/chrome/browser/chromeos/login/enrollment/enrollment_screen.cc b/chrome/browser/chromeos/login/enrollment/enrollment_screen.cc
index 72b3075..b0f64b7 100644
--- a/chrome/browser/chromeos/login/enrollment/enrollment_screen.cc
+++ b/chrome/browser/chromeos/login/enrollment/enrollment_screen.cc
@@ -105,7 +105,6 @@
     const GoogleServiceAuthError& error) {
   enrollment_failed_once_ = true;
   actor_->ShowAuthError(error);
-  NotifyTestingObservers(false);
 
   switch (error.state()) {
     case GoogleServiceAuthError::NONE:
@@ -114,6 +113,8 @@
     case GoogleServiceAuthError::HOSTED_NOT_ALLOWED:
     case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS:
     case GoogleServiceAuthError::REQUEST_CANCELED:
+    case GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE:
+    case GoogleServiceAuthError::SERVICE_ERROR:
       UMAFailure(policy::kMetricEnrollmentLoginFailed);
       LOG(ERROR) << "Auth error " << error.state();
       return;
@@ -160,7 +161,6 @@
       base::Bind(&ScreenObserver::OnExit,
                  base::Unretained(get_screen_observer()),
                  ScreenObserver::ENTERPRISE_ENROLLMENT_COMPLETED));
-  NotifyTestingObservers(false);
 }
 
 void EnrollmentScreen::OnConfirmationClosed() {
@@ -187,15 +187,6 @@
   }
 }
 
-void EnrollmentScreen::AddTestingObserver(TestingObserver* observer) {
-  observers_.AddObserver(observer);
-}
-
-void EnrollmentScreen::RemoveTestingObserver(
-    TestingObserver* observer) {
-  observers_.RemoveObserver(observer);
-}
-
 void EnrollmentScreen::RegisterForDevicePolicy(
     const std::string& token) {
   policy::BrowserPolicyConnector* connector =
@@ -207,7 +198,6 @@
     UMAFailure(policy::kMetricEnrollmentWrongUserError);
     actor_->ShowUIError(
         EnrollmentScreenActor::UI_ERROR_DOMAIN_MISMATCH);
-    NotifyTestingObservers(false);
     return;
   }
 
@@ -226,7 +216,6 @@
   bool success = status.status() == policy::EnrollmentStatus::STATUS_SUCCESS;
   enrollment_failed_once_ |= !success;
   actor_->ShowEnrollmentStatus(status);
-  NotifyTestingObservers(success);
 
   switch (status.status()) {
     case policy::EnrollmentStatus::STATUS_SUCCESS:
@@ -294,9 +283,4 @@
   actor_->ShowSigninScreen();
 }
 
-void EnrollmentScreen::NotifyTestingObservers(bool succeeded) {
-  FOR_EACH_OBSERVER(TestingObserver, observers_,
-                    OnEnrollmentComplete(succeeded));
-}
-
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/enrollment/enrollment_screen.h b/chrome/browser/chromeos/login/enrollment/enrollment_screen.h
index 3114978..0db7475 100644
--- a/chrome/browser/chromeos/login/enrollment/enrollment_screen.h
+++ b/chrome/browser/chromeos/login/enrollment/enrollment_screen.h
@@ -10,7 +10,6 @@
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "base/memory/weak_ptr.h"
-#include "base/observer_list.h"
 #include "chrome/browser/chromeos/login/enrollment/enrollment_screen_actor.h"
 #include "chrome/browser/chromeos/login/screens/wizard_screen.h"
 #include "chrome/browser/policy/cloud/cloud_policy_constants.h"
@@ -25,15 +24,6 @@
     : public WizardScreen,
       public EnrollmentScreenActor::Controller {
  public:
-  // Used in PyAuto testing.
-  class TestingObserver {
-   public:
-    virtual ~TestingObserver() {}
-
-    // Notifies observers of a change in enrollment state.
-    virtual void OnEnrollmentComplete(bool succeeded) = 0;
-  };
-
   EnrollmentScreen(ScreenObserver* observer,
                    EnrollmentScreenActor* actor);
   virtual ~EnrollmentScreen();
@@ -61,10 +51,6 @@
     return actor_;
   }
 
-  // Used for testing.
-  void AddTestingObserver(TestingObserver* observer);
-  void RemoveTestingObserver(TestingObserver* observer);
-
  private:
   // Starts the Lockbox storage process.
   void WriteInstallAttributesData();
@@ -84,9 +70,6 @@
   // Shows the signin screen. Used as a callback to run after auth reset.
   void ShowSigninScreen();
 
-  // Notifies testing observers about the result of the enrollment.
-  void NotifyTestingObservers(bool succeeded);
-
   EnrollmentScreenActor* actor_;
   bool is_auto_enrollment_;
   bool can_exit_enrollment_;
@@ -95,9 +78,6 @@
   int lockbox_init_duration_;
   base::WeakPtrFactory<EnrollmentScreen> weak_ptr_factory_;
 
-  // Observers.
-  ObserverList<TestingObserver, true> observers_;
-
   DISALLOW_COPY_AND_ASSIGN(EnrollmentScreen);
 };
 
diff --git a/chrome/browser/chromeos/login/enrollment/enrollment_screen_actor.h b/chrome/browser/chromeos/login/enrollment/enrollment_screen_actor.h
index d9b5470..1430309 100644
--- a/chrome/browser/chromeos/login/enrollment/enrollment_screen_actor.h
+++ b/chrome/browser/chromeos/login/enrollment/enrollment_screen_actor.h
@@ -84,10 +84,6 @@
 
   // Update the UI to report the |status| of the enrollment procedure.
   virtual void ShowEnrollmentStatus(policy::EnrollmentStatus status) = 0;
-
-  // Used for testing only.
-  virtual void SubmitTestCredentials(const std::string& email,
-                                     const std::string& password) = 0;
 };
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/enrollment/mock_enrollment_screen.h b/chrome/browser/chromeos/login/enrollment/mock_enrollment_screen.h
index dca38f4..5687331 100644
--- a/chrome/browser/chromeos/login/enrollment/mock_enrollment_screen.h
+++ b/chrome/browser/chromeos/login/enrollment/mock_enrollment_screen.h
@@ -38,8 +38,6 @@
   MOCK_METHOD1(ShowAuthError, void(const GoogleServiceAuthError&));
   MOCK_METHOD1(ShowUIError, void(UIError));
   MOCK_METHOD1(ShowEnrollmentStatus, void(policy::EnrollmentStatus status));
-  MOCK_METHOD2(SubmitTestCredentials, void(const std::string& email,
-                                           const std::string& password));
 };
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/existing_user_controller.cc b/chrome/browser/chromeos/login/existing_user_controller.cc
index 505746b..aa9b0ea 100644
--- a/chrome/browser/chromeos/login/existing_user_controller.cc
+++ b/chrome/browser/chromeos/login/existing_user_controller.cc
@@ -181,8 +181,13 @@
   if (show_users_on_signin) {
     for (UserList::const_iterator it = users.begin(); it != users.end(); ++it) {
       // TODO(xiyuan): Clean user profile whose email is not in whitelist.
-      if (LoginUtils::IsWhitelisted((*it)->email()) ||
-          (*it)->GetType() != User::USER_TYPE_REGULAR) {
+      bool meets_locally_managed_requirements =
+          (*it)->GetType() != User::USER_TYPE_LOCALLY_MANAGED ||
+          UserManager::Get()->AreLocallyManagedUsersAllowed();
+      bool meets_whitelist_requirements =
+          LoginUtils::IsWhitelisted((*it)->email()) ||
+          (*it)->GetType() != User::USER_TYPE_REGULAR;
+      if (meets_locally_managed_requirements && meets_whitelist_requirements) {
         filtered_users.push_back(*it);
       }
     }
@@ -438,6 +443,11 @@
   is_login_in_progress_ = true;
   if (gaia::ExtractDomainName(user_context.username) ==
           UserManager::kLocallyManagedUserDomain) {
+    if (!UserManager::Get()->AreLocallyManagedUsersAllowed()) {
+      LOG(ERROR) << "Login attempt of locally managed user detected.";
+      login_display_->SetUIEnabled(true);
+      return;
+    }
     login_performer_->LoginAsLocallyManagedUser(
         UserContext(user_context.username,
                     user_context.password,
diff --git a/chrome/browser/chromeos/login/existing_user_controller.h b/chrome/browser/chromeos/login/existing_user_controller.h
index a9557b6..1dc7609 100644
--- a/chrome/browser/chromeos/login/existing_user_controller.h
+++ b/chrome/browser/chromeos/login/existing_user_controller.h
@@ -14,8 +14,8 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/strings/string16.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
 #include "chrome/browser/chromeos/login/login_display.h"
 #include "chrome/browser/chromeos/login/login_performer.h"
diff --git a/chrome/browser/chromeos/login/hwid_checker.cc b/chrome/browser/chromeos/login/hwid_checker.cc
index 9554a5e..0f1f0f6 100644
--- a/chrome/browser/chromeos/login/hwid_checker.cc
+++ b/chrome/browser/chromeos/login/hwid_checker.cc
@@ -91,7 +91,7 @@
   std::string hwid;
   chromeos::system::StatisticsProvider* stats =
       chromeos::system::StatisticsProvider::GetInstance();
-  if (!stats->GetMachineStatistic("hardware_class", &hwid)) {
+  if (!stats->GetMachineStatistic(chromeos::system::kHardwareClass, &hwid)) {
     LOG(ERROR) << "Couldn't get machine statistic 'hardware_class'.";
     return false;
   }
diff --git a/chrome/browser/chromeos/login/kiosk_browsertest.cc b/chrome/browser/chromeos/login/kiosk_browsertest.cc
index 3998ea9..5f24137 100644
--- a/chrome/browser/chromeos/login/kiosk_browsertest.cc
+++ b/chrome/browser/chromeos/login/kiosk_browsertest.cc
@@ -443,7 +443,7 @@
 
     scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse());
     if (url.path() == "/ServiceLogin") {
-      http_response->set_code(net::test_server::SUCCESS);
+      http_response->set_code(net::HTTP_OK);
       http_response->set_content(service_login_response_);
       http_response->set_content_type("text/html");
     } else if (url.path() == "/ServiceLoginAuth") {
@@ -454,7 +454,7 @@
       int continue_arg_end = request.content.find("&", continue_arg_begin);
       const std::string continue_url = request.content.substr(
           continue_arg_begin, continue_arg_end - continue_arg_begin);
-      http_response->set_code(net::test_server::SUCCESS);
+      http_response->set_code(net::HTTP_OK);
       const std::string redirect_js =
           "document.location.href = unescape('" + continue_url + "');";
       http_response->set_content(
diff --git a/chrome/browser/chromeos/login/lock_window_aura.cc b/chrome/browser/chromeos/login/lock_window_aura.cc
index 79191b7..ea9cc17 100644
--- a/chrome/browser/chromeos/login/lock_window_aura.cc
+++ b/chrome/browser/chromeos/login/lock_window_aura.cc
@@ -43,7 +43,7 @@
   views::Widget::InitParams params(
       views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
   params.show_state = ui::SHOW_STATE_FULLSCREEN;
-  params.transparent = true;
+  params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
   // TODO(oshima): move the lock screen harness to ash.
   params.parent =
       ash::Shell::GetContainer(
diff --git a/chrome/browser/chromeos/login/login_display_host_impl.cc b/chrome/browser/chromeos/login/login_display_host_impl.cc
index aa656d2..67fe948 100644
--- a/chrome/browser/chromeos/login/login_display_host_impl.cc
+++ b/chrome/browser/chromeos/login/login_display_host_impl.cc
@@ -18,7 +18,7 @@
 #include "base/prefs/pref_service.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_restrictions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_shutdown.h"
@@ -42,6 +42,7 @@
 #include "chrome/browser/chromeos/policy/auto_enrollment_client.h"
 #include "chrome/browser/chromeos/system/statistics_provider.h"
 #include "chrome/browser/chromeos/system/timezone_settings.h"
+#include "chrome/browser/chromeos/ui/focus_ring_controller.h"
 #include "chrome/browser/lifetime/application_lifetime.h"
 #include "chrome/browser/managed_mode/managed_mode.h"
 #include "chrome/browser/policy/browser_policy_connector.h"
@@ -261,9 +262,14 @@
 
   bool keyboard_driven_oobe = false;
   system::StatisticsProvider::GetInstance()->GetMachineFlag(
-      chromeos::kOemKeyboardDrivenOobeKey, &keyboard_driven_oobe);
-  if (keyboard_driven_oobe)
+      chromeos::system::kOemKeyboardDrivenOobeKey,
+      &keyboard_driven_oobe);
+  if (keyboard_driven_oobe) {
     views::FocusManager::set_arrow_key_traversal_enabled(true);
+
+    focus_ring_controller_.reset(new FocusRingController);
+    focus_ring_controller_->SetVisible(true);
+  }
 }
 
 LoginDisplayHostImpl::~LoginDisplayHostImpl() {
@@ -753,7 +759,7 @@
       views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
   params.bounds = background_bounds();
   params.show_state = ui::SHOW_STATE_FULLSCREEN;
-  params.transparent = true;
+  params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
   params.parent =
       ash::Shell::GetContainer(
           ash::Shell::GetPrimaryRootWindow(),
diff --git a/chrome/browser/chromeos/login/login_display_host_impl.h b/chrome/browser/chromeos/login/login_display_host_impl.h
index 14d8251..42c279e 100644
--- a/chrome/browser/chromeos/login/login_display_host_impl.h
+++ b/chrome/browser/chromeos/login/login_display_host_impl.h
@@ -29,6 +29,7 @@
 
 namespace chromeos {
 
+class FocusRingController;
 class OobeUI;
 class WebUILoginDisplay;
 class WebUILoginView;
@@ -221,6 +222,10 @@
   // Active instance of authentication prewarmer.
   scoped_ptr<AuthPrewarmer> auth_prewarmer_;
 
+  // A focus ring controller to draw focus ring around view for keyboard
+  // driven oobe.
+  scoped_ptr<FocusRingController> focus_ring_controller_;
+
   DISALLOW_COPY_AND_ASSIGN(LoginDisplayHostImpl);
 };
 
diff --git a/chrome/browser/chromeos/login/login_utils.cc b/chrome/browser/chromeos/login/login_utils.cc
index ecb901d..98f1764 100644
--- a/chrome/browser/chromeos/login/login_utils.cc
+++ b/chrome/browser/chromeos/login/login_utils.cc
@@ -26,7 +26,7 @@
 #include "base/synchronization/lock.h"
 #include "base/task_runner_util.h"
 #include "base/threading/worker_pool.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/about_flags.h"
 #include "chrome/browser/app_mode/app_mode_utils.h"
 #include "chrome/browser/browser_process.h"
@@ -254,7 +254,9 @@
   CommandLine user_flags(CommandLine::NO_PROGRAM);
   about_flags::PrefServiceFlagsStorage flags_storage_(profile->GetPrefs());
   about_flags::ConvertFlagsToSwitches(&flags_storage_, &user_flags);
-  if (!about_flags::AreSwitchesIdenticalToCurrentCommandLine(
+  // Only restart if needed and if not going into managed mode.
+  if (!UserManager::Get()->IsLoggedInAsLocallyManagedUser() &&
+      !about_flags::AreSwitchesIdenticalToCurrentCommandLine(
           user_flags, *CommandLine::ForCurrentProcess())) {
     CommandLine::StringVector flags;
     // argv[0] is the program name |CommandLine::NO_PROGRAM|.
diff --git a/chrome/browser/chromeos/login/login_utils_browsertest.cc b/chrome/browser/chromeos/login/login_utils_browsertest.cc
index 9b633a0..275c521 100644
--- a/chrome/browser/chromeos/login/login_utils_browsertest.cc
+++ b/chrome/browser/chromeos/login/login_utils_browsertest.cc
@@ -736,4 +736,4 @@
 
 }  // namespace
 
-}  // namespace chromeos
+}
diff --git a/chrome/browser/chromeos/login/managed/locally_managed_user_creation_controller.cc b/chrome/browser/chromeos/login/managed/locally_managed_user_creation_controller.cc
index 6ce2359..55b1d82 100644
--- a/chrome/browser/chromeos/login/managed/locally_managed_user_creation_controller.cc
+++ b/chrome/browser/chromeos/login/managed/locally_managed_user_creation_controller.cc
@@ -90,6 +90,12 @@
 
 void LocallyManagedUserCreationController::StartCreation() {
   DCHECK(creation_context_);
+  VLOG(1) << "Starting supervised user creation";
+  timeout_timer_.Start(
+      FROM_HERE, base::TimeDelta::FromSeconds(kUserCreationTimeoutSeconds),
+      this,
+      &LocallyManagedUserCreationController::CreationTimedOut);
+
   UserManager::Get()->StartLocallyManagedUserCreationTransaction(
       creation_context_->display_name);
 
@@ -102,7 +108,7 @@
 
   UserManager::Get()->SetLocallyManagedUserCreationTransactionUserId(
       creation_context_->user_id);
-
+  VLOG(1) << "Creating cryptohome";
   authenticator_ = new ManagedUserAuthenticator(this);
   authenticator_->AuthenticateToCreate(user->email(),
                                        creation_context_->password);
@@ -110,6 +116,7 @@
 
 void LocallyManagedUserCreationController::OnAuthenticationFailure(
     ManagedUserAuthenticator::AuthState error) {
+  timeout_timer_.Stop();
   ErrorCode code = NO_ERROR;
   switch (error) {
     case ManagedUserAuthenticator::NO_MOUNT:
@@ -138,18 +145,18 @@
   creation_context_->master_key = StringToLowerASCII(base::HexEncode(
       reinterpret_cast<const void*>(master_key_bytes),
       sizeof(master_key_bytes)));
-  // TODO(antrim): Add this key as secondary as soon as wad@ adds API in
-  // cryptohome.
+  VLOG(1) << "Adding master key";
+  authenticator_->AddMasterKey(creation_context_->user_id,
+                               creation_context_->password,
+                               creation_context_->master_key);
+}
 
-  timeout_timer_.Start(
-      FROM_HERE, base::TimeDelta::FromSeconds(kUserCreationTimeoutSeconds),
-      this,
-      &LocallyManagedUserCreationController::CreationTimedOut);
-
+void LocallyManagedUserCreationController::OnAddKeySuccess() {
   creation_context_->service =
       ManagedUserRegistrationServiceFactory::GetForProfile(
           creation_context_->manager_profile);
 
+  VLOG(1) << "Creating user on server";
   ManagedUserRegistrationInfo info(creation_context_->display_name);
   info.master_key = creation_context_->master_key;
   creation_context_->service->Register(
@@ -161,20 +168,18 @@
 void LocallyManagedUserCreationController::RegistrationCallback(
     const GoogleServiceAuthError& error,
     const std::string& token) {
-  timeout_timer_.Stop();
   if (error.state() == GoogleServiceAuthError::NONE) {
     TokenFetched(token);
   } else {
-    // Do not report error if we cancelled request.
+    timeout_timer_.Stop();
     LOG(ERROR) << "Managed user creation failed. Error code " << error.state();
-    if (error.state() == GoogleServiceAuthError::REQUEST_CANCELED)
-      return;
     if (consumer_)
       consumer_->OnCreationError(CLOUD_SERVER_ERROR);
   }
 }
 
 void LocallyManagedUserCreationController::CreationTimedOut() {
+  LOG(ERROR) << "Supervised user creation timed out.";
   if (consumer_)
     consumer_->OnCreationTimeout();
 }
@@ -212,6 +217,7 @@
 
 void LocallyManagedUserCreationController::OnManagedUserFilesStored(
     bool success) {
+  timeout_timer_.Stop();
   if (!success) {
     if (consumer_)
       consumer_->OnCreationError(TOKEN_WRITE_FAILED);
diff --git a/chrome/browser/chromeos/login/managed/locally_managed_user_creation_controller.h b/chrome/browser/chromeos/login/managed/locally_managed_user_creation_controller.h
index cd0fa83..2185fe8 100644
--- a/chrome/browser/chromeos/login/managed/locally_managed_user_creation_controller.h
+++ b/chrome/browser/chromeos/login/managed/locally_managed_user_creation_controller.h
@@ -11,7 +11,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/strings/string16.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/chromeos/login/managed/managed_user_authenticator.h"
 #include "chrome/browser/managed_mode/managed_user_registration_service.h"
 
@@ -94,6 +94,7 @@
   virtual void OnAuthenticationFailure(
       ManagedUserAuthenticator::AuthState error) OVERRIDE;
   virtual void OnMountSuccess(const std::string& mount_hash) OVERRIDE;
+  virtual void OnAddKeySuccess() OVERRIDE;
 
   void CreationTimedOut();
   void RegistrationCallback(const GoogleServiceAuthError& error,
diff --git a/chrome/browser/chromeos/login/managed/locally_managed_user_creation_screen.cc b/chrome/browser/chromeos/login/managed/locally_managed_user_creation_screen.cc
index cb83007..78fe1b1 100644
--- a/chrome/browser/chromeos/login/managed/locally_managed_user_creation_screen.cc
+++ b/chrome/browser/chromeos/login/managed/locally_managed_user_creation_screen.cc
@@ -5,14 +5,20 @@
 #include "chrome/browser/chromeos/login/managed/locally_managed_user_creation_screen.h"
 
 #include "base/values.h"
+#include "chrome/browser/chromeos/camera_detector.h"
 #include "chrome/browser/chromeos/login/existing_user_controller.h"
 #include "chrome/browser/chromeos/login/managed/locally_managed_user_creation_controller.h"
 #include "chrome/browser/chromeos/login/screens/error_screen.h"
 #include "chrome/browser/chromeos/login/screens/screen_observer.h"
+#include "chrome/browser/chromeos/login/user_image.h"
+#include "chrome/browser/chromeos/login/user_image_manager.h"
 #include "chrome/browser/chromeos/login/wizard_controller.h"
 #include "chromeos/network/network_state.h"
+#include "content/public/browser/browser_thread.h"
 #include "grit/generated_resources.h"
+#include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/image/image_skia.h"
 
 namespace chromeos {
 
@@ -51,9 +57,13 @@
     ScreenObserver* observer,
     LocallyManagedUserCreationScreenHandler* actor)
     : WizardScreen(observer),
+      weak_factory_(this),
       actor_(actor),
       on_error_screen_(false),
-      on_image_screen_(false) {
+      on_image_screen_(false),
+      image_decoder_(NULL),
+      apply_photo_after_decoding_(false),
+      selected_image_(0) {
   DCHECK(actor_);
   if (actor_)
     actor_->SetDelegate(this);
@@ -62,6 +72,8 @@
 LocallyManagedUserCreationScreen::~LocallyManagedUserCreationScreen() {
   if (actor_)
     actor_->SetDelegate(NULL);
+  if (image_decoder_.get())
+    image_decoder_->set_delegate(NULL);
 }
 
 void LocallyManagedUserCreationScreen::PrepareToShow() {
@@ -221,22 +233,6 @@
     actor_->ShowErrorPage(title, message, button);
 }
 
-void LocallyManagedUserCreationScreen::SelectPicture() {
-  on_image_screen_ = true;
-  WizardController::default_controller()->
-      EnableUserImageScreenReturnToPreviousHack();
-  DictionaryValue* params = new DictionaryValue();
-  params->SetBoolean("profile_picture_enabled", false);
-  params->SetString("user_id", controller_->GetManagedUserId());
-
-  WizardController::default_controller()->
-      AdvanceToScreenWithParams(WizardController::kUserImageScreenName, params);
-}
-
-void LocallyManagedUserCreationScreen::OnCreationSuccess() {
-  SelectPicture();
-}
-
 void LocallyManagedUserCreationScreen::OnCreationTimeout() {
   if (actor_) {
     actor_->ShowStatusMessage(false /* error */, l10n_util::GetStringUTF16(
@@ -244,4 +240,97 @@
   }
 }
 
+// TODO(antrim) : this is an explicit code duplications with UserImageScreen.
+// It should be removed by issue 251179.
+
+void LocallyManagedUserCreationScreen::ApplyPicture() {
+  UserManager* user_manager = UserManager::Get();
+  UserImageManager* image_manager = user_manager->GetUserImageManager();
+  std::string user_id = controller_->GetManagedUserId();
+  switch (selected_image_) {
+    case User::kExternalImageIndex:
+      // Photo decoding may not have been finished yet.
+      if (user_photo_.isNull()) {
+        apply_photo_after_decoding_ = true;
+        return;
+      }
+      image_manager->
+          SaveUserImage(user_id, UserImage::CreateAndEncode(user_photo_));
+      break;
+    case User::kProfileImageIndex:
+      NOTREACHED() << "Supervised users have no profile pictures";
+      break;
+    default:
+      DCHECK(selected_image_ >= 0 && selected_image_ < kDefaultImagesCount);
+      image_manager->SaveUserDefaultImageIndex(user_id, selected_image_);
+      break;
+  }
+  // Proceed to tutorial.
+  actor_->ShowTutorialPage();
+}
+
+void LocallyManagedUserCreationScreen::OnCreationSuccess() {
+  ApplyPicture();
+}
+
+void LocallyManagedUserCreationScreen::CheckCameraPresence() {
+  CameraDetector::StartPresenceCheck(
+      base::Bind(&LocallyManagedUserCreationScreen::OnCameraPresenceCheckDone,
+                 weak_factory_.GetWeakPtr()));
+}
+
+void LocallyManagedUserCreationScreen::OnCameraPresenceCheckDone() {
+  if (actor_) {
+    actor_->SetCameraPresent(
+        CameraDetector::camera_presence() == CameraDetector::kCameraPresent);
+  }
+}
+
+void LocallyManagedUserCreationScreen::OnPhotoTaken(
+    const std::string& raw_data) {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  user_photo_ = gfx::ImageSkia();
+  if (image_decoder_.get())
+    image_decoder_->set_delegate(NULL);
+  image_decoder_ = new ImageDecoder(this, raw_data,
+                                    ImageDecoder::DEFAULT_CODEC);
+  scoped_refptr<base::MessageLoopProxy> task_runner =
+      content::BrowserThread::GetMessageLoopProxyForThread(
+          content::BrowserThread::UI);
+  image_decoder_->Start(task_runner);
+}
+
+void LocallyManagedUserCreationScreen::OnImageDecoded(
+    const ImageDecoder* decoder,
+    const SkBitmap& decoded_image) {
+  DCHECK_EQ(image_decoder_.get(), decoder);
+  user_photo_ = gfx::ImageSkia::CreateFrom1xBitmap(decoded_image);
+  if (apply_photo_after_decoding_)
+    ApplyPicture();
+}
+
+void LocallyManagedUserCreationScreen::OnDecodeImageFailed(
+    const ImageDecoder* decoder) {
+  NOTREACHED() << "Failed to decode PNG image from WebUI";
+}
+
+void LocallyManagedUserCreationScreen::OnImageSelected(
+    const std::string& image_type,
+    const std::string& image_url) {
+  if (image_url.empty())
+    return;
+  int user_image_index = User::kInvalidImageIndex;
+  if (image_type == "default" &&
+      IsDefaultImageUrl(image_url, &user_image_index)) {
+    selected_image_ = user_image_index;
+  } else if (image_type == "camera") {
+    selected_image_ = User::kExternalImageIndex;
+  } else {
+    NOTREACHED() << "Unexpected image type: " << image_type;
+  }
+}
+
+void LocallyManagedUserCreationScreen::OnImageAccepted() {
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/managed/locally_managed_user_creation_screen.h b/chrome/browser/chromeos/login/managed/locally_managed_user_creation_screen.h
index efef788..f5b338d 100644
--- a/chrome/browser/chromeos/login/managed/locally_managed_user_creation_screen.h
+++ b/chrome/browser/chromeos/login/managed/locally_managed_user_creation_screen.h
@@ -12,7 +12,9 @@
 #include "chrome/browser/chromeos/login/managed/locally_managed_user_creation_controller.h"
 #include "chrome/browser/chromeos/login/screens/wizard_screen.h"
 #include "chrome/browser/chromeos/net/network_portal_detector.h"
+#include "chrome/browser/image_decoder.h"
 #include "chrome/browser/ui/webui/chromeos/login/locally_managed_user_creation_screen_handler.h"
+#include "ui/gfx/image/image_skia.h"
 
 class Profile;
 
@@ -25,6 +27,7 @@
     : public WizardScreen,
       public LocallyManagedUserCreationScreenHandler::Delegate,
       public LocallyManagedUserCreationController::StatusConsumer,
+      public ImageDecoder::Delegate,
       public NetworkPortalDetector::Observer {
  public:
   LocallyManagedUserCreationScreen(
@@ -73,7 +76,6 @@
       const std::string& manager_password) OVERRIDE;
   virtual void AbortFlow() OVERRIDE;
   virtual void FinishFlow() OVERRIDE;
-  virtual void SelectPicture() OVERRIDE;
 
   // LocallyManagedUserController::StatusConsumer overrides.
   virtual void OnCreationError(
@@ -85,7 +87,26 @@
   virtual void OnPortalDetectionCompleted(
           const NetworkState* network,
           const NetworkPortalDetector::CaptivePortalState& state) OVERRIDE;
+
+  // TODO(antrim) : this is an explicit code duplications with UserImageScreen.
+  // It should be removed by issue 251179.
+
+  // LocallyManagedUserCreationScreenHandler::Delegate (image) implementation:
+  virtual void CheckCameraPresence() OVERRIDE;
+  virtual void OnPhotoTaken(const std::string& raw_data) OVERRIDE;
+  virtual void OnImageSelected(const std::string& image_url,
+                               const std::string& image_type) OVERRIDE;
+  virtual void OnImageAccepted() OVERRIDE;
+  // ImageDecoder::Delegate overrides:
+  virtual void OnImageDecoded(const ImageDecoder* decoder,
+                              const SkBitmap& decoded_image) OVERRIDE;
+  virtual void OnDecodeImageFailed(const ImageDecoder* decoder) OVERRIDE;
+
  private:
+  void ApplyPicture();
+  void OnCameraPresenceCheckDone();
+
+  base::WeakPtrFactory<LocallyManagedUserCreationScreen> weak_factory_;
   LocallyManagedUserCreationScreenHandler* actor_;
 
   scoped_ptr<LocallyManagedUserCreationController> controller_;
@@ -93,6 +114,11 @@
   bool on_error_screen_;
   bool on_image_screen_;
 
+  gfx::ImageSkia user_photo_;
+  scoped_refptr<ImageDecoder> image_decoder_;
+  bool apply_photo_after_decoding_;
+  int selected_image_;
+
   DISALLOW_COPY_AND_ASSIGN(LocallyManagedUserCreationScreen);
 };
 
diff --git a/chrome/browser/chromeos/login/managed/managed_user_authenticator.cc b/chrome/browser/chromeos/login/managed/managed_user_authenticator.cc
index 1f82c38..4984cf0 100644
--- a/chrome/browser/chromeos/login/managed/managed_user_authenticator.cc
+++ b/chrome/browser/chromeos/login/managed/managed_user_authenticator.cc
@@ -64,7 +64,6 @@
 void Mount(ManagedUserAuthenticator::AuthAttempt* attempt,
            scoped_refptr<ManagedUserAuthenticator> resolver,
            int flags) {
-  // TODO(antrim) : use additional mount function here.
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   chromeos::BootTimesLoader::Get()->AddLoginTimeMarker(
       "CryptohomeMount-LMU-Start", false);
@@ -82,6 +81,23 @@
       base::Bind(&TriggerResolveResult, attempt, resolver));
 }
 
+// Calls cryptohome's addKey method.
+void AddKey(ManagedUserAuthenticator::AuthAttempt* attempt,
+            scoped_refptr<ManagedUserAuthenticator> resolver,
+            const std::string& hashed_master_key) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  chromeos::BootTimesLoader::Get()->AddLoginTimeMarker(
+      "CryptohomeAddKey-LMU-Start", false);
+  cryptohome::AsyncMethodCaller::GetInstance()->AsyncAddKey(
+      attempt->username,
+      attempt->hashed_password,
+      hashed_master_key,
+      base::Bind(&TriggerResolveWithLoginTimeMarker,
+                 "CryptohomeAddKey-LMU-End",
+                 attempt,
+                 resolver));
+}
+
 // Returns hash of |password|, salted with the system salt.
 std::string HashPassword(const std::string& password) {
   // Get salt, ascii encode, update sha with that, then update with ascii
@@ -106,12 +122,13 @@
 ManagedUserAuthenticator::ManagedUserAuthenticator(AuthStatusConsumer* consumer)
     : consumer_(consumer) {}
 
-void ManagedUserAuthenticator::AuthenticateToMount(const std::string& username,
-                                               const std::string& password) {
+void ManagedUserAuthenticator::AuthenticateToMount(
+    const std::string& username,
+    const std::string& password) {
   std::string canonicalized = gaia::CanonicalizeEmail(username);
 
   current_state_.reset(new ManagedUserAuthenticator::AuthAttempt(
-      canonicalized, password, HashPassword(password)));
+      canonicalized, password, HashPassword(password), false));
 
   BrowserThread::PostTask(BrowserThread::UI,
       FROM_HERE,
@@ -121,13 +138,13 @@
           cryptohome::MOUNT_FLAGS_NONE));
 }
 
-void ManagedUserAuthenticator::AuthenticateToCreate(const std::string& username,
-                                                const std::string& password) {
-
+void ManagedUserAuthenticator::AuthenticateToCreate(
+    const std::string& username,
+    const std::string& password) {
   std::string canonicalized = gaia::CanonicalizeEmail(username);
 
   current_state_.reset(new ManagedUserAuthenticator::AuthAttempt(
-      canonicalized, password, HashPassword(password)));
+      canonicalized, password, HashPassword(password), false));
 
   BrowserThread::PostTask(BrowserThread::UI,
       FROM_HERE,
@@ -137,13 +154,34 @@
            cryptohome::CREATE_IF_MISSING));
 }
 
+void ManagedUserAuthenticator::AddMasterKey(
+    const std::string& username,
+    const std::string& password,
+    const std::string& master_key) {
+  std::string canonicalized = gaia::CanonicalizeEmail(username);
+
+  current_state_.reset(new ManagedUserAuthenticator::AuthAttempt(
+      canonicalized, password, HashPassword(password), true));
+
+  BrowserThread::PostTask(BrowserThread::UI,
+      FROM_HERE,
+      base::Bind(&AddKey,
+           current_state_.get(),
+           scoped_refptr<ManagedUserAuthenticator>(this),
+           HashPassword(master_key)));
+}
+
 void ManagedUserAuthenticator::OnAuthenticationSuccess(
-    const std::string& mount_hash) {
+    const std::string& mount_hash,
+    bool add_key) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   VLOG(1) << "Locally managed user authentication success";
-
-  if (consumer_)
-    consumer_->OnMountSuccess(mount_hash);
+  if (consumer_) {
+    if (add_key)
+      consumer_->OnAddKeySuccess();
+    else
+      consumer_->OnMountSuccess(mount_hash);
+  }
 }
 
 void ManagedUserAuthenticator::OnAuthenticationFailure(
@@ -200,7 +238,8 @@
           FROM_HERE,
           base::Bind(&ManagedUserAuthenticator::OnAuthenticationSuccess,
                      this,
-                     current_state_->hash()));
+                     current_state_->hash(),
+                     current_state_->add_key));
       break;
     default:
       NOTREACHED();
@@ -217,7 +256,7 @@
   // This is an important invariant.
   if (!current_state_->cryptohome_complete())
     return CONTINUE;
-  if (!current_state_->hash_obtained())
+  if (!current_state_->add_key && !current_state_->hash_obtained())
     return CONTINUE;
 
   AuthState state;
@@ -228,7 +267,7 @@
     state = ResolveCryptohomeFailureState();
 
   DCHECK(current_state_->cryptohome_complete());
-  DCHECK(current_state_->hash_obtained());
+  DCHECK(current_state_->hash_obtained() || current_state_->add_key);
   return state;
 }
 
@@ -258,11 +297,13 @@
 }
 
 ManagedUserAuthenticator::AuthAttempt::AuthAttempt(const std::string& username,
-                                               const std::string& password,
-                                               const std::string& hashed)
+                                                   const std::string& password,
+                                                   const std::string& hashed,
+                                                   bool add_key_attempt)
     : username(username),
       password(password),
       hashed_password(hashed),
+      add_key(add_key_attempt),
       cryptohome_complete_(false),
       cryptohome_outcome_(false),
       hash_obtained_(false),
diff --git a/chrome/browser/chromeos/login/managed/managed_user_authenticator.h b/chrome/browser/chromeos/login/managed/managed_user_authenticator.h
index 19b0c3d..2e12630 100644
--- a/chrome/browser/chromeos/login/managed/managed_user_authenticator.h
+++ b/chrome/browser/chromeos/login/managed/managed_user_authenticator.h
@@ -35,7 +35,8 @@
    public:
     AuthAttempt(const std::string& username,
                 const std::string& password,
-                const std::string& hashed_password);
+                const std::string& hashed_password,
+                bool add_key_attempt);
     ~AuthAttempt();
 
     // Copy |cryptohome_code| and |cryptohome_outcome| into this object,
@@ -58,6 +59,7 @@
     const std::string username;
     const std::string password;
     const std::string hashed_password;
+    const bool add_key;
 
    private:
     bool cryptohome_complete_;
@@ -76,6 +78,8 @@
     virtual void OnAuthenticationFailure(AuthState state) = 0;
     // The current login attempt has ended succesfully.
     virtual void OnMountSuccess(const std::string& mount_hash) = 0;
+    // The current add key attempt has ended succesfully.
+    virtual void OnAddKeySuccess() = 0;
   };
 
   explicit ManagedUserAuthenticator(AuthStatusConsumer* consumer);
@@ -85,6 +89,10 @@
 
   void AuthenticateToCreate(const std::string& username,
                             const std::string& password);
+
+  void AddMasterKey(const std::string& username,
+                    const std::string& password,
+                    const std::string& master_key);
   void Resolve();
 
  private:
@@ -95,7 +103,7 @@
   AuthState ResolveState();
   AuthState ResolveCryptohomeFailureState();
   AuthState ResolveCryptohomeSuccessState();
-  void OnAuthenticationSuccess(const std::string& mount_hash);
+  void OnAuthenticationSuccess(const std::string& mount_hash, bool add_key);
   void OnAuthenticationFailure(AuthState state);
 
   scoped_ptr<AuthAttempt> current_state_;
diff --git a/chrome/browser/chromeos/login/mock_user_manager.h b/chrome/browser/chromeos/login/mock_user_manager.h
index 92efb2b..503f04a 100644
--- a/chrome/browser/chromeos/login/mock_user_manager.h
+++ b/chrome/browser/chromeos/login/mock_user_manager.h
@@ -95,6 +95,7 @@
                                                      std::string*));
   MOCK_METHOD2(SetAppModeChromeClientOAuthInfo, void(const std::string&,
                                                      const std::string&));
+  MOCK_CONST_METHOD0(AreLocallyManagedUsersAllowed, bool(void));
 
   // You can't mock these functions easily because nobody can create
   // User objects but the UserManagerImpl and us.
diff --git a/chrome/browser/chromeos/login/oauth2_login_verifier.cc b/chrome/browser/chromeos/login/oauth2_login_verifier.cc
index ad31626..abff7b1 100644
--- a/chrome/browser/chromeos/login/oauth2_login_verifier.cc
+++ b/chrome/browser/chromeos/login/oauth2_login_verifier.cc
@@ -10,7 +10,7 @@
 #include "base/metrics/histogram.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/chromeos/cros/cros_library.h"
 #include "chrome/browser/chromeos/net/connectivity_state_helper.h"
 #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/chromeos/login/oobe_browsertest.cc b/chrome/browser/chromeos/login/oobe_browsertest.cc
index 676fe87..ec6c1f8 100644
--- a/chrome/browser/chromeos/login/oobe_browsertest.cc
+++ b/chrome/browser/chromeos/login/oobe_browsertest.cc
@@ -176,7 +176,7 @@
 
     scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse());
     if (url.path() == "/ServiceLogin") {
-      http_response->set_code(net::test_server::SUCCESS);
+      http_response->set_code(net::HTTP_OK);
       http_response->set_content(service_login_response_);
       http_response->set_content_type("text/html");
     } else if (url.path() == "/ServiceLoginAuth") {
@@ -187,7 +187,7 @@
       int continue_arg_end = request.content.find("&", continue_arg_begin);
       const std::string continue_url = request.content.substr(
           continue_arg_begin, continue_arg_end - continue_arg_begin);
-      http_response->set_code(net::test_server::SUCCESS);
+      http_response->set_code(net::HTTP_OK);
       const std::string redirect_js =
           "document.location.href = unescape('" + continue_url + "');";
       http_response->set_content(
diff --git a/chrome/browser/chromeos/login/screen_locker.cc b/chrome/browser/chromeos/login/screen_locker.cc
index 263c7ca..f2b0bda 100644
--- a/chrome/browser/chromeos/login/screen_locker.cc
+++ b/chrome/browser/chromeos/login/screen_locker.cc
@@ -18,7 +18,7 @@
 #include "base/message_loop.h"
 #include "base/metrics/histogram.h"
 #include "base/strings/string_util.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/chromeos/login/authenticator.h"
 #include "chrome/browser/chromeos/login/login_performer.h"
 #include "chrome/browser/chromeos/login/login_utils.h"
diff --git a/chrome/browser/chromeos/login/screen_locker.h b/chrome/browser/chromeos/login/screen_locker.h
index eac312c..42c8a52 100644
--- a/chrome/browser/chromeos/login/screen_locker.h
+++ b/chrome/browser/chromeos/login/screen_locker.h
@@ -11,7 +11,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/sequenced_task_runner_helpers.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/chromeos/login/help_app_launcher.h"
 #include "chrome/browser/chromeos/login/login_status_consumer.h"
 #include "chrome/browser/chromeos/login/screen_locker_delegate.h"
diff --git a/chrome/browser/chromeos/login/screens/network_screen.cc b/chrome/browser/chromeos/login/screens/network_screen.cc
index c79d620..167c867 100644
--- a/chrome/browser/chromeos/login/screens/network_screen.cc
+++ b/chrome/browser/chromeos/login/screens/network_screen.cc
@@ -59,9 +59,9 @@
 }
 
 void NetworkScreen::Show() {
+  Refresh();
   if (actor_)
     actor_->Show();
-  Refresh();
 }
 
 void NetworkScreen::Hide() {
diff --git a/chrome/browser/chromeos/login/screens/network_screen.h b/chrome/browser/chromeos/login/screens/network_screen.h
index ad9fdf6..1a3ccf2 100644
--- a/chrome/browser/chromeos/login/screens/network_screen.h
+++ b/chrome/browser/chromeos/login/screens/network_screen.h
@@ -8,7 +8,7 @@
 #include "base/compiler_specific.h"
 #include "base/memory/ref_counted.h"
 #include "base/strings/string16.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/chromeos/login/language_switch_menu.h"
 #include "chrome/browser/chromeos/login/screens/network_screen_actor.h"
 #include "chrome/browser/chromeos/login/screens/wizard_screen.h"
diff --git a/chrome/browser/chromeos/login/screens/terms_of_service_screen.cc b/chrome/browser/chromeos/login/screens/terms_of_service_screen.cc
index f5be2fd..4cc4060 100644
--- a/chrome/browser/chromeos/login/screens/terms_of_service_screen.cc
+++ b/chrome/browser/chromeos/login/screens/terms_of_service_screen.cc
@@ -9,7 +9,7 @@
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/prefs/pref_service.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/login/screens/screen_observer.h"
 #include "chrome/browser/chromeos/login/wizard_controller.h"
diff --git a/chrome/browser/chromeos/login/screens/terms_of_service_screen.h b/chrome/browser/chromeos/login/screens/terms_of_service_screen.h
index c1cec5d..1b79569 100644
--- a/chrome/browser/chromeos/login/screens/terms_of_service_screen.h
+++ b/chrome/browser/chromeos/login/screens/terms_of_service_screen.h
@@ -8,7 +8,7 @@
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/chromeos/login/screens/terms_of_service_screen_actor.h"
 #include "chrome/browser/chromeos/login/screens/wizard_screen.h"
 #include "net/url_request/url_fetcher_delegate.h"
diff --git a/chrome/browser/chromeos/login/screens/update_screen.h b/chrome/browser/chromeos/login/screens/update_screen.h
index bdfd26b..cb10c67 100644
--- a/chrome/browser/chromeos/login/screens/update_screen.h
+++ b/chrome/browser/chromeos/login/screens/update_screen.h
@@ -11,8 +11,8 @@
 #include "base/compiler_specific.h"
 #include "base/gtest_prod_util.h"
 #include "base/memory/weak_ptr.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/chromeos/login/screens/update_screen_actor.h"
 #include "chrome/browser/chromeos/login/screens/wizard_screen.h"
 #include "chrome/browser/chromeos/net/network_portal_detector.h"
diff --git a/chrome/browser/chromeos/login/screens/update_screen_actor.h b/chrome/browser/chromeos/login/screens/update_screen_actor.h
index d17276c..89095ae 100644
--- a/chrome/browser/chromeos/login/screens/update_screen_actor.h
+++ b/chrome/browser/chromeos/login/screens/update_screen_actor.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_UPDATE_SCREEN_ACTOR_H_
 #define CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_UPDATE_SCREEN_ACTOR_H_
 
-#include "base/time.h"
+#include "base/time/time.h"
 
 namespace chromeos {
 
diff --git a/chrome/browser/chromeos/login/screens/user_image_screen.cc b/chrome/browser/chromeos/login/screens/user_image_screen.cc
index 7fd947e..def0424 100644
--- a/chrome/browser/chromeos/login/screens/user_image_screen.cc
+++ b/chrome/browser/chromeos/login/screens/user_image_screen.cc
@@ -166,7 +166,7 @@
 }
 
 void UserImageScreen::SetUserID(const std::string& user_id) {
-  DCHECK(!user_id_.empty());
+  DCHECK(!user_id.empty());
   user_id_ = user_id;
 }
 
diff --git a/chrome/browser/chromeos/login/user_image_manager_browsertest.cc b/chrome/browser/chromeos/login/user_image_manager_browsertest.cc
index 4e967e8..e485561 100644
--- a/chrome/browser/chromeos/login/user_image_manager_browsertest.cc
+++ b/chrome/browser/chromeos/login/user_image_manager_browsertest.cc
@@ -250,7 +250,8 @@
   EXPECT_EQ(saved_image.height(), user->image().height());
 }
 
-IN_PROC_BROWSER_TEST_F(UserImageManagerTest, NonJPEGImageFromFile) {
+// http://crbug.com/257009.
+IN_PROC_BROWSER_TEST_F(UserImageManagerTest, DISABLED_NonJPEGImageFromFile) {
   ExpectImageChange();
   UserManager::Get()->GetUsers();  // Load users.
   // Wait for image load.
diff --git a/chrome/browser/chromeos/login/user_image_manager_impl.cc b/chrome/browser/chromeos/login/user_image_manager_impl.cc
index 0af1479..f22a8d4 100644
--- a/chrome/browser/chromeos/login/user_image_manager_impl.cc
+++ b/chrome/browser/chromeos/login/user_image_manager_impl.cc
@@ -15,7 +15,7 @@
 #include "base/prefs/pref_service.h"
 #include "base/rand_util.h"
 #include "base/threading/worker_pool.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/login/default_user_images.h"
@@ -145,7 +145,7 @@
   BrowserThread::PostTask(
       BrowserThread::FILE,
       FROM_HERE,
-      base::Bind(base::IgnoreResult(&file_util::Delete),
+      base::Bind(base::IgnoreResult(&base::Delete),
                  fp, /* recursive= */  false));
 }
 
diff --git a/chrome/browser/chromeos/login/user_image_manager_impl.h b/chrome/browser/chromeos/login/user_image_manager_impl.h
index e6fb534..ef6da72 100644
--- a/chrome/browser/chromeos/login/user_image_manager_impl.h
+++ b/chrome/browser/chromeos/login/user_image_manager_impl.h
@@ -10,8 +10,8 @@
 
 #include "base/basictypes.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/chromeos/login/user.h"
 #include "chrome/browser/chromeos/login/user_image_loader.h"
 #include "chrome/browser/chromeos/login/user_image_manager.h"
diff --git a/chrome/browser/chromeos/login/user_manager.h b/chrome/browser/chromeos/login/user_manager.h
index 49c3448..2b9b93a 100644
--- a/chrome/browser/chromeos/login/user_manager.h
+++ b/chrome/browser/chromeos/login/user_manager.h
@@ -349,6 +349,9 @@
 
   virtual void NotifyLocalStateChanged() = 0;
 
+  // Returns true if locally managed users allowed.
+  virtual bool AreLocallyManagedUsersAllowed() const = 0;
+
  private:
   friend class ScopedUserManagerEnabler;
 
diff --git a/chrome/browser/chromeos/login/user_manager_impl.cc b/chrome/browser/chromeos/login/user_manager_impl.cc
index 0fc5a6a..7edf248 100644
--- a/chrome/browser/chromeos/login/user_manager_impl.cc
+++ b/chrome/browser/chromeos/login/user_manager_impl.cc
@@ -35,6 +35,7 @@
 #include "chrome/browser/chromeos/policy/device_local_account.h"
 #include "chrome/browser/chromeos/session_length_limiter.h"
 #include "chrome/browser/chromeos/settings/cros_settings_names.h"
+#include "chrome/browser/managed_mode/managed_user_service.h"
 #include "chrome/browser/policy/browser_policy_connector.h"
 #include "chrome/browser/prefs/scoped_user_pref_update.h"
 #include "chrome/browser/profiles/profile_manager.h"
@@ -205,6 +206,7 @@
       is_current_user_new_(false),
       is_current_user_ephemeral_regular_user_(false),
       ephemeral_users_enabled_(false),
+      locally_managed_users_enabled_by_policy_(false),
       merge_session_state_(MERGE_STATUS_NOT_STARTED),
       observed_sync_service_(NULL),
       user_image_manager_(new UserImageManagerImpl) {
@@ -215,6 +217,10 @@
   registrar_.Add(this, chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED,
       content::NotificationService::AllSources());
   RetrieveTrustedDevicePolicies();
+  cros_settings_->AddSettingsObserver(kAccountsPrefDeviceLocalAccounts,
+                                      this);
+  cros_settings_->AddSettingsObserver(kAccountsPrefSupervisedUsersEnabled,
+                                      this);
   UpdateLoginState();
 }
 
@@ -237,6 +243,9 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   cros_settings_->RemoveSettingsObserver(kAccountsPrefDeviceLocalAccounts,
                                          this);
+  cros_settings_->RemoveSettingsObserver(
+      kAccountsPrefSupervisedUsersEnabled,
+      this);
   // Stop the session length limiter.
   session_length_limiter_.reset();
 
@@ -436,8 +445,7 @@
   prefs_new_users_update->Insert(0, new base::StringValue(e_mail));
   users_.insert(users_.begin(), new_user);
 
-
-  const User* manager = FindUser(manager_id);
+  const User* manager = FindUser(gaia::CanonicalizeEmail(manager_id));
   CHECK(manager);
 
   DictionaryPrefUpdate manager_update(local_state, kManagedUserManagers);
@@ -713,11 +721,14 @@
         }
       }
       break;
-    case chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED:
-      DCHECK_EQ(*content::Details<const std::string>(details).ptr(),
-                kAccountsPrefDeviceLocalAccounts);
+    case chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED: {
+      std::string changed_setting =
+          *content::Details<const std::string>(details).ptr();
+      DCHECK(changed_setting == kAccountsPrefDeviceLocalAccounts ||
+             changed_setting == kAccountsPrefSupervisedUsersEnabled);
       RetrieveTrustedDevicePolicies();
       break;
+    }
     default:
       NOTREACHED();
   }
@@ -1010,6 +1021,7 @@
 
 void UserManagerImpl::RetrieveTrustedDevicePolicies() {
   ephemeral_users_enabled_ = false;
+  locally_managed_users_enabled_by_policy_ = false;
   owner_email_ = "";
 
   // Schedule a callback if device policy has not yet been verified.
@@ -1021,6 +1033,8 @@
 
   cros_settings_->GetBoolean(kAccountsPrefEphemeralUsersEnabled,
                              &ephemeral_users_enabled_);
+  cros_settings_->GetBoolean(kAccountsPrefSupervisedUsersEnabled,
+                             &locally_managed_users_enabled_by_policy_);
   cros_settings_->GetString(kDeviceOwner, &owner_email_);
 
   EnsureUsersLoaded();
@@ -1052,9 +1066,6 @@
 
   if (changed)
     NotifyUserListChanged();
-
-  cros_settings_->AddSettingsObserver(kAccountsPrefDeviceLocalAccounts,
-                                      this);
 }
 
 bool UserManagerImpl::AreEphemeralUsersEnabled() const {
@@ -1542,7 +1553,9 @@
 
 UserFlow* UserManagerImpl::GetUserFlow(const std::string& email) const {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  FlowMap::const_iterator it = specific_flows_.find(email);
+  std::string canonical_email = email.empty() ? email :
+      gaia::CanonicalizeEmail(email);
+  FlowMap::const_iterator it = specific_flows_.find(canonical_email);
   if (it != specific_flows_.end())
     return it->second;
   return GetDefaultUserFlow();
@@ -1550,13 +1563,15 @@
 
 void UserManagerImpl::SetUserFlow(const std::string& email, UserFlow* flow) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  ResetUserFlow(email);
-  specific_flows_[email] = flow;
+  std::string canonical_email = gaia::CanonicalizeEmail(email);
+  ResetUserFlow(canonical_email);
+  specific_flows_[canonical_email] = flow;
 }
 
 void UserManagerImpl::ResetUserFlow(const std::string& email) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  FlowMap::iterator it = specific_flows_.find(email);
+  std::string canonical_email = gaia::CanonicalizeEmail(email);
+  FlowMap::iterator it = specific_flows_.find(canonical_email);
   if (it != specific_flows_.end()) {
     delete it->second;
     specific_flows_.erase(it);
@@ -1586,6 +1601,12 @@
   chrome_client_secret_ = chrome_client_secret;
 }
 
+bool UserManagerImpl::AreLocallyManagedUsersAllowed() const {
+  return ManagedUserService::AreManagedUsersEnabled() &&
+        (locally_managed_users_enabled_by_policy_ ||
+         !g_browser_process->browser_policy_connector()->IsEnterpriseManaged());
+}
+
 UserFlow* UserManagerImpl::GetDefaultUserFlow() const {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   if (!default_flow_.get())
diff --git a/chrome/browser/chromeos/login/user_manager_impl.h b/chrome/browser/chromeos/login/user_manager_impl.h
index 63be822..19c8d45 100644
--- a/chrome/browser/chromeos/login/user_manager_impl.h
+++ b/chrome/browser/chromeos/login/user_manager_impl.h
@@ -134,6 +134,7 @@
   virtual void SetAppModeChromeClientOAuthInfo(
       const std::string& chrome_client_id,
       const std::string& chrome_client_secret) OVERRIDE;
+  virtual bool AreLocallyManagedUsersAllowed() const OVERRIDE;
 
   // content::NotificationObserver implementation.
   virtual void Observe(int type,
@@ -357,6 +358,11 @@
   // policy yet.
   bool ephemeral_users_enabled_;
 
+  // Cached flag indicating whether the locally managed users are enabled by
+  // policy. Defaults to |false| if the value has not been read from trusted
+  // device policy yet.
+  bool locally_managed_users_enabled_by_policy_;
+
   // Merge session state (cookie restore process state).
   MergeSessionState merge_session_state_;
 
@@ -392,7 +398,8 @@
   // Lazy-initialized default flow.
   mutable scoped_ptr<UserFlow> default_flow_;
 
-  // Specific flows by user e-mail.
+  // Specific flows by user e-mail. Keys should be canonicalized before
+  // access.
   FlowMap specific_flows_;
 
   // User sessions that have to be restored after browser crash.
diff --git a/chrome/browser/chromeos/login/user_manager_unittest.cc b/chrome/browser/chromeos/login/user_manager_unittest.cc
index b0fe8d8..e2c4773 100644
--- a/chrome/browser/chromeos/login/user_manager_unittest.cc
+++ b/chrome/browser/chromeos/login/user_manager_unittest.cc
@@ -47,12 +47,11 @@
     cros_settings_->AddSettingsProvider(&stub_settings_provider_);
 
     // Populate the stub DeviceSettingsProvider with valid values.
-    SetDeviceSettings(false, "");
+    SetDeviceSettings(false, "", false);
 
     // Register an in-memory local settings instance.
     local_state_.reset(new TestingPrefServiceSimple);
-    reinterpret_cast<TestingBrowserProcess*>(g_browser_process)
-        ->SetLocalState(local_state_.get());
+    TestingBrowserProcess::GetGlobal()->SetLocalState(local_state_.get());
     UserManager::RegisterPrefs(local_state_->registry());
     // Wallpaper manager and user image managers prefs will be accessed by the
     // unit-test as well.
@@ -64,8 +63,7 @@
 
   virtual void TearDown() OVERRIDE {
     // Unregister the in-memory local settings instance.
-    reinterpret_cast<TestingBrowserProcess*>(g_browser_process)
-        ->SetLocalState(0);
+    TestingBrowserProcess::GetGlobal()->SetLocalState(0);
 
     // Restore the real DeviceSettingsProvider.
     EXPECT_TRUE(
@@ -78,24 +76,28 @@
     base::RunLoop().RunUntilIdle();
   }
 
+  UserManagerImpl* GetUserManagerImpl() const {
+    return static_cast<UserManagerImpl*>(UserManager::Get());
+  }
+
   bool GetUserManagerEphemeralUsersEnabled() const {
-    return reinterpret_cast<UserManagerImpl*>(UserManager::Get())->
-        ephemeral_users_enabled_;
+    return GetUserManagerImpl()->ephemeral_users_enabled_;
+  }
+
+  bool GetUserManagerLocallyManagedUsersEnabledByPolicy() const {
+    return GetUserManagerImpl()->locally_managed_users_enabled_by_policy_;
   }
 
   void SetUserManagerEphemeralUsersEnabled(bool ephemeral_users_enabled) {
-    reinterpret_cast<UserManagerImpl*>(UserManager::Get())->
-        ephemeral_users_enabled_ = ephemeral_users_enabled;
+    GetUserManagerImpl()->ephemeral_users_enabled_ = ephemeral_users_enabled;
   }
 
   const std::string& GetUserManagerOwnerEmail() const {
-    return reinterpret_cast<UserManagerImpl*>(UserManager::Get())->
-        owner_email_;
+    return GetUserManagerImpl()-> owner_email_;
   }
 
   void SetUserManagerOwnerEmail(const std::string& owner_email) {
-    reinterpret_cast<UserManagerImpl*>(UserManager::Get())->
-        owner_email_ = owner_email;
+    GetUserManagerImpl()->owner_email_ = owner_email;
   }
 
   void ResetUserManager() {
@@ -107,18 +109,20 @@
   }
 
   void SetDeviceSettings(bool ephemeral_users_enabled,
-                         const std::string &owner) {
+                         const std::string &owner,
+                         bool locally_managed_users_enabled) {
     base::FundamentalValue
         ephemeral_users_enabled_value(ephemeral_users_enabled);
     stub_settings_provider_.Set(kAccountsPrefEphemeralUsersEnabled,
         ephemeral_users_enabled_value);
     base::StringValue owner_value(owner);
     stub_settings_provider_.Set(kDeviceOwner, owner_value);
+    stub_settings_provider_.Set(kAccountsPrefSupervisedUsersEnabled,
+        base::FundamentalValue(locally_managed_users_enabled));
   }
 
   void RetrieveTrustedDevicePolicies() {
-    reinterpret_cast<UserManagerImpl*>(UserManager::Get())->
-        RetrieveTrustedDevicePolicies();
+    GetUserManagerImpl()->RetrieveTrustedDevicePolicies();
   }
 
  protected:
@@ -142,7 +146,7 @@
   SetUserManagerEphemeralUsersEnabled(true);
   SetUserManagerOwnerEmail("");
 
-  SetDeviceSettings(false, "owner@invalid.domain");
+  SetDeviceSettings(false, "owner@invalid.domain", false);
   RetrieveTrustedDevicePolicies();
 
   EXPECT_FALSE(GetUserManagerEphemeralUsersEnabled());
@@ -166,7 +170,7 @@
   EXPECT_EQ((*users)[1]->email(), "user0@invalid.domain");
   EXPECT_EQ((*users)[2]->email(), "owner@invalid.domain");
 
-  SetDeviceSettings(true, "owner@invalid.domain");
+  SetDeviceSettings(true, "owner@invalid.domain", false);
   RetrieveTrustedDevicePolicies();
 
   users = &UserManager::Get()->GetUsers();
@@ -175,7 +179,7 @@
 }
 
 TEST_F(UserManagerTest, RegularUserLoggedInAsEphemeral) {
-  SetDeviceSettings(true, "owner@invalid.domain");
+  SetDeviceSettings(true, "owner@invalid.domain", false);
   RetrieveTrustedDevicePolicies();
 
   UserManager::Get()->UserLoggedIn(
@@ -190,4 +194,13 @@
   EXPECT_EQ((*users)[0]->email(), "owner@invalid.domain");
 }
 
+TEST_F(UserManagerTest, DisablingLMUByDeviceSettings) {
+  SetDeviceSettings(false, "owner@invalid.domain", false);
+  RetrieveTrustedDevicePolicies();
+  EXPECT_EQ(GetUserManagerLocallyManagedUsersEnabledByPolicy(), false);
+  SetDeviceSettings(false, "owner@invalid.domain", true);
+  RetrieveTrustedDevicePolicies();
+  EXPECT_EQ(GetUserManagerLocallyManagedUsersEnabledByPolicy(), true);
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/wallpaper_manager.cc b/chrome/browser/chromeos/login/wallpaper_manager.cc
index 9a0cc85..dcd09ae 100644
--- a/chrome/browser/chromeos/login/wallpaper_manager.cc
+++ b/chrome/browser/chromeos/login/wallpaper_manager.cc
@@ -20,7 +20,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/worker_pool.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/login/startup_utils.h"
@@ -393,7 +393,7 @@
   if (layout == ash::WALLPAPER_LAYOUT_CENTER) {
     // TODO(bshe): Generates cropped custom wallpaper for CENTER layout.
     if (file_util::PathExists(path))
-      file_util::Delete(path, false);
+      base::Delete(path, false);
     return;
   }
   scoped_refptr<base::RefCountedBytes> data;
@@ -490,25 +490,10 @@
 }
 
 void WallpaperManager::SetDefaultWallpaper() {
-  ash::DesktopBackgroundController* controller =
-      ash::Shell::GetInstance()->desktop_background_controller();
-  ash::WallpaperResolution resolution = controller->GetAppropriateResolution();
-  ash::WallpaperInfo info;
-  if (UserManager::Get()->IsLoggedInAsGuest()) {
-    info = (resolution == ash::WALLPAPER_RESOLUTION_LARGE) ?
-        ash::kGuestLargeWallpaper : ash::kGuestSmallWallpaper;
-  } else {
-    info = (resolution == ash::WALLPAPER_RESOLUTION_LARGE) ?
-        ash::kDefaultLargeWallpaper : ash::kDefaultSmallWallpaper;
-  }
-
-  // Prevents loading of the same wallpaper as the currently loading/loaded one.
-  if (controller->GetWallpaperIDR() == info.idr)
-    return;
-
   current_wallpaper_path_.clear();
-  loaded_wallpapers_++;
-  controller->SetDefaultWallpaper(info);
+  if (ash::Shell::GetInstance()->desktop_background_controller()->
+          SetDefaultWallpaper(UserManager::Get()->IsLoggedInAsGuest()))
+    loaded_wallpapers_++;
 }
 
 void WallpaperManager::SetInitialUserWallpaper(const std::string& username,
@@ -690,7 +675,7 @@
     for (base::FilePath current = files.Next(); !current.empty();
          current = files.Next()) {
       if (current != path)
-        file_util::Delete(current, false);
+        base::Delete(current, false);
     }
   }
 }
@@ -702,8 +687,8 @@
     base::FilePath path = *it;
     // Some users may still have legacy wallpapers with png extension. We need
     // to delete these wallpapers too.
-    if (!file_util::Delete(path, true) &&
-        !file_util::Delete(path.AddExtension(".png"), false)) {
+    if (!base::Delete(path, true) &&
+        !base::Delete(path.AddExtension(".png"), false)) {
       LOG(ERROR) << "Failed to remove user wallpaper at " << path.value();
     }
   }
@@ -866,14 +851,14 @@
       // Appends DUMMY to the file name of moved custom wallpaper. This way we
       // do not need to update WallpaperInfo for user.
       to_path = GetCustomWallpaperPath(kSmallWallpaperSubDir, email, "DUMMY");
-      file_util::Move(from_path, to_path);
+      base::Move(from_path, to_path);
     }
     from_path = GetWallpaperPathForUser(email, false);
     if (!file_util::PathExists(from_path))
       from_path = from_path.AddExtension(".png");
     if (file_util::PathExists(from_path)) {
       to_path = GetCustomWallpaperPath(kLargeWallpaperSubDir, email, "DUMMY");
-      file_util::Move(from_path, to_path);
+      base::Move(from_path, to_path);
     }
     from_path = GetOriginalWallpaperPathForUser(email);
     if (!file_util::PathExists(from_path))
@@ -881,7 +866,7 @@
     if (file_util::PathExists(from_path)) {
       to_path = GetCustomWallpaperPath(kOriginalWallpaperSubDir, email,
                                        "DUMMY");
-      file_util::Move(from_path, to_path);
+      base::Move(from_path, to_path);
     }
   }
 }
diff --git a/chrome/browser/chromeos/login/wallpaper_manager.h b/chrome/browser/chromeos/login/wallpaper_manager.h
index 882bcc4..62e00d7 100644
--- a/chrome/browser/chromeos/login/wallpaper_manager.h
+++ b/chrome/browser/chromeos/login/wallpaper_manager.h
@@ -12,8 +12,8 @@
 #include "base/memory/ref_counted_memory.h"
 #include "base/memory/weak_ptr.h"
 #include "base/threading/sequenced_worker_pool.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/chromeos/login/user.h"
 #include "chrome/browser/chromeos/login/user_image.h"
 #include "chrome/browser/chromeos/login/user_image_loader.h"
diff --git a/chrome/browser/chromeos/login/wallpaper_manager_browsertest.cc b/chrome/browser/chromeos/login/wallpaper_manager_browsertest.cc
index 0bb93e6..77b3be6 100644
--- a/chrome/browser/chromeos/login/wallpaper_manager_browsertest.cc
+++ b/chrome/browser/chromeos/login/wallpaper_manager_browsertest.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/chromeos/login/wallpaper_manager.h"
 
+#include "ash/ash_resources/grit/ash_wallpaper_resources.h"
 #include "ash/desktop_background/desktop_background_controller.h"
 #include "ash/desktop_background/desktop_background_controller_observer.h"
 #include "ash/display/display_manager.h"
@@ -13,7 +14,7 @@
 #include "base/file_util.h"
 #include "base/message_loop.h"
 #include "base/strings/string_number_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/chromeos/cros/cros_in_process_browser_test.h"
 #include "chrome/browser/chromeos/login/user.h"
@@ -31,19 +32,13 @@
 
 namespace {
 
-#if defined(GOOGLE_CHROME_BUILD)
-int kExpectedSmallWallpaperWidth = ash::kSmallWallpaperMaxWidth;
-int kExpectedSmallWallpaperHeight = ash::kSmallWallpaperMaxHeight;
-int kExpectedLargeWallpaperWidth = ash::kLargeWallpaperMaxWidth;
-int kExpectedLargeWallpaperHeight = ash::kLargeWallpaperMaxHeight;
-#else
-// The defualt wallpaper for non official build is a gradient wallpaper which
-// stretches to fit screen.
-int kExpectedSmallWallpaperWidth = 256;
-int kExpectedSmallWallpaperHeight = ash::kSmallWallpaperMaxHeight;
-int kExpectedLargeWallpaperWidth = 256;
-int kExpectedLargeWallpaperHeight = ash::kLargeWallpaperMaxHeight;
-#endif
+const int kLargeWallpaperResourceId = IDR_AURA_WALLPAPERS_5_GRADIENT5_LARGE;
+const int kSmallWallpaperResourceId = IDR_AURA_WALLPAPERS_5_GRADIENT5_SMALL;
+
+int kLargeWallpaperWidth = 256;
+int kLargeWallpaperHeight = ash::kLargeWallpaperMaxHeight;
+int kSmallWallpaperWidth = 256;
+int kSmallWallpaperHeight = ash::kSmallWallpaperMaxHeight;
 
 const char kTestUser1[] = "test@domain.com";
 
@@ -95,8 +90,8 @@
  protected:
   // Return custom wallpaper path. Create directory if not exist.
   base::FilePath GetCustomWallpaperPath(const char* sub_dir,
-                                  const std::string& email,
-                                  const std::string& id) {
+                                        const std::string& email,
+                                        const std::string& id) {
     base::FilePath wallpaper_path =
         WallpaperManager::Get()->GetCustomWallpaperPath(sub_dir, email, id);
     if (!file_util::DirectoryExists(wallpaper_path.DirName()))
@@ -135,57 +130,8 @@
   DISALLOW_COPY_AND_ASSIGN(WallpaperManagerBrowserTest);
 };
 
-// The large resolution wallpaper should be loaded when a large external screen
-// is hooked up. If the external screen is smaller than small wallpaper
-// resolution, do not load large resolution wallpaper.
-IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,
-                       LoadLargeWallpaperForLargeExternalScreen) {
-  LogIn(kTestUser1);
-  WaitAsyncWallpaperLoad();
-  gfx::ImageSkia wallpaper = controller_->GetWallpaper();
-
-  // Display is initialized to 800x600. The small resolution default wallpaper
-  // is expected.
-  EXPECT_EQ(kExpectedSmallWallpaperWidth, wallpaper.width());
-  EXPECT_EQ(kExpectedSmallWallpaperHeight, wallpaper.height());
-
-  // Hook up another 800x600 display.
-  UpdateDisplay("800x600,800x600");
-#if !defined(GOOGLE_CHROME_BUILD)
-  // wallpaper.width() < 800, expect to reload wallpaper.
-  WaitAsyncWallpaperLoad();
-#endif
-  // The small resolution wallpaper is expected.
-  EXPECT_EQ(kExpectedSmallWallpaperWidth, wallpaper.width());
-  EXPECT_EQ(kExpectedSmallWallpaperHeight, wallpaper.height());
-
-  // Detach the secondary display.
-  UpdateDisplay("800x600");
-  // Hook up a 2000x2000 display. The large resolution default wallpaper should
-  // be loaded.
-  UpdateDisplay("800x600,2000x2000");
-  WaitAsyncWallpaperLoad();
-  wallpaper = controller_->GetWallpaper();
-
-  // The large resolution default wallpaper is expected.
-  EXPECT_EQ(kExpectedLargeWallpaperWidth, wallpaper.width());
-  EXPECT_EQ(kExpectedLargeWallpaperHeight, wallpaper.height());
-
-  // Detach the secondary display.
-  UpdateDisplay("800x600");
-  // Hook up the 2000x2000 display again. The large resolution default wallpaper
-  // should persist. Test for crbug/165788.
-  UpdateDisplay("800x600,2000x2000");
-  WaitAsyncWallpaperLoad();
-  wallpaper = controller_->GetWallpaper();
-
-  // The large resolution default wallpaper is expected.
-  EXPECT_EQ(kExpectedLargeWallpaperWidth, wallpaper.width());
-  EXPECT_EQ(kExpectedLargeWallpaperHeight, wallpaper.height());
-}
-
-// This test is similar to LoadLargeWallpaperForExternalScreen test. Instead of
-// testing default wallpaper, it tests custom wallpaper.
+// Tests that the appropriate custom wallpaper (large vs. small) is loaded
+// depending on the desktop resolution.
 IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,
                        LoadCustomLargeWallpaperForLargeExternalScreen) {
   WallpaperManager* wallpaper_manager = WallpaperManager::Get();
@@ -206,10 +152,10 @@
   // wallpaper paths.
   SaveUserWallpaperData(kTestUser1,
                         small_wallpaper_path,
-                        ash::kDefaultSmallWallpaper.idr);
+                        kSmallWallpaperResourceId);
   SaveUserWallpaperData(kTestUser1,
                         large_wallpaper_path,
-                        ash::kDefaultLargeWallpaper.idr);
+                        kLargeWallpaperResourceId);
 
   // Saves wallpaper info to local state for user |kTestUser1|.
   WallpaperInfo info = {
@@ -227,18 +173,15 @@
 
   // Display is initialized to 800x600. The small resolution custom wallpaper is
   // expected.
-  EXPECT_EQ(kExpectedSmallWallpaperWidth, wallpaper.width());
-  EXPECT_EQ(kExpectedSmallWallpaperHeight, wallpaper.height());
+  EXPECT_EQ(kSmallWallpaperWidth, wallpaper.width());
+  EXPECT_EQ(kSmallWallpaperHeight, wallpaper.height());
 
   // Hook up another 800x600 display.
   UpdateDisplay("800x600,800x600");
-#if !defined(GOOGLE_CHROME_BUILD)
-  // wallpaper.width() < 800, expect to reload wallpaper.
   WaitAsyncWallpaperLoad();
-#endif
   // The small resolution custom wallpaper is expected.
-  EXPECT_EQ(kExpectedSmallWallpaperWidth, wallpaper.width());
-  EXPECT_EQ(kExpectedSmallWallpaperHeight, wallpaper.height());
+  EXPECT_EQ(kSmallWallpaperWidth, wallpaper.width());
+  EXPECT_EQ(kSmallWallpaperHeight, wallpaper.height());
 
   // Detach the secondary display.
   UpdateDisplay("800x600");
@@ -249,8 +192,8 @@
   wallpaper = controller_->GetWallpaper();
 
   // The large resolution custom wallpaper is expected.
-  EXPECT_EQ(kExpectedLargeWallpaperWidth, wallpaper.width());
-  EXPECT_EQ(kExpectedLargeWallpaperHeight, wallpaper.height());
+  EXPECT_EQ(kLargeWallpaperWidth, wallpaper.width());
+  EXPECT_EQ(kLargeWallpaperHeight, wallpaper.height());
 
   // Detach the secondary display.
   UpdateDisplay("800x600");
@@ -261,8 +204,8 @@
   wallpaper = controller_->GetWallpaper();
 
   // The large resolution custom wallpaper is expected.
-  EXPECT_EQ(kExpectedLargeWallpaperWidth, wallpaper.width());
-  EXPECT_EQ(kExpectedLargeWallpaperHeight, wallpaper.height());
+  EXPECT_EQ(kLargeWallpaperWidth, wallpaper.width());
+  EXPECT_EQ(kLargeWallpaperHeight, wallpaper.height());
 }
 
 // If chrome tries to reload the same wallpaper twice, the latter request should
@@ -293,7 +236,7 @@
       id);
   SaveUserWallpaperData(kTestUser1,
                         small_wallpaper_path,
-                        ash::kDefaultSmallWallpaper.idr);
+                        kSmallWallpaperResourceId);
 
   // Saves wallpaper info to local state for user |kTestUser1|.
   WallpaperInfo info = {
@@ -328,7 +271,7 @@
       GetOriginalWallpaperPathForUser(kTestUser1);
   SaveUserWallpaperData(kTestUser1,
                         old_wallpaper_path,
-                        ash::kDefaultSmallWallpaper.idr);
+                        kSmallWallpaperResourceId);
   // Saves wallpaper info to local state for user |kTestUser1|.
   WallpaperInfo info = {
       "DUMMY",
@@ -463,4 +406,4 @@
   // can not handle pre migrated user profile (M21 profile or older).
 }
 
-}  // namepace chromeos
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/webui_login_display.h b/chrome/browser/chromeos/login/webui_login_display.h
index 04a880b..de2f8cd 100644
--- a/chrome/browser/chromeos/login/webui_login_display.h
+++ b/chrome/browser/chromeos/login/webui_login_display.h
@@ -10,7 +10,7 @@
 
 #include "ash/wm/user_activity_observer.h"
 #include "base/compiler_specific.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/chromeos/login/login_display.h"
 #include "chrome/browser/chromeos/login/user.h"
 #include "chrome/browser/ui/webui/chromeos/login/native_window_delegate.h"
diff --git a/chrome/browser/chromeos/login/webui_screen_locker.h b/chrome/browser/chromeos/login/webui_screen_locker.h
index 888f422..8c52c81 100644
--- a/chrome/browser/chromeos/login/webui_screen_locker.h
+++ b/chrome/browser/chromeos/login/webui_screen_locker.h
@@ -11,7 +11,7 @@
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/chromeos/login/lock_window.h"
 #include "chrome/browser/chromeos/login/login_display.h"
 #include "chrome/browser/chromeos/login/screen_locker_delegate.h"
diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc
index bd83578..a8adf9c 100644
--- a/chrome/browser/chromeos/login/wizard_controller.cc
+++ b/chrome/browser/chromeos/login/wizard_controller.cc
@@ -47,8 +47,6 @@
 #include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
 #include "chrome/browser/chromeos/settings/cros_settings_names.h"
-#include "chrome/browser/chromeos/system/statistics_provider.h"
-#include "chrome/browser/chromeos/ui/focus_ring_controller.h"
 #include "chrome/browser/policy/browser_policy_connector.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
@@ -187,18 +185,9 @@
   screen_parameters_ = screen_parameters.Pass();
 
   bool oobe_complete = StartupUtils::IsOobeCompleted();
-  if (!oobe_complete || first_screen_name == kOutOfBoxScreenName) {
+  if (!oobe_complete || first_screen_name == kOutOfBoxScreenName)
     is_out_of_box_ = true;
 
-    bool keyboard_driven_oobe = false;
-    system::StatisticsProvider::GetInstance()->GetMachineFlag(
-        chromeos::kOemKeyboardDrivenOobeKey, &keyboard_driven_oobe);
-    if (keyboard_driven_oobe) {
-      focus_ring_controller_.reset(new FocusRingController);
-      focus_ring_controller_->SetVisible(true);
-    }
-  }
-
   AdvanceToScreen(first_screen_name);
   content::NotificationService::current()->Notify(
       chrome::NOTIFICATION_WIZARD_FIRST_SCREEN_SHOWN,
diff --git a/chrome/browser/chromeos/login/wizard_controller.h b/chrome/browser/chromeos/login/wizard_controller.h
index 4b77900..192ef93 100644
--- a/chrome/browser/chromeos/login/wizard_controller.h
+++ b/chrome/browser/chromeos/login/wizard_controller.h
@@ -11,8 +11,8 @@
 #include "base/gtest_prod_util.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/observer_list.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/chromeos/login/screens/screen_observer.h"
 #include "chrome/browser/chromeos/login/screens/wizard_screen.h"
 #include "googleurl/src/gurl.h"
@@ -29,7 +29,6 @@
 class EnrollmentScreen;
 class ErrorScreen;
 class EulaScreen;
-class FocusRingController;
 class KioskAutolaunchScreen;
 class KioskEnableScreen;
 class LocallyManagedUserCreationScreen;
@@ -309,10 +308,6 @@
   // a previous screen instead of proceeding with usual flow.
   bool user_image_screen_return_to_previous_hack_;
 
-  // A focus ring controller to draw focus ring around view for keyboard
-  // driven oobe.
-  scoped_ptr<FocusRingController> focus_ring_controller_;
-
   FRIEND_TEST_ALL_PREFIXES(EnrollmentScreenTest, TestCancel);
   FRIEND_TEST_ALL_PREFIXES(WizardControllerFlowTest, Accelerators);
   friend class WizardControllerFlowTest;
diff --git a/chrome/browser/chromeos/memory/oom_priority_manager.cc b/chrome/browser/chromeos/memory/oom_priority_manager.cc
index 4fda45b..85b6217 100644
--- a/chrome/browser/chromeos/memory/oom_priority_manager.cc
+++ b/chrome/browser/chromeos/memory/oom_priority_manager.cc
@@ -21,7 +21,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/lock.h"
 #include "base/threading/thread.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "build/build_config.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_process_platform_part_chromeos.h"
diff --git a/chrome/browser/chromeos/memory/oom_priority_manager.h b/chrome/browser/chromeos/memory/oom_priority_manager.h
index 56f8668..f666db7 100644
--- a/chrome/browser/chromeos/memory/oom_priority_manager.h
+++ b/chrome/browser/chromeos/memory/oom_priority_manager.h
@@ -14,8 +14,8 @@
 #include "base/process.h"
 #include "base/strings/string16.h"
 #include "base/synchronization/lock.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "chromeos/memory/low_memory_listener_delegate.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
diff --git a/chrome/browser/chromeos/memory/oom_priority_manager_unittest.cc b/chrome/browser/chromeos/memory/oom_priority_manager_unittest.cc
index 88ebe32..cf5fa16 100644
--- a/chrome/browser/chromeos/memory/oom_priority_manager_unittest.cc
+++ b/chrome/browser/chromeos/memory/oom_priority_manager_unittest.cc
@@ -7,7 +7,7 @@
 
 #include "base/logging.h"
 #include "base/strings/string16.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/chromeos/memory/oom_priority_manager.h"
 #include "chrome/common/url_constants.h"
 #include "googleurl/src/gurl.h"
diff --git a/chrome/browser/chromeos/mobile/mobile_activator.cc b/chrome/browser/chromeos/mobile/mobile_activator.cc
index b4e8022..2628fb1 100644
--- a/chrome/browser/chromeos/mobile/mobile_activator.cc
+++ b/chrome/browser/chromeos/mobile/mobile_activator.cc
@@ -21,7 +21,7 @@
 #include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/cros/cros_library.h"
diff --git a/chrome/browser/chromeos/mobile_config.h b/chrome/browser/chromeos/mobile_config.h
index d44b7bd..014231f 100644
--- a/chrome/browser/chromeos/mobile_config.h
+++ b/chrome/browser/chromeos/mobile_config.h
@@ -12,7 +12,7 @@
 #include "base/gtest_prod_util.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/singleton.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/chromeos/customization_document.h"
 
 namespace base {
diff --git a/chrome/browser/chromeos/mobile_config_unittest.cc b/chrome/browser/chromeos/mobile_config_unittest.cc
index 95aece9..abd3992 100644
--- a/chrome/browser/chromeos/mobile_config_unittest.cc
+++ b/chrome/browser/chromeos/mobile_config_unittest.cc
@@ -4,7 +4,7 @@
 
 #include "chrome/browser/chromeos/mobile_config.h"
 
-#include "base/time.h"
+#include "base/time/time.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
diff --git a/chrome/browser/chromeos/net/network_portal_detector_impl.h b/chrome/browser/chromeos/net/network_portal_detector_impl.h
index bbc40f9..b523f65 100644
--- a/chrome/browser/chromeos/net/network_portal_detector_impl.h
+++ b/chrome/browser/chromeos/net/network_portal_detector_impl.h
@@ -16,7 +16,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "base/threading/non_thread_safe.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/captive_portal/captive_portal_detector.h"
 #include "chrome/browser/chromeos/net/network_portal_detector.h"
 #include "chromeos/network/network_state_handler_observer.h"
diff --git a/chrome/browser/chromeos/net/network_portal_detector_impl_unittest.cc b/chrome/browser/chromeos/net/network_portal_detector_impl_unittest.cc
index 6b497dd..16994e8 100644
--- a/chrome/browser/chromeos/net/network_portal_detector_impl_unittest.cc
+++ b/chrome/browser/chromeos/net/network_portal_detector_impl_unittest.cc
@@ -190,23 +190,24 @@
     ShillServiceClient::TestInterface* service_test =
         DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
     service_test->ClearServices();
+    const bool add_to_visible = true;
     const bool add_to_watchlist = true;
     service_test->AddService(kStubEthernet,
                              kStubEthernet,
                              flimflam::kTypeEthernet, flimflam::kStateIdle,
-                             add_to_watchlist);
+                             add_to_visible, add_to_watchlist);
     service_test->AddService(kStubWireless1,
                              kStubWireless1,
                              flimflam::kTypeWifi, flimflam::kStateIdle,
-                             add_to_watchlist);
+                             add_to_visible, add_to_watchlist);
     service_test->AddService(kStubWireless2,
                              kStubWireless2,
                              flimflam::kTypeWifi, flimflam::kStateIdle,
-                             add_to_watchlist);
+                             add_to_visible, add_to_watchlist);
     service_test->AddService(kStubCellular,
                              kStubCellular,
                              flimflam::kTypeCellular, flimflam::kStateIdle,
-                             add_to_watchlist);
+                             add_to_visible, add_to_watchlist);
   }
 
   void SetupNetworkHandler() {
diff --git a/chrome/browser/chromeos/options/network_connect.cc b/chrome/browser/chromeos/options/network_connect.cc
index 8ebe55c..4daccc2 100644
--- a/chrome/browser/chromeos/options/network_connect.cc
+++ b/chrome/browser/chromeos/options/network_connect.cc
@@ -10,7 +10,7 @@
 #include "ash/system/chromeos/network/network_observer.h"
 #include "ash/system/tray/system_tray_notifier.h"
 #include "base/command_line.h"
-#include "base/stringprintf.h"
+#include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/chromeos/cros/cros_library.h"
 #include "chrome/browser/chromeos/cros/network_library.h"
diff --git a/chrome/browser/chromeos/options/vpn_config_view.cc b/chrome/browser/chromeos/options/vpn_config_view.cc
index 0894749..f35536e 100644
--- a/chrome/browser/chromeos/options/vpn_config_view.cc
+++ b/chrome/browser/chromeos/options/vpn_config_view.cc
@@ -313,7 +313,7 @@
         config_data.group_name = GetGroupName();
         break;
       case PROVIDER_TYPE_L2TP_IPSEC_USER_CERT: {
-        config_data.server_ca_cert_nss_nickname = GetServerCACertNssNickname();
+        config_data.server_ca_cert_pem = GetServerCACertPEM();
         config_data.client_cert_pkcs11_id = GetUserCertID();
         config_data.username = GetUsername();
         config_data.user_passphrase = GetUserPassphrase();
@@ -321,7 +321,7 @@
         break;
       }
       case PROVIDER_TYPE_OPEN_VPN:
-        config_data.server_ca_cert_nss_nickname = GetServerCACertNssNickname();
+        config_data.server_ca_cert_pem = GetServerCACertPEM();
         config_data.client_cert_pkcs11_id = GetUserCertID();
         config_data.username = GetUsername();
         config_data.user_passphrase = GetUserPassphrase();
@@ -421,7 +421,7 @@
   return GetTextFromField(otp_textfield_, true);
 }
 
-const std::string VPNConfigView::GetServerCACertNssNickname() const {
+const std::string VPNConfigView::GetServerCACertPEM() const {
   int index = server_ca_cert_combobox_ ?
       server_ca_cert_combobox_->selected_index() : 0;
   if (index == 0) {
@@ -429,7 +429,7 @@
     return std::string();
   } else {
     int cert_index = index - 1;
-    return CertLibrary::Get()->GetCertNicknameAt(
+    return CertLibrary::Get()->GetCertPEMAt(
         CertLibrary::CERT_TYPE_SERVER_CA, cert_index);
   }
 }
@@ -453,14 +453,20 @@
   if (vpn) {
     ProviderType type = vpn->provider_type();
     std::string type_dict_name = ProviderTypeToONCDictKey(type);
-    ParseVPNUIProperty(&ca_cert_ui_data_, vpn, type_dict_name,
-                       onc::vpn::kServerCARef);
-    ParseVPNUIProperty(&psk_passphrase_ui_data_, vpn, type_dict_name,
-                       onc::vpn::kPSK);
+
+    if (type == PROVIDER_TYPE_L2TP_IPSEC_PSK) {
+      ParseVPNUIProperty(&ca_cert_ui_data_, vpn, type_dict_name,
+                         onc::ipsec::kServerCARef);
+      ParseVPNUIProperty(&psk_passphrase_ui_data_, vpn, type_dict_name,
+                         onc::ipsec::kPSK);
+      ParseVPNUIProperty(&group_name_ui_data_, vpn, type_dict_name,
+                         onc::ipsec::kGroup);
+    } else { // OpenVPN
+      ParseVPNUIProperty(&ca_cert_ui_data_, vpn, type_dict_name,
+                         onc::openvpn::kServerCARef);
+    }
     ParseVPNUIProperty(&user_cert_ui_data_, vpn, type_dict_name,
                        onc::vpn::kClientCertRef);
-    ParseVPNUIProperty(&group_name_ui_data_, vpn, type_dict_name,
-                       onc::vpn::kGroup);
 
     const std::string credentials_dict_name(
         type == PROVIDER_TYPE_L2TP_IPSEC_PSK ?
@@ -718,10 +724,10 @@
   if (server_ca_cert_combobox_) {
     server_ca_cert_combobox_->ModelChanged();
     if (enable_server_ca_cert_ &&
-        (vpn && !vpn->ca_cert_nss().empty())) {
+        (vpn && !vpn->ca_cert_pem().empty())) {
       // Select the current server CA certificate in the combobox.
-      int cert_index = CertLibrary::Get()->GetCertIndexByNickname(
-          CertLibrary::CERT_TYPE_SERVER_CA, vpn->ca_cert_nss());
+      int cert_index = CertLibrary::Get()->GetCertIndexByPEM(
+          CertLibrary::CERT_TYPE_SERVER_CA, vpn->ca_cert_pem());
       if (cert_index >= 0) {
         // Skip item for "Default"
         server_ca_cert_combobox_->SetSelectedIndex(1 + cert_index);
diff --git a/chrome/browser/chromeos/options/vpn_config_view.h b/chrome/browser/chromeos/options/vpn_config_view.h
index 4b437e8..cb5f7ce 100644
--- a/chrome/browser/chromeos/options/vpn_config_view.h
+++ b/chrome/browser/chromeos/options/vpn_config_view.h
@@ -106,7 +106,7 @@
   const std::string GetUserPassphrase() const;
   const std::string GetOTP() const;
   const std::string GetGroupName() const;
-  const std::string GetServerCACertNssNickname() const;
+  const std::string GetServerCACertPEM() const;
   const std::string GetUserCertID() const;
   bool GetSaveCredentials() const;
 
diff --git a/chrome/browser/chromeos/options/wifi_config_view.cc b/chrome/browser/chromeos/options/wifi_config_view.cc
index cd72843..4e7257d 100644
--- a/chrome/browser/chromeos/options/wifi_config_view.cc
+++ b/chrome/browser/chromeos/options/wifi_config_view.cc
@@ -681,7 +681,7 @@
       chromeos::NetworkLibrary::EAPConfigData config_data;
       config_data.method = GetEapMethod();
       config_data.auth = GetEapPhase2Auth();
-      config_data.server_ca_cert_nss_nickname = GetEapServerCaCertNssNickname();
+      config_data.server_ca_cert_pem = GetEapServerCaCertPEM();
       config_data.use_system_cas = GetEapUseSystemCas();
       config_data.client_cert_pkcs11_id = GetEapClientCertPkcs11Id();
       config_data.identity = GetEapIdentity();
@@ -708,7 +708,7 @@
       DCHECK(method != EAP_METHOD_UNKNOWN);
       wifi->SetEAPMethod(method);
       wifi->SetEAPPhase2Auth(GetEapPhase2Auth());
-      wifi->SetEAPServerCaCertNssNickname(GetEapServerCaCertNssNickname());
+      wifi->SetEAPServerCaCertPEM(GetEapServerCaCertPEM());
       wifi->SetEAPUseSystemCAs(GetEapUseSystemCas());
       wifi->SetEAPClientCertPkcs11Id(GetEapClientCertPkcs11Id());
       wifi->SetEAPIdentity(GetEapIdentity());
@@ -799,7 +799,7 @@
   }
 }
 
-std::string WifiConfigView::GetEapServerCaCertNssNickname() const {
+std::string WifiConfigView::GetEapServerCaCertPEM() const {
   DCHECK(server_ca_cert_combobox_);
   int index = server_ca_cert_combobox_->selected_index();
   if (index == 0) {
@@ -810,7 +810,7 @@
     return std::string();
   } else {
     int cert_index = index - 1;
-    return CertLibrary::Get()->GetCertNicknameAt(
+    return CertLibrary::Get()->GetCertPEMAt(
         CertLibrary::CERT_TYPE_SERVER_CA, cert_index);
   }
 }
@@ -1180,9 +1180,9 @@
 
     // Server CA certificate.
     if (CaCertActive()) {
-      const std::string& nss_nickname =
-          (wifi ? wifi->eap_server_ca_cert_nss_nickname() : std::string());
-      if (nss_nickname.empty()) {
+      const std::string& ca_cert_pem =
+          (wifi ? wifi->eap_server_ca_cert_pem() : std::string());
+      if (ca_cert_pem.empty()) {
         if (wifi->eap_use_system_cas()) {
           // "Default".
           server_ca_cert_combobox_->SetSelectedIndex(0);
@@ -1193,8 +1193,8 @@
         }
       } else {
         // Select the certificate if available.
-        int cert_index = CertLibrary::Get()->GetCertIndexByNickname(
-            CertLibrary::CERT_TYPE_SERVER_CA, nss_nickname);
+        int cert_index = CertLibrary::Get()->GetCertIndexByPEM(
+            CertLibrary::CERT_TYPE_SERVER_CA, ca_cert_pem);
         if (cert_index >= 0) {
           // Skip item for "Default".
           server_ca_cert_combobox_->SetSelectedIndex(1 + cert_index);
diff --git a/chrome/browser/chromeos/options/wifi_config_view.h b/chrome/browser/chromeos/options/wifi_config_view.h
index 6e05033..574072d 100644
--- a/chrome/browser/chromeos/options/wifi_config_view.h
+++ b/chrome/browser/chromeos/options/wifi_config_view.h
@@ -99,7 +99,7 @@
   // Get various 802.1X EAP values from the widgets.
   EAPMethod GetEapMethod() const;
   EAPPhase2Auth GetEapPhase2Auth() const;
-  std::string GetEapServerCaCertNssNickname() const;
+  std::string GetEapServerCaCertPEM() const;
   bool GetEapUseSystemCas() const;
   std::string GetEapClientCertPkcs11Id() const;
   std::string GetEapIdentity() const;
diff --git a/chrome/browser/chromeos/policy/app_pack_updater.cc b/chrome/browser/chromeos/policy/app_pack_updater.cc
index 74bb18d..628150f 100644
--- a/chrome/browser/chromeos/policy/app_pack_updater.cc
+++ b/chrome/browser/chromeos/policy/app_pack_updater.cc
@@ -261,7 +261,7 @@
 
     if (info.IsDirectory() || file_util::IsLink(info.GetName())) {
       LOG(ERROR) << "Erasing bad file in AppPack directory: " << basename;
-      file_util::Delete(path, true /* recursive */);
+      base::Delete(path, true /* recursive */);
       continue;
     }
 
@@ -294,7 +294,7 @@
 
     if (id.empty() || version.empty()) {
       LOG(ERROR) << "Invalid file in AppPack cache, erasing: " << basename;
-      file_util::Delete(path, true /* recursive */);
+      base::Delete(path, true /* recursive */);
       continue;
     }
 
@@ -313,10 +313,10 @@
       DCHECK(vEntry.IsValid());
       DCHECK(vCurrent.IsValid());
       if (vEntry.CompareTo(vCurrent) < 0) {
-        file_util::Delete(base::FilePath(entry.path), true /* recursive */);
+        base::Delete(base::FilePath(entry.path), true /* recursive */);
         entry.path = path.value();
       } else {
-        file_util::Delete(path, true /* recursive */);
+        base::Delete(path, true /* recursive */);
       }
       continue;
     }
@@ -470,7 +470,7 @@
   if (!version_validator.IsValid()) {
     LOG(ERROR) << "AppPack downloaded extension " << id << " but got bad "
                << "version: " << version;
-    file_util::Delete(path, true /* recursive */);
+    base::Delete(path, true /* recursive */);
     return;
   }
 
@@ -481,7 +481,7 @@
   if (file_util::PathExists(cached_crx_path)) {
     LOG(WARNING) << "AppPack downloaded a crx whose filename will overwrite "
                  << "an existing cached crx.";
-    file_util::Delete(cached_crx_path, true /* recursive */);
+    base::Delete(cached_crx_path, true /* recursive */);
   }
 
   if (!file_util::DirectoryExists(cache_dir)) {
@@ -489,15 +489,15 @@
                << cache_dir.value();
     if (!file_util::CreateDirectory(cache_dir)) {
       LOG(ERROR) << "Failed to create the AppPack cache dir!";
-      file_util::Delete(path, true /* recursive */);
+      base::Delete(path, true /* recursive */);
       return;
     }
   }
 
-  if (!file_util::Move(path, cached_crx_path)) {
+  if (!base::Move(path, cached_crx_path)) {
     LOG(ERROR) << "Failed to move AppPack crx from " << path.value()
                << " to " << cached_crx_path.value();
-    file_util::Delete(path, true /* recursive */);
+    base::Delete(path, true /* recursive */);
     return;
   }
 
@@ -539,7 +539,7 @@
       // The file will be downloaded again on the next restart.
       BrowserThread::PostTask(
           BrowserThread::FILE, FROM_HERE,
-          base::Bind(base::IgnoreResult(file_util::Delete), path, true));
+          base::Bind(base::IgnoreResult(base::Delete), path, true));
 
       // Don't try to DownloadMissingExtensions() from here,
       // since it can cause a fail/retry loop.
diff --git a/chrome/browser/chromeos/policy/auto_enrollment_client.h b/chrome/browser/chromeos/policy/auto_enrollment_client.h
index 2e8b424..95c22ef 100644
--- a/chrome/browser/chromeos/policy/auto_enrollment_client.h
+++ b/chrome/browser/chromeos/policy/auto_enrollment_client.h
@@ -11,7 +11,7 @@
 #include "base/callback.h"
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/policy/cloud/cloud_policy_constants.h"
 #include "third_party/protobuf/src/google/protobuf/repeated_field.h"
 
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 ebc0442..e12200f 100644
--- a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc
+++ b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc
@@ -138,10 +138,12 @@
   std::string requisition;
   const PrefService::Preference* pref = local_state_->FindPreference(
       prefs::kDeviceEnrollmentRequisition);
-  if (pref->IsDefaultValue())
-    requisition = GetMachineStatistic(chromeos::kOemDeviceRequisitionKey);
-  else
+  if (pref->IsDefaultValue()) {
+    requisition =
+        GetMachineStatistic(chromeos::system::kOemDeviceRequisitionKey);
+  } else {
     pref->GetValue()->GetAsString(&requisition);
+  }
 
   return requisition;
 }
@@ -165,14 +167,15 @@
   if (local_state_->HasPrefPath(prefs::kDeviceEnrollmentAutoStart))
     return local_state_->GetBoolean(prefs::kDeviceEnrollmentAutoStart);
 
-  return GetMachineFlag(chromeos::kOemIsEnterpriseManagedKey, false);
+  return GetMachineFlag(chromeos::system::kOemIsEnterpriseManagedKey, false);
 }
 
 bool DeviceCloudPolicyManagerChromeOS::CanExitEnrollment() const {
   if (local_state_->HasPrefPath(prefs::kDeviceEnrollmentCanExit))
     return local_state_->GetBoolean(prefs::kDeviceEnrollmentCanExit);
 
-  return GetMachineFlag(chromeos::kOemCanExitEnterpriseEnrollmentKey, true);
+  return GetMachineFlag(chromeos::system::kOemCanExitEnterpriseEnrollmentKey,
+                        true);
 }
 
 void DeviceCloudPolicyManagerChromeOS::Shutdown() {
@@ -220,6 +223,11 @@
   return GetMachineStatistic(kMachineInfoSystemHwqual);
 }
 
+std::string DeviceCloudPolicyManagerChromeOS::GetRobotAccountId() {
+  const enterprise_management::PolicyData* policy = device_store_->policy();
+  return policy ? policy->service_account_identity() : std::string();
+}
+
 scoped_ptr<CloudPolicyClient> DeviceCloudPolicyManagerChromeOS::CreateClient() {
   return make_scoped_ptr(
       new CloudPolicyClient(GetMachineID(), GetMachineModel(),
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 005028d..e10a54a 100644
--- a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h
+++ b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h
@@ -88,6 +88,11 @@
   // Returns the machine model, or an empty string if not available.
   static std::string GetMachineModel();
 
+  // Returns the robot 'email address' associated with the device robot
+  // account (sometimes called a service account) associated with this device
+  // during enterprise enrollment.
+  std::string GetRobotAccountId();
+
  private:
   // Creates a new CloudPolicyClient.
   scoped_ptr<CloudPolicyClient> CreateClient();
diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos_unittest.cc b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos_unittest.cc
index 22b47d6..2c7c0be 100644
--- a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos_unittest.cc
+++ b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos_unittest.cc
@@ -28,6 +28,7 @@
 #include "chromeos/cryptohome/mock_cryptohome_library.h"
 #include "chromeos/dbus/cryptohome_client.h"
 #include "chromeos/dbus/dbus_client_implementation_type.h"
+#include "google_apis/gaia/gaia_oauth_client.h"
 #include "net/url_request/test_url_fetcher_factory.h"
 #include "net/url_request/url_request_test_util.h"
 #include "policy/policy_constants.h"
@@ -158,6 +159,9 @@
 
   manager_.Shutdown();
   EXPECT_TRUE(manager_.policies().Equals(bundle));
+
+  EXPECT_EQ(manager_.GetRobotAccountId(),
+            PolicyBuilder::kFakeServiceAccountIdentity);
 }
 
 TEST_F(DeviceCloudPolicyManagerChromeOSTest, ConsumerDevice) {
@@ -326,7 +330,8 @@
     // We return a successful OAuth response via a TestURLFetcher to trigger the
     // happy path for these classes so that enrollment can continue.
     if (robot_auth_fetch_status_ == DM_STATUS_SUCCESS) {
-      net::TestURLFetcher* url_fetcher = url_fetcher_factory_.GetFetcherByID(0);
+      net::TestURLFetcher* url_fetcher = url_fetcher_factory_.GetFetcherByID(
+          gaia::GaiaOAuthClient::kUrlFetcherId);
       ASSERT_TRUE(url_fetcher);
       url_fetcher->SetMaxRetriesOn5xx(0);
       url_fetcher->set_status(net::URLRequestStatus());
@@ -484,5 +489,5 @@
             status_.store_status());
 }
 
-}  // namespace test
+}  // namespace
 }  // namespace policy
diff --git a/chrome/browser/chromeos/policy/device_local_account_browsertest.cc b/chrome/browser/chromeos/policy/device_local_account_browsertest.cc
index 9a13741..ac604d6 100644
--- a/chrome/browser/chromeos/policy/device_local_account_browsertest.cc
+++ b/chrome/browser/chromeos/policy/device_local_account_browsertest.cc
@@ -8,30 +8,28 @@
 #include "base/basictypes.h"
 #include "base/bind.h"
 #include "base/command_line.h"
-#include "base/file_util.h"
-#include "base/files/file_path.h"
-#include "base/files/scoped_temp_dir.h"
+#include "base/memory/scoped_ptr.h"
 #include "base/message_loop.h"
-#include "base/path_service.h"
 #include "base/run_loop.h"
-#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/login/existing_user_controller.h"
 #include "chrome/browser/chromeos/login/login_display_host.h"
 #include "chrome/browser/chromeos/login/login_display_host_impl.h"
+#include "chrome/browser/chromeos/login/mock_login_status_consumer.h"
+#include "chrome/browser/chromeos/login/screens/wizard_screen.h"
 #include "chrome/browser/chromeos/login/user.h"
 #include "chrome/browser/chromeos/login/user_manager.h"
+#include "chrome/browser/chromeos/login/wizard_controller.h"
 #include "chrome/browser/chromeos/policy/device_local_account.h"
 #include "chrome/browser/chromeos/policy/device_policy_builder.h"
-#include "chrome/browser/chromeos/policy/enterprise_install_attributes.h"
+#include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h"
 #include "chrome/browser/lifetime/application_lifetime.h"
 #include "chrome/browser/policy/cloud/cloud_policy_constants.h"
 #include "chrome/browser/policy/cloud/policy_builder.h"
 #include "chrome/browser/policy/policy_service.h"
 #include "chrome/browser/policy/proto/chromeos/chrome_device_policy.pb.h"
-#include "chrome/browser/policy/proto/chromeos/install_attributes.pb.h"
 #include "chrome/browser/policy/test/local_policy_test_server.h"
 #include "chrome/browser/prefs/session_startup_pref.h"
 #include "chrome/browser/ui/browser.h"
@@ -40,24 +38,23 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "chrome/common/chrome_switches.h"
-#include "chrome/test/base/in_process_browser_test.h"
-#include "chromeos/chromeos_paths.h"
 #include "chromeos/chromeos_switches.h"
 #include "chromeos/dbus/cryptohome_client.h"
 #include "chromeos/dbus/dbus_method_call_status.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/fake_cryptohome_client.h"
 #include "chromeos/dbus/fake_session_manager_client.h"
-#include "chromeos/dbus/mock_dbus_thread_manager_without_gmock.h"
 #include "chromeos/dbus/session_manager_client.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/test_utils.h"
+#include "crypto/rsa_private_key.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
 namespace em = enterprise_management;
 
+using testing::InvokeWithoutArgs;
 using testing::Return;
+using testing::_;
 
 namespace policy {
 
@@ -65,8 +62,7 @@
 
 const char kAccountId1[] = "dla1@example.com";
 const char kAccountId2[] = "dla2@example.com";
-const char kDisplayName1[] = "display name for account 1";
-const char kDisplayName2[] = "display name for account 2";
+const char kDisplayName[] = "display name";
 const char* kStartupURLs[] = {
   "chrome://policy",
   "chrome://about",
@@ -74,7 +70,7 @@
 
 }  // namespace
 
-class DeviceLocalAccountTest : public InProcessBrowserTest {
+class DeviceLocalAccountTest : public DevicePolicyCrosBrowserTest {
  protected:
   DeviceLocalAccountTest()
       : user_id_1_(GenerateDeviceLocalAccountUserId(
@@ -94,7 +90,7 @@
                                 PolicyBuilder::kFakeDeviceId);
     ASSERT_TRUE(test_server_.Start());
 
-    InProcessBrowserTest::SetUp();
+    DevicePolicyCrosBrowserTest::SetUp();
   }
 
   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
@@ -106,7 +102,7 @@
   }
 
   virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
-    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+    DevicePolicyCrosBrowserTest::SetUpInProcessBrowserTestFixture();
 
     // Clear command-line arguments (but keep command-line switches) so the
     // startup pages policy takes effect.
@@ -116,17 +112,10 @@
                argv.end());
     command_line->InitFromArgv(argv);
 
-    // Mark the device enterprise-enrolled.
-    SetUpInstallAttributes();
+    InstallOwnerKey();
+    MarkAsEnterpriseOwned();
 
-    // Redirect session_manager DBus calls to FakeSessionManagerClient.
-    chromeos::MockDBusThreadManagerWithoutGMock* dbus_thread_manager =
-        new chromeos::MockDBusThreadManagerWithoutGMock();
-    session_manager_client_ =
-        dbus_thread_manager->fake_session_manager_client();
-    chromeos::DBusThreadManager::InitializeForTesting(dbus_thread_manager);
-
-    SetUpPolicy();
+    InitializePolicy();
   }
 
   virtual void CleanUpOnMainThread() OVERRIDE {
@@ -136,98 +125,68 @@
     base::RunLoop().RunUntilIdle();
   }
 
-  void SetUpInstallAttributes() {
-    cryptohome::SerializedInstallAttributes install_attrs_proto;
-    cryptohome::SerializedInstallAttributes::Attribute* attribute = NULL;
-
-    attribute = install_attrs_proto.add_attributes();
-    attribute->set_name(EnterpriseInstallAttributes::kAttrEnterpriseOwned);
-    attribute->set_value("true");
-
-    attribute = install_attrs_proto.add_attributes();
-    attribute->set_name(EnterpriseInstallAttributes::kAttrEnterpriseUser);
-    attribute->set_value(PolicyBuilder::kFakeUsername);
-
-    base::FilePath install_attrs_file =
-        temp_dir_.path().AppendASCII("install_attributes.pb");
-    const std::string install_attrs_blob(
-        install_attrs_proto.SerializeAsString());
-    ASSERT_EQ(static_cast<int>(install_attrs_blob.size()),
-              file_util::WriteFile(install_attrs_file,
-                                   install_attrs_blob.c_str(),
-                                   install_attrs_blob.size()));
-    ASSERT_TRUE(PathService::Override(chromeos::FILE_INSTALL_ATTRIBUTES,
-                                      install_attrs_file));
+  void RemoveOwnerPrivateKeyFromPolicyBuilders() {
+    // Any instances of the private half of the owner key held by policy
+    // builders must be dropped as otherwise the NSS library will tell Chrome
+    // that the key is available - which is incorrect and leads to Chrome
+    // behaving as if a local owner were logged in.
+    device_policy()->set_signing_key(scoped_ptr<crypto::RSAPrivateKey>());
+    device_policy()->set_new_signing_key(scoped_ptr<crypto::RSAPrivateKey>());
+    device_local_account_policy_.set_signing_key(
+        scoped_ptr<crypto::RSAPrivateKey>());
+    device_local_account_policy_.set_new_signing_key(
+        scoped_ptr<crypto::RSAPrivateKey>());
   }
 
-  void SetUpPolicy() {
-    // Configure two device-local accounts in device settings.
-    DevicePolicyBuilder device_policy;
-    device_policy.policy_data().set_public_key_version(1);
-    em::ChromeDeviceSettingsProto& proto(device_policy.payload());
+  void InitializePolicy() {
+    device_policy()->policy_data().set_public_key_version(1);
+    em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
     proto.mutable_show_user_names()->set_show_user_names(true);
-    em::DeviceLocalAccountInfoProto* account1 =
-        proto.mutable_device_local_accounts()->add_account();
-    account1->set_account_id(kAccountId1);
-    account1->set_type(
-        em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION);
-    em::DeviceLocalAccountInfoProto* account2 =
-        proto.mutable_device_local_accounts()->add_account();
-    account2->set_account_id(kAccountId2);
-    account2->set_type(
-        em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION);
-    device_policy.Build();
-    session_manager_client_->set_device_policy(device_policy.GetBlob());
-    test_server_.UpdatePolicy(dm_protocol::kChromeDevicePolicyType,
-                              std::string(), proto.SerializeAsString());
 
-    // Install the owner key.
-    base::FilePath owner_key_file = temp_dir_.path().AppendASCII("owner.key");
-    std::vector<uint8> owner_key_bits;
-    ASSERT_TRUE(device_policy.signing_key()->ExportPublicKey(&owner_key_bits));
-    ASSERT_EQ(
-        static_cast<int>(owner_key_bits.size()),
-        file_util::WriteFile(
-            owner_key_file,
-            reinterpret_cast<const char*>(vector_as_array(&owner_key_bits)),
-            owner_key_bits.size()));
-    ASSERT_TRUE(
-        PathService::Override(chromeos::FILE_OWNER_KEY, owner_key_file));
-
-    // Configure device-local account policy for the first device-local account.
-    UserPolicyBuilder device_local_account_policy;
-    device_local_account_policy.policy_data().set_policy_type(
+    device_local_account_policy_.policy_data().set_policy_type(
         dm_protocol::kChromePublicAccountPolicyType);
-    device_local_account_policy.policy_data().set_username(kAccountId1);
-    device_local_account_policy.policy_data().set_settings_entity_id(
+    device_local_account_policy_.policy_data().set_username(kAccountId1);
+    device_local_account_policy_.policy_data().set_settings_entity_id(
         kAccountId1);
-    device_local_account_policy.policy_data().set_public_key_version(1);
-    device_local_account_policy.payload().mutable_restoreonstartup()->set_value(
-        SessionStartupPref::kPrefValueURLs);
-    em::StringListPolicyProto* startup_urls_proto =
-        device_local_account_policy.payload().mutable_restoreonstartupurls();
-    for (size_t i = 0; i < arraysize(kStartupURLs); ++i)
-      startup_urls_proto->mutable_value()->add_entries(kStartupURLs[i]);
-    device_local_account_policy.payload().mutable_userdisplayname()->set_value(
-        kDisplayName1);
-    device_local_account_policy.Build();
-    session_manager_client_->set_device_local_account_policy(
-        kAccountId1, device_local_account_policy.GetBlob());
+    device_local_account_policy_.policy_data().set_public_key_version(1);
+    device_local_account_policy_.payload().mutable_userdisplayname()->set_value(
+        kDisplayName);
+
+    RemoveOwnerPrivateKeyFromPolicyBuilders();
+  }
+
+  void BuildDeviceLocalAccountPolicy() {
+    device_local_account_policy_.set_signing_key(
+        PolicyBuilder::CreateTestSigningKey());
+    device_local_account_policy_.Build();
+    RemoveOwnerPrivateKeyFromPolicyBuilders();
+  }
+
+  void InstallDeviceLocalAccountPolicy() {
+    BuildDeviceLocalAccountPolicy();
+    session_manager_client()->set_device_local_account_policy(
+        kAccountId1, device_local_account_policy_.GetBlob());
+  }
+
+  void UploadDeviceLocalAccountPolicy() {
+    BuildDeviceLocalAccountPolicy();
+    ASSERT_TRUE(session_manager_client()->device_local_account_policy(
+        kAccountId1).empty());
     test_server_.UpdatePolicy(
         dm_protocol::kChromePublicAccountPolicyType, kAccountId1,
-        device_local_account_policy.payload().SerializeAsString());
+        device_local_account_policy_.payload().SerializeAsString());
+  }
 
-    // Make policy for the second account available from the server.
-    device_local_account_policy.payload().mutable_userdisplayname()->set_value(
-        kDisplayName2);
-    test_server_.UpdatePolicy(
-        dm_protocol::kChromePublicAccountPolicyType, kAccountId2,
-        device_local_account_policy.payload().SerializeAsString());
-
-    // Don't install policy for |kAccountId2| yet so initial download gets
-    // test coverage.
-    ASSERT_TRUE(session_manager_client_->device_local_account_policy(
-        kAccountId2).empty());
+  void AddPublicSessionToDevicePolicy(const std::string& username) {
+    em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
+    em::DeviceLocalAccountInfoProto* account =
+        proto.mutable_device_local_accounts()->add_account();
+    account->set_account_id(username);
+    account->set_type(
+        em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION);
+    RefreshDevicePolicy();
+    test_server_.UpdatePolicy(dm_protocol::kChromeDevicePolicyType,
+                              std::string(), proto.SerializeAsString());
   }
 
   void CheckPublicSessionPresent(const std::string& id) {
@@ -240,10 +199,8 @@
   const std::string user_id_1_;
   const std::string user_id_2_;
 
+  UserPolicyBuilder device_local_account_policy_;
   LocalPolicyTestServer test_server_;
-  base::ScopedTempDir temp_dir_;
-
-  chromeos::FakeSessionManagerClient* session_manager_client_;
 };
 
 static bool IsKnownUser(const std::string& account_id) {
@@ -251,6 +208,9 @@
 }
 
 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, LoginScreen) {
+  AddPublicSessionToDevicePolicy(kAccountId1);
+  AddPublicSessionToDevicePolicy(kAccountId2);
+
   content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED,
                                         base::Bind(&IsKnownUser, user_id_1_))
       .Wait();
@@ -263,7 +223,7 @@
 }
 
 static bool DisplayNameMatches(const std::string& account_id,
-                        const std::string& display_name) {
+                               const std::string& display_name) {
   const chromeos::User* user =
       chromeos::UserManager::Get()->FindUser(account_id);
   if (!user || user->display_name().empty())
@@ -273,23 +233,28 @@
 }
 
 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, DisplayName) {
+  InstallDeviceLocalAccountPolicy();
+  AddPublicSessionToDevicePolicy(kAccountId1);
+
   content::WindowedNotificationObserver(
       chrome::NOTIFICATION_USER_LIST_CHANGED,
-      base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName1)).Wait();
+      base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait();
 }
 
 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, PolicyDownload) {
-  // Policy for kAccountId2 is not installed in session_manager_client, make
-  // sure it gets fetched from the server. Note that the test setup doesn't set
-  // up policy for kAccountId2, so the presence of the display name can be used
-  // as signal to indicate successful policy download.
+  UploadDeviceLocalAccountPolicy();
+  AddPublicSessionToDevicePolicy(kAccountId1);
+
+  // Policy for the account is not installed in session_manager_client. Because
+  // of this, the presence of the display name (which comes from policy) can be
+  // used as a signal that indicates successful policy download.
   content::WindowedNotificationObserver(
       chrome::NOTIFICATION_USER_LIST_CHANGED,
-      base::Bind(&DisplayNameMatches, user_id_2_, kDisplayName2)).Wait();
+      base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait();
 
   // Sanity check: The policy should be present now.
-  ASSERT_FALSE(session_manager_client_->device_local_account_policy(
-      kAccountId2).empty());
+  ASSERT_FALSE(session_manager_client()->device_local_account_policy(
+      kAccountId1).empty());
 }
 
 static bool IsNotKnownUser(const std::string& account_id) {
@@ -297,6 +262,9 @@
 }
 
 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, DevicePolicyChange) {
+  AddPublicSessionToDevicePolicy(kAccountId1);
+  AddPublicSessionToDevicePolicy(kAccountId2);
+
   // Wait until the login screen is up.
   content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED,
                                         base::Bind(&IsKnownUser, user_id_1_))
@@ -306,6 +274,10 @@
       .Wait();
 
   // Update policy to remove kAccountId2.
+  em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
+  proto.mutable_device_local_accounts()->clear_account();
+  AddPublicSessionToDevicePolicy(kAccountId1);
+
   em::ChromeDeviceSettingsProto policy;
   policy.mutable_show_user_names()->set_show_user_names(true);
   em::DeviceLocalAccountInfoProto* account1 =
@@ -329,12 +301,22 @@
 }
 
 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, StartSession) {
+  // Specify startup pages.
+  device_local_account_policy_.payload().mutable_restoreonstartup()->set_value(
+      SessionStartupPref::kPrefValueURLs);
+  em::StringListPolicyProto* startup_urls_proto =
+      device_local_account_policy_.payload().mutable_restoreonstartupurls();
+  for (size_t i = 0; i < arraysize(kStartupURLs); ++i)
+    startup_urls_proto->mutable_value()->add_entries(kStartupURLs[i]);
+  InstallDeviceLocalAccountPolicy();
+  AddPublicSessionToDevicePolicy(kAccountId1);
+
   // This observes the display name becoming available as this indicates
   // device-local account policy is fully loaded, which is a prerequisite for
   // successful login.
   content::WindowedNotificationObserver(
       chrome::NOTIFICATION_USER_LIST_CHANGED,
-      base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName1)).Wait();
+      base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait();
 
   chromeos::LoginDisplayHost* host =
       chromeos::LoginDisplayHostImpl::default_host();
@@ -363,4 +345,49 @@
     EXPECT_EQ(GURL(kStartupURLs[i]), tabs->GetWebContentsAt(i)->GetURL());
 }
 
+IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, TermsOfService) {
+  // Specify Terms of Service. The URL does not really matter as the test does
+  // not wait for the terms to load.
+  device_local_account_policy_.payload().mutable_termsofserviceurl()->set_value(
+      "http://localhost/tos");
+  InstallDeviceLocalAccountPolicy();
+  AddPublicSessionToDevicePolicy(kAccountId1);
+
+  // Wait for the device-local account policy to be fully loaded.
+  content::WindowedNotificationObserver(
+      chrome::NOTIFICATION_USER_LIST_CHANGED,
+      base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait();
+
+  // Start login into the device-local account.
+  chromeos::LoginDisplayHost* host =
+      chromeos::LoginDisplayHostImpl::default_host();
+  ASSERT_TRUE(host);
+  host->StartSignInScreen();
+  chromeos::ExistingUserController* controller =
+      chromeos::ExistingUserController::current_controller();
+  ASSERT_TRUE(controller);
+  controller->LoginAsPublicAccount(user_id_1_);
+
+  // Set up an observer that will quit the message loop when login has succeeded
+  // and the first wizard screen, if any, is being shown.
+  base::RunLoop run_loop;
+  chromeos::MockConsumer login_status_consumer;
+  EXPECT_CALL(login_status_consumer, OnLoginSuccess(_, false, false))
+      .Times(1)
+      .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
+
+  // Spin the loop until the observer fires. Then, unregister the observer.
+  controller->set_login_status_consumer(&login_status_consumer);
+  run_loop.Run();
+  controller->set_login_status_consumer(NULL);
+
+  // Verify that the Terms of Service screen is being shown.
+  chromeos::WizardController* wizard_controller =
+        chromeos::WizardController::default_controller();
+  ASSERT_TRUE(wizard_controller);
+  ASSERT_TRUE(wizard_controller->current_screen());
+  EXPECT_EQ(chromeos::WizardController::kTermsOfServiceScreenName,
+            wizard_controller->current_screen()->GetName());
+}
+
 }  // namespace policy
diff --git a/chrome/browser/chromeos/policy/device_policy_cros_browser_test.cc b/chrome/browser/chromeos/policy/device_policy_cros_browser_test.cc
index bbc8471..d62c486 100644
--- a/chrome/browser/chromeos/policy/device_policy_cros_browser_test.cc
+++ b/chrome/browser/chromeos/policy/device_policy_cros_browser_test.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h"
 
+#include <string>
 #include <vector>
 
 #include "base/file_util.h"
@@ -12,6 +13,8 @@
 #include "base/path_service.h"
 #include "base/stl_util.h"
 #include "chrome/browser/chromeos/policy/device_policy_builder.h"
+#include "chrome/browser/chromeos/policy/enterprise_install_attributes.h"
+#include "chrome/browser/policy/proto/chromeos/install_attributes.pb.h"
 #include "chromeos/chromeos_paths.h"
 #include "chromeos/dbus/mock_dbus_thread_manager_without_gmock.h"
 #include "crypto/rsa_private_key.h"
@@ -24,6 +27,30 @@
 
 namespace policy {
 
+void DevicePolicyCrosBrowserTest::MarkAsEnterpriseOwned() {
+  cryptohome::SerializedInstallAttributes install_attrs_proto;
+  cryptohome::SerializedInstallAttributes::Attribute* attribute = NULL;
+
+  attribute = install_attrs_proto.add_attributes();
+  attribute->set_name(EnterpriseInstallAttributes::kAttrEnterpriseOwned);
+  attribute->set_value("true");
+
+  attribute = install_attrs_proto.add_attributes();
+  attribute->set_name(EnterpriseInstallAttributes::kAttrEnterpriseUser);
+  attribute->set_value(DevicePolicyBuilder::kFakeUsername);
+
+  base::FilePath install_attrs_file =
+      temp_dir_.path().AppendASCII("install_attributes.pb");
+  const std::string install_attrs_blob(
+      install_attrs_proto.SerializeAsString());
+  ASSERT_EQ(static_cast<int>(install_attrs_blob.size()),
+            file_util::WriteFile(install_attrs_file,
+                                 install_attrs_blob.c_str(),
+                                 install_attrs_blob.size()));
+  ASSERT_TRUE(PathService::Override(chromeos::FILE_INSTALL_ATTRIBUTES,
+                                    install_attrs_file));
+}
+
 DevicePolicyCrosBrowserTest::DevicePolicyCrosBrowserTest()
     : mock_dbus_thread_manager_(
         new chromeos::MockDBusThreadManagerWithoutGMock) {
diff --git a/chrome/browser/chromeos/policy/device_policy_cros_browser_test.h b/chrome/browser/chromeos/policy/device_policy_cros_browser_test.h
index 88961e6..41efb7f 100644
--- a/chrome/browser/chromeos/policy/device_policy_cros_browser_test.h
+++ b/chrome/browser/chromeos/policy/device_policy_cros_browser_test.h
@@ -20,6 +20,12 @@
 // Used to test Device policy changes in Chrome OS.
 class DevicePolicyCrosBrowserTest :
     public chromeos::CrosInProcessBrowserTest {
+ public:
+  // Marks the device as enterprise-owned. Must be called to make device
+  // policies apply Chrome-wide. If this is not called, device policies will
+  // affect CrosSettings only.
+  void MarkAsEnterpriseOwned();
+
  protected:
   DevicePolicyCrosBrowserTest();
   virtual ~DevicePolicyCrosBrowserTest();
@@ -46,15 +52,15 @@
   DevicePolicyBuilder* device_policy() { return &device_policy_; }
 
  private:
+  // Stores the device owner key and the install attributes.
+  base::ScopedTempDir temp_dir_;
+
   // MockDBusThreadManagerWithoutGMock uses FakeSessionManagerClient.
   chromeos::MockDBusThreadManagerWithoutGMock* mock_dbus_thread_manager_;
 
   // Carries Chrome OS device policies for tests.
   DevicePolicyBuilder device_policy_;
 
-  // Stores the device owner key.
-  base::ScopedTempDir temp_dir_;
-
   DISALLOW_COPY_AND_ASSIGN(DevicePolicyCrosBrowserTest);
 };
 
diff --git a/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc b/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
index b1d9b62..15359ec 100644
--- a/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
+++ b/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
@@ -177,6 +177,19 @@
                         container.enable_auto_login_bailout()));
     }
   }
+
+  if (policy.has_supervised_users_settings()) {
+    const em::SupervisedUsersSettingsProto& container =
+        policy.supervised_users_settings();
+    if (container.has_supervised_users_enabled()) {
+      Value* value = Value::CreateBooleanValue(
+          container.supervised_users_enabled());
+      policies->Set(key::kSupervisedUsersEnabled,
+                    POLICY_LEVEL_MANDATORY,
+                    POLICY_SCOPE_MACHINE,
+                    value);
+    }
+  }
 }
 
 void DecodeKioskPolicies(const em::ChromeDeviceSettingsProto& policy,
@@ -416,6 +429,50 @@
   }
 }
 
+void DecodeAccessibilityPolicies(const em::ChromeDeviceSettingsProto& policy,
+                                 PolicyMap* policies) {
+  if (policy.has_accessibility_settings()) {
+    const em::AccessibilitySettingsProto&
+        container(policy.accessibility_settings());
+
+    if (container.has_login_screen_default_large_cursor_enabled()) {
+      policies->Set(
+          key::kDeviceLoginScreenDefaultLargeCursorEnabled,
+          POLICY_LEVEL_MANDATORY,
+          POLICY_SCOPE_MACHINE,
+          Value::CreateBooleanValue(
+              container.login_screen_default_large_cursor_enabled()));
+    }
+
+    if (container.has_login_screen_default_spoken_feedback_enabled()) {
+      policies->Set(
+          key::kDeviceLoginScreenDefaultSpokenFeedbackEnabled,
+          POLICY_LEVEL_MANDATORY,
+          POLICY_SCOPE_MACHINE,
+          Value::CreateBooleanValue(
+              container.login_screen_default_spoken_feedback_enabled()));
+    }
+
+    if (container.has_login_screen_default_high_contrast_enabled()) {
+      policies->Set(
+          key::kDeviceLoginScreenDefaultHighContrastEnabled,
+          POLICY_LEVEL_MANDATORY,
+          POLICY_SCOPE_MACHINE,
+          Value::CreateBooleanValue(
+              container.login_screen_default_high_contrast_enabled()));
+    }
+
+    if (container.has_login_screen_default_screen_magnifier_type()) {
+      policies->Set(
+          key::kDeviceLoginScreenDefaultScreenMagnifierType,
+          POLICY_LEVEL_MANDATORY,
+          POLICY_SCOPE_MACHINE,
+          DecodeIntegerValue(
+              container.login_screen_default_screen_magnifier_type()));
+    }
+  }
+}
+
 void DecodeGenericPolicies(const em::ChromeDeviceSettingsProto& policy,
                            PolicyMap* policies) {
   if (policy.has_device_policy_refresh_rate()) {
@@ -533,6 +590,7 @@
   DecodeNetworkPolicies(policy, policies, install_attributes);
   DecodeReportingPolicies(policy, policies);
   DecodeAutoUpdatePolicies(policy, policies);
+  DecodeAccessibilityPolicies(policy, policies);
   DecodeGenericPolicies(policy, policies);
 }
 
diff --git a/chrome/browser/chromeos/policy/device_status_collector.cc b/chrome/browser/chromeos/policy/device_status_collector.cc
index 215de16..2c31a3a 100644
--- a/chrome/browser/chromeos/policy/device_status_collector.cc
+++ b/chrome/browser/chromeos/policy/device_status_collector.cc
@@ -371,7 +371,7 @@
     em::DeviceStatusReportRequest* request) {
   std::string dev_switch_mode;
   if (statistics_provider_->GetMachineStatistic(
-      "devsw_boot", &dev_switch_mode)) {
+          chromeos::system::kDevSwitchBootMode, &dev_switch_mode)) {
     if (dev_switch_mode == "1")
       request->set_boot_mode("Dev");
     else if (dev_switch_mode == "0")
diff --git a/chrome/browser/chromeos/policy/device_status_collector.h b/chrome/browser/chromeos/policy/device_status_collector.h
index 7eb8f90..2144019 100644
--- a/chrome/browser/chromeos/policy/device_status_collector.h
+++ b/chrome/browser/chromeos/policy/device_status_collector.h
@@ -12,8 +12,8 @@
 #include "base/compiler_specific.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/chromeos/version_loader.h"
 #include "chrome/browser/idle.h"
 #include "chrome/browser/policy/cloud/cloud_policy_client.h"
diff --git a/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc b/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc
index 9f74d3f..e23ce1e 100644
--- a/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc
+++ b/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc
@@ -216,7 +216,6 @@
 
   // Use the system request context to avoid sending user cookies.
   gaia_oauth_client_.reset(new gaia::GaiaOAuthClient(
-      GaiaUrls::GetInstance()->oauth2_token_url(),
       g_browser_process->system_request_context()));
   gaia_oauth_client_->GetTokensFromAuthCode(client_info,
                                             client->robot_api_auth_code(),
diff --git a/chrome/browser/chromeos/policy/login_profile_policy_provider.cc b/chrome/browser/chromeos/policy/login_profile_policy_provider.cc
new file mode 100644
index 0000000..da88bea
--- /dev/null
+++ b/chrome/browser/chromeos/policy/login_profile_policy_provider.cc
@@ -0,0 +1,114 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/policy/login_profile_policy_provider.h"
+
+#include <string>
+
+#include "base/bind.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/values.h"
+#include "chrome/browser/policy/policy_bundle.h"
+#include "chrome/browser/policy/policy_map.h"
+#include "chrome/browser/policy/policy_types.h"
+#include "policy/policy_constants.h"
+
+namespace policy {
+
+namespace {
+
+// Applies the value of |device_policy| in |device_policy_map| as the
+// recommended value of |user_policy| in |user_policy_map|. If the value of
+// |device_policy| is unset, does nothing.
+void ApplyDevicePolicy(const std::string& device_policy,
+                       const std::string& user_policy,
+                       const PolicyMap& device_policy_map,
+                       PolicyMap* user_policy_map) {
+  const base::Value* value = device_policy_map.GetValue(device_policy);
+  if (value) {
+    user_policy_map->Set(user_policy,
+                         POLICY_LEVEL_RECOMMENDED,
+                         POLICY_SCOPE_USER,
+                         value->DeepCopy());
+  }
+}
+
+}  // namespace
+
+LoginProfilePolicyProvider::LoginProfilePolicyProvider(
+    PolicyService* device_policy_service)
+    : device_policy_service_(device_policy_service),
+      waiting_for_device_policy_refresh_(false),
+      weak_factory_(this) {
+}
+
+LoginProfilePolicyProvider::~LoginProfilePolicyProvider() {
+}
+
+void LoginProfilePolicyProvider::Init() {
+  ConfigurationPolicyProvider::Init();
+  device_policy_service_->AddObserver(POLICY_DOMAIN_CHROME, this);
+  if (device_policy_service_->IsInitializationComplete(POLICY_DOMAIN_CHROME))
+    UpdateFromDevicePolicy();
+}
+
+void LoginProfilePolicyProvider::Shutdown() {
+  device_policy_service_->RemoveObserver(POLICY_DOMAIN_CHROME, this);
+  weak_factory_.InvalidateWeakPtrs();
+  ConfigurationPolicyProvider::Shutdown();
+}
+
+void LoginProfilePolicyProvider::RefreshPolicies() {
+  waiting_for_device_policy_refresh_ = true;
+  weak_factory_.InvalidateWeakPtrs();
+  device_policy_service_->RefreshPolicies(base::Bind(
+      &LoginProfilePolicyProvider::OnDevicePolicyRefreshDone,
+      weak_factory_.GetWeakPtr()));
+}
+
+void LoginProfilePolicyProvider::OnPolicyUpdated(const PolicyNamespace& ns,
+                                                 const PolicyMap& previous,
+                                                 const PolicyMap& current) {
+  if (ns == PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
+    UpdateFromDevicePolicy();
+}
+
+void LoginProfilePolicyProvider::OnPolicyServiceInitialized(
+    PolicyDomain domain) {
+  if (domain == POLICY_DOMAIN_CHROME)
+    UpdateFromDevicePolicy();
+}
+
+void LoginProfilePolicyProvider::OnDevicePolicyRefreshDone() {
+  waiting_for_device_policy_refresh_ = false;
+  UpdateFromDevicePolicy();
+}
+
+void LoginProfilePolicyProvider::UpdateFromDevicePolicy() {
+  // If a policy refresh is in progress, wait for it to finish.
+  if (waiting_for_device_policy_refresh_)
+    return;
+
+  const PolicyNamespace chrome_namespaces(POLICY_DOMAIN_CHROME, std::string());
+  const PolicyMap& device_policy_map =
+      device_policy_service_->GetPolicies(chrome_namespaces);
+  scoped_ptr<PolicyBundle> bundle(new PolicyBundle);
+  PolicyMap& user_policy_map = bundle->Get(chrome_namespaces);
+
+  ApplyDevicePolicy(key::kDeviceLoginScreenDefaultLargeCursorEnabled,
+                    key::kLargeCursorEnabled,
+                    device_policy_map, &user_policy_map);
+  ApplyDevicePolicy(key::kDeviceLoginScreenDefaultSpokenFeedbackEnabled,
+                    key::kSpokenFeedbackEnabled,
+                    device_policy_map, &user_policy_map);
+  ApplyDevicePolicy(key::kDeviceLoginScreenDefaultHighContrastEnabled,
+                    key::kHighContrastEnabled,
+                    device_policy_map, &user_policy_map);
+  ApplyDevicePolicy(key::kDeviceLoginScreenDefaultScreenMagnifierType,
+                    key::kScreenMagnifierType,
+                    device_policy_map, &user_policy_map);
+  UpdatePolicy(bundle.Pass());
+}
+
+}  // namespace policy
diff --git a/chrome/browser/chromeos/policy/login_profile_policy_provider.h b/chrome/browser/chromeos/policy/login_profile_policy_provider.h
new file mode 100644
index 0000000..47ee1af
--- /dev/null
+++ b/chrome/browser/chromeos/policy/login_profile_policy_provider.h
@@ -0,0 +1,53 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_POLICY_LOGIN_PROFILE_POLICY_PROVIDER_H_
+#define CHROME_BROWSER_CHROMEOS_POLICY_LOGIN_PROFILE_POLICY_PROVIDER_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/policy/configuration_policy_provider.h"
+#include "chrome/browser/policy/policy_service.h"
+
+namespace policy {
+
+// Policy provider for the login profile. Since the login profile is not
+// associated with any user, it does not receive regular user policy. However,
+// several device policies that control features on the login screen surface as
+// recommended user policies in the login profile.
+class LoginProfilePolicyProvider : public ConfigurationPolicyProvider,
+                                   public PolicyService::Observer {
+ public:
+  explicit LoginProfilePolicyProvider(PolicyService* device_policy_service);
+  virtual ~LoginProfilePolicyProvider();
+
+  // ConfigurationPolicyProvider:
+  virtual void Init() OVERRIDE;
+  virtual void Shutdown() OVERRIDE;
+  virtual void RefreshPolicies() OVERRIDE;
+
+  // PolicyService::Observer:
+  virtual void OnPolicyUpdated(const PolicyNamespace& ns,
+                               const PolicyMap& previous,
+                               const PolicyMap& current) OVERRIDE;
+  virtual void OnPolicyServiceInitialized(PolicyDomain domain) OVERRIDE;
+
+  void OnDevicePolicyRefreshDone();
+
+ private:
+  void UpdateFromDevicePolicy();
+
+  PolicyService* device_policy_service_;  // Not owned.
+
+  bool waiting_for_device_policy_refresh_;
+
+  base::WeakPtrFactory<LoginProfilePolicyProvider> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(LoginProfilePolicyProvider);
+};
+
+}  // namespace policy
+
+#endif  // CHROME_BROWSER_CHROMEOS_POLICY_LOGIN_PROFILE_POLICY_PROVIDER_H_
diff --git a/chrome/browser/chromeos/policy/login_screen_default_policy_browsertest.cc b/chrome/browser/chromeos/policy/login_screen_default_policy_browsertest.cc
new file mode 100644
index 0000000..e58cb3c
--- /dev/null
+++ b/chrome/browser/chromeos/policy/login_screen_default_policy_browsertest.cc
@@ -0,0 +1,437 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+
+#include "ash/magnifier/magnifier_constants.h"
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/command_line.h"
+#include "base/compiler_specific.h"
+#include "base/location.h"
+#include "base/message_loop.h"
+#include "base/prefs/pref_change_registrar.h"
+#include "base/prefs/pref_service.h"
+#include "base/run_loop.h"
+#include "base/values.h"
+#include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
+#include "chrome/browser/chromeos/accessibility/magnification_manager.h"
+#include "chrome/browser/chromeos/policy/device_policy_builder.h"
+#include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h"
+#include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chrome/browser/chromeos/settings/device_settings_service.h"
+#include "chrome/browser/lifetime/application_lifetime.h"
+#include "chrome/browser/policy/proto/chromeos/chrome_device_policy.pb.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/common/pref_names.h"
+#include "chromeos/chromeos_switches.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace em = enterprise_management;
+
+namespace policy {
+
+namespace {
+
+const em::AccessibilitySettingsProto_ScreenMagnifierType kFullScreenMagnifier =
+    em::AccessibilitySettingsProto_ScreenMagnifierType_SCREEN_MAGNIFIER_TYPE_FULL;
+
+// Spins the loop until a notification is received from |prefs| that the value
+// of |pref_name| has changed. If the notification is received before Wait()
+// has been called, Wait() returns immediately and no loop is spun.
+class PrefChangeWatcher {
+ public:
+  PrefChangeWatcher(const char* pref_name, PrefService* prefs);
+
+  void Wait();
+
+  void OnPrefChange();
+
+ private:
+  bool pref_changed_;
+
+  base::RunLoop run_loop_;
+  PrefChangeRegistrar registrar_;
+
+  DISALLOW_COPY_AND_ASSIGN(PrefChangeWatcher);
+};
+
+PrefChangeWatcher::PrefChangeWatcher(const char* pref_name,
+                                     PrefService* prefs)
+    : pref_changed_(false) {
+  registrar_.Init(prefs);
+  registrar_.Add(pref_name, base::Bind(&PrefChangeWatcher::OnPrefChange,
+                                       base::Unretained(this)));
+}
+
+void PrefChangeWatcher::Wait() {
+  if (!pref_changed_)
+    run_loop_.Run();
+}
+
+void PrefChangeWatcher::OnPrefChange() {
+  pref_changed_ = true;
+  run_loop_.Quit();
+}
+
+}  // namespace
+
+class LoginScreenDefaultPolicyBrowsertestBase
+    : public DevicePolicyCrosBrowserTest {
+ protected:
+  LoginScreenDefaultPolicyBrowsertestBase();
+  virtual ~LoginScreenDefaultPolicyBrowsertestBase();
+
+  // DevicePolicyCrosBrowserTest:
+  virtual void SetUpInProcessBrowserTestFixture() OVERRIDE;
+  virtual void SetUpOnMainThread() OVERRIDE;
+
+  void RefreshDevicePolicyAndWaitForPrefChange(const char* pref_name);
+
+  Profile* login_profile_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(LoginScreenDefaultPolicyBrowsertestBase);
+};
+
+class LoginScreenDefaultPolicyLoginScreenBrowsertest
+    : public LoginScreenDefaultPolicyBrowsertestBase {
+ protected:
+  LoginScreenDefaultPolicyLoginScreenBrowsertest();
+  virtual ~LoginScreenDefaultPolicyLoginScreenBrowsertest();
+
+  // LoginScreenDefaultPolicyBrowsertestBase:
+  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE;
+  virtual void SetUpOnMainThread() OVERRIDE;
+  virtual void CleanUpOnMainThread() OVERRIDE;
+
+  void VerifyPrefFollowsRecommendation(const char* pref_name,
+                                       const base::Value& recommended_value);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(LoginScreenDefaultPolicyLoginScreenBrowsertest);
+};
+
+class LoginScreenDefaultPolicyInSessionBrowsertest
+    : public LoginScreenDefaultPolicyBrowsertestBase {
+ protected:
+  LoginScreenDefaultPolicyInSessionBrowsertest();
+  virtual ~LoginScreenDefaultPolicyInSessionBrowsertest();
+
+  // LoginScreenDefaultPolicyBrowsertestBase:
+  virtual void SetUpOnMainThread() OVERRIDE;
+
+  void VerifyPrefFollowsDefault(const char* pref_name);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(LoginScreenDefaultPolicyInSessionBrowsertest);
+};
+
+LoginScreenDefaultPolicyBrowsertestBase::
+    LoginScreenDefaultPolicyBrowsertestBase() : login_profile_(NULL) {
+}
+
+LoginScreenDefaultPolicyBrowsertestBase::
+    ~LoginScreenDefaultPolicyBrowsertestBase() {
+}
+
+void LoginScreenDefaultPolicyBrowsertestBase::
+    SetUpInProcessBrowserTestFixture() {
+  InstallOwnerKey();
+  MarkAsEnterpriseOwned();
+  DevicePolicyCrosBrowserTest::SetUpInProcessBrowserTestFixture();
+}
+
+void LoginScreenDefaultPolicyBrowsertestBase::SetUpOnMainThread() {
+  DevicePolicyCrosBrowserTest::SetUpOnMainThread();
+  login_profile_ = chromeos::ProfileHelper::GetSigninProfile();
+  ASSERT_TRUE(login_profile_);
+}
+
+void LoginScreenDefaultPolicyBrowsertestBase::
+    RefreshDevicePolicyAndWaitForPrefChange(const char* pref_name) {
+  PrefChangeWatcher watcher(pref_name, login_profile_->GetPrefs());
+  RefreshDevicePolicy();
+  watcher.Wait();
+}
+
+LoginScreenDefaultPolicyLoginScreenBrowsertest::
+    LoginScreenDefaultPolicyLoginScreenBrowsertest() {
+}
+
+LoginScreenDefaultPolicyLoginScreenBrowsertest::
+    ~LoginScreenDefaultPolicyLoginScreenBrowsertest() {
+}
+
+void LoginScreenDefaultPolicyLoginScreenBrowsertest::SetUpCommandLine(
+    CommandLine* command_line) {
+  LoginScreenDefaultPolicyBrowsertestBase::SetUpCommandLine(command_line);
+  command_line->AppendSwitch(chromeos::switches::kLoginManager);
+  command_line->AppendSwitch(chromeos::switches::kForceLoginManagerInTests);
+}
+
+void LoginScreenDefaultPolicyLoginScreenBrowsertest::SetUpOnMainThread() {
+  LoginScreenDefaultPolicyBrowsertestBase::SetUpOnMainThread();
+
+  // Set the login screen profile.
+  chromeos::AccessibilityManager* accessibility_manager =
+      chromeos::AccessibilityManager::Get();
+  ASSERT_TRUE(accessibility_manager);
+  accessibility_manager->SetProfileForTest(
+      chromeos::ProfileHelper::GetSigninProfile());
+
+  chromeos::MagnificationManager* magnification_manager =
+      chromeos::MagnificationManager::Get();
+  ASSERT_TRUE(magnification_manager);
+  magnification_manager->SetProfileForTest(
+      chromeos::ProfileHelper::GetSigninProfile());
+}
+
+void LoginScreenDefaultPolicyLoginScreenBrowsertest::CleanUpOnMainThread() {
+  base::MessageLoop::current()->PostTask(FROM_HERE,
+                                         base::Bind(&chrome::AttemptExit));
+  base::RunLoop().RunUntilIdle();
+  LoginScreenDefaultPolicyBrowsertestBase::CleanUpOnMainThread();
+}
+
+void LoginScreenDefaultPolicyLoginScreenBrowsertest::
+    VerifyPrefFollowsRecommendation(const char* pref_name,
+                                    const base::Value& recommended_value) {
+  const PrefService::Preference* pref =
+      login_profile_->GetPrefs()->FindPreference(pref_name);
+  ASSERT_TRUE(pref);
+  EXPECT_FALSE(pref->IsManaged());
+  EXPECT_FALSE(pref->IsDefaultValue());
+  EXPECT_TRUE(base::Value::Equals(&recommended_value, pref->GetValue()));
+  EXPECT_TRUE(base::Value::Equals(&recommended_value,
+                                  pref->GetRecommendedValue()));
+}
+
+LoginScreenDefaultPolicyInSessionBrowsertest::
+    LoginScreenDefaultPolicyInSessionBrowsertest() {
+}
+
+LoginScreenDefaultPolicyInSessionBrowsertest::
+    ~LoginScreenDefaultPolicyInSessionBrowsertest() {
+}
+
+void LoginScreenDefaultPolicyInSessionBrowsertest::SetUpOnMainThread() {
+  LoginScreenDefaultPolicyBrowsertestBase::SetUpOnMainThread();
+
+  // Tell the DeviceSettingsService that there is no local owner.
+  chromeos::DeviceSettingsService::Get()->SetUsername(std::string());
+}
+
+void LoginScreenDefaultPolicyInSessionBrowsertest::VerifyPrefFollowsDefault(
+    const char* pref_name) {
+  Profile* profile = ProfileManager::GetDefaultProfile();
+  ASSERT_TRUE(profile);
+  const PrefService::Preference* pref =
+      profile->GetPrefs()->FindPreference(pref_name);
+  ASSERT_TRUE(pref);
+  EXPECT_FALSE(pref->IsManaged());
+  EXPECT_TRUE(pref->IsDefaultValue());
+  EXPECT_FALSE(pref->GetRecommendedValue());
+}
+
+IN_PROC_BROWSER_TEST_F(LoginScreenDefaultPolicyLoginScreenBrowsertest,
+                       DeviceLoginScreenDefaultLargeCursorEnabled) {
+  // Verifies that the default state of the large cursor accessibility feature
+  // on the login screen can be controlled through device policy.
+
+  // Enable the large cursor through device policy and wait for the change to
+  // take effect.
+  em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
+  proto.mutable_accessibility_settings()->
+      set_login_screen_default_large_cursor_enabled(true);
+  RefreshDevicePolicyAndWaitForPrefChange(prefs::kLargeCursorEnabled);
+
+  // Verify that the pref which controls the large cursor in the login profile
+  // has changed to the policy-supplied default.
+  VerifyPrefFollowsRecommendation(prefs::kLargeCursorEnabled,
+                                  base::FundamentalValue(true));
+
+  // Verify that the large cursor is enabled.
+  chromeos::AccessibilityManager* accessibility_manager =
+      chromeos::AccessibilityManager::Get();
+  ASSERT_TRUE(accessibility_manager);
+  EXPECT_TRUE(accessibility_manager->IsLargeCursorEnabled());
+}
+
+IN_PROC_BROWSER_TEST_F(LoginScreenDefaultPolicyLoginScreenBrowsertest,
+                       DeviceLoginScreenDefaultSpokenFeedbackEnabled) {
+  // Verifies that the default state of the spoken feedback accessibility
+  // feature on the login screen can be controlled through device policy.
+
+  // Enable spoken feedback through device policy and wait for the change to
+  // take effect.
+  em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
+  proto.mutable_accessibility_settings()->
+      set_login_screen_default_spoken_feedback_enabled(true);
+  RefreshDevicePolicyAndWaitForPrefChange(prefs::kSpokenFeedbackEnabled);
+
+  // Verify that the pref which controls spoken feedback in the login profile
+  // has changed to the policy-supplied default.
+  VerifyPrefFollowsRecommendation(prefs::kSpokenFeedbackEnabled,
+                                  base::FundamentalValue(true));
+
+  // Verify that spoken feedback is enabled.
+  chromeos::AccessibilityManager* accessibility_manager =
+      chromeos::AccessibilityManager::Get();
+  ASSERT_TRUE(accessibility_manager);
+  EXPECT_TRUE(accessibility_manager->IsSpokenFeedbackEnabled());
+}
+
+IN_PROC_BROWSER_TEST_F(LoginScreenDefaultPolicyLoginScreenBrowsertest,
+                       DeviceLoginScreenDefaultHighContrastEnabled) {
+  // Verifies that the default state of the high contrast mode accessibility
+  // feature on the login screen can be controlled through device policy.
+
+  // Enable high contrast mode through device policy and wait for the change to
+  // take effect.
+  em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
+  proto.mutable_accessibility_settings()->
+      set_login_screen_default_high_contrast_enabled(true);
+  RefreshDevicePolicyAndWaitForPrefChange(prefs::kHighContrastEnabled);
+
+  // Verify that the pref which controls high contrast mode in the login profile
+  // has changed to the policy-supplied default.
+  VerifyPrefFollowsRecommendation(prefs::kHighContrastEnabled,
+                                  base::FundamentalValue(true));
+
+  // Verify that high contrast mode is enabled.
+  chromeos::AccessibilityManager* accessibility_manager =
+      chromeos::AccessibilityManager::Get();
+  ASSERT_TRUE(accessibility_manager);
+  EXPECT_TRUE(accessibility_manager->IsHighContrastEnabled());
+}
+
+IN_PROC_BROWSER_TEST_F(LoginScreenDefaultPolicyLoginScreenBrowsertest,
+                       DeviceLoginScreenDefaultScreenMagnifierType) {
+  // Verifies that the default screen magnifier type enabled on the login screen
+  // can be controlled through device policy.
+
+  // Set the screen magnifier type through device policy and wait for the change
+  // to take effect.
+  em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
+  proto.mutable_accessibility_settings()->
+      set_login_screen_default_screen_magnifier_type(kFullScreenMagnifier);
+  RefreshDevicePolicyAndWaitForPrefChange(prefs::kScreenMagnifierType);
+
+  // Verify that the prefs which control the screen magnifier type have changed
+  // to the policy-supplied default.
+  VerifyPrefFollowsRecommendation(prefs::kScreenMagnifierEnabled,
+                                  base::FundamentalValue(true));
+  VerifyPrefFollowsRecommendation(prefs::kScreenMagnifierType,
+                                  base::FundamentalValue(ash::MAGNIFIER_FULL));
+
+  // Verify that the full-screen magnifier is enabled.
+  chromeos::MagnificationManager* magnification_manager =
+      chromeos::MagnificationManager::Get();
+  ASSERT_TRUE(magnification_manager);
+  EXPECT_TRUE(magnification_manager->IsMagnifierEnabled());
+  EXPECT_EQ(ash::MAGNIFIER_FULL, magnification_manager->GetMagnifierType());
+}
+
+IN_PROC_BROWSER_TEST_F(LoginScreenDefaultPolicyInSessionBrowsertest,
+                       DeviceLoginScreenDefaultLargeCursorEnabled) {
+  // Verifies that changing the default state of the large cursor accessibility
+  // feature on the login screen through policy does not affect its state in a
+  // session.
+
+  // Enable the large cursor through device policy and wait for the change to
+  // take effect.
+  em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
+  proto.mutable_accessibility_settings()->
+      set_login_screen_default_large_cursor_enabled(true);
+  RefreshDevicePolicyAndWaitForPrefChange(prefs::kLargeCursorEnabled);
+
+  // Verify that the pref which controls the large cursor in the session is
+  // unchanged.
+  VerifyPrefFollowsDefault(prefs::kLargeCursorEnabled);
+
+  // Verify that the large cursor is disabled.
+  chromeos::AccessibilityManager* accessibility_manager =
+      chromeos::AccessibilityManager::Get();
+  ASSERT_TRUE(accessibility_manager);
+  EXPECT_FALSE(accessibility_manager->IsLargeCursorEnabled());
+}
+
+IN_PROC_BROWSER_TEST_F(LoginScreenDefaultPolicyInSessionBrowsertest,
+                       DeviceLoginScreenDefaultSpokenFeedbackEnabled) {
+  // Verifies that changing the default state of the spoken feedback
+  // accessibility feature on the login screen through policy does not affect
+  // its state in a session.
+
+  // Enable spoken feedback through device policy and wait for the change to
+  // take effect.
+  em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
+  proto.mutable_accessibility_settings()->
+      set_login_screen_default_spoken_feedback_enabled(true);
+  RefreshDevicePolicyAndWaitForPrefChange(prefs::kSpokenFeedbackEnabled);
+
+  // Verify that the pref which controls the spoken feedback in the session is
+  // unchanged.
+  VerifyPrefFollowsDefault(prefs::kSpokenFeedbackEnabled);
+
+  // Verify that spoken feedback is disabled.
+  chromeos::AccessibilityManager* accessibility_manager =
+      chromeos::AccessibilityManager::Get();
+  ASSERT_TRUE(accessibility_manager);
+  EXPECT_FALSE(accessibility_manager->IsSpokenFeedbackEnabled());
+}
+
+IN_PROC_BROWSER_TEST_F(LoginScreenDefaultPolicyInSessionBrowsertest,
+                       DeviceLoginScreenDefaultHighContrastEnabled) {
+  // Verifies that changing the default state of the high contrast mode
+  // accessibility feature on the login screen through policy does not affect
+  // its state in a session.
+
+  // Enable high contrast mode through device policy and wait for the change to
+  // take effect.
+  em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
+  proto.mutable_accessibility_settings()->
+      set_login_screen_default_high_contrast_enabled(true);
+  RefreshDevicePolicyAndWaitForPrefChange(prefs::kHighContrastEnabled);
+
+  // Verify that the pref which controls high contrast mode in the session is
+  // unchanged.
+  VerifyPrefFollowsDefault(prefs::kHighContrastEnabled);
+
+  // Verify that high contrast mode is disabled.
+  chromeos::AccessibilityManager* accessibility_manager =
+      chromeos::AccessibilityManager::Get();
+  ASSERT_TRUE(accessibility_manager);
+  EXPECT_FALSE(accessibility_manager->IsHighContrastEnabled());
+}
+
+IN_PROC_BROWSER_TEST_F(LoginScreenDefaultPolicyInSessionBrowsertest,
+                       DeviceLoginScreenDefaultScreenMagnifierType) {
+  // Verifies that changing the default screen magnifier type enabled on the
+  // login screen through policy does not affect its state in a session.
+
+  // Set the screen magnifier type through device policy and wait for the change
+  // to take effect.
+  em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
+  proto.mutable_accessibility_settings()->
+      set_login_screen_default_screen_magnifier_type(kFullScreenMagnifier);
+  RefreshDevicePolicyAndWaitForPrefChange(prefs::kScreenMagnifierType);
+
+  // Verify that the prefs which control the screen magnifier in the session are
+  // unchanged.
+  VerifyPrefFollowsDefault(prefs::kScreenMagnifierEnabled);
+  VerifyPrefFollowsDefault(prefs::kScreenMagnifierType);
+
+  // Verify that the screen magnifier is disabled.
+  chromeos::MagnificationManager* magnification_manager =
+      chromeos::MagnificationManager::Get();
+  ASSERT_TRUE(magnification_manager);
+  EXPECT_FALSE(magnification_manager->IsMagnifierEnabled());
+  EXPECT_EQ(ash::kDefaultMagnifierType,
+            magnification_manager->GetMagnifierType());
+}
+
+} // namespace policy
diff --git a/chrome/browser/chromeos/policy/network_configuration_updater_impl.cc b/chrome/browser/chromeos/policy/network_configuration_updater_impl.cc
index 54e4033..5fa896c 100644
--- a/chrome/browser/chromeos/policy/network_configuration_updater_impl.cc
+++ b/chrome/browser/chromeos/policy/network_configuration_updater_impl.cc
@@ -97,15 +97,24 @@
   ParseAndValidateOncForImport(
       onc_blob, onc_source, "", &network_configs, &certificates);
 
+  chromeos::CertificateHandler::CertsByGUID imported_server_and_ca_certs;
+  scoped_ptr<net::CertificateList> web_trust_certs(new net::CertificateList);
+  certificate_handler_->ImportCertificates(
+      certificates, onc_source, web_trust_certs.get(),
+      &imported_server_and_ca_certs);
+
+  if (!chromeos::onc::ResolveServerCertRefsInNetworks(
+          imported_server_and_ca_certs, &network_configs)) {
+    LOG(ERROR) << "Some certificate references in the ONC policy for source "
+               << chromeos::onc::GetSourceAsString(onc_source)
+               << " could not be resolved.";
+  }
+
   std::string userhash = onc_source == chromeos::onc::ONC_SOURCE_USER_POLICY ?
       hashed_username_ : std::string();
   chromeos::NetworkHandler::Get()->managed_network_configuration_handler()->
       SetPolicy(onc_source, userhash, network_configs);
 
-  scoped_ptr<net::CertificateList> web_trust_certs(new net::CertificateList);
-  certificate_handler_->ImportCertificates(
-      certificates, onc_source, web_trust_certs.get());
-
   if (onc_source == chromeos::onc::ONC_SOURCE_USER_POLICY)
     SetTrustAnchors(web_trust_certs.Pass());
 }
diff --git a/chrome/browser/chromeos/policy/network_configuration_updater_impl_cros.cc b/chrome/browser/chromeos/policy/network_configuration_updater_impl_cros.cc
index 41a9986..ea60fc2 100644
--- a/chrome/browser/chromeos/policy/network_configuration_updater_impl_cros.cc
+++ b/chrome/browser/chromeos/policy/network_configuration_updater_impl_cros.cc
@@ -165,11 +165,20 @@
   ParseAndValidateOncForImport(
       onc_blob, onc_source, "", &network_configs, &certificates);
 
-  network_library_->LoadOncNetworks(network_configs, onc_source);
-
+  chromeos::CertificateHandler::CertsByGUID imported_server_and_ca_certs;
   scoped_ptr<net::CertificateList> web_trust_certs(new net::CertificateList);
   certificate_handler_->ImportCertificates(
-      certificates, onc_source, web_trust_certs.get());
+      certificates, onc_source, web_trust_certs.get(),
+      &imported_server_and_ca_certs);
+
+  if (!chromeos::onc::ResolveServerCertRefsInNetworks(
+          imported_server_and_ca_certs, &network_configs)) {
+    LOG(ERROR) << "Some certificate references in the ONC policy for source "
+               << chromeos::onc::GetSourceAsString(onc_source)
+               << " could not be resolved.";
+  }
+
+  network_library_->LoadOncNetworks(network_configs, onc_source);
 
   if (onc_source == chromeos::onc::ONC_SOURCE_USER_POLICY)
     SetTrustAnchors(web_trust_certs.Pass());
diff --git a/chrome/browser/chromeos/policy/network_configuration_updater_impl_cros_unittest.cc b/chrome/browser/chromeos/policy/network_configuration_updater_impl_cros_unittest.cc
index b62bca7..afbdb9f 100644
--- a/chrome/browser/chromeos/policy/network_configuration_updater_impl_cros_unittest.cc
+++ b/chrome/browser/chromeos/policy/network_configuration_updater_impl_cros_unittest.cc
@@ -23,6 +23,7 @@
 #include "net/cert/cert_trust_anchor_provider.h"
 #include "net/cert/x509_certificate.h"
 #include "net/test/cert_test_util.h"
+#include "net/test/test_certificate_data.h"
 #include "policy/policy_constants.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -77,6 +78,11 @@
   return true;
 }
 
+ACTION_P(SetImportedCerts, map) {
+  *arg3 = map;
+  return true;
+}
+
 }  // namespace
 
 // Tests of NetworkConfigurationUpdaterImplCros
@@ -175,7 +181,7 @@
   EXPECT_CALL(network_library_, LoadOncNetworks(_, _));
   StrictMock<chromeos::MockCertificateHandler>* certificate_handler =
       new StrictMock<chromeos::MockCertificateHandler>();
-  EXPECT_CALL(*certificate_handler, ImportCertificates(_, _, _));
+  EXPECT_CALL(*certificate_handler, ImportCertificates(_, _, _, _));
 
   NetworkConfigurationUpdaterImplCros updater(
       policy_service_.get(),
@@ -191,7 +197,18 @@
   EXPECT_CALL(network_library_, LoadOncNetworks(
       IsEqualTo(network_configs_repaired),
       onc::ONC_SOURCE_USER_POLICY));
-  EXPECT_CALL(*certificate_handler, ImportCertificates(_, _, _)).Times(2);
+  EXPECT_CALL(*certificate_handler,
+              ImportCertificates(_, chromeos::onc::ONC_SOURCE_DEVICE_POLICY,
+                                 _, _));
+  scoped_refptr<net::X509Certificate> google_cert(
+      net::X509Certificate::CreateFromBytes(
+          reinterpret_cast<const char*>(google_der), sizeof(google_der)));
+  chromeos::CertificateHandler::CertsByGUID imported_certs;
+  imported_certs["test-ca"] = google_cert;
+  EXPECT_CALL(*certificate_handler,
+              ImportCertificates(_, chromeos::onc::ONC_SOURCE_USER_POLICY,
+                                 _, _))
+      .WillOnce(SetImportedCerts(imported_certs));
 
   EXPECT_CALL(network_library_, RemoveNetworkProfileObserver(_));
 
@@ -235,7 +252,7 @@
   StrictMock<chromeos::MockCertificateHandler>* certificate_handler =
       new StrictMock<chromeos::MockCertificateHandler>();
   EXPECT_CALL(*certificate_handler, ImportCertificates(
-      IsEqualTo(device_certs), onc::ONC_SOURCE_DEVICE_POLICY, _));
+      IsEqualTo(device_certs), onc::ONC_SOURCE_DEVICE_POLICY, _, _));
 
   NetworkConfigurationUpdaterImplCros updater(
       policy_service_.get(),
@@ -249,12 +266,12 @@
   EXPECT_CALL(network_library_, LoadOncNetworks(
       IsEqualTo(device_networks), onc::ONC_SOURCE_DEVICE_POLICY));
   EXPECT_CALL(*certificate_handler, ImportCertificates(
-      IsEqualTo(device_certs), onc::ONC_SOURCE_DEVICE_POLICY, _));
+      IsEqualTo(device_certs), onc::ONC_SOURCE_DEVICE_POLICY, _, _));
 
   EXPECT_CALL(network_library_, LoadOncNetworks(
       IsEqualTo(user_networks), onc::ONC_SOURCE_USER_POLICY));
   EXPECT_CALL(*certificate_handler, ImportCertificates(
-      IsEqualTo(user_certs), onc::ONC_SOURCE_USER_POLICY, _));
+      IsEqualTo(user_certs), onc::ONC_SOURCE_USER_POLICY, _, _));
 
   EXPECT_CALL(network_library_, RemoveNetworkProfileObserver(_));
 
@@ -279,7 +296,7 @@
   EXPECT_CALL(network_library_, LoadOncNetworks(_, _)).Times(AnyNumber());
   StrictMock<chromeos::MockCertificateHandler>* certificate_handler =
       new StrictMock<chromeos::MockCertificateHandler>();
-  EXPECT_CALL(*certificate_handler, ImportCertificates(_, _, _))
+  EXPECT_CALL(*certificate_handler, ImportCertificates(_, _, _, _))
       .WillRepeatedly(SetCertificateList(empty_cert_list));
   NetworkConfigurationUpdaterImplCros updater(
       policy_service_.get(),
@@ -302,11 +319,11 @@
   // Certificates with the "Web" trust flag set should be forwarded to the
   // trust provider.
   EXPECT_CALL(network_library_, LoadOncNetworks(_, _));
-  EXPECT_CALL(*certificate_handler, ImportCertificates(_, _, _))
+  EXPECT_CALL(*certificate_handler, ImportCertificates(_, _, _, _))
       .WillRepeatedly(SetCertificateList(empty_cert_list));
   onc::ONCSource current_source = NameToONCSource(GetParam());
   EXPECT_CALL(network_library_, LoadOncNetworks(_, current_source));
-  EXPECT_CALL(*certificate_handler, ImportCertificates(_, current_source, _))
+  EXPECT_CALL(*certificate_handler, ImportCertificates(_, current_source, _, _))
       .WillRepeatedly(SetCertificateList(cert_list));
   // Trigger a new policy load, and spin the IO message loop to pass the
   // certificates to the |trust_provider| on the IO thread.
@@ -336,7 +353,7 @@
       .Times(AnyNumber());
   StrictMock<chromeos::MockCertificateHandler>* certificate_handler =
       new StrictMock<chromeos::MockCertificateHandler>();
-  EXPECT_CALL(*certificate_handler, ImportCertificates(_, _, _))
+  EXPECT_CALL(*certificate_handler, ImportCertificates(_, _, _, _))
       .Times(AnyNumber());
   NetworkConfigurationUpdaterImplCros updater(
       policy_service_.get(),
@@ -350,7 +367,7 @@
   EXPECT_CALL(network_library_, LoadOncNetworks(
       IsEqualTo(fake_network_configs_.get()), NameToONCSource(GetParam())));
   EXPECT_CALL(*certificate_handler, ImportCertificates(
-      IsEqualTo(fake_certificates_.get()), NameToONCSource(GetParam()), _));
+      IsEqualTo(fake_certificates_.get()), NameToONCSource(GetParam()), _, _));
 
   // In the current implementation, we always apply both policies.
   EXPECT_CALL(network_library_, LoadOncNetworks(
@@ -359,7 +376,7 @@
   EXPECT_CALL(*certificate_handler, ImportCertificates(
       IsEqualTo(empty_certificates_.get()),
       Ne(NameToONCSource(GetParam())),
-      _));
+      _, _));
 
   PolicyMap policy;
   policy.Set(GetParam(), POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
@@ -376,7 +393,7 @@
   EXPECT_CALL(*certificate_handler, ImportCertificates(
       IsEqualTo(empty_certificates_.get()),
       onc::ONC_SOURCE_DEVICE_POLICY,
-      _));
+      _, _));
 
   EXPECT_CALL(network_library_, LoadOncNetworks(
       IsEqualTo(empty_network_configs_.get()),
@@ -384,7 +401,7 @@
   EXPECT_CALL(*certificate_handler, ImportCertificates(
       IsEqualTo(empty_certificates_.get()),
       onc::ONC_SOURCE_USER_POLICY,
-      _));
+      _, _));
 
   EXPECT_CALL(network_library_, RemoveNetworkProfileObserver(_));
 
diff --git a/chrome/browser/chromeos/policy/policy_cert_verifier_browsertest.cc b/chrome/browser/chromeos/policy/policy_cert_verifier_browsertest.cc
index aea0574..4f00bcf 100644
--- a/chrome/browser/chromeos/policy/policy_cert_verifier_browsertest.cc
+++ b/chrome/browser/chromeos/policy/policy_cert_verifier_browsertest.cc
@@ -152,7 +152,7 @@
 TEST_F(PolicyCertVerifierTest, VerifyTrustedCert) {
   // |ca_cert| is the issuer of |cert|.
   scoped_refptr<net::X509Certificate> ca_cert =
-      LoadCertificate("root_ca_cert.crt", net::CA_CERT);
+      LoadCertificate("root_ca_cert.pem", net::CA_CERT);
   ASSERT_TRUE(ca_cert.get());
   scoped_refptr<net::X509Certificate> cert =
       LoadCertificate("ok_cert.pem", net::SERVER_CERT);
@@ -206,7 +206,7 @@
 
   // |ca_cert| is the issuer of |cert|.
   scoped_refptr<net::X509Certificate> ca_cert =
-      LoadCertificate("root_ca_cert.crt", net::CA_CERT);
+      LoadCertificate("root_ca_cert.pem", net::CA_CERT);
   ASSERT_TRUE(ca_cert.get());
   scoped_refptr<net::X509Certificate> cert =
       LoadCertificate("ok_cert.pem", net::SERVER_CERT);
@@ -251,7 +251,7 @@
 
   // |ca_cert| is the issuer of |cert|.
   scoped_refptr<net::X509Certificate> ca_cert =
-      LoadCertificate("root_ca_cert.crt", net::CA_CERT);
+      LoadCertificate("root_ca_cert.pem", net::CA_CERT);
   ASSERT_TRUE(ca_cert.get());
   scoped_refptr<net::X509Certificate> cert =
       LoadCertificate("ok_cert.pem", net::SERVER_CERT);
diff --git a/chrome/browser/chromeos/policy/power_policy_browsertest.cc b/chrome/browser/chromeos/policy/power_policy_browsertest.cc
index 13889cc..72d4a44 100644
--- a/chrome/browser/chromeos/policy/power_policy_browsertest.cc
+++ b/chrome/browser/chromeos/policy/power_policy_browsertest.cc
@@ -84,10 +84,19 @@
 
   pm::PowerManagementPolicy power_management_policy =
       original_power_management_policy;
-  power_management_policy.set_idle_action(
+  power_management_policy.set_ac_idle_action(
       pm::PowerManagementPolicy::STOP_SESSION);
   SetUserPolicy(
-      key::kIdleAction,
+      key::kIdleActionAC,
+      base::Value::CreateIntegerValue(pm::PowerManagementPolicy::STOP_SESSION));
+  EXPECT_EQ(GetDebugString(power_management_policy),
+            GetDebugString(power_manager_client_->get_policy()));
+
+  power_management_policy = original_power_management_policy;
+  power_management_policy.set_battery_idle_action(
+      pm::PowerManagementPolicy::STOP_SESSION);
+  SetUserPolicy(
+      key::kIdleActionBattery,
       base::Value::CreateIntegerValue(pm::PowerManagementPolicy::STOP_SESSION));
   EXPECT_EQ(GetDebugString(power_management_policy),
             GetDebugString(power_manager_client_->get_policy()));
@@ -181,8 +190,8 @@
             GetDebugString(power_manager_client_->get_policy()));
 
   power_management_policy = original_power_management_policy;
-  power_management_policy.set_presentation_idle_delay_factor(3.0);
-  SetUserPolicy(key::kPresentationIdleDelayScale,
+  power_management_policy.set_presentation_screen_dim_delay_factor(3.0);
+  SetUserPolicy(key::kPresentationScreenDimDelayScale,
                 base::Value::CreateIntegerValue(300));
   EXPECT_EQ(GetDebugString(power_management_policy),
             GetDebugString(power_manager_client_->get_policy()));
@@ -211,7 +220,10 @@
   policy.mutable_ac_delays()->set_screen_off_ms(0);
   policy.mutable_battery_delays()->set_screen_dim_ms(0);
   policy.mutable_battery_delays()->set_screen_off_ms(0);
-  policy.set_idle_action(power_manager_client_->get_policy().idle_action());
+  policy.set_ac_idle_action(
+      power_manager_client_->get_policy().ac_idle_action());
+  policy.set_battery_idle_action(
+      power_manager_client_->get_policy().battery_idle_action());
   policy.set_reason(power_manager_client_->get_policy().reason());
   EXPECT_EQ(GetDebugString(policy),
             GetDebugString(power_manager_client_->get_policy()));
@@ -220,7 +232,10 @@
   SetUserPolicy(key::kAllowScreenWakeLocks,
                 base::Value::CreateBooleanValue(false));
   policy = baseline_policy;
-  policy.set_idle_action(power_manager_client_->get_policy().idle_action());
+  policy.set_ac_idle_action(
+      power_manager_client_->get_policy().ac_idle_action());
+  policy.set_battery_idle_action(
+      power_manager_client_->get_policy().battery_idle_action());
   policy.set_reason(power_manager_client_->get_policy().reason());
   EXPECT_EQ(GetDebugString(policy),
             GetDebugString(power_manager_client_->get_policy()));
diff --git a/chrome/browser/chromeos/policy/recommendation_restorer.cc b/chrome/browser/chromeos/policy/recommendation_restorer.cc
new file mode 100644
index 0000000..ba2945c
--- /dev/null
+++ b/chrome/browser/chromeos/policy/recommendation_restorer.cc
@@ -0,0 +1,153 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/policy/recommendation_restorer.h"
+
+#include "ash/shell.h"
+#include "ash/wm/user_activity_detector.h"
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/prefs/pref_service.h"
+#include "base/time/time.h"
+#include "base/values.h"
+#include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "chrome/common/pref_names.h"
+#include "content/public/browser/notification_details.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_source.h"
+
+namespace policy {
+
+namespace {
+// The amount of idle time after which recommended values are restored.
+const int kRestoreDelayInMs = 60 * 1000;  // 1 minute.
+}  // namespace
+
+RecommendationRestorer::RecommendationRestorer(Profile* profile)
+    : logged_in_(false) {
+  if (!chromeos::ProfileHelper::IsSigninProfile(profile))
+    return;
+
+  pref_change_registrar_.Init(profile->GetPrefs());
+  pref_change_registrar_.Add(prefs::kLargeCursorEnabled,
+                             base::Bind(&RecommendationRestorer::Restore,
+                                        base::Unretained(this), true));
+  pref_change_registrar_.Add(prefs::kSpokenFeedbackEnabled,
+                             base::Bind(&RecommendationRestorer::Restore,
+                                        base::Unretained(this), true));
+  pref_change_registrar_.Add(prefs::kHighContrastEnabled,
+                             base::Bind(&RecommendationRestorer::Restore,
+                                        base::Unretained(this), true));
+  pref_change_registrar_.Add(prefs::kScreenMagnifierEnabled,
+                             base::Bind(&RecommendationRestorer::Restore,
+                                        base::Unretained(this), true));
+  pref_change_registrar_.Add(prefs::kScreenMagnifierType,
+                             base::Bind(&RecommendationRestorer::Restore,
+                                        base::Unretained(this), true));
+
+  notification_registrar_.Add(this, chrome::NOTIFICATION_LOGIN_USER_CHANGED,
+                              content::NotificationService::AllSources());
+
+  RestoreAll();
+}
+
+RecommendationRestorer::~RecommendationRestorer() {
+}
+
+void RecommendationRestorer::Shutdown() {
+  StopTimer();
+  pref_change_registrar_.RemoveAll();
+  notification_registrar_.RemoveAll();
+}
+
+void RecommendationRestorer::Observe(
+    int type,
+    const content::NotificationSource& source,
+    const content::NotificationDetails& details) {
+  if (type == chrome::NOTIFICATION_LOGIN_USER_CHANGED) {
+    logged_in_ = true;
+    notification_registrar_.RemoveAll();
+    StopTimer();
+    RestoreAll();
+  } else {
+    NOTREACHED();
+  }
+}
+
+void RecommendationRestorer::OnUserActivity() {
+  if (restore_timer_.IsRunning())
+    restore_timer_.Reset();
+}
+
+void RecommendationRestorer::Restore(bool allow_delay,
+                                     const std::string& pref_name) {
+  const PrefService::Preference* pref =
+      pref_change_registrar_.prefs()->FindPreference(pref_name.c_str());
+  if (!pref) {
+    NOTREACHED();
+    return;
+  }
+
+  if (!pref->GetRecommendedValue() || !pref->HasUserSetting())
+    return;
+
+  if (logged_in_) {
+    allow_delay = false;
+  } else if (allow_delay && ash::Shell::HasInstance()) {
+    // Skip the delay if there has been no user input since the browser started.
+    const ash::UserActivityDetector* user_activity_detector =
+        ash::Shell::GetInstance()->user_activity_detector();
+    allow_delay = !user_activity_detector->last_activity_time().is_null();
+  }
+
+  if (allow_delay)
+    StartTimer();
+  else
+    pref_change_registrar_.prefs()->ClearPref(pref->name().c_str());
+}
+
+void RecommendationRestorer::RestoreAll() {
+  Restore(false, prefs::kLargeCursorEnabled);
+  Restore(false, prefs::kSpokenFeedbackEnabled);
+  Restore(false, prefs::kHighContrastEnabled);
+  Restore(false, prefs::kScreenMagnifierEnabled);
+  Restore(false, prefs::kScreenMagnifierType);
+}
+
+void RecommendationRestorer::StartTimer() {
+  // Listen for user activity so that the timer can be reset while the user is
+  // active, causing it to fire only when the user remains idle for
+  // |kRestoreDelayInMs|.
+  if (ash::Shell::HasInstance()) {
+    ash::UserActivityDetector* user_activity_detector =
+        ash::Shell::GetInstance()->user_activity_detector();
+    if (!user_activity_detector->HasObserver(this))
+      user_activity_detector->AddObserver(this);
+  }
+
+  // There should be a separate timer for each pref. However, in the common
+  // case of the user changing settings, a single timer is sufficient. This is
+  // because a change initiated by the user implies user activity, so that even
+  // if there was a separate timer per pref, they would all be reset at that
+  // point, causing them to fire at exactly the same time. In the much rarer
+  // case of a recommended value changing, a single timer is a close
+  // approximation of the behavior that would be obtained by resetting the timer
+  // for the affected pref only.
+  restore_timer_.Start(FROM_HERE,
+                       base::TimeDelta::FromMilliseconds(kRestoreDelayInMs),
+                       base::Bind(&RecommendationRestorer::RestoreAll,
+                                  base::Unretained(this)));
+}
+
+void RecommendationRestorer::StopTimer() {
+  restore_timer_.Stop();
+  if (ash::Shell::HasInstance())
+    ash::Shell::GetInstance()->user_activity_detector()->RemoveObserver(this);
+}
+
+}  // namespace policy
diff --git a/chrome/browser/chromeos/policy/recommendation_restorer.h b/chrome/browser/chromeos/policy/recommendation_restorer.h
new file mode 100644
index 0000000..1d67159
--- /dev/null
+++ b/chrome/browser/chromeos/policy/recommendation_restorer.h
@@ -0,0 +1,74 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_POLICY_RECOMMENDATION_RESTORER_H_
+#define CHROME_BROWSER_CHROMEOS_POLICY_RECOMMENDATION_RESTORER_H_
+
+#include <string>
+
+#include "ash/wm/user_activity_observer.h"
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/prefs/pref_change_registrar.h"
+#include "base/timer/timer.h"
+#include "components/browser_context_keyed_service/browser_context_keyed_service.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+
+class Profile;
+
+namespace policy {
+
+// Observes a set of prefs in the login profile. If any of the prefs has a
+// recommended value, its user setting is cleared so that the recommendation can
+// take effect. This happens immediately when the login screen is shown, when
+// a session is being started and whenever recommended values change during a
+// user session. On the login screen, user settings are cleared when the user
+// becomes idle for one minute.
+class RecommendationRestorer : public BrowserContextKeyedService,
+                               public content::NotificationObserver,
+                               public ash::UserActivityObserver {
+ public:
+  explicit RecommendationRestorer(Profile* profile);
+  virtual ~RecommendationRestorer();
+
+  // BrowserContextKeyedService:
+  virtual void Shutdown() OVERRIDE;
+
+  // content::NotificationObserver:
+  virtual void Observe(int type,
+                       const content::NotificationSource& source,
+                       const content::NotificationDetails& details) OVERRIDE;
+
+  // ash::UserActivityObserver::Observer:
+  virtual void OnUserActivity() OVERRIDE;
+
+  // If a recommended value and a user setting exist for |pref_name|, clears the
+  // user setting so that the recommended value can take effect. If
+  // |allow_delay| is |true| and the login screen is being shown, a timer is
+  // started that will clear the setting when the user becomes idle for one
+  // minute. Otherwise, the setting is cleared immediately.
+  void Restore(bool allow_delay, const std::string& pref_name);
+
+ private:
+  friend class RecommendationRestorerTest;
+
+  void RestoreAll();
+
+  void StartTimer();
+  void StopTimer();
+
+  PrefChangeRegistrar pref_change_registrar_;
+  content::NotificationRegistrar notification_registrar_;
+
+  bool logged_in_;
+
+  base::OneShotTimer<RecommendationRestorer> restore_timer_;
+
+  DISALLOW_COPY_AND_ASSIGN(RecommendationRestorer);
+};
+
+}  // namespace policy
+
+#endif  // CHROME_BROWSER_CHROMEOS_POLICY_RECOMMENDATION_RESTORER_H_
diff --git a/chrome/browser/chromeos/policy/recommendation_restorer_factory.cc b/chrome/browser/chromeos/policy/recommendation_restorer_factory.cc
new file mode 100644
index 0000000..59cab9a
--- /dev/null
+++ b/chrome/browser/chromeos/policy/recommendation_restorer_factory.cc
@@ -0,0 +1,45 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/policy/recommendation_restorer_factory.h"
+
+#include "chrome/browser/chromeos/policy/recommendation_restorer.h"
+#include "chrome/browser/profiles/profile.h"
+#include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
+#include "content/public/browser/browser_context.h"
+
+namespace policy {
+
+// static
+RecommendationRestorerFactory* RecommendationRestorerFactory::GetInstance() {
+  return Singleton<RecommendationRestorerFactory>::get();
+}
+
+// static
+RecommendationRestorer* RecommendationRestorerFactory::GetForProfile(
+    Profile* profile) {
+  return reinterpret_cast<RecommendationRestorer*>(
+          GetInstance()->GetServiceForBrowserContext(profile, false));
+}
+
+BrowserContextKeyedService*
+    RecommendationRestorerFactory::BuildServiceInstanceFor(
+        content::BrowserContext* context) const {
+  return new RecommendationRestorer(static_cast<Profile*>(context));
+}
+
+bool RecommendationRestorerFactory::ServiceIsCreatedWithBrowserContext() const {
+  return true;
+}
+
+RecommendationRestorerFactory::RecommendationRestorerFactory()
+    : BrowserContextKeyedServiceFactory(
+          "RecommendationRestorer",
+          BrowserContextDependencyManager::GetInstance()) {
+}
+
+RecommendationRestorerFactory::~RecommendationRestorerFactory() {
+}
+
+}  // namespace policy
diff --git a/chrome/browser/chromeos/policy/recommendation_restorer_factory.h b/chrome/browser/chromeos/policy/recommendation_restorer_factory.h
new file mode 100644
index 0000000..9b5cda2
--- /dev/null
+++ b/chrome/browser/chromeos/policy/recommendation_restorer_factory.h
@@ -0,0 +1,42 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_POLICY_RECOMMENDATION_RESTORER_FACTORY_H_
+#define CHROME_BROWSER_CHROMEOS_POLICY_RECOMMENDATION_RESTORER_FACTORY_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/singleton.h"
+#include "components/browser_context_keyed_service/browser_context_keyed_service_factory.h"
+
+class Profile;
+
+namespace policy {
+
+class RecommendationRestorer;
+
+class RecommendationRestorerFactory : public BrowserContextKeyedServiceFactory {
+ public:
+  static RecommendationRestorerFactory* GetInstance();
+
+  static RecommendationRestorer* GetForProfile(Profile* profile);
+
+ protected:
+  // BrowserContextKeyedServiceFactory:
+  virtual BrowserContextKeyedService* BuildServiceInstanceFor(
+      content::BrowserContext* context) const OVERRIDE;
+  virtual bool ServiceIsCreatedWithBrowserContext() const OVERRIDE;
+
+ private:
+  friend struct DefaultSingletonTraits<RecommendationRestorerFactory>;
+
+  RecommendationRestorerFactory();
+  virtual ~RecommendationRestorerFactory();
+
+  DISALLOW_COPY_AND_ASSIGN(RecommendationRestorerFactory);
+};
+
+} //  namespace policy
+
+#endif  // CHROME_BROWSER_CHROMEOS_POLICY_RECOMMENDATION_RESTORER_FACTORY_H_
diff --git a/chrome/browser/chromeos/policy/recommendation_restorer_unittest.cc b/chrome/browser/chromeos/policy/recommendation_restorer_unittest.cc
new file mode 100644
index 0000000..c5d5b3a
--- /dev/null
+++ b/chrome/browser/chromeos/policy/recommendation_restorer_unittest.cc
@@ -0,0 +1,485 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/policy/recommendation_restorer.h"
+
+#include "ash/magnifier/magnifier_constants.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/prefs/pref_notifier_impl.h"
+#include "base/prefs/testing_pref_store.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/test_simple_task_runner.h"
+#include "base/thread_task_runner_handle.h"
+#include "base/time/time.h"
+#include "base/values.h"
+#include "chrome/browser/chromeos/policy/recommendation_restorer_factory.h"
+#include "chrome/browser/prefs/browser_prefs.h"
+#include "chrome/browser/prefs/pref_service_syncable.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/base/testing_browser_process.h"
+#include "chrome/test/base/testing_pref_service_syncable.h"
+#include "chrome/test/base/testing_profile.h"
+#include "chrome/test/base/testing_profile_manager.h"
+#include "components/user_prefs/pref_registry_syncable.h"
+#include "content/public/browser/notification_details.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_source.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace policy {
+
+namespace {
+  // The amount of idle time after which recommended values are restored.
+  const int kRestoreDelayInMs = 60 * 1000;  // 1 minute.
+}  // namespace
+
+class RecommendationRestorerTest : public testing::Test {
+ protected:
+  RecommendationRestorerTest();
+
+  // testing::Test:
+  virtual void SetUp() OVERRIDE;
+
+  void SetRecommendedValues();
+  void SetUserSettings();
+
+  void CreateLoginProfile();
+  void CreateUserProfile();
+
+  void NotifyOfSessionStart();
+  void NotifyOfUserActivity();
+
+  void VerifyPrefFollowsUser(const char* pref_name,
+                             const base::Value& expected_value) const;
+  void VerifyPrefsFollowUser() const;
+  void VerifyPrefFollowsRecommendation(const char* pref_name,
+                                       const base::Value& expected_value) const;
+  void VerifyPrefsFollowRecommendations() const;
+
+  void VerifyNotListeningForNotifications() const;
+  void VerifyTimerIsStopped() const;
+  void VerifyTimerIsRunning() const;
+
+  TestingPrefStore* recommended_prefs_;  // Not owned.
+  TestingPrefServiceSyncable* prefs_;    // Not owned.
+  RecommendationRestorer* restorer_;     // Not owned.
+
+  scoped_refptr<base::TestSimpleTaskRunner> runner_;
+  base::ThreadTaskRunnerHandle runner_handler_;
+
+ private:
+  scoped_ptr<PrefServiceSyncable> prefs_owner_;
+
+  TestingProfileManager profile_manager_;
+
+  DISALLOW_COPY_AND_ASSIGN(RecommendationRestorerTest);
+};
+
+RecommendationRestorerTest::RecommendationRestorerTest()
+    : recommended_prefs_(new TestingPrefStore),
+      prefs_(new TestingPrefServiceSyncable(
+          new TestingPrefStore,
+          new TestingPrefStore,
+          recommended_prefs_,
+          new user_prefs::PrefRegistrySyncable,
+          new PrefNotifierImpl)),
+      restorer_(NULL),
+      runner_(new base::TestSimpleTaskRunner),
+      runner_handler_(runner_),
+      prefs_owner_(prefs_),
+      profile_manager_(TestingBrowserProcess::GetGlobal()) {
+  chrome::RegisterUserPrefs(prefs_->registry());
+}
+
+void RecommendationRestorerTest::SetUp() {
+  testing::Test::SetUp();
+  ASSERT_TRUE(profile_manager_.SetUp());
+}
+
+void RecommendationRestorerTest::SetRecommendedValues() {
+  recommended_prefs_->SetBoolean(prefs::kLargeCursorEnabled, false);
+  recommended_prefs_->SetBoolean(prefs::kSpokenFeedbackEnabled, false);
+  recommended_prefs_->SetBoolean(prefs::kHighContrastEnabled, false);
+  recommended_prefs_->SetBoolean(prefs::kScreenMagnifierEnabled, false);
+  recommended_prefs_->SetInteger(prefs::kScreenMagnifierType, 0);
+}
+
+void RecommendationRestorerTest::SetUserSettings() {
+  prefs_->SetBoolean(prefs::kLargeCursorEnabled, true);
+  prefs_->SetBoolean(prefs::kSpokenFeedbackEnabled, true);
+  prefs_->SetBoolean(prefs::kHighContrastEnabled, true);
+  prefs_->SetBoolean(prefs::kScreenMagnifierEnabled, true);
+  prefs_->SetInteger(prefs::kScreenMagnifierType, ash::MAGNIFIER_FULL);
+}
+
+void RecommendationRestorerTest::CreateLoginProfile() {
+  ASSERT_FALSE(restorer_);
+  TestingProfile* profile = profile_manager_.CreateTestingProfile(
+      chrome::kInitialProfile, prefs_owner_.Pass(),
+      UTF8ToUTF16(chrome::kInitialProfile), 0);
+  restorer_ = RecommendationRestorerFactory::GetForProfile(profile);
+  EXPECT_TRUE(restorer_);
+}
+
+void RecommendationRestorerTest::CreateUserProfile() {
+  ASSERT_FALSE(restorer_);
+  TestingProfile* profile = profile_manager_.CreateTestingProfile(
+      "user", prefs_owner_.Pass(), UTF8ToUTF16("user"), 0);
+  restorer_ = RecommendationRestorerFactory::GetForProfile(profile);
+  EXPECT_TRUE(restorer_);
+}
+
+void RecommendationRestorerTest::NotifyOfSessionStart() {
+  ASSERT_TRUE(restorer_);
+  restorer_->Observe(chrome::NOTIFICATION_LOGIN_USER_CHANGED,
+                     content::Source<RecommendationRestorerTest>(this),
+                     content::NotificationService::NoDetails());
+}
+
+void RecommendationRestorerTest::NotifyOfUserActivity() {
+  ASSERT_TRUE(restorer_);
+  restorer_->OnUserActivity();
+}
+
+void RecommendationRestorerTest::VerifyPrefFollowsUser(
+    const char* pref_name,
+    const base::Value& expected_value) const {
+  const PrefServiceSyncable::Preference* pref =
+      prefs_->FindPreference(pref_name);
+  ASSERT_TRUE(pref);
+  EXPECT_TRUE(pref->HasUserSetting());
+  const base::Value* value = pref->GetValue();
+  ASSERT_TRUE(value);
+  EXPECT_TRUE(expected_value.Equals(value));
+}
+
+void RecommendationRestorerTest::VerifyPrefsFollowUser() const {
+  VerifyPrefFollowsUser(prefs::kLargeCursorEnabled,
+                        base::FundamentalValue(true));
+  VerifyPrefFollowsUser(prefs::kSpokenFeedbackEnabled,
+                        base::FundamentalValue(true));
+  VerifyPrefFollowsUser(prefs::kHighContrastEnabled,
+                        base::FundamentalValue(true));
+  VerifyPrefFollowsUser(prefs::kScreenMagnifierEnabled,
+                        base::FundamentalValue(true));
+  VerifyPrefFollowsUser(prefs::kScreenMagnifierType,
+                        base::FundamentalValue(ash::MAGNIFIER_FULL));
+}
+
+void RecommendationRestorerTest::VerifyPrefFollowsRecommendation(
+    const char* pref_name,
+    const base::Value& expected_value) const {
+  const PrefServiceSyncable::Preference* pref =
+      prefs_->FindPreference(pref_name);
+  ASSERT_TRUE(pref);
+  EXPECT_TRUE(pref->IsRecommended());
+  EXPECT_FALSE(pref->HasUserSetting());
+  const base::Value* value = pref->GetValue();
+  ASSERT_TRUE(value);
+  EXPECT_TRUE(expected_value.Equals(value));
+}
+
+void RecommendationRestorerTest::VerifyPrefsFollowRecommendations() const {
+  VerifyPrefFollowsRecommendation(prefs::kLargeCursorEnabled,
+                                  base::FundamentalValue(false));
+  VerifyPrefFollowsRecommendation(prefs::kSpokenFeedbackEnabled,
+                                  base::FundamentalValue(false));
+  VerifyPrefFollowsRecommendation(prefs::kHighContrastEnabled,
+                                  base::FundamentalValue(false));
+  VerifyPrefFollowsRecommendation(prefs::kScreenMagnifierEnabled,
+                                  base::FundamentalValue(false));
+  VerifyPrefFollowsRecommendation(prefs::kScreenMagnifierType,
+                                  base::FundamentalValue(0));
+}
+
+void RecommendationRestorerTest::VerifyNotListeningForNotifications() const {
+  ASSERT_TRUE(restorer_);
+  EXPECT_TRUE(restorer_->pref_change_registrar_.IsEmpty());
+  EXPECT_TRUE(restorer_->notification_registrar_.IsEmpty());
+}
+
+void RecommendationRestorerTest::VerifyTimerIsStopped() const {
+  ASSERT_TRUE(restorer_);
+  EXPECT_FALSE(restorer_->restore_timer_.IsRunning());
+}
+
+void RecommendationRestorerTest::VerifyTimerIsRunning() const {
+  ASSERT_TRUE(restorer_);
+  EXPECT_TRUE(restorer_->restore_timer_.IsRunning());
+  EXPECT_EQ(base::TimeDelta::FromMilliseconds(kRestoreDelayInMs),
+            restorer_->restore_timer_.GetCurrentDelay());
+}
+
+TEST_F(RecommendationRestorerTest, CreateForUserProfile) {
+  // Verifies that when a RecommendationRestorer is created for a user profile,
+  // it does not start listening for any notifications, does not clear user
+  // settings on initialization and does not start a timer that will clear user
+  // settings eventually.
+  SetRecommendedValues();
+  SetUserSettings();
+
+  CreateUserProfile();
+  VerifyNotListeningForNotifications();
+  VerifyPrefsFollowUser();
+  VerifyTimerIsStopped();
+}
+
+TEST_F(RecommendationRestorerTest, NoRecommendations) {
+  // Verifies that when no recommended values have been set and a
+  // RecommendationRestorer is created for the login profile, it does not clear
+  // user settings on initialization and does not start a timer that will clear
+  // user settings eventually.
+  SetUserSettings();
+
+  CreateLoginProfile();
+  VerifyPrefsFollowUser();
+  VerifyTimerIsStopped();
+}
+
+TEST_F(RecommendationRestorerTest, RestoreOnStartup) {
+  // Verifies that when recommended values have been set and a
+  // RecommendationRestorer is created for the login profile, it clears user
+  // settings on initialization.
+  SetRecommendedValues();
+  SetUserSettings();
+
+  CreateLoginProfile();
+  VerifyPrefsFollowRecommendations();
+  VerifyTimerIsStopped();
+}
+
+TEST_F(RecommendationRestorerTest, RestoreOnRecommendationChangeOnLoginScreen) {
+  // Verifies that if recommended values change while the login screen is being
+  // shown, a timer is started that will clear user settings eventually.
+  SetUserSettings();
+
+  CreateLoginProfile();
+
+  VerifyTimerIsStopped();
+  recommended_prefs_->SetBoolean(prefs::kLargeCursorEnabled, false);
+  VerifyPrefFollowsUser(prefs::kLargeCursorEnabled,
+                        base::FundamentalValue(true));
+  VerifyTimerIsRunning();
+  runner_->RunUntilIdle();
+  VerifyPrefFollowsRecommendation(prefs::kLargeCursorEnabled,
+                                  base::FundamentalValue(false));
+
+  VerifyTimerIsStopped();
+  recommended_prefs_->SetBoolean(prefs::kSpokenFeedbackEnabled, false);
+  VerifyPrefFollowsUser(prefs::kSpokenFeedbackEnabled,
+                        base::FundamentalValue(true));
+  VerifyTimerIsRunning();
+  runner_->RunUntilIdle();
+  VerifyPrefFollowsRecommendation(prefs::kSpokenFeedbackEnabled,
+                                  base::FundamentalValue(false));
+
+  VerifyTimerIsStopped();
+  recommended_prefs_->SetBoolean(prefs::kHighContrastEnabled, false);
+  VerifyPrefFollowsUser(prefs::kHighContrastEnabled,
+                        base::FundamentalValue(true));
+  VerifyTimerIsRunning();
+  runner_->RunUntilIdle();
+  VerifyPrefFollowsRecommendation(prefs::kHighContrastEnabled,
+                                  base::FundamentalValue(false));
+
+  VerifyTimerIsStopped();
+  recommended_prefs_->SetBoolean(prefs::kScreenMagnifierEnabled, false);
+  recommended_prefs_->SetInteger(prefs::kScreenMagnifierType, 0);
+  VerifyPrefFollowsUser(prefs::kScreenMagnifierEnabled,
+                        base::FundamentalValue(true));
+  VerifyPrefFollowsUser(prefs::kScreenMagnifierType,
+                        base::FundamentalValue(ash::MAGNIFIER_FULL));
+  VerifyTimerIsRunning();
+  runner_->RunUntilIdle();
+  VerifyPrefFollowsRecommendation(prefs::kScreenMagnifierEnabled,
+                                  base::FundamentalValue(false));
+  VerifyPrefFollowsRecommendation(prefs::kScreenMagnifierType,
+                                  base::FundamentalValue(0));
+
+  VerifyTimerIsStopped();
+}
+
+TEST_F(RecommendationRestorerTest, RestoreOnRecommendationChangeInUserSession) {
+  // Verifies that if recommended values change while a user session is in
+  // progress, user settings are cleared immediately.
+  SetUserSettings();
+
+  CreateLoginProfile();
+  NotifyOfSessionStart();
+
+  VerifyPrefFollowsUser(prefs::kLargeCursorEnabled,
+                        base::FundamentalValue(true));
+  recommended_prefs_->SetBoolean(prefs::kLargeCursorEnabled, false);
+  VerifyTimerIsStopped();
+  VerifyPrefFollowsRecommendation(prefs::kLargeCursorEnabled,
+                                  base::FundamentalValue(false));
+
+  VerifyPrefFollowsUser(prefs::kSpokenFeedbackEnabled,
+                        base::FundamentalValue(true));
+  recommended_prefs_->SetBoolean(prefs::kSpokenFeedbackEnabled, false);
+  VerifyTimerIsStopped();
+  VerifyPrefFollowsRecommendation(prefs::kSpokenFeedbackEnabled,
+                                  base::FundamentalValue(false));
+
+  VerifyPrefFollowsUser(prefs::kHighContrastEnabled,
+                        base::FundamentalValue(true));
+  recommended_prefs_->SetBoolean(prefs::kHighContrastEnabled, false);
+  VerifyTimerIsStopped();
+  VerifyPrefFollowsRecommendation(prefs::kHighContrastEnabled,
+                                  base::FundamentalValue(false));
+
+  VerifyPrefFollowsUser(prefs::kScreenMagnifierEnabled,
+                        base::FundamentalValue(true));
+  VerifyPrefFollowsUser(prefs::kScreenMagnifierType,
+                        base::FundamentalValue(ash::MAGNIFIER_FULL));
+  recommended_prefs_->SetBoolean(prefs::kScreenMagnifierEnabled, false);
+  recommended_prefs_->SetInteger(prefs::kScreenMagnifierType, 0);
+  VerifyTimerIsStopped();
+  VerifyPrefFollowsRecommendation(prefs::kScreenMagnifierEnabled,
+                                  base::FundamentalValue(false));
+  VerifyPrefFollowsRecommendation(prefs::kScreenMagnifierType,
+                                  base::FundamentalValue(0));
+}
+
+TEST_F(RecommendationRestorerTest, DoNothingOnUserChange) {
+  // Verifies that if no recommended values have been set and user settings
+  // change, the user settings are not cleared immediately and no timer is
+  // started that will clear the user settings eventually.
+  CreateLoginProfile();
+
+  prefs_->SetBoolean(prefs::kLargeCursorEnabled, true);
+  VerifyPrefFollowsUser(prefs::kLargeCursorEnabled,
+                        base::FundamentalValue(true));
+  VerifyTimerIsStopped();
+
+  prefs_->SetBoolean(prefs::kSpokenFeedbackEnabled, true);
+  VerifyPrefFollowsUser(prefs::kSpokenFeedbackEnabled,
+                        base::FundamentalValue(true));
+  VerifyTimerIsStopped();
+
+  prefs_->SetBoolean(prefs::kHighContrastEnabled, true);
+  VerifyPrefFollowsUser(prefs::kHighContrastEnabled,
+                        base::FundamentalValue(true));
+  VerifyTimerIsStopped();
+
+  prefs_->SetBoolean(prefs::kScreenMagnifierEnabled, true);
+  VerifyPrefFollowsUser(prefs::kScreenMagnifierEnabled,
+                        base::FundamentalValue(true));
+  VerifyTimerIsStopped();
+
+  prefs_->SetBoolean(prefs::kScreenMagnifierEnabled, true);
+  prefs_->SetInteger(prefs::kScreenMagnifierType, ash::MAGNIFIER_FULL);
+  VerifyPrefFollowsUser(prefs::kScreenMagnifierEnabled,
+                        base::FundamentalValue(true));
+  VerifyPrefFollowsUser(prefs::kScreenMagnifierType,
+                        base::FundamentalValue(ash::MAGNIFIER_FULL));
+  VerifyTimerIsStopped();
+}
+
+TEST_F(RecommendationRestorerTest, RestoreOnUserChange) {
+  // Verifies that if recommended values have been set and user settings change
+  // while the login screen is being shown, a timer is started that will clear
+  // the user settings eventually.
+  SetRecommendedValues();
+
+  CreateLoginProfile();
+
+  VerifyTimerIsStopped();
+  prefs_->SetBoolean(prefs::kLargeCursorEnabled, true);
+  VerifyPrefFollowsUser(prefs::kLargeCursorEnabled,
+                        base::FundamentalValue(true));
+  VerifyTimerIsRunning();
+  runner_->RunUntilIdle();
+  VerifyPrefFollowsRecommendation(prefs::kLargeCursorEnabled,
+                                  base::FundamentalValue(false));
+
+  VerifyTimerIsStopped();
+  prefs_->SetBoolean(prefs::kSpokenFeedbackEnabled, true);
+  VerifyPrefFollowsUser(prefs::kSpokenFeedbackEnabled,
+                        base::FundamentalValue(true));
+  VerifyTimerIsRunning();
+  runner_->RunUntilIdle();
+  VerifyPrefFollowsRecommendation(prefs::kSpokenFeedbackEnabled,
+                                  base::FundamentalValue(false));
+
+  VerifyTimerIsStopped();
+  prefs_->SetBoolean(prefs::kHighContrastEnabled, true);
+  VerifyPrefFollowsUser(prefs::kHighContrastEnabled,
+                        base::FundamentalValue(true));
+  VerifyTimerIsRunning();
+  runner_->RunUntilIdle();
+  VerifyPrefFollowsRecommendation(prefs::kHighContrastEnabled,
+                                  base::FundamentalValue(false));
+
+  VerifyTimerIsStopped();
+  prefs_->SetBoolean(prefs::kScreenMagnifierEnabled, true);
+  prefs_->SetInteger(prefs::kScreenMagnifierType, ash::MAGNIFIER_FULL);
+  VerifyPrefFollowsUser(prefs::kScreenMagnifierEnabled,
+                        base::FundamentalValue(true));
+  VerifyPrefFollowsUser(prefs::kScreenMagnifierType,
+                        base::FundamentalValue(ash::MAGNIFIER_FULL));
+  VerifyTimerIsRunning();
+  runner_->RunUntilIdle();
+  VerifyPrefFollowsRecommendation(prefs::kScreenMagnifierEnabled,
+                                  base::FundamentalValue(false));
+  VerifyPrefFollowsRecommendation(prefs::kScreenMagnifierType,
+                                  base::FundamentalValue(0));
+
+  VerifyTimerIsStopped();
+}
+
+TEST_F(RecommendationRestorerTest, RestoreOnSessionStart) {
+  // Verifies that if recommended values have been set, user settings have
+  // changed and a session is then started, the user settings are cleared
+  // immediately and the timer that would have cleared them eventually on the
+  // login screen is stopped.
+  SetRecommendedValues();
+
+  CreateLoginProfile();
+  SetUserSettings();
+
+  NotifyOfSessionStart();
+  VerifyPrefsFollowRecommendations();
+  VerifyTimerIsStopped();
+}
+
+TEST_F(RecommendationRestorerTest, DoNothingOnSessionStart) {
+  // Verifies that if recommended values have not been set, user settings have
+  // changed and a session is then started, the user settings are not cleared
+  // immediately.
+  CreateLoginProfile();
+  SetUserSettings();
+
+  NotifyOfSessionStart();
+  VerifyPrefsFollowUser();
+  VerifyTimerIsStopped();
+}
+
+TEST_F(RecommendationRestorerTest, UserActivityResetsTimer) {
+  // Verifies that user activity resets the timer which clears user settings.
+  recommended_prefs_->SetBoolean(prefs::kLargeCursorEnabled, false);
+
+  CreateLoginProfile();
+
+  prefs_->SetBoolean(prefs::kLargeCursorEnabled, true);
+  VerifyTimerIsRunning();
+
+  // Notify that there is user activity, then fast forward until the originally
+  // set timer fires.
+  NotifyOfUserActivity();
+  runner_->RunPendingTasks();
+  VerifyPrefFollowsUser(prefs::kLargeCursorEnabled,
+                        base::FundamentalValue(true));
+
+  // Fast forward until the reset timer fires.
+  VerifyTimerIsRunning();
+  runner_->RunUntilIdle();
+  VerifyPrefFollowsRecommendation(prefs::kLargeCursorEnabled,
+                                  base::FundamentalValue(false));
+  VerifyTimerIsStopped();
+}
+
+}  // namespace policy
diff --git a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_unittest.cc b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_unittest.cc
index 1beca08..fce36a9 100644
--- a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_unittest.cc
+++ b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_unittest.cc
@@ -24,6 +24,7 @@
 #include "chrome/browser/policy/mock_configuration_policy_provider.h"
 #include "chrome/browser/policy/proto/cloud/device_management_backend.pb.h"
 #include "chrome/browser/prefs/browser_prefs.h"
+#include "chrome/browser/prefs/pref_service_syncable.h"
 #include "chrome/browser/signin/token_service.h"
 #include "chrome/browser/signin/token_service_factory.h"
 #include "chrome/common/chrome_constants.h"
@@ -85,7 +86,8 @@
         new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
     ASSERT_TRUE(profile_manager_->SetUp());
     profile_ = profile_manager_->CreateTestingProfile(
-        chrome::kInitialProfile, UTF8ToUTF16("testing_profile"), 0);
+        chrome::kInitialProfile, scoped_ptr<PrefServiceSyncable>(),
+        UTF8ToUTF16("testing_profile"), 0);
     signin_profile_ = profile_manager_->CreateTestingProfile("signin_profile");
     signin_profile_->set_incognito(true);
     // Usually the signin Profile and the main Profile are separate, but since
diff --git a/chrome/browser/chromeos/policy/user_cloud_policy_store_chromeos.cc b/chrome/browser/chromeos/policy/user_cloud_policy_store_chromeos.cc
index 884cda0..ae9b79c 100644
--- a/chrome/browser/chromeos/policy/user_cloud_policy_store_chromeos.cc
+++ b/chrome/browser/chromeos/policy/user_cloud_policy_store_chromeos.cc
@@ -409,7 +409,7 @@
 // static
 void UserCloudPolicyStoreChromeOS::RemoveLegacyCacheDir(
     const base::FilePath& dir) {
-  if (file_util::PathExists(dir) && !file_util::Delete(dir, true))
+  if (file_util::PathExists(dir) && !base::Delete(dir, true))
     LOG(ERROR) << "Failed to remove cache dir " << dir.value();
 }
 
diff --git a/chrome/browser/chromeos/policy/user_cloud_policy_store_chromeos_unittest.cc b/chrome/browser/chromeos/policy/user_cloud_policy_store_chromeos_unittest.cc
index 9cb2b9c..ec73418 100644
--- a/chrome/browser/chromeos/policy/user_cloud_policy_store_chromeos_unittest.cc
+++ b/chrome/browser/chromeos/policy/user_cloud_policy_store_chromeos_unittest.cc
@@ -239,7 +239,7 @@
 
 TEST_F(UserCloudPolicyStoreChromeOSTest, InitialStore) {
   // Start without any public key to trigger the initial key checks.
-  ASSERT_TRUE(file_util::Delete(user_policy_key_file(), false));
+  ASSERT_TRUE(base::Delete(user_policy_key_file(), false));
   // Make the policy blob contain a new public key.
   policy_.set_new_signing_key(PolicyBuilder::CreateTestNewSigningKey());
   policy_.Build();
@@ -383,7 +383,7 @@
 
 TEST_F(UserCloudPolicyStoreChromeOSTest, LoadNoKey) {
   // The loaded policy can't be verified without the public key.
-  ASSERT_TRUE(file_util::Delete(user_policy_key_file(), false));
+  ASSERT_TRUE(base::Delete(user_policy_key_file(), false));
   ExpectError(CloudPolicyStore::STATUS_VALIDATION_ERROR);
   ASSERT_NO_FATAL_FAILURE(PerformPolicyLoad(policy_.GetBlob()));
   VerifyStoreHasValidationError();
@@ -480,7 +480,7 @@
 
 TEST_F(UserCloudPolicyStoreChromeOSTest, MigrationAndStoreNew) {
   // Start without an existing public key.
-  ASSERT_TRUE(file_util::Delete(user_policy_key_file(), false));
+  ASSERT_TRUE(base::Delete(user_policy_key_file(), false));
 
   std::string data;
   em::CachedCloudPolicyResponse cached_policy;
diff --git a/chrome/browser/chromeos/power/suspend_observer.cc b/chrome/browser/chromeos/power/suspend_observer.cc
index fd7eb21..3ae7f11 100644
--- a/chrome/browser/chromeos/power/suspend_observer.cc
+++ b/chrome/browser/chromeos/power/suspend_observer.cc
@@ -39,8 +39,7 @@
   if (profile && profile->GetPrefs()->GetBoolean(prefs::kEnableScreenLock) &&
       UserManager::Get()->CanCurrentUserLock() && !screen_locked_) {
     screen_lock_callback_ = power_client_->GetSuspendReadinessCallback();
-    // TODO(antrim) : additional logging for crbug/173178
-    LOG(WARNING) << "Requesting screen lock from SuspendObserver";
+    VLOG(1) << "Requesting screen lock from SuspendObserver";
     session_client_->RequestLockScreen();
   }
 
@@ -53,14 +52,14 @@
 
   // Stop blocking suspend after the screen is locked.
   if (!screen_lock_callback_.is_null()) {
-    LOG(WARNING) << "Locking screen due to suspend.";
+    VLOG(1) << "Screen locked due to suspend";
     // Run the callback asynchronously.  ScreenIsLocked() is currently
     // called asynchronously after RequestLockScreen(), but this guards
     // against it being made synchronous later.
     base::MessageLoop::current()->PostTask(FROM_HERE, screen_lock_callback_);
     screen_lock_callback_.Reset();
   } else {
-    LOG(WARNING) << "Locking screen without suspend.";
+    VLOG(1) << "Screen locked without suspend";
   }
 }
 
diff --git a/chrome/browser/chromeos/power/user_activity_notifier.h b/chrome/browser/chromeos/power/user_activity_notifier.h
index 0e96e54..f1189ef 100644
--- a/chrome/browser/chromeos/power/user_activity_notifier.h
+++ b/chrome/browser/chromeos/power/user_activity_notifier.h
@@ -8,7 +8,7 @@
 #include "ash/wm/user_activity_observer.h"
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
-#include "base/time.h"
+#include "base/time/time.h"
 
 namespace chromeos {
 
diff --git a/chrome/browser/chromeos/power/video_activity_notifier.cc b/chrome/browser/chromeos/power/video_activity_notifier.cc
index a92dcac..3f0698c 100644
--- a/chrome/browser/chromeos/power/video_activity_notifier.cc
+++ b/chrome/browser/chromeos/power/video_activity_notifier.cc
@@ -29,8 +29,8 @@
   base::TimeTicks now = base::TimeTicks::Now();
   if (last_notify_time_.is_null() ||
       (now - last_notify_time_).InSeconds() >= kNotifyIntervalSec) {
-    DBusThreadManager::Get()->GetPowerManagerClient()->
-        NotifyVideoActivity(now, is_fullscreen);
+    DBusThreadManager::Get()->GetPowerManagerClient()->NotifyVideoActivity(
+        is_fullscreen);
     last_notify_time_ = now;
   }
 }
diff --git a/chrome/browser/chromeos/power/video_activity_notifier.h b/chrome/browser/chromeos/power/video_activity_notifier.h
index 9ba22d9..ffe2a2c 100644
--- a/chrome/browser/chromeos/power/video_activity_notifier.h
+++ b/chrome/browser/chromeos/power/video_activity_notifier.h
@@ -8,7 +8,7 @@
 #include "ash/wm/video_detector.h"
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
-#include "base/time.h"
+#include "base/time/time.h"
 
 namespace chromeos {
 
diff --git a/chrome/browser/chromeos/preferences.cc b/chrome/browser/chromeos/preferences.cc
index 41b3e64..c73dadf 100644
--- a/chrome/browser/chromeos/preferences.cc
+++ b/chrome/browser/chromeos/preferences.cc
@@ -370,7 +370,11 @@
       600000,
       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
   registry->RegisterIntegerPref(
-      prefs::kPowerIdleAction,
+      prefs::kPowerAcIdleAction,
+      PowerPolicyController::ACTION_SUSPEND,
+      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+  registry->RegisterIntegerPref(
+      prefs::kPowerBatteryIdleAction,
       PowerPolicyController::ACTION_SUSPEND,
       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
   registry->RegisterIntegerPref(
@@ -390,10 +394,6 @@
       true,
       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
   registry->RegisterDoublePref(
-      prefs::kPowerPresentationIdleDelayFactor,
-      2.0,
-      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
-  registry->RegisterDoublePref(
       prefs::kPowerPresentationScreenDimDelayFactor,
       2.0,
       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
@@ -525,7 +525,9 @@
       prefs::kPowerBatteryIdleWarningDelayMs, prefs, callback);
   power_battery_idle_delay_ms_.Init(
       prefs::kPowerBatteryIdleDelayMs, prefs, callback);
-  power_idle_action_.Init(prefs::kPowerIdleAction, prefs, callback);
+  power_ac_idle_action_.Init(prefs::kPowerAcIdleAction, prefs, callback);
+  power_battery_idle_action_.Init(
+      prefs::kPowerBatteryIdleAction, prefs, callback);
   power_lid_closed_action_.Init(prefs::kPowerLidClosedAction, prefs, callback);
   power_use_audio_activity_.Init(
       prefs::kPowerUseAudioActivity, prefs, callback);
@@ -625,22 +627,26 @@
     const int sensitivity = mouse_sensitivity_.GetValue();
     system::mouse_settings::SetSensitivity(sensitivity);
     if (pref_name) {
-      UMA_HISTOGRAM_CUSTOM_COUNTS(
-          "Mouse.Sensitivity.Changed", sensitivity, 1, 5, 5);
+      UMA_HISTOGRAM_ENUMERATION("Mouse.PointerSensitivity.Changed",
+                                sensitivity,
+                                system::kMaxPointerSensitivity + 1);
     } else {
-      UMA_HISTOGRAM_CUSTOM_COUNTS(
-          "Mouse.Sensitivity.Started", sensitivity, 1, 5, 5);
+      UMA_HISTOGRAM_ENUMERATION("Mouse.PointerSensitivity.Started",
+                                sensitivity,
+                                system::kMaxPointerSensitivity + 1);
     }
   }
   if (!pref_name || *pref_name == prefs::kTouchpadSensitivity) {
     const int sensitivity = touchpad_sensitivity_.GetValue();
     system::touchpad_settings::SetSensitivity(sensitivity);
     if (pref_name) {
-      UMA_HISTOGRAM_CUSTOM_COUNTS(
-          "Touchpad.Sensitivity.Changed", sensitivity, 1, 5, 5);
+      UMA_HISTOGRAM_ENUMERATION("Touchpad.PointerSensitivity.Changed",
+                                sensitivity,
+                                system::kMaxPointerSensitivity + 1);
     } else {
-      UMA_HISTOGRAM_CUSTOM_COUNTS(
-          "Touchpad.Sensitivity.Started", sensitivity, 1, 5, 5);
+      UMA_HISTOGRAM_ENUMERATION("Touchpad.PointerSensitivity.Started",
+                                sensitivity,
+                                system::kMaxPointerSensitivity + 1);
     }
   }
   if (!pref_name || *pref_name == prefs::kPrimaryMouseButtonRight) {
@@ -733,6 +739,7 @@
   // Do not check |*pref_name| of the prefs for remembering current/previous
   // input methods here. We're only interested in initial values of the prefs.
 
+  // TODO(nona): remove all IME preference entries. crbug.com/256102
   for (size_t i = 0; i < language_prefs::kNumChewingBooleanPrefs; ++i) {
     if (!pref_name ||
         *pref_name == language_prefs::kChewingBooleanPrefs[i].pref_name) {
@@ -770,9 +777,13 @@
   }
   if (!pref_name ||
       *pref_name == prefs::kLanguageHangulKeyboard) {
-    SetLanguageConfigString(language_prefs::kHangulSectionName,
-                            language_prefs::kHangulKeyboardConfigName,
-                            hangul_keyboard_.GetValue());
+    std::vector<std::string> new_input_method_ids;
+    if (input_method_manager_->MigrateKoreanKeyboard(
+            hangul_keyboard_.GetValue(),
+            &new_input_method_ids)) {
+      preload_engines_.SetValue(JoinString(new_input_method_ids, ','));
+      hangul_keyboard_.SetValue("dummy_value_already_migrated");
+    }
   }
   if (!pref_name || *pref_name == prefs::kLanguageHangulHanjaBindingKeys) {
     SetLanguageConfigString(language_prefs::kHangulSectionName,
@@ -855,7 +866,8 @@
       *pref_name == prefs::kPowerBatteryScreenLockDelayMs ||
       *pref_name == prefs::kPowerBatteryIdleWarningDelayMs ||
       *pref_name == prefs::kPowerBatteryIdleDelayMs ||
-      *pref_name == prefs::kPowerIdleAction ||
+      *pref_name == prefs::kPowerAcIdleAction ||
+      *pref_name == prefs::kPowerBatteryIdleAction ||
       *pref_name == prefs::kPowerLidClosedAction ||
       *pref_name == prefs::kPowerUseAudioActivity ||
       *pref_name == prefs::kPowerUseVideoActivity ||
@@ -879,8 +891,10 @@
     values.battery_idle_warning_delay_ms =
         power_battery_idle_warning_delay_ms_.GetValue();
     values.battery_idle_delay_ms = power_battery_idle_delay_ms_.GetValue();
-    values.idle_action = static_cast<PowerPolicyController::Action>(
-        power_idle_action_.GetValue());
+    values.ac_idle_action = static_cast<PowerPolicyController::Action>(
+        power_ac_idle_action_.GetValue());
+    values.battery_idle_action = static_cast<PowerPolicyController::Action>(
+        power_battery_idle_action_.GetValue());
     values.lid_closed_action = static_cast<PowerPolicyController::Action>(
         power_lid_closed_action_.GetValue());
     values.use_audio_activity = power_use_audio_activity_.GetValue();
diff --git a/chrome/browser/chromeos/preferences.h b/chrome/browser/chromeos/preferences.h
index e23c051..e1e3c81 100644
--- a/chrome/browser/chromeos/preferences.h
+++ b/chrome/browser/chromeos/preferences.h
@@ -180,7 +180,8 @@
   IntegerPrefMember power_battery_screen_lock_delay_ms_;
   IntegerPrefMember power_battery_idle_warning_delay_ms_;
   IntegerPrefMember power_battery_idle_delay_ms_;
-  IntegerPrefMember power_idle_action_;
+  IntegerPrefMember power_ac_idle_action_;
+  IntegerPrefMember power_battery_idle_action_;
   IntegerPrefMember power_lid_closed_action_;
   BooleanPrefMember power_use_audio_activity_;
   BooleanPrefMember power_use_video_activity_;
diff --git a/chrome/browser/chromeos/profiles/profile_helper.cc b/chrome/browser/chromeos/profiles/profile_helper.cc
index c94cf27..3d83458 100644
--- a/chrome/browser/chromeos/profiles/profile_helper.cc
+++ b/chrome/browser/chromeos/profiles/profile_helper.cc
@@ -19,6 +19,16 @@
 
 namespace chromeos {
 
+namespace {
+
+base::FilePath GetSigninProfileDir() {
+  ProfileManager* profile_manager = g_browser_process->profile_manager();
+  base::FilePath user_data_dir = profile_manager->user_data_dir();
+  return user_data_dir.AppendASCII(chrome::kInitialProfile);
+}
+
+}  // anonymous namespace
+
 ////////////////////////////////////////////////////////////////////////////////
 // ProfileHelper, public
 
@@ -61,10 +71,7 @@
 // static
 Profile* ProfileHelper::GetSigninProfile() {
   ProfileManager* profile_manager = g_browser_process->profile_manager();
-  base::FilePath user_data_dir = profile_manager->user_data_dir();
-  base::FilePath signin_profile_dir =
-      user_data_dir.AppendASCII(chrome::kInitialProfile);
-  return profile_manager->GetProfile(signin_profile_dir)->
+  return profile_manager->GetProfile(GetSigninProfileDir())->
       GetOffTheRecordProfile();
 }
 
@@ -123,6 +130,12 @@
   on_clear_callbacks_.push_back(on_clear_callback);
   if (signin_profile_clear_requested_)
     return;
+  ProfileManager* profile_manager = g_browser_process->profile_manager();
+  // Check if signin profile was loaded.
+  if (!profile_manager->GetProfileByPath(GetSigninProfileDir())) {
+    OnBrowsingDataRemoverDone();
+    return;
+  }
   signin_profile_clear_requested_ = true;
   BrowsingDataRemover* remover =
       BrowsingDataRemover::CreateForUnboundedRange(GetSigninProfile());
diff --git a/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc b/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc
index b3f48c0..feffd4d 100644
--- a/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc
+++ b/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc
@@ -245,14 +245,11 @@
 
     service_test->AddService("stub_wifi2", "wifi2_PSK",
                              flimflam::kTypeWifi, flimflam::kStateOnline,
-                             true /* add to watchlist */);
+                             true /* visible */, true /* watch */);
     service_test->SetServiceProperty("stub_wifi2",
                                      flimflam::kGuidProperty,
                                      base::StringValue("stub_wifi2"));
-    service_test->SetServiceProperty("stub_wifi2",
-                                     flimflam::kProfileProperty,
-                                     base::StringValue(kUserProfilePath));
-    profile_test->AddService("stub_wifi2");
+    profile_test->AddService(kUserProfilePath, "stub_wifi2");
 
     loop_.RunUntilIdle();
   }
diff --git a/chrome/browser/chromeos/screensaver/screensaver_controller.h b/chrome/browser/chromeos/screensaver/screensaver_controller.h
index 36e9877..1223415 100644
--- a/chrome/browser/chromeos/screensaver/screensaver_controller.h
+++ b/chrome/browser/chromeos/screensaver/screensaver_controller.h
@@ -11,7 +11,7 @@
 #include "base/basictypes.h"
 #include "base/gtest_prod_util.h"
 #include "base/memory/weak_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chromeos/dbus/power_manager_client.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
diff --git a/chrome/browser/chromeos/session_length_limiter.h b/chrome/browser/chromeos/session_length_limiter.h
index f634000..8c6d089 100644
--- a/chrome/browser/chromeos/session_length_limiter.h
+++ b/chrome/browser/chromeos/session_length_limiter.h
@@ -9,8 +9,8 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/prefs/pref_change_registrar.h"
 #include "base/threading/thread_checker.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 
 class PrefService;
 class PrefRegistrySimple;
diff --git a/chrome/browser/chromeos/settings/cros_settings_names.cc b/chrome/browser/chromeos/settings/cros_settings_names.cc
index b9dedf3..0468c6c 100644
--- a/chrome/browser/chromeos/settings/cros_settings_names.cc
+++ b/chrome/browser/chromeos/settings/cros_settings_names.cc
@@ -32,6 +32,8 @@
     "cros.accounts.deviceLocalAccountAutoLoginDelay";
 const char kAccountsPrefDeviceLocalAccountAutoLoginBailoutEnabled[] =
     "cros.accounts.deviceLocalAccountAutoLoginBailoutEnabled";
+const char kAccountsPrefSupervisedUsersEnabled[] =
+    "cros.accounts.supervisedUsersEnabled";
 
 // All cros.signed.* settings are stored in SignedSettings.
 const char kSignedDataRoamingEnabled[] = "cros.signed.data_roaming_enabled";
diff --git a/chrome/browser/chromeos/settings/cros_settings_names.h b/chrome/browser/chromeos/settings/cros_settings_names.h
index be47a46..cd6a9be 100644
--- a/chrome/browser/chromeos/settings/cros_settings_names.h
+++ b/chrome/browser/chromeos/settings/cros_settings_names.h
@@ -22,6 +22,7 @@
 extern const char kAccountsPrefDeviceLocalAccountAutoLoginId[];
 extern const char kAccountsPrefDeviceLocalAccountAutoLoginDelay[];
 extern const char kAccountsPrefDeviceLocalAccountAutoLoginBailoutEnabled[];
+extern const char kAccountsPrefSupervisedUsersEnabled[];
 
 extern const char kSignedDataRoamingEnabled[];
 
diff --git a/chrome/browser/chromeos/settings/device_oauth2_token_service.cc b/chrome/browser/chromeos/settings/device_oauth2_token_service.cc
index 1e277a5..361d49e 100644
--- a/chrome/browser/chromeos/settings/device_oauth2_token_service.cc
+++ b/chrome/browser/chromeos/settings/device_oauth2_token_service.cc
@@ -4,22 +4,244 @@
 
 #include "chrome/browser/chromeos/settings/device_oauth2_token_service.h"
 
+#include <string>
+#include <vector>
+
 #include "base/prefs/pref_registry_simple.h"
 #include "base/prefs/pref_service.h"
+#include "base/values.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h"
+#include "chrome/browser/policy/browser_policy_connector.h"
+#include "chrome/browser/policy/proto/cloud/device_management_backend.pb.h"
 #include "chrome/common/pref_names.h"
 #include "chromeos/cryptohome/cryptohome_library.h"
 #include "content/public/browser/browser_thread.h"
+#include "google_apis/gaia/gaia_urls.h"
+#include "google_apis/gaia/google_service_auth_error.h"
+
+namespace {
+const char kServiceScopeGetUserInfo[] =
+    "https://www.googleapis.com/auth/userinfo.email";
+}  // namespace
 
 namespace chromeos {
 
+// A wrapper for the consumer passed to StartRequest, which doesn't call
+// through to the target Consumer unless the refresh token validation is
+// complete.
+class DeviceOAuth2TokenService::ValidatingConsumer
+    : public OAuth2TokenService::Consumer,
+      public gaia::GaiaOAuthClient::Delegate {
+ public:
+  explicit ValidatingConsumer(DeviceOAuth2TokenService* token_service,
+                              Consumer* consumer);
+  virtual ~ValidatingConsumer();
+
+  void StartValidation();
+
+  // OAuth2TokenService::Consumer
+  virtual void OnGetTokenSuccess(
+      const Request* request,
+      const std::string& access_token,
+      const base::Time& expiration_time) OVERRIDE;
+  virtual void OnGetTokenFailure(
+      const Request* request,
+      const GoogleServiceAuthError& error) OVERRIDE;
+
+  // gaia::GaiaOAuthClient::Delegate implementation.
+  virtual void OnRefreshTokenResponse(const std::string& access_token,
+                                      int expires_in_seconds) OVERRIDE;
+  virtual void OnGetTokenInfoResponse(scoped_ptr<DictionaryValue> token_info)
+      OVERRIDE;
+  virtual void OnOAuthError() OVERRIDE;
+  virtual void OnNetworkError(int response_code) OVERRIDE;
+
+ private:
+  void RefreshTokenIsValid(bool is_valid);
+  void InformConsumer();
+
+  DeviceOAuth2TokenService* token_service_;
+  Consumer* consumer_;
+  scoped_ptr<gaia::GaiaOAuthClient> gaia_oauth_client_;
+
+  // We don't know which will complete first: the validation or the token
+  // minting.  So, we need to cache the results so the final callback can
+  // take action.
+
+  // RefreshTokenValidationConsumer results
+  bool token_validation_done_;
+  bool token_is_valid_;
+
+  // OAuth2TokenService::Consumer results
+  const Request* request_;
+  std::string access_token_;
+  base::Time expiration_time_;
+  scoped_ptr<GoogleServiceAuthError> error_;
+};
+
+DeviceOAuth2TokenService::ValidatingConsumer::ValidatingConsumer(
+    DeviceOAuth2TokenService* token_service,
+    Consumer* consumer)
+        : token_service_(token_service),
+          consumer_(consumer),
+          token_validation_done_(false),
+          token_is_valid_(false),
+          request_(NULL) {
+}
+
+DeviceOAuth2TokenService::ValidatingConsumer::~ValidatingConsumer() {
+}
+
+void DeviceOAuth2TokenService::ValidatingConsumer::StartValidation() {
+  DCHECK(!gaia_oauth_client_);
+  gaia_oauth_client_.reset(new gaia::GaiaOAuthClient(
+      g_browser_process->system_request_context()));
+
+  GaiaUrls* gaia_urls = GaiaUrls::GetInstance();
+  gaia::OAuthClientInfo client_info;
+  client_info.client_id = gaia_urls->oauth2_chrome_client_id();
+  client_info.client_secret = gaia_urls->oauth2_chrome_client_secret();
+
+  gaia_oauth_client_->RefreshToken(
+      client_info,
+      token_service_->GetRefreshToken(),
+      std::vector<std::string>(1, kServiceScopeGetUserInfo),
+      token_service_->max_refresh_token_validation_retries_,
+      this);
+}
+
+void DeviceOAuth2TokenService::ValidatingConsumer::OnRefreshTokenResponse(
+    const std::string& access_token,
+    int expires_in_seconds) {
+  gaia_oauth_client_->GetTokenInfo(
+      access_token,
+      token_service_->max_refresh_token_validation_retries_,
+      this);
+}
+
+void DeviceOAuth2TokenService::ValidatingConsumer::OnGetTokenInfoResponse(
+    scoped_ptr<DictionaryValue> token_info) {
+  std::string gaia_robot_id;
+  token_info->GetString("email", &gaia_robot_id);
+
+  std::string policy_robot_id = token_service_->GetRobotAccountId();
+
+  if (policy_robot_id == gaia_robot_id) {
+    RefreshTokenIsValid(true);
+  } else {
+    if (gaia_robot_id.empty()) {
+      LOG(WARNING) << "Device service account owner in policy is empty.";
+    } else {
+      LOG(INFO) << "Device service account owner in policy does not match "
+                << "refresh token owner \"" << gaia_robot_id << "\".";
+    }
+    RefreshTokenIsValid(false);
+  }
+}
+
+void DeviceOAuth2TokenService::ValidatingConsumer::OnOAuthError() {
+  RefreshTokenIsValid(false);
+}
+
+void DeviceOAuth2TokenService::ValidatingConsumer::OnNetworkError(
+    int response_code) {
+  RefreshTokenIsValid(false);
+}
+
+void DeviceOAuth2TokenService::ValidatingConsumer::OnGetTokenSuccess(
+      const Request* request,
+      const std::string& access_token,
+      const base::Time& expiration_time) {
+  request_ = request;
+  access_token_ = access_token;
+  expiration_time_ = expiration_time;
+  if (token_validation_done_)
+    InformConsumer();
+}
+
+void DeviceOAuth2TokenService::ValidatingConsumer::OnGetTokenFailure(
+      const Request* request,
+      const GoogleServiceAuthError& error) {
+  request_ = request;
+  error_.reset(new GoogleServiceAuthError(error.state()));
+  if (token_validation_done_)
+    InformConsumer();
+}
+
+void DeviceOAuth2TokenService::ValidatingConsumer::RefreshTokenIsValid(
+    bool is_valid) {
+  token_validation_done_ = true;
+  token_is_valid_ = is_valid;
+  // If we have a request pointer, then the minting is complete.
+  if (request_)
+    InformConsumer();
+}
+
+void DeviceOAuth2TokenService::ValidatingConsumer::InformConsumer() {
+  DCHECK(request_);
+  DCHECK(token_validation_done_);
+  if (!token_is_valid_) {
+    consumer_->OnGetTokenFailure(request_, GoogleServiceAuthError(
+        GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
+  } else if (error_) {
+    consumer_->OnGetTokenFailure(request_, *error_.get());
+  } else {
+    consumer_->OnGetTokenSuccess(request_, access_token_, expiration_time_);
+  }
+  token_service_->OnValidationComplete(this, token_is_valid_);
+}
+
 DeviceOAuth2TokenService::DeviceOAuth2TokenService(
     net::URLRequestContextGetter* getter,
     PrefService* local_state)
     : OAuth2TokenService(getter),
+      refresh_token_is_valid_(false),
+      max_refresh_token_validation_retries_(3),
+      pending_validators_(new std::set<ValidatingConsumer*>()),
       local_state_(local_state) {
 }
 
 DeviceOAuth2TokenService::~DeviceOAuth2TokenService() {
+  STLDeleteElements(pending_validators_.get());
+}
+
+// TODO(davidroche): if the caller deletes the returned Request while
+// the fetches are in-flight, the OAuth2TokenService class won't call
+// back into the ValidatingConsumer and we'll end up with stale values
+// in pending_validators_ until this object is deleted.  Probably not a
+// big deal, but it should be resolved by returning a Request that this
+// object owns.
+scoped_ptr<OAuth2TokenService::Request> DeviceOAuth2TokenService::StartRequest(
+    const OAuth2TokenService::ScopeSet& scopes,
+    OAuth2TokenService::Consumer* consumer) {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+  if (refresh_token_is_valid_) {
+    return OAuth2TokenService::StartRequest(scopes, consumer).Pass();
+  } else {
+    ValidatingConsumer* validating_consumer = new ValidatingConsumer(this,
+                                                                     consumer);
+    pending_validators_->insert(validating_consumer);
+
+    validating_consumer->StartValidation();
+    return OAuth2TokenService::StartRequest(scopes, validating_consumer).Pass();
+  }
+}
+
+void DeviceOAuth2TokenService::OnValidationComplete(
+    ValidatingConsumer* validator,
+    bool refresh_token_is_valid) {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  refresh_token_is_valid_ = refresh_token_is_valid;
+  std::set<ValidatingConsumer*>::iterator iter = pending_validators_->find(
+      validator);
+  if (iter != pending_validators_->end()) {
+    delete *iter;
+    pending_validators_->erase(iter);
+  } else {
+    LOG(ERROR) << "OnValidationComplete called for unknown validator";
+  }
 }
 
 // static
@@ -49,4 +271,12 @@
   return refresh_token_;
 }
 
+std::string DeviceOAuth2TokenService::GetRobotAccountId() {
+  policy::BrowserPolicyConnector* connector =
+      g_browser_process->browser_policy_connector();
+  if (connector)
+    return connector->GetDeviceCloudPolicyManager()->GetRobotAccountId();
+  return std::string();
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/settings/device_oauth2_token_service.h b/chrome/browser/chromeos/settings/device_oauth2_token_service.h
index 9d4bc6a..9ace020 100644
--- a/chrome/browser/chromeos/settings/device_oauth2_token_service.h
+++ b/chrome/browser/chromeos/settings/device_oauth2_token_service.h
@@ -5,12 +5,16 @@
 #ifndef CHROME_BROWSER_CHROMEOS_SETTINGS_DEVICE_OAUTH2_TOKEN_SERVICE_H_
 #define CHROME_BROWSER_CHROMEOS_SETTINGS_DEVICE_OAUTH2_TOKEN_SERVICE_H_
 
+#include <set>
 #include <string>
 
 #include "base/basictypes.h"
 #include "base/gtest_prod_util.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/stl_util.h"
+#include "base/time/time.h"
 #include "chrome/browser/signin/oauth2_token_service.h"
+#include "google_apis/gaia/gaia_oauth_client.h"
 #include "net/url_request/url_request_context_getter.h"
 
 namespace net {
@@ -33,6 +37,11 @@
 // Note that requests must be made from the UI thread.
 class DeviceOAuth2TokenService : public OAuth2TokenService {
  public:
+  // Specialization of StartRequest that in parallel validates that the refresh
+  // token stored on the device is owned by the device service account.
+  virtual scoped_ptr<Request> StartRequest(const ScopeSet& scopes,
+                                           Consumer* consumer) OVERRIDE;
+
   // Persist the given refresh token on the device.  Overwrites any previous
   // value.  Should only be called during initial device setup.
   void SetAndSaveRefreshToken(const std::string& refresh_token);
@@ -41,15 +50,29 @@
 
   virtual std::string GetRefreshToken() OVERRIDE;
 
+ protected:
+  // Pull the robot account ID from device policy.
+  virtual std::string GetRobotAccountId();
+
  private:
+  class ValidatingConsumer;
+  friend class ValidatingConsumer;
   friend class DeviceOAuth2TokenServiceFactory;
-  FRIEND_TEST_ALL_PREFIXES(DeviceOAuth2TokenServiceTest, SaveEncryptedToken);
+  friend class DeviceOAuth2TokenServiceTest;
+  friend class TestDeviceOAuth2TokenService;
 
   // Use DeviceOAuth2TokenServiceFactory to get an instance of this class.
   explicit DeviceOAuth2TokenService(net::URLRequestContextGetter* getter,
                                     PrefService* local_state);
   virtual ~DeviceOAuth2TokenService();
 
+  void OnValidationComplete(ValidatingConsumer* validator, bool token_is_valid);
+
+  bool refresh_token_is_valid_;
+  int max_refresh_token_validation_retries_;
+
+  scoped_ptr<std::set<ValidatingConsumer*> > pending_validators_;
+
   // Cache the decrypted refresh token, so we only decrypt once.
   std::string refresh_token_;
   PrefService* local_state_;
diff --git a/chrome/browser/chromeos/settings/device_oauth2_token_service_unittest.cc b/chrome/browser/chromeos/settings/device_oauth2_token_service_unittest.cc
index 6424ccb..c01fda7 100644
--- a/chrome/browser/chromeos/settings/device_oauth2_token_service_unittest.cc
+++ b/chrome/browser/chromeos/settings/device_oauth2_token_service_unittest.cc
@@ -6,11 +6,18 @@
 
 #include "base/message_loop.h"
 #include "base/prefs/testing_pref_service.h"
+#include "base/run_loop.h"
+#include "chrome/browser/signin/oauth2_token_service_test_util.h"
+#include "chrome/common/pref_names.h"
 #include "chrome/test/base/scoped_testing_local_state.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chromeos/cryptohome/mock_cryptohome_library.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/test/test_browser_thread.h"
+#include "google_apis/gaia/gaia_oauth_client.h"
+#include "net/http/http_status_code.h"
+#include "net/url_request/test_url_fetcher_factory.h"
+#include "net/url_request/url_fetcher_delegate.h"
 #include "net/url_request/url_request_test_util.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -23,25 +30,122 @@
 
 namespace chromeos {
 
+static const int kOAuthTokenServiceUrlFetcherId = 0;
+static const int kValidatorUrlFetcherId = gaia::GaiaOAuthClient::kUrlFetcherId;
+
+class TestDeviceOAuth2TokenService : public DeviceOAuth2TokenService {
+ public:
+  explicit TestDeviceOAuth2TokenService(net::URLRequestContextGetter* getter,
+                                        PrefService* local_state)
+      : DeviceOAuth2TokenService(getter, local_state) {
+  }
+  void SetRobotAccountIdPolicyValue(const std::string& id) {
+    robot_account_id_ = id;
+  }
+
+ protected:
+  // Skip calling into the policy subsystem and return our test value.
+  virtual std::string GetRobotAccountId() OVERRIDE {
+    return robot_account_id_;
+  }
+
+ private:
+  std::string robot_account_id_;
+  DISALLOW_COPY_AND_ASSIGN(TestDeviceOAuth2TokenService);
+};
+
 class DeviceOAuth2TokenServiceTest : public testing::Test {
  public:
   DeviceOAuth2TokenServiceTest()
       : ui_thread_(content::BrowserThread::UI, &message_loop_),
-        scoped_testing_local_state_(TestingBrowserProcess::GetGlobal()) {}
+        scoped_testing_local_state_(TestingBrowserProcess::GetGlobal()),
+        request_context_getter_(new net::TestURLRequestContextGetter(
+            message_loop_.message_loop_proxy())),
+        oauth2_service_(request_context_getter_,
+                        scoped_testing_local_state_.Get()) {
+    oauth2_service_.max_refresh_token_validation_retries_ = 0;
+    oauth2_service_.set_max_authorization_token_fetch_retries_for_testing(0);
+  }
   virtual ~DeviceOAuth2TokenServiceTest() {}
 
-  virtual void SetUp() OVERRIDE {
+  // Most tests just want a noop crypto impl with a dummy refresh token value in
+  // Local State (if the value is an empty string, it will be ignored).
+  void SetUpDefaultValues() {
+    cryptohome_library_.reset(chromeos::CryptohomeLibrary::GetTestImpl());
+    chromeos::CryptohomeLibrary::SetForTest(cryptohome_library_.get());
+    SetDeviceRefreshTokenInLocalState("device_refresh_token_4_test");
+    oauth2_service_.SetRobotAccountIdPolicyValue("service_acct@g.com");
+    AssertConsumerTokensAndErrors(0, 0);
+  }
+
+  scoped_ptr<OAuth2TokenService::Request> StartTokenRequest() {
+    return oauth2_service_.StartRequest(std::set<std::string>(), &consumer_);
   }
 
   virtual void TearDown() OVERRIDE {
+    CryptohomeLibrary::SetForTest(NULL);
+    base::RunLoop().RunUntilIdle();
   }
 
+  // Utility method to set a value in Local State for the device refresh token
+  // (it must have a non-empty value or it won't be used).
+  void SetDeviceRefreshTokenInLocalState(const std::string& refresh_token) {
+    scoped_testing_local_state_.Get()->SetManagedPref(
+        prefs::kDeviceRobotAnyApiRefreshToken,
+        Value::CreateStringValue(refresh_token));
+  }
+
+  std::string GetValidTokenInfoResponse(const std::string email) {
+    return "{ \"email\": \"" + email + "\","
+           "  \"user_id\": \"1234567890\" }";
+  }
+
+  // A utility method to return fake URL results, for testing the refresh token
+  // validation logic.  For a successful validation attempt, this method will be
+  // called three times for the steps listed below (steps 1 and 2 happen in
+  // parallel).
+  //
+  // Step 1a: fetch the access token for the tokeninfo API.
+  // Step 1b: call the tokeninfo API.
+  // Step 2:  Fetch the access token for the requested scope
+  //          (in this case, cloudprint).
+  void ReturnOAuthUrlFetchResults(int fetcher_id,
+                                  net::HttpStatusCode response_code,
+                                  const std::string&  response_string);
+
+  void AssertConsumerTokensAndErrors(int num_tokens, int num_errors);
+
  protected:
   base::MessageLoop message_loop_;
   content::TestBrowserThread ui_thread_;
   ScopedTestingLocalState scoped_testing_local_state_;
+  scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_;
+  net::TestURLFetcherFactory factory_;
+  TestDeviceOAuth2TokenService oauth2_service_;
+  TestingOAuth2TokenServiceConsumer consumer_;
+  scoped_ptr<chromeos::CryptohomeLibrary> cryptohome_library_;
+
 };
 
+void DeviceOAuth2TokenServiceTest::ReturnOAuthUrlFetchResults(
+    int fetcher_id,
+    net::HttpStatusCode response_code,
+    const std::string&  response_string) {
+
+  net::TestURLFetcher* fetcher = factory_.GetFetcherByID(fetcher_id);
+  ASSERT_TRUE(fetcher);
+  fetcher->set_response_code(response_code);
+  fetcher->SetResponseString(response_string);
+  fetcher->delegate()->OnURLFetchComplete(fetcher);
+}
+
+void DeviceOAuth2TokenServiceTest::AssertConsumerTokensAndErrors(
+    int num_tokens,
+    int num_errors) {
+  ASSERT_EQ(num_tokens, consumer_.number_of_successful_tokens_);
+  ASSERT_EQ(num_errors, consumer_.number_of_errors_);
+}
+
 TEST_F(DeviceOAuth2TokenServiceTest, SaveEncryptedToken) {
   StrictMock<MockCryptohomeLibrary> mock_cryptohome_library;
   CryptohomeLibrary::SetForTest(&mock_cryptohome_library);
@@ -58,16 +162,207 @@
       .Times(1)
       .WillOnce(Return("test-token"));
 
-  DeviceOAuth2TokenService oauth2_service(
-      new net::TestURLRequestContextGetter(message_loop_.message_loop_proxy()),
-      scoped_testing_local_state_.Get());
-
-  ASSERT_EQ("", oauth2_service.GetRefreshToken());
-  oauth2_service.SetAndSaveRefreshToken("test-token");
-  ASSERT_EQ("test-token", oauth2_service.GetRefreshToken());
+  ASSERT_EQ("", oauth2_service_.GetRefreshToken());
+  oauth2_service_.SetAndSaveRefreshToken("test-token");
+  ASSERT_EQ("test-token", oauth2_service_.GetRefreshToken());
 
   // This call won't invoke decrypt again, since the value is cached.
-  ASSERT_EQ("test-token", oauth2_service.GetRefreshToken());
+  ASSERT_EQ("test-token", oauth2_service_.GetRefreshToken());
+}
+
+TEST_F(DeviceOAuth2TokenServiceTest, RefreshTokenValidation_Success) {
+  SetUpDefaultValues();
+  scoped_ptr<OAuth2TokenService::Request> request = StartTokenRequest();
+
+  ReturnOAuthUrlFetchResults(
+      kValidatorUrlFetcherId,
+      net::HTTP_OK,
+      GetValidTokenResponse("tokeninfo_access_token", 3600));
+
+  ReturnOAuthUrlFetchResults(
+      kValidatorUrlFetcherId,
+      net::HTTP_OK,
+      GetValidTokenInfoResponse("service_acct@g.com"));
+
+  ReturnOAuthUrlFetchResults(
+      kOAuthTokenServiceUrlFetcherId,
+      net::HTTP_OK,
+      GetValidTokenResponse("scoped_access_token", 3600));
+
+  AssertConsumerTokensAndErrors(1, 0);
+
+  EXPECT_EQ("scoped_access_token", consumer_.last_token_);
+}
+
+TEST_F(DeviceOAuth2TokenServiceTest,
+       RefreshTokenValidation_Failure_TokenInfoAccessTokenHttpError) {
+  SetUpDefaultValues();
+  scoped_ptr<OAuth2TokenService::Request> request = StartTokenRequest();
+
+  ReturnOAuthUrlFetchResults(
+      kValidatorUrlFetcherId,
+      net::HTTP_UNAUTHORIZED,
+      "");
+
+  // TokenInfo API call skipped (error returned in previous step).
+
+  // CloudPrint access token fetch is successful, but consumer still given error
+  // due to bad refresh token.
+  ReturnOAuthUrlFetchResults(
+      kOAuthTokenServiceUrlFetcherId,
+      net::HTTP_OK,
+      GetValidTokenResponse("ignored_scoped_access_token", 3600));
+
+  AssertConsumerTokensAndErrors(0, 1);
+}
+
+TEST_F(DeviceOAuth2TokenServiceTest,
+       RefreshTokenValidation_Failure_TokenInfoAccessTokenInvalidResponse) {
+  SetUpDefaultValues();
+  scoped_ptr<OAuth2TokenService::Request> request = StartTokenRequest();
+
+  ReturnOAuthUrlFetchResults(
+      kValidatorUrlFetcherId,
+      net::HTTP_OK,
+      "invalid response");
+
+  // TokenInfo API call skipped (error returned in previous step).
+
+  ReturnOAuthUrlFetchResults(
+      kOAuthTokenServiceUrlFetcherId,
+      net::HTTP_OK,
+      GetValidTokenResponse("ignored_scoped_access_token", 3600));
+
+  // CloudPrint access token fetch is successful, but consumer still given error
+  // due to bad refresh token.
+  AssertConsumerTokensAndErrors(0, 1);
+}
+
+TEST_F(DeviceOAuth2TokenServiceTest,
+       RefreshTokenValidation_Failure_TokenInfoApiCallHttpError) {
+  SetUpDefaultValues();
+  scoped_ptr<OAuth2TokenService::Request> request = StartTokenRequest();
+
+  ReturnOAuthUrlFetchResults(
+      kValidatorUrlFetcherId,
+      net::HTTP_OK,
+      GetValidTokenResponse("tokeninfo_access_token", 3600));
+
+  ReturnOAuthUrlFetchResults(
+      kValidatorUrlFetcherId,
+      net::HTTP_INTERNAL_SERVER_ERROR,
+      "");
+
+  ReturnOAuthUrlFetchResults(
+      kOAuthTokenServiceUrlFetcherId,
+      net::HTTP_OK,
+      GetValidTokenResponse("ignored_scoped_access_token", 3600));
+
+  // CloudPrint access token fetch is successful, but consumer still given error
+  // due to bad refresh token.
+  AssertConsumerTokensAndErrors(0, 1);
+}
+
+TEST_F(DeviceOAuth2TokenServiceTest,
+       RefreshTokenValidation_Failure_TokenInfoApiCallInvalidResponse) {
+  SetUpDefaultValues();
+  scoped_ptr<OAuth2TokenService::Request> request = StartTokenRequest();
+
+  ReturnOAuthUrlFetchResults(
+      kValidatorUrlFetcherId,
+      net::HTTP_OK,
+      GetValidTokenResponse("tokeninfo_access_token", 3600));
+
+  ReturnOAuthUrlFetchResults(
+      kValidatorUrlFetcherId,
+      net::HTTP_OK,
+      "invalid response");
+
+  ReturnOAuthUrlFetchResults(
+      kOAuthTokenServiceUrlFetcherId,
+      net::HTTP_OK,
+      GetValidTokenResponse("ignored_scoped_access_token", 3600));
+
+  // CloudPrint access token fetch is successful, but consumer still given error
+  // due to bad refresh token.
+  AssertConsumerTokensAndErrors(0, 1);
+}
+
+TEST_F(DeviceOAuth2TokenServiceTest,
+       RefreshTokenValidation_Failure_CloudPrintAccessTokenHttpError) {
+  SetUpDefaultValues();
+  scoped_ptr<OAuth2TokenService::Request> request = StartTokenRequest();
+
+  ReturnOAuthUrlFetchResults(
+      kValidatorUrlFetcherId,
+      net::HTTP_OK,
+      GetValidTokenResponse("tokeninfo_access_token", 3600));
+
+  ReturnOAuthUrlFetchResults(
+      kValidatorUrlFetcherId,
+      net::HTTP_OK,
+      GetValidTokenInfoResponse("service_acct@g.com"));
+
+  ReturnOAuthUrlFetchResults(
+      kOAuthTokenServiceUrlFetcherId,
+      net::HTTP_BAD_REQUEST,
+      "");
+
+  AssertConsumerTokensAndErrors(0, 1);
+}
+
+TEST_F(DeviceOAuth2TokenServiceTest,
+       RefreshTokenValidation_Failure_CloudPrintAccessTokenInvalidResponse) {
+  SetUpDefaultValues();
+  scoped_ptr<OAuth2TokenService::Request> request = StartTokenRequest();
+
+  ReturnOAuthUrlFetchResults(
+      kValidatorUrlFetcherId,
+      net::HTTP_OK,
+      GetValidTokenResponse("tokeninfo_access_token", 3600));
+
+  ReturnOAuthUrlFetchResults(
+      kValidatorUrlFetcherId,
+      net::HTTP_OK,
+      GetValidTokenInfoResponse("service_acct@g.com"));
+
+  ReturnOAuthUrlFetchResults(
+      kOAuthTokenServiceUrlFetcherId,
+      net::HTTP_OK,
+      "invalid request");
+
+  AssertConsumerTokensAndErrors(0, 1);
+}
+
+TEST_F(DeviceOAuth2TokenServiceTest, RefreshTokenValidation_Failure_BadOwner) {
+  SetUpDefaultValues();
+  scoped_ptr<OAuth2TokenService::Request> request = StartTokenRequest();
+
+  oauth2_service_.SetRobotAccountIdPolicyValue("WRONG_service_acct@g.com");
+
+  // The requested token comes in before any of the validation calls complete,
+  // but the consumer still gets an error, since the results don't get returned
+  // until validation is over.
+  ReturnOAuthUrlFetchResults(
+      kOAuthTokenServiceUrlFetcherId,
+      net::HTTP_OK,
+      GetValidTokenResponse("ignored_scoped_access_token", 3600));
+  AssertConsumerTokensAndErrors(0, 0);
+
+  ReturnOAuthUrlFetchResults(
+      kValidatorUrlFetcherId,
+      net::HTTP_OK,
+      GetValidTokenResponse("tokeninfo_access_token", 3600));
+  AssertConsumerTokensAndErrors(0, 0);
+
+  ReturnOAuthUrlFetchResults(
+      kValidatorUrlFetcherId,
+      net::HTTP_OK,
+      GetValidTokenInfoResponse("service_acct@g.com"));
+
+  // All fetches were successful, but consumer still given error since
+  // the token owner doesn't match the policy value.
+  AssertConsumerTokensAndErrors(0, 1);
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/settings/device_settings_provider.cc b/chrome/browser/chromeos/settings/device_settings_provider.cc
index 6a7876c..98293ad 100644
--- a/chrome/browser/chromeos/settings/device_settings_provider.cc
+++ b/chrome/browser/chromeos/settings/device_settings_provider.cc
@@ -47,6 +47,7 @@
   kAccountsPrefDeviceLocalAccountAutoLoginId,
   kAccountsPrefEphemeralUsersEnabled,
   kAccountsPrefShowUserNamesOnSignIn,
+  kAccountsPrefSupervisedUsersEnabled,
   kAccountsPrefUsers,
   kAllowRedeemChromeOsRegistrationOffers,
   kAllowedConnectionTypesForUpdate,
@@ -366,16 +367,17 @@
   } else {
     // The remaining settings don't support Set(), since they are not
     // intended to be customizable by the user:
+    //   kAccountsPrefSupervisedUsersEnabled
     //   kAppPack
     //   kDeviceAttestationEnabled
     //   kDeviceOwner
     //   kIdleLogoutTimeout
     //   kIdleLogoutWarningDuration
     //   kReleaseChannelDelegated
-    //   kReportDeviceVersionInfo
     //   kReportDeviceActivityTimes
     //   kReportDeviceBootMode
     //   kReportDeviceLocation
+    //   kReportDeviceVersionInfo
     //   kScreenSaverExtensionId
     //   kScreenSaverTimeout
     //   kStartUpUrls
@@ -448,6 +450,11 @@
       policy.ephemeral_users_enabled().has_ephemeral_users_enabled() &&
       policy.ephemeral_users_enabled().ephemeral_users_enabled());
 
+  new_values_cache->SetBoolean(
+      kAccountsPrefSupervisedUsersEnabled,
+      policy.has_supervised_users_settings() &&
+      policy.supervised_users_settings().supervised_users_enabled());
+
   base::ListValue* list = new base::ListValue();
   const em::UserWhitelistProto& whitelist_proto = policy.user_whitelist();
   const RepeatedPtrField<std::string>& whitelist =
diff --git a/chrome/browser/chromeos/settings/owner_flags_storage.cc b/chrome/browser/chromeos/settings/owner_flags_storage.cc
new file mode 100644
index 0000000..38c2ba9
--- /dev/null
+++ b/chrome/browser/chromeos/settings/owner_flags_storage.cc
@@ -0,0 +1,63 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/settings/owner_flags_storage.h"
+
+#include "base/prefs/pref_service.h"
+#include "base/values.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chromeos/settings/cros_settings.h"
+#include "chrome/browser/chromeos/settings/cros_settings_names.h"
+#include "chrome/common/pref_names.h"
+
+namespace chromeos {
+namespace about_flags {
+
+OwnerFlagsStorage::OwnerFlagsStorage(PrefService *prefs,
+                                     CrosSettings *cros_settings)
+    : ::about_flags::PrefServiceFlagsStorage(prefs),
+      cros_settings_(cros_settings) {
+  // Make this code more unit test friendly.
+  if (g_browser_process->local_state()) {
+    const ListValue* legacy_experiments =
+        g_browser_process->local_state()->GetList(
+            prefs::kEnabledLabsExperiments);
+    if (!legacy_experiments->empty()) {
+      // If there are any flags set in local state migrate them to the owner's
+      // prefs and device settings.
+      std::set<std::string> flags;
+      for (ListValue::const_iterator it = legacy_experiments->begin();
+           it != legacy_experiments->end(); ++it) {
+        std::string experiment_name;
+        if (!(*it)->GetAsString(&experiment_name)) {
+          LOG(WARNING) << "Invalid entry in " << prefs::kEnabledLabsExperiments;
+          continue;
+        }
+        flags.insert(experiment_name);
+      }
+      SetFlags(flags);
+      g_browser_process->local_state()->ClearPref(
+          prefs::kEnabledLabsExperiments);
+    }
+  }
+}
+
+OwnerFlagsStorage::~OwnerFlagsStorage() {}
+
+bool OwnerFlagsStorage::SetFlags(std::set<std::string> flags) {
+  PrefServiceFlagsStorage::SetFlags(flags);
+
+  base::ListValue experiments_list;
+
+  for (std::set<std::string>::const_iterator it = flags.begin();
+       it != flags.end(); ++it) {
+    experiments_list.Append(new base::StringValue(*it));
+  }
+  cros_settings_->Set(kStartUpFlags, experiments_list);
+
+  return true;
+}
+
+}  // namespace about_flags
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/settings/owner_flags_storage.h b/chrome/browser/chromeos/settings/owner_flags_storage.h
new file mode 100644
index 0000000..77d7830
--- /dev/null
+++ b/chrome/browser/chromeos/settings/owner_flags_storage.h
@@ -0,0 +1,34 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_SETTINGS_OWNER_FLAGS_STORAGE_H_
+#define CHROME_BROWSER_CHROMEOS_SETTINGS_OWNER_FLAGS_STORAGE_H_
+
+#include "base/compiler_specific.h"
+#include "chrome/browser/pref_service_flags_storage.h"
+
+namespace chromeos {
+
+class CrosSettings;
+
+namespace about_flags {
+
+// Implements the FlagsStorage interface for the owner flags. It inherits from
+// PrefServiceFlagsStorage but extends it with storing the flags in the signed
+// settings as well which effectively applies them to the login session as well.
+class OwnerFlagsStorage : public ::about_flags::PrefServiceFlagsStorage {
+ public:
+  OwnerFlagsStorage(PrefService *prefs, CrosSettings *cros_settings);
+  virtual ~OwnerFlagsStorage();
+
+  virtual bool SetFlags(std::set<std::string> flags) OVERRIDE;
+
+ private:
+  CrosSettings* cros_settings_;
+};
+
+}  // namespace about_flags
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_SETTINGS_OWNER_FLAGS_STORAGE_H_
diff --git a/chrome/browser/chromeos/settings/session_manager_operation.cc b/chrome/browser/chromeos/settings/session_manager_operation.cc
index e7c9a9d..5339f3f 100644
--- a/chrome/browser/chromeos/settings/session_manager_operation.cc
+++ b/chrome/browser/chromeos/settings/session_manager_operation.cc
@@ -11,7 +11,7 @@
 #include "base/stl_util.h"
 #include "base/task_runner_util.h"
 #include "base/threading/sequenced_worker_pool.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/chromeos/settings/owner_key_util.h"
 #include "chrome/browser/policy/cloud/cloud_policy_constants.h"
 #include "chrome/browser/policy/proto/chromeos/chrome_device_policy.pb.h"
diff --git a/chrome/browser/chromeos/settings/system_settings_provider.cc b/chrome/browser/chromeos/settings/system_settings_provider.cc
index 5f2741f..35549aa 100644
--- a/chrome/browser/chromeos/settings/system_settings_provider.cc
+++ b/chrome/browser/chromeos/settings/system_settings_provider.cc
@@ -5,7 +5,7 @@
 #include "chrome/browser/chromeos/settings/system_settings_provider.h"
 
 #include "base/strings/string16.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/chromeos/login/user_manager.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
diff --git a/chrome/browser/chromeos/status/network_menu_icon.h b/chrome/browser/chromeos/status/network_menu_icon.h
index 5e8fc7b..f0fb554 100644
--- a/chrome/browser/chromeos/status/network_menu_icon.h
+++ b/chrome/browser/chromeos/status/network_menu_icon.h
@@ -35,7 +35,7 @@
 
 #include "ash/system/chromeos/network/network_icon_animation_observer.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/chromeos/cros/network_library.h"
 #include "ui/gfx/image/image_skia.h"
 
diff --git a/chrome/browser/chromeos/swap_metrics.cc b/chrome/browser/chromeos/swap_metrics.cc
new file mode 100644
index 0000000..6b25be0
--- /dev/null
+++ b/chrome/browser/chromeos/swap_metrics.cc
@@ -0,0 +1,432 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/swap_metrics.h"
+
+#include <string>
+#include <vector>
+
+#include "ash/shell.h"
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/metrics/histogram.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/synchronization/cancellation_flag.h"
+#include "base/sys_info.h"
+#include "base/threading/sequenced_worker_pool.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "content/public/browser/browser_thread.h"
+#include "ui/base/events/event.h"
+
+using base::FilePath;
+
+namespace chromeos {
+namespace {
+
+// Time delays for metrics collections, starting after an interesting UI event.
+// Times are relative to the UI event. Start with zero to record the initial
+// state of the metrics immediately.
+const int kMetricsDelayMs[] = { 0, 100, 300, 1000, 3000 };
+
+}  // namespace
+
+///////////////////////////////////////////////////////////////////////////////
+
+// Runs in the blocking thread pool to load metrics and record them.
+// Reads data about CPU utilization and swap activity from the /proc and /sys
+// file systems. Owned by SwapMetrics on the UI thread.
+class SwapMetrics::Backend : public base::RefCountedThreadSafe<Backend> {
+ public:
+  explicit Backend(const std::string& reason);
+
+  // Records one set of statistics for |time_index| after the interesting
+  // event. May trigger another delayed task to record more statistics.
+  void RecordMetricsOnBlockingPool(size_t time_index);
+
+  // Sets the thread-safe cancellation flag.
+  void CancelOnUIThread() { cancelled_.Set(); }
+
+ private:
+  friend class base::RefCountedThreadSafe<Backend>;
+
+  virtual ~Backend();
+
+  // Extracts a field value from a list of name-value pairs
+  // in a file (typically a /proc or /sys file). Returns false
+  // if the field is not found, or for other errors.
+  bool GetFieldFromKernelOutput(const std::string& path,
+                                const std::string& field,
+                                int64* value);
+
+  // Reads a file whose content is a single line, and returns its content as a
+  // list of tokens. |expected_tokens_count| is the expected number of tokens.
+  // |delimiters| is a string containing characters that may appear between
+  // tokens. Returns true on success, false otherwise.
+  bool TokenizeOneLineFile(const std::string& path,
+                           size_t expected_tokens_count,
+                           const std::string& delimiters,
+                           std::vector<std::string>* tokens);
+
+  // Retrieve various system metrics. Return true on success.
+  bool GetMeminfoField(const std::string& field, int64* value);
+  bool GetUptime(double* uptime_secs, double* idle_time_secs);
+  bool GetPageFaults(int64* page_faults);
+
+  // Record histogram samples.
+  void RecordFaultsHistogramSample(int faults,
+                                   const std::string& reason,
+                                   int swap_group,
+                                   int time_index);
+  void RecordCpuHistogramSample(int cpu,
+                                const std::string& reason,
+                                int swap_group,
+                                int time_index);
+
+  // Cancellation flag that can be written from the UI thread (which owns this
+  // object) and read from any thread.
+  base::CancellationFlag cancelled_;
+
+  // Data initialized once and shared by all instances of this class.
+  static bool first_time_;
+  static int64 swap_total_kb_;
+  static int number_of_cpus_;
+
+  // Values at the beginning of each sampling interval.
+  double last_uptime_secs_;
+  double last_idle_time_secs_;
+  int64 last_page_faults_;
+
+  // Swap group for a set of samples, chosen at the beginning of the set.
+  int swap_group_;
+
+  // Reason for sampling.
+  const std::string reason_;
+
+  DISALLOW_COPY_AND_ASSIGN(Backend);
+};
+
+// static
+bool SwapMetrics::Backend::first_time_ = true;
+// static
+int64 SwapMetrics::Backend::swap_total_kb_ = 0;
+// static
+int SwapMetrics::Backend::number_of_cpus_ = 0;
+
+SwapMetrics::Backend::Backend(const std::string& reason)
+    : last_uptime_secs_(0.0),
+      last_idle_time_secs_(0.0),
+      last_page_faults_(0),
+      swap_group_(0),
+      reason_(reason) {
+}
+
+SwapMetrics::Backend::~Backend() {
+}
+
+void SwapMetrics::Backend::RecordMetricsOnBlockingPool(size_t time_index) {
+  DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
+  // Another UI event might have occurred. Don't run this metrics collection
+  // and don't post another task. This object's refcount will drop and it will
+  // be deleted when the next backend is created on the UI thread.
+  if (cancelled_.IsSet())
+    return;
+  DVLOG(1) << "RecordMetricsInBlockingPool " << time_index;
+
+  // At init time, get the number of cpus and the total swap. The number of cpus
+  // is necessary because the idle time reported is the sum of the idle
+  // times of all cpus.
+  //
+  // When an event occurs:
+  // - At time t_0, save the initial values for uptime, idle_time, page_faults,
+  //   and swap used.
+  //
+  // - At time t_i, compute cpu utilization as a fraction (1 = fully utilized):
+  //  utilization =
+  //      1 - (idle_time_i - idle_time_0) / (uptime_i - uptime_0) / ncpus
+  //
+  // then UMA-report it in the right swap group. Do the same for page faults.
+
+  if (first_time_) {
+    first_time_ = false;
+    number_of_cpus_ = base::SysInfo::NumberOfProcessors();
+    // Avoid divide by zero in case of errors.
+    if (number_of_cpus_ == 0)
+      number_of_cpus_ = 1;
+    GetMeminfoField("SwapTotal:", &swap_total_kb_);
+  }
+
+  if (time_index == 0) {
+    // Record baseline data.
+    GetUptime(&last_uptime_secs_, &last_idle_time_secs_);
+    GetPageFaults(&last_page_faults_);
+    int64 swap_free_kb = 0;
+    GetMeminfoField("SwapFree:", &swap_free_kb);
+    int swap_percent = swap_total_kb_ > 0
+        ? (swap_total_kb_ - swap_free_kb) * 100 / swap_total_kb_
+        : 0;
+    if (swap_percent < 10)
+      swap_group_ = 0;
+    else if (swap_percent < 30)
+      swap_group_ = 1;
+    else if (swap_percent < 60)
+      swap_group_ = 2;
+    else
+      swap_group_ = 3;
+  } else {
+    int64 page_faults = 0;
+    double idle_time_secs = 0.0;
+    double uptime_secs = 0.0;
+    GetUptime(&uptime_secs, &idle_time_secs);
+    GetPageFaults(&page_faults);
+    double delta_time_secs = uptime_secs - last_uptime_secs_;
+    // Unexpected, but not worth agonizing over it.
+    if (delta_time_secs == 0)
+      return;
+
+    int cpu = (1.0 - (idle_time_secs - last_idle_time_secs_) /
+               delta_time_secs / number_of_cpus_) * 100;
+    int faults_per_sec = (page_faults - last_page_faults_) / delta_time_secs;
+
+    RecordCpuHistogramSample(cpu, reason_, swap_group_, time_index);
+    RecordFaultsHistogramSample(faults_per_sec, reason_,
+                                swap_group_, time_index);
+
+    last_uptime_secs_ = uptime_secs;
+    last_page_faults_ = page_faults;
+    last_idle_time_secs_ = idle_time_secs;
+  }
+
+  // Check if another metrics recording is needed.
+  if (++time_index >= arraysize(kMetricsDelayMs))
+    return;
+  PostTaskRecordMetrics(
+      scoped_refptr<Backend>(this),
+      time_index,
+      kMetricsDelayMs[time_index] - kMetricsDelayMs[time_index - 1]);
+}
+
+void SwapMetrics::Backend::RecordFaultsHistogramSample(
+    int faults,
+    const std::string& reason,
+    int swap_group,
+    int time_index) {
+  std::string name =
+      base::StringPrintf("Platform.SwapJank.%s.Faults.Swap%d.Time%d",
+                         reason.c_str(),
+                         swap_group,
+                         time_index);
+  const int kMinimumBucket = 10;
+  const int kMaximumBucket = 200000;
+  const size_t kBucketCount = 50;
+  base::HistogramBase* counter =
+      base::Histogram::FactoryGet(name,
+                                  kMinimumBucket,
+                                  kMaximumBucket,
+                                  kBucketCount,
+                                  base::Histogram::kUmaTargetedHistogramFlag);
+  counter->Add(faults);
+}
+
+void SwapMetrics::Backend::RecordCpuHistogramSample(int cpu,
+                                                    const std::string& reason,
+                                                    int swap_group,
+                                                    int time_index) {
+  std::string name =
+      base::StringPrintf("Platform.SwapJank.%s.Cpu.Swap%d.Time%d",
+                         reason.c_str(),
+                         swap_group,
+                         time_index);
+  const int kMinimumBucket = 0;
+  const int kMaximumBucket = 101;
+  const size_t kBucketCount = 102;
+  base::HistogramBase* counter = base::LinearHistogram::FactoryGet(
+      name,
+      kMinimumBucket,
+      kMaximumBucket,
+      kBucketCount,
+      base::Histogram::kUmaTargetedHistogramFlag);
+  counter->Add(cpu);
+}
+
+// Extracts a field value from a list of name-value pairs
+// in a file (typically a /proc or /sys file). Returns false
+// if the field is not found, or for other errors.
+bool SwapMetrics::Backend::GetFieldFromKernelOutput(const std::string& path,
+                                                    const std::string& field,
+                                                    int64* value) {
+  std::string file_content;
+  if (!file_util::ReadFileToString(FilePath(path), &file_content)) {
+    LOG(WARNING) << "Cannot read " << path;
+    return false;
+  }
+  std::vector<std::string> lines;
+  size_t line_count = Tokenize(file_content, "\n", &lines);
+  if (line_count < 2) {
+    LOG(WARNING) << "Error breaking " << path << " into lines";
+    return false;
+  }
+  for (size_t i = 0; i < line_count; ++i) {
+    std::vector<std::string> tokens;
+    size_t token_count = Tokenize(lines[i], " ", &tokens);
+    if (token_count < 2) {
+      LOG(WARNING) << "Unexpected line: " << lines[i];
+      return false;
+    }
+    if (tokens[0].compare(field) != 0)
+      continue;
+    if (!base::StringToInt64(tokens[1], value)) {
+      LOG(WARNING) << "Cannot convert " << tokens[1] << " to int";
+      return false;
+    }
+    return true;
+  }
+  LOG(WARNING) << "could not find field " << field;
+  return false;
+}
+
+bool SwapMetrics::Backend::TokenizeOneLineFile(const std::string& path,
+                                               size_t expected_tokens_count,
+                                               const std::string& delimiters,
+                                               std::vector<std::string>*
+                                               tokens) {
+  std::string file_content;
+  if (!file_util::ReadFileToString(FilePath(path), &file_content)) {
+    LOG(WARNING) << "cannot read " << path;
+    return false;
+  }
+  size_t tokens_count = Tokenize(file_content, delimiters, tokens);
+  if (tokens_count != expected_tokens_count) {
+    LOG(WARNING) << "unexpected content of " << path << ": " << file_content;
+    return false;
+  }
+  return true;
+}
+
+bool SwapMetrics::Backend::GetMeminfoField(const std::string& name,
+                                           int64* value) {
+  return GetFieldFromKernelOutput("/proc/meminfo", name, value);
+}
+
+bool SwapMetrics::Backend::GetUptime(double* uptime_secs,
+                                     double* idle_time_secs) {
+  // Get the time since boot.
+  const char kUptimePath[] = "/proc/uptime";
+  std::vector<std::string> tokens;
+  if (!TokenizeOneLineFile(kUptimePath, 2, " \n", &tokens))
+    return false;
+
+  if (!base::StringToDouble(tokens[0], uptime_secs)) {
+    LOG(WARNING) << "cannot convert " << tokens[0] << " to double";
+    return false;
+  }
+
+  // Get the idle time since boot. The number available in /proc/stat is more
+  // precise, but this one should be good enough.
+  if (!base::StringToDouble(tokens[1], idle_time_secs)) {
+    LOG(WARNING) << "cannot convert " << tokens[0] << " to double";
+    return false;
+  }
+  return true;
+}
+
+bool SwapMetrics::Backend::GetPageFaults(int64* page_faults) {
+  // Get number of page faults.
+  return GetFieldFromKernelOutput("/proc/vmstat", "pgmajfault", page_faults);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+SwapMetrics::SwapMetrics() : browser_(NULL) {
+  ash::Shell::GetInstance()->AddPreTargetHandler(this);
+  BrowserList::AddObserver(this);
+}
+
+SwapMetrics::~SwapMetrics() {
+  if (backend_)
+    backend_->CancelOnUIThread();
+  ash::Shell::GetInstance()->RemovePreTargetHandler(this);
+  BrowserList::RemoveObserver(this);
+  SetBrowser(NULL);
+}
+
+void SwapMetrics::OnBrowserRemoved(Browser* browser) {
+  if (browser_ == browser)
+    SetBrowser(NULL);
+}
+
+void SwapMetrics::OnBrowserSetLastActive(Browser* browser) {
+  if (browser && browser->type() == Browser::TYPE_TABBED)
+    SetBrowser(browser);
+  else
+    SetBrowser(NULL);
+}
+
+void SwapMetrics::ActiveTabChanged(content::WebContents* old_contents,
+                                   content::WebContents* new_contents,
+                                   int index,
+                                   int reason) {
+  // Only measure tab switches, not tabs being replaced with new contents.
+  if (reason != TabStripModelObserver::CHANGE_REASON_USER_GESTURE)
+    return;
+  DVLOG(1) << "ActiveTabChanged";
+  StartMetricsCollection("TabSwitch");
+}
+
+// This exists primarily for debugging on desktop builds.
+void SwapMetrics::OnMouseEvent(ui::MouseEvent* event) {
+  if (event->type() != ui::ET_MOUSEWHEEL)
+    return;
+  DVLOG(1) << "OnMouseEvent";
+  StartMetricsCollection("Scroll");
+}
+
+void SwapMetrics::OnScrollEvent(ui::ScrollEvent* event) {
+  if (event->type() != ui::ET_SCROLL &&
+      event->type() != ui::ET_SCROLL_FLING_START)
+    return;
+  DVLOG(1) << "OnScrollEvent";
+  StartMetricsCollection("Scroll");
+}
+
+// static
+void SwapMetrics::PostTaskRecordMetrics(scoped_refptr<Backend> backend,
+                                        size_t time_index,
+                                        int delay_ms) {
+  // Don't block shutdown on these tasks, as UMA will be disappearing.
+  scoped_refptr<base::TaskRunner> runner =
+      content::BrowserThread::GetBlockingPool()->
+          GetTaskRunnerWithShutdownBehavior(
+                base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
+  runner->PostDelayedTask(
+      FROM_HERE,
+      base::Bind(&SwapMetrics::Backend::RecordMetricsOnBlockingPool,
+                 backend,
+                 time_index),
+      base::TimeDelta::FromMilliseconds(delay_ms));
+}
+
+void SwapMetrics::StartMetricsCollection(const std::string& reason) {
+  // Cancel any existing metrics run.
+  if (backend_)
+    backend_->CancelOnUIThread();
+  backend_ = new Backend(reason);
+  PostTaskRecordMetrics(backend_, 0, kMetricsDelayMs[0]);
+}
+
+void SwapMetrics::SetBrowser(Browser* browser) {
+  if (browser_ == browser)
+    return;
+  if (browser_)
+    browser_->tab_strip_model()->RemoveObserver(this);
+  browser_ = browser;
+  if (browser_)
+    browser_->tab_strip_model()->AddObserver(this);
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/swap_metrics.h b/chrome/browser/chromeos/swap_metrics.h
new file mode 100644
index 0000000..ccda9db
--- /dev/null
+++ b/chrome/browser/chromeos/swap_metrics.h
@@ -0,0 +1,72 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_SWAP_METRICS_H_
+#define CHROME_BROWSER_CHROMEOS_SWAP_METRICS_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/ref_counted.h"
+#include "chrome/browser/ui/browser_list_observer.h"
+#include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
+#include "ui/base/events/event_handler.h"
+
+namespace base {
+class FilePath;
+}
+
+namespace chromeos {
+
+// Watches for bursts of swap activity and CPU consumption after interesting UI
+// events like tab switch or scrolling, recording the values to UMA statistics.
+// Only records stats for the last active browser.
+class SwapMetrics : public chrome::BrowserListObserver,
+                    public TabStripModelObserver,
+                    public ui::EventHandler {
+ public:
+  SwapMetrics();
+  virtual ~SwapMetrics();
+
+  // chrome::BrowserListObserver overrides:
+  virtual void OnBrowserRemoved(Browser* browser) OVERRIDE;
+  virtual void OnBrowserSetLastActive(Browser* browser) OVERRIDE;
+
+  // TabStripModelObserver overrides:
+  virtual void ActiveTabChanged(content::WebContents* old_contents,
+                                content::WebContents* new_contents,
+                                int index,
+                                int reason) OVERRIDE;
+
+  // ui::EventHandler overrides:
+  virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE;
+  virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE;
+
+ private:
+  class Backend;
+
+  // Posts a task to record metrics for |sample_index| after |delay_ms|.
+  static void PostTaskRecordMetrics(scoped_refptr<Backend> backend,
+                                    size_t sample_index,
+                                    int delay_ms);
+
+  // Starts a metrics collection run, canceling any run already in progress.
+  void StartMetricsCollection(const std::string& reason);
+
+  // Sets the browser being monitored for events.
+  void SetBrowser(Browser* browser);
+
+  // Browser being monitored for UI events.
+  Browser* browser_;
+
+  // Backend to handle processing in the blocking thread pool.
+  scoped_refptr<Backend> backend_;
+
+  DISALLOW_COPY_AND_ASSIGN(SwapMetrics);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_SWAP_METRICS_H_
diff --git a/chrome/browser/chromeos/system/ash_system_tray_delegate.cc b/chrome/browser/chromeos/system/ash_system_tray_delegate.cc
index d17df61..f4a6030 100644
--- a/chrome/browser/chromeos/system/ash_system_tray_delegate.cc
+++ b/chrome/browser/chromeos/system/ash_system_tray_delegate.cc
@@ -43,7 +43,7 @@
 #include "base/prefs/pref_service.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
 #include "chrome/browser/chromeos/accessibility/magnification_manager.h"
@@ -84,6 +84,7 @@
 #include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/host_desktop.h"
 #include "chrome/browser/ui/singleton_tabs.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/upgrade_detector.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "chrome/common/pref_names.h"
@@ -104,6 +105,7 @@
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/user_metrics.h"
+#include "content/public/browser/web_contents.h"
 #include "device/bluetooth/bluetooth_adapter.h"
 #include "device/bluetooth/bluetooth_adapter_factory.h"
 #include "device/bluetooth/bluetooth_device.h"
@@ -127,6 +129,9 @@
 // The maximum session length limit that can be set.
 const int kSessionLengthLimitMaxMs = 24 * 60 * 60 * 1000;  // 24 hours.
 
+const char kDisplaySettingsSubPageName[] = "display";
+const char kDisplayOverscanSettingsSubPageName[] = "displayOverscan";
+
 void ExtractIMEInfo(const input_method::InputMethodDescriptor& ime,
                     const input_method::InputMethodUtil& util,
                     ash::IMEInfo* info) {
@@ -464,12 +469,18 @@
         chromeos::UserManager::Get()->GetActiveUser()->email());
   }
 
+  virtual const string16 GetLocallyManagedUserManagerName() const OVERRIDE {
+    if (GetUserLoginStatus() != ash::user::LOGGED_IN_LOCALLY_MANAGED)
+      return string16();
+    return UserManager::Get()->GetManagerDisplayNameForManagedUser(
+        chromeos::UserManager::Get()->GetActiveUser()->email());
+  }
+
   virtual const string16 GetLocallyManagedUserMessage() const OVERRIDE {
     if (GetUserLoginStatus() != ash::user::LOGGED_IN_LOCALLY_MANAGED)
         return string16();
     return l10n_util::GetStringFUTF16(IDS_USER_IS_LOCALLY_MANAGED_BY_NOTICE,
-                                      UTF8ToUTF16(
-                                          GetLocallyManagedUserManager()));
+                                      GetLocallyManagedUserManagerName());
   }
 
   virtual bool SystemShouldUpgrade() const OVERRIDE {
@@ -520,7 +531,32 @@
 
   virtual void ShowDisplaySettings() OVERRIDE {
     content::RecordAction(content::UserMetricsAction("ShowDisplayOptions"));
-    chrome::ShowSettingsSubPage(GetAppropriateBrowser(), "display");
+    chrome::ShowSettingsSubPage(GetAppropriateBrowser(),
+                                kDisplaySettingsSubPageName);
+  }
+
+  virtual bool ShouldShowDisplayNotification() OVERRIDE {
+    // Packaged app is not counted as 'last active', so if a browser opening the
+    // display settings is in background of a packaged app, it will return true.
+    // TODO(mukai): fix this.
+    Browser* active_browser = chrome::FindLastActiveWithHostDesktopType(
+        chrome::HOST_DESKTOP_TYPE_ASH);
+    if (!active_browser)
+      return true;
+
+    content::WebContents* active_contents =
+        active_browser->tab_strip_model()->GetActiveWebContents();
+    if (!active_contents)
+      return true;
+
+    GURL active_url = active_contents->GetActiveURL();
+    std::string display_settings_url =
+        std::string(chrome::kChromeUISettingsURL) + kDisplaySettingsSubPageName;
+    std::string display_overscan_url =
+        std::string(chrome::kChromeUISettingsURL) +
+        kDisplayOverscanSettingsSubPageName;
+    return (active_url.spec() != display_settings_url) &&
+        (active_url.spec() != display_overscan_url);
   }
 
   virtual void ShowDriveSettings() OVERRIDE {
diff --git a/chrome/browser/chromeos/system/automatic_reboot_manager.cc b/chrome/browser/chromeos/system/automatic_reboot_manager.cc
index b13db1c..c77d06e 100644
--- a/chrome/browser/chromeos/system/automatic_reboot_manager.cc
+++ b/chrome/browser/chromeos/system/automatic_reboot_manager.cc
@@ -33,6 +33,7 @@
 #include "base/time/tick_clock.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/login/user_manager.h"
+#include "chrome/browser/chromeos/system/automatic_reboot_manager_observer.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "chrome/common/pref_names.h"
 #include "chromeos/chromeos_paths.h"
@@ -194,6 +195,10 @@
 }
 
 AutomaticRebootManager::~AutomaticRebootManager() {
+  FOR_EACH_OBSERVER(AutomaticRebootManagerObserver,
+                    observers_,
+                    WillDestroyAutomaticRebootManager());
+
   DBusThreadManager* dbus_thread_manager = DBusThreadManager::Get();
   dbus_thread_manager->GetPowerManagerClient()->RemoveObserver(this);
   dbus_thread_manager->GetUpdateEngineClient()->RemoveObserver(this);
@@ -201,6 +206,16 @@
     ash::Shell::GetInstance()->user_activity_detector()->RemoveObserver(this);
 }
 
+void AutomaticRebootManager::AddObserver(
+    AutomaticRebootManagerObserver* observer) {
+  observers_.AddObserver(observer);
+}
+
+void AutomaticRebootManager::RemoveObserver(
+    AutomaticRebootManagerObserver* observer) {
+  observers_.RemoveObserver(observer);
+}
+
 void AutomaticRebootManager::SystemResumed(
     const base::TimeDelta& sleep_duration) {
   MaybeReboot(true);
@@ -303,6 +318,8 @@
   reboot_requested_ = false;
 
   const base::TimeDelta kZeroTimeDelta;
+  AutomaticRebootManagerObserver::Reason reboot_reason =
+      AutomaticRebootManagerObserver::REBOOT_REASON_UNKNOWN;
 
   // If an uptime limit is set, calculate the time at which it should cause a
   // reboot to be requested.
@@ -310,6 +327,8 @@
       local_state_registrar_.prefs()->GetInteger(prefs::kUptimeLimit));
   base::TimeTicks reboot_request_time = boot_time_ + uptime_limit;
   bool have_reboot_request_time = uptime_limit != kZeroTimeDelta;
+  if (have_reboot_request_time)
+    reboot_reason = AutomaticRebootManagerObserver::REBOOT_REASON_PERIODIC;
 
   // If the policy to automatically reboot after an update is enabled and an
   // update has been applied, set the time at which a reboot should be
@@ -321,6 +340,7 @@
        update_reboot_needed_time_ < reboot_request_time)) {
     reboot_request_time = update_reboot_needed_time_;
     have_reboot_request_time = true;
+    reboot_reason = AutomaticRebootManagerObserver::REBOOT_REASON_OS_UPDATE;
   }
 
   // If no reboot should be requested, remove any grace period.
@@ -355,6 +375,12 @@
                           std::max(grace_end_time - now, kZeroTimeDelta),
                           base::Bind(&AutomaticRebootManager::Reboot,
                                      base::Unretained(this)));
+
+  DCHECK_NE(AutomaticRebootManagerObserver::REBOOT_REASON_UNKNOWN,
+            reboot_reason);
+  FOR_EACH_OBSERVER(AutomaticRebootManagerObserver,
+                    observers_,
+                    OnRebootScheduled(reboot_reason));
 }
 
 void AutomaticRebootManager::RequestReboot() {
diff --git a/chrome/browser/chromeos/system/automatic_reboot_manager.h b/chrome/browser/chromeos/system/automatic_reboot_manager.h
index 9d29262..faafcd4 100644
--- a/chrome/browser/chromeos/system/automatic_reboot_manager.h
+++ b/chrome/browser/chromeos/system/automatic_reboot_manager.h
@@ -10,9 +10,10 @@
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
+#include "base/observer_list.h"
 #include "base/prefs/pref_change_registrar.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "chromeos/dbus/power_manager_client.h"
 #include "chromeos/dbus/update_engine_client.h"
 #include "content/public/browser/notification_observer.h"
@@ -27,6 +28,8 @@
 namespace chromeos {
 namespace system {
 
+class AutomaticRebootManagerObserver;
+
 // Schedules and executes automatic reboots.
 //
 // Automatic reboots may be scheduled for any number of reasons. Currently, the
@@ -90,6 +93,9 @@
   explicit AutomaticRebootManager(scoped_ptr<base::TickClock> clock);
   virtual ~AutomaticRebootManager();
 
+  void AddObserver(AutomaticRebootManagerObserver* observer);
+  void RemoveObserver(AutomaticRebootManagerObserver* observer);
+
   // PowerManagerClient::Observer:
   virtual void SystemResumed(const base::TimeDelta& sleep_duration) OVERRIDE;
 
@@ -160,6 +166,8 @@
 
   base::WeakPtrFactory<AutomaticRebootManager> weak_ptr_factory_;
 
+  ObserverList<AutomaticRebootManagerObserver, true> observers_;
+
   DISALLOW_COPY_AND_ASSIGN(AutomaticRebootManager);
 };
 
diff --git a/chrome/browser/chromeos/system/automatic_reboot_manager_observer.h b/chrome/browser/chromeos/system/automatic_reboot_manager_observer.h
new file mode 100644
index 0000000..67c1b50
--- /dev/null
+++ b/chrome/browser/chromeos/system/automatic_reboot_manager_observer.h
@@ -0,0 +1,32 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_SYSTEM_AUTOMATIC_REBOOT_MANAGER_OBSERVER_H_
+#define CHROME_BROWSER_CHROMEOS_SYSTEM_AUTOMATIC_REBOOT_MANAGER_OBSERVER_H_
+
+namespace chromeos {
+namespace system {
+
+class AutomaticRebootManagerObserver {
+ public:
+  enum Reason {
+    REBOOT_REASON_UNKNOWN,
+    REBOOT_REASON_OS_UPDATE,
+    REBOOT_REASON_PERIODIC,
+  };
+
+  // Invoked when a reboot is scheduled.
+  virtual void OnRebootScheduled(Reason reason) = 0;
+
+  // Invoked before the automatic reboot manager is destroyed.
+  virtual void WillDestroyAutomaticRebootManager() = 0;
+
+ protected:
+  virtual ~AutomaticRebootManagerObserver() {}
+};
+
+}  // namespace system
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_SYSTEM_AUTOMATIC_REBOOT_MANAGER_OBSERVER_H_
diff --git a/chrome/browser/chromeos/system/input_device_settings.cc b/chrome/browser/chromeos/system/input_device_settings.cc
index 261dca1..68e6f01 100644
--- a/chrome/browser/chromeos/system/input_device_settings.cc
+++ b/chrome/browser/chromeos/system/input_device_settings.cc
@@ -14,6 +14,7 @@
 #include "base/file_util.h"
 #include "base/files/file_path.h"
 #include "base/message_loop.h"
+#include "base/process.h"
 #include "base/process_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/sequenced_worker_pool.h"
@@ -23,6 +24,7 @@
 namespace system {
 
 namespace {
+
 const char kTpControl[] = "/opt/google/touchpad/tpcontrol";
 const char kMouseControl[] = "/opt/google/mouse/mousecontrol";
 
@@ -43,9 +45,9 @@
   if (!ScriptExists(script))
     return;
 
-  base::LaunchOptions options;
-  options.wait = true;
-  base::LaunchProcess(CommandLine(argv), options, NULL);
+  base::ProcessHandle handle;
+  base::LaunchProcess(CommandLine(argv), base::LaunchOptions(), &handle);
+  base::EnsureProcessGetsReaped(handle);
 }
 
 void ExecuteScript(int argc, ...) {
@@ -64,7 +66,7 @@
 
 void SetPointerSensitivity(const char* script, int value) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-  DCHECK(value > 0 && value < 6);
+  DCHECK(value >= kMinPointerSensitivity && value <= kMaxPointerSensitivity);
   ExecuteScript(
       3, script, "sensitivity", base::StringPrintf("%d", value).c_str());
 }
diff --git a/chrome/browser/chromeos/system/input_device_settings.h b/chrome/browser/chromeos/system/input_device_settings.h
index 5116f92..821c179 100644
--- a/chrome/browser/chromeos/system/input_device_settings.h
+++ b/chrome/browser/chromeos/system/input_device_settings.h
@@ -10,6 +10,11 @@
 namespace chromeos {
 namespace system {
 
+// Min/max possible pointer sensitivity values. Defined in CrOS inputcontrol
+// scripts (see kTpControl/kMouseControl in the source file).
+const int kMinPointerSensitivity = 1;
+const int kMaxPointerSensitivity = 5;
+
 typedef base::Callback<void(bool)> DeviceExistsCallback;
 
 namespace touchpad_settings {
diff --git a/chrome/browser/chromeos/system/statistics_provider.cc b/chrome/browser/chromeos/system/statistics_provider.cc
index 5f82b2a..e58278b 100644
--- a/chrome/browser/chromeos/system/statistics_provider.cc
+++ b/chrome/browser/chromeos/system/statistics_provider.cc
@@ -13,7 +13,7 @@
 #include "base/path_service.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/threading/thread_restrictions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chromeos/app_mode/kiosk_oem_manifest_parser.h"
 #include "chromeos/chromeos_constants.h"
 #include "chromeos/chromeos_switches.h"
@@ -75,6 +75,22 @@
 
 }  // namespace
 
+// Key values for GetMachineStatistic()/GetMachineFlag() calls.
+const char kDevSwitchBootMode[] = "devsw_boot";
+const char kHardwareClass[] = "hardware_class";
+const char kMachineInfoBoard[] =
+    "CHROMEOS_RELEASE_BOARD";
+const char kOffersCouponCodeKey[] = "ubind_attribute";
+const char kOffersGroupCodeKey[] = "gbind_attribute";
+const char kOemCanExitEnterpriseEnrollmentKey[] =
+    "oem_can_exit_enrollment";
+const char kOemDeviceRequisitionKey[] =
+    "oem_device_requisition";
+const char kOemIsEnterpriseManagedKey[] =
+    "oem_enterprise_managed";
+const char kOemKeyboardDrivenOobeKey[] =
+    "oem_keyboard_driven_oobe";
+
 // The StatisticsProvider implementation used in production.
 class StatisticsProviderImpl : public StatisticsProvider {
  public:
@@ -252,13 +268,13 @@
   if (!KioskOemManifestParser::Load(file, &oem_manifest))
     return;
 
-  machine_info_[chromeos::kOemDeviceRequisitionKey] =
+  machine_info_[kOemDeviceRequisitionKey] =
       oem_manifest.device_requisition;
-  machine_flags_[chromeos::kOemIsEnterpriseManagedKey] =
+  machine_flags_[kOemIsEnterpriseManagedKey] =
       oem_manifest.enterprise_managed;
-  machine_flags_[chromeos::kOemCanExitEnterpriseEnrollmentKey] =
+  machine_flags_[kOemCanExitEnterpriseEnrollmentKey] =
       oem_manifest.can_exit_enrollment;
-  machine_flags_[chromeos::kOemKeyboardDrivenOobeKey] =
+  machine_flags_[kOemKeyboardDrivenOobeKey] =
       oem_manifest.keyboard_driven_oobe;
 }
 
diff --git a/chrome/browser/chromeos/system/statistics_provider.h b/chrome/browser/chromeos/system/statistics_provider.h
index b193563..48e7dd8 100644
--- a/chrome/browser/chromeos/system/statistics_provider.h
+++ b/chrome/browser/chromeos/system/statistics_provider.h
@@ -10,6 +10,35 @@
 namespace chromeos {
 namespace system {
 
+// Developer switch value.
+extern const char kDevSwitchBootMode[];
+
+// HWID key.
+extern const char kHardwareClass[];
+
+// Machine board key.
+extern const char kMachineInfoBoard[];
+
+// OEM customization flag that permits exiting enterprise enrollment flow in
+// OOBE when 'oem_enterprise_managed' flag is set.
+extern const char kOemCanExitEnterpriseEnrollmentKey[];
+
+// OEM customization directive that specified intended device purpose.
+extern const char kOemDeviceRequisitionKey[];
+
+// OEM customization flag that enforces enterprise enrollment flow in OOBE.
+extern const char kOemIsEnterpriseManagedKey[];
+
+// OEM customization flag that specifies if OOBE flow should be enhanced for
+// keyboard driven control.
+extern const char kOemKeyboardDrivenOobeKey[];
+
+// Offer coupon code key.
+extern const char kOffersCouponCodeKey[];
+
+// Offer group key.
+extern const char kOffersGroupCodeKey[];
+
 // This interface provides access to Chrome OS statistics.
 class StatisticsProvider {
  public:
diff --git a/chrome/browser/chromeos/system/syslogs_provider.cc b/chrome/browser/chromeos/system/syslogs_provider.cc
index 1c7e06a..643d355 100644
--- a/chrome/browser/chromeos/system/syslogs_provider.cc
+++ b/chrome/browser/chromeos/system/syslogs_provider.cc
@@ -146,7 +146,7 @@
                                                   &data);
   // if we were using an internal temp file, the user does not need the
   // logs to stay past the ReadFile call - delete the file
-  file_util::Delete(temp_filename, false);
+  base::Delete(temp_filename, false);
 
   if (!read_success)
     return NULL;
@@ -321,7 +321,7 @@
     // Load compressed logs.
     zip_content = new std::string();
     LoadCompressedLogs(zip_file, zip_content);
-    file_util::Delete(zip_file, false);
+    base::Delete(zip_file, false);
   }
 
   // Include dbus statistics summary
diff --git a/chrome/browser/chromeos/system/timezone_settings.cc b/chrome/browser/chromeos/system/timezone_settings.cc
index 4f59057..5aa6593 100644
--- a/chrome/browser/chromeos/system/timezone_settings.cc
+++ b/chrome/browser/chromeos/system/timezone_settings.cc
@@ -208,7 +208,7 @@
   }
 
   // Delete old symlink2 if it exists.
-  file_util::Delete(timezone_symlink2, false);
+  base::Delete(timezone_symlink2, false);
 
   // Create new symlink2.
   if (symlink(timezone_file.value().c_str(),
@@ -219,7 +219,7 @@
   }
 
   // Move symlink2 to symlink.
-  if (!file_util::ReplaceFile(timezone_symlink2, timezone_symlink)) {
+  if (!base::ReplaceFile(timezone_symlink2, timezone_symlink, NULL)) {
     LOG(ERROR) << "SetTimezoneID: Unable to move symlink "
                << timezone_symlink2.value() << " to "
                << timezone_symlink.value();
@@ -352,21 +352,12 @@
 }
 
 void TimezoneSettingsBaseImpl::NotifyRenderers() {
-  content::RenderProcessHost::iterator process_iterator(
-      content::RenderProcessHost::AllHostsIterator());
-  for (; !process_iterator.IsAtEnd(); process_iterator.Advance()) {
-    content::RenderProcessHost* render_process_host =
-        process_iterator.GetCurrentValue();
-    content::RenderProcessHost::RenderWidgetHostsIterator widget_iterator(
-        render_process_host->GetRenderWidgetHostsIterator());
-    for (; !widget_iterator.IsAtEnd(); widget_iterator.Advance()) {
-      const content::RenderWidgetHost* widget =
-          widget_iterator.GetCurrentValue();
-      if (widget->IsRenderView()) {
-        content::RenderViewHost* view = content::RenderViewHost::From(
-            const_cast<content::RenderWidgetHost*>(widget));
-        view->NotifyTimezoneChange();
-      }
+  content::RenderWidgetHost::List widgets =
+      content::RenderWidgetHost::GetRenderWidgetHosts();
+  for (size_t i = 0; i < widgets.size(); ++i) {
+    if (widgets[i]->IsRenderView()) {
+      content::RenderViewHost* view = content::RenderViewHost::From(widgets[i]);
+      view->NotifyTimezoneChange();
     }
   }
 }
diff --git a/chrome/browser/chromeos/system_logs/touch_log_source.cc b/chrome/browser/chromeos/system_logs/touch_log_source.cc
index 7e2b263..2acbdee 100644
--- a/chrome/browser/chromeos/system_logs/touch_log_source.cc
+++ b/chrome/browser/chromeos/system_logs/touch_log_source.cc
@@ -4,7 +4,7 @@
 
 #include "chrome/browser/chromeos/system_logs/touch_log_source.h"
 
-#include "ash/touch/touch_observer_hud.h"
+#include "ash/touch/touch_hud_debug.h"
 #include "base/json/json_string_value_serializer.h"
 #include "chrome/browser/feedback/feedback_util.h"
 #include "content/public/browser/browser_thread.h"
@@ -25,7 +25,7 @@
 
   SystemLogsResponse response;
   scoped_ptr<DictionaryValue> dictionary =
-      ash::internal::TouchObserverHUD::GetAllAsDictionary();
+      ash::internal::TouchHudDebug::GetAllAsDictionary();
   if (!dictionary->empty()) {
     std::string touch_log;
     JSONStringValueSerializer json(&touch_log);
diff --git a/chrome/browser/chromeos/ui/focus_ring_controller.cc b/chrome/browser/chromeos/ui/focus_ring_controller.cc
index 1c089de..6a9459a 100644
--- a/chrome/browser/chromeos/ui/focus_ring_controller.cc
+++ b/chrome/browser/chromeos/ui/focus_ring_controller.cc
@@ -27,8 +27,9 @@
 
   if (visible_) {
     views::WidgetFocusManager::GetInstance()->AddFocusChangeListener(this);
-    SetWidget(views::Widget::GetWidgetForNativeWindow(
-        ash::wm::GetActiveWindow()));
+    aura::Window* active_window = ash::wm::GetActiveWindow();
+    if (active_window)
+      SetWidget(views::Widget::GetWidgetForNativeWindow(active_window));
   } else {
     views::WidgetFocusManager::GetInstance()->RemoveFocusChangeListener(this);
     SetWidget(NULL);
@@ -86,7 +87,8 @@
 
 void FocusRingController::OnNativeFocusChange(gfx::NativeView focused_before,
                                               gfx::NativeView focused_now) {
-  views::Widget* widget = views::Widget::GetWidgetForNativeWindow(focused_now);
+  views::Widget* widget =
+      focused_now ? views::Widget::GetWidgetForNativeWindow(focused_now) : NULL;
   SetWidget(widget);
 }
 
diff --git a/chrome/browser/chromeos/ui/idle_logout_dialog_view.cc b/chrome/browser/chromeos/ui/idle_logout_dialog_view.cc
index 7d87000..63b9c7e 100644
--- a/chrome/browser/chromeos/ui/idle_logout_dialog_view.cc
+++ b/chrome/browser/chromeos/ui/idle_logout_dialog_view.cc
@@ -9,7 +9,7 @@
 #include "base/bind_helpers.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
diff --git a/chrome/browser/chromeos/ui/idle_logout_dialog_view.h b/chrome/browser/chromeos/ui/idle_logout_dialog_view.h
index 720f12d..f96cd64 100644
--- a/chrome/browser/chromeos/ui/idle_logout_dialog_view.h
+++ b/chrome/browser/chromeos/ui/idle_logout_dialog_view.h
@@ -7,7 +7,7 @@
 
 #include "base/gtest_prod_util.h"
 #include "base/memory/weak_ptr.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "ui/views/window/dialog_delegate.h"
 
 namespace base {
diff --git a/chrome/browser/chromeos/upgrade_detector_chromeos.h b/chrome/browser/chromeos/upgrade_detector_chromeos.h
index 62eb07a..f3853b7 100644
--- a/chrome/browser/chromeos/upgrade_detector_chromeos.h
+++ b/chrome/browser/chromeos/upgrade_detector_chromeos.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_CHROMEOS_UPGRADE_DETECTOR_CHROMEOS_H_
 
 #include "base/compiler_specific.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/upgrade_detector.h"
 #include "chromeos/dbus/update_engine_client.h"
 
diff --git a/chrome/browser/chromeos/version_loader.cc b/chrome/browser/chromeos/version_loader.cc
index cd4aa04..5e65c26 100644
--- a/chrome/browser/chromeos/version_loader.cc
+++ b/chrome/browser/chromeos/version_loader.cc
@@ -16,7 +16,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/threading/sequenced_worker_pool.h"
 #include "base/threading/thread.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/browser_process.h"
 #include "content/public/browser/browser_thread.h"
 
diff --git a/chrome/browser/collected_cookies_browsertest.cc b/chrome/browser/collected_cookies_browsertest.cc
index 539fcac..b26c17e 100644
--- a/chrome/browser/collected_cookies_browsertest.cc
+++ b/chrome/browser/collected_cookies_browsertest.cc
@@ -13,20 +13,13 @@
 #include "chrome/common/url_constants.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
-#include "net/test/spawned_test_server/spawned_test_server.h"
-
-namespace {
-
-const base::FilePath::CharType kDocRoot[] =
-    FILE_PATH_LITERAL("chrome/test/data");
-
-}  // namespace
+#include "net/test/embedded_test_server/embedded_test_server.h"
 
 typedef InProcessBrowserTest CollectedCookiesTest;
 
 // If this crashes on Windows, use http://crbug.com/79331
 IN_PROC_BROWSER_TEST_F(CollectedCookiesTest, DoubleDisplay) {
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   // Disable cookies.
   CookieSettings::Factory::GetForProfile(browser()->profile())->
@@ -34,7 +27,7 @@
 
   // Load a page with cookies.
   ui_test_utils::NavigateToURL(
-      browser(), test_server()->GetURL("files/cookie1.html"));
+      browser(), embedded_test_server()->GetURL("/cookie1.html"));
 
   // Click on the info link twice.
   content::WebContents* web_contents =
@@ -52,7 +45,7 @@
 
   // Load a page with cookies.
   ui_test_utils::NavigateToURL(
-      browser(), test_server()->GetURL("files/cookie1.html"));
+      browser(), embedded_test_server()->GetURL("/cookie1.html"));
 
   // Click on the info link.
   content::WebContents* web_contents =
@@ -61,5 +54,5 @@
 
   // Navigate to another page.
   ui_test_utils::NavigateToURL(
-      browser(), test_server()->GetURL("files/cookie2.html"));
+      browser(), embedded_test_server()->GetURL("/cookie2.html"));
 }
diff --git a/chrome/browser/component_updater/component_patcher.cc b/chrome/browser/component_updater/component_patcher.cc
new file mode 100644
index 0000000..54bc62d
--- /dev/null
+++ b/chrome/browser/component_updater/component_patcher.cc
@@ -0,0 +1,81 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/component_updater/component_patcher.h"
+
+#include <string>
+#include <vector>
+
+#include "base/file_util.h"
+#include "base/json/json_file_value_serializer.h"
+#include "base/values.h"
+#include "chrome/browser/component_updater/component_patcher_operation.h"
+#include "chrome/browser/component_updater/component_updater_service.h"
+
+namespace {
+
+// Deserialize the commands file (present in delta update packages). The top
+// level must be a list.
+base::ListValue* ReadCommands(const base::FilePath& unpack_path) {
+  const base::FilePath commands =
+      unpack_path.Append(FILE_PATH_LITERAL("commands.json"));
+  if (!file_util::PathExists(commands))
+    return NULL;
+
+  JSONFileValueSerializer serializer(commands);
+  scoped_ptr<base::Value> root(serializer.Deserialize(NULL, NULL));
+
+  return (root.get() && root->IsType(base::Value::TYPE_LIST)) ?
+      static_cast<base::ListValue*>(root.release()) : NULL;
+}
+
+}  // namespace
+
+
+// The patching support is not cross-platform at the moment.
+ComponentPatcherCrossPlatform::ComponentPatcherCrossPlatform() {}
+
+ComponentUnpacker::Error ComponentPatcherCrossPlatform::Patch(
+    PatchType patch_type,
+    const base::FilePath& input_file,
+    const base::FilePath& patch_file,
+    const base::FilePath& output_file,
+    int* error) {
+  return ComponentUnpacker::kDeltaUnsupportedCommand;
+}
+
+
+// Takes the contents of a differential component update in input_dir
+// and produces the contents of a full component update in unpack_dir
+// using input_abs_path_ files that the installer knows about.
+ComponentUnpacker::Error DifferentialUpdatePatch(
+    const base::FilePath& input_dir,
+    const base::FilePath& unpack_dir,
+    ComponentPatcher* patcher,
+    ComponentInstaller* installer,
+    int* error) {
+  *error = 0;
+  scoped_ptr<base::ListValue> commands(ReadCommands(input_dir));
+  if (!commands.get())
+    return ComponentUnpacker::kDeltaBadCommands;
+
+  for (base::ValueVector::const_iterator command = commands->begin(),
+      end = commands->end(); command != end; command++) {
+    if (!(*command)->IsType(base::Value::TYPE_DICTIONARY))
+      return ComponentUnpacker::kDeltaBadCommands;
+    base::DictionaryValue* command_args =
+        static_cast<base::DictionaryValue*>(*command);
+    scoped_ptr<DeltaUpdateOp> operation(CreateDeltaUpdateOp(command_args));
+    if (!operation)
+      return ComponentUnpacker::kDeltaUnsupportedCommand;
+
+    ComponentUnpacker::Error result = operation->Run(
+        command_args, input_dir, unpack_dir, patcher, installer, error);
+    if (result != ComponentUnpacker::kNone)
+      return result;
+  }
+
+  return ComponentUnpacker::kNone;
+}
+
diff --git a/chrome/browser/component_updater/component_patcher.h b/chrome/browser/component_updater/component_patcher.h
new file mode 100644
index 0000000..1990922
--- /dev/null
+++ b/chrome/browser/component_updater/component_patcher.h
@@ -0,0 +1,86 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Component updates can be either differential updates or full updates.
+// Full updates come in CRX format; differential updates come in CRX-style
+// archives, but have a different magic number. They contain "commands.json", a
+// list of commands for the patcher to follow. The patcher uses these commands,
+// the other files in the archive, and the files from the existing installation
+// of the component to create the contents of a full update, which is then
+// installed normally.
+// Component updates are specified by the 'codebasediff' attribute of an
+// updatecheck response:
+//   <updatecheck codebase="http://example.com/extension_1.2.3.4.crx"
+//                hash="12345" size="9854" status="ok" version="1.2.3.4"
+//                prodversionmin="2.0.143.0"
+//                codebasediff="http://example.com/diff_1.2.3.4.crx"
+//                hashdiff="123" sizediff="101"
+//                fp="1.123" />
+// The component updater will attempt a differential update if it is available
+// and allowed to, and fall back to a full update if it fails.
+//
+// After installation (diff or full), the component updater records "fp", the
+// fingerprint of the installed files, to later identify the existing files to
+// the server so that a proper differential update can be provided next cycle.
+
+
+#ifndef CHROME_BROWSER_COMPONENT_UPDATER_COMPONENT_PATCHER_H_
+#define CHROME_BROWSER_COMPONENT_UPDATER_COMPONENT_PATCHER_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "chrome/browser/component_updater/component_unpacker.h"
+
+namespace base {
+class FilePath;
+}
+
+class ComponentInstaller;
+
+// Applies a delta patch to a single file. Specifically, creates a file at
+// |output_file| using |input_file| patched according to the algorithm
+// specified by |patch_type| using |patch_file|. Sets the value of error to
+// the error code of the failing patch operation, if there is such a failure.
+class ComponentPatcher {
+ public:
+  // The type of a patch file.
+  enum PatchType {
+    kPatchTypeUnknown,
+    kPatchTypeCourgette,
+    kPatchTypeBsdiff,
+  };
+
+  virtual ComponentUnpacker::Error Patch(PatchType patch_type,
+                                         const base::FilePath& input_file,
+                                         const base::FilePath& patch_file,
+                                         const base::FilePath& output_file,
+                                         int* error) = 0;
+  virtual ~ComponentPatcher() {}
+};
+
+class ComponentPatcherCrossPlatform : public ComponentPatcher {
+ public:
+  ComponentPatcherCrossPlatform();
+  virtual ComponentUnpacker::Error Patch(PatchType patch_type,
+                                         const base::FilePath& input_file,
+                                         const base::FilePath& patch_file,
+                                         const base::FilePath& output_file,
+                                         int* error) OVERRIDE;
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ComponentPatcherCrossPlatform);
+};
+
+// This function takes an unpacked differential CRX (|input_dir|) and a
+// component installer, and creates a new (non-differential) unpacked CRX, which
+// is then installed normally.
+// The non-differential files are written into the |unpack_dir| directory.
+// Sets |error| to the error code of the first failing patch operation.
+ComponentUnpacker::Error DifferentialUpdatePatch(
+    const base::FilePath& input_dir,
+    const base::FilePath& unpack_dir,
+    ComponentPatcher* component_patcher,
+    ComponentInstaller* installer,
+    int* error);
+
+#endif  // CHROME_BROWSER_COMPONENT_UPDATER_COMPONENT_PATCHER_H_
diff --git a/chrome/browser/component_updater/component_patcher_operation.cc b/chrome/browser/component_updater/component_patcher_operation.cc
new file mode 100644
index 0000000..f814238
--- /dev/null
+++ b/chrome/browser/component_updater/component_patcher_operation.cc
@@ -0,0 +1,222 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/component_updater/component_patcher_operation.h"
+
+#include <string>
+#include <vector>
+
+#include "base/file_util.h"
+#include "base/files/memory_mapped_file.h"
+#include "base/json/json_file_value_serializer.h"
+#include "base/memory/scoped_handle.h"
+#include "base/path_service.h"
+#include "base/strings/string_number_conversions.h"
+#include "chrome/browser/component_updater/component_patcher.h"
+#include "chrome/browser/component_updater/component_updater_service.h"
+#include "chrome/common/extensions/extension_constants.h"
+#include "crypto/secure_hash.h"
+#include "crypto/sha2.h"
+#include "crypto/signature_verifier.h"
+#include "extensions/common/crx_file.h"
+#include "third_party/zlib/google/zip.h"
+
+using crypto::SecureHash;
+
+namespace {
+
+const char kInput[] = "input";
+const char kOp[] = "op";
+const char kOutput[] = "output";
+const char kPatch[] = "patch";
+const char kSha256[] = "sha256";
+
+}  // namespace
+
+DeltaUpdateOp* CreateDeltaUpdateOp(base::DictionaryValue* command) {
+  std::string operation;
+  if (!command->GetString(kOp, &operation))
+    return NULL;
+  if (operation == "copy")
+    return new DeltaUpdateOpCopy();
+  else if (operation == "create")
+    return new DeltaUpdateOpCreate();
+  else if (operation == "bsdiff")
+    return new DeltaUpdateOpPatchBsdiff();
+  else if (operation == "courgette")
+    return new DeltaUpdateOpPatchCourgette();
+  return NULL;
+}
+
+DeltaUpdateOp::DeltaUpdateOp() {}
+
+DeltaUpdateOp::~DeltaUpdateOp() {}
+
+ComponentUnpacker::Error DeltaUpdateOp::Run(base::DictionaryValue* command_args,
+                                            const base::FilePath& input_dir,
+                                            const base::FilePath& unpack_dir,
+                                            ComponentPatcher* patcher,
+                                            ComponentInstaller* installer,
+                                            int* error) {
+  std::string output_rel_path;
+  if (!command_args->GetString(kOutput, &output_rel_path) ||
+      !command_args->GetString(kSha256, &output_sha256_))
+    return ComponentUnpacker::kDeltaBadCommands;
+
+  output_abs_path_ = unpack_dir.Append(
+      base::FilePath::FromUTF8Unsafe(output_rel_path));
+  ComponentUnpacker::Error parse_result = DoParseArguments(
+      command_args, input_dir, installer);
+  if (parse_result != ComponentUnpacker::kNone)
+    return parse_result;
+
+  const base::FilePath parent = output_abs_path_.DirName();
+  if (!file_util::DirectoryExists(parent)) {
+    if (!file_util::CreateDirectory(parent))
+      return ComponentUnpacker::kIoError;
+  }
+
+  ComponentUnpacker::Error run_result = DoRun(patcher, error);
+  if (run_result != ComponentUnpacker::kNone)
+    return run_result;
+
+  return CheckHash();
+}
+
+// Uses the hash as a checksum to confirm that the file now residing in the
+// output directory probably has the contents it should.
+ComponentUnpacker::Error DeltaUpdateOp::CheckHash() {
+  std::vector<uint8> expected_hash;
+  if (!base::HexStringToBytes(output_sha256_, &expected_hash) ||
+      expected_hash.size() != crypto::kSHA256Length)
+    return ComponentUnpacker::kDeltaVerificationFailure;
+
+  base::MemoryMappedFile output_file_mmapped;
+  if (!output_file_mmapped.Initialize(output_abs_path_))
+    return ComponentUnpacker::kDeltaVerificationFailure;
+
+  uint8 actual_hash[crypto::kSHA256Length] = {0};
+  const scoped_ptr<SecureHash> hasher(SecureHash::Create(SecureHash::SHA256));
+  hasher->Update(output_file_mmapped.data(), output_file_mmapped.length());
+  hasher->Finish(actual_hash, sizeof(actual_hash));
+  if (memcmp(actual_hash, &expected_hash[0], sizeof(actual_hash)))
+    return ComponentUnpacker::kDeltaVerificationFailure;
+
+  return ComponentUnpacker::kNone;
+}
+
+DeltaUpdateOpCopy::DeltaUpdateOpCopy() {}
+
+ComponentUnpacker::Error DeltaUpdateOpCopy::DoParseArguments(
+    base::DictionaryValue* command_args,
+    const base::FilePath& input_dir,
+    ComponentInstaller* installer) {
+  std::string input_rel_path;
+  if (!command_args->GetString(kInput, &input_rel_path))
+    return ComponentUnpacker::kDeltaBadCommands;
+
+  if (!installer->GetInstalledFile(input_rel_path, &input_abs_path_))
+    return ComponentUnpacker::kDeltaMissingExistingFile;
+
+  return ComponentUnpacker::kNone;
+}
+
+ComponentUnpacker::Error DeltaUpdateOpCopy::DoRun(ComponentPatcher*,
+                                                  int* error) {
+  *error = 0;
+  if (!file_util::CopyFile(input_abs_path_, output_abs_path_))
+    return ComponentUnpacker::kDeltaOperationFailure;
+
+  return ComponentUnpacker::kNone;
+}
+
+DeltaUpdateOpCreate::DeltaUpdateOpCreate() {}
+
+ComponentUnpacker::Error DeltaUpdateOpCreate::DoParseArguments(
+    base::DictionaryValue* command_args,
+    const base::FilePath& input_dir,
+    ComponentInstaller* installer) {
+  std::string patch_rel_path;
+  if (!command_args->GetString(kPatch, &patch_rel_path))
+    return ComponentUnpacker::kDeltaBadCommands;
+
+  patch_abs_path_ = input_dir.Append(
+      base::FilePath::FromUTF8Unsafe(patch_rel_path));
+
+  return ComponentUnpacker::kNone;
+}
+
+ComponentUnpacker::Error DeltaUpdateOpCreate::DoRun(ComponentPatcher*,
+                                                    int* error) {
+  *error = 0;
+  if (!base::Move(patch_abs_path_, output_abs_path_))
+    return ComponentUnpacker::kDeltaOperationFailure;
+
+  return ComponentUnpacker::kNone;
+}
+
+DeltaUpdateOpPatchBsdiff::DeltaUpdateOpPatchBsdiff() {}
+
+ComponentUnpacker::Error DeltaUpdateOpPatchBsdiff::DoParseArguments(
+    base::DictionaryValue* command_args,
+    const base::FilePath& input_dir,
+    ComponentInstaller* installer) {
+  std::string patch_rel_path;
+  std::string input_rel_path;
+  if (!command_args->GetString(kPatch, &patch_rel_path) ||
+      !command_args->GetString(kInput, &input_rel_path))
+    return ComponentUnpacker::kDeltaBadCommands;
+
+  if (!installer->GetInstalledFile(input_rel_path, &input_abs_path_))
+    return ComponentUnpacker::kDeltaMissingExistingFile;
+
+  patch_abs_path_ = input_dir.Append(
+      base::FilePath::FromUTF8Unsafe(patch_rel_path));
+
+  return ComponentUnpacker::kNone;
+}
+
+ComponentUnpacker::Error DeltaUpdateOpPatchBsdiff::DoRun(
+    ComponentPatcher* patcher,
+    int* error) {
+  *error = 0;
+  return patcher->Patch(ComponentPatcher::kPatchTypeBsdiff,
+                        input_abs_path_,
+                        patch_abs_path_,
+                        output_abs_path_,
+                        error);
+}
+
+DeltaUpdateOpPatchCourgette::DeltaUpdateOpPatchCourgette() {}
+
+ComponentUnpacker::Error DeltaUpdateOpPatchCourgette::DoParseArguments(
+    base::DictionaryValue* command_args,
+    const base::FilePath& input_dir,
+    ComponentInstaller* installer) {
+  std::string patch_rel_path;
+  std::string input_rel_path;
+  if (!command_args->GetString(kPatch, &patch_rel_path) ||
+      !command_args->GetString(kInput, &input_rel_path))
+    return ComponentUnpacker::kDeltaBadCommands;
+
+  if (!installer->GetInstalledFile(input_rel_path, &input_abs_path_))
+    return ComponentUnpacker::kDeltaMissingExistingFile;
+
+  patch_abs_path_ = input_dir.Append(
+      base::FilePath::FromUTF8Unsafe(patch_rel_path));
+
+  return ComponentUnpacker::kNone;
+}
+
+ComponentUnpacker::Error DeltaUpdateOpPatchCourgette::DoRun(
+    ComponentPatcher* patcher,
+    int* error) {
+  *error = 0;
+  return patcher->Patch(ComponentPatcher::kPatchTypeCourgette,
+                        input_abs_path_,
+                        patch_abs_path_,
+                        output_abs_path_,
+                        error);
+}
+
diff --git a/chrome/browser/component_updater/component_patcher_operation.h b/chrome/browser/component_updater/component_patcher_operation.h
new file mode 100644
index 0000000..6e9fe5b
--- /dev/null
+++ b/chrome/browser/component_updater/component_patcher_operation.h
@@ -0,0 +1,158 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_COMPONENT_UPDATER_COMPONENT_PATCHER_OPERATION_H_
+#define CHROME_BROWSER_COMPONENT_UPDATER_COMPONENT_PATCHER_OPERATION_H_
+
+#include <string>
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "chrome/browser/component_updater/component_unpacker.h"
+
+namespace base {
+
+class FilePath;
+class DictionaryValue;
+
+}  // namespace base
+
+class ComponentInstaller;
+class ComponentPatcher;
+
+class DeltaUpdateOp {
+ public:
+
+  DeltaUpdateOp();
+  virtual ~DeltaUpdateOp();
+
+  // Parses, runs, and verifies the operation, returning an error code if an
+  // error is encountered, and DELTA_OK otherwise. In case of errors,
+  // extended error information can be returned in the |error| parameter.
+  ComponentUnpacker::Error Run(
+      base::DictionaryValue* command_args,
+      const base::FilePath& input_dir,
+      const base::FilePath& unpack_dir,
+      ComponentPatcher* patcher,
+      ComponentInstaller* installer,
+      int* error);
+
+ protected:
+  std::string output_sha256_;
+  base::FilePath output_abs_path_;
+
+ private:
+  ComponentUnpacker::Error CheckHash();
+
+  // Subclasses must override DoParseArguments to parse operation-specific
+  // arguments. DoParseArguments returns DELTA_OK on success; any other code
+  // represents failure.
+  virtual ComponentUnpacker::Error DoParseArguments(
+      base::DictionaryValue* command_args,
+      const base::FilePath& input_dir,
+      ComponentInstaller* installer) = 0;
+
+  // Subclasses must override DoRun to actually perform the patching operation.
+  // DoRun returns DELTA_OK on success; any other code represents failure.
+  // Additional error information can be returned in the |error| parameter.
+  virtual ComponentUnpacker::Error DoRun(ComponentPatcher* patcher,
+                                         int* error) = 0;
+
+  DISALLOW_COPY_AND_ASSIGN(DeltaUpdateOp);
+};
+
+// A 'copy' operation takes a file currently residing on the disk and moves it
+// into the unpacking directory: this represents "no change" in the file being
+// installed.
+class DeltaUpdateOpCopy : public DeltaUpdateOp {
+ public:
+  DeltaUpdateOpCopy();
+
+ private:
+  // Overrides of DeltaUpdateOp.
+  virtual ComponentUnpacker::Error DoParseArguments(
+      base::DictionaryValue* command_args,
+      const base::FilePath& input_dir,
+      ComponentInstaller* installer) OVERRIDE;
+
+  virtual ComponentUnpacker::Error DoRun(ComponentPatcher* patcher,
+                                         int* error) OVERRIDE;
+
+  base::FilePath input_abs_path_;
+
+  DISALLOW_COPY_AND_ASSIGN(DeltaUpdateOpCopy);
+};
+
+// A 'create' operation takes a full file that was sent in the delta update
+// archive and moves it into the unpacking directory: this represents the
+// addition of a new file, or a file so different that no bandwidth could be
+// saved by transmitting a differential update.
+class DeltaUpdateOpCreate : public DeltaUpdateOp {
+ public:
+  DeltaUpdateOpCreate();
+
+ private:
+  // Overrides of DeltaUpdateOp.
+  virtual ComponentUnpacker::Error DoParseArguments(
+      base::DictionaryValue* command_args,
+      const base::FilePath& input_dir,
+      ComponentInstaller* installer) OVERRIDE;
+
+  virtual ComponentUnpacker::Error DoRun(ComponentPatcher* patcher,
+                                         int* error) OVERRIDE;
+
+  base::FilePath patch_abs_path_;
+
+  DISALLOW_COPY_AND_ASSIGN(DeltaUpdateOpCreate);
+};
+
+// A 'bsdiff' operation takes an existing file on disk, and a bsdiff-
+// format patch file provided in the delta update package, and runs bsdiff
+// to construct an output file in the unpacking directory.
+class DeltaUpdateOpPatchBsdiff : public DeltaUpdateOp {
+ public:
+  DeltaUpdateOpPatchBsdiff();
+
+ private:
+  // Overrides of DeltaUpdateOp.
+  virtual ComponentUnpacker::Error DoParseArguments(
+      base::DictionaryValue* command_args,
+      const base::FilePath& input_dir,
+      ComponentInstaller* installer) OVERRIDE;
+
+  virtual ComponentUnpacker::Error DoRun(ComponentPatcher* patcher,
+                                         int* error) OVERRIDE;
+
+  base::FilePath patch_abs_path_;
+  base::FilePath input_abs_path_;
+
+  DISALLOW_COPY_AND_ASSIGN(DeltaUpdateOpPatchBsdiff);
+};
+
+// A 'courgette' operation takes an existing file on disk, and a Courgette-
+// format patch file provided in the delta update package, and runs Courgette
+// to construct an output file in the unpacking directory.
+class DeltaUpdateOpPatchCourgette : public DeltaUpdateOp {
+ public:
+  DeltaUpdateOpPatchCourgette();
+
+ private:
+  // Overrides of DeltaUpdateOp.
+  virtual ComponentUnpacker::Error DoParseArguments(
+      base::DictionaryValue* command_args,
+      const base::FilePath& input_dir,
+      ComponentInstaller* installer) OVERRIDE;
+
+  virtual ComponentUnpacker::Error DoRun(ComponentPatcher* patcher,
+                                         int* error) OVERRIDE;
+
+  base::FilePath patch_abs_path_;
+  base::FilePath input_abs_path_;
+
+  DISALLOW_COPY_AND_ASSIGN(DeltaUpdateOpPatchCourgette);
+};
+
+// Factory function to create DeltaUpdateOp instances.
+DeltaUpdateOp* CreateDeltaUpdateOp(base::DictionaryValue* command);
+
+#endif  // CHROME_BROWSER_COMPONENT_UPDATER_COMPONENT_PATCHER_OPERATION_H_
diff --git a/chrome/browser/component_updater/component_patcher_win.cc b/chrome/browser/component_updater/component_patcher_win.cc
new file mode 100644
index 0000000..a2f6865
--- /dev/null
+++ b/chrome/browser/component_updater/component_patcher_win.cc
@@ -0,0 +1,112 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/component_updater/component_patcher_win.h"
+
+#include <string>
+
+#include "base/base_paths.h"
+#include "base/command_line.h"
+#include "base/file_util.h"
+#include "base/path_service.h"
+#include "base/process_util.h"
+#include "base/strings/string_util.h"
+#include "base/win/scoped_handle.h"
+#include "chrome/installer/util/util_constants.h"
+
+namespace {
+
+std::string PatchTypeToCommandLineSwitch(
+    ComponentPatcher::PatchType patch_type) {
+  if (patch_type == ComponentPatcher::kPatchTypeCourgette)
+    return std::string(installer::kCourgette);
+  else if (patch_type == ComponentPatcher::kPatchTypeBsdiff)
+    return std::string(installer::kBsdiff);
+  else
+    return std::string();
+}
+
+// Finds the path to the setup.exe. First, it looks for the program in the
+// "installer" directory. If the program is not found there, it tries to find it
+// in the directory where chrome.dll lives. Returns the path to the setup.exe,
+// if the path exists, otherwise it returns an an empty path.
+base::FilePath FindSetupProgram() {
+  base::FilePath exe_dir;
+  if (!PathService::Get(base::DIR_MODULE, &exe_dir))
+    return base::FilePath();
+
+  const std::string installer_dir(WideToASCII(installer::kInstallerDir));
+  const std::string setup_exe(WideToASCII(installer::kSetupExe));
+
+  base::FilePath setup_path = exe_dir;
+  setup_path = setup_path.AppendASCII(installer_dir);
+  setup_path = setup_path.AppendASCII(setup_exe);
+  if (file_util::PathExists(setup_path))
+    return setup_path;
+
+  setup_path = exe_dir;
+  setup_path = setup_path.AppendASCII(setup_exe);
+  if (file_util::PathExists(setup_path))
+    return setup_path;
+
+  return base::FilePath();
+}
+
+}  // namespace
+
+// Applies the patch to the input file. Returns kNone if the patch was
+// successfully applied, kDeltaOperationFailure if the patch operation
+// encountered errors, and kDeltaPatchProcessFailure if there was an error
+// when running the patch code out of process. In the error case, detailed error
+// information could be returned in the error parameter.
+ComponentUnpacker::Error ComponentPatcherWin::Patch(
+    PatchType patch_type,
+    const base::FilePath& input_file,
+    const base::FilePath& patch_file,
+    const base::FilePath& output_file,
+    int* error) {
+  *error = 0;
+
+  const base::FilePath exe_path = FindSetupProgram();
+  if (exe_path.empty())
+    return ComponentUnpacker::kDeltaPatchProcessFailure;
+
+  const std::string patch_type_str(PatchTypeToCommandLineSwitch(patch_type));
+
+  CommandLine cl(CommandLine::NO_PROGRAM);
+  cl.AppendSwitchASCII(installer::switches::kPatch, patch_type_str.c_str());
+  cl.AppendSwitchPath(installer::switches::kInputFile, input_file);
+  cl.AppendSwitchPath(installer::switches::kPatchFile, patch_file);
+  cl.AppendSwitchPath(installer::switches::kOutputFile, output_file);
+
+  // Create the child process in a job object. The job object prevents leaving
+  // child processes around when the parent process exits, either gracefully or
+  // accidentally.
+  base::win::ScopedHandle job(CreateJobObject(NULL, NULL));
+  if (!job || !base::SetJobObjectAsKillOnJobClose(job)) {
+    *error = GetLastError();
+    return ComponentUnpacker::kDeltaPatchProcessFailure;
+  }
+
+  base::LaunchOptions launch_options;
+  launch_options.wait = true;
+  launch_options.job_handle = job;
+  launch_options.start_hidden = true;
+  CommandLine setup_path(exe_path);
+  setup_path.AppendArguments(cl, false);
+
+  // |ph| is closed by WaitForExitCode.
+  base::ProcessHandle ph = base::kNullProcessHandle;
+  int exit_code = 0;
+  if (!base::LaunchProcess(setup_path, launch_options, &ph) ||
+      !base::WaitForExitCode(ph, &exit_code)) {
+    *error = GetLastError();
+    return ComponentUnpacker::kDeltaPatchProcessFailure;
+  }
+
+  *error = exit_code;
+  return *error ? ComponentUnpacker::kDeltaOperationFailure :
+                  ComponentUnpacker::kNone;
+}
+
diff --git a/chrome/browser/component_updater/component_patcher_win.h b/chrome/browser/component_updater/component_patcher_win.h
new file mode 100644
index 0000000..d87ba54
--- /dev/null
+++ b/chrome/browser/component_updater/component_patcher_win.h
@@ -0,0 +1,24 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_COMPONENT_UPDATER_COMPONENT_PATCHER_WIN_H_
+#define CHROME_BROWSER_COMPONENT_UPDATER_COMPONENT_PATCHER_WIN_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "chrome/browser/component_updater/component_patcher.h"
+
+class ComponentPatcherWin : public ComponentPatcher {
+ public:
+  ComponentPatcherWin() {}
+  virtual ComponentUnpacker::Error Patch(PatchType patch_type,
+                                         const base::FilePath& input_file,
+                                         const base::FilePath& patch_file,
+                                         const base::FilePath& output_file,
+                                         int* error) OVERRIDE;
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ComponentPatcherWin);
+};
+
+#endif  // CHROME_BROWSER_COMPONENT_UPDATER_COMPONENT_PATCHER_WIN_H_
diff --git a/chrome/browser/component_updater/component_unpacker.cc b/chrome/browser/component_updater/component_unpacker.cc
index 9454637..de7cfcb 100644
--- a/chrome/browser/component_updater/component_unpacker.cc
+++ b/chrome/browser/component_updater/component_unpacker.cc
@@ -12,6 +12,7 @@
 #include "base/memory/scoped_handle.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
+#include "chrome/browser/component_updater/component_patcher.h"
 #include "chrome/browser/component_updater/component_updater_service.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "crypto/secure_hash.h"
@@ -22,11 +23,12 @@
 using crypto::SecureHash;
 
 namespace {
+
 // This class makes sure that the CRX digital signature is valid
 // and well formed.
 class CRXValidator {
  public:
-  explicit CRXValidator(FILE* crx_file) : valid_(false) {
+  explicit CRXValidator(FILE* crx_file) : valid_(false), delta_(false) {
     extensions::CrxFile::Header header;
     size_t len = fread(&header, 1, sizeof(header), crx_file);
     if (len < sizeof(header))
@@ -37,6 +39,7 @@
         extensions::CrxFile::Parse(header, &error));
     if (!crx.get())
       return;
+    delta_ = extensions::CrxFile::HeaderIsDelta(header);
 
     std::vector<uint8> key(header.key_size);
     len = fread(&key[0], sizeof(uint8), header.key_size, crx_file);
@@ -72,10 +75,13 @@
 
   bool valid() const { return valid_; }
 
+  bool delta() const { return delta_; }
+
   const std::vector<uint8>& public_key() const { return public_key_; }
 
  private:
   bool valid_;
+  bool delta_;
   std::vector<uint8> public_key_;
 };
 
@@ -98,12 +104,29 @@
   return static_cast<base::DictionaryValue*>(root.release());
 }
 
+// Deletes a path if it exists, and then creates a directory there.
+// Returns true if and only if these operations were successful.
+// This method doesn't take any special steps to prevent files from
+// being inserted into the target directory by another process or thread.
+bool MakeEmptyDirectory(const base::FilePath& path) {
+  if (file_util::PathExists(path)) {
+    if (!base::Delete(path, true))
+      return false;
+  }
+  if (!file_util::CreateDirectory(path))
+    return false;
+  return true;
+}
+
 }  // namespace.
 
 ComponentUnpacker::ComponentUnpacker(const std::vector<uint8>& pk_hash,
                                      const base::FilePath& path,
+                                     const std::string& fingerprint,
+                                     ComponentPatcher* patcher,
                                      ComponentInstaller* installer)
-  : error_(kNone) {
+    : error_(kNone),
+      extended_error_(0) {
   if (pk_hash.empty() || path.empty()) {
     error_ = kInvalidParams;
     return;
@@ -135,31 +158,61 @@
     return;
   }
   // We want the temporary directory to be unique and yet predictable, so
-  // we can easily find the package in a end user machine.
-  std::string dir(
+  // we can easily find the package in an end user machine.
+  const std::string dir(
       base::StringPrintf("CRX_%s", base::HexEncode(hash, 6).c_str()));
   unpack_path_ = path.DirName().AppendASCII(dir.c_str());
-  if (file_util::DirectoryExists(unpack_path_)) {
-    if (!file_util::Delete(unpack_path_, true)) {
-      unpack_path_.clear();
-      error_ = kUzipPathError;
+  if (!MakeEmptyDirectory(unpack_path_)) {
+    unpack_path_.clear();
+    error_ = kUnzipPathError;
+    return;
+  }
+  if (validator.delta()) {  // Package is a diff package.
+    // We want a different temp directory for the delta files; we'll put the
+    // patch output into unpack_path_.
+    std::string dir(
+        base::StringPrintf("CRX_%s_diff", base::HexEncode(hash, 6).c_str()));
+    base::FilePath unpack_diff_path = path.DirName().AppendASCII(dir.c_str());
+    if (!MakeEmptyDirectory(unpack_diff_path)) {
+      error_ = kUnzipPathError;
       return;
     }
-  }
-  if (!file_util::CreateDirectory(unpack_path_)) {
-    unpack_path_.clear();
-    error_ = kUzipPathError;
-    return;
-  }
-  if (!zip::Unzip(path, unpack_path_)) {
-    error_ = kUnzipFailed;
-    return;
+    if (!zip::Unzip(path, unpack_diff_path)) {
+      error_ = kUnzipFailed;
+      return;
+    }
+    ComponentUnpacker::Error result = DifferentialUpdatePatch(unpack_diff_path,
+                                                              unpack_path_,
+                                                              patcher,
+                                                              installer,
+                                                              &extended_error_);
+    base::Delete(unpack_diff_path, true);
+    unpack_diff_path.clear();
+    error_ = result;
+    if (error_ != kNone) {
+      return;
+    }
+  } else {
+    // Package is a normal update/install; unzip it into unpack_path_ directly.
+    if (!zip::Unzip(path, unpack_path_)) {
+      error_ = kUnzipFailed;
+      return;
+    }
   }
   scoped_ptr<base::DictionaryValue> manifest(ReadManifest(unpack_path_));
   if (!manifest.get()) {
     error_ = kBadManifest;
     return;
   }
+  // Write the fingerprint to disk.
+  if (static_cast<int>(fingerprint.size()) !=
+      file_util::WriteFile(
+          unpack_path_.Append(FILE_PATH_LITERAL("manifest.fingerprint")),
+          fingerprint.c_str(),
+          fingerprint.size())) {
+    error_ = kFingerprintWriteFailed;
+    return;
+  }
   if (!installer->Install(*manifest, unpack_path_)) {
     error_ = kInstallerError;
     return;
@@ -169,7 +222,6 @@
 }
 
 ComponentUnpacker::~ComponentUnpacker() {
-  if (!unpack_path_.empty()) {
-    file_util::Delete(unpack_path_, true);
-  }
+  if (!unpack_path_.empty())
+    base::Delete(unpack_path_, true);
 }
diff --git a/chrome/browser/component_updater/component_unpacker.h b/chrome/browser/component_updater/component_unpacker.h
index e51555c..6ae7277 100644
--- a/chrome/browser/component_updater/component_unpacker.h
+++ b/chrome/browser/component_updater/component_unpacker.h
@@ -5,11 +5,13 @@
 #ifndef CHROME_BROWSER_COMPONENT_UPDATER_COMPONENT_UNPACKER_H_
 #define CHROME_BROWSER_COMPONENT_UPDATER_COMPONENT_UNPACKER_H_
 
+#include <string>
 #include <vector>
-
+#include "base/basictypes.h"
 #include "base/files/file_path.h"
 
 class ComponentInstaller;
+class ComponentPatcher;
 
 // In charge of unpacking the component CRX package and verifying that it is
 // well formed and the cryptographic signature is correct. If there is no
@@ -26,22 +28,33 @@
 class ComponentUnpacker {
  public:
   // Possible error conditions.
+  // Add only to the bottom of this enum; the order must be kept stable.
   enum Error {
     kNone,
     kInvalidParams,
     kInvalidFile,
-    kUzipPathError,
+    kUnzipPathError,
     kUnzipFailed,
     kNoManifest,
     kBadManifest,
     kBadExtension,
     kInvalidId,
     kInstallerError,
+    kIoError,
+    kDeltaVerificationFailure,
+    kDeltaBadCommands,
+    kDeltaUnsupportedCommand,
+    kDeltaOperationFailure,
+    kDeltaPatchProcessFailure,
+    kDeltaMissingExistingFile,
+    kFingerprintWriteFailed,
   };
   // Unpacks, verifies and calls the installer. |pk_hash| is the expected
   // public key SHA256 hash. |path| is the current location of the CRX.
   ComponentUnpacker(const std::vector<uint8>& pk_hash,
                     const base::FilePath& path,
+                    const std::string& fingerprint,
+                    ComponentPatcher* patcher,
                     ComponentInstaller* installer);
 
   // If something went wrong during unpacking or installer invocation, the
@@ -50,9 +63,12 @@
 
   Error error() const { return error_; }
 
+  int extended_error() const { return extended_error_; }
+
  private:
   base::FilePath unpack_path_;
   Error error_;
+  int extended_error_;  // Provides additional error information.
 };
 
 #endif  // CHROME_BROWSER_COMPONENT_UPDATER_COMPONENT_UNPACKER_H_
diff --git a/chrome/browser/component_updater/component_updater_configurator.cc b/chrome/browser/component_updater/component_updater_configurator.cc
index 16fa3e9..d211e5e 100644
--- a/chrome/browser/component_updater/component_updater_configurator.cc
+++ b/chrome/browser/component_updater/component_updater_configurator.cc
@@ -14,36 +14,66 @@
 #include "base/strings/string_util.h"
 #include "base/win/windows_version.h"
 #include "build/build_config.h"
+#include "chrome/browser/component_updater/component_patcher.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/omaha_query_params/omaha_query_params.h"
 #include "net/url_request/url_request_context_getter.h"
 
+#if defined(OS_WIN)
+#include "chrome/browser/component_updater/component_patcher_win.h"
+#endif
+
 namespace {
+
 // Default time constants.
 const int kDelayOneMinute = 60;
 const int kDelayOneHour = kDelayOneMinute * 60;
 
-// Debug values you can pass to --component-updater-debug=value1,value2.
+// Debug values you can pass to --component-updater=value1,value2.
 // Speed up component checking.
-const char kDebugFastUpdate[] = "fast-update";
+const char kSwitchFastUpdate[] = "fast-update";
 // Force out-of-process-xml parsing.
-const char kDebugOutOfProcess[] = "out-of-process";
+const char kSwitchOutOfProcess[] = "out-of-process";
 // Add "testrequest=1" parameter to the update check query.
-const char kDebugRequestParam[] = "test-request";
+const char kSwitchRequestParam[] = "test-request";
+// Disables differential updates.
+const char kSwitchDisableDeltaUpdates[] = "disable-delta-updates";
+// Sets the URL for updates.
+const char kSwitchUrlSource[] = "url-source";
 
-// The urls from which an update manifest can be fetched.
-const char* kUrlSources[] = {
-  "http://clients2.google.com/service/update2/crx",       // BANDAID
-  "http://omaha.google.com/service/update2/crx",          // CWS_PUBLIC
-  "http://omaha.sandbox.google.com/service/update2/crx"   // CWS_SANDBOX
-};
+// The default url from which an update manifest can be fetched. Can be
+// overridden with --component-updater=url-source=someurl.
+const char kDefaultUrlSource[] =
+    "http://clients2.google.com/service/update2/crx";
 
-bool HasDebugValue(const std::vector<std::string>& vec, const char* test) {
+// Returns true if and only if |test| is contained in |vec|.
+bool HasSwitchValue(const std::vector<std::string>& vec, const char* test) {
   if (vec.empty())
     return 0;
   return (std::find(vec.begin(), vec.end(), test) != vec.end());
 }
 
+// If there is an element of |vec| of the form |test|=.*, returns the right-
+// hand side of that assignment. Otherwise, returns an empty string.
+// The right-hand side may contain additional '=' characters, allowing for
+// further nesting of switch arguments.
+std::string GetSwitchArgument(const std::vector<std::string>& vec,
+                              const char* test) {
+  if (vec.empty())
+    return std::string();
+  for (std::vector<std::string>::const_iterator it = vec.begin();
+      it != vec.end();
+      ++it) {
+    const std::size_t found = it->find("=");
+    if (found != std::string::npos) {
+      if (it->substr(0, found) == test) {
+        return it->substr(found + 1);
+      }
+    }
+  }
+  return std::string();
+}
+
 }  // namespace
 
 class ChromeConfigurator : public ComponentUpdateService::Configurator {
@@ -58,31 +88,48 @@
   virtual int StepDelay() OVERRIDE;
   virtual int MinimumReCheckWait() OVERRIDE;
   virtual int OnDemandDelay() OVERRIDE;
-  virtual GURL UpdateUrl(CrxComponent::UrlSource source) OVERRIDE;
+  virtual GURL UpdateUrl() OVERRIDE;
   virtual const char* ExtraRequestParams() OVERRIDE;
   virtual size_t UrlSizeLimit() OVERRIDE;
   virtual net::URLRequestContextGetter* RequestContext() OVERRIDE;
   virtual bool InProcess() OVERRIDE;
   virtual void OnEvent(Events event, int val) OVERRIDE;
+  virtual ComponentPatcher* CreateComponentPatcher() OVERRIDE;
+  virtual bool DeltasEnabled() const OVERRIDE;
 
  private:
   net::URLRequestContextGetter* url_request_getter_;
   std::string extra_info_;
+  std::string url_source_;
   bool fast_update_;
   bool out_of_process_;
+  bool deltas_enabled_;
 };
 
 ChromeConfigurator::ChromeConfigurator(const CommandLine* cmdline,
     net::URLRequestContextGetter* url_request_getter)
       : url_request_getter_(url_request_getter),
         extra_info_(chrome::OmahaQueryParams::Get(
-            chrome::OmahaQueryParams::CHROME)) {
+            chrome::OmahaQueryParams::CHROME)),
+        fast_update_(false),
+        out_of_process_(false),
+        deltas_enabled_(false) {
   // Parse comma-delimited debug flags.
-  std::vector<std::string> debug_values;
-  Tokenize(cmdline->GetSwitchValueASCII(switches::kComponentUpdaterDebug),
-      ",", &debug_values);
-  fast_update_ = HasDebugValue(debug_values, kDebugFastUpdate);
-  out_of_process_ = HasDebugValue(debug_values, kDebugOutOfProcess);
+  std::vector<std::string> switch_values;
+  Tokenize(cmdline->GetSwitchValueASCII(switches::kComponentUpdater),
+      ",", &switch_values);
+  fast_update_ = HasSwitchValue(switch_values, kSwitchFastUpdate);
+  out_of_process_ = HasSwitchValue(switch_values, kSwitchOutOfProcess);
+#if defined(OS_WIN)
+  deltas_enabled_ = !HasSwitchValue(switch_values, kSwitchDisableDeltaUpdates);
+#else
+  deltas_enabled_ = false;
+#endif
+
+  url_source_ = GetSwitchArgument(switch_values, kSwitchUrlSource);
+  if (url_source_.empty()) {
+    url_source_ = kDefaultUrlSource;
+  }
 
   // Make the extra request params, they are necessary so omaha does
   // not deliver components that are going to be rejected at install time.
@@ -91,7 +138,7 @@
       base::win::OSInfo::WOW64_ENABLED)
     extra_info_ += "&wow64=1";
 #endif
-  if (HasDebugValue(debug_values, kDebugRequestParam))
+  if (HasSwitchValue(switch_values, kSwitchRequestParam))
     extra_info_ += "&testrequest=1";
 }
 
@@ -115,8 +162,8 @@
   return fast_update_ ? 2 : (30 * kDelayOneMinute);
 }
 
-GURL ChromeConfigurator::UpdateUrl(CrxComponent::UrlSource source) {
-  return GURL(kUrlSources[source]);
+GURL ChromeConfigurator::UpdateUrl() {
+  return GURL(url_source_);
 }
 
 const char* ChromeConfigurator::ExtraRequestParams() {
@@ -161,6 +208,18 @@
   }
 }
 
+ComponentPatcher* ChromeConfigurator::CreateComponentPatcher() {
+#if defined(OS_WIN)
+  return new ComponentPatcherWin();
+#else
+  return new ComponentPatcherCrossPlatform();
+#endif
+}
+
+bool ChromeConfigurator::DeltasEnabled() const {
+  return deltas_enabled_;
+}
+
 ComponentUpdateService::Configurator* MakeChromeComponentUpdaterConfigurator(
     const CommandLine* cmdline, net::URLRequestContextGetter* context_getter) {
   return new ChromeConfigurator(cmdline, context_getter);
diff --git a/chrome/browser/component_updater/component_updater_service.cc b/chrome/browser/component_updater/component_updater_service.cc
index f3eee77..7b3d683 100644
--- a/chrome/browser/component_updater/component_updater_service.cc
+++ b/chrome/browser/component_updater/component_updater_service.cc
@@ -10,6 +10,7 @@
 
 #include "base/at_exit.h"
 #include "base/bind.h"
+#include "base/compiler_specific.h"
 #include "base/file_util.h"
 #include "base/files/file_path.h"
 #include "base/logging.h"
@@ -19,24 +20,26 @@
 #include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/browser_process.h"
+#include "chrome/browser/component_updater/component_patcher.h"
 #include "chrome/browser/component_updater/component_unpacker.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "chrome/common/chrome_utility_messages.h"
 #include "chrome/common/chrome_version_info.h"
 #include "chrome/common/extensions/extension.h"
+#include "chrome/common/omaha_query_params/omaha_query_params.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/utility_process_host.h"
 #include "content/public/browser/utility_process_host_client.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/escape.h"
 #include "net/base/load_flags.h"
 #include "net/base/net_errors.h"
 #include "net/url_request/url_fetcher.h"
 #include "net/url_request/url_fetcher_delegate.h"
 #include "net/url_request/url_request_status.h"
+#include "url/gurl.h"
 
 using content::BrowserThread;
 using content::UtilityProcessHost;
@@ -47,21 +50,21 @@
 // base::Bind() calls are not refcounted.
 
 namespace {
-// Manifest sources, from most important to least important.
-const CrxComponent::UrlSource kManifestSources[] = {
-  CrxComponent::BANDAID,
-  CrxComponent::CWS_PUBLIC,
-  CrxComponent::CWS_SANDBOX
-};
 
 // Extends an omaha compatible update check url |query| string. Does
 // not mutate the string if it would be longer than |limit| chars.
 bool AddQueryString(const std::string& id,
                     const std::string& version,
+                    const std::string& fingerprint,
+                    bool ondemand,
                     size_t limit,
                     std::string* query) {
   std::string additional =
-      base::StringPrintf("id=%s&v=%s&uc", id.c_str(), version.c_str());
+      base::StringPrintf("id=%s&v=%s&fp=%s&uc%s",
+                         id.c_str(),
+                         version.c_str(),
+                         fingerprint.c_str(),
+                         ondemand ? "&installsource=ondemand" : "");
   additional = "x=" + net::EscapeQueryParamValue(additional, true);
   if ((additional.size() + query->size() + 1) > limit)
     return false;
@@ -163,7 +166,7 @@
   fetcher->Start();
 }
 
-// Returs true if the url request of |fetcher| was succesful.
+// Returns true if the url request of |fetcher| was succesful.
 bool FetchSuccess(const net::URLFetcher& fetcher) {
   return (fetcher.GetStatus().status() == net::URLRequestStatus::SUCCESS) &&
          (fetcher.GetResponseCode() == 200);
@@ -174,23 +177,44 @@
 // which is supplied by the the component updater client and |status| which
 // is modified as the item is processed by the update pipeline. The expected
 // transition graph is:
-//                                error          error         error
-//              +--kNoUpdate<------<-------+------<------+------<------+
-//              |                          |             |             |
-//              V                  yes     |             |             |
-//  kNew --->kChecking-->[update?]----->kCanUpdate-->kDownloading-->kUpdating
-//              ^               |                                      |
-//              |               |no                                    |
-//              |--kUpToDate<---+                                      |
-//              |                                  success             |
-//              +--kUpdated<-------------------------------------------+
+//
+//                                 kNew
+//                                  |
+//                                  V
+//     +----------------------> kChecking -<---------+-----<-------+
+//     |                            |                |             |
+//     |              error         V       no       |             |
+//  kNoUpdate <---------------- [update?] ->---- kUpToDate     kUpdated
+//     ^                            |                              ^
+//     |                        yes |                              |
+//     |        diff=false          V                              |
+//     |          +-----------> kCanUpdate                         |
+//     |          |                 |                              |
+//     |          |                 V              no              |
+//     |          |        [differential update?]->----+           |
+//     |          |                 |                  |           |
+//     |          |             yes |                  |           |
+//     |          |   error         V                  |           |
+//     |          +---------<- kDownloadingDiff        |           |
+//     |          |                 |                  |           |
+//     |          |                 |                  |           |
+//     |          |   error         V                  |           |
+//     |          +---------<- kUpdatingDiff ->--------|-----------+ success
+//     |                                               |           |
+//     |              error                            V           |
+//     +----------------------------------------- kDownloading     |
+//     |                                               |           |
+//     |              error                            V           |
+//     +------------------------------------------ kUpdating ->----+ success
 //
 struct CrxUpdateItem {
   enum Status {
     kNew,
     kChecking,
     kCanUpdate,
+    kDownloadingDiff,
     kDownloading,
+    kUpdatingDiff,
     kUpdating,
     kUpdated,
     kUpToDate,
@@ -199,13 +223,33 @@
   };
 
   Status status;
-  GURL crx_url;
   std::string id;
-  base::Time last_check;
   CrxComponent component;
-  Version next_version;
 
-  CrxUpdateItem() : status(kNew) {}
+  base::Time last_check;
+
+  // These members are initialized with their corresponding values from the
+  // update server response.
+  GURL crx_url;
+  GURL diff_crx_url;
+  int size;
+  int diff_size;
+
+  // The from/to version and fingerprint values.
+  Version previous_version;
+  Version next_version;
+  std::string previous_fp;
+  std::string next_fp;
+
+  // True if the differential update failed for any reason.
+  bool diff_update_failed;
+
+  CrxUpdateItem()
+      : status(kNew),
+        size(0),
+        diff_size(0),
+        diff_update_failed(false) {
+  }
 
   // Function object used to find a specific component.
   class FindById {
@@ -220,13 +264,24 @@
   };
 };
 
+// Returns true if a differential update is available for the update item.
+bool IsDiffUpdateAvailable(const CrxUpdateItem* update_item) {
+  return update_item->diff_crx_url.is_valid();
+}
+
+// Returns true if a differential update is available, it has not failed yet,
+// and the configuration allows it.
+bool CanTryDiffUpdate(const CrxUpdateItem* update_item,
+                      const ComponentUpdateService::Configurator& config) {
+  return IsDiffUpdateAvailable(update_item) &&
+         !update_item->diff_update_failed &&
+         config.DeltasEnabled();
+}
+
 }  // namespace.
 
-typedef ComponentUpdateService::Configurator Config;
-
 CrxComponent::CrxComponent()
-    : installer(NULL),
-      source(BANDAID) {
+    : installer(NULL) {
 }
 
 CrxComponent::~CrxComponent() {
@@ -240,7 +295,7 @@
 // rest of the browser, so even if we have many components registered and
 // eligible for update, we only do one thing at a time with pauses in between
 // the tasks. Also when we do network requests there is only one |url_fetcher_|
-// in flight at at a time.
+// in flight at a time.
 // There are no locks in this code, the main structure |work_items_| is mutated
 // only from the UI thread. The unpack and installation is done in the file
 // thread and the network requests are done in the IO thread and in the file
@@ -304,6 +359,7 @@
     ComponentInstaller* installer;
     std::vector<uint8> pk_hash;
     std::string id;
+    std::string fingerprint;
     CRXContext() : installer(NULL) {}
   };
 
@@ -319,8 +375,7 @@
       const UpdateManifest::Results& results);
 
   // See ManifestParserBridge.
-  void OnParseUpdateManifestFailed(
-      const std::string& error_message);
+  void OnParseUpdateManifestFailed(const std::string& error_message);
 
   bool AddItemToUpdateCheck(CrxUpdateItem* item, std::string* query);
 
@@ -333,19 +388,22 @@
   void Install(const CRXContext* context, const base::FilePath& crx_path);
 
   void DoneInstalling(const std::string& component_id,
-                      ComponentUnpacker::Error error);
+                      ComponentUnpacker::Error error,
+                      int extended_error);
 
   size_t ChangeItemStatus(CrxUpdateItem::Status from,
                           CrxUpdateItem::Status to);
 
   CrxUpdateItem* FindUpdateItemById(const std::string& id);
 
-  scoped_ptr<Config> config_;
+  scoped_ptr<ComponentUpdateService::Configurator> config_;
+
+  scoped_ptr<ComponentPatcher> component_patcher_;
 
   scoped_ptr<net::URLFetcher> url_fetcher_;
 
-  typedef std::vector<CrxUpdateItem*> UpdateItems;
   // A collection of every work item.
+  typedef std::vector<CrxUpdateItem*> UpdateItems;
   UpdateItems work_items_;
 
   // A particular set of items from work_items_, which should be checked ASAP.
@@ -353,7 +411,8 @@
 
   base::OneShotTimer<CrxUpdateService> timer_;
 
-  Version chrome_version_;
+  const Version chrome_version_;
+  const std::string prod_id_;
 
   bool running_;
 
@@ -362,10 +421,12 @@
 
 //////////////////////////////////////////////////////////////////////////////
 
-CrxUpdateService::CrxUpdateService(
-    ComponentUpdateService::Configurator* config)
+CrxUpdateService::CrxUpdateService(ComponentUpdateService::Configurator* config)
     : config_(config),
+      component_patcher_(config->CreateComponentPatcher()),
       chrome_version_(chrome::VersionInfo().Version()),
+      prod_id_(chrome::OmahaQueryParams::GetProdIdString(
+          chrome::OmahaQueryParams::CHROME)),
       running_(false) {
 }
 
@@ -450,7 +511,7 @@
 }
 
 // Changes all the components in |work_items_| that have |from| status to
-// |to| statatus and returns how many have been changed.
+// |to| status and returns how many have been changed.
 size_t CrxUpdateService::ChangeItemStatus(CrxUpdateItem::Status from,
                                           CrxUpdateItem::Status to) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -491,6 +552,7 @@
   uit = new CrxUpdateItem;
   uit->id.swap(id);
   uit->component = component;
+
   work_items_.push_back(uit);
   // If this is the first component registered we call Start to
   // schedule the first timer.
@@ -501,17 +563,29 @@
 }
 
 // Sets a component to be checked for updates.
-// The componet to add is |crxit| and the |query| string is modified with the
-// required omaha compatible query. Returns false when the query strings
-// is longer than specified by UrlSizeLimit().
+// The component to add is |item| and the |query| string is modified with the
+// required omaha compatible query. Returns false when the query string is
+// longer than specified by UrlSizeLimit().
+// If the item is currently on the requested_work_items_ list, the update check
+// is considered to be "on-demand": the server may honor on-demand checks by
+// serving updates at 100% rather than a gated fraction.
 bool CrxUpdateService::AddItemToUpdateCheck(CrxUpdateItem* item,
                                             std::string* query) {
   if (!AddQueryString(item->id,
                       item->component.version.GetString(),
-                      config_->UrlSizeLimit(), query))
+                      item->component.fingerprint,
+                      requested_work_items_.count(item) > 0,  // is_ondemand
+                      config_->UrlSizeLimit(),
+                      query))
     return false;
+
   item->status = CrxUpdateItem::kChecking;
   item->last_check = base::Time::Now();
+  item->previous_version = item->component.version;
+  item->next_version = Version();
+  item->previous_fp = item->component.fingerprint;
+  item->next_fp.clear();
+  item->diff_update_failed = false;
   return true;
 }
 
@@ -535,16 +609,17 @@
 
   // Check if the request is too soon.
   base::TimeDelta delta = base::Time::Now() - uit->last_check;
-  if (delta < base::TimeDelta::FromSeconds(config_->OnDemandDelay())) {
+  if (delta < base::TimeDelta::FromSeconds(config_->OnDemandDelay()))
     return kError;
-  }
 
   switch (uit->status) {
     // If the item is already in the process of being updated, there is
     // no point in this call, so return kInProgress.
     case CrxUpdateItem::kChecking:
     case CrxUpdateItem::kCanUpdate:
+    case CrxUpdateItem::kDownloadingDiff:
     case CrxUpdateItem::kDownloading:
+    case CrxUpdateItem::kUpdatingDiff:
     case CrxUpdateItem::kUpdating:
       return kInProgress;
     // Otherwise the item was already checked a while back (or it is new),
@@ -583,85 +658,81 @@
     if (item->status != CrxUpdateItem::kCanUpdate)
       continue;
     // Found component to update, start the process.
-    item->status = CrxUpdateItem::kDownloading;
     CRXContext* context = new CRXContext;
     context->pk_hash = item->component.pk_hash;
     context->id = item->id;
     context->installer = item->component.installer;
+    context->fingerprint = item->next_fp;
+    GURL package_url;
+    if (CanTryDiffUpdate(item, *config_)) {
+      package_url = item->diff_crx_url;
+      item->status = CrxUpdateItem::kDownloadingDiff;
+    } else {
+      package_url = item->crx_url;
+      item->status = CrxUpdateItem::kDownloading;
+    }
     url_fetcher_.reset(net::URLFetcher::Create(
-        0, item->crx_url, net::URLFetcher::GET,
+        0, package_url, net::URLFetcher::GET,
         MakeContextDelegate(this, context)));
     StartFetch(url_fetcher_.get(), config_->RequestContext(), true);
     return;
   }
 
-  for (size_t ix = 0; ix != arraysize(kManifestSources); ++ix) {
-    const CrxComponent::UrlSource manifest_source = kManifestSources[ix];
-
-    std::string query;
-    // If no pending upgrades, we check if there are new components we have not
-    // checked against the server. We can batch some in a single url request.
-    for (UpdateItems::const_iterator it = work_items_.begin();
-         it != work_items_.end(); ++it) {
-      CrxUpdateItem* item = *it;
-      if (item->status != CrxUpdateItem::kNew)
-        continue;
-      if (item->component.source != manifest_source)
-        continue;
-      if (!AddItemToUpdateCheck(item, &query))
-        break;
-      // Requested work items may speed up the update cycle up until
-      // the point that we start an update check. I.e., transition
-      // from kNew -> kChecking.  Since the service doesn't guarantee that
-      // the requested items make it any further than kChecking,
-      // forget them now.
-      requested_work_items_.erase(item);
-    }
-
-    // Next we can go back to components we already checked, here
-    // we can also batch them in a single url request, as long as
-    // we have not checked them recently.
-    const base::TimeDelta min_delta_time =
-        base::TimeDelta::FromSeconds(config_->MinimumReCheckWait());
-
-    for (UpdateItems::const_iterator it = work_items_.begin();
-         it != work_items_.end(); ++it) {
-      CrxUpdateItem* item = *it;
-      if ((item->status != CrxUpdateItem::kNoUpdate) &&
-          (item->status != CrxUpdateItem::kUpToDate))
-        continue;
-      if (item->component.source != manifest_source)
-        continue;
-      base::TimeDelta delta = base::Time::Now() - item->last_check;
-      if (delta < min_delta_time)
-        continue;
-      if (!AddItemToUpdateCheck(item, &query))
-        break;
-    }
-
-    // Finally, we check components that we already updated as long as
-    // we have not checked them recently.
-    for (UpdateItems::const_iterator it = work_items_.begin();
-         it != work_items_.end(); ++it) {
-      CrxUpdateItem* item = *it;
-      if (item->status != CrxUpdateItem::kUpdated)
-        continue;
-      if (item->component.source != manifest_source)
-        continue;
-      base::TimeDelta delta = base::Time::Now() - item->last_check;
-      if (delta < min_delta_time)
-        continue;
-      if (!AddItemToUpdateCheck(item, &query))
-        break;
-    }
-
-    // If no components to update we move down to the next source.
-    if (query.empty())
+  std::string query;
+  // If no pending upgrades, we check if there are new components we have not
+  // checked against the server. We can batch some in a single url request.
+  for (UpdateItems::const_iterator it = work_items_.begin();
+       it != work_items_.end(); ++it) {
+    CrxUpdateItem* item = *it;
+    if (item->status != CrxUpdateItem::kNew)
       continue;
+    if (!AddItemToUpdateCheck(item, &query))
+      break;
+    // Requested work items may speed up the update cycle up until
+    // the point that we start an update check. I.e., transition
+    // from kNew -> kChecking.  Since the service doesn't guarantee that
+    // the requested items make it any further than kChecking,
+    // forget them now.
+    requested_work_items_.erase(item);
+  }
 
+  // Next we can go back to components we already checked, here
+  // we can also batch them in a single url request, as long as
+  // we have not checked them recently.
+  const base::TimeDelta min_delta_time =
+      base::TimeDelta::FromSeconds(config_->MinimumReCheckWait());
+
+  for (UpdateItems::const_iterator it = work_items_.begin();
+       it != work_items_.end(); ++it) {
+    CrxUpdateItem* item = *it;
+    if ((item->status != CrxUpdateItem::kNoUpdate) &&
+        (item->status != CrxUpdateItem::kUpToDate))
+      continue;
+    base::TimeDelta delta = base::Time::Now() - item->last_check;
+    if (delta < min_delta_time)
+      continue;
+    if (!AddItemToUpdateCheck(item, &query))
+      break;
+  }
+
+  // Finally, we check components that we already updated as long as
+  // we have not checked them recently.
+  for (UpdateItems::const_iterator it = work_items_.begin();
+       it != work_items_.end(); ++it) {
+    CrxUpdateItem* item = *it;
+    if (item->status != CrxUpdateItem::kUpdated)
+      continue;
+    base::TimeDelta delta = base::Time::Now() - item->last_check;
+    if (delta < min_delta_time)
+      continue;
+    if (!AddItemToUpdateCheck(item, &query))
+      break;
+  }
+
+  if (!query.empty()) {
     // We got components to check. Start the url request and exit.
     const std::string full_query =
-        MakeFinalQuery(config_->UpdateUrl(manifest_source).spec(),
+        MakeFinalQuery(config_->UpdateUrl().spec(),
                        query,
                        config_->ExtraRequestParams());
 
@@ -700,11 +771,10 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   if (config_->InProcess()) {
     UpdateManifest manifest;
-    if (!manifest.Parse(xml)) {
+    if (!manifest.Parse(xml))
        CrxUpdateService::OnParseUpdateManifestFailed(manifest.errors());
-    } else {
+    else
        CrxUpdateService::OnParseUpdateManifestSucceeded(manifest.results());
-    }
   } else {
     UtilityProcessHost* host =
         UtilityProcessHost::Create(new ManifestParserBridge(this),
@@ -753,8 +823,12 @@
     // All test passed. Queue an upgrade for this component and fire the
     // notifications.
     crx->crx_url = it->crx_url;
+    crx->size = it->size;
+    crx->diff_crx_url = it->diff_crx_url;
+    crx->diff_size = it->diff_size;
     crx->status = CrxUpdateItem::kCanUpdate;
     crx->next_version = Version(it->version);
+    crx->next_fp = it->package_fingerprint;
     ++update_pending;
 
     content::NotificationService::current()->Notify(
@@ -789,19 +863,40 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   int error_code = net::OK;
 
+  CrxUpdateItem* crx = FindUpdateItemById(context->id);
+  DCHECK(crx->status == CrxUpdateItem::kDownloadingDiff ||
+         crx->status == CrxUpdateItem::kDownloading);
+
   if (source->FileErrorOccurred(&error_code) || !FetchSuccess(*source)) {
+    if (crx->status == CrxUpdateItem::kDownloadingDiff) {
+      crx->diff_update_failed = true;
+      size_t count = ChangeItemStatus(CrxUpdateItem::kDownloadingDiff,
+                                      CrxUpdateItem::kCanUpdate);
+      DCHECK_EQ(count, 1ul);
+      ScheduleNextRun(true);
+      return;
+    }
     size_t count = ChangeItemStatus(CrxUpdateItem::kDownloading,
                                     CrxUpdateItem::kNoUpdate);
     DCHECK_EQ(count, 1ul);
     config_->OnEvent(Configurator::kNetworkError, CrxIdtoUMAId(context->id));
     url_fetcher_.reset();
+
     ScheduleNextRun(false);
   } else {
     base::FilePath temp_crx_path;
     CHECK(source->GetResponseAsFilePath(true, &temp_crx_path));
-    size_t count = ChangeItemStatus(CrxUpdateItem::kDownloading,
-                                    CrxUpdateItem::kUpdating);
+
+    size_t count = 0;
+    if (crx->status == CrxUpdateItem::kDownloadingDiff) {
+      count = ChangeItemStatus(CrxUpdateItem::kDownloadingDiff,
+                               CrxUpdateItem::kUpdatingDiff);
+    } else {
+      count = ChangeItemStatus(CrxUpdateItem::kDownloading,
+                               CrxUpdateItem::kUpdating);
+    }
     DCHECK_EQ(count, 1ul);
+
     url_fetcher_.reset();
 
     content::NotificationService::current()->Notify(
@@ -829,17 +924,19 @@
                                const base::FilePath& crx_path) {
   // This function owns the |crx_path| and the |context| object.
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-  ComponentUnpacker
-      unpacker(context->pk_hash, crx_path, context->installer);
-  if (!file_util::Delete(crx_path, false)) {
+  ComponentUnpacker unpacker(context->pk_hash,
+                             crx_path,
+                             context->fingerprint,
+                             component_patcher_.get(),
+                             context->installer);
+  if (!base::Delete(crx_path, false))
     NOTREACHED() << crx_path.value();
-  }
   // Why unretained? See comment at top of file.
   BrowserThread::PostDelayedTask(
       BrowserThread::UI,
       FROM_HERE,
       base::Bind(&CrxUpdateService::DoneInstalling, base::Unretained(this),
-                 context->id, unpacker.error()),
+                 context->id, unpacker.error(), unpacker.extended_error()),
       base::TimeDelta::FromMilliseconds(config_->StepDelay()));
   delete context;
 }
@@ -847,14 +944,28 @@
 // Installation has been completed. Adjust the component status and
 // schedule the next check.
 void CrxUpdateService::DoneInstalling(const std::string& component_id,
-                                      ComponentUnpacker::Error error) {
+                                      ComponentUnpacker::Error error,
+                                      int extra_code) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   CrxUpdateItem* item = FindUpdateItemById(component_id);
+  if (item->status == CrxUpdateItem::kUpdatingDiff) {
+    if (error != ComponentUnpacker::kNone) {
+      item->diff_update_failed = true;
+      size_t count = ChangeItemStatus(CrxUpdateItem::kUpdatingDiff,
+                                      CrxUpdateItem::kCanUpdate);
+      DCHECK_EQ(count, 1ul);
+      ScheduleNextRun(true);
+      return;
+    }
+  }
+
   item->status = (error == ComponentUnpacker::kNone) ? CrxUpdateItem::kUpdated :
                                                        CrxUpdateItem::kNoUpdate;
-  if (item->status == CrxUpdateItem::kUpdated)
+  if (item->status == CrxUpdateItem::kUpdated) {
     item->component.version = item->next_version;
+    item->component.fingerprint = item->next_fp;
+  }
 
   Configurator::Events event;
   switch (error) {
diff --git a/chrome/browser/component_updater/component_updater_service.h b/chrome/browser/component_updater/component_updater_service.h
index 3ac645d..de1748b 100644
--- a/chrome/browser/component_updater/component_updater_service.h
+++ b/chrome/browser/component_updater/component_updater_service.h
@@ -9,7 +9,7 @@
 #include <vector>
 
 #include "base/version.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 namespace net {
 class URLRequestContextGetter;
@@ -20,6 +20,8 @@
 class FilePath;
 }
 
+class ComponentPatcher;
+
 // Component specific installers must derive from this class and implement
 // OnUpdateError() and Install(). A valid instance of this class must be
 // given to ComponentUpdateService::RegisterComponent().
@@ -37,32 +39,28 @@
   virtual bool Install(const base::DictionaryValue& manifest,
                        const base::FilePath& unpack_path) = 0;
 
+  // Set |installed_file| to the full path to the installed |file|. |file| is
+  // the filename of the file in this component's CRX. Returns false if this is
+  // not possible (the file has been removed or modified, or its current
+  // location is unknown). Otherwise, returns true.
+  virtual bool GetInstalledFile(const std::string& file,
+                                base::FilePath* installed_file) = 0;
+
  protected:
   virtual ~ComponentInstaller() {}
 };
 
 // Describes a particular component that can be installed or updated. This
 // structure is required to register a component with the component updater.
-// Only |name| is optional. |pk_hash| is the SHA256 hash of the component's
-// public key. If the component is to be installed then version should be
-// "0" or "0.0", else it should be the current version.
-// |source| is by default pointing to BANDAID but if needed it can be made
-// to point to the webstore (CWS_PUBLIC) or to the webstore sandbox. It is
-// important to note that the BANDAID source if active throught the day
-// can pre-empt updates from the other sources down the list.
+// |pk_hash| is the SHA256 hash of the component's public key. If the component
+// is to be installed then version should be "0" or "0.0", else it should be
+// the current version. |fingerprint| and |name| are optional.
 struct CrxComponent {
-  // Specifies the source url for manifest check.
-  enum UrlSource {
-    BANDAID,
-    CWS_PUBLIC,
-    CWS_SANDBOX
-  };
-
   std::vector<uint8> pk_hash;
   ComponentInstaller* installer;
   Version version;
+  std::string fingerprint;
   std::string name;
-  UrlSource source;
   CrxComponent();
   ~CrxComponent();
 };
@@ -115,7 +113,7 @@
     // for the same component.
     virtual int OnDemandDelay() = 0;
     // The url that is going to be used update checks over Omaha protocol.
-    virtual GURL UpdateUrl(CrxComponent::UrlSource source) = 0;
+    virtual GURL UpdateUrl() = 0;
     // Parameters added to each url request. It can be null if none are needed.
     virtual const char* ExtraRequestParams() = 0;
     // How big each update request can be. Don't go above 2000.
@@ -128,6 +126,11 @@
     // happens. It should be used mostly as a place to add application specific
     // logging or telemetry. |extra| is |event| dependent.
     virtual void OnEvent(Events event, int extra) = 0;
+    // Creates a new ComponentPatcher in a platform-specific way. This is useful
+    // for dependency injection.
+    virtual ComponentPatcher* CreateComponentPatcher() = 0;
+    // True means that this client can handle delta updates.
+    virtual bool DeltasEnabled() const = 0;
   };
 
   // Start doing update checks and installing new versions of registered
diff --git a/chrome/browser/component_updater/pepper_flash_component_installer.cc b/chrome/browser/component_updater/pepper_flash_component_installer.cc
index 696c6d9..c7cf4da 100644
--- a/chrome/browser/component_updater/pepper_flash_component_installer.cc
+++ b/chrome/browser/component_updater/pepper_flash_component_installer.cc
@@ -250,6 +250,9 @@
   virtual bool Install(const base::DictionaryValue& manifest,
                        const base::FilePath& unpack_path) OVERRIDE;
 
+  virtual bool GetInstalledFile(const std::string& file,
+                                base::FilePath* installed_file) OVERRIDE;
+
  private:
   Version current_version_;
 };
@@ -279,7 +282,7 @@
       GetPepperFlashBaseDirectory().AppendASCII(version.GetString());
   if (file_util::PathExists(path))
     return false;
-  if (!file_util::Move(unpack_path, path))
+  if (!base::Move(unpack_path, path))
     return false;
   // Installation is done. Now tell the rest of chrome. Both the path service
   // and to the plugin service.
@@ -292,6 +295,11 @@
   return true;
 }
 
+bool PepperFlashComponentInstaller::GetInstalledFile(
+    const std::string& file, base::FilePath* installed_file) {
+  return false;
+}
+
 bool CheckPepperFlashManifest(const base::DictionaryValue& manifest,
                               Version* version_out) {
   std::string name;
@@ -377,7 +385,7 @@
   // Remove older versions of Pepper Flash.
   for (std::vector<base::FilePath>::iterator iter = older_dirs.begin();
        iter != older_dirs.end(); ++iter) {
-    file_util::Delete(*iter, true);
+    base::Delete(*iter, true);
   }
 }
 #endif  // defined(GOOGLE_CHROME_BUILD) && !defined(OS_LINUX)
diff --git a/chrome/browser/component_updater/pnacl/pnacl_component_installer.cc b/chrome/browser/component_updater/pnacl/pnacl_component_installer.cc
index 8da767b..44b66f3 100644
--- a/chrome/browser/component_updater/pnacl/pnacl_component_installer.cc
+++ b/chrome/browser/component_updater/pnacl/pnacl_component_installer.cc
@@ -6,6 +6,7 @@
 
 #include "base/base_paths.h"
 #include "base/bind.h"
+#include "base/callback.h"
 #include "base/command_line.h"
 #include "base/compiler_specific.h"
 #include "base/file_util.h"
@@ -33,11 +34,6 @@
 
 namespace {
 
-// If PNaCl isn't installed yet, but a user is running chrome with
-// --enable-pnacl, this is the amount of time to wait before starting
-// a background install.
-const int kInitialDelaySeconds = 10;
-
 // Name of the Pnacl component specified in the manifest.
 const char kPnaclManifestName[] = "PNaCl Translator";
 
@@ -150,7 +146,10 @@
                                  Version* version_out) {
   // Make sure we have the right |manifest| file.
   std::string name;
-  manifest.GetStringASCII("name", &name);
+  if (!manifest.GetStringASCII("name", &name)) {
+    LOG(WARNING) << "'name' field is missing from manifest!";
+    return false;
+  }
   // For the webstore, we've given different names to each of the
   // architecture specific packages (and test/QA vs not test/QA)
   // so only part of it is the same.
@@ -162,7 +161,10 @@
   }
 
   std::string proposed_version;
-  manifest.GetStringASCII("version", &proposed_version);
+  if (!manifest.GetStringASCII("version", &proposed_version)) {
+    LOG(WARNING) << "'version' field is missing from manifest!";
+    return false;
+  }
   Version version(proposed_version.c_str());
   if (!version.IsValid()) {
     LOG(WARNING) << "'version' field in manifest is invalid "
@@ -172,7 +174,10 @@
 
   // Now check the |pnacl_manifest|.
   std::string arch;
-  pnacl_manifest.GetStringASCII("pnacl-arch", &arch);
+  if (!pnacl_manifest.GetStringASCII("pnacl-arch", &arch)) {
+    LOG(WARNING) << "'pnacl-arch' field is missing from pnacl-manifest!";
+    return false;
+  }
   if (arch.compare(OmahaQueryParams::getNaclArch()) != 0) {
     LOG(WARNING) << "'pnacl-arch' field in manifest is invalid ("
                  << arch << " vs " << OmahaQueryParams::getNaclArch() << ")";
@@ -185,10 +190,13 @@
 
 PnaclComponentInstaller::PnaclComponentInstaller()
     : per_user_(false),
-      cus_(NULL) {
+      updates_disabled_(false),
+      cus_(NULL),
+      callback_nums_(0) {
 #if defined(OS_CHROMEOS)
   per_user_ = true;
 #endif
+  updater_observer_.reset(new PnaclUpdaterObserver(this));
 }
 
 PnaclComponentInstaller::~PnaclComponentInstaller() {
@@ -232,56 +240,115 @@
 
 bool PnaclComponentInstaller::Install(const base::DictionaryValue& manifest,
                                       const base::FilePath& unpack_path) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
   scoped_ptr<base::DictionaryValue> pnacl_manifest(
       ReadPnaclManifest(unpack_path));
   if (pnacl_manifest == NULL) {
     LOG(WARNING) << "Failed to read pnacl manifest.";
+    NotifyInstallError();
     return false;
   }
 
   Version version;
   if (!CheckPnaclComponentManifest(manifest, *pnacl_manifest, &version)) {
     LOG(WARNING) << "CheckPnaclComponentManifest failed, not installing.";
+    NotifyInstallError();
     return false;
   }
 
   // Don't install if the current version is actually newer.
-  if (current_version().CompareTo(version) > 0)
+  if (current_version().CompareTo(version) > 0) {
+    NotifyInstallError();
     return false;
+  }
 
   // Passed the basic tests. Time to install it.
   base::FilePath path = GetPnaclBaseDirectory().AppendASCII(
       version.GetString());
   if (file_util::PathExists(path)) {
     LOG(WARNING) << "Target path already exists, not installing.";
+    NotifyInstallError();
     return false;
   }
-  if (!file_util::Move(unpack_path, path)) {
+  if (!base::Move(unpack_path, path)) {
     LOG(WARNING) << "Move failed, not installing.";
+    NotifyInstallError();
     return false;
   }
 
-  // Installation is done. Now tell the rest of chrome (just the path service
-  // for now). TODO(jvoung): we need notifications if someone surfed to a
-  // Pnacl webpage and Pnacl was just installed at this time. They should
-  // then be able to reload the page and retry (or something).
-  // See: http://code.google.com/p/chromium/issues/detail?id=107438
+  // Installation is done. Now tell the rest of chrome.
+  // - The path service.
+  // - Callbacks that requested an update.
   set_current_version(version);
-
+  NotifyInstallSuccess();
   OverrideDirPnaclComponent(path);
   return true;
 }
 
-namespace {
+// Given |file|, which can be a path like "_platform_specific/arm/pnacl_foo",
+// returns the assumed install path. The path separator in |file| is '/'
+// for all platforms. Caller is responsible for checking that the
+// |installed_file| actually exists.
+bool PnaclComponentInstaller::GetInstalledFile(
+    const std::string& file, base::FilePath* installed_file) {
+  if (current_version().Equals(Version(kNullVersion)))
+    return false;
 
-void DoCheckForUpdate(ComponentUpdateService* cus,
-                   const CrxComponent& pnacl) {
-  if (cus->CheckForUpdateSoon(pnacl) != ComponentUpdateService::kOk) {
-    LOG(WARNING) << "Pnacl check for update failed.";
+  *installed_file = GetPnaclBaseDirectory().AppendASCII(
+      current_version().GetString()).AppendASCII(file);
+  return true;
+}
+
+void PnaclComponentInstaller::AddInstallCallback(
+    const InstallCallback& cb) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  int num = ++callback_nums_;
+  install_callbacks_.push_back(std::make_pair(cb, num));
+}
+
+void PnaclComponentInstaller::CancelCallback(int num) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  for (std::list<std::pair<InstallCallback, int> >::iterator
+           i = install_callbacks_.begin(),
+           e = install_callbacks_.end(); i != e; ++i) {
+    if (i->second == num) {
+      i->first.Run(false);
+      install_callbacks_.erase(i);
+      return;
+    }
   }
 }
 
-// Finally, do the registration with the right version number.
+void PnaclComponentInstaller::NotifyAllWithResult(bool status) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  while (!install_callbacks_.empty()) {
+    install_callbacks_.front().first.Run(status);
+    install_callbacks_.pop_front();
+  }
+}
+
+void PnaclComponentInstaller::NotifyInstallError() {
+  if (!install_callbacks_.empty()) {
+    BrowserThread::PostTask(
+        BrowserThread::UI, FROM_HERE,
+        base::Bind(&PnaclComponentInstaller::NotifyAllWithResult,
+                   // Unretained because installer lives until process shutdown.
+                   base::Unretained(this), false));
+  }
+}
+
+void PnaclComponentInstaller::NotifyInstallSuccess() {
+  if (!install_callbacks_.empty()) {
+    BrowserThread::PostTask(
+        BrowserThread::UI, FROM_HERE,
+        base::Bind(&PnaclComponentInstaller::NotifyAllWithResult,
+                   // Unretained because installer lives until process shutdown.
+                   base::Unretained(this), true));
+  }
+}
+
+namespace {
+
 void FinishPnaclUpdateRegistration(const Version& current_version,
                                    PnaclComponentInstaller* pci) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -298,17 +365,6 @@
       && status != ComponentUpdateService::kReplaced) {
     NOTREACHED() << "Pnacl component registration failed.";
   }
-
-  // If PNaCl is not yet installed but it is requested by --enable-pnacl,
-  // we want it to be available "soon", so kick off an update check
-  // earlier than usual.
-  Version null_version(kNullVersion);
-  if (pci->current_version().Equals(null_version)) {
-    BrowserThread::PostDelayedTask(
-        BrowserThread::UI, FROM_HERE,
-        base::Bind(DoCheckForUpdate, pci->cus(), pnacl_component),
-        base::TimeDelta::FromSeconds(kInitialDelaySeconds));
-  }
 }
 
 // Check if there is an existing version on disk first to know when
@@ -334,8 +390,10 @@
     // Check that the component manifest and PNaCl manifest files
     // are legit, and that the indicated version matches the one
     // encoded within the path name.
-    if (!CheckPnaclComponentManifest(*manifest, *pnacl_manifest,
-                                     &manifest_version)
+    if (manifest == NULL || pnacl_manifest == NULL
+        || !CheckPnaclComponentManifest(*manifest,
+                                        *pnacl_manifest,
+                                        &manifest_version)
         || !version.Equals(manifest_version)) {
       version = Version(kNullVersion);
     } else {
@@ -343,6 +401,13 @@
     }
   }
 
+  // If updates are disabled, only discover the current version
+  // and OverrideDirPnaclComponent. That way, developers can use
+  // a pinned version. Do not actually finish registration with
+  // the component update service.
+  if (pci->updates_disabled())
+    return;
+
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
       base::Bind(&FinishPnaclUpdateRegistration, version, pci));
@@ -350,7 +415,7 @@
   // Remove older versions of PNaCl.
   for (std::vector<base::FilePath>::iterator iter = older_dirs.begin();
        iter != older_dirs.end(); ++iter) {
-    file_util::Delete(*iter, true);
+    base::Delete(*iter, true);
   }
 }
 
@@ -373,36 +438,48 @@
 void PnaclComponentInstaller::RegisterPnaclComponent(
                             ComponentUpdateService* cus,
                             const CommandLine& command_line) {
-  // Only register when given the right flag.  This is important since
-  // we do an early component updater check above (in DoCheckForUpdate).
-  if (command_line.HasSwitch(switches::kEnablePnacl)) {
-    cus_ = cus;
-    // If per_user, create a profile observer to watch for logins.
-    // Only do so after cus_ is set to something non-null.
-    if (per_user_ && !profile_observer_) {
-      profile_observer_.reset(new PnaclProfileObserver(this));
-    }
-    if (per_user_) {
-      // Figure out profile information, before proceeding to look for files.
-      BrowserThread::PostTask(
-           BrowserThread::UI, FROM_HERE,
-           base::Bind(&GetProfileInformation, this));
-    } else {
-      BrowserThread::PostTask(
-           BrowserThread::FILE, FROM_HERE,
-           base::Bind(&StartPnaclUpdateRegistration, this));
-    }
+  // Register PNaCl by default (can be disabled).
+  updates_disabled_ = command_line.HasSwitch(switches::kDisablePnaclInstall);
+  cus_ = cus;
+  // If per_user, create a profile observer to watch for logins.
+  // Only do so after cus_ is set to something non-null.
+  if (per_user_ && !profile_observer_) {
+    profile_observer_.reset(new PnaclProfileObserver(this));
+  }
+  if (per_user_) {
+    // Figure out profile information, before proceeding to look for files.
+    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+                            base::Bind(&GetProfileInformation, this));
+  } else {
+    BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+                            base::Bind(&StartPnaclUpdateRegistration, this));
   }
 }
 
 void PnaclComponentInstaller::ReRegisterPnacl() {
-  // No need to check the commandline flags again here.
-  // We could only have gotten here after RegisterPnaclComponent
-  // found --enable-pnacl, since that is where we create the profile_observer_,
-  // which in turn calls ReRegisterPnacl.
   DCHECK(per_user_);
   // Figure out profile information, before proceeding to look for files.
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
       base::Bind(&GetProfileInformation, this));
 }
+
+void RequestFirstInstall(ComponentUpdateService* cus,
+                         PnaclComponentInstaller* pci,
+                          const base::Callback<void(bool)>& installed) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  Version null_version(kNullVersion);
+  CrxComponent pnacl_component;
+  pci->set_current_version(null_version);
+  pnacl_component.version = null_version;
+  pnacl_component.name = "pnacl";
+  pnacl_component.installer = pci;
+  SetPnaclHash(&pnacl_component);
+  ComponentUpdateService::Status status = cus->CheckForUpdateSoon(
+      pnacl_component);
+  if (status != ComponentUpdateService::kOk) {
+    installed.Run(false);
+    return;
+  }
+  pci->AddInstallCallback(installed);
+}
diff --git a/chrome/browser/component_updater/pnacl/pnacl_component_installer.h b/chrome/browser/component_updater/pnacl/pnacl_component_installer.h
index 9ba2997..88fb61f 100644
--- a/chrome/browser/component_updater/pnacl/pnacl_component_installer.h
+++ b/chrome/browser/component_updater/pnacl/pnacl_component_installer.h
@@ -5,11 +5,16 @@
 #ifndef CHROME_BROWSER_COMPONENT_UPDATER_PNACL_PNACL_COMPONENT_INSTALLER_H_
 #define CHROME_BROWSER_COMPONENT_UPDATER_PNACL_PNACL_COMPONENT_INSTALLER_H_
 
+#include <list>
+
+#include "base/callback_forward.h"
+#include "base/compiler_specific.h"
 #include "base/files/file_path.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/version.h"
 #include "chrome/browser/component_updater/component_updater_service.h"
 #include "chrome/browser/component_updater/pnacl/pnacl_profile_observer.h"
+#include "chrome/browser/component_updater/pnacl/pnacl_updater_observer.h"
 
 class CommandLine;
 
@@ -31,6 +36,9 @@
   virtual bool Install(const base::DictionaryValue& manifest,
                        const base::FilePath& unpack_path) OVERRIDE;
 
+  virtual bool GetInstalledFile(const std::string& file,
+                                base::FilePath* installed_file) OVERRIDE;
+
   // Register a PNaCl component for the first time.
   void RegisterPnaclComponent(ComponentUpdateService* cus,
                               const CommandLine& command_line);
@@ -39,11 +47,15 @@
   // updater service.
   void ReRegisterPnacl();
 
+  // Return true if PNaCl installs are separated by user.
   bool per_user() const { return per_user_; }
 
   // If per_user, function to call when profile is changed.
   void OnProfileChange();
 
+  // Return true if PNaCl updates are disabled.
+  bool updates_disabled() const { return updates_disabled_; }
+
   // Determine the base directory for storing each version of PNaCl.
   base::FilePath GetPnaclBaseDirectory();
 
@@ -53,12 +65,32 @@
 
   ComponentUpdateService* cus() const { return cus_; }
 
+  typedef base::Callback<void(bool)> InstallCallback;
+  void AddInstallCallback(const InstallCallback& cb);
+
+  void NotifyInstallError();
+
+  void NotifyInstallSuccess();
+
  private:
+  // Cancel a particular callback after a timeout.
+  void CancelCallback(int callback_num);
+
+  void NotifyAllWithResult(bool status);
+
   bool per_user_;
+  bool updates_disabled_;
   scoped_ptr<PnaclProfileObserver> profile_observer_;
   base::FilePath current_profile_path_;
   base::Version current_version_;
   ComponentUpdateService* cus_;
+  // Counter to issue identifiers to each callback.
+  int callback_nums_;
+  // List of callbacks to issue when an install completes successfully.
+  std::list<std::pair<InstallCallback, int> > install_callbacks_;
+  // Component updater service observer, to determine when an on-demand
+  // install request failed.
+  scoped_ptr<PnaclUpdaterObserver> updater_observer_;
   DISALLOW_COPY_AND_ASSIGN(PnaclComponentInstaller);
 };
 
@@ -67,4 +99,11 @@
 bool CheckPnaclComponentManifest(const base::DictionaryValue& manifest,
                                  base::Version* version_out);
 
+// Ask the given component updater service to do a first-install for PNaCl.
+// The |installed| callback will be run with |true| on success,
+// or run with |false| on an error. The callback is called on the UI thread.
+void RequestFirstInstall(ComponentUpdateService* cus,
+                         PnaclComponentInstaller* pci,
+                         const base::Callback<void(bool)>& installed);
+
 #endif  // CHROME_BROWSER_COMPONENT_UPDATER_PNACL_PNACL_COMPONENT_INSTALLER_H_
diff --git a/chrome/browser/component_updater/pnacl/pnacl_profile_observer.h b/chrome/browser/component_updater/pnacl/pnacl_profile_observer.h
index 52ab984..18ef4e8 100644
--- a/chrome/browser/component_updater/pnacl/pnacl_profile_observer.h
+++ b/chrome/browser/component_updater/pnacl/pnacl_profile_observer.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_COMPONENT_UPDATER_PNACL_PNACL_PROFILE_OBSERVER_H_
 #define CHROME_BROWSER_COMPONENT_UPDATER_PNACL_PNACL_PROFILE_OBSERVER_H_
 
+#include "base/compiler_specific.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 
diff --git a/chrome/browser/component_updater/pnacl/pnacl_updater_observer.cc b/chrome/browser/component_updater/pnacl/pnacl_updater_observer.cc
new file mode 100644
index 0000000..2a3a6fa
--- /dev/null
+++ b/chrome/browser/component_updater/pnacl/pnacl_updater_observer.cc
@@ -0,0 +1,31 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/component_updater/pnacl/pnacl_updater_observer.h"
+
+#include "base/logging.h"
+#include "chrome/browser/component_updater/pnacl/pnacl_component_installer.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "content/public/browser/notification_service.h"
+
+PnaclUpdaterObserver::PnaclUpdaterObserver(
+    PnaclComponentInstaller* installer) : pnacl_installer_(installer) {
+  registrar_.Add(this,
+                 chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING,
+                 content::NotificationService::AllSources());
+}
+
+PnaclUpdaterObserver::~PnaclUpdaterObserver() { }
+
+void PnaclUpdaterObserver::Observe(
+    int type,
+    const content::NotificationSource& source,
+    const content::NotificationDetails& details) {
+  if (type == chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING) {
+    // If the component updater sleeps before a NotifyInstallSuccess,
+    // then requests for installs were likely skipped, or an error occurred.
+    pnacl_installer_->NotifyInstallError();
+    return;
+  }
+}
diff --git a/chrome/browser/component_updater/pnacl/pnacl_updater_observer.h b/chrome/browser/component_updater/pnacl/pnacl_updater_observer.h
new file mode 100644
index 0000000..48a6f0d
--- /dev/null
+++ b/chrome/browser/component_updater/pnacl/pnacl_updater_observer.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_COMPONENT_UPDATER_PNACL_PNACL_UPDATER_OBSERVER_H_
+#define CHROME_BROWSER_COMPONENT_UPDATER_PNACL_PNACL_UPDATER_OBSERVER_H_
+
+#include "base/compiler_specific.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+
+class PnaclComponentInstaller;
+
+// Monitors the component updater service, so that the callbacks registered
+// against the PnaclComponentInstaller can be notified of events.
+class PnaclUpdaterObserver : public content::NotificationObserver {
+ public:
+  explicit PnaclUpdaterObserver(PnaclComponentInstaller* installer);
+  virtual ~PnaclUpdaterObserver();
+
+  virtual void Observe(
+      int type,
+      const content::NotificationSource& source,
+      const content::NotificationDetails& details) OVERRIDE;
+
+ private:
+  content::NotificationRegistrar registrar_;
+  PnaclComponentInstaller* pnacl_installer_;
+  DISALLOW_COPY_AND_ASSIGN(PnaclUpdaterObserver);
+};
+
+#endif  // CHROME_BROWSER_COMPONENT_UPDATER_PNACL_PNACL_UPDATER_OBSERVER_H_
diff --git a/chrome/browser/component_updater/recovery_component_installer.cc b/chrome/browser/component_updater/recovery_component_installer.cc
index c2a7d5a..4891aab 100644
--- a/chrome/browser/component_updater/recovery_component_installer.cc
+++ b/chrome/browser/component_updater/recovery_component_installer.cc
@@ -56,6 +56,9 @@
   virtual bool Install(const base::DictionaryValue& manifest,
                        const base::FilePath& unpack_path) OVERRIDE;
 
+  virtual bool GetInstalledFile(const std::string& file,
+                                base::FilePath* installed_file) OVERRIDE;
+
  private:
   Version current_version_;
   PrefService* prefs_;
@@ -130,6 +133,11 @@
   return base::LaunchProcess(cmdline, base::LaunchOptions(), NULL);
 }
 
+bool RecoveryComponentInstaller::GetInstalledFile(
+    const std::string& file, base::FilePath* installed_file) {
+  return false;
+}
+
 void RegisterRecoveryComponent(ComponentUpdateService* cus,
                                PrefService* prefs) {
 #if !defined(OS_CHROMEOS)
diff --git a/chrome/browser/component_updater/swiftshader_component_installer.cc b/chrome/browser/component_updater/swiftshader_component_installer.cc
index e09e524..9aa42e0 100644
--- a/chrome/browser/component_updater/swiftshader_component_installer.cc
+++ b/chrome/browser/component_updater/swiftshader_component_installer.cc
@@ -105,6 +105,9 @@
   virtual bool Install(const base::DictionaryValue& manifest,
                        const base::FilePath& unpack_path) OVERRIDE;
 
+  virtual bool GetInstalledFile(const std::string& file,
+                                base::FilePath* installed_file) OVERRIDE;
+
  private:
   Version current_version_;
 };
@@ -140,7 +143,7 @@
       GetSwiftShaderBaseDirectory().AppendASCII(version.GetString());
   if (file_util::PathExists(path))
     return false;
-  if (!file_util::Move(unpack_path, path))
+  if (!base::Move(unpack_path, path))
     return false;
   // Installation is done. Now tell the rest of chrome.
   current_version_ = version;
@@ -149,6 +152,11 @@
   return true;
 }
 
+bool SwiftShaderComponentInstaller::GetInstalledFile(
+    const std::string& file, base::FilePath* installed_file) {
+  return false;
+}
+
 void FinishSwiftShaderUpdateRegistration(ComponentUpdateService* cus,
                                          const Version& version) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -222,7 +230,7 @@
   // Remove older versions of SwiftShader.
   for (std::vector<base::FilePath>::iterator iter = older_dirs.begin();
        iter != older_dirs.end(); ++iter) {
-    file_util::Delete(*iter, true);
+    base::Delete(*iter, true);
   }
 }
 
diff --git a/chrome/browser/component_updater/test/DEPS b/chrome/browser/component_updater/test/DEPS
index e63018d..397b12e 100644
--- a/chrome/browser/component_updater/test/DEPS
+++ b/chrome/browser/component_updater/test/DEPS
@@ -1,4 +1,5 @@
 include_rules = [
   # For access to the ppapi test globals.
   "+ppapi/shared_impl",
+  "+courgette",
 ]
diff --git a/chrome/browser/component_updater/test/component_patcher_mock.h b/chrome/browser/component_updater/test/component_patcher_mock.h
new file mode 100644
index 0000000..1843b29
--- /dev/null
+++ b/chrome/browser/component_updater/test/component_patcher_mock.h
@@ -0,0 +1,28 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_COMPONENT_UPDATER_TEST_COMPONENT_PATCHER_MOCK_H_
+#define CHROME_BROWSER_COMPONENT_UPDATER_TEST_COMPONENT_PATCHER_MOCK_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "chrome/browser/component_updater/component_patcher.h"
+
+namespace base {
+class FilePath;
+}
+
+class MockComponentPatcher : public ComponentPatcher {
+ public:
+  MockComponentPatcher() {}
+  virtual ComponentUnpacker::Error Patch(PatchType patch_type,
+                                         const base::FilePath& input_file,
+                                         const base::FilePath& patch_file,
+                                         const base::FilePath& output_file,
+                                         int* error) OVERRIDE;
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockComponentPatcher);
+};
+
+#endif  // CHROME_BROWSER_COMPONENT_UPDATER_TEST_COMPONENT_PATCHER_MOCK_H_
diff --git a/chrome/browser/component_updater/test/component_patcher_unittest.cc b/chrome/browser/component_updater/test/component_patcher_unittest.cc
new file mode 100644
index 0000000..7593a4b
--- /dev/null
+++ b/chrome/browser/component_updater/test/component_patcher_unittest.cc
@@ -0,0 +1,118 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/compiler_specific.h"
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/path_service.h"
+#include "base/values.h"
+#include "chrome/browser/component_updater/component_patcher.h"
+#include "chrome/browser/component_updater/component_patcher_operation.h"
+#include "chrome/browser/component_updater/component_updater_service.h"
+#include "chrome/browser/component_updater/test/component_patcher_mock.h"
+#include "chrome/browser/component_updater/test/component_patcher_unittest.h"
+#include "chrome/browser/component_updater/test/test_installer.h"
+#include "chrome/common/chrome_paths.h"
+#include "courgette/courgette.h"
+#include "courgette/third_party/bsdiff.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+base::FilePath test_file(const char* file) {
+  base::FilePath path;
+  PathService::Get(chrome::DIR_TEST_DATA, &path);
+  return path.AppendASCII("components").AppendASCII(file);
+}
+
+ComponentPatcherOperationTest::ComponentPatcherOperationTest() {
+  EXPECT_TRUE(unpack_dir_.CreateUniqueTempDir());
+  EXPECT_TRUE(input_dir_.CreateUniqueTempDir());
+  EXPECT_TRUE(installed_dir_.CreateUniqueTempDir());
+  patcher_.reset(new MockComponentPatcher());
+  installer_.reset(new ReadOnlyTestInstaller(installed_dir_.path()));
+}
+
+ComponentPatcherOperationTest::~ComponentPatcherOperationTest() {
+}
+
+ComponentUnpacker::Error MockComponentPatcher::Patch(
+    PatchType patch_type,
+    const base::FilePath& input_file,
+    const base::FilePath& patch_file,
+    const base::FilePath& output_file,
+    int* error) {
+  *error = 0;
+  int exit_code;
+  if (patch_type == kPatchTypeCourgette) {
+    exit_code = courgette::ApplyEnsemblePatch(input_file.value().c_str(),
+                                              patch_file.value().c_str(),
+                                              output_file.value().c_str());
+    if (exit_code == courgette::C_OK)
+      return ComponentUnpacker::kNone;
+    *error = exit_code + kCourgetteErrorOffset;
+  } else if (patch_type == kPatchTypeBsdiff) {
+    exit_code = courgette::ApplyBinaryPatch(input_file,
+                                            patch_file,
+                                            output_file);
+    if (exit_code == courgette::OK)
+      return ComponentUnpacker::kNone;
+    *error = exit_code + kBsdiffErrorOffset;
+  }
+  return ComponentUnpacker::kDeltaOperationFailure;
+}
+
+// Verify that a 'create' delta update operation works correctly.
+TEST_F(ComponentPatcherOperationTest, CheckCreateOperation) {
+  EXPECT_TRUE(file_util::CopyFile(
+      test_file("binary_output.bin"),
+      input_dir_.path().Append(FILE_PATH_LITERAL("binary_output.bin"))));
+
+  scoped_ptr<base::DictionaryValue> command_args(new base::DictionaryValue());
+  command_args->SetString("output", "output.bin");
+  command_args->SetString("sha256", binary_output_hash);
+  command_args->SetString("op", "create");
+  command_args->SetString("patch", "binary_output.bin");
+
+  int error = 0;
+  scoped_ptr<DeltaUpdateOp> op(new DeltaUpdateOpCreate());
+  ComponentUnpacker::Error result = op->Run(command_args.get(),
+                                     input_dir_.path(),
+                                     unpack_dir_.path(),
+                                     patcher_.get(),
+                                     NULL,
+                                     &error);
+
+  EXPECT_EQ(ComponentUnpacker::kNone, result);
+  EXPECT_EQ(0, error);
+  EXPECT_TRUE(file_util::ContentsEqual(
+      unpack_dir_.path().Append(FILE_PATH_LITERAL("output.bin")),
+      test_file("binary_output.bin")));
+}
+
+// Verify that a 'copy' delta update operation works correctly.
+TEST_F(ComponentPatcherOperationTest, CheckCopyOperation) {
+  EXPECT_TRUE(file_util::CopyFile(
+      test_file("binary_output.bin"),
+      installed_dir_.path().Append(FILE_PATH_LITERAL("binary_output.bin"))));
+
+  scoped_ptr<base::DictionaryValue> command_args(new base::DictionaryValue());
+  command_args->SetString("output", "output.bin");
+  command_args->SetString("sha256", binary_output_hash);
+  command_args->SetString("op", "copy");
+  command_args->SetString("input", "binary_output.bin");
+
+  int error = 0;
+  scoped_ptr<DeltaUpdateOp> op(new DeltaUpdateOpCopy());
+  ComponentUnpacker::Error result = op->Run(command_args.get(),
+                                     input_dir_.path(),
+                                     unpack_dir_.path(),
+                                     patcher_.get(),
+                                     installer_.get(),
+                                     &error);
+  EXPECT_EQ(ComponentUnpacker::kNone, result);
+  EXPECT_EQ(0, error);
+  EXPECT_TRUE(file_util::ContentsEqual(
+      unpack_dir_.path().Append(FILE_PATH_LITERAL("output.bin")),
+      test_file("binary_output.bin")));
+}
diff --git a/chrome/browser/component_updater/test/component_patcher_unittest.h b/chrome/browser/component_updater/test/component_patcher_unittest.h
new file mode 100644
index 0000000..ee30308
--- /dev/null
+++ b/chrome/browser/component_updater/test/component_patcher_unittest.h
@@ -0,0 +1,42 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_COMPONENT_UPDATER_TEST_COMPONENT_PATCHER_UNITTEST_H_
+#define CHROME_BROWSER_COMPONENT_UPDATER_TEST_COMPONENT_PATCHER_UNITTEST_H_
+
+#include "base/files/file_path.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/memory/scoped_ptr.h"
+#include "chrome/common/chrome_paths.h"
+#include "courgette/courgette.h"
+#include "courgette/third_party/bsdiff.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class MockComponentPatcher;
+class ReadOnlyTestInstaller;
+
+const char binary_output_hash[] =
+    "599aba6d15a7da390621ef1bacb66601ed6aed04dadc1f9b445dcfe31296142a";
+
+// These constants are duplicated from chrome/installer/util/util_constants.h,
+// to avoid introducing a dependency from the unit tests to the installer.
+const int kCourgetteErrorOffset = 300;
+const int kBsdiffErrorOffset = 600;
+
+base::FilePath test_file(const char* file);
+
+class ComponentPatcherOperationTest : public testing::Test {
+ public:
+  explicit ComponentPatcherOperationTest();
+  virtual ~ComponentPatcherOperationTest();
+
+ protected:
+  base::ScopedTempDir input_dir_;
+  base::ScopedTempDir installed_dir_;
+  base::ScopedTempDir unpack_dir_;
+  scoped_ptr<MockComponentPatcher> patcher_;
+  scoped_ptr<ReadOnlyTestInstaller> installer_;
+};
+
+#endif  // CHROME_BROWSER_COMPONENT_UPDATER_TEST_COMPONENT_PATCHER_UNITTEST_H_
diff --git a/chrome/browser/component_updater/test/component_patcher_unittest_win.cc b/chrome/browser/component_updater/test/component_patcher_unittest_win.cc
new file mode 100644
index 0000000..896cf59
--- /dev/null
+++ b/chrome/browser/component_updater/test/component_patcher_unittest_win.cc
@@ -0,0 +1,83 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/compiler_specific.h"
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/path_service.h"
+#include "base/values.h"
+#include "chrome/browser/component_updater/component_patcher.h"
+#include "chrome/browser/component_updater/component_patcher_operation.h"
+#include "chrome/browser/component_updater/component_updater_service.h"
+#include "chrome/browser/component_updater/test/component_patcher_mock.h"
+#include "chrome/browser/component_updater/test/component_patcher_unittest.h"
+#include "chrome/browser/component_updater/test/test_installer.h"
+#include "chrome/common/chrome_paths.h"
+#include "courgette/courgette.h"
+#include "courgette/third_party/bsdiff.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+// Verify that a 'courgette' delta update operation works correctly.
+TEST_F(ComponentPatcherOperationTest, CheckCourgetteOperation) {
+  EXPECT_TRUE(file_util::CopyFile(
+      test_file("binary_input.bin"),
+      installed_dir_.path().Append(FILE_PATH_LITERAL("binary_input.bin"))));
+  EXPECT_TRUE(file_util::CopyFile(
+      test_file("binary_courgette_patch.bin"),
+      input_dir_.path().Append(
+          FILE_PATH_LITERAL("binary_courgette_patch.bin"))));
+
+  scoped_ptr<base::DictionaryValue> command_args(new base::DictionaryValue());
+  command_args->SetString("output", "output.bin");
+  command_args->SetString("sha256", binary_output_hash);
+  command_args->SetString("op", "courgette");
+  command_args->SetString("input", "binary_input.bin");
+  command_args->SetString("patch", "binary_courgette_patch.bin");
+
+  int error = 0;
+  scoped_ptr<DeltaUpdateOp> op(new DeltaUpdateOpPatchCourgette());
+  ComponentUnpacker::Error result = op->Run(command_args.get(),
+                                     input_dir_.path(),
+                                     unpack_dir_.path(),
+                                     patcher_.get(),
+                                     installer_.get(),
+                                     &error);
+  EXPECT_EQ(ComponentUnpacker::kNone, result);
+  EXPECT_EQ(0, error);
+  EXPECT_TRUE(file_util::ContentsEqual(
+      unpack_dir_.path().Append(FILE_PATH_LITERAL("output.bin")),
+      test_file("binary_output.bin")));
+}
+
+// Verify that a 'bsdiff' delta update operation works correctly.
+TEST_F(ComponentPatcherOperationTest, CheckBsdiffOperation) {
+  EXPECT_TRUE(file_util::CopyFile(
+      test_file("binary_input.bin"),
+      installed_dir_.path().Append(FILE_PATH_LITERAL("binary_input.bin"))));
+  EXPECT_TRUE(file_util::CopyFile(
+      test_file("binary_bsdiff_patch.bin"),
+      input_dir_.path().Append(FILE_PATH_LITERAL("binary_bsdiff_patch.bin"))));
+
+  scoped_ptr<base::DictionaryValue> command_args(new base::DictionaryValue());
+  command_args->SetString("output", "output.bin");
+  command_args->SetString("sha256", binary_output_hash);
+  command_args->SetString("op", "courgette");
+  command_args->SetString("input", "binary_input.bin");
+  command_args->SetString("patch", "binary_bsdiff_patch.bin");
+
+  int error = 0;
+  scoped_ptr<DeltaUpdateOp> op(new DeltaUpdateOpPatchBsdiff());
+  ComponentUnpacker::Error result = op->Run(command_args.get(),
+                                     input_dir_.path(),
+                                     unpack_dir_.path(),
+                                     patcher_.get(),
+                                     installer_.get(),
+                                     &error);
+  EXPECT_EQ(ComponentUnpacker::kNone, result);
+  EXPECT_EQ(0, error);
+  EXPECT_TRUE(file_util::ContentsEqual(
+      unpack_dir_.path().Append(FILE_PATH_LITERAL("output.bin")),
+      test_file("binary_output.bin")));
+}
diff --git a/chrome/browser/component_updater/test/component_updater_service_unittest.cc b/chrome/browser/component_updater/test/component_updater_service_unittest.cc
index 080b1d2..9277e88 100644
--- a/chrome/browser/component_updater/test/component_updater_service_unittest.cc
+++ b/chrome/browser/component_updater/test/component_updater_service_unittest.cc
@@ -2,18 +2,21 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/component_updater/component_updater_service.h"
-
 #include <list>
 #include <utility>
-
 #include "base/compiler_specific.h"
 #include "base/file_util.h"
 #include "base/files/file_path.h"
 #include "base/memory/scoped_vector.h"
 #include "base/message_loop.h"
 #include "base/path_service.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/stringprintf.h"
 #include "base/values.h"
+#include "chrome/browser/component_updater/component_updater_service.h"
+#include "chrome/browser/component_updater/test/component_patcher_mock.h"
+#include "chrome/browser/component_updater/test/component_updater_service_unittest.h"
+#include "chrome/browser/component_updater/test/test_installer.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "chrome/common/chrome_paths.h"
 #include "content/public/browser/notification_observer.h"
@@ -21,244 +24,178 @@
 #include "content/public/test/test_browser_thread.h"
 #include "content/public/test/test_notification_tracker.h"
 #include "content/test/net/url_request_prepackaged_interceptor.h"
-#include "googleurl/src/gurl.h"
 #include "libxml/globals.h"
+#include "net/base/upload_bytes_element_reader.h"
 #include "net/url_request/url_fetcher.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_filter.h"
+#include "net/url_request/url_request_simple_job.h"
 #include "net/url_request/url_request_test_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 using content::BrowserThread;
 using content::TestNotificationTracker;
 
-namespace {
-// Overrides some of the component updater behaviors so it is easier to test
-// and loops faster. In actual usage it takes hours do to a full cycle.
-class TestConfigurator : public ComponentUpdateService::Configurator {
- public:
-  TestConfigurator()
-      : times_(1), recheck_time_(0), ondemand_time_(0), cus_(NULL) {
-  }
+TestConfigurator::TestConfigurator()
+    : times_(1), recheck_time_(0), ondemand_time_(0), cus_(NULL) {
+}
 
-  virtual int InitialDelay() OVERRIDE { return 0; }
+TestConfigurator::~TestConfigurator() {
+}
 
-  typedef std::pair<CrxComponent*, int> CheckAtLoopCount;
+int TestConfigurator::InitialDelay() { return 0; }
 
-  virtual int NextCheckDelay() OVERRIDE {
-    // This is called when a new full cycle of checking for updates is going
-    // to happen. In test we normally only test one cycle so it is a good
-    // time to break from the test messageloop Run() method so the test can
-    // finish.
-    if (--times_ <= 0) {
-      base::MessageLoop::current()->Quit();
-      return 0;
-
-    }
-
-    // Look for checks to issue in the middle of the loop.
-    for (std::list<CheckAtLoopCount>::iterator
-             i = components_to_check_.begin();
-         i != components_to_check_.end(); ) {
-      if (i->second == times_) {
-        cus_->CheckForUpdateSoon(*i->first);
-        i = components_to_check_.erase(i);
-      } else {
-        ++i;
-      }
-    }
-    return 1;
-  }
-
-  virtual int StepDelay() OVERRIDE {
+int TestConfigurator::NextCheckDelay() {
+  // This is called when a new full cycle of checking for updates is going
+  // to happen. In test we normally only test one cycle so it is a good
+  // time to break from the test messageloop Run() method so the test can
+  // finish.
+  if (--times_ <= 0) {
+    base::MessageLoop::current()->Quit();
     return 0;
   }
 
-  virtual int MinimumReCheckWait() OVERRIDE {
-    return recheck_time_;
+  // Look for checks to issue in the middle of the loop.
+  for (std::list<CheckAtLoopCount>::iterator
+           i = components_to_check_.begin();
+       i != components_to_check_.end(); ) {
+    if (i->second == times_) {
+      cus_->CheckForUpdateSoon(*i->first);
+      i = components_to_check_.erase(i);
+    } else {
+      ++i;
+    }
   }
+  return 1;
+}
 
-  virtual int OnDemandDelay() OVERRIDE {
-    return ondemand_time_;
-  }
+int TestConfigurator::StepDelay() {
+  return 0;
+}
 
-  virtual GURL UpdateUrl(CrxComponent::UrlSource source) OVERRIDE {
-    switch (source) {
-      case CrxComponent::BANDAID:
-        return GURL("http://localhost/upd");
-      case CrxComponent::CWS_PUBLIC:
-        return GURL("http://localhost/cws");
-      default:
-        return GURL("http://wronghost/bad");
-    };
-  }
+int TestConfigurator::MinimumReCheckWait() {
+  return recheck_time_;
+}
 
-  virtual const char* ExtraRequestParams() OVERRIDE { return "extra=foo"; }
+int TestConfigurator::OnDemandDelay() {
+  return ondemand_time_;
+}
 
-  virtual size_t UrlSizeLimit() OVERRIDE { return 256; }
+GURL TestConfigurator::UpdateUrl() {
+  return GURL("http://localhost/upd");
+}
 
-  virtual net::URLRequestContextGetter* RequestContext() OVERRIDE {
-    return new net::TestURLRequestContextGetter(
-        BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
-  }
+const char* TestConfigurator::ExtraRequestParams() { return "extra=foo"; }
 
-  // Don't use the utility process to decode files.
-  virtual bool InProcess() OVERRIDE { return true; }
+size_t TestConfigurator::UrlSizeLimit() { return 256; }
 
-  virtual void OnEvent(Events event, int extra) OVERRIDE { }
+net::URLRequestContextGetter* TestConfigurator::RequestContext() {
+  return new net::TestURLRequestContextGetter(
+      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
+}
 
-  // Set how many update checks are called, the default value is just once.
-  void SetLoopCount(int times) { times_ = times; }
+// Don't use the utility process to decode files.
+bool TestConfigurator::InProcess() { return true; }
 
-  void SetRecheckTime(int seconds) {
-    recheck_time_ = seconds;
-  }
+void TestConfigurator::OnEvent(Events event, int extra) { }
 
-  void SetOnDemandTime(int seconds) {
-    ondemand_time_ = seconds;
-  }
+ComponentPatcher* TestConfigurator::CreateComponentPatcher() {
+  return new MockComponentPatcher();
+}
 
-  void AddComponentToCheck(CrxComponent* com, int at_loop_iter) {
-    components_to_check_.push_back(std::make_pair(com, at_loop_iter));
-  }
+bool TestConfigurator::DeltasEnabled() const {
+  return true;
+}
 
-  void SetComponentUpdateService(ComponentUpdateService* cus) {
-    cus_ = cus;
-  }
+// Set how many update checks are called, the default value is just once.
+void TestConfigurator::SetLoopCount(int times) { times_ = times; }
 
- private:
-  int times_;
-  int recheck_time_;
-  int ondemand_time_;
+void TestConfigurator::SetRecheckTime(int seconds) {
+  recheck_time_ = seconds;
+}
 
-  std::list<CheckAtLoopCount> components_to_check_;
-  ComponentUpdateService* cus_;
-};
+void TestConfigurator::SetOnDemandTime(int seconds) {
+  ondemand_time_ = seconds;
+}
 
-class TestInstaller : public ComponentInstaller {
- public :
-  explicit TestInstaller()
-      : error_(0), install_count_(0) {
-  }
+void TestConfigurator::AddComponentToCheck(CrxComponent* com,
+                                           int at_loop_iter) {
+  components_to_check_.push_back(std::make_pair(com, at_loop_iter));
+}
 
-  virtual void OnUpdateError(int error) OVERRIDE {
-    EXPECT_NE(0, error);
-    error_ = error;
-  }
+void TestConfigurator::SetComponentUpdateService(ComponentUpdateService* cus) {
+  cus_ = cus;
+}
 
-  virtual bool Install(const base::DictionaryValue& manifest,
-                       const base::FilePath& unpack_path) OVERRIDE {
-    ++install_count_;
-    return file_util::Delete(unpack_path, true);
-  }
+ComponentUpdaterTest::ComponentUpdaterTest() : test_config_(NULL) {
+  // The component updater instance under test.
+  test_config_ = new TestConfigurator;
+  component_updater_.reset(ComponentUpdateServiceFactory(test_config_));
+  test_config_->SetComponentUpdateService(component_updater_.get());
+  // The test directory is chrome/test/data/components.
+  PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_);
+  test_data_dir_ = test_data_dir_.AppendASCII("components");
 
-  int error() const { return error_; }
-
-  int install_count() const { return install_count_; }
-
- private:
-  int error_;
-  int install_count_;
-};
-
-// component 1 has extension id "jebgalgnebhfojomionfpkfelancnnkf", and
-// the RSA public key the following hash:
-const uint8 jebg_hash[] = {0x94,0x16,0x0b,0x6d,0x41,0x75,0xe9,0xec,0x8e,0xd5,
-                           0xfa,0x54,0xb0,0xd2,0xdd,0xa5,0x6e,0x05,0x6b,0xe8,
-                           0x73,0x47,0xf6,0xc4,0x11,0x9f,0xbc,0xb3,0x09,0xb3,
-                           0x5b,0x40};
-// component 2 has extension id "abagagagagagagagagagagagagagagag", and
-// the RSA public key the following hash:
-const uint8 abag_hash[] = {0x01,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,
-                           0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,
-                           0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,
-                           0x06,0x01};
-
-const char expected_crx_url[] =
-    "http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx";
-
-}  // namespace
-
-// Common fixture for all the component updater tests.
-class ComponentUpdaterTest : public testing::Test {
- public:
-  enum TestComponents {
-    kTestComponent_abag,
-    kTestComponent_jebg
+  // Subscribe to all component updater notifications.
+  const int notifications[] = {
+    chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED,
+    chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING,
+    chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND,
+    chrome::NOTIFICATION_COMPONENT_UPDATE_READY
   };
 
-  ComponentUpdaterTest() : test_config_(NULL) {
-    // The component updater instance under test.
-    test_config_ = new TestConfigurator;
-    component_updater_.reset(ComponentUpdateServiceFactory(test_config_));
-    test_config_->SetComponentUpdateService(component_updater_.get());
-    // The test directory is chrome/test/data/components.
-    PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_);
-    test_data_dir_ = test_data_dir_.AppendASCII("components");
-
-    // Subscribe to all component updater notifications.
-    const int notifications[] = {
-      chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED,
-      chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING,
-      chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND,
-      chrome::NOTIFICATION_COMPONENT_UPDATE_READY
-    };
-
-    for (int ix = 0; ix != arraysize(notifications); ++ix) {
-      notification_tracker_.ListenFor(
-          notifications[ix], content::NotificationService::AllSources());
-    }
-    net::URLFetcher::SetEnableInterceptionForTests(true);
+  for (int ix = 0; ix != arraysize(notifications); ++ix) {
+    notification_tracker_.ListenFor(
+        notifications[ix], content::NotificationService::AllSources());
   }
+  net::URLFetcher::SetEnableInterceptionForTests(true);
+}
 
-  virtual ~ComponentUpdaterTest() {
-    net::URLFetcher::SetEnableInterceptionForTests(false);
-  }
+ComponentUpdaterTest::~ComponentUpdaterTest() {
+  net::URLFetcher::SetEnableInterceptionForTests(false);
+}
 
-  virtual void TearDown() {
-    xmlCleanupGlobals();
-  }
+void ComponentUpdaterTest::TearDown() {
+  xmlCleanupGlobals();
+}
 
-  ComponentUpdateService* component_updater() {
-    return component_updater_.get();
-  }
+ComponentUpdateService* ComponentUpdaterTest::component_updater() {
+  return component_updater_.get();
+}
 
   // Makes the full path to a component updater test file.
-  const base::FilePath test_file(const char* file) {
-    return test_data_dir_.AppendASCII(file);
-  }
+const base::FilePath ComponentUpdaterTest::test_file(const char* file) {
+  return test_data_dir_.AppendASCII(file);
+}
 
-  TestNotificationTracker& notification_tracker() {
-    return notification_tracker_;
-  }
+TestNotificationTracker& ComponentUpdaterTest::notification_tracker() {
+  return notification_tracker_;
+}
 
-  TestConfigurator* test_configurator() {
-    return test_config_;
-  }
+TestConfigurator* ComponentUpdaterTest::test_configurator() {
+  return test_config_;
+}
 
-  ComponentUpdateService::Status RegisterComponent(CrxComponent* com,
-                                                   TestComponents component,
-                                                   const Version& version) {
-    if (component == kTestComponent_abag) {
-      com->name = "test_abag";
-      com->pk_hash.assign(abag_hash, abag_hash + arraysize(abag_hash));
-    } else {
-      com->name = "test_jebg";
-      com->pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash));
-    }
-    com->version = version;
-    TestInstaller* installer = new TestInstaller;
-    com->installer = installer;
-    test_installers_.push_back(installer);
-    return component_updater_->RegisterComponent(*com);
+ComponentUpdateService::Status ComponentUpdaterTest::RegisterComponent(
+    CrxComponent* com,
+    TestComponents component,
+    const Version& version,
+    TestInstaller* installer) {
+  if (component == kTestComponent_abag) {
+    com->name = "test_abag";
+    com->pk_hash.assign(abag_hash, abag_hash + arraysize(abag_hash));
+  } else if (component == kTestComponent_jebg) {
+    com->name = "test_jebg";
+    com->pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash));
+  } else {
+    com->name = "test_ihfo";
+    com->pk_hash.assign(ihfo_hash, ihfo_hash + arraysize(ihfo_hash));
   }
-
- private:
-  scoped_ptr<ComponentUpdateService> component_updater_;
-  base::FilePath test_data_dir_;
-  TestNotificationTracker notification_tracker_;
-  TestConfigurator* test_config_;
-  // ComponentInstaller objects to delete after each test.
-  ScopedVector<TestInstaller> test_installers_;
-};
+  com->version = version;
+  com->installer = installer;
+  return component_updater_->RegisterComponent(*com);
+}
 
 // Verify that our test fixture work and the component updater can
 // be created and destroyed with no side effects.
@@ -295,13 +232,17 @@
 
   content::URLLocalHostRequestPrepackagedInterceptor interceptor;
 
+  TestInstaller installer;
   CrxComponent com;
   EXPECT_EQ(ComponentUpdateService::kOk,
-            RegisterComponent(&com, kTestComponent_abag, Version("1.1")));
+            RegisterComponent(&com,
+                              kTestComponent_abag,
+                              Version("1.1"),
+                              &installer));
 
   const GURL expected_update_url(
-      "http://localhost/upd?extra=foo&x=id%3D"
-      "abagagagagagagagagagagagagagagag%26v%3D1.1%26uc");
+      "http://localhost/upd?extra=foo"
+      "&x=id%3Dabagagagagagagagagagagagagagagag%26v%3D1.1%26fp%3D%26uc");
 
   interceptor.SetResponse(expected_update_url,
                           test_file("updatecheck_reply_1.xml"));
@@ -374,20 +315,22 @@
 
   content::URLLocalHostRequestPrepackagedInterceptor interceptor;
 
+  TestInstaller installer1;
   CrxComponent com1;
-  RegisterComponent(&com1, kTestComponent_jebg, Version("0.9"));
+  RegisterComponent(&com1, kTestComponent_jebg, Version("0.9"), &installer1);
+  TestInstaller installer2;
   CrxComponent com2;
-  RegisterComponent(&com2, kTestComponent_abag, Version("2.2"));
+  RegisterComponent(&com2, kTestComponent_abag, Version("2.2"), &installer2);
 
   const GURL expected_update_url_1(
-      "http://localhost/upd?extra=foo&x=id%3D"
-      "jebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26uc&x=id%3D"
-      "abagagagagagagagagagagagagagagag%26v%3D2.2%26uc");
+      "http://localhost/upd?extra=foo"
+      "&x=id%3Djebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26fp%3D%26uc"
+      "&x=id%3Dabagagagagagagagagagagagagagagag%26v%3D2.2%26fp%3D%26uc");
 
   const GURL expected_update_url_2(
-      "http://localhost/upd?extra=foo&x=id%3D"
-      "abagagagagagagagagagagagagagagag%26v%3D2.2%26uc&x=id%3D"
-      "jebgalgnebhfojomionfpkfelancnnkf%26v%3D1.0%26uc");
+      "http://localhost/upd?extra=foo"
+      "&x=id%3Dabagagagagagagagagagagagagagagag%26v%3D2.2%26fp%3D%26uc"
+      "&x=id%3Djebgalgnebhfojomionfpkfelancnnkf%26v%3D1.0%26fp%3D%26uc");
 
   interceptor.SetResponse(expected_update_url_1,
                           test_file("updatecheck_reply_1.xml"));
@@ -425,78 +368,6 @@
   component_updater()->Stop();
 }
 
-// This test is like the above InstallCrx but the second component
-// has a different source. In this case there would be two manifest
-// checks to different urls, each only containing one component.
-TEST_F(ComponentUpdaterTest, InstallCrxTwoSources) {
-  base::MessageLoop message_loop;
-  content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop);
-  content::TestBrowserThread file_thread(BrowserThread::FILE);
-  content::TestBrowserThread io_thread(BrowserThread::IO);
-
-  io_thread.StartIOThread();
-  file_thread.Start();
-
-  content::URLLocalHostRequestPrepackagedInterceptor interceptor;
-
-  CrxComponent com1;
-  RegisterComponent(&com1, kTestComponent_abag, Version("2.2"));
-  CrxComponent com2;
-  com2.source = CrxComponent::CWS_PUBLIC;
-  RegisterComponent(&com2, kTestComponent_jebg, Version("0.9"));
-
-  const GURL expected_update_url_1(
-      "http://localhost/upd?extra=foo&x=id%3D"
-      "abagagagagagagagagagagagagagagag%26v%3D2.2%26uc");
-
-  const GURL expected_update_url_2(
-      "http://localhost/cws?extra=foo&x=id%3D"
-      "jebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26uc");
-
-  interceptor.SetResponse(expected_update_url_1,
-                          test_file("updatecheck_reply_3.xml"));
-  interceptor.SetResponse(expected_update_url_2,
-                          test_file("updatecheck_reply_1.xml"));
-  interceptor.SetResponse(GURL(expected_crx_url),
-                          test_file("jebgalgnebhfojomionfpkfelancnnkf.crx"));
-
-  test_configurator()->SetLoopCount(3);
-
-  // We have to set SetRecheckTime to something bigger than 0 or else the
-  // component updater will keep re-checking the 'abag' component because
-  // the default source pre-empts the other sources.
-  test_configurator()->SetRecheckTime(60*60);
-
-  component_updater()->Start();
-  message_loop.Run();
-
-  EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->error());
-  EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->install_count());
-  EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->error());
-  EXPECT_EQ(1, static_cast<TestInstaller*>(com2.installer)->install_count());
-
-  EXPECT_EQ(3, interceptor.GetHitCount());
-
-  ASSERT_EQ(6ul, notification_tracker().size());
-
-  TestNotificationTracker::Event ev0 = notification_tracker().at(1);
-  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev0.type);
-
-  TestNotificationTracker::Event ev1 = notification_tracker().at(2);
-  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND, ev1.type);
-
-  TestNotificationTracker::Event ev2 = notification_tracker().at(3);
-  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_READY, ev2.type);
-
-  TestNotificationTracker::Event ev3 = notification_tracker().at(4);
-  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev3.type);
-
-  TestNotificationTracker::Event ev4 = notification_tracker().at(5);
-  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev4.type);
-
-  component_updater()->Stop();
-}
-
 // This test checks that the "prodversionmin" value is handled correctly. In
 // particular there should not be an install because the minimum product
 // version is much higher than of chrome.
@@ -511,12 +382,13 @@
 
   content::URLLocalHostRequestPrepackagedInterceptor interceptor;
 
+  TestInstaller installer;
   CrxComponent com;
-  RegisterComponent(&com, kTestComponent_jebg, Version("0.9"));
+  RegisterComponent(&com, kTestComponent_jebg, Version("0.9"), &installer);
 
   const GURL expected_update_url(
       "http://localhost/upd?extra=foo&x=id%3D"
-      "jebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26uc");
+      "jebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26fp%3D%26uc");
 
   interceptor.SetResponse(expected_update_url,
                           test_file("updatecheck_reply_2.xml"));
@@ -551,20 +423,23 @@
 
   content::URLLocalHostRequestPrepackagedInterceptor interceptor;
 
+  TestInstaller installer1;
   CrxComponent com1;
-  RegisterComponent(&com1, kTestComponent_abag, Version("2.2"));
+  RegisterComponent(&com1, kTestComponent_abag, Version("2.2"), &installer1);
+  TestInstaller installer2;
   CrxComponent com2;
-  RegisterComponent(&com2, kTestComponent_jebg, Version("0.9"));
+  RegisterComponent(&com2, kTestComponent_jebg, Version("0.9"), &installer2);
 
   const GURL expected_update_url_1(
-      "http://localhost/upd?extra=foo&x=id%3D"
-      "abagagagagagagagagagagagagagagag%26v%3D2.2%26uc&x=id%3D"
-      "jebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26uc");
+      "http://localhost/upd?extra=foo"
+      "&x=id%3Dabagagagagagagagagagagagagagagag%26v%3D2.2%26fp%3D%26uc"
+      "&x=id%3Djebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26fp%3D%26uc");
 
   const GURL expected_update_url_2(
-      "http://localhost/upd?extra=foo&x=id%3D"
-      "jebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26uc&x=id%3D"
-      "abagagagagagagagagagagagagagagag%26v%3D2.2%26uc");
+      "http://localhost/upd?extra=foo"
+      "&x=id%3Djebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26fp%3D%26uc"
+      "%26installsource%3Dondemand"
+      "&x=id%3Dabagagagagagagagagagagagagagagag%26v%3D2.2%26fp%3D%26uc");
 
   interceptor.SetResponse(expected_update_url_1,
                           test_file("updatecheck_reply_empty"));
@@ -613,9 +488,9 @@
   // Test a few error cases. NOTE: We don't have callbacks for
   // when the updates failed yet.
   const GURL expected_update_url_3(
-      "http://localhost/upd?extra=foo&x=id%3D"
-      "jebgalgnebhfojomionfpkfelancnnkf%26v%3D1.0%26uc&x=id%3D"
-      "abagagagagagagagagagagagagagagag%26v%3D2.2%26uc");
+      "http://localhost/upd?extra=foo"
+      "&x=id%3Djebgalgnebhfojomionfpkfelancnnkf%26v%3D1.0%26fp%3D%26uc"
+      "&x=id%3Dabagagagagagagagagagagagagagagag%26v%3D2.2%26fp%3D%26uc");
 
   // No update: error from no server response
   interceptor.SetResponse(expected_update_url_3,
@@ -667,21 +542,23 @@
 
   content::URLLocalHostRequestPrepackagedInterceptor interceptor;
 
+  TestInstaller installer1;
   CrxComponent com1;
-  RegisterComponent(&com1, kTestComponent_jebg, Version("0.9"));
+  RegisterComponent(&com1, kTestComponent_jebg, Version("0.9"), &installer1);
+  TestInstaller installer2;
   CrxComponent com2;
-  RegisterComponent(&com2, kTestComponent_abag, Version("2.2"));
+  RegisterComponent(&com2, kTestComponent_abag, Version("2.2"), &installer2);
 
   // Start with 0.9, and update to 1.0
   const GURL expected_update_url_1(
-      "http://localhost/upd?extra=foo&x=id%3D"
-      "jebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26uc&x=id%3D"
-      "abagagagagagagagagagagagagagagag%26v%3D2.2%26uc");
+      "http://localhost/upd?extra=foo"
+      "&x=id%3Djebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26fp%3D%26uc"
+      "&x=id%3Dabagagagagagagagagagagagagagagag%26v%3D2.2%26fp%3D%26uc");
 
   const GURL expected_update_url_2(
-      "http://localhost/upd?extra=foo&x=id%3D"
-      "abagagagagagagagagagagagagagagag%26v%3D2.2%26uc&x=id%3D"
-      "jebgalgnebhfojomionfpkfelancnnkf%26v%3D1.0%26uc");
+      "http://localhost/upd?extra=foo"
+      "&x=id%3Dabagagagagagagagagagagagagagagag%26v%3D2.2%26fp%3D%26uc"
+      "&x=id%3Djebgalgnebhfojomionfpkfelancnnkf%26v%3D1.0%26fp%3D%26uc");
 
   interceptor.SetResponse(expected_update_url_1,
                           test_file("updatecheck_reply_1.xml"));
@@ -722,16 +599,20 @@
   EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev4.type);
 
   // Now re-register, pretending to be an even newer version (2.2)
+  TestInstaller installer3;
   component_updater()->Stop();
   EXPECT_EQ(ComponentUpdateService::kReplaced,
-            RegisterComponent(&com1, kTestComponent_jebg, Version("2.2")));
+            RegisterComponent(&com1,
+                              kTestComponent_jebg,
+                              Version("2.2"),
+                              &installer3));
 
   // Check that we send out 2.2 as our version.
   // Interceptor's hit count should go up by 1.
   const GURL expected_update_url_3(
-      "http://localhost/upd?extra=foo&x=id%3D"
-      "jebgalgnebhfojomionfpkfelancnnkf%26v%3D2.2%26uc&x=id%3D"
-      "abagagagagagagagagagagagagagagag%26v%3D2.2%26uc");
+      "http://localhost/upd?extra=foo"
+      "&x=id%3Djebgalgnebhfojomionfpkfelancnnkf%26v%3D2.2%26fp%3D%26uc"
+      "&x=id%3Dabagagagagagagagagagagagagagagag%26v%3D2.2%26fp%3D%26uc");
 
   interceptor.SetResponse(expected_update_url_3,
                           test_file("updatecheck_reply_1.xml"));
@@ -753,8 +634,7 @@
 
   EXPECT_EQ(4, interceptor.GetHitCount());
 
-  // The test harness's Register() function creates a new installer,
-  // so the counts go back to 0.
+  // We created a new installer, so the counts go back to 0.
   EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->error());
   EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->install_count());
   EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->error());
@@ -762,3 +642,127 @@
 
   component_updater()->Stop();
 }
+
+// Verify that component installation falls back to downloading and installing
+// a full update if the differential update fails (in this case, because the
+// installer does not know about the existing files). We do two loops; the final
+// loop should do nothing.
+// We also check that exactly 4 network requests are issued:
+// 1- update check (loop 1)
+// 2- download differential crx
+// 3- download full crx
+// 4- update check (loop 2 - no update available)
+TEST_F(ComponentUpdaterTest, DifferentialUpdateFails) {
+  base::MessageLoop message_loop;
+  content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop);
+  content::TestBrowserThread file_thread(BrowserThread::FILE);
+  content::TestBrowserThread io_thread(BrowserThread::IO);
+
+  io_thread.StartIOThread();
+  file_thread.Start();
+
+  content::URLLocalHostRequestPrepackagedInterceptor interceptor;
+
+  TestInstaller installer;
+  CrxComponent com;
+  RegisterComponent(&com, kTestComponent_ihfo, Version("1.0"), &installer);
+
+  const GURL expected_update_url_1(
+      "http://localhost/upd?extra=foo"
+      "&x=id%3Dihfokbkgjpifnbbojhneepfflplebdkc%26v%3D1.0%26fp%3D%26uc");
+  const GURL expected_update_url_2(
+      "http://localhost/upd?extra=foo"
+      "&x=id%3Dihfokbkgjpifnbbojhneepfflplebdkc%26v%3D2.0%26fp%3Df22%26uc");
+  const GURL expected_crx_url_1(
+      "http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx");
+  const GURL expected_crx_url_1_diff_2(
+      "http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx");
+  const GURL expected_crx_url_2(
+      "http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_2.crx");
+
+  interceptor.SetResponse(expected_update_url_1,
+                          test_file("updatecheck_diff_reply_2.xml"));
+  interceptor.SetResponse(expected_update_url_2,
+                          test_file("updatecheck_diff_reply_3.xml"));
+  interceptor.SetResponse(expected_crx_url_1,
+                          test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"));
+  interceptor.SetResponse(
+      expected_crx_url_1_diff_2,
+      test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"));
+  interceptor.SetResponse(expected_crx_url_2,
+                          test_file("ihfokbkgjpifnbbojhneepfflplebdkc_2.crx"));
+
+  test_configurator()->SetLoopCount(2);
+
+  component_updater()->Start();
+  message_loop.Run();
+
+  // A failed differential update does not count as a failed install.
+  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
+  EXPECT_EQ(1, static_cast<TestInstaller*>(com.installer)->install_count());
+
+  EXPECT_EQ(4, interceptor.GetHitCount());
+
+  component_updater()->Stop();
+}
+
+// Verify that we successfully propagate a patcher error.
+// ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad.crx contains an incorrect
+// patching instruction that should fail.
+TEST_F(ComponentUpdaterTest, DifferentialUpdateFailErrorcode) {
+  base::MessageLoop message_loop;
+  content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop);
+  content::TestBrowserThread file_thread(BrowserThread::FILE);
+  content::TestBrowserThread io_thread(BrowserThread::IO);
+
+  io_thread.StartIOThread();
+  file_thread.Start();
+
+  content::URLLocalHostRequestPrepackagedInterceptor interceptor;
+
+  VersionedTestInstaller installer;
+  CrxComponent com;
+  RegisterComponent(&com, kTestComponent_ihfo, Version("0.0"), &installer);
+
+  const GURL expected_update_url_0(
+      "http://localhost/upd?extra=foo"
+      "&x=id%3Dihfokbkgjpifnbbojhneepfflplebdkc%26v%3D0.0%26fp%3D%26uc");
+  const GURL expected_update_url_1(
+      "http://localhost/upd?extra=foo"
+      "&x=id%3Dihfokbkgjpifnbbojhneepfflplebdkc%26v%3D1.0%26fp%3D1%26uc");
+  const GURL expected_update_url_2(
+      "http://localhost/upd?extra=foo"
+      "&x=id%3Dihfokbkgjpifnbbojhneepfflplebdkc%26v%3D2.0%26fp%3Df22%26uc");
+  const GURL expected_crx_url_1(
+      "http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx");
+  const GURL expected_crx_url_1_diff_2(
+      "http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx");
+  const GURL expected_crx_url_2(
+      "http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_2.crx");
+
+  interceptor.SetResponse(expected_update_url_0,
+                          test_file("updatecheck_diff_reply_1.xml"));
+  interceptor.SetResponse(expected_update_url_1,
+                          test_file("updatecheck_diff_reply_2.xml"));
+  interceptor.SetResponse(expected_update_url_2,
+                          test_file("updatecheck_diff_reply_3.xml"));
+  interceptor.SetResponse(expected_crx_url_1,
+                          test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"));
+  interceptor.SetResponse(
+      expected_crx_url_1_diff_2,
+      test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad.crx"));
+  interceptor.SetResponse(expected_crx_url_2,
+                          test_file("ihfokbkgjpifnbbojhneepfflplebdkc_2.crx"));
+
+  test_configurator()->SetLoopCount(3);
+
+  component_updater()->Start();
+  message_loop.Run();
+
+  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
+  EXPECT_EQ(2, static_cast<TestInstaller*>(com.installer)->install_count());
+
+  EXPECT_EQ(6, interceptor.GetHitCount());
+
+  component_updater()->Stop();
+}
diff --git a/chrome/browser/component_updater/test/component_updater_service_unittest.h b/chrome/browser/component_updater/test/component_updater_service_unittest.h
new file mode 100644
index 0000000..ba98102
--- /dev/null
+++ b/chrome/browser/component_updater/test/component_updater_service_unittest.h
@@ -0,0 +1,134 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_COMPONENT_UPDATER_TEST_COMPONENT_UPDATER_SERVICE_UNITTEST_H_
+#define CHROME_BROWSER_COMPONENT_UPDATER_TEST_COMPONENT_UPDATER_SERVICE_UNITTEST_H_
+
+#include <list>
+#include <utility>
+
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "chrome/browser/component_updater/component_updater_service.h"
+#include "chrome/browser/component_updater/test/component_patcher_mock.h"
+#include "content/public/test/test_notification_tracker.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using content::TestNotificationTracker;
+
+class GURL;
+class TestInstaller;
+
+// component 1 has extension id "jebgalgnebhfojomionfpkfelancnnkf", and
+// the RSA public key the following hash:
+const uint8 jebg_hash[] = {0x94, 0x16, 0x0b, 0x6d, 0x41, 0x75, 0xe9, 0xec,
+                           0x8e, 0xd5, 0xfa, 0x54, 0xb0, 0xd2, 0xdd, 0xa5,
+                           0x6e, 0x05, 0x6b, 0xe8, 0x73, 0x47, 0xf6, 0xc4,
+                           0x11, 0x9f, 0xbc, 0xb3, 0x09, 0xb3, 0x5b, 0x40};
+// component 2 has extension id "abagagagagagagagagagagagagagagag", and
+// the RSA public key the following hash:
+const uint8 abag_hash[] = {0x01, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+                           0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+                           0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+                           0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x01};
+// component 3 has extension id "ihfokbkgjpifnbbojhneepfflplebdkc", and
+// the RSA public key the following hash:
+const uint8 ihfo_hash[] = {0x87, 0x5e, 0xa1, 0xa6, 0x9f, 0x85, 0xd1, 0x1e,
+                           0x97, 0xd4, 0x4f, 0x55, 0xbf, 0xb4, 0x13, 0xa2,
+                           0xe7, 0xc5, 0xc8, 0xf5, 0x60, 0x19, 0x78, 0x1b,
+                           0x6d, 0xe9, 0x4c, 0xeb, 0x96, 0x05, 0x42, 0x17};
+
+class TestConfigurator : public ComponentUpdateService::Configurator {
+ public:
+  explicit TestConfigurator();
+
+  virtual ~TestConfigurator();
+
+  virtual int InitialDelay() OVERRIDE;
+
+  typedef std::pair<CrxComponent*, int> CheckAtLoopCount;
+
+  virtual int NextCheckDelay() OVERRIDE;
+
+  virtual int StepDelay() OVERRIDE;
+
+  virtual int MinimumReCheckWait() OVERRIDE;
+
+  virtual int OnDemandDelay() OVERRIDE;
+
+  virtual GURL UpdateUrl() OVERRIDE;
+
+  virtual const char* ExtraRequestParams() OVERRIDE;
+
+  virtual size_t UrlSizeLimit() OVERRIDE;
+
+  virtual net::URLRequestContextGetter* RequestContext() OVERRIDE;
+
+  // Don't use the utility process to decode files.
+  virtual bool InProcess() OVERRIDE;
+
+  virtual void OnEvent(Events event, int extra) OVERRIDE;
+
+  virtual ComponentPatcher* CreateComponentPatcher() OVERRIDE;
+
+  virtual bool DeltasEnabled() const OVERRIDE;
+
+  void SetLoopCount(int times);
+
+  void SetRecheckTime(int seconds);
+
+  void SetOnDemandTime(int seconds);
+
+  void AddComponentToCheck(CrxComponent* com, int at_loop_iter);
+
+  void SetComponentUpdateService(ComponentUpdateService* cus);
+
+ private:
+  int times_;
+  int recheck_time_;
+  int ondemand_time_;
+
+  std::list<CheckAtLoopCount> components_to_check_;
+  ComponentUpdateService* cus_;
+};
+
+class ComponentUpdaterTest : public testing::Test {
+ public:
+  enum TestComponents {
+    kTestComponent_abag,
+    kTestComponent_jebg,
+    kTestComponent_ihfo,
+  };
+
+  ComponentUpdaterTest();
+
+  virtual ~ComponentUpdaterTest();
+
+  virtual void TearDown();
+
+  ComponentUpdateService* component_updater();
+
+  // Makes the full path to a component updater test file.
+  const base::FilePath test_file(const char* file);
+
+  TestNotificationTracker& notification_tracker();
+
+  TestConfigurator* test_configurator();
+
+  ComponentUpdateService::Status RegisterComponent(CrxComponent* com,
+                                                   TestComponents component,
+                                                   const Version& version,
+                                                   TestInstaller* installer);
+
+ private:
+  scoped_ptr<ComponentUpdateService> component_updater_;
+  base::FilePath test_data_dir_;
+  TestNotificationTracker notification_tracker_;
+  TestConfigurator* test_config_;
+};
+
+const char expected_crx_url[] =
+    "http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx";
+
+#endif  // CHROME_BROWSER_COMPONENT_UPDATER_TEST_COMPONENT_UPDATER_SERVICE_UNITTEST_H_
diff --git a/chrome/browser/component_updater/test/component_updater_service_unittest_win.cc b/chrome/browser/component_updater/test/component_updater_service_unittest_win.cc
new file mode 100644
index 0000000..973f037
--- /dev/null
+++ b/chrome/browser/component_updater/test/component_updater_service_unittest_win.cc
@@ -0,0 +1,101 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <list>
+#include <utility>
+#include "base/compiler_specific.h"
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/memory/scoped_vector.h"
+#include "base/message_loop.h"
+#include "base/path_service.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/stringprintf.h"
+#include "base/values.h"
+#include "chrome/browser/component_updater/component_updater_service.h"
+#include "chrome/browser/component_updater/test/component_patcher_mock.h"
+#include "chrome/browser/component_updater/test/component_updater_service_unittest.h"
+#include "chrome/browser/component_updater/test/test_installer.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "chrome/common/chrome_paths.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_notification_tracker.h"
+#include "content/test/net/url_request_prepackaged_interceptor.h"
+#include "libxml/globals.h"
+#include "net/base/upload_bytes_element_reader.h"
+#include "net/url_request/url_fetcher.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_filter.h"
+#include "net/url_request/url_request_simple_job.h"
+#include "net/url_request/url_request_test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+using content::BrowserThread;
+using content::TestNotificationTracker;
+
+// Verify that we can download and install a component and a differential
+// update to that component. We do three loops; the final loop should do
+// nothing.
+// We also check that exactly 5 network requests are issued:
+// 1- update check (response: v1 available)
+// 2- download crx (v1)
+// 3- update check (response: v2 available)
+// 4- download differential crx (v1 to v2)
+// 5- update check (response: no further update available)
+TEST_F(ComponentUpdaterTest, DifferentialUpdate) {
+  base::MessageLoop message_loop;
+  content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop);
+  content::TestBrowserThread file_thread(BrowserThread::FILE);
+  content::TestBrowserThread io_thread(BrowserThread::IO);
+
+  io_thread.StartIOThread();
+  file_thread.Start();
+
+  content::URLLocalHostRequestPrepackagedInterceptor interceptor;
+
+  VersionedTestInstaller installer;
+  CrxComponent com;
+  RegisterComponent(&com, kTestComponent_ihfo, Version("0.0"), &installer);
+
+  const GURL expected_update_url_0(
+      "http://localhost/upd?extra=foo"
+      "&x=id%3Dihfokbkgjpifnbbojhneepfflplebdkc%26v%3D0.0%26fp%3D%26uc");
+  const GURL expected_update_url_1(
+      "http://localhost/upd?extra=foo"
+      "&x=id%3Dihfokbkgjpifnbbojhneepfflplebdkc%26v%3D1.0%26fp%3D1%26uc");
+  const GURL expected_update_url_2(
+      "http://localhost/upd?extra=foo"
+      "&x=id%3Dihfokbkgjpifnbbojhneepfflplebdkc%26v%3D2.0%26fp%3Df22%26uc");
+  const GURL expected_crx_url_1(
+      "http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx");
+  const GURL expected_crx_url_1_diff_2(
+      "http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx");
+
+  interceptor.SetResponse(expected_update_url_0,
+                          test_file("updatecheck_diff_reply_1.xml"));
+  interceptor.SetResponse(expected_update_url_1,
+                          test_file("updatecheck_diff_reply_2.xml"));
+  interceptor.SetResponse(expected_update_url_2,
+                          test_file("updatecheck_diff_reply_3.xml"));
+  interceptor.SetResponse(expected_crx_url_1,
+                          test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"));
+  interceptor.SetResponse(
+      expected_crx_url_1_diff_2,
+      test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"));
+
+  test_configurator()->SetLoopCount(3);
+
+  component_updater()->Start();
+  message_loop.Run();
+
+  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
+  EXPECT_EQ(2, static_cast<TestInstaller*>(com.installer)->install_count());
+
+  EXPECT_EQ(5, interceptor.GetHitCount());
+
+  component_updater()->Stop();
+}
diff --git a/chrome/browser/component_updater/test/test_installer.cc b/chrome/browser/component_updater/test/test_installer.cc
new file mode 100644
index 0000000..3f9b0e0
--- /dev/null
+++ b/chrome/browser/component_updater/test/test_installer.cc
@@ -0,0 +1,81 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/component_updater/test/test_installer.h"
+
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/values.h"
+
+TestInstaller::TestInstaller()
+    : error_(0), install_count_(0) {
+}
+
+void TestInstaller::OnUpdateError(int error) {
+  error_ = error;
+}
+
+bool TestInstaller::Install(const base::DictionaryValue& manifest,
+                            const base::FilePath& unpack_path) {
+  ++install_count_;
+  return base::Delete(unpack_path, true);
+}
+
+bool TestInstaller::GetInstalledFile(const std::string& file,
+                                     base::FilePath* installed_file) {
+  return false;
+}
+
+int TestInstaller::error() const { return error_; }
+
+int TestInstaller::install_count() const { return install_count_; }
+
+
+ReadOnlyTestInstaller::ReadOnlyTestInstaller(const base::FilePath& install_dir)
+    : install_directory_(install_dir) {
+}
+
+ReadOnlyTestInstaller::~ReadOnlyTestInstaller() {
+}
+
+bool ReadOnlyTestInstaller::GetInstalledFile(const std::string& file,
+                                             base::FilePath* installed_file) {
+  *installed_file = install_directory_.AppendASCII(file);
+  return true;
+}
+
+
+VersionedTestInstaller::VersionedTestInstaller() {
+  file_util::CreateNewTempDirectory(FILE_PATH_LITERAL("TEST_"),
+                                    &install_directory_);
+}
+
+VersionedTestInstaller::~VersionedTestInstaller() {
+  base::Delete(install_directory_, true);
+}
+
+
+bool VersionedTestInstaller::Install(const base::DictionaryValue& manifest,
+                                     const base::FilePath& unpack_path) {
+  std::string version_string;
+  manifest.GetStringASCII("version", &version_string);
+  Version version(version_string.c_str());
+
+  base::FilePath path;
+  path = install_directory_.AppendASCII(version.GetString());
+  file_util::CreateDirectory(path.DirName());
+  if (!base::Move(unpack_path, path))
+    return false;
+  current_version_ = version;
+  ++install_count_;
+  return true;
+}
+
+bool VersionedTestInstaller::GetInstalledFile(const std::string& file,
+                                              base::FilePath* installed_file) {
+  base::FilePath path;
+  path = install_directory_.AppendASCII(current_version_.GetString());
+  *installed_file = path.Append(base::FilePath::FromUTF8Unsafe(file));
+  return true;
+}
diff --git a/chrome/browser/component_updater/test/test_installer.h b/chrome/browser/component_updater/test/test_installer.h
new file mode 100644
index 0000000..2233d88
--- /dev/null
+++ b/chrome/browser/component_updater/test/test_installer.h
@@ -0,0 +1,73 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_COMPONENT_UPDATER_TEST_TEST_INSTALLER_H_
+#define CHROME_BROWSER_COMPONENT_UPDATER_TEST_TEST_INSTALLER_H_
+
+#include "base/compiler_specific.h"
+#include "base/files/file_path.h"
+#include "chrome/browser/component_updater/component_updater_service.h"
+
+namespace base {
+class DictionaryValue;
+}
+
+// A TestInstaller is an installer that does nothing for installation except
+// increment a counter.
+class TestInstaller : public ComponentInstaller {
+ public:
+  explicit TestInstaller();
+
+  virtual void OnUpdateError(int error) OVERRIDE;
+
+  virtual bool Install(const base::DictionaryValue& manifest,
+                       const base::FilePath& unpack_path) OVERRIDE;
+
+  virtual bool GetInstalledFile(const std::string& file,
+                                base::FilePath* installed_file) OVERRIDE;
+
+  int error() const;
+
+  int install_count() const;
+
+ protected:
+  int error_;
+  int install_count_;
+};
+
+// A ReadOnlyTestInstaller is an installer that knows about files in an existing
+// directory. It will not write to the directory.
+class ReadOnlyTestInstaller : public TestInstaller {
+ public:
+  explicit ReadOnlyTestInstaller(const base::FilePath& installed_path);
+
+  virtual ~ReadOnlyTestInstaller();
+
+  virtual bool GetInstalledFile(const std::string& file,
+                                base::FilePath* installed_file) OVERRIDE;
+
+ private:
+  base::FilePath install_directory_;
+};
+
+// A VersionedTestInstaller is an installer that installs files into versioned
+// directories (e.g. somedir/25.23.89.141/<files>).
+class VersionedTestInstaller : public TestInstaller {
+ public :
+  explicit VersionedTestInstaller();
+
+  virtual ~VersionedTestInstaller();
+
+  virtual bool Install(const base::DictionaryValue& manifest,
+                       const base::FilePath& unpack_path) OVERRIDE;
+
+  virtual bool GetInstalledFile(const std::string& file,
+                                base::FilePath* installed_file) OVERRIDE;
+
+ private:
+  base::FilePath install_directory_;
+  Version current_version_;
+};
+
+#endif  // CHROME_BROWSER_COMPONENT_UPDATER_TEST_TEST_INSTALLER_H_
diff --git a/chrome/browser/component_updater/widevine_cdm_component_installer.cc b/chrome/browser/component_updater/widevine_cdm_component_installer.cc
index 822aff2..bbfebbd 100644
--- a/chrome/browser/component_updater/widevine_cdm_component_installer.cc
+++ b/chrome/browser/component_updater/widevine_cdm_component_installer.cc
@@ -195,6 +195,9 @@
   virtual bool Install(const base::DictionaryValue& manifest,
                        const base::FilePath& unpack_path) OVERRIDE;
 
+  virtual bool GetInstalledFile(const std::string& file,
+                                base::FilePath* installed_file) OVERRIDE;
+
  private:
   base::Version current_version_;
 };
@@ -231,7 +234,7 @@
       GetWidevineCdmBaseDirectory().AppendASCII(version.GetString());
   if (file_util::PathExists(install_path))
     return false;
-  if (!file_util::Move(unpack_path, install_path))
+  if (!base::Move(unpack_path, install_path))
     return false;
 
   base::FilePath adapter_install_path =
@@ -246,6 +249,21 @@
   return true;
 }
 
+bool WidevineCdmComponentInstaller::GetInstalledFile(
+    const std::string& file, base::FilePath* installed_file) {
+  // Only the CDM is component-updated.
+  if (file != kWidevineCdmFileName)
+    return false;
+
+  if (current_version_.Equals(base::Version(kNullVersion)))
+    return false;  // No CDM has been installed yet.
+
+  *installed_file =
+      GetWidevineCdmBaseDirectory().AppendASCII(current_version_.GetString())
+          .AppendASCII(kWidevineCdmFileName);
+  return true;
+}
+
 void FinishWidevineCdmUpdateRegistration(ComponentUpdateService* cus,
                                          const base::Version& version) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -284,7 +302,7 @@
           BrowserThread::UI, FROM_HERE,
           base::Bind(&RegisterWidevineCdmWithChrome, adapter_path, version));
     } else {
-      file_util::Delete(latest_dir, true);
+      base::Delete(latest_dir, true);
       version = base::Version(kNullVersion);
     }
   }
@@ -296,7 +314,7 @@
   // Remove older versions of Widevine CDM.
   for (std::vector<base::FilePath>::iterator iter = older_dirs.begin();
        iter != older_dirs.end(); ++iter) {
-    file_util::Delete(*iter, true);
+    base::Delete(*iter, true);
   }
 }
 
diff --git a/chrome/browser/content_settings/content_settings_browsertest.cc b/chrome/browser/content_settings/content_settings_browsertest.cc
index 3bb6c42..857612c 100644
--- a/chrome/browser/content_settings/content_settings_browsertest.cc
+++ b/chrome/browser/content_settings/content_settings_browsertest.cc
@@ -489,7 +489,7 @@
     const char kLibraryName[] = "clearkeycdmadapter.plugin";
 #elif defined(OS_POSIX)
     const char kLibraryName[] = "libclearkeycdmadapter.so";
-#endif
+#endif  // defined(OS_MACOSX)
 #endif  // defined(OS_WIN)
 
     // Append the switch to register the External Clear Key CDM.
@@ -571,7 +571,7 @@
 
 #if defined(ENABLE_PEPPER_CDMS)
   RunLoadPepperPluginTest(kExternalClearKeyMimeType, true);
-#endif
+#endif  // defined(ENABLE_PEPPER_CDMS)
 
   // Next, test behavior when plug-ins are blocked.
   content_settings->SetDefaultContentSetting(
@@ -583,12 +583,12 @@
 
 #if defined(WIDEVINE_CDM_AVAILABLE)
   RunLoadPepperPluginTest(kWidevineCdmPluginMimeType, true);
-#endif
+#endif  // defined(WIDEVINE_CDM_AVAILABLE)
 #endif  // defined(ENABLE_PEPPER_CDMS)
 
 #if !defined(DISABLE_NACL)
   RunLoadPepperPluginTest("application/x-nacl", true);
-#endif
+#endif  // !defined(DISABLE_NACL)
 
   // Finally, test behavior when (just) JavaScript is blocked.
   content_settings->SetDefaultContentSetting(
@@ -602,12 +602,12 @@
 
 #if defined(WIDEVINE_CDM_AVAILABLE)
   RunJavaScriptBlockedTest("load_widevine_no_js.html", true);
-#endif
+#endif  // defined(WIDEVINE_CDM_AVAILABLE)
 #endif  // defined(ENABLE_PEPPER_CDMS)
 
 #if !defined(DISABLE_NACL)
   RunJavaScriptBlockedTest("load_nacl_no_js.html", true);
-#endif
+#endif  // !defined(DISABLE_NACL)
 }
 
 #endif  // defined(ENABLE_PLUGINS)
diff --git a/chrome/browser/content_settings/content_settings_default_provider.cc b/chrome/browser/content_settings/content_settings_default_provider.cc
index 51592fa..af80637 100644
--- a/chrome/browser/content_settings/content_settings_default_provider.cc
+++ b/chrome/browser/content_settings/content_settings_default_provider.cc
@@ -24,7 +24,7 @@
 #include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_source.h"
 #include "content/public/browser/user_metrics.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 using content::BrowserThread;
 using content::UserMetricsAction;
diff --git a/chrome/browser/content_settings/content_settings_default_provider_unittest.cc b/chrome/browser/content_settings/content_settings_default_provider_unittest.cc
index cfd7448..0e2fdcf 100644
--- a/chrome/browser/content_settings/content_settings_default_provider_unittest.cc
+++ b/chrome/browser/content_settings/content_settings_default_provider_unittest.cc
@@ -12,8 +12,8 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/test/test_browser_thread.h"
-#include "googleurl/src/gurl.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 using ::testing::_;
 using content::BrowserThread;
diff --git a/chrome/browser/content_settings/content_settings_origin_identifier_value_map.cc b/chrome/browser/content_settings/content_settings_origin_identifier_value_map.cc
index 56cc0bd..c46cf91 100644
--- a/chrome/browser/content_settings/content_settings_origin_identifier_value_map.cc
+++ b/chrome/browser/content_settings/content_settings_origin_identifier_value_map.cc
@@ -12,7 +12,7 @@
 #include "chrome/browser/content_settings/content_settings_rule.h"
 #include "chrome/browser/content_settings/content_settings_utils.h"
 #include "chrome/common/content_settings_types.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 namespace content_settings {
 
diff --git a/chrome/browser/content_settings/content_settings_origin_identifier_value_map_unittest.cc b/chrome/browser/content_settings/content_settings_origin_identifier_value_map_unittest.cc
index b8612a5..aad03fa 100644
--- a/chrome/browser/content_settings/content_settings_origin_identifier_value_map_unittest.cc
+++ b/chrome/browser/content_settings/content_settings_origin_identifier_value_map_unittest.cc
@@ -8,8 +8,8 @@
 #include "base/values.h"
 #include "chrome/browser/content_settings/content_settings_rule.h"
 #include "chrome/browser/content_settings/content_settings_utils.h"
-#include "googleurl/src/gurl.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 TEST(OriginIdentifierValueMapTest, SetGetValue) {
   content_settings::OriginIdentifierValueMap map;
diff --git a/chrome/browser/content_settings/content_settings_policy_provider_unittest.cc b/chrome/browser/content_settings/content_settings_policy_provider_unittest.cc
index ca4ab11..345663f 100644
--- a/chrome/browser/content_settings/content_settings_policy_provider_unittest.cc
+++ b/chrome/browser/content_settings/content_settings_policy_provider_unittest.cc
@@ -20,8 +20,8 @@
 #include "chrome/test/base/testing_pref_service_syncable.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/test/test_browser_thread.h"
-#include "googleurl/src/gurl.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 using ::testing::_;
 using content::BrowserThread;
diff --git a/chrome/browser/content_settings/content_settings_pref_provider.cc b/chrome/browser/content_settings/content_settings_pref_provider.cc
index 8f53c68..d5b4894 100644
--- a/chrome/browser/content_settings/content_settings_pref_provider.cc
+++ b/chrome/browser/content_settings/content_settings_pref_provider.cc
@@ -27,7 +27,7 @@
 #include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_source.h"
 #include "content/public/browser/user_metrics.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 using content::BrowserThread;
 using content::UserMetricsAction;
diff --git a/chrome/browser/content_settings/content_settings_pref_provider_unittest.cc b/chrome/browser/content_settings/content_settings_pref_provider_unittest.cc
index b227855..efbe7cf 100644
--- a/chrome/browser/content_settings/content_settings_pref_provider_unittest.cc
+++ b/chrome/browser/content_settings/content_settings_pref_provider_unittest.cc
@@ -28,8 +28,8 @@
 #include "chrome/test/base/testing_profile.h"
 #include "components/user_prefs/pref_registry_syncable.h"
 #include "content/public/test/test_browser_thread.h"
-#include "googleurl/src/gurl.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 using ::testing::_;
 using content::BrowserThread;
diff --git a/chrome/browser/content_settings/content_settings_provider.h b/chrome/browser/content_settings/content_settings_provider.h
index 6bc64de..c75aca0 100644
--- a/chrome/browser/content_settings/content_settings_provider.h
+++ b/chrome/browser/content_settings/content_settings_provider.h
@@ -54,7 +54,7 @@
       const ContentSettingsPattern& secondary_pattern,
       ContentSettingsType content_type,
       const ResourceIdentifier& resource_identifier,
-      Value* value) = 0;
+      base::Value* value) = 0;
 
   // Resets all content settings for the given |content_type| and empty resource
   // identifier to CONTENT_SETTING_DEFAULT.
diff --git a/chrome/browser/content_settings/content_settings_provider_unittest.cc b/chrome/browser/content_settings/content_settings_provider_unittest.cc
index 0832a1c..d3d092c 100644
--- a/chrome/browser/content_settings/content_settings_provider_unittest.cc
+++ b/chrome/browser/content_settings/content_settings_provider_unittest.cc
@@ -7,7 +7,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "chrome/browser/content_settings/content_settings_mock_provider.h"
 #include "chrome/browser/content_settings/content_settings_utils.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 namespace content_settings {
 
diff --git a/chrome/browser/content_settings/content_settings_utils.cc b/chrome/browser/content_settings/content_settings_utils.cc
index 9754ba1..52f1650 100644
--- a/chrome/browser/content_settings/content_settings_utils.cc
+++ b/chrome/browser/content_settings/content_settings_utils.cc
@@ -17,7 +17,7 @@
 #include "chrome/browser/content_settings/host_content_settings_map.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/content_settings_pattern.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 namespace {
 
diff --git a/chrome/browser/content_settings/cookie_settings.cc b/chrome/browser/content_settings/cookie_settings.cc
index 2513a0c..bd82c1d 100644
--- a/chrome/browser/content_settings/cookie_settings.cc
+++ b/chrome/browser/content_settings/cookie_settings.cc
@@ -22,9 +22,9 @@
 #include "content/public/browser/notification_source.h"
 #include "content/public/browser/user_metrics.h"
 #include "extensions/common/constants.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/net_errors.h"
 #include "net/base/static_cookie_policy.h"
+#include "url/gurl.h"
 
 using content::BrowserThread;
 using content::UserMetricsAction;
diff --git a/chrome/browser/content_settings/cookie_settings_unittest.cc b/chrome/browser/content_settings/cookie_settings_unittest.cc
index 59f4570..45e1eeb 100644
--- a/chrome/browser/content_settings/cookie_settings_unittest.cc
+++ b/chrome/browser/content_settings/cookie_settings_unittest.cc
@@ -12,9 +12,9 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/test/test_browser_thread.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/static_cookie_policy.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 using content::BrowserThread;
 
diff --git a/chrome/browser/content_settings/host_content_settings_map.cc b/chrome/browser/content_settings/host_content_settings_map.cc
index 4cc1d77..fad7c9d 100644
--- a/chrome/browser/content_settings/host_content_settings_map.cc
+++ b/chrome/browser/content_settings/host_content_settings_map.cc
@@ -35,9 +35,9 @@
 #include "content/public/browser/user_metrics.h"
 #include "content/public/common/content_switches.h"
 #include "extensions/common/constants.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/net_errors.h"
 #include "net/base/static_cookie_policy.h"
+#include "url/gurl.h"
 
 using content::BrowserThread;
 using content::UserMetricsAction;
diff --git a/chrome/browser/content_settings/host_content_settings_map_unittest.cc b/chrome/browser/content_settings/host_content_settings_map_unittest.cc
index 78f5a39..76f0dff 100644
--- a/chrome/browser/content_settings/host_content_settings_map_unittest.cc
+++ b/chrome/browser/content_settings/host_content_settings_map_unittest.cc
@@ -19,9 +19,9 @@
 #include "chrome/test/base/testing_pref_service_syncable.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/test/test_browser_thread.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/static_cookie_policy.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 using content::BrowserThread;
 
diff --git a/chrome/browser/content_settings/local_shared_objects_container.cc b/chrome/browser/content_settings/local_shared_objects_container.cc
index 3fd6d06..d4a996d 100644
--- a/chrome/browser/content_settings/local_shared_objects_container.cc
+++ b/chrome/browser/content_settings/local_shared_objects_container.cc
@@ -14,9 +14,9 @@
 #include "chrome/browser/browsing_data/cookies_tree_model.h"
 #include "chrome/browser/profiles/profile.h"
 #include "content/public/common/url_constants.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
 #include "net/cookies/canonical_cookie.h"
+#include "url/gurl.h"
 
 namespace {
 
diff --git a/chrome/browser/content_settings/mock_settings_observer.cc b/chrome/browser/content_settings/mock_settings_observer.cc
index c8de7fa..0640a2e 100644
--- a/chrome/browser/content_settings/mock_settings_observer.cc
+++ b/chrome/browser/content_settings/mock_settings_observer.cc
@@ -9,7 +9,7 @@
 #include "chrome/common/chrome_notification_types.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_source.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 MockSettingsObserver::MockSettingsObserver() {
   registrar_.Add(this, chrome::NOTIFICATION_CONTENT_SETTINGS_CHANGED,
diff --git a/chrome/browser/crash_handler_host_linux.cc b/chrome/browser/crash_handler_host_linux.cc
index 51e1a3c..b25696f 100644
--- a/chrome/browser/crash_handler_host_linux.cc
+++ b/chrome/browser/crash_handler_host_linux.cc
@@ -28,8 +28,8 @@
 #include "breakpad/src/client/linux/minidump_writer/linux_dumper.h"
 #include "breakpad/src/client/linux/minidump_writer/minidump_writer.h"
 #include "chrome/app/breakpad_linux_impl.h"
+#include "chrome/common/chrome_paths.h"
 #include "chrome/common/env_vars.h"
-#include "components/breakpad/common/breakpad_paths.h"
 #include "content/public/browser/browser_thread.h"
 
 #if defined(OS_ANDROID)
@@ -379,7 +379,7 @@
   base::FilePath dumps_path("/tmp");
   PathService::Get(base::DIR_TEMP, &dumps_path);
   if (!info->upload)
-    PathService::Get(breakpad::DIR_CRASH_DUMPS, &dumps_path);
+    PathService::Get(chrome::DIR_CRASH_DUMPS, &dumps_path);
   const uint64 rand = base::RandUint64();
   const std::string minidump_filename =
       base::StringPrintf("%s/chromium-%s-minidump-%016" PRIx64 ".dmp",
diff --git a/chrome/browser/crash_upload_list.cc b/chrome/browser/crash_upload_list.cc
index d5463ac..911fec4 100644
--- a/chrome/browser/crash_upload_list.cc
+++ b/chrome/browser/crash_upload_list.cc
@@ -4,107 +4,31 @@
 
 #include "chrome/browser/crash_upload_list.h"
 
-#include <algorithm>
-#include <iterator>
-
-#include "base/bind.h"
-#include "base/file_util.h"
 #include "base/files/file_path.h"
 #include "base/path_service.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_split.h"
+#include "chrome/common/chrome_paths.h"
 #if defined(OS_WIN)
 #include "chrome/browser/crash_upload_list_win.h"
 #endif
-#include "components/breakpad/common/breakpad_paths.h"
-#include "content/public/browser/browser_thread.h"
-
-using content::BrowserThread;
-
-CrashUploadList::CrashInfo::CrashInfo(const std::string& c, const base::Time& t)
-    : crash_id(c), crash_time(t) {}
-
-CrashUploadList::CrashInfo::~CrashInfo() {}
-
-// static
-CrashUploadList* CrashUploadList::Create(Delegate* delegate) {
-#if defined(OS_WIN)
-  return new CrashUploadListWin(delegate);
-#else
-  return new CrashUploadList(delegate);
-#endif
-}
 
 // static
 const char* CrashUploadList::kReporterLogFilename = "uploads.log";
 
-CrashUploadList::CrashUploadList(Delegate* delegate) : delegate_(delegate) {}
+// static
+CrashUploadList* CrashUploadList::Create(Delegate* delegate) {
+  base::FilePath crash_dir_path;
+  PathService::Get(chrome::DIR_CRASH_DUMPS, &crash_dir_path);
+  base::FilePath upload_log_path =
+      crash_dir_path.AppendASCII(kReporterLogFilename);
+#if defined(OS_WIN)
+  return new CrashUploadListWin(delegate, upload_log_path);
+#else
+  return new CrashUploadList(delegate, upload_log_path);
+#endif
+}
+
+CrashUploadList::CrashUploadList(Delegate* delegate,
+                                 const base::FilePath& upload_log_path)
+    : UploadList(delegate, upload_log_path) {}
 
 CrashUploadList::~CrashUploadList() {}
-
-void CrashUploadList::LoadCrashListAsynchronously() {
-  BrowserThread::PostBlockingPoolTask(
-      FROM_HERE,
-      base::Bind(&CrashUploadList::LoadCrashListAndInformDelegateOfCompletion,
-                 this));
-}
-
-void CrashUploadList::ClearDelegate() {
-  delegate_ = NULL;
-}
-
-
-void CrashUploadList::LoadCrashListAndInformDelegateOfCompletion() {
-  LoadCrashList();
-  BrowserThread::PostTask(
-      BrowserThread::UI,
-      FROM_HERE,
-      base::Bind(&CrashUploadList::InformDelegateOfCompletion, this));
-}
-
-void CrashUploadList::LoadCrashList() {
-  base::FilePath crash_dir_path;
-  PathService::Get(breakpad::DIR_CRASH_DUMPS, &crash_dir_path);
-  base::FilePath upload_log_path = crash_dir_path.AppendASCII("uploads.log");
-  if (file_util::PathExists(upload_log_path)) {
-    std::string contents;
-    file_util::ReadFileToString(upload_log_path, &contents);
-    std::vector<std::string> log_entries;
-    base::SplitStringAlongWhitespace(contents, &log_entries);
-    ParseLogEntries(log_entries);
-  }
-}
-
-void CrashUploadList::ParseLogEntries(
-    const std::vector<std::string>& log_entries) {
-  std::vector<std::string>::const_reverse_iterator i;
-  for (i = log_entries.rbegin(); i != log_entries.rend(); ++i) {
-    std::vector<std::string> components;
-    base::SplitString(*i, ',', &components);
-    // Skip any blank (or corrupted) lines.
-    if (components.size() != 2)
-      continue;
-    double seconds_since_epoch;
-    if (!base::StringToDouble(components[0], &seconds_since_epoch))
-      continue;
-    CrashInfo info(components[1], base::Time::FromDoubleT(seconds_since_epoch));
-    crashes_.push_back(info);
-  }
-}
-
-void CrashUploadList::InformDelegateOfCompletion() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  if (delegate_)
-    delegate_->OnCrashListAvailable();
-}
-
-void CrashUploadList::GetUploadedCrashes(unsigned int max_count,
-                                         std::vector<CrashInfo>* crashes) {
-  std::copy(crashes_.begin(),
-            crashes_.begin() + std::min<size_t>(crashes_.size(), max_count),
-            std::back_inserter(*crashes));
-}
-
-std::vector<CrashUploadList::CrashInfo>& CrashUploadList::crashes() {
-  return crashes_;
-}
diff --git a/chrome/browser/crash_upload_list.h b/chrome/browser/crash_upload_list.h
index 78af39d..f0b201c 100644
--- a/chrome/browser/crash_upload_list.h
+++ b/chrome/browser/crash_upload_list.h
@@ -5,32 +5,11 @@
 #ifndef CHROME_BROWSER_CRASH_UPLOAD_LIST_H_
 #define CHROME_BROWSER_CRASH_UPLOAD_LIST_H_
 
-#include <string>
-#include <vector>
+#include "chrome/browser/upload_list.h"
 
-#include "base/memory/ref_counted.h"
-#include "base/time.h"
-
-class CrashUploadList : public base::RefCountedThreadSafe<CrashUploadList> {
+// An upload list manager for crash reports from breakpad.
+class CrashUploadList : public UploadList {
  public:
-  struct CrashInfo {
-    CrashInfo(const std::string& c, const base::Time& t);
-    ~CrashInfo();
-
-    std::string crash_id;
-    base::Time crash_time;
-  };
-
-  class Delegate {
-   public:
-    // Invoked when the crash list has been loaded. Will be called on the
-    // UI thread.
-    virtual void OnCrashListAvailable() = 0;
-
-   protected:
-    virtual ~Delegate() {}
-  };
-
   // Static factory method that creates the platform-specific implementation
   // of the crash upload list with the given callback delegate.
   static CrashUploadList* Create(Delegate* delegate);
@@ -40,46 +19,12 @@
   static const char* kReporterLogFilename;
 
   // Creates a new crash upload list with the given callback delegate.
-  explicit CrashUploadList(Delegate* delegate);
-
-  // Starts loading the crash list. OnCrashListAvailable will be called when
-  // loading is complete.
-  void LoadCrashListAsynchronously();
-
-  // Clears the delegate, so that any outstanding asynchronous load will not
-  // call the delegate on completion.
-  void ClearDelegate();
-
-  // Populates |crashes| with the |max_count| most recent uploaded crashes,
-  // in reverse chronological order.
-  // Must be called only after OnCrashListAvailable has been called.
-  void GetUploadedCrashes(unsigned int max_count,
-                          std::vector<CrashInfo>* crashes);
+  CrashUploadList(Delegate* delegate, const base::FilePath& upload_log_path);
 
  protected:
   virtual ~CrashUploadList();
 
-  // Reads the upload log and stores the entries in crashes_.
-  virtual void LoadCrashList();
-
-  // Returns a reference to the list of crashes.
-  std::vector<CrashInfo>& crashes();
-
  private:
-  friend class base::RefCountedThreadSafe<CrashUploadList>;
-
-  // Manages the background thread work for LoadCrashListAsynchronously().
-  void LoadCrashListAndInformDelegateOfCompletion();
-
-  // Calls the delegate's callback method, if there is a delegate.
-  void InformDelegateOfCompletion();
-
-  // Parses crash log lines, converting them to CrashInfo entries.
-  void ParseLogEntries(const std::vector<std::string>& log_entries);
-
-  std::vector<CrashInfo> crashes_;
-  Delegate* delegate_;
-
   DISALLOW_COPY_AND_ASSIGN(CrashUploadList);
 };
 
diff --git a/chrome/browser/crash_upload_list_win.cc b/chrome/browser/crash_upload_list_win.cc
index e0130ac..418cbcb 100644
--- a/chrome/browser/crash_upload_list_win.cc
+++ b/chrome/browser/crash_upload_list_win.cc
@@ -8,10 +8,11 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/sys_string_conversions.h"
 
-CrashUploadListWin::CrashUploadListWin(Delegate* delegate)
-    : CrashUploadList(delegate) {}
+CrashUploadListWin::CrashUploadListWin(Delegate* delegate,
+                                       const base::FilePath& upload_log_path)
+    : CrashUploadList(delegate, upload_log_path) {}
 
-void CrashUploadListWin::LoadCrashList() {
+void CrashUploadListWin::LoadUploadList() {
   std::vector<uint8> buffer(1024);
   HANDLE event_log = OpenEventLog(NULL, L"Application");
   if (event_log) {
@@ -72,9 +73,9 @@
     if (end_index != std::wstring::npos) {
       std::wstring crash_id =
           message.substr(start_index, end_index - start_index);
-      crashes().push_back(
-          CrashInfo(base::SysWideToUTF8(crash_id),
-                    base::Time::FromDoubleT(record->TimeGenerated)));
+      AppendUploadInfo(
+          UploadInfo(base::SysWideToUTF8(crash_id),
+                     base::Time::FromDoubleT(record->TimeGenerated)));
     }
   }
 }
diff --git a/chrome/browser/crash_upload_list_win.h b/chrome/browser/crash_upload_list_win.h
index c42365f..fd93e22 100644
--- a/chrome/browser/crash_upload_list_win.h
+++ b/chrome/browser/crash_upload_list_win.h
@@ -12,11 +12,11 @@
 // from the Windows Event Log.
 class CrashUploadListWin : public CrashUploadList {
  public:
-  explicit CrashUploadListWin(Delegate* delegate);
+  CrashUploadListWin(Delegate* delegate, const base::FilePath& upload_log_path);
 
  protected:
   // Loads the list of crashes from the Windows Event Log.
-  virtual void LoadCrashList() OVERRIDE;
+  virtual void LoadUploadList() OVERRIDE;
 
  private:
   // Returns whether the event record is likely a Chrome crash log.
diff --git a/chrome/browser/custom_home_pages_table_model.cc b/chrome/browser/custom_home_pages_table_model.cc
index 0af2677..2460717 100644
--- a/chrome/browser/custom_home_pages_table_model.cc
+++ b/chrome/browser/custom_home_pages_table_model.cc
@@ -18,13 +18,13 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
 #include "content/public/browser/web_contents.h"
-#include "googleurl/src/gurl.h"
 #include "grit/generated_resources.h"
 #include "grit/ui_resources.h"
 #include "net/base/net_util.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/models/table_model_observer.h"
 #include "ui/gfx/codec/png_codec.h"
+#include "url/gurl.h"
 
 namespace {
 
diff --git a/chrome/browser/devtools/adb/android_usb_device.cc b/chrome/browser/devtools/adb/android_usb_device.cc
new file mode 100644
index 0000000..c77fd4e
--- /dev/null
+++ b/chrome/browser/devtools/adb/android_usb_device.cc
@@ -0,0 +1,403 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/devtools/adb/android_usb_device.h"
+
+#include "base/base64.h"
+#include "base/message_loop/message_loop.h"
+#include "base/strings/stringprintf.h"
+#include "chrome/browser/devtools/adb/android_usb_socket.h"
+#include "chrome/browser/usb/usb_interface.h"
+#include "chrome/browser/usb/usb_service.h"
+#include "chrome/browser/usb/usb_service_factory.h"
+#include "net/base/ip_endpoint.h"
+#include "net/base/net_errors.h"
+#include "net/socket/stream_socket.h"
+
+namespace {
+
+void Noop() {}
+void BoolNoop(bool success) {}
+
+const size_t kHeaderSize = 24;
+
+const int kAdbClass = 0xff;
+const int kAdbSubclass = 0x42;
+const int kAdbProtocol = 0x1;
+
+const int kUsbTimeout = 1000;
+
+const uint32 kMaxPayload = 4096;
+const uint32 kVersion = 0x01000000;
+
+static const char kHostConnectMessage[] = "host::";
+static const char kRSAPublicKey[] =
+    "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6OSJ64q+ZLg7VV2ojEPh5TRbYjwbT"
+    "TifSPeFIV45CHnbTWYiiIn41wrozpYizNsMWZUBjdah1N78WVhbyDrnr0bDgFp+gXjfVppa3I"
+    "gjiohEcemK3omXi3GDMK8ERhriLUKfQS842SXtQ8I+KoZtpCkGM//0h7+P+Rhm0WwdipIRMhR"
+    "8haNAeyDiiCvqJcvevv2T52vqKtS3aWz+GjaTJJLVWydEpz9WdvWeLfFVhe2ZnqwwZNa30Qoj"
+    "fsnvjaMwK2MU7uYfRBPuvLyK5QESWBpArNDd6ULl8Y+NU6kwNOVDc87OASCVEM1gw2IMi2mo2"
+    "WO5ywp0UWRiGZCkK+wOFQIDAQAB";
+
+static bool CheckUsbInterface(
+    const UsbInterface* interface,
+    int* inbound_address,
+    int* outbound_address,
+    int* zero_mask) {
+  if (interface->GetNumAltSettings() == 0)
+    return false;
+
+  scoped_refptr<const UsbInterfaceDescriptor> idesc =
+      interface->GetAltSetting(0).get();
+
+  if (idesc->GetInterfaceClass() != kAdbClass ||
+      idesc->GetInterfaceSubclass() != kAdbSubclass ||
+      idesc->GetInterfaceProtocol() != kAdbProtocol ||
+      idesc->GetNumEndpoints() != 2) {
+    return false;
+  }
+
+  for (size_t i = 0; i < idesc->GetNumEndpoints(); ++i) {
+    scoped_refptr<const UsbEndpointDescriptor> edesc =
+        idesc->GetEndpoint(i).get();
+    if (edesc->GetTransferType() != USB_TRANSFER_BULK)
+      continue;
+    if (edesc->GetDirection() == USB_DIRECTION_INBOUND)
+      *inbound_address = edesc->GetAddress();
+    else
+      *outbound_address = edesc->GetAddress();
+    *zero_mask = edesc->GetMaximumPacketSize() - 1;
+  }
+
+  if (inbound_address == 0 || outbound_address == 0)
+    return false;
+  return true;
+}
+
+static uint32 Checksum(const std::string& data) {
+  unsigned char* x = (unsigned char*)data.data();
+  int count = data.length();
+  uint32 sum = 0;
+  while (count-- > 0)
+    sum += *x++;
+  return sum;
+}
+
+static void DumpMessage(bool outgoing, const char* data, size_t length) {
+#if 0
+  std::string result = "";
+  if (length == kHeaderSize) {
+    for (size_t i = 0; i < 24; ++i) {
+      result += base::StringPrintf("%02x",
+          data[i] > 0 ? data[i] : (data[i] + 0x100) & 0xFF);
+      if ((i + 1) % 4 == 0)
+        result += " ";
+    }
+    for (size_t i = 0; i < 24; ++i) {
+      if (data[i] >= 0x20 && data[i] <= 0x7E)
+        result += data[i];
+      else
+        result += ".";
+    }
+  } else {
+    result = base::StringPrintf("%d: ", (int)length);
+    for (size_t i = 0; i < length; ++i) {
+      if (data[i] >= 0x20 && data[i] <= 0x7E)
+        result += data[i];
+      else
+        result += ".";
+    }
+  }
+  LOG(ERROR) << (outgoing ? "[out] " : "[ in] ") << result;
+#endif  // 0
+}
+
+}  // namespace
+
+AdbMessage::AdbMessage(uint32 command,
+                       uint32 arg0,
+                       uint32 arg1,
+                       const std::string& body)
+    : command(command),
+      arg0(arg0),
+      arg1(arg1),
+      body(body) {
+}
+
+AdbMessage::~AdbMessage() {
+}
+
+// static
+void AndroidUsbDevice::Enumerate(
+    Profile* profile,
+    std::vector<scoped_refptr<AndroidUsbDevice> >* devices) {
+  UsbService* service =
+      UsbServiceFactory::GetInstance()->GetForProfile(profile);
+
+  // Enumerate usb devices.
+  std::vector<scoped_refptr<UsbDevice> > usb_devices;
+  service->EnumerateDevices(&usb_devices);
+  for (size_t i = 0; i < usb_devices.size(); ++i) {
+    scoped_refptr<UsbDevice> usb_device = usb_devices[i];
+
+    // Enumerate device interfaces.
+    scoped_refptr<UsbConfigDescriptor> config = new UsbConfigDescriptor();
+    usb_device->ListInterfaces(config.get(), base::Bind(&BoolNoop));
+    for (size_t i = 0; i < config->GetNumInterfaces(); ++i) {
+      scoped_refptr<const UsbInterface> interface = config->GetInterface(i);
+
+      int inbound_address = 0;
+      int outbound_address = 0;
+      int zero_mask = 0;
+      if (CheckUsbInterface(interface, &inbound_address, &outbound_address,
+                            &zero_mask)) {
+        devices->push_back(new AndroidUsbDevice(usb_device, inbound_address,
+                                                outbound_address, zero_mask));
+      }
+    }
+  }
+}
+
+AndroidUsbDevice::AndroidUsbDevice(scoped_refptr<UsbDevice> usb_device,
+                                   int inbound_address,
+                                   int outbound_address,
+                                   int zero_mask)
+    : message_loop_(NULL),
+      usb_device_(usb_device),
+      inbound_address_(inbound_address),
+      outbound_address_(outbound_address),
+      zero_mask_(zero_mask),
+      is_connected_(false),
+      last_socket_id_(256) {
+  message_loop_ = base::MessageLoop::current();
+  usb_device_->ClaimInterface(1, base::Bind(&AndroidUsbDevice::InterfaceClaimed,
+                                            this));
+}
+
+net::StreamSocket* AndroidUsbDevice::CreateSocket(const std::string& command) {
+  uint32 socket_id = ++last_socket_id_;
+  sockets_[socket_id] = new AndroidUsbSocket(this, socket_id, command,
+      base::Bind(&AndroidUsbDevice::SocketDeleted, this));
+  return sockets_[socket_id];
+}
+
+void AndroidUsbDevice::Send(uint32 command,
+                            uint32 arg0,
+                            uint32 arg1,
+                            const std::string& body) {
+  scoped_refptr<AdbMessage> m = new AdbMessage(command, arg0, arg1, body);
+  // Delay open request if not yet connected.
+  if (!is_connected_) {
+    pending_messages_.push_back(m);
+    return;
+  }
+  Queue(m);
+}
+
+AndroidUsbDevice::~AndroidUsbDevice() {
+  usb_device_->ReleaseInterface(1, base::Bind(&BoolNoop));
+  usb_device_->Close(base::Bind(&Noop));
+}
+
+void AndroidUsbDevice::InterfaceClaimed(bool success) {
+  if (!success)
+    return;
+  Queue(new AdbMessage(AdbMessage::kCommandCNXN, kVersion, kMaxPayload,
+                       kHostConnectMessage));
+  ReadHeader();
+}
+
+void AndroidUsbDevice::Queue(scoped_refptr<AdbMessage> message) {
+  // Queue header.
+  std::vector<uint32> header;
+  header.push_back(message->command);
+  header.push_back(message->arg0);
+  header.push_back(message->arg1);
+  bool append_zero = true;
+  if (message->body.empty())
+    append_zero = false;
+  if (message->command == AdbMessage::kCommandAUTH &&
+      message->arg0 == AdbMessage::kAuthSignature)
+    append_zero = false;
+  if (message->command == AdbMessage::kCommandWRTE)
+    append_zero = false;
+
+  size_t body_length = message->body.length() + (append_zero ? 1 : 0);
+  header.push_back(body_length);
+  header.push_back(Checksum(message->body));
+  header.push_back(message->command ^ 0xffffffff);
+  scoped_refptr<net::IOBuffer> header_buffer = new net::IOBuffer(kHeaderSize);
+  memcpy(header_buffer.get()->data(), &header[0], kHeaderSize);
+  outgoing_queue_.push(std::make_pair(header_buffer, kHeaderSize));
+
+  // Queue body.
+  if (!message->body.empty()) {
+    scoped_refptr<net::IOBuffer> body_buffer = new net::IOBuffer(body_length);
+    memcpy(body_buffer->data(), message->body.data(), message->body.length());
+    if (append_zero)
+      body_buffer->data()[body_length - 1] = 0;
+    outgoing_queue_.push(std::make_pair(body_buffer, body_length));
+  }
+  ProcessOutgoing();
+}
+
+void AndroidUsbDevice::ProcessOutgoing() {
+  if (outgoing_queue_.empty())
+    return;
+
+  BulkMessage message = outgoing_queue_.front();
+  outgoing_queue_.pop();
+  DumpMessage(true, message.first->data(), message.second);
+  usb_device_->BulkTransfer(USB_DIRECTION_OUTBOUND, outbound_address_,
+      message.first, message.second, kUsbTimeout,
+      base::Bind(&AndroidUsbDevice::OutgoingMessageSent, this));
+}
+
+void AndroidUsbDevice::OutgoingMessageSent(UsbTransferStatus status,
+                                           scoped_refptr<net::IOBuffer> buffer,
+                                           size_t result) {
+  if (status != USB_TRANSFER_COMPLETED)
+    return;
+  message_loop_->PostTask(FROM_HERE,
+                          base::Bind(&AndroidUsbDevice::ProcessOutgoing,
+                                     this));
+}
+
+void AndroidUsbDevice::ReadHeader() {
+  if (HasOneRef())
+    return;  // Stop polling.
+  scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kHeaderSize);
+  usb_device_->BulkTransfer(USB_DIRECTION_INBOUND, inbound_address_,
+      buffer, kHeaderSize, kUsbTimeout,
+      base::Bind(&AndroidUsbDevice::ParseHeader, this));
+}
+
+void AndroidUsbDevice::ParseHeader(UsbTransferStatus status,
+                                   scoped_refptr<net::IOBuffer> buffer,
+                                   size_t result) {
+  if (status == USB_TRANSFER_TIMEOUT) {
+    message_loop_->PostTask(FROM_HERE,
+                            base::Bind(&AndroidUsbDevice::ReadHeader, this));
+    return;
+  }
+
+  if (status != USB_TRANSFER_COMPLETED) {
+    LOG(ERROR) << "Unexpeced transfer status: " << status;
+    return;
+  }
+
+  if (result != kHeaderSize) {
+    LOG(ERROR) << "Unexpeced header size: " << result;
+    return;
+  }
+
+  DumpMessage(false, buffer->data(), result);
+  std::vector<uint32> header(6);
+  memcpy(&header[0], buffer->data(), result);
+  scoped_refptr<AdbMessage> message =
+      new AdbMessage(header[0], header[1], header[2], "");
+  uint32 data_length = header[3];
+  uint32 data_check = header[4];
+  uint32 magic = header[5];
+  if ((message->command ^ 0xffffffff) != magic)
+    return;
+
+  if (data_length == 0) {
+    message_loop_->PostTask(FROM_HERE,
+                            base::Bind(&AndroidUsbDevice::HandleIncoming, this,
+                                       message));
+    return;
+  }
+
+  message_loop_->PostTask(FROM_HERE,
+                          base::Bind(&AndroidUsbDevice::ReadBody, this,
+                                     message, data_length, data_check));
+}
+
+void AndroidUsbDevice::ReadBody(scoped_refptr<AdbMessage> message,
+                                uint32 data_length,
+                                uint32 data_check) {
+  scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(data_length);
+  usb_device_->BulkTransfer(USB_DIRECTION_INBOUND, inbound_address_,
+      buffer, data_length, kUsbTimeout,
+      base::Bind(&AndroidUsbDevice::ParseBody, this, message, data_length,
+                 data_check));
+}
+
+void AndroidUsbDevice::ParseBody(scoped_refptr<AdbMessage> message,
+                                 uint32 data_length,
+                                 uint32 data_check,
+                                 UsbTransferStatus status,
+                                 scoped_refptr<net::IOBuffer> buffer,
+                                 size_t result) {
+  if (status == USB_TRANSFER_TIMEOUT) {
+    message_loop_->PostTask(FROM_HERE,
+                            base::Bind(&AndroidUsbDevice::ReadBody, this,
+                            message, data_length, data_check));
+    return;
+  }
+
+  if (status != USB_TRANSFER_COMPLETED) {
+    LOG(ERROR) << "Unexpeced transfer status: " << status;
+    return;
+  }
+
+  if (static_cast<uint32>(result) != data_length) {
+    LOG(ERROR) << "Unexpeced body length: " << result << ", expecteced" <<
+        data_length;
+    return;
+  }
+
+  DumpMessage(false, buffer->data(), data_length);
+  message->body = std::string(buffer->data(), result);
+  if (Checksum(message->body) != data_check) {
+    LOG(ERROR) << "Wrong body checksum";
+    return;
+  }
+
+  message_loop_->PostTask(FROM_HERE,
+                          base::Bind(&AndroidUsbDevice::HandleIncoming, this,
+                                     message));
+}
+
+void AndroidUsbDevice::HandleIncoming(scoped_refptr<AdbMessage> message) {
+  switch (message->command) {
+    case AdbMessage::kCommandAUTH:
+      {
+        DCHECK_EQ(message->arg0, static_cast<uint32>(AdbMessage::kAuthToken));
+        Queue(new AdbMessage(AdbMessage::kCommandAUTH,
+                             AdbMessage::kAuthRSAPublicKey, 0,
+                             kRSAPublicKey));
+      }
+      break;
+    case AdbMessage::kCommandCNXN:
+      {
+        is_connected_ = true;
+        PendingMessages pending;
+        pending.swap(pending_messages_);
+        for (PendingMessages::iterator it = pending.begin();
+             it != pending.end(); ++it) {
+          Queue(*it);
+        }
+      }
+      break;
+    case AdbMessage::kCommandOKAY:
+    case AdbMessage::kCommandWRTE:
+    case AdbMessage::kCommandCLSE:
+      {
+        // Route these to sockets
+        AndroidUsbSockets::iterator it = sockets_.find(message->arg1);
+        if (it != sockets_.end())
+          it->second->HandleIncoming(message);
+      }
+      break;
+    default:
+      break;
+  }
+  ReadHeader();
+}
+
+void AndroidUsbDevice::SocketDeleted(uint32 socket_id) {
+  sockets_.erase(socket_id);
+}
diff --git a/chrome/browser/devtools/adb/android_usb_device.h b/chrome/browser/devtools/adb/android_usb_device.h
new file mode 100644
index 0000000..4b27a13
--- /dev/null
+++ b/chrome/browser/devtools/adb/android_usb_device.h
@@ -0,0 +1,135 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_DEVTOOLS_ADB_ANDROID_USB_DEVICE_H_
+#define CHROME_BROWSER_DEVTOOLS_ADB_ANDROID_USB_DEVICE_H_
+
+#include <map>
+#include <queue>
+#include <vector>
+#include "base/memory/ref_counted.h"
+#include "chrome/browser/usb/usb_device.h"
+
+namespace base {
+class MessageLoop;
+}
+
+namespace net {
+class StreamSocket;
+}
+
+class AndroidUsbSocket;
+class Profile;
+
+class AdbMessage : public base::RefCounted<AdbMessage> {
+ public:
+  enum Command {
+    kCommandSYNC = 0x434e5953,
+    kCommandCNXN = 0x4e584e43,
+    kCommandOPEN = 0x4e45504f,
+    kCommandOKAY = 0x59414b4f,
+    kCommandCLSE = 0x45534c43,
+    kCommandWRTE = 0x45545257,
+    kCommandAUTH = 0x48545541
+  };
+
+  enum Auth {
+    kAuthToken = 1,
+    kAuthSignature = 2,
+    kAuthRSAPublicKey = 3
+  };
+
+  AdbMessage(uint32 command,
+             uint32 arg0,
+             uint32 arg1,
+             const std::string& body);
+
+  uint32 command;
+  uint32 arg0;
+  uint32 arg1;
+  std::string body;
+ private:
+  friend class base::RefCounted<AdbMessage>;
+  ~AdbMessage();
+
+  DISALLOW_COPY_AND_ASSIGN(AdbMessage);
+};
+
+typedef base::Callback<void(int, AdbMessage*)> AdbCallback;
+
+class AndroidUsbDevice : public base::RefCountedThreadSafe<AndroidUsbDevice> {
+ public:
+  static void Enumerate(
+      Profile* profile,
+      std::vector<scoped_refptr<AndroidUsbDevice> >* devices);
+  AndroidUsbDevice(scoped_refptr<UsbDevice> device,
+                   int inbound_address,
+                   int outbound_address,
+                   int zero_mask);
+
+  net::StreamSocket* CreateSocket(const std::string& command);
+
+  void Send(uint32 command,
+            uint32 arg0,
+            uint32 arg1,
+            const std::string& body);
+
+ private:
+  friend class base::RefCountedThreadSafe<AndroidUsbDevice>;
+  virtual ~AndroidUsbDevice();
+
+  void InterfaceClaimed(bool success);
+
+  void Queue(scoped_refptr<AdbMessage> message);
+  void ProcessOutgoing();
+  void OutgoingMessageSent(UsbTransferStatus status,
+                           scoped_refptr<net::IOBuffer> buffer,
+                           size_t result);
+
+  void ReadHeader();
+  void ParseHeader(UsbTransferStatus status,
+                   scoped_refptr<net::IOBuffer> buffer,
+                   size_t result);
+
+  void ReadBody(scoped_refptr<AdbMessage> message,
+                uint32 data_length,
+                uint32 data_check);
+  void ParseBody(scoped_refptr<AdbMessage> message,
+                 uint32 data_length,
+                 uint32 data_check,
+                 UsbTransferStatus status,
+                 scoped_refptr<net::IOBuffer> buffer,
+                 size_t result);
+
+  void HandleIncoming(scoped_refptr<AdbMessage> message);
+
+  void SocketDeleted(uint32 socket_id);
+
+  base::MessageLoop* message_loop_;
+
+  // Device info
+  scoped_refptr<UsbDevice> usb_device_;
+  int inbound_address_;
+  int outbound_address_;
+  int zero_mask_;
+
+  bool is_connected_;
+
+  // Created sockets info
+  uint32 last_socket_id_;
+  typedef std::map<uint32, AndroidUsbSocket*> AndroidUsbSockets;
+  AndroidUsbSockets sockets_;
+
+  // Outgoing bulk queue
+  typedef std::pair<scoped_refptr<net::IOBuffer>, size_t> BulkMessage;
+  std::queue<BulkMessage> outgoing_queue_;
+
+  // Outgoing messages pending connect
+  typedef std::vector<scoped_refptr<AdbMessage> > PendingMessages;
+  PendingMessages pending_messages_;
+
+  DISALLOW_COPY_AND_ASSIGN(AndroidUsbDevice);
+};
+
+#endif  // CHROME_BROWSER_DEVTOOLS_ADB_ANDROID_USB_DEVICE_H_
diff --git a/chrome/browser/devtools/adb/android_usb_socket.cc b/chrome/browser/devtools/adb/android_usb_socket.cc
new file mode 100644
index 0000000..2baefe1
--- /dev/null
+++ b/chrome/browser/devtools/adb/android_usb_socket.cc
@@ -0,0 +1,219 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/devtools/adb/android_usb_socket.h"
+
+#include "base/message_loop/message_loop.h"
+
+namespace {
+
+const int kMaxPayload = 4096;
+
+}  // namespace
+
+AndroidUsbSocket::IORequest::IORequest(
+    net::IOBuffer* buffer,
+    int length,
+    const net::CompletionCallback& callback)
+    : buffer(buffer),
+      length(length),
+      callback(callback) {
+}
+
+AndroidUsbSocket::IORequest::~IORequest() {
+}
+
+AndroidUsbSocket::AndroidUsbSocket(scoped_refptr<AndroidUsbDevice> device,
+                                   uint32 socket_id,
+                                   const std::string& command,
+                                   base::Callback<void(uint32)> delete_callback)
+    : message_loop_(base::MessageLoop::current()),
+      device_(device),
+      command_(command),
+      delete_callback_(delete_callback),
+      local_id_(socket_id),
+      remote_id_(0),
+      is_connected_(false) {
+}
+
+AndroidUsbSocket::~AndroidUsbSocket() {
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
+  if (is_connected_)
+    Disconnect();
+  delete_callback_.Run(local_id_);
+}
+
+void AndroidUsbSocket::HandleIncoming(scoped_refptr<AdbMessage> message) {
+  CHECK_EQ(message->arg1, local_id_);
+  switch (message->command) {
+    case AdbMessage::kCommandOKAY:
+      if (!is_connected_) {
+        remote_id_ = message->arg0;
+        is_connected_ = true;
+        connect_callback_.Run(net::OK);
+        // Can be NULL after response.
+      } else {
+        RespondToWriters();
+        // Can be NULL after response.
+      }
+      break;
+    case AdbMessage::kCommandWRTE:
+      read_buffer_ += message->body;
+      device_->Send(AdbMessage::kCommandOKAY, local_id_, remote_id_, "");
+      RespondToReaders(false);
+      // Can be NULL after response.
+      break;
+    case AdbMessage::kCommandCLSE:
+      if (is_connected_) {
+        device_->Send(AdbMessage::kCommandCLSE, local_id_, 0, "");
+      }
+      is_connected_ = false;
+      RespondToReaders(true);
+      // Can be NULL after response.
+      break;
+    default:
+      break;
+  }
+}
+
+int AndroidUsbSocket::Read(net::IOBuffer* buffer,
+                           int length,
+                           const net::CompletionCallback& callback) {
+  if (!is_connected_)
+    return net::ERR_SOCKET_NOT_CONNECTED;
+
+  if (read_buffer_.empty()) {
+    read_requests_.push_back(IORequest(buffer, length, callback));
+    return net::ERR_IO_PENDING;
+  }
+
+  size_t bytes_to_copy = static_cast<size_t>(length) > read_buffer_.length() ?
+      read_buffer_.length() : static_cast<size_t>(length);
+  memcpy(buffer->data(), read_buffer_.data(), bytes_to_copy);
+  if (read_buffer_.length() > bytes_to_copy)
+    read_buffer_ = read_buffer_.substr(bytes_to_copy);
+  else
+    read_buffer_ = "";
+  return net::OK;
+}
+
+int AndroidUsbSocket::Write(net::IOBuffer* buffer,
+                            int length,
+                            const net::CompletionCallback& callback) {
+  if (!is_connected_)
+    return net::ERR_SOCKET_NOT_CONNECTED;
+
+  if (length > kMaxPayload)
+    length = kMaxPayload;
+  write_requests_.push_back(IORequest(NULL, length, callback));
+  device_->Send(AdbMessage::kCommandWRTE, local_id_, remote_id_,
+                 std::string(buffer->data(), length));
+  return net::ERR_IO_PENDING;
+}
+
+bool AndroidUsbSocket::SetReceiveBufferSize(int32 size) {
+  NOTIMPLEMENTED();
+  return false;
+}
+
+bool AndroidUsbSocket::SetSendBufferSize(int32 size) {
+  NOTIMPLEMENTED();
+  return false;
+}
+
+int AndroidUsbSocket::Connect(const net::CompletionCallback& callback) {
+  CHECK_EQ(message_loop_, base::MessageLoop::current());
+  connect_callback_ = callback;
+  device_->Send(AdbMessage::kCommandOPEN, local_id_, 0, command_);
+  return net::ERR_IO_PENDING;
+}
+
+void AndroidUsbSocket::Disconnect() {
+  is_connected_ = false;
+  device_->Send(AdbMessage::kCommandCLSE, local_id_, remote_id_, "");
+  RespondToReaders(true);
+}
+
+bool AndroidUsbSocket::IsConnected() const {
+  CHECK_EQ(message_loop_, base::MessageLoop::current());
+  return is_connected_;
+}
+
+bool AndroidUsbSocket::IsConnectedAndIdle() const {
+  NOTIMPLEMENTED();
+  return false;
+}
+
+int AndroidUsbSocket::GetPeerAddress(net::IPEndPoint* address) const {
+  net::IPAddressNumber ip(net::kIPv4AddressSize);
+  *address = net::IPEndPoint(ip, 0);
+  return net::OK;
+}
+
+int AndroidUsbSocket::GetLocalAddress(net::IPEndPoint* address) const {
+  NOTIMPLEMENTED();
+  return net::ERR_FAILED;
+}
+
+const net::BoundNetLog& AndroidUsbSocket::NetLog() const {
+  return net_log_;
+}
+
+void AndroidUsbSocket::SetSubresourceSpeculation() {
+  NOTIMPLEMENTED();
+}
+
+void AndroidUsbSocket::SetOmniboxSpeculation() {
+  NOTIMPLEMENTED();
+}
+
+bool AndroidUsbSocket::WasEverUsed() const {
+  NOTIMPLEMENTED();
+  return true;
+}
+
+bool AndroidUsbSocket::UsingTCPFastOpen() const {
+  NOTIMPLEMENTED();
+  return true;
+}
+
+bool AndroidUsbSocket::WasNpnNegotiated() const {
+  NOTIMPLEMENTED();
+  return true;
+}
+
+net::NextProto AndroidUsbSocket::GetNegotiatedProtocol() const {
+  NOTIMPLEMENTED();
+  return net::kProtoUnknown;
+}
+
+bool AndroidUsbSocket::GetSSLInfo(net::SSLInfo* ssl_info) {
+  return false;
+}
+
+void AndroidUsbSocket::RespondToReaders(bool disconnect) {
+  std::deque<IORequest> read_requests;
+  read_requests.swap(read_requests_);
+  while (!read_requests.empty() && (!read_buffer_.empty() || disconnect)) {
+    IORequest read_request = read_requests.front();
+    read_requests.pop_front();
+    size_t bytes_to_copy =
+        static_cast<size_t>(read_request.length) > read_buffer_.length() ?
+            read_buffer_.length() : static_cast<size_t>(read_request.length);
+    memcpy(read_request.buffer->data(), read_buffer_.data(), bytes_to_copy);
+    if (read_buffer_.length() > bytes_to_copy)
+      read_buffer_ = read_buffer_.substr(bytes_to_copy);
+    else
+      read_buffer_ = "";
+    read_request.callback.Run(bytes_to_copy);
+  }
+}
+
+void AndroidUsbSocket::RespondToWriters() {
+  if (!write_requests_.empty()) {
+    IORequest write_request = write_requests_.front();
+    write_requests_.pop_front();
+    write_request.callback.Run(write_request.length);
+  }
+}
diff --git a/chrome/browser/devtools/adb/android_usb_socket.h b/chrome/browser/devtools/adb/android_usb_socket.h
new file mode 100644
index 0000000..d6367f8
--- /dev/null
+++ b/chrome/browser/devtools/adb/android_usb_socket.h
@@ -0,0 +1,86 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_DEVTOOLS_ADB_ANDROID_USB_SOCKET_H_
+#define CHROME_BROWSER_DEVTOOLS_ADB_ANDROID_USB_SOCKET_H_
+
+#include <deque>
+
+#include "base/memory/ref_counted.h"
+#include "chrome/browser/devtools/adb/android_usb_device.h"
+#include "net/base/ip_endpoint.h"
+#include "net/base/net_errors.h"
+#include "net/socket/stream_socket.h"
+
+namespace base {
+class MessageLoop;
+}
+
+class AdbMessage;
+
+class AndroidUsbSocket : public net::StreamSocket {
+ public:
+  AndroidUsbSocket(scoped_refptr<AndroidUsbDevice> device,
+                   uint32 socket_id,
+                   const std::string& command,
+                   base::Callback<void(uint32)> delete_callback);
+  virtual ~AndroidUsbSocket();
+
+  void HandleIncoming(scoped_refptr<AdbMessage> message);
+
+  // net::StreamSocket implementation.
+  virtual int Read(net::IOBuffer* buf, int buf_len,
+                   const net::CompletionCallback& callback) OVERRIDE;
+  virtual int Write(net::IOBuffer* buf, int buf_len,
+                    const net::CompletionCallback& callback) OVERRIDE;
+  virtual bool SetReceiveBufferSize(int32 size) OVERRIDE;
+  virtual bool SetSendBufferSize(int32 size) OVERRIDE;
+  virtual int Connect(const net::CompletionCallback& callback) OVERRIDE;
+  virtual void Disconnect() OVERRIDE;
+  virtual bool IsConnected() const OVERRIDE;
+  virtual bool IsConnectedAndIdle() const OVERRIDE;
+  virtual int GetPeerAddress(net::IPEndPoint* address) const OVERRIDE;
+  virtual int GetLocalAddress(net::IPEndPoint* address) const OVERRIDE;
+  virtual const net::BoundNetLog& NetLog() const OVERRIDE;
+  virtual void SetSubresourceSpeculation() OVERRIDE;
+  virtual void SetOmniboxSpeculation() OVERRIDE;
+  virtual bool WasEverUsed() const OVERRIDE;
+  virtual bool UsingTCPFastOpen() const OVERRIDE;
+  virtual bool WasNpnNegotiated() const OVERRIDE;
+  virtual net::NextProto GetNegotiatedProtocol() const OVERRIDE;
+  virtual bool GetSSLInfo(net::SSLInfo* ssl_info) OVERRIDE;
+
+ private:
+  class IORequest {
+   public:
+    IORequest(net::IOBuffer* buffer,
+              int length,
+              const net::CompletionCallback& callback);
+    ~IORequest();
+
+    scoped_refptr<net::IOBuffer> buffer;
+    int length;
+    net::CompletionCallback callback;
+  };
+
+  void RespondToReaders(bool diconnect);
+  void RespondToWriters();
+
+  base::MessageLoop* message_loop_;
+  scoped_refptr<AndroidUsbDevice> device_;
+  std::string command_;
+  base::Callback<void(uint32)> delete_callback_;
+  uint32 local_id_;
+  uint32 remote_id_;
+  net::BoundNetLog net_log_;
+  bool is_connected_;
+  std::string read_buffer_;
+  net::CompletionCallback connect_callback_;
+  std::deque<IORequest> read_requests_;
+  std::deque<IORequest> write_requests_;
+
+  DISALLOW_COPY_AND_ASSIGN(AndroidUsbSocket);
+};
+
+#endif  // CHROME_BROWSER_DEVTOOLS_ADB_ANDROID_USB_SOCKET_H_
diff --git a/chrome/browser/devtools/devtools_adb_bridge.cc b/chrome/browser/devtools/devtools_adb_bridge.cc
index fb006f1..c903b5a 100644
--- a/chrome/browser/devtools/devtools_adb_bridge.cc
+++ b/chrome/browser/devtools/devtools_adb_bridge.cc
@@ -38,7 +38,6 @@
 namespace {
 
 static const char kDevToolsAdbBridgeThreadName[] = "Chrome_DevToolsADBThread";
-static const char kDevToolsChannelPattern[] = "devtools_remote";
 static const char kHostDevicesCommand[] = "host:devices";
 static const char kDeviceModelCommand[] =
     "host:transport:%s|shell:getprop ro.product.model";
@@ -274,7 +273,8 @@
     socket_to_package_.clear();
     std::vector<std::string> entries;
     Tokenize(response, "\n", &entries);
-    const std::string channel_pattern = kDevToolsChannelPattern;
+    const std::string channel_pattern =
+        base::StringPrintf(kDevToolsChannelNameFormat, "");
     for (size_t i = 1; i < entries.size(); ++i) {
       std::vector<std::string> fields;
       Tokenize(entries[i], " ", &fields);
@@ -309,6 +309,8 @@
 
 }  // namespace
 
+const char kDevToolsChannelNameFormat[] = "%s_devtools_remote";
+
 class AgentHostDelegate;
 
 typedef std::map<std::string, AgentHostDelegate*> AgentHostDelegates;
diff --git a/chrome/browser/devtools/devtools_adb_bridge.h b/chrome/browser/devtools/devtools_adb_bridge.h
index e2ef879..a828cb1 100644
--- a/chrome/browser/devtools/devtools_adb_bridge.h
+++ b/chrome/browser/devtools/devtools_adb_bridge.h
@@ -22,6 +22,9 @@
 
 class Profile;
 
+// The format used for constructing DevTools server socket names.
+extern const char kDevToolsChannelNameFormat[];
+
 class DevToolsAdbBridge {
  public:
   typedef base::Callback<void(int result,
diff --git a/chrome/browser/devtools/devtools_sanity_browsertest.cc b/chrome/browser/devtools/devtools_sanity_browsertest.cc
index 40a2c38..aba2865 100644
--- a/chrome/browser/devtools/devtools_sanity_browsertest.cc
+++ b/chrome/browser/devtools/devtools_sanity_browsertest.cc
@@ -552,9 +552,15 @@
   ASSERT_EQ(GetInspectedTab()->GetURL(), url);
 }
 
+#if defined(OS_WIN)
+// Flakily times out: http://crbug.com/163411
+#define MAYBE_TestReattachAfterCrash DISABLED_TestReattachAfterCrash
+#else
+#define MAYBE_TestReattachAfterCrash TestReattachAfterCrash
+#endif
 // Tests that inspector will reattach to inspected page when it is reloaded
 // after a crash. See http://crbug.com/101952
-IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestReattachAfterCrash) {
+IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, MAYBE_TestReattachAfterCrash) {
   OpenDevToolsWindow(kDebuggerTestPage);
 
   content::CrashTab(GetInspectedTab());
diff --git a/chrome/browser/diagnostics/OWNERS b/chrome/browser/diagnostics/OWNERS
index 3aae3d6..4478b09 100644
--- a/chrome/browser/diagnostics/OWNERS
+++ b/chrome/browser/diagnostics/OWNERS
@@ -1 +1,2 @@
 cpu@chromium.org
+gspencer@chromium.org
diff --git a/chrome/browser/diagnostics/diagnostics_main.cc b/chrome/browser/diagnostics/diagnostics_main.cc
index cd9530b..7d02a23 100644
--- a/chrome/browser/diagnostics/diagnostics_main.cc
+++ b/chrome/browser/diagnostics/diagnostics_main.cc
@@ -20,7 +20,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/diagnostics/diagnostics_model.h"
 #include "chrome/common/chrome_paths.h"
 #include "ui/base/resource/resource_bundle.h"
diff --git a/chrome/browser/diagnostics/recon_diagnostics.cc b/chrome/browser/diagnostics/recon_diagnostics.cc
index b4be36b..b66fd03 100644
--- a/chrome/browser/diagnostics/recon_diagnostics.cc
+++ b/chrome/browser/diagnostics/recon_diagnostics.cc
@@ -243,7 +243,7 @@
 
     int64 dir_or_file_size = 0;
     if (path_info_.is_directory) {
-      dir_or_file_size = file_util::ComputeDirectorySize(dir_or_file);
+      dir_or_file_size = base::ComputeDirectorySize(dir_or_file);
     } else {
       file_util::GetFileSize(dir_or_file, &dir_or_file_size);
     }
diff --git a/chrome/browser/download/chrome_download_manager_delegate.cc b/chrome/browser/download/chrome_download_manager_delegate.cc
index f894dc0..2274fb7 100644
--- a/chrome/browser/download/chrome_download_manager_delegate.cc
+++ b/chrome/browser/download/chrome_download_manager_delegate.cc
@@ -15,7 +15,7 @@
 #include "base/rand_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/download/download_completion_blocker.h"
 #include "chrome/browser/download/download_crx_util.h"
diff --git a/chrome/browser/download/download_browsertest.cc b/chrome/browser/download/download_browsertest.cc
index 2f9700c..505c42a 100644
--- a/chrome/browser/download/download_browsertest.cc
+++ b/chrome/browser/download/download_browsertest.cc
@@ -899,7 +899,7 @@
         base::FilePath destination_folder = GetDownloadDirectory(browser());
         base::FilePath my_downloaded_file = item->GetTargetFilePath();
         EXPECT_TRUE(file_util::PathExists(my_downloaded_file));
-        EXPECT_TRUE(file_util::Delete(my_downloaded_file, false));
+        EXPECT_TRUE(base::Delete(my_downloaded_file, false));
 
         EXPECT_EQ(download_info.should_redirect_to_documents ?
                       std::string::npos :
diff --git a/chrome/browser/download/download_item_model.cc b/chrome/browser/download/download_item_model.cc
index 8561c6b..ec11fc0 100644
--- a/chrome/browser/download/download_item_model.cc
+++ b/chrome/browser/download/download_item_model.cc
@@ -10,7 +10,7 @@
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/supports_user_data.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/download/download_crx_util.h"
 #include "chrome/browser/safe_browsing/download_feedback_service.h"
 #include "chrome/common/time_format.h"
diff --git a/chrome/browser/download/download_query.cc b/chrome/browser/download/download_query.cc
index 3f7ed10..14bc73e 100644
--- a/chrome/browser/download/download_query.cc
+++ b/chrome/browser/download/download_query.cc
@@ -21,15 +21,15 @@
 #include "base/strings/string_split.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/pref_names.h"
 #include "content/public/browser/content_browser_client.h"
 #include "content/public/browser/download_item.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/net_util.h"
 #include "third_party/re2/re2/re2.h"
+#include "url/gurl.h"
 
 using content::DownloadDangerType;
 using content::DownloadItem;
diff --git a/chrome/browser/download/download_query_unittest.cc b/chrome/browser/download/download_query_unittest.cc
index d7bf5a1..e86e40e 100644
--- a/chrome/browser/download/download_query_unittest.cc
+++ b/chrome/browser/download/download_query_unittest.cc
@@ -10,7 +10,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/stl_util.h"
 #include "base/strings/string16.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/download/download_query.h"
 #include "content/public/test/mock_download_item.h"
diff --git a/chrome/browser/download/download_shelf.h b/chrome/browser/download/download_shelf.h
index 9498a86..dd61a49 100644
--- a/chrome/browser/download/download_shelf.h
+++ b/chrome/browser/download/download_shelf.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_DOWNLOAD_DOWNLOAD_SHELF_H_
 
 #include "base/memory/weak_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
 
 namespace content {
 class DownloadItem;
diff --git a/chrome/browser/download/download_status_updater.cc b/chrome/browser/download/download_status_updater.cc
index 646e106..b084378 100644
--- a/chrome/browser/download/download_status_updater.cc
+++ b/chrome/browser/download/download_status_updater.cc
@@ -10,6 +10,10 @@
 #include "base/stl_util.h"
 #include "chrome/browser/download/download_util.h"
 
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+#include "ui/linux_ui/linux_ui.h"
+#endif
+
 namespace {
 
 // DownloadStatusUpdater::UpdateAppIconDownloadProgress() expects to only be
@@ -133,7 +137,16 @@
 #if defined(USE_AURA) || defined(OS_ANDROID)
 void DownloadStatusUpdater::UpdateAppIconDownloadProgress(
     content::DownloadItem* download) {
-  // TODO(davemoore): Implement once UX for aura download is decided <104742>
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+  const ui::LinuxUI* linux_ui = ui::LinuxUI::instance();
+  if (linux_ui) {
+    float progress = 0;
+    int download_count = 0;
+    GetProgress(&progress, &download_count);
+    linux_ui->SetDownloadCount(download_count);
+    linux_ui->SetProgressFraction(progress);
+  }
+#endif
   // TODO(avi): Implement for Android?
 }
 #endif
diff --git a/chrome/browser/download/download_status_updater_mac.mm b/chrome/browser/download/download_status_updater_mac.mm
index fbf010e..4e80610 100644
--- a/chrome/browser/download/download_status_updater_mac.mm
+++ b/chrome/browser/download/download_status_updater_mac.mm
@@ -5,12 +5,12 @@
 #include "chrome/browser/download/download_status_updater.h"
 
 #include "base/mac/foundation_util.h"
-#include "base/memory/scoped_nsobject.h"
-#include "base/supports_user_data.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/strings/sys_string_conversions.h"
-#include "content/public/browser/download_item.h"
+#include "base/supports_user_data.h"
 #import "chrome/browser/ui/cocoa/dock_icon.h"
-#include "googleurl/src/gurl.h"
+#include "content/public/browser/download_item.h"
+#include "url/gurl.h"
 
 // --- Private 10.8 API for showing progress ---
 // rdar://12058866 http://www.openradar.me/12058866
@@ -19,6 +19,11 @@
 
 NSString* const kNSProgressAppBundleIdentifierKey =
     @"NSProgressAppBundleIdentifierKey";
+NSString* const kNSProgressEstimatedTimeRemainingKey =
+    @"NSProgressEstimatedTimeRemainingKey";
+
+// NSProgressEstimatedTimeKey is 10.8 SPI only; it became
+// NSProgressEstimatedTimeRemainingKey when NSProgress became API in 10.9.
 NSString* const kNSProgressEstimatedTimeKey =
     @"NSProgressEstimatedTimeKey";
 NSString* const kNSProgressFileCompletedCountKey =
@@ -67,8 +72,19 @@
   NSString* result = [cache objectForKey:string];
   if (!result) {
     NSString** ref = static_cast<NSString**>(
-        CFBundleGetDataPointerForName(foundation,
-                                      base::mac::NSToCFCast(string)));
+        CFBundleGetDataPointerForName(
+            foundation, base::mac::NSToCFCast(string)));
+    if (ref) {
+      result = *ref;
+      [cache setObject:result forKey:string];
+    }
+  }
+
+  if (!result && string == kNSProgressEstimatedTimeRemainingKey) {
+    // Perhaps this is 10.8; try the old name of this key.
+    NSString** ref = static_cast<NSString**>(
+        CFBundleGetDataPointerForName(
+            foundation, base::mac::NSToCFCast(kNSProgressEstimatedTimeKey)));
     if (ref) {
       result = *ref;
       [cache setObject:result forKey:string];
@@ -169,7 +185,7 @@
   void setTarget(const base::FilePath& target) { target_ = target; }
 
  private:
-  scoped_nsobject<NSProgress> progress_;
+  base::scoped_nsobject<NSProgress> progress_;
   base::FilePath target_;
 };
 
@@ -236,6 +252,15 @@
   NSProgress* progress = progress_data->progress();
   progress.totalUnitCount = download->GetTotalBytes();
   progress.completedUnitCount = download->GetReceivedBytes();
+  [progress setUserInfoObject:@(download->CurrentSpeed())
+                       forKey:ProgressString(kNSProgressThroughputKey)];
+
+  base::TimeDelta time_remaining;
+  NSNumber* time_remaining_ns = nil;
+  if (download->TimeRemaining(&time_remaining))
+    time_remaining_ns = @(time_remaining.InSeconds());
+  [progress setUserInfoObject:time_remaining_ns
+                   forKey:ProgressString(kNSProgressEstimatedTimeRemainingKey)];
 
   base::FilePath download_path = download->GetFullPath();
   if (progress_data->target() != download_path) {
diff --git a/chrome/browser/download/download_status_updater_win.cc b/chrome/browser/download/download_status_updater_win.cc
index df74cea..515e54e 100644
--- a/chrome/browser/download/download_status_updater_win.cc
+++ b/chrome/browser/download/download_status_updater_win.cc
@@ -20,9 +20,9 @@
 #include "chrome/browser/ui/browser_window.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
-#include "googleurl/src/gurl.h"
 #include "grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "url/gurl.h"
 #include "win8/util/win8_util.h"
 
 // This code doesn't compile with Aura on. TODO(avi): hook it up so that
diff --git a/chrome/browser/download/download_target_determiner.cc b/chrome/browser/download/download_target_determiner.cc
index 1d23aba..794886f 100644
--- a/chrome/browser/download/download_target_determiner.cc
+++ b/chrome/browser/download/download_target_determiner.cc
@@ -7,7 +7,7 @@
 #include "base/prefs/pref_service.h"
 #include "base/rand_util.h"
 #include "base/strings/stringprintf.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/download/chrome_download_manager_delegate.h"
 #include "chrome/browser/download/download_crx_util.h"
 #include "chrome/browser/download/download_extensions.h"
diff --git a/chrome/browser/drive/drive_api_service.cc b/chrome/browser/drive/drive_api_service.cc
index 85f7a8ac..4ad4732 100644
--- a/chrome/browser/drive/drive_api_service.cc
+++ b/chrome/browser/drive/drive_api_service.cc
@@ -8,24 +8,62 @@
 #include <vector>
 
 #include "base/bind.h"
-#include "base/message_loop/message_loop_proxy.h"
 #include "base/strings/stringprintf.h"
 #include "base/task_runner_util.h"
-#include "base/threading/sequenced_worker_pool.h"
 #include "base/values.h"
+#include "chrome/browser/drive/drive_api_util.h"
 #include "chrome/browser/google_apis/auth_service.h"
 #include "chrome/browser/google_apis/drive_api_parser.h"
 #include "chrome/browser/google_apis/drive_api_requests.h"
-#include "chrome/browser/google_apis/drive_api_util.h"
 #include "chrome/browser/google_apis/gdata_wapi_parser.h"
 #include "chrome/browser/google_apis/request_sender.h"
-#include "chrome/browser/google_apis/time_util.h"
-#include "chrome/browser/profiles/profile.h"
 #include "content/public/browser/browser_thread.h"
 
 using content::BrowserThread;
+using google_apis::AppList;
+using google_apis::AuthorizeAppCallback;
+using google_apis::CancelCallback;
+using google_apis::ChangeList;
+using google_apis::DownloadActionCallback;
+using google_apis::EntryActionCallback;
+using google_apis::FileList;
+using google_apis::FileResource;
+using google_apis::GDATA_OTHER_ERROR;
+using google_apis::GDATA_PARSE_ERROR;
+using google_apis::GDataErrorCode;
+using google_apis::GetAboutRequest;
+using google_apis::GetAboutResourceCallback;
+using google_apis::GetAppListCallback;
+using google_apis::GetApplistRequest;
+using google_apis::GetChangelistRequest;
+using google_apis::GetContentCallback;
+using google_apis::GetFileRequest;
+using google_apis::GetFilelistRequest;
+using google_apis::GetResourceEntryCallback;
+using google_apis::GetResourceListCallback;
+using google_apis::HTTP_SUCCESS;
+using google_apis::InitiateUploadCallback;
+using google_apis::ProgressCallback;
+using google_apis::RequestSender;
+using google_apis::ResourceEntry;
+using google_apis::ResourceList;
+using google_apis::UploadRangeCallback;
+using google_apis::UploadRangeResponse;
+using google_apis::drive::ContinueGetFileListRequest;
+using google_apis::drive::CopyResourceRequest;
+using google_apis::drive::CreateDirectoryRequest;
+using google_apis::drive::DeleteResourceRequest;
+using google_apis::drive::DownloadFileRequest;
+using google_apis::drive::GetUploadStatusRequest;
+using google_apis::drive::InitiateUploadExistingFileRequest;
+using google_apis::drive::InitiateUploadNewFileRequest;
+using google_apis::drive::InsertResourceRequest;
+using google_apis::drive::RenameResourceRequest;
+using google_apis::drive::ResumeUploadRequest;
+using google_apis::drive::TouchResourceRequest;
+using google_apis::drive::TrashResourceRequest;
 
-namespace google_apis {
+namespace drive {
 
 namespace {
 
@@ -91,6 +129,7 @@
 // Sends a task to parse the JSON value into ResourceList on blocking pool,
 // with a callback which is called when the task is done.
 void ParseResourceListOnBlockingPoolAndRun(
+    scoped_refptr<base::TaskRunner> blocking_task_runner,
     const GetResourceListCallback& callback,
     GDataErrorCode error,
     scoped_ptr<base::Value> value) {
@@ -104,7 +143,7 @@
   }
 
   PostTaskAndReplyWithResult(
-      BrowserThread::GetBlockingPool(),
+      blocking_task_runner.get(),
       FROM_HERE,
       base::Bind(&ParseResourceListOnBlockingPool, base::Passed(&value)),
       base::Bind(&DidParseResourceListOnBlockingPool, callback));
@@ -221,11 +260,14 @@
 
 DriveAPIService::DriveAPIService(
     net::URLRequestContextGetter* url_request_context_getter,
+    base::TaskRunner* blocking_task_runner,
     const GURL& base_url,
+    const GURL& base_download_url,
     const std::string& custom_user_agent)
     : url_request_context_getter_(url_request_context_getter),
+      blocking_task_runner_(blocking_task_runner),
       profile_(NULL),
-      url_generator_(base_url),
+      url_generator_(base_url, base_download_url),
       custom_user_agent_(custom_user_agent) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 }
@@ -287,12 +329,13 @@
   return sender_->StartRequestWithRetry(
       new GetChangelistRequest(
           sender_.get(),
-          url_request_context_getter_,
           url_generator_,
           false,  // include deleted
           0,
           kMaxNumFilesResourcePerRequest,
-          base::Bind(&ParseResourceListOnBlockingPoolAndRun, callback)));
+          base::Bind(&ParseResourceListOnBlockingPoolAndRun,
+                     blocking_task_runner_,
+                     callback)));
 }
 
 CancelCallback DriveAPIService::GetResourceListInDirectory(
@@ -306,20 +349,21 @@
   // children's references, but we need all file resource list.
   // So, here we use files.list method instead, with setting parents query.
   // After the migration from GData WAPI to Drive API v2, we should clean the
-  // code up by moving the resposibility to include "parents" in the query
+  // code up by moving the responsibility to include "parents" in the query
   // to client side.
   // We aren't interested in files in trash in this context, neither.
   return sender_->StartRequestWithRetry(
       new GetFilelistRequest(
           sender_.get(),
-          url_request_context_getter_,
           url_generator_,
           base::StringPrintf(
               "'%s' in parents and trashed = false",
               drive::util::EscapeQueryStringValue(
                   directory_resource_id).c_str()),
           kMaxNumFilesResourcePerRequest,
-          base::Bind(&ParseResourceListOnBlockingPoolAndRun, callback)));
+          base::Bind(&ParseResourceListOnBlockingPoolAndRun,
+                     blocking_task_runner_,
+                     callback)));
 }
 
 CancelCallback DriveAPIService::Search(
@@ -332,11 +376,12 @@
   return sender_->StartRequestWithRetry(
       new GetFilelistRequest(
           sender_.get(),
-          url_request_context_getter_,
           url_generator_,
           drive::util::TranslateQuery(search_query),
           kMaxNumFilesResourcePerRequestForSearch,
-          base::Bind(&ParseResourceListOnBlockingPoolAndRun, callback)));
+          base::Bind(&ParseResourceListOnBlockingPoolAndRun,
+                     blocking_task_runner_,
+                     callback)));
 }
 
 CancelCallback DriveAPIService::SearchByTitle(
@@ -360,11 +405,12 @@
   return sender_->StartRequestWithRetry(
       new GetFilelistRequest(
           sender_.get(),
-          url_request_context_getter_,
           url_generator_,
           query,
           kMaxNumFilesResourcePerRequest,
-          base::Bind(&ParseResourceListOnBlockingPoolAndRun, callback)));
+          base::Bind(&ParseResourceListOnBlockingPoolAndRun,
+                     blocking_task_runner_,
+                     callback)));
 }
 
 CancelCallback DriveAPIService::GetChangeList(
@@ -376,12 +422,13 @@
   return sender_->StartRequestWithRetry(
       new GetChangelistRequest(
           sender_.get(),
-          url_request_context_getter_,
           url_generator_,
           true,  // include deleted
           start_changestamp,
           kMaxNumFilesResourcePerRequest,
-          base::Bind(&ParseResourceListOnBlockingPoolAndRun, callback)));
+          base::Bind(&ParseResourceListOnBlockingPoolAndRun,
+                     blocking_task_runner_,
+                     callback)));
 }
 
 CancelCallback DriveAPIService::ContinueGetResourceList(
@@ -391,11 +438,12 @@
   DCHECK(!callback.is_null());
 
   return sender_->StartRequestWithRetry(
-      new drive::ContinueGetFileListRequest(
+      new ContinueGetFileListRequest(
           sender_.get(),
-          url_request_context_getter_,
           override_url,
-          base::Bind(&ParseResourceListOnBlockingPoolAndRun, callback)));
+          base::Bind(&ParseResourceListOnBlockingPoolAndRun,
+                     blocking_task_runner_,
+                     callback)));
 }
 
 CancelCallback DriveAPIService::GetResourceEntry(
@@ -406,7 +454,6 @@
 
   return sender_->StartRequestWithRetry(new GetFileRequest(
       sender_.get(),
-      url_request_context_getter_,
       url_generator_,
       resource_id,
       base::Bind(&ParseResourceEntryAndRun, callback)));
@@ -420,7 +467,6 @@
   return sender_->StartRequestWithRetry(
       new GetAboutRequest(
           sender_.get(),
-          url_request_context_getter_,
           url_generator_,
           callback));
 }
@@ -431,15 +477,13 @@
 
   return sender_->StartRequestWithRetry(new GetApplistRequest(
       sender_.get(),
-      url_request_context_getter_,
       url_generator_,
       base::Bind(&ParseAppListAndRun, callback)));
 }
 
 CancelCallback DriveAPIService::DownloadFile(
-    const base::FilePath& virtual_path,
     const base::FilePath& local_cache_path,
-    const GURL& download_url,
+    const std::string& resource_id,
     const DownloadActionCallback& download_action_callback,
     const GetContentCallback& get_content_callback,
     const ProgressCallback& progress_callback) {
@@ -449,13 +493,12 @@
 
   return sender_->StartRequestWithRetry(
       new DownloadFileRequest(sender_.get(),
-                              url_request_context_getter_,
+                              url_generator_,
+                              resource_id,
+                              local_cache_path,
                               download_action_callback,
                               get_content_callback,
-                              progress_callback,
-                              download_url,
-                              virtual_path,
-                              local_cache_path));
+                              progress_callback));
 }
 
 CancelCallback DriveAPIService::DeleteResource(
@@ -465,9 +508,8 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(!callback.is_null());
 
-  return sender_->StartRequestWithRetry(new drive::TrashResourceRequest(
+  return sender_->StartRequestWithRetry(new TrashResourceRequest(
       sender_.get(),
-      url_request_context_getter_,
       url_generator_,
       resource_id,
       callback));
@@ -481,9 +523,8 @@
   DCHECK(!callback.is_null());
 
   return sender_->StartRequestWithRetry(
-      new drive::CreateDirectoryRequest(
+      new CreateDirectoryRequest(
           sender_.get(),
-          url_request_context_getter_,
           url_generator_,
           parent_resource_id,
           directory_name,
@@ -499,9 +540,8 @@
   DCHECK(!callback.is_null());
 
   return sender_->StartRequestWithRetry(
-      new drive::CopyResourceRequest(
+      new CopyResourceRequest(
           sender_.get(),
-          url_request_context_getter_,
           url_generator_,
           resource_id,
           parent_resource_id,
@@ -517,9 +557,8 @@
   DCHECK(!callback.is_null());
 
   return sender_->StartRequestWithRetry(
-      new drive::CopyResourceRequest(
+      new CopyResourceRequest(
           sender_.get(),
-          url_request_context_getter_,
           url_generator_,
           resource_id,
           std::string(),  // parent_resource_id.
@@ -535,9 +574,8 @@
   DCHECK(!callback.is_null());
 
   return sender_->StartRequestWithRetry(
-      new drive::RenameResourceRequest(
+      new RenameResourceRequest(
           sender_.get(),
-          url_request_context_getter_,
           url_generator_,
           resource_id,
           new_name,
@@ -555,9 +593,8 @@
   DCHECK(!callback.is_null());
 
   return sender_->StartRequestWithRetry(
-      new drive::TouchResourceRequest(
+      new TouchResourceRequest(
           sender_.get(),
-          url_request_context_getter_,
           url_generator_,
           resource_id,
           modified_date,
@@ -573,9 +610,8 @@
   DCHECK(!callback.is_null());
 
   return sender_->StartRequestWithRetry(
-      new drive::InsertResourceRequest(
+      new InsertResourceRequest(
           sender_.get(),
-          url_request_context_getter_,
           url_generator_,
           parent_resource_id,
           resource_id,
@@ -590,9 +626,8 @@
   DCHECK(!callback.is_null());
 
   return sender_->StartRequestWithRetry(
-      new drive::DeleteResourceRequest(
+      new DeleteResourceRequest(
           sender_.get(),
-          url_request_context_getter_,
           url_generator_,
           parent_resource_id,
           resource_id,
@@ -600,7 +635,6 @@
 }
 
 CancelCallback DriveAPIService::InitiateUploadNewFile(
-    const base::FilePath& drive_file_path,
     const std::string& content_type,
     int64 content_length,
     const std::string& parent_resource_id,
@@ -610,11 +644,9 @@
   DCHECK(!callback.is_null());
 
   return sender_->StartRequestWithRetry(
-      new drive::InitiateUploadNewFileRequest(
+      new InitiateUploadNewFileRequest(
           sender_.get(),
-          url_request_context_getter_,
           url_generator_,
-          drive_file_path,
           content_type,
           content_length,
           parent_resource_id,
@@ -623,7 +655,6 @@
 }
 
 CancelCallback DriveAPIService::InitiateUploadExistingFile(
-    const base::FilePath& drive_file_path,
     const std::string& content_type,
     int64 content_length,
     const std::string& resource_id,
@@ -633,11 +664,9 @@
   DCHECK(!callback.is_null());
 
   return sender_->StartRequestWithRetry(
-      new drive::InitiateUploadExistingFileRequest(
+      new InitiateUploadExistingFileRequest(
           sender_.get(),
-          url_request_context_getter_,
           url_generator_,
-          drive_file_path,
           content_type,
           content_length,
           resource_id,
@@ -646,7 +675,6 @@
 }
 
 CancelCallback DriveAPIService::ResumeUpload(
-    const base::FilePath& drive_file_path,
     const GURL& upload_url,
     int64 start_position,
     int64 end_position,
@@ -659,10 +687,8 @@
   DCHECK(!callback.is_null());
 
   return sender_->StartRequestWithRetry(
-      new drive::ResumeUploadRequest(
+      new ResumeUploadRequest(
           sender_.get(),
-          url_request_context_getter_,
-          drive_file_path,
           upload_url,
           start_position,
           end_position,
@@ -674,17 +700,14 @@
 }
 
 CancelCallback DriveAPIService::GetUploadStatus(
-    const base::FilePath& drive_file_path,
     const GURL& upload_url,
     int64 content_length,
     const UploadRangeCallback& callback) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(!callback.is_null());
 
-  return sender_->StartRequestWithRetry(new drive::GetUploadStatusRequest(
+  return sender_->StartRequestWithRetry(new GetUploadStatusRequest(
       sender_.get(),
-      url_request_context_getter_,
-      drive_file_path,
       upload_url,
       content_length,
       base::Bind(&ParseResourceEntryForUploadRangeAndRun, callback)));
@@ -699,7 +722,6 @@
 
   return sender_->StartRequestWithRetry(new GetFileRequest(
       sender_.get(),
-      url_request_context_getter_,
       url_generator_,
       resource_id,
       base::Bind(&ExtractOpenUrlAndRun, app_id, callback)));
@@ -738,4 +760,4 @@
   }
 }
 
-}  // namespace google_apis
+}  // namespace drive
diff --git a/chrome/browser/drive/drive_api_service.h b/chrome/browser/drive/drive_api_service.h
index e869355..3a330d6 100644
--- a/chrome/browser/drive/drive_api_service.h
+++ b/chrome/browser/drive/drive_api_service.h
@@ -7,6 +7,7 @@
 
 #include <string>
 
+#include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/observer_list.h"
 #include "chrome/browser/drive/drive_service_interface.h"
@@ -18,28 +19,37 @@
 
 namespace base {
 class FilePath;
+class TaskRunner;
+}
+
+namespace google_apis {
+class RequestSender;
 }
 
 namespace net {
 class URLRequestContextGetter;
 }  // namespace net
 
-namespace google_apis {
-class RequestSender;
+namespace drive {
 
 // This class provides Drive request calls using Drive V2 API.
 // Details of API call are abstracted in each request class and this class
 // works as a thin wrapper for the API.
 class DriveAPIService : public DriveServiceInterface,
-                        public AuthServiceObserver {
+                        public google_apis::AuthServiceObserver {
  public:
   // |url_request_context_getter| is used to initialize URLFetcher.
+  // |blocking_task_runner| is used to run blocking tasks (like parsing JSON).
   // |base_url| is used to generate URLs for communication with the drive API.
+  // |base_download_url| is used to generate URLs for downloading file from the
+  // drive API.
   // |custom_user_agent| will be used for the User-Agent header in HTTP
   // requests issues through the service if the value is not empty.
   DriveAPIService(
       net::URLRequestContextGetter* url_request_context_getter,
+      base::TaskRunner* blocking_task_runner,
       const GURL& base_url,
+      const GURL& base_download_url,
       const std::string& custom_user_agent);
   virtual ~DriveAPIService();
 
@@ -55,120 +65,116 @@
   virtual void ClearAccessToken() OVERRIDE;
   virtual void ClearRefreshToken() OVERRIDE;
   virtual std::string GetRootResourceId() const OVERRIDE;
-  virtual CancelCallback GetAllResourceList(
-      const GetResourceListCallback& callback) OVERRIDE;
-  virtual CancelCallback GetResourceListInDirectory(
+  virtual google_apis::CancelCallback GetAllResourceList(
+      const google_apis::GetResourceListCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback GetResourceListInDirectory(
       const std::string& directory_resource_id,
-      const GetResourceListCallback& callback) OVERRIDE;
-  virtual CancelCallback Search(
+      const google_apis::GetResourceListCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback Search(
       const std::string& search_query,
-      const GetResourceListCallback& callback) OVERRIDE;
-  virtual CancelCallback SearchByTitle(
+      const google_apis::GetResourceListCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback SearchByTitle(
       const std::string& title,
       const std::string& directory_resource_id,
-      const GetResourceListCallback& callback) OVERRIDE;
-  virtual CancelCallback GetChangeList(
+      const google_apis::GetResourceListCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback GetChangeList(
       int64 start_changestamp,
-      const GetResourceListCallback& callback) OVERRIDE;
-  virtual CancelCallback ContinueGetResourceList(
+      const google_apis::GetResourceListCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback ContinueGetResourceList(
       const GURL& override_url,
-      const GetResourceListCallback& callback) OVERRIDE;
-  virtual CancelCallback GetResourceEntry(
+      const google_apis::GetResourceListCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback GetResourceEntry(
       const std::string& resource_id,
-      const GetResourceEntryCallback& callback) OVERRIDE;
-  virtual CancelCallback GetAboutResource(
-      const GetAboutResourceCallback& callback) OVERRIDE;
-  virtual CancelCallback GetAppList(
-      const GetAppListCallback& callback) OVERRIDE;
-  virtual CancelCallback DeleteResource(
+      const google_apis::GetResourceEntryCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback GetAboutResource(
+      const google_apis::GetAboutResourceCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback GetAppList(
+      const google_apis::GetAppListCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback DeleteResource(
       const std::string& resource_id,
       const std::string& etag,
-      const EntryActionCallback& callback) OVERRIDE;
-  virtual CancelCallback DownloadFile(
-      const base::FilePath& virtual_path,
+      const google_apis::EntryActionCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback DownloadFile(
       const base::FilePath& local_cache_path,
-      const GURL& download_url,
-      const DownloadActionCallback& download_action_callback,
-      const GetContentCallback& get_content_callback,
-      const ProgressCallback& progress_callback) OVERRIDE;
-  virtual CancelCallback CopyResource(
+      const std::string& resource_id,
+      const google_apis::DownloadActionCallback& download_action_callback,
+      const google_apis::GetContentCallback& get_content_callback,
+      const google_apis::ProgressCallback& progress_callback) OVERRIDE;
+  virtual google_apis::CancelCallback CopyResource(
       const std::string& resource_id,
       const std::string& parent_resource_id,
       const std::string& new_name,
-      const GetResourceEntryCallback& callback) OVERRIDE;
-  virtual CancelCallback CopyHostedDocument(
+      const google_apis::GetResourceEntryCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback CopyHostedDocument(
       const std::string& resource_id,
       const std::string& new_name,
-      const GetResourceEntryCallback& callback) OVERRIDE;
-  virtual CancelCallback RenameResource(
+      const google_apis::GetResourceEntryCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback RenameResource(
       const std::string& resource_id,
       const std::string& new_name,
-      const EntryActionCallback& callback) OVERRIDE;
-  virtual CancelCallback TouchResource(
+      const google_apis::EntryActionCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback TouchResource(
       const std::string& resource_id,
       const base::Time& modified_date,
       const base::Time& last_viewed_by_me_date,
-      const GetResourceEntryCallback& callback) OVERRIDE;
-  virtual CancelCallback AddResourceToDirectory(
+      const google_apis::GetResourceEntryCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback AddResourceToDirectory(
       const std::string& parent_resource_id,
       const std::string& resource_id,
-      const EntryActionCallback& callback) OVERRIDE;
-  virtual CancelCallback RemoveResourceFromDirectory(
+      const google_apis::EntryActionCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback RemoveResourceFromDirectory(
       const std::string& parent_resource_id,
       const std::string& resource_id,
-      const EntryActionCallback& callback) OVERRIDE;
-  virtual CancelCallback AddNewDirectory(
+      const google_apis::EntryActionCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback AddNewDirectory(
       const std::string& parent_resource_id,
       const std::string& directory_name,
-      const GetResourceEntryCallback& callback) OVERRIDE;
-  virtual CancelCallback InitiateUploadNewFile(
-      const base::FilePath& drive_file_path,
+      const google_apis::GetResourceEntryCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback InitiateUploadNewFile(
       const std::string& content_type,
       int64 content_length,
       const std::string& parent_resource_id,
       const std::string& title,
-      const InitiateUploadCallback& callback) OVERRIDE;
-  virtual CancelCallback InitiateUploadExistingFile(
-      const base::FilePath& drive_file_path,
+      const google_apis::InitiateUploadCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback InitiateUploadExistingFile(
       const std::string& content_type,
       int64 content_length,
       const std::string& resource_id,
       const std::string& etag,
-      const InitiateUploadCallback& callback) OVERRIDE;
-  virtual CancelCallback ResumeUpload(
-      const base::FilePath& drive_file_path,
+      const google_apis::InitiateUploadCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback ResumeUpload(
       const GURL& upload_url,
       int64 start_position,
       int64 end_position,
       int64 content_length,
       const std::string& content_type,
       const base::FilePath& local_file_path,
-      const UploadRangeCallback& callback,
-      const ProgressCallback& progress_callback) OVERRIDE;
-  virtual CancelCallback GetUploadStatus(
-      const base::FilePath& drive_file_path,
+      const google_apis::UploadRangeCallback& callback,
+      const google_apis::ProgressCallback& progress_callback) OVERRIDE;
+  virtual google_apis::CancelCallback GetUploadStatus(
       const GURL& upload_url,
       int64 content_length,
-      const UploadRangeCallback& callback) OVERRIDE;
-  virtual CancelCallback AuthorizeApp(
+      const google_apis::UploadRangeCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback AuthorizeApp(
       const std::string& resource_id,
       const std::string& app_id,
-      const AuthorizeAppCallback& callback) OVERRIDE;
+      const google_apis::AuthorizeAppCallback& callback) OVERRIDE;
 
  private:
   // AuthServiceObserver override.
   virtual void OnOAuth2RefreshTokenChanged() OVERRIDE;
 
   net::URLRequestContextGetter* url_request_context_getter_;
+  scoped_refptr<base::TaskRunner> blocking_task_runner_;
   Profile* profile_;
-  scoped_ptr<RequestSender> sender_;
+  scoped_ptr<google_apis::RequestSender> sender_;
   ObserverList<DriveServiceObserver> observers_;
-  DriveApiUrlGenerator url_generator_;
+  google_apis::DriveApiUrlGenerator url_generator_;
   const std::string custom_user_agent_;
 
   DISALLOW_COPY_AND_ASSIGN(DriveAPIService);
 };
 
-}  // namespace google_apis
+}  // namespace drive
 
 #endif  // CHROME_BROWSER_DRIVE_DRIVE_API_SERVICE_H_
diff --git a/chrome/browser/drive/drive_api_util.cc b/chrome/browser/drive/drive_api_util.cc
new file mode 100644
index 0000000..b9a8274
--- /dev/null
+++ b/chrome/browser/drive/drive_api_util.cc
@@ -0,0 +1,132 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/drive/drive_api_util.h"
+
+#include <string>
+
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "base/strings/string16.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/drive/drive_switches.h"
+#include "net/base/escape.h"
+#include "third_party/re2/re2/re2.h"
+#include "url/gurl.h"
+
+namespace drive {
+namespace util {
+
+bool IsDriveV2ApiEnabled() {
+  const CommandLine* command_line = CommandLine::ForCurrentProcess();
+
+  // Disable Drive API v2 by default.
+  if (!command_line->HasSwitch(switches::kEnableDriveV2Api))
+    return false;
+
+  std::string value =
+      command_line->GetSwitchValueASCII(switches::kEnableDriveV2Api);
+  StringToLowerASCII(&value);
+  // The value must be "" or "true" for true, or "false" for false.
+  DCHECK(value.empty() || value == "true" || value == "false");
+  return value != "false";
+}
+
+std::string EscapeQueryStringValue(const std::string& str) {
+  std::string result;
+  result.reserve(str.size());
+  for (size_t i = 0; i < str.size(); ++i) {
+    if (str[i] == '\\' || str[i] == '\'') {
+      result.push_back('\\');
+    }
+    result.push_back(str[i]);
+  }
+  return result;
+}
+
+std::string TranslateQuery(const std::string& original_query) {
+  // In order to handle non-ascii white spaces correctly, convert to UTF16.
+  base::string16 query = UTF8ToUTF16(original_query);
+  const base::string16 kDelimiter(
+      kWhitespaceUTF16 + base::string16(1, static_cast<char16>('"')));
+
+  std::string result;
+  for (size_t index = query.find_first_not_of(kWhitespaceUTF16);
+       index != base::string16::npos;
+       index = query.find_first_not_of(kWhitespaceUTF16, index)) {
+    bool is_exclusion = (query[index] == '-');
+    if (is_exclusion)
+      ++index;
+    if (index == query.length()) {
+      // Here, the token is '-' and it should be ignored.
+      continue;
+    }
+
+    size_t begin_token = index;
+    base::string16 token;
+    if (query[begin_token] == '"') {
+      // Quoted query.
+      ++begin_token;
+      size_t end_token = query.find('"', begin_token);
+      if (end_token == base::string16::npos) {
+        // This is kind of syntax error, since quoted string isn't finished.
+        // However, the query is built by user manually, so here we treat
+        // whole remaining string as a token as a fallback, by appending
+        // a missing double-quote character.
+        end_token = query.length();
+        query.push_back('"');
+      }
+
+      token = query.substr(begin_token, end_token - begin_token);
+      index = end_token + 1;  // Consume last '"', too.
+    } else {
+      size_t end_token = query.find_first_of(kDelimiter, begin_token);
+      if (end_token == base::string16::npos) {
+        end_token = query.length();
+      }
+
+      token = query.substr(begin_token, end_token - begin_token);
+      index = end_token;
+    }
+
+    if (token.empty()) {
+      // Just ignore an empty token.
+      continue;
+    }
+
+    if (!result.empty()) {
+      // If there are two or more tokens, need to connect with "and".
+      result.append(" and ");
+    }
+
+    // The meaning of "fullText" should include title, description and content.
+    base::StringAppendF(
+        &result,
+        "%sfullText contains \'%s\'",
+        is_exclusion ? "not " : "",
+        EscapeQueryStringValue(UTF16ToUTF8(token)).c_str());
+  }
+
+  return result;
+}
+
+std::string ExtractResourceIdFromUrl(const GURL& url) {
+  return net::UnescapeURLComponent(url.ExtractFileName(),
+                                   net::UnescapeRule::URL_SPECIAL_CHARS);
+}
+
+std::string CanonicalizeResourceId(const std::string& resource_id) {
+  // If resource ID is in the old WAPI format starting with a prefix like
+  // "document:", strip it and return the remaining part.
+  std::string stripped_resource_id;
+  if (RE2::FullMatch(resource_id, "^[a-z-]+(?::|%3A)([\\w-]+)$",
+                     &stripped_resource_id))
+    return stripped_resource_id;
+  return resource_id;
+}
+
+}  // namespace util
+}  // namespace drive
diff --git a/chrome/browser/drive/drive_api_util.h b/chrome/browser/drive/drive_api_util.h
new file mode 100644
index 0000000..2d1d991
--- /dev/null
+++ b/chrome/browser/drive/drive_api_util.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_DRIVE_DRIVE_API_UTIL_H_
+#define CHROME_BROWSER_DRIVE_DRIVE_API_UTIL_H_
+
+#include <string>
+
+class GURL;
+
+namespace drive {
+namespace util {
+
+// Returns true if Drive v2 API is enabled via commandline switch.
+bool IsDriveV2ApiEnabled();
+
+// Escapes ' to \' in the |str|. This is designed to use for string value of
+// search parameter on Drive API v2.
+// See also: https://developers.google.com/drive/search-parameters
+std::string EscapeQueryStringValue(const std::string& str);
+
+// Parses the query, and builds a search query for Drive API v2.
+// This only supports:
+//   Regular query (e.g. dog => fullText contains 'dog')
+//   Conjunctions
+//     (e.g. dog cat => fullText contains 'dog' and fullText contains 'cat')
+//   Exclusion query (e.g. -cat => not fullText contains 'cat').
+//   Quoted query (e.g. "dog cat" => fullText contains 'dog cat').
+// See also: https://developers.google.com/drive/search-parameters
+std::string TranslateQuery(const std::string& original_query);
+
+// Extracts resource_id out of edit url.
+std::string ExtractResourceIdFromUrl(const GURL& url);
+
+// If |resource_id| is in the old resource ID format used by WAPI, converts it
+// into the new format.
+std::string CanonicalizeResourceId(const std::string& resource_id);
+
+}  // namespace util
+}  // namespace drive
+
+#endif  // CHROME_BROWSER_DRIVE_DRIVE_API_UTIL_H_
diff --git a/chrome/browser/drive/drive_api_util_unittest.cc b/chrome/browser/drive/drive_api_util_unittest.cc
new file mode 100644
index 0000000..1b4e32e
--- /dev/null
+++ b/chrome/browser/drive/drive_api_util_unittest.cc
@@ -0,0 +1,78 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/drive/drive_api_util.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace drive {
+namespace util {
+
+TEST(DriveApiUtilTest, EscapeQueryStringValue) {
+  EXPECT_EQ("abcde", EscapeQueryStringValue("abcde"));
+  EXPECT_EQ("\\'", EscapeQueryStringValue("'"));
+  EXPECT_EQ("\\'abcde\\'", EscapeQueryStringValue("'abcde'"));
+  EXPECT_EQ("\\\\", EscapeQueryStringValue("\\"));
+  EXPECT_EQ("\\\\\\'", EscapeQueryStringValue("\\'"));
+}
+
+TEST(DriveApiUtilTest, TranslateQuery) {
+  EXPECT_EQ("", TranslateQuery(""));
+  EXPECT_EQ("fullText contains 'dog'", TranslateQuery("dog"));
+  EXPECT_EQ("fullText contains 'dog' and fullText contains 'cat'",
+            TranslateQuery("dog cat"));
+  EXPECT_EQ("not fullText contains 'cat'", TranslateQuery("-cat"));
+  EXPECT_EQ("fullText contains 'dog cat'", TranslateQuery("\"dog cat\""));
+
+  // Should handles full-width white space correctly.
+  // Note: \xE3\x80\x80 (\u3000) is Ideographic Space (a.k.a. Japanese
+  //   full-width whitespace).
+  EXPECT_EQ("fullText contains 'dog' and fullText contains 'cat'",
+            TranslateQuery("dog" "\xE3\x80\x80" "cat"));
+
+  // If the quoted token is not closed (i.e. the last '"' is missing),
+  // we handle the remaining string is one token, as a fallback.
+  EXPECT_EQ("fullText contains 'dog cat'", TranslateQuery("\"dog cat"));
+
+  // For quoted text with leading '-'.
+  EXPECT_EQ("not fullText contains 'dog cat'", TranslateQuery("-\"dog cat\""));
+
+  // Empty tokens should be simply ignored.
+  EXPECT_EQ("", TranslateQuery("-"));
+  EXPECT_EQ("", TranslateQuery("\"\""));
+  EXPECT_EQ("", TranslateQuery("-\"\""));
+  EXPECT_EQ("", TranslateQuery("\"\"\"\""));
+  EXPECT_EQ("", TranslateQuery("\"\" \"\""));
+  EXPECT_EQ("fullText contains 'dog'", TranslateQuery("\"\" dog \"\""));
+}
+
+TEST(FileSystemUtilTest, ExtractResourceIdFromUrl) {
+  EXPECT_EQ("file:2_file_resource_id", ExtractResourceIdFromUrl(
+      GURL("https://file1_link_self/file:2_file_resource_id")));
+  // %3A should be unescaped.
+  EXPECT_EQ("file:2_file_resource_id", ExtractResourceIdFromUrl(
+      GURL("https://file1_link_self/file%3A2_file_resource_id")));
+
+  // The resource ID cannot be extracted, hence empty.
+  EXPECT_EQ("", ExtractResourceIdFromUrl(GURL("https://www.example.com/")));
+}
+
+TEST(FileSystemUtilTest, CanonicalizeResourceId) {
+  std::string resource_id("1YsCnrMxxgp7LDdtlFDt-WdtEIth89vA9inrILtvK-Ug");
+
+  // New style ID is unchanged.
+  EXPECT_EQ(resource_id, CanonicalizeResourceId(resource_id));
+
+  // Drop prefixes from old style IDs.
+  EXPECT_EQ(resource_id, CanonicalizeResourceId("document:" + resource_id));
+  EXPECT_EQ(resource_id, CanonicalizeResourceId("spreadsheet:" + resource_id));
+  EXPECT_EQ(resource_id, CanonicalizeResourceId("presentation:" + resource_id));
+  EXPECT_EQ(resource_id, CanonicalizeResourceId("drawing:" + resource_id));
+  EXPECT_EQ(resource_id, CanonicalizeResourceId("table:" + resource_id));
+  EXPECT_EQ(resource_id, CanonicalizeResourceId("externalapp:" + resource_id));
+}
+
+}  // namespace util
+}  // namespace drive
diff --git a/chrome/browser/drive/drive_notification_manager.cc b/chrome/browser/drive/drive_notification_manager.cc
index 7979715..ae94124 100644
--- a/chrome/browser/drive/drive_notification_manager.cc
+++ b/chrome/browser/drive/drive_notification_manager.cc
@@ -5,13 +5,13 @@
 #include "chrome/browser/drive/drive_notification_manager.h"
 
 #include "base/metrics/histogram.h"
-#include "chrome/browser/google_apis/drive_notification_observer.h"
+#include "chrome/browser/drive/drive_notification_observer.h"
+#include "chrome/browser/invalidation/invalidation_service.h"
+#include "chrome/browser/invalidation/invalidation_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/sync/profile_sync_service.h"
-#include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "google/cacheinvalidation/types.pb.h"
 
-namespace google_apis {
+namespace drive {
 
 namespace {
 
@@ -42,15 +42,16 @@
 
 void DriveNotificationManager::Shutdown() {
   // Unregister for Drive notifications.
-  ProfileSyncService* profile_sync_service =
-      ProfileSyncServiceFactory::GetForProfile(profile_);
-  if (!profile_sync_service || !push_notification_registered_) {
+  invalidation::InvalidationService* invalidation_service =
+      invalidation::InvalidationServiceFactory::GetForProfile(profile_);
+  if (!invalidation_service || !push_notification_registered_) {
     return;
   }
 
-  profile_sync_service->UpdateRegisteredInvalidationIds(
-      this, syncer::ObjectIdSet());
-  profile_sync_service->UnregisterInvalidationHandler(this);
+  // We unregister the handler without updating unregistering our IDs on
+  // purpose.  See the class comment on the InvalidationService interface for
+  // more information.
+  invalidation_service->UnregisterInvalidationHandler(this);
 }
 
 void DriveNotificationManager::OnInvalidatorStateChange(
@@ -76,9 +77,10 @@
 
   // TODO(dcheng): Only acknowledge the invalidation once the fetch has
   // completed. http://crbug.com/156843
-  ProfileSyncService* profile_sync_service =
-      ProfileSyncServiceFactory::GetForProfile(profile_);
-  profile_sync_service->AcknowledgeInvalidation(
+  invalidation::InvalidationService* invalidation_service =
+      invalidation::InvalidationServiceFactory::GetForProfile(profile_);
+  DCHECK(invalidation_service);
+  invalidation_service->AcknowledgeInvalidation(
       invalidation_map.begin()->first,
       invalidation_map.begin()->second.ack_handle);
 
@@ -128,19 +130,19 @@
 void DriveNotificationManager::RegisterDriveNotifications() {
   DCHECK(!push_notification_enabled_);
 
-  ProfileSyncService* profile_sync_service =
-      ProfileSyncServiceFactory::GetForProfile(profile_);
-  if (!profile_sync_service)
+  invalidation::InvalidationService* invalidation_service =
+      invalidation::InvalidationServiceFactory::GetForProfile(profile_);
+  if (!invalidation_service)
     return;
 
-  profile_sync_service->RegisterInvalidationHandler(this);
+  invalidation_service->RegisterInvalidationHandler(this);
   syncer::ObjectIdSet ids;
   ids.insert(invalidation::ObjectId(
       ipc::invalidation::ObjectSource::COSMO_CHANGELOG,
       kDriveInvalidationObjectId));
-  profile_sync_service->UpdateRegisteredInvalidationIds(this, ids);
+  invalidation_service->UpdateRegisteredInvalidationIds(this, ids);
   push_notification_registered_ = true;
-  OnInvalidatorStateChange(profile_sync_service->GetInvalidatorState());
+  OnInvalidatorStateChange(invalidation_service->GetInvalidatorState());
 
   UMA_HISTOGRAM_BOOLEAN("Drive.PushNotificationRegistered",
                         push_notification_registered_);
@@ -160,4 +162,4 @@
   return "";
 }
 
-}  // namespace google_apis
+}  // namespace drive
diff --git a/chrome/browser/drive/drive_notification_manager.h b/chrome/browser/drive/drive_notification_manager.h
index 007709a..f519a41 100644
--- a/chrome/browser/drive/drive_notification_manager.h
+++ b/chrome/browser/drive/drive_notification_manager.h
@@ -7,15 +7,15 @@
 
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
-#include "base/timer.h"
-#include "chrome/browser/google_apis/drive_notification_observer.h"
+#include "base/timer/timer.h"
+#include "chrome/browser/drive/drive_notification_observer.h"
 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
 #include "sync/notifier/invalidation_handler.h"
 
 class Profile;
 class ProfileSyncService;
 
-namespace google_apis {
+namespace drive {
 
 // Informs observers when they should check Google Drive for updates.
 // Conditions under which updates should be searched:
@@ -90,6 +90,6 @@
   DISALLOW_COPY_AND_ASSIGN(DriveNotificationManager);
 };
 
-}  // namespace google_apis
+}  // namespace drive
 
 #endif  // CHROME_BROWSER_DRIVE_DRIVE_NOTIFICATION_MANAGER_H_
diff --git a/chrome/browser/drive/drive_notification_manager_factory.cc b/chrome/browser/drive/drive_notification_manager_factory.cc
index cebea28..4792e08 100644
--- a/chrome/browser/drive/drive_notification_manager_factory.cc
+++ b/chrome/browser/drive/drive_notification_manager_factory.cc
@@ -5,12 +5,13 @@
 #include "chrome/browser/drive/drive_notification_manager_factory.h"
 
 #include "chrome/browser/drive/drive_notification_manager.h"
+#include "chrome/browser/invalidation/invalidation_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sync/profile_sync_service.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
 
-namespace google_apis {
+namespace drive {
 
 // static
 DriveNotificationManager*
@@ -33,6 +34,7 @@
         "DriveNotificationManager",
         BrowserContextDependencyManager::GetInstance()) {
   DependsOn(ProfileSyncServiceFactory::GetInstance());
+  DependsOn(invalidation::InvalidationServiceFactory::GetInstance());
 }
 
 DriveNotificationManagerFactory::~DriveNotificationManagerFactory() {}
@@ -43,4 +45,4 @@
   return new DriveNotificationManager(static_cast<Profile*>(profile));
 }
 
-}  // namespace google_apis
+}  // namespace drive
diff --git a/chrome/browser/drive/drive_notification_manager_factory.h b/chrome/browser/drive/drive_notification_manager_factory.h
index b273577..65340d0 100644
--- a/chrome/browser/drive/drive_notification_manager_factory.h
+++ b/chrome/browser/drive/drive_notification_manager_factory.h
@@ -10,7 +10,7 @@
 
 class Profile;
 
-namespace google_apis {
+namespace drive {
 
 class DriveNotificationManager;
 
@@ -34,6 +34,6 @@
       content::BrowserContext* profile) const OVERRIDE;
 };
 
-}  // namespace google_apis
+}  // namespace drive
 
 #endif  // CHROME_BROWSER_DRIVE_DRIVE_NOTIFICATION_MANAGER_FACTORY_H_
diff --git a/chrome/browser/drive/drive_notification_observer.h b/chrome/browser/drive/drive_notification_observer.h
new file mode 100644
index 0000000..5f6738f
--- /dev/null
+++ b/chrome/browser/drive/drive_notification_observer.h
@@ -0,0 +1,26 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_DRIVE_DRIVE_NOTIFICATION_OBSERVER_H_
+#define CHROME_BROWSER_DRIVE_DRIVE_NOTIFICATION_OBSERVER_H_
+
+namespace drive {
+
+// Interface for classes which need to know when to check Google Drive for
+// updates.
+class DriveNotificationObserver {
+ public:
+  // Called when a notification from Google Drive is received.
+  virtual void OnNotificationReceived() = 0;
+
+  // Called when XMPP-based push notification is enabled or disabled.
+  virtual void OnPushNotificationEnabled(bool enabled) {}
+
+ protected:
+  virtual ~DriveNotificationObserver() {}
+};
+
+}  // namespace drive
+
+#endif  // CHROME_BROWSER_DRIVE_DRIVE_NOTIFICATION_OBSERVER_H_
diff --git a/chrome/browser/drive/drive_service_interface.h b/chrome/browser/drive/drive_service_interface.h
index 774de4f..f792d24 100644
--- a/chrome/browser/drive/drive_service_interface.h
+++ b/chrome/browser/drive/drive_service_interface.h
@@ -12,7 +12,7 @@
 
 class Profile;
 
-namespace google_apis {
+namespace drive {
 
 // Observer interface for DriveServiceInterface.
 class DriveServiceObserver {
@@ -80,8 +80,8 @@
   // ContinueGetResourceList.
   //
   // |callback| must not be null.
-  virtual CancelCallback GetAllResourceList(
-      const GetResourceListCallback& callback) = 0;
+  virtual google_apis::CancelCallback GetAllResourceList(
+      const google_apis::GetResourceListCallback& callback) = 0;
 
   // Fetches a resource list in the directory with |directory_resource_id|.
   // |callback| will be called upon completion.
@@ -91,9 +91,9 @@
   //
   // |directory_resource_id| must not be empty.
   // |callback| must not be null.
-  virtual CancelCallback GetResourceListInDirectory(
+  virtual google_apis::CancelCallback GetResourceListInDirectory(
       const std::string& directory_resource_id,
-      const GetResourceListCallback& callback) = 0;
+      const google_apis::GetResourceListCallback& callback) = 0;
 
   // Searches the resources for the |search_query| from all the user's
   // resources. |callback| will be called upon completion.
@@ -103,9 +103,9 @@
   //
   // |search_query| must not be empty.
   // |callback| must not be null.
-  virtual CancelCallback Search(
+  virtual google_apis::CancelCallback Search(
       const std::string& search_query,
-      const GetResourceListCallback& callback) = 0;
+      const google_apis::GetResourceListCallback& callback) = 0;
 
   // Searches the resources with the |title|.
   // |directory_resource_id| is an optional parameter. If it is empty,
@@ -116,10 +116,10 @@
   // ContinueGetResourceList.
   //
   // |title| must not be empty, and |callback| must not be null.
-  virtual CancelCallback SearchByTitle(
+  virtual google_apis::CancelCallback SearchByTitle(
       const std::string& title,
       const std::string& directory_resource_id,
-      const GetResourceListCallback& callback) = 0;
+      const google_apis::GetResourceListCallback& callback) = 0;
 
   // Fetches change list since |start_changestamp|. |callback| will be
   // called upon completion.
@@ -128,9 +128,9 @@
   // ContinueGetResourceList.
   //
   // |callback| must not be null.
-  virtual CancelCallback GetChangeList(
+  virtual google_apis::CancelCallback GetChangeList(
       int64 start_changestamp,
-      const GetResourceListCallback& callback) = 0;
+      const google_apis::GetResourceListCallback& callback) = 0;
 
   // Requests returning GetResourceList may be paged. In such a case,
   // a URL to fetch remaining result is returned. The URL can be used for this
@@ -138,38 +138,39 @@
   //
   // |override_url| must not be empty.
   // |callback| must not be null.
-  virtual CancelCallback ContinueGetResourceList(
+  virtual google_apis::CancelCallback ContinueGetResourceList(
       const GURL& override_url,
-      const GetResourceListCallback& callback) = 0;
+      const google_apis::GetResourceListCallback& callback) = 0;
 
   // Fetches single entry metadata from server. The entry's resource id equals
   // |resource_id|.
   // Upon completion, invokes |callback| with results on the calling thread.
   // |callback| must not be null.
-  virtual CancelCallback GetResourceEntry(
+  virtual google_apis::CancelCallback GetResourceEntry(
       const std::string& resource_id,
-      const GetResourceEntryCallback& callback) = 0;
+      const google_apis::GetResourceEntryCallback& callback) = 0;
 
   // Gets the about resource information from the server.
   // Upon completion, invokes |callback| with results on the calling thread.
   // |callback| must not be null.
-  virtual CancelCallback GetAboutResource(
-      const GetAboutResourceCallback& callback) = 0;
+  virtual google_apis::CancelCallback GetAboutResource(
+      const google_apis::GetAboutResourceCallback& callback) = 0;
 
   // Gets the application information from the server.
   // Upon completion, invokes |callback| with results on the calling thread.
   // |callback| must not be null.
-  virtual CancelCallback GetAppList(const GetAppListCallback& callback) = 0;
+  virtual google_apis::CancelCallback GetAppList(
+      const google_apis::GetAppListCallback& callback) = 0;
 
   // Deletes a resource identified by its |resource_id|.
   // If |etag| is not empty and did not match, the deletion fails with
   // HTTP_PRECONDITION error.
   // Upon completion, invokes |callback| with results on the calling thread.
   // |callback| must not be null.
-  virtual CancelCallback DeleteResource(
+  virtual google_apis::CancelCallback DeleteResource(
       const std::string& resource_id,
       const std::string& etag,
-      const EntryActionCallback& callback) = 0;
+      const google_apis::EntryActionCallback& callback) = 0;
 
   // Makes a copy of a resource with |resource_id|.
   // The new resource will be put under a directory with |parent_resource_id|,
@@ -178,11 +179,11 @@
   // doesn't support the function unfortunately.
   // Upon completion, invokes |callback| with results on the calling thread.
   // |callback| must not be null.
-  virtual CancelCallback CopyResource(
+  virtual google_apis::CancelCallback CopyResource(
       const std::string& resource_id,
       const std::string& parent_resource_id,
       const std::string& new_name,
-      const GetResourceEntryCallback& callback) = 0;
+      const google_apis::GetResourceEntryCallback& callback) = 0;
 
   // Makes a copy of a hosted document identified by its |resource_id|.
   // The copy is named as the UTF-8 encoded |new_name| and is not added to any
@@ -192,47 +193,48 @@
   // |callback| must not be null.
   // TODO(hidehiko): After the migration to Drive API v2, remove this method,
   // because we can use CopyResource instead.
-  virtual CancelCallback CopyHostedDocument(
+  virtual google_apis::CancelCallback CopyHostedDocument(
       const std::string& resource_id,
       const std::string& new_name,
-      const GetResourceEntryCallback& callback) = 0;
+      const google_apis::GetResourceEntryCallback& callback) = 0;
 
   // Renames a document or collection identified by its |resource_id|
   // to the UTF-8 encoded |new_name|. Upon completion,
   // invokes |callback| with results on the calling thread.
   // |callback| must not be null.
-  virtual CancelCallback RenameResource(const std::string& resource_id,
-                                       const std::string& new_name,
-                                       const EntryActionCallback& callback) = 0;
+  virtual google_apis::CancelCallback RenameResource(
+      const std::string& resource_id,
+      const std::string& new_name,
+      const google_apis::EntryActionCallback& callback) = 0;
 
   // Touches the resource with |resource_id|.
   // Its modifiedDate and lastViewedByMeDate fields on the server will be
   // updated to |modified_date| and |last_viewed_by_me_date| respectively.
   // Upon completion, invokes |callback| with the updated resource data.
   // |modified_date|, |last_viewed_by_me_date| and |callback| must not be null.
-  virtual CancelCallback TouchResource(
+  virtual google_apis::CancelCallback TouchResource(
       const std::string& resource_id,
       const base::Time& modified_date,
       const base::Time& last_viewed_by_me_date,
-      const GetResourceEntryCallback& callback) = 0;
+      const google_apis::GetResourceEntryCallback& callback) = 0;
 
   // Adds a resource (document, file, or collection) identified by its
   // |resource_id| to a collection represented by the |parent_resource_id|.
   // Upon completion, invokes |callback| with results on the calling thread.
   // |callback| must not be null.
-  virtual CancelCallback AddResourceToDirectory(
+  virtual google_apis::CancelCallback AddResourceToDirectory(
       const std::string& parent_resource_id,
       const std::string& resource_id,
-      const EntryActionCallback& callback) = 0;
+      const google_apis::EntryActionCallback& callback) = 0;
 
   // Removes a resource (document, file, collection) identified by its
   // |resource_id| from a collection represented by the |parent_resource_id|.
   // Upon completion, invokes |callback| with results on the calling thread.
   // |callback| must not be null.
-  virtual CancelCallback RemoveResourceFromDirectory(
+  virtual google_apis::CancelCallback RemoveResourceFromDirectory(
       const std::string& parent_resource_id,
       const std::string& resource_id,
-      const EntryActionCallback& callback) = 0;
+      const google_apis::EntryActionCallback& callback) = 0;
 
   // Adds new collection with |directory_name| under parent directory
   // identified with |parent_resource_id|. |parent_resource_id| can be the
@@ -242,12 +244,12 @@
   // This function cannot be named as "CreateDirectory" as it conflicts with
   // a macro on Windows.
   // |callback| must not be null.
-  virtual CancelCallback AddNewDirectory(
+  virtual google_apis::CancelCallback AddNewDirectory(
       const std::string& parent_resource_id,
       const std::string& directory_name,
-      const GetResourceEntryCallback& callback) = 0;
+      const google_apis::GetResourceEntryCallback& callback) = 0;
 
-  // Downloads a file from |download_url|. The downloaded file will
+  // Downloads a file with |resourced_id|. The downloaded file will
   // be stored at |local_cache_path| location. Upon completion, invokes
   // |download_action_callback| with results on the calling thread.
   // If |get_content_callback| is not empty,
@@ -258,70 +260,65 @@
   //
   // |download_action_callback| must not be null.
   // |get_content_callback| and |progress_callback| may be null.
-  virtual CancelCallback DownloadFile(
-      const base::FilePath& virtual_path,
+  virtual google_apis::CancelCallback DownloadFile(
       const base::FilePath& local_cache_path,
-      const GURL& download_url,
-      const DownloadActionCallback& download_action_callback,
-      const GetContentCallback& get_content_callback,
-      const ProgressCallback& progress_callback) = 0;
+      const std::string& resource_id,
+      const google_apis::DownloadActionCallback& download_action_callback,
+      const google_apis::GetContentCallback& get_content_callback,
+      const google_apis::ProgressCallback& progress_callback) = 0;
 
   // Initiates uploading of a new document/file.
   // |content_type| and |content_length| should be the ones of the file to be
   // uploaded.
   // |callback| must not be null.
-  virtual CancelCallback InitiateUploadNewFile(
-      const base::FilePath& drive_file_path,
+  virtual google_apis::CancelCallback InitiateUploadNewFile(
       const std::string& content_type,
       int64 content_length,
       const std::string& parent_resource_id,
       const std::string& title,
-      const InitiateUploadCallback& callback) = 0;
+      const google_apis::InitiateUploadCallback& callback) = 0;
 
   // Initiates uploading of an existing document/file.
   // |content_type| and |content_length| should be the ones of the file to be
   // uploaded.
   // |callback| must not be null.
-  virtual CancelCallback InitiateUploadExistingFile(
-      const base::FilePath& drive_file_path,
+  virtual google_apis::CancelCallback InitiateUploadExistingFile(
       const std::string& content_type,
       int64 content_length,
       const std::string& resource_id,
       const std::string& etag,
-      const InitiateUploadCallback& callback) = 0;
+      const google_apis::InitiateUploadCallback& callback) = 0;
 
   // Resumes uploading of a document/file on the calling thread.
   // |callback| must not be null. |progress_callback| may be null.
-  virtual CancelCallback ResumeUpload(
-      const base::FilePath& drive_file_path,
+  virtual google_apis::CancelCallback ResumeUpload(
       const GURL& upload_url,
       int64 start_position,
       int64 end_position,
       int64 content_length,
       const std::string& content_type,
       const base::FilePath& local_file_path,
-      const UploadRangeCallback& callback,
-      const ProgressCallback& progress_callback) = 0;
+      const google_apis::UploadRangeCallback& callback,
+      const google_apis::ProgressCallback& progress_callback) = 0;
 
   // Gets the current status of the uploading to |upload_url| from the server.
   // |drive_file_path| and |content_length| should be set to the same value
   // which is used for ResumeUpload.
   // |callback| must not be null.
-  virtual CancelCallback GetUploadStatus(
-      const base::FilePath& drive_file_path,
+  virtual google_apis::CancelCallback GetUploadStatus(
       const GURL& upload_url,
       int64 content_length,
-      const UploadRangeCallback& callback) = 0;
+      const google_apis::UploadRangeCallback& callback) = 0;
 
   // Authorizes a Drive app with the id |app_id| to open the given file.
   // Upon completion, invokes |callback| with the link to open the file with
   // the provided app. |callback| must not be null.
-  virtual CancelCallback AuthorizeApp(
+  virtual google_apis::CancelCallback AuthorizeApp(
       const std::string& resource_id,
       const std::string& app_id,
-      const AuthorizeAppCallback& callback) = 0;
+      const google_apis::AuthorizeAppCallback& callback) = 0;
 };
 
-}  // namespace google_apis
+}  // namespace drive
 
 #endif  // CHROME_BROWSER_DRIVE_DRIVE_SERVICE_INTERFACE_H_
diff --git a/chrome/browser/drive/drive_switches.cc b/chrome/browser/drive/drive_switches.cc
new file mode 100644
index 0000000..0505a00
--- /dev/null
+++ b/chrome/browser/drive/drive_switches.cc
@@ -0,0 +1,14 @@
+// Copyright 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/drive/drive_switches.h"
+
+namespace drive {
+namespace switches {
+
+// Enables Drive v2 API instead of Google Documents List API.
+const char kEnableDriveV2Api[] = "enable-drive-v2-api";
+
+}  // namespace switches
+}  // namespace drive
diff --git a/chrome/browser/drive/drive_switches.h b/chrome/browser/drive/drive_switches.h
new file mode 100644
index 0000000..59282e4
--- /dev/null
+++ b/chrome/browser/drive/drive_switches.h
@@ -0,0 +1,16 @@
+// Copyright 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_DRIVE_DRIVE_SWITCHES_H_
+#define CHROME_BROWSER_DRIVE_DRIVE_SWITCHES_H_
+
+namespace drive {
+namespace switches {
+
+extern const char kEnableDriveV2Api[];
+
+}  // namespace switches
+}  // namespace drive
+
+#endif  // CHROME_BROWSER_DRIVE_DRIVE_SWITCHES_H_
diff --git a/chrome/browser/drive/drive_uploader.cc b/chrome/browser/drive/drive_uploader.cc
index 4f9247a..0d4866a 100644
--- a/chrome/browser/drive/drive_uploader.cc
+++ b/chrome/browser/drive/drive_uploader.cc
@@ -11,26 +11,37 @@
 #include "base/file_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/task_runner_util.h"
-#include "base/threading/sequenced_worker_pool.h"
 #include "chrome/browser/drive/drive_service_interface.h"
 #include "chrome/browser/google_apis/gdata_wapi_parser.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/power_save_blocker.h"
 
 using content::BrowserThread;
+using google_apis::CancelCallback;
+using google_apis::GDATA_CANCELLED;
+using google_apis::GDataErrorCode;
+using google_apis::GDATA_NO_SPACE;
+using google_apis::HTTP_CONFLICT;
+using google_apis::HTTP_CREATED;
+using google_apis::HTTP_FORBIDDEN;
+using google_apis::HTTP_NOT_FOUND;
+using google_apis::HTTP_PRECONDITION;
+using google_apis::HTTP_RESUME_INCOMPLETE;
+using google_apis::HTTP_SUCCESS;
+using google_apis::ProgressCallback;
+using google_apis::ResourceEntry;
+using google_apis::UploadRangeResponse;
 
-namespace google_apis {
+namespace drive {
 
 // Structure containing current upload information of file, passed between
 // DriveServiceInterface methods and callbacks.
 struct DriveUploader::UploadFileInfo {
-  UploadFileInfo(const base::FilePath& drive_path,
-                 const base::FilePath& local_path,
+  UploadFileInfo(const base::FilePath& local_path,
                  const std::string& content_type,
                  const UploadCompletionCallback& callback,
                  const ProgressCallback& progress_callback)
-      : drive_path(drive_path),
-        file_path(local_path),
+      : file_path(local_path),
         content_type(content_type),
         completion_callback(callback),
         progress_callback(progress_callback),
@@ -50,7 +61,6 @@
     return "file_path=[" + file_path.AsUTF8Unsafe() +
            "], content_type=[" + content_type +
            "], content_length=[" + base::UintToString(content_length) +
-           "], drive_path=[" + drive_path.AsUTF8Unsafe() +
            "]";
   }
 
@@ -59,9 +69,6 @@
     return base::Bind(&UploadFileInfo::Cancel, weak_ptr_factory_.GetWeakPtr());
   }
 
-  // Final path in gdata. Looks like /special/drive/MyFolder/MyFile.
-  const base::FilePath drive_path;
-
   // The local file path of the file to be uploaded.
   const base::FilePath file_path;
 
@@ -105,8 +112,10 @@
   DISALLOW_COPY_AND_ASSIGN(UploadFileInfo);
 };
 
-DriveUploader::DriveUploader(DriveServiceInterface* drive_service)
+DriveUploader::DriveUploader(DriveServiceInterface* drive_service,
+                             base::TaskRunner* blocking_task_runner)
     : drive_service_(drive_service),
+      blocking_task_runner_(blocking_task_runner),
       weak_ptr_factory_(this) {
 }
 
@@ -114,7 +123,6 @@
 
 CancelCallback DriveUploader::UploadNewFile(
     const std::string& parent_resource_id,
-    const base::FilePath& drive_file_path,
     const base::FilePath& local_file_path,
     const std::string& title,
     const std::string& content_type,
@@ -122,15 +130,13 @@
     const ProgressCallback& progress_callback) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(!parent_resource_id.empty());
-  DCHECK(!drive_file_path.empty());
   DCHECK(!local_file_path.empty());
   DCHECK(!title.empty());
   DCHECK(!content_type.empty());
   DCHECK(!callback.is_null());
 
   return StartUploadFile(
-      scoped_ptr<UploadFileInfo>(new UploadFileInfo(drive_file_path,
-                                                    local_file_path,
+      scoped_ptr<UploadFileInfo>(new UploadFileInfo(local_file_path,
                                                     content_type,
                                                     callback,
                                                     progress_callback)),
@@ -142,7 +148,6 @@
 
 CancelCallback DriveUploader::UploadExistingFile(
     const std::string& resource_id,
-    const base::FilePath& drive_file_path,
     const base::FilePath& local_file_path,
     const std::string& content_type,
     const std::string& etag,
@@ -150,14 +155,12 @@
     const ProgressCallback& progress_callback) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(!resource_id.empty());
-  DCHECK(!drive_file_path.empty());
   DCHECK(!local_file_path.empty());
   DCHECK(!content_type.empty());
   DCHECK(!callback.is_null());
 
   return StartUploadFile(
-      scoped_ptr<UploadFileInfo>(new UploadFileInfo(drive_file_path,
-                                                    local_file_path,
+      scoped_ptr<UploadFileInfo>(new UploadFileInfo(local_file_path,
                                                     content_type,
                                                     callback,
                                                     progress_callback)),
@@ -169,19 +172,17 @@
 
 CancelCallback DriveUploader::ResumeUploadFile(
     const GURL& upload_location,
-    const base::FilePath& drive_file_path,
     const base::FilePath& local_file_path,
     const std::string& content_type,
     const UploadCompletionCallback& callback,
     const ProgressCallback& progress_callback) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  DCHECK(!drive_file_path.empty());
   DCHECK(!local_file_path.empty());
   DCHECK(!content_type.empty());
   DCHECK(!callback.is_null());
 
   scoped_ptr<UploadFileInfo> upload_file_info(new UploadFileInfo(
-      drive_file_path, local_file_path, content_type,
+      local_file_path, content_type,
       callback, progress_callback));
   upload_file_info->upload_location = upload_location;
 
@@ -199,9 +200,10 @@
 
   UploadFileInfo* info_ptr = upload_file_info.get();
   base::PostTaskAndReplyWithResult(
-      BrowserThread::GetBlockingPool(),
+      blocking_task_runner_.get(),
       FROM_HERE,
-      base::Bind(&file_util::GetFileSize, info_ptr->file_path,
+      base::Bind(&file_util::GetFileSize,
+                 info_ptr->file_path,
                  &info_ptr->content_length),
       base::Bind(&DriveUploader::StartUploadFileAfterGetFileSize,
                  weak_ptr_factory_.GetWeakPtr(),
@@ -237,7 +239,6 @@
 
   UploadFileInfo* info_ptr = upload_file_info.get();
   info_ptr->cancel_callback = drive_service_->InitiateUploadNewFile(
-      info_ptr->drive_path,
       info_ptr->content_type,
       info_ptr->content_length,
       parent_resource_id,
@@ -255,7 +256,6 @@
 
   UploadFileInfo* info_ptr = upload_file_info.get();
   info_ptr->cancel_callback = drive_service_->InitiateUploadExistingFile(
-      info_ptr->drive_path,
       info_ptr->content_type,
       info_ptr->content_length,
       resource_id,
@@ -272,7 +272,7 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   DVLOG(1) << "Got upload location [" << upload_location.spec()
-           << "] for [" << upload_file_info->drive_path.value() << "]";
+           << "] for [" << upload_file_info->file_path.value() << "]";
 
   if (code != HTTP_SUCCESS) {
     // TODO(achuith): Handle error codes from Google Docs server.
@@ -296,7 +296,6 @@
 
   UploadFileInfo* info_ptr = upload_file_info.get();
   info_ptr->cancel_callback = drive_service_->GetUploadStatus(
-      info_ptr->drive_path,
       info_ptr->upload_location,
       info_ptr->content_length,
       base::Bind(&DriveUploader::OnUploadRangeResponseReceived,
@@ -319,7 +318,6 @@
 
   UploadFileInfo* info_ptr = upload_file_info.get();
   info_ptr->cancel_callback = drive_service_->ResumeUpload(
-      info_ptr->drive_path,
       info_ptr->upload_location,
       start_position,
       info_ptr->content_length,
@@ -353,7 +351,7 @@
     // TODO(hidehiko): Upload metadata only for empty files, after GData WAPI
     // code is gone.
     DVLOG(1) << "Successfully created uploaded file=["
-             << upload_file_info->drive_path.value() << "]";
+             << upload_file_info->file_path.value() << "]";
 
     // Done uploading.
     upload_file_info->completion_callback.Run(
@@ -384,7 +382,7 @@
 
   DVLOG(1) << "Received range " << response.start_position_received
            << "-" << response.end_position_received
-           << " for [" << upload_file_info->drive_path.value() << "]";
+           << " for [" << upload_file_info->file_path.value() << "]";
 
   UploadNextChunk(upload_file_info.Pass(), response.end_position_received);
 }
@@ -408,4 +406,4 @@
       error, upload_file_info->upload_location, scoped_ptr<ResourceEntry>());
 }
 
-}  // namespace google_apis
+}  // namespace drive
diff --git a/chrome/browser/drive/drive_uploader.h b/chrome/browser/drive/drive_uploader.h
index d93b2f3..cb8bc80 100644
--- a/chrome/browser/drive/drive_uploader.h
+++ b/chrome/browser/drive/drive_uploader.h
@@ -9,6 +9,7 @@
 
 #include "base/basictypes.h"
 #include "base/callback_forward.h"
+#include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/drive/drive_service_interface.h"
 #include "chrome/browser/google_apis/gdata_errorcode.h"
@@ -18,19 +19,24 @@
 
 namespace base {
 class FilePath;
+class TaskRunner;
 }
 
 namespace google_apis {
-class DriveServiceInterface;
 struct UploadRangeResponse;
+}
+
+namespace drive {
+class DriveServiceInterface;
 
 // Callback to be invoked once the upload has completed.
 // |upload_location| will be returned when the uploading process is started but
 // terminated before the completion due to some errors. It can be used to
 // resume it.
-typedef base::Callback<void(GDataErrorCode error,
-                            const GURL& upload_location,
-                            scoped_ptr<ResourceEntry> resource_entry)>
+typedef base::Callback<void(
+    google_apis::GDataErrorCode error,
+    const GURL& upload_location,
+    scoped_ptr<google_apis::ResourceEntry> resource_entry)>
     UploadCompletionCallback;
 
 class DriveUploaderInterface {
@@ -43,9 +49,6 @@
   // parent_resource_id:
   //   resource id of the destination directory.
   //
-  // drive_file_path:
-  //   The destination path like "drive/foo/bar.txt".
-  //
   // local_file_path:
   //   The path to the local file to be uploaded.
   //
@@ -62,14 +65,13 @@
   // progress_callback:
   //   Periodically called back with the total number of bytes sent so far.
   //   May be null if the information is not needed.
-  virtual CancelCallback UploadNewFile(
+  virtual google_apis::CancelCallback UploadNewFile(
       const std::string& parent_resource_id,
-      const base::FilePath& drive_file_path,
       const base::FilePath& local_file_path,
       const std::string& title,
       const std::string& content_type,
       const UploadCompletionCallback& callback,
-      const ProgressCallback& progress_callback) = 0;
+      const google_apis::ProgressCallback& progress_callback) = 0;
 
   // Uploads an existing file (a file that already exists on Drive).
   //
@@ -82,14 +84,13 @@
   //   Expected ETag for the destination file. If it does not match, the upload
   //   fails with UPLOAD_ERROR_CONFLICT.
   //   If |etag| is empty, the test is skipped.
-  virtual CancelCallback UploadExistingFile(
+  virtual google_apis::CancelCallback UploadExistingFile(
       const std::string& resource_id,
-      const base::FilePath& drive_file_path,
       const base::FilePath& local_file_path,
       const std::string& content_type,
       const std::string& etag,
       const UploadCompletionCallback& callback,
-      const ProgressCallback& progress_callback) = 0;
+      const google_apis::ProgressCallback& progress_callback) = 0;
 
   // Resumes the uploading process terminated before the completion.
   // |upload_location| should be the one returned via UploadCompletionCallback
@@ -97,44 +98,41 @@
   // |content_type| must be set to the same ones for previous invocation.
   //
   // See comments at UploadNewFile about common parameters and the return value.
-  virtual CancelCallback ResumeUploadFile(
+  virtual google_apis::CancelCallback ResumeUploadFile(
       const GURL& upload_location,
-      const base::FilePath& drive_file_path,
       const base::FilePath& local_file_path,
       const std::string& content_type,
       const UploadCompletionCallback& callback,
-      const ProgressCallback& progress_callback) = 0;
+      const google_apis::ProgressCallback& progress_callback) = 0;
 };
 
 class DriveUploader : public DriveUploaderInterface {
  public:
-  explicit DriveUploader(DriveServiceInterface* drive_service);
+  DriveUploader(DriveServiceInterface* drive_service,
+                base::TaskRunner* blocking_task_runner);
   virtual ~DriveUploader();
 
   // DriveUploaderInterface overrides.
-  virtual CancelCallback UploadNewFile(
+  virtual google_apis::CancelCallback UploadNewFile(
       const std::string& parent_resource_id,
-      const base::FilePath& drive_file_path,
       const base::FilePath& local_file_path,
       const std::string& title,
       const std::string& content_type,
       const UploadCompletionCallback& callback,
-      const ProgressCallback& progress_callback) OVERRIDE;
-  virtual CancelCallback UploadExistingFile(
+      const google_apis::ProgressCallback& progress_callback) OVERRIDE;
+  virtual google_apis::CancelCallback UploadExistingFile(
       const std::string& resource_id,
-      const base::FilePath& drive_file_path,
       const base::FilePath& local_file_path,
       const std::string& content_type,
       const std::string& etag,
       const UploadCompletionCallback& callback,
-      const ProgressCallback& progress_callback) OVERRIDE;
-  virtual CancelCallback ResumeUploadFile(
+      const google_apis::ProgressCallback& progress_callback) OVERRIDE;
+  virtual google_apis::CancelCallback ResumeUploadFile(
       const GURL& upload_location,
-      const base::FilePath& drive_file_path,
       const base::FilePath& local_file_path,
       const std::string& content_type,
       const UploadCompletionCallback& callback,
-      const ProgressCallback& progress_callback) OVERRIDE;
+      const google_apis::ProgressCallback& progress_callback) OVERRIDE;
 
  private:
   struct UploadFileInfo;
@@ -142,7 +140,7 @@
       StartInitiateUploadCallback;
 
   // Starts uploading a file with |upload_file_info|.
-  CancelCallback StartUploadFile(
+  google_apis::CancelCallback StartUploadFile(
       scoped_ptr<UploadFileInfo> upload_file_info,
       const StartInitiateUploadCallback& start_initiate_upload_callback);
   void StartUploadFileAfterGetFileSize(
@@ -166,7 +164,7 @@
 
   // DriveService callback for InitiateUpload.
   void OnUploadLocationReceived(scoped_ptr<UploadFileInfo> upload_file_info,
-                                GDataErrorCode code,
+                                google_apis::GDataErrorCode code,
                                 const GURL& upload_location);
 
   // Starts to get the current upload status for the file uploading.
@@ -180,9 +178,9 @@
   // DriveService callback for ResumeUpload.
   void OnUploadRangeResponseReceived(
       scoped_ptr<UploadFileInfo> upload_file_info,
-      const UploadRangeResponse& response,
-      scoped_ptr<ResourceEntry> entry);
-  void OnUploadProgress(const ProgressCallback& callback,
+      const google_apis::UploadRangeResponse& response,
+      scoped_ptr<google_apis::ResourceEntry> entry);
+  void OnUploadProgress(const google_apis::ProgressCallback& callback,
                         int64 start_position,
                         int64 total_size,
                         int64 progress_of_chunk,
@@ -190,18 +188,20 @@
 
   // Handle failed uploads.
   void UploadFailed(scoped_ptr<UploadFileInfo> upload_file_info,
-                    GDataErrorCode error);
+                    google_apis::GDataErrorCode error);
 
   // The lifetime of this object should be guaranteed to exceed that of the
   // DriveUploader instance.
   DriveServiceInterface* drive_service_;  // Not owned by this class.
 
+  scoped_refptr<base::TaskRunner> blocking_task_runner_;
+
   // Note: This should remain the last member so it'll be destroyed and
   // invalidate its weak pointers before any other members are destroyed.
   base::WeakPtrFactory<DriveUploader> weak_ptr_factory_;
   DISALLOW_COPY_AND_ASSIGN(DriveUploader);
 };
 
-}  // namespace google_apis
+}  // namespace drive
 
 #endif  // CHROME_BROWSER_DRIVE_DRIVE_UPLOADER_H_
diff --git a/chrome/browser/drive/drive_uploader_unittest.cc b/chrome/browser/drive/drive_uploader_unittest.cc
index 363e5af..117cdba 100644
--- a/chrome/browser/drive/drive_uploader_unittest.cc
+++ b/chrome/browser/drive/drive_uploader_unittest.cc
@@ -4,29 +4,43 @@
 
 #include "chrome/browser/drive/drive_uploader.h"
 
-#include <algorithm>
-#include <cstdlib>
 #include <string>
-#include <utility>
 #include <vector>
 
 #include "base/bind.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/message_loop.h"
+#include "base/run_loop.h"
 #include "base/values.h"
 #include "chrome/browser/drive/dummy_drive_service.h"
 #include "chrome/browser/google_apis/test_util.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace google_apis {
+using google_apis::CancelCallback;
+using google_apis::GDataErrorCode;
+using google_apis::GDATA_NO_CONNECTION;
+using google_apis::GDATA_OTHER_ERROR;
+using google_apis::HTTP_CONFLICT;
+using google_apis::HTTP_CREATED;
+using google_apis::HTTP_NOT_FOUND;
+using google_apis::HTTP_PRECONDITION;
+using google_apis::HTTP_RESUME_INCOMPLETE;
+using google_apis::HTTP_SUCCESS;
+using google_apis::InitiateUploadCallback;
+using google_apis::ProgressCallback;
+using google_apis::ResourceEntry;
+using google_apis::UploadRangeCallback;
+using google_apis::UploadRangeResponse;
+namespace test_util = google_apis::test_util;
+
+namespace drive {
 
 namespace {
 
 const char kTestDummyId[] = "file:dummy_id";
 const char kTestDocumentTitle[] = "Hello world";
-const char kTestDrivePath[] = "drive/dummy.txt";
 const char kTestInitiateUploadParentResourceId[] = "parent_resource_id";
 const char kTestInitiateUploadResourceId[] = "resource_id";
 const char kTestMimeType[] = "text/plain";
@@ -61,7 +75,6 @@
   // DriveServiceInterface overrides.
   // Handles a request for obtaining an upload location URL.
   virtual CancelCallback InitiateUploadNewFile(
-      const base::FilePath& drive_file_path,
       const std::string& content_type,
       int64 content_length,
       const std::string& parent_resource_id,
@@ -80,7 +93,6 @@
   }
 
   virtual CancelCallback InitiateUploadExistingFile(
-      const base::FilePath& drive_file_path,
       const std::string& content_type,
       int64 content_length,
       const std::string& resource_id,
@@ -105,7 +117,6 @@
 
   // Handles a request for uploading a chunk of bytes.
   virtual CancelCallback ResumeUpload(
-      const base::FilePath& drive_file_path,
       const GURL& upload_location,
       int64 start_position,
       int64 end_position,
@@ -150,7 +161,6 @@
 
   // Handles a request to fetch the current upload status.
   virtual CancelCallback GetUploadStatus(
-      const base::FilePath& drive_file_path,
       const GURL& upload_location,
       int64 content_length,
       const UploadRangeCallback& callback) OVERRIDE {
@@ -197,7 +207,6 @@
 class MockDriveServiceNoConnectionAtInitiate : public DummyDriveService {
   // Returns error.
   virtual CancelCallback InitiateUploadNewFile(
-      const base::FilePath& drive_file_path,
       const std::string& content_type,
       int64 content_length,
       const std::string& parent_resource_id,
@@ -209,7 +218,6 @@
   }
 
   virtual CancelCallback InitiateUploadExistingFile(
-      const base::FilePath& drive_file_path,
       const std::string& content_type,
       int64 content_length,
       const std::string& resource_id,
@@ -222,7 +230,6 @@
 
   // Should not be used.
   virtual CancelCallback ResumeUpload(
-      const base::FilePath& drive_file_path,
       const GURL& upload_url,
       int64 start_position,
       int64 end_position,
@@ -240,7 +247,6 @@
 class MockDriveServiceNoConnectionAtResume : public DummyDriveService {
   // Succeeds and returns an upload location URL.
   virtual CancelCallback InitiateUploadNewFile(
-      const base::FilePath& drive_file_path,
       const std::string& content_type,
       int64 content_length,
       const std::string& parent_resource_id,
@@ -252,7 +258,6 @@
   }
 
   virtual CancelCallback InitiateUploadExistingFile(
-      const base::FilePath& drive_file_path,
       const std::string& content_type,
       int64 content_length,
       const std::string& resource_id,
@@ -265,7 +270,6 @@
 
   // Returns error.
   virtual CancelCallback ResumeUpload(
-      const base::FilePath& drive_file_path,
       const GURL& upload_url,
       int64 start_position,
       int64 end_position,
@@ -288,10 +292,6 @@
     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
   }
 
-  virtual void TearDown() OVERRIDE {
-    ASSERT_TRUE(temp_dir_.Delete());
-  }
-
  protected:
   content::TestBrowserThreadBundle thread_bundle_;
   base::ScopedTempDir temp_dir_;
@@ -310,11 +310,11 @@
   scoped_ptr<ResourceEntry> resource_entry;
 
   MockDriveServiceWithUploadExpectation mock_service(local_path, data.size());
-  DriveUploader uploader(&mock_service);
+  DriveUploader uploader(&mock_service,
+                         base::MessageLoopProxy::current().get());
   std::vector<test_util::ProgressInfo> upload_progress_values;
   uploader.UploadExistingFile(
       kTestInitiateUploadResourceId,
-      base::FilePath::FromUTF8Unsafe(kTestDrivePath),
       local_path,
       kTestMimeType,
       std::string(),  // etag
@@ -322,7 +322,7 @@
           &error, &upload_location, &resource_entry),
       base::Bind(&test_util::AppendProgressCallbackResult,
                  &upload_progress_values));
-  test_util::RunBlockingPoolTask();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(1, mock_service.resume_upload_call_count());
   EXPECT_EQ(0, mock_service.received_bytes());
@@ -345,11 +345,11 @@
   scoped_ptr<ResourceEntry> resource_entry;
 
   MockDriveServiceWithUploadExpectation mock_service(local_path, data.size());
-  DriveUploader uploader(&mock_service);
+  DriveUploader uploader(&mock_service,
+                         base::MessageLoopProxy::current().get());
   std::vector<test_util::ProgressInfo> upload_progress_values;
   uploader.UploadExistingFile(
       kTestInitiateUploadResourceId,
-      base::FilePath::FromUTF8Unsafe(kTestDrivePath),
       local_path,
       kTestMimeType,
       std::string(),  // etag
@@ -357,7 +357,7 @@
           &error, &upload_location, &resource_entry),
       base::Bind(&test_util::AppendProgressCallbackResult,
                  &upload_progress_values));
-  test_util::RunBlockingPoolTask();
+  base::RunLoop().RunUntilIdle();
 
   // 512KB upload should not be split into multiple chunks.
   EXPECT_EQ(1, mock_service.resume_upload_call_count());
@@ -382,17 +382,16 @@
   scoped_ptr<ResourceEntry> resource_entry;
 
   MockDriveServiceNoConnectionAtInitiate mock_service;
-  DriveUploader uploader(&mock_service);
-  uploader.UploadExistingFile(
-      kTestInitiateUploadResourceId,
-      base::FilePath::FromUTF8Unsafe(kTestDrivePath),
-      local_path,
-      kTestMimeType,
-      std::string(),  // etag
-      test_util::CreateCopyResultCallback(
-          &error, &upload_location, &resource_entry),
-      google_apis::ProgressCallback());
-  test_util::RunBlockingPoolTask();
+  DriveUploader uploader(&mock_service,
+                         base::MessageLoopProxy::current().get());
+  uploader.UploadExistingFile(kTestInitiateUploadResourceId,
+                              local_path,
+                              kTestMimeType,
+                              std::string(),  // etag
+                              test_util::CreateCopyResultCallback(
+                                  &error, &upload_location, &resource_entry),
+                              google_apis::ProgressCallback());
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(GDATA_NO_CONNECTION, error);
   EXPECT_TRUE(upload_location.is_empty());
@@ -410,17 +409,16 @@
   scoped_ptr<ResourceEntry> resource_entry;
 
   MockDriveServiceWithUploadExpectation mock_service(local_path, data.size());
-  DriveUploader uploader(&mock_service);
-  uploader.UploadExistingFile(
-      kTestInitiateUploadResourceId,
-      base::FilePath::FromUTF8Unsafe(kTestDrivePath),
-      local_path,
-      kTestMimeType,
-      kTestETag,
-      test_util::CreateCopyResultCallback(
-          &error, &upload_location, &resource_entry),
-      google_apis::ProgressCallback());
-  test_util::RunBlockingPoolTask();
+  DriveUploader uploader(&mock_service,
+                         base::MessageLoopProxy::current().get());
+  uploader.UploadExistingFile(kTestInitiateUploadResourceId,
+                              local_path,
+                              kTestMimeType,
+                              kTestETag,
+                              test_util::CreateCopyResultCallback(
+                                  &error, &upload_location, &resource_entry),
+                              google_apis::ProgressCallback());
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   EXPECT_TRUE(upload_location.is_empty());
@@ -438,17 +436,16 @@
   scoped_ptr<ResourceEntry> resource_entry;
 
   MockDriveServiceWithUploadExpectation mock_service(local_path, data.size());
-  DriveUploader uploader(&mock_service);
-  uploader.UploadExistingFile(
-      kTestInitiateUploadResourceId,
-      base::FilePath::FromUTF8Unsafe(kTestDrivePath),
-      local_path,
-      kTestMimeType,
-      kDestinationETag,
-      test_util::CreateCopyResultCallback(
-          &error, &upload_location, &resource_entry),
-      google_apis::ProgressCallback());
-  test_util::RunBlockingPoolTask();
+  DriveUploader uploader(&mock_service,
+                         base::MessageLoopProxy::current().get());
+  uploader.UploadExistingFile(kTestInitiateUploadResourceId,
+                              local_path,
+                              kTestMimeType,
+                              kDestinationETag,
+                              test_util::CreateCopyResultCallback(
+                                  &error, &upload_location, &resource_entry),
+                              google_apis::ProgressCallback());
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_CONFLICT, error);
   EXPECT_TRUE(upload_location.is_empty());
@@ -465,17 +462,16 @@
   scoped_ptr<ResourceEntry> resource_entry;
 
   MockDriveServiceNoConnectionAtResume mock_service;
-  DriveUploader uploader(&mock_service);
-  uploader.UploadExistingFile(
-      kTestInitiateUploadResourceId,
-      base::FilePath::FromUTF8Unsafe(kTestDrivePath),
-      local_path,
-      kTestMimeType,
-      std::string(),  // etag
-      test_util::CreateCopyResultCallback(
-          &error, &upload_location, &resource_entry),
-      google_apis::ProgressCallback());
-  test_util::RunBlockingPoolTask();
+  DriveUploader uploader(&mock_service,
+                         base::MessageLoopProxy::current().get());
+  uploader.UploadExistingFile(kTestInitiateUploadResourceId,
+                              local_path,
+                              kTestMimeType,
+                              std::string(),  // etag
+                              test_util::CreateCopyResultCallback(
+                                  &error, &upload_location, &resource_entry),
+                              google_apis::ProgressCallback());
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(GDATA_NO_CONNECTION, error);
   EXPECT_EQ(GURL(kTestUploadExistingFileURL), upload_location);
@@ -486,17 +482,17 @@
   GURL upload_location;
   scoped_ptr<ResourceEntry> resource_entry;
 
-  DriveUploader uploader(NULL);  // NULL, the service won't be used.
+  DriveUploader uploader(NULL,  // NULL, the service won't be used.
+                         base::MessageLoopProxy::current().get());
   uploader.UploadExistingFile(
       kTestInitiateUploadResourceId,
-      base::FilePath::FromUTF8Unsafe(kTestDrivePath),
       temp_dir_.path().AppendASCII("_this_path_should_not_exist_"),
       kTestMimeType,
-      std::string(),             // etag
+      std::string(),  // etag
       test_util::CreateCopyResultCallback(
           &error, &upload_location, &resource_entry),
       google_apis::ProgressCallback());
-  test_util::RunBlockingPoolTask();
+  base::RunLoop().RunUntilIdle();
 
   // Should return failure without doing any attempt to connect to the server.
   EXPECT_EQ(HTTP_NOT_FOUND, error);
@@ -514,7 +510,8 @@
   scoped_ptr<ResourceEntry> resource_entry;
 
   MockDriveServiceWithUploadExpectation mock_service(local_path, data.size());
-  DriveUploader uploader(&mock_service);
+  DriveUploader uploader(&mock_service,
+                         base::MessageLoopProxy::current().get());
   // Emulate the situation that the only first part is successfully uploaded,
   // but not the latter half.
   mock_service.set_received_bytes(512 * 1024);
@@ -522,14 +519,13 @@
   std::vector<test_util::ProgressInfo> upload_progress_values;
   uploader.ResumeUploadFile(
       GURL(kTestUploadExistingFileURL),
-      base::FilePath::FromUTF8Unsafe(kTestDrivePath),
       local_path,
       kTestMimeType,
       test_util::CreateCopyResultCallback(
           &error, &upload_location, &resource_entry),
       base::Bind(&test_util::AppendProgressCallbackResult,
                  &upload_progress_values));
-  test_util::RunBlockingPoolTask();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(1, mock_service.resume_upload_call_count());
   EXPECT_EQ(1024 * 1024, mock_service.received_bytes());
@@ -542,4 +538,4 @@
             upload_progress_values[0]);
 }
 
-}  // namespace google_apis
+}  // namespace drive
diff --git a/chrome/browser/drive/dummy_drive_service.cc b/chrome/browser/drive/dummy_drive_service.cc
index d9442d1..24da00a 100644
--- a/chrome/browser/drive/dummy_drive_service.cc
+++ b/chrome/browser/drive/dummy_drive_service.cc
@@ -4,7 +4,20 @@
 
 #include "chrome/browser/drive/dummy_drive_service.h"
 
-namespace google_apis {
+using google_apis::AuthorizeAppCallback;
+using google_apis::CancelCallback;
+using google_apis::DownloadActionCallback;
+using google_apis::EntryActionCallback;
+using google_apis::GetAboutResourceCallback;
+using google_apis::GetAppListCallback;
+using google_apis::GetContentCallback;
+using google_apis::GetResourceEntryCallback;
+using google_apis::GetResourceListCallback;
+using google_apis::InitiateUploadCallback;
+using google_apis::ProgressCallback;
+using google_apis::UploadRangeCallback;
+
+namespace drive {
 
 DummyDriveService::DummyDriveService() {}
 
@@ -75,9 +88,8 @@
     const EntryActionCallback& callback) { return CancelCallback(); }
 
 CancelCallback DummyDriveService::DownloadFile(
-    const base::FilePath& virtual_path,
     const base::FilePath& local_cache_path,
-    const GURL& download_url,
+    const std::string& resource_id,
     const DownloadActionCallback& download_action_callback,
     const GetContentCallback& get_content_callback,
     const ProgressCallback& progress_callback) { return CancelCallback(); }
@@ -120,7 +132,6 @@
     const GetResourceEntryCallback& callback) { return CancelCallback(); }
 
 CancelCallback DummyDriveService::InitiateUploadNewFile(
-    const base::FilePath& drive_file_path,
     const std::string& content_type,
     int64 content_length,
     const std::string& parent_resource_id,
@@ -128,7 +139,6 @@
     const InitiateUploadCallback& callback) { return CancelCallback(); }
 
 CancelCallback DummyDriveService::InitiateUploadExistingFile(
-    const base::FilePath& drive_file_path,
     const std::string& content_type,
     int64 content_length,
     const std::string& resource_id,
@@ -136,7 +146,6 @@
     const InitiateUploadCallback& callback) { return CancelCallback(); }
 
 CancelCallback DummyDriveService::ResumeUpload(
-    const base::FilePath& drive_file_path,
     const GURL& upload_url,
     int64 start_position,
     int64 end_position,
@@ -147,7 +156,6 @@
     const ProgressCallback& progress_callback) { return CancelCallback(); }
 
 CancelCallback DummyDriveService::GetUploadStatus(
-    const base::FilePath& drive_file_path,
     const GURL& upload_url,
     int64 content_length,
     const UploadRangeCallback& callback) { return CancelCallback(); }
@@ -157,4 +165,4 @@
     const std::string& app_id,
     const AuthorizeAppCallback& callback) { return CancelCallback(); }
 
-}  // namespace google_apis
+}  // namespace drive
diff --git a/chrome/browser/drive/dummy_drive_service.h b/chrome/browser/drive/dummy_drive_service.h
index e2c75ca..bcb89bf 100644
--- a/chrome/browser/drive/dummy_drive_service.h
+++ b/chrome/browser/drive/dummy_drive_service.h
@@ -7,7 +7,7 @@
 
 #include "chrome/browser/drive/drive_service_interface.h"
 
-namespace google_apis {
+namespace drive {
 
 // Dummy implementation of DriveServiceInterface.
 // All functions do nothing, or return place holder values like 'true'.
@@ -28,107 +28,102 @@
   virtual void ClearAccessToken() OVERRIDE;
   virtual void ClearRefreshToken() OVERRIDE;
   virtual std::string GetRootResourceId() const OVERRIDE;
-  virtual CancelCallback GetAllResourceList(
-      const GetResourceListCallback& callback) OVERRIDE;
-  virtual CancelCallback GetResourceListInDirectory(
+  virtual google_apis::CancelCallback GetAllResourceList(
+      const google_apis::GetResourceListCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback GetResourceListInDirectory(
       const std::string& directory_resource_id,
-      const GetResourceListCallback& callback) OVERRIDE;
-  virtual CancelCallback Search(
+      const google_apis::GetResourceListCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback Search(
       const std::string& search_query,
-      const GetResourceListCallback& callback) OVERRIDE;
-  virtual CancelCallback SearchByTitle(
+      const google_apis::GetResourceListCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback SearchByTitle(
       const std::string& title,
       const std::string& directory_resource_id,
-      const GetResourceListCallback& callback) OVERRIDE;
-  virtual CancelCallback GetChangeList(
+      const google_apis::GetResourceListCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback GetChangeList(
       int64 start_changestamp,
-      const GetResourceListCallback& callback) OVERRIDE;
-  virtual CancelCallback ContinueGetResourceList(
+      const google_apis::GetResourceListCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback ContinueGetResourceList(
       const GURL& override_url,
-      const GetResourceListCallback& callback) OVERRIDE;
-  virtual CancelCallback GetResourceEntry(
+      const google_apis::GetResourceListCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback GetResourceEntry(
       const std::string& resource_id,
-      const GetResourceEntryCallback& callback) OVERRIDE;
-  virtual CancelCallback GetAboutResource(
-      const GetAboutResourceCallback& callback) OVERRIDE;
-  virtual CancelCallback GetAppList(
-      const GetAppListCallback& callback) OVERRIDE;
-  virtual CancelCallback DeleteResource(
+      const google_apis::GetResourceEntryCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback GetAboutResource(
+      const google_apis::GetAboutResourceCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback GetAppList(
+      const google_apis::GetAppListCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback DeleteResource(
       const std::string& resource_id,
       const std::string& etag,
-      const EntryActionCallback& callback) OVERRIDE;
-  virtual CancelCallback DownloadFile(
-      const base::FilePath& virtual_path,
+      const google_apis::EntryActionCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback DownloadFile(
       const base::FilePath& local_cache_path,
-      const GURL& download_url,
-      const DownloadActionCallback& download_action_callback,
-      const GetContentCallback& get_content_callback,
-      const ProgressCallback& progress_callback) OVERRIDE;
-  virtual CancelCallback CopyResource(
+      const std::string& resource_id,
+      const google_apis::DownloadActionCallback& download_action_callback,
+      const google_apis::GetContentCallback& get_content_callback,
+      const google_apis::ProgressCallback& progress_callback) OVERRIDE;
+  virtual google_apis::CancelCallback CopyResource(
       const std::string& resource_id,
       const std::string& parent_resource_id,
       const std::string& new_name,
-      const GetResourceEntryCallback& callback) OVERRIDE;
-  virtual CancelCallback CopyHostedDocument(
+      const google_apis::GetResourceEntryCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback CopyHostedDocument(
       const std::string& resource_id,
       const std::string& new_name,
-      const GetResourceEntryCallback& callback) OVERRIDE;
-  virtual CancelCallback RenameResource(
+      const google_apis::GetResourceEntryCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback RenameResource(
       const std::string& resource_id,
       const std::string& new_name,
-      const EntryActionCallback& callback) OVERRIDE;
-  virtual CancelCallback TouchResource(
+      const google_apis::EntryActionCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback TouchResource(
       const std::string& resource_id,
       const base::Time& modified_date,
       const base::Time& last_viewed_by_me_date,
-      const GetResourceEntryCallback& callback) OVERRIDE;
-  virtual CancelCallback AddResourceToDirectory(
+      const google_apis::GetResourceEntryCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback AddResourceToDirectory(
       const std::string& parent_resource_id,
       const std::string& resource_id,
-      const EntryActionCallback& callback) OVERRIDE;
-  virtual CancelCallback RemoveResourceFromDirectory(
+      const google_apis::EntryActionCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback RemoveResourceFromDirectory(
       const std::string& parent_resource_id,
       const std::string& resource_id,
-      const EntryActionCallback& callback) OVERRIDE;
-  virtual CancelCallback AddNewDirectory(
+      const google_apis::EntryActionCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback AddNewDirectory(
       const std::string& parent_resource_id,
       const std::string& directory_name,
-      const GetResourceEntryCallback& callback) OVERRIDE;
-  virtual CancelCallback InitiateUploadNewFile(
-      const base::FilePath& drive_file_path,
+      const google_apis::GetResourceEntryCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback InitiateUploadNewFile(
       const std::string& content_type,
       int64 content_length,
       const std::string& parent_resource_id,
       const std::string& title,
-      const InitiateUploadCallback& callback) OVERRIDE;
-  virtual CancelCallback InitiateUploadExistingFile(
-      const base::FilePath& drive_file_path,
+      const google_apis::InitiateUploadCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback InitiateUploadExistingFile(
       const std::string& content_type,
       int64 content_length,
       const std::string& resource_id,
       const std::string& etag,
-      const InitiateUploadCallback& callback) OVERRIDE;
-  virtual CancelCallback ResumeUpload(
-      const base::FilePath& drive_file_path,
+      const google_apis::InitiateUploadCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback ResumeUpload(
       const GURL& upload_url,
       int64 start_position,
       int64 end_position,
       int64 content_length,
       const std::string& content_type,
       const base::FilePath& local_file_path,
-      const UploadRangeCallback& callback,
-      const ProgressCallback& progress_callback) OVERRIDE;
-  virtual CancelCallback GetUploadStatus(
-      const base::FilePath& drive_file_path,
+      const google_apis::UploadRangeCallback& callback,
+      const google_apis::ProgressCallback& progress_callback) OVERRIDE;
+  virtual google_apis::CancelCallback GetUploadStatus(
       const GURL& upload_url,
       int64 content_length,
-      const UploadRangeCallback& callback) OVERRIDE;
-  virtual CancelCallback AuthorizeApp(
+      const google_apis::UploadRangeCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback AuthorizeApp(
       const std::string& resource_id,
       const std::string& app_id,
-      const AuthorizeAppCallback& callback) OVERRIDE;
+      const google_apis::AuthorizeAppCallback& callback) OVERRIDE;
 };
 
-}  // namespace google_apis
+}  // namespace drive
 
 #endif  // CHROME_BROWSER_DRIVE_DUMMY_DRIVE_SERVICE_H_
diff --git a/chrome/browser/drive/event_logger.cc b/chrome/browser/drive/event_logger.cc
new file mode 100644
index 0000000..630a6be
--- /dev/null
+++ b/chrome/browser/drive/event_logger.cc
@@ -0,0 +1,54 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/drive/event_logger.h"
+
+#include "base/strings/stringprintf.h"
+
+namespace drive {
+
+EventLogger::Event::Event(int id, const std::string& what)
+    : id(id),
+      when(base::Time::Now()),
+      what(what) {
+}
+
+EventLogger::EventLogger()
+    : history_size_(kDefaultHistorySize),
+      next_event_id_(0) {
+}
+
+EventLogger::~EventLogger() {
+}
+
+void EventLogger::Log(const char* format, ...) {
+  std::string what;
+
+  va_list args;
+  va_start(args, format);
+  base::StringAppendV(&what, format, args);
+  va_end(args);
+
+  base::AutoLock auto_lock(lock_);
+  history_.push_back(Event(next_event_id_, what));
+  ++next_event_id_;
+  if (history_.size() > history_size_)
+    history_.pop_front();
+}
+
+void EventLogger::SetHistorySize(size_t history_size) {
+  base::AutoLock auto_lock(lock_);
+  history_.clear();
+  history_size_ = history_size;
+}
+
+std::vector<EventLogger::Event> EventLogger::GetHistory() {
+  base::AutoLock auto_lock(lock_);
+  std::vector<Event> output;
+  output.assign(history_.begin(), history_.end());
+  return output;
+}
+
+
+}  // namespace drive
diff --git a/chrome/browser/drive/event_logger.h b/chrome/browser/drive/event_logger.h
new file mode 100644
index 0000000..95a10e6
--- /dev/null
+++ b/chrome/browser/drive/event_logger.h
@@ -0,0 +1,65 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_DRIVE_EVENT_LOGGER_H_
+#define CHROME_BROWSER_DRIVE_EVENT_LOGGER_H_
+
+#include <stdarg.h>   // va_list
+#include <deque>
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/synchronization/lock.h"
+#include "base/time/time.h"
+
+namespace drive {
+
+// The default history size used by EventLogger.
+const int kDefaultHistorySize = 1000;
+
+// EventLogger is used to collect and expose text messages for diagnosing
+// behaviors of Google APIs stuff. For instance, the collected messages are
+// exposed to chrome:drive-internals.
+class EventLogger {
+ public:
+  // Represents a single event log.
+  struct Event {
+    Event(int id, const std::string& what);
+    int id;  // Monotonically increasing ID starting from 0.
+    base::Time when;  // When the event occurred.
+    std::string what;  // What happened.
+  };
+
+  // Creates an event logger that keeps the latest kDefaultHistorySize events.
+  EventLogger();
+  ~EventLogger();
+
+  // Logs a message using printf format.
+  // Can be called from any thread as long as the object is alive.
+  // Note that PRINTF_FORMAT should be (2, 3) instead of (1, 2) as this is a
+  // C++ member function.
+  void Log(const char* format, ...) PRINTF_FORMAT(2, 3);
+
+  // Sets the history size. The existing history is cleared.
+  // Can be called from any thread as long as the object is alive.
+  void SetHistorySize(size_t history_size);
+
+  // Gets the list of latest events (the oldest event comes first).
+  // Can be called from any thread as long as the object is alive.
+  std::vector<Event> GetHistory();
+
+ private:
+  std::deque<Event> history_;  // guarded by lock_.
+  size_t history_size_;  // guarded by lock_.
+  int next_event_id_;  // guarded by lock_.
+  base::Lock lock_;
+
+  DISALLOW_COPY_AND_ASSIGN(EventLogger);
+};
+
+}  // namespace drive
+
+#endif  // CHROME_BROWSER_DRIVE_EVENT_LOGGER_H_
diff --git a/chrome/browser/drive/event_logger_unittest.cc b/chrome/browser/drive/event_logger_unittest.cc
new file mode 100644
index 0000000..c57078f
--- /dev/null
+++ b/chrome/browser/drive/event_logger_unittest.cc
@@ -0,0 +1,43 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/drive/event_logger.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace drive {
+
+TEST(EventLoggerTest, BasicLogging) {
+  EventLogger logger;
+  logger.SetHistorySize(3);  // At most 3 events are kept.
+  EXPECT_EQ(0U, logger.GetHistory().size());
+
+  logger.Log("first");
+  logger.Log("%dnd", 2);
+  logger.Log("third");
+
+  // Events are recorded in the chronological order with sequential IDs.
+  std::vector<EventLogger::Event> history = logger.GetHistory();
+  ASSERT_EQ(3U, history.size());
+  EXPECT_EQ(0, history[0].id);
+  EXPECT_EQ("first", history[0].what);
+  EXPECT_EQ(1, history[1].id);
+  EXPECT_EQ("2nd", history[1].what);
+  EXPECT_EQ(2, history[2].id);
+  EXPECT_EQ("third", history[2].what);
+
+  logger.Log("fourth");
+  // It does not log events beyond the specified.
+  history = logger.GetHistory();
+  ASSERT_EQ(3U, history.size());
+  // The oldest events is pushed out.
+  EXPECT_EQ(1, history[0].id);
+  EXPECT_EQ("2nd", history[0].what);
+  EXPECT_EQ(2, history[1].id);
+  EXPECT_EQ("third", history[1].what);
+  EXPECT_EQ(3, history[2].id);
+  EXPECT_EQ("fourth", history[2].what);
+}
+
+}   // namespace drive
diff --git a/chrome/browser/drive/fake_drive_service.cc b/chrome/browser/drive/fake_drive_service.cc
index 8fec2c8..28899cf 100644
--- a/chrome/browser/drive/fake_drive_service.cc
+++ b/chrome/browser/drive/fake_drive_service.cc
@@ -6,7 +6,9 @@
 
 #include <string>
 
+#include "base/file_util.h"
 #include "base/logging.h"
+#include "base/md5.h"
 #include "base/message_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
@@ -23,8 +25,39 @@
 #include "net/base/url_util.h"
 
 using content::BrowserThread;
+using google_apis::AboutResource;
+using google_apis::AccountMetadata;
+using google_apis::AppList;
+using google_apis::AuthorizeAppCallback;
+using google_apis::CancelCallback;
+using google_apis::DownloadActionCallback;
+using google_apis::EntryActionCallback;
+using google_apis::GDataErrorCode;
+using google_apis::GDATA_FILE_ERROR;
+using google_apis::GDATA_NO_CONNECTION;
+using google_apis::GDATA_OTHER_ERROR;
+using google_apis::GetAboutResourceCallback;
+using google_apis::GetAppListCallback;
+using google_apis::GetContentCallback;
+using google_apis::GetResourceEntryCallback;
+using google_apis::GetResourceListCallback;
+using google_apis::HTTP_BAD_REQUEST;
+using google_apis::HTTP_CREATED;
+using google_apis::HTTP_NOT_FOUND;
+using google_apis::HTTP_PRECONDITION;
+using google_apis::HTTP_RESUME_INCOMPLETE;
+using google_apis::HTTP_SUCCESS;
+using google_apis::InitiateUploadCallback;
+using google_apis::Link;
+using google_apis::ProgressCallback;
+using google_apis::ResourceEntry;
+using google_apis::ResourceList;
+using google_apis::UploadRangeCallback;
+using google_apis::UploadRangeResponse;
+namespace test_util = google_apis::test_util;
+namespace util = google_apis::util;
 
-namespace google_apis {
+namespace drive {
 namespace {
 
 // Rel property of upload link in the entries dictionary value.
@@ -66,28 +99,6 @@
   return true;
 }
 
-// Gets the upload URL from the given entry. Returns an empty URL if not
-// found.
-GURL GetUploadUrl(const base::DictionaryValue& entry) {
-  std::string upload_url;
-  const base::ListValue* links = NULL;
-  if (entry.GetList("link", &links) && links) {
-    for (size_t link_index = 0;
-         link_index < links->GetSize();
-         ++link_index) {
-      const base::DictionaryValue* link = NULL;
-      std::string rel;
-      if (links->GetDictionary(link_index, &link) &&
-          link && link->GetString("rel", &rel) &&
-          rel == kUploadUrlRel &&
-          link->GetString("href", &upload_url)) {
-        break;
-      }
-    }
-  }
-  return GURL(upload_url);
-}
-
 // Returns |url| without query parameter.
 GURL RemoveQueryParameter(const GURL& url) {
   GURL::Replacements replacements;
@@ -95,11 +106,57 @@
   return url.ReplaceComponents(replacements);
 }
 
+void ScheduleUploadRangeCallback(const UploadRangeCallback& callback,
+                                 int64 start_position,
+                                 int64 end_position,
+                                 GDataErrorCode error,
+                                 scoped_ptr<ResourceEntry> entry) {
+  base::MessageLoop::current()->PostTask(
+      FROM_HERE,
+      base::Bind(callback,
+                 UploadRangeResponse(error,
+                                     start_position,
+                                     end_position),
+                 base::Passed(&entry)));
+}
+
 }  // namespace
 
+struct FakeDriveService::UploadSession {
+  std::string content_type;
+  int64 content_length;
+  std::string parent_resource_id;
+  std::string resource_id;
+  std::string etag;
+  std::string title;
+
+  int64 uploaded_size;
+
+  UploadSession()
+      : content_length(0),
+        uploaded_size(0) {}
+
+  UploadSession(
+      std::string content_type,
+      int64 content_length,
+      std::string parent_resource_id,
+      std::string resource_id,
+      std::string etag,
+      std::string title)
+    : content_type(content_type),
+      content_length(content_length),
+      parent_resource_id(parent_resource_id),
+      resource_id(resource_id),
+      etag(etag),
+      title(title),
+      uploaded_size(0) {
+  }
+};
+
 FakeDriveService::FakeDriveService()
     : largest_changestamp_(0),
       published_date_seq_(0),
+      next_upload_sequence_number_(0),
       default_max_results_(0),
       resource_id_count_(0),
       resource_list_load_count_(0),
@@ -472,25 +529,29 @@
       if (entries->GetDictionary(i, &entry) &&
           entry->GetString("gd$resourceId.$t", &current_resource_id) &&
           resource_id == current_resource_id) {
-        entries->Remove(i, NULL);
+        GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
+        if (entry->HasKey("gd$deleted")) {
+          error = HTTP_NOT_FOUND;
+        } else {
+          entry->Set("gd$deleted", new DictionaryValue);
+          AddNewChangestampAndETag(entry);
+          error = HTTP_SUCCESS;
+        }
         base::MessageLoop::current()->PostTask(
-            FROM_HERE, base::Bind(callback, HTTP_SUCCESS));
+            FROM_HERE, base::Bind(callback, error));
         return CancelCallback();
       }
     }
   }
 
-  // TODO(satorux): Add support for returning "deleted" entries in
-  // changelists from GetResourceList().
   base::MessageLoop::current()->PostTask(
       FROM_HERE, base::Bind(callback, HTTP_NOT_FOUND));
   return CancelCallback();
 }
 
 CancelCallback FakeDriveService::DownloadFile(
-    const base::FilePath& virtual_path,
     const base::FilePath& local_cache_path,
-    const GURL& download_url,
+    const std::string& resource_id,
     const DownloadActionCallback& download_action_callback,
     const GetContentCallback& get_content_callback,
     const ProgressCallback& progress_callback) {
@@ -507,7 +568,7 @@
   }
 
   // The field content.src is the URL to download the file.
-  base::DictionaryValue* entry = FindEntryByContentUrl(download_url);
+  base::DictionaryValue* entry = FindEntryByResourceId(resource_id);
   if (!entry) {
     base::MessageLoopProxy::current()->PostTask(
         FROM_HERE,
@@ -518,7 +579,6 @@
   // Write "x"s of the file size specified in the entry.
   std::string file_size_string;
   entry->GetString("docs$size.$t", &file_size_string);
-  // TODO(satorux): To be correct, we should update docs$md5Checksum.$t here.
   int64 file_size = 0;
   if (base::StringToInt64(file_size_string, &file_size)) {
     base::BinaryValue* content_binary_data;
@@ -620,7 +680,7 @@
         link->SetString("href", GetFakeLinkUrl(parent_resource_id).spec());
         links->Append(link);
 
-        AddNewChangestamp(copied_entry.get());
+        AddNewChangestampAndETag(copied_entry.get());
 
         // Parse the new entry.
         scoped_ptr<ResourceEntry> resource_entry =
@@ -671,7 +731,7 @@
   base::DictionaryValue* entry = FindEntryByResourceId(resource_id);
   if (entry) {
     entry->SetString("title.$t", new_name);
-    AddNewChangestamp(entry);
+    AddNewChangestampAndETag(entry);
     base::MessageLoop::current()->PostTask(
         FROM_HERE, base::Bind(callback, HTTP_SUCCESS));
     return CancelCallback();
@@ -713,7 +773,7 @@
                    util::FormatTimeAsString(modified_date));
   entry->SetString("gd$lastViewed.$t",
                    util::FormatTimeAsString(last_viewed_by_me_date));
-  AddNewChangestamp(entry);
+  AddNewChangestampAndETag(entry);
 
   scoped_ptr<ResourceEntry> parsed_entry(ResourceEntry::CreateFrom(*entry));
   base::MessageLoop::current()->PostTask(
@@ -753,7 +813,7 @@
         "href", GetFakeLinkUrl(parent_resource_id).spec());
     links->Append(link);
 
-    AddNewChangestamp(entry);
+    AddNewChangestampAndETag(entry);
     base::MessageLoop::current()->PostTask(
         FROM_HERE, base::Bind(callback, HTTP_SUCCESS));
     return CancelCallback();
@@ -792,7 +852,7 @@
             rel == "http://schemas.google.com/docs/2007#parent" &&
             GURL(href) == parent_content_url) {
           links->Remove(i, NULL);
-          AddNewChangestamp(entry);
+          AddNewChangestampAndETag(entry);
           base::MessageLoop::current()->PostTask(
               FROM_HERE, base::Bind(callback, HTTP_SUCCESS));
           return CancelCallback();
@@ -846,7 +906,6 @@
 }
 
 CancelCallback FakeDriveService::InitiateUploadNewFile(
-    const base::FilePath& drive_file_path,
     const std::string& content_type,
     int64 content_length,
     const std::string& parent_resource_id,
@@ -862,32 +921,29 @@
     return CancelCallback();
   }
 
-  // Content length should be zero, as we'll create an empty file first. The
-  // content will be added in ResumeUpload().
-  const base::DictionaryValue* new_entry = AddNewEntry(content_type,
-                                                       "",  // content_data
-                                                       parent_resource_id,
-                                                       title,
-                                                       false,  // shared_with_me
-                                                       "file");
-  if (!new_entry) {
+  if (parent_resource_id != GetRootResourceId() &&
+      !FindEntryByResourceId(parent_resource_id)) {
     base::MessageLoop::current()->PostTask(
         FROM_HERE,
         base::Bind(callback, HTTP_NOT_FOUND, GURL()));
     return CancelCallback();
   }
-  const GURL upload_url = GetUploadUrl(*new_entry);
-  DCHECK(upload_url.is_valid());
+
+  GURL session_url = GetNewUploadSessionUrl();
+  upload_sessions_[session_url] =
+      UploadSession(content_type, content_length,
+                    parent_resource_id,
+                    "",  // resource_id
+                    "",  // etag
+                    title);
 
   base::MessageLoop::current()->PostTask(
       FROM_HERE,
-      base::Bind(callback, HTTP_SUCCESS,
-                 net::AppendQueryParameter(upload_url, "mode", "newfile")));
+      base::Bind(callback, HTTP_SUCCESS, session_url));
   return CancelCallback();
 }
 
 CancelCallback FakeDriveService::InitiateUploadExistingFile(
-    const base::FilePath& drive_file_path,
     const std::string& content_type,
     int64 content_length,
     const std::string& resource_id,
@@ -919,20 +975,22 @@
         base::Bind(callback, HTTP_PRECONDITION, GURL()));
     return CancelCallback();
   }
-  entry->SetString("docs$size.$t", "0");
 
-  const GURL upload_url = GetUploadUrl(*entry);
-  DCHECK(upload_url.is_valid());
+  GURL session_url = GetNewUploadSessionUrl();
+  upload_sessions_[session_url] =
+      UploadSession(content_type, content_length,
+                    "",  // parent_resource_id
+                    resource_id,
+                    entry_etag,
+                    "" /* title */);
 
   base::MessageLoop::current()->PostTask(
       FROM_HERE,
-      base::Bind(callback, HTTP_SUCCESS,
-                 net::AppendQueryParameter(upload_url, "mode", "existing")));
+      base::Bind(callback, HTTP_SUCCESS, session_url));
   return CancelCallback();
 }
 
 CancelCallback FakeDriveService::GetUploadStatus(
-    const base::FilePath& drive_file_path,
     const GURL& upload_url,
     int64 content_length,
     const UploadRangeCallback& callback) {
@@ -942,7 +1000,6 @@
 }
 
 CancelCallback FakeDriveService::ResumeUpload(
-      const base::FilePath& drive_file_path,
       const GURL& upload_url,
       int64 start_position,
       int64 end_position,
@@ -954,51 +1011,29 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(!callback.is_null());
 
-  scoped_ptr<ResourceEntry> result_entry;
+  GetResourceEntryCallback completion_callback
+      = base::Bind(&ScheduleUploadRangeCallback,
+                   callback, start_position, end_position);
 
   if (offline_) {
-    base::MessageLoop::current()->PostTask(
-        FROM_HERE,
-        base::Bind(callback,
-                   UploadRangeResponse(GDATA_NO_CONNECTION,
-                                       start_position,
-                                       end_position),
-                   base::Passed(&result_entry)));
+    completion_callback.Run(GDATA_NO_CONNECTION, scoped_ptr<ResourceEntry>());
     return CancelCallback();
   }
 
-  DictionaryValue* entry = NULL;
-  entry = FindEntryByUploadUrl(RemoveQueryParameter(upload_url));
-  if (!entry) {
-    base::MessageLoop::current()->PostTask(
-        FROM_HERE,
-        base::Bind(callback,
-                   UploadRangeResponse(HTTP_NOT_FOUND,
-                                       start_position,
-                                       end_position),
-                   base::Passed(&result_entry)));
+  if (!upload_sessions_.count(upload_url)) {
+    completion_callback.Run(HTTP_NOT_FOUND, scoped_ptr<ResourceEntry>());
     return CancelCallback();
   }
 
+  UploadSession* session = &upload_sessions_[upload_url];
+
   // Chunks are required to be sent in such a ways that they fill from the start
   // of the not-yet-uploaded part with no gaps nor overlaps.
-  std::string current_size_string;
-  int64 current_size;
-  if (!entry->GetString("docs$size.$t", &current_size_string) ||
-      !base::StringToInt64(current_size_string, &current_size) ||
-      current_size != start_position) {
-    base::MessageLoop::current()->PostTask(
-        FROM_HERE,
-        base::Bind(callback,
-                   UploadRangeResponse(HTTP_BAD_REQUEST,
-                                       start_position,
-                                       end_position),
-                   base::Passed(&result_entry)));
+  if (session->uploaded_size != start_position) {
+    completion_callback.Run(HTTP_BAD_REQUEST, scoped_ptr<ResourceEntry>());
     return CancelCallback();
   }
 
-  entry->SetString("docs$size.$t", base::Int64ToString(end_position));
-
   if (!progress_callback.is_null()) {
     // In the real GDataWapi/Drive DriveService, progress is reported in
     // nondeterministic timing. In this fake implementation, we choose to call
@@ -1014,35 +1049,62 @@
   }
 
   if (content_length != end_position) {
-    base::MessageLoop::current()->PostTask(
-        FROM_HERE,
-        base::Bind(callback,
-                   UploadRangeResponse(HTTP_RESUME_INCOMPLETE,
-                                       start_position,
-                                       end_position),
-                    base::Passed(&result_entry)));
+    session->uploaded_size = end_position;
+    completion_callback.Run(HTTP_RESUME_INCOMPLETE,
+                            scoped_ptr<ResourceEntry>());
     return CancelCallback();
   }
 
-  AddNewChangestamp(entry);
-  result_entry = ResourceEntry::CreateFrom(*entry).Pass();
+  std::string content_data;
+  if (!file_util::ReadFileToString(local_file_path, &content_data)) {
+    session->uploaded_size = end_position;
+    completion_callback.Run(GDATA_FILE_ERROR, scoped_ptr<ResourceEntry>());
+    return CancelCallback();
+  }
+  session->uploaded_size = end_position;
 
-  std::string upload_mode;
-  bool upload_mode_found =
-      net::GetValueForKeyInQuery(upload_url, "mode", &upload_mode);
-  DCHECK(upload_mode_found &&
-         (upload_mode == "newfile" || upload_mode == "existing"));
+  // |resource_id| is empty if the upload is for new file.
+  if (session->resource_id.empty()) {
+    DCHECK(!session->parent_resource_id.empty());
+    DCHECK(!session->title.empty());
+    const DictionaryValue* new_entry = AddNewEntry(
+        session->content_type,
+        content_data,
+        session->parent_resource_id,
+        session->title,
+        false,  // shared_with_me
+        "file");
+    if (!new_entry) {
+      completion_callback.Run(HTTP_NOT_FOUND, scoped_ptr<ResourceEntry>());
+      return CancelCallback();
+    }
 
-  GDataErrorCode return_code =
-      upload_mode == "newfile" ? HTTP_CREATED : HTTP_SUCCESS;
+    completion_callback.Run(HTTP_CREATED,
+                            ResourceEntry::CreateFrom(*new_entry));
+    return CancelCallback();
+  }
 
-  base::MessageLoop::current()->PostTask(
-      FROM_HERE,
-      base::Bind(callback,
-                 UploadRangeResponse(return_code,
-                                     start_position,
-                                     end_position),
-                 base::Passed(&result_entry)));
+  DictionaryValue* entry = FindEntryByResourceId(session->resource_id);
+  if (!entry) {
+    completion_callback.Run(HTTP_NOT_FOUND, scoped_ptr<ResourceEntry>());
+    return CancelCallback();
+  }
+
+  std::string entry_etag;
+  entry->GetString("gd$etag", &entry_etag);
+  if (entry_etag.empty() || session->etag != entry_etag) {
+    completion_callback.Run(HTTP_PRECONDITION, scoped_ptr<ResourceEntry>());
+    return CancelCallback();
+  }
+
+  entry->SetString("docs$md5Checksum.$t", base::MD5String(content_data));
+  entry->Set("test$data",
+             base::BinaryValue::CreateWithCopiedBuffer(
+                 content_data.data(), content_data.size()));
+  entry->SetString("docs$size.$t", base::Int64ToString(end_position));
+  AddNewChangestampAndETag(entry);
+
+  completion_callback.Run(HTTP_SUCCESS, ResourceEntry::CreateFrom(*entry));
   return CancelCallback();
 }
 
@@ -1184,40 +1246,6 @@
   return NULL;
 }
 
-base::DictionaryValue* FakeDriveService::FindEntryByUploadUrl(
-    const GURL& upload_url) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  base::ListValue* entries = NULL;
-  // Go through entries and return the one that matches |upload_url|.
-  if (resource_list_value_->GetList("entry", &entries)) {
-    for (size_t i = 0; i < entries->GetSize(); ++i) {
-      base::DictionaryValue* entry = NULL;
-      base::ListValue* links = NULL;
-      if (entries->GetDictionary(i, &entry) &&
-          entry->GetList("link", &links) &&
-          links) {
-        for (size_t link_index = 0;
-            link_index < links->GetSize();
-            ++link_index) {
-          base::DictionaryValue* link = NULL;
-          std::string rel;
-          std::string found_upload_url;
-          if (links->GetDictionary(link_index, &link) &&
-              link && link->GetString("rel", &rel) &&
-              rel == kUploadUrlRel &&
-              link->GetString("href", &found_upload_url) &&
-              GURL(found_upload_url) == upload_url) {
-            return entry;
-          }
-        }
-      }
-    }
-  }
-
-  return NULL;
-}
-
 std::string FakeDriveService::GetNewResourceId() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
@@ -1225,10 +1253,12 @@
   return base::StringPrintf("resource_id_%d", resource_id_count_);
 }
 
-void FakeDriveService::AddNewChangestamp(base::DictionaryValue* entry) {
+void FakeDriveService::AddNewChangestampAndETag(base::DictionaryValue* entry) {
   ++largest_changestamp_;
   entry->SetString("docs$changestamp.value",
                    base::Int64ToString(largest_changestamp_));
+  entry->SetString("gd$etag",
+                   "etag_" + base::Int64ToString(largest_changestamp_));
 }
 
 const base::DictionaryValue* FakeDriveService::AddNewEntry(
@@ -1260,9 +1290,8 @@
             content_data.c_str(), content_data.size()));
     new_entry->SetString("docs$size.$t",
                          base::Int64ToString(content_data.size()));
-    // TODO(satorux): Set the correct MD5 here.
     new_entry->SetString("docs$md5Checksum.$t",
-                         "3b4385ebefec6e743574c76bbd0575de");
+                         base::MD5String(content_data));
   }
 
   // Add "category" which sets the resource type to |entry_kind|.
@@ -1311,7 +1340,7 @@
   links->Append(upload_link);
   new_entry->Set("link", links);
 
-  AddNewChangestamp(new_entry.get());
+  AddNewChangestampAndETag(new_entry.get());
 
   base::Time published_date =
       base::Time() + base::TimeDelta::FromMilliseconds(++published_date_seq_);
@@ -1390,6 +1419,11 @@
     if (start_changestamp > 0 && entry->changestamp() < start_changestamp)
       should_exclude = true;
 
+    // If the caller requests other list than change list by specifying
+    // zero-|start_changestamp|, exclude deleted entry from the result.
+    if (!start_changestamp && entry->deleted())
+      should_exclude = true;
+
     // The entry matched the criteria for inclusion.
     if (!should_exclude)
       ++num_entries_matched;
@@ -1447,4 +1481,9 @@
                  base::Passed(&resource_list)));
 }
 
-}  // namespace google_apis
+GURL FakeDriveService::GetNewUploadSessionUrl() {
+  return GURL("https://upload_session_url/" +
+              base::Int64ToString(next_upload_sequence_number_++));
+}
+
+}  // namespace drive
diff --git a/chrome/browser/drive/fake_drive_service.h b/chrome/browser/drive/fake_drive_service.h
index f677c7d..9b59e0c 100644
--- a/chrome/browser/drive/fake_drive_service.h
+++ b/chrome/browser/drive/fake_drive_service.h
@@ -9,7 +9,7 @@
 #include "base/values.h"
 #include "chrome/browser/drive/drive_service_interface.h"
 
-namespace google_apis {
+namespace drive {
 
 // This class implements a fake DriveService which acts like a real Drive
 // service. The fake service works as follows:
@@ -88,109 +88,104 @@
   virtual bool HasRefreshToken() const OVERRIDE;
   virtual void ClearAccessToken() OVERRIDE;
   virtual void ClearRefreshToken() OVERRIDE;
-  virtual CancelCallback GetAllResourceList(
-      const GetResourceListCallback& callback) OVERRIDE;
-  virtual CancelCallback GetResourceListInDirectory(
+  virtual google_apis::CancelCallback GetAllResourceList(
+      const google_apis::GetResourceListCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback GetResourceListInDirectory(
       const std::string& directory_resource_id,
-      const GetResourceListCallback& callback) OVERRIDE;
+      const google_apis::GetResourceListCallback& callback) OVERRIDE;
   // See the comment for EntryMatchWidthQuery() in .cc file for details about
   // the supported search query types.
-  virtual CancelCallback Search(
+  virtual google_apis::CancelCallback Search(
       const std::string& search_query,
-      const GetResourceListCallback& callback) OVERRIDE;
-  virtual CancelCallback SearchByTitle(
+      const google_apis::GetResourceListCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback SearchByTitle(
       const std::string& title,
       const std::string& directory_resource_id,
-      const GetResourceListCallback& callback) OVERRIDE;
-  virtual CancelCallback GetChangeList(
+      const google_apis::GetResourceListCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback GetChangeList(
       int64 start_changestamp,
-      const GetResourceListCallback& callback) OVERRIDE;
-  virtual CancelCallback ContinueGetResourceList(
+      const google_apis::GetResourceListCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback ContinueGetResourceList(
       const GURL& override_url,
-      const GetResourceListCallback& callback) OVERRIDE;
-  virtual CancelCallback GetResourceEntry(
+      const google_apis::GetResourceListCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback GetResourceEntry(
       const std::string& resource_id,
-      const GetResourceEntryCallback& callback) OVERRIDE;
-  virtual CancelCallback GetAboutResource(
-      const GetAboutResourceCallback& callback) OVERRIDE;
-  virtual CancelCallback GetAppList(
-      const GetAppListCallback& callback) OVERRIDE;
-  virtual CancelCallback DeleteResource(
+      const google_apis::GetResourceEntryCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback GetAboutResource(
+      const google_apis::GetAboutResourceCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback GetAppList(
+      const google_apis::GetAppListCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback DeleteResource(
       const std::string& resource_id,
       const std::string& etag,
-      const EntryActionCallback& callback) OVERRIDE;
-  virtual CancelCallback DownloadFile(
-      const base::FilePath& virtual_path,
+      const google_apis::EntryActionCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback DownloadFile(
       const base::FilePath& local_cache_path,
-      const GURL& download_url,
-      const DownloadActionCallback& download_action_callback,
-      const GetContentCallback& get_content_callback,
-      const ProgressCallback& progress_callback) OVERRIDE;
-  virtual CancelCallback CopyResource(
+      const std::string& resource_id,
+      const google_apis::DownloadActionCallback& download_action_callback,
+      const google_apis::GetContentCallback& get_content_callback,
+      const google_apis::ProgressCallback& progress_callback) OVERRIDE;
+  virtual google_apis::CancelCallback CopyResource(
       const std::string& resource_id,
       const std::string& parent_resource_id,
       const std::string& new_name,
-      const GetResourceEntryCallback& callback) OVERRIDE;
+      const google_apis::GetResourceEntryCallback& callback) OVERRIDE;
   // The new resource ID for the copied document will look like
   // |resource_id| + "_copied".
-  virtual CancelCallback CopyHostedDocument(
+  virtual google_apis::CancelCallback CopyHostedDocument(
       const std::string& resource_id,
       const std::string& new_name,
-      const GetResourceEntryCallback& callback) OVERRIDE;
-  virtual CancelCallback RenameResource(
+      const google_apis::GetResourceEntryCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback RenameResource(
       const std::string& resource_id,
       const std::string& new_name,
-      const EntryActionCallback& callback) OVERRIDE;
-  virtual CancelCallback TouchResource(
+      const google_apis::EntryActionCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback TouchResource(
       const std::string& resource_id,
       const base::Time& modified_date,
       const base::Time& last_viewed_by_me_date,
-      const GetResourceEntryCallback& callback) OVERRIDE;
-  virtual CancelCallback AddResourceToDirectory(
+      const google_apis::GetResourceEntryCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback AddResourceToDirectory(
       const std::string& parent_resource_id,
       const std::string& resource_id,
-      const EntryActionCallback& callback) OVERRIDE;
-  virtual CancelCallback RemoveResourceFromDirectory(
+      const google_apis::EntryActionCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback RemoveResourceFromDirectory(
       const std::string& parent_resource_id,
       const std::string& resource_id,
-      const EntryActionCallback& callback) OVERRIDE;
-  virtual CancelCallback AddNewDirectory(
+      const google_apis::EntryActionCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback AddNewDirectory(
       const std::string& parent_resource_id,
       const std::string& directory_name,
-      const GetResourceEntryCallback& callback) OVERRIDE;
-  virtual CancelCallback InitiateUploadNewFile(
-      const base::FilePath& drive_file_path,
+      const google_apis::GetResourceEntryCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback InitiateUploadNewFile(
       const std::string& content_type,
       int64 content_length,
       const std::string& parent_resource_id,
       const std::string& title,
-      const InitiateUploadCallback& callback) OVERRIDE;
-  virtual CancelCallback InitiateUploadExistingFile(
-      const base::FilePath& drive_file_path,
+      const google_apis::InitiateUploadCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback InitiateUploadExistingFile(
       const std::string& content_type,
       int64 content_length,
       const std::string& resource_id,
       const std::string& etag,
-      const InitiateUploadCallback& callback) OVERRIDE;
-  virtual CancelCallback ResumeUpload(
-      const base::FilePath& drive_file_path,
+      const google_apis::InitiateUploadCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback ResumeUpload(
       const GURL& upload_url,
       int64 start_position,
       int64 end_position,
       int64 content_length,
       const std::string& content_type,
       const base::FilePath& local_file_path,
-      const UploadRangeCallback& callback,
-      const ProgressCallback& progress_callback) OVERRIDE;
-  virtual CancelCallback GetUploadStatus(
-      const base::FilePath& drive_file_path,
+      const google_apis::UploadRangeCallback& callback,
+      const google_apis::ProgressCallback& progress_callback) OVERRIDE;
+  virtual google_apis::CancelCallback GetUploadStatus(
       const GURL& upload_url,
       int64 content_length,
-      const UploadRangeCallback& callback) OVERRIDE;
-  virtual CancelCallback AuthorizeApp(
+      const google_apis::UploadRangeCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback AuthorizeApp(
       const std::string& resource_id,
       const std::string& app_id,
-      const AuthorizeAppCallback& callback) OVERRIDE;
+      const google_apis::AuthorizeAppCallback& callback) OVERRIDE;
 
   // Adds a new file with the given parameters. On success, returns
   // HTTP_CREATED with the parsed entry.
@@ -200,15 +195,19 @@
                   const std::string& parent_resource_id,
                   const std::string& title,
                   bool shared_with_me,
-                  const GetResourceEntryCallback& callback);
+                  const google_apis::GetResourceEntryCallback& callback);
 
   // Sets the last modified time for an entry specified by |resource_id|.
   // On success, returns HTTP_SUCCESS with the parsed entry.
   // |callback| must not be null.
-  void SetLastModifiedTime(const std::string& resource_id,
-                           const base::Time& last_modified_time,
-                           const GetResourceEntryCallback& callback);
+  void SetLastModifiedTime(
+      const std::string& resource_id,
+      const base::Time& last_modified_time,
+      const google_apis::GetResourceEntryCallback& callback);
+
  private:
+  struct UploadSession;
+
   // Returns a pointer to the entry that matches |resource_id|, or NULL if
   // not found.
   base::DictionaryValue* FindEntryByResourceId(const std::string& resource_id);
@@ -217,17 +216,13 @@
   // not found.
   base::DictionaryValue* FindEntryByContentUrl(const GURL& content_url);
 
-  // Returns a pointer to the entry that matches |upload_url|, or NULL if
-  // not found.
-  base::DictionaryValue* FindEntryByUploadUrl(const GURL& upload_url);
-
   // Returns a new resource ID, which looks like "resource_id_<num>" where
   // <num> is a monotonically increasing number starting from 1.
   std::string GetNewResourceId();
 
-  // Increments |largest_changestamp_| and adds the new changestamp to
+  // Increments |largest_changestamp_| and adds the new changestamp and ETag to
   // |entry|.
-  void AddNewChangestamp(base::DictionaryValue* entry);
+  void AddNewChangestampAndETag(base::DictionaryValue* entry);
 
   // Adds a new entry based on the given parameters. |entry_kind| should be
   // "file" or "folder". Returns a pointer to the newly added entry, or NULL
@@ -245,19 +240,25 @@
   // is between |start_offset| (inclusive) and |start_offset| + |max_results|
   // (exclusive).
   // Increments *load_counter by 1 before it returns successfully.
-  void GetResourceListInternal(int64 start_changestamp,
-                               const std::string& search_query,
-                               const std::string& directory_resource_id,
-                               int start_offset,
-                               int max_results,
-                               int* load_counter,
-                               const GetResourceListCallback& callback);
+  void GetResourceListInternal(
+      int64 start_changestamp,
+      const std::string& search_query,
+      const std::string& directory_resource_id,
+      int start_offset,
+      int max_results,
+      int* load_counter,
+      const google_apis::GetResourceListCallback& callback);
+
+  // Returns new upload session URL.
+  GURL GetNewUploadSessionUrl();
 
   scoped_ptr<base::DictionaryValue> resource_list_value_;
   scoped_ptr<base::Value> account_metadata_value_;
   scoped_ptr<base::Value> app_info_value_;
+  std::map<GURL, UploadSession> upload_sessions_;
   int64 largest_changestamp_;
   int64 published_date_seq_;
+  int64 next_upload_sequence_number_;
   int default_max_results_;
   int resource_id_count_;
   int resource_list_load_count_;
@@ -270,6 +271,6 @@
   DISALLOW_COPY_AND_ASSIGN(FakeDriveService);
 };
 
-}  // namespace google_apis
+}  // namespace drive
 
 #endif  // CHROME_BROWSER_DRIVE_FAKE_DRIVE_SERVICE_H_
diff --git a/chrome/browser/drive/fake_drive_service_unittest.cc b/chrome/browser/drive/fake_drive_service_unittest.cc
index 20bd5bf..26334d5 100644
--- a/chrome/browser/drive/fake_drive_service_unittest.cc
+++ b/chrome/browser/drive/fake_drive_service_unittest.cc
@@ -9,6 +9,7 @@
 
 #include "base/file_util.h"
 #include "base/files/scoped_temp_dir.h"
+#include "base/md5.h"
 #include "base/run_loop.h"
 #include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
@@ -20,7 +21,25 @@
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace google_apis {
+using google_apis::AboutResource;
+using google_apis::AppList;
+using google_apis::GDataErrorCode;
+using google_apis::GDATA_NO_CONNECTION;
+using google_apis::GDATA_OTHER_ERROR;
+using google_apis::GetContentCallback;
+using google_apis::HTTP_CREATED;
+using google_apis::HTTP_NOT_FOUND;
+using google_apis::HTTP_PRECONDITION;
+using google_apis::HTTP_RESUME_INCOMPLETE;
+using google_apis::HTTP_SUCCESS;
+using google_apis::Link;
+using google_apis::ProgressCallback;
+using google_apis::ResourceEntry;
+using google_apis::ResourceList;
+using google_apis::UploadRangeResponse;
+namespace test_util = google_apis::test_util;
+
+namespace drive {
 
 namespace {
 
@@ -40,7 +59,7 @@
   // Returns true if the resource identified by |resource_id| exists.
   bool Exists(const std::string& resource_id) {
     scoped_ptr<ResourceEntry> resource_entry = FindEntry(resource_id);
-    return resource_entry;
+    return resource_entry && !resource_entry->deleted();
   }
 
   // Adds a new directory at |parent_resource_id| with the given name.
@@ -91,7 +110,7 @@
 
 TEST_F(FakeDriveServiceTest, GetAllResourceList) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
   scoped_ptr<ResourceList> resource_list;
@@ -108,7 +127,7 @@
 
 TEST_F(FakeDriveServiceTest, GetAllResourceList_Offline) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   fake_service_.set_offline(true);
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
@@ -123,7 +142,7 @@
 
 TEST_F(FakeDriveServiceTest, GetResourceListInDirectory_InRootDirectory) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
   scoped_ptr<ResourceList> resource_list;
@@ -141,7 +160,7 @@
 
 TEST_F(FakeDriveServiceTest, GetResourceListInDirectory_InNonRootDirectory) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
   scoped_ptr<ResourceList> resource_list;
@@ -160,7 +179,7 @@
 
 TEST_F(FakeDriveServiceTest, GetResourceListInDirectory_Offline) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   fake_service_.set_offline(true);
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
@@ -176,7 +195,7 @@
 
 TEST_F(FakeDriveServiceTest, Search) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
   scoped_ptr<ResourceList> resource_list;
@@ -194,7 +213,7 @@
 
 TEST_F(FakeDriveServiceTest, Search_WithAttribute) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
   scoped_ptr<ResourceList> resource_list;
@@ -212,14 +231,14 @@
 
 TEST_F(FakeDriveServiceTest, Search_MultipleQueries) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
   scoped_ptr<ResourceList> resource_list;
   fake_service_.Search(
       "Directory 1",  // search_query
       test_util::CreateCopyResultCallback(&error, &resource_list));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   ASSERT_TRUE(resource_list);
@@ -229,7 +248,7 @@
   fake_service_.Search(
       "\"Directory 1\"",  // search_query
       test_util::CreateCopyResultCallback(&error, &resource_list));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   ASSERT_TRUE(resource_list);
@@ -239,7 +258,7 @@
 
 TEST_F(FakeDriveServiceTest, Search_Offline) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   fake_service_.set_offline(true);
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
@@ -247,15 +266,40 @@
   fake_service_.Search(
       "Directory 1",  // search_query
       test_util::CreateCopyResultCallback(&error, &resource_list));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(GDATA_NO_CONNECTION, error);
   EXPECT_FALSE(resource_list);
 }
 
+TEST_F(FakeDriveServiceTest, Search_Deleted) {
+  ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
+      "gdata/root_feed.json"));
+
+  GDataErrorCode error = GDATA_OTHER_ERROR;
+  fake_service_.DeleteResource("file:2_file_resource_id",
+                               std::string(),  // etag
+                               test_util::CreateCopyResultCallback(&error));
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(HTTP_SUCCESS, error);
+
+  error = GDATA_OTHER_ERROR;
+  scoped_ptr<ResourceList> resource_list;
+  fake_service_.Search(
+      "File",  // search_query
+      test_util::CreateCopyResultCallback(&error, &resource_list));
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_EQ(HTTP_SUCCESS, error);
+  ASSERT_TRUE(resource_list);
+  // Do some sanity check. There are 4 entries that contain "File" in their
+  // titles and one of them is deleted.
+  EXPECT_EQ(3U, resource_list->entries().size());
+}
+
 TEST_F(FakeDriveServiceTest, SearchByTitle) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
   scoped_ptr<ResourceList> resource_list;
@@ -263,7 +307,7 @@
       "1.txt",  // title
       fake_service_.GetRootResourceId(),  // directory_resource_id
       test_util::CreateCopyResultCallback(&error, &resource_list));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   ASSERT_TRUE(resource_list);
@@ -274,7 +318,7 @@
 
 TEST_F(FakeDriveServiceTest, SearchByTitle_EmptyDirectoryResourceId) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
   scoped_ptr<ResourceList> resource_list;
@@ -282,7 +326,7 @@
       "1.txt",  // title
       "",  // directory resource id
       test_util::CreateCopyResultCallback(&error, &resource_list));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   ASSERT_TRUE(resource_list);
@@ -293,7 +337,7 @@
 
 TEST_F(FakeDriveServiceTest, SearchByTitle_Offline) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   fake_service_.set_offline(true);
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
@@ -302,7 +346,7 @@
       "Directory 1",  // title
       fake_service_.GetRootResourceId(),  // directory_resource_id
       test_util::CreateCopyResultCallback(&error, &resource_list));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(GDATA_NO_CONNECTION, error);
   EXPECT_FALSE(resource_list);
@@ -310,18 +354,18 @@
 
 TEST_F(FakeDriveServiceTest, GetChangeList_NoNewEntries) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   // Load the account_metadata.json as well to add the largest changestamp
   // (654321) to the existing entries.
   ASSERT_TRUE(fake_service_.LoadAccountMetadataForWapi(
-      "chromeos/gdata/account_metadata.json"));
+      "gdata/account_metadata.json"));
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
   scoped_ptr<ResourceList> resource_list;
   fake_service_.GetChangeList(
       654321 + 1,  // start_changestamp
       test_util::CreateCopyResultCallback(&error, &resource_list));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   ASSERT_TRUE(resource_list);
@@ -334,11 +378,11 @@
 
 TEST_F(FakeDriveServiceTest, GetChangeList_WithNewEntry) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   // Load the account_metadata.json as well to add the largest changestamp
   // (654321) to the existing entries.
   ASSERT_TRUE(fake_service_.LoadAccountMetadataForWapi(
-      "chromeos/gdata/account_metadata.json"));
+      "gdata/account_metadata.json"));
   // Add a new directory in the root directory. The new directory will have
   // the changestamp of 654322.
   ASSERT_TRUE(AddNewDirectory(
@@ -350,7 +394,7 @@
   fake_service_.GetChangeList(
       654321 + 1,  // start_changestamp
       test_util::CreateCopyResultCallback(&error, &resource_list));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   ASSERT_TRUE(resource_list);
@@ -362,7 +406,7 @@
 
 TEST_F(FakeDriveServiceTest, GetChangeList_Offline) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   fake_service_.set_offline(true);
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
@@ -370,22 +414,59 @@
   fake_service_.GetChangeList(
       654321,  // start_changestamp
       test_util::CreateCopyResultCallback(&error, &resource_list));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(GDATA_NO_CONNECTION, error);
   EXPECT_FALSE(resource_list);
 }
 
+TEST_F(FakeDriveServiceTest, GetChangeList_DeletedEntry) {
+  ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
+      "gdata/root_feed.json"));
+  // Load the account_metadata.json as well to add the largest changestamp
+  // (654321) to the existing entries.
+  ASSERT_TRUE(fake_service_.LoadAccountMetadataForWapi(
+      "gdata/account_metadata.json"));
+  // Add a new directory in the root directory. The new directory will have
+  // the changestamp of 654322.
+  ASSERT_TRUE(Exists("file:2_file_resource_id"));
+
+  GDataErrorCode error = GDATA_OTHER_ERROR;
+  fake_service_.DeleteResource("file:2_file_resource_id",
+                               std::string(),  // etag
+                               test_util::CreateCopyResultCallback(&error));
+  base::RunLoop().RunUntilIdle();
+  ASSERT_EQ(HTTP_SUCCESS, error);
+  ASSERT_FALSE(Exists("file:2_file_resource_id"));
+
+  // Get the resource list newer than 654321.
+  error = GDATA_OTHER_ERROR;
+  scoped_ptr<ResourceList> resource_list;
+  fake_service_.GetChangeList(
+      654321 + 1,  // start_changestamp
+      test_util::CreateCopyResultCallback(&error, &resource_list));
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_EQ(HTTP_SUCCESS, error);
+  ASSERT_TRUE(resource_list);
+  // The result should only contain the newly created directory.
+  ASSERT_EQ(1U, resource_list->entries().size());
+  const ResourceEntry& entry = *resource_list->entries()[0];
+  EXPECT_EQ("file:2_file_resource_id", entry.resource_id());
+  EXPECT_TRUE(entry.deleted());
+  EXPECT_EQ(1, fake_service_.change_list_load_count());
+}
+
 TEST_F(FakeDriveServiceTest, ContinueGetResourceList_GetAllResourceList) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   fake_service_.set_default_max_results(6);
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
   scoped_ptr<ResourceList> resource_list;
   fake_service_.GetAllResourceList(
       test_util::CreateCopyResultCallback(&error, &resource_list));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(HTTP_SUCCESS, error);
   ASSERT_TRUE(resource_list);
 
@@ -407,7 +488,7 @@
   fake_service_.ContinueGetResourceList(
       next_url,
       test_util::CreateCopyResultCallback(&error, &resource_list));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   ASSERT_TRUE(resource_list);
@@ -425,7 +506,7 @@
   fake_service_.ContinueGetResourceList(
       next_url,
       test_util::CreateCopyResultCallback(&error, &resource_list));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   ASSERT_TRUE(resource_list);
@@ -437,7 +518,7 @@
 TEST_F(FakeDriveServiceTest,
        ContinueGetResourceList_GetResourceListInDirectory) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   fake_service_.set_default_max_results(3);
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
@@ -445,7 +526,7 @@
   fake_service_.GetResourceListInDirectory(
       fake_service_.GetRootResourceId(),
       test_util::CreateCopyResultCallback(&error, &resource_list));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(HTTP_SUCCESS, error);
   ASSERT_TRUE(resource_list);
 
@@ -467,7 +548,7 @@
   fake_service_.ContinueGetResourceList(
       next_url,
       test_util::CreateCopyResultCallback(&error, &resource_list));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   ASSERT_TRUE(resource_list);
@@ -485,7 +566,7 @@
   fake_service_.ContinueGetResourceList(
       next_url,
       test_util::CreateCopyResultCallback(&error, &resource_list));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   ASSERT_TRUE(resource_list);
@@ -496,7 +577,7 @@
 
 TEST_F(FakeDriveServiceTest, ContinueGetResourceList_Search) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   fake_service_.set_default_max_results(2);
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
@@ -504,7 +585,7 @@
   fake_service_.Search(
       "File",  // search_query
       test_util::CreateCopyResultCallback(&error, &resource_list));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(HTTP_SUCCESS, error);
   ASSERT_TRUE(resource_list);
 
@@ -525,7 +606,7 @@
   fake_service_.ContinueGetResourceList(
       next_url,
       test_util::CreateCopyResultCallback(&error, &resource_list));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   ASSERT_TRUE(resource_list);
@@ -535,13 +616,13 @@
 
 TEST_F(FakeDriveServiceTest, ContinueGetResourceList_GetChangeList) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   fake_service_.set_default_max_results(2);
 
   // Load the account_metadata.json as well to add the largest changestamp
   // (654321) to the existing entries.
   ASSERT_TRUE(fake_service_.LoadAccountMetadataForWapi(
-      "chromeos/gdata/account_metadata.json"));
+      "gdata/account_metadata.json"));
   // Add 5 new directory in the root directory. The new directory will have
   // the changestamp of 654326.
   for (int i = 0; i < 5; ++i) {
@@ -555,7 +636,7 @@
   fake_service_.GetChangeList(
       654321 + 1,  // start_changestamp
       test_util::CreateCopyResultCallback(&error, &resource_list));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(HTTP_SUCCESS, error);
   ASSERT_TRUE(resource_list);
 
@@ -577,7 +658,7 @@
   fake_service_.ContinueGetResourceList(
       next_url,
       test_util::CreateCopyResultCallback(&error, &resource_list));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   ASSERT_TRUE(resource_list);
@@ -595,7 +676,7 @@
   fake_service_.ContinueGetResourceList(
       next_url,
       test_util::CreateCopyResultCallback(&error, &resource_list));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   ASSERT_TRUE(resource_list);
@@ -606,13 +687,13 @@
 
 TEST_F(FakeDriveServiceTest, GetAboutResource) {
   ASSERT_TRUE(fake_service_.LoadAccountMetadataForWapi(
-      "chromeos/gdata/account_metadata.json"));
+      "gdata/account_metadata.json"));
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
   scoped_ptr<AboutResource> about_resource;
   fake_service_.GetAboutResource(
       test_util::CreateCopyResultCallback(&error, &about_resource));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_SUCCESS, error);
 
@@ -625,14 +706,14 @@
 
 TEST_F(FakeDriveServiceTest, GetAboutResource_Offline) {
   ASSERT_TRUE(fake_service_.LoadAccountMetadataForWapi(
-      "chromeos/gdata/account_metadata.json"));
+      "gdata/account_metadata.json"));
   fake_service_.set_offline(true);
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
   scoped_ptr<AboutResource> about_resource;
   fake_service_.GetAboutResource(
       test_util::CreateCopyResultCallback(&error, &about_resource));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(GDATA_NO_CONNECTION, error);
   EXPECT_FALSE(about_resource);
@@ -640,13 +721,13 @@
 
 TEST_F(FakeDriveServiceTest, GetAppList) {
   ASSERT_TRUE(fake_service_.LoadAppListForDriveApi(
-      "chromeos/drive/applist.json"));
+      "drive/applist.json"));
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
   scoped_ptr<AppList> app_list;
   fake_service_.GetAppList(
       test_util::CreateCopyResultCallback(&error, &app_list));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_SUCCESS, error);
 
@@ -655,14 +736,14 @@
 
 TEST_F(FakeDriveServiceTest, GetAppList_Offline) {
   ASSERT_TRUE(fake_service_.LoadAppListForDriveApi(
-      "chromeos/drive/applist.json"));
+      "drive/applist.json"));
   fake_service_.set_offline(true);
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
   scoped_ptr<AppList> app_list;
   fake_service_.GetAppList(
       test_util::CreateCopyResultCallback(&error, &app_list));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(GDATA_NO_CONNECTION, error);
   EXPECT_FALSE(app_list);
@@ -670,7 +751,7 @@
 
 TEST_F(FakeDriveServiceTest, GetResourceEntry_ExistingFile) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
 
   const std::string kResourceId = "file:2_file_resource_id";
   GDataErrorCode error = GDATA_OTHER_ERROR;
@@ -678,7 +759,7 @@
   fake_service_.GetResourceEntry(
       kResourceId,
       test_util::CreateCopyResultCallback(&error, &resource_entry));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   ASSERT_TRUE(resource_entry);
@@ -688,7 +769,7 @@
 
 TEST_F(FakeDriveServiceTest, GetResourceEntry_NonexistingFile) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
 
   const std::string kResourceId = "file:nonexisting_resource_id";
   GDataErrorCode error = GDATA_OTHER_ERROR;
@@ -696,7 +777,7 @@
   fake_service_.GetResourceEntry(
       kResourceId,
       test_util::CreateCopyResultCallback(&error, &resource_entry));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_NOT_FOUND, error);
   ASSERT_FALSE(resource_entry);
@@ -704,7 +785,7 @@
 
 TEST_F(FakeDriveServiceTest, GetResourceEntry_Offline) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   fake_service_.set_offline(true);
 
   const std::string kResourceId = "file:2_file_resource_id";
@@ -713,7 +794,7 @@
   fake_service_.GetResourceEntry(
       kResourceId,
       test_util::CreateCopyResultCallback(&error, &resource_entry));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(GDATA_NO_CONNECTION, error);
   EXPECT_FALSE(resource_entry);
@@ -721,7 +802,7 @@
 
 TEST_F(FakeDriveServiceTest, DeleteResource_ExistingFile) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
 
   // Resource "file:2_file_resource_id" should now exist.
   ASSERT_TRUE(Exists("file:2_file_resource_id"));
@@ -730,64 +811,70 @@
   fake_service_.DeleteResource("file:2_file_resource_id",
                                std::string(),  // etag
                                test_util::CreateCopyResultCallback(&error));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   // Resource "file:2_file_resource_id" should be gone now.
   EXPECT_FALSE(Exists("file:2_file_resource_id"));
+
+  error = GDATA_OTHER_ERROR;
+  fake_service_.DeleteResource("file:2_file_resource_id",
+                               std::string(),  // etag
+                               test_util::CreateCopyResultCallback(&error));
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(HTTP_NOT_FOUND, error);
+  EXPECT_FALSE(Exists("file:2_file_resource_id"));
 }
 
 TEST_F(FakeDriveServiceTest, DeleteResource_NonexistingFile) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
   fake_service_.DeleteResource("file:nonexisting_resource_id",
                                std::string(),  // etag
                                test_util::CreateCopyResultCallback(&error));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_NOT_FOUND, error);
 }
 
 TEST_F(FakeDriveServiceTest, DeleteResource_Offline) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   fake_service_.set_offline(true);
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
   fake_service_.DeleteResource("file:2_file_resource_id",
                                std::string(),  // etag
                                test_util::CreateCopyResultCallback(&error));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(GDATA_NO_CONNECTION, error);
 }
 
 TEST_F(FakeDriveServiceTest, DownloadFile_ExistingFile) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
 
   base::ScopedTempDir temp_dir;
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
 
   std::vector<test_util::ProgressInfo> download_progress_values;
 
-  const GURL kContentUrl("https://file_content_url/");
   const base::FilePath kOutputFilePath =
       temp_dir.path().AppendASCII("whatever.txt");
   GDataErrorCode error = GDATA_OTHER_ERROR;
   base::FilePath output_file_path;
   test_util::TestGetContentCallback get_content_callback;
   fake_service_.DownloadFile(
-      base::FilePath::FromUTF8Unsafe("/drive/whatever.txt"),  // virtual path
       kOutputFilePath,
-      kContentUrl,
+      "file:2_file_resource_id",
       test_util::CreateCopyResultCallback(&error, &output_file_path),
       get_content_callback.callback(),
       base::Bind(&test_util::AppendProgressCallbackResult,
                  &download_progress_values));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   EXPECT_EQ(output_file_path, kOutputFilePath);
@@ -804,58 +891,54 @@
 
 TEST_F(FakeDriveServiceTest, DownloadFile_NonexistingFile) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
 
   base::ScopedTempDir temp_dir;
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
 
-  const GURL kContentUrl("https://non_existing_content_url/");
   const base::FilePath kOutputFilePath =
       temp_dir.path().AppendASCII("whatever.txt");
   GDataErrorCode error = GDATA_OTHER_ERROR;
   base::FilePath output_file_path;
   fake_service_.DownloadFile(
-      base::FilePath::FromUTF8Unsafe("/drive/whatever.txt"),  // virtual path
       kOutputFilePath,
-      kContentUrl,
+      "file:non_existent_file_resource_id",
       test_util::CreateCopyResultCallback(&error, &output_file_path),
       GetContentCallback(),
       ProgressCallback());
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_NOT_FOUND, error);
 }
 
 TEST_F(FakeDriveServiceTest, DownloadFile_Offline) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   fake_service_.set_offline(true);
 
   base::ScopedTempDir temp_dir;
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
 
-  const GURL kContentUrl("https://file_content_url/");
   const base::FilePath kOutputFilePath =
       temp_dir.path().AppendASCII("whatever.txt");
   GDataErrorCode error = GDATA_OTHER_ERROR;
   base::FilePath output_file_path;
   fake_service_.DownloadFile(
-      base::FilePath::FromUTF8Unsafe("/drive/whatever.txt"),  // virtual path
       kOutputFilePath,
-      kContentUrl,
+      "file:2_file_resource_id",
       test_util::CreateCopyResultCallback(&error, &output_file_path),
       GetContentCallback(),
       ProgressCallback());
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(GDATA_NO_CONNECTION, error);
 }
 
 TEST_F(FakeDriveServiceTest, CopyResource) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   ASSERT_TRUE(fake_service_.LoadAccountMetadataForWapi(
-      "chromeos/gdata/account_metadata.json"));
+      "gdata/account_metadata.json"));
 
   int64 old_largest_change_id = GetLargestChangeByAboutResource();
 
@@ -868,7 +951,7 @@
       kParentResourceId,
       "new name",
       test_util::CreateCopyResultCallback(&error, &resource_entry));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   ASSERT_TRUE(resource_entry);
@@ -883,7 +966,7 @@
 
 TEST_F(FakeDriveServiceTest, CopyResource_NonExisting) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
 
   const std::string kResourceId = "document:nonexisting_resource_id";
   GDataErrorCode error = GDATA_OTHER_ERROR;
@@ -893,16 +976,16 @@
       "folder:1_folder_resource_id",
       "new name",
       test_util::CreateCopyResultCallback(&error, &resource_entry));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_NOT_FOUND, error);
 }
 
 TEST_F(FakeDriveServiceTest, CopyResource_EmptyParentResourceId) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   ASSERT_TRUE(fake_service_.LoadAccountMetadataForWapi(
-      "chromeos/gdata/account_metadata.json"));
+      "gdata/account_metadata.json"));
 
   int64 old_largest_change_id = GetLargestChangeByAboutResource();
 
@@ -914,7 +997,7 @@
       std::string(),
       "new name",
       test_util::CreateCopyResultCallback(&error, &resource_entry));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   ASSERT_TRUE(resource_entry);
@@ -929,7 +1012,7 @@
 
 TEST_F(FakeDriveServiceTest, CopyResource_Offline) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   fake_service_.set_offline(true);
 
   const std::string kResourceId = "file:2_file_resource_id";
@@ -940,7 +1023,7 @@
       "folder:1_folder_resource_id",
       "new name",
       test_util::CreateCopyResultCallback(&error, &resource_entry));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(GDATA_NO_CONNECTION, error);
   EXPECT_FALSE(resource_entry);
@@ -948,9 +1031,9 @@
 
 TEST_F(FakeDriveServiceTest, CopyHostedDocument_Existing) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   ASSERT_TRUE(fake_service_.LoadAccountMetadataForWapi(
-      "chromeos/gdata/account_metadata.json"));
+      "gdata/account_metadata.json"));
 
   int64 old_largest_change_id = GetLargestChangeByAboutResource();
 
@@ -961,7 +1044,7 @@
       kResourceId,
       "new name",
       test_util::CreateCopyResultCallback(&error, &resource_entry));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   ASSERT_TRUE(resource_entry);
@@ -975,7 +1058,7 @@
 
 TEST_F(FakeDriveServiceTest, CopyHostedDocument_NonExisting) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
 
   const std::string kResourceId = "document:nonexisting_resource_id";
   GDataErrorCode error = GDATA_OTHER_ERROR;
@@ -984,14 +1067,14 @@
       kResourceId,
       "new name",
       test_util::CreateCopyResultCallback(&error, &resource_entry));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_NOT_FOUND, error);
 }
 
 TEST_F(FakeDriveServiceTest, CopyHostedDocument_Offline) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   fake_service_.set_offline(true);
 
   const std::string kResourceId = "document:5_document_resource_id";
@@ -1001,7 +1084,7 @@
       kResourceId,
       "new name",
       test_util::CreateCopyResultCallback(&error, &resource_entry));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(GDATA_NO_CONNECTION, error);
   EXPECT_FALSE(resource_entry);
@@ -1009,9 +1092,9 @@
 
 TEST_F(FakeDriveServiceTest, RenameResource_ExistingFile) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   ASSERT_TRUE(fake_service_.LoadAccountMetadataForWapi(
-      "chromeos/gdata/account_metadata.json"));
+      "gdata/account_metadata.json"));
 
   int64 old_largest_change_id = GetLargestChangeByAboutResource();
 
@@ -1021,7 +1104,7 @@
   fake_service_.RenameResource(kResourceId,
                                "new name",
                                test_util::CreateCopyResultCallback(&error));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_SUCCESS, error);
 
@@ -1035,7 +1118,7 @@
 
 TEST_F(FakeDriveServiceTest, RenameResource_NonexistingFile) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
 
   const std::string kResourceId = "file:nonexisting_file";
 
@@ -1043,14 +1126,14 @@
   fake_service_.RenameResource(kResourceId,
                                "new name",
                                test_util::CreateCopyResultCallback(&error));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_NOT_FOUND, error);
 }
 
 TEST_F(FakeDriveServiceTest, RenameResource_Offline) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   fake_service_.set_offline(true);
 
   const std::string kResourceId = "file:2_file_resource_id";
@@ -1059,16 +1142,16 @@
   fake_service_.RenameResource(kResourceId,
                                "new name",
                                test_util::CreateCopyResultCallback(&error));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(GDATA_NO_CONNECTION, error);
 }
 
 TEST_F(FakeDriveServiceTest, TouchResource_ExistingFile) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   ASSERT_TRUE(fake_service_.LoadAccountMetadataForWapi(
-      "chromeos/gdata/account_metadata.json"));
+      "gdata/account_metadata.json"));
 
   int64 old_largest_change_id = GetLargestChangeByAboutResource();
 
@@ -1084,7 +1167,7 @@
       base::Time::FromUTCExploded(kModifiedDate),
       base::Time::FromUTCExploded(kLastViewedByMeDate),
       test_util::CreateCopyResultCallback(&error, &entry));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_SUCCESS, error);
 
@@ -1101,7 +1184,7 @@
 
 TEST_F(FakeDriveServiceTest, TouchResource_NonexistingFile) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
 
   const std::string kResourceId = "file:nonexisting_file";
   const base::Time::Exploded kModifiedDate = {2012, 7, 0, 19, 15, 59, 13, 123};
@@ -1115,14 +1198,14 @@
       base::Time::FromUTCExploded(kModifiedDate),
       base::Time::FromUTCExploded(kLastViewedByMeDate),
       test_util::CreateCopyResultCallback(&error, &entry));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_NOT_FOUND, error);
 }
 
 TEST_F(FakeDriveServiceTest, TouchResource_Offline) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   fake_service_.set_offline(true);
 
   const std::string kResourceId = "file:2_file_resource_id";
@@ -1137,16 +1220,16 @@
       base::Time::FromUTCExploded(kModifiedDate),
       base::Time::FromUTCExploded(kLastViewedByMeDate),
       test_util::CreateCopyResultCallback(&error, &entry));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(GDATA_NO_CONNECTION, error);
 }
 
 TEST_F(FakeDriveServiceTest, AddResourceToDirectory_FileInRootDirectory) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   ASSERT_TRUE(fake_service_.LoadAccountMetadataForWapi(
-      "chromeos/gdata/account_metadata.json"));
+      "gdata/account_metadata.json"));
 
   int64 old_largest_change_id = GetLargestChangeByAboutResource();
 
@@ -1163,7 +1246,7 @@
       kNewParentResourceId,
       kResourceId,
       test_util::CreateCopyResultCallback(&error));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_SUCCESS, error);
 
@@ -1177,9 +1260,9 @@
 
 TEST_F(FakeDriveServiceTest, AddResourceToDirectory_FileInNonRootDirectory) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   ASSERT_TRUE(fake_service_.LoadAccountMetadataForWapi(
-      "chromeos/gdata/account_metadata.json"));
+      "gdata/account_metadata.json"));
 
   int64 old_largest_change_id = GetLargestChangeByAboutResource();
 
@@ -1196,7 +1279,7 @@
       kNewParentResourceId,
       kResourceId,
       test_util::CreateCopyResultCallback(&error));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_SUCCESS, error);
 
@@ -1210,7 +1293,7 @@
 
 TEST_F(FakeDriveServiceTest, AddResourceToDirectory_NonexistingFile) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
 
   const std::string kResourceId = "file:nonexisting_file";
   const std::string kNewParentResourceId = "folder:1_folder_resource_id";
@@ -1220,16 +1303,16 @@
       kNewParentResourceId,
       kResourceId,
       test_util::CreateCopyResultCallback(&error));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_NOT_FOUND, error);
 }
 
 TEST_F(FakeDriveServiceTest, AddResourceToDirectory_OrphanFile) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   ASSERT_TRUE(fake_service_.LoadAccountMetadataForWapi(
-      "chromeos/gdata/account_metadata.json"));
+      "gdata/account_metadata.json"));
 
   int64 old_largest_change_id = GetLargestChangeByAboutResource();
 
@@ -1245,7 +1328,7 @@
       kNewParentResourceId,
       kResourceId,
       test_util::CreateCopyResultCallback(&error));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_SUCCESS, error);
 
@@ -1259,7 +1342,7 @@
 
 TEST_F(FakeDriveServiceTest, AddResourceToDirectory_Offline) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   fake_service_.set_offline(true);
 
   const std::string kResourceId = "file:2_file_resource_id";
@@ -1270,16 +1353,16 @@
       kNewParentResourceId,
       kResourceId,
       test_util::CreateCopyResultCallback(&error));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(GDATA_NO_CONNECTION, error);
 }
 
 TEST_F(FakeDriveServiceTest, RemoveResourceFromDirectory_ExistingFile) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   ASSERT_TRUE(fake_service_.LoadAccountMetadataForWapi(
-      "chromeos/gdata/account_metadata.json"));
+      "gdata/account_metadata.json"));
 
   int64 old_largest_change_id = GetLargestChangeByAboutResource();
 
@@ -1298,7 +1381,7 @@
       kParentResourceId,
       kResourceId,
       test_util::CreateCopyResultCallback(&error));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_SUCCESS, error);
 
@@ -1314,7 +1397,7 @@
 
 TEST_F(FakeDriveServiceTest, RemoveResourceFromDirectory_NonexistingFile) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
 
   const std::string kResourceId = "file:nonexisting_file";
   const std::string kParentResourceId = "folder:1_folder_resource_id";
@@ -1324,14 +1407,14 @@
       kParentResourceId,
       kResourceId,
       test_util::CreateCopyResultCallback(&error));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_NOT_FOUND, error);
 }
 
 TEST_F(FakeDriveServiceTest, RemoveResourceFromDirectory_OrphanFile) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
 
   const std::string kResourceId = "file:1_orphanfile_resource_id";
   const std::string kParentResourceId = fake_service_.GetRootResourceId();
@@ -1341,14 +1424,14 @@
       kParentResourceId,
       kResourceId,
       test_util::CreateCopyResultCallback(&error));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_NOT_FOUND, error);
 }
 
 TEST_F(FakeDriveServiceTest, RemoveResourceFromDirectory_Offline) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   fake_service_.set_offline(true);
 
   const std::string kResourceId = "file:subdirectory_file_1_id";
@@ -1359,16 +1442,16 @@
       kParentResourceId,
       kResourceId,
       test_util::CreateCopyResultCallback(&error));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(GDATA_NO_CONNECTION, error);
 }
 
 TEST_F(FakeDriveServiceTest, AddNewDirectory_ToRootDirectory) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   ASSERT_TRUE(fake_service_.LoadAccountMetadataForWapi(
-      "chromeos/gdata/account_metadata.json"));
+      "gdata/account_metadata.json"));
 
   int64 old_largest_change_id = GetLargestChangeByAboutResource();
 
@@ -1378,7 +1461,7 @@
       fake_service_.GetRootResourceId(),
       "new directory",
       test_util::CreateCopyResultCallback(&error, &resource_entry));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_CREATED, error);
   ASSERT_TRUE(resource_entry);
@@ -1394,9 +1477,9 @@
 
 TEST_F(FakeDriveServiceTest, AddNewDirectory_ToRootDirectoryOnEmptyFileSystem) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/empty_feed.json"));
+      "gdata/empty_feed.json"));
   ASSERT_TRUE(fake_service_.LoadAccountMetadataForWapi(
-      "chromeos/gdata/account_metadata.json"));
+      "gdata/account_metadata.json"));
 
   int64 old_largest_change_id = GetLargestChangeByAboutResource();
 
@@ -1406,7 +1489,7 @@
       fake_service_.GetRootResourceId(),
       "new directory",
       test_util::CreateCopyResultCallback(&error, &resource_entry));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_CREATED, error);
   ASSERT_TRUE(resource_entry);
@@ -1422,9 +1505,9 @@
 
 TEST_F(FakeDriveServiceTest, AddNewDirectory_ToNonRootDirectory) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   ASSERT_TRUE(fake_service_.LoadAccountMetadataForWapi(
-      "chromeos/gdata/account_metadata.json"));
+      "gdata/account_metadata.json"));
 
   int64 old_largest_change_id = GetLargestChangeByAboutResource();
 
@@ -1436,7 +1519,7 @@
       kParentResourceId,
       "new directory",
       test_util::CreateCopyResultCallback(&error, &resource_entry));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_CREATED, error);
   ASSERT_TRUE(resource_entry);
@@ -1451,7 +1534,7 @@
 
 TEST_F(FakeDriveServiceTest, AddNewDirectory_ToNonexistingDirectory) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
 
   const std::string kParentResourceId = "folder:nonexisting_resource_id";
 
@@ -1461,7 +1544,7 @@
       kParentResourceId,
       "new directory",
       test_util::CreateCopyResultCallback(&error, &resource_entry));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_NOT_FOUND, error);
   EXPECT_FALSE(resource_entry);
@@ -1469,7 +1552,7 @@
 
 TEST_F(FakeDriveServiceTest, AddNewDirectory_Offline) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   fake_service_.set_offline(true);
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
@@ -1478,7 +1561,7 @@
       fake_service_.GetRootResourceId(),
       "new directory",
       test_util::CreateCopyResultCallback(&error, &resource_entry));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(GDATA_NO_CONNECTION, error);
   EXPECT_FALSE(resource_entry);
@@ -1486,19 +1569,18 @@
 
 TEST_F(FakeDriveServiceTest, InitiateUploadNewFile_Offline) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   fake_service_.set_offline(true);
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
   GURL upload_location;
   fake_service_.InitiateUploadNewFile(
-      base::FilePath(FILE_PATH_LITERAL("drive/Directory 1")),
       "test/foo",
       13,
       "folder:1_folder_resource_id",
       "new file.foo",
       test_util::CreateCopyResultCallback(&error, &upload_location));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(GDATA_NO_CONNECTION, error);
   EXPECT_TRUE(upload_location.is_empty());
@@ -1506,18 +1588,17 @@
 
 TEST_F(FakeDriveServiceTest, InitiateUploadNewFile_NotFound) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
   GURL upload_location;
   fake_service_.InitiateUploadNewFile(
-      base::FilePath(FILE_PATH_LITERAL("drive/Directory 1")),
       "test/foo",
       13,
       "non_existent",
       "new file.foo",
       test_util::CreateCopyResultCallback(&error, &upload_location));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_NOT_FOUND, error);
   EXPECT_TRUE(upload_location.is_empty());
@@ -1525,18 +1606,17 @@
 
 TEST_F(FakeDriveServiceTest, InitiateUploadNewFile) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
   GURL upload_location;
   fake_service_.InitiateUploadNewFile(
-      base::FilePath(FILE_PATH_LITERAL("drive/Directory 1")),
       "test/foo",
       13,
       "folder:1_folder_resource_id",
       "new file.foo",
       test_util::CreateCopyResultCallback(&error, &upload_location));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   EXPECT_FALSE(upload_location.is_empty());
@@ -1546,19 +1626,18 @@
 
 TEST_F(FakeDriveServiceTest, InitiateUploadExistingFile_Offline) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   fake_service_.set_offline(true);
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
   GURL upload_location;
   fake_service_.InitiateUploadExistingFile(
-      base::FilePath(FILE_PATH_LITERAL("drive/File 1")),
       "test/foo",
       13,
       "file:2_file_resource_id",
       std::string(),  // etag
       test_util::CreateCopyResultCallback(&error, &upload_location));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(GDATA_NO_CONNECTION, error);
   EXPECT_TRUE(upload_location.is_empty());
@@ -1566,18 +1645,17 @@
 
 TEST_F(FakeDriveServiceTest, InitiateUploadExistingFile_NotFound) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
   GURL upload_location;
   fake_service_.InitiateUploadExistingFile(
-      base::FilePath(FILE_PATH_LITERAL("drive/File 1")),
       "test/foo",
       13,
       "non_existent",
       std::string(),  // etag
       test_util::CreateCopyResultCallback(&error, &upload_location));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_NOT_FOUND, error);
   EXPECT_TRUE(upload_location.is_empty());
@@ -1585,18 +1663,17 @@
 
 TEST_F(FakeDriveServiceTest, InitiateUploadExistingFile_WrongETag) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
   GURL upload_location;
   fake_service_.InitiateUploadExistingFile(
-      base::FilePath(FILE_PATH_LITERAL("drive/File 1.txt")),
       "text/plain",
       13,
       "file:2_file_resource_id",
       "invalid_etag",
       test_util::CreateCopyResultCallback(&error, &upload_location));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_PRECONDITION, error);
   EXPECT_TRUE(upload_location.is_empty());
@@ -1604,38 +1681,35 @@
 
 TEST_F(FakeDriveServiceTest, InitiateUpload_ExistingFile) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
   GURL upload_location;
   fake_service_.InitiateUploadExistingFile(
-      base::FilePath(FILE_PATH_LITERAL("drive/File 1.txt")),
       "text/plain",
       13,
       "file:2_file_resource_id",
       "\"HhMOFgxXHit7ImBr\"",
       test_util::CreateCopyResultCallback(&error, &upload_location));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_SUCCESS, error);
-  EXPECT_EQ(GURL("https://2_file_link_resumable_create_media?mode=existing"),
-            upload_location);
+  EXPECT_TRUE(upload_location.is_valid());
 }
 
 TEST_F(FakeDriveServiceTest, ResumeUpload_Offline) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
   GURL upload_location;
   fake_service_.InitiateUploadNewFile(
-      base::FilePath(FILE_PATH_LITERAL("drive/Directory 1/new file.foo")),
       "test/foo",
       15,
       "folder:1_folder_resource_id",
       "new file.foo",
       test_util::CreateCopyResultCallback(&error, &upload_location));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   EXPECT_FALSE(upload_location.is_empty());
@@ -1647,13 +1721,12 @@
   UploadRangeResponse response;
   scoped_ptr<ResourceEntry> entry;
   fake_service_.ResumeUpload(
-      base::FilePath(FILE_PATH_LITERAL("drive/Directory 1/new file.foo")),
       upload_location,
       0, 13, 15, "test/foo",
       base::FilePath(),
       test_util::CreateCopyResultCallback(&response, &entry),
       ProgressCallback());
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(GDATA_NO_CONNECTION, response.code);
   EXPECT_FALSE(entry.get());
@@ -1661,50 +1734,54 @@
 
 TEST_F(FakeDriveServiceTest, ResumeUpload_NotFound) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
   GURL upload_location;
   fake_service_.InitiateUploadNewFile(
-      base::FilePath(FILE_PATH_LITERAL("drive/Directory 1/new file.foo")),
       "test/foo",
       15,
       "folder:1_folder_resource_id",
       "new file.foo",
       test_util::CreateCopyResultCallback(&error, &upload_location));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   ASSERT_EQ(HTTP_SUCCESS, error);
 
   UploadRangeResponse response;
   scoped_ptr<ResourceEntry> entry;
   fake_service_.ResumeUpload(
-      base::FilePath(FILE_PATH_LITERAL("drive/Directory 1/new file.foo")),
       GURL("https://foo.com/"),
       0, 13, 15, "test/foo",
       base::FilePath(),
       test_util::CreateCopyResultCallback(&response, &entry),
       ProgressCallback());
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_NOT_FOUND, response.code);
   EXPECT_FALSE(entry.get());
 }
 
 TEST_F(FakeDriveServiceTest, ResumeUpload_ExistingFile) {
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+  base::FilePath local_file_path =
+      temp_dir.path().Append(FILE_PATH_LITERAL("File 1.txt"));
+  std::string contents("hogefugapiyo");
+  ASSERT_TRUE(test_util::WriteStringToFile(local_file_path, contents));
+
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
   GURL upload_location;
   fake_service_.InitiateUploadExistingFile(
-      base::FilePath(FILE_PATH_LITERAL("drive/File 1.txt")),
       "text/plain",
-      15,
+      contents.size(),
       "file:2_file_resource_id",
       "\"HhMOFgxXHit7ImBr\"",
       test_util::CreateCopyResultCallback(&error, &upload_location));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   ASSERT_EQ(HTTP_SUCCESS, error);
 
@@ -1712,57 +1789,65 @@
   scoped_ptr<ResourceEntry> entry;
   std::vector<test_util::ProgressInfo> upload_progress_values;
   fake_service_.ResumeUpload(
-      base::FilePath(FILE_PATH_LITERAL("drive/File 1.txt")),
       upload_location,
-      0, 13, 15, "text/plain",
-      base::FilePath(),
+      0, contents.size() / 2, contents.size(), "text/plain",
+      local_file_path,
       test_util::CreateCopyResultCallback(&response, &entry),
       base::Bind(&test_util::AppendProgressCallbackResult,
                  &upload_progress_values));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_RESUME_INCOMPLETE, response.code);
   EXPECT_FALSE(entry.get());
   ASSERT_TRUE(!upload_progress_values.empty());
   EXPECT_TRUE(base::STLIsSorted(upload_progress_values));
   EXPECT_LE(0, upload_progress_values.front().first);
-  EXPECT_GE(13, upload_progress_values.back().first);
+  EXPECT_GE(static_cast<int64>(contents.size() / 2),
+            upload_progress_values.back().first);
 
   upload_progress_values.clear();
   fake_service_.ResumeUpload(
-      base::FilePath(FILE_PATH_LITERAL("drive/File 1.txt")),
       upload_location,
-      13, 15, 15, "text/plain",
-      base::FilePath(),
+      contents.size() / 2, contents.size(), contents.size(), "text/plain",
+      local_file_path,
       test_util::CreateCopyResultCallback(&response, &entry),
       base::Bind(&test_util::AppendProgressCallbackResult,
                  &upload_progress_values));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_SUCCESS, response.code);
   EXPECT_TRUE(entry.get());
-  EXPECT_EQ(15L, entry->file_size());
+  EXPECT_EQ(static_cast<int64>(contents.size()),
+            entry->file_size());
   EXPECT_TRUE(Exists(entry->resource_id()));
   ASSERT_TRUE(!upload_progress_values.empty());
   EXPECT_TRUE(base::STLIsSorted(upload_progress_values));
   EXPECT_LE(0, upload_progress_values.front().first);
-  EXPECT_GE(2, upload_progress_values.back().first);
+  EXPECT_GE(static_cast<int64>(contents.size() - contents.size() / 2),
+            upload_progress_values.back().first);
+  EXPECT_EQ(base::MD5String(contents), entry->file_md5());
 }
 
 TEST_F(FakeDriveServiceTest, ResumeUpload_NewFile) {
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+  base::FilePath local_file_path =
+      temp_dir.path().Append(FILE_PATH_LITERAL("new file.foo"));
+  std::string contents("hogefugapiyo");
+  ASSERT_TRUE(test_util::WriteStringToFile(local_file_path, contents));
+
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
   GURL upload_location;
   fake_service_.InitiateUploadNewFile(
-      base::FilePath(FILE_PATH_LITERAL("drive/Directory 1/new file.foo")),
       "test/foo",
-      15,
+      contents.size(),
       "folder:1_folder_resource_id",
       "new file.foo",
       test_util::CreateCopyResultCallback(&error, &upload_location));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   EXPECT_FALSE(upload_location.is_empty());
@@ -1773,48 +1858,49 @@
   scoped_ptr<ResourceEntry> entry;
   std::vector<test_util::ProgressInfo> upload_progress_values;
   fake_service_.ResumeUpload(
-      base::FilePath(FILE_PATH_LITERAL("drive/Directory 1/new file.foo")),
       upload_location,
-      0, 13, 15, "test/foo",
-      base::FilePath(),
+      0, contents.size() / 2, contents.size(), "test/foo",
+      local_file_path,
       test_util::CreateCopyResultCallback(&response, &entry),
       base::Bind(&test_util::AppendProgressCallbackResult,
                  &upload_progress_values));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_RESUME_INCOMPLETE, response.code);
   EXPECT_FALSE(entry.get());
   ASSERT_TRUE(!upload_progress_values.empty());
   EXPECT_TRUE(base::STLIsSorted(upload_progress_values));
   EXPECT_LE(0, upload_progress_values.front().first);
-  EXPECT_GE(13, upload_progress_values.back().first);
+  EXPECT_GE(static_cast<int64>(contents.size() / 2),
+            upload_progress_values.back().first);
 
   upload_progress_values.clear();
   fake_service_.ResumeUpload(
-      base::FilePath(FILE_PATH_LITERAL("drive/Directory 1/new file.foo")),
       upload_location,
-      13, 15, 15, "test/foo",
-      base::FilePath(),
+      contents.size() / 2, contents.size(), contents.size(), "test/foo",
+      local_file_path,
       test_util::CreateCopyResultCallback(&response, &entry),
       base::Bind(&test_util::AppendProgressCallbackResult,
                  &upload_progress_values));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_CREATED, response.code);
   EXPECT_TRUE(entry.get());
-  EXPECT_EQ(15L, entry->file_size());
+  EXPECT_EQ(static_cast<int64>(contents.size()), entry->file_size());
   EXPECT_TRUE(Exists(entry->resource_id()));
   ASSERT_TRUE(!upload_progress_values.empty());
   EXPECT_TRUE(base::STLIsSorted(upload_progress_values));
   EXPECT_LE(0, upload_progress_values.front().first);
-  EXPECT_GE(2, upload_progress_values.back().first);
+  EXPECT_GE(static_cast<int64>(contents.size() - contents.size() / 2),
+            upload_progress_values.back().first);
+  EXPECT_EQ(base::MD5String(contents), entry->file_md5());
 }
 
 TEST_F(FakeDriveServiceTest, AddNewFile_ToRootDirectory) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   ASSERT_TRUE(fake_service_.LoadAccountMetadataForWapi(
-      "chromeos/gdata/account_metadata.json"));
+      "gdata/account_metadata.json"));
 
   int64 old_largest_change_id = GetLargestChangeByAboutResource();
 
@@ -1831,7 +1917,7 @@
       kTitle,
       false,  // shared_with_me
       test_util::CreateCopyResultCallback(&error, &resource_entry));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_CREATED, error);
   ASSERT_TRUE(resource_entry);
@@ -1846,13 +1932,14 @@
   // Should be incremented as a new directory was created.
   EXPECT_EQ(old_largest_change_id + 1, fake_service_.largest_changestamp());
   EXPECT_EQ(old_largest_change_id + 1, GetLargestChangeByAboutResource());
+  EXPECT_EQ(base::MD5String(kContentData), resource_entry->file_md5());
 }
 
 TEST_F(FakeDriveServiceTest, AddNewFile_ToRootDirectoryOnEmptyFileSystem) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/empty_feed.json"));
+      "gdata/empty_feed.json"));
   ASSERT_TRUE(fake_service_.LoadAccountMetadataForWapi(
-      "chromeos/gdata/account_metadata.json"));
+      "gdata/account_metadata.json"));
 
   int64 old_largest_change_id = GetLargestChangeByAboutResource();
 
@@ -1869,7 +1956,7 @@
       kTitle,
       false,  // shared_with_me
       test_util::CreateCopyResultCallback(&error, &resource_entry));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_CREATED, error);
   ASSERT_TRUE(resource_entry);
@@ -1884,13 +1971,14 @@
   // Should be incremented as a new directory was created.
   EXPECT_EQ(old_largest_change_id + 1, fake_service_.largest_changestamp());
   EXPECT_EQ(old_largest_change_id + 1, GetLargestChangeByAboutResource());
+  EXPECT_EQ(base::MD5String(kContentData), resource_entry->file_md5());
 }
 
 TEST_F(FakeDriveServiceTest, AddNewFile_ToNonRootDirectory) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   ASSERT_TRUE(fake_service_.LoadAccountMetadataForWapi(
-      "chromeos/gdata/account_metadata.json"));
+      "gdata/account_metadata.json"));
 
   int64 old_largest_change_id = GetLargestChangeByAboutResource();
 
@@ -1908,7 +1996,7 @@
       kTitle,
       false,  // shared_with_me
       test_util::CreateCopyResultCallback(&error, &resource_entry));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_CREATED, error);
   ASSERT_TRUE(resource_entry);
@@ -1922,11 +2010,12 @@
   // Should be incremented as a new directory was created.
   EXPECT_EQ(old_largest_change_id + 1, fake_service_.largest_changestamp());
   EXPECT_EQ(old_largest_change_id + 1, GetLargestChangeByAboutResource());
+  EXPECT_EQ(base::MD5String(kContentData), resource_entry->file_md5());
 }
 
 TEST_F(FakeDriveServiceTest, AddNewFile_ToNonexistingDirectory) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
 
   const std::string kContentType = "text/plain";
   const std::string kContentData = "This is some test content.";
@@ -1942,7 +2031,7 @@
       kTitle,
       false,  // shared_with_me
       test_util::CreateCopyResultCallback(&error, &resource_entry));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_NOT_FOUND, error);
   EXPECT_FALSE(resource_entry);
@@ -1950,7 +2039,7 @@
 
 TEST_F(FakeDriveServiceTest, AddNewFile_Offline) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   fake_service_.set_offline(true);
 
   const std::string kContentType = "text/plain";
@@ -1966,7 +2055,7 @@
       kTitle,
       false,  // shared_with_me
       test_util::CreateCopyResultCallback(&error, &resource_entry));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(GDATA_NO_CONNECTION, error);
   EXPECT_FALSE(resource_entry);
@@ -1974,9 +2063,9 @@
 
 TEST_F(FakeDriveServiceTest, AddNewFile_SharedWithMeLabel) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   ASSERT_TRUE(fake_service_.LoadAccountMetadataForWapi(
-      "chromeos/gdata/account_metadata.json"));
+      "gdata/account_metadata.json"));
 
   const std::string kContentType = "text/plain";
   const std::string kContentData = "This is some test content.";
@@ -1993,7 +2082,7 @@
       kTitle,
       true,  // shared_with_me
       test_util::CreateCopyResultCallback(&error, &resource_entry));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_CREATED, error);
   ASSERT_TRUE(resource_entry);
@@ -2010,11 +2099,12 @@
   // Should be incremented as a new directory was created.
   EXPECT_EQ(old_largest_change_id + 1, fake_service_.largest_changestamp());
   EXPECT_EQ(old_largest_change_id + 1, GetLargestChangeByAboutResource());
+  EXPECT_EQ(base::MD5String(kContentData), resource_entry->file_md5());
 }
 
 TEST_F(FakeDriveServiceTest, SetLastModifiedTime_ExistingFile) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
 
   const std::string kResourceId = "file:2_file_resource_id";
   base::Time time;
@@ -2026,7 +2116,7 @@
       kResourceId,
       time,
       test_util::CreateCopyResultCallback(&error, &resource_entry));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   ASSERT_TRUE(resource_entry);
@@ -2035,7 +2125,7 @@
 
 TEST_F(FakeDriveServiceTest, SetLastModifiedTime_NonexistingFile) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
 
   const std::string kResourceId = "file:nonexisting_resource_id";
   base::Time time;
@@ -2047,7 +2137,7 @@
       kResourceId,
       time,
       test_util::CreateCopyResultCallback(&error, &resource_entry));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(HTTP_NOT_FOUND, error);
   EXPECT_FALSE(resource_entry);
@@ -2055,7 +2145,7 @@
 
 TEST_F(FakeDriveServiceTest, SetLastModifiedTime_Offline) {
   ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
-      "chromeos/gdata/root_feed.json"));
+      "gdata/root_feed.json"));
   fake_service_.set_offline(true);
 
   const std::string kResourceId = "file:2_file_resource_id";
@@ -2068,7 +2158,7 @@
       kResourceId,
       time,
       test_util::CreateCopyResultCallback(&error, &resource_entry));
-      base::RunLoop().RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(GDATA_NO_CONNECTION, error);
   EXPECT_FALSE(resource_entry);
@@ -2076,4 +2166,4 @@
 
 }  // namespace
 
-}  // namespace google_apis
+}  // namespace drive
diff --git a/chrome/browser/drive/gdata_wapi_service.cc b/chrome/browser/drive/gdata_wapi_service.cc
index 8c8209c..689726b 100644
--- a/chrome/browser/drive/gdata_wapi_service.cc
+++ b/chrome/browser/drive/gdata_wapi_service.cc
@@ -9,22 +9,56 @@
 
 #include "base/bind.h"
 #include "base/message_loop.h"
-#include "base/strings/stringprintf.h"
 #include "base/values.h"
+#include "chrome/browser/drive/drive_api_util.h"
 #include "chrome/browser/google_apis/auth_service.h"
 #include "chrome/browser/google_apis/drive_api_parser.h"
-#include "chrome/browser/google_apis/drive_api_util.h"
 #include "chrome/browser/google_apis/gdata_wapi_parser.h"
 #include "chrome/browser/google_apis/gdata_wapi_requests.h"
 #include "chrome/browser/google_apis/gdata_wapi_url_generator.h"
 #include "chrome/browser/google_apis/request_sender.h"
-#include "chrome/browser/google_apis/time_util.h"
 #include "content/public/browser/browser_thread.h"
-#include "net/base/url_util.h"
 
 using content::BrowserThread;
+using google_apis::AboutResource;
+using google_apis::AccountMetadata;
+using google_apis::AddResourceToDirectoryRequest;
+using google_apis::AppList;
+using google_apis::AuthorizeAppCallback;
+using google_apis::AuthorizeAppRequest;
+using google_apis::AuthService;
+using google_apis::CancelCallback;
+using google_apis::CopyHostedDocumentRequest;
+using google_apis::CreateDirectoryRequest;
+using google_apis::DeleteResourceRequest;
+using google_apis::DownloadActionCallback;
+using google_apis::DownloadFileRequest;
+using google_apis::EntryActionCallback;
+using google_apis::GDataErrorCode;
+using google_apis::GDATA_PARSE_ERROR;
+using google_apis::GetAboutResourceCallback;
+using google_apis::GetAccountMetadataRequest;
+using google_apis::GetAppListCallback;
+using google_apis::GetContentCallback;
+using google_apis::GetResourceEntryCallback;
+using google_apis::GetResourceEntryRequest;
+using google_apis::GetResourceListCallback;
+using google_apis::GetResourceListRequest;
+using google_apis::GetUploadStatusRequest;
+using google_apis::HTTP_NOT_IMPLEMENTED;
+using google_apis::InitiateUploadCallback;
+using google_apis::InitiateUploadExistingFileRequest;
+using google_apis::InitiateUploadNewFileRequest;
+using google_apis::ProgressCallback;
+using google_apis::RemoveResourceFromDirectoryRequest;
+using google_apis::RenameResourceRequest;
+using google_apis::RequestSender;
+using google_apis::ResourceEntry;
+using google_apis::ResumeUploadRequest;
+using google_apis::SearchByTitleRequest;
+using google_apis::UploadRangeCallback;
 
-namespace google_apis {
+namespace drive {
 
 namespace {
 
@@ -95,10 +129,13 @@
 
 GDataWapiService::GDataWapiService(
     net::URLRequestContextGetter* url_request_context_getter,
+    base::TaskRunner* blocking_task_runner,
     const GURL& base_url,
+    const GURL& base_download_url,
     const std::string& custom_user_agent)
     : url_request_context_getter_(url_request_context_getter),
-      url_generator_(base_url),
+      blocking_task_runner_(blocking_task_runner),
+      url_generator_(base_url, base_download_url),
       custom_user_agent_(custom_user_agent) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 }
@@ -165,13 +202,12 @@
 
   return sender_->StartRequestWithRetry(
       new GetResourceListRequest(sender_.get(),
-                                   url_request_context_getter_,
-                                   url_generator_,
-                                   GURL(),         // No override url
-                                   0,              // start changestamp
-                                   std::string(),  // empty search query
-                                   std::string(),  // no directory resource id
-                                   callback));
+                                 url_generator_,
+                                 GURL(),         // No override url
+                                 0,              // start changestamp
+                                 std::string(),  // empty search query
+                                 std::string(),  // no directory resource id
+                                 callback));
 }
 
 CancelCallback GDataWapiService::GetResourceListInDirectory(
@@ -183,13 +219,12 @@
 
   return sender_->StartRequestWithRetry(
       new GetResourceListRequest(sender_.get(),
-                                   url_request_context_getter_,
-                                   url_generator_,
-                                   GURL(),         // No override url
-                                   0,              // start changestamp
-                                   std::string(),  // empty search query
-                                   directory_resource_id,
-                                   callback));
+                                 url_generator_,
+                                 GURL(),         // No override url
+                                 0,              // start changestamp
+                                 std::string(),  // empty search query
+                                 directory_resource_id,
+                                 callback));
 }
 
 CancelCallback GDataWapiService::Search(
@@ -201,13 +236,12 @@
 
   return sender_->StartRequestWithRetry(
       new GetResourceListRequest(sender_.get(),
-                                   url_request_context_getter_,
-                                   url_generator_,
-                                   GURL(),         // No override url
-                                   0,              // start changestamp
-                                   search_query,
-                                   std::string(),  // no directory resource id
-                                   callback));
+                                 url_generator_,
+                                 GURL(),         // No override url
+                                 0,              // start changestamp
+                                 search_query,
+                                 std::string(),  // no directory resource id
+                                 callback));
 }
 
 CancelCallback GDataWapiService::SearchByTitle(
@@ -219,13 +253,11 @@
   DCHECK(!callback.is_null());
 
   return sender_->StartRequestWithRetry(
-      new SearchByTitleRequest(
-          sender_.get(),
-          url_request_context_getter_,
-          url_generator_,
-          title,
-          directory_resource_id,
-          callback));
+      new SearchByTitleRequest(sender_.get(),
+                               url_generator_,
+                               title,
+                               directory_resource_id,
+                               callback));
 }
 
 CancelCallback GDataWapiService::GetChangeList(
@@ -236,13 +268,12 @@
 
   return sender_->StartRequestWithRetry(
       new GetResourceListRequest(sender_.get(),
-                                   url_request_context_getter_,
-                                   url_generator_,
-                                   GURL(),         // No override url
-                                   start_changestamp,
-                                   std::string(),  // empty search query
-                                   std::string(),  // no directory resource id
-                                   callback));
+                                 url_generator_,
+                                 GURL(),         // No override url
+                                 start_changestamp,
+                                 std::string(),  // empty search query
+                                 std::string(),  // no directory resource id
+                                 callback));
 }
 
 CancelCallback GDataWapiService::ContinueGetResourceList(
@@ -254,13 +285,12 @@
 
   return sender_->StartRequestWithRetry(
       new GetResourceListRequest(sender_.get(),
-                                   url_request_context_getter_,
-                                   url_generator_,
-                                   override_url,
-                                   0,              // start changestamp
-                                   std::string(),  // empty search query
-                                   std::string(),  // no directory resource id
-                                   callback));
+                                 url_generator_,
+                                 override_url,
+                                 0,              // start changestamp
+                                 std::string(),  // empty search query
+                                 std::string(),  // no directory resource id
+                                 callback));
 }
 
 CancelCallback GDataWapiService::GetResourceEntry(
@@ -270,12 +300,11 @@
   DCHECK(!callback.is_null());
 
   return sender_->StartRequestWithRetry(
-      new GetResourceEntryRequest(
-          sender_.get(),
-          url_request_context_getter_,
-          url_generator_,
-          resource_id,
-          base::Bind(&ParseResourceEntryAndRun, callback)));
+      new GetResourceEntryRequest(sender_.get(),
+                                  url_generator_,
+                                  resource_id,
+                                  base::Bind(&ParseResourceEntryAndRun,
+                                             callback)));
 }
 
 CancelCallback GDataWapiService::GetAboutResource(
@@ -286,7 +315,6 @@
   return sender_->StartRequestWithRetry(
       new GetAccountMetadataRequest(
           sender_.get(),
-          url_request_context_getter_,
           url_generator_,
           base::Bind(&ParseAboutResourceAndRun, callback),
           false));  // Exclude installed apps.
@@ -298,18 +326,15 @@
   DCHECK(!callback.is_null());
 
   return sender_->StartRequestWithRetry(
-      new GetAccountMetadataRequest(
-          sender_.get(),
-          url_request_context_getter_,
-          url_generator_,
-          base::Bind(&ParseAppListAndRun, callback),
-          true));  // Include installed apps.
+      new GetAccountMetadataRequest(sender_.get(),
+                                    url_generator_,
+                                    base::Bind(&ParseAppListAndRun, callback),
+                                    true));  // Include installed apps.
 }
 
 CancelCallback GDataWapiService::DownloadFile(
-    const base::FilePath& virtual_path,
     const base::FilePath& local_cache_path,
-    const GURL& download_url,
+    const std::string& resource_id,
     const DownloadActionCallback& download_action_callback,
     const GetContentCallback& get_content_callback,
     const ProgressCallback& progress_callback) {
@@ -319,12 +344,11 @@
 
   return sender_->StartRequestWithRetry(
       new DownloadFileRequest(sender_.get(),
-                              url_request_context_getter_,
+                              url_generator_,
                               download_action_callback,
                               get_content_callback,
                               progress_callback,
-                              download_url,
-                              virtual_path,
+                              resource_id,
                               local_cache_path));
 }
 
@@ -337,11 +361,10 @@
 
   return sender_->StartRequestWithRetry(
       new DeleteResourceRequest(sender_.get(),
-                                  url_request_context_getter_,
-                                  url_generator_,
-                                  callback,
-                                  resource_id,
-                                  etag));
+                                url_generator_,
+                                callback,
+                                resource_id,
+                                etag));
 }
 
 CancelCallback GDataWapiService::AddNewDirectory(
@@ -353,12 +376,11 @@
 
   return sender_->StartRequestWithRetry(
       new CreateDirectoryRequest(sender_.get(),
-                                   url_request_context_getter_,
-                                   url_generator_,
-                                   base::Bind(&ParseResourceEntryAndRun,
-                                              callback),
-                                   parent_resource_id,
-                                   directory_name));
+                                 url_generator_,
+                                 base::Bind(&ParseResourceEntryAndRun,
+                                            callback),
+                                 parent_resource_id,
+                                 directory_name));
 }
 
 CancelCallback GDataWapiService::CopyResource(
@@ -384,13 +406,12 @@
   DCHECK(!callback.is_null());
 
   return sender_->StartRequestWithRetry(
-      new CopyHostedDocumentRequest(
-          sender_.get(),
-          url_request_context_getter_,
-          url_generator_,
-          base::Bind(&ParseResourceEntryAndRun, callback),
-          resource_id,
-          new_name));
+      new CopyHostedDocumentRequest(sender_.get(),
+                                    url_generator_,
+                                    base::Bind(&ParseResourceEntryAndRun,
+                                               callback),
+                                    resource_id,
+                                    new_name));
 }
 
 CancelCallback GDataWapiService::RenameResource(
@@ -402,11 +423,10 @@
 
   return sender_->StartRequestWithRetry(
       new RenameResourceRequest(sender_.get(),
-                                  url_request_context_getter_,
-                                  url_generator_,
-                                  callback,
-                                  resource_id,
-                                  new_name));
+                                url_generator_,
+                                callback,
+                                resource_id,
+                                new_name));
 }
 
 CancelCallback GDataWapiService::TouchResource(
@@ -437,11 +457,10 @@
 
   return sender_->StartRequestWithRetry(
       new AddResourceToDirectoryRequest(sender_.get(),
-                                          url_request_context_getter_,
-                                          url_generator_,
-                                          callback,
-                                          parent_resource_id,
-                                          resource_id));
+                                        url_generator_,
+                                        callback,
+                                        parent_resource_id,
+                                        resource_id));
 }
 
 CancelCallback GDataWapiService::RemoveResourceFromDirectory(
@@ -453,15 +472,13 @@
 
   return sender_->StartRequestWithRetry(
       new RemoveResourceFromDirectoryRequest(sender_.get(),
-                                               url_request_context_getter_,
-                                               url_generator_,
-                                               callback,
-                                               parent_resource_id,
-                                               resource_id));
+                                             url_generator_,
+                                             callback,
+                                             parent_resource_id,
+                                             resource_id));
 }
 
 CancelCallback GDataWapiService::InitiateUploadNewFile(
-    const base::FilePath& drive_file_path,
     const std::string& content_type,
     int64 content_length,
     const std::string& parent_resource_id,
@@ -473,18 +490,15 @@
 
   return sender_->StartRequestWithRetry(
       new InitiateUploadNewFileRequest(sender_.get(),
-                                         url_request_context_getter_,
-                                         url_generator_,
-                                         callback,
-                                         drive_file_path,
-                                         content_type,
-                                         content_length,
-                                         parent_resource_id,
-                                         title));
+                                       url_generator_,
+                                       callback,
+                                       content_type,
+                                       content_length,
+                                       parent_resource_id,
+                                       title));
 }
 
 CancelCallback GDataWapiService::InitiateUploadExistingFile(
-    const base::FilePath& drive_file_path,
     const std::string& content_type,
     int64 content_length,
     const std::string& resource_id,
@@ -496,18 +510,15 @@
 
   return sender_->StartRequestWithRetry(
       new InitiateUploadExistingFileRequest(sender_.get(),
-                                              url_request_context_getter_,
-                                              url_generator_,
-                                              callback,
-                                              drive_file_path,
-                                              content_type,
-                                              content_length,
-                                              resource_id,
-                                              etag));
+                                            url_generator_,
+                                            callback,
+                                            content_type,
+                                            content_length,
+                                            resource_id,
+                                            etag));
 }
 
 CancelCallback GDataWapiService::ResumeUpload(
-    const base::FilePath& drive_file_path,
     const GURL& upload_url,
     int64 start_position,
     int64 end_position,
@@ -521,20 +532,17 @@
 
   return sender_->StartRequestWithRetry(
       new ResumeUploadRequest(sender_.get(),
-                                url_request_context_getter_,
-                                callback,
-                                progress_callback,
-                                drive_file_path,
-                                upload_url,
-                                start_position,
-                                end_position,
-                                content_length,
-                                content_type,
-                                local_file_path));
+                              callback,
+                              progress_callback,
+                              upload_url,
+                              start_position,
+                              end_position,
+                              content_length,
+                              content_type,
+                              local_file_path));
 }
 
 CancelCallback GDataWapiService::GetUploadStatus(
-    const base::FilePath& drive_file_path,
     const GURL& upload_url,
     int64 content_length,
     const UploadRangeCallback& callback) {
@@ -543,11 +551,9 @@
 
   return sender_->StartRequestWithRetry(
       new GetUploadStatusRequest(sender_.get(),
-                                   url_request_context_getter_,
-                                   callback,
-                                   drive_file_path,
-                                   upload_url,
-                                   content_length));
+                                 callback,
+                                 upload_url,
+                                 content_length));
 }
 
 CancelCallback GDataWapiService::AuthorizeApp(
@@ -558,13 +564,11 @@
   DCHECK(!callback.is_null());
 
   return sender_->StartRequestWithRetry(
-      new AuthorizeAppRequest(
-          sender_.get(),
-          url_request_context_getter_,
-          url_generator_,
-          callback,
-          resource_id,
-          app_id));
+      new AuthorizeAppRequest(sender_.get(),
+                              url_generator_,
+                              callback,
+                              resource_id,
+                              app_id));
 }
 
 bool GDataWapiService::HasAccessToken() const {
@@ -600,4 +604,4 @@
   }
 }
 
-}  // namespace google_apis
+}  // namespace drive
diff --git a/chrome/browser/drive/gdata_wapi_service.h b/chrome/browser/drive/gdata_wapi_service.h
index ee91ecc..72e6c6c 100644
--- a/chrome/browser/drive/gdata_wapi_service.h
+++ b/chrome/browser/drive/gdata_wapi_service.h
@@ -7,6 +7,7 @@
 
 #include <string>
 
+#include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
@@ -20,33 +21,41 @@
 
 namespace base {
 class FilePath;
+class TaskRunner;
+}
+
+namespace google_apis {
+class AuthService;
+class RequestSender;
 }
 
 namespace net {
 class URLRequestContextGetter;
 }  // namespace net
 
-namespace google_apis {
-class AuthService;
-class RequestSender;
+namespace drive {
 
 // This class provides documents feed service calls for WAPI (codename for
 // DocumentsList API).
 // Details of API call are abstracted in each request class and this class
 // works as a thin wrapper for the API.
 class GDataWapiService : public DriveServiceInterface,
-                         public AuthServiceObserver {
+                         public google_apis::AuthServiceObserver {
  public:
   // |url_request_context_getter| is used to initialize URLFetcher.
+  // |blocking_task_runner| is used to run blocking tasks (like parsing JSON).
   // |base_url| is used to generate URLs for communicating with the WAPI
+  // |base_download_url| is used to generate URLs for downloading file with WAPI
   // |custom_user_agent| is used for the User-Agent header in HTTP
   // requests issued through the service if the value is not empty.
   GDataWapiService(net::URLRequestContextGetter* url_request_context_getter,
+                   base::TaskRunner* blocking_task_runner,
                    const GURL& base_url,
+                   const GURL& base_download_url,
                    const std::string& custom_user_agent);
   virtual ~GDataWapiService();
 
-  AuthService* auth_service_for_testing();
+  google_apis::AuthService* auth_service_for_testing();
 
   // DriveServiceInterface Overrides
   virtual void Initialize(Profile* profile) OVERRIDE;
@@ -60,121 +69,117 @@
   virtual void ClearAccessToken() OVERRIDE;
   virtual void ClearRefreshToken() OVERRIDE;
   virtual std::string GetRootResourceId() const OVERRIDE;
-  virtual CancelCallback GetAllResourceList(
-      const GetResourceListCallback& callback) OVERRIDE;
-  virtual CancelCallback GetResourceListInDirectory(
+  virtual google_apis::CancelCallback GetAllResourceList(
+      const google_apis::GetResourceListCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback GetResourceListInDirectory(
       const std::string& directory_resource_id,
-      const GetResourceListCallback& callback) OVERRIDE;
-  virtual CancelCallback Search(
+      const google_apis::GetResourceListCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback Search(
       const std::string& search_query,
-      const GetResourceListCallback& callback) OVERRIDE;
-  virtual CancelCallback SearchByTitle(
+      const google_apis::GetResourceListCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback SearchByTitle(
       const std::string& title,
       const std::string& directory_resource_id,
-      const GetResourceListCallback& callback) OVERRIDE;
-  virtual CancelCallback GetChangeList(
+      const google_apis::GetResourceListCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback GetChangeList(
       int64 start_changestamp,
-      const GetResourceListCallback& callback) OVERRIDE;
-  virtual CancelCallback ContinueGetResourceList(
+      const google_apis::GetResourceListCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback ContinueGetResourceList(
       const GURL& override_url,
-      const GetResourceListCallback& callback) OVERRIDE;
-  virtual CancelCallback GetResourceEntry(
+      const google_apis::GetResourceListCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback GetResourceEntry(
       const std::string& resource_id,
-      const GetResourceEntryCallback& callback) OVERRIDE;
-  virtual CancelCallback GetAboutResource(
-      const GetAboutResourceCallback& callback) OVERRIDE;
-  virtual CancelCallback GetAppList(
-      const GetAppListCallback& callback) OVERRIDE;
-  virtual CancelCallback DeleteResource(
+      const google_apis::GetResourceEntryCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback GetAboutResource(
+      const google_apis::GetAboutResourceCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback GetAppList(
+      const google_apis::GetAppListCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback DeleteResource(
       const std::string& resource_id,
       const std::string& etag,
-      const EntryActionCallback& callback) OVERRIDE;
-  virtual CancelCallback DownloadFile(
-      const base::FilePath& virtual_path,
+      const google_apis::EntryActionCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback DownloadFile(
       const base::FilePath& local_cache_path,
-      const GURL& download_url,
-      const DownloadActionCallback& download_action_callback,
-      const GetContentCallback& get_content_callback,
-      const ProgressCallback& progress_callback) OVERRIDE;
-  virtual CancelCallback CopyResource(
+      const std::string& resource_id,
+      const google_apis::DownloadActionCallback& download_action_callback,
+      const google_apis::GetContentCallback& get_content_callback,
+      const google_apis::ProgressCallback& progress_callback) OVERRIDE;
+  virtual google_apis::CancelCallback CopyResource(
       const std::string& resource_id,
       const std::string& parent_resource_id,
       const std::string& new_name,
-      const GetResourceEntryCallback& callback) OVERRIDE;
-  virtual CancelCallback CopyHostedDocument(
+      const google_apis::GetResourceEntryCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback CopyHostedDocument(
       const std::string& resource_id,
       const std::string& new_name,
-      const GetResourceEntryCallback& callback) OVERRIDE;
-  virtual CancelCallback RenameResource(
+      const google_apis::GetResourceEntryCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback RenameResource(
       const std::string& resource_id,
       const std::string& new_name,
-      const EntryActionCallback& callback) OVERRIDE;
-  virtual CancelCallback TouchResource(
+      const google_apis::EntryActionCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback TouchResource(
       const std::string& resource_id,
       const base::Time& modified_date,
       const base::Time& last_viewed_by_me_date,
-      const GetResourceEntryCallback& callback) OVERRIDE;
-  virtual CancelCallback AddResourceToDirectory(
+      const google_apis::GetResourceEntryCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback AddResourceToDirectory(
       const std::string& parent_resource_id,
       const std::string& resource_id,
-      const EntryActionCallback& callback) OVERRIDE;
-  virtual CancelCallback RemoveResourceFromDirectory(
+      const google_apis::EntryActionCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback RemoveResourceFromDirectory(
       const std::string& parent_resource_id,
       const std::string& resource_id,
-      const EntryActionCallback& callback) OVERRIDE;
-  virtual CancelCallback AddNewDirectory(
+      const google_apis::EntryActionCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback AddNewDirectory(
       const std::string& parent_resource_id,
       const std::string& directory_name,
-      const GetResourceEntryCallback& callback) OVERRIDE;
-  virtual CancelCallback InitiateUploadNewFile(
-      const base::FilePath& drive_file_path,
+      const google_apis::GetResourceEntryCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback InitiateUploadNewFile(
       const std::string& content_type,
       int64 content_length,
       const std::string& parent_resource_id,
       const std::string& title,
-      const InitiateUploadCallback& callback) OVERRIDE;
-  virtual CancelCallback InitiateUploadExistingFile(
-      const base::FilePath& drive_file_path,
+      const google_apis::InitiateUploadCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback InitiateUploadExistingFile(
       const std::string& content_type,
       int64 content_length,
       const std::string& resource_id,
       const std::string& etag,
-      const InitiateUploadCallback& callback) OVERRIDE;
-  virtual CancelCallback ResumeUpload(
-      const base::FilePath& drive_file_path,
+      const google_apis::InitiateUploadCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback ResumeUpload(
       const GURL& upload_url,
       int64 start_position,
       int64 end_position,
       int64 content_length,
       const std::string& content_type,
       const base::FilePath& local_file_path,
-      const UploadRangeCallback& callback,
-      const ProgressCallback& progress_callback) OVERRIDE;
-  virtual CancelCallback GetUploadStatus(
-      const base::FilePath& drive_file_path,
+      const google_apis::UploadRangeCallback& callback,
+      const google_apis::ProgressCallback& progress_callback) OVERRIDE;
+  virtual google_apis::CancelCallback GetUploadStatus(
       const GURL& upload_url,
       int64 content_length,
-      const UploadRangeCallback& callback) OVERRIDE;
-  virtual CancelCallback AuthorizeApp(
+      const google_apis::UploadRangeCallback& callback) OVERRIDE;
+  virtual google_apis::CancelCallback AuthorizeApp(
       const std::string& resource_id,
       const std::string& app_id,
-      const AuthorizeAppCallback& callback) OVERRIDE;
+      const google_apis::AuthorizeAppCallback& callback) OVERRIDE;
 
  private:
   // AuthService::Observer override.
   virtual void OnOAuth2RefreshTokenChanged() OVERRIDE;
 
   net::URLRequestContextGetter* url_request_context_getter_;  // Not owned.
-  scoped_ptr<RequestSender> sender_;
+  scoped_refptr<base::TaskRunner> blocking_task_runner_;
+  scoped_ptr<google_apis::RequestSender> sender_;
   ObserverList<DriveServiceObserver> observers_;
   // Request objects should hold a copy of this, rather than a const
   // reference, as they may outlive this object.
-  const GDataWapiUrlGenerator url_generator_;
+  const google_apis::GDataWapiUrlGenerator url_generator_;
   const std::string custom_user_agent_;
 
   DISALLOW_COPY_AND_ASSIGN(GDataWapiService);
 };
 
-}  // namespace google_apis
+}  // namespace drive
 
 #endif  // CHROME_BROWSER_DRIVE_GDATA_WAPI_SERVICE_H_
diff --git a/chrome/browser/drive/mock_drive_service.cc b/chrome/browser/drive/mock_drive_service.cc
deleted file mode 100644
index 0e94823..0000000
--- a/chrome/browser/drive/mock_drive_service.cc
+++ /dev/null
@@ -1,144 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/drive/mock_drive_service.h"
-
-#include "base/bind.h"
-#include "base/files/file_path.h"
-#include "base/location.h"
-#include "base/message_loop/message_loop_proxy.h"
-#include "base/values.h"
-#include "chrome/browser/google_apis/gdata_wapi_parser.h"
-#include "chrome/browser/google_apis/test_util.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-using ::testing::_;
-using ::testing::Invoke;
-using ::testing::Return;
-
-namespace google_apis {
-
-MockDriveService::MockDriveService() {
-  ON_CALL(*this, GetChangeList(_, _))
-      .WillByDefault(Invoke(this, &MockDriveService::GetChangeListStub));
-  ON_CALL(*this, DeleteResource(_, _, _))
-      .WillByDefault(Invoke(this, &MockDriveService::DeleteResourceStub));
-  ON_CALL(*this, CopyHostedDocument(_, _, _))
-      .WillByDefault(Invoke(this, &MockDriveService::CopyHostedDocumentStub));
-  ON_CALL(*this, RenameResource(_, _, _))
-      .WillByDefault(Invoke(this, &MockDriveService::RenameResourceStub));
-  ON_CALL(*this, AddResourceToDirectory(_, _, _))
-      .WillByDefault(
-          Invoke(this, &MockDriveService::AddResourceToDirectoryStub));
-  ON_CALL(*this, RemoveResourceFromDirectory(_, _, _))
-      .WillByDefault(
-          Invoke(this, &MockDriveService::RemoveResourceFromDirectoryStub));
-  ON_CALL(*this, AddNewDirectory(_, _, _))
-      .WillByDefault(Invoke(this, &MockDriveService::CreateDirectoryStub));
-  ON_CALL(*this, DownloadFile(_, _, _, _, _, _))
-      .WillByDefault(Invoke(this, &MockDriveService::DownloadFileStub));
-
-  // Fill in the default values for mock data.
-  directory_data_ =
-      test_util::LoadJSONFile("chromeos/gdata/new_folder_entry.json");
-}
-
-MockDriveService::~MockDriveService() {}
-
-CancelCallback MockDriveService::GetChangeListStub(
-    int64 start_changestamp,
-    const GetResourceListCallback& callback) {
-  scoped_ptr<ResourceList> resource_list(new ResourceList());
-  base::MessageLoopProxy::current()->PostTask(
-      FROM_HERE,
-      base::Bind(callback, HTTP_SUCCESS,
-                 base::Passed(&resource_list)));
-  return CancelCallback();
-}
-
-CancelCallback MockDriveService::DeleteResourceStub(
-    const std::string& resource_id,
-    const std::string& etag,
-    const EntryActionCallback& callback) {
-  base::MessageLoopProxy::current()->PostTask(
-      FROM_HERE,
-      base::Bind(callback, HTTP_SUCCESS));
-  return CancelCallback();
-}
-
-CancelCallback MockDriveService::CopyHostedDocumentStub(
-    const std::string& resource_id,
-    const std::string& new_name,
-    const GetResourceEntryCallback& callback) {
-  scoped_ptr<ResourceEntry> resource_entry =
-      ResourceEntry::ExtractAndParse(*document_data_);
-  base::MessageLoopProxy::current()->PostTask(
-      FROM_HERE,
-      base::Bind(callback, HTTP_SUCCESS,
-                 base::Passed(&resource_entry)));
-  return CancelCallback();
-}
-
-CancelCallback MockDriveService::RenameResourceStub(
-    const std::string& resource_id,
-    const std::string& new_name,
-    const EntryActionCallback& callback) {
-  base::MessageLoopProxy::current()->PostTask(
-      FROM_HERE,
-      base::Bind(callback, HTTP_SUCCESS));
-  return CancelCallback();
-}
-
-CancelCallback MockDriveService::AddResourceToDirectoryStub(
-    const std::string& parent_resource_id,
-    const std::string& resource_id,
-    const EntryActionCallback& callback) {
-  base::MessageLoopProxy::current()->PostTask(
-      FROM_HERE,
-      base::Bind(callback, HTTP_SUCCESS));
-  return CancelCallback();
-}
-
-CancelCallback MockDriveService::RemoveResourceFromDirectoryStub(
-    const std::string& parent_resource_id,
-    const std::string& resource_id,
-    const EntryActionCallback& callback) {
-  base::MessageLoopProxy::current()->PostTask(
-      FROM_HERE,
-      base::Bind(callback, HTTP_SUCCESS));
-  return CancelCallback();
-}
-
-CancelCallback MockDriveService::CreateDirectoryStub(
-    const std::string& parent_resource_id,
-    const std::string& directory_name,
-    const GetResourceEntryCallback& callback) {
-  scoped_ptr<ResourceEntry> resource_entry =
-      ResourceEntry::ExtractAndParse(*directory_data_);
-  base::MessageLoopProxy::current()->PostTask(
-      FROM_HERE,
-      base::Bind(callback, HTTP_SUCCESS,
-                 base::Passed(&resource_entry)));
-  return CancelCallback();
-}
-
-CancelCallback MockDriveService::DownloadFileStub(
-    const base::FilePath& virtual_path,
-    const base::FilePath& local_tmp_path,
-    const GURL& download_url,
-    const DownloadActionCallback& download_action_callback,
-    const GetContentCallback& get_content_callback,
-    const ProgressCallback& progress_callback) {
-  GDataErrorCode error = HTTP_SUCCESS;
-  if (file_data_.get()) {
-    if (!test_util::WriteStringToFile(local_tmp_path, *file_data_))
-      error = GDATA_FILE_ERROR;
-  }
-  base::MessageLoopProxy::current()->PostTask(
-      FROM_HERE,
-      base::Bind(download_action_callback, error, local_tmp_path));
-  return CancelCallback();
-}
-
-}  // namespace google_apis
diff --git a/chrome/browser/drive/mock_drive_service.h b/chrome/browser/drive/mock_drive_service.h
deleted file mode 100644
index 77b7770..0000000
--- a/chrome/browser/drive/mock_drive_service.h
+++ /dev/null
@@ -1,216 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This file contains mocks for classes in drive_service_interface.h
-
-#ifndef CHROME_BROWSER_DRIVE_MOCK_DRIVE_SERVICE_H_
-#define CHROME_BROWSER_DRIVE_MOCK_DRIVE_SERVICE_H_
-
-#include <string>
-
-#include "base/memory/scoped_ptr.h"
-#include "chrome/browser/drive/drive_service_interface.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-namespace base {
-class FilePath;
-}
-
-namespace google_apis {
-
-class MockDriveService : public DriveServiceInterface {
- public:
-  MockDriveService();
-  virtual ~MockDriveService();
-
-  // DriveServiceInterface overrides.
-  MOCK_METHOD1(Initialize, void(Profile* profile));
-  MOCK_METHOD1(AddObserver, void(DriveServiceObserver* observer));
-  MOCK_METHOD1(RemoveObserver,
-      void(DriveServiceObserver* observer));
-  MOCK_CONST_METHOD0(CanSendRequest, bool());
-  MOCK_CONST_METHOD1(CanonicalizeResourceId,
-                     std::string(const std::string& resource_id));
-  MOCK_CONST_METHOD0(GetRootResourceId, std::string());
-  MOCK_METHOD1(GetAllResourceList,
-      CancelCallback(const GetResourceListCallback& callback));
-  MOCK_METHOD2(GetResourceListInDirectory,
-      CancelCallback(const std::string& directory_resource_id,
-                     const GetResourceListCallback& callback));
-  MOCK_METHOD2(Search,
-      CancelCallback(const std::string& search_query,
-                     const GetResourceListCallback& callback));
-  MOCK_METHOD3(SearchByTitle,
-      CancelCallback(const std::string& title,
-                     const std::string& directory_resource_id,
-                     const GetResourceListCallback& callback));
-  MOCK_METHOD2(GetChangeList,
-      CancelCallback(int64 start_changestamp,
-                    const GetResourceListCallback& callback));
-  MOCK_METHOD2(ContinueGetResourceList,
-      CancelCallback(const GURL& override_url,
-                     const GetResourceListCallback& callback));
-  MOCK_METHOD2(GetResourceEntry,
-      CancelCallback(const std::string& resource_id,
-                     const GetResourceEntryCallback& callback));
-  MOCK_METHOD1(GetAboutResource,
-      CancelCallback(const GetAboutResourceCallback& callback));
-  MOCK_METHOD1(GetAppList,
-      CancelCallback(const GetAppListCallback& callback));
-  MOCK_METHOD3(DeleteResource,
-      CancelCallback(const std::string& resource_id,
-                     const std::string& etag,
-                     const EntryActionCallback& callback));
-  MOCK_METHOD4(CopyResource,
-      CancelCallback(const std::string& resource_id,
-                     const std::string& parent_resource_id,
-                     const std::string& new_name,
-                     const GetResourceEntryCallback& callback));
-  MOCK_METHOD3(CopyHostedDocument,
-      CancelCallback(const std::string& resource_id,
-                     const std::string& new_name,
-                     const GetResourceEntryCallback& callback));
-  MOCK_METHOD3(RenameResource,
-      CancelCallback(const std::string& resource_id,
-                     const std::string& new_name,
-                     const EntryActionCallback& callback));
-  MOCK_METHOD4(TouchResource,
-      CancelCallback(const std::string& resource_id,
-                     const base::Time& modified_date,
-                     const base::Time& last_viewed_by_me_date,
-                     const GetResourceEntryCallback& callback));
-  MOCK_METHOD3(AddResourceToDirectory,
-      CancelCallback(const std::string& parent_resource_id,
-                     const std::string& resource_id,
-                     const EntryActionCallback& callback));
-  MOCK_METHOD3(RemoveResourceFromDirectory,
-      CancelCallback(const std::string& parent_resource_id,
-                     const std::string& resource_id,
-                     const EntryActionCallback& callback));
-  MOCK_METHOD3(AddNewDirectory,
-      CancelCallback(const std::string& parent_resource_id,
-                     const std::string& directory_name,
-                     const GetResourceEntryCallback& callback));
-  MOCK_METHOD6(
-      DownloadFile,
-      CancelCallback(const base::FilePath& virtual_path,
-                     const base::FilePath& local_cache_path,
-                     const GURL& download_url,
-                     const DownloadActionCallback& donwload_action_callback,
-                     const GetContentCallback& get_content_callback,
-                     const ProgressCallback& progress_callback));
-  MOCK_METHOD6(InitiateUploadNewFile,
-      CancelCallback(const base::FilePath& drive_file_path,
-                     const std::string& content_type,
-                     int64 content_length,
-                     const std::string& parent_resource_id,
-                     const std::string& title,
-                     const InitiateUploadCallback& callback));
-  MOCK_METHOD6(InitiateUploadExistingFile,
-      CancelCallback(const base::FilePath& drive_file_path,
-                     const std::string& content_type,
-                     int64 content_length,
-                     const std::string& resource_id,
-                     const std::string& etag,
-                     const InitiateUploadCallback& callback));
-  MOCK_METHOD9(ResumeUpload,
-      CancelCallback(const base::FilePath& drive_file_path,
-                     const GURL& upload_url,
-                     int64 start_position,
-                     int64 end_position,
-                     int64 content_length,
-                     const std::string& content_type,
-                     const base::FilePath& local_file_path,
-                     const UploadRangeCallback& callback,
-                     const ProgressCallback& progress_callback));
-  MOCK_METHOD4(GetUploadStatus,
-      CancelCallback(const base::FilePath& drive_file_path,
-                     const GURL& upload_url,
-                     int64 content_length,
-                     const UploadRangeCallback& callback));
-  MOCK_METHOD3(AuthorizeApp,
-      CancelCallback(const std::string& resource_id,
-                     const std::string& app_id,
-                     const AuthorizeAppCallback& callback));
-  MOCK_CONST_METHOD0(HasAccessToken, bool());
-  MOCK_CONST_METHOD0(HasRefreshToken, bool());
-  MOCK_METHOD0(ClearAccessToken, void());
-  MOCK_METHOD0(ClearRefreshToken, void());
-
-  void set_file_data(std::string* file_data) {
-    file_data_.reset(file_data);
-  }
-
- private:
-  // Helper stub methods for functions which take callbacks, so that
-  // the callbacks get called with testable results.
-
-  // Will call |callback| with HTTP_SUCCESS and a empty ResourceList.
-  CancelCallback GetChangeListStub(
-      int64 start_changestamp,
-      const GetResourceListCallback& callback);
-
-  // Will call |callback| with HTTP_SUCCESS.
-  CancelCallback DeleteResourceStub(
-      const std::string& resource_id,
-      const std::string& etag,
-      const EntryActionCallback& callback);
-
-  // Will call |callback| with HTTP_SUCCESS and the current value of
-  // |document_data_|.
-  CancelCallback CopyHostedDocumentStub(
-      const std::string& resource_id,
-      const std::string& new_name,
-      const GetResourceEntryCallback& callback);
-
-  // Will call |callback| with HTTP_SUCCESS.
-  CancelCallback RenameResourceStub(
-      const std::string& resource_id,
-      const std::string& new_name,
-      const EntryActionCallback& callback);
-
-  // Will call |callback| with HTTP_SUCCESS.
-  CancelCallback AddResourceToDirectoryStub(
-      const std::string& parent_resource_id,
-      const std::string& resource_id,
-      const EntryActionCallback& callback);
-
-  // Will call |callback| with HTTP_SUCCESS.
-  CancelCallback RemoveResourceFromDirectoryStub(
-      const std::string& parent_resource_id,
-      const std::string& resource_id,
-      const EntryActionCallback& callback);
-
-  // Will call |callback| with HTTP_SUCCESS and the current value of
-  // |directory_data_|.
-  CancelCallback CreateDirectoryStub(
-      const std::string& parent_resource_id,
-      const std::string& directory_name,
-      const GetResourceEntryCallback& callback);
-
-  // Will call |callback| with HTTP_SUCCESS, the given URL, and the host+path
-  // portion of the URL as the temporary file path. If |file_data_| is not null,
-  // |file_data_| is written to the temporary file.
-  CancelCallback DownloadFileStub(
-      const base::FilePath& virtual_path,
-      const base::FilePath& local_tmp_path,
-      const GURL& download_url,
-      const DownloadActionCallback& download_action_callback,
-      const GetContentCallback& get_content_callback,
-      const ProgressCallback& progress_callback);
-
-  // JSON data to be returned from CreateDirectory.
-  scoped_ptr<base::Value> directory_data_;
-
-  // JSON data to be returned from CopyHostedDocument.
-  scoped_ptr<base::Value> document_data_;
-
-  // File data to be written to the local temporary file when
-  // DownloadFileStub is called.
-  scoped_ptr<std::string> file_data_;
-};
-
-}  // namespace google_apis
-
-#endif  // CHROME_BROWSER_DRIVE_MOCK_DRIVE_SERVICE_H_
diff --git a/chrome/browser/enumerate_modules_model_win.cc b/chrome/browser/enumerate_modules_model_win.cc
index a8bedbb..279cbd2 100644
--- a/chrome/browser/enumerate_modules_model_win.cc
+++ b/chrome/browser/enumerate_modules_model_win.cc
@@ -18,7 +18,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "base/version.h"
 #include "base/win/registry.h"
diff --git a/chrome/browser/enumerate_modules_model_win.h b/chrome/browser/enumerate_modules_model_win.h
index 87e53c4..51243d1 100644
--- a/chrome/browser/enumerate_modules_model_win.h
+++ b/chrome/browser/enumerate_modules_model_win.h
@@ -12,9 +12,9 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/singleton.h"
 #include "base/strings/string16.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "content/public/browser/browser_thread.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 class EnumerateModulesModel;
 
diff --git a/chrome/browser/extensions/DEPS b/chrome/browser/extensions/DEPS
index 92be07f..05df41b 100644
--- a/chrome/browser/extensions/DEPS
+++ b/chrome/browser/extensions/DEPS
@@ -1,5 +1,10 @@
 include_rules = [
+  # TODO(benwells): Once the extensions component is established
+  # and there are only chrome specific extension things left in
+  # chrome/browser/extensions, the restriction of not being able
+  # to depend on apps will be lifted.
   "-apps",
+  "+apps/shell_window.h",
 
   # TODO(tfarina): Remove all these. crbug.com/125846.
   # DO NOT ADD ANY MORE ITEMS TO THE LIST BELOW!
diff --git a/chrome/browser/extensions/OWNERS b/chrome/browser/extensions/OWNERS
index 58e6f16..bb8432e 100644
--- a/chrome/browser/extensions/OWNERS
+++ b/chrome/browser/extensions/OWNERS
@@ -12,7 +12,6 @@
 benwells@chromium.org
 erikkay@chromium.org
 finnur@chromium.org
-jeremya@chromium.org
 jyasskin@chromium.org
 kalman@chromium.org
 koz@chromium.org
diff --git a/chrome/browser/extensions/active_tab_apitest.cc b/chrome/browser/extensions/active_tab_apitest.cc
index 836d94c..d6a6d1d 100644
--- a/chrome/browser/extensions/active_tab_apitest.cc
+++ b/chrome/browser/extensions/active_tab_apitest.cc
@@ -9,6 +9,7 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/test/base/ui_test_utils.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
 
 namespace extensions {
 namespace {
@@ -20,7 +21,7 @@
 #define MAYBE_ActiveTab ActiveTab
 #endif
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MAYBE_ActiveTab) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   const Extension* extension =
       LoadExtension(test_data_dir_.AppendASCII("active_tab"));
@@ -32,7 +33,10 @@
   // Shouldn't be initially granted based on activeTab.
   {
     ResultCatcher catcher;
-    ui_test_utils::NavigateToURL(browser(), test_server()->GetURL("page.html"));
+    ui_test_utils::NavigateToURL(
+        browser(),
+        embedded_test_server()->GetURL(
+            "/extensions/api_test/active_tab/page.html"));
     EXPECT_TRUE(catcher.GetNextResult()) << message_;
   }
 
@@ -46,8 +50,10 @@
   // Changing page should go back to it not having access.
   {
     ResultCatcher catcher;
-    ui_test_utils::NavigateToURL(browser(),
-                                 test_server()->GetURL("final_page.html"));
+    ui_test_utils::NavigateToURL(
+        browser(),
+        embedded_test_server()->GetURL(
+            "/extensions/api_test/active_tab/final_page.html"));
     EXPECT_TRUE(catcher.GetNextResult()) << message_;
   }
 }
diff --git a/chrome/browser/extensions/activity_log/activity_actions.h b/chrome/browser/extensions/activity_log/activity_actions.h
index 5e2cbd5..2a5d636 100644
--- a/chrome/browser/extensions/activity_log/activity_actions.h
+++ b/chrome/browser/extensions/activity_log/activity_actions.h
@@ -7,7 +7,7 @@
 
 #include <string>
 #include "base/memory/ref_counted_memory.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/common/extensions/api/activity_log_private.h"
 #include "sql/connection.h"
diff --git a/chrome/browser/extensions/activity_log/activity_database.cc b/chrome/browser/extensions/activity_log/activity_database.cc
index 47e22a6..20f4b98 100644
--- a/chrome/browser/extensions/activity_log/activity_database.cc
+++ b/chrome/browser/extensions/activity_log/activity_database.cc
@@ -9,8 +9,8 @@
 #include "base/strings/stringprintf.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_checker.h"
-#include "base/time.h"
 #include "base/time/clock.h"
+#include "base/time/time.h"
 #include "chrome/browser/extensions/activity_log/activity_database.h"
 #include "chrome/common/chrome_switches.h"
 #include "sql/error_delegate_util.h"
diff --git a/chrome/browser/extensions/activity_log/activity_database.h b/chrome/browser/extensions/activity_log/activity_database.h
index 242aaf8..8c3c42f 100644
--- a/chrome/browser/extensions/activity_log/activity_database.h
+++ b/chrome/browser/extensions/activity_log/activity_database.h
@@ -11,7 +11,7 @@
 #include "base/files/file_path.h"
 #include "base/memory/ref_counted_memory.h"
 #include "base/synchronization/lock.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/extensions/activity_log/api_actions.h"
 #include "chrome/browser/extensions/activity_log/blocked_actions.h"
 #include "chrome/browser/extensions/activity_log/dom_actions.h"
diff --git a/chrome/browser/extensions/activity_log/activity_database_unittest.cc b/chrome/browser/extensions/activity_log/activity_database_unittest.cc
index dae4f72..56ac824 100644
--- a/chrome/browser/extensions/activity_log/activity_database_unittest.cc
+++ b/chrome/browser/extensions/activity_log/activity_database_unittest.cc
@@ -9,7 +9,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/run_loop.h"
 #include "base/test/simple_test_clock.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/extensions/activity_log/activity_database.h"
 #include "chrome/browser/extensions/activity_log/api_actions.h"
 #include "chrome/browser/extensions/activity_log/blocked_actions.h"
@@ -75,7 +75,7 @@
   base::FilePath db_file;
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
   db_file = temp_dir.path().AppendASCII("ActivityInit.db");
-  file_util::Delete(db_file, false);
+  base::Delete(db_file, false);
 
   ActivityDatabase* activity_db = new ActivityDatabase();
   activity_db->Init(db_file);
@@ -96,7 +96,7 @@
   base::FilePath db_file;
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
   db_file = temp_dir.path().AppendASCII("ActivityRecord.db");
-  file_util::Delete(db_file, false);
+  base::Delete(db_file, false);
 
   ActivityDatabase* activity_db = new ActivityDatabase();
   activity_db->Init(db_file);
@@ -132,7 +132,7 @@
   base::FilePath db_file;
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
   db_file = temp_dir.path().AppendASCII("ActivityRecord.db");
-  file_util::Delete(db_file, false);
+  base::Delete(db_file, false);
 
   ActivityDatabase* activity_db = new ActivityDatabase();
   activity_db->Init(db_file);
@@ -177,7 +177,7 @@
   base::FilePath db_file;
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
   db_file = temp_dir.path().AppendASCII("ActivityRecord.db");
-  file_util::Delete(db_file, false);
+  base::Delete(db_file, false);
 
   ActivityDatabase* activity_db = new ActivityDatabase();
   activity_db->Init(db_file);
@@ -213,7 +213,7 @@
   base::FilePath db_file;
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
   db_file = temp_dir.path().AppendASCII("ActivityRecord.db");
-  file_util::Delete(db_file, false);
+  base::Delete(db_file, false);
 
   // Use a mock clock to ensure that events are not recorded on the wrong day
   // when the test is run close to local midnight.
@@ -273,7 +273,7 @@
   base::FilePath db_file;
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
   db_file = temp_dir.path().AppendASCII("ActivityRecord.db");
-  file_util::Delete(db_file, false);
+  base::Delete(db_file, false);
 
   // Use a mock clock to ensure that events are not recorded on the wrong day
   // when the test is run close to local midnight.
@@ -343,7 +343,7 @@
   base::FilePath db_file;
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
   db_file = temp_dir.path().AppendASCII("ActivityRecord.db");
-  file_util::Delete(db_file, false);
+  base::Delete(db_file, false);
 
   // Use a mock clock to ensure that events are not recorded on the wrong day
   // when the test is run close to local midnight.
@@ -377,7 +377,7 @@
   base::FilePath db_file;
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
   db_file = temp_dir.path().AppendASCII("ActivityRecord.db");
-  file_util::Delete(db_file, false);
+  base::Delete(db_file, false);
 
   // Use a mock clock to set the time, and a special timer to control the
   // timing and skip ahead in time.
@@ -421,7 +421,7 @@
   base::FilePath db_file;
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
   db_file = temp_dir.path().AppendASCII("ActivityRecord.db");
-  file_util::Delete(db_file, false);
+  base::Delete(db_file, false);
 
   ActivityDatabase* activity_db = new ActivityDatabase();
   scoped_refptr<APIAction> action = new APIAction(
diff --git a/chrome/browser/extensions/activity_log/activity_log.cc b/chrome/browser/extensions/activity_log/activity_log.cc
index cecf3fe..278a157 100644
--- a/chrome/browser/extensions/activity_log/activity_log.cc
+++ b/chrome/browser/extensions/activity_log/activity_log.cc
@@ -32,9 +32,9 @@
 namespace {
 
 // Concatenate arguments.
-std::string MakeArgList(const ListValue* args) {
+std::string MakeArgList(const base::ListValue* args) {
   std::string call_signature;
-  ListValue::const_iterator it = args->begin();
+  base::ListValue::const_iterator it = args->begin();
   for (; it != args->end(); ++it) {
     std::string arg;
     JSONStringValueSerializer serializer(&arg);
@@ -237,7 +237,7 @@
 
 void ActivityLog::LogAPIActionInternal(const std::string& extension_id,
                                        const std::string& api_call,
-                                       ListValue* args,
+                                       base::ListValue* args,
                                        const std::string& extra,
                                        const APIAction::Type type) {
   std::string verb, manager;
@@ -283,7 +283,7 @@
 // A wrapper around LogAPIActionInternal, but we know it's an API call.
 void ActivityLog::LogAPIAction(const std::string& extension_id,
                                const std::string& api_call,
-                               ListValue* args,
+                               base::ListValue* args,
                                const std::string& extra) {
   if (!IsLogEnabled() ||
       ActivityLogAPI::IsExtensionWhitelisted(extension_id)) return;
@@ -300,7 +300,7 @@
 // handle them. Right now they're being handled almost the same.
 void ActivityLog::LogEventAction(const std::string& extension_id,
                                  const std::string& api_call,
-                                 ListValue* args,
+                                 base::ListValue* args,
                                  const std::string& extra) {
   if (!IsLogEnabled() ||
       ActivityLogAPI::IsExtensionWhitelisted(extension_id)) return;
@@ -313,7 +313,7 @@
 
 void ActivityLog::LogBlockedAction(const std::string& extension_id,
                                    const std::string& blocked_call,
-                                   ListValue* args,
+                                   base::ListValue* args,
                                    BlockedAction::Reason reason,
                                    const std::string& extra) {
   if (!IsLogEnabled() ||
@@ -348,7 +348,7 @@
                                const GURL& url,
                                const string16& url_title,
                                const std::string& api_call,
-                               const ListValue* args,
+                               const base::ListValue* args,
                                DomActionType::Type call_type,
                                const std::string& extra) {
   if (!IsLogEnabled() ||
@@ -480,8 +480,8 @@
         ext_scripts_str += *it2;
         ext_scripts_str += " ";
       }
-      scoped_ptr<ListValue> script_names(new ListValue());
-      script_names->Set(0, new StringValue(ext_scripts_str));
+      scoped_ptr<base::ListValue> script_names(new base::ListValue());
+      script_names->Set(0, new base::StringValue(ext_scripts_str));
       LogDOMAction(extension->id(),
                    on_url,
                    web_contents->GetTitle(),
diff --git a/chrome/browser/extensions/activity_log/activity_log.h b/chrome/browser/extensions/activity_log/activity_log.h
index 423de34..fd9b6e2 100644
--- a/chrome/browser/extensions/activity_log/activity_log.h
+++ b/chrome/browser/extensions/activity_log/activity_log.h
@@ -70,7 +70,7 @@
   // (Note: implemented as a wrapper for LogAPIActionInternal.)
   void LogAPIAction(const std::string& extension_id,
                     const std::string& name,    // e.g., tabs.get
-                    ListValue* args,            // the argument values e.g. 46
+                    base::ListValue* args,      // the argument values e.g. 46
                     const std::string& extra);  // any extra logging info
 
   // Log an event notification delivered to an extension.
@@ -78,14 +78,14 @@
   // (Note: implemented as a wrapper for LogAPIActionInternal.)
   void LogEventAction(const std::string& extension_id,
                       const std::string& name,    // e.g., tabs.onUpdate
-                      ListValue* args,            // arguments to the callback
+                      base::ListValue* args,      // arguments to the callback
                       const std::string& extra);  // any extra logging info
 
   // Log a blocked API call made by an extension.
   // This will create a BlockedAction for storage in the database.
   void LogBlockedAction(const std::string& extension_id,
                         const std::string& blocked_call,  // e.g., tabs.get
-                        ListValue* args,                  // argument values
+                        base::ListValue* args,            // argument values
                         BlockedAction::Reason reason,     // why it's blocked
                         const std::string& extra);        // extra logging info
 
@@ -95,7 +95,7 @@
                     const GURL& url,                      // target URL
                     const string16& url_title,            // title of the URL
                     const std::string& api_call,          // api call
-                    const ListValue* args,                // arguments
+                    const base::ListValue* args,          // arguments
                     DomActionType::Type call_type,        // type of the call
                     const std::string& extra);            // extra logging info
 
@@ -168,7 +168,7 @@
   void LogAPIActionInternal(
       const std::string& extension_id,
       const std::string& api_call,
-      ListValue* args,
+      base::ListValue* args,
       const std::string& extra,
       const APIAction::Type type);
 
diff --git a/chrome/browser/extensions/activity_log/activity_log_browsertest.cc b/chrome/browser/extensions/activity_log/activity_log_browsertest.cc
index 2080b6e..3368730 100644
--- a/chrome/browser/extensions/activity_log/activity_log_browsertest.cc
+++ b/chrome/browser/extensions/activity_log/activity_log_browsertest.cc
@@ -15,6 +15,7 @@
 #include "content/public/browser/notification_service.h"
 #include "content/public/test/browser_test_utils.h"
 #include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
 
 namespace extensions {
 
@@ -37,9 +38,9 @@
   }
   // Start the test server, load the activity log extension, and navigate
   // the browser to the options page of the extension.
-  TabStripModel* StartTestServerAndInitialize() {
+  TabStripModel* StartEmbeddedTestServerAndInitialize() {
     host_resolver()->AddRule("*", "127.0.0.1");
-    StartTestServer();
+    StartEmbeddedTestServer();
 
     // Get the extension (chrome/test/data/extensions/activity_log)
     const extensions::Extension* ext =
@@ -81,12 +82,12 @@
 #endif
 
 IN_PROC_BROWSER_TEST_F(ActivityLogExtensionTest, MAYBE_ChromeEndToEnd) {
-  TabStripModel* tab_strip = StartTestServerAndInitialize();
+  TabStripModel* tab_strip = StartEmbeddedTestServerAndInitialize();
   ResultCatcher catcher;
   // Set the default URL so that is has the correct port number.
-  net::HostPortPair host_port = test_server()->host_port_pair();
   std::string url_setting_script = base::StringPrintf(
-      "defaultUrl = \'http://www.google.com:%d\';", host_port.port());
+      "defaultUrl = \'http://www.google.com:%d\';",
+      embedded_test_server()->port());
   ASSERT_TRUE(content::ExecuteScript(tab_strip->GetActiveWebContents(),
                                      url_setting_script));
   // Set the test buttons array
@@ -108,12 +109,12 @@
 #endif
 
 IN_PROC_BROWSER_TEST_F(ActivityLogExtensionTest, MAYBE_DOMEndToEnd) {
-  TabStripModel* tab_strip = StartTestServerAndInitialize();
+  TabStripModel* tab_strip = StartEmbeddedTestServerAndInitialize();
   ResultCatcher catcher;
   // Set the default URL so that is has the correct port number.
-  net::HostPortPair host_port = test_server()->host_port_pair();
   std::string url_setting_script = base::StringPrintf(
-      "defaultUrl = \'http://www.google.com:%d\';", host_port.port());
+      "defaultUrl = \'http://www.google.com:%d\';",
+      embedded_test_server()->port());
   ASSERT_TRUE(content::ExecuteScript(tab_strip->GetActiveWebContents(),
                                      url_setting_script));
   // Set the test buttons array
@@ -129,8 +130,8 @@
 
 IN_PROC_BROWSER_TEST_F(ActivityLogExtensionTest, ExtensionPrerender) {
   host_resolver()->AddRule("*", "127.0.0.1");
-  StartTestServer();
-  int port = test_server()->host_port_pair().port();
+  StartEmbeddedTestServer();
+  int port = embedded_test_server()->port();
 
   // Get the extension (chrome/test/data/extensions/activity_log)
   const Extension* ext =
diff --git a/chrome/browser/extensions/activity_log/activity_log_policy.cc b/chrome/browser/extensions/activity_log/activity_log_policy.cc
index 21d9deb..528f260 100644
--- a/chrome/browser/extensions/activity_log/activity_log_policy.cc
+++ b/chrome/browser/extensions/activity_log/activity_log_policy.cc
@@ -5,7 +5,7 @@
 #include <stdint.h>
 
 #include "base/logging.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/extensions/activity_log/activity_log_policy.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/extensions/extension.h"
diff --git a/chrome/browser/extensions/activity_log/activity_log_policy.h b/chrome/browser/extensions/activity_log/activity_log_policy.h
index 7dadeb9..797cba5 100644
--- a/chrome/browser/extensions/activity_log/activity_log_policy.h
+++ b/chrome/browser/extensions/activity_log/activity_log_policy.h
@@ -13,7 +13,7 @@
 #include "base/callback.h"
 #include "base/files/file_path.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "base/values.h"
 #include "chrome/browser/extensions/activity_log/activity_actions.h"
 #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/extensions/activity_log/activity_log_unittest.cc b/chrome/browser/extensions/activity_log/activity_log_unittest.cc
index 64b7d4d..01bdcd1 100644
--- a/chrome/browser/extensions/activity_log/activity_log_unittest.cc
+++ b/chrome/browser/extensions/activity_log/activity_log_unittest.cc
@@ -188,7 +188,7 @@
 
 TEST_F(ActivityLogTest, Construct) {
   ActivityLog* activity_log = ActivityLog::GetInstance(profile_.get());
-  scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   ASSERT_TRUE(activity_log->IsLogEnabled());
   activity_log->LogAPIAction(
       kExtensionId, std::string("tabs.testMethod"), args.get(), std::string());
@@ -196,7 +196,7 @@
 
 TEST_F(ActivityLogTest, LogAndFetchActions) {
   ActivityLog* activity_log = ActivityLog::GetInstance(profile_.get());
-  scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   ASSERT_TRUE(activity_log->IsLogEnabled());
 
   // Write some API calls
@@ -217,7 +217,7 @@
 
 TEST_F(ActivityLogTest, LogAndFetchPathActions) {
   ActivityLog* activity_log = ActivityLog::GetInstance(profile_.get());
-  scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   ASSERT_TRUE(activity_log->IsLogEnabled());
 
   activity_log->LogDOMAction(kExtensionId,
@@ -238,7 +238,7 @@
   activity_log->SetArgumentLoggingForTesting(false);
   ASSERT_TRUE(activity_log->IsLogEnabled());
   activity_log->SetDefaultPolicy(ActivityLogPolicy::POLICY_NOARGS);
-  scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   args->Set(0, new base::StringValue("hello"));
   args->Set(1, new base::StringValue("world"));
   activity_log->LogAPIAction(
@@ -252,7 +252,7 @@
   activity_log->SetDefaultPolicy(ActivityLogPolicy::POLICY_FULLSTREAM);
   ASSERT_TRUE(activity_log->IsLogEnabled());
 
-  scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   args->Set(0, new base::StringValue("hello"));
   args->Set(1, new base::StringValue("world"));
   activity_log->LogAPIAction(kExtensionId,
diff --git a/chrome/browser/extensions/activity_log/api_actions.cc b/chrome/browser/extensions/activity_log/api_actions.cc
index c1b4fe7..483d394 100644
--- a/chrome/browser/extensions/activity_log/api_actions.cc
+++ b/chrome/browser/extensions/activity_log/api_actions.cc
@@ -208,7 +208,7 @@
 
 // static
 void APIAction::LookupTabId(const std::string& api_call,
-                            ListValue* args,
+                            base::ListValue* args,
                             Profile* profile) {
   if (api_call == "tabs.get" ||                 // api calls, ID as int
       api_call == "tabs.connect" ||
@@ -228,7 +228,7 @@
       api_call == "tabs.onRemoved" ||
       api_call == "tabs.onReplaced") {
     int tab_id;
-    ListValue* id_list;
+    base::ListValue* id_list;
     if (args->GetInteger(0, &tab_id)) {
       std::string url = GetURLForTabId(tab_id, profile);
       if (url != std::string())
diff --git a/chrome/browser/extensions/activity_log/api_actions.h b/chrome/browser/extensions/activity_log/api_actions.h
index c56ed6a..70a16a7 100644
--- a/chrome/browser/extensions/activity_log/api_actions.h
+++ b/chrome/browser/extensions/activity_log/api_actions.h
@@ -55,7 +55,7 @@
   // the original int. There is a small chance that the URL translation could
   // be wrong, if the tab has already been navigated by the time of invocation.
   static void LookupTabId(const std::string& api_call,
-                          ListValue* args,
+                          base::ListValue* args,
                           Profile* profile);
 
   // Print a APIAction as a regular string for debugging purposes.
diff --git a/chrome/browser/extensions/activity_log/api_name_constants.h b/chrome/browser/extensions/activity_log/api_name_constants.h
index 350ac21..7a6383d 100644
--- a/chrome/browser/extensions/activity_log/api_name_constants.h
+++ b/chrome/browser/extensions/activity_log/api_name_constants.h
@@ -191,7 +191,8 @@
     "windows.onFocusChanged", "windows.onRemoved", "windows.remove",
     "windows.update",
     "tabs.getSelected", "tabs.sendRequest",
-    "systemInfo.cpu.get", "systemInfo.memory.get"
+    "systemInfo.cpu.get", "systemInfo.memory.get",
+    "runtime.onRestartRequired"
 };
 
 }  // namespace activity_log_api_name_constants
diff --git a/chrome/browser/extensions/activity_log/fullstream_ui_policy.cc b/chrome/browser/extensions/activity_log/fullstream_ui_policy.cc
index 0cfa146..ddf56c7 100644
--- a/chrome/browser/extensions/activity_log/fullstream_ui_policy.cc
+++ b/chrome/browser/extensions/activity_log/fullstream_ui_policy.cc
@@ -5,7 +5,7 @@
 #include "base/files/file_path.h"
 #include "base/json/json_string_value_serializer.h"
 #include "base/logging.h"
-#include "base/string16.h"
+#include "base/strings/string16.h"
 #include "chrome/browser/extensions/activity_log/activity_database.h"
 #include "chrome/browser/extensions/activity_log/api_actions.h"
 #include "chrome/browser/extensions/activity_log/blocked_actions.h"
@@ -94,10 +94,10 @@
 std::string FullStreamUIPolicy::ProcessArguments(
     ActionType action_type,
     const std::string& name,
-    const ListValue* args) const {
+    const base::ListValue* args) const {
   std::string processed_args;
   if (args) {
-    ListValue::const_iterator it = args->begin();
+    base::ListValue::const_iterator it = args->begin();
     // TODO(felt,dbabic) Think about replacing the loop with a single
     // call to SerializeAndOmitBinaryValues.
     for (; it != args->end(); ++it) {
@@ -126,7 +126,7 @@
     const std::string& extension_id,
     const std::string& name,
     const GURL& url_param,
-    const ListValue* args,
+    const base::ListValue* args,
     const DictionaryValue* details) {
   std::string concatenated_args = ProcessArguments(action_type, name, args);
   const Time now = Time::Now();
diff --git a/chrome/browser/extensions/activity_log/fullstream_ui_policy_unittest.cc b/chrome/browser/extensions/activity_log/fullstream_ui_policy_unittest.cc
index ebbfd83..19db206 100644
--- a/chrome/browser/extensions/activity_log/fullstream_ui_policy_unittest.cc
+++ b/chrome/browser/extensions/activity_log/fullstream_ui_policy_unittest.cc
@@ -97,8 +97,8 @@
                        .Set("version", "1.0.0")
                        .Set("manifest_version", 2))
           .Build();
-  extension_service_->AddExtension(extension);
-  scoped_ptr<ListValue> args(new ListValue());
+  extension_service_->AddExtension(extension.get());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   policy->ProcessAction(ActivityLogPolicy::ACTION_API, extension->id(),
       std::string("tabs.testMethod"), GURL(), args.get(), NULL);
 }
@@ -112,8 +112,8 @@
                        .Set("version", "1.0.0")
                        .Set("manifest_version", 2))
           .Build();
-  extension_service_->AddExtension(extension);
-  scoped_ptr<ListValue> args(new ListValue());
+  extension_service_->AddExtension(extension.get());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   GURL gurl("http://www.google.com");
 
   // Write some API calls
@@ -135,8 +135,8 @@
                        .Set("version", "1.0.0")
                        .Set("manifest_version", 2))
           .Build();
-  extension_service_->AddExtension(extension);
-  scoped_ptr<ListValue> args(new ListValue());
+  extension_service_->AddExtension(extension.get());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   args->Set(0, new base::StringValue("hello"));
   args->Set(1, new base::StringValue("world"));
   policy->ProcessAction(ActivityLogPolicy::ACTION_API, extension->id(),
diff --git a/chrome/browser/extensions/activity_log/stream_noargs_ui_policy_unittest.cc b/chrome/browser/extensions/activity_log/stream_noargs_ui_policy_unittest.cc
index 39e3235..df279d1 100644
--- a/chrome/browser/extensions/activity_log/stream_noargs_ui_policy_unittest.cc
+++ b/chrome/browser/extensions/activity_log/stream_noargs_ui_policy_unittest.cc
@@ -98,8 +98,8 @@
                        .Set("version", "1.0.0")
                        .Set("manifest_version", 2))
           .Build();
-  extension_service_->AddExtension(extension);
-  scoped_ptr<ListValue> args(new ListValue());
+  extension_service_->AddExtension(extension.get());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   policy->ProcessAction(ActivityLogPolicy::ACTION_API, extension->id(),
       std::string("tabs.testMethod"), GURL(), args.get(), NULL);
 }
@@ -114,8 +114,8 @@
                        .Set("version", "1.0.0")
                        .Set("manifest_version", 2))
           .Build();
-  extension_service_->AddExtension(extension);
-  scoped_ptr<ListValue> args(new ListValue());
+  extension_service_->AddExtension(extension.get());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   GURL gurl("http://www.google.com");
 
   // Write some API calls
@@ -139,8 +139,8 @@
                        .Set("version", "1.0.0")
                        .Set("manifest_version", 2))
           .Build();
-  extension_service_->AddExtension(extension);
-  scoped_ptr<ListValue> args(new ListValue());
+  extension_service_->AddExtension(extension.get());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   args->Set(0, new base::StringValue("hello"));
   args->Set(1, new base::StringValue("world"));
   policy->ProcessAction(ActivityLogPolicy::ACTION_API, extension->id(),
diff --git a/chrome/browser/extensions/ad_view_browsertest.cc b/chrome/browser/extensions/ad_view_browsertest.cc
index 615a674..494ab6b 100644
--- a/chrome/browser/extensions/ad_view_browsertest.cc
+++ b/chrome/browser/extensions/ad_view_browsertest.cc
@@ -19,14 +19,8 @@
 
 // This test checks the "loadcommit" event is called when the page inside an
 // <adview> is loaded.
-#if defined(OS_MACOSX)
-// Very flaky on MacOS 10.8.
-#define MAYBE_LoadCommitEventIsCalled DISABLED_LoadCommitEventIsCalled
-#else
-#define MAYBE_LoadCommitEventIsCalled LoadCommitEventIsCalled
-#endif
-IN_PROC_BROWSER_TEST_F(AdViewTest, MAYBE_LoadCommitEventIsCalled) {
-  ASSERT_TRUE(StartTestServer());
+IN_PROC_BROWSER_TEST_F(AdViewTest, LoadCommitEventIsCalled) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   ASSERT_TRUE(RunPlatformAppTest(
       "platform_apps/ad_view/loadcommit_event")) << message_;
@@ -35,7 +29,7 @@
 // This test checks the "loadabort" event is called when the "src" attribute
 // of an <adview> is an invalid URL.
 IN_PROC_BROWSER_TEST_F(AdViewTest, LoadAbortEventIsCalled) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   ASSERT_TRUE(RunPlatformAppTest(
       "platform_apps/ad_view/loadabort_event")) << message_;
@@ -51,7 +45,7 @@
 #define MAYBE_CommitMessageFromAdNetwork CommitMessageFromAdNetwork
 #endif
 IN_PROC_BROWSER_TEST_F(AdViewTest, MAYBE_CommitMessageFromAdNetwork) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   ASSERT_TRUE(RunPlatformAppTest(
       "platform_apps/ad_view/onloadcommit_ack")) << message_;
@@ -63,7 +57,7 @@
 //       file (image035.png) which the trybots don't process correctly when
 //       first checked-in.
 IN_PROC_BROWSER_TEST_F(AdViewTest, DISABLED_DisplayFirstAd) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   ASSERT_TRUE(RunPlatformAppTest(
       "platform_apps/ad_view/display_first_ad")) << message_;
@@ -72,7 +66,7 @@
 // This test checks that <adview> attributes are also exposed as properties
 // (with the same name and value).
 IN_PROC_BROWSER_TEST_F(AdViewTest, PropertiesAreInSyncWithAttributes) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   ASSERT_TRUE(RunPlatformAppTest(
       "platform_apps/ad_view/properties_exposed")) << message_;
@@ -81,7 +75,7 @@
 // This test checks an <adview> element has no behavior when the "adview"
 // permission is missing from the application manifest.
 IN_PROC_BROWSER_TEST_F(AdViewTest, AdViewPermissionIsRequired) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   ASSERT_TRUE(RunPlatformAppTest(
       "platform_apps/ad_view/permission_required")) << message_;
@@ -90,8 +84,14 @@
 // This test checks that 1) it is possible change the value of the "ad-network"
 // attribute of an <adview> element and 2) changing the value will reset the
 // "src" attribute.
-IN_PROC_BROWSER_TEST_F(AdViewTest, ChangeAdNetworkValue) {
-  ASSERT_TRUE(StartTestServer());
+#if defined(OS_MACOSX)
+// Very flaky on MacOS 10.8 - crbug.com/253644.
+#define MAYBE_ChangeAdNetworkValue DISABLED_ChangeAdNetworkValue
+#else
+#define MAYBE_ChangeAdNetworkValue ChangeAdNetworkValue
+#endif
+IN_PROC_BROWSER_TEST_F(AdViewTest, MAYBE_ChangeAdNetworkValue) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   ASSERT_TRUE(RunPlatformAppTest(
       "platform_apps/ad_view/change_ad_network")) << message_;
@@ -109,7 +109,7 @@
 // This test checks an invalid "ad-network" value (i.e. not whitelisted)
 // is ignored.
 IN_PROC_BROWSER_TEST_F(AdViewNoSrcTest, InvalidAdNetworkIsIgnored) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   ASSERT_TRUE(RunPlatformAppTest(
       "platform_apps/ad_view/invalid_ad_network")) << message_;
@@ -118,7 +118,7 @@
 // This test checks the "src" attribute is ignored when the
 // "kEnableAdviewSrcAttribute" is missing.
 IN_PROC_BROWSER_TEST_F(AdViewNoSrcTest, EnableAdviewSrcAttributeFlagRequired) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   ASSERT_TRUE(RunPlatformAppTest(
       "platform_apps/ad_view/src_flag_required")) << message_;
@@ -158,7 +158,7 @@
 // This test checks an <adview> element has no behavior when the "kEnableAdview"
 // flag is missing.
 IN_PROC_BROWSER_TEST_F(AdViewNotEnabledTest, EnableAdviewFlagRequired) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   ASSERT_TRUE(RunPlatformAppTest(
       "platform_apps/ad_view/flag_required")) << message_;
diff --git a/chrome/browser/extensions/api/alarms/alarm_manager.cc b/chrome/browser/extensions/api/alarms/alarm_manager.cc
index 9f96d2c..74b1e03 100644
--- a/chrome/browser/extensions/api/alarms/alarm_manager.cc
+++ b/chrome/browser/extensions/api/alarms/alarm_manager.cc
@@ -8,9 +8,9 @@
 #include "base/json/json_writer.h"
 #include "base/lazy_instance.h"
 #include "base/message_loop.h"
-#include "base/time.h"
 #include "base/time/clock.h"
 #include "base/time/default_clock.h"
+#include "base/time/time.h"
 #include "base/value_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/extensions/event_router.h"
@@ -41,7 +41,7 @@
 
   virtual void OnAlarm(const std::string& extension_id,
                        const Alarm& alarm) OVERRIDE {
-    scoped_ptr<ListValue> args(new ListValue());
+    scoped_ptr<base::ListValue> args(new base::ListValue());
     args->Append(alarm.js_alarm->ToValue().release());
     scoped_ptr<Event> event(new Event(kOnAlarmEvent, args.Pass()));
     ExtensionSystem::Get(profile_)->event_router()->DispatchEventToExtension(
@@ -75,7 +75,7 @@
 }
 
 scoped_ptr<base::ListValue> AlarmsToValue(const std::vector<Alarm>& alarms) {
-  scoped_ptr<base::ListValue> list(new ListValue());
+  scoped_ptr<base::ListValue> list(new base::ListValue());
   for (size_t i = 0; i < alarms.size(); ++i) {
     scoped_ptr<base::DictionaryValue> alarm =
         alarms[i].js_alarm->ToValue().Pass();
@@ -234,7 +234,7 @@
   if (!storage)
     return;
 
-  scoped_ptr<Value> alarms;
+  scoped_ptr<base::Value> alarms;
   AlarmMap::iterator list = alarms_.find(extension_id);
   if (list != alarms_.end())
     alarms.reset(AlarmsToValue(list->second).release());
diff --git a/chrome/browser/extensions/api/alarms/alarm_manager.h b/chrome/browser/extensions/api/alarms/alarm_manager.h
index a021603..66ebfc8 100644
--- a/chrome/browser/extensions/api/alarms/alarm_manager.h
+++ b/chrome/browser/extensions/api/alarms/alarm_manager.h
@@ -5,12 +5,12 @@
 #ifndef CHROME_BROWSER_EXTENSIONS_API_ALARMS_ALARM_MANAGER_H__
 #define CHROME_BROWSER_EXTENSIONS_API_ALARMS_ALARM_MANAGER_H__
 
-#include <string>
 #include <map>
+#include <string>
 #include <vector>
 
 #include "base/memory/weak_ptr.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/extensions/api/profile_keyed_api_factory.h"
 #include "chrome/browser/extensions/extension_function.h"
 #include "chrome/common/extensions/api/alarms.h"
diff --git a/chrome/browser/extensions/api/app_current_window_internal/app_current_window_internal_api.cc b/chrome/browser/extensions/api/app_current_window_internal/app_current_window_internal_api.cc
index c1912ea..2f1b92b 100644
--- a/chrome/browser/extensions/api/app_current_window_internal/app_current_window_internal_api.cc
+++ b/chrome/browser/extensions/api/app_current_window_internal/app_current_window_internal_api.cc
@@ -4,14 +4,15 @@
 
 #include "chrome/browser/extensions/api/app_current_window_internal/app_current_window_internal_api.h"
 
+#include "apps/shell_window.h"
 #include "base/command_line.h"
 #include "chrome/browser/extensions/shell_window_registry.h"
 #include "chrome/browser/ui/extensions/native_app_window.h"
-#include "chrome/browser/ui/extensions/shell_window.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/extensions/api/app_current_window_internal.h"
 #include "chrome/common/extensions/api/app_window.h"
 
+using apps::ShellWindow;
 namespace SetBounds = extensions::api::app_current_window_internal::SetBounds;
 using extensions::api::app_current_window_internal::Bounds;
 namespace SetIcon = extensions::api::app_current_window_internal::SetIcon;
diff --git a/chrome/browser/extensions/api/app_current_window_internal/app_current_window_internal_api.h b/chrome/browser/extensions/api/app_current_window_internal/app_current_window_internal_api.h
index 110b5eb..806ae3b 100644
--- a/chrome/browser/extensions/api/app_current_window_internal/app_current_window_internal_api.h
+++ b/chrome/browser/extensions/api/app_current_window_internal/app_current_window_internal_api.h
@@ -7,7 +7,9 @@
 
 #include "chrome/browser/extensions/extension_function.h"
 
+namespace apps {
 class ShellWindow;
+}
 
 namespace extensions {
 
@@ -16,7 +18,7 @@
   virtual ~AppCurrentWindowInternalExtensionFunction() {}
 
   // Invoked with the current shell window.
-  virtual bool RunWithWindow(ShellWindow* window) = 0;
+  virtual bool RunWithWindow(apps::ShellWindow* window) = 0;
 
  private:
   virtual bool RunImpl() OVERRIDE;
@@ -30,7 +32,7 @@
 
  protected:
   virtual ~AppCurrentWindowInternalFocusFunction() {}
-  virtual bool RunWithWindow(ShellWindow* window) OVERRIDE;
+  virtual bool RunWithWindow(apps::ShellWindow* window) OVERRIDE;
 };
 
 class AppCurrentWindowInternalFullscreenFunction
@@ -41,7 +43,7 @@
 
  protected:
   virtual ~AppCurrentWindowInternalFullscreenFunction() {}
-  virtual bool RunWithWindow(ShellWindow* window) OVERRIDE;
+  virtual bool RunWithWindow(apps::ShellWindow* window) OVERRIDE;
 };
 
 class AppCurrentWindowInternalMaximizeFunction
@@ -52,7 +54,7 @@
 
  protected:
   virtual ~AppCurrentWindowInternalMaximizeFunction() {}
-  virtual bool RunWithWindow(ShellWindow* window) OVERRIDE;
+  virtual bool RunWithWindow(apps::ShellWindow* window) OVERRIDE;
 };
 
 class AppCurrentWindowInternalMinimizeFunction
@@ -63,7 +65,7 @@
 
  protected:
   virtual ~AppCurrentWindowInternalMinimizeFunction() {}
-  virtual bool RunWithWindow(ShellWindow* window) OVERRIDE;
+  virtual bool RunWithWindow(apps::ShellWindow* window) OVERRIDE;
 };
 
 class AppCurrentWindowInternalRestoreFunction
@@ -74,7 +76,7 @@
 
  protected:
   virtual ~AppCurrentWindowInternalRestoreFunction() {}
-  virtual bool RunWithWindow(ShellWindow* window) OVERRIDE;
+  virtual bool RunWithWindow(apps::ShellWindow* window) OVERRIDE;
 };
 
 class AppCurrentWindowInternalDrawAttentionFunction
@@ -85,7 +87,7 @@
 
  protected:
   virtual ~AppCurrentWindowInternalDrawAttentionFunction() {}
-  virtual bool RunWithWindow(ShellWindow* window) OVERRIDE;
+  virtual bool RunWithWindow(apps::ShellWindow* window) OVERRIDE;
 };
 
 class AppCurrentWindowInternalClearAttentionFunction
@@ -96,7 +98,7 @@
 
  protected:
   virtual ~AppCurrentWindowInternalClearAttentionFunction() {}
-  virtual bool RunWithWindow(ShellWindow* window) OVERRIDE;
+  virtual bool RunWithWindow(apps::ShellWindow* window) OVERRIDE;
 };
 
 class AppCurrentWindowInternalShowFunction
@@ -107,7 +109,7 @@
 
  protected:
   virtual ~AppCurrentWindowInternalShowFunction() {}
-  virtual bool RunWithWindow(ShellWindow* window) OVERRIDE;
+  virtual bool RunWithWindow(apps::ShellWindow* window) OVERRIDE;
 };
 
 class AppCurrentWindowInternalHideFunction
@@ -118,7 +120,7 @@
 
  protected:
   virtual ~AppCurrentWindowInternalHideFunction() {}
-  virtual bool RunWithWindow(ShellWindow* window) OVERRIDE;
+  virtual bool RunWithWindow(apps::ShellWindow* window) OVERRIDE;
 };
 
 class AppCurrentWindowInternalSetBoundsFunction
@@ -128,7 +130,7 @@
                              APP_CURRENTWINDOWINTERNAL_SETBOUNDS)
  protected:
   virtual ~AppCurrentWindowInternalSetBoundsFunction() {}
-  virtual bool RunWithWindow(ShellWindow* window) OVERRIDE;
+  virtual bool RunWithWindow(apps::ShellWindow* window) OVERRIDE;
 };
 
 class AppCurrentWindowInternalSetIconFunction
@@ -139,7 +141,7 @@
 
  protected:
   virtual ~AppCurrentWindowInternalSetIconFunction() {}
-  virtual bool RunWithWindow(ShellWindow* window) OVERRIDE;
+  virtual bool RunWithWindow(apps::ShellWindow* window) OVERRIDE;
 };
 
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/app_runtime/app_runtime_api.cc b/chrome/browser/extensions/api/app_runtime/app_runtime_api.cc
index 52db244..d4af336 100644
--- a/chrome/browser/extensions/api/app_runtime/app_runtime_api.cc
+++ b/chrome/browser/extensions/api/app_runtime/app_runtime_api.cc
@@ -48,14 +48,14 @@
 // static.
 void AppEventRouter::DispatchOnLaunchedEvent(
     Profile* profile, const Extension* extension) {
-  scoped_ptr<ListValue> arguments(new ListValue());
+  scoped_ptr<base::ListValue> arguments(new base::ListValue());
   DispatchOnLaunchedEventImpl(extension->id(), arguments.Pass(), profile);
 }
 
 // static.
 void AppEventRouter::DispatchOnRestartedEvent(Profile* profile,
                                               const Extension* extension) {
-  scoped_ptr<ListValue> arguments(new ListValue());
+  scoped_ptr<base::ListValue> arguments(new base::ListValue());
   scoped_ptr<Event> event(new Event(kOnRestarted, arguments.Pass()));
   event->restrict_to_profile = profile;
   extensions::ExtensionSystem::Get(profile)->event_router()->
@@ -67,15 +67,15 @@
     Profile* profile, const Extension* extension,
     const std::string& handler_id, const std::string& mime_type,
     const extensions::app_file_handler_util::GrantedFileEntry& file_entry) {
-  scoped_ptr<ListValue> args(new ListValue());
-  DictionaryValue* launch_data = new DictionaryValue();
+  scoped_ptr<base::ListValue> args(new base::ListValue());
+  base::DictionaryValue* launch_data = new base::DictionaryValue();
   launch_data->SetString("id", handler_id);
-  DictionaryValue* launch_item = new DictionaryValue;
+  base::DictionaryValue* launch_item = new base::DictionaryValue;
   launch_item->SetString("fileSystemId", file_entry.filesystem_id);
   launch_item->SetString("baseName", file_entry.registered_name);
   launch_item->SetString("mimeType", mime_type);
   launch_item->SetString("entryId", file_entry.id);
-  ListValue* items = new ListValue;
+  base::ListValue* items = new base::ListValue;
   items->Append(launch_item);
   launch_data->Set("items", items);
   args->Append(launch_data);
diff --git a/chrome/browser/extensions/api/app_window/app_window_api.cc b/chrome/browser/extensions/api/app_window/app_window_api.cc
index 5655f04..1c0a0e5 100644
--- a/chrome/browser/extensions/api/app_window/app_window_api.cc
+++ b/chrome/browser/extensions/api/app_window/app_window_api.cc
@@ -4,16 +4,17 @@
 
 #include "chrome/browser/extensions/api/app_window/app_window_api.h"
 
+#include "apps/shell_window.h"
 #include "base/command_line.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/app_mode/app_mode_utils.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/devtools/devtools_window.h"
 #include "chrome/browser/extensions/shell_window_registry.h"
 #include "chrome/browser/extensions/window_controller.h"
+#include "chrome/browser/ui/apps/chrome_shell_window_delegate.h"
 #include "chrome/browser/ui/extensions/native_app_window.h"
-#include "chrome/browser/ui/extensions/shell_window.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/extensions/api/app_window.h"
 #include "content/public/browser/notification_registrar.h"
@@ -33,6 +34,8 @@
 #include "ui/aura/window.h"
 #endif
 
+using apps::ShellWindow;
+
 namespace app_window = extensions::api::app_window;
 namespace Create = app_window::Create;
 
@@ -89,7 +92,7 @@
   result->SetBoolean("fullscreen", window->GetBaseWindow()->IsFullscreen());
   result->SetBoolean("minimized", window->GetBaseWindow()->IsMinimized());
   result->SetBoolean("maximized", window->GetBaseWindow()->IsMaximized());
-  DictionaryValue* boundsValue = new DictionaryValue();
+  base::DictionaryValue* boundsValue = new base::DictionaryValue();
   gfx::Rect bounds = window->GetClientBounds();
   boundsValue->SetInteger("left", bounds.x());
   boundsValue->SetInteger("top", bounds.y());
@@ -289,8 +292,12 @@
   if (force_maximize)
     create_params.state = ui::SHOW_STATE_MAXIMIZED;
 
-  ShellWindow* shell_window =
-      ShellWindow::Create(profile(), GetExtension(), url, create_params);
+  ShellWindow* shell_window = ShellWindow::Create(
+      profile(),
+      new chrome::ChromeShellWindowDelegate(),
+      GetExtension(),
+      url,
+      create_params);
 
   if (chrome::ShouldForceFullscreenApp())
     shell_window->Fullscreen();
diff --git a/chrome/browser/extensions/api/app_window/app_window_apitest.cc b/chrome/browser/extensions/api/app_window/app_window_apitest.cc
index a7acfc3..31eeaf7 100644
--- a/chrome/browser/extensions/api/app_window/app_window_apitest.cc
+++ b/chrome/browser/extensions/api/app_window/app_window_apitest.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "apps/shell_window.h"
 #include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "chrome/browser/extensions/extension_test_message_listener.h"
@@ -9,7 +10,6 @@
 #include "chrome/browser/extensions/shell_window_registry.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/extensions/native_app_window.h"
-#include "chrome/browser/ui/extensions/shell_window.h"
 #include "chrome/test/base/testing_profile.h"
 #include "ui/base/base_window.h"
 #include "ui/gfx/rect.h"
@@ -18,6 +18,8 @@
 #include "content/public/test/test_utils.h"
 #endif
 
+using apps::ShellWindow;
+
 namespace {
 
 class TestShellWindowRegistryObserver
diff --git a/chrome/browser/extensions/api/audio/audio_api.cc b/chrome/browser/extensions/api/audio/audio_api.cc
index 0c717b1..b6c37fb 100644
--- a/chrome/browser/extensions/api/audio/audio_api.cc
+++ b/chrome/browser/extensions/api/audio/audio_api.cc
@@ -38,8 +38,9 @@
 
 void AudioAPI::OnDeviceChanged() {
   if (profile_ && ExtensionSystem::Get(profile_)->event_router()) {
-    scoped_ptr<Event> event(new Event(event_names::kOnAudioDeviceChanged,
-                                      scoped_ptr<ListValue>(new ListValue())));
+    scoped_ptr<Event> event(new Event(
+        event_names::kOnAudioDeviceChanged,
+        scoped_ptr<base::ListValue>(new base::ListValue())));
     ExtensionSystem::Get(profile_)->event_router()->BroadcastEvent(
         event.Pass());
   }
diff --git a/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc b/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc
index e6bb9cd..86fc7ea 100644
--- a/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc
+++ b/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc
@@ -53,7 +53,7 @@
 bool AutotestPrivateLoginStatusFunction::RunImpl() {
   DVLOG(1) << "AutotestPrivateLoginStatusFunction";
 
-  DictionaryValue* result(new DictionaryValue);
+  base::DictionaryValue* result(new base::DictionaryValue);
 #if defined(OS_CHROMEOS)
   const chromeos::UserManager* user_manager = chromeos::UserManager::Get();
   const bool is_screen_locked =
diff --git a/chrome/browser/extensions/api/bluetooth/bluetooth_api.cc b/chrome/browser/extensions/api/bluetooth/bluetooth_api.cc
index 11c91f5..0055d9b 100644
--- a/chrome/browser/extensions/api/bluetooth/bluetooth_api.cc
+++ b/chrome/browser/extensions/api/bluetooth/bluetooth_api.cc
@@ -15,7 +15,7 @@
 #include "chrome/browser/extensions/extension_system.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/extensions/api/bluetooth.h"
-#include "chrome/common/extensions/permissions/bluetooth_device_permission.h"
+#include "chrome/common/extensions/permissions/bluetooth_permission.h"
 #include "chrome/common/extensions/permissions/permissions_data.h"
 #include "content/public/browser/browser_thread.h"
 #include "device/bluetooth/bluetooth_adapter.h"
@@ -47,10 +47,10 @@
     "Could not get local Out Of Band Pairing Data";
 const char kCouldNotSetOutOfBandPairingData[] =
     "Could not set Out Of Band Pairing Data";
-const char kDevicePermissionDenied[] = "Permission to access device denied";
 const char kFailedToConnect[] = "Connection failed";
 const char kInvalidDevice[] = "Invalid device";
 const char kInvalidUuid[] = "Invalid UUID";
+const char kPermissionDenied[] = "Permission to add profile denied.";
 const char kPlatformNotSupported[] =
     "This operation is not supported on your platform";
 const char kProfileAlreadyRegistered[] =
@@ -126,6 +126,13 @@
     return false;
   }
 
+  BluetoothPermission::CheckParam param(params->profile.uuid);
+  if (!PermissionsData::CheckAPIPermissionWithParam(
+          GetExtension(), APIPermission::kBluetooth, &param)) {
+    SetError(kPermissionDenied);
+    return false;
+  }
+
   uuid_ = device::bluetooth_utils::CanonicalUuid(params->profile.uuid);
 
   if (GetEventRouter(profile())->HasProfile(uuid_)) {
@@ -229,7 +236,7 @@
 
   BluetoothDevice::ServiceList service_list = device->GetServices();
 
-  ListValue* profiles = new ListValue;
+  base::ListValue* profiles = new base::ListValue;
   for (BluetoothDevice::ServiceList::const_iterator iter = service_list.begin();
        iter != service_list.end();
        ++iter) {
@@ -348,7 +355,7 @@
     return false;
   }
 
-  ListValue* services = new ListValue;
+  base::ListValue* services = new base::ListValue;
   SetResult(services);
 
   device->GetServiceRecords(
@@ -375,14 +382,6 @@
   EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
   const bluetooth::ConnectOptions& options = params->options;
 
-  BluetoothDevicePermission::CheckParam param(options.device.address);
-  if (!PermissionsData::CheckAPIPermissionWithParam(
-          GetExtension(), APIPermission::kBluetoothDevice, &param)) {
-    SetError(kDevicePermissionDenied);
-    SendResponse(false);
-    return false;
-  }
-
   if (!BluetoothDevice::IsUUIDValid(options.profile.uuid)) {
     SetError(kInvalidUuid);
     SendResponse(false);
@@ -469,10 +468,10 @@
 bool BluetoothWriteFunction::Prepare() {
   // TODO(bryeung): update to new-style parameter passing when ArrayBuffer
   // support is added
-  DictionaryValue* options;
+  base::DictionaryValue* options;
   EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &options));
 
-  DictionaryValue* socket;
+  base::DictionaryValue* socket;
   EXTENSION_FUNCTION_VALIDATE(options->GetDictionary("socket", &socket));
 
   int socket_id;
@@ -506,8 +505,8 @@
   success_ = socket_->Send(drainable_io_buffer.get());
   if (success_) {
     if (drainable_io_buffer->BytesConsumed() > 0)
-      SetResult(
-          Value::CreateIntegerValue(drainable_io_buffer->BytesConsumed()));
+      SetResult(base::Value::CreateIntegerValue(
+          drainable_io_buffer->BytesConsumed()));
     else
       results_.reset();
   } else {
@@ -532,7 +531,7 @@
     scoped_refptr<BluetoothAdapter> adapter) {
   // TODO(bryeung): update to new-style parameter passing when ArrayBuffer
   // support is added
-  DictionaryValue* options;
+  base::DictionaryValue* options;
   EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &options));
   std::string address;
   EXTENSION_FUNCTION_VALIDATE(options->GetString("deviceAddress", &address));
@@ -545,7 +544,7 @@
   }
 
   if (options->HasKey("data")) {
-    DictionaryValue* data_in;
+    base::DictionaryValue* data_in;
     EXTENSION_FUNCTION_VALIDATE(options->GetDictionary("data", &data_in));
 
     device::BluetoothOutOfBandPairingData data_out;
@@ -593,7 +592,7 @@
 
   // TODO(bryeung): convert to bluetooth::OutOfBandPairingData
   // when ArrayBuffer support within objects is completed.
-  DictionaryValue* result = new DictionaryValue();
+  base::DictionaryValue* result = new base::DictionaryValue();
   result->Set("hash", hash);
   result->Set("randomizer", randomizer);
 
diff --git a/chrome/browser/extensions/api/bluetooth/bluetooth_apitest.cc b/chrome/browser/extensions/api/bluetooth/bluetooth_apitest.cc
index a2f43f2..92ad350 100644
--- a/chrome/browser/extensions/api/bluetooth/bluetooth_apitest.cc
+++ b/chrome/browser/extensions/api/bluetooth/bluetooth_apitest.cc
@@ -7,7 +7,6 @@
 #include "base/strings/stringprintf.h"
 #include "chrome/browser/extensions/api/bluetooth/bluetooth_api.h"
 #include "chrome/browser/extensions/api/bluetooth/bluetooth_event_router.h"
-#include "chrome/browser/extensions/api/permissions/permissions_api.h"
 #include "chrome/browser/extensions/extension_apitest.h"
 #include "chrome/browser/extensions/extension_function_test_utils.h"
 #include "chrome/browser/extensions/extension_service.h"
@@ -136,13 +135,6 @@
   return true;
 }
 
-static void CallConnectToProfileCallback(
-    BluetoothProfile* profile,
-    const base::Closure& callback,
-    const BluetoothDevice::ErrorCallback& error_callback) {
-  callback.Run();
-}
-
 static void CallDiscoveryCallback(
     const base::Closure& callback,
     const BluetoothAdapter::ErrorCallback& error_callback) {
@@ -164,46 +156,66 @@
 }  // namespace
 
 IN_PROC_BROWSER_TEST_F(BluetoothApiTest, Profiles) {
+  // Run in context of an extension that has permissions for the profiles
+  // we intend to register.
+  scoped_refptr<const Extension> extension(
+      LoadExtension(test_data_dir_.AppendASCII("bluetooth/profiles")));
+  ASSERT_TRUE(extension.get());
+
   EXPECT_CALL(*profile1_, SetConnectionCallback(testing::_));
   scoped_refptr<TestBluetoothAddProfileFunction> add_profile_function;
-  add_profile_function = setupFunction(
-      new TestBluetoothAddProfileFunction(profile1_.get()));
+  add_profile_function = new TestBluetoothAddProfileFunction(profile1_.get());
+  add_profile_function->set_extension(extension.get());
+  add_profile_function->set_has_callback(true);
   std::string error(utils::RunFunctionAndReturnError(
       add_profile_function.get(), "[{\"uuid\": \"1234\"}]", browser()));
   ASSERT_TRUE(error.empty());
 
   // Registering the profile for the same uuid again will throw an error.
-  add_profile_function = setupFunction(
-      new TestBluetoothAddProfileFunction(profile2_.get()));
+  add_profile_function = new TestBluetoothAddProfileFunction(profile2_.get());
+  add_profile_function->set_extension(extension.get());
+  add_profile_function->set_has_callback(true);
   error = utils::RunFunctionAndReturnError(
       add_profile_function.get(), "[{\"uuid\": \"1234\"}]", browser());
   ASSERT_FALSE(error.empty());
 
-  add_profile_function = setupFunction(
-      new TestBluetoothAddProfileFunction(profile2_.get()));
+  add_profile_function = new TestBluetoothAddProfileFunction(profile2_.get());
+  add_profile_function->set_extension(extension.get());
+  add_profile_function->set_has_callback(true);
   error = utils::RunFunctionAndReturnError(
       add_profile_function.get(), "[{\"uuid\": \"5678\"}]", browser());
   ASSERT_TRUE(error.empty());
 
   scoped_refptr<api::BluetoothRemoveProfileFunction> remove_profile_function;
-  remove_profile_function = setupFunction(
-      new api::BluetoothRemoveProfileFunction());
+  remove_profile_function = new api::BluetoothRemoveProfileFunction();
+  remove_profile_function->set_extension(extension.get());
+  remove_profile_function->set_has_callback(true);
   error = utils::RunFunctionAndReturnError(
       remove_profile_function.get(), "[{\"uuid\": \"1234\"}]", browser());
   ASSERT_TRUE(error.empty());
 
-  remove_profile_function = setupFunction(
-      new api::BluetoothRemoveProfileFunction());
+  remove_profile_function = new api::BluetoothRemoveProfileFunction();
+  remove_profile_function->set_extension(extension.get());
+  remove_profile_function->set_has_callback(true);
   error = utils::RunFunctionAndReturnError(
       remove_profile_function.get(), "[{\"uuid\": \"5678\"}]", browser());
   ASSERT_TRUE(error.empty());
 
   // Removing the same profile again will throw an error.
-  remove_profile_function = setupFunction(
-      new api::BluetoothRemoveProfileFunction());
+  remove_profile_function = new api::BluetoothRemoveProfileFunction();
+  remove_profile_function->set_extension(extension.get());
+  remove_profile_function->set_has_callback(true);
   error = utils::RunFunctionAndReturnError(
       remove_profile_function.get(), "[{\"uuid\": \"5678\"}]", browser());
   ASSERT_FALSE(error.empty());
+
+  // Registering a profile we don't have permission for will throw an error.
+  add_profile_function = new TestBluetoothAddProfileFunction(profile1_.get());
+  add_profile_function->set_extension(extension.get());
+  add_profile_function->set_has_callback(true);
+  error = utils::RunFunctionAndReturnError(
+      add_profile_function.get(), "[{\"uuid\": \"9999\"}]", browser());
+  ASSERT_FALSE(error.empty());
 }
 
 IN_PROC_BROWSER_TEST_F(BluetoothApiTest, GetAdapterState) {
@@ -571,19 +583,3 @@
 
   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
 }
-
-IN_PROC_BROWSER_TEST_F(BluetoothApiTest, Permissions) {
-  extensions::PermissionsRequestFunction::SetAutoConfirmForTests(true);
-  extensions::PermissionsRequestFunction::SetIgnoreUserGestureForTests(true);
-
-  event_router()->AddProfile(
-      "00001101-0000-1000-8000-00805f9b34fb", profile1_.get());
-
-  EXPECT_CALL(*mock_adapter_, GetDevice(device1_->GetAddress()))
-      .WillOnce(testing::Return(device1_.get()));
-  EXPECT_CALL(*device1_,
-              ConnectToProfile(testing::_, testing::_, testing::_))
-      .WillOnce(testing::Invoke(CallConnectToProfileCallback));
-
-  EXPECT_TRUE(RunExtensionTest("bluetooth/permissions")) << message_;
-}
diff --git a/chrome/browser/extensions/api/bluetooth/bluetooth_event_router.cc b/chrome/browser/extensions/api/bluetooth/bluetooth_event_router.cc
index 5915b54..5147a7b 100644
--- a/chrome/browser/extensions/api/bluetooth/bluetooth_event_router.cc
+++ b/chrome/browser/extensions/api/bluetooth/bluetooth_event_router.cc
@@ -162,7 +162,7 @@
 
 void ExtensionBluetoothEventRouter::DispatchDeviceEvent(
     const char* event_name, const extensions::api::bluetooth::Device& device) {
-  scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   args->Append(device.ToValue().release());
   scoped_ptr<Event> event(new Event(event_name, args.Pass()));
   ExtensionSystem::Get(profile_)->event_router()->BroadcastEvent(event.Pass());
@@ -182,7 +182,7 @@
   result_socket.profile.uuid = uuid;
   result_socket.id = socket_id;
 
-  scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   args->Append(result_socket.ToValue().release());
   scoped_ptr<Event> event(new Event(
       extensions::event_names::kBluetoothOnConnection, args.Pass()));
@@ -271,7 +271,7 @@
   api::bluetooth::AdapterState state;
   PopulateAdapterState(*adapter_.get(), &state);
 
-  scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   args->Append(state.ToValue().release());
   scoped_ptr<Event> event(new Event(
       extensions::event_names::kBluetoothOnAdapterStateChanged,
diff --git a/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.cc b/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.cc
index c7f06e7..67d0cf1 100644
--- a/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.cc
+++ b/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.cc
@@ -88,8 +88,8 @@
 // Recursively adds a node to a list. This is by used |BookmarkNodeDataToJSON|
 // when the data comes from the current profile. In this case we have a
 // BookmarkNode since we got the data from the current profile.
-void AddNodeToList(ListValue* list, const BookmarkNode& node) {
-  DictionaryValue* dict = new DictionaryValue();
+void AddNodeToList(base::ListValue* list, const BookmarkNode& node) {
+  base::DictionaryValue* dict = new base::DictionaryValue();
 
   // Add id and parentId so we can associate the data with existing nodes on the
   // client side.
@@ -104,7 +104,7 @@
 
   dict->SetString(bookmark_keys::kTitleKey, node.GetTitle());
 
-  ListValue* children = new ListValue();
+  base::ListValue* children = new base::ListValue();
   for (int i = 0; i < node.child_count(); ++i)
     AddNodeToList(children, *node.GetChild(i));
   dict->Set(bookmark_keys::kChildrenKey, children);
@@ -115,16 +115,16 @@
 // Recursively adds an element to a list. This is used by
 // |BookmarkNodeDataToJSON| when the data comes from a different profile. When
 // the data comes from a different profile we do not have any IDs or parent IDs.
-void AddElementToList(ListValue* list,
+void AddElementToList(base::ListValue* list,
                       const BookmarkNodeData::Element& element) {
-  DictionaryValue* dict = new DictionaryValue();
+  base::DictionaryValue* dict = new base::DictionaryValue();
 
   if (element.is_url)
     dict->SetString(bookmark_keys::kUrlKey, element.url.spec());
 
   dict->SetString(bookmark_keys::kTitleKey, element.title);
 
-  ListValue* children = new ListValue();
+  base::ListValue* children = new base::ListValue();
   for (size_t i = 0; i < element.children.size(); ++i)
     AddElementToList(children, element.children[i]);
   dict->Set(bookmark_keys::kChildrenKey, children);
@@ -134,12 +134,12 @@
 
 // Builds the JSON structure based on the BookmarksDragData.
 void BookmarkNodeDataToJSON(Profile* profile, const BookmarkNodeData& data,
-                            ListValue* args) {
+                            base::ListValue* args) {
   bool same_profile = data.IsFromProfile(profile);
-  DictionaryValue* value = new DictionaryValue();
+  base::DictionaryValue* value = new base::DictionaryValue();
   value->SetBoolean(manager_keys::kSameProfileKey, same_profile);
 
-  ListValue* list = new ListValue();
+  base::ListValue* list = new base::ListValue();
   if (same_profile) {
     std::vector<const BookmarkNode*> nodes = data.GetNodes(profile);
     for (size_t i = 0; i < nodes.size(); ++i)
@@ -176,7 +176,7 @@
 
 void BookmarkManagerPrivateEventRouter::DispatchEvent(
     const char* event_name,
-    scoped_ptr<ListValue> args) {
+    scoped_ptr<base::ListValue> args) {
   if (!ExtensionSystem::Get(profile_)->event_router())
     return;
 
@@ -190,7 +190,7 @@
   if (data.size() == 0)
     return;
 
-  scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   BookmarkNodeDataToJSON(profile_, data, args.get());
   DispatchEvent(event_name, args.Pass());
 }
@@ -323,7 +323,7 @@
 }
 
 bool BookmarkManagerPrivateGetStringsFunction::RunImpl() {
-  DictionaryValue* localized_strings = new DictionaryValue();
+  base::DictionaryValue* localized_strings = new base::DictionaryValue();
 
   localized_strings->SetString("title",
       l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_TITLE));
@@ -501,7 +501,7 @@
     return false;
   }
 
-  scoped_ptr<ListValue> json(new ListValue());
+  scoped_ptr<base::ListValue> json(new base::ListValue());
   if (params->folders_only)
     bookmark_api_helpers::AddNodeFoldersOnly(node, json.get(), true);
   else
diff --git a/chrome/browser/extensions/api/bookmarks/bookmark_api_helpers.cc b/chrome/browser/extensions/api/bookmarks/bookmark_api_helpers.cc
index fc3a988..4b6a252 100644
--- a/chrome/browser/extensions/api/bookmarks/bookmark_api_helpers.cc
+++ b/chrome/browser/extensions/api/bookmarks/bookmark_api_helpers.cc
@@ -132,7 +132,8 @@
     for (int i = 0; i < node->child_count(); ++i) {
       const BookmarkNode* child = node->GetChild(i);
       if (child->IsVisible() && (!only_folders || child->is_folder())) {
-        DictionaryValue* dict = GetNodeDictionary(child, true, only_folders);
+        base::DictionaryValue* dict =
+            GetNodeDictionary(child, true, only_folders);
         children->Append(dict);
       }
     }
diff --git a/chrome/browser/extensions/api/bookmarks/bookmarks_api.cc b/chrome/browser/extensions/api/bookmarks/bookmarks_api.cc
index 0336c98..553a13f 100644
--- a/chrome/browser/extensions/api/bookmarks/bookmarks_api.cc
+++ b/chrome/browser/extensions/api/bookmarks/bookmarks_api.cc
@@ -19,7 +19,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/bookmarks/bookmark_html_writer.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
@@ -30,14 +30,14 @@
 #include "chrome/browser/extensions/extension_function_dispatcher.h"
 #include "chrome/browser/extensions/extension_system.h"
 #include "chrome/browser/extensions/extensions_quota_service.h"
-#include "chrome/browser/importer/importer_data_types.h"
-#include "chrome/browser/importer/importer_host.h"
-#include "chrome/browser/importer/importer_type.h"
+#include "chrome/browser/importer/external_process_importer_host.h"
+#include "chrome/browser/importer/importer_creator.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/chrome_select_file_policy.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/extensions/api/bookmarks.h"
+#include "chrome/common/importer/importer_data_types.h"
 #include "chrome/common/pref_names.h"
 #include "components/user_prefs/user_prefs.h"
 #include "content/public/browser/notification_service.h"
@@ -148,7 +148,7 @@
 
 void BookmarkEventRouter::DispatchEvent(
     const char* event_name,
-    scoped_ptr<ListValue> event_args) {
+    scoped_ptr<base::ListValue> event_args) {
   if (extensions::ExtensionSystem::Get(profile_)->event_router()) {
     extensions::ExtensionSystem::Get(profile_)->event_router()->BroadcastEvent(
         make_scoped_ptr(new extensions::Event(event_name, event_args.Pass())));
@@ -169,10 +169,10 @@
                                             int old_index,
                                             const BookmarkNode* new_parent,
                                             int new_index) {
-  scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   const BookmarkNode* node = new_parent->GetChild(new_index);
-  args->Append(new StringValue(base::Int64ToString(node->id())));
-  DictionaryValue* object_args = new DictionaryValue();
+  args->Append(new base::StringValue(base::Int64ToString(node->id())));
+  base::DictionaryValue* object_args = new base::DictionaryValue();
   object_args->SetString(keys::kParentIdKey,
                          base::Int64ToString(new_parent->id()));
   object_args->SetInteger(keys::kIndexKey, new_index);
@@ -187,9 +187,9 @@
 void BookmarkEventRouter::BookmarkNodeAdded(BookmarkModel* model,
                                             const BookmarkNode* parent,
                                             int index) {
-  scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   const BookmarkNode* node = parent->GetChild(index);
-  args->Append(new StringValue(base::Int64ToString(node->id())));
+  args->Append(new base::StringValue(base::Int64ToString(node->id())));
   scoped_ptr<BookmarkTreeNode> tree_node(
       bookmark_api_helpers::GetBookmarkTreeNode(node, false, false));
   args->Append(tree_node->ToValue().release());
@@ -201,9 +201,9 @@
                                               const BookmarkNode* parent,
                                               int index,
                                               const BookmarkNode* node) {
-  scoped_ptr<ListValue> args(new ListValue());
-  args->Append(new StringValue(base::Int64ToString(node->id())));
-  DictionaryValue* object_args = new DictionaryValue();
+  scoped_ptr<base::ListValue> args(new base::ListValue());
+  args->Append(new base::StringValue(base::Int64ToString(node->id())));
+  base::DictionaryValue* object_args = new base::DictionaryValue();
   object_args->SetString(keys::kParentIdKey,
                          base::Int64ToString(parent->id()));
   object_args->SetInteger(keys::kIndexKey, index);
@@ -221,15 +221,15 @@
 
 void BookmarkEventRouter::BookmarkNodeChanged(BookmarkModel* model,
                                               const BookmarkNode* node) {
-  scoped_ptr<ListValue> args(new ListValue());
-  args->Append(new StringValue(base::Int64ToString(node->id())));
+  scoped_ptr<base::ListValue> args(new base::ListValue());
+  args->Append(new base::StringValue(base::Int64ToString(node->id())));
 
   // TODO(erikkay) The only three things that BookmarkModel sends this
   // notification for are title, url and favicon.  Since we're currently
   // ignoring favicon and since the notification doesn't say which one anyway,
   // for now we only include title and url.  The ideal thing would be to change
   // BookmarkModel to indicate what changed.
-  DictionaryValue* object_args = new DictionaryValue();
+  base::DictionaryValue* object_args = new base::DictionaryValue();
   object_args->SetString(keys::kTitleKey, node->GetTitle());
   if (node->is_url())
     object_args->SetString(keys::kUrlKey, node->url().spec());
@@ -246,16 +246,17 @@
 void BookmarkEventRouter::BookmarkNodeChildrenReordered(
     BookmarkModel* model,
     const BookmarkNode* node) {
-  scoped_ptr<ListValue> args(new ListValue());
-  args->Append(new StringValue(base::Int64ToString(node->id())));
+  scoped_ptr<base::ListValue> args(new base::ListValue());
+  args->Append(new base::StringValue(base::Int64ToString(node->id())));
   int childCount = node->child_count();
-  ListValue* children = new ListValue();
+  base::ListValue* children = new base::ListValue();
   for (int i = 0; i < childCount; ++i) {
     const BookmarkNode* child = node->GetChild(i);
-    Value* child_id = new StringValue(base::Int64ToString(child->id()));
+    base::Value* child_id =
+        new base::StringValue(base::Int64ToString(child->id()));
     children->Append(child_id);
   }
-  DictionaryValue* reorder_info = new DictionaryValue();
+  base::DictionaryValue* reorder_info = new base::DictionaryValue();
   reorder_info->Set(keys::kChildIdsKey, children);
   args->Append(reorder_info);
 
@@ -264,12 +265,12 @@
 
 void BookmarkEventRouter::ExtensiveBookmarkChangesBeginning(
     BookmarkModel* model) {
-  scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   DispatchEvent(keys::kOnBookmarkImportBegan, args.Pass());
 }
 
 void BookmarkEventRouter::ExtensiveBookmarkChangesEnded(BookmarkModel* model) {
-  scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   DispatchEvent(keys::kOnBookmarkImportEnded, args.Pass());
 }
 
@@ -457,7 +458,7 @@
 }
 
 // static
-bool BookmarksRemoveFunction::ExtractIds(const ListValue* args,
+bool BookmarksRemoveFunction::ExtractIds(const base::ListValue* args,
                                          std::list<int64>* ids,
                                          bool* invalid_id) {
   std::string id_string;
@@ -568,7 +569,7 @@
 }
 
 // static
-bool BookmarksMoveFunction::ExtractIds(const ListValue* args,
+bool BookmarksMoveFunction::ExtractIds(const base::ListValue* args,
                                        std::list<int64>* ids,
                                        bool* invalid_id) {
   // For now, Move accepts ID parameters in the same way as an Update.
@@ -642,7 +643,7 @@
 }
 
 // static
-bool BookmarksUpdateFunction::ExtractIds(const ListValue* args,
+bool BookmarksUpdateFunction::ExtractIds(const base::ListValue* args,
                                          std::list<int64>* ids,
                                          bool* invalid_id) {
   // For now, Update accepts ID parameters in the same way as an Remove.
@@ -728,9 +729,9 @@
   explicit CreateBookmarkBucketMapper(Profile* profile) : profile_(profile) {}
   // TODO(tim): This should share code with BookmarksCreateFunction::RunImpl,
   // but I can't figure out a good way to do that with all the macros.
-  virtual void GetBucketsForArgs(const ListValue* args,
+  virtual void GetBucketsForArgs(const base::ListValue* args,
                                  BucketList* buckets) OVERRIDE {
-    const DictionaryValue* json;
+    const base::DictionaryValue* json;
     if (!args->GetDictionary(0, &json))
       return;
 
@@ -767,7 +768,7 @@
 class RemoveBookmarksBucketMapper : public BookmarkBucketMapper<std::string> {
  public:
   explicit RemoveBookmarksBucketMapper(Profile* profile) : profile_(profile) {}
-  virtual void GetBucketsForArgs(const ListValue* args,
+  virtual void GetBucketsForArgs(const base::ListValue* args,
                                  BucketList* buckets) OVERRIDE {
     typedef std::list<int64> IdList;
     IdList ids;
@@ -802,7 +803,8 @@
 class BookmarkIdMapper : public BookmarkBucketMapper<int64> {
  public:
   typedef std::list<int64> IdList;
-  virtual void GetBucketsForArgs(const ListValue* args, BucketList* buckets) {
+  virtual void GetBucketsForArgs(const base::ListValue* args,
+                                 BucketList* buckets) {
     IdList ids;
     bool invalid_id = false;
     if (!FunctionType::ExtractIds(args, &ids, &invalid_id) || invalid_id)
@@ -977,7 +979,7 @@
   // TODO(jgreenwald): remove ifdef once extensions are no longer built on
   // Android.
   // Deletes itself.
-  ImporterHost* importer_host = new ImporterHost;
+  ExternalProcessImporterHost* importer_host = new ExternalProcessImporterHost;
   importer::SourceProfile source_profile;
   source_profile.importer_type = importer::TYPE_BOOKMARKS_FILE;
   source_profile.source_path = path;
diff --git a/chrome/browser/extensions/api/browsing_data/browsing_data_api.cc b/chrome/browser/extensions/api/browsing_data/browsing_data_api.cc
index 0471aed..d8a5378 100644
--- a/chrome/browser/extensions/api/browsing_data/browsing_data_api.cc
+++ b/chrome/browser/extensions/api/browsing_data/browsing_data_api.cc
@@ -121,7 +121,7 @@
   // REMOVE_SITE_DATA in browsing_data_remover.h, the former for the unprotected
   // web, the latter for  protected web data. There is no UI control for
   // extension data.
-  scoped_ptr<DictionaryValue> origin_types(new DictionaryValue);
+  scoped_ptr<base::DictionaryValue> origin_types(new base::DictionaryValue);
   origin_types->SetBoolean(
       extension_browsing_data_api_constants::kUnprotectedWebKey,
       prefs->GetBoolean(prefs::kDeleteCookies));
@@ -141,14 +141,14 @@
     since = time.ToJsTime();
   }
 
-  scoped_ptr<DictionaryValue> options(new DictionaryValue);
+  scoped_ptr<base::DictionaryValue> options(new base::DictionaryValue);
   options->Set(extension_browsing_data_api_constants::kOriginTypesKey,
                origin_types.release());
   options->SetDouble(extension_browsing_data_api_constants::kSinceKey, since);
 
   // Fill dataToRemove and dataRemovalPermitted.
-  scoped_ptr<DictionaryValue> selected(new DictionaryValue);
-  scoped_ptr<DictionaryValue> permitted(new DictionaryValue);
+  scoped_ptr<base::DictionaryValue> selected(new base::DictionaryValue);
+  scoped_ptr<base::DictionaryValue> permitted(new base::DictionaryValue);
 
   bool delete_site_data = prefs->GetBoolean(prefs::kDeleteCookies) ||
                           prefs->GetBoolean(prefs::kDeleteHostedAppsData);
@@ -195,7 +195,7 @@
              extension_browsing_data_api_constants::kPasswordsKey,
              prefs->GetBoolean(prefs::kDeletePasswords));
 
-  scoped_ptr<DictionaryValue> result(new DictionaryValue);
+  scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue);
   result->Set(extension_browsing_data_api_constants::kOptionsKey,
               options.release());
   result->Set(extension_browsing_data_api_constants::kDataToRemoveKey,
@@ -206,10 +206,11 @@
   return true;
 }
 
-void BrowsingDataSettingsFunction::SetDetails(DictionaryValue* selected_dict,
-                                              DictionaryValue* permitted_dict,
-                                              const char* data_type,
-                                              bool is_selected) {
+void BrowsingDataSettingsFunction::SetDetails(
+    base::DictionaryValue* selected_dict,
+    base::DictionaryValue* permitted_dict,
+    const char* data_type,
+    bool is_selected) {
   bool is_permitted = IsRemovalPermitted(MaskForKey(data_type),
                                          profile()->GetPrefs());
   selected_dict->SetBoolean(data_type, is_selected && is_permitted);
@@ -228,7 +229,7 @@
   DCHECK(profile());
 
   // Grab the initial |options| parameter, and parse out the arguments.
-  DictionaryValue* options;
+  base::DictionaryValue* options;
   EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &options));
   DCHECK(options);
 
@@ -311,7 +312,7 @@
   // UNPROTECTED_WEB if the developer doesn't specify anything.
   int mask = BrowsingDataHelper::UNPROTECTED_WEB;
 
-  const DictionaryValue* d = NULL;
+  const base::DictionaryValue* d = NULL;
   if (options.HasKey(extension_browsing_data_api_constants::kOriginTypesKey)) {
     EXTENSION_FUNCTION_VALIDATE(options.GetDictionary(
         extension_browsing_data_api_constants::kOriginTypesKey, &d));
@@ -358,7 +359,7 @@
 
   int removal_mask = 0;
 
-  for (DictionaryValue::Iterator i(*data_to_remove);
+  for (base::DictionaryValue::Iterator i(*data_to_remove);
        !i.IsAtEnd();
        i.Advance()) {
     bool selected = false;
diff --git a/chrome/browser/extensions/api/browsing_data/browsing_data_api.h b/chrome/browser/extensions/api/browsing_data/browsing_data_api.h
index cefc547..f0a4f79 100644
--- a/chrome/browser/extensions/api/browsing_data/browsing_data_api.h
+++ b/chrome/browser/extensions/api/browsing_data/browsing_data_api.h
@@ -67,8 +67,8 @@
   // indicating whether the data type is both selected and permitted to be
   // removed; and a value in the |permitted_dict| with the |data_type| as a
   // key, indicating only whether the data type is permitted to be removed.
-  void SetDetails(DictionaryValue* selected_dict,
-                  DictionaryValue* permitted_dict,
+  void SetDetails(base::DictionaryValue* selected_dict,
+                  base::DictionaryValue* permitted_dict,
                   const char* data_type,
                   bool is_selected);
 };
diff --git a/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc b/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc
index bfc91de..376a3f1 100644
--- a/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc
+++ b/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc
@@ -77,7 +77,8 @@
             details).ptr()));
   }
 
-  int GetAsMask(const DictionaryValue* dict, std::string path, int mask_value) {
+  int GetAsMask(const base::DictionaryValue* dict, std::string path,
+                int mask_value) {
     bool result;
     EXPECT_TRUE(dict->GetBoolean(path, &result)) << "for " << path;
     return result ? mask_value : 0;
@@ -347,7 +348,8 @@
       UNPROTECTED_WEB | PROTECTED_WEB | EXTENSION);
 }
 
-IN_PROC_BROWSER_TEST_F(ExtensionBrowsingDataTest, BrowsingDataRemovalMask) {
+IN_PROC_BROWSER_TEST_F(ExtensionBrowsingDataTest,
+                       FLAKY_BrowsingDataRemovalMask) {
   RunRemoveBrowsingDataWithKeyAndCompareRemovalMask(
       "appcache", BrowsingDataRemover::REMOVE_APPCACHE);
   RunRemoveBrowsingDataWithKeyAndCompareRemovalMask(
diff --git a/chrome/browser/extensions/api/commands/command_service.cc b/chrome/browser/extensions/api/commands/command_service.cc
index a14a38b..d5d75f3 100644
--- a/chrome/browser/extensions/api/commands/command_service.cc
+++ b/chrome/browser/extensions/api/commands/command_service.cc
@@ -43,7 +43,7 @@
 void SetInitialBindingsHaveBeenAssigned(
     ExtensionPrefs* prefs, const std::string& extension_id) {
   prefs->UpdateExtensionPref(extension_id, kInitialBindingsHaveBeenAssigned,
-                             Value::CreateBooleanValue(true));
+                             base::Value::CreateBooleanValue(true));
 }
 
 bool InitialBindingsHaveBeenAssigned(
@@ -165,14 +165,14 @@
 
   DictionaryPrefUpdate updater(profile_->GetPrefs(),
                                prefs::kExtensionCommands);
-  DictionaryValue* bindings = updater.Get();
+  base::DictionaryValue* bindings = updater.Get();
 
   std::string key = GetPlatformKeybindingKeyForAccelerator(accelerator);
 
   if (!allow_overrides && bindings->HasKey(key))
     return false;  // Already taken.
 
-  DictionaryValue* keybinding = new DictionaryValue();
+  base::DictionaryValue* keybinding = new base::DictionaryValue();
   keybinding->SetString(kExtension, extension_id);
   keybinding->SetString(kCommandName, command_name);
 
@@ -222,10 +222,11 @@
 
 ui::Accelerator CommandService::FindShortcutForCommand(
     const std::string& extension_id, const std::string& command) {
-  const DictionaryValue* bindings =
+  const base::DictionaryValue* bindings =
       profile_->GetPrefs()->GetDictionary(prefs::kExtensionCommands);
-  for (DictionaryValue::Iterator it(*bindings); !it.IsAtEnd(); it.Advance()) {
-    const DictionaryValue* item = NULL;
+  for (base::DictionaryValue::Iterator it(*bindings); !it.IsAtEnd();
+       it.Advance()) {
+    const base::DictionaryValue* item = NULL;
     it.value().GetAsDictionary(&item);
 
     std::string extension;
@@ -312,12 +313,13 @@
                                            const std::string& command_name) {
   DictionaryPrefUpdate updater(profile_->GetPrefs(),
                                prefs::kExtensionCommands);
-  DictionaryValue* bindings = updater.Get();
+  base::DictionaryValue* bindings = updater.Get();
 
   typedef std::vector<std::string> KeysToRemove;
   KeysToRemove keys_to_remove;
-  for (DictionaryValue::Iterator it(*bindings); !it.IsAtEnd(); it.Advance()) {
-    const DictionaryValue* item = NULL;
+  for (base::DictionaryValue::Iterator it(*bindings); !it.IsAtEnd();
+       it.Advance()) {
+    const base::DictionaryValue* item = NULL;
     it.value().GetAsDictionary(&item);
 
     std::string extension;
diff --git a/chrome/browser/extensions/api/commands/command_service_new.cc b/chrome/browser/extensions/api/commands/command_service_new.cc
index 98cbe6d..4143d6a 100644
--- a/chrome/browser/extensions/api/commands/command_service_new.cc
+++ b/chrome/browser/extensions/api/commands/command_service_new.cc
@@ -141,14 +141,14 @@
 
   DictionaryPrefUpdate updater(profile_->GetPrefs(),
                                prefs::kExtensionCommands);
-  DictionaryValue* bindings = updater.Get();
+  base::DictionaryValue* bindings = updater.Get();
 
   std::string key = GetPlatformKeybindingKeyForAccelerator(accelerator);
 
   if (!allow_overrides && bindings->HasKey(key))
     return false;  // Already taken.
 
-  DictionaryValue* keybinding = new DictionaryValue();
+  base::DictionaryValue* keybinding = new base::DictionaryValue();
   keybinding->SetString(kExtension, extension_id);
   keybinding->SetString(kCommandName, command_name);
 
@@ -198,10 +198,11 @@
 
 ui::Accelerator CommandService::FindShortcutForCommand(
     const std::string& extension_id, const std::string& command) {
-  const DictionaryValue* bindings =
+  const base::DictionaryValue* bindings =
       profile_->GetPrefs()->GetDictionary(prefs::kExtensionCommands);
-  for (DictionaryValue::Iterator it(*bindings); !it.IsAtEnd(); it.Advance()) {
-    const DictionaryValue* item = NULL;
+  for (base::DictionaryValue::Iterator it(*bindings); !it.IsAtEnd();
+       it.Advance()) {
+    const base::DictionaryValue* item = NULL;
     it.value().GetAsDictionary(&item);
 
     std::string extension;
@@ -269,12 +270,13 @@
                                            const std::string& command_name) {
   DictionaryPrefUpdate updater(profile_->GetPrefs(),
                                prefs::kExtensionCommands);
-  DictionaryValue* bindings = updater.Get();
+  base::DictionaryValue* bindings = updater.Get();
 
   typedef std::vector<std::string> KeysToRemove;
   KeysToRemove keys_to_remove;
-  for (DictionaryValue::Iterator it(*bindings); !it.IsAtEnd(); it.Advance()) {
-    const DictionaryValue* item = NULL;
+  for (base::DictionaryValue::Iterator it(*bindings); !it.IsAtEnd();
+       it.Advance()) {
+    const base::DictionaryValue* item = NULL;
     it.value().GetAsDictionary(&item);
 
     std::string extension;
diff --git a/chrome/browser/extensions/api/commands/commands.cc b/chrome/browser/extensions/api/commands/commands.cc
index ebe8bad..1bfe054 100644
--- a/chrome/browser/extensions/api/commands/commands.cc
+++ b/chrome/browser/extensions/api/commands/commands.cc
@@ -10,7 +10,7 @@
 
 base::DictionaryValue* CreateCommandValue(
     const extensions::Command& command, bool active) {
-  DictionaryValue* result = new DictionaryValue();
+  base::DictionaryValue* result = new base::DictionaryValue();
   result->SetString("name", command.command_name());
   result->SetString("description", command.description());
   result->SetString("shortcut",
@@ -22,7 +22,7 @@
 }  // namespace
 
 bool GetAllCommandsFunction::RunImpl() {
-  ListValue* command_list = new ListValue();
+  base::ListValue* command_list = new base::ListValue();
 
   extensions::CommandService* command_service =
       extensions::CommandService::Get(profile_);
diff --git a/chrome/browser/extensions/api/content_settings/content_settings_api.cc b/chrome/browser/extensions/api/content_settings/content_settings_api.cc
index 1f07c04..35223b8 100644
--- a/chrome/browser/extensions/api/content_settings/content_settings_api.cc
+++ b/chrome/browser/extensions/api/content_settings/content_settings_api.cc
@@ -42,7 +42,8 @@
 
 const std::vector<webkit::WebPluginInfo>* g_testing_plugins_;
 
-bool RemoveContentType(ListValue* args, ContentSettingsType* content_type) {
+bool RemoveContentType(base::ListValue* args,
+                       ContentSettingsType* content_type) {
   std::string content_type_str;
   if (!args->GetString(0, &content_type_str))
     return false;
@@ -160,7 +161,7 @@
                                      resource_identifier);
   }
 
-  DictionaryValue* result = new DictionaryValue();
+  base::DictionaryValue* result = new base::DictionaryValue();
   result->SetString(keys::kContentSettingKey,
                     helpers::ContentSettingToString(setting));
 
@@ -274,7 +275,7 @@
     const std::vector<webkit::WebPluginInfo>& plugins) {
   PluginFinder* finder = PluginFinder::GetInstance();
   std::set<std::string> group_identifiers;
-  ListValue* list = new ListValue();
+  base::ListValue* list = new base::ListValue();
   for (std::vector<webkit::WebPluginInfo>::const_iterator it = plugins.begin();
        it != plugins.end(); ++it) {
     scoped_ptr<PluginMetadata> plugin_metadata(finder->GetPluginMetadata(*it));
@@ -283,7 +284,7 @@
       continue;
 
     group_identifiers.insert(group_identifier);
-    DictionaryValue* dict = new DictionaryValue();
+    base::DictionaryValue* dict = new base::DictionaryValue();
     dict->SetString(keys::kIdKey, group_identifier);
     dict->SetString(keys::kDescriptionKey, plugin_metadata->name());
     list->Append(dict);
diff --git a/chrome/browser/extensions/api/content_settings/content_settings_store.h b/chrome/browser/extensions/api/content_settings/content_settings_store.h
index 07238c7..f3e9912 100644
--- a/chrome/browser/extensions/api/content_settings/content_settings_store.h
+++ b/chrome/browser/extensions/api/content_settings/content_settings_store.h
@@ -12,7 +12,7 @@
 #include "base/observer_list.h"
 #include "base/synchronization/lock.h"
 #include "base/threading/thread_checker.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/tuple.h"
 #include "chrome/browser/content_settings/content_settings_provider.h"
 #include "chrome/common/content_settings.h"
diff --git a/chrome/browser/extensions/api/context_menus/context_menus_api.cc b/chrome/browser/extensions/api/context_menus/context_menus_api.cc
index df0e743..de30534 100644
--- a/chrome/browser/extensions/api/context_menus/context_menus_api.cc
+++ b/chrome/browser/extensions/api/context_menus/context_menus_api.cc
@@ -166,7 +166,7 @@
     }
 
     // The Generated Id is added by context_menus_custom_bindings.js.
-    DictionaryValue* properties = NULL;
+    base::DictionaryValue* properties = NULL;
     EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &properties));
     EXTENSION_FUNCTION_VALIDATE(properties->GetInteger(kGeneratedIdKey,
                                                        &id.uid));
diff --git a/chrome/browser/extensions/api/cookies/cookies_api.cc b/chrome/browser/extensions/api/cookies/cookies_api.cc
index 72fc053..c2cd6de 100644
--- a/chrome/browser/extensions/api/cookies/cookies_api.cc
+++ b/chrome/browser/extensions/api/cookies/cookies_api.cc
@@ -13,7 +13,7 @@
 #include "base/lazy_instance.h"
 #include "base/memory/linked_ptr.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/extensions/api/cookies/cookies_api_constants.h"
 #include "chrome/browser/extensions/api/cookies/cookies_helpers.h"
@@ -82,8 +82,8 @@
 void CookiesEventRouter::CookieChanged(
     Profile* profile,
     ChromeCookieDetails* details) {
-  scoped_ptr<ListValue> args(new ListValue());
-  DictionaryValue* dict = new DictionaryValue();
+  scoped_ptr<base::ListValue> args(new base::ListValue());
+  base::DictionaryValue* dict = new base::DictionaryValue();
   dict->SetBoolean(keys::kRemovedKey, details->removed);
 
   scoped_ptr<Cookie> cookie(
@@ -129,7 +129,7 @@
 void CookiesEventRouter::DispatchEvent(
     Profile* profile,
     const std::string& event_name,
-    scoped_ptr<ListValue> event_args,
+    scoped_ptr<base::ListValue> event_args,
     GURL& cookie_domain) {
   EventRouter* router = profile ?
       extensions::ExtensionSystem::Get(profile)->event_router() : NULL;
@@ -511,13 +511,13 @@
 bool CookiesGetAllCookieStoresFunction::RunImpl() {
   Profile* original_profile = profile();
   DCHECK(original_profile);
-  scoped_ptr<ListValue> original_tab_ids(new ListValue());
+  scoped_ptr<base::ListValue> original_tab_ids(new base::ListValue());
   Profile* incognito_profile = NULL;
-  scoped_ptr<ListValue> incognito_tab_ids;
+  scoped_ptr<base::ListValue> incognito_tab_ids;
   if (include_incognito() && profile()->HasOffTheRecordProfile()) {
     incognito_profile = profile()->GetOffTheRecordProfile();
     if (incognito_profile)
-      incognito_tab_ids.reset(new ListValue());
+      incognito_tab_ids.reset(new base::ListValue());
   }
   DCHECK(original_profile != incognito_profile);
 
diff --git a/chrome/browser/extensions/api/cookies/cookies_helpers.cc b/chrome/browser/extensions/api/cookies/cookies_helpers.cc
index fe1f01f..c151c92 100644
--- a/chrome/browser/extensions/api/cookies/cookies_helpers.cc
+++ b/chrome/browser/extensions/api/cookies/cookies_helpers.cc
@@ -90,10 +90,10 @@
 }
 
 scoped_ptr<CookieStore> CreateCookieStore(Profile* profile,
-                                          ListValue* tab_ids) {
+                                          base::ListValue* tab_ids) {
   DCHECK(profile);
   DCHECK(tab_ids);
-  DictionaryValue dict;
+  base::DictionaryValue dict;
   dict.SetString(keys::kIdKey, GetStoreIdFromProfile(profile));
   dict.Set(keys::kTabIdsKey, tab_ids);
 
@@ -146,7 +146,7 @@
   }
 }
 
-void AppendToTabIdList(Browser* browser, ListValue* tab_ids) {
+void AppendToTabIdList(Browser* browser, base::ListValue* tab_ids) {
   DCHECK(browser);
   DCHECK(tab_ids);
   TabStripModel* tab_strip = browser->tab_strip_model();
diff --git a/chrome/browser/extensions/api/cookies/cookies_unittest.cc b/chrome/browser/extensions/api/cookies/cookies_unittest.cc
index 172ed31..f5f1523 100644
--- a/chrome/browser/extensions/api/cookies/cookies_unittest.cc
+++ b/chrome/browser/extensions/api/cookies/cookies_unittest.cc
@@ -143,7 +143,7 @@
   EXPECT_EQ(10000, *cookie2->expiration_date);
 
   TestingProfile profile;
-  ListValue* tab_ids_list = new ListValue();
+  base::ListValue* tab_ids_list = new base::ListValue();
   std::vector<int> tab_ids;
   scoped_ptr<CookieStore> cookie_store(
       cookies_helpers::CreateCookieStore(&profile, tab_ids_list));
@@ -168,7 +168,7 @@
 }
 
 TEST_F(ExtensionCookiesTest, EmptyDictionary) {
-  DictionaryValue dict;
+  base::DictionaryValue dict;
   GetAll::Params::Details details;
   bool rv = GetAll::Params::Details::Populate(dict, &details);
   ASSERT_TRUE(rv);
@@ -190,8 +190,8 @@
 
   for (size_t i = 0; i < arraysize(tests); ++i) {
     // Build up the Params struct.
-    ListValue args;
-    DictionaryValue* dict = new DictionaryValue();
+    base::ListValue args;
+    base::DictionaryValue* dict = new base::DictionaryValue();
     dict->SetString(keys::kDomainKey, std::string(tests[i].filter));
     args.Set(0, dict);
     scoped_ptr<GetAll::Params> params(GetAll::Params::Create(args));
diff --git a/chrome/browser/extensions/api/debugger/debugger_api.cc b/chrome/browser/extensions/api/debugger/debugger_api.cc
index 2ae2b7f..6ad5f83 100644
--- a/chrome/browser/extensions/api/debugger/debugger_api.cc
+++ b/chrome/browser/extensions/api/debugger/debugger_api.cc
@@ -33,6 +33,7 @@
 #include "chrome/common/extensions/extension.h"
 #include "content/public/browser/devtools_agent_host.h"
 #include "content/public/browser/devtools_client_host.h"
+#include "content/public/browser/devtools_http_handler.h"
 #include "content/public/browser/devtools_manager.h"
 #include "content/public/browser/favicon_status.h"
 #include "content/public/browser/navigation_entry.h"
@@ -48,10 +49,10 @@
 #include "extensions/common/error_utils.h"
 #include "grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
-#include "webkit/glue/webkit_glue.h"
 
 using content::DevToolsAgentHost;
 using content::DevToolsClientHost;
+using content::DevToolsHttpHandler;
 using content::DevToolsManager;
 using content::RenderProcessHost;
 using content::RenderViewHost;
@@ -454,7 +455,7 @@
     DebuggerSendCommandFunction* function,
     const std::string& method,
     SendCommand::Params::CommandParams* command_params) {
-  DictionaryValue protocol_request;
+  base::DictionaryValue protocol_request;
   int request_id = ++last_request_id_;
   pending_requests_[request_id] = function;
   protocol_request.SetInteger("id", request_id);
@@ -517,7 +518,8 @@
   scoped_ptr<Value> result(base::JSONReader::Read(message));
   if (!result->IsType(Value::TYPE_DICTIONARY))
     return;
-  DictionaryValue* dictionary = static_cast<DictionaryValue*>(result.get());
+  base::DictionaryValue* dictionary =
+      static_cast<base::DictionaryValue*>(result.get());
 
   int id;
   if (!dictionary->GetInteger("id", &id)) {
@@ -526,7 +528,7 @@
       return;
 
     OnEvent::Params params;
-    DictionaryValue* params_value;
+    base::DictionaryValue* params_value;
     if (dictionary->GetDictionary("params", &params_value))
       params.additional_properties.Swap(params_value);
 
@@ -635,8 +637,8 @@
   if (!InitAgentHost())
     return false;
 
-  if (!webkit_glue::IsInspectorProtocolVersionSupported(
-      params->required_version)) {
+  if (!DevToolsHttpHandler::IsSupportedProtocolVersion(
+          params->required_version)) {
     error_ = ErrorUtils::FormatErrorMessage(
         keys::kProtocolVersionNotSupportedError,
         params->required_version);
@@ -715,7 +717,7 @@
 }
 
 void DebuggerSendCommandFunction::SendResponseBody(
-    DictionaryValue* response) {
+    base::DictionaryValue* response) {
   Value* error_body;
   if (response->Get("error", &error_body)) {
     base::JSONWriter::Write(error_body, &error_);
@@ -723,7 +725,7 @@
     return;
   }
 
-  DictionaryValue* result_body;
+  base::DictionaryValue* result_body;
   SendCommand::Results::Result result;
   if (response->GetDictionary("result", &result_body))
     result.additional_properties.Swap(result_body);
diff --git a/chrome/browser/extensions/api/declarative/declarative_rule.h b/chrome/browser/extensions/api/declarative/declarative_rule.h
index 11d223a..d1dab32 100644
--- a/chrome/browser/extensions/api/declarative/declarative_rule.h
+++ b/chrome/browser/extensions/api/declarative/declarative_rule.h
@@ -19,7 +19,7 @@
 #include "base/memory/linked_ptr.h"
 #include "base/memory/scoped_vector.h"
 #include "base/stl_util.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/common/extensions/api/events.h"
 #include "extensions/common/matcher/url_matcher.h"
 
diff --git a/chrome/browser/extensions/api/declarative/rules_registry_with_cache.cc b/chrome/browser/extensions/api/declarative/rules_registry_with_cache.cc
index 28096a1..059e7ba 100644
--- a/chrome/browser/extensions/api/declarative/rules_registry_with_cache.cc
+++ b/chrome/browser/extensions/api/declarative/rules_registry_with_cache.cc
@@ -9,7 +9,7 @@
 #include "base/message_loop.h"
 #include "base/metrics/histogram.h"
 #include "base/strings/stringprintf.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/extensions/extension_info_map.h"
 #include "chrome/browser/extensions/extension_prefs.h"
@@ -332,7 +332,7 @@
   if (!profile_)
     return;
 
-  const ListValue* rules = NULL;
+  const base::ListValue* rules = NULL;
   CHECK(value->GetAsList(&rules));
   bool rules_stored_previously = GetDeclarativeRulesStored(extension_id);
   bool store_rules = !rules->empty();
diff --git a/chrome/browser/extensions/api/declarative/rules_registry_with_cache_unittest.cc b/chrome/browser/extensions/api/declarative/rules_registry_with_cache_unittest.cc
index cf02cef..49bdf21 100644
--- a/chrome/browser/extensions/api/declarative/rules_registry_with_cache_unittest.cc
+++ b/chrome/browser/extensions/api/declarative/rules_registry_with_cache_unittest.cc
@@ -234,7 +234,7 @@
   // 2. Test writing behavior.
   int write_count = store->write_count();
 
-  scoped_ptr<base::ListValue> value(new ListValue);
+  scoped_ptr<base::ListValue> value(new base::ListValue);
   value->AppendBoolean(true);
   ui_part->WriteToStorage(extension_id, value.PassAs<base::Value>());
   EXPECT_TRUE(ui_part->GetDeclarativeRulesStored(extension_id));
@@ -242,7 +242,7 @@
   EXPECT_EQ(write_count + 1, store->write_count());
   write_count = store->write_count();
 
-  value.reset(new ListValue);
+  value.reset(new base::ListValue);
   ui_part->WriteToStorage(extension_id, value.PassAs<base::Value>());
   EXPECT_FALSE(ui_part->GetDeclarativeRulesStored(extension_id));
   message_loop_.RunUntilIdle();
@@ -250,7 +250,7 @@
   EXPECT_EQ(write_count + 1, store->write_count());
   write_count = store->write_count();
 
-  value.reset(new ListValue);
+  value.reset(new base::ListValue);
   ui_part->WriteToStorage(extension_id, value.PassAs<base::Value>());
   EXPECT_FALSE(ui_part->GetDeclarativeRulesStored(extension_id));
   message_loop_.RunUntilIdle();
diff --git a/chrome/browser/extensions/api/declarative_content/content_rules_registry.h b/chrome/browser/extensions/api/declarative_content/content_rules_registry.h
index 66c6a93..59fe6f4 100644
--- a/chrome/browser/extensions/api/declarative_content/content_rules_registry.h
+++ b/chrome/browser/extensions/api/declarative_content/content_rules_registry.h
@@ -13,7 +13,7 @@
 #include "base/memory/linked_ptr.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/extensions/api/declarative/declarative_rule.h"
 #include "chrome/browser/extensions/api/declarative/rules_registry_with_cache.h"
 #include "chrome/browser/extensions/api/declarative_content/content_action.h"
diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_action.cc b/chrome/browser/extensions/api/declarative_webrequest/webrequest_action.cc
index 1d267a8..fb38c55 100644
--- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_action.cc
+++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_action.cc
@@ -46,7 +46,7 @@
   } while (0)
 
 scoped_ptr<helpers::RequestCookie> ParseRequestCookie(
-    const DictionaryValue* dict) {
+    const base::DictionaryValue* dict) {
   scoped_ptr<helpers::RequestCookie> result(new helpers::RequestCookie);
   std::string tmp;
   if (dict->GetString(keys::kNameKey, &tmp))
@@ -56,7 +56,7 @@
   return result.Pass();
 }
 
-void ParseResponseCookieImpl(const DictionaryValue* dict,
+void ParseResponseCookieImpl(const base::DictionaryValue* dict,
                              helpers::ResponseCookie* cookie) {
   std::string string_tmp;
   int int_tmp = 0;
@@ -80,14 +80,14 @@
 }
 
 scoped_ptr<helpers::ResponseCookie> ParseResponseCookie(
-    const DictionaryValue* dict) {
+    const base::DictionaryValue* dict) {
   scoped_ptr<helpers::ResponseCookie> result(new helpers::ResponseCookie);
   ParseResponseCookieImpl(dict, result.get());
   return result.Pass();
 }
 
 scoped_ptr<helpers::FilterResponseCookie> ParseFilterResponseCookie(
-    const DictionaryValue* dict) {
+    const base::DictionaryValue* dict) {
   scoped_ptr<helpers::FilterResponseCookie> result(
       new helpers::FilterResponseCookie);
   ParseResponseCookieImpl(dict, result.get());
@@ -266,18 +266,18 @@
   // Get filter.
   if (modification->type == helpers::EDIT ||
       modification->type == helpers::REMOVE) {
-    const DictionaryValue* filter = NULL;
+    const base::DictionaryValue* filter = NULL;
     INPUT_FORMAT_VALIDATE(dict->GetDictionary(keys::kFilterKey, &filter));
     modification->filter = ParseRequestCookie(filter);
   }
 
   // Get new value.
   if (modification->type == helpers::ADD) {
-    const DictionaryValue* value = NULL;
+    const base::DictionaryValue* value = NULL;
     INPUT_FORMAT_VALIDATE(dict->GetDictionary(keys::kCookieKey, &value));
     modification->modification = ParseRequestCookie(value);
   } else if (modification->type == helpers::EDIT) {
-    const DictionaryValue* value = NULL;
+    const base::DictionaryValue* value = NULL;
     INPUT_FORMAT_VALIDATE(dict->GetDictionary(keys::kModificationKey, &value));
     modification->modification = ParseRequestCookie(value);
   }
@@ -312,18 +312,18 @@
   // Get filter.
   if (modification->type == helpers::EDIT ||
       modification->type == helpers::REMOVE) {
-    const DictionaryValue* filter = NULL;
+    const base::DictionaryValue* filter = NULL;
     INPUT_FORMAT_VALIDATE(dict->GetDictionary(keys::kFilterKey, &filter));
     modification->filter = ParseFilterResponseCookie(filter);
   }
 
   // Get new value.
   if (modification->type == helpers::ADD) {
-    const DictionaryValue* value = NULL;
+    const base::DictionaryValue* value = NULL;
     INPUT_FORMAT_VALIDATE(dict->GetDictionary(keys::kCookieKey, &value));
     modification->modification = ParseResponseCookie(value);
   } else if (modification->type == helpers::EDIT) {
-    const DictionaryValue* value = NULL;
+    const base::DictionaryValue* value = NULL;
     INPUT_FORMAT_VALIDATE(dict->GetDictionary(keys::kModificationKey, &value));
     modification->modification = ParseResponseCookie(value);
   }
diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_action_unittest.cc b/chrome/browser/extensions/api/declarative_webrequest/webrequest_action_unittest.cc
index f5fc66c..998b8eb 100644
--- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_action_unittest.cc
+++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_action_unittest.cc
@@ -11,7 +11,7 @@
 #include "base/message_loop.h"
 #include "base/path_service.h"
 #include "base/test/values_test_util.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/extensions/api/declarative_webrequest/request_stage.h"
 #include "chrome/browser/extensions/api/declarative_webrequest/webrequest_condition.h"
diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry.h b/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry.h
index a1c4353..f628425 100644
--- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry.h
+++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry.h
@@ -12,10 +12,10 @@
 #include <vector>
 
 #include "base/gtest_prod_util.h"
-#include "base/time.h"
 #include "base/memory/linked_ptr.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/time/time.h"
 #include "chrome/browser/extensions/api/declarative/declarative_rule.h"
 #include "chrome/browser/extensions/api/declarative/rules_registry_with_cache.h"
 #include "chrome/browser/extensions/api/declarative_webrequest/request_stage.h"
diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc b/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc
index d80baf7..5452e18 100644
--- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc
+++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc
@@ -93,28 +93,28 @@
   // Returns a rule that roughly matches http://*.example.com and
   // https://www.example.com and cancels it
   linked_ptr<RulesRegistry::Rule> CreateRule1() {
-    ListValue* scheme_http = new ListValue();
+    base::ListValue* scheme_http = new base::ListValue();
     scheme_http->Append(Value::CreateStringValue("http"));
-    DictionaryValue* http_condition_dict = new DictionaryValue();
+    base::DictionaryValue* http_condition_dict = new base::DictionaryValue();
     http_condition_dict->Set(keys2::kSchemesKey, scheme_http);
     http_condition_dict->SetString(keys2::kHostSuffixKey, "example.com");
-    DictionaryValue http_condition_url_filter;
+    base::DictionaryValue http_condition_url_filter;
     http_condition_url_filter.Set(keys::kUrlKey, http_condition_dict);
     http_condition_url_filter.SetString(keys::kInstanceTypeKey,
                                         keys::kRequestMatcherType);
 
-    ListValue* scheme_https = new ListValue();
+    base::ListValue* scheme_https = new base::ListValue();
     scheme_http->Append(Value::CreateStringValue("https"));
-    DictionaryValue* https_condition_dict = new DictionaryValue();
+    base::DictionaryValue* https_condition_dict = new base::DictionaryValue();
     https_condition_dict->Set(keys2::kSchemesKey, scheme_https);
     https_condition_dict->SetString(keys2::kHostSuffixKey, "example.com");
     https_condition_dict->SetString(keys2::kHostPrefixKey, "www");
-    DictionaryValue https_condition_url_filter;
+    base::DictionaryValue https_condition_url_filter;
     https_condition_url_filter.Set(keys::kUrlKey, https_condition_dict);
     https_condition_url_filter.SetString(keys::kInstanceTypeKey,
                                          keys::kRequestMatcherType);
 
-    DictionaryValue action_dict;
+    base::DictionaryValue action_dict;
     action_dict.SetString(keys::kInstanceTypeKey, keys::kCancelRequestType);
 
     linked_ptr<RulesRegistry::Rule> rule(new RulesRegistry::Rule);
@@ -130,10 +130,10 @@
 
   // Returns a rule that matches anything and cancels it.
   linked_ptr<RulesRegistry::Rule> CreateRule2() {
-    DictionaryValue condition_dict;
+    base::DictionaryValue condition_dict;
     condition_dict.SetString(keys::kInstanceTypeKey, keys::kRequestMatcherType);
 
-    DictionaryValue action_dict;
+    base::DictionaryValue action_dict;
     action_dict.SetString(keys::kInstanceTypeKey, keys::kCancelRequestType);
 
     linked_ptr<RulesRegistry::Rule> rule(new RulesRegistry::Rule);
@@ -147,10 +147,10 @@
 
   linked_ptr<RulesRegistry::Rule> CreateRedirectRule(
       const std::string& destination) {
-    DictionaryValue condition_dict;
+    base::DictionaryValue condition_dict;
     condition_dict.SetString(keys::kInstanceTypeKey, keys::kRequestMatcherType);
 
-    DictionaryValue action_dict;
+    base::DictionaryValue action_dict;
     action_dict.SetString(keys::kInstanceTypeKey, keys::kRedirectRequestType);
     action_dict.SetString(keys::kRedirectUrlKey, destination);
 
@@ -166,13 +166,13 @@
   // Create a rule to ignore all other rules for a destination that
   // contains index.html.
   linked_ptr<RulesRegistry::Rule> CreateIgnoreRule() {
-    DictionaryValue condition_dict;
-    DictionaryValue* http_condition_dict = new DictionaryValue();
+    base::DictionaryValue condition_dict;
+    base::DictionaryValue* http_condition_dict = new base::DictionaryValue();
     http_condition_dict->SetString(keys2::kPathContainsKey, "index.html");
     condition_dict.SetString(keys::kInstanceTypeKey, keys::kRequestMatcherType);
     condition_dict.Set(keys::kUrlKey, http_condition_dict);
 
-    DictionaryValue action_dict;
+    base::DictionaryValue action_dict;
     action_dict.SetString(keys::kInstanceTypeKey, keys::kIgnoreRulesType);
     action_dict.SetInteger(keys::kLowerPriorityThanKey, 150);
 
@@ -204,7 +204,7 @@
   linked_ptr<RulesRegistry::Rule> CreateCancellingRule(
       const char* rule_id,
       const std::vector<const std::string*>& attributes) {
-    DictionaryValue action_dict;
+    base::DictionaryValue action_dict;
     action_dict.SetString(keys::kInstanceTypeKey, keys::kCancelRequestType);
 
     linked_ptr<RulesRegistry::Rule> rule(new RulesRegistry::Rule);
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api.cc b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
index 278d1d8..54d4db5 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_api.cc
+++ b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
@@ -7,6 +7,7 @@
 #include "apps/app_load_service.h"
 #include "apps/app_restore_service.h"
 #include "apps/saved_files_service.h"
+#include "apps/shell_window.h"
 #include "base/base64.h"
 #include "base/command_line.h"
 #include "base/file_util.h"
@@ -19,6 +20,7 @@
 #include "chrome/browser/extensions/api/developer_private/developer_private_api_factory.h"
 #include "chrome/browser/extensions/api/developer_private/entry_picker.h"
 #include "chrome/browser/extensions/api/extension_action/extension_action_api.h"
+#include "chrome/browser/extensions/event_names.h"
 #include "chrome/browser/extensions/extension_disabled_ui.h"
 #include "chrome/browser/extensions/extension_error_reporter.h"
 #include "chrome/browser/extensions/extension_service.h"
@@ -31,7 +33,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sync_file_system/drive_file_sync_service.h"
 #include "chrome/browser/ui/chrome_select_file_policy.h"
-#include "chrome/browser/ui/extensions/shell_window.h"
 #include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "chrome/common/chrome_switches.h"
@@ -47,6 +48,7 @@
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
+#include "content/public/browser/site_instance.h"
 #include "content/public/browser/storage_partition.h"
 #include "content/public/browser/web_contents.h"
 #include "extensions/browser/view_type_utils.h"
@@ -63,10 +65,13 @@
 #include "webkit/browser/fileapi/syncable/syncable_file_system_util.h"
 #include "webkit/common/blob/shareable_file_reference.h"
 
+using apps::ShellWindow;
 using content::RenderViewHost;
 
 namespace extensions {
 
+namespace events = event_names;
+
 namespace {
 
 const base::FilePath::CharType kUnpackedAppsFolder[]
@@ -105,6 +110,13 @@
   return NULL;
 }
 
+std::string GetExtensionID(const RenderViewHost* render_view_host) {
+  if (!render_view_host->GetSiteInstance())
+    return std::string();
+
+  return render_view_host->GetSiteInstance()->GetSiteURL().host();
+}
+
 }  // namespace
 
 namespace AllowFileAccess = api::developer_private::AllowFileAccess;
@@ -121,23 +133,87 @@
   return DeveloperPrivateAPIFactory::GetForProfile(profile);
 }
 
-DeveloperPrivateAPI::DeveloperPrivateAPI(Profile* profile) {
+DeveloperPrivateAPI::DeveloperPrivateAPI(Profile* profile) : profile_(profile) {
   RegisterNotifications();
 }
 
+DeveloperPrivateEventRouter::DeveloperPrivateEventRouter(Profile* profile)
+: profile_(profile) {
+  int types[] = {
+    chrome::NOTIFICATION_EXTENSION_INSTALLED,
+    chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
+    chrome::NOTIFICATION_EXTENSION_LOADED,
+    chrome::NOTIFICATION_EXTENSION_UNLOADED,
+    chrome::NOTIFICATION_EXTENSION_VIEW_REGISTERED,
+    chrome::NOTIFICATION_EXTENSION_VIEW_UNREGISTERED
+  };
 
-void DeveloperPrivateAPI::Observe(
+  CHECK(registrar_.IsEmpty());
+  for (size_t i = 0; i < arraysize(types); ++i) {
+    registrar_.Add(this,
+                   types[i],
+                   content::Source<Profile>(profile_));
+  }
+}
+
+
+DeveloperPrivateEventRouter::~DeveloperPrivateEventRouter() {}
+
+void DeveloperPrivateEventRouter::Observe(
     int type,
     const content::NotificationSource& source,
     const content::NotificationDetails& details) {
+  const char* event_name = NULL;
+  Profile* profile = content::Source<Profile>(source).ptr();
+  CHECK(profile);
+  CHECK(profile_->IsSameProfile(profile));
+  developer::EventData event_data;
+  std::string extension_id;
+  const Extension* extension = NULL;
+
   switch (type) {
-    // TODO(grv): Listen to other notifications and expose them
-    // as events in API.
-    case chrome::NOTIFICATION_BACKGROUND_CONTENTS_DELETED:
+    case chrome::NOTIFICATION_EXTENSION_INSTALLED:
+      event_data.event_type = developer::EVENT_TYPE_INSTALLED;
+      extension =
+          content::Details<const InstalledExtensionInfo>(details)->extension;
+      break;
+    case chrome::NOTIFICATION_EXTENSION_UNINSTALLED:
+      event_data.event_type = developer::EVENT_TYPE_UNINSTALLED;
+      extension = content::Details<const Extension>(details).ptr();
+      break;
+    case chrome::NOTIFICATION_EXTENSION_LOADED:
+      event_data.event_type = developer::EVENT_TYPE_LOADED;
+      extension = content::Details<const Extension>(details).ptr();
+      break;
+    case chrome::NOTIFICATION_EXTENSION_UNLOADED:
+      event_data.event_type = developer::EVENT_TYPE_UNLOADED;
+      extension =
+          content::Details<const UnloadedExtensionInfo>(details)->extension;
+      break;
+    case chrome::NOTIFICATION_EXTENSION_VIEW_UNREGISTERED:
+      event_data.event_type = developer::EVENT_TYPE_VIEW_UNREGISTERED;
+      event_data.item_id = GetExtensionID(
+          content::Details<const RenderViewHost>(details).ptr());
+      break;
+    case chrome::NOTIFICATION_EXTENSION_VIEW_REGISTERED:
+      event_data.event_type = developer::EVENT_TYPE_VIEW_REGISTERED;
+      event_data.item_id = GetExtensionID(
+          content::Details<const RenderViewHost>(details).ptr());
       break;
     default:
       NOTREACHED();
+      return;
   }
+
+  if (extension)
+    event_data.item_id = extension->id();
+
+  scoped_ptr<ListValue> args(new ListValue());
+  args->Append(event_data.ToValue().release());
+
+  event_name = events::kDeveloperPrivateOnItemStateChanged;
+  scoped_ptr<Event> event(new Event(event_name, args.Pass()));
+  ExtensionSystem::Get(profile)->event_router()->BroadcastEvent(event.Pass());
 }
 
 void DeveloperPrivateAPI::SetLastUnpackedDirectory(const base::FilePath& path) {
@@ -145,15 +221,28 @@
 }
 
 void DeveloperPrivateAPI::RegisterNotifications() {
-  registrar_.Add(this,
-                 chrome::NOTIFICATION_BACKGROUND_CONTENTS_DELETED,
-                 content::NotificationService::AllBrowserContextsAndSources());
+  ExtensionSystem::Get(profile_)->event_router()->RegisterObserver(
+      this, events::kDeveloperPrivateOnItemStateChanged);
 }
 
 DeveloperPrivateAPI::~DeveloperPrivateAPI() {}
 
 void DeveloperPrivateAPI::Shutdown() {}
 
+void DeveloperPrivateAPI::OnListenerAdded(
+    const EventListenerInfo& details) {
+  if (!developer_private_event_router_)
+    developer_private_event_router_.reset(
+        new DeveloperPrivateEventRouter(profile_));
+}
+
+void DeveloperPrivateAPI::OnListenerRemoved(
+    const EventListenerInfo& details) {
+  if (!ExtensionSystem::Get(profile_)->event_router()->HasEventListener(
+          event_names::kDeveloperPrivateOnItemStateChanged))
+    developer_private_event_router_.reset(NULL);
+}
+
 namespace api {
 
 bool DeveloperPrivateAutoUpdateFunction::RunImpl() {
@@ -536,6 +625,11 @@
 
   apps::AppLoadService* service = apps::AppLoadService::Get(profile());
   EXTENSION_FUNCTION_VALIDATE(!params->item_id.empty());
+  ExtensionService* extension_service = profile()->GetExtensionService();
+  // Don't restart disabled applications.
+  if (!extension_service->IsExtensionEnabled(params->item_id))
+    return false;
+
   service->RestartApplication(params->item_id);
   return true;
 }
@@ -826,7 +920,7 @@
 
 void DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
     ClearPrexistingDirectoryContent(const base::FilePath& project_path) {
-  if (!file_util::Delete(project_path, true/*recursive*/)) {
+  if (!base::Delete(project_path, true/*recursive*/)) {
     SetError("Error in copying files from sync filesystem.");
     content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
         base::Bind(&DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
@@ -836,28 +930,33 @@
     return;
   }
 
+  pendingCopyOperationsCount_ = 1;
+
   content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
       base::Bind(&DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
                  ReadSyncFileSystemDirectory,
-                 this, project_path));
+                 this, project_path, project_path.BaseName()));
 }
 
 void DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
-    ReadSyncFileSystemDirectory(const base::FilePath& project_path) {
+    ReadSyncFileSystemDirectory(const base::FilePath& project_path,
+                                const base::FilePath& destination_path) {
   std::string origin_url(
       Extension::GetBaseURLFromExtensionId(extension_id()).spec());
   fileapi::FileSystemURL url(sync_file_system::CreateSyncableFileSystemURL(
       GURL(origin_url),
-      project_path.BaseName()));
+      destination_path));
 
   context_->operation_runner()->ReadDirectory(
       url, base::Bind(&DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
-                      ReadSyncFileSystemDirectoryCb, this, project_path));
+                      ReadSyncFileSystemDirectoryCb,
+                      this, project_path, destination_path));
 }
 
 void DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
     ReadSyncFileSystemDirectoryCb(
     const base::FilePath& project_path,
+    const base::FilePath& destination_path,
     base::PlatformFileError status,
     const fileapi::FileSystemOperation::FileEntryList& file_list,
     bool has_more) {
@@ -867,24 +966,27 @@
     return;
   }
 
-  // Create an empty project folder if there are no files.
-  if (!file_list.size()) {
-    content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
-      base::Bind(&DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
-                     CreateFolderAndSendResponse,
-                 this,
-                 project_path));
-    return;
-  }
-
-  pendingCallbacksCount_ = file_list.size();
+  // We add 1 to the pending copy operations for both files and directories. We
+  // release the directory copy operation once all the files under the directory
+  // are added for copying. We do that to ensure that pendingCopyOperationsCount
+  // does not become zero before all copy operations are finished.
+  // In case the directory happens to be executing the last copy operation it
+  // will call SendResponse to send the response to the API. The pending copy
+  // operations of files are released by the CopyFile function.
+  pendingCopyOperationsCount_ += file_list.size();
 
   for (size_t i = 0; i < file_list.size(); ++i) {
+    if (file_list[i].is_directory) {
+      ReadSyncFileSystemDirectory(project_path.Append(file_list[i].name),
+                                  destination_path.Append(file_list[i].name));
+      continue;
+    }
+
     std::string origin_url(
         Extension::GetBaseURLFromExtensionId(extension_id()).spec());
     fileapi::FileSystemURL url(sync_file_system::CreateSyncableFileSystemURL(
         GURL(origin_url),
-        project_path.BaseName().Append(file_list[i].name)));
+        destination_path.Append(file_list[i].name)));
     base::FilePath target_path = project_path;
     target_path = target_path.Append(file_list[i].name);
 
@@ -895,19 +997,19 @@
                 SnapshotFileCallback,
             this,
             target_path));
-  }
-}
 
-void DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
-    CreateFolderAndSendResponse(const base::FilePath& project_path) {
-  if (!(success_ = file_util::CreateDirectory(project_path))) {
-    SetError("Error in copying files from sync filesystem.");
   }
-  content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
-      base::Bind(&DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
-                     SendResponse,
-                 this,
-                 success_));
+
+  // Directory copy operation released here.
+  pendingCopyOperationsCount_--;
+
+  if (!pendingCopyOperationsCount_) {
+    content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
+        base::Bind(&DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
+                       SendResponse,
+                   this,
+                   success_));
+  }
 }
 
 void DeveloperPrivateExportSyncfsFolderToLocalfsFunction::SnapshotFileCallback(
@@ -940,10 +1042,10 @@
   if (success_)
     file_util::CopyFile(src_path, target_path);
 
-  CHECK(pendingCallbacksCount_ > 0);
-  pendingCallbacksCount_--;
+  CHECK(pendingCopyOperationsCount_ > 0);
+  pendingCopyOperationsCount_--;
 
-  if (!pendingCallbacksCount_) {
+  if (!pendingCopyOperationsCount_) {
     content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
         base::Bind(&DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
                        SendResponse,
@@ -954,7 +1056,7 @@
 
 DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
     DeveloperPrivateExportSyncfsFolderToLocalfsFunction()
-    : pendingCallbacksCount_(0), success_(true) {}
+    : pendingCopyOperationsCount_(0), success_(true) {}
 
 DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
     ~DeveloperPrivateExportSyncfsFolderToLocalfsFunction() {}
@@ -1063,7 +1165,7 @@
 DeveloperPrivateChoosePathFunction::~DeveloperPrivateChoosePathFunction() {}
 
 bool DeveloperPrivateGetStringsFunction::RunImpl() {
-  DictionaryValue* dict = new DictionaryValue();
+  base::DictionaryValue* dict = new base::DictionaryValue();
   SetResult(dict);
 
   webui::SetFontAndTextDirection(dict);
@@ -1107,7 +1209,7 @@
   SET_STRING("extensionSettingsPolicyControlled",
              IDS_EXTENSIONS_POLICY_CONTROLLED);
   SET_STRING("extensionSettingsManagedMode",
-             IDS_EXTENSIONS_LOCKED_MANAGED_MODE);
+             IDS_EXTENSIONS_LOCKED_MANAGED_USER);
   SET_STRING("extensionSettingsShowButton", IDS_EXTENSIONS_SHOW_BUTTON);
   SET_STRING("appsDevtoolLoadUnpackedButton",
              IDS_APPS_DEVTOOL_LOAD_UNPACKED_BUTTON);
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api.h b/chrome/browser/extensions/api/developer_private/developer_private_api.h
index 01361b9..567f2d9 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_api.h
+++ b/chrome/browser/extensions/api/developer_private/developer_private_api.h
@@ -8,6 +8,7 @@
 #include "base/platform_file.h"
 #include "chrome/browser/extensions/api/developer_private/entry_picker.h"
 #include "chrome/browser/extensions/api/file_system/file_system_api.h"
+#include "chrome/browser/extensions/event_router.h"
 #include "chrome/browser/extensions/extension_function.h"
 #include "chrome/browser/extensions/extension_install_prompt.h"
 #include "chrome/browser/extensions/extension_uninstall_dialog.h"
@@ -54,9 +55,27 @@
 
 namespace extensions {
 
+class DeveloperPrivateEventRouter : public content::NotificationObserver {
+ public:
+  explicit DeveloperPrivateEventRouter(Profile* profile);
+  virtual ~DeveloperPrivateEventRouter();
+
+ private:
+  // content::NotificationObserver implementation
+  virtual void Observe(int type,
+                       const content::NotificationSource& source,
+                       const content::NotificationDetails& details) OVERRIDE;
+
+  content::NotificationRegistrar registrar_;
+
+  Profile* profile_;
+
+  DISALLOW_COPY_AND_ASSIGN(DeveloperPrivateEventRouter);
+};
+
 // The profile-keyed service that manages the DeveloperPrivate API.
 class DeveloperPrivateAPI : public BrowserContextKeyedService,
-                            public content::NotificationObserver {
+                            public extensions::EventRouter::Observer {
  public:
   // Convenience method to get the DeveloperPrivateAPI for a profile.
   static DeveloperPrivateAPI* Get(Profile* profile);
@@ -73,19 +92,25 @@
   // BrowserContextKeyedService implementation
   virtual void Shutdown() OVERRIDE;
 
-  // content::NotificationObserver implementation.
-  virtual void Observe(int type,
-                       const content::NotificationSource& source,
-                       const content::NotificationDetails& details) OVERRIDE;
+  // EventRouter::Observer implementation.
+  virtual void OnListenerAdded(const extensions::EventListenerInfo& details)
+      OVERRIDE;
+  virtual void OnListenerRemoved(const extensions::EventListenerInfo& details)
+      OVERRIDE;
 
  private:
   void RegisterNotifications();
 
+  Profile* profile_;
+
   // Used to start the load |load_extension_dialog_| in the last directory that
   // was loaded.
   base::FilePath last_unpacked_directory_;
 
-  content::NotificationRegistrar registrar_;
+  // Created lazily upon OnListenerAdded.
+  scoped_ptr<DeveloperPrivateEventRouter> developer_private_event_router_;
+
+  DISALLOW_COPY_AND_ASSIGN(DeveloperPrivateAPI);
 
 };
 
@@ -351,16 +376,16 @@
 
    void ClearPrexistingDirectoryContent(const base::FilePath& project_path);
 
-   void ReadSyncFileSystemDirectory(const base::FilePath& project_path);
+   void ReadSyncFileSystemDirectory(const base::FilePath& project_path,
+                                    const base::FilePath& destination_path);
 
    void ReadSyncFileSystemDirectoryCb(
        const base::FilePath& project_path,
+       const base::FilePath& destination_path,
        base::PlatformFileError result,
        const fileapi::FileSystemOperation::FileEntryList& file_list,
        bool has_more);
 
-   void CreateFolderAndSendResponse(const base::FilePath& project_path);
-
    void SnapshotFileCallback(
        const base::FilePath& target_path,
        base::PlatformFileError result,
@@ -374,7 +399,7 @@
    scoped_refptr<fileapi::FileSystemContext> context_;
 
   private:
-   int pendingCallbacksCount_;
+   int pendingCopyOperationsCount_;
 
    // This is set to false if any of the copyFile operations fail on
    // call of the API. It is returned as a response of the API call.
diff --git a/chrome/browser/extensions/api/developer_private/entry_picker.cc b/chrome/browser/extensions/api/developer_private/entry_picker.cc
index e70ae4a..91bc1f3 100644
--- a/chrome/browser/extensions/api/developer_private/entry_picker.cc
+++ b/chrome/browser/extensions/api/developer_private/entry_picker.cc
@@ -8,10 +8,8 @@
 #include "base/files/file_path.h"
 #include "base/strings/string_util.h"
 #include "chrome/browser/extensions/api/developer_private/developer_private_api.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
 #include "chrome/browser/platform_util.h"
 #include "chrome/browser/ui/chrome_select_file_policy.h"
-#include "chrome/browser/ui/extensions/shell_window.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_view.h"
 #include "ui/shell_dialogs/select_file_dialog.h"
diff --git a/chrome/browser/extensions/api/diagnostics/diagnostics_api.cc b/chrome/browser/extensions/api/diagnostics/diagnostics_api.cc
new file mode 100644
index 0000000..0f6e8d2
--- /dev/null
+++ b/chrome/browser/extensions/api/diagnostics/diagnostics_api.cc
@@ -0,0 +1,54 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/api/diagnostics/diagnostics_api.h"
+
+namespace SendPacket = extensions::api::diagnostics::SendPacket;
+
+namespace {
+
+const char kErrorPingNotImplemented[] = "Not implemented";
+const char kErrorPingFailed[] = "Failed to send ping packet";
+
+}
+
+namespace extensions {
+
+DiagnosticsSendPacketFunction::DiagnosticsSendPacketFunction() {}
+
+DiagnosticsSendPacketFunction::~DiagnosticsSendPacketFunction() {}
+
+bool DiagnosticsSendPacketFunction::Prepare() {
+  parameters_ = SendPacket::Params::Create(*args_);
+  EXTENSION_FUNCTION_VALIDATE(parameters_.get());
+  return true;
+}
+
+bool DiagnosticsSendPacketFunction::Respond() {
+  return error_.empty();
+}
+
+void DiagnosticsSendPacketFunction::OnCompleted(
+    SendPacketResultCode result_code,
+    const std::string& ip,
+    double latency) {
+  switch (result_code) {
+    case SEND_PACKET_OK: {
+      extensions::api::diagnostics::SendPacketResult result;
+      result.ip = ip;
+      result.latency = latency;
+      results_ = SendPacket::Results::Create(result);
+      break;
+    }
+    case SEND_PACKET_NOT_IMPLEMENTED:
+      SetError(kErrorPingNotImplemented);
+      break;
+    case SEND_PACKET_FAILED:
+      SetError(kErrorPingFailed);
+      break;
+  }
+  AsyncWorkCompleted();
+}
+
+}  // namespace extensions
diff --git a/chrome/browser/extensions/api/diagnostics/diagnostics_api.h b/chrome/browser/extensions/api/diagnostics/diagnostics_api.h
new file mode 100644
index 0000000..6397c71
--- /dev/null
+++ b/chrome/browser/extensions/api/diagnostics/diagnostics_api.h
@@ -0,0 +1,57 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_API_DIAGNOSTICS_DIAGNOSTICS_API_H_
+#define CHROME_BROWSER_EXTENSIONS_API_DIAGNOSTICS_DIAGNOSTICS_API_H_
+
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+#include "chrome/browser/extensions/api/api_function.h"
+#include "chrome/common/extensions/api/diagnostics.h"
+
+namespace extensions {
+
+class DiagnosticsSendPacketFunction : public AsyncApiFunction {
+ public:
+  // Result code for sending packet. Platform specific AsyncWorkStart() will
+  // finish with this ResultCode so we can maximize shared code.
+  enum SendPacketResultCode {
+    // Ping packed is sent and ICMP reply is received before time out.
+    SEND_PACKET_OK,
+
+    // Not implemented on the platform.
+    SEND_PACKET_NOT_IMPLEMENTED,
+
+    // The ping operation failed because of timeout or network unreachable.
+    SEND_PACKET_FAILED,
+  };
+
+  DECLARE_EXTENSION_FUNCTION("diagnostics.sendPacket",
+                             DIAGNOSTICS_SENDPACKET);
+
+  DiagnosticsSendPacketFunction();
+
+ protected:
+  virtual ~DiagnosticsSendPacketFunction();
+
+  // AsyncApiFunction:
+  virtual bool Prepare() OVERRIDE;
+  // This methods will be implemented differently on different platforms.
+  virtual void AsyncWorkStart() OVERRIDE;
+  virtual bool Respond() OVERRIDE;
+
+ private:
+  void SendPingPacket();
+  void OnCompleted(SendPacketResultCode result_code,
+                   const std::string& ip,
+                   double latency);
+
+  scoped_ptr<extensions::api::diagnostics::SendPacket::Params>
+      parameters_;
+};
+
+}  // namespace extensions
+
+#endif  // CHROME_BROWSER_EXTENSIONS_API_DIAGNOSTICS_DIAGNOSTICS_API_H_
diff --git a/chrome/browser/extensions/api/diagnostics/diagnostics_api_chromeos.cc b/chrome/browser/extensions/api/diagnostics/diagnostics_api_chromeos.cc
new file mode 100644
index 0000000..55f2cb0
--- /dev/null
+++ b/chrome/browser/extensions/api/diagnostics/diagnostics_api_chromeos.cc
@@ -0,0 +1,92 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/api/diagnostics/diagnostics_api.h"
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/json/json_reader.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/values.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/debug_daemon_client.h"
+
+namespace extensions {
+
+namespace {
+
+const char kCount[] = "count";
+const char kDefaultCount[] = "1";
+const char kTTL[] = "ttl";
+const char kTimeout[] = "timeout";
+const char kSize[] = "size";
+
+typedef base::Callback<void(
+    DiagnosticsSendPacketFunction::SendPacketResultCode result_code,
+    const std::string& ip,
+    double latency)>
+    SendPacketCallback;
+
+bool ParseResult(const std::string& status,
+                 std::string* ip,
+                 double* latency) {
+    // Parses the result and returns IP and latency.
+    scoped_ptr<base::Value> parsed_value(base::JSONReader::Read(status));
+    if (!parsed_value)
+      return false;
+
+    base::DictionaryValue* result = NULL;
+    if (!parsed_value->GetAsDictionary(&result) || result->size() != 1)
+      return false;
+
+    // Returns the first item.
+    base::DictionaryValue::Iterator iterator(*result);
+
+    const base::DictionaryValue* info;
+    if (!iterator.value().GetAsDictionary(&info))
+      return false;
+
+    if (info->GetDouble("avg", latency))
+      return false;
+
+    *ip = iterator.key();
+    return true;
+}
+
+void OnTestICMPCompleted(
+    const SendPacketCallback& callback,
+    bool succeeded,
+    const std::string& status) {
+  std::string ip;
+  double latency;
+  if (!succeeded || !ParseResult(status, &ip, &latency)) {
+    callback.Run(DiagnosticsSendPacketFunction::SEND_PACKET_FAILED, "", 0.0);
+  } else {
+    callback.Run(DiagnosticsSendPacketFunction::SEND_PACKET_OK,
+                 ip,
+                 latency);
+  }
+}
+
+}  // namespace
+
+void DiagnosticsSendPacketFunction::AsyncWorkStart() {
+  std::map<std::string, std::string> config;
+  config[kCount] = kDefaultCount;
+  if (parameters_->options.ttl)
+    config[kTTL] = base::IntToString(*parameters_->options.ttl);
+  if (parameters_->options.timeout)
+    config[kTimeout] = base::IntToString(*parameters_->options.timeout);
+  if (parameters_->options.size)
+    config[kSize] = base::IntToString(*parameters_->options.size);
+
+  chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()->
+      TestICMPWithOptions(
+          parameters_->options.ip, config,
+          base::Bind(
+              OnTestICMPCompleted,
+              base::Bind(&DiagnosticsSendPacketFunction::OnCompleted, this)));
+}
+
+}  // namespace extensions
diff --git a/chrome/browser/extensions/api/diagnostics/diagnostics_api_nonchromeos.cc b/chrome/browser/extensions/api/diagnostics/diagnostics_api_nonchromeos.cc
new file mode 100644
index 0000000..4e75936
--- /dev/null
+++ b/chrome/browser/extensions/api/diagnostics/diagnostics_api_nonchromeos.cc
@@ -0,0 +1,13 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/api/diagnostics/diagnostics_api.h"
+
+namespace extensions {
+
+void DiagnosticsSendPacketFunction::AsyncWorkStart() {
+  OnCompleted(SEND_PACKET_NOT_IMPLEMENTED, "", 0.0);
+}
+
+}  // namespace extensions
diff --git a/chrome/browser/extensions/api/dial/dial_api.cc b/chrome/browser/extensions/api/dial/dial_api.cc
index c790185..2a30d9a 100644
--- a/chrome/browser/extensions/api/dial/dial_api.cc
+++ b/chrome/browser/extensions/api/dial/dial_api.cc
@@ -6,7 +6,7 @@
 
 #include <vector>
 
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/extensions/api/dial/dial_api_factory.h"
 #include "chrome/browser/extensions/event_names.h"
 #include "chrome/browser/extensions/event_router.h"
diff --git a/chrome/browser/extensions/api/dial/dial_device_data.h b/chrome/browser/extensions/api/dial/dial_device_data.h
index 1ee0c40..ddda6b7 100644
--- a/chrome/browser/extensions/api/dial/dial_device_data.h
+++ b/chrome/browser/extensions/api/dial/dial_device_data.h
@@ -8,7 +8,7 @@
 #include <string>
 #include <vector>
 
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "googleurl/src/gurl.h"
 
diff --git a/chrome/browser/extensions/api/dial/dial_registry.cc b/chrome/browser/extensions/api/dial/dial_registry.cc
index bc1e2d7..e6191dc 100644
--- a/chrome/browser/extensions/api/dial/dial_registry.cc
+++ b/chrome/browser/extensions/api/dial/dial_registry.cc
@@ -7,7 +7,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/extensions/api/dial/dial_api.h"
@@ -301,17 +301,10 @@
     NetworkChangeNotifier::ConnectionType type) {
   switch (type) {
     case NetworkChangeNotifier::CONNECTION_NONE:
-    case NetworkChangeNotifier::CONNECTION_2G:
-    case NetworkChangeNotifier::CONNECTION_3G:
-    case NetworkChangeNotifier::CONNECTION_4G:
       if (dial_.get()) {
         DVLOG(1) << "Lost connection, shutting down discovery and clearing"
                  << " list.";
-
-        if (NetworkChangeNotifier::IsConnectionCellular(type))
-          dial_api_->OnDialError(DIAL_CELLULAR_NETWORK);
-        else
-          dial_api_->OnDialError(DIAL_NETWORK_DISCONNECTED);
+        dial_api_->OnDialError(DIAL_NETWORK_DISCONNECTED);
 
         StopPeriodicDiscovery();
         // TODO(justinlin): As an optimization, we can probably keep our device
@@ -321,17 +314,17 @@
         MaybeSendEvent();
       }
       break;
-    case NetworkChangeNotifier::CONNECTION_UNKNOWN:
+    case NetworkChangeNotifier::CONNECTION_2G:
+    case NetworkChangeNotifier::CONNECTION_3G:
+    case NetworkChangeNotifier::CONNECTION_4G:
     case NetworkChangeNotifier::CONNECTION_ETHERNET:
     case NetworkChangeNotifier::CONNECTION_WIFI:
+    case NetworkChangeNotifier::CONNECTION_UNKNOWN:
       if (!dial_.get()) {
         DVLOG(1) << "Connection detected, restarting discovery.";
         StartPeriodicDiscovery();
       }
       break;
-    default:
-      NOTREACHED();
-      break;
   }
 }
 
diff --git a/chrome/browser/extensions/api/dial/dial_registry.h b/chrome/browser/extensions/api/dial/dial_registry.h
index f15628d..d78f531 100644
--- a/chrome/browser/extensions/api/dial/dial_registry.h
+++ b/chrome/browser/extensions/api/dial/dial_registry.h
@@ -15,8 +15,8 @@
 #include "base/memory/linked_ptr.h"
 #include "base/memory/ref_counted.h"
 #include "base/threading/thread_checker.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/extensions/api/dial/dial_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "net/base/network_change_notifier.h"
diff --git a/chrome/browser/extensions/api/dial/dial_registry_unittest.cc b/chrome/browser/extensions/api/dial/dial_registry_unittest.cc
index 0e3acfd..3e1b034 100644
--- a/chrome/browser/extensions/api/dial/dial_registry_unittest.cc
+++ b/chrome/browser/extensions/api/dial/dial_registry_unittest.cc
@@ -328,7 +328,8 @@
       .Times(1);
   EXPECT_CALL(mock_observer_, OnDialDeviceEvent(list_with_first_device_))
       .Times(1);
-  EXPECT_CALL(mock_observer_, OnDialError(DialRegistry::DIAL_CELLULAR_NETWORK))
+  EXPECT_CALL(mock_observer_,
+              OnDialError(DialRegistry::DIAL_NETWORK_DISCONNECTED))
       .Times(1);
   EXPECT_CALL(mock_observer_, OnDialDeviceEvent(empty_list_))
       .Times(2);
@@ -342,7 +343,7 @@
   registry_->OnDeviceDiscovered(NULL, first_device_);
   registry_->OnDiscoveryFinished(NULL);
 
-  registry_->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_3G);
+  registry_->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_NONE);
 
   registry_->OnDiscoveryRequest(NULL);
   registry_->OnDiscoveryFinished(NULL);
diff --git a/chrome/browser/extensions/api/dial/dial_service.cc b/chrome/browser/extensions/api/dial/dial_service.cc
index 8c106e3..b4bc70e 100644
--- a/chrome/browser/extensions/api/dial/dial_service.cc
+++ b/chrome/browser/extensions/api/dial/dial_service.cc
@@ -12,7 +12,7 @@
 #include "base/rand_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/extensions/api/dial/dial_device_data.h"
 #include "chrome/common/chrome_version_info.h"
 #include "content/public/browser/browser_thread.h"
@@ -24,6 +24,11 @@
 #include "net/base/net_util.h"
 #include "net/http/http_response_headers.h"
 #include "net/http/http_util.h"
+#if defined(OS_CHROMEOS)
+#include "chromeos/network/network_state.h"
+#include "chromeos/network/network_state_handler.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+#endif
 
 using base::Time;
 using base::TimeDelta;
@@ -170,17 +175,51 @@
   if (socket_.get())
     return;
 
+#if defined(OS_CHROMEOS)
+  // The ChromeOS specific version of getting network interfaces does not
+  // require trampolining to another thread, and contains additional interface
+  // information such as interface types (i.e. wifi vs cellular).
+  BindSocketAndSendRequest(GetBestBindAddressChromeOS());
+#else
   BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, base::Bind(
       &GetNetworkListOnFileThread,
       base::MessageLoopProxy::current(), base::Bind(
           &DialServiceImpl::SendNetworkList, AsWeakPtr())));
+#endif
 }
 
+#if defined(OS_CHROMEOS)
+IPAddressNumber DialServiceImpl::GetBestBindAddressChromeOS() {
+  std::string connection_types[] =
+      {flimflam::kTypeWifi, flimflam::kTypeEthernet};
+  for (uint i = 0; i < arraysize(connection_types); ++i) {
+    IPAddressNumber bind_ip_address;
+    const chromeos::NetworkState* state =
+        chromeos::NetworkHandler::Get()->network_state_handler()->
+            ConnectedNetworkByType(connection_types[i]);
+    if (state &&
+        net::ParseIPLiteralToNumber(state->ip_address(), &bind_ip_address)) {
+      DCHECK(bind_ip_address.size() == net::kIPv4AddressSize);
+      DVLOG(1) << "Found " << state->type() << ", " << state->name() << ":"
+               << state->ip_address();
+      return bind_ip_address;
+    }
+  }
+  return IPAddressNumber();
+}
+#endif
+
 bool DialServiceImpl::BindSocketAndSendRequest(
       const IPAddressNumber& bind_ip_address) {
   DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(!socket_.get());
 
+  if (bind_ip_address.size() == 0) {
+    DVLOG(1) << "Could not find a valid interface to bind.";
+    FinishDiscovery();
+    return false;
+  }
+
   net::RandIntCallback rand_cb = base::Bind(&base::RandInt);
   socket_.reset(new UDPSocket(net::DatagramSocket::RANDOM_BIND,
                               rand_cb,
@@ -393,7 +432,7 @@
 
 void DialServiceImpl::SendNetworkList(const NetworkInterfaceList& networks) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  const NetworkInterface* interface = NULL;
+  IPAddressNumber bind_ip_address;
   // Returns the first IPv4 address found.  If there is a need for discovery
   // across multiple networks, we could manage multiple sockets.
 
@@ -403,17 +442,12 @@
     DVLOG(1) << "Found " << iter->name << ", "
              << net::IPAddressToString(iter->address);
     if (iter->address.size() == net::kIPv4AddressSize) {
-      interface = &*iter;
+      bind_ip_address = (*iter).address;
       break;
     }
   }
 
-  if (interface == NULL) {
-    DVLOG(1) << "Could not find a valid interface to bind.";
-    FinishDiscovery();
-  } else {
-    BindSocketAndSendRequest(interface->address);
-  }
+  BindSocketAndSendRequest(bind_ip_address);
 }
 
 void DialServiceImpl::FinishDiscovery() {
diff --git a/chrome/browser/extensions/api/dial/dial_service.h b/chrome/browser/extensions/api/dial/dial_service.h
index a714f35..05d328c 100644
--- a/chrome/browser/extensions/api/dial/dial_service.h
+++ b/chrome/browser/extensions/api/dial/dial_service.h
@@ -12,7 +12,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "base/threading/thread_checker.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "net/base/net_log.h"
 #include "net/udp/udp_socket.h"
 
@@ -113,6 +113,12 @@
   // Starts the control flow for one discovery cycle.
   void StartDiscovery();
 
+#if defined(OS_CHROMEOS)
+  // Returns the IP address of the preferred interface to bind the socket. This
+  // ChromeOS version can prioritize wifi and ethernet interfaces.
+  net::IPAddressNumber GetBestBindAddressChromeOS();
+#endif
+
   // Establishes the UDP socket that is used for requests and responses,
   // establishes a read callback on the socket, and sends the first discovery
   // request.  Returns true if successful.
diff --git a/chrome/browser/extensions/api/dns/dns_apitest.cc b/chrome/browser/extensions/api/dns/dns_apitest.cc
index 14c005f..ccd9602 100644
--- a/chrome/browser/extensions/api/dns/dns_apitest.cc
+++ b/chrome/browser/extensions/api/dns/dns_apitest.cc
@@ -63,7 +63,8 @@
   scoped_ptr<base::Value> result(RunFunctionAndReturnSingleResult(
       resolve_function.get(), "[\"127.0.0.1\"]", browser()));
   ASSERT_EQ(base::Value::TYPE_DICTIONARY, result->GetType());
-  DictionaryValue *value = static_cast<DictionaryValue*>(result.get());
+  base::DictionaryValue *value =
+      static_cast<base::DictionaryValue*>(result.get());
 
   int resultCode;
   EXPECT_TRUE(value->GetInteger("resultCode", &resultCode));
@@ -89,7 +90,8 @@
       RunFunctionAndReturnSingleResult(resolve_function.get(),
                                        function_arguments, browser()));
   ASSERT_EQ(base::Value::TYPE_DICTIONARY, result->GetType());
-  DictionaryValue *value = static_cast<DictionaryValue*>(result.get());
+  base::DictionaryValue *value =
+      static_cast<base::DictionaryValue*>(result.get());
 
   int resultCode;
   EXPECT_TRUE(value->GetInteger("resultCode", &resultCode));
diff --git a/chrome/browser/extensions/api/downloads/downloads_api.cc b/chrome/browser/extensions/api/downloads/downloads_api.cc
index bdd3ff4..b831d52 100644
--- a/chrome/browser/extensions/api/downloads/downloads_api.cc
+++ b/chrome/browser/extensions/api/downloads/downloads_api.cc
@@ -787,7 +787,7 @@
     ExtensionDownloadsEventRouterData* data,
     Profile* profile,
     const extensions::Extension* extension,
-    ListValue* event_args) {
+    base::ListValue* event_args) {
   *any_determiners = true;
   base::Time installed = extensions::ExtensionSystem::Get(
       profile)->extension_service()->extension_prefs()->
@@ -1046,7 +1046,7 @@
   DownloadItem* download_item = GetDownloadIfInProgress(
       profile(), include_incognito(), params->download_id);
   content::WebContents* web_contents =
-      dispatcher()->delegate()->GetAssociatedWebContents();
+      dispatcher()->delegate()->GetVisibleWebContents();
   if (!download_item ||
       !download_item->IsDangerous() ||
       !web_contents) {
@@ -1128,7 +1128,7 @@
   DownloadItem* download_item = GetDownload(
       profile(), include_incognito(), params->download_id);
   content::WebContents* web_contents =
-      dispatcher()->delegate()->GetAssociatedWebContents();
+      dispatcher()->delegate()->GetVisibleWebContents();
   if (!download_item || !web_contents) {
     error_ = download_extension_errors::kInvalidOperationError;
     return false;
diff --git a/chrome/browser/extensions/api/downloads/downloads_api_unittest.cc b/chrome/browser/extensions/api/downloads/downloads_api_unittest.cc
index 8eacf45..b3f08d0 100644
--- a/chrome/browser/extensions/api/downloads/downloads_api_unittest.cc
+++ b/chrome/browser/extensions/api/downloads/downloads_api_unittest.cc
@@ -1541,7 +1541,8 @@
 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
                        DownloadExtensionTest_Download_Basic) {
   LoadExtension("downloads_split");
-  CHECK(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
+  ASSERT_TRUE(test_server()->Start());
   std::string download_url = test_server()->GetURL("slow?0").spec();
   GoOnTheRecord();
 
@@ -1584,7 +1585,8 @@
 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
                        DownloadExtensionTest_Download_Incognito) {
   LoadExtension("downloads_split");
-  CHECK(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
+  ASSERT_TRUE(test_server()->Start());
   GoOffTheRecord();
   std::string download_url = test_server()->GetURL("slow?0").spec();
 
@@ -1635,7 +1637,8 @@
 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
                        MAYBE_DownloadExtensionTest_Download_UnsafeHeaders) {
   LoadExtension("downloads_split");
-  CHECK(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
+  ASSERT_TRUE(test_server()->Start());
   GoOnTheRecord();
 
   static const char* kUnsafeHeaders[] = {
@@ -1687,7 +1690,8 @@
 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
                        DownloadExtensionTest_Download_Subdirectory) {
   LoadExtension("downloads_split");
-  CHECK(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
+  ASSERT_TRUE(test_server()->Start());
   std::string download_url = test_server()->GetURL("slow?0").spec();
   GoOnTheRecord();
 
@@ -1703,7 +1707,8 @@
 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
                        DownloadExtensionTest_Download_InvalidFilename) {
   LoadExtension("downloads_split");
-  CHECK(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
+  ASSERT_TRUE(test_server()->Start());
   std::string download_url = test_server()->GetURL("slow?0").spec();
   GoOnTheRecord();
 
@@ -1749,7 +1754,8 @@
 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
                        DownloadExtensionTest_Download_URLFragment) {
   LoadExtension("downloads_split");
-  CHECK(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
+  ASSERT_TRUE(test_server()->Start());
   std::string download_url = test_server()->GetURL("slow?0#fragment").spec();
   GoOnTheRecord();
 
@@ -1886,7 +1892,8 @@
 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
                        DownloadExtensionTest_Download_AuthBasic_Fail) {
   LoadExtension("downloads_split");
-  CHECK(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
+  ASSERT_TRUE(test_server()->Start());
   std::string download_url = test_server()->GetURL("auth-basic").spec();
   GoOnTheRecord();
 
@@ -1916,7 +1923,8 @@
 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
                        DownloadExtensionTest_Download_Headers) {
   LoadExtension("downloads_split");
-  CHECK(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
+  ASSERT_TRUE(test_server()->Start());
   std::string download_url = test_server()->GetURL("files/downloads/"
       "a_zip_file.zip?expected_headers=Foo:bar&expected_headers=Qx:yo").spec();
   GoOnTheRecord();
@@ -1966,7 +1974,8 @@
 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
                        DownloadExtensionTest_Download_Headers_Fail) {
   LoadExtension("downloads_split");
-  CHECK(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
+  ASSERT_TRUE(test_server()->Start());
   std::string download_url = test_server()->GetURL("files/downloads/"
       "a_zip_file.zip?expected_headers=Foo:bar&expected_headers=Qx:yo").spec();
   GoOnTheRecord();
@@ -1999,7 +2008,8 @@
 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
                        DownloadExtensionTest_Download_AuthBasic) {
   LoadExtension("downloads_split");
-  CHECK(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
+  ASSERT_TRUE(test_server()->Start());
   std::string download_url = test_server()->GetURL("auth-basic").spec();
   // This is just base64 of 'username:secret'.
   static const char* kAuthorization = "dXNlcm5hbWU6c2VjcmV0";
@@ -2039,7 +2049,8 @@
 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
                        DownloadExtensionTest_Download_Post) {
   LoadExtension("downloads_split");
-  CHECK(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
+  ASSERT_TRUE(test_server()->Start());
   std::string download_url = test_server()->GetURL("files/post/downloads/"
       "a_zip_file.zip?expected_body=BODY").spec();
   GoOnTheRecord();
@@ -2088,7 +2099,8 @@
 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
                        DownloadExtensionTest_Download_Post_Get) {
   LoadExtension("downloads_split");
-  CHECK(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
+  ASSERT_TRUE(test_server()->Start());
   std::string download_url = test_server()->GetURL("files/post/downloads/"
       "a_zip_file.zip?expected_body=BODY").spec();
   GoOnTheRecord();
@@ -2126,7 +2138,8 @@
 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
                        DownloadExtensionTest_Download_Post_NoBody) {
   LoadExtension("downloads_split");
-  CHECK(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
+  ASSERT_TRUE(test_server()->Start());
   std::string download_url = test_server()->GetURL("files/post/downloads/"
       "a_zip_file.zip?expected_body=BODY").spec();
   GoOnTheRecord();
@@ -2163,7 +2176,8 @@
 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
                        DownloadExtensionTest_Download_Cancel) {
   LoadExtension("downloads_split");
-  CHECK(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
+  ASSERT_TRUE(test_server()->Start());
   std::string download_url = test_server()->GetURL(
       "download-known-size").spec();
   GoOnTheRecord();
@@ -2258,7 +2272,8 @@
   GoOnTheRecord();
   LoadExtension("downloads_split");
   AddFilenameDeterminer();
-  CHECK(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
+  ASSERT_TRUE(test_server()->Start());
   std::string download_url = test_server()->GetURL("slow?0").spec();
 
   // Start downloading a file.
@@ -2325,7 +2340,8 @@
   GoOnTheRecord();
   LoadExtension("downloads_split");
   AddFilenameDeterminer();
-  CHECK(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
+  ASSERT_TRUE(test_server()->Start());
   std::string download_url = test_server()->GetURL("slow?0").spec();
 
   // Start downloading a file.
@@ -2401,7 +2417,8 @@
   GoOnTheRecord();
   LoadExtension("downloads_split");
   AddFilenameDeterminer();
-  CHECK(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
+  ASSERT_TRUE(test_server()->Start());
   std::string download_url = test_server()->GetURL("slow?0").spec();
 
   // Start downloading a file.
@@ -2465,7 +2482,8 @@
   GoOnTheRecord();
   LoadExtension("downloads_split");
   AddFilenameDeterminer();
-  CHECK(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
+  ASSERT_TRUE(test_server()->Start());
   std::string download_url = test_server()->GetURL("slow?0").spec();
 
   // Start downloading a file.
@@ -2529,7 +2547,8 @@
   GoOnTheRecord();
   LoadExtension("downloads_split");
   AddFilenameDeterminer();
-  CHECK(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
+  ASSERT_TRUE(test_server()->Start());
   std::string download_url = test_server()->GetURL("slow?0").spec();
 
   // Start downloading a file.
@@ -2594,7 +2613,8 @@
   GoOnTheRecord();
   LoadExtension("downloads_split");
   AddFilenameDeterminer();
-  CHECK(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
+  ASSERT_TRUE(test_server()->Start());
   std::string download_url = test_server()->GetURL("slow?0").spec();
 
   // Start downloading a file.
@@ -2658,7 +2678,8 @@
   GoOnTheRecord();
   LoadExtension("downloads_split");
   AddFilenameDeterminer();
-  CHECK(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
+  ASSERT_TRUE(test_server()->Start());
   std::string download_url = test_server()->GetURL("slow?0").spec();
 
   // Start downloading a file.
@@ -2719,7 +2740,8 @@
 IN_PROC_BROWSER_TEST_F(
     DownloadExtensionTest,
     DownloadExtensionTest_OnDeterminingFilename_ParentDirInvalid) {
-  CHECK(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
+  ASSERT_TRUE(test_server()->Start());
   GoOnTheRecord();
   LoadExtension("downloads_split");
   AddFilenameDeterminer();
@@ -2786,7 +2808,8 @@
   GoOnTheRecord();
   LoadExtension("downloads_split");
   AddFilenameDeterminer();
-  CHECK(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
+  ASSERT_TRUE(test_server()->Start());
   std::string download_url = test_server()->GetURL("slow?0").spec();
 
   // Start downloading a file.
@@ -2851,7 +2874,8 @@
   GoOnTheRecord();
   LoadExtension("downloads_split");
   AddFilenameDeterminer();
-  CHECK(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
+  ASSERT_TRUE(test_server()->Start());
   std::string download_url = test_server()->GetURL("slow?0").spec();
 
   // Start downloading a file.
@@ -2916,7 +2940,8 @@
   GoOnTheRecord();
   LoadExtension("downloads_split");
   AddFilenameDeterminer();
-  CHECK(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
+  ASSERT_TRUE(test_server()->Start());
   std::string download_url = test_server()->GetURL("slow?0").spec();
 
   // Start downloading a file.
@@ -3037,7 +3062,8 @@
 IN_PROC_BROWSER_TEST_F(
     DownloadExtensionTest,
     DownloadExtensionTest_OnDeterminingFilename_RemoveFilenameDeterminer) {
-  CHECK(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
+  ASSERT_TRUE(test_server()->Start());
   GoOnTheRecord();
   LoadExtension("downloads_split");
   content::RenderProcessHost* host = AddFilenameDeterminer();
@@ -3087,7 +3113,8 @@
     DownloadExtensionTest,
     DownloadExtensionTest_OnDeterminingFilename_IncognitoSplit) {
   LoadExtension("downloads_split");
-  CHECK(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
+  ASSERT_TRUE(test_server()->Start());
   std::string download_url = test_server()->GetURL("slow?0").spec();
 
   GoOnTheRecord();
@@ -3219,7 +3246,8 @@
     DownloadExtensionTest,
     DownloadExtensionTest_OnDeterminingFilename_IncognitoSpanning) {
   LoadExtension("downloads_spanning");
-  CHECK(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
+  ASSERT_TRUE(test_server()->Start());
   std::string download_url = test_server()->GetURL("slow?0").spec();
 
   GoOnTheRecord();
@@ -3364,7 +3392,8 @@
   CommandLine::ForCurrentProcess()->AppendSwitch(
       switches::kEnableDownloadResumption);
   LoadExtension("downloads_split");
-  CHECK(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
+  ASSERT_TRUE(test_server()->Start());
   GoOnTheRecord();
   content::RenderProcessHost* host = AddFilenameDeterminer();
 
diff --git a/chrome/browser/extensions/api/execute_code_function.cc b/chrome/browser/extensions/api/execute_code_function.cc
index 0665657..d1a0f83 100644
--- a/chrome/browser/extensions/api/execute_code_function.cc
+++ b/chrome/browser/extensions/api/execute_code_function.cc
@@ -172,7 +172,7 @@
     const std::string& error,
     int32 on_page_id,
     const GURL& on_url,
-    const ListValue& result) {
+    const base::ListValue& result) {
   if (!error.empty())
     SetError(error);
 
diff --git a/chrome/browser/extensions/api/execute_code_function.h b/chrome/browser/extensions/api/execute_code_function.h
index 2e6dbb9..b3de979 100644
--- a/chrome/browser/extensions/api/execute_code_function.h
+++ b/chrome/browser/extensions/api/execute_code_function.h
@@ -36,7 +36,7 @@
   virtual void OnExecuteCodeFinished(const std::string& error,
                                      int32 on_page_id,
                                      const GURL& on_url,
-                                     const ListValue& result);
+                                     const base::ListValue& result);
 
   // The injection details.
   scoped_ptr<api::tabs::InjectDetails> details_;
diff --git a/chrome/browser/extensions/api/extension_action/extension_action_api.cc b/chrome/browser/extensions/api/extension_action/extension_action_api.cc
index 1047994..5102b6e 100644
--- a/chrome/browser/extensions/api/extension_action/extension_action_api.cc
+++ b/chrome/browser/extensions/api/extension_action/extension_action_api.cc
@@ -150,7 +150,7 @@
 // disk.
 scoped_ptr<base::DictionaryValue> DefaultsToValue(ExtensionAction* action) {
   const int kTabId = ExtensionAction::kDefaultTabId;
-  scoped_ptr<base::DictionaryValue> dict(new DictionaryValue());
+  scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
 
   dict->SetString(kPopupUrlStorageKey, action->GetPopupUrl(kTabId).spec());
   dict->SetString(kTitleStorageKey, action->GetTitle(kTabId));
@@ -631,7 +631,7 @@
   EXTENSION_FUNCTION_VALIDATE(details_->Get("color", &color_value));
   SkColor color = 0;
   if (color_value->IsType(Value::TYPE_LIST)) {
-    ListValue* list = NULL;
+    base::ListValue* list = NULL;
     EXTENSION_FUNCTION_VALIDATE(details_->GetList("color", &list));
     EXTENSION_FUNCTION_VALIDATE(list->GetSize() == 4);
 
@@ -671,7 +671,7 @@
 }
 
 bool ExtensionActionGetBadgeBackgroundColorFunction::RunExtensionAction() {
-  ListValue* list = new ListValue();
+  base::ListValue* list = new base::ListValue();
   SkColor color = extension_action_->GetBadgeBackgroundColor(tab_id_);
   list->Append(Value::CreateIntegerValue(SkColorGetR(color)));
   list->Append(Value::CreateIntegerValue(SkColorGetG(color)));
diff --git a/chrome/browser/extensions/api/extension_action/script_badge_apitest.cc b/chrome/browser/extensions/api/extension_action/script_badge_apitest.cc
index f81f958..c30884d 100644
--- a/chrome/browser/extensions/api/extension_action/script_badge_apitest.cc
+++ b/chrome/browser/extensions/api/extension_action/script_badge_apitest.cc
@@ -19,7 +19,7 @@
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/web_contents.h"
 #include "net/dns/mock_host_resolver.h"
-#include "net/test/spawned_test_server/spawned_test_server.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
 namespace extensions {
@@ -40,7 +40,7 @@
 };
 
 IN_PROC_BROWSER_TEST_F(ScriptBadgeApiTest, Basics) {
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
   ASSERT_TRUE(RunExtensionTest("script_badge/basics")) << message_;
   const Extension* extension = GetSingleLoadedExtension();
   ASSERT_TRUE(extension) << message_;
@@ -88,8 +88,8 @@
     ResultCatcher catcher;
     // Visit a non-extension page so the extension can run a content script and
     // cause the script badge to be animated in.
-    ui_test_utils::NavigateToURL(browser(),
-                                 test_server()->GetURL(std::string()));
+    ui_test_utils::NavigateToURL(
+        browser(), embedded_test_server()->GetURL("/title1.html"));
     ASSERT_TRUE(catcher.GetNextResult());
   }
   EXPECT_TRUE(script_badge->GetIsVisible(tab_id));
diff --git a/chrome/browser/extensions/api/file_system/file_system_api.cc b/chrome/browser/extensions/api/file_system/file_system_api.cc
index a2a5182..a441157 100644
--- a/chrome/browser/extensions/api/file_system/file_system_api.cc
+++ b/chrome/browser/extensions/api/file_system/file_system_api.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/extensions/api/file_system/file_system_api.h"
 
 #include "apps/saved_files_service.h"
+#include "apps/shell_window.h"
 #include "base/bind.h"
 #include "base/file_util.h"
 #include "base/files/file_path.h"
@@ -13,13 +14,14 @@
 #include "base/strings/string_util.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/value_conversions.h"
+#include "base/values.h"
 #include "chrome/browser/extensions/api/file_handlers/app_file_handler_util.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_system.h"
 #include "chrome/browser/extensions/shell_window_registry.h"
 #include "chrome/browser/platform_util.h"
 #include "chrome/browser/ui/chrome_select_file_policy.h"
-#include "chrome/browser/ui/extensions/shell_window.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/extensions/api/file_system.h"
 #include "chrome/common/extensions/permissions/api_permission.h"
@@ -50,6 +52,7 @@
 
 using apps::SavedFileEntry;
 using apps::SavedFilesService;
+using apps::ShellWindow;
 using fileapi::IsolatedContext;
 
 const char kInvalidParameters[] = "Invalid parameters";
@@ -85,12 +88,8 @@
 // Retrieves the localized display name for the base name of the given path.
 // If the path is not localized, this will just return the base name.
 std::string GetDisplayBaseName(const base::FilePath& path) {
-  base::mac::ScopedCFTypeRef<CFURLRef> url(
-      CFURLCreateFromFileSystemRepresentation(
-          NULL,
-          (const UInt8*)path.value().c_str(),
-          path.value().length(),
-          true));
+  base::ScopedCFTypeRef<CFURLRef> url(CFURLCreateFromFileSystemRepresentation(
+      NULL, (const UInt8*)path.value().c_str(), path.value().length(), true));
   if (!url)
     return path.BaseName().value();
 
@@ -338,10 +337,40 @@
   return true;
 }
 
+// Key for the path of the directory of the file last chosen by the user in
+// response to a chrome.fileSystem.chooseEntry() call.
+const char kLastChooseEntryDirectory[] = "last_choose_file_directory";
+
 }  // namespace
 
 namespace extensions {
 
+namespace file_system_api {
+
+bool GetLastChooseEntryDirectory(const ExtensionPrefs* prefs,
+                                 const std::string& extension_id,
+                                 base::FilePath* path) {
+  std::string string_path;
+  if (!prefs->ReadPrefAsString(extension_id,
+                               kLastChooseEntryDirectory,
+                               &string_path)) {
+    return false;
+  }
+
+  *path = base::FilePath::FromUTF8Unsafe(string_path);
+  return true;
+}
+
+void SetLastChooseEntryDirectory(ExtensionPrefs* prefs,
+                                 const std::string& extension_id,
+                                 const base::FilePath& path) {
+  prefs->UpdateExtensionPref(extension_id,
+                             kLastChooseEntryDirectory,
+                             base::CreateFilePathValue(path));
+}
+
+}  // namespace file_system_api
+
 bool FileSystemGetDisplayPathFunction::RunImpl() {
   std::string filesystem_name;
   std::string filesystem_path;
@@ -405,7 +434,7 @@
           GetExtension()->id(), render_view_host_->GetProcess()->GetID(), path,
           writable);
 
-  DictionaryValue* dict = new DictionaryValue();
+  base::DictionaryValue* dict = new base::DictionaryValue();
   SetResult(dict);
   dict->SetString("fileSystemId", file_entry.filesystem_id);
   dict->SetString("baseName", file_entry.registered_name);
@@ -643,9 +672,10 @@
 
 void FileSystemChooseEntryFunction::FileSelected(const base::FilePath& path,
                                                  EntryType entry_type) {
-  extensions::ExtensionSystem::Get(profile())->extension_service()->
-      extension_prefs()->SetLastChooseEntryDirectory(
-          GetExtension()->id(), path.DirName());
+  file_system_api::SetLastChooseEntryDirectory(
+      ExtensionPrefs::Get(profile()),
+      GetExtension()->id(),
+      path.DirName());
   if (entry_type == WRITABLE) {
     CheckWritableFile(path);
     return;
@@ -755,9 +785,10 @@
   file_type_info.support_drive = true;
 
   base::FilePath previous_path;
-  extensions::ExtensionSystem::Get(profile())->extension_service()->
-      extension_prefs()->GetLastChooseEntryDirectory(
-          GetExtension()->id(), &previous_path);
+  file_system_api::GetLastChooseEntryDirectory(
+      ExtensionPrefs::Get(profile()),
+      GetExtension()->id(),
+      &previous_path);
 
   content::BrowserThread::PostTaskAndReply(
       content::BrowserThread::FILE,
diff --git a/chrome/browser/extensions/api/file_system/file_system_api.h b/chrome/browser/extensions/api/file_system/file_system_api.h
index 9793e57..97b8dd1 100644
--- a/chrome/browser/extensions/api/file_system/file_system_api.h
+++ b/chrome/browser/extensions/api/file_system/file_system_api.h
@@ -9,7 +9,29 @@
 #include "chrome/common/extensions/api/file_system.h"
 #include "ui/shell_dialogs/select_file_dialog.h"
 
+namespace base {
+class FilePath;
+}
+
 namespace extensions {
+class ExtensionPrefs;
+
+namespace file_system_api {
+
+// Methods to get and set the path of the directory containing the last file
+// chosen by the user in response to a chrome.fileSystem.chooseEntry() call for
+// the given extension.
+
+// Returns true and populates result on success; false on failure.
+bool GetLastChooseEntryDirectory(const ExtensionPrefs* prefs,
+                                 const std::string& extension_id,
+                                 base::FilePath* path);
+
+void SetLastChooseEntryDirectory(ExtensionPrefs* prefs,
+                                 const std::string& extension_id,
+                                 const base::FilePath& path);
+
+}  // namespace file_system_api
 
 class FileSystemGetDisplayPathFunction : public SyncExtensionFunction {
  public:
diff --git a/chrome/browser/extensions/api/file_system/file_system_apitest.cc b/chrome/browser/extensions/api/file_system/file_system_apitest.cc
index 11f5823..ab7c4d5 100644
--- a/chrome/browser/extensions/api/file_system/file_system_apitest.cc
+++ b/chrome/browser/extensions/api/file_system/file_system_apitest.cc
@@ -7,22 +7,21 @@
 #include "base/path_service.h"
 #include "build/build_config.h"
 #include "chrome/browser/extensions/api/file_system/file_system_api.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/extensions/extension_system.h"
+#include "chrome/browser/extensions/extension_prefs.h"
 #include "chrome/browser/extensions/platform_app_browsertest_util.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "chrome/common/chrome_paths.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_service.h"
 
-using extensions::FileSystemChooseEntryFunction;
+namespace extensions {
 
 namespace {
 
 class AppInstallObserver : public content::NotificationObserver {
  public:
   AppInstallObserver(
-      base::Callback<void(const extensions::Extension*)> callback)
+      base::Callback<void(const Extension*)> callback)
       : callback_(callback) {
     registrar_.Add(this,
                    chrome::NOTIFICATION_EXTENSION_LOADED,
@@ -33,40 +32,42 @@
                        const content::NotificationSource& source,
                        const content::NotificationDetails& details) OVERRIDE {
     EXPECT_EQ(chrome::NOTIFICATION_EXTENSION_LOADED, type);
-    callback_.Run(content::Details<const extensions::Extension>(details).ptr());
+    callback_.Run(content::Details<const Extension>(details).ptr());
   }
 
  private:
   content::NotificationRegistrar registrar_;
-  base::Callback<void(const extensions::Extension*)> callback_;
+  base::Callback<void(const Extension*)> callback_;
   DISALLOW_COPY_AND_ASSIGN(AppInstallObserver);
 };
 
 void SetLastChooseEntryDirectory(const base::FilePath& choose_entry_directory,
-                                 extensions::ExtensionPrefs* prefs,
-                                 const extensions::Extension* extension) {
-  prefs->SetLastChooseEntryDirectory(extension->id(), choose_entry_directory);
+                                 ExtensionPrefs* prefs,
+                                 const Extension* extension) {
+  file_system_api::SetLastChooseEntryDirectory(
+      prefs, extension->id(), choose_entry_directory);
 }
 
 void SetLastChooseEntryDirectoryToAppDirectory(
-    extensions::ExtensionPrefs* prefs,
-    const extensions::Extension* extension) {
-  prefs->SetLastChooseEntryDirectory(extension->id(), extension->path());
+    ExtensionPrefs* prefs,
+    const Extension* extension) {
+  file_system_api::SetLastChooseEntryDirectory(
+      prefs, extension->id(), extension->path());
 }
 
 void AddSavedEntry(const base::FilePath& path_to_save,
                    apps::SavedFilesService* service,
-                   const extensions::Extension* extension) {
+                   const Extension* extension) {
   service->RegisterFileEntry(
       extension->id(), "magic id", path_to_save, /* writable */ true);
 }
 
 }  // namespace
 
-class FileSystemApiTest : public extensions::PlatformAppBrowserTest {
+class FileSystemApiTest : public PlatformAppBrowserTest {
  public:
   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
-    extensions::PlatformAppBrowserTest::SetUpCommandLine(command_line);
+    PlatformAppBrowserTest::SetUpCommandLine(command_line);
     test_root_folder_ = test_data_dir_.AppendASCII("api_test")
         .AppendASCII("file_system");
     FileSystemChooseEntryFunction::RegisterTempExternalFileSystemForTest(
@@ -75,7 +76,7 @@
 
   virtual void TearDown() OVERRIDE {
     FileSystemChooseEntryFunction::StopSkippingPickerForTest();
-    extensions::PlatformAppBrowserTest::TearDown();
+    PlatformAppBrowserTest::TearDown();
   };
 
  protected:
@@ -97,18 +98,17 @@
   }
 
   void CheckStoredDirectoryMatches(const base::FilePath& filename) {
-    const extensions::Extension* extension = GetSingleLoadedExtension();
+    const Extension* extension = GetSingleLoadedExtension();
     ASSERT_TRUE(extension);
     std::string extension_id = extension->id();
-    extensions::ExtensionPrefs* prefs = extensions::ExtensionSystem::Get(
-        profile())->extension_service()->extension_prefs();
+    ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
     base::FilePath stored_value;
     if (filename.empty()) {
-      EXPECT_FALSE(prefs->GetLastChooseEntryDirectory(extension_id,
-                                                      &stored_value));
+      EXPECT_FALSE(file_system_api::GetLastChooseEntryDirectory(
+          prefs, extension_id, &stored_value));
     } else {
-      EXPECT_TRUE(prefs->GetLastChooseEntryDirectory(extension_id,
-                                                     &stored_value));
+      EXPECT_TRUE(file_system_api::GetLastChooseEntryDirectory(
+          prefs, extension_id, &stored_value));
       EXPECT_EQ(base::MakeAbsoluteFilePath(filename.DirName()),
                 base::MakeAbsoluteFilePath(stored_value));
     }
@@ -182,8 +182,7 @@
     AppInstallObserver observer(
         base::Bind(SetLastChooseEntryDirectory,
                    test_file.DirName(),
-                   extensions::ExtensionSystem::Get(
-                       profile())->extension_service()->extension_prefs()));
+                   ExtensionPrefs::Get(profile())));
     ASSERT_TRUE(RunPlatformAppTest("api_test/file_system/open_existing"))
         << message_;
   }
@@ -203,8 +202,7 @@
         SetLastChooseEntryDirectory,
         test_file.DirName().Append(
             base::FilePath::FromUTF8Unsafe("fake_directory_does_not_exist")),
-        extensions::ExtensionSystem::Get(
-            profile())->extension_service()->extension_prefs()));
+        ExtensionPrefs::Get(profile())));
     ASSERT_TRUE(RunPlatformAppTest("api_test/file_system/open_existing"))
         << message_;
   }
@@ -392,8 +390,7 @@
   {
     AppInstallObserver observer(
         base::Bind(SetLastChooseEntryDirectoryToAppDirectory,
-                   extensions::ExtensionSystem::Get(
-                       profile())->extension_service()->extension_prefs()));
+                   ExtensionPrefs::Get(profile())));
     ASSERT_TRUE(RunPlatformAppTest(
         "api_test/file_system/get_writable_file_entry_non_writable_file"))
         << message_;
@@ -499,10 +496,11 @@
   {
     AppInstallObserver observer(
         base::Bind(SetLastChooseEntryDirectoryToAppDirectory,
-                   extensions::ExtensionSystem::Get(
-                       profile())->extension_service()->extension_prefs()));
+                   ExtensionPrefs::Get(profile())));
     ASSERT_TRUE(RunPlatformAppTest(
         "api_test/file_system/open_writable_existing_non_writable"))
         << message_;
   }
 }
+
+}  // namespace extensions
diff --git a/chrome/browser/extensions/api/font_settings/font_settings_api.cc b/chrome/browser/extensions/api/font_settings/font_settings_api.cc
index 7ec693d..722172a 100644
--- a/chrome/browser/extensions/api/font_settings/font_settings_api.cc
+++ b/chrome/browser/extensions/api/font_settings/font_settings_api.cc
@@ -174,8 +174,8 @@
   }
   font_name = MaybeGetLocalizedFontName(font_name);
 
-  ListValue args;
-  DictionaryValue* dict = new DictionaryValue();
+  base::ListValue args;
+  base::DictionaryValue* dict = new base::DictionaryValue();
   args.Append(dict);
   dict->SetString(kFontIdKey, font_name);
   dict->SetString(kGenericFamilyKey, generic_family);
@@ -198,8 +198,8 @@
       pref_name.c_str());
   CHECK(pref);
 
-  ListValue args;
-  DictionaryValue* dict = new DictionaryValue();
+  base::ListValue args;
+  base::DictionaryValue* dict = new base::DictionaryValue();
   args.Append(dict);
   dict->Set(key, pref->GetValue()->DeepCopy());
 
@@ -275,7 +275,7 @@
                                                         pref_path,
                                                         kIncognito);
 
-  DictionaryValue* result = new DictionaryValue();
+  base::DictionaryValue* result = new base::DictionaryValue();
   result->SetString(kFontIdKey, font_name);
   result->SetString(kLevelOfControlKey, level_of_control);
   SetResult(result);
@@ -314,15 +314,17 @@
 }
 
 void FontSettingsGetFontListFunction::FontListHasLoaded(
-    scoped_ptr<ListValue> list) {
+    scoped_ptr<base::ListValue> list) {
   bool success = CopyFontsToResult(list.get());
   SendResponse(success);
 }
 
-bool FontSettingsGetFontListFunction::CopyFontsToResult(ListValue* fonts) {
-  scoped_ptr<ListValue> result(new ListValue());
-  for (ListValue::iterator it = fonts->begin(); it != fonts->end(); ++it) {
-    ListValue* font_list_value;
+bool FontSettingsGetFontListFunction::CopyFontsToResult(
+    base::ListValue* fonts) {
+  scoped_ptr<base::ListValue> result(new base::ListValue());
+  for (base::ListValue::iterator it = fonts->begin();
+       it != fonts->end(); ++it) {
+    base::ListValue* font_list_value;
     if (!(*it)->GetAsList(&font_list_value)) {
       NOTREACHED();
       return false;
@@ -340,7 +342,7 @@
       return false;
     }
 
-    DictionaryValue* font_name = new DictionaryValue();
+    base::DictionaryValue* font_name = new base::DictionaryValue();
     font_name->Set(kFontIdKey, Value::CreateStringValue(name));
     font_name->Set(kDisplayNameKey, Value::CreateStringValue(localized_name));
     result->Append(font_name);
@@ -376,7 +378,7 @@
                                                         GetPrefName(),
                                                         kIncognito);
 
-  DictionaryValue* result = new DictionaryValue();
+  base::DictionaryValue* result = new base::DictionaryValue();
   result->Set(GetKey(), pref->GetValue()->DeepCopy());
   result->SetString(kLevelOfControlKey, level_of_control);
   SetResult(result);
@@ -389,7 +391,7 @@
     return false;
   }
 
-  DictionaryValue* details = NULL;
+  base::DictionaryValue* details = NULL;
   EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &details));
 
   Value* value;
diff --git a/chrome/browser/extensions/api/history/history_api.cc b/chrome/browser/extensions/api/history/history_api.cc
index 474db65..e45e94b 100644
--- a/chrome/browser/extensions/api/history/history_api.cc
+++ b/chrome/browser/extensions/api/history/history_api.cc
@@ -14,7 +14,7 @@
 #include "base/prefs/pref_service.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/extensions/event_router.h"
 #include "chrome/browser/extensions/extension_system.h"
@@ -168,7 +168,7 @@
     Profile* profile,
     const history::URLVisitedDetails* details) {
   scoped_ptr<HistoryItem> history_item = GetHistoryItem(details->row);
-  scoped_ptr<ListValue> args = OnVisited::Create(*history_item);
+  scoped_ptr<base::ListValue> args = OnVisited::Create(*history_item);
 
   DispatchEvent(profile, kOnVisited, args.Pass());
 }
@@ -186,14 +186,14 @@
   }
   removed.urls.reset(urls);
 
-  scoped_ptr<ListValue> args = OnVisitRemoved::Create(removed);
+  scoped_ptr<base::ListValue> args = OnVisitRemoved::Create(removed);
   DispatchEvent(profile, kOnVisitRemoved, args.Pass());
 }
 
 void HistoryEventRouter::DispatchEvent(
     Profile* profile,
     const char* event_name,
-    scoped_ptr<ListValue> event_args) {
+    scoped_ptr<base::ListValue> event_args) {
   if (profile && extensions::ExtensionSystem::Get(profile)->event_router()) {
     scoped_ptr<extensions::Event> event(new extensions::Event(
         event_name, event_args.Pass()));
diff --git a/chrome/browser/extensions/api/history/history_apitest.cc b/chrome/browser/extensions/api/history/history_apitest.cc
index b690e0c..f2394e0 100644
--- a/chrome/browser/extensions/api/history/history_apitest.cc
+++ b/chrome/browser/extensions/api/history/history_apitest.cc
@@ -26,8 +26,6 @@
 
     host_resolver()->AddRule("www.a.com", "127.0.0.1");
     host_resolver()->AddRule("www.b.com", "127.0.0.1");
-
-    ASSERT_TRUE(StartTestServer());
   }
 
   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
@@ -38,11 +36,13 @@
 
 // Full text search indexing sometimes exceeds a timeout. (http://crbug/119505)
 IN_PROC_BROWSER_TEST_F(HistoryApiTest, DISABLED_MiscSearch) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionSubtest("history", "misc_search.html")) << message_;
 }
 
 // Same could happen here without the FTS (http://crbug/119505)
 IN_PROC_BROWSER_TEST_F(HistoryApiTest, DISABLED_TimedSearch) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionSubtest("history", "timed_search.html")) << message_;
 }
 
@@ -53,18 +53,21 @@
 #define MAYBE_Delete Delete
 #endif
 IN_PROC_BROWSER_TEST_F(HistoryApiTest, MAYBE_Delete) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionSubtest("history", "delete.html")) << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(HistoryApiTest, DeleteProhibited) {
   browser()->profile()->GetPrefs()->
       SetBoolean(prefs::kAllowDeletingBrowserHistory, false);
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionSubtest("history", "delete_prohibited.html")) <<
       message_;
 }
 
 // See crbug.com/79074
 IN_PROC_BROWSER_TEST_F(HistoryApiTest, DISABLED_GetVisits) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionSubtest("history", "get_visits.html")) << message_;
 }
 
@@ -77,11 +80,14 @@
 #endif
 
 IN_PROC_BROWSER_TEST_F(HistoryApiTest, MAYBE_SearchAfterAdd) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionSubtest("history", "search_after_add.html"))
       << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(HistoryApiTest, MostVisited) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
+
   // Add entries to the history database that we can query for (using the
   // extension history API for this doesn't work as it only adds URLs with
   // LINK transition type).
diff --git a/chrome/browser/extensions/api/i18n/i18n_apitest.cc b/chrome/browser/extensions/api/i18n/i18n_apitest.cc
index a255d1f..12c7142 100644
--- a/chrome/browser/extensions/api/i18n/i18n_apitest.cc
+++ b/chrome/browser/extensions/api/i18n/i18n_apitest.cc
@@ -10,15 +10,15 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/test/base/ui_test_utils.h"
-#include "net/test/spawned_test_server/spawned_test_server.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
 
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, I18N) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionTest("i18n")) << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, I18NUpdate) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
   // Create an Extension whose messages.json file will be updated.
   base::ScopedTempDir extension_dir;
   ASSERT_TRUE(extension_dir.CreateUniqueTempDir());
@@ -42,7 +42,8 @@
 
   // Test that the messages.json file is loaded and the i18n message is loaded.
   ui_test_utils::NavigateToURL(
-      browser(), test_server()->GetURL("file/extensions/test_file.html"));
+      browser(),
+      embedded_test_server()->GetURL("/extensions/test_file.html"));
   EXPECT_TRUE(catcher.GetNextResult());
 
   string16 title;
@@ -58,7 +59,8 @@
 
   // Check that the i18n message is also changed.
   ui_test_utils::NavigateToURL(
-      browser(), test_server()->GetURL("file/extensions/test_file.html"));
+      browser(),
+      embedded_test_server()->GetURL("/extensions/test_file.html"));
   EXPECT_TRUE(catcher.GetNextResult());
 
   ui_test_utils::GetCurrentTabTitle(browser(), &title);
diff --git a/chrome/browser/extensions/api/identity/identity_api.cc b/chrome/browser/extensions/api/identity/identity_api.cc
index cdcd4dc..3191610 100644
--- a/chrome/browser/extensions/api/identity/identity_api.cc
+++ b/chrome/browser/extensions/api/identity/identity_api.cc
@@ -18,6 +18,7 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/extensions/extension_function_dispatcher.h"
 #include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/policy/browser_policy_connector.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
@@ -31,10 +32,13 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
 #include "google_apis/gaia/gaia_constants.h"
+#include "google_apis/gaia/gaia_urls.h"
 #include "googleurl/src/gurl.h"
 
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/login/user_manager.h"
+#include "chrome/browser/chromeos/settings/device_oauth2_token_service.h"
+#include "chrome/browser/chromeos/settings/device_oauth2_token_service_factory.h"
 #endif
 
 namespace extensions {
@@ -88,7 +92,8 @@
   const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
 
   // Check that the necessary information is present in the manifest.
-  if (oauth2_info.client_id.empty()) {
+  oauth2_client_id_ = GetOAuth2ClientId();
+  if (oauth2_client_id_.empty()) {
     error_ = identity_constants::kInvalidClientId;
     return false;
   }
@@ -101,6 +106,14 @@
   // Balanced in CompleteFunctionWithResult|CompleteFunctionWithError
   AddRef();
 
+#if defined(OS_CHROMEOS)
+  if (chromeos::UserManager::Get()->IsLoggedInAsKioskApp() &&
+      g_browser_process->browser_policy_connector()->IsEnterpriseManaged()) {
+    StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_NONINTERACTIVE);
+    return true;
+  }
+#endif
+
   if (!HasLoginToken()) {
     if (!should_prompt_for_signin_) {
       error_ = identity_constants::kUserNotSignedIn;
@@ -206,11 +219,21 @@
       case IdentityTokenCacheValue::CACHE_STATUS_NOTFOUND:
 #if defined(OS_CHROMEOS)
         // Always force minting token for ChromeOS kiosk app.
-        if (chrome::IsRunningInForcedAppMode()) {
-          StartGaiaRequest(OAuth2MintTokenFlow::MODE_MINT_TOKEN_FORCE);
+        if (chromeos::UserManager::Get()->IsLoggedInAsKioskApp()) {
+          if (g_browser_process->browser_policy_connector()->
+                  IsEnterpriseManaged()) {
+            OAuth2TokenService::ScopeSet scope_set(oauth2_info.scopes.begin(),
+                                                   oauth2_info.scopes.end());
+            device_token_request_ =
+                chromeos::DeviceOAuth2TokenServiceFactory::Get()->StartRequest(
+                    scope_set, this);
+          } else {
+            StartGaiaRequest(OAuth2MintTokenFlow::MODE_MINT_TOKEN_FORCE);
+          }
           return;
         }
 #endif
+
         if (oauth2_info.auto_approve)
           // oauth2_info.auto_approve is protected by a whitelist in
           // _manifest_features.json hence only selected extensions take
@@ -330,8 +353,6 @@
       error = MapOAuth2ErrorToDescription(oauth_error);
       break;
 
-      // TODO(courage): load failure tests
-
     case GaiaWebAuthFlow::LOAD_FAILED:
       error = identity_constants::kPageLoadFailure;
       break;
@@ -362,6 +383,32 @@
   CompleteFunctionWithResult(access_token);
 }
 
+void IdentityGetAuthTokenFunction::OnGetTokenSuccess(
+    const OAuth2TokenService::Request* request,
+    const std::string& access_token,
+    const base::Time& expiration_time) {
+  DCHECK_EQ(device_token_request_.get(), request);
+  device_token_request_.reset();
+
+  const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
+  IdentityTokenCacheValue token(access_token,
+                                expiration_time - base::Time::Now());
+  IdentityAPI::GetFactoryInstance()->GetForProfile(profile())->SetCachedToken(
+      GetExtension()->id(), oauth2_info.scopes, token);
+
+  CompleteMintTokenFlow();
+  CompleteFunctionWithResult(access_token);
+}
+
+void IdentityGetAuthTokenFunction::OnGetTokenFailure(
+    const OAuth2TokenService::Request* request,
+    const GoogleServiceAuthError& error) {
+  DCHECK_EQ(device_token_request_.get(), request);
+  device_token_request_.reset();
+
+  OnGaiaFlowFailure(GaiaWebAuthFlow::SERVICE_AUTH_ERROR, error, std::string());
+}
+
 void IdentityGetAuthTokenFunction::StartGaiaRequest(
     OAuth2MintTokenFlow::Mode mode) {
   mint_token_flow_.reset(CreateMintTokenFlow(mode));
@@ -387,6 +434,7 @@
 OAuth2MintTokenFlow* IdentityGetAuthTokenFunction::CreateMintTokenFlow(
     OAuth2MintTokenFlow::Mode mode) {
   const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
+
   OAuth2MintTokenFlow* mint_token_flow =
       new OAuth2MintTokenFlow(
           profile()->GetRequestContext(),
@@ -394,7 +442,7 @@
           OAuth2MintTokenFlow::Parameters(
               refresh_token_,
               GetExtension()->id(),
-              oauth2_info.client_id,
+              oauth2_client_id_,
               oauth2_info.scopes,
               mode));
 #if defined(OS_CHROMEOS)
@@ -429,6 +477,19 @@
     return std::string(identity_constants::kAuthFailure) + error;
 }
 
+std::string IdentityGetAuthTokenFunction::GetOAuth2ClientId() const {
+  const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
+  std::string client_id = oauth2_info.client_id;
+
+  // Component apps using auto_approve may use Chrome's client ID by
+  // omitting the field.
+  if (client_id.empty() && GetExtension()->location() == Manifest::COMPONENT &&
+      oauth2_info.auto_approve) {
+    client_id = GaiaUrls::GetInstance()->oauth2_chrome_client_id();
+  }
+  return client_id;
+}
+
 IdentityRemoveCachedAuthTokenFunction::IdentityRemoveCachedAuthTokenFunction() {
 }
 
diff --git a/chrome/browser/extensions/api/identity/identity_api.h b/chrome/browser/extensions/api/identity/identity_api.h
index b2b85c3..a04a01d 100644
--- a/chrome/browser/extensions/api/identity/identity_api.h
+++ b/chrome/browser/extensions/api/identity/identity_api.h
@@ -19,10 +19,12 @@
 #include "chrome/browser/extensions/api/identity/web_auth_flow.h"
 #include "chrome/browser/extensions/api/profile_keyed_api_factory.h"
 #include "chrome/browser/extensions/extension_function.h"
+#include "chrome/browser/signin/oauth2_token_service.h"
 #include "chrome/browser/signin/signin_global_error.h"
 #include "google_apis/gaia/oauth2_mint_token_flow.h"
 
 class GoogleServiceAuthError;
+class MockGetAuthTokenFunction;
 class Profile;
 class SigninManagerBase;
 
@@ -65,7 +67,8 @@
                                      public GaiaWebAuthFlow::Delegate,
                                      public IdentityMintRequestQueue::Request,
                                      public OAuth2MintTokenFlow::Delegate,
-                                     public IdentitySigninFlow::Delegate {
+                                     public IdentitySigninFlow::Delegate,
+                                     public OAuth2TokenService::Consumer {
  public:
   DECLARE_EXTENSION_FUNCTION("identity.getAuthToken",
                              EXPERIMENTAL_IDENTITY_GETAUTHTOKEN);
@@ -76,7 +79,10 @@
   virtual ~IdentityGetAuthTokenFunction();
 
  private:
-  friend class GetAuthTokenFunctionTest;
+  FRIEND_TEST_ALL_PREFIXES(GetAuthTokenFunctionTest,
+                           ComponentWithChromeClientId);
+  FRIEND_TEST_ALL_PREFIXES(GetAuthTokenFunctionTest,
+                           ComponentWithNormalClientId);
   friend class MockGetAuthTokenFunction;
 
   // ExtensionFunction:
@@ -113,6 +119,13 @@
   virtual void OnGaiaFlowCompleted(const std::string& access_token,
                                    const std::string& expiration) OVERRIDE;
 
+  // OAuth2TokenService::Consumer implementation:
+  virtual void OnGetTokenSuccess(const OAuth2TokenService::Request* request,
+                                 const std::string& access_token,
+                                 const base::Time& expiration_time) OVERRIDE;
+  virtual void OnGetTokenFailure(const OAuth2TokenService::Request* request,
+                                 const GoogleServiceAuthError& error) OVERRIDE;
+
   // Starts a mint token request to GAIA.
   void StartGaiaRequest(OAuth2MintTokenFlow::Mode mode);
 
@@ -130,17 +143,21 @@
   // developer in chrome.runtime.lastError.
   std::string MapOAuth2ErrorToDescription(const std::string& error);
 
+  std::string GetOAuth2ClientId() const;
+
   bool should_prompt_for_scopes_;
   IdentityMintRequestQueue::MintType mint_token_flow_type_;
   scoped_ptr<OAuth2MintTokenFlow> mint_token_flow_;
   std::string refresh_token_;
   bool should_prompt_for_signin_;
 
+  std::string oauth2_client_id_;
   // When launched in interactive mode, and if there is no existing grant,
   // a permissions prompt will be popped up to the user.
   IssueAdviceInfo issue_advice_;
   scoped_ptr<GaiaWebAuthFlow> gaia_web_auth_flow_;
   scoped_ptr<IdentitySigninFlow> signin_flow_;
+  scoped_ptr<OAuth2TokenService::Request> device_token_request_;
 };
 
 class IdentityRemoveCachedAuthTokenFunction : public SyncExtensionFunction {
diff --git a/chrome/browser/extensions/api/identity/identity_apitest.cc b/chrome/browser/extensions/api/identity/identity_apitest.cc
index 73e871d..8659114 100644
--- a/chrome/browser/extensions/api/identity/identity_apitest.cc
+++ b/chrome/browser/extensions/api/identity/identity_apitest.cc
@@ -315,7 +315,8 @@
   enum OAuth2Fields {
     NONE = 0,
     CLIENT_ID = 1,
-    SCOPES = 2
+    SCOPES = 2,
+    AS_COMPONENT = 4
   };
 
   virtual ~GetAuthTokenFunctionTest() {}
@@ -323,10 +324,17 @@
   // Helper to create an extension with specific OAuth2Info fields set.
   // |fields_to_set| should be computed by using fields of Oauth2Fields enum.
   const Extension* CreateExtension(int fields_to_set) {
-    const Extension* ext = LoadExtension(
-        test_data_dir_.AppendASCII("platform_apps/oauth2"));
-    OAuth2Info& oauth2_info = const_cast<OAuth2Info&>(
-        OAuth2Info::GetOAuth2Info(ext));
+    const Extension* ext;
+    base::FilePath manifest_path =
+        test_data_dir_.AppendASCII("platform_apps/oauth2");
+    base::FilePath component_manifest_path =
+        test_data_dir_.AppendASCII("packaged_app/component_oauth2");
+    if ((fields_to_set & AS_COMPONENT) == 0)
+      ext = LoadExtension(manifest_path);
+    else
+      ext = LoadExtensionAsComponent(component_manifest_path);
+    OAuth2Info& oauth2_info =
+        const_cast<OAuth2Info&>(OAuth2Info::GetOAuth2Info(ext));
     if ((fields_to_set & CLIENT_ID) != 0)
       oauth2_info.client_id = "client1";
     if ((fields_to_set & SCOPES) != 0) {
@@ -934,6 +942,25 @@
                                      oauth2_info.scopes).status());
 }
 
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ComponentWithChromeClientId) {
+  scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
+  scoped_refptr<const Extension> extension(
+      CreateExtension(SCOPES | AS_COMPONENT));
+  func->set_extension(extension.get());
+  const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(extension.get());
+  EXPECT_TRUE(oauth2_info.client_id.empty());
+  EXPECT_FALSE(func->GetOAuth2ClientId().empty());
+  EXPECT_NE("client1", func->GetOAuth2ClientId());
+}
+
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ComponentWithNormalClientId) {
+  scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
+  scoped_refptr<const Extension> extension(
+      CreateExtension(CLIENT_ID | SCOPES | AS_COMPONENT));
+  func->set_extension(extension.get());
+  EXPECT_EQ("client1", func->GetOAuth2ClientId());
+}
+
 class RemoveCachedAuthTokenFunctionTest : public ExtensionBrowserTest {
  protected:
   bool InvalidateDefaultToken() {
diff --git a/chrome/browser/extensions/api/identity/web_auth_flow.cc b/chrome/browser/extensions/api/identity/web_auth_flow.cc
index b0ad761..4a8f2ad 100644
--- a/chrome/browser/extensions/api/identity/web_auth_flow.cc
+++ b/chrome/browser/extensions/api/identity/web_auth_flow.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/extensions/api/identity/web_auth_flow.h"
 
+#include "apps/shell_window.h"
 #include "base/base64.h"
 #include "base/location.h"
 #include "base/message_loop.h"
@@ -15,7 +16,6 @@
 #include "chrome/browser/extensions/extension_system.h"
 #include "chrome/browser/extensions/extension_system.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/extensions/shell_window.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "content/public/browser/navigation_details.h"
 #include "content/public/browser/navigation_entry.h"
@@ -30,6 +30,7 @@
 #include "googleurl/src/gurl.h"
 #include "grit/browser_resources.h"
 
+using apps::ShellWindow;
 using content::RenderViewHost;
 using content::ResourceRedirectDetails;
 using content::WebContents;
@@ -77,7 +78,7 @@
   DCHECK(success);
 
   // identityPrivate.onWebFlowRequest(shell_window_key, provider_url_, mode_)
-  scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   args->AppendString(shell_window_key_);
   args->AppendString(provider_url_.spec());
   if (mode_ == WebAuthFlow::INTERACTIVE)
@@ -124,6 +125,8 @@
   }
 }
 
+void WebAuthFlow::OnShellWindowIconChanged(ShellWindow* shell_window) {}
+
 void WebAuthFlow::OnShellWindowRemoved(ShellWindow* shell_window) {
   if (shell_window->window_key() == shell_window_key_ &&
       shell_window->extension()->id() == extension_misc::kIdentityApiUiAppId) {
diff --git a/chrome/browser/extensions/api/identity/web_auth_flow.h b/chrome/browser/extensions/api/identity/web_auth_flow.h
index df6c0f9..cbe42c6 100644
--- a/chrome/browser/extensions/api/identity/web_auth_flow.h
+++ b/chrome/browser/extensions/api/identity/web_auth_flow.h
@@ -92,9 +92,10 @@
   friend class ::WebAuthFlowTest;
 
   // ShellWindowRegistry::Observer implementation.
-  virtual void OnShellWindowAdded(ShellWindow* shell_window) OVERRIDE;
-  virtual void OnShellWindowIconChanged(ShellWindow* shell_window) OVERRIDE {}
-  virtual void OnShellWindowRemoved(ShellWindow* shell_window) OVERRIDE;
+  virtual void OnShellWindowAdded(apps::ShellWindow* shell_window) OVERRIDE;
+  virtual void OnShellWindowIconChanged(apps::ShellWindow* shell_window)
+      OVERRIDE;
+  virtual void OnShellWindowRemoved(apps::ShellWindow* shell_window) OVERRIDE;
 
   // NotificationObserver implementation.
   virtual void Observe(int type,
@@ -132,7 +133,7 @@
   GURL provider_url_;
   Mode mode_;
 
-  ShellWindow* shell_window_;
+  apps::ShellWindow* shell_window_;
   std::string shell_window_key_;
   bool embedded_window_created_;
 
diff --git a/chrome/browser/extensions/api/identity_private/identity_private_api.cc b/chrome/browser/extensions/api/identity_private/identity_private_api.cc
index 0d2d52c..d1e3270 100644
--- a/chrome/browser/extensions/api/identity_private/identity_private_api.cc
+++ b/chrome/browser/extensions/api/identity_private/identity_private_api.cc
@@ -19,7 +19,7 @@
 IdentityPrivateGetResourcesFunction::~IdentityPrivateGetResourcesFunction() {}
 
 bool IdentityPrivateGetResourcesFunction::RunImpl() {
-  DictionaryValue* result = new DictionaryValue;
+  base::DictionaryValue* result = new base::DictionaryValue;
 
   result->SetString("IDR_CLOSE_DIALOG",
                     webui::GetBitmapDataUrlFromResource(IDR_CLOSE_DIALOG));
diff --git a/chrome/browser/extensions/api/idle/idle_manager.cc b/chrome/browser/extensions/api/idle/idle_manager.cc
index c907b81..bf02c33 100644
--- a/chrome/browser/extensions/api/idle/idle_manager.cc
+++ b/chrome/browser/extensions/api/idle/idle_manager.cc
@@ -49,7 +49,7 @@
 
 void DefaultEventDelegate::OnStateChanged(const std::string& extension_id,
                                           IdleState new_state) {
-  scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   args->Append(IdleManager::CreateIdleValue(new_state));
   scoped_ptr<Event> event(new Event(keys::kOnStateChanged, args.Pass()));
   event->restrict_to_profile = profile_;
diff --git a/chrome/browser/extensions/api/idle/idle_manager.h b/chrome/browser/extensions/api/idle/idle_manager.h
index 96d8723..91108c2 100644
--- a/chrome/browser/extensions/api/idle/idle_manager.h
+++ b/chrome/browser/extensions/api/idle/idle_manager.h
@@ -12,7 +12,7 @@
 #include "base/gtest_prod_util.h"
 #include "base/memory/weak_ptr.h"
 #include "base/threading/thread_checker.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/extensions/event_router.h"
 #include "chrome/browser/idle.h"
 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
diff --git a/chrome/browser/extensions/api/idltest/idltest_api.cc b/chrome/browser/extensions/api/idltest/idltest_api.cc
index 744aa79..98ef9b3 100644
--- a/chrome/browser/extensions/api/idltest/idltest_api.cc
+++ b/chrome/browser/extensions/api/idltest/idltest_api.cc
@@ -10,8 +10,8 @@
 
 namespace {
 
-ListValue* CopyBinaryValueToIntegerList(const BinaryValue* input) {
-  ListValue* output = new ListValue();
+base::ListValue* CopyBinaryValueToIntegerList(const BinaryValue* input) {
+  base::ListValue* output = new base::ListValue();
   const char* input_buffer = input->GetBuffer();
   for (size_t i = 0; i < input->GetSize(); i++) {
     output->Append(Value::CreateIntegerValue(input_buffer[i]));
diff --git a/chrome/browser/extensions/api/input/input.cc b/chrome/browser/extensions/api/input/input.cc
index f0eecbe..b4d264f 100644
--- a/chrome/browser/extensions/api/input/input.cc
+++ b/chrome/browser/extensions/api/input/input.cc
@@ -4,17 +4,15 @@
 
 #include "chrome/browser/extensions/api/input/input.h"
 
-#include <string>
-
 #include "base/lazy_instance.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/strings/string16.h"
 #include "chrome/browser/extensions/extension_function_registry.h"
 #include "content/public/browser/browser_thread.h"
 #include "ui/base/events/event.h"
 
 #if defined(USE_ASH)
 #include "ash/shell.h"
-#include "ui/aura/root_window.h"
 #include "ui/keyboard/keyboard_util.h"
 #endif
 
@@ -27,19 +25,14 @@
 
 namespace extensions {
 
-bool SendKeyboardEventInputFunction::RunImpl() {
+bool InsertTextInputFunction::RunImpl() {
 #if defined(USE_ASH)
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
 
-  scoped_ptr<ui::KeyEvent> event(
-      keyboard::KeyEventFromArgs(args_.get(), &error_));
-  if (!event)
-    return false;
+  string16 text;
+  EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &text));
 
-  ash::Shell::GetActiveRootWindow()->AsRootWindowHostDelegate()->OnHostKeyEvent(
-      event.get());
-
-  return true;
+  return keyboard::InsertText(text, ash::Shell::GetPrimaryRootWindow());
 #endif
   error_ = kNotYetImplementedError;
   return false;
@@ -48,7 +41,7 @@
 InputAPI::InputAPI(Profile* profile) {
   ExtensionFunctionRegistry* registry =
       ExtensionFunctionRegistry::GetInstance();
-  registry->RegisterFunction<SendKeyboardEventInputFunction>();
+  registry->RegisterFunction<InsertTextInputFunction>();
 }
 
 InputAPI::~InputAPI() {
diff --git a/chrome/browser/extensions/api/input/input.h b/chrome/browser/extensions/api/input/input.h
index 51cae3a..4cdf3fa 100644
--- a/chrome/browser/extensions/api/input/input.h
+++ b/chrome/browser/extensions/api/input/input.h
@@ -13,14 +13,14 @@
 
 namespace extensions {
 
-class SendKeyboardEventInputFunction : public SyncExtensionFunction {
+class InsertTextInputFunction : public SyncExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION(
-      "experimental.input.virtualKeyboard.sendKeyboardEvent",
-      EXPERIMENTAL_INPUT_VIRTUALKEYBOARD_SENDKEYBOARDEVENT);
+      "experimental.input.virtualKeyboard.insertText",
+      EXPERIMENTAL_INPUT_VIRTUALKEYBOARD_INSERTTEXT);
 
  protected:
-  virtual ~SendKeyboardEventInputFunction() {}
+  virtual ~InsertTextInputFunction() {}
 
   // ExtensionFunction:
   virtual bool RunImpl() OVERRIDE;
diff --git a/chrome/browser/extensions/api/input/input_apitest.cc b/chrome/browser/extensions/api/input/input_apitest.cc
deleted file mode 100644
index cb15dcf..0000000
--- a/chrome/browser/extensions/api/input/input_apitest.cc
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/extensions/extension_apitest.h"
-#include "chrome/common/chrome_switches.h"
-
-// Fails on Windows, but we're not really supporting windows yet.
-#if defined(USE_ASH) && defined(USE_AURA) && !defined(OS_WIN)
-IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Input) {
-  CommandLine::ForCurrentProcess()->AppendSwitch(
-      switches::kEnableExperimentalExtensionApis);
-
-  ASSERT_TRUE(RunExtensionTest("input")) << message_;
-}
-#endif
diff --git a/chrome/browser/extensions/api/input_ime/input_ime_api.cc b/chrome/browser/extensions/api/input_ime/input_ime_api.cc
index c33eff7..0e4845b 100644
--- a/chrome/browser/extensions/api/input_ime/input_ime_api.cc
+++ b/chrome/browser/extensions/api/input_ime/input_ime_api.cc
@@ -36,10 +36,10 @@
 const char kErrorUpdateMenuItemsFail[] = "Could not update menu Items";
 
 bool ReadMenuItems(
-    ListValue* menu_items,
+    base::ListValue* menu_items,
     std::vector<chromeos::InputMethodEngine::MenuItem>* output) {
   for (size_t i = 0; i < menu_items->GetSize(); ++i) {
-    DictionaryValue* item_dict;
+    base::DictionaryValue* item_dict;
     if (!menu_items->GetDictionary(i, &item_dict)) {
       return false;
     }
@@ -118,7 +118,7 @@
     output->back().modified = modified;
 
     if (item_dict->HasKey(keys::kItemsKey)) {
-      ListValue* sub_list;
+      base::ListValue* sub_list;
       if (!item_dict->GetList(keys::kItemsKey, &sub_list)) {
         return false;
       }
@@ -135,7 +135,7 @@
 static void DispatchEventToExtension(Profile* profile,
                                      const std::string& extension_id,
                                      const std::string& event_name,
-                                     scoped_ptr<ListValue> args) {
+                                     scoped_ptr<base::ListValue> args) {
   scoped_ptr<extensions::Event> event(new extensions::Event(
       event_name, args.Pass()));
   event->restrict_to_profile = profile;
@@ -176,7 +176,7 @@
     if (profile_ == NULL || extension_id_.empty())
       return;
 
-    scoped_ptr<base::ListValue> args(new ListValue());
+    scoped_ptr<base::ListValue> args(new base::ListValue());
     args->Append(Value::CreateStringValue(engine_id));
 
     DispatchEventToExtension(profile_, extension_id_,
@@ -187,7 +187,7 @@
     if (profile_ == NULL || extension_id_.empty())
       return;
 
-    scoped_ptr<base::ListValue> args(new ListValue());
+    scoped_ptr<base::ListValue> args(new base::ListValue());
     args->Append(Value::CreateStringValue(engine_id));
 
     DispatchEventToExtension(profile_, extension_id_,
@@ -199,11 +199,11 @@
     if (profile_ == NULL || extension_id_.empty())
       return;
 
-    DictionaryValue* dict = new DictionaryValue();
+    base::DictionaryValue* dict = new base::DictionaryValue();
     dict->SetInteger("contextID", context.id);
     dict->SetString("type", context.type);
 
-    scoped_ptr<base::ListValue> args(new ListValue());
+    scoped_ptr<base::ListValue> args(new base::ListValue());
     args->Append(dict);
 
     DispatchEventToExtension(profile_, extension_id_,
@@ -214,7 +214,7 @@
     if (profile_ == NULL || extension_id_.empty())
       return;
 
-    scoped_ptr<base::ListValue> args(new ListValue());
+    scoped_ptr<base::ListValue> args(new base::ListValue());
     args->Append(Value::CreateIntegerValue(context_id));
 
     DispatchEventToExtension(profile_, extension_id_,
@@ -226,11 +226,11 @@
     if (profile_ == NULL || extension_id_.empty())
       return;
 
-    DictionaryValue* dict = new DictionaryValue();
+    base::DictionaryValue* dict = new base::DictionaryValue();
     dict->SetInteger("contextID", context.id);
     dict->SetString("type", context.type);
 
-    scoped_ptr<base::ListValue> args(new ListValue());
+    scoped_ptr<base::ListValue> args(new base::ListValue());
     args->Append(dict);
 
     DispatchEventToExtension(profile_, extension_id_,
@@ -248,7 +248,7 @@
         extensions::InputImeEventRouter::GetInstance()->AddRequest(engine_id,
                                                                    key_data);
 
-    DictionaryValue* dict = new DictionaryValue();
+    base::DictionaryValue* dict = new base::DictionaryValue();
     dict->SetString("type", event.type);
     dict->SetString("requestId", request_id);
     dict->SetString("key", event.key);
@@ -258,7 +258,7 @@
     dict->SetBoolean("shiftKey", event.shift_key);
     dict->SetBoolean("capsLock", event.caps_lock);
 
-    scoped_ptr<base::ListValue> args(new ListValue());
+    scoped_ptr<base::ListValue> args(new base::ListValue());
     args->Append(Value::CreateStringValue(engine_id));
     args->Append(dict);
 
@@ -273,7 +273,7 @@
     if (profile_ == NULL || extension_id_.empty())
       return;
 
-    scoped_ptr<base::ListValue> args(new ListValue());
+    scoped_ptr<base::ListValue> args(new base::ListValue());
     args->Append(Value::CreateStringValue(engine_id));
     args->Append(Value::CreateIntegerValue(candidate_id));
     switch (button) {
@@ -301,7 +301,7 @@
     if (profile_ == NULL || extension_id_.empty())
       return;
 
-    scoped_ptr<base::ListValue> args(new ListValue());
+    scoped_ptr<base::ListValue> args(new base::ListValue());
     args->Append(Value::CreateStringValue(engine_id));
     args->Append(Value::CreateStringValue(menu_id));
 
@@ -315,12 +315,12 @@
                                         int anchor_pos) OVERRIDE {
     if (profile_ == NULL || extension_id_.empty())
       return;
-    DictionaryValue* dict = new DictionaryValue();
+    base::DictionaryValue* dict = new base::DictionaryValue();
     dict->SetString("text", text);
     dict->SetInteger("focus", cursor_pos);
     dict->SetInteger("anchor", anchor_pos);
 
-    scoped_ptr<ListValue> args(new ListValue);
+    scoped_ptr<ListValue> args(new base::ListValue);
     args->Append(Value::CreateStringValue(engine_id));
     args->Append(dict);
 
@@ -331,7 +331,7 @@
   virtual void OnReset(const std::string& engine_id) OVERRIDE {
     if (profile_ == NULL || extension_id_.empty())
       return;
-    scoped_ptr<base::ListValue> args(new ListValue());
+    scoped_ptr<base::ListValue> args(new base::ListValue());
     args->Append(Value::CreateStringValue(engine_id));
 
     DispatchEventToExtension(profile_, extension_id_,
@@ -506,7 +506,7 @@
     return true;
   }
 
-  DictionaryValue* args;
+  base::DictionaryValue* args;
   EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args));
   int context_id;
   std::string text;
@@ -533,12 +533,12 @@
   }
 
   if (args->HasKey(keys::kSegmentsKey)) {
-    ListValue* segment_list = NULL;
+    base::ListValue* segment_list = NULL;
     EXTENSION_FUNCTION_VALIDATE(args->GetList(keys::kSegmentsKey,
                                               &segment_list));
 
     for (size_t i = 0; i < segment_list->GetSize(); ++i) {
-      DictionaryValue* segment = NULL;
+      base::DictionaryValue* segment = NULL;
       if (!segment_list->GetDictionary(i, &segment))
         continue;
 
@@ -581,7 +581,7 @@
     return true;
   }
 
-  DictionaryValue* args;
+  base::DictionaryValue* args;
   EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args));
   int context_id;
 
@@ -605,7 +605,7 @@
     return true;
   }
 
-  DictionaryValue* args;
+  base::DictionaryValue* args;
   EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args));
   int context_id;
   std::string text;
@@ -623,7 +623,7 @@
 }
 
 bool SetCandidateWindowPropertiesFunction::RunImpl() {
-  DictionaryValue* args;
+  base::DictionaryValue* args;
   EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args));
 
   std::string engine_id;
@@ -636,7 +636,7 @@
     return true;
   }
 
-  DictionaryValue* properties;
+  base::DictionaryValue* properties;
   EXTENSION_FUNCTION_VALIDATE(args->GetDictionary(keys::kPropertiesKey,
                                                   &properties));
 
@@ -707,10 +707,10 @@
 
 #if defined(OS_CHROMEOS)
 bool SetCandidatesFunction::ReadCandidates(
-    ListValue* candidates,
+    base::ListValue* candidates,
     std::vector<chromeos::InputMethodEngine::Candidate>* output) {
   for (size_t i = 0; i < candidates->GetSize(); ++i) {
-    DictionaryValue* candidate_dict;
+    base::DictionaryValue* candidate_dict;
     EXTENSION_FUNCTION_VALIDATE(candidates->GetDictionary(i, &candidate_dict));
 
     std::string candidate;
@@ -734,7 +734,7 @@
     }
 
     if (candidate_dict->HasKey(keys::kUsageKey)) {
-      DictionaryValue* usage_dict;
+      base::DictionaryValue* usage_dict;
       EXTENSION_FUNCTION_VALIDATE(candidate_dict->GetDictionary(keys::kUsageKey,
                                                                 &usage_dict));
       EXTENSION_FUNCTION_VALIDATE(usage_dict->GetString(keys::kUsageTitleKey,
@@ -751,7 +751,7 @@
     output->back().usage = usage_entry;
 
     if (candidate_dict->HasKey(keys::kCandidatesKey)) {
-      ListValue* sub_list;
+      base::ListValue* sub_list;
       EXTENSION_FUNCTION_VALIDATE(candidate_dict->GetList(keys::kCandidatesKey,
                                                           &sub_list));
       if (!ReadCandidates(sub_list, &(output->back().candidates))) {
@@ -772,7 +772,7 @@
     return true;
   }
 
-  DictionaryValue* args;
+  base::DictionaryValue* args;
   EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args));
 
   int context_id;
@@ -781,7 +781,7 @@
   EXTENSION_FUNCTION_VALIDATE(args->GetInteger(keys::kContextIdKey,
                                                      &context_id));
 
-  ListValue* candidate_list;
+  base::ListValue* candidate_list;
   EXTENSION_FUNCTION_VALIDATE(args->GetList(keys::kCandidatesKey,
                                             &candidate_list));
   if (!ReadCandidates(candidate_list, &candidates)) {
@@ -806,7 +806,7 @@
     return true;
   }
 
-  DictionaryValue* args;
+  base::DictionaryValue* args;
   EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args));
   int context_id;
   int candidate_id;
@@ -825,7 +825,7 @@
 }
 
 bool SetMenuItemsFunction::RunImpl() {
-  DictionaryValue* args;
+  base::DictionaryValue* args;
   EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args));
 
   std::string engine_id;
@@ -838,7 +838,7 @@
     return false;
   }
 
-  ListValue* items;
+  base::ListValue* items;
   EXTENSION_FUNCTION_VALIDATE(args->GetList(keys::kItemsKey, &items));
 
   std::vector<chromeos::InputMethodEngine::MenuItem> menu_items;
@@ -851,7 +851,7 @@
 }
 
 bool UpdateMenuItemsFunction::RunImpl() {
-  DictionaryValue* args;
+  base::DictionaryValue* args;
   EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args));
 
   std::string engine_id;
@@ -864,7 +864,7 @@
     return false;
   }
 
-  ListValue* items;
+  base::ListValue* items;
   EXTENSION_FUNCTION_VALIDATE(args->GetList(keys::kItemsKey, &items));
 
   std::vector<chromeos::InputMethodEngine::MenuItem> menu_items;
@@ -877,7 +877,7 @@
 }
 
 bool DeleteSurroundingTextFunction::RunImpl() {
-  DictionaryValue* args;
+  base::DictionaryValue* args;
   EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args));
 
   std::string engine_id;
diff --git a/chrome/browser/extensions/api/input_ime/input_ime_api.h b/chrome/browser/extensions/api/input_ime/input_ime_api.h
index aee6111..e744195 100644
--- a/chrome/browser/extensions/api/input_ime/input_ime_api.h
+++ b/chrome/browser/extensions/api/input_ime/input_ime_api.h
@@ -128,7 +128,7 @@
 
  private:
   bool ReadCandidates(
-      ListValue* candidates,
+      base::ListValue* candidates,
       std::vector<chromeos::InputMethodEngine::Candidate>* output);
 };
 
diff --git a/chrome/browser/extensions/api/location/location_api.cc b/chrome/browser/extensions/api/location/location_api.cc
index d547879..41a9917 100644
--- a/chrome/browser/extensions/api/location/location_api.cc
+++ b/chrome/browser/extensions/api/location/location_api.cc
@@ -6,6 +6,7 @@
 
 #include "chrome/browser/extensions/api/location/location_manager.h"
 #include "chrome/common/extensions/api/location.h"
+#include "extensions/common/error_utils.h"
 
 // TODO(vadimt): add tests.
 
@@ -15,14 +16,43 @@
 
 namespace extensions {
 
+const char kMustBePositive[] = "'*' must be 0 or greater.";
+const char kMinDistanceInMeters[] = "minDistanceInMeters";
+const char kMinTimeInMilliseconds[] = "minTimeInMilliseconds";
+
+bool IsNegative(double* value) {
+  return value && *value < 0.0;
+}
+
 bool LocationWatchLocationFunction::RunImpl() {
   scoped_ptr<WatchLocation::Params> params(
       WatchLocation::Params::Create(*args_));
   EXTENSION_FUNCTION_VALIDATE(params.get());
 
-  // TODO(vadimt): validate and use params->request_info.
+  double* min_distance_in_meters =
+      params->request_info.min_distance_in_meters.get();
+  if (IsNegative(min_distance_in_meters)) {
+    error_ = ErrorUtils::FormatErrorMessage(
+        kMustBePositive,
+        kMinDistanceInMeters);
+    return false;
+  }
+
+  double* min_time_in_milliseconds =
+      params->request_info.min_time_in_milliseconds.get();
+  if (IsNegative(min_time_in_milliseconds)) {
+    error_ = ErrorUtils::FormatErrorMessage(
+        kMustBePositive,
+        kMinTimeInMilliseconds);
+    return false;
+  }
+
+  // TODO(vadimt): validate and use params->request_info.maximumAge
   LocationManager::Get(profile())->AddLocationRequest(
-      extension_id(), params->name);
+      extension_id(),
+      params->name,
+      min_distance_in_meters,
+      min_time_in_milliseconds);
 
   return true;
 }
diff --git a/chrome/browser/extensions/api/location/location_manager.cc b/chrome/browser/extensions/api/location/location_manager.cc
index 509494e..173a44a 100644
--- a/chrome/browser/extensions/api/location/location_manager.cc
+++ b/chrome/browser/extensions/api/location/location_manager.cc
@@ -4,8 +4,12 @@
 
 #include "chrome/browser/extensions/api/location/location_manager.h"
 
+#include <math.h>
+#include <vector>
+
 #include "base/bind.h"
 #include "base/lazy_instance.h"
+#include "base/time/time.h"
 #include "chrome/browser/extensions/event_router.h"
 #include "chrome/browser/extensions/extension_system.h"
 #include "chrome/common/chrome_notification_types.h"
@@ -25,6 +29,115 @@
 
 namespace location = api::location;
 
+namespace updatepolicy {
+
+// Base class for all update policies for sending a location.
+class UpdatePolicy : public base::RefCounted<UpdatePolicy> {
+ public:
+  explicit UpdatePolicy() {}
+
+  // True if the caller should send an update based off of this policy.
+  virtual bool ShouldSendUpdate(const content::Geoposition&) const = 0;
+
+  // Updates any policy state on reporting a position.
+  virtual void OnPositionReported(const content::Geoposition&) = 0;
+
+ protected:
+  virtual ~UpdatePolicy() {}
+
+ private:
+  friend class base::RefCounted<UpdatePolicy>;
+  DISALLOW_COPY_AND_ASSIGN(UpdatePolicy);
+};
+
+// A policy that controls sending an update below a distance threshold.
+class DistanceBasedUpdatePolicy : public UpdatePolicy {
+ public:
+  explicit DistanceBasedUpdatePolicy(double distance_update_threshold_meters) :
+      distance_update_threshold_meters_(distance_update_threshold_meters)
+  {}
+
+  // UpdatePolicy Implementation
+  virtual bool ShouldSendUpdate(const content::Geoposition& position) const
+      OVERRIDE {
+    return !last_updated_position_.Validate() ||
+        Distance(position.latitude,
+                 position.longitude,
+                 last_updated_position_.latitude,
+                 last_updated_position_.longitude) >
+            distance_update_threshold_meters_;
+  }
+
+  virtual void OnPositionReported(const content::Geoposition& position)
+      OVERRIDE {
+    last_updated_position_ = position;
+  }
+
+ private:
+  virtual ~DistanceBasedUpdatePolicy() {}
+
+  // Calculates the distance between two latitude and longitude points.
+  static double Distance(const double latitude1,
+                         const double longitude1,
+                         const double latitude2,
+                         const double longitude2) {
+    // The earth has a radius of about 6371 km.
+    const double kRadius = 6371000;
+    const double kPi = 3.14159265358979323846;
+    const double kDegreesToRadians = kPi / 180.0;
+
+    // Conversions
+    const double latitude1Rad = latitude1 * kDegreesToRadians;
+    const double latitude2Rad = latitude2 * kDegreesToRadians;
+    const double latitudeDistRad = latitude2Rad - latitude1Rad;
+    const double longitudeDistRad = (longitude2 - longitude1) *
+                                    kDegreesToRadians;
+
+    // The Haversine Formula determines the great circle distance
+    // between two points on a sphere.
+    const double chordLengthSquared = pow(sin(latitudeDistRad / 2.0), 2) +
+                                      (pow(sin(longitudeDistRad / 2.0), 2) *
+                                       cos(latitude1Rad) *
+                                       cos(latitude2Rad));
+    const double angularDistance = 2.0 * atan2(sqrt(chordLengthSquared),
+                                               sqrt(1.0 - chordLengthSquared));
+    return kRadius * angularDistance;
+  }
+
+  const double distance_update_threshold_meters_;
+  content::Geoposition last_updated_position_;
+
+  DISALLOW_COPY_AND_ASSIGN(DistanceBasedUpdatePolicy);
+};
+
+// A policy that controls sending an update above a time threshold.
+class TimeBasedUpdatePolicy : public UpdatePolicy {
+ public:
+  explicit TimeBasedUpdatePolicy(double time_between_updates_ms) :
+      time_between_updates_ms_(time_between_updates_ms)
+  {}
+
+  // UpdatePolicy Implementation
+  virtual bool ShouldSendUpdate(const content::Geoposition&) const OVERRIDE {
+    return (base::Time::Now() - last_update_time_).InMilliseconds() >
+        time_between_updates_ms_;
+  }
+
+  virtual void OnPositionReported(const content::Geoposition&) OVERRIDE {
+    last_update_time_ = base::Time::Now();
+  }
+
+ private:
+  virtual ~TimeBasedUpdatePolicy() {}
+
+  base::Time last_update_time_;
+  const double time_between_updates_ms_;
+
+  DISALLOW_COPY_AND_ASSIGN(TimeBasedUpdatePolicy);
+};
+
+} // namespace updatepolicy
+
 // Request created by chrome.location.watchLocation() call.
 // Lives in the IO thread, except for the constructor.
 class LocationRequest
@@ -34,7 +147,9 @@
   LocationRequest(
       const base::WeakPtr<LocationManager>& location_manager,
       const std::string& extension_id,
-      const std::string& request_name);
+      const std::string& request_name,
+      const double* distance_update_threshold_meters,
+      const double* time_between_updates_ms);
 
   // Finishes the necessary setup for this object.
   // Call this method immediately after taking a strong reference
@@ -61,6 +176,13 @@
 
   void OnLocationUpdate(const content::Geoposition& position);
 
+  // Determines if all policies say to send a position update.
+  // If there are no policies, this always says yes.
+  bool ShouldSendUpdate(const content::Geoposition& position);
+
+  // Updates the policies on sending a position update.
+  void OnPositionReported(const content::Geoposition& position);
+
   // Request name.
   const std::string request_name_;
 
@@ -70,6 +192,11 @@
   // Owning location manager.
   const base::WeakPtr<LocationManager> location_manager_;
 
+  // Holds Update Policies.
+  typedef std::vector<scoped_refptr<updatepolicy::UpdatePolicy> >
+      UpdatePolicyVector;
+  UpdatePolicyVector update_policies_;
+
   content::GeolocationProvider::LocationUpdateCallback callback_;
 
   DISALLOW_COPY_AND_ASSIGN(LocationRequest);
@@ -78,12 +205,26 @@
 LocationRequest::LocationRequest(
     const base::WeakPtr<LocationManager>& location_manager,
     const std::string& extension_id,
-    const std::string& request_name)
+    const std::string& request_name,
+    const double* distance_update_threshold_meters,
+    const double* time_between_updates_ms)
     : request_name_(request_name),
       extension_id_(extension_id),
       location_manager_(location_manager) {
   // TODO(vadimt): use request_info.
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  if (time_between_updates_ms) {
+    update_policies_.push_back(
+        new updatepolicy::TimeBasedUpdatePolicy(
+            *time_between_updates_ms));
+  }
+
+  if (distance_update_threshold_meters) {
+    update_policies_.push_back(
+        new updatepolicy::DistanceBasedUpdatePolicy(
+              *distance_update_threshold_meters));
+  }
 }
 
 void LocationRequest::Initialize() {
@@ -121,15 +262,38 @@
 
 void LocationRequest::OnLocationUpdate(const content::Geoposition& position) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  if (ShouldSendUpdate(position)) {
+    OnPositionReported(position);
+    BrowserThread::PostTask(
+        BrowserThread::UI,
+        FROM_HERE,
+        base::Bind(&LocationManager::SendLocationUpdate,
+                   location_manager_,
+                   extension_id_,
+                   request_name_,
+                   position));
+  }
+}
 
-  BrowserThread::PostTask(
-      BrowserThread::UI,
-      FROM_HERE,
-      base::Bind(&LocationManager::SendLocationUpdate,
-                 location_manager_,
-                 extension_id_,
-                 request_name_,
-                 position));
+bool LocationRequest::ShouldSendUpdate(const content::Geoposition& position) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  for (UpdatePolicyVector::iterator it = update_policies_.begin();
+       it != update_policies_.end();
+       ++it) {
+    if (!((*it)->ShouldSendUpdate(position))) {
+      return false;
+    }
+  }
+  return true;
+}
+
+void LocationRequest::OnPositionReported(const content::Geoposition& position) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  for (UpdatePolicyVector::iterator it = update_policies_.begin();
+       it != update_policies_.end();
+       ++it) {
+    (*it)->OnPositionReported(position);
+  }
 }
 
 LocationManager::LocationManager(Profile* profile)
@@ -140,17 +304,23 @@
                  content::Source<Profile>(profile_));
 }
 
-void LocationManager::AddLocationRequest(const std::string& extension_id,
-                                         const std::string& request_name) {
+void LocationManager::AddLocationRequest(
+    const std::string& extension_id,
+    const std::string& request_name,
+    const double* distance_update_threshold_meters,
+    const double* time_between_updates_ms) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   // TODO(vadimt): Consider resuming requests after restarting the browser.
 
   // Override any old request with the same name.
   RemoveLocationRequest(extension_id, request_name);
 
-  LocationRequestPointer location_request = new LocationRequest(AsWeakPtr(),
-                                                                extension_id,
-                                                                request_name);
+  LocationRequestPointer location_request =
+      new LocationRequest(AsWeakPtr(),
+                          extension_id,
+                          request_name,
+                          distance_update_threshold_meters,
+                          time_between_updates_ms);
   location_request->Initialize();
   location_requests_.insert(
       LocationRequestMap::value_type(extension_id, location_request));
@@ -200,7 +370,7 @@
     const content::Geoposition& position) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-  scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   std::string event_name;
 
   if (position.Validate() &&
diff --git a/chrome/browser/extensions/api/location/location_manager.h b/chrome/browser/extensions/api/location/location_manager.h
index 5b24685..6983b17 100644
--- a/chrome/browser/extensions/api/location/location_manager.h
+++ b/chrome/browser/extensions/api/location/location_manager.h
@@ -43,8 +43,11 @@
 
   // Adds location request for the given extension, and starts the location
   // tracking.
-  void AddLocationRequest(const std::string& extension_id,
-                          const std::string& request_name);
+  void AddLocationRequest(
+      const std::string& extension_id,
+      const std::string& request_name,
+      const double* distance_update_threshold_meters,
+      const double* time_between_updates_ms);
 
   // Cancels and removes the request with the given |name| for the given
   // extension.
diff --git a/chrome/browser/extensions/api/management/management_api.cc b/chrome/browser/extensions/api/management/management_api.cc
index c855b83..7f98037 100644
--- a/chrome/browser/extensions/api/management/management_api.cc
+++ b/chrome/browser/extensions/api/management/management_api.cc
@@ -315,13 +315,13 @@
     return handled;
   }
 
-  void OnJSONParseSucceeded(const ListValue& wrapper) {
+  void OnJSONParseSucceeded(const base::ListValue& wrapper) {
     CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
     const Value* value = NULL;
     CHECK(wrapper.Get(0, &value));
     if (value->IsType(Value::TYPE_DICTIONARY))
       parsed_manifest_.reset(
-          static_cast<const DictionaryValue*>(value)->DeepCopy());
+          static_cast<const base::DictionaryValue*>(value)->DeepCopy());
     else
       error_ = keys::kManifestParseError;
 
@@ -358,7 +358,7 @@
   std::string manifest_;
 
   // Results of parsing.
-  scoped_ptr<DictionaryValue> parsed_manifest_;
+  scoped_ptr<base::DictionaryValue> parsed_manifest_;
 
   std::string error_;
 };
@@ -382,7 +382,7 @@
 }
 
 void ManagementGetPermissionWarningsByManifestFunction::OnParseSuccess(
-    DictionaryValue* parsed_manifest) {
+    base::DictionaryValue* parsed_manifest) {
   CHECK(parsed_manifest);
 
   scoped_refptr<Extension> extension = Extension::Create(
@@ -676,7 +676,7 @@
   DCHECK(event_name);
   DCHECK(extension);
 
-  scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   if (event_name == events::kOnExtensionUninstalled) {
     args->Append(Value::CreateStringValue(extension->id()));
   } else {
diff --git a/chrome/browser/extensions/api/management/management_browsertest.cc b/chrome/browser/extensions/api/management/management_browsertest.cc
index 8457eea..ae05985 100644
--- a/chrome/browser/extensions/api/management/management_browsertest.cc
+++ b/chrome/browser/extensions/api/management/management_browsertest.cc
@@ -511,14 +511,14 @@
   ASSERT_TRUE(service->disabled_extensions()->is_empty());
 
   PrefService* prefs = browser()->profile()->GetPrefs();
-  const DictionaryValue* forcelist =
+  const base::DictionaryValue* forcelist =
       prefs->GetDictionary(prefs::kExtensionInstallForceList);
   ASSERT_TRUE(forcelist->empty()) << kForceInstallNotEmptyHelp;
 
   {
     // Set the policy as a user preference and fire notification observers.
     DictionaryPrefUpdate pref_update(prefs, prefs::kExtensionInstallForceList);
-    DictionaryValue* forcelist = pref_update.Get();
+    base::DictionaryValue* forcelist = pref_update.Get();
     extensions::ExternalPolicyLoader::AddExtension(
         forcelist, kExtensionId, "http://localhost/autoupdate/manifest");
   }
@@ -584,7 +584,7 @@
 
   // Check that the policy is initially empty.
   PrefService* prefs = browser()->profile()->GetPrefs();
-  const DictionaryValue* forcelist =
+  const base::DictionaryValue* forcelist =
       prefs->GetDictionary(prefs::kExtensionInstallForceList);
   ASSERT_TRUE(forcelist->empty()) << kForceInstallNotEmptyHelp;
 
@@ -638,7 +638,7 @@
   // and force enable it too.
   {
     DictionaryPrefUpdate pref_update(prefs, prefs::kExtensionInstallForceList);
-    DictionaryValue* forcelist = pref_update.Get();
+    base::DictionaryValue* forcelist = pref_update.Get();
     extensions::ExternalPolicyLoader::AddExtension(
         forcelist, kExtensionId, "http://localhost/autoupdate/manifest");
   }
diff --git a/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc b/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc
index 4fbc75b..49d55f0 100644
--- a/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc
+++ b/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc
@@ -10,6 +10,7 @@
 #include <string>
 #include <vector>
 
+#include "apps/shell_window.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/platform_file.h"
 #include "base/stl_util.h"
@@ -21,7 +22,6 @@
 #include "chrome/browser/media_galleries/media_galleries_dialog_controller.h"
 #include "chrome/browser/storage_monitor/storage_monitor.h"
 #include "chrome/browser/ui/chrome_select_file_policy.h"
-#include "chrome/browser/ui/extensions/shell_window.h"
 #include "chrome/common/extensions/api/experimental_media_galleries.h"
 #include "chrome/common/extensions/api/media_galleries.h"
 #include "chrome/common/extensions/extension.h"
@@ -39,6 +39,7 @@
 #include "base/strings/sys_string_conversions.h"
 #endif
 
+using apps::ShellWindow;
 using chrome::MediaFileSystemInfo;
 using chrome::MediaFileSystemRegistry;
 using chrome::MediaFileSystemsCallback;
@@ -93,7 +94,7 @@
     interactive = params->details->interactive;
   }
 
-  chrome::StorageMonitor::GetInstance()->Initialize(base::Bind(
+  chrome::StorageMonitor::GetInstance()->EnsureInitialized(base::Bind(
       &MediaGalleriesGetMediaFileSystemsFunction::OnStorageMonitorInit,
       this,
       interactive));
@@ -205,6 +206,13 @@
   WebContents* contents = WebContents::FromRenderViewHost(render_view_host());
   WebContentsModalDialogManager* web_contents_modal_dialog_manager =
       WebContentsModalDialogManager::FromWebContents(contents);
+  // If there's no user gesture associated with the API call, do not show
+  // the dialog.
+  if (!user_gesture()) {
+    GetAndReturnGalleries();
+    return;
+  }
+
   if (!web_contents_modal_dialog_manager) {
     // If there is no WebContentsModalDialogManager, then this contents is
     // probably the background page for an app. Try to find a shell window to
diff --git a/chrome/browser/extensions/api/media_galleries_private/gallery_watch_manager.cc b/chrome/browser/extensions/api/media_galleries_private/gallery_watch_manager.cc
index c2cbfe1..c12d9d7 100644
--- a/chrome/browser/extensions/api/media_galleries_private/gallery_watch_manager.cc
+++ b/chrome/browser/extensions/api/media_galleries_private/gallery_watch_manager.cc
@@ -16,7 +16,7 @@
 #include "base/location.h"
 #include "base/memory/ref_counted.h"
 #include "base/stl_util.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/extensions/api/media_galleries_private/media_galleries_private_event_router.h"
 #include "content/public/browser/browser_thread.h"
 
diff --git a/chrome/browser/extensions/api/media_galleries_private/gallery_watch_state_tracker.cc b/chrome/browser/extensions/api/media_galleries_private/gallery_watch_state_tracker.cc
index bcd2ff5..309b008 100644
--- a/chrome/browser/extensions/api/media_galleries_private/gallery_watch_state_tracker.cc
+++ b/chrome/browser/extensions/api/media_galleries_private/gallery_watch_state_tracker.cc
@@ -55,7 +55,7 @@
 scoped_ptr<base::ListValue> WatchedGalleryIdsToValue(
     const chrome::MediaGalleryPrefIdSet gallery_ids) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-  scoped_ptr<base::ListValue> list(new ListValue());
+  scoped_ptr<base::ListValue> list(new base::ListValue());
   for (chrome::MediaGalleryPrefIdSet::const_iterator id_iter =
            gallery_ids.begin();
        id_iter != gallery_ids.end(); ++id_iter)
diff --git a/chrome/browser/extensions/api/media_galleries_private/media_galleries_private_api.cc b/chrome/browser/extensions/api/media_galleries_private/media_galleries_private_api.cc
index fa1246b..86a414a 100644
--- a/chrome/browser/extensions/api/media_galleries_private/media_galleries_private_api.cc
+++ b/chrome/browser/extensions/api/media_galleries_private/media_galleries_private_api.cc
@@ -128,7 +128,7 @@
   // This method is called synchronously with the message handler for the
   // JS invocation.
 
-  chrome::StorageMonitor::GetInstance()->Initialize(base::Bind(
+  chrome::StorageMonitor::GetInstance()->EnsureInitialized(base::Bind(
       &MediaGalleriesPrivateAPI::MaybeInitializeEventRouterAndTracker,
       weak_ptr_factory_.GetWeakPtr()));
 }
@@ -171,7 +171,7 @@
       AddGalleryWatch::Params::Create(*args_));
   EXTENSION_FUNCTION_VALIDATE(params.get());
 
-  chrome::StorageMonitor::GetInstance()->Initialize(base::Bind(
+  chrome::StorageMonitor::GetInstance()->EnsureInitialized(base::Bind(
       &MediaGalleriesPrivateAddGalleryWatchFunction::OnStorageMonitorInit,
       this,
       params->gallery_id));
@@ -251,7 +251,7 @@
       RemoveGalleryWatch::Params::Create(*args_));
   EXTENSION_FUNCTION_VALIDATE(params.get());
 
-  chrome::StorageMonitor::GetInstance()->Initialize(base::Bind(
+  chrome::StorageMonitor::GetInstance()->EnsureInitialized(base::Bind(
       &MediaGalleriesPrivateRemoveGalleryWatchFunction::OnStorageMonitorInit,
       this,
       params->gallery_id));
@@ -298,7 +298,7 @@
   if (!render_view_host() || !render_view_host()->GetProcess())
     return false;
 
-  chrome::StorageMonitor::GetInstance()->Initialize(base::Bind(
+  chrome::StorageMonitor::GetInstance()->EnsureInitialized(base::Bind(
       &MediaGalleriesPrivateGetAllGalleryWatchFunction::OnStorageMonitorInit,
       this));
   return true;
@@ -335,7 +335,7 @@
   if (!render_view_host() || !render_view_host()->GetProcess())
     return false;
 
-  chrome::StorageMonitor::GetInstance()->Initialize(base::Bind(
+  chrome::StorageMonitor::GetInstance()->EnsureInitialized(base::Bind(
       &MediaGalleriesPrivateRemoveAllGalleryWatchFunction::OnStorageMonitorInit,
       this));
   return true;
@@ -371,7 +371,7 @@
   scoped_ptr<EjectDevice::Params> params(EjectDevice::Params::Create(*args_));
   EXTENSION_FUNCTION_VALIDATE(params.get());
 
-  chrome::StorageMonitor::GetInstance()->Initialize(base::Bind(
+  chrome::StorageMonitor::GetInstance()->EnsureInitialized(base::Bind(
       &MediaGalleriesPrivateEjectDeviceFunction::OnStorageMonitorInit,
       this,
       params->device_id));
diff --git a/chrome/browser/extensions/api/media_galleries_private/media_galleries_private_apitest.cc b/chrome/browser/extensions/api/media_galleries_private/media_galleries_private_apitest.cc
index 197a01e..c85d58a 100644
--- a/chrome/browser/extensions/api/media_galleries_private/media_galleries_private_apitest.cc
+++ b/chrome/browser/extensions/api/media_galleries_private/media_galleries_private_apitest.cc
@@ -11,6 +11,7 @@
 #include "chrome/browser/extensions/extension_test_message_listener.h"
 #include "chrome/browser/storage_monitor/storage_info.h"
 #include "chrome/browser/storage_monitor/storage_monitor.h"
+#include "chrome/browser/storage_monitor/test_storage_monitor.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/extensions/extension.h"
@@ -86,37 +87,32 @@
   }
 
   void Attach() {
+    DCHECK(chrome::StorageMonitor::GetInstance()->IsInitialized());
     chrome::StorageInfo info(device_id_, ASCIIToUTF16(kDeviceName), kDevicePath,
                              string16(), string16(), string16(), 0);
     chrome::StorageMonitor::GetInstance()->receiver()->ProcessAttach(info);
-    WaitForDeviceEvents();
-  }
-
-  void Detach() {
-    chrome::StorageMonitor::GetInstance()->receiver()->ProcessDetach(
-        device_id_);
-    WaitForDeviceEvents();
-  }
-
- private:
-  void WaitForDeviceEvents() {
     content::RunAllPendingInMessageLoop();
   }
 
+  void Detach() {
+    DCHECK(chrome::StorageMonitor::GetInstance()->IsInitialized());
+    chrome::StorageMonitor::GetInstance()->receiver()->ProcessDetach(
+        device_id_);
+    content::RunAllPendingInMessageLoop();
+  }
+
+ private:
   std::string device_id_;
 
   DISALLOW_COPY_AND_ASSIGN(MediaGalleriesPrivateApiTest);
 };
 
-// TODO(jschuh): Flaky on Win64 & Linux Aura build. crbug.com/247336
-#if (defined(OS_WIN) && defined(ARCH_CPU_X86_64)) || \
-    (defined(OS_LINUX) && defined(USE_AURA))
-#define MAYBE_DeviceAttachDetachEvents DISABLED_DeviceAttachDetachEvents
-#else
-#define MAYBE_DeviceAttachDetachEvents DeviceAttachDetachEvents
-#endif
-IN_PROC_BROWSER_TEST_F(MediaGalleriesPrivateApiTest,
-                       MAYBE_DeviceAttachDetachEvents) {
+IN_PROC_BROWSER_TEST_F(MediaGalleriesPrivateApiTest, DeviceAttachDetachEvents) {
+  scoped_ptr<chrome::test::TestStorageMonitor> monitor(
+      chrome::test::TestStorageMonitor::CreateForBrowserTests());
+  monitor->Init();
+  monitor->MarkInitialized();
+
   // Setup.
   const extensions::Extension* extension =
       LoadExtension(test_data_dir_.AppendASCII(kTestExtensionPath));
diff --git a/chrome/browser/extensions/api/media_galleries_private/media_galleries_private_event_router.cc b/chrome/browser/extensions/api/media_galleries_private/media_galleries_private_event_router.cc
index 2d7bb43..8a2070a 100644
--- a/chrome/browser/extensions/api/media_galleries_private/media_galleries_private_event_router.cc
+++ b/chrome/browser/extensions/api/media_galleries_private/media_galleries_private_event_router.cc
@@ -62,7 +62,7 @@
        it != extension_ids.end(); ++it) {
     GalleryChangeDetails details;
     details.gallery_id = gallery_id;
-    scoped_ptr<ListValue> args(new ListValue());
+    scoped_ptr<base::ListValue> args(new base::ListValue());
     args->Append(details.ToValue().release());
     scoped_ptr<extensions::Event> event(new extensions::Event(
         event_names::kOnGalleryChangedEventName,
@@ -106,7 +106,7 @@
   DeviceDetachmentDetails details;
   details.device_id = GetTransientIdForDeviceId(info.device_id());
 
-  scoped_ptr<base::ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   args->Append(details.ToValue().release());
   DispatchEvent(event_names::kOnDetachEventName, args.Pass());
 }
diff --git a/chrome/browser/extensions/api/messaging/extension_message_port.cc b/chrome/browser/extensions/api/messaging/extension_message_port.cc
index a3bba97..e4782c7 100644
--- a/chrome/browser/extensions/api/messaging/extension_message_port.cc
+++ b/chrome/browser/extensions/api/messaging/extension_message_port.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/extensions/api/messaging/extension_message_port.h"
 
-#include "base/values.h"
 #include "chrome/browser/extensions/extension_host.h"
 #include "chrome/browser/extensions/extension_process_manager.h"
 #include "chrome/browser/extensions/extension_system.h"
@@ -46,11 +45,10 @@
       routing_id_, source_port_id, error_message));
 }
 
-void ExtensionMessagePort::DispatchOnMessage(
-    scoped_ptr<base::ListValue> message,
-    int target_port_id) {
-  process_->Send(new ExtensionMsg_DeliverMessage(
-      routing_id_, target_port_id, *message));
+void ExtensionMessagePort::DispatchOnMessage(const std::string& message,
+                                             int target_port_id) {
+    process_->Send(new ExtensionMsg_DeliverMessage(
+        routing_id_, target_port_id, message));
 }
 
 void ExtensionMessagePort::IncrementLazyKeepaliveCount() {
diff --git a/chrome/browser/extensions/api/messaging/extension_message_port.h b/chrome/browser/extensions/api/messaging/extension_message_port.h
index 7cc386a..ccf9b69 100644
--- a/chrome/browser/extensions/api/messaging/extension_message_port.h
+++ b/chrome/browser/extensions/api/messaging/extension_message_port.h
@@ -9,10 +9,6 @@
 
 class GURL;
 
-namespace base {
-class ListValue;
-}
-
 namespace content {
 class RenderProcessHost;
 }  // namespace content
@@ -34,7 +30,7 @@
       const GURL& source_url) OVERRIDE;
   virtual void DispatchOnDisconnect(int source_port_id,
                                     const std::string& error_message) OVERRIDE;
-  virtual void DispatchOnMessage(scoped_ptr<base::ListValue> message,
+  virtual void DispatchOnMessage(const std::string& message,
                                  int target_port_id) OVERRIDE;
   virtual void IncrementLazyKeepaliveCount() OVERRIDE;
   virtual void DecrementLazyKeepaliveCount() OVERRIDE;
diff --git a/chrome/browser/extensions/api/messaging/message_service.cc b/chrome/browser/extensions/api/messaging/message_service.cc
index 3188a7f..6ef2531 100644
--- a/chrome/browser/extensions/api/messaging/message_service.cc
+++ b/chrome/browser/extensions/api/messaging/message_service.cc
@@ -6,7 +6,6 @@
 
 #include "base/atomic_sequence_num.h"
 #include "base/bind.h"
-#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/json/json_writer.h"
 #include "base/lazy_instance.h"
@@ -71,7 +70,7 @@
 
 struct MessageService::OpenChannelParams {
   content::RenderProcessHost* source;
-  DictionaryValue source_tab;
+  base::DictionaryValue source_tab;
   scoped_ptr<MessagePort> receiver;
   int receiver_port_id;
   std::string source_extension_id;
@@ -81,7 +80,7 @@
 
   // Takes ownership of receiver.
   OpenChannelParams(content::RenderProcessHost* source,
-                    scoped_ptr<DictionaryValue> source_tab,
+                    scoped_ptr<base::DictionaryValue> source_tab,
                     MessagePort* receiver,
                     int receiver_port_id,
                     const std::string& source_extension_id,
@@ -241,7 +240,7 @@
       source_process_id, source_routing_id);
 
   // Include info about the opener's tab (if it was a tab).
-  scoped_ptr<DictionaryValue> source_tab;
+  scoped_ptr<base::DictionaryValue> source_tab;
   GURL source_url_for_tab;
 
   if (source_contents && ExtensionTabUtil::GetTabId(source_contents) >= 0) {
@@ -356,8 +355,8 @@
 
   scoped_ptr<OpenChannelParams> params(new OpenChannelParams(
         source,
-        scoped_ptr<DictionaryValue>(),  // Source tab doesn't make sense for
-                                        // opening to tabs.
+        scoped_ptr<base::DictionaryValue>(),  // Source tab doesn't make sense
+                                              // for opening to tabs.
         receiver.release(),
         receiver_port_id,
         extension_id,
@@ -458,7 +457,7 @@
 }
 
 void MessageService::PostMessage(
-    int source_port_id, scoped_ptr<base::ListValue> message) {
+    int source_port_id, const std::string& message) {
   int channel_id = GET_CHANNEL_ID(source_port_id);
   MessageChannelMap::iterator iter = channels_.find(channel_id);
   if (iter == channels_.end()) {
@@ -469,9 +468,7 @@
       lazy_background_task_queue_->AddPendingTask(
           pending->second.first, pending->second.second,
           base::Bind(&MessageService::PendingPostMessage,
-                     weak_factory_.GetWeakPtr(),
-                     source_port_id,
-                     base::Passed(&message)));
+                     weak_factory_.GetWeakPtr(), source_port_id, message));
     }
     return;
   }
@@ -481,13 +478,12 @@
   MessagePort* port = IS_OPENER_PORT_ID(dest_port_id) ?
       iter->second->opener.get() : iter->second->receiver.get();
 
-  port->DispatchOnMessage(message.Pass(), dest_port_id);
+  port->DispatchOnMessage(message, dest_port_id);
 }
 
-void MessageService::PostMessageFromNativeProcess(
-    int port_id,
-    scoped_ptr<base::ListValue> message) {
-  PostMessage(port_id, message.Pass());
+void MessageService::PostMessageFromNativeProcess(int port_id,
+                                                  const std::string& message) {
+  PostMessage(port_id, message);
 }
 
 void MessageService::Observe(int type,
diff --git a/chrome/browser/extensions/api/messaging/message_service.h b/chrome/browser/extensions/api/messaging/message_service.h
index 59ba6ff..6de5a74 100644
--- a/chrome/browser/extensions/api/messaging/message_service.h
+++ b/chrome/browser/extensions/api/messaging/message_service.h
@@ -22,7 +22,6 @@
 
 namespace base {
 class DictionaryValue;
-class ListValue;
 }
 
 namespace content {
@@ -83,7 +82,7 @@
                                       const std::string& error_message) {}
 
     // Dispatch a message to this end of the communication.
-    virtual void DispatchOnMessage(scoped_ptr<base::ListValue> message,
+    virtual void DispatchOnMessage(const std::string& message,
                                    int target_port_id) = 0;
 
     // MessagPorts that target extensions will need to adjust their keepalive
@@ -145,12 +144,12 @@
                             const std::string& error_message) OVERRIDE;
 
   // Sends a message to the given port.
-  void PostMessage(int port_id, scoped_ptr<base::ListValue> message);
+  void PostMessage(int port_id, const std::string& message);
 
   // NativeMessageProcessHost::Client
   virtual void PostMessageFromNativeProcess(
       int port_id,
-      scoped_ptr<base::ListValue> message) OVERRIDE;
+      const std::string& message) OVERRIDE;
 
  private:
   friend class MockMessageService;
@@ -206,10 +205,10 @@
       CloseChannel(port_id, error_message);
   }
   void PendingPostMessage(int port_id,
-                          scoped_ptr<base::ListValue> message,
+                          const std::string& message,
                           extensions::ExtensionHost* host) {
     if (host)
-      PostMessage(port_id, message.Pass());
+      PostMessage(port_id, message);
   }
 
   // Immediate dispatches a disconnect to |source| for |port_id|. Sets source's
diff --git a/chrome/browser/extensions/api/messaging/native_message_port.cc b/chrome/browser/extensions/api/messaging/native_message_port.cc
index 7ca7bea..e746e29 100644
--- a/chrome/browser/extensions/api/messaging/native_message_port.cc
+++ b/chrome/browser/extensions/api/messaging/native_message_port.cc
@@ -5,8 +5,6 @@
 #include "chrome/browser/extensions/api/messaging/native_message_port.h"
 
 #include "base/bind.h"
-#include "base/json/json_writer.h"
-#include "base/values.h"
 #include "chrome/browser/extensions/api/messaging/native_message_process_host.h"
 #include "content/public/browser/browser_thread.h"
 
@@ -21,20 +19,12 @@
       content::BrowserThread::IO, FROM_HERE, native_process_);
 }
 
-void NativeMessagePort::DispatchOnMessage(scoped_ptr<base::ListValue> message,
+void NativeMessagePort::DispatchOnMessage(const std::string& message,
                                           int target_port_id) {
-  std::string message_as_json;
-  if (!message->empty()) {
-    DCHECK_EQ(1u, message->GetSize());
-    base::Value* value = NULL;
-    message->Get(0, &value);
-    base::JSONWriter::Write(value, &message_as_json);
-  }
   content::BrowserThread::PostTask(
       content::BrowserThread::IO, FROM_HERE,
       base::Bind(&NativeMessageProcessHost::Send,
-                 base::Unretained(native_process_),
-                 message_as_json));
+                 base::Unretained(native_process_), message));
 }
 
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/messaging/native_message_port.h b/chrome/browser/extensions/api/messaging/native_message_port.h
index 4c88445..6afce8a 100644
--- a/chrome/browser/extensions/api/messaging/native_message_port.h
+++ b/chrome/browser/extensions/api/messaging/native_message_port.h
@@ -16,7 +16,7 @@
   // Takes ownership of |native_process|.
   explicit NativeMessagePort(NativeMessageProcessHost* native_process);
   virtual ~NativeMessagePort();
-  virtual void DispatchOnMessage(scoped_ptr<base::ListValue> message,
+  virtual void DispatchOnMessage(const std::string& message,
                                  int target_port_id) OVERRIDE;
 
  private:
diff --git a/chrome/browser/extensions/api/messaging/native_message_process_host.cc b/chrome/browser/extensions/api/messaging/native_message_process_host.cc
index 9f8c50b..9187a08 100644
--- a/chrome/browser/extensions/api/messaging/native_message_process_host.cc
+++ b/chrome/browser/extensions/api/messaging/native_message_process_host.cc
@@ -5,9 +5,7 @@
 #include "chrome/browser/extensions/api/messaging/native_message_process_host.h"
 
 #include "base/bind.h"
-#include "base/bind_helpers.h"
 #include "base/files/file_path.h"
-#include "base/json/json_reader.h"
 #include "base/logging.h"
 #include "base/platform_file.h"
 #include "base/process_util.h"
@@ -44,8 +42,6 @@
     "Access to the specified native messaging host is forbidden.";
 const char kHostInputOuputError[] =
     "Error when communicating with the native messaging host.";
-const char kInvalidJsonError[] =
-    "Message must be valid JSON";
 
 }  // namespace
 
@@ -272,35 +268,10 @@
     if (incoming_data_.size() < message_size + kMessageHeaderSize)
       return;
 
-    scoped_ptr<base::ListValue> message(new base::ListValue());
-    {
-      std::string message_as_json =
-          incoming_data_.substr(kMessageHeaderSize, message_size);
-      int error_code;
-      std::string error_message;
-      scoped_ptr<base::Value> message_as_value(
-          base::JSONReader::ReadAndReturnError(message_as_json,
-                                               0,  // no flags
-                                               &error_code,
-                                               &error_message));
-      if (!message_as_value) {
-        base::JSONReader::JsonParseError parse_error =
-            static_cast<base::JSONReader::JsonParseError>(error_code);
-        LOG(ERROR) << "Native Messaging host sent message with invalid JSON \""
-                   << message_as_json << "\": " << error_message << " ("
-                   << base::JSONReader::ErrorCodeToString(parse_error) << "), "
-                   << "message size " << message_size << ", "
-                   << "incoming data size " << incoming_data_.size() << ".";
-        Close(kInvalidJsonError);
-        return;
-      }
-      message->Append(message_as_value.release());
-    }
-
     content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
         base::Bind(&Client::PostMessageFromNativeProcess, weak_client_ui_,
             destination_port_,
-            base::Passed(&message)));
+            incoming_data_.substr(kMessageHeaderSize, message_size)));
 
     incoming_data_.erase(0, kMessageHeaderSize + message_size);
   }
diff --git a/chrome/browser/extensions/api/messaging/native_message_process_host.h b/chrome/browser/extensions/api/messaging/native_message_process_host.h
index ef339b2..987055f 100644
--- a/chrome/browser/extensions/api/messaging/native_message_process_host.h
+++ b/chrome/browser/extensions/api/messaging/native_message_process_host.h
@@ -15,15 +15,13 @@
 #include "chrome/browser/extensions/api/messaging/native_process_launcher.h"
 #include "content/public/browser/browser_thread.h"
 
-namespace base {
-class ListValue;
-}
-
 namespace net {
+
 class DrainableIOBuffer;
 class FileStream;
 class IOBuffer;
 class IOBufferWithSize;
+
 }  // namespace net
 
 namespace extensions {
@@ -45,9 +43,8 @@
    public:
     virtual ~Client() {}
     // Called on the UI thread.
-    virtual void PostMessageFromNativeProcess(
-        int port_id,
-        scoped_ptr<base::ListValue> message) = 0;
+    virtual void PostMessageFromNativeProcess(int port_id,
+                                              const std::string& message) = 0;
     virtual void CloseChannel(int port_id,
                               const std::string& error_message) = 0;
   };
diff --git a/chrome/browser/extensions/api/messaging/native_message_process_host_unittest.cc b/chrome/browser/extensions/api/messaging/native_message_process_host_unittest.cc
index d8fe2c4..5b7f0c8 100644
--- a/chrome/browser/extensions/api/messaging/native_message_process_host_unittest.cc
+++ b/chrome/browser/extensions/api/messaging/native_message_process_host_unittest.cc
@@ -19,7 +19,7 @@
 #include "base/test/test_timeouts.h"
 #include "base/threading/platform_thread.h"
 #include "base/threading/sequenced_worker_pool.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/extensions/api/messaging/native_message_process_host.h"
 #include "chrome/browser/extensions/api/messaging/native_messaging_test_util.h"
 #include "chrome/browser/extensions/api/messaging/native_process_launcher.h"
@@ -104,15 +104,19 @@
 
   virtual void PostMessageFromNativeProcess(
       int port_id,
-      scoped_ptr<base::ListValue> message_as_list) OVERRIDE  {
-    // |message_as_list| should contain a single DictionaryValue. Extract it
-    // into |last_message_|.
-    ASSERT_EQ(1u, message_as_list->GetSize());
-    base::Value* last_message_value = NULL;
-    message_as_list->Remove(0, &last_message_value);
-    ASSERT_EQ(base::Value::TYPE_DICTIONARY, last_message_value->GetType());
-    last_message_.reset(
-        static_cast<base::DictionaryValue*>(last_message_value));
+      const std::string& message) OVERRIDE  {
+    last_message_ = message;
+
+    // Parse the message.
+    base::Value* parsed = base::JSONReader::Read(message);
+    base::DictionaryValue* dict_value;
+    if (parsed && parsed->GetAsDictionary(&dict_value)) {
+      last_message_parsed_.reset(dict_value);
+    } else {
+      LOG(ERROR) << "Failed to parse " << message;
+      last_message_parsed_.reset();
+      delete parsed;
+    }
 
     if (read_message_run_loop_)
       read_message_run_loop_->Quit();
@@ -146,7 +150,8 @@
   base::FilePath user_data_dir_;
   scoped_ptr<base::RunLoop> read_message_run_loop_;
   content::TestBrowserThreadBundle thread_bundle_;
-  scoped_ptr<DictionaryValue> last_message_;
+  std::string last_message_;
+  scoped_ptr<base::DictionaryValue> last_message_parsed_;
 };
 
 // Read a single message from a local file.
@@ -163,26 +168,19 @@
   read_message_run_loop_.reset(new base::RunLoop());
   read_message_run_loop_->RunUntilIdle();
 
-  if (!last_message_) {
+  if (last_message_.empty()) {
     read_message_run_loop_.reset(new base::RunLoop());
     native_message_process_host_->ReadNowForTesting();
     read_message_run_loop_->Run();
   }
-  ASSERT_TRUE(last_message_);
-
-  scoped_ptr<base::Value> kTestMessageAsValue(
-      base::JSONReader::Read(kTestMessage));
-  ASSERT_TRUE(kTestMessageAsValue);
-  EXPECT_TRUE(base::Value::Equals(kTestMessageAsValue.get(),
-                                  last_message_.get()))
-      << "Expected " << *kTestMessageAsValue << " got " << *last_message_;
+  EXPECT_EQ(kTestMessage, last_message_);
 }
 
 // Tests sending a single message. The message should get written to
 // |temp_file| and should match the contents of single_message_request.msg.
 TEST_F(NativeMessagingTest, SingleSendMessageWrite) {
   base::FilePath temp_output_file = temp_dir_.path().AppendASCII("output");
-  base::FilePath temp_input_file = CreateTempFileWithMessage("{}");
+  base::FilePath temp_input_file = CreateTempFileWithMessage(std::string());
 
   scoped_ptr<NativeProcessLauncher> launcher(
       new FakeLauncher(temp_input_file, temp_output_file));
@@ -228,29 +226,30 @@
   native_message_process_host_->Send("{\"text\": \"Hello.\"}");
   read_message_run_loop_.reset(new base::RunLoop());
   read_message_run_loop_->Run();
-  ASSERT_TRUE(last_message_);
+  ASSERT_FALSE(last_message_.empty());
+  ASSERT_TRUE(last_message_parsed_);
 
   std::string expected_url = std::string("chrome-extension://") +
       kTestNativeMessagingExtensionId + "/";
   int id;
-  EXPECT_TRUE(last_message_->GetInteger("id", &id));
+  EXPECT_TRUE(last_message_parsed_->GetInteger("id", &id));
   EXPECT_EQ(1, id);
   std::string text;
-  EXPECT_TRUE(last_message_->GetString("echo.text", &text));
+  EXPECT_TRUE(last_message_parsed_->GetString("echo.text", &text));
   EXPECT_EQ("Hello.", text);
   std::string url;
-  EXPECT_TRUE(last_message_->GetString("caller_url", &url));
+  EXPECT_TRUE(last_message_parsed_->GetString("caller_url", &url));
   EXPECT_EQ(expected_url, url);
 
 
   native_message_process_host_->Send("{\"foo\": \"bar\"}");
   read_message_run_loop_.reset(new base::RunLoop());
   read_message_run_loop_->Run();
-  EXPECT_TRUE(last_message_->GetInteger("id", &id));
+  EXPECT_TRUE(last_message_parsed_->GetInteger("id", &id));
   EXPECT_EQ(2, id);
-  EXPECT_TRUE(last_message_->GetString("echo.foo", &text));
+  EXPECT_TRUE(last_message_parsed_->GetString("echo.foo", &text));
   EXPECT_EQ("bar", text);
-  EXPECT_TRUE(last_message_->GetString("caller_url", &url));
+  EXPECT_TRUE(last_message_parsed_->GetString("caller_url", &url));
   EXPECT_EQ(expected_url, url);
 }
 
diff --git a/chrome/browser/extensions/api/messaging/native_process_launcher_win.cc b/chrome/browser/extensions/api/messaging/native_process_launcher_win.cc
index 6dd0769..70d0fd6 100644
--- a/chrome/browser/extensions/api/messaging/native_process_launcher_win.cc
+++ b/chrome/browser/extensions/api/messaging/native_process_launcher_win.cc
@@ -23,36 +23,41 @@
 const wchar_t kNativeMessagingRegistryKey[] =
     L"SOFTWARE\\Google\\Chrome\\NativeMessagingHosts";
 
+namespace {
+
+// Reads path to the native messaging host manifest from the registry. Returns
+// empty string if the path isn't found.
+string16 GetManifestPath(const string16& native_host_name, DWORD flags) {
+  base::win::RegKey key;
+  string16 result;
+
+  if (key.Open(HKEY_LOCAL_MACHINE, kNativeMessagingRegistryKey,
+               KEY_QUERY_VALUE | flags) != ERROR_SUCCESS ||
+      key.OpenKey(native_host_name.c_str(),
+                  KEY_QUERY_VALUE | flags) != ERROR_SUCCESS ||
+      key.ReadValue(NULL, &result) != ERROR_SUCCESS) {
+    return string16();
+  }
+
+  return result;
+}
+
+}  // namespace
+
 // static
 scoped_ptr<NativeMessagingHostManifest>
 NativeProcessLauncher::FindAndLoadManifest(
     const std::string& native_host_name,
     std::string* error_message) {
-  base::win::RegKey key;
-
-  string16 manifest_path;
   string16 native_host_name_wide = UTF8ToUTF16(native_host_name);
 
-  bool found = false;
-
   // First check 32-bit registry and then try 64-bit.
-  if (key.Open(HKEY_LOCAL_MACHINE, kNativeMessagingRegistryKey,
-               KEY_QUERY_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS) {
-    if (key.ReadValue(native_host_name_wide.c_str(), &manifest_path) ==
-        ERROR_SUCCESS) {
-      found = true;
-    }
-  }
+  string16 manifest_path =
+      GetManifestPath(native_host_name_wide, KEY_WOW64_32KEY);
+  if (manifest_path.empty())
+    manifest_path = GetManifestPath(native_host_name_wide, KEY_WOW64_64KEY);
 
-  if (!found && key.Open(HKEY_LOCAL_MACHINE, kNativeMessagingRegistryKey,
-                         KEY_QUERY_VALUE | KEY_WOW64_64KEY) == ERROR_SUCCESS) {
-    if (key.ReadValue(native_host_name_wide.c_str(), &manifest_path) ==
-        ERROR_SUCCESS) {
-      found = true;
-    }
-  }
-
-  if (!found) {
+  if (manifest_path.empty()) {
     *error_message = "Native messaging host " + native_host_name +
         " is not registered";
     return scoped_ptr<NativeMessagingHostManifest>();
diff --git a/chrome/browser/extensions/api/metrics_private/metrics_apitest.cc b/chrome/browser/extensions/api/metrics_private/metrics_apitest.cc
index 655670f..1794fc2 100644
--- a/chrome/browser/extensions/api/metrics_private/metrics_apitest.cc
+++ b/chrome/browser/extensions/api/metrics_private/metrics_apitest.cc
@@ -4,6 +4,7 @@
 
 #include <map>
 
+#include "base/metrics/field_trial.h"
 #include "base/metrics/histogram.h"
 #include "base/metrics/statistics_recorder.h"
 #include "chrome/browser/extensions/extension_apitest.h"
@@ -126,6 +127,8 @@
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Metrics) {
   UserActionObserver observer;
 
+  base::FieldTrialList::CreateFieldTrial("apitestfieldtrial2", "group1");
+
   ASSERT_TRUE(RunComponentExtensionTest("metrics")) << message_;
 
   observer.ValidateUserActions(g_user_actions, arraysize(g_user_actions));
diff --git a/chrome/browser/extensions/api/metrics_private/metrics_private_api.cc b/chrome/browser/extensions/api/metrics_private/metrics_private_api.cc
index 08ac6f3..f65d80e 100644
--- a/chrome/browser/extensions/api/metrics_private/metrics_private_api.cc
+++ b/chrome/browser/extensions/api/metrics_private/metrics_private_api.cc
@@ -6,6 +6,7 @@
 
 #include <algorithm>
 
+#include "base/metrics/field_trial.h"
 #include "base/metrics/histogram.h"
 #include "base/prefs/pref_service.h"
 #include "chrome/browser/browser_process.h"
@@ -22,6 +23,7 @@
 
 namespace GetIsCrashReportingEnabled =
     api::metrics_private::GetIsCrashReportingEnabled;
+namespace GetFieldTrial = api::metrics_private::GetFieldTrial;
 namespace RecordUserAction = api::metrics_private::RecordUserAction;
 namespace RecordValue = api::metrics_private::RecordValue;
 namespace RecordPercentage = api::metrics_private::RecordPercentage;
@@ -66,6 +68,14 @@
   return true;
 }
 
+bool MetricsPrivateGetFieldTrialFunction::RunImpl() {
+  std::string name;
+  EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &name));
+
+  SetResult(new base::StringValue(base::FieldTrialList::FindFullName(name)));
+  return true;
+}
+
 bool MetricsPrivateRecordUserActionFunction::RunImpl() {
   scoped_ptr<RecordUserAction::Params> params(
       RecordUserAction::Params::Create(*args_));
diff --git a/chrome/browser/extensions/api/metrics_private/metrics_private_api.h b/chrome/browser/extensions/api/metrics_private/metrics_private_api.h
index f3307c3..7679aa2 100644
--- a/chrome/browser/extensions/api/metrics_private/metrics_private_api.h
+++ b/chrome/browser/extensions/api/metrics_private/metrics_private_api.h
@@ -25,6 +25,18 @@
   virtual bool RunImpl() OVERRIDE;
 };
 
+class MetricsPrivateGetFieldTrialFunction : public SyncExtensionFunction {
+ public:
+  DECLARE_EXTENSION_FUNCTION("metricsPrivate.getFieldTrial",
+                             METRICSPRIVATE_GETFIELDTRIAL)
+
+ protected:
+  virtual ~MetricsPrivateGetFieldTrialFunction() {}
+
+  // ExtensionFunction:
+  virtual bool RunImpl() OVERRIDE;
+};
+
 class MetricsPrivateRecordUserActionFunction : public SyncExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("metricsPrivate.recordUserAction",
diff --git a/chrome/browser/extensions/api/music_manager_private/device_id_mac.cc b/chrome/browser/extensions/api/music_manager_private/device_id_mac.cc
index d768167..e66c0e2 100644
--- a/chrome/browser/extensions/api/music_manager_private/device_id_mac.cc
+++ b/chrome/browser/extensions/api/music_manager_private/device_id_mac.cc
@@ -46,20 +46,20 @@
 std::string GetVolumeUUIDFromBSDName(const std::string& bsd_name) {
   const CFAllocatorRef allocator = NULL;
 
-  base::mac::ScopedCFTypeRef<DASessionRef> session(DASessionCreate(allocator));
+  base::ScopedCFTypeRef<DASessionRef> session(DASessionCreate(allocator));
   if (session.get() == NULL) {
     VLOG(1) << "Error creating DA Session.";
     return std::string();
   }
 
-  base::mac::ScopedCFTypeRef<DADiskRef> disk(
+  base::ScopedCFTypeRef<DADiskRef> disk(
       DADiskCreateFromBSDName(allocator, session, bsd_name.c_str()));
   if (disk.get() == NULL) {
     VLOG(1) << "Error creating DA disk from BSD disk name.";
     return std::string();
   }
 
-  base::mac::ScopedCFTypeRef<CFDictionaryRef> disk_description(
+  base::ScopedCFTypeRef<CFDictionaryRef> disk_description(
       DADiskCopyDescription(disk));
   if (disk_description.get() == NULL) {
     VLOG(1) << "Error getting disk description.";
@@ -74,7 +74,7 @@
     return std::string();
   }
 
-  base::mac::ScopedCFTypeRef<CFStringRef> volume_uuid_string(
+  base::ScopedCFTypeRef<CFStringRef> volume_uuid_string(
       CFUUIDCreateString(allocator, volume_uuid));
   if (volume_uuid_string.get() == NULL) {
     VLOG(1) << "Error creating string from CSStringRef.";
diff --git a/chrome/browser/extensions/api/notifications/notifications_api.cc b/chrome/browser/extensions/api/notifications/notifications_api.cc
index 7365649..b5f9600 100644
--- a/chrome/browser/extensions/api/notifications/notifications_api.cc
+++ b/chrome/browser/extensions/api/notifications/notifications_api.cc
@@ -7,7 +7,7 @@
 #include "base/callback.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/extensions/event_names.h"
 #include "chrome/browser/extensions/event_router.h"
@@ -135,18 +135,18 @@
   virtual void Display() OVERRIDE { }
 
   virtual void Error() OVERRIDE {
-    scoped_ptr<ListValue> args(CreateBaseEventArgs());
+    scoped_ptr<base::ListValue> args(CreateBaseEventArgs());
     SendEvent(event_names::kOnNotificationError, args.Pass());
   }
 
   virtual void Close(bool by_user) OVERRIDE {
-    scoped_ptr<ListValue> args(CreateBaseEventArgs());
+    scoped_ptr<base::ListValue> args(CreateBaseEventArgs());
     args->Append(Value::CreateBooleanValue(by_user));
     SendEvent(event_names::kOnNotificationClosed, args.Pass());
   }
 
   virtual void Click() OVERRIDE {
-    scoped_ptr<ListValue> args(CreateBaseEventArgs());
+    scoped_ptr<base::ListValue> args(CreateBaseEventArgs());
     SendEvent(event_names::kOnNotificationClicked, args.Pass());
   }
 
@@ -156,7 +156,7 @@
   }
 
   virtual void ButtonClick(int index) OVERRIDE {
-    scoped_ptr<ListValue> args(CreateBaseEventArgs());
+    scoped_ptr<base::ListValue> args(CreateBaseEventArgs());
     args->Append(Value::CreateIntegerValue(index));
     SendEvent(event_names::kOnNotificationButtonClicked, args.Pass());
   }
@@ -186,14 +186,14 @@
  private:
   virtual ~NotificationsApiDelegate() {}
 
-  void SendEvent(const std::string& name, scoped_ptr<ListValue> args) {
+  void SendEvent(const std::string& name, scoped_ptr<base::ListValue> args) {
     scoped_ptr<Event> event(new Event(name, args.Pass()));
     ExtensionSystem::Get(profile_)->event_router()->DispatchEventToExtension(
         extension_id_, event.Pass());
   }
 
-  scoped_ptr<ListValue> CreateBaseEventArgs() {
-    scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> CreateBaseEventArgs() {
+    scoped_ptr<base::ListValue> args(new base::ListValue());
     args->Append(Value::CreateStringValue(id_));
     return args.Pass();
   }
@@ -442,7 +442,7 @@
       notification_ui_manager->GetAllIdsByProfileAndSourceOrigin(
           profile_, extension_->url());
 
-  scoped_ptr<DictionaryValue> result(new DictionaryValue());
+  scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue());
 
   for (std::set<std::string>::iterator iter = notification_ids.begin();
        iter != notification_ids.end(); iter++) {
diff --git a/chrome/browser/extensions/api/omnibox/omnibox_api.cc b/chrome/browser/extensions/api/omnibox/omnibox_api.cc
index 774055f..400fc32 100644
--- a/chrome/browser/extensions/api/omnibox/omnibox_api.cc
+++ b/chrome/browser/extensions/api/omnibox/omnibox_api.cc
@@ -74,7 +74,7 @@
       ExtensionSystem::Get(profile)->extension_service()->extension_prefs();
 
   scoped_ptr<omnibox::SuggestResult> suggestion;
-  const DictionaryValue* dict = NULL;
+  const base::DictionaryValue* dict = NULL;
   if (prefs && prefs->ReadPrefAsDictionary(extension_id,
                                            kOmniboxDefaultSuggestion,
                                            &dict)) {
@@ -112,7 +112,7 @@
 void ExtensionOmniboxEventRouter::OnInputStarted(
     Profile* profile, const std::string& extension_id) {
   scoped_ptr<Event> event(new Event(
-      events::kOnInputStarted, make_scoped_ptr(new ListValue())));
+      events::kOnInputStarted, make_scoped_ptr(new base::ListValue())));
   event->restrict_to_profile = profile;
   ExtensionSystem::Get(profile)->event_router()->
       DispatchEventToExtension(extension_id, event.Pass());
@@ -126,7 +126,7 @@
           ExtensionHasEventListener(extension_id, events::kOnInputChanged))
     return false;
 
-  scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   args->Set(0, Value::CreateStringValue(input));
   args->Set(1, Value::CreateIntegerValue(suggest_id));
 
@@ -153,7 +153,7 @@
   extensions::TabHelper::FromWebContents(web_contents)->
       active_tab_permission_granter()->GrantIfRequested(extension);
 
-  scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   args->Set(0, Value::CreateStringValue(input));
   if (disposition == NEW_FOREGROUND_TAB)
     args->Set(1, Value::CreateStringValue(kForegroundTabDisposition));
@@ -177,7 +177,7 @@
 void ExtensionOmniboxEventRouter::OnInputCancelled(
     Profile* profile, const std::string& extension_id) {
   scoped_ptr<Event> event(new Event(
-      events::kOnInputCancelled, make_scoped_ptr(new ListValue())));
+      events::kOnInputCancelled, make_scoped_ptr(new base::ListValue())));
   event->restrict_to_profile = profile;
   ExtensionSystem::Get(profile)->event_router()->
       DispatchEventToExtension(extension_id, event.Pass());
diff --git a/chrome/browser/extensions/api/omnibox/omnibox_unittest.cc b/chrome/browser/extensions/api/omnibox/omnibox_unittest.cc
index f1ab1ed..549367f 100644
--- a/chrome/browser/extensions/api/omnibox/omnibox_unittest.cc
+++ b/chrome/browser/extensions/api/omnibox/omnibox_unittest.cc
@@ -41,7 +41,7 @@
 // +       ddd
 // = nmmmmndddn
 TEST(ExtensionOmniboxTest, DescriptionStylesSimple) {
-  scoped_ptr<ListValue> list = ListBuilder()
+  scoped_ptr<base::ListValue> list = ListBuilder()
       .Append(42)
       .Append(ListBuilder()
         .Append(DictionaryBuilder()
@@ -72,7 +72,7 @@
       *params->suggest_results[0]));
 
   // Same input, but swap the order. Ensure it still works.
-  scoped_ptr<ListValue> swap_list = ListBuilder()
+  scoped_ptr<base::ListValue> swap_list = ListBuilder()
       .Append(42)
       .Append(ListBuilder()
         .Append(DictionaryBuilder()
@@ -104,7 +104,7 @@
 // +  dd
 // = 3773unnnn66
 TEST(ExtensionOmniboxTest, DescriptionStylesCombine) {
-  scoped_ptr<ListValue> list = ListBuilder()
+  scoped_ptr<base::ListValue> list = ListBuilder()
       .Append(42)
       .Append(ListBuilder()
         .Append(DictionaryBuilder()
@@ -149,7 +149,7 @@
 
   // Try moving the "dim/match" style pair at offset 9. Output should be the
   // same.
-  scoped_ptr<ListValue> moved_list = ListBuilder()
+  scoped_ptr<base::ListValue> moved_list = ListBuilder()
       .Append(42)
       .Append(ListBuilder()
         .Append(DictionaryBuilder()
@@ -193,7 +193,7 @@
 // + ddd
 // = 77777nnnnn
 TEST(ExtensionOmniboxTest, DescriptionStylesCombine2) {
-  scoped_ptr<ListValue> list = ListBuilder()
+  scoped_ptr<base::ListValue> list = ListBuilder()
       .Append(42)
       .Append(ListBuilder()
         .Append(DictionaryBuilder()
@@ -242,7 +242,7 @@
 // = 77777nnnnn
 TEST(ExtensionOmniboxTest, DefaultSuggestResult) {
   // Default suggestions should not have a content parameter.
-  scoped_ptr<ListValue> list = ListBuilder()
+  scoped_ptr<base::ListValue> list = ListBuilder()
       .Append(DictionaryBuilder()
         .Set("description", "description")
         .Set("descriptionStyles", ListBuilder()
diff --git a/chrome/browser/extensions/api/page_capture/page_capture_api.cc b/chrome/browser/extensions/api/page_capture/page_capture_api.cc
index 62a800e..1fe87c7 100644
--- a/chrome/browser/extensions/api/page_capture/page_capture_api.cc
+++ b/chrome/browser/extensions/api/page_capture/page_capture_api.cc
@@ -175,7 +175,7 @@
   ChildProcessSecurityPolicy::GetInstance()->GrantReadFile(
       child_id, mhtml_path_);
 
-  DictionaryValue* dict = new DictionaryValue();
+  base::DictionaryValue* dict = new base::DictionaryValue();
   SetResult(dict);
   dict->SetString("mhtmlFilePath", mhtml_path_.value());
   dict->SetInteger("mhtmlFileLength", file_size);
diff --git a/chrome/browser/extensions/api/page_capture/page_capture_apitest.cc b/chrome/browser/extensions/api/page_capture/page_capture_apitest.cc
index 34e7654..a2bb28b 100644
--- a/chrome/browser/extensions/api/page_capture/page_capture_apitest.cc
+++ b/chrome/browser/extensions/api/page_capture/page_capture_apitest.cc
@@ -18,23 +18,8 @@
     ExtensionApiTest::SetUpCommandLine(command_line);
     command_line->AppendSwitchASCII(switches::kJavaScriptFlags, "--expose-gc");
   }
-
-  virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
-    ExtensionApiTest::SetUpInProcessBrowserTestFixture();
-
-    host_resolver()->AddRule("www.a.com", "127.0.0.1");
-
-    ASSERT_TRUE(StartTestServer());
-  }
 };
 
-// Disabled on Linux http://crbug.com/98194
-#if defined(OS_LINUX)
-#define MAYBE_SaveAsMHTML DISABLED_SaveAsMHTML
-#else
-#define MAYBE_SaveAsMHTML SaveAsMHTML
-#endif  // defined(OS_LINUX)
-
 class PageCaptureSaveAsMHTMLDelegate
     : public PageCaptureSaveAsMHTMLFunction::TestDelegate {
  public:
@@ -54,7 +39,9 @@
   base::FilePath temp_file_;
 };
 
-IN_PROC_BROWSER_TEST_F(ExtensionPageCaptureApiTest, MAYBE_SaveAsMHTML) {
+IN_PROC_BROWSER_TEST_F(ExtensionPageCaptureApiTest, SaveAsMHTML) {
+  host_resolver()->AddRule("www.a.com", "127.0.0.1");
+  ASSERT_TRUE(StartEmbeddedTestServer());
   PageCaptureSaveAsMHTMLDelegate delegate;
   ASSERT_TRUE(RunExtensionTest("page_capture")) << message_;
   ASSERT_FALSE(delegate.temp_file_.empty());
diff --git a/chrome/browser/extensions/api/permissions/permissions_api_helpers.cc b/chrome/browser/extensions/api/permissions/permissions_api_helpers.cc
index dff6acb..9a610c0 100644
--- a/chrome/browser/extensions/api/permissions/permissions_api_helpers.cc
+++ b/chrome/browser/extensions/api/permissions/permissions_api_helpers.cc
@@ -9,7 +9,6 @@
 #include "base/values.h"
 #include "chrome/common/extensions/api/permissions.h"
 #include "chrome/common/extensions/extension.h"
-#include "chrome/common/extensions/permissions/bluetooth_device_permission.h"
 #include "chrome/common/extensions/permissions/permission_set.h"
 #include "chrome/common/extensions/permissions/permissions_info.h"
 #include "chrome/common/extensions/permissions/usb_device_permission.h"
@@ -36,7 +35,7 @@
 const char kUnknownPermissionError[] =
     "'*' is not a recognized permission.";
 const char kUnsupportedPermissionId[] =
-    "Only the bluetoothDevices and usbDevices permissions support arguments.";
+    "Only the usbDevices permission supports arguments.";
 
 }  // namespace
 
@@ -95,14 +94,9 @@
 
         // Explicitly check the permissions that accept arguments until the bug
         // referenced above is fixed.
-        const APIPermissionInfo* bluetooth_device_permission_info =
-            info->GetByID(APIPermission::kBluetoothDevice);
         const APIPermissionInfo* usb_device_permission_info =
             info->GetByID(APIPermission::kUsbDevice);
-        if (permission_name == bluetooth_device_permission_info->name()) {
-          permission = new BluetoothDevicePermission(
-              bluetooth_device_permission_info);
-        } else if (permission_name == usb_device_permission_info->name()) {
+        if (permission_name == usb_device_permission_info->name()) {
           permission = new UsbDevicePermission(usb_device_permission_info);
         } else {
           *error = kUnsupportedPermissionId;
diff --git a/chrome/browser/extensions/api/permissions/permissions_api_helpers_unittest.cc b/chrome/browser/extensions/api/permissions/permissions_api_helpers_unittest.cc
index 429ee70..3ec4abc 100644
--- a/chrome/browser/extensions/api/permissions/permissions_api_helpers_unittest.cc
+++ b/chrome/browser/extensions/api/permissions/permissions_api_helpers_unittest.cc
@@ -41,9 +41,9 @@
 
   // Pack the permission set to value and verify its contents.
   scoped_ptr<Permissions> permissions(PackPermissionSet(permission_set.get()));
-  scoped_ptr<DictionaryValue> value(permissions->ToValue());
-  ListValue* api_list = NULL;
-  ListValue* origin_list = NULL;
+  scoped_ptr<base::DictionaryValue> value(permissions->ToValue());
+  base::ListValue* api_list = NULL;
+  base::ListValue* origin_list = NULL;
   EXPECT_TRUE(value->GetList("permissions", &api_list));
   EXPECT_TRUE(value->GetList("origins", &origin_list));
 
@@ -77,12 +77,12 @@
 // Tests various error conditions and edge cases when unpacking values
 // into PermissionSets.
 TEST(ExtensionPermissionsAPIHelpers, Unpack) {
-  scoped_ptr<ListValue> apis(new ListValue());
+  scoped_ptr<base::ListValue> apis(new base::ListValue());
   apis->Append(Value::CreateStringValue("tabs"));
-  scoped_ptr<ListValue> origins(new ListValue());
+  scoped_ptr<base::ListValue> origins(new base::ListValue());
   origins->Append(Value::CreateStringValue("http://a.com/*"));
 
-  scoped_ptr<DictionaryValue> value(new DictionaryValue());
+  scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue());
   scoped_refptr<PermissionSet> permissions;
   std::string error;
 
@@ -113,7 +113,7 @@
   {
     Permissions permissions_object;
     value->Clear();
-    scoped_ptr<ListValue> invalid_apis(apis->DeepCopy());
+    scoped_ptr<base::ListValue> invalid_apis(apis->DeepCopy());
     invalid_apis->Append(Value::CreateIntegerValue(3));
     value->Set("permissions", invalid_apis->DeepCopy());
     EXPECT_FALSE(Permissions::Populate(*value, &permissions_object));
@@ -123,7 +123,7 @@
   {
     Permissions permissions_object;
     value->Clear();
-    scoped_ptr<ListValue> invalid_origins(origins->DeepCopy());
+    scoped_ptr<base::ListValue> invalid_origins(origins->DeepCopy());
     invalid_origins->Append(Value::CreateIntegerValue(3));
     value->Set("origins", invalid_origins->DeepCopy());
     EXPECT_FALSE(Permissions::Populate(*value, &permissions_object));
@@ -161,7 +161,7 @@
   {
     Permissions permissions_object;
     value->Clear();
-    scoped_ptr<ListValue> invalid_apis(apis->DeepCopy());
+    scoped_ptr<base::ListValue> invalid_apis(apis->DeepCopy());
     invalid_apis->Append(Value::CreateStringValue("unknown_permission"));
     value->Set("permissions", invalid_apis->DeepCopy());
     EXPECT_TRUE(Permissions::Populate(*value, &permissions_object));
diff --git a/chrome/browser/extensions/api/permissions/permissions_apitest.cc b/chrome/browser/extensions/api/permissions/permissions_apitest.cc
index ef20085..1bfea06 100644
--- a/chrome/browser/extensions/api/permissions/permissions_apitest.cc
+++ b/chrome/browser/extensions/api/permissions/permissions_apitest.cc
@@ -84,7 +84,7 @@
 
   PermissionsRequestFunction::SetIgnoreUserGestureForTests(true);
   host_resolver()->AddRule("*.com", "127.0.0.1");
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   EXPECT_TRUE(RunExtensionTest("permissions/optional")) << message_;
 }
 
@@ -95,26 +95,16 @@
   PermissionsRequestFunction::SetAutoConfirmForTests(true);
   PermissionsRequestFunction::SetIgnoreUserGestureForTests(true);
   host_resolver()->AddRule("*.com", "127.0.0.1");
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   EXPECT_TRUE(RunExtensionTest("permissions/optional")) << message_;
 }
 
-// Tests that the optional permissions API works correctly with complex
-// permissions.
-IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ComplexOptionalPermissions) {
-  // Rather than setting the granted permissions, set the UI autoconfirm flag
-  // and run the same tests.
-  PermissionsRequestFunction::SetAutoConfirmForTests(true);
-  PermissionsRequestFunction::SetIgnoreUserGestureForTests(true);
-  EXPECT_TRUE(RunExtensionTest("permissions/complex_optional")) << message_;
-}
-
 // Test that denying the optional permissions confirmation dialog works.
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, OptionalPermissionsDeny) {
   PermissionsRequestFunction::SetAutoConfirmForTests(false);
   PermissionsRequestFunction::SetIgnoreUserGestureForTests(true);
   host_resolver()->AddRule("*.com", "127.0.0.1");
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   EXPECT_TRUE(RunExtensionTest("permissions/optional_deny")) << message_;
 }
 
@@ -123,7 +113,7 @@
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, OptionalPermissionsGesture) {
   PermissionsRequestFunction::SetIgnoreUserGestureForTests(false);
   host_resolver()->AddRule("*.com", "127.0.0.1");
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   EXPECT_TRUE(RunExtensionTest("permissions/optional_gesture")) << message_;
 }
 
diff --git a/chrome/browser/extensions/api/preference/preference_helpers.cc b/chrome/browser/extensions/api/preference/preference_helpers.cc
index c8f1f6b..e4192dd 100644
--- a/chrome/browser/extensions/api/preference/preference_helpers.cc
+++ b/chrome/browser/extensions/api/preference/preference_helpers.cc
@@ -88,7 +88,7 @@
 void DispatchEventToExtensions(
     Profile* profile,
     const std::string& event_name,
-    ListValue* args,
+    base::ListValue* args,
     APIPermission::ID permission,
     bool incognito,
     const std::string& browser_pref) {
@@ -108,7 +108,7 @@
         (!incognito || IncognitoInfo::IsSplitMode(it->get()) ||
          extension_service->CanCrossIncognito(it->get()))) {
       // Inject level of control key-value.
-      DictionaryValue* dict;
+      base::DictionaryValue* dict;
       bool rv = args->GetDictionary(0, &dict);
       DCHECK(rv);
       std::string level_of_control =
@@ -134,7 +134,7 @@
         }
       }
 
-      scoped_ptr<ListValue> args_copy(args->DeepCopy());
+      scoped_ptr<base::ListValue> args_copy(args->DeepCopy());
       scoped_ptr<Event> event(new Event(event_name, args_copy.Pass()));
       event->restrict_to_profile = restrict_to_profile;
       router->DispatchEventToExtension(extension_id, event.Pass());
diff --git a/chrome/browser/extensions/api/processes/processes_api.cc b/chrome/browser/extensions/api/processes/processes_api.cc
index adcd39d..5472844 100644
--- a/chrome/browser/extensions/api/processes/processes_api.cc
+++ b/chrome/browser/extensions/api/processes/processes_api.cc
@@ -44,16 +44,16 @@
 
 #if defined(ENABLE_TASK_MANAGER)
 
-DictionaryValue* CreateCacheData(
+base::DictionaryValue* CreateCacheData(
     const WebKit::WebCache::ResourceTypeStat& stat) {
 
-  DictionaryValue* cache = new DictionaryValue();
+  base::DictionaryValue* cache = new base::DictionaryValue();
   cache->SetDouble(keys::kCacheSize, static_cast<double>(stat.size));
   cache->SetDouble(keys::kCacheLiveSize, static_cast<double>(stat.liveSize));
   return cache;
 }
 
-void SetProcessType(DictionaryValue* result,
+void SetProcessType(base::DictionaryValue* result,
                     TaskManagerModel* model,
                     int index) {
   // Determine process type.
@@ -87,7 +87,6 @@
     case task_manager::Resource::GPU:
       type = keys::kProcessTypeGPU;
       break;
-    case task_manager::Resource::PROFILE_IMPORT:
     case task_manager::Resource::ZYGOTE:
     case task_manager::Resource::SANDBOX_HELPER:
     case task_manager::Resource::UNKNOWN:
@@ -99,8 +98,8 @@
   result->SetString(keys::kTypeKey, type);
 }
 
-ListValue* GetTabsForProcess(int process_id) {
-  ListValue* tabs_list = new ListValue();
+base::ListValue* GetTabsForProcess(int process_id) {
+  base::ListValue* tabs_list = new base::ListValue();
 
   // The tabs list only makes sense for render processes, so if we don't find
   // one, just return the empty list.
@@ -112,16 +111,15 @@
   int tab_id = -1;
   // We need to loop through all the RVHs to ensure we collect the set of all
   // tabs using this renderer process.
-  content::RenderProcessHost::RenderWidgetHostsIterator iter(
-      rph->GetRenderWidgetHostsIterator());
-  for (; !iter.IsAtEnd(); iter.Advance()) {
-    const content::RenderWidgetHost* widget = iter.GetCurrentValue();
-    DCHECK(widget);
-    if (!widget || !widget->IsRenderView())
+  content::RenderWidgetHost::List widgets =
+      content::RenderWidgetHost::GetRenderWidgetHosts();
+  for (size_t i = 0; i < widgets.size(); ++i) {
+    if (widgets[i]->GetProcess()->GetID() != process_id)
+      continue;
+    if (!widgets[i]->IsRenderView())
       continue;
 
-    content::RenderViewHost* host = content::RenderViewHost::From(
-        const_cast<content::RenderWidgetHost*>(widget));
+    content::RenderViewHost* host = content::RenderViewHost::From(widgets[i]);
     content::WebContents* contents =
         content::WebContents::FromRenderViewHost(host);
     if (contents) {
@@ -137,11 +135,11 @@
 // This function creates a Process object to be returned to the extensions
 // using these APIs. For memory details, which are not added by this function,
 // the callers need to use AddMemoryDetails.
-DictionaryValue* CreateProcessFromModel(int process_id,
-                                        TaskManagerModel* model,
-                                        int index,
-                                        bool include_optional) {
-  DictionaryValue* result = new DictionaryValue();
+base::DictionaryValue* CreateProcessFromModel(int process_id,
+                                              TaskManagerModel* model,
+                                              int index,
+                                              bool include_optional) {
+  base::DictionaryValue* result = new base::DictionaryValue();
   size_t mem;
 
   result->SetInteger(keys::kIdKey, process_id);
@@ -200,7 +198,7 @@
 // Since memory details are expensive to gather, we don't do it by default.
 // This function is a helper to add memory details data to an existing
 // Process object representation.
-void AddMemoryDetails(DictionaryValue* result,
+void AddMemoryDetails(base::DictionaryValue* result,
                       TaskManagerModel* model,
                       int index) {
   size_t mem;
@@ -307,8 +305,8 @@
     index = model_->GetGroupIndexForResource(start);
   }
 
-  scoped_ptr<ListValue> args(new ListValue());
-  DictionaryValue* process = CreateProcessFromModel(
+  scoped_ptr<base::ListValue> args(new base::ListValue());
+  base::DictionaryValue* process = CreateProcessFromModel(
       model_->GetUniqueChildProcessId(index), model_, index, false);
   DCHECK(process != NULL);
 
@@ -339,21 +337,21 @@
 
   DCHECK(updated || updated_memory);
 
-  IDMap<DictionaryValue> processes_map;
+  IDMap<base::DictionaryValue> processes_map;
   for (int i = start; i < start + length; i++) {
     if (model_->IsResourceFirstInGroup(i)) {
       int id = model_->GetUniqueChildProcessId(i);
-      DictionaryValue* process = CreateProcessFromModel(id, model_, i, true);
+      base::DictionaryValue* process = CreateProcessFromModel(id, model_, i, true);
       processes_map.AddWithID(process, i);
     }
   }
 
   int id;
   std::string idkey(keys::kIdKey);
-  DictionaryValue* processes = new DictionaryValue();
+  base::DictionaryValue* processes = new base::DictionaryValue();
 
   if (updated) {
-    IDMap<DictionaryValue>::iterator it(&processes_map);
+    IDMap<base::DictionaryValue>::iterator it(&processes_map);
     for (; !it.IsAtEnd(); it.Advance()) {
       if (!it.GetCurrentValue()->GetInteger(idkey, &id))
         continue;
@@ -362,13 +360,13 @@
       processes->Set(base::IntToString(id), it.GetCurrentValue());
     }
 
-    scoped_ptr<ListValue> args(new ListValue());
+    scoped_ptr<base::ListValue> args(new base::ListValue());
     args->Append(processes);
     DispatchEvent(keys::kOnUpdated, args.Pass());
   }
 
   if (updated_memory) {
-    IDMap<DictionaryValue>::iterator it(&processes_map);
+    IDMap<base::DictionaryValue>::iterator it(&processes_map);
     for (; !it.IsAtEnd(); it.Advance()) {
       if (!it.GetCurrentValue()->GetInteger(idkey, &id))
         continue;
@@ -381,7 +379,7 @@
         processes->Set(base::IntToString(id), it.GetCurrentValue());
     }
 
-    scoped_ptr<ListValue> args(new ListValue());
+    scoped_ptr<base::ListValue> args(new base::ListValue());
     args->Append(processes);
     DispatchEvent(keys::kOnUpdatedWithMemory, args.Pass());
   }
@@ -400,7 +398,7 @@
     return;
 
   // The callback function parameters.
-  scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
 
   // First arg: The id of the process that was closed.
   args->Append(Value::CreateIntegerValue(
@@ -422,7 +420,7 @@
   if (!HasEventListeners(event))
     return;
 
-  DictionaryValue* process = NULL;
+  base::DictionaryValue* process = NULL;
   int count = model_->ResourceCount();
   int id = widget->GetProcess()->GetID();
 
@@ -439,7 +437,7 @@
   if (process == NULL)
     return;
 
-  scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   args->Append(process);
 
   DispatchEvent(keys::kOnUnresponsive, args.Pass());
@@ -451,7 +449,7 @@
     content::RenderProcessHost::RendererClosedDetails* details) {
 #if defined(ENABLE_TASK_MANAGER)
   // The callback function parameters.
-  scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
 
   // First arg: The id of the process that was closed.
   args->Append(Value::CreateIntegerValue(rph->GetID()));
@@ -466,8 +464,9 @@
 #endif  // defined(ENABLE_TASK_MANAGER)
 }
 
-void ProcessesEventRouter::DispatchEvent(const char* event_name,
-                                         scoped_ptr<ListValue> event_args) {
+void ProcessesEventRouter::DispatchEvent(
+    const char* event_name,
+    scoped_ptr<base::ListValue> event_args) {
   if (extensions::ExtensionSystem::Get(profile_)->event_router()) {
     scoped_ptr<extensions::Event> event(new extensions::Event(
         event_name, event_args.Pass()));
@@ -732,7 +731,7 @@
 void GetProcessInfoFunction::GatherProcessInfo() {
 #if defined(ENABLE_TASK_MANAGER)
   TaskManagerModel* model = TaskManager::GetInstance()->model();
-  DictionaryValue* processes = new DictionaryValue();
+  base::DictionaryValue* processes = new base::DictionaryValue();
 
   // If there are no process IDs specified, it means we need to return all of
   // the ones we know of.
@@ -741,7 +740,7 @@
     for (int i = 0; i < resources; ++i) {
       if (model->IsResourceFirstInGroup(i)) {
         int id = model->GetUniqueChildProcessId(i);
-        DictionaryValue* d = CreateProcessFromModel(id, model, i, false);
+        base::DictionaryValue* d = CreateProcessFromModel(id, model, i, false);
         if (memory_)
           AddMemoryDetails(d, model, i);
         processes->Set(base::IntToString(id), d);
@@ -755,7 +754,8 @@
         std::vector<int>::iterator proc_id = std::find(process_ids_.begin(),
                                                        process_ids_.end(), id);
         if (proc_id != process_ids_.end()) {
-          DictionaryValue* d = CreateProcessFromModel(id, model, i, false);
+          base::DictionaryValue* d =
+              CreateProcessFromModel(id, model, i, false);
           if (memory_)
             AddMemoryDetails(d, model, i);
           processes->Set(base::IntToString(id), d);
diff --git a/chrome/browser/extensions/api/processes/processes_apitest.cc b/chrome/browser/extensions/api/processes/processes_apitest.cc
index af7c08b..d38a683 100644
--- a/chrome/browser/extensions/api/processes/processes_apitest.cc
+++ b/chrome/browser/extensions/api/processes/processes_apitest.cc
@@ -50,7 +50,7 @@
   EXPECT_EQ(TaskManagerModel::TASK_PENDING, model->update_state_);
 
   // Now show the task manager and wait for it to be ready
-  chrome::ShowTaskManager(browser(), false);
+  chrome::ShowTaskManager(browser());
 
   EXPECT_EQ(2, model->update_requests_);
   EXPECT_EQ(TaskManagerModel::TASK_PENDING, model->update_state_);
diff --git a/chrome/browser/extensions/api/proxy/proxy_api.cc b/chrome/browser/extensions/api/proxy/proxy_api.cc
index 054cab6..a115a1b 100644
--- a/chrome/browser/extensions/api/proxy/proxy_api.cc
+++ b/chrome/browser/extensions/api/proxy/proxy_api.cc
@@ -37,8 +37,8 @@
     EventRouterForwarder* event_router,
     void* profile,
     int error_code) {
-  scoped_ptr<ListValue> args(new ListValue());
-  DictionaryValue* dict = new DictionaryValue();
+  scoped_ptr<base::ListValue> args(new base::ListValue());
+  base::DictionaryValue* dict = new base::DictionaryValue();
   dict->SetBoolean(keys::kProxyEventFatal, true);
   dict->SetString(keys::kProxyEventError, net::ErrorToString(error_code));
   dict->SetString(keys::kProxyEventDetails, std::string());
@@ -58,8 +58,8 @@
     void* profile,
     int line_number,
     const string16& error) {
-  scoped_ptr<ListValue> args(new ListValue());
-  DictionaryValue* dict = new DictionaryValue();
+  scoped_ptr<base::ListValue> args(new base::ListValue());
+  base::DictionaryValue* dict = new base::DictionaryValue();
   dict->SetBoolean(keys::kProxyEventFatal, false);
   dict->SetString(keys::kProxyEventError,
                   net::ErrorToString(net::ERR_PAC_SCRIPT_FAILED));
@@ -95,8 +95,8 @@
   // has been verified already by the extension API to match the schema
   // defined in the extension API JSON.
   CHECK(extension_pref->IsType(Value::TYPE_DICTIONARY));
-  const DictionaryValue* config =
-      static_cast<const DictionaryValue*>(extension_pref);
+  const base::DictionaryValue* config =
+      static_cast<const base::DictionaryValue*>(extension_pref);
 
   // Extract the various pieces of information passed to
   // chrome.proxy.settings.set(). Several of these strings will
@@ -135,7 +135,7 @@
   // This is a dictionary wrapper that exposes the proxy configuration stored in
   // the browser preferences.
   ProxyConfigDictionary config(
-      static_cast<const DictionaryValue*>(browser_pref));
+      static_cast<const base::DictionaryValue*>(browser_pref));
 
   ProxyPrefs::ProxyMode mode;
   if (!config.GetMode(&mode)) {
@@ -144,7 +144,7 @@
   }
 
   // Build a new ProxyConfig instance as defined in the extension API.
-  scoped_ptr<DictionaryValue> extension_pref(new DictionaryValue);
+  scoped_ptr<base::DictionaryValue> extension_pref(new base::DictionaryValue);
 
   extension_pref->SetString(keys::kProxyConfigMode,
                             ProxyPrefs::ProxyModeToString(mode));
@@ -159,7 +159,7 @@
       // A PAC URL either point to a PAC script or contain a base64 encoded
       // PAC script. In either case we build a PacScript dictionary as defined
       // in the extension API.
-      DictionaryValue* pac_dict = helpers::CreatePacScriptDict(config);
+      base::DictionaryValue* pac_dict = helpers::CreatePacScriptDict(config);
       if (!pac_dict)
         return NULL;
       extension_pref->Set(keys::kProxyConfigPacScript, pac_dict);
@@ -167,7 +167,8 @@
     }
     case ProxyPrefs::MODE_FIXED_SERVERS: {
       // Build ProxyRules dictionary according to the extension API.
-      DictionaryValue* proxy_rules_dict = helpers::CreateProxyRulesDict(config);
+      base::DictionaryValue* proxy_rules_dict =
+          helpers::CreateProxyRulesDict(config);
       if (!proxy_rules_dict)
         return NULL;
       extension_pref->Set(keys::kProxyConfigRules, proxy_rules_dict);
diff --git a/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc b/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc
index 8dcd291..f0fc389 100644
--- a/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc
+++ b/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc
@@ -58,7 +58,7 @@
 
 // Extension Pref -> Browser Pref conversion.
 
-bool GetProxyModeFromExtensionPref(const DictionaryValue* proxy_config,
+bool GetProxyModeFromExtensionPref(const base::DictionaryValue* proxy_config,
                                    ProxyPrefs::ProxyMode* out,
                                    std::string* error,
                                    bool* bad_message) {
@@ -75,11 +75,11 @@
   return true;
 }
 
-bool GetPacMandatoryFromExtensionPref(const DictionaryValue* proxy_config,
+bool GetPacMandatoryFromExtensionPref(const base::DictionaryValue* proxy_config,
                                       bool* out,
                                       std::string* error,
                                       bool* bad_message){
-  const DictionaryValue* pac_dict = NULL;
+  const base::DictionaryValue* pac_dict = NULL;
   proxy_config->GetDictionary(keys::kProxyConfigPacScript, &pac_dict);
   if (!pac_dict)
     return true;
@@ -96,11 +96,11 @@
   return true;
 }
 
-bool GetPacUrlFromExtensionPref(const DictionaryValue* proxy_config,
+bool GetPacUrlFromExtensionPref(const base::DictionaryValue* proxy_config,
                                 std::string* out,
                                 std::string* error,
                                 bool* bad_message) {
-  const DictionaryValue* pac_dict = NULL;
+  const base::DictionaryValue* pac_dict = NULL;
   proxy_config->GetDictionary(keys::kProxyConfigPacScript, &pac_dict);
   if (!pac_dict)
     return true;
@@ -122,11 +122,11 @@
   return true;
 }
 
-bool GetPacDataFromExtensionPref(const DictionaryValue* proxy_config,
+bool GetPacDataFromExtensionPref(const base::DictionaryValue* proxy_config,
                                  std::string* out,
                                  std::string* error,
                                  bool* bad_message) {
-  const DictionaryValue* pac_dict = NULL;
+  const base::DictionaryValue* pac_dict = NULL;
   proxy_config->GetDictionary(keys::kProxyConfigPacScript, &pac_dict);
   if (!pac_dict)
     return true;
@@ -147,7 +147,7 @@
   return true;
 }
 
-bool GetProxyServer(const DictionaryValue* proxy_server,
+bool GetProxyServer(const base::DictionaryValue* proxy_server,
                     net::ProxyServer::Scheme default_scheme,
                     net::ProxyServer* out,
                     std::string* error,
@@ -188,11 +188,12 @@
   return true;
 }
 
-bool GetProxyRulesStringFromExtensionPref(const DictionaryValue* proxy_config,
-                                          std::string* out,
-                                          std::string* error,
-                                          bool* bad_message) {
-  const DictionaryValue* proxy_rules = NULL;
+bool GetProxyRulesStringFromExtensionPref(
+    const base::DictionaryValue* proxy_config,
+    std::string* out,
+    std::string* error,
+    bool* bad_message) {
+  const base::DictionaryValue* proxy_rules = NULL;
   proxy_config->GetDictionary(keys::kProxyConfigRules, &proxy_rules);
   if (!proxy_rules)
     return true;
@@ -207,7 +208,7 @@
   // singleProxy that will supersede per-URL proxies, but it's worth it to keep
   // the code simple and extensible.
   for (size_t i = 0; i <= keys::SCHEME_MAX; ++i) {
-    const DictionaryValue* proxy_dict = NULL;
+    const base::DictionaryValue* proxy_dict = NULL;
     has_proxy[i] = proxy_rules->GetDictionary(keys::field_name[i],
                                               &proxy_dict);
     if (has_proxy[i]) {
@@ -255,7 +256,7 @@
   return true;
 }
 
-bool JoinUrlList(const ListValue* list,
+bool JoinUrlList(const base::ListValue* list,
                  const std::string& joiner,
                  std::string* out,
                  std::string* error,
@@ -283,11 +284,11 @@
   return true;
 }
 
-bool GetBypassListFromExtensionPref(const DictionaryValue* proxy_config,
+bool GetBypassListFromExtensionPref(const base::DictionaryValue* proxy_config,
                                     std::string* out,
                                     std::string* error,
                                     bool* bad_message) {
-  const DictionaryValue* proxy_rules = NULL;
+  const base::DictionaryValue* proxy_rules = NULL;
   proxy_config->GetDictionary(keys::kProxyConfigRules, &proxy_rules);
   if (!proxy_rules)
     return true;
@@ -296,7 +297,7 @@
     *out = "";
     return true;
   }
-  const ListValue* bypass_list = NULL;
+  const base::ListValue* bypass_list = NULL;
   if (!proxy_rules->GetList(keys::kProxyConfigBypassList, &bypass_list)) {
     LOG(ERROR) << "'rules.bypassList' could not be parsed.";
     *bad_message = true;
@@ -306,14 +307,15 @@
   return JoinUrlList(bypass_list, ",", out, error, bad_message);
 }
 
-DictionaryValue* CreateProxyConfigDict(ProxyPrefs::ProxyMode mode_enum,
-                                       bool pac_mandatory,
-                                       const std::string& pac_url,
-                                       const std::string& pac_data,
-                                       const std::string& proxy_rules_string,
-                                       const std::string& bypass_list,
-                                       std::string* error) {
-  DictionaryValue* result_proxy_config = NULL;
+base::DictionaryValue* CreateProxyConfigDict(
+    ProxyPrefs::ProxyMode mode_enum,
+    bool pac_mandatory,
+    const std::string& pac_url,
+    const std::string& pac_data,
+    const std::string& proxy_rules_string,
+    const std::string& bypass_list,
+    std::string* error) {
+  base::DictionaryValue* result_proxy_config = NULL;
   switch (mode_enum) {
     case ProxyPrefs::MODE_DIRECT:
       result_proxy_config = ProxyConfigDictionary::CreateDirect();
@@ -357,12 +359,13 @@
   return result_proxy_config;
 }
 
-DictionaryValue* CreateProxyRulesDict(
+base::DictionaryValue* CreateProxyRulesDict(
     const ProxyConfigDictionary& proxy_config) {
   ProxyPrefs::ProxyMode mode;
   CHECK(proxy_config.GetMode(&mode) && mode == ProxyPrefs::MODE_FIXED_SERVERS);
 
-  scoped_ptr<DictionaryValue> extension_proxy_rules(new DictionaryValue);
+  scoped_ptr<base::DictionaryValue> extension_proxy_rules(
+      new base::DictionaryValue);
 
   std::string proxy_servers;
   if (!proxy_config.GetProxyServer(&proxy_servers)) {
@@ -417,15 +420,16 @@
       LOG(ERROR) << "Invalid bypassList in configuration.";
       return NULL;
     }
-    ListValue* bypass_list = TokenizeToStringList(bypass_list_string, ",;");
+    base::ListValue* bypass_list =
+        TokenizeToStringList(bypass_list_string, ",;");
     extension_proxy_rules->Set(keys::kProxyConfigBypassList, bypass_list);
   }
 
   return extension_proxy_rules.release();
 }
 
-DictionaryValue* CreateProxyServerDict(const net::ProxyServer& proxy) {
-  scoped_ptr<DictionaryValue> out(new DictionaryValue);
+base::DictionaryValue* CreateProxyServerDict(const net::ProxyServer& proxy) {
+  scoped_ptr<base::DictionaryValue> out(new base::DictionaryValue);
   switch (proxy.scheme()) {
     case net::ProxyServer::SCHEME_HTTP:
       out->SetString(keys::kProxyConfigRuleScheme, "http");
@@ -449,12 +453,12 @@
   return out.release();
 }
 
-DictionaryValue* CreatePacScriptDict(
+base::DictionaryValue* CreatePacScriptDict(
     const ProxyConfigDictionary& proxy_config) {
   ProxyPrefs::ProxyMode mode;
   CHECK(proxy_config.GetMode(&mode) && mode == ProxyPrefs::MODE_PAC_SCRIPT);
 
-  scoped_ptr<DictionaryValue> pac_script_dict(new DictionaryValue);
+  scoped_ptr<base::DictionaryValue> pac_script_dict(new base::DictionaryValue);
   std::string pac_url;
   if (!proxy_config.GetPacUrl(&pac_url)) {
     LOG(ERROR) << "Invalid proxy configuration. Missing PAC URL.";
@@ -481,9 +485,9 @@
   return pac_script_dict.release();
 }
 
-ListValue* TokenizeToStringList(const std::string& in,
+base::ListValue* TokenizeToStringList(const std::string& in,
                                 const std::string& delims) {
-  ListValue* out = new ListValue;
+  base::ListValue* out = new base::ListValue;
   base::StringTokenizer entries(in, delims);
   while (entries.GetNext())
     out->Append(Value::CreateStringValue(entries.token()));
diff --git a/chrome/browser/extensions/api/proxy/proxy_api_helpers_unittest.cc b/chrome/browser/extensions/api/proxy/proxy_api_helpers_unittest.cc
index ff3cd32..f830710 100644
--- a/chrome/browser/extensions/api/proxy/proxy_api_helpers_unittest.cc
+++ b/chrome/browser/extensions/api/proxy/proxy_api_helpers_unittest.cc
@@ -27,18 +27,18 @@
 
 // Helper function to create a ProxyServer dictionary as defined in the
 // extension API.
-DictionaryValue* CreateTestProxyServerDict(const std::string& host) {
-  DictionaryValue* dict = new DictionaryValue;
+base::DictionaryValue* CreateTestProxyServerDict(const std::string& host) {
+  base::DictionaryValue* dict = new base::DictionaryValue;
   dict->SetString(keys::kProxyConfigRuleHost, host);
   return dict;
 }
 
 // Helper function to create a ProxyServer dictionary as defined in the
 // extension API.
-DictionaryValue* CreateTestProxyServerDict(const std::string& schema,
-                                           const std::string& host,
-                                           int port) {
-  DictionaryValue* dict = new DictionaryValue;
+base::DictionaryValue* CreateTestProxyServerDict(const std::string& schema,
+                                                 const std::string& host,
+                                                 int port) {
+  base::DictionaryValue* dict = new base::DictionaryValue;
   dict->SetString(keys::kProxyConfigRuleScheme, schema);
   dict->SetString(keys::kProxyConfigRuleHost, host);
   dict->SetInteger(keys::kProxyConfigRulePort, port);
@@ -69,7 +69,7 @@
 }
 
 TEST(ExtensionProxyApiHelpers, GetProxyModeFromExtensionPref) {
-  DictionaryValue proxy_config;
+  base::DictionaryValue proxy_config;
   ProxyPrefs::ProxyMode mode;
   std::string error;
   bool bad_message = false;
@@ -99,7 +99,7 @@
   std::string error;
   bool bad_message = false;
 
-  DictionaryValue proxy_config;
+  base::DictionaryValue proxy_config;
   proxy_config.SetString(
       keys::kProxyConfigMode,
       ProxyPrefs::ProxyModeToString(ProxyPrefs::MODE_PAC_SCRIPT));
@@ -113,7 +113,7 @@
   EXPECT_FALSE(bad_message);
 
   // Set up a pac script.
-  DictionaryValue* pacScriptDict = new DictionaryValue;
+  base::DictionaryValue* pacScriptDict = new base::DictionaryValue;
   pacScriptDict->SetString(keys::kProxyConfigPacScriptUrl, kSamplePacScriptUrl);
   proxy_config.Set(keys::kProxyConfigPacScript, pacScriptDict);
 
@@ -129,7 +129,7 @@
   std::string error;
   bool bad_message = false;
 
-  DictionaryValue proxy_config;
+  base::DictionaryValue proxy_config;
   proxy_config.SetString(
       keys::kProxyConfigMode,
       ProxyPrefs::ProxyModeToString(ProxyPrefs::MODE_PAC_SCRIPT));
@@ -142,7 +142,7 @@
   EXPECT_FALSE(bad_message);
 
   // Set up a PAC script.
-  DictionaryValue* pacScriptDict = new DictionaryValue;
+  base::DictionaryValue* pacScriptDict = new base::DictionaryValue;
   pacScriptDict->SetString(keys::kProxyConfigPacScriptData, kSamplePacScript);
   proxy_config.Set(keys::kProxyConfigPacScript, pacScriptDict);
 
@@ -158,7 +158,7 @@
   std::string error;
   bool bad_message = false;
 
-  DictionaryValue proxy_config;
+  base::DictionaryValue proxy_config;
   proxy_config.SetString(
       keys::kProxyConfigMode,
       ProxyPrefs::ProxyModeToString(ProxyPrefs::MODE_FIXED_SERVERS));
@@ -171,7 +171,7 @@
   EXPECT_EQ(std::string(), out);
   EXPECT_EQ(std::string(), error);
 
-  DictionaryValue* proxy_rules = new DictionaryValue;
+  base::DictionaryValue* proxy_rules = new base::DictionaryValue;
   proxy_rules->Set(keys::field_name[1], CreateTestProxyServerDict("proxy1"));
   proxy_rules->Set(keys::field_name[2], CreateTestProxyServerDict("proxy2"));
   proxy_config.Set(keys::kProxyConfigRules, proxy_rules);
@@ -189,7 +189,7 @@
   std::string error;
   bool bad_message = false;
 
-  DictionaryValue proxy_config;
+  base::DictionaryValue proxy_config;
   proxy_config.SetString(
       keys::kProxyConfigMode,
       ProxyPrefs::ProxyModeToString(ProxyPrefs::MODE_FIXED_SERVERS));
@@ -203,10 +203,10 @@
   EXPECT_EQ(std::string(), error);
   EXPECT_FALSE(bad_message);
 
-  ListValue* bypass_list = new ListValue;
+  base::ListValue* bypass_list = new base::ListValue;
   bypass_list->Append(Value::CreateStringValue("host1"));
   bypass_list->Append(Value::CreateStringValue("host2"));
-  DictionaryValue* proxy_rules = new DictionaryValue;
+  base::DictionaryValue* proxy_rules = new base::DictionaryValue;
   proxy_rules->Set(keys::kProxyConfigBypassList, bypass_list);
   proxy_config.Set(keys::kProxyConfigRules, proxy_rules);
 
@@ -220,8 +220,9 @@
 
 TEST(ExtensionProxyApiHelpers, CreateProxyConfigDict) {
   std::string error;
-  scoped_ptr<DictionaryValue> exp_direct(ProxyConfigDictionary::CreateDirect());
-  scoped_ptr<DictionaryValue> out_direct(
+  scoped_ptr<base::DictionaryValue> exp_direct(
+      ProxyConfigDictionary::CreateDirect());
+  scoped_ptr<base::DictionaryValue> out_direct(
       CreateProxyConfigDict(ProxyPrefs::MODE_DIRECT,
                             false,
                             std::string(),
@@ -231,9 +232,9 @@
                             &error));
   EXPECT_TRUE(Value::Equals(exp_direct.get(), out_direct.get()));
 
-  scoped_ptr<DictionaryValue> exp_auto(
+  scoped_ptr<base::DictionaryValue> exp_auto(
       ProxyConfigDictionary::CreateAutoDetect());
-  scoped_ptr<DictionaryValue> out_auto(
+  scoped_ptr<base::DictionaryValue> out_auto(
       CreateProxyConfigDict(ProxyPrefs::MODE_AUTO_DETECT,
                             false,
                             std::string(),
@@ -243,9 +244,9 @@
                             &error));
   EXPECT_TRUE(Value::Equals(exp_auto.get(), out_auto.get()));
 
-  scoped_ptr<DictionaryValue> exp_pac_url(
+  scoped_ptr<base::DictionaryValue> exp_pac_url(
       ProxyConfigDictionary::CreatePacScript(kSamplePacScriptUrl, false));
-  scoped_ptr<DictionaryValue> out_pac_url(
+  scoped_ptr<base::DictionaryValue> out_pac_url(
       CreateProxyConfigDict(ProxyPrefs::MODE_PAC_SCRIPT,
                             false,
                             kSamplePacScriptUrl,
@@ -255,9 +256,9 @@
                             &error));
   EXPECT_TRUE(Value::Equals(exp_pac_url.get(), out_pac_url.get()));
 
-  scoped_ptr<DictionaryValue> exp_pac_data(
+  scoped_ptr<base::DictionaryValue> exp_pac_data(
       ProxyConfigDictionary::CreatePacScript(kSamplePacScriptAsDataUrl, false));
-  scoped_ptr<DictionaryValue> out_pac_data(
+  scoped_ptr<base::DictionaryValue> out_pac_data(
       CreateProxyConfigDict(ProxyPrefs::MODE_PAC_SCRIPT,
                             false,
                             std::string(),
@@ -267,9 +268,9 @@
                             &error));
   EXPECT_TRUE(Value::Equals(exp_pac_data.get(), out_pac_data.get()));
 
-  scoped_ptr<DictionaryValue> exp_fixed(
+  scoped_ptr<base::DictionaryValue> exp_fixed(
       ProxyConfigDictionary::CreateFixedServers("foo:80", "localhost"));
-  scoped_ptr<DictionaryValue> out_fixed(
+  scoped_ptr<base::DictionaryValue> out_fixed(
       CreateProxyConfigDict(ProxyPrefs::MODE_FIXED_SERVERS,
                             false,
                             std::string(),
@@ -279,8 +280,9 @@
                             &error));
   EXPECT_TRUE(Value::Equals(exp_fixed.get(), out_fixed.get()));
 
-  scoped_ptr<DictionaryValue> exp_system(ProxyConfigDictionary::CreateSystem());
-  scoped_ptr<DictionaryValue> out_system(
+  scoped_ptr<base::DictionaryValue> exp_system(
+      ProxyConfigDictionary::CreateSystem());
+  scoped_ptr<base::DictionaryValue> out_system(
       CreateProxyConfigDict(ProxyPrefs::MODE_SYSTEM,
                             false,
                             std::string(),
@@ -295,7 +297,7 @@
 }
 
 TEST(ExtensionProxyApiHelpers, GetProxyServer) {
-  DictionaryValue proxy_server_dict;
+  base::DictionaryValue proxy_server_dict;
   net::ProxyServer created;
   std::string error;
   bool bad_message = false;
@@ -320,7 +322,7 @@
 
 TEST(ExtensionProxyApiHelpers, JoinUrlList) {
   bool bad_message = false;
-  ListValue list;
+  base::ListValue list;
   list.Append(Value::CreateStringValue("s1"));
   list.Append(Value::CreateStringValue("s2"));
   list.Append(Value::CreateStringValue("s3"));
@@ -334,15 +336,16 @@
 
 // This tests CreateProxyServerDict as well.
 TEST(ExtensionProxyApiHelpers, CreateProxyRulesDict) {
-  scoped_ptr<DictionaryValue> browser_pref(
+  scoped_ptr<base::DictionaryValue> browser_pref(
       ProxyConfigDictionary::CreateFixedServers(
           "http=proxy1:80;https=proxy2:80;ftp=proxy3:80;socks=proxy4:80",
           "localhost"));
   ProxyConfigDictionary config(browser_pref.get());
-  scoped_ptr<DictionaryValue> extension_pref(CreateProxyRulesDict(config));
+  scoped_ptr<base::DictionaryValue> extension_pref(
+      CreateProxyRulesDict(config));
   ASSERT_TRUE(extension_pref.get());
 
-  scoped_ptr<DictionaryValue> expected(new DictionaryValue);
+  scoped_ptr<base::DictionaryValue> expected(new base::DictionaryValue);
   expected->Set("proxyForHttp",
                 CreateTestProxyServerDict("http", "proxy1", 80));
   expected->Set("proxyForHttps",
@@ -351,7 +354,7 @@
                 CreateTestProxyServerDict("http", "proxy3", 80));
   expected->Set("fallbackProxy",
                 CreateTestProxyServerDict("socks4", "proxy4", 80));
-  ListValue* bypass_list = new ListValue;
+  base::ListValue* bypass_list = new base::ListValue;
   bypass_list->Append(Value::CreateStringValue("localhost"));
   expected->Set(keys::kProxyConfigBypassList, bypass_list);
 
@@ -360,16 +363,17 @@
 
 // Test multiple proxies per scheme -- expect that only the first is returned.
 TEST(ExtensionProxyApiHelpers, CreateProxyRulesDictMultipleProxies) {
-  scoped_ptr<DictionaryValue> browser_pref(
+  scoped_ptr<base::DictionaryValue> browser_pref(
       ProxyConfigDictionary::CreateFixedServers(
           "http=proxy1:80,default://;https=proxy2:80,proxy1:80;ftp=proxy3:80,"
           "https://proxy5:443;socks=proxy4:80,proxy1:80",
           "localhost"));
   ProxyConfigDictionary config(browser_pref.get());
-  scoped_ptr<DictionaryValue> extension_pref(CreateProxyRulesDict(config));
+  scoped_ptr<base::DictionaryValue> extension_pref(
+      CreateProxyRulesDict(config));
   ASSERT_TRUE(extension_pref.get());
 
-  scoped_ptr<DictionaryValue> expected(new DictionaryValue);
+  scoped_ptr<base::DictionaryValue> expected(new base::DictionaryValue);
   expected->Set("proxyForHttp",
                 CreateTestProxyServerDict("http", "proxy1", 80));
   expected->Set("proxyForHttps",
@@ -378,7 +382,7 @@
                 CreateTestProxyServerDict("http", "proxy3", 80));
   expected->Set("fallbackProxy",
                 CreateTestProxyServerDict("socks4", "proxy4", 80));
-  ListValue* bypass_list = new ListValue;
+  base::ListValue* bypass_list = new base::ListValue;
   bypass_list->Append(Value::CreateStringValue("localhost"));
   expected->Set(keys::kProxyConfigBypassList, bypass_list);
 
@@ -387,13 +391,13 @@
 
 // Test if a PAC script URL is specified.
 TEST(ExtensionProxyApiHelpers, CreatePacScriptDictWithUrl) {
-  scoped_ptr<DictionaryValue> browser_pref(
+  scoped_ptr<base::DictionaryValue> browser_pref(
       ProxyConfigDictionary::CreatePacScript(kSamplePacScriptUrl, false));
   ProxyConfigDictionary config(browser_pref.get());
-  scoped_ptr<DictionaryValue> extension_pref(CreatePacScriptDict(config));
+  scoped_ptr<base::DictionaryValue> extension_pref(CreatePacScriptDict(config));
   ASSERT_TRUE(extension_pref.get());
 
-  scoped_ptr<DictionaryValue> expected(new DictionaryValue);
+  scoped_ptr<base::DictionaryValue> expected(new base::DictionaryValue);
   expected->SetString(keys::kProxyConfigPacScriptUrl, kSamplePacScriptUrl);
   expected->SetBoolean(keys::kProxyConfigPacScriptMandatory, false);
 
@@ -402,13 +406,13 @@
 
 // Test if a PAC script is encoded in a data URL.
 TEST(ExtensionProxyApiHelpers, CreatePacScriptDictWidthData) {
-  scoped_ptr<DictionaryValue> browser_pref(
+  scoped_ptr<base::DictionaryValue> browser_pref(
       ProxyConfigDictionary::CreatePacScript(kSamplePacScriptAsDataUrl, false));
   ProxyConfigDictionary config(browser_pref.get());
-  scoped_ptr<DictionaryValue> extension_pref(CreatePacScriptDict(config));
+  scoped_ptr<base::DictionaryValue> extension_pref(CreatePacScriptDict(config));
   ASSERT_TRUE(extension_pref.get());
 
-  scoped_ptr<DictionaryValue> expected(new DictionaryValue);
+  scoped_ptr<base::DictionaryValue> expected(new base::DictionaryValue);
   expected->SetString(keys::kProxyConfigPacScriptData, kSamplePacScript);
   expected->SetBoolean(keys::kProxyConfigPacScriptMandatory, false);
 
@@ -416,12 +420,12 @@
 }
 
 TEST(ExtensionProxyApiHelpers, TokenizeToStringList) {
-  ListValue expected;
+  base::ListValue expected;
   expected.Append(Value::CreateStringValue("s1"));
   expected.Append(Value::CreateStringValue("s2"));
   expected.Append(Value::CreateStringValue("s3"));
 
-  scoped_ptr<ListValue> out(TokenizeToStringList("s1;s2;s3", ";"));
+  scoped_ptr<base::ListValue> out(TokenizeToStringList("s1;s2;s3", ";"));
   EXPECT_TRUE(Value::Equals(&expected, out.get()));
 }
 
diff --git a/chrome/browser/extensions/api/proxy/proxy_apitest.cc b/chrome/browser/extensions/api/proxy/proxy_apitest.cc
index be76c40..a05e71a 100644
--- a/chrome/browser/extensions/api/proxy/proxy_apitest.cc
+++ b/chrome/browser/extensions/api/proxy/proxy_apitest.cc
@@ -283,7 +283,7 @@
 
 // Tests error events: invalid proxy
 IN_PROC_BROWSER_TEST_F(ProxySettingsApiTest, MAYBE_ProxyEventsInvalidProxy) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(
       RunExtensionSubtest("proxy/events", "invalid_proxy.html")) << message_;
 }
diff --git a/chrome/browser/extensions/api/push_messaging/obfuscated_gaia_id_fetcher.cc b/chrome/browser/extensions/api/push_messaging/obfuscated_gaia_id_fetcher.cc
index 3dc1267..6063b1f 100644
--- a/chrome/browser/extensions/api/push_messaging/obfuscated_gaia_id_fetcher.cc
+++ b/chrome/browser/extensions/api/push_messaging/obfuscated_gaia_id_fetcher.cc
@@ -127,7 +127,7 @@
   if (!value.get())
     return false;
 
-  DictionaryValue* dict = NULL;
+  base::DictionaryValue* dict = NULL;
   if (!value->GetAsDictionary(&dict))
     return false;
 
diff --git a/chrome/browser/extensions/api/push_messaging/push_messaging_api.cc b/chrome/browser/extensions/api/push_messaging/push_messaging_api.cc
index c84a393..9d89f17 100644
--- a/chrome/browser/extensions/api/push_messaging/push_messaging_api.cc
+++ b/chrome/browser/extensions/api/push_messaging/push_messaging_api.cc
@@ -19,11 +19,11 @@
 #include "chrome/browser/extensions/extension_system_factory.h"
 #include "chrome/browser/extensions/token_cache/token_cache_service.h"
 #include "chrome/browser/extensions/token_cache/token_cache_service_factory.h"
+#include "chrome/browser/invalidation/invalidation_service.h"
+#include "chrome/browser/invalidation/invalidation_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/token_service.h"
 #include "chrome/browser/signin/token_service_factory.h"
-#include "chrome/browser/sync/profile_sync_service.h"
-#include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "chrome/common/extensions/api/push_messaging.h"
@@ -302,17 +302,18 @@
 void PushMessagingAPI::Observe(int type,
                                const content::NotificationSource& source,
                                const content::NotificationDetails& details) {
-  ProfileSyncService* pss = ProfileSyncServiceFactory::GetForProfile(profile_);
+  invalidation::InvalidationService* invalidation_service =
+      invalidation::InvalidationServiceFactory::GetForProfile(profile_);
   // This may be NULL; for example, for the ChromeOS guest user. In these cases,
   // just return without setting up anything, since it won't work anyway.
-  if (!pss)
+  if (!invalidation_service)
     return;
 
   if (!event_router_)
     event_router_.reset(new PushMessagingEventRouter(profile_));
   if (!handler_) {
     handler_.reset(new PushMessagingInvalidationHandler(
-        pss, event_router_.get()));
+        invalidation_service, event_router_.get()));
   }
   switch (type) {
     case chrome::NOTIFICATION_EXTENSION_INSTALLED: {
@@ -351,7 +352,7 @@
 template <>
 void ProfileKeyedAPIFactory<PushMessagingAPI>::DeclareFactoryDependencies() {
   DependsOn(ExtensionSystemFactory::GetInstance());
-  DependsOn(ProfileSyncServiceFactory::GetInstance());
+  DependsOn(invalidation::InvalidationServiceFactory::GetInstance());
 }
 
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/push_messaging/push_messaging_apitest.cc b/chrome/browser/extensions/api/push_messaging/push_messaging_apitest.cc
index 6960205..6a38470 100644
--- a/chrome/browser/extensions/api/push_messaging/push_messaging_apitest.cc
+++ b/chrome/browser/extensions/api/push_messaging/push_messaging_apitest.cc
@@ -10,19 +10,23 @@
 #include "chrome/browser/extensions/extension_apitest.h"
 #include "chrome/browser/extensions/extension_test_message_listener.h"
 #include "chrome/browser/extensions/platform_app_launcher.h"
+#include "chrome/browser/invalidation/fake_invalidation_service.h"
+#include "chrome/browser/invalidation/invalidation_service.h"
+#include "chrome/browser/invalidation/invalidation_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/sync/profile_sync_service.h"
-#include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "google/cacheinvalidation/types.pb.h"
+#include "sync/notifier/fake_invalidator.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
 using ::testing::_;
 using ::testing::SaveArg;
 using ::testing::StrictMock;
 
+using invalidation::InvalidationServiceFactory;
+
 namespace extensions {
 
 namespace {
@@ -52,10 +56,34 @@
 
 class PushMessagingApiTest : public ExtensionApiTest {
  public:
+  PushMessagingApiTest()
+      : fake_invalidation_service_(NULL) {
+  }
+
   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
     ExtensionApiTest::SetUpCommandLine(command_line);
   }
 
+  virtual void SetUp() OVERRIDE {
+    InvalidationServiceFactory::GetInstance()->
+        SetBuildOnlyFakeInvalidatorsForTest(true);
+    ExtensionApiTest::SetUp();
+  }
+
+  virtual void SetUpOnMainThread() OVERRIDE {
+    ExtensionApiTest::SetUpOnMainThread();
+    fake_invalidation_service_ =
+        static_cast<invalidation::FakeInvalidationService*>(
+            InvalidationServiceFactory::GetInstance()->GetForProfile(
+                profile()));
+  }
+
+  void EmitInvalidation(
+      const invalidation::ObjectId& object_id,
+      const std::string& payload) {
+    fake_invalidation_service_->EmitInvalidationForTest(object_id, payload);
+  }
+
   PushMessagingAPI* GetAPI() {
     return PushMessagingAPI::Get(profile());
   }
@@ -63,6 +91,8 @@
   PushMessagingEventRouter* GetEventRouter() {
     return PushMessagingAPI::Get(profile())->GetEventRouterForTest();
   }
+
+  invalidation::FakeInvalidationService* fake_invalidation_service_;
 };
 
 IN_PROC_BROWSER_TEST_F(PushMessagingApiTest, EventDispatch) {
@@ -92,18 +122,14 @@
   ui_test_utils::NavigateToURL(
       browser(), extension->GetResourceURL("event_dispatch.html"));
 
-  ProfileSyncService* pss =
-      ProfileSyncServiceFactory::GetForProfile(profile());
-  ASSERT_TRUE(pss);
-
   // PushMessagingInvalidationHandler suppresses the initial invalidation on
   // each subchannel at install, so trigger the suppressions first.
   for (int i = 0; i < 3; ++i) {
-    pss->EmitInvalidationForTest(
+    EmitInvalidation(
         ExtensionAndSubchannelToObjectId(extension->id(), i), std::string());
   }
 
-  pss->EmitInvalidationForTest(
+  EmitInvalidation(
       ExtensionAndSubchannelToObjectId(extension->id(), 1), "payload");
   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
 }
diff --git a/chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler.cc b/chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler.cc
index 95eb4e7..f9208e5 100644
--- a/chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler.cc
+++ b/chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler.cc
@@ -10,7 +10,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler_delegate.h"
-#include "chrome/browser/invalidation/invalidation_frontend.h"
+#include "chrome/browser/invalidation/invalidation_service.h"
 #include "chrome/common/extensions/extension.h"
 #include "google/cacheinvalidation/types.pb.h"
 
@@ -78,7 +78,7 @@
 }  // namespace
 
 PushMessagingInvalidationHandler::PushMessagingInvalidationHandler(
-    invalidation::InvalidationFrontend* service,
+    invalidation::InvalidationService* service,
     PushMessagingInvalidationHandlerDelegate* delegate)
     : service_(service),
       delegate_(delegate) {
diff --git a/chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler.h b/chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler.h
index ef40b76..4f7d9e3 100644
--- a/chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler.h
+++ b/chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler.h
@@ -15,7 +15,7 @@
 #include "sync/notifier/invalidation_handler.h"
 
 namespace invalidation {
-class InvalidationFrontend;
+class InvalidationService;
 }
 
 namespace extensions {
@@ -32,7 +32,7 @@
   // |extension_ids| is the set of extension IDs for which push messaging is
   // enabled.
   PushMessagingInvalidationHandler(
-      invalidation::InvalidationFrontend* service,
+      invalidation::InvalidationService* service,
       PushMessagingInvalidationHandlerDelegate* delegate);
   virtual ~PushMessagingInvalidationHandler();
 
@@ -56,7 +56,7 @@
   void UpdateRegistrations();
 
   base::ThreadChecker thread_checker_;
-  invalidation::InvalidationFrontend* const service_;
+  invalidation::InvalidationService* const service_;
   std::set<std::string> registered_extensions_;
   syncer::ObjectIdSet suppressed_ids_;
   PushMessagingInvalidationHandlerDelegate* const delegate_;
diff --git a/chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler_unittest.cc b/chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler_unittest.cc
index 9ab280b..9db3b46 100644
--- a/chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler_unittest.cc
+++ b/chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler_unittest.cc
@@ -7,7 +7,7 @@
 #include "base/basictypes.h"
 #include "base/memory/scoped_ptr.h"
 #include "chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler_delegate.h"
-#include "chrome/browser/invalidation/invalidation_frontend.h"
+#include "chrome/browser/invalidation/invalidation_service.h"
 #include "google/cacheinvalidation/types.pb.h"
 #include "sync/internal_api/public/base/invalidation_test_util.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -22,10 +22,10 @@
 
 namespace {
 
-class MockInvalidationFrontend : public invalidation::InvalidationFrontend {
+class MockInvalidationService : public invalidation::InvalidationService {
  public:
-  MockInvalidationFrontend();
-  ~MockInvalidationFrontend();
+  MockInvalidationService();
+  ~MockInvalidationService();
   MOCK_METHOD1(RegisterInvalidationHandler,
                void(syncer::InvalidationHandler*));
   MOCK_METHOD2(UpdateRegisteredInvalidationIds,
@@ -35,13 +35,14 @@
   MOCK_METHOD2(AcknowledgeInvalidation, void(const invalidation::ObjectId&,
                                              const syncer::AckHandle&));
   MOCK_CONST_METHOD0(GetInvalidatorState, syncer::InvalidatorState());
+  MOCK_CONST_METHOD0(GetInvalidatorClientId, std::string());
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(MockInvalidationFrontend);
+  DISALLOW_COPY_AND_ASSIGN(MockInvalidationService);
 };
 
-MockInvalidationFrontend::MockInvalidationFrontend() {}
-MockInvalidationFrontend::~MockInvalidationFrontend() {}
+MockInvalidationService::MockInvalidationService() {}
+MockInvalidationService::~MockInvalidationService() {}
 
 class MockInvalidationHandlerDelegate
     : public PushMessagingInvalidationHandlerDelegate {
@@ -74,7 +75,7 @@
     EXPECT_CALL(service_, UnregisterInvalidationHandler(handler_.get()));
     handler_.reset();
   }
-  StrictMock<MockInvalidationFrontend> service_;
+  StrictMock<MockInvalidationService> service_;
   StrictMock<MockInvalidationHandlerDelegate> delegate_;
   scoped_ptr<PushMessagingInvalidationHandler> handler_;
 };
diff --git a/chrome/browser/extensions/api/push_messaging/sync_setup_helper.cc b/chrome/browser/extensions/api/push_messaging/sync_setup_helper.cc
index b0292d9..f4dffc3 100644
--- a/chrome/browser/extensions/api/push_messaging/sync_setup_helper.cc
+++ b/chrome/browser/extensions/api/push_messaging/sync_setup_helper.cc
@@ -29,7 +29,8 @@
 
 bool SyncSetupHelper::InitializeSync(Profile* profile) {
   profile_ = profile;
-  client_.reset(new ProfileSyncServiceHarness(profile_, username_, password_));
+  client_.reset(
+      ProfileSyncServiceHarness::Create(profile_, username_, password_));
 
   if (client_->service()->IsSyncEnabledAndLoggedIn())
     return true;
diff --git a/chrome/browser/extensions/api/record/record_api.h b/chrome/browser/extensions/api/record/record_api.h
index e5c6189..d0ea960 100644
--- a/chrome/browser/extensions/api/record/record_api.h
+++ b/chrome/browser/extensions/api/record/record_api.h
@@ -7,7 +7,7 @@
 
 #include "base/command_line.h"
 #include "base/files/file_path.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/extensions/extension_function.h"
 
 namespace {
diff --git a/chrome/browser/extensions/api/record/record_api_test.cc b/chrome/browser/extensions/api/record/record_api_test.cc
index c276ba3..4548501 100644
--- a/chrome/browser/extensions/api/record/record_api_test.cc
+++ b/chrome/browser/extensions/api/record/record_api_test.cc
@@ -188,7 +188,7 @@
     InProcessBrowserTest::CleanUpOnMainThread();
     for (std::vector<base::FilePath>::const_iterator it = temp_files_.begin();
         it != temp_files_.end(); ++it) {
-      if (!file_util::Delete(*it, false))
+      if (!base::Delete(*it, false))
         NOTREACHED();
     }
   }
@@ -241,7 +241,7 @@
 
   // Verify that the URL list of good and bad URLs was properly handled.
   // Needed by several tests.
-  bool VerifyURLHandling(const ListValue* result,
+  bool VerifyURLHandling(const base::ListValue* result,
       const TestProcessStrategy& strategy) {
 
     // Check that the two bad URLs are returned.
@@ -345,7 +345,7 @@
    // Check for return value with proper stats.
   EXPECT_EQ(kTestStatistics, utils::GetString(result.get(), kStatsKey));
 
-  ListValue* errors = NULL;
+  base::ListValue* errors = NULL;
   EXPECT_TRUE(result->GetList(kErrorsKey, &errors));
   EXPECT_TRUE(VerifyURLHandling(errors, strategy));
 }
diff --git a/chrome/browser/extensions/api/rtc_private/rtc_private_api.cc b/chrome/browser/extensions/api/rtc_private/rtc_private_api.cc
index 6018a81..5a0a120 100644
--- a/chrome/browser/extensions/api/rtc_private/rtc_private_api.cc
+++ b/chrome/browser/extensions/api/rtc_private/rtc_private_api.cc
@@ -8,7 +8,7 @@
 #include "base/message_loop.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/value_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/chromeos/contacts/contact.pb.h"
diff --git a/chrome/browser/extensions/api/runtime/runtime_api.cc b/chrome/browser/extensions/api/runtime/runtime_api.cc
index d00ab43..c04d181 100644
--- a/chrome/browser/extensions/api/runtime/runtime_api.cc
+++ b/chrome/browser/extensions/api/runtime/runtime_api.cc
@@ -4,7 +4,11 @@
 
 #include "chrome/browser/extensions/api/runtime/runtime_api.h"
 
+#include <utility>
+
+#include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/extensions/event_router.h"
 #include "chrome/browser/extensions/extension_host.h"
@@ -19,7 +23,6 @@
 #include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/common/chrome_notification_types.h"
-#include "chrome/common/extensions/api/runtime.h"
 #include "chrome/common/extensions/background_info.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/omaha_query_params/omaha_query_params.h"
@@ -42,6 +45,7 @@
 const char kOnUpdateAvailableEvent[] = "runtime.onUpdateAvailable";
 const char kOnBrowserUpdateAvailableEvent[] =
     "runtime.onBrowserUpdateAvailable";
+const char kOnRestartRequiredEvent[] = "runtime.onRestartRequired";
 const char kNoBackgroundPageError[] = "You do not have a background page.";
 const char kPageLoadError[] = "Background page failed to load.";
 const char kInstallReason[] = "reason";
@@ -100,7 +104,7 @@
     return;
   }
 
-  scoped_ptr<base::ListValue> event_args(new ListValue());
+  scoped_ptr<base::ListValue> event_args(new base::ListValue());
   scoped_ptr<Event> event(new Event(kOnStartupEvent, event_args.Pass()));
   system->event_router()->DispatchEventToExtension(extension_id, event.Pass());
 }
@@ -143,7 +147,7 @@
   // chance to register for events. So we register on its behalf. If the
   // extension does not actually have a listener, the event will just be
   // ignored.
-  scoped_ptr<base::ListValue> event_args(new ListValue());
+  scoped_ptr<base::ListValue> event_args(new base::ListValue());
   base::DictionaryValue* info = new base::DictionaryValue();
   event_args->Append(info);
   if (old_version.IsValid()) {
@@ -166,12 +170,12 @@
 void RuntimeEventRouter::DispatchOnUpdateAvailableEvent(
     Profile* profile,
     const std::string& extension_id,
-    const DictionaryValue* manifest) {
+    const base::DictionaryValue* manifest) {
   ExtensionSystem* system = ExtensionSystem::Get(profile);
   if (!system)
     return;
 
-  scoped_ptr<ListValue> args(new ListValue);
+  scoped_ptr<base::ListValue> args(new base::ListValue);
   args->Append(manifest->DeepCopy());
   DCHECK(system->event_router());
   scoped_ptr<Event> event(new Event(kOnUpdateAvailableEvent, args.Pass()));
@@ -185,7 +189,7 @@
   if (!system)
     return;
 
-  scoped_ptr<ListValue> args(new ListValue);
+  scoped_ptr<base::ListValue> args(new base::ListValue);
   DCHECK(system->event_router());
   scoped_ptr<Event> event(new Event(kOnBrowserUpdateAvailableEvent,
                                     args.Pass()));
@@ -193,8 +197,25 @@
 }
 
 // static
+void RuntimeEventRouter::DispatchOnRestartRequiredEvent(
+    Profile* profile,
+    const std::string& app_id,
+    api::runtime::OnRestartRequired::Reason reason) {
+  ExtensionSystem* system = ExtensionSystem::Get(profile);
+  if (!system)
+    return;
+
+  scoped_ptr<Event> event(
+      new Event(kOnRestartRequiredEvent,
+                api::runtime::OnRestartRequired::Create(reason)));
+
+  DCHECK(system->event_router());
+  system->event_router()->DispatchEventToExtension(app_id, event.Pass());
+}
+
+// static
 void RuntimeEventRouter::OnExtensionUninstalled(
-    Profile *profile,
+    Profile* profile,
     const std::string& extension_id) {
 #if defined(ENABLE_EXTENSIONS)
   GURL uninstall_url(GetUninstallUrl(ExtensionPrefs::Get(profile),
@@ -409,7 +430,7 @@
   if (!policy->CanReadFile(renderer_id, path))
     policy->GrantReadFile(renderer_id, path);
 
-  DictionaryValue* dict = new DictionaryValue();
+  base::DictionaryValue* dict = new base::DictionaryValue();
   SetResult(dict);
   dict->SetString("fileSystemId", filesystem_id);
   dict->SetString("baseName", relative_path);
diff --git a/chrome/browser/extensions/api/runtime/runtime_api.h b/chrome/browser/extensions/api/runtime/runtime_api.h
index c21255e..d936945 100644
--- a/chrome/browser/extensions/api/runtime/runtime_api.h
+++ b/chrome/browser/extensions/api/runtime/runtime_api.h
@@ -5,7 +5,10 @@
 #ifndef CHROME_BROWSER_EXTENSIONS_API_RUNTIME_RUNTIME_API_H_
 #define CHROME_BROWSER_EXTENSIONS_API_RUNTIME_RUNTIME_API_H_
 
+#include <string>
+
 #include "chrome/browser/extensions/extension_function.h"
+#include "chrome/common/extensions/api/runtime.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 
@@ -40,6 +43,12 @@
   // Dispatches the onBrowserUpdateAvailable event to all extensions.
   static void DispatchOnBrowserUpdateAvailableEvent(Profile* profile);
 
+  // Dispatches the onRestartRequired event to the given app.
+  static void DispatchOnRestartRequiredEvent(
+      Profile* profile,
+      const std::string& app_id,
+      api::runtime::OnRestartRequired::Reason reason);
+
   // Does any work needed at extension uninstall (e.g. load uninstall url).
   static void OnExtensionUninstalled(Profile* profile,
                                      const std::string& extension_id);
diff --git a/chrome/browser/extensions/api/runtime/runtime_apitest.cc b/chrome/browser/extensions/api/runtime/runtime_apitest.cc
index 55f0d2a..c2c17be 100644
--- a/chrome/browser/extensions/api/runtime/runtime_apitest.cc
+++ b/chrome/browser/extensions/api/runtime/runtime_apitest.cc
@@ -6,6 +6,7 @@
 #include "chrome/browser/extensions/extension_apitest.h"
 #include "chrome/browser/extensions/extension_function_test_utils.h"
 #include "chrome/test/base/ui_test_utils.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
 
 // Tests the privileged components of chrome.runtime.
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ChromeRuntimePrivileged) {
@@ -14,14 +15,14 @@
 
 // Tests the unprivileged components of chrome.runtime.
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ChromeRuntimeUnprivileged) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(
       LoadExtension(test_data_dir_.AppendASCII("runtime/content_script")));
 
   // The content script runs on webpage.html.
   ResultCatcher catcher;
   ui_test_utils::NavigateToURL(browser(),
-                               test_server()->GetURL("webpage.html"));
+                               embedded_test_server()->GetURL("/webpage.html"));
   EXPECT_TRUE(catcher.GetNextResult()) << message_;
 }
 
diff --git a/chrome/browser/extensions/api/serial/serial_api.cc b/chrome/browser/extensions/api/serial/serial_api.cc
index 1a36453..b0e7925 100644
--- a/chrome/browser/extensions/api/serial/serial_api.cc
+++ b/chrome/browser/extensions/api/serial/serial_api.cc
@@ -60,7 +60,7 @@
 void SerialGetPortsFunction::Work() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
 
-  ListValue* ports = new ListValue();
+  base::ListValue* ports = new base::ListValue();
   SerialPortEnumerator::StringSet port_names =
       SerialPortEnumerator::GenerateValidSerialPortNames();
   SerialPortEnumerator::StringSet::const_iterator i = port_names.begin();
@@ -96,7 +96,7 @@
   EXTENSION_FUNCTION_VALIDATE(params_.get());
 
   if (params_->options.get()) {
-    scoped_ptr<DictionaryValue> options = params_->options->ToValue();
+    scoped_ptr<base::DictionaryValue> options = params_->options->ToValue();
     if (options->HasKey(kBitrateKey))
       EXTENSION_FUNCTION_VALIDATE(options->GetInteger(kBitrateKey, &bitrate_));
   }
@@ -128,12 +128,12 @@
       id = -1;
     }
 
-    DictionaryValue* result = new DictionaryValue();
+    base::DictionaryValue* result = new base::DictionaryValue();
     result->SetInteger(kConnectionIdKey, id);
     SetResult(result);
     AsyncWorkCompleted();
   } else {
-    DictionaryValue* result = new DictionaryValue();
+    base::DictionaryValue* result = new base::DictionaryValue();
     result->SetInteger(kConnectionIdKey, -1);
     SetResult(result);
     AsyncWorkCompleted();
@@ -218,7 +218,7 @@
   if (serial_connection)
     bytes_read = serial_connection->Read(io_buffer);
 
-  DictionaryValue* result = new DictionaryValue();
+  base::DictionaryValue* result = new base::DictionaryValue();
 
   // The API is defined to require a 'data' value, so we will always
   // create a BinaryValue, even if it's zero-length.
@@ -262,7 +262,7 @@
   else
     error_ = kSerialConnectionNotFoundError;
 
-  DictionaryValue* result = new DictionaryValue();
+  base::DictionaryValue* result = new base::DictionaryValue();
   result->SetInteger(kBytesWrittenKey, bytes_written);
   SetResult(result);
 }
@@ -318,7 +318,7 @@
 }
 
 void SerialGetControlSignalsFunction::Work() {
-  DictionaryValue *result = new DictionaryValue();
+  base::DictionaryValue *result = new base::DictionaryValue();
   SerialConnection* serial_connection = GetSerialConnection(
       params_->connection_id);
   if (serial_connection) {
diff --git a/chrome/browser/extensions/api/serial/serial_apitest.cc b/chrome/browser/extensions/api/serial/serial_apitest.cc
index 9b1d8dd..646dfd1 100644
--- a/chrome/browser/extensions/api/serial/serial_apitest.cc
+++ b/chrome/browser/extensions/api/serial/serial_apitest.cc
@@ -36,7 +36,7 @@
 class FakeSerialGetPortsFunction : public AsyncExtensionFunction {
  public:
   virtual bool RunImpl() OVERRIDE {
-    ListValue* ports = new ListValue();
+    base::ListValue* ports = new base::ListValue();
     ports->Append(Value::CreateStringValue("/dev/fakeserial"));
     ports->Append(Value::CreateStringValue("\\\\COM800\\"));
     SetResult(ports);
diff --git a/chrome/browser/extensions/api/socket/socket_api.cc b/chrome/browser/extensions/api/socket/socket_api.cc
index b21769f..6a43ce7 100644
--- a/chrome/browser/extensions/api/socket/socket_api.cc
+++ b/chrome/browser/extensions/api/socket/socket_api.cc
@@ -151,7 +151,7 @@
   }
   DCHECK(socket);
 
-  DictionaryValue* result = new DictionaryValue();
+  base::DictionaryValue* result = new base::DictionaryValue();
   result->SetInteger(kSocketIdKey, manager_->Add(socket));
   SetResult(result);
 }
@@ -348,7 +348,7 @@
 
 void SocketAcceptFunction::OnAccept(int result_code,
                                     net::TCPClientSocket *socket) {
-  DictionaryValue* result = new DictionaryValue();
+  base::DictionaryValue* result = new base::DictionaryValue();
   result->SetInteger(kResultCodeKey, result_code);
   if (socket) {
     Socket *client_socket = new TCPSocket(socket, extension_id(), true);
@@ -383,7 +383,7 @@
 
 void SocketReadFunction::OnCompleted(int bytes_read,
                                      scoped_refptr<net::IOBuffer> io_buffer) {
-  DictionaryValue* result = new DictionaryValue();
+  base::DictionaryValue* result = new base::DictionaryValue();
   result->SetInteger(kResultCodeKey, bytes_read);
   if (bytes_read > 0) {
     result->Set(kDataKey,
@@ -429,7 +429,7 @@
 }
 
 void SocketWriteFunction::OnCompleted(int bytes_written) {
-  DictionaryValue* result = new DictionaryValue();
+  base::DictionaryValue* result = new base::DictionaryValue();
   result->SetInteger(kBytesWrittenKey, bytes_written);
   SetResult(result);
 
@@ -462,7 +462,7 @@
                                          scoped_refptr<net::IOBuffer> io_buffer,
                                          const std::string& address,
                                          int port) {
-  DictionaryValue* result = new DictionaryValue();
+  base::DictionaryValue* result = new base::DictionaryValue();
   result->SetInteger(kResultCodeKey, bytes_read);
   if (bytes_read > 0) {
     result->Set(kDataKey,
@@ -541,7 +541,7 @@
 }
 
 void SocketSendToFunction::OnCompleted(int bytes_written) {
-  DictionaryValue* result = new DictionaryValue();
+  base::DictionaryValue* result = new base::DictionaryValue();
   result->SetInteger(kBytesWrittenKey, bytes_written);
   SetResult(result);
 
diff --git a/chrome/browser/extensions/api/socket/socket_apitest.cc b/chrome/browser/extensions/api/socket/socket_apitest.cc
index 970c922..0d0f8c8 100644
--- a/chrome/browser/extensions/api/socket/socket_apitest.cc
+++ b/chrome/browser/extensions/api/socket/socket_apitest.cc
@@ -125,7 +125,8 @@
   scoped_ptr<base::Value> result(utils::RunFunctionAndReturnSingleResult(
       socket_create_function.get(), "[\"udp\"]", browser(), utils::NONE));
   ASSERT_EQ(base::Value::TYPE_DICTIONARY, result->GetType());
-  DictionaryValue *value = static_cast<DictionaryValue*>(result.get());
+  base::DictionaryValue *value =
+      static_cast<base::DictionaryValue*>(result.get());
   int socketId = -1;
   EXPECT_TRUE(value->GetInteger("socketId", &socketId));
   EXPECT_TRUE(socketId > 0);
@@ -142,7 +143,8 @@
   scoped_ptr<base::Value> result(utils::RunFunctionAndReturnSingleResult(
       socket_create_function.get(), "[\"tcp\"]", browser(), utils::NONE));
   ASSERT_EQ(base::Value::TYPE_DICTIONARY, result->GetType());
-  DictionaryValue *value = static_cast<DictionaryValue*>(result.get());
+  base::DictionaryValue *value =
+      static_cast<base::DictionaryValue*>(result.get());
   int socketId = -1;
   EXPECT_TRUE(value->GetInteger("socketId", &socketId));
   ASSERT_TRUE(socketId > 0);
@@ -162,7 +164,7 @@
 
   // If we're invoking socket tests, all we can confirm is that we have at
   // least one address, but not what it is.
-  ListValue *value = static_cast<ListValue*>(result.get());
+  base::ListValue *value = static_cast<base::ListValue*>(result.get());
   ASSERT_TRUE(value->GetSize() > 0);
 }
 
diff --git a/chrome/browser/extensions/api/storage/setting_sync_data.cc b/chrome/browser/extensions/api/storage/setting_sync_data.cc
index cb4fe79..42f72f2 100644
--- a/chrome/browser/extensions/api/storage/setting_sync_data.cc
+++ b/chrome/browser/extensions/api/storage/setting_sync_data.cc
@@ -51,7 +51,7 @@
   if (!value.get()) {
     LOG(WARNING) << "Specifics for " << specifics.extension_id() << "/" <<
         specifics.key() << " had bad JSON for value: " << specifics.value();
-    value.reset(new DictionaryValue());
+    value.reset(new base::DictionaryValue());
   }
   internal_ = new Internal(
       change_type,
diff --git a/chrome/browser/extensions/api/storage/settings_apitest.cc b/chrome/browser/extensions/api/storage/settings_apitest.cc
index 433f69c..45e3386 100644
--- a/chrome/browser/extensions/api/storage/settings_apitest.cc
+++ b/chrome/browser/extensions/api/storage/settings_apitest.cc
@@ -196,7 +196,7 @@
       Namespace settings_namespace,
       const std::string& action,
       bool is_final_action) {
-    scoped_ptr<DictionaryValue> message(new DictionaryValue());
+    scoped_ptr<base::DictionaryValue> message(new base::DictionaryValue());
     message->SetString("namespace", ToString(settings_namespace));
     message->SetString("action", action);
     message->SetBoolean("isFinalAction", is_final_action);
@@ -454,7 +454,7 @@
   policy::PolicyService* service = connector->policy_service();
   scoped_refptr<const policy::PolicyDomainDescriptor> descriptor =
       service->GetPolicyDomainDescriptor(policy::POLICY_DOMAIN_EXTENSIONS);
-  EXPECT_TRUE(descriptor);
+  EXPECT_TRUE(descriptor.get());
 }
 
 IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest, ManagedStorage) {
diff --git a/chrome/browser/extensions/api/storage/settings_backend.cc b/chrome/browser/extensions/api/storage/settings_backend.cc
index e1a5d37..cd4976a 100644
--- a/chrome/browser/extensions/api/storage/settings_backend.cc
+++ b/chrome/browser/extensions/api/storage/settings_backend.cc
@@ -41,12 +41,13 @@
 ValueStore* SettingsBackend::GetStorage(
     const std::string& extension_id) const {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-  DictionaryValue empty;
+  base::DictionaryValue empty;
   return GetOrCreateStorageWithSyncData(extension_id, empty);
 }
 
 SyncableSettingsStorage* SettingsBackend::GetOrCreateStorageWithSyncData(
-    const std::string& extension_id, const DictionaryValue& sync_data) const {
+    const std::string& extension_id,
+    const base::DictionaryValue& sync_data) const {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
 
   StorageObjMap::iterator maybe_storage = storage_objs_.find(extension_id);
@@ -132,10 +133,10 @@
 
 static void AddAllSyncData(
     const std::string& extension_id,
-    const DictionaryValue& src,
+    const base::DictionaryValue& src,
     syncer::ModelType type,
     syncer::SyncDataList* dst) {
-  for (DictionaryValue::Iterator it(src); !it.IsAtEnd(); it.Advance()) {
+  for (base::DictionaryValue::Iterator it(src); !it.IsAtEnd(); it.Advance()) {
     dst->push_back(settings_sync_util::CreateData(
         extension_id, it.key(), it.value(), type));
   }
@@ -184,14 +185,15 @@
   sync_error_factory_ = sync_error_factory.Pass();
 
   // Group the initial sync data by extension id.
-  std::map<std::string, linked_ptr<DictionaryValue> > grouped_sync_data;
+  std::map<std::string, linked_ptr<base::DictionaryValue> > grouped_sync_data;
   for (syncer::SyncDataList::const_iterator it = initial_sync_data.begin();
       it != initial_sync_data.end(); ++it) {
     SettingSyncData data(*it);
-    linked_ptr<DictionaryValue> sync_data =
+    linked_ptr<base::DictionaryValue> sync_data =
         grouped_sync_data[data.extension_id()];
     if (!sync_data.get()) {
-      sync_data = linked_ptr<DictionaryValue>(new DictionaryValue());
+      sync_data = linked_ptr<base::DictionaryValue>(
+          new base::DictionaryValue());
       grouped_sync_data[data.extension_id()] = sync_data;
     }
     DCHECK(!sync_data->HasKey(data.key())) <<
@@ -203,7 +205,7 @@
   // the future will start being synced as part of the creation process.
   for (StorageObjMap::iterator it = storage_objs_.begin();
       it != storage_objs_.end(); ++it) {
-    std::map<std::string, linked_ptr<DictionaryValue> >::iterator
+    std::map<std::string, linked_ptr<base::DictionaryValue> >::iterator
         maybe_sync_data = grouped_sync_data.find(it->first);
     syncer::SyncError error;
     if (maybe_sync_data != grouped_sync_data.end()) {
@@ -212,7 +214,7 @@
           CreateSettingsSyncProcessor(it->first).Pass());
       grouped_sync_data.erase(it->first);
     } else {
-      DictionaryValue empty;
+      base::DictionaryValue empty;
       error = it->second->StartSyncing(
           empty,
           CreateSettingsSyncProcessor(it->first).Pass());
@@ -224,7 +226,7 @@
   // Eagerly create and init the rest of the storage areas that have sync data.
   // Under normal circumstances (i.e. not first-time sync) this will be all of
   // them.
-  for (std::map<std::string, linked_ptr<DictionaryValue> >::iterator it =
+  for (std::map<std::string, linked_ptr<base::DictionaryValue> >::iterator it =
       grouped_sync_data.begin(); it != grouped_sync_data.end(); ++it) {
     GetOrCreateStorageWithSyncData(it->first, *it->second);
   }
@@ -247,7 +249,7 @@
   }
 
   // Create any storage areas that don't exist yet but have sync data.
-  DictionaryValue empty;
+  base::DictionaryValue empty;
   for (std::map<std::string, SettingSyncDataList>::iterator
       it = grouped_sync_data.begin(); it != grouped_sync_data.end(); ++it) {
     SyncableSettingsStorage* storage =
diff --git a/chrome/browser/extensions/api/storage/settings_backend.h b/chrome/browser/extensions/api/storage/settings_backend.h
index 9de4f0e..0882b68 100644
--- a/chrome/browser/extensions/api/storage/settings_backend.h
+++ b/chrome/browser/extensions/api/storage/settings_backend.h
@@ -72,7 +72,7 @@
   // initializing sync with some initial data if sync enabled.
   SyncableSettingsStorage* GetOrCreateStorageWithSyncData(
       const std::string& extension_id,
-      const DictionaryValue& sync_data) const;
+      const base::DictionaryValue& sync_data) const;
 
   // Gets all extension IDs known to extension settings.  This may not be all
   // installed extensions.
diff --git a/chrome/browser/extensions/api/storage/settings_frontend.cc b/chrome/browser/extensions/api/storage/settings_frontend.cc
index dece669..a14ed69 100644
--- a/chrome/browser/extensions/api/storage/settings_frontend.cc
+++ b/chrome/browser/extensions/api/storage/settings_frontend.cc
@@ -44,7 +44,7 @@
       const std::string& change_json) OVERRIDE {
     // TODO(gdk): This is a temporary hack while the refactoring for
     // string-based event payloads is removed. http://crbug.com/136045
-    scoped_ptr<ListValue> args(new ListValue());
+    scoped_ptr<base::ListValue> args(new base::ListValue());
     args->Append(base::JSONReader::Read(change_json));
     args->Append(Value::CreateStringValue(settings_namespace::ToString(
         settings_namespace)));
diff --git a/chrome/browser/extensions/api/storage/settings_frontend_unittest.cc b/chrome/browser/extensions/api/storage/settings_frontend_unittest.cc
index 28015a8..9705531 100644
--- a/chrome/browser/extensions/api/storage/settings_frontend_unittest.cc
+++ b/chrome/browser/extensions/api/storage/settings_frontend_unittest.cc
@@ -40,7 +40,7 @@
 
 // Creates a megabyte of data.
 scoped_ptr<Value> CreateMegabyte() {
-  ListValue* megabyte = new ListValue();
+  base::ListValue* megabyte = new base::ListValue();
   for (int i = 0; i < 1000; ++i) {
     megabyte->Append(CreateKilobyte().release());
   }
diff --git a/chrome/browser/extensions/api/storage/settings_quota_unittest.cc b/chrome/browser/extensions/api/storage/settings_quota_unittest.cc
index 8ed71e8..0e4ea79 100644
--- a/chrome/browser/extensions/api/storage/settings_quota_unittest.cc
+++ b/chrome/browser/extensions/api/storage/settings_quota_unittest.cc
@@ -11,6 +11,10 @@
 #include "chrome/browser/value_store/testing_value_store.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+using base::DictionaryValue;
+using base::ListValue;
+using base::Value;
+
 namespace extensions {
 
 // To save typing ValueStore::DEFAULTS/IGNORE_QUOTA everywhere.
diff --git a/chrome/browser/extensions/api/storage/settings_storage_quota_enforcer.cc b/chrome/browser/extensions/api/storage/settings_storage_quota_enforcer.cc
index ffe05ab..c64dd6c 100644
--- a/chrome/browser/extensions/api/storage/settings_storage_quota_enforcer.cc
+++ b/chrome/browser/extensions/api/storage/settings_storage_quota_enforcer.cc
@@ -91,7 +91,7 @@
     return;
   }
 
-  for (DictionaryValue::Iterator it(*maybe_settings->settings().get());
+  for (base::DictionaryValue::Iterator it(*maybe_settings->settings().get());
        !it.IsAtEnd(); it.Advance()) {
     Allocate(it.key(), it.value(), &used_total_, &used_per_setting_);
   }
@@ -164,10 +164,11 @@
 }
 
 ValueStore::WriteResult SettingsStorageQuotaEnforcer::Set(
-    WriteOptions options, const DictionaryValue& values) {
+    WriteOptions options, const base::DictionaryValue& values) {
   size_t new_used_total = used_total_;
   std::map<std::string, size_t> new_used_per_setting = used_per_setting_;
-  for (DictionaryValue::Iterator it(values); !it.IsAtEnd(); it.Advance()) {
+  for (base::DictionaryValue::Iterator it(values); !it.IsAtEnd();
+       it.Advance()) {
     Allocate(it.key(), it.value(), &new_used_total, &new_used_per_setting);
 
     if (!(options & IGNORE_QUOTA) &&
diff --git a/chrome/browser/extensions/api/storage/settings_storage_quota_enforcer.h b/chrome/browser/extensions/api/storage/settings_storage_quota_enforcer.h
index 537ee33..7db793e 100644
--- a/chrome/browser/extensions/api/storage/settings_storage_quota_enforcer.h
+++ b/chrome/browser/extensions/api/storage/settings_storage_quota_enforcer.h
@@ -42,7 +42,7 @@
       const std::string& key,
       const Value& value) OVERRIDE;
   virtual WriteResult Set(
-      WriteOptions options, const DictionaryValue& values) OVERRIDE;
+      WriteOptions options, const base::DictionaryValue& values) OVERRIDE;
   virtual WriteResult Remove(const std::string& key) OVERRIDE;
   virtual WriteResult Remove(const std::vector<std::string>& keys) OVERRIDE;
   virtual WriteResult Clear() OVERRIDE;
diff --git a/chrome/browser/extensions/api/storage/settings_sync_processor.cc b/chrome/browser/extensions/api/storage/settings_sync_processor.cc
index 06b4ee8..b016e9e 100644
--- a/chrome/browser/extensions/api/storage/settings_sync_processor.cc
+++ b/chrome/browser/extensions/api/storage/settings_sync_processor.cc
@@ -31,11 +31,12 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
 }
 
-void SettingsSyncProcessor::Init(const DictionaryValue& initial_state) {
+void SettingsSyncProcessor::Init(const base::DictionaryValue& initial_state) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
   CHECK(!initialized_) << "Init called multiple times";
 
-  for (DictionaryValue::Iterator i(initial_state); !i.IsAtEnd(); i.Advance())
+  for (base::DictionaryValue::Iterator i(initial_state); !i.IsAtEnd();
+       i.Advance())
     synced_keys_.insert(i.key());
 
   initialized_ = true;
diff --git a/chrome/browser/extensions/api/storage/settings_sync_processor.h b/chrome/browser/extensions/api/storage/settings_sync_processor.h
index 834e026..acc836f 100644
--- a/chrome/browser/extensions/api/storage/settings_sync_processor.h
+++ b/chrome/browser/extensions/api/storage/settings_sync_processor.h
@@ -31,7 +31,7 @@
   ~SettingsSyncProcessor();
 
   // Initializes this with the initial state of sync.
-  void Init(const DictionaryValue& initial_state);
+  void Init(const base::DictionaryValue& initial_state);
 
   // Sends |changes| to sync.
   syncer::SyncError SendChanges(const ValueStoreChangeList& changes);
diff --git a/chrome/browser/extensions/api/storage/settings_sync_unittest.cc b/chrome/browser/extensions/api/storage/settings_sync_unittest.cc
index ae4a353..b1b22a9 100644
--- a/chrome/browser/extensions/api/storage/settings_sync_unittest.cc
+++ b/chrome/browser/extensions/api/storage/settings_sync_unittest.cc
@@ -24,6 +24,9 @@
 #include "sync/api/sync_error_factory_mock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+using base::DictionaryValue;
+using base::ListValue;
+using base::Value;
 using content::BrowserThread;
 
 namespace extensions {
@@ -94,6 +97,7 @@
     if (fail_all_requests_) {
       return syncer::SyncError(
           FROM_HERE,
+          syncer::SyncError::DATATYPE_ERROR,
           "MockSyncChangeProcessor: configured to fail",
           change_list[0].sync_data().GetDataType());
     }
diff --git a/chrome/browser/extensions/api/storage/settings_sync_util.cc b/chrome/browser/extensions/api/storage/settings_sync_util.cc
index b9246e0..4509ee9 100644
--- a/chrome/browser/extensions/api/storage/settings_sync_util.cc
+++ b/chrome/browser/extensions/api/storage/settings_sync_util.cc
@@ -98,7 +98,7 @@
     const std::string& extension_id,
     const std::string& key,
     syncer::ModelType type) {
-  DictionaryValue no_value;
+  base::DictionaryValue no_value;
   return syncer::SyncChange(
       FROM_HERE,
       syncer::SyncChange::ACTION_DELETE,
diff --git a/chrome/browser/extensions/api/storage/settings_test_util.cc b/chrome/browser/extensions/api/storage/settings_test_util.cc
index 30bf92b..3d8d110 100644
--- a/chrome/browser/extensions/api/storage/settings_test_util.cc
+++ b/chrome/browser/extensions/api/storage/settings_test_util.cc
@@ -60,11 +60,11 @@
     const std::string& id,
     Manifest::Type type,
     const std::set<std::string>& permissions_set) {
-  DictionaryValue manifest;
+  base::DictionaryValue manifest;
   manifest.SetString("name", std::string("Test extension ") + id);
   manifest.SetString("version", "1.0");
 
-  scoped_ptr<ListValue> permissions(new ListValue());
+  scoped_ptr<base::ListValue> permissions(new base::ListValue());
   for (std::set<std::string>::const_iterator it = permissions_set.begin();
       it != permissions_set.end(); ++it) {
     permissions->Append(Value::CreateStringValue(*it));
@@ -76,8 +76,8 @@
       break;
 
     case Manifest::TYPE_LEGACY_PACKAGED_APP: {
-      DictionaryValue* app = new DictionaryValue();
-      DictionaryValue* app_launch = new DictionaryValue();
+      base::DictionaryValue* app = new base::DictionaryValue();
+      base::DictionaryValue* app_launch = new base::DictionaryValue();
       app_launch->SetString("local_path", "fake.html");
       app->Set("launch", app_launch);
       manifest.Set("app", app);
diff --git a/chrome/browser/extensions/api/storage/storage_api.cc b/chrome/browser/extensions/api/storage/storage_api.cc
index bfc41a5..d86b763 100644
--- a/chrome/browser/extensions/api/storage/storage_api.cc
+++ b/chrome/browser/extensions/api/storage/storage_api.cc
@@ -113,10 +113,12 @@
 namespace {
 
 // Adds all StringValues from a ListValue to a vector of strings.
-void AddAllStringValues(const ListValue& from, std::vector<std::string>* to) {
+void AddAllStringValues(const base::ListValue& from,
+                        std::vector<std::string>* to) {
   DCHECK(to->empty());
   std::string as_string;
-  for (ListValue::const_iterator it = from.begin(); it != from.end(); ++it) {
+  for (base::ListValue::const_iterator it = from.begin();
+       it != from.end(); ++it) {
     if ((*it)->GetAsString(&as_string)) {
       to->push_back(as_string);
     }
@@ -124,9 +126,9 @@
 }
 
 // Gets the keys of a DictionaryValue.
-std::vector<std::string> GetKeys(const DictionaryValue& dict) {
+std::vector<std::string> GetKeys(const base::DictionaryValue& dict) {
   std::vector<std::string> keys;
-  for (DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) {
+  for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) {
     keys.push_back(it.key());
   }
   return keys;
@@ -162,33 +164,34 @@
 }  // namespace
 
 bool StorageStorageAreaGetFunction::RunWithStorage(ValueStore* storage) {
-  Value* input = NULL;
+  base::Value* input = NULL;
   EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &input));
 
   switch (input->GetType()) {
-    case Value::TYPE_NULL:
+    case base::Value::TYPE_NULL:
       return UseReadResult(storage->Get());
 
-    case Value::TYPE_STRING: {
+    case base::Value::TYPE_STRING: {
       std::string as_string;
       input->GetAsString(&as_string);
       return UseReadResult(storage->Get(as_string));
     }
 
-    case Value::TYPE_LIST: {
+    case base::Value::TYPE_LIST: {
       std::vector<std::string> as_string_list;
-      AddAllStringValues(*static_cast<ListValue*>(input), &as_string_list);
+      AddAllStringValues(*static_cast<base::ListValue*>(input),
+                         &as_string_list);
       return UseReadResult(storage->Get(as_string_list));
     }
 
-    case Value::TYPE_DICTIONARY: {
-      DictionaryValue* as_dict = static_cast<DictionaryValue*>(input);
+    case base::Value::TYPE_DICTIONARY: {
+      base::DictionaryValue* as_dict = static_cast<base::DictionaryValue*>(input);
       ValueStore::ReadResult result = storage->Get(GetKeys(*as_dict));
       if (result->HasError()) {
         return UseReadResult(result.Pass());
       }
 
-      DictionaryValue* with_default_values = as_dict->DeepCopy();
+      base::DictionaryValue* with_default_values = as_dict->DeepCopy();
       with_default_values->MergeDictionary(result->settings().get());
       return UseReadResult(
           ValueStore::MakeReadResult(with_default_values));
@@ -202,26 +205,27 @@
 
 bool StorageStorageAreaGetBytesInUseFunction::RunWithStorage(
     ValueStore* storage) {
-  Value* input = NULL;
+  base::Value* input = NULL;
   EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &input));
 
   size_t bytes_in_use = 0;
 
   switch (input->GetType()) {
-    case Value::TYPE_NULL:
+    case base::Value::TYPE_NULL:
       bytes_in_use = storage->GetBytesInUse();
       break;
 
-    case Value::TYPE_STRING: {
+    case base::Value::TYPE_STRING: {
       std::string as_string;
       input->GetAsString(&as_string);
       bytes_in_use = storage->GetBytesInUse(as_string);
       break;
     }
 
-    case Value::TYPE_LIST: {
+    case base::Value::TYPE_LIST: {
       std::vector<std::string> as_string_list;
-      AddAllStringValues(*static_cast<ListValue*>(input), &as_string_list);
+      AddAllStringValues(*static_cast<base::ListValue*>(input),
+                         &as_string_list);
       bytes_in_use = storage->GetBytesInUse(as_string_list);
       break;
     }
@@ -231,12 +235,12 @@
       return false;
   }
 
-  SetResult(Value::CreateIntegerValue(bytes_in_use));
+  SetResult(base::Value::CreateIntegerValue(bytes_in_use));
   return true;
 }
 
 bool StorageStorageAreaSetFunction::RunWithStorage(ValueStore* storage) {
-  DictionaryValue* input = NULL;
+  base::DictionaryValue* input = NULL;
   EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &input));
   return UseWriteResult(storage->Set(ValueStore::DEFAULTS, *input));
 }
@@ -247,19 +251,20 @@
 }
 
 bool StorageStorageAreaRemoveFunction::RunWithStorage(ValueStore* storage) {
-  Value* input = NULL;
+  base::Value* input = NULL;
   EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &input));
 
   switch (input->GetType()) {
-    case Value::TYPE_STRING: {
+    case base::Value::TYPE_STRING: {
       std::string as_string;
       input->GetAsString(&as_string);
       return UseWriteResult(storage->Remove(as_string));
     }
 
-    case Value::TYPE_LIST: {
+    case base::Value::TYPE_LIST: {
       std::vector<std::string> as_string_list;
-      AddAllStringValues(*static_cast<ListValue*>(input), &as_string_list);
+      AddAllStringValues(*static_cast<base::ListValue*>(input),
+                         &as_string_list);
       return UseWriteResult(storage->Remove(as_string_list));
     }
 
diff --git a/chrome/browser/extensions/api/storage/storage_schema_manifest_handler_unittest.cc b/chrome/browser/extensions/api/storage/storage_schema_manifest_handler_unittest.cc
index 1d0a7bb..a7fd429 100644
--- a/chrome/browser/extensions/api/storage/storage_schema_manifest_handler_unittest.cc
+++ b/chrome/browser/extensions/api/storage/storage_schema_manifest_handler_unittest.cc
@@ -48,7 +48,7 @@
       return NULL;
     base::FilePath schema_path = temp_dir_.path().AppendASCII("schema.json");
     if (schema.empty()) {
-      file_util::Delete(schema_path, false);
+      base::Delete(schema_path, false);
     } else {
       if (file_util::WriteFile(schema_path, schema.data(), schema.size()) !=
           static_cast<int>(schema.size())) {
diff --git a/chrome/browser/extensions/api/storage/syncable_settings_storage.cc b/chrome/browser/extensions/api/storage/syncable_settings_storage.cc
index 221ebeb..66fd94f 100644
--- a/chrome/browser/extensions/api/storage/syncable_settings_storage.cc
+++ b/chrome/browser/extensions/api/storage/syncable_settings_storage.cc
@@ -75,7 +75,7 @@
 }
 
 ValueStore::WriteResult SyncableSettingsStorage::Set(
-    WriteOptions options, const DictionaryValue& values) {
+    WriteOptions options, const base::DictionaryValue& values) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
   WriteResult result = delegate_->Set(options, values);
   if (result->HasError()) {
@@ -129,7 +129,7 @@
 // Sync-related methods.
 
 syncer::SyncError SyncableSettingsStorage::StartSyncing(
-    const DictionaryValue& sync_state,
+    const base::DictionaryValue& sync_state,
     scoped_ptr<SettingsSyncProcessor> sync_processor) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
   DCHECK(!sync_processor_.get());
@@ -141,11 +141,12 @@
   if (maybe_settings->HasError()) {
     return syncer::SyncError(
         FROM_HERE,
+        syncer::SyncError::DATATYPE_ERROR,
         std::string("Failed to get settings: ") + maybe_settings->error(),
         sync_processor_->type());
   }
 
-  const DictionaryValue& settings = *maybe_settings->settings().get();
+  const base::DictionaryValue& settings = *maybe_settings->settings().get();
   if (sync_state.empty())
     return SendLocalSettingsToSync(settings);
   else
@@ -153,11 +154,11 @@
 }
 
 syncer::SyncError SyncableSettingsStorage::SendLocalSettingsToSync(
-    const DictionaryValue& settings) {
+    const base::DictionaryValue& settings) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
 
   ValueStoreChangeList changes;
-  for (DictionaryValue::Iterator i(settings); !i.IsAtEnd(); i.Advance()) {
+  for (base::DictionaryValue::Iterator i(settings); !i.IsAtEnd(); i.Advance()) {
     changes.push_back(ValueStoreChange(i.key(), NULL, i.value().DeepCopy()));
   }
 
@@ -172,14 +173,15 @@
 }
 
 syncer::SyncError SyncableSettingsStorage::OverwriteLocalSettingsWithSync(
-    const DictionaryValue& sync_state, const DictionaryValue& settings) {
+    const base::DictionaryValue& sync_state,
+    const base::DictionaryValue& settings) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
   // Treat this as a list of changes to sync and use ProcessSyncChanges.
   // This gives notifications etc for free.
-  scoped_ptr<DictionaryValue> new_sync_state(sync_state.DeepCopy());
+  scoped_ptr<base::DictionaryValue> new_sync_state(sync_state.DeepCopy());
 
   SettingSyncDataList changes;
-  for (DictionaryValue::Iterator it(settings); !it.IsAtEnd(); it.Advance()) {
+  for (base::DictionaryValue::Iterator it(settings); !it.IsAtEnd(); it.Advance()) {
     Value* orphaned_sync_value = NULL;
     if (new_sync_state->RemoveWithoutPathExpansion(
           it.key(), &orphaned_sync_value)) {
@@ -202,13 +204,13 @@
               syncer::SyncChange::ACTION_DELETE,
               extension_id_,
               it.key(),
-              scoped_ptr<Value>(new DictionaryValue())));
+              scoped_ptr<Value>(new base::DictionaryValue())));
     }
   }
 
   // Add all new settings to local settings.
   while (!new_sync_state->empty()) {
-    DictionaryValue::Iterator first_entry(*new_sync_state);
+    base::DictionaryValue::Iterator first_entry(*new_sync_state);
     std::string key = first_entry.key();
     Value* value = NULL;
     CHECK(new_sync_state->RemoveWithoutPathExpansion(key, &value));
@@ -239,6 +241,7 @@
   if (!sync_processor_.get()) {
     return syncer::SyncError(
         FROM_HERE,
+        syncer::SyncError::DATATYPE_ERROR,
         std::string("Sync is inactive for ") + extension_id_,
         syncer::UNSPECIFIED);
   }
@@ -259,6 +262,7 @@
       if (maybe_settings->HasError()) {
         errors.push_back(syncer::SyncError(
             FROM_HERE,
+            syncer::SyncError::DATATYPE_ERROR,
             std::string("Error getting current sync state for ") +
                 extension_id_ + "/" + key + ": " + maybe_settings->error(),
             sync_processor_->type()));
@@ -338,6 +342,7 @@
   if (result->HasError()) {
     return syncer::SyncError(
         FROM_HERE,
+        syncer::SyncError::DATATYPE_ERROR,
         std::string("Error pushing sync add to local settings: ") +
             result->error(),
         sync_processor_->type());
@@ -357,6 +362,7 @@
   if (result->HasError()) {
     return syncer::SyncError(
         FROM_HERE,
+        syncer::SyncError::DATATYPE_ERROR,
         std::string("Error pushing sync update to local settings: ") +
             result->error(),
         sync_processor_->type());
@@ -374,6 +380,7 @@
   if (result->HasError()) {
     return syncer::SyncError(
         FROM_HERE,
+        syncer::SyncError::DATATYPE_ERROR,
         std::string("Error pushing sync remove to local settings: ") +
             result->error(),
         sync_processor_->type());
diff --git a/chrome/browser/extensions/api/storage/syncable_settings_storage.h b/chrome/browser/extensions/api/storage/syncable_settings_storage.h
index ec57f83..d971ef0 100644
--- a/chrome/browser/extensions/api/storage/syncable_settings_storage.h
+++ b/chrome/browser/extensions/api/storage/syncable_settings_storage.h
@@ -43,7 +43,7 @@
       const std::string& key,
       const Value& value) OVERRIDE;
   virtual WriteResult Set(
-      WriteOptions options, const DictionaryValue& values) OVERRIDE;
+      WriteOptions options, const base::DictionaryValue& values) OVERRIDE;
   virtual WriteResult Remove(const std::string& key) OVERRIDE;
   virtual WriteResult Remove(const std::vector<std::string>& keys) OVERRIDE;
   virtual WriteResult Clear() OVERRIDE;
@@ -54,7 +54,7 @@
 
   // Must only be called if sync isn't already active.
   syncer::SyncError StartSyncing(
-      const DictionaryValue& sync_state,
+      const base::DictionaryValue& sync_state,
       scoped_ptr<SettingsSyncProcessor> sync_processor);
 
   // May be called at any time (idempotent).
@@ -69,11 +69,12 @@
 
   // Sends all local settings to sync (synced settings assumed to be empty).
   syncer::SyncError SendLocalSettingsToSync(
-      const DictionaryValue& settings);
+      const base::DictionaryValue& settings);
 
   // Overwrites local state with sync state.
   syncer::SyncError OverwriteLocalSettingsWithSync(
-      const DictionaryValue& sync_state, const DictionaryValue& settings);
+      const base::DictionaryValue& sync_state,
+      const base::DictionaryValue& settings);
 
   // Called when an Add/Update/Remove comes from sync.  Ownership of Value*s
   // are taken.
diff --git a/chrome/browser/extensions/api/storage/weak_unlimited_settings_storage.cc b/chrome/browser/extensions/api/storage/weak_unlimited_settings_storage.cc
index 7adf5f4..241ae2f 100644
--- a/chrome/browser/extensions/api/storage/weak_unlimited_settings_storage.cc
+++ b/chrome/browser/extensions/api/storage/weak_unlimited_settings_storage.cc
@@ -41,12 +41,12 @@
 }
 
 ValueStore::WriteResult WeakUnlimitedSettingsStorage::Set(
-    WriteOptions options, const std::string& key, const Value& value) {
+    WriteOptions options, const std::string& key, const base::Value& value) {
   return delegate_->Set(IGNORE_QUOTA, key, value);
 }
 
 ValueStore::WriteResult WeakUnlimitedSettingsStorage::Set(
-    WriteOptions options, const DictionaryValue& values) {
+    WriteOptions options, const base::DictionaryValue& values) {
   return delegate_->Set(IGNORE_QUOTA, values);
 }
 
diff --git a/chrome/browser/extensions/api/storage/weak_unlimited_settings_storage.h b/chrome/browser/extensions/api/storage/weak_unlimited_settings_storage.h
index c74d57c..66a4002 100644
--- a/chrome/browser/extensions/api/storage/weak_unlimited_settings_storage.h
+++ b/chrome/browser/extensions/api/storage/weak_unlimited_settings_storage.h
@@ -32,7 +32,7 @@
       const std::string& key,
       const Value& value) OVERRIDE;
   virtual WriteResult Set(
-      WriteOptions options, const DictionaryValue& values) OVERRIDE;
+      WriteOptions options, const base::DictionaryValue& values) OVERRIDE;
   virtual WriteResult Remove(const std::string& key) OVERRIDE;
   virtual WriteResult Remove(const std::vector<std::string>& keys) OVERRIDE;
   virtual WriteResult Clear() OVERRIDE;
diff --git a/chrome/browser/extensions/api/streams_private/streams_private_api.cc b/chrome/browser/extensions/api/streams_private/streams_private_api.cc
index d87c9a0..dc1fb07 100644
--- a/chrome/browser/extensions/api/streams_private/streams_private_api.cc
+++ b/chrome/browser/extensions/api/streams_private/streams_private_api.cc
@@ -52,7 +52,7 @@
     scoped_ptr<content::StreamHandle> stream,
     int64 expected_content_size) {
   // Create the event's arguments value.
-  scoped_ptr<ListValue> event_args(new ListValue());
+  scoped_ptr<base::ListValue> event_args(new base::ListValue());
   event_args->Append(new base::StringValue(stream->GetMimeType()));
   event_args->Append(new base::StringValue(stream->GetOriginalURL().spec()));
   event_args->Append(new base::StringValue(stream->GetURL().spec()));
diff --git a/chrome/browser/extensions/api/streams_private/streams_private_apitest.cc b/chrome/browser/extensions/api/streams_private/streams_private_apitest.cc
index 7fd3672..3139336 100644
--- a/chrome/browser/extensions/api/streams_private/streams_private_apitest.cc
+++ b/chrome/browser/extensions/api/streams_private/streams_private_apitest.cc
@@ -51,7 +51,7 @@
   // For relative path "/doc_path.doc", return success response with MIME type
   // "application/msword".
   if (request.relative_url == "/doc_path.doc") {
-    response->set_code(net::test_server::SUCCESS);
+    response->set_code(net::HTTP_OK);
     response->set_content_type("application/msword");
     return response.PassAs<HttpResponse>();
   }
@@ -60,7 +60,7 @@
   // MIME type "plain/text" and content "txt content". Also, set content
   // disposition to be attachment.
   if (request.relative_url == "/text_path_attch.txt") {
-    response->set_code(net::test_server::SUCCESS);
+    response->set_code(net::HTTP_OK);
     response->set_content("txt content");
     response->set_content_type("plain/text");
     response->AddCustomHeader("Content-Disposition",
@@ -70,7 +70,7 @@
   // For relative path "/test_path_attch.txt", return success response with
   // MIME type "plain/text" and content "txt content".
   if (request.relative_url == "/text_path.txt") {
-    response->set_code(net::test_server::SUCCESS);
+    response->set_code(net::HTTP_OK);
     response->set_content("txt content");
     response->set_content_type("plain/text");
     return response.PassAs<HttpResponse>();
@@ -78,7 +78,7 @@
 
   // No other requests should be handled in the tests.
   EXPECT_TRUE(false) << "NOTREACHED!";
-  response->set_code(net::test_server::NOT_FOUND);
+  response->set_code(net::HTTP_NOT_FOUND);
   return response.PassAs<HttpResponse>();
 }
 
@@ -134,7 +134,7 @@
   // event with the "test/done" MIME type (unless the 'chrome.test.notifyFail'
   // has already been called).
   void SendDoneEvent() {
-    scoped_ptr<ListValue> event_args(new ListValue());
+    scoped_ptr<base::ListValue> event_args(new base::ListValue());
     event_args->Append(new base::StringValue("test/done"));
     event_args->Append(new base::StringValue("http://foo"));
     event_args->Append(new base::StringValue("blob://bar"));
diff --git a/chrome/browser/extensions/api/sync_file_system/extension_sync_event_observer.cc b/chrome/browser/extensions/api/sync_file_system/extension_sync_event_observer.cc
index e856033..3b76078 100644
--- a/chrome/browser/extensions/api/sync_file_system/extension_sync_event_observer.cc
+++ b/chrome/browser/extensions/api/sync_file_system/extension_sync_event_observer.cc
@@ -75,7 +75,7 @@
     sync_file_system::SyncFileStatus status,
     sync_file_system::SyncAction action,
     sync_file_system::SyncDirection direction) {
-  scoped_ptr<base::ListValue> params(new ListValue());
+  scoped_ptr<base::ListValue> params(new base::ListValue());
 
   // For now we always assume events come only for files (not directories).
   params->Append(CreateDictionaryValueForFileSystemEntry(
diff --git a/chrome/browser/extensions/api/sync_file_system/sync_file_system_api.cc b/chrome/browser/extensions/api/sync_file_system/sync_file_system_api.cc
index cb0c0fd..640ad9e 100644
--- a/chrome/browser/extensions/api/sync_file_system/sync_file_system_api.cc
+++ b/chrome/browser/extensions/api/sync_file_system/sync_file_system_api.cc
@@ -142,7 +142,7 @@
 
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      Bind(&fileapi::FileSystemContext::OpenSyncableFileSystem,
+      Bind(&fileapi::FileSystemContext::OpenFileSystem,
            GetFileSystemContext(),
            source_url().GetOrigin(),
            fileapi::kFileSystemTypeSyncable,
@@ -171,7 +171,7 @@
     return;
   }
 
-  DictionaryValue* dict = new DictionaryValue();
+  base::DictionaryValue* dict = new base::DictionaryValue();
   SetResult(dict);
   dict->SetString("name", file_system_name);
   dict->SetString("root", root_url.spec());
@@ -220,7 +220,7 @@
 
 bool SyncFileSystemGetFileStatusesFunction::RunImpl() {
   // All FileEntries converted into array of URL Strings in JS custom bindings.
-  ListValue* file_entry_urls = NULL;
+  base::ListValue* file_entry_urls = NULL;
   EXTENSION_FUNCTION_VALIDATE(args_->GetList(0, &file_entry_urls));
 
   scoped_refptr<fileapi::FileSystemContext> file_system_context =
@@ -274,7 +274,7 @@
   base::ListValue* status_array = new base::ListValue();
   for (URLToStatusMap::iterator it = file_sync_statuses_.begin();
        it != file_sync_statuses_.end(); ++it) {
-    DictionaryValue* dict = new DictionaryValue();
+    base::DictionaryValue* dict = new base::DictionaryValue();
     status_array->Append(dict);
 
     fileapi::FileSystemURL url = it->first;
@@ -357,7 +357,7 @@
   EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &policy_string));
   ConflictResolutionPolicy policy = ExtensionEnumToConflictResolutionPolicy(
       api::sync_file_system::ParseConflictResolutionPolicy(policy_string));
-  if (policy == sync_file_system::CONFLICT_RESOLUTION_UNKNOWN) {
+  if (policy == sync_file_system::CONFLICT_RESOLUTION_POLICY_UNKNOWN) {
     SetError(base::StringPrintf(kUnsupportedConflictResolutionPolicy,
                                 policy_string.c_str()));
     return false;
diff --git a/chrome/browser/extensions/api/sync_file_system/sync_file_system_api_helpers.cc b/chrome/browser/extensions/api/sync_file_system/sync_file_system_api_helpers.cc
index 0adc20b..7398440 100644
--- a/chrome/browser/extensions/api/sync_file_system/sync_file_system_api_helpers.cc
+++ b/chrome/browser/extensions/api/sync_file_system/sync_file_system_api_helpers.cc
@@ -77,25 +77,25 @@
     api::sync_file_system::ConflictResolutionPolicy policy) {
   switch (policy) {
     case api::sync_file_system::CONFLICT_RESOLUTION_POLICY_NONE:
-      return sync_file_system::CONFLICT_RESOLUTION_UNKNOWN;
+      return sync_file_system::CONFLICT_RESOLUTION_POLICY_UNKNOWN;
     case api::sync_file_system::CONFLICT_RESOLUTION_POLICY_LAST_WRITE_WIN:
-      return sync_file_system::CONFLICT_RESOLUTION_LAST_WRITE_WIN;
+      return sync_file_system::CONFLICT_RESOLUTION_POLICY_LAST_WRITE_WIN;
     case api::sync_file_system::CONFLICT_RESOLUTION_POLICY_MANUAL:
-      return sync_file_system::CONFLICT_RESOLUTION_MANUAL;
+      return sync_file_system::CONFLICT_RESOLUTION_POLICY_MANUAL;
   }
   NOTREACHED() << "Invalid conflict resolution policy: " << policy;
-  return sync_file_system::CONFLICT_RESOLUTION_UNKNOWN;
+  return sync_file_system::CONFLICT_RESOLUTION_POLICY_UNKNOWN;
 }
 
 api::sync_file_system::ConflictResolutionPolicy
 ConflictResolutionPolicyToExtensionEnum(
     sync_file_system::ConflictResolutionPolicy policy) {
   switch (policy) {
-    case sync_file_system::CONFLICT_RESOLUTION_UNKNOWN:
+    case sync_file_system::CONFLICT_RESOLUTION_POLICY_UNKNOWN:
       return api::sync_file_system::CONFLICT_RESOLUTION_POLICY_NONE;
-    case sync_file_system::CONFLICT_RESOLUTION_LAST_WRITE_WIN:
+    case sync_file_system::CONFLICT_RESOLUTION_POLICY_LAST_WRITE_WIN:
         return api::sync_file_system::CONFLICT_RESOLUTION_POLICY_LAST_WRITE_WIN;
-    case sync_file_system::CONFLICT_RESOLUTION_MANUAL:
+    case sync_file_system::CONFLICT_RESOLUTION_POLICY_MANUAL:
       return api::sync_file_system::CONFLICT_RESOLUTION_POLICY_MANUAL;
   }
   NOTREACHED() << "Invalid conflict resolution policy: " << policy;
diff --git a/chrome/browser/extensions/api/sync_file_system/sync_file_system_api_helpers.h b/chrome/browser/extensions/api/sync_file_system/sync_file_system_api_helpers.h
index 16bb547..a08b701 100644
--- a/chrome/browser/extensions/api/sync_file_system/sync_file_system_api_helpers.h
+++ b/chrome/browser/extensions/api/sync_file_system/sync_file_system_api_helpers.h
@@ -6,10 +6,10 @@
 #define CHROME_BROWSER_EXTENSIONS_API_SYNC_FILE_SYSTEM_SYNC_FILE_SYSTEM_API_HELPERS_H_
 
 #include "chrome/browser/sync_file_system/conflict_resolution_policy.h"
+#include "chrome/browser/sync_file_system/sync_action.h"
+#include "chrome/browser/sync_file_system/sync_direction.h"
 #include "chrome/browser/sync_file_system/sync_service_state.h"
 #include "chrome/common/extensions/api/sync_file_system.h"
-#include "webkit/browser/fileapi/syncable/sync_action.h"
-#include "webkit/browser/fileapi/syncable/sync_direction.h"
 #include "webkit/browser/fileapi/syncable/sync_file_status.h"
 #include "webkit/browser/fileapi/syncable/sync_file_type.h"
 
diff --git a/chrome/browser/extensions/api/system_info_cpu/cpu_info_provider.h b/chrome/browser/extensions/api/system_info_cpu/cpu_info_provider.h
index e84db05..df7d77c 100644
--- a/chrome/browser/extensions/api/system_info_cpu/cpu_info_provider.h
+++ b/chrome/browser/extensions/api/system_info_cpu/cpu_info_provider.h
@@ -6,7 +6,7 @@
 
 #include <vector>
 
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/extensions/api/system_info/system_info_provider.h"
 #include "chrome/common/extensions/api/system_info_cpu.h"
 
diff --git a/chrome/browser/extensions/api/system_info_display/display_info_provider_chromeos.cc b/chrome/browser/extensions/api/system_info_display/display_info_provider_chromeos.cc
index 5fb380b..7ce7621 100644
--- a/chrome/browser/extensions/api/system_info_display/display_info_provider_chromeos.cc
+++ b/chrome/browser/extensions/api/system_info_display/display_info_provider_chromeos.cc
@@ -7,7 +7,7 @@
 #include "ash/display/display_controller.h"
 #include "ash/display/display_manager.h"
 #include "ash/shell.h"
-#include "base/message_loop_proxy.h"
+#include "base/message_loop/message_loop_proxy.h"
 #include "base/strings/string_number_conversions.h"
 #include "content/public/browser/browser_thread.h"
 #include "ui/gfx/display.h"
diff --git a/chrome/browser/extensions/api/system_info_storage/storage_info_provider.h b/chrome/browser/extensions/api/system_info_storage/storage_info_provider.h
index 5ed7b5a..88c147b 100644
--- a/chrome/browser/extensions/api/system_info_storage/storage_info_provider.h
+++ b/chrome/browser/extensions/api/system_info_storage/storage_info_provider.h
@@ -8,7 +8,7 @@
 
 #include "base/memory/ref_counted.h"
 #include "base/observer_list_threadsafe.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/extensions/api/system_info/system_info_provider.h"
 #include "chrome/browser/extensions/api/system_info_storage/storage_info_observer.h"
 #include "chrome/browser/storage_monitor/removable_storage_observer.h"
diff --git a/chrome/browser/extensions/api/system_info_storage/storage_info_provider_linux_unittest.cc b/chrome/browser/extensions/api/system_info_storage/storage_info_provider_linux_unittest.cc
index 24bd8d8..46a013d 100644
--- a/chrome/browser/extensions/api/system_info_storage/storage_info_provider_linux_unittest.cc
+++ b/chrome/browser/extensions/api/system_info_storage/storage_info_provider_linux_unittest.cc
@@ -109,7 +109,7 @@
   }
 
   virtual void TearDown() OVERRIDE {
-    file_util::Delete(mtab_file_, false);
+    base::Delete(mtab_file_, false);
   }
 
   scoped_refptr<StorageInfoProviderLinuxWrapper> storage_info_provider_;
diff --git a/chrome/browser/extensions/api/system_info_storage/storage_info_provider_mac.cc b/chrome/browser/extensions/api/system_info_storage/storage_info_provider_mac.cc
index 125152b..0041224 100644
--- a/chrome/browser/extensions/api/system_info_storage/storage_info_provider_mac.cc
+++ b/chrome/browser/extensions/api/system_info_storage/storage_info_provider_mac.cc
@@ -105,11 +105,9 @@
   for (base::mac::ScopedIOObject<io_service_t> media(IOIteratorNext(iterator));
        media;
        media.reset(IOIteratorNext(iterator))) {
-    base::mac::ScopedCFTypeRef<CFTypeRef> dev_path_cf(
-        IORegistryEntryCreateCFProperty(media,
-                                        CFSTR(kIOBSDNameKey),
-                                        kCFAllocatorDefault,
-                                        0));
+    base::ScopedCFTypeRef<CFTypeRef> dev_path_cf(
+        IORegistryEntryCreateCFProperty(
+            media, CFSTR(kIOBSDNameKey), kCFAllocatorDefault, 0));
 
     if (!dev_path_cf)
       continue;
@@ -119,11 +117,9 @@
         base::SysCFStringRefToUTF8(
             base::mac::CFCast<CFStringRef>(dev_path_cf)));
 
-    base::mac::ScopedCFTypeRef<CFTypeRef> removable_cf(
-        IORegistryEntryCreateCFProperty(media,
-                                        CFSTR(kIOMediaEjectableKey),
-                                        kCFAllocatorDefault,
-                                        0));
+    base::ScopedCFTypeRef<CFTypeRef> removable_cf(
+        IORegistryEntryCreateCFProperty(
+            media, CFSTR(kIOMediaEjectableKey), kCFAllocatorDefault, 0));
     if (!removable_cf)
       dev_path_to_type_map_[dev_path] = systeminfo::kStorageTypeUnknown;
     else if (CFBooleanGetValue(base::mac::CFCast<CFBooleanRef>(removable_cf)))
diff --git a/chrome/browser/extensions/api/system_info_storage/system_info_storage_apitest.cc b/chrome/browser/extensions/api/system_info_storage/system_info_storage_apitest.cc
index 7374342..b4ca0fe 100644
--- a/chrome/browser/extensions/api/system_info_storage/system_info_storage_apitest.cc
+++ b/chrome/browser/extensions/api/system_info_storage/system_info_storage_apitest.cc
@@ -4,7 +4,7 @@
 #include "base/command_line.h"
 #include "base/message_loop.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/extensions/api/system_info_storage/storage_info_provider.h"
 #include "chrome/browser/extensions/extension_apitest.h"
 #include "chrome/browser/extensions/extension_test_message_listener.h"
diff --git a/chrome/browser/extensions/api/system_private/system_private_api.cc b/chrome/browser/extensions/api/system_private/system_private_api.cc
index bab2503..55296e3 100644
--- a/chrome/browser/extensions/api/system_private/system_private_api.cc
+++ b/chrome/browser/extensions/api/system_private/system_private_api.cc
@@ -124,7 +124,7 @@
     state = kNotAvailableState;
   }
 #endif
-  DictionaryValue* dict = new DictionaryValue();
+  base::DictionaryValue* dict = new base::DictionaryValue();
   dict->SetString(kStateKey, state);
   dict->SetDouble(kDownloadProgressKey, download_progress);
   SetResult(dict);
@@ -133,14 +133,14 @@
 }
 
 void DispatchVolumeChangedEvent(double volume, bool is_volume_muted) {
-  DictionaryValue* dict = new DictionaryValue();
+  base::DictionaryValue* dict = new base::DictionaryValue();
   dict->SetDouble(kVolumeKey, volume);
   dict->SetBoolean(kIsVolumeMutedKey, is_volume_muted);
   DispatchEvent(kOnVolumeChanged, dict);
 }
 
 void DispatchBrightnessChangedEvent(int brightness, bool user_initiated) {
-  DictionaryValue* dict = new DictionaryValue();
+  base::DictionaryValue* dict = new base::DictionaryValue();
   dict->SetInteger(kBrightnessKey, brightness);
   dict->SetBoolean(kUserInitiatedKey, user_initiated);
   DispatchEvent(kOnBrightnessChanged, dict);
diff --git a/chrome/browser/extensions/api/tab_capture/tab_capture_apitest.cc b/chrome/browser/extensions/api/tab_capture/tab_capture_apitest.cc
index ebb9bfc..cfef6e3 100644
--- a/chrome/browser/extensions/api/tab_capture/tab_capture_apitest.cc
+++ b/chrome/browser/extensions/api/tab_capture/tab_capture_apitest.cc
@@ -13,6 +13,7 @@
 #include "chrome/browser/extensions/extension_test_message_listener.h"
 #include "chrome/browser/extensions/tab_helper.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/fullscreen/fullscreen_controller.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/chrome_version_info.h"
 #include "chrome/common/extensions/feature_switch.h"
@@ -185,4 +186,55 @@
   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
 }
 
+// http://crbug.com/177163
+#if defined(OS_WIN) && !defined(NDEBUG)
+#define MAYBE_FullscreenEvents DISABLED_FullscreenEvents
+#elif defined(USE_AURA) || defined(OS_MACOSX)
+// These don't always fire fullscreen events when run in tests. Tested manually.
+#define MAYBE_FullscreenEvents DISABLED_FullscreenEvents
+#elif defined(OS_LINUX)
+// Flaky to get out of fullscreen in tests. Tested manually.
+#define MAYBE_FullscreenEvents DISABLED_FullscreenEvents
+#else
+#define MAYBE_FullscreenEvents FullscreenEvents
+#endif
+IN_PROC_BROWSER_TEST_F(TabCaptureApiTest, MAYBE_FullscreenEvents) {
+#if defined(OS_WIN)
+  // TODO(justinlin): Disabled for WinXP due to timeout issues.
+  if (base::win::GetVersion() < base::win::VERSION_VISTA) {
+    return;
+  }
+#endif
+
+  AddExtensionToCommandLineWhitelist();
+
+  content::OpenURLParams params(GURL("chrome://version"),
+                                content::Referrer(),
+                                CURRENT_TAB,
+                                content::PAGE_TRANSITION_LINK, false);
+  content::WebContents* web_contents = browser()->OpenURL(params);
+
+  ExtensionTestMessageListener listeners_setup("ready1", true);
+  ExtensionTestMessageListener fullscreen_entered("ready2", true);
+
+  ASSERT_TRUE(RunExtensionSubtest("tab_capture/experimental",
+                                  "fullscreen_test.html")) << message_;
+  EXPECT_TRUE(listeners_setup.WaitUntilSatisfied());
+
+  // Toggle fullscreen after setting up listeners.
+  browser()->fullscreen_controller()->ToggleFullscreenModeForTab(web_contents,
+                                                                 true);
+  listeners_setup.Reply("");
+
+  // Toggle again after JS should have the event.
+  EXPECT_TRUE(fullscreen_entered.WaitUntilSatisfied());
+  browser()->fullscreen_controller()->ToggleFullscreenModeForTab(web_contents,
+                                                                 false);
+  fullscreen_entered.Reply("");
+
+  ResultCatcher catcher;
+  catcher.RestrictToProfile(browser()->profile());
+  EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
+}
+
 }  // namespace chrome
diff --git a/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc b/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc
index 406d9de..88d37be 100644
--- a/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc
+++ b/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc
@@ -10,11 +10,13 @@
 #include "chrome/browser/extensions/event_router.h"
 #include "chrome/browser/extensions/extension_system.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/fullscreen/fullscreen_controller.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "chrome/common/extensions/extension.h"
 #include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_details.h"
+#include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_source.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
@@ -109,7 +111,9 @@
   registrar_.Add(this,
                  chrome::NOTIFICATION_EXTENSION_UNLOADED,
                  content::Source<Profile>(profile_));
-  // TODO(justinlin): Hook up HTML5 fullscreen.
+  registrar_.Add(this,
+                 chrome::NOTIFICATION_FULLSCREEN_CHANGED,
+                 content::NotificationService::AllSources());
 }
 
 TabCaptureRegistry::~TabCaptureRegistry() {
@@ -132,6 +136,7 @@
 void TabCaptureRegistry::Observe(int type,
                                  const content::NotificationSource& source,
                                  const content::NotificationDetails& details) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   switch (type) {
     case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
       // Cleanup all the requested media streams for this extension.
@@ -149,7 +154,36 @@
       break;
     }
     case chrome::NOTIFICATION_FULLSCREEN_CHANGED: {
-      // TODO(justinlin): Hook up HTML5 fullscreen.
+      FullscreenController* fullscreen_controller =
+          content::Source<FullscreenController>(source).ptr();
+      const bool is_fullscreen = *content::Details<bool>(details).ptr();
+      for (ScopedVector<TabCaptureRequest>::iterator it = requests_.begin();
+           it != requests_.end(); ++it) {
+        // If we are exiting fullscreen mode, we only need to check if any of
+        // the requests had the fullscreen flag toggled previously. The
+        // fullscreen controller no longer has the reference to the fullscreen
+        // web_contents here.
+        if (!is_fullscreen) {
+          if ((*it)->fullscreen) {
+            (*it)->fullscreen = false;
+            DispatchStatusChangeEvent(*it);
+            break;
+          }
+          continue;
+        }
+
+        // If we are entering fullscreen mode, find whether the web_contents we
+        // are capturing entered fullscreen mode.
+        content::RenderViewHost* const rvh =
+            content::RenderViewHost::FromID((*it)->render_process_id,
+                                            (*it)->render_view_id);
+        if (rvh && fullscreen_controller->IsFullscreenForTabOrPending(
+                content::WebContents::FromRenderViewHost(rvh))) {
+          (*it)->fullscreen = true;
+          DispatchStatusChangeEvent(*it);
+          break;
+        }
+      }
       break;
     }
   }
@@ -278,7 +312,7 @@
   info->status = request->status;
   info->fullscreen = request->fullscreen;
 
-  scoped_ptr<base::ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   args->Append(info->ToValue().release());
   scoped_ptr<Event> event(new Event(
       extensions::event_names::kOnTabCaptureStatusChanged, args.Pass()));
diff --git a/chrome/browser/extensions/api/tabs/ash_panel_contents.cc b/chrome/browser/extensions/api/tabs/ash_panel_contents.cc
index 059847b..27b7d5e 100644
--- a/chrome/browser/extensions/api/tabs/ash_panel_contents.cc
+++ b/chrome/browser/extensions/api/tabs/ash_panel_contents.cc
@@ -13,7 +13,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sessions/session_tab_helper.h"
 #include "chrome/browser/ui/extensions/native_app_window.h"
-#include "chrome/browser/ui/extensions/shell_window.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_messages.h"
@@ -21,6 +20,8 @@
 #include "content/public/browser/web_contents.h"
 #include "ui/gfx/image/image.h"
 
+using apps::ShellWindow;
+
 // AshPanelWindowController ----------------------------------------------------
 
 // This class enables a ShellWindow instance to be accessed (to a limited
@@ -78,9 +79,9 @@
     const extensions::Extension* extension) const {
   DCHECK(IsVisibleToExtension(extension));
   base::DictionaryValue* result = CreateWindowValue();
-  DictionaryValue* tab_value = CreateTabValue(extension, 0);
+  base::DictionaryValue* tab_value = CreateTabValue(extension, 0);
   if (tab_value) {
-    base::ListValue* tab_list = new ListValue();
+    base::ListValue* tab_list = new base::ListValue();
     tab_list->Append(tab_value);
     result->Set(extensions::tabs_constants::kTabsKey, tab_list);
   }
@@ -97,7 +98,7 @@
   if (!web_contents)
     return NULL;
 
-  DictionaryValue* tab_value = new DictionaryValue();
+  base::DictionaryValue* tab_value = new base::DictionaryValue();
   tab_value->SetInteger(extensions::tabs_constants::kIdKey,
                         SessionID::IdForTab(web_contents));
   tab_value->SetInteger(extensions::tabs_constants::kIndexKey, 0);
diff --git a/chrome/browser/extensions/api/tabs/ash_panel_contents.h b/chrome/browser/extensions/api/tabs/ash_panel_contents.h
index 5aa0c46..4f79971 100644
--- a/chrome/browser/extensions/api/tabs/ash_panel_contents.h
+++ b/chrome/browser/extensions/api/tabs/ash_panel_contents.h
@@ -7,11 +7,11 @@
 
 #include <vector>
 
+#include "apps/shell_window.h"
 #include "base/basictypes.h"
 #include "base/memory/scoped_ptr.h"
 #include "chrome/browser/extensions/extension_function_dispatcher.h"
 #include "chrome/browser/ui/ash/launcher/launcher_favicon_loader.h"
-#include "chrome/browser/ui/extensions/shell_window.h"
 #include "content/public/browser/web_contents_observer.h"
 
 class AshPanelWindowController;
@@ -25,20 +25,20 @@
 struct DraggableRegion;
 }
 
-// ShellWindowContents class specific to panel windows created by v1
+// apps::ShellWindowContents class specific to panel windows created by v1
 // extenstions. This class maintains a WebContents instance and observes it for
 // the purpose of passing messages to the extensions system. It also creates
 // an extensions::WindowController instance for interfacing with the v1
 // extensions API.
-class AshPanelContents : public ShellWindowContents,
+class AshPanelContents : public apps::ShellWindowContents,
                          public content::WebContentsObserver,
                          public LauncherFaviconLoader::Delegate,
                          public ExtensionFunctionDispatcher::Delegate {
  public:
-  explicit AshPanelContents(ShellWindow* host);
+  explicit AshPanelContents(apps::ShellWindow* host);
   virtual ~AshPanelContents();
 
-  // ShellWindowContents
+  // apps::ShellWindowContents
   virtual void Initialize(Profile* profile, const GURL& url) OVERRIDE;
   virtual void LoadContents(int32 creator_process_id) OVERRIDE;
   virtual void NativeWindowChanged(NativeAppWindow* native_app_window) OVERRIDE;
@@ -63,7 +63,7 @@
 
   void OnRequest(const ExtensionHostMsg_Request_Params& params);
 
-  ShellWindow* host_;
+  apps::ShellWindow* host_;
   GURL url_;
   scoped_ptr<content::WebContents> web_contents_;
   scoped_ptr<ExtensionFunctionDispatcher> extension_function_dispatcher_;
diff --git a/chrome/browser/extensions/api/tabs/tabs_api.cc b/chrome/browser/extensions/api/tabs/tabs_api.cc
index 81d938e..1a7027e 100644
--- a/chrome/browser/extensions/api/tabs/tabs_api.cc
+++ b/chrome/browser/extensions/api/tabs/tabs_api.cc
@@ -8,6 +8,7 @@
 #include <limits>
 #include <vector>
 
+#include "apps/shell_window.h"
 #include "base/base64.h"
 #include "base/bind.h"
 #include "base/command_line.h"
@@ -34,6 +35,7 @@
 #include "chrome/browser/prefs/incognito_mode_prefs.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/translate/translate_tab_helper.h"
+#include "chrome/browser/ui/apps/chrome_shell_window_delegate.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_finder.h"
@@ -41,7 +43,6 @@
 #include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/extensions/shell_window.h"
 #include "chrome/browser/ui/host_desktop.h"
 #include "chrome/browser/ui/panels/panel_manager.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
@@ -97,6 +98,7 @@
 #include "chrome/browser/extensions/shell_window_registry.h"
 #endif
 
+using apps::ShellWindow;
 using content::BrowserThread;
 using content::NavigationController;
 using content::NavigationEntry;
@@ -328,7 +330,7 @@
   if (params->get_info.get() && params->get_info->populate.get())
     populate_tabs = *params->get_info->populate;
 
-  ListValue* window_list = new ListValue();
+  base::ListValue* window_list = new base::ListValue();
   const WindowControllerList::ControllerList& windows =
       WindowControllerList::GetInstance()->windows();
   for (WindowControllerList::ControllerList::const_iterator iter =
@@ -396,7 +398,7 @@
 }
 
 bool WindowsCreateFunction::RunImpl() {
-  DictionaryValue* args = NULL;
+  base::DictionaryValue* args = NULL;
   std::vector<GURL> urls;
   TabStripModel* source_tab_strip = NULL;
   int tab_index = -1;
@@ -417,7 +419,8 @@
         url_value->GetAsString(&url_string);
         url_strings.push_back(url_string);
       } else if (url_value->IsType(Value::TYPE_LIST)) {
-        const ListValue* url_list = static_cast<const ListValue*>(url_value);
+        const base::ListValue* url_list =
+            static_cast<const base::ListValue*>(url_value);
         for (size_t i = 0; i < url_list->GetSize(); ++i) {
           std::string url_string;
           EXTENSION_FUNCTION_VALIDATE(url_list->GetString(i, &url_string));
@@ -584,8 +587,9 @@
       create_params.window_type = ShellWindow::WINDOW_TYPE_V1_PANEL;
       create_params.bounds = window_bounds;
       create_params.focused = saw_focus_key && focused;
-      ShellWindow* shell_window =
-          new ShellWindow(window_profile, GetExtension());
+      ShellWindow* shell_window = new ShellWindow(
+          window_profile, new chrome::ChromeShellWindowDelegate(),
+          GetExtension());
       AshPanelContents* ash_panel_contents = new AshPanelContents(shell_window);
       shell_window->Init(urls[0], ash_panel_contents, create_params);
       SetResult(ash_panel_contents->GetExtensionWindowController()->
@@ -689,7 +693,7 @@
 bool WindowsUpdateFunction::RunImpl() {
   int window_id = extension_misc::kUnknownWindowId;
   EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &window_id));
-  DictionaryValue* update_props;
+  base::DictionaryValue* update_props;
   EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &update_props));
 
   WindowController* controller;
@@ -795,6 +799,8 @@
       error_ = keys::kInvalidWindowStateError;
       return false;
     }
+    // TODO(varkha): Updating bounds during a drag can cause problems and a more
+    // general solution is needed. See http://crbug.com/251813 .
     controller->window()->SetBounds(bounds);
   }
 
@@ -937,7 +943,7 @@
         params->query_info.window_type);
   }
 
-  ListValue* result = new ListValue();
+  base::ListValue* result = new base::ListValue();
   for (chrome::BrowserIterator it; !it.done(); it.Next()) {
     Browser* browser = *it;
     if (!profile()->IsSameProfile(browser->profile()))
@@ -1114,7 +1120,8 @@
 
   index = std::min(std::max(index, -1), tab_strip->count());
 
-  int add_types = active ? TabStripModel::ADD_ACTIVE : TabStripModel::ADD_NONE;
+  int add_types = active ? TabStripModel::ADD_ACTIVE :
+                             TabStripModel::ADD_NONE;
   add_types |= TabStripModel::ADD_FORCE_INDEX;
   if (pinned)
     add_types |= TabStripModel::ADD_PINNED;
@@ -1134,10 +1141,8 @@
   if (opener)
     tab_strip->SetOpenerOfWebContentsAt(new_index, opener);
 
-  if (active) {
-    navigate_params.target_contents->GetDelegate()->ActivateContents(
-        navigate_params.target_contents);
-  }
+  if (active)
+    navigate_params.target_contents->GetView()->SetInitialFocus();
 
   // Return data about the newly created tab.
   if (has_callback()) {
@@ -1345,7 +1350,6 @@
       tab_strip->ActivateTabAt(tab_index, false);
       DCHECK_EQ(contents, tab_strip->GetActiveWebContents());
     }
-    web_contents_->GetDelegate()->ActivateContents(web_contents_);
   }
 
   if (params->update_properties.highlighted.get()) {
@@ -1447,10 +1451,11 @@
   SetResult(ExtensionTabUtil::CreateTabValue(web_contents_, GetExtension()));
 }
 
-void TabsUpdateFunction::OnExecuteCodeFinished(const std::string& error,
-                                              int32 on_page_id,
-                                              const GURL& url,
-                                              const ListValue& script_result) {
+void TabsUpdateFunction::OnExecuteCodeFinished(
+    const std::string& error,
+    int32 on_page_id,
+    const GURL& url,
+    const base::ListValue& script_result) {
   if (error.empty())
     PopulateResult();
   else
@@ -1464,7 +1469,7 @@
 
   int new_index = params->move_properties.index;
   int* window_id = params->move_properties.window_id.get();
-  ListValue tab_values;
+  base::ListValue tab_values;
 
   std::vector<int> tab_ids;
   if (params->tab_ids.as_array.get()) {
@@ -1503,7 +1508,7 @@
 bool TabsMoveFunction::MoveTab(int tab_id,
                                int *new_index,
                                int iteration,
-                               ListValue* tab_values,
+                               base::ListValue* tab_values,
                                int* window_id) {
   Browser* source_browser = NULL;
   TabStripModel* source_tab_strip = NULL;
@@ -1730,8 +1735,8 @@
   image_quality_ = kDefaultQuality;  // Default quality setting.
 
   if (params->options.get()) {
-    image_format_ = params->options->format;
-    EXTENSION_FUNCTION_VALIDATE(image_format_ != FormatEnum::FORMAT_NONE);
+    if (params->options->format != FormatEnum::FORMAT_NONE)
+      image_format_ = params->options->format;
 
     if (params->options->quality.get())
       image_quality_ = *params->options->quality;
@@ -2026,10 +2031,11 @@
   return false;
 }
 
-void TabsExecuteScriptFunction::OnExecuteCodeFinished(const std::string& error,
-                                                      int32 on_page_id,
-                                                      const GURL& on_url,
-                                                      const ListValue& result) {
+void TabsExecuteScriptFunction::OnExecuteCodeFinished(
+    const std::string& error,
+    int32 on_page_id,
+    const GURL& on_url,
+    const base::ListValue& result) {
   if (error.empty())
     SetResult(result.DeepCopy());
   ExecuteCodeInTabFunction::OnExecuteCodeFinished(error, on_page_id, on_url,
@@ -2046,7 +2052,7 @@
     EXTENSION_FUNCTION_VALIDATE(tab_id >= 0);
 
   // |details| are not optional.
-  DictionaryValue* details_value = NULL;
+  base::DictionaryValue* details_value = NULL;
   if (!args_->GetDictionary(1, &details_value))
     return false;
   scoped_ptr<InjectDetails> details(new InjectDetails());
diff --git a/chrome/browser/extensions/api/tabs/tabs_api.h b/chrome/browser/extensions/api/tabs/tabs_api.h
index 3b61e62..80e47a6 100644
--- a/chrome/browser/extensions/api/tabs/tabs_api.h
+++ b/chrome/browser/extensions/api/tabs/tabs_api.h
@@ -150,7 +150,7 @@
   void OnExecuteCodeFinished(const std::string& error,
                              int32 on_page_id,
                              const GURL& on_url,
-                             const ListValue& script_result);
+                             const base::ListValue& script_result);
 
   DECLARE_EXTENSION_FUNCTION("tabs.update", TABS_UPDATE)
 };
@@ -160,7 +160,7 @@
   bool MoveTab(int tab_id,
                int* new_index,
                int iteration,
-               ListValue* tab_values,
+               base::ListValue* tab_values,
                int* window_id);
   DECLARE_EXTENSION_FUNCTION("tabs.move", TABS_MOVE)
 };
@@ -253,10 +253,11 @@
  private:
   virtual ~TabsExecuteScriptFunction() {}
 
-  virtual void OnExecuteCodeFinished(const std::string& error,
-                                     int32 on_page_id,
-                                     const GURL& on_url,
-                                     const ListValue& script_result) OVERRIDE;
+  virtual void OnExecuteCodeFinished(
+      const std::string& error,
+      int32 on_page_id,
+      const GURL& on_url,
+      const base::ListValue& script_result) OVERRIDE;
 
   DECLARE_EXTENSION_FUNCTION("tabs.executeScript", TABS_EXECUTESCRIPT)
 };
diff --git a/chrome/browser/extensions/api/tabs/tabs_interactive_test.cc b/chrome/browser/extensions/api/tabs/tabs_interactive_test.cc
index 7af0c97..293f076 100644
--- a/chrome/browser/extensions/api/tabs/tabs_interactive_test.cc
+++ b/chrome/browser/extensions/api/tabs/tabs_interactive_test.cc
@@ -45,7 +45,7 @@
   // The id should always match the last focused window and does not depend
   // on what was passed to RunFunctionAndReturnSingleResult.
   EXPECT_EQ(focused_window_id, utils::GetInteger(result.get(), "id"));
-  ListValue* tabs = NULL;
+  base::ListValue* tabs = NULL;
   EXPECT_FALSE(result.get()->GetList(keys::kTabsKey, &tabs));
 
   function = new extensions::WindowsGetLastFocusedFunction();
@@ -91,11 +91,11 @@
                                               "[{\"lastFocusedWindow\":true}]",
                                               browser())));
 
-  ListValue* result_tabs = result.get();
+  base::ListValue* result_tabs = result.get();
   // We should have one initial tab and one added tab.
   EXPECT_EQ(2u, result_tabs->GetSize());
   for (size_t i = 0; i < result_tabs->GetSize(); ++i) {
-    DictionaryValue* result_tab = NULL;
+    base::DictionaryValue* result_tab = NULL;
     EXPECT_TRUE(result_tabs->GetDictionary(i, &result_tab));
     EXPECT_EQ(focused_window_id, utils::GetInteger(result_tab,
                                                    keys::kWindowIdKey));
@@ -112,7 +112,7 @@
   // We should get one tab for each extra window and one for the initial window.
   EXPECT_EQ(kExtraWindows + 1, result_tabs->GetSize());
   for (size_t i = 0; i < result_tabs->GetSize(); ++i) {
-    DictionaryValue* result_tab = NULL;
+    base::DictionaryValue* result_tab = NULL;
     EXPECT_TRUE(result_tabs->GetDictionary(i, &result_tab));
     EXPECT_NE(focused_window_id, utils::GetInteger(result_tab,
                                                    keys::kWindowIdKey));
diff --git a/chrome/browser/extensions/api/tabs/tabs_test.cc b/chrome/browser/extensions/api/tabs/tabs_test.cc
index 821d254..0ce9e1f 100644
--- a/chrome/browser/extensions/api/tabs/tabs_test.cc
+++ b/chrome/browser/extensions/api/tabs/tabs_test.cc
@@ -83,7 +83,7 @@
 
   EXPECT_EQ(window_id, utils::GetInteger(result.get(), "id"));
   // "populate" was enabled so tabs should be populated.
-  ListValue* tabs = NULL;
+  base::ListValue* tabs = NULL;
   EXPECT_TRUE(result.get()->GetList(keys::kTabsKey, &tabs));
 
   // TODO(aa): Can't assume window is focused. On mac, calling Activate() from a
@@ -153,7 +153,7 @@
   // The id should match the window id of the browser instance that was passed
   // to RunFunctionAndReturnSingleResult.
   EXPECT_EQ(new_id, utils::GetInteger(result.get(), "id"));
-  ListValue* tabs = NULL;
+  base::ListValue* tabs = NULL;
   EXPECT_FALSE(result.get()->GetList(keys::kTabsKey, &tabs));
 
   // Get the current window using the old window and make the tabs populated.
@@ -190,15 +190,15 @@
                                               "[]",
                                               browser())));
 
-  ListValue* windows = result.get();
+  base::ListValue* windows = result.get();
   EXPECT_EQ(NUM_WINDOWS, windows->GetSize());
   for (size_t i = 0; i < NUM_WINDOWS; ++i) {
-    DictionaryValue* result_window = NULL;
+    base::DictionaryValue* result_window = NULL;
     EXPECT_TRUE(windows->GetDictionary(i, &result_window));
     result_ids.insert(utils::GetInteger(result_window, "id"));
 
     // "populate" was not passed in so tabs are not populated.
-    ListValue* tabs = NULL;
+    base::ListValue* tabs = NULL;
     EXPECT_FALSE(result_window->GetList(keys::kTabsKey, &tabs));
   }
   // The returned ids should contain all the current browser instance ids.
@@ -215,12 +215,12 @@
   windows = result.get();
   EXPECT_EQ(NUM_WINDOWS, windows->GetSize());
   for (size_t i = 0; i < windows->GetSize(); ++i) {
-    DictionaryValue* result_window = NULL;
+    base::DictionaryValue* result_window = NULL;
     EXPECT_TRUE(windows->GetDictionary(i, &result_window));
     result_ids.insert(utils::GetInteger(result_window, "id"));
 
     // "populate" was enabled so tabs should be populated.
-    ListValue* tabs = NULL;
+    base::ListValue* tabs = NULL;
     EXPECT_TRUE(result_window->GetList(keys::kTabsKey, &tabs));
   }
   // The returned ids should contain all the current browser instance ids.
@@ -404,11 +404,11 @@
                                               "[{\"currentWindow\":true}]",
                                               browser())));
 
-  ListValue* result_tabs = result.get();
+  base::ListValue* result_tabs = result.get();
   // We should have one initial tab and one added tab.
   EXPECT_EQ(2u, result_tabs->GetSize());
   for (size_t i = 0; i < result_tabs->GetSize(); ++i) {
-    DictionaryValue* result_tab = NULL;
+    base::DictionaryValue* result_tab = NULL;
     EXPECT_TRUE(result_tabs->GetDictionary(i, &result_tab));
     EXPECT_EQ(window_id, utils::GetInteger(result_tab, keys::kWindowIdKey));
   }
@@ -425,7 +425,7 @@
   // We should have one tab for each extra window.
   EXPECT_EQ(kExtraWindows, result_tabs->GetSize());
   for (size_t i = 0; i < kExtraWindows; ++i) {
-    DictionaryValue* result_tab = NULL;
+    base::DictionaryValue* result_tab = NULL;
     EXPECT_TRUE(result_tabs->GetDictionary(i, &result_tab));
     EXPECT_NE(window_id, utils::GetInteger(result_tab, keys::kWindowIdKey));
   }
diff --git a/chrome/browser/extensions/api/tabs/windows_event_router.cc b/chrome/browser/extensions/api/tabs/windows_event_router.cc
index 2880c3a..54d9b2d 100644
--- a/chrome/browser/extensions/api/tabs/windows_event_router.cc
+++ b/chrome/browser/extensions/api/tabs/windows_event_router.cc
@@ -57,8 +57,9 @@
   if (!profile_->IsSameProfile(window_controller->profile()))
     return;
 
-  scoped_ptr<base::ListValue> args(new ListValue());
-  DictionaryValue* window_dictionary = window_controller->CreateWindowValue();
+  scoped_ptr<base::ListValue> args(new base::ListValue());
+  base::DictionaryValue* window_dictionary =
+      window_controller->CreateWindowValue();
   args->Append(window_dictionary);
   DispatchEvent(event_names::kOnWindowCreated, window_controller->profile(),
                 args.Pass());
@@ -70,7 +71,7 @@
     return;
 
   int window_id = window_controller->GetWindowId();
-  scoped_ptr<base::ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   args->Append(Value::CreateIntegerValue(window_id));
   DispatchEvent(event_names::kOnWindowRemoved, window_controller->profile(),
                 args.Pass());
@@ -107,7 +108,7 @@
                                            int window_id,
                                            Profile* profile,
                                            const Extension* extension,
-                                           ListValue* event_args) {
+                                           base::ListValue* event_args) {
   // When switching between windows in the default and incognito profiles,
   // dispatch WINDOW_ID_NONE to extensions whose profile lost focus that
   // can't see the new focused window across the incognito boundary.
@@ -143,7 +144,7 @@
   focused_window_id_ = window_id;
 
   scoped_ptr<Event> event(new Event(event_names::kOnWindowFocusedChanged,
-                                    make_scoped_ptr(new ListValue())));
+                                    make_scoped_ptr(new base::ListValue())));
   event->will_dispatch_callback =
       base::Bind(&WillDispatchWindowFocusedEvent, window_profile, window_id);
   ExtensionSystem::Get(profile_)->event_router()->BroadcastEvent(event.Pass());
diff --git a/chrome/browser/extensions/api/test/test_api.cc b/chrome/browser/extensions/api/test/test_api.cc
index 207cc91..c6efce0 100644
--- a/chrome/browser/extensions/api/test/test_api.cc
+++ b/chrome/browser/extensions/api/test/test_api.cc
@@ -98,7 +98,7 @@
       CreateIncognitoTab::Params::Create(*args_));
   EXTENSION_FUNCTION_VALIDATE(params.get());
   chrome::OpenURLOffTheRecord(profile(), GURL(params->url),
-                              chrome::HOST_DESKTOP_TYPE_NATIVE);
+                              chrome::GetActiveDesktop());
   return true;
 }
 
@@ -124,7 +124,7 @@
 
 // static
 void TestGetConfigFunction::set_test_config_state(
-    DictionaryValue* value) {
+    base::DictionaryValue* value) {
   TestConfigState* test_config_state = TestConfigState::GetInstance();
   test_config_state->set_config_state(value);
 }
diff --git a/chrome/browser/extensions/api/test/test_api.h b/chrome/browser/extensions/api/test/test_api.h
index 5c0df7d..fa0c2ab 100644
--- a/chrome/browser/extensions/api/test/test_api.h
+++ b/chrome/browser/extensions/api/test/test_api.h
@@ -98,7 +98,7 @@
 
   // Set the dictionary returned by chrome.test.getConfig().
   // Does not take ownership of |value|.
-  static void set_test_config_state(DictionaryValue* value);
+  static void set_test_config_state(base::DictionaryValue* value);
 
  protected:
   // Tests that set configuration state do so by calling
@@ -109,11 +109,11 @@
    public:
     static TestConfigState* GetInstance();
 
-    void set_config_state(DictionaryValue* config_state) {
+    void set_config_state(base::DictionaryValue* config_state) {
       config_state_ = config_state;
     }
 
-    const DictionaryValue* config_state() {
+    const base::DictionaryValue* config_state() {
       return config_state_;
     }
 
@@ -121,7 +121,7 @@
     friend struct DefaultSingletonTraits<TestConfigState>;
     TestConfigState();
 
-    DictionaryValue* config_state_;
+    base::DictionaryValue* config_state_;
 
     DISALLOW_COPY_AND_ASSIGN(TestConfigState);
   };
diff --git a/chrome/browser/extensions/api/top_sites/top_sites_api.cc b/chrome/browser/extensions/api/top_sites/top_sites_api.cc
index 84d31a3..77d5a93 100644
--- a/chrome/browser/extensions/api/top_sites/top_sites_api.cc
+++ b/chrome/browser/extensions/api/top_sites/top_sites_api.cc
@@ -30,11 +30,11 @@
 
 void TopSitesGetFunction::OnMostVisitedURLsAvailable(
     const history::MostVisitedURLList& data) {
-  scoped_ptr<base::ListValue> pages_value(new ListValue);
+  scoped_ptr<base::ListValue> pages_value(new base::ListValue);
   for (size_t i = 0; i < data.size(); i++) {
     const history::MostVisitedURL& url = data[i];
     if (!url.url.is_empty()) {
-      DictionaryValue* page_value = new DictionaryValue();
+      base::DictionaryValue* page_value = new base::DictionaryValue();
       page_value->SetString("url", url.url.spec());
       if (url.title.empty())
         page_value->SetString("title", url.url.spec());
diff --git a/chrome/browser/extensions/api/usb/usb_api.cc b/chrome/browser/extensions/api/usb/usb_api.cc
index 29aa7c3..c4bb050 100644
--- a/chrome/browser/extensions/api/usb/usb_api.cc
+++ b/chrome/browser/extensions/api/usb/usb_api.cc
@@ -321,7 +321,7 @@
   descriptor.alternate_setting = alternate_setting;
   descriptor.interface_class = interface_class;
   descriptor.interface_subclass = interface_subclass;
-  descriptor.interface_protocol = interface_subclass;
+  descriptor.interface_protocol = interface_protocol;
   descriptor.endpoints = *endpoints;
   return descriptor.ToValue().release();
 }
diff --git a/chrome/browser/extensions/api/web_navigation/web_navigation_api_helpers.cc b/chrome/browser/extensions/api/web_navigation/web_navigation_api_helpers.cc
index 84b94cc..86213ee 100644
--- a/chrome/browser/extensions/api/web_navigation/web_navigation_api_helpers.cc
+++ b/chrome/browser/extensions/api/web_navigation/web_navigation_api_helpers.cc
@@ -8,7 +8,7 @@
 
 #include "base/json/json_writer.h"
 #include "base/strings/string_number_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/extensions/api/web_navigation/web_navigation_api_constants.h"
 #include "chrome/browser/extensions/event_router.h"
@@ -37,7 +37,7 @@
 // Dispatches events to the extension message service.
 void DispatchEvent(content::BrowserContext* browser_context,
                    const char* event_name,
-                   scoped_ptr<ListValue> args,
+                   scoped_ptr<base::ListValue> args,
                    const GURL& url) {
   EventFilteringInfo info;
   info.SetURL(url);
@@ -65,8 +65,8 @@
                               int64 parent_frame_id,
                               bool parent_is_main_frame,
                               const GURL& validated_url) {
-  scoped_ptr<ListValue> args(new ListValue());
-  DictionaryValue* dict = new DictionaryValue();
+  scoped_ptr<base::ListValue> args(new base::ListValue());
+  base::DictionaryValue* dict = new base::DictionaryValue();
   dict->SetInteger(keys::kTabIdKey, ExtensionTabUtil::GetTabId(web_contents));
   dict->SetString(keys::kUrlKey, validated_url.spec());
   dict->SetInteger(keys::kProcessIdKey, render_process_id);
@@ -90,8 +90,8 @@
                          bool is_main_frame,
                          const GURL& url,
                          content::PageTransition transition_type) {
-  scoped_ptr<ListValue> args(new ListValue());
-  DictionaryValue* dict = new DictionaryValue();
+  scoped_ptr<base::ListValue> args(new base::ListValue());
+  base::DictionaryValue* dict = new base::DictionaryValue();
   dict->SetInteger(keys::kTabIdKey, ExtensionTabUtil::GetTabId(web_contents));
   dict->SetString(keys::kUrlKey, url.spec());
   dict->SetInteger(keys::kProcessIdKey,
@@ -100,7 +100,7 @@
   dict->SetString(
       keys::kTransitionTypeKey,
       content::PageTransitionGetCoreTransitionString(transition_type));
-  ListValue* qualifiers = new ListValue();
+  base::ListValue* qualifiers = new base::ListValue();
   if (transition_type & content::PAGE_TRANSITION_CLIENT_REDIRECT)
     qualifiers->Append(Value::CreateStringValue("client_redirect"));
   if (transition_type & content::PAGE_TRANSITION_SERVER_REDIRECT)
@@ -122,8 +122,8 @@
                                 const GURL& url,
                                 bool is_main_frame,
                                 int64 frame_id) {
-  scoped_ptr<ListValue> args(new ListValue());
-  DictionaryValue* dict = new DictionaryValue();
+  scoped_ptr<base::ListValue> args(new base::ListValue());
+  base::DictionaryValue* dict = new base::DictionaryValue();
   dict->SetInteger(keys::kTabIdKey,
                    ExtensionTabUtil::GetTabId(web_contents));
   dict->SetString(keys::kUrlKey, url.spec());
@@ -144,8 +144,8 @@
                          const GURL& url,
                          bool is_main_frame,
                          int64 frame_id) {
-  scoped_ptr<ListValue> args(new ListValue());
-  DictionaryValue* dict = new DictionaryValue();
+  scoped_ptr<base::ListValue> args(new base::ListValue());
+  base::DictionaryValue* dict = new base::DictionaryValue();
   dict->SetInteger(keys::kTabIdKey,
                    ExtensionTabUtil::GetTabId(web_contents));
   dict->SetString(keys::kUrlKey, url.spec());
@@ -174,8 +174,8 @@
       Profile::FromBrowserContext(target_web_contents->GetBrowserContext()),
       false, NULL, NULL, NULL, NULL));
 
-  scoped_ptr<ListValue> args(new ListValue());
-  DictionaryValue* dict = new DictionaryValue();
+  scoped_ptr<base::ListValue> args(new base::ListValue());
+  base::DictionaryValue* dict = new base::DictionaryValue();
   dict->SetInteger(keys::kSourceTabIdKey,
                    ExtensionTabUtil::GetTabId(web_contents));
   dict->SetInteger(keys::kSourceProcessIdKey,
@@ -199,8 +199,8 @@
                              int64 frame_id,
                              bool is_main_frame,
                              int error_code) {
-  scoped_ptr<ListValue> args(new ListValue());
-  DictionaryValue* dict = new DictionaryValue();
+  scoped_ptr<base::ListValue> args(new base::ListValue());
+  base::DictionaryValue* dict = new base::DictionaryValue();
   dict->SetInteger(keys::kTabIdKey, ExtensionTabUtil::GetTabId(web_contents));
   dict->SetString(keys::kUrlKey, url.spec());
   dict->SetInteger(keys::kProcessIdKey, render_process_id);
@@ -218,8 +218,8 @@
     content::WebContents* old_web_contents,
     content::BrowserContext* browser_context,
     content::WebContents* new_web_contents) {
-  scoped_ptr<ListValue> args(new ListValue());
-  DictionaryValue* dict = new DictionaryValue();
+  scoped_ptr<base::ListValue> args(new base::ListValue());
+  base::DictionaryValue* dict = new base::DictionaryValue();
   dict->SetInteger(keys::kReplacedTabIdKey,
                    ExtensionTabUtil::GetTabId(old_web_contents));
   dict->SetInteger(keys::kTabIdKey,
diff --git a/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc b/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc
index d0b3aeb..d57a78e 100644
--- a/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc
+++ b/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc
@@ -37,6 +37,7 @@
 #include "content/public/common/url_constants.h"
 #include "content/public/test/browser_test_utils.h"
 #include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
 #include "third_party/WebKit/public/web/WebContextMenuData.h"
 #include "third_party/WebKit/public/web/WebInputEvent.h"
 #include "webkit/glue/resource_type.h"
@@ -360,7 +361,6 @@
         switches::kAllowLegacyExtensionManifests);
 
     host_resolver()->AddRule("*", "127.0.0.1");
-    ASSERT_TRUE(StartTestServer());
   }
 
   virtual void TearDownInProcessBrowserTestFixture() OVERRIDE {
@@ -387,6 +387,7 @@
 #define MAYBE_Api Api
 #endif  // defined(OS_WIN)
 IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, MAYBE_Api) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(
       RunExtensionSubtest("webnavigation", "test_api.html")) << message_;
 }
@@ -398,17 +399,20 @@
 #define MAYBE_GetFrame GetFrame
 #endif  // defined(OS_WIN)
 IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, MAYBE_GetFrame) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(
       RunExtensionSubtest("webnavigation", "test_getFrame.html")) << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, ClientRedirect) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(
       RunExtensionSubtest("webnavigation", "test_clientRedirect.html"))
           << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, ServerRedirect) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(
       RunExtensionSubtest("webnavigation", "test_serverRedirect.html"))
           << message_;
@@ -423,6 +427,8 @@
 #endif
 IN_PROC_BROWSER_TEST_F(WebNavigationApiTest,
                        MAYBE_ServerRedirectSingleProcess) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
+
   // Set max renderers to 1 to force running out of processes.
   content::RenderProcessHost::SetMaxRendererProcessCount(1);
 
@@ -437,15 +443,15 @@
   ResultCatcher catcher;
   GURL url(base::StringPrintf(
       "http://www.a.com:%d/"
-          "files/extensions/api_test/webnavigation/serverRedirect/a.html",
-      test_server()->host_port_pair().port()));
+          "extensions/api_test/webnavigation/serverRedirect/a.html",
+      embedded_test_server()->port()));
 
   ui_test_utils::NavigateToURL(browser(), url);
 
   url = GURL(base::StringPrintf(
       "http://www.b.com:%d/server-redirect?http://www.b.com:%d/",
-      test_server()->host_port_pair().port(),
-      test_server()->host_port_pair().port()));
+      embedded_test_server()->port(),
+      embedded_test_server()->port()));
 
   ui_test_utils::NavigateToURL(browser(), url);
 
@@ -453,33 +459,39 @@
 }
 
 IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, ForwardBack) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(
       RunExtensionSubtest("webnavigation", "test_forwardBack.html"))
           << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, IFrame) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(
       RunExtensionSubtest("webnavigation", "test_iframe.html")) << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, SrcDoc) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(
       RunExtensionSubtest("webnavigation", "test_srcdoc.html")) << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, OpenTab) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(
       RunExtensionSubtest("webnavigation", "test_openTab.html")) << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, ReferenceFragment) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(
       RunExtensionSubtest("webnavigation", "test_referenceFragment.html"))
           << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, SimpleLoad) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(
       RunExtensionSubtest("webnavigation", "test_simpleLoad.html")) << message_;
 }
@@ -491,11 +503,13 @@
 #define MAYBE_Failures Failures
 #endif  // defined(OS_WIN)
 IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, MAYBE_Failures) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(
       RunExtensionSubtest("webnavigation", "test_failures.html")) << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, FilteredTest) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(
       RunExtensionSubtest("webnavigation", "test_filtered.html")) << message_;
 }
@@ -507,6 +521,8 @@
 #define MAYBE_UserAction UserAction
 #endif  // defined(OS_WIN)
 IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, MAYBE_UserAction) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
+
   // Wait for the extension to set itself up and return control to us.
   ASSERT_TRUE(
       RunExtensionSubtest("webnavigation", "test_userAction.html")) << message_;
@@ -547,6 +563,8 @@
 #define MAYBE_RequestOpenTab RequestOpenTab
 #endif
 IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, MAYBE_RequestOpenTab) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
+
   // Wait for the extension to set itself up and return control to us.
   ASSERT_TRUE(RunExtensionSubtest("webnavigation", "test_requestOpenTab.html"))
       << message_;
@@ -585,6 +603,8 @@
 #define MAYBE_TargetBlank TargetBlank
 #endif  // defined(OS_WIN)
 IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, MAYBE_TargetBlank) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
+
   // Wait for the extension to set itself up and return control to us.
   ASSERT_TRUE(RunExtensionSubtest("webnavigation", "test_targetBlank.html"))
       << message_;
@@ -594,8 +614,8 @@
 
   ResultCatcher catcher;
 
-  GURL url = test_server()->GetURL(
-      "files/extensions/api_test/webnavigation/targetBlank/a.html");
+  GURL url = embedded_test_server()->GetURL(
+      "/extensions/api_test/webnavigation/targetBlank/a.html");
 
   chrome::NavigateParams params(browser(), url, content::PAGE_TRANSITION_LINK);
   ui_test_utils::NavigateToURL(&params);
@@ -622,6 +642,8 @@
 #define MAYBE_TargetBlankIncognito TargetBlankIncognito
 #endif
 IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, MAYBE_TargetBlankIncognito) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
+
   // Wait for the extension to set itself up and return control to us.
   ASSERT_TRUE(RunExtensionSubtest(
       "webnavigation", "test_targetBlank.html",
@@ -629,8 +651,8 @@
 
   ResultCatcher catcher;
 
-  GURL url = test_server()->GetURL(
-      "files/extensions/api_test/webnavigation/targetBlank/a.html");
+  GURL url = embedded_test_server()->GetURL(
+      "/extensions/api_test/webnavigation/targetBlank/a.html");
 
   Browser* otr_browser = ui_test_utils::OpenURLOffTheRecord(
       browser()->profile(), url);
@@ -652,12 +674,15 @@
 }
 
 IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, History) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(
       RunExtensionSubtest("webnavigation", "test_history.html"))
           << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, CrossProcess) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
+
   LoadExtension(test_data_dir_.AppendASCII("webnavigation").AppendASCII("app"));
   LoadExtension(test_data_dir_.AppendASCII("webnavigation"));
 
@@ -669,7 +694,7 @@
   // See crossProcess/d.html.
   DelayLoadStartAndExecuteJavascript call_script(
       test_navigation_listener(),
-      test_server()->GetURL("test1"),
+      embedded_test_server()->GetURL("/test1"),
       "navigate2()",
       extension->GetResourceURL("crossProcess/empty.html"));
 
@@ -679,6 +704,8 @@
 }
 
 IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, CrossProcessFragment) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
+
   LoadExtension(test_data_dir_.AppendASCII("webnavigation"));
 
   ExtensionService* service = extensions::ExtensionSystem::Get(
@@ -689,20 +716,20 @@
   // See crossProcess/f.html.
   DelayLoadStartAndExecuteJavascript call_script3(
       test_navigation_listener(),
-      test_server()->GetURL("test3"),
+      embedded_test_server()->GetURL("/test3"),
       "updateFragment()",
       extension->GetResourceURL(base::StringPrintf(
           "crossProcess/f.html?%d#foo",
-          test_server()->host_port_pair().port())));
+          embedded_test_server()->port())));
 
   // See crossProcess/g.html.
   DelayLoadStartAndExecuteJavascript call_script4(
       test_navigation_listener(),
-      test_server()->GetURL("test4"),
+      embedded_test_server()->GetURL("/test4"),
       "updateFragment()",
       extension->GetResourceURL(base::StringPrintf(
           "crossProcess/g.html?%d#foo",
-          test_server()->host_port_pair().port())));
+          embedded_test_server()->port())));
 
   ASSERT_TRUE(RunPageTest(
       extension->GetResourceURL("test_crossProcessFragment.html").spec()))
@@ -710,6 +737,8 @@
 }
 
 IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, CrossProcessHistory) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
+
   LoadExtension(test_data_dir_.AppendASCII("webnavigation"));
 
   ExtensionService* service = extensions::ExtensionSystem::Get(
@@ -720,21 +749,21 @@
   // See crossProcess/e.html.
   DelayLoadStartAndExecuteJavascript call_script2(
       test_navigation_listener(),
-      test_server()->GetURL("test2"),
+      embedded_test_server()->GetURL("/test2"),
       "updateHistory()",
       extension->GetResourceURL("crossProcess/empty.html"));
 
   // See crossProcess/h.html.
   DelayLoadStartAndExecuteJavascript call_script5(
       test_navigation_listener(),
-      test_server()->GetURL("test5"),
+      embedded_test_server()->GetURL("/test5"),
       "updateHistory()",
       extension->GetResourceURL("crossProcess/empty.html"));
 
   // See crossProcess/i.html.
   DelayLoadStartAndExecuteJavascript call_script6(
       test_navigation_listener(),
-      test_server()->GetURL("test6"),
+      embedded_test_server()->GetURL("/test6"),
       "updateHistory()",
       extension->GetResourceURL("crossProcess/empty.html"));
 
@@ -750,6 +779,8 @@
 #define MAYBE_Crash Crash
 #endif
 IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, MAYBE_Crash) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
+
   // Wait for the extension to set itself up and return control to us.
   ASSERT_TRUE(RunExtensionSubtest("webnavigation", "test_crash.html"))
       << message_;
@@ -761,16 +792,16 @@
 
   GURL url(base::StringPrintf(
       "http://www.a.com:%d/"
-          "files/extensions/api_test/webnavigation/crash/a.html",
-      test_server()->host_port_pair().port()));
+          "extensions/api_test/webnavigation/crash/a.html",
+      embedded_test_server()->port()));
   ui_test_utils::NavigateToURL(browser(), url);
 
   ui_test_utils::NavigateToURL(browser(), GURL(content::kChromeUICrashURL));
 
   url = GURL(base::StringPrintf(
       "http://www.a.com:%d/"
-          "files/extensions/api_test/webnavigation/crash/b.html",
-      test_server()->host_port_pair().port()));
+          "extensions/api_test/webnavigation/crash/b.html",
+      embedded_test_server()->port()));
   ui_test_utils::NavigateToURL(browser(), url);
 
   ASSERT_TRUE(catcher.GetNextResult()) << catcher.message();
diff --git a/chrome/browser/extensions/api/web_request/upload_data_presenter_unittest.cc b/chrome/browser/extensions/api/web_request/upload_data_presenter_unittest.cc
index 5e06660..c445982 100644
--- a/chrome/browser/extensions/api/web_request/upload_data_presenter_unittest.cc
+++ b/chrome/browser/extensions/api/web_request/upload_data_presenter_unittest.cc
@@ -9,11 +9,6 @@
 #include "net/base/upload_bytes_element_reader.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-using base::BinaryValue;
-using base::ListValue;
-using base::StringValue;
-using base::Value;
-
 namespace keys = extension_web_request_api_constants;
 
 namespace extensions {
@@ -27,9 +22,9 @@
   net::UploadBytesElementReader element(block, sizeof(block) - 1);
 
   // Expected output.
-  scoped_ptr<ListValue> values(new ListValue);
-  values->Append(Value::CreateStringValue("value"));
-  DictionaryValue expected_form;
+  scoped_ptr<base::ListValue> values(new base::ListValue);
+  values->Append(base::Value::CreateStringValue("value"));
+  base::DictionaryValue expected_form;
   expected_form.SetWithoutPathExpansion("key.with.dots", values.release());
 
   // Real output.
@@ -38,7 +33,7 @@
   ASSERT_TRUE(parsed_data_presenter.get() != NULL);
   parsed_data_presenter->FeedNext(element);
   EXPECT_TRUE(parsed_data_presenter->Succeeded());
-  scoped_ptr<Value> result = parsed_data_presenter->Result();
+  scoped_ptr<base::Value> result = parsed_data_presenter->Result();
   ASSERT_TRUE(result.get() != NULL);
 
   EXPECT_TRUE(result->Equals(&expected_form));
@@ -53,16 +48,17 @@
   const size_t block2_size = sizeof(block2) - 1;
 
   // Expected output.
-  scoped_ptr<BinaryValue> expected_a(
-      BinaryValue::CreateWithCopiedBuffer(block1, block1_size));
+  scoped_ptr<base::BinaryValue> expected_a(
+      base::BinaryValue::CreateWithCopiedBuffer(block1, block1_size));
   ASSERT_TRUE(expected_a.get() != NULL);
-  scoped_ptr<StringValue> expected_b(Value::CreateStringValue(kFilename));
+  scoped_ptr<base::StringValue> expected_b(
+      base::Value::CreateStringValue(kFilename));
   ASSERT_TRUE(expected_b.get() != NULL);
-  scoped_ptr<BinaryValue> expected_c(
-      BinaryValue::CreateWithCopiedBuffer(block2, block2_size));
+  scoped_ptr<base::BinaryValue> expected_c(
+      base::BinaryValue::CreateWithCopiedBuffer(block2, block2_size));
   ASSERT_TRUE(expected_c.get() != NULL);
 
-  ListValue expected_list;
+  base::ListValue expected_list;
   subtle::AppendKeyValuePair(
       keys::kRequestBodyRawBytesKey, expected_a.release(), &expected_list);
   subtle::AppendKeyValuePair(
@@ -76,7 +72,7 @@
   raw_presenter.FeedNextFile(kFilename);
   raw_presenter.FeedNextBytes(block2, block2_size);
   EXPECT_TRUE(raw_presenter.Succeeded());
-  scoped_ptr<Value> result = raw_presenter.Result();
+  scoped_ptr<base::Value> result = raw_presenter.Result();
   ASSERT_TRUE(result.get() != NULL);
 
   EXPECT_TRUE(result->Equals(&expected_list));
diff --git a/chrome/browser/extensions/api/web_request/web_request_api.cc b/chrome/browser/extensions/api/web_request/web_request_api.cc
index 06b9cb4..38e35f3 100644
--- a/chrome/browser/extensions/api/web_request/web_request_api.cc
+++ b/chrome/browser/extensions/api/web_request/web_request_api.cc
@@ -13,7 +13,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_content_browser_client.h"
diff --git a/chrome/browser/extensions/api/web_request/web_request_api.h b/chrome/browser/extensions/api/web_request/web_request_api.h
index 3a0d43e..1f717f4 100644
--- a/chrome/browser/extensions/api/web_request/web_request_api.h
+++ b/chrome/browser/extensions/api/web_request/web_request_api.h
@@ -13,7 +13,7 @@
 
 #include "base/memory/singleton.h"
 #include "base/memory/weak_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/extensions/api/declarative_webrequest/request_stage.h"
 #include "chrome/browser/extensions/api/web_request/web_request_api_helpers.h"
 #include "chrome/browser/extensions/api/web_request/web_request_permissions.h"
diff --git a/chrome/browser/extensions/api/web_request/web_request_api_helpers.cc b/chrome/browser/extensions/api/web_request/web_request_api_helpers.cc
index f083906..058f122 100644
--- a/chrome/browser/extensions/api/web_request/web_request_api_helpers.cc
+++ b/chrome/browser/extensions/api/web_request/web_request_api_helpers.cc
@@ -10,7 +10,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/extensions/api/web_request/web_request_api.h"
@@ -216,10 +216,10 @@
 Value* NetLogModificationCallback(
     const EventResponseDelta* delta,
     net::NetLog::LogLevel log_level) {
-  DictionaryValue* dict = new DictionaryValue();
+  base::DictionaryValue* dict = new base::DictionaryValue();
   dict->SetString("extension_id", delta->extension_id);
 
-  ListValue* modified_headers = new ListValue();
+  base::ListValue* modified_headers = new base::ListValue();
   net::HttpRequestHeaders::Iterator modification(
       delta->modified_request_headers);
   while (modification.GetNext()) {
@@ -228,7 +228,7 @@
   }
   dict->Set("modified_headers", modified_headers);
 
-  ListValue* deleted_headers = new ListValue();
+  base::ListValue* deleted_headers = new base::ListValue();
   for (std::vector<std::string>::const_iterator key =
            delta->deleted_request_headers.begin();
        key != delta->deleted_request_headers.end();
@@ -245,8 +245,8 @@
   return a->extension_install_time > b->extension_install_time;
 }
 
-ListValue* StringToCharList(const std::string& s) {
-  ListValue* result = new ListValue;
+base::ListValue* StringToCharList(const std::string& s) {
+  base::ListValue* result = new base::ListValue;
   for (size_t i = 0, n = s.size(); i < n; ++i) {
     result->Append(
         Value::CreateIntegerValue(
@@ -255,7 +255,7 @@
   return result;
 }
 
-bool CharListToString(const ListValue* list, std::string* out) {
+bool CharListToString(const base::ListValue* list, std::string* out) {
   if (!list)
     return false;
   const size_t list_length = list->GetSize();
diff --git a/chrome/browser/extensions/api/web_request/web_request_api_helpers.h b/chrome/browser/extensions/api/web_request/web_request_api_helpers.h
index d14f5ca..76325b3 100644
--- a/chrome/browser/extensions/api/web_request/web_request_api_helpers.h
+++ b/chrome/browser/extensions/api/web_request/web_request_api_helpers.h
@@ -11,10 +11,10 @@
 #include <set>
 #include <string>
 
-#include "base/memory/ref_counted.h"
 #include "base/memory/linked_ptr.h"
+#include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/extensions/extension_warning_set.h"
 #include "googleurl/src/gurl.h"
 #include "net/base/auth.h"
diff --git a/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc b/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc
index 0e58bdc..408ed01 100644
--- a/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc
+++ b/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc
@@ -19,7 +19,7 @@
 #include "base/strings/string_piece.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/content_settings/cookie_settings.h"
 #include "chrome/browser/extensions/api/web_request/upload_data_presenter.h"
 #include "chrome/browser/extensions/api/web_request/web_request_api.h"
diff --git a/chrome/browser/extensions/api/web_request/web_request_apitest.cc b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
index 767eeec..0cca09d 100644
--- a/chrome/browser/extensions/api/web_request/web_request_apitest.cc
+++ b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
@@ -22,6 +22,7 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test_utils.h"
 #include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
 #include "third_party/WebKit/public/web/WebInputEvent.h"
 
 using content::WebContents;
@@ -64,7 +65,6 @@
 
     ExtensionApiTest::SetUpInProcessBrowserTestFixture();
     host_resolver()->AddRule("*", "127.0.0.1");
-    ASSERT_TRUE(StartTestServer());
   }
 
   void RunPermissionTest(
@@ -76,6 +76,7 @@
 };
 
 IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, WebRequestApi) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionSubtest("webrequest", "test_api.html")) << message_;
 }
 
@@ -86,11 +87,13 @@
 #define MAYBE_WebRequestSimple WebRequestSimple
 #endif  // defined(OS_WIN)
 IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, MAYBE_WebRequestSimple) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionSubtest("webrequest", "test_simple.html")) <<
       message_;
 }
 
 IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, WebRequestComplex) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionSubtest("webrequest", "test_complex.html")) <<
       message_;
 }
@@ -100,6 +103,7 @@
                        DISABLED_WebRequestAuthRequired) {
   CancelLoginDialog login_dialog_helper;
 
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionSubtest("webrequest", "test_auth_required.html")) <<
       message_;
 }
@@ -111,6 +115,7 @@
 #define MAYBE_WebRequestBlocking WebRequestBlocking
 #endif
 IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, MAYBE_WebRequestBlocking) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionSubtest("webrequest", "test_blocking.html")) <<
       message_;
 }
@@ -122,6 +127,7 @@
 #define MAYBE_WebRequestNewTab WebRequestNewTab
 #endif  // defined(OS_WIN)
 IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, MAYBE_WebRequestNewTab) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
   // Wait for the extension to set itself up and return control to us.
   ASSERT_TRUE(RunExtensionSubtest("webrequest", "test_newTab.html"))
       << message_;
@@ -155,6 +161,7 @@
 }
 
 IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, WebRequestDeclarative1) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionSubtest("webrequest", "test_declarative1.html"))
       << message_;
 }
@@ -167,6 +174,7 @@
 #endif
 IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
                        MAYBE_WebRequestDeclarative2) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionSubtest("webrequest", "test_declarative2.html"))
       << message_;
 }
@@ -200,7 +208,7 @@
   // This navigation should be redirected.
   ui_test_utils::NavigateToURL(
       browser(),
-      test_server()->GetURL("files/extensions/test_file.html"));
+      embedded_test_server()->GetURL("/extensions/test_file.html"));
 
   std::string body;
   WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
@@ -221,7 +229,7 @@
   // load_extension_with_incognito_permission is true.
   ui_test_utils::NavigateToURL(
       otr_browser,
-      test_server()->GetURL("files/extensions/test_file.html"));
+      embedded_test_server()->GetURL("/extensions/test_file.html"));
 
   body.clear();
   WebContents* otr_tab = otr_browser->tab_strip_model()->GetActiveWebContents();
@@ -235,12 +243,14 @@
 IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
                        WebRequestDeclarativePermissionSpanning1) {
   // Test spanning with incognito permission.
+  ASSERT_TRUE(StartEmbeddedTestServer());
   RunPermissionTest("spanning", true, false, "redirected1", "redirected1");
 }
 
 IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
                        WebRequestDeclarativePermissionSpanning2) {
   // Test spanning without incognito permission.
+  ASSERT_TRUE(StartEmbeddedTestServer());
   RunPermissionTest("spanning", false, false, "redirected1", "");
 }
 
@@ -248,12 +258,14 @@
 IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
                        WebRequestDeclarativePermissionSplit1) {
   // Test split with incognito permission.
+  ASSERT_TRUE(StartEmbeddedTestServer());
   RunPermissionTest("split", true, true, "redirected1", "redirected2");
 }
 
 IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
                        WebRequestDeclarativePermissionSplit2) {
   // Test split without incognito permission.
+  ASSERT_TRUE(StartEmbeddedTestServer());
   RunPermissionTest("split", false, false, "redirected1", "");
 }
 
@@ -267,18 +279,21 @@
 #endif
 IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, MAYBE_PostData1) {
   // Test HTML form POST data access with the default and "url" encoding.
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionSubtest("webrequest", "test_post1.html")) <<
       message_;
 }
 
 IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, MAYBE_PostData2) {
   // Test HTML form POST data access with the multipart and plaintext encoding.
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionSubtest("webrequest", "test_post2.html")) <<
       message_;
 }
 
 IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
                        DeclarativeSendMessage) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionTest("webrequest_sendmessage")) << message_;
 }
 
@@ -286,6 +301,7 @@
 // has two active background pages with registered events does not crash the
 // browser. Regression test for http://crbug.com/224094
 IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, IncognitoSplitModeReload) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
   // Wait for rules to be set up.
   ExtensionTestMessageListener listener("done", true);
   ExtensionTestMessageListener listener_incognito("done_incognito", true);
diff --git a/chrome/browser/extensions/api/web_request/web_request_time_tracker.h b/chrome/browser/extensions/api/web_request/web_request_time_tracker.h
index fc58aa0..ff33e70 100644
--- a/chrome/browser/extensions/api/web_request/web_request_time_tracker.h
+++ b/chrome/browser/extensions/api/web_request/web_request_time_tracker.h
@@ -12,7 +12,7 @@
 
 #include "base/gtest_prod_util.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "googleurl/src/gurl.h"
 
 namespace base {
diff --git a/chrome/browser/extensions/api/web_socket_proxy_private/web_socket_proxy_private_api.cc b/chrome/browser/extensions/api/web_socket_proxy_private/web_socket_proxy_private_api.cc
index 91483c5..3e551a3 100644
--- a/chrome/browser/extensions/api/web_socket_proxy_private/web_socket_proxy_private_api.cc
+++ b/chrome/browser/extensions/api/web_socket_proxy_private/web_socket_proxy_private_api.cc
@@ -171,7 +171,7 @@
 
 bool WebSocketProxyPrivateGetURLForTCPFunction::RunImpl() {
 #if defined(OS_CHROMEOS)
-  DictionaryValue* qualification = NULL;
+  base::DictionaryValue* qualification = NULL;
   if (args_->GetDictionary(2, &qualification)) {
     const char kTlsOption[] = "tls";
     if (qualification->HasKey(kTlsOption)) {
diff --git a/chrome/browser/extensions/api/web_socket_proxy_private/web_socket_proxy_private_api.h b/chrome/browser/extensions/api/web_socket_proxy_private/web_socket_proxy_private_api.h
index 29677a6..bec791e 100644
--- a/chrome/browser/extensions/api/web_socket_proxy_private/web_socket_proxy_private_api.h
+++ b/chrome/browser/extensions/api/web_socket_proxy_private/web_socket_proxy_private_api.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_EXTENSIONS_API_WEB_SOCKET_PROXY_PRIVATE_WEB_SOCKET_PROXY_PRIVATE_API_H_
 #define CHROME_BROWSER_EXTENSIONS_API_WEB_SOCKET_PROXY_PRIVATE_WEB_SOCKET_PROXY_PRIVATE_API_H_
 
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/extensions/extension_function.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
diff --git a/chrome/browser/extensions/api/web_socket_proxy_private/web_socket_proxy_private_apitest.cc b/chrome/browser/extensions/api/web_socket_proxy_private/web_socket_proxy_private_apitest.cc
index d75832c..c417921 100644
--- a/chrome/browser/extensions/api/web_socket_proxy_private/web_socket_proxy_private_apitest.cc
+++ b/chrome/browser/extensions/api/web_socket_proxy_private/web_socket_proxy_private_apitest.cc
@@ -18,7 +18,7 @@
 IN_PROC_BROWSER_TEST_F(ExtensionWebSocketProxyPrivateApiTest, Pass) {
   // Currently WebSocket-to-TCP proxy is operational only on ChromeOS platform.
 #if defined(OS_CHROMEOS)
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionTest("web_socket_proxy_private")) << message_;
   // Check if API still works on subsequent calls.
   ASSERT_TRUE(RunExtensionTest("web_socket_proxy_private")) << message_;
diff --git a/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc b/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc
index 9d25844..2f398b5 100644
--- a/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc
+++ b/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc
@@ -20,8 +20,6 @@
 #include "chrome/browser/extensions/extension_prefs.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_system.h"
-#include "chrome/browser/extensions/install_tracker.h"
-#include "chrome/browser/extensions/install_tracker_factory.h"
 #include "chrome/browser/extensions/webstore_installer.h"
 #include "chrome/browser/gpu/gpu_feature_checker.h"
 #include "chrome/browser/profiles/profile_manager.h"
@@ -168,8 +166,8 @@
 
 // Helper to create a dictionary with login properties set from the appropriate
 // values in the passed-in |profile|.
-DictionaryValue* CreateLoginResult(Profile* profile) {
-  DictionaryValue* dictionary = new DictionaryValue();
+base::DictionaryValue* CreateLoginResult(Profile* profile) {
+  base::DictionaryValue* dictionary = new base::DictionaryValue();
   std::string username = profile->GetPrefs()->GetString(
       prefs::kGoogleServicesUsername);
   dictionary->SetString(kLoginKey, username);
@@ -222,7 +220,7 @@
 InstallBundleFunction::~InstallBundleFunction() {}
 
 bool InstallBundleFunction::RunImpl() {
-  ListValue* extensions = NULL;
+  base::ListValue* extensions = NULL;
   EXTENSION_FUNCTION_VALIDATE(args_->GetList(0, &extensions));
 
   BundleInstaller::ItemList items;
@@ -237,10 +235,10 @@
   return true;
 }
 
-bool InstallBundleFunction::ReadBundleInfo(ListValue* extensions,
+bool InstallBundleFunction::ReadBundleInfo(base::ListValue* extensions,
                                            BundleInstaller::ItemList* items) {
   for (size_t i = 0; i < extensions->GetSize(); ++i) {
-    DictionaryValue* details = NULL;
+    base::DictionaryValue* details = NULL;
     EXTENSION_FUNCTION_VALIDATE(extensions->GetDictionary(i, &details));
 
     BundleInstaller::Item item;
@@ -286,7 +284,7 @@
 BeginInstallWithManifestFunction::~BeginInstallWithManifestFunction() {}
 
 bool BeginInstallWithManifestFunction::RunImpl() {
-  DictionaryValue* details = NULL;
+  base::DictionaryValue* details = NULL;
   EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &details));
   CHECK(details);
 
@@ -401,7 +399,7 @@
 void BeginInstallWithManifestFunction::OnWebstoreParseSuccess(
     const std::string& id,
     const SkBitmap& icon,
-    DictionaryValue* parsed_manifest) {
+    base::DictionaryValue* parsed_manifest) {
   CHECK_EQ(id_, id);
   CHECK(parsed_manifest);
   icon_ = icon;
@@ -584,20 +582,9 @@
     LOG(ERROR) << "Error installing app launcher";
   std::string id = approval_->extension_id;
   if (apps::IsAppLauncherEnabled()) {
-    std::string name;
-    if (!approval_->manifest->value()->GetString(extension_manifest_keys::kName,
-                                                 &name)) {
-      NOTREACHED();
-    }
     // Show the app list so it receives install progress notifications.
     if (approval_->manifest->is_app())
       AppListService::Get()->ShowAppList(profile());
-
-    extensions::InstallTracker* tracker =
-        extensions::InstallTrackerFactory::GetForProfile(profile());
-    tracker->OnBeginExtensionInstall(
-        id, name, approval_->installing_icon, approval_->manifest->is_app(),
-        approval_->manifest->is_platform_app());
   }
 
   // The extension will install through the normal extension install flow, but
@@ -626,9 +613,6 @@
     const std::string& id,
     const std::string& error,
     WebstoreInstaller::FailureReason reason) {
-  extensions::InstallTracker* tracker =
-      extensions::InstallTrackerFactory::GetForProfile(profile());
-  tracker->OnInstallFailure(id);
   if (test_webstore_installer_delegate) {
     test_webstore_installer_delegate->OnExtensionInstallFailure(
         id, error, reason);
@@ -643,14 +627,6 @@
   Release();
 }
 
-void CompleteInstallFunction::OnExtensionDownloadProgress(
-    const std::string& id,
-    content::DownloadItem* item) {
-  extensions::InstallTracker* tracker =
-      extensions::InstallTrackerFactory::GetForProfile(profile());
-  tracker->OnDownloadProgress(id, item->PercentComplete());
-}
-
 EnableAppLauncherFunction::EnableAppLauncherFunction() {}
 
 EnableAppLauncherFunction::~EnableAppLauncherFunction() {}
@@ -714,4 +690,11 @@
   return true;
 }
 
+bool IsInIncognitoModeFunction::RunImpl() {
+  SetResult(
+      Value::CreateBooleanValue(profile_ != profile_->GetOriginalProfile()));
+  SendResponse(true);
+  return true;
+}
+
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/webstore_private/webstore_private_api.h b/chrome/browser/extensions/api/webstore_private/webstore_private_api.h
index 18ef67f..5866259 100644
--- a/chrome/browser/extensions/api/webstore_private/webstore_private_api.h
+++ b/chrome/browser/extensions/api/webstore_private/webstore_private_api.h
@@ -182,9 +182,6 @@
       const std::string& id,
       const std::string& error,
       WebstoreInstaller::FailureReason reason) OVERRIDE;
-  virtual void OnExtensionDownloadProgress(
-      const std::string& id,
-      content::DownloadItem* item) OVERRIDE;
 
  protected:
   virtual ~CompleteInstallFunction();
@@ -290,6 +287,20 @@
   void OnIsLauncherCheckCompleted(bool is_enabled);
 };
 
+class IsInIncognitoModeFunction : public AsyncExtensionFunction {
+ public:
+  DECLARE_EXTENSION_FUNCTION("webstorePrivate.isInIncognitoMode",
+                             WEBSTOREPRIVATE_ISININCOGNITOMODEFUNCTION)
+
+  IsInIncognitoModeFunction() {}
+
+ protected:
+  virtual ~IsInIncognitoModeFunction() {}
+
+  // ExtensionFunction:
+  virtual bool RunImpl() OVERRIDE;
+};
+
 }  // namespace extensions
 
 #endif  // CHROME_BROWSER_EXTENSIONS_API_WEBSTORE_PRIVATE_WEBSTORE_PRIVATE_API_H_
diff --git a/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc b/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc
index 40ddd5b..ad7dfbe 100644
--- a/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc
+++ b/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc
@@ -191,7 +191,7 @@
   base::ScopedTempDir temp_dir;
   EXPECT_TRUE(temp_dir.CreateUniqueTempDir());
   base::FilePath missing_directory = temp_dir.Take();
-  EXPECT_TRUE(file_util::Delete(missing_directory, true));
+  EXPECT_TRUE(base::Delete(missing_directory, true));
   WebstoreInstaller::SetDownloadDirectoryForTests(&missing_directory);
 
   // Now run the install test, which should succeed.
@@ -199,7 +199,7 @@
 
   // Cleanup.
   if (file_util::DirectoryExists(missing_directory))
-    EXPECT_TRUE(file_util::Delete(missing_directory, true));
+    EXPECT_TRUE(base::Delete(missing_directory, true));
 }
 
 // Tests passing a localized name.
@@ -241,6 +241,17 @@
   ASSERT_EQ("iladmdjkfniedhfhcfoefgojhgaiaccc", listener.id());
 }
 
+IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTest, IsInIncognitoMode) {
+  GURL page_url = GetTestServerURL("incognito.html");
+  ASSERT_TRUE(
+      RunPageTest(page_url.spec(), ExtensionApiTest::kFlagUseIncognito));
+}
+
+IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTest, IsNotInIncognitoMode) {
+  GURL page_url = GetTestServerURL("not_incognito.html");
+  ASSERT_TRUE(RunPageTest(page_url.spec()));
+}
+
 // Fails often on Windows dbg bots. http://crbug.com/177163.
 #if defined(OS_WIN)
 #define MAYBE_IconUrl DISABLED_IconUrl
diff --git a/chrome/browser/extensions/api/webview/webview_api.cc b/chrome/browser/extensions/api/webview/webview_api.cc
index a5be9df..c342072 100644
--- a/chrome/browser/extensions/api/webview/webview_api.cc
+++ b/chrome/browser/extensions/api/webview/webview_api.cc
@@ -5,7 +5,7 @@
 #include "chrome/browser/extensions/api/webview/webview_api.h"
 
 #include "chrome/browser/extensions/tab_helper.h"
-#include "chrome/browser/webview/webview_guest.h"
+#include "chrome/browser/guestview/webview/webview_guest.h"
 #include "chrome/common/extensions/api/webview.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
@@ -32,7 +32,7 @@
   if (!guest_instance_id_)
     return false;
 
-  DictionaryValue* details_value = NULL;
+  base::DictionaryValue* details_value = NULL;
   if (!args_->GetDictionary(1, &details_value))
     return false;
   scoped_ptr<InjectDetails> details(new InjectDetails());
@@ -52,7 +52,7 @@
 }
 
 extensions::ScriptExecutor* WebviewExecuteCodeFunction::GetScriptExecutor() {
-  chrome::WebViewGuest* guest = chrome::WebViewGuest::From(
+  WebViewGuest* guest = WebViewGuest::From(
       render_view_host()->GetProcess()->GetID(), guest_instance_id_);
   if (!guest)
     return NULL;
@@ -64,11 +64,14 @@
   return true;
 }
 
+WebviewExecuteScriptFunction::WebviewExecuteScriptFunction() {
+}
+
 void WebviewExecuteScriptFunction::OnExecuteCodeFinished(
     const std::string& error,
     int32 on_page_id,
     const GURL& on_url,
-    const ListValue& result) {
+    const base::ListValue& result) {
   content::RecordAction(content::UserMetricsAction("WebView.ExecuteScript"));
   if (error.empty())
     SetResult(result.DeepCopy());
@@ -76,7 +79,31 @@
                                                     result);
 }
 
+WebviewInsertCSSFunction::WebviewInsertCSSFunction() {
+}
+
 bool WebviewInsertCSSFunction::ShouldInsertCSS() const {
   return true;
 }
 
+WebviewGoFunction::WebviewGoFunction() {
+}
+
+WebviewGoFunction::~WebviewGoFunction() {
+}
+
+bool WebviewGoFunction::RunImpl() {
+  int instance_id = 0;
+  EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &instance_id));
+
+  int relative_index = 0;
+  EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(1, &relative_index));
+
+  WebViewGuest* guest = WebViewGuest::From(
+      render_view_host()->GetProcess()->GetID(), instance_id);
+  if (!guest)
+    return false;
+
+  guest->Go(relative_index);
+  return true;
+}
diff --git a/chrome/browser/extensions/api/webview/webview_api.h b/chrome/browser/extensions/api/webview/webview_api.h
index c525e2c..a015119 100644
--- a/chrome/browser/extensions/api/webview/webview_api.h
+++ b/chrome/browser/extensions/api/webview/webview_api.h
@@ -27,26 +27,57 @@
   extensions::ExtensionResource resource_;
 
   int guest_instance_id_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebviewExecuteCodeFunction);
 };
 
 class WebviewExecuteScriptFunction : public WebviewExecuteCodeFunction {
+ public:
+  WebviewExecuteScriptFunction();
+
  protected:
   virtual ~WebviewExecuteScriptFunction() {}
 
   virtual void OnExecuteCodeFinished(const std::string& error,
                                      int32 on_page_id,
                                      const GURL& on_url,
-                                     const ListValue& result) OVERRIDE;
+                                     const base::ListValue& result) OVERRIDE;
 
   DECLARE_EXTENSION_FUNCTION("webview.executeScript", WEBVIEW_EXECUTESCRIPT)
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(WebviewExecuteScriptFunction);
 };
 
 class WebviewInsertCSSFunction : public WebviewExecuteCodeFunction {
+ public:
+  WebviewInsertCSSFunction();
+
  protected:
   virtual ~WebviewInsertCSSFunction() {}
 
   virtual bool ShouldInsertCSS() const OVERRIDE;
 
   DECLARE_EXTENSION_FUNCTION("webview.insertCSS", WEBVIEW_INSERTCSS)
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(WebviewInsertCSSFunction);
 };
+
+class WebviewGoFunction : public AsyncExtensionFunction {
+ public:
+  DECLARE_EXTENSION_FUNCTION("webview.go", WEBVIEW_GO);
+
+  WebviewGoFunction();
+
+ protected:
+  virtual ~WebviewGoFunction();
+
+  // ExtensionFunction implementation.
+  virtual bool RunImpl() OVERRIDE;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(WebviewGoFunction);
+};
+
 #endif  // CHROME_BROWSER_EXTENSIONS_API_WEBVIEW_WEBVIEW_API_H_
diff --git a/chrome/browser/extensions/app_background_page_apitest.cc b/chrome/browser/extensions/app_background_page_apitest.cc
index 773c528..75fe6cf 100644
--- a/chrome/browser/extensions/app_background_page_apitest.cc
+++ b/chrome/browser/extensions/app_background_page_apitest.cc
@@ -20,6 +20,7 @@
 #include "content/public/test/test_notification_tracker.h"
 #include "content/public/test/test_utils.h"
 #include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
 
 #if defined(OS_MACOSX)
 #include "base/mac/scoped_nsautorelease_pool.h"
@@ -114,7 +115,7 @@
 
 IN_PROC_BROWSER_TEST_F(AppBackgroundPageApiTest, MAYBE_Basic) {
   host_resolver()->AddRule("a.com", "127.0.0.1");
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   std::string app_manifest = base::StringPrintf(
       "{"
@@ -131,7 +132,7 @@
       "  },"
       "  \"permissions\": [\"background\"]"
       "}",
-      test_server()->host_port_pair().port());
+      embedded_test_server()->port());
 
   base::FilePath app_dir;
   ASSERT_TRUE(CreateApp(app_manifest, &app_dir));
@@ -147,7 +148,7 @@
 // Crashy, http://crbug.com/69215.
 IN_PROC_BROWSER_TEST_F(AppBackgroundPageApiTest, DISABLED_LacksPermission) {
   host_resolver()->AddRule("a.com", "127.0.0.1");
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   std::string app_manifest = base::StringPrintf(
       "{"
@@ -163,7 +164,7 @@
       "    }"
       "  }"
       "}",
-      test_server()->host_port_pair().port());
+      embedded_test_server()->port());
 
   base::FilePath app_dir;
   ASSERT_TRUE(CreateApp(app_manifest, &app_dir));
@@ -175,7 +176,7 @@
 
 IN_PROC_BROWSER_TEST_F(AppBackgroundPageApiTest, ManifestBackgroundPage) {
   host_resolver()->AddRule("a.com", "127.0.0.1");
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   std::string app_manifest = base::StringPrintf(
       "{"
@@ -195,8 +196,8 @@
       "    \"page\": \"http://a.com:%d/test.html\""
       "  }"
       "}",
-      test_server()->host_port_pair().port(),
-      test_server()->host_port_pair().port());
+      embedded_test_server()->port(),
+      embedded_test_server()->port());
 
   base::FilePath app_dir;
   ASSERT_TRUE(CreateApp(app_manifest, &app_dir));
@@ -223,7 +224,7 @@
       content::Source<Profile>(browser()->profile()));
 
   host_resolver()->AddRule("a.com", "127.0.0.1");
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   std::string app_manifest = base::StringPrintf(
       "{"
@@ -243,7 +244,7 @@
       "    \"allow_js_access\": false"
       "  }"
       "}",
-      test_server()->host_port_pair().port());
+      embedded_test_server()->port());
 
   base::FilePath app_dir;
   ASSERT_TRUE(CreateApp(app_manifest, &app_dir));
@@ -267,7 +268,7 @@
 
 IN_PROC_BROWSER_TEST_F(AppBackgroundPageApiTest, NoJsManifestBackgroundPage) {
   host_resolver()->AddRule("a.com", "127.0.0.1");
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   std::string app_manifest = base::StringPrintf(
       "{"
@@ -288,8 +289,8 @@
       "    \"allow_js_access\": false"
       "  }"
       "}",
-      test_server()->host_port_pair().port(),
-      test_server()->host_port_pair().port());
+      embedded_test_server()->port(),
+      embedded_test_server()->port());
 
   base::FilePath app_dir;
   ASSERT_TRUE(CreateApp(app_manifest, &app_dir));
@@ -307,7 +308,7 @@
 
 IN_PROC_BROWSER_TEST_F(AppBackgroundPageApiTest, OpenTwoBackgroundPages) {
   host_resolver()->AddRule("a.com", "127.0.0.1");
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   std::string app_manifest = base::StringPrintf(
       "{"
@@ -324,7 +325,7 @@
       "  },"
       "  \"permissions\": [\"background\"]"
       "}",
-      test_server()->host_port_pair().port());
+      embedded_test_server()->port());
 
   base::FilePath app_dir;
   ASSERT_TRUE(CreateApp(app_manifest, &app_dir));
@@ -336,7 +337,7 @@
 
 IN_PROC_BROWSER_TEST_F(AppBackgroundPageApiTest, OpenTwoPagesWithManifest) {
   host_resolver()->AddRule("a.com", "127.0.0.1");
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   std::string app_manifest = base::StringPrintf(
       "{"
@@ -356,8 +357,8 @@
       "  },"
       "  \"permissions\": [\"background\"]"
       "}",
-      test_server()->host_port_pair().port(),
-      test_server()->host_port_pair().port());
+      embedded_test_server()->port(),
+      embedded_test_server()->port());
 
   base::FilePath app_dir;
   ASSERT_TRUE(CreateApp(app_manifest, &app_dir));
@@ -371,7 +372,7 @@
 // Times out occasionally -- see crbug.com/108493
 IN_PROC_BROWSER_TEST_F(AppBackgroundPageApiTest, DISABLED_OpenPopupFromBGPage) {
   host_resolver()->AddRule("a.com", "127.0.0.1");
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   std::string app_manifest = base::StringPrintf(
       "{"
@@ -386,12 +387,12 @@
       "      \"web_url\": \"http://a.com:%d/\""
       "    }"
       "  },"
-      "  \"background\": { \"page\": \"http://a.com:%d/files/extensions/api_test/"
+      "  \"background\": { \"page\": \"http://a.com:%d/extensions/api_test/"
       "app_background_page/bg_open/bg_open_bg.html\" },"
       "  \"permissions\": [\"background\"]"
       "}",
-      test_server()->host_port_pair().port(),
-      test_server()->host_port_pair().port());
+      embedded_test_server()->port(),
+      embedded_test_server()->port());
 
   base::FilePath app_dir;
   ASSERT_TRUE(CreateApp(app_manifest, &app_dir));
@@ -401,7 +402,7 @@
 
 IN_PROC_BROWSER_TEST_F(AppBackgroundPageApiTest, DISABLED_OpenThenClose) {
   host_resolver()->AddRule("a.com", "127.0.0.1");
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   std::string app_manifest = base::StringPrintf(
       "{"
@@ -418,7 +419,7 @@
       "  },"
       "  \"permissions\": [\"background\"]"
       "}",
-      test_server()->host_port_pair().port());
+      embedded_test_server()->port());
 
   base::FilePath app_dir;
   ASSERT_TRUE(CreateApp(app_manifest, &app_dir));
@@ -447,7 +448,7 @@
 
 IN_PROC_BROWSER_TEST_F(AppBackgroundPageApiTest, UnloadExtensionWhileHidden) {
   host_resolver()->AddRule("a.com", "127.0.0.1");
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   std::string app_manifest = base::StringPrintf(
       "{"
@@ -467,8 +468,8 @@
       "    \"page\": \"http://a.com:%d/test.html\""
       "  }"
       "}",
-      test_server()->host_port_pair().port(),
-      test_server()->host_port_pair().port());
+      embedded_test_server()->port(),
+      embedded_test_server()->port());
 
   base::FilePath app_dir;
   ASSERT_TRUE(CreateApp(app_manifest, &app_dir));
diff --git a/chrome/browser/extensions/app_process_apitest.cc b/chrome/browser/extensions/app_process_apitest.cc
index f47eb7b..e48b29d 100644
--- a/chrome/browser/extensions/app_process_apitest.cc
+++ b/chrome/browser/extensions/app_process_apitest.cc
@@ -28,6 +28,7 @@
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_navigation_observer.h"
 #include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
 #include "sync/api/string_ordinal.h"
 
 using content::NavigationController;
@@ -44,8 +45,8 @@
     GURL::Replacements replace_host;
     std::string host_str("localhost");  // must stay in scope with replace_host
     replace_host.SetHostStr(host_str);
-    GURL base_url = test_server()->GetURL(
-        "files/extensions/api_test/" + test_directory + "/");
+    GURL base_url = embedded_test_server()->GetURL(
+        "/extensions/api_test/" + test_directory + "/");
     return base_url.ReplaceComponents(replace_host);
   }
 
@@ -67,7 +68,7 @@
         browser()->profile())->extension_service()->process_map();
 
     host_resolver()->AddRule("*", "127.0.0.1");
-    ASSERT_TRUE(test_server()->Start());
+    ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
     ASSERT_TRUE(LoadExtension(
         test_data_dir_.AppendASCII(app_name)));
@@ -144,7 +145,7 @@
       browser()->profile())->extension_service()->process_map();
 
   host_resolver()->AddRule("*", "127.0.0.1");
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("app_process")));
 
@@ -291,7 +292,7 @@
   extensions::ProcessMap* process_map = service->process_map();
 
   host_resolver()->AddRule("*", "127.0.0.1");
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
   GURL base_url = GetTestBaseURL("app_process");
 
   // Load an app as a bookmark app.
@@ -371,7 +372,7 @@
 // See http://crbug.com/61757
 IN_PROC_BROWSER_TEST_F(AppApiTest, AppProcessRedirectBack) {
   host_resolver()->AddRule("*", "127.0.0.1");
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("app_process")));
 
@@ -397,7 +398,7 @@
   // 3 tabs, including the initial about:blank. The last 2 should be the same
   // process.
   ASSERT_EQ(3, browser()->tab_strip_model()->count());
-  EXPECT_EQ("/files/extensions/api_test/app_process/path1/empty.html",
+  EXPECT_EQ("/extensions/api_test/app_process/path1/empty.html",
             browser()->tab_strip_model()->GetWebContentsAt(2)->
                 GetController().GetLastCommittedEntry()->GetURL().path());
   EXPECT_EQ(browser()->tab_strip_model()->GetWebContentsAt(1)->
@@ -416,7 +417,7 @@
       browser()->profile())->extension_service()->process_map();
 
   host_resolver()->AddRule("*", "127.0.0.1");
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   // The app under test acts on URLs whose host is "localhost",
   // so the URLs we navigate to must have host "localhost".
@@ -463,7 +464,7 @@
       browser()->profile())->extension_service()->process_map();
 
   host_resolver()->AddRule("*", "127.0.0.1");
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   // The app under test acts on URLs whose host is "localhost",
   // so the URLs we navigate to must have host "localhost".
@@ -528,7 +529,7 @@
       browser()->profile())->extension_service()->process_map();
 
   host_resolver()->AddRule("*", "127.0.0.1");
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   // The app under test acts on URLs whose host is "localhost",
   // so the URLs we navigate to must have host "localhost".
@@ -602,7 +603,7 @@
       browser()->profile())->extension_service()->process_map();
 
   host_resolver()->AddRule("*", "127.0.0.1");
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   GURL base_url = GetTestBaseURL("app_process");
 
@@ -638,7 +639,7 @@
 #endif
 IN_PROC_BROWSER_TEST_F(BlockedAppApiTest, MAYBE_OpenAppFromIframe) {
   host_resolver()->AddRule("*", "127.0.0.1");
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   // Load app and start URL (not in the app).
   const Extension* app =
@@ -666,7 +667,7 @@
 // up with an app process. See http://crbug.com/99349 for more details.
 IN_PROC_BROWSER_TEST_F(AppApiTest, ServerRedirectToAppFromExtension) {
   host_resolver()->AddRule("*", "127.0.0.1");
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   LoadExtension(test_data_dir_.AppendASCII("app_process"));
   const Extension* launcher =
@@ -708,7 +709,7 @@
 // up with an app process.
 IN_PROC_BROWSER_TEST_F(AppApiTest, ClientRedirectToAppFromExtension) {
   host_resolver()->AddRule("*", "127.0.0.1");
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   LoadExtension(test_data_dir_.AppendASCII("app_process"));
   const Extension* launcher =
@@ -757,7 +758,7 @@
       browser()->profile())->extension_service()->process_map();
 
   host_resolver()->AddRule("*", "127.0.0.1");
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   GURL base_url = GetTestBaseURL("app_process");
 
@@ -794,7 +795,7 @@
       browser()->profile())->extension_service()->process_map();
 
   host_resolver()->AddRule("*", "127.0.0.1");
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("app_process")));
 
diff --git a/chrome/browser/extensions/app_window_contents.cc b/chrome/browser/extensions/app_window_contents.cc
index f515fc8..5c6ff07 100644
--- a/chrome/browser/extensions/app_window_contents.cc
+++ b/chrome/browser/extensions/app_window_contents.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/extensions/app_window_contents.h"
 
+#include "chrome/browser/printing/print_preview_message_handler.h"
+#include "chrome/browser/printing/print_view_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/extensions/native_app_window.h"
 #include "chrome/common/chrome_notification_types.h"
@@ -19,6 +21,8 @@
 
 namespace app_window = extensions::api::app_window;
 
+using apps::ShellWindow;
+
 AppWindowContents::AppWindowContents(ShellWindow* host)
     : host_(host) {
 }
@@ -40,6 +44,12 @@
   web_contents_->GetMutableRendererPrefs()->
       browser_handles_all_top_level_requests = true;
   web_contents_->GetRenderViewHost()->SyncRendererPrefs();
+
+#if defined(ENABLE_PRINTING)
+  printing::PrintPreviewMessageHandler::CreateForWebContents(
+      web_contents_.get());
+  printing::PrintViewManager::CreateForWebContents(web_contents_.get());
+#endif
 }
 
 void AppWindowContents::LoadContents(int32 creator_process_id) {
@@ -76,7 +86,7 @@
 
 void AppWindowContents::NativeWindowChanged(
     NativeAppWindow* native_app_window) {
-  ListValue args;
+  base::ListValue args;
   DictionaryValue* dictionary = new DictionaryValue();
   args.Append(dictionary);
 
diff --git a/chrome/browser/extensions/app_window_contents.h b/chrome/browser/extensions/app_window_contents.h
index 3cf2a32..bb37787 100644
--- a/chrome/browser/extensions/app_window_contents.h
+++ b/chrome/browser/extensions/app_window_contents.h
@@ -7,10 +7,10 @@
 
 #include <vector>
 
+#include "apps/shell_window.h"
 #include "base/basictypes.h"
 #include "base/memory/scoped_ptr.h"
 #include "chrome/browser/extensions/extension_function_dispatcher.h"
-#include "chrome/browser/ui/extensions/shell_window.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/web_contents_observer.h"
 
@@ -24,18 +24,18 @@
 struct DraggableRegion;
 }
 
-// ShellWindowContents class specific to app windows. It maintains a
+// apps::ShellWindowContents class specific to app windows. It maintains a
 // WebContents instance and observes it for the purpose of passing
 // messages to the extensions system.
-class AppWindowContents : public ShellWindowContents,
+class AppWindowContents : public apps::ShellWindowContents,
                           public content::NotificationObserver,
                           public content::WebContentsObserver,
                           public ExtensionFunctionDispatcher::Delegate {
  public:
-  explicit AppWindowContents(ShellWindow* host);
+  explicit AppWindowContents(apps::ShellWindow* host);
   virtual ~AppWindowContents();
 
-  // ShellWindowContents
+  // apps::ShellWindowContents
   virtual void Initialize(Profile* profile, const GURL& url) OVERRIDE;
   virtual void LoadContents(int32 creator_process_id) OVERRIDE;
   virtual void NativeWindowChanged(NativeAppWindow* native_app_window) OVERRIDE;
@@ -61,7 +61,7 @@
       const std::vector<extensions::DraggableRegion>& regions);
   void SuspendRenderViewHost(content::RenderViewHost* rvh);
 
-  ShellWindow* host_;  // This class is owned by |host_|
+  apps::ShellWindow* host_;  // This class is owned by |host_|
   GURL url_;
   content::NotificationRegistrar registrar_;
   scoped_ptr<content::WebContents> web_contents_;
diff --git a/chrome/browser/extensions/background_app_browsertest.cc b/chrome/browser/extensions/background_app_browsertest.cc
new file mode 100644
index 0000000..7951e40
--- /dev/null
+++ b/chrome/browser/extensions/background_app_browsertest.cc
@@ -0,0 +1,78 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/background/background_mode_manager.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/extensions/extension_browsertest.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/test/base/ui_test_utils.h"
+
+class TestBackgroundModeManager : public BackgroundModeManager {
+ public:
+  TestBackgroundModeManager(CommandLine* command_line,
+                            ProfileInfoCache* profile_cache)
+      : BackgroundModeManager(command_line, profile_cache),
+        showed_background_app_installed_notification_for_test_(false) {}
+
+  virtual ~TestBackgroundModeManager() {}
+
+  virtual void DisplayAppInstalledNotification(
+      const extensions::Extension* extension) OVERRIDE {
+    showed_background_app_installed_notification_for_test_ = true;
+  }
+
+  bool showed_background_app_installed_notification_for_test() {
+    return showed_background_app_installed_notification_for_test_;
+  }
+
+  void set_showed_background_app_installed_notification_for_test(
+      bool showed) {
+    showed_background_app_installed_notification_for_test_ = showed;
+  }
+
+ private:
+  // Tracks if we have shown a "Background App Installed" notification to the
+  // user.  Used for unit tests only.
+  bool showed_background_app_installed_notification_for_test_;
+
+  FRIEND_TEST_ALL_PREFIXES(BackgroundAppBrowserTest,
+                           ReloadBackgroundApp);
+
+  DISALLOW_COPY_AND_ASSIGN(TestBackgroundModeManager);
+};
+
+class BackgroundAppBrowserTest: public ExtensionBrowserTest {};
+
+// Tests that if we reload a background app, we don't get a popup bubble
+// telling us that a new background app has been installed.
+IN_PROC_BROWSER_TEST_F(BackgroundAppBrowserTest, ReloadBackgroundApp) {
+
+  // Pass this in to the browser test.
+  scoped_ptr<BackgroundModeManager> test_background_mode_manager(
+      new TestBackgroundModeManager(
+          CommandLine::ForCurrentProcess(),
+          &(g_browser_process->profile_manager()->GetProfileInfoCache())));
+  g_browser_process->set_background_mode_manager_for_test(
+      test_background_mode_manager.Pass());
+  TestBackgroundModeManager* manager =
+      reinterpret_cast<TestBackgroundModeManager*>(
+          g_browser_process->background_mode_manager());
+
+  // Load our background extension
+  ASSERT_FALSE(
+      manager->showed_background_app_installed_notification_for_test());
+  const extensions::Extension* extension = LoadExtension(
+      test_data_dir_.AppendASCII("background_app"));
+  ASSERT_FALSE(extension == NULL);
+
+  // Set the test flag to not shown.
+  manager->set_showed_background_app_installed_notification_for_test(false);
+
+  // Reload our background extension
+  ReloadExtension(extension->id());
+
+  // Ensure that we did not see a "Background extension loaded" dialog.
+  EXPECT_FALSE(
+      manager->showed_background_app_installed_notification_for_test());
+}
diff --git a/chrome/browser/extensions/browser_event_router.cc b/chrome/browser/extensions/browser_event_router.cc
index d2c8b5d..3f85d96 100644
--- a/chrome/browser/extensions/browser_event_router.cc
+++ b/chrome/browser/extensions/browser_event_router.cc
@@ -165,7 +165,7 @@
                                         bool active,
                                         Profile* profile,
                                         const Extension* extension,
-                                        ListValue* event_args) {
+                                        base::ListValue* event_args) {
   DictionaryValue* tab_value = ExtensionTabUtil::CreateTabValue(
       contents, extension);
   event_args->Clear();
@@ -177,7 +177,7 @@
                                       int index,
                                       bool active) {
   Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext());
-  scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   scoped_ptr<Event> event(new Event(events::kOnTabCreated, args.Pass()));
   event->restrict_to_profile = profile;
   event->user_gesture = EventRouter::USER_GESTURE_NOT_ENABLED;
@@ -200,7 +200,7 @@
     return;
   }
 
-  scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   args->Append(Value::CreateIntegerValue(tab_id));
 
   DictionaryValue* object_args = new DictionaryValue();
@@ -221,7 +221,7 @@
     return;
   }
 
-  scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   args->Append(Value::CreateIntegerValue(ExtensionTabUtil::GetTabId(contents)));
 
   DictionaryValue* object_args = new DictionaryValue();
@@ -241,7 +241,7 @@
                                       int index) {
   int tab_id = ExtensionTabUtil::GetTabId(contents);
 
-  scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   args->Append(Value::CreateIntegerValue(tab_id));
 
   DictionaryValue* object_args = new DictionaryValue();
@@ -265,7 +265,7 @@
                                           WebContents* new_contents,
                                           int index,
                                           int reason) {
-  scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   int tab_id = ExtensionTabUtil::GetTabId(new_contents);
   args->Append(Value::CreateIntegerValue(tab_id));
 
@@ -283,9 +283,9 @@
       ? EventRouter::USER_GESTURE_ENABLED
       : EventRouter::USER_GESTURE_NOT_ENABLED;
   DispatchEvent(profile, events::kOnTabSelectionChanged,
-                scoped_ptr<ListValue>(args->DeepCopy()), gesture);
+                scoped_ptr<base::ListValue>(args->DeepCopy()), gesture);
   DispatchEvent(profile, events::kOnTabActiveChanged,
-                scoped_ptr<ListValue>(args->DeepCopy()), gesture);
+                scoped_ptr<base::ListValue>(args->DeepCopy()), gesture);
 
   // The onActivated event takes one argument: {windowId, tabId}.
   args->Remove(0, NULL);
@@ -298,7 +298,7 @@
     const ui::ListSelectionModel& old_model) {
   ui::ListSelectionModel::SelectedIndices new_selection =
       tab_strip_model->selection_model().selected_indices();
-  ListValue* all = new ListValue();
+  base::ListValue* all = new base::ListValue();
 
   for (size_t i = 0; i < new_selection.size(); ++i) {
     int index = new_selection[i];
@@ -309,7 +309,7 @@
     all->Append(Value::CreateIntegerValue(tab_id));
   }
 
-  scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   DictionaryValue* select_info = new DictionaryValue();
 
   select_info->Set(tab_keys::kWindowIdKey, Value::CreateIntegerValue(
@@ -321,7 +321,7 @@
   // The onHighlighted event replaced onHighlightChanged.
   Profile* profile = tab_strip_model->profile();
   DispatchEvent(profile, events::kOnTabHighlightChanged,
-                scoped_ptr<ListValue>(args->DeepCopy()),
+                scoped_ptr<base::ListValue>(args->DeepCopy()),
                 EventRouter::USER_GESTURE_UNKNOWN);
   DispatchEvent(profile, events::kOnTabHighlighted, args.Pass(),
                 EventRouter::USER_GESTURE_UNKNOWN);
@@ -330,7 +330,7 @@
 void BrowserEventRouter::TabMoved(WebContents* contents,
                                   int from_index,
                                   int to_index) {
-  scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   args->Append(Value::CreateIntegerValue(ExtensionTabUtil::GetTabId(contents)));
 
   DictionaryValue* object_args = new DictionaryValue();
@@ -380,7 +380,7 @@
 void BrowserEventRouter::DispatchEvent(
     Profile* profile,
     const char* event_name,
-    scoped_ptr<ListValue> args,
+    scoped_ptr<base::ListValue> args,
     EventRouter::UserGestureState user_gesture) {
   if (!profile_->IsSameProfile(profile) ||
       !extensions::ExtensionSystem::Get(profile)->event_router())
@@ -396,7 +396,7 @@
     Profile* profile,
     const std::string& extension_id,
     const char* event_name,
-    scoped_ptr<ListValue> event_args,
+    scoped_ptr<base::ListValue> event_args,
     EventRouter::UserGestureState user_gesture) {
   if (!profile_->IsSameProfile(profile) ||
       !extensions::ExtensionSystem::Get(profile)->event_router())
@@ -414,7 +414,7 @@
   if (!profile_->IsSameProfile(profile))
     return;
 
-  scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   args->Append(Value::CreateIntegerValue(window_id));
 
   DispatchEvent(profile, event_name, args.Pass(),
@@ -426,7 +426,7 @@
     const DictionaryValue* changed_properties,
     Profile* profile,
     const Extension* extension,
-    ListValue* event_args) {
+    base::ListValue* event_args) {
   // Overwrite the second argument with the appropriate properties dictionary,
   // depending on extension permissions.
   DictionaryValue* properties_value = changed_properties->DeepCopy();
@@ -447,7 +447,7 @@
 
   // The state of the tab (as seen from the extension point of view) has
   // changed.  Send a notification to the extension.
-  scoped_ptr<ListValue> args_base(new ListValue());
+  scoped_ptr<base::ListValue> args_base(new base::ListValue());
 
   // First arg: The id of the tab that changed.
   args_base->AppendInteger(ExtensionTabUtil::GetTabId(contents));
@@ -517,7 +517,7 @@
   // WebContents being swapped.
   const int new_tab_id = ExtensionTabUtil::GetTabId(new_contents);
   const int old_tab_id = ExtensionTabUtil::GetTabId(old_contents);
-  scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   args->Append(Value::CreateIntegerValue(new_tab_id));
   args->Append(Value::CreateIntegerValue(old_tab_id));
 
@@ -559,7 +559,7 @@
     int tab_id,
     const std::string& url,
     int button) {
-  scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   args->Append(Value::CreateStringValue(page_action_id));
 
   DictionaryValue* data = new DictionaryValue();
@@ -632,7 +632,7 @@
   }
 
   if (event_name) {
-    scoped_ptr<ListValue> args(new ListValue());
+    scoped_ptr<base::ListValue> args(new base::ListValue());
     DictionaryValue* tab_value = ExtensionTabUtil::CreateTabValue(
         web_contents);
     args->Append(tab_value);
diff --git a/chrome/browser/extensions/component_loader.cc b/chrome/browser/extensions/component_loader.cc
index 370ae71..b2b10b6 100644
--- a/chrome/browser/extensions/component_loader.cc
+++ b/chrome/browser/extensions/component_loader.cc
@@ -27,6 +27,7 @@
 
 #if defined(USE_AURA)
 #include "grit/keyboard_resources.h"
+#include "ui/keyboard/keyboard_util.h"
 #endif
 
 #if defined(GOOGLE_CHROME_BUILD)
@@ -289,7 +290,8 @@
 
 void ComponentLoader::AddKeyboardApp() {
 #if defined(USE_AURA)
-  Add(IDR_KEYBOARD_MANIFEST, base::FilePath(FILE_PATH_LITERAL("keyboard")));
+  if (keyboard::IsKeyboardEnabled())
+    Add(IDR_KEYBOARD_MANIFEST, base::FilePath(FILE_PATH_LITERAL("keyboard")));
 #endif
 }
 
@@ -394,9 +396,7 @@
         fileapi::FileSystemContext* context =
             content::BrowserContext::GetStoragePartitionForSite(profile, site)->
                 GetFileSystemContext();
-        fileapi::SandboxMountPointProvider* provider =
-            context->sandbox_provider();
-        provider->set_enable_temporary_file_system_in_incognito(true);
+        context->EnableTemporaryFileSystemInIncognito();
       }
     }
 #endif  // defined(GOOGLE_CHROME_BUILD)
diff --git a/chrome/browser/extensions/content_script_apitest.cc b/chrome/browser/extensions/content_script_apitest.cc
index 1bd0dce..48f6cc6 100644
--- a/chrome/browser/extensions/content_script_apitest.cc
+++ b/chrome/browser/extensions/content_script_apitest.cc
@@ -16,31 +16,32 @@
 #include "content/public/test/browser_test_utils.h"
 #include "googleurl/src/gurl.h"
 #include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
 
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptAllFrames) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionTest("content_scripts/all_frames")) << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptAboutBlankIframes) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(
       RunExtensionTest("content_scripts/about_blank_iframes")) << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptExtensionIframe) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionTest("content_scripts/extension_iframe")) << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptExtensionProcess) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(
       RunExtensionTest("content_scripts/extension_process")) << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptFragmentNavigation) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   const char* extension_name = "content_scripts/fragment";
   ASSERT_TRUE(RunExtensionTest(extension_name)) << message_;
 }
@@ -54,7 +55,7 @@
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MAYBE_ContentScriptIsolatedWorlds) {
   // This extension runs various bits of script and tests that they all run in
   // the same isolated world.
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionTest("content_scripts/isolated_world1")) << message_;
 
   // Now load a different extension, inject into same page, verify worlds aren't
@@ -65,14 +66,14 @@
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptIgnoreHostPermissions) {
   host_resolver()->AddRule("a.com", "127.0.0.1");
   host_resolver()->AddRule("b.com", "127.0.0.1");
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionTest(
       "content_scripts/dont_match_host_permissions")) << message_;
 }
 
 // crbug.com/39249 -- content scripts js should not run on view source.
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptViewSource) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionTest("content_scripts/view_source")) << message_;
 }
 
@@ -80,7 +81,7 @@
 // extensions.
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptOtherExtensions) {
   host_resolver()->AddRule("a.com", "127.0.0.1");
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   // First, load extension that sets up content script.
   ASSERT_TRUE(RunExtensionTest("content_scripts/other_extensions/injector"))
       << message_;
@@ -93,7 +94,7 @@
 IN_PROC_BROWSER_TEST_F(
     ExtensionApiTest,
     DISABLED_ContentScriptStylesInjectedIntoExistingRenderers) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   content::WindowedNotificationObserver signal(
       chrome::NOTIFICATION_USER_SCRIPTS_UPDATED,
@@ -121,25 +122,29 @@
 
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest,
                        ContentScriptCSSLocalization) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionTest("content_scripts/css_l10n")) << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptExtensionAPIs) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   const extensions::Extension* extension = LoadExtension(
       test_data_dir_.AppendASCII("content_scripts/extension_api"));
 
   ResultCatcher catcher;
   ui_test_utils::NavigateToURL(
-      browser(), test_server()->GetURL("functions.html"));
+      browser(),
+      embedded_test_server()->GetURL(
+          "/extensions/api_test/content_scripts/extension_api/functions.html"));
   EXPECT_TRUE(catcher.GetNextResult());
 
   // Navigate to a page that will cause a content script to run that starts
   // listening for an extension event.
   ui_test_utils::NavigateToURL(
-      browser(), test_server()->GetURL("events.html"));
+      browser(),
+      embedded_test_server()->GetURL(
+          "/extensions/api_test/content_scripts/extension_api/events.html"));
 
   // Navigate to an extension page that will fire the event events.js is
   // listening for.
@@ -159,11 +164,11 @@
   extensions::PermissionsRequestFunction::SetIgnoreUserGestureForTests(true);
   extensions::PermissionsRequestFunction::SetAutoConfirmForTests(true);
   host_resolver()->AddRule("*.com", "127.0.0.1");
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionTest("content_scripts/permissions")) << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptBypassPageCSP) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionTest("content_scripts/bypass_page_csp")) << message_;
 }
diff --git a/chrome/browser/extensions/content_security_policy_apitest.cc b/chrome/browser/extensions/content_security_policy_apitest.cc
index d2a4969..cbf104d 100644
--- a/chrome/browser/extensions/content_security_policy_apitest.cc
+++ b/chrome/browser/extensions/content_security_policy_apitest.cc
@@ -7,12 +7,12 @@
 #include "net/dns/mock_host_resolver.h"
 
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentSecurityPolicy) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionTest("content_security_policy")) << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, DefaultContentSecurityPolicy) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionTest("default_content_security_policy")) <<
       message_;
 }
diff --git a/chrome/browser/extensions/convert_user_script.cc b/chrome/browser/extensions/convert_user_script.cc
index 752e6a3..e823819 100644
--- a/chrome/browser/extensions/convert_user_script.cc
+++ b/chrome/browser/extensions/convert_user_script.cc
@@ -101,12 +101,12 @@
   root->SetString(keys::kPublicKey, key);
   root->SetBoolean(keys::kConvertedFromUserScript, true);
 
-  ListValue* js_files = new ListValue();
+  base::ListValue* js_files = new base::ListValue();
   js_files->Append(Value::CreateStringValue("script.js"));
 
   // If the script provides its own match patterns, we use those. Otherwise, we
   // generate some using the include globs.
-  ListValue* matches = new ListValue();
+  base::ListValue* matches = new base::ListValue();
   if (!script.url_patterns().is_empty()) {
     for (URLPatternSet::const_iterator i = script.url_patterns().begin();
          i != script.url_patterns().end(); ++i) {
@@ -119,7 +119,7 @@
   }
 
   // Read the exclude matches, if any are present.
-  ListValue* exclude_matches = new ListValue();
+  base::ListValue* exclude_matches = new base::ListValue();
   if (!script.exclude_url_patterns().is_empty()) {
     for (URLPatternSet::const_iterator i =
          script.exclude_url_patterns().begin();
@@ -128,11 +128,11 @@
     }
   }
 
-  ListValue* includes = new ListValue();
+  base::ListValue* includes = new base::ListValue();
   for (size_t i = 0; i < script.globs().size(); ++i)
     includes->Append(Value::CreateStringValue(script.globs().at(i)));
 
-  ListValue* excludes = new ListValue();
+  base::ListValue* excludes = new base::ListValue();
   for (size_t i = 0; i < script.exclude_globs().size(); ++i)
     excludes->Append(Value::CreateStringValue(script.exclude_globs().at(i)));
 
@@ -151,7 +151,7 @@
     // This is the default, but store it just in case we change that.
     content_script->SetString(keys::kRunAt, values::kRunAtDocumentIdle);
 
-  ListValue* content_scripts = new ListValue();
+  base::ListValue* content_scripts = new base::ListValue();
   content_scripts->Append(content_script);
 
   root->Set(keys::kContentScripts, content_scripts);
diff --git a/chrome/browser/extensions/convert_web_app.cc b/chrome/browser/extensions/convert_web_app.cc
index 9d61a86..e1dcf8e 100644
--- a/chrome/browser/extensions/convert_web_app.cc
+++ b/chrome/browser/extensions/convert_web_app.cc
@@ -18,7 +18,7 @@
 #include "base/path_service.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_file_util.h"
@@ -130,14 +130,14 @@
   }
 
   // Add the permissions.
-  ListValue* permissions = new ListValue();
+  base::ListValue* permissions = new base::ListValue();
   root->Set(keys::kPermissions, permissions);
   for (size_t i = 0; i < web_app.permissions.size(); ++i) {
     permissions->Append(Value::CreateStringValue(web_app.permissions[i]));
   }
 
   // Add the URLs.
-  ListValue* urls = new ListValue();
+  base::ListValue* urls = new base::ListValue();
   root->Set(keys::kWebURLs, urls);
   for (size_t i = 0; i < web_app.urls.size(); ++i) {
     urls->Append(Value::CreateStringValue(web_app.urls[i].spec()));
diff --git a/chrome/browser/extensions/convert_web_app_unittest.cc b/chrome/browser/extensions/convert_web_app_unittest.cc
index c6805be..cea76d4 100644
--- a/chrome/browser/extensions/convert_web_app_unittest.cc
+++ b/chrome/browser/extensions/convert_web_app_unittest.cc
@@ -13,7 +13,7 @@
 #include "base/path_service.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/version.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/extensions/extension.h"
diff --git a/chrome/browser/extensions/cross_origin_xhr_apitest.cc b/chrome/browser/extensions/cross_origin_xhr_apitest.cc
index 4198b7d..eae682f 100644
--- a/chrome/browser/extensions/cross_origin_xhr_apitest.cc
+++ b/chrome/browser/extensions/cross_origin_xhr_apitest.cc
@@ -7,19 +7,19 @@
 
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, CrossOriginXHRBackgroundPage) {
   host_resolver()->AddRule("*.com", "127.0.0.1");
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionTest("cross_origin_xhr/background_page")) << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, CrossOriginXHRAllURLs) {
   host_resolver()->AddRule("*.com", "127.0.0.1");
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionTest("cross_origin_xhr/all_urls")) << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, CrossOriginXHRContentScript) {
   host_resolver()->AddRule("*.com", "127.0.0.1");
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionTest("cross_origin_xhr/content_script")) << message_;
 }
 
diff --git a/chrome/browser/extensions/crx_installer.cc b/chrome/browser/extensions/crx_installer.cc
index 424ef62..4f15cb9 100644
--- a/chrome/browser/extensions/crx_installer.cc
+++ b/chrome/browser/extensions/crx_installer.cc
@@ -19,7 +19,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/sequenced_worker_pool.h"
 #include "base/threading/thread_restrictions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/version.h"
 #include "chrome/browser/extensions/convert_user_script.h"
 #include "chrome/browser/extensions/convert_web_app.h"
@@ -412,17 +412,8 @@
       Version version_required(i->minimum_version);
       const Extension* imported_module =
           service->GetExtensionById(i->extension_id, true);
-      if (!imported_module ||
-          (version_required.IsValid() &&
-           imported_module->version()->CompareTo(version_required) < 0)) {
-        ReportFailureFromUIThread(
-            CrxInstallerError(l10n_util::GetStringFUTF16(
-                IDS_EXTENSION_INSTALL_DEPENDENCY_NOT_FOUND,
-                ASCIIToUTF16(i->extension_id),
-                ASCIIToUTF16(i->minimum_version))));
-        return;
-      }
-      if (!SharedModuleInfo::IsSharedModule(imported_module)) {
+      if (imported_module &&
+          !SharedModuleInfo::IsSharedModule(imported_module)) {
         ReportFailureFromUIThread(
             CrxInstallerError(l10n_util::GetStringFUTF16(
                 IDS_EXTENSION_INSTALL_DEPENDENCY_NOT_SHARED_MODULE,
@@ -457,6 +448,11 @@
 
   string16 error = installer_.CheckManagementPolicy();
   if (!error.empty()) {
+    // We don't want to show the error infobar for installs from the WebStore,
+    // because the WebStore already shows an error dialog itself.
+    // Note: |client_| can be NULL in unit_tests!
+    if (extension()->from_webstore() && client_)
+      client_->install_ui()->SetSkipPostInstallUI(true);
     ReportFailureFromUIThread(CrxInstallerError(error));
     return;
   }
diff --git a/chrome/browser/extensions/event_listener_map.cc b/chrome/browser/extensions/event_listener_map.cc
index 5843714..2ea49e9 100644
--- a/chrome/browser/extensions/event_listener_map.cc
+++ b/chrome/browser/extensions/event_listener_map.cc
@@ -168,7 +168,7 @@
     const DictionaryValue& filtered) {
   for (DictionaryValue::Iterator it(filtered); !it.IsAtEnd(); it.Advance()) {
     // We skip entries if they are malformed.
-    const ListValue* filter_list = NULL;
+    const base::ListValue* filter_list = NULL;
     if (!it.value().GetAsList(&filter_list))
       continue;
     for (size_t i = 0; i < filter_list->GetSize(); i++) {
diff --git a/chrome/browser/extensions/event_listener_map_unittest.cc b/chrome/browser/extensions/event_listener_map_unittest.cc
index da4eb24..d1b657f 100644
--- a/chrome/browser/extensions/event_listener_map_unittest.cc
+++ b/chrome/browser/extensions/event_listener_map_unittest.cc
@@ -9,6 +9,10 @@
 #include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/test_browser_context.h"
 
+using base::DictionaryValue;
+using base::ListValue;
+using base::StringValue;
+
 namespace extensions {
 
 namespace {
diff --git a/chrome/browser/extensions/event_names.cc b/chrome/browser/extensions/event_names.cc
index deb5d58..3270043 100644
--- a/chrome/browser/extensions/event_names.cc
+++ b/chrome/browser/extensions/event_names.cc
@@ -103,6 +103,9 @@
 
 const char kOnFeedbackRequested[] = "feedbackPrivate.onFeedbackRequested";
 
+const char kDeveloperPrivateOnItemStateChanged[] =
+    "developerPrivate.onItemStateChanged";
+
 }  // namespace event_names
 
 }  // namespace extensions
diff --git a/chrome/browser/extensions/event_names.h b/chrome/browser/extensions/event_names.h
index bf81d6b..0428921 100644
--- a/chrome/browser/extensions/event_names.h
+++ b/chrome/browser/extensions/event_names.h
@@ -122,6 +122,9 @@
 // FeedbackPrivate
 extern const char kOnFeedbackRequested[];
 
+// DeveloperPrivate.
+extern const char kDeveloperPrivateOnItemStateChanged[];
+
 }  // namespace event_names
 
 }  // namespace extensions
diff --git a/chrome/browser/extensions/event_router.h b/chrome/browser/extensions/event_router.h
index ad8b72b..32a079c 100644
--- a/chrome/browser/extensions/event_router.h
+++ b/chrome/browser/extensions/event_router.h
@@ -165,7 +165,7 @@
   static void LogExtensionEventMessage(void* profile_id,
                                        const std::string& extension_id,
                                        const std::string& event_name,
-                                       scoped_ptr<ListValue> event_args);
+                                       scoped_ptr<base::ListValue> event_args);
 
   // TODO(gdk): Document this.
   static void DispatchExtensionMessage(
diff --git a/chrome/browser/extensions/event_router_forwarder.cc b/chrome/browser/extensions/event_router_forwarder.cc
index 50b0d8f..f04c16e 100644
--- a/chrome/browser/extensions/event_router_forwarder.cc
+++ b/chrome/browser/extensions/event_router_forwarder.cc
@@ -69,7 +69,7 @@
 
 void EventRouterForwarder::HandleEvent(const std::string& extension_id,
                                        const std::string& event_name,
-                                       scoped_ptr<ListValue> event_args,
+                                       scoped_ptr<base::ListValue> event_args,
                                        void* profile_ptr,
                                        bool use_profile_to_restrict_events,
                                        const GURL& event_url) {
@@ -98,7 +98,8 @@
   } else {
     std::vector<Profile*> profiles(profile_manager->GetLoadedProfiles());
     for (size_t i = 0; i < profiles.size(); ++i) {
-      scoped_ptr<ListValue> per_profile_event_args(event_args->DeepCopy());
+      scoped_ptr<base::ListValue> per_profile_event_args(
+          event_args->DeepCopy());
       CallEventRouter(
           profiles[i], extension_id, event_name, per_profile_event_args.Pass(),
           use_profile_to_restrict_events ? profiles[i] : NULL, event_url);
@@ -106,12 +107,13 @@
   }
 }
 
-void EventRouterForwarder::CallEventRouter(Profile* profile,
-                                           const std::string& extension_id,
-                                           const std::string& event_name,
-                                           scoped_ptr<ListValue> event_args,
-                                           Profile* restrict_to_profile,
-                                           const GURL& event_url) {
+void EventRouterForwarder::CallEventRouter(
+    Profile* profile,
+    const std::string& extension_id,
+    const std::string& event_name,
+    scoped_ptr<base::ListValue> event_args,
+    Profile* restrict_to_profile,
+    const GURL& event_url) {
   // We may not have an extension in cases like chromeos login
   // (crosbug.com/12856), chrome_frame_net_tests.exe which reuses the chrome
   // browser single process framework.
diff --git a/chrome/browser/extensions/event_router_forwarder_unittest.cc b/chrome/browser/extensions/event_router_forwarder_unittest.cc
index ee2bf3e..c3c1056 100644
--- a/chrome/browser/extensions/event_router_forwarder_unittest.cc
+++ b/chrome/browser/extensions/event_router_forwarder_unittest.cc
@@ -47,7 +47,7 @@
 static void BroadcastEventToRenderers(EventRouterForwarder* event_router,
                                       const std::string& event_name,
                                       const GURL& url) {
-  scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   event_router->BroadcastEventToRenderers(event_name, args.Pass(), url);
 }
 
@@ -56,7 +56,7 @@
                                      void* profile,
                                      bool use_profile_to_restrict_events,
                                      const GURL& url) {
-  scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   event_router->DispatchEventToRenderers(event_name, args.Pass(), profile,
                                          use_profile_to_restrict_events, url);
 }
@@ -65,7 +65,7 @@
                                       const std::string& extension,
                                       const std::string& event_name,
                                       const GURL& url) {
-  scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   event_router->BroadcastEventToExtension(extension, event_name, args.Pass(),
                                           url);
 }
@@ -76,7 +76,7 @@
                                      void* profile,
                                      bool use_profile_to_restrict_events,
                                      const GURL& url) {
-  scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   event_router->DispatchEventToExtension(
       extension, event_name, args.Pass(), profile,
       use_profile_to_restrict_events, url);
diff --git a/chrome/browser/extensions/execute_script_apitest.cc b/chrome/browser/extensions/execute_script_apitest.cc
index c2d96d7..f28ba8c 100644
--- a/chrome/browser/extensions/execute_script_apitest.cc
+++ b/chrome/browser/extensions/execute_script_apitest.cc
@@ -18,14 +18,14 @@
 // If failing, mark disabled and update http://crbug.com/92105.
 IN_PROC_BROWSER_TEST_F(ExecuteScriptApiTest, ExecuteScriptBasic) {
   SetupDelayedHostResolver();
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionTest("executescript/basic")) << message_;
 }
 
 // If failing, mark disabled and update http://crbug.com/92105.
 IN_PROC_BROWSER_TEST_F(ExecuteScriptApiTest, ExecuteScriptInFrame) {
   SetupDelayedHostResolver();
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionTest("executescript/in_frame")) << message_;
 }
 
@@ -39,20 +39,20 @@
 
 IN_PROC_BROWSER_TEST_F(ExecuteScriptApiTest, MAYBE_ExecuteScriptPermissions) {
   SetupDelayedHostResolver();
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionTest("executescript/permissions")) << message_;
 }
 
 // If failing, mark disabled and update http://crbug.com/84760.
 IN_PROC_BROWSER_TEST_F(ExecuteScriptApiTest, ExecuteScriptFileAfterClose) {
   host_resolver()->AddRule("b.com", "127.0.0.1");
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionTest("executescript/file_after_close")) << message_;
 }
 
 // If crashing, mark disabled and update http://crbug.com/67774.
 IN_PROC_BROWSER_TEST_F(ExecuteScriptApiTest, ExecuteScriptFragmentNavigation) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   const char* extension_name = "executescript/fragment";
   ASSERT_TRUE(RunExtensionTest(extension_name)) << message_;
 }
@@ -67,7 +67,7 @@
                        MAYBE_NavigationRaceExecuteScript) {
   host_resolver()->AddRule("a.com", "127.0.0.1");
   host_resolver()->AddRule("b.com", "127.0.0.1");
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionSubtest("executescript/navigation_race",
                                   "execute_script.html")) << message_;
 }
@@ -75,7 +75,7 @@
 IN_PROC_BROWSER_TEST_F(ExecuteScriptApiTest, NavigationRaceJavaScriptURL) {
   host_resolver()->AddRule("a.com", "127.0.0.1");
   host_resolver()->AddRule("b.com", "127.0.0.1");
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionSubtest("executescript/navigation_race",
                                   "javascript_url.html")) << message_;
 }
@@ -83,18 +83,18 @@
 // If failing, mark disabled and update http://crbug.com/92105.
 IN_PROC_BROWSER_TEST_F(ExecuteScriptApiTest, ExecuteScriptFrameAfterLoad) {
   SetupDelayedHostResolver();
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionTest("executescript/frame_after_load")) << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(ExecuteScriptApiTest, ExecuteScriptRunAt) {
   SetupDelayedHostResolver();
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionTest("executescript/run_at")) << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(ExecuteScriptApiTest, ExecuteScriptCallback) {
   SetupDelayedHostResolver();
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionTest("executescript/callback")) << message_;
 }
diff --git a/chrome/browser/extensions/extension_apitest.cc b/chrome/browser/extensions/extension_apitest.cc
index c14182b..ed6d644 100644
--- a/chrome/browser/extensions/extension_apitest.cc
+++ b/chrome/browser/extensions/extension_apitest.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/extensions/extension_apitest.h"
 
+#include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "chrome/browser/extensions/api/test/test_api.h"
@@ -18,7 +19,11 @@
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/notification_registrar.h"
 #include "content/public/browser/notification_service.h"
+#include "net/base/escape.h"
 #include "net/base/net_util.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "net/test/embedded_test_server/http_response.h"
+#include "net/test/embedded_test_server/http_request.h"
 #include "net/test/spawned_test_server/spawned_test_server.h"
 
 namespace {
@@ -28,9 +33,108 @@
 const char kTestDataDirectory[] = "testDataDirectory";
 const char kTestWebSocketPort[] = "testWebSocketPort";
 
+scoped_ptr<net::test_server::HttpResponse> HandleServerRedirectRequest(
+    const net::test_server::HttpRequest& request) {
+  if (!StartsWithASCII(request.relative_url, "/server-redirect?", true))
+    return scoped_ptr<net::test_server::HttpResponse>();
+
+  size_t query_string_pos = request.relative_url.find('?');
+  std::string redirect_target =
+      request.relative_url.substr(query_string_pos + 1);
+
+  scoped_ptr<net::test_server::BasicHttpResponse> http_response(
+      new net::test_server::BasicHttpResponse);
+  http_response->set_code(net::HTTP_MOVED_PERMANENTLY);
+  http_response->AddCustomHeader("Location", redirect_target);
+  return http_response.PassAs<net::test_server::HttpResponse>();
+}
+
+scoped_ptr<net::test_server::HttpResponse> HandleEchoHeaderRequest(
+    const net::test_server::HttpRequest& request) {
+  if (!StartsWithASCII(request.relative_url, "/echoheader?", true))
+    return scoped_ptr<net::test_server::HttpResponse>();
+
+  size_t query_string_pos = request.relative_url.find('?');
+  std::string header_name =
+      request.relative_url.substr(query_string_pos + 1);
+
+  std::string header_value;
+  std::map<std::string, std::string>::const_iterator it = request.headers.find(
+      header_name);
+  if (it != request.headers.end())
+    header_value = it->second;
+
+  scoped_ptr<net::test_server::BasicHttpResponse> http_response(
+      new net::test_server::BasicHttpResponse);
+  http_response->set_code(net::HTTP_OK);
+  http_response->set_content(header_value);
+  return http_response.PassAs<net::test_server::HttpResponse>();
+}
+
+scoped_ptr<net::test_server::HttpResponse> HandleSetCookieRequest(
+    const net::test_server::HttpRequest& request) {
+  if (!StartsWithASCII(request.relative_url, "/set-cookie?", true))
+    return scoped_ptr<net::test_server::HttpResponse>();
+
+  scoped_ptr<net::test_server::BasicHttpResponse> http_response(
+      new net::test_server::BasicHttpResponse);
+  http_response->set_code(net::HTTP_OK);
+
+  size_t query_string_pos = request.relative_url.find('?');
+  std::string cookie_value =
+      request.relative_url.substr(query_string_pos + 1);
+
+  std::vector<std::string> cookies;
+  base::SplitString(cookie_value, '&', &cookies);
+
+  for (size_t i = 0; i < cookies.size(); i++)
+    http_response->AddCustomHeader("Set-Cookie", cookies[i]);
+
+  return http_response.PassAs<net::test_server::HttpResponse>();
+}
+
+scoped_ptr<net::test_server::HttpResponse> HandleSetHeaderRequest(
+    const net::test_server::HttpRequest& request) {
+  if (!StartsWithASCII(request.relative_url, "/set-header?", true))
+    return scoped_ptr<net::test_server::HttpResponse>();
+
+  size_t query_string_pos = request.relative_url.find('?');
+  std::string escaped_header =
+      request.relative_url.substr(query_string_pos + 1);
+
+  std::string header =
+      net::UnescapeURLComponent(escaped_header,
+                                net::UnescapeRule::NORMAL |
+                                net::UnescapeRule::SPACES |
+                                net::UnescapeRule::URL_SPECIAL_CHARS);
+
+  size_t colon_pos = header.find(':');
+  if (colon_pos == std::string::npos)
+    return scoped_ptr<net::test_server::HttpResponse>();
+
+  std::string header_name = header.substr(0, colon_pos);
+  // Skip space after colon.
+  std::string header_value = header.substr(colon_pos + 2);
+
+  scoped_ptr<net::test_server::BasicHttpResponse> http_response(
+      new net::test_server::BasicHttpResponse);
+  http_response->set_code(net::HTTP_OK);
+  http_response->AddCustomHeader(header_name, header_value);
+  return http_response.PassAs<net::test_server::HttpResponse>();
+}
+
 };  // namespace
 
-ExtensionApiTest::ExtensionApiTest() {}
+ExtensionApiTest::ExtensionApiTest() {
+  embedded_test_server()->RegisterRequestHandler(
+      base::Bind(&HandleServerRedirectRequest));
+  embedded_test_server()->RegisterRequestHandler(
+      base::Bind(&HandleEchoHeaderRequest));
+  embedded_test_server()->RegisterRequestHandler(
+      base::Bind(&HandleSetCookieRequest));
+  embedded_test_server()->RegisterRequestHandler(
+      base::Bind(&HandleSetHeaderRequest));
+}
 
 ExtensionApiTest::~ExtensionApiTest() {}
 
@@ -305,15 +409,15 @@
   return extension;
 }
 
-bool ExtensionApiTest::StartTestServer() {
-  if (!test_server()->Start())
+bool ExtensionApiTest::StartEmbeddedTestServer() {
+  if (!embedded_test_server()->InitializeAndWaitUntilReady())
     return false;
 
   // Build a dictionary of values that tests can use to build URLs that
   // access the test server and local file system.  Tests can see these values
   // using the extension API function chrome.test.getConfig().
   test_config_->SetInteger(kTestServerPort,
-                           test_server()->host_port_pair().port());
+                           embedded_test_server()->port());
 
   return true;
 }
diff --git a/chrome/browser/extensions/extension_apitest.h b/chrome/browser/extensions/extension_apitest.h
index 9d6cf0c..12827ad 100644
--- a/chrome/browser/extensions/extension_apitest.h
+++ b/chrome/browser/extensions/extension_apitest.h
@@ -158,7 +158,7 @@
 
   // Start the test server, and store details of its state.  Those details
   // will be available to javascript tests using chrome.test.getConfig().
-  bool StartTestServer();
+  bool StartEmbeddedTestServer();
 
   // Start the test WebSocket server, and store details of its state. Those
   // details will be available to javascript tests using
diff --git a/chrome/browser/extensions/extension_browsertest.cc b/chrome/browser/extensions/extension_browsertest.cc
index c2ec75b..07fb324 100644
--- a/chrome/browser/extensions/extension_browsertest.cc
+++ b/chrome/browser/extensions/extension_browsertest.cc
@@ -239,7 +239,7 @@
 base::FilePath ExtensionBrowserTest::PackExtension(
     const base::FilePath& dir_path) {
   base::FilePath crx_path = temp_dir_.path().AppendASCII("temp.crx");
-  if (!file_util::Delete(crx_path, false)) {
+  if (!base::Delete(crx_path, false)) {
     ADD_FAILURE() << "Failed to delete crx: " << crx_path.value();
     return base::FilePath();
   }
@@ -252,7 +252,7 @@
   if (!file_util::PathExists(pem_path)) {
     pem_path = base::FilePath();
     pem_path_out = crx_path.DirName().AppendASCII("temp.pem");
-    if (!file_util::Delete(pem_path_out, false)) {
+    if (!base::Delete(pem_path_out, false)) {
       ADD_FAILURE() << "Failed to delete pem: " << pem_path_out.value();
       return base::FilePath();
     }
@@ -452,7 +452,7 @@
   return service->GetExtensionById(last_loaded_extension_id_, false);
 }
 
-void ExtensionBrowserTest::ReloadExtension(const std::string& extension_id) {
+void ExtensionBrowserTest::ReloadExtension(const std::string extension_id) {
   ExtensionService* service = extensions::ExtensionSystem::Get(
       profile())->extension_service();
   service->ReloadExtension(extension_id);
diff --git a/chrome/browser/extensions/extension_browsertest.h b/chrome/browser/extensions/extension_browsertest.h
index ef2b4c8..2b750c3 100644
--- a/chrome/browser/extensions/extension_browsertest.h
+++ b/chrome/browser/extensions/extension_browsertest.h
@@ -170,7 +170,7 @@
         std::string(), path, INSTALL_UI_TYPE_CANCEL, 0);
   }
 
-  void ReloadExtension(const std::string& extension_id);
+  void ReloadExtension(const std::string extension_id);
 
   void UnloadExtension(const std::string& extension_id);
 
diff --git a/chrome/browser/extensions/extension_context_menu_model_unittest.cc b/chrome/browser/extensions/extension_context_menu_model_unittest.cc
index 9aa6929..6abe35c 100644
--- a/chrome/browser/extensions/extension_context_menu_model_unittest.cc
+++ b/chrome/browser/extensions/extension_context_menu_model_unittest.cc
@@ -39,8 +39,7 @@
   service_->AddExtension(extension.get());
 
   // Create a Browser for the ExtensionContextMenuModel to use.
-  Browser::CreateParams params(profile_.get(),
-                               chrome::HOST_DESKTOP_TYPE_NATIVE);
+  Browser::CreateParams params(profile_.get(), chrome::GetActiveDesktop());
   TestBrowserWindow test_window;
   params.window = &test_window;
   Browser browser(params);
diff --git a/chrome/browser/extensions/extension_creator.cc b/chrome/browser/extensions/extension_creator.cc
index 8aa0301..cedc048 100644
--- a/chrome/browser/extensions/extension_creator.cc
+++ b/chrome/browser/extensions/extension_creator.cc
@@ -237,7 +237,7 @@
                                 const std::vector<uint8>& signature,
                                 const base::FilePath& crx_path) {
   if (file_util::PathExists(crx_path))
-    file_util::Delete(crx_path, false);
+    base::Delete(crx_path, false);
   ScopedStdioHandle crx_handle(file_util::OpenFile(crx_path, "wb"));
   if (!crx_handle.get()) {
     error_message_ = l10n_util::GetStringUTF8(IDS_EXTENSION_SHARING_VIOLATION);
@@ -322,7 +322,7 @@
     result = true;
   }
 
-  file_util::Delete(zip_path, false);
+  base::Delete(zip_path, false);
   return result;
 }
 
diff --git a/chrome/browser/extensions/extension_creator_filter_unittest.cc b/chrome/browser/extensions/extension_creator_filter_unittest.cc
index 45e9941..48f5806 100644
--- a/chrome/browser/extensions/extension_creator_filter_unittest.cc
+++ b/chrome/browser/extensions/extension_creator_filter_unittest.cc
@@ -26,7 +26,7 @@
     base::FilePath test_file(test_dir_.Append(file_path));
     base::FilePath temp_file;
     EXPECT_TRUE(file_util::CreateTemporaryFileInDir(test_dir_, &temp_file));
-    EXPECT_TRUE(file_util::Move(temp_file, test_file));
+    EXPECT_TRUE(base::Move(temp_file, test_file));
     return test_file;
   }
 
diff --git a/chrome/browser/extensions/extension_dom_clipboard_apitest.cc b/chrome/browser/extensions/extension_dom_clipboard_apitest.cc
index 0d63acb..0d2e6a1 100644
--- a/chrome/browser/extensions/extension_dom_clipboard_apitest.cc
+++ b/chrome/browser/extensions/extension_dom_clipboard_apitest.cc
@@ -11,6 +11,7 @@
 #include "content/public/test/browser_test_utils.h"
 #include "googleurl/src/gurl.h"
 #include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
 
 namespace {
 
@@ -29,7 +30,7 @@
                                      const std::string& launch_page) {
   host_resolver()->AddRule("*", "127.0.0.1");
 
-  if (!StartTestServer()) {
+  if (!StartEmbeddedTestServer()) {
     message_ = "Failed to start test server.";
     return false;
   }
@@ -40,7 +41,8 @@
     return false;
   }
 
-  GURL base_url = test_server()->GetURL("files/extensions/api_test/clipboard/");
+  GURL base_url = embedded_test_server()->GetURL(
+      "/extensions/api_test/clipboard/");
   GURL::Replacements replace_host;
   std::string host_str("localhost");  // Must stay in scope with replace_host.
   replace_host.SetHostStr(host_str);
@@ -80,12 +82,12 @@
 }  // namespace
 
 IN_PROC_BROWSER_TEST_F(ClipboardApiTest, Extension) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionTest("clipboard/extension")) << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(ClipboardApiTest, ExtensionNoPermission) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionTest("clipboard/extension_no_permission"))
       << message_;
 }
diff --git a/chrome/browser/extensions/extension_function.cc b/chrome/browser/extensions/extension_function.cc
index 484abd7..3e6a397 100644
--- a/chrome/browser/extensions/extension_function.cc
+++ b/chrome/browser/extensions/extension_function.cc
@@ -88,7 +88,7 @@
   results_->Append(result);
 }
 
-const ListValue* ExtensionFunction::GetResultList() {
+const base::ListValue* ExtensionFunction::GetResultList() {
   return results_.get();
 }
 
@@ -128,7 +128,7 @@
 
   // If results were never set, we send an empty argument list.
   if (!results_)
-    results_.reset(new ListValue());
+    results_.reset(new base::ListValue());
 
   response_callback_.Run(type, *results_, GetError());
 }
diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc
index a7ff244..daa25d2 100644
--- a/chrome/browser/extensions/extension_function_dispatcher.cc
+++ b/chrome/browser/extensions/extension_function_dispatcher.cc
@@ -48,7 +48,7 @@
 
 void LogSuccess(const std::string& extension_id,
                 const std::string& api_name,
-                scoped_ptr<ListValue> args,
+                scoped_ptr<base::ListValue> args,
                 Profile* profile) {
   // The ActivityLog can only be accessed from the main (UI) thread.  If we're
   // running on the wrong thread, re-dispatch from the main thread.
@@ -70,7 +70,7 @@
 
 void LogFailure(const std::string& extension_id,
                 const std::string& api_name,
-                scoped_ptr<ListValue> args,
+                scoped_ptr<base::ListValue> args,
                 extensions::BlockedAction::Reason reason,
                 Profile* profile) {
   // The ActivityLog can only be accessed from the main (UI) thread.  If we're
@@ -226,6 +226,11 @@
   return NULL;
 }
 
+content::WebContents*
+ExtensionFunctionDispatcher::Delegate::GetVisibleWebContents() const {
+  return GetAssociatedWebContents();
+}
+
 void ExtensionFunctionDispatcher::GetAllFunctionNames(
     std::vector<std::string>* names) {
   ExtensionFunctionRegistry::GetInstance()->GetAllNames(names);
diff --git a/chrome/browser/extensions/extension_function_dispatcher.h b/chrome/browser/extensions/extension_function_dispatcher.h
index b6cebd6..85f15ef 100644
--- a/chrome/browser/extensions/extension_function_dispatcher.h
+++ b/chrome/browser/extensions/extension_function_dispatcher.h
@@ -57,11 +57,16 @@
     virtual extensions::WindowController* GetExtensionWindowController() const;
 
     // Asks the delegate for any relevant WebContents associated with this
-    // context. For example, the WebbContents in which an infobar or
+    // context. For example, the WebContents in which an infobar or
     // chrome-extension://<id> URL are being shown. Callers must check for a
     // NULL return value (as in the case of a background page).
     virtual content::WebContents* GetAssociatedWebContents() const;
 
+    // If the associated web contents is not null, returns that. Otherwise,
+    // returns the next most relevant visible web contents. Callers must check
+    // for a NULL return value (as in the case of a background page).
+    virtual content::WebContents* GetVisibleWebContents() const;
+
    protected:
     virtual ~Delegate() {}
   };
diff --git a/chrome/browser/extensions/extension_function_histogram_value.h b/chrome/browser/extensions/extension_function_histogram_value.h
index 6b1a5d4..9a8ef6d 100644
--- a/chrome/browser/extensions/extension_function_histogram_value.h
+++ b/chrome/browser/extensions/extension_function_histogram_value.h
@@ -484,7 +484,7 @@
   DEVELOPERPRIVATE_RESTART,
   DEVELOPERPRIVATE_ALLOWINCOGNITO,
   INPUT_IME_DELETESURROUNDINGTEXT,
-  FILEBROWSERPRIVATE_OPENNEWWINDOW,
+  DELETED_FILEBROWSERPRIVATE_OPENNEWWINDOW,
   CLOUDPRINTPRIVATE_GETCLIENTID,
   ECHOPRIVATE_GETUSERCONSENT,
   SYNCFILESYSTEM_SETCONFLICTRESOLUTIONPOLICY,
@@ -552,6 +552,12 @@
   FEEDBACKPRIVATE_GETUSEREMAIL,
   FEEDBACKPRIVATE_GETSYSTEMINFORMATION,
   FEEDBACKPRIVATE_SENDFEEDBACK,
+  EXPERIMENTAL_INPUT_VIRTUALKEYBOARD_INSERTTEXT,
+  DIAGNOSTICS_SENDPACKET,
+  METRICSPRIVATE_GETFIELDTRIAL,
+  FILEBROWSERPRIVATE_ZOOM,
+  WEBVIEW_GO,
+  WEBSTOREPRIVATE_ISININCOGNITOMODEFUNCTION,
   ENUM_BOUNDARY // Last entry: Add new entries above.
 };
 
diff --git a/chrome/browser/extensions/extension_function_registry.cc b/chrome/browser/extensions/extension_function_registry.cc
index 23d3a70..c6b3d4d 100644
--- a/chrome/browser/extensions/extension_function_registry.cc
+++ b/chrome/browser/extensions/extension_function_registry.cc
@@ -73,6 +73,7 @@
   RegisterFunction<extensions::EnableAppLauncherFunction>();
   RegisterFunction<extensions::GetWebGLStatusFunction>();
   RegisterFunction<extensions::GetIsLauncherEnabledFunction>();
+  RegisterFunction<extensions::IsInIncognitoModeFunction>();
 
   // Runtime
   RegisterFunction<extensions::RuntimeGetBackgroundPageFunction>();
diff --git a/chrome/browser/extensions/extension_host.cc b/chrome/browser/extensions/extension_host.cc
index 74c14f6..5668535 100644
--- a/chrome/browser/extensions/extension_host.cc
+++ b/chrome/browser/extensions/extension_host.cc
@@ -55,6 +55,10 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
 
+#if !defined(OS_ANDROID)
+#include "components/web_modal/web_contents_modal_dialog_manager.h"
+#endif
+
 using WebKit::WebDragOperation;
 using WebKit::WebDragOperationsMask;
 using content::NativeWebKeyboardEvent;
@@ -191,6 +195,15 @@
   return associated_web_contents_;
 }
 
+WebContents* ExtensionHost::GetVisibleWebContents() const {
+  if (associated_web_contents_)
+    return associated_web_contents_;
+  if ((extension_host_type_ == VIEW_TYPE_EXTENSION_POPUP) ||
+      (extension_host_type_ == VIEW_TYPE_PANEL))
+    return host_contents_.get();
+  return NULL;
+}
+
 void ExtensionHost::SetAssociatedWebContents(
     content::WebContents* web_contents) {
   associated_web_contents_ = web_contents;
@@ -252,6 +265,16 @@
     return;
   }
 
+#if !defined(OS_ANDROID)
+  if ((extension_host_type_ == VIEW_TYPE_EXTENSION_POPUP) ||
+      (extension_host_type_ == VIEW_TYPE_PANEL)) {
+    web_modal::WebContentsModalDialogManager::CreateForWebContents(
+        host_contents_.get());
+    web_modal::WebContentsModalDialogManager::FromWebContents(
+        host_contents_.get())->set_delegate(this);
+  }
+#endif
+
   host_contents_->GetController().LoadURL(
       initial_url_, content::Referrer(), content::PAGE_TRANSITION_LINK,
       std::string());
diff --git a/chrome/browser/extensions/extension_host.h b/chrome/browser/extensions/extension_host.h
index 9433037..b9a9972 100644
--- a/chrome/browser/extensions/extension_host.h
+++ b/chrome/browser/extensions/extension_host.h
@@ -29,6 +29,10 @@
 #include "chrome/browser/ui/android/extensions/extension_view_android.h"
 #endif
 
+#if !defined(OS_ANDROID)
+#include "chrome/browser/ui/chrome_web_modal_dialog_manager_delegate.h"
+#endif
+
 class Browser;
 class PrefsTabHelper;
 
@@ -47,6 +51,9 @@
 // privileges available to extensions.  It may have a view to be shown in the
 // browser UI, or it may be hidden.
 class ExtensionHost : public content::WebContentsDelegate,
+#if !defined(OS_ANDROID)
+                      public ChromeWebModalDialogManagerDelegate,
+#endif
                       public content::WebContentsObserver,
                       public ExtensionFunctionDispatcher::Delegate,
                       public content::NotificationObserver {
@@ -110,6 +117,7 @@
 
   // ExtensionFunctionDispatcher::Delegate
   virtual content::WebContents* GetAssociatedWebContents() const OVERRIDE;
+  virtual content::WebContents* GetVisibleWebContents() const OVERRIDE;
   void SetAssociatedWebContents(content::WebContents* web_contents);
 
   // Returns true if the render view is initialized and didn't crash.
diff --git a/chrome/browser/extensions/extension_incognito_apitest.cc b/chrome/browser/extensions/extension_incognito_apitest.cc
index dbf7033..c122733 100644
--- a/chrome/browser/extensions/extension_incognito_apitest.cc
+++ b/chrome/browser/extensions/extension_incognito_apitest.cc
@@ -16,11 +16,12 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test_utils.h"
 #include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
 
 using content::WebContents;
 
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, IncognitoNoScript) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   // Loads a simple extension which attempts to change the title of every page
   // that loads to "modified".
@@ -30,7 +31,7 @@
   // Open incognito window and navigate to test page.
   Browser* otr_browser = ui_test_utils::OpenURLOffTheRecord(
       browser()->profile(),
-      test_server()->GetURL("files/extensions/test_file.html"));
+      embedded_test_server()->GetURL("/extensions/test_file.html"));
 
   WebContents* tab = otr_browser->tab_strip_model()->GetActiveWebContents();
 
@@ -52,7 +53,7 @@
 
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MAYBE_IncognitoYesScript) {
   host_resolver()->AddRule("*", "127.0.0.1");
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   // Load a dummy extension. This just tests that we don't regress a
   // crash fix when multiple incognito- and non-incognito-enabled extensions
@@ -72,7 +73,7 @@
   // Open incognito window and navigate to test page.
   Browser* otr_browser = ui_test_utils::OpenURLOffTheRecord(
       browser()->profile(),
-      test_server()->GetURL("files/extensions/test_file.html"));
+      embedded_test_server()->GetURL("/extensions/test_file.html"));
 
   WebContents* tab = otr_browser->tab_strip_model()->GetActiveWebContents();
 
@@ -102,14 +103,14 @@
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Incognito) {
 #endif
   host_resolver()->AddRule("*", "127.0.0.1");
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   ResultCatcher catcher;
 
   // Open incognito window and navigate to test page.
   ui_test_utils::OpenURLOffTheRecord(
       browser()->profile(),
-      test_server()->GetURL("files/extensions/test_file.html"));
+      embedded_test_server()->GetURL("/extensions/test_file.html"));
 
   ASSERT_TRUE(LoadExtensionIncognito(test_data_dir_
       .AppendASCII("incognito").AppendASCII("apis")));
@@ -126,7 +127,7 @@
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, IncognitoSplitMode) {
 #endif
   host_resolver()->AddRule("*", "127.0.0.1");
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   // We need 2 ResultCatchers because we'll be running the same test in both
   // regular and incognito mode.
@@ -142,7 +143,7 @@
   // Open incognito window and navigate to test page.
   ui_test_utils::OpenURLOffTheRecord(
       browser()->profile(),
-      test_server()->GetURL("files/extensions/test_file.html"));
+      embedded_test_server()->GetURL("/extensions/test_file.html"));
 
   ASSERT_TRUE(LoadExtensionIncognito(test_data_dir_
       .AppendASCII("incognito").AppendASCII("split")));
@@ -166,14 +167,14 @@
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, IncognitoDisabled) {
 #endif
   host_resolver()->AddRule("*", "127.0.0.1");
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   ResultCatcher catcher;
 
   // Open incognito window and navigate to test page.
   ui_test_utils::OpenURLOffTheRecord(
       browser()->profile(),
-      test_server()->GetURL("files/extensions/test_file.html"));
+      embedded_test_server()->GetURL("/extensions/test_file.html"));
 
   ASSERT_TRUE(LoadExtension(test_data_dir_
       .AppendASCII("incognito").AppendASCII("apis_disabled")));
@@ -190,7 +191,7 @@
 // Test that opening a popup from an incognito browser window works properly.
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MAYBE_IncognitoPopup) {
   host_resolver()->AddRule("*", "127.0.0.1");
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   ResultCatcher catcher;
 
@@ -200,7 +201,7 @@
   // Open incognito window and navigate to test page.
   Browser* incognito_browser = ui_test_utils::OpenURLOffTheRecord(
       browser()->profile(),
-      test_server()->GetURL("files/extensions/test_file.html"));
+      embedded_test_server()->GetURL("/extensions/test_file.html"));
 
   // Simulate the incognito's browser action being clicked.
   BrowserActionTestUtil(incognito_browser).Press(0);
diff --git a/chrome/browser/extensions/extension_info_map.h b/chrome/browser/extensions/extension_info_map.h
index a5f1b14..cfbf6c6 100644
--- a/chrome/browser/extensions/extension_info_map.h
+++ b/chrome/browser/extensions/extension_info_map.h
@@ -8,9 +8,9 @@
 #include <string>
 
 #include "base/basictypes.h"
-#include "base/time.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/time/time.h"
 #include "chrome/browser/extensions/extensions_quota_service.h"
 #include "chrome/browser/extensions/process_map.h"
 #include "chrome/common/extensions/extension_constants.h"
diff --git a/chrome/browser/extensions/extension_javascript_url_apitest.cc b/chrome/browser/extensions/extension_javascript_url_apitest.cc
index 4076c14..9e7fca1 100644
--- a/chrome/browser/extensions/extension_javascript_url_apitest.cc
+++ b/chrome/browser/extensions/extension_javascript_url_apitest.cc
@@ -9,7 +9,7 @@
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, JavaScriptURLPermissions) {
   host_resolver()->AddRule("a.com", "127.0.0.1");
   host_resolver()->AddRule("b.com", "127.0.0.1");
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   ASSERT_TRUE(RunExtensionTest("tabs/javascript_url_permissions")) << message_;
 }
diff --git a/chrome/browser/extensions/extension_keybinding_registry.cc b/chrome/browser/extensions/extension_keybinding_registry.cc
index e5cf544..9cc3cfb 100644
--- a/chrome/browser/extensions/extension_keybinding_registry.cc
+++ b/chrome/browser/extensions/extension_keybinding_registry.cc
@@ -70,7 +70,7 @@
   if (granter)
     granter->GrantIfRequested(extension);
 
-  scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
   args->Append(Value::CreateStringValue(command));
 
   scoped_ptr<Event> event(new Event("commands.onCommand", args.Pass()));
diff --git a/chrome/browser/extensions/extension_messages_apitest.cc b/chrome/browser/extensions/extension_messages_apitest.cc
index e2a605c..2b9d995 100644
--- a/chrome/browser/extensions/extension_messages_apitest.cc
+++ b/chrome/browser/extensions/extension_messages_apitest.cc
@@ -36,18 +36,19 @@
   }
 
  private:
-  static scoped_ptr<ListValue> BuildEventArguments(const bool last_message,
-                                                   const std::string& data) {
+  static scoped_ptr<base::ListValue> BuildEventArguments(
+      const bool last_message,
+      const std::string& data) {
     DictionaryValue* event = new DictionaryValue();
     event->SetBoolean("lastMessage", last_message);
     event->SetString("data", data);
-    scoped_ptr<ListValue> arguments(new ListValue());
+    scoped_ptr<base::ListValue> arguments(new base::ListValue());
     arguments->Append(event);
     return arguments.Pass();
   }
 
   static scoped_ptr<extensions::Event> BuildEvent(
-      scoped_ptr<ListValue> event_args,
+      scoped_ptr<base::ListValue> event_args,
       Profile* profile,
       GURL event_url) {
     scoped_ptr<extensions::Event> event(new extensions::Event(
@@ -91,7 +92,7 @@
 
 // Tests that message passing between extensions and content scripts works.
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Messaging) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionTest("messaging/connect")) << message_;
 }
 
@@ -174,6 +175,7 @@
         "onConnectExternal",
         "onMessage",
         "onMessageExternal",
+        "onRestartRequired",
         "id",
     };
 
diff --git a/chrome/browser/extensions/extension_override_apitest.cc b/chrome/browser/extensions/extension_override_apitest.cc
index d0989a6..dcaa3cd 100644
--- a/chrome/browser/extensions/extension_override_apitest.cc
+++ b/chrome/browser/extensions/extension_override_apitest.cc
@@ -27,7 +27,7 @@
         browser()->profile()->GetPrefs()->GetDictionary(
             ExtensionWebUI::kExtensionURLOverrides);
 
-    const ListValue* values = NULL;
+    const base::ListValue* values = NULL;
     if (!overrides->GetList("history", &values))
       return false;
 
@@ -125,7 +125,7 @@
   // a preferences file without corresponding UnloadExtension() calls. This is
   // the same as the above test, except for that it is testing the case where
   // the file already contains dupes when an extension is loaded.
-  ListValue* list = new ListValue();
+  base::ListValue* list = new base::ListValue();
   for (size_t i = 0; i < 3; ++i)
     list->Append(Value::CreateStringValue("http://www.google.com/"));
 
diff --git a/chrome/browser/extensions/extension_pref_value_map.h b/chrome/browser/extensions/extension_pref_value_map.h
index a0120f9..9f8e3b2 100644
--- a/chrome/browser/extensions/extension_pref_value_map.h
+++ b/chrome/browser/extensions/extension_pref_value_map.h
@@ -11,7 +11,7 @@
 
 #include "base/observer_list.h"
 #include "base/prefs/pref_value_map.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
 #include "extensions/browser/extension_prefs_scope.h"
diff --git a/chrome/browser/extensions/extension_prefs.cc b/chrome/browser/extensions/extension_prefs.cc
index c7f5bbf..5dea347 100644
--- a/chrome/browser/extensions/extension_prefs.cc
+++ b/chrome/browser/extensions/extension_prefs.cc
@@ -121,6 +121,9 @@
 // updates that were waiting for idle.
 const char kDelayedInstallInfo[] = "idle_install_info";
 
+// Reason why the extension's install was delayed.
+const char kDelayedInstallReason[] = "delay_install_reason";
+
 // Path for the suggested page ordinal of a delayed extension install.
 const char kPrefSuggestedPageOrdinal[] = "suggested_page_ordinal";
 
@@ -182,10 +185,6 @@
 // Key for Geometry Cache preference.
 const char kPrefGeometryCache[] = "geometry_cache";
 
-// Key for the path of the directory of the file last chosen by the user in
-// response to a chrome.fileSystem.chooseEntry() call.
-const char kLastChooseEntryDirectory[] = "last_choose_file_directory";
-
 // Provider of write access to a dictionary storing extension prefs.
 class ScopedExtensionPrefUpdate : public DictionaryPrefUpdate {
  public:
@@ -1328,6 +1327,7 @@
 void ExtensionPrefs::SetDelayedInstallInfo(
     const Extension* extension,
     Extension::State initial_state,
+    DelayReason delay_reason,
     const syncer::StringOrdinal& page_ordinal) {
   DictionaryValue* extension_dict = new DictionaryValue();
   PopulateExtensionInfoPrefs(extension, time_provider_->GetCurrentTime(),
@@ -1342,6 +1342,8 @@
         page_ordinal.IsValid() ? page_ordinal.ToInternalValue()
                                : std::string());
   }
+  extension_dict->SetInteger(kDelayedInstallReason,
+                             static_cast<int>(delay_reason));
 
   UpdateExtensionPref(extension->id(), kDelayedInstallInfo, extension_dict);
 }
@@ -1377,6 +1379,7 @@
     needs_sort_ordinal = true;
     pending_install_dict->Remove(kPrefSuggestedPageOrdinal, NULL);
   }
+  pending_install_dict->Remove(kDelayedInstallReason, NULL);
 
   const base::Time install_time = time_provider_->GetCurrentTime();
   pending_install_dict->Set(
@@ -1405,6 +1408,24 @@
   return GetInstalledInfoHelper(extension_id, ext);
 }
 
+ExtensionPrefs::DelayReason ExtensionPrefs::GetDelayedInstallReason(
+    const std::string& extension_id) const {
+  const DictionaryValue* extension_prefs =
+      GetExtensionPref(extension_id);
+  if (!extension_prefs)
+    return DELAY_REASON_NONE;
+
+  const DictionaryValue* ext = NULL;
+  if (!extension_prefs->GetDictionary(kDelayedInstallInfo, &ext))
+    return DELAY_REASON_NONE;
+
+  int delay_reason;
+  if (!ext->GetInteger(kDelayedInstallReason, &delay_reason))
+    return DELAY_REASON_NONE;
+
+  return static_cast<DelayReason>(delay_reason);
+}
+
 scoped_ptr<ExtensionPrefs::ExtensionsInfo> ExtensionPrefs::
     GetAllDelayedInstallInfo() const {
   scoped_ptr<ExtensionsInfo> extensions_info(new ExtensionsInfo);
@@ -1465,6 +1486,16 @@
   return creation_flags;
 }
 
+int ExtensionPrefs::GetDelayedInstallCreationFlags(
+    const std::string& extension_id) const {
+  int creation_flags = Extension::NO_FLAGS;
+  const DictionaryValue* delayed_info = NULL;
+  if (ReadPrefAsDictionary(extension_id, kDelayedInstallInfo, &delayed_info)) {
+    delayed_info->GetInteger(kPrefCreationFlags, &creation_flags);
+  }
+  return creation_flags;
+}
+
 bool ExtensionPrefs::WasInstalledByDefault(
     const std::string& extension_id) const {
   const DictionaryValue* dictionary = GetExtensionPref(extension_id);
@@ -1624,25 +1655,6 @@
   UpdateExtensionPref(extension_id, kPrefGeometryCache, cache.release());
 }
 
-bool ExtensionPrefs::GetLastChooseEntryDirectory(
-    const std::string& extension_id, base::FilePath* result) const {
-  const DictionaryValue* dictionary = GetExtensionPref(extension_id);
-  if (!dictionary)
-    return false;
-
-  const Value* value;
-  if (!dictionary->Get(kLastChooseEntryDirectory, &value))
-    return false;
-
-  return base::GetValueAsFilePath(*value, result);
-}
-
-void ExtensionPrefs::SetLastChooseEntryDirectory(
-    const std::string& extension_id, const base::FilePath& value) {
-  UpdateExtensionPref(extension_id, kLastChooseEntryDirectory,
-                      base::CreateFilePathValue(value));
-}
-
 ExtensionPrefs::ExtensionPrefs(
     PrefService* prefs,
     const base::FilePath& root_dir,
diff --git a/chrome/browser/extensions/extension_prefs.h b/chrome/browser/extensions/extension_prefs.h
index a0eb1ec..d721375 100644
--- a/chrome/browser/extensions/extension_prefs.h
+++ b/chrome/browser/extensions/extension_prefs.h
@@ -11,7 +11,7 @@
 
 #include "base/memory/linked_ptr.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/extensions/extension_scoped_prefs.h"
 #include "chrome/browser/prefs/scoped_user_pref_update.h"
@@ -81,6 +81,17 @@
     LAUNCH_DEFAULT = LAUNCH_REGULAR
   };
 
+  // This enum is used to store the reason an extension's install has been
+  // delayed.  Do not remove items or re-order this enum as it is used in
+  // preferences.
+  enum DelayReason {
+    DELAY_REASON_NONE = 0,
+    DELAY_REASON_GC = 1,
+    DELAY_REASON_WAIT_FOR_IDLE = 2,
+    DELAY_REASON_WAIT_FOR_IMPORTS = 3,
+  };
+
+
   // Creates base::Time classes. The default implementation is just to return
   // the current time, but tests can inject alternative implementations.
   class TimeProvider {
@@ -394,9 +405,10 @@
       const std::string& extension_id) const;
 
   // We've downloaded an updated .crx file for the extension, but are waiting
-  // for idle time to install it.
+  // to install it.
   void SetDelayedInstallInfo(const Extension* extension,
                              Extension::State initial_state,
+                             DelayReason delay_reason,
                              const syncer::StringOrdinal& page_ordinal);
 
   // Removes any delayed install information we have for the given
@@ -411,6 +423,8 @@
   scoped_ptr<ExtensionInfo> GetDelayedInstallInfo(
       const std::string& extension_id) const;
 
+  DelayReason GetDelayedInstallReason(const std::string& extension_id) const;
+
   // Returns information about all the extensions that have delayed install
   // information.
   scoped_ptr<ExtensionsInfo> GetAllDelayedInstallInfo() const;
@@ -430,6 +444,9 @@
   // Returns the creation flags mask for the extension.
   int GetCreationFlags(const std::string& extension_id) const;
 
+  // Returns the creation flags mask for a delayed install extension.
+  int GetDelayedInstallCreationFlags(const std::string& extension_id) const;
+
   // Returns true if the extension was installed from the Chrome Web Store.
   bool IsFromWebStore(const std::string& extension_id) const;
 
@@ -478,13 +495,6 @@
   void SetGeometryCache(const std::string& extension_id,
                         scoped_ptr<base::DictionaryValue> cache);
 
-  // The path of the directory containing the last file chosen by the user in
-  // response to a chrome.fileSystem.chooseEntry() call for this extension.
-  bool GetLastChooseEntryDirectory(const std::string& extension_id,
-                                   base::FilePath* result) const;
-  void SetLastChooseEntryDirectory(const std::string& extension_id,
-                                   const base::FilePath& value);
-
  private:
   friend class ExtensionPrefsBlacklistedExtensions;  // Unit test.
   friend class ExtensionPrefsUninstallExtension;     // Unit test.
diff --git a/chrome/browser/extensions/extension_prefs_unittest.cc b/chrome/browser/extensions/extension_prefs_unittest.cc
index 5fc8484..08d07d6 100644
--- a/chrome/browser/extensions/extension_prefs_unittest.cc
+++ b/chrome/browser/extensions/extension_prefs_unittest.cc
@@ -168,7 +168,7 @@
     scoped_ptr<APIPermission> permission(
         permission_info->CreateAPIPermission());
     {
-      scoped_ptr<ListValue> value(new ListValue());
+      scoped_ptr<base::ListValue> value(new base::ListValue());
       value->Append(Value::CreateStringValue("tcp-connect:*.example.com:80"));
       value->Append(Value::CreateStringValue("udp-bind::8080"));
       value->Append(Value::CreateStringValue("udp-send-to::8888"));
@@ -452,6 +452,7 @@
     ASSERT_TRUE(extension.get()) << errors;
     ASSERT_EQ(id, extension->id());
     prefs()->SetDelayedInstallInfo(extension.get(), Extension::ENABLED,
+                                   ExtensionPrefs::DELAY_REASON_WAIT_FOR_IDLE,
                                    syncer::StringOrdinal());
   }
 
diff --git a/chrome/browser/extensions/extension_process_manager.cc b/chrome/browser/extensions/extension_process_manager.cc
index 4ef475d..7346c25 100644
--- a/chrome/browser/extensions/extension_process_manager.cc
+++ b/chrome/browser/extensions/extension_process_manager.cc
@@ -12,7 +12,7 @@
 #include "base/metrics/histogram.h"
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/extensions/api/runtime/runtime_api.h"
 #include "chrome/browser/extensions/extension_host.h"
diff --git a/chrome/browser/extensions/extension_process_manager.h b/chrome/browser/extensions/extension_process_manager.h
index 75cdb40..12fdf4a 100644
--- a/chrome/browser/extensions/extension_process_manager.h
+++ b/chrome/browser/extensions/extension_process_manager.h
@@ -13,7 +13,7 @@
 #include "base/compiler_specific.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "extensions/common/view_type.h"
diff --git a/chrome/browser/extensions/extension_protocols_unittest.cc b/chrome/browser/extensions/extension_protocols_unittest.cc
index acffeeb..b096d98 100644
--- a/chrome/browser/extensions/extension_protocols_unittest.cc
+++ b/chrome/browser/extensions/extension_protocols_unittest.cc
@@ -67,7 +67,7 @@
   manifest.SetString("name", "An extension with web-accessible resources");
   manifest.SetString("version", "2");
 
-  ListValue* web_accessible_list = new ListValue();
+  base::ListValue* web_accessible_list = new base::ListValue();
   web_accessible_list->AppendString("test.dat");
   manifest.Set("web_accessible_resources", web_accessible_list);
 
diff --git a/chrome/browser/extensions/extension_renderer_state.cc b/chrome/browser/extensions/extension_renderer_state.cc
index c43c690..551d895 100644
--- a/chrome/browser/extensions/extension_renderer_state.cc
+++ b/chrome/browser/extensions/extension_renderer_state.cc
@@ -8,7 +8,6 @@
 #include "base/bind_helpers.h"
 #include "chrome/browser/sessions/session_tab_helper.h"
 #include "chrome/browser/tab_contents/retargeting_details.h"
-#include "chrome/browser/webview/webview_guest.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/navigation_details.h"
diff --git a/chrome/browser/extensions/extension_renderer_state.h b/chrome/browser/extensions/extension_renderer_state.h
index 8118585..1ce2dde 100644
--- a/chrome/browser/extensions/extension_renderer_state.h
+++ b/chrome/browser/extensions/extension_renderer_state.h
@@ -12,9 +12,7 @@
 #include "base/basictypes.h"
 #include "base/memory/singleton.h"
 
-namespace chrome {
 class WebViewGuest;
-}  // namespace chrome
 
 // This class keeps track of renderer state for use on the IO thread. All
 // methods should be called on the IO thread except for Init and Shutdown.
@@ -48,7 +46,7 @@
   class RenderViewHostObserver;
   class TabObserver;
   friend class TabObserver;
-  friend class chrome::WebViewGuest;
+  friend class WebViewGuest;
   friend struct DefaultSingletonTraits<ExtensionRendererState>;
 
   typedef std::pair<int, int> RenderId;
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc
index c08866d..2458305 100644
--- a/chrome/browser/extensions/extension_service.cc
+++ b/chrome/browser/extensions/extension_service.cc
@@ -23,7 +23,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/sequenced_worker_pool.h"
 #include "base/threading/thread_restrictions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "base/version.h"
 #include "chrome/browser/app_mode/app_mode_utils.h"
@@ -76,6 +76,7 @@
 #include "chrome/common/chrome_version_info.h"
 #include "chrome/common/extensions/background_info.h"
 #include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/extension_constants.h"
 #include "chrome/common/extensions/extension_file_util.h"
 #include "chrome/common/extensions/extension_manifest_constants.h"
 #include "chrome/common/extensions/extension_messages.h"
@@ -85,6 +86,7 @@
 #include "chrome/common/extensions/manifest.h"
 #include "chrome/common/extensions/manifest_handlers/app_isolation_info.h"
 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
+#include "chrome/common/extensions/manifest_handlers/shared_module_info.h"
 #include "chrome/common/extensions/manifest_url_handler.h"
 #include "chrome/common/extensions/permissions/permissions_data.h"
 #include "chrome/common/extensions/sync_helper.h"
@@ -128,6 +130,7 @@
 using extensions::PermissionMessage;
 using extensions::PermissionMessages;
 using extensions::PermissionSet;
+using extensions::SharedModuleInfo;
 using extensions::UnloadedExtensionInfo;
 
 namespace errors = extension_manifest_errors;
@@ -157,6 +160,10 @@
 // which can be garbage collected.
 static const int kGarbageCollectStartupDelay = 30;
 
+static bool IsSharedModule(const Extension* extension) {
+  return SharedModuleInfo::IsSharedModule(extension);
+}
+
 }  // namespace
 
 ExtensionService::ExtensionRuntimeData::ExtensionRuntimeData()
@@ -340,7 +347,7 @@
       event_routers_initialized_(false),
       update_once_all_providers_are_ready_(false),
       browser_terminating_(false),
-      installs_delayed_(false),
+      installs_delayed_for_gc_(false),
       is_first_run_(false),
       app_sync_bundle_(this),
       extension_sync_bundle_(this) {
@@ -457,33 +464,6 @@
   }
 }
 
-void ExtensionService::InitEventRoutersAfterImport() {
-  RegisterForImportFinished();
-}
-
-void ExtensionService::RegisterForImportFinished() {
-  if (!registrar_.IsRegistered(this, chrome::NOTIFICATION_IMPORT_FINISHED,
-                               content::Source<Profile>(profile_))) {
-    registrar_.Add(this, chrome::NOTIFICATION_IMPORT_FINISHED,
-                   content::Source<Profile>(profile_));
-  }
-}
-
-void ExtensionService::InitAfterImport() {
-  startup_metric_utils::ScopedSlowStartupUMA
-      scoped_timer("Startup.SlowStartupExtensionServiceInitAfterImport");
-  component_loader_->LoadAll();
-
-  CheckForExternalUpdates();
-
-  GarbageCollectExtensions();
-
-  // Idempotent, so although there is a possible race if the import
-  // process finished sometime in the middle of ProfileImpl::InitExtensions,
-  // it cannot happen twice.
-  InitEventRouters();
-}
-
 void ExtensionService::InitEventRouters() {
   if (event_routers_initialized_)
     return;
@@ -557,31 +537,48 @@
     // extension listens to onStartup and opens a window).
     SetReadyAndNotifyListeners();
   } else {
-    // TODO(mek): It might be cleaner to do the FinishDelayedInstallInfo stuff
-    // here instead of in installedloader.
-    if (g_browser_process->profile_manager() &&
-        g_browser_process->profile_manager()->will_import()) {
-      // Do not load any component extensions, since they may conflict with the
-      // import process.
+    // LoadAllExtensions() calls OnLoadedInstalledExtensions().
+    component_loader_->LoadAll();
+    extensions::InstalledLoader(this).LoadAllExtensions();
 
-      extensions::InstalledLoader(this).LoadAllExtensions();
-      SetReadyAndNotifyListeners();
-      RegisterForImportFinished();
-    } else {
-      // In this case, LoadAllExtensions() calls OnLoadedInstalledExtensions().
-      component_loader_->LoadAll();
-      extensions::InstalledLoader(this).LoadAllExtensions();
-      SetReadyAndNotifyListeners();
-
-      // TODO(erikkay) this should probably be deferred to a future point
-      // rather than running immediately at startup.
-      CheckForExternalUpdates();
-
-      base::MessageLoop::current()->PostDelayedTask(
-          FROM_HERE,
-          base::Bind(&ExtensionService::GarbageCollectExtensions, AsWeakPtr()),
-          base::TimeDelta::FromSeconds(kGarbageCollectStartupDelay));
+    // Finish install (if possible) of extensions that were still delayed while
+    // the browser was shut down.
+    scoped_ptr<extensions::ExtensionPrefs::ExtensionsInfo> delayed_info(
+        extension_prefs_->GetAllDelayedInstallInfo());
+    for (size_t i = 0; i < delayed_info->size(); ++i) {
+      ExtensionInfo* info = delayed_info->at(i).get();
+      scoped_refptr<const Extension> extension(NULL);
+      if (info->extension_manifest) {
+        std::string error;
+        extension = Extension::Create(
+            info->extension_path,
+            info->extension_location,
+            *info->extension_manifest,
+            extension_prefs_->GetDelayedInstallCreationFlags(
+                info->extension_id),
+            info->extension_id,
+            &error);
+        if (extension.get())
+          delayed_installs_.Insert(extension);
+      }
     }
+    MaybeFinishDelayedInstallations();
+
+    scoped_ptr<extensions::ExtensionPrefs::ExtensionsInfo> delayed_info2(
+        extension_prefs_->GetAllDelayedInstallInfo());
+    UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateOnLoad",
+                             delayed_info2->size() - delayed_info->size());
+
+    SetReadyAndNotifyListeners();
+
+    // TODO(erikkay) this should probably be deferred to a future point
+    // rather than running immediately at startup.
+    CheckForExternalUpdates();
+
+    base::MessageLoop::current()->PostDelayedTask(
+        FROM_HERE,
+        base::Bind(&ExtensionService::GarbageCollectExtensions, AsWeakPtr()),
+        base::TimeDelta::FromSeconds(kGarbageCollectStartupDelay));
 
     if (extension_prefs_->NeedsStorageGarbageCollection()) {
       GarbageCollectIsolatedStorage();
@@ -672,7 +669,7 @@
   return true;
 }
 
-void ExtensionService::ReloadExtension(const std::string& extension_id) {
+void ExtensionService::ReloadExtension(const std::string extension_id) {
   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   // If the extension is already reloading, don't reload again.
@@ -708,7 +705,7 @@
     path = unloaded_extension_paths_[extension_id];
   }
 
-  if (delayed_updates_for_idle_.Contains(extension_id)) {
+  if (delayed_installs_.Contains(extension_id)) {
     FinishDelayedInstallation(extension_id);
     return;
   }
@@ -716,12 +713,15 @@
   // If we're reloading a component extension, use the component extension
   // loader's reloader.
   if (component_loader_->Exists(extension_id)) {
+    SetBeingReloaded(extension_id, true);
     component_loader_->Reload(extension_id);
+    SetBeingReloaded(extension_id, false);
     return;
   }
 
   // Check the installed extensions to see if what we're reloading was already
   // installed.
+  SetBeingReloaded(extension_id, true);
   scoped_ptr<ExtensionInfo> installed_extension(
       extension_prefs_->GetInstalledExtensionInfo(extension_id));
   if (installed_extension.get() &&
@@ -734,6 +734,8 @@
     CHECK(!path.empty());
     extensions::UnpackedInstaller::Create(this)->Load(path);
   }
+  // When reloading is done, mark this extension as done reloading.
+  SetBeingReloaded(extension_id, false);
 }
 
 bool ExtensionService::UninstallExtension(
@@ -836,9 +838,10 @@
     extension_sync_bundle_.ProcessDeletion(extension_id, sync_change);
   }
 
-  delayed_updates_for_idle_.Remove(extension_id);
   delayed_installs_.Remove(extension_id);
 
+  PruneSharedModulesOnUninstall(extension.get());
+
   // Track the uninstallation.
   UMA_HISTOGRAM_ENUMERATION("Extensions.ExtensionUninstalled", 1, 2);
 
@@ -924,6 +927,7 @@
   // |extension| can be NULL if sync disables an extension that is not
   // installed yet.
   if (extension &&
+      disable_reason != Extension::DISABLE_RELOAD &&
       !system_->management_policy()->UserMayModifySettings(extension, NULL)) {
     return;
   }
@@ -960,12 +964,12 @@
 
   for (ExtensionSet::const_iterator extension = extensions_.begin();
       extension != extensions_.end(); ++extension) {
-    if (management_policy->UserMayModifySettings(*extension, NULL))
+    if (management_policy->UserMayModifySettings(extension->get(), NULL))
       to_disable.push_back(*extension);
   }
   for (ExtensionSet::const_iterator extension = terminated_extensions_.begin();
       extension != terminated_extensions_.end(); ++extension) {
-    if (management_policy->UserMayModifySettings(*extension, NULL))
+    if (management_policy->UserMayModifySettings(extension->get(), NULL))
       to_disable.push_back(*extension);
   }
 
@@ -2205,6 +2209,92 @@
   child_process_logging::SetActiveExtensions(extension_ids);
 }
 
+ExtensionService::ImportStatus ExtensionService::SatisfyImports(
+    const Extension* extension) {
+  ImportStatus status = IMPORT_STATUS_OK;
+  std::vector<std::string> pending;
+  // TODO(elijahtaylor): Message the user if there is a failure that is
+  // unrecoverable.
+  if (SharedModuleInfo::ImportsModules(extension)) {
+    const std::vector<SharedModuleInfo::ImportInfo>& imports =
+        SharedModuleInfo::GetImports(extension);
+    std::vector<SharedModuleInfo::ImportInfo>::const_iterator i;
+    for (i = imports.begin(); i != imports.end(); ++i) {
+      Version version_required(i->minimum_version);
+      const Extension* imported_module =
+          GetExtensionById(i->extension_id, true);
+      if (!imported_module) {
+        if (extension->from_webstore()) {
+          status = IMPORT_STATUS_UNSATISFIED;
+          pending.push_back(i->extension_id);
+        } else {
+          return IMPORT_STATUS_UNRECOVERABLE;
+        }
+      } else if (!SharedModuleInfo::IsSharedModule(imported_module)) {
+        return IMPORT_STATUS_UNRECOVERABLE;
+      } else if (version_required.IsValid() &&
+                 imported_module->version()->CompareTo(version_required) < 0) {
+        if (imported_module->from_webstore()) {
+          status = IMPORT_STATUS_UNSATISFIED;
+        } else {
+          return IMPORT_STATUS_UNRECOVERABLE;
+        }
+      }
+    }
+  }
+  if (status == IMPORT_STATUS_UNSATISFIED) {
+    for (std::vector<std::string>::const_iterator iter = pending.begin();
+         iter != pending.end();
+         ++iter) {
+      pending_extension_manager()->AddFromExtensionImport(
+          *iter,
+          extension_urls::GetWebstoreUpdateUrl(),
+          IsSharedModule);
+    }
+    CheckForUpdatesSoon();
+  }
+  return status;
+}
+
+scoped_ptr<const ExtensionSet>
+    ExtensionService::GetDependentExtensions(const Extension* extension) {
+  scoped_ptr<ExtensionSet> dependents(new ExtensionSet());
+  scoped_ptr<ExtensionSet> set_to_check(new ExtensionSet());
+  if (SharedModuleInfo::IsSharedModule(extension)) {
+    set_to_check->InsertAll(disabled_extensions_);
+    set_to_check->InsertAll(delayed_installs_);
+    set_to_check->InsertAll(extensions_);
+    for (ExtensionSet::const_iterator iter = set_to_check->begin();
+         iter != set_to_check->end(); ++iter) {
+      if (SharedModuleInfo::ImportsExtensionById(iter->get(),
+                                                 extension->id())) {
+        dependents->Insert(*iter);
+      }
+    }
+  }
+  return dependents.PassAs<const ExtensionSet>();
+}
+
+void ExtensionService::PruneSharedModulesOnUninstall(
+    const Extension* extension) {
+  if (SharedModuleInfo::ImportsModules(extension)) {
+    const std::vector<SharedModuleInfo::ImportInfo>& imports =
+        SharedModuleInfo::GetImports(extension);
+    std::vector<SharedModuleInfo::ImportInfo>::const_iterator i;
+    for (i = imports.begin(); i != imports.end(); ++i) {
+      const Extension* imported_module =
+          GetExtensionById(i->extension_id, true);
+      if (imported_module && imported_module->from_webstore()) {
+        scoped_ptr<const ExtensionSet> dependents =
+            GetDependentExtensions(imported_module);
+        if (dependents->size() == 0) {
+          UninstallExtension(i->extension_id, false, NULL);
+        }
+      }
+    }
+  }
+}
+
 void ExtensionService::OnExtensionInstalled(
     const Extension* extension,
     const syncer::StringOrdinal& page_ordinal,
@@ -2287,10 +2377,10 @@
       initial_enable ? Extension::ENABLED : Extension::DISABLED;
   if (ShouldDelayExtensionUpdate(id, wait_for_idle)) {
     extension_prefs_->SetDelayedInstallInfo(extension, initial_state,
-                                            page_ordinal);
+        extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IDLE, page_ordinal);
 
     // Transfer ownership of |extension|.
-    delayed_updates_for_idle_.Insert(extension);
+    delayed_installs_.Insert(extension);
 
     // Notify extension of available update.
     extensions::RuntimeEventRouter::DispatchOnUpdateAvailableEvent(
@@ -2302,10 +2392,18 @@
     return;
   }
 
-  if (installs_delayed()) {
+  ImportStatus status = SatisfyImports(extension);
+  if (installs_delayed_for_gc()) {
     extension_prefs_->SetDelayedInstallInfo(extension, initial_state,
-                                            page_ordinal);
+        extensions::ExtensionPrefs::DELAY_REASON_GC, page_ordinal);
     delayed_installs_.Insert(extension);
+  } else if (status != IMPORT_STATUS_OK) {
+    if (status == IMPORT_STATUS_UNSATISFIED) {
+      extension_prefs_->SetDelayedInstallInfo(extension, initial_state,
+          extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IMPORTS,
+          page_ordinal);
+      delayed_installs_.Insert(extension);
+    }
   } else {
     AddNewOrUpdatedExtension(extension, initial_state, page_ordinal);
   }
@@ -2327,13 +2425,35 @@
 
 void ExtensionService::MaybeFinishDelayedInstallation(
     const std::string& extension_id) {
-  // Check if the extension already got updated.
-  if (!delayed_updates_for_idle_.Contains(extension_id))
+  // Check if the extension already got installed.
+  if (!delayed_installs_.Contains(extension_id))
     return;
-  // Check if the extension is idle.
-  if (!IsExtensionIdle(extension_id))
+  extensions::ExtensionPrefs::DelayReason reason =
+      extension_prefs_->GetDelayedInstallReason(extension_id);
+
+  // Check if the extension is idle. DELAY_REASON_NONE is used for older
+  // preferences files that will not have set this field but it was previously
+  // only used for idle updates.
+  if ((reason == extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IDLE ||
+       reason == extensions::ExtensionPrefs::DELAY_REASON_NONE) &&
+       is_ready() && !IsExtensionIdle(extension_id))
     return;
 
+  const Extension* extension = delayed_installs_.GetByID(extension_id);
+  if (reason == extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IMPORTS) {
+    ImportStatus status = SatisfyImports(extension);
+    if (status != IMPORT_STATUS_OK) {
+      if (status == IMPORT_STATUS_UNRECOVERABLE) {
+        delayed_installs_.Remove(extension_id);
+        // Make sure no version of the extension is actually installed, (i.e.,
+        // that this delayed install was not an update).
+        CHECK(!extension_prefs_->GetInstalledExtensionInfo(extension_id).get());
+        extension_prefs_->DeleteExtensionPrefs(extension_id);
+      }
+      return;
+    }
+  }
+
   FinishDelayedInstallation(extension_id);
 }
 
@@ -2342,7 +2462,7 @@
   scoped_refptr<const Extension> extension(
       GetPendingExtensionUpdate(extension_id));
   CHECK(extension.get());
-  delayed_updates_for_idle_.Remove(extension_id);
+  delayed_installs_.Remove(extension_id);
 
   if (!extension_prefs_->FinishDelayedInstallInfo(extension_id))
     NOTREACHED();
@@ -2399,11 +2519,17 @@
                               EXTERNAL_EXTENSION_INSTALLED,
                               EXTERNAL_EXTENSION_BUCKET_BOUNDARY);
   }
+
+  // Check extensions that may have been delayed only because this shared module
+  // was not available.
+  if (SharedModuleInfo::IsSharedModule(extension)) {
+    MaybeFinishDelayedInstallations();
+  }
 }
 
 const Extension* ExtensionService::GetPendingExtensionUpdate(
     const std::string& id) const {
-  return delayed_updates_for_idle_.GetByID(id);
+  return delayed_installs_.GetByID(id);
 }
 
 void ExtensionService::TrackTerminatedExtension(const Extension* extension) {
@@ -2642,15 +2768,11 @@
                      process->GetID()));
       break;
     }
-    case chrome::NOTIFICATION_IMPORT_FINISHED: {
-      InitAfterImport();
-      break;
-    }
     case chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED: {
       extensions::ExtensionHost* host =
           content::Details<extensions::ExtensionHost>(details).ptr();
       std::string extension_id = host->extension_id();
-      if (delayed_updates_for_idle_.Contains(extension_id)) {
+      if (delayed_installs_.Contains(extension_id)) {
         // We were waiting for this extension to become idle, it now might have,
         // so maybe finish installation.
         base::MessageLoop::current()->PostDelayedTask(
@@ -2746,6 +2868,27 @@
   extension_runtime_data_[extension->id()].being_upgraded = value;
 }
 
+bool ExtensionService::IsBeingReloaded(
+    const std::string& extension_id) const {
+  return ContainsKey(extensions_being_reloaded_, extension_id);
+}
+
+void ExtensionService::SetBeingReloaded(const std::string& extension_id,
+                                         bool isBeingReloaded) {
+  LOG(INFO) << "****** " << __FUNCTION__;
+  LOG(INFO) << "****** " << __FUNCTION__ << " extension_id is: "
+            << extension_id << " and isBeingReloaded is " << isBeingReloaded;
+  LOG(INFO) << "****** " << __FUNCTION__ << " Set size is "
+            << extensions_being_reloaded_.size();
+  if (isBeingReloaded) {
+    extensions_being_reloaded_.insert(extension_id);
+    LOG(INFO) << "****** " << __FUNCTION__ << " insert succeeded.";
+  } else {
+    extensions_being_reloaded_.erase(extension_id);
+    LOG(INFO) << "****** " << __FUNCTION__ << " erase succeeded.";
+  }
+}
+
 bool ExtensionService::HasUsedWebRequest(const Extension* extension) const {
   ExtensionRuntimeDataMap::const_iterator it =
       extension_runtime_data_.find(extension->id());
@@ -2834,8 +2977,8 @@
     }
   }
 
-  DCHECK(!installs_delayed());
-  set_installs_delayed(true);
+  DCHECK(!installs_delayed_for_gc());
+  set_installs_delayed_for_gc(true);
   BrowserContext::GarbageCollectStoragePartitions(
       profile_, active_paths.Pass(),
       base::Bind(&ExtensionService::OnGarbageCollectIsolatedStorageFinished,
@@ -2843,18 +2986,22 @@
 }
 
 void ExtensionService::OnGarbageCollectIsolatedStorageFinished() {
-  set_installs_delayed(false);
+  set_installs_delayed_for_gc(false);
+  MaybeFinishDelayedInstallations();
+}
+
+void ExtensionService::MaybeFinishDelayedInstallations() {
+  std::vector<std::string> to_be_installed;
   for (ExtensionSet::const_iterator it = delayed_installs_.begin();
        it != delayed_installs_.end();
        ++it) {
-    FinishDelayedInstallation((*it)->id());
+    to_be_installed.push_back((*it)->id());
   }
-  for (ExtensionSet::const_iterator it = delayed_updates_for_idle_.begin();
-       it != delayed_updates_for_idle_.end();
+  for (std::vector<std::string>::const_iterator it = to_be_installed.begin();
+       it != to_be_installed.end();
        ++it) {
-    MaybeFinishDelayedInstallation((*it)->id());
+    MaybeFinishDelayedInstallation(*it);
   }
-  delayed_installs_.Clear();
 }
 
 void ExtensionService::OnNeedsToGarbageCollectIsolatedStorage() {
diff --git a/chrome/browser/extensions/extension_service.h b/chrome/browser/extensions/extension_service.h
index e83a3a6..8d0c6c3 100644
--- a/chrome/browser/extensions/extension_service.h
+++ b/chrome/browser/extensions/extension_service.h
@@ -66,7 +66,7 @@
 class ExtensionUpdater;
 class PendingExtensionManager;
 class SettingsFrontend;
-} // namespace extensions
+}  // namespace extensions
 
 namespace syncer {
 class SyncErrorFactory;
@@ -249,6 +249,11 @@
   bool IsBeingUpgraded(const extensions::Extension* extension) const;
   void SetBeingUpgraded(const extensions::Extension* extension, bool value);
 
+  // Getter and setter for the flag that specifies whether the extension is
+  // being reloaded.
+  bool IsBeingReloaded(const std::string& extension_name) const;
+  void SetBeingReloaded(const std::string& extension_id, bool value);
+
   // Getter and setter for the flag that specifies if the extension has used
   // the webrequest API.
   // TODO(mpcomplete): remove. http://crbug.com/100411
@@ -258,15 +263,6 @@
   // Initialize and start all installed extensions.
   void Init();
 
-  // To delay some initialization until after import has finished, register
-  // for the notification.
-  // TODO(yoz): remove InitEventRoutersAterImport.
-  void InitEventRoutersAfterImport();
-  void RegisterForImportFinished();
-
-  // Complete some initialization after being notified that import has finished.
-  void InitAfterImport();
-
   // Start up the extension event routers.
   void InitEventRouters();
 
@@ -320,7 +316,7 @@
 
   // Reloads the specified extension, sending the onLaunched() event to it if it
   // currently has any window showing.
-  void ReloadExtension(const std::string& extension_id);
+  void ReloadExtension(const std::string extension_id);
 
   // Uninstalls the specified extension. Callers should only call this method
   // with extensions that exist. |external_uninstall| is a magical parameter
@@ -413,6 +409,24 @@
   virtual void AddComponentExtension(const extensions::Extension* extension)
       OVERRIDE;
 
+  enum ImportStatus {
+   IMPORT_STATUS_OK,
+   IMPORT_STATUS_UNSATISFIED,
+   IMPORT_STATUS_UNRECOVERABLE
+  };
+
+  // Checks an extension's shared module imports to see if they are satisfied.
+  // If they are not, this function adds the dependencies to the pending install
+  // list if |extension| came from the webstore.
+  ImportStatus SatisfyImports(const extensions::Extension* extension);
+
+  // Returns a set of extensions that import a given extension.
+  scoped_ptr<const ExtensionSet> GetDependentExtensions(
+      const extensions::Extension* extension);
+
+  // Uninstalls shared modules that were only referenced by |extension|.
+  void PruneSharedModulesOnUninstall(const extensions::Extension* extension);
+
   // Informs the service that an extension's files are in place for loading.
   //
   // Please make sure the Blacklist is checked some time before calling this
@@ -423,6 +437,9 @@
       bool has_requirement_errors,
       bool wait_for_idle);
 
+  // Checks for delayed installation for all pending installs.
+  void MaybeFinishDelayedInstallations();
+
   // Similar to FinishInstallation, but first checks if there still is an update
   // pending for the extension, and makes sure the extension is still idle.
   void MaybeFinishDelayedInstallation(const std::string& extension_id);
@@ -770,9 +787,12 @@
   void ManageBlacklist(const std::set<std::string>& old_blacklisted_ids,
                        const std::set<std::string>& new_blacklisted_ids);
 
-  // Controls if installs are delayed. See comment for |installs_delayed_|.
-  void set_installs_delayed(bool value) { installs_delayed_ = value; }
-  bool installs_delayed() const { return installs_delayed_; }
+  // Controls if installs are delayed. See comment for
+  // |installs_delayed_for_gc_|.
+  void set_installs_delayed_for_gc(bool value) {
+    installs_delayed_for_gc_ = value;
+  }
+  bool installs_delayed_for_gc() const { return installs_delayed_for_gc_; }
 
   // The normal profile associated with this ExtensionService.
   Profile* profile_;
@@ -804,13 +824,8 @@
   // they can easily be un-blacklisted.
   ExtensionSet blacklisted_extensions_;
 
-  // The list of extension updates that have had their installs delayed because
-  // they are waiting for idle.
-  ExtensionSet delayed_updates_for_idle_;
-
-  // The list of extension installs delayed by |installs_delayed_|.
-  // This is a disjoint set from |delayed_updates_for_idle_|. Extensions in
-  // the |delayed_installs_| do not need to wait for idle.
+  // The list of extension installs delayed for various reasons.  The reason
+  // for delayed install is stored in ExtensionPrefs.
   ExtensionSet delayed_installs_;
 
   // Hold the set of pending extensions.
@@ -891,11 +906,11 @@
   // decide to abort.
   bool browser_terminating_;
 
-  // Set to true to delay all new extension installations. Acts as a lock
-  // to allow background processing of tasks such as garbage collection of
-  // on-disk state without needing to worry about race conditions caused
-  // by extension installation and reinstallation.
-  bool installs_delayed_;
+  // Set to true to delay all new extension installations. Acts as a lock to
+  // allow background processing of garbage collection of on-disk state without
+  // needing to worry about race conditions caused by extension installation and
+  // reinstallation.
+  bool installs_delayed_for_gc_;
 
   // Set to true if this is the first time this ExtensionService has run.
   // Used for specially handling external extensions that are installed the
@@ -907,6 +922,10 @@
 
   extensions::ProcessMap process_map_;
 
+  // A set of the extension ids currently being reloaded.  We use this to
+  // avoid showing a "new install" notice for an extension reinstall.
+  std::set<std::string> extensions_being_reloaded_;
+
   scoped_ptr<ExtensionErrorUI> extension_error_ui_;
   // Sequenced task runner for extension related file operations.
   scoped_refptr<base::SequencedTaskRunner> file_task_runner_;
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc
index 7d9aca1..9297723 100644
--- a/chrome/browser/extensions/extension_service_unittest.cc
+++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -116,6 +116,9 @@
 #include "chrome/browser/chromeos/settings/device_settings_service.h"
 #endif
 
+using base::DictionaryValue;
+using base::ListValue;
+using base::Value;
 using content::BrowserContext;
 using content::BrowserThread;
 using content::DOMStorageContext;
@@ -155,7 +158,8 @@
 const char* const updates_from_webstore = "akjooamlhcgeopfifcmlggaebeocgokj";
 
 struct ExtensionsOrder {
-  bool operator()(const Extension* a, const Extension* b) {
+  bool operator()(const scoped_refptr<const Extension>& a,
+                  const scoped_refptr<const Extension>& b) {
     return a->name() < b->name();
   }
 };
@@ -506,13 +510,13 @@
   ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
   base::FilePath path = temp_dir_.path();
   path = path.Append(FILE_PATH_LITERAL("TestingExtensionsPath"));
-  file_util::Delete(path, true);
+  base::Delete(path, true);
   file_util::CreateDirectory(path);
   base::FilePath temp_prefs = path.Append(FILE_PATH_LITERAL("Preferences"));
   file_util::CopyFile(prefs_file, temp_prefs);
 
   extensions_install_dir_ = path.Append(FILE_PATH_LITERAL("Extensions"));
-  file_util::Delete(extensions_install_dir_, true);
+  base::Delete(extensions_install_dir_, true);
   file_util::CopyDirectory(source_install_dir, extensions_install_dir_, true);
 
   ExtensionServiceInitParams params;
@@ -542,12 +546,12 @@
   ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
   base::FilePath path = temp_dir_.path();
   path = path.Append(FILE_PATH_LITERAL("TestingExtensionsPath"));
-  file_util::Delete(path, true);
+  base::Delete(path, true);
   file_util::CreateDirectory(path);
   base::FilePath prefs_filename =
       path.Append(FILE_PATH_LITERAL("TestPreferences"));
   extensions_install_dir_ = path.Append(FILE_PATH_LITERAL("Extensions"));
-  file_util::Delete(extensions_install_dir_, true);
+  base::Delete(extensions_install_dir_, true);
   file_util::CreateDirectory(extensions_install_dir_);
 
   ExtensionServiceInitParams params;
@@ -654,7 +658,7 @@
       ASSERT_TRUE(file_util::PathExists(pem_path));
     }
 
-    ASSERT_TRUE(file_util::Delete(crx_path, false));
+    ASSERT_TRUE(base::Delete(crx_path, false));
 
     scoped_ptr<ExtensionCreator> creator(new ExtensionCreator());
     ASSERT_TRUE(creator->Run(dir_path,
@@ -1450,6 +1454,66 @@
       prefs->GetDelayedInstallInfo("bjafgdebaacbbbecmhlhpofkepfkgcpa"));
 }
 
+// Test various cases for delayed install because of missing imports.
+TEST_F(ExtensionServiceTest, PendingImports) {
+  InitPluginService();
+
+  base::FilePath source_install_dir = data_dir_
+      .AppendASCII("pending_updates_with_imports")
+      .AppendASCII("Extensions");
+  base::FilePath pref_path = source_install_dir
+      .DirName()
+      .AppendASCII("Preferences");
+
+  InitializeInstalledExtensionService(pref_path, source_install_dir);
+
+  // Verify there are no pending extensions initially.
+  EXPECT_FALSE(service_->pending_extension_manager()->HasPendingExtensions());
+
+  service_->Init();
+  // Wait for GarbageCollectExtensions task to complete.
+  loop_.RunUntilIdle();
+
+  // These extensions are used by the extensions we test below, they must be
+  // installed.
+  EXPECT_TRUE(file_util::PathExists(extensions_install_dir_.AppendASCII(
+      "bjafgdebaacbbbecmhlhpofkepfkgcpa/1.0")));
+  EXPECT_TRUE(file_util::PathExists(extensions_install_dir_.AppendASCII(
+      "hpiknbiabeeppbpihjehijgoemciehgk/2")));
+
+  // Each of these extensions should have been rejected because of dependencies
+  // that cannot be satisfied.
+  ExtensionPrefs* prefs = service_->extension_prefs();
+  EXPECT_FALSE(
+      prefs->GetDelayedInstallInfo("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
+  EXPECT_FALSE(
+      prefs->GetInstalledExtensionInfo("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
+  EXPECT_FALSE(
+      prefs->GetDelayedInstallInfo("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"));
+  EXPECT_FALSE(
+      prefs->GetInstalledExtensionInfo("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"));
+  EXPECT_FALSE(
+      prefs->GetDelayedInstallInfo("cccccccccccccccccccccccccccccccc"));
+  EXPECT_FALSE(
+      prefs->GetInstalledExtensionInfo("cccccccccccccccccccccccccccccccc"));
+
+  // Make sure the import started for the extension with a dependency.
+  EXPECT_TRUE(
+      prefs->GetDelayedInstallInfo("behllobkkfkfnphdnhnkndlbkcpglgmj"));
+  EXPECT_EQ(ExtensionPrefs::DELAY_REASON_WAIT_FOR_IMPORTS,
+      prefs->GetDelayedInstallReason("behllobkkfkfnphdnhnkndlbkcpglgmj"));
+
+  EXPECT_FALSE(file_util::PathExists(extensions_install_dir_.AppendASCII(
+      "behllobkkfkfnphdnhnkndlbkcpglgmj/1.0.0.0")));
+
+  EXPECT_TRUE(service_->pending_extension_manager()->HasPendingExtensions());
+  std::string pending_id("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee");
+  EXPECT_TRUE(service_->pending_extension_manager()->IsIdPending(pending_id));
+  // Remove it because we are not testing the pending extension manager's
+  // ability to download and install extensions.
+  EXPECT_TRUE(service_->pending_extension_manager()->Remove(pending_id));
+}
+
 // Test installing extensions. This test tries to install few extensions using
 // crx files. If you need to change those crx files, feel free to repackage
 // them, throw away the key used and change the id's above.
@@ -1974,7 +2038,7 @@
 
   // Repeat the run with the pem file gone, and no special flags
   // Should refuse to overwrite the existing crx.
-  file_util::Delete(privkey_path, false);
+  base::Delete(privkey_path, false);
   ASSERT_FALSE(creator->Run(input_directory, crx_path, base::FilePath(),
       privkey_path, ExtensionCreator::kNoRunFlags));
 
@@ -2111,9 +2175,9 @@
   ASSERT_TRUE(file_util::PathExists(crx_path));
   ASSERT_TRUE(file_util::PathExists(privkey_path));
 
-  file_util::Delete(crx_path, false);
+  base::Delete(crx_path, false);
   // Move the pem file into the extension.
-  file_util::Move(privkey_path,
+  base::Move(privkey_path,
                   input_directory.AppendASCII("privkey.pem"));
 
   // This pack should fail because of the contained private key.
@@ -2214,7 +2278,7 @@
   // directory, and we don't want to copy the whole extension for a unittest.
   base::FilePath theme_file = extension_path.Append(chrome::kThemePackFilename);
   ASSERT_TRUE(file_util::PathExists(theme_file));
-  ASSERT_TRUE(file_util::Delete(theme_file, false));  // Not recursive.
+  ASSERT_TRUE(base::Delete(theme_file, false));  // Not recursive.
 }
 
 // Tests that we can change the ID of an unpacked extension by adding a key
@@ -3944,6 +4008,8 @@
   IndexedDBContext* idb_context =
       BrowserContext::GetDefaultStoragePartition(profile_.get())->
           GetIndexedDBContext();
+  idb_context->SetTaskRunnerForTesting(
+      base::MessageLoop::current()->message_loop_proxy().get());
   base::FilePath idb_path = idb_context->GetFilePathForTesting(origin_id);
   EXPECT_TRUE(file_util::CreateDirectory(idb_path));
   EXPECT_TRUE(file_util::DirectoryExists(idb_path));
@@ -4059,6 +4125,8 @@
   IndexedDBContext* idb_context =
       BrowserContext::GetDefaultStoragePartition(profile_.get())->
           GetIndexedDBContext();
+  idb_context->SetTaskRunnerForTesting(
+      base::MessageLoop::current()->message_loop_proxy().get());
   base::FilePath idb_path = idb_context->GetFilePathForTesting(origin_id);
   EXPECT_TRUE(file_util::CreateDirectory(idb_path));
   EXPECT_TRUE(file_util::DirectoryExists(idb_path));
diff --git a/chrome/browser/extensions/extension_sorting.cc b/chrome/browser/extensions/extension_sorting.cc
index dc92c4c..ec2ba25 100644
--- a/chrome/browser/extensions/extension_sorting.cc
+++ b/chrome/browser/extensions/extension_sorting.cc
@@ -467,6 +467,7 @@
     // Ensure that the web store app still isn't found in this list, since
     // it is added after this loop.
     DCHECK(*ext_it != extension_misc::kWebStoreAppId);
+    DCHECK(*ext_it != extension_misc::kChromeAppId);
   }
 
   // Include the Web Store App since it is displayed on the NTP.
@@ -477,6 +478,14 @@
                       web_store_app_page,
                       GetAppLaunchOrdinal(extension_misc::kWebStoreAppId));
   }
+  // Include the Chrome App since it is displayed in the app launcher.
+  syncer::StringOrdinal chrome_app_page =
+      GetPageOrdinal(extension_misc::kChromeAppId);
+  if (chrome_app_page.IsValid()) {
+    AddOrdinalMapping(extension_misc::kChromeAppId,
+                      chrome_app_page,
+                      GetAppLaunchOrdinal(extension_misc::kChromeAppId));
+  }
 }
 
 void ExtensionSorting::AddOrdinalMapping(
@@ -540,6 +549,7 @@
   chromeos::default_app_order::Get(&app_ids);
 #else
   const char* kDefaultAppOrder[] = {
+    extension_misc::kChromeAppId,
     extension_misc::kWebStoreAppId,
   };
   const std::vector<const char*> app_ids(
diff --git a/chrome/browser/extensions/extension_special_storage_policy_unittest.cc b/chrome/browser/extensions/extension_special_storage_policy_unittest.cc
index 3ae4143..7e07052 100644
--- a/chrome/browser/extensions/extension_special_storage_policy_unittest.cc
+++ b/chrome/browser/extensions/extension_special_storage_policy_unittest.cc
@@ -104,7 +104,7 @@
     manifest.SetString(keys::kName, "Protected");
     manifest.SetString(keys::kVersion, "1");
     manifest.SetString(keys::kLaunchWebURL, "http://explicit/protected/start");
-    ListValue* list = new ListValue();
+    base::ListValue* list = new base::ListValue();
     list->Append(Value::CreateStringValue("http://explicit/protected"));
     list->Append(Value::CreateStringValue("*://*.wildcards/protected"));
     manifest.Set(keys::kWebURLs, list);
@@ -126,10 +126,10 @@
     manifest.SetString(keys::kName, "Unlimited");
     manifest.SetString(keys::kVersion, "1");
     manifest.SetString(keys::kLaunchWebURL, "http://explicit/unlimited/start");
-    ListValue* list = new ListValue();
+    base::ListValue* list = new base::ListValue();
     list->Append(Value::CreateStringValue("unlimitedStorage"));
     manifest.Set(keys::kPermissions, list);
-    list = new ListValue();
+    list = new base::ListValue();
     list->Append(Value::CreateStringValue("http://explicit/unlimited"));
     list->Append(Value::CreateStringValue("*://*.wildcards/unlimited"));
     manifest.Set(keys::kWebURLs, list);
diff --git a/chrome/browser/extensions/extension_startup_browsertest.cc b/chrome/browser/extensions/extension_startup_browsertest.cc
index ada7f89..43519a9 100644
--- a/chrome/browser/extensions/extension_startup_browsertest.cc
+++ b/chrome/browser/extensions/extension_startup_browsertest.cc
@@ -79,11 +79,11 @@
   }
 
   virtual void TearDown() {
-    EXPECT_TRUE(file_util::Delete(preferences_file_, false));
+    EXPECT_TRUE(base::Delete(preferences_file_, false));
 
     // TODO(phajdan.jr): Check return values of the functions below, carefully.
-    file_util::Delete(user_scripts_dir_, true);
-    file_util::Delete(extensions_dir_, true);
+    base::Delete(user_scripts_dir_, true);
+    base::Delete(extensions_dir_, true);
 
     InProcessBrowserTest::TearDown();
   }
diff --git a/chrome/browser/extensions/extension_system.cc b/chrome/browser/extensions/extension_system.cc
index a2ae1f3..c65ec53 100644
--- a/chrome/browser/extensions/extension_system.cc
+++ b/chrome/browser/extensions/extension_system.cc
@@ -204,14 +204,7 @@
   // initialized (see issue 40144). Now that bookmarks aren't imported and
   // the event routers need to be initialized for every profile individually,
   // initialize them with the extension service.
-  // If import is going to run in a separate process (the profile itself is on
-  // the main process), wait for import to finish before initializing the
-  // routers.
-  if (g_browser_process->profile_manager()->will_import()) {
-    extension_service_->InitEventRoutersAfterImport();
-  } else {
-    extension_service_->InitEventRouters();
-  }
+  extension_service_->InitEventRouters();
 
   extension_warning_service_.reset(new ExtensionWarningService(profile_));
   extension_warning_badge_service_.reset(
diff --git a/chrome/browser/extensions/extension_tab_util.cc b/chrome/browser/extensions/extension_tab_util.cc
index e86607f..e8e50b0 100644
--- a/chrome/browser/extensions/extension_tab_util.cc
+++ b/chrome/browser/extensions/extension_tab_util.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/extensions/extension_tab_util.h"
 
+#include "apps/shell_window.h"
 #include "chrome/browser/extensions/api/tabs/tabs_constants.h"
 #include "chrome/browser/extensions/shell_window_registry.h"
 #include "chrome/browser/extensions/tab_helper.h"
@@ -16,7 +17,6 @@
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_iterator.h"
 #include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/extensions/shell_window.h"
 #include "chrome/browser/ui/tab_contents/tab_contents_iterator.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/extensions/extension.h"
@@ -33,6 +33,7 @@
 namespace keys = extensions::tabs_constants;
 namespace tabs = extensions::api::tabs;
 
+using apps::ShellWindow;
 using content::NavigationEntry;
 using content::WebContents;
 using extensions::APIPermission;
@@ -99,10 +100,10 @@
   return result;
 }
 
-ListValue* ExtensionTabUtil::CreateTabList(
+base::ListValue* ExtensionTabUtil::CreateTabList(
     const Browser* browser,
     const Extension* extension) {
-  ListValue* tab_list = new ListValue();
+  base::ListValue* tab_list = new base::ListValue();
   TabStripModel* tab_strip = browser->tab_strip_model();
   for (int i = 0; i < tab_strip->count(); ++i) {
     tab_list->Append(CreateTabValue(tab_strip->GetWebContentsAt(i),
diff --git a/chrome/browser/extensions/extension_tabs_apitest.cc b/chrome/browser/extensions/extension_tabs_apitest.cc
index 128e0b3..7a654a5 100644
--- a/chrome/browser/extensions/extension_tabs_apitest.cc
+++ b/chrome/browser/extensions/extension_tabs_apitest.cc
@@ -22,15 +22,14 @@
 #define MAYBE_UpdateWindowShowState DISABLED_UpdateWindowShowState
 #else
 
-#if defined(USE_AURA) || defined(OS_MACOSX) || defined(OS_WIN)
+#if defined(USE_AURA) || defined(OS_MACOSX)
 // Maximizing/fullscreen popup window doesn't work on aura's managed mode.
 // See bug crbug.com/116305.
 // Mac: http://crbug.com/103912
-// Failing on Win7: http://crbug.com/176683
 #define MAYBE_UpdateWindowShowState DISABLED_UpdateWindowShowState
 #else
 #define MAYBE_UpdateWindowShowState UpdateWindowShowState
-#endif  // defined(USE_AURA) || defined(OS_MACOSX) || defined(OS_WIN)
+#endif  // defined(USE_AURA) || defined(OS_MACOSX)
 
 #define MAYBE_UpdateWindowResize UpdateWindowResize
 #endif  // defined(OS_LINUX) && !defined(USE_AURA)
@@ -140,7 +139,7 @@
 
 // Flaky on the trybots. See http://crbug.com/96725.
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, DISABLED_TabConnect) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionTest("tabs/connect")) << message_;
 }
 
@@ -156,7 +155,7 @@
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, DISABLED_CaptureVisibleTabJpeg) {
   host_resolver()->AddRule("a.com", "127.0.0.1");
   host_resolver()->AddRule("b.com", "127.0.0.1");
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionSubtest("tabs/capture_visible_tab",
                                   "test_jpeg.html")) << message_;
 }
@@ -164,7 +163,7 @@
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, DISABLED_CaptureVisibleTabPng) {
   host_resolver()->AddRule("a.com", "127.0.0.1");
   host_resolver()->AddRule("b.com", "127.0.0.1");
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionSubtest("tabs/capture_visible_tab",
                                   "test_png.html")) << message_;
 }
diff --git a/chrome/browser/extensions/extension_web_ui.cc b/chrome/browser/extensions/extension_web_ui.cc
index fc851b9..b62af29 100644
--- a/chrome/browser/extensions/extension_web_ui.cc
+++ b/chrome/browser/extensions/extension_web_ui.cc
@@ -45,7 +45,7 @@
 namespace {
 
 // De-dupes the items in |list|. Assumes the values are strings.
-void CleanUpDuplicates(ListValue* list) {
+void CleanUpDuplicates(base::ListValue* list) {
   std::set<std::string> seen_values;
 
   // Loop backwards as we may be removing items.
@@ -178,10 +178,10 @@
     return false;
 
   Profile* profile = Profile::FromBrowserContext(browser_context);
-  const DictionaryValue* overrides =
+  const base::DictionaryValue* overrides =
       profile->GetPrefs()->GetDictionary(kExtensionURLOverrides);
   std::string page = url->host();
-  const ListValue* url_list = NULL;
+  const base::ListValue* url_list = NULL;
   if (!overrides || !overrides->GetList(page, &url_list))
     return false;
 
@@ -244,7 +244,7 @@
 bool ExtensionWebUI::HandleChromeURLOverrideReverse(
     GURL* url, content::BrowserContext* browser_context) {
   Profile* profile = Profile::FromBrowserContext(browser_context);
-  const DictionaryValue* overrides =
+  const base::DictionaryValue* overrides =
       profile->GetPrefs()->GetDictionary(kExtensionURLOverrides);
   if (!overrides)
     return false;
@@ -253,12 +253,13 @@
   // internal URL
   // chrome-extension://eemcgdkfndhakfknompkggombfjjjeno/main.html#1 to
   // chrome://bookmarks/#1 for display in the omnibox.
-  for (DictionaryValue::Iterator it(*overrides); !it.IsAtEnd(); it.Advance()) {
-    const ListValue* url_list = NULL;
+  for (base::DictionaryValue::Iterator it(*overrides); !it.IsAtEnd();
+       it.Advance()) {
+    const base::ListValue* url_list = NULL;
     if (!it.value().GetAsList(&url_list))
       continue;
 
-    for (ListValue::const_iterator it2 = url_list->begin();
+    for (base::ListValue::const_iterator it2 = url_list->begin();
          it2 != url_list->end(); ++it2) {
       std::string override;
       if (!(*it2)->GetAsString(&override))
@@ -283,22 +284,22 @@
 
   PrefService* prefs = profile->GetPrefs();
   DictionaryPrefUpdate update(prefs, kExtensionURLOverrides);
-  DictionaryValue* all_overrides = update.Get();
+  base::DictionaryValue* all_overrides = update.Get();
 
   // For each override provided by the extension, add it to the front of
   // the override list if it's not already in the list.
   URLOverrides::URLOverrideMap::const_iterator iter = overrides.begin();
   for (; iter != overrides.end(); ++iter) {
     const std::string& key = iter->first;
-    ListValue* page_overrides = NULL;
+    base::ListValue* page_overrides = NULL;
     if (!all_overrides->GetList(key, &page_overrides)) {
-      page_overrides = new ListValue();
+      page_overrides = new base::ListValue();
       all_overrides->Set(key, page_overrides);
     } else {
       CleanUpDuplicates(page_overrides);
 
       // Verify that the override isn't already in the list.
-      ListValue::iterator i = page_overrides->begin();
+      base::ListValue::iterator i = page_overrides->begin();
       for (; i != page_overrides->end(); ++i) {
         std::string override_val;
         if (!(*i)->GetAsString(&override_val)) {
@@ -321,7 +322,7 @@
 // static
 void ExtensionWebUI::UnregisterAndReplaceOverride(const std::string& page,
                                                   Profile* profile,
-                                                  ListValue* list,
+                                                  base::ListValue* list,
                                                   const Value* override) {
   size_t index = 0;
   bool found = list->Remove(*override, &index);
@@ -342,8 +343,8 @@
     return;
   PrefService* prefs = profile->GetPrefs();
   DictionaryPrefUpdate update(prefs, kExtensionURLOverrides);
-  DictionaryValue* all_overrides = update.Get();
-  ListValue* page_overrides = NULL;
+  base::DictionaryValue* all_overrides = update.Get();
+  base::ListValue* page_overrides = NULL;
   if (!all_overrides->GetList(page, &page_overrides)) {
     // If it's being unregistered, it should already be in the list.
     NOTREACHED();
@@ -360,11 +361,11 @@
     return;
   PrefService* prefs = profile->GetPrefs();
   DictionaryPrefUpdate update(prefs, kExtensionURLOverrides);
-  DictionaryValue* all_overrides = update.Get();
+  base::DictionaryValue* all_overrides = update.Get();
   URLOverrides::URLOverrideMap::const_iterator iter = overrides.begin();
   for (; iter != overrides.end(); ++iter) {
     const std::string& page = iter->first;
-    ListValue* page_overrides = NULL;
+    base::ListValue* page_overrides = NULL;
     if (!all_overrides->GetList(page, &page_overrides)) {
       // If it's being unregistered, it should already be in the list.
       NOTREACHED();
diff --git a/chrome/browser/extensions/extensions_quota_service.cc b/chrome/browser/extensions/extensions_quota_service.cc
index bd34b1f..f776c40 100644
--- a/chrome/browser/extensions/extensions_quota_service.cc
+++ b/chrome/browser/extensions/extensions_quota_service.cc
@@ -37,7 +37,7 @@
 std::string ExtensionsQuotaService::Assess(
     const std::string& extension_id,
     ExtensionFunction* function,
-    const ListValue* args,
+    const base::ListValue* args,
     const base::TimeTicks& event_time) {
   DCHECK(CalledOnValidThread());
 
@@ -106,7 +106,7 @@
 }
 
 void QuotaLimitHeuristic::SingletonBucketMapper::GetBucketsForArgs(
-    const ListValue* args,
+    const base::ListValue* args,
     BucketList* buckets) {
   buckets->push_back(&bucket_);
 }
@@ -119,7 +119,7 @@
 
 QuotaLimitHeuristic::~QuotaLimitHeuristic() {}
 
-bool QuotaLimitHeuristic::ApplyToArgs(const ListValue* args,
+bool QuotaLimitHeuristic::ApplyToArgs(const base::ListValue* args,
     const base::TimeTicks& event_time) {
   BucketList buckets;
   bucket_mapper_->GetBucketsForArgs(args, &buckets);
diff --git a/chrome/browser/extensions/extensions_quota_service.h b/chrome/browser/extensions/extensions_quota_service.h
index e29300e..5644397 100644
--- a/chrome/browser/extensions/extensions_quota_service.h
+++ b/chrome/browser/extensions/extensions_quota_service.h
@@ -22,8 +22,8 @@
 #include "base/containers/hash_tables.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/threading/non_thread_safe.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "base/values.h"
 
 class ExtensionFunction;
@@ -56,7 +56,7 @@
   // or empty-string if the request is fine and can proceed.
   std::string Assess(const std::string& extension_id,
                      ExtensionFunction* function,
-                     const ListValue* args,
+                     const base::ListValue* args,
                      const base::TimeTicks& event_time);
 
  private:
@@ -152,7 +152,7 @@
     // occurs while parsing |args|, the function aborts - buckets may be non-
     // empty). The expectation is that invalid args and associated errors are
     // handled by the ExtensionFunction itself so we don't concern ourselves.
-    virtual void GetBucketsForArgs(const ListValue* args,
+    virtual void GetBucketsForArgs(const base::ListValue* args,
                                    BucketList* buckets) = 0;
   };
 
@@ -162,7 +162,7 @@
    public:
     SingletonBucketMapper() {}
     virtual ~SingletonBucketMapper() {}
-    virtual void GetBucketsForArgs(const ListValue* args,
+    virtual void GetBucketsForArgs(const base::ListValue* args,
                                    BucketList* buckets) OVERRIDE;
 
    private:
@@ -180,7 +180,8 @@
   // implementation of a derived class) to perform an operation with |args|,
   // based on the history of similar operations with similar arguments (which
   // is retrieved using the BucketMapper).
-  bool ApplyToArgs(const ListValue* args, const base::TimeTicks& event_time);
+  bool ApplyToArgs(const base::ListValue* args,
+                   const base::TimeTicks& event_time);
 
   // Returns an error formatted according to this heuristic.
   std::string GetError() const;
diff --git a/chrome/browser/extensions/extensions_quota_service_unittest.cc b/chrome/browser/extensions/extensions_quota_service_unittest.cc
index e8eefd0..4ebbf5a 100644
--- a/chrome/browser/extensions/extensions_quota_service_unittest.cc
+++ b/chrome/browser/extensions/extensions_quota_service_unittest.cc
@@ -34,7 +34,7 @@
  public:
   Mapper() {}
   virtual ~Mapper() { STLDeleteValues(&buckets_); }
-  virtual void GetBucketsForArgs(const ListValue* args,
+  virtual void GetBucketsForArgs(const base::ListValue* args,
                                  BucketList* buckets) OVERRIDE {
     for (size_t i = 0; i < args->GetSize(); i++) {
       int id;
@@ -52,7 +52,7 @@
 
 class MockMapper : public QuotaLimitHeuristic::BucketMapper {
  public:
-  virtual void GetBucketsForArgs(const ListValue* args,
+  virtual void GetBucketsForArgs(const base::ListValue* args,
                                  BucketList* buckets) OVERRIDE {
   }
 };
@@ -61,7 +61,7 @@
  public:
   explicit MockFunction(const std::string& name) { set_name(name); }
 
-  virtual void SetArgs(const ListValue* args) OVERRIDE {}
+  virtual void SetArgs(const base::ListValue* args) OVERRIDE {}
   virtual const std::string GetError() OVERRIDE { return std::string(); }
   virtual void SetError(const std::string& error) OVERRIDE {}
   virtual void Run() OVERRIDE {}
@@ -217,20 +217,20 @@
 
 TEST_F(ExtensionsQuotaServiceTest, NoHeuristic) {
   scoped_refptr<MockFunction> f(new MockFunction("foo"));
-  ListValue args;
+  base::ListValue args;
   EXPECT_EQ("", service_->Assess(extension_a_, f.get(), &args, kStartTime));
 }
 
 TEST_F(ExtensionsQuotaServiceTest, FrozenHeuristic) {
   scoped_refptr<MockFunction> f(new FrozenMockFunction("foo"));
-  ListValue args;
+  base::ListValue args;
   args.Append(new base::FundamentalValue(1));
   EXPECT_NE("", service_->Assess(extension_a_, f.get(), &args, kStartTime));
 }
 
 TEST_F(ExtensionsQuotaServiceTest, SingleHeuristic) {
   scoped_refptr<MockFunction> f(new TimedLimitMockFunction("foo"));
-  ListValue args;
+  base::ListValue args;
   args.Append(new base::FundamentalValue(1));
   EXPECT_EQ("", service_->Assess(extension_a_, f.get(), &args, kStartTime));
   EXPECT_EQ("",
@@ -244,7 +244,7 @@
                              &args,
                              kStartTime + TimeDelta::FromSeconds(15)));
 
-  ListValue args2;
+  base::ListValue args2;
   args2.Append(new base::FundamentalValue(1));
   args2.Append(new base::FundamentalValue(2));
   EXPECT_EQ("", service_->Assess(extension_b_, f.get(), &args2, kStartTime));
@@ -269,7 +269,7 @@
                              kStartTime + peace + TimeDelta::FromSeconds(15)));
 
   // Test that items are independent.
-  ListValue args3;
+  base::ListValue args3;
   args3.Append(new base::FundamentalValue(3));
   EXPECT_EQ("", service_->Assess(extension_c_, f.get(), &args, kStartTime));
   EXPECT_EQ("",
@@ -301,7 +301,7 @@
 
 TEST_F(ExtensionsQuotaServiceTest, ChainedHeuristics) {
   scoped_refptr<MockFunction> f(new ChainedLimitsMockFunction("foo"));
-  ListValue args;
+  base::ListValue args;
   args.Append(new base::FundamentalValue(1));
 
   // First, test that the low limit can be avoided but the higher one is hit.
@@ -356,8 +356,8 @@
   scoped_refptr<MockFunction> f(new TimedLimitMockFunction("foo"));
   scoped_refptr<MockFunction> g(new TimedLimitMockFunction("bar"));
 
-  ListValue args_f;
-  ListValue args_g;
+  base::ListValue args_f;
+  base::ListValue args_g;
   args_f.Append(new base::FundamentalValue(1));
   args_g.Append(new base::FundamentalValue(2));
 
@@ -388,7 +388,7 @@
 TEST_F(ExtensionsQuotaServiceTest, ViolatorsWillBeViolators) {
   scoped_refptr<MockFunction> f(new TimedLimitMockFunction("foo"));
   scoped_refptr<MockFunction> g(new TimedLimitMockFunction("bar"));
-  ListValue arg;
+  base::ListValue arg;
   arg.Append(new base::FundamentalValue(1));
   EXPECT_EQ("", service_->Assess(extension_a_, f.get(), &arg, kStartTime));
   EXPECT_EQ("",
diff --git a/chrome/browser/extensions/external_provider_impl.cc b/chrome/browser/extensions/external_provider_impl.cc
index 08efd2e..b5f3dc5 100644
--- a/chrome/browser/extensions/external_provider_impl.cc
+++ b/chrome/browser/extensions/external_provider_impl.cc
@@ -90,7 +90,7 @@
   loader_->StartLoading();
 }
 
-void ExternalProviderImpl::SetPrefs(DictionaryValue* prefs) {
+void ExternalProviderImpl::SetPrefs(base::DictionaryValue* prefs) {
   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   // Check if the service is still alive. It is possible that it went
@@ -104,9 +104,9 @@
   std::set<std::string> unsupported_extensions;
 
   // Notify ExtensionService about all the extensions this provider has.
-  for (DictionaryValue::Iterator i(*prefs_); !i.IsAtEnd(); i.Advance()) {
+  for (base::DictionaryValue::Iterator i(*prefs_); !i.IsAtEnd(); i.Advance()) {
     const std::string& extension_id = i.key();
-    const DictionaryValue* extension = NULL;
+    const base::DictionaryValue* extension = NULL;
 
     if (!Extension::IdIsValid(extension_id)) {
       LOG(WARNING) << "Malformed extension dictionary: key "
@@ -159,7 +159,7 @@
     }
 
     // Check that extension supports current browser locale.
-    const ListValue* supported_locales = NULL;
+    const base::ListValue* supported_locales = NULL;
     if (extension->GetList(kSupportedLocales, &supported_locales)) {
       std::vector<std::string> browser_locales;
       l10n_util::GetParentLocales(g_browser_process->GetApplicationLocale(),
@@ -307,7 +307,7 @@
   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   CHECK(prefs_.get());
   CHECK(ready_);
-  DictionaryValue* extension = NULL;
+  base::DictionaryValue* extension = NULL;
   if (!prefs_->GetDictionary(id, &extension))
     return false;
 
diff --git a/chrome/browser/extensions/external_registry_loader_win.cc b/chrome/browser/extensions/external_registry_loader_win.cc
index 05498fb..47cf902 100644
--- a/chrome/browser/extensions/external_registry_loader_win.cc
+++ b/chrome/browser/extensions/external_registry_loader_win.cc
@@ -11,7 +11,7 @@
 #include "base/metrics/histogram.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "base/version.h"
 #include "base/win/registry.h"
diff --git a/chrome/browser/extensions/image_loader.cc b/chrome/browser/extensions/image_loader.cc
index a941e23..9d775dd 100644
--- a/chrome/browser/extensions/image_loader.cc
+++ b/chrome/browser/extensions/image_loader.cc
@@ -174,19 +174,24 @@
 #endif
 #if defined(USE_AURA)
     {"keyboard/api_adapter.js", IDR_KEYBOARD_API_ADAPTER_JS},
-    {"keyboard/common.js", IDR_KEYBOARD_COMMON_JS},
-    {"keyboard/images/chevron.svg", IDR_KEYBOARD_IMAGES_CHEVRON},
-    {"keyboard/images/del.svg", IDR_KEYBOARD_IMAGES_DEL},
+    {"keyboard/constants.js", IDR_KEYBOARD_CONSTANTS_JS},
+    {"keyboard/elements/kb-accent-container.html",
+        IDR_KEYBOARD_ELEMENTS_ACCENT_CONTAINER},
+    {"keyboard/elements/kb-accent-key.html", IDR_KEYBOARD_ELEMENTS_ACCENT_KEY},
+    {"keyboard/elements/kb-accent-set.html", IDR_KEYBOARD_ELEMENTS_ACCENT_SET},
+    {"keyboard/elements/kb-key.html", IDR_KEYBOARD_ELEMENTS_KEY},
+    {"keyboard/elements/kb-keyboard.html", IDR_KEYBOARD_ELEMENTS_KEYBOARD},
+    {"keyboard/elements/kb-keyset.html", IDR_KEYBOARD_ELEMENTS_KEYSET},
+    {"keyboard/elements/kb-row.html", IDR_KEYBOARD_ELEMENTS_ROW},
     {"keyboard/images/keyboard.svg", IDR_KEYBOARD_IMAGES_KEYBOARD},
     {"keyboard/images/mic.svg", IDR_KEYBOARD_IMAGES_MIC},
-    {"keyboard/images/ret.svg", IDR_KEYBOARD_IMAGES_RET},
-    {"keyboard/images/shift.svg", IDR_KEYBOARD_IMAGES_SHIFT},
-    {"keyboard/images/shift_down.svg", IDR_KEYBOARD_IMAGES_SHIFT_DOWN},
-    {"keyboard/images/tab.svg", IDR_KEYBOARD_IMAGES_TAB},
+    {"keyboard/images/mic-green.svg", IDR_KEYBOARD_IMAGES_MIC_GREEN},
     {"keyboard/index.html", IDR_KEYBOARD_INDEX},
-    {"keyboard/layout_us.js", IDR_KEYBOARD_LAYOUT_US_JS},
+    {"keyboard/keysets.html", IDR_KEYBOARD_KEYSETS},
     {"keyboard/main.css", IDR_KEYBOARD_MAIN_CSS},
     {"keyboard/main.js", IDR_KEYBOARD_MAIN_JS},
+    {"keyboard/polymer.min.js", IDR_KEYBOARD_POLYMER},
+    {"keyboard/voice_input.js", IDR_KEYBOARD_VOICE_INPUT_JS},
 #endif
   };
   static const size_t kExtraComponentExtensionResourcesSize =
diff --git a/chrome/browser/extensions/installed_loader.cc b/chrome/browser/extensions/installed_loader.cc
index 2fc4b46..ee65eda 100644
--- a/chrome/browser/extensions/installed_loader.cc
+++ b/chrome/browser/extensions/installed_loader.cc
@@ -164,7 +164,6 @@
 
   std::vector<int> reload_reason_counts(NUM_MANIFEST_RELOAD_REASONS, 0);
   bool should_write_prefs = false;
-  int update_count = 0;
 
   for (size_t i = 0; i < extensions_info->size(); ++i) {
     ExtensionInfo* info = extensions_info->at(i).get();
@@ -174,31 +173,6 @@
     if (info->extension_location == Manifest::COMMAND_LINE)
       continue;
 
-    scoped_ptr<ExtensionInfo> pending_update(
-        extension_prefs_->GetDelayedInstallInfo(info->extension_id));
-    if (pending_update) {
-      if (!extension_prefs_->FinishDelayedInstallInfo(info->extension_id))
-        NOTREACHED();
-
-      Version old_version;
-      if (info->extension_manifest) {
-        std::string version_str;
-        if (info->extension_manifest->GetString(
-            extension_manifest_keys::kVersion, &version_str)) {
-          old_version = Version(version_str);
-        }
-      }
-      base::MessageLoop::current()->PostTask(FROM_HERE,
-          base::Bind(&DispatchOnInstalledEvent, extension_service_->profile(),
-                     info->extension_id, old_version, false));
-
-      info = extension_prefs_->GetInstalledExtensionInfo(
-          info->extension_id).release();
-      extensions_info->at(i).reset(info);
-
-      update_count++;
-    }
-
     ManifestReloadReason reload_reason = ShouldReloadExtensionManifest(*info);
     ++reload_reason_counts[reload_reason];
     UMA_HISTOGRAM_ENUMERATION("Extensions.ManifestReloadEnumValue",
@@ -255,8 +229,6 @@
                            extension_service_->extensions()->size());
   UMA_HISTOGRAM_COUNTS_100("Extensions.Disabled",
                            extension_service_->disabled_extensions()->size());
-  UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateOnLoad",
-                           update_count);
 
   UMA_HISTOGRAM_TIMES("Extensions.LoadAllTime",
                       base::TimeTicks::Now() - start_time);
diff --git a/chrome/browser/extensions/isolated_app_browsertest.cc b/chrome/browser/extensions/isolated_app_browsertest.cc
index ca84974..0dcdfa7 100644
--- a/chrome/browser/extensions/isolated_app_browsertest.cc
+++ b/chrome/browser/extensions/isolated_app_browsertest.cc
@@ -21,6 +21,9 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test_utils.h"
 #include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "net/test/embedded_test_server/http_response.h"
+#include "net/test/embedded_test_server/http_request.h"
 
 using content::ExecuteScript;
 using content::ExecuteScriptAndExtractString;
@@ -35,6 +38,64 @@
       javascript_expression + ")";
 }
 
+scoped_ptr<net::test_server::HttpResponse> HandleExpectAndSetCookieRequest(
+    const net::test_server::EmbeddedTestServer* test_server,
+    const net::test_server::HttpRequest& request) {
+  if (!StartsWithASCII(request.relative_url, "/expect-and-set-cookie?", true))
+    return scoped_ptr<net::test_server::HttpResponse>();
+
+  scoped_ptr<net::test_server::BasicHttpResponse> http_response(
+      new net::test_server::BasicHttpResponse);
+  http_response->set_code(net::HTTP_OK);
+
+  std::string request_cookies;
+  std::map<std::string, std::string>::const_iterator it =
+      request.headers.find("Cookie");
+  if (it != request.headers.end())
+    request_cookies = it->second;
+
+  size_t query_string_pos = request.relative_url.find('?');
+  std::string query_string =
+      request.relative_url.substr(query_string_pos + 1);
+  url_parse::Component query(0, query_string.length()), key_pos, value_pos;
+  bool expectations_satisfied = true;
+  std::vector<std::string> cookies_to_set;
+  while (url_parse::ExtractQueryKeyValue(
+             query_string.c_str(), &query, &key_pos, &value_pos)) {
+    std::string escaped_key(query_string.substr(key_pos.begin, key_pos.len));
+    std::string escaped_value(
+        query_string.substr(value_pos.begin, value_pos.len));
+
+    std::string key =
+        net::UnescapeURLComponent(escaped_key,
+                                  net::UnescapeRule::NORMAL |
+                                  net::UnescapeRule::SPACES |
+                                  net::UnescapeRule::URL_SPECIAL_CHARS);
+
+    std::string value =
+        net::UnescapeURLComponent(escaped_value,
+                                  net::UnescapeRule::NORMAL |
+                                  net::UnescapeRule::SPACES |
+                                  net::UnescapeRule::URL_SPECIAL_CHARS);
+
+    if (key == "expect") {
+      if (request_cookies.find(value) == std::string::npos)
+        expectations_satisfied = false;
+    } else if (key == "set") {
+      cookies_to_set.push_back(value);
+    } else {
+      return scoped_ptr<net::test_server::HttpResponse>();
+    }
+  }
+
+  if (expectations_satisfied) {
+    for (size_t i = 0; i < cookies_to_set.size(); i++)
+      http_response->AddCustomHeader("Set-Cookie", cookies_to_set[i]);
+  }
+
+  return http_response.PassAs<net::test_server::HttpResponse>();
+}
+
 class IsolatedAppTest : public ExtensionBrowserTest {
  public:
   // Returns whether the given tab's current URL has the given cookie.
@@ -76,12 +137,12 @@
 
 IN_PROC_BROWSER_TEST_F(IsolatedAppTest, CrossProcessClientRedirect) {
   host_resolver()->AddRule("*", "127.0.0.1");
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("isolated_apps/app1")));
   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("isolated_apps/app2")));
 
-  GURL base_url = test_server()->GetURL("files/extensions/isolated_apps/");
+  GURL base_url = embedded_test_server()->GetURL("/extensions/isolated_apps/");
   GURL::Replacements replace_host;
   std::string host_str("localhost");  // Must stay in scope with replace_host.
   replace_host.SetHostStr(host_str);
@@ -91,8 +152,8 @@
       CURRENT_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
 
   // Redirect to app2.
-  GURL redirect_url(test_server()->GetURL(
-      "client-redirect?files/extensions/isolated_apps/app2/main.html"));
+  GURL redirect_url(embedded_test_server()->GetURL(
+      "/extensions/isolated_apps/app2/redirect.html"));
   ui_test_utils::NavigateToURLWithDisposition(
       browser(), redirect_url,
       CURRENT_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
@@ -143,14 +204,14 @@
 // separation as you would expect.
 IN_PROC_BROWSER_TEST_F(IsolatedAppTest, CookieIsolation) {
   host_resolver()->AddRule("*", "127.0.0.1");
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("isolated_apps/app1")));
   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("isolated_apps/app2")));
 
   // The app under test acts on URLs whose host is "localhost",
   // so the URLs we navigate to must have host "localhost".
-  GURL base_url = test_server()->GetURL("files/extensions/isolated_apps/");
+  GURL base_url = embedded_test_server()->GetURL("/extensions/isolated_apps/");
   GURL::Replacements replace_host;
   std::string host_str("localhost");  // Must stay in scope with replace_host.
   replace_host.SetHostStr(host_str);
@@ -242,11 +303,11 @@
 // Ensure that cookies are not isolated if the isolated apps are not installed.
 IN_PROC_BROWSER_TEST_F(IsolatedAppTest, DISABLED_NoCookieIsolationWithoutApp) {
   host_resolver()->AddRule("*", "127.0.0.1");
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   // The app under test acts on URLs whose host is "localhost",
   // so the URLs we navigate to must have host "localhost".
-  GURL base_url = test_server()->GetURL("files/extensions/isolated_apps/");
+  GURL base_url = embedded_test_server()->GetURL("/extensions/isolated_apps/");
   GURL::Replacements replace_host;
   std::string host_str("localhost");  // Must stay in scope with replace_host.
   replace_host.SetHostStr(host_str);
@@ -321,15 +382,18 @@
 // Tests that subresource and media requests use the app's cookie store.
 // See http://crbug.com/141172.
 IN_PROC_BROWSER_TEST_F(IsolatedAppTest, MAYBE_SubresourceCookieIsolation) {
+  embedded_test_server()->RegisterRequestHandler(
+      base::Bind(&HandleExpectAndSetCookieRequest, embedded_test_server()));
+
   host_resolver()->AddRule("*", "127.0.0.1");
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("isolated_apps/app1")));
 
   // The app under test acts on URLs whose host is "localhost",
   // so the URLs we navigate to must have host "localhost".
-  GURL root_url = test_server()->GetURL(std::string());
-  GURL base_url = test_server()->GetURL("files/extensions/isolated_apps/");
+  GURL root_url = embedded_test_server()->GetURL("/");
+  GURL base_url = embedded_test_server()->GetURL("/extensions/isolated_apps/");
   GURL::Replacements replace_host;
   std::string host_str("localhost");  // Must stay in scope with replace_host.
   replace_host.SetHostStr(host_str);
@@ -338,7 +402,7 @@
 
   // First set cookies inside and outside the app.
   ui_test_utils::NavigateToURLWithDisposition(
-      browser(), root_url.Resolve("set-cookie?nonApp=1"),
+      browser(), root_url.Resolve("expect-and-set-cookie?set=nonApp%3d1"),
       CURRENT_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
   WebContents* tab0 = browser()->tab_strip_model()->GetWebContentsAt(0);
   ASSERT_FALSE(GetInstalledApp(tab0));
@@ -397,13 +461,13 @@
 // where non-app popups may be kept in the hosted app process.
 IN_PROC_BROWSER_TEST_F(IsolatedAppTest, MAYBE_IsolatedAppProcessModel) {
   host_resolver()->AddRule("*", "127.0.0.1");
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("isolated_apps/app1")));
 
   // The app under test acts on URLs whose host is "localhost",
   // so the URLs we navigate to must have host "localhost".
-  GURL base_url = test_server()->GetURL("files/extensions/isolated_apps/");
+  GURL base_url = embedded_test_server()->GetURL("/extensions/isolated_apps/");
   GURL::Replacements replace_host;
   std::string host_str("localhost");  // Must stay in scope with replace_host.
   replace_host.SetHostStr(host_str);
@@ -457,14 +521,14 @@
 // removed. http://crbug.com/159932
 IN_PROC_BROWSER_TEST_F(IsolatedAppTest, DISABLED_SessionStorage) {
   host_resolver()->AddRule("*", "127.0.0.1");
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("isolated_apps/app1")));
   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("isolated_apps/app2")));
 
   // The app under test acts on URLs whose host is "localhost",
   // so the URLs we navigate to must have host "localhost".
-  GURL base_url = test_server()->GetURL("files/extensions/isolated_apps/");
+  GURL base_url = embedded_test_server()->GetURL("/extensions/isolated_apps/");
   GURL::Replacements replace_host;
   std::string host_str("localhost");  // Must stay in scope with replace_host.
   replace_host.SetHostStr(host_str);
diff --git a/chrome/browser/extensions/lazy_background_page_apitest.cc b/chrome/browser/extensions/lazy_background_page_apitest.cc
index 8bb4b11..ba6f7de 100644
--- a/chrome/browser/extensions/lazy_background_page_apitest.cc
+++ b/chrome/browser/extensions/lazy_background_page_apitest.cc
@@ -30,6 +30,7 @@
 #include "content/public/test/browser_test_utils.h"
 #include "googleurl/src/gurl.h"
 #include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
 
 using extensions::Extension;
 
@@ -141,7 +142,7 @@
 }
 
 IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, BroadcastEvent) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   const Extension* extension = LoadExtensionAndWait("broadcast_event");
   ASSERT_TRUE(extension);
@@ -159,7 +160,7 @@
         chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED,
         content::NotificationService::AllSources());
   ui_test_utils::NavigateToURL(
-      browser(), test_server()->GetURL("files/extensions/test_file.html"));
+      browser(), embedded_test_server()->GetURL("/extensions/test_file.html"));
   page_complete.Wait();
 
   EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id_));
@@ -183,7 +184,7 @@
   // Open a tab to a URL that will fire a webNavigation event.
   LazyBackgroundObserver page_complete;
   ui_test_utils::NavigateToURL(
-      browser(), test_server()->GetURL("files/extensions/test_file.html"));
+      browser(), embedded_test_server()->GetURL("/extensions/test_file.html"));
   page_complete.Wait();
 }
 
@@ -235,7 +236,7 @@
 // are complete.
 IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, WaitForRequest) {
   host_resolver()->AddRule("*", "127.0.0.1");
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   LazyBackgroundObserver page_complete;
   ResultCatcher catcher;
@@ -376,7 +377,7 @@
 // Tests that messages from the content script activate the lazy background
 // page, and keep it alive until all channels are closed.
 IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, Messaging) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(LoadExtensionAndWait("messaging"));
 
   // Lazy Background Page doesn't exist yet.
@@ -389,7 +390,7 @@
   ResultCatcher catcher;
   LazyBackgroundObserver lazybg;
   ui_test_utils::NavigateToURL(
-      browser(), test_server()->GetURL("files/extensions/test_file.html"));
+      browser(), embedded_test_server()->GetURL("/extensions/test_file.html"));
   lazybg.WaitUntilLoaded();
 
   // Background page got the content script's message and is still loaded
diff --git a/chrome/browser/extensions/media_galleries_handler.cc b/chrome/browser/extensions/media_galleries_handler.cc
index d2349a8..a1a361a 100644
--- a/chrome/browser/extensions/media_galleries_handler.cc
+++ b/chrome/browser/extensions/media_galleries_handler.cc
@@ -78,10 +78,10 @@
 // |result|.
 bool LoadMediaGalleriesHandlers(
     const std::string& extension_id,
-    const ListValue* extension_actions,
+    const base::ListValue* extension_actions,
     MediaGalleriesHandler::List* result,
     string16* error) {
-  for (ListValue::const_iterator iter = extension_actions->begin();
+  for (base::ListValue::const_iterator iter = extension_actions->begin();
        iter != extension_actions->end();
        ++iter) {
     if (!(*iter)->IsType(Value::TYPE_DICTIONARY)) {
@@ -124,7 +124,7 @@
 
 bool MediaGalleriesHandlerParser::Parse(extensions::Extension* extension,
                                         string16* error) {
-  const ListValue* media_galleries_handlers_value = NULL;
+  const base::ListValue* media_galleries_handlers_value = NULL;
   if (!extension->manifest()->GetList(keys::kMediaGalleriesHandlers,
                                       &media_galleries_handlers_value)) {
     *error = ASCIIToUTF16(errors::kInvalidMediaGalleriesHandler);
diff --git a/chrome/browser/extensions/menu_manager.cc b/chrome/browser/extensions/menu_manager.cc
index b11b3e5..cb2ce0e 100644
--- a/chrome/browser/extensions/menu_manager.cc
+++ b/chrome/browser/extensions/menu_manager.cc
@@ -82,7 +82,7 @@
 }
 
 scoped_ptr<base::Value> MenuItemsToValue(const MenuItem::List& items) {
-  scoped_ptr<base::ListValue> list(new ListValue());
+  scoped_ptr<base::ListValue> list(new base::ListValue());
   for (size_t i = 0; i < items.size(); ++i)
     list->Append(items[i]->ToValue().release());
   return scoped_ptr<Value>(list.release());
@@ -94,7 +94,7 @@
   if (!dict.HasKey(key))
     return true;
 
-  const ListValue* list = NULL;
+  const base::ListValue* list = NULL;
   if (!dict.GetListWithoutPathExpansion(key, &list))
     return false;
 
@@ -606,7 +606,7 @@
   if (item->type() == MenuItem::RADIO)
     RadioItemSelected(item);
 
-  scoped_ptr<ListValue> args(new ListValue());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
 
   DictionaryValue* properties = new DictionaryValue();
   SetIdKeyValue(properties, "menuItemId", item->id());
@@ -673,8 +673,9 @@
   }
 
   {
-    scoped_ptr<Event> event(new Event(event_names::kOnContextMenus,
-                                      scoped_ptr<ListValue>(args->DeepCopy())));
+    scoped_ptr<Event> event(new Event(
+        event_names::kOnContextMenus,
+        scoped_ptr<base::ListValue>(args->DeepCopy())));
     event->restrict_to_profile = profile;
     event->user_gesture = EventRouter::USER_GESTURE_ENABLED;
     event_router->DispatchEventToExtension(item->extension_id(), event.Pass());
diff --git a/chrome/browser/extensions/menu_manager.h b/chrome/browser/extensions/menu_manager.h
index c4e56ac..764e861 100644
--- a/chrome/browser/extensions/menu_manager.h
+++ b/chrome/browser/extensions/menu_manager.h
@@ -109,11 +109,11 @@
       value_ |= context;
     }
 
-    scoped_ptr<Value> ToValue() const {
-      return scoped_ptr<Value>(Value::CreateIntegerValue(value_));
+    scoped_ptr<base::Value> ToValue() const {
+      return scoped_ptr<base::Value>(base::Value::CreateIntegerValue(value_));
     }
 
-    bool Populate(const Value& value) {
+    bool Populate(const base::Value& value) {
       int int_value;
       if (!value.GetAsInteger(&int_value) || int_value < 0)
         return false;
@@ -178,7 +178,7 @@
   // Returns a new MenuItem created from |value|, or NULL if there is
   // an error. The caller takes ownership of the MenuItem.
   static MenuItem* Populate(const std::string& extension_id,
-                            const DictionaryValue& value,
+                            const base::DictionaryValue& value,
                             std::string* error);
 
   // Sets any document and target URL patterns from |properties|.
diff --git a/chrome/browser/extensions/menu_manager_unittest.cc b/chrome/browser/extensions/menu_manager_unittest.cc
index f9adbd9..73c8357 100644
--- a/chrome/browser/extensions/menu_manager_unittest.cc
+++ b/chrome/browser/extensions/menu_manager_unittest.cc
@@ -214,13 +214,13 @@
   int contexts_value = 0;
   ASSERT_TRUE(contexts.ToValue()->GetAsInteger(&contexts_value));
 
-  ListValue* document_url_patterns(new ListValue());
+  base::ListValue* document_url_patterns(new base::ListValue());
   document_url_patterns->Append(
       Value::CreateStringValue("http://www.google.com/*"));
   document_url_patterns->Append(
       Value::CreateStringValue("http://www.reddit.com/*"));
 
-  ListValue* target_url_patterns(new ListValue());
+  base::ListValue* target_url_patterns(new base::ListValue());
   target_url_patterns->Append(
       Value::CreateStringValue("http://www.yahoo.com/*"));
   target_url_patterns->Append(
diff --git a/chrome/browser/extensions/message_handler.cc b/chrome/browser/extensions/message_handler.cc
index f0576e5..8389b9a 100644
--- a/chrome/browser/extensions/message_handler.cc
+++ b/chrome/browser/extensions/message_handler.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/extensions/message_handler.h"
 
-#include "base/values.h"
 #include "chrome/browser/extensions/api/messaging/message_service.h"
 #include "chrome/browser/extensions/extension_system.h"
 #include "chrome/browser/profiles/profile.h"
@@ -44,12 +43,12 @@
 }
 
 void MessageHandler::OnPostMessage(int port_id,
-                                   const base::ListValue& message) {
+                                   const std::string& message) {
   Profile* profile = Profile::FromBrowserContext(
       render_view_host()->GetProcess()->GetBrowserContext());
   MessageService* message_service = MessageService::Get(profile);
   if (message_service) {
-    message_service->PostMessage(port_id, make_scoped_ptr(message.DeepCopy()));
+    message_service->PostMessage(port_id, message);
   }
 }
 
diff --git a/chrome/browser/extensions/message_handler.h b/chrome/browser/extensions/message_handler.h
index 7142682..140105d 100644
--- a/chrome/browser/extensions/message_handler.h
+++ b/chrome/browser/extensions/message_handler.h
@@ -9,10 +9,6 @@
 
 #include "content/public/browser/render_view_host_observer.h"
 
-namespace base {
-class ListValue;
-}
-
 namespace extensions {
 
 // Filters and dispatches extension-related IPC messages that arrive from
@@ -37,7 +33,7 @@
 
  private:
   // Message handlers.
-  void OnPostMessage(int port_id, const base::ListValue& message);
+  void OnPostMessage(int port_id, const std::string& message);
 
   DISALLOW_COPY_AND_ASSIGN(MessageHandler);
 };
diff --git a/chrome/browser/extensions/pending_extension_manager.cc b/chrome/browser/extensions/pending_extension_manager.cc
index 15aac52..fcf1660 100644
--- a/chrome/browser/extensions/pending_extension_manager.cc
+++ b/chrome/browser/extensions/pending_extension_manager.cc
@@ -119,6 +119,26 @@
                           kIsFromSync, install_silently, kSyncLocation);
 }
 
+bool PendingExtensionManager::AddFromExtensionImport(
+    const std::string& id,
+    const GURL& update_url,
+    PendingExtensionInfo::ShouldAllowInstallPredicate should_allow_install) {
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  if (service_.GetInstalledExtension(id)) {
+    LOG(ERROR) << "Trying to add pending extension " << id
+               << " which already exists";
+    return false;
+  }
+
+  const bool kIsFromSync = false;
+  const bool kInstallSilently = true;
+  const Manifest::Location kManifestLocation = Manifest::INTERNAL;
+
+  return AddExtensionImpl(id, update_url, Version(), should_allow_install,
+                          kIsFromSync, kInstallSilently, kManifestLocation);
+}
+
 bool PendingExtensionManager::AddFromExternalUpdateUrl(
     const std::string& id,
     const GURL& update_url,
diff --git a/chrome/browser/extensions/pending_extension_manager.h b/chrome/browser/extensions/pending_extension_manager.h
index d275adf..41bf30c 100644
--- a/chrome/browser/extensions/pending_extension_manager.h
+++ b/chrome/browser/extensions/pending_extension_manager.h
@@ -80,6 +80,12 @@
       PendingExtensionInfo::ShouldAllowInstallPredicate should_allow_install,
       bool install_silently);
 
+  // Adds an extension that was depended on by another extension.
+  bool AddFromExtensionImport(
+      const std::string& id,
+      const GURL& update_url,
+      PendingExtensionInfo::ShouldAllowInstallPredicate should_allow_install);
+
   // Given an extension id and an update URL, schedule the extension
   // to be fetched, installed, and activated.
   bool AddFromExternalUpdateUrl(const std::string& id,
diff --git a/chrome/browser/extensions/permissions_updater.cc b/chrome/browser/extensions/permissions_updater.cc
index 46bb60f..a985332 100644
--- a/chrome/browser/extensions/permissions_updater.cc
+++ b/chrome/browser/extensions/permissions_updater.cc
@@ -101,7 +101,7 @@
       !ExtensionSystem::Get(profile_)->event_router())
     return;
 
-  scoped_ptr<ListValue> value(new ListValue());
+  scoped_ptr<base::ListValue> value(new base::ListValue());
   scoped_ptr<api::permissions::Permissions> permissions =
       PackPermissionSet(changed_permissions);
   value->Append(permissions->ToValue().release());
diff --git a/chrome/browser/extensions/platform_app_browsertest.cc b/chrome/browser/extensions/platform_app_browsertest.cc
index 2b88475..28168bb 100644
--- a/chrome/browser/extensions/platform_app_browsertest.cc
+++ b/chrome/browser/extensions/platform_app_browsertest.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "apps/shell_window.h"
 #include "base/bind.h"
 #include "base/file_util.h"
 #include "base/files/scoped_temp_dir.h"
@@ -29,7 +30,6 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/extensions/application_launch.h"
 #include "chrome/browser/ui/extensions/native_app_window.h"
-#include "chrome/browser/ui/extensions/shell_window.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "chrome/common/chrome_switches.h"
@@ -42,8 +42,10 @@
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/web_contents_view.h"
 #include "content/public/test/test_utils.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
 #include "googleurl/src/gurl.h"
 
+using apps::ShellWindow;
 using content::WebContents;
 using web_modal::WebContentsModalDialogManager;
 
@@ -303,7 +305,7 @@
 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, DisallowNavigation) {
   TabsAddedNotificationObserver observer(2);
 
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunPlatformAppTest("platform_apps/navigation")) << message_;
 
   observer.Wait();
@@ -315,7 +317,7 @@
 }
 
 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, Iframes) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunPlatformAppTest("platform_apps/iframes")) << message_;
 }
 
@@ -342,11 +344,11 @@
 
 // Tests that platform apps have isolated storage by default.
 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, Isolation) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   // Load a (non-app) page under the "localhost" origin that sets a cookie.
-  GURL set_cookie_url = test_server()->GetURL(
-      "files/extensions/platform_apps/isolation/set_cookie.html");
+  GURL set_cookie_url = embedded_test_server()->GetURL(
+      "/extensions/platform_apps/isolation/set_cookie.html");
   GURL::Replacements replace_host;
   std::string host_str("localhost");  // Must stay in scope with replace_host.
   replace_host.SetHostStr(host_str);
@@ -607,7 +609,7 @@
 #endif  // defined(OS_CHROMEOS)
 
 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, OpenLink) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   content::WindowedNotificationObserver observer(
       chrome::NOTIFICATION_TAB_ADDED,
       content::Source<content::WebContentsDelegate>(browser()));
@@ -646,6 +648,82 @@
   ASSERT_TRUE(RunPlatformAppTest("platform_apps/restore_state"));
 }
 
+IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
+                       ShellWindowAdjustBoundsToBeVisibleOnScreen) {
+  const Extension* extension = LoadAndLaunchPlatformApp("minimal");
+  ShellWindow* window = CreateShellWindow(extension);
+
+  // The screen bounds didn't change, the cached bounds didn't need to adjust.
+  gfx::Rect cached_bounds(80, 100, 400, 400);
+  gfx::Rect cached_screen_bounds(0, 0, 1600, 900);
+  gfx::Rect current_screen_bounds(0, 0, 1600, 900);
+  gfx::Size minimum_size(200, 200);
+  gfx::Rect bounds;
+  CallAdjustBoundsToBeVisibleOnScreenForShellWindow(window,
+                                                    cached_bounds,
+                                                    cached_screen_bounds,
+                                                    current_screen_bounds,
+                                                    minimum_size,
+                                                    &bounds);
+  EXPECT_EQ(bounds, cached_bounds);
+
+  // We have an empty screen bounds, the cached bounds didn't need to adjust.
+  gfx::Rect empty_screen_bounds;
+  CallAdjustBoundsToBeVisibleOnScreenForShellWindow(window,
+                                                    cached_bounds,
+                                                    empty_screen_bounds,
+                                                    current_screen_bounds,
+                                                    minimum_size,
+                                                    &bounds);
+  EXPECT_EQ(bounds, cached_bounds);
+
+  // Cached bounds is completely off the new screen bounds in horizontal
+  // locations. Expect to reposition the bounds.
+  gfx::Rect horizontal_out_of_screen_bounds(-800, 100, 400, 400);
+  CallAdjustBoundsToBeVisibleOnScreenForShellWindow(
+      window,
+      horizontal_out_of_screen_bounds,
+      gfx::Rect(-1366, 0, 1600, 900),
+      current_screen_bounds,
+      minimum_size,
+      &bounds);
+  EXPECT_EQ(bounds, gfx::Rect(0, 100, 400, 400));
+
+  // Cached bounds is completely off the new screen bounds in vertical
+  // locations. Expect to reposition the bounds.
+  gfx::Rect vertical_out_of_screen_bounds(10, 1000, 400, 400);
+  CallAdjustBoundsToBeVisibleOnScreenForShellWindow(
+      window,
+      vertical_out_of_screen_bounds,
+      gfx::Rect(-1366, 0, 1600, 900),
+      current_screen_bounds,
+      minimum_size,
+      &bounds);
+  EXPECT_EQ(bounds, gfx::Rect(10, 500, 400, 400));
+
+  // From a large screen resulotion to a small one. Expect it fit on screen.
+  gfx::Rect big_cache_bounds(10, 10, 1000, 1000);
+  CallAdjustBoundsToBeVisibleOnScreenForShellWindow(
+      window,
+      big_cache_bounds,
+      gfx::Rect(0, 0, 1600, 1000),
+      gfx::Rect(0, 0, 800, 600),
+      minimum_size,
+      &bounds);
+  EXPECT_EQ(bounds, gfx::Rect(0, 0, 800, 600));
+
+  // Don't resize the bounds smaller than minimum size, when the minimum size is
+  // larger than the screen.
+  CallAdjustBoundsToBeVisibleOnScreenForShellWindow(
+      window,
+      big_cache_bounds,
+      gfx::Rect(0, 0, 1600, 1000),
+      gfx::Rect(0, 0, 800, 600),
+      gfx::Size(900, 900),
+      &bounds);
+  EXPECT_EQ(bounds, gfx::Rect(0, 0, 900, 900));
+}
+
 namespace {
 
 class PlatformAppDevToolsBrowserTest : public PlatformAppBrowserTest {
diff --git a/chrome/browser/extensions/platform_app_browsertest_util.cc b/chrome/browser/extensions/platform_app_browsertest_util.cc
index a815326..2d1cdd0 100644
--- a/chrome/browser/extensions/platform_app_browsertest_util.cc
+++ b/chrome/browser/extensions/platform_app_browsertest_util.cc
@@ -9,6 +9,7 @@
 #include "chrome/browser/extensions/api/tabs/tabs_api.h"
 #include "chrome/browser/extensions/extension_function_test_utils.h"
 #include "chrome/browser/extensions/shell_window_registry.h"
+#include "chrome/browser/ui/apps/chrome_shell_window_delegate.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/extensions/application_launch.h"
 #include "chrome/browser/ui/extensions/native_app_window.h"
@@ -16,6 +17,7 @@
 #include "content/public/browser/notification_service.h"
 #include "content/public/test/test_utils.h"
 
+using apps::ShellWindow;
 using content::WebContents;
 
 namespace utils = extension_function_test_utils;
@@ -23,7 +25,7 @@
 namespace extensions {
 
 PlatformAppBrowserTest::PlatformAppBrowserTest() {
-  ShellWindow::DisableExternalOpenForTesting();
+  chrome::ChromeShellWindowDelegate::DisableExternalOpenForTesting();
 }
 
 void PlatformAppBrowserTest::SetUpCommandLine(CommandLine* command_line) {
@@ -146,13 +148,15 @@
     const Extension* extension) {
   ShellWindow::CreateParams params;
   return ShellWindow::Create(
-      browser()->profile(), extension, GURL(std::string()), params);
+      browser()->profile(), new chrome::ChromeShellWindowDelegate(),
+      extension, GURL(std::string()), params);
 }
 
 ShellWindow* PlatformAppBrowserTest::CreateShellWindowFromParams(
     const Extension* extension, const ShellWindow::CreateParams& params) {
   return ShellWindow::Create(
-      browser()->profile(), extension, GURL(std::string()), params);
+      browser()->profile(), new chrome::ChromeShellWindowDelegate(),
+      extension, GURL(std::string()), params);
 }
 
 void PlatformAppBrowserTest::CloseShellWindow(ShellWindow* window) {
@@ -163,6 +167,20 @@
   destroyed_observer.Wait();
 }
 
+void PlatformAppBrowserTest::CallAdjustBoundsToBeVisibleOnScreenForShellWindow(
+    ShellWindow* window,
+    const gfx::Rect& cached_bounds,
+    const gfx::Rect& cached_screen_bounds,
+    const gfx::Rect& current_screen_bounds,
+    const gfx::Size& minimum_size,
+    gfx::Rect* bounds) {
+  window->AdjustBoundsToBeVisibleOnScreen(cached_bounds,
+                                          cached_screen_bounds,
+                                          current_screen_bounds,
+                                          minimum_size,
+                                          bounds);
+}
+
 void ExperimentalPlatformAppBrowserTest::SetUpCommandLine(
     CommandLine* command_line) {
   PlatformAppBrowserTest::SetUpCommandLine(command_line);
diff --git a/chrome/browser/extensions/platform_app_browsertest_util.h b/chrome/browser/extensions/platform_app_browsertest_util.h
index d484909..6cc179b 100644
--- a/chrome/browser/extensions/platform_app_browsertest_util.h
+++ b/chrome/browser/extensions/platform_app_browsertest_util.h
@@ -6,15 +6,14 @@
 #define CHROME_BROWSER_EXTENSIONS_PLATFORM_APP_BROWSERTEST_UTIL_H_
 
 
+#include "apps/shell_window.h"
 #include "chrome/browser/extensions/extension_apitest.h"
-#include "chrome/browser/ui/extensions/shell_window.h"
 
 namespace content {
 class WebContents;
 }
 
 class CommandLine;
-class ShellWindow;
 
 namespace extensions {
 class Extension;
@@ -41,7 +40,7 @@
 
   // Gets the first shell window that is found (most tests only deal with one
   // platform app window, so this is good enough).
-  ShellWindow* GetFirstShellWindow();
+  apps::ShellWindow* GetFirstShellWindow();
 
   // Runs chrome.windows.getAll for the given extension and returns the number
   // of windows that the function returns.
@@ -64,13 +63,23 @@
   void SetCommandLineArg(const std::string& test_file);
 
   // Creates an empty shell window for |extension|.
-  ShellWindow* CreateShellWindow(const Extension* extension);
+  apps::ShellWindow* CreateShellWindow(const Extension* extension);
 
-  ShellWindow* CreateShellWindowFromParams(
-      const Extension* extension, const ShellWindow::CreateParams& params);
+  apps::ShellWindow* CreateShellWindowFromParams(
+      const Extension* extension,
+      const apps::ShellWindow::CreateParams& params);
 
   // Closes |window| and waits until it's gone.
-  void CloseShellWindow(ShellWindow* window);
+  void CloseShellWindow(apps::ShellWindow* window);
+
+  // Call AdjustBoundsToBeVisibleOnScreen of |window|.
+  void CallAdjustBoundsToBeVisibleOnScreenForShellWindow(
+      apps::ShellWindow* window,
+      const gfx::Rect& cached_bounds,
+      const gfx::Rect& cached_screen_bounds,
+      const gfx::Rect& current_screen_bounds,
+      const gfx::Size& minimum_size,
+      gfx::Rect* bounds);
 };
 
 class ExperimentalPlatformAppBrowserTest : public PlatformAppBrowserTest {
@@ -78,6 +87,6 @@
   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE;
 };
 
-}
+}  // namespace extensions
 
 #endif  // CHROME_BROWSER_EXTENSIONS_PLATFORM_APP_BROWSERTEST_UTIL_H_
diff --git a/chrome/browser/extensions/process_management_browsertest.cc b/chrome/browser/extensions/process_management_browsertest.cc
index d6ea919..bb54aeb 100644
--- a/chrome/browser/extensions/process_management_browsertest.cc
+++ b/chrome/browser/extensions/process_management_browsertest.cc
@@ -20,6 +20,7 @@
 #include "content/public/browser/site_instance.h"
 #include "content/public/browser/web_contents.h"
 #include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
 
 using content::NavigationController;
 using content::WebContents;
@@ -53,7 +54,7 @@
   content::RenderProcessHost::SetMaxRendererProcessCount(1);
 
   host_resolver()->AddRule("*", "127.0.0.1");
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("isolated_apps/app1")));
   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("isolated_apps/app2")));
@@ -63,8 +64,8 @@
 
   // The app under test acts on URLs whose host is "localhost",
   // so the URLs we navigate to must have host "localhost".
-  GURL base_url = test_server()->GetURL(
-      "files/extensions/");
+  GURL base_url = embedded_test_server()->GetURL(
+      "/extensions/");
   GURL::Replacements replace_host;
   std::string host_str("localhost");  // Must stay in scope with replace_host.
   replace_host.SetHostStr(host_str);
@@ -194,12 +195,12 @@
   content::RenderProcessHost::SetMaxRendererProcessCount(6);
 
   host_resolver()->AddRule("*", "127.0.0.1");
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   // The app under test acts on URLs whose host is "localhost",
   // so the URLs we navigate to must have host "localhost".
-  GURL base_url = test_server()->GetURL(
-      "files/extensions/");
+  GURL base_url = embedded_test_server()->GetURL(
+      "/extensions/");
   GURL::Replacements replace_host;
   std::string host_str("localhost");  // Must stay in scope with replace_host.
   replace_host.SetHostStr(host_str);
diff --git a/chrome/browser/extensions/sandboxed_unpacker.cc b/chrome/browser/extensions/sandboxed_unpacker.cc
index 80241b7..91b4cbc 100644
--- a/chrome/browser/extensions/sandboxed_unpacker.cc
+++ b/chrome/browser/extensions/sandboxed_unpacker.cc
@@ -141,7 +141,7 @@
     *temp_dir = normalized_temp_file.DirName();
   }
   // Clean up the temp file.
-  file_util::Delete(temp_file, false);
+  base::Delete(temp_file, false);
 
   return normalized;
 }
@@ -661,7 +661,7 @@
               ASCIIToUTF16("INVALID_PATH_FOR_BROWSER_IMAGE")));
       return false;
     }
-    if (!file_util::Delete(extension_root_.Append(path), false)) {
+    if (!base::Delete(extension_root_.Append(path), false)) {
       // Error removing old image file.
       ReportFailure(
           ERROR_REMOVING_OLD_IMAGE_FILE,
diff --git a/chrome/browser/extensions/sandboxed_unpacker.h b/chrome/browser/extensions/sandboxed_unpacker.h
index d4ef975..4a694c8 100644
--- a/chrome/browser/extensions/sandboxed_unpacker.h
+++ b/chrome/browser/extensions/sandboxed_unpacker.h
@@ -10,7 +10,7 @@
 #include "base/files/file_path.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/memory/ref_counted.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/common/extensions/manifest.h"
 #include "content/public/browser/utility_process_host_client.h"
 
diff --git a/chrome/browser/extensions/scoped_gaia_auth_extension.cc b/chrome/browser/extensions/scoped_gaia_auth_extension.cc
index 33464fa..57e160e 100644
--- a/chrome/browser/extensions/scoped_gaia_auth_extension.cc
+++ b/chrome/browser/extensions/scoped_gaia_auth_extension.cc
@@ -34,7 +34,7 @@
   if (command_line->HasSwitch(switches::kAuthExtensionPath)) {
     base::FilePath auth_extension_path =
         command_line->GetSwitchValuePath(switches::kAuthExtensionPath);
-    component_loader->Add(IDR_GAIA_TEST_AUTH_MANIFEST, auth_extension_path);
+    component_loader->Add(IDR_GAIA_AUTH_MANIFEST, auth_extension_path);
     return;
   }
 
@@ -42,7 +42,7 @@
 #if defined(OS_CHROMEOS)
   chromeos::system::StatisticsProvider* provider =
       chromeos::system::StatisticsProvider::GetInstance();
-  provider->GetMachineFlag(chromeos::kOemKeyboardDrivenOobeKey,
+  provider->GetMachineFlag(chromeos::system::kOemKeyboardDrivenOobeKey,
                            &force_keyboard_oobe);
 #endif // OS_CHROMEOS
   if (force_keyboard_oobe) {
diff --git a/chrome/browser/extensions/shell_window_registry.cc b/chrome/browser/extensions/shell_window_registry.cc
index 4e4c02a..38a8d38 100644
--- a/chrome/browser/extensions/shell_window_registry.cc
+++ b/chrome/browser/extensions/shell_window_registry.cc
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "apps/shell_window.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/extensions/shell_window_registry.h"
 #include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/extensions/native_app_window.h"
-#include "chrome/browser/ui/extensions/shell_window.h"
 #include "chrome/common/extensions/extension.h"
 #include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
 #include "content/public/browser/devtools_agent_host.h"
@@ -17,6 +17,8 @@
 #include "content/public/browser/site_instance.h"
 #include "content/public/browser/web_contents.h"
 
+using apps::ShellWindow;
+
 namespace {
 
 // Create a key that identifies a ShellWindow in a RenderViewHost across App
@@ -41,7 +43,7 @@
   return key;
 }
 
-}
+}  // namespace
 
 namespace extensions {
 
diff --git a/chrome/browser/extensions/shell_window_registry.h b/chrome/browser/extensions/shell_window_registry.h
index ba3dd76..da1072c 100644
--- a/chrome/browser/extensions/shell_window_registry.h
+++ b/chrome/browser/extensions/shell_window_registry.h
@@ -16,7 +16,10 @@
 #include "ui/gfx/native_widget_types.h"
 
 class Profile;
+
+namespace apps {
 class ShellWindow;
+}
 
 namespace content {
 class DevToolsAgentHost;
@@ -37,17 +40,17 @@
   class Observer {
    public:
     // Called just after a shell window was added.
-    virtual void OnShellWindowAdded(ShellWindow* shell_window) = 0;
+    virtual void OnShellWindowAdded(apps::ShellWindow* shell_window) = 0;
     // Called when the window icon changes.
-    virtual void OnShellWindowIconChanged(ShellWindow* shell_window) = 0;
+    virtual void OnShellWindowIconChanged(apps::ShellWindow* shell_window) = 0;
     // Called just after a shell window was removed.
-    virtual void OnShellWindowRemoved(ShellWindow* shell_window) = 0;
+    virtual void OnShellWindowRemoved(apps::ShellWindow* shell_window) = 0;
 
    protected:
     virtual ~Observer() {}
   };
 
-  typedef std::list<ShellWindow*> ShellWindowList;
+  typedef std::list<apps::ShellWindow*> ShellWindowList;
   typedef ShellWindowList::const_iterator const_iterator;
   typedef std::set<std::string> InspectedWindowSet;
 
@@ -58,11 +61,11 @@
   // a convenience wrapper around ShellWindowRegistry::Factory::GetForProfile.
   static ShellWindowRegistry* Get(Profile* profile);
 
-  void AddShellWindow(ShellWindow* shell_window);
-  void ShellWindowIconChanged(ShellWindow* shell_window);
+  void AddShellWindow(apps::ShellWindow* shell_window);
+  void ShellWindowIconChanged(apps::ShellWindow* shell_window);
   // Called by |shell_window| when it is activated.
-  void ShellWindowActivated(ShellWindow* shell_window);
-  void RemoveShellWindow(ShellWindow* shell_window);
+  void ShellWindowActivated(apps::ShellWindow* shell_window);
+  void RemoveShellWindow(apps::ShellWindow* shell_window);
 
   void AddObserver(Observer* observer);
   void RemoveObserver(Observer* observer);
@@ -72,19 +75,22 @@
   const ShellWindowList& shell_windows() const { return shell_windows_; }
 
   // Helper functions to find shell windows with particular attributes.
-  ShellWindow* GetShellWindowForRenderViewHost(
+  apps::ShellWindow* GetShellWindowForRenderViewHost(
       content::RenderViewHost* render_view_host) const;
-  ShellWindow* GetShellWindowForNativeWindow(gfx::NativeWindow window) const;
+  apps::ShellWindow* GetShellWindowForNativeWindow(
+      gfx::NativeWindow window) const;
   // Returns an app window for the given app, or NULL if no shell windows are
   // open. If there is a window for the given app that is active, that one will
   // be returned, otherwise an arbitrary window will be returned.
-  ShellWindow* GetCurrentShellWindowForApp(const std::string& app_id) const;
+  apps::ShellWindow* GetCurrentShellWindowForApp(
+      const std::string& app_id) const;
   // Returns an app window for the given app and window key, or NULL if no shell
   // window with the key are open. If there is a window for the given app and
   // key that is active, that one will be returned, otherwise an arbitrary
   // window will be returned.
-  ShellWindow* GetShellWindowForAppAndKey(const std::string& app_id,
-                                          const std::string& window_key) const;
+  apps::ShellWindow* GetShellWindowForAppAndKey(
+      const std::string& app_id,
+      const std::string& window_key) const;
 
   // Returns whether a ShellWindow's ID was last known to have a DevToolsAgent
   // attached to it, which should be restored during a reload of a corresponding
@@ -92,7 +98,7 @@
   bool HadDevToolsAttached(content::RenderViewHost* render_view_host) const;
 
   // Returns the shell window for |window|, looking in all profiles.
-  static ShellWindow* GetShellWindowForNativeWindowAnyProfile(
+  static apps::ShellWindow* GetShellWindowForNativeWindowAnyProfile(
       gfx::NativeWindow window);
 
   // Returns true if the number of shell windows registered across all profiles
@@ -126,11 +132,11 @@
  private:
   // Ensures the specified |shell_window| is included in |shell_windows_|.
   // Otherwise adds |shell_window| to the back of |shell_windows_|.
-  void AddShellWindowToList(ShellWindow* shell_window);
+  void AddShellWindowToList(apps::ShellWindow* shell_window);
 
   // Bring |shell_window| to the front of |shell_windows_|. If it is not in the
   // list, add it first.
-  void BringToFront(ShellWindow* shell_window);
+  void BringToFront(apps::ShellWindow* shell_window);
 
   Profile* profile_;
   ShellWindowList shell_windows_;
diff --git a/chrome/browser/extensions/stubs_apitest.cc b/chrome/browser/extensions/stubs_apitest.cc
index 7a5a407..982d317 100644
--- a/chrome/browser/extensions/stubs_apitest.cc
+++ b/chrome/browser/extensions/stubs_apitest.cc
@@ -6,7 +6,7 @@
 #include "chrome/common/chrome_paths.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "googleurl/src/gurl.h"
-#include "net/test/spawned_test_server/spawned_test_server.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
 
 // Tests that we throw errors when you try using extension APIs that aren't
 // supported in content scripts.
@@ -17,13 +17,13 @@
 #define MAYBE_Stubs Stubs
 #endif
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MAYBE_Stubs) {
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   ASSERT_TRUE(RunExtensionTest("stubs")) << message_;
 
   // Navigate to a simple http:// page, which should get the content script
   // injected and run the rest of the test.
-  GURL url(test_server()->GetURL("file/extensions/test_file.html"));
+  GURL url(embedded_test_server()->GetURL("/extensions/test_file.html"));
   ui_test_utils::NavigateToURL(browser(), url);
 
   ResultCatcher catcher;
diff --git a/chrome/browser/extensions/token_cache/token_cache_service.h b/chrome/browser/extensions/token_cache/token_cache_service.h
index 70ee415..bab555e 100644
--- a/chrome/browser/extensions/token_cache/token_cache_service.h
+++ b/chrome/browser/extensions/token_cache/token_cache_service.h
@@ -10,7 +10,7 @@
 
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
diff --git a/chrome/browser/extensions/token_cache/token_cache_service_unittest.cc b/chrome/browser/extensions/token_cache/token_cache_service_unittest.cc
index 83ffaaf..fb42678 100644
--- a/chrome/browser/extensions/token_cache/token_cache_service_unittest.cc
+++ b/chrome/browser/extensions/token_cache/token_cache_service_unittest.cc
@@ -4,7 +4,7 @@
 
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/extensions/token_cache/token_cache_service.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "content/public/browser/notification_details.h"
diff --git a/chrome/browser/extensions/updater/extension_downloader.cc b/chrome/browser/extensions/updater/extension_downloader.cc
index 30ef6d6..0af857d 100644
--- a/chrome/browser/extensions/updater/extension_downloader.cc
+++ b/chrome/browser/extensions/updater/extension_downloader.cc
@@ -17,7 +17,7 @@
 #include "base/platform_file.h"
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/version.h"
 #include "chrome/browser/extensions/updater/request_queue_impl.h"
 #include "chrome/browser/extensions/updater/safe_manifest_parser.h"
diff --git a/chrome/browser/extensions/updater/extension_downloader_delegate.h b/chrome/browser/extensions/updater/extension_downloader_delegate.h
index 58e0dc9..99f5d6e 100644
--- a/chrome/browser/extensions/updater/extension_downloader_delegate.h
+++ b/chrome/browser/extensions/updater/extension_downloader_delegate.h
@@ -8,7 +8,7 @@
 #include <set>
 #include <string>
 
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/extensions/updater/manifest_fetch_data.h"
 
 class GURL;
diff --git a/chrome/browser/extensions/updater/extension_updater.h b/chrome/browser/extensions/updater/extension_updater.h
index ffb40e9..94e0176 100644
--- a/chrome/browser/extensions/updater/extension_updater.h
+++ b/chrome/browser/extensions/updater/extension_updater.h
@@ -17,8 +17,8 @@
 #include "base/gtest_prod_util.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/extensions/updater/extension_downloader_delegate.h"
 #include "chrome/browser/extensions/updater/manifest_fetch_data.h"
 #include "content/public/browser/notification_observer.h"
diff --git a/chrome/browser/extensions/updater/request_queue.h b/chrome/browser/extensions/updater/request_queue.h
index 2ec72f5..c147881 100644
--- a/chrome/browser/extensions/updater/request_queue.h
+++ b/chrome/browser/extensions/updater/request_queue.h
@@ -11,8 +11,8 @@
 #include "base/callback.h"
 #include "base/memory/linked_ptr.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "net/base/backoff_entry.h"
 
 namespace extensions {
diff --git a/chrome/browser/extensions/web_view_browsertest.cc b/chrome/browser/extensions/web_view_browsertest.cc
index bfe49c3..d3400ae 100644
--- a/chrome/browser/extensions/web_view_browsertest.cc
+++ b/chrome/browser/extensions/web_view_browsertest.cc
@@ -20,12 +20,21 @@
 #include "content/public/browser/web_contents_delegate.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/fake_speech_recognition_manager.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "net/test/embedded_test_server/http_request.h"
+#include "net/test/embedded_test_server/http_response.h"
 #include "ui/compositor/compositor_setup.h"
 #include "ui/gl/gl_switches.h"
 
 using prerender::PrerenderLinkManager;
 using prerender::PrerenderLinkManagerFactory;
 
+namespace {
+  const char kRedirectResponsePath[] = "/server-redirect";
+  const char kRedirectResponseFullPath[] =
+      "/extensions/platform_apps/web_view/shim/guest_redirect.html";
+}  // namespace
+
 // This class intercepts media access request from the embedder. The request
 // should be triggered only if the embedder API (from tests) allows the request
 // in Javascript.
@@ -204,26 +213,26 @@
 
     navigate_to_url = navigate_to_url.ReplaceComponents(replace_host);
 
-    GURL tag_url1 = test_server()->GetURL(
-        "files/extensions/platform_apps/web_view/isolation/cookie.html");
+    GURL tag_url1 = embedded_test_server()->GetURL(
+        "/extensions/platform_apps/web_view/isolation/cookie.html");
     tag_url1 = tag_url1.ReplaceComponents(replace_host);
-    GURL tag_url2 = test_server()->GetURL(
-        "files/extensions/platform_apps/web_view/isolation/cookie2.html");
+    GURL tag_url2 = embedded_test_server()->GetURL(
+        "/extensions/platform_apps/web_view/isolation/cookie2.html");
     tag_url2 = tag_url2.ReplaceComponents(replace_host);
-    GURL tag_url3 = test_server()->GetURL(
-        "files/extensions/platform_apps/web_view/isolation/storage1.html");
+    GURL tag_url3 = embedded_test_server()->GetURL(
+        "/extensions/platform_apps/web_view/isolation/storage1.html");
     tag_url3 = tag_url3.ReplaceComponents(replace_host);
-    GURL tag_url4 = test_server()->GetURL(
-        "files/extensions/platform_apps/web_view/isolation/storage2.html");
+    GURL tag_url4 = embedded_test_server()->GetURL(
+        "/extensions/platform_apps/web_view/isolation/storage2.html");
     tag_url4 = tag_url4.ReplaceComponents(replace_host);
-    GURL tag_url5 = test_server()->GetURL(
-        "files/extensions/platform_apps/web_view/isolation/storage1.html#p1");
+    GURL tag_url5 = embedded_test_server()->GetURL(
+        "/extensions/platform_apps/web_view/isolation/storage1.html#p1");
     tag_url5 = tag_url5.ReplaceComponents(replace_host);
-    GURL tag_url6 = test_server()->GetURL(
-        "files/extensions/platform_apps/web_view/isolation/storage1.html#p2");
+    GURL tag_url6 = embedded_test_server()->GetURL(
+        "/extensions/platform_apps/web_view/isolation/storage1.html#p2");
     tag_url6 = tag_url6.ReplaceComponents(replace_host);
-    GURL tag_url7 = test_server()->GetURL(
-        "files/extensions/platform_apps/web_view/isolation/storage1.html#p3");
+    GURL tag_url7 = embedded_test_server()->GetURL(
+        "/extensions/platform_apps/web_view/isolation/storage1.html#p3");
     tag_url7 = tag_url7.ReplaceComponents(replace_host);
 
     ui_test_utils::NavigateToURLWithDisposition(
@@ -352,24 +361,44 @@
     EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
   }
 
-  void GeolocationTestHelper(const std::string& test_name,
-                             const std::string& app_location) {
-    ASSERT_TRUE(StartTestServer());  // For serving guest pages.
+  // Handles |request| by serving a redirect response.
+  static scoped_ptr<net::test_server::HttpResponse> RedirectResponseHandler(
+      const std::string& path,
+      const GURL& redirect_target,
+      const net::test_server::HttpRequest& request) {
+    if (!StartsWithASCII(path, request.relative_url, true))
+      return scoped_ptr<net::test_server::HttpResponse>();
+
+    scoped_ptr<net::test_server::BasicHttpResponse> http_response(
+        new net::test_server::BasicHttpResponse);
+    http_response->set_code(net::HTTP_MOVED_PERMANENTLY);
+    http_response->AddCustomHeader("Location", redirect_target.spec());
+    return http_response.PassAs<net::test_server::HttpResponse>();
+  }
+
+  void TestHelper(const std::string& test_name,
+                  const std::string& test_passed_msg,
+                  const std::string& test_failed_msg,
+                  const std::string& app_location) {
+    ASSERT_TRUE(StartEmbeddedTestServer());  // For serving guest pages.
     ExtensionTestMessageListener launched_listener("Launched", false);
     LoadAndLaunchPlatformApp(app_location.c_str());
     ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
 
+    embedded_test_server()->RegisterRequestHandler(
+        base::Bind(&WebViewTest::RedirectResponseHandler,
+                   kRedirectResponsePath,
+                   embedded_test_server()->GetURL(kRedirectResponseFullPath)));
+
     content::WebContents* embedder_web_contents =
         GetFirstShellWindowWebContents();
     ASSERT_TRUE(embedder_web_contents);
 
-    ExtensionTestMessageListener done_listener("DoneGeolocationTest.PASSED",
-                                               false);
-    done_listener.AlsoListenForFailureMessage("DoneGeolocationTest.FAILED");
+    ExtensionTestMessageListener done_listener(test_passed_msg, false);
+    done_listener.AlsoListenForFailureMessage(test_failed_msg);
     EXPECT_TRUE(content::ExecuteScript(
                     embedder_web_contents,
-                    base::StringPrintf("runGeolocationTest('%s')",
-                                       test_name.c_str())));
+                    base::StringPrintf("runTest('%s')", test_name.c_str())));
     ASSERT_TRUE(done_listener.WaitUntilSatisfied());
   }
 
@@ -379,7 +408,7 @@
     std::string host_str("localhost");  // Must stay in scope with replace_host.
     replace_host.SetHostStr(host_str);
 
-    GURL guest_url = test_server()->GetURL(guest_path);
+    GURL guest_url = embedded_test_server()->GetURL(guest_path);
     guest_url = guest_url.ReplaceComponents(replace_host);
 
     ui_test_utils::UrlLoadObserver guest_observer(
@@ -407,7 +436,7 @@
   // Runs media_access/deny tests, each of them are run separately otherwise
   // they timeout (mostly on Windows).
   void MediaAccessAPIDenyTestHelper(const std::string& test_name) {
-    ASSERT_TRUE(StartTestServer());  // For serving guest pages.
+    ASSERT_TRUE(StartEmbeddedTestServer());  // For serving guest pages.
     ExtensionTestMessageListener loaded_listener("loaded", false);
     LoadAndLaunchPlatformApp("web_view/media_access/deny");
     ASSERT_TRUE(loaded_listener.WaitUntilSatisfied());
@@ -430,17 +459,146 @@
       fake_speech_recognition_manager_;
 };
 
-// This test is flaky on Windows, Chrome OS, and Mac (all platforms that
-// have threaded compositing enabled).
-// http://crbug.com/176122
-#if defined(OS_WIN) || defined(OS_CHROMEOS) || defined(OS_MACOSX)
-#define MAYBE_Shim DISABLED_Shim
-#else
-#define MAYBE_Shim Shim
-#endif
-IN_PROC_BROWSER_TEST_F(WebViewTest, MAYBE_Shim) {
-  ASSERT_TRUE(StartTestServer());
-  ASSERT_TRUE(RunPlatformAppTest("platform_apps/web_view/shim")) << message_;
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestSize) {
+  TestHelper("testSize",
+             "DoneShimTest.PASSED",
+             "DoneShimTest.FAILED",
+             "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestAPIMethodExistence) {
+  TestHelper("testAPIMethodExistence",
+             "DoneShimTest.PASSED",
+             "DoneShimTest.FAILED",
+             "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestEventName) {
+  TestHelper("testEventName",
+             "DoneShimTest.PASSED",
+             "DoneShimTest.FAILED",
+             "web_view/shim");
+}
+
+// WebViewTest.Shim_TestDestroyOnEventListener is flaky, so disable it.
+// http://crbug.com/255106
+IN_PROC_BROWSER_TEST_F(WebViewTest, DISABLED_Shim_TestDestroyOnEventListener) {
+  TestHelper("testDestroyOnEventListener",
+             "DoneShimTest.PASSED",
+             "DoneShimTest.FAILED",
+             "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestCannotMutateEventName) {
+  TestHelper("testCannotMutateEventName",
+             "DoneShimTest.PASSED",
+             "DoneShimTest.FAILED",
+             "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestPartitionRaisesException) {
+  TestHelper("testPartitionRaisesException",
+             "DoneShimTest.PASSED",
+             "DoneShimTest.FAILED",
+             "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestExecuteScriptFail) {
+  TestHelper("testExecuteScriptFail",
+             "DoneShimTest.PASSED",
+             "DoneShimTest.FAILED",
+             "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestExecuteScript) {
+  TestHelper("testExecuteScript",
+             "DoneShimTest.PASSED",
+             "DoneShimTest.FAILED",
+             "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestTerminateAfterExit) {
+  TestHelper("testTerminateAfterExit",
+             "DoneShimTest.PASSED",
+             "DoneShimTest.FAILED",
+             "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestAssignSrcAfterCrash) {
+  TestHelper("testAssignSrcAfterCrash",
+             "DoneShimTest.PASSED",
+             "DoneShimTest.FAILED",
+             "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestRemoveSrcAttribute) {
+  TestHelper("testRemoveSrcAttribute",
+             "DoneShimTest.PASSED",
+             "DoneShimTest.FAILED",
+             "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestBrowserPluginNotAllowed) {
+  TestHelper("testBrowserPluginNotAllowed",
+             "DoneShimTest.PASSED",
+             "DoneShimTest.FAILED",
+             "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestNewWindow) {
+  TestHelper("testNewWindow",
+             "DoneShimTest.PASSED",
+             "DoneShimTest.FAILED",
+             "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestNewWindowTwoListeners) {
+  TestHelper("testNewWindowTwoListeners",
+             "DoneShimTest.PASSED",
+             "DoneShimTest.FAILED",
+             "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestNewWindowNoPreventDefault) {
+  TestHelper("testNewWindowNoPreventDefault",
+             "DoneShimTest.PASSED",
+             "DoneShimTest.FAILED",
+             "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestNewWindowNoReferrerLink) {
+  TestHelper("testNewWindowNoReferrerLink",
+             "DoneShimTest.PASSED",
+             "DoneShimTest.FAILED",
+             "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestContentLoadEvent) {
+  TestHelper("testContentLoadEvent",
+             "DoneShimTest.PASSED",
+             "DoneShimTest.FAILED",
+             "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestWebRequestAPI) {
+  TestHelper("testWebRequestAPI",
+             "DoneShimTest.PASSED",
+             "DoneShimTest.FAILED",
+             "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestLoadStartLoadRedirect) {
+  TestHelper("testLoadStartLoadRedirect",
+             "DoneShimTest.PASSED",
+             "DoneShimTest.FAILED",
+             "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestGetProcessId) {
+  TestHelper("testGetProcessId",
+             "DoneShimTest.PASSED",
+             "DoneShimTest.FAILED",
+             "web_view/shim");
 }
 
 IN_PROC_BROWSER_TEST_F(WebViewTest, ShimSrcAttribute) {
@@ -452,10 +610,10 @@
 // This test is here rather than in PrerenderBrowserTest for testing convenience
 // only. If it breaks then this is a bug in the prerenderer.
 IN_PROC_BROWSER_TEST_F(WebViewTest, NoPrerenderer) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   content::WebContents* guest_web_contents =
       LoadGuest(
-          "files/extensions/platform_apps/web_view/noprerenderer/guest.html",
+          "/extensions/platform_apps/web_view/noprerenderer/guest.html",
           "web_view/noprerenderer");
   ASSERT_TRUE(guest_web_contents != NULL);
 
@@ -471,7 +629,7 @@
 // multiple webview tags. Each tag sets a cookie and the test checks the proper
 // storage isolation is enforced.
 IN_PROC_BROWSER_TEST_F(WebViewTest, CookieIsolation) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   const std::string kExpire =
       "var expire = new Date(Date.now() + 24 * 60 * 60 * 1000);";
   std::string cookie_script1(kExpire);
@@ -485,8 +643,8 @@
   std::string host_str("localhost");  // Must stay in scope with replace_host.
   replace_host.SetHostStr(host_str);
 
-  GURL set_cookie_url = test_server()->GetURL(
-      "files/extensions/platform_apps/isolation/set_cookie.html");
+  GURL set_cookie_url = embedded_test_server()->GetURL(
+      "/extensions/platform_apps/isolation/set_cookie.html");
   set_cookie_url = set_cookie_url.ReplaceComponents(replace_host);
 
   // The first two partitions will be used to set cookies and ensure they are
@@ -537,7 +695,7 @@
 // This tests that in-memory storage partitions are reset on browser restart,
 // but persistent ones maintain state for cookies and HTML5 storage.
 IN_PROC_BROWSER_TEST_F(WebViewTest, PRE_StoragePersistence) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   const std::string kExpire =
       "var expire = new Date(Date.now() + 24 * 60 * 60 * 1000);";
   std::string cookie_script1(kExpire);
@@ -622,7 +780,7 @@
 // This is the post-reset portion of the StoragePersistence test.  See
 // PRE_StoragePersistence for main comment.
 IN_PROC_BROWSER_TEST_F(WebViewTest, DISABLED_StoragePersistence) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   // We don't care where the main browser is on this test.
   GURL blank_url("about:blank");
@@ -692,8 +850,8 @@
 // entries, which the test checks to ensure proper storage isolation is
 // enforced.
 IN_PROC_BROWSER_TEST_F(WebViewTest, MAYBE_DOMStorageIsolation) {
-  ASSERT_TRUE(StartTestServer());
-  GURL regular_url = test_server()->GetURL("files/title1.html");
+  ASSERT_TRUE(StartEmbeddedTestServer());
+  GURL regular_url = embedded_test_server()->GetURL("/title1.html");
 
   std::string output;
   std::string get_local_storage("window.domAutomationController.send("
@@ -786,8 +944,8 @@
 // an app with multiple webview tags and each tag creates an IndexedDB record,
 // which the test checks to ensure proper storage isolation is enforced.
 IN_PROC_BROWSER_TEST_F(WebViewTest, MAYBE_IndexedDBIsolation) {
-  ASSERT_TRUE(StartTestServer());
-  GURL regular_url = test_server()->GetURL("files/title1.html");
+  ASSERT_TRUE(StartEmbeddedTestServer());
+  GURL regular_url = embedded_test_server()->GetURL("/title1.html");
 
   content::WebContents* default_tag_contents1;
   content::WebContents* default_tag_contents2;
@@ -899,7 +1057,7 @@
 }
 
 void WebViewTest::MediaAccessAPIAllowTestHelper(const std::string& test_name) {
-  ASSERT_TRUE(StartTestServer());  // For serving guest pages.
+  ASSERT_TRUE(StartEmbeddedTestServer());  // For serving guest pages.
   ExtensionTestMessageListener launched_listener("Launched", false);
   LoadAndLaunchPlatformApp("web_view/media_access/allow");
   ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
@@ -941,16 +1099,16 @@
 // Checks that window.screenX/screenY/screenLeft/screenTop works correctly for
 // guests.
 IN_PROC_BROWSER_TEST_F(WebViewTest, ScreenCoordinates) {
-  ASSERT_TRUE(StartTestServer());  // For serving guest pages.
+  ASSERT_TRUE(StartEmbeddedTestServer());  // For serving guest pages.
   ASSERT_TRUE(RunPlatformAppTestWithArg(
       "platform_apps/web_view/common", "screen_coordinates"))
           << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(WebViewTest, SpeechRecognition) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   content::WebContents* guest_web_contents = LoadGuest(
-      "files/extensions/platform_apps/web_view/speech/guest.html",
+      "/extensions/platform_apps/web_view/speech/guest.html",
       "web_view/speech");
   ASSERT_TRUE(guest_web_contents);
 
@@ -970,7 +1128,7 @@
   const extensions::Extension* extension =
       LoadAndLaunchPlatformApp("web_view/teardown");
   ASSERT_TRUE(first_loaded_listener.WaitUntilSatisfied());
-  ShellWindow* window = NULL;
+  apps::ShellWindow* window = NULL;
   if (!GetShellWindowCount())
     window = CreateShellWindow(extension);
   else
@@ -988,13 +1146,17 @@
 // No matter what the API does, geolocation permission would be denied.
 // Note that the test name prefix must be "GeolocationAPI".
 IN_PROC_BROWSER_TEST_F(WebViewTest, GeolocationAPIEmbedderHasNoAccessAllow) {
-  GeolocationTestHelper("testDenyDenies",
-                        "web_view/geolocation/embedder_has_no_permission");
+  TestHelper("testDenyDenies",
+             "DoneGeolocationTest.PASSED",
+             "DoneGeolocationTest.FAILED",
+             "web_view/geolocation/embedder_has_no_permission");
 }
 
 IN_PROC_BROWSER_TEST_F(WebViewTest, GeolocationAPIEmbedderHasNoAccessDeny) {
-  GeolocationTestHelper("testDenyDenies",
-                        "web_view/geolocation/embedder_has_no_permission");
+  TestHelper("testDenyDenies",
+             "DoneGeolocationTest.PASSED",
+             "DoneGeolocationTest.FAILED",
+             "web_view/geolocation/embedder_has_no_permission");
 }
 
 // In following GeolocationAPIEmbedderHasAccess* tests, embedder (i.e. the
@@ -1008,43 +1170,56 @@
 // the tests become flaky.
 // GeolocationAPI* test 1 of 3.
 IN_PROC_BROWSER_TEST_F(WebViewTest, GeolocationAPIEmbedderHasAccessAllow) {
-  GeolocationTestHelper("testAllow",
-                        "web_view/geolocation/embedder_has_permission");
+  TestHelper("testAllow",
+             "DoneGeolocationTest.PASSED",
+             "DoneGeolocationTest.FAILED",
+             "web_view/geolocation/embedder_has_permission");
 }
 
 // GeolocationAPI* test 2 of 3.
 IN_PROC_BROWSER_TEST_F(WebViewTest, GeolocationAPIEmbedderHasAccessDeny) {
-  GeolocationTestHelper("testDeny",
-                        "web_view/geolocation/embedder_has_permission");
+  TestHelper("testDeny",
+             "DoneGeolocationTest.PASSED",
+             "DoneGeolocationTest.FAILED",
+             "web_view/geolocation/embedder_has_permission");
 }
 
 // GeolocationAPI* test 3 of 3.
 IN_PROC_BROWSER_TEST_F(WebViewTest,
                        GeolocationAPIEmbedderHasAccessMultipleBridgeIdAllow) {
-  GeolocationTestHelper("testMultipleBridgeIdAllow",
-                        "web_view/geolocation/embedder_has_permission");
+  TestHelper("testMultipleBridgeIdAllow",
+             "DoneGeolocationTest.PASSED",
+             "DoneGeolocationTest.FAILED",
+             "web_view/geolocation/embedder_has_permission");
 }
 
 // Tests that
 // BrowserPluginGeolocationPermissionContext::CancelGeolocationPermissionRequest
 // is handled correctly (and does not crash).
 IN_PROC_BROWSER_TEST_F(WebViewTest, GeolocationAPICancelGeolocation) {
-  ASSERT_TRUE(StartTestServer());  // For serving guest pages.
+  ASSERT_TRUE(StartEmbeddedTestServer());  // For serving guest pages.
   ASSERT_TRUE(RunPlatformAppTest(
         "platform_apps/web_view/geolocation/cancel_request")) << message_;
 }
 
+IN_PROC_BROWSER_TEST_F(WebViewTest, Navigation) {
+  TestHelper("testNavigation",
+             "DoneNavigationTest.PASSED",
+             "DoneNavigationTest.FAILED",
+             "web_view/navigation");
+}
+
 IN_PROC_BROWSER_TEST_F(WebViewTest, ConsoleMessage) {
-  ASSERT_TRUE(StartTestServer());  // For serving guest pages.
+  ASSERT_TRUE(StartEmbeddedTestServer());  // For serving guest pages.
   ASSERT_TRUE(RunPlatformAppTestWithArg(
       "platform_apps/web_view/common", "console_messages"))
           << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(WebViewTest, DownloadPermission) {
-  ASSERT_TRUE(StartTestServer());  // For serving guest pages.
+  ASSERT_TRUE(StartEmbeddedTestServer());  // For serving guest pages.
   content::WebContents* guest_web_contents =
-      LoadGuest("files/extensions/platform_apps/web_view/download/guest.html",
+      LoadGuest("/extensions/platform_apps/web_view/download/guest.html",
                 "web_view/download");
   ASSERT_TRUE(guest_web_contents);
 
diff --git a/chrome/browser/extensions/web_view_interactive_browsertest.cc b/chrome/browser/extensions/web_view_interactive_browsertest.cc
index 5d854bd..69b5cbc 100644
--- a/chrome/browser/extensions/web_view_interactive_browsertest.cc
+++ b/chrome/browser/extensions/web_view_interactive_browsertest.cc
@@ -1,13 +1,13 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/stringprintf.h"
+#include "apps/shell_window.h"
+#include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/extensions/extension_test_message_listener.h"
 #include "chrome/browser/extensions/platform_app_browsertest_util.h"
 #include "chrome/browser/extensions/shell_window_registry.h"
-#include "chrome/browser/ui/extensions/shell_window.h"
 #include "chrome/test/base/interactive_test_utils.h"
 #include "chrome/test/base/test_launcher_utils.h"
 #include "chrome/test/base/ui_test_utils.h"
@@ -18,9 +18,12 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_view.h"
 #include "content/public/test/browser_test_utils.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
 #include "ui/base/keycodes/keyboard_codes.h"
 #include "ui/base/test/ui_controls.h"
 
+using apps::ShellWindow;
+
 class WebViewInteractiveTest
     : public extensions::PlatformAppBrowserTest {
  public:
@@ -101,7 +104,7 @@
 
   void NewWindowTestHelper(const std::string& test_name,
                            const std::string& app_location) {
-    ASSERT_TRUE(StartTestServer());  // For serving guest pages.
+    ASSERT_TRUE(StartEmbeddedTestServer());  // For serving guest pages.
     ExtensionTestMessageListener launched_listener("Launched", false);
     LoadAndLaunchPlatformApp(app_location.c_str());
     ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
@@ -122,12 +125,12 @@
 
   void SetupTest(const std::string& app_name,
                  const std::string& guest_url_spec) {
-    ASSERT_TRUE(StartTestServer());
+    ASSERT_TRUE(StartEmbeddedTestServer());
     GURL::Replacements replace_host;
     std::string host_str("localhost");  // Must stay in scope with replace_host.
     replace_host.SetHostStr(host_str);
 
-    GURL guest_url = test_server()->GetURL(guest_url_spec);
+    GURL guest_url = embedded_test_server()->GetURL(guest_url_spec);
     guest_url = guest_url.ReplaceComponents(replace_host);
 
     ui_test_utils::UrlLoadObserver guest_observer(
@@ -290,7 +293,7 @@
 
 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, PointerLock) {
   SetupTest("web_view/pointer_lock",
-            "files/extensions/platform_apps/web_view/pointer_lock/guest.html");
+            "/extensions/platform_apps/web_view/pointer_lock/guest.html");
 
   // Move the mouse over the Lock Pointer button.
   ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(
@@ -364,7 +367,7 @@
 
 // Tests that setting focus on the <webview> sets focus on the guest.
 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, DISABLED_Focus) {
-  ASSERT_TRUE(StartTestServer());  // For serving guest pages.
+  ASSERT_TRUE(StartEmbeddedTestServer());  // For serving guest pages.
   ASSERT_TRUE(RunPlatformAppTest("platform_apps/web_view/focus"))
       << message_;
 }
@@ -372,7 +375,7 @@
 // Tests that guests receive edit commands and respond appropriately.
 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, EditCommands) {
   SetupTest("web_view/edit_commands",
-            "files/extensions/platform_apps/web_view/edit_commands/guest.html");
+            "/extensions/platform_apps/web_view/edit_commands/guest.html");
 
   ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(
       GetPlatformAppWindow()));
@@ -390,7 +393,7 @@
 // Tests that guests receive edit commands and respond appropriately.
 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, EditCommandsNoMenu) {
   SetupTest("web_view/edit_commands_no_menu",
-      "files/extensions/platform_apps/web_view/edit_commands_no_menu/"
+      "/extensions/platform_apps/web_view/edit_commands_no_menu/"
       "guest.html");
 
   ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(
@@ -436,7 +439,7 @@
 }
 
 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, ExecuteCode) {
-  ASSERT_TRUE(StartTestServer());  // For serving guest pages.
+  ASSERT_TRUE(StartEmbeddedTestServer());  // For serving guest pages.
   ASSERT_TRUE(RunPlatformAppTestWithArg(
       "platform_apps/web_view/common", "execute_code")) << message_;
 }
@@ -444,7 +447,7 @@
 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, PopupPositioning) {
   SetupTest(
       "web_view/popup_positioning",
-      "files/extensions/platform_apps/web_view/popup_positioning/guest.html");
+      "/extensions/platform_apps/web_view/popup_positioning/guest.html");
   ASSERT_TRUE(guest_web_contents());
 
   PopupTestHelper(gfx::Point());
@@ -461,7 +464,7 @@
 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, DISABLED_PopupPositioningMoved) {
   SetupTest(
       "web_view/popup_positioning_moved",
-      "files/extensions/platform_apps/web_view/popup_positioning_moved"
+      "/extensions/platform_apps/web_view/popup_positioning_moved"
       "/guest.html");
   ASSERT_TRUE(guest_web_contents());
 
diff --git a/chrome/browser/extensions/webstore_install_helper.cc b/chrome/browser/extensions/webstore_install_helper.cc
index 67bbbf1..323cba4 100644
--- a/chrome/browser/extensions/webstore_install_helper.cc
+++ b/chrome/browser/extensions/webstore_install_helper.cc
@@ -149,7 +149,8 @@
   ReportResultsIfComplete();
 }
 
-void WebstoreInstallHelper::OnJSONParseSucceeded(const ListValue& wrapper) {
+void WebstoreInstallHelper::OnJSONParseSucceeded(
+    const base::ListValue& wrapper) {
   CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
   manifest_parse_complete_ = true;
   const Value* value = NULL;
diff --git a/chrome/browser/extensions/webstore_installer.cc b/chrome/browser/extensions/webstore_installer.cc
index b0573eb..bd40ef5 100644
--- a/chrome/browser/extensions/webstore_installer.cc
+++ b/chrome/browser/extensions/webstore_installer.cc
@@ -18,6 +18,8 @@
 #include "chrome/browser/download/download_prefs.h"
 #include "chrome/browser/download/download_util.h"
 #include "chrome/browser/extensions/crx_installer.h"
+#include "chrome/browser/extensions/install_tracker.h"
+#include "chrome/browser/extensions/install_tracker_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
@@ -25,6 +27,7 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_constants.h"
+#include "chrome/common/extensions/extension_manifest_constants.h"
 #include "chrome/common/omaha_query_params/omaha_query_params.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/download_manager.h"
@@ -66,7 +69,7 @@
 const char kDownloadInterruptedError[] = "Download interrupted";
 const char kInvalidDownloadError[] = "Download was not a CRX";
 const char kInlineInstallSource[] = "inline";
-const char kDefaultInstallSource[] = "";
+const char kDefaultInstallSource[] = "ondemand";
 
 base::FilePath* g_download_directory_for_tests = NULL;
 
@@ -230,6 +233,17 @@
       BrowserThread::FILE, FROM_HERE,
       base::Bind(&GetDownloadFilePath, download_path, id_,
                  base::Bind(&WebstoreInstaller::StartDownload, this)));
+
+  std::string name;
+  if (!approval_->manifest->value()->GetString(extension_manifest_keys::kName,
+                                               &name)) {
+    NOTREACHED();
+  }
+  extensions::InstallTracker* tracker =
+      extensions::InstallTrackerFactory::GetForProfile(profile_);
+  tracker->OnBeginExtensionInstall(
+      id_, name, approval_->installing_icon, approval_->manifest->is_app(),
+      approval_->manifest->is_platform_app());
 }
 
 void WebstoreInstaller::Observe(int type,
@@ -323,15 +337,27 @@
       break;
     case DownloadItem::COMPLETE:
       // Wait for other notifications if the download is really an extension.
-      if (!download_crx_util::IsExtensionDownload(*download))
+      if (!download_crx_util::IsExtensionDownload(*download)) {
         ReportFailure(kInvalidDownloadError, FAILURE_REASON_OTHER);
-      else if (delegate_)
-        delegate_->OnExtensionDownloadProgress(id_, download);
+      } else {
+        if (delegate_)
+          delegate_->OnExtensionDownloadProgress(id_, download);
+
+        extensions::InstallTracker* tracker =
+            extensions::InstallTrackerFactory::GetForProfile(profile_);
+        tracker->OnDownloadProgress(id_, 100);
+      }
       break;
-    case DownloadItem::IN_PROGRESS:
+    case DownloadItem::IN_PROGRESS: {
       if (delegate_)
         delegate_->OnExtensionDownloadProgress(id_, download);
+
+      extensions::InstallTracker* tracker =
+          extensions::InstallTrackerFactory::GetForProfile(profile_);
+      tracker->OnDownloadProgress(id_, download->PercentComplete());
+
       break;
+    }
     default:
       // Continue listening if the download is not in one of the above states.
       break;
@@ -422,6 +448,10 @@
     delegate_ = NULL;
   }
 
+  extensions::InstallTracker* tracker =
+      extensions::InstallTrackerFactory::GetForProfile(profile_);
+  tracker->OnInstallFailure(id_);
+
   Release();  // Balanced in Start().
 }
 
diff --git a/chrome/browser/extensions/webstore_standalone_installer.cc b/chrome/browser/extensions/webstore_standalone_installer.cc
index 8508281..70e61ce 100644
--- a/chrome/browser/extensions/webstore_standalone_installer.cc
+++ b/chrome/browser/extensions/webstore_standalone_installer.cc
@@ -73,6 +73,11 @@
   webstore_data_fetcher_->Start();
 }
 
+scoped_ptr<ExtensionInstallPrompt>
+WebstoreStandaloneInstaller::CreateInstallUI() {
+  return make_scoped_ptr(new ExtensionInstallPrompt(GetWebContents()));
+}
+
 void WebstoreStandaloneInstaller::OnWebstoreRequestFailure() {
   CompleteInstall(kWebstoreRequestError);
 }
@@ -174,7 +179,7 @@
 
   install_prompt_ = CreateInstallPrompt();
   if (install_prompt_) {
-    CreateInstallUI();
+    ShowInstallUI();
     // Control flow finishes up in InstallUIProceed or InstallUIAbort.
   } else {
     InstallUIProceed();
@@ -251,7 +256,7 @@
 }
 
 void
-WebstoreStandaloneInstaller::CreateInstallUI() {
+WebstoreStandaloneInstaller::ShowInstallUI() {
   std::string error;
   localized_extension_for_display_ =
       ExtensionInstallPrompt::GetLocalizedExtensionForDisplay(
@@ -266,7 +271,7 @@
     return;
   }
 
-  install_ui_.reset(new ExtensionInstallPrompt(GetWebContents()));
+  install_ui_ = CreateInstallUI();
   install_ui_->ConfirmStandaloneInstall(
       this, localized_extension_for_display_.get(), &icon_, *install_prompt_);
 }
diff --git a/chrome/browser/extensions/webstore_standalone_installer.h b/chrome/browser/extensions/webstore_standalone_installer.h
index fb4c02b..a49a868 100644
--- a/chrome/browser/extensions/webstore_standalone_installer.h
+++ b/chrome/browser/extensions/webstore_standalone_installer.h
@@ -107,6 +107,10 @@
       const base::DictionaryValue& webstore_data,
       std::string* error) const = 0;
 
+  // Returns an install UI to be shown. By default, this returns an install UI
+  // that is a transient child of the host window for GetWebContents().
+  virtual scoped_ptr<ExtensionInstallPrompt> CreateInstallUI();
+
   // Accessors to be used by subclasses.
   const std::string& localized_user_count() const {
     return localized_user_count_;
@@ -161,7 +165,7 @@
       const std::string& error,
       WebstoreInstaller::FailureReason reason) OVERRIDE;
 
-  void CreateInstallUI();
+  void ShowInstallUI();
 
   // Input configuration.
   std::string id_;
@@ -185,7 +189,7 @@
   scoped_ptr<DictionaryValue> manifest_;
   SkBitmap icon_;
 
-  // Created by CreateInstallUI() when a prompt is shown (if
+  // Created by ShowInstallUI() when a prompt is shown (if
   // the implementor returns a non-NULL in CreateInstallPrompt()).
   scoped_refptr<Extension> localized_extension_for_display_;
 
diff --git a/chrome/browser/extensions/webstore_startup_installer_browsertest.cc b/chrome/browser/extensions/webstore_startup_installer_browsertest.cc
index b1febf4..019acee 100644
--- a/chrome/browser/extensions/webstore_startup_installer_browsertest.cc
+++ b/chrome/browser/extensions/webstore_startup_installer_browsertest.cc
@@ -11,6 +11,9 @@
 #include "chrome/browser/extensions/extension_system.h"
 #include "chrome/browser/extensions/startup_helper.h"
 #include "chrome/browser/extensions/webstore_standalone_installer.h"
+#include "chrome/browser/infobars/infobar_service.h"
+#include "chrome/browser/managed_mode/managed_user_service.h"
+#include "chrome/browser/managed_mode/managed_user_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
@@ -18,6 +21,7 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/extensions/extension_builder.h"
 #include "chrome/common/extensions/value_builder.h"
+#include "chrome/common/pref_names.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/notification_registrar.h"
@@ -235,6 +239,28 @@
   EXPECT_TRUE(extension_service->extensions()->Contains(kTestExtensionId));
 }
 
+IN_PROC_BROWSER_TEST_F(WebstoreStartupInstallerTest,
+                       InstallProhibitedForManagedUsers) {
+  CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+      switches::kAppsGalleryInstallAutoConfirmForTests, "accept");
+
+  // Make the profile managed such that no extension installs are allowed.
+  browser()->profile()->GetPrefs()->SetBoolean(prefs::kProfileIsManaged, true);
+  ManagedUserService* service =
+      ManagedUserServiceFactory::GetForProfile(browser()->profile());
+  service->Init();
+
+  ui_test_utils::NavigateToURL(
+      browser(), GenerateTestServerUrl(kAppDomain, "install_prohibited.html"));
+
+  RunTest("runTest");
+
+  // No error infobar should show up.
+  WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
+  InfoBarService* info_bar_service = InfoBarService::FromWebContents(contents);
+  EXPECT_EQ(info_bar_service->infobar_count(), 0u);
+}
+
 // The unpack failure test needs to use a different install .crx, which is
 // specified via a command-line flag, so it needs its own test subclass.
 class WebstoreStartupInstallUnpackFailureTest
diff --git a/chrome/browser/extensions/window_controls_browsertest.cc b/chrome/browser/extensions/window_controls_browsertest.cc
new file mode 100644
index 0000000..a8bc465
--- /dev/null
+++ b/chrome/browser/extensions/window_controls_browsertest.cc
@@ -0,0 +1,80 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/extension_process_manager.h"
+#include "chrome/browser/extensions/extension_test_message_listener.h"
+#include "chrome/browser/extensions/platform_app_browsertest_util.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/chrome_switches.h"
+#include "content/public/browser/web_contents_view.h"
+#include "content/public/test/browser_test_utils.h"
+
+class WindowControlsTest : public extensions::PlatformAppBrowserTest {
+ protected:
+  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+    extensions::PlatformAppBrowserTest::SetUpCommandLine(command_line);
+    command_line->AppendSwitch(switches::kEnableAppWindowControls);
+  }
+  content::WebContents* GetWebContentsForExtensionWindow(
+      const extensions::Extension* extension);
+};
+
+content::WebContents* WindowControlsTest::GetWebContentsForExtensionWindow(
+    const extensions::Extension* extension) {
+  ExtensionProcessManager* process_manager =
+      extensions::ExtensionSystem::Get(profile())->process_manager();
+
+  // Lookup render view host for background page.
+  const extensions::ExtensionHost* extension_host =
+      process_manager->GetBackgroundHostForExtension(extension->id());
+  content::RenderViewHost* background_view_host =
+      extension_host->render_view_host();
+
+  // Go through all active views, looking for the first window of the extension
+  const ExtensionProcessManager::ViewSet all_views =
+      process_manager->GetAllViews();
+  ExtensionProcessManager::ViewSet::const_iterator it = all_views.begin();
+  for (; it != all_views.end(); ++it) {
+    content::RenderViewHost* host = *it;
+
+    // Filter out views not part of this extension
+    if (process_manager->GetExtensionForRenderViewHost(host) == extension) {
+      // Filter out the background page view
+      if (host != background_view_host) {
+        content::WebContents* web_contents =
+            content::WebContents::FromRenderViewHost(host);
+        return web_contents;
+      }
+    }
+  }
+  return NULL;
+}
+
+IN_PROC_BROWSER_TEST_F(WindowControlsTest, CloseControlWorks) {
+  // Launch app and wait for window to show up
+  ExtensionTestMessageListener window_opened("window-opened", false);
+  const extensions::Extension* extension =
+      LoadAndLaunchPlatformApp("window_controls/buttons");
+  ASSERT_TRUE(window_opened.WaitUntilSatisfied());
+
+  // Find WebContents of window
+  content::WebContents* web_contents =
+      GetWebContentsForExtensionWindow(extension);
+  ASSERT_TRUE(web_contents != NULL);
+
+  // Send a left click on the "Close" button and wait for the close action
+  // to happen.
+  ExtensionTestMessageListener window_closed("window-closed", false);
+
+  // Send mouse click somewhere inside the [x] button
+  const int controlOffset = 25;
+  int x = web_contents->GetView()->GetContainerSize().width() - controlOffset;
+  int y = controlOffset;
+  content::SimulateMouseClickAt(web_contents,
+                                0,
+                                WebKit::WebMouseEvent::ButtonLeft,
+                                gfx::Point(x, y));
+
+  ASSERT_TRUE(window_closed.WaitUntilSatisfied());
+}
diff --git a/chrome/browser/extensions/window_open_apitest.cc b/chrome/browser/extensions/window_open_apitest.cc
index fe79889..840ff58 100644
--- a/chrome/browser/extensions/window_open_apitest.cc
+++ b/chrome/browser/extensions/window_open_apitest.cc
@@ -107,7 +107,7 @@
 
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, BrowserIsApp) {
   host_resolver()->AddRule("a.com", "127.0.0.1");
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(LoadExtension(
       test_data_dir_.AppendASCII("window_open").AppendASCII("browser_is_app")));
 
@@ -122,7 +122,7 @@
 }
 
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, WindowOpenPopupDefault) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(LoadExtension(
       test_data_dir_.AppendASCII("window_open").AppendASCII("popup")));
 
@@ -132,7 +132,7 @@
 }
 
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, WindowOpenPopupLarge) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(LoadExtension(
       test_data_dir_.AppendASCII("window_open").AppendASCII("popup_large")));
 
@@ -143,7 +143,7 @@
 }
 
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, WindowOpenPopupSmall) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(LoadExtension(
       test_data_dir_.AppendASCII("window_open").AppendASCII("popup_small")));
 
@@ -162,7 +162,7 @@
 #endif
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MAYBE_PopupBlockingExtension) {
   host_resolver()->AddRule("*", "127.0.0.1");
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   ASSERT_TRUE(LoadExtension(
       test_data_dir_.AppendASCII("window_open").AppendASCII("popup_blocking")
@@ -241,10 +241,14 @@
   ASSERT_TRUE(RunExtensionTest("window_open/panel")) << message_;
 }
 
+#if defined(USE_ASH_PANELS)
 // On Ash, this currently fails because we're currently opening new panel
 // windows as popup windows instead.
-// This is also flakey on Windows, ASan and Mac builds: crbug.com/179251
-IN_PROC_BROWSER_TEST_F(WindowOpenPanelTest, DISABLED_WindowOpenPanelDetached) {
+#define MAYBE_WindowOpenPanelDetached DISABLED_WindowOpenPanelDetached
+#else
+#define MAYBE_WindowOpenPanelDetached WindowOpenPanelDetached
+#endif
+IN_PROC_BROWSER_TEST_F(WindowOpenPanelTest, MAYBE_WindowOpenPanelDetached) {
   ASSERT_TRUE(RunExtensionTest("window_open/panel_detached")) << message_;
 }
 
@@ -264,7 +268,7 @@
   int num_popups = 2;
   int num_panels = 2;
 #endif
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   // Setup listeners to wait on strings we expect the extension pages to send.
   std::vector<std::string> test_strings;
@@ -331,7 +335,7 @@
   int num_popups = 2;
   int num_panels = 2;
 #endif
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   // Setup listeners to wait on strings we expect the extension pages to send.
   std::vector<std::string> test_strings;
@@ -381,7 +385,7 @@
 #define MAYBE_WindowOpenFromPanel WindowOpenFromPanel
 #endif
 IN_PROC_BROWSER_TEST_F(WindowOpenPanelTest, MAYBE_WindowOpenFromPanel) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
 
   // Load the extension that will open a panel which then calls window.open.
   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("window_open").
diff --git a/chrome/browser/extensions/window_open_interactive_apitest.cc b/chrome/browser/extensions/window_open_interactive_apitest.cc
index 75384ab..7cf4f66 100644
--- a/chrome/browser/extensions/window_open_interactive_apitest.cc
+++ b/chrome/browser/extensions/window_open_interactive_apitest.cc
@@ -13,7 +13,9 @@
   }
 };
 
-#if defined(OS_MACOSX)  // http://crbug.com/162912 || defined(OS_WIN)
+// http://crbug.com/162912 || defined(OS_WIN)
+// http://crbug.com/253417 for NDEBUG
+#if defined(OS_MACOSX) && defined(NDEBUG)
 // Focus test fails if there is no window manager on Linux.
 IN_PROC_BROWSER_TEST_F(WindowOpenPanelTest, WindowOpenFocus) {
   ASSERT_TRUE(RunExtensionTest("window_open/focus")) << message_;
diff --git a/chrome/browser/external_protocol/external_protocol_handler.cc b/chrome/browser/external_protocol/external_protocol_handler.cc
index 580d261..04d59e8 100644
--- a/chrome/browser/external_protocol/external_protocol_handler.cc
+++ b/chrome/browser/external_protocol/external_protocol_handler.cc
@@ -19,8 +19,8 @@
 #include "chrome/browser/prefs/scoped_user_pref_update.h"
 #include "chrome/common/pref_names.h"
 #include "content/public/browser/browser_thread.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/escape.h"
+#include "url/gurl.h"
 
 using content::BrowserThread;
 
diff --git a/chrome/browser/favicon/favicon_changed_details.h b/chrome/browser/favicon/favicon_changed_details.h
index 921513a..ec1277c 100644
--- a/chrome/browser/favicon/favicon_changed_details.h
+++ b/chrome/browser/favicon/favicon_changed_details.h
@@ -8,7 +8,7 @@
 #include <set>
 
 #include "chrome/browser/history/history_details.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 // Details for chrome::NOTIFICATION_FAVICON_CHANGED.
 struct FaviconChangedDetails : public history::HistoryDetails {
diff --git a/chrome/browser/favicon/favicon_handler.cc b/chrome/browser/favicon/favicon_handler.cc
index 4771790..881008d 100644
--- a/chrome/browser/favicon/favicon_handler.cc
+++ b/chrome/browser/favicon/favicon_handler.cc
@@ -30,6 +30,10 @@
 
 namespace {
 
+// Size (along each axis) of a touch icon. This currently corresponds to
+// the apple touch icon for iPad.
+const int kTouchIconSize = 72;
+
 // Returns chrome::IconType the given icon_type corresponds to.
 chrome::IconType ToHistoryIconType(FaviconURL::IconType icon_type) {
   switch (icon_type) {
@@ -47,6 +51,25 @@
   return chrome::INVALID_ICON;
 }
 
+// Get the maximal icon size in pixels for a icon of type |icon_type| for the
+// current platform.
+int GetMaximalIconSize(chrome::IconType icon_type) {
+  int base_size = 0;
+  switch (icon_type) {
+    case chrome::FAVICON:
+      base_size = gfx::kFaviconSize;
+      break;
+    case chrome::TOUCH_ICON:
+    case chrome::TOUCH_PRECOMPOSED_ICON:
+      base_size = kTouchIconSize;
+      break;
+    case chrome::INVALID_ICON:
+      base_size = 0;
+      break;
+  }
+  return ui::GetScaleFactorScale(ui::GetMaxScaleFactor()) * base_size;
+}
+
 bool DoUrlAndIconMatch(const FaviconURL& favicon_url,
                        const GURL& url,
                        chrome::IconType icon_type) {
@@ -300,7 +323,10 @@
   if (image.IsEmpty())
     return;
 
-  entry->GetFavicon().image = image;
+  gfx::Image image_with_adjusted_colorspace = image;
+  FaviconUtil::SetFaviconColorSpace(&image_with_adjusted_colorspace);
+
+  entry->GetFavicon().image = image_with_adjusted_colorspace;
   delegate_->NotifyFaviconUpdated(icon_url_changed);
 }
 
@@ -406,12 +432,15 @@
   return NULL;
 }
 
-int FaviconHandler::DownloadFavicon(const GURL& image_url, int image_size) {
+int FaviconHandler::DownloadFavicon(const GURL& image_url,
+                                    int image_size,
+                                    chrome::IconType icon_type) {
   if (!image_url.is_valid()) {
     NOTREACHED();
     return 0;
   }
-  int id = delegate_->StartDownload(image_url, image_size);
+  int id = delegate_->StartDownload(
+      image_url, image_size, GetMaximalIconSize(icon_type));
   return id;
 }
 
@@ -590,7 +619,7 @@
     const GURL& image_url,
     int image_size,
     chrome::IconType icon_type) {
-  const int download_id = DownloadFavicon(image_url, image_size);
+  const int download_id = DownloadFavicon(image_url, image_size, icon_type);
   if (download_id) {
     // Download ids should be unique.
     DCHECK(download_requests_.find(download_id) == download_requests_.end());
diff --git a/chrome/browser/favicon/favicon_handler.h b/chrome/browser/favicon/favicon_handler.h
index 8d23a79..2d62d5b 100644
--- a/chrome/browser/favicon/favicon_handler.h
+++ b/chrome/browser/favicon/favicon_handler.h
@@ -15,9 +15,9 @@
 #include "chrome/common/cancelable_task_tracker.h"
 #include "chrome/common/ref_counted_util.h"
 #include "content/public/common/favicon_url.h"
-#include "googleurl/src/gurl.h"
 #include "ui/gfx/favicon_size.h"
 #include "ui/gfx/image/image.h"
+#include "url/gurl.h"
 
 class FaviconHandlerDelegate;
 class Profile;
@@ -122,7 +122,9 @@
   virtual content::NavigationEntry* GetEntry();
 
   // Asks the render to download favicon, returns the request id.
-  virtual int DownloadFavicon(const GURL& image_url, int image_size);
+  virtual int DownloadFavicon(const GURL& image_url,
+                              int image_size,
+                              chrome::IconType icon_type);
 
   // Ask the favicon from history
   virtual void UpdateFaviconMappingAndFetch(
diff --git a/chrome/browser/favicon/favicon_handler_delegate.h b/chrome/browser/favicon/favicon_handler_delegate.h
index 0fc1749..b7664fd 100644
--- a/chrome/browser/favicon/favicon_handler_delegate.h
+++ b/chrome/browser/favicon/favicon_handler_delegate.h
@@ -23,7 +23,13 @@
   // will call OnDidDownloadFavicon() with the results.
   // Returns the unique id of the download request. The id will be passed
   // in OnDidDownloadFavicon().
-  virtual int StartDownload(const GURL& url, int image_size) = 0;
+  // |preferred_image_size| is used to select the size of the returned image if
+  // the |url| is a multi resolution image.
+  // |max_image_size| is the maximal size of the image. If the image at |url| is
+  // bigger than this, it will be resized. 0 means unlimited.
+  virtual int StartDownload(const GURL& url,
+                            int preferred_image_size,
+                            int max_image_size) = 0;
 
   // Notifies the delegate that the favicon for the active entry was updated.
   // |icon_url_changed| is true if a favicon with a different icon URL has
diff --git a/chrome/browser/favicon/favicon_handler_unittest.cc b/chrome/browser/favicon/favicon_handler_unittest.cc
index 52dbb7a..c74cb86 100644
--- a/chrome/browser/favicon/favicon_handler_unittest.cc
+++ b/chrome/browser/favicon/favicon_handler_unittest.cc
@@ -178,7 +178,9 @@
     return NULL;
   }
 
-  virtual int StartDownload(const GURL& url, int image_size) OVERRIDE {
+  virtual int StartDownload(const GURL& url,
+                            int preferred_image_size,
+                            int max_image_size) OVERRIDE {
     ADD_FAILURE() << "TestFaviconHandlerDelegate::StartDownload() "
                   << "should never be called in tests.";
     return -1;
@@ -270,7 +272,9 @@
                                                      icon_types, callback));
   }
 
-  virtual int DownloadFavicon(const GURL& image_url, int image_size) OVERRIDE {
+  virtual int DownloadFavicon(const GURL& image_url,
+                              int image_size,
+                              chrome::IconType icon_type) OVERRIDE {
     download_id_++;
     download_handler_->AddDownload(download_id_, image_url, image_size);
     return download_id_;
@@ -1056,7 +1060,7 @@
   int download_id = 0;
 
   // Try to download missing icon.
-  download_id = favicon_tab_helper->StartDownload(missing_icon_url, 0);
+  download_id = favicon_tab_helper->StartDownload(missing_icon_url, 0, 0);
   EXPECT_NE(0, download_id);
   EXPECT_FALSE(favicon_service->WasUnableToDownloadFavicon(missing_icon_url));
 
@@ -1067,7 +1071,7 @@
   EXPECT_FALSE(favicon_service->WasUnableToDownloadFavicon(missing_icon_url));
 
   // Try to download again.
-  download_id = favicon_tab_helper->StartDownload(missing_icon_url, 0);
+  download_id = favicon_tab_helper->StartDownload(missing_icon_url, 0, 0);
   EXPECT_NE(0, download_id);
   EXPECT_FALSE(favicon_service->WasUnableToDownloadFavicon(missing_icon_url));
 
@@ -1078,13 +1082,13 @@
   EXPECT_TRUE(favicon_service->WasUnableToDownloadFavicon(missing_icon_url));
 
   // Try to download again.
-  download_id = favicon_tab_helper->StartDownload(missing_icon_url, 0);
+  download_id = favicon_tab_helper->StartDownload(missing_icon_url, 0, 0);
   // Download is not started and Icon is still marked as UnableToDownload.
   EXPECT_EQ(0, download_id);
   EXPECT_TRUE(favicon_service->WasUnableToDownloadFavicon(missing_icon_url));
 
   // Try to download another icon.
-  download_id = favicon_tab_helper->StartDownload(another_icon_url, 0);
+  download_id = favicon_tab_helper->StartDownload(another_icon_url, 0, 0);
   // Download is started as another icon URL is not same as missing_icon_url.
   EXPECT_NE(0, download_id);
   EXPECT_FALSE(favicon_service->WasUnableToDownloadFavicon(another_icon_url));
@@ -1095,7 +1099,7 @@
   EXPECT_FALSE(favicon_service->WasUnableToDownloadFavicon(another_icon_url));
 
   // Try to download again.
-  download_id = favicon_tab_helper->StartDownload(missing_icon_url, 0);
+  download_id = favicon_tab_helper->StartDownload(missing_icon_url, 0, 0);
   EXPECT_NE(0, download_id);
   // Report download success with HTTP 200 status.
   favicon_tab_helper->DidDownloadFavicon(download_id, 200, missing_icon_url,
diff --git a/chrome/browser/favicon/favicon_service.cc b/chrome/browser/favicon/favicon_service.cc
index 37d691a..dc4cab9 100644
--- a/chrome/browser/favicon/favicon_service.cc
+++ b/chrome/browser/favicon/favicon_service.cc
@@ -8,12 +8,12 @@
 #include "base/message_loop/message_loop_proxy.h"
 #include "chrome/browser/favicon/favicon_types.h"
 #include "chrome/browser/favicon/favicon_util.h"
-#include "chrome/browser/favicon/imported_favicon_usage.h"
 #include "chrome/browser/history/history_backend.h"
 #include "chrome/browser/history/history_service.h"
 #include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/history/select_favicon_frames.h"
 #include "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h"
+#include "chrome/common/importer/imported_favicon_usage.h"
 #include "chrome/common/url_constants.h"
 #include "extensions/common/constants.h"
 #include "third_party/skia/include/core/SkBitmap.h"
@@ -314,6 +314,8 @@
       favicon_bitmap_results,
       FaviconUtil::GetFaviconScaleFactors(),
       desired_size_in_dip);
+  FaviconUtil::SetFaviconColorSpace(&image_result.image);
+
   image_result.icon_url = image_result.image.IsEmpty() ?
       GURL() : favicon_bitmap_results[0].icon_url;
   callback.Run(image_result);
diff --git a/chrome/browser/favicon/favicon_tab_helper.cc b/chrome/browser/favicon/favicon_tab_helper.cc
index 7be0450..93af404 100644
--- a/chrome/browser/favicon/favicon_tab_helper.cc
+++ b/chrome/browser/favicon/favicon_tab_helper.cc
@@ -134,7 +134,9 @@
   return web_contents()->GetController().GetActiveEntry();
 }
 
-int FaviconTabHelper::StartDownload(const GURL& url, int image_size) {
+int FaviconTabHelper::StartDownload(const GURL& url,
+                                    int preferred_image_size,
+                                    int max_image_size) {
   FaviconService* favicon_service = FaviconServiceFactory::GetForProfile(
       profile_->GetOriginalProfile(), Profile::IMPLICIT_ACCESS);
   if (favicon_service && favicon_service->WasUnableToDownloadFavicon(url)) {
@@ -145,7 +147,8 @@
   return web_contents()->DownloadImage(
       url,
       true,
-      image_size,
+      preferred_image_size,
+      max_image_size,
       base::Bind(&FaviconTabHelper::DidDownloadFavicon,base::Unretained(this)));
 }
 
diff --git a/chrome/browser/favicon/favicon_tab_helper.h b/chrome/browser/favicon/favicon_tab_helper.h
index 6f0f4ad..fad95a8 100644
--- a/chrome/browser/favicon/favicon_tab_helper.h
+++ b/chrome/browser/favicon/favicon_tab_helper.h
@@ -68,7 +68,9 @@
 
   // FaviconHandlerDelegate methods.
   virtual content::NavigationEntry* GetActiveEntry() OVERRIDE;
-  virtual int StartDownload(const GURL& url, int image_size) OVERRIDE;
+  virtual int StartDownload(const GURL& url,
+                            int preferred_image_size,
+                            int max_image_size) OVERRIDE;
   virtual void NotifyFaviconUpdated(bool icon_url_changed) OVERRIDE;
 
   // Favicon download callback.
diff --git a/chrome/browser/favicon/favicon_types.h b/chrome/browser/favicon/favicon_types.h
index f48ec4b..16724e0 100644
--- a/chrome/browser/favicon/favicon_types.h
+++ b/chrome/browser/favicon/favicon_types.h
@@ -6,9 +6,9 @@
 #define CHROME_BROWSER_FAVICON_FAVICON_TYPES_H_
 
 #include "base/memory/ref_counted_memory.h"
-#include "googleurl/src/gurl.h"
 #include "ui/gfx/image/image.h"
 #include "ui/gfx/size.h"
+#include "url/gurl.h"
 
 namespace chrome {
 
diff --git a/chrome/browser/favicon/favicon_util.cc b/chrome/browser/favicon/favicon_util.cc
index df96a47..21c9d75 100644
--- a/chrome/browser/favicon/favicon_util.cc
+++ b/chrome/browser/favicon/favicon_util.cc
@@ -7,14 +7,19 @@
 #include "chrome/browser/favicon/favicon_types.h"
 #include "chrome/browser/history/select_favicon_frames.h"
 #include "content/public/browser/render_view_host.h"
-#include "googleurl/src/gurl.h"
+#include "content/public/child/image_decoder_utils.h"
 #include "skia/ext/image_operations.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/gfx/codec/png_codec.h"
 #include "ui/gfx/favicon_size.h"
 #include "ui/gfx/image/image_png_rep.h"
 #include "ui/gfx/image/image_skia.h"
-#include "webkit/glue/image_decoder.h"
+#include "ui/gfx/size.h"
+#include "url/gurl.h"
+
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+#include "base/mac/mac_util.h"
+#endif  // defined(OS_MACOSX) && !defined(OS_IOS)
 
 namespace {
 
@@ -105,6 +110,13 @@
 }
 
 // static
+void FaviconUtil::SetFaviconColorSpace(gfx::Image* image) {
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+  image->SetSourceColorSpace(base::mac::GetSystemColorSpace());
+#endif  // defined(OS_MACOSX) && !defined(OS_IOS)
+}
+
+// static
 gfx::Image FaviconUtil::SelectFaviconFramesFromPNGs(
       const std::vector<chrome::FaviconBitmapResult>& png_data,
       const std::vector<ui::ScaleFactor>& scale_factors,
@@ -194,9 +206,10 @@
                                   size_t src_len,
                                   std::vector<unsigned char>* png_data) {
   // Decode the favicon using WebKit's image decoder.
-  webkit_glue::ImageDecoder decoder(
-      gfx::Size(gfx::kFaviconSize, gfx::kFaviconSize));
-  SkBitmap decoded = decoder.Decode(src_data, src_len);
+  SkBitmap decoded = content::DecodeImage(
+      src_data,
+      gfx::Size(gfx::kFaviconSize, gfx::kFaviconSize),
+      src_len);
   if (decoded.empty())
     return false;  // Unable to decode.
 
diff --git a/chrome/browser/favicon/favicon_util.h b/chrome/browser/favicon/favicon_util.h
index 32dc6e0..89474e9 100644
--- a/chrome/browser/favicon/favicon_util.h
+++ b/chrome/browser/favicon/favicon_util.h
@@ -34,6 +34,11 @@
   // the default favicon.
   static std::vector<ui::ScaleFactor> GetFaviconScaleFactors();
 
+  // Sets the color space used for converting |image| to an NSImage to the
+  // system colorspace. This makes the favicon look the same in the browser UI
+  // as it does in the renderer.
+  static void SetFaviconColorSpace(gfx::Image* image);
+
   // Takes a vector of png-encoded frames, decodes them, and converts them to
   // a favicon of size favicon_size (in DIPs) at the desired ui scale factors.
   static gfx::Image SelectFaviconFramesFromPNGs(
diff --git a/chrome/browser/favicon/imported_favicon_usage.cc b/chrome/browser/favicon/imported_favicon_usage.cc
deleted file mode 100644
index 42da286..0000000
--- a/chrome/browser/favicon/imported_favicon_usage.cc
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/favicon/imported_favicon_usage.h"
-
-ImportedFaviconUsage::ImportedFaviconUsage() {
-}
-
-ImportedFaviconUsage::~ImportedFaviconUsage() {
-}
diff --git a/chrome/browser/favicon/imported_favicon_usage.h b/chrome/browser/favicon/imported_favicon_usage.h
deleted file mode 100644
index ec7957d..0000000
--- a/chrome/browser/favicon/imported_favicon_usage.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_FAVICON_IMPORTED_FAVICON_USAGE_H_
-#define CHROME_BROWSER_FAVICON_IMPORTED_FAVICON_USAGE_H_
-
-#include <set>
-#include <vector>
-
-#include "googleurl/src/gurl.h"
-
-// Used to correlate favicons to imported bookmarks.
-struct ImportedFaviconUsage {
-  ImportedFaviconUsage();
-  ~ImportedFaviconUsage();
-
-  // The URL of the favicon.
-  GURL favicon_url;
-
-  // The raw png-encoded data.
-  std::vector<unsigned char> png_data;
-
-  // The list of URLs using this favicon.
-  std::set<GURL> urls;
-};
-
-#endif  // CHROME_BROWSER_FAVICON_IMPORTED_FAVICON_USAGE_H_
diff --git a/chrome/browser/feedback/feedback_data.h b/chrome/browser/feedback/feedback_data.h
index 14217cc..111721b 100644
--- a/chrome/browser/feedback/feedback_data.h
+++ b/chrome/browser/feedback/feedback_data.h
@@ -10,7 +10,7 @@
 
 #include "base/memory/ref_counted.h"
 #include "chrome/browser/ui/webui/screenshot_source.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
diff --git a/chrome/browser/feedback/feedback_util.cc b/chrome/browser/feedback/feedback_util.cc
index 2ed8930..c16691c 100644
--- a/chrome/browser/feedback/feedback_util.cc
+++ b/chrome/browser/feedback/feedback_util.cc
@@ -28,7 +28,6 @@
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_client.h"
-#include "googleurl/src/gurl.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "grit/theme_resources.h"
@@ -39,6 +38,7 @@
 #include "net/url_request/url_request_status.h"
 #include "third_party/icu/public/common/unicode/locid.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "url/gurl.h"
 
 using content::WebContents;
 
diff --git a/chrome/browser/first_run/first_run.cc b/chrome/browser/first_run/first_run.cc
index a6c9080..4216528 100644
--- a/chrome/browser/first_run/first_run.cc
+++ b/chrome/browser/first_run/first_run.cc
@@ -23,10 +23,9 @@
 #include "chrome/browser/first_run/first_run_internal.h"
 #include "chrome/browser/google/google_util.h"
 #include "chrome/browser/importer/external_process_importer_host.h"
-#include "chrome/browser/importer/importer_host.h"
+#include "chrome/browser/importer/importer_creator.h"
 #include "chrome/browser/importer/importer_list.h"
 #include "chrome/browser/importer/importer_progress_observer.h"
-#include "chrome/browser/importer/importer_type.h"
 #include "chrome/browser/importer/profile_writer.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/search_engines/template_url_service.h"
@@ -39,9 +38,9 @@
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/global_error/global_error_service.h"
 #include "chrome/browser/ui/global_error/global_error_service_factory.h"
+#include "chrome/browser/ui/sync/sync_promo_ui.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
-#include "chrome/browser/ui/webui/sync_promo/sync_promo_ui.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
@@ -56,7 +55,7 @@
 #include "content/public/browser/user_metrics.h"
 #include "content/public/browser/web_contents.h"
 #include "google_apis/gaia/gaia_auth_util.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 using content::UserMetricsAction;
 
@@ -231,12 +230,12 @@
 // |target_profile| for the items specified in the |items_to_import| bitfield.
 // This may be done in a separate process depending on the platform, but it will
 // always block until done.
-void ImportFromSourceProfile(ImporterHost* importer_host,
+void ImportFromSourceProfile(ExternalProcessImporterHost* importer_host,
                              const importer::SourceProfile& source_profile,
                              Profile* target_profile,
                              uint16 items_to_import) {
   ImportEndedObserver observer;
-  importer_host->SetObserver(&observer);
+  importer_host->set_observer(&observer);
   importer_host->StartImportSettings(source_profile,
                                      target_profile,
                                      items_to_import,
@@ -251,7 +250,7 @@
 // Imports bookmarks from an html file whose path is provided by
 // |import_bookmarks_path|.
 void ImportFromFile(Profile* profile,
-                    ImporterHost* file_importer_host,
+                    ExternalProcessImporterHost* file_importer_host,
                     const std::string& import_bookmarks_path) {
   importer::SourceProfile source_profile;
   source_profile.importer_type = importer::TYPE_BOOKMARKS_FILE;
@@ -271,7 +270,7 @@
 
 // Imports settings from the first profile in |importer_list|.
 void ImportSettings(Profile* profile,
-                    ImporterHost* importer_host,
+                    ExternalProcessImporterHost* importer_host,
                     scoped_refptr<ImporterList> importer_list,
                     int items_to_import) {
   const importer::SourceProfile& source_profile =
@@ -453,9 +452,6 @@
 #endif
 
 }  // namespace internal
-}  // namespace first_run
-
-namespace first_run {
 
 MasterPrefs::MasterPrefs()
     : ping_delay(0),
@@ -506,7 +502,7 @@
   base::FilePath first_run_sentinel;
   if (!internal::GetFirstRunSentinelFilePath(&first_run_sentinel))
     return false;
-  return file_util::Delete(first_run_sentinel, false);
+  return base::Delete(first_run_sentinel, false);
 }
 
 bool SetShowFirstRunBubblePref(FirstRunBubbleOptions show_bubble_option) {
@@ -676,24 +672,16 @@
     int import_items,
     int dont_import_items,
     const std::string& import_bookmarks_path) {
-#if !defined(USE_AURA)
   // Deletes itself.
-  ImporterHost* importer_host;
-  // TODO(csilv,mirandac): Out-of-process import has only been qualified on
-  // MacOS X and Windows, so we will only use it on those platforms.
-  // Linux still uses the in-process import (http://crbug.com/56816).
-#if defined(OS_MACOSX) || defined(OS_WIN)
-  importer_host = new ExternalProcessImporterHost;
-#else
-  importer_host = new ImporterHost;
-#endif
+  ExternalProcessImporterHost* importer_host = new ExternalProcessImporterHost;
 
   base::FilePath local_state_path;
   PathService::Get(chrome::FILE_LOCAL_STATE, &local_state_path);
   bool local_state_file_exists = file_util::PathExists(local_state_path);
 
-  scoped_refptr<ImporterList> importer_list(new ImporterList(NULL));
-  importer_list->DetectSourceProfilesHack();
+  scoped_refptr<ImporterList> importer_list(new ImporterList());
+  importer_list->DetectSourceProfilesHack(
+      g_browser_process->GetApplicationLocale());
 
   // Do import if there is an available profile for us to import.
   if (importer_list->count() > 0) {
@@ -753,14 +741,8 @@
 
   if (!import_bookmarks_path.empty()) {
     // Deletes itself.
-    ImporterHost* file_importer_host;
-    // TODO(gab): Make Linux use OOP import as well (http://crbug.com/56816) and
-    // get rid of these ugly ifdefs.
-#if defined(OS_MACOSX) || defined(OS_WIN)
-    file_importer_host = new ExternalProcessImporterHost;
-#else
-    file_importer_host = new ImporterHost;
-#endif
+    ExternalProcessImporterHost* file_importer_host =
+        new ExternalProcessImporterHost;
     file_importer_host->set_headless();
 
     ImportFromFile(profile, file_importer_host, import_bookmarks_path);
@@ -768,7 +750,6 @@
 
   content::RecordAction(UserMetricsAction("FirstRunDef_Accept"));
 
-#endif  // !defined(USE_AURA)
   g_auto_import_state |= AUTO_IMPORT_CALLED;
 }
 
diff --git a/chrome/browser/first_run/first_run_browsertest.cc b/chrome/browser/first_run/first_run_browsertest.cc
index 6f1cf93..437f691 100644
--- a/chrome/browser/first_run/first_run_browsertest.cc
+++ b/chrome/browser/first_run/first_run_browsertest.cc
@@ -4,12 +4,14 @@
 
 #include "base/command_line.h"
 #include "base/files/file_path.h"
+#include "base/memory/ref_counted.h"
 #include "base/prefs/pref_service.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/extensions/component_loader.h"
 #include "chrome/browser/first_run/first_run.h"
+#include "chrome/browser/importer/importer_list.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
@@ -91,7 +93,7 @@
   }
 
   virtual void TearDown() OVERRIDE {
-    EXPECT_TRUE(file_util::Delete(prefs_file_, false));
+    EXPECT_TRUE(base::Delete(prefs_file_, false));
     InProcessBrowserTest::TearDown();
   }
 
@@ -130,45 +132,40 @@
   DISALLOW_COPY_AND_ASSIGN(FirstRunMasterPrefsBrowserTestT);
 };
 
-}  // namespace
-
-// TODO(tapted): Investigate why this fails on Linux bots but does not
-// reproduce locally. See http://crbug.com/178062 .
-// TODO(tapted): Investigate why this fails on mac_asan flakily
-// http://crbug.com/181499 .
-#if defined(OS_LINUX) || (defined(OS_MACOSX) && defined(ADDRESS_SANITIZER))
-#define MAYBE_ImportDefault DISABLED_ImportDefault
-#else
-#define MAYBE_ImportDefault ImportDefault
+// Returns the true expected import state, derived from the original
+// |expected_import_state|, for the current test machine's configuration. Some
+// bot configurations do not have another profile (browser) to import from and
+// thus the import must not be expected to have occurred.
+int MaskExpectedImportState(int expected_import_state) {
+  scoped_refptr<ImporterList> importer_list(new ImporterList());
+  importer_list->DetectSourceProfilesHack(
+      g_browser_process->GetApplicationLocale());
+  int source_profile_count = importer_list->count();
+#if defined(OS_WIN)
+  // On Windows, the importer's DetectIEProfiles() will always add to the count.
+  // Internet Explorer always exists and always has something to import.
+  EXPECT_GT(source_profile_count, 0);
 #endif
+  if (source_profile_count == 0)
+    return expected_import_state & ~first_run::AUTO_IMPORT_PROFILE_IMPORTED;
+
+  return expected_import_state;
+}
+
+}  // namespace
 
 extern const char kImportDefault[] =
     "{\n"
     "}\n";
 typedef FirstRunMasterPrefsBrowserTestT<kImportDefault>
     FirstRunMasterPrefsImportDefault;
-IN_PROC_BROWSER_TEST_F(FirstRunMasterPrefsImportDefault, MAYBE_ImportDefault) {
+IN_PROC_BROWSER_TEST_F(FirstRunMasterPrefsImportDefault, ImportDefault) {
   int auto_import_state = first_run::auto_import_state();
-  // Aura builds skip over the import process.
-#if defined(USE_AURA)
-  EXPECT_EQ(first_run::AUTO_IMPORT_CALLED, auto_import_state);
-#else
-  EXPECT_EQ(first_run::AUTO_IMPORT_CALLED |
-                first_run::AUTO_IMPORT_PROFILE_IMPORTED,
+  EXPECT_EQ(MaskExpectedImportState(first_run::AUTO_IMPORT_CALLED |
+                                    first_run::AUTO_IMPORT_PROFILE_IMPORTED),
             auto_import_state);
-#endif
 }
 
-// TODO(tapted): Investigate why this fails on Linux bots but does not
-// reproduce locally. See http://crbug.com/178062 .
-// TODO(tapted): Investigate why this fails on mac_asan flakily
-// http://crbug.com/181499 .
-#if defined(OS_LINUX) || (defined(OS_MACOSX) && defined(ADDRESS_SANITIZER))
-#define MAYBE_ImportBookmarksFile DISABLED_ImportBookmarksFile
-#else
-#define MAYBE_ImportBookmarksFile ImportBookmarksFile
-#endif
-
 // The bookmarks file doesn't actually need to exist for this integration test
 // to trigger the interaction being tested.
 extern const char kImportBookmarksFile[] =
@@ -180,17 +177,13 @@
 typedef FirstRunMasterPrefsBrowserTestT<kImportBookmarksFile>
     FirstRunMasterPrefsImportBookmarksFile;
 IN_PROC_BROWSER_TEST_F(FirstRunMasterPrefsImportBookmarksFile,
-                       MAYBE_ImportBookmarksFile) {
+                       ImportBookmarksFile) {
   int auto_import_state = first_run::auto_import_state();
-  // Aura builds skip over the import process.
-#if defined(USE_AURA)
-  EXPECT_EQ(first_run::AUTO_IMPORT_CALLED, auto_import_state);
-#else
-  EXPECT_EQ(first_run::AUTO_IMPORT_CALLED |
-                first_run::AUTO_IMPORT_PROFILE_IMPORTED |
-                first_run::AUTO_IMPORT_BOOKMARKS_FILE_IMPORTED,
-            auto_import_state);
-#endif
+  EXPECT_EQ(
+      MaskExpectedImportState(first_run::AUTO_IMPORT_CALLED |
+                              first_run::AUTO_IMPORT_PROFILE_IMPORTED |
+                              first_run::AUTO_IMPORT_BOOKMARKS_FILE_IMPORTED),
+      auto_import_state);
 }
 
 // Test an import with all import options disabled. This is a regression test
diff --git a/chrome/browser/first_run/first_run_internal.h b/chrome/browser/first_run/first_run_internal.h
index ae6f152..eec3cf8 100644
--- a/chrome/browser/first_run/first_run_internal.h
+++ b/chrome/browser/first_run/first_run_internal.h
@@ -5,21 +5,8 @@
 #ifndef CHROME_BROWSER_FIRST_RUN_FIRST_RUN_INTERNAL_H_
 #define CHROME_BROWSER_FIRST_RUN_FIRST_RUN_INTERNAL_H_
 
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/gtest_prod_util.h"
-#include "base/memory/ref_counted.h"
-#include "ui/gfx/native_widget_types.h"
-
-class CommandLine;
-class GURL;
-class ImporterHost;
-class ImporterList;
+class MasterPrefs;
 class Profile;
-class ProcessSingleton;
-class TemplateURLService;
 
 namespace base {
 class FilePath;
diff --git a/chrome/browser/first_run/first_run_internal_linux.cc b/chrome/browser/first_run/first_run_internal_linux.cc
new file mode 100644
index 0000000..f2441e2
--- /dev/null
+++ b/chrome/browser/first_run/first_run_internal_linux.cc
@@ -0,0 +1,29 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/first_run/first_run_internal.h"
+
+#include "base/base_paths.h"
+#include "base/files/file_path.h"
+#include "base/path_service.h"
+#include "chrome/installer/util/master_preferences.h"
+
+namespace first_run {
+namespace internal {
+
+bool IsOrganicFirstRun() {
+  // We treat all installs as organic.
+  return true;
+}
+
+base::FilePath MasterPrefsPath() {
+  // The standard location of the master prefs is next to the chrome binary.
+  base::FilePath master_prefs;
+  if (!PathService::Get(base::DIR_EXE, &master_prefs))
+    return base::FilePath();
+  return master_prefs.AppendASCII(installer::kDefaultMasterPrefs);
+}
+
+}  // namespace internal
+}  // namespace first_run
diff --git a/chrome/browser/first_run/first_run_internal_mac.mm b/chrome/browser/first_run/first_run_internal_mac.mm
new file mode 100644
index 0000000..38efc78
--- /dev/null
+++ b/chrome/browser/first_run/first_run_internal_mac.mm
@@ -0,0 +1,17 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/first_run/first_run_internal.h"
+
+#include "chrome/browser/mac/master_prefs.h"
+
+namespace first_run {
+namespace internal {
+
+base::FilePath MasterPrefsPath() {
+  return master_prefs::MasterPrefsPath();
+}
+
+}  // namespace internal
+}  // namespace first_run
diff --git a/chrome/browser/first_run/first_run_internal_posix.cc b/chrome/browser/first_run/first_run_internal_posix.cc
new file mode 100644
index 0000000..ce26df8
--- /dev/null
+++ b/chrome/browser/first_run/first_run_internal_posix.cc
@@ -0,0 +1,66 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/first_run/first_run_internal.h"
+
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/path_service.h"
+#include "base/prefs/pref_service.h"
+#include "build/build_config.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/first_run/first_run_dialog.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/startup_metric_utils.h"
+#include "chrome/installer/util/google_update_settings.h"
+#include "chrome/installer/util/master_preferences.h"
+
+namespace first_run {
+namespace internal {
+
+void DoPostImportPlatformSpecificTasks(Profile* profile) {
+#if !defined(OS_CHROMEOS)
+  // Aura needs a views implementation of the first run dialog for Linux.
+  // http://crbug.com/234637
+#if !defined(USE_AURA)
+  base::FilePath local_state_path;
+  PathService::Get(chrome::FILE_LOCAL_STATE, &local_state_path);
+  bool local_state_file_exists = file_util::PathExists(local_state_path);
+  // Launch the first run dialog only for certain builds, and only if the user
+  // has not already set preferences.
+  if (internal::IsOrganicFirstRun() && !local_state_file_exists) {
+    if (ShowFirstRunDialog(profile))
+      startup_metric_utils::SetNonBrowserUIDisplayed();
+  }
+#endif
+
+  // If stats reporting was turned on by the first run dialog then toggle
+  // the pref (on Windows, the download is tagged with enable/disable stats so
+  // this is POSIX-specific).
+  if (GoogleUpdateSettings::GetCollectStatsConsent()) {
+    g_browser_process->local_state()->SetBoolean(
+        prefs::kMetricsReportingEnabled, true);
+  }
+#endif
+}
+
+bool GetFirstRunSentinelFilePath(base::FilePath* path) {
+  base::FilePath first_run_sentinel;
+
+  if (!PathService::Get(chrome::DIR_USER_DATA, &first_run_sentinel))
+    return false;
+
+  *path = first_run_sentinel.Append(chrome::kFirstRunSentinel);
+  return true;
+}
+
+bool ShowPostInstallEULAIfNeeded(installer::MasterPreferences* install_prefs) {
+  // The EULA is only handled on Windows.
+  return true;
+}
+
+}  // namespace internal
+}  // namespace first_run
diff --git a/chrome/browser/first_run/first_run_internal_win.cc b/chrome/browser/first_run/first_run_internal_win.cc
new file mode 100644
index 0000000..6004248
--- /dev/null
+++ b/chrome/browser/first_run/first_run_internal_win.cc
@@ -0,0 +1,217 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/first_run/first_run_internal.h"
+
+#include <windows.h>
+#include <shellapi.h>
+
+#include "base/base_paths.h"
+#include "base/callback.h"
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/path_service.h"
+#include "base/prefs/pref_service.h"
+#include "base/process.h"
+#include "base/process_util.h"
+#include "base/threading/sequenced_worker_pool.h"
+#include "base/time/time.h"
+#include "base/win/metro.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/installer/util/google_update_settings.h"
+#include "chrome/installer/util/install_util.h"
+#include "chrome/installer/util/master_preferences.h"
+#include "chrome/installer/util/master_preferences_constants.h"
+#include "chrome/installer/util/util_constants.h"
+#include "content/public/browser/browser_thread.h"
+#include "google_update/google_update_idl.h"
+#include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/win/shell.h"
+
+namespace {
+
+// Launches the setup exe with the given parameter/value on the command-line.
+// For non-metro Windows, it waits for its termination, returns its exit code
+// in |*ret_code|, and returns true if the exit code is valid.
+// For metro Windows, it launches setup via ShellExecuteEx and returns in order
+// to bounce the user back to the desktop, then returns immediately.
+bool LaunchSetupForEula(const base::FilePath::StringType& value,
+                        int* ret_code) {
+  base::FilePath exe_dir;
+  if (!PathService::Get(base::DIR_MODULE, &exe_dir))
+    return false;
+  exe_dir = exe_dir.Append(installer::kInstallerDir);
+  base::FilePath exe_path = exe_dir.Append(installer::kSetupExe);
+  base::ProcessHandle ph;
+
+  CommandLine cl(CommandLine::NO_PROGRAM);
+  cl.AppendSwitchNative(installer::switches::kShowEula, value);
+
+  CommandLine* browser_command_line = CommandLine::ForCurrentProcess();
+  if (browser_command_line->HasSwitch(switches::kChromeFrame)) {
+    cl.AppendSwitch(switches::kChromeFrame);
+  }
+
+  if (base::win::IsMetroProcess()) {
+    cl.AppendSwitch(installer::switches::kShowEulaForMetro);
+
+    // This obscure use of the 'log usage' mask for windows 8 is documented here
+    // http://go.microsoft.com/fwlink/?LinkID=243079. It causes the desktop
+    // process to receive focus. Pass SEE_MASK_FLAG_NO_UI to avoid hangs if an
+    // error occurs since the UI can't be shown from a metro process.
+    ui::win::OpenAnyViaShell(exe_path.value(),
+                             exe_dir.value(),
+                             cl.GetCommandLineString(),
+                             SEE_MASK_FLAG_LOG_USAGE | SEE_MASK_FLAG_NO_UI);
+    return false;
+  } else {
+    base::LaunchOptions launch_options;
+    launch_options.wait = true;
+    CommandLine setup_path(exe_path);
+    setup_path.AppendArguments(cl, false);
+
+    DWORD exit_code = 0;
+    if (!base::LaunchProcess(setup_path, launch_options, &ph) ||
+        !::GetExitCodeProcess(ph, &exit_code)) {
+      return false;
+    }
+
+    *ret_code = exit_code;
+    return true;
+  }
+}
+
+// Populates |path| with the path to |file| in the sentinel directory. This is
+// the application directory for user-level installs, and the default user data
+// dir for system-level installs. Returns false on error.
+bool GetSentinelFilePath(const wchar_t* file, base::FilePath* path) {
+  base::FilePath exe_path;
+  if (!PathService::Get(base::DIR_EXE, &exe_path))
+    return false;
+  if (InstallUtil::IsPerUserInstall(exe_path.value().c_str()))
+    *path = exe_path;
+  else if (!PathService::Get(chrome::DIR_USER_DATA, path))
+    return false;
+  *path = path->Append(file);
+  return true;
+}
+
+bool GetEULASentinelFilePath(base::FilePath* path) {
+  return GetSentinelFilePath(installer::kEULASentinelFile, path);
+}
+
+// Returns true if the EULA is required but has not been accepted by this user.
+// The EULA is considered having been accepted if the user has gotten past
+// first run in the "other" environment (desktop or metro).
+bool IsEULANotAccepted(installer::MasterPreferences* install_prefs) {
+  bool value = false;
+  if (install_prefs->GetBool(installer::master_preferences::kRequireEula,
+          &value) && value) {
+    base::FilePath eula_sentinel;
+    // Be conservative and show the EULA if the path to the sentinel can't be
+    // determined.
+    if (!GetEULASentinelFilePath(&eula_sentinel) ||
+        !file_util::PathExists(eula_sentinel)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+// Writes the EULA to a temporary file, returned in |*eula_path|, and returns
+// true if successful.
+bool WriteEULAtoTempFile(base::FilePath* eula_path) {
+  std::string terms = l10n_util::GetStringUTF8(IDS_TERMS_HTML);
+  if (terms.empty())
+    return false;
+  FILE *file = file_util::CreateAndOpenTemporaryFile(eula_path);
+  if (!file)
+    return false;
+  bool good = fwrite(terms.data(), terms.size(), 1, file) == 1;
+  fclose(file);
+  return good;
+}
+
+// Creates the sentinel indicating that the EULA was required and has been
+// accepted.
+bool CreateEULASentinel() {
+  base::FilePath eula_sentinel;
+  if (!GetEULASentinelFilePath(&eula_sentinel))
+    return false;
+
+  return (file_util::CreateDirectory(eula_sentinel.DirName()) &&
+          file_util::WriteFile(eula_sentinel, "", 0) != -1);
+}
+
+}  // namespace
+
+namespace first_run {
+namespace internal {
+
+void DoPostImportPlatformSpecificTasks(Profile* /* profile */) {
+  // Trigger the Active Setup command for system-level Chromes to finish
+  // configuring this user's install (e.g. per-user shortcuts).
+  // Delay the task slightly to give Chrome launch I/O priority while also
+  // making sure shortcuts are created promptly to avoid annoying the user by
+  // re-creating shortcuts he previously deleted.
+  static const int64 kTiggerActiveSetupDelaySeconds = 5;
+  base::FilePath chrome_exe;
+  if (!PathService::Get(base::FILE_EXE, &chrome_exe)) {
+    NOTREACHED();
+  } else if (!InstallUtil::IsPerUserInstall(chrome_exe.value().c_str())) {
+    content::BrowserThread::GetBlockingPool()->PostDelayedTask(
+        FROM_HERE,
+        base::Bind(&InstallUtil::TriggerActiveSetupCommand),
+        base::TimeDelta::FromSeconds(kTiggerActiveSetupDelaySeconds));
+  }
+}
+
+bool GetFirstRunSentinelFilePath(base::FilePath* path) {
+  return GetSentinelFilePath(chrome::kFirstRunSentinel, path);
+}
+
+bool ShowPostInstallEULAIfNeeded(installer::MasterPreferences* install_prefs) {
+  if (IsEULANotAccepted(install_prefs)) {
+    // Show the post-installation EULA. This is done by setup.exe and the
+    // result determines if we continue or not. We wait here until the user
+    // dismisses the dialog.
+
+    // The actual eula text is in a resource in chrome. We extract it to
+    // a text file so setup.exe can use it as an inner frame.
+    base::FilePath inner_html;
+    if (WriteEULAtoTempFile(&inner_html)) {
+      int retcode = 0;
+      if (!LaunchSetupForEula(inner_html.value(), &retcode) ||
+          (retcode != installer::EULA_ACCEPTED &&
+           retcode != installer::EULA_ACCEPTED_OPT_IN)) {
+        LOG(WARNING) << "EULA flow requires fast exit.";
+        return false;
+      }
+      CreateEULASentinel();
+
+      if (retcode == installer::EULA_ACCEPTED) {
+        VLOG(1) << "EULA : no collection";
+        GoogleUpdateSettings::SetCollectStatsConsent(false);
+      } else if (retcode == installer::EULA_ACCEPTED_OPT_IN) {
+        VLOG(1) << "EULA : collection consent";
+        GoogleUpdateSettings::SetCollectStatsConsent(true);
+      }
+    }
+  }
+  return true;
+}
+
+base::FilePath MasterPrefsPath() {
+  // The standard location of the master prefs is next to the chrome binary.
+  base::FilePath master_prefs;
+  if (!PathService::Get(base::DIR_EXE, &master_prefs))
+    return base::FilePath();
+  return master_prefs.AppendASCII(installer::kDefaultMasterPrefs);
+}
+
+}  // namespace internal
+}  // namespace first_run
diff --git a/chrome/browser/first_run/first_run_linux.cc b/chrome/browser/first_run/first_run_linux.cc
deleted file mode 100644
index 4d4d084..0000000
--- a/chrome/browser/first_run/first_run_linux.cc
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/first_run/first_run.h"
-
-#include "base/command_line.h"
-#include "base/files/file_path.h"
-#include "base/path_service.h"
-#include "base/process_util.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/first_run/first_run_internal.h"
-#include "chrome/browser/importer/importer_host.h"
-#include "chrome/browser/process_singleton.h"
-#include "chrome/browser/shell_integration.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/installer/util/google_update_settings.h"
-#include "chrome/installer/util/master_preferences.h"
-#include "content/public/common/result_codes.h"
-#include "googleurl/src/gurl.h"
-#include "ui/base/ui_base_switches.h"
-
-namespace first_run {
-namespace internal {
-
-bool IsOrganicFirstRun() {
-  // We treat all installs as organic.
-  return true;
-}
-
-base::FilePath MasterPrefsPath() {
-  // The standard location of the master prefs is next to the chrome binary.
-  base::FilePath master_prefs;
-  if (!PathService::Get(base::DIR_EXE, &master_prefs))
-    return base::FilePath();
-  return master_prefs.AppendASCII(installer::kDefaultMasterPrefs);
-}
-
-}  // namespace internal
-}  // namespace first_run
diff --git a/chrome/browser/first_run/first_run_mac.mm b/chrome/browser/first_run/first_run_mac.mm
deleted file mode 100644
index 85a43d2..0000000
--- a/chrome/browser/first_run/first_run_mac.mm
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/first_run/first_run.h"
-
-#include "base/files/file_path.h"
-#include "base/strings/string_util.h"
-#include "chrome/browser/first_run/first_run_internal.h"
-#include "chrome/browser/importer/external_process_importer_host.h"
-#include "chrome/browser/importer/importer_host.h"
-#include "chrome/browser/mac/master_prefs.h"
-#include "chrome/browser/process_singleton.h"
-
-namespace first_run {
-namespace internal {
-
-base::FilePath MasterPrefsPath() {
-  return master_prefs::MasterPrefsPath();
-}
-
-}  // namespace internal
-}  // namespace first_run
diff --git a/chrome/browser/first_run/first_run_posix.cc b/chrome/browser/first_run/first_run_posix.cc
deleted file mode 100644
index 7498a90..0000000
--- a/chrome/browser/first_run/first_run_posix.cc
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/first_run/first_run.h"
-
-#include "base/file_util.h"
-#include "base/files/file_path.h"
-#include "base/path_service.h"
-#include "base/prefs/pref_service.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/first_run/first_run_dialog.h"
-#include "chrome/browser/first_run/first_run_internal.h"
-#include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/common/chrome_constants.h"
-#include "chrome/common/chrome_paths.h"
-#include "chrome/common/pref_names.h"
-#include "chrome/common/startup_metric_utils.h"
-#include "chrome/installer/util/google_update_settings.h"
-#include "chrome/installer/util/master_preferences.h"
-
-namespace first_run {
-namespace internal {
-
-void DoPostImportPlatformSpecificTasks(Profile* profile) {
-#if !defined(OS_CHROMEOS)
-  // Aura needs a views implementation of the first run dialog for Linux.
-  // http://crbug.com/234637
-#if !defined(USE_AURA)
-  base::FilePath local_state_path;
-  PathService::Get(chrome::FILE_LOCAL_STATE, &local_state_path);
-  bool local_state_file_exists = file_util::PathExists(local_state_path);
-  // Launch the first run dialog only for certain builds, and only if the user
-  // has not already set preferences.
-  if (internal::IsOrganicFirstRun() && !local_state_file_exists) {
-    if (ShowFirstRunDialog(profile))
-      startup_metric_utils::SetNonBrowserUIDisplayed();
-  }
-#endif
-
-  // If stats reporting was turned on by the first run dialog then toggle
-  // the pref (on Windows, the download is tagged with enable/disable stats so
-  // this is POSIX-specific).
-  if (GoogleUpdateSettings::GetCollectStatsConsent()) {
-    g_browser_process->local_state()->SetBoolean(
-        prefs::kMetricsReportingEnabled, true);
-  }
-#endif
-}
-
-bool GetFirstRunSentinelFilePath(base::FilePath* path) {
-  base::FilePath first_run_sentinel;
-
-  if (!PathService::Get(chrome::DIR_USER_DATA, &first_run_sentinel))
-    return false;
-
-  *path = first_run_sentinel.Append(chrome::kFirstRunSentinel);
-  return true;
-}
-
-bool ShowPostInstallEULAIfNeeded(installer::MasterPreferences* install_prefs) {
-  // The EULA is only handled on Windows.
-  return true;
-}
-
-}  // namespace internal
-}  // namespace first_run
diff --git a/chrome/browser/first_run/first_run_win.cc b/chrome/browser/first_run/first_run_win.cc
deleted file mode 100644
index 7aa0e5d..0000000
--- a/chrome/browser/first_run/first_run_win.cc
+++ /dev/null
@@ -1,217 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/first_run/first_run.h"
-
-#include <shellapi.h>
-
-#include "base/base_paths.h"
-#include "base/callback.h"
-#include "base/file_util.h"
-#include "base/files/file_path.h"
-#include "base/path_service.h"
-#include "base/prefs/pref_service.h"
-#include "base/process.h"
-#include "base/process_util.h"
-#include "base/threading/sequenced_worker_pool.h"
-#include "base/time.h"
-#include "base/win/metro.h"
-#include "chrome/browser/first_run/first_run_internal.h"
-#include "chrome/common/chrome_constants.h"
-#include "chrome/common/chrome_paths.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/installer/util/google_update_settings.h"
-#include "chrome/installer/util/install_util.h"
-#include "chrome/installer/util/master_preferences.h"
-#include "chrome/installer/util/master_preferences_constants.h"
-#include "chrome/installer/util/util_constants.h"
-#include "content/public/browser/browser_thread.h"
-#include "google_update/google_update_idl.h"
-#include "grit/locale_settings.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/base/win/shell.h"
-
-namespace {
-
-// Launches the setup exe with the given parameter/value on the command-line.
-// For non-metro Windows, it waits for its termination, returns its exit code
-// in |*ret_code|, and returns true if the exit code is valid.
-// For metro Windows, it launches setup via ShellExecuteEx and returns in order
-// to bounce the user back to the desktop, then returns immediately.
-bool LaunchSetupForEula(const base::FilePath::StringType& value,
-                        int* ret_code) {
-  base::FilePath exe_dir;
-  if (!PathService::Get(base::DIR_MODULE, &exe_dir))
-    return false;
-  exe_dir = exe_dir.Append(installer::kInstallerDir);
-  base::FilePath exe_path = exe_dir.Append(installer::kSetupExe);
-  base::ProcessHandle ph;
-
-  CommandLine cl(CommandLine::NO_PROGRAM);
-  cl.AppendSwitchNative(installer::switches::kShowEula, value);
-
-  CommandLine* browser_command_line = CommandLine::ForCurrentProcess();
-  if (browser_command_line->HasSwitch(switches::kChromeFrame)) {
-    cl.AppendSwitch(switches::kChromeFrame);
-  }
-
-  if (base::win::IsMetroProcess()) {
-    cl.AppendSwitch(installer::switches::kShowEulaForMetro);
-
-    // This obscure use of the 'log usage' mask for windows 8 is documented here
-    // http://go.microsoft.com/fwlink/?LinkID=243079. It causes the desktop
-    // process to receive focus. Pass SEE_MASK_FLAG_NO_UI to avoid hangs if an
-    // error occurs since the UI can't be shown from a metro process.
-    ui::win::OpenAnyViaShell(exe_path.value(),
-                             exe_dir.value(),
-                             cl.GetCommandLineString(),
-                             SEE_MASK_FLAG_LOG_USAGE | SEE_MASK_FLAG_NO_UI);
-    return false;
-  } else {
-    base::LaunchOptions launch_options;
-    launch_options.wait = true;
-    CommandLine setup_path(exe_path);
-    setup_path.AppendArguments(cl, false);
-
-    DWORD exit_code = 0;
-    if (!base::LaunchProcess(setup_path, launch_options, &ph) ||
-        !::GetExitCodeProcess(ph, &exit_code)) {
-      return false;
-    }
-
-    *ret_code = exit_code;
-    return true;
-  }
-}
-
-// Populates |path| with the path to |file| in the sentinel directory. This is
-// the application directory for user-level installs, and the default user data
-// dir for system-level installs. Returns false on error.
-bool GetSentinelFilePath(const wchar_t* file, base::FilePath* path) {
-  base::FilePath exe_path;
-  if (!PathService::Get(base::DIR_EXE, &exe_path))
-    return false;
-  if (InstallUtil::IsPerUserInstall(exe_path.value().c_str()))
-    *path = exe_path;
-  else if (!PathService::Get(chrome::DIR_USER_DATA, path))
-    return false;
-  *path = path->Append(file);
-  return true;
-}
-
-bool GetEULASentinelFilePath(base::FilePath* path) {
-  return GetSentinelFilePath(installer::kEULASentinelFile, path);
-}
-
-// Returns true if the EULA is required but has not been accepted by this user.
-// The EULA is considered having been accepted if the user has gotten past
-// first run in the "other" environment (desktop or metro).
-bool IsEULANotAccepted(installer::MasterPreferences* install_prefs) {
-  bool value = false;
-  if (install_prefs->GetBool(installer::master_preferences::kRequireEula,
-          &value) && value) {
-    base::FilePath eula_sentinel;
-    // Be conservative and show the EULA if the path to the sentinel can't be
-    // determined.
-    if (!GetEULASentinelFilePath(&eula_sentinel) ||
-        !file_util::PathExists(eula_sentinel)) {
-      return true;
-    }
-  }
-  return false;
-}
-
-// Writes the EULA to a temporary file, returned in |*eula_path|, and returns
-// true if successful.
-bool WriteEULAtoTempFile(base::FilePath* eula_path) {
-  std::string terms = l10n_util::GetStringUTF8(IDS_TERMS_HTML);
-  if (terms.empty())
-    return false;
-  FILE *file = file_util::CreateAndOpenTemporaryFile(eula_path);
-  if (!file)
-    return false;
-  bool good = fwrite(terms.data(), terms.size(), 1, file) == 1;
-  fclose(file);
-  return good;
-}
-
-// Creates the sentinel indicating that the EULA was required and has been
-// accepted.
-bool CreateEULASentinel() {
-  base::FilePath eula_sentinel;
-  if (!GetEULASentinelFilePath(&eula_sentinel))
-    return false;
-
-  return (file_util::CreateDirectory(eula_sentinel.DirName()) &&
-          file_util::WriteFile(eula_sentinel, "", 0) != -1);
-}
-
-}  // namespace
-
-namespace first_run {
-namespace internal {
-
-void DoPostImportPlatformSpecificTasks(Profile* /* profile */) {
-  // Trigger the Active Setup command for system-level Chromes to finish
-  // configuring this user's install (e.g. per-user shortcuts).
-  // Delay the task slightly to give Chrome launch I/O priority while also
-  // making sure shortcuts are created promptly to avoid annoying the user by
-  // re-creating shortcuts he previously deleted.
-  static const int64 kTiggerActiveSetupDelaySeconds = 5;
-  base::FilePath chrome_exe;
-  if (!PathService::Get(base::FILE_EXE, &chrome_exe)) {
-    NOTREACHED();
-  } else if (!InstallUtil::IsPerUserInstall(chrome_exe.value().c_str())) {
-    content::BrowserThread::GetBlockingPool()->PostDelayedTask(
-        FROM_HERE,
-        base::Bind(&InstallUtil::TriggerActiveSetupCommand),
-        base::TimeDelta::FromSeconds(kTiggerActiveSetupDelaySeconds));
-  }
-}
-
-bool GetFirstRunSentinelFilePath(base::FilePath* path) {
-  return GetSentinelFilePath(chrome::kFirstRunSentinel, path);
-}
-
-bool ShowPostInstallEULAIfNeeded(installer::MasterPreferences* install_prefs) {
-  if (IsEULANotAccepted(install_prefs)) {
-    // Show the post-installation EULA. This is done by setup.exe and the
-    // result determines if we continue or not. We wait here until the user
-    // dismisses the dialog.
-
-    // The actual eula text is in a resource in chrome. We extract it to
-    // a text file so setup.exe can use it as an inner frame.
-    base::FilePath inner_html;
-    if (WriteEULAtoTempFile(&inner_html)) {
-      int retcode = 0;
-      if (!LaunchSetupForEula(inner_html.value(), &retcode) ||
-          (retcode != installer::EULA_ACCEPTED &&
-           retcode != installer::EULA_ACCEPTED_OPT_IN)) {
-        LOG(WARNING) << "EULA flow requires fast exit.";
-        return false;
-      }
-      CreateEULASentinel();
-
-      if (retcode == installer::EULA_ACCEPTED) {
-        VLOG(1) << "EULA : no collection";
-        GoogleUpdateSettings::SetCollectStatsConsent(false);
-      } else if (retcode == installer::EULA_ACCEPTED_OPT_IN) {
-        VLOG(1) << "EULA : collection consent";
-        GoogleUpdateSettings::SetCollectStatsConsent(true);
-      }
-    }
-  }
-  return true;
-}
-
-base::FilePath MasterPrefsPath() {
-  // The standard location of the master prefs is next to the chrome binary.
-  base::FilePath master_prefs;
-  if (!PathService::Get(base::DIR_EXE, &master_prefs))
-    return base::FilePath();
-  return master_prefs.AppendASCII(installer::kDefaultMasterPrefs);
-}
-
-}  // namespace internal
-}  // namespace first_run
diff --git a/chrome/browser/geolocation/chrome_access_token_store.cc b/chrome/browser/geolocation/chrome_access_token_store.cc
index 9bf2b9f..cefb644 100644
--- a/chrome/browser/geolocation/chrome_access_token_store.cc
+++ b/chrome/browser/geolocation/chrome_access_token_store.cc
@@ -14,7 +14,7 @@
 #include "chrome/browser/prefs/scoped_user_pref_update.h"
 #include "chrome/common/pref_names.h"
 #include "content/public/browser/browser_thread.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 using content::AccessTokenStore;
 using content::BrowserThread;
diff --git a/chrome/browser/geolocation/geolocation_browsertest.cc b/chrome/browser/geolocation/geolocation_browsertest.cc
index 9ffc81a..597ce45 100644
--- a/chrome/browser/geolocation/geolocation_browsertest.cc
+++ b/chrome/browser/geolocation/geolocation_browsertest.cc
@@ -31,7 +31,7 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test_utils.h"
 #include "net/base/net_util.h"
-#include "net/test/spawned_test_server/spawned_test_server.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
 
 using content::DomOperationNotificationDetails;
 using content::NavigationController;
@@ -274,9 +274,6 @@
   double fake_latitude_;
   double fake_longitude_;
 
-  // TODO(phajdan.jr): Remove after we can ask TestServer whether it is started.
-  bool started_test_server_;
-
  private:
   DISALLOW_COPY_AND_ASSIGN(GeolocationBrowserTest);
 };
@@ -284,10 +281,10 @@
 GeolocationBrowserTest::GeolocationBrowserTest()
   : infobar_(NULL),
     current_browser_(NULL),
-    html_for_tests_("files/geolocation/simple.html"),
+    html_for_tests_("/geolocation/simple.html"),
     fake_latitude_(1.23),
-    fake_longitude_(4.56),
-    started_test_server_(false) {}
+    fake_longitude_(4.56) {
+}
 
 void GeolocationBrowserTest::SetUpOnMainThread() {
   ui_test_utils::OverrideGeolocation(fake_latitude_, fake_longitude_);
@@ -298,13 +295,13 @@
 }
 
 bool GeolocationBrowserTest::Initialize(InitializationOptions options) {
-  if (!started_test_server_)
-    started_test_server_ = test_server()->Start();
-  EXPECT_TRUE(started_test_server_);
-  if (!started_test_server_)
+  if (!embedded_test_server()->Started() &&
+      !embedded_test_server()->InitializeAndWaitUntilReady()) {
+    ADD_FAILURE() << "Test server failed to start.";
     return false;
+  }
 
-  current_url_ = test_server()->GetURL(html_for_tests_);
+  current_url_ = embedded_test_server()->GetURL(html_for_tests_);
   LOG(WARNING) << "before navigate";
   if (options == INITIALIZATION_OFFTHERECORD) {
     current_browser_ = ui_test_utils::OpenURLOffTheRecord(
@@ -540,7 +537,7 @@
 // crbug.com/176291
 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest,
                        DISABLED_IFramesWithFreshPosition) {
-  html_for_tests_ = "files/geolocation/iframes_different_origin.html";
+  html_for_tests_ = "/geolocation/iframes_different_origin.html";
   ASSERT_TRUE(Initialize(INITIALIZATION_IFRAMES));
   LoadIFrames(2);
   LOG(WARNING) << "frames loaded";
@@ -585,7 +582,7 @@
 
 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest,
                        IFramesWithCachedPosition) {
-  html_for_tests_ = "files/geolocation/iframes_different_origin.html";
+  html_for_tests_ = "/geolocation/iframes_different_origin.html";
   ASSERT_TRUE(Initialize(INITIALIZATION_IFRAMES));
   LoadIFrames(2);
 
@@ -624,7 +621,7 @@
 // crbug.com/176291
 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest,
                        DISABLED_CancelPermissionForFrame) {
-  html_for_tests_ = "files/geolocation/iframes_different_origin.html";
+  html_for_tests_ = "/geolocation/iframes_different_origin.html";
   ASSERT_TRUE(Initialize(INITIALIZATION_IFRAMES));
   LoadIFrames(2);
   LOG(WARNING) << "frames loaded";
@@ -653,7 +650,7 @@
 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, InvalidUrlRequest) {
   // Tests that an invalid URL (e.g. from a popup window) is rejected
   // correctly. Also acts as a regression test for http://crbug.com/40478
-  html_for_tests_ = "files/geolocation/invalid_request_url.html";
+  html_for_tests_ = "/geolocation/invalid_request_url.html";
   ASSERT_TRUE(Initialize(INITIALIZATION_NONE));
   WebContents* original_tab =
       current_browser_->tab_strip_model()->GetActiveWebContents();
@@ -663,7 +660,7 @@
 
 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, NoInfoBarBeforeStart) {
   // See http://crbug.com/42789
-  html_for_tests_ = "files/geolocation/iframes_different_origin.html";
+  html_for_tests_ = "/geolocation/iframes_different_origin.html";
   ASSERT_TRUE(Initialize(INITIALIZATION_IFRAMES));
   LoadIFrames(2);
   LOG(WARNING) << "frames loaded";
@@ -686,7 +683,7 @@
 }
 
 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, TwoWatchesInOneFrame) {
-  html_for_tests_ = "files/geolocation/two_watches.html";
+  html_for_tests_ = "/geolocation/two_watches.html";
   ASSERT_TRUE(Initialize(INITIALIZATION_NONE));
   // First, set the JavaScript to navigate when it receives |final_position|.
   double final_position_latitude = 3.17;
@@ -720,7 +717,7 @@
 
 // crbug.com/176291
 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, DISABLED_TabDestroyed) {
-  html_for_tests_ = "files/geolocation/tab_destroyed.html";
+  html_for_tests_ = "/geolocation/tab_destroyed.html";
   ASSERT_TRUE(Initialize(INITIALIZATION_IFRAMES));
   LoadIFrames(3);
 
diff --git a/chrome/browser/geolocation/geolocation_infobar_delegate.h b/chrome/browser/geolocation/geolocation_infobar_delegate.h
index 64e2f2b..d149836 100644
--- a/chrome/browser/geolocation/geolocation_infobar_delegate.h
+++ b/chrome/browser/geolocation/geolocation_infobar_delegate.h
@@ -5,11 +5,11 @@
 #ifndef CHROME_BROWSER_GEOLOCATION_GEOLOCATION_INFOBAR_DELEGATE_H_
 #define CHROME_BROWSER_GEOLOCATION_GEOLOCATION_INFOBAR_DELEGATE_H_
 
+#include <string>
+
 #include "chrome/browser/geolocation/geolocation_permission_request_id.h"
 #include "chrome/browser/infobars/confirm_infobar_delegate.h"
-#include "googleurl/src/gurl.h"
-
-#include <string>
+#include "url/gurl.h"
 
 class GeolocationInfoBarQueueController;
 class InfoBarService;
diff --git a/chrome/browser/geolocation/geolocation_settings_state.h b/chrome/browser/geolocation/geolocation_settings_state.h
index e927626..c5f9948 100644
--- a/chrome/browser/geolocation/geolocation_settings_state.h
+++ b/chrome/browser/geolocation/geolocation_settings_state.h
@@ -9,7 +9,7 @@
 #include <set>
 
 #include "chrome/common/content_settings.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 class Profile;
 
diff --git a/chrome/browser/google/google_search_counter.cc b/chrome/browser/google/google_search_counter.cc
index e15da72..ecf670c8 100644
--- a/chrome/browser/google/google_search_counter.cc
+++ b/chrome/browser/google/google_search_counter.cc
@@ -20,7 +20,7 @@
 bool IsOmniboxGoogleSearchNavigation(const content::NavigationEntry& entry) {
   const content::PageTransition stripped_transition =
       PageTransitionStripQualifier(entry.GetTransitionType());
-  DCHECK(google_util::IsGoogleSearchUrl(entry.GetURL().spec()));
+  DCHECK(google_util::IsGoogleSearchUrl(entry.GetURL()));
   return stripped_transition == content::PAGE_TRANSITION_GENERATED;
 }
 
@@ -28,7 +28,7 @@
 // App. This method assumes that we have already verified that |entry|'s URL is
 // a Google search URL.
 bool IsSearchAppGoogleSearchNavigation(const content::NavigationEntry& entry) {
-  DCHECK(google_util::IsGoogleSearchUrl(entry.GetURL().spec()));
+  DCHECK(google_util::IsGoogleSearchUrl(entry.GetURL()));
   return entry.GetURL().query().find("source=search_app") !=
          std::string::npos;
 }
@@ -60,7 +60,7 @@
   const content::NavigationEntry& entry = *commit->entry;
 
   // First see if this is a Google search URL at all.
-  if (!google_util::IsGoogleSearchUrl(entry.GetURL().spec()))
+  if (!google_util::IsGoogleSearchUrl(entry.GetURL()))
     return;
 
   // If the commit is a GENERATED commit with a Google search URL, we know it's
diff --git a/chrome/browser/google/google_update_settings_posix.cc b/chrome/browser/google/google_update_settings_posix.cc
index 0bced14..c4bd2cd 100644
--- a/chrome/browser/google/google_update_settings_posix.cc
+++ b/chrome/browser/google/google_update_settings_posix.cc
@@ -51,7 +51,7 @@
     }
   } else {
     google_update::posix_guid().clear();
-    return file_util::Delete(consent_file, false);
+    return base::Delete(consent_file, false);
   }
   return true;
 }
diff --git a/chrome/browser/google/google_update_win.cc b/chrome/browser/google/google_update_win.cc
index 8192412..5b9dd1b 100644
--- a/chrome/browser/google/google_update_win.cc
+++ b/chrome/browser/google/google_update_win.cc
@@ -60,10 +60,15 @@
       !InstallUtil::IsPerUserInstall(chrome_exe_path.value().c_str()));
   DCHECK(!app_guid.empty());
 
-  if (GoogleUpdateSettings::GetAppUpdatePolicy(app_guid, NULL) ==
-      GoogleUpdateSettings::UPDATES_DISABLED)
+  GoogleUpdateSettings::UpdatePolicy update_policy =
+      GoogleUpdateSettings::GetAppUpdatePolicy(app_guid, NULL);
+
+  if (update_policy == GoogleUpdateSettings::UPDATES_DISABLED)
     return GOOGLE_UPDATE_DISABLED_BY_POLICY;
 
+  if (update_policy == GoogleUpdateSettings::AUTO_UPDATES_ONLY)
+    return GOOGLE_UPDATE_DISABLED_BY_POLICY_AUTO_ONLY;
+
   return GOOGLE_UPDATE_NO_ERROR;
 #endif
 }
diff --git a/chrome/browser/google/google_update_win.h b/chrome/browser/google/google_update_win.h
index d9b8951..06e5fe2 100644
--- a/chrome/browser/google/google_update_win.h
+++ b/chrome/browser/google/google_update_win.h
@@ -56,8 +56,12 @@
   // An error occurred while upgrading (or while checking for update).
   // Check the Google Update log in %TEMP% for more details.
   GOOGLE_UPDATE_ERROR_UPDATING,
-  // Updates can not be downloaded because the administrator has disabled them.
+  // Updates can not be downloaded because the administrator has disabled all
+  // types of updating.
   GOOGLE_UPDATE_DISABLED_BY_POLICY,
+  // Updates can not be downloaded because the administrator has disabled
+  // manual (on-demand) updates.  Automatic background updates are allowed.
+  GOOGLE_UPDATE_DISABLED_BY_POLICY_AUTO_ONLY,
 };
 
 // The GoogleUpdateStatusListener interface is used by components to receive
diff --git a/chrome/browser/google/google_url_tracker.cc b/chrome/browser/google/google_url_tracker.cc
index 0f78cfb..2472417 100644
--- a/chrome/browser/google/google_url_tracker.cc
+++ b/chrome/browser/google/google_url_tracker.cc
@@ -139,8 +139,7 @@
   GURL url(url_str);
   if (!url.is_valid() || (url.path().length() > 1) || url.has_query() ||
       url.has_ref() ||
-      !google_util::IsGoogleDomainUrl(url.spec(),
-                                      google_util::DISALLOW_SUBDOMAIN,
+      !google_util::IsGoogleDomainUrl(url, google_util::DISALLOW_SUBDOMAIN,
                                       google_util::DISALLOW_NON_STANDARD_PORTS))
     return;
 
diff --git a/chrome/browser/google/google_url_tracker.h b/chrome/browser/google/google_url_tracker.h
index 2784179..d71e7e7 100644
--- a/chrome/browser/google/google_url_tracker.h
+++ b/chrome/browser/google/google_url_tracker.h
@@ -15,10 +15,10 @@
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/google/google_url_tracker_map_entry.h"
 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/network_change_notifier.h"
 #include "net/url_request/url_fetcher.h"
 #include "net/url_request/url_fetcher_delegate.h"
+#include "url/gurl.h"
 
 class GoogleURLTrackerNavigationHelper;
 class PrefService;
diff --git a/chrome/browser/google/google_url_tracker_infobar_delegate.h b/chrome/browser/google/google_url_tracker_infobar_delegate.h
index 694d6ba..7e01655 100644
--- a/chrome/browser/google/google_url_tracker_infobar_delegate.h
+++ b/chrome/browser/google/google_url_tracker_infobar_delegate.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_GOOGLE_GOOGLE_URL_TRACKER_INFOBAR_DELEGATE_H_
 
 #include "chrome/browser/infobars/confirm_infobar_delegate.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 class GoogleURLTracker;
 
diff --git a/chrome/browser/google/google_url_tracker_navigation_helper_impl.cc b/chrome/browser/google/google_url_tracker_navigation_helper_impl.cc
index 8a1cb14..867a84f 100644
--- a/chrome/browser/google/google_url_tracker_navigation_helper_impl.cc
+++ b/chrome/browser/google/google_url_tracker_navigation_helper_impl.cc
@@ -31,13 +31,9 @@
   if (listen) {
     registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_PENDING,
         content::NotificationService::AllBrowserContextsAndSources());
-    registrar_.Add(this, chrome::NOTIFICATION_INSTANT_COMMITTED,
-        content::NotificationService::AllBrowserContextsAndSources());
   } else {
     registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_PENDING,
         content::NotificationService::AllBrowserContextsAndSources());
-    registrar_.Remove(this, chrome::NOTIFICATION_INSTANT_COMMITTED,
-        content::NotificationService::AllBrowserContextsAndSources());
   }
 }
 
@@ -148,33 +144,7 @@
       break;
     }
 
-    case chrome::NOTIFICATION_INSTANT_COMMITTED: {
-      content::WebContents* web_contents =
-          content::Source<content::WebContents>(source).ptr();
-      content::NavigationController* nav_controller =
-          &web_contents->GetController();
-      const GURL& search_url = web_contents->GetURL();
-      if (!search_url.is_valid())  // Not clear if this can happen.
-        tracker_->OnTabClosed(nav_controller);
-      OnInstantCommitted(nav_controller,
-                         InfoBarService::FromWebContents(web_contents),
-                         search_url);
-      break;
-    }
-
     default:
       NOTREACHED() << "Unknown notification received:" << type;
   }
 }
-
-void GoogleURLTrackerNavigationHelperImpl::OnInstantCommitted(
-    content::NavigationController* nav_controller,
-    InfoBarService* infobar_service,
-    const GURL& search_url) {
-  // Call OnNavigationPending, giving |tracker_| the option to register for
-  // navigation commit messages for this navigation controller. If it does
-  // register for them, simulate the commit as well.
-  tracker_->OnNavigationPending(nav_controller, infobar_service, 0);
-  if (IsListeningForNavigationCommit(nav_controller))
-    tracker_->OnNavigationCommitted(infobar_service, search_url);
-}
diff --git a/chrome/browser/google/google_url_tracker_navigation_helper_impl.h b/chrome/browser/google/google_url_tracker_navigation_helper_impl.h
index a710b5e..2900590 100644
--- a/chrome/browser/google/google_url_tracker_navigation_helper_impl.h
+++ b/chrome/browser/google/google_url_tracker_navigation_helper_impl.h
@@ -8,7 +8,7 @@
 #include "chrome/browser/google/google_url_tracker_navigation_helper.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 class GoogleURLTrackerNavigationHelperImpl
     : public GoogleURLTrackerNavigationHelper,
@@ -40,12 +40,6 @@
                        const content::NotificationSource& source,
                        const content::NotificationDetails& details) OVERRIDE;
 
-  // Handles instant commit notifications by simulating the relevant navigation
-  // callbacks.
-  void OnInstantCommitted(content::NavigationController* nav_controller,
-                          InfoBarService* infobar_service,
-                          const GURL& search_url);
-
   // Returns a WebContents NavigationSource for the WebContents corresponding to
   // the given NavigationController NotificationSource.
   virtual content::NotificationSource GetWebContentsSource(
diff --git a/chrome/browser/google/google_util.cc b/chrome/browser/google/google_util.cc
index e2c09ec..d14ec5a 100644
--- a/chrome/browser/google/google_util.cc
+++ b/chrome/browser/google/google_util.cc
@@ -17,9 +17,9 @@
 #include "chrome/browser/google/google_url_tracker.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/installer/util/google_update_settings.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
 #include "net/base/url_util.h"
+#include "url/gurl.h"
 
 #if defined(OS_MACOSX)
 #include "chrome/browser/mac/keystone_glue.h"
@@ -35,16 +35,25 @@
 #define LINKDOCTOR_SERVER_REQUEST_URL std::string()
 #endif
 
+
+// Helpers --------------------------------------------------------------------
+
 namespace {
 
 const char* brand_for_testing = NULL;
-
 bool gUseMockLinkDoctorBaseURLForTesting = false;
 
-}  // anonymous namespace
+bool IsPathHomePageBase(const std::string& path) {
+  return (path == "/") || (path == "/webhp");
+}
+
+}  // namespace
+
 
 namespace google_util {
 
+// Global functions -----------------------------------------------------------
+
 bool HasGoogleSearchQueryParam(const std::string& str) {
   url_parse::Component query(0, str.length()), key, value;
   while (url_parse::ExtractQueryKeyValue(str.c_str(), &query, &key,
@@ -65,15 +74,6 @@
   gUseMockLinkDoctorBaseURLForTesting = true;
 }
 
-BrandForTesting::BrandForTesting(const std::string& brand) : brand_(brand) {
-  DCHECK(brand_for_testing == NULL);
-  brand_for_testing = brand_.c_str();
-}
-
-BrandForTesting::~BrandForTesting() {
-  brand_for_testing = NULL;
-}
-
 GURL AppendGoogleLocaleParam(const GURL& url) {
   // Google does not yet recognize 'nb' for Norwegian Bokmal, but it uses
   // 'no' for that.
@@ -152,32 +152,23 @@
 
 #endif
 
-bool IsGoogleDomainUrl(const std::string& url,
-                       SubdomainPermission subdomain_permission,
-                       PortPermission port_permission) {
-  GURL original_url(url);
-  if (!original_url.is_valid() ||
-      !(original_url.SchemeIs("http") || original_url.SchemeIs("https")))
-    return false;
-
-  // If we have the Instant URL overridden with a command line flag, accept
-  // its domain/port combination as well.
-  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
-  if (command_line.HasSwitch(switches::kInstantURL)) {
-    GURL custom_instant_url(
-        command_line.GetSwitchValueASCII(switches::kInstantURL));
-    if (original_url.host() == custom_instant_url.host() &&
-        original_url.port() == custom_instant_url.port())
-      return true;
-  }
-
-  return (original_url.port().empty() ||
-      port_permission == ALLOW_NON_STANDARD_PORTS) &&
-      google_util::IsGoogleHostname(original_url.host(), subdomain_permission);
+bool StartsWithCommandLineGoogleBaseURL(const GURL& url) {
+  const std::string base_url(CommandLine::ForCurrentProcess()->
+      GetSwitchValueASCII(switches::kGoogleBaseURL));
+  return !base_url.empty() &&
+      StartsWithASCII(url.possibly_invalid_spec(), base_url, true);
 }
 
 bool IsGoogleHostname(const std::string& host,
                       SubdomainPermission subdomain_permission) {
+  const std::string base_url(CommandLine::ForCurrentProcess()->
+      GetSwitchValueASCII(switches::kGoogleBaseURL));
+  if (!base_url.empty()) {
+    GURL base_gurl(base_url);
+    if (base_gurl.is_valid() && (host == base_gurl.host()))
+      return true;
+  }
+
   size_t tld_length = net::registry_controlled_domains::GetRegistryLength(
       host,
       net::registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES,
@@ -192,51 +183,39 @@
   return LowerCaseEqualsASCII(host_minus_tld, "www.google.");
 }
 
-bool IsGoogleHomePageUrl(const std::string& url) {
-  GURL original_url(url);
+bool IsGoogleDomainUrl(const GURL& url,
+                       SubdomainPermission subdomain_permission,
+                       PortPermission port_permission) {
+  return url.is_valid() && (url.SchemeIs("http") || url.SchemeIs("https")) &&
+      (url.port().empty() || (port_permission == ALLOW_NON_STANDARD_PORTS)) &&
+      google_util::IsGoogleHostname(url.host(), subdomain_permission);
+}
 
+bool IsGoogleHomePageUrl(const GURL& url) {
   // First check to see if this has a Google domain.
   if (!IsGoogleDomainUrl(url, DISALLOW_SUBDOMAIN, DISALLOW_NON_STANDARD_PORTS))
     return false;
 
   // Make sure the path is a known home page path.
-  std::string path(original_url.path());
-  if (path != "/" && path != "/webhp" &&
-      !StartsWithASCII(path, "/ig", false)) {
-    return false;
-  }
-
-  return true;
+  std::string path(url.path());
+  return IsPathHomePageBase(path) || StartsWithASCII(path, "/ig", false);
 }
 
-bool IsGoogleSearchUrl(const std::string& url) {
-  GURL original_url(url);
-
+bool IsGoogleSearchUrl(const GURL& url) {
   // First check to see if this has a Google domain.
   if (!IsGoogleDomainUrl(url, DISALLOW_SUBDOMAIN, DISALLOW_NON_STANDARD_PORTS))
     return false;
 
   // Make sure the path is a known search path.
-  std::string path(original_url.path());
-  bool has_valid_path = false;
-  bool is_home_page_base = false;
-  if (path == "/search") {
-    has_valid_path = true;
-  } else if (path == "/webhp" || path == "/") {
-    // Note that we allow both "/" and "" paths, but GURL spits them
-    // both out as just "/".
-    has_valid_path = true;
-    is_home_page_base = true;
-  }
-  if (!has_valid_path)
+  std::string path(url.path());
+  bool is_home_page_base = IsPathHomePageBase(path);
+  if (!is_home_page_base && (path != "/search"))
     return false;
 
   // Check for query parameter in URL parameter and hash fragment, depending on
   // the path type.
-  std::string query(original_url.query());
-  std::string ref(original_url.ref());
-  return HasGoogleSearchQueryParam(ref) ||
-      (!is_home_page_base && HasGoogleSearchQueryParam(query));
+  return HasGoogleSearchQueryParam(url.ref()) ||
+      (!is_home_page_base && HasGoogleSearchQueryParam(url.query()));
 }
 
 bool IsOrganic(const std::string& brand) {
@@ -300,4 +279,17 @@
   return found != end;
 }
 
+
+// BrandForTesting ------------------------------------------------------------
+
+BrandForTesting::BrandForTesting(const std::string& brand) : brand_(brand) {
+  DCHECK(brand_for_testing == NULL);
+  brand_for_testing = brand_.c_str();
+}
+
+BrandForTesting::~BrandForTesting() {
+  brand_for_testing = NULL;
+}
+
+
 }  // namespace google_util
diff --git a/chrome/browser/google/google_util.h b/chrome/browser/google/google_util.h
index ea49f36..f3da3b4 100644
--- a/chrome/browser/google/google_util.h
+++ b/chrome/browser/google/google_util.h
@@ -69,22 +69,31 @@
   DISALLOW_NON_STANDARD_PORTS,
 };
 
-// True if |url| is an HTTP[S] request with host "[www.]google.<TLD>". If
-// |subdomain_permission| is ALLOW_SUBDOMAIN, this checks against host
-// "*.google.<TLD>" instead. If |port_permission| is ALLOW_NON_STANDARD_PORTS,
-// this also allows ports other than 80 for http or 443 for https.
-bool IsGoogleDomainUrl(const std::string& url,
-                       SubdomainPermission subdomain_permission,
-                       PortPermission port_permission);
+// Returns true if a Google base URL was specified on the command line and |url|
+// begins with that base URL.  This uses a simple string equality check.
+bool StartsWithCommandLineGoogleBaseURL(const GURL& url);
+
 // True if |host| is "[www.]google.<TLD>" with a valid TLD. If
 // |subdomain_permission| is ALLOW_SUBDOMAIN, we check against host
 // "*.google.<TLD>" instead.
+//
+// If the Google base URL has been overridden on the command line, this function
+// will also return true for any URL whose hostname exactly matches the hostname
+// of the URL specified on the command line.  In this case,
+// |subdomain_permission| is ignored.
 bool IsGoogleHostname(const std::string& host,
                       SubdomainPermission subdomain_permission);
+// True if |url| is a valid URL with a host that returns true for
+// IsGoogleHostname(), and an HTTP or HTTPS scheme.  If |port_permission| is
+// DISALLOW_NON_STANDARD_PORTS, this also requires |url| to use the standard
+// port for its scheme (80 for HTTP, 443 for HTTPS).
+bool IsGoogleDomainUrl(const GURL& url,
+                       SubdomainPermission subdomain_permission,
+                       PortPermission port_permission);
 // True if |url| represents a valid Google home page URL.
-bool IsGoogleHomePageUrl(const std::string& url);
+bool IsGoogleHomePageUrl(const GURL& url);
 // True if |url| represents a valid Google search URL.
-bool IsGoogleSearchUrl(const std::string& url);
+bool IsGoogleSearchUrl(const GURL& url);
 
 // True if a build is strictly organic, according to its brand code.
 bool IsOrganic(const std::string& brand);
diff --git a/chrome/browser/google/google_util_unittest.cc b/chrome/browser/google/google_util_unittest.cc
index 719c9b4..3701758 100644
--- a/chrome/browser/google/google_util_unittest.cc
+++ b/chrome/browser/google/google_util_unittest.cc
@@ -3,346 +3,334 @@
 // found in the LICENSE file.
 
 #include "base/command_line.h"
-#include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/google/google_url_tracker.h"
 #include "chrome/browser/google/google_util.h"
 #include "chrome/common/chrome_switches.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using google_util::IsGoogleDomainUrl;
-using google_util::IsGoogleHomePageUrl;
-using google_util::IsGoogleSearchUrl;
+
+
+// Helpers --------------------------------------------------------------------
+
+namespace {
+
+// These functions merely provide brevity in the callers.
+
+bool IsHomePage(const std::string& url) {
+  return google_util::IsGoogleHomePageUrl(GURL(url));
+}
+
+bool IsSearch(const std::string& url) {
+  return google_util::IsGoogleSearchUrl(GURL(url));
+}
+
+bool StartsWithBaseURL(const std::string& url) {
+  return google_util::StartsWithCommandLineGoogleBaseURL(GURL(url));
+}
+
+}  // namespace
+
+
+// Actual tests ---------------------------------------------------------------
 
 TEST(GoogleUtilTest, GoodHomePagesNonSecure) {
   // Valid home page hosts.
-  EXPECT_TRUE(IsGoogleHomePageUrl(GoogleURLTracker::kDefaultGoogleHomepage));
-  EXPECT_TRUE(IsGoogleHomePageUrl("http://google.com"));
-  EXPECT_TRUE(IsGoogleHomePageUrl("http://www.google.com"));
-  EXPECT_TRUE(IsGoogleHomePageUrl("http://www.google.ca"));
-  EXPECT_TRUE(IsGoogleHomePageUrl("http://www.google.co.uk"));
-  EXPECT_TRUE(IsGoogleHomePageUrl("http://www.google.com:80/"));
+  EXPECT_TRUE(IsHomePage(GoogleURLTracker::kDefaultGoogleHomepage));
+  EXPECT_TRUE(IsHomePage("http://google.com"));
+  EXPECT_TRUE(IsHomePage("http://www.google.com"));
+  EXPECT_TRUE(IsHomePage("http://www.google.ca"));
+  EXPECT_TRUE(IsHomePage("http://www.google.co.uk"));
+  EXPECT_TRUE(IsHomePage("http://www.google.com:80/"));
 
   // Only the paths /, /webhp, and /ig.* are valid.  Query parameters are
   // ignored.
-  EXPECT_TRUE(IsGoogleHomePageUrl("http://www.google.com/"));
-  EXPECT_TRUE(IsGoogleHomePageUrl("http://www.google.com/webhp"));
-  EXPECT_TRUE(IsGoogleHomePageUrl("http://www.google.com/webhp?rlz=TEST"));
-  EXPECT_TRUE(IsGoogleHomePageUrl("http://www.google.com/ig"));
-  EXPECT_TRUE(IsGoogleHomePageUrl("http://www.google.com/ig/foo"));
-  EXPECT_TRUE(IsGoogleHomePageUrl("http://www.google.com/ig?rlz=TEST"));
-  EXPECT_TRUE(IsGoogleHomePageUrl("http://www.google.com/ig/foo?rlz=TEST"));
+  EXPECT_TRUE(IsHomePage("http://www.google.com/"));
+  EXPECT_TRUE(IsHomePage("http://www.google.com/webhp"));
+  EXPECT_TRUE(IsHomePage("http://www.google.com/webhp?rlz=TEST"));
+  EXPECT_TRUE(IsHomePage("http://www.google.com/ig"));
+  EXPECT_TRUE(IsHomePage("http://www.google.com/ig/foo"));
+  EXPECT_TRUE(IsHomePage("http://www.google.com/ig?rlz=TEST"));
+  EXPECT_TRUE(IsHomePage("http://www.google.com/ig/foo?rlz=TEST"));
 }
 
 TEST(GoogleUtilTest, GoodHomePagesSecure) {
   // Valid home page hosts.
-  EXPECT_TRUE(IsGoogleHomePageUrl("https://google.com"));
-  EXPECT_TRUE(IsGoogleHomePageUrl("https://www.google.com"));
-  EXPECT_TRUE(IsGoogleHomePageUrl("https://www.google.ca"));
-  EXPECT_TRUE(IsGoogleHomePageUrl("https://www.google.co.uk"));
-  EXPECT_TRUE(IsGoogleHomePageUrl("https://www.google.com:443/"));
+  EXPECT_TRUE(IsHomePage("https://google.com"));
+  EXPECT_TRUE(IsHomePage("https://www.google.com"));
+  EXPECT_TRUE(IsHomePage("https://www.google.ca"));
+  EXPECT_TRUE(IsHomePage("https://www.google.co.uk"));
+  EXPECT_TRUE(IsHomePage("https://www.google.com:443/"));
 
   // Only the paths /, /webhp, and /ig.* are valid.  Query parameters are
   // ignored.
-  EXPECT_TRUE(IsGoogleHomePageUrl("https://www.google.com/"));
-  EXPECT_TRUE(IsGoogleHomePageUrl("https://www.google.com/webhp"));
-  EXPECT_TRUE(IsGoogleHomePageUrl("https://www.google.com/webhp?rlz=TEST"));
-  EXPECT_TRUE(IsGoogleHomePageUrl("https://www.google.com/ig"));
-  EXPECT_TRUE(IsGoogleHomePageUrl("https://www.google.com/ig/foo"));
-  EXPECT_TRUE(IsGoogleHomePageUrl("https://www.google.com/ig?rlz=TEST"));
-  EXPECT_TRUE(IsGoogleHomePageUrl("https://www.google.com/ig/foo?rlz=TEST"));
+  EXPECT_TRUE(IsHomePage("https://www.google.com/"));
+  EXPECT_TRUE(IsHomePage("https://www.google.com/webhp"));
+  EXPECT_TRUE(IsHomePage("https://www.google.com/webhp?rlz=TEST"));
+  EXPECT_TRUE(IsHomePage("https://www.google.com/ig"));
+  EXPECT_TRUE(IsHomePage("https://www.google.com/ig/foo"));
+  EXPECT_TRUE(IsHomePage("https://www.google.com/ig?rlz=TEST"));
+  EXPECT_TRUE(IsHomePage("https://www.google.com/ig/foo?rlz=TEST"));
 }
 
 TEST(GoogleUtilTest, BadHomePages) {
-  EXPECT_FALSE(IsGoogleHomePageUrl(std::string()));
+  EXPECT_FALSE(IsHomePage(std::string()));
 
   // If specified, only the "www" subdomain is OK.
-  EXPECT_FALSE(IsGoogleHomePageUrl("http://maps.google.com"));
-  EXPECT_FALSE(IsGoogleHomePageUrl("http://foo.google.com"));
+  EXPECT_FALSE(IsHomePage("http://maps.google.com"));
+  EXPECT_FALSE(IsHomePage("http://foo.google.com"));
 
   // No non-standard port numbers.
-  EXPECT_FALSE(IsGoogleHomePageUrl("http://www.google.com:1234"));
-  EXPECT_FALSE(IsGoogleHomePageUrl("https://www.google.com:5678"));
+  EXPECT_FALSE(IsHomePage("http://www.google.com:1234"));
+  EXPECT_FALSE(IsHomePage("https://www.google.com:5678"));
 
   // Invalid TLDs.
-  EXPECT_FALSE(IsGoogleHomePageUrl("http://www.google.abc"));
-  EXPECT_FALSE(IsGoogleHomePageUrl("http://www.google.com.abc"));
-  EXPECT_FALSE(IsGoogleHomePageUrl("http://www.google.abc.com"));
-  EXPECT_FALSE(IsGoogleHomePageUrl("http://www.google.ab.cd"));
-  EXPECT_FALSE(IsGoogleHomePageUrl("http://www.google.uk.qq"));
+  EXPECT_FALSE(IsHomePage("http://www.google.abc"));
+  EXPECT_FALSE(IsHomePage("http://www.google.com.abc"));
+  EXPECT_FALSE(IsHomePage("http://www.google.abc.com"));
+  EXPECT_FALSE(IsHomePage("http://www.google.ab.cd"));
+  EXPECT_FALSE(IsHomePage("http://www.google.uk.qq"));
 
   // Must be http or https.
-  EXPECT_FALSE(IsGoogleHomePageUrl("ftp://www.google.com"));
-  EXPECT_FALSE(IsGoogleHomePageUrl("file://does/not/exist"));
-  EXPECT_FALSE(IsGoogleHomePageUrl("bad://www.google.com"));
-  EXPECT_FALSE(IsGoogleHomePageUrl("www.google.com"));
+  EXPECT_FALSE(IsHomePage("ftp://www.google.com"));
+  EXPECT_FALSE(IsHomePage("file://does/not/exist"));
+  EXPECT_FALSE(IsHomePage("bad://www.google.com"));
+  EXPECT_FALSE(IsHomePage("www.google.com"));
 
   // Only the paths /, /webhp, and /ig.* are valid.
-  EXPECT_FALSE(IsGoogleHomePageUrl("http://www.google.com/abc"));
-  EXPECT_FALSE(IsGoogleHomePageUrl("http://www.google.com/webhpabc"));
-  EXPECT_FALSE(IsGoogleHomePageUrl("http://www.google.com/webhp/abc"));
-  EXPECT_FALSE(IsGoogleHomePageUrl("http://www.google.com/abcig"));
-  EXPECT_FALSE(IsGoogleHomePageUrl("http://www.google.com/webhp/ig"));
+  EXPECT_FALSE(IsHomePage("http://www.google.com/abc"));
+  EXPECT_FALSE(IsHomePage("http://www.google.com/webhpabc"));
+  EXPECT_FALSE(IsHomePage("http://www.google.com/webhp/abc"));
+  EXPECT_FALSE(IsHomePage("http://www.google.com/abcig"));
+  EXPECT_FALSE(IsHomePage("http://www.google.com/webhp/ig"));
 
   // A search URL should not be identified as a home page URL.
-  EXPECT_FALSE(IsGoogleHomePageUrl("http://www.google.com/search?q=something"));
+  EXPECT_FALSE(IsHomePage("http://www.google.com/search?q=something"));
 
   // Path is case sensitive.
-  EXPECT_FALSE(IsGoogleHomePageUrl("https://www.google.com/WEBHP"));
+  EXPECT_FALSE(IsHomePage("https://www.google.com/WEBHP"));
 }
 
 TEST(GoogleUtilTest, GoodSearchPagesNonSecure) {
   // Queries with path "/search" need to have the query parameter in either
   // the url parameter or the hash fragment.
-  EXPECT_TRUE(IsGoogleSearchUrl(
-      "http://www.google.com/search?q=something"));
-  EXPECT_TRUE(IsGoogleSearchUrl(
-      "http://www.google.com/search#q=something"));
-  EXPECT_TRUE(IsGoogleSearchUrl(
-      "http://www.google.com/search?name=bob&q=something"));
-  EXPECT_TRUE(IsGoogleSearchUrl(
-      "http://www.google.com/search?name=bob#q=something"));
-  EXPECT_TRUE(IsGoogleSearchUrl(
-      "http://www.google.com/search?name=bob#age=24&q=something"));
-  EXPECT_TRUE(IsGoogleSearchUrl(
-      "http://www.google.co.uk/search?q=something"));
+  EXPECT_TRUE(IsSearch("http://www.google.com/search?q=something"));
+  EXPECT_TRUE(IsSearch("http://www.google.com/search#q=something"));
+  EXPECT_TRUE(IsSearch("http://www.google.com/search?name=bob&q=something"));
+  EXPECT_TRUE(IsSearch("http://www.google.com/search?name=bob#q=something"));
+  EXPECT_TRUE(IsSearch("http://www.google.com/search?name=bob#age=24&q=thing"));
+  EXPECT_TRUE(IsSearch("http://www.google.co.uk/search?q=something"));
   // It's actually valid for both to have the query parameter.
-  EXPECT_TRUE(IsGoogleSearchUrl(
-      "http://www.google.com/search?q=something#q=other"));
+  EXPECT_TRUE(IsSearch("http://www.google.com/search?q=something#q=other"));
 
   // Queries with path "/webhp", "/" or "" need to have the query parameter in
   // the hash fragment.
-  EXPECT_TRUE(IsGoogleSearchUrl(
-      "http://www.google.com/webhp#q=something"));
-  EXPECT_TRUE(IsGoogleSearchUrl(
-      "http://www.google.com/webhp#name=bob&q=something"));
-  EXPECT_TRUE(IsGoogleSearchUrl(
-      "http://www.google.com/webhp?name=bob#q=something"));
-  EXPECT_TRUE(IsGoogleSearchUrl(
-      "http://www.google.com/webhp?name=bob#age=24&q=something"));
+  EXPECT_TRUE(IsSearch("http://www.google.com/webhp#q=something"));
+  EXPECT_TRUE(IsSearch("http://www.google.com/webhp#name=bob&q=something"));
+  EXPECT_TRUE(IsSearch("http://www.google.com/webhp?name=bob#q=something"));
+  EXPECT_TRUE(IsSearch("http://www.google.com/webhp?name=bob#age=24&q=thing"));
 
-  EXPECT_TRUE(IsGoogleSearchUrl(
-      "http://www.google.com/#q=something"));
-  EXPECT_TRUE(IsGoogleSearchUrl(
-      "http://www.google.com/#name=bob&q=something"));
-  EXPECT_TRUE(IsGoogleSearchUrl(
-      "http://www.google.com/?name=bob#q=something"));
-  EXPECT_TRUE(IsGoogleSearchUrl(
-      "http://www.google.com/?name=bob#age=24&q=something"));
+  EXPECT_TRUE(IsSearch("http://www.google.com/#q=something"));
+  EXPECT_TRUE(IsSearch("http://www.google.com/#name=bob&q=something"));
+  EXPECT_TRUE(IsSearch("http://www.google.com/?name=bob#q=something"));
+  EXPECT_TRUE(IsSearch("http://www.google.com/?name=bob#age=24&q=something"));
 
-  EXPECT_TRUE(IsGoogleSearchUrl(
-      "http://www.google.com#q=something"));
-  EXPECT_TRUE(IsGoogleSearchUrl(
-      "http://www.google.com#name=bob&q=something"));
-  EXPECT_TRUE(IsGoogleSearchUrl(
-      "http://www.google.com?name=bob#q=something"));
-  EXPECT_TRUE(IsGoogleSearchUrl(
-      "http://www.google.com?name=bob#age=24&q=something"));
+  EXPECT_TRUE(IsSearch("http://www.google.com#q=something"));
+  EXPECT_TRUE(IsSearch("http://www.google.com#name=bob&q=something"));
+  EXPECT_TRUE(IsSearch("http://www.google.com?name=bob#q=something"));
+  EXPECT_TRUE(IsSearch("http://www.google.com?name=bob#age=24&q=something"));
 }
 
 TEST(GoogleUtilTest, GoodSearchPagesSecure) {
   // Queries with path "/search" need to have the query parameter in either
   // the url parameter or the hash fragment.
-  EXPECT_TRUE(IsGoogleSearchUrl(
-      "https://www.google.com/search?q=something"));
-  EXPECT_TRUE(IsGoogleSearchUrl(
-      "https://www.google.com/search#q=something"));
-  EXPECT_TRUE(IsGoogleSearchUrl(
-      "https://www.google.com/search?name=bob&q=something"));
-  EXPECT_TRUE(IsGoogleSearchUrl(
-      "https://www.google.com/search?name=bob#q=something"));
-  EXPECT_TRUE(IsGoogleSearchUrl(
-      "https://www.google.com/search?name=bob#age=24&q=something"));
-  EXPECT_TRUE(IsGoogleSearchUrl(
-      "https://www.google.co.uk/search?q=something"));
+  EXPECT_TRUE(IsSearch("https://www.google.com/search?q=something"));
+  EXPECT_TRUE(IsSearch("https://www.google.com/search#q=something"));
+  EXPECT_TRUE(IsSearch("https://www.google.com/search?name=bob&q=something"));
+  EXPECT_TRUE(IsSearch("https://www.google.com/search?name=bob#q=something"));
+  EXPECT_TRUE(IsSearch("https://www.google.com/search?name=bob#age=24&q=q"));
+  EXPECT_TRUE(IsSearch("https://www.google.co.uk/search?q=something"));
   // It's actually valid for both to have the query parameter.
-  EXPECT_TRUE(IsGoogleSearchUrl(
-      "https://www.google.com/search?q=something#q=other"));
+  EXPECT_TRUE(IsSearch("https://www.google.com/search?q=something#q=other"));
 
   // Queries with path "/webhp", "/" or "" need to have the query parameter in
   // the hash fragment.
-  EXPECT_TRUE(IsGoogleSearchUrl(
-      "https://www.google.com/webhp#q=something"));
-  EXPECT_TRUE(IsGoogleSearchUrl(
-      "https://www.google.com/webhp#name=bob&q=something"));
-  EXPECT_TRUE(IsGoogleSearchUrl(
-      "https://www.google.com/webhp?name=bob#q=something"));
-  EXPECT_TRUE(IsGoogleSearchUrl(
-      "https://www.google.com/webhp?name=bob#age=24&q=something"));
+  EXPECT_TRUE(IsSearch("https://www.google.com/webhp#q=something"));
+  EXPECT_TRUE(IsSearch("https://www.google.com/webhp#name=bob&q=something"));
+  EXPECT_TRUE(IsSearch("https://www.google.com/webhp?name=bob#q=something"));
+  EXPECT_TRUE(IsSearch("https://www.google.com/webhp?name=bob#age=24&q=thing"));
 
-  EXPECT_TRUE(IsGoogleSearchUrl(
-      "https://www.google.com/#q=something"));
-  EXPECT_TRUE(IsGoogleSearchUrl(
-      "https://www.google.com/#name=bob&q=something"));
-  EXPECT_TRUE(IsGoogleSearchUrl(
-      "https://www.google.com/?name=bob#q=something"));
-  EXPECT_TRUE(IsGoogleSearchUrl(
-      "https://www.google.com/?name=bob#age=24&q=something"));
+  EXPECT_TRUE(IsSearch("https://www.google.com/#q=something"));
+  EXPECT_TRUE(IsSearch("https://www.google.com/#name=bob&q=something"));
+  EXPECT_TRUE(IsSearch("https://www.google.com/?name=bob#q=something"));
+  EXPECT_TRUE(IsSearch("https://www.google.com/?name=bob#age=24&q=something"));
 
-  EXPECT_TRUE(IsGoogleSearchUrl(
-      "https://www.google.com#q=something"));
-  EXPECT_TRUE(IsGoogleSearchUrl(
-      "https://www.google.com#name=bob&q=something"));
-  EXPECT_TRUE(IsGoogleSearchUrl(
-      "https://www.google.com?name=bob#q=something"));
-  EXPECT_TRUE(IsGoogleSearchUrl(
-      "https://www.google.com?name=bob#age=24&q=something"));
+  EXPECT_TRUE(IsSearch("https://www.google.com#q=something"));
+  EXPECT_TRUE(IsSearch("https://www.google.com#name=bob&q=something"));
+  EXPECT_TRUE(IsSearch("https://www.google.com?name=bob#q=something"));
+  EXPECT_TRUE(IsSearch("https://www.google.com?name=bob#age=24&q=something"));
 }
 
 TEST(GoogleUtilTest, BadSearches) {
   // A home page URL should not be identified as a search URL.
-  EXPECT_FALSE(IsGoogleSearchUrl(GoogleURLTracker::kDefaultGoogleHomepage));
-  EXPECT_FALSE(IsGoogleSearchUrl("http://google.com"));
-  EXPECT_FALSE(IsGoogleSearchUrl("http://www.google.com"));
-  EXPECT_FALSE(IsGoogleSearchUrl("http://www.google.com/search"));
-  EXPECT_FALSE(IsGoogleSearchUrl("http://www.google.com/search?"));
+  EXPECT_FALSE(IsSearch(GoogleURLTracker::kDefaultGoogleHomepage));
+  EXPECT_FALSE(IsSearch("http://google.com"));
+  EXPECT_FALSE(IsSearch("http://www.google.com"));
+  EXPECT_FALSE(IsSearch("http://www.google.com/search"));
+  EXPECT_FALSE(IsSearch("http://www.google.com/search?"));
 
   // Must be http or https
-  EXPECT_FALSE(IsGoogleSearchUrl(
-      "ftp://www.google.com/search?q=something"));
-  EXPECT_FALSE(IsGoogleSearchUrl(
-      "file://does/not/exist/search?q=something"));
-  EXPECT_FALSE(IsGoogleSearchUrl(
-      "bad://www.google.com/search?q=something"));
-  EXPECT_FALSE(IsGoogleSearchUrl(
-      "www.google.com/search?q=something"));
+  EXPECT_FALSE(IsSearch("ftp://www.google.com/search?q=something"));
+  EXPECT_FALSE(IsSearch("file://does/not/exist/search?q=something"));
+  EXPECT_FALSE(IsSearch("bad://www.google.com/search?q=something"));
+  EXPECT_FALSE(IsSearch("www.google.com/search?q=something"));
 
   // Can't have an empty query parameter.
-  EXPECT_FALSE(IsGoogleSearchUrl(
-      "http://www.google.com/search?q="));
-  EXPECT_FALSE(IsGoogleSearchUrl(
-      "http://www.google.com/search?name=bob&q="));
-  EXPECT_FALSE(IsGoogleSearchUrl(
-      "http://www.google.com/webhp#q="));
-  EXPECT_FALSE(IsGoogleSearchUrl(
-      "http://www.google.com/webhp#name=bob&q="));
+  EXPECT_FALSE(IsSearch("http://www.google.com/search?q="));
+  EXPECT_FALSE(IsSearch("http://www.google.com/search?name=bob&q="));
+  EXPECT_FALSE(IsSearch("http://www.google.com/webhp#q="));
+  EXPECT_FALSE(IsSearch("http://www.google.com/webhp#name=bob&q="));
 
   // Home page searches without a hash fragment query parameter are invalid.
-  EXPECT_FALSE(IsGoogleSearchUrl(
-      "http://www.google.com/webhp?q=something"));
-  EXPECT_FALSE(IsGoogleSearchUrl(
-      "http://www.google.com/webhp?q=something#no=good"));
-  EXPECT_FALSE(IsGoogleSearchUrl(
-      "http://www.google.com/webhp?name=bob&q=something"));
-  EXPECT_FALSE(IsGoogleSearchUrl(
-      "http://www.google.com/?q=something"));
-  EXPECT_FALSE(IsGoogleSearchUrl(
-      "http://www.google.com?q=something"));
+  EXPECT_FALSE(IsSearch("http://www.google.com/webhp?q=something"));
+  EXPECT_FALSE(IsSearch("http://www.google.com/webhp?q=something#no=good"));
+  EXPECT_FALSE(IsSearch("http://www.google.com/webhp?name=bob&q=something"));
+  EXPECT_FALSE(IsSearch("http://www.google.com/?q=something"));
+  EXPECT_FALSE(IsSearch("http://www.google.com?q=something"));
 
   // Some paths are outright invalid as searches.
-  EXPECT_FALSE(IsGoogleSearchUrl(
-      "http://www.google.com/notreal?q=something"));
-  EXPECT_FALSE(IsGoogleSearchUrl(
-      "http://www.google.com/chrome?q=something"));
-  EXPECT_FALSE(IsGoogleSearchUrl(
-      "http://www.google.com/search/nogood?q=something"));
-  EXPECT_FALSE(IsGoogleSearchUrl(
-      "http://www.google.com/webhp/nogood#q=something"));
-  EXPECT_FALSE(IsGoogleSearchUrl(std::string()));
+  EXPECT_FALSE(IsSearch("http://www.google.com/notreal?q=something"));
+  EXPECT_FALSE(IsSearch("http://www.google.com/chrome?q=something"));
+  EXPECT_FALSE(IsSearch("http://www.google.com/search/nogood?q=something"));
+  EXPECT_FALSE(IsSearch("http://www.google.com/webhp/nogood#q=something"));
+  EXPECT_FALSE(IsSearch(std::string()));
 
   // Case sensitive paths.
-  EXPECT_FALSE(IsGoogleSearchUrl(
-      "http://www.google.com/SEARCH?q=something"));
-  EXPECT_FALSE(IsGoogleSearchUrl(
-      "http://www.google.com/WEBHP#q=something"));
+  EXPECT_FALSE(IsSearch("http://www.google.com/SEARCH?q=something"));
+  EXPECT_FALSE(IsSearch("http://www.google.com/WEBHP#q=something"));
 }
 
 TEST(GoogleUtilTest, GoogleDomains) {
   // Test some good Google domains (valid TLDs).
-  EXPECT_TRUE(IsGoogleDomainUrl("http://www.google.com",
+  EXPECT_TRUE(IsGoogleDomainUrl(GURL("http://www.google.com"),
                                 google_util::ALLOW_SUBDOMAIN,
                                 google_util::DISALLOW_NON_STANDARD_PORTS));
-  EXPECT_TRUE(IsGoogleDomainUrl("http://google.com",
+  EXPECT_TRUE(IsGoogleDomainUrl(GURL("http://google.com"),
                                 google_util::ALLOW_SUBDOMAIN,
                                 google_util::DISALLOW_NON_STANDARD_PORTS));
-  EXPECT_TRUE(IsGoogleDomainUrl("http://www.google.ca",
+  EXPECT_TRUE(IsGoogleDomainUrl(GURL("http://www.google.ca"),
                                 google_util::ALLOW_SUBDOMAIN,
                                 google_util::DISALLOW_NON_STANDARD_PORTS));
-  EXPECT_TRUE(IsGoogleDomainUrl("http://www.google.biz.tj",
+  EXPECT_TRUE(IsGoogleDomainUrl(GURL("http://www.google.biz.tj"),
                                 google_util::ALLOW_SUBDOMAIN,
                                 google_util::DISALLOW_NON_STANDARD_PORTS));
-  EXPECT_TRUE(IsGoogleDomainUrl("http://www.google.com/search?q=something",
+  EXPECT_TRUE(IsGoogleDomainUrl(GURL("http://www.google.com/search?q=thing"),
                                 google_util::ALLOW_SUBDOMAIN,
                                 google_util::DISALLOW_NON_STANDARD_PORTS));
-  EXPECT_TRUE(IsGoogleDomainUrl("http://www.google.com/webhp",
+  EXPECT_TRUE(IsGoogleDomainUrl(GURL("http://www.google.com/webhp"),
                                 google_util::ALLOW_SUBDOMAIN,
                                 google_util::DISALLOW_NON_STANDARD_PORTS));
 
   // Test some bad Google domains (invalid TLDs).
-  EXPECT_FALSE(IsGoogleDomainUrl("http://www.google.notrealtld",
+  EXPECT_FALSE(IsGoogleDomainUrl(GURL("http://www.google.notrealtld"),
                                  google_util::ALLOW_SUBDOMAIN,
                                  google_util::DISALLOW_NON_STANDARD_PORTS));
-  EXPECT_FALSE(IsGoogleDomainUrl("http://www.google.faketld/search?q=something",
+  EXPECT_FALSE(IsGoogleDomainUrl(GURL("http://www.google.faketld/search?q=q"),
                                  google_util::ALLOW_SUBDOMAIN,
                                  google_util::DISALLOW_NON_STANDARD_PORTS));
-  EXPECT_FALSE(IsGoogleDomainUrl("http://www.yahoo.com",
+  EXPECT_FALSE(IsGoogleDomainUrl(GURL("http://www.yahoo.com"),
                                  google_util::ALLOW_SUBDOMAIN,
                                  google_util::DISALLOW_NON_STANDARD_PORTS));
 
   // Test subdomain checks.
-  EXPECT_TRUE(IsGoogleDomainUrl("http://images.google.com",
+  EXPECT_TRUE(IsGoogleDomainUrl(GURL("http://images.google.com"),
                                 google_util::ALLOW_SUBDOMAIN,
                                 google_util::DISALLOW_NON_STANDARD_PORTS));
-  EXPECT_FALSE(IsGoogleDomainUrl("http://images.google.com",
+  EXPECT_FALSE(IsGoogleDomainUrl(GURL("http://images.google.com"),
                                  google_util::DISALLOW_SUBDOMAIN,
                                  google_util::DISALLOW_NON_STANDARD_PORTS));
-  EXPECT_TRUE(IsGoogleDomainUrl("http://google.com",
+  EXPECT_TRUE(IsGoogleDomainUrl(GURL("http://google.com"),
                                 google_util::DISALLOW_SUBDOMAIN,
                                 google_util::DISALLOW_NON_STANDARD_PORTS));
-  EXPECT_TRUE(IsGoogleDomainUrl("http://www.google.com",
+  EXPECT_TRUE(IsGoogleDomainUrl(GURL("http://www.google.com"),
                                 google_util::DISALLOW_SUBDOMAIN,
                                 google_util::DISALLOW_NON_STANDARD_PORTS));
 
   // Port and scheme checks.
-  EXPECT_TRUE(IsGoogleDomainUrl("http://www.google.com:80",
+  EXPECT_TRUE(IsGoogleDomainUrl(GURL("http://www.google.com:80"),
                                 google_util::DISALLOW_SUBDOMAIN,
                                 google_util::DISALLOW_NON_STANDARD_PORTS));
-  EXPECT_FALSE(IsGoogleDomainUrl("http://www.google.com:123",
+  EXPECT_FALSE(IsGoogleDomainUrl(GURL("http://www.google.com:123"),
                                  google_util::DISALLOW_SUBDOMAIN,
                                  google_util::DISALLOW_NON_STANDARD_PORTS));
-  EXPECT_TRUE(IsGoogleDomainUrl("https://www.google.com:443",
+  EXPECT_TRUE(IsGoogleDomainUrl(GURL("https://www.google.com:443"),
                                 google_util::DISALLOW_SUBDOMAIN,
                                 google_util::DISALLOW_NON_STANDARD_PORTS));
-  EXPECT_FALSE(IsGoogleDomainUrl("http://www.google.com:123",
+  EXPECT_FALSE(IsGoogleDomainUrl(GURL("http://www.google.com:123"),
                                  google_util::DISALLOW_SUBDOMAIN,
                                  google_util::DISALLOW_NON_STANDARD_PORTS));
-  EXPECT_TRUE(IsGoogleDomainUrl("http://www.google.com:123",
+  EXPECT_TRUE(IsGoogleDomainUrl(GURL("http://www.google.com:123"),
                                 google_util::DISALLOW_SUBDOMAIN,
                                 google_util::ALLOW_NON_STANDARD_PORTS));
-  EXPECT_TRUE(IsGoogleDomainUrl("https://www.google.com:123",
+  EXPECT_TRUE(IsGoogleDomainUrl(GURL("https://www.google.com:123"),
                                 google_util::DISALLOW_SUBDOMAIN,
                                 google_util::ALLOW_NON_STANDARD_PORTS));
-  EXPECT_TRUE(IsGoogleDomainUrl("http://www.google.com:80",
+  EXPECT_TRUE(IsGoogleDomainUrl(GURL("http://www.google.com:80"),
                                 google_util::DISALLOW_SUBDOMAIN,
                                 google_util::ALLOW_NON_STANDARD_PORTS));
-  EXPECT_TRUE(IsGoogleDomainUrl("https://www.google.com:443",
+  EXPECT_TRUE(IsGoogleDomainUrl(GURL("https://www.google.com:443"),
                                 google_util::DISALLOW_SUBDOMAIN,
                                 google_util::ALLOW_NON_STANDARD_PORTS));
-  EXPECT_FALSE(IsGoogleDomainUrl("file://www.google.com",
+  EXPECT_FALSE(IsGoogleDomainUrl(GURL("file://www.google.com"),
                                  google_util::DISALLOW_SUBDOMAIN,
                                  google_util::DISALLOW_NON_STANDARD_PORTS));
-  EXPECT_FALSE(IsGoogleDomainUrl("doesnotexist://www.google.com",
+  EXPECT_FALSE(IsGoogleDomainUrl(GURL("doesnotexist://www.google.com"),
                                  google_util::DISALLOW_SUBDOMAIN,
                                  google_util::DISALLOW_NON_STANDARD_PORTS));
+}
 
-  // Test overriding with --instant-url works.
-  EXPECT_FALSE(IsGoogleDomainUrl("http://test.foo.com",
+TEST(GoogleUtilTest, GoogleBaseURL) {
+  // When no command-line flag is specified, no input to
+  // StartsWithCommandLineGoogleBaseURL() should return true.
+  EXPECT_FALSE(StartsWithBaseURL(std::string()));
+  EXPECT_FALSE(StartsWithBaseURL("http://www.foo.com/"));
+  EXPECT_FALSE(StartsWithBaseURL("http://www.google.com/"));
+
+  // By default, none of the IsGoogleXXX functions should return true for a
+  // "foo.com" URL.
+  EXPECT_FALSE(IsGoogleHostname("www.foo.com",
+                                google_util::DISALLOW_SUBDOMAIN));
+  EXPECT_FALSE(IsGoogleDomainUrl(GURL("http://www.foo.com/xyz"),
                                  google_util::DISALLOW_SUBDOMAIN,
                                  google_util::DISALLOW_NON_STANDARD_PORTS));
-  EXPECT_FALSE(IsGoogleDomainUrl("http://test.foo.com:1234",
+  EXPECT_FALSE(IsGoogleDomainUrl(GURL("https://www.foo.com/"),
                                  google_util::DISALLOW_SUBDOMAIN,
                                  google_util::DISALLOW_NON_STANDARD_PORTS));
-  CommandLine::ForCurrentProcess()->AppendSwitchASCII(
-      switches::kInstantURL, "http://test.foo.com:1234/bar");
-  EXPECT_FALSE(IsGoogleDomainUrl("http://test.foo.com",
-                                 google_util::DISALLOW_SUBDOMAIN,
-                                 google_util::DISALLOW_NON_STANDARD_PORTS));
-  EXPECT_TRUE(IsGoogleDomainUrl("http://test.foo.com:1234",
+  EXPECT_FALSE(IsHomePage("https://www.foo.com/webhp"));
+  EXPECT_FALSE(IsSearch("http://www.foo.com/search?q=a"));
+
+  // Override the Google base URL on the command line.
+  CommandLine::ForCurrentProcess()->AppendSwitchASCII(switches::kGoogleBaseURL,
+                                                      "http://www.foo.com/");
+
+  // Only URLs which start with exactly the string on the command line should
+  // cause StartsWithCommandLineGoogleBaseURL() to return true.
+  EXPECT_FALSE(StartsWithBaseURL(std::string()));
+  EXPECT_TRUE(StartsWithBaseURL("http://www.foo.com/"));
+  EXPECT_TRUE(StartsWithBaseURL("http://www.foo.com/abc"));
+  EXPECT_FALSE(StartsWithBaseURL("https://www.foo.com/"));
+  EXPECT_FALSE(StartsWithBaseURL("http://www.google.com/"));
+
+  // The various IsGoogleXXX functions should respect the command-line flag.
+  EXPECT_TRUE(IsGoogleHostname("www.foo.com", google_util::DISALLOW_SUBDOMAIN));
+  EXPECT_FALSE(IsGoogleHostname("foo.com", google_util::ALLOW_SUBDOMAIN));
+  EXPECT_TRUE(IsGoogleDomainUrl(GURL("http://www.foo.com/xyz"),
                                 google_util::DISALLOW_SUBDOMAIN,
                                 google_util::DISALLOW_NON_STANDARD_PORTS));
-  EXPECT_FALSE(IsGoogleDomainUrl("file://test.foo.com:1234",
-                                 google_util::DISALLOW_SUBDOMAIN,
-                                 google_util::DISALLOW_NON_STANDARD_PORTS));
-  EXPECT_TRUE(IsGoogleDomainUrl("http://www.google.com",
+  EXPECT_TRUE(IsGoogleDomainUrl(GURL("https://www.foo.com/"),
                                 google_util::DISALLOW_SUBDOMAIN,
                                 google_util::DISALLOW_NON_STANDARD_PORTS));
+  EXPECT_TRUE(IsHomePage("https://www.foo.com/webhp"));
+  EXPECT_FALSE(IsHomePage("http://www.foo.com/xyz"));
+  EXPECT_TRUE(IsSearch("http://www.foo.com/search?q=a"));
 }
diff --git a/chrome/browser/google_apis/DEPS b/chrome/browser/google_apis/DEPS
index d24803e..3fc08f4 100644
--- a/chrome/browser/google_apis/DEPS
+++ b/chrome/browser/google_apis/DEPS
@@ -3,17 +3,19 @@
   "-content",
   "+chrome/browser/google_apis",
 
-  # Temporarily needed, see http://crbug.com/146989
+  # BrowserThread should be gone: crbug.com/256112
   "!content/public/browser/browser_thread.h",
 ]
 
+# Exceptions are temporarily needed. crbug.com/146989
 specific_include_rules = {
-  ".*_[a-z]+test\.cc": [
-    # Temporarily needed, see http://crbug.com/146989
-    "!chrome/browser/chromeos/system/timezone_settings.h",
+  ".*requests.*unittest\.cc": [
+    # This is necessary for AuthService. See below.
     "!chrome/test/base/testing_profile.h",
+    # TestBrowserThreadBundle should be gone: crbug.com/256109
     "!content/public/test/test_browser_thread_bundle.h",
   ],
+  # AuthService should be gone. crbug.com/162157
   "auth_service\.(h|cc)": [
     "!chrome/browser/profiles/profile.h",
     "!chrome/browser/signin/token_service_factory.h",
diff --git a/chrome/browser/google_apis/auth_service.cc b/chrome/browser/google_apis/auth_service.cc
index 3f019ae..10377f1 100644
--- a/chrome/browser/google_apis/auth_service.cc
+++ b/chrome/browser/google_apis/auth_service.cc
@@ -15,7 +15,6 @@
 #include "chrome/browser/signin/token_service.h"
 #include "chrome/browser/signin/token_service_factory.h"
 #include "chrome/common/chrome_notification_types.h"
-#include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_source.h"
 #include "content/public/browser/notification_types.h"
@@ -28,8 +27,6 @@
 #include "chromeos/login/login_state.h"
 #endif  // OS_CHROMEOS
 
-using content::BrowserThread;
-
 namespace google_apis {
 
 namespace {
@@ -65,6 +62,7 @@
   AuthStatusCallback callback_;
   std::vector<std::string> scopes_;
   scoped_ptr<OAuth2AccessTokenFetcher> oauth2_access_token_fetcher_;
+  base::ThreadChecker thread_checker_;
 
   DISALLOW_COPY_AND_ASSIGN(AuthRequest);
 };
@@ -98,7 +96,7 @@
 // used to start fetching user data.
 void AuthRequest::OnGetTokenSuccess(const std::string& access_token,
                                     const base::Time& expiration_time) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(thread_checker_.CalledOnValidThread());
 
   UMA_HISTOGRAM_ENUMERATION("GData.AuthSuccess",
                             kSuccessRatioHistogramSuccess,
@@ -110,7 +108,7 @@
 
 // Callback for OAuth2AccessTokenFetcher on failure.
 void AuthRequest::OnGetTokenFailure(const GoogleServiceAuthError& error) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(thread_checker_.CalledOnValidThread());
 
   LOG(WARNING) << "AuthRequest: token request using refresh token failed: "
                << error.ToString();
@@ -164,14 +162,14 @@
       url_request_context_getter_(url_request_context_getter),
       scopes_(scopes),
       weak_ptr_factory_(this) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(thread_checker_.CalledOnValidThread());
 }
 
 AuthService::~AuthService() {
 }
 
 void AuthService::StartAuthentication(const AuthStatusCallback& callback) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(thread_checker_.CalledOnValidThread());
   scoped_refptr<base::MessageLoopProxy> relay_proxy(
       base::MessageLoopProxy::current());
 
@@ -220,7 +218,7 @@
 void AuthService::OnAuthCompleted(const AuthStatusCallback& callback,
                                   GDataErrorCode error,
                                   const std::string& access_token) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(!callback.is_null());
 
   if (error == HTTP_SUCCESS) {
diff --git a/chrome/browser/google_apis/auth_service.h b/chrome/browser/google_apis/auth_service.h
index 2ebbc05..8f47ecd 100644
--- a/chrome/browser/google_apis/auth_service.h
+++ b/chrome/browser/google_apis/auth_service.h
@@ -10,6 +10,7 @@
 
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
+#include "base/threading/thread_checker.h"
 #include "chrome/browser/google_apis/auth_service_interface.h"
 #include "chrome/browser/google_apis/gdata_errorcode.h"
 #include "content/public/browser/notification_observer.h"
@@ -79,6 +80,7 @@
   std::string access_token_;
   std::vector<std::string> scopes_;
   ObserverList<AuthServiceObserver> observers_;
+  base::ThreadChecker thread_checker_;
 
   content::NotificationRegistrar registrar_;
 
diff --git a/chrome/browser/google_apis/base_requests.cc b/chrome/browser/google_apis/base_requests.cc
index 0f3dfce..49a5f07 100644
--- a/chrome/browser/google_apis/base_requests.cc
+++ b/chrome/browser/google_apis/base_requests.cc
@@ -44,8 +44,6 @@
 
 // Parse JSON string to base::Value object.
 scoped_ptr<base::Value> ParseJsonOnBlockingPool(const std::string& json) {
-  DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
-
   int error_code = -1;
   std::string error_message;
   scoped_ptr<base::Value> value(base::JSONReader::ReadAndReturnError(
@@ -92,29 +90,10 @@
 
 //============================ UrlFetchRequestBase ===========================
 
-UrlFetchRequestBase::UrlFetchRequestBase(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter)
-    : RequestRegistry::Request(runner->request_registry()),
-      url_request_context_getter_(url_request_context_getter),
-      re_authenticate_count_(0),
-      started_(false),
-      save_temp_file_(false),
+UrlFetchRequestBase::UrlFetchRequestBase(RequestSender* sender)
+    : re_authenticate_count_(0),
+      sender_(sender),
       weak_ptr_factory_(this) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-}
-
-UrlFetchRequestBase::UrlFetchRequestBase(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
-    const base::FilePath& path)
-    : RequestRegistry::Request(runner->request_registry(), path),
-      url_request_context_getter_(url_request_context_getter),
-      re_authenticate_count_(0),
-      started_(false),
-      save_temp_file_(false),
-      weak_ptr_factory_(this) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 }
 
 UrlFetchRequestBase::~UrlFetchRequestBase() {}
@@ -122,8 +101,7 @@
 void UrlFetchRequestBase::Start(const std::string& access_token,
                                 const std::string& custom_user_agent,
                                 const ReAuthenticateCallback& callback) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  DCHECK(url_request_context_getter_);
+  DCHECK(CalledOnValidThread());
   DCHECK(!access_token.empty());
   DCHECK(!callback.is_null());
   DCHECK(re_authenticate_callback_.is_null());
@@ -143,17 +121,16 @@
   URLFetcher::RequestType request_type = GetRequestType();
   url_fetcher_.reset(
       URLFetcher::Create(url, request_type, this));
-  url_fetcher_->SetRequestContext(url_request_context_getter_);
+  url_fetcher_->SetRequestContext(sender_->url_request_context_getter());
   // Always set flags to neither send nor save cookies.
   url_fetcher_->SetLoadFlags(
       net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES |
       net::LOAD_DISABLE_CACHE);
-  if (save_temp_file_) {
-    url_fetcher_->SaveResponseToTemporaryFile(
-        BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE));
-  } else if (!output_file_path_.empty()) {
+
+  base::FilePath output_file_path;
+  if (GetOutputFilePath(&output_file_path)) {
     url_fetcher_->SaveResponseToFileAtPath(
-        output_file_path_,
+        output_file_path,
         BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE));
   }
 
@@ -204,11 +181,7 @@
     }
   }
 
-  // Register to request registry.
-  NotifyStart();
-
   url_fetcher_->Start();
-  started_ = true;
 }
 
 URLFetcher::RequestType UrlFetchRequestBase::GetRequestType() const {
@@ -231,9 +204,14 @@
   return false;
 }
 
-void UrlFetchRequestBase::DoCancel() {
+bool UrlFetchRequestBase::GetOutputFilePath(base::FilePath* local_file_path) {
+  return false;
+}
+
+void UrlFetchRequestBase::Cancel() {
   url_fetcher_.reset(NULL);
   RunCallbackOnPrematureFailure(GDATA_CANCELLED);
+  sender_->RequestFinished(this);
 }
 
 // static
@@ -251,8 +229,12 @@
   return code;
 }
 
+bool UrlFetchRequestBase::CalledOnValidThread() {
+  return thread_checker_.CalledOnValidThread();
+}
+
 void UrlFetchRequestBase::OnProcessURLFetchResultsComplete(bool result) {
-  NotifyFinish(result ? REQUEST_COMPLETED : REQUEST_FAILED);
+  sender_->RequestFinished(this);
 }
 
 void UrlFetchRequestBase::OnURLFetchComplete(const URLFetcher* source) {
@@ -278,20 +260,7 @@
 
 void UrlFetchRequestBase::OnAuthFailed(GDataErrorCode code) {
   RunCallbackOnPrematureFailure(code);
-
-  // Check if this failed before we even started fetching. If so, register
-  // for start so we can properly unregister with finish.
-  if (!started_)
-    NotifyStart();
-
-  // Note: NotifyFinish() must be invoked at the end, after all other callbacks
-  // and notifications. Once NotifyFinish() is called, the current instance of
-  // request will be deleted from the RequestRegistry and become invalid.
-  NotifyFinish(REQUEST_FAILED);
-}
-
-RequestRegistry::Request* UrlFetchRequestBase::AsRequestRegistryRequest() {
-  return this;
+  sender_->RequestFinished(this);
 }
 
 base::WeakPtr<AuthenticatedRequestInterface>
@@ -301,11 +270,9 @@
 
 //============================ EntryActionRequest ============================
 
-EntryActionRequest::EntryActionRequest(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
-    const EntryActionCallback& callback)
-    : UrlFetchRequestBase(runner, url_request_context_getter),
+EntryActionRequest::EntryActionRequest(RequestSender* sender,
+                                       const EntryActionCallback& callback)
+    : UrlFetchRequestBase(sender),
       callback_(callback) {
   DCHECK(!callback_.is_null());
 }
@@ -325,11 +292,9 @@
 
 //============================== GetDataRequest ==============================
 
-GetDataRequest::GetDataRequest(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
-    const GetDataCallback& callback)
-    : UrlFetchRequestBase(runner, url_request_context_getter),
+GetDataRequest::GetDataRequest(RequestSender* sender,
+                               const GetDataCallback& callback)
+    : UrlFetchRequestBase(sender),
       callback_(callback),
       weak_ptr_factory_(this) {
   DCHECK(!callback_.is_null());
@@ -339,7 +304,7 @@
 
 void GetDataRequest::ParseResponse(GDataErrorCode fetch_error_code,
                                    const std::string& data) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(CalledOnValidThread());
 
   VLOG(1) << "JSON received from " << GetURL().spec() << ": "
           << data.size() << " bytes";
@@ -373,10 +338,9 @@
   callback_.Run(fetch_error_code, scoped_ptr<base::Value>());
 }
 
-void GetDataRequest::OnDataParsed(
-    GDataErrorCode fetch_error_code,
-    scoped_ptr<base::Value> value) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+void GetDataRequest::OnDataParsed(GDataErrorCode fetch_error_code,
+                                  scoped_ptr<base::Value> value) {
+  DCHECK(CalledOnValidThread());
 
   bool success = true;
   if (!value.get()) {
@@ -392,24 +356,19 @@
 
 void GetDataRequest::RunCallbackOnSuccess(GDataErrorCode fetch_error_code,
                                           scoped_ptr<base::Value> value) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(CalledOnValidThread());
   callback_.Run(fetch_error_code, value.Pass());
 }
 
 //========================= InitiateUploadRequestBase ========================
 
 InitiateUploadRequestBase::InitiateUploadRequestBase(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
+    RequestSender* sender,
     const InitiateUploadCallback& callback,
-    const base::FilePath& drive_file_path,
     const std::string& content_type,
     int64 content_length)
-    : UrlFetchRequestBase(runner,
-                          url_request_context_getter,
-                          drive_file_path),
+    : UrlFetchRequestBase(sender),
       callback_(callback),
-      drive_file_path_(drive_file_path),
       content_type_(content_type),
       content_length_(content_length) {
   DCHECK(!callback_.is_null());
@@ -430,9 +389,6 @@
                                                   kUploadResponseLocation,
                                                   &upload_location);
   }
-  VLOG(1) << "Got response for [" << drive_file_path_.value()
-          << "]: code=" << code
-          << ", location=[" << upload_location << "]";
 
   callback_.Run(code, GURL(upload_location));
   OnProcessURLFetchResultsComplete(code == HTTP_SUCCESS);
@@ -473,15 +429,9 @@
 
 //========================== UploadRangeRequestBase ==========================
 
-UploadRangeRequestBase::UploadRangeRequestBase(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
-    const base::FilePath& drive_file_path,
-    const GURL& upload_url)
-    : UrlFetchRequestBase(runner,
-                          url_request_context_getter,
-                          drive_file_path),
-      drive_file_path_(drive_file_path),
+UploadRangeRequestBase::UploadRangeRequestBase(RequestSender* sender,
+                                               const GURL& upload_url)
+    : UrlFetchRequestBase(sender),
       upload_url_(upload_url),
       weak_ptr_factory_(this) {
 }
@@ -528,11 +478,6 @@
     // The Range header has the received data range, so the start position
     // should be always 0.
     DCHECK_EQ(start_position_received, 0);
-    DVLOG(1) << "Got response for [" << drive_file_path_.value()
-             << "]: code=" << code
-             << ", range_hdr=[" << range_received
-             << "], range_parsed=" << start_position_received
-             << "," << end_position_received;
 
     OnRangeRequestComplete(UploadRangeResponse(code,
                                                start_position_received,
@@ -544,9 +489,6 @@
     // There might be explanation of unexpected error code in response.
     std::string response_content;
     source->GetResponseAsString(&response_content);
-    DVLOG(1) << "Got response for [" << drive_file_path_.value()
-             << "]: code=" << code
-             << ", content=[\n" << response_content << "\n]";
 
     ParseJson(response_content,
               base::Bind(&UploadRangeRequestBase::OnDataParsed,
@@ -557,7 +499,7 @@
 
 void UploadRangeRequestBase::OnDataParsed(GDataErrorCode code,
                                           scoped_ptr<base::Value> value) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(CalledOnValidThread());
 
   OnRangeRequestComplete(UploadRangeResponse(code, -1, -1), value.Pass());
   OnProcessURLFetchResultsComplete(
@@ -573,19 +515,14 @@
 //========================== ResumeUploadRequestBase =========================
 
 ResumeUploadRequestBase::ResumeUploadRequestBase(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
-    const base::FilePath& drive_file_path,
+    RequestSender* sender,
     const GURL& upload_location,
     int64 start_position,
     int64 end_position,
     int64 content_length,
     const std::string& content_type,
     const base::FilePath& local_file_path)
-    : UploadRangeRequestBase(runner,
-                             url_request_context_getter,
-                             drive_file_path,
-                             upload_location),
+    : UploadRangeRequestBase(sender, upload_location),
       start_position_(start_position),
       end_position_(end_position),
       content_length_(content_length),
@@ -642,16 +579,10 @@
 
 //======================== GetUploadStatusRequestBase ========================
 
-GetUploadStatusRequestBase::GetUploadStatusRequestBase(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
-    const base::FilePath& drive_file_path,
-    const GURL& upload_url,
-    int64 content_length)
-    : UploadRangeRequestBase(runner,
-                             url_request_context_getter,
-                             drive_file_path,
-                             upload_url),
+GetUploadStatusRequestBase::GetUploadStatusRequestBase(RequestSender* sender,
+                                                       const GURL& upload_url,
+                                                       int64 content_length)
+    : UploadRangeRequestBase(sender, upload_url),
       content_length_(content_length) {}
 
 GetUploadStatusRequestBase::~GetUploadStatusRequestBase() {}
@@ -671,60 +602,60 @@
   return headers;
 }
 
-//============================ DownloadFileRequest ===========================
+//============================ DownloadFileRequestBase =========================
 
-DownloadFileRequest::DownloadFileRequest(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
+DownloadFileRequestBase::DownloadFileRequestBase(
+    RequestSender* sender,
     const DownloadActionCallback& download_action_callback,
     const GetContentCallback& get_content_callback,
     const ProgressCallback& progress_callback,
     const GURL& download_url,
-    const base::FilePath& drive_file_path,
     const base::FilePath& output_file_path)
-    : UrlFetchRequestBase(runner,
-                          url_request_context_getter,
-                          drive_file_path),
+    : UrlFetchRequestBase(sender),
       download_action_callback_(download_action_callback),
       get_content_callback_(get_content_callback),
       progress_callback_(progress_callback),
-      download_url_(download_url) {
+      download_url_(download_url),
+      output_file_path_(output_file_path) {
   DCHECK(!download_action_callback_.is_null());
+  DCHECK(!output_file_path_.empty());
   // get_content_callback may be null.
-
-  // Make sure we download the content into a temp file.
-  if (output_file_path.empty())
-    set_save_temp_file(true);
-  else
-    set_output_file_path(output_file_path);
 }
 
-DownloadFileRequest::~DownloadFileRequest() {}
+DownloadFileRequestBase::~DownloadFileRequestBase() {}
 
 // Overridden from UrlFetchRequestBase.
-GURL DownloadFileRequest::GetURL() const {
+GURL DownloadFileRequestBase::GetURL() const {
   return download_url_;
 }
 
-void DownloadFileRequest::OnURLFetchDownloadProgress(const URLFetcher* source,
-                                                     int64 current,
-                                                     int64 total) {
+bool DownloadFileRequestBase::GetOutputFilePath(
+    base::FilePath* local_file_path) {
+  // Configure so that the downloaded content is saved to |output_file_path_|.
+  *local_file_path = output_file_path_;
+  return true;
+}
+
+void DownloadFileRequestBase::OnURLFetchDownloadProgress(
+    const URLFetcher* source,
+    int64 current,
+    int64 total) {
   if (!progress_callback_.is_null())
     progress_callback_.Run(current, total);
 }
 
-bool DownloadFileRequest::ShouldSendDownloadData() {
+bool DownloadFileRequestBase::ShouldSendDownloadData() {
   return !get_content_callback_.is_null();
 }
 
-void DownloadFileRequest::OnURLFetchDownloadData(
+void DownloadFileRequestBase::OnURLFetchDownloadData(
     const URLFetcher* source,
     scoped_ptr<std::string> download_data) {
   if (!get_content_callback_.is_null())
     get_content_callback_.Run(HTTP_SUCCESS, download_data.Pass());
 }
 
-void DownloadFileRequest::ProcessURLFetchResults(const URLFetcher* source) {
+void DownloadFileRequestBase::ProcessURLFetchResults(const URLFetcher* source) {
   GDataErrorCode code = GetErrorCode(source);
 
   // Take over the ownership of the the downloaded temp file.
@@ -739,7 +670,8 @@
   OnProcessURLFetchResultsComplete(code == HTTP_SUCCESS);
 }
 
-void DownloadFileRequest::RunCallbackOnPrematureFailure(GDataErrorCode code) {
+void DownloadFileRequestBase::RunCallbackOnPrematureFailure(
+    GDataErrorCode code) {
   download_action_callback_.Run(code, base::FilePath());
 }
 
diff --git a/chrome/browser/google_apis/base_requests.h b/chrome/browser/google_apis/base_requests.h
index f187b15..d57a6c6 100644
--- a/chrome/browser/google_apis/base_requests.h
+++ b/chrome/browser/google_apis/base_requests.h
@@ -12,21 +12,18 @@
 #include <vector>
 
 #include "base/callback.h"
+#include "base/files/file_path.h"
 #include "base/memory/weak_ptr.h"
+#include "base/threading/thread_checker.h"
 #include "chrome/browser/google_apis/gdata_errorcode.h"
-#include "chrome/browser/google_apis/request_registry.h"
-#include "googleurl/src/gurl.h"
 #include "net/url_request/url_fetcher.h"
 #include "net/url_request/url_fetcher_delegate.h"
+#include "url/gurl.h"
 
 namespace base {
 class Value;
 }  // namespace base
 
-namespace net {
-class URLRequestContextGetter;
-}  // namespace net
-
 namespace google_apis {
 
 class RequestSender;
@@ -74,20 +71,18 @@
   // deleted when it is canceled by user action, for posting asynchronous tasks
   // on the authentication request object, weak pointers have to be used.
   // TODO(kinaba): crbug.com/134814 use more clean life time management than
-  // using weak pointers, while deprecating RequestRegistry.
+  // using weak pointers.
   virtual base::WeakPtr<AuthenticatedRequestInterface> GetWeakPtr() = 0;
 
-  // TODO(kinaba): crbug.com/{164089, 231209} This is temporarily added during
-  // migration of cancellation from RequestRegistry to JobScheduler. It should
-  // go away *very soon*.
-  virtual RequestRegistry::Request* AsRequestRegistryRequest() = 0;
+  // Cancels the request. It will invoke the callback object passed in
+  // each request's constructor with error code GDATA_CANCELLED.
+  virtual void Cancel() = 0;
 };
 
 //============================ UrlFetchRequestBase ===========================
 
 // Base class for requests that are fetching URLs.
 class UrlFetchRequestBase : public AuthenticatedRequestInterface,
-                            public RequestRegistry::Request,
                             public net::URLFetcherDelegate {
  public:
   // AuthenticatedRequestInterface overrides.
@@ -95,19 +90,10 @@
                      const std::string& custom_user_agent,
                      const ReAuthenticateCallback& callback) OVERRIDE;
   virtual base::WeakPtr<AuthenticatedRequestInterface> GetWeakPtr() OVERRIDE;
+  virtual void Cancel() OVERRIDE;
 
  protected:
-  UrlFetchRequestBase(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter);
-  // Use this constructor when you need to implement requests that take a
-  // drive file path (ex. for downloading and uploading).
-  // |url_request_context_getter| is used to initialize URLFetcher.
-  // TODO(satorux): Remove the drive file path hack. crbug.com/163296
-  UrlFetchRequestBase(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
-      const base::FilePath& drive_file_path);
+  explicit UrlFetchRequestBase(RequestSender* sender);
   virtual ~UrlFetchRequestBase();
 
   // Gets URL for the request.
@@ -138,6 +124,10 @@
                               int64* range_length,
                               std::string* upload_content_type);
 
+  // Used by a derived class to set an output file path if they want to save
+  // the downloaded content to a file at a specific path.
+  virtual bool GetOutputFilePath(base::FilePath* local_file_path);
+
   // Invoked by OnURLFetchComplete when the request completes without an
   // authentication error. Must be implemented by a derived class.
   virtual void ProcessURLFetchResults(const net::URLFetcher* source) = 0;
@@ -153,44 +143,28 @@
   // the status of the URLFetcher.
   static GDataErrorCode GetErrorCode(const net::URLFetcher* source);
 
-  // By default, no temporary file will be saved. Derived classes can set
-  // this to true in their constructors, if they want to save the downloaded
-  // content to a temporary file.
-  void set_save_temp_file(bool save_temp_file) {
-    save_temp_file_ = save_temp_file;
-  }
-
-  // By default, no file will be saved. Derived classes can set an output
-  // file path in their constructors, if they want to save the downloaded
-  // content to a file at a specific path.
-  void set_output_file_path(const base::FilePath& output_file_path) {
-    output_file_path_ = output_file_path;
-  }
+  // Returns true if called on the thread where the constructor was called.
+  bool CalledOnValidThread();
 
  private:
-  // RequestRegistry::Request overrides.
-  virtual void DoCancel() OVERRIDE;
-
   // URLFetcherDelegate overrides.
   virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
 
   // AuthenticatedRequestInterface overrides.
   virtual void OnAuthFailed(GDataErrorCode code) OVERRIDE;
-  virtual RequestRegistry::Request* AsRequestRegistryRequest() OVERRIDE;
 
-  net::URLRequestContextGetter* url_request_context_getter_;
   ReAuthenticateCallback re_authenticate_callback_;
   int re_authenticate_count_;
   scoped_ptr<net::URLFetcher> url_fetcher_;
-  bool started_;
+  RequestSender* sender_;
 
-  bool save_temp_file_;
-  base::FilePath output_file_path_;
+  base::ThreadChecker thread_checker_;
 
-  // WeakPtrFactory bound to the UI thread.
   // Note: This should remain the last member so it'll be destroyed and
   // invalidate its weak pointers before any other members are destroyed.
   base::WeakPtrFactory<UrlFetchRequestBase> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(UrlFetchRequestBase);
 };
 
 //============================ EntryActionRequest ============================
@@ -204,10 +178,8 @@
  public:
   // |url_request_context_getter| is used to initialize URLFetcher.
   // |callback| must not be null.
-  EntryActionRequest(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
-      const EntryActionCallback& callback);
+  EntryActionRequest(RequestSender* sender,
+                     const EntryActionCallback& callback);
   virtual ~EntryActionRequest();
 
  protected:
@@ -234,9 +206,7 @@
 class GetDataRequest : public UrlFetchRequestBase {
  public:
   // |callback| must not be null.
-  GetDataRequest(RequestSender* runner,
-                 net::URLRequestContextGetter* url_request_context_getter,
-                 const GetDataCallback& callback);
+  GetDataRequest(RequestSender* sender, const GetDataCallback& callback);
   virtual ~GetDataRequest();
 
   // Parses JSON response.
@@ -263,6 +233,7 @@
   // Note: This should remain the last member so it'll be destroyed and
   // invalidate its weak pointers before any other members are destroyed.
   base::WeakPtrFactory<GetDataRequest> weak_ptr_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(GetDataRequest);
 };
 
@@ -291,13 +262,10 @@
   // |callback| must not be null.
   // |content_type| and |content_length| should be the attributes of the
   // uploading file.
-  InitiateUploadRequestBase(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
-      const InitiateUploadCallback& callback,
-      const base::FilePath& drive_file_path,
-      const std::string& content_type,
-      int64 content_length);
+  InitiateUploadRequestBase(RequestSender* sender,
+                            const InitiateUploadCallback& callback,
+                            const std::string& content_type,
+                            int64 content_length);
   virtual ~InitiateUploadRequestBase();
 
   // UrlFetchRequestBase overrides.
@@ -307,7 +275,6 @@
 
  private:
   const InitiateUploadCallback callback_;
-  const base::FilePath drive_file_path_;
   const std::string content_type_;
   const int64 content_length_;
 
@@ -341,14 +308,7 @@
 class UploadRangeRequestBase : public UrlFetchRequestBase {
  protected:
   // |upload_location| is the URL of where to upload the file to.
-  // |drive_file_path| is the path to the file seen in the UI. Not necessary
-  // for resuming an upload, but used for adding an entry to RequestRegistry.
-  // TODO(satorux): Remove the drive file path hack. crbug.com/163296
-  UploadRangeRequestBase(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
-      const base::FilePath& drive_file_path,
-      const GURL& upload_url);
+  UploadRangeRequestBase(RequestSender* sender, const GURL& upload_url);
   virtual ~UploadRangeRequestBase();
 
   // UrlFetchRequestBase overrides.
@@ -380,12 +340,12 @@
   // Called when ParseJson() is completed.
   void OnDataParsed(GDataErrorCode code, scoped_ptr<base::Value> value);
 
-  const base::FilePath drive_file_path_;
   const GURL upload_url_;
 
   // Note: This should remain the last member so it'll be destroyed and
   // invalidate its weak pointers before any other members are destroyed.
   base::WeakPtrFactory<UploadRangeRequestBase> weak_ptr_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(UploadRangeRequestBase);
 };
 
@@ -408,17 +368,14 @@
   // file content to be uploaded respectively.
   // |buf| holds current content to be uploaded.
   // See also UploadRangeRequestBase's comment for remaining parameters
-  // meaining.
-  ResumeUploadRequestBase(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
-      const base::FilePath& drive_file_path,
-      const GURL& upload_location,
-      int64 start_position,
-      int64 end_position,
-      int64 content_length,
-      const std::string& content_type,
-      const base::FilePath& local_file_path);
+  // meaning.
+  ResumeUploadRequestBase(RequestSender* sender,
+                          const GURL& upload_location,
+                          int64 start_position,
+                          int64 end_position,
+                          int64 content_length,
+                          const std::string& content_type,
+                          const base::FilePath& local_file_path);
   virtual ~ResumeUploadRequestBase();
 
   // UrlFetchRequestBase overrides.
@@ -454,12 +411,9 @@
   // |content_length| is the whole data size to be uploaded.
   // See also UploadRangeRequestBase's constructor comment for other
   // parameters.
-  GetUploadStatusRequestBase(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
-      const base::FilePath& drive_file_path,
-      const GURL& upload_url,
-      int64 content_length);
+  GetUploadStatusRequestBase(RequestSender* sender,
+                             const GURL& upload_url,
+                             int64 content_length);
   virtual ~GetUploadStatusRequestBase();
 
  protected:
@@ -484,8 +438,8 @@
                             const base::FilePath& temp_file)>
     DownloadActionCallback;
 
-// This class performs the request for downloading of a given document/file.
-class DownloadFileRequest : public UrlFetchRequestBase {
+// This is a base class for performing the request for downloading a file.
+class DownloadFileRequestBase : public UrlFetchRequestBase {
  public:
   // download_action_callback:
   //   This callback is called when the download is complete. Must not be null.
@@ -501,27 +455,22 @@
   // download_url:
   //   Specifies the target file to download.
   //
-  // drive_file_path:
-  //   Specifies the drive path of the target file. Shown in UI.
-  //   TODO(satorux): Remove the drive file path hack. crbug.com/163296
-  //
   // output_file_path:
   //   Specifies the file path to save the downloaded file.
   //
-  DownloadFileRequest(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
+  DownloadFileRequestBase(
+      RequestSender* sender,
       const DownloadActionCallback& download_action_callback,
       const GetContentCallback& get_content_callback,
       const ProgressCallback& progress_callback,
       const GURL& download_url,
-      const base::FilePath& drive_file_path,
       const base::FilePath& output_file_path);
-  virtual ~DownloadFileRequest();
+  virtual ~DownloadFileRequestBase();
 
  protected:
   // UrlFetchRequestBase overrides.
   virtual GURL GetURL() const OVERRIDE;
+  virtual bool GetOutputFilePath(base::FilePath* local_file_path) OVERRIDE;
   virtual void ProcessURLFetchResults(const net::URLFetcher* source) OVERRIDE;
   virtual void RunCallbackOnPrematureFailure(GDataErrorCode code) OVERRIDE;
 
@@ -538,8 +487,9 @@
   const GetContentCallback get_content_callback_;
   const ProgressCallback progress_callback_;
   const GURL download_url_;
+  const base::FilePath output_file_path_;
 
-  DISALLOW_COPY_AND_ASSIGN(DownloadFileRequest);
+  DISALLOW_COPY_AND_ASSIGN(DownloadFileRequestBase);
 };
 
 }  // namespace google_apis
diff --git a/chrome/browser/google_apis/base_requests_server_unittest.cc b/chrome/browser/google_apis/base_requests_server_unittest.cc
index 539f1ad..58f8941 100644
--- a/chrome/browser/google_apis/base_requests_server_unittest.cc
+++ b/chrome/browser/google_apis/base_requests_server_unittest.cc
@@ -7,8 +7,7 @@
 #include "base/bind.h"
 #include "base/file_util.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/message_loop.h"
-#include "base/values.h"
+#include "base/run_loop.h"
 #include "chrome/browser/google_apis/auth_service.h"
 #include "chrome/browser/google_apis/request_sender.h"
 #include "chrome/browser/google_apis/task_util.h"
@@ -60,11 +59,6 @@
                    base::Unretained(&http_request_)));
   }
 
-  virtual void TearDown() OVERRIDE {
-    EXPECT_TRUE(test_server_.ShutdownAndWaitUntilComplete());
-    request_context_getter_ = NULL;
-  }
-
   // Returns a temporary file path suitable for storing the cache file.
   base::FilePath GetTestCachedFilePath(const base::FilePath& file_name) {
     return profile_->GetPath().Append(file_name);
@@ -85,31 +79,32 @@
 TEST_F(BaseRequestsServerTest, DownloadFileRequest_ValidFile) {
   GDataErrorCode result_code = GDATA_OTHER_ERROR;
   base::FilePath temp_file;
-  DownloadFileRequest* request = new DownloadFileRequest(
-      request_sender_.get(),
-      request_context_getter_.get(),
-      CreateComposedCallback(
-          base::Bind(&test_util::RunAndQuit),
-          test_util::CreateCopyResultCallback(&result_code, &temp_file)),
-      GetContentCallback(),
-      ProgressCallback(),
-      test_server_.GetURL("/files/chromeos/gdata/testfile.txt"),
-      base::FilePath::FromUTF8Unsafe("/dummy/gdata/testfile.txt"),
-      GetTestCachedFilePath(
-          base::FilePath::FromUTF8Unsafe("cached_testfile.txt")));
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    DownloadFileRequestBase* request = new DownloadFileRequestBase(
+        request_sender_.get(),
+        test_util::CreateQuitCallback(
+            &run_loop,
+            test_util::CreateCopyResultCallback(&result_code, &temp_file)),
+        GetContentCallback(),
+        ProgressCallback(),
+        test_server_.GetURL("/files/gdata/testfile.txt"),
+        GetTestCachedFilePath(
+            base::FilePath::FromUTF8Unsafe("cached_testfile.txt")));
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   std::string contents;
   file_util::ReadFileToString(temp_file, &contents);
-  file_util::Delete(temp_file, false);
+  base::Delete(temp_file, false);
 
   EXPECT_EQ(HTTP_SUCCESS, result_code);
   EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method);
-  EXPECT_EQ("/files/chromeos/gdata/testfile.txt", http_request_.relative_url);
+  EXPECT_EQ("/files/gdata/testfile.txt", http_request_.relative_url);
 
   const base::FilePath expected_path =
-      test_util::GetTestFilePath("chromeos/gdata/testfile.txt");
+      test_util::GetTestFilePath("gdata/testfile.txt");
   std::string expected_contents;
   file_util::ReadFileToString(expected_path, &expected_contents);
   EXPECT_EQ(expected_contents, contents);
@@ -118,24 +113,24 @@
 TEST_F(BaseRequestsServerTest, DownloadFileRequest_NonExistentFile) {
   GDataErrorCode result_code = GDATA_OTHER_ERROR;
   base::FilePath temp_file;
-  DownloadFileRequest* request = new DownloadFileRequest(
-      request_sender_.get(),
-      request_context_getter_.get(),
-      CreateComposedCallback(
-          base::Bind(&test_util::RunAndQuit),
-          test_util::CreateCopyResultCallback(&result_code, &temp_file)),
-      GetContentCallback(),
-      ProgressCallback(),
-      test_server_.GetURL("/files/chromeos/gdata/no-such-file.txt"),
-      base::FilePath::FromUTF8Unsafe("/dummy/gdata/no-such-file.txt"),
-      GetTestCachedFilePath(
-          base::FilePath::FromUTF8Unsafe("cache_no-such-file.txt")));
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
-
+  {
+    base::RunLoop run_loop;
+    DownloadFileRequestBase* request = new DownloadFileRequestBase(
+        request_sender_.get(),
+        test_util::CreateQuitCallback(
+            &run_loop,
+            test_util::CreateCopyResultCallback(&result_code, &temp_file)),
+        GetContentCallback(),
+        ProgressCallback(),
+        test_server_.GetURL("/files/gdata/no-such-file.txt"),
+        GetTestCachedFilePath(
+            base::FilePath::FromUTF8Unsafe("cache_no-such-file.txt")));
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
   EXPECT_EQ(HTTP_NOT_FOUND, result_code);
   EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method);
-  EXPECT_EQ("/files/chromeos/gdata/no-such-file.txt",
+  EXPECT_EQ("/files/gdata/no-such-file.txt",
             http_request_.relative_url);
   // Do not verify the not found message.
 }
diff --git a/chrome/browser/google_apis/base_requests_unittest.cc b/chrome/browser/google_apis/base_requests_unittest.cc
index a0a3f36..a4eb9f0 100644
--- a/chrome/browser/google_apis/base_requests_unittest.cc
+++ b/chrome/browser/google_apis/base_requests_unittest.cc
@@ -22,16 +22,14 @@
 
 class FakeGetDataRequest : public GetDataRequest {
  public:
-  explicit FakeGetDataRequest(RequestSender* runner,
+  explicit FakeGetDataRequest(RequestSender* sender,
                               const GetDataCallback& callback)
-      : GetDataRequest(runner, NULL, callback) {
+      : GetDataRequest(sender, callback) {
   }
 
   virtual ~FakeGetDataRequest() {
   }
 
-  using RequestRegistry::Request::NotifyStart;
-
  protected:
   virtual GURL GetURL() const OVERRIDE {
     NOTREACHED();  // This method is not called in tests.
@@ -43,58 +41,31 @@
 
 class BaseRequestsTest : public testing::Test {
  public:
-  BaseRequestsTest()
-      : parse_json_callback_called_(false),
-        get_data_callback_called_(false) {
-  }
-
-  void ParseJsonCallback(scoped_ptr<base::Value> value) {
-    parse_json_result_ = value.Pass();;
-    parse_json_callback_called_ = true;
-  }
-
-  void GetDataCallback(GDataErrorCode error, scoped_ptr<base::Value> value) {
-    get_data_result_error_ = error;
-    get_data_result_value_ = value.Pass();
-    get_data_callback_called_ = true;
-  }
-
   virtual void SetUp() OVERRIDE {
     profile_.reset(new TestingProfile);
-    runner_.reset(new RequestSender(profile_.get(),
+    sender_.reset(new RequestSender(profile_.get(),
                                     NULL /* url_request_context_getter */,
                                     std::vector<std::string>() /* scopes */,
                                     std::string() /* custom user agent */));
-    runner_->Initialize();
-    LOG(ERROR) << "Initialized.";
+    sender_->Initialize();
   }
 
   content::TestBrowserThreadBundle thread_bundle_;
   scoped_ptr<TestingProfile> profile_;
-  scoped_ptr<RequestSender> runner_;
-
-  // Following members stores data returned with callbacks to be verified
-  // by tests.
-  scoped_ptr<base::Value> parse_json_result_;
-  bool parse_json_callback_called_;
-  GDataErrorCode get_data_result_error_;
-  scoped_ptr<base::Value> get_data_result_value_;
-  bool get_data_callback_called_;
+  scoped_ptr<RequestSender> sender_;
 };
 
 TEST_F(BaseRequestsTest, ParseValidJson) {
+  scoped_ptr<base::Value> json;
   ParseJson(kValidJsonString,
-            base::Bind(&BaseRequestsTest::ParseJsonCallback,
-                       base::Unretained(this)));
+            base::Bind(test_util::CreateCopyResultCallback(&json)));
   // Should wait for a blocking pool task, as the JSON parsing is done in the
   // blocking pool.
   test_util::RunBlockingPoolTask();
 
-  ASSERT_TRUE(parse_json_callback_called_);
-  ASSERT_TRUE(parse_json_result_.get());
-
   DictionaryValue* root_dict = NULL;
-  ASSERT_TRUE(parse_json_result_->GetAsDictionary(&root_dict));
+  ASSERT_TRUE(json);
+  ASSERT_TRUE(json->GetAsDictionary(&root_dict));
 
   int int_value = 0;
   ASSERT_TRUE(root_dict->GetInteger("test", &int_value));
@@ -102,51 +73,49 @@
 }
 
 TEST_F(BaseRequestsTest, ParseInvalidJson) {
+  // Initialize with a valid pointer to verify that null is indeed assigned.
+  scoped_ptr<base::Value> json(base::Value::CreateNullValue());
   ParseJson(kInvalidJsonString,
-            base::Bind(&BaseRequestsTest::ParseJsonCallback,
-                       base::Unretained(this)));
+            base::Bind(test_util::CreateCopyResultCallback(&json)));
   // Should wait for a blocking pool task, as the JSON parsing is done in the
   // blocking pool.
   test_util::RunBlockingPoolTask();
 
-  ASSERT_TRUE(parse_json_callback_called_);
-  ASSERT_FALSE(parse_json_result_.get());
+  EXPECT_FALSE(json);
 }
 
 TEST_F(BaseRequestsTest, GetDataRequestParseValidResponse) {
+  GDataErrorCode error = GDATA_OTHER_ERROR;
+  scoped_ptr<base::Value> value;
   FakeGetDataRequest* get_data_request =
       new FakeGetDataRequest(
-          runner_.get(),
-          base::Bind(&BaseRequestsTest::GetDataCallback,
-                     base::Unretained(this)));
-  get_data_request->NotifyStart();
+          sender_.get(),
+          base::Bind(test_util::CreateCopyResultCallback(&error, &value)));
 
   get_data_request->ParseResponse(HTTP_SUCCESS, kValidJsonString);
   // Should wait for a blocking pool task, as the JSON parsing is done in the
   // blocking pool.
   test_util::RunBlockingPoolTask();
 
-  ASSERT_TRUE(get_data_callback_called_);
-  ASSERT_EQ(HTTP_SUCCESS, get_data_result_error_);
-  ASSERT_TRUE(get_data_result_value_.get());
+  EXPECT_EQ(HTTP_SUCCESS, error);
+  EXPECT_TRUE(value);
 }
 
 TEST_F(BaseRequestsTest, GetDataRequestParseInvalidResponse) {
+  GDataErrorCode error = GDATA_OTHER_ERROR;
+  scoped_ptr<base::Value> value;
   FakeGetDataRequest* get_data_request =
       new FakeGetDataRequest(
-          runner_.get(),
-          base::Bind(&BaseRequestsTest::GetDataCallback,
-                     base::Unretained(this)));
-  get_data_request->NotifyStart();
+          sender_.get(),
+          base::Bind(test_util::CreateCopyResultCallback(&error, &value)));
 
   get_data_request->ParseResponse(HTTP_SUCCESS, kInvalidJsonString);
   // Should wait for a blocking pool task, as the JSON parsing is done in the
   // blocking pool.
   test_util::RunBlockingPoolTask();
 
-  ASSERT_TRUE(get_data_callback_called_);
-  ASSERT_EQ(GDATA_PARSE_ERROR, get_data_result_error_);
-  ASSERT_FALSE(get_data_result_value_.get());
+  EXPECT_EQ(GDATA_PARSE_ERROR, error);
+  EXPECT_FALSE(value);
 }
 
 }  // namespace google_apis
diff --git a/chrome/browser/google_apis/drive_api_parser.h b/chrome/browser/google_apis/drive_api_parser.h
index f8d001d..7042320 100644
--- a/chrome/browser/google_apis/drive_api_parser.h
+++ b/chrome/browser/google_apis/drive_api_parser.h
@@ -12,8 +12,8 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/scoped_vector.h"
 #include "base/strings/string_piece.h"
-#include "base/time.h"
-#include "googleurl/src/gurl.h"
+#include "base/time/time.h"
+#include "url/gurl.h"
 // TODO(kochi): Eliminate this dependency once dependency to EntryKind is gone.
 // http://crbug.com/142293
 #include "chrome/browser/google_apis/gdata_wapi_parser.h"
diff --git a/chrome/browser/google_apis/drive_api_parser_unittest.cc b/chrome/browser/google_apis/drive_api_parser_unittest.cc
index 8fa6197..60d4f35 100644
--- a/chrome/browser/google_apis/drive_api_parser_unittest.cc
+++ b/chrome/browser/google_apis/drive_api_parser_unittest.cc
@@ -4,7 +4,7 @@
 
 #include "chrome/browser/google_apis/drive_api_parser.h"
 
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/google_apis/gdata_wapi_parser.h"
 #include "chrome/browser/google_apis/test_util.h"
@@ -20,7 +20,7 @@
 TEST(DriveAPIParserTest, AboutResourceParser) {
   std::string error;
   scoped_ptr<base::Value> document = test_util::LoadJSONFile(
-      "chromeos/drive/about.json");
+      "drive/about.json");
   ASSERT_TRUE(document.get());
 
   ASSERT_EQ(base::Value::TYPE_DICTIONARY, document->GetType());
@@ -56,7 +56,7 @@
 TEST(DriveAPIParserTest, AppListParser) {
   std::string error;
   scoped_ptr<base::Value> document = test_util::LoadJSONFile(
-      "chromeos/drive/applist.json");
+      "drive/applist.json");
   ASSERT_TRUE(document.get());
 
   ASSERT_EQ(base::Value::TYPE_DICTIONARY, document->GetType());
@@ -234,7 +234,7 @@
 TEST(DriveAPIParserTest, FileListParser) {
   std::string error;
   scoped_ptr<base::Value> document = test_util::LoadJSONFile(
-      "chromeos/drive/filelist.json");
+      "drive/filelist.json");
   ASSERT_TRUE(document.get());
 
   ASSERT_EQ(base::Value::TYPE_DICTIONARY, document->GetType());
@@ -350,7 +350,7 @@
 TEST(DriveAPIParserTest, ChangeListParser) {
   std::string error;
   scoped_ptr<base::Value> document =
-      test_util::LoadJSONFile("chromeos/drive/changelist.json");
+      test_util::LoadJSONFile("drive/changelist.json");
   ASSERT_TRUE(document.get());
 
   ASSERT_EQ(base::Value::TYPE_DICTIONARY, document->GetType());
@@ -413,9 +413,9 @@
 
 TEST(DriveAPIParserTest, HasKind) {
   scoped_ptr<base::Value> change_list_json(
-      test_util::LoadJSONFile("chromeos/drive/changelist.json"));
+      test_util::LoadJSONFile("drive/changelist.json"));
   scoped_ptr<base::Value> file_list_json(
-      test_util::LoadJSONFile("chromeos/drive/filelist.json"));
+      test_util::LoadJSONFile("drive/filelist.json"));
 
   EXPECT_TRUE(ChangeList::HasChangeListKind(*change_list_json));
   EXPECT_FALSE(ChangeList::HasChangeListKind(*file_list_json));
diff --git a/chrome/browser/google_apis/drive_api_requests.cc b/chrome/browser/google_apis/drive_api_requests.cc
index 555ff22..04e163e 100644
--- a/chrome/browser/google_apis/drive_api_requests.cc
+++ b/chrome/browser/google_apis/drive_api_requests.cc
@@ -11,9 +11,6 @@
 #include "chrome/browser/google_apis/drive_api_parser.h"
 #include "chrome/browser/google_apis/request_util.h"
 #include "chrome/browser/google_apis/time_util.h"
-#include "content/public/browser/browser_thread.h"
-
-using content::BrowserThread;
 
 namespace google_apis {
 namespace {
@@ -29,7 +26,6 @@
     const base::Callback<void(GDataErrorCode, scoped_ptr<T>)>& callback,
     GDataErrorCode error,
     scoped_ptr<base::Value> value) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(!callback.is_null());
 
   scoped_ptr<T> resource;
@@ -53,7 +49,6 @@
     const drive::UploadRangeCallback& callback,
     const UploadRangeResponse& response,
     scoped_ptr<base::Value> value) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(!callback.is_null());
 
   scoped_ptr<FileResource> file_resource;
@@ -77,11 +72,10 @@
 //============================== GetAboutRequest =============================
 
 GetAboutRequest::GetAboutRequest(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
+    RequestSender* sender,
     const DriveApiUrlGenerator& url_generator,
     const GetAboutResourceCallback& callback)
-    : GetDataRequest(runner, url_request_context_getter,
+    : GetDataRequest(sender,
                      base::Bind(&ParseJsonAndRun<AboutResource>, callback)),
       url_generator_(url_generator) {
   DCHECK(!callback.is_null());
@@ -96,11 +90,10 @@
 //============================== GetApplistRequest ===========================
 
 GetApplistRequest::GetApplistRequest(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
+    RequestSender* sender,
     const DriveApiUrlGenerator& url_generator,
     const GetDataCallback& callback)
-    : GetDataRequest(runner, url_request_context_getter, callback),
+    : GetDataRequest(sender, callback),
       url_generator_(url_generator) {
   DCHECK(!callback.is_null());
 }
@@ -114,14 +107,13 @@
 //============================ GetChangelistRequest ==========================
 
 GetChangelistRequest::GetChangelistRequest(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
+    RequestSender* sender,
     const DriveApiUrlGenerator& url_generator,
     bool include_deleted,
     int64 start_changestamp,
     int max_results,
     const GetDataCallback& callback)
-    : GetDataRequest(runner, url_request_context_getter, callback),
+    : GetDataRequest(sender, callback),
       url_generator_(url_generator),
       include_deleted_(include_deleted),
       start_changestamp_(start_changestamp),
@@ -139,13 +131,12 @@
 //============================= GetFilelistRequest ===========================
 
 GetFilelistRequest::GetFilelistRequest(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
+    RequestSender* sender,
     const DriveApiUrlGenerator& url_generator,
     const std::string& search_string,
     int max_results,
     const GetDataCallback& callback)
-    : GetDataRequest(runner, url_request_context_getter, callback),
+    : GetDataRequest(sender, callback),
       url_generator_(url_generator),
       search_string_(search_string),
       max_results_(max_results) {
@@ -161,12 +152,11 @@
 //=============================== GetFileRequest =============================
 
 GetFileRequest::GetFileRequest(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
+    RequestSender* sender,
     const DriveApiUrlGenerator& url_generator,
     const std::string& file_id,
     const FileResourceCallback& callback)
-    : GetDataRequest(runner, url_request_context_getter,
+    : GetDataRequest(sender,
                      base::Bind(&ParseJsonAndRun<FileResource>, callback)),
       url_generator_(url_generator),
       file_id_(file_id) {
@@ -184,11 +174,10 @@
 //======================= ContinueGetFileListRequest =========================
 
 ContinueGetFileListRequest::ContinueGetFileListRequest(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
+    RequestSender* sender,
     const GURL& url,
     const GetDataCallback& callback)
-    : GetDataRequest(runner, url_request_context_getter, callback),
+    : GetDataRequest(sender, callback),
       url_(url) {
   DCHECK(!callback.is_null());
 }
@@ -202,13 +191,12 @@
 //========================== CreateDirectoryRequest ==========================
 
 CreateDirectoryRequest::CreateDirectoryRequest(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
+    RequestSender* sender,
     const DriveApiUrlGenerator& url_generator,
     const std::string& parent_resource_id,
     const std::string& directory_name,
     const FileResourceCallback& callback)
-    : GetDataRequest(runner, url_request_context_getter,
+    : GetDataRequest(sender,
                      base::Bind(&ParseJsonAndRun<FileResource>, callback)),
       url_generator_(url_generator),
       parent_resource_id_(parent_resource_id),
@@ -253,13 +241,12 @@
 //=========================== RenameResourceRequest ==========================
 
 RenameResourceRequest::RenameResourceRequest(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
+    RequestSender* sender,
     const DriveApiUrlGenerator& url_generator,
     const std::string& resource_id,
     const std::string& new_name,
     const EntryActionCallback& callback)
-    : EntryActionRequest(runner, url_request_context_getter, callback),
+    : EntryActionRequest(sender, callback),
       url_generator_(url_generator),
       resource_id_(resource_id),
       new_name_(new_name) {
@@ -299,14 +286,13 @@
 //=========================== TouchResourceRequest ===========================
 
 TouchResourceRequest::TouchResourceRequest(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
+    RequestSender* sender,
     const DriveApiUrlGenerator& url_generator,
     const std::string& resource_id,
     const base::Time& modified_date,
     const base::Time& last_viewed_by_me_date,
     const FileResourceCallback& callback)
-    : GetDataRequest(runner, url_request_context_getter,
+    : GetDataRequest(sender,
                      base::Bind(&ParseJsonAndRun<FileResource>, callback)),
       url_generator_(url_generator),
       resource_id_(resource_id),
@@ -352,14 +338,13 @@
 //=========================== CopyResourceRequest ============================
 
 CopyResourceRequest::CopyResourceRequest(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
+    RequestSender* sender,
     const DriveApiUrlGenerator& url_generator,
     const std::string& resource_id,
     const std::string& parent_resource_id,
     const std::string& new_name,
     const FileResourceCallback& callback)
-    : GetDataRequest(runner, url_request_context_getter,
+    : GetDataRequest(sender,
                      base::Bind(&ParseJsonAndRun<FileResource>, callback)),
       url_generator_(url_generator),
       resource_id_(resource_id),
@@ -405,12 +390,11 @@
 //=========================== TrashResourceRequest ===========================
 
 TrashResourceRequest::TrashResourceRequest(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
+    RequestSender* sender,
     const DriveApiUrlGenerator& url_generator,
     const std::string& resource_id,
     const EntryActionCallback& callback)
-    : EntryActionRequest(runner, url_request_context_getter, callback),
+    : EntryActionRequest(sender, callback),
       url_generator_(url_generator),
       resource_id_(resource_id) {
   DCHECK(!callback.is_null());
@@ -429,13 +413,12 @@
 //========================== InsertResourceRequest ===========================
 
 InsertResourceRequest::InsertResourceRequest(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
+    RequestSender* sender,
     const DriveApiUrlGenerator& url_generator,
     const std::string& parent_resource_id,
     const std::string& resource_id,
     const EntryActionCallback& callback)
-    : EntryActionRequest(runner, url_request_context_getter, callback),
+    : EntryActionRequest(sender, callback),
       url_generator_(url_generator),
       parent_resource_id_(parent_resource_id),
       resource_id_(resource_id) {
@@ -468,13 +451,12 @@
 //========================== DeleteResourceRequest ===========================
 
 DeleteResourceRequest::DeleteResourceRequest(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
+    RequestSender* sender,
     const DriveApiUrlGenerator& url_generator,
     const std::string& parent_resource_id,
     const std::string& resource_id,
     const EntryActionCallback& callback)
-    : EntryActionRequest(runner, url_request_context_getter, callback),
+    : EntryActionRequest(sender, callback),
       url_generator_(url_generator),
       parent_resource_id_(parent_resource_id),
       resource_id_(resource_id) {
@@ -495,19 +477,15 @@
 //======================= InitiateUploadNewFileRequest =======================
 
 InitiateUploadNewFileRequest::InitiateUploadNewFileRequest(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
+    RequestSender* sender,
     const DriveApiUrlGenerator& url_generator,
-    const base::FilePath& drive_file_path,
     const std::string& content_type,
     int64 content_length,
     const std::string& parent_resource_id,
     const std::string& title,
     const InitiateUploadCallback& callback)
-    : InitiateUploadRequestBase(runner,
-                                url_request_context_getter,
+    : InitiateUploadRequestBase(sender,
                                 callback,
-                                drive_file_path,
                                 content_type,
                                 content_length),
       url_generator_(url_generator),
@@ -556,19 +534,15 @@
 //===================== InitiateUploadExistingFileRequest ====================
 
 InitiateUploadExistingFileRequest::InitiateUploadExistingFileRequest(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
+    RequestSender* sender,
     const DriveApiUrlGenerator& url_generator,
-    const base::FilePath& drive_file_path,
     const std::string& content_type,
     int64 content_length,
     const std::string& resource_id,
     const std::string& etag,
     const InitiateUploadCallback& callback)
-    : InitiateUploadRequestBase(runner,
-                                url_request_context_getter,
+    : InitiateUploadRequestBase(sender,
                                 callback,
-                                drive_file_path,
                                 content_type,
                                 content_length),
       url_generator_(url_generator),
@@ -598,9 +572,7 @@
 //============================ ResumeUploadRequest ===========================
 
 ResumeUploadRequest::ResumeUploadRequest(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
-    const base::FilePath& drive_file_path,
+    RequestSender* sender,
     const GURL& upload_location,
     int64 start_position,
     int64 end_position,
@@ -609,9 +581,7 @@
     const base::FilePath& local_file_path,
     const UploadRangeCallback& callback,
     const ProgressCallback& progress_callback)
-    : ResumeUploadRequestBase(runner,
-                              url_request_context_getter,
-                              drive_file_path,
+    : ResumeUploadRequestBase(sender,
                               upload_location,
                               start_position,
                               end_position,
@@ -626,7 +596,9 @@
 ResumeUploadRequest::~ResumeUploadRequest() {}
 
 void ResumeUploadRequest::OnRangeRequestComplete(
-    const UploadRangeResponse& response, scoped_ptr<base::Value> value) {
+    const UploadRangeResponse& response,
+    scoped_ptr<base::Value> value) {
+  DCHECK(CalledOnValidThread());
   ParseFileResourceWithUploadRangeAndRun(callback_, response, value.Pass());
 }
 
@@ -639,15 +611,11 @@
 //========================== GetUploadStatusRequest ==========================
 
 GetUploadStatusRequest::GetUploadStatusRequest(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
-    const base::FilePath& drive_file_path,
+    RequestSender* sender,
     const GURL& upload_url,
     int64 content_length,
     const UploadRangeCallback& callback)
-    : GetUploadStatusRequestBase(runner,
-                                 url_request_context_getter,
-                                 drive_file_path,
+    : GetUploadStatusRequestBase(sender,
                                  upload_url,
                                  content_length),
       callback_(callback) {
@@ -657,9 +625,33 @@
 GetUploadStatusRequest::~GetUploadStatusRequest() {}
 
 void GetUploadStatusRequest::OnRangeRequestComplete(
-    const UploadRangeResponse& response, scoped_ptr<base::Value> value) {
+    const UploadRangeResponse& response,
+    scoped_ptr<base::Value> value) {
+  DCHECK(CalledOnValidThread());
   ParseFileResourceWithUploadRangeAndRun(callback_, response, value.Pass());
 }
 
+//========================== DownloadFileRequest ==========================
+
+DownloadFileRequest::DownloadFileRequest(
+    RequestSender* sender,
+    const DriveApiUrlGenerator& url_generator,
+    const std::string& resource_id,
+    const base::FilePath& output_file_path,
+    const DownloadActionCallback& download_action_callback,
+    const GetContentCallback& get_content_callback,
+    const ProgressCallback& progress_callback)
+    : DownloadFileRequestBase(
+          sender,
+          download_action_callback,
+          get_content_callback,
+          progress_callback,
+          url_generator.GenerateDownloadFileUrl(resource_id),
+          output_file_path) {
+}
+
+DownloadFileRequest::~DownloadFileRequest() {
+}
+
 }  // namespace drive
 }  // namespace google_apis
diff --git a/chrome/browser/google_apis/drive_api_requests.h b/chrome/browser/google_apis/drive_api_requests.h
index f48513e..0fa5a79 100644
--- a/chrome/browser/google_apis/drive_api_requests.h
+++ b/chrome/browser/google_apis/drive_api_requests.h
@@ -12,10 +12,6 @@
 #include "chrome/browser/google_apis/drive_api_url_generator.h"
 #include "chrome/browser/google_apis/drive_common_callbacks.h"
 
-namespace net {
-class URLRequestContextGetter;
-}  // namespace net
-
 namespace google_apis {
 
 class FileResource;
@@ -32,8 +28,7 @@
 // This class performs the request for fetching About data.
 class GetAboutRequest : public GetDataRequest {
  public:
-  GetAboutRequest(RequestSender* runner,
-                  net::URLRequestContextGetter* url_request_context_getter,
+  GetAboutRequest(RequestSender* sender,
                   const DriveApiUrlGenerator& url_generator,
                   const GetAboutResourceCallback& callback);
   virtual ~GetAboutRequest();
@@ -53,8 +48,7 @@
 // This class performs the request for fetching Applist.
 class GetApplistRequest : public GetDataRequest {
  public:
-  GetApplistRequest(RequestSender* runner,
-                    net::URLRequestContextGetter* url_request_context_getter,
+  GetApplistRequest(RequestSender* sender,
                     const DriveApiUrlGenerator& url_generator,
                     const GetDataCallback& callback);
   virtual ~GetApplistRequest();
@@ -82,14 +76,12 @@
   // all changes are necessary.
   // |max_results| specifies the max of the number of files resource in the
   // response.
-  GetChangelistRequest(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
-      const DriveApiUrlGenerator& url_generator,
-      bool include_deleted,
-      int64 start_changestamp,
-      int max_results,
-      const GetDataCallback& callback);
+  GetChangelistRequest(RequestSender* sender,
+                       const DriveApiUrlGenerator& url_generator,
+                       bool include_deleted,
+                       int64 start_changestamp,
+                       int max_results,
+                       const GetDataCallback& callback);
   virtual ~GetChangelistRequest();
 
  protected:
@@ -112,13 +104,11 @@
 // should be able to be fetched by ContinueGetFileListRequest defined below.
 class GetFilelistRequest : public GetDataRequest {
  public:
-  GetFilelistRequest(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
-      const DriveApiUrlGenerator& url_generator,
-      const std::string& search_string,
-      int max_results,
-      const GetDataCallback& callback);
+  GetFilelistRequest(RequestSender* sender,
+                     const DriveApiUrlGenerator& url_generator,
+                     const std::string& search_string,
+                     int max_results,
+                     const GetDataCallback& callback);
   virtual ~GetFilelistRequest();
 
  protected:
@@ -138,8 +128,7 @@
 // This class performs the request for fetching a file.
 class GetFileRequest : public GetDataRequest {
  public:
-  GetFileRequest(RequestSender* runner,
-                 net::URLRequestContextGetter* url_request_context_getter,
+  GetFileRequest(RequestSender* sender,
                  const DriveApiUrlGenerator& url_generator,
                  const std::string& file_id,
                  const FileResourceCallback& callback);
@@ -169,11 +158,9 @@
 // This class performs the request to fetch remaining Filelist result.
 class ContinueGetFileListRequest : public GetDataRequest {
  public:
-  ContinueGetFileListRequest(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
-      const GURL& url,
-      const GetDataCallback& callback);
+  ContinueGetFileListRequest(RequestSender* sender,
+                             const GURL& url,
+                             const GetDataCallback& callback);
   virtual ~ContinueGetFileListRequest();
 
  protected:
@@ -190,13 +177,11 @@
 // This class performs the request for creating a directory.
 class CreateDirectoryRequest : public GetDataRequest {
  public:
-  CreateDirectoryRequest(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
-      const DriveApiUrlGenerator& url_generator,
-      const std::string& parent_resource_id,
-      const std::string& directory_name,
-      const FileResourceCallback& callback);
+  CreateDirectoryRequest(RequestSender* sender,
+                         const DriveApiUrlGenerator& url_generator,
+                         const std::string& parent_resource_id,
+                         const std::string& directory_name,
+                         const FileResourceCallback& callback);
   virtual ~CreateDirectoryRequest();
 
  protected:
@@ -220,13 +205,11 @@
 class RenameResourceRequest : public EntryActionRequest {
  public:
   // |callback| must not be null.
-  RenameResourceRequest(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
-      const DriveApiUrlGenerator& url_generator,
-      const std::string& resource_id,
-      const std::string& new_name,
-      const EntryActionCallback& callback);
+  RenameResourceRequest(RequestSender* sender,
+                        const DriveApiUrlGenerator& url_generator,
+                        const std::string& resource_id,
+                        const std::string& new_name,
+                        const EntryActionCallback& callback);
   virtual ~RenameResourceRequest();
 
  protected:
@@ -255,14 +238,12 @@
 class TouchResourceRequest : public GetDataRequest {
  public:
   // |callback| must not be null.
-  TouchResourceRequest(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
-      const DriveApiUrlGenerator& url_generator,
-      const std::string& resource_id,
-      const base::Time& modified_date,
-      const base::Time& last_viewed_by_me_date,
-      const FileResourceCallback& callback);
+  TouchResourceRequest(RequestSender* sender,
+                       const DriveApiUrlGenerator& url_generator,
+                       const std::string& resource_id,
+                       const base::Time& modified_date,
+                       const base::Time& last_viewed_by_me_date,
+                       const FileResourceCallback& callback);
   virtual ~TouchResourceRequest();
 
  protected:
@@ -298,14 +279,12 @@
 class CopyResourceRequest : public GetDataRequest {
  public:
   // Upon completion, |callback| will be called. |callback| must not be null.
-  CopyResourceRequest(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
-      const DriveApiUrlGenerator& url_generator,
-      const std::string& resource_id,
-      const std::string& parent_resource_id,
-      const std::string& new_name,
-      const FileResourceCallback& callback);
+  CopyResourceRequest(RequestSender* sender,
+                      const DriveApiUrlGenerator& url_generator,
+                      const std::string& resource_id,
+                      const std::string& parent_resource_id,
+                      const std::string& new_name,
+                      const FileResourceCallback& callback);
   virtual ~CopyResourceRequest();
 
  protected:
@@ -338,12 +317,10 @@
 class TrashResourceRequest : public EntryActionRequest {
  public:
   // |callback| must not be null.
-  TrashResourceRequest(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
-      const DriveApiUrlGenerator& url_generator,
-      const std::string& resource_id,
-      const EntryActionCallback& callback);
+  TrashResourceRequest(RequestSender* sender,
+                       const DriveApiUrlGenerator& url_generator,
+                       const std::string& resource_id,
+                       const EntryActionCallback& callback);
   virtual ~TrashResourceRequest();
 
  protected:
@@ -366,13 +343,11 @@
 class InsertResourceRequest : public EntryActionRequest {
  public:
   // |callback| must not be null.
-  InsertResourceRequest(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
-      const DriveApiUrlGenerator& url_generator,
-      const std::string& parent_resource_id,
-      const std::string& resource_id,
-      const EntryActionCallback& callback);
+  InsertResourceRequest(RequestSender* sender,
+                        const DriveApiUrlGenerator& url_generator,
+                        const std::string& parent_resource_id,
+                        const std::string& resource_id,
+                        const EntryActionCallback& callback);
   virtual ~InsertResourceRequest();
 
  protected:
@@ -401,13 +376,11 @@
 class DeleteResourceRequest : public EntryActionRequest {
  public:
   // |callback| must not be null.
-  DeleteResourceRequest(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
-      const DriveApiUrlGenerator& url_generator,
-      const std::string& parent_resource_id,
-      const std::string& resource_id,
-      const EntryActionCallback& callback);
+  DeleteResourceRequest(RequestSender* sender,
+                        const DriveApiUrlGenerator& url_generator,
+                        const std::string& parent_resource_id,
+                        const std::string& resource_id,
+                        const EntryActionCallback& callback);
   virtual ~DeleteResourceRequest();
 
  protected:
@@ -432,16 +405,13 @@
   // |title| should be set.
   // See also the comments of InitiateUploadRequestBase for more details
   // about the other parameters.
-  InitiateUploadNewFileRequest(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
-      const DriveApiUrlGenerator& url_generator,
-      const base::FilePath& drive_file_path,
-      const std::string& content_type,
-      int64 content_length,
-      const std::string& parent_resource_id,
-      const std::string& title,
-      const InitiateUploadCallback& callback);
+  InitiateUploadNewFileRequest(RequestSender* sender,
+                               const DriveApiUrlGenerator& url_generator,
+                               const std::string& content_type,
+                               int64 content_length,
+                               const std::string& parent_resource_id,
+                               const std::string& title,
+                               const InitiateUploadCallback& callback);
   virtual ~InitiateUploadNewFileRequest();
 
  protected:
@@ -471,16 +441,13 @@
   // |etag| should be set if it is available to detect the upload confliction.
   // See also the comments of InitiateUploadRequestBase for more details
   // about the other parameters.
-  InitiateUploadExistingFileRequest(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
-      const DriveApiUrlGenerator& url_generator,
-      const base::FilePath& drive_file_path,
-      const std::string& content_type,
-      int64 content_length,
-      const std::string& resource_id,
-      const std::string& etag,
-      const InitiateUploadCallback& callback);
+  InitiateUploadExistingFileRequest(RequestSender* sender,
+                                    const DriveApiUrlGenerator& url_generator,
+                                    const std::string& content_type,
+                                    int64 content_length,
+                                    const std::string& resource_id,
+                                    const std::string& etag,
+                                    const InitiateUploadCallback& callback);
   virtual ~InitiateUploadExistingFileRequest();
 
  protected:
@@ -509,18 +476,15 @@
  public:
   // See also ResumeUploadRequestBase's comment for parameters meaning.
   // |callback| must not be null. |progress_callback| may be null.
-  ResumeUploadRequest(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
-      const base::FilePath& drive_file_path,
-      const GURL& upload_location,
-      int64 start_position,
-      int64 end_position,
-      int64 content_length,
-      const std::string& content_type,
-      const base::FilePath& local_file_path,
-      const UploadRangeCallback& callback,
-      const ProgressCallback& progress_callback);
+  ResumeUploadRequest(RequestSender* sender,
+                      const GURL& upload_location,
+                      int64 start_position,
+                      int64 end_position,
+                      int64 content_length,
+                      const std::string& content_type,
+                      const base::FilePath& local_file_path,
+                      const UploadRangeCallback& callback,
+                      const ProgressCallback& progress_callback);
   virtual ~ResumeUploadRequest();
 
  protected:
@@ -546,13 +510,10 @@
  public:
   // See also GetUploadStatusRequestBase's comment for parameters meaning.
   // |callback| must not be null.
-  GetUploadStatusRequest(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
-      const base::FilePath& drive_file_path,
-      const GURL& upload_url,
-      int64 content_length,
-      const UploadRangeCallback& callback);
+  GetUploadStatusRequest(RequestSender* sender,
+                         const GURL& upload_url,
+                         int64 content_length,
+                         const UploadRangeCallback& callback);
   virtual ~GetUploadStatusRequest();
 
  protected:
@@ -567,6 +528,23 @@
   DISALLOW_COPY_AND_ASSIGN(GetUploadStatusRequest);
 };
 
+//========================== DownloadFileRequest ==========================
+
+// This class performs the request for downloading of a specified file.
+class DownloadFileRequest : public DownloadFileRequestBase {
+ public:
+  // See also DownloadFileRequestBase's comment for parameters meaning.
+  DownloadFileRequest(RequestSender* sender,
+                      const DriveApiUrlGenerator& url_generator,
+                      const std::string& resource_id,
+                      const base::FilePath& output_file_path,
+                      const DownloadActionCallback& download_action_callback,
+                      const GetContentCallback& get_content_callback,
+                      const ProgressCallback& progress_callback);
+  virtual ~DownloadFileRequest();
+
+  DISALLOW_COPY_AND_ASSIGN(DownloadFileRequest);
+};
 
 }  // namespace drive
 }  // namespace google_apis
diff --git a/chrome/browser/google_apis/drive_api_requests_unittest.cc b/chrome/browser/google_apis/drive_api_requests_unittest.cc
index ce6de2b..903e2df 100644
--- a/chrome/browser/google_apis/drive_api_requests_unittest.cc
+++ b/chrome/browser/google_apis/drive_api_requests_unittest.cc
@@ -3,9 +3,10 @@
 // found in the LICENSE file.
 
 #include "base/bind.h"
+#include "base/file_util.h"
 #include "base/files/file_path.h"
 #include "base/files/scoped_temp_dir.h"
-#include "base/message_loop/message_loop_proxy.h"
+#include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/google_apis/auth_service.h"
@@ -13,7 +14,6 @@
 #include "chrome/browser/google_apis/drive_api_requests.h"
 #include "chrome/browser/google_apis/drive_api_url_generator.h"
 #include "chrome/browser/google_apis/request_sender.h"
-#include "chrome/browser/google_apis/task_util.h"
 #include "chrome/browser/google_apis/test_util.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/browser/browser_thread.h"
@@ -42,6 +42,7 @@
 
 const char kTestUploadExistingFilePath[] = "/upload/existingfile/path";
 const char kTestUploadNewFilePath[] = "/upload/newfile/path";
+const char kTestDownloadPathPrefix[] = "/download/";
 
 }  // namespace
 
@@ -85,9 +86,13 @@
     test_server_.RegisterRequestHandler(
         base::Bind(&DriveApiRequestsTest::HandleContentResponse,
                    base::Unretained(this)));
+    test_server_.RegisterRequestHandler(
+        base::Bind(&DriveApiRequestsTest::HandleDownloadRequest,
+                   base::Unretained(this)));
 
+    GURL test_base_url = test_util::GetBaseUrlForTesting(test_server_.port());
     url_generator_.reset(new DriveApiUrlGenerator(
-        test_util::GetBaseUrlForTesting(test_server_.port())));
+        test_base_url, test_base_url.Resolve(kTestDownloadPathPrefix)));
 
     // Reset the server's expected behavior just in case.
     ResetExpectedResponse();
@@ -95,12 +100,6 @@
     content_length_ = 0;
   }
 
-  virtual void TearDown() OVERRIDE {
-    EXPECT_TRUE(test_server_.ShutdownAndWaitUntilComplete());
-    request_context_getter_ = NULL;
-    ResetExpectedResponse();
-  }
-
   content::TestBrowserThreadBundle thread_bundle_;
   net::test_server::EmbeddedTestServer test_server_;
   scoped_ptr<TestingProfile> profile_;
@@ -151,7 +150,7 @@
     // Return the response with just "204 No Content" status code.
     scoped_ptr<net::test_server::BasicHttpResponse> http_response(
         new net::test_server::BasicHttpResponse);
-    http_response->set_code(net::test_server::NO_CONTENT);
+    http_response->set_code(net::HTTP_NO_CONTENT);
     return http_response.PassAs<net::test_server::HttpResponse>();
   }
 
@@ -199,7 +198,7 @@
     if (found != request.headers.end() &&
         found->second != "*" &&
         found->second != kTestETag) {
-      response->set_code(net::test_server::PRECONDITION);
+      response->set_code(net::HTTP_PRECONDITION_FAILED);
       return response.PassAs<net::test_server::HttpResponse>();
     }
 
@@ -212,7 +211,7 @@
     }
     received_bytes_ = 0;
 
-    response->set_code(net::test_server::SUCCESS);
+    response->set_code(net::HTTP_OK);
     response->AddCustomHeader(
         "Location",
         test_server_.base_url().Resolve(expected_upload_path_).spec());
@@ -257,7 +256,7 @@
       scoped_ptr<net::test_server::BasicHttpResponse> response(
           new net::test_server::BasicHttpResponse);
       // Set RESUME INCOMPLETE (308) status code.
-      response->set_code(net::test_server::RESUME_INCOMPLETE);
+      response->set_code(static_cast<net::HttpStatusCode>(308));
 
       // Add Range header to the response, based on the values of
       // Content-Range header in the request.
@@ -274,11 +273,11 @@
     // (dummy) metadata.
     scoped_ptr<net::test_server::BasicHttpResponse> response =
         test_util::CreateHttpResponseFromFile(
-            test_util::GetTestFilePath("chromeos/drive/file_entry.json"));
+            test_util::GetTestFilePath("drive/file_entry.json"));
 
     // The response code is CREATED if it is new file uploading.
     if (http_request_.relative_url == kTestUploadNewFilePath) {
-      response->set_code(net::test_server::CREATED);
+      response->set_code(net::HTTP_CREATED);
     }
 
     return response.PassAs<net::test_server::HttpResponse>();
@@ -299,12 +298,34 @@
 
     scoped_ptr<net::test_server::BasicHttpResponse> response(
         new net::test_server::BasicHttpResponse);
-    response->set_code(net::test_server::SUCCESS);
+    response->set_code(net::HTTP_OK);
     response->set_content_type(expected_content_type_);
     response->set_content(expected_content_);
     return response.PassAs<net::test_server::HttpResponse>();
   }
 
+  // Handles a request for downloading a file.
+  scoped_ptr<net::test_server::HttpResponse> HandleDownloadRequest(
+      const net::test_server::HttpRequest& request) {
+    http_request_ = request;
+
+    const GURL absolute_url = test_server_.GetURL(request.relative_url);
+    std::string id;
+    if (!test_util::RemovePrefix(absolute_url.path(),
+                                 kTestDownloadPathPrefix,
+                                 &id)) {
+      return scoped_ptr<net::test_server::HttpResponse>();
+    }
+
+    // For testing, returns a text with |id| repeated 3 times.
+    scoped_ptr<net::test_server::BasicHttpResponse> response(
+        new net::test_server::BasicHttpResponse);
+    response->set_code(net::HTTP_OK);
+    response->set_content(id + id + id);
+    response->set_content_type("text/plain");
+    return response.PassAs<net::test_server::HttpResponse>();
+  }
+
   // These are for the current upload file status.
   int64 received_bytes_;
   int64 content_length_;
@@ -313,20 +334,22 @@
 TEST_F(DriveApiRequestsTest, GetAboutRequest_ValidJson) {
   // Set an expected data file containing valid result.
   expected_data_file_path_ = test_util::GetTestFilePath(
-      "chromeos/drive/about.json");
+      "drive/about.json");
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
   scoped_ptr<AboutResource> about_resource;
 
-  GetAboutRequest* request = new GetAboutRequest(
-      request_sender_.get(),
-      request_context_getter_.get(),
-      *url_generator_,
-      CreateComposedCallback(
-          base::Bind(&test_util::RunAndQuit),
-          test_util::CreateCopyResultCallback(&error, &about_resource)));
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    GetAboutRequest* request = new GetAboutRequest(
+        request_sender_.get(),
+        *url_generator_,
+        test_util::CreateQuitCallback(
+            &run_loop,
+            test_util::CreateCopyResultCallback(&error, &about_resource)));
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method);
@@ -334,7 +357,7 @@
 
   scoped_ptr<AboutResource> expected(
       AboutResource::CreateFrom(
-          *test_util::LoadJSONFile("chromeos/drive/about.json")));
+          *test_util::LoadJSONFile("drive/about.json")));
   ASSERT_TRUE(about_resource.get());
   EXPECT_EQ(expected->largest_change_id(), about_resource->largest_change_id());
   EXPECT_EQ(expected->quota_bytes_total(), about_resource->quota_bytes_total());
@@ -345,20 +368,22 @@
 TEST_F(DriveApiRequestsTest, GetAboutRequest_InvalidJson) {
   // Set an expected data file containing invalid result.
   expected_data_file_path_ = test_util::GetTestFilePath(
-      "chromeos/gdata/testfile.txt");
+      "gdata/testfile.txt");
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
   scoped_ptr<AboutResource> about_resource;
 
-  GetAboutRequest* request = new GetAboutRequest(
-      request_sender_.get(),
-      request_context_getter_.get(),
-      *url_generator_,
-      CreateComposedCallback(
-          base::Bind(&test_util::RunAndQuit),
-          test_util::CreateCopyResultCallback(&error, &about_resource)));
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    GetAboutRequest* request = new GetAboutRequest(
+        request_sender_.get(),
+        *url_generator_,
+        test_util::CreateQuitCallback(
+            &run_loop,
+            test_util::CreateCopyResultCallback(&error, &about_resource)));
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   // "parse error" should be returned, and the about resource should be NULL.
   EXPECT_EQ(GDATA_PARSE_ERROR, error);
@@ -370,20 +395,22 @@
 TEST_F(DriveApiRequestsTest, GetApplistRequest) {
   // Set an expected data file containing valid result.
   expected_data_file_path_ = test_util::GetTestFilePath(
-      "chromeos/drive/applist.json");
+      "drive/applist.json");
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
   scoped_ptr<base::Value> result;
 
-  GetApplistRequest* request = new GetApplistRequest(
-      request_sender_.get(),
-      request_context_getter_.get(),
-      *url_generator_,
-      CreateComposedCallback(
-          base::Bind(&test_util::RunAndQuit),
-          test_util::CreateCopyResultCallback(&error, &result)));
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    GetApplistRequest* request = new GetApplistRequest(
+        request_sender_.get(),
+        *url_generator_,
+        test_util::CreateQuitCallback(
+            &run_loop,
+            test_util::CreateCopyResultCallback(&error, &result)));
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method);
@@ -394,23 +421,25 @@
 TEST_F(DriveApiRequestsTest, GetChangelistRequest) {
   // Set an expected data file containing valid result.
   expected_data_file_path_ = test_util::GetTestFilePath(
-      "chromeos/drive/changelist.json");
+      "drive/changelist.json");
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
   scoped_ptr<base::Value> result;
 
-  GetChangelistRequest* request = new GetChangelistRequest(
-      request_sender_.get(),
-      request_context_getter_.get(),
-      *url_generator_,
-      true,  // include deleted
-      100,  // start changestamp
-      500,  // max results
-      CreateComposedCallback(
-          base::Bind(&test_util::RunAndQuit),
-          test_util::CreateCopyResultCallback(&error, &result)));
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    GetChangelistRequest* request = new GetChangelistRequest(
+        request_sender_.get(),
+        *url_generator_,
+        true,  // include deleted
+        100,  // start changestamp
+        500,  // max results
+        test_util::CreateQuitCallback(
+            &run_loop,
+            test_util::CreateCopyResultCallback(&error, &result)));
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method);
@@ -422,22 +451,24 @@
 TEST_F(DriveApiRequestsTest, GetFilelistRequest) {
   // Set an expected data file containing valid result.
   expected_data_file_path_ = test_util::GetTestFilePath(
-      "chromeos/drive/filelist.json");
+      "drive/filelist.json");
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
   scoped_ptr<base::Value> result;
 
-  GetFilelistRequest* request = new GetFilelistRequest(
-      request_sender_.get(),
-      request_context_getter_.get(),
-      *url_generator_,
-      "\"abcde\" in parents",
-      50,  // max results
-      CreateComposedCallback(
-          base::Bind(&test_util::RunAndQuit),
-          test_util::CreateCopyResultCallback(&error, &result)));
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    GetFilelistRequest* request = new GetFilelistRequest(
+        request_sender_.get(),
+        *url_generator_,
+        "\"abcde\" in parents",
+        50,  // max results
+        test_util::CreateQuitCallback(
+            &run_loop,
+            test_util::CreateCopyResultCallback(&error, &result)));
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method);
@@ -449,21 +480,23 @@
 TEST_F(DriveApiRequestsTest, ContinueGetFileListRequest) {
   // Set an expected data file containing valid result.
   expected_data_file_path_ = test_util::GetTestFilePath(
-      "chromeos/drive/filelist.json");
+      "drive/filelist.json");
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
   scoped_ptr<base::Value> result;
 
-  drive::ContinueGetFileListRequest* request =
-      new drive::ContinueGetFileListRequest(
-          request_sender_.get(),
-          request_context_getter_.get(),
-          test_server_.GetURL("/continue/get/file/list"),
-          CreateComposedCallback(
-              base::Bind(&test_util::RunAndQuit),
-              test_util::CreateCopyResultCallback(&error, &result)));
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    drive::ContinueGetFileListRequest* request =
+        new drive::ContinueGetFileListRequest(
+            request_sender_.get(),
+            test_server_.GetURL("/continue/get/file/list"),
+            test_util::CreateQuitCallback(
+                &run_loop,
+                test_util::CreateCopyResultCallback(&error, &result)));
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method);
@@ -474,24 +507,26 @@
 TEST_F(DriveApiRequestsTest, CreateDirectoryRequest) {
   // Set an expected data file containing the directory's entry data.
   expected_data_file_path_ =
-      test_util::GetTestFilePath("chromeos/drive/directory_entry.json");
+      test_util::GetTestFilePath("drive/directory_entry.json");
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
   scoped_ptr<FileResource> file_resource;
 
   // Create "new directory" in the root directory.
-  drive::CreateDirectoryRequest* request =
-      new drive::CreateDirectoryRequest(
-          request_sender_.get(),
-          request_context_getter_.get(),
-          *url_generator_,
-          "root",
-          "new directory",
-          CreateComposedCallback(
-              base::Bind(&test_util::RunAndQuit),
-              test_util::CreateCopyResultCallback(&error, &file_resource)));
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    drive::CreateDirectoryRequest* request =
+        new drive::CreateDirectoryRequest(
+            request_sender_.get(),
+            *url_generator_,
+            "root",
+            "new directory",
+            test_util::CreateQuitCallback(
+                &run_loop,
+                test_util::CreateCopyResultCallback(&error, &file_resource)));
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   EXPECT_EQ(net::test_server::METHOD_POST, http_request_.method);
@@ -502,7 +537,7 @@
 
   scoped_ptr<FileResource> expected(
       FileResource::CreateFrom(
-          *test_util::LoadJSONFile("chromeos/drive/directory_entry.json")));
+          *test_util::LoadJSONFile("drive/directory_entry.json")));
 
   // Sanity check.
   ASSERT_TRUE(file_resource.get());
@@ -517,23 +552,25 @@
   // Set an expected data file containing the directory's entry data.
   // It'd be returned if we rename a directory.
   expected_data_file_path_ =
-      test_util::GetTestFilePath("chromeos/drive/directory_entry.json");
+      test_util::GetTestFilePath("drive/directory_entry.json");
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
 
   // Create "new directory" in the root directory.
-  drive::RenameResourceRequest* request =
-      new drive::RenameResourceRequest(
-          request_sender_.get(),
-          request_context_getter_.get(),
-          *url_generator_,
-          "resource_id",
-          "new name",
-          CreateComposedCallback(
-              base::Bind(&test_util::RunAndQuit),
-              test_util::CreateCopyResultCallback(&error)));
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    drive::RenameResourceRequest* request =
+        new drive::RenameResourceRequest(
+            request_sender_.get(),
+            *url_generator_,
+            "resource_id",
+            "new name",
+            test_util::CreateQuitCallback(
+                &run_loop,
+                test_util::CreateCopyResultCallback(&error)));
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   EXPECT_EQ(net::test_server::METHOD_PATCH, http_request_.method);
@@ -548,7 +585,7 @@
   // Set an expected data file containing the directory's entry data.
   // It'd be returned if we rename a directory.
   expected_data_file_path_ =
-      test_util::GetTestFilePath("chromeos/drive/directory_entry.json");
+      test_util::GetTestFilePath("drive/directory_entry.json");
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
   scoped_ptr<FileResource> file_resource;
@@ -557,18 +594,20 @@
       {2013, 7, 0, 19, 15, 59, 13, 123};
 
   // Touch a file with |resource_id|.
-  drive::TouchResourceRequest* request = new drive::TouchResourceRequest(
-      request_sender_.get(),
-      request_context_getter_.get(),
-      *url_generator_,
-      "resource_id",
-      base::Time::FromUTCExploded(kModifiedDate),
-      base::Time::FromUTCExploded(kLastViewedByMeDate),
-      CreateComposedCallback(
-          base::Bind(&test_util::RunAndQuit),
-          test_util::CreateCopyResultCallback(&error, &file_resource)));
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    drive::TouchResourceRequest* request = new drive::TouchResourceRequest(
+        request_sender_.get(),
+        *url_generator_,
+        "resource_id",
+        base::Time::FromUTCExploded(kModifiedDate),
+        base::Time::FromUTCExploded(kLastViewedByMeDate),
+        test_util::CreateQuitCallback(
+            &run_loop,
+            test_util::CreateCopyResultCallback(&error, &file_resource)));
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   EXPECT_EQ(net::test_server::METHOD_PATCH, http_request_.method);
@@ -587,25 +626,27 @@
   // Set an expected data file containing the dummy file entry data.
   // It'd be returned if we copy a file.
   expected_data_file_path_ =
-      test_util::GetTestFilePath("chromeos/drive/file_entry.json");
+      test_util::GetTestFilePath("drive/file_entry.json");
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
   scoped_ptr<FileResource> file_resource;
 
   // Copy the file to a new file named "new name".
-  drive::CopyResourceRequest* request =
-      new drive::CopyResourceRequest(
-          request_sender_.get(),
-          request_context_getter_.get(),
-          *url_generator_,
-          "resource_id",
-          "parent_resource_id",
-          "new name",
-          CreateComposedCallback(
-              base::Bind(&test_util::RunAndQuit),
-              test_util::CreateCopyResultCallback(&error, &file_resource)));
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    drive::CopyResourceRequest* request =
+        new drive::CopyResourceRequest(
+            request_sender_.get(),
+            *url_generator_,
+            "resource_id",
+            "parent_resource_id",
+            "new name",
+            test_util::CreateQuitCallback(
+                &run_loop,
+                test_util::CreateCopyResultCallback(&error, &file_resource)));
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   EXPECT_EQ(net::test_server::METHOD_POST, http_request_.method);
@@ -623,25 +664,27 @@
   // Set an expected data file containing the dummy file entry data.
   // It'd be returned if we copy a file.
   expected_data_file_path_ =
-      test_util::GetTestFilePath("chromeos/drive/file_entry.json");
+      test_util::GetTestFilePath("drive/file_entry.json");
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
   scoped_ptr<FileResource> file_resource;
 
   // Copy the file to a new file named "new name".
-  drive::CopyResourceRequest* request =
-      new drive::CopyResourceRequest(
-          request_sender_.get(),
-          request_context_getter_.get(),
-          *url_generator_,
-          "resource_id",
-          std::string(),  // parent resource id.
-          "new name",
-          CreateComposedCallback(
-              base::Bind(&test_util::RunAndQuit),
-              test_util::CreateCopyResultCallback(&error, &file_resource)));
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    drive::CopyResourceRequest* request =
+        new drive::CopyResourceRequest(
+            request_sender_.get(),
+            *url_generator_,
+            "resource_id",
+            std::string(),  // parent resource id.
+            "new name",
+            test_util::CreateQuitCallback(
+                &run_loop,
+                test_util::CreateCopyResultCallback(&error, &file_resource)));
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   EXPECT_EQ(net::test_server::METHOD_POST, http_request_.method);
@@ -657,22 +700,24 @@
   // Set data for the expected result. Directory entry should be returned
   // if the trashing entry is a directory, so using it here should be fine.
   expected_data_file_path_ =
-      test_util::GetTestFilePath("chromeos/drive/directory_entry.json");
+      test_util::GetTestFilePath("drive/directory_entry.json");
 
   GDataErrorCode error = GDATA_OTHER_ERROR;
 
   // Trash a resource with the given resource id.
-  drive::TrashResourceRequest* request =
-      new drive::TrashResourceRequest(
-          request_sender_.get(),
-          request_context_getter_.get(),
-          *url_generator_,
-          "resource_id",
-          CreateComposedCallback(
-              base::Bind(&test_util::RunAndQuit),
-              test_util::CreateCopyResultCallback(&error)));
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    drive::TrashResourceRequest* request =
+        new drive::TrashResourceRequest(
+            request_sender_.get(),
+            *url_generator_,
+            "resource_id",
+            test_util::CreateQuitCallback(
+                &run_loop,
+                test_util::CreateCopyResultCallback(&error)));
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   EXPECT_EQ(net::test_server::METHOD_POST, http_request_.method);
@@ -690,18 +735,20 @@
 
   // Add a resource with "resource_id" to a directory with
   // "parent_resource_id".
-  drive::InsertResourceRequest* request =
-      new drive::InsertResourceRequest(
-          request_sender_.get(),
-          request_context_getter_.get(),
-          *url_generator_,
-          "parent_resource_id",
-          "resource_id",
-          CreateComposedCallback(
-              base::Bind(&test_util::RunAndQuit),
-              test_util::CreateCopyResultCallback(&error)));
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    drive::InsertResourceRequest* request =
+        new drive::InsertResourceRequest(
+            request_sender_.get(),
+            *url_generator_,
+            "parent_resource_id",
+            "resource_id",
+            test_util::CreateQuitCallback(
+                &run_loop,
+                test_util::CreateCopyResultCallback(&error)));
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   EXPECT_EQ(net::test_server::METHOD_POST, http_request_.method);
@@ -718,18 +765,20 @@
 
   // Remove a resource with "resource_id" from a directory with
   // "parent_resource_id".
-  drive::DeleteResourceRequest* request =
-      new drive::DeleteResourceRequest(
-          request_sender_.get(),
-          request_context_getter_.get(),
-          *url_generator_,
-          "parent_resource_id",
-          "resource_id",
-          CreateComposedCallback(
-              base::Bind(&test_util::RunAndQuit),
-              test_util::CreateCopyResultCallback(&error)));
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    drive::DeleteResourceRequest* request =
+        new drive::DeleteResourceRequest(
+            request_sender_.get(),
+            *url_generator_,
+            "parent_resource_id",
+            "resource_id",
+            test_util::CreateQuitCallback(
+                &run_loop,
+                test_util::CreateCopyResultCallback(&error)));
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_NO_CONTENT, error);
   EXPECT_EQ(net::test_server::METHOD_DELETE, http_request_.method);
@@ -753,21 +802,22 @@
 
   // Initiate uploading a new file to the directory with
   // "parent_resource_id".
-  drive::InitiateUploadNewFileRequest* request =
-      new drive::InitiateUploadNewFileRequest(
-          request_sender_.get(),
-          request_context_getter_.get(),
-          *url_generator_,
-          base::FilePath(FILE_PATH_LITERAL("drive/file/path")),
-          kTestContentType,
-          kTestContent.size(),
-          "parent_resource_id",  // The resource id of the parent directory.
-          "new file title",  // The title of the file being uploaded.
-          CreateComposedCallback(
-              base::Bind(&test_util::RunAndQuit),
-              test_util::CreateCopyResultCallback(&error, &upload_url)));
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    drive::InitiateUploadNewFileRequest* request =
+        new drive::InitiateUploadNewFileRequest(
+            request_sender_.get(),
+            *url_generator_,
+            kTestContentType,
+            kTestContent.size(),
+            "parent_resource_id",  // The resource id of the parent directory.
+            "new file title",  // The title of the file being uploaded.
+            test_util::CreateQuitCallback(
+                &run_loop,
+                test_util::CreateCopyResultCallback(&error, &upload_url)));
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   EXPECT_EQ(kTestUploadNewFilePath, upload_url.path());
@@ -791,23 +841,24 @@
   UploadRangeResponse response;
   scoped_ptr<FileResource> new_entry;
 
-  drive::ResumeUploadRequest* resume_request =
-      new drive::ResumeUploadRequest(
-          request_sender_.get(),
-          request_context_getter_.get(),
-          base::FilePath(FILE_PATH_LITERAL("drive/file/path")),
-          upload_url,
-          0,  // start_position
-          kTestContent.size(),  // end_position (exclusive)
-          kTestContent.size(),  // content_length,
-          kTestContentType,
-          kTestFilePath,
-          CreateComposedCallback(
-              base::Bind(&test_util::RunAndQuit),
-              test_util::CreateCopyResultCallback(&response, &new_entry)),
-          ProgressCallback());
-  request_sender_->StartRequestWithRetry(resume_request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    drive::ResumeUploadRequest* resume_request =
+        new drive::ResumeUploadRequest(
+            request_sender_.get(),
+            upload_url,
+            0,  // start_position
+            kTestContent.size(),  // end_position (exclusive)
+            kTestContent.size(),  // content_length,
+            kTestContentType,
+            kTestFilePath,
+            test_util::CreateQuitCallback(
+                &run_loop,
+                test_util::CreateCopyResultCallback(&response, &new_entry)),
+            ProgressCallback());
+    request_sender_->StartRequestWithRetry(resume_request);
+    run_loop.Run();
+  }
 
   // METHOD_PUT should be used to upload data.
   EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method);
@@ -843,21 +894,22 @@
   GURL upload_url;
 
   // Initiate uploading a new file to the directory with "parent_resource_id".
-  drive::InitiateUploadNewFileRequest* request =
-      new drive::InitiateUploadNewFileRequest(
-          request_sender_.get(),
-          request_context_getter_.get(),
-          *url_generator_,
-          base::FilePath(FILE_PATH_LITERAL("drive/file/path")),
-          kTestContentType,
-          0,
-          "parent_resource_id",  // The resource id of the parent directory.
-          "new file title",  // The title of the file being uploaded.
-          CreateComposedCallback(
-              base::Bind(&test_util::RunAndQuit),
-              test_util::CreateCopyResultCallback(&error, &upload_url)));
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    drive::InitiateUploadNewFileRequest* request =
+        new drive::InitiateUploadNewFileRequest(
+            request_sender_.get(),
+            *url_generator_,
+            kTestContentType,
+            0,
+            "parent_resource_id",  // The resource id of the parent directory.
+            "new file title",  // The title of the file being uploaded.
+            test_util::CreateQuitCallback(
+                &run_loop,
+                test_util::CreateCopyResultCallback(&error, &upload_url)));
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   EXPECT_EQ(kTestUploadNewFilePath, upload_url.path());
@@ -880,23 +932,24 @@
   UploadRangeResponse response;
   scoped_ptr<FileResource> new_entry;
 
-  drive::ResumeUploadRequest* resume_request =
-      new drive::ResumeUploadRequest(
-          request_sender_.get(),
-          request_context_getter_.get(),
-          base::FilePath(FILE_PATH_LITERAL("drive/file/path")),
-          upload_url,
-          0,  // start_position
-          0,  // end_position (exclusive)
-          0,  // content_length,
-          kTestContentType,
-          kTestFilePath,
-          CreateComposedCallback(
-              base::Bind(&test_util::RunAndQuit),
-              test_util::CreateCopyResultCallback(&response, &new_entry)),
-          ProgressCallback());
-  request_sender_->StartRequestWithRetry(resume_request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    drive::ResumeUploadRequest* resume_request =
+        new drive::ResumeUploadRequest(
+            request_sender_.get(),
+            upload_url,
+            0,  // start_position
+            0,  // end_position (exclusive)
+            0,  // content_length,
+            kTestContentType,
+            kTestFilePath,
+            test_util::CreateQuitCallback(
+                &run_loop,
+                test_util::CreateCopyResultCallback(&response, &new_entry)),
+            ProgressCallback());
+    request_sender_->StartRequestWithRetry(resume_request);
+    run_loop.Run();
+  }
 
   // METHOD_PUT should be used to upload data.
   EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method);
@@ -915,9 +968,6 @@
   EXPECT_EQ(-1, response.end_position_received);
 }
 
-// TODO(kinaba): crbug.com/{241241,164098} Re-enable the test.
-#define NO_GET_UPLOAD_STATUS_TEST
-
 TEST_F(DriveApiRequestsTest, UploadNewLargeFileRequest) {
   // Set an expected url for uploading.
   expected_upload_path_ = kTestUploadNewFilePath;
@@ -933,21 +983,22 @@
   GURL upload_url;
 
   // Initiate uploading a new file to the directory with "parent_resource_id".
-  drive::InitiateUploadNewFileRequest* request =
-      new drive::InitiateUploadNewFileRequest(
-          request_sender_.get(),
-          request_context_getter_.get(),
-          *url_generator_,
-          base::FilePath(FILE_PATH_LITERAL("drive/file/path")),
-          kTestContentType,
-          kTestContent.size(),
-          "parent_resource_id",  // The resource id of the parent directory.
-          "new file title",  // The title of the file being uploaded.
-          CreateComposedCallback(
-              base::Bind(&test_util::RunAndQuit),
-              test_util::CreateCopyResultCallback(&error, &upload_url)));
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    drive::InitiateUploadNewFileRequest* request =
+        new drive::InitiateUploadNewFileRequest(
+            request_sender_.get(),
+            *url_generator_,
+            kTestContentType,
+            kTestContent.size(),
+            "parent_resource_id",  // The resource id of the parent directory.
+            "new file title",  // The title of the file being uploaded.
+            test_util::CreateQuitCallback(
+                &run_loop,
+                test_util::CreateCopyResultCallback(&error, &upload_url)));
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   EXPECT_EQ(kTestUploadNewFilePath, upload_url.path());
@@ -967,7 +1018,6 @@
             "\"title\":\"new file title\"}",
             http_request_.content);
 
-#if !defined(NO_GET_UPLOAD_STATUS_TEST)
   // Before sending any data, check the current status.
   // This is an edge case test for GetUploadStatusRequest.
   {
@@ -975,18 +1025,19 @@
     scoped_ptr<FileResource> new_entry;
 
     // Check the response by GetUploadStatusRequest.
-    drive::GetUploadStatusRequest* get_upload_status_request =
-        new drive::GetUploadStatusRequest(
-            request_sender_.get(),
-            request_context_getter_.get(),
-            base::FilePath(FILE_PATH_LITERAL("drive/file/path")),
-            upload_url,
-            kTestContent.size(),
-            CreateComposedCallback(
-                base::Bind(&test_util::RunAndQuit),
-                test_util::CreateCopyResultCallback(&response, &new_entry)));
-    request_sender_->StartRequestWithRetry(get_upload_status_request);
-    base::MessageLoop::current()->Run();
+    {
+      base::RunLoop run_loop;
+      drive::GetUploadStatusRequest* get_upload_status_request =
+          new drive::GetUploadStatusRequest(
+              request_sender_.get(),
+              upload_url,
+              kTestContent.size(),
+              test_util::CreateQuitCallback(
+                  &run_loop,
+                  test_util::CreateCopyResultCallback(&response, &new_entry)));
+      request_sender_->StartRequestWithRetry(get_upload_status_request);
+      run_loop.Run();
+    }
 
     // METHOD_PUT should be used to upload data.
     EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method);
@@ -1003,7 +1054,6 @@
     EXPECT_EQ(0, response.start_position_received);
     EXPECT_EQ(0, response.end_position_received);
   }
-#endif  // NO_GET_UPLOAD_STATUS_TEST
 
   // Upload the content to the upload URL.
   for (size_t start_position = 0; start_position < kTestContent.size();
@@ -1016,23 +1066,24 @@
     UploadRangeResponse response;
     scoped_ptr<FileResource> new_entry;
 
-    drive::ResumeUploadRequest* resume_request =
-        new drive::ResumeUploadRequest(
-            request_sender_.get(),
-            request_context_getter_.get(),
-            base::FilePath(FILE_PATH_LITERAL("drive/file/path")),
-            upload_url,
-            start_position,
-            end_position,
-            kTestContent.size(),  // content_length,
-            kTestContentType,
-            kTestFilePath,
-            CreateComposedCallback(
-                base::Bind(&test_util::RunAndQuit),
-                test_util::CreateCopyResultCallback(&response, &new_entry)),
-            ProgressCallback());
-    request_sender_->StartRequestWithRetry(resume_request);
-    base::MessageLoop::current()->Run();
+    {
+      base::RunLoop run_loop;
+      drive::ResumeUploadRequest* resume_request =
+          new drive::ResumeUploadRequest(
+              request_sender_.get(),
+              upload_url,
+              start_position,
+              end_position,
+              kTestContent.size(),  // content_length,
+              kTestContentType,
+              kTestFilePath,
+              test_util::CreateQuitCallback(
+                  &run_loop,
+                  test_util::CreateCopyResultCallback(&response, &new_entry)),
+              ProgressCallback());
+      request_sender_->StartRequestWithRetry(resume_request);
+      run_loop.Run();
+    }
 
     // METHOD_PUT should be used to upload data.
     EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method);
@@ -1063,20 +1114,20 @@
     EXPECT_EQ(0, response.start_position_received);
     EXPECT_EQ(static_cast<int64>(end_position), response.end_position_received);
 
-#if !defined(NO_GET_UPLOAD_STATUS_TEST)
     // Check the response by GetUploadStatusRequest.
-    drive::GetUploadStatusRequest* get_upload_status_request =
-        new drive::GetUploadStatusRequest(
-            request_sender_.get(),
-            request_context_getter_.get(),
-            base::FilePath(FILE_PATH_LITERAL("drive/file/path")),
-            upload_url,
-            kTestContent.size(),
-            CreateComposedCallback(
-                base::Bind(&test_util::RunAndQuit),
-                test_util::CreateCopyResultCallback(&response, &new_entry)));
-    request_sender_->StartRequestWithRetry(get_upload_status_request);
-    base::MessageLoop::current()->Run();
+    {
+      base::RunLoop run_loop;
+      drive::GetUploadStatusRequest* get_upload_status_request =
+          new drive::GetUploadStatusRequest(
+              request_sender_.get(),
+              upload_url,
+              kTestContent.size(),
+              test_util::CreateQuitCallback(
+                  &run_loop,
+                  test_util::CreateCopyResultCallback(&response, &new_entry)));
+      request_sender_->StartRequestWithRetry(get_upload_status_request);
+      run_loop.Run();
+    }
 
     // METHOD_PUT should be used to upload data.
     EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method);
@@ -1093,7 +1144,6 @@
     EXPECT_EQ(0, response.start_position_received);
     EXPECT_EQ(static_cast<int64>(end_position),
               response.end_position_received);
-#endif  // NO_GET_UPLOAD_STATUS_TEST
   }
 }
 
@@ -1111,21 +1161,22 @@
   GURL upload_url;
 
   // Initiate uploading a new file to the directory with "parent_resource_id".
-  drive::InitiateUploadExistingFileRequest* request =
-      new drive::InitiateUploadExistingFileRequest(
-          request_sender_.get(),
-          request_context_getter_.get(),
-          *url_generator_,
-          base::FilePath(FILE_PATH_LITERAL("drive/file/path")),
-          kTestContentType,
-          kTestContent.size(),
-          "resource_id",  // The resource id of the file to be overwritten.
-          std::string(),  // No etag.
-          CreateComposedCallback(
-              base::Bind(&test_util::RunAndQuit),
-              test_util::CreateCopyResultCallback(&error, &upload_url)));
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    drive::InitiateUploadExistingFileRequest* request =
+        new drive::InitiateUploadExistingFileRequest(
+            request_sender_.get(),
+            *url_generator_,
+            kTestContentType,
+            kTestContent.size(),
+            "resource_id",  // The resource id of the file to be overwritten.
+            std::string(),  // No etag.
+            test_util::CreateQuitCallback(
+                &run_loop,
+                test_util::CreateCopyResultCallback(&error, &upload_url)));
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   EXPECT_EQ(kTestUploadExistingFilePath, upload_url.path());
@@ -1144,23 +1195,24 @@
   UploadRangeResponse response;
   scoped_ptr<FileResource> new_entry;
 
-  drive::ResumeUploadRequest* resume_request =
-      new drive::ResumeUploadRequest(
-          request_sender_.get(),
-          request_context_getter_.get(),
-          base::FilePath(FILE_PATH_LITERAL("drive/file/path")),
-          upload_url,
-          0,  // start_position
-          kTestContent.size(),  // end_position (exclusive)
-          kTestContent.size(),  // content_length,
-          kTestContentType,
-          kTestFilePath,
-          CreateComposedCallback(
-              base::Bind(&test_util::RunAndQuit),
-              test_util::CreateCopyResultCallback(&response, &new_entry)),
-          ProgressCallback());
-  request_sender_->StartRequestWithRetry(resume_request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    drive::ResumeUploadRequest* resume_request =
+        new drive::ResumeUploadRequest(
+            request_sender_.get(),
+            upload_url,
+            0,  // start_position
+            kTestContent.size(),  // end_position (exclusive)
+            kTestContent.size(),  // content_length,
+            kTestContentType,
+            kTestFilePath,
+            test_util::CreateQuitCallback(
+                &run_loop,
+                test_util::CreateCopyResultCallback(&response, &new_entry)),
+            ProgressCallback());
+    request_sender_->StartRequestWithRetry(resume_request);
+    run_loop.Run();
+  }
 
   // METHOD_PUT should be used to upload data.
   EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method);
@@ -1196,21 +1248,22 @@
   GURL upload_url;
 
   // Initiate uploading a new file to the directory with "parent_resource_id".
-  drive::InitiateUploadExistingFileRequest* request =
-      new drive::InitiateUploadExistingFileRequest(
-          request_sender_.get(),
-          request_context_getter_.get(),
-          *url_generator_,
-          base::FilePath(FILE_PATH_LITERAL("drive/file/path")),
-          kTestContentType,
-          kTestContent.size(),
-          "resource_id",  // The resource id of the file to be overwritten.
-          kTestETag,
-          CreateComposedCallback(
-              base::Bind(&test_util::RunAndQuit),
-              test_util::CreateCopyResultCallback(&error, &upload_url)));
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    drive::InitiateUploadExistingFileRequest* request =
+        new drive::InitiateUploadExistingFileRequest(
+            request_sender_.get(),
+            *url_generator_,
+            kTestContentType,
+            kTestContent.size(),
+            "resource_id",  // The resource id of the file to be overwritten.
+            kTestETag,
+            test_util::CreateQuitCallback(
+                &run_loop,
+                test_util::CreateCopyResultCallback(&error, &upload_url)));
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_SUCCESS, error);
   EXPECT_EQ(kTestUploadExistingFilePath, upload_url.path());
@@ -1229,23 +1282,24 @@
   UploadRangeResponse response;
   scoped_ptr<FileResource> new_entry;
 
-  drive::ResumeUploadRequest* resume_request =
-      new drive::ResumeUploadRequest(
-          request_sender_.get(),
-          request_context_getter_.get(),
-          base::FilePath(FILE_PATH_LITERAL("drive/file/path")),
-          upload_url,
-          0,  // start_position
-          kTestContent.size(),  // end_position (exclusive)
-          kTestContent.size(),  // content_length,
-          kTestContentType,
-          kTestFilePath,
-          CreateComposedCallback(
-              base::Bind(&test_util::RunAndQuit),
-              test_util::CreateCopyResultCallback(&response, &new_entry)),
-          ProgressCallback());
-  request_sender_->StartRequestWithRetry(resume_request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    drive::ResumeUploadRequest* resume_request =
+        new drive::ResumeUploadRequest(
+            request_sender_.get(),
+            upload_url,
+            0,  // start_position
+            kTestContent.size(),  // end_position (exclusive)
+            kTestContent.size(),  // content_length,
+            kTestContentType,
+            kTestFilePath,
+            test_util::CreateQuitCallback(
+                &run_loop,
+                test_util::CreateCopyResultCallback(&response, &new_entry)),
+            ProgressCallback());
+    request_sender_->StartRequestWithRetry(resume_request);
+    run_loop.Run();
+  }
 
   // METHOD_PUT should be used to upload data.
   EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method);
@@ -1278,21 +1332,22 @@
   GURL upload_url;
 
   // Initiate uploading a new file to the directory with "parent_resource_id".
-  drive::InitiateUploadExistingFileRequest* request =
-      new drive::InitiateUploadExistingFileRequest(
-          request_sender_.get(),
-          request_context_getter_.get(),
-          *url_generator_,
-          base::FilePath(FILE_PATH_LITERAL("drive/file/path")),
-          kTestContentType,
-          kTestContent.size(),
-          "resource_id",  // The resource id of the file to be overwritten.
-          "Conflicting-etag",
-          CreateComposedCallback(
-              base::Bind(&test_util::RunAndQuit),
-              test_util::CreateCopyResultCallback(&error, &upload_url)));
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    drive::InitiateUploadExistingFileRequest* request =
+        new drive::InitiateUploadExistingFileRequest(
+            request_sender_.get(),
+            *url_generator_,
+            kTestContentType,
+            kTestContent.size(),
+            "resource_id",  // The resource id of the file to be overwritten.
+            "Conflicting-etag",
+            test_util::CreateQuitCallback(
+                &run_loop,
+                test_util::CreateCopyResultCallback(&error, &upload_url)));
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_PRECONDITION, error);
   EXPECT_EQ(kTestContentType, http_request_.headers["X-Upload-Content-Type"]);
@@ -1307,4 +1362,40 @@
   EXPECT_TRUE(http_request_.content.empty());
 }
 
+TEST_F(DriveApiRequestsTest, DownloadFileRequest) {
+  const base::FilePath kDownloadedFilePath =
+      temp_dir_.path().AppendASCII("cache_file");
+  const std::string kTestId("dummyId");
+
+  GDataErrorCode result_code = GDATA_OTHER_ERROR;
+  base::FilePath temp_file;
+  {
+    base::RunLoop run_loop;
+    drive::DownloadFileRequest* request = new drive::DownloadFileRequest(
+        request_sender_.get(),
+        *url_generator_,
+        kTestId,
+        kDownloadedFilePath,
+        test_util::CreateQuitCallback(
+            &run_loop,
+            test_util::CreateCopyResultCallback(&result_code, &temp_file)),
+        GetContentCallback(),
+        ProgressCallback());
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
+
+  std::string contents;
+  file_util::ReadFileToString(temp_file, &contents);
+  base::Delete(temp_file, false);
+
+  EXPECT_EQ(HTTP_SUCCESS, result_code);
+  EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method);
+  EXPECT_EQ(kTestDownloadPathPrefix + kTestId, http_request_.relative_url);
+  EXPECT_EQ(kDownloadedFilePath, temp_file);
+
+  const std::string expected_contents = kTestId + kTestId + kTestId;
+  EXPECT_EQ(expected_contents, contents);
+}
+
 }  // namespace google_apis
diff --git a/chrome/browser/google_apis/drive_api_url_generator.cc b/chrome/browser/google_apis/drive_api_url_generator.cc
index 1de3704..53a6200 100644
--- a/chrome/browser/google_apis/drive_api_url_generator.cc
+++ b/chrome/browser/google_apis/drive_api_url_generator.cc
@@ -41,8 +41,10 @@
 
 }  // namespace
 
-DriveApiUrlGenerator::DriveApiUrlGenerator(const GURL& base_url)
-    : base_url_(base_url) {
+DriveApiUrlGenerator::DriveApiUrlGenerator(const GURL& base_url,
+                                           const GURL& base_download_url)
+    : base_url_(base_url),
+      base_download_url_(base_download_url) {
   // Do nothing.
 }
 
@@ -52,6 +54,8 @@
 
 const char DriveApiUrlGenerator::kBaseUrlForProduction[] =
     "https://www.googleapis.com";
+const char DriveApiUrlGenerator::kBaseDownloadUrlForProduction[] =
+    "https://www.googledrive.com/host/";
 
 GURL DriveApiUrlGenerator::GetAboutUrl() const {
   return base_url_.Resolve(kDriveV2AboutUrl);
@@ -153,4 +157,9 @@
   return AddResumableUploadParam(url);
 }
 
+GURL DriveApiUrlGenerator::GenerateDownloadFileUrl(
+    const std::string& resource_id) const {
+  return base_download_url_.Resolve(net::EscapePath(resource_id));
+}
+
 }  // namespace google_apis
diff --git a/chrome/browser/google_apis/drive_api_url_generator.h b/chrome/browser/google_apis/drive_api_url_generator.h
index 84f35f4..f121969 100644
--- a/chrome/browser/google_apis/drive_api_url_generator.h
+++ b/chrome/browser/google_apis/drive_api_url_generator.h
@@ -7,7 +7,7 @@
 
 #include <string>
 
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 namespace google_apis {
 
@@ -17,12 +17,15 @@
  public:
   // |base_url| is the path to the target drive api server.
   // Note that this is an injecting point for a testing server.
-  explicit DriveApiUrlGenerator(const GURL& base_url);
+  DriveApiUrlGenerator(const GURL& base_url, const GURL& base_download_url);
   ~DriveApiUrlGenerator();
 
   // The base URL for communicating with the production drive api server.
   static const char kBaseUrlForProduction[];
 
+  // The base URL for the file download server for production.
+  static const char kBaseDownloadUrlForProduction[];
+
   // Returns a URL to fetch "about" data.
   GURL GetAboutUrl() const;
 
@@ -86,8 +89,12 @@
   // |resource_id|.
   GURL GetInitiateUploadExistingFileUrl(const std::string& resource_id) const;
 
+  // Generates a URL for downloading a file.
+  GURL GenerateDownloadFileUrl(const std::string& resource_id) const;
+
  private:
   const GURL base_url_;
+  const GURL base_download_url_;
 
   // This class is copyable hence no DISALLOW_COPY_AND_ASSIGN here.
 };
diff --git a/chrome/browser/google_apis/drive_api_url_generator_unittest.cc b/chrome/browser/google_apis/drive_api_url_generator_unittest.cc
index 6729105..cb6212d 100644
--- a/chrome/browser/google_apis/drive_api_url_generator_unittest.cc
+++ b/chrome/browser/google_apis/drive_api_url_generator_unittest.cc
@@ -5,16 +5,20 @@
 #include "chrome/browser/google_apis/drive_api_url_generator.h"
 
 #include "chrome/browser/google_apis/test_util.h"
-#include "googleurl/src/gurl.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 namespace google_apis {
 
 class DriveApiUrlGeneratorTest : public testing::Test {
  public:
   DriveApiUrlGeneratorTest()
-      : url_generator_(GURL(DriveApiUrlGenerator::kBaseUrlForProduction)),
-        test_url_generator_(test_util::GetBaseUrlForTesting(12345)) {
+      : url_generator_(
+            GURL(DriveApiUrlGenerator::kBaseUrlForProduction),
+            GURL(DriveApiUrlGenerator::kBaseDownloadUrlForProduction)),
+        test_url_generator_(
+            test_util::GetBaseUrlForTesting(12345),
+            test_util::GetBaseUrlForTesting(12345).Resolve("download/")) {
   }
 
  protected:
@@ -256,4 +260,16 @@
           "file:file_id").spec());
 }
 
+TEST_F(DriveApiUrlGeneratorTest, GenerateDownloadFileUrl) {
+  EXPECT_EQ(
+      "https://www.googledrive.com/host/resourceId",
+      url_generator_.GenerateDownloadFileUrl("resourceId").spec());
+  EXPECT_EQ(
+      "https://www.googledrive.com/host/file%3AresourceId",
+      url_generator_.GenerateDownloadFileUrl("file:resourceId").spec());
+  EXPECT_EQ(
+      "http://127.0.0.1:12345/download/resourceId",
+      test_url_generator_.GenerateDownloadFileUrl("resourceId").spec());
+}
+
 }  // namespace google_apis
diff --git a/chrome/browser/google_apis/drive_api_util.cc b/chrome/browser/google_apis/drive_api_util.cc
deleted file mode 100644
index 7f96bf6..0000000
--- a/chrome/browser/google_apis/drive_api_util.cc
+++ /dev/null
@@ -1,138 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/google_apis/drive_api_util.h"
-
-#include <string>
-
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "base/strings/string16.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/google_apis/drive_switches.h"
-#include "googleurl/src/gurl.h"
-#include "net/base/escape.h"
-#include "third_party/re2/re2/re2.h"
-
-namespace google_apis {
-namespace util {
-
-bool IsDriveV2ApiEnabled() {
-  const CommandLine* command_line = CommandLine::ForCurrentProcess();
-
-  // Disable Drive API v2 by default.
-  if (!command_line->HasSwitch(switches::kEnableDriveV2Api))
-    return false;
-
-  std::string value =
-      command_line->GetSwitchValueASCII(switches::kEnableDriveV2Api);
-  StringToLowerASCII(&value);
-  // The value must be "" or "true" for true, or "false" for false.
-  DCHECK(value.empty() || value == "true" || value == "false");
-  return value != "false";
-}
-
-}  // namespace util
-
-namespace drive {
-namespace util {
-
-std::string EscapeQueryStringValue(const std::string& str) {
-  std::string result;
-  result.reserve(str.size());
-  for (size_t i = 0; i < str.size(); ++i) {
-    if (str[i] == '\\' || str[i] == '\'') {
-      result.push_back('\\');
-    }
-    result.push_back(str[i]);
-  }
-  return result;
-}
-
-std::string TranslateQuery(const std::string& original_query) {
-  // In order to handle non-ascii white spaces correctly, convert to UTF16.
-  base::string16 query = UTF8ToUTF16(original_query);
-  const base::string16 kDelimiter(
-      kWhitespaceUTF16 + base::string16(1, static_cast<char16>('"')));
-
-  std::string result;
-  for (size_t index = query.find_first_not_of(kWhitespaceUTF16);
-       index != base::string16::npos;
-       index = query.find_first_not_of(kWhitespaceUTF16, index)) {
-    bool is_exclusion = (query[index] == '-');
-    if (is_exclusion)
-      ++index;
-    if (index == query.length()) {
-      // Here, the token is '-' and it should be ignored.
-      continue;
-    }
-
-    size_t begin_token = index;
-    base::string16 token;
-    if (query[begin_token] == '"') {
-      // Quoted query.
-      ++begin_token;
-      size_t end_token = query.find('"', begin_token);
-      if (end_token == base::string16::npos) {
-        // This is kind of syntax error, since quoted string isn't finished.
-        // However, the query is built by user manually, so here we treat
-        // whole remaining string as a token as a fallback, by appending
-        // a missing double-quote character.
-        end_token = query.length();
-        query.push_back('"');
-      }
-
-      token = query.substr(begin_token, end_token - begin_token);
-      index = end_token + 1;  // Consume last '"', too.
-    } else {
-      size_t end_token = query.find_first_of(kDelimiter, begin_token);
-      if (end_token == base::string16::npos) {
-        end_token = query.length();
-      }
-
-      token = query.substr(begin_token, end_token - begin_token);
-      index = end_token;
-    }
-
-    if (token.empty()) {
-      // Just ignore an empty token.
-      continue;
-    }
-
-    if (!result.empty()) {
-      // If there are two or more tokens, need to connect with "and".
-      result.append(" and ");
-    }
-
-    // The meaning of "fullText" should include title, description and content.
-    base::StringAppendF(
-        &result,
-        "%sfullText contains \'%s\'",
-        is_exclusion ? "not " : "",
-        EscapeQueryStringValue(UTF16ToUTF8(token)).c_str());
-  }
-
-  return result;
-}
-
-std::string ExtractResourceIdFromUrl(const GURL& url) {
-  return net::UnescapeURLComponent(url.ExtractFileName(),
-                                   net::UnescapeRule::URL_SPECIAL_CHARS);
-}
-
-std::string CanonicalizeResourceId(const std::string& resource_id) {
-  // If resource ID is in the old WAPI format starting with a prefix like
-  // "document:", strip it and return the remaining part.
-  std::string stripped_resource_id;
-  if (RE2::FullMatch(resource_id, "^[a-z-]+(?::|%3A)([\\w-]+)$",
-                     &stripped_resource_id))
-    return stripped_resource_id;
-  return resource_id;
-}
-
-}  // namespace util
-}  // namespace drive
-}  // namespace google_apis
diff --git a/chrome/browser/google_apis/drive_api_util.h b/chrome/browser/google_apis/drive_api_util.h
deleted file mode 100644
index e0f9c05..0000000
--- a/chrome/browser/google_apis/drive_api_util.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GOOGLE_APIS_DRIVE_API_UTIL_H_
-#define CHROME_BROWSER_GOOGLE_APIS_DRIVE_API_UTIL_H_
-
-#include <string>
-
-class GURL;
-
-namespace google_apis {
-namespace util {
-
-// Returns true if Drive v2 API is enabled via commandline switch.
-bool IsDriveV2ApiEnabled();
-
-}  // namespace util
-
-namespace drive {
-namespace util {
-
-// Escapes ' to \' in the |str|. This is designed to use for string value of
-// search parameter on Drive API v2.
-// See also: https://developers.google.com/drive/search-parameters
-std::string EscapeQueryStringValue(const std::string& str);
-
-// Parses the query, and builds a search query for Drive API v2.
-// This only supports:
-//   Regular query (e.g. dog => fullText contains 'dog')
-//   Conjunctions
-//     (e.g. dog cat => fullText contains 'dog' and fullText contains 'cat')
-//   Exclusion query (e.g. -cat => not fullText contains 'cat').
-//   Quoted query (e.g. "dog cat" => fullText contains 'dog cat').
-// See also: https://developers.google.com/drive/search-parameters
-std::string TranslateQuery(const std::string& original_query);
-
-// Extracts resource_id out of edit url.
-std::string ExtractResourceIdFromUrl(const GURL& url);
-
-// If |resource_id| is in the old resource ID format used by WAPI, converts it
-// into the new format.
-std::string CanonicalizeResourceId(const std::string& resource_id);
-
-}  // namespace util
-}  // namespace drive
-}  // namespace google_apis
-
-#endif  // CHROME_BROWSER_GOOGLE_APIS_DRIVE_API_UTIL_H_
diff --git a/chrome/browser/google_apis/drive_api_util_unittest.cc b/chrome/browser/google_apis/drive_api_util_unittest.cc
deleted file mode 100644
index a301362..0000000
--- a/chrome/browser/google_apis/drive_api_util_unittest.cc
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/google_apis/drive_api_util.h"
-
-#include "googleurl/src/gurl.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace google_apis {
-namespace drive {
-namespace util {
-
-TEST(DriveApiUtilTest, EscapeQueryStringValue) {
-  EXPECT_EQ("abcde", EscapeQueryStringValue("abcde"));
-  EXPECT_EQ("\\'", EscapeQueryStringValue("'"));
-  EXPECT_EQ("\\'abcde\\'", EscapeQueryStringValue("'abcde'"));
-  EXPECT_EQ("\\\\", EscapeQueryStringValue("\\"));
-  EXPECT_EQ("\\\\\\'", EscapeQueryStringValue("\\'"));
-}
-
-TEST(DriveApiUtilTest, TranslateQuery) {
-  EXPECT_EQ("", TranslateQuery(""));
-  EXPECT_EQ("fullText contains 'dog'", TranslateQuery("dog"));
-  EXPECT_EQ("fullText contains 'dog' and fullText contains 'cat'",
-            TranslateQuery("dog cat"));
-  EXPECT_EQ("not fullText contains 'cat'", TranslateQuery("-cat"));
-  EXPECT_EQ("fullText contains 'dog cat'", TranslateQuery("\"dog cat\""));
-
-  // Should handles full-width white space correctly.
-  // Note: \xE3\x80\x80 (\u3000) is Ideographic Space (a.k.a. Japanese
-  //   full-width whitespace).
-  EXPECT_EQ("fullText contains 'dog' and fullText contains 'cat'",
-            TranslateQuery("dog" "\xE3\x80\x80" "cat"));
-
-  // If the quoted token is not closed (i.e. the last '"' is missing),
-  // we handle the remaining string is one token, as a fallback.
-  EXPECT_EQ("fullText contains 'dog cat'", TranslateQuery("\"dog cat"));
-
-  // For quoted text with leading '-'.
-  EXPECT_EQ("not fullText contains 'dog cat'", TranslateQuery("-\"dog cat\""));
-
-  // Empty tokens should be simply ignored.
-  EXPECT_EQ("", TranslateQuery("-"));
-  EXPECT_EQ("", TranslateQuery("\"\""));
-  EXPECT_EQ("", TranslateQuery("-\"\""));
-  EXPECT_EQ("", TranslateQuery("\"\"\"\""));
-  EXPECT_EQ("", TranslateQuery("\"\" \"\""));
-  EXPECT_EQ("fullText contains 'dog'", TranslateQuery("\"\" dog \"\""));
-}
-
-TEST(FileSystemUtilTest, ExtractResourceIdFromUrl) {
-  EXPECT_EQ("file:2_file_resource_id", ExtractResourceIdFromUrl(
-      GURL("https://file1_link_self/file:2_file_resource_id")));
-  // %3A should be unescaped.
-  EXPECT_EQ("file:2_file_resource_id", ExtractResourceIdFromUrl(
-      GURL("https://file1_link_self/file%3A2_file_resource_id")));
-
-  // The resource ID cannot be extracted, hence empty.
-  EXPECT_EQ("", ExtractResourceIdFromUrl(GURL("https://www.example.com/")));
-}
-
-TEST(FileSystemUtilTest, CanonicalizeResourceId) {
-  std::string resource_id("1YsCnrMxxgp7LDdtlFDt-WdtEIth89vA9inrILtvK-Ug");
-
-  // New style ID is unchanged.
-  EXPECT_EQ(resource_id, CanonicalizeResourceId(resource_id));
-
-  // Drop prefixes from old style IDs.
-  EXPECT_EQ(resource_id, CanonicalizeResourceId("document:" + resource_id));
-  EXPECT_EQ(resource_id, CanonicalizeResourceId("spreadsheet:" + resource_id));
-  EXPECT_EQ(resource_id, CanonicalizeResourceId("presentation:" + resource_id));
-  EXPECT_EQ(resource_id, CanonicalizeResourceId("drawing:" + resource_id));
-  EXPECT_EQ(resource_id, CanonicalizeResourceId("table:" + resource_id));
-  EXPECT_EQ(resource_id, CanonicalizeResourceId("externalapp:" + resource_id));
-}
-
-}  // namespace util
-}  // namespace drive
-}  // namespace google_apis
diff --git a/chrome/browser/google_apis/drive_notification_observer.h b/chrome/browser/google_apis/drive_notification_observer.h
deleted file mode 100644
index 5aadf14..0000000
--- a/chrome/browser/google_apis/drive_notification_observer.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GOOGLE_APIS_DRIVE_NOTIFICATION_OBSERVER_H_
-#define CHROME_BROWSER_GOOGLE_APIS_DRIVE_NOTIFICATION_OBSERVER_H_
-
-namespace google_apis {
-
-// Interface for classes which need to know when to check Google Drive for
-// updates.
-class DriveNotificationObserver {
- public:
-  // Called when a notification from Google Drive is received.
-  virtual void OnNotificationReceived() = 0;
-
-  // Called when XMPP-based push notification is enabled or disabled.
-  virtual void OnPushNotificationEnabled(bool enabled) {}
-
- protected:
-  virtual ~DriveNotificationObserver() {}
-};
-
-}  // namespace google_apis
-
-#endif  // CHROME_BROWSER_GOOGLE_APIS_DRIVE_NOTIFICATION_OBSERVER_H_
diff --git a/chrome/browser/google_apis/drive_switches.cc b/chrome/browser/google_apis/drive_switches.cc
deleted file mode 100644
index e90dd19..0000000
--- a/chrome/browser/google_apis/drive_switches.cc
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/google_apis/drive_switches.h"
-
-namespace google_apis {
-namespace switches {
-
-// Enables Drive v2 API instead of Google Documents List API.
-const char kEnableDriveV2Api[] = "enable-drive-v2-api";
-
-}  // namespace switches
-}  // namespace google_apis
diff --git a/chrome/browser/google_apis/drive_switches.h b/chrome/browser/google_apis/drive_switches.h
deleted file mode 100644
index 67f270d..0000000
--- a/chrome/browser/google_apis/drive_switches.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GOOGLE_APIS_DRIVE_SWITCHES_H_
-#define CHROME_BROWSER_GOOGLE_APIS_DRIVE_SWITCHES_H_
-
-namespace google_apis {
-namespace switches {
-
-extern const char kEnableDriveV2Api[];
-
-}  // namespace switches
-}  // namespace google_apis
-
-#endif  // CHROME_BROWSER_GOOGLE_APIS_DRIVE_SWITCHES_H_
diff --git a/chrome/browser/google_apis/event_logger.cc b/chrome/browser/google_apis/event_logger.cc
deleted file mode 100644
index c853b74..0000000
--- a/chrome/browser/google_apis/event_logger.cc
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/google_apis/event_logger.h"
-
-#include "base/strings/stringprintf.h"
-
-namespace google_apis {
-
-EventLogger::Event::Event(int id, const std::string& what)
-    : id(id),
-      when(base::Time::Now()),
-      what(what) {
-}
-
-EventLogger::EventLogger()
-    : history_size_(kDefaultHistorySize),
-      next_event_id_(0) {
-}
-
-EventLogger::~EventLogger() {
-}
-
-void EventLogger::Log(const char* format, ...) {
-  std::string what;
-
-  va_list args;
-  va_start(args, format);
-  base::StringAppendV(&what, format, args);
-  va_end(args);
-
-  base::AutoLock auto_lock(lock_);
-  history_.push_back(Event(next_event_id_, what));
-  ++next_event_id_;
-  if (history_.size() > history_size_)
-    history_.pop_front();
-}
-
-void EventLogger::SetHistorySize(size_t history_size) {
-  base::AutoLock auto_lock(lock_);
-  history_.clear();
-  history_size_ = history_size;
-}
-
-std::vector<EventLogger::Event> EventLogger::GetHistory() {
-  base::AutoLock auto_lock(lock_);
-  std::vector<Event> output;
-  output.assign(history_.begin(), history_.end());
-  return output;
-}
-
-
-}  // namespace google_apis
diff --git a/chrome/browser/google_apis/event_logger.h b/chrome/browser/google_apis/event_logger.h
deleted file mode 100644
index 3828b17..0000000
--- a/chrome/browser/google_apis/event_logger.h
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GOOGLE_APIS_EVENT_LOGGER_H_
-#define CHROME_BROWSER_GOOGLE_APIS_EVENT_LOGGER_H_
-
-#include <stdarg.h>   // va_list
-#include <deque>
-#include <string>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/synchronization/lock.h"
-#include "base/time.h"
-
-namespace google_apis {
-
-// The default history size used by EventLogger.
-const int kDefaultHistorySize = 1000;
-
-// EventLogger is used to collect and expose text messages for diagnosing
-// behaviors of Google APIs stuff. For instance, the collected messages are
-// exposed to chrome:drive-internals.
-class EventLogger {
- public:
-  // Represents a single event log.
-  struct Event {
-    Event(int id, const std::string& what);
-    int id;  // Monotonically increasing ID starting from 0.
-    base::Time when;  // When the event occurred.
-    std::string what;  // What happened.
-  };
-
-  // Creates an event logger that keeps the latest kDefaultHistorySize events.
-  EventLogger();
-  ~EventLogger();
-
-  // Logs a message using printf format.
-  // Can be called from any thread as long as the object is alive.
-  // Note that PRINTF_FORMAT should be (2, 3) instead of (1, 2) as this is a
-  // C++ member function.
-  void Log(const char* format, ...) PRINTF_FORMAT(2, 3);
-
-  // Sets the history size. The existing history is cleared.
-  // Can be called from any thread as long as the object is alive.
-  void SetHistorySize(size_t history_size);
-
-  // Gets the list of latest events (the oldest event comes first).
-  // Can be called from any thread as long as the object is alive.
-  std::vector<Event> GetHistory();
-
- private:
-  std::deque<Event> history_;  // guarded by lock_.
-  size_t history_size_;  // guarded by lock_.
-  int next_event_id_;  // guarded by lock_.
-  base::Lock lock_;
-
-  DISALLOW_COPY_AND_ASSIGN(EventLogger);
-};
-
-}  // namespace google_apis
-
-#endif  // CHROME_BROWSER_GOOGLE_APIS_EVENT_LOGGER_H_
diff --git a/chrome/browser/google_apis/event_logger_unittest.cc b/chrome/browser/google_apis/event_logger_unittest.cc
deleted file mode 100644
index e4c5308..0000000
--- a/chrome/browser/google_apis/event_logger_unittest.cc
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/google_apis/event_logger.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace google_apis {
-
-TEST(EventLoggerTest, BasicLogging) {
-  EventLogger logger;
-  logger.SetHistorySize(3);  // At most 3 events are kept.
-  EXPECT_EQ(0U, logger.GetHistory().size());
-
-  logger.Log("first");
-  logger.Log("%dnd", 2);
-  logger.Log("third");
-
-  // Events are recorded in the chronological order with sequential IDs.
-  std::vector<EventLogger::Event> history = logger.GetHistory();
-  ASSERT_EQ(3U, history.size());
-  EXPECT_EQ(0, history[0].id);
-  EXPECT_EQ("first", history[0].what);
-  EXPECT_EQ(1, history[1].id);
-  EXPECT_EQ("2nd", history[1].what);
-  EXPECT_EQ(2, history[2].id);
-  EXPECT_EQ("third", history[2].what);
-
-  logger.Log("fourth");
-  // It does not log events beyond the specified.
-  history = logger.GetHistory();
-  ASSERT_EQ(3U, history.size());
-  // The oldest events is pushed out.
-  EXPECT_EQ(1, history[0].id);
-  EXPECT_EQ("2nd", history[0].what);
-  EXPECT_EQ(2, history[1].id);
-  EXPECT_EQ("third", history[1].what);
-  EXPECT_EQ(3, history[2].id);
-  EXPECT_EQ("fourth", history[2].what);
-}
-
-}   // namespace google_apis
diff --git a/chrome/browser/google_apis/gdata_contacts_requests.cc b/chrome/browser/google_apis/gdata_contacts_requests.cc
index f864bd2..74c547d 100644
--- a/chrome/browser/google_apis/gdata_contacts_requests.cc
+++ b/chrome/browser/google_apis/gdata_contacts_requests.cc
@@ -5,8 +5,8 @@
 #include "chrome/browser/google_apis/gdata_contacts_requests.h"
 
 #include "chrome/browser/google_apis/time_util.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/url_util.h"
+#include "url/gurl.h"
 
 namespace google_apis {
 
@@ -38,9 +38,8 @@
 
 GetContactGroupsRequest::GetContactGroupsRequest(
     RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
     const GetDataCallback& callback)
-    : GetDataRequest(runner, url_request_context_getter, callback) {
+    : GetDataRequest(runner, callback) {
 }
 
 GetContactGroupsRequest::~GetContactGroupsRequest() {}
@@ -55,11 +54,10 @@
 
 GetContactsRequest::GetContactsRequest(
     RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
     const std::string& group_id,
     const base::Time& min_update_time,
     const GetDataCallback& callback)
-    : GetDataRequest(runner, url_request_context_getter, callback),
+    : GetDataRequest(runner, callback),
       group_id_(group_id),
       min_update_time_(min_update_time) {
 }
@@ -87,10 +85,9 @@
 
 GetContactPhotoRequest::GetContactPhotoRequest(
     RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
     const GURL& photo_url,
     const GetContentCallback& callback)
-    : UrlFetchRequestBase(runner, url_request_context_getter),
+    : UrlFetchRequestBase(runner),
       photo_url_(photo_url),
       callback_(callback) {
 }
diff --git a/chrome/browser/google_apis/gdata_contacts_requests.h b/chrome/browser/google_apis/gdata_contacts_requests.h
index 08fcb06..67861e3 100644
--- a/chrome/browser/google_apis/gdata_contacts_requests.h
+++ b/chrome/browser/google_apis/gdata_contacts_requests.h
@@ -9,10 +9,6 @@
 
 #include "chrome/browser/google_apis/base_requests.h"
 
-namespace net {
-class URLRequestContextGetter;
-}  // namespace net
-
 namespace google_apis {
 
 //========================== GetContactGroupsRequest =========================
@@ -20,10 +16,8 @@
 // This class fetches a JSON feed containing a user's contact groups.
 class GetContactGroupsRequest : public GetDataRequest {
  public:
-  GetContactGroupsRequest(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
-      const GetDataCallback& callback);
+  GetContactGroupsRequest(RequestSender* runner,
+                          const GetDataCallback& callback);
   virtual ~GetContactGroupsRequest();
 
   void set_feed_url_for_testing(const GURL& url) {
@@ -46,12 +40,10 @@
 // This class fetches a JSON feed containing a user's contacts.
 class GetContactsRequest : public GetDataRequest {
  public:
-  GetContactsRequest(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
-      const std::string& group_id,
-      const base::Time& min_update_time,
-      const GetDataCallback& callback);
+  GetContactsRequest(RequestSender* runner,
+                     const std::string& group_id,
+                     const base::Time& min_update_time,
+                     const GetDataCallback& callback);
   virtual ~GetContactsRequest();
 
   void set_feed_url_for_testing(const GURL& url) {
@@ -83,11 +75,9 @@
 // This class fetches a contact's photo.
 class GetContactPhotoRequest : public UrlFetchRequestBase {
  public:
-  GetContactPhotoRequest(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
-      const GURL& photo_url,
-      const GetContentCallback& callback);
+  GetContactPhotoRequest(RequestSender* runner,
+                         const GURL& photo_url,
+                         const GetContentCallback& callback);
   virtual ~GetContactPhotoRequest();
 
  protected:
diff --git a/chrome/browser/google_apis/gdata_wapi_parser.h b/chrome/browser/google_apis/gdata_wapi_parser.h
index 1cf4a30..332e8d6 100644
--- a/chrome/browser/google_apis/gdata_wapi_parser.h
+++ b/chrome/browser/google_apis/gdata_wapi_parser.h
@@ -13,9 +13,9 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/scoped_vector.h"
 #include "base/strings/string_piece.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/google_apis/drive_entry_kinds.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 namespace base {
 class FilePath;
diff --git a/chrome/browser/google_apis/gdata_wapi_parser_unittest.cc b/chrome/browser/google_apis/gdata_wapi_parser_unittest.cc
index 217bdde..f4f564d 100644
--- a/chrome/browser/google_apis/gdata_wapi_parser_unittest.cc
+++ b/chrome/browser/google_apis/gdata_wapi_parser_unittest.cc
@@ -9,7 +9,7 @@
 #include "base/files/file_path.h"
 #include "base/json/json_file_value_serializer.h"
 #include "base/logging.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/google_apis/test_util.h"
 #include "chrome/browser/google_apis/time_util.h"
@@ -23,7 +23,7 @@
 TEST(GDataWAPIParserTest, ResourceListJsonParser) {
   std::string error;
   scoped_ptr<base::Value> document =
-      test_util::LoadJSONFile("chromeos/gdata/basic_feed.json");
+      test_util::LoadJSONFile("gdata/basic_feed.json");
   ASSERT_TRUE(document.get());
   ASSERT_EQ(base::Value::TYPE_DICTIONARY, document->GetType());
   scoped_ptr<ResourceList> feed(ResourceList::ExtractAndParse(*document));
@@ -152,7 +152,7 @@
 TEST(GDataWAPIParserTest, ResourceEntryJsonParser) {
   std::string error;
   scoped_ptr<base::Value> document =
-      test_util::LoadJSONFile("chromeos/gdata/file_entry.json");
+      test_util::LoadJSONFile("gdata/file_entry.json");
   ASSERT_TRUE(document.get());
   ASSERT_EQ(base::Value::TYPE_DICTIONARY, document->GetType());
   scoped_ptr<ResourceEntry> entry(ResourceEntry::ExtractAndParse(*document));
@@ -233,7 +233,7 @@
 
 TEST(GDataWAPIParserTest, AccountMetadataParser) {
   scoped_ptr<base::Value> document =
-      test_util::LoadJSONFile("chromeos/gdata/account_metadata.json");
+      test_util::LoadJSONFile("gdata/account_metadata.json");
   ASSERT_TRUE(document.get());
   base::DictionaryValue* document_dict = NULL;
   base::DictionaryValue* entry_value = NULL;
diff --git a/chrome/browser/google_apis/gdata_wapi_requests.cc b/chrome/browser/google_apis/gdata_wapi_requests.cc
index d479f14..187ee2b 100644
--- a/chrome/browser/google_apis/gdata_wapi_requests.cc
+++ b/chrome/browser/google_apis/gdata_wapi_requests.cc
@@ -25,7 +25,6 @@
 
 namespace {
 
-
 const char kUploadContentRange[] = "Content-Range: bytes ";
 
 const char kFeedField[] = "feed";
@@ -36,7 +35,6 @@
 // Parses the JSON value to ResourceList.
 scoped_ptr<ResourceList> ParseResourceListOnBlockingPool(
     scoped_ptr<base::Value> value) {
-  DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(value);
 
   return ResourceList::ExtractAndParse(*value);
@@ -48,7 +46,6 @@
     const GetResourceListCallback& callback,
     GDataErrorCode error,
     scoped_ptr<ResourceList> resource_list) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(!callback.is_null());
 
   // resource_list being NULL indicates there was a parsing error.
@@ -63,7 +60,6 @@
 void ParseResourceListAndRun(const GetResourceListCallback& callback,
                              GDataErrorCode error,
                              scoped_ptr<base::Value> value) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(!callback.is_null());
 
   if (!value) {
@@ -83,7 +79,6 @@
 void ParseAccounetMetadataAndRun(const GetAccountMetadataCallback& callback,
                                  GDataErrorCode error,
                                  scoped_ptr<base::Value> value) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(!callback.is_null());
 
   if (!value) {
@@ -124,7 +119,6 @@
                          const AuthorizeAppCallback& callback,
                          GDataErrorCode error,
                          scoped_ptr<base::Value> value) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(!callback.is_null());
 
   if (!value) {
@@ -161,15 +155,14 @@
 //============================ GetResourceListRequest ========================
 
 GetResourceListRequest::GetResourceListRequest(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
+    RequestSender* sender,
     const GDataWapiUrlGenerator& url_generator,
     const GURL& override_url,
     int64 start_changestamp,
     const std::string& search_string,
     const std::string& directory_resource_id,
     const GetResourceListCallback& callback)
-    : GetDataRequest(runner, url_request_context_getter,
+    : GetDataRequest(sender,
                      base::Bind(&ParseResourceListAndRun, callback)),
       url_generator_(url_generator),
       override_url_(override_url),
@@ -191,13 +184,12 @@
 //============================ SearchByTitleRequest ==========================
 
 SearchByTitleRequest::SearchByTitleRequest(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
+    RequestSender* sender,
     const GDataWapiUrlGenerator& url_generator,
     const std::string& title,
     const std::string& directory_resource_id,
     const GetResourceListCallback& callback)
-    : GetDataRequest(runner, url_request_context_getter,
+    : GetDataRequest(sender,
                      base::Bind(&ParseResourceListAndRun, callback)),
       url_generator_(url_generator),
       title_(title),
@@ -215,12 +207,11 @@
 //============================ GetResourceEntryRequest =======================
 
 GetResourceEntryRequest::GetResourceEntryRequest(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
+    RequestSender* sender,
     const GDataWapiUrlGenerator& url_generator,
     const std::string& resource_id,
     const GetDataCallback& callback)
-    : GetDataRequest(runner, url_request_context_getter, callback),
+    : GetDataRequest(sender, callback),
       url_generator_(url_generator),
       resource_id_(resource_id) {
   DCHECK(!callback.is_null());
@@ -235,12 +226,11 @@
 //========================= GetAccountMetadataRequest ========================
 
 GetAccountMetadataRequest::GetAccountMetadataRequest(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
+    RequestSender* sender,
     const GDataWapiUrlGenerator& url_generator,
     const GetAccountMetadataCallback& callback,
     bool include_installed_apps)
-    : GetDataRequest(runner, url_request_context_getter,
+    : GetDataRequest(sender,
                      base::Bind(&ParseAccounetMetadataAndRun, callback)),
       url_generator_(url_generator),
       include_installed_apps_(include_installed_apps) {
@@ -256,13 +246,12 @@
 //=========================== DeleteResourceRequest ==========================
 
 DeleteResourceRequest::DeleteResourceRequest(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
+    RequestSender* sender,
     const GDataWapiUrlGenerator& url_generator,
     const EntryActionCallback& callback,
     const std::string& resource_id,
     const std::string& etag)
-    : EntryActionRequest(runner, url_request_context_getter, callback),
+    : EntryActionRequest(sender, callback),
       url_generator_(url_generator),
       resource_id_(resource_id),
       etag_(etag) {
@@ -289,13 +278,12 @@
 //========================== CreateDirectoryRequest ==========================
 
 CreateDirectoryRequest::CreateDirectoryRequest(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
+    RequestSender* sender,
     const GDataWapiUrlGenerator& url_generator,
     const GetDataCallback& callback,
     const std::string& parent_resource_id,
     const std::string& directory_name)
-    : GetDataRequest(runner, url_request_context_getter, callback),
+    : GetDataRequest(sender, callback),
       url_generator_(url_generator),
       parent_resource_id_(parent_resource_id),
       directory_name_(directory_name) {
@@ -341,13 +329,12 @@
 //============================ CopyHostedDocumentRequest =====================
 
 CopyHostedDocumentRequest::CopyHostedDocumentRequest(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
+    RequestSender* sender,
     const GDataWapiUrlGenerator& url_generator,
     const GetDataCallback& callback,
     const std::string& resource_id,
     const std::string& new_name)
-    : GetDataRequest(runner, url_request_context_getter, callback),
+    : GetDataRequest(sender, callback),
       url_generator_(url_generator),
       resource_id_(resource_id),
       new_name_(new_name) {
@@ -387,13 +374,12 @@
 //=========================== RenameResourceRequest ==========================
 
 RenameResourceRequest::RenameResourceRequest(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
+    RequestSender* sender,
     const GDataWapiUrlGenerator& url_generator,
     const EntryActionCallback& callback,
     const std::string& resource_id,
     const std::string& new_name)
-    : EntryActionRequest(runner, url_request_context_getter, callback),
+    : EntryActionRequest(sender, callback),
       url_generator_(url_generator),
       resource_id_(resource_id),
       new_name_(new_name) {
@@ -438,13 +424,12 @@
 //=========================== AuthorizeAppRequest ==========================
 
 AuthorizeAppRequest::AuthorizeAppRequest(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
+    RequestSender* sender,
     const GDataWapiUrlGenerator& url_generator,
     const AuthorizeAppCallback& callback,
     const std::string& resource_id,
     const std::string& app_id)
-    : GetDataRequest(runner, url_request_context_getter,
+    : GetDataRequest(sender,
                      base::Bind(&ParseOpenLinkAndRun, app_id, callback)),
       url_generator_(url_generator),
       resource_id_(resource_id),
@@ -490,13 +475,12 @@
 //======================= AddResourceToDirectoryRequest ======================
 
 AddResourceToDirectoryRequest::AddResourceToDirectoryRequest(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
+    RequestSender* sender,
     const GDataWapiUrlGenerator& url_generator,
     const EntryActionCallback& callback,
     const std::string& parent_resource_id,
     const std::string& resource_id)
-    : EntryActionRequest(runner, url_request_context_getter, callback),
+    : EntryActionRequest(sender, callback),
       url_generator_(url_generator),
       parent_resource_id_(parent_resource_id),
       resource_id_(resource_id) {
@@ -536,13 +520,12 @@
 //==================== RemoveResourceFromDirectoryRequest ====================
 
 RemoveResourceFromDirectoryRequest::RemoveResourceFromDirectoryRequest(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
+    RequestSender* sender,
     const GDataWapiUrlGenerator& url_generator,
     const EntryActionCallback& callback,
     const std::string& parent_resource_id,
     const std::string& document_resource_id)
-    : EntryActionRequest(runner, url_request_context_getter, callback),
+    : EntryActionRequest(sender, callback),
       url_generator_(url_generator),
       resource_id_(document_resource_id),
       parent_resource_id_(parent_resource_id) {
@@ -572,19 +555,15 @@
 //======================= InitiateUploadNewFileRequest =======================
 
 InitiateUploadNewFileRequest::InitiateUploadNewFileRequest(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
+    RequestSender* sender,
     const GDataWapiUrlGenerator& url_generator,
     const InitiateUploadCallback& callback,
-    const base::FilePath& drive_file_path,
     const std::string& content_type,
     int64 content_length,
     const std::string& parent_resource_id,
     const std::string& title)
-    : InitiateUploadRequestBase(runner,
-                                url_request_context_getter,
+    : InitiateUploadRequestBase(sender,
                                 callback,
-                                drive_file_path,
                                 content_type,
                                 content_length),
       url_generator_(url_generator),
@@ -625,19 +604,15 @@
 //===================== InitiateUploadExistingFileRequest ====================
 
 InitiateUploadExistingFileRequest::InitiateUploadExistingFileRequest(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
+    RequestSender* sender,
     const GDataWapiUrlGenerator& url_generator,
     const InitiateUploadCallback& callback,
-    const base::FilePath& drive_file_path,
     const std::string& content_type,
     int64 content_length,
     const std::string& resource_id,
     const std::string& etag)
-    : InitiateUploadRequestBase(runner,
-                                url_request_context_getter,
+    : InitiateUploadRequestBase(sender,
                                 callback,
-                                drive_file_path,
                                 content_type,
                                 content_length),
       url_generator_(url_generator),
@@ -679,20 +654,16 @@
 //============================ ResumeUploadRequest ===========================
 
 ResumeUploadRequest::ResumeUploadRequest(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
+    RequestSender* sender,
     const UploadRangeCallback& callback,
     const ProgressCallback& progress_callback,
-    const base::FilePath& drive_file_path,
     const GURL& upload_location,
     int64 start_position,
     int64 end_position,
     int64 content_length,
     const std::string& content_type,
     const base::FilePath& local_file_path)
-    : ResumeUploadRequestBase(runner,
-                              url_request_context_getter,
-                              drive_file_path,
+    : ResumeUploadRequestBase(sender,
                               upload_location,
                               start_position,
                               end_position,
@@ -720,17 +691,11 @@
 //========================== GetUploadStatusRequest ==========================
 
 GetUploadStatusRequest::GetUploadStatusRequest(
-    RequestSender* runner,
-    net::URLRequestContextGetter* url_request_context_getter,
+    RequestSender* sender,
     const UploadRangeCallback& callback,
-    const base::FilePath& drive_file_path,
     const GURL& upload_url,
     int64 content_length)
-    : GetUploadStatusRequestBase(runner,
-                                 url_request_context_getter,
-                                 drive_file_path,
-                                 upload_url,
-                                 content_length),
+    : GetUploadStatusRequestBase(sender, upload_url, content_length),
       callback_(callback) {
   DCHECK(!callback.is_null());
 }
@@ -742,4 +707,27 @@
   callback_.Run(response, ParseResourceEntry(value.Pass()));
 }
 
+
+//========================== DownloadFileRequest ==========================
+
+DownloadFileRequest::DownloadFileRequest(
+    RequestSender* sender,
+    const GDataWapiUrlGenerator& url_generator,
+    const DownloadActionCallback& download_action_callback,
+    const GetContentCallback& get_content_callback,
+    const ProgressCallback& progress_callback,
+    const std::string& resource_id,
+    const base::FilePath& output_file_path)
+    : DownloadFileRequestBase(
+          sender,
+          download_action_callback,
+          get_content_callback,
+          progress_callback,
+          url_generator.GenerateDownloadFileUrl(resource_id),
+          output_file_path) {
+}
+
+DownloadFileRequest::~DownloadFileRequest() {
+}
+
 }  // namespace google_apis
diff --git a/chrome/browser/google_apis/gdata_wapi_requests.h b/chrome/browser/google_apis/gdata_wapi_requests.h
index 2c9d37c..ba6f774 100644
--- a/chrome/browser/google_apis/gdata_wapi_requests.h
+++ b/chrome/browser/google_apis/gdata_wapi_requests.h
@@ -12,10 +12,6 @@
 #include "chrome/browser/google_apis/drive_common_callbacks.h"
 #include "chrome/browser/google_apis/gdata_wapi_url_generator.h"
 
-namespace net {
-class URLRequestContextGetter;
-}  // namespace net
-
 namespace google_apis {
 
 class AccountMetadata;
@@ -45,15 +41,13 @@
   //
   // callback:
   //   Called once the feed is fetched. Must not be null.
-  GetResourceListRequest(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
-      const GDataWapiUrlGenerator& url_generator,
-      const GURL& override_url,
-      int64 start_changestamp,
-      const std::string& search_string,
-      const std::string& directory_resource_id,
-      const GetResourceListCallback& callback);
+  GetResourceListRequest(RequestSender* sender,
+                         const GDataWapiUrlGenerator& url_generator,
+                         const GURL& override_url,
+                         int64 start_changestamp,
+                         const std::string& search_string,
+                         const std::string& directory_resource_id,
+                         const GetResourceListCallback& callback);
   virtual ~GetResourceListRequest();
 
  protected:
@@ -83,13 +77,11 @@
   //
   // callback:
   //   Called once the feed is fetched. Must not be null.
-  SearchByTitleRequest(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
-      const GDataWapiUrlGenerator& url_generator,
-      const std::string& title,
-      const std::string& directory_resource_id,
-      const GetResourceListCallback& callback);
+  SearchByTitleRequest(RequestSender* sender,
+                       const GDataWapiUrlGenerator& url_generator,
+                       const std::string& title,
+                       const std::string& directory_resource_id,
+                       const GetResourceListCallback& callback);
   virtual ~SearchByTitleRequest();
 
  protected:
@@ -110,12 +102,10 @@
 class GetResourceEntryRequest : public GetDataRequest {
  public:
   // |callback| must not be null.
-  GetResourceEntryRequest(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
-      const GDataWapiUrlGenerator& url_generator,
-      const std::string& resource_id,
-      const GetDataCallback& callback);
+  GetResourceEntryRequest(RequestSender* sender,
+                          const GDataWapiUrlGenerator& url_generator,
+                          const std::string& resource_id,
+                          const GetDataCallback& callback);
   virtual ~GetResourceEntryRequest();
 
  protected:
@@ -143,12 +133,10 @@
   // If |include_installed_apps| is set to true, the result should include
   // the list of installed third party applications.
   // |callback| must not be null.
-  GetAccountMetadataRequest(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
-      const GDataWapiUrlGenerator& url_generator,
-      const GetAccountMetadataCallback& callback,
-      bool include_installed_apps);
+  GetAccountMetadataRequest(RequestSender* sender,
+                            const GDataWapiUrlGenerator& url_generator,
+                            const GetAccountMetadataCallback& callback,
+                            bool include_installed_apps);
   virtual ~GetAccountMetadataRequest();
 
  protected:
@@ -173,13 +161,11 @@
 class DeleteResourceRequest : public EntryActionRequest {
  public:
   // |callback| must not be null.
-  DeleteResourceRequest(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
-      const GDataWapiUrlGenerator& url_generator,
-      const EntryActionCallback& callback,
-      const std::string& resource_id,
-      const std::string& etag);
+  DeleteResourceRequest(RequestSender* sender,
+                        const GDataWapiUrlGenerator& url_generator,
+                        const EntryActionCallback& callback,
+                        const std::string& resource_id,
+                        const std::string& etag);
   virtual ~DeleteResourceRequest();
 
  protected:
@@ -205,13 +191,11 @@
   // |parent_resource_id|. If this parameter is empty, a new directory will
   // be created in the root directory.
   // |callback| must not be null.
-  CreateDirectoryRequest(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
-      const GDataWapiUrlGenerator& url_generator,
-      const GetDataCallback& callback,
-      const std::string& parent_resource_id,
-      const std::string& directory_name);
+  CreateDirectoryRequest(RequestSender* sender,
+                         const GDataWapiUrlGenerator& url_generator,
+                         const GetDataCallback& callback,
+                         const std::string& parent_resource_id,
+                         const std::string& directory_name);
   virtual ~CreateDirectoryRequest();
 
  protected:
@@ -237,13 +221,11 @@
 class CopyHostedDocumentRequest : public GetDataRequest {
  public:
   // |callback| must not be null.
-  CopyHostedDocumentRequest(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
-      const GDataWapiUrlGenerator& url_generator,
-      const GetDataCallback& callback,
-      const std::string& resource_id,
-      const std::string& new_name);
+  CopyHostedDocumentRequest(RequestSender* sender,
+                            const GDataWapiUrlGenerator& url_generator,
+                            const GetDataCallback& callback,
+                            const std::string& resource_id,
+                            const std::string& new_name);
   virtual ~CopyHostedDocumentRequest();
 
  protected:
@@ -267,13 +249,11 @@
 class RenameResourceRequest : public EntryActionRequest {
  public:
   // |callback| must not be null.
-  RenameResourceRequest(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
-      const GDataWapiUrlGenerator& url_generator,
-      const EntryActionCallback& callback,
-      const std::string& resource_id,
-      const std::string& new_name);
+  RenameResourceRequest(RequestSender* sender,
+                        const GDataWapiUrlGenerator& url_generator,
+                        const EntryActionCallback& callback,
+                        const std::string& resource_id,
+                        const std::string& new_name);
   virtual ~RenameResourceRequest();
 
  protected:
@@ -299,13 +279,11 @@
 class AuthorizeAppRequest : public GetDataRequest {
  public:
   // |callback| must not be null.
-  AuthorizeAppRequest(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
-      const GDataWapiUrlGenerator& url_generator,
-      const AuthorizeAppCallback& callback,
-      const std::string& resource_id,
-      const std::string& app_id);
+  AuthorizeAppRequest(RequestSender* sender,
+                      const GDataWapiUrlGenerator& url_generator,
+                      const AuthorizeAppCallback& callback,
+                      const std::string& resource_id,
+                      const std::string& app_id);
   virtual ~AuthorizeAppRequest();
 
  protected:
@@ -331,13 +309,11 @@
 class AddResourceToDirectoryRequest : public EntryActionRequest {
  public:
   // |callback| must not be null.
-  AddResourceToDirectoryRequest(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
-      const GDataWapiUrlGenerator& url_generator,
-      const EntryActionCallback& callback,
-      const std::string& parent_resource_id,
-      const std::string& resource_id);
+  AddResourceToDirectoryRequest(RequestSender* sender,
+                                const GDataWapiUrlGenerator& url_generator,
+                                const EntryActionCallback& callback,
+                                const std::string& parent_resource_id,
+                                const std::string& resource_id);
   virtual ~AddResourceToDirectoryRequest();
 
  protected:
@@ -362,13 +338,11 @@
 class RemoveResourceFromDirectoryRequest : public EntryActionRequest {
  public:
   // |callback| must not be null.
-  RemoveResourceFromDirectoryRequest(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
-      const GDataWapiUrlGenerator& url_generator,
-      const EntryActionCallback& callback,
-      const std::string& parent_resource_id,
-      const std::string& resource_id);
+  RemoveResourceFromDirectoryRequest(RequestSender* sender,
+                                     const GDataWapiUrlGenerator& url_generator,
+                                     const EntryActionCallback& callback,
+                                     const std::string& parent_resource_id,
+                                     const std::string& resource_id);
   virtual ~RemoveResourceFromDirectoryRequest();
 
  protected:
@@ -395,16 +369,13 @@
   //   (resumable-create-media URL)
   // See also the comments of InitiateUploadRequestBase for more details
   // about the other parameters.
-  InitiateUploadNewFileRequest(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
-      const GDataWapiUrlGenerator& url_generator,
-      const InitiateUploadCallback& callback,
-      const base::FilePath& drive_file_path,
-      const std::string& content_type,
-      int64 content_length,
-      const std::string& parent_resource_id,
-      const std::string& title);
+  InitiateUploadNewFileRequest(RequestSender* sender,
+                               const GDataWapiUrlGenerator& url_generator,
+                               const InitiateUploadCallback& callback,
+                               const std::string& content_type,
+                               int64 content_length,
+                               const std::string& parent_resource_id,
+                               const std::string& title);
   virtual ~InitiateUploadNewFileRequest();
 
  protected:
@@ -434,16 +405,13 @@
   // |etag| should be set if it is available to detect the upload confliction.
   // See also the comments of InitiateUploadRequestBase for more details
   // about the other parameters.
-  InitiateUploadExistingFileRequest(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
-      const GDataWapiUrlGenerator& url_generator,
-      const InitiateUploadCallback& callback,
-      const base::FilePath& drive_file_path,
-      const std::string& content_type,
-      int64 content_length,
-      const std::string& resource_id,
-      const std::string& etag);
+  InitiateUploadExistingFileRequest(RequestSender* sender,
+                                    const GDataWapiUrlGenerator& url_generator,
+                                    const InitiateUploadCallback& callback,
+                                    const std::string& content_type,
+                                    int64 content_length,
+                                    const std::string& resource_id,
+                                    const std::string& etag);
   virtual ~InitiateUploadExistingFileRequest();
 
  protected:
@@ -467,20 +435,17 @@
 // Performs the request for resuming the upload of a file.
 class ResumeUploadRequest : public ResumeUploadRequestBase {
  public:
-  // See also ResumeUploadRequestBase's comment for parameters meaining.
+  // See also ResumeUploadRequestBase's comment for parameters meaning.
   // |callback| must not be null.
-  ResumeUploadRequest(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
-      const UploadRangeCallback& callback,
-      const ProgressCallback& progress_callback,
-      const base::FilePath& drive_file_path,
-      const GURL& upload_location,
-      int64 start_position,
-      int64 end_position,
-      int64 content_length,
-      const std::string& content_type,
-      const base::FilePath& local_file_path);
+  ResumeUploadRequest(RequestSender* sender,
+                      const UploadRangeCallback& callback,
+                      const ProgressCallback& progress_callback,
+                      const GURL& upload_location,
+                      int64 start_position,
+                      int64 end_position,
+                      int64 content_length,
+                      const std::string& content_type,
+                      const base::FilePath& local_file_path);
   virtual ~ResumeUploadRequest();
 
  protected:
@@ -506,13 +471,10 @@
  public:
   // See also GetUploadStatusRequestBase's comment for parameters meaning.
   // |callback| must not be null.
-  GetUploadStatusRequest(
-      RequestSender* runner,
-      net::URLRequestContextGetter* url_request_context_getter,
-      const UploadRangeCallback& callback,
-      const base::FilePath& drive_file_path,
-      const GURL& upload_url,
-      int64 content_length);
+  GetUploadStatusRequest(RequestSender* sender,
+                         const UploadRangeCallback& callback,
+                         const GURL& upload_url,
+                         int64 content_length);
   virtual ~GetUploadStatusRequest();
 
  protected:
@@ -527,6 +489,25 @@
   DISALLOW_COPY_AND_ASSIGN(GetUploadStatusRequest);
 };
 
+
+//========================== DownloadFileRequest ==========================
+
+// This class performs the request for downloading of a specified file.
+class DownloadFileRequest : public DownloadFileRequestBase {
+ public:
+  // See also DownloadFileRequestBase's comment for parameters meaning.
+  DownloadFileRequest(RequestSender* sender,
+                      const GDataWapiUrlGenerator& url_generator,
+                      const DownloadActionCallback& download_action_callback,
+                      const GetContentCallback& get_content_callback,
+                      const ProgressCallback& progress_callback,
+                      const std::string& resource_id,
+                      const base::FilePath& output_file_path);
+  virtual ~DownloadFileRequest();
+
+  DISALLOW_COPY_AND_ASSIGN(DownloadFileRequest);
+};
+
 }  // namespace google_apis
 
 #endif  // CHROME_BROWSER_GOOGLE_APIS_GDATA_WAPI_REQUESTS_H_
diff --git a/chrome/browser/google_apis/gdata_wapi_requests_unittest.cc b/chrome/browser/google_apis/gdata_wapi_requests_unittest.cc
index 4406039..39302ac 100644
--- a/chrome/browser/google_apis/gdata_wapi_requests_unittest.cc
+++ b/chrome/browser/google_apis/gdata_wapi_requests_unittest.cc
@@ -6,11 +6,12 @@
 #include <map>
 
 #include "base/bind.h"
+#include "base/file_util.h"
 #include "base/files/file_path.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/json/json_reader.h"
 #include "base/json/json_writer.h"
-#include "base/message_loop/message_loop_proxy.h"
+#include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/values.h"
@@ -19,7 +20,6 @@
 #include "chrome/browser/google_apis/gdata_wapi_requests.h"
 #include "chrome/browser/google_apis/gdata_wapi_url_generator.h"
 #include "chrome/browser/google_apis/request_sender.h"
-#include "chrome/browser/google_apis/task_util.h"
 #include "chrome/browser/google_apis/test_util.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/browser/browser_thread.h"
@@ -38,6 +38,7 @@
 const char kTestGDataAuthToken[] = "testtoken";
 const char kTestUserAgent[] = "test-user-agent";
 const char kTestETag[] = "test_etag";
+const char kTestDownloadPathPrefix[] = "/download/";
 
 class GDataWapiRequestsTest : public testing::Test {
  public:
@@ -80,19 +81,18 @@
     test_server_.RegisterRequestHandler(
         base::Bind(&GDataWapiRequestsTest::HandleUploadRequest,
                    base::Unretained(this)));
+    test_server_.RegisterRequestHandler(
+        base::Bind(&GDataWapiRequestsTest::HandleDownloadRequest,
+                   base::Unretained(this)));
 
+    GURL test_base_url = test_util::GetBaseUrlForTesting(test_server_.port());
     url_generator_.reset(new GDataWapiUrlGenerator(
-        test_util::GetBaseUrlForTesting(test_server_.port())));
+        test_base_url, test_base_url.Resolve(kTestDownloadPathPrefix)));
 
     received_bytes_ = 0;
     content_length_ = 0;
   }
 
-  virtual void TearDown() OVERRIDE {
-    EXPECT_TRUE(test_server_.ShutdownAndWaitUntilComplete());
-    request_context_getter_ = NULL;
-  }
-
  protected:
   // Handles a request for fetching a resource feed.
   scoped_ptr<net::test_server::HttpResponse> HandleResourceFeedRequest(
@@ -108,7 +108,7 @@
       // copied document but for now, just return "file_entry.json"
       scoped_ptr<net::test_server::BasicHttpResponse> result(
           test_util::CreateHttpResponseFromFile(
-              test_util::GetTestFilePath("chromeos/gdata/file_entry.json")));
+              test_util::GetTestFilePath("gdata/file_entry.json")));
       return result.PassAs<net::test_server::HttpResponse>();
     }
 
@@ -122,7 +122,7 @@
       // Process the default feed.
       scoped_ptr<net::test_server::BasicHttpResponse> result(
           test_util::CreateHttpResponseFromFile(
-              test_util::GetTestFilePath("chromeos/gdata/root_feed.json")));
+              test_util::GetTestFilePath("gdata/root_feed.json")));
       return result.PassAs<net::test_server::HttpResponse>();
     } else {
       // Process a feed for a single resource ID.
@@ -131,7 +131,7 @@
       if (resource_id == "file:2_file_resource_id") {
         scoped_ptr<net::test_server::BasicHttpResponse> result(
             test_util::CreateHttpResponseFromFile(
-                test_util::GetTestFilePath("chromeos/gdata/file_entry.json")));
+                test_util::GetTestFilePath("gdata/file_entry.json")));
         return result.PassAs<net::test_server::HttpResponse>();
       } else if (resource_id == "folder:root/contents" &&
                  request.method == net::test_server::METHOD_POST) {
@@ -141,7 +141,7 @@
         scoped_ptr<net::test_server::BasicHttpResponse> result(
             test_util::CreateHttpResponseFromFile(
                 test_util::GetTestFilePath(
-                    "chromeos/gdata/directory_entry.json")));
+                    "gdata/directory_entry.json")));
         return result.PassAs<net::test_server::HttpResponse>();
       } else if (resource_id ==
                  "folder:root/contents/file:2_file_resource_id" &&
@@ -152,7 +152,7 @@
         // matter.
         scoped_ptr<net::test_server::BasicHttpResponse> result(
             test_util::CreateHttpResponseFromFile(
-                test_util::GetTestFilePath("chromeos/gdata/testfile.txt")));
+                test_util::GetTestFilePath("gdata/testfile.txt")));
         return result.PassAs<net::test_server::HttpResponse>();
       } else if (resource_id == "invalid_resource_id") {
         // Check if this is an authorization request for an app.
@@ -161,7 +161,7 @@
             request.content.find("<docs:authorizedApp>") != std::string::npos) {
           scoped_ptr<net::test_server::BasicHttpResponse> result(
               test_util::CreateHttpResponseFromFile(
-                  test_util::GetTestFilePath("chromeos/gdata/testfile.txt")));
+                  test_util::GetTestFilePath("gdata/testfile.txt")));
           return result.PassAs<net::test_server::HttpResponse>();
         }
       }
@@ -182,7 +182,7 @@
     scoped_ptr<net::test_server::BasicHttpResponse> result(
         test_util::CreateHttpResponseFromFile(
             test_util::GetTestFilePath(
-                "chromeos/gdata/account_metadata.json")));
+                "gdata/account_metadata.json")));
     if (absolute_url.query().find("include-installed-apps=true") ==
         string::npos) {
       // Exclude the list of installed apps.
@@ -223,7 +223,7 @@
       if (found != request.headers.end() &&
           found->second != "*" &&
           found->second != kTestETag) {
-        http_response->set_code(net::test_server::PRECONDITION);
+        http_response->set_code(net::HTTP_PRECONDITION_FAILED);
         return http_response.PassAs<net::test_server::HttpResponse>();
       }
 
@@ -236,7 +236,7 @@
       }
       received_bytes_ = 0;
 
-      http_response->set_code(net::test_server::SUCCESS);
+      http_response->set_code(net::HTTP_OK);
       GURL upload_url;
       // POST is used for a new file, and PUT is used for an existing file.
       if (request.method == net::test_server::METHOD_POST) {
@@ -268,11 +268,11 @@
     // file, but for now, just return file_entry.json.
     scoped_ptr<net::test_server::BasicHttpResponse> response =
         test_util::CreateHttpResponseFromFile(
-            test_util::GetTestFilePath("chromeos/gdata/file_entry.json"));
+            test_util::GetTestFilePath("gdata/file_entry.json"));
     // response.code() is set to SUCCESS. Change it to CREATED if it's a new
     // file.
     if (absolute_url.path() == "/upload_new_file")
-      response->set_code(net::test_server::CREATED);
+      response->set_code(net::HTTP_CREATED);
 
     // Check if the Content-Range header is present. This must be present if
     // the request body is not empty.
@@ -307,11 +307,33 @@
 
     // Change the code to RESUME_INCOMPLETE if upload is not complete.
     if (received_bytes_ < content_length_)
-      response->set_code(net::test_server::RESUME_INCOMPLETE);
+      response->set_code(static_cast<net::HttpStatusCode>(308));
 
     return response.PassAs<net::test_server::HttpResponse>();
   }
 
+  // Handles a request for downloading a file.
+  scoped_ptr<net::test_server::HttpResponse> HandleDownloadRequest(
+      const net::test_server::HttpRequest& request) {
+    http_request_ = request;
+
+    const GURL absolute_url = test_server_.GetURL(request.relative_url);
+    std::string id;
+    if (!test_util::RemovePrefix(absolute_url.path(),
+                                 kTestDownloadPathPrefix,
+                                 &id)) {
+      return scoped_ptr<net::test_server::HttpResponse>();
+    }
+
+    // For testing, returns a text with |id| repeated 3 times.
+    scoped_ptr<net::test_server::BasicHttpResponse> response(
+        new net::test_server::BasicHttpResponse);
+    response->set_code(net::HTTP_OK);
+    response->set_content(id + id + id);
+    response->set_content_type("text/plain");
+    return response.PassAs<net::test_server::HttpResponse>();
+  }
+
   content::TestBrowserThreadBundle thread_bundle_;
   net::test_server::EmbeddedTestServer test_server_;
   scoped_ptr<TestingProfile> profile_;
@@ -340,19 +362,21 @@
   GDataErrorCode result_code = GDATA_OTHER_ERROR;
   scoped_ptr<ResourceList> result_data;
 
-  GetResourceListRequest* request = new GetResourceListRequest(
-      request_sender_.get(),
-      request_context_getter_.get(),
-      *url_generator_,
-      GURL(),         // Pass an empty URL to use the default feed
-      0,              // start changestamp
-      std::string(),  // search string
-      std::string(),  // directory resource ID
-      CreateComposedCallback(
-          base::Bind(&test_util::RunAndQuit),
-          test_util::CreateCopyResultCallback(&result_code, &result_data)));
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    GetResourceListRequest* request = new GetResourceListRequest(
+        request_sender_.get(),
+        *url_generator_,
+        GURL(),         // Pass an empty URL to use the default feed
+        0,              // start changestamp
+        std::string(),  // search string
+        std::string(),  // directory resource ID
+        test_util::CreateQuitCallback(
+            &run_loop,
+            test_util::CreateCopyResultCallback(&result_code, &result_data)));
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_SUCCESS, result_code);
   EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method);
@@ -363,7 +387,7 @@
   // Sanity check of the result.
   scoped_ptr<ResourceList> expected(
       ResourceList::ExtractAndParse(
-          *test_util::LoadJSONFile("chromeos/gdata/root_feed.json")));
+          *test_util::LoadJSONFile("gdata/root_feed.json")));
   ASSERT_TRUE(result_data);
   EXPECT_EQ(expected->title(), result_data->title());
 }
@@ -372,29 +396,31 @@
   GDataErrorCode result_code = GDATA_OTHER_ERROR;
   scoped_ptr<ResourceList> result_data;
 
-  GetResourceListRequest* request = new GetResourceListRequest(
-      request_sender_.get(),
-      request_context_getter_.get(),
-      *url_generator_,
-      test_server_.GetURL("/files/chromeos/gdata/root_feed.json"),
-      0,              // start changestamp
-      std::string(),  // search string
-      std::string(),  // directory resource ID
-      CreateComposedCallback(
-          base::Bind(&test_util::RunAndQuit),
-          test_util::CreateCopyResultCallback(&result_code, &result_data)));
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    GetResourceListRequest* request = new GetResourceListRequest(
+        request_sender_.get(),
+        *url_generator_,
+        test_server_.GetURL("/files/gdata/root_feed.json"),
+        0,              // start changestamp
+        std::string(),  // search string
+        std::string(),  // directory resource ID
+        test_util::CreateQuitCallback(
+            &run_loop,
+            test_util::CreateCopyResultCallback(&result_code, &result_data)));
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_SUCCESS, result_code);
   EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method);
-  EXPECT_EQ("/files/chromeos/gdata/root_feed.json?v=3&alt=json&showroot=true&"
+  EXPECT_EQ("/files/gdata/root_feed.json?v=3&alt=json&showroot=true&"
             "showfolders=true&include-shared=true&max-results=500",
             http_request_.relative_url);
 
   scoped_ptr<ResourceList> expected(
       ResourceList::ExtractAndParse(
-          *test_util::LoadJSONFile("chromeos/gdata/root_feed.json")));
+          *test_util::LoadJSONFile("gdata/root_feed.json")));
   ASSERT_TRUE(result_data);
   EXPECT_EQ(expected->title(), result_data->title());
 }
@@ -405,23 +431,25 @@
   GDataErrorCode result_code = GDATA_OTHER_ERROR;
   scoped_ptr<ResourceList> result_data;
 
-  GetResourceListRequest* request = new GetResourceListRequest(
-      request_sender_.get(),
-      request_context_getter_.get(),
-      *url_generator_,
-      test_server_.GetURL("/files/chromeos/gdata/testfile.txt"),
-      0,              // start changestamp
-      std::string(),  // search string
-      std::string(),  // directory resource ID
-      CreateComposedCallback(
-          base::Bind(&test_util::RunAndQuit),
-          test_util::CreateCopyResultCallback(&result_code, &result_data)));
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    GetResourceListRequest* request = new GetResourceListRequest(
+        request_sender_.get(),
+        *url_generator_,
+        test_server_.GetURL("/files/gdata/testfile.txt"),
+        0,              // start changestamp
+        std::string(),  // search string
+        std::string(),  // directory resource ID
+        test_util::CreateQuitCallback(
+            &run_loop,
+            test_util::CreateCopyResultCallback(&result_code, &result_data)));
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(GDATA_PARSE_ERROR, result_code);
   EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method);
-  EXPECT_EQ("/files/chromeos/gdata/testfile.txt?v=3&alt=json&showroot=true&"
+  EXPECT_EQ("/files/gdata/testfile.txt?v=3&alt=json&showroot=true&"
             "showfolders=true&include-shared=true&max-results=500",
             http_request_.relative_url);
   EXPECT_FALSE(result_data);
@@ -431,17 +459,19 @@
   GDataErrorCode result_code = GDATA_OTHER_ERROR;
   scoped_ptr<ResourceList> result_data;
 
-  SearchByTitleRequest* request = new SearchByTitleRequest(
-      request_sender_.get(),
-      request_context_getter_.get(),
-      *url_generator_,
-      "search-title",
-      std::string(),  // directory resource id
-      CreateComposedCallback(
-          base::Bind(&test_util::RunAndQuit),
-          test_util::CreateCopyResultCallback(&result_code, &result_data)));
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    SearchByTitleRequest* request = new SearchByTitleRequest(
+        request_sender_.get(),
+        *url_generator_,
+        "search-title",
+        std::string(),  // directory resource id
+        test_util::CreateQuitCallback(
+            &run_loop,
+            test_util::CreateCopyResultCallback(&result_code, &result_data)));
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_SUCCESS, result_code);
   EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method);
@@ -456,16 +486,18 @@
   GDataErrorCode result_code = GDATA_OTHER_ERROR;
   scoped_ptr<base::Value> result_data;
 
-  GetResourceEntryRequest* request = new GetResourceEntryRequest(
-      request_sender_.get(),
-      request_context_getter_.get(),
-      *url_generator_,
-      "file:2_file_resource_id",  // resource ID
-      CreateComposedCallback(
-          base::Bind(&test_util::RunAndQuit),
-          test_util::CreateCopyResultCallback(&result_code, &result_data)));
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    GetResourceEntryRequest* request = new GetResourceEntryRequest(
+        request_sender_.get(),
+        *url_generator_,
+        "file:2_file_resource_id",  // resource ID
+        test_util::CreateQuitCallback(
+            &run_loop,
+            test_util::CreateCopyResultCallback(&result_code, &result_data)));
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_SUCCESS, result_code);
   EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method);
@@ -473,7 +505,7 @@
             "?v=3&alt=json&showroot=true",
             http_request_.relative_url);
   EXPECT_TRUE(test_util::VerifyJsonData(
-      test_util::GetTestFilePath("chromeos/gdata/file_entry.json"),
+      test_util::GetTestFilePath("gdata/file_entry.json"),
       result_data.get()));
 }
 
@@ -481,16 +513,18 @@
   GDataErrorCode result_code = GDATA_OTHER_ERROR;
   scoped_ptr<base::Value> result_data;
 
-  GetResourceEntryRequest* request = new GetResourceEntryRequest(
-      request_sender_.get(),
-      request_context_getter_.get(),
-      *url_generator_,
-      "<invalid>",  // resource ID
-      CreateComposedCallback(
-          base::Bind(&test_util::RunAndQuit),
-          test_util::CreateCopyResultCallback(&result_code, &result_data)));
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    GetResourceEntryRequest* request = new GetResourceEntryRequest(
+        request_sender_.get(),
+        *url_generator_,
+        "<invalid>",  // resource ID
+        test_util::CreateQuitCallback(
+            &run_loop,
+            test_util::CreateCopyResultCallback(&result_code, &result_data)));
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_NOT_FOUND, result_code);
   EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method);
@@ -504,16 +538,18 @@
   GDataErrorCode result_code = GDATA_OTHER_ERROR;
   scoped_ptr<AccountMetadata> result_data;
 
-  GetAccountMetadataRequest* request = new GetAccountMetadataRequest(
-      request_sender_.get(),
-      request_context_getter_.get(),
-      *url_generator_,
-      CreateComposedCallback(
-          base::Bind(&test_util::RunAndQuit),
-          test_util::CreateCopyResultCallback(&result_code, &result_data)),
-      true);  // Include installed apps.
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    GetAccountMetadataRequest* request = new GetAccountMetadataRequest(
+        request_sender_.get(),
+        *url_generator_,
+        test_util::CreateQuitCallback(
+            &run_loop,
+            test_util::CreateCopyResultCallback(&result_code, &result_data)),
+        true);  // Include installed apps.
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_SUCCESS, result_code);
   EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method);
@@ -523,7 +559,7 @@
 
   scoped_ptr<AccountMetadata> expected(
       AccountMetadata::CreateFrom(
-          *test_util::LoadJSONFile("chromeos/gdata/account_metadata.json")));
+          *test_util::LoadJSONFile("gdata/account_metadata.json")));
 
   ASSERT_TRUE(result_data.get());
   EXPECT_EQ(expected->largest_changestamp(),
@@ -543,16 +579,18 @@
   GDataErrorCode result_code = GDATA_OTHER_ERROR;
   scoped_ptr<AccountMetadata> result_data;
 
-  GetAccountMetadataRequest* request = new GetAccountMetadataRequest(
-      request_sender_.get(),
-      request_context_getter_.get(),
-      *url_generator_,
-      CreateComposedCallback(
-          base::Bind(&test_util::RunAndQuit),
-          test_util::CreateCopyResultCallback(&result_code, &result_data)),
-      false);  // Exclude installed apps.
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    GetAccountMetadataRequest* request = new GetAccountMetadataRequest(
+        request_sender_.get(),
+        *url_generator_,
+        test_util::CreateQuitCallback(
+            &run_loop,
+            test_util::CreateCopyResultCallback(&result_code, &result_data)),
+        false);  // Exclude installed apps.
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_SUCCESS, result_code);
   EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method);
@@ -561,7 +599,7 @@
 
   scoped_ptr<AccountMetadata> expected(
       AccountMetadata::CreateFrom(
-          *test_util::LoadJSONFile("chromeos/gdata/account_metadata.json")));
+          *test_util::LoadJSONFile("gdata/account_metadata.json")));
 
   ASSERT_TRUE(result_data.get());
   EXPECT_EQ(expected->largest_changestamp(),
@@ -578,17 +616,20 @@
 TEST_F(GDataWapiRequestsTest, DeleteResourceRequest) {
   GDataErrorCode result_code = GDATA_OTHER_ERROR;
 
-  DeleteResourceRequest* request = new DeleteResourceRequest(
-      request_sender_.get(),
-      request_context_getter_.get(),
-      *url_generator_,
-      CreateComposedCallback(base::Bind(&test_util::RunAndQuit),
-                             test_util::CreateCopyResultCallback(&result_code)),
-      "file:2_file_resource_id",
-      std::string());
+  {
+    base::RunLoop run_loop;
+    DeleteResourceRequest* request = new DeleteResourceRequest(
+        request_sender_.get(),
+        *url_generator_,
+        test_util::CreateQuitCallback(
+            &run_loop,
+            test_util::CreateCopyResultCallback(&result_code)),
+        "file:2_file_resource_id",
+        std::string());
 
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_SUCCESS, result_code);
   EXPECT_EQ(net::test_server::METHOD_DELETE, http_request_.method);
@@ -602,18 +643,20 @@
 TEST_F(GDataWapiRequestsTest, DeleteResourceRequestWithETag) {
   GDataErrorCode result_code = GDATA_OTHER_ERROR;
 
-  DeleteResourceRequest* request = new DeleteResourceRequest(
-      request_sender_.get(),
-      request_context_getter_.get(),
-      *url_generator_,
-      CreateComposedCallback(
-          base::Bind(&test_util::RunAndQuit),
-          test_util::CreateCopyResultCallback(&result_code)),
-      "file:2_file_resource_id",
-      "etag");
+  {
+    base::RunLoop run_loop;
+    DeleteResourceRequest* request = new DeleteResourceRequest(
+        request_sender_.get(),
+        *url_generator_,
+        test_util::CreateQuitCallback(
+            &run_loop,
+            test_util::CreateCopyResultCallback(&result_code)),
+        "file:2_file_resource_id",
+        "etag");
 
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_SUCCESS, result_code);
   EXPECT_EQ(net::test_server::METHOD_DELETE, http_request_.method);
@@ -629,18 +672,20 @@
   scoped_ptr<base::Value> result_data;
 
   // Create "new directory" in the root directory.
-  CreateDirectoryRequest* request = new CreateDirectoryRequest(
-      request_sender_.get(),
-      request_context_getter_.get(),
-      *url_generator_,
-      CreateComposedCallback(
-          base::Bind(&test_util::RunAndQuit),
-          test_util::CreateCopyResultCallback(&result_code, &result_data)),
-      "folder:root",
-      "new directory");
+  {
+    base::RunLoop run_loop;
+    CreateDirectoryRequest* request = new CreateDirectoryRequest(
+        request_sender_.get(),
+        *url_generator_,
+        test_util::CreateQuitCallback(
+            &run_loop,
+            test_util::CreateCopyResultCallback(&result_code, &result_data)),
+        "folder:root",
+        "new directory");
 
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_SUCCESS, result_code);
   EXPECT_EQ(net::test_server::METHOD_POST, http_request_.method);
@@ -664,18 +709,20 @@
   scoped_ptr<base::Value> result_data;
 
   // Copy a document with a new name "New Document".
-  CopyHostedDocumentRequest* request = new CopyHostedDocumentRequest(
-      request_sender_.get(),
-      request_context_getter_.get(),
-      *url_generator_,
-      CreateComposedCallback(
-          base::Bind(&test_util::RunAndQuit),
-          test_util::CreateCopyResultCallback(&result_code, &result_data)),
-      "document:5_document_resource_id",  // source resource ID
-      "New Document");
+  {
+    base::RunLoop run_loop;
+    CopyHostedDocumentRequest* request = new CopyHostedDocumentRequest(
+        request_sender_.get(),
+        *url_generator_,
+        test_util::CreateQuitCallback(
+            &run_loop,
+            test_util::CreateCopyResultCallback(&result_code, &result_data)),
+        "document:5_document_resource_id",  // source resource ID
+        "New Document");
 
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_SUCCESS, result_code);
   EXPECT_EQ(net::test_server::METHOD_POST, http_request_.method);
@@ -696,18 +743,20 @@
   GDataErrorCode result_code = GDATA_OTHER_ERROR;
 
   // Rename a file with a new name "New File".
-  RenameResourceRequest* request = new RenameResourceRequest(
-      request_sender_.get(),
-      request_context_getter_.get(),
-      *url_generator_,
-      CreateComposedCallback(
-          base::Bind(&test_util::RunAndQuit),
-          test_util::CreateCopyResultCallback(&result_code)),
-      "file:2_file_resource_id",
-      "New File");
+  {
+    base::RunLoop run_loop;
+    RenameResourceRequest* request = new RenameResourceRequest(
+        request_sender_.get(),
+        *url_generator_,
+        test_util::CreateQuitCallback(
+            &run_loop,
+            test_util::CreateCopyResultCallback(&result_code)),
+        "file:2_file_resource_id",
+        "New File");
 
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_SUCCESS, result_code);
   EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method);
@@ -731,18 +780,20 @@
   GURL result_data;
 
   // Authorize an app with APP_ID to access to a document.
-  AuthorizeAppRequest* request = new AuthorizeAppRequest(
-      request_sender_.get(),
-      request_context_getter_.get(),
-      *url_generator_,
-      CreateComposedCallback(
-          base::Bind(&test_util::RunAndQuit),
-          test_util::CreateCopyResultCallback(&result_code, &result_data)),
-      "file:2_file_resource_id",
-      "the_app_id");
+  {
+    base::RunLoop run_loop;
+    AuthorizeAppRequest* request = new AuthorizeAppRequest(
+        request_sender_.get(),
+        *url_generator_,
+        test_util::CreateQuitCallback(
+            &run_loop,
+            test_util::CreateCopyResultCallback(&result_code, &result_data)),
+        "file:2_file_resource_id",
+        "the_app_id");
 
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_SUCCESS, result_code);
   EXPECT_EQ(GURL("https://entry1_open_with_link/"), result_data);
@@ -768,18 +819,20 @@
   GURL result_data;
 
   // Authorize an app with APP_ID to access to a document.
-  AuthorizeAppRequest* request = new AuthorizeAppRequest(
-      request_sender_.get(),
-      request_context_getter_.get(),
-      *url_generator_,
-      CreateComposedCallback(
-          base::Bind(&test_util::RunAndQuit),
-          test_util::CreateCopyResultCallback(&result_code, &result_data)),
-      "file:2_file_resource_id",
-      "unauthorized_app_id");
+  {
+    base::RunLoop run_loop;
+    AuthorizeAppRequest* request = new AuthorizeAppRequest(
+        request_sender_.get(),
+        *url_generator_,
+        test_util::CreateQuitCallback(
+            &run_loop,
+            test_util::CreateCopyResultCallback(&result_code, &result_data)),
+        "file:2_file_resource_id",
+        "unauthorized_app_id");
 
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(GDATA_OTHER_ERROR, result_code);
   EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method);
@@ -803,18 +856,20 @@
   GURL result_data;
 
   // Authorize an app with APP_ID to access to a document but an invalid feed.
-  AuthorizeAppRequest* request = new AuthorizeAppRequest(
-      request_sender_.get(),
-      request_context_getter_.get(),
-      *url_generator_,
-      CreateComposedCallback(
-          base::Bind(&test_util::RunAndQuit),
-          test_util::CreateCopyResultCallback(&result_code, &result_data)),
-      "invalid_resource_id",
-      "APP_ID");
+  {
+    base::RunLoop run_loop;
+    AuthorizeAppRequest* request = new AuthorizeAppRequest(
+        request_sender_.get(),
+        *url_generator_,
+        test_util::CreateQuitCallback(
+            &run_loop,
+            test_util::CreateCopyResultCallback(&result_code, &result_data)),
+        "invalid_resource_id",
+        "APP_ID");
 
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(GDATA_PARSE_ERROR, result_code);
   EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method);
@@ -837,19 +892,21 @@
   GDataErrorCode result_code = GDATA_OTHER_ERROR;
 
   // Add a file to the root directory.
-  AddResourceToDirectoryRequest* request =
-      new AddResourceToDirectoryRequest(
-          request_sender_.get(),
-          request_context_getter_.get(),
-          *url_generator_,
-          CreateComposedCallback(
-              base::Bind(&test_util::RunAndQuit),
-              test_util::CreateCopyResultCallback(&result_code)),
-          "folder:root",
-          "file:2_file_resource_id");
+  {
+    base::RunLoop run_loop;
+    AddResourceToDirectoryRequest* request =
+        new AddResourceToDirectoryRequest(
+            request_sender_.get(),
+            *url_generator_,
+            test_util::CreateQuitCallback(
+                &run_loop,
+                test_util::CreateCopyResultCallback(&result_code)),
+            "folder:root",
+            "file:2_file_resource_id");
 
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_SUCCESS, result_code);
   EXPECT_EQ(net::test_server::METHOD_POST, http_request_.method);
@@ -872,19 +929,21 @@
   GDataErrorCode result_code = GDATA_OTHER_ERROR;
 
   // Remove a file from the root directory.
-  RemoveResourceFromDirectoryRequest* request =
-      new RemoveResourceFromDirectoryRequest(
-          request_sender_.get(),
-          request_context_getter_.get(),
-          *url_generator_,
-          CreateComposedCallback(
-              base::Bind(&test_util::RunAndQuit),
-              test_util::CreateCopyResultCallback(&result_code)),
-          "folder:root",
-          "file:2_file_resource_id");
+  {
+    base::RunLoop run_loop;
+    RemoveResourceFromDirectoryRequest* request =
+        new RemoveResourceFromDirectoryRequest(
+            request_sender_.get(),
+            *url_generator_,
+            test_util::CreateQuitCallback(
+                &run_loop,
+                test_util::CreateCopyResultCallback(&result_code)),
+            "folder:root",
+            "file:2_file_resource_id");
 
-  request_sender_->StartRequestWithRetry(request);
-  base::MessageLoop::current()->Run();
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_SUCCESS, result_code);
   // DELETE method should be used, without the body content.
@@ -908,22 +967,22 @@
   GURL upload_url;
 
   // 1) Get the upload URL for uploading a new file.
-  InitiateUploadNewFileRequest* initiate_request =
-      new InitiateUploadNewFileRequest(
-          request_sender_.get(),
-          request_context_getter_.get(),
-          *url_generator_,
-          CreateComposedCallback(
-              base::Bind(&test_util::RunAndQuit),
-              test_util::CreateCopyResultCallback(&result_code, &upload_url)),
-          base::FilePath::FromUTF8Unsafe("drive/newfile.txt"),
-          "text/plain",
-          kUploadContent.size(),
-          "folder:id",
-          "New file");
-
-  request_sender_->StartRequestWithRetry(initiate_request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    InitiateUploadNewFileRequest* initiate_request =
+        new InitiateUploadNewFileRequest(
+            request_sender_.get(),
+            *url_generator_,
+            test_util::CreateQuitCallback(
+                &run_loop,
+                test_util::CreateCopyResultCallback(&result_code, &upload_url)),
+            "text/plain",
+            kUploadContent.size(),
+            "folder:id",
+            "New file");
+    request_sender_->StartRequestWithRetry(initiate_request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_SUCCESS, result_code);
   EXPECT_EQ(test_server_.GetURL("/upload_new_file"), upload_url);
@@ -950,23 +1009,24 @@
   UploadRangeResponse response;
   scoped_ptr<ResourceEntry> new_entry;
 
-  ResumeUploadRequest* resume_request = new ResumeUploadRequest(
-      request_sender_.get(),
-      request_context_getter_.get(),
-      CreateComposedCallback(
-          base::Bind(&test_util::RunAndQuit),
-          test_util::CreateCopyResultCallback(&response, &new_entry)),
-      ProgressCallback(),
-      base::FilePath::FromUTF8Unsafe("drive/newfile.txt"),
-      upload_url,
-      0,  // start_position
-      kUploadContent.size(),  // end_position (exclusive)
-      kUploadContent.size(),  // content_length,
-      "text/plain",  // content_type
-      kTestFilePath);
+  {
+    base::RunLoop run_loop;
+    ResumeUploadRequest* resume_request = new ResumeUploadRequest(
+        request_sender_.get(),
+        test_util::CreateQuitCallback(
+            &run_loop,
+            test_util::CreateCopyResultCallback(&response, &new_entry)),
+        ProgressCallback(),
+        upload_url,
+        0,  // start_position
+        kUploadContent.size(),  // end_position (exclusive)
+        kUploadContent.size(),  // content_length,
+        "text/plain",  // content_type
+        kTestFilePath);
 
-  request_sender_->StartRequestWithRetry(resume_request);
-  base::MessageLoop::current()->Run();
+    request_sender_->StartRequestWithRetry(resume_request);
+    run_loop.Run();
+  }
 
   // METHOD_PUT should be used to upload data.
   EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method);
@@ -988,9 +1048,6 @@
   EXPECT_EQ(-1, response.end_position_received);
 }
 
-// TODO(kinaba): crbug.com/{241241,164098} Re-enable the test.
-#define NO_GET_UPLOAD_STATUS_TEST
-
 // This test exercises InitiateUploadNewFileRequest and ResumeUploadRequest
 // for a scenario of uploading a new *large* file, which requires multiple
 // requests of ResumeUploadRequest. GetUploadRequest is also tested in this
@@ -1010,22 +1067,22 @@
   GURL upload_url;
 
   // 1) Get the upload URL for uploading a new file.
-  InitiateUploadNewFileRequest* initiate_request =
-      new InitiateUploadNewFileRequest(
-          request_sender_.get(),
-          request_context_getter_.get(),
-          *url_generator_,
-          CreateComposedCallback(
-              base::Bind(&test_util::RunAndQuit),
-              test_util::CreateCopyResultCallback(&result_code, &upload_url)),
-          base::FilePath::FromUTF8Unsafe("drive/newfile.txt"),
-          "text/plain",
-          kUploadContent.size(),
-          "folder:id",
-          "New file");
-
-  request_sender_->StartRequestWithRetry(initiate_request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    InitiateUploadNewFileRequest* initiate_request =
+        new InitiateUploadNewFileRequest(
+            request_sender_.get(),
+            *url_generator_,
+            test_util::CreateQuitCallback(
+                &run_loop,
+                test_util::CreateCopyResultCallback(&result_code, &upload_url)),
+            "text/plain",
+            kUploadContent.size(),
+            "folder:id",
+            "New file");
+    request_sender_->StartRequestWithRetry(initiate_request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_SUCCESS, result_code);
   EXPECT_EQ(test_server_.GetURL("/upload_new_file"), upload_url);
@@ -1048,7 +1105,6 @@
             "</entry>\n",
             http_request_.content);
 
-#if !defined(NO_GET_UPLOAD_STATUS_TEST)
   // 2) Before sending any data, check the current status.
   // This is an edge case test for GetUploadStatusRequest
   // (UploadRangeRequestBase).
@@ -1057,18 +1113,19 @@
     scoped_ptr<ResourceEntry> new_entry;
 
     // Check the response by GetUploadStatusRequest.
-    GetUploadStatusRequest* get_upload_status_request =
-        new GetUploadStatusRequest(
-            request_sender_.get(),
-            request_context_getter_.get(),
-            CreateComposedCallback(
-                base::Bind(&test_util::RunAndQuit),
-                test_util::CreateCopyResultCallback(&response, &new_entry)),
-            base::FilePath::FromUTF8Unsafe("drive/newfile.txt"),
-            upload_url,
-            kUploadContent.size());
-    request_sender_->StartRequestWithRetry(get_upload_status_request);
-    base::MessageLoop::current()->Run();
+    {
+      base::RunLoop run_loop;
+      GetUploadStatusRequest* get_upload_status_request =
+          new GetUploadStatusRequest(
+              request_sender_.get(),
+              test_util::CreateQuitCallback(
+                  &run_loop,
+                  test_util::CreateCopyResultCallback(&response, &new_entry)),
+              upload_url,
+              kUploadContent.size());
+      request_sender_->StartRequestWithRetry(get_upload_status_request);
+      run_loop.Run();
+    }
 
     // METHOD_PUT should be used to upload data.
     EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method);
@@ -1085,7 +1142,6 @@
     EXPECT_EQ(0, response.start_position_received);
     EXPECT_EQ(0, response.end_position_received);
   }
-#endif  // NO_GET_UPLOAD_STATUS_TEST
 
   // 3) Upload the content to the upload URL with multiple requests.
   size_t num_bytes_consumed = 0;
@@ -1104,23 +1160,23 @@
     UploadRangeResponse response;
     scoped_ptr<ResourceEntry> new_entry;
 
-    ResumeUploadRequest* resume_request = new ResumeUploadRequest(
-        request_sender_.get(),
-        request_context_getter_.get(),
-        CreateComposedCallback(
-            base::Bind(&test_util::RunAndQuit),
-            test_util::CreateCopyResultCallback(&response, &new_entry)),
-        ProgressCallback(),
-        base::FilePath::FromUTF8Unsafe("drive/newfile.txt"),
-        upload_url,
-        start_position,
-        end_position,
-        kUploadContent.size(),  // content_length,
-        "text/plain",  // content_type
-        kTestFilePath);
-
-    request_sender_->StartRequestWithRetry(resume_request);
-    base::MessageLoop::current()->Run();
+    {
+      base::RunLoop run_loop;
+      ResumeUploadRequest* resume_request = new ResumeUploadRequest(
+          request_sender_.get(),
+          test_util::CreateQuitCallback(
+              &run_loop,
+              test_util::CreateCopyResultCallback(&response, &new_entry)),
+          ProgressCallback(),
+          upload_url,
+          start_position,
+          end_position,
+          kUploadContent.size(),  // content_length,
+          "text/plain",  // content_type
+          kTestFilePath);
+      request_sender_->StartRequestWithRetry(resume_request);
+      run_loop.Run();
+    }
 
     // METHOD_PUT should be used to upload data.
     EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method);
@@ -1152,20 +1208,20 @@
     EXPECT_EQ(static_cast<int64>(end_position),
               response.end_position_received);
 
-#if !defined(NO_GET_UPLOAD_STATUS_TEST)
     // Check the response by GetUploadStatusRequest.
-    GetUploadStatusRequest* get_upload_status_request =
-        new GetUploadStatusRequest(
-            request_sender_.get(),
-            request_context_getter_.get(),
-            CreateComposedCallback(
-                base::Bind(&test_util::RunAndQuit),
-                test_util::CreateCopyResultCallback(&response, &new_entry)),
-            base::FilePath::FromUTF8Unsafe("drive/newfile.txt"),
-            upload_url,
-            kUploadContent.size());
-    request_sender_->StartRequestWithRetry(get_upload_request);
-    base::MessageLoop::current()->Run();
+    {
+      base::RunLoop run_loop;
+      GetUploadStatusRequest* get_upload_status_request =
+          new GetUploadStatusRequest(
+              request_sender_.get(),
+              test_util::CreateQuitCallback(
+                  &run_loop,
+                  test_util::CreateCopyResultCallback(&response, &new_entry)),
+              upload_url,
+              kUploadContent.size());
+      request_sender_->StartRequestWithRetry(get_upload_status_request);
+      run_loop.Run();
+    }
 
     // METHOD_PUT should be used to upload data.
     EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method);
@@ -1182,7 +1238,6 @@
     EXPECT_EQ(0, response.start_position_received);
     EXPECT_EQ(static_cast<int64>(end_position),
               response.end_position_received);
-#endif  // NO_GET_UPLOAD_STATUS_TEST
   }
 
   EXPECT_EQ(kUploadContent.size(), num_bytes_consumed);
@@ -1203,22 +1258,22 @@
   GURL upload_url;
 
   // 1) Get the upload URL for uploading a new file.
-  InitiateUploadNewFileRequest* initiate_request =
-      new InitiateUploadNewFileRequest(
-          request_sender_.get(),
-          request_context_getter_.get(),
-          *url_generator_,
-          CreateComposedCallback(
-              base::Bind(&test_util::RunAndQuit),
-              test_util::CreateCopyResultCallback(&result_code, &upload_url)),
-          base::FilePath::FromUTF8Unsafe("drive/newfile.txt"),
-          "text/plain",
-          kUploadContent.size(),
-          "folder:id",
-          "New file");
-
-  request_sender_->StartRequestWithRetry(initiate_request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    InitiateUploadNewFileRequest* initiate_request =
+        new InitiateUploadNewFileRequest(
+            request_sender_.get(),
+            *url_generator_,
+            test_util::CreateQuitCallback(
+                &run_loop,
+                test_util::CreateCopyResultCallback(&result_code, &upload_url)),
+            "text/plain",
+            kUploadContent.size(),
+            "folder:id",
+            "New file");
+    request_sender_->StartRequestWithRetry(initiate_request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_SUCCESS, result_code);
   EXPECT_EQ(test_server_.GetURL("/upload_new_file"), upload_url);
@@ -1245,23 +1300,23 @@
   UploadRangeResponse response;
   scoped_ptr<ResourceEntry> new_entry;
 
-  ResumeUploadRequest* resume_request = new ResumeUploadRequest(
-      request_sender_.get(),
-      request_context_getter_.get(),
-      CreateComposedCallback(
-          base::Bind(&test_util::RunAndQuit),
-          test_util::CreateCopyResultCallback(&response, &new_entry)),
-      ProgressCallback(),
-      base::FilePath::FromUTF8Unsafe("drive/newfile.txt"),
-      upload_url,
-      0,  // start_position
-      kUploadContent.size(),  // end_position (exclusive)
-      kUploadContent.size(),  // content_length,
-      "text/plain",  // content_type
-      kTestFilePath);
-
-  request_sender_->StartRequestWithRetry(resume_request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    ResumeUploadRequest* resume_request = new ResumeUploadRequest(
+        request_sender_.get(),
+        test_util::CreateQuitCallback(
+            &run_loop,
+            test_util::CreateCopyResultCallback(&response, &new_entry)),
+        ProgressCallback(),
+        upload_url,
+        0,  // start_position
+        kUploadContent.size(),  // end_position (exclusive)
+        kUploadContent.size(),  // content_length,
+        "text/plain",  // content_type
+        kTestFilePath);
+    request_sender_->StartRequestWithRetry(resume_request);
+    run_loop.Run();
+  }
 
   // METHOD_PUT should be used to upload data.
   EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method);
@@ -1293,22 +1348,22 @@
   GURL upload_url;
 
   // 1) Get the upload URL for uploading an existing file.
-  InitiateUploadExistingFileRequest* initiate_request =
-      new InitiateUploadExistingFileRequest(
-          request_sender_.get(),
-          request_context_getter_.get(),
-          *url_generator_,
-          CreateComposedCallback(
-              base::Bind(&test_util::RunAndQuit),
-              test_util::CreateCopyResultCallback(&result_code, &upload_url)),
-          base::FilePath::FromUTF8Unsafe("drive/existingfile.txt"),
-          "text/plain",
-          kUploadContent.size(),
-          "file:foo",
-          std::string() /* etag */);
-
-  request_sender_->StartRequestWithRetry(initiate_request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    InitiateUploadExistingFileRequest* initiate_request =
+        new InitiateUploadExistingFileRequest(
+            request_sender_.get(),
+            *url_generator_,
+            test_util::CreateQuitCallback(
+                &run_loop,
+                test_util::CreateCopyResultCallback(&result_code, &upload_url)),
+            "text/plain",
+            kUploadContent.size(),
+            "file:foo",
+            std::string() /* etag */);
+    request_sender_->StartRequestWithRetry(initiate_request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_SUCCESS, result_code);
   EXPECT_EQ(test_server_.GetURL("/upload_existing_file"), upload_url);
@@ -1334,23 +1389,24 @@
   UploadRangeResponse response;
   scoped_ptr<ResourceEntry> new_entry;
 
-  ResumeUploadRequest* resume_request = new ResumeUploadRequest(
-      request_sender_.get(),
-      request_context_getter_.get(),
-      CreateComposedCallback(
-          base::Bind(&test_util::RunAndQuit),
-          test_util::CreateCopyResultCallback(&response, &new_entry)),
-      ProgressCallback(),
-      base::FilePath::FromUTF8Unsafe("drive/existingfile.txt"),
-      upload_url,
-      0,  // start_position
-      kUploadContent.size(),  // end_position (exclusive)
-      kUploadContent.size(),  // content_length,
-      "text/plain",  // content_type
-      kTestFilePath);
+  {
+    base::RunLoop run_loop;
+    ResumeUploadRequest* resume_request = new ResumeUploadRequest(
+        request_sender_.get(),
+        test_util::CreateQuitCallback(
+            &run_loop,
+            test_util::CreateCopyResultCallback(&response, &new_entry)),
+        ProgressCallback(),
+        upload_url,
+        0,  // start_position
+        kUploadContent.size(),  // end_position (exclusive)
+        kUploadContent.size(),  // content_length,
+        "text/plain",  // content_type
+        kTestFilePath);
 
-  request_sender_->StartRequestWithRetry(resume_request);
-  base::MessageLoop::current()->Run();
+    request_sender_->StartRequestWithRetry(resume_request);
+    run_loop.Run();
+  }
 
   // METHOD_PUT should be used to upload data.
   EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method);
@@ -1384,22 +1440,22 @@
   GURL upload_url;
 
   // 1) Get the upload URL for uploading an existing file.
-  InitiateUploadExistingFileRequest* initiate_request =
-      new InitiateUploadExistingFileRequest(
-          request_sender_.get(),
-          request_context_getter_.get(),
-          *url_generator_,
-          CreateComposedCallback(
-              base::Bind(&test_util::RunAndQuit),
-              test_util::CreateCopyResultCallback(&result_code, &upload_url)),
-          base::FilePath::FromUTF8Unsafe("drive/existingfile.txt"),
-          "text/plain",
-          kUploadContent.size(),
-          "file:foo",
-          kTestETag);
-
-  request_sender_->StartRequestWithRetry(initiate_request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    InitiateUploadExistingFileRequest* initiate_request =
+        new InitiateUploadExistingFileRequest(
+            request_sender_.get(),
+            *url_generator_,
+            test_util::CreateQuitCallback(
+                &run_loop,
+                test_util::CreateCopyResultCallback(&result_code, &upload_url)),
+            "text/plain",
+            kUploadContent.size(),
+            "file:foo",
+            kTestETag);
+    request_sender_->StartRequestWithRetry(initiate_request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_SUCCESS, result_code);
   EXPECT_EQ(test_server_.GetURL("/upload_existing_file"), upload_url);
@@ -1425,23 +1481,23 @@
   UploadRangeResponse response;
   scoped_ptr<ResourceEntry> new_entry;
 
-  ResumeUploadRequest* resume_request = new ResumeUploadRequest(
-      request_sender_.get(),
-      request_context_getter_.get(),
-      CreateComposedCallback(
-          base::Bind(&test_util::RunAndQuit),
-          test_util::CreateCopyResultCallback(&response, &new_entry)),
-      ProgressCallback(),
-      base::FilePath::FromUTF8Unsafe("drive/existingfile.txt"),
-      upload_url,
-      0,  // start_position
-      kUploadContent.size(),  // end_position (exclusive)
-      kUploadContent.size(),  // content_length,
-      "text/plain",  // content_type
-      kTestFilePath);
-
-  request_sender_->StartRequestWithRetry(resume_request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    ResumeUploadRequest* resume_request = new ResumeUploadRequest(
+        request_sender_.get(),
+        test_util::CreateQuitCallback(
+            &run_loop,
+            test_util::CreateCopyResultCallback(&response, &new_entry)),
+        ProgressCallback(),
+        upload_url,
+        0,  // start_position
+        kUploadContent.size(),  // end_position (exclusive)
+        kUploadContent.size(),  // content_length,
+        "text/plain",  // content_type
+        kTestFilePath);
+    request_sender_->StartRequestWithRetry(resume_request);
+    run_loop.Run();
+  }
 
   // METHOD_PUT should be used to upload data.
   EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method);
@@ -1471,22 +1527,22 @@
   GDataErrorCode result_code = GDATA_OTHER_ERROR;
   GURL upload_url;
 
-  InitiateUploadExistingFileRequest* initiate_request =
-      new InitiateUploadExistingFileRequest(
-          request_sender_.get(),
-          request_context_getter_.get(),
-          *url_generator_,
-          CreateComposedCallback(
-              base::Bind(&test_util::RunAndQuit),
-              test_util::CreateCopyResultCallback(&result_code, &upload_url)),
-          base::FilePath::FromUTF8Unsafe("drive/existingfile.txt"),
-          "text/plain",
-          kUploadContent.size(),
-          "file:foo",
-          kWrongETag);
-
-  request_sender_->StartRequestWithRetry(initiate_request);
-  base::MessageLoop::current()->Run();
+  {
+    base::RunLoop run_loop;
+    InitiateUploadExistingFileRequest* initiate_request =
+        new InitiateUploadExistingFileRequest(
+            request_sender_.get(),
+            *url_generator_,
+            test_util::CreateQuitCallback(
+                &run_loop,
+                test_util::CreateCopyResultCallback(&result_code, &upload_url)),
+            "text/plain",
+            kUploadContent.size(),
+            "file:foo",
+            kWrongETag);
+    request_sender_->StartRequestWithRetry(initiate_request);
+    run_loop.Run();
+  }
 
   EXPECT_EQ(HTTP_PRECONDITION, result_code);
   // For updating an existing file, METHOD_PUT should be used.
@@ -1508,4 +1564,41 @@
   EXPECT_EQ(kWrongETag, http_request_.headers["If-Match"]);
 }
 
+TEST_F(GDataWapiRequestsTest, DownloadFileRequest) {
+  const base::FilePath kDownloadedFilePath =
+      temp_dir_.path().AppendASCII("cache_file");
+  const std::string kTestIdWithTypeLabel("file:dummyId");
+  const std::string kTestId("dummyId");
+
+  GDataErrorCode result_code = GDATA_OTHER_ERROR;
+  base::FilePath temp_file;
+  {
+    base::RunLoop run_loop;
+    DownloadFileRequest* request = new DownloadFileRequest(
+        request_sender_.get(),
+        *url_generator_,
+        test_util::CreateQuitCallback(
+            &run_loop,
+            test_util::CreateCopyResultCallback(&result_code, &temp_file)),
+        GetContentCallback(),
+        ProgressCallback(),
+        kTestIdWithTypeLabel,
+        kDownloadedFilePath);
+    request_sender_->StartRequestWithRetry(request);
+    run_loop.Run();
+  }
+
+  std::string contents;
+  file_util::ReadFileToString(temp_file, &contents);
+  base::Delete(temp_file, false);
+
+  EXPECT_EQ(HTTP_SUCCESS, result_code);
+  EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method);
+  EXPECT_EQ(kTestDownloadPathPrefix + kTestId, http_request_.relative_url);
+  EXPECT_EQ(kDownloadedFilePath, temp_file);
+
+  const std::string expected_contents = kTestId + kTestId + kTestId;
+  EXPECT_EQ(expected_contents, contents);
+}
+
 }  // namespace google_apis
diff --git a/chrome/browser/google_apis/gdata_wapi_url_generator.cc b/chrome/browser/google_apis/gdata_wapi_url_generator.cc
index 85e4517..f4956a8 100644
--- a/chrome/browser/google_apis/gdata_wapi_url_generator.cc
+++ b/chrome/browser/google_apis/gdata_wapi_url_generator.cc
@@ -7,9 +7,9 @@
 #include "base/logging.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/escape.h"
 #include "net/base/url_util.h"
+#include "url/gurl.h"
 
 namespace google_apis {
 namespace {
@@ -57,6 +57,9 @@
 const char GDataWapiUrlGenerator::kBaseUrlForProduction[] =
     "https://docs.google.com/";
 
+const char GDataWapiUrlGenerator::kBaseDownloadUrlForProduction[] =
+    "https://www.googledrive.com/host/";
+
 // static
 GURL GDataWapiUrlGenerator::AddStandardUrlParams(const GURL& url) {
   GURL result = net::AppendOrReplaceQueryParameter(url, "v", "3");
@@ -83,8 +86,10 @@
   return result;
 }
 
-GDataWapiUrlGenerator::GDataWapiUrlGenerator(const GURL& base_url)
-    : base_url_(GURL(base_url)) {
+GDataWapiUrlGenerator::GDataWapiUrlGenerator(const GURL& base_url,
+                                             const GURL& base_download_url)
+    : base_url_(base_url),
+      base_download_url_(base_download_url) {
 }
 
 GDataWapiUrlGenerator::~GDataWapiUrlGenerator() {
@@ -215,4 +220,13 @@
   return result;
 }
 
+GURL GDataWapiUrlGenerator::GenerateDownloadFileUrl(
+    const std::string& resource_id) const {
+  // Strip the file type prefix before the colon character.
+  size_t colon = resource_id.find(':');
+  return base_download_url_.Resolve(net::EscapePath(
+      colon == std::string::npos ? resource_id
+                                 : resource_id.substr(colon + 1)));
+}
+
 }  // namespace google_apis
diff --git a/chrome/browser/google_apis/gdata_wapi_url_generator.h b/chrome/browser/google_apis/gdata_wapi_url_generator.h
index e071f8c..31d17f9 100644
--- a/chrome/browser/google_apis/gdata_wapi_url_generator.h
+++ b/chrome/browser/google_apis/gdata_wapi_url_generator.h
@@ -9,7 +9,7 @@
 
 #include <string>
 
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 namespace google_apis {
 
@@ -17,12 +17,16 @@
 // for production, and the local server for testing.
 class GDataWapiUrlGenerator {
  public:
-  explicit GDataWapiUrlGenerator(const GURL& base_url);
+  // The
+  GDataWapiUrlGenerator(const GURL& base_url, const GURL& base_download_url);
   ~GDataWapiUrlGenerator();
 
   // The base URL for communicating with the WAPI server for production.
   static const char kBaseUrlForProduction[];
 
+  // The base URL for the file download server for production.
+  static const char kBaseDownloadUrlForProduction[];
+
   // Adds additional parameters for API version, output content type and to
   // show folders in the feed are added to document feed URLs.
   static GURL AddStandardUrlParams(const GURL& url);
@@ -119,8 +123,12 @@
   // list of installed third party applications.
   GURL GenerateAccountMetadataUrl(bool include_installed_apps) const;
 
+  // Generates a URL for downloading a file.
+  GURL GenerateDownloadFileUrl(const std::string& resource_id) const;
+
  private:
   const GURL base_url_;
+  const GURL base_download_url_;
 };
 
 }  // namespace google_apis
diff --git a/chrome/browser/google_apis/gdata_wapi_url_generator_unittest.cc b/chrome/browser/google_apis/gdata_wapi_url_generator_unittest.cc
index 94a518a..ef8f1da 100644
--- a/chrome/browser/google_apis/gdata_wapi_url_generator_unittest.cc
+++ b/chrome/browser/google_apis/gdata_wapi_url_generator_unittest.cc
@@ -4,15 +4,17 @@
 
 #include "chrome/browser/google_apis/gdata_wapi_url_generator.h"
 
-#include "googleurl/src/gurl.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 namespace google_apis {
 
 class GDataWapiUrlGeneratorTest : public testing::Test {
  public:
   GDataWapiUrlGeneratorTest()
-      : url_generator_(GURL(GDataWapiUrlGenerator::kBaseUrlForProduction)) {
+      : url_generator_(
+          GURL(GDataWapiUrlGenerator::kBaseUrlForProduction),
+          GURL(GDataWapiUrlGenerator::kBaseDownloadUrlForProduction)) {
   }
 
  protected:
@@ -196,4 +198,10 @@
       url_generator_.GenerateAccountMetadataUrl(false).spec());
 }
 
+TEST_F(GDataWapiUrlGeneratorTest, GenerateDownloadFileUrl) {
+  EXPECT_EQ(
+      "https://www.googledrive.com/host/resourceId",
+      url_generator_.GenerateDownloadFileUrl("file:resourceId").spec());
+}
+
 }  // namespace google_apis
diff --git a/chrome/browser/google_apis/request_registry.cc b/chrome/browser/google_apis/request_registry.cc
deleted file mode 100644
index 240b388..0000000
--- a/chrome/browser/google_apis/request_registry.cc
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/google_apis/request_registry.h"
-
-#include "content/public/browser/browser_thread.h"
-
-using content::BrowserThread;
-
-namespace google_apis {
-
-RequestProgressStatus::RequestProgressStatus(const base::FilePath& path)
-    : request_id(-1),
-      file_path(path),
-      transfer_state(REQUEST_NOT_STARTED) {
-}
-
-RequestRegistry::Request::Request(RequestRegistry* registry)
-    : registry_(registry),
-      progress_status_(base::FilePath()) {
-}
-
-RequestRegistry::Request::Request(RequestRegistry* registry,
-                                        const base::FilePath& path)
-    : registry_(registry),
-      progress_status_(path) {
-}
-
-RequestRegistry::Request::~Request() {
-  DCHECK(progress_status_.transfer_state == REQUEST_COMPLETED ||
-         progress_status_.transfer_state == REQUEST_FAILED);
-}
-
-void RequestRegistry::Request::Cancel() {
-  DoCancel();
-  NotifyFinish(REQUEST_FAILED);
-}
-
-void RequestRegistry::Request::NotifyStart() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  // Some request_ids may be restarted. Report only the first "start".
-  if (progress_status_.transfer_state == REQUEST_NOT_STARTED) {
-    progress_status_.transfer_state = REQUEST_STARTED;
-    registry_->OnRequestStart(this, &progress_status_.request_id);
-  }
-}
-
-void RequestRegistry::Request::NotifyFinish(
-    RequestTransferState status) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  DCHECK(progress_status_.transfer_state >= REQUEST_STARTED);
-  DCHECK(status == REQUEST_COMPLETED || status == REQUEST_FAILED);
-  progress_status_.transfer_state = status;
-  registry_->OnRequestFinish(progress_status().request_id);
-}
-
-RequestRegistry::RequestRegistry() {
-  in_flight_requests_.set_check_on_null_data(true);
-}
-
-RequestRegistry::~RequestRegistry() {
-}
-
-void RequestRegistry::CancelRequest(Request* request) {
-  request->Cancel();
-}
-
-void RequestRegistry::OnRequestStart(
-    RequestRegistry::Request* request,
-    RequestID* id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  *id = in_flight_requests_.Add(request);
-  DVLOG(1) << "Request[" << *id << "] started.";
-}
-
-void RequestRegistry::OnRequestFinish(RequestID id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  Request* request = in_flight_requests_.Lookup(id);
-  DCHECK(request);
-
-  DVLOG(1) << "Request[" << id << "] finished.";
-  in_flight_requests_.Remove(id);
-}
-
-}  // namespace google_apis
diff --git a/chrome/browser/google_apis/request_registry.h b/chrome/browser/google_apis/request_registry.h
deleted file mode 100644
index 0c034a7..0000000
--- a/chrome/browser/google_apis/request_registry.h
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GOOGLE_APIS_REQUEST_REGISTRY_H_
-#define CHROME_BROWSER_GOOGLE_APIS_REQUEST_REGISTRY_H_
-
-#include "base/basictypes.h"
-#include "base/files/file_path.h"
-#include "base/id_map.h"
-#include "chrome/browser/google_apis/gdata_errorcode.h"
-
-namespace google_apis {
-
-// Unique ID to identify each request.
-typedef int32 RequestID;
-
-// Enumeration type for indicating the state of the transfer.
-enum RequestTransferState {
-  REQUEST_NOT_STARTED,
-  REQUEST_STARTED,
-  REQUEST_IN_PROGRESS,
-  REQUEST_COMPLETED,
-  REQUEST_FAILED,
-};
-
-// Returns string representations of the request state.
-std::string RequestTransferStateToString(RequestTransferState state);
-
-// Structure that packs progress information of each request.
-struct RequestProgressStatus {
-  explicit RequestProgressStatus(const base::FilePath& file_path);
-
-  RequestID request_id;
-
-  // Drive path of the file dealt with the current request.
-  base::FilePath file_path;
-  // Current state of the transfer;
-  RequestTransferState transfer_state;
-};
-
-// This class tracks all the in-flight Google API requests and manage
-// their lifetime.
-class RequestRegistry {
- public:
-  RequestRegistry();
-  ~RequestRegistry();
-
-  // Base class for requests that this registry class can maintain.
-  // NotifyStart() passes the ownership of the Request object to the registry.
-  // In particular, calling NotifyFinish() causes the registry to delete the
-  // Request object itself.
-  class Request {
-   public:
-    explicit Request(RequestRegistry* registry);
-    Request(RequestRegistry* registry, const base::FilePath& file_path);
-    virtual ~Request();
-
-    // Cancels the ongoing request. NotifyFinish() is called and the Request
-    // object is deleted once the cancellation is done in DoCancel().
-    void Cancel();
-
-    // Retrieves the current progress status of the request.
-    const RequestProgressStatus& progress_status() const {
-      return progress_status_;
-    }
-
-   protected:
-    // Notifies the registry about current status.
-    void NotifyStart();
-    void NotifyFinish(RequestTransferState status);
-
-   private:
-    // Does the cancellation.
-    virtual void DoCancel() = 0;
-
-    RequestRegistry* const registry_;
-    RequestProgressStatus progress_status_;
-  };
-
-  // Cancels the specified request.
-  void CancelRequest(Request* request);
-
- private:
-  // Handlers for notifications from Requests.
-  friend class Request;
-  // Notifies that an request has started. This method passes the ownership of
-  // the request to the registry. A fresh request ID is returned to *id.
-  void OnRequestStart(Request* request, RequestID* id);
-  void OnRequestFinish(RequestID request_id);
-
-  typedef IDMap<Request, IDMapOwnPointer> RequestIDMap;
-  RequestIDMap in_flight_requests_;
-
-  DISALLOW_COPY_AND_ASSIGN(RequestRegistry);
-};
-
-}  // namespace google_apis
-
-#endif  // CHROME_BROWSER_GOOGLE_APIS_REQUEST_REGISTRY_H_
diff --git a/chrome/browser/google_apis/request_sender.cc b/chrome/browser/google_apis/request_sender.cc
index f4eae24..b2709dc 100644
--- a/chrome/browser/google_apis/request_sender.cc
+++ b/chrome/browser/google_apis/request_sender.cc
@@ -5,11 +5,9 @@
 #include "chrome/browser/google_apis/request_sender.h"
 
 #include "base/bind.h"
+#include "base/stl_util.h"
 #include "chrome/browser/google_apis/auth_service.h"
 #include "chrome/browser/google_apis/base_requests.h"
-#include "content/public/browser/browser_thread.h"
-
-using content::BrowserThread;
 
 namespace google_apis {
 
@@ -19,25 +17,29 @@
     const std::vector<std::string>& scopes,
     const std::string& custom_user_agent)
     : profile_(profile),
+      url_request_context_getter_(url_request_context_getter),
       auth_service_(new AuthService(url_request_context_getter, scopes)),
-      request_registry_(new RequestRegistry()),
       custom_user_agent_(custom_user_agent),
       weak_ptr_factory_(this) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(thread_checker_.CalledOnValidThread());
 }
 
 RequestSender::~RequestSender() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(thread_checker_.CalledOnValidThread());
+  STLDeleteContainerPointers(in_flight_requests_.begin(),
+                             in_flight_requests_.end());
 }
 
 void RequestSender::Initialize() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(thread_checker_.CalledOnValidThread());
   auth_service_->Initialize(profile_);
 }
 
 base::Closure RequestSender::StartRequestWithRetry(
     AuthenticatedRequestInterface* request) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(thread_checker_.CalledOnValidThread());
+
+  in_flight_requests_.insert(request);
 
   // TODO(kinaba): Stop relying on weak pointers. Move lifetime management
   // of the requests to request sender.
@@ -66,7 +68,7 @@
     const base::WeakPtr<AuthenticatedRequestInterface>& request,
     GDataErrorCode code,
     const std::string& /* access_token */) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(thread_checker_.CalledOnValidThread());
 
   // Do nothing if the request is canceled during authentication.
   if (!request.get())
@@ -81,7 +83,7 @@
 }
 
 void RequestSender::RetryRequest(AuthenticatedRequestInterface* request) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(thread_checker_.CalledOnValidThread());
 
   auth_service_->ClearAccessToken();
   // User authentication might have expired - rerun the request to force
@@ -91,12 +93,17 @@
 
 void RequestSender::CancelRequest(
     const base::WeakPtr<AuthenticatedRequestInterface>& request) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(thread_checker_.CalledOnValidThread());
 
   // Do nothing if the request is already finished.
   if (!request.get())
     return;
-  request_registry_->CancelRequest(request->AsRequestRegistryRequest());
+  request->Cancel();
+}
+
+void RequestSender::RequestFinished(AuthenticatedRequestInterface* request) {
+  in_flight_requests_.erase(request);
+  delete request;
 }
 
 }  // namespace google_apis
diff --git a/chrome/browser/google_apis/request_sender.h b/chrome/browser/google_apis/request_sender.h
index 5b9b8dc..f20c394 100644
--- a/chrome/browser/google_apis/request_sender.h
+++ b/chrome/browser/google_apis/request_sender.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_GOOGLE_APIS_REQUEST_SENDER_H_
 #define CHROME_BROWSER_GOOGLE_APIS_REQUEST_SENDER_H_
 
+#include <set>
 #include <string>
 #include <vector>
 
@@ -12,6 +13,7 @@
 #include "base/callback_forward.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
+#include "base/threading/thread_checker.h"
 #include "chrome/browser/google_apis/gdata_errorcode.h"
 
 class Profile;
@@ -24,7 +26,6 @@
 
 class AuthenticatedRequestInterface;
 class AuthService;
-class RequestRegistry;
 
 // Helper class that sends requests implementing
 // AuthenticatedRequestInterface and handles retries and authentication.
@@ -44,8 +45,9 @@
   virtual ~RequestSender();
 
   AuthService* auth_service() { return auth_service_.get(); }
-  RequestRegistry* request_registry() {
-    return request_registry_.get();
+
+  net::URLRequestContextGetter* url_request_context_getter() const {
+    return url_request_context_getter_;
   }
 
   // Prepares the object for use.
@@ -53,12 +55,18 @@
 
   // Starts a request implementing the AuthenticatedRequestInterface
   // interface, and makes the request retry upon authentication failures by
-  // calling back to RetryRequest.
+  // calling back to RetryRequest. The |request| object is owned by this
+  // RequestSender. It will be deleted in RequestSender's destructor or
+  // in RequestFinished().
   //
   // Returns a closure to cancel the request. The closure cancels the request
   // if it is in-flight, and does nothing if it is already terminated.
   base::Closure StartRequestWithRetry(AuthenticatedRequestInterface* request);
 
+  // Notifies to this RequestSender that |request| has finished.
+  // TODO(kinaba): refactor the life time management and make this at private.
+  void RequestFinished(AuthenticatedRequestInterface* request);
+
  private:
   // Called when the access token is fetched.
   void OnAccessTokenFetched(
@@ -76,11 +84,14 @@
       const base::WeakPtr<AuthenticatedRequestInterface>& request);
 
   Profile* profile_;  // Not owned.
+  net::URLRequestContextGetter* url_request_context_getter_;  // Not owned.
 
   scoped_ptr<AuthService> auth_service_;
-  scoped_ptr<RequestRegistry> request_registry_;
+  std::set<AuthenticatedRequestInterface*> in_flight_requests_;
   const std::string custom_user_agent_;
 
+  base::ThreadChecker thread_checker_;
+
   // Note: This should remain the last member so it'll be destroyed and
   // invalidate its weak pointers before any other members are destroyed.
   base::WeakPtrFactory<RequestSender> weak_ptr_factory_;
diff --git a/chrome/browser/google_apis/task_util.cc b/chrome/browser/google_apis/task_util.cc
index 7d048ee..eb175d8 100644
--- a/chrome/browser/google_apis/task_util.cc
+++ b/chrome/browser/google_apis/task_util.cc
@@ -5,9 +5,6 @@
 #include "chrome/browser/google_apis/task_util.h"
 
 #include "base/location.h"
-#include "content/public/browser/browser_thread.h"
-
-using content::BrowserThread;
 
 namespace google_apis {
 
@@ -21,9 +18,4 @@
   }
 }
 
-void RunTaskOnUIThread(const base::Closure& task) {
-  RunTaskOnThread(
-      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), task);
-}
-
 }  // namespace google_apis
diff --git a/chrome/browser/google_apis/task_util.h b/chrome/browser/google_apis/task_util.h
index d4fd59b..f6e874b 100644
--- a/chrome/browser/google_apis/task_util.h
+++ b/chrome/browser/google_apis/task_util.h
@@ -14,9 +14,6 @@
 void RunTaskOnThread(scoped_refptr<base::MessageLoopProxy> relay_proxy,
                      const base::Closure& task);
 
-// Runs task on UI thread.
-void RunTaskOnUIThread(const base::Closure& task);
-
 namespace internal {
 
 // Implementation of the composed callback, whose signature is |Sig|.
diff --git a/chrome/browser/google_apis/test_util.cc b/chrome/browser/google_apis/test_util.cc
index 84dab6c..30c2d35 100644
--- a/chrome/browser/google_apis/test_util.cc
+++ b/chrome/browser/google_apis/test_util.cc
@@ -11,6 +11,7 @@
 #include "base/path_service.h"
 #include "base/pending_task.h"
 #include "base/rand_util.h"
+#include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
@@ -20,9 +21,9 @@
 #include "chrome/browser/google_apis/gdata_wapi_parser.h"
 #include "chrome/browser/google_apis/gdata_wapi_requests.h"
 #include "content/public/browser/browser_thread.h"
-#include "googleurl/src/gurl.h"
 #include "net/test/embedded_test_server/http_request.h"
 #include "net/test/embedded_test_server/http_response.h"
+#include "url/gurl.h"
 
 namespace google_apis {
 namespace test_util {
@@ -79,16 +80,16 @@
 
     TaskObserver task_observer;
     base::MessageLoop::current()->AddTaskObserver(&task_observer);
-    base::MessageLoop::current()->RunUntilIdle();
+    base::RunLoop().RunUntilIdle();
     base::MessageLoop::current()->RemoveTaskObserver(&task_observer);
     if (!task_observer.posted())
       break;
   }
 }
 
-void RunAndQuit(const base::Closure& closure) {
+void RunAndQuit(base::RunLoop* run_loop, const base::Closure& closure) {
   closure.Run();
-  base::MessageLoop::current()->Quit();
+  run_loop->Quit();
 }
 
 bool WriteStringToFile(const base::FilePath& file_path,
@@ -138,7 +139,7 @@
 
   scoped_ptr<net::test_server::BasicHttpResponse> http_response(
       new net::test_server::BasicHttpResponse);
-  http_response->set_code(net::test_server::SUCCESS);
+  http_response->set_code(net::HTTP_OK);
   http_response->set_content(content);
   http_response->set_content_type(content_type);
   return http_response.Pass();
diff --git a/chrome/browser/google_apis/test_util.h b/chrome/browser/google_apis/test_util.h
index 0e770bd..173674d 100644
--- a/chrome/browser/google_apis/test_util.h
+++ b/chrome/browser/google_apis/test_util.h
@@ -16,11 +16,13 @@
 #include "base/template_util.h"
 #include "chrome/browser/google_apis/base_requests.h"
 #include "chrome/browser/google_apis/gdata_errorcode.h"
+#include "chrome/browser/google_apis/task_util.h"
 
 class GURL;
 
 namespace base {
 class FilePath;
+class RunLoop;
 class Value;
 }
 
@@ -33,15 +35,6 @@
 }
 
 namespace google_apis {
-
-class AboutResource;
-class AccountMetadata;
-class AppList;
-class AuthenticatedRequestInterface;
-class ResourceEntry;
-class ResourceList;
-struct UploadRangeResponse;
-
 namespace test_util {
 
 // Runs a task posted to the blocking pool, including subsequent tasks posted
@@ -53,8 +46,15 @@
 // repeatedly.
 void RunBlockingPoolTask();
 
-// Runs the closure, and then quits the current MessageLoop.
-void RunAndQuit(const base::Closure& closure);
+// Runs the closure, and then quits the |run_loop|.
+void RunAndQuit(base::RunLoop* run_loop, const base::Closure& closure);
+
+// Returns callback which runs the given |callback| and then quits |run_loop|.
+template<typename CallbackType>
+CallbackType CreateQuitCallback(base::RunLoop* run_loop,
+                                const CallbackType& callback) {
+  return CreateComposedCallback(base::Bind(&RunAndQuit, run_loop), callback);
+}
 
 // Removes |prefix| from |input| and stores the result in |output|. Returns
 // true if the prefix is removed.
diff --git a/chrome/browser/google_apis/time_util.cc b/chrome/browser/google_apis/time_util.cc
index 01a40dd..3c274b5 100644
--- a/chrome/browser/google_apis/time_util.cc
+++ b/chrome/browser/google_apis/time_util.cc
@@ -10,7 +10,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
-#include "base/time.h"
+#include "base/time/time.h"
 
 namespace google_apis {
 namespace util {
diff --git a/chrome/browser/google_apis/time_util_unittest.cc b/chrome/browser/google_apis/time_util_unittest.cc
index af7eec9..14c8c3c 100644
--- a/chrome/browser/google_apis/time_util_unittest.cc
+++ b/chrome/browser/google_apis/time_util_unittest.cc
@@ -6,52 +6,27 @@
 
 #include "base/i18n/time_formatting.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if defined(OS_CHROMEOS)
-#include "chrome/browser/chromeos/system/timezone_settings.h"
-#endif  // OS_CHROMEOS
-
 namespace google_apis {
 namespace util {
 namespace {
 
 std::string FormatTime(const base::Time& time) {
-  return UTF16ToUTF8(TimeFormatShortDateAndTime(time));
+  return base::UTF16ToUTF8(base::TimeFormatShortDateAndTime(time));
 }
 
 }  // namespace
 
-#if defined(OS_CHROMEOS)
-// ChromeOS can test utilities using ICU library.
-TEST(TimeUtilTest, GetTimeFromStringLocalTimezoneForChromeOs) {
-  // Creates time object GMT.
-  base::Time::Exploded exploded = {2012, 7, 0, 14, 1, 3, 21, 151};
-  base::Time target_time = base::Time::FromUTCExploded(exploded);
-
-  // Creates time object as the local time.
-  base::Time test_time;
-  ASSERT_TRUE(GetTimeFromString("2012-07-14T01:03:21.151", &test_time));
-
-  // Gets the offset between the local time and GMT.
-  const icu::TimeZone& tz =
-      chromeos::system::TimezoneSettings::GetInstance()->GetTimezone();
-  UErrorCode status = U_ZERO_ERROR;
-  int millisecond_in_day = ((1 * 60 + 3) * 60 + 21) * 1000 + 151;
-  int offset = tz.getOffset(1, 2012, 7, 14, 1, millisecond_in_day, status);
-  ASSERT_TRUE(U_SUCCESS(status));
-
-  EXPECT_EQ((target_time - test_time).InMilliseconds(), offset);
-}
-#endif  // OS_CHROMEOS
-
 TEST(TimeUtilTest, GetTimeFromStringLocalTimezone) {
   // Creates local time objects from exploded structure.
   base::Time::Exploded exploded = {2013, 1, 0, 15, 17, 11, 35, 374};
   base::Time local_time = base::Time::FromLocalExploded(exploded);
 
-  // Creates local time object, parsing time string.
+  // Creates local time object, parsing time string. Note that if there is
+  // not timezone suffix, GetTimeFromString() will handle this as local time
+  // with FromLocalExploded().
   base::Time test_time;
   ASSERT_TRUE(GetTimeFromString("2013-01-15T17:11:35.374", &test_time));
 
@@ -59,7 +34,7 @@
   EXPECT_EQ(local_time, test_time);
 }
 
-TEST(TimeUtilTest, GetTimeFromStringTimezone) {
+TEST(TimeUtilTest, GetTimeFromStringNonTrivialTimezones) {
   base::Time target_time;
   base::Time test_time;
   // Creates the target time.
@@ -78,19 +53,23 @@
   EXPECT_EQ(FormatTime(target_time), FormatTime(test_time));
 }
 
-TEST(TimeUtilTest, GetTimeFromString) {
+TEST(TimeUtilTest, GetTimeFromStringBasic) {
   base::Time test_time;
 
+  // Test that the special timezone "Z" (UTC) is handled.
   base::Time::Exploded target_time1 = {2005, 1, 0, 7, 8, 2, 0, 0};
   EXPECT_TRUE(GetTimeFromString("2005-01-07T08:02:00Z", &test_time));
   EXPECT_EQ(FormatTime(base::Time::FromUTCExploded(target_time1)),
             FormatTime(test_time));
 
+  // Test that a simple timezone "-08:00" is handled
+  // 17:57 - 8 hours = 09:57
   base::Time::Exploded target_time2 = {2005, 8, 0, 9, 17, 57, 0, 0};
   EXPECT_TRUE(GetTimeFromString("2005-08-09T09:57:00-08:00", &test_time));
   EXPECT_EQ(FormatTime(base::Time::FromUTCExploded(target_time2)),
             FormatTime(test_time));
 
+  // Test that milliseconds (.123) are handled.
   base::Time::Exploded target_time3 = {2005, 1, 0, 7, 8, 2, 0, 123};
   EXPECT_TRUE(GetTimeFromString("2005-01-07T08:02:00.123Z", &test_time));
   EXPECT_EQ(FormatTime(base::Time::FromUTCExploded(target_time3)),
diff --git a/chrome/browser/gpu/OWNERS b/chrome/browser/gpu/OWNERS
index fed3782..92ac858 100644
--- a/chrome/browser/gpu/OWNERS
+++ b/chrome/browser/gpu/OWNERS
@@ -1,5 +1,4 @@
 apatrick@chromium.org
 kbr@chromium.org
-gman@chromium.org
 piman@chromium.org
 zmo@chromium.org
diff --git a/chrome/browser/webview/OWNERS b/chrome/browser/guestview/OWNERS
similarity index 100%
rename from chrome/browser/webview/OWNERS
rename to chrome/browser/guestview/OWNERS
diff --git a/chrome/browser/guestview/adview/adview_constants.cc b/chrome/browser/guestview/adview/adview_constants.cc
new file mode 100644
index 0000000..98790ea
--- /dev/null
+++ b/chrome/browser/guestview/adview/adview_constants.cc
@@ -0,0 +1,12 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/guestview/adview/adview_constants.h"
+
+namespace adview {
+
+// Events.
+const char kEventLoadCommit[] = "adview.onLoadCommit";
+
+}  // namespace adview
diff --git a/chrome/browser/guestview/adview/adview_constants.h b/chrome/browser/guestview/adview/adview_constants.h
new file mode 100644
index 0000000..480bc5c
--- /dev/null
+++ b/chrome/browser/guestview/adview/adview_constants.h
@@ -0,0 +1,18 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Constants used for the adview API.
+
+#ifndef CHROME_BROWSER_GUESTVIEW_ADVIEW_ADVIEW_CONSTANTS_H_
+#define CHROME_BROWSER_GUESTVIEW_ADVIEW_ADVIEW_CONSTANTS_H_
+
+namespace adview {
+
+// Events.
+extern const char kEventLoadCommit[];
+
+}  // namespace adview
+
+#endif  // CHROME_BROWSER_GUESTVIEW_ADVIEW_ADVIEW_CONSTANTS_H_
+
diff --git a/chrome/browser/guestview/adview/adview_guest.cc b/chrome/browser/guestview/adview/adview_guest.cc
new file mode 100644
index 0000000..1f20a21
--- /dev/null
+++ b/chrome/browser/guestview/adview/adview_guest.cc
@@ -0,0 +1,56 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/guestview/adview/adview_guest.h"
+
+#include "chrome/browser/guestview/adview/adview_constants.h"
+#include "chrome/browser/guestview/guestview_constants.h"
+#include "content/public/browser/web_contents.h"
+
+using content::WebContents;
+
+AdViewGuest::AdViewGuest(WebContents* guest_web_contents)
+    : GuestView(guest_web_contents),
+      WebContentsObserver(guest_web_contents) {
+}
+
+// static
+AdViewGuest* AdViewGuest::From(int embedder_process_id,
+                               int guest_instance_id) {
+  GuestView* guest = GuestView::From(embedder_process_id, guest_instance_id);
+  if (!guest)
+    return NULL;
+  return guest->AsAdView();
+}
+
+GuestView::Type AdViewGuest::GetViewType() const {
+  return GuestView::ADVIEW;
+}
+
+WebViewGuest* AdViewGuest::AsWebView() {
+  return NULL;
+}
+
+AdViewGuest* AdViewGuest::AsAdView() {
+  return this;
+}
+
+AdViewGuest::~AdViewGuest() {
+}
+
+void AdViewGuest::DidCommitProvisionalLoadForFrame(
+    int64 frame_id,
+    bool is_main_frame,
+    const GURL& url,
+    content::PageTransition transition_type,
+    content::RenderViewHost* render_view_host) {
+  scoped_ptr<DictionaryValue> args(new DictionaryValue());
+  args->SetString(guestview::kUrl, url.spec());
+  args->SetBoolean(guestview::kIsTopLevel, is_main_frame);
+  DispatchEvent(new GuestView::Event(adview::kEventLoadCommit, args.Pass()));
+}
+
+void AdViewGuest::WebContentsDestroyed(WebContents* web_contents) {
+  delete this;
+}
diff --git a/chrome/browser/guestview/adview/adview_guest.h b/chrome/browser/guestview/adview/adview_guest.h
new file mode 100644
index 0000000..35db3c3
--- /dev/null
+++ b/chrome/browser/guestview/adview/adview_guest.h
@@ -0,0 +1,46 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_GUESTVIEW_ADVIEW_ADVIEW_GUEST_H_
+#define CHROME_BROWSER_GUESTVIEW_ADVIEW_ADVIEW_GUEST_H_
+
+#include "base/values.h"
+#include "chrome/browser/guestview/guestview.h"
+#include "content/public/browser/web_contents_observer.h"
+
+// An AdViewGuest is a WebContentsObserver on the guest WebContents of a
+// <adview> tag. It provides the browser-side implementation of the <adview>
+// API and manages the lifetime of <adview> extension events. AdViewGuest is
+// created on attachment. When a guest WebContents is associated with
+// a particular embedder WebContents, we call this "attachment".
+// TODO(fsamuel): There might be an opportunity here to refactor and reuse code
+// between AdViewGuest and WebViewGuest.
+class AdViewGuest : public GuestView,
+                    public content::WebContentsObserver {
+ public:
+  explicit AdViewGuest(content::WebContents* guest_web_contents);
+
+  static AdViewGuest* From(int embedder_process_id, int instance_id);
+
+  // GuestView implementation.
+  virtual GuestView::Type GetViewType() const OVERRIDE;
+  virtual WebViewGuest* AsWebView() OVERRIDE;
+  virtual AdViewGuest* AsAdView() OVERRIDE;
+
+ private:
+  virtual ~AdViewGuest();
+
+  virtual void DidCommitProvisionalLoadForFrame(
+      int64 frame_id,
+      bool is_main_frame,
+      const GURL& url,
+      content::PageTransition transition_type,
+      content::RenderViewHost* render_view_host) OVERRIDE;
+  virtual void WebContentsDestroyed(
+      content::WebContents* web_contents) OVERRIDE;
+
+  DISALLOW_COPY_AND_ASSIGN(AdViewGuest);
+};
+
+#endif  // CHROME_BROWSER_GUESTVIEW_ADVIEW_ADVIEW_GUEST_H_
diff --git a/chrome/browser/guestview/guestview.cc b/chrome/browser/guestview/guestview.cc
new file mode 100644
index 0000000..502f6db
--- /dev/null
+++ b/chrome/browser/guestview/guestview.cc
@@ -0,0 +1,149 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/guestview/guestview.h"
+
+#include "base/lazy_instance.h"
+#include "chrome/browser/extensions/event_router.h"
+#include "chrome/browser/guestview/guestview_constants.h"
+#include "chrome/browser/profiles/profile.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/web_contents.h"
+
+using content::WebContents;
+
+namespace {
+
+// <embedder_process_id, guest_instance_id> => GuestView*
+typedef std::map<std::pair<int, int>, GuestView*> EmbedderGuestViewMap;
+static base::LazyInstance<EmbedderGuestViewMap> embedder_guestview_map =
+    LAZY_INSTANCE_INITIALIZER;
+
+typedef std::map<WebContents*, GuestView*> WebContentsGuestViewMap;
+static base::LazyInstance<WebContentsGuestViewMap> webcontents_guestview_map =
+    LAZY_INSTANCE_INITIALIZER;
+
+}  // namespace
+
+GuestView::Event::Event(const std::string& event_name,
+                        scoped_ptr<DictionaryValue> args)
+    : event_name_(event_name),
+      args_(args.Pass()) {
+}
+
+GuestView::Event::~Event() {
+}
+
+scoped_ptr<DictionaryValue> GuestView::Event::GetArguments() {
+  return args_.Pass();
+}
+
+GuestView::GuestView(WebContents* guest_web_contents)
+    : guest_web_contents_(guest_web_contents),
+      embedder_web_contents_(NULL),
+      embedder_render_process_id_(0),
+      browser_context_(guest_web_contents->GetBrowserContext()),
+      guest_instance_id_(guest_web_contents->GetEmbeddedInstanceID()),
+      view_instance_id_(guestview::kInstanceIDNone) {
+  webcontents_guestview_map.Get().insert(
+      std::make_pair(guest_web_contents, this));
+}
+
+// static
+GuestView* GuestView::FromWebContents(WebContents* web_contents) {
+  WebContentsGuestViewMap* guest_map = webcontents_guestview_map.Pointer();
+  WebContentsGuestViewMap::iterator it = guest_map->find(web_contents);
+  return it == guest_map->end() ? NULL : it->second;
+}
+
+// static
+GuestView* GuestView::From(int embedder_process_id, int guest_instance_id) {
+  EmbedderGuestViewMap* guest_map = embedder_guestview_map.Pointer();
+  EmbedderGuestViewMap::iterator it = guest_map->find(
+      std::make_pair(embedder_process_id, guest_instance_id));
+  return it == guest_map->end() ? NULL : it->second;
+}
+
+void GuestView::Attach(content::WebContents* embedder_web_contents,
+                       const std::string& extension_id,
+                       int view_instance_id,
+                       const base::DictionaryValue& args) {
+  embedder_web_contents_ = embedder_web_contents;
+  embedder_render_process_id_ =
+      embedder_web_contents->GetRenderProcessHost()->GetID();
+  extension_id_ = extension_id;
+  view_instance_id_ = view_instance_id;
+
+  std::pair<int, int> key(embedder_render_process_id_, guest_instance_id_);
+  embedder_guestview_map.Get().insert(std::make_pair(key, this));
+
+  // GuestView::Attach is called prior to initialization (and initial
+  // navigation) of the guest in the content layer in order to permit mapping
+  // the necessary associations between the <*view> element and its guest. This
+  // is needed by the <webview> WebRequest API to allow intercepting resource
+  // requests during navigation. However, queued events should be fired after
+  // content layer initialization in order to ensure that load events (such as
+  // 'loadstop') fire in embedder after the contentWindow is available.
+  base::MessageLoop::current()->PostTask(
+      FROM_HERE,
+      base::Bind(&GuestView::SendQueuedEvents,
+                  base::Unretained(this)));
+}
+
+GuestView::Type GuestView::GetViewType() const {
+  return GuestView::UNKNOWN;
+}
+
+WebViewGuest* GuestView::AsWebView() {
+  return NULL;
+}
+
+AdViewGuest* GuestView::AsAdView() {
+  return NULL;
+}
+
+GuestView::~GuestView() {
+  std::pair<int, int> key(embedder_render_process_id_, guest_instance_id_);
+  embedder_guestview_map.Get().erase(key);
+
+  webcontents_guestview_map.Get().erase(guest_web_contents());
+
+  while (!pending_events_.empty()) {
+    delete pending_events_.front();
+    pending_events_.pop();
+  }
+}
+
+void GuestView::DispatchEvent(Event* event) {
+  if (!attached()) {
+    pending_events_.push(event);
+    return;
+  }
+
+  Profile* profile = Profile::FromBrowserContext(browser_context_);
+
+  extensions::EventFilteringInfo info;
+  info.SetURL(GURL());
+  info.SetInstanceID(guest_instance_id_);
+  scoped_ptr<ListValue> args(new ListValue());
+  args->Append(event->GetArguments().release());
+
+  extensions::EventRouter::DispatchEvent(
+      embedder_web_contents_, profile, extension_id_,
+      event->event_name(), args.Pass(),
+      extensions::EventRouter::USER_GESTURE_UNKNOWN, info);
+
+  delete event;
+}
+
+void GuestView::SendQueuedEvents() {
+  if (!attached())
+    return;
+
+  while (!pending_events_.empty()) {
+    Event* event = pending_events_.front();
+    pending_events_.pop();
+    DispatchEvent(event);
+  }
+}
diff --git a/chrome/browser/guestview/guestview.h b/chrome/browser/guestview/guestview.h
new file mode 100644
index 0000000..4a0570b
--- /dev/null
+++ b/chrome/browser/guestview/guestview.h
@@ -0,0 +1,116 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_GUESTVIEW_GUESTVIEW_H_
+#define CHROME_BROWSER_GUESTVIEW_GUESTVIEW_H_
+
+#include <queue>
+
+#include "base/values.h"
+#include "content/public/browser/web_contents.h"
+
+class AdViewGuest;
+class WebViewGuest;
+
+// A GuestView is the base class browser-side API implementation for a <*view>
+// tag. GuestView maintains an association between a guest WebContents and an
+// embedder WebContents. It receives events issued from the guest and relays
+// them to the embedder.
+class GuestView {
+ public:
+  enum Type {
+    WEBVIEW,
+    ADVIEW,
+    UNKNOWN
+  };
+
+  class Event {
+   public:
+     Event(const std::string& event_name, scoped_ptr<DictionaryValue> args);
+     ~Event();
+
+    const std::string& event_name() const { return event_name_; }
+
+    scoped_ptr<DictionaryValue> GetArguments();
+
+   private:
+    const std::string event_name_;
+    scoped_ptr<DictionaryValue> args_;
+  };
+
+  explicit GuestView(content::WebContents* guest_web_contents);
+
+  static GuestView* FromWebContents(content::WebContents* web_contents);
+
+  static GuestView* From(int embedder_process_id, int instance_id);
+
+  virtual void Attach(content::WebContents* embedder_web_contents,
+                      const std::string& extension_id,
+                      int view_instance_id,
+                      const base::DictionaryValue& args);
+
+  content::WebContents* embedder_web_contents() const {
+    return embedder_web_contents_;
+  }
+
+  // Returns the guest WebContents.
+  content::WebContents* guest_web_contents() const {
+    return guest_web_contents_;
+  }
+
+  virtual Type GetViewType() const;
+
+  // Returns a WebViewGuest if this GuestView belongs to a <webview>.
+  virtual WebViewGuest* AsWebView() = 0;
+
+  // Returns an AdViewGuest if the GuestView belongs to an <adview>.
+  virtual AdViewGuest* AsAdView() = 0;
+
+  // Returns whether this guest has an associated embedder.
+  bool attached() const { return !!embedder_web_contents_; }
+
+  // Returns the instance ID of the <*view> element.
+  int view_instance_id() const { return view_instance_id_; }
+
+  // Returns the instance ID of the guest WebContents.
+  int guest_instance_id() const { return guest_instance_id_; }
+
+  // Returns the extension ID of the embedder.
+  const std::string& extension_id() const { return extension_id_; }
+
+  // Returns the user browser context of the embedder.
+  content::BrowserContext* browser_context() const { return browser_context_; }
+
+  // Returns the embedder's process ID.
+  int embedder_render_process_id() const { return embedder_render_process_id_; }
+
+ protected:
+  virtual ~GuestView();
+
+  // Dispatches an event |event_name| to the embedder with the |event| fields.
+  void DispatchEvent(Event* event);
+
+ private:
+  void SendQueuedEvents();
+
+  content::WebContents* guest_web_contents_;
+  content::WebContents* embedder_web_contents_;
+  std::string extension_id_;
+  int embedder_render_process_id_;
+  content::BrowserContext* browser_context_;
+  // |guest_instance_id_| is a profile-wide unique identifier for a guest
+  // WebContents.
+  const int guest_instance_id_;
+  // |view_instance_id_| is an identifier that's unique within a particular
+  // embedder RenderViewHost for a particular <*view> instance.
+  int view_instance_id_;
+
+  // This is a queue of Events that are destined to be sent to the embedder once
+  // the guest is attached to a particular embedder.
+  std::queue<Event*> pending_events_;
+
+  DISALLOW_COPY_AND_ASSIGN(GuestView);
+};
+
+#endif  // CHROME_BROWSER_GUESTVIEW_GUESTVIEW_H_
diff --git a/chrome/browser/guestview/guestview_constants.cc b/chrome/browser/guestview/guestview_constants.cc
new file mode 100644
index 0000000..3659bec
--- /dev/null
+++ b/chrome/browser/guestview/guestview_constants.cc
@@ -0,0 +1,19 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/guestview/guestview_constants.h"
+
+namespace guestview {
+
+// Parameters/properties on events.
+const char kIsTopLevel[] = "isTopLevel";
+const char kUrl[] = "url";
+
+// Attributes.
+const char kAttributeApi[] = "api";
+
+// Other.
+const int kInstanceIDNone = 0;
+
+}  // namespace guestview
diff --git a/chrome/browser/guestview/guestview_constants.h b/chrome/browser/guestview/guestview_constants.h
new file mode 100644
index 0000000..70a09a5
--- /dev/null
+++ b/chrome/browser/guestview/guestview_constants.h
@@ -0,0 +1,25 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Constants used for the WebView API.
+
+#ifndef CHROME_BROWSER_GUESTVIEW_GUESTVIEW_CONSTANTS_H_
+#define CHROME_BROWSER_GUESTVIEW_GUESTVIEW_CONSTANTS_H_
+
+namespace guestview {
+
+// Parameters/properties on events.
+extern const char kIsTopLevel[];
+extern const char kUrl[];
+
+// Attributes.
+extern const char kAttributeApi[];
+
+// Other.
+extern const int kInstanceIDNone;
+
+}  // namespace guestview
+
+#endif  // CHROME_BROWSER_GUESTVIEW_GUESTVIEW_CONSTANTS_H_
+
diff --git a/chrome/browser/guestview/webview/webview_constants.cc b/chrome/browser/guestview/webview/webview_constants.cc
new file mode 100644
index 0000000..dd4c8f4
--- /dev/null
+++ b/chrome/browser/guestview/webview/webview_constants.cc
@@ -0,0 +1,25 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/guestview/webview/webview_constants.h"
+
+namespace webview {
+
+// Events.
+const char kEventContentLoad[] = "webview.onContentLoad";
+const char kEventLoadCommit[] = "webview.onLoadCommit";
+const char kEventLoadRedirect[] = "webview.onLoadRedirect";
+const char kEventLoadStart[] = "webview.onLoadStart";
+const char kEventLoadStop[] = "webview.onLoadStop";
+
+// Internal parameters/properties on events.
+const char kInternalCurrentEntryIndex[] = "currentEntryIndex";
+const char kInternalEntryCount[] = "entryCount";
+const char kInternalProcessId[] = "processId";
+
+// Parameters/properties on events.
+extern const char kNewURL[];
+extern const char kOldURL[];
+
+}  // namespace webview
diff --git a/chrome/browser/guestview/webview/webview_constants.h b/chrome/browser/guestview/webview/webview_constants.h
new file mode 100644
index 0000000..01cec96
--- /dev/null
+++ b/chrome/browser/guestview/webview/webview_constants.h
@@ -0,0 +1,31 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Constants used for the WebView API.
+
+#ifndef CHROME_BROWSER_GUESTVIEW_WEBVIEW_WEBVIEW_CONSTANTS_H_
+#define CHROME_BROWSER_GUESTVIEW_WEBVIEW_WEBVIEW_CONSTANTS_H_
+
+namespace webview {
+
+// Events.
+extern const char kEventContentLoad[];
+extern const char kEventLoadCommit[];
+extern const char kEventLoadRedirect[];
+extern const char kEventLoadStart[];
+extern const char kEventLoadStop[];
+
+// Internal parameters/properties on events.
+extern const char kInternalCurrentEntryIndex[];
+extern const char kInternalEntryCount[];
+extern const char kInternalProcessId[];
+
+// Parameters/properties on events.
+const char kNewURL[] = "newUrl";
+const char kOldURL[] = "oldUrl";
+
+}  // namespace webview
+
+#endif  // CHROME_BROWSER_GUESTVIEW_WEBVIEW_WEBVIEW_CONSTANTS_H_
+
diff --git a/chrome/browser/guestview/webview/webview_guest.cc b/chrome/browser/guestview/webview/webview_guest.cc
new file mode 100644
index 0000000..5c15a6f
--- /dev/null
+++ b/chrome/browser/guestview/webview/webview_guest.cc
@@ -0,0 +1,209 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/guestview/webview/webview_guest.h"
+
+#include "chrome/browser/extensions/api/web_request/web_request_api.h"
+#include "chrome/browser/extensions/extension_renderer_state.h"
+#include "chrome/browser/extensions/script_executor.h"
+#include "chrome/browser/guestview/guestview_constants.h"
+#include "chrome/browser/guestview/webview/webview_constants.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/notification_details.h"
+#include "content/public/browser/notification_source.h"
+#include "content/public/browser/notification_types.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/resource_request_details.h"
+#include "content/public/browser/web_contents.h"
+
+using content::WebContents;
+
+namespace {
+
+void RemoveWebViewEventListenersOnIOThread(
+    void* profile,
+    const std::string& extension_id,
+    int embedder_process_id,
+    int guest_instance_id) {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+  ExtensionWebRequestEventRouter::GetInstance()->RemoveWebViewEventListeners(
+      profile, extension_id, embedder_process_id, guest_instance_id);
+}
+
+}  // namespace
+
+WebViewGuest::WebViewGuest(WebContents* guest_web_contents)
+    : GuestView(guest_web_contents),
+      WebContentsObserver(guest_web_contents),
+      script_executor_(new extensions::ScriptExecutor(guest_web_contents,
+                                                      &script_observers_)) {
+  notification_registrar_.Add(
+      this, content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
+      content::Source<WebContents>(guest_web_contents));
+
+  notification_registrar_.Add(
+      this, content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT,
+      content::Source<WebContents>(guest_web_contents));
+}
+
+// static
+WebViewGuest* WebViewGuest::From(int embedder_process_id,
+                                 int guest_instance_id) {
+  GuestView* guest = GuestView::From(embedder_process_id, guest_instance_id);
+  if (!guest)
+    return NULL;
+  return guest->AsWebView();
+}
+
+void WebViewGuest::Attach(WebContents* embedder_web_contents,
+                          const std::string& extension_id,
+                          int view_instance_id,
+                          const base::DictionaryValue& args) {
+  GuestView::Attach(
+      embedder_web_contents, extension_id, view_instance_id, args);
+
+  AddWebViewToExtensionRendererState();
+}
+
+GuestView::Type WebViewGuest::GetViewType() const {
+  return GuestView::WEBVIEW;
+}
+
+WebViewGuest* WebViewGuest::AsWebView() {
+  return this;
+}
+
+AdViewGuest* WebViewGuest::AsAdView() {
+  return NULL;
+}
+
+void WebViewGuest::Observe(int type,
+                           const content::NotificationSource& source,
+                           const content::NotificationDetails& details) {
+  switch (type) {
+    case content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME: {
+      DCHECK_EQ(content::Source<WebContents>(source).ptr(),
+                guest_web_contents());
+      if (content::Source<WebContents>(source).ptr() == guest_web_contents())
+        LoadHandlerCalled();
+      break;
+    }
+    case content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT: {
+      DCHECK_EQ(content::Source<WebContents>(source).ptr(),
+                guest_web_contents());
+      content::ResourceRedirectDetails* resource_redirect_details =
+          content::Details<content::ResourceRedirectDetails>(details).ptr();
+      bool is_top_level =
+          resource_redirect_details->resource_type == ResourceType::MAIN_FRAME;
+      LoadRedirect(resource_redirect_details->url,
+                   resource_redirect_details->new_url,
+                   is_top_level);
+      break;
+    }
+    default:
+      NOTREACHED() << "Unexpected notification sent.";
+      break;
+  }
+}
+
+void WebViewGuest::Go(int relative_index) {
+  guest_web_contents()->GetController().GoToOffset(relative_index);
+}
+
+WebViewGuest::~WebViewGuest() {
+}
+
+void WebViewGuest::DidCommitProvisionalLoadForFrame(
+    int64 frame_id,
+    bool is_main_frame,
+    const GURL& url,
+    content::PageTransition transition_type,
+    content::RenderViewHost* render_view_host) {
+  scoped_ptr<DictionaryValue> args(new DictionaryValue());
+  args->SetString(guestview::kUrl, url.spec());
+  args->SetBoolean(guestview::kIsTopLevel, is_main_frame);
+  args->SetInteger(webview::kInternalCurrentEntryIndex,
+      web_contents()->GetController().GetCurrentEntryIndex());
+  args->SetInteger(webview::kInternalEntryCount,
+      web_contents()->GetController().GetEntryCount());
+  args->SetInteger(webview::kInternalProcessId,
+      web_contents()->GetRenderProcessHost()->GetID());
+  DispatchEvent(new GuestView::Event(webview::kEventLoadCommit, args.Pass()));
+}
+
+void WebViewGuest::DidStartProvisionalLoadForFrame(
+    int64 frame_id,
+    int64 parent_frame_id,
+    bool is_main_frame,
+    const GURL& validated_url,
+    bool is_error_page,
+    bool is_iframe_srcdoc,
+    content::RenderViewHost* render_view_host) {
+  scoped_ptr<DictionaryValue> args(new DictionaryValue());
+  args->SetString(guestview::kUrl, validated_url.spec());
+  args->SetBoolean(guestview::kIsTopLevel, is_main_frame);
+  DispatchEvent(new GuestView::Event(webview::kEventLoadStart, args.Pass()));
+}
+
+void WebViewGuest::DidStopLoading(content::RenderViewHost* render_view_host) {
+  scoped_ptr<DictionaryValue> args(new DictionaryValue());
+  DispatchEvent(new GuestView::Event(webview::kEventLoadStop, args.Pass()));
+}
+
+void WebViewGuest::WebContentsDestroyed(WebContents* web_contents) {
+  RemoveWebViewFromExtensionRendererState(web_contents);
+  content::BrowserThread::PostTask(
+      content::BrowserThread::IO,
+      FROM_HERE,
+      base::Bind(
+          &RemoveWebViewEventListenersOnIOThread,
+          browser_context(), extension_id(),
+          embedder_render_process_id(),
+          view_instance_id()));
+  delete this;
+}
+
+void WebViewGuest::LoadHandlerCalled() {
+  scoped_ptr<DictionaryValue> args(new DictionaryValue());
+  DispatchEvent(new GuestView::Event(webview::kEventContentLoad, args.Pass()));
+}
+
+void WebViewGuest::LoadRedirect(const GURL& old_url,
+                                const GURL& new_url,
+                                bool is_top_level) {
+  scoped_ptr<DictionaryValue> args(new DictionaryValue());
+  args->SetBoolean(guestview::kIsTopLevel, is_top_level);
+  args->SetString(webview::kNewURL, new_url.spec());
+  args->SetString(webview::kOldURL, old_url.spec());
+  DispatchEvent(new GuestView::Event(webview::kEventLoadRedirect, args.Pass()));
+}
+
+void WebViewGuest::AddWebViewToExtensionRendererState() {
+  ExtensionRendererState::WebViewInfo webview_info;
+  webview_info.embedder_process_id = embedder_render_process_id();
+  webview_info.embedder_routing_id = embedder_web_contents()->GetRoutingID();
+  webview_info.guest_instance_id = guest_instance_id();
+  webview_info.instance_id = view_instance_id();
+
+  content::BrowserThread::PostTask(
+      content::BrowserThread::IO, FROM_HERE,
+      base::Bind(
+          &ExtensionRendererState::AddWebView,
+          base::Unretained(ExtensionRendererState::GetInstance()),
+          guest_web_contents()->GetRenderProcessHost()->GetID(),
+          guest_web_contents()->GetRoutingID(),
+          webview_info));
+}
+
+// static
+void WebViewGuest::RemoveWebViewFromExtensionRendererState(
+    WebContents* web_contents) {
+  content::BrowserThread::PostTask(
+      content::BrowserThread::IO, FROM_HERE,
+      base::Bind(
+          &ExtensionRendererState::RemoveWebView,
+          base::Unretained(ExtensionRendererState::GetInstance()),
+          web_contents->GetRenderProcessHost()->GetID(),
+          web_contents->GetRoutingID()));
+}
diff --git a/chrome/browser/guestview/webview/webview_guest.h b/chrome/browser/guestview/webview/webview_guest.h
new file mode 100644
index 0000000..905d346
--- /dev/null
+++ b/chrome/browser/guestview/webview/webview_guest.h
@@ -0,0 +1,99 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_GUESTVIEW_WEBVIEW_WEBVIEW_GUEST_H_
+#define CHROME_BROWSER_GUESTVIEW_WEBVIEW_WEBVIEW_GUEST_H_
+
+#include "base/observer_list.h"
+#include "chrome/browser/extensions/tab_helper.h"
+#include "chrome/browser/guestview/guestview.h"
+#include "content/public/browser/notification_registrar.h"
+#include "content/public/browser/web_contents_observer.h"
+
+namespace extensions {
+class ScriptExecutor;
+}  // namespace extensions
+
+// A WebViewGuest is a WebContentsObserver on the guest WebContents of a
+// <webview> tag. It provides the browser-side implementation of the <webview>
+// API and manages the lifetime of <webview> extension events. WebViewGuest is
+// created on attachment. That is, when a guest WebContents is associated with
+// a particular embedder WebContents. This happens on either initial navigation
+// or through the use of the New Window API, when a new window is attached to
+// a particular <webview>.
+class WebViewGuest : public GuestView,
+                     public content::NotificationObserver,
+                     public content::WebContentsObserver {
+ public:
+  explicit WebViewGuest(content::WebContents* guest_web_contents);
+
+  static WebViewGuest* From(int embedder_process_id, int instance_id);
+
+  // GuestView implementation.
+  virtual void Attach(content::WebContents* embedder_web_contents,
+                      const std::string& extension_id,
+                      int view_instance_id,
+                      const base::DictionaryValue& args) OVERRIDE;
+  virtual GuestView::Type GetViewType() const OVERRIDE;
+  virtual WebViewGuest* AsWebView() OVERRIDE;
+  virtual AdViewGuest* AsAdView() OVERRIDE;
+
+  // NotificationObserver implementation.
+  virtual void Observe(int type,
+                       const content::NotificationSource& source,
+                       const content::NotificationDetails& details) OVERRIDE;
+
+  // If possible, navigate the guest to |relative_index| entries away from the
+  // current navigation entry.
+  void Go(int relative_index);
+
+  extensions::ScriptExecutor* script_executor() {
+    return script_executor_.get();
+  }
+
+ private:
+  virtual ~WebViewGuest();
+
+  // WebContentsObserver implementation.
+  virtual void DidCommitProvisionalLoadForFrame(
+      int64 frame_id,
+      bool is_main_frame,
+      const GURL& url,
+      content::PageTransition transition_type,
+      content::RenderViewHost* render_view_host) OVERRIDE;
+  virtual void DidStartProvisionalLoadForFrame(
+      int64 frame_id,
+      int64 parent_frame_id,
+      bool is_main_frame,
+      const GURL& validated_url,
+      bool is_error_page,
+      bool is_iframe_srcdoc,
+      content::RenderViewHost* render_view_host) OVERRIDE;
+  virtual void DidStopLoading(
+      content::RenderViewHost* render_view_host) OVERRIDE;
+  virtual void WebContentsDestroyed(
+      content::WebContents* web_contents) OVERRIDE;
+
+  // Called after the load handler is called in the guest's main frame.
+  void LoadHandlerCalled();
+
+  // Called when a redirect notification occurs.
+  void LoadRedirect(const GURL& old_url,
+                    const GURL& new_url,
+                    bool is_top_level);
+
+  void AddWebViewToExtensionRendererState();
+  static void RemoveWebViewFromExtensionRendererState(
+      content::WebContents* web_contents);
+
+  ObserverList<extensions::TabHelper::ScriptExecutionObserver>
+      script_observers_;
+  scoped_ptr<extensions::ScriptExecutor> script_executor_;
+
+  content::NotificationRegistrar notification_registrar_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebViewGuest);
+};
+
+#endif  // CHROME_BROWSER_GUESTVIEW_WEBVIEW_WEBVIEW_GUEST_H_
diff --git a/chrome/browser/history/android/android_cache_database.cc b/chrome/browser/history/android/android_cache_database.cc
index 52a0d40..1fdd981 100644
--- a/chrome/browser/history/android/android_cache_database.cc
+++ b/chrome/browser/history/android/android_cache_database.cc
@@ -174,8 +174,7 @@
 
 bool AndroidCacheDatabase::CreateDatabase(const base::FilePath& db_name) {
   db_name_ = db_name;
-  if (file_util::PathExists(db_name_))
-    file_util::Delete(db_name_, false);
+  sql::Connection::Delete(db_name_);
 
   // Using a new connection, otherwise we can not create the database.
   sql::Connection connection;
diff --git a/chrome/browser/history/android/android_cache_database.h b/chrome/browser/history/android/android_cache_database.h
index ac6d1c4..4f4dd19 100644
--- a/chrome/browser/history/android/android_cache_database.h
+++ b/chrome/browser/history/android/android_cache_database.h
@@ -7,7 +7,7 @@
 
 #include "base/files/file_path.h"
 #include "base/gtest_prod_util.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/history/android/android_history_types.h"
 #include "sql/connection.h"
 #include "sql/init_status.h"
diff --git a/chrome/browser/history/android/android_history_provider_service_unittest.cc b/chrome/browser/history/android/android_history_provider_service_unittest.cc
index 626bf8a..7919849 100644
--- a/chrome/browser/history/android/android_history_provider_service_unittest.cc
+++ b/chrome/browser/history/android/android_history_provider_service_unittest.cc
@@ -5,7 +5,7 @@
 #include "chrome/browser/history/android/android_history_provider_service.h"
 
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/history/android/android_history_types.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/test/base/testing_browser_process.h"
diff --git a/chrome/browser/history/android/android_time.h b/chrome/browser/history/android/android_time.h
index f9499fa..a2f3fee 100644
--- a/chrome/browser/history/android/android_time.h
+++ b/chrome/browser/history/android/android_time.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_HISTORY_ANDROID_ANDROID_TIME_H_
 #define CHROME_BROWSER_HISTORY_ANDROID_ANDROID_TIME_H_
 
-#include "base/time.h"
+#include "base/time/time.h"
 
 namespace history {
 
diff --git a/chrome/browser/history/android/favicon_sql_handler.cc b/chrome/browser/history/android/favicon_sql_handler.cc
index 0028184..6c0c3d7 100644
--- a/chrome/browser/history/android/favicon_sql_handler.cc
+++ b/chrome/browser/history/android/favicon_sql_handler.cc
@@ -40,7 +40,6 @@
   chrome::FaviconID favicon_id = thumbnail_db_->AddFavicon(
       GURL(),
       chrome::FAVICON,
-      history::GetDefaultFaviconSizes(),
       row.favicon(),
       Time::Now(),
       gfx::Size());
@@ -110,7 +109,6 @@
   chrome::FaviconID id = thumbnail_db_->AddFavicon(
       GURL(),
       chrome::FAVICON,
-      history::GetDefaultFaviconSizes(),
       row->favicon(),
       Time::Now(),
       gfx::Size());
diff --git a/chrome/browser/history/android/sqlite_cursor_unittest.cc b/chrome/browser/history/android/sqlite_cursor_unittest.cc
index ac97f2f..7491cd1 100644
--- a/chrome/browser/history/android/sqlite_cursor_unittest.cc
+++ b/chrome/browser/history/android/sqlite_cursor_unittest.cc
@@ -10,7 +10,7 @@
 #include "base/android/jni_array.h"
 #include "base/android/jni_string.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/history/android/android_history_provider_service.h"
 #include "chrome/browser/history/android/android_history_types.h"
 #include "chrome/browser/history/android/android_time.h"
diff --git a/chrome/browser/history/delete_directive_handler.cc b/chrome/browser/history/delete_directive_handler.cc
index f87ac9c..c08bf77 100644
--- a/chrome/browser/history/delete_directive_handler.cc
+++ b/chrome/browser/history/delete_directive_handler.cc
@@ -6,7 +6,7 @@
 
 #include "base/json/json_writer.h"
 #include "base/rand_util.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/history/history_backend.h"
 #include "chrome/browser/history/history_db_task.h"
@@ -344,6 +344,7 @@
   if (!sync_processor_) {
     return syncer::SyncError(
         FROM_HERE,
+        syncer::SyncError::DATATYPE_ERROR,
         "Cannot send local delete directive to sync",
         syncer::HISTORY_DELETE_DIRECTIVES);
   }
@@ -372,7 +373,10 @@
   DCHECK(thread_checker_.CalledOnValidThread());
   if (!sync_processor_) {
     return syncer::SyncError(
-        FROM_HERE, "Sync is disabled.", syncer::HISTORY_DELETE_DIRECTIVES);
+        FROM_HERE,
+        syncer::SyncError::DATATYPE_ERROR,
+        "Sync is disabled.",
+        syncer::HISTORY_DELETE_DIRECTIVES);
   }
 
   syncer::SyncDataList delete_directives;
diff --git a/chrome/browser/history/download_database.cc b/chrome/browser/history/download_database.cc
index c21734d..4d1d70e 100644
--- a/chrome/browser/history/download_database.cc
+++ b/chrome/browser/history/download_database.cc
@@ -15,7 +15,7 @@
 #include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "build/build_config.h"
 #include "chrome/browser/history/download_row.h"
 #include "chrome/browser/history/history_types.h"
@@ -37,18 +37,19 @@
 };
 
 static const char kSchema[] =
-  "CREATE TABLE downloads ("
-  "id INTEGER PRIMARY KEY,"           // Primary key.
-  "current_path LONGVARCHAR NOT NULL,"  // Current disk location of the download
-  "target_path LONGVARCHAR NOT NULL,"  // Final disk location of the download
-  "start_time INTEGER NOT NULL,"      // When the download was started.
-  "received_bytes INTEGER NOT NULL,"  // Total size downloaded.
-  "total_bytes INTEGER NOT NULL,"     // Total size of the download.
-  "state INTEGER NOT NULL,"           // 1=complete, 4=interrupted
-  "danger_type INTEGER NOT NULL, "    // Not dangerous, danger type, validated.
-  "interrupt_reason INTEGER NOT NULL,"  // Reason the download was interrupted.
-  "end_time INTEGER NOT NULL,"        // When the download completed.
-  "opened INTEGER NOT NULL)";         // 1 if it has ever been opened else 0
+    "CREATE TABLE downloads ("
+    "id INTEGER PRIMARY KEY,"  // Primary key.
+    "current_path LONGVARCHAR NOT NULL,"  // Current disk location
+    "target_path LONGVARCHAR NOT NULL,"  // Final disk location
+    "start_time INTEGER NOT NULL,"  // When the download was started.
+    "received_bytes INTEGER NOT NULL,"  // Total size downloaded.
+    "total_bytes INTEGER NOT NULL,"  // Total size of the download.
+    "state INTEGER NOT NULL,"  // 1=complete, 4=interrupted
+    "danger_type INTEGER NOT NULL, "  // Not dangerous, danger type, validated.
+    "interrupt_reason INTEGER NOT NULL,"
+    "end_time INTEGER NOT NULL,"  // When the download completed.
+    "opened INTEGER NOT NULL,"  // 1 if it has ever been opened else 0
+    "referrer VARCHAR NOT NULL)";  // HTTP Referrer
 
 static const char kUrlChainSchema[] =
     "CREATE TABLE downloads_url_chains ("
@@ -234,7 +235,7 @@
   sql::Statement statement_populate(GetDB().GetUniqueStatement(
     "INSERT INTO downloads "
     "( id, current_path, target_path, start_time, received_bytes, total_bytes, "
-    "  state, danger_type, interrupt_reason, end_time, opened ) "
+    "  state, danger_type, interrupt_reason, end_time, opened, referrer ) "
     "SELECT id, full_path, full_path, "
     "       CASE start_time WHEN 0 THEN 0 ELSE "
     "            (start_time + 11644473600) * 1000000 END, "
@@ -242,7 +243,7 @@
     "       state, ?, ?, "
     "       CASE end_time WHEN 0 THEN 0 ELSE "
     "            (end_time + 11644473600) * 1000000 END, "
-    "       opened "
+    "       opened, \"\" "
     "FROM downloads_tmp"));
   statement_populate.BindInt(0, content::DOWNLOAD_INTERRUPT_REASON_NONE);
   statement_populate.BindInt(1, kDangerTypeNotDangerous);
@@ -265,6 +266,10 @@
   return true;
 }
 
+bool DownloadDatabase::MigrateReferrer() {
+  return EnsureColumnExists("referrer", "VARCHAR NOT NULL DEFAULT \"\"");
+}
+
 bool DownloadDatabase::InitDownloadTable() {
   GetMetaTable().GetValue(kNextDownloadId, &next_id_);
   if (GetDB().DoesTableExist("downloads")) {
@@ -295,9 +300,9 @@
 
   sql::Statement statement_main(GetDB().GetCachedStatement(SQL_FROM_HERE,
       "SELECT id, current_path, target_path, start_time, received_bytes, "
-        "total_bytes, state, danger_type, interrupt_reason, end_time, opened "
-      "FROM downloads "
-      "ORDER BY start_time"));
+      "total_bytes, state, danger_type, interrupt_reason, end_time, opened, "
+      "referrer "
+      "FROM downloads ORDER BY start_time"));
 
   while (statement_main.Step()) {
     scoped_ptr<DownloadRow> info(new DownloadRow());
@@ -321,6 +326,7 @@
     info->end_time = base::Time::FromInternalValue(
         statement_main.ColumnInt64(column++));
     info->opened = statement_main.ColumnInt(column++) != 0;
+    info->referrer_url = GURL(statement_main.ColumnString(column++));
     if (info->db_handle >= next_db_handle_)
       next_db_handle_ = info->db_handle + 1;
     if (!db_handles.insert(info->db_handle).second) {
@@ -482,8 +488,8 @@
         "INSERT INTO downloads "
         "(id, current_path, target_path, start_time, "
         " received_bytes, total_bytes, state, danger_type, interrupt_reason, "
-        " end_time, opened) "
-        "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"));
+        " end_time, opened, referrer) "
+        "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"));
 
     int column = 0;
     statement_insert.BindInt64(column++, db_handle);
@@ -497,6 +503,7 @@
     statement_insert.BindInt(column++, info.interrupt_reason);
     statement_insert.BindInt64(column++, info.end_time.ToInternalValue());
     statement_insert.BindInt(column++, info.opened ? 1 : 0);
+    statement_insert.BindString(column++, info.referrer_url.spec());
     if (!statement_insert.Run()) {
       // GetErrorCode() returns a bitmask where the lower byte is a more general
       // code and the upper byte is a more specific code. In order to save
diff --git a/chrome/browser/history/download_database.h b/chrome/browser/history/download_database.h
index afb5fd0..ef85279 100644
--- a/chrome/browser/history/download_database.h
+++ b/chrome/browser/history/download_database.h
@@ -67,6 +67,10 @@
   // two target paths to downloads.
   bool MigrateDownloadsReasonPathsAndDangerType();
 
+  // Returns true if able to successfully add the referrer column to the
+  // downloads table.
+  bool MigrateReferrer();
+
   // Creates the downloads table if needed.
   bool InitDownloadTable();
 
diff --git a/chrome/browser/history/download_row.h b/chrome/browser/history/download_row.h
index 2f8b63b..7e91655 100644
--- a/chrome/browser/history/download_row.h
+++ b/chrome/browser/history/download_row.h
@@ -8,11 +8,11 @@
 #include <vector>
 
 #include "base/files/file_path.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "content/public/browser/download_danger_type.h"
 #include "content/public/browser/download_interrupt_reasons.h"
 #include "content/public/browser/download_item.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 namespace history {
 
diff --git a/chrome/browser/history/expire_history_backend.cc b/chrome/browser/history/expire_history_backend.cc
index 6652aca..4e46a2e 100644
--- a/chrome/browser/history/expire_history_backend.cc
+++ b/chrome/browser/history/expire_history_backend.cc
@@ -382,11 +382,9 @@
     if (!thumb_db_->HasMappingFor(*i)) {
       GURL icon_url;
       chrome::IconType icon_type;
-      FaviconSizes favicon_sizes;
       if (thumb_db_->GetFaviconHeader(*i,
                                       &icon_url,
-                                      &icon_type,
-                                      &favicon_sizes) &&
+                                      &icon_type) &&
           thumb_db_->DeleteFavicon(*i)) {
         expired_favicons->insert(icon_url);
       }
@@ -762,7 +760,7 @@
        file = file_enumerator.Next()) {
     TextDatabase::DBIdent file_id = TextDatabase::FileNameToID(file);
     if (file_id < cutoff_id)
-      file_util::Delete(file, false);
+      sql::Connection::Delete(file);
   }
 }
 
diff --git a/chrome/browser/history/expire_history_backend.h b/chrome/browser/history/expire_history_backend.h
index a7e8cdd..626ad12 100644
--- a/chrome/browser/history/expire_history_backend.h
+++ b/chrome/browser/history/expire_history_backend.h
@@ -13,7 +13,7 @@
 #include "base/gtest_prod_util.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/history/history_types.h"
 
 class BookmarkService;
diff --git a/chrome/browser/history/expire_history_backend_unittest.cc b/chrome/browser/history/expire_history_backend_unittest.cc
index 37155bb..415d6b2 100644
--- a/chrome/browser/history/expire_history_backend_unittest.cc
+++ b/chrome/browser/history/expire_history_backend_unittest.cc
@@ -211,9 +211,9 @@
   // Two favicons. The first two URLs will share the same one, while the last
   // one will have a unique favicon.
   chrome::FaviconID favicon1 = thumb_db_->AddFavicon(
-      GURL("http://favicon/url1"), chrome::FAVICON, GetDefaultFaviconSizes());
+      GURL("http://favicon/url1"), chrome::FAVICON);
   chrome::FaviconID favicon2 = thumb_db_->AddFavicon(
-      GURL("http://favicon/url2"), chrome::FAVICON, GetDefaultFaviconSizes());
+      GURL("http://favicon/url2"), chrome::FAVICON);
 
   // Three URLs.
   URLRow url_row1(GURL("http://www.google.com/1"));
@@ -325,7 +325,7 @@
 bool ExpireHistoryTest::HasFavicon(chrome::FaviconID favicon_id) {
   if (!thumb_db_.get() || favicon_id == 0)
     return false;
-  return thumb_db_->GetFaviconHeader(favicon_id, NULL, NULL, NULL);
+  return thumb_db_->GetFaviconHeader(favicon_id, NULL, NULL);
 }
 
 chrome::FaviconID ExpireHistoryTest::GetFavicon(const GURL& page_url,
@@ -410,7 +410,7 @@
   // Add a favicon record.
   const GURL favicon_url("http://www.google.com/favicon.ico");
   chrome::FaviconID icon_id = thumb_db_->AddFavicon(
-      favicon_url, chrome::FAVICON, GetDefaultFaviconSizes());
+      favicon_url, chrome::FAVICON);
   EXPECT_TRUE(icon_id);
   EXPECT_TRUE(HasFavicon(icon_id));
 
@@ -425,7 +425,7 @@
 
   // Add back the favicon.
   icon_id = thumb_db_->AddFavicon(
-      favicon_url, chrome::TOUCH_ICON, GetDefaultFaviconSizes());
+      favicon_url, chrome::TOUCH_ICON);
   EXPECT_TRUE(icon_id);
   EXPECT_TRUE(HasFavicon(icon_id));
 
diff --git a/chrome/browser/history/history_backend.cc b/chrome/browser/history/history_backend.cc
index 614d93a..ed1419c 100644
--- a/chrome/browser/history/history_backend.cc
+++ b/chrome/browser/history/history_backend.cc
@@ -14,7 +14,6 @@
 #include "base/basictypes.h"
 #include "base/bind.h"
 #include "base/compiler_specific.h"
-#include "base/file_util.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/scoped_vector.h"
 #include "base/message_loop.h"
@@ -22,11 +21,10 @@
 #include "base/rand_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/autocomplete/history_url_provider.h"
 #include "chrome/browser/bookmarks/bookmark_service.h"
 #include "chrome/browser/favicon/favicon_changed_details.h"
-#include "chrome/browser/favicon/imported_favicon_usage.h"
 #include "chrome/browser/history/download_row.h"
 #include "chrome/browser/history/history_db_task.h"
 #include "chrome/browser/history/history_notifications.h"
@@ -39,12 +37,13 @@
 #include "chrome/browser/history/visit_filter.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_notification_types.h"
+#include "chrome/common/importer/imported_favicon_usage.h"
 #include "chrome/common/url_constants.h"
-#include "googleurl/src/gurl.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
 #include "sql/error_delegate_util.h"
+#include "url/gurl.h"
 
 #if defined(OS_ANDROID)
 #include "chrome/browser/history/android/android_provider_backend.h"
@@ -103,6 +102,11 @@
 // and is archived.
 static const int kArchiveDaysThreshold = 90;
 
+#if defined(OS_ANDROID)
+// The maximum number of top sites to track when recording top page visit stats.
+static const size_t kPageVisitStatsMaxTopSites = 50;
+#endif
+
 // Converts from PageUsageData to MostVisitedURL. |redirects| is a
 // list of redirects for this URL. Empty list means no redirects.
 MostVisitedURL MakeMostVisitedURL(const PageUsageData& page_data,
@@ -247,7 +251,7 @@
   }
 
 #if defined(OS_ANDROID)
-  file_util::Delete(GetAndroidCacheFileName(), false);
+  sql::Connection::Delete(GetAndroidCacheFileName());
 #endif
 }
 
@@ -256,6 +260,9 @@
     InitImpl(languages);
   delegate_->DBLoaded(id_);
   typed_url_syncable_service_.reset(new TypedUrlSyncableService(this));
+#if defined(OS_ANDROID)
+  PopulateMostVisitedURLMap();
+#endif
 }
 
 void HistoryBackend::SetOnBackendDestroyTask(base::MessageLoop* message_loop,
@@ -706,7 +713,7 @@
     // See needs_version_17_migration() decl for more. In this case, we want
     // to delete the archived database and need to do so before we try to
     // open the file. We can ignore any error (maybe the file doesn't exist).
-    file_util::Delete(archived_name, false);
+    sql::Connection::Delete(archived_name);
   }
   archived_db_.reset(new ArchivedDatabase());
   if (!archived_db_->Init(archived_name)) {
@@ -800,6 +807,15 @@
       transition_type == content::PAGE_TRANSITION_KEYWORD_GENERATED)
     typed_increment = 1;
 
+#if defined(OS_ANDROID)
+  // Only count the page visit if it came from user browsing and only count it
+  // once when cycling through a redirect chain.
+  if (visit_source == SOURCE_BROWSED &&
+      (transition & content::PAGE_TRANSITION_CHAIN_END) != 0) {
+    RecordTopPageVisitStats(url);
+  }
+#endif
+
   // See if this URL is already in the DB.
   URLRow url_info(url);
   URLID url_id = db_->GetRowForURL(url, &url_info);
@@ -1358,8 +1374,14 @@
       // if (archived_db_.get() &&
       //     expirer_.GetCurrentArchiveTime() - TimeDelta::FromDays(7)) {
     } else {
-      // Full text history query.
-      QueryHistoryFTS(text_query, options, &request->value);
+      // Text history query.
+      QueryHistoryText(db_.get(), db_.get(), text_query, options,
+                       &request->value);
+      if (archived_db_.get() &&
+          expirer_.GetCurrentArchiveTime() >= options.begin_time) {
+        QueryHistoryText(archived_db_.get(), archived_db_.get(), text_query,
+                         options, &request->value);
+      }
     }
   }
 
@@ -1424,6 +1446,43 @@
     result->set_reached_beginning(true);
 }
 
+// Text-based querying of history.
+void HistoryBackend::QueryHistoryText(URLDatabase* url_db,
+                                      VisitDatabase* visit_db,
+                                      const string16& text_query,
+                                      const QueryOptions& options,
+                                      QueryResults* result) {
+  URLRows text_matches;
+  url_db->GetTextMatches(text_query, &text_matches);
+
+  std::vector<URLResult> matching_visits;
+  VisitVector visits;    // Declare outside loop to prevent re-construction.
+  for (size_t i = 0; i < text_matches.size(); i++) {
+    const URLRow& text_match = text_matches[i];
+    // Get all visits for given URL match.
+    visit_db->GetVisitsForURLWithOptions(text_match.id(), options, &visits);
+    for (size_t j = 0; j < visits.size(); j++) {
+      URLResult url_result(text_match);
+      url_result.set_visit_time(visits[j].visit_time);
+      matching_visits.push_back(url_result);
+    }
+  }
+
+  std::sort(matching_visits.begin(), matching_visits.end(),
+            URLResult::CompareVisitTime);
+
+  size_t max_results = options.max_count == 0 ?
+      std::numeric_limits<size_t>::max() : static_cast<int>(options.max_count);
+  for (std::vector<URLResult>::iterator it = matching_visits.begin();
+       it != matching_visits.end() && result->size() < max_results; ++it) {
+    result->AppendURLBySwapping(&(*it));
+  }
+
+  if (matching_visits.size() == result->size() &&
+      options.begin_time <= first_recorded_time_)
+    result->set_reached_beginning(true);
+}
+
 void HistoryBackend::QueryHistoryFTS(const string16& text_query,
                                      const QueryOptions& options,
                                      QueryResults* result) {
@@ -1923,8 +1982,7 @@
 
   if (!favicon_id) {
     // There is no favicon at |icon_url|, create it.
-    favicon_id = thumbnail_db_->AddFavicon(icon_url, icon_type,
-                                           GetDefaultFaviconSizes());
+    favicon_id = thumbnail_db_->AddFavicon(icon_url, icon_type);
   }
 
   std::vector<FaviconBitmapIDSize> bitmap_id_sizes;
@@ -2083,8 +2141,7 @@
     if (!icon_id) {
       // TODO(pkotwicz): Remove the favicon sizes attribute from
       // ThumbnailDatabase::AddFavicon().
-      icon_id = thumbnail_db_->AddFavicon(icon_url, icon_type,
-                                          GetDefaultFaviconSizes());
+      icon_id = thumbnail_db_->AddFavicon(icon_url, icon_type);
       data_modified = true;
     }
     icon_ids.push_back(icon_id);
@@ -2153,7 +2210,6 @@
       favicon_id = thumbnail_db_->AddFavicon(
           favicon_usage[i].favicon_url,
           chrome::FAVICON,
-          GetDefaultFaviconSizes(),
           new base::RefCountedBytes(favicon_usage[i].png_data),
           now,
           gfx::Size());
@@ -2438,7 +2494,7 @@
   GURL icon_url;
   chrome::IconType icon_type;
   if (!thumbnail_db_->GetFaviconHeader(best_favicon_id, &icon_url,
-                                       &icon_type, NULL)) {
+                                       &icon_type)) {
     return false;
   }
 
@@ -2934,7 +2990,7 @@
     // Close the database and delete the file.
     archived_db_.reset();
     base::FilePath archived_file_name = GetArchivedFileName();
-    file_util::Delete(archived_file_name, false);
+    sql::Connection::Delete(archived_file_name);
 
     // Now re-initialize the database (which may fail).
     archived_db_.reset(new ArchivedDatabase());
@@ -2963,7 +3019,7 @@
     // error opening it. In this case, we just try to blow it away to try to
     // fix the error if it exists. This may fail, in which case either the
     // file doesn't exist or there's no more we can do.
-    file_util::Delete(GetThumbnailFileName(), false);
+    sql::Connection::Delete(GetThumbnailFileName());
     return true;
   }
 
@@ -3074,4 +3130,28 @@
     delegate_->NotifyVisitDBObserversOnAddVisit(info);
 }
 
+#if defined(OS_ANDROID)
+void HistoryBackend::PopulateMostVisitedURLMap() {
+  MostVisitedURLList most_visited_urls;
+  QueryMostVisitedURLsImpl(kPageVisitStatsMaxTopSites, kSegmentDataRetention,
+                           &most_visited_urls);
+
+  DCHECK_LE(most_visited_urls.size(), kPageVisitStatsMaxTopSites);
+  for (size_t i = 0; i < most_visited_urls.size(); ++i) {
+    most_visited_urls_map_[most_visited_urls[i].url] = i;
+    for (size_t j = 0; j < most_visited_urls[i].redirects.size(); ++j)
+      most_visited_urls_map_[most_visited_urls[i].redirects[j]] = i;
+  }
+}
+
+void HistoryBackend::RecordTopPageVisitStats(const GURL& url) {
+  int rank = kPageVisitStatsMaxTopSites;
+  std::map<GURL, int>::const_iterator it = most_visited_urls_map_.find(url);
+  if (it != most_visited_urls_map_.end())
+    rank = (*it).second;
+  UMA_HISTOGRAM_ENUMERATION("History.TopSitesVisitsByRank",
+                            rank, kPageVisitStatsMaxTopSites + 1);
+}
+#endif
+
 }  // namespace history
diff --git a/chrome/browser/history/history_backend.h b/chrome/browser/history/history_backend.h
index a55d6eb..188847b 100644
--- a/chrome/browser/history/history_backend.h
+++ b/chrome/browser/history/history_backend.h
@@ -578,6 +578,18 @@
 #if defined(OS_ANDROID)
   // Returns the name of android cache database.
   base::FilePath GetAndroidCacheFileName() const;
+
+  // Populate a map from a |MostVisitedURLList|. The map assigns a rank to each
+  // top URL and its redirects. This should only be done once at backend
+  // initialization.
+  // This can be removed for M31. (See issue 248761.)
+
+  void PopulateMostVisitedURLMap();
+  // Record counts of page visits by rank. If a url is not ranked, record the
+  // page visit in a slot corresponding to |max_top_url_count|, which should
+  // be one greater than the largest rank of any url in |top_urls|.
+  // This can be removed for M31. (See issue 248761.)
+  void RecordTopPageVisitStats(const GURL& url);
 #endif
 
   class URLQuerier;
@@ -629,12 +641,18 @@
 
   // Querying ------------------------------------------------------------------
 
-  // Backends for QueryHistory. *Basic() handles queries that are not FTS (full
-  // text search) queries and can just be given directly to the history DB).
-  // The FTS version queries the text_database, then merges with the history DB.
+  // Backends for QueryHistory. *Basic() handles queries that are not
+  // text search queries and can just be given directly to the history DB.
+  // The *Text() version performs a brute force query of the history DB to
+  // search for results which match the given text query.
   // Both functions assume QueryHistory already checked the DB for validity.
   void QueryHistoryBasic(URLDatabase* url_db, VisitDatabase* visit_db,
                          const QueryOptions& options, QueryResults* result);
+  void QueryHistoryText(URLDatabase* url_db,
+                        VisitDatabase* visit_db,
+                        const string16& text_query,
+                        const QueryOptions& options,
+                        QueryResults* result);
   void QueryHistoryFTS(const string16& text_query,
                        const QueryOptions& options,
                        QueryResults* result);
@@ -909,6 +927,12 @@
 #if defined(OS_ANDROID)
   // Used to provide the Android ContentProvider APIs.
   scoped_ptr<AndroidProviderBackend> android_provider_backend_;
+
+  // Used to provide UMA on the number of page visits that are to the most
+  // visited URLs. This is here because the backend both has access to this
+  // information and is notified of page visits. The top sites service should
+  // be used instead whenever possible.
+  std::map<GURL, int> most_visited_urls_map_;
 #endif
 
   // Used to manage syncing of the typed urls datatype. This will be NULL
diff --git a/chrome/browser/history/history_backend_unittest.cc b/chrome/browser/history/history_backend_unittest.cc
index faf15f4..75b426b 100644
--- a/chrome/browser/history/history_backend_unittest.cc
+++ b/chrome/browser/history/history_backend_unittest.cc
@@ -21,7 +21,6 @@
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/browser/bookmarks/bookmark_utils.h"
-#include "chrome/browser/favicon/imported_favicon_usage.h"
 #include "chrome/browser/history/history_backend.h"
 #include "chrome/browser/history/history_notifications.h"
 #include "chrome/browser/history/history_service.h"
@@ -32,6 +31,7 @@
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
+#include "chrome/common/importer/imported_favicon_usage.h"
 #include "chrome/common/thumbnail_score.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/ui_test_utils.h"
@@ -39,11 +39,11 @@
 #include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_source.h"
 #include "content/public/test/test_browser_thread.h"
-#include "googleurl/src/gurl.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/gfx/codec/jpeg_codec.h"
 #include "ui/gfx/image/image.h"
+#include "url/gurl.h"
 
 using base::Time;
 using base::TimeDelta;
@@ -75,7 +75,7 @@
   return a.pixel_size.GetArea() < b.pixel_size.GetArea();
 }
 
-}  // namepace
+}  // namespace
 
 namespace history {
 
@@ -391,7 +391,8 @@
       backend_->Closing();
     backend_ = NULL;
     mem_backend_.reset();
-    file_util::Delete(test_dir_, true);
+    base::Delete(test_dir_, true);
+    base::RunLoop().RunUntilIdle();
   }
 
   void SetInMemoryBackend(int backend_id, InMemoryHistoryBackend* backend) {
@@ -460,9 +461,9 @@
   GURL favicon_url1("http://www.google.com/favicon.ico");
   GURL favicon_url2("http://news.google.com/favicon.ico");
   chrome::FaviconID favicon2 = backend_->thumbnail_db_->AddFavicon(favicon_url2,
-      chrome::FAVICON, GetSizesSmallAndLarge());
+      chrome::FAVICON);
   chrome::FaviconID favicon1 = backend_->thumbnail_db_->AddFavicon(favicon_url1,
-      chrome::FAVICON, GetSizesSmallAndLarge());
+      chrome::FAVICON);
 
   std::vector<unsigned char> data;
   data.push_back('a');
@@ -688,7 +689,6 @@
   chrome::FaviconID favicon1 = backend_->thumbnail_db_->AddFavicon(
       favicon_url1,
       chrome::FAVICON,
-      GetDefaultFaviconSizes(),
       new base::RefCountedBytes(data),
       Time::Now(),
       gfx::Size());
@@ -697,7 +697,6 @@
   chrome::FaviconID favicon2 = backend_->thumbnail_db_->AddFavicon(
       favicon_url2,
       chrome::FAVICON,
-      GetDefaultFaviconSizes(),
       new base::RefCountedBytes(data),
       Time::Now(),
       gfx::Size());
@@ -870,7 +869,6 @@
   chrome::FaviconID favicon1 = backend_->thumbnail_db_->AddFavicon(
       favicon_url1,
       chrome::FAVICON,
-      GetDefaultFaviconSizes(),
       base::RefCountedBytes::TakeVector(&data),
       Time::Now(),
       gfx::Size());
@@ -1277,7 +1275,7 @@
   // Copy history database file to current directory so that it will be deleted
   // in Teardown.
   base::FilePath new_history_path(getTestDir());
-  file_util::Delete(new_history_path, true);
+  base::Delete(new_history_path, true);
   file_util::CreateDirectory(new_history_path);
   base::FilePath new_history_file =
       new_history_path.Append(chrome::kHistoryFilename);
@@ -2072,7 +2070,7 @@
   const GURL icon_url("http://www.google.com/icon1");
 
   chrome::FaviconID icon_id = backend_->thumbnail_db_->AddFavicon(
-      icon_url, chrome::FAVICON, GetSizesSmallAndLarge());
+      icon_url, chrome::FAVICON);
   EXPECT_NE(0, icon_id);
   EXPECT_NE(0, backend_->thumbnail_db_->AddIconMapping(page_url, icon_id));
 
@@ -2197,7 +2195,6 @@
   chrome::FaviconID icon_id =
       backend_->thumbnail_db_->AddFavicon(icon_url,
                                           chrome::FAVICON,
-                                          GetSizesSmallAndLarge(),
                                           bitmap_data,
                                           last_updated,
                                           kSmallSize);
@@ -2517,7 +2514,7 @@
   // Copy history database file to current directory so that it will be deleted
   // in Teardown.
   base::FilePath new_history_path(getTestDir());
-  file_util::Delete(new_history_path, true);
+  base::Delete(new_history_path, true);
   file_util::CreateDirectory(new_history_path);
   base::FilePath new_history_file =
       new_history_path.Append(chrome::kHistoryFilename);
diff --git a/chrome/browser/history/history_browsertest.cc b/chrome/browser/history/history_browsertest.cc
index a7831ff..a563511 100644
--- a/chrome/browser/history/history_browsertest.cc
+++ b/chrome/browser/history/history_browsertest.cc
@@ -25,7 +25,7 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_browser_thread.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 using content::BrowserThread;
 
diff --git a/chrome/browser/history/history_database.cc b/chrome/browser/history/history_database.cc
index 9be2f15..4c49ee8 100644
--- a/chrome/browser/history/history_database.cc
+++ b/chrome/browser/history/history_database.cc
@@ -13,7 +13,7 @@
 #include "base/metrics/histogram.h"
 #include "base/rand_util.h"
 #include "base/strings/string_util.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "sql/transaction.h"
 
 #if defined(OS_MACOSX)
@@ -27,7 +27,7 @@
 // Current version number. We write databases at the "current" version number,
 // but any previous version that can read the "compatible" one can make do with
 // or database without *too* many bad effects.
-static const int kCurrentVersionNumber = 25;
+static const int kCurrentVersionNumber = 26;
 static const int kCompatibleVersionNumber = 16;
 static const char kEarlyExpirationThresholdKey[] = "early_expiration_threshold";
 
@@ -56,11 +56,11 @@
   // this is a NOP. Must be a power of 2 and a max of 8192.
   db_.set_page_size(4096);
 
-  // Increase the cache size. The page size, plus a little extra, times this
+  // Set the cache size. The page size, plus a little extra, times this
   // value, tells us how much memory the cache will use maximum.
-  // 6000 * 4MB = 24MB
+  // 1000 * 4kB = 4MB
   // TODO(brettw) scale this value to the amount of available memory.
-  db_.set_cache_size(6000);
+  db_.set_cache_size(1000);
 
   // Note that we don't set exclusive locking here. That's done by
   // BeginExclusiveMode below which is called later (we have to be in shared
@@ -418,6 +418,15 @@
     meta_table_.SetVersionNumber(cur_version);
   }
 
+  if (cur_version == 25) {
+    if (!MigrateReferrer()) {
+      LOG(WARNING) << "Unable to migrate history to version 26";
+      return sql::INIT_FAILURE;
+    }
+    cur_version++;
+    meta_table_.SetVersionNumber(cur_version);
+  }
+
   // When the version is too old, we just try to continue anyway, there should
   // not be a released product that makes a database too old for us to handle.
   LOG_IF(WARNING, cur_version < GetCurrentVersion()) <<
diff --git a/chrome/browser/history/history_database_unittest.cc b/chrome/browser/history/history_database_unittest.cc
index 67f7290..45832d4 100644
--- a/chrome/browser/history/history_database_unittest.cc
+++ b/chrome/browser/history/history_database_unittest.cc
@@ -20,7 +20,7 @@
 
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
   db_file = temp_dir.path().AppendASCII("DropBookmarks.db");
-  file_util::Delete(db_file, false);
+  sql::Connection::Delete(db_file);
 
   // Copy db file over that contains starred URLs.
   base::FilePath old_history_path;
diff --git a/chrome/browser/history/history_notifications.h b/chrome/browser/history/history_notifications.h
index afe48f1..2f596e8 100644
--- a/chrome/browser/history/history_notifications.h
+++ b/chrome/browser/history/history_notifications.h
@@ -12,7 +12,7 @@
 #include "chrome/browser/history/history_details.h"
 #include "chrome/browser/history/history_types.h"
 #include "chrome/browser/search_engines/template_url_id.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 namespace history {
 
diff --git a/chrome/browser/history/history_publisher_none.cc b/chrome/browser/history/history_publisher_none.cc
index 956f1f5..ddf75fc 100644
--- a/chrome/browser/history/history_publisher_none.cc
+++ b/chrome/browser/history/history_publisher_none.cc
@@ -8,7 +8,7 @@
 
 #include "chrome/browser/history/history_publisher.h"
 
-#include "base/time.h"
+#include "base/time/time.h"
 
 namespace history {
 
diff --git a/chrome/browser/history/history_publisher_win.cc b/chrome/browser/history/history_publisher_win.cc
index 37b32bf..e6178b5 100644
--- a/chrome/browser/history/history_publisher_win.cc
+++ b/chrome/browser/history/history_publisher_win.cc
@@ -10,12 +10,12 @@
 
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/win/registry.h"
 #include "base/win/scoped_bstr.h"
 #include "base/win/scoped_comptr.h"
 #include "base/win/scoped_variant.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 namespace {
 
diff --git a/chrome/browser/history/history_querying_unittest.cc b/chrome/browser/history/history_querying_unittest.cc
index 4719b90..aa69fc4 100644
--- a/chrome/browser/history/history_querying_unittest.cc
+++ b/chrome/browser/history/history_querying_unittest.cc
@@ -26,29 +26,25 @@
   const char* url;
   const char* title;
   const int days_ago;
-  const char* body;
   Time time;  // Filled by SetUp.
 } test_entries[] = {
   // This one is visited super long ago so it will be in a different database
   // from the next appearance of it at the end.
-  {"http://example.com/", "Other", 180, "Other"},
+  {"http://example.com/", "Other", 180},
 
   // These are deliberately added out of chronological order. The history
   // service should sort them by visit time when returning query results.
   // The correct index sort order is 4 2 3 1 7 6 5 0.
-  {"http://www.google.com/1", "Title 1", 10,
-   "PAGEONE FOO some body text"},
-  {"http://www.google.com/3", "Title 3", 8,
-   "PAGETHREE BAR some hello world for you"},
-  {"http://www.google.com/2", "Title 2", 9,
-   "PAGETWO FOO some more blah blah blah Title"},
+  {"http://www.google.com/1", "Title PAGEONE FOO some text", 10},
+  {"http://www.google.com/3", "Title PAGETHREE BAR some hello world", 8},
+  {"http://www.google.com/2", "Title PAGETWO FOO some more blah blah blah", 9},
 
   // A more recent visit of the first one.
-  {"http://example.com/", "Other", 6, "Other"},
+  {"http://example.com/", "Other", 6},
 
-  {"http://www.google.com/6", "Title 6", 13, "I'm the second oldest"},
-  {"http://www.google.com/4", "Title 4", 12, "four"},
-  {"http://www.google.com/5", "Title 5", 11, "five"},
+  {"http://www.google.com/6", "Title I'm the second oldest", 13},
+  {"http://www.google.com/4", "Title four", 12},
+  {"http://www.google.com/5", "Title five", 11},
 };
 
 // Returns true if the nth result in the given results set matches. It will
@@ -91,8 +87,8 @@
   }
 
   // Test paging through results, with a fixed number of results per page.
-  // Defined here so code can be shared for the FTS version and the non-FTS
-  // version.
+  // Defined here so code can be shared for the text search and the non-text
+  // seach versions.
   void TestPaging(const std::string& query_text,
                   const int* expected_results,
                   int results_length) {
@@ -125,10 +121,10 @@
     }
 
     // Add a couple of entries with duplicate timestamps. Use |query_text| as
-    // the body of both entries so that they match a full-text query.
+    // the title of both entries so that they match a text query.
     TestEntry duplicates[] = {
-      { "http://www.google.com/x", "", 1, query_text.c_str() },
-      { "http://www.google.com/y", "", 1, query_text.c_str() }
+      { "http://www.google.com/x",  query_text.c_str(), 1, },
+      { "http://www.google.com/y",  query_text.c_str(), 1, }
     };
     AddEntryToHistory(duplicates[0]);
     AddEntryToHistory(duplicates[1]);
@@ -157,7 +153,6 @@
                       history::RedirectList(), content::PAGE_TRANSITION_LINK,
                       history::SOURCE_BROWSED, false);
     history_->SetPageTitle(url, UTF8ToUTF16(entry.title));
-    history_->SetPageContents(url, UTF8ToUTF16(entry.body));
   }
 
  private:
@@ -313,14 +308,13 @@
   EXPECT_TRUE(results.reached_beginning());
   options.max_count = results.size();
   QueryHistory("some", options, &results);
-  // Since the query didn't cover the oldest visit in the database, we
-  // expect false here.
-  EXPECT_FALSE(results.reached_beginning());
+  EXPECT_TRUE(results.reached_beginning());
 }
 
-// This does most of the same tests above, but searches for a FTS string that
-// will match the pages in question. This will trigger a different code path.
-TEST_F(HistoryQueryTest, FTS) {
+// This does most of the same tests above, but performs a text searches for a
+// string that will match the pages in question. This will trigger a
+// different code path.
+TEST_F(HistoryQueryTest, TextSearch) {
   ASSERT_TRUE(history_.get());
 
   QueryOptions options;
@@ -349,33 +343,8 @@
   EXPECT_TRUE(NthResultIs(results, 0, 1));
 }
 
-// Searches titles.
-TEST_F(HistoryQueryTest, FTSTitle) {
-  ASSERT_TRUE(history_.get());
-
-  QueryOptions options;
-  QueryResults results;
-
-  // First execute a body-only query, to ensure that it works and that that
-  // version of the statement is not cached for the next query.
-  options.body_only = true;
-  QueryHistory("Title", options, &results);
-  EXPECT_EQ(1U, results.size());
-  EXPECT_TRUE(NthResultIs(results, 0, 3));
-  options.body_only = false;
-
-  // Query all time but with a limit on the number of entries. We should
-  // get the N most recent entries.
-  options.max_count = 3;
-  QueryHistory("title", options, &results);
-  EXPECT_EQ(3U, results.size());
-  EXPECT_TRUE(NthResultIs(results, 0, 2));
-  EXPECT_TRUE(NthResultIs(results, 1, 3));
-  EXPECT_TRUE(NthResultIs(results, 2, 1));
-}
-
-// Tests prefix searching for Full Text Search queries.
-TEST_F(HistoryQueryTest, FTSPrefix) {
+// Tests prefix searching for text search queries.
+TEST_F(HistoryQueryTest, TextSearchPrefix) {
   ASSERT_TRUE(history_.get());
 
   QueryOptions options;
@@ -389,8 +358,8 @@
   EXPECT_TRUE(NthResultIs(results, 1, 3));
 }
 
-// Tests max_count feature for Full Text Search queries.
-TEST_F(HistoryQueryTest, FTSCount) {
+// Tests max_count feature for text search queries.
+TEST_F(HistoryQueryTest, TextSearchCount) {
   ASSERT_TRUE(history_.get());
 
   QueryOptions options;
@@ -413,21 +382,21 @@
   EXPECT_TRUE(NthResultIs(results, 0, 3));
 }
 
-// Tests that FTS queries can find URLs when they exist only in the archived
-// database. This also tests that imported URLs can be found, since we use
-// AddPageWithDetails just like the importer.
-TEST_F(HistoryQueryTest, FTSArchived) {
+// Tests that text search queries can find URLs when they exist only in the
+// archived database. This also tests that imported URLs can be found, since
+// we use AddPageWithDetails just like the importer.
+TEST_F(HistoryQueryTest, TextSearchArchived) {
   ASSERT_TRUE(history_.get());
 
   URLRows urls_to_add;
 
   URLRow row1(GURL("http://foo.bar/"));
-  row1.set_title(UTF8ToUTF16("archived title"));
+  row1.set_title(UTF8ToUTF16("archived title same"));
   row1.set_last_visit(Time::Now() - TimeDelta::FromDays(365));
   urls_to_add.push_back(row1);
 
   URLRow row2(GURL("http://foo.bar/"));
-  row2.set_title(UTF8ToUTF16("nonarchived title"));
+  row2.set_title(UTF8ToUTF16("nonarchived title same"));
   row2.set_last_visit(Time::Now());
   urls_to_add.push_back(row2);
 
@@ -436,13 +405,22 @@
   QueryOptions options;
   QueryResults results;
 
-  // Query all time. The title we get should be the one in the full text
-  // database and not the most current title (since otherwise highlighting in
+  // Query all time. The title we get should be the one in the archived and
+  // not the most current title (since otherwise highlighting in
   // the title might be wrong).
   QueryHistory("archived", options, &results);
   ASSERT_EQ(1U, results.size());
   EXPECT_TRUE(row1.url() == results[0].url());
   EXPECT_TRUE(row1.title() == results[0].title());
+
+  // Check query is ordered correctly when split between archived and
+  // non-archived database.
+  QueryHistory("same", options, &results);
+  ASSERT_EQ(2U, results.size());
+  EXPECT_TRUE(row2.url() == results[0].url());
+  EXPECT_TRUE(row2.title() == results[0].title());
+  EXPECT_TRUE(row1.url() == results[1].url());
+  EXPECT_TRUE(row1.title() == results[1].title());
 }
 
 /* TODO(brettw) re-enable this. It is commented out because the current history
@@ -451,15 +429,15 @@
    won't get picked up by the deletor and it can happen again. When this is the
    case, we should fix this test to duplicate that situation.
 
-// Tests duplicate collapsing and not in Full Text Search situations.
-TEST_F(HistoryQueryTest, FTSDupes) {
+// Tests duplicate collapsing and not in text search situations.
+TEST_F(HistoryQueryTest, TextSearchDupes) {
   ASSERT_TRUE(history_.get());
 
   QueryOptions options;
   QueryResults results;
 
   QueryHistory("Other", options, &results);
-  EXPECT_EQ(1, results.urls().size());
+  EXPECT_EQ(1U, results.size());
   EXPECT_TRUE(NthResultIs(results, 0, 4));
 }
 */
@@ -472,7 +450,7 @@
   TestPaging(std::string(), expected_results, arraysize(expected_results));
 }
 
-TEST_F(HistoryQueryTest, FTSPaging) {
+TEST_F(HistoryQueryTest, TextSearchPaging) {
   // Since results are fetched 1 and 2 at a time, entry #0 and #6 will not
   // be de-duplicated. Entry #4 does not contain the text "title", so it
   // shouldn't appear.
diff --git a/chrome/browser/history/history_service.cc b/chrome/browser/history/history_service.cc
index 1e4361a..49e4b07 100644
--- a/chrome/browser/history/history_service.cc
+++ b/chrome/browser/history/history_service.cc
@@ -35,12 +35,11 @@
 #include "base/prefs/pref_service.h"
 #include "base/thread_task_runner_handle.h"
 #include "base/threading/thread.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/autocomplete/history_url_provider.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/favicon/imported_favicon_usage.h"
 #include "chrome/browser/history/download_row.h"
 #include "chrome/browser/history/history_backend.h"
 #include "chrome/browser/history/history_notifications.h"
@@ -58,6 +57,7 @@
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "chrome/common/chrome_switches.h"
+#include "chrome/common/importer/imported_favicon_usage.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/thumbnail_score.h"
 #include "chrome/common/url_constants.h"
@@ -155,10 +155,11 @@
   virtual void SetInMemoryBackend(int backend_id,
       history::InMemoryHistoryBackend* backend) OVERRIDE {
     // Send the backend to the history service on the main thread.
+    scoped_ptr<history::InMemoryHistoryBackend> in_memory_backend(backend);
     service_task_runner_->PostTask(
         FROM_HERE,
         base::Bind(&HistoryService::SetInMemoryBackend, history_service_,
-                   backend_id, backend));
+                   backend_id, base::Passed(&in_memory_backend)));
   }
 
   virtual void BroadcastNotifications(
@@ -1076,17 +1077,16 @@
       delete_directive);
 }
 
-void HistoryService::SetInMemoryBackend(int backend_id,
-    history::InMemoryHistoryBackend* mem_backend) {
+void HistoryService::SetInMemoryBackend(
+    int backend_id, scoped_ptr<history::InMemoryHistoryBackend> mem_backend) {
   DCHECK(thread_checker_.CalledOnValidThread());
   if (!history_backend_.get() || current_backend_id_ != backend_id) {
     DVLOG(1) << "Message from obsolete backend";
-    // Cleaning up the memory backend.
-    delete mem_backend;
+    // mem_backend is deleted.
     return;
   }
   DCHECK(!in_memory_backend_) << "Setting mem DB twice";
-  in_memory_backend_.reset(mem_backend);
+  in_memory_backend_.reset(mem_backend.release());
 
   // The database requires additional initialization once we own it.
   in_memory_backend_->AttachToHistoryService(profile_);
diff --git a/chrome/browser/history/history_service.h b/chrome/browser/history/history_service.h
index 2a0cb81..885c75c 100644
--- a/chrome/browser/history/history_service.h
+++ b/chrome/browser/history/history_service.h
@@ -19,7 +19,7 @@
 #include "base/observer_list.h"
 #include "base/strings/string16.h"
 #include "base/threading/thread_checker.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/common/cancelable_request.h"
 #include "chrome/browser/favicon/favicon_service.h"
 #include "chrome/browser/history/delete_directive_handler.h"
@@ -831,8 +831,9 @@
 
   // Sets the in-memory URL database. This is called by the backend once the
   // database is loaded to make it available.
-  void SetInMemoryBackend(int backend_id,
-                          history::InMemoryHistoryBackend* mem_backend);
+  void SetInMemoryBackend(
+      int backend_id,
+      scoped_ptr<history::InMemoryHistoryBackend> mem_backend);
 
   // Called by our BackendDelegate when there is a problem reading the database.
   void NotifyProfileError(int backend_id, sql::InitStatus init_status);
diff --git a/chrome/browser/history/history_tab_helper.cc b/chrome/browser/history/history_tab_helper.cc
index 5438b97..f0285ab 100644
--- a/chrome/browser/history/history_tab_helper.cc
+++ b/chrome/browser/history/history_tab_helper.cc
@@ -12,7 +12,6 @@
 #include "chrome/browser/prerender/prerender_manager.h"
 #include "chrome/browser/prerender/prerender_manager_factory.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/search/instant_overlay.h"
 #include "chrome/common/render_messages.h"
 #include "content/public/browser/navigation_details.h"
 #include "content/public/browser/navigation_entry.h"
@@ -128,13 +127,6 @@
     }
   }
 
-  InstantOverlay* instant_overlay =
-      InstantOverlay::FromWebContents(web_contents());
-  if (instant_overlay) {
-    instant_overlay->DidNavigate(add_page_args);
-    return;
-  }
-
 #if !defined(OS_ANDROID)
   // Don't update history if this web contents isn't associatd with a tab.
   Browser* browser = chrome::FindBrowserWithWebContents(web_contents());
diff --git a/chrome/browser/history/history_tab_helper.h b/chrome/browser/history/history_tab_helper.h
index 3615ecb..95c4ee0 100644
--- a/chrome/browser/history/history_tab_helper.h
+++ b/chrome/browser/history/history_tab_helper.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_HISTORY_HISTORY_TAB_HELPER_H_
 
 #include "base/memory/ref_counted.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "content/public/browser/web_contents_observer.h"
diff --git a/chrome/browser/history/history_types.cc b/chrome/browser/history/history_types.cc
index 09fed81..f0e6439 100644
--- a/chrome/browser/history/history_types.cc
+++ b/chrome/browser/history/history_types.cc
@@ -107,6 +107,10 @@
     : URLRow(url) {
   title_match_positions_ = title_matches;
 }
+URLResult::URLResult(const URLRow& url_row)
+    : URLRow(url_row),
+      blocked_visit_(false) {
+}
 
 URLResult::~URLResult() {
 }
@@ -119,6 +123,11 @@
   std::swap(blocked_visit_, other->blocked_visit_);
 }
 
+// static
+bool URLResult::CompareVisitTime(const URLResult& lhs, const URLResult& rhs) {
+  return lhs.visit_time() > rhs.visit_time();
+}
+
 // QueryResults ----------------------------------------------------------------
 
 QueryResults::QueryResults() : reached_beginning_(false) {
@@ -385,13 +394,6 @@
 
 IconMapping::~IconMapping() {}
 
-// FaviconSizes --------------------------------------------------------------
-
-const FaviconSizes& GetDefaultFaviconSizes() {
-  CR_DEFINE_STATIC_LOCAL(FaviconSizes, kDefaultFaviconSizes, ());
-  return kDefaultFaviconSizes;
-}
-
 // FaviconBitmapIDSize ---------------------------------------------------------
 
 FaviconBitmapIDSize::FaviconBitmapIDSize()
diff --git a/chrome/browser/history/history_types.h b/chrome/browser/history/history_types.h
index c99457d..d78d40f 100644
--- a/chrome/browser/history/history_types.h
+++ b/chrome/browser/history/history_types.h
@@ -16,16 +16,16 @@
 #include "base/memory/ref_counted_memory.h"
 #include "base/memory/scoped_vector.h"
 #include "base/strings/string16.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/favicon/favicon_types.h"
 #include "chrome/browser/history/snippet.h"
 #include "chrome/browser/search_engines/template_url_id.h"
 #include "chrome/common/ref_counted_util.h"
 #include "chrome/common/thumbnail_score.h"
 #include "content/public/common/page_transition_types.h"
-#include "googleurl/src/gurl.h"
 #include "ui/gfx/image/image.h"
 #include "ui/gfx/size.h"
+#include "url/gurl.h"
 
 class PageUsageData;
 
@@ -294,6 +294,7 @@
   // Constructor that create a URLResult from the specified URL and title match
   // positions from title_matches.
   URLResult(const GURL& url, const Snippet::MatchPositions& title_matches);
+  explicit URLResult(const URLRow& url_row);
   virtual ~URLResult();
 
   base::Time visit_time() const { return visit_time_; }
@@ -315,6 +316,8 @@
 
   void SwapResult(URLResult* other);
 
+  static bool CompareVisitTime(const URLResult& lhs, const URLResult& rhs);
+
  private:
   friend class HistoryBackend;
 
@@ -608,8 +611,6 @@
   // scoped_refptr<base::RefCountedBytes> favicon;
 };
 
-typedef std::vector<MostVisitedURL> MostVisitedURLList;
-
 struct MostVisitedURLWithRank {
   MostVisitedURL url;
   int rank;
@@ -697,19 +698,6 @@
   chrome::IconType icon_type;
 };
 
-// FaviconSizes represents the sizes that the thumbnail database knows a
-// favicon is available from the web. FaviconSizes has several entries
-// only if FaviconSizes is for an .ico file. FaviconSizes can be different
-// from the pixel sizes of the entries in the |favicon_bitmaps| table. For
-// instance, if a web page has a .ico favicon with bitmaps of pixel sizes
-// (16x16, 32x32), FaviconSizes will have both sizes regardless of whether
-// either of these bitmaps is cached in the favicon_bitmaps database table.
-typedef std::vector<gfx::Size> FaviconSizes;
-
-// Returns the default FaviconSizes to use if the favicon sizes for a FaviconID
-// are unknown.
-const FaviconSizes& GetDefaultFaviconSizes();
-
 // Defines a favicon bitmap and its associated pixel size.
 struct FaviconBitmapIDSize {
   FaviconBitmapIDSize();
diff --git a/chrome/browser/history/history_unittest.cc b/chrome/browser/history/history_unittest.cc
index d9e8949..ebdf67d 100644
--- a/chrome/browser/history/history_unittest.cc
+++ b/chrome/browser/history/history_unittest.cc
@@ -40,7 +40,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/platform_thread.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/history/download_row.h"
 #include "chrome/browser/history/history_backend.h"
 #include "chrome/browser/history/history_database.h"
@@ -165,10 +165,10 @@
     std::vector<GURL> url_chain;
     url_chain.push_back(GURL("foo-url"));
 
-    DownloadRow download(base::FilePath(FILE_PATH_LITERAL("foo-path")),
-                         base::FilePath(FILE_PATH_LITERAL("foo-path")),
+    DownloadRow download(base::FilePath(FILE_PATH_LITERAL("current-path")),
+                         base::FilePath(FILE_PATH_LITERAL("target-path")),
                          url_chain,
-                         GURL(std::string()),
+                         GURL("http://referrer.com/"),
                          time,
                          time,
                          0,
@@ -177,7 +177,7 @@
                          content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
                          content::DOWNLOAD_INTERRUPT_REASON_NONE,
                          0,
-                         0);
+                         false);
     return db_->CreateDownload(download);
   }
 
@@ -221,12 +221,33 @@
   db_->QueryDownloads(&downloads);
   EXPECT_EQ(0U, downloads.size());
 
-  // Add a download, test that it was added, remove it, test that it was
-  // removed.
+  // Add a download, test that it was added correctly, remove it, test that it
+  // was removed.
   DownloadID handle;
-  EXPECT_NE(0, handle = AddDownload(DownloadItem::COMPLETE, Time()));
+  Time now = Time();
+  EXPECT_NE(0, handle = AddDownload(DownloadItem::COMPLETE, now));
   db_->QueryDownloads(&downloads);
   EXPECT_EQ(1U, downloads.size());
+
+  EXPECT_EQ(base::FilePath(FILE_PATH_LITERAL("current-path")),
+            downloads[0].current_path);
+  EXPECT_EQ(base::FilePath(FILE_PATH_LITERAL("target-path")),
+            downloads[0].target_path);
+  EXPECT_EQ(1UL, downloads[0].url_chain.size());
+  EXPECT_EQ(GURL("foo-url"), downloads[0].url_chain[0]);
+  EXPECT_EQ(std::string("http://referrer.com/"),
+            std::string(downloads[0].referrer_url.spec()));
+  EXPECT_EQ(now, downloads[0].start_time);
+  EXPECT_EQ(now, downloads[0].end_time);
+  EXPECT_EQ(0, downloads[0].received_bytes);
+  EXPECT_EQ(512, downloads[0].total_bytes);
+  EXPECT_EQ(DownloadItem::COMPLETE, downloads[0].state);
+  EXPECT_EQ(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
+            downloads[0].danger_type);
+  EXPECT_EQ(content::DOWNLOAD_INTERRUPT_REASON_NONE,
+            downloads[0].interrupt_reason);
+  EXPECT_FALSE(downloads[0].opened);
+
   db_->RemoveDownload(handle);
   db_->QueryDownloads(&downloads);
   EXPECT_EQ(0U, downloads.size());
@@ -411,6 +432,54 @@
   }
 }
 
+TEST_F(HistoryBackendDBTest, MigrateReferrer) {
+  Time now(base::Time::Now());
+  ASSERT_NO_FATAL_FAILURE(CreateDBVersion(22));
+  {
+    sql::Connection db;
+    ASSERT_TRUE(db.Open(history_dir_.Append(chrome::kHistoryFilename)));
+    sql::Statement s(db.GetUniqueStatement(
+        "INSERT INTO downloads (id, full_path, url, start_time, "
+        "received_bytes, total_bytes, state, end_time, opened) VALUES "
+        "(?, ?, ?, ?, ?, ?, ?, ?, ?)"));
+    int64 db_handle = 0;
+    s.BindInt64(0, ++db_handle);
+    s.BindString(1, "full_path");
+    s.BindString(2, "http://whatever.com/index.html");
+    s.BindInt64(3, now.ToTimeT());
+    s.BindInt64(4, 100);
+    s.BindInt64(5, 100);
+    s.BindInt(6, 1);
+    s.BindInt64(7, now.ToTimeT());
+    s.BindInt(8, 1);
+    ASSERT_TRUE(s.Run());
+  }
+  // Re-open the db using the HistoryDatabase, which should migrate to version
+  // 26, creating the referrer column.
+  CreateBackendAndDatabase();
+  DeleteBackend();
+  {
+    // Re-open the db for manual manipulation.
+    sql::Connection db;
+    ASSERT_TRUE(db.Open(history_dir_.Append(chrome::kHistoryFilename)));
+    // The version should have been updated.
+    int cur_version = HistoryDatabase::GetCurrentVersion();
+    ASSERT_LE(26, cur_version);
+    {
+      sql::Statement s(db.GetUniqueStatement(
+          "SELECT value FROM meta WHERE key = 'version'"));
+      EXPECT_TRUE(s.Step());
+      EXPECT_EQ(cur_version, s.ColumnInt(0));
+    }
+    {
+      sql::Statement s(db.GetUniqueStatement(
+          "SELECT referrer from downloads"));
+      EXPECT_TRUE(s.Step());
+      EXPECT_EQ(std::string(), s.ColumnString(0));
+    }
+  }
+}
+
 TEST_F(HistoryBackendDBTest, ConfirmDownloadRowCreateAndDelete) {
   // Create the DB.
   CreateBackendAndDatabase();
diff --git a/chrome/browser/history/in_memory_database.cc b/chrome/browser/history/in_memory_database.cc
index 40babf5..61e2570 100644
--- a/chrome/browser/history/in_memory_database.cc
+++ b/chrome/browser/history/in_memory_database.cc
@@ -8,7 +8,7 @@
 #include "base/logging.h"
 #include "base/metrics/histogram.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "build/build_config.h"
 
 namespace history {
diff --git a/chrome/browser/history/in_memory_history_backend.cc b/chrome/browser/history/in_memory_history_backend.cc
index 0dc276f..ce9f965 100644
--- a/chrome/browser/history/in_memory_history_backend.cc
+++ b/chrome/browser/history/in_memory_history_backend.cc
@@ -9,7 +9,7 @@
 
 #include "base/command_line.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/history/history_notifications.h"
 #include "chrome/browser/history/in_memory_database.h"
diff --git a/chrome/browser/history/in_memory_url_index.cc b/chrome/browser/history/in_memory_url_index.cc
index 50098cd..e0f4462 100644
--- a/chrome/browser/history/in_memory_url_index.cc
+++ b/chrome/browser/history/in_memory_url_index.cc
@@ -31,7 +31,7 @@
 // there is no private data to save. Runs on the FILE thread.
 void DeleteCacheFile(const base::FilePath& path) {
   DCHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-  file_util::Delete(path, false);
+  base::Delete(path, false);
 }
 
 // Initializes a whitelist of URL schemes.
diff --git a/chrome/browser/history/in_memory_url_index_types.h b/chrome/browser/history/in_memory_url_index_types.h
index b4f51cf..19547fa 100644
--- a/chrome/browser/history/in_memory_url_index_types.h
+++ b/chrome/browser/history/in_memory_url_index_types.h
@@ -12,7 +12,7 @@
 #include "base/strings/string16.h"
 #include "chrome/browser/autocomplete/history_provider_util.h"
 #include "chrome/browser/history/history_types.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 namespace history {
 
diff --git a/chrome/browser/history/page_usage_data.h b/chrome/browser/history/page_usage_data.h
index 1f27440..07f58dd 100644
--- a/chrome/browser/history/page_usage_data.h
+++ b/chrome/browser/history/page_usage_data.h
@@ -6,9 +6,9 @@
 #define CHROME_BROWSER_HISTORY_PAGE_USAGE_DATA_H__
 
 #include "base/strings/string16.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/history/history_types.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 class SkBitmap;
 
diff --git a/chrome/browser/history/query_parser.cc b/chrome/browser/history/query_parser.cc
index 9fafc9b..322da23 100644
--- a/chrome/browser/history/query_parser.cc
+++ b/chrome/browser/history/query_parser.cc
@@ -11,6 +11,7 @@
 #include "base/i18n/case_conversion.h"
 #include "base/logging.h"
 #include "base/stl_util.h"
+#include "base/strings/utf_string_conversions.h"
 
 namespace {
 
@@ -88,6 +89,8 @@
   virtual bool HasMatchIn(
       const std::vector<QueryWord>& words,
       Snippet::MatchPositions* match_positions) const OVERRIDE;
+  virtual bool HasMatchIn(
+      const std::vector<QueryWord>& words) const OVERRIDE;
   virtual void AppendWords(std::vector<string16>* words) const OVERRIDE;
 
  private:
@@ -138,6 +141,14 @@
   return matched;
 }
 
+bool QueryNodeWord::HasMatchIn(const std::vector<QueryWord>& words) const {
+  for (size_t i = 0; i < words.size(); ++i) {
+    if (Matches(words[i].word, false))
+      return true;
+  }
+  return false;
+}
+
 void QueryNodeWord::AppendWords(std::vector<string16>* words) const {
   words->push_back(word_);
 }
@@ -164,6 +175,8 @@
   virtual bool HasMatchIn(
       const std::vector<QueryWord>& words,
       Snippet::MatchPositions* match_positions) const OVERRIDE;
+  virtual bool HasMatchIn(
+      const std::vector<QueryWord>& words) const OVERRIDE;
   virtual void AppendWords(std::vector<string16>* words) const OVERRIDE;
 
  protected:
@@ -219,6 +232,11 @@
   return false;
 }
 
+bool QueryNodeList::HasMatchIn(const std::vector<QueryWord>& words) const {
+  NOTREACHED();
+  return false;
+}
+
 void QueryNodeList::AppendWords(std::vector<string16>* words) const {
   for (size_t i = 0; i < children_.size(); ++i)
     children_[i]->AppendWords(words);
@@ -246,8 +264,13 @@
   virtual bool HasMatchIn(
       const std::vector<QueryWord>& words,
       Snippet::MatchPositions* match_positions) const OVERRIDE;
+  virtual bool HasMatchIn(
+      const std::vector<QueryWord>& words) const OVERRIDE;
 
  private:
+  bool MatchesAll(const std::vector<QueryWord>& words,
+                  const QueryWord** first_word,
+                  const QueryWord** last_word) const;
   DISALLOW_COPY_AND_ASSIGN(QueryNodePhrase);
 };
 
@@ -262,9 +285,9 @@
   return num_words;
 }
 
-bool QueryNodePhrase::HasMatchIn(
-    const std::vector<QueryWord>& words,
-    Snippet::MatchPositions* match_positions) const {
+bool QueryNodePhrase::MatchesAll(const std::vector<QueryWord>& words,
+                                 const QueryWord** first_word,
+                                 const QueryWord** last_word) const {
   if (words.size() < children_.size())
     return false;
 
@@ -277,16 +300,35 @@
       }
     }
     if (matched_all) {
-      const QueryWord& last_word = words[i + children_.size() - 1];
-      match_positions->push_back(
-          Snippet::MatchPosition(words[i].position,
-                                 last_word.position + last_word.word.length()));
+      *first_word = &words[i];
+      *last_word = &words[i + children_.size() - 1];
       return true;
     }
   }
   return false;
 }
 
+bool QueryNodePhrase::HasMatchIn(
+    const std::vector<QueryWord>& words,
+    Snippet::MatchPositions* match_positions) const {
+  const QueryWord* first_word;
+  const QueryWord* last_word;
+
+  if (MatchesAll(words, &first_word, &last_word)) {
+    match_positions->push_back(
+        Snippet::MatchPosition(first_word->position,
+                               last_word->position + last_word->word.length()));
+      return true;
+  }
+  return false;
+}
+
+bool QueryNodePhrase::HasMatchIn(const std::vector<QueryWord>& words) const {
+  const QueryWord* first_word;
+  const QueryWord* last_word;
+  return MatchesAll(words, &first_word, &last_word);
+}
+
 QueryParser::QueryParser() {}
 
 // static
@@ -354,6 +396,18 @@
   return true;
 }
 
+bool QueryParser::DoesQueryMatch(const std::vector<QueryWord>& query_words,
+                                 const std::vector<QueryNode*>& query_nodes) {
+  if (query_nodes.empty() || query_words.empty())
+    return false;
+
+  for (size_t i = 0; i < query_nodes.size(); ++i) {
+    if (!query_nodes[i]->HasMatchIn(query_words))
+      return false;
+  }
+  return true;
+}
+
 bool QueryParser::ParseQueryImpl(const string16& query, QueryNodeList* root) {
   base::i18n::BreakIterator iter(query, base::i18n::BreakIterator::BREAK_WORD);
   // TODO(evanm): support a locale here
diff --git a/chrome/browser/history/query_parser.h b/chrome/browser/history/query_parser.h
index 6bb0787..fe69e0b 100644
--- a/chrome/browser/history/query_parser.h
+++ b/chrome/browser/history/query_parser.h
@@ -46,6 +46,9 @@
   virtual bool HasMatchIn(const std::vector<QueryWord>& words,
                           Snippet::MatchPositions* match_positions) const = 0;
 
+  // Returns true if this node matches at least one of the words in |words|.
+  virtual bool HasMatchIn(const std::vector<QueryWord>& words) const = 0;
+
   // Appends the words that make up this node in |words|.
   virtual void AppendWords(std::vector<string16>* words) const = 0;
 };
@@ -87,14 +90,19 @@
                       const std::vector<QueryNode*>& nodes,
                       Snippet::MatchPositions* match_positions);
 
+  // Returns true if all of the |words| match the query |nodes| created by a
+  // call to ParseQuery.
+  bool DoesQueryMatch(const std::vector<QueryWord>& words,
+                      const std::vector<QueryNode*>& nodes);
+
+  // Extracts the words from |text|, placing each word into |words|.
+  void ExtractQueryWords(const string16& text, std::vector<QueryWord>* words);
+
  private:
   // Does the work of parsing |query|; creates nodes in |root| as appropriate.
   // This is invoked from both of the ParseQuery methods.
   bool ParseQueryImpl(const string16& query, QueryNodeList* root);
 
-  // Extracts the words from |text|, placing each word into |words|.
-  void ExtractQueryWords(const string16& text, std::vector<QueryWord>* words);
-
   DISALLOW_COPY_AND_ASSIGN(QueryParser);
 };
 
diff --git a/chrome/browser/history/shortcuts_backend.h b/chrome/browser/history/shortcuts_backend.h
index a634c5b..6979271 100644
--- a/chrome/browser/history/shortcuts_backend.h
+++ b/chrome/browser/history/shortcuts_backend.h
@@ -16,12 +16,12 @@
 #include "base/observer_list.h"
 #include "base/strings/string16.h"
 #include "base/synchronization/lock.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/autocomplete/autocomplete_match.h"
 #include "components/browser_context_keyed_service/refcounted_browser_context_keyed_service.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 class Profile;
 
diff --git a/chrome/browser/history/shortcuts_backend_unittest.cc b/chrome/browser/history/shortcuts_backend_unittest.cc
index dbc4e83..804f1df 100644
--- a/chrome/browser/history/shortcuts_backend_unittest.cc
+++ b/chrome/browser/history/shortcuts_backend_unittest.cc
@@ -7,7 +7,7 @@
 #include "base/path_service.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/history/shortcuts_backend.h"
 #include "chrome/browser/history/shortcuts_backend_factory.h"
 #include "chrome/browser/history/shortcuts_database.h"
diff --git a/chrome/browser/history/shortcuts_database.cc b/chrome/browser/history/shortcuts_database.cc
index 69dcd33..f739073 100644
--- a/chrome/browser/history/shortcuts_database.cc
+++ b/chrome/browser/history/shortcuts_database.cc
@@ -11,7 +11,7 @@
 #include "base/guid.h"
 #include "base/logging.h"
 #include "base/strings/stringprintf.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/chrome_constants.h"
 #include "sql/statement.h"
diff --git a/chrome/browser/history/shortcuts_database.h b/chrome/browser/history/shortcuts_database.h
index 36e803d..647b000 100644
--- a/chrome/browser/history/shortcuts_database.h
+++ b/chrome/browser/history/shortcuts_database.h
@@ -14,8 +14,8 @@
 #include "base/memory/ref_counted.h"
 #include "base/strings/string16.h"
 #include "chrome/browser/history/shortcuts_backend.h"
-#include "googleurl/src/gurl.h"
 #include "sql/connection.h"
+#include "url/gurl.h"
 
 class Profile;
 
diff --git a/chrome/browser/history/shortcuts_database_unittest.cc b/chrome/browser/history/shortcuts_database_unittest.cc
index 86040a6..dd3a322 100644
--- a/chrome/browser/history/shortcuts_database_unittest.cc
+++ b/chrome/browser/history/shortcuts_database_unittest.cc
@@ -6,7 +6,7 @@
 #include "base/path_service.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/history/shortcuts_database.h"
 #include "chrome/test/base/testing_profile.h"
 #include "sql/statement.h"
diff --git a/chrome/browser/history/text_database.h b/chrome/browser/history/text_database.h
index efb9563..ddb247b 100644
--- a/chrome/browser/history/text_database.h
+++ b/chrome/browser/history/text_database.h
@@ -12,9 +12,9 @@
 #include "base/files/file_path.h"
 #include "base/strings/string16.h"
 #include "chrome/browser/history/history_types.h"
-#include "googleurl/src/gurl.h"
 #include "sql/connection.h"
 #include "sql/meta_table.h"
+#include "url/gurl.h"
 
 namespace history {
 
diff --git a/chrome/browser/history/text_database_manager.cc b/chrome/browser/history/text_database_manager.cc
index a55b0a0..e0d8484 100644
--- a/chrome/browser/history/text_database_manager.cc
+++ b/chrome/browser/history/text_database_manager.cc
@@ -9,7 +9,6 @@
 
 #include "base/bind.h"
 #include "base/compiler_specific.h"
-#include "base/file_util.h"
 #include "base/files/file_enumerator.h"
 #include "base/logging.h"
 #include "base/message_loop.h"
@@ -415,7 +414,7 @@
   for (DBIdentSet::iterator i = present_databases_.begin();
        i != present_databases_.end(); ++i) {
     base::FilePath file_name = dir_.Append(TextDatabase::IDToFileName(*i));
-    file_util::Delete(file_name, false);
+    sql::Connection::Delete(file_name);
   }
 }
 
diff --git a/chrome/browser/history/text_database_manager_unittest.cc b/chrome/browser/history/text_database_manager_unittest.cc
index eccd7a8..fa5a1f3 100644
--- a/chrome/browser/history/text_database_manager_unittest.cc
+++ b/chrome/browser/history/text_database_manager_unittest.cc
@@ -161,7 +161,7 @@
   }
 
   virtual void TearDown() {
-    file_util::Delete(dir_, true);
+    base::Delete(dir_, true);
   }
 
   base::MessageLoop message_loop_;
diff --git a/chrome/browser/history/text_database_unittest.cc b/chrome/browser/history/text_database_unittest.cc
index 72447f0..25b7d79 100644
--- a/chrome/browser/history/text_database_unittest.cc
+++ b/chrome/browser/history/text_database_unittest.cc
@@ -4,7 +4,6 @@
 
 #include <string>
 
-#include "base/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/string_util.h"
@@ -106,7 +105,7 @@
     TextDatabase* db = new TextDatabase(temp_dir_.path(), id, allow_create);
 
     if (delete_file)
-      file_util::Delete(db->file_name(), false);
+      sql::Connection::Delete(db->file_name());
 
     if (!db->Init()) {
       delete db;
diff --git a/chrome/browser/history/thumbnail_database.cc b/chrome/browser/history/thumbnail_database.cc
index 9f26548..ef5c439 100644
--- a/chrome/browser/history/thumbnail_database.cc
+++ b/chrome/browser/history/thumbnail_database.cc
@@ -19,7 +19,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/diagnostics/sqlite_diagnostics.h"
 #include "chrome/browser/history/history_publisher.h"
 #include "chrome/browser/history/top_sites.h"
@@ -55,22 +55,13 @@
 //   icon_type        The type of the favicon specified in the rel attribute of
 //                    the link tag. The FAVICON type is used for the default
 //                    favicon.ico favicon.
-//   sizes            Sizes is a listing of all the sizes at which the favicon
-//                    at |url| is available from the web. Note that this may
-//                    include sizes for which a bitmap is not stored in the
-//                    favicon_bitmaps table. Each widthxheight pair is
-//                    separated by a space. Width and height are separated by
-//                    a space as well. For instance, if |icon_id| represents a
-//                    .ico file containing 16x16 and 32x32 bitmaps, |sizes|
-//                    would be "16 16 32 32".
 //
 // favicon_bitmaps    This table contains the PNG encoded bitmap data of the
 //                    favicons. There is a separate row for every size in a
 //                    multi resolution bitmap. The bitmap data is associated
 //                    to the favicon via the |icon_id| field which matches
 //                    the |id| field in the appropriate row in the |favicons|
-//                    table. There is not necessarily a row for each size
-//                    specified in the sizes attribute.
+//                    table.
 //
 //  id                Unique ID.
 //  icon_id           The ID of the favicon that the bitmap is associated to.
@@ -288,8 +279,8 @@
 namespace history {
 
 // Version number of the database.
-static const int kCurrentVersionNumber = 6;
-static const int kCompatibleVersionNumber = 6;
+static const int kCurrentVersionNumber = 7;
+static const int kCompatibleVersionNumber = 7;
 
 // Use 90 quality (out of 100) which is pretty high, because we're very
 // sensitive to artifacts for these small sized, highly detailed images.
@@ -391,7 +382,7 @@
       return CantUpgradeToVersion(cur_version);
   }
 
-  if (!db_.DoesColumnExist("favicons", "sizes")) {
+  if (cur_version < 7 && !db_.DoesColumnExist("favicons", "sizes")) {
     LOG(ERROR) << "Raze because of missing favicon.sizes";
     RecordInvalidStructure(STRUCTURE_EVENT_VERSION5);
 
@@ -405,6 +396,12 @@
       return CantUpgradeToVersion(cur_version);
   }
 
+  if (cur_version == 6) {
+    ++cur_version;
+    if (!UpgradeToVersion7())
+      return CantUpgradeToVersion(cur_version);
+  }
+
   LOG_IF(WARNING, cur_version < kCurrentVersionNumber) <<
       "Thumbnail database version " << cur_version << " is too old to handle.";
 
@@ -523,8 +520,7 @@
                "url LONGVARCHAR NOT NULL,"
                // Set the default icon_type as FAVICON to be consistent with
                // table upgrade in UpgradeToVersion4().
-               "icon_type INTEGER DEFAULT 1,"
-               "sizes LONGVARCHAR)");
+               "icon_type INTEGER DEFAULT 1)");
     if (!db->Execute(sql.c_str()))
       return false;
   }
@@ -566,7 +562,7 @@
 }
 
 bool ThumbnailDatabase::IsFaviconDBStructureIncorrect() {
-  return !db_.IsSQLValid("SELECT id, url, icon_type, sizes FROM favicons");
+  return !db_.IsSQLValid("SELECT id, url, icon_type FROM favicons");
 }
 
 void ThumbnailDatabase::BeginTransaction() {
@@ -851,19 +847,6 @@
   return statement.Run();
 }
 
-bool ThumbnailDatabase::SetFaviconSizes(chrome::FaviconID icon_id,
-                                        const FaviconSizes& favicon_sizes) {
-  std::string favicon_sizes_as_string;
-  FaviconSizesToDatabaseString(favicon_sizes, &favicon_sizes_as_string);
-
-  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
-      "UPDATE favicons SET sizes=? WHERE id=?"));
-  statement.BindString(0, favicon_sizes_as_string);
-  statement.BindInt64(1, icon_id);
-
-  return statement.Run();
-}
-
 bool ThumbnailDatabase::SetFaviconOutOfDate(chrome::FaviconID icon_id) {
   sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
       "UPDATE favicon_bitmaps SET last_updated=? WHERE icon_id=?"));
@@ -893,12 +876,11 @@
 
 bool ThumbnailDatabase::GetFaviconHeader(chrome::FaviconID icon_id,
                                          GURL* icon_url,
-                                         chrome::IconType* icon_type,
-                                         FaviconSizes* favicon_sizes) {
+                                         chrome::IconType* icon_type) {
   DCHECK(icon_id);
 
   sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
-      "SELECT url, icon_type, sizes FROM favicons WHERE id=?"));
+      "SELECT url, icon_type FROM favicons WHERE id=?"));
   statement.BindInt64(0, icon_id);
 
   if (!statement.Step())
@@ -908,24 +890,18 @@
     *icon_url = GURL(statement.ColumnString(0));
   if (icon_type)
     *icon_type = static_cast<chrome::IconType>(statement.ColumnInt(1));
-  if (favicon_sizes)
-    DatabaseStringToFaviconSizes(statement.ColumnString(2), favicon_sizes);
 
   return true;
 }
 
 chrome::FaviconID ThumbnailDatabase::AddFavicon(
     const GURL& icon_url,
-    chrome::IconType icon_type,
-    const FaviconSizes& favicon_sizes) {
-  std::string favicon_sizes_as_string;
-  FaviconSizesToDatabaseString(favicon_sizes, &favicon_sizes_as_string);
+    chrome::IconType icon_type) {
 
   sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
-      "INSERT INTO favicons (url, icon_type, sizes) VALUES (?, ?, ?)"));
+      "INSERT INTO favicons (url, icon_type) VALUES (?, ?)"));
   statement.BindString(0, URLDatabase::GURLToDatabaseURL(icon_url));
   statement.BindInt(1, icon_type);
-  statement.BindString(2, favicon_sizes_as_string);
 
   if (!statement.Run())
     return 0;
@@ -935,11 +911,10 @@
 chrome::FaviconID ThumbnailDatabase::AddFavicon(
     const GURL& icon_url,
     chrome::IconType icon_type,
-    const FaviconSizes& favicon_sizes,
     const scoped_refptr<base::RefCountedMemory>& icon_data,
     base::Time time,
     const gfx::Size& pixel_size) {
-  chrome::FaviconID icon_id = AddFavicon(icon_url, icon_type, favicon_sizes);
+  chrome::FaviconID icon_id = AddFavicon(icon_url, icon_type);
   if (!icon_id || !AddFaviconBitmap(icon_id, icon_data, time, pixel_size))
     return 0;
 
@@ -1155,8 +1130,8 @@
     chrome::FaviconID source) {
   sql::Statement statement;
   statement.Assign(db_.GetCachedStatement(SQL_FROM_HERE,
-      "INSERT INTO temp_favicons (url, icon_type, sizes) "
-      "SELECT url, icon_type, sizes FROM favicons WHERE id = ?"));
+      "INSERT INTO temp_favicons (url, icon_type) "
+      "SELECT url, icon_type FROM favicons WHERE id = ?"));
   statement.BindInt64(0, source);
 
   if (!statement.Run())
@@ -1248,7 +1223,7 @@
   if (OpenDatabase(&db_, new_db_file) != sql::INIT_OK)
     return false;
 
-  file_util::Delete(old_db_file, false);
+  sql::Connection::Delete(old_db_file);
 
   meta_table_.Reset();
   if (!meta_table_.Init(&db_, kCurrentVersionNumber, kCompatibleVersionNumber))
@@ -1360,39 +1335,24 @@
   return true;
 }
 
-// static
-void ThumbnailDatabase::FaviconSizesToDatabaseString(
-    const FaviconSizes& favicon_sizes,
-    std::string* favicon_sizes_string) {
-  std::vector<std::string> parts;
-  for (FaviconSizes::const_iterator it = favicon_sizes.begin();
-       it != favicon_sizes.end(); ++it) {
-    parts.push_back(base::IntToString(it->width()));
-    parts.push_back(base::IntToString(it->height()));
-  }
-  *favicon_sizes_string = JoinString(parts, ' ');
-}
+bool ThumbnailDatabase::UpgradeToVersion7() {
+  bool success =
+      db_.Execute("CREATE TABLE temp_favicons ("
+                  "id INTEGER PRIMARY KEY,"
+                  "url LONGVARCHAR NOT NULL,"
+                  "icon_type INTEGER DEFAULT 1)") &&
+      db_.Execute("INSERT INTO temp_favicons (id, url, icon_type) "
+                  "SELECT id, url, icon_type FROM favicons") &&
+      db_.Execute("DROP TABLE favicons") &&
+      db_.Execute("ALTER TABLE temp_favicons RENAME TO favicons") &&
+      db_.Execute("CREATE INDEX IF NOT EXISTS favicons_url ON favicons(url)");
 
-// static
-void ThumbnailDatabase::DatabaseStringToFaviconSizes(
-    const std::string& favicon_sizes_string,
-    FaviconSizes* favicon_sizes) {
-  bool parsing_errors = false;
+  if (!success)
+    return false;
 
-  base::StringTokenizer t(favicon_sizes_string, " ");
-  while (t.GetNext() && !parsing_errors) {
-    int width, height = 0;
-    parsing_errors |= !base::StringToInt(t.token(), &width);
-    if (!t.GetNext()) {
-      parsing_errors = true;
-      break;
-    }
-    parsing_errors |= !base::StringToInt(t.token(), &height);
-    favicon_sizes->push_back(gfx::Size(width, height));
-  }
-
-  if (parsing_errors)
-    favicon_sizes->clear();
+  meta_table_.SetVersionNumber(7);
+  meta_table_.SetCompatibleVersionNumber(std::min(7, kCompatibleVersionNumber));
+  return true;
 }
 
 }  // namespace history
diff --git a/chrome/browser/history/thumbnail_database.h b/chrome/browser/history/thumbnail_database.h
index fc726d6..00931f1 100644
--- a/chrome/browser/history/thumbnail_database.h
+++ b/chrome/browser/history/thumbnail_database.h
@@ -161,11 +161,6 @@
 
   // Favicons ------------------------------------------------------------------
 
-  // Updates the favicon sizes associated with a favicon to |favicon_sizes|.
-  // See comment in history_types.h for description of |favicon_sizes|.
-  bool SetFaviconSizes(chrome::FaviconID icon_id,
-                       const FaviconSizes& favicon_sizes);
-
   // Sets the the favicon as out of date. This will set |last_updated| for all
   // of the bitmaps for |icon_id| to be out of date.
   bool SetFaviconOutOfDate(chrome::FaviconID icon_id);
@@ -184,21 +179,18 @@
   // Gets the icon_url, icon_type and sizes for the specified |icon_id|.
   bool GetFaviconHeader(chrome::FaviconID icon_id,
                         GURL* icon_url,
-                        chrome::IconType* icon_type,
-                        FaviconSizes* favicon_sizes);
+                        chrome::IconType* icon_type);
 
   // Adds favicon with |icon_url|, |icon_type| and |favicon_sizes| to the
   // favicon db, returning its id.
   chrome::FaviconID AddFavicon(const GURL& icon_url,
-                               chrome::IconType icon_type,
-                               const FaviconSizes& favicon_sizes);
+                               chrome::IconType icon_type);
 
   // Adds a favicon with a single bitmap. This call is equivalent to calling
   // AddFavicon and AddFaviconBitmap.
   chrome::FaviconID AddFavicon(
       const GURL& icon_url,
       chrome::IconType icon_type,
-      const FaviconSizes& favicon_sizes,
       const scoped_refptr<base::RefCountedMemory>& icon_data,
       base::Time time,
       const gfx::Size& pixel_size);
@@ -325,7 +317,7 @@
   FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest, UpgradeToVersion4);
   FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest, UpgradeToVersion5);
   FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest, UpgradeToVersion6);
-  FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest, FaviconSizesToAndFromString);
+  FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest, UpgradeToVersion7);
   FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, MigrationIconMapping);
 
   // Creates the thumbnail table, returning true if the table already exists
@@ -344,9 +336,12 @@
   // Adds support for sizes in favicon table.
   bool UpgradeToVersion5();
 
-  // Adds support for size in favicons table and removes sizes column.
+  // Adds support for size in favicons table.
   bool UpgradeToVersion6();
 
+  // Removes sizes column.
+  bool UpgradeToVersion7();
+
   // Migrates the icon mapping data from URL database to Thumbnail database.
   // Return whether the migration succeeds.
   bool MigrateIconMappingData(URLDatabase* url_db);
@@ -401,23 +396,6 @@
   // Returns True if the current database is latest.
   bool IsLatestVersion();
 
-  // Converts the vector representation of favicon sizes as passed into
-  // SetFaviconSizes to a string to store in the |favicons| database table.
-  // Format:
-  //   Each widthxheight pair is separated by a space.
-  //   Width and height are separated by a space.
-  // For instance, if sizes contains pixel sizes (16x16, 32x32), the
-  // string representation is "16 16 32 32".
-  static void FaviconSizesToDatabaseString(const FaviconSizes& favicon_sizes,
-                                           std::string* favicon_sizes_string);
-
-  // Converts the string representation of favicon sizes as stored in the
-  // |favicons| database table to a vector. Returns an empty vector if there
-  // were parsing errors.
-  static void DatabaseStringToFaviconSizes(
-      const std::string& favicon_sizes_string,
-      FaviconSizes* favicon_sizes);
-
   sql::Connection db_;
   sql::MetaTable meta_table_;
 
diff --git a/chrome/browser/history/thumbnail_database_unittest.cc b/chrome/browser/history/thumbnail_database_unittest.cc
index d81ad30..6446fd1 100644
--- a/chrome/browser/history/thumbnail_database_unittest.cc
+++ b/chrome/browser/history/thumbnail_database_unittest.cc
@@ -19,10 +19,10 @@
 #include "chrome/common/thumbnail_score.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/tools/profiles/thumbnail-inl.h"
-#include "googleurl/src/gurl.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/gfx/codec/jpeg_codec.h"
+#include "url/gurl.h"
 
 using base::Time;
 using base::TimeDelta;
@@ -69,13 +69,6 @@
         gfx::JPEGCodec::Decode(kGoogleThumbnail, sizeof(kGoogleThumbnail)));
   }
 
-  const FaviconSizes GetFaviconSizesSmallAndLarge() {
-    FaviconSizes sizes_small_and_large;
-    sizes_small_and_large.push_back(kSmallSize);
-    sizes_small_and_large.push_back(kLargeSize);
-    return sizes_small_and_large;
-  }
-
   scoped_ptr<SkBitmap> google_bitmap_;
 
   base::ScopedTempDir temp_dir_;
@@ -128,8 +121,7 @@
   scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data));
 
   GURL url("http://google.com");
-  chrome::FaviconID icon_id =
-      db.AddFavicon(url, chrome::FAVICON, GetFaviconSizesSmallAndLarge());
+  chrome::FaviconID icon_id = db.AddFavicon(url, chrome::FAVICON);
   base::Time time = base::Time::Now();
   FaviconBitmapID bitmap1_id = db.AddFaviconBitmap(icon_id, favicon, time,
                                                    kSmallSize);
@@ -140,13 +132,10 @@
 
   GURL url_out;
   chrome::IconType icon_type_out;
-  FaviconSizes favicon_sizes_out;
-  EXPECT_TRUE(db.GetFaviconHeader(icon_id, &url_out, &icon_type_out,
-                                  &favicon_sizes_out));
+  EXPECT_TRUE(db.GetFaviconHeader(icon_id, &url_out, &icon_type_out));
 
   EXPECT_EQ(url, url_out);
   EXPECT_EQ(chrome::FAVICON, icon_type_out);
-  EXPECT_EQ(GetFaviconSizesSmallAndLarge(), favicon_sizes_out);
 
   std::vector<FaviconBitmap> favicon_bitmaps_out;
   EXPECT_TRUE(db.GetFaviconBitmaps(icon_id, &favicon_bitmaps_out));
@@ -195,7 +184,6 @@
   base::Time time = base::Time::Now();
   chrome::FaviconID id = db.AddFavicon(url,
                                        chrome::TOUCH_ICON,
-                                       GetDefaultFaviconSizes(),
                                        favicon,
                                        time,
                                        gfx::Size());
@@ -216,7 +204,7 @@
 
   GURL url("http://google.com");
   chrome::FaviconID id =
-      db.AddFavicon(url, chrome::TOUCH_ICON, GetDefaultFaviconSizes());
+      db.AddFavicon(url, chrome::TOUCH_ICON);
 
   EXPECT_LT(0, db.AddIconMapping(url, id));
   std::vector<IconMapping> icon_mapping;
@@ -227,7 +215,7 @@
 
   GURL url1("http://www.google.com/");
   chrome::FaviconID new_id =
-      db.AddFavicon(url1, chrome::TOUCH_ICON, GetDefaultFaviconSizes());
+      db.AddFavicon(url1, chrome::TOUCH_ICON);
   EXPECT_TRUE(db.UpdateIconMapping(icon_mapping.front().mapping_id, new_id));
 
   icon_mapping.clear();
@@ -248,13 +236,13 @@
 
   GURL url("http://google.com");
   chrome::FaviconID id =
-      db.AddFavicon(url, chrome::TOUCH_ICON, GetDefaultFaviconSizes());
+      db.AddFavicon(url, chrome::TOUCH_ICON);
   base::Time time = base::Time::Now();
   db.AddFaviconBitmap(id, favicon, time, gfx::Size());
   EXPECT_LT(0, db.AddIconMapping(url, id));
 
   chrome::FaviconID id2 =
-      db.AddFavicon(url, chrome::FAVICON, GetDefaultFaviconSizes());
+      db.AddFavicon(url, chrome::FAVICON);
   EXPECT_LT(0, db.AddIconMapping(url, id2));
   ASSERT_NE(id, id2);
 
@@ -280,15 +268,13 @@
 
   GURL url("http://google.com");
 
-  chrome::FaviconID id1 =
-      db.AddFavicon(url, chrome::TOUCH_ICON, GetFaviconSizesSmallAndLarge());
+  chrome::FaviconID id1 = db.AddFavicon(url, chrome::TOUCH_ICON);
   base::Time time = base::Time::Now();
   db.AddFaviconBitmap(id1, favicon, time, kSmallSize);
   db.AddFaviconBitmap(id1, favicon, time, kLargeSize);
   EXPECT_LT(0, db.AddIconMapping(url, id1));
 
-  chrome::FaviconID id2 =
-      db.AddFavicon(url, chrome::FAVICON, GetFaviconSizesSmallAndLarge());
+  chrome::FaviconID id2 = db.AddFavicon(url, chrome::FAVICON);
   EXPECT_NE(id1, id2);
   db.AddFaviconBitmap(id2, favicon, time, kSmallSize);
   EXPECT_LT(0, db.AddIconMapping(url, id2));
@@ -437,6 +423,53 @@
   EXPECT_EQ(0, statement.ColumnInt(4));
 }
 
+// Test upgrading database to version 7.
+TEST_F(ThumbnailDatabaseTest, UpgradeToVersion7) {
+  ThumbnailDatabase db;
+  ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
+  db.BeginTransaction();
+
+  const char* name = "favicons";
+  std::string sql;
+  sql.append("DROP TABLE IF EXISTS ");
+  sql.append(name);
+  EXPECT_TRUE(db.db_.Execute(sql.c_str()));
+
+  sql.clear();
+  sql.append("CREATE TABLE ");
+  sql.append(name);
+  sql.append("("
+             "id INTEGER PRIMARY KEY,"
+             "url LONGVARCHAR NOT NULL,"
+             "icon_type INTEGER DEFAULT 1,"
+             "sizes LONGVARCHAR)");
+  EXPECT_TRUE(db.db_.Execute(sql.c_str()));
+
+  int favicon_id = 1;
+  GURL url("http://google.com");
+
+  sql::Statement statement;
+  statement.Assign(db.db_.GetCachedStatement(SQL_FROM_HERE,
+      "INSERT INTO favicons (id, url, icon_type, sizes) "
+      "VALUES (?, ?, ?, ?)"));
+  statement.BindInt(0, favicon_id);
+  statement.BindString(1, URLDatabase::GURLToDatabaseURL(url));
+  statement.BindInt(2, chrome::TOUCH_ICON);
+  statement.BindCString(3, "Data which happened to be there");
+  EXPECT_TRUE(statement.Run());
+
+  EXPECT_TRUE(db.UpgradeToVersion7());
+
+  EXPECT_FALSE(db.db_.DoesColumnExist("favicons", "sizes"));
+
+  statement.Assign(db.db_.GetCachedStatement(SQL_FROM_HERE,
+      "SELECT id, url, icon_type FROM favicons"));
+  EXPECT_TRUE(statement.Step());
+  EXPECT_EQ(favicon_id, statement.ColumnInt(0));
+  EXPECT_EQ(url, GURL(statement.ColumnString(1)));
+  EXPECT_EQ(chrome::TOUCH_ICON, statement.ColumnInt(2));
+}
+
 // Test that only data moved to a temporary table is left in the main table
 // once the temporary table is committed.
 TEST_F(ThumbnailDatabaseTest, TemporaryTables) {
@@ -452,13 +485,11 @@
   scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data));
 
   GURL unkept_url("http://google.com/favicon2.ico");
-  chrome::FaviconID unkept_id = db.AddFavicon(
-      unkept_url, chrome::FAVICON, GetFaviconSizesSmallAndLarge());
+  chrome::FaviconID unkept_id = db.AddFavicon(unkept_url, chrome::FAVICON);
   db.AddFaviconBitmap(unkept_id, favicon, base::Time::Now(), kSmallSize);
 
   GURL kept_url("http://google.com/favicon.ico");
-  chrome::FaviconID kept_id =
-      db.AddFavicon(kept_url, chrome::FAVICON, GetFaviconSizesSmallAndLarge());
+  chrome::FaviconID kept_id = db.AddFavicon(kept_url, chrome::FAVICON);
   db.AddFaviconBitmap(kept_id, favicon, base::Time::Now(), kLargeSize);
 
   GURL page_url("http://google.com");
@@ -503,8 +534,7 @@
       new base::RefCountedBytes(data2));
 
   GURL url("http://google.com");
-  chrome::FaviconID id =
-      db.AddFavicon(url, chrome::FAVICON, GetFaviconSizesSmallAndLarge());
+  chrome::FaviconID id = db.AddFavicon(url, chrome::FAVICON);
   base::Time last_updated = base::Time::Now();
   db.AddFaviconBitmap(id, favicon1, last_updated, kSmallSize);
   db.AddFaviconBitmap(id, favicon2, last_updated, kLargeSize);
@@ -530,7 +560,6 @@
 
   chrome::FaviconID id = db.AddFavicon(icon_url,
                                        chrome::FAVICON,
-                                       GetDefaultFaviconSizes(),
                                        favicon,
                                        time,
                                        gfx::Size());
@@ -550,7 +579,6 @@
 
   chrome::FaviconID id2 = db.AddFavicon(icon_url,
                                         chrome::TOUCH_ICON,
-                                        GetDefaultFaviconSizes(),
                                         favicon2,
                                         time,
                                         gfx::Size());
@@ -570,7 +598,6 @@
 
   chrome::FaviconID id3 = db.AddFavicon(icon_url,
                                         chrome::TOUCH_PRECOMPOSED_ICON,
-                                        GetDefaultFaviconSizes(),
                                         favicon3,
                                         time,
                                         gfx::Size());
@@ -598,7 +625,6 @@
 
   chrome::FaviconID id1 = db.AddFavicon(url,
                                         chrome::FAVICON,
-                                        GetDefaultFaviconSizes(),
                                         favicon,
                                         time,
                                         gfx::Size());
@@ -606,7 +632,6 @@
 
   chrome::FaviconID id2 = db.AddFavicon(url,
                                         chrome::TOUCH_ICON,
-                                        GetDefaultFaviconSizes(),
                                         favicon,
                                         time,
                                         gfx::Size());
@@ -614,7 +639,6 @@
 
   chrome::FaviconID id3 = db.AddFavicon(url,
                                         chrome::TOUCH_ICON,
-                                        GetDefaultFaviconSizes(),
                                         favicon,
                                         time,
                                         gfx::Size());
@@ -665,7 +689,6 @@
   base::Time time = base::Time::Now();
   chrome::FaviconID id1 = db.AddFavicon(GURL("http://google.com"),
                                         chrome::FAVICON,
-                                        GetDefaultFaviconSizes(),
                                         favicon,
                                         time,
                                         gfx::Size());
@@ -675,7 +698,6 @@
   time = base::Time::Now();
   chrome::FaviconID id2 = db.AddFavicon(GURL("http://www.google.com/icon"),
                                         chrome::TOUCH_ICON,
-                                        GetDefaultFaviconSizes(),
                                         favicon,
                                         time,
                                         gfx::Size());
@@ -685,7 +707,6 @@
   time = base::Time::Now();
   chrome::FaviconID id3 = db.AddFavicon(GURL("http://www.google.com/icon"),
                                         chrome::TOUCH_ICON,
-                                        GetDefaultFaviconSizes(),
                                         favicon,
                                         time,
                                         gfx::Size());
@@ -717,23 +738,21 @@
 
   // Add a favicon which will have icon_mappings
   chrome::FaviconID id1 = db.AddFavicon(
-      GURL("http://google.com"), chrome::FAVICON, GetDefaultFaviconSizes());
+      GURL("http://google.com"), chrome::FAVICON);
   EXPECT_NE(0, id1);
   base::Time time = base::Time::Now();
   db.AddFaviconBitmap(id1, favicon, time, gfx::Size());
 
   // Add another type of favicon
   chrome::FaviconID id2 = db.AddFavicon(GURL("http://www.google.com/icon"),
-                                        chrome::TOUCH_ICON,
-                                        GetDefaultFaviconSizes());
+                                        chrome::TOUCH_ICON);
   EXPECT_NE(0, id2);
   time = base::Time::Now();
   db.AddFaviconBitmap(id2, favicon, time, gfx::Size());
 
   // Add 3rd favicon
   chrome::FaviconID id3 = db.AddFavicon(GURL("http://www.google.com/icon"),
-                                        chrome::TOUCH_ICON,
-                                        GetDefaultFaviconSizes());
+                                        chrome::TOUCH_ICON);
   EXPECT_NE(0, id3);
   time = base::Time::Now();
   db.AddFaviconBitmap(id3, favicon, time, gfx::Size());
@@ -834,7 +853,6 @@
   GURL icon_url1("http://google.com/favicon.ico");
   chrome::FaviconID touch_icon_id1 = db.AddFavicon(icon_url1,
                                                    chrome::TOUCH_ICON,
-                                                   GetDefaultFaviconSizes(),
                                                    favicon,
                                                    base::Time::Now(),
                                                    gfx::Size());
@@ -844,7 +862,6 @@
 
   chrome::FaviconID favicon_id1 = db.AddFavicon(icon_url1,
                                                 chrome::FAVICON,
-                                                GetDefaultFaviconSizes(),
                                                 favicon,
                                                 base::Time::Now(),
                                                 gfx::Size());
@@ -856,7 +873,6 @@
   GURL icon_url2("http://chromium.org/favicon.ico");
   chrome::FaviconID favicon_id2 = db.AddFavicon(icon_url2,
                                                 chrome::FAVICON,
-                                                GetDefaultFaviconSizes(),
                                                 favicon,
                                                 base::Time::Now(),
                                                 gfx::Size());
@@ -903,38 +919,4 @@
   EXPECT_FALSE(enumerator2.GetNextIconMapping(&icon_mapping));
 }
 
-TEST_F(ThumbnailDatabaseTest, FaviconSizesToAndFromString) {
-  // Invalid input.
-  FaviconSizes sizes_missing_height;
-  ThumbnailDatabase::DatabaseStringToFaviconSizes("0 0 10",
-      &sizes_missing_height);
-  EXPECT_EQ(0u, sizes_missing_height.size());
-
-  FaviconSizes sizes_non_int;
-  ThumbnailDatabase::DatabaseStringToFaviconSizes("0 0 a 10",
-      &sizes_non_int);
-  EXPECT_EQ(0u, sizes_non_int.size());
-
-  // Valid input.
-  FaviconSizes sizes_empty;
-  ThumbnailDatabase::DatabaseStringToFaviconSizes(std::string(), &sizes_empty);
-  EXPECT_EQ(0u, sizes_empty.size());
-
-  FaviconSizes sizes_valid;
-  ThumbnailDatabase::DatabaseStringToFaviconSizes("10 15 20 25", &sizes_valid);
-  EXPECT_EQ(2u, sizes_valid.size());
-  if (sizes_valid[0] == gfx::Size(10, 15)) {
-    EXPECT_EQ(sizes_valid[1], gfx::Size(20, 25));
-  } else {
-    EXPECT_EQ(sizes_valid[0], gfx::Size(20, 25));
-    EXPECT_EQ(sizes_valid[1], gfx::Size(10, 15));
-  }
-
-  std::string sizes_as_string;
-  ThumbnailDatabase::FaviconSizesToDatabaseString(sizes_valid,
-                                                  &sizes_as_string);
-  EXPECT_TRUE(sizes_as_string == "10 15 20 25" ||
-              sizes_as_string == "20 25 10 15");
-}
-
 }  // namespace history
diff --git a/chrome/browser/history/top_sites.h b/chrome/browser/history/top_sites.h
index 47351ad..b55821d 100644
--- a/chrome/browser/history/top_sites.h
+++ b/chrome/browser/history/top_sites.h
@@ -13,9 +13,9 @@
 #include "chrome/browser/history/history_service.h"
 #include "chrome/browser/history/history_types.h"
 #include "chrome/common/thumbnail_score.h"
-#include "googleurl/src/gurl.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/gfx/image/image.h"
+#include "url/gurl.h"
 
 class Profile;
 
diff --git a/chrome/browser/history/top_sites_backend.cc b/chrome/browser/history/top_sites_backend.cc
index bdf589c..58bf38d 100644
--- a/chrome/browser/history/top_sites_backend.cc
+++ b/chrome/browser/history/top_sites_backend.cc
@@ -6,7 +6,6 @@
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
-#include "base/file_util.h"
 #include "base/files/file_path.h"
 #include "base/memory/ref_counted.h"
 #include "chrome/browser/history/top_sites_database.h"
@@ -137,7 +136,7 @@
 void TopSitesBackend::ResetDatabaseOnDBThread(const base::FilePath& file_path) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
   db_.reset(NULL);
-  file_util::Delete(db_path_, false);
+  sql::Connection::Delete(db_path_);
   db_.reset(new TopSitesDatabase());
   InitDBOnDBThread(db_path_);
 }
diff --git a/chrome/browser/history/top_sites_database.cc b/chrome/browser/history/top_sites_database.cc
index f63dc16..ec0e1de 100644
--- a/chrome/browser/history/top_sites_database.cc
+++ b/chrome/browser/history/top_sites_database.cc
@@ -43,9 +43,7 @@
     // the entries as they are no longer applicable, but it's safest to just
     // remove the file and start over.
     db_.reset(NULL);
-    if (!file_util::Delete(db_name, false) &&
-        !file_util::Delete(db_name, false)) {
-      // Try to delete twice. If we can't, fail.
+    if (!sql::Connection::Delete(db_name)) {
       LOG(ERROR) << "unable to delete old TopSites file";
       return false;
     }
diff --git a/chrome/browser/history/top_sites_impl.h b/chrome/browser/history/top_sites_impl.h
index f76aaab..025ac4d 100644
--- a/chrome/browser/history/top_sites_impl.h
+++ b/chrome/browser/history/top_sites_impl.h
@@ -16,8 +16,8 @@
 #include "base/gtest_prod_util.h"
 #include "base/memory/ref_counted.h"
 #include "base/synchronization/lock.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/common/cancelable_request.h"
 #include "chrome/browser/history/history_service.h"
 #include "chrome/browser/history/history_types.h"
@@ -26,9 +26,9 @@
 #include "chrome/browser/history/top_sites_backend.h"
 #include "chrome/common/cancelable_task_tracker.h"
 #include "chrome/common/thumbnail_score.h"
-#include "googleurl/src/gurl.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/gfx/image/image.h"
+#include "url/gurl.h"
 
 class Profile;
 
diff --git a/chrome/browser/history/top_sites_impl_unittest.cc b/chrome/browser/history/top_sites_impl_unittest.cc
index 5f5179e..566e8e9 100644
--- a/chrome/browser/history/top_sites_impl_unittest.cc
+++ b/chrome/browser/history/top_sites_impl_unittest.cc
@@ -33,7 +33,6 @@
 #include "chrome/tools/profiles/thumbnail-inl.h"
 #include "content/public/test/test_browser_thread.h"
 #include "content/public/test/test_utils.h"
-#include "googleurl/src/gurl.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
@@ -41,6 +40,7 @@
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/codec/jpeg_codec.h"
+#include "url/gurl.h"
 
 using content::BrowserThread;
 
@@ -1198,8 +1198,8 @@
 
   // Remove the TopSites file. This forces TopSites to wait until history loads
   // before TopSites is considered loaded.
-  file_util::Delete(profile()->GetPath().Append(chrome::kTopSitesFilename),
-                    false);
+  sql::Connection::Delete(
+      profile()->GetPath().Append(chrome::kTopSitesFilename));
 
   // Create TopSites, but not History.
   profile()->CreateTopSites();
diff --git a/chrome/browser/history/top_sites_likely_impl.h b/chrome/browser/history/top_sites_likely_impl.h
index 7080f22..89122d4 100644
--- a/chrome/browser/history/top_sites_likely_impl.h
+++ b/chrome/browser/history/top_sites_likely_impl.h
@@ -16,8 +16,8 @@
 #include "base/gtest_prod_util.h"
 #include "base/memory/ref_counted.h"
 #include "base/synchronization/lock.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/common/cancelable_request.h"
 #include "chrome/browser/history/history_service.h"
 #include "chrome/browser/history/history_types.h"
@@ -26,9 +26,9 @@
 #include "chrome/browser/history/top_sites_backend.h"
 #include "chrome/common/cancelable_task_tracker.h"
 #include "chrome/common/thumbnail_score.h"
-#include "googleurl/src/gurl.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/gfx/image/image.h"
+#include "url/gurl.h"
 
 class Profile;
 
diff --git a/chrome/browser/history/top_sites_likely_impl_unittest.cc b/chrome/browser/history/top_sites_likely_impl_unittest.cc
index 34eb652..14529ca 100644
--- a/chrome/browser/history/top_sites_likely_impl_unittest.cc
+++ b/chrome/browser/history/top_sites_likely_impl_unittest.cc
@@ -33,7 +33,6 @@
 #include "chrome/tools/profiles/thumbnail-inl.h"
 #include "content/public/test/test_browser_thread.h"
 #include "content/public/test/test_utils.h"
-#include "googleurl/src/gurl.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
@@ -41,6 +40,7 @@
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/codec/jpeg_codec.h"
+#include "url/gurl.h"
 
 using content::BrowserThread;
 
@@ -1199,8 +1199,8 @@
 
   // Remove the TopSites file. This forces TopSites to wait until history loads
   // before TopSites is considered loaded.
-  file_util::Delete(profile()->GetPath().Append(chrome::kTopSitesFilename),
-                    false);
+  sql::Connection::Delete(
+      profile()->GetPath().Append(chrome::kTopSitesFilename));
 
   // Create TopSites, but not History.
   profile()->CreateTopSites();
diff --git a/chrome/browser/history/typed_url_syncable_service.cc b/chrome/browser/history/typed_url_syncable_service.cc
index 3b6d57e..fcb3cfa 100644
--- a/chrome/browser/history/typed_url_syncable_service.cc
+++ b/chrome/browser/history/typed_url_syncable_service.cc
@@ -119,6 +119,7 @@
   // TODO(mgist): Add implementation
 
   return syncer::SyncError(FROM_HERE,
+                           syncer::SyncError::DATATYPE_ERROR,
                            "Typed url syncable service is not implemented.",
                            syncer::TYPED_URLS);
 }
diff --git a/chrome/browser/history/url_database.cc b/chrome/browser/history/url_database.cc
index 0856d25..4f5a72d 100644
--- a/chrome/browser/history/url_database.cc
+++ b/chrome/browser/history/url_database.cc
@@ -12,9 +12,9 @@
 #include "base/i18n/case_conversion.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/common/url_constants.h"
-#include "googleurl/src/gurl.h"
 #include "sql/statement.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "url/gurl.h"
 
 namespace history {
 
@@ -358,6 +358,32 @@
   return true;
 }
 
+bool URLDatabase::GetTextMatches(const string16& query,
+                                 URLRows* results) {
+  ScopedVector<QueryNode> query_nodes;
+  query_parser_.ParseQueryNodes(query, &query_nodes.get());
+
+  results->clear();
+  sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE,
+      "SELECT" HISTORY_URL_ROW_FIELDS "FROM urls WHERE hidden = 0"));
+
+  while (statement.Step()) {
+    std::vector<QueryWord> query_words;
+    string16 url = base::i18n::ToLower(statement.ColumnString16(1));
+    query_parser_.ExtractQueryWords(url, &query_words);
+    string16 title = base::i18n::ToLower(statement.ColumnString16(2));
+    query_parser_.ExtractQueryWords(title, &query_words);
+
+    if (query_parser_.DoesQueryMatch(query_words, query_nodes.get())) {
+      history::URLResult info;
+      FillURLRow(statement, &info);
+      if (info.url().is_valid())
+        results->push_back(info);
+    }
+  }
+  return !results->empty();
+}
+
 bool URLDatabase::InitKeywordSearchTermsTable() {
   has_keyword_search_terms_ = true;
   if (!GetDB().DoesTableExist("keyword_search_terms")) {
diff --git a/chrome/browser/history/url_database.h b/chrome/browser/history/url_database.h
index 5cf44c2..c486560 100644
--- a/chrome/browser/history/url_database.h
+++ b/chrome/browser/history/url_database.h
@@ -7,6 +7,7 @@
 
 #include "base/basictypes.h"
 #include "chrome/browser/history/history_types.h"
+#include "chrome/browser/history/query_parser.h"
 #include "chrome/browser/search_engines/template_url_id.h"
 #include "sql/statement.h"
 
@@ -189,6 +190,12 @@
                                bool allow_base,
                                history::URLRow* info);
 
+  // History search ------------------------------------------------------------
+
+  // Performs a brute force search over the database to find any URLs or titles
+  // which match the |query| string.  Returns any matches in |results|.
+  bool GetTextMatches(const string16& query, URLRows* results);
+
   // Keyword Search Terms ------------------------------------------------------
 
   // Sets the search terms for the specified url/keyword pair.
@@ -289,6 +296,8 @@
   // have keyword search terms.
   bool has_keyword_search_terms_;
 
+  QueryParser query_parser_;
+
   DISALLOW_COPY_AND_ASSIGN(URLDatabase);
 };
 
@@ -303,6 +312,6 @@
     " urls.id, urls.url, urls.title, urls.visit_count, urls.typed_count, " \
     "urls.last_visit_time, urls.hidden "
 
-}  // history
+}  // namespace history
 
 #endif  // CHROME_BROWSER_HISTORY_URL_DATABASE_H_
diff --git a/chrome/browser/history/url_index_private_data.cc b/chrome/browser/history/url_index_private_data.cc
index 9ddd230..3315adb 100644
--- a/chrome/browser/history/url_index_private_data.cc
+++ b/chrome/browser/history/url_index_private_data.cc
@@ -18,7 +18,7 @@
 #include "base/metrics/histogram.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/autocomplete/autocomplete_provider.h"
 #include "chrome/browser/autocomplete/url_prefix.h"
 #include "chrome/browser/bookmarks/bookmark_service.h"
diff --git a/chrome/browser/history/visit_database.cc b/chrome/browser/history/visit_database.cc
index 4ef7f21..883fe6f 100644
--- a/chrome/browser/history/visit_database.cc
+++ b/chrome/browser/history/visit_database.cc
@@ -118,6 +118,39 @@
   return statement.Succeeded();
 }
 
+// static
+bool VisitDatabase::FillVisitVectorWithOptions(sql::Statement& statement,
+                                               const QueryOptions& options,
+                                               VisitVector* visits) {
+  std::set<URLID> found_urls;
+
+  // Keeps track of the day that |found_urls| is holding the URLs for, in order
+  // to handle removing per-day duplicates.
+  base::Time found_urls_midnight;
+
+  while (statement.Step()) {
+    VisitRow visit;
+    FillVisitRow(statement, &visit);
+
+    if (options.duplicate_policy != QueryOptions::KEEP_ALL_DUPLICATES) {
+      if (options.duplicate_policy == QueryOptions::REMOVE_DUPLICATES_PER_DAY &&
+          found_urls_midnight != visit.visit_time.LocalMidnight()) {
+        found_urls.clear();
+        found_urls_midnight = visit.visit_time.LocalMidnight();
+      }
+      // Make sure the URL this visit corresponds to is unique.
+      if (found_urls.find(visit.url_id) != found_urls.end())
+        continue;
+      found_urls.insert(visit.url_id);
+    }
+
+    if (static_cast<int>(visits->size()) >= options.EffectiveMaxCount())
+      return true;
+    visits->push_back(visit);
+  }
+  return false;
+}
+
 VisitID VisitDatabase::AddVisit(VisitRow* visit, VisitSource source) {
   sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE,
       "INSERT INTO visits "
@@ -245,6 +278,31 @@
   return FillVisitVector(statement, visits);
 }
 
+bool VisitDatabase::GetVisitsForURLWithOptions(URLID url_id,
+                                               const QueryOptions& options,
+                                               VisitVector* visits) {
+  visits->clear();
+
+  if (options.REMOVE_ALL_DUPLICATES) {
+    VisitRow visit_row;
+    VisitID visit_id = GetMostRecentVisitForURL(url_id, &visit_row);
+    if (visit_id && options.EffectiveMaxCount() != 0) {
+      visits->push_back(visit_row);
+    }
+    return options.EffectiveMaxCount() == 0 && visit_id;
+  } else {
+    sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE,
+        "SELECT" HISTORY_VISIT_ROW_FIELDS
+        "FROM visits "
+        "WHERE url=? AND visit_time >= ? AND visit_time < ? "
+        "ORDER BY visit_time DESC"));
+    statement.BindInt64(0, url_id);
+    statement.BindInt64(1, options.EffectiveBeginTime());
+    statement.BindInt64(2, options.EffectiveEndTime());
+
+    return FillVisitVectorWithOptions(statement, options, visits);
+  }
+}
 
 bool VisitDatabase::GetVisitsForTimes(const std::vector<base::Time>& times,
                                       VisitVector* visits) {
@@ -333,33 +391,7 @@
   statement.BindInt(5, content::PAGE_TRANSITION_MANUAL_SUBFRAME);
   statement.BindInt(6, content::PAGE_TRANSITION_KEYWORD_GENERATED);
 
-  std::set<URLID> found_urls;
-
-  // Keeps track of the day that |found_urls| is holding the URLs for, in order
-  // to handle removing per-day duplicates.
-  base::Time found_urls_midnight;
-
-  while (statement.Step()) {
-    VisitRow visit;
-    FillVisitRow(statement, &visit);
-
-    if (options.duplicate_policy != QueryOptions::KEEP_ALL_DUPLICATES) {
-      if (options.duplicate_policy == QueryOptions::REMOVE_DUPLICATES_PER_DAY &&
-          found_urls_midnight != visit.visit_time.LocalMidnight()) {
-        found_urls.clear();
-        found_urls_midnight = visit.visit_time.LocalMidnight();
-      }
-      // Make sure the URL this visit corresponds to is unique.
-      if (found_urls.find(visit.url_id) != found_urls.end())
-        continue;
-      found_urls.insert(visit.url_id);
-    }
-
-    if (static_cast<int>(visits->size()) >= options.EffectiveMaxCount())
-      return true;
-    visits->push_back(visit);
-  }
-  return false;
+  return FillVisitVectorWithOptions(statement, options, visits);
 }
 
 void VisitDatabase::GetDirectVisitsDuringTimes(const VisitFilter& time_filter,
diff --git a/chrome/browser/history/visit_database.h b/chrome/browser/history/visit_database.h
index 18efc3c..effaa8f 100644
--- a/chrome/browser/history/visit_database.h
+++ b/chrome/browser/history/visit_database.h
@@ -63,6 +63,15 @@
   // Returns true on success (although there may still be no matches).
   bool GetIndexedVisitsForURL(URLID url_id, VisitVector* visits);
 
+  // Fills in the given vector with the visits for the given page ID which
+  // match the set of options passed, sorted in ascending order of date.
+  //
+  // Returns true if there are more results available, i.e. if the number of
+  // results was restricted by |options.max_count|.
+  bool GetVisitsForURLWithOptions(URLID url_id,
+                                  const QueryOptions& options,
+                                  VisitVector* visits);
+
   // Fills the vector with all visits with times in the given list.
   //
   // The results will be in no particular order.  Also, no duplicate
@@ -202,6 +211,14 @@
   // hasn't happened yet.
   static bool FillVisitVector(sql::Statement& statement, VisitVector* visits);
 
+  // Convenience to fill a VisitVector while respecting the set of options.
+  // |statement| should order the query decending by visit_time to ensure
+  // correct duplicate management behavior. Assumes that statement.step()
+  // hasn't happened yet.
+  static bool FillVisitVectorWithOptions(sql::Statement& statement,
+                                         const QueryOptions& options,
+                                         VisitVector* visits);
+
   // Called by the derived classes to migrate the older visits table which
   // don't have visit_duration column yet.
   bool MigrateVisitsWithoutDuration();
@@ -216,6 +233,6 @@
     " id,url,visit_time,from_visit,transition,segment_id,is_indexed," \
     "visit_duration "
 
-}  // history
+}  // namespace history
 
 #endif  // CHROME_BROWSER_HISTORY_VISIT_DATABASE_H_
diff --git a/chrome/browser/history/visit_database_unittest.cc b/chrome/browser/history/visit_database_unittest.cc
index cac1394..a6146b4 100644
--- a/chrome/browser/history/visit_database_unittest.cc
+++ b/chrome/browser/history/visit_database_unittest.cc
@@ -9,7 +9,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/path_service.h"
 #include "base/strings/string_util.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/history/url_database.h"
 #include "chrome/browser/history/visit_database.h"
 #include "sql/connection.h"
diff --git a/chrome/browser/history/visit_filter.cc b/chrome/browser/history/visit_filter.cc
index 32ca426..0a5ab74 100644
--- a/chrome/browser/history/visit_filter.cc
+++ b/chrome/browser/history/visit_filter.cc
@@ -9,7 +9,7 @@
 #include <algorithm>
 
 #include "base/logging.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/history/history_types.h"
 
 namespace history {
diff --git a/chrome/browser/history/visit_filter.h b/chrome/browser/history/visit_filter.h
index ce68f98..deeacf3 100644
--- a/chrome/browser/history/visit_filter.h
+++ b/chrome/browser/history/visit_filter.h
@@ -8,7 +8,7 @@
 #include <vector>
 
 #include "base/gtest_prod_util.h"
-#include "base/time.h"
+#include "base/time/time.h"
 
 namespace history {
 
diff --git a/chrome/browser/history/visit_filter_unittest.cc b/chrome/browser/history/visit_filter_unittest.cc
index bc0b7b2..f100ad7 100644
--- a/chrome/browser/history/visit_filter_unittest.cc
+++ b/chrome/browser/history/visit_filter_unittest.cc
@@ -7,7 +7,7 @@
 #include <math.h>
 
 #include "base/logging.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/history/history_types.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/chrome/browser/history/web_history_service.cc b/chrome/browser/history/web_history_service.cc
index cea7f2f..8e91d69 100644
--- a/chrome/browser/history/web_history_service.cc
+++ b/chrome/browser/history/web_history_service.cc
@@ -16,13 +16,13 @@
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "google_apis/gaia/google_service_auth_error.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/load_flags.h"
 #include "net/base/url_util.h"
 #include "net/http/http_status_code.h"
 #include "net/http/http_util.h"
 #include "net/url_request/url_fetcher.h"
 #include "net/url_request/url_fetcher_delegate.h"
+#include "url/gurl.h"
 
 namespace history {
 
diff --git a/chrome/browser/icon_loader_linux.cc b/chrome/browser/icon_loader_linux.cc
index 3860ea0..acecd0a 100644
--- a/chrome/browser/icon_loader_linux.cc
+++ b/chrome/browser/icon_loader_linux.cc
@@ -11,9 +11,10 @@
 #include "base/logging.h"
 #include "base/message_loop.h"
 #include "base/nix/mime_util_xdg.h"
+#include "content/public/child/image_decoder_utils.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/gfx/image/image_skia.h"
-#include "webkit/glue/image_decoder.h"
+#include "ui/gfx/size.h"
 
 using std::string;
 
@@ -50,10 +51,10 @@
     string icon_data;
     file_util::ReadFileToString(filename, &icon_data);
 
-    webkit_glue::ImageDecoder decoder;
     SkBitmap bitmap;
-    bitmap = decoder.Decode(
+    bitmap = content::DecodeImage(
         reinterpret_cast<const unsigned char*>(icon_data.data()),
+        gfx::Size(),
         icon_data.length());
     if (!bitmap.empty()) {
       DCHECK_EQ(size_pixels, bitmap.width());
diff --git a/chrome/browser/idle_chromeos.cc b/chrome/browser/idle_chromeos.cc
index 9bb2f12..aa8c221 100644
--- a/chrome/browser/idle_chromeos.cc
+++ b/chrome/browser/idle_chromeos.cc
@@ -7,7 +7,7 @@
 #include "ash/session_state_delegate.h"
 #include "ash/shell.h"
 #include "ash/wm/user_activity_detector.h"
-#include "base/time.h"
+#include "base/time/time.h"
 
 void CalculateIdleTime(IdleTimeCallback notify) {
   base::TimeDelta idle_time = base::TimeTicks::Now() -
diff --git a/chrome/browser/iframe_browsertest.cc b/chrome/browser/iframe_browsertest.cc
index 3f650e3..941cb3f 100644
--- a/chrome/browser/iframe_browsertest.cc
+++ b/chrome/browser/iframe_browsertest.cc
@@ -9,7 +9,7 @@
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/web_contents.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 class IFrameTest : public InProcessBrowserTest {
  protected:
diff --git a/chrome/browser/importer/bookmark_html_reader.cc b/chrome/browser/importer/bookmark_html_reader.cc
new file mode 100644
index 0000000..e618bad
--- /dev/null
+++ b/chrome/browser/importer/bookmark_html_reader.cc
@@ -0,0 +1,432 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/importer/bookmark_html_reader.h"
+
+#include "base/callback.h"
+#include "base/file_util.h"
+#include "base/i18n/icu_string_conversions.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "base/time/time.h"
+#include "chrome/browser/favicon/favicon_util.h"
+#include "chrome/common/importer/imported_bookmark_entry.h"
+#include "chrome/common/importer/imported_favicon_usage.h"
+#include "content/public/common/url_constants.h"
+#include "net/base/data_url.h"
+#include "net/base/escape.h"
+#include "url/gurl.h"
+
+namespace {
+
+// Fetches the given |attribute| value from the |attribute_list|. Returns true
+// if successful, and |value| will contain the value.
+bool GetAttribute(const std::string& attribute_list,
+                  const std::string& attribute,
+                  std::string* value) {
+  const char kQuote[] = "\"";
+
+  size_t begin = attribute_list.find(attribute + "=" + kQuote);
+  if (begin == std::string::npos)
+    return false;  // Can't find the attribute.
+
+  begin += attribute.size() + 2;
+  size_t end = begin + 1;
+
+  while (end < attribute_list.size()) {
+    if (attribute_list[end] == '"' &&
+        attribute_list[end - 1] != '\\') {
+      break;
+    }
+    end++;
+  }
+
+  if (end == attribute_list.size())
+    return false;  // The value is not quoted.
+
+  *value = attribute_list.substr(begin, end - begin);
+  return true;
+}
+
+// Given the URL of a page and a favicon data URL, adds an appropriate record
+// to the given favicon usage vector.
+void DataURLToFaviconUsage(
+    const GURL& link_url,
+    const GURL& favicon_data,
+    std::vector<ImportedFaviconUsage>* favicons) {
+  if (!link_url.is_valid() || !favicon_data.is_valid() ||
+      !favicon_data.SchemeIs(chrome::kDataScheme))
+    return;
+
+  // Parse the data URL.
+  std::string mime_type, char_set, data;
+  if (!net::DataURL::Parse(favicon_data, &mime_type, &char_set, &data) ||
+      data.empty())
+    return;
+
+  ImportedFaviconUsage usage;
+  if (!FaviconUtil::ReencodeFavicon(
+          reinterpret_cast<const unsigned char*>(&data[0]),
+          data.size(), &usage.png_data))
+    return;  // Unable to decode.
+
+  // We need to make up a URL for the favicon. We use a version of the page's
+  // URL so that we can be sure it will not collide.
+  usage.favicon_url = GURL(std::string("made-up-favicon:") + link_url.spec());
+
+  // We only have one URL per favicon for Firefox 2 bookmarks.
+  usage.urls.insert(link_url);
+
+  favicons->push_back(usage);
+}
+
+}  // namespace
+
+namespace bookmark_html_reader {
+
+void ImportBookmarksFile(
+      const base::Callback<bool(void)>& cancellation_callback,
+      const base::Callback<bool(const GURL&)>& valid_url_callback,
+      const base::FilePath& file_path,
+      std::vector<ImportedBookmarkEntry>* bookmarks,
+      std::vector<ImportedFaviconUsage>* favicons) {
+  std::string content;
+  file_util::ReadFileToString(file_path, &content);
+  std::vector<std::string> lines;
+  base::SplitString(content, '\n', &lines);
+
+  base::string16 last_folder;
+  bool last_folder_on_toolbar = false;
+  bool last_folder_is_empty = true;
+  bool has_subfolder = false;
+  base::Time last_folder_add_date;
+  std::vector<base::string16> path;
+  size_t toolbar_folder_index = 0;
+  std::string charset;
+  for (size_t i = 0;
+       i < lines.size() &&
+           (cancellation_callback.is_null() || !cancellation_callback.Run());
+       ++i) {
+    std::string line;
+    TrimString(lines[i], " ", &line);
+
+    // Get the encoding of the bookmark file.
+    if (internal::ParseCharsetFromLine(line, &charset))
+      continue;
+
+    // Get the folder name.
+    if (internal::ParseFolderNameFromLine(line,
+                                          charset,
+                                          &last_folder,
+                                          &last_folder_on_toolbar,
+                                          &last_folder_add_date)) {
+      continue;
+    }
+
+    // Get the bookmark entry.
+    base::string16 title;
+    base::string16 shortcut;
+    GURL url, favicon;
+    base::Time add_date;
+    base::string16 post_data;
+    bool is_bookmark;
+    // TODO(jcampan): http://b/issue?id=1196285 we do not support POST based
+    //                keywords yet.
+    is_bookmark =
+        internal::ParseBookmarkFromLine(line, charset, &title,
+                                        &url, &favicon, &shortcut,
+                                        &add_date, &post_data) ||
+        internal::ParseMinimumBookmarkFromLine(line, charset, &title, &url);
+
+    if (is_bookmark)
+      last_folder_is_empty = false;
+
+    if (is_bookmark &&
+        post_data.empty() &&
+        (valid_url_callback.is_null() || valid_url_callback.Run(url))) {
+      if (toolbar_folder_index > path.size() && !path.empty()) {
+        NOTREACHED();  // error in parsing.
+        break;
+      }
+
+      ImportedBookmarkEntry entry;
+      entry.creation_time = add_date;
+      entry.url = url;
+      entry.title = title;
+
+      if (toolbar_folder_index) {
+        // The toolbar folder should be at the top level.
+        entry.in_toolbar = true;
+        entry.path.assign(path.begin() + toolbar_folder_index - 1, path.end());
+      } else {
+        // Add this bookmark to the list of |bookmarks|.
+        if (!has_subfolder && !last_folder.empty()) {
+          path.push_back(last_folder);
+          last_folder.clear();
+        }
+        entry.path.assign(path.begin(), path.end());
+      }
+      bookmarks->push_back(entry);
+
+      // Save the favicon. DataURLToFaviconUsage will handle the case where
+      // there is no favicon.
+      if (favicons)
+        DataURLToFaviconUsage(url, favicon, favicons);
+
+      continue;
+    }
+
+    // Bookmarks in sub-folder are encapsulated with <DL> tag.
+    if (StartsWithASCII(line, "<DL>", false)) {
+      has_subfolder = true;
+      if (!last_folder.empty()) {
+        path.push_back(last_folder);
+        last_folder.clear();
+      }
+      if (last_folder_on_toolbar && !toolbar_folder_index)
+        toolbar_folder_index = path.size();
+
+      // Mark next folder empty as initial state.
+      last_folder_is_empty = true;
+    } else if (StartsWithASCII(line, "</DL>", false)) {
+      if (path.empty())
+        break;  // Mismatch <DL>.
+
+      base::string16 folder_title = path.back();
+      path.pop_back();
+
+      if (last_folder_is_empty) {
+        // Empty folder should be added explicitly.
+        ImportedBookmarkEntry entry;
+        entry.is_folder = true;
+        entry.creation_time = last_folder_add_date;
+        entry.title = folder_title;
+        if (toolbar_folder_index) {
+          // The toolbar folder should be at the top level.
+          // Make sure we don't add the toolbar folder itself if it is empty.
+          if (toolbar_folder_index <= path.size()) {
+            entry.in_toolbar = true;
+            entry.path.assign(path.begin() + toolbar_folder_index - 1,
+                              path.end());
+            bookmarks->push_back(entry);
+          }
+        } else {
+          // Add this folder to the list of |bookmarks|.
+          entry.path.assign(path.begin(), path.end());
+          bookmarks->push_back(entry);
+        }
+
+        // Parent folder include current one, so it's not empty.
+        last_folder_is_empty = false;
+      }
+
+      if (toolbar_folder_index > path.size())
+        toolbar_folder_index = 0;
+    }
+  }
+}
+
+namespace internal {
+
+bool ParseCharsetFromLine(const std::string& line, std::string* charset) {
+  const char kCharset[] = "charset=";
+  if (StartsWithASCII(line, "<META", false) &&
+      (line.find("CONTENT=\"") != std::string::npos ||
+          line.find("content=\"") != std::string::npos)) {
+    size_t begin = line.find(kCharset);
+    if (begin == std::string::npos)
+      return false;
+    begin += std::string(kCharset).size();
+    size_t end = line.find_first_of('\"', begin);
+    *charset = line.substr(begin, end - begin);
+    return true;
+  }
+  return false;
+}
+
+bool ParseFolderNameFromLine(const std::string& line,
+                             const std::string& charset,
+                             base::string16* folder_name,
+                             bool* is_toolbar_folder,
+                             base::Time* add_date) {
+  const char kFolderOpen[] = "<DT><H3";
+  const char kFolderClose[] = "</H3>";
+  const char kToolbarFolderAttribute[] = "PERSONAL_TOOLBAR_FOLDER";
+  const char kAddDateAttribute[] = "ADD_DATE";
+
+  if (!StartsWithASCII(line, kFolderOpen, true))
+    return false;
+
+  size_t end = line.find(kFolderClose);
+  size_t tag_end = line.rfind('>', end) + 1;
+  // If no end tag or start tag is broken, we skip to find the folder name.
+  if (end == std::string::npos || tag_end < arraysize(kFolderOpen))
+    return false;
+
+  base::CodepageToUTF16(line.substr(tag_end, end - tag_end), charset.c_str(),
+                        base::OnStringConversionError::SKIP, folder_name);
+  *folder_name = net::UnescapeForHTML(*folder_name);
+
+  std::string attribute_list = line.substr(arraysize(kFolderOpen),
+      tag_end - arraysize(kFolderOpen) - 1);
+  std::string value;
+
+  // Add date
+  if (GetAttribute(attribute_list, kAddDateAttribute, &value)) {
+    int64 time;
+    base::StringToInt64(value, &time);
+    // Upper bound it at 32 bits.
+    if (0 < time && time < (1LL << 32))
+      *add_date = base::Time::FromTimeT(time);
+  }
+
+  if (GetAttribute(attribute_list, kToolbarFolderAttribute, &value) &&
+      LowerCaseEqualsASCII(value, "true"))
+    *is_toolbar_folder = true;
+  else
+    *is_toolbar_folder = false;
+
+  return true;
+}
+
+bool ParseBookmarkFromLine(const std::string& line,
+                           const std::string& charset,
+                           base::string16* title,
+                           GURL* url,
+                           GURL* favicon,
+                           base::string16* shortcut,
+                           base::Time* add_date,
+                           base::string16* post_data) {
+  const char kItemOpen[] = "<DT><A";
+  const char kItemClose[] = "</A>";
+  const char kFeedURLAttribute[] = "FEEDURL";
+  const char kHrefAttribute[] = "HREF";
+  const char kIconAttribute[] = "ICON";
+  const char kShortcutURLAttribute[] = "SHORTCUTURL";
+  const char kAddDateAttribute[] = "ADD_DATE";
+  const char kPostDataAttribute[] = "POST_DATA";
+
+  title->clear();
+  *url = GURL();
+  *favicon = GURL();
+  shortcut->clear();
+  post_data->clear();
+  *add_date = base::Time();
+
+  if (!StartsWithASCII(line, kItemOpen, true))
+    return false;
+
+  size_t end = line.find(kItemClose);
+  size_t tag_end = line.rfind('>', end) + 1;
+  if (end == std::string::npos || tag_end < arraysize(kItemOpen))
+    return false;  // No end tag or start tag is broken.
+
+  std::string attribute_list = line.substr(arraysize(kItemOpen),
+      tag_end - arraysize(kItemOpen) - 1);
+
+  // We don't import Live Bookmark folders, which is Firefox's RSS reading
+  // feature, since the user never necessarily bookmarked them and we don't
+  // have this feature to update their contents.
+  std::string value;
+  if (GetAttribute(attribute_list, kFeedURLAttribute, &value))
+    return false;
+
+  // Title
+  base::CodepageToUTF16(line.substr(tag_end, end - tag_end), charset.c_str(),
+                        base::OnStringConversionError::SKIP, title);
+  *title = net::UnescapeForHTML(*title);
+
+  // URL
+  if (GetAttribute(attribute_list, kHrefAttribute, &value)) {
+    base::string16 url16;
+    base::CodepageToUTF16(value, charset.c_str(),
+                          base::OnStringConversionError::SKIP, &url16);
+    url16 = net::UnescapeForHTML(url16);
+
+    *url = GURL(url16);
+  }
+
+  // Favicon
+  if (GetAttribute(attribute_list, kIconAttribute, &value))
+    *favicon = GURL(value);
+
+  // Keyword
+  if (GetAttribute(attribute_list, kShortcutURLAttribute, &value)) {
+    base::CodepageToUTF16(value, charset.c_str(),
+                          base::OnStringConversionError::SKIP, shortcut);
+    *shortcut = net::UnescapeForHTML(*shortcut);
+  }
+
+  // Add date
+  if (GetAttribute(attribute_list, kAddDateAttribute, &value)) {
+    int64 time;
+    base::StringToInt64(value, &time);
+    // Upper bound it at 32 bits.
+    if (0 < time && time < (1LL << 32))
+      *add_date = base::Time::FromTimeT(time);
+  }
+
+  // Post data.
+  if (GetAttribute(attribute_list, kPostDataAttribute, &value)) {
+    base::CodepageToUTF16(value, charset.c_str(),
+                          base::OnStringConversionError::SKIP, post_data);
+    *post_data = net::UnescapeForHTML(*post_data);
+  }
+
+  return true;
+}
+
+bool ParseMinimumBookmarkFromLine(const std::string& line,
+                                  const std::string& charset,
+                                  base::string16* title,
+                                  GURL* url) {
+  const char kItemOpen[] = "<DT><A";
+  const char kItemClose[] = "</";
+  const char kHrefAttributeUpper[] = "HREF";
+  const char kHrefAttributeLower[] = "href";
+
+  title->clear();
+  *url = GURL();
+
+  // Case-insensitive check of open tag.
+  if (!StartsWithASCII(line, kItemOpen, false))
+    return false;
+
+  // Find any close tag.
+  size_t end = line.find(kItemClose);
+  size_t tag_end = line.rfind('>', end) + 1;
+  if (end == std::string::npos || tag_end < arraysize(kItemOpen))
+    return false;  // No end tag or start tag is broken.
+
+  std::string attribute_list = line.substr(arraysize(kItemOpen),
+      tag_end - arraysize(kItemOpen) - 1);
+
+  // Title
+  base::CodepageToUTF16(line.substr(tag_end, end - tag_end), charset.c_str(),
+                        base::OnStringConversionError::SKIP, title);
+  *title = net::UnescapeForHTML(*title);
+
+  // URL
+  std::string value;
+  if (GetAttribute(attribute_list, kHrefAttributeUpper, &value) ||
+      GetAttribute(attribute_list, kHrefAttributeLower, &value)) {
+    if (charset.length() != 0) {
+      base::string16 url16;
+      base::CodepageToUTF16(value, charset.c_str(),
+                            base::OnStringConversionError::SKIP, &url16);
+      url16 = net::UnescapeForHTML(url16);
+
+      *url = GURL(url16);
+    } else {
+      *url = GURL(value);
+    }
+  }
+
+  return true;
+}
+
+}  // namespace internal
+
+}  // namespace bookmark_html_reader
diff --git a/chrome/browser/importer/bookmark_html_reader.h b/chrome/browser/importer/bookmark_html_reader.h
new file mode 100644
index 0000000..5d34ab2
--- /dev/null
+++ b/chrome/browser/importer/bookmark_html_reader.h
@@ -0,0 +1,97 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_IMPORTER_BOOKMARK_HTML_READER_H_
+#define CHROME_BROWSER_IMPORTER_BOOKMARK_HTML_READER_H_
+
+#include <string>
+#include <vector>
+
+#include "base/callback_forward.h"
+#include "base/strings/string16.h"
+
+class GURL;
+struct ImportedBookmarkEntry;
+struct ImportedFaviconUsage;
+
+namespace base {
+class FilePath;
+class Time;
+}
+
+namespace bookmark_html_reader {
+
+// Imports the bookmarks from the specified file.
+//
+// |cancellation_callback| is polled to query if the import should be cancelled;
+// if it returns |true| at any time the import will be cancelled. If
+// |cancellation_callback| is a null callback the import will run to completion.
+//
+// |valid_url_callback| is called to determine if a specified URL is valid for
+// import; it returns |true| if it is. If |valid_url_callback| is a null
+// callback, all URLs are considered to be valid.
+//
+// |file_path| is the path of the file on disk to import.
+//
+// |bookmarks| is a pointer to a vector, which is filled with the imported
+// bookmarks. It may not be NULL.
+//
+// |favicons| is a pointer to a vector, which is filled with the favicons of
+// imported bookmarks. It may be NULL, in which case favicons are not imported.
+void ImportBookmarksFile(
+    const base::Callback<bool(void)>& cancellation_callback,
+    const base::Callback<bool(const GURL&)>& valid_url_callback,
+    const base::FilePath& file_path,
+    std::vector<ImportedBookmarkEntry>* bookmarks,
+    std::vector<ImportedFaviconUsage>* favicons);
+
+namespace internal {
+
+// The file format that BookmarkHTMLReader parses starts with a heading
+// tag, which contains its title. All bookmarks and sub-folders follow,
+// bracketed by a <DL> tag:
+//   <DT><H3 PERSONAL_TOOLBAR_FOLDER="true" ...>title</H3>
+//   <DL><p>
+//      ... container ...
+//   </DL><p>
+// And a bookmark is presented by a <A> tag:
+//   <DT><A HREF="url" SHORTCUTURL="shortcut" ADD_DATE="11213014"...>name</A>
+// Reference: http://kb.mozillazine.org/Bookmarks.html
+
+bool ParseCharsetFromLine(const std::string& line,
+                          std::string* charset);
+bool ParseFolderNameFromLine(const std::string& line,
+                             const std::string& charset,
+                             base::string16* folder_name,
+                             bool* is_toolbar_folder,
+                             base::Time* add_date);
+// See above, this will also put the data: URL of the favicon into |*favicon|
+// if there is a favicon given. |post_data| is set for POST base keywords to
+// the contents of the actual POST (with %s for the search term).
+bool ParseBookmarkFromLine(const std::string& line,
+                           const std::string& charset,
+                           base::string16* title,
+                           GURL* url,
+                           GURL* favicon,
+                           base::string16* shortcut,
+                           base::Time* add_date,
+                           base::string16* post_data);
+// Save bookmarks imported from browsers with Firefox 2 compatible bookmark
+// systems such as Epiphany. This bookmark format is the same as that of the
+// basic Firefox 2 bookmark, but it misses additional properties and uses
+// lower-case tag:
+//   ...<h1>Bookmarks</h1><dl>
+//   <dt><a href="url">name</a></dt>
+//   <dt><a href="url">name</a></dt>
+//   </dl>
+bool ParseMinimumBookmarkFromLine(const std::string& line,
+                                  const std::string& charset,
+                                  base::string16* title,
+                                  GURL* url);
+
+}  // namespace internal
+
+}  // namespace bookmark_html_reader
+
+#endif  // CHROME_BROWSER_IMPORTER_BOOKMARK_HTML_READER_H_
diff --git a/chrome/browser/importer/bookmark_html_reader_unittest.cc b/chrome/browser/importer/bookmark_html_reader_unittest.cc
new file mode 100644
index 0000000..8374a12
--- /dev/null
+++ b/chrome/browser/importer/bookmark_html_reader_unittest.cc
@@ -0,0 +1,275 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/importer/bookmark_html_reader.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/callback.h"
+#include "base/files/file_path.h"
+#include "base/path_service.h"
+#include "base/strings/string16.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/importer/imported_bookmark_entry.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace bookmark_html_reader {
+
+TEST(BookmarkHTMLReaderTest, ParseTests) {
+  bool result;
+
+  // Tests charset.
+  std::string charset;
+  result = internal::ParseCharsetFromLine(
+      "<META HTTP-EQUIV=\"Content-Type\" "
+      "CONTENT=\"text/html; charset=UTF-8\">",
+      &charset);
+  EXPECT_TRUE(result);
+  EXPECT_EQ("UTF-8", charset);
+
+  // Escaped characters in name.
+  base::string16 folder_name;
+  bool is_toolbar_folder;
+  base::Time folder_add_date;
+  result = internal::ParseFolderNameFromLine(
+      "<DT><H3 ADD_DATE=\"1207558707\" >&lt; &gt;"
+      " &amp; &quot; &#39; \\ /</H3>",
+      charset, &folder_name, &is_toolbar_folder, &folder_add_date);
+  EXPECT_TRUE(result);
+  EXPECT_EQ(ASCIIToUTF16("< > & \" ' \\ /"), folder_name);
+  EXPECT_FALSE(is_toolbar_folder);
+  EXPECT_TRUE(base::Time::FromTimeT(1207558707) == folder_add_date);
+
+  // Empty name and toolbar folder attribute.
+  result = internal::ParseFolderNameFromLine(
+      "<DT><H3 PERSONAL_TOOLBAR_FOLDER=\"true\"></H3>",
+      charset, &folder_name, &is_toolbar_folder, &folder_add_date);
+  EXPECT_TRUE(result);
+  EXPECT_EQ(base::string16(), folder_name);
+  EXPECT_TRUE(is_toolbar_folder);
+
+  // Unicode characters in title and shortcut.
+  base::string16 title;
+  GURL url, favicon;
+  base::string16 shortcut;
+  base::string16 post_data;
+  base::Time add_date;
+  result = internal::ParseBookmarkFromLine(
+      "<DT><A HREF=\"http://chinese.site.cn/path?query=1#ref\" "
+      "SHORTCUTURL=\"\xE4\xB8\xAD\">\xE4\xB8\xAD\xE6\x96\x87</A>",
+      charset, &title, &url, &favicon, &shortcut, &add_date, &post_data);
+  EXPECT_TRUE(result);
+  EXPECT_EQ(L"\x4E2D\x6587", UTF16ToWide(title));
+  EXPECT_EQ("http://chinese.site.cn/path?query=1#ref", url.spec());
+  EXPECT_EQ(L"\x4E2D", UTF16ToWide(shortcut));
+  EXPECT_EQ(base::string16(), post_data);
+  EXPECT_TRUE(base::Time() == add_date);
+
+  // No shortcut, and url contains %22 ('"' character).
+  result = internal::ParseBookmarkFromLine(
+      "<DT><A HREF=\"http://domain.com/?q=%22<>%22\">name</A>",
+      charset, &title, &url, &favicon, &shortcut, &add_date, &post_data);
+  EXPECT_TRUE(result);
+  EXPECT_EQ(ASCIIToUTF16("name"), title);
+  EXPECT_EQ("http://domain.com/?q=%22%3C%3E%22", url.spec());
+  EXPECT_EQ(base::string16(), shortcut);
+  EXPECT_EQ(base::string16(), post_data);
+  EXPECT_TRUE(base::Time() == add_date);
+
+  result = internal::ParseBookmarkFromLine(
+      "<DT><A HREF=\"http://domain.com/?g=&quot;\"\">name</A>",
+      charset, &title, &url, &favicon, &shortcut, &add_date, &post_data);
+  EXPECT_TRUE(result);
+  EXPECT_EQ(ASCIIToUTF16("name"), title);
+  EXPECT_EQ("http://domain.com/?g=%22", url.spec());
+  EXPECT_EQ(base::string16(), shortcut);
+  EXPECT_EQ(base::string16(), post_data);
+  EXPECT_TRUE(base::Time() == add_date);
+
+  // Creation date.
+  result = internal::ParseBookmarkFromLine(
+      "<DT><A HREF=\"http://site/\" ADD_DATE=\"1121301154\">name</A>",
+      charset, &title, &url, &favicon, &shortcut, &add_date, &post_data);
+  EXPECT_TRUE(result);
+  EXPECT_EQ(ASCIIToUTF16("name"), title);
+  EXPECT_EQ(GURL("http://site/"), url);
+  EXPECT_EQ(base::string16(), shortcut);
+  EXPECT_EQ(base::string16(), post_data);
+  EXPECT_TRUE(base::Time::FromTimeT(1121301154) == add_date);
+
+  // Post-data
+  result = internal::ParseBookmarkFromLine(
+      "<DT><A HREF=\"http://localhost:8080/test/hello.html\" ADD_DATE=\""
+      "1212447159\" LAST_VISIT=\"1212447251\" LAST_MODIFIED=\"1212447248\""
+      "SHORTCUTURL=\"post\" ICON=\"data:\" POST_DATA=\"lname%3D%25s\""
+      "LAST_CHARSET=\"UTF-8\" ID=\"rdf:#$weKaR3\">Test Post keyword</A>",
+      charset, &title, &url, &favicon, &shortcut, &add_date, &post_data);
+  EXPECT_TRUE(result);
+  EXPECT_EQ(ASCIIToUTF16("Test Post keyword"), title);
+  EXPECT_EQ("http://localhost:8080/test/hello.html", url.spec());
+  EXPECT_EQ(ASCIIToUTF16("post"), shortcut);
+  EXPECT_EQ(ASCIIToUTF16("lname%3D%25s"), post_data);
+  EXPECT_TRUE(base::Time::FromTimeT(1212447159) == add_date);
+
+  // Invalid case.
+  result = internal::ParseBookmarkFromLine(
+      "<DT><A HREF=\"http://domain.com/?q=%22",
+      charset, &title, &url, &favicon, &shortcut, &add_date, &post_data);
+  EXPECT_FALSE(result);
+  EXPECT_EQ(base::string16(), title);
+  EXPECT_EQ("", url.spec());
+  EXPECT_EQ(base::string16(), shortcut);
+  EXPECT_EQ(base::string16(), post_data);
+  EXPECT_TRUE(base::Time() == add_date);
+
+  // Epiphany format.
+  result = internal::ParseMinimumBookmarkFromLine(
+      "<dt><a href=\"http://www.google.com/\">Google</a></dt>",
+      charset, &title, &url);
+  EXPECT_TRUE(result);
+  EXPECT_EQ(ASCIIToUTF16("Google"), title);
+  EXPECT_EQ("http://www.google.com/", url.spec());
+}
+
+namespace {
+
+void ExpectFirstFirefox2Bookmark(const ImportedBookmarkEntry& entry) {
+  EXPECT_EQ(ASCIIToUTF16("Empty"), entry.title);
+  EXPECT_TRUE(entry.is_folder);
+  EXPECT_EQ(base::Time::FromTimeT(1295938143), entry.creation_time);
+  EXPECT_EQ(1U, entry.path.size());
+  if (entry.path.size() == 1)
+    EXPECT_EQ(ASCIIToUTF16("Empty's Parent"), entry.path.front());
+}
+
+void ExpectSecondFirefox2Bookmark(const ImportedBookmarkEntry& entry) {
+  EXPECT_EQ(ASCIIToUTF16("[Tamura Yukari.com]"), entry.title);
+  EXPECT_FALSE(entry.is_folder);
+  EXPECT_EQ(base::Time::FromTimeT(1234567890), entry.creation_time);
+  EXPECT_EQ(1U, entry.path.size());
+  if (entry.path.size() == 1)
+    EXPECT_EQ(ASCIIToUTF16("Not Empty"), entry.path.front());
+  EXPECT_EQ("http://www.tamurayukari.com/", entry.url.spec());
+}
+
+void ExpectThirdFirefox2Bookmark(const ImportedBookmarkEntry& entry) {
+  EXPECT_EQ(ASCIIToUTF16("Google"), entry.title);
+  EXPECT_FALSE(entry.is_folder);
+  EXPECT_EQ(base::Time::FromTimeT(0000000000), entry.creation_time);
+  EXPECT_EQ(1U, entry.path.size());
+  if (entry.path.size() == 1)
+    EXPECT_EQ(ASCIIToUTF16("Not Empty But Default"), entry.path.front());
+  EXPECT_EQ("http://www.google.com/", entry.url.spec());
+}
+
+void ExpectFirstEpiphanyBookmark(const ImportedBookmarkEntry& entry) {
+  EXPECT_EQ(ASCIIToUTF16("[Tamura Yukari.com]"), entry.title);
+  EXPECT_EQ("http://www.tamurayukari.com/", entry.url.spec());
+  EXPECT_EQ(0U, entry.path.size());
+}
+
+void ExpectSecondEpiphanyBookmark(const ImportedBookmarkEntry& entry) {
+  EXPECT_EQ(ASCIIToUTF16("Google"), entry.title);
+  EXPECT_EQ("http://www.google.com/", entry.url.spec());
+  EXPECT_EQ(0U, entry.path.size());
+}
+
+}  // namespace
+
+TEST(BookmarkHTMLReaderTest, Firefox2BookmarkFileImport) {
+  base::FilePath path;
+  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &path));
+  path = path.AppendASCII("bookmark_html_reader");
+  path = path.AppendASCII("firefox2.html");
+
+  std::vector<ImportedBookmarkEntry> bookmarks;
+  ImportBookmarksFile(base::Callback<bool(void)>(),
+                      base::Callback<bool(const GURL&)>(),
+                      path, &bookmarks, NULL);
+
+  ASSERT_EQ(3U, bookmarks.size());
+  ExpectFirstFirefox2Bookmark(bookmarks[0]);
+  ExpectSecondFirefox2Bookmark(bookmarks[1]);
+  ExpectThirdFirefox2Bookmark(bookmarks[2]);
+}
+
+TEST(BookmarkHTMLReaderTest, EpiphanyBookmarkFileImport) {
+  base::FilePath path;
+  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &path));
+  path = path.AppendASCII("bookmark_html_reader");
+  path = path.AppendASCII("epiphany.html");
+
+  std::vector<ImportedBookmarkEntry> bookmarks;
+  ImportBookmarksFile(base::Callback<bool(void)>(),
+                      base::Callback<bool(const GURL&)>(),
+                      path, &bookmarks, NULL);
+
+  ASSERT_EQ(2U, bookmarks.size());
+  ExpectFirstEpiphanyBookmark(bookmarks[0]);
+  ExpectSecondEpiphanyBookmark(bookmarks[1]);
+}
+
+namespace {
+
+class CancelAfterFifteenCalls {
+  int count;
+ public:
+  CancelAfterFifteenCalls() : count(0) { }
+  bool ShouldCancel() {
+    return ++count > 16;
+  }
+};
+
+}  // namespace
+
+TEST(BookmarkHTMLReaderTest, CancellationCallback) {
+  base::FilePath path;
+  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &path));
+  path = path.AppendASCII("bookmark_html_reader");
+  // Use a file for testing that has multiple bookmarks.
+  path = path.AppendASCII("firefox2.html");
+
+  std::vector<ImportedBookmarkEntry> bookmarks;
+  CancelAfterFifteenCalls cancel_fifteen;
+  ImportBookmarksFile(base::Bind(&CancelAfterFifteenCalls::ShouldCancel,
+                                 base::Unretained(&cancel_fifteen)),
+                      base::Callback<bool(const GURL&)>(),
+                      path, &bookmarks, NULL);
+
+  // The cancellation callback is checked before each line is read, so fifteen
+  // lines are imported. The first fifteen lines of firefox2.html include only
+  // one bookmark.
+  ASSERT_EQ(1U, bookmarks.size());
+  ExpectFirstFirefox2Bookmark(bookmarks[0]);
+}
+
+namespace {
+
+bool IsURLValid(const GURL& url) {
+  // No offense to whomever owns this domain...
+  return !url.DomainIs("tamurayukari.com");
+}
+
+}  // namespace
+
+TEST(BookmarkHTMLReaderTest, ValidURLCallback) {
+  base::FilePath path;
+  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &path));
+  path = path.AppendASCII("bookmark_html_reader");
+  // Use a file for testing that has multiple bookmarks.
+  path = path.AppendASCII("firefox2.html");
+
+  std::vector<ImportedBookmarkEntry> bookmarks;
+  ImportBookmarksFile(base::Callback<bool(void)>(),
+                      base::Bind(&IsURLValid),
+                      path, &bookmarks, NULL);
+
+  ASSERT_EQ(2U, bookmarks.size());
+  ExpectFirstFirefox2Bookmark(bookmarks[0]);
+  ExpectThirdFirefox2Bookmark(bookmarks[1]);
+}
+
+}  // namespace bookmark_html_reader
diff --git a/chrome/browser/importer/bookmark_html_writer_unittest.cc b/chrome/browser/importer/bookmark_html_writer_unittest.cc
new file mode 100644
index 0000000..37beb81
--- /dev/null
+++ b/chrome/browser/importer/bookmark_html_writer_unittest.cc
@@ -0,0 +1,283 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/bookmarks/bookmark_html_writer.h"
+
+#include "base/files/scoped_temp_dir.h"
+#include "base/i18n/time_formatting.h"
+#include "base/path_service.h"
+#include "base/run_loop.h"
+#include "base/strings/string16.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
+#include "chrome/browser/bookmarks/bookmark_model.h"
+#include "chrome/browser/bookmarks/bookmark_model_factory.h"
+#include "chrome/browser/favicon/favicon_service.h"
+#include "chrome/browser/favicon/favicon_service_factory.h"
+#include "chrome/browser/history/history_service.h"
+#include "chrome/browser/history/history_service_factory.h"
+#include "chrome/browser/importer/bookmark_html_reader.h"
+#include "chrome/common/importer/imported_bookmark_entry.h"
+#include "chrome/common/importer/imported_favicon_usage.h"
+#include "chrome/test/base/testing_profile.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "grit/generated_resources.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/codec/png_codec.h"
+
+using content::BrowserThread;
+
+namespace {
+
+const int kIconWidth = 16;
+const int kIconHeight = 16;
+
+void MakeTestSkBitmap(int w, int h, SkBitmap* bmp) {
+  bmp->setConfig(SkBitmap::kARGB_8888_Config, w, h);
+  bmp->allocPixels();
+
+  uint32_t* src_data = bmp->getAddr32(0, 0);
+  for (int i = 0; i < w * h; i++) {
+    src_data[i] = SkPreMultiplyARGB(i % 255, i % 250, i % 245, i % 240);
+  }
+}
+
+}  // namespace
+
+class BookmarkHTMLWriterTest : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    testing::Test::SetUp();
+    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+    path_ = temp_dir_.path().AppendASCII("bookmarks.html");
+  }
+
+  // Converts an ImportedBookmarkEntry to a string suitable for assertion
+  // testing.
+  string16 BookmarkEntryToString(const ImportedBookmarkEntry& entry) {
+    string16 result;
+    result.append(ASCIIToUTF16("on_toolbar="));
+    if (entry.in_toolbar)
+      result.append(ASCIIToUTF16("true"));
+    else
+      result.append(ASCIIToUTF16("false"));
+
+    result.append(ASCIIToUTF16(" url=") + UTF8ToUTF16(entry.url.spec()));
+
+    result.append(ASCIIToUTF16(" path="));
+    for (size_t i = 0; i < entry.path.size(); ++i) {
+      if (i != 0)
+        result.append(ASCIIToUTF16("/"));
+      result.append(entry.path[i]);
+    }
+
+    result.append(ASCIIToUTF16(" title="));
+    result.append(entry.title);
+
+    result.append(ASCIIToUTF16(" time="));
+    result.append(base::TimeFormatFriendlyDateAndTime(entry.creation_time));
+    return result;
+  }
+
+  // Creates a set of bookmark values to a string for assertion testing.
+  string16 BookmarkValuesToString(bool on_toolbar,
+                                  const GURL& url,
+                                  const string16& title,
+                                  base::Time creation_time,
+                                  const string16& f1,
+                                  const string16& f2,
+                                  const string16& f3) {
+    ImportedBookmarkEntry entry;
+    entry.in_toolbar = on_toolbar;
+    entry.url = url;
+    if (!f1.empty()) {
+      entry.path.push_back(f1);
+      if (!f2.empty()) {
+        entry.path.push_back(f2);
+        if (!f3.empty())
+          entry.path.push_back(f3);
+      }
+    }
+    entry.title = title;
+    entry.creation_time = creation_time;
+    return BookmarkEntryToString(entry);
+  }
+
+  void AssertBookmarkEntryEquals(const ImportedBookmarkEntry& entry,
+                                 bool on_toolbar,
+                                 const GURL& url,
+                                 const string16& title,
+                                 base::Time creation_time,
+                                 const string16& f1,
+                                 const string16& f2,
+                                 const string16& f3) {
+    EXPECT_EQ(BookmarkValuesToString(on_toolbar, url, title, creation_time,
+                                     f1, f2, f3),
+              BookmarkEntryToString(entry));
+  }
+
+  base::ScopedTempDir temp_dir_;
+  base::FilePath path_;
+};
+
+// Class that will notify message loop when file is written.
+class BookmarksObserver : public BookmarksExportObserver {
+ public:
+  explicit BookmarksObserver(base::RunLoop* loop) : loop_(loop) {
+    DCHECK(loop);
+  }
+
+  virtual void OnExportFinished() OVERRIDE {
+    loop_->Quit();
+  }
+
+ private:
+  base::RunLoop* loop_;
+
+  DISALLOW_COPY_AND_ASSIGN(BookmarksObserver);
+};
+
+// Tests bookmark_html_writer by populating a BookmarkModel, writing it out by
+// way of bookmark_html_writer, then using the importer to read it back in.
+TEST_F(BookmarkHTMLWriterTest, Test) {
+  content::TestBrowserThreadBundle thread_bundle;
+
+  TestingProfile profile;
+  profile.CreateHistoryService(true, false);
+  profile.BlockUntilHistoryProcessesPendingRequests();
+  profile.CreateFaviconService();
+  profile.CreateBookmarkModel(true);
+
+  BookmarkModel* model = BookmarkModelFactory::GetForProfile(&profile);
+  ui_test_utils::WaitForBookmarkModelToLoad(model);
+
+  // Create test PNG representing favicon for url1.
+  SkBitmap bitmap;
+  MakeTestSkBitmap(kIconWidth, kIconHeight, &bitmap);
+  std::vector<unsigned char> icon_data;
+  gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &icon_data);
+
+  // Populate the BookmarkModel. This creates the following bookmark structure:
+  // Bookmarks bar
+  //   F1
+  //     url1
+  //     F2
+  //       url2
+  //   url3
+  //   url4
+  // Other
+  //   url1
+  //   url2
+  //   F3
+  //     F4
+  //       url1
+  // Mobile
+  //   url1
+  //   <bookmark without a title.>
+  string16 f1_title = ASCIIToUTF16("F\"&;<1\"");
+  string16 f2_title = ASCIIToUTF16("F2");
+  string16 f3_title = ASCIIToUTF16("F 3");
+  string16 f4_title = ASCIIToUTF16("F4");
+  string16 url1_title = ASCIIToUTF16("url 1");
+  string16 url2_title = ASCIIToUTF16("url&2");
+  string16 url3_title = ASCIIToUTF16("url\"3");
+  string16 url4_title = ASCIIToUTF16("url\"&;");
+  string16 unnamed_bookmark_title = ASCIIToUTF16("");
+  GURL url1("http://url1");
+  GURL url1_favicon("http://url1/icon.ico");
+  GURL url2("http://url2");
+  GURL url3("http://url3");
+  GURL url4("javascript:alert(\"Hello!\");");
+  GURL unnamed_bookmark_url("about:blank");
+  base::Time t1(base::Time::Now());
+  base::Time t2(t1 + base::TimeDelta::FromHours(1));
+  base::Time t3(t1 + base::TimeDelta::FromHours(1));
+  base::Time t4(t1 + base::TimeDelta::FromHours(1));
+  const BookmarkNode* f1 = model->AddFolder(
+      model->bookmark_bar_node(), 0, f1_title);
+  model->AddURLWithCreationTime(f1, 0, url1_title, url1, t1);
+  HistoryServiceFactory::GetForProfile(&profile, Profile::EXPLICIT_ACCESS)->
+      AddPage(url1, base::Time::Now(), history::SOURCE_BROWSED);
+  FaviconServiceFactory::GetForProfile(
+      &profile, Profile::EXPLICIT_ACCESS)->SetFavicons(
+          url1, url1_favicon, chrome::FAVICON,
+          gfx::Image::CreateFrom1xBitmap(bitmap));
+  const BookmarkNode* f2 = model->AddFolder(f1, 1, f2_title);
+  model->AddURLWithCreationTime(f2, 0, url2_title, url2, t2);
+  model->AddURLWithCreationTime(model->bookmark_bar_node(),
+                                1, url3_title, url3, t3);
+
+  model->AddURLWithCreationTime(model->other_node(), 0, url1_title, url1, t1);
+  model->AddURLWithCreationTime(model->other_node(), 1, url2_title, url2, t2);
+  const BookmarkNode* f3 = model->AddFolder(model->other_node(), 2, f3_title);
+  const BookmarkNode* f4 = model->AddFolder(f3, 0, f4_title);
+  model->AddURLWithCreationTime(f4, 0, url1_title, url1, t1);
+  model->AddURLWithCreationTime(model->bookmark_bar_node(), 2, url4_title,
+                                url4, t4);
+  model->AddURLWithCreationTime(model->mobile_node(), 0, url1_title, url1, t1);
+  model->AddURLWithCreationTime(model->mobile_node(), 1, unnamed_bookmark_title,
+                                unnamed_bookmark_url, t2);
+
+  base::RunLoop run_loop;
+
+  // Write to a temp file.
+  BookmarksObserver observer(&run_loop);
+  bookmark_html_writer::WriteBookmarks(&profile, path_, &observer);
+  run_loop.Run();
+
+  // Clear favicon so that it would be read from file.
+  FaviconServiceFactory::GetForProfile(
+      &profile, Profile::EXPLICIT_ACCESS)->SetFavicons(
+          url1, url1_favicon, chrome::FAVICON, gfx::Image());
+
+  // Read the bookmarks back in.
+  std::vector<ImportedBookmarkEntry> parsed_bookmarks;
+  std::vector<ImportedFaviconUsage> favicons;
+  bookmark_html_reader::ImportBookmarksFile(base::Callback<bool(void)>(),
+                                            base::Callback<bool(const GURL&)>(),
+                                            path_,
+                                            &parsed_bookmarks,
+                                            &favicons);
+
+  // Check loaded favicon (url1 is represented by 4 separate bookmarks).
+  EXPECT_EQ(4U, favicons.size());
+  for (size_t i = 0; i < favicons.size(); i++) {
+    if (url1_favicon == favicons[i].favicon_url) {
+      EXPECT_EQ(1U, favicons[i].urls.size());
+      std::set<GURL>::const_iterator iter = favicons[i].urls.find(url1);
+      ASSERT_TRUE(iter != favicons[i].urls.end());
+      ASSERT_TRUE(*iter == url1);
+      ASSERT_TRUE(favicons[i].png_data == icon_data);
+    }
+  }
+
+  // Verify we got back what we wrote.
+  ASSERT_EQ(9U, parsed_bookmarks.size());
+  // Windows and ChromeOS builds use Sentence case.
+  string16 bookmark_folder_name =
+      l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_FOLDER_NAME);
+  AssertBookmarkEntryEquals(parsed_bookmarks[0], true, url1, url1_title, t1,
+                            bookmark_folder_name, f1_title, string16());
+  AssertBookmarkEntryEquals(parsed_bookmarks[1], true, url2, url2_title, t2,
+                            bookmark_folder_name, f1_title, f2_title);
+  AssertBookmarkEntryEquals(parsed_bookmarks[2], true, url3, url3_title, t3,
+                            bookmark_folder_name, string16(), string16());
+  AssertBookmarkEntryEquals(parsed_bookmarks[3], true, url4, url4_title, t4,
+                            bookmark_folder_name, string16(), string16());
+  AssertBookmarkEntryEquals(parsed_bookmarks[4], false, url1, url1_title, t1,
+                            string16(), string16(), string16());
+  AssertBookmarkEntryEquals(parsed_bookmarks[5], false, url2, url2_title, t2,
+                            string16(), string16(), string16());
+  AssertBookmarkEntryEquals(parsed_bookmarks[6], false, url1, url1_title, t1,
+                            f3_title, f4_title, string16());
+  AssertBookmarkEntryEquals(parsed_bookmarks[7], false, url1, url1_title, t1,
+                            string16(), string16(), string16());
+  AssertBookmarkEntryEquals(parsed_bookmarks[8], false, unnamed_bookmark_url,
+                            unnamed_bookmark_title, t2,
+                            string16(), string16(), string16());
+}
diff --git a/chrome/browser/importer/bookmarks_file_importer.cc b/chrome/browser/importer/bookmarks_file_importer.cc
index 5a35863..3a1c871 100644
--- a/chrome/browser/importer/bookmarks_file_importer.cc
+++ b/chrome/browser/importer/bookmarks_file_importer.cc
@@ -5,12 +5,12 @@
 #include "chrome/browser/importer/bookmarks_file_importer.h"
 
 #include "base/bind.h"
-#include "chrome/browser/bookmarks/bookmark_html_reader.h"
-#include "chrome/browser/bookmarks/imported_bookmark_entry.h"
-#include "chrome/browser/favicon/imported_favicon_usage.h"
+#include "chrome/browser/importer/bookmark_html_reader.h"
 #include "chrome/browser/importer/firefox_importer_utils.h"
 #include "chrome/browser/importer/importer_bridge.h"
-#include "chrome/browser/importer/importer_data_types.h"
+#include "chrome/common/importer/imported_bookmark_entry.h"
+#include "chrome/common/importer/imported_favicon_usage.h"
+#include "chrome/common/importer/importer_data_types.h"
 #include "grit/generated_resources.h"
 
 namespace {
diff --git a/chrome/browser/importer/external_process_importer_bridge.cc b/chrome/browser/importer/external_process_importer_bridge.cc
index 2395fa0..23cc3bc 100644
--- a/chrome/browser/importer/external_process_importer_bridge.cc
+++ b/chrome/browser/importer/external_process_importer_bridge.cc
@@ -10,9 +10,10 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/task_runner.h"
 #include "base/values.h"
-#include "chrome/browser/bookmarks/imported_bookmark_entry.h"
-#include "chrome/browser/favicon/imported_favicon_usage.h"
-#include "chrome/browser/importer/profile_import_process_messages.h"
+#include "chrome/common/importer/imported_bookmark_entry.h"
+#include "chrome/common/importer/imported_favicon_usage.h"
+#include "chrome/common/importer/importer_data_types.h"
+#include "chrome/common/importer/profile_import_process_messages.h"
 #include "content/public/common/password_form.h"
 #include "ipc/ipc_sender.h"
 
@@ -103,7 +104,7 @@
 }
 
 void ExternalProcessImporterBridge::SetHistoryItems(
-    const history::URLRows& rows,
+    const std::vector<ImporterURLRow>& rows,
     history::VisitSource visit_source) {
   Send(new ProfileImportProcessHostMsg_NotifyHistoryImportStart(rows.size()));
 
@@ -111,9 +112,10 @@
   // Debug bounds-check which prevents pushing an iterator beyond its end()
   // (i.e., |it + 2 < s.end()| crashes in debug mode if |i + 1 == s.end()|).
   int rows_left = rows.end() - rows.begin();
-  for (history::URLRows::const_iterator it = rows.begin(); it < rows.end();) {
-    history::URLRows row_group;
-    history::URLRows::const_iterator end_group =
+  for (std::vector<ImporterURLRow>::const_iterator it = rows.begin();
+       it < rows.end();) {
+    std::vector<ImporterURLRow> row_group;
+    std::vector<ImporterURLRow>::const_iterator end_group =
         it + std::min(rows_left, kNumHistoryRowsToSend);
     row_group.assign(it, end_group);
 
@@ -126,11 +128,16 @@
 }
 
 void ExternalProcessImporterBridge::SetKeywords(
-    const std::vector<TemplateURL*>& template_urls,
+    const std::vector<importer::URLKeywordInfo>& url_keywords,
     bool unique_on_host_and_path) {
-  Send(new ProfileImportProcessHostMsg_NotifyKeywordsReady(template_urls,
-      unique_on_host_and_path));
-  STLDeleteContainerPointers(template_urls.begin(), template_urls.end());
+  Send(new ProfileImportProcessHostMsg_NotifyKeywordsReady(
+      url_keywords, unique_on_host_and_path));
+}
+
+void ExternalProcessImporterBridge::SetFirefoxSearchEnginesXMLData(
+    const std::vector<std::string>& search_engine_data) {
+  Send(new ProfileImportProcessHostMsg_NotifyFirefoxSearchEngData(
+      search_engine_data));
 }
 
 void ExternalProcessImporterBridge::SetPasswordForm(
diff --git a/chrome/browser/importer/external_process_importer_bridge.h b/chrome/browser/importer/external_process_importer_bridge.h
index c5450de..b1cb519 100644
--- a/chrome/browser/importer/external_process_importer_bridge.h
+++ b/chrome/browser/importer/external_process_importer_bridge.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_IMPORTER_EXTERNAL_PROCESS_IMPORTER_BRIDGE_H_
 #define CHROME_BROWSER_IMPORTER_EXTERNAL_PROCESS_IMPORTER_BRIDGE_H_
 
+#include <string>
 #include <vector>
 
 #include "base/basictypes.h"
@@ -20,6 +21,10 @@
 class TaskRunner;
 }
 
+namespace importer {
+struct URLKeywordInfo;
+}
+
 namespace IPC {
 class Message;
 class Sender;
@@ -52,11 +57,15 @@
   virtual void SetFavicons(
       const std::vector<ImportedFaviconUsage>& favicons) OVERRIDE;
 
-  virtual void SetHistoryItems(const history::URLRows& rows,
+  virtual void SetHistoryItems(const std::vector<ImporterURLRow>& rows,
                                history::VisitSource visit_source) OVERRIDE;
 
-  virtual void SetKeywords(const std::vector<TemplateURL*>& template_urls,
-                           bool unique_on_host_and_path) OVERRIDE;
+  virtual void SetKeywords(
+      const std::vector<importer::URLKeywordInfo>& url_keywords,
+      bool unique_on_host_and_path) OVERRIDE;
+
+  virtual void SetFirefoxSearchEnginesXMLData(
+      const std::vector<std::string>& seach_engine_data) OVERRIDE;
 
   virtual void SetPasswordForm(
       const content::PasswordForm& form) OVERRIDE;
diff --git a/chrome/browser/importer/external_process_importer_client.cc b/chrome/browser/importer/external_process_importer_client.cc
index 56ee2e6..d90d9a0 100644
--- a/chrome/browser/importer/external_process_importer_client.cc
+++ b/chrome/browser/importer/external_process_importer_client.cc
@@ -6,15 +6,12 @@
 
 #include "base/bind.h"
 #include "base/strings/string_number_conversions.h"
-#include "chrome/browser/bookmarks/imported_bookmark_entry.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/importer/external_process_importer_host.h"
 #include "chrome/browser/importer/firefox_importer_utils.h"
-#include "chrome/browser/importer/importer_host.h"
 #include "chrome/browser/importer/in_process_importer_bridge.h"
-#include "chrome/browser/importer/profile_import_process_messages.h"
-#include "chrome/browser/search_engines/template_url.h"
-#include "chrome/browser/search_engines/template_url_service.h"
+#include "chrome/common/importer/imported_bookmark_entry.h"
+#include "chrome/common/importer/profile_import_process_messages.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/utility_process_host.h"
 #include "grit/generated_resources.h"
@@ -64,6 +61,7 @@
 }
 
 void ExternalProcessImporterClient::OnProcessCrashed(int exit_code) {
+  DLOG(ERROR) << __FUNCTION__;
   if (cancelled_)
     return;
 
@@ -102,6 +100,8 @@
                         OnPasswordFormImportReady)
     IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_NotifyKeywordsReady,
                         OnKeywordsImportReady)
+    IPC_MESSAGE_HANDLER(ProfileImportProcessHostMsg_NotifyFirefoxSearchEngData,
+                        OnFirefoxSearchEngineDataReceived)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
   return handled;
@@ -155,7 +155,7 @@
 }
 
 void ExternalProcessImporterClient::OnHistoryImportGroup(
-    const history::URLRows& history_rows_group,
+    const std::vector<ImporterURLRow>& history_rows_group,
     int visit_source) {
   if (cancelled_)
     return;
@@ -228,13 +228,18 @@
 }
 
 void ExternalProcessImporterClient::OnKeywordsImportReady(
-    const std::vector<TemplateURL*>& template_urls,
+    const std::vector<importer::URLKeywordInfo>& url_keywords,
     bool unique_on_host_and_path) {
   if (cancelled_)
     return;
+  bridge_->SetKeywords(url_keywords, unique_on_host_and_path);
+}
 
-  bridge_->SetKeywords(template_urls, unique_on_host_and_path);
-  // The pointers in |template_urls| have now been deleted.
+void ExternalProcessImporterClient::OnFirefoxSearchEngineDataReceived(
+    const std::vector<std::string> search_engine_data) {
+  if (cancelled_)
+    return;
+  bridge_->SetFirefoxSearchEnginesXMLData(search_engine_data);
 }
 
 ExternalProcessImporterClient::~ExternalProcessImporterClient() {}
@@ -287,9 +292,6 @@
       base::IntToString(IDS_IMPORT_FROM_FIREFOX),
       l10n_util::GetStringUTF8(IDS_IMPORT_FROM_FIREFOX));
   localized_strings.SetString(
-      base::IntToString(IDS_IMPORT_FROM_GOOGLE_TOOLBAR),
-      l10n_util::GetStringUTF8(IDS_IMPORT_FROM_GOOGLE_TOOLBAR));
-  localized_strings.SetString(
       base::IntToString(IDS_IMPORT_FROM_SAFARI),
       l10n_util::GetStringUTF8(IDS_IMPORT_FROM_SAFARI));
   localized_strings.SetString(
diff --git a/chrome/browser/importer/external_process_importer_client.h b/chrome/browser/importer/external_process_importer_client.h
index f5a03d7..5af485e 100644
--- a/chrome/browser/importer/external_process_importer_client.h
+++ b/chrome/browser/importer/external_process_importer_client.h
@@ -13,7 +13,8 @@
 #include "base/memory/weak_ptr.h"
 #include "base/strings/string16.h"
 #include "chrome/browser/history/history_types.h"
-#include "chrome/browser/importer/importer_data_types.h"
+#include "chrome/common/importer/importer_data_types.h"
+#include "chrome/common/importer/importer_url_row.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/utility_process_host_client.h"
 
@@ -21,13 +22,16 @@
 struct ImportedBookmarkEntry;
 struct ImportedFaviconUsage;
 class InProcessImporterBridge;
-class TemplateURL;
 
 namespace content {
 struct PasswordForm;
 class UtilityProcessHost;
 }
 
+namespace importer {
+struct URLKeywordInfo;
+}
+
 // This class is the client for the out of process profile importing.  It
 // collects notifications from this process host and feeds data back to the
 // importer host, who actually does the writing.
@@ -54,8 +58,9 @@
   void OnImportItemStart(int item);
   void OnImportItemFinished(int item);
   void OnHistoryImportStart(size_t total_history_rows_count);
-  void OnHistoryImportGroup(const history::URLRows& history_rows_group,
-                            int visit_source);
+  void OnHistoryImportGroup(
+      const std::vector<ImporterURLRow>& history_rows_group,
+      int visit_source);
   void OnHomePageImportReady(const GURL& home_page);
   void OnBookmarksImportStart(const string16& first_folder_name,
                               size_t total_bookmarks_count);
@@ -65,10 +70,11 @@
   void OnFaviconsImportGroup(
       const std::vector<ImportedFaviconUsage>& favicons_group);
   void OnPasswordFormImportReady(const content::PasswordForm& form);
-  // WARNING: This function takes ownership of (and deletes) the pointers in
-  // |template_urls|!
-  void OnKeywordsImportReady(const std::vector<TemplateURL*>& template_urls,
-                             bool unique_on_host_and_path);
+  void OnKeywordsImportReady(
+      const std::vector<importer::URLKeywordInfo>& url_keywords,
+      bool unique_on_host_and_path);
+  void OnFirefoxSearchEngineDataReceived(
+      const std::vector<std::string> search_engine_data);
 
  protected:
   virtual ~ExternalProcessImporterClient();
@@ -88,7 +94,7 @@
 
   // These variables store data being collected from the importer until the
   // entire group has been collected and is ready to be written to the profile.
-  history::URLRows history_rows_;
+  std::vector<ImporterURLRow> history_rows_;
   std::vector<ImportedBookmarkEntry> bookmarks_;
   std::vector<ImportedFaviconUsage> favicons_;
 
@@ -117,7 +123,7 @@
   base::WeakPtr<content::UtilityProcessHost> utility_process_host_;
 
   // Data to be passed from the importer host to the external importer.
-  const importer::SourceProfile& source_profile_;
+  importer::SourceProfile source_profile_;
   uint16 items_;
 
   // Takes import data coming over IPC and delivers it to be written by the
diff --git a/chrome/browser/importer/external_process_importer_host.cc b/chrome/browser/importer/external_process_importer_host.cc
index 1e66b69..a461aac 100644
--- a/chrome/browser/importer/external_process_importer_host.cc
+++ b/chrome/browser/importer/external_process_importer_host.cc
@@ -4,13 +4,34 @@
 
 #include "chrome/browser/importer/external_process_importer_host.h"
 
+#include "base/bind.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
+#include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/browser/importer/external_process_importer_client.h"
-#include "chrome/browser/importer/importer_type.h"
+#include "chrome/browser/importer/firefox_profile_lock.h"
+#include "chrome/browser/importer/importer.h"
+#include "chrome/browser/importer/importer_creator.h"
+#include "chrome/browser/importer/importer_lock_dialog.h"
+#include "chrome/browser/importer/importer_progress_observer.h"
 #include "chrome/browser/importer/in_process_importer_bridge.h"
+#include "chrome/browser/search_engines/template_url_service.h"
+#include "chrome/browser/search_engines/template_url_service_factory.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/notification_source.h"
+
+using content::BrowserThread;
 
 ExternalProcessImporterHost::ExternalProcessImporterHost()
-    : client_(NULL),
+    : weak_ptr_factory_(this),
+      headless_(false),
+      parent_window_(NULL),
+      observer_(NULL),
+      profile_(NULL),
+      waiting_for_bookmarkbar_model_(false),
+      installed_bookmark_observer_(false),
+      is_source_readable_(true),
+      client_(NULL),
       source_profile_(NULL),
       items_(0),
       cancelled_(false),
@@ -24,8 +45,6 @@
   NotifyImportEnded();  // Tells the observer that we're done, and deletes us.
 }
 
-ExternalProcessImporterHost::~ExternalProcessImporterHost() {}
-
 void ExternalProcessImporterHost::StartImportSettings(
     const importer::SourceProfile& source_profile,
     Profile* target_profile,
@@ -47,10 +66,42 @@
 
   CheckForLoadedModels(items);
 
-  InvokeTaskIfDone();
+  LaunchImportIfReady();
 }
 
-void ExternalProcessImporterHost::InvokeTaskIfDone() {
+void ExternalProcessImporterHost::NotifyImportStarted() {
+  if (observer_)
+    observer_->ImportStarted();
+}
+
+void ExternalProcessImporterHost::NotifyImportItemStarted(
+    importer::ImportItem item) {
+  if (observer_)
+    observer_->ImportItemStarted(item);
+}
+
+void ExternalProcessImporterHost::NotifyImportItemEnded(
+    importer::ImportItem item) {
+  if (observer_)
+    observer_->ImportItemEnded(item);
+}
+
+void ExternalProcessImporterHost::NotifyImportEnded() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  firefox_lock_.reset();
+  if (observer_)
+    observer_->ImportEnded();
+  delete this;
+}
+
+ExternalProcessImporterHost::~ExternalProcessImporterHost() {
+  if (installed_bookmark_observer_) {
+    DCHECK(profile_);
+    BookmarkModelFactory::GetForProfile(profile_)->RemoveObserver(this);
+  }
+}
+
+void ExternalProcessImporterHost::LaunchImportIfReady() {
   if (waiting_for_bookmarkbar_model_ || !registrar_.IsEmpty() ||
       !is_source_readable_ || cancelled_)
     return;
@@ -76,5 +127,93 @@
   waiting_for_bookmarkbar_model_ = false;
   installed_bookmark_observer_ = false;
 
-  InvokeTaskIfDone();
+  LaunchImportIfReady();
+}
+
+void ExternalProcessImporterHost::BookmarkModelBeingDeleted(
+    BookmarkModel* model) {
+  installed_bookmark_observer_ = false;
+}
+
+void ExternalProcessImporterHost::BookmarkModelChanged() {
+}
+
+void ExternalProcessImporterHost::Observe(int type,
+                           const content::NotificationSource& source,
+                           const content::NotificationDetails& details) {
+  DCHECK_EQ(type, chrome::NOTIFICATION_TEMPLATE_URL_SERVICE_LOADED);
+  registrar_.RemoveAll();
+  LaunchImportIfReady();
+}
+
+void ExternalProcessImporterHost::ShowWarningDialog() {
+  DCHECK(!headless_);
+  importer::ShowImportLockDialog(
+      parent_window_,
+      base::Bind(&ExternalProcessImporterHost::OnImportLockDialogEnd,
+                 weak_ptr_factory_.GetWeakPtr()));
+}
+
+void ExternalProcessImporterHost::OnImportLockDialogEnd(bool is_continue) {
+  if (is_continue) {
+    // User chose to continue, then we check the lock again to make
+    // sure that Firefox has been closed. Try to import the settings
+    // if successful. Otherwise, show a warning dialog.
+    firefox_lock_->Lock();
+    if (firefox_lock_->HasAcquired()) {
+      is_source_readable_ = true;
+      LaunchImportIfReady();
+    } else {
+      ShowWarningDialog();
+    }
+  } else {
+    NotifyImportEnded();
+  }
+}
+
+bool ExternalProcessImporterHost::CheckForFirefoxLock(
+    const importer::SourceProfile& source_profile) {
+  if (source_profile.importer_type != importer::TYPE_FIREFOX3)
+    return true;
+
+  DCHECK(!firefox_lock_.get());
+  firefox_lock_.reset(new FirefoxProfileLock(source_profile.source_path));
+  if (firefox_lock_->HasAcquired())
+    return true;
+
+  // If fail to acquire the lock, we set the source unreadable and
+  // show a warning dialog, unless running without UI (in which case the import
+  // must be aborted).
+  is_source_readable_ = false;
+  if (headless_)
+    return false;
+
+  ShowWarningDialog();
+  return true;
+}
+
+void ExternalProcessImporterHost::CheckForLoadedModels(uint16 items) {
+  // A target profile must be loaded by StartImportSettings().
+  DCHECK(profile_);
+
+  // BookmarkModel should be loaded before adding IE favorites. So we observe
+  // the BookmarkModel if needed, and start the task after it has been loaded.
+  if ((items & importer::FAVORITES) && !writer_->BookmarkModelIsLoaded()) {
+    BookmarkModelFactory::GetForProfile(profile_)->AddObserver(this);
+    waiting_for_bookmarkbar_model_ = true;
+    installed_bookmark_observer_ = true;
+  }
+
+  // Observes the TemplateURLService if needed to import search engines from the
+  // other browser. We also check to see if we're importing bookmarks because
+  // we can import bookmark keywords from Firefox as search engines.
+  if ((items & importer::SEARCH_ENGINES) || (items & importer::FAVORITES)) {
+    if (!writer_->TemplateURLServiceIsLoaded()) {
+      TemplateURLService* model =
+          TemplateURLServiceFactory::GetForProfile(profile_);
+      registrar_.Add(this, chrome::NOTIFICATION_TEMPLATE_URL_SERVICE_LOADED,
+                     content::Source<TemplateURLService>(model));
+      model->Load();
+    }
+  }
 }
diff --git a/chrome/browser/importer/external_process_importer_host.h b/chrome/browser/importer/external_process_importer_host.h
index 215263e..abf8077 100644
--- a/chrome/browser/importer/external_process_importer_host.h
+++ b/chrome/browser/importer/external_process_importer_host.h
@@ -7,11 +7,21 @@
 
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
-#include "chrome/browser/importer/importer_host.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/bookmarks/base_bookmark_model_observer.h"
+#include "chrome/browser/importer/importer_progress_observer.h"
+#include "chrome/browser/importer/profile_writer.h"
+#include "chrome/common/importer/importer_data_types.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+#include "ui/gfx/native_widget_types.h"
 
 class ExternalProcessImporterClient;
+class FirefoxProfileLock;
+class Importer;
 class Profile;
-class ProfileWriter;
 
 namespace importer {
 struct SourceProfile;
@@ -19,23 +29,124 @@
 
 // This class manages the import process. It creates the in-process half of the
 // importer bridge and the external process importer client.
-class ExternalProcessImporterHost : public ImporterHost {
+class ExternalProcessImporterHost : public BaseBookmarkModelObserver,
+                                    public content::NotificationObserver {
  public:
   ExternalProcessImporterHost();
 
   void Cancel();
 
- private:
-  virtual ~ExternalProcessImporterHost();
-
-  // ImporterHost:
+  // Starts the process of importing the settings and data depending on what the
+  // user selected.
+  // |source_profile| - importer profile to import.
+  // |target_profile| - profile to import into.
+  // |items| - specifies which data to import (bitmask of importer::ImportItem).
+  // |writer| - called to actually write data back to the profile.
   virtual void StartImportSettings(
       const importer::SourceProfile& source_profile,
       Profile* target_profile,
       uint16 items,
-      ProfileWriter* writer) OVERRIDE;
-  virtual void InvokeTaskIfDone() OVERRIDE;
+      ProfileWriter* writer);
+
+  // When in headless mode, the importer will not show any warning dialog if
+  // a user action is required (e.g., Firefox profile is locked and user should
+  // close Firefox to continue) and the outcome is as if the user had canceled
+  // the import operation.
+  void set_headless() { headless_ = true; }
+  bool is_headless() const { return headless_; }
+
+  void set_parent_window(gfx::NativeWindow parent_window) {
+    parent_window_ = parent_window;
+  }
+
+  void set_observer(importer::ImporterProgressObserver* observer) {
+    observer_ = observer;
+  }
+
+  // A series of functions invoked at the start, during and end of the import
+  // process. The middle functions are notifications that the a harvesting of a
+  // particular source of data (specified by |item|) is under way.
+  void NotifyImportStarted();
+  void NotifyImportItemStarted(importer::ImportItem item);
+  void NotifyImportItemEnded(importer::ImportItem item);
+  void NotifyImportEnded();
+
+ private:
+  // ExternalProcessImporterHost deletes itself in OnImportEnded().
+  virtual ~ExternalProcessImporterHost();
+
+  // Launches the utility process that starts the import task, unless bookmark
+  // or template model are not yet loaded. If load is not detected, this method
+  // will be called when the loading observer sees that model loading is
+  // complete.
+  virtual void LaunchImportIfReady();
+
+  // BaseBookmarkModelObserver:
   virtual void Loaded(BookmarkModel* model, bool ids_reassigned) OVERRIDE;
+  virtual void BookmarkModelBeingDeleted(BookmarkModel* model) OVERRIDE;
+  virtual void BookmarkModelChanged() OVERRIDE;
+
+  // content::NotificationObserver:
+  // Called when TemplateURLService has been loaded.
+  virtual void Observe(int type,
+                       const content::NotificationSource& source,
+                       const content::NotificationDetails& details) OVERRIDE;
+
+  // ShowWarningDialog() asks user to close the application that is owning the
+  // lock. They can retry or skip the importing process.
+  // This method should not be called if the importer is in headless mode.
+  void ShowWarningDialog();
+
+  // This is called when when user ends the lock dialog by clicking on either
+  // the "Skip" or "Continue" buttons. |is_continue| is true when user clicked
+  // the "Continue" button.
+  void OnImportLockDialogEnd(bool is_continue);
+
+  // Make sure that Firefox isn't running, if import browser is Firefox. Show
+  // to the user a dialog that notifies that is necessary to close Firefox
+  // prior to continue.
+  // |source_profile| - importer profile to import.
+  // Returns false iff import should be aborted.
+  bool CheckForFirefoxLock(const importer::SourceProfile& source_profile);
+
+  // Make sure BookmarkModel and TemplateURLService are loaded before import
+  // process starts, if bookmarks and/or search engines are among the items
+  // which are to be imported.
+  void CheckForLoadedModels(uint16 items);
+
+  // Vends weak pointers for the importer to call us back.
+  base::WeakPtrFactory<ExternalProcessImporterHost> weak_ptr_factory_;
+
+  // True if UI is not to be shown.
+  bool headless_;
+
+  // Parent window that we pass to the import lock dialog (i.e, the Firefox
+  // warning dialog).
+  gfx::NativeWindow parent_window_;
+
+  // The observer that we need to notify about changes in the import process.
+  importer::ImporterProgressObserver* observer_;
+
+  // Firefox profile lock.
+  scoped_ptr<FirefoxProfileLock> firefox_lock_;
+
+  // Profile we're importing from.
+  Profile* profile_;
+
+  // True if we're waiting for the model to finish loading.
+  bool waiting_for_bookmarkbar_model_;
+
+  // Have we installed a listener on the bookmark model?
+  bool installed_bookmark_observer_;
+
+  // True if source profile is readable.
+  bool is_source_readable_;
+
+  // Receives notification when the TemplateURLService has loaded.
+  content::NotificationRegistrar registrar_;
+
+  // Writes data from the importer back to the profile.
+  scoped_refptr<ProfileWriter> writer_;
 
   // Used to pass notifications from the browser side to the external process.
   ExternalProcessImporterClient* client_;
diff --git a/chrome/browser/importer/firefox3_importer.cc b/chrome/browser/importer/firefox3_importer.cc
index e58fa81..c3ec58d 100644
--- a/chrome/browser/importer/firefox3_importer.cc
+++ b/chrome/browser/importer/firefox3_importer.cc
@@ -13,22 +13,22 @@
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/bookmarks/bookmark_html_reader.h"
-#include "chrome/browser/bookmarks/imported_bookmark_entry.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/favicon/favicon_util.h"
-#include "chrome/browser/favicon/imported_favicon_usage.h"
+#include "chrome/browser/importer/bookmark_html_reader.h"
 #include "chrome/browser/importer/firefox_importer_utils.h"
 #include "chrome/browser/importer/importer_bridge.h"
 #include "chrome/browser/importer/nss_decryptor.h"
-#include "chrome/browser/search_engines/template_url.h"
+#include "chrome/common/importer/imported_bookmark_entry.h"
+#include "chrome/common/importer/imported_favicon_usage.h"
+#include "chrome/common/importer/importer_url_row.h"
 #include "chrome/common/time_format.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/common/password_form.h"
-#include "googleurl/src/gurl.h"
 #include "grit/generated_resources.h"
 #include "sql/connection.h"
 #include "sql/statement.h"
+#include "url/gurl.h"
 
 using content::BrowserThread;
 
@@ -43,24 +43,6 @@
   TYPE_DYNAMIC_CONTAINER = 4
 };
 
-// Creates a TemplateURL with the |keyword| and |url|. |title| may be empty.
-// This function transfers ownership of the created TemplateURL to the caller.
-TemplateURL* CreateTemplateURL(const string16& title,
-                               const string16& keyword,
-                               const GURL& url) {
-  // Skip if the keyword or url is invalid.
-  if (keyword.empty() || !url.is_valid())
-    return NULL;
-
-  TemplateURLData data;
-  // We set short name by using the title if it exists.
-  // Otherwise, we use the shortcut.
-  data.short_name = title.empty() ? keyword : title;
-  data.SetKeyword(keyword);
-  data.SetURL(TemplateURLRef::DisplayURLToURLRef(UTF8ToUTF16(url.spec())));
-  return new TemplateURL(NULL, data);
-}
-
 // Loads the default bookmarks in the Firefox installed at |app_path|,
 // and stores their locations in |urls|.
 void LoadDefaultBookmarks(const base::FilePath& app_path,
@@ -95,10 +77,6 @@
 };
 
 Firefox3Importer::Firefox3Importer() {
-#if defined(OS_POSIX) && !defined(OS_MACOSX)
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  locale_ = g_browser_process->GetApplicationLocale();
-#endif
 }
 
 Firefox3Importer::~Firefox3Importer() {
@@ -108,13 +86,14 @@
     const importer::SourceProfile& source_profile,
     uint16 items,
     ImporterBridge* bridge) {
-#if defined(OS_POSIX) && !defined(OS_MACOSX)
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-#endif
   bridge_ = bridge;
   source_path_ = source_profile.source_path;
   app_path_ = source_profile.app_path;
 
+#if defined(OS_POSIX)
+  locale_ = source_profile.locale;
+#endif
+
   // The order here is important!
   bridge_->NotifyStarted();
   if ((items & importer::HOME_PAGE) && !cancelled())
@@ -169,7 +148,7 @@
 
   sql::Statement s(db.GetUniqueStatement(query));
 
-  history::URLRows rows;
+  std::vector<ImporterURLRow> rows;
   while (s.Step() && !cancelled()) {
     GURL url(s.ColumnString(0));
 
@@ -177,12 +156,12 @@
     if (!CanImportURL(url))
       continue;
 
-    history::URLRow row(url);
-    row.set_title(s.ColumnString16(1));
-    row.set_visit_count(s.ColumnInt(2));
-    row.set_hidden(s.ColumnInt(3) == 1);
-    row.set_typed_count(s.ColumnInt(4));
-    row.set_last_visit(base::Time::FromTimeT(s.ColumnInt64(5)/1000000));
+    ImporterURLRow row(url);
+    row.title = s.ColumnString16(1);
+    row.visit_count = s.ColumnInt(2);
+    row.hidden = s.ColumnInt(3) == 1;
+    row.typed_count = s.ColumnInt(4);
+    row.last_visit = base::Time::FromTimeT(s.ColumnInt64(5)/1000000);
 
     rows.push_back(row);
   }
@@ -223,7 +202,7 @@
     GetWholeBookmarkFolder(&db, &list, i, NULL);
 
   std::vector<ImportedBookmarkEntry> bookmarks;
-  std::vector<TemplateURL*> template_urls;
+  std::vector<importer::URLKeywordInfo> url_keywords;
   FaviconMap favicon_map;
 
   // TODO(jcampan): http://b/issue?id=1196285 we do not support POST based
@@ -311,11 +290,14 @@
       if (item->favicon)
         favicon_map[item->favicon].insert(item->url);
 
-      // This bookmark has a keyword, we import it to our TemplateURL model.
-      TemplateURL* t_url = CreateTemplateURL(
-          item->title, UTF8ToUTF16(item->keyword), item->url);
-      if (t_url)
-        template_urls.push_back(t_url);
+      // This bookmark has a keyword, we should import it.
+      if (!item->keyword.empty() && item->url.is_valid()) {
+        importer::URLKeywordInfo url_keyword_info;
+        url_keyword_info.url = item->url;
+        url_keyword_info.keyword.assign(UTF8ToUTF16(item->keyword));
+        url_keyword_info.display_name = item->title;
+        url_keywords.push_back(url_keyword_info);
+      }
     }
   }
 
@@ -327,10 +309,9 @@
         bridge_->GetLocalizedString(IDS_BOOKMARK_GROUP_FROM_FIREFOX);
     bridge_->AddBookmarks(bookmarks, first_folder_name);
   }
-  if (!template_urls.empty() && !cancelled())
-    bridge_->SetKeywords(template_urls, false);
-  else
-    STLDeleteElements(&template_urls);
+  if (!url_keywords.empty() && !cancelled()) {
+    bridge_->SetKeywords(url_keywords, false);
+  }
   if (!favicon_map.empty() && !cancelled()) {
     std::vector<ImportedFaviconUsage> favicons;
     LoadFavicons(&db, favicon_map, &favicons);
@@ -371,13 +352,10 @@
 }
 
 void Firefox3Importer::ImportSearchEngines() {
-  std::vector<base::FilePath> files;
-  GetSearchEnginesXMLFiles(&files);
+  std::vector<std::string> search_engine_data;
+  GetSearchEnginesXMLData(&search_engine_data);
 
-  std::vector<TemplateURL*> search_engines;
-  ParseSearchEnginesFromXMLFiles(files, &search_engines);
-
-  bridge_->SetKeywords(search_engines, true);
+  bridge_->SetFirefoxSearchEnginesXMLData(search_engine_data);
 }
 
 void Firefox3Importer::ImportHomepage() {
@@ -387,8 +365,8 @@
   }
 }
 
-void Firefox3Importer::GetSearchEnginesXMLFiles(
-    std::vector<base::FilePath>* files) {
+void Firefox3Importer::GetSearchEnginesXMLData(
+    std::vector<std::string>* search_engine_data) {
   base::FilePath file = source_path_.AppendASCII("search.sqlite");
   if (!file_util::PathExists(file))
     return;
@@ -435,16 +413,19 @@
         // Looks like absolute path to the file.
         file = base::FilePath::FromUTF8Unsafe(engine);
       }
-      files->push_back(file);
+      std::string file_data;
+      file_util::ReadFileToString(file, &file_data);
+      search_engine_data->push_back(file_data);
     } while (s.Step() && !cancelled());
   }
 
-#if defined(OS_POSIX) && !defined(OS_MACOSX)
+#if defined(OS_POSIX)
   // Ubuntu-flavored Firefox3 supports locale-specific search engines via
   // locale-named subdirectories. They fall back to en-US.
   // See http://crbug.com/53899
   // TODO(jshin): we need to make sure our locale code matches that of
   // Firefox.
+  DCHECK(!locale_.empty());
   base::FilePath locale_app_path = app_path.AppendASCII(locale_);
   base::FilePath default_locale_app_path = app_path.AppendASCII("en-US");
   if (file_util::DirectoryExists(locale_app_path))
@@ -457,7 +438,9 @@
   base::FileEnumerator engines(app_path, false, base::FileEnumerator::FILES);
   for (base::FilePath engine_path = engines.Next();
        !engine_path.value().empty(); engine_path = engines.Next()) {
-    files->push_back(engine_path);
+    std::string file_data;
+    file_util::ReadFileToString(file, &file_data);
+    search_engine_data->push_back(file_data);
   }
 }
 
diff --git a/chrome/browser/importer/firefox3_importer.h b/chrome/browser/importer/firefox3_importer.h
index bff7eb3..a609f80 100644
--- a/chrome/browser/importer/firefox3_importer.h
+++ b/chrome/browser/importer/firefox3_importer.h
@@ -46,7 +46,7 @@
   // Import the user's home page, unless it is set to default home page as
   // defined in browserconfig.properties.
   void ImportHomepage();
-  void GetSearchEnginesXMLFiles(std::vector<base::FilePath>* files);
+  void GetSearchEnginesXMLData(std::vector<std::string>* search_engine_data);
 
   // The struct stores the information about a bookmark item.
   struct BookmarkItem;
@@ -78,9 +78,8 @@
   base::FilePath source_path_;
   base::FilePath app_path_;
 
-#if defined(OS_POSIX) && !defined(OS_MACOSX)
-  // Stored because we can only access it from the UI thread. Not usable
-  // in Mac because no access from out-of-process import.
+#if defined(OS_POSIX)
+  // Stored because we can only access it from the UI thread.
   std::string locale_;
 #endif
 
diff --git a/chrome/browser/importer/firefox_importer_browsertest.cc b/chrome/browser/importer/firefox_importer_browsertest.cc
index 4042f35..8cde615 100644
--- a/chrome/browser/importer/firefox_importer_browsertest.cc
+++ b/chrome/browser/importer/firefox_importer_browsertest.cc
@@ -11,17 +11,16 @@
 #include "base/strings/string16.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/bookmarks/imported_bookmark_entry.h"
-#include "chrome/browser/favicon/imported_favicon_usage.h"
 #include "chrome/browser/importer/external_process_importer_host.h"
 #include "chrome/browser/importer/firefox_importer_unittest_utils.h"
-#include "chrome/browser/importer/importer_data_types.h"
-#include "chrome/browser/importer/importer_host.h"
 #include "chrome/browser/importer/importer_progress_observer.h"
 #include "chrome/browser/importer/importer_unittest_utils.h"
 #include "chrome/browser/search_engines/template_url.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/common/chrome_paths.h"
+#include "chrome/common/importer/imported_bookmark_entry.h"
+#include "chrome/common/importer/imported_favicon_usage.h"
+#include "chrome/common/importer/importer_data_types.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "content/public/common/password_form.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -220,7 +219,7 @@
     // Creates a new profile in a new subdirectory in the temp directory.
     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
     base::FilePath test_path = temp_dir_.path().AppendASCII("ImporterTest");
-    file_util::Delete(test_path, true);
+    base::Delete(test_path, true);
     file_util::CreateDirectory(test_path);
     profile_path_ = test_path.AppendASCII("profile");
     app_path_ = test_path.AppendASCII("app");
@@ -262,20 +261,15 @@
     source_profile.importer_type = importer::TYPE_FIREFOX3;
     source_profile.app_path = app_path_;
     source_profile.source_path = profile_path_;
+    source_profile.locale = "en-US";
 
     int items = importer::HISTORY | importer::PASSWORDS | importer::FAVORITES;
     if (import_search_plugins)
       items = items | importer::SEARCH_ENGINES;
 
     // Deletes itself.
-    // TODO(gab): Use ExternalProcessImporterHost on Linux as well.
-    ImporterHost* host;
-#if defined(OS_MACOSX) || defined(OS_WIN)
-    host = new ExternalProcessImporterHost;
-#else
-    host = new ImporterHost;
-#endif
-    host->SetObserver(observer);
+    ExternalProcessImporterHost* host = new ExternalProcessImporterHost;
+    host->set_observer(observer);
     host->StartImportSettings(source_profile,
                               browser()->profile(),
                               items,
diff --git a/chrome/browser/importer/firefox_importer_utils.cc b/chrome/browser/importer/firefox_importer_utils.cc
index 4553c11..5610f5b 100644
--- a/chrome/browser/importer/firefox_importer_utils.cc
+++ b/chrome/browser/importer/firefox_importer_utils.cc
@@ -16,38 +16,9 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
-#include "chrome/browser/search_engines/template_url.h"
-#include "chrome/browser/search_engines/template_url_parser.h"
-#include "chrome/browser/search_engines/template_url_prepopulate_data.h"
-#include "chrome/browser/search_engines/template_url_service.h"
-#include "googleurl/src/gurl.h"
 #include "grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
-
-namespace {
-
-// FirefoxURLParameterFilter is used to remove parameter mentioning Firefox from
-// the search URL when importing search engines.
-class FirefoxURLParameterFilter : public TemplateURLParser::ParameterFilter {
- public:
-  FirefoxURLParameterFilter() {}
-  virtual ~FirefoxURLParameterFilter() {}
-
-  // TemplateURLParser::ParameterFilter method.
-  virtual bool KeepParameter(const std::string& key,
-                             const std::string& value) OVERRIDE {
-    std::string low_value = StringToLowerASCII(value);
-    if (low_value.find("mozilla") != std::string::npos ||
-        low_value.find("firefox") != std::string::npos ||
-        low_value.find("moz:") != std::string::npos )
-      return false;
-    return true;
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(FirefoxURLParameterFilter);
-};
-}  // namespace
+#include "url/gurl.h"
 
 base::FilePath GetFirefoxProfilePath() {
   base::FilePath ini_file = GetProfilesINI();
@@ -149,53 +120,6 @@
   return true;
 }
 
-void ParseSearchEnginesFromXMLFiles(
-    const std::vector<base::FilePath>& xml_files,
-    std::vector<TemplateURL*>* search_engines) {
-  DCHECK(search_engines);
-
-  typedef std::map<std::string, TemplateURL*> SearchEnginesMap;
-  SearchEnginesMap search_engine_for_url;
-  std::string content;
-  // The first XML file represents the default search engine in Firefox 3, so we
-  // need to keep it on top of the list.
-  SearchEnginesMap::const_iterator default_turl = search_engine_for_url.end();
-  for (std::vector<base::FilePath>::const_iterator file_iter =
-           xml_files.begin(); file_iter != xml_files.end(); ++file_iter) {
-    file_util::ReadFileToString(*file_iter, &content);
-    FirefoxURLParameterFilter param_filter;
-    TemplateURL* template_url = TemplateURLParser::Parse(NULL, true,
-        content.data(), content.length(), &param_filter);
-    if (template_url) {
-      SearchEnginesMap::iterator iter =
-          search_engine_for_url.find(template_url->url());
-      if (iter == search_engine_for_url.end()) {
-        iter = search_engine_for_url.insert(
-            std::make_pair(template_url->url(), template_url)).first;
-      } else {
-        // We have already found a search engine with the same URL.  We give
-        // priority to the latest one found, as GetSearchEnginesXMLFiles()
-        // returns a vector with first Firefox default search engines and then
-        // the user's ones.  We want to give priority to the user ones.
-        delete iter->second;
-        iter->second = template_url;
-      }
-      if (default_turl == search_engine_for_url.end())
-        default_turl = iter;
-    }
-    content.clear();
-  }
-
-  // Put the results in the |search_engines| vector.
-  for (SearchEnginesMap::iterator t_iter = search_engine_for_url.begin();
-       t_iter != search_engine_for_url.end(); ++t_iter) {
-    if (t_iter == default_turl)
-      search_engines->insert(search_engines->begin(), default_turl->second);
-    else
-      search_engines->push_back(t_iter->second);
-  }
-}
-
 bool ReadPrefFile(const base::FilePath& path, std::string* content) {
   if (content == NULL)
     return false;
diff --git a/chrome/browser/importer/firefox_importer_utils.h b/chrome/browser/importer/firefox_importer_utils.h
index 54e7162..5446ddf 100644
--- a/chrome/browser/importer/firefox_importer_utils.h
+++ b/chrome/browser/importer/firefox_importer_utils.h
@@ -71,11 +71,6 @@
 // with a unsupported scheme.
 bool CanImportURL(const GURL& url);
 
-// Parses the OpenSearch XML files in |xml_files| and populates |search_engines|
-// with the resulting TemplateURLs.
-void ParseSearchEnginesFromXMLFiles(const std::vector<base::FilePath>& xml_files,
-                                    std::vector<TemplateURL*>* search_engines);
-
 // Returns the home page set in Firefox in a particular profile.
 GURL GetHomepage(const base::FilePath& profile_path);
 
diff --git a/chrome/browser/importer/firefox_profile_lock_posix.cc b/chrome/browser/importer/firefox_profile_lock_posix.cc
index 2b24187..dd00b70 100644
--- a/chrome/browser/importer/firefox_profile_lock_posix.cc
+++ b/chrome/browser/importer/firefox_profile_lock_posix.cc
@@ -78,7 +78,7 @@
     return;
   close(lock_fd_);
   lock_fd_ = -1;
-  file_util::Delete(old_lock_file_, false);
+  base::Delete(old_lock_file_, false);
 }
 
 bool FirefoxProfileLock::HasAcquired() {
diff --git a/chrome/browser/importer/ie_importer.cc b/chrome/browser/importer/ie_importer.cc
index cb6e7a2..b5ad754 100644
--- a/chrome/browser/importer/ie_importer.cc
+++ b/chrome/browser/importer/ie_importer.cc
@@ -22,30 +22,28 @@
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/win/registry.h"
 #include "base/win/scoped_co_mem.h"
 #include "base/win/scoped_comptr.h"
 #include "base/win/scoped_handle.h"
 #include "base/win/scoped_propvariant.h"
 #include "base/win/windows_version.h"
-#include "chrome/browser/bookmarks/imported_bookmark_entry.h"
 #include "chrome/browser/favicon/favicon_util.h"
-#include "chrome/browser/favicon/imported_favicon_usage.h"
 #include "chrome/browser/importer/ie_importer_utils_win.h"
 #include "chrome/browser/importer/importer_bridge.h"
-#include "chrome/browser/importer/importer_data_types.h"
 #include "chrome/browser/importer/pstore_declarations.h"
-#include "chrome/browser/search_engines/template_url.h"
-#include "chrome/browser/search_engines/template_url_prepopulate_data.h"
-#include "chrome/browser/search_engines/template_url_service.h"
+#include "chrome/common/importer/imported_bookmark_entry.h"
+#include "chrome/common/importer/imported_favicon_usage.h"
+#include "chrome/common/importer/importer_data_types.h"
+#include "chrome/common/importer/importer_url_row.h"
 #include "chrome/common/time_format.h"
 #include "chrome/common/url_constants.h"
 #include "components/webdata/encryptor/ie7_password.h"
 #include "content/public/common/password_form.h"
-#include "googleurl/src/gurl.h"
 #include "grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "url/gurl.h"
 
 namespace {
 
@@ -489,7 +487,7 @@
     return;
   base::win::ScopedComPtr<IEnumSTATURL> enum_url;
   if (SUCCEEDED(result = url_history_stg2->EnumUrls(enum_url.Receive()))) {
-    history::URLRows rows;
+    std::vector<ImporterURLRow> rows;
     STATURL stat_url;
     ULONG fetched;
     while (!cancelled() &&
@@ -512,14 +510,14 @@
            kSchemes + total_schemes))
         continue;
 
-      history::URLRow row(url);
-      row.set_title(title_string);
-      row.set_last_visit(base::Time::FromFileTime(stat_url.ftLastVisited));
+      ImporterURLRow row(url);
+      row.title = title_string;
+      row.last_visit = base::Time::FromFileTime(stat_url.ftLastVisited);
       if (stat_url.dwFlags == STATURL_QUERYFLAG_TOPLEVEL) {
-        row.set_visit_count(1);
-        row.set_hidden(false);
+        row.visit_count = 1;
+        row.hidden = false;
       } else {
-        row.set_hidden(true);
+        row.hidden = true;
       }
 
       rows.push_back(row);
@@ -686,7 +684,7 @@
   // Software\Microsoft\Internet Explorer\SearchScopes
   // Each key represents a search engine. The URL value contains the URL and
   // the DisplayName the name.
-  typedef std::map<std::string, TemplateURL*> SearchEnginesMap;
+  typedef std::map<std::string, string16> SearchEnginesMap;
   SearchEnginesMap search_engines_map;
   for (base::win::RegistryKeyIterator key_iter(HKEY_CURRENT_USER,
        kSearchScopePath); key_iter.Valid(); ++key_iter) {
@@ -719,24 +717,20 @@
       // First time we see that URL.
       GURL gurl(url);
       if (gurl.is_valid()) {
-        TemplateURLData data;
-        data.short_name = name;
-        data.SetKeyword(TemplateURLService::GenerateKeyword(gurl));
-        data.SetURL(url);
-        data.show_in_default_list = true;
-        t_iter = search_engines_map.insert(std::make_pair(url,
-            new TemplateURL(NULL, data))).first;
+        t_iter = search_engines_map.insert(std::make_pair(url, name)).first;
       }
     }
   }
-
   // ProfileWriter::AddKeywords() requires a vector and we have a map.
-  std::vector<TemplateURL*> search_engines;
+  std::vector<importer::URLKeywordInfo> url_keywords;
   for (SearchEnginesMap::iterator i = search_engines_map.begin();
-       i != search_engines_map.end(); ++i)
-    search_engines.push_back(i->second);
-
-  bridge_->SetKeywords(search_engines, true);
+       i != search_engines_map.end(); ++i) {
+    importer::URLKeywordInfo url_keyword_info;
+    url_keyword_info.url = GURL(i->first);
+    url_keyword_info.display_name = i->second;
+    url_keywords.push_back(url_keyword_info);
+  }
+  bridge_->SetKeywords(url_keywords, true);
 }
 
 void IEImporter::ImportHomepage() {
diff --git a/chrome/browser/importer/ie_importer_browsertest_win.cc b/chrome/browser/importer/ie_importer_browsertest_win.cc
index b281b57..d4747d4 100644
--- a/chrome/browser/importer/ie_importer_browsertest_win.cc
+++ b/chrome/browser/importer/ie_importer_browsertest_win.cc
@@ -6,10 +6,10 @@
 #include <windows.h>
 #include <unknwn.h>
 #include <intshcut.h>
-#include <shlguid.h>
-#include <urlhist.h>
-#include <shlobj.h>
 #include <propvarutil.h>
+#include <shlguid.h>
+#include <shlobj.h>
+#include <urlhist.h>
 
 #include <algorithm>
 #include <vector>
@@ -28,21 +28,20 @@
 #include "base/win/scoped_comptr.h"
 #include "base/win/scoped_propvariant.h"
 #include "base/win/windows_version.h"
-#include "chrome/browser/bookmarks/imported_bookmark_entry.h"
-#include "chrome/browser/favicon/imported_favicon_usage.h"
 #include "chrome/browser/importer/external_process_importer_host.h"
 #include "chrome/browser/importer/ie_importer.h"
 #include "chrome/browser/importer/ie_importer_test_registry_overrider_win.h"
 #include "chrome/browser/importer/ie_importer_utils_win.h"
 #include "chrome/browser/importer/importer_bridge.h"
-#include "chrome/browser/importer/importer_data_types.h"
-#include "chrome/browser/importer/importer_host.h"
 #include "chrome/browser/importer/importer_progress_observer.h"
 #include "chrome/browser/importer/importer_unittest_utils.h"
 #include "chrome/browser/importer/pstore_declarations.h"
 #include "chrome/browser/search_engines/template_url.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/common/chrome_paths.h"
+#include "chrome/common/importer/imported_bookmark_entry.h"
+#include "chrome/common/importer/imported_favicon_usage.h"
+#include "chrome/common/importer/importer_data_types.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/common/password_form.h"
@@ -485,9 +484,9 @@
 
   // Starts to import the above settings.
   // Deletes itself.
-  ImporterHost* host = new ExternalProcessImporterHost;
+  ExternalProcessImporterHost* host = new ExternalProcessImporterHost;
   TestObserver* observer = new TestObserver();
-  host->SetObserver(observer);
+  host->set_observer(observer);
 
   importer::SourceProfile source_profile;
   source_profile.importer_type = importer::TYPE_IE;
@@ -561,10 +560,10 @@
 
     // Starts to import the above settings.
     // Deletes itself.
-    ImporterHost* host = new ExternalProcessImporterHost;
+    ExternalProcessImporterHost* host = new ExternalProcessImporterHost;
     MalformedFavoritesRegistryTestObserver* observer =
         new MalformedFavoritesRegistryTestObserver();
-    host->SetObserver(observer);
+    host->set_observer(observer);
 
     importer::SourceProfile source_profile;
     source_profile.importer_type = importer::TYPE_IE;
diff --git a/chrome/browser/importer/importer_bridge.h b/chrome/browser/importer/importer_bridge.h
index 76915d3..ac9cfd5 100644
--- a/chrome/browser/importer/importer_bridge.h
+++ b/chrome/browser/importer/importer_bridge.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_IMPORTER_IMPORTER_BRIDGE_H_
 #define CHROME_BROWSER_IMPORTER_IMPORTER_BRIDGE_H_
 
+#include <string>
 #include <vector>
 
 #include "base/basictypes.h"
@@ -12,15 +13,17 @@
 #include "base/strings/string16.h"
 #include "build/build_config.h"
 #include "chrome/browser/history/history_types.h"
-#include "chrome/browser/importer/importer_data_types.h"
+#include "chrome/common/importer/importer_data_types.h"
+#include "chrome/common/importer/importer_url_row.h"
 
 class GURL;
 struct IE7PasswordInfo;
 struct ImportedBookmarkEntry;
 struct ImportedFaviconUsage;
-class TemplateURL;
-// TODO: remove this, see friend declaration in ImporterBridge.
-class Toolbar5Importer;
+
+namespace importer {
+struct URLKeywordInfo;
+}
 
 namespace content {
 struct PasswordForm;
@@ -43,13 +46,17 @@
   virtual void SetFavicons(
       const std::vector<ImportedFaviconUsage>& favicons) = 0;
 
-  virtual void SetHistoryItems(const history::URLRows& rows,
+  virtual void SetHistoryItems(const std::vector<ImporterURLRow>& rows,
                                history::VisitSource visit_source) = 0;
 
-  // WARNING: This function takes ownership of (and deletes) the pointers in
-  // |template_urls|!
-  virtual void SetKeywords(const std::vector<TemplateURL*>& template_urls,
-                           bool unique_on_host_and_path) = 0;
+  virtual void SetKeywords(
+      const std::vector<importer::URLKeywordInfo>& url_keywords,
+      bool unique_on_host_and_path) = 0;
+
+  // The search_engine_data vector contains XML data retrieved from the Firefox
+  // profile and its sqlite db.
+  virtual void SetFirefoxSearchEnginesXMLData(
+      const std::vector<std::string>& search_engine_data) = 0;
 
   virtual void SetPasswordForm(const content::PasswordForm& form) = 0;
 
@@ -75,10 +82,6 @@
 
  protected:
   friend class base::RefCountedThreadSafe<ImporterBridge>;
-  // TODO: In order to run Toolbar5Importer OOP we need to cut this
-  // connection, but as an interim step we allow Toolbar5Import to break
-  // the abstraction here and assume import is in-process.
-  friend class Toolbar5Importer;
 
   virtual ~ImporterBridge();
 
diff --git a/chrome/browser/importer/importer_creator.cc b/chrome/browser/importer/importer_creator.cc
new file mode 100644
index 0000000..7127ed2
--- /dev/null
+++ b/chrome/browser/importer/importer_creator.cc
@@ -0,0 +1,107 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/importer/importer_creator.h"
+
+#include "base/logging.h"
+#include "base/metrics/histogram.h"
+#include "chrome/browser/importer/bookmarks_file_importer.h"
+#include "chrome/browser/importer/firefox3_importer.h"
+
+#if defined(OS_WIN)
+#include "chrome/browser/importer/ie_importer.h"
+#endif
+
+#if defined(OS_MACOSX)
+#include <CoreFoundation/CoreFoundation.h>
+#include "base/mac/foundation_util.h"
+#include "chrome/browser/importer/safari_importer.h"
+#endif
+
+namespace importer {
+
+namespace {
+
+// The enum used to register importer use.
+enum ImporterTypeMetrics {
+  IMPORTER_METRICS_UNKNOWN         = 0,
+#if defined(OS_WIN)
+  IMPORTER_METRICS_IE              = 1,
+#endif
+  IMPORTER_METRICS_FIREFOX2        = 2,  // obsolete
+  IMPORTER_METRICS_FIREFOX3        = 3,
+#if defined(OS_MACOSX)
+  IMPORTER_METRICS_SAFARI          = 4,
+#endif
+  IMPORTER_METRICS_GOOGLE_TOOLBAR5 = 5,  // obsolete
+  IMPORTER_METRICS_BOOKMARKS_FILE  = 6,
+
+  // Insert new values here. Never remove any existing values, as this enum is
+  // used to bucket a UMA histogram, and removing values breaks that.
+  IMPORTER_METRICS_SIZE
+};
+
+
+}  // namespace
+
+Importer* CreateImporterByType(ImporterType type) {
+  switch (type) {
+#if defined(OS_WIN)
+    case TYPE_IE:
+      return new IEImporter();
+#endif
+    case TYPE_BOOKMARKS_FILE:
+      return new BookmarksFileImporter();
+    case TYPE_FIREFOX3:
+      return new Firefox3Importer();
+#if defined(OS_MACOSX)
+    case TYPE_SAFARI:
+      return new SafariImporter(base::mac::GetUserLibraryPath());
+#endif
+    default:
+      NOTREACHED();
+      return NULL;
+  }
+  NOTREACHED();
+  return NULL;
+}
+
+void LogImporterUseToMetrics(const std::string& metric_postfix,
+                             ImporterType type) {
+  ImporterTypeMetrics metrics_type = IMPORTER_METRICS_UNKNOWN;
+  switch (type) {
+    case TYPE_UNKNOWN:
+      metrics_type = IMPORTER_METRICS_UNKNOWN;
+      break;
+#if defined(OS_WIN)
+    case TYPE_IE:
+      metrics_type = IMPORTER_METRICS_IE;
+      break;
+#endif
+    case TYPE_FIREFOX3:
+      metrics_type = IMPORTER_METRICS_FIREFOX3;
+      break;
+#if defined(OS_MACOSX)
+    case TYPE_SAFARI:
+      metrics_type = IMPORTER_METRICS_SAFARI;
+      break;
+#endif
+    case TYPE_BOOKMARKS_FILE:
+      metrics_type = IMPORTER_METRICS_BOOKMARKS_FILE;
+      break;
+  }
+
+  // Note: This leaks memory, which is the expected behavior as the factory
+  // creates and owns the histogram.
+  base::HistogramBase* histogram =
+      base::LinearHistogram::FactoryGet(
+          "Import.ImporterType." + metric_postfix,
+          1,
+          IMPORTER_METRICS_SIZE,
+          IMPORTER_METRICS_SIZE + 1,
+          base::HistogramBase::kUmaTargetedHistogramFlag);
+  histogram->Add(metrics_type);
+}
+
+}  // namespace importer
diff --git a/chrome/browser/importer/importer_creator.h b/chrome/browser/importer/importer_creator.h
new file mode 100644
index 0000000..b3b7465
--- /dev/null
+++ b/chrome/browser/importer/importer_creator.h
@@ -0,0 +1,28 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_IMPORTER_IMPORTER_CREATOR_H_
+#define CHROME_BROWSER_IMPORTER_IMPORTER_CREATOR_H_
+
+#include <string>
+
+#include "chrome/common/importer/importer_type.h"
+
+class Importer;
+
+namespace importer {
+
+// Creates an Importer of the specified |type|.
+Importer* CreateImporterByType(ImporterType type);
+
+// Logs to UMA that an Importer of the specified |type| was used. Uses
+// |metric_postfix| to split by entry point. Note: Values passed via
+// |metric_postfix| require a matching "Import.ImporterType.|metric_postfix|"
+// entry in tools/metrics/histograms/histograms.xml.
+void LogImporterUseToMetrics(const std::string& metric_prefix,
+                             ImporterType type);
+
+}  // namespace importer
+
+#endif  // CHROME_BROWSER_IMPORTER_IMPORTER_CREATOR_H_
diff --git a/chrome/browser/importer/importer_data_types.cc b/chrome/browser/importer/importer_data_types.cc
deleted file mode 100644
index a178fc2..0000000
--- a/chrome/browser/importer/importer_data_types.cc
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/importer/importer_data_types.h"
-
-namespace importer {
-
-SourceProfile::SourceProfile()
-    : importer_type(TYPE_UNKNOWN),
-      services_supported(0) {
-}
-
-SourceProfile::~SourceProfile() {
-}
-
-}  // namespace importer
diff --git a/chrome/browser/importer/importer_data_types.h b/chrome/browser/importer/importer_data_types.h
deleted file mode 100644
index 9b44fb2..0000000
--- a/chrome/browser/importer/importer_data_types.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_IMPORTER_IMPORTER_DATA_TYPES_H_
-#define CHROME_BROWSER_IMPORTER_IMPORTER_DATA_TYPES_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/files/file_path.h"
-#include "base/memory/ref_counted.h"
-#include "base/strings/string16.h"
-#include "chrome/browser/importer/importer_type.h"
-#include "net/url_request/url_request_context_getter.h"
-
-// Types needed for importing data from other browsers and the Google Toolbar.
-namespace importer {
-
-// An enumeration of the type of data that can be imported.
-enum ImportItem {
-  NONE           = 0,
-  HISTORY        = 1 << 0,
-  FAVORITES      = 1 << 1,
-  COOKIES        = 1 << 2,  // Not supported yet.
-  PASSWORDS      = 1 << 3,
-  SEARCH_ENGINES = 1 << 4,
-  HOME_PAGE      = 1 << 5,
-  ALL            = (1 << 6) - 1  // All the bits should be 1, hence the -1.
-};
-
-// Information about a profile needed by an importer to do import work.
-struct SourceProfile {
-  SourceProfile();
-  ~SourceProfile();
-
-  string16 importer_name;
-  ImporterType importer_type;
-  base::FilePath source_path;
-  base::FilePath app_path;
-  uint16 services_supported;  // Bitmask of ImportItem.
-  // The URLRequestContextGetter is only used for Google Toolbar.
-  scoped_refptr<net::URLRequestContextGetter> request_context_getter;
-};
-
-}  // namespace importer
-
-#endif  // CHROME_BROWSER_IMPORTER_IMPORTER_DATA_TYPES_H_
diff --git a/chrome/browser/importer/importer_host.cc b/chrome/browser/importer/importer_host.cc
deleted file mode 100644
index b22f7bc..0000000
--- a/chrome/browser/importer/importer_host.cc
+++ /dev/null
@@ -1,282 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/importer/importer_host.h"
-
-#include "base/bind.h"
-#include "base/message_loop.h"
-#include "base/metrics/histogram.h"
-#include "base/prefs/pref_service.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/bookmarks/bookmark_model.h"
-#include "chrome/browser/bookmarks/bookmark_model_factory.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/importer/firefox_profile_lock.h"
-#include "chrome/browser/importer/importer.h"
-#include "chrome/browser/importer/importer_lock_dialog.h"
-#include "chrome/browser/importer/importer_progress_observer.h"
-#include "chrome/browser/importer/importer_type.h"
-#include "chrome/browser/importer/in_process_importer_bridge.h"
-#include "chrome/browser/importer/toolbar_importer_utils.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/search_engines/template_url.h"
-#include "chrome/browser/search_engines/template_url_service.h"
-#include "chrome/browser/search_engines/template_url_service_factory.h"
-#include "chrome/browser/ui/browser_list.h"
-#include "chrome/browser/ui/browser_tabstrip.h"
-#include "chrome/browser/ui/simple_message_box.h"
-#include "chrome/common/chrome_notification_types.h"
-#include "chrome/common/pref_names.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/notification_source.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-#include "ui/base/l10n/l10n_util.h"
-
-using content::BrowserThread;
-
-ImporterHost::ImporterHost()
-    : weak_ptr_factory_(this),
-      profile_(NULL),
-      waiting_for_bookmarkbar_model_(false),
-      installed_bookmark_observer_(false),
-      is_source_readable_(true),
-      headless_(false),
-      parent_window_(NULL),
-      browser_(NULL),
-      observer_(NULL) {
-  BrowserList::AddObserver(this);
-}
-
-void ImporterHost::ShowWarningDialog() {
-  DCHECK(!headless_);
-  importer::ShowImportLockDialog(
-      parent_window_,
-      base::Bind(&ImporterHost::OnImportLockDialogEnd,
-                 weak_ptr_factory_.GetWeakPtr()));
-}
-
-void ImporterHost::OnImportLockDialogEnd(bool is_continue) {
-  if (is_continue) {
-    // User chose to continue, then we check the lock again to make
-    // sure that Firefox has been closed. Try to import the settings
-    // if successful. Otherwise, show a warning dialog.
-    firefox_lock_->Lock();
-    if (firefox_lock_->HasAcquired()) {
-      is_source_readable_ = true;
-      InvokeTaskIfDone();
-    } else {
-      ShowWarningDialog();
-    }
-  } else {
-    // User chose to skip the import process. We should reset the |task_| and
-    // notify the ImporterHost to finish.
-    task_.Reset();
-    importer_ = NULL;
-    NotifyImportEnded();
-  }
-}
-
-void ImporterHost::SetObserver(importer::ImporterProgressObserver* observer) {
-  observer_ = observer;
-}
-
-void ImporterHost::NotifyImportStarted() {
-  if (observer_)
-    observer_->ImportStarted();
-}
-
-void ImporterHost::NotifyImportItemStarted(importer::ImportItem item) {
-  if (observer_)
-    observer_->ImportItemStarted(item);
-}
-
-void ImporterHost::NotifyImportItemEnded(importer::ImportItem item) {
-  if (observer_)
-    observer_->ImportItemEnded(item);
-}
-
-void ImporterHost::NotifyImportEnded() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  firefox_lock_.reset();  // Release the Firefox profile lock.
-  if (observer_)
-    observer_->ImportEnded();
-  delete this;
-}
-
-void ImporterHost::StartImportSettings(
-    const importer::SourceProfile& source_profile,
-    Profile* target_profile,
-    uint16 items,
-    ProfileWriter* writer) {
-  // We really only support importing from one host at a time.
-  DCHECK(!profile_);
-  DCHECK(target_profile);
-
-  profile_ = target_profile;
-  PrefService* user_prefs = profile_->GetPrefs();
-
-  // Make sure only items that were not disabled by policy are imported.
-  if (!user_prefs->GetBoolean(prefs::kImportHistory))
-    items &= ~importer::HISTORY;
-  if (!user_prefs->GetBoolean(prefs::kImportSearchEngine))
-    items &= ~importer::SEARCH_ENGINES;
-  if (!user_prefs->GetBoolean(prefs::kImportBookmarks))
-    items &= ~importer::FAVORITES;
-  if (!user_prefs->GetBoolean(prefs::kImportSavedPasswords))
-    items &= ~importer::PASSWORDS;
-
-  // Preserves the observer and creates a task, since we do async import so that
-  // it doesn't block the UI. When the import is complete, observer will be
-  // notified.
-  writer_ = writer;
-  importer_ = importer::CreateImporterByType(source_profile.importer_type);
-  // If we fail to create the Importer, exit, as we cannot do anything.
-  if (!importer_.get()) {
-    NotifyImportEnded();
-    return;
-  }
-
-  scoped_refptr<InProcessImporterBridge> bridge(
-      new InProcessImporterBridge(writer_.get(),
-                                  weak_ptr_factory_.GetWeakPtr()));
-  task_ = base::Bind(
-      &Importer::StartImport, importer_, source_profile, items, bridge);
-
-  if (!CheckForFirefoxLock(source_profile)) {
-    NotifyImportEnded();
-    return;
-  }
-
-#if defined(OS_WIN)
-  // For google toolbar import, we need the user to log in and store their GAIA
-  // credentials.
-  if (source_profile.importer_type == importer::TYPE_GOOGLE_TOOLBAR5) {
-    toolbar_importer_utils::IsGoogleGAIACookieInstalled(
-        base::Bind(&ImporterHost::OnGoogleGAIACookieChecked,
-                   weak_ptr_factory_.GetWeakPtr()),
-        profile_);
-    is_source_readable_ = false;
-  }
-#endif
-
-  CheckForLoadedModels(items);
-  InvokeTaskIfDone();
-}
-
-void ImporterHost::OnGoogleGAIACookieChecked(bool result) {
-#if defined(OS_WIN)
-  if (!result) {
-    chrome::ShowMessageBox(
-        NULL,
-        l10n_util::GetStringUTF16(IDS_PRODUCT_NAME),
-        l10n_util::GetStringUTF16(IDS_IMPORTER_GOOGLE_LOGIN_TEXT),
-        chrome::MESSAGE_BOX_TYPE_INFORMATION);
-
-    GURL url("https://accounts.google.com/ServiceLogin");
-    if (browser_)
-      chrome::AddSelectedTabWithURL(browser_, url,
-                                    content::PAGE_TRANSITION_TYPED);
-
-    base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
-        &ImporterHost::OnImportLockDialogEnd,
-        weak_ptr_factory_.GetWeakPtr(), false));
-  } else {
-    is_source_readable_ = true;
-    InvokeTaskIfDone();
-  }
-#endif
-}
-
-ImporterHost::~ImporterHost() {
-  BrowserList::RemoveObserver(this);
-
-  if (installed_bookmark_observer_) {
-    DCHECK(profile_);
-    BookmarkModelFactory::GetForProfile(profile_)->RemoveObserver(this);
-  }
-}
-
-bool ImporterHost::CheckForFirefoxLock(
-    const importer::SourceProfile& source_profile) {
-  if (source_profile.importer_type != importer::TYPE_FIREFOX3)
-    return true;
-
-  DCHECK(!firefox_lock_.get());
-  firefox_lock_.reset(new FirefoxProfileLock(source_profile.source_path));
-  if (firefox_lock_->HasAcquired())
-    return true;
-
-  // If fail to acquire the lock, we set the source unreadable and
-  // show a warning dialog, unless running without UI (in which case the import
-  // must be aborted).
-  is_source_readable_ = false;
-  if (headless_)
-    return false;
-
-  ShowWarningDialog();
-  return true;
-}
-
-void ImporterHost::CheckForLoadedModels(uint16 items) {
-  // A target profile must be loaded by StartImportSettings().
-  DCHECK(profile_);
-
-  // BookmarkModel should be loaded before adding IE favorites. So we observe
-  // the BookmarkModel if needed, and start the task after it has been loaded.
-  if ((items & importer::FAVORITES) && !writer_->BookmarkModelIsLoaded()) {
-    BookmarkModelFactory::GetForProfile(profile_)->AddObserver(this);
-    waiting_for_bookmarkbar_model_ = true;
-    installed_bookmark_observer_ = true;
-  }
-
-  // Observes the TemplateURLService if needed to import search engines from the
-  // other browser. We also check to see if we're importing bookmarks because
-  // we can import bookmark keywords from Firefox as search engines.
-  if ((items & importer::SEARCH_ENGINES) || (items & importer::FAVORITES)) {
-    if (!writer_->TemplateURLServiceIsLoaded()) {
-      TemplateURLService* model =
-          TemplateURLServiceFactory::GetForProfile(profile_);
-      registrar_.Add(this, chrome::NOTIFICATION_TEMPLATE_URL_SERVICE_LOADED,
-                     content::Source<TemplateURLService>(model));
-      model->Load();
-    }
-  }
-}
-
-void ImporterHost::InvokeTaskIfDone() {
-  if (waiting_for_bookmarkbar_model_ || !registrar_.IsEmpty() ||
-      !is_source_readable_)
-    return;
-  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, task_);
-}
-
-void ImporterHost::Loaded(BookmarkModel* model, bool ids_reassigned) {
-  DCHECK(model->loaded());
-  model->RemoveObserver(this);
-  waiting_for_bookmarkbar_model_ = false;
-  installed_bookmark_observer_ = false;
-
-  InvokeTaskIfDone();
-}
-
-void ImporterHost::BookmarkModelBeingDeleted(BookmarkModel* model) {
-  installed_bookmark_observer_ = false;
-}
-
-void ImporterHost::BookmarkModelChanged() {
-}
-
-void ImporterHost::Observe(int type,
-                           const content::NotificationSource& source,
-                           const content::NotificationDetails& details) {
-  DCHECK(type == chrome::NOTIFICATION_TEMPLATE_URL_SERVICE_LOADED);
-  registrar_.RemoveAll();
-  InvokeTaskIfDone();
-}
-
-void ImporterHost::OnBrowserRemoved(Browser* browser) {
-  if (browser_ == browser)
-    browser_ = NULL;
-}
diff --git a/chrome/browser/importer/importer_host.h b/chrome/browser/importer/importer_host.h
deleted file mode 100644
index ecfe9e6..0000000
--- a/chrome/browser/importer/importer_host.h
+++ /dev/null
@@ -1,171 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_IMPORTER_IMPORTER_HOST_H_
-#define CHROME_BROWSER_IMPORTER_IMPORTER_HOST_H_
-
-#include "base/basictypes.h"
-#include "base/callback.h"
-#include "base/compiler_specific.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "chrome/browser/bookmarks/base_bookmark_model_observer.h"
-#include "chrome/browser/importer/importer_data_types.h"
-#include "chrome/browser/importer/profile_writer.h"
-#include "chrome/browser/ui/browser_list_observer.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
-#include "ui/gfx/native_widget_types.h"
-
-class FirefoxProfileLock;
-class Importer;
-class Profile;
-
-namespace importer {
-class ImporterProgressObserver;
-}
-
-// This class hosts the importers. It enumerates profiles from other
-// browsers dynamically, and controls the process of importing. When
-// the import process is done, ImporterHost deletes itself.
-class ImporterHost : public BaseBookmarkModelObserver,
-                     public content::NotificationObserver,
-                     public chrome::BrowserListObserver {
- public:
-  ImporterHost();
-
-  void SetObserver(importer::ImporterProgressObserver* observer);
-
-  // A series of functions invoked at the start, during and end of the import
-  // process. The middle functions are notifications that the a harvesting of a
-  // particular source of data (specified by |item|) is under way.
-  void NotifyImportStarted();
-  void NotifyImportItemStarted(importer::ImportItem item);
-  void NotifyImportItemEnded(importer::ImportItem item);
-  void NotifyImportEnded();
-
-  // When in headless mode, the importer will not show any warning dialog if
-  // a user action is required (e.g., Firefox profile is locked and user should
-  // close Firefox to continue) and the outcome is as if the user had canceled
-  // the import operation.
-  void set_headless() { headless_ = true; }
-  bool is_headless() const { return headless_; }
-
-  void set_parent_window(gfx::NativeWindow parent_window) {
-    parent_window_ = parent_window;
-  }
-
-  void set_browser(Browser* browser) { browser_ = browser; }
-
-  // Starts the process of importing the settings and data depending on what the
-  // user selected.
-  // |source_profile| - importer profile to import.
-  // |target_profile| - profile to import into.
-  // |items| - specifies which data to import (bitmask of importer::ImportItem).
-  // |writer| - called to actually write data back to the profile.
-  virtual void StartImportSettings(
-      const importer::SourceProfile& source_profile,
-      Profile* target_profile,
-      uint16 items,
-      ProfileWriter* writer);
-
- protected:
-  virtual ~ImporterHost();
-
-  // ShowWarningDialog() asks user to close the application that is owning the
-  // lock. They can retry or skip the importing process.
-  // This method should not be called if the importer is in headless mode.
-  void ShowWarningDialog();
-
-  // This is called when when user ends the lock dialog by clicking on either
-  // the "Skip" or "Continue" buttons. |is_continue| is true when user clicked
-  // the "Continue" button.
-  void OnImportLockDialogEnd(bool is_continue);
-
-  // Make sure that Firefox isn't running, if import browser is Firefox. Show
-  // to the user a dialog that notifies that is necessary to close Firefox
-  // prior to continue.
-  // |source_profile| - importer profile to import.
-  // Returns false iff import should be aborted.
-  bool CheckForFirefoxLock(const importer::SourceProfile& source_profile);
-
-  // Make sure BookmarkModel and TemplateURLService are loaded before import
-  // process starts, if bookmarks and/or search engines are among the items
-  // which are to be imported.
-  void CheckForLoadedModels(uint16 items);
-
-  // Vends weak pointers for the importer to call us back.
-  base::WeakPtrFactory<ImporterHost> weak_ptr_factory_;
-
-  // Profile we're importing from.
-  Profile* profile_;
-
-  // True if we're waiting for the model to finish loading.
-  bool waiting_for_bookmarkbar_model_;
-
-  // Have we installed a listener on the bookmark model?
-  bool installed_bookmark_observer_;
-
-  // True if source profile is readable.
-  bool is_source_readable_;
-
-  // Receives notification when the TemplateURLService has loaded.
-  content::NotificationRegistrar registrar_;
-
-  // Writes data from the importer back to the profile.
-  scoped_refptr<ProfileWriter> writer_;
-
- private:
-  friend class base::RefCountedThreadSafe<ImporterHost>;
-
-  // Launches the thread that starts the import task, unless bookmark or
-  // template model are not yet loaded. If load is not detected, this method
-  // will be called when the loading observer sees that model loading is
-  // complete.
-  virtual void InvokeTaskIfDone();
-
-  // Called when IsGoogleGAIACookieInstalled is done.
-  void OnGoogleGAIACookieChecked(bool result);
-
-  // BaseBookmarkModelObserver:
-  virtual void Loaded(BookmarkModel* model, bool ids_reassigned) OVERRIDE;
-  virtual void BookmarkModelBeingDeleted(BookmarkModel* model) OVERRIDE;
-  virtual void BookmarkModelChanged() OVERRIDE;
-
-  // content::NotificationObserver:
-  // Called when TemplateURLService has been loaded.
-  virtual void Observe(int type,
-                       const content::NotificationSource& source,
-                       const content::NotificationDetails& details) OVERRIDE;
-
-  // chrome::BrowserListObserver
-  virtual void OnBrowserRemoved(Browser* browser) OVERRIDE;
-
-  // The task is the process of importing settings from other browsers.
-  base::Closure task_;
-
-  // The importer used in the task.
-  scoped_refptr<Importer> importer_;
-
-  // True if UI is not to be shown.
-  bool headless_;
-
-  // Parent window that we pass to the import lock dialog (i.e, the Firefox
-  // warning dialog).
-  gfx::NativeWindow parent_window_;
-
-  // Used to add a new tab if we need the user to sign in.
-  Browser* browser_;
-
-  // The observer that we need to notify about changes in the import process.
-  importer::ImporterProgressObserver* observer_;
-
-  // Firefox profile lock.
-  scoped_ptr<FirefoxProfileLock> firefox_lock_;
-
-  DISALLOW_COPY_AND_ASSIGN(ImporterHost);
-};
-
-#endif  // CHROME_BROWSER_IMPORTER_IMPORTER_HOST_H_
diff --git a/chrome/browser/importer/importer_list.cc b/chrome/browser/importer/importer_list.cc
index 04fddc9..7c9df71 100644
--- a/chrome/browser/importer/importer_list.cc
+++ b/chrome/browser/importer/importer_list.cc
@@ -5,12 +5,11 @@
 #include "chrome/browser/importer/importer_list.h"
 
 #include "base/bind.h"
-#include "chrome/browser/first_run/first_run.h"
 #include "chrome/browser/importer/firefox_importer_utils.h"
 #include "chrome/browser/importer/importer_bridge.h"
-#include "chrome/browser/importer/importer_data_types.h"
 #include "chrome/browser/importer/importer_list_observer.h"
 #include "chrome/browser/shell_integration.h"
+#include "chrome/common/importer/importer_data_types.h"
 #include "grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
 
@@ -55,7 +54,11 @@
 }
 #endif  // defined(OS_MACOSX)
 
-void DetectFirefoxProfiles(std::vector<importer::SourceProfile*>* profiles) {
+// |locale|: The application locale used for lookups in Firefox's
+// locale-specific search engines feature (see firefox3_importer.cc for
+// details).
+void DetectFirefoxProfiles(const std::string locale,
+                           std::vector<importer::SourceProfile*>* profiles) {
   base::FilePath profile_path = GetFirefoxProfilePath();
   if (profile_path.empty())
     return;
@@ -88,40 +91,21 @@
     firefox->app_path = app_path;
   firefox->services_supported = importer::HISTORY | importer::FAVORITES |
       importer::PASSWORDS | importer::SEARCH_ENGINES;
+  firefox->locale = locale;
   profiles->push_back(firefox);
 }
 
-#if defined(OS_WIN)
-void DetectGoogleToolbarProfiles(
-    std::vector<importer::SourceProfile*>* profiles,
-    scoped_refptr<net::URLRequestContextGetter> request_context_getter) {
-  if (first_run::IsChromeFirstRun())
-    return;
-
-  importer::SourceProfile* google_toolbar = new importer::SourceProfile;
-  google_toolbar->importer_name =
-      l10n_util::GetStringUTF16(IDS_IMPORT_FROM_GOOGLE_TOOLBAR);
-  google_toolbar->importer_type = importer::TYPE_GOOGLE_TOOLBAR5;
-  google_toolbar->source_path.clear();
-  google_toolbar->app_path.clear();
-  google_toolbar->services_supported = importer::FAVORITES;
-  google_toolbar->request_context_getter = request_context_getter;
-  profiles->push_back(google_toolbar);
-}
-#endif
-
 }  // namespace
 
-ImporterList::ImporterList(
-    net::URLRequestContextGetter* request_context_getter)
+ImporterList::ImporterList()
     : source_thread_id_(BrowserThread::UI),
       observer_(NULL),
       is_observed_(false),
       source_profiles_loaded_(false) {
- request_context_getter_ = make_scoped_refptr(request_context_getter);
 }
 
 void ImporterList::DetectSourceProfiles(
+    const std::string& locale,
     importer::ImporterListObserver* observer) {
   DCHECK(observer);
   observer_ = observer;
@@ -133,15 +117,11 @@
   BrowserThread::PostTask(
       BrowserThread::FILE,
       FROM_HERE,
-      base::Bind(&ImporterList::DetectSourceProfilesWorker, this));
+      base::Bind(&ImporterList::DetectSourceProfilesWorker, this, locale));
 }
 
-void ImporterList::SetObserver(importer::ImporterListObserver* observer) {
-  observer_ = observer;
-}
-
-void ImporterList::DetectSourceProfilesHack() {
-  DetectSourceProfilesWorker();
+void ImporterList::DetectSourceProfilesHack(const std::string& locale) {
+  DetectSourceProfilesWorker(locale);
 }
 
 const importer::SourceProfile& ImporterList::GetSourceProfileAt(
@@ -166,7 +146,7 @@
 ImporterList::~ImporterList() {
 }
 
-void ImporterList::DetectSourceProfilesWorker() {
+void ImporterList::DetectSourceProfilesWorker(const std::string& locale) {
   // TODO(jhawkins): Remove this condition once DetectSourceProfilesHack is
   // removed.
   if (is_observed_)
@@ -178,24 +158,22 @@
   // profile detected, which should be the user's current default.
 #if defined(OS_WIN)
   if (ShellIntegration::IsFirefoxDefaultBrowser()) {
-    DetectFirefoxProfiles(&profiles);
+    DetectFirefoxProfiles(locale, &profiles);
     DetectIEProfiles(&profiles);
   } else {
     DetectIEProfiles(&profiles);
-    DetectFirefoxProfiles(&profiles);
+    DetectFirefoxProfiles(locale, &profiles);
   }
-  // TODO(brg) : Current UI requires win_util.
-  DetectGoogleToolbarProfiles(&profiles, request_context_getter_);
 #elif defined(OS_MACOSX)
   if (ShellIntegration::IsFirefoxDefaultBrowser()) {
-    DetectFirefoxProfiles(&profiles);
+    DetectFirefoxProfiles(locale, &profiles);
     DetectSafariProfiles(&profiles);
   } else {
     DetectSafariProfiles(&profiles);
-    DetectFirefoxProfiles(&profiles);
+    DetectFirefoxProfiles(locale, &profiles);
   }
 #else
-  DetectFirefoxProfiles(&profiles);
+  DetectFirefoxProfiles(locale, &profiles);
 #endif
 
   // TODO(jhawkins): Remove this condition once DetectSourceProfilesHack is
diff --git a/chrome/browser/importer/importer_list.h b/chrome/browser/importer/importer_list.h
index b31e82d..9a18a82 100644
--- a/chrome/browser/importer/importer_list.h
+++ b/chrome/browser/importer/importer_list.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_IMPORTER_IMPORTER_LIST_H_
 #define CHROME_BROWSER_IMPORTER_IMPORTER_LIST_H_
 
+#include <string>
 #include <vector>
 
 #include "base/basictypes.h"
@@ -12,7 +13,6 @@
 #include "base/memory/scoped_vector.h"
 #include "base/strings/string16.h"
 #include "content/public/browser/browser_thread.h"
-#include "net/url_request/url_request_context_getter.h"
 
 namespace importer {
 class ImporterListObserver;
@@ -21,22 +21,27 @@
 
 class ImporterList : public base::RefCountedThreadSafe<ImporterList> {
  public:
-  explicit ImporterList(net::URLRequestContextGetter* request_context_getter);
+  ImporterList();
 
   // Detects the installed browsers and their associated profiles, then stores
   // their information in a list. It returns the list of description of all
   // profiles. Calls into DetectSourceProfilesWorker() on the FILE thread to do
   // the real work of detecting source profiles. |observer| must be non-NULL.
-  void DetectSourceProfiles(importer::ImporterListObserver* observer);
+  // |locale|: As in DetectSourceProfilesWorker().
+  void DetectSourceProfiles(const std::string& locale,
+                            importer::ImporterListObserver* observer);
 
   // Sets the observer of this object. When the current observer is destroyed,
   // this method should be called with a NULL |observer| so it is not notified
   // after destruction.
-  void SetObserver(importer::ImporterListObserver* observer);
+  void set_observer(importer::ImporterListObserver* observer) {
+    observer_ = observer;
+  }
 
   // DEPRECATED: This method is synchronous and performs file operations which
   // may end up blocking the current thread, which is usually the UI thread.
-  void DetectSourceProfilesHack();
+  // |locale|: As in DetectSourceProfilesWorker().
+  void DetectSourceProfilesHack(const std::string& locale);
 
   // Returns the number of different source profiles you can import from.
   size_t count() const { return source_profiles_.size(); }
@@ -59,8 +64,10 @@
   ~ImporterList();
 
   // The worker method for DetectSourceProfiles(). Must be called on the FILE
-  // thread.
-  void DetectSourceProfilesWorker();
+  // thread. |locale|:The application locale (it must be taken as an argument
+  // since this code runs on the FILE thread where GetApplicationLocale() isn't
+  // available).
+  void DetectSourceProfilesWorker(const std::string& locale);
 
   // Called by DetectSourceProfilesWorker() on the source thread. This method
   // notifies |observer_| that the source profiles are loaded. |profiles| is
@@ -71,9 +78,6 @@
   // The list of profiles with the default one first.
   ScopedVector<importer::SourceProfile> source_profiles_;
 
-  // Needed for Google Toolbar Import to connect to Toolbar server.
-  scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
-
   // The ID of the thread DetectSourceProfiles() is called on. Only valid after
   // DetectSourceProfiles() is called and until SourceProfilesLoaded() has
   // returned.
diff --git a/chrome/browser/importer/importer_progress_observer.h b/chrome/browser/importer/importer_progress_observer.h
index 92bca81..b033af8 100644
--- a/chrome/browser/importer/importer_progress_observer.h
+++ b/chrome/browser/importer/importer_progress_observer.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_IMPORTER_IMPORTER_PROGRESS_OBSERVER_H_
 #define CHROME_BROWSER_IMPORTER_IMPORTER_PROGRESS_OBSERVER_H_
 
-#include "chrome/browser/importer/importer_data_types.h"
+#include "chrome/common/importer/importer_data_types.h"
 
 namespace importer {
 
diff --git a/chrome/browser/importer/importer_type.cc b/chrome/browser/importer/importer_type.cc
deleted file mode 100644
index 59e5123..0000000
--- a/chrome/browser/importer/importer_type.cc
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/importer/importer_type.h"
-
-#include "base/logging.h"
-#include "base/metrics/histogram.h"
-#include "chrome/browser/importer/bookmarks_file_importer.h"
-#include "chrome/browser/importer/firefox3_importer.h"
-#include "chrome/browser/importer/toolbar_importer.h"
-
-#if defined(OS_WIN)
-#include "chrome/browser/importer/ie_importer.h"
-#endif
-
-#if defined(OS_MACOSX)
-#include <CoreFoundation/CoreFoundation.h>
-#include "base/mac/foundation_util.h"
-#include "chrome/browser/importer/safari_importer.h"
-#endif
-
-namespace importer {
-
-namespace {
-
-// The enum used to register importer use.
-enum ImporterTypeMetrics {
-  IMPORTER_METRICS_UNKNOWN         = 0,
-#if defined(OS_WIN)
-  IMPORTER_METRICS_IE              = 1,
-#endif
-  IMPORTER_METRICS_FIREFOX2        = 2,  // obsolete
-  IMPORTER_METRICS_FIREFOX3        = 3,
-#if defined(OS_MACOSX)
-  IMPORTER_METRICS_SAFARI          = 4,
-#endif
-  IMPORTER_METRICS_GOOGLE_TOOLBAR5 = 5,
-  IMPORTER_METRICS_BOOKMARKS_FILE  = 6,
-
-  // Insert new values here. Never remove any existing values, as this enum is
-  // used to bucket a UMA histogram, and removing values breaks that.
-  IMPORTER_METRICS_SIZE
-};
-
-
-}  // namespace
-
-Importer* CreateImporterByType(ImporterType type) {
-  switch (type) {
-#if defined(OS_WIN)
-    case TYPE_IE:
-      return new IEImporter();
-#endif
-    case TYPE_BOOKMARKS_FILE:
-      return new BookmarksFileImporter();
-    case TYPE_FIREFOX3:
-      return new Firefox3Importer();
-#if defined(OS_MACOSX)
-    case TYPE_SAFARI:
-      return new SafariImporter(base::mac::GetUserLibraryPath());
-#endif
-    case TYPE_GOOGLE_TOOLBAR5:
-      return new Toolbar5Importer();
-    default:
-      NOTREACHED();
-      return NULL;
-  }
-  NOTREACHED();
-  return NULL;
-}
-
-void LogImporterUseToMetrics(const std::string& metric_postfix,
-                             ImporterType type) {
-  ImporterTypeMetrics metrics_type = IMPORTER_METRICS_UNKNOWN;
-  switch (type) {
-    case TYPE_UNKNOWN:
-      metrics_type = IMPORTER_METRICS_UNKNOWN;
-      break;
-#if defined(OS_WIN)
-    case TYPE_IE:
-      metrics_type = IMPORTER_METRICS_IE;
-      break;
-#endif
-    case TYPE_FIREFOX3:
-      metrics_type = IMPORTER_METRICS_FIREFOX3;
-      break;
-#if defined(OS_MACOSX)
-    case TYPE_SAFARI:
-      metrics_type = IMPORTER_METRICS_SAFARI;
-      break;
-#endif
-    case TYPE_GOOGLE_TOOLBAR5:
-      metrics_type = IMPORTER_METRICS_GOOGLE_TOOLBAR5;
-      break;
-    case TYPE_BOOKMARKS_FILE:
-      metrics_type = IMPORTER_METRICS_BOOKMARKS_FILE;
-      break;
-  }
-
-  // Note: This leaks memory, which is the expected behavior as the factory
-  // creates and owns the histogram.
-  base::HistogramBase* histogram =
-      base::LinearHistogram::FactoryGet(
-          "Import.ImporterType." + metric_postfix,
-          1,
-          IMPORTER_METRICS_SIZE,
-          IMPORTER_METRICS_SIZE + 1,
-          base::HistogramBase::kUmaTargetedHistogramFlag);
-  histogram->Add(metrics_type);
-}
-
-}  // namespace importer
diff --git a/chrome/browser/importer/importer_type.h b/chrome/browser/importer/importer_type.h
deleted file mode 100644
index 6705dd8..0000000
--- a/chrome/browser/importer/importer_type.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_IMPORTER_IMPORTER_TYPE_H_
-#define CHROME_BROWSER_IMPORTER_IMPORTER_TYPE_H_
-
-#include <string>
-
-#include "build/build_config.h"
-
-class Importer;
-
-namespace importer {
-
-// An enumeration of the type of importers that we support to import
-// settings and data from (browsers, google toolbar and a bookmarks html file).
-// NOTE: Numbers added so that data can be reliably cast to ints and passed
-// across IPC.
-enum ImporterType {
-  TYPE_UNKNOWN         = -1,
-#if defined(OS_WIN)
-  TYPE_IE              = 0,
-#endif
-  // Value 1 was the (now deleted) Firefox 2 profile importer.
-  TYPE_FIREFOX3        = 2,
-#if defined(OS_MACOSX)
-  TYPE_SAFARI          = 3,
-#endif
-  TYPE_GOOGLE_TOOLBAR5 = 4,
-  // Identifies a 'bookmarks.html' file.
-  TYPE_BOOKMARKS_FILE  = 5
-};
-
-// Creates an Importer of the specified |type|.
-Importer* CreateImporterByType(ImporterType type);
-
-// Logs to UMA that an Importer of the specified |type| was used. Uses
-// |metric_postfix| to split by entry point. Note: Values passed via
-// |metric_postfix| require a matching "Import.ImporterType.|metric_postfix|"
-// entry in tools/metrics/histograms/histograms.xml.
-void LogImporterUseToMetrics(const std::string& metric_prefix,
-                             ImporterType type);
-
-}  // namespace importer
-
-#endif  // CHROME_BROWSER_IMPORTER_IMPORTER_TYPE_H_
diff --git a/chrome/browser/importer/importer_unittest_utils.cc b/chrome/browser/importer/importer_unittest_utils.cc
index c96cf81..d0ff6eb 100644
--- a/chrome/browser/importer/importer_unittest_utils.cc
+++ b/chrome/browser/importer/importer_unittest_utils.cc
@@ -5,7 +5,7 @@
 #include "chrome/browser/importer/importer_unittest_utils.h"
 
 #include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/bookmarks/imported_bookmark_entry.h"
+#include "chrome/common/importer/imported_bookmark_entry.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 void TestEqualBookmarkEntry(const ImportedBookmarkEntry& entry,
diff --git a/chrome/browser/importer/in_process_importer_bridge.cc b/chrome/browser/importer/in_process_importer_bridge.cc
index 6d1dc1d..14c1593 100644
--- a/chrome/browser/importer/in_process_importer_bridge.cc
+++ b/chrome/browser/importer/in_process_importer_bridge.cc
@@ -5,11 +5,15 @@
 #include "chrome/browser/importer/in_process_importer_bridge.h"
 
 #include "base/bind.h"
+#include "base/file_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/bookmarks/imported_bookmark_entry.h"
-#include "chrome/browser/favicon/imported_favicon_usage.h"
-#include "chrome/browser/importer/importer_host.h"
+#include "chrome/browser/importer/external_process_importer_host.h"
 #include "chrome/browser/search_engines/template_url.h"
+#include "chrome/browser/search_engines/template_url_parser.h"
+#include "chrome/browser/search_engines/template_url_prepopulate_data.h"
+#include "chrome/browser/search_engines/template_url_service.h"
+#include "chrome/common/importer/imported_bookmark_entry.h"
+#include "chrome/common/importer/imported_favicon_usage.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/common/password_form.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -20,12 +24,128 @@
 
 #include <iterator>
 
+namespace {
+
+history::URLRows ConvertImporterURLRowsToHistoryURLRows(
+    const std::vector<ImporterURLRow>& rows) {
+  history::URLRows converted;
+  converted.reserve(rows.size());
+  for (std::vector<ImporterURLRow>::const_iterator it = rows.begin();
+       it != rows.end(); ++it) {
+    history::URLRow row(it->url);
+    row.set_title(it->title);
+    row.set_visit_count(it->visit_count);
+    row.set_typed_count(it->typed_count);
+    row.set_last_visit(it->last_visit);
+    row.set_hidden(it->hidden);
+    converted.push_back(row);
+  }
+  return converted;
+}
+
+}  // namespace
+
 using content::BrowserThread;
 
+namespace {
+
+// FirefoxURLParameterFilter is used to remove parameter mentioning Firefox from
+// the search URL when importing search engines.
+class FirefoxURLParameterFilter : public TemplateURLParser::ParameterFilter {
+ public:
+  FirefoxURLParameterFilter() {}
+  virtual ~FirefoxURLParameterFilter() {}
+
+  // TemplateURLParser::ParameterFilter method.
+  virtual bool KeepParameter(const std::string& key,
+                             const std::string& value) OVERRIDE {
+    std::string low_value = StringToLowerASCII(value);
+    if (low_value.find("mozilla") != std::string::npos ||
+        low_value.find("firefox") != std::string::npos ||
+        low_value.find("moz:") != std::string::npos) {
+      return false;
+    }
+    return true;
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(FirefoxURLParameterFilter);
+};
+
+// Creates a TemplateURL with the |keyword| and |url|. |title| may be empty.
+// This function transfers ownership of the created TemplateURL to the caller.
+TemplateURL* CreateTemplateURL(const string16& title,
+                               const string16& keyword,
+                               const GURL& url) {
+  // Skip if the url is invalid.
+  if (!url.is_valid())
+    return NULL;
+
+  TemplateURLData data;
+  if (keyword.empty())
+    data.SetKeyword(TemplateURLService::GenerateKeyword(url));
+  else
+    data.SetKeyword(keyword);
+  // We set short name by using the title if it exists.
+  // Otherwise, we use the shortcut.
+  data.short_name = title.empty() ? keyword : title;
+  data.SetURL(TemplateURLRef::DisplayURLToURLRef(UTF8ToUTF16(url.spec())));
+  return new TemplateURL(NULL, data);
+}
+
+// Parses the OpenSearch XML files in |xml_files| and populates |search_engines|
+// with the resulting TemplateURLs.
+void ParseSearchEnginesFromFirefoxXMLData(
+    const std::vector<std::string>& xml_data,
+    std::vector<TemplateURL*>* search_engines) {
+  DCHECK(search_engines);
+
+  typedef std::map<std::string, TemplateURL*> SearchEnginesMap;
+  SearchEnginesMap search_engine_for_url;
+  std::string content;
+  FirefoxURLParameterFilter param_filter;
+  // The first XML file represents the default search engine in Firefox 3, so we
+  // need to keep it on top of the list.
+  SearchEnginesMap::const_iterator default_turl = search_engine_for_url.end();
+  for (std::vector<std::string>::const_iterator xml_iter =
+           xml_data.begin(); xml_iter != xml_data.end(); ++xml_iter) {
+    TemplateURL* template_url = TemplateURLParser::Parse(NULL, true,
+        xml_iter->data(), xml_iter->length(), &param_filter);
+    if (template_url) {
+      SearchEnginesMap::iterator iter =
+          search_engine_for_url.find(template_url->url());
+      if (iter == search_engine_for_url.end()) {
+        iter = search_engine_for_url.insert(
+            std::make_pair(template_url->url(), template_url)).first;
+      } else {
+        // We have already found a search engine with the same URL.  We give
+        // priority to the latest one found, as GetSearchEnginesXMLFiles()
+        // returns a vector with first Firefox default search engines and then
+        // the user's ones.  We want to give priority to the user ones.
+        delete iter->second;
+        iter->second = template_url;
+      }
+      if (default_turl == search_engine_for_url.end())
+        default_turl = iter;
+    }
+  }
+
+  // Put the results in the |search_engines| vector.
+  for (SearchEnginesMap::iterator t_iter = search_engine_for_url.begin();
+       t_iter != search_engine_for_url.end(); ++t_iter) {
+    if (t_iter == default_turl)
+      search_engines->insert(search_engines->begin(), default_turl->second);
+    else
+      search_engines->push_back(t_iter->second);
+  }
+}
+
+}  // namespace
+
 InProcessImporterBridge::InProcessImporterBridge(
     ProfileWriter* writer,
-    base::WeakPtr<ImporterHost> host) : writer_(writer),
-                                        host_(host) {
+    base::WeakPtr<ExternalProcessImporterHost> host) : writer_(writer),
+                                                       host_(host) {
 }
 
 void InProcessImporterBridge::AddBookmarks(
@@ -60,24 +180,45 @@
 }
 
 void InProcessImporterBridge::SetHistoryItems(
-    const history::URLRows &rows,
+    const std::vector<ImporterURLRow>& rows,
     history::VisitSource visit_source) {
+  history::URLRows converted = ConvertImporterURLRowsToHistoryURLRows(rows);
   BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      base::Bind(&ProfileWriter::AddHistoryPage, writer_, rows, visit_source));
+      BrowserThread::UI,
+      FROM_HERE,
+      base::Bind(
+          &ProfileWriter::AddHistoryPage, writer_, converted, visit_source));
 }
 
 void InProcessImporterBridge::SetKeywords(
-    const std::vector<TemplateURL*>& template_urls,
+    const std::vector<importer::URLKeywordInfo>& url_keywords,
     bool unique_on_host_and_path) {
   ScopedVector<TemplateURL> owned_template_urls;
-  std::copy(template_urls.begin(), template_urls.end(),
-            std::back_inserter(owned_template_urls));
+  for (size_t i = 0; i < url_keywords.size(); ++i) {
+    owned_template_urls.push_back(
+        CreateTemplateURL(url_keywords[i].display_name,
+                          url_keywords[i].keyword,
+                          url_keywords[i].url));
+  }
   BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
       base::Bind(&ProfileWriter::AddKeywords, writer_,
                  base::Passed(&owned_template_urls), unique_on_host_and_path));
 }
 
+void InProcessImporterBridge::SetFirefoxSearchEnginesXMLData(
+    const std::vector<std::string>& search_engine_data) {
+  std::vector<TemplateURL*> search_engines;
+  ParseSearchEnginesFromFirefoxXMLData(search_engine_data, &search_engines);
+
+  ScopedVector<TemplateURL> owned_template_urls;
+  std::copy(search_engines.begin(), search_engines.end(),
+            std::back_inserter(owned_template_urls));
+
+  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+      base::Bind(&ProfileWriter::AddKeywords, writer_,
+                 base::Passed(&owned_template_urls), true));
+}
+
 void InProcessImporterBridge::SetPasswordForm(
     const content::PasswordForm& form) {
   BrowserThread::PostTask(
@@ -88,25 +229,27 @@
 void InProcessImporterBridge::NotifyStarted() {
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
-      base::Bind(&ImporterHost::NotifyImportStarted, host_));
+      base::Bind(&ExternalProcessImporterHost::NotifyImportStarted, host_));
 }
 
 void InProcessImporterBridge::NotifyItemStarted(importer::ImportItem item) {
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
-      base::Bind(&ImporterHost::NotifyImportItemStarted, host_, item));
+      base::Bind(&ExternalProcessImporterHost::NotifyImportItemStarted,
+                 host_, item));
 }
 
 void InProcessImporterBridge::NotifyItemEnded(importer::ImportItem item) {
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
-      base::Bind(&ImporterHost::NotifyImportItemEnded, host_, item));
+      base::Bind(&ExternalProcessImporterHost::NotifyImportItemEnded,
+                 host_, item));
 }
 
 void InProcessImporterBridge::NotifyEnded() {
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
-      base::Bind(&ImporterHost::NotifyImportEnded, host_));
+      base::Bind(&ExternalProcessImporterHost::NotifyImportEnded, host_));
 }
 
 string16 InProcessImporterBridge::GetLocalizedString(int message_id) {
diff --git a/chrome/browser/importer/in_process_importer_bridge.h b/chrome/browser/importer/in_process_importer_bridge.h
index 2b439c4..89786d4 100644
--- a/chrome/browser/importer/in_process_importer_bridge.h
+++ b/chrome/browser/importer/in_process_importer_bridge.h
@@ -18,12 +18,16 @@
 class GURL;
 struct ImportedBookmarkEntry;
 struct ImportedFaviconUsage;
-class ImporterHost;
+class ExternalProcessImporterHost;
+
+namespace importer {
+struct URLKeywordInfo;
+}
 
 class InProcessImporterBridge : public ImporterBridge {
  public:
   InProcessImporterBridge(ProfileWriter* writer,
-                          base::WeakPtr<ImporterHost> host);
+                          base::WeakPtr<ExternalProcessImporterHost> host);
 
   // Begin ImporterBridge implementation:
   virtual void AddBookmarks(
@@ -40,11 +44,15 @@
   virtual void SetFavicons(
       const std::vector<ImportedFaviconUsage>& favicons) OVERRIDE;
 
-  virtual void SetHistoryItems(const history::URLRows& rows,
+  virtual void SetHistoryItems(const std::vector<ImporterURLRow>& rows,
                                history::VisitSource visit_source) OVERRIDE;
 
-  virtual void SetKeywords(const std::vector<TemplateURL*>& template_urls,
-                           bool unique_on_host_and_path) OVERRIDE;
+  virtual void SetKeywords(
+      const std::vector<importer::URLKeywordInfo>& url_keywords,
+      bool unique_on_host_and_path) OVERRIDE;
+
+  virtual void SetFirefoxSearchEnginesXMLData(
+      const std::vector<std::string>& search_engine_data) OVERRIDE;
 
   virtual void SetPasswordForm(
       const content::PasswordForm& form) OVERRIDE;
@@ -61,7 +69,7 @@
   virtual ~InProcessImporterBridge();
 
   ProfileWriter* const writer_;  // weak
-  const base::WeakPtr<ImporterHost> host_;
+  const base::WeakPtr<ExternalProcessImporterHost> host_;
 
   DISALLOW_COPY_AND_ASSIGN(InProcessImporterBridge);
 };
diff --git a/chrome/browser/importer/profile_import_process_messages.cc b/chrome/browser/importer/profile_import_process_messages.cc
deleted file mode 100644
index 68603e4..0000000
--- a/chrome/browser/importer/profile_import_process_messages.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) 2011 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.
-
-// Get basic type definitions.
-#define IPC_MESSAGE_IMPL
-#include "chrome/browser/importer/profile_import_process_messages.h"
-
-// Generate constructors.
-#include "ipc/struct_constructor_macros.h"
-#include "chrome/browser/importer/profile_import_process_messages.h"
-
-// Generate destructors.
-#include "ipc/struct_destructor_macros.h"
-#include "chrome/browser/importer/profile_import_process_messages.h"
-
-// Generate param traits write methods.
-#include "ipc/param_traits_write_macros.h"
-namespace IPC {
-#include "chrome/browser/importer/profile_import_process_messages.h"
-}  // namespace IPC
-
-// Generate param traits read methods.
-#include "ipc/param_traits_read_macros.h"
-namespace IPC {
-#include "chrome/browser/importer/profile_import_process_messages.h"
-}  // namespace IPC
-
-// Generate param traits log methods.
-#include "ipc/param_traits_log_macros.h"
-namespace IPC {
-#include "chrome/browser/importer/profile_import_process_messages.h"
-}  // namespace IPC
diff --git a/chrome/browser/importer/profile_import_process_messages.h b/chrome/browser/importer/profile_import_process_messages.h
deleted file mode 100644
index ba2d1ab..0000000
--- a/chrome/browser/importer/profile_import_process_messages.h
+++ /dev/null
@@ -1,342 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Multiply-included message file, no traditonal include guard.
-#include <string>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/strings/string16.h"
-#include "base/values.h"
-#include "chrome/browser/bookmarks/imported_bookmark_entry.h"
-#include "chrome/browser/favicon/imported_favicon_usage.h"
-#include "chrome/browser/history/history_types.h"
-#include "chrome/browser/importer/importer_data_types.h"
-#include "chrome/browser/search_engines/template_url.h"
-#include "chrome/common/common_param_traits_macros.h"
-#include "content/public/common/common_param_traits.h"
-#include "content/public/common/password_form.h"
-#include "ipc/ipc_message_macros.h"
-#include "ipc/ipc_message_utils.h"
-
-#ifndef CHROME_BROWSER_IMPORTER_PROFILE_IMPORT_PROCESS_MESSAGES_H_
-#define CHROME_BROWSER_IMPORTER_PROFILE_IMPORT_PROCESS_MESSAGES_H_
-
-namespace IPC {
-
-// Traits for importer::SourceProfile struct to pack/unpack.
-template <>
-struct ParamTraits<importer::SourceProfile> {
-  typedef importer::SourceProfile param_type;
-  static void Write(Message* m, const param_type& p) {
-    WriteParam(m, p.importer_name);
-    WriteParam(m, static_cast<int>(p.importer_type));
-    WriteParam(m, p.source_path);
-    WriteParam(m, p.app_path);
-    WriteParam(m, static_cast<int>(p.services_supported));
-  }
-  static bool Read(const Message* m, PickleIterator* iter, param_type* p) {
-    if (!ReadParam(m, iter, &p->importer_name))
-      return false;
-
-    int importer_type = 0;
-    if (!ReadParam(m, iter, &importer_type))
-      return false;
-    p->importer_type = static_cast<importer::ImporterType>(importer_type);
-
-    if (!ReadParam(m, iter, &p->source_path) ||
-        !ReadParam(m, iter, &p->app_path))
-        return false;
-
-    int services_supported = 0;
-    if (!ReadParam(m, iter, &services_supported))
-      return false;
-    p->services_supported = static_cast<uint16>(services_supported);
-
-    return true;
-  }
-  static void Log(const param_type& p, std::string* l) {
-    l->append("(");
-    LogParam(p.importer_name, l);
-    l->append(", ");
-    LogParam(static_cast<int>(p.importer_type), l);
-    l->append(", ");
-    LogParam(p.source_path, l);
-    l->append(", ");
-    LogParam(p.app_path, l);
-    l->append(", ");
-    LogParam(static_cast<int>(p.services_supported), l);
-    l->append(")");
-  }
-};  // ParamTraits<importer::SourceProfile>
-
-// Traits for history::URLRow to pack/unpack.
-template <>
-struct ParamTraits<history::URLRow> {
-  typedef history::URLRow param_type;
-  static void Write(Message* m, const param_type& p) {
-    WriteParam(m, p.id());
-    WriteParam(m, p.url());
-    WriteParam(m, p.title());
-    WriteParam(m, p.visit_count());
-    WriteParam(m, p.typed_count());
-    WriteParam(m, p.last_visit());
-    WriteParam(m, p.hidden());
-  }
-  static bool Read(const Message* m, PickleIterator* iter, param_type* p) {
-    history::URLID id;
-    GURL url;
-    string16 title;
-    int visit_count, typed_count;
-    base::Time last_visit;
-    bool hidden;
-    if (!ReadParam(m, iter, &id) ||
-        !ReadParam(m, iter, &url) ||
-        !ReadParam(m, iter, &title) ||
-        !ReadParam(m, iter, &visit_count) ||
-        !ReadParam(m, iter, &typed_count) ||
-        !ReadParam(m, iter, &last_visit) ||
-        !ReadParam(m, iter, &hidden))
-      return false;
-    *p = history::URLRow(url, id);
-    p->set_title(title);
-    p->set_visit_count(visit_count);
-    p->set_typed_count(typed_count);
-    p->set_last_visit(last_visit);
-    p->set_hidden(hidden);
-    return true;
-  }
-  static void Log(const param_type& p, std::string* l) {
-    l->append("(");
-    LogParam(p.id(), l);
-    l->append(", ");
-    LogParam(p.url(), l);
-    l->append(", ");
-    LogParam(p.title(), l);
-    l->append(", ");
-    LogParam(p.visit_count(), l);
-    l->append(", ");
-    LogParam(p.typed_count(), l);
-    l->append(", ");
-    LogParam(p.last_visit(), l);
-    l->append(", ");
-    LogParam(p.hidden(), l);
-    l->append(")");
-  }
-};  // ParamTraits<history::URLRow>
-
-// Traits for ImportedBookmarkEntry to pack/unpack.
-template <>
-struct ParamTraits<ImportedBookmarkEntry> {
-  typedef ImportedBookmarkEntry param_type;
-  static void Write(Message* m, const param_type& p) {
-    WriteParam(m, p.in_toolbar);
-    WriteParam(m, p.is_folder);
-    WriteParam(m, p.url);
-    WriteParam(m, p.path);
-    WriteParam(m, p.title);
-    WriteParam(m, p.creation_time);
-  }
-  static bool Read(const Message* m, PickleIterator* iter, param_type* p) {
-    return
-        (ReadParam(m, iter, &p->in_toolbar)) &&
-        (ReadParam(m, iter, &p->is_folder)) &&
-        (ReadParam(m, iter, &p->url)) &&
-        (ReadParam(m, iter, &p->path)) &&
-        (ReadParam(m, iter, &p->title)) &&
-        (ReadParam(m, iter, &p->creation_time));
-  }
-  static void Log(const param_type& p, std::string* l) {
-    l->append("(");
-    LogParam(p.in_toolbar, l);
-    l->append(", ");
-    LogParam(p.is_folder, l);
-    l->append(", ");
-    LogParam(p.url, l);
-    l->append(", ");
-    LogParam(p.path, l);
-    l->append(", ");
-    LogParam(p.title, l);
-    l->append(", ");
-    LogParam(p.creation_time, l);
-    l->append(")");
-  }
-};  // ParamTraits<ImportedBookmarkEntry>
-
-// Traits for ImportedFaviconUsage.
-template <>
-struct ParamTraits<ImportedFaviconUsage> {
-  typedef ImportedFaviconUsage param_type;
-  static void Write(Message* m, const param_type& p) {
-    WriteParam(m, p.favicon_url);
-    WriteParam(m, p.png_data);
-    WriteParam(m, p.urls);
-  }
-  static bool Read(const Message* m, PickleIterator* iter, param_type* p) {
-    return
-        ReadParam(m, iter, &p->favicon_url) &&
-        ReadParam(m, iter, &p->png_data) &&
-        ReadParam(m, iter, &p->urls);
-  }
-  static void Log(const param_type& p, std::string* l) {
-    l->append("(");
-    LogParam(p.favicon_url, l);
-    l->append(", ");
-    LogParam(p.png_data, l);
-    l->append(", ");
-    LogParam(p.urls, l);
-    l->append(")");
-  }
-};  // ParamTraits<ImportedFaviconUsage>
-
-// Traits for TemplateURLData
-template <>
-struct ParamTraits<TemplateURLData> {
-  typedef TemplateURLData param_type;
-  static void Write(Message* m, const param_type& p) {
-    WriteParam(m, p.short_name);
-    WriteParam(m, p.keyword());
-    WriteParam(m, p.url());
-    WriteParam(m, p.suggestions_url);
-    WriteParam(m, p.instant_url);
-    WriteParam(m, p.favicon_url);
-    WriteParam(m, p.originating_url);
-    WriteParam(m, p.show_in_default_list);
-    WriteParam(m, p.safe_for_autoreplace);
-    WriteParam(m, p.input_encodings);
-    WriteParam(m, p.id);
-    WriteParam(m, p.date_created);
-    WriteParam(m, p.last_modified);
-    WriteParam(m, p.created_by_policy);
-    WriteParam(m, p.usage_count);
-    WriteParam(m, p.prepopulate_id);
-    WriteParam(m, p.sync_guid);
-  }
-  static bool Read(const Message* m, PickleIterator* iter, param_type* p) {
-    string16 keyword;
-    std::string url;
-    if (!ReadParam(m, iter, &p->short_name) ||
-        !ReadParam(m, iter, &keyword) ||
-        !ReadParam(m, iter, &url) ||
-        !ReadParam(m, iter, &p->suggestions_url) ||
-        !ReadParam(m, iter, &p->instant_url) ||
-        !ReadParam(m, iter, &p->favicon_url) ||
-        !ReadParam(m, iter, &p->originating_url) ||
-        !ReadParam(m, iter, &p->show_in_default_list) ||
-        !ReadParam(m, iter, &p->safe_for_autoreplace) ||
-        !ReadParam(m, iter, &p->input_encodings) ||
-        !ReadParam(m, iter, &p->id) ||
-        !ReadParam(m, iter, &p->date_created) ||
-        !ReadParam(m, iter, &p->last_modified) ||
-        !ReadParam(m, iter, &p->created_by_policy) ||
-        !ReadParam(m, iter, &p->usage_count) ||
-        !ReadParam(m, iter, &p->prepopulate_id) ||
-        !ReadParam(m, iter, &p->sync_guid))
-      return false;
-    p->SetKeyword(keyword);
-    p->SetURL(url);
-    return true;
-  }
-  static void Log(const param_type& p, std::string* l) {
-    l->append("<TemplateURLData>");
-  }
-};
-
-// Traits for TemplateURL*.
-// WARNING: These will cause us to allocate a new TemplateURL on the heap on the
-// receiver side.  Any messages using this type must have handlers that are
-// careful to properly take ownership and avoid leaks!  See warning below on
-// ProfileImportProcessHostMsg_NotifyKeywordsReady.
-template <>
-struct ParamTraits<TemplateURL*> {
-  typedef TemplateURL* param_type;
-  static void Write(Message* m, const param_type& p) {
-    WriteParam(m, p->data());
-  }
-  static bool Read(const Message* m, PickleIterator* iter, param_type* p) {
-    TemplateURLData data;
-    if (!ReadParam(m, iter, &data))
-      return false;
-    // Since we don't have access to a Profile*, just supply NULL.  The caller
-    // can create a new TemplateURL or modify this one (e.g. via
-    // TemplateURLService::AddAndSetProfile()) to correct this later.
-    *p = new TemplateURL(NULL, data);
-    return true;
-  }
-  static void Log(const param_type& p, std::string* l) {
-    l->append("<TemplateURL*>");
-  }
-};
-
-}  // namespace IPC
-
-#endif  // CHROME_BROWSER_IMPORTER_PROFILE_IMPORT_PROCESS_MESSAGES_H_
-
-#define IPC_MESSAGE_START ProfileImportMsgStart
-
-//-----------------------------------------------------------------------------
-// ProfileImportProcess messages
-// These are messages sent from the browser to the profile import process.
-IPC_MESSAGE_CONTROL3(ProfileImportProcessMsg_StartImport,
-                     importer::SourceProfile,
-                     int                     /* Bitmask of items to import. */,
-                     DictionaryValue         /* Localized strings. */)
-
-IPC_MESSAGE_CONTROL0(ProfileImportProcessMsg_CancelImport)
-
-IPC_MESSAGE_CONTROL1(ProfileImportProcessMsg_ReportImportItemFinished,
-                     int  /* ImportItem */)
-
-//---------------------------------------------------------------------------
-// ProfileImportProcessHost messages
-// These are messages sent from the profile import process to the browser.
-// These messages send information about the status of the import and
-// individual import tasks.
-IPC_MESSAGE_CONTROL0(ProfileImportProcessHostMsg_Import_Started)
-
-IPC_MESSAGE_CONTROL2(ProfileImportProcessHostMsg_Import_Finished,
-                     bool         /* was import successful? */,
-                     std::string  /* error message, if any */)
-
-IPC_MESSAGE_CONTROL1(ProfileImportProcessHostMsg_ImportItem_Started,
-                     int  /* ImportItem */)
-
-IPC_MESSAGE_CONTROL1(ProfileImportProcessHostMsg_ImportItem_Finished,
-                     int  /* ImportItem */)
-
-// These messages send data from the external importer process back to
-// the process host so it can be written to the profile.
-IPC_MESSAGE_CONTROL1(ProfileImportProcessHostMsg_NotifyHistoryImportStart,
-                     int  /* total number of history::URLRow items */)
-
-IPC_MESSAGE_CONTROL2(ProfileImportProcessHostMsg_NotifyHistoryImportGroup,
-                     history::URLRows,
-                     int  /* the source of URLs as in history::VisitSource.*/
-                          /* To simplify IPC call, pass as an integer */)
-
-IPC_MESSAGE_CONTROL1(ProfileImportProcessHostMsg_NotifyHomePageImportReady,
-                     GURL  /* GURL of home page */)
-
-IPC_MESSAGE_CONTROL2(ProfileImportProcessHostMsg_NotifyBookmarksImportStart,
-                     string16  /* first folder name */,
-                     int       /* total number of bookmarks */)
-
-IPC_MESSAGE_CONTROL1(ProfileImportProcessHostMsg_NotifyBookmarksImportGroup,
-                     std::vector<ImportedBookmarkEntry>)
-
-IPC_MESSAGE_CONTROL1(ProfileImportProcessHostMsg_NotifyFaviconsImportStart,
-                     int  /* total number of favicons */)
-
-IPC_MESSAGE_CONTROL1(ProfileImportProcessHostMsg_NotifyFaviconsImportGroup,
-                     std::vector<ImportedFaviconUsage>)
-
-IPC_MESSAGE_CONTROL1(ProfileImportProcessHostMsg_NotifyPasswordFormReady,
-                     content::PasswordForm)
-
-// WARNING: The TemplateURL*s in the following message get heap-allocated on the
-// receiving end.  The message handler for this message MUST take ownership of
-// these pointers and ensure they're properly freed!
-IPC_MESSAGE_CONTROL2(ProfileImportProcessHostMsg_NotifyKeywordsReady,
-                     std::vector<TemplateURL*>,
-                     bool  /* unique on host and path */)
diff --git a/chrome/browser/importer/profile_writer.cc b/chrome/browser/importer/profile_writer.cc
index 5430313..ce85351 100644
--- a/chrome/browser/importer/profile_writer.cc
+++ b/chrome/browser/importer/profile_writer.cc
@@ -15,10 +15,8 @@
 #include "base/threading/thread.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
-#include "chrome/browser/bookmarks/imported_bookmark_entry.h"
 #include "chrome/browser/favicon/favicon_service.h"
 #include "chrome/browser/favicon/favicon_service_factory.h"
-#include "chrome/browser/favicon/imported_favicon_usage.h"
 #include "chrome/browser/history/history_service.h"
 #include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/password_manager/password_store.h"
@@ -29,6 +27,8 @@
 #include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/browser/webdata/web_data_service.h"
 #include "chrome/common/chrome_notification_types.h"
+#include "chrome/common/importer/imported_bookmark_entry.h"
+#include "chrome/common/importer/imported_favicon_usage.h"
 #include "chrome/common/pref_names.h"
 
 namespace {
diff --git a/chrome/browser/importer/profile_writer.h b/chrome/browser/importer/profile_writer.h
index cc47044..2d7b6db 100644
--- a/chrome/browser/importer/profile_writer.h
+++ b/chrome/browser/importer/profile_writer.h
@@ -11,10 +11,10 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_vector.h"
 #include "base/strings/string16.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "build/build_config.h"
 #include "chrome/browser/history/history_types.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 struct ImportedBookmarkEntry;
 struct ImportedFaviconUsage;
diff --git a/chrome/browser/importer/profile_writer_unittest.cc b/chrome/browser/importer/profile_writer_unittest.cc
index 072b327..f61b6c8 100644
--- a/chrome/browser/importer/profile_writer_unittest.cc
+++ b/chrome/browser/importer/profile_writer_unittest.cc
@@ -10,11 +10,11 @@
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/browser/bookmarks/bookmark_title_match.h"
 #include "chrome/browser/bookmarks/bookmark_utils.h"
-#include "chrome/browser/bookmarks/imported_bookmark_entry.h"
 #include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/history/history_types.h"
 #include "chrome/browser/importer/importer_unittest_utils.h"
 #include "chrome/browser/importer/profile_writer.h"
+#include "chrome/common/importer/imported_bookmark_entry.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/test/test_browser_thread.h"
diff --git a/chrome/browser/importer/safari_importer.h b/chrome/browser/importer/safari_importer.h
index cc7d721..fd83083 100644
--- a/chrome/browser/importer/safari_importer.h
+++ b/chrome/browser/importer/safari_importer.h
@@ -15,6 +15,7 @@
 #include "base/gtest_prod_util.h"
 #include "chrome/browser/history/history_types.h"
 #include "chrome/browser/importer/importer.h"
+#include "chrome/common/importer/importer_url_row.h"
 
 #if __OBJC__
 @class NSDictionary;
@@ -93,7 +94,7 @@
   double HistoryTimeToEpochTime(NSString* history_time);
 
   // Parses Safari's history and loads it into the input array.
-  void ParseHistoryItems(history::URLRows* history_items);
+  void ParseHistoryItems(std::vector<ImporterURLRow>* history_items);
 
   // Opens the favicon database file.
   bool OpenDatabase(sql::Connection* db);
diff --git a/chrome/browser/importer/safari_importer.mm b/chrome/browser/importer/safari_importer.mm
index 422cc68..4a61298 100644
--- a/chrome/browser/importer/safari_importer.mm
+++ b/chrome/browser/importer/safari_importer.mm
@@ -11,20 +11,19 @@
 
 #include "base/file_util.h"
 #include "base/mac/mac_util.h"
-#include "base/memory/scoped_nsobject.h"
 #include "base/strings/string16.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
-#include "chrome/browser/bookmarks/imported_bookmark_entry.h"
+#include "base/time/time.h"
 #include "chrome/browser/favicon/favicon_util.h"
-#include "chrome/browser/favicon/imported_favicon_usage.h"
 #include "chrome/browser/importer/importer_bridge.h"
+#include "chrome/common/importer/imported_bookmark_entry.h"
+#include "chrome/common/importer/imported_favicon_usage.h"
 #include "chrome/common/url_constants.h"
-#include "googleurl/src/gurl.h"
 #include "grit/generated_resources.h"
 #include "net/base/data_url.h"
 #include "sql/statement.h"
+#include "url/gurl.h"
 
 namespace {
 
@@ -319,7 +318,7 @@
 }
 
 void SafariImporter::ImportHistory() {
-  history::URLRows rows;
+  std::vector<ImporterURLRow> rows;
   ParseHistoryItems(&rows);
 
   if (!rows.empty() && !cancelled()) {
@@ -336,7 +335,8 @@
       kCFAbsoluteTimeIntervalSince1970;
 }
 
-void SafariImporter::ParseHistoryItems(history::URLRows* history_items) {
+void SafariImporter::ParseHistoryItems(
+    std::vector<ImporterURLRow>* history_items) {
   DCHECK(history_items);
 
   // Construct ~/Library/Safari/History.plist path
@@ -366,7 +366,7 @@
     if (!CanImportSafariURL(url))
       continue;
 
-    history::URLRow row(url);
+    ImporterURLRow row(url);
     NSString* title_ns = [history_item objectForKey:@"title"];
 
     // Sometimes items don't have a title, in which case we just substitue
@@ -374,14 +374,14 @@
     if (!title_ns)
       title_ns = url_ns;
 
-    row.set_title(base::SysNSStringToUTF16(title_ns));
+    row.title = base::SysNSStringToUTF16(title_ns);
     int visit_count = [[history_item objectForKey:@"visitCount"]
                           intValue];
-    row.set_visit_count(visit_count);
+    row.visit_count = visit_count;
     // Include imported URLs in autocompletion - don't hide them.
-    row.set_hidden(0);
+    row.hidden = 0;
     // Item was never typed before in the omnibox.
-    row.set_typed_count(0);
+    row.typed_count = 0;
 
     NSString* last_visit_str = [history_item objectForKey:@"lastVisitedDate"];
     // The last visit time should always be in the history item, but if not
@@ -392,7 +392,7 @@
 
     // Convert Safari's last visit time to Unix Epoch time.
     double seconds_since_unix_epoch = HistoryTimeToEpochTime(last_visit_str);
-    row.set_last_visit(base::Time::FromDoubleT(seconds_since_unix_epoch));
+    row.last_visit = base::Time::FromDoubleT(seconds_since_unix_epoch);
 
     history_items->push_back(row);
   }
diff --git a/chrome/browser/importer/safari_importer_unittest.mm b/chrome/browser/importer/safari_importer_unittest.mm
index 6725b75..93e110c 100644
--- a/chrome/browser/importer/safari_importer_unittest.mm
+++ b/chrome/browser/importer/safari_importer_unittest.mm
@@ -13,10 +13,10 @@
 #include "base/strings/string_util.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/bookmarks/imported_bookmark_entry.h"
-#include "chrome/browser/favicon/imported_favicon_usage.h"
 #include "chrome/browser/importer/importer_bridge.h"
 #include "chrome/common/chrome_paths.h"
+#include "chrome/common/importer/imported_bookmark_entry.h"
+#include "chrome/common/importer/imported_favicon_usage.h"
 #include "sql/connection.h"
 #include "testing/platform_test.h"
 
@@ -47,30 +47,30 @@
 TEST_F(SafariImporterTest, HistoryImport) {
   scoped_refptr<SafariImporter> importer(GetSafariImporter());
 
-  history::URLRows history_items;
+  std::vector<ImporterURLRow> history_items;
   importer->ParseHistoryItems(&history_items);
 
   // Should be 2 history items.
   ASSERT_EQ(history_items.size(), 2U);
 
-  history::URLRow& it1 = history_items[0];
-  EXPECT_EQ(it1.url(), GURL("http://www.firsthistoryitem.com/"));
-  EXPECT_EQ(it1.title(), UTF8ToUTF16("First History Item Title"));
-  EXPECT_EQ(it1.visit_count(), 1);
-  EXPECT_EQ(it1.hidden(), 0);
-  EXPECT_EQ(it1.typed_count(), 0);
-  EXPECT_EQ(it1.last_visit().ToDoubleT(),
+  ImporterURLRow& it1 = history_items[0];
+  EXPECT_EQ(it1.url, GURL("http://www.firsthistoryitem.com/"));
+  EXPECT_EQ(it1.title, UTF8ToUTF16("First History Item Title"));
+  EXPECT_EQ(it1.visit_count, 1);
+  EXPECT_EQ(it1.hidden, 0);
+  EXPECT_EQ(it1.typed_count, 0);
+  EXPECT_EQ(it1.last_visit.ToDoubleT(),
       importer->HistoryTimeToEpochTime(@"270598264.4"));
 
-  history::URLRow& it2 = history_items[1];
+  ImporterURLRow& it2 = history_items[1];
   std::string second_item_title("http://www.secondhistoryitem.com/");
-  EXPECT_EQ(it2.url(), GURL(second_item_title));
+  EXPECT_EQ(it2.url, GURL(second_item_title));
   // The second item lacks a title so we expect the URL to be substituted.
-  EXPECT_EQ(UTF16ToUTF8(it2.title()), second_item_title.c_str());
-  EXPECT_EQ(it2.visit_count(), 55);
-  EXPECT_EQ(it2.hidden(), 0);
-  EXPECT_EQ(it2.typed_count(), 0);
-  EXPECT_EQ(it2.last_visit().ToDoubleT(),
+  EXPECT_EQ(UTF16ToUTF8(it2.title), second_item_title.c_str());
+  EXPECT_EQ(it2.visit_count, 55);
+  EXPECT_EQ(it2.hidden, 0);
+  EXPECT_EQ(it2.typed_count, 0);
+  EXPECT_EQ(it2.last_visit.ToDoubleT(),
       importer->HistoryTimeToEpochTime(@"270598231.4"));
 }
 
diff --git a/chrome/browser/importer/toolbar_importer.cc b/chrome/browser/importer/toolbar_importer.cc
deleted file mode 100644
index dea1d61..0000000
--- a/chrome/browser/importer/toolbar_importer.cc
+++ /dev/null
@@ -1,573 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/importer/toolbar_importer.h"
-
-#include <limits>
-
-#include "base/bind.h"
-#include "base/rand_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_split.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/bookmarks/imported_bookmark_entry.h"
-#include "chrome/browser/first_run/first_run.h"
-#include "chrome/browser/importer/importer_bridge.h"
-#include "chrome/browser/importer/importer_data_types.h"
-#include "chrome/browser/profiles/profile.h"
-#include "content/public/browser/browser_thread.h"
-#include "grit/generated_resources.h"
-#include "net/base/load_flags.h"
-#include "net/url_request/url_fetcher.h"
-#include "third_party/libxml/chromium/libxml_utils.h"
-
-using content::BrowserThread;
-
-// Toolbar5Importer
-const char Toolbar5Importer::kXmlApiReplyXmlTag[] = "xml_api_reply";
-const char Toolbar5Importer::kBookmarksXmlTag[] = "bookmarks";
-const char Toolbar5Importer::kBookmarkXmlTag[] = "bookmark";
-const char Toolbar5Importer::kTitleXmlTag[] = "title";
-const char Toolbar5Importer::kUrlXmlTag[] = "url";
-const char Toolbar5Importer::kTimestampXmlTag[] = "timestamp";
-const char Toolbar5Importer::kLabelsXmlTag[] = "labels";
-const char Toolbar5Importer::kLabelsXmlCloseTag[] = "/labels";
-const char Toolbar5Importer::kLabelXmlTag[] = "label";
-const char Toolbar5Importer::kAttributesXmlTag[] = "attributes";
-
-const char Toolbar5Importer::kRandomNumberToken[] = "{random_number}";
-const char Toolbar5Importer::kAuthorizationToken[] = "{auth_token}";
-const char Toolbar5Importer::kAuthorizationTokenPrefix[] = "/*";
-const char Toolbar5Importer::kAuthorizationTokenSuffix[] = "*/";
-const char Toolbar5Importer::kMaxNumToken[] = "{max_num}";
-const char Toolbar5Importer::kMaxTimestampToken[] = "{max_timestamp}";
-
-const char Toolbar5Importer::kT5AuthorizationTokenUrl[] =
-    "http://www.google.com/notebook/token?zx={random_number}";
-const char Toolbar5Importer::kT5FrontEndUrlTemplate[] =
-    "http://www.google.com/notebook/toolbar?cmd=list&tok={auth_token}&"
-    "num={max_num}&min={max_timestamp}&all=0&zx={random_number}";
-
-// Importer methods.
-
-// The constructor should set the initial state to NOT_USED.
-Toolbar5Importer::Toolbar5Importer()
-    : state_(NOT_USED),
-      items_to_import_(importer::NONE),
-      token_fetcher_(NULL),
-      data_fetcher_(NULL) {
-}
-
-// The destructor insures that the fetchers are currently not being used, as
-// their thread-safe implementation requires that they are cancelled from the
-// thread in which they were constructed.
-Toolbar5Importer::~Toolbar5Importer() {
-  DCHECK(!token_fetcher_);
-  DCHECK(!data_fetcher_);
-}
-
-void Toolbar5Importer::StartImport(
-    const importer::SourceProfile& source_profile,
-    uint16 items,
-    ImporterBridge* bridge) {
-  DCHECK(bridge);
-
-  bridge_ = bridge;
-  items_to_import_ = items;
-  DCHECK(source_profile.request_context_getter.get());
-  request_context_getter_ = source_profile.request_context_getter;
-  state_ = INITIALIZED;
-
-  bridge_->NotifyStarted();
-  ContinueImport();
-}
-
-// The public cancel method serves two functions, as a callback from the UI
-// as well as an internal callback in case of cancel.  An internal callback
-// is required since the URLFetcher must be destroyed from the thread it was
-// created.
-void Toolbar5Importer::Cancel() {
-  // In the case when the thread is not importing messages we are to
-  // cancel as soon as possible.
-  Importer::Cancel();
-
-  // If we are conducting network operations, post a message to the importer
-  // thread for synchronization.
-  if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
-    EndImport();
-  } else {
-    BrowserThread::PostTask(
-        BrowserThread::UI, FROM_HERE,
-        base::Bind(&Toolbar5Importer::Cancel, this));
-  }
-}
-
-void Toolbar5Importer::OnURLFetchComplete(const net::URLFetcher* source) {
-  if (cancelled()) {
-    EndImport();
-    return;
-  }
-
-  if (200 != source->GetResponseCode()) {  // HTTP/Ok
-    // Cancelling here will update the UI and bypass the rest of bookmark
-    // import.
-    EndImportBookmarks();
-    return;
-  }
-
-  std::string data;
-  source->GetResponseAsString(&data);
-  switch (state_) {
-    case GET_AUTHORIZATION_TOKEN:
-      GetBookmarkDataFromServer(data);
-      break;
-    case GET_BOOKMARKS:
-      GetBookmarksFromServerDataResponse(data);
-      break;
-    default:
-      NOTREACHED() << "Invalid state.";
-      EndImportBookmarks();
-      break;
-  }
-}
-
-void Toolbar5Importer::ContinueImport() {
-  DCHECK((items_to_import_ == importer::FAVORITES) ||
-         (items_to_import_ == importer::NONE)) <<
-      "The items requested are not supported";
-
-  // The order here is important.  Each Begin... will clear the flag
-  // of its item before its task finishes and re-enters this method.
-  if (importer::NONE == items_to_import_) {
-    EndImport();
-    return;
-  }
-  if ((items_to_import_ & importer::FAVORITES) && !cancelled()) {
-    items_to_import_ &= ~importer::FAVORITES;
-    BeginImportBookmarks();
-    return;
-  }
-  // TODO(brg): Import history, autocomplete, other toolbar information
-  // in a future release.
-
-  // This code should not be reached, but gracefully handles the possibility
-  // that StartImport was called with unsupported items_to_import.
-  if (!cancelled())
-    EndImport();
-}
-
-void Toolbar5Importer::EndImport() {
-  if (state_ != DONE) {
-    state_ = DONE;
-    // By spec the fetchers must be destroyed within the same
-    // thread they are created.  The importer is destroyed in the ui_thread
-    // so when we complete in the file_thread we destroy them first.
-    if (NULL != token_fetcher_) {
-      delete token_fetcher_;
-      token_fetcher_ = NULL;
-    }
-
-    if (NULL != data_fetcher_) {
-      delete data_fetcher_;
-      data_fetcher_ = NULL;
-    }
-
-    if (bridge_.get())
-      bridge_->NotifyEnded();
-  }
-}
-
-void Toolbar5Importer::BeginImportBookmarks() {
-  bridge_->NotifyItemStarted(importer::FAVORITES);
-  GetAuthenticationFromServer();
-}
-
-void Toolbar5Importer::EndImportBookmarks() {
-  bridge_->NotifyItemEnded(importer::FAVORITES);
-  ContinueImport();
-}
-
-
-// Notebook front-end connection manager implementation follows.
-void Toolbar5Importer::GetAuthenticationFromServer() {
-  if (cancelled()) {
-    EndImport();
-    return;
-  }
-
-  // Authentication is a token string retrieved from the authentication server
-  // To access it we call the url below with a random number replacing the
-  // value in the string.
-  state_ = GET_AUTHORIZATION_TOKEN;
-
-  // Random number construction.
-  int random = base::RandInt(0, std::numeric_limits<int>::max());
-  std::string random_string = base::UintToString(random);
-
-  // Retrieve authorization token from the network.
-  std::string url_string(kT5AuthorizationTokenUrl);
-  url_string.replace(url_string.find(kRandomNumberToken),
-                     arraysize(kRandomNumberToken) - 1,
-                     random_string);
-  GURL url(url_string);
-
-  // Because the importer is started as the result of a user action which
-  // explicitly requires authentication, sending cookies here is reasonable.
-  token_fetcher_ = net::URLFetcher::Create(
-      url, net::URLFetcher::GET, this);
-  token_fetcher_->SetRequestContext(request_context_getter_.get());
-  token_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES);
-  token_fetcher_->Start();
-}
-
-void Toolbar5Importer::GetBookmarkDataFromServer(const std::string& response) {
-  if (cancelled()) {
-    EndImport();
-    return;
-  }
-
-  state_ = GET_BOOKMARKS;
-
-  // Parse and verify the authorization token from the response.
-  std::string token;
-  if (!ParseAuthenticationTokenResponse(response, &token)) {
-    EndImportBookmarks();
-    return;
-  }
-
-  // Build the Toolbar FE connection string, and call the server for
-  // the xml blob.  We must tag the connection string with a random number.
-  std::string conn_string = kT5FrontEndUrlTemplate;
-  int random = base::RandInt(0, std::numeric_limits<int>::max());
-  std::string random_string = base::UintToString(random);
-  conn_string.replace(conn_string.find(kRandomNumberToken),
-                      arraysize(kRandomNumberToken) - 1,
-                      random_string);
-  conn_string.replace(conn_string.find(kAuthorizationToken),
-                      arraysize(kAuthorizationToken) - 1,
-                      token);
-  GURL url(conn_string);
-
-  // Because the importer is started as the result of a user action which
-  // explicitly requires authentication, sending cookies here is reasonable.
-  data_fetcher_ = net::URLFetcher::Create(
-      url, net::URLFetcher::GET, this);
-  data_fetcher_->SetRequestContext(request_context_getter_.get());
-  data_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES);
-  data_fetcher_->Start();
-}
-
-void Toolbar5Importer::GetBookmarksFromServerDataResponse(
-    const std::string& response) {
-  if (cancelled()) {
-    EndImport();
-    return;
-  }
-
-  state_ = PARSE_BOOKMARKS;
-
-  XmlReader reader;
-  if (reader.Load(response) && !cancelled()) {
-    // Construct Bookmarks
-    std::vector<ImportedBookmarkEntry> bookmarks;
-    if (ParseBookmarksFromReader(&reader, &bookmarks,
-        bridge_->GetLocalizedString(IDS_BOOKMARK_GROUP_FROM_GOOGLE_TOOLBAR)))
-      AddBookmarksToChrome(bookmarks);
-  }
-  EndImportBookmarks();
-}
-
-bool Toolbar5Importer::ParseAuthenticationTokenResponse(
-    const std::string& response,
-    std::string* token) {
-  DCHECK(token);
-
-  *token = response;
-  size_t position = token->find(kAuthorizationTokenPrefix);
-  if (0 != position)
-    return false;
-  token->replace(position, arraysize(kAuthorizationTokenPrefix) - 1, "");
-
-  position = token->find(kAuthorizationTokenSuffix);
-  if (token->size() != (position + (arraysize(kAuthorizationTokenSuffix) - 1)))
-    return false;
-  token->replace(position, arraysize(kAuthorizationTokenSuffix) - 1, "");
-
-  return true;
-}
-
-// Parsing
-bool Toolbar5Importer::ParseBookmarksFromReader(
-    XmlReader* reader,
-    std::vector<ImportedBookmarkEntry>* bookmarks,
-    const string16& bookmark_group_string) {
-  DCHECK(reader);
-  DCHECK(bookmarks);
-
-  // The XML blob returned from the server is described in the
-  // Toolbar-Notebook/Bookmarks Protocol document located at
-  // https://docs.google.com/a/google.com/Doc?docid=cgt3m7dr_24djt62m&hl=en
-  // We are searching for the section with structure
-  // <bookmarks><bookmark>...</bookmark><bookmark>...</bookmark></bookmarks>
-
-  // Locate the |bookmarks| blob.
-  if (!reader->SkipToElement())
-    return false;
-
-  if (!LocateNextTagByName(reader, kBookmarksXmlTag))
-    return false;
-
-  // Parse each |bookmark| blob
-  while (LocateNextTagWithStopByName(reader, kBookmarkXmlTag,
-                                     kBookmarksXmlTag)) {
-    ImportedBookmarkEntry bookmark_entry;
-    std::vector<BookmarkFolderType> folders;
-    if (ExtractBookmarkInformation(reader, &bookmark_entry, &folders,
-                                   bookmark_group_string)) {
-      // For each folder we create a new bookmark entry.  Duplicates will
-      // be detected when we attempt to create the bookmark in the profile.
-      for (std::vector<BookmarkFolderType>::iterator folder = folders.begin();
-          folder != folders.end();
-          ++folder) {
-        bookmark_entry.path = *folder;
-        bookmarks->push_back(bookmark_entry);
-      }
-    }
-  }
-
-  if (0 == bookmarks->size())
-    return false;
-
-  return true;
-}
-
-bool Toolbar5Importer::LocateNextOpenTag(XmlReader* reader) {
-  DCHECK(reader);
-
-  while (!reader->SkipToElement()) {
-    if (!reader->Read())
-      return false;
-  }
-  return true;
-}
-
-bool Toolbar5Importer::LocateNextTagByName(XmlReader* reader,
-                                           const std::string& tag) {
-  DCHECK(reader);
-
-  // Locate the |tag| blob.
-  while (tag != reader->NodeName()) {
-    if (!reader->Read() || !LocateNextOpenTag(reader))
-      return false;
-  }
-  return true;
-}
-
-bool Toolbar5Importer::LocateNextTagWithStopByName(XmlReader* reader,
-                                                   const std::string& tag,
-                                                   const std::string& stop) {
-  DCHECK(reader);
-
-  DCHECK_NE(tag, stop);
-  // Locate the |tag| blob.
-  while (tag != reader->NodeName()) {
-    // Move to the next open tag.
-    if (!reader->Read() || !LocateNextOpenTag(reader))
-      return false;
-    // If we encounter the stop word return false.
-    if (stop == reader->NodeName())
-      return false;
-  }
-  return true;
-}
-
-bool Toolbar5Importer::ExtractBookmarkInformation(
-    XmlReader* reader,
-    ImportedBookmarkEntry* bookmark_entry,
-    std::vector<BookmarkFolderType>* bookmark_folders,
-    const string16& bookmark_group_string) {
-  DCHECK(reader);
-  DCHECK(bookmark_entry);
-  DCHECK(bookmark_folders);
-
-  // The following is a typical bookmark entry.
-  // The reader should be pointing to the <title> tag at the moment.
-  //
-  // <bookmark>
-  // <title>MyTitle</title>
-  // <url>http://www.sohu.com/</url>
-  // <timestamp>1153328691085181</timestamp>
-  // <id>N123nasdf239</id>
-  // <notebook_id>Bxxxxxxx</notebook_id> (for bookmarks, a special id is used)
-  // <section_id>Sxxxxxx</section_id>
-  // <has_highlight>0</has_highlight>
-  // <labels>
-  // <label>China</label>
-  // <label>^k</label> (if this special label is present, the note is deleted)
-  // </labels>
-  // <attributes>
-  // <attribute>
-  // <name>favicon_url</name>
-  // <value>http://www.sohu.com/favicon.ico</value>
-  // </attribute>
-  // <attribute>
-  // <name>favicon_timestamp</name>
-  // <value>1153328653</value>
-  // </attribute>
-  // <attribute>
-  // <name>notebook_name</name>
-  // <value>My notebook 0</value>
-  // </attribute>
-  // <attribute>
-  // <name>section_name</name>
-  // <value>My section 0</value>
-  // </attribute>
-  // </attributes>
-  // </bookmark>
-  //
-  // We parse the blob in order, title->url->timestamp etc.  Any failure
-  // causes us to skip this bookmark.
-
-  if (!ExtractTitleFromXmlReader(reader, bookmark_entry))
-    return false;
-  if (!ExtractUrlFromXmlReader(reader, bookmark_entry))
-    return false;
-  if (!ExtractTimeFromXmlReader(reader, bookmark_entry))
-    return false;
-  if (!ExtractFoldersFromXmlReader(reader, bookmark_folders,
-                                   bookmark_group_string))
-    return false;
-
-  return true;
-}
-
-bool Toolbar5Importer::ExtractNamedValueFromXmlReader(XmlReader* reader,
-                                                      const std::string& name,
-                                                      std::string* buffer) {
-  DCHECK(reader);
-  DCHECK(buffer);
-
-  if (name != reader->NodeName())
-    return false;
-  if (!reader->ReadElementContent(buffer))
-    return false;
-  return true;
-}
-
-bool Toolbar5Importer::ExtractTitleFromXmlReader(
-    XmlReader* reader,
-    ImportedBookmarkEntry* entry) {
-  DCHECK(reader);
-  DCHECK(entry);
-
-  if (!LocateNextTagWithStopByName(reader, kTitleXmlTag, kUrlXmlTag))
-    return false;
-  std::string buffer;
-  if (!ExtractNamedValueFromXmlReader(reader, kTitleXmlTag, &buffer)) {
-    return false;
-  }
-  entry->title = UTF8ToUTF16(buffer);
-  return true;
-}
-
-bool Toolbar5Importer::ExtractUrlFromXmlReader(
-    XmlReader* reader,
-    ImportedBookmarkEntry* entry) {
-  DCHECK(reader);
-  DCHECK(entry);
-
-  if (!LocateNextTagWithStopByName(reader, kUrlXmlTag, kTimestampXmlTag))
-    return false;
-  std::string buffer;
-  if (!ExtractNamedValueFromXmlReader(reader, kUrlXmlTag, &buffer)) {
-    return false;
-  }
-  entry->url = GURL(buffer);
-  return true;
-}
-
-bool Toolbar5Importer::ExtractTimeFromXmlReader(
-    XmlReader* reader,
-    ImportedBookmarkEntry* entry) {
-  DCHECK(reader);
-  DCHECK(entry);
-  if (!LocateNextTagWithStopByName(reader, kTimestampXmlTag, kLabelsXmlTag))
-    return false;
-  std::string buffer;
-  if (!ExtractNamedValueFromXmlReader(reader, kTimestampXmlTag, &buffer)) {
-    return false;
-  }
-  int64 timestamp;
-  if (!base::StringToInt64(buffer, &timestamp)) {
-    return false;
-  }
-  entry->creation_time = base::Time::FromTimeT(timestamp);
-  return true;
-}
-
-bool Toolbar5Importer::ExtractFoldersFromXmlReader(
-    XmlReader* reader,
-    std::vector<BookmarkFolderType>* bookmark_folders,
-    const string16& bookmark_group_string) {
-  DCHECK(reader);
-  DCHECK(bookmark_folders);
-
-  // Read in the labels for this bookmark from the xml.  There may be many
-  // labels for any one bookmark.
-  if (!LocateNextTagWithStopByName(reader, kLabelsXmlTag, kAttributesXmlTag))
-    return false;
-
-  // It is within scope to have an empty labels section, so we do not
-  // return false if the labels are empty.
-  if (!reader->Read() || !LocateNextOpenTag(reader))
-    return false;
-
-  std::vector<string16> label_vector;
-  while (kLabelXmlTag == reader->NodeName()) {
-    std::string label_buffer;
-    if (!reader->ReadElementContent(&label_buffer)) {
-      label_buffer = "";
-    }
-    label_vector.push_back(UTF8ToUTF16(label_buffer));
-    LocateNextOpenTag(reader);
-  }
-
-  if (0 == label_vector.size()) {
-    if (!first_run::IsChromeFirstRun()) {
-      bookmark_folders->resize(1);
-      (*bookmark_folders)[0].push_back(bookmark_group_string);
-    }
-    return true;
-  }
-
-  // We will be making one bookmark folder for each label.
-  bookmark_folders->resize(label_vector.size());
-
-  for (size_t index = 0; index < label_vector.size(); ++index) {
-    // If this is the first run then we place favorites with no labels
-    // in the title bar.  Else they are placed in the "Google Toolbar" folder.
-    if (!first_run::IsChromeFirstRun() || !label_vector[index].empty()) {
-      (*bookmark_folders)[index].push_back(bookmark_group_string);
-    }
-
-    // If the label and is in the form "xxx:yyy:zzz" this was created from an
-    // IE or Firefox folder.  We undo the label creation and recreate the
-    // correct folder.
-    std::vector<string16> folder_names;
-    base::SplitString(label_vector[index], ':', &folder_names);
-    (*bookmark_folders)[index].insert((*bookmark_folders)[index].end(),
-        folder_names.begin(), folder_names.end());
-  }
-
-  return true;
-}
-
-void  Toolbar5Importer::AddBookmarksToChrome(
-    const std::vector<ImportedBookmarkEntry>& bookmarks) {
-  if (!bookmarks.empty() && !cancelled()) {
-    const string16& first_folder_name =
-        bridge_->GetLocalizedString(IDS_BOOKMARK_GROUP_FROM_GOOGLE_TOOLBAR);
-    bridge_->AddBookmarks(bookmarks, first_folder_name);
-  }
-}
diff --git a/chrome/browser/importer/toolbar_importer.h b/chrome/browser/importer/toolbar_importer.h
deleted file mode 100644
index 961b67f..0000000
--- a/chrome/browser/importer/toolbar_importer.h
+++ /dev/null
@@ -1,170 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// The functionality provided here allows the user to import their bookmarks
-// (favorites) from Google Toolbar.
-
-#ifndef CHROME_BROWSER_IMPORTER_TOOLBAR_IMPORTER_H_
-#define CHROME_BROWSER_IMPORTER_TOOLBAR_IMPORTER_H_
-
-#include <string>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/gtest_prod_util.h"
-#include "base/memory/ref_counted.h"
-#include "base/strings/string16.h"
-#include "chrome/browser/importer/importer.h"
-#include "net/url_request/url_fetcher_delegate.h"
-#include "net/url_request/url_request_context_getter.h"
-
-struct ImportedBookmarkEntry;
-class ImporterBridge;
-class XmlReader;
-
-namespace net {
-class URLFetcher;
-}  // namespace net
-
-// Toolbar5Importer is a class which exposes the functionality needed to
-// communicate with the Google Toolbar v5 front-end, negotiate the download of
-// Toolbar bookmarks, parse them, and install them on the client.
-// Toolbar5Importer should not have StartImport called more than once. Futher
-// if StartImport is called, then the class must not be destroyed until it has
-// either completed or Toolbar5Importer->Cancel() has been called.
-class Toolbar5Importer : public net::URLFetcherDelegate, public Importer {
- public:
-  Toolbar5Importer();
-
-  // Importer:
-  // The importer view calls this method to begin the process. |items| should
-  // only either be NONE or FAVORITES, since as of right now these are the only
-  // items this importer supports.
-  virtual void StartImport(const importer::SourceProfile& source_profile,
-                           uint16 items,
-                           ImporterBridge* bridge) OVERRIDE;
-
-  // Importer view call this method when the user clicks the cancel button
-  // in the tabbed options UI.  We need to post a message to our loop
-  // to cancel network retrieval.
-  virtual void Cancel() OVERRIDE;
-
-  // net::URLFetcherDelegate method called back from the URLFetcher object.
-  virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
-
- private:
-  FRIEND_TEST_ALL_PREFIXES(Toolbar5ImporterTest, BookmarkParse);
-
-  virtual ~Toolbar5Importer();
-
-  // Internal states of the toolbar importer.
-  enum InternalStateEnum {
-    NOT_USED = -1,
-    INITIALIZED,
-    GET_AUTHORIZATION_TOKEN,
-    GET_BOOKMARKS,
-    PARSE_BOOKMARKS,
-    DONE
-  };
-
-  typedef std::vector<string16> BookmarkFolderType;
-
-  // URLs for connecting to the toolbar front end are defined below.
-  static const char kT5AuthorizationTokenUrl[];
-  static const char kT5FrontEndUrlTemplate[];
-
-  // Token replacement tags are defined below.
-  static const char kRandomNumberToken[];
-  static const char kAuthorizationToken[];
-  static const char kAuthorizationTokenPrefix[];
-  static const char kAuthorizationTokenSuffix[];
-  static const char kMaxNumToken[];
-  static const char kMaxTimestampToken[];
-
-  // XML tag names are defined below.
-  static const char kXmlApiReplyXmlTag[];
-  static const char kBookmarksXmlTag[];
-  static const char kBookmarkXmlTag[];
-  static const char kTitleXmlTag[];
-  static const char kUrlXmlTag[];
-  static const char kTimestampXmlTag[];
-  static const char kLabelsXmlTag[];
-  static const char kLabelsXmlCloseTag[];
-  static const char kLabelXmlTag[];
-  static const char kAttributesXmlTag[];
-
-  // Flow control for asynchronous import is controlled by the methods below.
-  // ContinueImport is called back by each import action taken.  BeginXXX
-  // and EndXXX are responsible for updating the state of the asynchronous
-  // import.  EndImport is responsible for state cleanup and notifying the
-  // caller that import has completed.
-  void ContinueImport();
-  void EndImport();
-  void BeginImportBookmarks();
-  void EndImportBookmarks();
-
-  // Network I/O is done by the methods below.  These three methods are called
-  // in the order provided.  The last two are called back with the HTML
-  // response provided by the Toolbar server.
-  void GetAuthenticationFromServer();
-  void GetBookmarkDataFromServer(const std::string& response);
-  void GetBookmarksFromServerDataResponse(const std::string& response);
-
-  // XML Parsing is implemented with the methods below.
-  bool ParseAuthenticationTokenResponse(const std::string& response,
-                                        std::string* token);
-
-  static bool ParseBookmarksFromReader(
-      XmlReader* reader,
-      std::vector<ImportedBookmarkEntry>* bookmarks,
-      const string16& bookmark_group_string);
-
-  static bool LocateNextOpenTag(XmlReader* reader);
-  static bool LocateNextTagByName(XmlReader* reader, const std::string& tag);
-  static bool LocateNextTagWithStopByName(
-      XmlReader* reader,
-      const std::string& tag,
-      const std::string& stop);
-
-  static bool ExtractBookmarkInformation(
-      XmlReader* reader,
-      ImportedBookmarkEntry* bookmark_entry,
-      std::vector<BookmarkFolderType>* bookmark_folders,
-      const string16& bookmark_group_string);
-  static bool ExtractNamedValueFromXmlReader(XmlReader* reader,
-                                             const std::string& name,
-                                             std::string* buffer);
-  static bool ExtractTitleFromXmlReader(XmlReader* reader,
-                                        ImportedBookmarkEntry* entry);
-  static bool ExtractUrlFromXmlReader(XmlReader* reader,
-                                      ImportedBookmarkEntry* entry);
-  static bool ExtractTimeFromXmlReader(XmlReader* reader,
-                                       ImportedBookmarkEntry* entry);
-  static bool ExtractFoldersFromXmlReader(
-      XmlReader* reader,
-      std::vector<BookmarkFolderType>* bookmark_folders,
-      const string16& bookmark_group_string);
-
-  // Bookmark creation is done by the method below.
-  void AddBookmarksToChrome(
-      const std::vector<ImportedBookmarkEntry>& bookmarks);
-
-  InternalStateEnum state_;
-
-  // Bitmask of Importer::ImportItem.
-  uint16 items_to_import_;
-
-  // The fetchers need to be available to cancel the network call on user cancel
-  // hence they are stored as member variables.
-  net::URLFetcher* token_fetcher_;
-  net::URLFetcher* data_fetcher_;
-
-  // Used to get correct login data for the toolbar server.
-  scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
-
-  DISALLOW_COPY_AND_ASSIGN(Toolbar5Importer);
-};
-
-#endif  // CHROME_BROWSER_IMPORTER_TOOLBAR_IMPORTER_H_
diff --git a/chrome/browser/importer/toolbar_importer_unittest.cc b/chrome/browser/importer/toolbar_importer_unittest.cc
deleted file mode 100644
index f8c89dc..0000000
--- a/chrome/browser/importer/toolbar_importer_unittest.cc
+++ /dev/null
@@ -1,488 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-#include <string>
-#include <vector>
-
-#include "base/strings/string16.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/bookmarks/imported_bookmark_entry.h"
-#include "chrome/browser/first_run/first_run.h"
-#include "chrome/browser/first_run/first_run_internal.h"
-#include "chrome/browser/importer/toolbar_importer.h"
-#include "googleurl/src/gurl.h"
-#include "third_party/libxml/chromium/libxml_utils.h"
-
-// See http://crbug.com/11838
-TEST(Toolbar5ImporterTest, BookmarkParse) {
-static const string16 kTitle = ASCIIToUTF16("MyTitle");
-static const char kUrl[] = "http://www.google.com/";
-static const string16 kFolder = ASCIIToUTF16("Google");
-static const string16 kFolder2 = ASCIIToUTF16("Homepage");
-static const string16 kFolderArray[3] = {
-  ASCIIToUTF16("Google"),
-  ASCIIToUTF16("Search"),
-  ASCIIToUTF16("Page")
-};
-static const string16 kOtherTitle = ASCIIToUTF16("MyOtherTitle");
-static const char* kOtherUrl = "http://www.google.com/mail";
-static const string16 kOtherFolder = ASCIIToUTF16("Mail");
-
-static const string16 kBookmarkGroupTitle = ASCIIToUTF16("BookmarkGroupTitle");
-
-// Since the following is very dense to read I enumerate the test cases here.
-// 1. Correct bookmark structure with one label.
-// 2. Correct bookmark structure with no labels.
-// 3. Correct bookmark structure with two labels.
-// 4. Correct bookmark structure with a folder->label translation by toolbar.
-// 5. Correct bookmark structure with no favicon.
-// 6. Two correct bookmarks.
-// The following are error cases by removing sections from the xml:
-// 7. Empty string passed as xml.
-// 8. No <bookmarks> section in the xml.
-// 9. No <bookmark> section below the <bookmarks> section.
-// 10. No <title> in a <bookmark> section.
-// 11. No <url> in a <bookmark> section.
-// 12. No <timestamp> in a <bookmark> section.
-// 13. No <labels> in a <bookmark> section.
-static const char* kGoodBookmark =
-    "<?xml version=\"1.0\" ?> <xml_api_reply version=\"1\"> <bookmarks>"
-    " <bookmark> "
-    "<title>MyTitle</title> "
-    "<url>http://www.google.com/</url> "
-    "<timestamp>1153328691085181</timestamp> "
-    "<id>N123nasdf239</id> <notebook_id>Bxxxxxxx</notebook_id> "
-    "<section_id>Sxxxxxx</section_id> <has_highlight>0</has_highlight>"
-    "<labels> <label>Google</label> </labels> "
-    "<attributes> "
-    "<attribute> "
-    "<name>favicon_url</name> <value>http://www.google.com/favicon.ico</value> "
-    "</attribute> "
-    "<attribute> "
-    "<name>favicon_timestamp</name> <value>1153328653</value> "
-    "</attribute> "
-    "<attribute> <name>notebook_name</name> <value>My notebook 0</value> "
-    "</attribute> "
-    "<attribute> <name>section_name</name> <value>My section 0 "
-    "</value> </attribute> </attributes> "
-    "</bookmark> </bookmarks>";
-static const char* kGoodBookmarkNoLabel =
-    "<?xml version=\"1.0\" ?> <xml_api_reply version=\"1\"> <bookmarks>"
-    " <bookmark> "
-    "<title>MyTitle</title> "
-    "<url>http://www.google.com/</url> "
-    "<timestamp>1153328691085181</timestamp> "
-    "<id>N123nasdf239</id> <notebook_id>Bxxxxxxx</notebook_id> "
-    "<section_id>Sxxxxxx</section_id> <has_highlight>0</has_highlight>"
-    "<labels> </labels> "
-    "<attributes> "
-    "<attribute> "
-    "<name>favicon_url</name> <value>http://www.google.com/favicon.ico</value> "
-    "</attribute> "
-    "<attribute> "
-    "<name>favicon_timestamp</name> <value>1153328653</value> "
-    "</attribute> "
-    "<attribute> <name>notebook_name</name> <value>My notebook 0</value> "
-    "</attribute> "
-    "<attribute> <name>section_name</name> <value>My section 0 "
-    "</value> </attribute> </attributes> "
-    "</bookmark> </bookmarks>";
-static const char* kGoodBookmarkTwoLabels =
-    "<?xml version=\"1.0\" ?> <xml_api_reply version=\"1\"> <bookmarks>"
-    " <bookmark> "
-    "<title>MyTitle</title> "
-    "<url>http://www.google.com/</url> "
-    "<timestamp>1153328691085181</timestamp> "
-    "<id>N123nasdf239</id> <notebook_id>Bxxxxxxx</notebook_id> "
-    "<section_id>Sxxxxxx</section_id> <has_highlight>0</has_highlight>"
-    "<labels> <label>Google</label> <label>Homepage</label> </labels> "
-    "<attributes> "
-    "<attribute> "
-    "<name>favicon_url</name> <value>http://www.google.com/favicon.ico</value> "
-    "</attribute> "
-    "<attribute> "
-    "<name>favicon_timestamp</name> <value>1153328653</value> "
-    "</attribute> "
-    "<attribute> <name>notebook_name</name> <value>My notebook 0</value> "
-    "</attribute> "
-    "<attribute> <name>section_name</name> <value>My section 0 "
-    "</value> </attribute> </attributes> "
-    "</bookmark> </bookmarks>";
-static const char* kGoodBookmarkFolderLabel =
-    "<?xml version=\"1.0\" ?> <xml_api_reply version=\"1\"> <bookmarks>"
-    " <bookmark> "
-    "<title>MyTitle</title> "
-    "<url>http://www.google.com/</url> "
-    "<timestamp>1153328691085181</timestamp> "
-    "<id>N123nasdf239</id> <notebook_id>Bxxxxxxx</notebook_id> "
-    "<section_id>Sxxxxxx</section_id> <has_highlight>0</has_highlight>"
-    "<labels> <label>Google:Search:Page</label> </labels> "
-    "<attributes> "
-    "<attribute> "
-    "<name>favicon_url</name> <value>http://www.google.com/favicon.ico</value> "
-    "</attribute> "
-    "<attribute> "
-    "<name>favicon_timestamp</name> <value>1153328653</value> "
-    "</attribute> "
-    "<attribute> <name>notebook_name</name> <value>My notebook 0</value> "
-    "</attribute> "
-    "<attribute> <name>section_name</name> <value>My section 0 "
-    "</value> </attribute> </attributes> "
-    "</bookmark> </bookmarks>";
-static const char* kGoodBookmarkNoFavicon =
-    "<?xml version=\"1.0\" ?> <xml_api_reply version=\"1\"> <bookmarks>"
-    " <bookmark> "
-    "<title>MyTitle</title> "
-    "<url>http://www.google.com/</url> "
-    "<timestamp>1153328691085181</timestamp> "
-    "<id>N123nasdf239</id> <notebook_id>Bxxxxxxx</notebook_id> "
-    "<section_id>Sxxxxxx</section_id> <has_highlight>0</has_highlight>"
-    "<labels> <label>Google</label> </labels> "
-    "<attributes> "
-    "<attribute> "
-    "<name>favicon_timestamp</name> <value>1153328653</value> "
-    "</attribute> "
-    "<attribute> <name>notebook_name</name> <value>My notebook 0</value> "
-    "</attribute> "
-    "<attribute> <name>section_name</name> <value>My section 0 "
-    "</value> </attribute> </attributes> "
-    "</bookmark> </bookmarks>";
-static const char* kGoodBookmark2Items =
-    "<?xml version=\"1.0\" ?> <xml_api_reply version=\"1\"> <bookmarks>"
-    " <bookmark> "
-    "<title>MyTitle</title> "
-    "<url>http://www.google.com/</url> "
-    "<timestamp>1153328691085181</timestamp> "
-    "<id>N123nasdf239</id> <notebook_id>Bxxxxxxx</notebook_id> "
-    "<section_id>Sxxxxxx</section_id> <has_highlight>0</has_highlight>"
-    "<labels> <label>Google</label> </labels> "
-    "<attributes> "
-    "<attribute> "
-    "<name>favicon_url</name> <value>http://www.google.com/favicon.ico</value> "
-    "</attribute> "
-    "<attribute> "
-    "<name>favicon_timestamp</name> <value>1153328653</value> "
-    "</attribute> "
-    "<attribute> <name>notebook_name</name> <value>My notebook 0</value> "
-    "</attribute> "
-    "<attribute> <name>section_name</name> <value>My section 0 "
-    "</value> </attribute> </attributes> "
-    "</bookmark>"
-    " <bookmark> "
-    "<title>MyOtherTitle</title> "
-    "<url>http://www.google.com/mail</url> "
-    "<timestamp>1153328691085181</timestamp> "
-    "<id>N123nasdf239</id> <notebook_id>Bxxxxxxx</notebook_id> "
-    "<section_id>Sxxxxxx</section_id> <has_highlight>0</has_highlight>"
-    "<labels> <label>Mail</label> </labels> "
-    "<attributes> "
-    "<attribute> "
-    "<name>favicon_url</name>"
-    "<value>http://www.google.com/mail/favicon.ico</value> "
-    "</attribute> "
-    "<attribute> "
-    "<name>favicon_timestamp</name> <value>1253328653</value> "
-    "</attribute> "
-    "<attribute> <name>notebook_name</name> <value>My notebook 0</value> "
-    "</attribute> "
-    "<attribute> <name>section_name</name> <value>My section 0 "
-    "</value> </attribute> </attributes> "
-    "</bookmark>"
-    "</bookmarks>";
-static const char* kEmptyString = "";
-static const char* kBadBookmarkNoBookmarks =
-    " <bookmark> "
-    "<title>MyTitle</title> "
-    "<url>http://www.google.com/</url> "
-    "<timestamp>1153328691085181</timestamp> "
-    "<id>N123nasdf239</id> <notebook_id>Bxxxxxxx</notebook_id> "
-    "<section_id>Sxxxxxx</section_id> <has_highlight>0</has_highlight>"
-    "<labels> <label>Google</label> </labels> "
-    "<attributes> "
-    "<attribute> "
-    "<name>favicon_url</name> <value>http://www.google.com/favicon.ico</value> "
-    "</attribute> "
-    "<attribute> "
-    "<name>favicon_timestamp</name> <value>1153328653</value> "
-    "</attribute> "
-    "<attribute> <name>notebook_name</name> <value>My notebook 0</value> "
-    "</attribute> "
-    "<attribute> <name>section_name</name> <value>My section 0 "
-    "</value> </attribute> </attributes> "
-    "</bookmark> </bookmarks>";
-static const char* kBadBookmarkNoBookmark =
-    "<?xml version=\"1.0\" ?> <xml_api_reply version=\"1\"> <bookmarks>"
-    "<title>MyTitle</title> "
-    "<url>http://www.google.com/</url> "
-    "<timestamp>1153328691085181</timestamp> "
-    "<id>N123nasdf239</id> <notebook_id>Bxxxxxxx</notebook_id> "
-    "<section_id>Sxxxxxx</section_id> <has_highlight>0</has_highlight>"
-    "<labels> <label>Google</label> </labels> "
-    "<attributes> "
-    "<attribute> "
-    "<name>favicon_url</name> <value>http://www.google.com/favicon.ico</value> "
-    "</attribute> "
-    "<attribute> "
-    "<name>favicon_timestamp</name> <value>1153328653</value> "
-    "</attribute> "
-    "<attribute> <name>notebook_name</name> <value>My notebook 0</value> "
-    "</attribute> "
-    "<attribute> <name>section_name</name> <value>My section 0 "
-    "</value> </attribute> </attributes> "
-    "</bookmark> </bookmarks>";
-static const char* kBadBookmarkNoTitle =
-    "<?xml version=\"1.0\" ?> <xml_api_reply version=\"1\"> <bookmarks>"
-    " <bookmark> "
-    "<url>http://www.google.com/</url> "
-    "<timestamp>1153328691085181</timestamp> "
-    "<id>N123nasdf239</id> <notebook_id>Bxxxxxxx</notebook_id> "
-    "<section_id>Sxxxxxx</section_id> <has_highlight>0</has_highlight>"
-    "<labels> <label>Google</label> </labels> "
-    "<attributes> "
-    "<attribute> "
-    "<name>favicon_url</name> <value>http://www.google.com/favicon.ico</value> "
-    "</attribute> "
-    "<attribute> "
-    "<name>favicon_timestamp</name> <value>1153328653</value> "
-    "</attribute> "
-    "<attribute> <name>notebook_name</name> <value>My notebook 0</value> "
-    "</attribute> "
-    "<attribute> <name>section_name</name> <value>My section 0 "
-    "</value> </attribute> </attributes> "
-    "</bookmark> </bookmarks>";
-static const char* kBadBookmarkNoUrl =
-    "<?xml version=\"1.0\" ?> <xml_api_reply version=\"1\"> <bookmarks>"
-    " <bookmark> "
-    "<title>MyTitle</title> "
-    "<timestamp>1153328691085181</timestamp> "
-    "<id>N123nasdf239</id> <notebook_id>Bxxxxxxx</notebook_id> "
-    "<section_id>Sxxxxxx</section_id> <has_highlight>0</has_highlight>"
-    "<labels> <label>Google</label> </labels> "
-    "<attributes> "
-    "<attribute> "
-    "<name>favicon_url</name> <value>http://www.google.com/favicon.ico</value> "
-    "</attribute> "
-    "<attribute> "
-    "<name>favicon_timestamp</name> <value>1153328653</value> "
-    "</attribute> "
-    "<attribute> <name>notebook_name</name> <value>My notebook 0</value> "
-    "</attribute> "
-    "<attribute> <name>section_name</name> <value>My section 0 "
-    "</value> </attribute> </attributes> "
-    "</bookmark> </bookmarks>";
-static const char* kBadBookmarkNoTimestamp =
-    "<?xml version=\"1.0\" ?> <xml_api_reply version=\"1\"> <bookmarks>"
-    " <bookmark> "
-    "<title>MyTitle</title> "
-    "<url>http://www.google.com/</url> "
-    "<id>N123nasdf239</id> <notebook_id>Bxxxxxxx</notebook_id> "
-    "<section_id>Sxxxxxx</section_id> <has_highlight>0</has_highlight>"
-    "<labels> <label>Google</label> </labels> "
-    "<attributes> "
-    "<attribute> "
-    "<name>favicon_url</name> <value>http://www.google.com/favicon.ico</value> "
-    "</attribute> "
-    "<attribute> "
-    "<name>favicon_timestamp</name> <value>1153328653</value> "
-    "</attribute> "
-    "<attribute> <name>notebook_name</name> <value>My notebook 0</value> "
-    "</attribute> "
-    "<attribute> <name>section_name</name> <value>My section 0 "
-    "</value> </attribute> </attributes> "
-    "</bookmark> </bookmarks>";
-static const char* kBadBookmarkNoLabels =
-    "<?xml version=\"1.0\" ?> <xml_api_reply version=\"1\"> <bookmarks>"
-    " <bookmark> "
-    "<title>MyTitle</title> "
-    "<url>http://www.google.com/</url> "
-    "<timestamp>1153328691085181</timestamp> "
-    "<id>N123nasdf239</id> <notebook_id>Bxxxxxxx</notebook_id> "
-    "<section_id>Sxxxxxx</section_id> <has_highlight>0</has_highlight>"
-    "<attributes> "
-    "<attribute> "
-    "<name>favicon_url</name> <value>http://www.google.com/favicon.ico</value> "
-    "</attribute> "
-    "<attribute> "
-    "<name>favicon_timestamp</name> <value>1153328653</value> "
-    "</attribute> "
-    "<attribute> <name>notebook_name</name> <value>My notebook 0</value> "
-    "</attribute> "
-    "<attribute> <name>section_name</name> <value>My section 0 "
-    "</value> </attribute> </attributes> "
-    "</bookmark> </bookmarks>";
-
-  XmlReader reader;
-  std::string bookmark_xml;
-  std::vector<ImportedBookmarkEntry> bookmarks;
-
-  const GURL url(kUrl);
-  const GURL other_url(kOtherUrl);
-
-  // Test doesn't work if the importer thinks this is the first run of Chromium.
-  // Mark this as a subsequent run of the browser.
-  first_run::internal::first_run_ = first_run::internal::FIRST_RUN_FALSE;
-
-  // Test case 1 is parsing a basic bookmark with a single label.
-  bookmark_xml = kGoodBookmark;
-  bookmarks.clear();
-  XmlReader reader1;
-  EXPECT_TRUE(reader1.Load(bookmark_xml));
-  EXPECT_TRUE(Toolbar5Importer::ParseBookmarksFromReader(&reader1, &bookmarks,
-      kBookmarkGroupTitle));
-
-  ASSERT_EQ(1U, bookmarks.size());
-  EXPECT_FALSE(bookmarks[0].in_toolbar);
-  EXPECT_EQ(kTitle, bookmarks[0].title);
-  EXPECT_EQ(url, bookmarks[0].url);
-  ASSERT_EQ(2U, bookmarks[0].path.size());
-  EXPECT_EQ(kFolder, bookmarks[0].path[1]);
-
-  // Test case 2 is parsing a single bookmark with no label.
-  bookmark_xml = kGoodBookmarkNoLabel;
-  bookmarks.clear();
-  XmlReader reader2;
-  EXPECT_TRUE(reader2.Load(bookmark_xml));
-  EXPECT_TRUE(Toolbar5Importer::ParseBookmarksFromReader(&reader2, &bookmarks,
-      kBookmarkGroupTitle));
-
-  ASSERT_EQ(1U, bookmarks.size());
-  EXPECT_FALSE(bookmarks[0].in_toolbar);
-  EXPECT_EQ(kTitle, bookmarks[0].title);
-  EXPECT_EQ(url, bookmarks[0].url);
-  EXPECT_EQ(1U, bookmarks[0].path.size());
-
-  // Test case 3 is parsing a single bookmark with two labels.
-  bookmark_xml = kGoodBookmarkTwoLabels;
-  bookmarks.clear();
-  XmlReader reader3;
-  EXPECT_TRUE(reader3.Load(bookmark_xml));
-  EXPECT_TRUE(Toolbar5Importer::ParseBookmarksFromReader(&reader3, &bookmarks,
-      kBookmarkGroupTitle));
-
-  ASSERT_EQ(2U, bookmarks.size());
-  EXPECT_FALSE(bookmarks[0].in_toolbar);
-  EXPECT_FALSE(bookmarks[1].in_toolbar);
-  EXPECT_EQ(kTitle, bookmarks[0].title);
-  EXPECT_EQ(kTitle, bookmarks[1].title);
-  EXPECT_EQ(url, bookmarks[0].url);
-  EXPECT_EQ(url, bookmarks[1].url);
-  ASSERT_EQ(2U, bookmarks[0].path.size());
-  EXPECT_EQ(kFolder, bookmarks[0].path[1]);
-  ASSERT_EQ(2U, bookmarks[1].path.size());
-  EXPECT_EQ(kFolder2, bookmarks[1].path[1]);
-
-  // Test case 4 is parsing a single bookmark which has a label with a colon,
-  // this test file name translation between Toolbar and Chrome.
-  bookmark_xml = kGoodBookmarkFolderLabel;
-  bookmarks.clear();
-  XmlReader reader4;
-  EXPECT_TRUE(reader4.Load(bookmark_xml));
-  EXPECT_TRUE(Toolbar5Importer::ParseBookmarksFromReader(&reader4, &bookmarks,
-      kBookmarkGroupTitle));
-
-  ASSERT_EQ(1U, bookmarks.size());
-  EXPECT_FALSE(bookmarks[0].in_toolbar);
-  EXPECT_EQ(kTitle, bookmarks[0].title);
-  EXPECT_EQ(url, bookmarks[0].url);
-  ASSERT_EQ(4U, bookmarks[0].path.size());
-  EXPECT_EQ(string16(kFolderArray[0]),
-            bookmarks[0].path[1]);
-  EXPECT_EQ(string16(kFolderArray[1]),
-            bookmarks[0].path[2]);
-  EXPECT_EQ(string16(kFolderArray[2]),
-            bookmarks[0].path[3]);
-
-  // Test case 5 is parsing a single bookmark without a favicon URL.
-  bookmark_xml = kGoodBookmarkNoFavicon;
-  bookmarks.clear();
-  XmlReader reader5;
-  EXPECT_TRUE(reader5.Load(bookmark_xml));
-  EXPECT_TRUE(Toolbar5Importer::ParseBookmarksFromReader(&reader5, &bookmarks,
-      kBookmarkGroupTitle));
-
-  ASSERT_EQ(1U, bookmarks.size());
-  EXPECT_FALSE(bookmarks[0].in_toolbar);
-  EXPECT_EQ(kTitle, bookmarks[0].title);
-  EXPECT_EQ(url, bookmarks[0].url);
-  ASSERT_EQ(2U, bookmarks[0].path.size());
-  EXPECT_EQ(kFolder, bookmarks[0].path[1]);
-
-  // Test case 6 is parsing two bookmarks.
-  bookmark_xml = kGoodBookmark2Items;
-  bookmarks.clear();
-  XmlReader reader6;
-  EXPECT_TRUE(reader6.Load(bookmark_xml));
-  EXPECT_TRUE(Toolbar5Importer::ParseBookmarksFromReader(&reader6, &bookmarks,
-      kBookmarkGroupTitle));
-
-  ASSERT_EQ(2U, bookmarks.size());
-  EXPECT_FALSE(bookmarks[0].in_toolbar);
-  EXPECT_FALSE(bookmarks[1].in_toolbar);
-  EXPECT_EQ(kTitle, bookmarks[0].title);
-  EXPECT_EQ(kOtherTitle, bookmarks[1].title);
-  EXPECT_EQ(url, bookmarks[0].url);
-  EXPECT_EQ(other_url, bookmarks[1].url);
-  ASSERT_EQ(2U, bookmarks[0].path.size());
-  EXPECT_EQ(kFolder, bookmarks[0].path[1]);
-  ASSERT_EQ(2U, bookmarks[1].path.size());
-  EXPECT_EQ(kOtherFolder, bookmarks[1].path[1]);
-
-  // Test case 7 is parsing an empty string for bookmarks.
-  bookmark_xml = kEmptyString;
-  bookmarks.clear();
-  XmlReader reader7;
-  EXPECT_FALSE(reader7.Load(bookmark_xml));
-
-  // Test case 8 is testing the error when no <bookmarks> section is present.
-  bookmark_xml = kBadBookmarkNoBookmarks;
-  bookmarks.clear();
-  XmlReader reader8;
-  EXPECT_TRUE(reader8.Load(bookmark_xml));
-  EXPECT_FALSE(Toolbar5Importer::ParseBookmarksFromReader(&reader8,
-      &bookmarks, kBookmarkGroupTitle));
-
-  // Test case 9 tests when no <bookmark> section is present.
-  bookmark_xml = kBadBookmarkNoBookmark;
-  bookmarks.clear();
-  XmlReader reader9;
-  EXPECT_TRUE(reader9.Load(bookmark_xml));
-  EXPECT_FALSE(Toolbar5Importer::ParseBookmarksFromReader(&reader9,
-      &bookmarks, kBookmarkGroupTitle));
-
-
-  // Test case 10 tests when a bookmark has no <title> section.
-  bookmark_xml = kBadBookmarkNoTitle;
-  bookmarks.clear();
-  XmlReader reader10;
-  EXPECT_TRUE(reader10.Load(bookmark_xml));
-  EXPECT_FALSE(Toolbar5Importer::ParseBookmarksFromReader(&reader10,
-      &bookmarks, kBookmarkGroupTitle));
-
-  // Test case 11 tests when a bookmark has no <url> section.
-  bookmark_xml = kBadBookmarkNoUrl;
-  bookmarks.clear();
-  XmlReader reader11;
-  EXPECT_TRUE(reader11.Load(bookmark_xml));
-  EXPECT_FALSE(Toolbar5Importer::ParseBookmarksFromReader(&reader11,
-      &bookmarks, kBookmarkGroupTitle));
-
-  // Test case 12 tests when a bookmark has no <timestamp> section.
-  bookmark_xml = kBadBookmarkNoTimestamp;
-  bookmarks.clear();
-  XmlReader reader12;
-  EXPECT_TRUE(reader12.Load(bookmark_xml));
-  EXPECT_FALSE(Toolbar5Importer::ParseBookmarksFromReader(&reader12,
-      &bookmarks, kBookmarkGroupTitle));
-
-  // Test case 13 tests when a bookmark has no <labels> section.
-  bookmark_xml = kBadBookmarkNoLabels;
-  bookmarks.clear();
-  XmlReader reader13;
-  EXPECT_TRUE(reader13.Load(bookmark_xml));
-  EXPECT_FALSE(Toolbar5Importer::ParseBookmarksFromReader(&reader13,
-      &bookmarks, kBookmarkGroupTitle));
-}
diff --git a/chrome/browser/importer/toolbar_importer_utils.cc b/chrome/browser/importer/toolbar_importer_utils.cc
deleted file mode 100644
index 81f2854..0000000
--- a/chrome/browser/importer/toolbar_importer_utils.cc
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/importer/toolbar_importer_utils.h"
-
-#include <string>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/strings/string_split.h"
-#include "chrome/browser/profiles/profile.h"
-#include "content/public/browser/browser_thread.h"
-#include "googleurl/src/gurl.h"
-#include "net/cookies/cookie_store.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_context_getter.h"
-
-using content::BrowserThread;
-
-namespace {
-const char kGoogleDomainUrl[] = "http://.google.com/";
-const char kGoogleDomainSecureCookieId[] = "SID=";
-const char kSplitStringToken = ';';
-}
-
-namespace toolbar_importer_utils {
-
-void OnGetCookies(const base::Callback<void(bool)>& callback,
-                  const std::string& cookies) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  std::vector<std::string> cookie_list;
-  base::SplitString(cookies, kSplitStringToken, &cookie_list);
-  for (std::vector<std::string>::iterator current = cookie_list.begin();
-       current != cookie_list.end();
-       ++current) {
-    size_t position = (*current).find(kGoogleDomainSecureCookieId);
-    if (position == 0) {
-      callback.Run(true);
-      return;
-    }
-  }
-  callback.Run(false);
-}
-
-void OnFetchComplete(const base::Callback<void(bool)>& callback,
-                     const std::string& cookies) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      base::Bind(&OnGetCookies, callback, cookies));
-}
-
-void FetchCookiesOnIOThread(
-    const base::Callback<void(bool)>& callback,
-    net::URLRequestContextGetter* context_getter) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-  net::CookieStore* store = context_getter->
-      GetURLRequestContext()->cookie_store();
-  GURL url(kGoogleDomainUrl);
-  net::CookieOptions options;
-  options.set_include_httponly();  // The SID cookie might be httponly.
-  store->GetCookiesWithOptionsAsync(
-      url, options,
-      base::Bind(&toolbar_importer_utils::OnFetchComplete, callback));
-}
-
-void IsGoogleGAIACookieInstalled(const base::Callback<void(bool)>& callback,
-                                 Profile* profile) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  if (!callback.is_null()) {
-    BrowserThread::PostTask(
-        BrowserThread::IO, FROM_HERE,
-        base::Bind(&FetchCookiesOnIOThread,
-                   callback, base::Unretained(profile->GetRequestContext())));
-  }
-}
-
-}  // namespace toolbar_importer_utils
diff --git a/chrome/browser/importer/toolbar_importer_utils.h b/chrome/browser/importer/toolbar_importer_utils.h
deleted file mode 100644
index ca89363..0000000
--- a/chrome/browser/importer/toolbar_importer_utils.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_IMPORTER_TOOLBAR_IMPORTER_UTILS_H_
-#define CHROME_BROWSER_IMPORTER_TOOLBAR_IMPORTER_UTILS_H_
-
-#include "base/callback_forward.h"
-
-class Profile;
-
-namespace toolbar_importer_utils {
-
-// Currently the only configuration information we need is to check whether or
-// not the user currently has their GAIA cookie.  This is done by the function
-// exposed through the ToolbarImportUtils namespace.
-void IsGoogleGAIACookieInstalled(const base::Callback<void(bool)>& callback,
-                                 Profile* profile);
-
-}  // namespace toolbar_importer_utils
-
-#endif  // CHROME_BROWSER_IMPORTER_TOOLBAR_IMPORTER_UTILS_H_
diff --git a/chrome/browser/importer/toolbar_importer_utils_browsertest.cc b/chrome/browser/importer/toolbar_importer_utils_browsertest.cc
deleted file mode 100644
index 1d71fca..0000000
--- a/chrome/browser/importer/toolbar_importer_utils_browsertest.cc
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/bind.h"
-#include "base/message_loop.h"
-#include "chrome/browser/importer/toolbar_importer_utils.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/test/base/in_process_browser_test.h"
-#include "chrome/test/base/ui_test_utils.h"
-
-namespace {
-
-class ToolbarImporterUtilsTest : public InProcessBrowserTest {
- public:
-  ToolbarImporterUtilsTest() : did_run_(false) {
-  }
-
-  void Callback(bool result) {
-    DCHECK(!result);
-    did_run_ = true;
-    base::MessageLoop::current()->Quit();
-  }
-
- protected:
-  bool did_run_;
-};
-
-IN_PROC_BROWSER_TEST_F(ToolbarImporterUtilsTest, NoCrash) {
-  // Regression test for http://crbug.com/89752
-  toolbar_importer_utils::IsGoogleGAIACookieInstalled(
-      base::Bind(&ToolbarImporterUtilsTest::Callback,
-                 base::Unretained(this)),
-      browser()->profile());
-  if (!did_run_) {
-    content::RunMessageLoop();
-  }
-  ASSERT_TRUE(did_run_);
-}
-
-}  // namespace
diff --git a/chrome/browser/infobars/infobar.cc b/chrome/browser/infobars/infobar.cc
index 8a37ced..079b571 100644
--- a/chrome/browser/infobars/infobar.cc
+++ b/chrome/browser/infobars/infobar.cc
@@ -37,7 +37,7 @@
 }
 
 // TODO(pkasting): Port Mac to use this.
-#if defined(TOOLKIT_VIEWS) || defined(TOOLKIT_GTK)
+#if defined(TOOLKIT_VIEWS) || defined(TOOLKIT_GTK) || defined(OS_ANDROID)
 
 InfoBar::InfoBar(InfoBarService* owner, InfoBarDelegate* delegate)
     : owner_(owner),
@@ -188,4 +188,4 @@
   }
 }
 
-#endif  // TOOLKIT_VIEWS || TOOLKIT_GTK
+#endif  // TOOLKIT_VIEWS || TOOLKIT_GTK || OS_ANDROID
diff --git a/chrome/browser/infobars/infobar.h b/chrome/browser/infobars/infobar.h
index eab823e..1c0fbb9 100644
--- a/chrome/browser/infobars/infobar.h
+++ b/chrome/browser/infobars/infobar.h
@@ -27,7 +27,7 @@
 typedef std::pair<InfoBarDelegate*, InfoBarDelegate*> InfoBarReplacedDetails;
 
 // TODO(pkasting): Port Mac to use this.
-#if defined(TOOLKIT_VIEWS) || defined(TOOLKIT_GTK)
+#if defined(TOOLKIT_VIEWS) || defined(TOOLKIT_GTK) || defined(OS_ANDROID)
 
 class InfoBarContainer;
 class InfoBarService;
diff --git a/chrome/browser/infobars/infobar_container.cc b/chrome/browser/infobars/infobar_container.cc
index bb13a07..9b8ce11 100644
--- a/chrome/browser/infobars/infobar_container.cc
+++ b/chrome/browser/infobars/infobar_container.cc
@@ -5,7 +5,7 @@
 #include "build/build_config.h"
 
 // TODO(pkasting): Port Mac to use this.
-#if defined(TOOLKIT_VIEWS) || defined(TOOLKIT_GTK)
+#if defined(TOOLKIT_VIEWS) || defined(TOOLKIT_GTK) || defined(OS_ANDROID)
 
 #include "chrome/browser/infobars/infobar_container.h"
 
@@ -265,4 +265,4 @@
           first_infobar_animation.GetCurrentValue());
 }
 
-#endif  // TOOLKIT_VIEWS || defined(TOOLKIT_GTK)
+#endif  // TOOLKIT_VIEWS || defined(TOOLKIT_GTK) || defined(OS_ANDROID)
diff --git a/chrome/browser/infobars/infobar_container.h b/chrome/browser/infobars/infobar_container.h
index c9d9ce2..0f2b241 100644
--- a/chrome/browser/infobars/infobar_container.h
+++ b/chrome/browser/infobars/infobar_container.h
@@ -8,7 +8,7 @@
 #include <vector>
 
 #include "base/compiler_specific.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/ui/search/search_model_observer.h"
 #include "chrome/common/search_types.h"
 #include "content/public/browser/notification_observer.h"
diff --git a/chrome/browser/infobars/infobars_browsertest.cc b/chrome/browser/infobars/infobars_browsertest.cc
index a9baaba..6b2c481 100644
--- a/chrome/browser/infobars/infobars_browsertest.cc
+++ b/chrome/browser/infobars/infobars_browsertest.cc
@@ -17,7 +17,7 @@
 #include "chrome/test/base/ui_test_utils.h"
 #include "chrome/test/ui/ui_test.h"
 #include "content/public/browser/notification_service.h"
-#include "net/test/spawned_test_server/spawned_test_server.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
 
 class InfoBarsTest : public InProcessBrowserTest {
  public:
@@ -51,10 +51,10 @@
 };
 
 IN_PROC_BROWSER_TEST_F(InfoBarsTest, TestInfoBarsCloseOnNewTheme) {
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   ui_test_utils::NavigateToURL(
-      browser(), test_server()->GetURL("files/simple.html"));
+      browser(), embedded_test_server()->GetURL("/simple.html"));
 
   content::WindowedNotificationObserver infobar_added_1(
         chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED,
@@ -63,7 +63,7 @@
   infobar_added_1.Wait();
 
   ui_test_utils::NavigateToURLWithDisposition(
-      browser(), test_server()->GetURL("files/simple.html"),
+      browser(), embedded_test_server()->GetURL("/simple.html"),
       NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
   content::WindowedNotificationObserver infobar_added_2(
         chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED,
diff --git a/chrome/browser/internal_auth.cc b/chrome/browser/internal_auth.cc
index 0c4fad0..ed8ff26 100644
--- a/chrome/browser/internal_auth.cc
+++ b/chrome/browser/internal_auth.cc
@@ -15,7 +15,7 @@
 #include "base/strings/string_util.h"
 #include "base/synchronization/lock.h"
 #include "base/threading/thread_checker.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "crypto/hmac.h"
 
diff --git a/chrome/browser/internal_auth_unittest.cc b/chrome/browser/internal_auth_unittest.cc
index 143b151..c504bd9 100644
--- a/chrome/browser/internal_auth_unittest.cc
+++ b/chrome/browser/internal_auth_unittest.cc
@@ -8,7 +8,7 @@
 
 #include "base/lazy_instance.h"
 #include "base/message_loop.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace chrome {
diff --git a/chrome/browser/intranet_redirect_detector.h b/chrome/browser/intranet_redirect_detector.h
index 68ef522..2a84791 100644
--- a/chrome/browser/intranet_redirect_detector.h
+++ b/chrome/browser/intranet_redirect_detector.h
@@ -12,10 +12,10 @@
 #include "base/memory/weak_ptr.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/network_change_notifier.h"
 #include "net/dns/host_resolver_proc.h"
 #include "net/url_request/url_fetcher_delegate.h"
+#include "url/gurl.h"
 
 class PrefRegistrySimple;
 
diff --git a/chrome/browser/invalidation/fake_invalidation_service.cc b/chrome/browser/invalidation/fake_invalidation_service.cc
new file mode 100644
index 0000000..a54a581
--- /dev/null
+++ b/chrome/browser/invalidation/fake_invalidation_service.cc
@@ -0,0 +1,62 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/invalidation/fake_invalidation_service.h"
+
+#include "chrome/browser/invalidation/invalidation_service_util.h"
+
+namespace invalidation {
+
+FakeInvalidationService::FakeInvalidationService()
+    : client_id_(GenerateInvalidatorClientId()) {
+}
+
+FakeInvalidationService::~FakeInvalidationService() {
+}
+
+void FakeInvalidationService::RegisterInvalidationHandler(
+      syncer::InvalidationHandler* handler) {
+  invalidator_registrar_.RegisterHandler(handler);
+}
+
+void FakeInvalidationService::UpdateRegisteredInvalidationIds(
+      syncer::InvalidationHandler* handler,
+      const syncer::ObjectIdSet& ids) {
+  invalidator_registrar_.UpdateRegisteredIds(handler, ids);
+}
+
+void FakeInvalidationService::UnregisterInvalidationHandler(
+      syncer::InvalidationHandler* handler) {
+  invalidator_registrar_.UnregisterHandler(handler);
+}
+
+void FakeInvalidationService::AcknowledgeInvalidation(
+      const invalidation::ObjectId& id,
+      const syncer::AckHandle& ack_handle) {
+  // TODO(sync): Use assertions to ensure this function is invoked correctly.
+}
+
+syncer::InvalidatorState FakeInvalidationService::GetInvalidatorState() const {
+  return syncer::INVALIDATIONS_ENABLED;
+}
+
+std::string FakeInvalidationService::GetInvalidatorClientId() const {
+  return client_id_;
+}
+
+void FakeInvalidationService::EmitInvalidationForTest(
+      const invalidation::ObjectId& object_id,
+      const std::string& payload) {
+  syncer::ObjectIdInvalidationMap invalidation_map;
+
+  syncer::Invalidation inv;
+  inv.payload = payload;
+  inv.ack_handle = syncer::AckHandle::CreateUnique();
+
+  invalidation_map.insert(std::make_pair(object_id, inv));
+
+  invalidator_registrar_.DispatchInvalidationsToHandlers(invalidation_map);
+}
+
+}  // namespace invalidation
diff --git a/chrome/browser/invalidation/fake_invalidation_service.h b/chrome/browser/invalidation/fake_invalidation_service.h
new file mode 100644
index 0000000..50aa619
--- /dev/null
+++ b/chrome/browser/invalidation/fake_invalidation_service.h
@@ -0,0 +1,48 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_INVALIDATION_FAKE_INVALIDATION_SERVICE_H_
+#define CHROME_BROWSER_INVALIDATION_FAKE_INVALIDATION_SERVICE_H_
+
+#include "chrome/browser/invalidation/invalidation_service.h"
+#include "sync/notifier/invalidator_registrar.h"
+
+namespace invalidation {
+
+// An InvalidationService that emits invalidations only when
+// its EmitInvalidationForTest method is called.
+class FakeInvalidationService : public InvalidationService {
+ public:
+  FakeInvalidationService();
+  virtual ~FakeInvalidationService();
+
+  virtual void RegisterInvalidationHandler(
+      syncer::InvalidationHandler* handler) OVERRIDE;
+  virtual void UpdateRegisteredInvalidationIds(
+      syncer::InvalidationHandler* handler,
+      const syncer::ObjectIdSet& ids) OVERRIDE;
+  virtual void UnregisterInvalidationHandler(
+      syncer::InvalidationHandler* handler) OVERRIDE;
+
+  virtual void AcknowledgeInvalidation(
+      const invalidation::ObjectId& id,
+      const syncer::AckHandle& ack_handle) OVERRIDE;
+
+  virtual syncer::InvalidatorState GetInvalidatorState() const OVERRIDE;
+  virtual std::string GetInvalidatorClientId() const OVERRIDE;
+
+  void EmitInvalidationForTest(
+      const invalidation::ObjectId& object_id,
+      const std::string& payload);
+
+ private:
+  std::string client_id_;
+  syncer::InvalidatorRegistrar invalidator_registrar_;
+
+  DISALLOW_COPY_AND_ASSIGN(FakeInvalidationService);
+};
+
+}  // namespace invalidation
+
+#endif  // CHROME_BROWSER_INVALIDATION_FAKE_INVALIDATION_SERVICE_H_
diff --git a/chrome/browser/invalidation/invalidation_frontend.h b/chrome/browser/invalidation/invalidation_frontend.h
deleted file mode 100644
index f8b61a5..0000000
--- a/chrome/browser/invalidation/invalidation_frontend.h
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_INVALIDATION_INVALIDATION_FRONTEND_H_
-#define CHROME_BROWSER_INVALIDATION_INVALIDATION_FRONTEND_H_
-
-#include "sync/notifier/invalidation_util.h"
-#include "sync/notifier/invalidator_state.h"
-
-namespace syncer {
-class InvalidationHandler;
-class AckHandle;
-}  // namespace syncer
-
-namespace invalidation {
-
-// Interface for classes that handle invalidation registrations and send out
-// invalidations to register handlers.
-//
-// Invalidation clients should follow the pattern below:
-//
-// When starting the client:
-//
-//   frontend->RegisterInvalidationHandler(client_handler);
-//
-// When the set of IDs to register changes for the client during its lifetime
-// (i.e., between calls to RegisterInvalidationHandler(client_handler) and
-// UnregisterInvalidationHandler(client_handler):
-//
-//   frontend->UpdateRegisteredInvalidationIds(client_handler, client_ids);
-//
-// To unregister for all invalidations:
-//
-//   frontend->UnregisterInvalidationHandler(client_handler);
-//
-// If an invalidation handler cares about the invalidator state, it should also
-// do the following when starting the client:
-//
-//   invalidator_state = frontend->GetInvalidatorState();
-//
-// It can also do the above in OnInvalidatorStateChange(), or it can use the
-// argument to OnInvalidatorStateChange().
-//
-// It is an error to have registered handlers when an InvalidationFrontend is
-// shut down; clients must ensure that they unregister themselves before then.
-//
-// TODO(rlarocque): This class should extend BrowserContextKeyedService.
-//
-// NOTE(akalin): Invalidations that come in during browser shutdown may get
-// dropped.  This won't matter once we have an Acknowledge API, though: see
-// http://crbug.com/78462 and http://crbug.com/124149.
-class InvalidationFrontend {
- public:
-  // Starts sending notifications to |handler|.  |handler| must not be NULL,
-  // and it must not already be registered.
-  //
-  // Handler registrations are persisted across restarts of sync.
-  virtual void RegisterInvalidationHandler(
-      syncer::InvalidationHandler* handler) = 0;
-
-  // Updates the set of ObjectIds associated with |handler|.  |handler| must
-  // not be NULL, and must already be registered.  An ID must be registered for
-  // at most one handler.
-  //
-  // Registered IDs are persisted across restarts of sync.
-  virtual void UpdateRegisteredInvalidationIds(
-      syncer::InvalidationHandler* handler,
-      const syncer::ObjectIdSet& ids) = 0;
-
-  // Stops sending notifications to |handler|.  |handler| must not be NULL, and
-  // it must already be registered.  Note that this doesn't unregister the IDs
-  // associated with |handler|.
-  //
-  // Handler registrations are persisted across restarts of sync.
-  virtual void UnregisterInvalidationHandler(
-      syncer::InvalidationHandler* handler) = 0;
-
-  // Sends an acknowledgement that an invalidation for |id| was successfully
-  // handled.
-  virtual void AcknowledgeInvalidation(const invalidation::ObjectId& id,
-                                       const syncer::AckHandle& ack_handle) = 0;
-
-  // Returns the current invalidator state.  When called from within
-  // InvalidationHandler::OnInvalidatorStateChange(), this must return
-  // the updated state.
-  virtual syncer::InvalidatorState GetInvalidatorState() const = 0;
-
- protected:
-  virtual ~InvalidationFrontend() { }
-};
-
-}  // namespace invalidation
-
-#endif  // CHROME_BROWSER_INVALIDATION_INVALIDATION_FRONTEND_H_
diff --git a/chrome/browser/invalidation/invalidation_frontend_test_template.cc b/chrome/browser/invalidation/invalidation_frontend_test_template.cc
deleted file mode 100644
index b454623..0000000
--- a/chrome/browser/invalidation/invalidation_frontend_test_template.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/invalidation/invalidation_frontend_test_template.h"
-
-namespace internal {
-
-BoundFakeInvalidationHandler::BoundFakeInvalidationHandler(
-    const invalidation::InvalidationFrontend& invalidator)
-    : invalidator_(invalidator),
-      last_retrieved_state_(syncer::DEFAULT_INVALIDATION_ERROR) {}
-
-BoundFakeInvalidationHandler::~BoundFakeInvalidationHandler() {}
-
-syncer::InvalidatorState
-BoundFakeInvalidationHandler::GetLastRetrievedState() const {
-  return last_retrieved_state_;
-}
-
-void BoundFakeInvalidationHandler::OnInvalidatorStateChange(
-    syncer::InvalidatorState state) {
-  FakeInvalidationHandler::OnInvalidatorStateChange(state);
-  last_retrieved_state_ = invalidator_.GetInvalidatorState();
-}
-
-}
diff --git a/chrome/browser/invalidation/invalidation_frontend_test_template.h b/chrome/browser/invalidation/invalidation_frontend_test_template.h
deleted file mode 100644
index 9643504..0000000
--- a/chrome/browser/invalidation/invalidation_frontend_test_template.h
+++ /dev/null
@@ -1,384 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This class defines tests that implementations of InvalidationFrontend should
-// pass in order to be conformant.  Here's how you use it to test your
-// implementation.
-//
-// Say your class is called MyInvalidationFrontend.  Then you need to define a
-// class called MyInvalidationFrontendTestDelegate in
-// my_invalidation_frontend_unittest.cc like this:
-//
-//   class MyInvalidationFrontendTestDelegate {
-//    public:
-//     MyInvalidationFrontendTestDelegate() ...
-//
-//     ~MyInvalidationFrontendTestDelegate() {
-//       // DestroyInvalidator() may not be explicitly called by tests.
-//       DestroyInvalidator();
-//     }
-//
-//     // Create the InvalidationFrontend implementation with the given params.
-//     void CreateInvalidationFrontend() {
-//       ...
-//     }
-//
-//     // Should return the InvalidationFrontend implementation.  Only called
-//     // after CreateInvalidator and before DestroyInvalidator.
-//     MyInvalidationFrontend* GetInvalidationFrontend() {
-//       ...
-//     }
-//
-//     // Destroy the InvalidationFrontend implementation.
-//     void DestroyInvalidationFrontend() {
-//       ...
-//     }
-//
-//     // The Trigger* functions below should block until the effects of
-//     // the call are visible on the current thread.
-//
-//     // Should cause OnInvalidatorStateChange() to be called on all
-//     // observers of the InvalidationFrontend implementation with the given
-//     // parameters.
-//     void TriggerOnInvalidatorStateChange(InvalidatorState state) {
-//       ...
-//     }
-//
-//     // Should cause OnIncomingInvalidation() to be called on all
-//     // observers of the InvalidationFrontend implementation with the given
-//     // parameters.
-//     void TriggerOnIncomingInvalidation(
-//         const ObjectIdInvalidationMap& invalidation_map) {
-//       ...
-//     }
-//   };
-//
-// The InvalidationFrontendTest test harness will have a member variable of
-// this delegate type and will call its functions in the various
-// tests.
-//
-// Then you simply #include this file as well as gtest.h and add the
-// following statement to my_sync_notifier_unittest.cc:
-//
-//   INSTANTIATE_TYPED_TEST_CASE_P(
-//       MyInvalidationFrontend,
-//       InvalidationFrontendTest,
-//       MyInvalidatorTestDelegate);
-//
-// Easy!
-
-#ifndef CHROME_BROWSER_INVALIDATION_INVALIDATION_FRONTEND_TEST_TEMPLATE_H_
-#define CHROME_BROWSER_INVALIDATION_INVALIDATION_FRONTEND_TEST_TEMPLATE_H_
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "chrome/browser/invalidation/invalidation_frontend.h"
-#include "google/cacheinvalidation/include/types.h"
-#include "google/cacheinvalidation/types.pb.h"
-#include "sync/notifier/fake_invalidation_handler.h"
-#include "sync/notifier/object_id_invalidation_map.h"
-#include "sync/notifier/object_id_invalidation_map_test_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-template <typename InvalidatorTestDelegate>
-class InvalidationFrontendTest : public testing::Test {
- protected:
-  // Note: The IDs defined below must be valid.  Otherwise they won't make it
-  // through the round-trip to ModelTypeInvalidationMap and back that the
-  // AndroidInvalidation test requires.
-  InvalidationFrontendTest()
-      : id1(ipc::invalidation::ObjectSource::CHROME_SYNC, "BOOKMARK"),
-        id2(ipc::invalidation::ObjectSource::CHROME_SYNC, "PREFERENCE"),
-        id3(ipc::invalidation::ObjectSource::CHROME_SYNC, "AUTOFILL"),
-        id4(ipc::invalidation::ObjectSource::CHROME_SYNC, "EXPERIMENTS") {
-  }
-
-  invalidation::InvalidationFrontend*
-  CreateAndInitializeInvalidationFrontend() {
-    this->delegate_.CreateInvalidationFrontend();
-    return this->delegate_.GetInvalidationFrontend();
-  }
-
-  InvalidatorTestDelegate delegate_;
-
-  const invalidation::ObjectId id1;
-  const invalidation::ObjectId id2;
-  const invalidation::ObjectId id3;
-  const invalidation::ObjectId id4;
-};
-
-TYPED_TEST_CASE_P(InvalidationFrontendTest);
-
-// Initialize the invalidator, register a handler, register some IDs for that
-// handler, and then unregister the handler, dispatching invalidations in
-// between.  The handler should only see invalidations when its registered and
-// its IDs are registered.
-TYPED_TEST_P(InvalidationFrontendTest, Basic) {
-  invalidation::InvalidationFrontend* const invalidator =
-      this->CreateAndInitializeInvalidationFrontend();
-
-  syncer::FakeInvalidationHandler handler;
-
-  invalidator->RegisterInvalidationHandler(&handler);
-
-  syncer::ObjectIdInvalidationMap states;
-  states[this->id1].payload = "1";
-  states[this->id2].payload = "2";
-  states[this->id3].payload = "3";
-
-  // Should be ignored since no IDs are registered to |handler|.
-  this->delegate_.TriggerOnIncomingInvalidation(states);
-  EXPECT_EQ(0, handler.GetInvalidationCount());
-
-  syncer::ObjectIdSet ids;
-  ids.insert(this->id1);
-  ids.insert(this->id2);
-  invalidator->UpdateRegisteredInvalidationIds(&handler, ids);
-
-  this->delegate_.TriggerOnInvalidatorStateChange(
-      syncer::INVALIDATIONS_ENABLED);
-  EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler.GetInvalidatorState());
-
-  syncer::ObjectIdInvalidationMap expected_states;
-  expected_states[this->id1].payload = "1";
-  expected_states[this->id2].payload = "2";
-
-  this->delegate_.TriggerOnIncomingInvalidation(states);
-  EXPECT_EQ(1, handler.GetInvalidationCount());
-  EXPECT_THAT(expected_states, Eq(handler.GetLastInvalidationMap()));
-
-  ids.erase(this->id1);
-  ids.insert(this->id3);
-  invalidator->UpdateRegisteredInvalidationIds(&handler, ids);
-
-  expected_states.erase(this->id1);
-  expected_states[this->id3].payload = "3";
-
-  // Removed object IDs should not be notified, newly-added ones should.
-  this->delegate_.TriggerOnIncomingInvalidation(states);
-  EXPECT_EQ(2, handler.GetInvalidationCount());
-  EXPECT_THAT(expected_states, Eq(handler.GetLastInvalidationMap()));
-
-  this->delegate_.TriggerOnInvalidatorStateChange(
-      syncer::TRANSIENT_INVALIDATION_ERROR);
-  EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
-            handler.GetInvalidatorState());
-
-  this->delegate_.TriggerOnInvalidatorStateChange(
-      syncer::INVALIDATION_CREDENTIALS_REJECTED);
-  EXPECT_EQ(syncer::INVALIDATION_CREDENTIALS_REJECTED,
-            handler.GetInvalidatorState());
-
-  invalidator->UnregisterInvalidationHandler(&handler);
-
-  // Should be ignored since |handler| isn't registered anymore.
-  this->delegate_.TriggerOnIncomingInvalidation(states);
-  EXPECT_EQ(2, handler.GetInvalidationCount());
-}
-
-// Register handlers and some IDs for those handlers, register a handler with
-// no IDs, and register a handler with some IDs but unregister it.  Then,
-// dispatch some invalidations and invalidations.  Handlers that are registered
-// should get invalidations, and the ones that have registered IDs should
-// receive invalidations for those IDs.
-TYPED_TEST_P(InvalidationFrontendTest, MultipleHandlers) {
-  invalidation::InvalidationFrontend* const invalidator =
-      this->CreateAndInitializeInvalidationFrontend();
-
-  syncer::FakeInvalidationHandler handler1;
-  syncer::FakeInvalidationHandler handler2;
-  syncer::FakeInvalidationHandler handler3;
-  syncer::FakeInvalidationHandler handler4;
-
-  invalidator->RegisterInvalidationHandler(&handler1);
-  invalidator->RegisterInvalidationHandler(&handler2);
-  invalidator->RegisterInvalidationHandler(&handler3);
-  invalidator->RegisterInvalidationHandler(&handler4);
-
-  {
-    syncer::ObjectIdSet ids;
-    ids.insert(this->id1);
-    ids.insert(this->id2);
-    invalidator->UpdateRegisteredInvalidationIds(&handler1, ids);
-  }
-
-  {
-    syncer::ObjectIdSet ids;
-    ids.insert(this->id3);
-    invalidator->UpdateRegisteredInvalidationIds(&handler2, ids);
-  }
-
-  // Don't register any IDs for handler3.
-
-  {
-    syncer::ObjectIdSet ids;
-    ids.insert(this->id4);
-    invalidator->UpdateRegisteredInvalidationIds(&handler4, ids);
-  }
-
-  invalidator->UnregisterInvalidationHandler(&handler4);
-
-  this->delegate_.TriggerOnInvalidatorStateChange(
-      syncer::INVALIDATIONS_ENABLED);
-  EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler1.GetInvalidatorState());
-  EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler2.GetInvalidatorState());
-  EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler3.GetInvalidatorState());
-  EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
-            handler4.GetInvalidatorState());
-
-  {
-    syncer::ObjectIdInvalidationMap states;
-    states[this->id1].payload = "1";
-    states[this->id2].payload = "2";
-    states[this->id3].payload = "3";
-    states[this->id4].payload = "4";
-    this->delegate_.TriggerOnIncomingInvalidation(states);
-
-    syncer::ObjectIdInvalidationMap expected_states;
-    expected_states[this->id1].payload = "1";
-    expected_states[this->id2].payload = "2";
-
-    EXPECT_EQ(1, handler1.GetInvalidationCount());
-    EXPECT_THAT(expected_states, Eq(handler1.GetLastInvalidationMap()));
-
-    expected_states.clear();
-    expected_states[this->id3].payload = "3";
-
-    EXPECT_EQ(1, handler2.GetInvalidationCount());
-    EXPECT_THAT(expected_states, Eq(handler2.GetLastInvalidationMap()));
-
-    EXPECT_EQ(0, handler3.GetInvalidationCount());
-    EXPECT_EQ(0, handler4.GetInvalidationCount());
-  }
-
-  this->delegate_.TriggerOnInvalidatorStateChange(
-      syncer::TRANSIENT_INVALIDATION_ERROR);
-  EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
-            handler1.GetInvalidatorState());
-  EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
-            handler2.GetInvalidatorState());
-  EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
-            handler3.GetInvalidatorState());
-  EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
-            handler4.GetInvalidatorState());
-
-  invalidator->UnregisterInvalidationHandler(&handler3);
-  invalidator->UnregisterInvalidationHandler(&handler2);
-  invalidator->UnregisterInvalidationHandler(&handler1);
-}
-
-// Make sure that passing an empty set to UpdateRegisteredInvalidationIds clears
-// the corresponding entries for the handler.
-TYPED_TEST_P(InvalidationFrontendTest, EmptySetUnregisters) {
-  invalidation::InvalidationFrontend* const invalidator =
-      this->CreateAndInitializeInvalidationFrontend();
-
-  syncer::FakeInvalidationHandler handler1;
-
-  // Control observer.
-  syncer::FakeInvalidationHandler handler2;
-
-  invalidator->RegisterInvalidationHandler(&handler1);
-  invalidator->RegisterInvalidationHandler(&handler2);
-
-  {
-    syncer::ObjectIdSet ids;
-    ids.insert(this->id1);
-    ids.insert(this->id2);
-    invalidator->UpdateRegisteredInvalidationIds(&handler1, ids);
-  }
-
-  {
-    syncer::ObjectIdSet ids;
-    ids.insert(this->id3);
-    invalidator->UpdateRegisteredInvalidationIds(&handler2, ids);
-  }
-
-  // Unregister the IDs for the first observer. It should not receive any
-  // further invalidations.
-  invalidator->UpdateRegisteredInvalidationIds(&handler1,
-                                               syncer::ObjectIdSet());
-
-  this->delegate_.TriggerOnInvalidatorStateChange(
-      syncer::INVALIDATIONS_ENABLED);
-  EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler1.GetInvalidatorState());
-  EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler2.GetInvalidatorState());
-
-  {
-    syncer::ObjectIdInvalidationMap states;
-    states[this->id1].payload = "1";
-    states[this->id2].payload = "2";
-    states[this->id3].payload = "3";
-    this->delegate_.TriggerOnIncomingInvalidation(states);
-    EXPECT_EQ(0, handler1.GetInvalidationCount());
-    EXPECT_EQ(1, handler2.GetInvalidationCount());
-  }
-
-  this->delegate_.TriggerOnInvalidatorStateChange(
-      syncer::TRANSIENT_INVALIDATION_ERROR);
-  EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
-            handler1.GetInvalidatorState());
-  EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
-            handler2.GetInvalidatorState());
-
-  invalidator->UnregisterInvalidationHandler(&handler2);
-  invalidator->UnregisterInvalidationHandler(&handler1);
-}
-
-namespace internal {
-
-// A FakeInvalidationHandler that is "bound" to a specific
-// InvalidationFrontend.  This is for cross-referencing state information with
-// the bound InvalidationFrontend.
-class BoundFakeInvalidationHandler : public syncer::FakeInvalidationHandler {
- public:
-  explicit BoundFakeInvalidationHandler(
-      const invalidation::InvalidationFrontend& invalidator);
-  virtual ~BoundFakeInvalidationHandler();
-
-  // Returns the last return value of GetInvalidatorState() on the
-  // bound invalidator from the last time the invalidator state
-  // changed.
-  syncer::InvalidatorState GetLastRetrievedState() const;
-
-  // InvalidationHandler implementation.
-  virtual void OnInvalidatorStateChange(
-      syncer::InvalidatorState state) OVERRIDE;
-
- private:
-  const invalidation::InvalidationFrontend& invalidator_;
-  syncer::InvalidatorState last_retrieved_state_;
-
-  DISALLOW_COPY_AND_ASSIGN(BoundFakeInvalidationHandler);
-};
-
-}  // namespace internal
-
-TYPED_TEST_P(InvalidationFrontendTest, GetInvalidatorStateAlwaysCurrent) {
-  invalidation::InvalidationFrontend* const invalidator =
-      this->CreateAndInitializeInvalidationFrontend();
-
-  internal::BoundFakeInvalidationHandler handler(*invalidator);
-  invalidator->RegisterInvalidationHandler(&handler);
-
-  this->delegate_.TriggerOnInvalidatorStateChange(
-      syncer::INVALIDATIONS_ENABLED);
-  EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler.GetInvalidatorState());
-  EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler.GetLastRetrievedState());
-
-  this->delegate_.TriggerOnInvalidatorStateChange(
-      syncer::TRANSIENT_INVALIDATION_ERROR);
-  EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
-            handler.GetInvalidatorState());
-  EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
-            handler.GetLastRetrievedState());
-
-  invalidator->UnregisterInvalidationHandler(&handler);
-}
-
-REGISTER_TYPED_TEST_CASE_P(InvalidationFrontendTest,
-                           Basic, MultipleHandlers, EmptySetUnregisters,
-                           GetInvalidatorStateAlwaysCurrent);
-
-#endif  // CHROME_BROWSER_INVALIDATION_INVALIDATION_FRONTEND_TEST_TEMPLATE_H_
diff --git a/chrome/browser/invalidation/invalidation_service.h b/chrome/browser/invalidation/invalidation_service.h
new file mode 100644
index 0000000..7ee0b73
--- /dev/null
+++ b/chrome/browser/invalidation/invalidation_service.h
@@ -0,0 +1,114 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_INVALIDATION_INVALIDATION_SERVICE_H_
+#define CHROME_BROWSER_INVALIDATION_INVALIDATION_SERVICE_H_
+
+#include "components/browser_context_keyed_service/browser_context_keyed_service.h"
+#include "sync/notifier/invalidation_util.h"
+#include "sync/notifier/invalidator_state.h"
+
+namespace syncer {
+class InvalidationHandler;
+class AckHandle;
+}  // namespace syncer
+
+namespace invalidation {
+
+// Interface for classes that handle invalidation registrations and send out
+// invalidations to register handlers.
+//
+// Invalidation clients should follow the pattern below:
+//
+// When starting the client:
+//
+//   frontend->RegisterInvalidationHandler(client_handler);
+//
+// When the set of IDs to register changes for the client during its lifetime
+// (i.e., between calls to RegisterInvalidationHandler(client_handler) and
+// UnregisterInvalidationHandler(client_handler):
+//
+//   frontend->UpdateRegisteredInvalidationIds(client_handler, client_ids);
+//
+// When shutting down the client for browser shutdown:
+//
+//   frontend->UnregisterInvalidationHandler(client_handler);
+//
+// Note that there's no call to UpdateRegisteredIds() -- this is because the
+// invalidation API persists registrations across browser restarts.
+//
+// When permanently shutting down the client, e.g. when disabling the related
+// feature:
+//
+//   frontend->UpdateRegisteredInvalidationIds(client_handler, ObjectIdSet());
+//   frontend->UnregisterInvalidationHandler(client_handler);
+//
+// If an invalidation handler cares about the invalidator state, it should also
+// do the following when starting the client:
+//
+//   invalidator_state = frontend->GetInvalidatorState();
+//
+// It can also do the above in OnInvalidatorStateChange(), or it can use the
+// argument to OnInvalidatorStateChange().
+//
+// It is an error to have registered handlers when an
+// InvalidationFrontend is shut down; clients must ensure that they
+// unregister themselves before then. (Depending on the
+// InvalidationFrontend, shutdown may be equivalent to destruction, or
+// a separate function call like Shutdown()).
+//
+// NOTE(akalin): Invalidations that come in during browser shutdown may get
+// dropped.  This won't matter once we have an Acknowledge API, though: see
+// http://crbug.com/78462 and http://crbug.com/124149.
+//
+// This class inherits from ProfileKeyedService to make it possible to correctly
+// cast from various InvalidationService implementations to ProfileKeyedService
+// in InvalidationServiceFactory.
+class InvalidationService : public BrowserContextKeyedService {
+ public:
+  // Starts sending notifications to |handler|.  |handler| must not be NULL,
+  // and it must not already be registered.
+  //
+  // Handler registrations are persisted across restarts of sync.
+  virtual void RegisterInvalidationHandler(
+      syncer::InvalidationHandler* handler) = 0;
+
+  // Updates the set of ObjectIds associated with |handler|.  |handler| must
+  // not be NULL, and must already be registered.  An ID must be registered for
+  // at most one handler.
+  //
+  // Registered IDs are persisted across restarts of sync.
+  virtual void UpdateRegisteredInvalidationIds(
+      syncer::InvalidationHandler* handler,
+      const syncer::ObjectIdSet& ids) = 0;
+
+  // Stops sending notifications to |handler|.  |handler| must not be NULL, and
+  // it must already be registered.  Note that this doesn't unregister the IDs
+  // associated with |handler|.
+  //
+  // Handler registrations are persisted across restarts of sync.
+  virtual void UnregisterInvalidationHandler(
+      syncer::InvalidationHandler* handler) = 0;
+
+  // Sends an acknowledgement that an invalidation for |id| was successfully
+  // handled.
+  virtual void AcknowledgeInvalidation(const invalidation::ObjectId& id,
+                                       const syncer::AckHandle& ack_handle) = 0;
+
+  // Returns the current invalidator state.  When called from within
+  // InvalidationHandler::OnInvalidatorStateChange(), this must return
+  // the updated state.
+  virtual syncer::InvalidatorState GetInvalidatorState() const = 0;
+
+  // Returns the ID belonging to this invalidation client.  Can be used to
+  // prevent the receipt of notifications of our own changes.
+  virtual std::string GetInvalidatorClientId() const = 0;
+
+ protected:
+  virtual ~InvalidationService() { }
+};
+
+}  // namespace invalidation
+
+#endif  // CHROME_BROWSER_INVALIDATION_INVALIDATION_SERVICE_H_
diff --git a/chrome/browser/invalidation/invalidation_service_android.h b/chrome/browser/invalidation/invalidation_service_android.h
index 6daef6a..244b1e7 100644
--- a/chrome/browser/invalidation/invalidation_service_android.h
+++ b/chrome/browser/invalidation/invalidation_service_android.h
@@ -8,7 +8,7 @@
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "base/threading/non_thread_safe.h"
-#include "chrome/browser/invalidation/invalidation_frontend.h"
+#include "chrome/browser/invalidation/invalidation_service.h"
 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
@@ -24,8 +24,7 @@
 // around Android's invalidations service.
 class InvalidationServiceAndroid
     : public base::NonThreadSafe,
-      public BrowserContextKeyedService,
-      public InvalidationFrontend,
+      public InvalidationService,
       public content::NotificationObserver {
  public:
   explicit InvalidationServiceAndroid(Profile* profile);
@@ -47,7 +46,7 @@
       const invalidation::ObjectId& id,
       const syncer::AckHandle& ack_handle) OVERRIDE;
   virtual syncer::InvalidatorState GetInvalidatorState() const OVERRIDE;
-  virtual std::string GetInvalidatorClientId() const;
+  virtual std::string GetInvalidatorClientId() const OVERRIDE;
 
   // content::NotificationObserver implementation.
   virtual void Observe(int type,
diff --git a/chrome/browser/invalidation/invalidation_service_android_unittest.cc b/chrome/browser/invalidation/invalidation_service_android_unittest.cc
index feadf24..9e332b2 100644
--- a/chrome/browser/invalidation/invalidation_service_android_unittest.cc
+++ b/chrome/browser/invalidation/invalidation_service_android_unittest.cc
@@ -4,8 +4,8 @@
 
 #include "chrome/browser/invalidation/invalidation_service_android.h"
 
-#include "chrome/browser/invalidation/invalidation_frontend_test_template.h"
 #include "chrome/browser/invalidation/invalidation_service_factory.h"
+#include "chrome/browser/invalidation/invalidation_service_test_template.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/browser/notification_service.h"
@@ -18,20 +18,20 @@
   InvalidationServiceAndroidTestDelegate() { }
 
   ~InvalidationServiceAndroidTestDelegate() {
-    DestroyInvalidationFrontend();
+    DestroyInvalidationService();
   }
 
-  void CreateInvalidationFrontend() {
+  void CreateInvalidationService() {
     profile_.reset(new TestingProfile());
     invalidation_service_android_.reset(
         new InvalidationServiceAndroid(profile_.get()));
   }
 
-  InvalidationFrontend* GetInvalidationFrontend() {
+  InvalidationService* GetInvalidationService() {
     return invalidation_service_android_.get();
   }
 
-  void DestroyInvalidationFrontend() {
+  void DestroyInvalidationService() {
     invalidation_service_android_->Shutdown();
   }
 
@@ -55,7 +55,7 @@
 };
 
 INSTANTIATE_TYPED_TEST_CASE_P(
-    AndroidInvalidationServiceTest, InvalidationFrontendTest,
+    AndroidInvalidationServiceTest, InvalidationServiceTest,
     InvalidationServiceAndroidTestDelegate);
 
 }  // namespace invalidation
diff --git a/chrome/browser/invalidation/invalidation_service_factory.cc b/chrome/browser/invalidation/invalidation_service_factory.cc
index 0fa857b..2085417 100644
--- a/chrome/browser/invalidation/invalidation_service_factory.cc
+++ b/chrome/browser/invalidation/invalidation_service_factory.cc
@@ -4,13 +4,19 @@
 
 #include "chrome/browser/invalidation/invalidation_service_factory.h"
 
-#include "chrome/browser/invalidation/invalidation_frontend.h"
+#include "base/prefs/pref_registry.h"
+#include "chrome/browser/invalidation/fake_invalidation_service.h"
+#include "chrome/browser/invalidation/invalidation_service.h"
 #include "chrome/browser/invalidation/invalidation_service_android.h"
+#include "chrome/browser/invalidation/invalidator_storage.h"
 #include "chrome/browser/invalidation/p2p_invalidation_service.h"
 #include "chrome/browser/invalidation/ticl_invalidation_service.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/signin/profile_oauth2_token_service.h"
+#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
+#include "chrome/browser/signin/token_service.h"
 #include "chrome/browser/signin/token_service_factory.h"
 #include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
 
@@ -18,14 +24,12 @@
 
 namespace invalidation {
 
-// TODO(rlarocque): Re-enable this once InvalidationFrontend can
-// extend BrowserContextKeyedService.
-// // static
-// InvalidationFrontend* InvalidationServiceFactory::GetForProfile(
-//     Profile* profile) {
-//   return static_cast<InvalidationFrontend*>(
-//       GetInstance()->GetServiceForBrowserContext(profile, true));
-// }
+// static
+InvalidationService* InvalidationServiceFactory::GetForProfile(
+    Profile* profile) {
+  return static_cast<InvalidationService*>(
+      GetInstance()->GetServiceForBrowserContext(profile, true));
+}
 
 // static
 InvalidationServiceFactory* InvalidationServiceFactory::GetInstance() {
@@ -35,24 +39,52 @@
 InvalidationServiceFactory::InvalidationServiceFactory()
     : BrowserContextKeyedServiceFactory(
         "InvalidationService",
-        BrowserContextDependencyManager::GetInstance()) {
+        BrowserContextDependencyManager::GetInstance()),
+      build_fake_invalidators_(false) {
 #if !defined(OS_ANDROID)
   DependsOn(SigninManagerFactory::GetInstance());
-  DependsOn(TokenServiceFactory::GetInstance());
+  DependsOn(ProfileOAuth2TokenServiceFactory::GetInstance());
 #endif
 }
 
 InvalidationServiceFactory::~InvalidationServiceFactory() {}
 
-// static
-BrowserContextKeyedService*
-InvalidationServiceFactory::BuildP2PInvalidationServiceFor(Profile* profile) {
+namespace {
+
+BrowserContextKeyedService* BuildP2PInvalidationService(
+    content::BrowserContext* context) {
+  Profile* profile = static_cast<Profile*>(context);
   return new P2PInvalidationService(profile);
 }
 
+BrowserContextKeyedService* BuildFakeInvalidationService(
+    content::BrowserContext* context) {
+  return new FakeInvalidationService();
+}
+
+}  // namespace
+
+void InvalidationServiceFactory::SetBuildOnlyFakeInvalidatorsForTest(
+    bool test_mode_enabled) {
+  build_fake_invalidators_ = test_mode_enabled;
+}
+
+P2PInvalidationService*
+InvalidationServiceFactory::BuildAndUseP2PInvalidationServiceForTest(
+    content::BrowserContext* context) {
+  BrowserContextKeyedService* service =
+      SetTestingFactoryAndUse(context, BuildP2PInvalidationService);
+  return static_cast<P2PInvalidationService*>(service);
+}
+
 BrowserContextKeyedService* InvalidationServiceFactory::BuildServiceInstanceFor(
     content::BrowserContext* context) const {
   Profile* profile = static_cast<Profile*>(context);
+
+  if (build_fake_invalidators_) {
+    return BuildFakeInvalidationService(context);
+  }
+
 #if defined(OS_ANDROID)
   InvalidationServiceAndroid* service = new InvalidationServiceAndroid(profile);
   return service;
@@ -60,12 +92,22 @@
   SigninManagerBase* signin_manager =
       SigninManagerFactory::GetForProfile(profile);
   TokenService* token_service = TokenServiceFactory::GetForProfile(profile);
+  OAuth2TokenService* oauth2_token_service =
+      ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
 
   TiclInvalidationService* service = new TiclInvalidationService(
-      signin_manager, token_service, profile);
+      signin_manager,
+      token_service,
+      oauth2_token_service,
+      profile);
   service->Init();
   return service;
 #endif
 }
 
+void InvalidationServiceFactory::RegisterUserPrefs(
+    user_prefs::PrefRegistrySyncable* registry) {
+  InvalidatorStorage::RegisterUserPrefs(registry);
+}
+
 }  // namespace invalidation
diff --git a/chrome/browser/invalidation/invalidation_service_factory.h b/chrome/browser/invalidation/invalidation_service_factory.h
index da6900a..fa2828a 100644
--- a/chrome/browser/invalidation/invalidation_service_factory.h
+++ b/chrome/browser/invalidation/invalidation_service_factory.h
@@ -9,15 +9,22 @@
 #include "base/memory/singleton.h"
 #include "components/browser_context_keyed_service/browser_context_keyed_service_factory.h"
 
+namespace user_prefs {
+class PrefRegistrySyncable;
+}
+
 namespace syncer {
 class Invalidator;
 }
 
-class InvalidationFrontend;
 class Profile;
 
 namespace invalidation {
 
+class InvalidationService;
+class P2PInvalidationService;
+class FakeInvalidationService;
+
 // A BrowserContextKeyedServiceFactory to construct InvalidationServices.  The
 // implementation of the InvalidationService may be completely different on
 // different platforms; this class should help to hide this complexity.  It also
@@ -25,16 +32,18 @@
 // on invalidations.
 class InvalidationServiceFactory : public BrowserContextKeyedServiceFactory {
  public:
-  // TODO(rlarocque): Re-enable this once InvalidationFrontend can extend
-  // BrowserContextKeyedService.
-  // static InvalidationFrontend* GetForProfile(Profile* profile);
+  static InvalidationService* GetForProfile(Profile* profile);
 
   static InvalidationServiceFactory* GetInstance();
 
-  static BrowserContextKeyedService* BuildP2PInvalidationServiceFor(
-      Profile* profile);
-  static BrowserContextKeyedService* BuildTestServiceInstanceFor(
-      Profile* profile);
+  // A helper function to set this factory to return FakeInvalidationServices
+  // instead of the default InvalidationService objects.
+  void SetBuildOnlyFakeInvalidatorsForTest(bool test_mode_enabled);
+
+  // These helper functions to set the factory to build a test-only type of
+  // invalidator and return the instance immeidately.
+  P2PInvalidationService* BuildAndUseP2PInvalidationServiceForTest(
+      content::BrowserContext* context);
 
  private:
   friend struct DefaultSingletonTraits<InvalidationServiceFactory>;
@@ -44,10 +53,12 @@
 
   // BrowserContextKeyedServiceFactory:
   virtual BrowserContextKeyedService* BuildServiceInstanceFor(
-      content::BrowserContext* profile) const OVERRIDE;
-  // TODO(rlarocque): Use this class, not InvalidatorStorage, to register
-  // for user prefs.
-  // virtual void RegisterUserPrefs(PrefRegistrySyncable* registry) OVERRIDE;
+      content::BrowserContext* context) const OVERRIDE;
+  virtual void RegisterUserPrefs(
+      user_prefs::PrefRegistrySyncable* registry) OVERRIDE;
+
+  // If true, this factory will return only FakeInvalidationService instances.
+  bool build_fake_invalidators_;
 
   DISALLOW_COPY_AND_ASSIGN(InvalidationServiceFactory);
 };
diff --git a/chrome/browser/invalidation/invalidation_service_test_template.cc b/chrome/browser/invalidation/invalidation_service_test_template.cc
new file mode 100644
index 0000000..1b591e8
--- /dev/null
+++ b/chrome/browser/invalidation/invalidation_service_test_template.cc
@@ -0,0 +1,27 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/invalidation/invalidation_service_test_template.h"
+
+namespace internal {
+
+BoundFakeInvalidationHandler::BoundFakeInvalidationHandler(
+    const invalidation::InvalidationService& invalidator)
+    : invalidator_(invalidator),
+      last_retrieved_state_(syncer::DEFAULT_INVALIDATION_ERROR) {}
+
+BoundFakeInvalidationHandler::~BoundFakeInvalidationHandler() {}
+
+syncer::InvalidatorState
+BoundFakeInvalidationHandler::GetLastRetrievedState() const {
+  return last_retrieved_state_;
+}
+
+void BoundFakeInvalidationHandler::OnInvalidatorStateChange(
+    syncer::InvalidatorState state) {
+  FakeInvalidationHandler::OnInvalidatorStateChange(state);
+  last_retrieved_state_ = invalidator_.GetInvalidatorState();
+}
+
+}  // namespace internal
diff --git a/chrome/browser/invalidation/invalidation_service_test_template.h b/chrome/browser/invalidation/invalidation_service_test_template.h
new file mode 100644
index 0000000..baad132
--- /dev/null
+++ b/chrome/browser/invalidation/invalidation_service_test_template.h
@@ -0,0 +1,384 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This class defines tests that implementations of InvalidationService should
+// pass in order to be conformant.  Here's how you use it to test your
+// implementation.
+//
+// Say your class is called MyInvalidationService.  Then you need to define a
+// class called MyInvalidationServiceTestDelegate in
+// my_invalidation_frontend_unittest.cc like this:
+//
+//   class MyInvalidationServiceTestDelegate {
+//    public:
+//     MyInvalidationServiceTestDelegate() ...
+//
+//     ~MyInvalidationServiceTestDelegate() {
+//       // DestroyInvalidator() may not be explicitly called by tests.
+//       DestroyInvalidator();
+//     }
+//
+//     // Create the InvalidationService implementation with the given params.
+//     void CreateInvalidationService() {
+//       ...
+//     }
+//
+//     // Should return the InvalidationService implementation.  Only called
+//     // after CreateInvalidator and before DestroyInvalidator.
+//     MyInvalidationService* GetInvalidationService() {
+//       ...
+//     }
+//
+//     // Destroy the InvalidationService implementation.
+//     void DestroyInvalidationService() {
+//       ...
+//     }
+//
+//     // The Trigger* functions below should block until the effects of
+//     // the call are visible on the current thread.
+//
+//     // Should cause OnInvalidatorStateChange() to be called on all
+//     // observers of the InvalidationService implementation with the given
+//     // parameters.
+//     void TriggerOnInvalidatorStateChange(InvalidatorState state) {
+//       ...
+//     }
+//
+//     // Should cause OnIncomingInvalidation() to be called on all
+//     // observers of the InvalidationService implementation with the given
+//     // parameters.
+//     void TriggerOnIncomingInvalidation(
+//         const ObjectIdInvalidationMap& invalidation_map) {
+//       ...
+//     }
+//   };
+//
+// The InvalidationServiceTest test harness will have a member variable of
+// this delegate type and will call its functions in the various
+// tests.
+//
+// Then you simply #include this file as well as gtest.h and add the
+// following statement to my_sync_notifier_unittest.cc:
+//
+//   INSTANTIATE_TYPED_TEST_CASE_P(
+//       MyInvalidationService,
+//       InvalidationServiceTest,
+//       MyInvalidatorTestDelegate);
+//
+// Easy!
+
+#ifndef CHROME_BROWSER_INVALIDATION_INVALIDATION_SERVICE_TEST_TEMPLATE_H_
+#define CHROME_BROWSER_INVALIDATION_INVALIDATION_SERVICE_TEST_TEMPLATE_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "chrome/browser/invalidation/invalidation_service.h"
+#include "google/cacheinvalidation/include/types.h"
+#include "google/cacheinvalidation/types.pb.h"
+#include "sync/notifier/fake_invalidation_handler.h"
+#include "sync/notifier/object_id_invalidation_map.h"
+#include "sync/notifier/object_id_invalidation_map_test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+template <typename InvalidatorTestDelegate>
+class InvalidationServiceTest : public testing::Test {
+ protected:
+  // Note: The IDs defined below must be valid.  Otherwise they won't make it
+  // through the round-trip to ModelTypeInvalidationMap and back that the
+  // AndroidInvalidation test requires.
+  InvalidationServiceTest()
+      : id1(ipc::invalidation::ObjectSource::CHROME_SYNC, "BOOKMARK"),
+        id2(ipc::invalidation::ObjectSource::CHROME_SYNC, "PREFERENCE"),
+        id3(ipc::invalidation::ObjectSource::CHROME_SYNC, "AUTOFILL"),
+        id4(ipc::invalidation::ObjectSource::CHROME_SYNC, "EXPERIMENTS") {
+  }
+
+  invalidation::InvalidationService*
+  CreateAndInitializeInvalidationService() {
+    this->delegate_.CreateInvalidationService();
+    return this->delegate_.GetInvalidationService();
+  }
+
+  InvalidatorTestDelegate delegate_;
+
+  const invalidation::ObjectId id1;
+  const invalidation::ObjectId id2;
+  const invalidation::ObjectId id3;
+  const invalidation::ObjectId id4;
+};
+
+TYPED_TEST_CASE_P(InvalidationServiceTest);
+
+// Initialize the invalidator, register a handler, register some IDs for that
+// handler, and then unregister the handler, dispatching invalidations in
+// between.  The handler should only see invalidations when its registered and
+// its IDs are registered.
+TYPED_TEST_P(InvalidationServiceTest, Basic) {
+  invalidation::InvalidationService* const invalidator =
+      this->CreateAndInitializeInvalidationService();
+
+  syncer::FakeInvalidationHandler handler;
+
+  invalidator->RegisterInvalidationHandler(&handler);
+
+  syncer::ObjectIdInvalidationMap states;
+  states[this->id1].payload = "1";
+  states[this->id2].payload = "2";
+  states[this->id3].payload = "3";
+
+  // Should be ignored since no IDs are registered to |handler|.
+  this->delegate_.TriggerOnIncomingInvalidation(states);
+  EXPECT_EQ(0, handler.GetInvalidationCount());
+
+  syncer::ObjectIdSet ids;
+  ids.insert(this->id1);
+  ids.insert(this->id2);
+  invalidator->UpdateRegisteredInvalidationIds(&handler, ids);
+
+  this->delegate_.TriggerOnInvalidatorStateChange(
+      syncer::INVALIDATIONS_ENABLED);
+  EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler.GetInvalidatorState());
+
+  syncer::ObjectIdInvalidationMap expected_states;
+  expected_states[this->id1].payload = "1";
+  expected_states[this->id2].payload = "2";
+
+  this->delegate_.TriggerOnIncomingInvalidation(states);
+  EXPECT_EQ(1, handler.GetInvalidationCount());
+  EXPECT_THAT(expected_states, Eq(handler.GetLastInvalidationMap()));
+
+  ids.erase(this->id1);
+  ids.insert(this->id3);
+  invalidator->UpdateRegisteredInvalidationIds(&handler, ids);
+
+  expected_states.erase(this->id1);
+  expected_states[this->id3].payload = "3";
+
+  // Removed object IDs should not be notified, newly-added ones should.
+  this->delegate_.TriggerOnIncomingInvalidation(states);
+  EXPECT_EQ(2, handler.GetInvalidationCount());
+  EXPECT_THAT(expected_states, Eq(handler.GetLastInvalidationMap()));
+
+  this->delegate_.TriggerOnInvalidatorStateChange(
+      syncer::TRANSIENT_INVALIDATION_ERROR);
+  EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
+            handler.GetInvalidatorState());
+
+  this->delegate_.TriggerOnInvalidatorStateChange(
+      syncer::INVALIDATIONS_ENABLED);
+  EXPECT_EQ(syncer::INVALIDATIONS_ENABLED,
+            handler.GetInvalidatorState());
+
+  invalidator->UnregisterInvalidationHandler(&handler);
+
+  // Should be ignored since |handler| isn't registered anymore.
+  this->delegate_.TriggerOnIncomingInvalidation(states);
+  EXPECT_EQ(2, handler.GetInvalidationCount());
+}
+
+// Register handlers and some IDs for those handlers, register a handler with
+// no IDs, and register a handler with some IDs but unregister it.  Then,
+// dispatch some invalidations and invalidations.  Handlers that are registered
+// should get invalidations, and the ones that have registered IDs should
+// receive invalidations for those IDs.
+TYPED_TEST_P(InvalidationServiceTest, MultipleHandlers) {
+  invalidation::InvalidationService* const invalidator =
+      this->CreateAndInitializeInvalidationService();
+
+  syncer::FakeInvalidationHandler handler1;
+  syncer::FakeInvalidationHandler handler2;
+  syncer::FakeInvalidationHandler handler3;
+  syncer::FakeInvalidationHandler handler4;
+
+  invalidator->RegisterInvalidationHandler(&handler1);
+  invalidator->RegisterInvalidationHandler(&handler2);
+  invalidator->RegisterInvalidationHandler(&handler3);
+  invalidator->RegisterInvalidationHandler(&handler4);
+
+  {
+    syncer::ObjectIdSet ids;
+    ids.insert(this->id1);
+    ids.insert(this->id2);
+    invalidator->UpdateRegisteredInvalidationIds(&handler1, ids);
+  }
+
+  {
+    syncer::ObjectIdSet ids;
+    ids.insert(this->id3);
+    invalidator->UpdateRegisteredInvalidationIds(&handler2, ids);
+  }
+
+  // Don't register any IDs for handler3.
+
+  {
+    syncer::ObjectIdSet ids;
+    ids.insert(this->id4);
+    invalidator->UpdateRegisteredInvalidationIds(&handler4, ids);
+  }
+
+  invalidator->UnregisterInvalidationHandler(&handler4);
+
+  this->delegate_.TriggerOnInvalidatorStateChange(
+      syncer::INVALIDATIONS_ENABLED);
+  EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler1.GetInvalidatorState());
+  EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler2.GetInvalidatorState());
+  EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler3.GetInvalidatorState());
+  EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
+            handler4.GetInvalidatorState());
+
+  {
+    syncer::ObjectIdInvalidationMap states;
+    states[this->id1].payload = "1";
+    states[this->id2].payload = "2";
+    states[this->id3].payload = "3";
+    states[this->id4].payload = "4";
+    this->delegate_.TriggerOnIncomingInvalidation(states);
+
+    syncer::ObjectIdInvalidationMap expected_states;
+    expected_states[this->id1].payload = "1";
+    expected_states[this->id2].payload = "2";
+
+    EXPECT_EQ(1, handler1.GetInvalidationCount());
+    EXPECT_THAT(expected_states, Eq(handler1.GetLastInvalidationMap()));
+
+    expected_states.clear();
+    expected_states[this->id3].payload = "3";
+
+    EXPECT_EQ(1, handler2.GetInvalidationCount());
+    EXPECT_THAT(expected_states, Eq(handler2.GetLastInvalidationMap()));
+
+    EXPECT_EQ(0, handler3.GetInvalidationCount());
+    EXPECT_EQ(0, handler4.GetInvalidationCount());
+  }
+
+  this->delegate_.TriggerOnInvalidatorStateChange(
+      syncer::TRANSIENT_INVALIDATION_ERROR);
+  EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
+            handler1.GetInvalidatorState());
+  EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
+            handler2.GetInvalidatorState());
+  EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
+            handler3.GetInvalidatorState());
+  EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
+            handler4.GetInvalidatorState());
+
+  invalidator->UnregisterInvalidationHandler(&handler3);
+  invalidator->UnregisterInvalidationHandler(&handler2);
+  invalidator->UnregisterInvalidationHandler(&handler1);
+}
+
+// Make sure that passing an empty set to UpdateRegisteredInvalidationIds clears
+// the corresponding entries for the handler.
+TYPED_TEST_P(InvalidationServiceTest, EmptySetUnregisters) {
+  invalidation::InvalidationService* const invalidator =
+      this->CreateAndInitializeInvalidationService();
+
+  syncer::FakeInvalidationHandler handler1;
+
+  // Control observer.
+  syncer::FakeInvalidationHandler handler2;
+
+  invalidator->RegisterInvalidationHandler(&handler1);
+  invalidator->RegisterInvalidationHandler(&handler2);
+
+  {
+    syncer::ObjectIdSet ids;
+    ids.insert(this->id1);
+    ids.insert(this->id2);
+    invalidator->UpdateRegisteredInvalidationIds(&handler1, ids);
+  }
+
+  {
+    syncer::ObjectIdSet ids;
+    ids.insert(this->id3);
+    invalidator->UpdateRegisteredInvalidationIds(&handler2, ids);
+  }
+
+  // Unregister the IDs for the first observer. It should not receive any
+  // further invalidations.
+  invalidator->UpdateRegisteredInvalidationIds(&handler1,
+                                               syncer::ObjectIdSet());
+
+  this->delegate_.TriggerOnInvalidatorStateChange(
+      syncer::INVALIDATIONS_ENABLED);
+  EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler1.GetInvalidatorState());
+  EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler2.GetInvalidatorState());
+
+  {
+    syncer::ObjectIdInvalidationMap states;
+    states[this->id1].payload = "1";
+    states[this->id2].payload = "2";
+    states[this->id3].payload = "3";
+    this->delegate_.TriggerOnIncomingInvalidation(states);
+    EXPECT_EQ(0, handler1.GetInvalidationCount());
+    EXPECT_EQ(1, handler2.GetInvalidationCount());
+  }
+
+  this->delegate_.TriggerOnInvalidatorStateChange(
+      syncer::TRANSIENT_INVALIDATION_ERROR);
+  EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
+            handler1.GetInvalidatorState());
+  EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
+            handler2.GetInvalidatorState());
+
+  invalidator->UnregisterInvalidationHandler(&handler2);
+  invalidator->UnregisterInvalidationHandler(&handler1);
+}
+
+namespace internal {
+
+// A FakeInvalidationHandler that is "bound" to a specific
+// InvalidationService.  This is for cross-referencing state information with
+// the bound InvalidationService.
+class BoundFakeInvalidationHandler : public syncer::FakeInvalidationHandler {
+ public:
+  explicit BoundFakeInvalidationHandler(
+      const invalidation::InvalidationService& invalidator);
+  virtual ~BoundFakeInvalidationHandler();
+
+  // Returns the last return value of GetInvalidatorState() on the
+  // bound invalidator from the last time the invalidator state
+  // changed.
+  syncer::InvalidatorState GetLastRetrievedState() const;
+
+  // InvalidationHandler implementation.
+  virtual void OnInvalidatorStateChange(
+      syncer::InvalidatorState state) OVERRIDE;
+
+ private:
+  const invalidation::InvalidationService& invalidator_;
+  syncer::InvalidatorState last_retrieved_state_;
+
+  DISALLOW_COPY_AND_ASSIGN(BoundFakeInvalidationHandler);
+};
+
+}  // namespace internal
+
+TYPED_TEST_P(InvalidationServiceTest, GetInvalidatorStateAlwaysCurrent) {
+  invalidation::InvalidationService* const invalidator =
+      this->CreateAndInitializeInvalidationService();
+
+  internal::BoundFakeInvalidationHandler handler(*invalidator);
+  invalidator->RegisterInvalidationHandler(&handler);
+
+  this->delegate_.TriggerOnInvalidatorStateChange(
+      syncer::INVALIDATIONS_ENABLED);
+  EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler.GetInvalidatorState());
+  EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler.GetLastRetrievedState());
+
+  this->delegate_.TriggerOnInvalidatorStateChange(
+      syncer::TRANSIENT_INVALIDATION_ERROR);
+  EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
+            handler.GetInvalidatorState());
+  EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
+            handler.GetLastRetrievedState());
+
+  invalidator->UnregisterInvalidationHandler(&handler);
+}
+
+REGISTER_TYPED_TEST_CASE_P(InvalidationServiceTest,
+                           Basic, MultipleHandlers, EmptySetUnregisters,
+                           GetInvalidatorStateAlwaysCurrent);
+
+#endif  // CHROME_BROWSER_INVALIDATION_INVALIDATION_SERVICE_TEST_TEMPLATE_H_
diff --git a/chrome/browser/invalidation/p2p_invalidation_service.h b/chrome/browser/invalidation/p2p_invalidation_service.h
index b624688..bbb18b9 100644
--- a/chrome/browser/invalidation/p2p_invalidation_service.h
+++ b/chrome/browser/invalidation/p2p_invalidation_service.h
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/threading/non_thread_safe.h"
-#include "chrome/browser/invalidation/invalidation_frontend.h"
+#include "chrome/browser/invalidation/invalidation_service.h"
 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
 #include "sync/notifier/object_id_invalidation_map.h"
 
@@ -23,8 +23,7 @@
 // only in tests, where we're unable to connect to a real invalidations server.
 class P2PInvalidationService
     : public base::NonThreadSafe,
-      public BrowserContextKeyedService,
-      public InvalidationFrontend {
+      public InvalidationService {
  public:
   explicit P2PInvalidationService(Profile* profile);
   virtual ~P2PInvalidationService();
@@ -32,7 +31,7 @@
   // Overrides BrowserContextKeyedService method.
   virtual void Shutdown() OVERRIDE;
 
-  // InvalidationFrontend implementation.
+  // InvalidationService implementation.
   // It is an error to have registered handlers when Shutdown() is called.
   virtual void RegisterInvalidationHandler(
       syncer::InvalidationHandler* handler) OVERRIDE;
@@ -45,7 +44,7 @@
       const invalidation::ObjectId& id,
       const syncer::AckHandle& ack_handle) OVERRIDE;
   virtual syncer::InvalidatorState GetInvalidatorState() const OVERRIDE;
-  virtual std::string GetInvalidatorClientId() const;
+  virtual std::string GetInvalidatorClientId() const OVERRIDE;
 
   void UpdateCredentials(const std::string& username,
                          const std::string& password);
diff --git a/chrome/browser/invalidation/ticl_invalidation_service.cc b/chrome/browser/invalidation/ticl_invalidation_service.cc
index bfee8f0..11a9759 100644
--- a/chrome/browser/invalidation/ticl_invalidation_service.cc
+++ b/chrome/browser/invalidation/ticl_invalidation_service.cc
@@ -6,9 +6,11 @@
 
 #include "base/command_line.h"
 #include "chrome/browser/invalidation/invalidation_service_util.h"
+#include "chrome/browser/managed_mode/managed_user_service.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/signin/profile_oauth2_token_service.h"
+#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
-#include "chrome/browser/signin/token_service.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "content/public/browser/notification_service.h"
 #include "google_apis/gaia/gaia_constants.h"
@@ -16,15 +18,52 @@
 #include "sync/notifier/invalidator_state.h"
 #include "sync/notifier/non_blocking_invalidator.h"
 
+static const char* kOAuth2Scopes[] = {
+  GaiaConstants::kGoogleTalkOAuth2Scope
+};
+
+static const net::BackoffEntry::Policy kRequestAccessTokenBackoffPolicy = {
+  // Number of initial errors (in sequence) to ignore before applying
+  // exponential back-off rules.
+  0,
+
+  // Initial delay for exponential back-off in ms.
+  2000,
+
+  // Factor by which the waiting time will be multiplied.
+  2,
+
+  // Fuzzing percentage. ex: 10% will spread requests randomly
+  // between 90%-100% of the calculated time.
+  0.2, // 20%
+
+  // Maximum amount of time we are willing to delay our request in ms.
+  // TODO(pavely): crbug.com/246686 ProfileSyncService should retry
+  // RequestAccessToken on connection state change after backoff
+  1000 * 3600 * 4, // 4 hours.
+
+  // Time to keep an entry from being discarded even when it
+  // has no significant state, -1 to never discard.
+  -1,
+
+  // Don't use initial delay unless the last request was an error.
+  false,
+};
+
 namespace invalidation {
 
-TiclInvalidationService::TiclInvalidationService(SigninManagerBase* signin,
-                                                 TokenService* token_service,
-                                                 Profile* profile)
-  : profile_(profile),
-    signin_manager_(signin),
-    token_service_(token_service),
-    invalidator_registrar_(new syncer::InvalidatorRegistrar()) { }
+TiclInvalidationService::TiclInvalidationService(
+    SigninManagerBase* signin,
+    TokenService* token_service,
+    OAuth2TokenService* oauth2_token_service,
+    Profile* profile)
+    : profile_(profile),
+      signin_manager_(signin),
+      token_service_(token_service),
+      oauth2_token_service_(oauth2_token_service),
+      invalidator_registrar_(new syncer::InvalidatorRegistrar()),
+      request_access_token_backoff_(&kRequestAccessTokenBackoffPolicy) {
+}
 
 TiclInvalidationService::~TiclInvalidationService() {
   DCHECK(CalledOnValidThread());
@@ -41,20 +80,24 @@
   }
 
   if (IsReadyToStart()) {
-    Start();
+    StartInvalidator();
   }
 
   notification_registrar_.Add(this,
+                              chrome::NOTIFICATION_GOOGLE_SIGNED_OUT,
+                              content::Source<Profile>(profile_));
+  notification_registrar_.Add(this,
                               chrome::NOTIFICATION_TOKEN_AVAILABLE,
                               content::Source<TokenService>(token_service_));
   notification_registrar_.Add(this,
-                              chrome::NOTIFICATION_GOOGLE_SIGNED_OUT,
-                              content::Source<Profile>(profile_));
+                              chrome::NOTIFICATION_TOKENS_CLEARED,
+                              content::Source<TokenService>(token_service_));
 }
 
 void TiclInvalidationService::InitForTest(syncer::Invalidator* invalidator) {
-  // Here we perform the equivalent of Init() and Start(), but with some minor
-  // changes to account for the fact that we're injecting the invalidator.
+  // Here we perform the equivalent of Init() and StartInvalidator(), but with
+  // some minor changes to account for the fact that we're injecting the
+  // invalidator.
   invalidator_.reset(invalidator);
 
   invalidator_->RegisterHandler(this);
@@ -129,16 +172,15 @@
 
   switch (type) {
     case chrome::NOTIFICATION_TOKEN_AVAILABLE: {
-      const TokenService::TokenAvailableDetails& token_details =
-          *(content::Details<const TokenService::TokenAvailableDetails>(
-                  details).ptr());
-      if (token_details.service() == GaiaConstants::kSyncService) {
-        DCHECK(IsReadyToStart());
-        if (!IsStarted()) {
-          Start();
-        } else {
-          UpdateToken();
-        }
+      if (!IsStarted() && IsReadyToStart()) {
+        StartInvalidator();
+      }
+      break;
+    }
+    case chrome::NOTIFICATION_TOKENS_CLEARED: {
+      access_token_.clear();
+      if (IsStarted()) {
+        UpdateInvalidatorCredentials();
       }
       break;
     }
@@ -152,6 +194,68 @@
   }
 }
 
+void TiclInvalidationService::RequestAccessToken() {
+  // Only one active request at a time.
+  if (access_token_request_ != NULL)
+    return;
+  request_access_token_retry_timer_.Stop();
+  OAuth2TokenService::ScopeSet oauth2_scopes;
+  for (size_t i = 0; i < arraysize(kOAuth2Scopes); i++)
+    oauth2_scopes.insert(kOAuth2Scopes[i]);
+  // Invalidate previous token, otherwise token service will return the same
+  // token again.
+  oauth2_token_service_->InvalidateToken(oauth2_scopes, access_token_);
+  access_token_.clear();
+  access_token_request_ =
+      oauth2_token_service_->StartRequest(oauth2_scopes, this);
+}
+
+void TiclInvalidationService::OnGetTokenSuccess(
+    const OAuth2TokenService::Request* request,
+    const std::string& access_token,
+    const base::Time& expiration_time) {
+  DCHECK_EQ(access_token_request_, request);
+  access_token_request_.reset();
+  // Reset backoff time after successful response.
+  request_access_token_backoff_.Reset();
+  access_token_ = access_token;
+  if (!IsStarted() && IsReadyToStart()) {
+    StartInvalidator();
+  } else {
+    UpdateInvalidatorCredentials();
+  }
+}
+
+void TiclInvalidationService::OnGetTokenFailure(
+    const OAuth2TokenService::Request* request,
+    const GoogleServiceAuthError& error) {
+  DCHECK_EQ(access_token_request_, request);
+  DCHECK_NE(error.state(), GoogleServiceAuthError::NONE);
+  access_token_request_.reset();
+  switch (error.state()) {
+    case GoogleServiceAuthError::CONNECTION_FAILED:
+    case GoogleServiceAuthError::SERVICE_UNAVAILABLE: {
+      // Transient error. Retry after some time.
+      request_access_token_backoff_.InformOfRequest(false);
+      request_access_token_retry_timer_.Start(
+            FROM_HERE,
+            request_access_token_backoff_.GetTimeUntilRelease(),
+            base::Bind(&TiclInvalidationService::RequestAccessToken,
+                       base::Unretained(this)));
+      break;
+    }
+    case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS: {
+      // This is a real auth error.
+      invalidator_registrar_->UpdateInvalidatorState(
+          syncer::INVALIDATION_CREDENTIALS_REJECTED);
+      break;
+    }
+    default: {
+      // We have no way to notify the user of this.  Do nothing.
+    }
+  }
+}
+
 void TiclInvalidationService::OnInvalidatorStateChange(
     syncer::InvalidatorState state) {
   invalidator_registrar_->UpdateInvalidatorState(state);
@@ -172,19 +276,25 @@
 }
 
 bool TiclInvalidationService::IsReadyToStart() {
-  if (signin_manager_->GetAuthenticatedUsername().empty()) {
-    DVLOG(2) << "Not starting TiclInvalidationService: user is not signed in.";
+  if (ManagedUserService::ProfileIsManaged(profile_)) {
+    DVLOG(2) << "Not starting TiclInvalidationService: User is managed.";
     return false;
   }
 
-  if (!token_service_) {
+  if (signin_manager_->GetAuthenticatedUsername().empty()) {
+    DVLOG(2) << "Not starting TiclInvalidationService: User is not signed in.";
+    return false;
+  }
+
+  if (!oauth2_token_service_) {
     DVLOG(2)
         << "Not starting TiclInvalidationService: TokenService unavailable.";
     return false;
   }
 
-  if (!token_service_->HasTokenForService(GaiaConstants::kSyncService)) {
-    DVLOG(2) << "Not starting TiclInvalidationService: Sync token unavailable.";
+  if (!oauth2_token_service_->RefreshTokenIsAvailable()) {
+    DVLOG(2)
+        << "Not starting TiclInvalidationServce: Waiting for refresh token.";
     return false;
   }
 
@@ -195,15 +305,24 @@
   return invalidator_.get() != NULL;
 }
 
-void TiclInvalidationService::Start() {
+void TiclInvalidationService::StartInvalidator() {
   DCHECK(CalledOnValidThread());
   DCHECK(!invalidator_);
   DCHECK(invalidator_storage_);
   DCHECK(!invalidator_storage_->GetInvalidatorClientId().empty());
 
+  if (access_token_.empty()) {
+    DVLOG(1)
+        << "TiclInvalidationService: "
+        << "Deferring start until we have an access token.";
+    RequestAccessToken();
+    return;
+  }
+
   notifier::NotifierOptions options =
       ParseNotifierOptions(*CommandLine::ForCurrentProcess());
   options.request_context_getter = profile_->GetRequestContext();
+  options.auth_mechanism = "X-OAUTH2";
   invalidator_.reset(new syncer::NonBlockingInvalidator(
           options,
           invalidator_storage_->GetInvalidatorClientId(),
@@ -213,7 +332,7 @@
               invalidator_storage_->AsWeakPtr()),
           content::GetUserAgent(GURL())));
 
-  UpdateToken();
+  UpdateInvalidatorCredentials();
 
   invalidator_->RegisterHandler(this);
   invalidator_->UpdateRegisteredIds(
@@ -221,16 +340,14 @@
       invalidator_registrar_->GetAllRegisteredIds());
 }
 
-void TiclInvalidationService::UpdateToken() {
+void TiclInvalidationService::UpdateInvalidatorCredentials() {
   std::string email = signin_manager_->GetAuthenticatedUsername();
-  DCHECK(!email.empty()) << "Expected user to be signed in.";
-  DCHECK(token_service_->HasTokenForService(GaiaConstants::kSyncService));
 
-  std::string sync_token = token_service_->GetTokenForService(
-      GaiaConstants::kSyncService);
+  DCHECK(!email.empty()) << "Expected user to be signed in.";
+  DCHECK(!access_token_.empty());
 
   DVLOG(2) << "UpdateCredentials: " << email;
-  invalidator_->UpdateCredentials(email, sync_token);
+  invalidator_->UpdateCredentials(email, access_token_);
 }
 
 void TiclInvalidationService::StopInvalidator() {
@@ -240,7 +357,11 @@
 }
 
 void TiclInvalidationService::Logout() {
-  StopInvalidator();
+  request_access_token_retry_timer_.Stop();
+
+  if (IsStarted()) {
+    StopInvalidator();
+  }
 
   // This service always expects to have a valid invalidator storage.
   // So we must not only clear the old one, but also start a new one.
diff --git a/chrome/browser/invalidation/ticl_invalidation_service.h b/chrome/browser/invalidation/ticl_invalidation_service.h
index dde6606..2403817 100644
--- a/chrome/browser/invalidation/ticl_invalidation_service.h
+++ b/chrome/browser/invalidation/ticl_invalidation_service.h
@@ -7,18 +7,20 @@
 
 #include "base/memory/scoped_ptr.h"
 #include "base/threading/non_thread_safe.h"
-#include "chrome/browser/invalidation/invalidation_frontend.h"
+#include "base/timer/timer.h"
+#include "chrome/browser/invalidation/invalidation_service.h"
 #include "chrome/browser/invalidation/invalidator_storage.h"
-#include "chrome/browser/signin/signin_global_error.h"
+#include "chrome/browser/signin/oauth2_token_service.h"
+#include "chrome/browser/signin/token_service.h"
 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
+#include "net/base/backoff_entry.h"
 #include "sync/notifier/invalidation_handler.h"
 #include "sync/notifier/invalidator_registrar.h"
 
 class Profile;
 class SigninManagerBase;
-class TokenService;
 
 namespace syncer {
 class Invalidator;
@@ -30,19 +32,20 @@
 // It provides invalidations for desktop platforms (Win, Mac, Linux).
 class TiclInvalidationService
     : public base::NonThreadSafe,
-      public BrowserContextKeyedService,
-      public InvalidationFrontend,
+      public InvalidationService,
       public content::NotificationObserver,
+      public OAuth2TokenService::Consumer,
       public syncer::InvalidationHandler {
  public:
   TiclInvalidationService(SigninManagerBase* signin,
                           TokenService* token_service,
+                          OAuth2TokenService* oauth2_token_service,
                           Profile* profile);
   virtual ~TiclInvalidationService();
 
   void Init();
 
-  // InvalidationFrontend implementation.
+  // InvalidationService implementation.
   // It is an error to have registered handlers when Shutdown() is called.
   virtual void RegisterInvalidationHandler(
       syncer::InvalidationHandler* handler) OVERRIDE;
@@ -55,13 +58,24 @@
       const invalidation::ObjectId& id,
       const syncer::AckHandle& ack_handle) OVERRIDE;
   virtual syncer::InvalidatorState GetInvalidatorState() const OVERRIDE;
-  virtual std::string GetInvalidatorClientId() const;
+  virtual std::string GetInvalidatorClientId() const OVERRIDE;
 
   // content::NotificationObserver implementation.
   virtual void Observe(int type,
                        const content::NotificationSource& source,
                        const content::NotificationDetails& details) OVERRIDE;
 
+  void RequestAccessToken();
+
+  // OAuth2TokenService::Consumer implementation
+  virtual void OnGetTokenSuccess(
+      const OAuth2TokenService::Request* request,
+      const std::string& access_token,
+      const base::Time& expiration_time) OVERRIDE;
+  virtual void OnGetTokenFailure(
+      const OAuth2TokenService::Request* request,
+      const GoogleServiceAuthError& error) OVERRIDE;
+
   // syncer::InvalidationHandler implementation.
   virtual void OnInvalidatorStateChange(
       syncer::InvalidatorState state) OVERRIDE;
@@ -81,14 +95,15 @@
   bool IsReadyToStart();
   bool IsStarted();
 
-  void Start();
-  void UpdateToken();
+  void StartInvalidator();
+  void UpdateInvalidatorCredentials();
   void StopInvalidator();
   void Logout();
 
   Profile *const profile_;
   SigninManagerBase *const signin_manager_;
   TokenService *const token_service_;
+  OAuth2TokenService *const oauth2_token_service_;
 
   scoped_ptr<syncer::InvalidatorRegistrar> invalidator_registrar_;
   scoped_ptr<InvalidatorStorage> invalidator_storage_;
@@ -96,9 +111,19 @@
 
   content::NotificationRegistrar notification_registrar_;
 
+  // TiclInvalidationService needs to remember access token in order to
+  // invalidate it with OAuth2TokenService.
+  std::string access_token_;
+
+  // TiclInvalidationService needs to hold reference to access_token_request_
+  // for the duration of request in order to receive callbacks.
+  scoped_ptr<OAuth2TokenService::Request> access_token_request_;
+  base::OneShotTimer<TiclInvalidationService> request_access_token_retry_timer_;
+  net::BackoffEntry request_access_token_backoff_;
+
   DISALLOW_COPY_AND_ASSIGN(TiclInvalidationService);
 };
 
-}
+}  // namespace invalidation
 
 #endif  // CHROME_BROWSER_INVALIDATION_TICL_INVALIDATION_SERVICE_H_
diff --git a/chrome/browser/invalidation/ticl_invalidation_service_unittest.cc b/chrome/browser/invalidation/ticl_invalidation_service_unittest.cc
index 225dc0a..314e8a7 100644
--- a/chrome/browser/invalidation/ticl_invalidation_service_unittest.cc
+++ b/chrome/browser/invalidation/ticl_invalidation_service_unittest.cc
@@ -4,8 +4,8 @@
 
 #include "chrome/browser/invalidation/ticl_invalidation_service.h"
 
-#include "chrome/browser/invalidation/invalidation_frontend_test_template.h"
 #include "chrome/browser/invalidation/invalidation_service_factory.h"
+#include "chrome/browser/invalidation/invalidation_service_test_template.h"
 #include "chrome/test/base/testing_profile.h"
 #include "sync/notifier/fake_invalidation_handler.h"
 #include "sync/notifier/fake_invalidator.h"
@@ -19,22 +19,22 @@
   TiclInvalidationServiceTestDelegate() { }
 
   ~TiclInvalidationServiceTestDelegate() {
-    DestroyInvalidationFrontend();
+    DestroyInvalidationService();
   }
 
-  void CreateInvalidationFrontend() {
+  void CreateInvalidationService() {
     fake_invalidator_ = new syncer::FakeInvalidator();
     profile_.reset(new TestingProfile());
     invalidation_service_.reset(
-        new TiclInvalidationService(NULL, NULL, profile_.get()));
+        new TiclInvalidationService(NULL, NULL, NULL, profile_.get()));
     invalidation_service_->InitForTest(fake_invalidator_);
   }
 
-  InvalidationFrontend* GetInvalidationFrontend() {
+  InvalidationService* GetInvalidationService() {
     return invalidation_service_.get();
   }
 
-  void DestroyInvalidationFrontend() {
+  void DestroyInvalidationService() {
     invalidation_service_->Shutdown();
   }
 
@@ -53,7 +53,7 @@
 };
 
 INSTANTIATE_TYPED_TEST_CASE_P(
-    TiclInvalidationServiceTest, InvalidationFrontendTest,
+    TiclInvalidationServiceTest, InvalidationServiceTest,
     TiclInvalidationServiceTestDelegate);
 
 }  // namespace invalidation
diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc
index f67c1ae..d68b6e5 100644
--- a/chrome/browser/io_thread.cc
+++ b/chrome/browser/io_thread.cc
@@ -692,6 +692,8 @@
     std::string spdy_mode =
         command_line.GetSwitchValueASCII(switches::kUseSpdy);
     EnableSpdy(spdy_mode);
+  } else if (command_line.HasSwitch(switches::kEnableSpdy4a2)) {
+    net::HttpStreamFactory::EnableNpnSpdy4a2();
   } else if (command_line.HasSwitch(switches::kDisableSpdy31)) {
     net::HttpStreamFactory::EnableNpnSpdy3();
   } else if (command_line.HasSwitch(switches::kEnableNpn)) {
diff --git a/chrome/browser/jankometer.cc b/chrome/browser/jankometer.cc
index af96cfc..5fa82c3 100644
--- a/chrome/browser/jankometer.cc
+++ b/chrome/browser/jankometer.cc
@@ -17,7 +17,7 @@
 #include "base/strings/string_util.h"
 #include "base/threading/thread.h"
 #include "base/threading/watchdog.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "build/build_config.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/common/chrome_switches.h"
diff --git a/chrome/browser/jumplist_win.cc b/chrome/browser/jumplist_win.cc
index d78a9fd..4447141 100644
--- a/chrome/browser/jumplist_win.cc
+++ b/chrome/browser/jumplist_win.cc
@@ -40,7 +40,6 @@
 #include "chrome/common/url_constants.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_source.h"
-#include "googleurl/src/gurl.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "third_party/skia/include/core/SkBitmap.h"
@@ -49,6 +48,7 @@
 #include "ui/gfx/favicon_size.h"
 #include "ui/gfx/icon_util.h"
 #include "ui/gfx/image/image_family.h"
+#include "url/gurl.h"
 
 using content::BrowserThread;
 
@@ -736,8 +736,8 @@
   // icon files.
   base::FilePath icon_dir_old(icon_dir_.value() + L"Old");
   if (file_util::PathExists(icon_dir_old))
-    file_util::Delete(icon_dir_old, true);
-  file_util::Move(icon_dir_, icon_dir_old);
+    base::Delete(icon_dir_old, true);
+  base::Move(icon_dir_, icon_dir_old);
   file_util::CreateDirectory(icon_dir_);
 
   // Create temporary icon files for shortcuts in the "Most Visited" category.
diff --git a/chrome/browser/loadtimes_extension_bindings_browsertest.cc b/chrome/browser/loadtimes_extension_bindings_browsertest.cc
index efca60a..24ab846 100644
--- a/chrome/browser/loadtimes_extension_bindings_browsertest.cc
+++ b/chrome/browser/loadtimes_extension_bindings_browsertest.cc
@@ -8,7 +8,7 @@
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test_utils.h"
-#include "net/test/spawned_test_server/spawned_test_server.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
 
 class LoadtimesExtensionBindingsTest : public InProcessBrowserTest {
  public:
@@ -45,8 +45,8 @@
 
 IN_PROC_BROWSER_TEST_F(LoadtimesExtensionBindingsTest,
                        LoadTimesSameAfterClientInDocNavigation) {
-  ASSERT_TRUE(test_server()->Start());
-  GURL plain_url = test_server()->GetURL("blank");
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+  GURL plain_url = embedded_test_server()->GetURL("/simple.html");
   ui_test_utils::NavigateToURL(browser(), plain_url);
   content::WebContents* contents =
       browser()->tab_strip_model()->GetActiveWebContents();
@@ -61,8 +61,8 @@
 
 IN_PROC_BROWSER_TEST_F(LoadtimesExtensionBindingsTest,
                        LoadTimesSameAfterUserInDocNavigation) {
-  ASSERT_TRUE(test_server()->Start());
-  GURL plain_url = test_server()->GetURL("blank");
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+  GURL plain_url = embedded_test_server()->GetURL("/simple.html");
   GURL hash_url(plain_url.spec() + "#");
   ui_test_utils::NavigateToURL(browser(), plain_url);
   content::WebContents* contents =
diff --git a/chrome/browser/local_discovery/local_domain_resolver.cc b/chrome/browser/local_discovery/local_domain_resolver.cc
new file mode 100644
index 0000000..bb5e563
--- /dev/null
+++ b/chrome/browser/local_discovery/local_domain_resolver.cc
@@ -0,0 +1,82 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/bind.h"
+#include "chrome/browser/local_discovery/local_domain_resolver.h"
+#include "net/dns/dns_protocol.h"
+#include "net/dns/record_parsed.h"
+#include "net/dns/record_rdata.h"
+
+namespace local_discovery {
+
+LocalDomainResolver::LocalDomainResolver(net::MDnsClient* mdns_client,
+                                         const std::string& domain,
+                                         net::AddressFamily address_family,
+                                         const IPAddressCallback& callback)
+    : domain_(domain), address_family_(address_family), callback_(callback),
+      transaction_failures_(0), mdns_client_(mdns_client) {
+}
+
+LocalDomainResolver::~LocalDomainResolver() {
+}
+
+bool LocalDomainResolver::Start() {
+  if (address_family_ == net::ADDRESS_FAMILY_IPV4 ||
+      address_family_ == net::ADDRESS_FAMILY_UNSPECIFIED) {
+    transaction_a_ = CreateTransaction(net::dns_protocol::kTypeA);
+    if (!transaction_a_->Start())
+      return false;
+  }
+
+  if (address_family_ == net::ADDRESS_FAMILY_IPV6 ||
+      address_family_ == net::ADDRESS_FAMILY_UNSPECIFIED) {
+    transaction_aaaa_ = CreateTransaction(net::dns_protocol::kTypeAAAA);
+    if (!transaction_aaaa_->Start())
+      return false;
+  }
+
+  return true;
+}
+
+scoped_ptr<net::MDnsTransaction> LocalDomainResolver::CreateTransaction(
+    uint16 type) {
+  return mdns_client_->CreateTransaction(
+      type, domain_, net::MDnsTransaction::SINGLE_RESULT |
+                     net::MDnsTransaction::QUERY_CACHE |
+                     net::MDnsTransaction::QUERY_NETWORK,
+      base::Bind(&LocalDomainResolver::OnTransactionComplete,
+                 base::Unretained(this)));
+}
+
+void LocalDomainResolver::OnTransactionComplete(
+    net::MDnsTransaction::Result result, const net::RecordParsed* record) {
+  if (result != net::MDnsTransaction::RESULT_RECORD &&
+      address_family_ == net::ADDRESS_FAMILY_UNSPECIFIED) {
+    transaction_failures_++;
+
+    if (transaction_failures_ < 2) {
+      return;
+    }
+  }
+
+  transaction_a_.reset();
+  transaction_aaaa_.reset();
+
+  net::IPAddressNumber address;
+  if (result == net::MDnsTransaction::RESULT_RECORD) {
+    if (record->type() == net::dns_protocol::kTypeA) {
+      const net::ARecordRdata* rdata = record->rdata<net::ARecordRdata>();
+      DCHECK(rdata);
+      address = rdata->address();
+    } else {
+      DCHECK(record->type() == net::dns_protocol::kTypeAAAA);
+      const net::AAAARecordRdata* rdata = record->rdata<net::AAAARecordRdata>();
+      address = rdata->address();
+    }
+  }
+
+  callback_.Run(result == net::MDnsTransaction::RESULT_RECORD, address);
+}
+
+}  // namespace local_discovery
diff --git a/chrome/browser/local_discovery/local_domain_resolver.h b/chrome/browser/local_discovery/local_domain_resolver.h
new file mode 100644
index 0000000..6c0c50d
--- /dev/null
+++ b/chrome/browser/local_discovery/local_domain_resolver.h
@@ -0,0 +1,56 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+
+#include "base/callback.h"
+#include "net/base/address_family.h"
+#include "net/base/net_util.h"
+#include "net/dns/mdns_client.h"
+
+#ifndef CHROME_BROWSER_LOCAL_DISCOVERY_LOCAL_DOMAIN_RESOLVER_H_
+#define CHROME_BROWSER_LOCAL_DISCOVERY_LOCAL_DOMAIN_RESOLVER_H_
+
+namespace local_discovery {
+
+class LocalDomainResolver {
+ public:
+  typedef base::Callback<void(bool, const net::IPAddressNumber&)>
+      IPAddressCallback;
+
+  // |mdns_client| must outlive the LocalDomainResolver.
+  LocalDomainResolver(net::MDnsClient* mdns_client,
+                      const std::string& domain,
+                      net::AddressFamily address_family,
+                      const IPAddressCallback& callback);
+  ~LocalDomainResolver();
+
+  bool Start();
+
+  const std::string& domain() { return domain_; }
+
+ private:
+  void OnTransactionComplete(
+      net::MDnsTransaction::Result result,
+      const net::RecordParsed* record);
+
+  scoped_ptr<net::MDnsTransaction> CreateTransaction(uint16 type);
+
+  std::string domain_;
+  net::AddressFamily address_family_;
+  IPAddressCallback callback_;
+
+  scoped_ptr<net::MDnsTransaction> transaction_a_;
+  scoped_ptr<net::MDnsTransaction> transaction_aaaa_;
+
+  int transaction_failures_;
+
+  net::MDnsClient* mdns_client_;
+
+  DISALLOW_COPY_AND_ASSIGN(LocalDomainResolver);
+};
+
+}  // namespace local_discovery
+
+#endif  // CHROME_BROWSER_LOCAL_DISCOVERY_LOCAL_DOMAIN_RESOLVER_H_
diff --git a/chrome/browser/local_discovery/local_domain_resolver_unittest.cc b/chrome/browser/local_discovery/local_domain_resolver_unittest.cc
new file mode 100644
index 0000000..96e6088
--- /dev/null
+++ b/chrome/browser/local_discovery/local_domain_resolver_unittest.cc
@@ -0,0 +1,168 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/local_discovery/local_domain_resolver.h"
+#include "net/dns/mdns_client_impl.h"
+#include "net/dns/mock_mdns_socket_factory.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::_;
+
+namespace local_discovery {
+
+namespace {
+
+const char kSamplePacketA[] = {
+  // Header
+  '\x00', '\x00',               // ID is zeroed out
+  '\x81', '\x80',               // Standard query response, RA, no error
+  '\x00', '\x00',               // No questions (for simplicity)
+  '\x00', '\x01',               // 1 RR (answers)
+  '\x00', '\x00',               // 0 authority RRs
+  '\x00', '\x00',               // 0 additional RRs
+
+  '\x07', 'm', 'y', 'h', 'e', 'l', 'l', 'o',
+  '\x05', 'l', 'o', 'c', 'a', 'l',
+  '\x00',
+  '\x00', '\x01',        // TYPE is A.
+  '\x00', '\x01',        // CLASS is IN.
+  '\x00', '\x00',        // TTL (4 bytes) is 16 seconds.
+  '\x00', '\x10',
+  '\x00', '\x04',        // RDLENGTH is 4 bytes.
+  '\x01', '\x02',
+  '\x03', '\x04',
+};
+
+const char kSamplePacketAAAA[] = {
+  // Header
+  '\x00', '\x00',               // ID is zeroed out
+  '\x81', '\x80',               // Standard query response, RA, no error
+  '\x00', '\x00',               // No questions (for simplicity)
+  '\x00', '\x01',               // 1 RR (answers)
+  '\x00', '\x00',               // 0 authority RRs
+  '\x00', '\x00',               // 0 additional RRs
+
+  '\x07', 'm', 'y', 'h', 'e', 'l', 'l', 'o',
+  '\x05', 'l', 'o', 'c', 'a', 'l',
+  '\x00',
+  '\x00', '\x1C',        // TYPE is AAAA.
+  '\x00', '\x01',        // CLASS is IN.
+  '\x00', '\x00',        // TTL (4 bytes) is 16 seconds.
+  '\x00', '\x10',
+  '\x00', '\x10',        // RDLENGTH is 4 bytes.
+  '\x00', '\x0A', '\x00', '\x00',
+  '\x00', '\x00', '\x00', '\x00',
+  '\x00', '\x01', '\x00', '\x02',
+  '\x00', '\x03', '\x00', '\x04',
+};
+
+class LocalDomainResolverTest : public testing::Test {
+ public:
+  LocalDomainResolverTest() : socket_factory_(new net::MockMDnsSocketFactory),
+    mdns_client_(
+        scoped_ptr<net::MDnsConnection::SocketFactory>(
+            socket_factory_)) {
+  }
+
+  ~LocalDomainResolverTest() {
+  }
+
+  void AddressCallback(bool resolved, const net::IPAddressNumber& address) {
+    if (address == net::IPAddressNumber()) {
+      AddressCallbackInternal(resolved, "");
+    } else {
+      AddressCallbackInternal(resolved, net::IPAddressToString(address));
+    }
+  }
+
+  void RunFor(base::TimeDelta time_period) {
+    base::CancelableCallback<void()> callback(base::Bind(
+        &base::MessageLoop::Quit,
+        base::Unretained(base::MessageLoop::current())));
+    base::MessageLoop::current()->PostDelayedTask(
+        FROM_HERE, callback.callback(), time_period);
+
+    base::MessageLoop::current()->Run();
+    callback.Cancel();
+  }
+
+  MOCK_METHOD2(AddressCallbackInternal,
+               void(bool resolved, std::string address));
+
+  net::MockMDnsSocketFactory* socket_factory_;
+  net::MDnsClientImpl mdns_client_;
+  base::MessageLoop message_loop_;
+};
+
+TEST_F(LocalDomainResolverTest, ResolveDomainA) {
+  LocalDomainResolver resolver(
+      &mdns_client_, "myhello.local", net::ADDRESS_FAMILY_IPV4,
+      base::Bind(&LocalDomainResolverTest::AddressCallback,
+                 base::Unretained(this)));
+
+  EXPECT_CALL(*socket_factory_, OnSendTo(_))
+      .Times(2);  // Twice per query
+
+  EXPECT_TRUE(resolver.Start());
+
+  EXPECT_CALL(*this, AddressCallbackInternal(true, "1.2.3.4"));
+
+  socket_factory_->SimulateReceive(
+      kSamplePacketA, sizeof(kSamplePacketA));
+}
+
+TEST_F(LocalDomainResolverTest, ResolveDomainAAAA) {
+  LocalDomainResolver resolver(
+      &mdns_client_, "myhello.local", net::ADDRESS_FAMILY_IPV6,
+      base::Bind(&LocalDomainResolverTest::AddressCallback,
+                 base::Unretained(this)));
+
+  EXPECT_CALL(*socket_factory_, OnSendTo(_))
+      .Times(2);  // Twice per query
+
+  EXPECT_TRUE(resolver.Start());
+
+  EXPECT_CALL(*this, AddressCallbackInternal(true, "a::1:2:3:4"));
+
+  socket_factory_->SimulateReceive(
+      kSamplePacketAAAA, sizeof(kSamplePacketAAAA));
+}
+
+TEST_F(LocalDomainResolverTest, ResolveDomainAny) {
+  LocalDomainResolver resolver(
+      &mdns_client_, "myhello.local", net::ADDRESS_FAMILY_UNSPECIFIED,
+      base::Bind(&LocalDomainResolverTest::AddressCallback,
+                 base::Unretained(this)));
+
+  EXPECT_CALL(*socket_factory_, OnSendTo(_))
+      .Times(4);  // Twice per query
+
+  EXPECT_TRUE(resolver.Start());
+
+  EXPECT_CALL(*this, AddressCallbackInternal(true, "a::1:2:3:4"));
+
+  socket_factory_->SimulateReceive(
+      kSamplePacketAAAA, sizeof(kSamplePacketAAAA));
+}
+
+TEST_F(LocalDomainResolverTest, ResolveDomainNone) {
+  LocalDomainResolver resolver(
+      &mdns_client_, "myhello.local", net::ADDRESS_FAMILY_UNSPECIFIED,
+      base::Bind(&LocalDomainResolverTest::AddressCallback,
+                 base::Unretained(this)));
+
+  EXPECT_CALL(*socket_factory_, OnSendTo(_))
+      .Times(4);  // Twice per query
+
+  EXPECT_TRUE(resolver.Start());
+
+  EXPECT_CALL(*this, AddressCallbackInternal(false, ""));
+
+  RunFor(base::TimeDelta::FromSeconds(4));
+}
+
+}  // namespace
+
+}  // namespace local_discovery
diff --git a/chrome/browser/local_discovery/service_discovery_client.cc b/chrome/browser/local_discovery/service_discovery_client.cc
new file mode 100644
index 0000000..0b63b85
--- /dev/null
+++ b/chrome/browser/local_discovery/service_discovery_client.cc
@@ -0,0 +1,31 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/local_discovery/service_discovery_client.h"
+
+namespace local_discovery {
+
+ServiceDescription::ServiceDescription() {
+}
+
+ServiceDescription::~ServiceDescription() {
+}
+
+std::string ServiceDescription::instance_name() const {
+  // TODO(noamsml): Once we have escaping working, get this to
+  // parse escaped domains.
+  size_t first_period = service_name.find_first_of('.');
+  return service_name.substr(0, first_period);
+}
+
+std::string ServiceDescription::service_type() const {
+  // TODO(noamsml): Once we have escaping working, get this to
+  // parse escaped domains.
+  size_t first_period = service_name.find_first_of('.');
+  if (first_period == std::string::npos)
+    return "";
+  return service_name.substr(first_period+1);
+}
+
+}  // namespace local_discovery
diff --git a/chrome/browser/local_discovery/service_discovery_client.h b/chrome/browser/local_discovery/service_discovery_client.h
new file mode 100644
index 0000000..ceeca7a
--- /dev/null
+++ b/chrome/browser/local_discovery/service_discovery_client.h
@@ -0,0 +1,137 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_LOCAL_DISCOVERY_SERVICE_DISCOVERY_CLIENT_H_
+#define CHROME_BROWSER_LOCAL_DISCOVERY_SERVICE_DISCOVERY_CLIENT_H_
+
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/time/time.h"
+#include "net/base/host_port_pair.h"
+#include "net/base/net_util.h"
+
+namespace net {
+class MDnsClient;
+}
+
+namespace local_discovery {
+
+struct ServiceDescription {
+ public:
+  ServiceDescription();
+  ~ServiceDescription();
+
+  // Convenience function to get useful parts of the service name. A service
+  // name follows the format <instance_name>.<service_type>.
+  std::string instance_name() const;
+  std::string service_type() const;
+
+  // The name of the service.
+  std::string service_name;
+  // The address (in host/port format) for the service (from SRV record).
+  net::HostPortPair address;
+  // The metadata (from TXT record) of the service.
+  std::vector<std::string> metadata;
+  // IP address of the service, if available from cache. May be empty.
+  net::IPAddressNumber ip_address;
+  // Last time the service was seen.
+  base::Time last_seen;
+};
+
+// Lets users browse the network for services of interest or listen for changes
+// in the services they are interested in. See
+// |ServiceDiscoveryClient::CreateServiceWatcher|.
+class ServiceWatcher {
+ public:
+  enum UpdateType {
+    UPDATE_ADDED,
+    UPDATE_CHANGED,
+    UPDATE_REMOVED
+  };
+
+  class Delegate {
+   public:
+    virtual ~Delegate() {}
+
+    // A service has been added or removed for a certain service name.
+    virtual void OnServiceUpdated(UpdateType update,
+                                  const std::string& service_name) = 0;
+  };
+
+  // Listening will automatically stop when the destructor is called.
+  virtual ~ServiceWatcher() {}
+
+  // Start the service type watcher.
+  virtual bool Start() = 0;
+
+  // Get all known services names of this watcher's type. Return them in
+  // |services|.
+  virtual void GetAvailableServices(
+      std::vector<std::string>* services) const = 0;
+
+  // Read services from the cache, alerting the delegate to any service that
+  // is not yet known.
+  virtual void ReadCachedServices() = 0;
+
+  // Probe for services of this type.
+  virtual void DiscoverNewServices(bool force_update) = 0;
+
+  virtual std::string GetServiceType() const = 0;
+};
+
+// Represents a service on the network and allows users to access the service's
+// address and metadata. See |ServiceDiscoveryClient::CreateServiceResolver|.
+class ServiceResolver {
+ public:
+  enum RequestStatus {
+    STATUS_SUCCESS = 0,
+    STATUS_REQUEST_TIMEOUT = 1,
+    STATUS_KNOWN_NONEXISTENT = 2
+  };
+
+  // A callback called once the service has been resolved.
+  typedef base::Callback<void(RequestStatus, const ServiceDescription&)>
+      ResolveCompleteCallback;
+
+  // Listening will automatically stop when the destructor is called.
+  virtual ~ServiceResolver() {}
+
+  // Start the service reader.
+  virtual bool StartResolving() = 0;
+
+  // Check whether the resolver is currently resolving. Can be called multiple
+  // times.
+  virtual bool IsResolving() const = 0;
+
+  // Check wheteher the resolver has resolved the service already.
+  virtual bool HasResolved() const = 0;
+
+  virtual std::string GetName() const = 0;
+
+  virtual const ServiceDescription& GetServiceDescription() const = 0;
+};
+
+class ServiceDiscoveryClient {
+ public:
+  virtual ~ServiceDiscoveryClient() {}
+
+  // Create a service watcher object listening for DNS-SD service announcements
+  // on service type |service_type|.
+  virtual scoped_ptr<ServiceWatcher> CreateServiceWatcher(
+      const std::string& service_type,
+      ServiceWatcher::Delegate* delegate) = 0;
+
+  // Create a service resolver object for getting detailed service information
+  // for the service called |service_name|.
+  virtual scoped_ptr<ServiceResolver> CreateServiceResolver(
+      const std::string& service_name,
+      const ServiceResolver::ResolveCompleteCallback& callback) = 0;
+};
+
+}  // namespace local_discovery
+
+#endif  // CHROME_BROWSER_LOCAL_DISCOVERY_SERVICE_DISCOVERY_CLIENT_H_
diff --git a/chrome/browser/local_discovery/service_discovery_client_impl.cc b/chrome/browser/local_discovery/service_discovery_client_impl.cc
new file mode 100644
index 0000000..219f5ed
--- /dev/null
+++ b/chrome/browser/local_discovery/service_discovery_client_impl.cc
@@ -0,0 +1,411 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <utility>
+
+#include "base/logging.h"
+#include "base/memory/singleton.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/stl_util.h"
+#include "chrome/browser/local_discovery/service_discovery_client_impl.h"
+#include "net/dns/dns_protocol.h"
+#include "net/dns/record_rdata.h"
+
+namespace local_discovery {
+
+ServiceDiscoveryClientImpl::ServiceDiscoveryClientImpl(
+    net::MDnsClient* mdns_client) : mdns_client_(mdns_client) {
+}
+
+ServiceDiscoveryClientImpl::~ServiceDiscoveryClientImpl() {
+}
+
+scoped_ptr<ServiceWatcher> ServiceDiscoveryClientImpl::CreateServiceWatcher(
+    const std::string& service_type,
+    ServiceWatcher::Delegate* delegate) {
+  return scoped_ptr<ServiceWatcher>(new ServiceWatcherImpl(
+      service_type,  delegate, mdns_client_));
+}
+
+scoped_ptr<ServiceResolver> ServiceDiscoveryClientImpl::CreateServiceResolver(
+    const std::string& service_name,
+    const ServiceResolver::ResolveCompleteCallback& callback) {
+  return scoped_ptr<ServiceResolver>(new ServiceResolverImpl(
+      service_name, callback, mdns_client_));
+}
+
+ServiceWatcherImpl::ServiceWatcherImpl(
+    const std::string& service_type,
+    ServiceWatcher::Delegate* delegate,
+    net::MDnsClient* mdns_client)
+    : service_type_(service_type), delegate_(delegate), started_(false),
+      mdns_client_(mdns_client) {
+}
+
+bool ServiceWatcherImpl::Start() {
+  DCHECK(!started_);
+  listener_ = mdns_client_->CreateListener(
+      net::dns_protocol::kTypePTR, service_type_, this);
+  if (!listener_->Start())
+    return false;
+
+  started_ = true;
+  return true;
+}
+
+ServiceWatcherImpl::~ServiceWatcherImpl() {
+}
+
+void ServiceWatcherImpl::GetAvailableServices(
+    std::vector<std::string>* services) const {
+  DCHECK(started_);
+  DCHECK(services);
+  services->reserve(services_.size());
+  for (ServiceListenersMap::const_iterator i = services_.begin();
+       i != services_.end(); i++) {
+    services->push_back(i->first);
+  }
+}
+
+void ServiceWatcherImpl::DiscoverNewServices(bool force_update) {
+  DCHECK(started_);
+  if (force_update)
+    services_.clear();
+  CreateTransaction(true /*network*/, false /*cache*/, force_update,
+                    &transaction_network_);
+}
+
+void ServiceWatcherImpl::ReadCachedServices() {
+  DCHECK(started_);
+  CreateTransaction(false /*network*/, true /*cache*/, false /*force refresh*/,
+                    &transaction_cache_);
+}
+
+bool ServiceWatcherImpl::CreateTransaction(
+    bool network, bool cache, bool force_refresh,
+    scoped_ptr<net::MDnsTransaction>* transaction) {
+  int transaction_flags = 0;
+  if (network)
+    transaction_flags |= net::MDnsTransaction::QUERY_NETWORK;
+
+  if (cache)
+    transaction_flags |= net::MDnsTransaction::QUERY_CACHE;
+
+  // TODO(noamsml): Add flag for force_refresh when supported.
+
+  if (transaction_flags) {
+    *transaction = mdns_client_->CreateTransaction(
+        net::dns_protocol::kTypePTR, service_type_, transaction_flags,
+        base::Bind(&ServiceWatcherImpl::OnTransactionResponse,
+                   base::Unretained(this), transaction));
+    return (*transaction)->Start();
+  }
+
+  return true;
+}
+
+std::string ServiceWatcherImpl::GetServiceType() const {
+  return listener_->GetName();
+}
+
+void ServiceWatcherImpl::OnRecordUpdate(
+    net::MDnsListener::UpdateType update,
+    const net::RecordParsed* record) {
+  DCHECK(started_);
+  if (record->type() == net::dns_protocol::kTypePTR) {
+    DCHECK(record->name() == GetServiceType());
+    const net::PtrRecordRdata* rdata = record->rdata<net::PtrRecordRdata>();
+
+    switch (update) {
+      case net::MDnsListener::RECORD_ADDED:
+        AddService(rdata->ptrdomain());
+        break;
+      case net::MDnsListener::RECORD_CHANGED:
+        NOTREACHED();
+        break;
+      case net::MDnsListener::RECORD_REMOVED:
+        RemoveService(rdata->ptrdomain());
+        break;
+    }
+  } else {
+    DCHECK(record->type() == net::dns_protocol::kTypeSRV ||
+           record->type() == net::dns_protocol::kTypeTXT);
+    DCHECK(services_.find(record->name()) != services_.end());
+
+    DeferUpdate(UPDATE_CHANGED, record->name());
+  }
+}
+
+void ServiceWatcherImpl::OnCachePurged() {
+  // Not yet implemented.
+}
+
+void ServiceWatcherImpl::OnTransactionResponse(
+    scoped_ptr<net::MDnsTransaction>* transaction,
+    net::MDnsTransaction::Result result,
+    const net::RecordParsed* record) {
+  DCHECK(started_);
+  if (result == net::MDnsTransaction::RESULT_RECORD) {
+    const net::PtrRecordRdata* rdata = record->rdata<net::PtrRecordRdata>();
+    DCHECK(rdata);
+    AddService(rdata->ptrdomain());
+  } else if (result == net::MDnsTransaction::RESULT_DONE) {
+    transaction->reset();
+  }
+
+  // Do nothing for NSEC records. It is an error for hosts to broadcast an NSEC
+  // record for PTR records on any name.
+}
+
+ServiceWatcherImpl::ServiceListeners::ServiceListeners(
+    const std::string& service_name,
+    ServiceWatcherImpl* watcher,
+    net::MDnsClient* mdns_client) : update_pending_(false) {
+  srv_listener_ = mdns_client->CreateListener(
+      net::dns_protocol::kTypeSRV, service_name, watcher);
+  txt_listener_ = mdns_client->CreateListener(
+      net::dns_protocol::kTypeTXT, service_name, watcher);
+}
+
+ServiceWatcherImpl::ServiceListeners::~ServiceListeners() {
+}
+
+bool ServiceWatcherImpl::ServiceListeners::Start() {
+  if (!srv_listener_->Start())
+    return false;
+  return txt_listener_->Start();
+}
+
+void ServiceWatcherImpl::AddService(const std::string& service) {
+  DCHECK(started_);
+  std::pair<ServiceListenersMap::iterator, bool> found = services_.insert(
+      make_pair(service, static_cast<ServiceListeners*>(NULL)));
+  if (found.second) {  // Newly inserted.
+    found.first->second = linked_ptr<ServiceListeners>(
+        new ServiceListeners(service, this, mdns_client_));
+    bool success = found.first->second->Start();
+
+    DeferUpdate(UPDATE_ADDED, service);
+
+    DCHECK(success);
+  }
+}
+
+void ServiceWatcherImpl::DeferUpdate(ServiceWatcher::UpdateType update_type,
+                                     const std::string& service_name) {
+  ServiceListenersMap::iterator found = services_.find(service_name);
+
+  if (found != services_.end() && !found->second->update_pending()) {
+    found->second->set_update_pending(true);
+    base::MessageLoop::current()->PostTask(
+        FROM_HERE,
+        base::Bind(&ServiceWatcherImpl::DeliverDeferredUpdate, AsWeakPtr(),
+                   update_type, service_name));
+  }
+}
+
+void ServiceWatcherImpl::DeliverDeferredUpdate(
+    ServiceWatcher::UpdateType update_type, const std::string& service_name) {
+  ServiceListenersMap::iterator found = services_.find(service_name);
+
+  if (found != services_.end()) {
+    found->second->set_update_pending(false);
+    delegate_->OnServiceUpdated(update_type, service_name);
+  }
+}
+
+void ServiceWatcherImpl::RemoveService(const std::string& service) {
+  DCHECK(started_);
+  ServiceListenersMap::iterator found = services_.find(service);
+  if (found != services_.end()) {
+    services_.erase(found);
+    delegate_->OnServiceUpdated(UPDATE_REMOVED, service);
+  }
+}
+
+void ServiceWatcherImpl::OnNsecRecord(const std::string& name,
+                                      unsigned rrtype) {
+  // Do nothing. It is an error for hosts to broadcast an NSEC record for PTR
+  // on any name.
+}
+
+ServiceResolverImpl::ServiceResolverImpl(
+    const std::string& service_name,
+    const ResolveCompleteCallback& callback,
+    net::MDnsClient* mdns_client)
+    : service_name_(service_name), callback_(callback),
+      is_resolving_(false), has_resolved_(false), metadata_resolved_(false),
+      address_resolved_(false), service_staging_(new ServiceDescription),
+      service_final_(new ServiceDescription), mdns_client_(mdns_client) {
+  service_staging_->service_name = service_name_;
+  service_final_->service_name = service_name_;
+}
+
+bool ServiceResolverImpl::StartResolving() {
+  is_resolving_ = true;
+  address_resolved_ = false;
+  metadata_resolved_ = false;
+
+  if (!CreateTxtTransaction())
+    return false;
+  if (!CreateSrvTransaction())
+    return false;
+  return true;
+}
+
+bool ServiceResolverImpl::IsResolving() const {
+  return is_resolving_;
+}
+
+bool ServiceResolverImpl::HasResolved() const {
+  return has_resolved_;
+}
+
+ServiceResolverImpl::~ServiceResolverImpl() {
+}
+
+bool ServiceResolverImpl::CreateTxtTransaction() {
+  txt_transaction_ = mdns_client_->CreateTransaction(
+      net::dns_protocol::kTypeTXT, service_name_,
+      net::MDnsTransaction::SINGLE_RESULT | net::MDnsTransaction::QUERY_CACHE |
+      net::MDnsTransaction::QUERY_NETWORK,
+      base::Bind(&ServiceResolverImpl::TxtRecordTransactionResponse,
+                 AsWeakPtr()));
+  return txt_transaction_->Start();
+}
+
+// TODO(noamsml): quick-resolve for AAAA records.  Since A records tend to be in
+void ServiceResolverImpl::CreateATransaction() {
+  a_transaction_ = mdns_client_->CreateTransaction(
+      net::dns_protocol::kTypeA,
+      service_staging_.get()->address.host(),
+      net::MDnsTransaction::SINGLE_RESULT | net::MDnsTransaction::QUERY_CACHE,
+      base::Bind(&ServiceResolverImpl::ARecordTransactionResponse,
+                 AsWeakPtr()));
+  a_transaction_->Start();
+}
+
+bool ServiceResolverImpl::CreateSrvTransaction() {
+  srv_transaction_ = mdns_client_->CreateTransaction(
+      net::dns_protocol::kTypeSRV, service_name_,
+      net::MDnsTransaction::SINGLE_RESULT | net::MDnsTransaction::QUERY_CACHE |
+      net::MDnsTransaction::QUERY_NETWORK,
+      base::Bind(&ServiceResolverImpl::SrvRecordTransactionResponse,
+                 AsWeakPtr()));
+  return srv_transaction_->Start();
+}
+
+std::string ServiceResolverImpl::GetName() const {
+  return service_name_;
+}
+
+void ServiceResolverImpl::SrvRecordTransactionResponse(
+    net::MDnsTransaction::Result status, const net::RecordParsed* record) {
+  srv_transaction_.reset();
+  if (status == net::MDnsTransaction::RESULT_RECORD) {
+    DCHECK(record);
+    service_staging_.get()->address = RecordToAddress(record);
+    service_staging_.get()->last_seen = record->time_created();
+    CreateATransaction();
+  } else {
+    ServiceNotFound(MDnsStatusToRequestStatus(status));
+  }
+}
+
+void ServiceResolverImpl::TxtRecordTransactionResponse(
+    net::MDnsTransaction::Result status, const net::RecordParsed* record) {
+  txt_transaction_.reset();
+  if (status == net::MDnsTransaction::RESULT_RECORD) {
+    DCHECK(record);
+    service_staging_.get()->metadata = RecordToMetadata(record);
+  } else {
+    service_staging_.get()->metadata = std::vector<std::string>();
+  }
+
+  metadata_resolved_ = true;
+  AlertCallbackIfReady();
+}
+
+void ServiceResolverImpl::ARecordTransactionResponse(
+    net::MDnsTransaction::Result status, const net::RecordParsed* record) {
+  a_transaction_.reset();
+
+  if (status == net::MDnsTransaction::RESULT_RECORD) {
+    DCHECK(record);
+    service_staging_.get()->ip_address = RecordToIPAddress(record);
+  } else {
+    service_staging_.get()->ip_address = net::IPAddressNumber();
+  }
+
+  address_resolved_ = true;
+  AlertCallbackIfReady();
+}
+
+void ServiceResolverImpl::AlertCallbackIfReady() {
+  if (metadata_resolved_ && address_resolved_) {
+    txt_transaction_.reset();
+    srv_transaction_.reset();
+    a_transaction_.reset();
+    has_resolved_ = true;
+    is_resolving_ = false;
+    service_final_.swap(service_staging_);
+    callback_.Run(STATUS_SUCCESS, GetServiceDescription());
+  }
+}
+
+void ServiceResolverImpl::ServiceNotFound(
+    ServiceResolver::RequestStatus status) {
+  txt_transaction_.reset();
+  srv_transaction_.reset();
+  a_transaction_.reset();
+  is_resolving_ = false;
+
+  callback_.Run(status, GetServiceDescription());
+}
+
+const ServiceDescription& ServiceResolverImpl::GetServiceDescription() const {
+  return *service_final_.get();
+}
+
+ServiceResolver::RequestStatus ServiceResolverImpl::MDnsStatusToRequestStatus(
+    net::MDnsTransaction::Result status) const {
+  switch (status) {
+    case net::MDnsTransaction::RESULT_RECORD:
+      return ServiceResolver::STATUS_SUCCESS;
+    case net::MDnsTransaction::RESULT_NO_RESULTS:
+      return ServiceResolver::STATUS_REQUEST_TIMEOUT;
+    case net::MDnsTransaction::RESULT_NSEC:
+      return ServiceResolver::STATUS_KNOWN_NONEXISTENT;
+    case net::MDnsTransaction::RESULT_DONE:  // Pass through.
+    default:
+      NOTREACHED();
+      return ServiceResolver::STATUS_REQUEST_TIMEOUT;
+  }
+}
+
+const std::vector<std::string>& ServiceResolverImpl::RecordToMetadata(
+    const net::RecordParsed* record) const {
+  DCHECK(record->type() == net::dns_protocol::kTypeTXT);
+  const net::TxtRecordRdata* txt_rdata = record->rdata<net::TxtRecordRdata>();
+  DCHECK(txt_rdata);
+  return txt_rdata->texts();
+}
+
+net::HostPortPair ServiceResolverImpl::RecordToAddress(
+    const net::RecordParsed* record) const {
+  DCHECK(record->type() == net::dns_protocol::kTypeSRV);
+  const net::SrvRecordRdata* srv_rdata = record->rdata<net::SrvRecordRdata>();
+  DCHECK(srv_rdata);
+  return net::HostPortPair(srv_rdata->target(), srv_rdata->port());
+}
+
+const net::IPAddressNumber& ServiceResolverImpl::RecordToIPAddress(
+    const net::RecordParsed* record) const {
+  DCHECK(record->type() == net::dns_protocol::kTypeA);
+  const net::ARecordRdata* a_rdata = record->rdata<net::ARecordRdata>();
+  DCHECK(a_rdata);
+  return a_rdata->address();
+}
+
+}  // namespace local_discovery
diff --git a/chrome/browser/local_discovery/service_discovery_client_impl.h b/chrome/browser/local_discovery/service_discovery_client_impl.h
new file mode 100644
index 0000000..13765e0
--- /dev/null
+++ b/chrome/browser/local_discovery/service_discovery_client_impl.h
@@ -0,0 +1,204 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_LOCAL_DISCOVERY_SERVICE_DISCOVERY_CLIENT_IMPL_H_
+#define CHROME_BROWSER_LOCAL_DISCOVERY_SERVICE_DISCOVERY_CLIENT_IMPL_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/cancelable_callback.h"
+#include "base/memory/linked_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/message_loop.h"
+#include "chrome/browser/local_discovery/service_discovery_client.h"
+#include "net/dns/mdns_client.h"
+
+namespace local_discovery {
+
+class ServiceDiscoveryClientImpl : public ServiceDiscoveryClient {
+ public:
+  // |mdns_client| must outlive the Service Discovery Client.
+  explicit ServiceDiscoveryClientImpl(net::MDnsClient* mdns_client);
+  virtual ~ServiceDiscoveryClientImpl();
+
+  // ServiceDiscoveryClient implementation:
+  virtual scoped_ptr<ServiceWatcher> CreateServiceWatcher(
+      const std::string& service_type,
+      ServiceWatcher::Delegate* delegate) OVERRIDE;
+
+  virtual scoped_ptr<ServiceResolver> CreateServiceResolver(
+      const std::string& service_name,
+      const ServiceResolver::ResolveCompleteCallback& callback) OVERRIDE;
+ private:
+  net::MDnsClient* mdns_client_;
+
+  DISALLOW_COPY_AND_ASSIGN(ServiceDiscoveryClientImpl);
+};
+
+class ServiceWatcherImpl : public ServiceWatcher,
+                           public net::MDnsListener::Delegate,
+                           public base::SupportsWeakPtr<ServiceWatcherImpl> {
+ public:
+  ServiceWatcherImpl(const std::string& service_type,
+                     ServiceWatcher::Delegate* delegate,
+                     net::MDnsClient* mdns_client);
+  // Listening will automatically stop when the destructor is called.
+  virtual ~ServiceWatcherImpl();
+
+  // ServiceWatcher implementation:
+  virtual bool Start() OVERRIDE;
+
+  virtual void GetAvailableServices(
+      std::vector<std::string>* services) const OVERRIDE;
+
+  virtual void DiscoverNewServices(bool force_update) OVERRIDE;
+
+  virtual std::string GetServiceType() const OVERRIDE;
+
+  virtual void ReadCachedServices() OVERRIDE;
+
+  virtual void OnRecordUpdate(net::MDnsListener::UpdateType update,
+                              const net::RecordParsed* record) OVERRIDE;
+
+  virtual void OnNsecRecord(const std::string& name, unsigned rrtype) OVERRIDE;
+
+  virtual void OnCachePurged() OVERRIDE;
+
+  virtual void OnTransactionResponse(
+      scoped_ptr<net::MDnsTransaction>* transaction,
+      net::MDnsTransaction::Result result,
+      const net::RecordParsed* record);
+
+ private:
+  struct ServiceListeners {
+    ServiceListeners(const std::string& service_name,
+                     ServiceWatcherImpl* watcher,
+                     net::MDnsClient* mdns_client);
+    ~ServiceListeners();
+    bool Start();
+
+    void set_update_pending(bool update_pending) {
+      update_pending_ = update_pending;
+    }
+
+    bool update_pending() { return update_pending_; }
+   private:
+    scoped_ptr<net::MDnsListener> srv_listener_;
+    scoped_ptr<net::MDnsListener> txt_listener_;
+    bool update_pending_;
+  };
+
+  typedef std::map<std::string, linked_ptr<ServiceListeners> >
+      ServiceListenersMap;
+
+  void AddService(const std::string& service);
+  void RemoveService(const std::string& service);
+  bool CreateTransaction(bool active, bool alert_existing_services,
+                         bool force_refresh,
+                         scoped_ptr<net::MDnsTransaction>* transaction);
+
+  void DeferUpdate(ServiceWatcher::UpdateType update_type,
+                   const std::string& service_name);
+  void DeliverDeferredUpdate(ServiceWatcher::UpdateType update_type,
+                             const std::string& service_name);
+
+  std::string service_type_;
+  ServiceListenersMap services_;
+  scoped_ptr<net::MDnsTransaction> transaction_network_;
+  scoped_ptr<net::MDnsTransaction> transaction_cache_;
+  scoped_ptr<net::MDnsListener> listener_;
+
+  ServiceWatcher::Delegate* delegate_;
+  bool started_;
+
+  net::MDnsClient* mdns_client_;
+
+  DISALLOW_COPY_AND_ASSIGN(ServiceWatcherImpl);
+};
+
+class ServiceResolverImpl
+    : public ServiceResolver,
+      public base::SupportsWeakPtr<ServiceResolverImpl> {
+ public:
+  ServiceResolverImpl(const std::string& service_name,
+                      const ServiceResolver::ResolveCompleteCallback& callback,
+                      net::MDnsClient* mdns_client);
+
+  virtual ~ServiceResolverImpl();
+
+  // ServiceResolver implementation:
+  virtual bool StartResolving() OVERRIDE;
+
+  virtual bool IsResolving() const OVERRIDE;
+
+  virtual bool HasResolved() const OVERRIDE;
+
+  virtual std::string GetName() const OVERRIDE;
+
+  virtual const ServiceDescription& GetServiceDescription() const OVERRIDE;
+
+ private:
+  // Respond to transaction finishing for SRV records.
+  void SrvRecordTransactionResponse(net::MDnsTransaction::Result status,
+                                    const net::RecordParsed* record);
+
+  // Respond to transaction finishing for TXT records.
+  void TxtRecordTransactionResponse(net::MDnsTransaction::Result status,
+                                    const net::RecordParsed* record);
+
+  // Respond to transaction finishing for A records.
+  void ARecordTransactionResponse(net::MDnsTransaction::Result status,
+                                  const net::RecordParsed* record);
+
+  void AlertCallbackIfReady();
+
+  void ServiceNotFound(RequestStatus status);
+
+  // Convert a TXT record to a vector of strings (metadata).
+  const std::vector<std::string>& RecordToMetadata(
+      const net::RecordParsed* record) const;
+
+  // Convert an SRV record to a host and port pair.
+  net::HostPortPair RecordToAddress(
+      const net::RecordParsed* record) const;
+
+  // Convert an A record to an IP address.
+  const net::IPAddressNumber& RecordToIPAddress(
+      const net::RecordParsed* record) const;
+
+  // Convert an MDns status to a service discovery status.
+  RequestStatus MDnsStatusToRequestStatus(
+      net::MDnsTransaction::Result status) const;
+
+  bool CreateTxtTransaction();
+  bool CreateSrvTransaction();
+  void CreateATransaction();
+
+  std::string service_name_;
+  ResolveCompleteCallback callback_;
+
+  bool is_resolving_;
+  bool has_resolved_;
+
+  bool metadata_resolved_;
+  bool address_resolved_;
+
+  scoped_ptr<net::MDnsTransaction> txt_transaction_;
+  scoped_ptr<net::MDnsTransaction> srv_transaction_;
+  scoped_ptr<net::MDnsTransaction> a_transaction_;
+
+  scoped_ptr<ServiceDescription> service_staging_;
+  scoped_ptr<ServiceDescription> service_final_;
+
+  net::MDnsClient* mdns_client_;
+
+  DISALLOW_COPY_AND_ASSIGN(ServiceResolverImpl);
+};
+
+}  // namespace local_discovery
+
+#endif  // CHROME_BROWSER_LOCAL_DISCOVERY_SERVICE_DISCOVERY_CLIENT_IMPL_H_
diff --git a/chrome/browser/local_discovery/service_discovery_client_unittest.cc b/chrome/browser/local_discovery/service_discovery_client_unittest.cc
new file mode 100644
index 0000000..9a7d90a
--- /dev/null
+++ b/chrome/browser/local_discovery/service_discovery_client_unittest.cc
@@ -0,0 +1,468 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/local_discovery/service_discovery_client_impl.h"
+#include "net/base/net_errors.h"
+#include "net/dns/dns_protocol.h"
+#include "net/dns/mdns_client_impl.h"
+#include "net/dns/mock_mdns_socket_factory.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::_;
+using ::testing::Invoke;
+using ::testing::StrictMock;
+using ::testing::NiceMock;
+using ::testing::Mock;
+using ::testing::SaveArg;
+using ::testing::SetArgPointee;
+using ::testing::Return;
+using ::testing::Exactly;
+
+namespace local_discovery {
+
+namespace {
+
+const char kSamplePacketPTR[] = {
+  // Header
+  '\x00', '\x00',               // ID is zeroed out
+  '\x81', '\x80',               // Standard query response, RA, no error
+  '\x00', '\x00',               // No questions (for simplicity)
+  '\x00', '\x01',               // 1 RR (answers)
+  '\x00', '\x00',               // 0 authority RRs
+  '\x00', '\x00',               // 0 additional RRs
+
+  '\x07', '_', 'p', 'r', 'i', 'v', 'e', 't',
+  '\x04', '_', 't', 'c', 'p',
+  '\x05', 'l', 'o', 'c', 'a', 'l',
+  '\x00',
+  '\x00', '\x0c',        // TYPE is PTR.
+  '\x00', '\x01',        // CLASS is IN.
+  '\x00', '\x00',        // TTL (4 bytes) is 1 second.
+  '\x00', '\x01',
+  '\x00', '\x08',        // RDLENGTH is 8 bytes.
+  '\x05', 'h', 'e', 'l', 'l', 'o',
+  '\xc0', '\x0c'
+};
+
+const char kSamplePacketSRV[] = {
+  // Header
+  '\x00', '\x00',               // ID is zeroed out
+  '\x81', '\x80',               // Standard query response, RA, no error
+  '\x00', '\x00',               // No questions (for simplicity)
+  '\x00', '\x01',               // 1 RR (answers)
+  '\x00', '\x00',               // 0 authority RRs
+  '\x00', '\x00',               // 0 additional RRs
+
+  '\x05', 'h', 'e', 'l', 'l', 'o',
+  '\x07', '_', 'p', 'r', 'i', 'v', 'e', 't',
+  '\x04', '_', 't', 'c', 'p',
+  '\x05', 'l', 'o', 'c', 'a', 'l',
+  '\x00',
+  '\x00', '\x21',        // TYPE is SRV.
+  '\x00', '\x01',        // CLASS is IN.
+  '\x00', '\x00',        // TTL (4 bytes) is 1 second.
+  '\x00', '\x01',
+  '\x00', '\x15',        // RDLENGTH is 21 bytes.
+  '\x00', '\x00',
+  '\x00', '\x00',
+  '\x22', '\xb8',  // port 8888
+  '\x07', 'm', 'y', 'h', 'e', 'l', 'l', 'o',
+  '\x05', 'l', 'o', 'c', 'a', 'l',
+  '\x00',
+};
+
+const char kSamplePacketTXT[] = {
+  // Header
+  '\x00', '\x00',               // ID is zeroed out
+  '\x81', '\x80',               // Standard query response, RA, no error
+  '\x00', '\x00',               // No questions (for simplicity)
+  '\x00', '\x01',               // 1 RR (answers)
+  '\x00', '\x00',               // 0 authority RRs
+  '\x00', '\x00',               // 0 additional RRs
+
+  '\x05', 'h', 'e', 'l', 'l', 'o',
+  '\x07', '_', 'p', 'r', 'i', 'v', 'e', 't',
+  '\x04', '_', 't', 'c', 'p',
+  '\x05', 'l', 'o', 'c', 'a', 'l',
+  '\x00',
+  '\x00', '\x10',        // TYPE is PTR.
+  '\x00', '\x01',        // CLASS is IN.
+  '\x00', '\x00',        // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
+  '\x00', '\x01',
+  '\x00', '\x06',        // RDLENGTH is 21 bytes.
+  '\x05', 'h', 'e', 'l', 'l', 'o'
+};
+
+const char kSamplePacketSRVA[] = {
+  // Header
+  '\x00', '\x00',               // ID is zeroed out
+  '\x81', '\x80',               // Standard query response, RA, no error
+  '\x00', '\x00',               // No questions (for simplicity)
+  '\x00', '\x02',               // 2 RR (answers)
+  '\x00', '\x00',               // 0 authority RRs
+  '\x00', '\x00',               // 0 additional RRs
+
+  '\x05', 'h', 'e', 'l', 'l', 'o',
+  '\x07', '_', 'p', 'r', 'i', 'v', 'e', 't',
+  '\x04', '_', 't', 'c', 'p',
+  '\x05', 'l', 'o', 'c', 'a', 'l',
+  '\x00',
+  '\x00', '\x21',        // TYPE is SRV.
+  '\x00', '\x01',        // CLASS is IN.
+  '\x00', '\x00',        // TTL (4 bytes) is 16 seconds.
+  '\x00', '\x10',
+  '\x00', '\x15',        // RDLENGTH is 21 bytes.
+  '\x00', '\x00',
+  '\x00', '\x00',
+  '\x22', '\xb8',  // port 8888
+  '\x07', 'm', 'y', 'h', 'e', 'l', 'l', 'o',
+  '\x05', 'l', 'o', 'c', 'a', 'l',
+  '\x00',
+
+  '\x07', 'm', 'y', 'h', 'e', 'l', 'l', 'o',
+  '\x05', 'l', 'o', 'c', 'a', 'l',
+  '\x00',
+  '\x00', '\x01',        // TYPE is A.
+  '\x00', '\x01',        // CLASS is IN.
+  '\x00', '\x00',        // TTL (4 bytes) is 16 seconds.
+  '\x00', '\x10',
+  '\x00', '\x04',        // RDLENGTH is 4 bytes.
+  '\x01', '\x02',
+  '\x03', '\x04',
+};
+
+class MockServiceWatcherDelegate : public ServiceWatcher::Delegate {
+ public:
+  MockServiceWatcherDelegate() {}
+  virtual ~MockServiceWatcherDelegate() {}
+
+  MOCK_METHOD2(OnServiceUpdated, void(ServiceWatcher::UpdateType,
+                                      const std::string&));
+};
+
+class ServiceDiscoveryTest : public ::testing::Test {
+ public:
+  ServiceDiscoveryTest()
+      : socket_factory_(new net::MockMDnsSocketFactory),
+        mdns_client_(
+            scoped_ptr<net::MDnsConnection::SocketFactory>(
+                socket_factory_)),
+        service_discovery_client_(&mdns_client_) {
+    mdns_client_.StartListening();
+  }
+
+  virtual ~ServiceDiscoveryTest() {
+  }
+
+ protected:
+  void RunFor(base::TimeDelta time_period) {
+    base::CancelableCallback<void()> callback(base::Bind(
+        &ServiceDiscoveryTest::Stop, base::Unretained(this)));
+    base::MessageLoop::current()->PostDelayedTask(
+        FROM_HERE, callback.callback(), time_period);
+
+    base::MessageLoop::current()->Run();
+    callback.Cancel();
+  }
+
+  void Stop() {
+    base::MessageLoop::current()->Quit();
+  }
+
+  net::MockMDnsSocketFactory* socket_factory_;
+  net::MDnsClientImpl mdns_client_;
+  ServiceDiscoveryClientImpl service_discovery_client_;
+  base::MessageLoop loop_;
+};
+
+TEST_F(ServiceDiscoveryTest, AddRemoveService) {
+  scoped_ptr<ServiceWatcher> watcher;
+  StrictMock<MockServiceWatcherDelegate> delegate;
+
+  watcher = service_discovery_client_.CreateServiceWatcher(
+      "_privet._tcp.local", &delegate);
+
+  watcher->Start();
+
+  EXPECT_CALL(delegate, OnServiceUpdated(ServiceWatcher::UPDATE_ADDED,
+                                         "hello._privet._tcp.local"))
+      .Times(Exactly(1));
+
+  socket_factory_->SimulateReceive(
+      kSamplePacketPTR, sizeof(kSamplePacketPTR));
+
+  EXPECT_CALL(delegate, OnServiceUpdated(ServiceWatcher::UPDATE_REMOVED,
+                                         "hello._privet._tcp.local"))
+      .Times(Exactly(1));
+
+  RunFor(base::TimeDelta::FromSeconds(2));
+};
+
+TEST_F(ServiceDiscoveryTest, DiscoverNewServices) {
+  scoped_ptr<ServiceWatcher> watcher;
+  StrictMock<MockServiceWatcherDelegate> delegate;
+
+  watcher = service_discovery_client_.CreateServiceWatcher(
+      "_privet._tcp.local", &delegate);
+
+  watcher->Start();
+
+  EXPECT_CALL(*socket_factory_, OnSendTo(_))
+      .Times(2);
+
+  watcher->DiscoverNewServices(false);
+};
+
+TEST_F(ServiceDiscoveryTest, GetAvailableServices) {
+  NiceMock<MockServiceWatcherDelegate> delegate;
+
+  std::vector<std::string> data_expected;
+  std::vector<std::string> data;
+
+  data_expected.push_back("hello._privet._tcp.local");
+
+  scoped_ptr<ServiceWatcher> watcher =
+      service_discovery_client_.CreateServiceWatcher(
+          "_privet._tcp.local", &delegate);
+
+  watcher->Start();
+
+  socket_factory_->SimulateReceive(
+      kSamplePacketPTR, sizeof(kSamplePacketPTR));
+
+  watcher->GetAvailableServices(&data);
+
+  EXPECT_EQ(data, data_expected);
+};
+
+TEST_F(ServiceDiscoveryTest, ReadCachedServices) {
+  NiceMock<MockServiceWatcherDelegate> delegate_irrelevant;
+  scoped_ptr<ServiceWatcher> watcher_irrelevant =
+      service_discovery_client_.CreateServiceWatcher(
+          "_privet._tcp.local", &delegate_irrelevant);
+
+  watcher_irrelevant->Start();
+
+  socket_factory_->SimulateReceive(
+      kSamplePacketPTR, sizeof(kSamplePacketPTR));
+
+  StrictMock<MockServiceWatcherDelegate> delegate;
+  scoped_ptr<ServiceWatcher> watcher =
+      service_discovery_client_.CreateServiceWatcher(
+          "_privet._tcp.local", &delegate);
+
+  watcher->Start();
+
+  EXPECT_CALL(delegate, OnServiceUpdated(ServiceWatcher::UPDATE_ADDED,
+                                         "hello._privet._tcp.local"))
+      .Times(Exactly(1));
+
+  watcher->ReadCachedServices();
+
+  base::MessageLoop::current()->RunUntilIdle();
+};
+
+TEST_F(ServiceDiscoveryTest, OnServiceChanged) {
+  StrictMock<MockServiceWatcherDelegate> delegate;
+  scoped_ptr<ServiceWatcher> watcher =
+      service_discovery_client_.CreateServiceWatcher(
+          "_privet._tcp.local", &delegate);
+
+  watcher->Start();
+
+  EXPECT_CALL(delegate, OnServiceUpdated(ServiceWatcher::UPDATE_ADDED,
+                                         "hello._privet._tcp.local"))
+      .Times(Exactly(1));
+
+  socket_factory_->SimulateReceive(
+      kSamplePacketPTR, sizeof(kSamplePacketPTR));
+
+  base::MessageLoop::current()->RunUntilIdle();
+
+  EXPECT_CALL(delegate, OnServiceUpdated(ServiceWatcher::UPDATE_CHANGED,
+                                         "hello._privet._tcp.local"))
+      .Times(Exactly(1));
+
+  socket_factory_->SimulateReceive(
+      kSamplePacketSRV, sizeof(kSamplePacketSRV));
+
+  socket_factory_->SimulateReceive(
+      kSamplePacketTXT, sizeof(kSamplePacketTXT));
+
+  base::MessageLoop::current()->RunUntilIdle();
+};
+
+TEST_F(ServiceDiscoveryTest, SinglePacket) {
+  StrictMock<MockServiceWatcherDelegate> delegate;
+  scoped_ptr<ServiceWatcher> watcher =
+      service_discovery_client_.CreateServiceWatcher(
+          "_privet._tcp.local", &delegate);
+
+  watcher->Start();
+
+  EXPECT_CALL(delegate, OnServiceUpdated(ServiceWatcher::UPDATE_ADDED,
+                                         "hello._privet._tcp.local"))
+      .Times(Exactly(1));
+
+  socket_factory_->SimulateReceive(
+      kSamplePacketPTR, sizeof(kSamplePacketPTR));
+
+  // Reset the "already updated" flag.
+  base::MessageLoop::current()->RunUntilIdle();
+
+  EXPECT_CALL(delegate, OnServiceUpdated(ServiceWatcher::UPDATE_CHANGED,
+                                         "hello._privet._tcp.local"))
+      .Times(Exactly(1));
+
+  socket_factory_->SimulateReceive(
+      kSamplePacketSRV, sizeof(kSamplePacketSRV));
+
+  socket_factory_->SimulateReceive(
+      kSamplePacketTXT, sizeof(kSamplePacketTXT));
+
+  base::MessageLoop::current()->RunUntilIdle();
+};
+
+class ServiceResolverTest : public ServiceDiscoveryTest {
+ public:
+  ServiceResolverTest() {
+    metadata_expected_.push_back("hello");
+    address_expected_ = net::HostPortPair("myhello.local", 8888);
+    ip_address_expected_.push_back(1);
+    ip_address_expected_.push_back(2);
+    ip_address_expected_.push_back(3);
+    ip_address_expected_.push_back(4);
+  }
+
+  ~ServiceResolverTest() {
+  }
+
+  void SetUp()  {
+    resolver_ = service_discovery_client_.CreateServiceResolver(
+        "hello._privet._tcp.local",
+        base::Bind(&ServiceResolverTest::OnFinishedResolving,
+                   base::Unretained(this)));
+  }
+
+  void OnFinishedResolving(ServiceResolver::RequestStatus request_status,
+                           const ServiceDescription& service_description) {
+    OnFinishedResolvingInternal(request_status);
+  }
+
+  MOCK_METHOD1(OnFinishedResolvingInternal, void(
+      ServiceResolver::RequestStatus));
+
+ protected:
+  scoped_ptr<ServiceResolver> resolver_;
+  net::IPAddressNumber ip_address_;
+  net::HostPortPair address_expected_;
+  std::vector<std::string> metadata_expected_;
+  net::IPAddressNumber ip_address_expected_;
+};
+
+TEST_F(ServiceResolverTest, TxtAndSrvButNoA) {
+  EXPECT_CALL(*socket_factory_, OnSendTo(_))
+      .Times(4);
+
+  EXPECT_FALSE(resolver_->IsResolving());
+  EXPECT_FALSE(resolver_->HasResolved());
+  EXPECT_TRUE(resolver_->StartResolving());
+  EXPECT_TRUE(resolver_->IsResolving());
+  EXPECT_FALSE(resolver_->HasResolved());
+
+  socket_factory_->SimulateReceive(
+      kSamplePacketSRV, sizeof(kSamplePacketSRV));
+
+  base::MessageLoop::current()->RunUntilIdle();
+
+  EXPECT_CALL(*this, OnFinishedResolvingInternal(
+      ServiceResolver::STATUS_SUCCESS));
+
+  socket_factory_->SimulateReceive(
+      kSamplePacketTXT, sizeof(kSamplePacketTXT));
+
+  EXPECT_EQ(address_expected_.ToString(),
+            resolver_->GetServiceDescription().address.ToString());
+  EXPECT_EQ(metadata_expected_, resolver_->GetServiceDescription().metadata);
+  EXPECT_EQ(net::IPAddressNumber(),
+            resolver_->GetServiceDescription().ip_address);
+};
+
+TEST_F(ServiceResolverTest, TxtSrvAndA) {
+  EXPECT_CALL(*socket_factory_, OnSendTo(_))
+      .Times(4);
+
+  EXPECT_FALSE(resolver_->IsResolving());
+  EXPECT_FALSE(resolver_->HasResolved());
+  EXPECT_TRUE(resolver_->StartResolving());
+  EXPECT_TRUE(resolver_->IsResolving());
+  EXPECT_FALSE(resolver_->HasResolved());
+
+  EXPECT_CALL(*this, OnFinishedResolvingInternal(
+      ServiceResolver::STATUS_SUCCESS));
+
+  socket_factory_->SimulateReceive(
+      kSamplePacketTXT, sizeof(kSamplePacketTXT));
+
+  socket_factory_->SimulateReceive(
+      kSamplePacketSRVA, sizeof(kSamplePacketSRVA));
+
+  EXPECT_EQ(address_expected_.ToString(),
+            resolver_->GetServiceDescription().address.ToString());
+  EXPECT_EQ(metadata_expected_, resolver_->GetServiceDescription().metadata);
+  EXPECT_EQ(ip_address_expected_,
+            resolver_->GetServiceDescription().ip_address);
+};
+
+TEST_F(ServiceResolverTest, JustSrv) {
+  EXPECT_CALL(*socket_factory_, OnSendTo(_))
+      .Times(4);
+
+  EXPECT_FALSE(resolver_->IsResolving());
+  EXPECT_FALSE(resolver_->HasResolved());
+  EXPECT_TRUE(resolver_->StartResolving());
+  EXPECT_TRUE(resolver_->IsResolving());
+  EXPECT_FALSE(resolver_->HasResolved());
+
+  EXPECT_CALL(*this, OnFinishedResolvingInternal(
+      ServiceResolver::STATUS_SUCCESS));
+
+  socket_factory_->SimulateReceive(
+      kSamplePacketSRVA, sizeof(kSamplePacketSRVA));
+
+  // TODO(noamsml): When NSEC record support is added, change this to use an
+  // NSEC record.
+  RunFor(base::TimeDelta::FromSeconds(4));
+
+  EXPECT_EQ(address_expected_.ToString(),
+            resolver_->GetServiceDescription().address.ToString());
+  EXPECT_EQ(std::vector<std::string>() ,
+            resolver_->GetServiceDescription().metadata);
+  EXPECT_EQ(ip_address_expected_,
+            resolver_->GetServiceDescription().ip_address);
+};
+
+TEST_F(ServiceResolverTest, WithNothing) {
+  EXPECT_CALL(*socket_factory_, OnSendTo(_))
+      .Times(4);
+
+  EXPECT_FALSE(resolver_->IsResolving());
+  EXPECT_FALSE(resolver_->HasResolved());
+  EXPECT_TRUE(resolver_->StartResolving());
+  EXPECT_TRUE(resolver_->IsResolving());
+  EXPECT_FALSE(resolver_->HasResolved());
+
+  EXPECT_CALL(*this, OnFinishedResolvingInternal(
+      ServiceResolver::STATUS_REQUEST_TIMEOUT));
+
+  // TODO(noamsml): When NSEC record support is added, change this to use an
+  // NSEC record.
+  RunFor(base::TimeDelta::FromSeconds(4));
+};
+
+}  // namespace
+
+}  // namespace local_discovery
diff --git a/chrome/browser/logging_chrome_browsertest.cc b/chrome/browser/logging_chrome_browsertest.cc
index d45b3f2..d3211fb 100644
--- a/chrome/browser/logging_chrome_browsertest.cc
+++ b/chrome/browser/logging_chrome_browsertest.cc
@@ -5,17 +5,17 @@
 #include "base/command_line.h"
 #include "base/environment.h"
 #include "chrome/common/chrome_switches.h"
-#include "chrome/common/url_constants.h"
 #include "chrome/common/env_vars.h"
 #include "chrome/common/logging_chrome.h"
+#include "chrome/common/url_constants.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_types.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_contents.h"
-#include "googleurl/src/gurl.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 using content::RenderProcessHost;
 
diff --git a/chrome/browser/mac/dock.mm b/chrome/browser/mac/dock.mm
index 51ac395..e55f4c8 100644
--- a/chrome/browser/mac/dock.mm
+++ b/chrome/browser/mac/dock.mm
@@ -47,7 +47,7 @@
 // Foundation data types and returns an autoreleased NSDictionary.
 NSDictionary* NSURLCopyDictionary(NSURL* url) {
   CFURLRef url_cf = base::mac::NSToCFCast(url);
-  base::mac::ScopedCFTypeRef<CFPropertyListRef> property_list(
+  base::ScopedCFTypeRef<CFPropertyListRef> property_list(
       _CFURLCopyPropertyListRepresentation(url_cf));
   CFDictionaryRef dictionary_cf =
       base::mac::CFCast<CFDictionaryRef>(property_list);
@@ -65,7 +65,7 @@
 // on Foundation data types and returns an autoreleased NSURL.
 NSURL* NSURLCreateFromDictionary(NSDictionary* dictionary) {
   CFDictionaryRef dictionary_cf = base::mac::NSToCFCast(dictionary);
-  base::mac::ScopedCFTypeRef<CFURLRef> url_cf(
+  base::ScopedCFTypeRef<CFURLRef> url_cf(
       _CFURLCreateFromPropertyListRepresentation(NULL, dictionary_cf));
   NSURL* url = base::mac::CFToNSCast(url_cf);
 
diff --git a/chrome/browser/mac/install_from_dmg.mm b/chrome/browser/mac/install_from_dmg.mm
index 56912db..ed64829 100644
--- a/chrome/browser/mac/install_from_dmg.mm
+++ b/chrome/browser/mac/install_from_dmg.mm
@@ -121,17 +121,15 @@
   }
 
   if (image_path) {
-    base::mac::ScopedCFTypeRef<CFTypeRef> image_path_cftyperef(
-        IORegistryEntryCreateCFProperty(hdix_drive,
-                                        CFSTR("image-path"),
-                                        NULL,
-                                        0));
+    base::ScopedCFTypeRef<CFTypeRef> image_path_cftyperef(
+        IORegistryEntryCreateCFProperty(
+            hdix_drive, CFSTR("image-path"), NULL, 0));
     if (!image_path_cftyperef) {
       LOG(ERROR) << "IORegistryEntryCreateCFProperty";
       return true;
     }
     if (CFGetTypeID(image_path_cftyperef) != CFDataGetTypeID()) {
-      base::mac::ScopedCFTypeRef<CFStringRef> observed_type_cf(
+      base::ScopedCFTypeRef<CFStringRef> observed_type_cf(
           CFCopyTypeIDDescription(CFGetTypeID(image_path_cftyperef)));
       std::string observed_type;
       if (observed_type_cf) {
@@ -516,7 +514,7 @@
         run_loop_running(false) {
   }
 
-  base::mac::ScopedCFTypeRef<DADissenterRef> dissenter;
+  base::ScopedCFTypeRef<DADissenterRef> dissenter;
   bool callback_called;
   bool run_loop_running;
 
@@ -605,13 +603,13 @@
 }  // namespace
 
 void EjectAndTrashDiskImage(const std::string& dmg_bsd_device_name) {
-  base::mac::ScopedCFTypeRef<DASessionRef> session(DASessionCreate(NULL));
+  base::ScopedCFTypeRef<DASessionRef> session(DASessionCreate(NULL));
   if (!session.get()) {
     LOG(ERROR) << "DASessionCreate";
     return;
   }
 
-  base::mac::ScopedCFTypeRef<DADiskRef> disk(
+  base::ScopedCFTypeRef<DADiskRef> disk(
       DADiskCreateFromBSDName(NULL, session, dmg_bsd_device_name.c_str()));
   if (!disk.get()) {
     LOG(ERROR) << "DADiskCreateFromBSDName";
diff --git a/chrome/browser/mac/keychain_reauthorize.mm b/chrome/browser/mac/keychain_reauthorize.mm
index 3e91511..24d046d 100644
--- a/chrome/browser/mac/keychain_reauthorize.mm
+++ b/chrome/browser/mac/keychain_reauthorize.mm
@@ -118,12 +118,10 @@
   // use CSSM_DL_DB_RECORD_ALL_KEYS, but that doesn't work.
   // CSSM_DL_DB_RECORD_ANY (as used by SecurityTool's keychain-dump) does
   // work.
-  base::mac::ScopedCFTypeRef<SecKeychainSearchRef> search(
-    CrSKeychainSearchCreateFromAttributes(NULL,
-                                          CSSM_DL_DB_RECORD_ANY,
-                                          NULL));
+  base::ScopedCFTypeRef<SecKeychainSearchRef> search(
+      CrSKeychainSearchCreateFromAttributes(NULL, CSSM_DL_DB_RECORD_ANY, NULL));
 
-  base::mac::ScopedCFTypeRef<SecTrustedApplicationRef> this_application(
+  base::ScopedCFTypeRef<SecTrustedApplicationRef> this_application(
       CrSTrustedApplicationCreateFromPath(NULL));
 
   std::vector<std::string> requirement_matches =
@@ -178,9 +176,9 @@
 
 std::string RequirementStringForApplication(
     SecTrustedApplicationRef application) {
-  base::mac::ScopedCFTypeRef<SecRequirementRef> requirement(
+  base::ScopedCFTypeRef<SecRequirementRef> requirement(
       CrSTrustedApplicationCopyRequirement(application));
-  base::mac::ScopedCFTypeRef<CFStringRef> requirement_string_cf(
+  base::ScopedCFTypeRef<CFStringRef> requirement_string_cf(
       CrSRequirementCopyString(requirement, kSecCSDefaultFlags));
   if (!requirement_string_cf) {
     return std::string();
@@ -298,7 +296,7 @@
     SecTrustedApplicationRef this_application) {
   std::vector<CrSKeychainItemAndAccess> items_and_accesses;
 
-  base::mac::ScopedCFTypeRef<SecKeychainItemRef> item;
+  base::ScopedCFTypeRef<SecKeychainItemRef> item;
   while (item.reset(CrSKeychainSearchCopyNext(search)), item) {
     scoped_ptr<CrSKeychainItemAndAccess> item_and_access(
         KCItemToKCItemAndReauthorizedAccess(item,
@@ -321,10 +319,8 @@
     return NULL;
   }
 
-  base::mac::ScopedCFTypeRef<SecAccessRef> access(
-      CrSKeychainItemCopyAccess(item));
-  base::mac::ScopedCFTypeRef<CFArrayRef> acl_list(
-      CrSAccessCopyACLList(access));
+  base::ScopedCFTypeRef<SecAccessRef> access(CrSKeychainItemCopyAccess(item));
+  base::ScopedCFTypeRef<CFArrayRef> acl_list(CrSAccessCopyACLList(access));
   if (!acl_list) {
     return NULL;
   }
@@ -444,7 +440,7 @@
 void WriteKCItemAndReauthorizedAccess(
     const CrSKeychainItemAndAccess& item_and_reauthorized_access) {
   SecKeychainItemRef old_item = item_and_reauthorized_access.item();
-  base::mac::ScopedCFTypeRef<SecKeychainRef> keychain(
+  base::ScopedCFTypeRef<SecKeychainRef> keychain(
       CrSKeychainItemCopyKeychain(old_item));
 
   ScopedCrSKeychainItemAttributesAndData old_attributes_and_data(
@@ -501,7 +497,7 @@
     return;
   }
 
-  base::mac::ScopedCFTypeRef<SecKeychainItemRef> new_item(
+  base::ScopedCFTypeRef<SecKeychainItemRef> new_item(
       CrSKeychainItemCreateFromContent(new_attributes_and_data,
                                        keychain,
                                        item_and_reauthorized_access.access()));
diff --git a/chrome/browser/mac/keystone_glue.h b/chrome/browser/mac/keystone_glue.h
index 8b696c2..d85763c 100644
--- a/chrome/browser/mac/keystone_glue.h
+++ b/chrome/browser/mac/keystone_glue.h
@@ -12,7 +12,7 @@
 #import <Foundation/Foundation.h>
 
 #include "base/mac/scoped_authorizationref.h"
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 
 // Possible outcomes of various operations.  A version may accompany some of
 // these, but beware: a version is never required.  For statuses that can be
@@ -89,7 +89,7 @@
   NSTimer* timer_;  // strong
 
   // The most recent kAutoupdateStatusNotification notification posted.
-  scoped_nsobject<NSNotification> recentNotification_;
+  base::scoped_nsobject<NSNotification> recentNotification_;
 
   // The authorization object, when it needs to persist because it's being
   // carried across threads.
diff --git a/chrome/browser/mac/keystone_glue.mm b/chrome/browser/mac/keystone_glue.mm
index 0a97252..f93e86d 100644
--- a/chrome/browser/mac/keystone_glue.mm
+++ b/chrome/browser/mac/keystone_glue.mm
@@ -97,9 +97,9 @@
     [target_ performSelector:sel_ withObject:arg_];
   }
 
-  scoped_nsobject<id> target_;
+  base::scoped_nsobject<id> target_;
   SEL sel_;
-  scoped_nsobject<id> arg_;
+  base::scoped_nsobject<id> arg_;
 };
 
 }  // namespace
diff --git a/chrome/browser/mac/relauncher.cc b/chrome/browser/mac/relauncher.cc
index 1f3db81..aa4794f 100644
--- a/chrome/browser/mac/relauncher.cc
+++ b/chrome/browser/mac/relauncher.cc
@@ -34,15 +34,6 @@
 #include "content/public/common/content_switches.h"
 #include "content/public/common/main_function_params.h"
 
-// RTLD_MAIN_ONLY is supported as of Mac OS X 10.5, but <dlfcn.h> does not
-// define it in the 10.5 SDK. It is present in the 10.6 SDK and is documented
-// as working on 10.5 and later. The source code for the version of dyld that
-// shipped in 10.5, dyld-95.3/src/dyldAPIs.cpp, confirms that this feature is
-// supported. Provide a fallback definition here.
-#if MAC_OS_X_VERSION_MAX_ALLOWED == MAC_OS_X_VERSION_10_5  // 10.5 SDK
-#define RTLD_MAIN_ONLY ((void*)-5)  // Search main executable only.
-#endif
-
 namespace mac_relauncher {
 
 const char* const kRelauncherDMGDeviceArg = "--dmg-device=";
@@ -294,7 +285,7 @@
   // won't contain the argv[0] of the relauncher process, the
   // RelauncherTypeArg() at argv[1], kRelauncherArgSeparator, or the
   // executable path of the process to be launched.
-  base::mac::ScopedCFTypeRef<CFMutableArrayRef> relaunch_args(
+  base::ScopedCFTypeRef<CFMutableArrayRef> relaunch_args(
       CFArrayCreateMutable(NULL, argc - 4, &kCFTypeArrayCallBacks));
   if (!relaunch_args) {
     LOG(ERROR) << "CFArrayCreateMutable";
@@ -335,7 +326,7 @@
         relaunch_executable.assign(arg);
         seen_relaunch_executable = true;
       } else {
-        base::mac::ScopedCFTypeRef<CFStringRef> arg_cf(
+        base::ScopedCFTypeRef<CFStringRef> arg_cf(
             base::SysUTF8ToCFStringRef(arg));
         if (!arg_cf) {
           LOG(ERROR) << "base::SysUTF8ToCFStringRef failed for " << arg;
diff --git a/chrome/browser/mac/security_wrappers.cc b/chrome/browser/mac/security_wrappers.cc
index 5e34b8a..85488d1 100644
--- a/chrome/browser/mac/security_wrappers.cc
+++ b/chrome/browser/mac/security_wrappers.cc
@@ -7,27 +7,6 @@
 #include "base/mac/foundation_util.h"
 #include "base/mac/mac_logging.h"
 
-#if !defined(MAC_OS_X_VERSION_10_5) || \
-    MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5
-
-enum {
-  // New Security.framework code uses errSecSuccess instead of noErr, but the
-  // constant is new in 10.6.
-  errSecSuccess = 0
-};
-
-// This exists on 10.5 for linking, but but because
-// <Security/SecRequirement.h> did not ship in the SDK in that version, no
-// declaration is present. This declaration is correct on 10.5, see
-// 10.5.0 libsecurity_codesigning-32568/lib/SecRequirement.h.
-extern "C" {
-OSStatus SecRequirementCopyString(SecRequirementRef requirement,
-                                  SecCSFlags flags,
-                                  CFStringRef* text);
-}  // extern "C"
-
-#endif
-
 extern "C" {
 OSStatus SecTrustedApplicationCopyRequirement(
     SecTrustedApplicationRef application,
@@ -361,7 +340,14 @@
     case kSecGenericPasswordItemClass:
       item_id = CSSM_DL_DB_RECORD_GENERIC_PASSWORD;
       break;
+    // kSecInternetPasswordItemClass is marked as deprecated in the 10.9 sdk,
+    // but the files in libsecurity_keychain from 10.7 referenced above still
+    // use it. Also see rdar://14281375 /
+    // http://openradar.appspot.com/radar?id=3143412 .
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
     case kSecAppleSharePasswordItemClass:
+#pragma clang diagnostic pop
       item_id = CSSM_DL_DB_RECORD_APPLESHARE_PASSWORD;
       break;
     default:
diff --git a/chrome/browser/mac/security_wrappers.h b/chrome/browser/mac/security_wrappers.h
index 42a7801..173c130 100644
--- a/chrome/browser/mac/security_wrappers.h
+++ b/chrome/browser/mac/security_wrappers.h
@@ -45,8 +45,8 @@
   SecAccessRef access() const { return access_; }
 
  private:
-  base::mac::ScopedCFTypeRef<SecKeychainItemRef> item_;
-  base::mac::ScopedCFTypeRef<SecAccessRef> access_;
+  base::ScopedCFTypeRef<SecKeychainItemRef> item_;
+  base::ScopedCFTypeRef<SecAccessRef> access_;
 };
 
 // Holds the return value from CrSACLCopySimpleContents and an argument to
@@ -56,8 +56,8 @@
   CrSACLSimpleContents();
   ~CrSACLSimpleContents();
 
-  base::mac::ScopedCFTypeRef<CFArrayRef> application_list;
-  base::mac::ScopedCFTypeRef<CFStringRef> description;
+  base::ScopedCFTypeRef<CFArrayRef> application_list;
+  base::ScopedCFTypeRef<CFStringRef> description;
   CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR prompt_selector;
 };
 
diff --git a/chrome/browser/managed_mode/managed_mode.cc b/chrome/browser/managed_mode/managed_mode.cc
index 1f3912a..4375615 100644
--- a/chrome/browser/managed_mode/managed_mode.cc
+++ b/chrome/browser/managed_mode/managed_mode.cc
@@ -51,7 +51,8 @@
 
   CommandLine* command_line = CommandLine::ForCurrentProcess();
 
-  if (ManagedUserService::AreManagedUsersEnabled()) {
+  if (CommandLine::ForCurrentProcess()->HasSwitch(
+      switches::kEnableManagedUsers)) {
     RecordAction(UserMetricsAction("ManagedMode_StartupEnableManagedSwitch"));
   }
 
diff --git a/chrome/browser/managed_mode/managed_mode_interstitial.cc b/chrome/browser/managed_mode/managed_mode_interstitial.cc
index d444fca..e74e665 100644
--- a/chrome/browser/managed_mode/managed_mode_interstitial.cc
+++ b/chrome/browser/managed_mode/managed_mode_interstitial.cc
@@ -52,19 +52,25 @@
   DictionaryValue strings;
   strings.SetString("blockPageTitle",
                     l10n_util::GetStringUTF16(IDS_BLOCK_INTERSTITIAL_TITLE));
-  strings.SetString("blockPageMessage",
-                    l10n_util::GetStringUTF16(IDS_BLOCK_INTERSTITIAL_MESSAGE));
+
+  Profile* profile =
+      Profile::FromBrowserContext(web_contents_->GetBrowserContext());
+  ManagedUserService* managed_user_service =
+      ManagedUserServiceFactory::GetForProfile(profile);
+  string16 custodian = UTF8ToUTF16(managed_user_service->GetCustodianName());
+  strings.SetString(
+      "blockPageMessage",
+      l10n_util::GetStringFUTF16(IDS_BLOCK_INTERSTITIAL_MESSAGE, custodian));
+
   strings.SetString("backButton", l10n_util::GetStringUTF16(IDS_BACK_BUTTON));
   strings.SetString(
       "requestAccessButton",
       l10n_util::GetStringUTF16(IDS_BLOCK_INTERSTITIAL_REQUEST_ACCESS_BUTTON));
 
-  // TODO(sergiu): Set name to real value here.
-  std::string custodian_name("John Doe");
   strings.SetString(
       "requestSentMessage",
       l10n_util::GetStringFUTF16(IDS_BLOCK_INTERSTITIAL_REQUEST_SENT_MESSAGE,
-                                 ASCIIToUTF16(custodian_name)));
+                                 custodian));
 
   webui::SetFontAndTextDirection(&strings);
 
diff --git a/chrome/browser/managed_mode/managed_mode_interstitial.h b/chrome/browser/managed_mode/managed_mode_interstitial.h
index ece0f31..656727c 100644
--- a/chrome/browser/managed_mode/managed_mode_interstitial.h
+++ b/chrome/browser/managed_mode/managed_mode_interstitial.h
@@ -11,7 +11,7 @@
 #include "base/compiler_specific.h"
 #include "base/memory/weak_ptr.h"
 #include "content/public/browser/interstitial_page_delegate.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 namespace content {
 class InterstitialPage;
diff --git a/chrome/browser/managed_mode/managed_mode_navigation_observer.cc b/chrome/browser/managed_mode/managed_mode_navigation_observer.cc
index c7666f8..7681a11 100644
--- a/chrome/browser/managed_mode/managed_mode_navigation_observer.cc
+++ b/chrome/browser/managed_mode/managed_mode_navigation_observer.cc
@@ -125,7 +125,7 @@
 }
 
 string16 ManagedModeWarningInfobarDelegate::GetMessageText() const {
-  return l10n_util::GetStringUTF16(IDS_MANAGED_MODE_WARNING_MESSAGE);
+  return l10n_util::GetStringUTF16(IDS_MANAGED_USER_WARN_INFOBAR_MESSAGE);
 }
 
 int ManagedModeWarningInfobarDelegate::GetButtons() const {
@@ -135,7 +135,7 @@
 string16 ManagedModeWarningInfobarDelegate::GetButtonLabel(
     InfoBarButton button) const {
   DCHECK_EQ(BUTTON_OK, button);
-  return l10n_util::GetStringUTF16(IDS_MANAGED_MODE_GO_BACK_ACTION);
+  return l10n_util::GetStringUTF16(IDS_MANAGED_USER_WARN_INFOBAR_GO_BACK);
 }
 
 bool ManagedModeWarningInfobarDelegate::Accept() {
diff --git a/chrome/browser/managed_mode/managed_mode_unittest.cc b/chrome/browser/managed_mode/managed_mode_unittest.cc
index d1d0241..a3fb02f 100644
--- a/chrome/browser/managed_mode/managed_mode_unittest.cc
+++ b/chrome/browser/managed_mode/managed_mode_unittest.cc
@@ -73,7 +73,7 @@
  public:
   BrowserFixture(FakeManagedMode* managed_mode,
                  TestingProfile* profile) {
-    Browser::CreateParams params(profile, chrome::HOST_DESKTOP_TYPE_NATIVE);
+    Browser::CreateParams params(profile, chrome::GetActiveDesktop());
     params.window = &window_;
     browser_.reset(new Browser(params));
   }
diff --git a/chrome/browser/managed_mode/managed_mode_url_filter.cc b/chrome/browser/managed_mode/managed_mode_url_filter.cc
index 85be975..189773e 100644
--- a/chrome/browser/managed_mode/managed_mode_url_filter.cc
+++ b/chrome/browser/managed_mode/managed_mode_url_filter.cc
@@ -15,7 +15,7 @@
 #include "base/threading/sequenced_worker_pool.h"
 #include "content/public/browser/browser_thread.h"
 #include "extensions/common/matcher/url_matcher.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 using content::BrowserThread;
 using extensions::URLMatcher;
diff --git a/chrome/browser/managed_mode/managed_mode_url_filter_unittest.cc b/chrome/browser/managed_mode/managed_mode_url_filter_unittest.cc
index f5ed8c5..4eaa308 100644
--- a/chrome/browser/managed_mode/managed_mode_url_filter_unittest.cc
+++ b/chrome/browser/managed_mode/managed_mode_url_filter_unittest.cc
@@ -7,8 +7,8 @@
 #include "base/message_loop.h"
 #include "base/run_loop.h"
 #include "chrome/browser/managed_mode/managed_mode_url_filter.h"
-#include "googleurl/src/gurl.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 class ManagedModeURLFilterTest : public ::testing::Test,
                                  public ManagedModeURLFilter::Observer {
diff --git a/chrome/browser/managed_mode/managed_user_refresh_token_fetcher.cc b/chrome/browser/managed_mode/managed_user_refresh_token_fetcher.cc
index de1a0fa..5c5a1a6 100644
--- a/chrome/browser/managed_mode/managed_user_refresh_token_fetcher.cc
+++ b/chrome/browser/managed_mode/managed_user_refresh_token_fetcher.cc
@@ -12,6 +12,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/signin/oauth2_token_service.h"
+#include "google_apis/gaia/gaia_constants.h"
 #include "google_apis/gaia/gaia_oauth_client.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "google_apis/gaia/google_service_auth_error.h"
@@ -25,6 +26,7 @@
 
 using base::Time;
 using gaia::GaiaOAuthClient;
+using GaiaConstants::kChromeSyncManagedOAuth2Scope;
 using net::URLFetcher;
 using net::URLFetcherDelegate;
 using net::URLRequestContextGetter;
@@ -33,9 +35,6 @@
 
 const int kNumRetries = 1;
 
-static const char kChromeSyncManagedScope[] =
-    "https://www.googleapis.com/auth/chromesync_playpen";
-
 static const char kIssueTokenBodyFormat[] =
     "client_id=%s"
     "&scope=%s"
@@ -161,7 +160,7 @@
       kIssueTokenBodyFormat,
       net::EscapeUrlEncodedData(
           GaiaUrls::GetInstance()->oauth2_chrome_client_id(), true).c_str(),
-      net::EscapeUrlEncodedData(kChromeSyncManagedScope, true).c_str(),
+      net::EscapeUrlEncodedData(kChromeSyncManagedOAuth2Scope, true).c_str(),
       net::EscapeUrlEncodedData(managed_user_id_, true).c_str(),
       net::EscapeUrlEncodedData(UTF16ToUTF8(name_), true).c_str(),
       net::EscapeUrlEncodedData(device_name_, true).c_str());
@@ -222,9 +221,7 @@
   GaiaUrls* urls = GaiaUrls::GetInstance();
   client_info.client_id = urls->oauth2_chrome_client_id();
   client_info.client_secret = urls->oauth2_chrome_client_secret();
-  gaia_oauth_client_.reset(
-      new gaia::GaiaOAuthClient(GaiaUrls::GetInstance()->oauth2_token_url(),
-                                context_));
+  gaia_oauth_client_.reset(new gaia::GaiaOAuthClient(context_));
   gaia_oauth_client_->GetTokensFromAuthCode(client_info, auth_code, kNumRetries,
                                             this);
 }
diff --git a/chrome/browser/managed_mode/managed_user_refresh_token_fetcher_unittest.cc b/chrome/browser/managed_mode/managed_user_refresh_token_fetcher_unittest.cc
index d488c11..424ed86 100644
--- a/chrome/browser/managed_mode/managed_user_refresh_token_fetcher_unittest.cc
+++ b/chrome/browser/managed_mode/managed_user_refresh_token_fetcher_unittest.cc
@@ -11,6 +11,7 @@
 #include "chrome/browser/signin/oauth2_token_service.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/test/test_browser_thread.h"
+#include "google_apis/gaia/gaia_oauth_client.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "google_apis/gaia/google_service_auth_error.h"
 #include "net/base/net_errors.h"
@@ -258,7 +259,8 @@
 
 net::TestURLFetcher*
 ManagedUserRefreshTokenFetcherTest::GetRefreshTokenRequest() {
-  net::TestURLFetcher* url_fetcher = url_fetcher_factory_.GetFetcherByID(0);
+  net::TestURLFetcher* url_fetcher = url_fetcher_factory_.GetFetcherByID(
+      gaia::GaiaOAuthClient::kUrlFetcherId);
   if (!url_fetcher)
     return NULL;
 
diff --git a/chrome/browser/managed_mode/managed_user_registration_service.cc b/chrome/browser/managed_mode/managed_user_registration_service.cc
index 25c5954..ae0da0e 100644
--- a/chrome/browser/managed_mode/managed_user_registration_service.cc
+++ b/chrome/browser/managed_mode/managed_user_registration_service.cc
@@ -74,7 +74,8 @@
     : weak_ptr_factory_(this),
       prefs_(prefs),
       token_fetcher_(token_fetcher.Pass()),
-      pending_managed_user_acknowledged_(false) {
+      pending_managed_user_acknowledged_(false),
+      download_profile_(NULL) {
   pref_change_registrar_.Init(prefs);
   pref_change_registrar_.Add(
       prefs::kGoogleServicesLastUsername,
@@ -143,6 +144,18 @@
                  weak_ptr_factory_.GetWeakPtr(), info.name));
 }
 
+void ManagedUserRegistrationService::DownloadProfile(
+    Profile* profile,
+    const DownloadProfileCallback& callback) {
+  download_callback_ = callback;
+  download_profile_ = profile;
+  // If another profile download is in progress, drop it. It's not worth
+  // queueing them up, and more likely that the one that hasn't ended yet is
+  // failing somehow than that the new one won't succeed.
+  profile_downloader_.reset(new ProfileDownloader(this));
+  profile_downloader_->Start();
+}
+
 void ManagedUserRegistrationService::CancelPendingRegistration() {
   AbortPendingRegistration(
       false,  // Don't run the callback. The error will be ignored.
@@ -399,3 +412,39 @@
   pending_managed_user_id_.clear();
   pending_managed_user_acknowledged_ = false;
 }
+
+bool ManagedUserRegistrationService::NeedsProfilePicture() const {
+  return false;
+}
+
+int ManagedUserRegistrationService::GetDesiredImageSideLength() const {
+  return 0;
+}
+
+std::string ManagedUserRegistrationService::GetCachedPictureURL() const {
+  return std::string();
+}
+
+Profile* ManagedUserRegistrationService::GetBrowserProfile() {
+  DCHECK(download_profile_);
+  return download_profile_;
+}
+
+void ManagedUserRegistrationService::OnProfileDownloadComplete() {
+  download_callback_.Reset();
+  download_profile_ = NULL;
+  profile_downloader_.reset();
+}
+
+void ManagedUserRegistrationService::OnProfileDownloadSuccess(
+    ProfileDownloader* downloader) {
+  download_callback_.Run(downloader->GetProfileFullName());
+  OnProfileDownloadComplete();
+}
+
+void ManagedUserRegistrationService::OnProfileDownloadFailure(
+    ProfileDownloader* downloader,
+    ProfileDownloaderDelegate::FailureReason reason) {
+  // Ignore failures; proceed without the custodian's name.
+  OnProfileDownloadComplete();
+}
diff --git a/chrome/browser/managed_mode/managed_user_registration_service.h b/chrome/browser/managed_mode/managed_user_registration_service.h
index c2938f4..c069ff4 100644
--- a/chrome/browser/managed_mode/managed_user_registration_service.h
+++ b/chrome/browser/managed_mode/managed_user_registration_service.h
@@ -12,7 +12,9 @@
 #include "base/memory/weak_ptr.h"
 #include "base/prefs/pref_change_registrar.h"
 #include "base/strings/string16.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
+#include "chrome/browser/profiles/profile_downloader.h"
+#include "chrome/browser/profiles/profile_downloader_delegate.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
 #include "sync/api/syncable_service.h"
@@ -40,7 +42,8 @@
 // management server and associating it with its custodian. It is owned by the
 // custodian's profile.
 class ManagedUserRegistrationService : public BrowserContextKeyedService,
-                                       public syncer::SyncableService {
+                                       public syncer::SyncableService,
+                                       public ProfileDownloaderDelegate {
  public:
   // Callback for Register() below. If registration is successful, |token| will
   // contain an OAuth2 refresh token for the newly registered managed user,
@@ -50,11 +53,26 @@
                               const std::string& /* token */)>
       RegistrationCallback;
 
+  // Callback for DownloadProfile() below. If the GAIA profile download is
+  // successful, the profile's full (display) name will be returned.
+  typedef base::Callback<void(const string16& /* full name */)>
+      DownloadProfileCallback;
+
   ManagedUserRegistrationService(
       PrefService* prefs,
       scoped_ptr<ManagedUserRefreshTokenFetcher> token_fetcher);
   virtual ~ManagedUserRegistrationService();
 
+  // ProfileDownloaderDelegate:
+  virtual bool NeedsProfilePicture() const OVERRIDE;
+  virtual int GetDesiredImageSideLength() const OVERRIDE;
+  virtual std::string GetCachedPictureURL() const OVERRIDE;
+  virtual Profile* GetBrowserProfile() OVERRIDE;
+  virtual void OnProfileDownloadSuccess(ProfileDownloader* downloader) OVERRIDE;
+  virtual void OnProfileDownloadFailure(
+      ProfileDownloader* downloader,
+      ProfileDownloaderDelegate::FailureReason reason) OVERRIDE;
+
   static void RegisterUserPrefs(user_prefs::PrefRegistrySyncable* registry);
 
   // Registers a new managed user with the server. |info| contains necessary
@@ -65,6 +83,14 @@
   void Register(const ManagedUserRegistrationInfo& info,
                 const RegistrationCallback& callback);
 
+  // Downloads the GAIA account information for the |profile|. This is a best-
+  // effort attempt with no error reporting nor timeout. If the download is
+  // successful, the profile's full (display) name will be returned via the
+  // callback. If the download fails or never completes, the callback will
+  // not be called.
+  void DownloadProfile(Profile* profile,
+                       const DownloadProfileCallback& callback);
+
   // Cancels any registration currently in progress, without calling the
   // callback or reporting an error. This should be called when the user
   // actively cancels the registration by canceling profile creation.
@@ -114,6 +140,8 @@
   void CompleteRegistration(bool run_callback,
                             const GoogleServiceAuthError& error);
 
+  void OnProfileDownloadComplete();
+
   base::WeakPtrFactory<ManagedUserRegistrationService> weak_ptr_factory_;
   PrefService* prefs_;
   PrefChangeRegistrar pref_change_registrar_;
@@ -130,6 +158,10 @@
   bool pending_managed_user_acknowledged_;
   RegistrationCallback callback_;
 
+  Profile* download_profile_;
+  scoped_ptr<ProfileDownloader> profile_downloader_;
+  DownloadProfileCallback download_callback_;
+
   DISALLOW_COPY_AND_ASSIGN(ManagedUserRegistrationService);
 };
 
diff --git a/chrome/browser/managed_mode/managed_user_service.cc b/chrome/browser/managed_mode/managed_user_service.cc
index 7ad603a..6d2e45f 100644
--- a/chrome/browser/managed_mode/managed_user_service.cc
+++ b/chrome/browser/managed_mode/managed_user_service.cc
@@ -139,10 +139,21 @@
 ManagedUserService::ManagedUserService(Profile* profile)
     : weak_ptr_factory_(this),
       profile_(profile),
-      elevated_for_testing_(false) {}
+      waiting_for_sync_initialization_(false),
+      elevated_for_testing_(false) {
+}
 
 ManagedUserService::~ManagedUserService() {}
 
+void ManagedUserService::Shutdown() {
+  if (!waiting_for_sync_initialization_)
+    return;
+
+  ProfileSyncService* sync_service =
+        ProfileSyncServiceFactory::GetForProfile(profile_);
+  sync_service->RemoveObserver(this);
+}
+
 bool ManagedUserService::ProfileIsManaged() const {
   return ProfileIsManaged(profile_);
 }
@@ -165,7 +176,12 @@
       prefs::kDefaultManagedModeFilteringBehavior, ManagedModeURLFilter::ALLOW,
       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
   registry->RegisterStringPref(
-      prefs::kManagedUserCustodian, std::string(),
+      prefs::kManagedUserCustodianEmail, std::string(),
+      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+  registry->RegisterStringPref(
+      prefs::kManagedUserCustodianName, std::string(),
+      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+  registry->RegisterBooleanPref(prefs::kManagedUserCreationAllowed, true,
       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
 }
 
@@ -207,7 +223,13 @@
 }
 
 std::string ManagedUserService::GetCustodianEmailAddress() const {
-  return profile_->GetPrefs()->GetString(prefs::kManagedUserCustodian);
+  return profile_->GetPrefs()->GetString(prefs::kManagedUserCustodianEmail);
+}
+
+std::string ManagedUserService::GetCustodianName() const {
+  std::string name = profile_->GetPrefs()->GetString(
+      prefs::kManagedUserCustodianName);
+  return name.empty() ? GetCustodianEmailAddress() : name;
 }
 
 std::string ManagedUserService::GetDebugPolicyProviderName() const {
@@ -269,6 +291,21 @@
       extension ? extension->id() : std::string(), error);
 }
 
+void ManagedUserService::OnStateChanged() {
+  ProfileSyncService* service =
+      ProfileSyncServiceFactory::GetForProfile(profile_);
+  if (waiting_for_sync_initialization_ && service->sync_initialized()) {
+    SetupSync();
+    service->RemoveObserver(this);
+    waiting_for_sync_initialization_ = false;
+    return;
+  }
+
+  DLOG_IF(ERROR, service->GetAuthError().state() ==
+                     GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)
+      << "Credentials rejected";
+}
+
 void ManagedUserService::Observe(int type,
                           const content::NotificationSource& source,
                           const content::NotificationDetails& details) {
@@ -296,6 +333,21 @@
   }
 }
 
+void ManagedUserService::SetupSync() {
+  ProfileSyncService* service =
+      ProfileSyncServiceFactory::GetForProfile(profile_);
+  DCHECK(service->sync_initialized());
+
+  bool sync_everything = false;
+  syncer::ModelTypeSet synced_datatypes;
+  synced_datatypes.Put(syncer::MANAGED_USER_SETTINGS);
+  service->OnUserChoseDatatypes(sync_everything, synced_datatypes);
+
+  // Notify ProfileSyncService that we are done with configuration.
+  service->SetSetupInProgress(false);
+  service->SetSyncSetupCompleted();
+}
+
 bool ManagedUserService::ExtensionManagementPolicyImpl(
     const std::string& extension_id,
     string16* error) const {
@@ -306,7 +358,7 @@
     return true;
 
   if (error)
-    *error = l10n_util::GetStringUTF16(IDS_EXTENSIONS_LOCKED_MANAGED_MODE);
+    *error = l10n_util::GetStringUTF16(IDS_EXTENSIONS_LOCKED_MANAGED_USER);
   return false;
 }
 
@@ -413,25 +465,24 @@
   Init();
 }
 
-void ManagedUserService::InitSync(const std::string& sync_token) {
+void ManagedUserService::InitSync(const std::string& refresh_token) {
   ProfileSyncService* service =
       ProfileSyncServiceFactory::GetForProfile(profile_);
-  DCHECK(!service->sync_initialized());
   // Tell the sync service that setup is in progress so we don't start syncing
   // until we've finished configuration.
   service->SetSetupInProgress(true);
 
   TokenService* token_service = TokenServiceFactory::GetForProfile(profile_);
-  token_service->AddAuthTokenManually(GaiaConstants::kSyncService, sync_token);
+  token_service->UpdateCredentialsWithOAuth2(
+      GaiaAuthConsumer::ClientOAuthResult(refresh_token, std::string(), 0));
 
-  bool sync_everything = false;
-  syncer::ModelTypeSet synced_datatypes;
-  synced_datatypes.Put(syncer::MANAGED_USER_SETTINGS);
-  service->OnUserChoseDatatypes(sync_everything, synced_datatypes);
-
-  // Notify ProfileSyncService that we are done with configuration.
-  service->SetSetupInProgress(false);
-  service->SetSyncSetupCompleted();
+  // Continue in SetupSync() once the Sync backend has been initialized.
+  if (service->sync_initialized()) {
+    SetupSync();
+  } else {
+    ProfileSyncServiceFactory::GetForProfile(profile_)->AddObserver(this);
+    waiting_for_sync_initialization_ = true;
+  }
 }
 
 // static
@@ -454,6 +505,11 @@
         command_line->GetSwitchValueASCII(switches::kManagedUserSyncToken));
   }
 
+  // TokenService only loads tokens automatically if we're signed in, so we have
+  // to nudge it ourselves.
+  TokenService* token_service = TokenServiceFactory::GetForProfile(profile_);
+  token_service->LoadTokensFromDB();
+
   extensions::ExtensionSystem* extension_system =
       extensions::ExtensionSystem::Get(profile_);
   extensions::ManagementPolicy* management_policy =
@@ -491,6 +547,8 @@
 void ManagedUserService::RegisterAndInitSync(
     Profile* custodian_profile,
     const ProfileManager::CreateCallback& callback) {
+
+  // Register the managed user with the custodian's account.
   ManagedUserRegistrationService* registration_service =
       ManagedUserRegistrationServiceFactory::GetForProfile(custodian_profile);
   string16 name = UTF8ToUTF16(
@@ -500,6 +558,19 @@
       info,
       base::Bind(&ManagedUserService::OnManagedUserRegistered,
                  weak_ptr_factory_.GetWeakPtr(), callback, custodian_profile));
+
+  // Fetch the custodian's profile information, to store the name.
+  // TODO(pamg): If --gaia-profile-info (keyword: switches::kGaiaProfileInfo)
+  // is ever enabled, take the name from the ProfileInfoCache instead.
+  registration_service->DownloadProfile(custodian_profile,
+    base::Bind(&ManagedUserService::OnCustodianProfileDownloaded,
+               weak_ptr_factory_.GetWeakPtr()));
+}
+
+void ManagedUserService::OnCustodianProfileDownloaded(
+    const string16& full_name) {
+  profile_->GetPrefs()->SetString(prefs::kManagedUserCustodianName,
+                                  UTF16ToUTF8(full_name));
 }
 
 void ManagedUserService::OnManagedUserRegistered(
@@ -517,7 +588,7 @@
   InitSync(token);
   SigninManagerBase* signin =
       SigninManagerFactory::GetForProfile(custodian_profile);
-  profile_->GetPrefs()->SetString(prefs::kManagedUserCustodian,
+  profile_->GetPrefs()->SetString(prefs::kManagedUserCustodianEmail,
                                   signin->GetAuthenticatedUsername());
   callback.Run(profile_, Profile::CREATE_STATUS_INITIALIZED);
 }
diff --git a/chrome/browser/managed_mode/managed_user_service.h b/chrome/browser/managed_mode/managed_user_service.h
index 43677d9..7c6da2a 100644
--- a/chrome/browser/managed_mode/managed_user_service.h
+++ b/chrome/browser/managed_mode/managed_user_service.h
@@ -14,6 +14,7 @@
 #include "chrome/browser/extensions/management_policy.h"
 #include "chrome/browser/managed_mode/managed_mode_url_filter.h"
 #include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/sync/profile_sync_service_observer.h"
 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
@@ -39,6 +40,7 @@
 // manual whitelist/blacklist overrides).
 class ManagedUserService : public BrowserContextKeyedService,
                            public extensions::ManagementPolicy::Provider,
+                           public ProfileSyncServiceObserver,
                            public content::NotificationObserver {
  public:
   typedef std::vector<string16> CategoryList;
@@ -52,6 +54,9 @@
   explicit ManagedUserService(Profile* profile);
   virtual ~ManagedUserService();
 
+  // ProfileKeyedService override:
+  virtual void Shutdown() OVERRIDE;
+
   bool ProfileIsManaged() const;
 
   // Checks whether the given profile is managed without constructing a
@@ -60,8 +65,9 @@
 
   static void RegisterUserPrefs(user_prefs::PrefRegistrySyncable* registry);
 
-  // Returns whether managed users are enabled by Finch or the command line
-  // flag.
+  // Returns true if managed users are enabled by either Finch or the command
+  // line flag.
+  // TODO(pamg, sergiu): Remove this once the feature is fully launched.
   static bool AreManagedUsersEnabled();
 
   // Returns the URL filter for the IO thread, for filtering network requests
@@ -88,6 +94,10 @@
   // Returns the email address of the custodian.
   std::string GetCustodianEmailAddress() const;
 
+  // Returns the name of the custodian, or the email address if the name is
+  // empty.
+  std::string GetCustodianName() const;
+
   // These methods allow querying and modifying the manual filtering behavior.
   // The manual behavior is set by the user and overrides all other settings
   // (whitelists or the default behavior).
@@ -109,9 +119,9 @@
   // Marks the profile as managed and initializes it.
   void InitForTesting();
 
-  // Initializes this profile for syncing, using the provided |token| to
-  // authenticate requests.
-  void InitSync(const std::string& token);
+  // Initializes this profile for syncing, using the provided |refresh_token| to
+  // mint access tokens for Sync.
+  void InitSync(const std::string& refresh_token);
 
   // Convenience method that registers this managed user with
   // |registration_service| and initializes sync with the returned token.
@@ -138,6 +148,9 @@
   virtual bool UserMayModifySettings(const extensions::Extension* extension,
                                      string16* error) const OVERRIDE;
 
+  // ProfileSyncServiceObserver implementation:
+  virtual void OnStateChanged() OVERRIDE;
+
   // content::NotificationObserver implementation:
   virtual void Observe(int type,
                        const content::NotificationSource& source,
@@ -176,11 +189,15 @@
     DISALLOW_COPY_AND_ASSIGN(URLFilterContext);
   };
 
+  void OnCustodianProfileDownloaded(const string16& full_name);
+
   void OnManagedUserRegistered(const ProfileManager::CreateCallback& callback,
                                Profile* custodian_profile,
                                const GoogleServiceAuthError& auth_error,
                                const std::string& token);
 
+  void SetupSync();
+
   // Internal implementation for ExtensionManagementPolicy::Delegate methods.
   // If |error| is not NULL, it will be filled with an error message if the
   // requested extension action (install, modify status, etc.) is not permitted.
@@ -213,6 +230,9 @@
   content::NotificationRegistrar registrar_;
   PrefChangeRegistrar pref_change_registrar_;
 
+  // True iff we're waiting for the Sync service to be initialized.
+  bool waiting_for_sync_initialization_;
+
   // Sets a profile in elevated state for testing if set to true.
   bool elevated_for_testing_;
 
diff --git a/chrome/browser/media/chrome_media_stream_infobar_browsertest.cc b/chrome/browser/media/chrome_media_stream_infobar_browsertest.cc
new file mode 100644
index 0000000..1e85475
--- /dev/null
+++ b/chrome/browser/media/chrome_media_stream_infobar_browsertest.cc
@@ -0,0 +1,287 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/file_util.h"
+#include "base/path_service.h"
+#include "base/process_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/test/test_timeouts.h"
+#include "base/time/time.h"
+#include "chrome/browser/content_settings/host_content_settings_map.h"
+#include "chrome/browser/infobars/infobar.h"
+#include "chrome/browser/infobars/infobar_service.h"
+#include "chrome/browser/media/media_stream_infobar_delegate.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_tabstrip.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/content_settings_types.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "chrome/test/ui/ui_test.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/test/browser_test_utils.h"
+#include "net/test/spawned_test_server/spawned_test_server.h"
+
+static const char kMainWebrtcTestHtmlPage[] =
+    "files/webrtc/webrtc_jsep01_test.html";
+static const char kFailedWithErrorPermissionDenied[] =
+    "failed-with-error-PERMISSION_DENIED";
+
+static const char kAudioVideoCallConstraints[] = "'{audio: true, video: true}'";
+static const char kAudioOnlyCallConstraints[] = "'{audio: true}'";
+static const char kVideoOnlyCallConstraints[] = "'{video: true}'";
+static const char kOkGotStream[] = "ok-got-stream";
+
+// Media stream infobar test for WebRTC.
+class MediaStreamInfobarTest : public InProcessBrowserTest {
+ public:
+  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+    // This test expects to run with fake devices but real UI.
+    command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream);
+    EXPECT_FALSE(command_line->HasSwitch(switches::kUseFakeUIForMediaStream))
+        << "Since this test tests the UI we want the real UI!";
+  }
+ protected:
+  content::WebContents* LoadTestPageInTab() {
+    EXPECT_TRUE(test_server()->Start());
+
+    ui_test_utils::NavigateToURL(
+        browser(), test_server()->GetURL(kMainWebrtcTestHtmlPage));
+    return browser()->tab_strip_model()->GetActiveWebContents();
+  }
+
+  // TODO(phoglund): upstream and reuse in other browser tests.
+  MediaStreamInfoBarDelegate* GetUserMediaAndWaitForInfobar(
+      content::WebContents* tab_contents,
+      const std::string& constraints) {
+    content::WindowedNotificationObserver infobar_added(
+        chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED,
+        content::NotificationService::AllSources());
+
+    // Request user media: this will launch the media stream info bar.
+    GetUserMedia(constraints, tab_contents);
+
+    // Wait for the bar to pop up, then return it
+    infobar_added.Wait();
+    content::Details<InfoBarAddedDetails> details(infobar_added.details());
+    MediaStreamInfoBarDelegate* media_infobar =
+        details.ptr()->AsMediaStreamInfoBarDelegate();
+    return media_infobar;
+  }
+
+  void CloseInfobarInTab(content::WebContents* tab_contents,
+                         MediaStreamInfoBarDelegate* infobar) {
+    content::WindowedNotificationObserver infobar_removed(
+        chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
+        content::NotificationService::AllSources());
+
+    InfoBarService* infobar_service =
+        InfoBarService::FromWebContents(tab_contents);
+    infobar_service->RemoveInfoBar(infobar);
+
+    infobar_removed.Wait();
+  }
+
+  // Convenience method which executes the provided javascript in the context
+  // of the provided web contents and returns what it evaluated to.
+  std::string ExecuteJavascript(const std::string& javascript,
+                                content::WebContents* tab_contents) {
+    std::string result;
+    EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+        tab_contents, javascript, &result));
+    return result;
+  }
+
+  void TestAcceptOnInfobar(content::WebContents* tab_contents) {
+    TestAcceptOnInfobarWithSpecificConstraints(tab_contents,
+                                               kAudioVideoCallConstraints);
+  }
+
+  void TestAcceptOnInfobarWithSpecificConstraints(
+      content::WebContents* tab_contents, const std::string& constraints) {
+    MediaStreamInfoBarDelegate* media_infobar =
+        GetUserMediaAndWaitForInfobar(tab_contents, constraints);
+
+    media_infobar->Accept();
+
+    CloseInfobarInTab(tab_contents, media_infobar);
+
+    // Wait for WebRTC to call the success callback.
+    EXPECT_TRUE(UglyPollingWaitUntil(
+        "obtainGetUserMediaResult()", kOkGotStream, tab_contents));
+  }
+
+  void TestDenyOnInfobar(content::WebContents* tab_contents) {
+    return TestDenyWithSpecificConstraints(tab_contents,
+                                           kAudioVideoCallConstraints);
+  }
+
+  void TestDenyWithSpecificConstraints(content::WebContents* tab_contents,
+                                       const std::string& constraints) {
+    MediaStreamInfoBarDelegate* media_infobar =
+        GetUserMediaAndWaitForInfobar(tab_contents, constraints);
+
+    media_infobar->Cancel();
+
+    CloseInfobarInTab(tab_contents, media_infobar);
+
+    // Wait for WebRTC to call the fail callback.
+    EXPECT_TRUE(UglyPollingWaitUntil("obtainGetUserMediaResult()",
+                                     kFailedWithErrorPermissionDenied,
+                                     tab_contents));
+  }
+
+  void TestDismissOnInfobar(content::WebContents* tab_contents) {
+    MediaStreamInfoBarDelegate* media_infobar =
+        GetUserMediaAndWaitForInfobar(tab_contents, kAudioVideoCallConstraints);
+
+    media_infobar->InfoBarDismissed();
+
+    CloseInfobarInTab(tab_contents, media_infobar);
+
+    // A dismiss should be treated like a deny.
+    EXPECT_TRUE(UglyPollingWaitUntil("obtainGetUserMediaResult()",
+                                     kFailedWithErrorPermissionDenied,
+                                     tab_contents));
+  }
+
+  // TODO(phoglund): de-dupe
+  // TODO(phoglund): This ugly poll method is only here while we transition
+  // the test javascript to just post events when things happen. Right now they
+  // don't because the webrtc_call.py and other tests use this polling way of
+  // communicating when we are waiting from an asynchronous event in the
+  // javascript. This method is meant to emulate WaitUntil in the PyAuto
+  // framework.
+  bool UglyPollingWaitUntil(const std::string& javascript,
+                            const std::string& evaluates_to,
+                            content::WebContents* tab_contents) {
+    const base::Time start_time = base::Time::Now();
+    const base::TimeDelta timeout = TestTimeouts::action_max_timeout();
+    std::string result;
+
+    while (base::Time::Now() - start_time < timeout) {
+      result = ExecuteJavascript(javascript, tab_contents);
+      LOG(INFO) << result;
+      if (evaluates_to == result)
+        return true;
+    }
+    LOG(ERROR) << "Timed out while waiting for " << javascript
+               << " to evaluate to " << evaluates_to << "; last result was '"
+               << result << "'";
+    return false;
+  }
+
+  void GetUserMedia(const std::string& constraints,
+                    content::WebContents* tab_contents) {
+    // Request user media: this will launch the media stream info bar.
+    EXPECT_EQ("ok-requested",
+              ExecuteJavascript(
+                  base::StringPrintf("getUserMedia(%s);", constraints.c_str()),
+                  tab_contents));
+  }
+};
+
+IN_PROC_BROWSER_TEST_F(MediaStreamInfobarTest, TestAllowingUserMedia) {
+  content::WebContents* tab_contents = LoadTestPageInTab();
+  TestAcceptOnInfobar(tab_contents);
+}
+
+IN_PROC_BROWSER_TEST_F(MediaStreamInfobarTest, TestDenyingUserMedia) {
+  content::WebContents* tab_contents = LoadTestPageInTab();
+  TestDenyOnInfobar(tab_contents);
+}
+
+IN_PROC_BROWSER_TEST_F(MediaStreamInfobarTest, TestDismissingInfobar) {
+  content::WebContents* tab_contents = LoadTestPageInTab();
+  TestDismissOnInfobar(tab_contents);
+}
+
+IN_PROC_BROWSER_TEST_F(MediaStreamInfobarTest,
+                       TestAcceptThenDenyWhichShouldBeSticky) {
+  content::WebContents* tab_contents = LoadTestPageInTab();
+
+  TestAcceptOnInfobar(tab_contents);
+  TestDenyOnInfobar(tab_contents);
+
+  // Should fail with permission denied right away with no infobar popping up.
+  GetUserMedia(kAudioVideoCallConstraints, tab_contents);
+  EXPECT_TRUE(UglyPollingWaitUntil("obtainGetUserMediaResult()",
+                                   kFailedWithErrorPermissionDenied,
+                                   tab_contents));
+  InfoBarService* infobar_service =
+      InfoBarService::FromWebContents(tab_contents);
+  EXPECT_EQ(0u, infobar_service->infobar_count());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaStreamInfobarTest, TestAcceptIsNotSticky) {
+  content::WebContents* tab_contents = LoadTestPageInTab();
+
+  // If accept were sticky the second call would hang because it hangs if an
+  // infobar does not pop up.
+  TestAcceptOnInfobar(tab_contents);
+  TestAcceptOnInfobar(tab_contents);
+}
+
+IN_PROC_BROWSER_TEST_F(MediaStreamInfobarTest, TestDismissIsNotSticky) {
+  content::WebContents* tab_contents = LoadTestPageInTab();
+
+  // If dismiss were sticky the second call would hang because it hangs if an
+  // infobar does not pop up.
+  TestDismissOnInfobar(tab_contents);
+  TestDismissOnInfobar(tab_contents);
+}
+
+IN_PROC_BROWSER_TEST_F(MediaStreamInfobarTest,
+                       TestDenyingThenClearingStickyException) {
+  content::WebContents* tab_contents = LoadTestPageInTab();
+
+  TestDenyOnInfobar(tab_contents);
+
+  HostContentSettingsMap* settings_map =
+      browser()->profile()->GetHostContentSettingsMap();
+
+  settings_map->ClearSettingsForOneType(
+      CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC);
+  settings_map->ClearSettingsForOneType(
+      CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA);
+
+  // If an infobar is not launched now, this will hang.
+  TestDenyOnInfobar(tab_contents);
+}
+
+IN_PROC_BROWSER_TEST_F(MediaStreamInfobarTest,
+                       DenyingMicDoesNotCauseStickyDenyForCameras) {
+  content::WebContents* tab_contents = LoadTestPageInTab();
+
+  // If mic blocking also blocked cameras, the second call here would hang.
+  TestDenyWithSpecificConstraints(tab_contents, kAudioOnlyCallConstraints);
+  TestAcceptOnInfobarWithSpecificConstraints(tab_contents,
+                                             kVideoOnlyCallConstraints);
+}
+
+IN_PROC_BROWSER_TEST_F(MediaStreamInfobarTest,
+                       DenyingCameraDoesNotCauseStickyDenyForMics) {
+  content::WebContents* tab_contents = LoadTestPageInTab();
+
+  // If camera blocking also blocked mics, the second call here would hang.
+  TestDenyWithSpecificConstraints(tab_contents, kVideoOnlyCallConstraints);
+  TestAcceptOnInfobarWithSpecificConstraints(tab_contents,
+                                             kAudioOnlyCallConstraints);
+}
+
+IN_PROC_BROWSER_TEST_F(MediaStreamInfobarTest,
+                       DenyingMicStillSucceedsWithCameraForAudioVideoCalls) {
+  content::WebContents* tab_contents = LoadTestPageInTab();
+
+  // If microphone blocking also blocked a AV call, the second call here
+  // would hang. The requester should only be granted access to the cam though.
+  TestDenyWithSpecificConstraints(tab_contents, kAudioOnlyCallConstraints);
+  TestAcceptOnInfobarWithSpecificConstraints(tab_contents,
+                                             kAudioVideoCallConstraints);
+
+  // TODO(phoglund): verify the requester actually only gets video tracks.
+}
diff --git a/chrome/browser/media/chrome_webrtc_browsertest.cc b/chrome/browser/media/chrome_webrtc_browsertest.cc
index 50ab0bc..fe63cd6 100644
--- a/chrome/browser/media/chrome_webrtc_browsertest.cc
+++ b/chrome/browser/media/chrome_webrtc_browsertest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,7 +6,7 @@
 #include "base/path_service.h"
 #include "base/process_util.h"
 #include "base/strings/stringprintf.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/infobars/infobar.h"
 #include "chrome/browser/infobars/infobar_service.h"
 #include "chrome/browser/media/media_stream_infobar_delegate.h"
@@ -21,7 +21,7 @@
 #include "chrome/test/ui/ui_test.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/test/browser_test_utils.h"
-#include "net/test/spawned_test_server/spawned_test_server.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
 
 static const base::FilePath::CharType kPeerConnectionServer[] =
 #if defined(OS_WIN)
@@ -31,7 +31,7 @@
 #endif
 
 static const char kMainWebrtcTestHtmlPage[] =
-    "files/webrtc/webrtc_jsep01_test.html";
+    "/webrtc/webrtc_jsep01_test.html";
 
 // Top-level integration test for WebRTC. Requires a real webcam and microphone
 // on the running system. This test is not meant to run in the main browser
@@ -58,6 +58,8 @@
     // device; it will not work with fake devices.
     EXPECT_FALSE(command_line->HasSwitch(
         switches::kUseFakeDeviceForMediaStream));
+    EXPECT_FALSE(command_line->HasSwitch(
+        switches::kUseFakeUIForMediaStream));
   }
 
   // TODO(phoglund): This ugly poll method is only here while we transition
@@ -216,10 +218,10 @@
 
 IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest,
                        MANUAL_RunsAudioVideoWebRTCCallInTwoTabs) {
-  EXPECT_TRUE(test_server()->Start());
+  EXPECT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   ui_test_utils::NavigateToURL(
-      browser(), test_server()->GetURL(kMainWebrtcTestHtmlPage));
+      browser(), embedded_test_server()->GetURL(kMainWebrtcTestHtmlPage));
   content::WebContents* left_tab =
       browser()->tab_strip_model()->GetActiveWebContents();
   GetUserMedia(left_tab);
@@ -228,7 +230,7 @@
   content::WebContents* right_tab =
       browser()->tab_strip_model()->GetActiveWebContents();
   ui_test_utils::NavigateToURL(
-        browser(), test_server()->GetURL(kMainWebrtcTestHtmlPage));
+        browser(), embedded_test_server()->GetURL(kMainWebrtcTestHtmlPage));
   GetUserMedia(right_tab);
 
   ConnectToPeerConnectionServer("peer 1", left_tab);
@@ -255,10 +257,10 @@
 
 IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest,
                        MANUAL_TestMediaStreamTrackEnableDisable) {
-  EXPECT_TRUE(test_server()->Start());
+  EXPECT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   ui_test_utils::NavigateToURL(
-      browser(), test_server()->GetURL(kMainWebrtcTestHtmlPage));
+      browser(), embedded_test_server()->GetURL(kMainWebrtcTestHtmlPage));
   content::WebContents* left_tab =
       browser()->tab_strip_model()->GetActiveWebContents();
   GetUserMedia(left_tab);
@@ -267,7 +269,7 @@
   content::WebContents* right_tab =
       browser()->tab_strip_model()->GetActiveWebContents();
   ui_test_utils::NavigateToURL(
-        browser(), test_server()->GetURL(kMainWebrtcTestHtmlPage));
+        browser(), embedded_test_server()->GetURL(kMainWebrtcTestHtmlPage));
   GetUserMedia(right_tab);
 
   ConnectToPeerConnectionServer("peer 1", left_tab);
diff --git a/chrome/browser/media/chrome_webrtc_video_quality_browsertest.cc b/chrome/browser/media/chrome_webrtc_video_quality_browsertest.cc
new file mode 100644
index 0000000..68f9057
--- /dev/null
+++ b/chrome/browser/media/chrome_webrtc_video_quality_browsertest.cc
@@ -0,0 +1,531 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/environment.h"
+#include "base/file_util.h"
+#include "base/path_service.h"
+#include "base/process_util.h"
+#include "base/strings/string_split.h"
+#include "base/strings/stringprintf.h"
+#include "base/test/test_timeouts.h"
+#include "base/time/time.h"
+#include "chrome/browser/infobars/infobar.h"
+#include "chrome/browser/infobars/infobar_service.h"
+#include "chrome/browser/media/media_stream_infobar_delegate.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_tabstrip.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "chrome/test/perf/perf_test.h"
+#include "chrome/test/ui/ui_test.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/test/browser_test_utils.h"
+#include "net/test/python_utils.h"
+#include "net/test/spawned_test_server/spawned_test_server.h"
+
+static const base::FilePath::CharType kPeerConnectionServer[] =
+#if defined(OS_WIN)
+    FILE_PATH_LITERAL("peerconnection_server.exe");
+#else
+    FILE_PATH_LITERAL("peerconnection_server");
+#endif
+
+static const base::FilePath::CharType kFrameAnalyzerExecutable[] =
+#if defined(OS_WIN)
+    FILE_PATH_LITERAL("frame_analyzer.exe");
+#else
+    FILE_PATH_LITERAL("frame_analyzer");
+#endif
+
+static const base::FilePath::CharType kArgbToI420ConverterExecutable[] =
+#if defined(OS_WIN)
+    FILE_PATH_LITERAL("rgba_to_i420_converter.exe");
+#else
+    FILE_PATH_LITERAL("rgba_to_i420_converter");
+#endif
+
+static const char kHomeEnvName[] =
+#if defined(OS_WIN)
+    "HOMEPATH";
+#else
+    "HOME";
+#endif
+
+// The working dir should be in the user's home folder.
+static const base::FilePath::CharType kWorkingDirName[] =
+    FILE_PATH_LITERAL("webrtc_video_quality");
+static const base::FilePath::CharType kReferenceYuvFileName[] =
+    FILE_PATH_LITERAL("reference_video.yuv");
+static const base::FilePath::CharType kCapturedYuvFileName[] =
+    FILE_PATH_LITERAL("captured_video.yuv");
+static const base::FilePath::CharType kStatsFileName[] =
+    FILE_PATH_LITERAL("stats.txt");
+static const char kMainWebrtcTestHtmlPage[] =
+    "files/webrtc/webrtc_jsep01_test.html";
+static const char kCapturingWebrtcHtmlPage[] =
+    "files/webrtc/webrtc_video_quality_test.html";
+static const int kVgaWidth = 640;
+static const int kVgaHeight = 480;
+
+// If you change the port number, don't forget to modify video_extraction.js
+// too!
+static const char kPyWebSocketPortNumber[] = "12221";
+
+// Test the video quality of the WebRTC output.
+//
+// Prerequisites: This test case must run on a machine with a virtual webcam
+// that plays video from the reference file located in <the running users home
+// folder>/kWorkingDirName/kReferenceYuvFileName.
+//
+// You must also compile the chromium_builder_webrtc target before you run this
+// test to get all the tools built.
+//
+// The external compare_videos.py script also depends on two external
+// executables which must be located in the PATH when running this test.
+// * zxing (see the CPP version at https://code.google.com/p/zxing)
+// * ffmpeg 0.11.1 or compatible version (see http://www.ffmpeg.org)
+//
+// The test case will launch a custom binary (peerconnection_server) which will
+// allow two WebRTC clients to find each other.
+//
+// The test also runs several other custom binaries - rgba_to_i420 converter and
+// frame_analyzer. Both tools can be found under third_party/webrtc/tools. The
+// test also runs a stand alone Python implementation of a WebSocket server
+// (pywebsocket) and a barcode_decoder script.
+class WebrtcVideoQualityBrowserTest : public InProcessBrowserTest {
+ public:
+  WebrtcVideoQualityBrowserTest()
+      : peerconnection_server_(0),
+        pywebsocket_server_(0),
+        environment_(base::Environment::Create()) {}
+
+  virtual void SetUp() OVERRIDE {
+    RunPeerConnectionServer();
+    InProcessBrowserTest::SetUp();
+
+    // Ensure we have the stuff we need.
+    EXPECT_TRUE(file_util::PathExists(GetWorkingDir()))
+        << "Cannot find the working directory for the reference video and "
+           "the temporary files:" << GetWorkingDir().value();
+    base::FilePath reference_file =
+        GetWorkingDir().Append(kReferenceYuvFileName);
+    EXPECT_TRUE(file_util::PathExists(reference_file))
+        << "Cannot find the reference file to be used for video quality "
+        << "comparison: " << reference_file.value();
+  }
+
+  virtual void TearDown() OVERRIDE {
+    ShutdownPeerConnectionServer();
+    InProcessBrowserTest::TearDown();
+    ShutdownPyWebSocketServer();
+  }
+
+  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+    // TODO(phoglund): check that user actually has the requisite devices and
+    // print a nice message if not; otherwise the test just times out which can
+    // be confusing.
+    // This test expects real device handling and requires a real webcam / audio
+    // device; it will not work with fake devices.
+    EXPECT_FALSE(
+        command_line->HasSwitch(switches::kUseFakeDeviceForMediaStream))
+        << "You cannot run this test with fake devices.";
+  }
+
+  void StartPyWebSocketServer() {
+    base::FilePath path_pywebsocket_dir =
+        GetSourceDir().Append(FILE_PATH_LITERAL("third_party/pywebsocket/src"));
+    base::FilePath pywebsocket_server = path_pywebsocket_dir.Append(
+        FILE_PATH_LITERAL("mod_pywebsocket/standalone.py"));
+    base::FilePath path_to_data_handler =
+        GetSourceDir().Append(FILE_PATH_LITERAL("chrome/test/functional"));
+
+    EXPECT_TRUE(file_util::PathExists(pywebsocket_server))
+        << "Fatal: missing pywebsocket server.";
+    EXPECT_TRUE(file_util::PathExists(path_to_data_handler))
+        << "Fatal: missing data handler for pywebsocket server.";
+
+    AppendToPythonPath(path_pywebsocket_dir);
+    CommandLine pywebsocket_command = MakePythonCommand(pywebsocket_server);
+
+    // Construct the command line manually, the server doesn't support -arg=val.
+    pywebsocket_command.AppendArg("-p");
+    pywebsocket_command.AppendArg(kPyWebSocketPortNumber);
+    pywebsocket_command.AppendArg("-d");
+    pywebsocket_command.AppendArgPath(path_to_data_handler);
+
+    LOG(INFO) << "Running " << pywebsocket_command.GetCommandLineString();
+    EXPECT_TRUE(base::LaunchProcess(
+        pywebsocket_command, base::LaunchOptions(), &pywebsocket_server_))
+        << "Failed to launch pywebsocket server.";
+  }
+
+  void ShutdownPyWebSocketServer() {
+    EXPECT_TRUE(base::KillProcess(pywebsocket_server_, 0, false))
+        << "Failed to shut down pywebsocket server!";
+  }
+
+  // TODO(phoglund): This ugly poll method is only here while we transition
+  // the test javascript to just post events when things happen. Right now they
+  // don't because the webrtc_call.py and other tests use this polling way of
+  // communicating when we are waiting from an asynchronous event in the
+  // javascript. This method is meant to emulate WaitUntil in the PyAuto
+  // framework.
+  bool UglyPollingWaitUntil(const std::string& javascript,
+                            const std::string& evaluates_to,
+                            content::WebContents* tab_contents) {
+    base::Time start_time = base::Time::Now();
+    base::TimeDelta timeout = TestTimeouts::action_max_timeout();
+    std::string result;
+
+    while (base::Time::Now() - start_time < timeout) {
+      result = ExecuteJavascript(javascript, tab_contents);
+      if (evaluates_to == result)
+        return true;
+    }
+    LOG(ERROR) << "Timed out while waiting for " << javascript
+               << " to evaluate to " << evaluates_to << "; last result was '"
+               << result << "'";
+    return false;
+  }
+
+  // Convenience method which executes the provided javascript in the context
+  // of the provided web contents and returns what it evaluated to.
+  std::string ExecuteJavascript(const std::string& javascript,
+                                content::WebContents* tab_contents) {
+    std::string result;
+    EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+        tab_contents, javascript, &result));
+    return result;
+  }
+
+  void GetUserMedia(content::WebContents* tab_contents) {
+    content::WindowedNotificationObserver infobar_added(
+        chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED,
+        content::NotificationService::AllSources());
+
+    // Request user media: this will launch the media stream info bar.
+    EXPECT_EQ("ok-requested",
+              ExecuteJavascript("getUserMedia('{video: true, audio: true}');",
+                                tab_contents));
+
+    // Wait for the bar to pop up, then accept.
+    infobar_added.Wait();
+    content::Details<InfoBarAddedDetails> details(infobar_added.details());
+    MediaStreamInfoBarDelegate* media_infobar =
+        details.ptr()->AsMediaStreamInfoBarDelegate();
+    media_infobar->Accept();
+
+    // Wait for WebRTC to call the success callback.
+    EXPECT_TRUE(UglyPollingWaitUntil(
+        "obtainGetUserMediaResult();", "ok-got-stream", tab_contents));
+  }
+
+  // Ensures we didn't get any errors asynchronously (e.g. while no javascript
+  // call from this test was outstanding).
+  // TODO(phoglund): this becomes obsolete when we switch to communicating with
+  // the DOM message queue.
+  void AssertNoAsynchronousErrors(content::WebContents* tab_contents) {
+    EXPECT_EQ("ok-no-errors",
+              ExecuteJavascript("getAnyTestFailures()", tab_contents));
+  }
+
+  // The peer connection server lets our two tabs find each other and talk to
+  // each other (e.g. it is the application-specific "signaling solution").
+  void ConnectToPeerConnectionServer(const std::string peer_name,
+                                     content::WebContents* tab_contents) {
+    std::string javascript = base::StringPrintf(
+        "connect('http://localhost:8888', '%s');", peer_name.c_str());
+    EXPECT_EQ("ok-connected", ExecuteJavascript(javascript, tab_contents));
+  }
+
+  void EstablishCall(content::WebContents* from_tab,
+                     content::WebContents* to_tab) {
+    EXPECT_EQ("ok-peerconnection-created",
+              ExecuteJavascript("preparePeerConnection()", from_tab));
+    EXPECT_EQ("ok-added", ExecuteJavascript("addLocalStream()", from_tab));
+    EXPECT_EQ("ok-negotiating", ExecuteJavascript("negotiateCall()", from_tab));
+
+    // Ensure the call gets up on both sides.
+    EXPECT_TRUE(UglyPollingWaitUntil(
+        "getPeerConnectionReadyState()", "active", from_tab));
+    EXPECT_TRUE(UglyPollingWaitUntil(
+        "getPeerConnectionReadyState()", "active", to_tab));
+  }
+
+  void HangUp(content::WebContents* from_tab) {
+    EXPECT_EQ("ok-call-hung-up", ExecuteJavascript("hangUp()", from_tab));
+  }
+
+  void WaitUntilHangupVerified(content::WebContents* tab_contents) {
+    EXPECT_TRUE(UglyPollingWaitUntil(
+        "getPeerConnectionReadyState()", "no-peer-connection", tab_contents));
+  }
+
+  // Runs the RGBA to I420 converter on the video in |capture_video_filename|,
+  // which should contain frames of size |width| x |height|.
+  //
+  // The rgba_to_i420_converter is part of the webrtc_test_tools target which
+  // should be build prior to running this test. The resulting binary should
+  // live next to Chrome.
+  void RunARGBtoI420Converter(int width,
+                              int height,
+                              const base::FilePath& captured_video_filename) {
+    base::FilePath path_to_converter = base::MakeAbsoluteFilePath(
+        GetBrowserDir().Append(kArgbToI420ConverterExecutable));
+    EXPECT_TRUE(file_util::PathExists(path_to_converter))
+        << "Missing ARGB->I420 converter: should be in "
+        << path_to_converter.value();
+
+    CommandLine converter_command(path_to_converter);
+    converter_command.AppendSwitchPath("--frames_dir", GetWorkingDir());
+    converter_command.AppendSwitchPath("--output_file",
+                                       captured_video_filename);
+    converter_command.AppendSwitchASCII("--width",
+                                        base::StringPrintf("%d", width));
+    converter_command.AppendSwitchASCII("--height",
+                                        base::StringPrintf("%d", height));
+
+    // We produce an output file that will later be used as an input to the
+    // barcode decoder and frame analyzer tools.
+    LOG(INFO) << "Running " << converter_command.GetCommandLineString();
+    std::string result;
+    EXPECT_TRUE(base::GetAppOutput(converter_command, &result));
+    LOG(INFO) << "Output was:\n\n" << result;
+  }
+
+  // Compares the |captured_video_filename| with the |reference_video_filename|.
+  //
+  // The barcode decoder decodes the captured video containing barcodes overlaid
+  // into every frame of the video (produced by rgba_to_i420_converter). It
+  // produces a set of PNG images and a |stats_file| that maps each captured
+  // frame to a frame in the reference video. The frames should be of size
+  // |width| x |height|. The output of compare_videos.py is returned.
+  std::string CompareVideos(int width,
+                            int height,
+                            const base::FilePath& captured_video_filename,
+                            const base::FilePath& reference_video_filename,
+                            const base::FilePath& stats_file) {
+    base::FilePath path_to_analyzer = base::MakeAbsoluteFilePath(
+        GetBrowserDir().Append(kFrameAnalyzerExecutable));
+    base::FilePath path_to_compare_script = GetSourceDir().Append(
+        FILE_PATH_LITERAL("third_party/webrtc/tools/compare_videos.py"));
+
+    EXPECT_TRUE(file_util::PathExists(path_to_analyzer))
+        << "Missing frame analyzer: should be in " << path_to_analyzer.value();
+    EXPECT_TRUE(file_util::PathExists(path_to_compare_script))
+        << "Missing video compare script: should be in "
+        << path_to_compare_script.value();
+
+    CommandLine compare_command = MakePythonCommand(path_to_compare_script);
+    compare_command.AppendSwitchPath("--ref_video", reference_video_filename);
+    compare_command.AppendSwitchPath("--test_video", captured_video_filename);
+    compare_command.AppendSwitchPath("--frame_analyzer", path_to_analyzer);
+    compare_command.AppendSwitchASCII("--yuv_frame_width",
+                                      base::StringPrintf("%d", width));
+    compare_command.AppendSwitchASCII("--yuv_frame_height",
+                                      base::StringPrintf("%d", height));
+    compare_command.AppendSwitchPath("--stats_file", stats_file);
+
+    LOG(INFO) << "Running " << compare_command.GetCommandLineString();
+    std::string result;
+    EXPECT_TRUE(base::GetAppOutput(compare_command, &result));
+    LOG(INFO) << "Output was:\n\n" << result;
+    return result;
+  }
+
+  // Processes the |frame_analyzer_output| for the different frame counts.
+  //
+  // The frame analyzer outputs additional information about the number of
+  // unique frames captured, The max number of repeated frames in a sequence and
+  // the max number of skipped frames. These values are then written to the Perf
+  // Graph. (Note: Some of the repeated or skipped frames will probably be due
+  // to the imperfection of JavaScript timers).
+  void PrintFramesCountPerfResults(std::string frame_analyzer_output) {
+    size_t unique_frames_pos =
+        frame_analyzer_output.rfind("Unique_frames_count");
+    EXPECT_NE(unique_frames_pos, std::string::npos)
+        << "Missing Unique_frames_count in frame analyzer output:\n"
+        << frame_analyzer_output;
+
+    std::string unique_frame_counts =
+        frame_analyzer_output.substr(unique_frames_pos);
+    // TODO(phoglund): Fix ESTATS result to not have this silly newline.
+    std::replace(
+        unique_frame_counts.begin(), unique_frame_counts.end(), '\n', ' ');
+
+    std::vector<std::pair<std::string, std::string> > key_values;
+    base::SplitStringIntoKeyValuePairs(
+        unique_frame_counts, ':', ' ', &key_values);
+    std::vector<std::pair<std::string, std::string> >::const_iterator iter;
+    for (iter = key_values.begin(); iter != key_values.end(); ++iter) {
+      const std::pair<std::string, std::string>& key_value = *iter;
+      perf_test::PrintResult(
+          key_value.first, "", "VGA", key_value.second, "", false);
+    }
+  }
+
+  // Processes the |frame_analyzer_output| to extract the PSNR and SSIM values.
+  //
+  // The frame analyzer produces PSNR and SSIM results for every unique frame
+  // that has been captured. This method forms a list of all the psnr and ssim
+  // values and passes it to PrintResultList() for printing on the Perf Graph.
+  void PrintPsnrAndSsimPerfResults(std::string frame_analyzer_output) {
+    size_t stats_start = frame_analyzer_output.find("BSTATS");
+    EXPECT_NE(stats_start, std::string::npos)
+        << "Missing BSTATS in frame analyzer output:\n"
+        << frame_analyzer_output;
+    size_t stats_end = frame_analyzer_output.find("ESTATS");
+    EXPECT_NE(stats_end, std::string::npos)
+        << "Missing ESTATS in frame analyzer output:\n"
+        << frame_analyzer_output;
+
+    stats_start += std::string("BSTATS").size();
+    std::string psnr_ssim_stats =
+        frame_analyzer_output.substr(stats_start, stats_end - stats_start);
+
+    // PSNR and SSIM values aren't really key-value pairs but it is convenient
+    // to parse them as such.
+    // TODO(phoglund): make the format more convenient so we need less
+    // processing here.
+    std::vector<std::pair<std::string, std::string> > psnr_ssim_entries;
+    base::SplitStringIntoKeyValuePairs(
+        psnr_ssim_stats, ' ', ';', &psnr_ssim_entries);
+
+    std::string psnr_value_list;
+    std::string ssim_value_list;
+    std::vector<std::pair<std::string, std::string> >::const_iterator iter;
+    for (iter = psnr_ssim_entries.begin(); iter != psnr_ssim_entries.end();
+         ++iter) {
+      const std::pair<std::string, std::string>& psnr_and_ssim = *iter;
+      psnr_value_list.append(psnr_and_ssim.first).append(",");
+      ssim_value_list.append(psnr_and_ssim.second).append(",");
+    }
+    // Nuke last comma.
+    psnr_value_list.erase(psnr_value_list.size() - 1);
+    ssim_value_list.erase(ssim_value_list.size() - 1);
+
+    perf_test::PrintResultList("PSNR", "", "VGA", psnr_value_list, "dB", false);
+    perf_test::PrintResultList("SSIM", "", "VGA", ssim_value_list, "", false);
+  }
+
+  base::FilePath GetWorkingDir() {
+    std::string home_dir;
+    environment_->GetVar(kHomeEnvName, &home_dir);
+    base::FilePath::StringType native_home_dir(home_dir.begin(),
+                                               home_dir.end());
+    return base::FilePath(native_home_dir).Append(kWorkingDirName);
+  }
+
+ private:
+  void RunPeerConnectionServer() {
+    // TODO(phoglund): de-dupe later: next line differs from original.
+    base::FilePath peerconnection_server =
+        GetBrowserDir().Append(kPeerConnectionServer);
+
+    EXPECT_TRUE(file_util::PathExists(peerconnection_server))
+        << "Missing peerconnection_server. You must build "
+           "it so it ends up next to the browser test binary.";
+    EXPECT_TRUE(base::LaunchProcess(CommandLine(peerconnection_server),
+                                    base::LaunchOptions(),
+                                    &peerconnection_server_))
+        << "Failed to launch peerconnection_server.";
+  }
+
+  void ShutdownPeerConnectionServer() {
+    EXPECT_TRUE(base::KillProcess(peerconnection_server_, 0, false))
+        << "Failed to shut down peerconnection_server!";
+  }
+
+  base::FilePath GetSourceDir() {
+    base::FilePath source_dir;
+    PathService::Get(base::DIR_SOURCE_ROOT, &source_dir);
+    return source_dir;
+  }
+
+  base::FilePath GetBrowserDir() {
+    base::FilePath browser_dir;
+    EXPECT_TRUE(PathService::Get(base::DIR_MODULE, &browser_dir));
+    return browser_dir;
+  }
+
+  CommandLine MakePythonCommand(base::FilePath python_script) {
+    CommandLine python_command(CommandLine::NO_PROGRAM);
+    EXPECT_TRUE(GetPythonCommand(&python_command));
+    CommandLine complete_command(python_script);
+    complete_command.PrependWrapper(python_command.GetCommandLineString());
+    return complete_command;
+  }
+
+  base::ProcessHandle peerconnection_server_;
+  base::ProcessHandle pywebsocket_server_;
+  scoped_ptr<base::Environment> environment_;
+};
+
+#if defined(OS_WIN)
+// Broken on Win: failing to start pywebsocket_server. http://crbug.com/255499.
+#define MAYBE_MANUAL_TestVGAVideoQuality DISABLED_MANUAL_TestVGAVideoQuality
+#else
+#define MAYBE_MANUAL_TestVGAVideoQuality MANUAL_TestVGAVideoQuality
+#endif
+
+IN_PROC_BROWSER_TEST_F(WebrtcVideoQualityBrowserTest,
+                       MAYBE_MANUAL_TestVGAVideoQuality) {
+  // TODO(phoglund): de-dupe from chrome_webrtc_browsertest.cc.
+  StartPyWebSocketServer();
+
+  EXPECT_TRUE(test_server()->Start());
+
+  ui_test_utils::NavigateToURL(browser(),
+                               test_server()->GetURL(kMainWebrtcTestHtmlPage));
+  content::WebContents* left_tab =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  GetUserMedia(left_tab);
+
+  chrome::AddBlankTabAt(browser(), -1, true);
+  content::WebContents* right_tab =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  // TODO(phoglund): (de-dupe later) different from original flow.
+  ui_test_utils::NavigateToURL(browser(),
+                               test_server()->GetURL(kCapturingWebrtcHtmlPage));
+  GetUserMedia(right_tab);
+
+  ConnectToPeerConnectionServer("peer 1", left_tab);
+  ConnectToPeerConnectionServer("peer 2", right_tab);
+
+  EstablishCall(left_tab, right_tab);
+
+  AssertNoAsynchronousErrors(left_tab);
+  AssertNoAsynchronousErrors(right_tab);
+
+  // TODO(phoglund): (de-dupe later) different from original flow.
+  EXPECT_TRUE(UglyPollingWaitUntil(
+      "doneFrameCapturing()", "done-capturing", right_tab));
+
+  HangUp(left_tab);
+  WaitUntilHangupVerified(left_tab);
+  WaitUntilHangupVerified(right_tab);
+
+  AssertNoAsynchronousErrors(left_tab);
+  AssertNoAsynchronousErrors(right_tab);
+
+  // TODO(phoglund): (de-dupe later) different from original flow.
+  EXPECT_TRUE(UglyPollingWaitUntil(
+      "haveMoreFramesToSend()", "no-more-frames", right_tab));
+
+  RunARGBtoI420Converter(
+      kVgaWidth, kVgaHeight, GetWorkingDir().Append(kCapturedYuvFileName));
+  std::string output =
+      CompareVideos(kVgaWidth,
+                    kVgaHeight,
+                    GetWorkingDir().Append(kCapturedYuvFileName),
+                    GetWorkingDir().Append(kReferenceYuvFileName),
+                    GetWorkingDir().Append(kStatsFileName));
+
+  PrintFramesCountPerfResults(output);
+  PrintPsnrAndSsimPerfResults(output);
+}
diff --git a/chrome/browser/media/media_capture_devices_dispatcher.cc b/chrome/browser/media/media_capture_devices_dispatcher.cc
index 56a7096..788d79d 100644
--- a/chrome/browser/media/media_capture_devices_dispatcher.cc
+++ b/chrome/browser/media/media_capture_devices_dispatcher.cc
@@ -137,9 +137,7 @@
 MediaCaptureDevicesDispatcher::GetAudioCaptureDevices() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   if (!is_device_enumeration_disabled_ && !devices_enumerated_) {
-    BrowserThread::PostTask(
-        BrowserThread::IO, FROM_HERE,
-        base::Bind(&content::EnsureMonitorCaptureDevices));
+    content::EnsureMonitorCaptureDevices();
     devices_enumerated_ = true;
   }
   return audio_devices_;
@@ -149,9 +147,7 @@
 MediaCaptureDevicesDispatcher::GetVideoCaptureDevices() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   if (!is_device_enumeration_disabled_ && !devices_enumerated_) {
-    BrowserThread::PostTask(
-        BrowserThread::IO, FROM_HERE,
-        base::Bind(&content::EnsureMonitorCaptureDevices));
+    content::EnsureMonitorCaptureDevices();
     devices_enumerated_ = true;
   }
   return video_devices_;
diff --git a/chrome/browser/media/media_stream_infobar_delegate.cc b/chrome/browser/media/media_stream_infobar_delegate.cc
index 403ca77..36bfa97 100644
--- a/chrome/browser/media/media_stream_infobar_delegate.cc
+++ b/chrome/browser/media/media_stream_infobar_delegate.cc
@@ -11,10 +11,10 @@
 #include "chrome/browser/infobars/infobar_service.h"
 #include "chrome/common/url_constants.h"
 #include "content/public/browser/web_contents.h"
-#include "googleurl/src/gurl.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "url/gurl.h"
 
 namespace {
 
diff --git a/chrome/browser/media/media_stream_infobar_delegate.h b/chrome/browser/media/media_stream_infobar_delegate.h
index 2950300..146c7536 100644
--- a/chrome/browser/media/media_stream_infobar_delegate.h
+++ b/chrome/browser/media/media_stream_infobar_delegate.h
@@ -31,7 +31,9 @@
                      const content::MediaResponseCallback& callback);
 
  private:
+  friend class MediaStreamInfobarTest;
   friend class WebrtcBrowserTest;
+  friend class WebrtcVideoQualityBrowserTest;
 
   // MediaStreamInfoBarDelegate takes the ownership of the |controller|.
   MediaStreamInfoBarDelegate(
diff --git a/chrome/browser/media/webrtc_log_upload_list.cc b/chrome/browser/media/webrtc_log_upload_list.cc
new file mode 100644
index 0000000..fdaaad0
--- /dev/null
+++ b/chrome/browser/media/webrtc_log_upload_list.cc
@@ -0,0 +1,28 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/media/webrtc_log_upload_list.h"
+
+#include "base/files/file_path.h"
+#include "base/path_service.h"
+#include "chrome/common/chrome_paths.h"
+
+// static
+const char* WebRtcLogUploadList::kWebRtcLogListFilename =
+    "webrtc_log_uploads.log";
+
+// static
+WebRtcLogUploadList* WebRtcLogUploadList::Create(Delegate* delegate) {
+  base::FilePath log_dir_path;
+  PathService::Get(chrome::DIR_USER_DATA, &log_dir_path);
+  base::FilePath upload_log_path =
+      log_dir_path.AppendASCII(kWebRtcLogListFilename);
+  return new WebRtcLogUploadList(delegate, upload_log_path);
+}
+
+WebRtcLogUploadList::WebRtcLogUploadList(Delegate* delegate,
+                                         const base::FilePath& upload_log_path)
+    : UploadList(delegate, upload_log_path) {}
+
+WebRtcLogUploadList::~WebRtcLogUploadList() {}
diff --git a/chrome/browser/media/webrtc_log_upload_list.h b/chrome/browser/media/webrtc_log_upload_list.h
new file mode 100644
index 0000000..b829d8e
--- /dev/null
+++ b/chrome/browser/media/webrtc_log_upload_list.h
@@ -0,0 +1,32 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_MEDIA_WEBRTC_LOG_UPLOAD_LIST_H_
+#define CHROME_BROWSER_MEDIA_WEBRTC_LOG_UPLOAD_LIST_H_
+
+#include "chrome/browser/upload_list.h"
+
+// Loads and parses a text file list of uploaded WebRTC logs.
+class WebRtcLogUploadList : public UploadList {
+ public:
+  // Creates the WebRTC log upload list with the given callback delegate.
+  static WebRtcLogUploadList* Create(Delegate* delegate);
+
+  // Used in this class when reading the list file and in WebRtcLogUploader when
+  // writing to the list file.
+  static const char* kWebRtcLogListFilename;
+
+  // Creates a new WebRTC log upload list with the given callback delegate.
+  // |upload_log_path| is the full path to the file to read the list from.
+  explicit WebRtcLogUploadList(Delegate* delegate,
+                               const base::FilePath& upload_log_path);
+
+ protected:
+  virtual ~WebRtcLogUploadList();
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(WebRtcLogUploadList);
+};
+
+#endif  // CHROME_BROWSER_MEDIA_WEBRTC_LOG_UPLOAD_LIST_H_
diff --git a/chrome/browser/media/webrtc_logging_handler_host.cc b/chrome/browser/media/webrtc_logging_handler_host.cc
index a318981..c46ae32 100644
--- a/chrome/browser/media/webrtc_logging_handler_host.cc
+++ b/chrome/browser/media/webrtc_logging_handler_host.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/media/webrtc_logging_handler_host.h"
 
+#include <string>
+
 #include "base/bind.h"
 #include "base/cpu.h"
 #include "base/logging.h"
@@ -22,6 +24,8 @@
 #include "content/public/browser/render_process_host.h"
 #include "gpu/config/gpu_info.h"
 #include "gpu/config/gpu_info_collector.h"
+#include "net/base/address_family.h"
+#include "net/base/net_util.h"
 #include "net/url_request/url_request_context_getter.h"
 
 #if defined(OS_LINUX)
@@ -42,6 +46,47 @@
 const size_t kWebRtcLogSize = 6 * 1024 * 1024;  // 6 MB
 #endif
 
+namespace {
+
+// For privacy reasons when logging IP addresses. The returned "sensitive
+// string" is for release builds a string with the end stripped away. Last
+// octet for IPv4 and last 80 bits (5 groups) for IPv6. String will be
+// "1.2.3.x" and "1.2.3::" respectively. For debug builds, the string is
+// not stripped.
+std::string IPAddressToSensitiveString(const net::IPAddressNumber& address) {
+#if defined(NDEBUG)
+  std::string sensitive_address;
+  switch (net::GetAddressFamily(address)) {
+    case net::ADDRESS_FAMILY_IPV4: {
+      sensitive_address = net::IPAddressToString(address);
+      size_t find_pos = sensitive_address.rfind('.');
+      if (find_pos == std::string::npos)
+        return std::string();
+      sensitive_address.resize(find_pos);
+      sensitive_address += ".x";
+      break;
+    }
+    case net::ADDRESS_FAMILY_IPV6: {
+      // TODO(grunell): Create a string of format "1:2:3:x:x:x:x:x" to clarify
+      // that the end has been stripped out.
+      net::IPAddressNumber sensitive_address_number = address;
+      sensitive_address_number.resize(net::kIPv6AddressSize - 10);
+      sensitive_address_number.resize(net::kIPv6AddressSize, 0);
+      sensitive_address = net::IPAddressToString(sensitive_address_number);
+      break;
+    }
+    case net::ADDRESS_FAMILY_UNSPECIFIED: {
+      break;
+    }
+  }
+  return sensitive_address;
+#else
+  return net::IPAddressToString(address);
+#endif
+}
+
+}  // namespace
+
 WebRtcLoggingHandlerHost::WebRtcLoggingHandlerHost() {}
 
 WebRtcLoggingHandlerHost::~WebRtcLoggingHandlerHost() {}
@@ -88,6 +133,10 @@
 #if defined(OS_CHROMEOS)
   chromeos::CrosSettings::Get()->GetBoolean(chromeos::kStatsReportingPref,
                                             &enabled);
+#elif defined(OS_ANDROID)
+  // Android has its own settings for metrics / crash uploading.
+  enabled = g_browser_process->local_state()->GetBoolean(
+      prefs::kCrashReportingEnabled);
 #else
   enabled = g_browser_process->local_state()->GetBoolean(
       prefs::kMetricsReportingEnabled);
@@ -156,6 +205,7 @@
   pcb.Write(info.c_str(), info.length());
   std::string cpu_brand = cpu.cpu_brand();
   // Workaround for crbug.com/249713.
+  // TODO(grunell): Remove workaround when bug is fixed.
   size_t null_pos = cpu_brand.find('\0');
   if (null_pos != std::string::npos)
     cpu_brand.erase(null_pos);
@@ -180,6 +230,19 @@
          "', driver-version=" + gpu_info.driver_version + '\n';
   pcb.Write(info.c_str(), info.length());
 
+  // Network interfaces
+  net::NetworkInterfaceList network_list;
+  net::GetNetworkList(&network_list);
+  info  = "Discovered " + IntToString(network_list.size()) +
+          " network interfaces:" + '\n';
+  pcb.Write(info.c_str(), info.length());
+  for (net::NetworkInterfaceList::iterator it = network_list.begin();
+       it != network_list.end(); ++it) {
+    info = "Name: " + it->name +
+           ", Address: " + IPAddressToSensitiveString(it->address) + '\n';
+    pcb.Write(info.c_str(), info.length());
+  }
+
   BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
       &WebRtcLoggingHandlerHost::NotifyLogOpened, this));
 }
diff --git a/chrome/browser/media_galleries/fileapi/device_media_async_file_util.cc b/chrome/browser/media_galleries/fileapi/device_media_async_file_util.cc
index b1cba04..29a7f11 100644
--- a/chrome/browser/media_galleries/fileapi/device_media_async_file_util.cc
+++ b/chrome/browser/media_galleries/fileapi/device_media_async_file_util.cc
@@ -91,8 +91,7 @@
   if (!callback.is_null()) {
     base::PlatformFile invalid_file = base::kInvalidPlatformFileValue;
     callback.Run(base::PLATFORM_FILE_ERROR_SECURITY,
-                 base::PassPlatformFile(&invalid_file),
-                 false);
+                 base::PassPlatformFile(&invalid_file));
   }
   return true;
 }
@@ -249,6 +248,16 @@
   return true;
 }
 
+bool DeviceMediaAsyncFileUtil::DeleteRecursively(
+    scoped_ptr<FileSystemOperationContext> context,
+    const FileSystemURL& url,
+    const StatusCallback& callback) {
+  DCHECK(IsOnIOThread(context.get()));
+  if (!callback.is_null())
+    callback.Run(base::PLATFORM_FILE_ERROR_INVALID_OPERATION);
+  return true;
+}
+
 bool DeviceMediaAsyncFileUtil::CreateSnapshotFile(
     scoped_ptr<FileSystemOperationContext> context,
     const FileSystemURL& url,
diff --git a/chrome/browser/media_galleries/fileapi/device_media_async_file_util.h b/chrome/browser/media_galleries/fileapi/device_media_async_file_util.h
index d965c50..e109c64 100644
--- a/chrome/browser/media_galleries/fileapi/device_media_async_file_util.h
+++ b/chrome/browser/media_galleries/fileapi/device_media_async_file_util.h
@@ -91,6 +91,10 @@
       scoped_ptr<fileapi::FileSystemOperationContext> context,
       const fileapi::FileSystemURL& url,
       const StatusCallback& callback) OVERRIDE;
+  virtual bool DeleteRecursively(
+      scoped_ptr<fileapi::FileSystemOperationContext> context,
+      const fileapi::FileSystemURL& url,
+      const StatusCallback& callback) OVERRIDE;
   virtual bool CreateSnapshotFile(
       scoped_ptr<fileapi::FileSystemOperationContext> context,
       const fileapi::FileSystemURL& url,
diff --git a/chrome/browser/media_galleries/fileapi/itunes_data_provider.cc b/chrome/browser/media_galleries/fileapi/itunes_data_provider.cc
index 9709b66..951e91b 100644
--- a/chrome/browser/media_galleries/fileapi/itunes_data_provider.cc
+++ b/chrome/browser/media_galleries/fileapi/itunes_data_provider.cc
@@ -7,13 +7,16 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/format_macros.h"
+#include "base/location.h"
 #include "base/logging.h"
 #include "base/platform_file.h"
 #include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/thread_restrictions.h"
-#include "chrome/browser/media_galleries/fileapi/itunes_library_parser.h"
 #include "chrome/browser/media_galleries/fileapi/media_file_system_mount_point_provider.h"
+#include "chrome/browser/media_galleries/imported_media_gallery_registry.h"
+#include "chrome/common/itunes_library.h"
+#include "content/public/browser/browser_thread.h"
 
 using chrome::MediaFileSystemMountPointProvider;
 
@@ -21,49 +24,22 @@
 
 namespace {
 
-// A "reasonable" artificial limit.
-// TODO(vandebo): Add a UMA to figure out what common values are.
-const int64 kMaxLibraryFileSize = 150 * 1024 * 1024;
+typedef base::Callback<void(scoped_ptr<base::FilePathWatcher> watcher)>
+    FileWatchStartedCallback;
 
-std::string ReadFile(const base::FilePath& path) {
-  base::ThreadRestrictions::AssertIOAllowed();
-
-  base::PlatformFile file = base::CreatePlatformFile(
-      path, base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ, NULL, NULL);
-  if (file == base::kInvalidPlatformFileValue)
-    return std::string();
-
-  base::PlatformFileInfo file_info;
-  if (!base::GetPlatformFileInfo(file, &file_info) ||
-      file_info.size > kMaxLibraryFileSize) {
-    base::ClosePlatformFile(file);
-    return std::string();
-  }
-
-  std::string result(file_info.size, 0);
-  if (base::ReadPlatformFile(file, 0, string_as_array(&result),
-        file_info.size) != file_info.size) {
-    result.clear();
-  }
-
-  base::ClosePlatformFile(file);
-  return result;
-}
-
-ITunesDataProvider::Album MakeUniqueTrackNames(
-    const ITunesLibraryParser::Album& album) {
+ITunesDataProvider::Album MakeUniqueTrackNames(const parser::Album& album) {
   // TODO(vandebo): It would be nice to ensure that names returned from here
   // are stable, but aside from persisting every name returned, it's not
   // obvious how to do that (without including the track id in every name).
-  typedef std::set<const ITunesLibraryParser::Track*> TrackRefs;
+  typedef std::set<const parser::Track*> TrackRefs;
   typedef std::map<ITunesDataProvider::TrackName, TrackRefs> AlbumInfo;
 
   ITunesDataProvider::Album result;
   AlbumInfo duped_tracks;
 
-  ITunesLibraryParser::Album::const_iterator album_it;
+  parser::Album::const_iterator album_it;
   for (album_it = album.begin(); album_it != album.end(); ++album_it) {
-    const ITunesLibraryParser::Track& track = *album_it;
+    const parser::Track& track = *album_it;
     std::string name = track.location.BaseName().AsUTF8Unsafe();
     duped_tracks[name].insert(&track);
   }
@@ -90,33 +66,68 @@
   return result;
 }
 
+// Bounces |path| and |error| to |callback| from the FILE thread to the media
+// task runner.
+void OnLibraryChanged(const base::FilePathWatcher::Callback& callback,
+                      const base::FilePath& path,
+                      bool error) {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
+  MediaFileSystemMountPointProvider::MediaTaskRunner()->PostTask(
+      FROM_HERE, base::Bind(callback, path, error));
+}
+
+// The watch has to be started on the FILE thread, and the callback called by
+// the FilePathWatcher also needs to run on the FILE thread.
+void StartLibraryWatchOnFileThread(
+    const base::FilePath& library_path,
+    const FileWatchStartedCallback& watch_started_callback,
+    const base::FilePathWatcher::Callback& library_changed_callback) {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
+  scoped_ptr<base::FilePathWatcher> watcher(new base::FilePathWatcher);
+  bool success = watcher->Watch(
+      library_path, false /*recursive*/,
+      base::Bind(&OnLibraryChanged, library_changed_callback));
+  if (!success)
+    LOG(ERROR) << "Adding watch for " << library_path.value() << " failed";
+  MediaFileSystemMountPointProvider::MediaTaskRunner()->PostTask(
+      FROM_HERE,
+      base::Bind(watch_started_callback, base::Passed(&watcher)));
+}
+
 }  // namespace
 
 ITunesDataProvider::ITunesDataProvider(const base::FilePath& library_path)
     : library_path_(library_path),
       needs_refresh_(true),
-      is_valid_(false),
-      weak_factory_(this) {
+      is_valid_(false) {
   DCHECK(MediaFileSystemMountPointProvider::CurrentlyOnMediaTaskRunnerThread());
   DCHECK(!library_path_.empty());
-  bool ret = library_watcher_.Watch(
-      library_path_, false /*recursive*/,
-      base::Bind(&ITunesDataProvider::OnLibraryChanged,
-                 weak_factory_.GetWeakPtr()));
-  if (!ret)
-    LOG(ERROR) << "Adding watch for " << library_path_.value() << " failed";
+
+  content::BrowserThread::PostTask(
+      content::BrowserThread::FILE,
+      FROM_HERE,
+      base::Bind(StartLibraryWatchOnFileThread,
+                 library_path_,
+                 base::Bind(&ITunesDataProvider::OnLibraryWatchStartedCallback),
+                 base::Bind(&ITunesDataProvider::OnLibraryChangedCallback)));
 }
 
 ITunesDataProvider::~ITunesDataProvider() {}
 
-void ITunesDataProvider::RefreshData(
-    const base::Callback<void(bool)>& ready_callback) {
+// TODO(vandebo): add a file watch that resets |needs_refresh_| when the
+// file changes.
+void ITunesDataProvider::RefreshData(const ReadyCallback& ready_callback) {
   DCHECK(MediaFileSystemMountPointProvider::CurrentlyOnMediaTaskRunnerThread());
-  if (needs_refresh_) {
-    is_valid_ = ParseLibrary();
-    needs_refresh_ = false;
+  if (!needs_refresh_) {
+    ready_callback.Run(is_valid_);
+    return;
   }
-  ready_callback.Run(is_valid_);
+
+  needs_refresh_ = false;
+  xml_parser_ = new SafeITunesLibraryParser(
+      library_path_,
+      base::Bind(&ITunesDataProvider::OnLibraryParsedCallback, ready_callback));
+  xml_parser_->Start();
 }
 
 const base::FilePath& ITunesDataProvider::library_path() const {
@@ -137,7 +148,6 @@
   if (library_it == library_.end())
     return false;
   return ContainsKey(library_it->second, album);
-
 }
 
 base::FilePath ITunesDataProvider::GetTrackLocation(
@@ -192,40 +202,55 @@
     const ArtistName& artist, const AlbumName& album) const {
   DCHECK(MediaFileSystemMountPointProvider::CurrentlyOnMediaTaskRunnerThread());
   DCHECK(is_valid_);
-  Album empty_result;
+  Album result;
   Library::const_iterator artist_lookup = library_.find(artist);
-  if (artist_lookup == library_.end())
-    return empty_result;
-
-  Artist::const_iterator album_lookup = artist_lookup->second.find(album);
-  if (album_lookup == artist_lookup->second.end())
-    return empty_result;
-
-  return album_lookup->second;
+  if (artist_lookup != library_.end()) {
+    Artist::const_iterator album_lookup = artist_lookup->second.find(album);
+    if (album_lookup != artist_lookup->second.end())
+      result = album_lookup->second;
+  }
+  return result;
 }
 
-bool ITunesDataProvider::ParseLibrary() {
+// static
+void ITunesDataProvider::OnLibraryWatchStartedCallback(
+    scoped_ptr<base::FilePathWatcher> library_watcher) {
   DCHECK(MediaFileSystemMountPointProvider::CurrentlyOnMediaTaskRunnerThread());
-  std::string xml = ReadFile(library_path_);
+  ITunesDataProvider* provider =
+      chrome::ImportedMediaGalleryRegistry::ITunesDataProvider();
+  if (provider)
+    provider->OnLibraryWatchStarted(library_watcher.Pass());
+}
 
-  library_.clear();
-  ITunesLibraryParser parser;
-  if (!parser.Parse(xml))
-    return false;
+// static
+void ITunesDataProvider::OnLibraryChangedCallback(const base::FilePath& path,
+                                                  bool error) {
+  DCHECK(MediaFileSystemMountPointProvider::CurrentlyOnMediaTaskRunnerThread());
+  ITunesDataProvider* provider =
+      chrome::ImportedMediaGalleryRegistry::ITunesDataProvider();
+  if (provider)
+    provider->OnLibraryChanged(path, error);
+}
 
-  ITunesLibraryParser::Library::const_iterator artist_it;
-  ITunesLibraryParser::Albums::const_iterator album_it;
-  for (artist_it = parser.library().begin();
-       artist_it != parser.library().end();
-       ++artist_it) {
-    for (album_it = artist_it->second.begin();
-         album_it != artist_it->second.end();
-         ++album_it) {
-      library_[artist_it->first][album_it->first] =
-          MakeUniqueTrackNames(album_it->second);
-    }
+// static
+void ITunesDataProvider::OnLibraryParsedCallback(
+    const ReadyCallback& ready_callback,
+    bool result,
+    const parser::Library& library) {
+  DCHECK(MediaFileSystemMountPointProvider::CurrentlyOnMediaTaskRunnerThread());
+  ITunesDataProvider* provider =
+      chrome::ImportedMediaGalleryRegistry::ITunesDataProvider();
+  if (!provider) {
+    ready_callback.Run(false);
+    return;
   }
-  return true;
+  provider->OnLibraryParsed(ready_callback, result, library);
+}
+
+void ITunesDataProvider::OnLibraryWatchStarted(
+    scoped_ptr<base::FilePathWatcher> library_watcher) {
+  DCHECK(MediaFileSystemMountPointProvider::CurrentlyOnMediaTaskRunnerThread());
+  library_watcher_.reset(library_watcher.release());
 }
 
 void ITunesDataProvider::OnLibraryChanged(const base::FilePath& path,
@@ -237,4 +262,25 @@
   needs_refresh_ = true;
 }
 
+void ITunesDataProvider::OnLibraryParsed(const ReadyCallback& ready_callback,
+                                         bool result,
+                                         const parser::Library& library) {
+  DCHECK(MediaFileSystemMountPointProvider::CurrentlyOnMediaTaskRunnerThread());
+  is_valid_ = result;
+  if (is_valid_) {
+    library_.clear();
+    for (parser::Library::const_iterator artist_it = library.begin();
+         artist_it != library.end();
+         ++artist_it) {
+      for (parser::Albums::const_iterator album_it = artist_it->second.begin();
+           album_it != artist_it->second.end();
+           ++album_it) {
+        library_[artist_it->first][album_it->first] =
+            MakeUniqueTrackNames(album_it->second);
+      }
+    }
+  }
+  ready_callback.Run(is_valid_);
+}
+
 }  // namespace itunes
diff --git a/chrome/browser/media_galleries/fileapi/itunes_data_provider.h b/chrome/browser/media_galleries/fileapi/itunes_data_provider.h
index 26d7e14..5d8cb4f 100644
--- a/chrome/browser/media_galleries/fileapi/itunes_data_provider.h
+++ b/chrome/browser/media_galleries/fileapi/itunes_data_provider.h
@@ -13,8 +13,7 @@
 #include "base/callback_forward.h"
 #include "base/files/file_path.h"
 #include "base/files/file_path_watcher.h"
-#include "base/memory/weak_ptr.h"
-#include "chrome/browser/media_galleries/fileapi/itunes_library_parser.h"
+#include "chrome/browser/media_galleries/fileapi/safe_itunes_library_parser.h"
 
 namespace itunes {
 
@@ -28,13 +27,14 @@
   typedef std::string AlbumName;
   typedef std::string TrackName;
   typedef std::map<TrackName, base::FilePath> Album;
+  typedef base::Callback<void(bool)> ReadyCallback;
 
   explicit ITunesDataProvider(const base::FilePath& library_path);
   ~ITunesDataProvider();
 
   // Ask the data provider to refresh the data if necessary. |ready_callback|
   // will be called with the result; false if unable to parse the XML file.
-  void RefreshData(const base::Callback<void(bool)>& ready_callback);
+  void RefreshData(const ReadyCallback& ready_callback);
 
   // Get the platform path for the library XML file.
   const base::FilePath& library_path() const;
@@ -64,10 +64,29 @@
   typedef std::map<AlbumName, Album> Artist;
   typedef std::map<ArtistName, Artist> Library;
 
-  bool ParseLibrary();
+  // These are hacks to work around http://crbug.com/165590. Otherwise a
+  // WeakPtrFactory would be the obvious answer here.
+  // static so they can call their real counterparts.
+  // TODO(vandebo) Remove these when the bug is fixed.
+  static void OnLibraryWatchStartedCallback(
+      scoped_ptr<base::FilePathWatcher> library_watcher);
+  static void OnLibraryChangedCallback(const base::FilePath& path, bool error);
+  static void OnLibraryParsedCallback(const ReadyCallback& ready_callback,
+                                      bool result,
+                                      const parser::Library& library);
 
+  // Called when the FilePathWatcher for |library_path_| has tried to add an
+  // watch.
+  void OnLibraryWatchStarted(scoped_ptr<base::FilePathWatcher> library_watcher);
+
+  // Called when |library_path_| has changed.
   void OnLibraryChanged(const base::FilePath& path, bool error);
 
+  // Called when the utility process finishes parsing the library XML file.
+  void OnLibraryParsed(const ReadyCallback& ready_callback,
+                       bool result,
+                       const parser::Library& library);
+
   // Path to the library XML file.
   const base::FilePath library_path_;
 
@@ -82,9 +101,9 @@
   bool is_valid_;
 
   // A watcher on the library xml file.
-  base::FilePathWatcher library_watcher_;
+  scoped_ptr<base::FilePathWatcher> library_watcher_;
 
-  base::WeakPtrFactory<ITunesDataProvider> weak_factory_;
+  scoped_refptr<SafeITunesLibraryParser> xml_parser_;
 
   DISALLOW_COPY_AND_ASSIGN(ITunesDataProvider);
 };
diff --git a/chrome/browser/media_galleries/fileapi/itunes_file_util.cc b/chrome/browser/media_galleries/fileapi/itunes_file_util.cc
index 12c0e70..d5e247d 100644
--- a/chrome/browser/media_galleries/fileapi/itunes_file_util.cc
+++ b/chrome/browser/media_galleries/fileapi/itunes_file_util.cc
@@ -4,6 +4,11 @@
 
 #include "chrome/browser/media_galleries/fileapi/itunes_file_util.h"
 
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/bind_helpers.h"
 #include "base/file_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/media_galleries/fileapi/itunes_data_provider.h"
@@ -46,30 +51,33 @@
 }
 
 void ItunesFileUtil::GetFileInfoOnTaskRunnerThread(
-    fileapi::FileSystemOperationContext* context,
+    scoped_ptr<fileapi::FileSystemOperationContext> context,
     const fileapi::FileSystemURL& url,
     const GetFileInfoCallback& callback) {
   GetDataProvider()->RefreshData(
       base::Bind(&ItunesFileUtil::GetFileInfoWithFreshDataProvider,
-                 weak_factory_.GetWeakPtr(), context, url, callback));
+                 weak_factory_.GetWeakPtr(), base::Passed(&context), url,
+                 callback));
 }
 
 void ItunesFileUtil::ReadDirectoryOnTaskRunnerThread(
-    fileapi::FileSystemOperationContext* context,
+    scoped_ptr<fileapi::FileSystemOperationContext> context,
     const fileapi::FileSystemURL& url,
     const ReadDirectoryCallback& callback) {
   GetDataProvider()->RefreshData(
       base::Bind(&ItunesFileUtil::ReadDirectoryWithFreshDataProvider,
-                 weak_factory_.GetWeakPtr(), context, url, callback));
+                 weak_factory_.GetWeakPtr(), base::Passed(&context), url,
+                 callback));
 }
 
 void ItunesFileUtil::CreateSnapshotFileOnTaskRunnerThread(
-    fileapi::FileSystemOperationContext* context,
+    scoped_ptr<fileapi::FileSystemOperationContext> context,
     const fileapi::FileSystemURL& url,
     const CreateSnapshotFileCallback& callback) {
   GetDataProvider()->RefreshData(
       base::Bind(&ItunesFileUtil::CreateSnapshotFileWithFreshDataProvider,
-                 weak_factory_.GetWeakPtr(), context, url, callback));
+                 weak_factory_.GetWeakPtr(), base::Passed(&context), url,
+                 callback));
 }
 
 // Contents of the iTunes media gallery:
@@ -262,7 +270,7 @@
 }
 
 void ItunesFileUtil::GetFileInfoWithFreshDataProvider(
-    fileapi::FileSystemOperationContext* context,
+    scoped_ptr<fileapi::FileSystemOperationContext> context,
     const fileapi::FileSystemURL& url,
     const GetFileInfoCallback& callback,
     bool valid_parse) {
@@ -276,11 +284,12 @@
     }
     return;
   }
-  NativeMediaFileUtil::GetFileInfoOnTaskRunnerThread(context, url, callback);
+  NativeMediaFileUtil::GetFileInfoOnTaskRunnerThread(context.Pass(), url,
+                                                     callback);
 }
 
 void ItunesFileUtil::ReadDirectoryWithFreshDataProvider(
-    fileapi::FileSystemOperationContext* context,
+    scoped_ptr<fileapi::FileSystemOperationContext> context,
     const fileapi::FileSystemURL& url,
     const ReadDirectoryCallback& callback,
     bool valid_parse) {
@@ -294,11 +303,12 @@
     }
     return;
   }
-  NativeMediaFileUtil::ReadDirectoryOnTaskRunnerThread(context, url, callback);
+  NativeMediaFileUtil::ReadDirectoryOnTaskRunnerThread(context.Pass(), url,
+                                                       callback);
 }
 
 void ItunesFileUtil::CreateSnapshotFileWithFreshDataProvider(
-    fileapi::FileSystemOperationContext* context,
+    scoped_ptr<fileapi::FileSystemOperationContext> context,
     const fileapi::FileSystemURL& url,
     const CreateSnapshotFileCallback& callback,
     bool valid_parse) {
@@ -315,7 +325,7 @@
     }
     return;
   }
-  NativeMediaFileUtil::CreateSnapshotFileOnTaskRunnerThread(context, url,
+  NativeMediaFileUtil::CreateSnapshotFileOnTaskRunnerThread(context.Pass(), url,
                                                             callback);
 }
 
diff --git a/chrome/browser/media_galleries/fileapi/itunes_file_util.h b/chrome/browser/media_galleries/fileapi/itunes_file_util.h
index b1208fa..d87bb51 100644
--- a/chrome/browser/media_galleries/fileapi/itunes_file_util.h
+++ b/chrome/browser/media_galleries/fileapi/itunes_file_util.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_ITUNES_FILE_UTIL_H_
 #define CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_ITUNES_FILE_UTIL_H_
 
+#include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/media_galleries/fileapi/native_media_file_util.h"
 
@@ -24,15 +25,15 @@
  protected:
   // NativeMediaFileUtil overrides.
   virtual void GetFileInfoOnTaskRunnerThread(
-      fileapi::FileSystemOperationContext* context,
+      scoped_ptr<fileapi::FileSystemOperationContext> context,
       const fileapi::FileSystemURL& url,
       const GetFileInfoCallback& callback) OVERRIDE;
   virtual void ReadDirectoryOnTaskRunnerThread(
-      fileapi::FileSystemOperationContext* context,
+      scoped_ptr<fileapi::FileSystemOperationContext> context,
       const fileapi::FileSystemURL& url,
       const ReadDirectoryCallback& callback) OVERRIDE;
   virtual void CreateSnapshotFileOnTaskRunnerThread(
-      fileapi::FileSystemOperationContext* context,
+      scoped_ptr<fileapi::FileSystemOperationContext> context,
       const fileapi::FileSystemURL& url,
       const CreateSnapshotFileCallback& callback) OVERRIDE;
   virtual base::PlatformFileError GetFileInfoSync(
@@ -57,17 +58,17 @@
 
  private:
   void GetFileInfoWithFreshDataProvider(
-      fileapi::FileSystemOperationContext* context,
+      scoped_ptr<fileapi::FileSystemOperationContext> context,
       const fileapi::FileSystemURL& url,
       const GetFileInfoCallback& callback,
       bool valid_parse);
   void ReadDirectoryWithFreshDataProvider(
-      fileapi::FileSystemOperationContext* context,
+      scoped_ptr<fileapi::FileSystemOperationContext> context,
       const fileapi::FileSystemURL& url,
       const ReadDirectoryCallback& callback,
       bool valid_parse);
   virtual void CreateSnapshotFileWithFreshDataProvider(
-      fileapi::FileSystemOperationContext* context,
+      scoped_ptr<fileapi::FileSystemOperationContext> context,
       const fileapi::FileSystemURL& url,
       const CreateSnapshotFileCallback& callback,
       bool valid_parse);
diff --git a/chrome/browser/media_galleries/fileapi/itunes_finder.cc b/chrome/browser/media_galleries/fileapi/itunes_finder.cc
index 3c4eaf4..1a59629 100644
--- a/chrome/browser/media_galleries/fileapi/itunes_finder.cc
+++ b/chrome/browser/media_galleries/fileapi/itunes_finder.cc
@@ -47,8 +47,8 @@
 
 void ITunesFinder::PostResultToUIThread(const std::string& unique_id) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
-  // The use of base::Owned() below will cause this class to delete as soon as
-  // FinishOnUIThread() finishes.
+  // The use of base::Owned() below will cause this class to get deleted either
+  // when FinishOnUIThread() finishes or if the PostTask() fails.
   content::BrowserThread::PostTask(
       content::BrowserThread::UI,
       FROM_HERE,
diff --git a/chrome/browser/media_galleries/fileapi/itunes_finder_mac.mm b/chrome/browser/media_galleries/fileapi/itunes_finder_mac.mm
index 79846ac..3780160 100644
--- a/chrome/browser/media_galleries/fileapi/itunes_finder_mac.mm
+++ b/chrome/browser/media_galleries/fileapi/itunes_finder_mac.mm
@@ -7,9 +7,9 @@
 #include "base/file_util.h"
 #include "base/logging.h"
 #import "base/mac/foundation_util.h"
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #include "base/strings/sys_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "content/public/browser/browser_thread.h"
 
 using base::mac::CFCast;
@@ -28,8 +28,8 @@
 
   CFStringRef iapp_id = CFSTR("com.apple.iApps");
   CFStringRef itunes_db_key = CFSTR("iTunesRecentDatabasePaths");
-  scoped_nsobject<NSArray> plist(CFToNSCast(CFCast<CFArrayRef>(
-      CFPreferencesCopyAppValue(itunes_db_key, iapp_id))));
+  base::scoped_nsobject<NSArray> plist(CFToNSCast(
+      CFCast<CFArrayRef>(CFPreferencesCopyAppValue(itunes_db_key, iapp_id))));
   if (!plist) {
     PostResultToUIThread(std::string());
     return;
diff --git a/chrome/browser/media_galleries/fileapi/itunes_finder_win.cc b/chrome/browser/media_galleries/fileapi/itunes_finder_win.cc
index 5626c30..40016a5 100644
--- a/chrome/browser/media_galleries/fileapi/itunes_finder_win.cc
+++ b/chrome/browser/media_galleries/fileapi/itunes_finder_win.cc
@@ -6,109 +6,32 @@
 
 #include <string>
 
-#include "base/base64.h"
 #include "base/base_paths_win.h"
 #include "base/file_util.h"
 #include "base/files/file_path.h"
 #include "base/logging.h"
 #include "base/path_service.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/media_galleries/fileapi/itunes_xml_utils.h"
+#include "chrome/browser/media_galleries/fileapi/safe_itunes_pref_parser_win.h"
 #include "chrome/common/chrome_paths.h"
-#include "third_party/libxml/chromium/libxml_utils.h"
+#include "content/public/browser/browser_thread.h"
 
 namespace itunes {
 
 namespace {
 
-// Read the iTunes preferences from |pref_file| and then try to extract the
-// library XML location from the XML file. Return it if found. The minimal
-// valid snippet of XML is:
-//
-//   <plist>
-//     <dict>
-//       <key>User Preferences</key>
-//       <dict>
-//         <key>iTunes Library XML Location:1</key>
-//         <data>Base64 encoded w string path</data>
-//       </dict>
-//     </dict>
-//   </plist>
-//
-base::FilePath::StringType FindLibraryLocationInPrefXML(
-    const std::string& pref_file) {
-  XmlReader reader;
-  base::FilePath::StringType result;
+// Try to read the iTunes preferences file from the default location and return
+// its contents if found.
+std::string GetPrefFileData() {
+  std::string xml_pref_data;
 
-  if (!reader.LoadFile(pref_file))
-    return result;
-
-  // Find the plist node and then search within that tag.
-  if (!SeekToNodeAtCurrentDepth(&reader, "plist"))
-    return result;
-  if (!reader.Read())
-    return result;
-
-  if (!SeekToNodeAtCurrentDepth(&reader, "dict"))
-    return result;
-
-  if (!SeekInDict(&reader, "User Preferences"))
-    return result;
-
-  if (!SeekToNodeAtCurrentDepth(&reader, "dict"))
-    return result;
-
-  if (!SeekInDict(&reader, "iTunes Library XML Location:1"))
-    return result;
-
-  if (!SeekToNodeAtCurrentDepth(&reader, "data"))
-    return result;
-
-  std::string pref_value;
-  if (!reader.ReadElementContent(&pref_value))
-    return result;
-  // The data is a base64 encoded wchar_t*. Because Base64Decode uses
-  // std::strings, the result has to be casted to a wchar_t*.
-  std::string data;
-  if (!base::Base64Decode(CollapseWhitespaceASCII(pref_value, true), &data))
-    return result;
-  return base::FilePath::StringType(
-      reinterpret_cast<const wchar_t*>(data.data()), data.size()/2);
-}
-
-// Try to find the iTunes library XML by examining the iTunes preferences
-// file and return it if found.
-base::FilePath TryPreferencesFile() {
   base::FilePath appdata_dir;
-  if (!PathService::Get(base::DIR_APP_DATA, &appdata_dir))
-    return base::FilePath();
-  base::FilePath pref_file = appdata_dir.AppendASCII("Apple Computer")
-                                        .AppendASCII("iTunes")
-                                        .AppendASCII("iTunesPrefs.xml");
-  if (!file_util::PathExists(pref_file))
-    return base::FilePath();
-
-  base::FilePath::StringType library_location =
-      FindLibraryLocationInPrefXML(pref_file.AsUTF8Unsafe());
-  base::FilePath library_file(library_location);
-  if (!file_util::PathExists(library_file))
-    return base::FilePath();
-  return library_file;
-}
-
-// Check the default location for the iTunes library XML file. Return the
-// location if found.
-base::FilePath TryDefaultLocation() {
-  base::FilePath music_dir;
-  if (!PathService::Get(chrome::DIR_USER_MUSIC, &music_dir))
-    return base::FilePath();
-  base::FilePath library_file =
-      music_dir.AppendASCII("iTunes").AppendASCII("iTunes Music Library.xml");
-
-  if (!file_util::PathExists(library_file))
-    return base::FilePath();
-  return library_file;
+  if (PathService::Get(base::DIR_APP_DATA, &appdata_dir)) {
+    base::FilePath pref_file = appdata_dir.AppendASCII("Apple Computer")
+                                          .AppendASCII("iTunes")
+                                          .AppendASCII("iTunesPrefs.xml");
+    file_util::ReadFileToString(pref_file, &xml_pref_data);
+  }
+  return xml_pref_data;
 }
 
 }  // namespace
@@ -120,16 +43,48 @@
 ITunesFinderWin::~ITunesFinderWin() {}
 
 void ITunesFinderWin::FindITunesLibraryOnFileThread() {
-  base::FilePath library_file = TryPreferencesFile();
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
 
-  if (library_file.empty())
-    library_file = TryDefaultLocation();
-
-  if (library_file.empty()) {
-    PostResultToUIThread(std::string());
+  std::string xml_pref_data = GetPrefFileData();
+  if (xml_pref_data.empty()) {
+    TryDefaultLocation();
     return;
   }
 
+  scoped_refptr<SafeITunesPrefParserWin> parser =
+      new SafeITunesPrefParserWin(
+          xml_pref_data,
+          base::Bind(&ITunesFinderWin::FinishedParsingPrefXML,
+                     base::Unretained(this)));
+  parser->Start();
+}
+
+void ITunesFinderWin::TryDefaultLocation() {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
+
+  base::FilePath music_dir;
+  if (!PathService::Get(chrome::DIR_USER_MUSIC, &music_dir)) {
+    PostResultToUIThread(std::string());
+    return;
+  }
+  base::FilePath library_file =
+      music_dir.AppendASCII("iTunes").AppendASCII("iTunes Music Library.xml");
+
+  if (!file_util::PathExists(library_file)) {
+    PostResultToUIThread(std::string());
+    return;
+  }
+  PostResultToUIThread(library_file.AsUTF8Unsafe());
+}
+
+void ITunesFinderWin::FinishedParsingPrefXML(
+    const base::FilePath& library_file) {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
+
+  if (library_file.empty() || !file_util::PathExists(library_file)) {
+    TryDefaultLocation();
+    return;
+  }
   PostResultToUIThread(library_file.AsUTF8Unsafe());
 }
 
diff --git a/chrome/browser/media_galleries/fileapi/itunes_finder_win.h b/chrome/browser/media_galleries/fileapi/itunes_finder_win.h
index 5dd957a..53307d0 100644
--- a/chrome/browser/media_galleries/fileapi/itunes_finder_win.h
+++ b/chrome/browser/media_galleries/fileapi/itunes_finder_win.h
@@ -7,8 +7,15 @@
 
 #include "chrome/browser/media_galleries/fileapi/itunes_finder.h"
 
+namespace base {
+class FilePath;
+}
+
 namespace itunes {
 
+// This Windows-specific ITunesFinder uses a utility process to parse the
+// iTunes preferences XML file if it exists. If not or if the parsing fails,
+// ITunesFinderWin will try a default location as well.
 class ITunesFinderWin : public ITunesFinder {
  public:
   explicit ITunesFinderWin(const ITunesFinderCallback& callback);
@@ -17,6 +24,14 @@
  private:
   virtual void FindITunesLibraryOnFileThread() OVERRIDE;
 
+  // Check the default location for the iTunes library XML file.
+  // Runs on the FILE thread.
+  void TryDefaultLocation();
+
+  // Called by SafeITunesPrefParser when it finishes parsing the preferences
+  // XML file. Runs on the FILE thread.
+  void FinishedParsingPrefXML(const base::FilePath& library_file);
+
   DISALLOW_COPY_AND_ASSIGN(ITunesFinderWin);
 };
 
diff --git a/chrome/browser/media_galleries/fileapi/itunes_finder_win_browsertest.cc b/chrome/browser/media_galleries/fileapi/itunes_finder_win_browsertest.cc
new file mode 100644
index 0000000..6182ede
--- /dev/null
+++ b/chrome/browser/media_galleries/fileapi/itunes_finder_win_browsertest.cc
@@ -0,0 +1,195 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/base64.h"
+#include "base/base_paths_win.h"
+#include "base/bind.h"
+#include "base/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop.h"
+#include "base/path_service.h"
+#include "base/run_loop.h"
+#include "base/strings/stringprintf.h"
+#include "base/test/scoped_path_override.h"
+#include "chrome/browser/media_galleries/fileapi/itunes_finder_win.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/test/base/in_process_browser_test.h"
+
+namespace itunes {
+
+namespace {
+
+std::string EncodePath(const base::FilePath& path) {
+  std::string input(reinterpret_cast<const char*>(path.value().data()),
+                                                  path.value().size()*2);
+  std::string result;
+  base::Base64Encode(input, &result);
+  return result;
+}
+
+void TouchFile(const base::FilePath& file) {
+  ASSERT_EQ(1, file_util::WriteFile(file, " ", 1));
+}
+
+class ITunesFinderWinTest : public InProcessBrowserTest {
+ public:
+  ITunesFinderWinTest() : test_finder_callback_called_(false) {}
+
+  virtual void SetUp() OVERRIDE {
+    ASSERT_TRUE(app_data_dir_.CreateUniqueTempDir());
+    ASSERT_TRUE(music_dir_.CreateUniqueTempDir());
+    app_data_dir_override_.reset(
+        new base::ScopedPathOverride(base::DIR_APP_DATA, app_data_dir()));
+    music_dir_override_.reset(
+        new base::ScopedPathOverride(chrome::DIR_USER_MUSIC, music_dir()));
+    InProcessBrowserTest::SetUp();
+  }
+
+  const base::FilePath& app_data_dir() {
+    return app_data_dir_.path();
+  }
+
+  const base::FilePath& music_dir() {
+    return music_dir_.path();
+  }
+
+  void WritePrefFile(const std::string& data) {
+    base::FilePath pref_dir =
+        app_data_dir().AppendASCII("Apple Computer").AppendASCII("iTunes");
+    ASSERT_TRUE(file_util::CreateDirectory(pref_dir));
+    ASSERT_EQ(data.size(),
+              file_util::WriteFile(pref_dir.AppendASCII("iTunesPrefs.xml"),
+                                   data.data(), data.size()));
+  }
+
+  void TouchDefault() {
+    base::FilePath default_dir = music_dir().AppendASCII("iTunes");
+    ASSERT_TRUE(file_util::CreateDirectory(default_dir));
+    TouchFile(default_dir.AppendASCII("iTunes Music Library.xml"));
+  }
+
+  void TestFindITunesLibrary() {
+    test_finder_callback_called_ = false;
+    result_.clear();
+    base::RunLoop loop;
+    ITunesFinder::FindITunesLibrary(
+        base::Bind(&ITunesFinderWinTest::TestFinderCallback,
+                   base::Unretained(this),
+                   loop.QuitClosure()));
+    loop.Run();
+  }
+
+  bool EmptyResult() const {
+    return result_.empty();
+  }
+
+  bool test_finder_callback_called() const {
+    return test_finder_callback_called_;
+  }
+
+ private:
+  void TestFinderCallback(const base::Closure& quit_closure,
+                          const std::string& result) {
+    test_finder_callback_called_ = true;
+    result_ = result;
+    quit_closure.Run();
+  }
+
+  scoped_ptr<base::ScopedPathOverride> app_data_dir_override_;
+  scoped_ptr<base::ScopedPathOverride> music_dir_override_;
+  base::ScopedTempDir app_data_dir_;
+  base::ScopedTempDir music_dir_;
+
+  bool test_finder_callback_called_;
+  std::string result_;
+
+  DISALLOW_COPY_AND_ASSIGN(ITunesFinderWinTest);
+};
+
+IN_PROC_BROWSER_TEST_F(ITunesFinderWinTest, NotFound) {
+  TestFindITunesLibrary();
+  EXPECT_TRUE(test_finder_callback_called());
+  EXPECT_TRUE(EmptyResult());
+}
+
+IN_PROC_BROWSER_TEST_F(ITunesFinderWinTest, DefaultLocation) {
+  TouchDefault();
+  TestFindITunesLibrary();
+  EXPECT_TRUE(test_finder_callback_called());
+  EXPECT_FALSE(EmptyResult());
+}
+
+IN_PROC_BROWSER_TEST_F(ITunesFinderWinTest, CustomLocation) {
+  base::FilePath library_xml = music_dir().AppendASCII("library.xml");
+  TouchFile(library_xml);
+  std::string xml = base::StringPrintf(
+      "<plist>"
+      "  <dict>"
+      "    <key>User Preferences</key>"
+      "    <dict>"
+      "      <key>iTunes Library XML Location:1</key>"
+      "      <data>%s</data>"
+      "    </dict>"
+      "  </dict>"
+      "</plist>", EncodePath(library_xml).c_str());
+  WritePrefFile(xml);
+  TestFindITunesLibrary();
+  EXPECT_TRUE(test_finder_callback_called());
+  EXPECT_FALSE(EmptyResult());
+}
+
+IN_PROC_BROWSER_TEST_F(ITunesFinderWinTest, BadCustomLocation) {
+  // Missing file.
+  base::FilePath library_xml = music_dir().AppendASCII("library.xml");
+  std::string xml = base::StringPrintf(
+      "<plist>"
+      "  <dict>"
+      "    <key>User Preferences</key>"
+      "    <dict>"
+      "      <key>iTunes Library XML Location:1</key>"
+      "      <data>%s</data>"
+      "    </dict>"
+      "  </dict>"
+      "</plist>", EncodePath(library_xml).c_str());
+  WritePrefFile(xml);
+  TestFindITunesLibrary();
+  EXPECT_TRUE(test_finder_callback_called());
+  EXPECT_TRUE(EmptyResult());
+  TouchFile(library_xml);
+
+  // User Preferences dictionary at the wrong level.
+  xml = base::StringPrintf(
+      "<plist>"
+      "    <key>User Preferences</key>"
+      "    <dict>"
+      "      <key>iTunes Library XML Location:1</key>"
+      "      <data>%s</data>"
+      "    </dict>"
+      "</plist>", EncodePath(library_xml).c_str());
+  WritePrefFile(xml);
+  TestFindITunesLibrary();
+  EXPECT_TRUE(test_finder_callback_called());
+  EXPECT_TRUE(EmptyResult());
+
+  // Library location at the wrong scope.
+  xml = base::StringPrintf(
+      "<plist>"
+      "  <dict>"
+      "    <key>User Preferences</key>"
+      "    <dict/>"
+      "    <key>iTunes Library XML Location:1</key>"
+      "    <data>%s</data>"
+      "  </dict>"
+      "</plist>", EncodePath(library_xml).c_str());
+  WritePrefFile(xml);
+  TestFindITunesLibrary();
+  EXPECT_TRUE(test_finder_callback_called());
+  EXPECT_TRUE(EmptyResult());
+}
+
+}  // namespace
+
+}  // namespace itunes
diff --git a/chrome/browser/media_galleries/fileapi/itunes_finder_win_unittest.cc b/chrome/browser/media_galleries/fileapi/itunes_finder_win_unittest.cc
deleted file mode 100644
index 7f9571a..0000000
--- a/chrome/browser/media_galleries/fileapi/itunes_finder_win_unittest.cc
+++ /dev/null
@@ -1,181 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/base64.h"
-#include "base/base_paths_win.h"
-#include "base/bind.h"
-#include "base/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop.h"
-#include "base/path_service.h"
-#include "base/run_loop.h"
-#include "base/strings/stringprintf.h"
-#include "base/test/scoped_path_override.h"
-#include "chrome/browser/media_galleries/fileapi/itunes_finder.h"
-#include "chrome/browser/media_galleries/fileapi/itunes_finder_win.h"
-#include "chrome/common/chrome_paths.h"
-#include "content/public/test/test_browser_thread.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace itunes {
-
-namespace {
-
-std::string EncodePath(const base::FilePath& path) {
-  std::string input(reinterpret_cast<const char*>(path.value().data()),
-                                                  path.value().size()*2);
-  std::string result;
-  base::Base64Encode(input, &result);
-  return result;
-}
-
-void TouchFile(const base::FilePath& file) {
-  ASSERT_EQ(1, file_util::WriteFile(file, " ", 1));
-}
-
-class ITunesFinderWinTest : public testing::Test {
- public:
-  ITunesFinderWinTest()
-    : ui_thread_(content::BrowserThread::UI, &loop_),
-      file_thread_(content::BrowserThread::FILE, &loop_) {
-  }
-
-  virtual void SetUp() OVERRIDE {
-    ASSERT_TRUE(app_data_dir_.CreateUniqueTempDir());
-    ASSERT_TRUE(music_dir_.CreateUniqueTempDir());
-    app_data_dir_override_.reset(
-        new base::ScopedPathOverride(base::DIR_APP_DATA, app_data_dir()));
-    music_dir_override_.reset(
-        new base::ScopedPathOverride(chrome::DIR_USER_MUSIC, music_dir()));
-  }
-
-  const base::FilePath& app_data_dir() {
-    return app_data_dir_.path();
-  }
-
-  const base::FilePath& music_dir() {
-    return music_dir_.path();
-  }
-
-  void WritePrefFile(const std::string& data) {
-    base::FilePath pref_dir =
-        app_data_dir().AppendASCII("Apple Computer").AppendASCII("iTunes");
-    ASSERT_TRUE(file_util::CreateDirectory(pref_dir));
-    ASSERT_EQ(data.size(),
-              file_util::WriteFile(pref_dir.AppendASCII("iTunesPrefs.xml"),
-                                   data.data(), data.size()));
-  }
-
-  void TouchDefault() {
-    base::FilePath default_dir = music_dir().AppendASCII("iTunes");
-    ASSERT_TRUE(file_util::CreateDirectory(default_dir));
-    TouchFile(default_dir.AppendASCII("iTunes Music Library.xml"));
-  }
-
-  std::string TestFindITunesLibrary() {
-    std::string result;
-    ITunesFinder::FindITunesLibrary(
-        base::Bind(&ITunesFinderWinTest::FinderCallback,
-                   base::Unretained(this), base::Unretained(&result)));
-    base::RunLoop().RunUntilIdle();
-    return result;
-  }
-
- private:
-  void FinderCallback(std::string* result_holder, const std::string& result) {
-    *result_holder = result;
-  }
-
-  scoped_ptr<base::ScopedPathOverride> app_data_dir_override_;
-  scoped_ptr<base::ScopedPathOverride> music_dir_override_;
-  base::ScopedTempDir app_data_dir_;
-  base::ScopedTempDir music_dir_;
-
-  base::MessageLoop loop_;
-  content::TestBrowserThread ui_thread_;
-  content::TestBrowserThread file_thread_;
-
-  DISALLOW_COPY_AND_ASSIGN(ITunesFinderWinTest);
-};
-
-TEST_F(ITunesFinderWinTest, NotFound) {
-  std::string result = TestFindITunesLibrary();
-  EXPECT_TRUE(result.empty());
-}
-
-TEST_F(ITunesFinderWinTest, DefaultLocation) {
-  TouchDefault();
-  std::string result = TestFindITunesLibrary();
-  EXPECT_FALSE(result.empty());
-}
-
-TEST_F(ITunesFinderWinTest, CustomLocation) {
-  base::FilePath library_xml = music_dir().AppendASCII("library.xml");
-  TouchFile(library_xml);
-  std::string xml = base::StringPrintf(
-      "<plist>"
-      "  <dict>"
-      "    <key>User Preferences</key>"
-      "    <dict>"
-      "      <key>iTunes Library XML Location:1</key>"
-      "      <data>%s</data>"
-      "    </dict>"
-      "  </dict>"
-      "</plist>", EncodePath(library_xml).c_str());
-  WritePrefFile(xml);
-  std::string result = TestFindITunesLibrary();
-  EXPECT_FALSE(result.empty());
-}
-
-TEST_F(ITunesFinderWinTest, BadCustomLocation) {
-  // Missing file.
-  base::FilePath library_xml = music_dir().AppendASCII("library.xml");
-  std::string xml = base::StringPrintf(
-      "<plist>"
-      "  <dict>"
-      "    <key>User Preferences</key>"
-      "    <dict>"
-      "      <key>iTunes Library XML Location:1</key>"
-      "      <data>%s</data>"
-      "    </dict>"
-      "  </dict>"
-      "</plist>", EncodePath(library_xml).c_str());
-  WritePrefFile(xml);
-  std::string result = TestFindITunesLibrary();
-  EXPECT_TRUE(result.empty());
-  TouchFile(library_xml);
-
-  // User Preferences dictionary at the wrong level.
-  xml = base::StringPrintf(
-      "<plist>"
-      "    <key>User Preferences</key>"
-      "    <dict>"
-      "      <key>iTunes Library XML Location:1</key>"
-      "      <data>%s</data>"
-      "    </dict>"
-      "</plist>", EncodePath(library_xml).c_str());
-  WritePrefFile(xml);
-  result = TestFindITunesLibrary();
-  EXPECT_TRUE(result.empty());
-
-  // Library location at the wrong scope.
-  xml = base::StringPrintf(
-      "<plist>"
-      "  <dict>"
-      "    <key>User Preferences</key>"
-      "    <dict/>"
-      "    <key>iTunes Library XML Location:1</key>"
-      "    <data>%s</data>"
-      "  </dict>"
-      "</plist>", EncodePath(library_xml).c_str());
-  WritePrefFile(xml);
-  result = TestFindITunesLibrary();
-  EXPECT_TRUE(result.empty());
-}
-
-}  // namespace
-
-}  // namespace itunes
diff --git a/chrome/browser/media_galleries/fileapi/itunes_library_parser.cc b/chrome/browser/media_galleries/fileapi/itunes_library_parser.cc
deleted file mode 100644
index 95f3d71..0000000
--- a/chrome/browser/media_galleries/fileapi/itunes_library_parser.cc
+++ /dev/null
@@ -1,208 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/media_galleries/fileapi/itunes_library_parser.h"
-
-#include <string>
-
-#include "base/logging.h"
-#include "base/strings/string16.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/media_galleries/fileapi/itunes_xml_utils.h"
-#include "googleurl/src/gurl.h"
-#include "googleurl/src/url_canon.h"
-#include "googleurl/src/url_util.h"
-#include "third_party/libxml/chromium/libxml_utils.h"
-
-namespace itunes {
-
-namespace {
-
-struct TrackInfo {
-  uint64 id;
-  base::FilePath location;
-  std::string artist;
-  std::string album;
-};
-
-// Seek to the start of a tag and read the value into |result| if the node's
-// name is |node_name|.
-bool ReadSimpleValue(XmlReader* reader, const std::string& node_name,
-                     std::string* result) {
-  if (!SkipToNextElement(reader))
-      return false;
-  if (reader->NodeName() != node_name)
-    return false;
-  return reader->ReadElementContent(result);
-}
-
-// Get the value out of a string node.
-bool ReadString(XmlReader* reader, std::string* result) {
-  return ReadSimpleValue(reader, "string", result);
-}
-
-// Get the value out of an integer node.
-bool ReadInteger(XmlReader* reader, uint64* result) {
-  std::string value;
-  if (!ReadSimpleValue(reader, "integer", &value))
-    return false;
-  return base::StringToUint64(value, result);
-}
-
-// Walk through a dictionary filling in |result| with track information. Return
-// true if it was all found, false otherwise.  In either case, the cursor is
-// advanced out of the dictionary.
-bool GetTrackInfoFromDict(XmlReader* reader, TrackInfo* result) {
-  DCHECK(result);
-  if (reader->NodeName() != "dict")
-    return false;
-
-  int dict_content_depth = reader->Depth() + 1;
-  // Advance past the dict node and into the body of the dictionary.
-  if (!reader->Read())
-    return false;
-
-  bool found_id = false;
-  bool found_location = false;
-  bool found_artist = false;
-  bool found_album = false;
-  while (reader->Depth() >= dict_content_depth &&
-         !(found_id && found_location && found_artist && found_album)) {
-    if (!SeekToNodeAtCurrentDepth(reader, "key"))
-      break;
-    std::string found_key;
-    if (!reader->ReadElementContent(&found_key))
-      break;
-    DCHECK_EQ(dict_content_depth, reader->Depth());
-
-    if (found_key == "Track ID") {
-      if (found_id)
-        break;
-      if (!ReadInteger(reader, &result->id))
-        break;
-      found_id = true;
-    } else if (found_key == "Location") {
-      if (found_location)
-        break;
-      std::string value;
-      if (!ReadString(reader, &value))
-        break;
-      GURL url(value);
-      if (!url.SchemeIsFile())
-        break;
-      url_canon::RawCanonOutputW<1024> decoded_location;
-      url_util::DecodeURLEscapeSequences(url.path().c_str() + 1,  // Strip /.
-                                         url.path().length() - 1,
-                                         &decoded_location);
-#if defined(OS_WIN)
-      string16 location(decoded_location.data(), decoded_location.length());
-#else
-      string16 location16(decoded_location.data(), decoded_location.length());
-      std::string location = UTF16ToUTF8(location16);
-#endif
-      result->location = base::FilePath(location);
-      found_location = true;
-    } else if (found_key == "Album Artist") {
-      if (found_artist)
-        break;
-      if (!ReadString(reader, &result->artist))
-        break;
-      found_artist = true;
-    } else if (found_key == "Album") {
-      if (found_album)
-        break;
-      if (!ReadString(reader, &result->album))
-        break;
-      found_album = true;
-    } else {
-      if (!SkipToNextElement(reader))
-        break;
-      if (!reader->Next())
-        break;
-    }
-  }
-
-  // Seek to the end of the dictionary
-  while (reader->Depth() >= dict_content_depth)
-    reader->Next();
-
-  return found_id && found_location && found_artist && found_album;
-}
-
-}  // namespace
-
-ITunesLibraryParser::Track::Track(uint64 id, const base::FilePath& location)
-    : id(id),
-      location(location) {
-}
-
-bool ITunesLibraryParser::Track::operator<(const Track& other) const {
-  return id < other.id;
-}
-
-ITunesLibraryParser::ITunesLibraryParser() {}
-ITunesLibraryParser::~ITunesLibraryParser() {}
-
-bool ITunesLibraryParser::Parse(const std::string& library_xml) {
-  XmlReader reader;
-
-  if (!reader.Load(library_xml))
-    return false;
-
-  // Find the plist node and then search within that tag.
-  if (!SeekToNodeAtCurrentDepth(&reader, "plist"))
-    return false;
-  if (!reader.Read())
-    return false;
-
-  if (!SeekToNodeAtCurrentDepth(&reader, "dict"))
-    return false;
-
-  if (!SeekInDict(&reader, "Tracks"))
-    return false;
-
-  // Once inside the Tracks dict, we expect track dictionaries keyed by id. i.e.
-  //   <key>Tracks</key>
-  //   <dict>
-  //     <key>160</key>
-  //     <dict>
-  //       <key>Track ID</key><integer>160</integer>
-  if (!SeekToNodeAtCurrentDepth(&reader, "dict"))
-    return false;
-  int tracks_dict_depth = reader.Depth() + 1;
-  if (!reader.Read())
-    return false;
-
-  // Once parsing has gotten this far, return whatever is found, even if
-  // some of the data isn't extracted just right.
-  bool no_errors = true;
-  bool track_found = false;
-  while (reader.Depth() >= tracks_dict_depth) {
-    if (!SeekToNodeAtCurrentDepth(&reader, "key"))
-      return track_found;
-    std::string key;  // Should match track id below.
-    if (!reader.ReadElementContent(&key))
-      return track_found;
-    uint64 id;
-    bool id_valid = base::StringToUint64(key, &id);
-    if (!reader.SkipToElement())
-      return track_found;
-
-    TrackInfo track_info;
-    if (GetTrackInfoFromDict(&reader, &track_info) &&
-        id_valid &&
-        id == track_info.id) {
-      Track track(track_info.id, track_info.location);
-      library_[track_info.artist][track_info.album].insert(track);
-      track_found = true;
-    } else {
-      no_errors = false;
-    }
-  }
-
-  return track_found || no_errors;
-}
-
-}  // namespace itunes
diff --git a/chrome/browser/media_galleries/fileapi/itunes_library_parser.h b/chrome/browser/media_galleries/fileapi/itunes_library_parser.h
deleted file mode 100644
index 6f6ad82..0000000
--- a/chrome/browser/media_galleries/fileapi/itunes_library_parser.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_ITUNES_LIBRARY_PARSER_H_
-#define CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_ITUNES_LIBRARY_PARSER_H_
-
-#include <map>
-#include <set>
-
-#include "base/files/file_path.h"
-
-namespace itunes {
-
-class ITunesLibraryParser {
- public:
-  struct Track {
-    Track(uint64 id, const base::FilePath& location);
-    bool operator<(const Track& other) const;
-
-    uint64 id;
-    base::FilePath location;
-  };
-
-  typedef std::set<Track> Album;
-  typedef std::map<std::string /*album name*/, Album> Albums;
-  typedef std::map<std::string /*artist name*/, Albums> Library;
-
-  ITunesLibraryParser();
-  ~ITunesLibraryParser();
-
-  // Returns true if at least one track was found. Malformed track entries
-  // are silently ignored.
-  bool Parse(const std::string& xml);
-
-  const Library& library() { return library_; }
-
- private:
-  Library library_;
-
-  DISALLOW_COPY_AND_ASSIGN(ITunesLibraryParser);
-};
-
-}  // namespace itunes
-
-#endif  // CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_ITUNES_LIBRARY_PARSER_H_
diff --git a/chrome/browser/media_galleries/fileapi/itunes_library_parser_unittest.cc b/chrome/browser/media_galleries/fileapi/itunes_library_parser_unittest.cc
deleted file mode 100644
index 7f2117f..0000000
--- a/chrome/browser/media_galleries/fileapi/itunes_library_parser_unittest.cc
+++ /dev/null
@@ -1,197 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/logging.h"
-#include "chrome/browser/media_galleries/fileapi/itunes_library_parser.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#define SIMPLE_HEADER()         \
-    "<plist>"                   \
-    "  <dict>"                  \
-    "    <key>Tracks</key>"     \
-    "    <dict>"
-
-#define SIMPLE_TRACK(key, id, path, artist, album)                     \
-    "<key>" #key "</key>"                                              \
-    "<dict>"                                                           \
-    "  <key>Track ID</key><integer>" #id "</integer>"                  \
-    "  <key>Location</key><string>file://localhost/" path "</string>"  \
-    "  <key>Album Artist</key><string>" artist "</string>"             \
-    "  <key>Album</key><string>" album "</string>"                     \
-    "</dict>"
-
-#define SIMPLE_FOOTER()  \
-    "    </dict>"        \
-    "  </dict>"          \
-    "</plist>"
-
-namespace itunes {
-
-namespace {
-
-void CompareTrack(const ITunesLibraryParser::Track& a,
-                  const ITunesLibraryParser::Track& b) {
-  EXPECT_EQ(a.id, b.id);
-  EXPECT_EQ(a.location, b.location);
-}
-
-void CompareAlbum(const ITunesLibraryParser::Album& a,
-                  const ITunesLibraryParser::Album& b) {
-  EXPECT_EQ(a.size(), b.size());
-
-  ITunesLibraryParser::Album::const_iterator a_it;
-  ITunesLibraryParser::Album::const_iterator b_it;
-  for (a_it = a.begin(), b_it = b.begin();
-       a_it != a.end() && b_it != b.end();
-       ++a_it, ++b_it) {
-    CompareTrack(*a_it, *b_it);
-  }
-}
-
-void CompareAlbums(const ITunesLibraryParser::Albums& a,
-                   const ITunesLibraryParser::Albums& b) {
-  EXPECT_EQ(a.size(), b.size());
-
-  ITunesLibraryParser::Albums::const_iterator a_it;
-  ITunesLibraryParser::Albums::const_iterator b_it;
-  for (a_it = a.begin(), b_it = b.begin();
-       a_it != a.end() && b_it != b.end();
-       ++a_it, ++b_it) {
-    EXPECT_EQ(a_it->first, b_it->first);
-    CompareAlbum(a_it->second, b_it->second);
-  }
-}
-
-void CompareLibrary(const ITunesLibraryParser::Library& a,
-                    const ITunesLibraryParser::Library& b) {
-  EXPECT_EQ(a.size(), b.size());
-
-  ITunesLibraryParser::Library::const_iterator a_it;
-  ITunesLibraryParser::Library::const_iterator b_it;
-  for (a_it = a.begin(), b_it = b.begin();
-       a_it != a.end() && b_it != b.end();
-       ++a_it, ++b_it) {
-    EXPECT_EQ(a_it->first, b_it->first);
-    CompareAlbums(a_it->second, b_it->second);
-  }
-}
-
-class ITunesLibraryParserTest : public testing::Test {
- public:
-  ITunesLibraryParserTest() {}
-
-  void TestParser(bool expected_result, const std::string& xml) {
-    ITunesLibraryParser parser;
-
-    EXPECT_EQ(expected_result, parser.Parse(xml));
-    if (!expected_result)
-      return;
-
-    CompareLibrary(expected_library_, parser.library());
-  }
-
-  void AddExpectedTrack(uint32 id, const std::string& location,
-                        const std::string& artist, const std::string& album) {
-    ITunesLibraryParser::Track track(id,
-                                     base::FilePath::FromUTF8Unsafe(location));
-    expected_library_[artist][album].insert(track);
-  }
-
- private:
-  ITunesLibraryParser::Library expected_library_;
-
-  DISALLOW_COPY_AND_ASSIGN(ITunesLibraryParserTest);
-};
-
-TEST_F(ITunesLibraryParserTest, EmptyLibrary) {
-  TestParser(false, "");
-}
-
-TEST_F(ITunesLibraryParserTest, MinimalXML) {
-  AddExpectedTrack(1, "C:/dir/Song With Space.mp3", "Artist A", "Album A");
-  TestParser(
-      true,
-      SIMPLE_HEADER()
-      SIMPLE_TRACK(1, 1, "C:/dir/Song%20With%20Space.mp3", "Artist A",
-                   "Album A")
-      SIMPLE_FOOTER());
-}
-
-TEST_F(ITunesLibraryParserTest, MultipleSongs) {
-  AddExpectedTrack(1, "C:/dir/SongA1.mp3", "Artist A", "Album A");
-  AddExpectedTrack(2, "C:/dir/SongA2.mp3", "Artist A", "Album A");
-  AddExpectedTrack(3, "C:/dir/SongA3.mp3", "Artist A", "Album A");
-  AddExpectedTrack(4, "C:/dir/SongB1.mp3", "Artist A", "Album B");
-  AddExpectedTrack(5, "C:/dir/SongB2.mp3", "Artist A", "Album B");
-  AddExpectedTrack(6, "C:/dir2/SongB1.mp3", "Artist B", "Album B");
-  AddExpectedTrack(7, "C:/dir2/SongB2.mp3", "Artist B", "Album B");
-  TestParser(
-      true,
-      SIMPLE_HEADER()
-      SIMPLE_TRACK(1, 1, "C:/dir/SongA1.mp3", "Artist A", "Album A")
-      SIMPLE_TRACK(2, 2, "C:/dir/SongA2.mp3", "Artist A", "Album A")
-      SIMPLE_TRACK(3, 3, "C:/dir/SongA3.mp3", "Artist A", "Album A")
-      SIMPLE_TRACK(4, 4, "C:/dir/SongB1.mp3", "Artist A", "Album B")
-      SIMPLE_TRACK(5, 5, "C:/dir/SongB2.mp3", "Artist A", "Album B")
-      SIMPLE_TRACK(6, 6, "C:/dir2/SongB1.mp3", "Artist B", "Album B")
-      SIMPLE_TRACK(7, 7, "C:/dir2/SongB2.mp3", "Artist B", "Album B")
-      SIMPLE_FOOTER());
-}
-
-TEST_F(ITunesLibraryParserTest, MismatchedId) {
-  TestParser(
-      false,
-      SIMPLE_HEADER()
-      SIMPLE_TRACK(1, 2, "C:/dir/SongA1.mp3", "Artist A", "Album A")
-      SIMPLE_FOOTER());
-
-  AddExpectedTrack(1, "C:/dir/SongA1.mp3", "Artist A", "Album A");
-  TestParser(
-      true,
-      SIMPLE_HEADER()
-      SIMPLE_TRACK(1, 1, "C:/dir/SongA1.mp3", "Artist A", "Album A")
-      SIMPLE_TRACK(2, 3, "C:/dir/SongA2.mp3", "Artist A", "Album A")
-      SIMPLE_FOOTER());
-}
-
-TEST_F(ITunesLibraryParserTest, OtherDictionaryEntries) {
-  AddExpectedTrack(1, "C:/dir/SongA1.mp3", "Artist A", "Album A");
-  TestParser(
-      true,
-      "<plist>"
-      "  <dict>"
-      "    <key>Other section</key>"
-      "    <dict>"
-      // In Other section, not Tracks.
-      SIMPLE_TRACK(10, 10, "C:/dir/SongB2.mp3", "Artist B", "Album B")
-      "    </dict>"
-      "    <key>Tracks</key>"
-      "    <dict>"
-      "      <key>1</key>"
-      "      <dict>"
-      // In the body of a track dictionary before the interesting entries.
-      SIMPLE_TRACK(20, 20, "C:/dir/SongB2.mp3", "Artist B", "Album B")
-      // Entries in a different order.
-      "        <key>Album Artist</key><string>Artist A</string>"
-      "        <key>Location</key>"
-      "          <string>file://localhost/C:/dir/SongA1.mp3</string>"
-      "        <key>Album</key><string>Album A</string>"
-      "        <key>Track ID</key><integer>1</integer>"
-      // In the body of a track dictionary after the interesting entries.
-      SIMPLE_TRACK(30, 30, "C:/dir/SongB3.mp3", "Artist B", "Album B")
-      "      </dict>"
-      "      <key>40</key>"
-      "      <dict>"
-      // Missing album name.
-      "        <key>Album Artist</key><string>Artist B</string>"
-      "        <key>Location</key>"
-      "          <string>file://localhost/C:/dir/SongB4.mp3</string>"
-      "        <key>Track ID</key><integer>1</integer>"
-      "      </dict>"
-      SIMPLE_FOOTER());
-}
-
-}  // namespace
-
-}  // namespace itunes
diff --git a/chrome/browser/media_galleries/fileapi/itunes_xml_utils.cc b/chrome/browser/media_galleries/fileapi/itunes_xml_utils.cc
deleted file mode 100644
index d59346b..0000000
--- a/chrome/browser/media_galleries/fileapi/itunes_xml_utils.cc
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/media_galleries/fileapi/itunes_xml_utils.h"
-#include <string>
-
-#include "base/logging.h"
-#include "third_party/libxml/chromium/libxml_utils.h"
-
-namespace itunes {
-
-bool SkipToNextElement(XmlReader* reader) {
-  if (!reader->SkipToElement()) {
-    // SkipToElement returns false if the current node is an end element,
-    // try to advance to the next element and then try again.
-    if (!reader->Read() || !reader->SkipToElement())
-      return false;
-  }
-  return true;
-}
-
-bool SeekToNodeAtCurrentDepth(XmlReader* reader, const std::string& name) {
-  int depth = reader->Depth();
-  do {
-    if (!SkipToNextElement(reader))
-      return false;
-    DCHECK_EQ(depth, reader->Depth());
-    if (reader->NodeName() == name)
-      return true;
-  } while (reader->Next());
-
-  return false;
-}
-
-bool SeekInDict(XmlReader* reader, const std::string& key) {
-  DCHECK_EQ("dict", reader->NodeName());
-
-  int dict_content_depth = reader->Depth() + 1;
-  // Advance past the dict node and into the body of the dictionary.
-  if (!reader->Read())
-    return false;
-
-  while (reader->Depth() >= dict_content_depth) {
-    if (!SeekToNodeAtCurrentDepth(reader, "key"))
-      return false;
-    std::string found_key;
-    if (!reader->ReadElementContent(&found_key))
-      return false;
-    DCHECK_EQ(dict_content_depth, reader->Depth());
-    if (found_key == key)
-      return true;
-  }
-  return false;
-}
-
-}  // namespace itunes
diff --git a/chrome/browser/media_galleries/fileapi/itunes_xml_utils.h b/chrome/browser/media_galleries/fileapi/itunes_xml_utils.h
deleted file mode 100644
index aad4865..0000000
--- a/chrome/browser/media_galleries/fileapi/itunes_xml_utils.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_ITUNES_XML_UTILS_H_
-#define CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_ITUNES_XML_UTILS_H_
-
-#include <string>
-
-class XmlReader;
-
-namespace itunes {
-
-// Like XmlReader::SkipToElement, but will advance to the next open tag if the
-// cursor is on a close tag.
-bool SkipToNextElement(XmlReader* reader);
-
-// Traverse |reader| looking for a node named |name| at the current depth
-// of |reader|.
-bool SeekToNodeAtCurrentDepth(XmlReader* reader, const std::string& name);
-
-// Search within a "dict" node for |key|. The cursor must be on the starting
-// "dict" node when entering this function.
-bool SeekInDict(XmlReader* reader, const std::string& key);
-
-}  // namespace itunes
-
-#endif  // CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_ITUNES_XML_UTILS_H_
diff --git a/chrome/browser/media_galleries/fileapi/media_file_system_mount_point_provider.cc b/chrome/browser/media_galleries/fileapi/media_file_system_mount_point_provider.cc
index 52d5c0e..7d65431 100644
--- a/chrome/browser/media_galleries/fileapi/media_file_system_mount_point_provider.cc
+++ b/chrome/browser/media_galleries/fileapi/media_file_system_mount_point_provider.cc
@@ -14,11 +14,9 @@
 #include "base/sequenced_task_runner.h"
 #include "base/threading/sequenced_worker_pool.h"
 #include "chrome/browser/media_galleries/fileapi/device_media_async_file_util.h"
-#include "chrome/browser/media_galleries/fileapi/itunes_file_util.h"
 #include "chrome/browser/media_galleries/fileapi/media_file_validator_factory.h"
 #include "chrome/browser/media_galleries/fileapi/media_path_filter.h"
 #include "chrome/browser/media_galleries/fileapi/native_media_file_util.h"
-#include "chrome/browser/media_galleries/fileapi/picasa/picasa_file_util.h"
 #include "content/public/browser/browser_thread.h"
 #include "webkit/browser/blob/local_file_stream_reader.h"
 #include "webkit/browser/fileapi/async_file_util_adapter.h"
@@ -35,6 +33,11 @@
 #include "webkit/common/fileapi/file_system_types.h"
 #include "webkit/common/fileapi/file_system_util.h"
 
+#if defined(OS_WIN) || defined(OS_MACOSX)
+#include "chrome/browser/media_galleries/fileapi/itunes_file_util.h"
+#include "chrome/browser/media_galleries/fileapi/picasa/picasa_file_util.h"
+#endif  // defined(OS_WIN) || defined(OS_MACOSX)
+
 using fileapi::FileSystemContext;
 using fileapi::FileSystemURL;
 
@@ -56,9 +59,13 @@
       media_copy_or_move_file_validator_factory_(new MediaFileValidatorFactory),
       native_media_file_util_(new NativeMediaFileUtil()),
       device_media_async_file_util_(
-          DeviceMediaAsyncFileUtil::Create(profile_path_)),
+          DeviceMediaAsyncFileUtil::Create(profile_path_))
+#if defined(OS_WIN) || defined(OS_MACOSX)
+      ,
       picasa_file_util_(new picasa::PicasaFileUtil()),
-      itunes_file_util_(new itunes::ItunesFileUtil()) {
+      itunes_file_util_(new itunes::ItunesFileUtil())
+#endif  // defined(OS_WIN) || defined(OS_MACOSX)
+{
 }
 
 MediaFileSystemMountPointProvider::~MediaFileSystemMountPointProvider() {
@@ -72,13 +79,24 @@
   return pool->IsRunningSequenceOnCurrentThread(media_sequence_token);
 }
 
+// static
+scoped_refptr<base::SequencedTaskRunner>
+MediaFileSystemMountPointProvider::MediaTaskRunner() {
+  base::SequencedWorkerPool* pool = content::BrowserThread::GetBlockingPool();
+  base::SequencedWorkerPool::SequenceToken media_sequence_token =
+      pool->GetNamedSequenceToken(kMediaTaskRunnerName);
+  return pool->GetSequencedTaskRunner(media_sequence_token);
+}
+
 bool MediaFileSystemMountPointProvider::CanHandleType(
     fileapi::FileSystemType type) const {
   switch (type) {
     case fileapi::kFileSystemTypeNativeMedia:
     case fileapi::kFileSystemTypeDeviceMedia:
+#if defined(OS_WIN) || defined(OS_MACOSX)
     case fileapi::kFileSystemTypePicasa:
     case fileapi::kFileSystemTypeItunes:
+#endif  // defined(OS_WIN) || defined(OS_MACOSX)
       return true;
     default:
       return false;
@@ -107,12 +125,14 @@
   switch (type) {
     case fileapi::kFileSystemTypeNativeMedia:
       return native_media_file_util_.get();
-    case fileapi::kFileSystemTypePicasa:
-      return picasa_file_util_.get();
     case fileapi::kFileSystemTypeDeviceMedia:
       return device_media_async_file_util_.get();
+#if defined(OS_WIN) || defined(OS_MACOSX)
     case fileapi::kFileSystemTypeItunes:
       return itunes_file_util_.get();
+    case fileapi::kFileSystemTypePicasa:
+      return picasa_file_util_.get();
+#endif  // defined(OS_WIN) || defined(OS_MACOSX)
     default:
       NOTREACHED();
   }
@@ -139,14 +159,6 @@
   return NULL;
 }
 
-fileapi::FilePermissionPolicy
-MediaFileSystemMountPointProvider::GetPermissionPolicy(
-    const FileSystemURL& url, int permissions) const {
-  // Access to media file systems should be checked using per-filesystem
-  // access permission.
-  return fileapi::FILE_PERMISSION_USE_FILESYSTEM_PERMISSION;
-}
-
 fileapi::FileSystemOperation*
 MediaFileSystemMountPointProvider::CreateFileSystemOperation(
     const FileSystemURL& url,
@@ -185,7 +197,9 @@
     int64 offset,
     FileSystemContext* context) const {
   return scoped_ptr<fileapi::FileStreamWriter>(
-      new fileapi::LocalFileStreamWriter(url.path(), offset));
+      new fileapi::LocalFileStreamWriter(
+          context->task_runners()->file_task_runner(),
+          url.path(), offset));
 }
 
 fileapi::FileSystemQuotaUtil*
diff --git a/chrome/browser/media_galleries/fileapi/media_file_system_mount_point_provider.h b/chrome/browser/media_galleries/fileapi/media_file_system_mount_point_provider.h
index b1b07a7..dbe18cf 100644
--- a/chrome/browser/media_galleries/fileapi/media_file_system_mount_point_provider.h
+++ b/chrome/browser/media_galleries/fileapi/media_file_system_mount_point_provider.h
@@ -36,6 +36,7 @@
   virtual ~MediaFileSystemMountPointProvider();
 
   static bool CurrentlyOnMediaTaskRunnerThread();
+  static scoped_refptr<base::SequencedTaskRunner> MediaTaskRunner();
 
   // FileSystemMountPointProvider implementation.
   virtual bool CanHandleType(fileapi::FileSystemType type) const OVERRIDE;
@@ -52,8 +53,6 @@
   GetCopyOrMoveFileValidatorFactory(
       fileapi::FileSystemType type,
       base::PlatformFileError* error_code) OVERRIDE;
-  virtual fileapi::FilePermissionPolicy GetPermissionPolicy(
-      const fileapi::FileSystemURL& url, int permissions) const OVERRIDE;
   virtual fileapi::FileSystemOperation* CreateFileSystemOperation(
       const fileapi::FileSystemURL& url,
       fileapi::FileSystemContext* context,
@@ -86,8 +85,10 @@
 
   scoped_ptr<fileapi::AsyncFileUtil> native_media_file_util_;
   scoped_ptr<DeviceMediaAsyncFileUtil> device_media_async_file_util_;
+#if defined(OS_WIN) || defined(OS_MACOSX)
   scoped_ptr<fileapi::AsyncFileUtil> picasa_file_util_;
   scoped_ptr<fileapi::AsyncFileUtil> itunes_file_util_;
+#endif  // defined(OS_WIN) || defined(OS_MACOSX)
 
   DISALLOW_COPY_AND_ASSIGN(MediaFileSystemMountPointProvider);
 };
diff --git a/chrome/browser/media_galleries/fileapi/media_file_validator_unittest.cc b/chrome/browser/media_galleries/fileapi/media_file_validator_unittest.cc
index e23e5b7..79d030f 100644
--- a/chrome/browser/media_galleries/fileapi/media_file_validator_unittest.cc
+++ b/chrome/browser/media_galleries/fileapi/media_file_validator_unittest.cc
@@ -7,8 +7,8 @@
 #include "base/file_util.h"
 #include "base/files/file_path.h"
 #include "base/files/scoped_temp_dir.h"
-#include "base/message_loop.h"
-#include "base/message_loop_proxy.h"
+#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_proxy.h"
 #include "chrome/browser/media_galleries/fileapi/media_file_system_mount_point_provider.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "content/public/test/browser_test.h"
diff --git a/chrome/browser/media_galleries/fileapi/native_media_file_util.cc b/chrome/browser/media_galleries/fileapi/native_media_file_util.cc
index 6cbccee..29e33dc 100644
--- a/chrome/browser/media_galleries/fileapi/native_media_file_util.cc
+++ b/chrome/browser/media_galleries/fileapi/native_media_file_util.cc
@@ -4,7 +4,10 @@
 
 #include "chrome/browser/media_galleries/fileapi/native_media_file_util.h"
 
+#include <string>
+
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/file_util.h"
 #include "base/files/file_enumerator.h"
 #include "base/strings/string_util.h"
@@ -12,8 +15,8 @@
 #include "chrome/browser/media_galleries/fileapi/media_file_system_mount_point_provider.h"
 #include "chrome/browser/media_galleries/fileapi/media_path_filter.h"
 #include "content/public/browser/browser_thread.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/mime_sniffer.h"
+#include "url/gurl.h"
 #include "webkit/browser/fileapi/file_system_context.h"
 #include "webkit/browser/fileapi/file_system_operation_context.h"
 #include "webkit/browser/fileapi/file_system_task_runners.h"
@@ -142,8 +145,7 @@
   base::PlatformFile invalid_file(base::kInvalidPlatformFileValue);
   if (!callback.is_null()) {
     callback.Run(base::PLATFORM_FILE_ERROR_SECURITY,
-                 base::PassPlatformFile(&invalid_file),
-                 false);
+                 base::PassPlatformFile(&invalid_file));
   }
   return true;
 }
@@ -165,11 +167,11 @@
     bool recursive,
     const StatusCallback& callback) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
-  fileapi::FileSystemOperationContext* context_ptr = context.release();
+  fileapi::FileSystemOperationContext* context_ptr = context.get();
   return context_ptr->task_runner()->PostTask(
       FROM_HERE,
       base::Bind(&NativeMediaFileUtil::CreateDirectoryOnTaskRunnerThread,
-                 weak_factory_.GetWeakPtr(), base::Owned(context_ptr),
+                 weak_factory_.GetWeakPtr(), base::Passed(&context),
                  url, exclusive, recursive, callback));
 }
 
@@ -178,11 +180,11 @@
     const fileapi::FileSystemURL& url,
     const GetFileInfoCallback& callback) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
-  fileapi::FileSystemOperationContext* context_ptr = context.release();
+  fileapi::FileSystemOperationContext* context_ptr = context.get();
   return context_ptr->task_runner()->PostTask(
       FROM_HERE,
       base::Bind(&NativeMediaFileUtil::GetFileInfoOnTaskRunnerThread,
-                 weak_factory_.GetWeakPtr(), base::Owned(context_ptr),
+                 weak_factory_.GetWeakPtr(), base::Passed(&context),
                  url, callback));
 }
 
@@ -191,11 +193,11 @@
     const fileapi::FileSystemURL& url,
     const ReadDirectoryCallback& callback) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
-  fileapi::FileSystemOperationContext* context_ptr = context.release();
+  fileapi::FileSystemOperationContext* context_ptr = context.get();
   return context_ptr->task_runner()->PostTask(
       FROM_HERE,
       base::Bind(&NativeMediaFileUtil::ReadDirectoryOnTaskRunnerThread,
-                 weak_factory_.GetWeakPtr(), base::Owned(context_ptr),
+                 weak_factory_.GetWeakPtr(), base::Passed(&context),
                  url, callback));
 }
 
@@ -228,11 +230,11 @@
     const fileapi::FileSystemURL& dest_url,
     const StatusCallback& callback) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
-  fileapi::FileSystemOperationContext* context_ptr = context.release();
+  fileapi::FileSystemOperationContext* context_ptr = context.get();
   return context_ptr->task_runner()->PostTask(
       FROM_HERE,
       base::Bind(&NativeMediaFileUtil::CopyOrMoveFileLocalOnTaskRunnerThread,
-                 weak_factory_.GetWeakPtr(), base::Owned(context_ptr),
+                 weak_factory_.GetWeakPtr(), base::Passed(&context),
                  src_url, dest_url, true /* copy */, callback));
 }
 
@@ -242,11 +244,11 @@
     const fileapi::FileSystemURL& dest_url,
     const StatusCallback& callback) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
-  fileapi::FileSystemOperationContext* context_ptr = context.release();
+  fileapi::FileSystemOperationContext* context_ptr = context.get();
   return context_ptr->task_runner()->PostTask(
       FROM_HERE,
       base::Bind(&NativeMediaFileUtil::CopyOrMoveFileLocalOnTaskRunnerThread,
-                 weak_factory_.GetWeakPtr(), base::Owned(context_ptr),
+                 weak_factory_.GetWeakPtr(), base::Passed(&context),
                  src_url, dest_url, false /* copy */, callback));
 }
 
@@ -256,11 +258,11 @@
     const fileapi::FileSystemURL& dest_url,
     const StatusCallback& callback) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
-  fileapi::FileSystemOperationContext* context_ptr = context.release();
+  fileapi::FileSystemOperationContext* context_ptr = context.get();
   return context_ptr->task_runner()->PostTask(
       FROM_HERE,
       base::Bind(&NativeMediaFileUtil::CopyInForeignFileOnTaskRunnerThread,
-                 weak_factory_.GetWeakPtr(), base::Owned(context_ptr),
+                 weak_factory_.GetWeakPtr(), base::Passed(&context),
                  src_file_path, dest_url, callback));
 }
 
@@ -280,36 +282,46 @@
     const fileapi::FileSystemURL& url,
     const StatusCallback& callback) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
-  fileapi::FileSystemOperationContext* context_ptr = context.release();
+  fileapi::FileSystemOperationContext* context_ptr = context.get();
   return context_ptr->task_runner()->PostTask(
       FROM_HERE,
       base::Bind(&NativeMediaFileUtil::DeleteDirectoryOnTaskRunnerThread,
-                 weak_factory_.GetWeakPtr(), base::Owned(context_ptr),
+                 weak_factory_.GetWeakPtr(), base::Passed(&context),
                  url, callback));
 }
 
+bool NativeMediaFileUtil::DeleteRecursively(
+    scoped_ptr<fileapi::FileSystemOperationContext> context,
+    const fileapi::FileSystemURL& url,
+    const StatusCallback& callback) {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+  if (!callback.is_null())
+    callback.Run(base::PLATFORM_FILE_ERROR_INVALID_OPERATION);
+  return true;
+}
+
 bool NativeMediaFileUtil::CreateSnapshotFile(
     scoped_ptr<fileapi::FileSystemOperationContext> context,
     const fileapi::FileSystemURL& url,
     const CreateSnapshotFileCallback& callback) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
-  fileapi::FileSystemOperationContext* context_ptr = context.release();
+  fileapi::FileSystemOperationContext* context_ptr = context.get();
   return context_ptr->task_runner()->PostTask(
       FROM_HERE,
       base::Bind(&NativeMediaFileUtil::CreateSnapshotFileOnTaskRunnerThread,
-                 weak_factory_.GetWeakPtr(), base::Owned(context_ptr),
+                 weak_factory_.GetWeakPtr(), base::Passed(&context),
                  url, callback));
 }
 
 void NativeMediaFileUtil::CreateDirectoryOnTaskRunnerThread(
-    fileapi::FileSystemOperationContext* context,
+    scoped_ptr<fileapi::FileSystemOperationContext> context,
     const fileapi::FileSystemURL& url,
     bool exclusive,
     bool recursive,
     const StatusCallback& callback) {
-  DCHECK(IsOnTaskRunnerThread(context));
+  DCHECK(IsOnTaskRunnerThread(context.get()));
   base::PlatformFileError error =
-      CreateDirectorySync(context, url, exclusive, recursive);
+      CreateDirectorySync(context.get(), url, exclusive, recursive);
   if (callback.is_null())
     return;
   content::BrowserThread::PostTask(
@@ -319,15 +331,15 @@
 }
 
 void NativeMediaFileUtil::GetFileInfoOnTaskRunnerThread(
-    fileapi::FileSystemOperationContext* context,
+    scoped_ptr<fileapi::FileSystemOperationContext> context,
     const fileapi::FileSystemURL& url,
     const GetFileInfoCallback& callback) {
-  DCHECK(IsOnTaskRunnerThread(context));
+  DCHECK(IsOnTaskRunnerThread(context.get()));
   base::PlatformFileInfo file_info;
   // TODO(thestig): remove this.
   base::FilePath platform_path;
   base::PlatformFileError error =
-      GetFileInfoSync(context, url, &file_info, &platform_path);
+      GetFileInfoSync(context.get(), url, &file_info, &platform_path);
   if (callback.is_null())
     return;
   content::BrowserThread::PostTask(
@@ -337,13 +349,13 @@
 }
 
 void NativeMediaFileUtil::ReadDirectoryOnTaskRunnerThread(
-    fileapi::FileSystemOperationContext* context,
+    scoped_ptr<fileapi::FileSystemOperationContext> context,
     const fileapi::FileSystemURL& url,
     const ReadDirectoryCallback& callback) {
-  DCHECK(IsOnTaskRunnerThread(context));
+  DCHECK(IsOnTaskRunnerThread(context.get()));
   EntryList entry_list;
   base::PlatformFileError error =
-      ReadDirectorySync(context, url, &entry_list);
+      ReadDirectorySync(context.get(), url, &entry_list);
   if (callback.is_null())
     return;
   content::BrowserThread::PostTask(
@@ -353,14 +365,14 @@
 }
 
 void NativeMediaFileUtil::CopyOrMoveFileLocalOnTaskRunnerThread(
-    fileapi::FileSystemOperationContext* context,
+    scoped_ptr<fileapi::FileSystemOperationContext> context,
     const fileapi::FileSystemURL& src_url,
     const fileapi::FileSystemURL& dest_url,
     bool copy,
     const StatusCallback& callback) {
-  DCHECK(IsOnTaskRunnerThread(context));
+  DCHECK(IsOnTaskRunnerThread(context.get()));
   base::PlatformFileError error =
-      CopyOrMoveFileSync(context, src_url, dest_url, copy);
+      CopyOrMoveFileSync(context.get(), src_url, dest_url, copy);
   if (callback.is_null())
     return;
   content::BrowserThread::PostTask(
@@ -370,13 +382,13 @@
 }
 
 void NativeMediaFileUtil::CopyInForeignFileOnTaskRunnerThread(
-    fileapi::FileSystemOperationContext* context,
+    scoped_ptr<fileapi::FileSystemOperationContext> context,
     const base::FilePath& src_file_path,
     const fileapi::FileSystemURL& dest_url,
     const StatusCallback& callback) {
-  DCHECK(IsOnTaskRunnerThread(context));
+  DCHECK(IsOnTaskRunnerThread(context.get()));
   base::PlatformFileError error =
-      CopyInForeignFileSync(context, src_file_path, dest_url);
+      CopyInForeignFileSync(context.get(), src_file_path, dest_url);
   if (callback.is_null())
     return;
   content::BrowserThread::PostTask(
@@ -386,11 +398,11 @@
 }
 
 void NativeMediaFileUtil::DeleteDirectoryOnTaskRunnerThread(
-    fileapi::FileSystemOperationContext* context,
+    scoped_ptr<fileapi::FileSystemOperationContext> context,
     const fileapi::FileSystemURL& url,
     const StatusCallback& callback) {
-  DCHECK(IsOnTaskRunnerThread(context));
-  base::PlatformFileError error = DeleteDirectorySync(context, url);
+  DCHECK(IsOnTaskRunnerThread(context.get()));
+  base::PlatformFileError error = DeleteDirectorySync(context.get(), url);
   if (callback.is_null())
     return;
   content::BrowserThread::PostTask(
@@ -400,15 +412,15 @@
 }
 
 void NativeMediaFileUtil::CreateSnapshotFileOnTaskRunnerThread(
-    fileapi::FileSystemOperationContext* context,
+    scoped_ptr<fileapi::FileSystemOperationContext> context,
     const fileapi::FileSystemURL& url,
     const CreateSnapshotFileCallback& callback) {
-  DCHECK(IsOnTaskRunnerThread(context));
+  DCHECK(IsOnTaskRunnerThread(context.get()));
   base::PlatformFileInfo file_info;
   base::FilePath platform_path;
   scoped_refptr<webkit_blob::ShareableFileReference> file_ref;
   base::PlatformFileError error =
-      CreateSnapshotFileSync(context, url, &file_info, &platform_path,
+      CreateSnapshotFileSync(context.get(), url, &file_info, &platform_path,
                              &file_ref);
   if (callback.is_null())
     return;
diff --git a/chrome/browser/media_galleries/fileapi/native_media_file_util.h b/chrome/browser/media_galleries/fileapi/native_media_file_util.h
index 76c1e58..731bdb9 100644
--- a/chrome/browser/media_galleries/fileapi/native_media_file_util.h
+++ b/chrome/browser/media_galleries/fileapi/native_media_file_util.h
@@ -82,6 +82,10 @@
       scoped_ptr<fileapi::FileSystemOperationContext> context,
       const fileapi::FileSystemURL& url,
       const StatusCallback& callback) OVERRIDE;
+  virtual bool DeleteRecursively(
+      scoped_ptr<fileapi::FileSystemOperationContext> context,
+      const fileapi::FileSystemURL& url,
+      const StatusCallback& callback) OVERRIDE;
   virtual bool CreateSnapshotFile(
       scoped_ptr<fileapi::FileSystemOperationContext> context,
       const fileapi::FileSystemURL& url,
@@ -89,36 +93,36 @@
 
  protected:
   virtual void CreateDirectoryOnTaskRunnerThread(
-      fileapi::FileSystemOperationContext* context,
+      scoped_ptr<fileapi::FileSystemOperationContext> context,
       const fileapi::FileSystemURL& url,
       bool exclusive,
       bool recursive,
       const StatusCallback& callback);
   virtual void GetFileInfoOnTaskRunnerThread(
-      fileapi::FileSystemOperationContext* context,
+      scoped_ptr<fileapi::FileSystemOperationContext> context,
       const fileapi::FileSystemURL& url,
       const GetFileInfoCallback& callback);
   virtual void ReadDirectoryOnTaskRunnerThread(
-      fileapi::FileSystemOperationContext* context,
+      scoped_ptr<fileapi::FileSystemOperationContext> context,
       const fileapi::FileSystemURL& url,
       const ReadDirectoryCallback& callback);
   virtual void CopyOrMoveFileLocalOnTaskRunnerThread(
-      fileapi::FileSystemOperationContext* context,
+      scoped_ptr<fileapi::FileSystemOperationContext> context,
       const fileapi::FileSystemURL& src_url,
       const fileapi::FileSystemURL& dest_url,
       bool copy,
       const StatusCallback& callback);
   virtual void CopyInForeignFileOnTaskRunnerThread(
-      fileapi::FileSystemOperationContext* context,
+      scoped_ptr<fileapi::FileSystemOperationContext> context,
       const base::FilePath& src_file_path,
       const fileapi::FileSystemURL& dest_url,
       const StatusCallback& callback);
   virtual void DeleteDirectoryOnTaskRunnerThread(
-      fileapi::FileSystemOperationContext* context,
+      scoped_ptr<fileapi::FileSystemOperationContext> context,
       const fileapi::FileSystemURL& url,
       const StatusCallback& callback);
   virtual void CreateSnapshotFileOnTaskRunnerThread(
-      fileapi::FileSystemOperationContext* context,
+      scoped_ptr<fileapi::FileSystemOperationContext> context,
       const fileapi::FileSystemURL& url,
       const CreateSnapshotFileCallback& callback);
 
diff --git a/chrome/browser/media_galleries/fileapi/native_media_file_util_unittest.cc b/chrome/browser/media_galleries/fileapi/native_media_file_util_unittest.cc
index 6fdd7cb..71f752f 100644
--- a/chrome/browser/media_galleries/fileapi/native_media_file_util_unittest.cc
+++ b/chrome/browser/media_galleries/fileapi/native_media_file_util_unittest.cc
@@ -9,10 +9,10 @@
 #include "base/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/format_macros.h"
-#include "base/message_loop.h"
-#include "base/message_loop_proxy.h"
+#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_proxy.h"
 #include "base/strings/stringprintf.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/media_galleries/fileapi/media_file_system_mount_point_provider.h"
 #include "chrome/browser/media_galleries/fileapi/native_media_file_util.h"
 #include "content/public/test/test_browser_thread.h"
@@ -288,7 +288,7 @@
     for (size_t i = 0; i < arraysize(kFilteringTestCases); ++i) {
       // Always start with an empty destination directory.
       // Copying to a non-empty destination directory is an invalid operation.
-      ASSERT_TRUE(file_util::Delete(dest_path, true));
+      ASSERT_TRUE(base::Delete(dest_path, true));
       ASSERT_TRUE(file_util::CreateDirectory(dest_path));
 
       FileSystemURL root_url = CreateURL(FPL(""));
@@ -318,7 +318,7 @@
     if (loop_count == 1) {
       // Reset the test directory between the two loops to remove old
       // directories and create new ones that should pre-exist.
-      ASSERT_TRUE(file_util::Delete(root_path(), true));
+      ASSERT_TRUE(base::Delete(root_path(), true));
       ASSERT_TRUE(file_util::CreateDirectory(root_path()));
       PopulateDirectoryWithTestCases(root_path(),
                                      kFilteringTestCases,
@@ -387,7 +387,7 @@
     for (size_t i = 0; i < arraysize(kFilteringTestCases); ++i) {
       // Always start with an empty destination directory.
       // Moving to a non-empty destination directory is an invalid operation.
-      ASSERT_TRUE(file_util::Delete(dest_path, true));
+      ASSERT_TRUE(base::Delete(dest_path, true));
       ASSERT_TRUE(file_util::CreateDirectory(dest_path));
 
       FileSystemURL root_url = CreateURL(FPL(""));
@@ -417,7 +417,7 @@
     if (loop_count == 1) {
       // Reset the test directory between the two loops to remove old
       // directories and create new ones that should pre-exist.
-      ASSERT_TRUE(file_util::Delete(root_path(), true));
+      ASSERT_TRUE(base::Delete(root_path(), true));
       ASSERT_TRUE(file_util::CreateDirectory(root_path()));
       PopulateDirectoryWithTestCases(root_path(),
                                      kFilteringTestCases,
diff --git a/chrome/browser/media_galleries/fileapi/picasa/picasa_album_table_reader.cc b/chrome/browser/media_galleries/fileapi/picasa/picasa_album_table_reader.cc
deleted file mode 100644
index e32e390..0000000
--- a/chrome/browser/media_galleries/fileapi/picasa/picasa_album_table_reader.cc
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/media_galleries/fileapi/picasa/picasa_album_table_reader.h"
-
-#include <vector>
-
-#include "base/path_service.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/media_galleries/fileapi/picasa/pmp_column_reader.h"
-#include "chrome/browser/media_galleries/fileapi/picasa/pmp_constants.h"
-#include "chrome/browser/media_galleries/fileapi/picasa/pmp_table_reader.h"
-
-namespace picasa {
-
-namespace {
-
-// |variant_time| is specified as the number of days from Dec 30, 1899.
-base::Time TimeFromMicrosoftVariantTime(double variant_time) {
-  base::TimeDelta variant_delta = base::TimeDelta::FromMicroseconds(
-      static_cast<int64>(variant_time * base::Time::kMicrosecondsPerDay));
-
-  return base::Time::FromLocalExploded(kPicasaVariantTimeEpoch) + variant_delta;
-}
-
-}  // namespace
-
-AlbumInfo::AlbumInfo() {}
-
-AlbumInfo::AlbumInfo(const std::string& name, const base::Time& timestamp,
-                     const std::string& uid, const base::FilePath& path)
-    : name(name),
-      timestamp(timestamp),
-      uid(uid),
-      path(path) {
-}
-
-AlbumInfo::~AlbumInfo() {}
-
-PicasaAlbumTableReader::PicasaAlbumTableReader(
-    const base::FilePath& directory_path)
-    : directory_path_(directory_path),
-      initialized_(false) {}
-
-PicasaAlbumTableReader::~PicasaAlbumTableReader() {}
-
-const std::vector<AlbumInfo>& PicasaAlbumTableReader::folders() const {
-  DCHECK(initialized_);
-  return folders_;
-}
-
-const std::vector<AlbumInfo>& PicasaAlbumTableReader::albums() const {
-  DCHECK(initialized_);
-  return albums_;
-}
-
-bool PicasaAlbumTableReader::Init() {
-  if (initialized_)
-    return true;
-
-  PmpTableReader pmp_reader(kPicasaAlbumTableName, directory_path_);
-
-  const PmpColumnReader* category_column =
-      pmp_reader.AddColumn("category", PMP_TYPE_UINT32);
-  const PmpColumnReader* date_column =
-      pmp_reader.AddColumn("date", PMP_TYPE_DOUBLE64);
-  const PmpColumnReader* filename_column =
-      pmp_reader.AddColumn("filename", PMP_TYPE_STRING);
-  const PmpColumnReader* name_column =
-      pmp_reader.AddColumn("name", PMP_TYPE_STRING);
-  const PmpColumnReader* token_column =
-      pmp_reader.AddColumn("token", PMP_TYPE_STRING);
-  const PmpColumnReader* uid_column =
-      pmp_reader.AddColumn("uid", PMP_TYPE_STRING);
-
-  if (pmp_reader.Columns().size() != 6)
-    return false;
-
-  for (uint32 i = 0; i < pmp_reader.RowCount(); i++) {
-    uint32 category = kAlbumCategoryInvalid;
-    double date = 0;
-    std::string name;
-    std::string uid;
-    if (!category_column->ReadUInt32(i, &category) ||
-        !date_column->ReadDouble64(i, &date) ||
-        !name_column->ReadString(i, &name) || name.empty() ||
-        !uid_column->ReadString(i, &uid) || uid.empty()) {
-      continue;
-    }
-
-    base::Time timestamp = TimeFromMicrosoftVariantTime(date);
-
-    switch (category) {
-      case kAlbumCategoryAlbum: {
-        std::string token;
-        if (!token_column->ReadString(i, &token) || token.empty() ||
-            !StartsWithASCII(token, kAlbumTokenPrefix, false)) {
-          continue;
-        }
-
-        albums_.push_back(AlbumInfo(name, timestamp, uid, base::FilePath()));
-        break;
-      }
-      case kAlbumCategoryFolder: {
-        std::string filename;
-        if (!filename_column->ReadString(i, &filename) || filename.empty())
-          continue;
-
-        base::FilePath path =
-            base::FilePath(base::FilePath::FromUTF8Unsafe(filename));
-
-        folders_.push_back(AlbumInfo(name, timestamp, uid, path));
-        break;
-      }
-      default: {
-        break;
-      }
-    }
-  }
-
-  initialized_ = true;
-  return true;
-}
-
-}  // namespace picasa
diff --git a/chrome/browser/media_galleries/fileapi/picasa/picasa_album_table_reader.h b/chrome/browser/media_galleries/fileapi/picasa/picasa_album_table_reader.h
deleted file mode 100644
index b4ef981..0000000
--- a/chrome/browser/media_galleries/fileapi/picasa/picasa_album_table_reader.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_PICASA_PICASA_ALBUM_TABLE_READER_H_
-#define CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_PICASA_PICASA_ALBUM_TABLE_READER_H_
-
-#include "base/basictypes.h"
-#include "base/files/file_path.h"
-#include "base/time.h"
-
-namespace picasa {
-
-const base::Time::Exploded kPicasaVariantTimeEpoch = {
-  1899, 12, 7, 30,  // Dec 30, 1899 (Saturday)
-  0, 0, 0, 0        // 00:00:00.000
-};
-
-const char kPicasaAlbumTableName[] = "albumdata";
-
-const uint32 kAlbumCategoryAlbum     = 0;
-const uint32 kAlbumCategoryFolder    = 2;
-const uint32 kAlbumCategoryInvalid   = 0xffff;  // Sentinel value.
-
-const char kAlbumTokenPrefix[] = "]album:";
-
-struct AlbumInfo {
-  AlbumInfo();
-  AlbumInfo(const std::string& name, const base::Time& timestamp,
-            const std::string& uid, const base::FilePath& path);
-
-  ~AlbumInfo();
-
-  std::string name;
-  base::Time timestamp;
-  std::string uid;
-  base::FilePath path;
-};
-
-class PicasaAlbumTableReader {
- public:
-  // |directory_path| is Picasa's db3 directory where the PMP table is stored.
-  explicit PicasaAlbumTableReader(const base::FilePath& directory_path);
-  virtual ~PicasaAlbumTableReader();
-
-  bool Init();
-
-  const std::vector<AlbumInfo>& albums() const;
-  const std::vector<AlbumInfo>& folders() const;
-
- private:
-  const base::FilePath directory_path_;
-
-  bool initialized_;
-
-  std::vector<AlbumInfo> albums_;
-  std::vector<AlbumInfo> folders_;
-
-  DISALLOW_COPY_AND_ASSIGN(PicasaAlbumTableReader);
-};
-
-}  // namespace picasa
-
-#endif  // CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_PICASA_PICASA_ALBUM_TABLE_READER_H_
diff --git a/chrome/browser/media_galleries/fileapi/picasa/picasa_album_table_reader_unittest.cc b/chrome/browser/media_galleries/fileapi/picasa/picasa_album_table_reader_unittest.cc
deleted file mode 100644
index b36691d..0000000
--- a/chrome/browser/media_galleries/fileapi/picasa/picasa_album_table_reader_unittest.cc
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/media_galleries/fileapi/picasa/picasa_album_table_reader.h"
-#include "chrome/browser/media_galleries/fileapi/picasa/pmp_constants.h"
-#include "chrome/browser/media_galleries/fileapi/picasa/pmp_test_helper.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-using picasa::PmpTestHelper;
-using picasa::PMP_TYPE_UINT32;
-
-TEST(PicasaAlbumTableReaderTest, FoldersAndAlbums) {
-  PmpTestHelper test_helper(picasa::kPicasaAlbumTableName);
-  ASSERT_TRUE(test_helper.Init());
-
-  int test_time_delta = 100;
-
-  std::vector<uint32> category_vector;
-  category_vector.push_back(picasa::kAlbumCategoryFolder);
-  category_vector.push_back(picasa::kAlbumCategoryInvalid);
-  category_vector.push_back(picasa::kAlbumCategoryAlbum);
-
-  std::vector<double> date_vector;
-  date_vector.push_back(0.0);
-  date_vector.push_back(0.0);
-  date_vector.push_back(0.0 + test_time_delta);
-
-  std::string test_folder_name = "Pix4dalulz";
-  std::string test_album_name = "Cats";
-
-  base::FilePath test_folder_path =
-      base::FilePath(base::FilePath::FromUTF8Unsafe("C:\\Pix4dalulz"));
-
-  // Only folders require filenames. Tests handling of different length columns.
-  std::vector<std::string> filename_vector;
-  filename_vector.push_back(test_folder_path.AsUTF8Unsafe());
-
-  std::vector<std::string> name_vector;
-  name_vector.push_back(test_folder_name);
-  name_vector.push_back("");
-  name_vector.push_back(test_album_name);
-
-  std::vector<std::string> token_vector;
-  token_vector.push_back("");
-  token_vector.push_back("");
-  token_vector.push_back(std::string(picasa::kAlbumTokenPrefix) + "uid3");
-
-  std::vector<std::string> uid_vector;
-  uid_vector.push_back("uid1");
-  uid_vector.push_back("uid2");
-  uid_vector.push_back("uid3");
-
-  ASSERT_TRUE(test_helper.WriteColumnFileFromVector(
-      "category", picasa::PMP_TYPE_UINT32, category_vector));
-  ASSERT_TRUE(test_helper.WriteColumnFileFromVector(
-      "date", picasa::PMP_TYPE_DOUBLE64, date_vector));
-  ASSERT_TRUE(test_helper.WriteColumnFileFromVector(
-      "filename", picasa::PMP_TYPE_STRING, filename_vector));
-  ASSERT_TRUE(test_helper.WriteColumnFileFromVector(
-      "name", picasa::PMP_TYPE_STRING, name_vector));
-  ASSERT_TRUE(test_helper.WriteColumnFileFromVector(
-      "token", picasa::PMP_TYPE_STRING, token_vector));
-  ASSERT_TRUE(test_helper.WriteColumnFileFromVector(
-      "uid", picasa::PMP_TYPE_STRING, uid_vector));
-
-  picasa::PicasaAlbumTableReader reader(test_helper.GetTempDirPath());
-
-  ASSERT_TRUE(reader.Init());
-
-  const std::vector<picasa::AlbumInfo>& albums = reader.albums();
-  const std::vector<picasa::AlbumInfo>& folders = reader.folders();
-
-  ASSERT_EQ(1u, albums.size());
-  ASSERT_EQ(1u, folders.size());
-
-  EXPECT_EQ(test_album_name, albums[0].name);
-  EXPECT_EQ(test_folder_name, folders[0].name);
-
-  EXPECT_EQ(test_folder_path, folders[0].path);
-
-  base::TimeDelta time_delta = albums[0].timestamp - folders[0].timestamp;
-
-  EXPECT_EQ(test_time_delta, time_delta.InDays());
-}
-
-}  // namespace
diff --git a/chrome/browser/media_galleries/fileapi/picasa/picasa_data_provider.cc b/chrome/browser/media_galleries/fileapi/picasa/picasa_data_provider.cc
index cdeec76..3cd4f8e 100644
--- a/chrome/browser/media_galleries/fileapi/picasa/picasa_data_provider.cc
+++ b/chrome/browser/media_galleries/fileapi/picasa/picasa_data_provider.cc
@@ -9,7 +9,7 @@
 #include "base/basictypes.h"
 #include "base/callback.h"
 #include "base/strings/stringprintf.h"
-#include "chrome/browser/media_galleries/fileapi/picasa/picasa_album_table_reader.h"
+#include "chrome/common/media_galleries/picasa_types.h"
 #include "webkit/browser/fileapi/file_system_operation_context.h"
 #include "webkit/browser/fileapi/file_system_url.h"
 
@@ -89,13 +89,20 @@
 }
 
 bool PicasaDataProvider::ReadData() {
-  PicasaAlbumTableReader album_table_reader(database_path_);
-
-  if (!album_table_reader.Init())
-    return false;
-
-  InitializeWith(album_table_reader.albums(),
-                 album_table_reader.folders());
+  // TODO(tommycli): Disabled until utility process host client implemented.
+  // PicasaAlbumTableFiles album_table_files(database_path_);
+  // PicasaAlbumTableReader album_table_reader((album_table_files));
+  //
+  // bool read_success = album_table_reader.Init();
+  //
+  // ClosePicasaAlbumTableFiles(&album_table_files);
+  //
+  // if (read_success) {
+  //   InitializeWith(album_table_reader.albums(),
+  //                  album_table_reader.folders());
+  // }
+  //
+  //  return read_success;
 
   return true;
 }
diff --git a/chrome/browser/media_galleries/fileapi/picasa/picasa_data_provider.h b/chrome/browser/media_galleries/fileapi/picasa/picasa_data_provider.h
index 20feb91..40a9bd1 100644
--- a/chrome/browser/media_galleries/fileapi/picasa/picasa_data_provider.h
+++ b/chrome/browser/media_galleries/fileapi/picasa/picasa_data_provider.h
@@ -12,7 +12,7 @@
 #include "base/callback_forward.h"
 #include "base/files/file_path.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
 
 namespace picasa {
 
diff --git a/chrome/browser/media_galleries/fileapi/picasa/picasa_file_util.cc b/chrome/browser/media_galleries/fileapi/picasa/picasa_file_util.cc
index b779535..15ce254 100644
--- a/chrome/browser/media_galleries/fileapi/picasa/picasa_file_util.cc
+++ b/chrome/browser/media_galleries/fileapi/picasa/picasa_file_util.cc
@@ -4,15 +4,19 @@
 
 #include "chrome/browser/media_galleries/fileapi/picasa/picasa_file_util.h"
 
+#include <string>
+#include <vector>
+
 #include "base/basictypes.h"
+#include "base/bind_helpers.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/media_galleries/fileapi/media_file_system_mount_point_provider.h"
-#include "chrome/browser/media_galleries/fileapi/picasa/picasa_album_table_reader.h"
 #include "chrome/browser/media_galleries/fileapi/picasa/picasa_data_provider.h"
 #include "chrome/browser/media_galleries/imported_media_gallery_registry.h"
+#include "chrome/common/media_galleries/picasa_types.h"
 #include "webkit/browser/fileapi/file_system_operation_context.h"
 #include "webkit/browser/fileapi/file_system_url.h"
 #include "webkit/common/fileapi/file_system_util.h"
@@ -56,21 +60,23 @@
 PicasaFileUtil::~PicasaFileUtil() {}
 
 void PicasaFileUtil::GetFileInfoOnTaskRunnerThread(
-    fileapi::FileSystemOperationContext* context,
+    scoped_ptr<fileapi::FileSystemOperationContext> context,
     const fileapi::FileSystemURL& url,
     const GetFileInfoCallback& callback) {
   GetDataProvider()->RefreshData(
       base::Bind(&PicasaFileUtil::GetFileInfoWithFreshDataProvider,
-                 weak_factory_.GetWeakPtr(), context, url, callback));
+                 weak_factory_.GetWeakPtr(), base::Passed(&context), url,
+                 callback));
 }
 
 void PicasaFileUtil::ReadDirectoryOnTaskRunnerThread(
-    fileapi::FileSystemOperationContext* context,
+    scoped_ptr<fileapi::FileSystemOperationContext> context,
     const fileapi::FileSystemURL& url,
     const ReadDirectoryCallback& callback) {
   GetDataProvider()->RefreshData(
       base::Bind(&PicasaFileUtil::ReadDirectoryWithFreshDataProvider,
-                 weak_factory_.GetWeakPtr(), context, url, callback));
+                 weak_factory_.GetWeakPtr(), base::Passed(&context), url,
+                 callback));
 }
 
 base::PlatformFileError PicasaFileUtil::GetFileInfoSync(
@@ -273,17 +279,19 @@
 }
 
 void PicasaFileUtil::GetFileInfoWithFreshDataProvider(
-    fileapi::FileSystemOperationContext* context,
+    scoped_ptr<fileapi::FileSystemOperationContext> context,
     const fileapi::FileSystemURL& url,
     const GetFileInfoCallback& callback) {
-  NativeMediaFileUtil::GetFileInfoOnTaskRunnerThread(context, url, callback);
+  NativeMediaFileUtil::GetFileInfoOnTaskRunnerThread(context.Pass(), url,
+                                                     callback);
 }
 
 void PicasaFileUtil::ReadDirectoryWithFreshDataProvider(
-    fileapi::FileSystemOperationContext* context,
+    scoped_ptr<fileapi::FileSystemOperationContext> context,
     const fileapi::FileSystemURL& url,
     const ReadDirectoryCallback& callback) {
-  NativeMediaFileUtil::ReadDirectoryOnTaskRunnerThread(context, url, callback);
+  NativeMediaFileUtil::ReadDirectoryOnTaskRunnerThread(context.Pass(), url,
+                                                       callback);
 }
 
 PicasaDataProvider* PicasaFileUtil::GetDataProvider() {
diff --git a/chrome/browser/media_galleries/fileapi/picasa/picasa_file_util.h b/chrome/browser/media_galleries/fileapi/picasa/picasa_file_util.h
index 1b14f16..f17cb66 100644
--- a/chrome/browser/media_galleries/fileapi/picasa/picasa_file_util.h
+++ b/chrome/browser/media_galleries/fileapi/picasa/picasa_file_util.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_PICASA_PICASA_FILE_UTIL_H_
 #define CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_PICASA_PICASA_FILE_UTIL_H_
 
+#include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/media_galleries/fileapi/native_media_file_util.h"
 
@@ -23,11 +24,11 @@
  protected:
   // NativeMediaFileUtil overrides.
   virtual void GetFileInfoOnTaskRunnerThread(
-      fileapi::FileSystemOperationContext* context,
+      scoped_ptr<fileapi::FileSystemOperationContext> context,
       const fileapi::FileSystemURL& url,
       const GetFileInfoCallback& callback) OVERRIDE;
   virtual void ReadDirectoryOnTaskRunnerThread(
-      fileapi::FileSystemOperationContext* context,
+      scoped_ptr<fileapi::FileSystemOperationContext> context,
       const fileapi::FileSystemURL& url,
       const ReadDirectoryCallback& callback) OVERRIDE;
   virtual base::PlatformFileError GetFileInfoSync(
@@ -46,11 +47,11 @@
 
  private:
   void GetFileInfoWithFreshDataProvider(
-      fileapi::FileSystemOperationContext* context,
+      scoped_ptr<fileapi::FileSystemOperationContext> context,
       const fileapi::FileSystemURL& url,
       const GetFileInfoCallback& callback);
   void ReadDirectoryWithFreshDataProvider(
-      fileapi::FileSystemOperationContext* context,
+      scoped_ptr<fileapi::FileSystemOperationContext> context,
       const fileapi::FileSystemURL& url,
       const ReadDirectoryCallback& callback);
 
diff --git a/chrome/browser/media_galleries/fileapi/picasa/picasa_file_util_unittest.cc b/chrome/browser/media_galleries/fileapi/picasa/picasa_file_util_unittest.cc
index fd7a29b..10ebb3a 100644
--- a/chrome/browser/media_galleries/fileapi/picasa/picasa_file_util_unittest.cc
+++ b/chrome/browser/media_galleries/fileapi/picasa/picasa_file_util_unittest.cc
@@ -4,22 +4,22 @@
 
 #include <set>
 #include <string>
+#include <vector>
 
 #include "base/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/memory/scoped_vector.h"
-#include "base/message_loop.h"
-#include "base/message_loop_proxy.h"
+#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_proxy.h"
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/media_galleries/fileapi/media_file_system_mount_point_provider.h"
 #include "chrome/browser/media_galleries/fileapi/media_path_filter.h"
-#include "chrome/browser/media_galleries/fileapi/picasa/picasa_album_table_reader.h"
 #include "chrome/browser/media_galleries/fileapi/picasa/picasa_data_provider.h"
 #include "chrome/browser/media_galleries/fileapi/picasa/picasa_file_util.h"
-#include "chrome/browser/media_galleries/fileapi/picasa/pmp_constants.h"
-#include "chrome/browser/media_galleries/fileapi/picasa/pmp_test_helper.h"
+#include "chrome/common/media_galleries/picasa_types.h"
+#include "chrome/common/media_galleries/pmp_constants.h"
 #include "content/public/test/test_browser_thread.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "webkit/browser/fileapi/async_file_util_adapter.h"
@@ -87,7 +87,7 @@
   double GetVariantTimestamp() const {
     DCHECK(!folder_dir_.path().empty());
     base::Time variant_epoch = base::Time::FromLocalExploded(
-        picasa::kPicasaVariantTimeEpoch);
+        picasa::kPmpVariantTimeEpoch);
 
     int64 microseconds_since_epoch =
         (folder_info_.timestamp - variant_epoch).InMicroseconds();
@@ -121,17 +121,26 @@
 
 class TestPicasaDataProvider : public PicasaDataProvider {
  public:
-  TestPicasaDataProvider(const std::vector<AlbumInfo>& albums,
-                         const std::vector<AlbumInfo>& folders)
-      : PicasaDataProvider(base::FilePath(FILE_PATH_LITERAL("Fake"))) {
+  TestPicasaDataProvider()
+      : PicasaDataProvider(base::FilePath(FILE_PATH_LITERAL("Fake"))),
+        initialized_(false) {
+  }
+
+  virtual ~TestPicasaDataProvider() {}
+
+  void Init(const std::vector<AlbumInfo>& albums,
+            const std::vector<AlbumInfo>& folders) {
     InitializeWith(albums, folders);
+    initialized_ = true;
   }
 
  private:
   virtual bool ReadData() OVERRIDE {
+    DCHECK(initialized_);
     return true;
   }
-  virtual ~TestPicasaDataProvider() {}
+
+  bool initialized_;
 };
 
 class TestPicasaFileUtil : public PicasaFileUtil {
@@ -142,10 +151,10 @@
   virtual ~TestPicasaFileUtil() {}
  private:
   virtual PicasaDataProvider* GetDataProvider() OVERRIDE {
-    return data_provider_.get();
+    return data_provider_;
   }
 
-  scoped_ptr<PicasaDataProvider> data_provider_;
+  PicasaDataProvider* data_provider_;
 };
 
 class TestMediaFileSystemMountPointProvider
@@ -218,19 +227,17 @@
   virtual ~PicasaFileUtilTest() {}
 
   virtual void SetUp() OVERRIDE {
-    test_helper_.reset(new PmpTestHelper(kPicasaAlbumTableName));
-    ASSERT_TRUE(test_helper_->Init());
-
     ASSERT_TRUE(profile_dir_.CreateUniqueTempDir());
 
     scoped_refptr<quota::SpecialStoragePolicy> storage_policy =
         new quota::MockSpecialStoragePolicy();
 
+    picasa_data_provider_.reset(new TestPicasaDataProvider());
+
     ScopedVector<fileapi::FileSystemMountPointProvider> additional_providers;
     additional_providers.push_back(new TestMediaFileSystemMountPointProvider(
         profile_dir_.path(),
-        new TestPicasaFileUtil(
-            new PicasaDataProvider(test_helper_->GetTempDirPath()))));
+        new TestPicasaFileUtil(picasa_data_provider_.get())));
 
     file_system_context_ = new fileapi::FileSystemContext(
         fileapi::FileSystemTaskRunners::CreateMockTaskRunners(),
@@ -245,38 +252,14 @@
  protected:
   // |test_folders| must be in alphabetical order for easy verification
   void SetupFolders(ScopedVector<TestFolder>* test_folders) {
-    // Build up pmp files.
-    std::vector<uint32> category_column;
-    std::vector<double> date_column;
-    std::vector<std::string> filename_column;
-    std::vector<std::string> name_column;
-    std::vector<std::string> uid_column;
-    std::vector<std::string> token_column;
-
+    std::vector<AlbumInfo> folders;
     for (ScopedVector<TestFolder>::iterator it = test_folders->begin();
         it != test_folders->end(); ++it) {
       TestFolder* test_folder = *it;
       ASSERT_TRUE(test_folder->Init());
-      category_column.push_back(picasa::kAlbumCategoryFolder);
-      date_column.push_back(test_folder->GetVariantTimestamp());
-      filename_column.push_back(test_folder->folder_info().path.AsUTF8Unsafe());
-      name_column.push_back(test_folder->folder_info().name);
-      uid_column.push_back(test_folder->folder_info().uid);
-      token_column.push_back("]album:" + test_folder->folder_info().uid);
+      folders.push_back(test_folder->folder_info());
     }
-
-    ASSERT_TRUE(test_helper_->WriteColumnFileFromVector(
-        "category", picasa::PMP_TYPE_UINT32, category_column));
-    ASSERT_TRUE(test_helper_->WriteColumnFileFromVector(
-        "date", picasa::PMP_TYPE_DOUBLE64, date_column));
-    ASSERT_TRUE(test_helper_->WriteColumnFileFromVector(
-        "filename", picasa::PMP_TYPE_STRING, filename_column));
-    ASSERT_TRUE(test_helper_->WriteColumnFileFromVector(
-        "name", picasa::PMP_TYPE_STRING, name_column));
-    ASSERT_TRUE(test_helper_->WriteColumnFileFromVector(
-        "uid", picasa::PMP_TYPE_STRING, uid_column));
-    ASSERT_TRUE(test_helper_->WriteColumnFileFromVector(
-        "token", picasa::PMP_TYPE_STRING, token_column));
+    picasa_data_provider_->Init(std::vector<AlbumInfo>(), folders);
   }
 
   void VerifyFolderDirectoryList(const ScopedVector<TestFolder>& test_folders) {
@@ -363,7 +346,7 @@
   base::ScopedTempDir profile_dir_;
 
   scoped_refptr<fileapi::FileSystemContext> file_system_context_;
-  scoped_ptr<PmpTestHelper> test_helper_;
+  scoped_ptr<TestPicasaDataProvider> picasa_data_provider_;
 
   DISALLOW_COPY_AND_ASSIGN(PicasaFileUtilTest);
 };
@@ -419,8 +402,10 @@
       chrome::MediaFileSystemMountPointProvider::kMediaPathFilterKey,
       media_path_filter.get());
 
-  TestPicasaFileUtil test_file_util(
-      new TestPicasaDataProvider(std::vector<AlbumInfo>(), folders));
+  scoped_ptr<TestPicasaDataProvider> test_picasa_data_provider(
+      new TestPicasaDataProvider());
+  test_picasa_data_provider->Init(std::vector<AlbumInfo>(), folders);
+  TestPicasaFileUtil test_file_util(test_picasa_data_provider.get());
 
   fileapi::AsyncFileUtil::EntryList file_list;
   ASSERT_EQ(base::PLATFORM_FILE_OK,
@@ -438,6 +423,9 @@
 }
 
 TEST_F(PicasaFileUtilTest, RootFolders) {
+  ScopedVector<TestFolder> empty_folders_list;
+  SetupFolders(&empty_folders_list);
+
   FileSystemOperation::FileEntryList contents;
   FileSystemURL url = CreateURL("");
   bool completed = false;
diff --git a/chrome/browser/media_galleries/fileapi/picasa/pmp_column_reader.cc b/chrome/browser/media_galleries/fileapi/picasa/pmp_column_reader.cc
deleted file mode 100644
index cf799d4..0000000
--- a/chrome/browser/media_galleries/fileapi/picasa/pmp_column_reader.cc
+++ /dev/null
@@ -1,197 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/media_galleries/fileapi/picasa/pmp_column_reader.h"
-
-#include <cstring>
-
-#include "base/file_util.h"
-#include "base/files/file_path.h"
-#include "base/logging.h"
-#include "base/threading/thread_restrictions.h"
-
-namespace picasa {
-
-namespace {
-
-const int64 kPmpMaxFilesize = 50*1024*1024;  // Arbitrary maximum of 50 MB.
-
-}  // namespace
-
-PmpColumnReader::PmpColumnReader()
-    : length_(0),
-      field_type_(PMP_TYPE_INVALID),
-      rows_(0) {}
-
-PmpColumnReader::~PmpColumnReader() {}
-
-bool PmpColumnReader::Init(const base::FilePath& filepath,
-                           const PmpFieldType expected_type,
-                           uint32* rows_read) {
-  DCHECK(!data_.get());
-  base::ThreadRestrictions::AssertIOAllowed();
-
-  if (!file_util::GetFileSize(filepath, &length_))
-    return false;
-
-  if (length_ < kPmpHeaderSize || length_ > kPmpMaxFilesize)
-    return false;
-
-  data_.reset(new uint8[length_]);
-
-  char* data_begin = reinterpret_cast<char*>(data_.get());
-
-  DCHECK(length_ < kint32max);  // ReadFile expects an int.
-
-  bool success = file_util::ReadFile(filepath, data_begin, length_) &&
-                 ParseData(expected_type, rows_read);
-
-  if (!success)
-    rows_ = 0;  // If any of the reading or parsing fails, prevent Read* calls.
-
-  return success;
-}
-
-bool PmpColumnReader::ReadString(const uint32 row, std::string* result) const {
-  DCHECK(data_.get() != NULL);
-
-  if (field_type_ != PMP_TYPE_STRING || row >= rows_)
-    return false;
-
-  DCHECK_LT(row, strings_.size());
-  *result = strings_[row];
-  return true;
-}
-
-bool PmpColumnReader::ReadUInt32(const uint32 row, uint32* result) const {
-  DCHECK(data_.get() != NULL);
-
-  if (field_type_ != PMP_TYPE_UINT32 || row >= rows_)
-    return false;
-
-  *result = reinterpret_cast<uint32*>(data_.get() + kPmpHeaderSize)[row];
-  return true;
-}
-
-bool PmpColumnReader::ReadDouble64(const uint32 row, double* result) const {
-  DCHECK(data_.get() != NULL);
-
-  if (field_type_ != PMP_TYPE_DOUBLE64 || row >= rows_)
-    return false;
-
-  *result = reinterpret_cast<double*>(data_.get() + kPmpHeaderSize)[row];
-  return true;
-}
-
-bool PmpColumnReader::ReadUInt8(const uint32 row, uint8* result) const {
-  DCHECK(data_.get() != NULL);
-
-  if (field_type_ != PMP_TYPE_UINT8 || row >= rows_)
-    return false;
-
-  *result = reinterpret_cast<uint8*>(data_.get() + kPmpHeaderSize)[row];
-  return true;
-}
-
-bool PmpColumnReader::ReadUInt64(const uint32 row, uint64* result) const {
-  DCHECK(data_.get() != NULL);
-
-  if (field_type_ != PMP_TYPE_UINT64 || row >= rows_)
-    return false;
-
-  *result = reinterpret_cast<uint64*>(data_.get() + kPmpHeaderSize)[row];
-  return true;
-}
-
-bool PmpColumnReader::ParseData(const PmpFieldType expected_type,
-                                uint32* rows_read) {
-  DCHECK(data_.get() != NULL);
-  DCHECK_GE(length_, kPmpHeaderSize);
-
-  // Check all magic bytes.
-  if (memcmp(&kPmpMagic1, &data_[kPmpMagic1Offset], sizeof(kPmpMagic1)) != 0 ||
-      memcmp(&kPmpMagic2, &data_[kPmpMagic2Offset], sizeof(kPmpMagic2)) != 0 ||
-      memcmp(&kPmpMagic3, &data_[kPmpMagic3Offset], sizeof(kPmpMagic3)) != 0 ||
-      memcmp(&kPmpMagic4, &data_[kPmpMagic4Offset], sizeof(kPmpMagic4)) != 0) {
-    return false;
-  }
-
-  uint16 field_type_data =
-      *(reinterpret_cast<uint16*>(&data_[kPmpFieldType1Offset]));
-
-  // Verify if field type matches second declaration
-  if (field_type_data !=
-      *(reinterpret_cast<uint16*>(&data_[kPmpFieldType2Offset]))) {
-    return false;
-  }
-
-  field_type_ = static_cast<PmpFieldType>(field_type_data);
-
-  if (field_type_ != expected_type)
-    return false;
-
-  rows_ = *(reinterpret_cast<uint32*>(&data_[kPmpRowCountOffset]));
-
-  // Sanity check against malicious row field.
-  if (rows_ > (kPmpMaxFilesize - kPmpHeaderSize))
-    return false;
-
-  DCHECK_GE(length_, kPmpHeaderSize);
-  int64 body_length = length_ - kPmpHeaderSize;
-  int64 expected_body_length = 0;
-  switch (field_type_) {
-    case PMP_TYPE_STRING:
-      expected_body_length = IndexStrings();
-      break;
-    case PMP_TYPE_UINT32:
-      expected_body_length = static_cast<int64>(rows_) * sizeof(uint32);
-      break;
-    case PMP_TYPE_DOUBLE64:
-      expected_body_length = static_cast<int64>(rows_) * sizeof(double);
-      break;
-    case PMP_TYPE_UINT8:
-      expected_body_length = static_cast<int64>(rows_) * sizeof(uint8);
-      break;
-    case PMP_TYPE_UINT64:
-      expected_body_length = static_cast<int64>(rows_) * sizeof(uint64);
-      break;
-    default:
-      return false;
-      break;
-  }
-
-  if (body_length == expected_body_length && rows_read)
-    *rows_read = rows_;
-  return body_length == expected_body_length;
-}
-
-int64 PmpColumnReader::IndexStrings() {
-  DCHECK(data_.get() != NULL);
-  DCHECK_GE(length_, kPmpHeaderSize);
-
-  strings_.reserve(rows_);
-
-  int64 bytes_parsed = kPmpHeaderSize;
-  const uint8* data_cursor = data_.get() + kPmpHeaderSize;
-
-  while (strings_.size() < rows_) {
-    const uint8* string_end = static_cast<const uint8*>(
-        memchr(data_cursor, '\0', length_ - bytes_parsed));
-
-    // Fail if cannot find null termination. String runs on past file end.
-    if (string_end == NULL)
-      return -1;
-
-    // Length of string. (+1 to include the termination character).
-    ptrdiff_t length_in_bytes = string_end - data_cursor + 1;
-
-    strings_.push_back(reinterpret_cast<const char*>(data_cursor));
-    data_cursor += length_in_bytes;
-    bytes_parsed += length_in_bytes;
-  }
-
-  return bytes_parsed - kPmpHeaderSize;
-}
-
-}  // namespace picasa
diff --git a/chrome/browser/media_galleries/fileapi/picasa/pmp_column_reader.h b/chrome/browser/media_galleries/fileapi/picasa/pmp_column_reader.h
deleted file mode 100644
index 19ec1d5..0000000
--- a/chrome/browser/media_galleries/fileapi/picasa/pmp_column_reader.h
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_PICASA_PMP_COLUMN_READER_H_
-#define CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_PICASA_PMP_COLUMN_READER_H_
-
-#include <string>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "chrome/browser/media_galleries/fileapi/picasa/pmp_constants.h"
-
-namespace base {
-class FilePath;
-}
-
-namespace picasa {
-
-// Reads a single PMP column from a file.
-class PmpColumnReader {
- public:
-  PmpColumnReader();
-  virtual ~PmpColumnReader();
-
-  // Returns true if read successfully.
-  // |rows_read| is undefined if returns false.
-  bool Init(const base::FilePath& filepath, const PmpFieldType expected_type,
-            uint32* rows_read);
-
-  // These functions read the value of that |row| into |result|.
-  // Functions return false if the column is of the wrong type or the row
-  // is out of range.
-  bool ReadString(const uint32 row, std::string* result) const;
-  bool ReadUInt32(const uint32 row, uint32* result) const;
-  bool ReadDouble64(const uint32 row, double* result) const;
-  bool ReadUInt8(const uint32 row, uint8* result) const;
-  bool ReadUInt64(const uint32 row, uint64* result) const;
-
- private:
-  bool ParseData(const PmpFieldType expected_type, uint32* rows_read);
-  // Returns the number of bytes parsed in the body, or, -1 on failure.
-  int64 IndexStrings();
-
-  // Source data
-  scoped_ptr<uint8[]> data_;
-  int64 length_;
-
-  // Header data
-  PmpFieldType field_type_;
-  uint32 rows_;
-
-  // Index of string start locations if fields are strings. Empty otherwise.
-  std::vector<const char*> strings_;
-
-  DISALLOW_COPY_AND_ASSIGN(PmpColumnReader);
-};
-
-}  // namespace picasa
-
-#endif  // CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_PICASA_PMP_COLUMN_READER_H_
diff --git a/chrome/browser/media_galleries/fileapi/picasa/pmp_column_reader_unittest.cc b/chrome/browser/media_galleries/fileapi/picasa/pmp_column_reader_unittest.cc
deleted file mode 100644
index 1873d16..0000000
--- a/chrome/browser/media_galleries/fileapi/picasa/pmp_column_reader_unittest.cc
+++ /dev/null
@@ -1,202 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <algorithm>
-#include <vector>
-
-#include "chrome/browser/media_galleries/fileapi/picasa/pmp_column_reader.h"
-#include "chrome/browser/media_galleries/fileapi/picasa/pmp_constants.h"
-#include "chrome/browser/media_galleries/fileapi/picasa/pmp_test_helper.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-using picasa::PmpColumnReader;
-using picasa::PmpTestHelper;
-
-// Overridden version of Read method to make test code templatable.
-bool DoRead(const PmpColumnReader* reader, uint32 row, std::string* target) {
-  return reader->ReadString(row, target);
-}
-
-bool DoRead(const PmpColumnReader* reader, uint32 row, uint32* target) {
-  return reader->ReadUInt32(row, target);
-}
-
-bool DoRead(const PmpColumnReader* reader, uint32 row, double* target) {
-  return reader->ReadDouble64(row, target);
-}
-
-bool DoRead(const PmpColumnReader* reader, uint32 row, uint8* target) {
-  return reader->ReadUInt8(row, target);
-}
-
-bool DoRead(const PmpColumnReader* reader, uint32 row, uint64* target) {
-  return reader->ReadUInt64(row, target);
-}
-
-// TestValid
-template<class T>
-void TestValid(const picasa::PmpFieldType field_type,
-               const std::vector<T>& elems) {
-  PmpTestHelper test_helper("test");
-  ASSERT_TRUE(test_helper.Init());
-
-  PmpColumnReader reader;
-
-  uint32 rows_read = 0xFF;
-
-  std::vector<uint8> data =
-      PmpTestHelper::MakeHeaderAndBody(field_type, elems.size(), elems);
-  ASSERT_TRUE(test_helper.InitColumnReaderFromBytes(
-      &reader, data, field_type, &rows_read));
-  EXPECT_EQ(elems.size(), rows_read);
-
-  for (uint32 i = 0; i < elems.size() && i < rows_read; i++) {
-    T target;
-    EXPECT_TRUE(DoRead(&reader, i, &target));
-    EXPECT_EQ(elems[i], target);
-  }
-}
-
-template<class T>
-void TestMalformed(const picasa::PmpFieldType field_type,
-                   const std::vector<T>& elems) {
-  PmpTestHelper test_helper("test");
-  ASSERT_TRUE(test_helper.Init());
-
-  PmpColumnReader reader_too_few_declared_rows;
-  std::vector<uint8> data_too_few_declared_rows =
-      PmpTestHelper::MakeHeaderAndBody(field_type, elems.size()-1, elems);
-  EXPECT_FALSE(test_helper.InitColumnReaderFromBytes(
-      &reader_too_few_declared_rows,
-      data_too_few_declared_rows,
-      field_type,
-      NULL));
-
-  PmpColumnReader reader_too_many_declared_rows;
-  std::vector<uint8> data_too_many_declared_rows =
-      PmpTestHelper::MakeHeaderAndBody(field_type, elems.size()+1, elems);
-  EXPECT_FALSE(test_helper.InitColumnReaderFromBytes(
-      &reader_too_many_declared_rows,
-      data_too_many_declared_rows,
-      field_type,
-      NULL));
-
-  PmpColumnReader reader_truncated;
-  std::vector<uint8> data_truncated =
-      PmpTestHelper::MakeHeaderAndBody(field_type, elems.size(), elems);
-  data_truncated.resize(data_truncated.size()-10);
-  EXPECT_FALSE(test_helper.InitColumnReaderFromBytes(
-      &reader_truncated, data_truncated, field_type, NULL));
-
-  PmpColumnReader reader_padded;
-  std::vector<uint8> data_padded =
-      PmpTestHelper::MakeHeaderAndBody(field_type, elems.size(), elems);
-  data_padded.resize(data_padded.size()+10);
-  EXPECT_FALSE(test_helper.InitColumnReaderFromBytes(
-      &reader_padded, data_padded, field_type, NULL));
-}
-
-template<class T>
-void TestPrimitive(const picasa::PmpFieldType field_type) {
-  // Make an ascending vector of the primitive.
-  uint32 n = 100;
-  std::vector<T> data(n, 0);
-  for (uint32 i = 0; i < n; i++) {
-    data[i] = i*3;
-  }
-
-  TestValid<T>(field_type, data);
-  TestMalformed<T>(field_type, data);
-}
-
-
-TEST(PmpColumnReaderTest, HeaderParsingAndValidation) {
-  PmpTestHelper test_helper("test");
-  ASSERT_TRUE(test_helper.Init());
-
-  PmpColumnReader reader_good_header;
-  uint32 rows_read = 0xFF;
-  std::vector<uint8> good_header =
-      PmpTestHelper::MakeHeader(picasa::PMP_TYPE_STRING, 0);
-  EXPECT_TRUE(test_helper.InitColumnReaderFromBytes(
-      &reader_good_header,
-      good_header,
-      picasa::PMP_TYPE_STRING,
-      &rows_read));
-  EXPECT_EQ(0U, rows_read) << "Read non-zero rows from header-only data.";
-
-  PmpColumnReader reader_bad_magic_bytes;
-  std::vector<uint8> bad_magic_bytes =
-      PmpTestHelper::MakeHeader(picasa::PMP_TYPE_STRING, 0);
-  bad_magic_bytes[0] = 0xff;
-  EXPECT_FALSE(test_helper.InitColumnReaderFromBytes(
-      &reader_bad_magic_bytes,
-      bad_magic_bytes,
-      picasa::PMP_TYPE_STRING,
-      NULL));
-
-  PmpColumnReader reader_inconsistent_types;
-  std::vector<uint8> inconsistent_type =
-      PmpTestHelper::MakeHeader(picasa::PMP_TYPE_STRING, 0);
-  inconsistent_type[picasa::kPmpFieldType1Offset] = 0xff;
-  EXPECT_FALSE(test_helper.InitColumnReaderFromBytes(
-      &reader_inconsistent_types,
-      inconsistent_type,
-      picasa::PMP_TYPE_STRING,
-      NULL));
-
-  PmpColumnReader reader_invalid_type;
-  std::vector<uint8> invalid_type =
-      PmpTestHelper::MakeHeader(picasa::PMP_TYPE_STRING, 0);
-  invalid_type[picasa::kPmpFieldType1Offset] = 0xff;
-  invalid_type[picasa::kPmpFieldType2Offset] = 0xff;
-  EXPECT_FALSE(test_helper.InitColumnReaderFromBytes(
-      &reader_invalid_type,
-      invalid_type,
-      picasa::PMP_TYPE_STRING,
-      NULL));
-
-  PmpColumnReader reader_incomplete_header;
-  std::vector<uint8> incomplete_header =
-      PmpTestHelper::MakeHeader(picasa::PMP_TYPE_STRING, 0);
-  incomplete_header.resize(10);
-  EXPECT_FALSE(test_helper.InitColumnReaderFromBytes(
-      &reader_incomplete_header,
-      incomplete_header,
-      picasa::PMP_TYPE_STRING,
-      NULL));
-}
-
-TEST(PmpColumnReaderTest, StringParsing) {
-  std::vector<std::string> empty_strings(100, "");
-
-  // Test empty strings read okay.
-  TestValid(picasa::PMP_TYPE_STRING, empty_strings);
-
-  std::vector<std::string> mixed_strings;
-  mixed_strings.push_back("");
-  mixed_strings.push_back("Hello");
-  mixed_strings.push_back("World");
-  mixed_strings.push_back("");
-  mixed_strings.push_back("123123");
-  mixed_strings.push_back("Q");
-  mixed_strings.push_back("");
-
-  // Test that a mixed set of strings read correctly.
-  TestValid(picasa::PMP_TYPE_STRING, mixed_strings);
-
-  // Test with the data messed up in a variety of ways.
-  TestMalformed(picasa::PMP_TYPE_STRING, mixed_strings);
-}
-
-TEST(PmpColumnReaderTest, PrimitiveParsing) {
-  TestPrimitive<uint32>(picasa::PMP_TYPE_UINT32);
-  TestPrimitive<double>(picasa::PMP_TYPE_DOUBLE64);
-  TestPrimitive<uint8>(picasa::PMP_TYPE_UINT8);
-  TestPrimitive<uint64>(picasa::PMP_TYPE_UINT64);
-}
-
-}  // namespace
diff --git a/chrome/browser/media_galleries/fileapi/picasa/pmp_constants.h b/chrome/browser/media_galleries/fileapi/picasa/pmp_constants.h
deleted file mode 100644
index 49ea36c..0000000
--- a/chrome/browser/media_galleries/fileapi/picasa/pmp_constants.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_PICASA_PMP_CONSTANTS_H_
-#define CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_PICASA_PMP_CONSTANTS_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-
-namespace picasa {
-
-// PMP file format.
-// Info derived from: http://sbktech.blogspot.com/2011/12/picasa-pmp-format.html
-
-const char* const kPmpExtension = "pmp";
-
-const int64 kPmpHeaderSize = 20;
-
-const int kPmpMagic1Offset = 0;
-const int kPmpMagic2Offset = 6;
-const int kPmpMagic3Offset = 8;
-const int kPmpMagic4Offset = 14;
-
-const uint32 kPmpMagic1 = 0x3fcccccd;
-const uint16 kPmpMagic2 = 0x1332;
-const uint32 kPmpMagic3 = 0x00000002;
-const uint16 kPmpMagic4 = 0x1332;
-
-const int kPmpFieldType1Offset = 4;
-const int kPmpFieldType2Offset = 12;
-const int kPmpRowCountOffset   = 16;
-
-enum PmpFieldType {
-  PMP_TYPE_STRING   = 0x00,
-  PMP_TYPE_UINT32   = 0x01,
-  PMP_TYPE_DOUBLE64 = 0x02,
-  PMP_TYPE_UINT8    = 0x03,
-  PMP_TYPE_UINT64   = 0x04,
-  PMP_TYPE_INVALID  = 0xff
-};
-
-}  // namespace picasa
-
-#endif  // CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_PICASA_PMP_CONSTANTS_H_
diff --git a/chrome/browser/media_galleries/fileapi/picasa/pmp_table_reader.cc b/chrome/browser/media_galleries/fileapi/picasa/pmp_table_reader.cc
deleted file mode 100644
index cf0b4fd..0000000
--- a/chrome/browser/media_galleries/fileapi/picasa/pmp_table_reader.cc
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/media_galleries/fileapi/picasa/pmp_table_reader.h"
-
-#include <algorithm>
-
-#include "base/file_util.h"
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/threading/thread_restrictions.h"
-#include "chrome/browser/media_galleries/fileapi/picasa/pmp_column_reader.h"
-
-namespace picasa {
-
-namespace {
-
-COMPILE_ASSERT(sizeof(double) == 8, double_must_be_8_bytes_long);
-
-}  // namespace
-
-PmpTableReader::PmpTableReader(const std::string& table_name,
-                               const base::FilePath& directory_path)
-    : initialized_(false),
-      table_name_(table_name),
-      directory_path_(directory_path),
-      max_row_count_(0) {
-  base::ThreadRestrictions::AssertIOAllowed();
-
-  if (!file_util::DirectoryExists(directory_path_))
-    return;
-
-  std::string indicator_file_name = table_name_ + "_0";
-
-  base::FilePath indicator_file = directory_path_.Append(
-      base::FilePath::FromUTF8Unsafe(indicator_file_name));
-
-  // Look for the indicator_file file, indicating table existence.
-  initialized_ = file_util::PathExists(indicator_file) &&
-                 !file_util::DirectoryExists(indicator_file);
-}
-
-PmpTableReader::~PmpTableReader() {}
-
-const PmpColumnReader* PmpTableReader::AddColumn(
-    const std::string& column_name, const PmpFieldType expected_type) {
-  if (!initialized_)
-    return NULL;
-
-  std::string filename = table_name_ + "_" + column_name + "." + kPmpExtension;
-
-  base::FilePath column_file_path = directory_path_.Append(
-        base::FilePath::FromUTF8Unsafe(filename));
-  scoped_ptr<PmpColumnReader> column_reader(new PmpColumnReader());
-
-  uint32 row_count;
-  if (!column_reader->Init(column_file_path, expected_type, &row_count))
-    return NULL;
-
-  column_readers_.push_back(column_reader.release());
-  column_map_[column_name] = column_readers_.back();
-
-  max_row_count_ = std::max(max_row_count_, row_count);
-
-  return column_readers_.back();
-}
-
-uint32 PmpTableReader::RowCount() const {
-  return max_row_count_;
-}
-
-std::map<std::string, const PmpColumnReader*> PmpTableReader::Columns() const {
-  return column_map_;
-}
-
-}  // namespace picasa
diff --git a/chrome/browser/media_galleries/fileapi/picasa/pmp_table_reader.h b/chrome/browser/media_galleries/fileapi/picasa/pmp_table_reader.h
deleted file mode 100644
index 8374a95..0000000
--- a/chrome/browser/media_galleries/fileapi/picasa/pmp_table_reader.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_PICASA_PMP_TABLE_READER_H_
-#define CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_PICASA_PMP_TABLE_READER_H_
-
-#include <map>
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/files/file_path.h"
-#include "base/memory/scoped_vector.h"
-#include "chrome/browser/media_galleries/fileapi/picasa/pmp_constants.h"
-
-namespace base {
-class FilePath;
-}
-
-namespace picasa {
-
-class PmpColumnReader;
-
-class PmpTableReader {
- public:
-  PmpTableReader(const std::string& table_name,
-                 const base::FilePath& directory_path);
-
-  virtual ~PmpTableReader();
-
-  // Returns NULL on failure.
-  const PmpColumnReader* AddColumn(const std::string& column_name,
-                                   const PmpFieldType expected_type);
-
-  // Returns a const "view" of the successfully added columns.
-  std::map<std::string, const PmpColumnReader*> Columns() const;
-
-  // This value may change after calls to AddColumn().
-  uint32 RowCount() const;
-
- private:
-  bool initialized_;
-
-  std::string table_name_;
-  base::FilePath directory_path_;
-
-  ScopedVector<PmpColumnReader> column_readers_;
-  std::map<std::string, const PmpColumnReader*> column_map_;
-
-  uint32 max_row_count_;
-
-  DISALLOW_COPY_AND_ASSIGN(PmpTableReader);
-};
-
-}  // namespace picasa
-
-#endif  // CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_PICASA_PMP_TABLE_READER_H_
diff --git a/chrome/browser/media_galleries/fileapi/picasa/pmp_table_reader_unittest.cc b/chrome/browser/media_galleries/fileapi/picasa/pmp_table_reader_unittest.cc
deleted file mode 100644
index 91df98b..0000000
--- a/chrome/browser/media_galleries/fileapi/picasa/pmp_table_reader_unittest.cc
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <algorithm>
-#include <vector>
-
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/media_galleries/fileapi/picasa/pmp_column_reader.h"
-#include "chrome/browser/media_galleries/fileapi/picasa/pmp_constants.h"
-#include "chrome/browser/media_galleries/fileapi/picasa/pmp_table_reader.h"
-#include "chrome/browser/media_galleries/fileapi/picasa/pmp_test_helper.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-using picasa::PmpTestHelper;
-
-TEST(PmpTableReaderTest, RowCountAndFieldType) {
-  std::string table_name("tabletest");
-  PmpTestHelper test_helper(table_name);
-  ASSERT_TRUE(test_helper.Init());
-
-  std::vector<std::string> column_names;
-  column_names.push_back("strings");
-  column_names.push_back("uint32s");
-  column_names.push_back("doubles");
-
-  const std::vector<std::string> strings_vector(10, "Hello");
-  const std::vector<uint32> uint32s_vector(30, 42);
-  const std::vector<double> doubles_vector(20, 0.5);
-
-  picasa::PmpFieldType column_field_types[] = {
-    picasa::PMP_TYPE_STRING,
-    picasa::PMP_TYPE_UINT32,
-    picasa::PMP_TYPE_DOUBLE64
-  };
-
-  const uint32 max_rows = uint32s_vector.size();
-
-  // Write three column files, one each for strings, uint32s, and doubles.
-
-  ASSERT_TRUE(test_helper.WriteColumnFileFromVector(
-      column_names[0], column_field_types[0], strings_vector));
-  ASSERT_TRUE(test_helper.WriteColumnFileFromVector(
-      column_names[1], column_field_types[1], uint32s_vector));
-  ASSERT_TRUE(test_helper.WriteColumnFileFromVector(
-      column_names[2], column_field_types[2], doubles_vector));
-
-  picasa::PmpTableReader table_reader(table_name,
-                                            test_helper.GetTempDirPath());
-
-  for (unsigned int i = 0; i < column_names.size(); i++) {
-    ASSERT_TRUE(
-        table_reader.AddColumn(column_names[i], column_field_types[i]) != NULL);
-  }
-
-  EXPECT_EQ(max_rows, table_reader.RowCount());
-}
-
-}  // namespace
diff --git a/chrome/browser/media_galleries/fileapi/picasa/pmp_test_helper.cc b/chrome/browser/media_galleries/fileapi/picasa/pmp_test_helper.cc
deleted file mode 100644
index b2c28c7..0000000
--- a/chrome/browser/media_galleries/fileapi/picasa/pmp_test_helper.cc
+++ /dev/null
@@ -1,182 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/media_galleries/fileapi/picasa/pmp_test_helper.h"
-
-#include <algorithm>
-#include <iterator>
-
-#include "base/file_util.h"
-#include "base/logging.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/media_galleries/fileapi/picasa/pmp_column_reader.h"
-
-namespace picasa {
-
-namespace {
-
-bool WriteToFile(const base::FilePath& path, std::vector<uint8> data) {
-  // Cast for usage in WriteFile function
-  const char* data_char = reinterpret_cast<const char*>(&data[0]);
-  size_t bytes_written = file_util::WriteFile(path, data_char, data.size());
-  return (bytes_written == data.size());
-}
-
-// Flatten a vector of elements into an array of bytes.
-template<class T>
-std::vector<uint8> Flatten(const std::vector<T>& elems) {
-  if (elems.empty())
-    return std::vector<uint8>();
-
-  const uint8* elems0 = reinterpret_cast<const uint8*>(&elems[0]);
-  std::vector<uint8> data_body(elems0, elems0 + sizeof(T) * elems.size());
-
-  return data_body;
-}
-
-// Custom specialization for std::string.
-template<>
-std::vector<uint8> Flatten(const std::vector<std::string>& strings) {
-  std::vector<uint8> totalchars;
-
-  for (std::vector<std::string>::const_iterator it = strings.begin();
-      it != strings.end(); ++it) {
-    std::copy(it->begin(), it->end(), std::back_inserter(totalchars));
-    totalchars.push_back('\0');  // Add the null termination too.
-  }
-
-  return totalchars;
-}
-
-// Returns a new vector with the concatenated contents of |a| and |b|.
-std::vector<uint8> CombinedVectors(const std::vector<uint8>& a,
-                                   const std::vector<uint8>& b) {
-  std::vector<uint8> total;
-
-  std::copy(a.begin(), a.end(), std::back_inserter(total));
-  std::copy(b.begin(), b.end(), std::back_inserter(total));
-
-  return total;
-}
-
-}  // namespace
-
-PmpTestHelper::PmpTestHelper(const std::string& table_name)
-    : table_name_(table_name) {
-}
-
-bool PmpTestHelper::Init() {
-  if (!temp_dir_.CreateUniqueTempDir() || !temp_dir_.IsValid())
-    return false;
-
-  base::FilePath indicator_path = temp_dir_.path().Append(
-      base::FilePath::FromUTF8Unsafe(table_name_ + "_0"));
-
-  return file_util::WriteFile(indicator_path, NULL, 0) == 0;
-}
-
-base::FilePath PmpTestHelper::GetTempDirPath() {
-  DCHECK(temp_dir_.IsValid());
-  return temp_dir_.path();
-}
-
-template<class T>
-bool PmpTestHelper::WriteColumnFileFromVector(
-    const std::string& column_name, const PmpFieldType field_type,
-    const std::vector<T>& elements_vector) {
-  DCHECK(temp_dir_.IsValid());
-
-  std::string file_name = table_name_ + "_" + column_name + "." + kPmpExtension;
-
-  base::FilePath path = temp_dir_.path().Append(
-      base::FilePath::FromUTF8Unsafe(file_name));
-
-  std::vector<uint8> data = PmpTestHelper::MakeHeaderAndBody(
-      field_type, elements_vector.size(), elements_vector);
-
-  return WriteToFile(path, data);
-}
-
-// Explicit Instantiation for all the valid types.
-template bool PmpTestHelper::WriteColumnFileFromVector<std::string>(
-    const std::string&, const PmpFieldType, const std::vector<std::string>&);
-template bool PmpTestHelper::WriteColumnFileFromVector<uint32>(
-    const std::string&, const PmpFieldType, const std::vector<uint32>&);
-template bool PmpTestHelper::WriteColumnFileFromVector<double>(
-    const std::string&, const PmpFieldType, const std::vector<double>&);
-template bool PmpTestHelper::WriteColumnFileFromVector<uint8>(
-    const std::string&, const PmpFieldType, const std::vector<uint8>&);
-template bool PmpTestHelper::WriteColumnFileFromVector<uint64>(
-    const std::string&, const PmpFieldType, const std::vector<uint64>&);
-
-bool PmpTestHelper::InitColumnReaderFromBytes(PmpColumnReader* const reader,
-                                              const std::vector<uint8>& data,
-                                              const PmpFieldType expected_type,
-                                              uint32* rows_read) {
-  DCHECK(temp_dir_.IsValid());
-
-  base::FilePath temp_path;
-
-  if (!file_util::CreateTemporaryFileInDir(temp_dir_.path(), &temp_path)
-      || !WriteToFile(temp_path, data)) {
-    return false;
-  }
-
-  bool success = reader->Init(temp_path, expected_type, rows_read);
-
-  file_util::Delete(temp_path, true);
-
-  return success;
-
-}
-
-// Return a vector so we don't have to worry about memory management.
-std::vector<uint8> PmpTestHelper::MakeHeader(const PmpFieldType field_type,
-                                             const uint32 row_count) {
-  std::vector<uint8> header(picasa::kPmpHeaderSize);
-
-  // Copy in magic bytes.
-  memcpy(&header[picasa::kPmpMagic1Offset], &picasa::kPmpMagic1,
-         sizeof(picasa::kPmpMagic1));
-  memcpy(&header[picasa::kPmpMagic2Offset], &picasa::kPmpMagic2,
-         sizeof(picasa::kPmpMagic2));
-  memcpy(&header[picasa::kPmpMagic3Offset], &picasa::kPmpMagic3,
-         sizeof(picasa::kPmpMagic3));
-  memcpy(&header[picasa::kPmpMagic4Offset], &picasa::kPmpMagic4,
-         sizeof(picasa::kPmpMagic4));
-
-  // Copy in field type.
-  uint16 field_type_short = static_cast<uint16>(field_type);
-  memcpy(&header[picasa::kPmpFieldType1Offset], &field_type_short,
-         sizeof(uint16));
-  memcpy(&header[picasa::kPmpFieldType2Offset], &field_type_short,
-         sizeof(uint16));
-
-  // Copy in row count.
-  memcpy(&header[picasa::kPmpRowCountOffset], &row_count, sizeof(uint32));
-
-  return header;
-}
-
-template<class T>
-std::vector<uint8> PmpTestHelper::MakeHeaderAndBody(
-    const PmpFieldType field_type, const uint32 row_count,
-    const std::vector<T>& elems) {
-  return CombinedVectors(PmpTestHelper::MakeHeader(field_type, row_count),
-                         Flatten(elems));
-}
-
-// Explicit Instantiation for all the valid types.
-template std::vector<uint8> PmpTestHelper::MakeHeaderAndBody<std::string>(
-    const PmpFieldType, const uint32, const std::vector<std::string>&);
-template std::vector<uint8> PmpTestHelper::MakeHeaderAndBody<uint32>(
-    const PmpFieldType, const uint32, const std::vector<uint32>&);
-template std::vector<uint8> PmpTestHelper::MakeHeaderAndBody<double>(
-    const PmpFieldType, const uint32, const std::vector<double>&);
-template std::vector<uint8> PmpTestHelper::MakeHeaderAndBody<uint8>(
-    const PmpFieldType, const uint32, const std::vector<uint8>&);
-template std::vector<uint8> PmpTestHelper::MakeHeaderAndBody<uint64>(
-    const PmpFieldType, const uint32, const std::vector<uint64>&);
-
-}  // namespace picasa
diff --git a/chrome/browser/media_galleries/fileapi/picasa/pmp_test_helper.h b/chrome/browser/media_galleries/fileapi/picasa/pmp_test_helper.h
deleted file mode 100644
index a20ac33..0000000
--- a/chrome/browser/media_galleries/fileapi/picasa/pmp_test_helper.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_PICASA_PMP_TEST_HELPER_H_
-#define CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_PICASA_PMP_TEST_HELPER_H_
-
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/files/scoped_temp_dir.h"
-#include "chrome/browser/media_galleries/fileapi/picasa/pmp_constants.h"
-
-namespace base {
-class FilePath;
-}  // namespace base
-
-namespace picasa {
-
-class PmpColumnReader;
-
-// A helper class used for unit tests only
-class PmpTestHelper {
- public:
-  explicit PmpTestHelper(const std::string& table_name);
-
-  bool Init();
-
-  base::FilePath GetTempDirPath();
-
-  template<class T>
-  bool WriteColumnFileFromVector(const std::string& column_name,
-                                 const PmpFieldType field_type,
-                                 const std::vector<T>& elements_vector);
-
-  bool InitColumnReaderFromBytes(PmpColumnReader* const reader,
-                                 const std::vector<uint8>& data,
-                                 const PmpFieldType expected_type,
-                                 uint32* rows_read);
-
-  static std::vector<uint8> MakeHeader(const PmpFieldType field_type,
-                                       const uint32 row_count);
-
-  template<class T>
-  static std::vector<uint8> MakeHeaderAndBody(const PmpFieldType field_type,
-                                              const uint32 row_count,
-                                              const std::vector<T>& elems);
-
- private:
-  std::string table_name_;
-  base::ScopedTempDir temp_dir_;
-};
-
-}  // namespace picasa
-
-#endif  // CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_PICASA_PMP_TEST_HELPER_H_
diff --git a/chrome/browser/media_galleries/fileapi/safe_itunes_library_parser.cc b/chrome/browser/media_galleries/fileapi/safe_itunes_library_parser.cc
new file mode 100644
index 0000000..1935336
--- /dev/null
+++ b/chrome/browser/media_galleries/fileapi/safe_itunes_library_parser.cc
@@ -0,0 +1,118 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/media_galleries/fileapi/safe_itunes_library_parser.h"
+
+#include "chrome/browser/media_galleries/fileapi/media_file_system_mount_point_provider.h"
+#include "chrome/common/chrome_utility_messages.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/child_process_data.h"
+#include "ipc/ipc_platform_file.h"
+
+using chrome::MediaFileSystemMountPointProvider;
+using content::BrowserThread;
+using content::UtilityProcessHost;
+
+namespace itunes {
+
+SafeITunesLibraryParser::SafeITunesLibraryParser(
+    const base::FilePath& itunes_library_file,
+    const ParserCallback& callback)
+    : itunes_library_file_(itunes_library_file),
+      callback_(callback),
+      parser_state_(INITIAL_STATE) {}
+
+void SafeITunesLibraryParser::Start() {
+  DCHECK(MediaFileSystemMountPointProvider::CurrentlyOnMediaTaskRunnerThread());
+
+  // |itunes_library_platform_file_| will be closed on the IO thread once it
+  // has been handed off to the child process.
+  itunes_library_platform_file_ = base::CreatePlatformFile(
+      itunes_library_file_,
+      base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ,
+      NULL,   // created
+      NULL);  // error_code
+  if (itunes_library_platform_file_ == base::kInvalidPlatformFileValue) {
+    VLOG(1) << "Could not open iTunes library XML file: "
+            << itunes_library_file_.value();
+    callback_.Run(false /* failed */, parser::Library());
+    BrowserThread::PostTask(
+        BrowserThread::IO, FROM_HERE,
+        base::Bind(&SafeITunesLibraryParser::OnOpenLibraryFileFailed, this));
+    return;
+  }
+
+  BrowserThread::PostTask(
+      BrowserThread::IO, FROM_HERE,
+      base::Bind(&SafeITunesLibraryParser::StartProcessOnIOThread, this));
+}
+
+SafeITunesLibraryParser::~SafeITunesLibraryParser() {}
+
+void SafeITunesLibraryParser::StartProcessOnIOThread() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_EQ(INITIAL_STATE, parser_state_);
+
+  scoped_refptr<base::MessageLoopProxy> message_loop_proxy =
+      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
+  utility_process_host_ =
+      UtilityProcessHost::Create(this, message_loop_proxy.get())->AsWeakPtr();
+  // Wait for the startup notification before sending the main IPC to the
+  // utility process, so that we can dup the file handle.
+  utility_process_host_->Send(new ChromeUtilityMsg_StartupPing);
+  parser_state_ = PINGED_UTILITY_PROCESS_STATE;
+}
+
+void SafeITunesLibraryParser::OnUtilityProcessStarted() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  if (parser_state_ != PINGED_UTILITY_PROCESS_STATE)
+    return;
+
+  if (utility_process_host_->GetData().handle == base::kNullProcessHandle)
+    DLOG(ERROR) << "Child process handle is null";
+  utility_process_host_->Send(
+      new ChromeUtilityMsg_ParseITunesLibraryXmlFile(
+          IPC::GetFileHandleForProcess(
+              itunes_library_platform_file_,
+              utility_process_host_->GetData().handle,
+              true /* close_source_handle */)));
+  parser_state_ = STARTED_PARSING_STATE;
+}
+
+void SafeITunesLibraryParser::OnGotITunesLibrary(
+    bool result, const parser::Library& library) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+  if (parser_state_ != STARTED_PARSING_STATE)
+    return;
+
+  MediaFileSystemMountPointProvider::MediaTaskRunner()->PostTask(
+      FROM_HERE,
+      base::Bind(callback_, result, library));
+  parser_state_ = FINISHED_PARSING_STATE;
+}
+
+void SafeITunesLibraryParser::OnOpenLibraryFileFailed() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  parser_state_ = FINISHED_PARSING_STATE;
+}
+
+void SafeITunesLibraryParser::OnProcessCrashed(int exit_code) {
+  OnGotITunesLibrary(false /* failed */, parser::Library());
+}
+
+bool SafeITunesLibraryParser::OnMessageReceived(
+    const IPC::Message& message) {
+  bool handled = true;
+  IPC_BEGIN_MESSAGE_MAP(SafeITunesLibraryParser, message)
+    IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ProcessStarted,
+                        OnUtilityProcessStarted)
+    IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_GotITunesLibrary,
+                        OnGotITunesLibrary)
+    IPC_MESSAGE_UNHANDLED(handled = false)
+  IPC_END_MESSAGE_MAP()
+  return handled;
+}
+
+}  // namespace itunes
diff --git a/chrome/browser/media_galleries/fileapi/safe_itunes_library_parser.h b/chrome/browser/media_galleries/fileapi/safe_itunes_library_parser.h
new file mode 100644
index 0000000..26e2e59
--- /dev/null
+++ b/chrome/browser/media_galleries/fileapi/safe_itunes_library_parser.h
@@ -0,0 +1,98 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_SAFE_ITUNES_LIBRARY_PARSER_H_
+#define CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_SAFE_ITUNES_LIBRARY_PARSER_H_
+
+#include <string>
+
+#include "base/callback.h"
+#include "base/compiler_specific.h"
+#include "base/files/file_path.h"
+#include "base/memory/weak_ptr.h"
+#include "base/platform_file.h"
+#include "chrome/common/itunes_library.h"
+#include "content/public/browser/utility_process_host.h"
+#include "content/public/browser/utility_process_host_client.h"
+
+namespace IPC {
+class Message;
+}
+
+namespace itunes {
+
+// SafeITunesLibraryParser parses the given iTunes library XML file safely via
+// a utility process. The SafeITunesLibraryParser object is ref-counted and
+// kept alive after Start() is called until the ParserCallback is called.
+// The ParserCallback is guaranteed to be called eventually either when the
+// utility process replies or when it dies.
+// Since iTunes library XML files can be big, SafeITunesLibraryParser passes
+// the file handle to the utility process.
+// SafeITunesLibraryParser lives on the Media Task Runner unless otherwise
+// noted.
+class SafeITunesLibraryParser : public content::UtilityProcessHostClient {
+ public:
+  typedef base::Callback<void(bool, const parser::Library&)> ParserCallback;
+
+  SafeITunesLibraryParser(const base::FilePath& itunes_library_file,
+                          const ParserCallback& callback);
+
+  // Posts a task to start the XML parsing in the utility process.
+  void Start();
+
+ private:
+  enum ParserState {
+    INITIAL_STATE,
+    PINGED_UTILITY_PROCESS_STATE,
+    STARTED_PARSING_STATE,
+    FINISHED_PARSING_STATE,
+  };
+
+  // content::UtilityProcessHostClient is ref-counted.
+  virtual ~SafeITunesLibraryParser();
+
+  // Launches the utility process.  Must run on the IO thread.
+  void StartProcessOnIOThread();
+
+  // Notification that the utility process is running, and we can now get its
+  // process handle.
+  // Runs on the IO thread.
+  void OnUtilityProcessStarted();
+
+  // Notification from the utility process when it finishes parsing the XML.
+  // Runs on the IO thread.
+  void OnGotITunesLibrary(bool result, const parser::Library& library);
+
+  // Sets |parser_state_| in case the library XML file cannot be opened.
+  // Runs on the IO thread.
+  void OnOpenLibraryFileFailed();
+
+  // UtilityProcessHostClient implementation.
+  // Runs on the IO thread.
+  virtual void OnProcessCrashed(int exit_code) OVERRIDE;
+  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+
+  const base::FilePath itunes_library_file_;
+
+  // Once we have opened the file, we store the handle so that we can use it
+  // once the utility process has launched.
+  base::PlatformFile itunes_library_platform_file_;
+
+  // Only accessed on the IO thread.
+  base::WeakPtr<content::UtilityProcessHost> utility_process_host_;
+
+  // Only accessed on the Media Task Runner.
+  const ParserCallback callback_;
+
+  // Verifies the messages from the utility process came at the right time.
+  // Initialized on the Media Task Runner, but only accessed on the IO thread.
+  ParserState parser_state_;
+
+
+  DISALLOW_COPY_AND_ASSIGN(SafeITunesLibraryParser);
+};
+
+}  // namespace itunes
+
+#endif  // CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_SAFE_ITUNES_LIBRARY_PARSER_H_
diff --git a/chrome/browser/media_galleries/fileapi/safe_itunes_pref_parser_win.cc b/chrome/browser/media_galleries/fileapi/safe_itunes_pref_parser_win.cc
new file mode 100644
index 0000000..a22a0eb
--- /dev/null
+++ b/chrome/browser/media_galleries/fileapi/safe_itunes_pref_parser_win.cc
@@ -0,0 +1,74 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/media_galleries/fileapi/safe_itunes_pref_parser_win.h"
+
+#include "chrome/common/chrome_utility_messages.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/utility_process_host.h"
+
+using content::BrowserThread;
+using content::UtilityProcessHost;
+
+namespace itunes {
+
+SafeITunesPrefParserWin::SafeITunesPrefParserWin(
+    const std::string& unsafe_xml,
+    const ParserCallback& callback)
+    : unsafe_xml_(unsafe_xml),
+      callback_(callback),
+      parser_state_(INITIAL_STATE) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK(!callback_.is_null());
+}
+
+void SafeITunesPrefParserWin::Start() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  BrowserThread::PostTask(
+      BrowserThread::IO,
+      FROM_HERE,
+      base::Bind(&SafeITunesPrefParserWin::StartWorkOnIOThread, this));
+}
+
+SafeITunesPrefParserWin::~SafeITunesPrefParserWin() {
+}
+
+void SafeITunesPrefParserWin::StartWorkOnIOThread() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_EQ(INITIAL_STATE, parser_state_);
+
+  UtilityProcessHost* host =
+      UtilityProcessHost::Create(this, base::MessageLoopProxy::current());
+  host->EnableZygote();
+  host->Send(new ChromeUtilityMsg_ParseITunesPrefXml(unsafe_xml_));
+  parser_state_ = STARTED_PARSING_STATE;
+}
+
+void SafeITunesPrefParserWin::OnGotITunesDirectory(
+    const base::FilePath& library_file) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+  if (parser_state_ != STARTED_PARSING_STATE)
+    return;
+  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+                          base::Bind(callback_, library_file));
+  parser_state_ = FINISHED_PARSING_STATE;
+}
+
+void SafeITunesPrefParserWin::OnProcessCrashed(int exit_code) {
+  OnGotITunesDirectory(base::FilePath());
+}
+
+bool SafeITunesPrefParserWin::OnMessageReceived(
+    const IPC::Message& message) {
+  bool handled = true;
+  IPC_BEGIN_MESSAGE_MAP(SafeITunesPrefParserWin, message)
+    IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_GotITunesDirectory,
+                        OnGotITunesDirectory)
+    IPC_MESSAGE_UNHANDLED(handled = false)
+  IPC_END_MESSAGE_MAP()
+  return handled;
+}
+
+}  // namespace itunes
diff --git a/chrome/browser/media_galleries/fileapi/safe_itunes_pref_parser_win.h b/chrome/browser/media_galleries/fileapi/safe_itunes_pref_parser_win.h
new file mode 100644
index 0000000..632be61
--- /dev/null
+++ b/chrome/browser/media_galleries/fileapi/safe_itunes_pref_parser_win.h
@@ -0,0 +1,70 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_SAFE_ITUNES_PREF_PARSER_WIN_H_
+#define CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_SAFE_ITUNES_PREF_PARSER_WIN_H_
+
+#include <string>
+
+#include "base/callback.h"
+#include "base/compiler_specific.h"
+#include "content/public/browser/utility_process_host_client.h"
+
+namespace base {
+class FilePath;
+}
+
+namespace IPC {
+class Message;
+}
+
+namespace itunes {
+
+// SafeITunesPrefParserWin parses the given iTunes preferences XML data safely
+// via a utility process. The SafeITunesPrefParserWin object is ref-counted and
+// kept alive after Start() is called until the ParserCallback is called.
+// The ParserCallback is guaranteed to be called eventually either when the
+// utility process replies or when it dies.
+class SafeITunesPrefParserWin : public content::UtilityProcessHostClient {
+ public:
+  typedef base::Callback<void(const base::FilePath&)> ParserCallback;
+
+  SafeITunesPrefParserWin(const std::string& unsafe_xml,
+                          const ParserCallback& callback);
+
+  void Start();
+
+ private:
+  enum ParserState {
+    INITIAL_STATE,
+    STARTED_PARSING_STATE,
+    FINISHED_PARSING_STATE,
+  };
+
+  // Private because content::UtilityProcessHostClient is ref-counted.
+  virtual ~SafeITunesPrefParserWin();
+
+  void StartWorkOnIOThread();
+
+  // Handles the results from OnProcessCrashed() and OnMessageReceived() on
+  // the IO thread.
+  void OnGotITunesDirectory(const base::FilePath& library_file);
+
+  // UtilityProcessHostClient implementation.
+  virtual void OnProcessCrashed(int exit_code) OVERRIDE;
+  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+
+  const std::string unsafe_xml_;
+  const ParserCallback callback_;
+
+  // Verifies the messages from the utility process came at the right time.
+  // Initialized on the FILE thread, but only accessed on the IO thread.
+  ParserState parser_state_;
+
+  DISALLOW_COPY_AND_ASSIGN(SafeITunesPrefParserWin);
+};
+
+}  // namespace itunes
+
+#endif  // CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_SAFE_ITUNES_PREF_PARSER_WIN_H_
diff --git a/chrome/browser/media_galleries/imported_media_gallery_registry.cc b/chrome/browser/media_galleries/imported_media_gallery_registry.cc
index a42b959..b9f6c13 100644
--- a/chrome/browser/media_galleries/imported_media_gallery_registry.cc
+++ b/chrome/browser/media_galleries/imported_media_gallery_registry.cc
@@ -6,7 +6,6 @@
 
 #include "base/bind.h"
 #include "base/logging.h"
-#include "base/threading/sequenced_worker_pool.h"
 #include "chrome/browser/media_galleries/fileapi/itunes_data_provider.h"
 #include "chrome/browser/media_galleries/fileapi/media_file_system_mount_point_provider.h"
 #include "chrome/browser/media_galleries/fileapi/picasa/picasa_data_provider.h"
@@ -15,22 +14,12 @@
 #include "webkit/browser/fileapi/isolated_context.h"
 
 using base::Bind;
+using fileapi::IsolatedContext;
 
 namespace chrome {
 
 namespace {
 
-scoped_refptr<base::SequencedTaskRunner> MediaTaskRunner() {
-  DCHECK(
-      !MediaFileSystemMountPointProvider::CurrentlyOnMediaTaskRunnerThread());
-  base::SequencedWorkerPool* pool = content::BrowserThread::GetBlockingPool();
-  base::SequencedWorkerPool::SequenceToken media_sequence_token =
-      pool->GetNamedSequenceToken(
-          MediaFileSystemMountPointProvider::kMediaTaskRunnerName);
-
-  return pool->GetSequencedTaskRunner(media_sequence_token);
-}
-
 static base::LazyInstance<ImportedMediaGalleryRegistry>::Leaky
 g_imported_media_gallery_registry = LAZY_INSTANCE_INITIALIZER;
 
@@ -46,19 +35,21 @@
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
   DCHECK(!database_path.empty());
 
-  std::string fsid =
-      fileapi::IsolatedContext::GetInstance()->RegisterFileSystemForVirtualPath(
+  std::string fsid;
+
+#if defined(OS_WIN) || defined(OS_MACOSX)
+  fsid = IsolatedContext::GetInstance()->RegisterFileSystemForVirtualPath(
            fileapi::kFileSystemTypePicasa,
            extension_misc::kMediaFileSystemPathPart,
            base::FilePath());
 
   if (fsid.empty())
-    return "";
+    return fsid;
 
   picasa_fsids_.insert(fsid);
 
   if (picasa_fsids_.size() == 1) {
-    MediaTaskRunner()->PostTask(
+    MediaFileSystemMountPointProvider::MediaTaskRunner()->PostTask(
         FROM_HERE,
         Bind(&ImportedMediaGalleryRegistry::RegisterPicasaFileSystem,
              base::Unretained(this), database_path));
@@ -68,6 +59,7 @@
     DCHECK_EQ(picasa_database_path_.value(), database_path.value());
 #endif
   }
+#endif  // defined(OS_WIN) || defined(OS_MACOSX)
 
   return fsid;
 }
@@ -77,19 +69,21 @@
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
   DCHECK(!library_xml_path.empty());
 
-  std::string fsid =
-      fileapi::IsolatedContext::GetInstance()->RegisterFileSystemForVirtualPath(
+  std::string fsid;
+
+#if defined(OS_WIN) || defined(OS_MACOSX)
+  fsid = IsolatedContext::GetInstance()->RegisterFileSystemForVirtualPath(
            fileapi::kFileSystemTypeItunes,
            extension_misc::kMediaFileSystemPathPart,
            base::FilePath());
 
   if (fsid.empty())
-    return std::string();
+    return fsid;
 
   itunes_fsids_.insert(fsid);
 
   if (itunes_fsids_.size() == 1) {
-    MediaTaskRunner()->PostTask(
+    MediaFileSystemMountPointProvider::MediaTaskRunner()->PostTask(
         FROM_HERE,
         Bind(&ImportedMediaGalleryRegistry::RegisterITunesFileSystem,
              base::Unretained(this), library_xml_path));
@@ -99,6 +93,7 @@
     DCHECK_EQ(itunes_xml_library_path_.value(), library_xml_path.value());
 #endif
   }
+#endif  // defined(OS_WIN) || defined(OS_MACOSX)
 
   return fsid;
 }
@@ -107,29 +102,32 @@
     const std::string& fsid) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
 
+#if defined(OS_WIN) || defined(OS_MACOSX)
   if (picasa_fsids_.erase(fsid)) {
     if (picasa_fsids_.empty()) {
-      MediaTaskRunner()->PostTask(
+      MediaFileSystemMountPointProvider::MediaTaskRunner()->PostTask(
           FROM_HERE,
           Bind(&ImportedMediaGalleryRegistry::RevokePicasaFileSystem,
                base::Unretained(this)));
     }
-    return fileapi::IsolatedContext::GetInstance()->RevokeFileSystem(fsid);
+    return IsolatedContext::GetInstance()->RevokeFileSystem(fsid);
   }
 
   if (itunes_fsids_.erase(fsid)) {
     if (itunes_fsids_.empty()) {
-      MediaTaskRunner()->PostTask(
+      MediaFileSystemMountPointProvider::MediaTaskRunner()->PostTask(
           FROM_HERE,
           Bind(&ImportedMediaGalleryRegistry::RevokeITunesFileSystem,
                base::Unretained(this)));
     }
-    return fileapi::IsolatedContext::GetInstance()->RevokeFileSystem(fsid);
+    return IsolatedContext::GetInstance()->RevokeFileSystem(fsid);
   }
+#endif  // defined(OS_WIN) || defined(OS_MACOSX)
 
   return false;
 }
 
+#if defined(OS_WIN) || defined(OS_MACOSX)
 // static
 picasa::PicasaDataProvider*
 ImportedMediaGalleryRegistry::PicasaDataProvider() {
@@ -145,14 +143,18 @@
   DCHECK(GetInstance()->itunes_data_provider_);
   return GetInstance()->itunes_data_provider_.get();
 }
+#endif  // defined(OS_WIN) || defined(OS_MACOSX)
 
 ImportedMediaGalleryRegistry::ImportedMediaGalleryRegistry() {}
 
 ImportedMediaGalleryRegistry::~ImportedMediaGalleryRegistry() {
+#if defined(OS_WIN) || defined(OS_MACOSX)
   DCHECK_EQ(0U, picasa_fsids_.size());
   DCHECK_EQ(0U, itunes_fsids_.size());
+#endif  // defined(OS_WIN) || defined(OS_MACOSX)
 }
 
+#if defined(OS_WIN) || defined(OS_MACOSX)
 void ImportedMediaGalleryRegistry::RegisterPicasaFileSystem(
     const base::FilePath& database_path) {
   DCHECK(MediaFileSystemMountPointProvider::CurrentlyOnMediaTaskRunnerThread());
@@ -178,5 +180,6 @@
   DCHECK(itunes_data_provider_);
   itunes_data_provider_.reset();
 }
+#endif  // defined(OS_WIN) || defined(OS_MACOSX)
 
 }  // namespace chrome
diff --git a/chrome/browser/media_galleries/imported_media_gallery_registry.h b/chrome/browser/media_galleries/imported_media_gallery_registry.h
index d8f0e69..f90e7c1 100644
--- a/chrome/browser/media_galleries/imported_media_gallery_registry.h
+++ b/chrome/browser/media_galleries/imported_media_gallery_registry.h
@@ -42,8 +42,10 @@
   bool RevokeImportedFilesystemOnUIThread(const std::string& fsid);
 
   // Should be called on the MediaTaskRunner thread only.
+#if defined(OS_WIN) || defined(OS_MACOSX)
   static picasa::PicasaDataProvider* PicasaDataProvider();
   static itunes::ITunesDataProvider* ITunesDataProvider();
+#endif  // defined(OS_WIN) || defined(OS_MACOSX)
 
  private:
   friend struct base::DefaultLazyInstanceTraits<ImportedMediaGalleryRegistry>;
@@ -51,6 +53,7 @@
   ImportedMediaGalleryRegistry();
   virtual ~ImportedMediaGalleryRegistry();
 
+#if defined(OS_WIN) || defined(OS_MACOSX)
   void RegisterPicasaFileSystem(const base::FilePath& database_path);
   void RevokePicasaFileSystem();
 
@@ -69,6 +72,7 @@
   base::FilePath picasa_database_path_;
   base::FilePath itunes_xml_library_path_;
 #endif
+#endif  // defined(OS_WIN) || defined(OS_MACOSX)
 
   DISALLOW_COPY_AND_ASSIGN(ImportedMediaGalleryRegistry);
 };
diff --git a/chrome/browser/media_galleries/linux/mtp_device_object_enumerator.h b/chrome/browser/media_galleries/linux/mtp_device_object_enumerator.h
index c5d1215..31a2ce4 100644
--- a/chrome/browser/media_galleries/linux/mtp_device_object_enumerator.h
+++ b/chrome/browser/media_galleries/linux/mtp_device_object_enumerator.h
@@ -8,7 +8,7 @@
 #include <vector>
 
 #include "base/files/file_path.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "device/media_transfer_protocol/mtp_file_entry.pb.h"
 #include "webkit/browser/fileapi/file_system_file_util.h"
 
diff --git a/chrome/browser/media_galleries/mac/mtp_device_delegate_impl_mac.mm b/chrome/browser/media_galleries/mac/mtp_device_delegate_impl_mac.mm
index 7c4447f..87119f1 100644
--- a/chrome/browser/media_galleries/mac/mtp_device_delegate_impl_mac.mm
+++ b/chrome/browser/media_galleries/mac/mtp_device_delegate_impl_mac.mm
@@ -6,7 +6,7 @@
 
 #include <algorithm>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/threading/sequenced_worker_pool.h"
 #include "chrome/browser/media_galleries/mtp_device_delegate_impl.h"
 #include "chrome/browser/storage_monitor/image_capture_device.h"
@@ -61,7 +61,7 @@
   virtual void ResetDelegate();
 
  private:
-  scoped_nsobject<ImageCaptureDevice> camera_device_;
+  base::scoped_nsobject<ImageCaptureDevice> camera_device_;
 
   // Weak pointer
   MTPDeviceDelegateImplMac* delegate_;
diff --git a/chrome/browser/media_galleries/mac/mtp_device_delegate_impl_mac_unittest.mm b/chrome/browser/media_galleries/mac/mtp_device_delegate_impl_mac_unittest.mm
index c88493b..7e71717 100644
--- a/chrome/browser/media_galleries/mac/mtp_device_delegate_impl_mac_unittest.mm
+++ b/chrome/browser/media_galleries/mac/mtp_device_delegate_impl_mac_unittest.mm
@@ -9,7 +9,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/mac/cocoa_protocols.h"
 #include "base/mac/foundation_util.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/sys_string_conversions.h"
@@ -47,7 +47,7 @@
 
 @interface MockMTPICCameraDevice : ICCameraDevice {
  @private
-  scoped_nsobject<NSMutableArray> allMediaFiles_;
+  base::scoped_nsobject<NSMutableArray> allMediaFiles_;
 }
 
 - (void)addMediaFile:(ICCameraFile*)file;
@@ -121,8 +121,8 @@
 
 @interface MockMTPICCameraFile : ICCameraFile {
  @private
-  scoped_nsobject<NSString> name_;
-  scoped_nsobject<NSDate> date_;
+  base::scoped_nsobject<NSString> name_;
+  base::scoped_nsobject<NSDate> date_;
 }
 
 - (id)init:(NSString*)name;
@@ -546,7 +546,7 @@
   info.last_accessed = t1;
   info.creation_time = t1;
   std::string kTestFileName("filename");
-  scoped_nsobject<MockMTPICCameraFile> picture1(
+  base::scoped_nsobject<MockMTPICCameraFile> picture1(
       [[MockMTPICCameraFile alloc]
           init:base::SysUTF8ToNSString(kTestFileName)]);
   [camera_ addMediaFile:picture1];
diff --git a/chrome/browser/media_galleries/media_file_system_registry.cc b/chrome/browser/media_galleries/media_file_system_registry.cc
index 345e8ea..b1a2f9d 100644
--- a/chrome/browser/media_galleries/media_file_system_registry.cc
+++ b/chrome/browser/media_galleries/media_file_system_registry.cc
@@ -341,8 +341,7 @@
         continue;
 
       MediaFileSystemInfo new_entry(
-          MediaGalleriesDialogController::GetGalleryDisplayNameNoAttachment(
-              gallery_info),
+          gallery_info.GetGalleryDisplayName(),
           path,
           fsid,
           pref_id,
diff --git a/chrome/browser/media_galleries/media_file_system_registry_unittest.cc b/chrome/browser/media_galleries/media_file_system_registry_unittest.cc
index c7b4adc..59a411b 100644
--- a/chrome/browser/media_galleries/media_file_system_registry_unittest.cc
+++ b/chrome/browser/media_galleries/media_file_system_registry_unittest.cc
@@ -54,12 +54,6 @@
 #include "chrome/browser/chromeos/settings/device_settings_service.h"
 #endif
 
-#if defined(OS_WIN)
-#include "chrome/browser/storage_monitor/test_portable_device_watcher_win.h"
-#include "chrome/browser/storage_monitor/test_storage_monitor_win.h"
-#include "chrome/browser/storage_monitor/test_volume_mount_watcher_win.h"
-#endif
-
 using content::BrowserThread;
 
 namespace chrome {
@@ -384,12 +378,7 @@
   scoped_ptr<chromeos::ScopedTestUserManager> test_user_manager_;
 #endif
 
-// TODO(gbillock): Eliminate windows-specific code from this test.
-#if defined(OS_WIN)
-  scoped_ptr<test::TestStorageMonitorWin> monitor_;
-#else
   scoped_ptr<chrome::test::TestStorageMonitor> monitor_;
-#endif
 
   MockProfileSharedRenderProcessHostFactory rph_factory_;
 
@@ -758,20 +747,10 @@
 
 void MediaFileSystemRegistryTest::SetUp() {
   ChromeRenderViewHostTestHarness::SetUp();
-#if defined(OS_WIN)
-  test::TestPortableDeviceWatcherWin* portable_device_watcher =
-      new test::TestPortableDeviceWatcherWin;
-  test::TestVolumeMountWatcherWin* mount_watcher =
-      new test::TestVolumeMountWatcherWin;
-  portable_device_watcher->set_use_dummy_mtp_storage_info(true);
-  monitor_.reset(new test::TestStorageMonitorWin(
-      mount_watcher, portable_device_watcher));
-#else
   monitor_.reset(new test::TestStorageMonitor());
   monitor_->MarkInitialized();
-#endif
   base::RunLoop runloop;
-  monitor_->Initialize(runloop.QuitClosure());
+  monitor_->EnsureInitialized(runloop.QuitClosure());
   runloop.Run();
 
   DeleteContents();
@@ -801,9 +780,6 @@
   test_user_manager_.reset();
 #endif
 
-#if defined(OS_WIN)
-  monitor_.reset();
-#endif
   ChromeRenderViewHostTestHarness::TearDown();
 }
 
@@ -925,21 +901,13 @@
   }
 }
 
-// TODO(gbillock): Put the platform-specific parts of this test in tests
-// for those classes, not here. This test, internally, ends up creating an
-// MTP delegate. (Probably ./win/mtp_device_delegate_impl_win_unittest)
-#if !defined(OS_MACOSX)
+// TODO(gbillock): Move the remaining test into the linux directory.
+#if !defined(OS_MACOSX) && !defined(OS_WIN)
 TEST_F(MediaFileSystemRegistryTest, GalleryMTP) {
   FSInfoMap galleries_info;
   InitForGalleriesInfoTest(&galleries_info);
 
-#if defined(OS_WIN)
-  base::FilePath location(
-      PortableDeviceWatcherWin::GetStoragePathFromStorageId(
-          test::TestPortableDeviceWatcherWin::kStorageUniqueIdA));
-#else
   base::FilePath location(FILE_PATH_LITERAL("/mtp_bogus"));
-#endif
   AttachDevice(StorageInfo::MTP_OR_PTP, "mtp_fake_id", location);
   CheckNewGalleryInfo(GetProfileState(0U), galleries_info, location,
                       true /*removable*/, true /* media device */);
diff --git a/chrome/browser/media_galleries/media_galleries_dialog_controller.cc b/chrome/browser/media_galleries/media_galleries_dialog_controller.cc
index 57e98d2..973bcdf 100644
--- a/chrome/browser/media_galleries/media_galleries_dialog_controller.cc
+++ b/chrome/browser/media_galleries/media_galleries_dialog_controller.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/media_galleries/media_galleries_dialog_controller.h"
 
-#include "base/i18n/time_formatting.h"
 #include "base/path_service.h"
 #include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
@@ -28,19 +27,6 @@
 
 namespace {
 
-bool IsAttachedDevice(const std::string& device_id) {
-  if (!StorageInfo::IsRemovableDevice(device_id))
-    return false;
-
-  std::vector<StorageInfo> storages =
-      StorageMonitor::GetInstance()->GetAllAvailableStorages();
-  for (size_t i = 0; i < storages.size(); ++i) {
-    if (storages[i].device_id() == device_id)
-      return true;
-  }
-  return false;
-}
-
 // Comparator for sorting GalleryPermissionsVector -- sorts
 // allowed galleries low, and then sorts by absolute path.
 bool GalleriesVectorComparator(
@@ -54,41 +40,6 @@
   return a.pref_info.AbsolutePath() < b.pref_info.AbsolutePath();
 }
 
-string16 GetDisplayNameForDevice(uint64 storage_size_in_bytes,
-                                 const string16& name) {
-  DCHECK(!name.empty());
-  return (storage_size_in_bytes == 0) ?
-      name : ui::FormatBytes(storage_size_in_bytes) + ASCIIToUTF16(" ") + name;
-}
-
-
-// For a device with |device_name| and a relative path |sub_folder|, construct
-// a display name. If |sub_folder| is empty, then just return |device_name|.
-string16 GetDisplayNameForSubFolder(const string16& device_name,
-                                    const base::FilePath& sub_folder) {
-  if (sub_folder.empty())
-    return device_name;
-  return (sub_folder.BaseName().LossyDisplayName() +
-          ASCIIToUTF16(" - ") +
-          device_name);
-}
-
-string16 GetFullProductName(const string16& vendor_name,
-                            const string16& model_name) {
-  if (vendor_name.empty() && model_name.empty())
-    return string16();
-
-  string16 product_name;
-  if (vendor_name.empty())
-    product_name = model_name;
-  else if (model_name.empty())
-    product_name = vendor_name;
-  else if (!vendor_name.empty() && !model_name.empty())
-    product_name = vendor_name + UTF8ToUTF16(", ") + model_name;
-
-  return product_name;
-}
-
 }  // namespace
 
 MediaGalleriesDialogController::MediaGalleriesDialogController(
@@ -101,7 +52,7 @@
   // Passing unretained pointer is safe, since the dialog controller
   // is self-deleting, and so won't be deleted until it can be shown
   // and then closed.
-  StorageMonitor::GetInstance()->Initialize(base::Bind(
+  StorageMonitor::GetInstance()->EnsureInitialized(base::Bind(
       &MediaGalleriesDialogController::OnStorageMonitorInitialized,
       base::Unretained(this)));
 }
@@ -133,96 +84,15 @@
     select_folder_dialog_->ListenerDestroyed();
 }
 
-// static
-string16 MediaGalleriesDialogController::GetGalleryDisplayName(
-    const MediaGalleryPrefInfo& gallery) {
-  string16 name = gallery.display_name;
-  if (IsAttachedDevice(gallery.device_id)) {
-    name += ASCIIToUTF16(" ");
-    name +=
-        l10n_util::GetStringUTF16(IDS_MEDIA_GALLERIES_DIALOG_DEVICE_ATTACHED);
-  }
-  return name;
-}
-
-// TODO(gbillock): Move this function and attendant helpers somewhere else,
-// probably to StorageInfo.
-// static
-string16 MediaGalleriesDialogController::GetGalleryDisplayNameNoAttachment(
-    const MediaGalleryPrefInfo& gallery) {
-  if (!StorageInfo::IsRemovableDevice(gallery.device_id)) {
-    // For fixed storage, the name is the directory name, or, in the case
-    // of a root directory, the root directory name.
-    // TODO(gbillock): Using only the BaseName can lead to ambiguity. The
-    // tooltip resolves it. Is that enough?
-    base::FilePath path = gallery.AbsolutePath();
-    if (!gallery.display_name.empty())
-      return gallery.display_name;
-    if (path == path.DirName())
-      return path.LossyDisplayName();
-    return path.BaseName().LossyDisplayName();
-  }
-
-  string16 name = gallery.display_name;
-  if (name.empty())
-    name = gallery.volume_label;
-  if (name.empty())
-    name = GetFullProductName(gallery.vendor_name, gallery.model_name);
-  if (name.empty())
-    name = l10n_util::GetStringUTF16(IDS_MEDIA_GALLERIES_UNLABELED_DEVICE);
-
-  name = GetDisplayNameForDevice(gallery.total_size_in_bytes, name);
-
-  if (!gallery.path.empty())
-    name = GetDisplayNameForSubFolder(name, gallery.path);
-
-  return name;
-}
-
-// static
-string16 MediaGalleriesDialogController::GetGalleryTooltip(
-    const MediaGalleryPrefInfo& gallery) {
-  return gallery.AbsolutePath().LossyDisplayName();
-}
-
-// static
-bool MediaGalleriesDialogController::GetGalleryAttached(
-    const MediaGalleryPrefInfo& gallery) {
-  return !StorageInfo::IsRemovableDevice(gallery.device_id) ||
-         IsAttachedDevice(gallery.device_id);
-}
-
-// static
-string16 MediaGalleriesDialogController::GetGalleryAdditionalDetails(
-    const MediaGalleryPrefInfo& gallery) {
-  string16 attached;
-  if (StorageInfo::IsRemovableDevice(gallery.device_id)) {
-    if (IsAttachedDevice(gallery.device_id)) {
-      attached = l10n_util::GetStringUTF16(
-          IDS_MEDIA_GALLERIES_DIALOG_DEVICE_ATTACHED);
-    } else if (!gallery.last_attach_time.is_null()) {
-      attached = l10n_util::GetStringFUTF16(
-          IDS_MEDIA_GALLERIES_LAST_ATTACHED,
-          base::TimeFormatShortDateNumeric(gallery.last_attach_time));
-    } else {
-      attached = l10n_util::GetStringUTF16(
-          IDS_MEDIA_GALLERIES_DIALOG_DEVICE_NOT_ATTACHED);
-    }
-  }
-
-  // TODO(gbillock): This is a placeholder. Need to actually get the
-  // right text here.
-  return attached;
-}
-
 string16 MediaGalleriesDialogController::GetHeader() const {
   return l10n_util::GetStringUTF16(IDS_MEDIA_GALLERIES_DIALOG_HEADER);
 }
 
 string16 MediaGalleriesDialogController::GetSubtext() const {
   std::string extension_name(extension_ ? extension_->name() : std::string());
-  return l10n_util::GetStringFUTF16(IDS_MEDIA_GALLERIES_DIALOG_SUBTEXT,
-                                    UTF8ToUTF16(extension_name));
+  return l10n_util::GetStringFUTF16(
+      IDS_MEDIA_GALLERIES_DIALOG_SUBTEXT_READ_ONLY,
+      UTF8ToUTF16(extension_name));
 }
 
 string16 MediaGalleriesDialogController::GetUnattachedLocationsHeader() const {
@@ -252,15 +122,15 @@
     const {
   for (KnownGalleryPermissions::const_iterator iter = known_galleries_.begin();
        iter != known_galleries_.end(); ++iter) {
-    if ((attached && GetGalleryAttached(iter->second.pref_info)) ||
-        (!attached && !GetGalleryAttached(iter->second.pref_info))) {
+    if ((attached && iter->second.pref_info.IsGalleryAvailable()) ||
+        (!attached && !iter->second.pref_info.IsGalleryAvailable())) {
       permissions->push_back(iter->second);
     }
   }
   for (GalleryPermissionsVector::const_iterator iter = new_galleries_.begin();
        iter != new_galleries_.end(); ++iter) {
-    if ((attached && GetGalleryAttached(iter->pref_info)) ||
-        (!attached && !GetGalleryAttached(iter->pref_info))) {
+    if ((attached && iter->pref_info.IsGalleryAvailable()) ||
+        (!attached && !iter->pref_info.IsGalleryAvailable())) {
       permissions->push_back(*iter);
     }
   }
diff --git a/chrome/browser/media_galleries/media_galleries_dialog_controller.h b/chrome/browser/media_galleries/media_galleries_dialog_controller.h
index b6bc2a2..c6d4d3b 100644
--- a/chrome/browser/media_galleries/media_galleries_dialog_controller.h
+++ b/chrome/browser/media_galleries/media_galleries_dialog_controller.h
@@ -72,17 +72,6 @@
                                  const extensions::Extension& extension,
                                  const base::Closure& on_finish);
 
-  // Called by the view to provide details for a particular gallery
-  // permission entry.
-  static string16 GetGalleryDisplayName(
-      const MediaGalleryPrefInfo& gallery);
-  static string16 GetGalleryDisplayNameNoAttachment(
-      const MediaGalleryPrefInfo& gallery);
-  static string16 GetGalleryTooltip(const MediaGalleryPrefInfo& gallery);
-  static bool GetGalleryAttached(const MediaGalleryPrefInfo& gallery);
-  static string16 GetGalleryAdditionalDetails(
-      const MediaGalleryPrefInfo& gallery);
-
   // The title of the dialog view.
   string16 GetHeader() const;
 
diff --git a/chrome/browser/media_galleries/media_galleries_dialog_controller_unittest.cc b/chrome/browser/media_galleries/media_galleries_dialog_controller_unittest.cc
index 33a354e..890750e 100644
--- a/chrome/browser/media_galleries/media_galleries_dialog_controller_unittest.cc
+++ b/chrome/browser/media_galleries/media_galleries_dialog_controller_unittest.cc
@@ -3,8 +3,8 @@
 // found in the LICENSE file.
 
 #include "base/files/file_path.h"
-#include "base/string_util.h"
 #include "base/strings/string16.h"
+#include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/media_galleries/media_galleries_dialog_controller.h"
 #include "chrome/browser/media_galleries/media_galleries_preferences.h"
@@ -12,10 +12,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 std::string GalleryName(const chrome::MediaGalleryPrefInfo& gallery) {
-  using chrome::MediaGalleriesDialogController;
-  string16 name =
-      MediaGalleriesDialogController::GetGalleryDisplayNameNoAttachment(
-          gallery);
+  string16 name = gallery.GetGalleryDisplayName();
   return UTF16ToASCII(name);
 }
 
diff --git a/chrome/browser/media_galleries/media_galleries_preferences.cc b/chrome/browser/media_galleries/media_galleries_preferences.cc
index 3843d58..451b617 100644
--- a/chrome/browser/media_galleries/media_galleries_preferences.cc
+++ b/chrome/browser/media_galleries/media_galleries_preferences.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/media_galleries/media_galleries_preferences.h"
 
+#include "base/i18n/time_formatting.h"
 #include "base/path_service.h"
 #include "base/prefs/pref_service.h"
 #include "base/stl_util.h"
@@ -30,6 +31,9 @@
 #include "chrome/common/extensions/permissions/permissions_data.h"
 #include "chrome/common/pref_names.h"
 #include "components/user_prefs/pref_registry_syncable.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/text/bytes_formatting.h"
 
 using base::DictionaryValue;
 using base::ListValue;
@@ -217,6 +221,40 @@
   return false;
 }
 
+string16 GetDisplayNameForDevice(uint64 storage_size_in_bytes,
+                                 const string16& name) {
+  DCHECK(!name.empty());
+  return (storage_size_in_bytes == 0) ?
+      name : ui::FormatBytes(storage_size_in_bytes) + ASCIIToUTF16(" ") + name;
+}
+
+// For a device with |device_name| and a relative path |sub_folder|, construct
+// a display name. If |sub_folder| is empty, then just return |device_name|.
+string16 GetDisplayNameForSubFolder(const string16& device_name,
+                                    const base::FilePath& sub_folder) {
+  if (sub_folder.empty())
+    return device_name;
+  return (sub_folder.BaseName().LossyDisplayName() +
+          ASCIIToUTF16(" - ") +
+          device_name);
+}
+
+string16 GetFullProductName(const string16& vendor_name,
+                            const string16& model_name) {
+  if (vendor_name.empty() && model_name.empty())
+    return string16();
+
+  string16 product_name;
+  if (vendor_name.empty())
+    product_name = model_name;
+  else if (model_name.empty())
+    product_name = vendor_name;
+  else if (!vendor_name.empty() && !model_name.empty())
+    product_name = vendor_name + UTF8ToUTF16(", ") + model_name;
+
+  return product_name;
+}
+
 }  // namespace
 
 MediaGalleryPrefInfo::MediaGalleryPrefInfo()
@@ -235,6 +273,64 @@
   return base_path.empty() ? base_path : base_path.Append(path);
 }
 
+string16 MediaGalleryPrefInfo::GetGalleryDisplayName() const {
+  if (!StorageInfo::IsRemovableDevice(device_id)) {
+    // For fixed storage, the name is the directory name, or, in the case
+    // of a root directory, the root directory name.
+    // TODO(gbillock): Using only the BaseName can lead to ambiguity. The
+    // tooltip resolves it. Is that enough?
+    base::FilePath path = AbsolutePath();
+    if (!display_name.empty())
+      return display_name;
+    if (path == path.DirName())
+      return path.LossyDisplayName();
+    return path.BaseName().LossyDisplayName();
+  }
+
+  string16 name = display_name;
+  if (name.empty())
+    name = volume_label;
+  if (name.empty())
+    name = GetFullProductName(vendor_name, model_name);
+  if (name.empty())
+    name = l10n_util::GetStringUTF16(IDS_MEDIA_GALLERIES_UNLABELED_DEVICE);
+
+  name = GetDisplayNameForDevice(total_size_in_bytes, name);
+
+  if (!path.empty())
+    name = GetDisplayNameForSubFolder(name, path);
+
+  return name;
+}
+
+string16 MediaGalleryPrefInfo::GetGalleryTooltip() const {
+  return AbsolutePath().LossyDisplayName();
+}
+
+string16 MediaGalleryPrefInfo::GetGalleryAdditionalDetails() const {
+  string16 attached;
+  if (StorageInfo::IsRemovableDevice(device_id)) {
+    if (MediaStorageUtil::IsRemovableStorageAttached(device_id)) {
+      attached = l10n_util::GetStringUTF16(
+          IDS_MEDIA_GALLERIES_DIALOG_DEVICE_ATTACHED);
+    } else if (!last_attach_time.is_null()) {
+      attached = l10n_util::GetStringFUTF16(
+          IDS_MEDIA_GALLERIES_LAST_ATTACHED,
+          base::TimeFormatShortDateNumeric(last_attach_time));
+    } else {
+      attached = l10n_util::GetStringUTF16(
+          IDS_MEDIA_GALLERIES_DIALOG_DEVICE_NOT_ATTACHED);
+    }
+  }
+
+  return attached;
+}
+
+bool MediaGalleryPrefInfo::IsGalleryAvailable() const {
+  return !StorageInfo::IsRemovableDevice(device_id) ||
+         MediaStorageUtil::IsRemovableStorageAttached(device_id);
+}
+
 MediaGalleriesPreferences::GalleryChangeObserver::~GalleryChangeObserver() {}
 
 MediaGalleriesPreferences::MediaGalleriesPreferences(Profile* profile)
diff --git a/chrome/browser/media_galleries/media_galleries_preferences.h b/chrome/browser/media_galleries/media_galleries_preferences.h
index 3d3cb4d..f15dc9b 100644
--- a/chrome/browser/media_galleries/media_galleries_preferences.h
+++ b/chrome/browser/media_galleries/media_galleries_preferences.h
@@ -14,7 +14,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "base/strings/string16.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/storage_monitor/removable_storage_observer.h"
 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
 
@@ -103,6 +103,15 @@
   // 1 if the display_name is only set externally when it is overriding
   // the name constructed from volume metadata.
   int prefs_version;
+
+  // Called by views to provide details for the gallery permission entries.
+  string16 GetGalleryDisplayName() const;
+  string16 GetGalleryTooltip() const;
+  string16 GetGalleryAdditionalDetails() const;
+
+  // Returns true if the gallery is currently a removable device gallery which
+  // is now attached, or a fixed storage gallery.
+  bool IsGalleryAvailable() const;
 };
 
 typedef std::map<MediaGalleryPrefId, MediaGalleryPrefInfo>
diff --git a/chrome/browser/media_galleries/media_galleries_preferences_unittest.cc b/chrome/browser/media_galleries/media_galleries_preferences_unittest.cc
index 9239aab..e4c208c 100644
--- a/chrome/browser/media_galleries/media_galleries_preferences_unittest.cc
+++ b/chrome/browser/media_galleries/media_galleries_preferences_unittest.cc
@@ -23,8 +23,10 @@
 #include "chrome/common/extensions/extension.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/test/test_browser_thread.h"
+#include "grit/generated_resources.h"
 #include "sync/api/string_ordinal.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/l10n/l10n_util.h"
 
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/login/user_manager.h"
@@ -809,4 +811,46 @@
   EXPECT_FALSE(UpdateDeviceIDForSingletonType(new_device_id));
 }
 
+TEST(MediaGalleryPrefInfoTest, NameGeneration) {
+  test::TestStorageMonitor monitor;
+
+  MediaGalleryPrefInfo info;
+  info.pref_id = 1;
+  info.display_name = ASCIIToUTF16("override");
+  info.device_id = StorageInfo::MakeDeviceId(
+      StorageInfo::REMOVABLE_MASS_STORAGE_WITH_DCIM, "unique");
+
+  EXPECT_EQ(ASCIIToUTF16("override"), info.GetGalleryDisplayName());
+
+  info.display_name = ASCIIToUTF16("o2");
+  EXPECT_EQ(ASCIIToUTF16("o2"), info.GetGalleryDisplayName());
+
+  EXPECT_EQ(l10n_util::GetStringUTF16(
+                IDS_MEDIA_GALLERIES_DIALOG_DEVICE_NOT_ATTACHED),
+            info.GetGalleryAdditionalDetails());
+
+  info.last_attach_time = base::Time::Now();
+  EXPECT_NE(l10n_util::GetStringUTF16(
+                IDS_MEDIA_GALLERIES_DIALOG_DEVICE_NOT_ATTACHED),
+            info.GetGalleryAdditionalDetails());
+  EXPECT_NE(l10n_util::GetStringUTF16(
+                IDS_MEDIA_GALLERIES_DIALOG_DEVICE_ATTACHED),
+            info.GetGalleryAdditionalDetails());
+
+  info.volume_label = ASCIIToUTF16("vol");
+  info.vendor_name = ASCIIToUTF16("vendor");
+  info.model_name = ASCIIToUTF16("model");
+  EXPECT_EQ(ASCIIToUTF16("o2"), info.GetGalleryDisplayName());
+
+  info.display_name = string16();
+  EXPECT_EQ(ASCIIToUTF16("vol"), info.GetGalleryDisplayName());
+  info.volume_label = string16();
+  EXPECT_EQ(ASCIIToUTF16("vendor, model"), info.GetGalleryDisplayName());
+
+  info.device_id = StorageInfo::MakeDeviceId(
+      StorageInfo::FIXED_MASS_STORAGE, "unique");
+  EXPECT_EQ(base::FilePath(FILE_PATH_LITERAL("unique")).AsUTF8Unsafe(),
+            UTF16ToUTF8(info.GetGalleryTooltip()));
+}
+
 }  // namespace chrome
diff --git a/chrome/browser/media_galleries/media_galleries_test_util.cc b/chrome/browser/media_galleries/media_galleries_test_util.cc
index a3e42fb..c73a5be 100644
--- a/chrome/browser/media_galleries/media_galleries_test_util.cc
+++ b/chrome/browser/media_galleries/media_galleries_test_util.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/media_galleries/media_galleries_test_util.h"
 
+#include "base/base_paths.h"
 #include "base/file_util.h"
 #include "base/files/file_path.h"
 #include "base/path_service.h"
@@ -71,35 +72,30 @@
   Init();
 }
 
+EnsureMediaDirectoriesExists::~EnsureMediaDirectoriesExists() {
+}
+
 void EnsureMediaDirectoriesExists::Init() {
 #if defined(OS_CHROMEOS) || defined(OS_ANDROID)
   return;
 #else
+
   ASSERT_TRUE(fake_dir_.CreateUniqueTempDir());
 
-  const int kDirectoryKeys[] = {
-    chrome::DIR_USER_MUSIC,
-    chrome::DIR_USER_PICTURES,
-    chrome::DIR_USER_VIDEOS,
-  };
+#if defined(OS_WIN) || defined(OS_MACOSX)
+  // This is to make sure the tests don't think iTunes is installed (unless
+  // we control it specifically).
+  appdir_override_.reset(new base::ScopedPathOverride(
+      base::DIR_APP_DATA, fake_dir_.path().AppendASCII("itunes")));
+#endif
 
-  const char* kDirectoryNames[] = {
-    "music",
-    "pictures",
-    "videos",
-  };
-
-  for (size_t i = 0; i < arraysize(kDirectoryKeys); ++i) {
-    PathService::OverrideAndCreateIfNeeded(
-        kDirectoryKeys[i], fake_dir_.path().AppendASCII(kDirectoryNames[i]),
-        true /*create*/);
-    base::FilePath path;
-    if (PathService::Get(kDirectoryKeys[i], &path) &&
-        file_util::DirectoryExists(path)) {
-      ++num_galleries_;
-    }
-  }
-  ASSERT_GT(num_galleries_, 0);
+  music_override_.reset(new base::ScopedPathOverride(
+    chrome::DIR_USER_MUSIC, fake_dir_.path().AppendASCII("music")));
+  pictures_override_.reset(new base::ScopedPathOverride(
+    chrome::DIR_USER_PICTURES, fake_dir_.path().AppendASCII("pictures")));
+  video_override_.reset(new base::ScopedPathOverride(
+    chrome::DIR_USER_VIDEOS, fake_dir_.path().AppendASCII("videos")));
+  num_galleries_ = 3;
 #endif
 }
 
diff --git a/chrome/browser/media_galleries/media_galleries_test_util.h b/chrome/browser/media_galleries/media_galleries_test_util.h
index 3a78643..d18f722 100644
--- a/chrome/browser/media_galleries/media_galleries_test_util.h
+++ b/chrome/browser/media_galleries/media_galleries_test_util.h
@@ -8,6 +8,8 @@
 #include "base/basictypes.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/test/scoped_path_override.h"
 
 namespace extensions {
 class Extension;
@@ -25,6 +27,7 @@
 class EnsureMediaDirectoriesExists {
  public:
   EnsureMediaDirectoriesExists();
+  ~EnsureMediaDirectoriesExists();
 
   int num_galleries() const { return num_galleries_; }
 
@@ -35,6 +38,11 @@
 
   int num_galleries_;
 
+  scoped_ptr<base::ScopedPathOverride> appdir_override_;
+  scoped_ptr<base::ScopedPathOverride> music_override_;
+  scoped_ptr<base::ScopedPathOverride> pictures_override_;
+  scoped_ptr<base::ScopedPathOverride> video_override_;
+
   DISALLOW_COPY_AND_ASSIGN(EnsureMediaDirectoriesExists);
 };
 
diff --git a/chrome/browser/media_galleries/win/mtp_device_delegate_impl_win_unittest.cc b/chrome/browser/media_galleries/win/mtp_device_delegate_impl_win_unittest.cc
new file mode 100644
index 0000000..8f7d042
--- /dev/null
+++ b/chrome/browser/media_galleries/win/mtp_device_delegate_impl_win_unittest.cc
@@ -0,0 +1,167 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <vector>
+
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/message_loop.h"
+#include "base/run_loop.h"
+#include "base/stl_util.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/extension_system.h"
+#include "chrome/browser/extensions/test_extension_system.h"
+#include "chrome/browser/media_galleries/media_file_system_registry.h"
+#include "chrome/browser/media_galleries/media_galleries_test_util.h"
+#include "chrome/browser/storage_monitor/storage_info.h"
+#include "chrome/browser/storage_monitor/storage_monitor.h"
+#include "chrome/browser/storage_monitor/test_portable_device_watcher_win.h"
+#include "chrome/browser/storage_monitor/test_storage_monitor_win.h"
+#include "chrome/browser/storage_monitor/test_volume_mount_watcher_win.h"
+#include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "chrome/test/base/testing_profile.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/web_contents.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chrome {
+
+namespace {
+
+typedef std::map<MediaGalleryPrefId, MediaFileSystemInfo> FSInfoMap;
+
+void GetGalleryInfoCallback(
+    FSInfoMap* results,
+    const std::vector<MediaFileSystemInfo>& file_systems) {
+  for (size_t i = 0; i < file_systems.size(); ++i) {
+    ASSERT_FALSE(ContainsKey(*results, file_systems[i].pref_id));
+    (*results)[file_systems[i].pref_id] = file_systems[i];
+  }
+}
+
+}  // namespace
+
+class MTPDeviceDelegateImplWinTest : public ChromeRenderViewHostTestHarness {
+ protected:
+  void SetUp() OVERRIDE;
+  void TearDown() OVERRIDE;
+
+  void ProcessAttach(const std::string& id,
+                     const string16& name,
+                     const base::FilePath::StringType& location);
+  std::string AttachDevice(StorageInfo::Type type,
+                           const std::string& unique_id,
+                           const base::FilePath& location);
+  void CheckGalleryInfo(const MediaFileSystemInfo& info,
+                        const string16& name,
+                        const base::FilePath& path,
+                        bool removable,
+                        bool media_device);
+
+  // Note: need to make this weak ptr once ownership moves to g_browser_process
+  scoped_ptr<test::TestStorageMonitorWin> monitor_;
+  scoped_refptr<extensions::Extension> extension_;
+
+  EnsureMediaDirectoriesExists media_directories_;
+};
+
+void MTPDeviceDelegateImplWinTest::SetUp() {
+  ChromeRenderViewHostTestHarness::SetUp();
+  test::TestPortableDeviceWatcherWin* portable_device_watcher =
+      new test::TestPortableDeviceWatcherWin;
+  test::TestVolumeMountWatcherWin* mount_watcher =
+      new test::TestVolumeMountWatcherWin;
+  portable_device_watcher->set_use_dummy_mtp_storage_info(true);
+  monitor_.reset(new test::TestStorageMonitorWin(
+      mount_watcher, portable_device_watcher));
+  base::RunLoop runloop;
+  monitor_->EnsureInitialized(runloop.QuitClosure());
+  runloop.Run();
+
+  extensions::TestExtensionSystem* extension_system(
+      static_cast<extensions::TestExtensionSystem*>(
+          extensions::ExtensionSystem::Get(profile())));
+  extension_system->CreateExtensionService(
+      CommandLine::ForCurrentProcess(), base::FilePath(), false);
+
+  std::vector<std::string> all_permissions;
+  all_permissions.push_back("allAutoDetected");
+  all_permissions.push_back("read");
+  extension_ = AddMediaGalleriesApp("all", all_permissions, profile());
+}
+
+void MTPDeviceDelegateImplWinTest::TearDown() {
+  monitor_.reset();
+
+  ChromeRenderViewHostTestHarness::TearDown();
+}
+
+void MTPDeviceDelegateImplWinTest::ProcessAttach(
+    const std::string& id,
+    const string16& label,
+    const base::FilePath::StringType& location) {
+  StorageInfo info(id, string16(), location, label, string16(), string16(), 0);
+  monitor_->receiver()->ProcessAttach(info);
+}
+
+std::string MTPDeviceDelegateImplWinTest::AttachDevice(
+    StorageInfo::Type type,
+    const std::string& unique_id,
+    const base::FilePath& location) {
+  std::string device_id = StorageInfo::MakeDeviceId(type, unique_id);
+  DCHECK(StorageInfo::IsRemovableDevice(device_id));
+  string16 label = location.LossyDisplayName();
+  ProcessAttach(device_id, label, location.value());
+  base::RunLoop().RunUntilIdle();
+  return device_id;
+}
+
+void MTPDeviceDelegateImplWinTest::CheckGalleryInfo(
+    const MediaFileSystemInfo& info,
+    const string16& name,
+    const base::FilePath& path,
+    bool removable,
+    bool media_device) {
+  EXPECT_EQ(name, info.name);
+  EXPECT_EQ(path, info.path);
+  EXPECT_EQ(removable, info.removable);
+  EXPECT_EQ(media_device, info.media_device);
+  EXPECT_NE(0UL, info.pref_id);
+
+  if (removable)
+    EXPECT_NE(0UL, info.transient_device_id.size());
+  else
+    EXPECT_EQ(0UL, info.transient_device_id.size());
+}
+
+TEST_F(MTPDeviceDelegateImplWinTest, GalleryNameMTP) {
+  base::FilePath location(
+      PortableDeviceWatcherWin::GetStoragePathFromStorageId(
+          test::TestPortableDeviceWatcherWin::kStorageUniqueIdA));
+  AttachDevice(StorageInfo::MTP_OR_PTP, "mtp_fake_id", location);
+
+  content::RenderViewHost* rvh = web_contents()->GetRenderViewHost();
+  FSInfoMap results;
+  MediaFileSystemRegistry* registry =
+      g_browser_process->media_file_system_registry();
+  registry->GetMediaFileSystemsForExtension(
+      rvh, extension_.get(),
+      base::Bind(&GetGalleryInfoCallback, base::Unretained(&results)));
+  base::RunLoop().RunUntilIdle();
+
+  ASSERT_EQ(media_directories_.num_galleries() + 1, results.size());
+  bool checked = false;
+  for (FSInfoMap::iterator i = results.begin(); i != results.end(); ++i) {
+    MediaFileSystemInfo info = i->second;
+    if (info.path == location) {
+      CheckGalleryInfo(info, location.LossyDisplayName(), location, true, true);
+      checked = true;
+      break;
+    }
+  }
+  EXPECT_TRUE(checked);
+}
+
+}  // namespace chrome
diff --git a/chrome/browser/media_galleries/win/mtp_device_object_entry.h b/chrome/browser/media_galleries/win/mtp_device_object_entry.h
index 4f80946..e9a5e64 100644
--- a/chrome/browser/media_galleries/win/mtp_device_object_entry.h
+++ b/chrome/browser/media_galleries/win/mtp_device_object_entry.h
@@ -9,7 +9,7 @@
 
 #include "base/basictypes.h"
 #include "base/strings/string16.h"
-#include "base/time.h"
+#include "base/time/time.h"
 
 namespace chrome {
 
diff --git a/chrome/browser/media_galleries/win/mtp_device_object_enumerator.h b/chrome/browser/media_galleries/win/mtp_device_object_enumerator.h
index 840a911..3287715 100644
--- a/chrome/browser/media_galleries/win/mtp_device_object_enumerator.h
+++ b/chrome/browser/media_galleries/win/mtp_device_object_enumerator.h
@@ -10,7 +10,7 @@
 
 #include "base/files/file_path.h"
 #include "base/threading/thread_checker.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/media_galleries/win/mtp_device_object_entry.h"
 #include "webkit/browser/fileapi/file_system_file_util.h"
 
diff --git a/chrome/browser/media_galleries/win/mtp_device_object_enumerator_unittest.cc b/chrome/browser/media_galleries/win/mtp_device_object_enumerator_unittest.cc
index 8f1f85b..24f5a55 100644
--- a/chrome/browser/media_galleries/win/mtp_device_object_enumerator_unittest.cc
+++ b/chrome/browser/media_galleries/win/mtp_device_object_enumerator_unittest.cc
@@ -10,7 +10,7 @@
 
 #include "base/basictypes.h"
 #include "base/strings/string16.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/media_galleries/win/mtp_device_object_entry.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/chrome/browser/media_galleries/win/mtp_device_operations_util.cc b/chrome/browser/media_galleries/win/mtp_device_operations_util.cc
index afe4af5..cb59d1a 100644
--- a/chrome/browser/media_galleries/win/mtp_device_operations_util.cc
+++ b/chrome/browser/media_galleries/win/mtp_device_operations_util.cc
@@ -15,7 +15,7 @@
 #include "base/safe_numerics.h"
 #include "base/strings/string_util.h"
 #include "base/threading/thread_restrictions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/win/scoped_co_mem.h"
 #include "base/win/scoped_propvariant.h"
 #include "chrome/browser/storage_monitor/removable_device_constants.h"
diff --git a/chrome/browser/memory_details.cc b/chrome/browser/memory_details.cc
index 716974a..8274960 100644
--- a/chrome/browser/memory_details.cc
+++ b/chrome/browser/memory_details.cc
@@ -214,11 +214,10 @@
     ProcessMemoryInformation& process =
         chrome_browser->processes[index];
 
-    for (content::RenderProcessHost::iterator renderer_iter(
-            content::RenderProcessHost::AllHostsIterator());
-         !renderer_iter.IsAtEnd(); renderer_iter.Advance()) {
+    RenderWidgetHost::List widgets = RenderWidgetHost::GetRenderWidgetHosts();
+    for (size_t i = 0; i < widgets.size(); ++i) {
       content::RenderProcessHost* render_process_host =
-          renderer_iter.GetCurrentValue();
+          widgets[i]->GetProcess();
       DCHECK(render_process_host);
       // Ignore processes that don't have a connection, such as crashed tabs.
       if (!render_process_host->HasConnection() ||
@@ -238,110 +237,104 @@
       // The RenderProcessHost may host multiple WebContentses.  Any
       // of them which contain diagnostics information make the whole
       // process be considered a diagnostics process.
-      content::RenderProcessHost::RenderWidgetHostsIterator iter(
-          render_process_host->GetRenderWidgetHostsIterator());
-      for (; !iter.IsAtEnd(); iter.Advance()) {
-        const RenderWidgetHost* widget = iter.GetCurrentValue();
-        DCHECK(widget);
-        if (!widget || !widget->IsRenderView())
-          continue;
+      if (!widgets[i]->IsRenderView())
+        continue;
 
-        RenderViewHost* host =
-            RenderViewHost::From(const_cast<RenderWidgetHost*>(widget));
-        WebContents* contents = WebContents::FromRenderViewHost(host);
-        GURL url;
-        if (contents) {
-          url = contents->GetURL();
-          SiteData* site_data =
-              &chrome_browser->site_data[contents->GetBrowserContext()];
-          SiteDetails::CollectSiteInfo(contents, site_data);
-        }
-        extensions::ViewType type = extensions::GetViewType(contents);
-        if (host->GetEnabledBindings() & content::BINDINGS_POLICY_WEB_UI) {
-          process.renderer_type = ProcessMemoryInformation::RENDERER_CHROME;
-        } else if (extension_process_map &&
-            extension_process_map->Contains(host->GetProcess()->GetID())) {
-          // For our purposes, don't count processes containing only hosted apps
-          // as extension processes. See also: crbug.com/102533.
-          std::set<std::string> extension_ids =
-              extension_process_map->GetExtensionsInProcess(
-                  host->GetProcess()->GetID());
-          for (std::set<std::string>::iterator iter = extension_ids.begin();
-               iter != extension_ids.end(); ++iter) {
-            const Extension* extension =
-                extension_service->GetExtensionById(*iter, false);
-            if (extension && !extension->is_hosted_app()) {
-              process.renderer_type =
-                  ProcessMemoryInformation::RENDERER_EXTENSION;
-              break;
-            }
-          }
-        }
-        if (extension_process_map &&
-            extension_process_map->Contains(host->GetProcess()->GetID())) {
+      RenderViewHost* host = RenderViewHost::From(widgets[i]);
+      WebContents* contents = WebContents::FromRenderViewHost(host);
+      GURL url;
+      if (contents) {
+        url = contents->GetURL();
+        SiteData* site_data =
+            &chrome_browser->site_data[contents->GetBrowserContext()];
+        SiteDetails::CollectSiteInfo(contents, site_data);
+      }
+      extensions::ViewType type = extensions::GetViewType(contents);
+      if (host->GetEnabledBindings() & content::BINDINGS_POLICY_WEB_UI) {
+        process.renderer_type = ProcessMemoryInformation::RENDERER_CHROME;
+      } else if (extension_process_map &&
+                 extension_process_map->Contains(host->GetProcess()->GetID())) {
+        // For our purposes, don't count processes containing only hosted apps
+        // as extension processes. See also: crbug.com/102533.
+        std::set<std::string> extension_ids =
+            extension_process_map->GetExtensionsInProcess(
+            host->GetProcess()->GetID());
+        for (std::set<std::string>::iterator iter = extension_ids.begin();
+             iter != extension_ids.end(); ++iter) {
           const Extension* extension =
-              extension_service->extensions()->GetByID(url.host());
-          if (extension) {
-            string16 title = UTF8ToUTF16(extension->name());
-            process.titles.push_back(title);
+              extension_service->GetExtensionById(*iter, false);
+          if (extension && !extension->is_hosted_app()) {
             process.renderer_type =
                 ProcessMemoryInformation::RENDERER_EXTENSION;
-            continue;
+            break;
           }
         }
-
-        if (!contents) {
+      }
+      if (extension_process_map &&
+          extension_process_map->Contains(host->GetProcess()->GetID())) {
+        const Extension* extension =
+            extension_service->extensions()->GetByID(url.host());
+        if (extension) {
+          string16 title = UTF8ToUTF16(extension->name());
+          process.titles.push_back(title);
           process.renderer_type =
-                ProcessMemoryInformation::RENDERER_INTERSTITIAL;
+              ProcessMemoryInformation::RENDERER_EXTENSION;
           continue;
         }
+      }
 
-        if (type == extensions::VIEW_TYPE_BACKGROUND_CONTENTS) {
-          process.titles.push_back(UTF8ToUTF16(url.spec()));
-          process.renderer_type =
-                    ProcessMemoryInformation::RENDERER_BACKGROUND_APP;
-          continue;
-        }
+      if (!contents) {
+        process.renderer_type =
+            ProcessMemoryInformation::RENDERER_INTERSTITIAL;
+        continue;
+      }
 
-        if (type == extensions::VIEW_TYPE_NOTIFICATION) {
-          process.titles.push_back(UTF8ToUTF16(url.spec()));
-          process.renderer_type =
-                    ProcessMemoryInformation::RENDERER_NOTIFICATION;
-          continue;
-        }
+      if (type == extensions::VIEW_TYPE_BACKGROUND_CONTENTS) {
+        process.titles.push_back(UTF8ToUTF16(url.spec()));
+        process.renderer_type =
+            ProcessMemoryInformation::RENDERER_BACKGROUND_APP;
+        continue;
+      }
 
-        // Since we have a WebContents and and the renderer type hasn't been
-        // set yet, it must be a normal tabbed renderer.
-        if (process.renderer_type == ProcessMemoryInformation::RENDERER_UNKNOWN)
-          process.renderer_type = ProcessMemoryInformation::RENDERER_NORMAL;
+      if (type == extensions::VIEW_TYPE_NOTIFICATION) {
+        process.titles.push_back(UTF8ToUTF16(url.spec()));
+        process.renderer_type =
+            ProcessMemoryInformation::RENDERER_NOTIFICATION;
+        continue;
+      }
 
-        string16 title = contents->GetTitle();
-        if (!title.length())
-          title = l10n_util::GetStringUTF16(IDS_DEFAULT_TAB_TITLE);
-        process.titles.push_back(title);
+      // Since we have a WebContents and and the renderer type hasn't been
+      // set yet, it must be a normal tabbed renderer.
+      if (process.renderer_type == ProcessMemoryInformation::RENDERER_UNKNOWN)
+        process.renderer_type = ProcessMemoryInformation::RENDERER_NORMAL;
 
-        // We need to check the pending entry as well as the virtual_url to
-        // see if it's a chrome://memory URL (we don't want to count these in
-        // the total memory usage of the browser).
-        //
-        // When we reach here, chrome://memory will be the pending entry since
-        // we haven't responded with any data such that it would be committed.
-        // If you have another chrome://memory tab open (which would be
-        // committed), we don't want to count it either, so we also check the
-        // last committed entry.
-        //
-        // Either the pending or last committed entries can be NULL.
-        const NavigationEntry* pending_entry =
-            contents->GetController().GetPendingEntry();
-        const NavigationEntry* last_committed_entry =
-            contents->GetController().GetLastCommittedEntry();
-        if ((last_committed_entry &&
-             LowerCaseEqualsASCII(last_committed_entry->GetVirtualURL().spec(),
-                                  chrome::kChromeUIMemoryURL)) ||
-            (pending_entry &&
-             LowerCaseEqualsASCII(pending_entry->GetVirtualURL().spec(),
-                                  chrome::kChromeUIMemoryURL)))
-          process.is_diagnostics = true;
+      string16 title = contents->GetTitle();
+      if (!title.length())
+        title = l10n_util::GetStringUTF16(IDS_DEFAULT_TAB_TITLE);
+      process.titles.push_back(title);
+
+      // We need to check the pending entry as well as the virtual_url to
+      // see if it's a chrome://memory URL (we don't want to count these in
+      // the total memory usage of the browser).
+      //
+      // When we reach here, chrome://memory will be the pending entry since
+      // we haven't responded with any data such that it would be committed.
+      // If you have another chrome://memory tab open (which would be
+      // committed), we don't want to count it either, so we also check the
+      // last committed entry.
+      //
+      // Either the pending or last committed entries can be NULL.
+      const NavigationEntry* pending_entry =
+          contents->GetController().GetPendingEntry();
+      const NavigationEntry* last_committed_entry =
+          contents->GetController().GetLastCommittedEntry();
+      if ((last_committed_entry &&
+           LowerCaseEqualsASCII(last_committed_entry->GetVirtualURL().spec(),
+                                chrome::kChromeUIMemoryURL)) ||
+          (pending_entry &&
+           LowerCaseEqualsASCII(pending_entry->GetVirtualURL().spec(),
+                                chrome::kChromeUIMemoryURL))) {
+        process.is_diagnostics = true;
       }
     }
 
diff --git a/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc b/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc
index 90f3855..7e50792 100644
--- a/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc
+++ b/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc
@@ -11,7 +11,7 @@
 #include "base/cpu.h"
 #include "base/metrics/histogram.h"
 #include "base/threading/sequenced_worker_pool.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/about_flags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_browser_main.h"
diff --git a/chrome/browser/metrics/metrics_log.cc b/chrome/browser/metrics/metrics_log.cc
index 75c68f1..bc8a7e7 100644
--- a/chrome/browser/metrics/metrics_log.cc
+++ b/chrome/browser/metrics/metrics_log.cc
@@ -21,7 +21,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/sys_info.h"
 #include "base/third_party/nspr/prtime.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/tracked_objects.h"
 #include "chrome/browser/autocomplete/autocomplete_input.h"
 #include "chrome/browser/autocomplete/autocomplete_match.h"
@@ -46,9 +46,9 @@
 #include "device/bluetooth/bluetooth_adapter.h"
 #include "device/bluetooth/bluetooth_adapter_factory.h"
 #include "device/bluetooth/bluetooth_device.h"
-#include "googleurl/src/gurl.h"
 #include "gpu/config/gpu_info.h"
 #include "ui/gfx/screen.h"
+#include "url/gurl.h"
 #include "webkit/plugins/webplugininfo.h"
 
 #if defined(OS_ANDROID)
@@ -165,8 +165,6 @@
       return ProfilerEventProto::TrackedObject::PPAPI_PLUGIN;
     case content::PROCESS_TYPE_PPAPI_BROKER:
       return ProfilerEventProto::TrackedObject::PPAPI_BROKER;
-    case PROCESS_TYPE_PROFILE_IMPORT:
-      return ProfilerEventProto::TrackedObject::PROFILE_IMPORT;
     case PROCESS_TYPE_NACL_LOADER:
       return ProfilerEventProto::TrackedObject::NACL_LOADER;
     case PROCESS_TYPE_NACL_BROKER:
@@ -420,8 +418,6 @@
   OPEN_ELEMENT_FOR_SCOPE("profile");
   WriteCommonEventAttributes();
 
-  WriteInstallElement();
-
   {
     OPEN_ELEMENT_FOR_SCOPE("stability");  // Minimal set of stability elements.
     WriteRequiredStabilityAttributes(pref);
@@ -688,56 +684,21 @@
 }
 
 void MetricsLog::WritePluginList(
-    const std::vector<webkit::WebPluginInfo>& plugin_list,
-    bool write_as_xml) {
+    const std::vector<webkit::WebPluginInfo>& plugin_list) {
   DCHECK(!locked());
 
-  OPEN_ELEMENT_FOR_SCOPE("plugins");
-
 #if defined(ENABLE_PLUGINS)
   PluginPrefs* plugin_prefs = GetPluginPrefs();
   SystemProfileProto* system_profile = uma_proto()->mutable_system_profile();
   for (std::vector<webkit::WebPluginInfo>::const_iterator iter =
            plugin_list.begin();
        iter != plugin_list.end(); ++iter) {
-    if (write_as_xml) {
-      std::string base64_name_hash;
-      uint64 numeric_hash_ignored;
-      CreateHashes(UTF16ToUTF8(iter->name), &base64_name_hash,
-                   &numeric_hash_ignored);
-
-      std::string filename_bytes = iter->path.BaseName().AsUTF8Unsafe();
-      std::string base64_filename_hash;
-      CreateHashes(filename_bytes, &base64_filename_hash,
-                   &numeric_hash_ignored);
-
-      // Write the XML version.
-      OPEN_ELEMENT_FOR_SCOPE("plugin");
-
-      // Plugin name and filename are hashed for the privacy of those
-      // testing unreleased new extensions.
-      WriteAttribute("name", base64_name_hash);
-      WriteAttribute("filename", base64_filename_hash);
-      WriteAttribute("version", UTF16ToUTF8(iter->version));
-      if (plugin_prefs)
-        WriteIntAttribute("disabled", !plugin_prefs->IsPluginEnabled(*iter));
-    } else {
-      // Write the protobuf version.
-      SystemProfileProto::Plugin* plugin = system_profile->add_plugin();
-      SetPluginInfo(*iter, plugin_prefs, plugin);
-    }
+    SystemProfileProto::Plugin* plugin = system_profile->add_plugin();
+    SetPluginInfo(*iter, plugin_prefs, plugin);
   }
 #endif  // defined(ENABLE_PLUGINS)
 }
 
-void MetricsLog::WriteInstallElement() {
-  // Write the XML version.
-  // We'll write the protobuf version in RecordEnvironmentProto().
-  OPEN_ELEMENT_FOR_SCOPE("install");
-  WriteAttribute("installdate", GetMetricsEnabledDate(GetPrefService()));
-  WriteIntAttribute("buildid", 0);  // We're using appversion instead.
-}
-
 void MetricsLog::RecordEnvironment(
          const std::vector<webkit::WebPluginInfo>& plugin_list,
          const GoogleUpdateMetrics& google_update_metrics,
@@ -749,13 +710,6 @@
   OPEN_ELEMENT_FOR_SCOPE("profile");
   WriteCommonEventAttributes();
 
-  WriteInstallElement();
-
-  // Write the XML version.
-  // We'll write the protobuf version in RecordEnvironmentProto().
-  bool write_as_xml = true;
-  WritePluginList(plugin_list, write_as_xml);
-
   WriteStabilityElement(plugin_list, pref);
 
   {
@@ -912,8 +866,7 @@
 
   WriteGoogleUpdateProto(google_update_metrics);
 
-  bool write_as_xml = false;
-  WritePluginList(plugin_list, write_as_xml);
+  WritePluginList(plugin_list);
 
   std::vector<ActiveGroupId> field_trial_ids;
   GetFieldTrialIds(&field_trial_ids);
@@ -1020,55 +973,10 @@
 void MetricsLog::RecordOmniboxOpenedURL(const OmniboxLog& log) {
   DCHECK(!locked());
 
-  // Write the XML version.
-  OPEN_ELEMENT_FOR_SCOPE("uielement");
-  WriteAttribute("action", "autocomplete");
-  WriteAttribute("targetidhash", std::string());
-  // TODO(kochi): Properly track windows.
-  WriteIntAttribute("window", 0);
-  if (log.tab_id != -1) {
-    // If we know what tab the autocomplete URL was opened in, log it.
-    WriteIntAttribute("tab", static_cast<int>(log.tab_id));
-  }
-  WriteCommonEventAttributes();
-
   std::vector<string16> terms;
   const int num_terms =
       static_cast<int>(Tokenize(log.text, kWhitespaceUTF16, &terms));
-  {
-    OPEN_ELEMENT_FOR_SCOPE("autocomplete");
 
-    WriteIntAttribute("typedlength", static_cast<int>(log.text.length()));
-    WriteIntAttribute("numterms", num_terms);
-    WriteIntAttribute("selectedindex", static_cast<int>(log.selected_index));
-    WriteIntAttribute("completedlength",
-                      log.completed_length != string16::npos ?
-                      static_cast<int>(log.completed_length) : 0);
-    if (log.elapsed_time_since_user_first_modified_omnibox !=
-        base::TimeDelta::FromMilliseconds(-1)) {
-      // Only upload the typing duration if it is set/valid.
-      WriteInt64Attribute("typingduration",
-          log.elapsed_time_since_user_first_modified_omnibox.InMilliseconds());
-    }
-    const std::string input_type(
-        AutocompleteInput::TypeToString(log.input_type));
-    if (!input_type.empty())
-      WriteAttribute("inputtype", input_type);
-
-    for (AutocompleteResult::const_iterator i(log.result.begin());
-         i != log.result.end(); ++i) {
-      OPEN_ELEMENT_FOR_SCOPE("autocompleteitem");
-      if (i->provider)
-        WriteAttribute("provider", i->provider->GetName());
-      const std::string result_type(AutocompleteMatchType::ToString(i->type));
-      if (!result_type.empty())
-        WriteAttribute("resulttype", result_type);
-      WriteIntAttribute("relevance", i->relevance);
-      WriteIntAttribute("isstarred", i->starred ? 1 : 0);
-    }
-  }
-
-  // Write the protobuf version.
   OmniboxEventProto* omnibox_event = uma_proto()->add_omnibox_event();
   omnibox_event->set_time(MetricsLogBase::GetCurrentTime());
   if (log.tab_id != -1) {
diff --git a/chrome/browser/metrics/metrics_log.h b/chrome/browser/metrics/metrics_log.h
index 303720c..86c84cc 100644
--- a/chrome/browser/metrics/metrics_log.h
+++ b/chrome/browser/metrics/metrics_log.h
@@ -170,14 +170,8 @@
   // chromium processes (ones that don't crash, and keep on running).
   void WriteRealtimeStabilityAttributes(PrefService* pref);
 
-  // Writes the list of installed plugins.  If |write_as_xml| is true, writes
-  // the XML version.  Otherwise, writes the protobuf version.
-  void WritePluginList(
-      const std::vector<webkit::WebPluginInfo>& plugin_list,
-      bool write_as_xml);
-
-  // Within the profile group, write basic install info including appversion.
-  void WriteInstallElement();
+  // Writes the list of installed plugins.
+  void WritePluginList(const std::vector<webkit::WebPluginInfo>& plugin_list);
 
   // Writes all profile metrics. This invokes WriteProfileMetrics for each key
   // in all_profiles_metrics that starts with kProfilePrefix.
diff --git a/chrome/browser/metrics/metrics_log_unittest.cc b/chrome/browser/metrics/metrics_log_unittest.cc
index b78c0d7..a319880 100644
--- a/chrome/browser/metrics/metrics_log_unittest.cc
+++ b/chrome/browser/metrics/metrics_log_unittest.cc
@@ -12,7 +12,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/sequenced_worker_pool.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/tracked_objects.h"
 #include "chrome/browser/google/google_util.h"
 #include "chrome/browser/metrics/metrics_log.h"
@@ -25,9 +25,9 @@
 #include "chrome/installer/util/google_update_settings.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/test/test_utils.h"
-#include "googleurl/src/gurl.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/gfx/size.h"
+#include "url/gurl.h"
 #include "webkit/plugins/webplugininfo.h"
 
 #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/metrics/metrics_reporting_scheduler.h b/chrome/browser/metrics/metrics_reporting_scheduler.h
index 320c41b..695f6ec 100644
--- a/chrome/browser/metrics/metrics_reporting_scheduler.h
+++ b/chrome/browser/metrics/metrics_reporting_scheduler.h
@@ -8,8 +8,8 @@
 #include "base/basictypes.h"
 #include "base/callback.h"
 #include "base/memory/weak_ptr.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 
 // Scheduler task to drive a MetricsService object's uploading.
 class MetricsReportingScheduler {
diff --git a/chrome/browser/metrics/metrics_service.cc b/chrome/browser/metrics/metrics_service.cc
index 024ec22..1a7c769 100644
--- a/chrome/browser/metrics/metrics_service.cc
+++ b/chrome/browser/metrics/metrics_service.cc
@@ -36,7 +36,7 @@
 // the MS was first constructed.  Note that even though the initial log is
 // commonly sent a full minute after startup, the initial log does not include
 // much in the way of user stats.   The most common interlog period (delay)
-// is 20 minutes. That time period starts when the first user action causes a
+// is 30 minutes. That time period starts when the first user action causes a
 // logging event.  This means that if there is no user action, there may be long
 // periods without any (ongoing) log transmissions.  Ongoing logs typically
 // contain very detailed records of user activities (ex: opened tab, closed
@@ -188,6 +188,7 @@
 #include "chrome/browser/search_engines/template_url_service.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/browser_otr_state.h"
+#include "chrome/browser/ui/search/search_tab_helper.h"
 #include "chrome/common/child_process_logging.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "chrome/common/chrome_process_type.h"
@@ -291,9 +292,9 @@
 }
 
 // The argument used to generate a non-identifying entropy source. We want no
-// more than 13 bits of entropy, so use this max to return a number between 1
-// and 2^13 = 8192 as the entropy source.
-const uint32 kMaxLowEntropySize = (1 << 13);
+// more than 13 bits of entropy, so use this max to return a number in the range
+// [0, 7999] as the entropy source (12.97 bits of entropy).
+const int kMaxLowEntropySize = 8000;
 
 // Default prefs value for prefs::kMetricsLowEntropySource to indicate that the
 // value has not yet been set.
@@ -705,9 +706,13 @@
       LogLoadComplete(type, source, details);
       break;
 
-    case content::NOTIFICATION_LOAD_START:
-      LogLoadStarted();
+    case content::NOTIFICATION_LOAD_START: {
+      content::NavigationController* controller =
+          content::Source<content::NavigationController>(source).ptr();
+      content::WebContents* web_contents = controller->GetWebContents();
+      LogLoadStarted(web_contents);
       break;
+    }
 
     case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: {
         content::RenderProcessHost::RendererClosedDetails* process_details =
@@ -1043,13 +1048,17 @@
   // Only try to load the value from prefs if the user did not request a reset.
   // Otherwise, skip to generating a new value.
   if (!command_line->HasSwitch(switches::kResetVariationState)) {
-    const int value = local_state->GetInteger(prefs::kMetricsLowEntropySource);
-    if (value != kLowEntropySourceNotSet) {
-      // Ensure the prefs value is in the range [0, kMaxLowEntropySize). Old
-      // versions of the code would generate values in the range of [1, 8192],
-      // so the below line ensures 8192 gets mapped to 0 and also guards against
-      // the case of corrupted values.
-      low_entropy_source_ = value % kMaxLowEntropySize;
+    int value = local_state->GetInteger(prefs::kMetricsLowEntropySource);
+    // Old versions of the code would generate values in the range of [1, 8192],
+    // before the range was switched to [0, 8191] and then to [0, 7999]. Map
+    // 8192 to 0, so that the 0th bucket remains uniform, while re-generating
+    // the low entropy source for old values in the [8000, 8191] range.
+    if (value == 8192)
+      value = 0;
+    // If the value is outside the [0, kMaxLowEntropySize) range, re-generate
+    // it below.
+    if (value >= 0 && value < kMaxLowEntropySize) {
+      low_entropy_source_ = value;
       UMA_HISTOGRAM_BOOLEAN("UMA.GeneratedLowEntropySource", false);
       return low_entropy_source_;
     }
@@ -1569,13 +1578,23 @@
   pref->SetInt64(path, value + 1);
 }
 
-void MetricsService::LogLoadStarted() {
+void MetricsService::LogLoadStarted(content::WebContents* web_contents) {
   content::RecordAction(content::UserMetricsAction("PageLoad"));
   HISTOGRAM_ENUMERATION("Chrome.UmaPageloadCounter", 1, 2);
   IncrementPrefValue(prefs::kStabilityPageLoadCount);
   IncrementLongPrefsValue(prefs::kUninstallMetricsPageLoadCount);
   // We need to save the prefs, as page load count is a critical stat, and it
   // might be lost due to a crash :-(.
+
+  // Track whether the page loaded is a search results page.
+  if (web_contents) {
+    SearchTabHelper* search_tab_helper =
+        SearchTabHelper::FromWebContents(web_contents);
+    if (search_tab_helper) {
+      if (search_tab_helper->model()->mode().is_search_results())
+        content::RecordAction(content::UserMetricsAction("PageLoadSRP"));
+    }
+  }
 }
 
 void MetricsService::LogRendererCrash(content::RenderProcessHost* host,
diff --git a/chrome/browser/metrics/metrics_service.h b/chrome/browser/metrics/metrics_service.h
index 365e857..52c9152 100644
--- a/chrome/browser/metrics/metrics_service.h
+++ b/chrome/browser/metrics/metrics_service.h
@@ -45,6 +45,7 @@
 
 namespace content {
 class RenderProcessHost;
+class WebContents;
 }
 
 namespace extensions {
@@ -385,8 +386,9 @@
   // buffered plugin stability statistics.
   void RecordCurrentState(PrefService* pref);
 
-  // Logs the initiation of a page load
-  void LogLoadStarted();
+  // Logs the initiation of a page load and uses |web_contents| to do
+  // additional logging of the type of page loaded.
+  void LogLoadStarted(content::WebContents* web_contents);
 
   // Records a page load notification.
   void LogLoadComplete(int type,
diff --git a/chrome/browser/metrics/metrics_service_browsertest.cc b/chrome/browser/metrics/metrics_service_browsertest.cc
index 7545615..228dbd3 100644
--- a/chrome/browser/metrics/metrics_service_browsertest.cc
+++ b/chrome/browser/metrics/metrics_service_browsertest.cc
@@ -21,9 +21,9 @@
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_types.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/net_util.h"
 #include "ui/base/window_open_disposition.h"
+#include "url/gurl.h"
 
 class MetricsServiceBrowserTest : public InProcessBrowserTest {
  public:
diff --git a/chrome/browser/metrics/perf_provider_chromeos.h b/chrome/browser/metrics/perf_provider_chromeos.h
index e3130be..6ba943e 100644
--- a/chrome/browser/metrics/perf_provider_chromeos.h
+++ b/chrome/browser/metrics/perf_provider_chromeos.h
@@ -9,8 +9,8 @@
 
 #include "base/basictypes.h"
 #include "base/threading/non_thread_safe.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "chrome/common/metrics/proto/perf_data.pb.h"
 
 namespace metrics {
diff --git a/chrome/browser/metrics/thread_watcher.h b/chrome/browser/metrics/thread_watcher.h
index 0e7fd6c..487d6de 100644
--- a/chrome/browser/metrics/thread_watcher.h
+++ b/chrome/browser/metrics/thread_watcher.h
@@ -57,7 +57,7 @@
 #include "base/threading/platform_thread.h"
 #include "base/threading/thread.h"
 #include "base/threading/watchdog.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
diff --git a/chrome/browser/metrics/thread_watcher_unittest.cc b/chrome/browser/metrics/thread_watcher_unittest.cc
index fdd03ec..6670722 100644
--- a/chrome/browser/metrics/thread_watcher_unittest.cc
+++ b/chrome/browser/metrics/thread_watcher_unittest.cc
@@ -16,7 +16,7 @@
 #include "base/synchronization/condition_variable.h"
 #include "base/synchronization/lock.h"
 #include "base/threading/platform_thread.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "build/build_config.h"
 #include "chrome/browser/metrics/thread_watcher.h"
 #include "chrome/common/chrome_switches.h"
diff --git a/chrome/browser/metrics/variations/variations_http_header_provider.cc b/chrome/browser/metrics/variations/variations_http_header_provider.cc
index 6a0e565..ebdf773 100644
--- a/chrome/browser/metrics/variations/variations_http_header_provider.cc
+++ b/chrome/browser/metrics/variations/variations_http_header_provider.cc
@@ -38,8 +38,7 @@
   //    for this install of Chrome.
   // 4. For the X-Chrome-Variations, only include non-empty variation IDs.
   if (incognito ||
-      !google_util::IsGoogleDomainUrl(url.spec(),
-                                      google_util::ALLOW_SUBDOMAIN,
+      !google_util::IsGoogleDomainUrl(url, google_util::ALLOW_SUBDOMAIN,
                                       google_util::ALLOW_NON_STANDARD_PORTS)) {
     return;
   }
diff --git a/chrome/browser/metrics/variations/variations_registry_syncer_win.h b/chrome/browser/metrics/variations/variations_registry_syncer_win.h
index 297a3ca..18ad9d5 100644
--- a/chrome/browser/metrics/variations/variations_registry_syncer_win.h
+++ b/chrome/browser/metrics/variations/variations_registry_syncer_win.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_METRICS_VARIATIONS_VARIATIONS_REGISTRY_SYNCER_WIN_H_
 #define CHROME_BROWSER_METRICS_VARIATIONS_VARIATIONS_REGISTRY_SYNCER_WIN_H_
 
-#include "base/timer.h"
+#include "base/timer/timer.h"
 
 namespace chrome_variations {
 
diff --git a/chrome/browser/metrics/variations/variations_request_scheduler.h b/chrome/browser/metrics/variations/variations_request_scheduler.h
index e6113ed..beb3bbf 100644
--- a/chrome/browser/metrics/variations/variations_request_scheduler.h
+++ b/chrome/browser/metrics/variations/variations_request_scheduler.h
@@ -6,8 +6,9 @@
 #define CHROME_BROWSER_METRICS_VARIATIONS_VARIATIONS_REQUEST_SCHEDULER_H_
 
 #include "base/bind.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/gtest_prod_util.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 
 class PrefService;
 
@@ -40,6 +41,9 @@
   base::Closure task() const;
 
  private:
+  FRIEND_TEST_ALL_PREFIXES(VariationsRequestSchedulerTest,
+                           ScheduleFetchShortly);
+
   // The task scheduled by this class.
   base::Closure task_;
 
diff --git a/chrome/browser/metrics/variations/variations_request_scheduler_unittest.cc b/chrome/browser/metrics/variations/variations_request_scheduler_unittest.cc
new file mode 100644
index 0000000..f69a0b8
--- /dev/null
+++ b/chrome/browser/metrics/variations/variations_request_scheduler_unittest.cc
@@ -0,0 +1,31 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/metrics/variations/variations_request_scheduler.h"
+
+#include "base/bind.h"
+#include "base/message_loop.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chrome_variations {
+
+namespace {
+
+void DoNothing() {
+}
+
+}  // namespace
+
+TEST(VariationsRequestSchedulerTest, ScheduleFetchShortly) {
+  base::MessageLoopForUI message_loop_;
+
+  const base::Closure task = base::Bind(&DoNothing);
+  VariationsRequestScheduler scheduler(task);
+  EXPECT_FALSE(scheduler.one_shot_timer_.IsRunning());
+
+  scheduler.ScheduleFetchShortly();
+  EXPECT_TRUE(scheduler.one_shot_timer_.IsRunning());
+}
+
+}  // namespace chrome_variations
diff --git a/chrome/browser/metrics/variations/variations_service.cc b/chrome/browser/metrics/variations/variations_service.cc
index 2b1bb3b..614290c 100644
--- a/chrome/browser/metrics/variations/variations_service.cc
+++ b/chrome/browser/metrics/variations/variations_service.cc
@@ -24,7 +24,6 @@
 #include "chrome/common/pref_names.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/common/url_fetcher.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/load_flags.h"
 #include "net/base/net_errors.h"
 #include "net/base/network_change_notifier.h"
@@ -34,6 +33,7 @@
 #include "net/http/http_util.h"
 #include "net/url_request/url_fetcher.h"
 #include "net/url_request/url_request_status.h"
+#include "url/gurl.h"
 
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/settings/cros_settings.h"
diff --git a/chrome/browser/metrics/variations/variations_service.h b/chrome/browser/metrics/variations/variations_service.h
index 35c2723..9275786 100644
--- a/chrome/browser/metrics/variations/variations_service.h
+++ b/chrome/browser/metrics/variations/variations_service.h
@@ -11,14 +11,14 @@
 #include "base/gtest_prod_util.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/metrics/field_trial.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/metrics/proto/study.pb.h"
 #include "chrome/browser/metrics/proto/trials_seed.pb.h"
 #include "chrome/browser/metrics/variations/variations_request_scheduler.h"
 #include "chrome/browser/web_resource/resource_request_allowed_notifier.h"
 #include "chrome/common/chrome_version_info.h"
-#include "googleurl/src/gurl.h"
 #include "net/url_request/url_fetcher_delegate.h"
+#include "url/gurl.h"
 
 #if defined(OS_WIN)
 #include "chrome/browser/metrics/variations/variations_registry_syncer_win.h"
diff --git a/chrome/browser/metro_viewer/chrome_metro_viewer_process_host_aurawin.cc b/chrome/browser/metro_viewer/chrome_metro_viewer_process_host_aurawin.cc
index 268510e..3518726 100644
--- a/chrome/browser/metro_viewer/chrome_metro_viewer_process_host_aurawin.cc
+++ b/chrome/browser/metro_viewer/chrome_metro_viewer_process_host_aurawin.cc
@@ -9,9 +9,7 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_process_platform_part_aurawin.h"
 #include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/browser/search_engines/template_url.h"
-#include "chrome/browser/search_engines/template_url_service.h"
-#include "chrome/browser/search_engines/template_url_service_factory.h"
+#include "chrome/browser/search_engines/util.h"
 #include "chrome/browser/ui/ash/ash_init.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
@@ -24,9 +22,9 @@
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/page_navigator.h"
 #include "content/public/browser/web_contents.h"
-#include "googleurl/src/gurl.h"
 #include "ui/aura/remote_root_window_host_win.h"
 #include "ui/surface/accelerated_surface_win.h"
+#include "url/gurl.h"
 
 namespace {
 
@@ -57,12 +55,10 @@
 
 }  // namespace
 
-ChromeMetroViewerProcessHost::ChromeMetroViewerProcessHost(
-    const std::string& ipc_channel_name)
-        : MetroViewerProcessHost(
-              ipc_channel_name,
-              content::BrowserThread::GetMessageLoopProxyForThread(
-                  content::BrowserThread::IO)) {
+ChromeMetroViewerProcessHost::ChromeMetroViewerProcessHost()
+    : MetroViewerProcessHost(
+          content::BrowserThread::GetMessageLoopProxyForThread(
+              content::BrowserThread::IO)) {
   g_browser_process->AddRefModule();
 }
 
@@ -107,15 +103,8 @@
 
 void ChromeMetroViewerProcessHost::OnHandleSearchRequest(
     const string16& search_string) {
-  const TemplateURL* default_provider =
-      TemplateURLServiceFactory::GetForProfile(
-          ProfileManager::GetDefaultProfileOrOffTheRecord())->
-              GetDefaultSearchProvider();
-  if (default_provider) {
-    const TemplateURLRef& search_url = default_provider->url_ref();
-    DCHECK(search_url.SupportsReplacement());
-    GURL request_url = GURL(search_url.ReplaceSearchTerms(
-        TemplateURLRef::SearchTermsArgs(search_string)));
-    OpenURL(request_url);
-  }
+  GURL url(GetDefaultSearchURLForSearchTerms(
+      ProfileManager::GetDefaultProfileOrOffTheRecord(), search_string));
+  if (url.is_valid())
+    OpenURL(url);
 }
diff --git a/chrome/browser/metro_viewer/chrome_metro_viewer_process_host_aurawin.h b/chrome/browser/metro_viewer/chrome_metro_viewer_process_host_aurawin.h
index 826deb2..96ff005 100644
--- a/chrome/browser/metro_viewer/chrome_metro_viewer_process_host_aurawin.h
+++ b/chrome/browser/metro_viewer/chrome_metro_viewer_process_host_aurawin.h
@@ -5,13 +5,11 @@
 #ifndef CHROME_BROWSER_METRO_VIEWER_CHROME_METRO_VIEWER_PROCESS_HOST_AURAWIN_H_
 #define CHROME_BROWSER_METRO_VIEWER_CHROME_METRO_VIEWER_PROCESS_HOST_AURAWIN_H_
 
-#include <string>
-
 #include "win8/viewer/metro_viewer_process_host.h"
 
 class ChromeMetroViewerProcessHost : public win8::MetroViewerProcessHost {
  public:
-  explicit ChromeMetroViewerProcessHost(const std::string& ipc_channel_name);
+  ChromeMetroViewerProcessHost();
 
  private:
   // win8::MetroViewerProcessHost implementation
diff --git a/chrome/browser/nacl_host/nacl_broker_host_win.cc b/chrome/browser/nacl_host/nacl_broker_host_win.cc
index 2115adb..74e4161 100644
--- a/chrome/browser/nacl_host/nacl_broker_host_win.cc
+++ b/chrome/browser/nacl_host/nacl_broker_host_win.cc
@@ -8,13 +8,13 @@
 #include "base/path_service.h"
 #include "ipc/ipc_switches.h"
 #include "chrome/browser/nacl_host/nacl_broker_service_win.h"
-#include "chrome/browser/nacl_host/nacl_process_host.h"
-#include "chrome/common/chrome_constants.h"
+#include "chrome/browser/nacl_host/nacl_browser.h"
 #include "chrome/common/chrome_process_type.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/logging_chrome.h"
 #include "chrome/common/nacl_cmd_line.h"
 #include "chrome/common/nacl_messages.h"
+#include "components/nacl/common/nacl_switches.h"
 #include "content/public/browser/browser_child_process_host.h"
 #include "content/public/browser/child_process_data.h"
 #include "content/public/common/child_process_host.h"
@@ -52,11 +52,10 @@
     return false;
 
   // Create the path to the nacl broker/loader executable.
-  base::FilePath module_path;
-  if (!PathService::Get(base::FILE_MODULE, &module_path))
+  base::FilePath nacl_path;
+  if (!NaClBrowser::GetInstance()->GetNaCl64ExePath(&nacl_path))
     return false;
 
-  base::FilePath nacl_path = module_path.DirName().Append(chrome::kNaClAppName);
   CommandLine* cmd_line = new CommandLine(nacl_path);
   nacl::CopyNaClCommandLineArguments(cmd_line);
 
diff --git a/chrome/browser/nacl_host/nacl_browser.cc b/chrome/browser/nacl_host/nacl_browser.cc
index e6811d3..9cf4bcd 100644
--- a/chrome/browser/nacl_host/nacl_browser.cc
+++ b/chrome/browser/nacl_host/nacl_browser.cc
@@ -19,7 +19,7 @@
 #include "chrome/common/chrome_switches.h"
 #include "content/public/browser/browser_thread.h"
 #include "extensions/common/url_pattern.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 namespace {
 
@@ -101,7 +101,7 @@
 
 void RemoveCache(const base::FilePath& filename,
                  const base::Closure& callback) {
-  file_util::Delete(filename, false);
+  base::Delete(filename, false);
   content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
                                    callback);
 }
@@ -197,6 +197,18 @@
   }
 }
 
+#if defined(OS_WIN)
+bool NaClBrowser::GetNaCl64ExePath(base::FilePath* exe_path) {
+  base::FilePath module_path;
+  if (!PathService::Get(base::FILE_MODULE, &module_path)) {
+    LOG(ERROR) << "NaCl process launch failed: could not resolve module";
+    return false;
+  }
+  *exe_path = module_path.DirName().Append(L"nacl64");
+  return true;
+}
+#endif
+
 NaClBrowser* NaClBrowser::GetInstance() {
   return Singleton<NaClBrowser>::get();
 }
diff --git a/chrome/browser/nacl_host/nacl_browser.h b/chrome/browser/nacl_host/nacl_browser.h
index e2f041e..77bae0f 100644
--- a/chrome/browser/nacl_host/nacl_browser.h
+++ b/chrome/browser/nacl_host/nacl_browser.h
@@ -109,6 +109,11 @@
   bool QueryKnownToValidate(const std::string& signature, bool off_the_record);
   void SetKnownToValidate(const std::string& signature, bool off_the_record);
   void ClearValidationCache(const base::Closure& callback);
+#if defined(OS_WIN)
+  // Get path to NaCl loader on the filesystem if possible.
+  // |exe_path| does not change if the method fails.
+  bool GetNaCl64ExePath(base::FilePath* exe_path);
+#endif
 
  private:
   friend struct DefaultSingletonTraits<NaClBrowser>;
diff --git a/chrome/browser/nacl_host/nacl_file_host.cc b/chrome/browser/nacl_host/nacl_file_host.cc
index 788876e..1acca3a 100644
--- a/chrome/browser/nacl_host/nacl_file_host.cc
+++ b/chrome/browser/nacl_host/nacl_file_host.cc
@@ -11,6 +11,8 @@
 #include "base/platform_file.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/sequenced_worker_pool.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/component_updater/pnacl/pnacl_component_installer.h"
 #include "chrome/browser/extensions/extension_info_map.h"
 #include "chrome/browser/nacl_host/nacl_browser.h"
 #include "chrome/browser/nacl_host/nacl_host_message_filter.h"
@@ -58,10 +60,64 @@
 void DoOpenPnaclFile(
     scoped_refptr<NaClHostMessageFilter> nacl_host_message_filter,
     const std::string& filename,
+    IPC::Message* reply_msg);
+
+void PnaclCheckDone(
+    scoped_refptr<NaClHostMessageFilter> nacl_host_message_filter,
+    const std::string& filename,
+    IPC::Message* reply_msg,
+    bool success) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  if (!success) {
+    NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg);
+  } else {
+    if (!BrowserThread::PostBlockingPoolTask(
+            FROM_HERE,
+            base::Bind(&DoOpenPnaclFile,
+                       nacl_host_message_filter,
+                       filename,
+                       reply_msg))) {
+      NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg);
+    }
+  }
+}
+
+void TryInstallPnacl(
+    scoped_refptr<NaClHostMessageFilter> nacl_host_message_filter,
+    const std::string& filename,
+    IPC::Message* reply_msg) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  ComponentUpdateService* cus = g_browser_process->component_updater();
+  PnaclComponentInstaller* pci =
+      g_browser_process->pnacl_component_installer();
+  RequestFirstInstall(cus,
+                      pci,
+                      base::Bind(&PnaclCheckDone,
+                                 nacl_host_message_filter,
+                                 filename,
+                                 reply_msg));
+}
+
+void DoOpenPnaclFile(
+    scoped_refptr<NaClHostMessageFilter> nacl_host_message_filter,
+    const std::string& filename,
     IPC::Message* reply_msg) {
   DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
   base::FilePath full_filepath;
 
+  // PNaCl must be installed.
+  base::FilePath pnacl_dir;
+  if (!PathService::Get(chrome::DIR_PNACL_COMPONENT, &pnacl_dir) ||
+      !file_util::PathExists(pnacl_dir)) {
+    BrowserThread::PostTask(
+        BrowserThread::UI, FROM_HERE,
+        base::Bind(&TryInstallPnacl,
+                   nacl_host_message_filter,
+                   filename,
+                   reply_msg));
+    return;
+  }
+
   // Do some validation.
   if (!nacl_file_host::PnaclCanOpenFile(filename, &full_filepath)) {
     NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg);
diff --git a/chrome/browser/nacl_host/nacl_host_message_filter.cc b/chrome/browser/nacl_host/nacl_host_message_filter.cc
index 20ad21f..1cb2167 100644
--- a/chrome/browser/nacl_host/nacl_host_message_filter.cc
+++ b/chrome/browser/nacl_host/nacl_host_message_filter.cc
@@ -13,23 +13,38 @@
 #include "chrome/browser/nacl_host/nacl_file_host.h"
 #include "chrome/browser/nacl_host/nacl_infobar.h"
 #include "chrome/browser/nacl_host/nacl_process_host.h"
-#include "chrome/browser/profiles/profile.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/nacl_host_messages.h"
-#include "googleurl/src/gurl.h"
+#include "extensions/common/constants.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_context_getter.h"
+#include "url/gurl.h"
+
+static base::FilePath GetManifestPath(
+    ExtensionInfoMap* extension_info_map, const std::string& manifest) {
+  GURL manifest_url(manifest);
+  const extensions::Extension* extension = extension_info_map->extensions()
+      .GetExtensionOrAppByURL(ExtensionURLInfo(manifest_url));
+  if (extension != NULL &&
+      manifest_url.SchemeIs(extensions::kExtensionScheme)) {
+    std::string path = manifest_url.path();
+    TrimString(path, "/", &path);  // Remove first slash
+    return extension->path().AppendASCII(path);
+  }
+  return base::FilePath();
+}
 
 NaClHostMessageFilter::NaClHostMessageFilter(
     int render_process_id,
-    Profile* profile,
+    bool is_off_the_record,
+    const base::FilePath& profile_directory,
+    ExtensionInfoMap* extension_info_map,
     net::URLRequestContextGetter* request_context)
     : render_process_id_(render_process_id),
-      profile_(profile),
-      off_the_record_(profile_->IsOffTheRecord()),
+      off_the_record_(is_off_the_record),
+      profile_directory_(profile_directory),
       request_context_(request_context),
-      extension_info_map_(
-          extensions::ExtensionSystem::Get(profile)->info_map()),
+      extension_info_map_(extension_info_map),
       weak_ptr_factory_(this) {
 }
 
@@ -72,8 +87,11 @@
       launch_params.enable_dyncode_syscalls,
       launch_params.enable_exception_handling,
       off_the_record_,
-      profile_->GetPath());
-  host->Launch(this, reply_msg, extension_info_map_);
+      profile_directory_);
+  base::FilePath manifest_url = GetManifestPath(
+        extension_info_map_,
+        launch_params.manifest_url);
+  host->Launch(this, reply_msg, manifest_url);
 }
 
 void NaClHostMessageFilter::OnGetReadonlyPnaclFd(
diff --git a/chrome/browser/nacl_host/nacl_host_message_filter.h b/chrome/browser/nacl_host/nacl_host_message_filter.h
index 61ffc74..4d9cdb0 100644
--- a/chrome/browser/nacl_host/nacl_host_message_filter.h
+++ b/chrome/browser/nacl_host/nacl_host_message_filter.h
@@ -5,12 +5,12 @@
 #ifndef CHROME_BROWSER_NACL_HOST_NACL_HOST_MESSAGE_FILTER_H_
 #define CHROME_BROWSER_NACL_HOST_NACL_HOST_MESSAGE_FILTER_H_
 
+#include "base/files/file_path.h"
 #include "base/memory/weak_ptr.h"
 #include "content/public/browser/browser_message_filter.h"
 
 class ExtensionInfoMap;
 class GURL;
-class Profile;
 
 namespace nacl {
 struct NaClLaunchParams;
@@ -26,7 +26,9 @@
 class NaClHostMessageFilter : public content::BrowserMessageFilter {
  public:
   NaClHostMessageFilter(int render_process_id,
-                        Profile* profile,
+                        bool is_off_the_record,
+                        const base::FilePath& profile_directory,
+                        ExtensionInfoMap* extension_info_map,
                         net::URLRequestContextGetter* request_context);
 
   // content::BrowserMessageFilter methods:
@@ -56,11 +58,10 @@
 #endif
   int render_process_id_;
 
-  // The Profile associated with our renderer process.  This should only be
-  // accessed on the UI thread!
-  Profile* profile_;
-  // Copied from the profile so that it can be read on the IO thread.
+  // off_the_record_ is copied from the profile partly so that it can be
+  // read on the IO thread.
   bool off_the_record_;
+  base::FilePath profile_directory_;
   scoped_refptr<net::URLRequestContextGetter> request_context_;
   scoped_refptr<ExtensionInfoMap> extension_info_map_;
 
diff --git a/chrome/browser/nacl_host/nacl_infobar.cc b/chrome/browser/nacl_host/nacl_infobar.cc
index 7583c22..e9c33d4 100644
--- a/chrome/browser/nacl_host/nacl_infobar.cc
+++ b/chrome/browser/nacl_host/nacl_infobar.cc
@@ -11,10 +11,10 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
-#include "googleurl/src/gurl.h"
 #include "grit/generated_resources.h"
 #include "ppapi/c/private/ppb_nacl_private.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "url/gurl.h"
 
 using content::BrowserThread;
 using content::RenderViewHost;
diff --git a/chrome/browser/nacl_host/nacl_process_host.cc b/chrome/browser/nacl_host/nacl_process_host.cc
index 6f7f50c..f713448 100644
--- a/chrome/browser/nacl_host/nacl_process_host.cc
+++ b/chrome/browser/nacl_host/nacl_process_host.cc
@@ -23,11 +23,9 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/win/windows_version.h"
 #include "build/build_config.h"
-#include "chrome/browser/extensions/extension_info_map.h"
 #include "chrome/browser/nacl_host/nacl_browser.h"
 #include "chrome/browser/nacl_host/nacl_host_message_filter.h"
 #include "chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h"
-#include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_process_type.h"
 #include "chrome/common/chrome_switches.h"
@@ -37,12 +35,12 @@
 #include "chrome/common/nacl_host_messages.h"
 #include "chrome/common/nacl_messages.h"
 #include "chrome/common/render_messages.h"
+#include "components/nacl/common/nacl_switches.h"
 #include "content/public/browser/browser_child_process_host.h"
 #include "content/public/browser/browser_ppapi_host.h"
 #include "content/public/browser/child_process_data.h"
 #include "content/public/common/child_process_host.h"
 #include "content/public/common/process_type.h"
-#include "extensions/common/constants.h"
 #include "ipc/ipc_channel.h"
 #include "ipc/ipc_switches.h"
 #include "native_client/src/shared/imc/nacl_imc_c.h"
@@ -282,10 +280,10 @@
 void NaClProcessHost::Launch(
     NaClHostMessageFilter* nacl_host_message_filter,
     IPC::Message* reply_msg,
-    scoped_refptr<ExtensionInfoMap> extension_info_map) {
+    const base::FilePath& manifest_path) {
   nacl_host_message_filter_ = nacl_host_message_filter;
   reply_msg_ = reply_msg;
-  extension_info_map_ = extension_info_map;
+  manifest_path_ = manifest_path;
 
   // Start getting the IRT open asynchronously while we launch the NaCl process.
   // We'll make sure this actually finished in StartWithLaunchedProcess, below.
@@ -374,10 +372,9 @@
   std::replace(irt_path.begin(), irt_path.end(), '\\', '/');
   cmd_line.AppendArgNative(FILE_PATH_LITERAL("nacl-irt \"") + irt_path +
                            FILE_PATH_LITERAL("\""));
-  base::FilePath manifest_path = GetManifestPath();
-  if (!manifest_path.empty()) {
+  if (!manifest_path_.empty()) {
     cmd_line.AppendArg("--eval-command");
-    base::FilePath::StringType manifest_path_value(manifest_path.value());
+    base::FilePath::StringType manifest_path_value(manifest_path_.value());
     std::replace(manifest_path_value.begin(), manifest_path_value.end(),
                  '\\', '/');
     cmd_line.AppendArgNative(FILE_PATH_LITERAL("nacl-manifest \"") +
@@ -394,18 +391,6 @@
   return base::LaunchProcess(cmd_line, base::LaunchOptions(), NULL);
 }
 
-base::FilePath NaClProcessHost::GetManifestPath() {
-  const extensions::Extension* extension = extension_info_map_->extensions()
-      .GetExtensionOrAppByURL(ExtensionURLInfo(manifest_url_));
-  if (extension != NULL &&
-      manifest_url_.SchemeIs(extensions::kExtensionScheme)) {
-    std::string path = manifest_url_.path();
-    TrimString(path, "/", &path);  // Remove first slash
-    return extension->path().AppendASCII(path);
-  }
-  return base::FilePath();
-}
-
 bool NaClProcessHost::LaunchSelLdr() {
   std::string channel_id = process_->GetHost()->CreateChannel();
   if (channel_id.empty()) {
@@ -443,12 +428,9 @@
 #if defined(OS_WIN)
   // On Windows 64-bit NaCl loader is called nacl64.exe instead of chrome.exe
   if (RunningOnWOW64()) {
-    base::FilePath module_path;
-    if (!PathService::Get(base::FILE_MODULE, &module_path)) {
-      LOG(ERROR) << "NaCl process launch failed: could not resolve module";
+    if (!NaClBrowser::GetInstance()->GetNaCl64ExePath(&exe_path)) {
       return false;
     }
-    exe_path = module_path.DirName().Append(chrome::kNaClAppName);
   }
 #endif
 
diff --git a/chrome/browser/nacl_host/nacl_process_host.h b/chrome/browser/nacl_host/nacl_process_host.h
index 4f15e8a..4496f92 100644
--- a/chrome/browser/nacl_host/nacl_process_host.h
+++ b/chrome/browser/nacl_host/nacl_process_host.h
@@ -16,14 +16,13 @@
 #include "chrome/common/nacl_types.h"
 #include "content/public/browser/browser_child_process_host_delegate.h"
 #include "content/public/browser/browser_child_process_host_iterator.h"
-#include "googleurl/src/gurl.h"
 #include "ipc/ipc_channel_handle.h"
 #include "net/socket/tcp_listen_socket.h"
 #include "ppapi/shared_impl/ppapi_permissions.h"
+#include "url/gurl.h"
 
 class NaClHostMessageFilter;
 class CommandLine;
-class ExtensionInfoMap;
 
 namespace content {
 class BrowserChildProcessHost;
@@ -65,7 +64,7 @@
   // message reply_msg.
   void Launch(NaClHostMessageFilter* nacl_host_message_filter,
               IPC::Message* reply_msg,
-              scoped_refptr<ExtensionInfoMap> extension_info_map);
+              const base::FilePath& manifest_path);
 
   virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
 
@@ -107,8 +106,6 @@
   // is enabled.
   SocketDescriptor GetDebugStubSocketHandle();
 #endif
-  // Get path to manifest on local disk if possible.
-  base::FilePath GetManifestPath();
   bool LaunchSelLdr();
 
   // BrowserChildProcessHostDelegate implementation:
@@ -181,9 +178,9 @@
   scoped_ptr<IPC::Message> attach_debug_exception_handler_reply_msg_;
 #endif
 
-  // Set of extensions for (NaCl) manifest auto-detection. The file path to
-  // manifest is passed to nacl-gdb when it is used to debug the NaCl loader.
-  scoped_refptr<ExtensionInfoMap> extension_info_map_;
+  // The file path to the manifest is passed to nacl-gdb when it is used to
+  // debug the NaCl loader.
+  base::FilePath manifest_path_;
 
   // Socket pairs for the NaCl process and renderer.
   scoped_ptr<NaClInternal> internal_;
diff --git a/chrome/browser/nacl_host/test/nacl_gdb_browsertest.cc b/chrome/browser/nacl_host/test/nacl_gdb_browsertest.cc
index 141008e..6e1c074 100644
--- a/chrome/browser/nacl_host/test/nacl_gdb_browsertest.cc
+++ b/chrome/browser/nacl_host/test/nacl_gdb_browsertest.cc
@@ -9,6 +9,7 @@
 #include "base/win/windows_version.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/ppapi/ppapi_test.h"
+#include "components/nacl/common/nacl_switches.h"
 
 static const base::FilePath::CharType kMockNaClGdb[] =
 #if defined(OS_WIN)
@@ -56,12 +57,12 @@
 
     EXPECT_TRUE(file_util::ReadFileToString(mock_nacl_gdb_file, &content));
     EXPECT_STREQ("PASS", content.c_str());
-    EXPECT_TRUE(file_util::Delete(mock_nacl_gdb_file, false));
+    EXPECT_TRUE(base::Delete(mock_nacl_gdb_file, false));
 
     content.clear();
     EXPECT_TRUE(file_util::ReadFileToString(script_, &content));
     EXPECT_STREQ("PASS", content.c_str());
-    EXPECT_TRUE(file_util::Delete(script_, false));
+    EXPECT_TRUE(base::Delete(script_, false));
   }
 
  private:
diff --git a/chrome/browser/net/chrome_fraudulent_certificate_reporter.cc b/chrome/browser/net/chrome_fraudulent_certificate_reporter.cc
index c5aed31..89e8b48 100644
--- a/chrome/browser/net/chrome_fraudulent_certificate_reporter.cc
+++ b/chrome/browser/net/chrome_fraudulent_certificate_reporter.cc
@@ -9,7 +9,7 @@
 #include "base/base64.h"
 #include "base/logging.h"
 #include "base/stl_util.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/net/cert_logger.pb.h"
 #include "net/base/load_flags.h"
 #include "net/base/upload_bytes_element_reader.h"
diff --git a/chrome/browser/net/chrome_net_log.cc b/chrome/browser/net/chrome_net_log.cc
index 093b0b5..b9a417a 100644
--- a/chrome/browser/net/chrome_net_log.cc
+++ b/chrome/browser/net/chrome_net_log.cc
@@ -11,9 +11,11 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/values.h"
-#include "chrome/browser/net/net_log_logger.h"
 #include "chrome/browser/net/net_log_temp_file.h"
+#include "chrome/browser/ui/webui/net_internals/net_internals_ui.h"
 #include "chrome/common/chrome_switches.h"
+#include "content/public/common/content_switches.h"
+#include "net/base/net_log_logger.h"
 
 ChromeNetLog::ChromeNetLog()
     : net_log_temp_file_(new NetLogTempFile(this)) {
@@ -52,7 +54,8 @@
       LOG(ERROR) << "Could not open file " << log_path.value()
                  << " for net logging";
     } else {
-      net_log_logger_.reset(new NetLogLogger(file));
+      scoped_ptr<base::Value> constants(NetInternalsUI::GetConstants());
+      net_log_logger_.reset(new net::NetLogLogger(file, *constants));
       net_log_logger_->StartObserving(this);
     }
   }
diff --git a/chrome/browser/net/chrome_net_log.h b/chrome/browser/net/chrome_net_log.h
index 10e45fb..4114868 100644
--- a/chrome/browser/net/chrome_net_log.h
+++ b/chrome/browser/net/chrome_net_log.h
@@ -11,15 +11,14 @@
 #include "base/synchronization/lock.h"
 #include "net/base/net_log.h"
 
+namespace net {
 class NetLogLogger;
+}
+
 class NetLogTempFile;
 
-// ChromeNetLog is an implementation of NetLog that dispatches network log
-// messages to a list of observers.
-//
-// All methods are thread safe, with the exception that no NetLog or
-// NetLog::ThreadSafeObserver functions may be called by an observer's
-// OnAddEntry() method.  Doing so will result in a deadlock.
+// ChromeNetLog is an implementation of NetLog that adds file loggers
+// as its observers.
 class ChromeNetLog : public net::NetLog {
  public:
   ChromeNetLog();
@@ -30,7 +29,7 @@
   }
 
  private:
-  scoped_ptr<NetLogLogger> net_log_logger_;
+  scoped_ptr<net::NetLogLogger> net_log_logger_;
   scoped_ptr<NetLogTempFile> net_log_temp_file_;
 
   DISALLOW_COPY_AND_ASSIGN(ChromeNetLog);
diff --git a/chrome/browser/net/chrome_network_delegate.cc b/chrome/browser/net/chrome_network_delegate.cc
index b43b53b..6697181 100644
--- a/chrome/browser/net/chrome_network_delegate.cc
+++ b/chrome/browser/net/chrome_network_delegate.cc
@@ -136,8 +136,8 @@
 // Sets the query part of |new_url| with the new value of the parameters.
 void ForceGoogleSafeSearch(net::URLRequest* request,
                            GURL* new_url) {
-  if (!google_util::IsGoogleSearchUrl(request->url().spec()) &&
-      !google_util::IsGoogleHomePageUrl(request->url().spec()))
+  if (!google_util::IsGoogleSearchUrl(request->url()) &&
+      !google_util::IsGoogleHomePageUrl(request->url()))
     return;
 
   std::string query = request->url().query();
@@ -327,7 +327,8 @@
 }
 
 void RecordContentLengthHistograms(
-    int64 received_content_length, int64 original_content_length,
+    int64 received_content_length,
+    int64 original_content_length,
     const base::TimeDelta& freshness_lifetime) {
 #if defined(OS_ANDROID)
   // Add the current resource to these histograms only when a valid
@@ -349,10 +350,11 @@
                        original_content_length);
   UMA_HISTOGRAM_COUNTS("Net.HttpContentLengthDifference",
                        original_content_length - received_content_length);
-  UMA_HISTOGRAM_CUSTOM_TIMES("Net.HttpContentFreshnessLifetime",
-                             freshness_lifetime,
-                             base::TimeDelta::FromHours(1),
-                             base::TimeDelta::FromDays(30), 100);
+  UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpContentFreshnessLifetime",
+                              freshness_lifetime.InSeconds(),
+                              base::TimeDelta::FromHours(1).InSeconds(),
+                              base::TimeDelta::FromDays(30).InSeconds(),
+                              100);
   if (freshness_lifetime.InSeconds() <= 0)
     return;
   UMA_HISTOGRAM_COUNTS("Net.HttpContentLengthCacheable",
diff --git a/chrome/browser/net/chrome_url_request_context.cc b/chrome/browser/net/chrome_url_request_context.cc
index c39ebec..a52fb1a 100644
--- a/chrome/browser/net/chrome_url_request_context.cc
+++ b/chrome/browser/net/chrome_url_request_context.cc
@@ -298,7 +298,8 @@
 ChromeURLRequestContext::ChromeURLRequestContext(
     ContextType type,
     chrome_browser_net::LoadTimeStats* load_time_stats)
-    : load_time_stats_(load_time_stats) {
+    : weak_factory_(this),
+      load_time_stats_(load_time_stats) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
   if (load_time_stats_)
     load_time_stats_->RegisterURLRequestContext(this, type);
diff --git a/chrome/browser/net/chrome_url_request_context.h b/chrome/browser/net/chrome_url_request_context.h
index 86f09fc..db09992 100644
--- a/chrome/browser/net/chrome_url_request_context.h
+++ b/chrome/browser/net/chrome_url_request_context.h
@@ -41,13 +41,15 @@
   virtual ~ChromeURLRequestContext();
 
   base::WeakPtr<ChromeURLRequestContext> GetWeakPtr() {
-    return base::AsWeakPtr(this);
+    return weak_factory_.GetWeakPtr();
   }
 
   // Copies the state from |other| into this context.
   void CopyFrom(ChromeURLRequestContext* other);
 
  private:
+  base::WeakPtrFactory<ChromeURLRequestContext> weak_factory_;
+
   // ---------------------------------------------------------------------------
   // Important: When adding any new members below, consider whether they need to
   // be added to CopyFrom.
diff --git a/chrome/browser/net/connection_tester.h b/chrome/browser/net/connection_tester.h
index d25c266..df1bf34 100644
--- a/chrome/browser/net/connection_tester.h
+++ b/chrome/browser/net/connection_tester.h
@@ -9,8 +9,8 @@
 
 #include "base/basictypes.h"
 #include "base/memory/scoped_ptr.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/completion_callback.h"
+#include "url/gurl.h"
 
 namespace net {
 class NetLog;
diff --git a/chrome/browser/net/crl_set_fetcher.cc b/chrome/browser/net/crl_set_fetcher.cc
index eba5d7c..95fbfd3 100644
--- a/chrome/browser/net/crl_set_fetcher.cc
+++ b/chrome/browser/net/crl_set_fetcher.cc
@@ -9,7 +9,7 @@
 #include "base/path_service.h"
 #include "base/rand_util.h"
 #include "base/strings/string_number_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/component_updater/component_updater_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/chrome_constants.h"
@@ -205,4 +205,9 @@
   return true;
 }
 
+bool CRLSetFetcher::GetInstalledFile(
+    const std::string& file, base::FilePath* installed_file) {
+  return false;
+}
+
 CRLSetFetcher::~CRLSetFetcher() {}
diff --git a/chrome/browser/net/crl_set_fetcher.h b/chrome/browser/net/crl_set_fetcher.h
index 476e1b9..5f7bdf3 100644
--- a/chrome/browser/net/crl_set_fetcher.h
+++ b/chrome/browser/net/crl_set_fetcher.h
@@ -33,6 +33,8 @@
   virtual void OnUpdateError(int error) OVERRIDE;
   virtual bool Install(const base::DictionaryValue& manifest,
                        const base::FilePath& unpack_path) OVERRIDE;
+  virtual bool GetInstalledFile(const std::string& file,
+                                base::FilePath* installed_file) OVERRIDE;
 
  private:
   friend class base::RefCountedThreadSafe<CRLSetFetcher>;
diff --git a/chrome/browser/net/dns_probe_job.cc b/chrome/browser/net/dns_probe_job.cc
index 204484e..f51f450 100644
--- a/chrome/browser/net/dns_probe_job.cc
+++ b/chrome/browser/net/dns_probe_job.cc
@@ -8,7 +8,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/message_loop.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "net/base/address_list.h"
 #include "net/base/net_errors.h"
 #include "net/base/net_log.h"
diff --git a/chrome/browser/net/dns_probe_service.h b/chrome/browser/net/dns_probe_service.h
index c40967a..a906d75 100644
--- a/chrome/browser/net/dns_probe_service.h
+++ b/chrome/browser/net/dns_probe_service.h
@@ -9,7 +9,7 @@
 
 #include "base/basictypes.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/net/dns_probe_job.h"
 #include "chrome/common/net/net_error_info.h"
 #include "net/base/network_change_notifier.h"
diff --git a/chrome/browser/net/evicted_domain_cookie_counter.h b/chrome/browser/net/evicted_domain_cookie_counter.h
index cd952c8..5cf8797 100644
--- a/chrome/browser/net/evicted_domain_cookie_counter.h
+++ b/chrome/browser/net/evicted_domain_cookie_counter.h
@@ -12,7 +12,7 @@
 #include "base/compiler_specific.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "net/cookies/cookie_monster.h"
 
 namespace net {
diff --git a/chrome/browser/net/evicted_domain_cookie_counter_unittest.cc b/chrome/browser/net/evicted_domain_cookie_counter_unittest.cc
index b5831b0..ca2597d 100644
--- a/chrome/browser/net/evicted_domain_cookie_counter_unittest.cc
+++ b/chrome/browser/net/evicted_domain_cookie_counter_unittest.cc
@@ -9,12 +9,12 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/scoped_vector.h"
 #include "base/strings/string_number_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/net/evicted_domain_cookie_counter.h"
-#include "googleurl/src/gurl.h"
 #include "net/cookies/canonical_cookie.h"
 #include "net/cookies/cookie_monster.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 namespace chrome_browser_net {
 
diff --git a/chrome/browser/net/ftp_browsertest.cc b/chrome/browser/net/ftp_browsertest.cc
index 283593e..50b3a6c 100644
--- a/chrome/browser/net/ftp_browsertest.cc
+++ b/chrome/browser/net/ftp_browsertest.cc
@@ -4,9 +4,9 @@
 
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
-#include "googleurl/src/gurl.h"
 #include "net/test/spawned_test_server/spawned_test_server.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 class FtpBrowserTest : public InProcessBrowserTest {
  public:
diff --git a/chrome/browser/net/gaia/gaia_oauth_fetcher.h b/chrome/browser/net/gaia/gaia_oauth_fetcher.h
index 46389ca..9228cd6 100644
--- a/chrome/browser/net/gaia/gaia_oauth_fetcher.h
+++ b/chrome/browser/net/gaia/gaia_oauth_fetcher.h
@@ -10,8 +10,8 @@
 
 #include "base/memory/scoped_ptr.h"
 #include "google_apis/gaia/google_service_auth_error.h"
-#include "googleurl/src/gurl.h"
 #include "net/url_request/url_fetcher_delegate.h"
+#include "url/gurl.h"
 
 class GaiaOAuthConsumer;
 
diff --git a/chrome/browser/net/gaia/gaia_oauth_fetcher_unittest.cc b/chrome/browser/net/gaia/gaia_oauth_fetcher_unittest.cc
index 75e9d29..284d34b 100644
--- a/chrome/browser/net/gaia/gaia_oauth_fetcher_unittest.cc
+++ b/chrome/browser/net/gaia/gaia_oauth_fetcher_unittest.cc
@@ -15,13 +15,13 @@
 #include "google_apis/gaia/gaia_constants.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "google_apis/gaia/google_service_auth_error.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/net_errors.h"
 #include "net/http/http_status_code.h"
 #include "net/url_request/test_url_fetcher_factory.h"
 #include "net/url_request/url_request_status.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 using ::testing::_;
 
diff --git a/chrome/browser/net/http_server_properties_manager.h b/chrome/browser/net/http_server_properties_manager.h
index ad87388..a63859a 100644
--- a/chrome/browser/net/http_server_properties_manager.h
+++ b/chrome/browser/net/http_server_properties_manager.h
@@ -12,7 +12,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/prefs/pref_change_registrar.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "base/values.h"
 #include "net/base/host_port_pair.h"
 #include "net/http/http_pipelined_host_capability.h"
diff --git a/chrome/browser/net/http_server_properties_manager_unittest.cc b/chrome/browser/net/http_server_properties_manager_unittest.cc
index 5ce5584..5be9d96 100644
--- a/chrome/browser/net/http_server_properties_manager_unittest.cc
+++ b/chrome/browser/net/http_server_properties_manager_unittest.cc
@@ -11,9 +11,9 @@
 #include "base/values.h"
 #include "chrome/common/pref_names.h"
 #include "content/public/test/test_browser_thread.h"
-#include "googleurl/src/gurl.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 namespace chrome_browser_net {
 
diff --git a/chrome/browser/net/load_time_stats.cc b/chrome/browser/net/load_time_stats.cc
index 8446b78..0801775 100644
--- a/chrome/browser/net/load_time_stats.cc
+++ b/chrome/browser/net/load_time_stats.cc
@@ -8,7 +8,7 @@
 #include "base/metrics/histogram.h"
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/io_thread.h"
 #include "chrome/browser/profiles/profile.h"
diff --git a/chrome/browser/net/load_time_stats.h b/chrome/browser/net/load_time_stats.h
index 958e922..c7ea58d 100644
--- a/chrome/browser/net/load_time_stats.h
+++ b/chrome/browser/net/load_time_stats.h
@@ -13,7 +13,7 @@
 #include "base/containers/hash_tables.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/message_loop.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/net/chrome_url_request_context.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/browser/web_contents_user_data.h"
diff --git a/chrome/browser/net/load_timing_browsertest.cc b/chrome/browser/net/load_timing_browsertest.cc
index b42bbf8..ac6e2a6 100644
--- a/chrome/browser/net/load_timing_browsertest.cc
+++ b/chrome/browser/net/load_timing_browsertest.cc
@@ -20,12 +20,12 @@
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/test/browser_test_utils.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/load_timing_info.h"
 #include "net/test/spawned_test_server/spawned_test_server.h"
 #include "net/url_request/url_request_file_job.h"
 #include "net/url_request/url_request_filter.h"
 #include "net/url_request/url_request_job_factory.h"
+#include "url/gurl.h"
 
 // This file tests that net::LoadTimingInfo is correctly hooked up to the
 // NavigationTiming API.  It depends on behavior in a large number of files
diff --git a/chrome/browser/net/net_log_logger.cc b/chrome/browser/net/net_log_logger.cc
deleted file mode 100644
index 35da9ef..0000000
--- a/chrome/browser/net/net_log_logger.cc
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/net/net_log_logger.h"
-
-#include <stdio.h>
-
-#include "base/json/json_writer.h"
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/values.h"
-#include "chrome/browser/ui/webui/net_internals/net_internals_ui.h"
-
-NetLogLogger::NetLogLogger(FILE* file) : file_(file), added_events_(false) {
-  DCHECK(file);
-
-  // Write constants to the output file.  This allows loading files that have
-  // different source and event types, as they may be added and removed
-  // between Chrome versions.
-  scoped_ptr<Value> value(NetInternalsUI::GetConstants());
-  std::string json;
-  base::JSONWriter::Write(value.get(), &json);
-  fprintf(file_.get(), "{\"constants\": %s,\n", json.c_str());
-  fprintf(file_.get(), "\"events\": [\n");
-}
-
-NetLogLogger::~NetLogLogger() {
-  if (file_.get())
-    fprintf(file_.get(), "]}");
-}
-
-void NetLogLogger::StartObserving(net::NetLog* net_log) {
-  net_log->AddThreadSafeObserver(this, net::NetLog::LOG_ALL_BUT_BYTES);
-}
-
-void NetLogLogger::StopObserving() {
-  net_log()->RemoveThreadSafeObserver(this);
-}
-
-void NetLogLogger::OnAddEntry(const net::NetLog::Entry& entry) {
-  // Add a comma and newline for every event but the first.  Newlines are needed
-  // so can load partial log files by just ignoring the last line.  For this to
-  // work, lines cannot be pretty printed.
-  scoped_ptr<Value> value(entry.ToValue());
-  std::string json;
-  base::JSONWriter::Write(value.get(), &json);
-  fprintf(file_.get(), "%s%s",
-          (added_events_ ? ",\n" : ""),
-          json.c_str());
-  added_events_ = true;
-}
diff --git a/chrome/browser/net/net_log_logger.h b/chrome/browser/net/net_log_logger.h
deleted file mode 100644
index bc9b19b..0000000
--- a/chrome/browser/net/net_log_logger.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_NET_NET_LOG_LOGGER_H_
-#define CHROME_BROWSER_NET_NET_LOG_LOGGER_H_
-
-#include <stdio.h>
-
-#include "base/memory/scoped_handle.h"
-#include "net/base/net_log.h"
-
-namespace base {
-class FilePath;
-}
-
-// NetLogLogger watches the NetLog event stream, and sends all entries to
-// a file specified on creation.  This is to debug errors in cases where
-// about:net-internals doesn't work well (Mobile, startup / shutdown errors,
-// errors that prevent getting to the about:net-internals).
-//
-// The text file will contain a single JSON object.
-//
-// Relies on ChromeNetLog only calling an Observer once at a time for
-// thread-safety.
-class NetLogLogger : public net::NetLog::ThreadSafeObserver {
- public:
-  // Takes ownership of |file| and will write network events to it once logging
-  // starts.  |file| must be non-NULL handle and be open for writing.
-  explicit NetLogLogger(FILE* file);
-  virtual ~NetLogLogger();
-
-  // Starts observing specified NetLog.  Must not already be watching a NetLog.
-  // Separate from constructor to enforce thread safety.
-  void StartObserving(net::NetLog* net_log);
-
-  // Stops observing net_log().  Must already be watching.
-  void StopObserving();
-
-  // net::NetLog::ThreadSafeObserver implementation:
-  virtual void OnAddEntry(const net::NetLog::Entry& entry) OVERRIDE;
-
- private:
-  ScopedStdioHandle file_;
-
-  // True if OnAddEntry() has been called at least once.
-  bool added_events_;
-
-  DISALLOW_COPY_AND_ASSIGN(NetLogLogger);
-};
-
-#endif  // CHROME_BROWSER_NET_NET_LOG_LOGGER_H_
diff --git a/chrome/browser/net/net_log_logger_unittest.cc b/chrome/browser/net/net_log_logger_unittest.cc
deleted file mode 100644
index 52bbc624..0000000
--- a/chrome/browser/net/net_log_logger_unittest.cc
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/net/net_log_logger.h"
-
-#include "base/file_util.h"
-#include "base/files/file_path.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/json/json_reader.h"
-#include "base/values.h"
-#include "net/base/net_log.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-class NetLogLoggerTest : public testing::Test {
- public:
-  virtual void SetUp() {
-    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
-    log_path_ = temp_dir_.path().AppendASCII("NetLogFile");
-  }
-
- protected:
-  base::ScopedTempDir temp_dir_;
-  base::FilePath log_path_;
-};
-
-TEST_F(NetLogLoggerTest, GeneratesValidJSONForNoEvents) {
-  {
-    // Create and destroy a logger.
-    FILE* file = file_util::OpenFile(log_path_, "w");
-    ASSERT_TRUE(file);
-    NetLogLogger logger(file);
-  }
-
-  std::string input;
-  ASSERT_TRUE(file_util::ReadFileToString(log_path_, &input));
-
-  base::JSONReader reader;
-  scoped_ptr<base::Value> root(reader.ReadToValue(input));
-  ASSERT_TRUE(root) << reader.GetErrorMessage();
-
-  base::DictionaryValue* dict;
-  ASSERT_TRUE(root->GetAsDictionary(&dict));
-  base::ListValue* events;
-  ASSERT_TRUE(dict->GetList("events", &events));
-  ASSERT_EQ(0u, events->GetSize());
-}
-
-TEST_F(NetLogLoggerTest, GeneratesValidJSONWithOneEvent) {
-  {
-    FILE* file = file_util::OpenFile(log_path_, "w");
-    ASSERT_TRUE(file);
-    NetLogLogger logger(file);
-
-    const int kDummyId = 1;
-    net::NetLog::Source source(net::NetLog::SOURCE_SPDY_SESSION, kDummyId);
-    net::NetLog::Entry entry(net::NetLog::TYPE_PROXY_SERVICE,
-                             source,
-                             net::NetLog::PHASE_BEGIN,
-                             base::TimeTicks::Now(),
-                             NULL,
-                             net::NetLog::LOG_BASIC);
-    logger.OnAddEntry(entry);
-  }
-
-  std::string input;
-  ASSERT_TRUE(file_util::ReadFileToString(log_path_, &input));
-
-  base::JSONReader reader;
-  scoped_ptr<base::Value> root(reader.ReadToValue(input));
-  ASSERT_TRUE(root) << reader.GetErrorMessage();
-
-  base::DictionaryValue* dict;
-  ASSERT_TRUE(root->GetAsDictionary(&dict));
-  base::ListValue* events;
-  ASSERT_TRUE(dict->GetList("events", &events));
-  ASSERT_EQ(1u, events->GetSize());
-}
-
-TEST_F(NetLogLoggerTest, GeneratesValidJSONWithMultipleEvents) {
-  {
-    FILE* file = file_util::OpenFile(log_path_, "w");
-    ASSERT_TRUE(file);
-    NetLogLogger logger(file);
-
-    const int kDummyId = 1;
-    net::NetLog::Source source(net::NetLog::SOURCE_SPDY_SESSION, kDummyId);
-    net::NetLog::Entry entry(net::NetLog::TYPE_PROXY_SERVICE,
-                             source,
-                             net::NetLog::PHASE_BEGIN,
-                             base::TimeTicks::Now(),
-                             NULL,
-                             net::NetLog::LOG_BASIC);
-
-    // Add the entry multiple times.
-    logger.OnAddEntry(entry);
-    logger.OnAddEntry(entry);
-  }
-
-  std::string input;
-  ASSERT_TRUE(file_util::ReadFileToString(log_path_, &input));
-
-  base::JSONReader reader;
-  scoped_ptr<base::Value> root(reader.ReadToValue(input));
-  ASSERT_TRUE(root) << reader.GetErrorMessage();
-
-  base::DictionaryValue* dict;
-  ASSERT_TRUE(root->GetAsDictionary(&dict));
-  base::ListValue* events;
-  ASSERT_TRUE(dict->GetList("events", &events));
-  ASSERT_EQ(2u, events->GetSize());
-}
diff --git a/chrome/browser/net/net_log_temp_file.cc b/chrome/browser/net/net_log_temp_file.cc
index e7e2869..c764d1f 100644
--- a/chrome/browser/net/net_log_temp_file.cc
+++ b/chrome/browser/net/net_log_temp_file.cc
@@ -7,8 +7,9 @@
 #include "base/file_util.h"
 #include "base/values.h"
 #include "chrome/browser/net/chrome_net_log.h"
-#include "chrome/browser/net/net_log_logger.h"
+#include "chrome/browser/ui/webui/net_internals/net_internals_ui.h"
 #include "content/public/browser/browser_thread.h"
+#include "net/base/net_log_logger.h"
 
 using content::BrowserThread;
 
@@ -99,7 +100,8 @@
   if (file == NULL)
     return;
 
-  net_log_logger_.reset(new NetLogLogger(file));
+  scoped_ptr<base::Value> constants(NetInternalsUI::GetConstants());
+  net_log_logger_.reset(new net::NetLogLogger(file, *constants));
   net_log_logger_->StartObserving(chrome_net_log_);
   state_ = STATE_ALLOW_STOP;
 }
diff --git a/chrome/browser/net/net_log_temp_file.h b/chrome/browser/net/net_log_temp_file.h
index 83d3d85..4688526 100644
--- a/chrome/browser/net/net_log_temp_file.h
+++ b/chrome/browser/net/net_log_temp_file.h
@@ -16,8 +16,11 @@
 class DictionaryValue;
 }
 
-class ChromeNetLog;
+namespace net {
 class NetLogLogger;
+}
+
+class ChromeNetLog;
 
 // NetLogTempFile logs all the NetLog entries into a temporary file
 // "chrome-net-export-log.json" created in file_util::GetTempDir() directory.
@@ -123,7 +126,7 @@
 
   // |net_log_logger_| watches the NetLog event stream, and sends all entries to
   // the file created in StartNetLog().
-  scoped_ptr<NetLogLogger> net_log_logger_;
+  scoped_ptr<net::NetLogLogger> net_log_logger_;
 
   // The |chrome_net_log_| is owned by the browser process, cached here to avoid
   // using global (g_browser_process).
diff --git a/chrome/browser/net/net_log_temp_file_unittest.cc b/chrome/browser/net/net_log_temp_file_unittest.cc
index 553c820..e77ecc5 100644
--- a/chrome/browser/net/net_log_temp_file_unittest.cc
+++ b/chrome/browser/net/net_log_temp_file_unittest.cc
@@ -79,7 +79,7 @@
 
   virtual void TearDown() OVERRIDE {
     // Delete the temporary file we have created.
-    ASSERT_TRUE(file_util::Delete(net_export_log_, false));
+    ASSERT_TRUE(base::Delete(net_export_log_, false));
   }
 
   std::string GetStateString() const {
diff --git a/chrome/browser/net/network_stats.cc b/chrome/browser/net/network_stats.cc
index a2ac5e4..5ea2ed2 100644
--- a/chrome/browser/net/network_stats.cc
+++ b/chrome/browser/net/network_stats.cc
@@ -12,11 +12,10 @@
 #include "base/rand_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/platform_thread.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/tuple.h"
 #include "chrome/common/chrome_version_info.h"
 #include "content/public/browser/browser_thread.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/net_errors.h"
 #include "net/base/net_util.h"
 #include "net/base/network_change_notifier.h"
@@ -25,6 +24,7 @@
 #include "net/proxy/proxy_service.h"
 #include "net/udp/udp_client_socket.h"
 #include "net/udp/udp_server_socket.h"
+#include "url/gurl.h"
 
 using content::BrowserThread;
 
diff --git a/chrome/browser/net/network_stats.h b/chrome/browser/net/network_stats.h
index d18aaf1..2d56c72 100644
--- a/chrome/browser/net/network_stats.h
+++ b/chrome/browser/net/network_stats.h
@@ -12,7 +12,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/string_util.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/io_thread.h"
 #include "net/base/address_list.h"
 #include "net/base/completion_callback.h"
diff --git a/chrome/browser/net/network_time_tracker.h b/chrome/browser/net/network_time_tracker.h
index 53e9bcc..5eaf97a 100644
--- a/chrome/browser/net/network_time_tracker.h
+++ b/chrome/browser/net/network_time_tracker.h
@@ -8,7 +8,7 @@
 #include "base/callback.h"
 #include "base/memory/weak_ptr.h"
 #include "base/threading/thread_checker.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "net/base/network_time_notifier.h"
 
 class IOThread;
diff --git a/chrome/browser/net/predictor.cc b/chrome/browser/net/predictor.cc
index b7061c7..67273cb 100644
--- a/chrome/browser/net/predictor.cc
+++ b/chrome/browser/net/predictor.cc
@@ -20,7 +20,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/threading/thread_restrictions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/io_thread.h"
 #include "chrome/browser/net/preconnect.h"
diff --git a/chrome/browser/net/predictor_unittest.cc b/chrome/browser/net/predictor_unittest.cc
index a2940a8..bc45792 100644
--- a/chrome/browser/net/predictor_unittest.cc
+++ b/chrome/browser/net/predictor_unittest.cc
@@ -11,7 +11,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/message_loop.h"
 #include "base/strings/string_number_conversions.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "base/values.h"
 #include "chrome/browser/net/predictor.h"
 #include "chrome/browser/net/url_info.h"
diff --git a/chrome/browser/net/referrer.h b/chrome/browser/net/referrer.h
index b38d96d..fb5d6d2 100644
--- a/chrome/browser/net/referrer.h
+++ b/chrome/browser/net/referrer.h
@@ -18,9 +18,9 @@
 #include <map>
 
 #include "base/basictypes.h"
-#include "base/time.h"
-#include "googleurl/src/gurl.h"
+#include "base/time/time.h"
 #include "net/base/host_port_pair.h"
+#include "url/gurl.h"
 
 namespace base {
 class Value;
diff --git a/chrome/browser/net/resource_prefetch_predictor_observer.cc b/chrome/browser/net/resource_prefetch_predictor_observer.cc
index c193f18..1ce3f8d 100644
--- a/chrome/browser/net/resource_prefetch_predictor_observer.cc
+++ b/chrome/browser/net/resource_prefetch_predictor_observer.cc
@@ -9,8 +9,8 @@
 #include "base/metrics/histogram.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/resource_request_info.h"
-#include "googleurl/src/gurl.h"
 #include "net/url_request/url_request.h"
+#include "url/gurl.h"
 
 using content::BrowserThread;
 using predictors::ResourcePrefetchPredictor;
diff --git a/chrome/browser/net/sqlite_server_bound_cert_store.cc b/chrome/browser/net/sqlite_server_bound_cert_store.cc
index cf2bca5..fe28561 100644
--- a/chrome/browser/net/sqlite_server_bound_cert_store.cc
+++ b/chrome/browser/net/sqlite_server_bound_cert_store.cc
@@ -19,7 +19,6 @@
 #include "base/threading/thread_restrictions.h"
 #include "chrome/browser/diagnostics/sqlite_diagnostics.h"
 #include "content/public/browser/browser_thread.h"
-#include "googleurl/src/gurl.h"
 #include "net/cert/x509_certificate.h"
 #include "net/cookies/cookie_util.h"
 #include "net/ssl/ssl_client_cert_type.h"
@@ -28,6 +27,7 @@
 #include "sql/statement.h"
 #include "sql/transaction.h"
 #include "third_party/sqlite/sqlite3.h"
+#include "url/gurl.h"
 #include "webkit/browser/quota/special_storage_policy.h"
 
 using content::BrowserThread;
diff --git a/chrome/browser/net/timed_cache.cc b/chrome/browser/net/timed_cache.cc
index e88fd27..2d0dd94 100644
--- a/chrome/browser/net/timed_cache.cc
+++ b/chrome/browser/net/timed_cache.cc
@@ -4,7 +4,7 @@
 
 #include "chrome/browser/net/timed_cache.h"
 
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 namespace chrome_browser_net {
 
diff --git a/chrome/browser/net/timed_cache.h b/chrome/browser/net/timed_cache.h
index f8b3c3b..dfcdc98 100644
--- a/chrome/browser/net/timed_cache.h
+++ b/chrome/browser/net/timed_cache.h
@@ -7,7 +7,7 @@
 
 #include "base/basictypes.h"
 #include "base/containers/mru_cache.h"
-#include "base/time.h"
+#include "base/time/time.h"
 
 class GURL;
 
diff --git a/chrome/browser/net/url_fixer_upper.cc b/chrome/browser/net/url_fixer_upper.cc
index fc68d2a..6c82ba4 100644
--- a/chrome/browser/net/url_fixer_upper.cc
+++ b/chrome/browser/net/url_fixer_upper.cc
@@ -14,12 +14,12 @@
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/common/url_constants.h"
-#include "googleurl/src/url_file.h"
-#include "googleurl/src/url_parse.h"
-#include "googleurl/src/url_util.h"
 #include "net/base/escape.h"
 #include "net/base/net_util.h"
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+#include "url/url_file.h"
+#include "url/url_parse.h"
+#include "url/url_util.h"
 
 const char* URLFixerUpper::home_directory_override = NULL;
 
diff --git a/chrome/browser/net/url_fixer_upper.h b/chrome/browser/net/url_fixer_upper.h
index eaf89c8..57ed512 100644
--- a/chrome/browser/net/url_fixer_upper.h
+++ b/chrome/browser/net/url_fixer_upper.h
@@ -8,7 +8,7 @@
 #include <string>
 
 #include "base/strings/string16.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 namespace base {
 class FilePath;
diff --git a/chrome/browser/net/url_fixer_upper_unittest.cc b/chrome/browser/net/url_fixer_upper_unittest.cc
index 706418a..5dc335c 100644
--- a/chrome/browser/net/url_fixer_upper_unittest.cc
+++ b/chrome/browser/net/url_fixer_upper_unittest.cc
@@ -11,10 +11,10 @@
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/net/url_fixer_upper.h"
 #include "chrome/common/chrome_paths.h"
-#include "googleurl/src/gurl.h"
-#include "googleurl/src/url_parse.h"
 #include "net/base/net_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+#include "url/url_parse.h"
 
 namespace {
   class URLFixerUpperTest : public testing::Test {
@@ -459,7 +459,7 @@
         file_cases[i].desired_tld).possibly_invalid_spec());
   }
 
-  EXPECT_TRUE(file_util::Delete(original, false));
+  EXPECT_TRUE(base::Delete(original, false));
 }
 
 TEST(URLFixerUpperTest, FixupRelativeFile) {
@@ -483,7 +483,7 @@
   // are no backslashes
   EXPECT_TRUE(IsMatchingFileURL(URLFixerUpper::FixupRelativeFile(dir,
       file_part).possibly_invalid_spec(), full_path));
-  EXPECT_TRUE(file_util::Delete(full_path, false));
+  EXPECT_TRUE(base::Delete(full_path, false));
 
   // create a filename we know doesn't exist and make sure it doesn't get
   // fixed up to a file URL
@@ -527,8 +527,8 @@
       base::FilePath(relative_file_str)).possibly_invalid_spec(), full_path));
 
   // done with the subdir
-  EXPECT_TRUE(file_util::Delete(full_path, false));
-  EXPECT_TRUE(file_util::Delete(new_dir, true));
+  EXPECT_TRUE(base::Delete(full_path, false));
+  EXPECT_TRUE(base::Delete(new_dir, true));
 
   // Test that an obvious HTTP URL isn't accidentally treated as an absolute
   // file path (on account of system-specific craziness).
diff --git a/chrome/browser/net/url_info.h b/chrome/browser/net/url_info.h
index 54c8159..e8e3408 100644
--- a/chrome/browser/net/url_info.h
+++ b/chrome/browser/net/url_info.h
@@ -19,9 +19,9 @@
 #include <string>
 #include <vector>
 
-#include "base/time.h"
-#include "googleurl/src/gurl.h"
+#include "base/time/time.h"
 #include "net/base/host_port_pair.h"
+#include "url/gurl.h"
 
 namespace chrome_browser_net {
 
diff --git a/chrome/browser/net/url_info_unittest.cc b/chrome/browser/net/url_info_unittest.cc
index 1ae6a89..730bb96 100644
--- a/chrome/browser/net/url_info_unittest.cc
+++ b/chrome/browser/net/url_info_unittest.cc
@@ -8,7 +8,7 @@
 #include <string>
 
 #include "base/threading/platform_thread.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/net/url_info.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/chrome/browser/notifications/balloon_collection_base.cc b/chrome/browser/notifications/balloon_collection_base.cc
index c97c14d..c748739 100644
--- a/chrome/browser/notifications/balloon_collection_base.cc
+++ b/chrome/browser/notifications/balloon_collection_base.cc
@@ -7,7 +7,7 @@
 #include "base/stl_util.h"
 #include "chrome/browser/notifications/balloon.h"
 #include "chrome/browser/notifications/notification.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 BalloonCollectionBase::BalloonCollectionBase() {
 }
diff --git a/chrome/browser/notifications/desktop_notification_service.cc b/chrome/browser/notifications/desktop_notification_service.cc
index 7459310..1fc2985 100644
--- a/chrome/browser/notifications/desktop_notification_service.cc
+++ b/chrome/browser/notifications/desktop_notification_service.cc
@@ -20,6 +20,8 @@
 #include "chrome/browser/notifications/notification.h"
 #include "chrome/browser/notifications/notification_object_proxy.h"
 #include "chrome/browser/notifications/notification_ui_manager.h"
+#include "chrome/browser/notifications/sync_notifier/chrome_notifier_service.h"
+#include "chrome/browser/notifications/sync_notifier/chrome_notifier_service_factory.h"
 #include "chrome/browser/prefs/scoped_user_pref_update.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
@@ -50,46 +52,13 @@
 using content::BrowserThread;
 using content::RenderViewHost;
 using content::WebContents;
+using message_center::NotifierId;
 using WebKit::WebNotificationPresenter;
 using WebKit::WebTextDirection;
 using WebKit::WebSecurityOrigin;
 
 const ContentSetting kDefaultSetting = CONTENT_SETTING_ASK;
 
-namespace {
-
-void ToggleListPrefItem(PrefService* prefs, const char* key,
-                        const std::string& item, bool flag) {
-  ListPrefUpdate update(prefs, key);
-  base::ListValue* const list = update.Get();
-  if (flag) {
-    // AppendIfNotPresent will delete |adding_value| when the same value
-    // already exists.
-    base::StringValue* const adding_value = new base::StringValue(item);
-    list->AppendIfNotPresent(adding_value);
-  } else {
-    base::StringValue removed_value(item);
-    list->Remove(removed_value, NULL);
-  }
-}
-
-void CopySetFromPrefToMemory(PrefService* prefs, const char* key,
-                             std::set<std::string>* dst) {
-  dst->clear();
-  const base::ListValue* pref_list = prefs->GetList(key);
-  for (size_t i = 0; i < pref_list->GetSize(); ++i) {
-    std::string element;
-    if (!pref_list->GetString(i, &element) && element.empty()) {
-      LOG(WARNING) << i << "-th element is not a string for "
-                   << key;
-      continue;
-    }
-    dst->insert(element);
-  }
-}
-
-}  // namespace
-
 // NotificationPermissionInfoBarDelegate --------------------------------------
 
 // The delegate for the infobar shown when an origin requests notification
@@ -234,6 +203,8 @@
                              user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
   registry->RegisterListPref(prefs::kMessageCenterDisabledSystemComponentIds,
                              user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+  registry->RegisterListPref(prefs::kMessageCenterEnabledSyncNotifierIds,
+                             user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
 }
 
 // static
@@ -351,22 +322,53 @@
     NotificationUIManager* ui_manager)
     : profile_(profile),
       ui_manager_(ui_manager) {
-  OnDisabledExtensionIdsChanged();
-  OnDisabledSystemComponentIdsChanged();
+  OnStringListPrefChanged(
+      prefs::kMessageCenterDisabledExtensionIds, &disabled_extension_ids_);
+  OnStringListPrefChanged(
+      prefs::kMessageCenterDisabledSystemComponentIds,
+      &disabled_system_component_ids_);
+  OnStringListPrefChanged(
+      prefs::kMessageCenterEnabledSyncNotifierIds, &enabled_sync_notifier_ids_);
   disabled_extension_id_pref_.Init(
       prefs::kMessageCenterDisabledExtensionIds,
       profile_->GetPrefs(),
       base::Bind(
-          &DesktopNotificationService::OnDisabledExtensionIdsChanged,
-          base::Unretained(this)));
+          &DesktopNotificationService::OnStringListPrefChanged,
+          base::Unretained(this),
+          base::Unretained(prefs::kMessageCenterDisabledExtensionIds),
+          base::Unretained(&disabled_extension_ids_)));
   disabled_system_component_id_pref_.Init(
       prefs::kMessageCenterDisabledSystemComponentIds,
       profile_->GetPrefs(),
       base::Bind(
-          &DesktopNotificationService::OnDisabledSystemComponentIdsChanged,
-          base::Unretained(this)));
+          &DesktopNotificationService::OnStringListPrefChanged,
+          base::Unretained(this),
+          base::Unretained(prefs::kMessageCenterDisabledSystemComponentIds),
+          base::Unretained(&disabled_system_component_ids_)));
+  enabled_sync_notifier_id_pref_.Init(
+      prefs::kMessageCenterEnabledSyncNotifierIds,
+      profile_->GetPrefs(),
+      base::Bind(
+          &DesktopNotificationService::OnStringListPrefChanged,
+          base::Unretained(this),
+          base::Unretained(prefs::kMessageCenterEnabledSyncNotifierIds),
+          base::Unretained(&enabled_sync_notifier_ids_)));
   registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
                  content::Source<Profile>(profile_));
+  // TODO(mukai, petewil): invoking notifier_service here directly may cause
+  // crashes on several tests, since notifier_service relies on
+  // NotificationUIManager in g_browser_process. To suppress the crashes,
+  // here checks if it really needs to ping notifier_service here.
+  if (!enabled_sync_notifier_ids_.empty()) {
+    notifier::ChromeNotifierService* notifier_service =
+        notifier::ChromeNotifierServiceFactory::GetInstance()->GetForProfile(
+            profile, Profile::EXPLICIT_ACCESS);
+    for (std::set<std::string>::const_iterator it =
+             enabled_sync_notifier_ids_.begin();
+         it != enabled_sync_notifier_ids_.end(); ++it) {
+      notifier_service->OnSyncedNotificationServiceEnabled(*it, true);
+    }
+  }
 }
 
 DesktopNotificationService::~DesktopNotificationService() {
@@ -534,7 +536,8 @@
           &extensions);
       for (ExtensionSet::const_iterator iter = extensions.begin();
            iter != extensions.end(); ++iter) {
-        if (IsExtensionEnabled((*iter)->id()))
+        NotifierId notifier_id(NotifierId::APPLICATION, (*iter)->id());
+        if (IsNotifierEnabled(notifier_id))
           return UTF8ToUTF16((*iter)->name());
       }
     }
@@ -557,49 +560,88 @@
   return ui_manager_;
 }
 
-bool DesktopNotificationService::IsExtensionEnabled(const std::string& id) {
-  return disabled_extension_ids_.find(id) == disabled_extension_ids_.end();
+bool DesktopNotificationService::IsNotifierEnabled(
+    const NotifierId& notifier_id) {
+  switch (notifier_id.type) {
+    case NotifierId::APPLICATION:
+      return disabled_extension_ids_.find(notifier_id.id) ==
+          disabled_extension_ids_.end();
+    case NotifierId::WEB_PAGE:
+      return GetContentSetting(notifier_id.url) == CONTENT_SETTING_ALLOW;
+    case NotifierId::SYSTEM_COMPONENT:
+      return disabled_system_component_ids_.find(
+          message_center::ToString(notifier_id.system_component_type)) ==
+          disabled_system_component_ids_.end();
+    case NotifierId::SYNCED_NOTIFICATION_SERVICE:
+      return enabled_sync_notifier_ids_.find(notifier_id.id) !=
+          enabled_sync_notifier_ids_.end();
+  }
+
+  NOTREACHED();
+  return false;
 }
 
-void DesktopNotificationService::SetExtensionEnabled(
-    const std::string& id, bool enabled) {
-  // Do not touch |disabled_extension_ids_|. It will be updated at
-  // OnDisabledExtensionIdsChanged() which will be called when the pref changes.
-  ToggleListPrefItem(
-      profile_->GetPrefs(),
-      prefs::kMessageCenterDisabledExtensionIds,
-      id,
-      !enabled);
+void DesktopNotificationService::SetNotifierEnabled(
+    const NotifierId& notifier_id,
+    bool enabled) {
+  DCHECK_NE(NotifierId::WEB_PAGE, notifier_id.type);
+
+  bool add_new_item = false;
+  const char* pref_name = NULL;
+  scoped_ptr<base::StringValue> id;
+  switch (notifier_id.type) {
+    case NotifierId::APPLICATION:
+      pref_name = prefs::kMessageCenterDisabledExtensionIds;
+      add_new_item = !enabled;
+      id.reset(new base::StringValue(notifier_id.id));
+      break;
+    case NotifierId::SYSTEM_COMPONENT:
+      pref_name = prefs::kMessageCenterDisabledSystemComponentIds;
+      add_new_item = !enabled;
+      id.reset(new base::StringValue(
+          message_center::ToString(notifier_id.system_component_type)));
+      break;
+    case NotifierId::SYNCED_NOTIFICATION_SERVICE:
+      pref_name = prefs::kMessageCenterEnabledSyncNotifierIds;
+      // Adding a new item if |enabled| == true, since synced notification
+      // services are opt-in.
+      add_new_item = enabled;
+      id.reset(new base::StringValue(notifier_id.id));
+      break;
+    default:
+      NOTREACHED();
+  }
+  DCHECK(pref_name != NULL);
+
+  {
+    ListPrefUpdate update(profile_->GetPrefs(), pref_name);
+    base::ListValue* const list = update.Get();
+    if (add_new_item) {
+      // AppendIfNotPresent will delete |adding_value| when the same value
+      // already exists.
+      list->AppendIfNotPresent(id.release());
+    } else {
+      list->Remove(*id, NULL);
+    }
+  }
 }
 
-void DesktopNotificationService::OnDisabledExtensionIdsChanged() {
-  CopySetFromPrefToMemory(profile_->GetPrefs(),
-                          prefs::kMessageCenterDisabledExtensionIds,
-                          &disabled_extension_ids_);
+bool DesktopNotificationService::IsExtensionEnabled(
+    const std::string& extension_id) {
+  return IsNotifierEnabled(NotifierId(NotifierId::APPLICATION, extension_id));
 }
 
-bool DesktopNotificationService::IsSystemComponentEnabled(
-    message_center::Notifier::SystemComponentNotifierType type) {
-  return disabled_system_component_ids_.find(message_center::ToString(type)) ==
-         disabled_system_component_ids_.end();
-}
-
-void DesktopNotificationService::SetSystemComponentEnabled(
-    message_center::Notifier::SystemComponentNotifierType type, bool enabled) {
-  // Do not touch |disabled_extension_ids_|. It will be updated at
-  // OnDisabledExtensionIdsChanged() which will be called when the pref changes.
-  ToggleListPrefItem(
-      profile_->GetPrefs(),
-      prefs::kMessageCenterDisabledSystemComponentIds,
-      message_center::ToString(type),
-      !enabled);
-}
-
-void DesktopNotificationService::OnDisabledSystemComponentIdsChanged() {
-  disabled_system_component_ids_.clear();
-  CopySetFromPrefToMemory(profile_->GetPrefs(),
-                          prefs::kMessageCenterDisabledSystemComponentIds,
-                          &disabled_system_component_ids_);
+void DesktopNotificationService::OnStringListPrefChanged(
+    const char* pref_name, std::set<std::string>* ids_field) {
+  ids_field->clear();
+  const base::ListValue* pref_list = profile_->GetPrefs()->GetList(pref_name);
+  for (size_t i = 0; i < pref_list->GetSize(); ++i) {
+    std::string element;
+    if (pref_list->GetString(i, &element) && !element.empty())
+      ids_field->insert(element);
+    else
+      LOG(WARNING) << i << "-th element is not a string for " << pref_name;
+  }
 }
 
 WebKit::WebNotificationPresenter::Permission
@@ -631,8 +673,9 @@
 
   extensions::Extension* extension =
       content::Details<extensions::Extension>(details).ptr();
-  if (IsExtensionEnabled(extension->id()))
+  NotifierId notifier_id(NotifierId::APPLICATION, extension->id());
+  if (IsNotifierEnabled(notifier_id))
     return;
 
-  SetExtensionEnabled(extension->id(), true);
+  SetNotifierEnabled(notifier_id, true);
 }
diff --git a/chrome/browser/notifications/desktop_notification_service.h b/chrome/browser/notifications/desktop_notification_service.h
index bad1d6f..3783950 100644
--- a/chrome/browser/notifications/desktop_notification_service.h
+++ b/chrome/browser/notifications/desktop_notification_service.h
@@ -18,10 +18,10 @@
 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
-#include "googleurl/src/gurl.h"
 #include "third_party/WebKit/public/web/WebNotificationPresenter.h"
 #include "third_party/WebKit/public/web/WebTextDirection.h"
 #include "ui/message_center/notifier_settings.h"
+#include "url/gurl.h"
 
 class ContentSettingsPattern;
 class Notification;
@@ -152,21 +152,17 @@
   WebKit::WebNotificationPresenter::Permission
       HasPermission(const GURL& origin);
 
-  // Returns true if the extension of the specified |id| is allowed to send
+  // Returns true if the notifier with |notifier_id| is allowed to send
   // notifications.
-  bool IsExtensionEnabled(const std::string& id);
+  bool IsNotifierEnabled(const message_center::NotifierId& notifier_id);
 
-  // Updates the availability of the extension to send notifications.
-  void SetExtensionEnabled(const std::string& id, bool enabled);
+  // Updates the availability of the notifier.
+  void SetNotifierEnabled(const message_center::NotifierId& notifier_id,
+                          bool enabled);
 
-  // Returns true if the system component of the specified |id| is allowed to
-  // send notifications.
-  bool IsSystemComponentEnabled(
-      message_center::Notifier::SystemComponentNotifierType type);
-
-  // Updates the availability of the system component to send notifications.
-  void SetSystemComponentEnabled(
-      message_center::Notifier::SystemComponentNotifierType type, bool enabled);
+  // IsExtensionEnabled is obsoleted, do not use this.
+  // TODO(mukai): remove this.
+  bool IsExtensionEnabled(const std::string& extension_id);
 
  private:
   // Takes a notification object and shows it in the UI.
@@ -182,12 +178,19 @@
 
   NotificationUIManager* GetUIManager();
 
+  // Called when the string list pref has been changed.
+  void OnStringListPrefChanged(
+      const char* pref_name, std::set<std::string>* ids_field);
+
   // Called when the disabled_extension_id pref has been changed.
   void OnDisabledExtensionIdsChanged();
 
   // Called when the disabled_system_component_id pref has been changed.
   void OnDisabledSystemComponentIdsChanged();
 
+  // Called when the enabled_sync_notifier_id pref has been changed.
+  void OnEnabledSyncNotifierIdsChanged();
+
   // content::NotificationObserver override.
   virtual void Observe(int type,
                        const content::NotificationSource& source,
@@ -203,15 +206,21 @@
   // Prefs listener for disabled_extension_id.
   StringListPrefMember disabled_extension_id_pref_;
 
-  // Prefs listener for disabled_extension_id.
+  // Prefs listener for disabled_system_component_id.
   StringListPrefMember disabled_system_component_id_pref_;
 
+  // Prefs listener for enabled_sync_notifier_id.
+  StringListPrefMember enabled_sync_notifier_id_pref_;
+
   // On-memory data for the availability of extensions.
   std::set<std::string> disabled_extension_ids_;
 
   // On-memory data for the availability of system_component.
   std::set<std::string> disabled_system_component_ids_;
 
+  // On-memory data for the availability of sync notifiers.
+  std::set<std::string> enabled_sync_notifier_ids_;
+
   // Registrar for the other kind of notifications (event signaling).
   content::NotificationRegistrar registrar_;
 
diff --git a/chrome/browser/notifications/desktop_notifications_unittest.cc b/chrome/browser/notifications/desktop_notifications_unittest.cc
index a539e7b..7b969f3 100644
--- a/chrome/browser/notifications/desktop_notifications_unittest.cc
+++ b/chrome/browser/notifications/desktop_notifications_unittest.cc
@@ -21,7 +21,6 @@
 #if defined(USE_ASH)
 #include "ash/shell.h"
 #include "ash/test/test_shell_delegate.h"
-#include "chrome/browser/ui/aura/active_desktop_monitor.h"
 #include "third_party/WebKit/public/web/WebKit.h"
 #include "ui/aura/env.h"
 #include "ui/aura/root_window.h"
@@ -113,7 +112,6 @@
   // MockBalloonCollection retrieves information about the screen on creation.
   // So it is necessary to make sure the desktop gets created first.
   ash::Shell::CreateInstance(new ash::test::TestShellDelegate);
-  active_desktop_monitor_.reset(new ActiveDesktopMonitor);
 #endif
 
   chrome::RegisterLocalState(local_state_.registry());
@@ -130,7 +128,6 @@
   ui_manager_.reset(NULL);
   profile_.reset(NULL);
 #if defined(USE_ASH)
-  active_desktop_monitor_.reset();
   ash::Shell::DeleteInstance();
   // The message center is notmally shutdown on |g_browser_process| which
   // is not created for these tests.
diff --git a/chrome/browser/notifications/desktop_notifications_unittest.h b/chrome/browser/notifications/desktop_notifications_unittest.h
index 1aa5947..ad8d0d8 100644
--- a/chrome/browser/notifications/desktop_notifications_unittest.h
+++ b/chrome/browser/notifications/desktop_notifications_unittest.h
@@ -117,8 +117,6 @@
 #if defined(USE_ASH)
   content::RenderViewTest::RendererWebKitPlatformSupportImplNoSandbox
       webkit_platform_support_;
-
-  scoped_ptr<ActiveDesktopMonitor> active_desktop_monitor_;
 #endif
 
   // Contains the cumulative output of the unit test.
diff --git a/chrome/browser/notifications/message_center_notification_manager.cc b/chrome/browser/notifications/message_center_notification_manager.cc
index be8bd2e..d0cbb7e 100644
--- a/chrome/browser/notifications/message_center_notification_manager.cc
+++ b/chrome/browser/notifications/message_center_notification_manager.cc
@@ -25,12 +25,29 @@
 #include "ui/message_center/message_center_tray.h"
 #include "ui/message_center/notifier_settings.h"
 
+namespace {
+// The first-run balloon will be shown |kFirstRunIdleDelaySeconds| after all
+// popups go away and the user has notifications in the message center.
+const int kFirstRunIdleDelaySeconds = 1;
+}  // namespace
+
 MessageCenterNotificationManager::MessageCenterNotificationManager(
-    message_center::MessageCenter* message_center)
+    message_center::MessageCenter* message_center,
+    PrefService* local_state)
     : message_center_(message_center),
+#if defined(OS_WIN)
+      first_run_idle_timeout_(
+          base::TimeDelta::FromSeconds(kFirstRunIdleDelaySeconds)),
+      weak_factory_(this),
+#endif
       settings_controller_(new MessageCenterSettingsController) {
+#if defined(OS_WIN)
+  first_run_pref_.Init(prefs::kMessageCenterShowedFirstRunBalloon, local_state);
+#endif
+
   message_center_->SetDelegate(this);
   message_center_->AddObserver(this);
+  message_center_->SetNotifierSettingsProvider(settings_controller_.get());
 
 #if defined(OS_WIN) || defined(OS_MACOSX) \
   || (defined(USE_AURA) && !defined(USE_ASH))
@@ -44,7 +61,6 @@
   message_center_->RemoveObserver(this);
 }
 
-
 ////////////////////////////////////////////////////////////////////////////////
 // NotificationUIManager
 
@@ -83,7 +99,7 @@
   for (NotificationMap::iterator iter = profile_notifications_.begin();
        iter != profile_notifications_.end(); iter++) {
     if ((*iter).second->notification().origin_url() == source &&
-        profile->IsSameProfile((*iter).second->profile())) {
+        profile == (*iter).second->profile()) {
       notification_ids.insert(iter->first);
     }
   }
@@ -114,7 +130,7 @@
   for (NotificationMap::iterator loopiter = profile_notifications_.begin();
        loopiter != profile_notifications_.end(); ) {
     NotificationMap::iterator curiter = loopiter++;
-    if (profile->IsSameProfile((*curiter).second->profile())) {
+    if (profile == (*curiter).second->profile()) {
       message_center_->RemoveNotification(curiter->first, /* by_user */ false);
       removed = true;
     }
@@ -164,7 +180,7 @@
     ProfileNotification* old_notification = (*iter).second;
     if (old_notification->notification().replace_id() == replace_id &&
         old_notification->notification().origin_url() == origin_url &&
-        old_notification->profile()->IsSameProfile(profile)) {
+        old_notification->profile() == profile) {
       std::string old_id =
           old_notification->notification().notification_id();
       DCHECK(message_center_->HasNotification(old_id));
@@ -208,7 +224,9 @@
   DesktopNotificationService* service =
       DesktopNotificationServiceFactory::GetForProfile(
           profile_notification->profile());
-  service->SetExtensionEnabled(extension_id, false);
+  message_center::NotifierId notifier_id(
+      message_center::NotifierId::APPLICATION, extension_id);
+  service->SetNotifierEnabled(notifier_id, false);
 }
 
 void MessageCenterNotificationManager::DisableNotificationsFromSource(
@@ -227,9 +245,9 @@
       chrome::kChromeUIScheme) {
     const std::string name =
         profile_notification->notification().origin_url().host();
-    const message_center::Notifier::SystemComponentNotifierType type =
-        message_center::ParseSystemComponentName(name);
-    service->SetSystemComponentEnabled(type, false);
+    message_center::NotifierId notifier_id(
+        message_center::ParseSystemComponentName(name));
+    service->SetNotifierEnabled(notifier_id, false);
   } else {
     service->DenyPermission(profile_notification->notification().origin_url());
   }
@@ -257,11 +275,6 @@
     chrome::ShowExtensions(browser, std::string());
 }
 
-message_center::NotifierSettingsDelegate*
-MessageCenterNotificationManager::ShowSettingsDialog(gfx::NativeView context) {
-  return settings_controller_->ShowSettingsDialog(context);
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // MessageCenter::Observer
 void MessageCenterNotificationManager::OnNotificationRemoved(
@@ -274,12 +287,31 @@
       profile_notifications_.find(notification_id);
   if (iter != profile_notifications_.end())
     RemoveProfileNotification(iter->second, by_user);
+
+#if defined(OS_WIN)
+  CheckFirstRunTimer();
+#endif
 }
 
 void MessageCenterNotificationManager::OnNotificationCenterClosed() {
   // When the center is open it halts all notifications, so we need to listen
   // for events indicating it's been closed.
   CheckAndShowNotifications();
+#if defined(OS_WIN)
+  CheckFirstRunTimer();
+#endif
+}
+
+void MessageCenterNotificationManager::OnNotificationUpdated(
+    const std::string& notification_id) {
+#if defined(OS_WIN)
+  CheckFirstRunTimer();
+#endif
+}
+
+void MessageCenterNotificationManager::SetMessageCenterTrayDelegateForTest(
+    message_center::MessageCenterTrayDelegate* delegate) {
+  tray_.reset(delegate);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -377,8 +409,9 @@
 
   contents->DownloadImage(
       url,
-      false,
-      size,
+      false,  // Not a favicon
+      size,  // Preferred size
+      0,  // No maximum size
       base::Bind(
           &MessageCenterNotificationManager::ImageDownloads::DownloadComplete,
           AsWeakPtr(),
@@ -451,8 +484,10 @@
       DesktopNotificationServiceFactory::GetForProfile(profile());
   for (ExtensionSet::const_iterator iter = extensions.begin();
        iter != extensions.end(); ++iter) {
-    if (desktop_service->IsExtensionEnabled((*iter)->id()))
+    if (desktop_service->IsNotifierEnabled(message_center::NotifierId(
+            message_center::NotifierId::APPLICATION, (*iter)->id()))) {
       return (*iter)->id();
+    }
   }
   return std::string();
 }
diff --git a/chrome/browser/notifications/message_center_notification_manager.h b/chrome/browser/notifications/message_center_notification_manager.h
index ae5fc9a..8ae5ee5 100644
--- a/chrome/browser/notifications/message_center_notification_manager.h
+++ b/chrome/browser/notifications/message_center_notification_manager.h
@@ -9,6 +9,10 @@
 #include <string>
 
 #include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/prefs/pref_member.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/notifications/notification.h"
 #include "chrome/browser/notifications/notification_ui_manager.h"
 #include "chrome/browser/notifications/notification_ui_manager_impl.h"
@@ -18,6 +22,7 @@
 
 class MessageCenterSettingsController;
 class Notification;
+class PrefService;
 class Profile;
 
 // This class extends NotificationUIManagerImpl and delegates actual display
@@ -28,7 +33,8 @@
       public message_center::MessageCenterObserver {
  public:
   explicit MessageCenterNotificationManager(
-      message_center::MessageCenter* message_center);
+      message_center::MessageCenter* message_center,
+      PrefService* local_state);
   virtual ~MessageCenterNotificationManager();
 
   // NotificationUIManager
@@ -52,13 +58,27 @@
   virtual void DisableNotificationsFromSource(
       const std::string& notification_id) OVERRIDE;
   virtual void ShowSettings(const std::string& notification_id) OVERRIDE;
-  virtual message_center::NotifierSettingsDelegate* ShowSettingsDialog(
-      gfx::NativeView context) OVERRIDE;
 
   // MessageCenterObserver
   virtual void OnNotificationRemoved(const std::string& notification_id,
                                      bool by_user) OVERRIDE;
   virtual void OnNotificationCenterClosed() OVERRIDE;
+  virtual void OnNotificationUpdated(const std::string& notification_id)
+      OVERRIDE;
+
+#if defined(OS_WIN)
+  // Called when the pref changes for the first run balloon. The first run
+  // balloon is only displayed on Windows, since the visibility of the tray
+  // icon is limited.
+  void DisplayFirstRunBalloon();
+
+  void SetFirstRunTimeoutForTest(base::TimeDelta timeout);
+  bool FirstRunTimerIsActive() const;
+#endif
+
+  // Takes ownership of |delegate|.
+  void SetMessageCenterTrayDelegateForTest(
+      message_center::MessageCenterTrayDelegate* delegate);
 
  private:
   class ImageDownloadsObserver {
@@ -159,8 +179,6 @@
   typedef std::map<std::string, ProfileNotification*> NotificationMap;
   NotificationMap profile_notifications_;
 
-  scoped_ptr<MessageCenterSettingsController> settings_controller_;
-
   // Helpers that add/remove the notification from local map and MessageCenter.
   // They take ownership of profile_notification object.
   void AddProfileNotification(ProfileNotification* profile_notification);
@@ -171,6 +189,30 @@
   // notification is found.
   ProfileNotification* FindProfileNotification(const std::string& id) const;
 
+#if defined(OS_WIN)
+  // This function is run on update to ensure that the notification balloon is
+  // shown only when there are no popups present.
+  void CheckFirstRunTimer();
+
+  // |first_run_pref_| is used to keep track of whether we've ever shown the
+  // first run balloon before, even across restarts.
+  BooleanPrefMember first_run_pref_;
+
+  // The timer after which we will show the first run balloon.  This timer is
+  // restarted every time the message center is closed and every time the last
+  // popup disappears from the screen.
+  base::OneShotTimer<MessageCenterNotificationManager> first_run_balloon_timer_;
+
+  // The first-run balloon will be shown |first_run_idle_timeout_| after all
+  // popups go away and the user has notifications in the message center.
+  base::TimeDelta first_run_idle_timeout_;
+
+  // Provides weak pointers for the purpose of the first run timer.
+  base::WeakPtrFactory<MessageCenterNotificationManager> weak_factory_;
+#endif
+
+  scoped_ptr<MessageCenterSettingsController> settings_controller_;
+
   DISALLOW_COPY_AND_ASSIGN(MessageCenterNotificationManager);
 };
 
diff --git a/chrome/browser/notifications/message_center_notification_manager_win.cc b/chrome/browser/notifications/message_center_notification_manager_win.cc
new file mode 100644
index 0000000..43525d2
--- /dev/null
+++ b/chrome/browser/notifications/message_center_notification_manager_win.cc
@@ -0,0 +1,53 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/notifications/message_center_notification_manager.h"
+
+#include "chrome/common/pref_names.h"
+#include "ui/message_center/message_center_tray.h"
+
+void MessageCenterNotificationManager::DisplayFirstRunBalloon() {
+  // Store for posterity the fact that we've shown the first-run balloon.
+  DCHECK(tray_.get());
+  first_run_pref_.SetValue(true);
+  tray_->DisplayFirstRunBalloon();
+}
+
+void MessageCenterNotificationManager::SetFirstRunTimeoutForTest(
+    base::TimeDelta timeout) {
+  first_run_idle_timeout_ = timeout;
+}
+
+bool MessageCenterNotificationManager::FirstRunTimerIsActive() const {
+  return first_run_balloon_timer_.IsRunning();
+}
+
+void MessageCenterNotificationManager::CheckFirstRunTimer() {
+  // If there is no tray_, we can't display a balloon here anyway.
+  // Also, we only want to display the first run balloon once, so the pref will
+  // store the flag on disk based on whether we ever showed the balloon.
+  DCHECK(tray_.get());
+  if (first_run_pref_.GetValue())
+    return;
+
+  // If there are popups, the message center is visible, or there are no more
+  // notifications, don't continue the timer since it will be annoying or
+  // useless.
+  if (message_center_->HasPopupNotifications() ||
+      message_center_->IsMessageCenterVisible() ||
+      0 == message_center_->NotificationCount()) {
+    first_run_balloon_timer_.Stop();
+    return;
+  }
+
+  // No need to restart the timer if it's already going.
+  if (first_run_balloon_timer_.IsRunning())
+    return;
+
+  first_run_balloon_timer_.Start(
+      FROM_HERE,
+      first_run_idle_timeout_,
+      base::Bind(&MessageCenterNotificationManager::DisplayFirstRunBalloon,
+                 weak_factory_.GetWeakPtr()));
+}
diff --git a/chrome/browser/notifications/message_center_notifications_unittest_win.cc b/chrome/browser/notifications/message_center_notifications_unittest_win.cc
new file mode 100644
index 0000000..8846ecc
--- /dev/null
+++ b/chrome/browser/notifications/message_center_notifications_unittest_win.cc
@@ -0,0 +1,159 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/memory/scoped_ptr.h"
+#include "base/prefs/testing_pref_service.h"
+#include "base/run_loop.h"
+#include "base/test/test_timeouts.h"
+#include "base/values.h"
+#include "chrome/browser/notifications/message_center_notification_manager.h"
+#include "chrome/browser/notifications/notification.h"
+#include "chrome/browser/notifications/notification_prefs_manager.h"
+#include "chrome/browser/notifications/notification_test_util.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/base/scoped_testing_local_state.h"
+#include "chrome/test/base/testing_browser_process.h"
+#include "chrome/test/base/testing_profile.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/message_center/message_center_impl.h"
+#include "ui/message_center/message_center_tray.h"
+#include "ui/message_center/message_center_tray_delegate.h"
+
+namespace message_center {
+class FakeMessageCenterTrayDelegate : public MessageCenterTrayDelegate {
+ public:
+  FakeMessageCenterTrayDelegate(MessageCenter* message_center,
+                                base::Closure quit_closure)
+      : tray_(this, message_center),
+        quit_closure_(quit_closure),
+        displayed_first_run_balloon_(false) {}
+
+  virtual void DisplayFirstRunBalloon() OVERRIDE {
+    displayed_first_run_balloon_ = true;
+    base::MessageLoop::current()->PostTask(FROM_HERE, quit_closure_);
+  }
+
+  virtual void OnMessageCenterTrayChanged() OVERRIDE {}
+  virtual bool ShowPopups() OVERRIDE { return true; }
+  virtual void HidePopups() OVERRIDE {}
+  virtual void UpdatePopups() OVERRIDE {}
+  virtual bool ShowMessageCenter() OVERRIDE { return true; }
+  virtual bool ShowNotifierSettings() OVERRIDE { return true; }
+  virtual void HideMessageCenter() OVERRIDE {}
+
+  bool displayed_first_run_balloon() const {
+    return displayed_first_run_balloon_;
+  }
+ private:
+  MessageCenterTray tray_;
+  base::Closure quit_closure_;
+  bool displayed_first_run_balloon_;
+};
+
+class MessageCenterNotificationManagerTest : public testing::Test {
+ protected:
+  MessageCenterNotificationManagerTest() {
+    NotificationPrefsManager::RegisterPrefs(local_state_.registry());
+  }
+
+  virtual void SetUp() {
+    // Clear the preference and initialize.
+    local_state_.ClearPref(prefs::kMessageCenterShowedFirstRunBalloon);
+    first_run_pref_.Init(prefs::kMessageCenterShowedFirstRunBalloon,
+                         &local_state_);
+
+    // Get ourselves a run loop.
+    run_loop_.reset(new base::RunLoop());
+
+    // Initialize message center infrastructure with mock tray delegate.
+    MessageCenter::Initialize();
+    message_center_ = MessageCenter::Get();
+    notification_manager_.reset(
+        new MessageCenterNotificationManager(message_center_, &local_state_));
+    delegate_ = new FakeMessageCenterTrayDelegate(message_center_,
+                                                  run_loop_->QuitClosure());
+    notification_manager_->SetMessageCenterTrayDelegateForTest(delegate_);
+    notification_manager_->SetFirstRunTimeoutForTest(
+        TestTimeouts::tiny_timeout());
+  }
+
+  virtual void TearDown() {
+    run_loop_.reset();
+    notification_manager_.reset();
+    MessageCenter::Shutdown();
+  }
+
+  MessageCenterNotificationManager* notification_manager() {
+    return notification_manager_.get();
+  }
+
+  FakeMessageCenterTrayDelegate* delegate() { return delegate_; }
+
+  MessageCenter* message_center() { return message_center_; }
+
+  const ::Notification GetANotification(const std::string& id) {
+    return ::Notification(GURL(),
+                          GURL(),
+                          string16(),
+                          string16(),
+                          new MockNotificationDelegate(id));
+  }
+
+  base::RunLoop* run_loop() { return run_loop_.get(); }
+  const TestingPrefServiceSimple& local_state() { return local_state_; }
+  bool DidFirstRunPref() { return first_run_pref_.GetValue(); }
+
+ private:
+  scoped_ptr<base::RunLoop> run_loop_;
+  TestingPrefServiceSimple local_state_;
+  MessageCenter* message_center_;
+  scoped_ptr<MessageCenterNotificationManager> notification_manager_;
+  FakeMessageCenterTrayDelegate* delegate_;
+  content::TestBrowserThreadBundle thread_bundle_;
+  BooleanPrefMember first_run_pref_;
+};
+
+TEST_F(MessageCenterNotificationManagerTest, SetupNotificationManager) {
+  TestingProfile profile;
+  notification_manager()->Add(GetANotification("test"), &profile);
+  EXPECT_FALSE(DidFirstRunPref());
+}
+
+// The following tests test the first run balloon, which is only implemented for
+// Windows.
+TEST_F(MessageCenterNotificationManagerTest, FirstRunShown) {
+  TestingProfile profile;
+  notification_manager()->Add(GetANotification("test"), &profile);
+  message_center()->DisplayedNotification("test");
+  message_center()->MarkSinglePopupAsShown("test", false);
+
+  run_loop()->Run();
+  base::RunLoop run_loop_2;
+  run_loop_2.RunUntilIdle();
+  EXPECT_TRUE(delegate()->displayed_first_run_balloon());
+  EXPECT_TRUE(DidFirstRunPref());
+}
+
+TEST_F(MessageCenterNotificationManagerTest,
+       FirstRunNotShownWithPopupsVisible) {
+  TestingProfile profile;
+  notification_manager()->Add(GetANotification("test"), &profile);
+  message_center()->DisplayedNotification("test");
+  run_loop()->RunUntilIdle();
+  EXPECT_FALSE(delegate()->displayed_first_run_balloon());
+  EXPECT_FALSE(notification_manager()->FirstRunTimerIsActive());
+  EXPECT_FALSE(DidFirstRunPref());
+}
+
+TEST_F(MessageCenterNotificationManagerTest,
+       FirstRunNotShownWithMessageCenter) {
+  TestingProfile profile;
+  notification_manager()->Add(GetANotification("test"), &profile);
+  message_center()->SetMessageCenterVisible(true);
+  run_loop()->RunUntilIdle();
+  EXPECT_FALSE(notification_manager()->FirstRunTimerIsActive());
+  EXPECT_FALSE(DidFirstRunPref());
+}
+}  // namespace message_center
diff --git a/chrome/browser/notifications/message_center_settings_controller.cc b/chrome/browser/notifications/message_center_settings_controller.cc
index 924c669..9acefdf 100644
--- a/chrome/browser/notifications/message_center_settings_controller.cc
+++ b/chrome/browser/notifications/message_center_settings_controller.cc
@@ -6,6 +6,7 @@
 
 #include <algorithm>
 
+#include "base/command_line.h"
 #include "base/i18n/string_compare.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/extensions/app_icon_loader_impl.h"
@@ -16,6 +17,8 @@
 #include "chrome/browser/history/history_types.h"
 #include "chrome/browser/notifications/desktop_notification_service.h"
 #include "chrome/browser/notifications/desktop_notification_service_factory.h"
+#include "chrome/browser/notifications/sync_notifier/chrome_notifier_service.h"
+#include "chrome/browser/notifications/sync_notifier/chrome_notifier_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/common/cancelable_task_tracker.h"
@@ -27,7 +30,13 @@
 #include "ui/gfx/image/image.h"
 #include "ui/message_center/message_center_style.h"
 
+#if defined(USE_ASH)
+#include "ash/shell.h"
+#include "ash/system/web_notification/web_notification_tray.h"
+#endif
+
 using message_center::Notifier;
+using message_center::NotifierId;
 
 namespace {
 
@@ -50,24 +59,29 @@
 
 }  // namespace
 
-MessageCenterSettingsController::MessageCenterSettingsController()
-    : delegate_(NULL) {
+MessageCenterSettingsController::MessageCenterSettingsController() {
 }
 
 MessageCenterSettingsController::~MessageCenterSettingsController() {
 }
 
-message_center::NotifierSettingsDelegate*
-MessageCenterSettingsController::ShowSettingsDialog(gfx::NativeView context) {
-  delegate_ = message_center::ShowSettings(this, context);
-  return delegate_;
+void MessageCenterSettingsController::AddObserver(
+    message_center::NotifierSettingsObserver* observer) {
+  observers_.AddObserver(observer);
+}
+
+void MessageCenterSettingsController::RemoveObserver(
+    message_center::NotifierSettingsObserver* observer) {
+  observers_.RemoveObserver(observer);
 }
 
 void MessageCenterSettingsController::GetNotifierList(
     std::vector<Notifier*>* notifiers) {
   DCHECK(notifiers);
   // TODO(mukai): Fix this for multi-profile.
-  Profile* profile = ProfileManager::GetDefaultProfile();
+  // Temporarily use the last used profile to prevent chrome from crashing when
+  // the default profile is not loaded.
+  Profile* profile = ProfileManager::GetLastUsedProfileAllowedByPolicy();
   DesktopNotificationService* notification_service =
       DesktopNotificationServiceFactory::GetForProfile(profile);
 
@@ -94,16 +108,27 @@
       continue;
     }
 
-    notifiers->push_back(new message_center::Notifier(
-        extension->id(),
+    NotifierId notifier_id(NotifierId::APPLICATION, extension->id());
+    notifiers->push_back(new Notifier(
+        notifier_id,
         UTF8ToUTF16(extension->name()),
-        notification_service->IsExtensionEnabled(extension->id())));
+        notification_service->IsNotifierEnabled(notifier_id)));
     app_icon_loader_->FetchImage(extension->id());
   }
-  if (comparator)
-    std::sort(notifiers->begin(), notifiers->end(), *comparator);
-  else
-    std::sort(notifiers->begin(), notifiers->end(), SimpleCompareNotifiers);
+
+  if (notifier::ChromeNotifierServiceFactory::UseSyncedNotifications(
+          CommandLine::ForCurrentProcess())) {
+    notifier::ChromeNotifierService* sync_notifier_service =
+        notifier::ChromeNotifierServiceFactory::GetInstance()->GetForProfile(
+            profile, Profile::EXPLICIT_ACCESS);
+    sync_notifier_service->GetSyncedNotificationServices(notifiers);
+
+    if (comparator)
+      std::sort(notifiers->begin(), notifiers->end(), *comparator);
+    else
+      std::sort(notifiers->begin(), notifiers->end(), SimpleCompareNotifiers);
+  }
+
   int app_count = notifiers->size();
 
   ContentSettingsForOneType settings;
@@ -123,10 +148,11 @@
     std::string url_pattern = iter->primary_pattern.ToString();
     string16 name = UTF8ToUTF16(url_pattern);
     GURL url(url_pattern);
-    notifiers->push_back(new message_center::Notifier(
-        url,
+    NotifierId notifier_id(url);
+    notifiers->push_back(new Notifier(
+        notifier_id,
         name,
-        notification_service->GetContentSetting(url) == CONTENT_SETTING_ALLOW));
+        notification_service->IsNotifierEnabled(notifier_id)));
     patterns_[name] = iter->primary_pattern;
     FaviconService::FaviconForURLParams favicon_params(
         profile, url, chrome::FAVICON | chrome::TOUCH_ICON,
@@ -145,12 +171,11 @@
 #if defined(OS_CHROMEOS)
   const string16 screenshot_name =
       l10n_util::GetStringUTF16(IDS_MESSAGE_CENTER_NOTIFIER_SCREENSHOT_NAME);
-  message_center::Notifier* const screenshot_notifier =
-      new message_center::Notifier(
-          message_center::Notifier::SCREENSHOT,
-          screenshot_name,
-          notification_service->IsSystemComponentEnabled(
-              message_center::Notifier::SCREENSHOT));
+  NotifierId screenshot_notifier_id(NotifierId::SCREENSHOT);
+  Notifier* const screenshot_notifier = new Notifier(
+      screenshot_notifier_id,
+      screenshot_name,
+      notification_service->IsNotifierEnabled(screenshot_notifier_id));
   screenshot_notifier->icon =
       ui::ResourceBundle::GetSharedInstance().GetImageNamed(
           IDR_SCREENSHOT_NOTIFICATION_ICON);
@@ -173,46 +198,49 @@
   DesktopNotificationService* notification_service =
       DesktopNotificationServiceFactory::GetForProfile(profile);
 
-  switch (notifier.type) {
-    case Notifier::APPLICATION:
-      notification_service->SetExtensionEnabled(notifier.id, enabled);
-      break;
-    case Notifier::WEB_PAGE: {
-      ContentSetting default_setting =
-          notification_service->GetDefaultContentSetting(NULL);
-      DCHECK(default_setting == CONTENT_SETTING_ALLOW ||
-             default_setting == CONTENT_SETTING_BLOCK ||
-             default_setting == CONTENT_SETTING_ASK);
-      if ((enabled && default_setting != CONTENT_SETTING_ALLOW) ||
-          (!enabled && default_setting == CONTENT_SETTING_ALLOW)) {
-        if (notifier.url.is_valid()) {
-          if (enabled)
-            notification_service->GrantPermission(notifier.url);
-          else
-            notification_service->DenyPermission(notifier.url);
-        } else {
-          LOG(ERROR) << "Invalid url pattern: " << notifier.url.spec();
-        }
+  if (notifier.notifier_id.type == NotifierId::WEB_PAGE) {
+    // WEB_PAGE notifier cannot handle in DesktopNotificationService
+    // since it has the exact URL pattern.
+    // TODO(mukai): fix this.
+    ContentSetting default_setting =
+        notification_service->GetDefaultContentSetting(NULL);
+    DCHECK(default_setting == CONTENT_SETTING_ALLOW ||
+           default_setting == CONTENT_SETTING_BLOCK ||
+           default_setting == CONTENT_SETTING_ASK);
+    if ((enabled && default_setting != CONTENT_SETTING_ALLOW) ||
+        (!enabled && default_setting == CONTENT_SETTING_ALLOW)) {
+      if (notifier.notifier_id.url.is_valid()) {
+        if (enabled)
+          notification_service->GrantPermission(notifier.notifier_id.url);
+        else
+          notification_service->DenyPermission(notifier.notifier_id.url);
       } else {
-        std::map<string16, ContentSettingsPattern>::const_iterator iter =
-            patterns_.find(notifier.name);
-        if (iter != patterns_.end()) {
-          notification_service->ClearSetting(iter->second);
-        } else {
-          LOG(ERROR) << "Invalid url pattern: " << notifier.url.spec();
-        }
+        LOG(ERROR) << "Invalid url pattern: "
+                   << notifier.notifier_id.url.spec();
       }
-      break;
+    } else {
+      std::map<string16, ContentSettingsPattern>::const_iterator iter =
+          patterns_.find(notifier.name);
+      if (iter != patterns_.end()) {
+        notification_service->ClearSetting(iter->second);
+      } else {
+        LOG(ERROR) << "Invalid url pattern: "
+                   << notifier.notifier_id.url.spec();
+      }
     }
-    case message_center::Notifier::SYSTEM_COMPONENT:
-      notification_service->SetSystemComponentEnabled(
-          notifier.system_component_type, enabled);
-      break;
+  } else {
+    notification_service->SetNotifierEnabled(notifier.notifier_id, enabled);
+    if (notifier.notifier_id.type == NotifierId::SYNCED_NOTIFICATION_SERVICE) {
+      notifier::ChromeNotifierService* notifier_service =
+          notifier::ChromeNotifierServiceFactory::GetInstance()->GetForProfile(
+              profile, Profile::EXPLICIT_ACCESS);
+      notifier_service->OnSyncedNotificationServiceEnabled(
+          notifier.notifier_id.id, enabled);
+    }
   }
 }
 
 void MessageCenterSettingsController::OnNotifierSettingsClosing() {
-  delegate_ = NULL;
   DCHECK(favicon_tracker_.get());
   favicon_tracker_->TryCancelAll();
   patterns_.clear();
@@ -221,15 +249,16 @@
 void MessageCenterSettingsController::OnFaviconLoaded(
     const GURL& url,
     const chrome::FaviconImageResult& favicon_result) {
-  if (!delegate_)
-    return;
-  delegate_->UpdateFavicon(url, favicon_result.image);
+  FOR_EACH_OBSERVER(message_center::NotifierSettingsObserver,
+                    observers_,
+                    UpdateIconImage(NotifierId(url), favicon_result.image));
 }
 
 
 void MessageCenterSettingsController::SetAppImage(const std::string& id,
                                                   const gfx::ImageSkia& image) {
-  if (!delegate_)
-    return;
-  delegate_->UpdateIconImage(id, gfx::Image(image) );
+  FOR_EACH_OBSERVER(message_center::NotifierSettingsObserver,
+                    observers_,
+                    UpdateIconImage(NotifierId(NotifierId::APPLICATION, id),
+                                    gfx::Image(image)));
 }
diff --git a/chrome/browser/notifications/message_center_settings_controller.h b/chrome/browser/notifications/message_center_settings_controller.h
index 45f6331..71487c5 100644
--- a/chrome/browser/notifications/message_center_settings_controller.h
+++ b/chrome/browser/notifications/message_center_settings_controller.h
@@ -10,6 +10,7 @@
 
 #include "base/basictypes.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/observer_list.h"
 #include "chrome/browser/extensions/app_icon_loader.h"
 #include "chrome/common/content_settings.h"
 #include "ui/message_center/notifier_settings.h"
@@ -29,13 +30,11 @@
   MessageCenterSettingsController();
   virtual ~MessageCenterSettingsController();
 
-  // Shows a new settings dialog window with specified |context|. If there's
-  // already an existing dialog, it raises the dialog instead of creating a new
-  // one.
-  message_center::NotifierSettingsDelegate* ShowSettingsDialog(
-      gfx::NativeView context);
-
-  // Overridden from message_center::NotifierSettingsViewDelegate.
+  // Overridden from message_center::NotifierSettingsProvider.
+  virtual void AddObserver(
+      message_center::NotifierSettingsObserver* observer) OVERRIDE;
+  virtual void RemoveObserver(
+      message_center::NotifierSettingsObserver* observer) OVERRIDE;
   virtual void GetNotifierList(
       std::vector<message_center::Notifier*>* notifiers)
       OVERRIDE;
@@ -52,9 +51,8 @@
   void OnFaviconLoaded(const GURL& url,
                        const chrome::FaviconImageResult& favicon_result);
 
-  // The view displaying notifier settings. NULL if the settings are not
-  // visible.
-  message_center::NotifierSettingsDelegate* delegate_;
+  // The views displaying notifier settings.
+  ObserverList<message_center::NotifierSettingsObserver> observers_;
 
   // The task tracker for loading favicons.
   scoped_ptr<CancelableTaskTracker> favicon_tracker_;
diff --git a/chrome/browser/notifications/notification.h b/chrome/browser/notifications/notification.h
index 05c3fff..3e4685c 100644
--- a/chrome/browser/notifications/notification.h
+++ b/chrome/browser/notifications/notification.h
@@ -12,11 +12,11 @@
 #include "base/strings/string16.h"
 #include "base/values.h"
 #include "chrome/browser/notifications/notification_delegate.h"
-#include "googleurl/src/gurl.h"
 #include "third_party/WebKit/public/web/WebTextDirection.h"
 #include "ui/gfx/image/image.h"
 #include "ui/message_center/notification.h"
 #include "ui/message_center/notification_types.h"
+#include "url/gurl.h"
 
 // Representation of a notification to be shown to the user.
 // On non-Ash platforms these are rendered as HTML, sometimes described by a
diff --git a/chrome/browser/notifications/notification_audio_controller.h b/chrome/browser/notifications/notification_audio_controller.h
index ce6cbdb..c8a27a7 100644
--- a/chrome/browser/notifications/notification_audio_controller.h
+++ b/chrome/browser/notifications/notification_audio_controller.h
@@ -10,7 +10,7 @@
 #include "base/callback.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_vector.h"
-#include "base/string_piece.h"
+#include "base/strings/string_piece.h"
 #include "media/audio/audio_parameters.h"
 
 namespace base {
diff --git a/chrome/browser/notifications/notification_browsertest.cc b/chrome/browser/notifications/notification_browsertest.cc
index 06fe062..fe5982a 100644
--- a/chrome/browser/notifications/notification_browsertest.cc
+++ b/chrome/browser/notifications/notification_browsertest.cc
@@ -40,15 +40,15 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_utils.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/net_util.h"
-#include "net/test/spawned_test_server/spawned_test_server.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/window_open_disposition.h"
 #include "ui/message_center/message_center.h"
 #include "ui/message_center/message_center_observer.h"
 #include "ui/message_center/message_center_switches.h"
 #include "ui/message_center/message_center_util.h"
+#include "url/gurl.h"
 
 // TODO(kbr): remove: http://crbug.com/222296
 #if defined(OS_MACOSX)
@@ -57,7 +57,7 @@
 
 namespace {
 
-const char kExpectedIconUrl[] = "files/notifications/no_such_file.png";
+const char kExpectedIconUrl[] = "/notifications/no_such_file.png";
 
 enum InfobarAction {
   DISMISS = 0,
@@ -206,9 +206,6 @@
   NotificationsTest() {}
 
  protected:
-  // Overriden from InProcessBrowserTest:
-  virtual void SetUpInProcessBrowserTestFixture() OVERRIDE;
-
   int GetNotificationCount();
 
   NotificationChangeObserver* CreateObserver();
@@ -244,23 +241,16 @@
   bool CheckOriginInSetting(const ContentSettingsForOneType& settings,
                             const GURL& origin);
 
-  GURL empty_page_url_;
-  GURL test_page_url_;
+  GURL GetTestPageURL() const {
+    return embedded_test_server()->GetURL(
+      "/notifications/notification_tester.html");
+  }
 
  private:
   void DropOriginPreference(const GURL& origin);
   DesktopNotificationService* GetDesktopNotificationService();
 };
 
-void NotificationsTest::SetUpInProcessBrowserTestFixture() {
-  InProcessBrowserTest::SetUpInProcessBrowserTestFixture();
-
-  ASSERT_TRUE(test_server()->Start());
-  empty_page_url_ = test_server()->GetURL("files/empty.html");
-  test_page_url_ = test_server()->GetURL(
-      "files/notifications/notification_tester.html");
-}
-
 int NotificationsTest::GetNotificationCount() {
   if (message_center::IsRichNotificationEnabled()) {
     return message_center::MessageCenter::Get()->NotificationCount();
@@ -483,10 +473,12 @@
 
 // If this flakes, use http://crbug.com/62311 and http://crbug.com/74428.
 IN_PROC_BROWSER_TEST_F(NotificationsTest, TestUserGestureInfobar) {
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
   ui_test_utils::NavigateToURL(
       browser(),
-      test_server()->GetURL(
-          "files/notifications/notifications_request_function.html"));
+      embedded_test_server()->GetURL(
+          "/notifications/notifications_request_function.html"));
 
   // Request permission by calling request() while eval'ing an inline script;
   // That's considered a user gesture to webkit, and should produce an infobar.
@@ -503,12 +495,14 @@
 
 // If this flakes, use http://crbug.com/62311.
 IN_PROC_BROWSER_TEST_F(NotificationsTest, TestNoUserGestureInfobar) {
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
   // Load a page which just does a request; no user gesture should result
   // in no infobar.
   ui_test_utils::NavigateToURL(
       browser(),
-      test_server()->GetURL(
-          "files/notifications/notifications_request_inline.html"));
+      embedded_test_server()->GetURL(
+          "/notifications/notifications_request_inline.html"));
 
   EXPECT_EQ(0U, InfoBarService::FromWebContents(
       browser()->tab_strip_model()->GetWebContentsAt(0))->infobar_count());
@@ -521,14 +515,16 @@
     return;
 #endif
 
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
   // Creates a simple notification.
   AllowAllOrigins();
-  ui_test_utils::NavigateToURL(browser(), test_page_url_);
+  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
 
   std::string result = CreateSimpleNotification(browser(), true);
   EXPECT_NE("-1", result);
 
-  GURL EXPECTED_ICON_URL = test_server()->GetURL(kExpectedIconUrl);
+  GURL EXPECTED_ICON_URL = embedded_test_server()->GetURL(kExpectedIconUrl);
   ASSERT_EQ(1, GetNotificationCount());
   if (message_center::IsRichNotificationEnabled()) {
     message_center::NotificationList::Notifications notifications =
@@ -553,9 +549,11 @@
     return;
 #endif
 
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
   // Creates a notification and closes it.
   AllowAllOrigins();
-  ui_test_utils::NavigateToURL(browser(), test_page_url_);
+  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
 
   std::string result = CreateSimpleNotification(browser(), true);
   EXPECT_NE("-1", result);
@@ -582,9 +580,11 @@
     return;
 #endif
 
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
   // Creates a notification and cancels it in the origin page.
   AllowAllOrigins();
-  ui_test_utils::NavigateToURL(browser(), test_page_url_);
+  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
 
   std::string note_id = CreateSimpleNotification(browser(), true);
   EXPECT_NE(note_id, "-1");
@@ -595,8 +595,10 @@
 }
 
 IN_PROC_BROWSER_TEST_F(NotificationsTest, TestPermissionInfobarAppears) {
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
   // Requests notification privileges and verifies the infobar appears.
-  ui_test_utils::NavigateToURL(browser(), test_page_url_);
+  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
   ASSERT_TRUE(RequestPermissionAndWait(browser()));
 
   ASSERT_EQ(0, GetNotificationCount());
@@ -610,8 +612,10 @@
     return;
 #endif
 
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
   // Tries to create a notification and clicks allow on the infobar.
-  ui_test_utils::NavigateToURL(browser(), test_page_url_);
+  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
   // This notification should not be shown because we do not have permission.
   CreateSimpleNotification(browser(), false);
   ASSERT_EQ(0, GetNotificationCount());
@@ -624,21 +628,25 @@
 }
 
 IN_PROC_BROWSER_TEST_F(NotificationsTest, TestDenyOnPermissionInfobar) {
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
   // Test that no notification is created
   // when Deny is chosen from permission infobar.
-  ui_test_utils::NavigateToURL(browser(), test_page_url_);
+  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
   ASSERT_TRUE(RequestPermissionAndWait(browser()));
   PerformActionOnInfobar(browser(), DENY, 0, 0);
   CreateSimpleNotification(browser(), false);
   ASSERT_EQ(0, GetNotificationCount());
   ContentSettingsForOneType settings;
   GetPrefsByContentSetting(CONTENT_SETTING_BLOCK, &settings);
-  EXPECT_TRUE(CheckOriginInSetting(settings, test_page_url_));
+  EXPECT_TRUE(CheckOriginInSetting(settings, GetTestPageURL()));
 }
 
 IN_PROC_BROWSER_TEST_F(NotificationsTest, TestClosePermissionInfobar) {
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
   // Test that no notification is created when permission infobar is dismissed.
-  ui_test_utils::NavigateToURL(browser(), test_page_url_);
+  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
   ASSERT_TRUE(RequestPermissionAndWait(browser()));
   PerformActionOnInfobar(browser(), DISMISS, 0, 0);
   CreateSimpleNotification(browser(), false);
@@ -654,9 +662,12 @@
   if (base::mac::IsOSMountainLionOrLater())
     return;
 #endif
+
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
   // Verify that all domains can be allowed to show notifications.
   SetDefaultPermissionSetting(CONTENT_SETTING_ALLOW);
-  ui_test_utils::NavigateToURL(browser(), test_page_url_);
+  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
 
   std::string result = CreateSimpleNotification(browser(), true);
   EXPECT_NE("-1", result);
@@ -667,9 +678,11 @@
 }
 
 IN_PROC_BROWSER_TEST_F(NotificationsTest, TestDenyNotificationsFromAllSites) {
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
   // Verify that no domain can show notifications.
   SetDefaultPermissionSetting(CONTENT_SETTING_BLOCK);
-  ui_test_utils::NavigateToURL(browser(), test_page_url_);
+  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
 
   std::string result = CreateSimpleNotification(browser(), false);
   EXPECT_EQ("-1", result);
@@ -678,12 +691,14 @@
 }
 
 IN_PROC_BROWSER_TEST_F(NotificationsTest, TestDenyDomainAndAllowAll) {
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
   // Verify that denying a domain and allowing all shouldn't show
   // notifications from the denied domain.
-  DenyOrigin(test_page_url_.GetOrigin());
+  DenyOrigin(GetTestPageURL().GetOrigin());
   SetDefaultPermissionSetting(CONTENT_SETTING_ALLOW);
 
-  ui_test_utils::NavigateToURL(browser(), test_page_url_);
+  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
 
   std::string result = CreateSimpleNotification(browser(), false);
   EXPECT_EQ("-1", result);
@@ -697,12 +712,15 @@
   if (base::mac::IsOSMountainLionOrLater())
     return;
 #endif
+
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
   // Verify that allowing a domain and denying all others should show
   // notifications from the allowed domain.
-  AllowOrigin(test_page_url_.GetOrigin());
+  AllowOrigin(GetTestPageURL().GetOrigin());
   SetDefaultPermissionSetting(CONTENT_SETTING_BLOCK);
 
-  ui_test_utils::NavigateToURL(browser(), test_page_url_);
+  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
 
   std::string result = CreateSimpleNotification(browser(), true);
   EXPECT_NE("-1", result);
@@ -716,17 +734,20 @@
   if (base::mac::IsOSMountainLionOrLater())
     return;
 #endif
-  // Verify that denying and again allowing should show notifications.
-  DenyOrigin(test_page_url_.GetOrigin());
 
-  ui_test_utils::NavigateToURL(browser(), test_page_url_);
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
+  // Verify that denying and again allowing should show notifications.
+  DenyOrigin(GetTestPageURL().GetOrigin());
+
+  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
 
   std::string result = CreateSimpleNotification(browser(), false);
   EXPECT_EQ("-1", result);
 
   ASSERT_EQ(0, GetNotificationCount());
 
-  AllowOrigin(test_page_url_.GetOrigin());
+  AllowOrigin(GetTestPageURL().GetOrigin());
   result = CreateSimpleNotification(browser(), true);
   EXPECT_NE("-1", result);
 
@@ -741,16 +762,19 @@
   if (base::mac::IsOSMountainLionOrLater())
     return;
 #endif
+
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
   // Verify able to create, deny, and close the notification.
   AllowAllOrigins();
-  ui_test_utils::NavigateToURL(browser(), test_page_url_);
+  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
   CreateSimpleNotification(browser(), true);
   ASSERT_EQ(1, GetNotificationCount());
 
-  DenyOrigin(test_page_url_.GetOrigin());
+  DenyOrigin(GetTestPageURL().GetOrigin());
   ContentSettingsForOneType settings;
   GetPrefsByContentSetting(CONTENT_SETTING_BLOCK, &settings);
-  ASSERT_TRUE(CheckOriginInSetting(settings, test_page_url_.GetOrigin()));
+  ASSERT_TRUE(CheckOriginInSetting(settings, GetTestPageURL().GetOrigin()));
 
   EXPECT_EQ(1, GetNotificationCount());
   if (message_center::IsRichNotificationEnabled()) {
@@ -770,15 +794,17 @@
 IN_PROC_BROWSER_TEST_F(
     NotificationsTest,
     DISABLED_TestOriginPrefsNotSavedInIncognito) {
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
   // Verify that allow/deny origin preferences are not saved in incognito.
   Browser* incognito = CreateIncognitoBrowser();
-  ui_test_utils::NavigateToURL(incognito, test_page_url_);
+  ui_test_utils::NavigateToURL(incognito, GetTestPageURL());
   ASSERT_TRUE(RequestPermissionAndWait(incognito));
   PerformActionOnInfobar(incognito, DENY, 0, 0);
   CloseBrowserWindow(incognito);
 
   incognito = CreateIncognitoBrowser();
-  ui_test_utils::NavigateToURL(incognito, test_page_url_);
+  ui_test_utils::NavigateToURL(incognito, GetTestPageURL());
   ASSERT_TRUE(RequestPermissionAndWait(incognito));
   PerformActionOnInfobar(incognito, ALLOW, 0, 0);
   CreateSimpleNotification(incognito, true);
@@ -786,7 +812,7 @@
   CloseBrowserWindow(incognito);
 
   incognito = CreateIncognitoBrowser();
-  ui_test_utils::NavigateToURL(incognito, test_page_url_);
+  ui_test_utils::NavigateToURL(incognito, GetTestPageURL());
   ASSERT_TRUE(RequestPermissionAndWait(incognito));
 
   ContentSettingsForOneType settings;
@@ -797,8 +823,10 @@
 }
 
 IN_PROC_BROWSER_TEST_F(NotificationsTest, TestExitBrowserWithInfobar) {
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
   // Exit the browser window, when the infobar appears.
-  ui_test_utils::NavigateToURL(browser(), test_page_url_);
+  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
   ASSERT_TRUE(RequestPermissionAndWait(browser()));
 }
 
@@ -812,14 +840,16 @@
 #endif
 IN_PROC_BROWSER_TEST_F(NotificationsTest,
                        MAYBE_TestCrashTabWithPermissionInfobar) {
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
   // Test crashing the tab with permission infobar doesn't crash Chrome.
   ui_test_utils::NavigateToURLWithDisposition(
       browser(),
-      empty_page_url_,
+      embedded_test_server()->GetURL("/empty.html"),
       NEW_BACKGROUND_TAB,
       ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
   browser()->tab_strip_model()->ActivateTabAt(0, true);
-  ui_test_utils::NavigateToURL(browser(), test_page_url_);
+  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
   ASSERT_TRUE(RequestPermissionAndWait(browser()));
   CrashTab(browser(), 0);
 }
@@ -834,9 +864,12 @@
   if (base::mac::IsOSMountainLionOrLater())
     return;
 #endif
+
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
   // Test killing a notification doesn't crash Chrome.
   AllowAllOrigins();
-  ui_test_utils::NavigateToURL(browser(), test_page_url_);
+  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
   CreateSimpleNotification(browser(), true);
   ASSERT_EQ(1, GetNotificationCount());
 
@@ -852,9 +885,12 @@
   if (base::mac::IsOSMountainLionOrLater())
     return;
 #endif
+
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
   // Test notifications in incognito window.
   Browser* browser = CreateIncognitoBrowser();
-  ui_test_utils::NavigateToURL(browser, test_page_url_);
+  ui_test_utils::NavigateToURL(browser, GetTestPageURL());
   browser->tab_strip_model()->ActivateTabAt(0, true);
   ASSERT_TRUE(RequestPermissionAndWait(browser));
   PerformActionOnInfobar(browser, ALLOW, 0, 0);
@@ -863,6 +899,8 @@
 }
 
 IN_PROC_BROWSER_TEST_F(NotificationsTest, TestCloseTabWithPermissionInfobar) {
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
   // Test that user can close tab when infobar present.
   ui_test_utils::NavigateToURLWithDisposition(
       browser(),
@@ -870,7 +908,7 @@
       NEW_BACKGROUND_TAB,
       ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
   browser()->tab_strip_model()->ActivateTabAt(0, true);
-  ui_test_utils::NavigateToURL(browser(), test_page_url_);
+  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
   ASSERT_TRUE(RequestPermissionAndWait(browser()));
   content::WindowedNotificationObserver observer(
       content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
@@ -888,6 +926,9 @@
   if (base::mac::IsOSMountainLionOrLater())
     return;
 #endif
+
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
   // Test navigating away when an infobar is present,
   // then trying to create a notification from the same page.
   ui_test_utils::NavigateToURLWithDisposition(
@@ -896,9 +937,9 @@
       NEW_BACKGROUND_TAB,
       ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
   browser()->tab_strip_model()->ActivateTabAt(0, true);
-  ui_test_utils::NavigateToURL(browser(), test_page_url_);
+  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
   ASSERT_TRUE(RequestPermissionAndWait(browser()));
-  ui_test_utils::NavigateToURL(browser(), test_page_url_);
+  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
   ASSERT_TRUE(RequestPermissionAndWait(browser()));
   PerformActionOnInfobar(browser(), ALLOW, 0, 0);
   CreateSimpleNotification(browser(), true);
@@ -921,6 +962,9 @@
   if (base::mac::IsOSMountainLionOrLater())
     return;
 #endif
+
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
   // Test crashing renderer does not close or crash notification.
   AllowAllOrigins();
   ui_test_utils::NavigateToURLWithDisposition(
@@ -929,7 +973,7 @@
       NEW_BACKGROUND_TAB,
       ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
   browser()->tab_strip_model()->ActivateTabAt(0, true);
-  ui_test_utils::NavigateToURL(browser(), test_page_url_);
+  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
   CreateSimpleNotification(browser(), true);
   ASSERT_EQ(1, GetNotificationCount());
   CrashTab(browser(), 0);
@@ -942,10 +986,13 @@
   if (base::mac::IsOSMountainLionOrLater())
     return;
 #endif
+
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
   // Test that we can replace a notification using the replaceId.
   AllowAllOrigins();
 
-  ui_test_utils::NavigateToURL(browser(), test_page_url_);
+  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
 
   std::string result = CreateNotification(
       browser(), true, "abc.png", "Title1", "Body1", "chat");
@@ -968,7 +1015,7 @@
     ASSERT_EQ(1U, balloons.size());
     Balloon* balloon = balloons[0];
     const Notification& notification = balloon->notification();
-    GURL EXPECTED_ICON_URL = test_server()->GetURL(kExpectedIconUrl);
+    GURL EXPECTED_ICON_URL = embedded_test_server()->GetURL(kExpectedIconUrl);
     EXPECT_EQ(EXPECTED_ICON_URL, notification.icon_url());
     EXPECT_EQ(ASCIIToUTF16("Title2"), notification.title());
     EXPECT_EQ(ASCIIToUTF16("Body2"), notification.message());
diff --git a/chrome/browser/notifications/notification_prefs_manager.cc b/chrome/browser/notifications/notification_prefs_manager.cc
index ad4b73b..a77eb63 100644
--- a/chrome/browser/notifications/notification_prefs_manager.cc
+++ b/chrome/browser/notifications/notification_prefs_manager.cc
@@ -25,4 +25,6 @@
 void NotificationPrefsManager::RegisterPrefs(PrefRegistrySimple* registry) {
   registry->RegisterIntegerPref(prefs::kDesktopNotificationPosition,
                                 BalloonCollection::DEFAULT_POSITION);
+  registry->RegisterBooleanPref(prefs::kMessageCenterShowedFirstRunBalloon,
+                                false);
 }
diff --git a/chrome/browser/notifications/notification_ui_manager.cc b/chrome/browser/notifications/notification_ui_manager.cc
index 2c73a9e..8bbafe7 100644
--- a/chrome/browser/notifications/notification_ui_manager.cc
+++ b/chrome/browser/notifications/notification_ui_manager.cc
@@ -26,7 +26,7 @@
 NotificationUIManager* NotificationUIManager::Create(PrefService* local_state) {
   if (DelegatesToMessageCenter())
     return new MessageCenterNotificationManager(
-        g_browser_process->message_center());
+        g_browser_process->message_center(), local_state);
 
   BalloonNotificationUIManager* balloon_manager =
       new BalloonNotificationUIManager(local_state);
diff --git a/chrome/browser/notifications/notification_ui_manager_impl.h b/chrome/browser/notifications/notification_ui_manager_impl.h
index 273beea..f8544ea 100644
--- a/chrome/browser/notifications/notification_ui_manager_impl.h
+++ b/chrome/browser/notifications/notification_ui_manager_impl.h
@@ -12,7 +12,7 @@
 #include "base/id_map.h"
 #include "base/memory/linked_ptr.h"
 #include "base/prefs/pref_member.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/notifications/notification_ui_manager.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
diff --git a/chrome/browser/notifications/notification_ui_manager_mac.h b/chrome/browser/notifications/notification_ui_manager_mac.h
index 709e2d2..20cc582 100644
--- a/chrome/browser/notifications/notification_ui_manager_mac.h
+++ b/chrome/browser/notifications/notification_ui_manager_mac.h
@@ -11,7 +11,7 @@
 #include <set>
 
 #include "base/basictypes.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/string16.h"
 #include "chrome/browser/notifications/balloon_notification_ui_manager.h"
@@ -74,7 +74,7 @@
       const string16& replacement_id) const;
 
   // Cocoa class that receives callbacks from the NSUserNotificationCenter.
-  scoped_nsobject<NotificationCenterDelegate> delegate_;
+  base::scoped_nsobject<NotificationCenterDelegate> delegate_;
 
   // Maps notification_ids to ControllerNotifications. The map owns the value,
   // so it must be deleted when remvoed from the map. This is typically handled
diff --git a/chrome/browser/notifications/notification_ui_manager_mac.mm b/chrome/browser/notifications/notification_ui_manager_mac.mm
index 96cea87..5222aa1 100644
--- a/chrome/browser/notifications/notification_ui_manager_mac.mm
+++ b/chrome/browser/notifications/notification_ui_manager_mac.mm
@@ -102,7 +102,7 @@
   // notification_ui_manager.cc.
   if (DelegatesToMessageCenter()) {
     return new MessageCenterNotificationManager(
-        g_browser_process->message_center());
+        g_browser_process->message_center(), local_state);
   }
 
   BalloonNotificationUIManager* balloon_manager = NULL;
diff --git a/chrome/browser/notifications/sync_notifier/chrome_notifier_service.cc b/chrome/browser/notifications/sync_notifier/chrome_notifier_service.cc
index ff4c5b4..8cb839f 100644
--- a/chrome/browser/notifications/sync_notifier/chrome_notifier_service.cc
+++ b/chrome/browser/notifications/sync_notifier/chrome_notifier_service.cc
@@ -8,18 +8,28 @@
 
 #include "chrome/browser/notifications/sync_notifier/chrome_notifier_service.h"
 
+#include "chrome/browser/notifications/desktop_notification_service.h"
+#include "chrome/browser/notifications/desktop_notification_service_factory.h"
 #include "chrome/browser/notifications/notification.h"
 #include "chrome/browser/notifications/notification_ui_manager.h"
 #include "chrome/browser/profiles/profile.h"
-#include "googleurl/src/gurl.h"
+#include "grit/ui_strings.h"
 #include "sync/api/sync_change.h"
 #include "sync/api/sync_change_processor.h"
 #include "sync/api/sync_error_factory.h"
 #include "sync/protocol/sync.pb.h"
 #include "sync/protocol/synced_notification_specifics.pb.h"
 #include "third_party/WebKit/public/web/WebTextDirection.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/message_center/notifier_settings.h"
+#include "url/gurl.h"
 
 namespace notifier {
+namespace {
+
+const char kSampleSyncedNotificationServiceId[] = "sample-synced-service";
+
+}
 
 bool ChromeNotifierService::avoid_bitmap_fetching_for_test_ = false;
 
@@ -251,6 +261,27 @@
   return NULL;
 }
 
+void ChromeNotifierService::GetSyncedNotificationServices(
+    std::vector<message_center::Notifier*>* notifiers) {
+  // TODO(mukai|petewil): should check the profile's eligibility before adding
+  // the sample app.
+
+  // Currently we just use kSampleSyncedNotificationServiceId as a place holder.
+  // TODO(petewil): Really obtain the list of apps from the server and create
+  // the list of ids here.
+  DesktopNotificationService* desktop_notification_service =
+      DesktopNotificationServiceFactory::GetForProfile(profile_);
+  message_center::NotifierId notifier_id(
+      message_center::NotifierId::SYNCED_NOTIFICATION_SERVICE,
+      kSampleSyncedNotificationServiceId);
+  notifiers->push_back(new message_center::Notifier(
+      notifier_id,
+      l10n_util::GetStringUTF16(
+          IDS_MESSAGE_CENTER_SAMPLE_SYNCED_NOTIFICATION_SERVICE_NAME),
+      desktop_notification_service->IsNotifierEnabled(notifier_id)));
+  // TODO(mukai): should add icon for the sample app.
+}
+
 void ChromeNotifierService::MarkNotificationAsDismissed(
     const std::string& key) {
   SyncedNotification* notification = FindNotificationByKey(key);
@@ -291,4 +322,9 @@
   notification_copy->StartBitmapFetch();
 }
 
+void ChromeNotifierService::OnSyncedNotificationServiceEnabled(
+    const std::string& notifier_id, bool enabled) {
+  // TODO(petewil): start/stop syncing
+}
+
 }  // namespace notifier
diff --git a/chrome/browser/notifications/sync_notifier/chrome_notifier_service.h b/chrome/browser/notifications/sync_notifier/chrome_notifier_service.h
index 270157f..ba3666d 100644
--- a/chrome/browser/notifications/sync_notifier/chrome_notifier_service.h
+++ b/chrome/browser/notifications/sync_notifier/chrome_notifier_service.h
@@ -17,6 +17,10 @@
 class NotificationUIManager;
 class Profile;
 
+namespace message_center {
+struct Notifier;
+}
+
 namespace notifier {
 
 // The ChromeNotifierService holds notifications which represent the state of
@@ -56,9 +60,19 @@
   // The caller must not free it.
   notifier::SyncedNotification* FindNotificationByKey(const std::string& key);
 
+  // Get the list of synced notification services and fill their meta data to
+  // |notifiers|.
+  void GetSyncedNotificationServices(
+      std::vector<message_center::Notifier*>* notifiers);
+
   // Called when we dismiss a notification.
   void MarkNotificationAsDismissed(const std::string& id);
 
+  // Called when a notier is enabled or disabled.
+  void OnSyncedNotificationServiceEnabled(
+      const std::string& notifier_id,
+      bool enabled);
+
   // functions for test
   void AddForTest(scoped_ptr<notifier::SyncedNotification> notification) {
     Add(notification.Pass());
diff --git a/chrome/browser/notifications/sync_notifier/chrome_notifier_service_factory.cc b/chrome/browser/notifications/sync_notifier/chrome_notifier_service_factory.cc
index a029c4d..16216a7 100644
--- a/chrome/browser/notifications/sync_notifier/chrome_notifier_service_factory.cc
+++ b/chrome/browser/notifications/sync_notifier/chrome_notifier_service_factory.cc
@@ -4,8 +4,10 @@
 
 #include "chrome/browser/notifications/sync_notifier/chrome_notifier_service_factory.h"
 
+#include "base/command_line.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/notifications/sync_notifier/chrome_notifier_service.h"
+#include "chrome/common/chrome_switches.h"
 #include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
 
 namespace notifier {
@@ -22,6 +24,16 @@
   return Singleton<ChromeNotifierServiceFactory>::get();
 }
 
+// static
+bool ChromeNotifierServiceFactory::UseSyncedNotifications(
+    CommandLine* command_line) {
+  if (command_line->HasSwitch(switches::kDisableSyncSyncedNotifications))
+    return false;
+  if (command_line->HasSwitch(switches::kEnableSyncSyncedNotifications))
+    return true;
+  return false;
+}
+
 ChromeNotifierServiceFactory::ChromeNotifierServiceFactory()
     : BrowserContextKeyedServiceFactory(
         "ChromeNotifierService",
diff --git a/chrome/browser/notifications/sync_notifier/chrome_notifier_service_factory.h b/chrome/browser/notifications/sync_notifier/chrome_notifier_service_factory.h
index 2261f9c..4861dad 100644
--- a/chrome/browser/notifications/sync_notifier/chrome_notifier_service_factory.h
+++ b/chrome/browser/notifications/sync_notifier/chrome_notifier_service_factory.h
@@ -9,6 +9,8 @@
 #include "chrome/browser/profiles/profile.h"
 #include "components/browser_context_keyed_service/browser_context_keyed_service_factory.h"
 
+class CommandLine;
+
 namespace notifier {
 
 class ChromeNotifierService;
@@ -20,6 +22,12 @@
 
   static ChromeNotifierServiceFactory* GetInstance();
 
+  // Based on command line switches, make the call to use SyncedNotifications or
+  // not.
+  // TODO(petewil): Remove this when the SyncedNotifications feature is ready
+  // to be turned on by default, and just use a disable switch instead then.
+  static bool UseSyncedNotifications(CommandLine* command_line);
+
  private:
   friend struct DefaultSingletonTraits<ChromeNotifierServiceFactory>;
 
diff --git a/chrome/browser/notifications/sync_notifier/notification_bitmap_fetcher.h b/chrome/browser/notifications/sync_notifier/notification_bitmap_fetcher.h
index e8c17cb..7a268e6 100644
--- a/chrome/browser/notifications/sync_notifier/notification_bitmap_fetcher.h
+++ b/chrome/browser/notifications/sync_notifier/notification_bitmap_fetcher.h
@@ -7,9 +7,9 @@
 
 #include "base/memory/scoped_ptr.h"
 #include "chrome/browser/image_decoder.h"
-#include "googleurl/src/gurl.h"
 #include "net/url_request/url_fetcher_delegate.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "url/gurl.h"
 
 namespace net {
 class URLFetcher;
diff --git a/chrome/browser/notifications/sync_notifier/synced_notification.cc b/chrome/browser/notifications/sync_notifier/synced_notification.cc
index e918c8b..69c19d6 100644
--- a/chrome/browser/notifications/sync_notifier/synced_notification.cc
+++ b/chrome/browser/notifications/sync_notifier/synced_notification.cc
@@ -6,7 +6,7 @@
 
 #include "base/basictypes.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/notifications/notification.h"
diff --git a/chrome/browser/notifications/sync_notifier/synced_notification.h b/chrome/browser/notifications/sync_notifier/synced_notification.h
index 70c15c2..52f37ee 100644
--- a/chrome/browser/notifications/sync_notifier/synced_notification.h
+++ b/chrome/browser/notifications/sync_notifier/synced_notification.h
@@ -15,10 +15,10 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/scoped_vector.h"
 #include "chrome/browser/notifications/sync_notifier/notification_bitmap_fetcher.h"
-#include "googleurl/src/gurl.h"
 #include "sync/api/sync_data.h"
 #include "sync/protocol/sync.pb.h"
 #include "ui/gfx/image/image.h"
+#include "url/gurl.h"
 
 namespace sync_pb {
 class SyncedNotificationSpecifics;
diff --git a/chrome/browser/omnibox/omnibox_field_trial.cc b/chrome/browser/omnibox/omnibox_field_trial.cc
index 4ec2c5c..da16943 100644
--- a/chrome/browser/omnibox/omnibox_field_trial.cc
+++ b/chrome/browser/omnibox/omnibox_field_trial.cc
@@ -22,6 +22,7 @@
 const char kHUPCreateShorterMatchFieldTrialName[] =
     "OmniboxHUPCreateShorterMatch";
 const char kStopTimerFieldTrialName[] = "OmniboxStopTimer";
+const char kShortcutsScoringFieldTrialName[] = "OmniboxShortcutsScoring";
 
 // The autocomplete dynamic field trial name prefix.  Each field trial is
 // configured dynamically and is retrieved automatically by Chrome during
@@ -240,3 +241,20 @@
   }
   return false;
 }
+
+// If the active group name starts with "MaxRelevance_", extract the
+// int that immediately following that, returning true on success.
+bool OmniboxFieldTrial::ShortcutsScoringMaxRelevance(int* max_relevance) {
+  std::string group_name =
+      base::FieldTrialList::FindFullName(kShortcutsScoringFieldTrialName);
+  const char kMaxRelevanceGroupPrefix[] = "MaxRelevance_";
+  if (!StartsWithASCII(group_name, kMaxRelevanceGroupPrefix, true))
+    return false;
+  if (!base::StringToInt(base::StringPiece(
+          group_name.substr(strlen(kMaxRelevanceGroupPrefix))),
+                         max_relevance)) {
+    LOG(WARNING) << "Malformed MaxRelevance string: " << group_name;
+    return false;
+  }
+  return true;
+}
diff --git a/chrome/browser/omnibox/omnibox_field_trial.h b/chrome/browser/omnibox/omnibox_field_trial.h
index e6f0345..ab5babc 100644
--- a/chrome/browser/omnibox/omnibox_field_trial.h
+++ b/chrome/browser/omnibox/omnibox_field_trial.h
@@ -97,6 +97,22 @@
   // user clicks on the omnibox but has not typed anything yet.
   static bool InZeroSuggestFieldTrial();
 
+  // ---------------------------------------------------------
+  // For the ShortcutsScoring field trial.
+
+  // If the field trial is active and the user is in an experiment
+  // group, extract from the experiment group name the maximum
+  // relevance score ShortcutsProvider:: CalculateScore() can return.
+  // Returns true on a successful extraction.  If the extraction failed,
+  // if the field trial is not active, etc., returns false.
+  // CalculateScore()'s return value is a product of this maximum
+  // relevance score and some attenuating factors that are all between
+  // 0 and 1.  (Note that Shortcuts results may have their scores
+  // reduced later if the assigned score is higher than allowed for
+  // non-inlineable results.  Shortcuts results are not allowed to be
+  // inlined.)
+  static bool ShortcutsScoringMaxRelevance(int* max_relevance);
+
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(OmniboxFieldTrial);
 };
diff --git a/chrome/browser/omnibox/omnibox_log.h b/chrome/browser/omnibox/omnibox_log.h
index 461ff85..a31c9c7 100644
--- a/chrome/browser/omnibox/omnibox_log.h
+++ b/chrome/browser/omnibox/omnibox_log.h
@@ -8,7 +8,7 @@
 #include <stddef.h>
 
 #include "base/strings/string16.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/autocomplete/autocomplete_input.h"
 #include "chrome/browser/autocomplete/autocomplete_provider.h"
 #include "chrome/browser/sessions/session_id.h"
diff --git a/chrome/browser/page_cycler/page_cycler.cc b/chrome/browser/page_cycler/page_cycler.cc
index 4912fe7..0d10e08 100644
--- a/chrome/browser/page_cycler/page_cycler.cc
+++ b/chrome/browser/page_cycler/page_cycler.cc
@@ -222,7 +222,7 @@
                            error_.size());
     } else if (file_util::PathExists(errors_file_)) {
       // If there is an old error file, delete it to avoid confusion.
-      file_util::Delete(errors_file_, false);
+      base::Delete(errors_file_, false);
     }
   }
   if (aborted_) {
diff --git a/chrome/browser/page_cycler/page_cycler_browsertest.cc b/chrome/browser/page_cycler/page_cycler_browsertest.cc
index c31f1e9..c4d8650 100644
--- a/chrome/browser/page_cycler/page_cycler_browsertest.cc
+++ b/chrome/browser/page_cycler/page_cycler_browsertest.cc
@@ -25,7 +25,7 @@
 #include "content/public/browser/notification_service.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/url_constants.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 // TODO(kbr): remove: http://crbug.com/222296
 #if defined(OS_MACOSX)
diff --git a/chrome/browser/password_manager/OWNERS b/chrome/browser/password_manager/OWNERS
index c1f1541..0249ef7 100644
--- a/chrome/browser/password_manager/OWNERS
+++ b/chrome/browser/password_manager/OWNERS
@@ -1,4 +1,5 @@
 albertb@chromium.org
+gcasto@chromium.org
 isherman@chromium.org
 mdm@chromium.org
 stuartmorgan@chromium.org
diff --git a/chrome/browser/password_manager/login_database.cc b/chrome/browser/password_manager/login_database.cc
index 4327728..be50c61 100644
--- a/chrome/browser/password_manager/login_database.cc
+++ b/chrome/browser/password_manager/login_database.cc
@@ -7,14 +7,16 @@
 #include <algorithm>
 #include <limits>
 
-#include "base/file_util.h"
+#include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/logging.h"
 #include "base/metrics/histogram.h"
 #include "base/pickle.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/strings/string_util.h"
+#include "base/time/time.h"
+#include "chrome/common/chrome_switches.h"
+#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+#include "sql/connection.h"
 #include "sql/statement.h"
 #include "sql/transaction.h"
 
@@ -45,9 +47,45 @@
   COLUMN_TIMES_USED
 };
 
+std::string GetRegistryControlledDomain(const GURL& signon_realm) {
+  return net::registry_controlled_domains::GetDomainAndRegistry(
+      signon_realm,
+      net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
+}
+
+std::string GetRegistryControlledDomain(const std::string& signon_realm_str) {
+  GURL signon_realm(signon_realm_str);
+  return net::registry_controlled_domains::GetDomainAndRegistry(
+      signon_realm,
+      net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
+}
+
+bool RegistryControlledDomainMatches(const scoped_ptr<PasswordForm>& found,
+                                     const PasswordForm current) {
+  const std::string found_registry_controlled_domain =
+      GetRegistryControlledDomain(found->signon_realm);
+  const std::string form_registry_controlled_domain =
+      GetRegistryControlledDomain(current.signon_realm);
+  return found_registry_controlled_domain == form_registry_controlled_domain;
+}
+
+bool SchemeMatches(const scoped_ptr<PasswordForm>& found,
+                   const PasswordForm current) {
+  const std::string found_scheme = GURL(found->signon_realm).scheme();
+  const std::string form_scheme = GURL(current.signon_realm).scheme();
+  return found_scheme == form_scheme;
+}
+
+bool PortMatches(const scoped_ptr<PasswordForm>& found,
+                   const PasswordForm current) {
+  const std::string found_port = GURL(found->signon_realm).port();
+  const std::string form_port = GURL(current.signon_realm).port();
+  return found_port == form_port;
+}
+
 }  // namespace
 
-LoginDatabase::LoginDatabase() {
+LoginDatabase::LoginDatabase() : public_suffix_domain_matching_(false) {
 }
 
 LoginDatabase::~LoginDatabase() {
@@ -100,6 +138,10 @@
     db_.Close();
     return false;
   }
+
+  public_suffix_domain_matching_ = CommandLine::ForCurrentProcess()->HasSwitch(
+      switches::kEnablePasswordAutofillPublicSuffixDomainMatching);
+
   return true;
 }
 
@@ -357,19 +399,73 @@
                               std::vector<PasswordForm*>* forms) const {
   DCHECK(forms);
   // You *must* change LoginTableColumns if this query changes.
-  sql::Statement s(db_.GetCachedStatement(SQL_FROM_HERE,
-      "SELECT origin_url, action_url, "
+  const std::string sql_query = "SELECT origin_url, action_url, "
       "username_element, username_value, "
       "password_element, password_value, submit_element, "
       "signon_realm, ssl_valid, preferred, date_created, blacklisted_by_user, "
       "scheme, password_type, possible_usernames, times_used "
-      "FROM logins WHERE signon_realm == ? "));
-  s.BindString(0, form.signon_realm);
+      "FROM logins WHERE signon_realm == ? ";
+  sql::Statement s;
+  if (public_suffix_domain_matching_) {
+    // We are extending the original SQL query with one that includes more
+    // possible matches based on public suffix domain matching. Using a regexp
+    // here is just an optimization to not have to parse all the stored entries
+    // in the |logins| table. The result (scheme, domain and port) is verified
+    // further down using GURL. See the functions SchemeMatches,
+    // RegistryControlledDomainMatches and PortMatches.
+    const std::string extended_sql_query =
+        sql_query + "OR signon_realm REGEXP ? ";
+    // TODO(nyquist) Re-enable usage of GetCachedStatement when
+    // http://crbug.com/248608 is fixed.
+    s.Assign(db_.GetUniqueStatement(extended_sql_query.c_str()));
+    const GURL signon_realm(form.signon_realm);
+    std::string domain = GetRegistryControlledDomain(signon_realm);
+    // We need to escape . in the domain. Since the domain has already been
+    // sanitized using GURL, we do not need to escape any other characters.
+    ReplaceChars(domain, ".", "\\.", &domain);
+    std::string scheme = signon_realm.scheme();
+    // We need to escape . in the scheme. Since the scheme has already been
+    // sanitized using GURL, we do not need to escape any other characters.
+    // The scheme soap.beep is an example with '.'.
+    ReplaceChars(scheme, ".", "\\.", &scheme);
+    const std::string port = signon_realm.port();
+    // For a signon realm such as http://foo.bar/, this regexp will match
+    // domains on the form http://foo.bar/, http://www.foo.bar/,
+    // http://www.mobile.foo.bar/. It will not match http://notfoo.bar/.
+    // The scheme and port has to be the same as the observed form.
+    std::string regexp = "^(" + scheme + ":\\/\\/)([\\w-]+\\.)*" +
+                         domain + "(:" + port + ")?\\/$";
+    s.BindString(0, form.signon_realm);
+    s.BindString(1, regexp);
+  } else {
+    s.Assign(db_.GetCachedStatement(SQL_FROM_HERE, sql_query.c_str()));
+    s.BindString(0, form.signon_realm);
+  }
 
   while (s.Step()) {
     scoped_ptr<PasswordForm> new_form(new PasswordForm());
     if (!InitPasswordFormFromStatement(new_form.get(), s))
       return false;
+    if (public_suffix_domain_matching_) {
+      if (!SchemeMatches(new_form, form) ||
+          !RegistryControlledDomainMatches(new_form, form) ||
+          !PortMatches(new_form, form)) {
+        // The database returned results that should not match. Skipping result.
+        continue;
+      }
+      if (form.signon_realm != new_form->signon_realm) {
+        // This is not a perfect match, so we need to create a new valid result.
+        // We do this by copying over origin, signon realm and action from the
+        // observed form and setting the original signon realm to what we found
+        // in the database. We use the fact that |original_signon_realm| is
+        // non-empty to communicate that this match was found using public
+        // suffix matching.
+        new_form->original_signon_realm = new_form->signon_realm;
+        new_form->origin = form.origin;
+        new_form->signon_realm = form.signon_realm;
+        new_form->action = form.action;
+      }
+    }
     forms->push_back(new_form.release());
   }
   return s.Succeeded();
@@ -438,7 +534,7 @@
   DCHECK(db_.is_open());
   meta_table_.Reset();
   db_.Close();
-  file_util::Delete(db_path_, false);
+  sql::Connection::Delete(db_path_);
   return Init(db_path_);
 }
 
diff --git a/chrome/browser/password_manager/login_database.h b/chrome/browser/password_manager/login_database.h
index 0cfa07e..f1d0e8d 100644
--- a/chrome/browser/password_manager/login_database.h
+++ b/chrome/browser/password_manager/login_database.h
@@ -115,6 +115,9 @@
   mutable sql::Connection db_;
   sql::MetaTable meta_table_;
 
+  // Set to true if the public suffix based domain matching is enabled.
+  bool public_suffix_domain_matching_;
+
   DISALLOW_COPY_AND_ASSIGN(LoginDatabase);
 };
 
diff --git a/chrome/browser/password_manager/login_database_unittest.cc b/chrome/browser/password_manager/login_database_unittest.cc
index 7c1b52d..3338058 100644
--- a/chrome/browser/password_manager/login_database_unittest.cc
+++ b/chrome/browser/password_manager/login_database_unittest.cc
@@ -9,7 +9,7 @@
 #include "base/path_service.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/password_manager/login_database.h"
 #include "chrome/common/chrome_paths.h"
 #include "content/public/common/password_form.h"
@@ -36,6 +36,10 @@
     return db_.DeserializeVector(pickle);
   }
 
+  void SetPublicSuffixMatching(bool enabled) {
+    db_.public_suffix_domain_matching_ = enabled;
+  }
+
   LoginDatabase db_;
   base::FilePath file_;
   base::ScopedTempDir temp_dir_;
@@ -177,6 +181,275 @@
   EXPECT_EQ(0U, result.size());
 }
 
+TEST_F(LoginDatabaseTest, TestPublicSuffixDomainMatching) {
+  SetPublicSuffixMatching(true);
+  std::vector<PasswordForm*> result;
+
+  // Verify the database is empty.
+  EXPECT_TRUE(db_.GetAutofillableLogins(&result));
+  EXPECT_EQ(0U, result.size());
+
+  // Example password form.
+  PasswordForm form;
+  form.origin = GURL("https://foo.com/");
+  form.action = GURL("https://foo.com/login");
+  form.username_element = ASCIIToUTF16("username");
+  form.username_value = ASCIIToUTF16("test@gmail.com");
+  form.password_element = ASCIIToUTF16("password");
+  form.password_value = ASCIIToUTF16("test");
+  form.submit_element = ASCIIToUTF16("");
+  form.signon_realm = "https://foo.com/";
+  form.ssl_valid = true;
+  form.preferred = false;
+  form.scheme = PasswordForm::SCHEME_HTML;
+
+  // Add it and make sure it is there.
+  EXPECT_TRUE(db_.AddLogin(form));
+  EXPECT_TRUE(db_.GetAutofillableLogins(&result));
+  EXPECT_EQ(1U, result.size());
+  delete result[0];
+  result.clear();
+
+  // Match against an exact copy.
+  EXPECT_TRUE(db_.GetLogins(form, &result));
+  EXPECT_EQ(1U, result.size());
+  delete result[0];
+  result.clear();
+
+  // We go to the mobile site.
+  PasswordForm form2(form);
+  form2.origin = GURL("https://mobile.foo.com/");
+  form2.action = GURL("https://mobile.foo.com/login");
+  form2.signon_realm = "https://mobile.foo.com/";
+
+  // Match against the mobile site.
+  EXPECT_TRUE(db_.GetLogins(form2, &result));
+  EXPECT_EQ(1U, result.size());
+  EXPECT_EQ("https://mobile.foo.com/", result[0]->signon_realm);
+  EXPECT_EQ("https://foo.com/", result[0]->original_signon_realm);
+  delete result[0];
+  result.clear();
+}
+
+// This test fails if the implementation of GetLogins uses GetCachedStatement
+// instead of GetUniqueStatement, since REGEXP is in use. See
+// http://crbug.com/248608.
+TEST_F(LoginDatabaseTest, TestPublicSuffixDomainMatchingDifferentSites) {
+  SetPublicSuffixMatching(true);
+  std::vector<PasswordForm*> result;
+
+  // Verify the database is empty.
+  EXPECT_TRUE(db_.GetAutofillableLogins(&result));
+  EXPECT_EQ(0U, result.size());
+
+  // Example password form.
+  PasswordForm form;
+  form.origin = GURL("https://foo.com/");
+  form.action = GURL("https://foo.com/login");
+  form.username_element = ASCIIToUTF16("username");
+  form.username_value = ASCIIToUTF16("test@gmail.com");
+  form.password_element = ASCIIToUTF16("password");
+  form.password_value = ASCIIToUTF16("test");
+  form.submit_element = ASCIIToUTF16("");
+  form.signon_realm = "https://foo.com/";
+  form.ssl_valid = true;
+  form.preferred = false;
+  form.scheme = PasswordForm::SCHEME_HTML;
+
+  // Add it and make sure it is there.
+  EXPECT_TRUE(db_.AddLogin(form));
+  EXPECT_TRUE(db_.GetAutofillableLogins(&result));
+  EXPECT_EQ(1U, result.size());
+  delete result[0];
+  result.clear();
+
+  // Match against an exact copy.
+  EXPECT_TRUE(db_.GetLogins(form, &result));
+  EXPECT_EQ(1U, result.size());
+  delete result[0];
+  result.clear();
+
+  // We go to the mobile site.
+  PasswordForm form2(form);
+  form2.origin = GURL("https://mobile.foo.com/");
+  form2.action = GURL("https://mobile.foo.com/login");
+  form2.signon_realm = "https://mobile.foo.com/";
+
+  // Match against the mobile site.
+  EXPECT_TRUE(db_.GetLogins(form2, &result));
+  EXPECT_EQ(1U, result.size());
+  EXPECT_EQ("https://mobile.foo.com/", result[0]->signon_realm);
+  EXPECT_EQ("https://foo.com/", result[0]->original_signon_realm);
+  delete result[0];
+  result.clear();
+
+  // Add baz.com desktop site.
+  form.origin = GURL("https://baz.com/login/");
+  form.action = GURL("https://baz.com/login/");
+  form.username_element = ASCIIToUTF16("email");
+  form.username_value = ASCIIToUTF16("test@gmail.com");
+  form.password_element = ASCIIToUTF16("password");
+  form.password_value = ASCIIToUTF16("test");
+  form.submit_element = ASCIIToUTF16("");
+  form.signon_realm = "https://baz.com/";
+  form.ssl_valid = true;
+  form.preferred = false;
+  form.scheme = PasswordForm::SCHEME_HTML;
+
+  // Add it and make sure it is there.
+  EXPECT_TRUE(db_.AddLogin(form));
+  EXPECT_TRUE(db_.GetAutofillableLogins(&result));
+  EXPECT_EQ(2U, result.size());
+  delete result[0];
+  delete result[1];
+  result.clear();
+
+  // We go to the mobile site of baz.com.
+  PasswordForm form3(form);
+  form3.origin = GURL("https://m.baz.com/login/");
+  form3.action = GURL("https://m.baz.com/login/");
+  form3.signon_realm = "https://m.baz.com/";
+
+  // Match against the mobile site of baz.com.
+  EXPECT_TRUE(db_.GetLogins(form3, &result));
+  EXPECT_EQ(1U, result.size());
+  EXPECT_EQ("https://m.baz.com/", result[0]->signon_realm);
+  EXPECT_EQ("https://baz.com/", result[0]->original_signon_realm);
+  delete result[0];
+  result.clear();
+}
+
+PasswordForm GetFormWithNewSignonRealm(PasswordForm form,
+                                       std::string signon_realm) {
+  PasswordForm form2(form);
+  form2.origin = GURL(signon_realm);
+  form2.action = GURL(signon_realm);
+  form2.signon_realm = signon_realm;
+  return form2;
+}
+
+TEST_F(LoginDatabaseTest, TestPublicSuffixDomainMatchingRegexp) {
+  SetPublicSuffixMatching(true);
+  std::vector<PasswordForm*> result;
+
+  // Verify the database is empty.
+  EXPECT_TRUE(db_.GetAutofillableLogins(&result));
+  EXPECT_EQ(0U, result.size());
+
+  // Example password form.
+  PasswordForm form;
+  form.origin = GURL("http://foo.com/");
+  form.action = GURL("http://foo.com/login");
+  form.username_element = ASCIIToUTF16("username");
+  form.username_value = ASCIIToUTF16("test@gmail.com");
+  form.password_element = ASCIIToUTF16("password");
+  form.password_value = ASCIIToUTF16("test");
+  form.submit_element = ASCIIToUTF16("");
+  form.signon_realm = "http://foo.com/";
+  form.ssl_valid = false;
+  form.preferred = false;
+  form.scheme = PasswordForm::SCHEME_HTML;
+
+  // Add it and make sure it is there.
+  EXPECT_TRUE(db_.AddLogin(form));
+  EXPECT_TRUE(db_.GetAutofillableLogins(&result));
+  EXPECT_EQ(1U, result.size());
+  delete result[0];
+  result.clear();
+
+  // Example password form that has - in the domain name.
+  PasswordForm form_dash =
+      GetFormWithNewSignonRealm(form, "http://www.foo-bar.com/");
+
+  // Add it and make sure it is there.
+  EXPECT_TRUE(db_.AddLogin(form_dash));
+  EXPECT_TRUE(db_.GetAutofillableLogins(&result));
+  EXPECT_EQ(2U, result.size());
+  delete result[0];
+  delete result[1];
+  result.clear();
+
+  // Match against an exact copy.
+  EXPECT_TRUE(db_.GetLogins(form, &result));
+  EXPECT_EQ(1U, result.size());
+  delete result[0];
+  result.clear();
+
+  // www.foo.com should match.
+  PasswordForm form2 = GetFormWithNewSignonRealm(form, "http://www.foo.com/");
+  EXPECT_TRUE(db_.GetLogins(form2, &result));
+  EXPECT_EQ(1U, result.size());
+  delete result[0];
+  result.clear();
+
+  // a.b.foo.com should match.
+  form2 = GetFormWithNewSignonRealm(form, "http://a.b.foo.com/");
+  EXPECT_TRUE(db_.GetLogins(form2, &result));
+  EXPECT_EQ(1U, result.size());
+  delete result[0];
+  result.clear();
+
+  // a-b.foo.com should match.
+  form2 = GetFormWithNewSignonRealm(form, "http://a-b.foo.com/");
+  EXPECT_TRUE(db_.GetLogins(form2, &result));
+  EXPECT_EQ(1U, result.size());
+  delete result[0];
+  result.clear();
+
+  // foo-bar.com should match.
+  form2 = GetFormWithNewSignonRealm(form, "http://foo-bar.com/");
+  EXPECT_TRUE(db_.GetLogins(form2, &result));
+  EXPECT_EQ(1U, result.size());
+  delete result[0];
+  result.clear();
+
+  // www.foo-bar.com should match.
+  form2 = GetFormWithNewSignonRealm(form, "http://www.foo-bar.com/");
+  EXPECT_TRUE(db_.GetLogins(form2, &result));
+  EXPECT_EQ(1U, result.size());
+  delete result[0];
+  result.clear();
+
+  // a.b.foo-bar.com should match.
+  form2 = GetFormWithNewSignonRealm(form, "http://a.b.foo-bar.com/");
+  EXPECT_TRUE(db_.GetLogins(form2, &result));
+  EXPECT_EQ(1U, result.size());
+  delete result[0];
+  result.clear();
+
+  // a-b.foo-bar.com should match.
+  form2 = GetFormWithNewSignonRealm(form, "http://a-b.foo-bar.com/");
+  EXPECT_TRUE(db_.GetLogins(form2, &result));
+  EXPECT_EQ(1U, result.size());
+  delete result[0];
+  result.clear();
+
+  // foo.com with port 1337 should not match.
+  form2 = GetFormWithNewSignonRealm(form, "http://foo.com:1337/");
+  EXPECT_TRUE(db_.GetLogins(form2, &result));
+  EXPECT_EQ(0U, result.size());
+
+  // http://foo.com should not match since the scheme is wrong.
+  form2 = GetFormWithNewSignonRealm(form, "https://foo.com/");
+  EXPECT_TRUE(db_.GetLogins(form2, &result));
+  EXPECT_EQ(0U, result.size());
+
+  // notfoo.com should not match.
+  form2 = GetFormWithNewSignonRealm(form, "http://notfoo.com/");
+  EXPECT_TRUE(db_.GetLogins(form2, &result));
+  EXPECT_EQ(0U, result.size());
+
+  // baz.com should not match.
+  form2 = GetFormWithNewSignonRealm(form, "http://baz.com/");
+  EXPECT_TRUE(db_.GetLogins(form2, &result));
+  EXPECT_EQ(0U, result.size());
+
+  // foo-baz.com should not match.
+  form2 = GetFormWithNewSignonRealm(form, "http://foo-baz.com/");
+  EXPECT_TRUE(db_.GetLogins(form2, &result));
+  EXPECT_EQ(0U, result.size());
+}
+
 static bool AddTimestampedLogin(LoginDatabase* db, std::string url,
                                 const std::string& unique_string,
                                 const base::Time& time) {
diff --git a/chrome/browser/password_manager/native_backend_gnome_x.cc b/chrome/browser/password_manager/native_backend_gnome_x.cc
index 735e381..68c54d4 100644
--- a/chrome/browser/password_manager/native_backend_gnome_x.cc
+++ b/chrome/browser/password_manager/native_backend_gnome_x.cc
@@ -18,7 +18,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/waitable_event.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "content/public/browser/browser_thread.h"
 
 using content::BrowserThread;
diff --git a/chrome/browser/password_manager/native_backend_gnome_x.h b/chrome/browser/password_manager/native_backend_gnome_x.h
index f421831..567d733 100644
--- a/chrome/browser/password_manager/native_backend_gnome_x.h
+++ b/chrome/browser/password_manager/native_backend_gnome_x.h
@@ -10,7 +10,7 @@
 #include <string>
 
 #include "base/basictypes.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/password_manager/password_store_factory.h"
 #include "chrome/browser/password_manager/password_store_x.h"
 #include "chrome/browser/profiles/profile.h"
diff --git a/chrome/browser/password_manager/native_backend_gnome_x_unittest.cc b/chrome/browser/password_manager/native_backend_gnome_x_unittest.cc
index a35b7e4..fac8b9f 100644
--- a/chrome/browser/password_manager/native_backend_gnome_x_unittest.cc
+++ b/chrome/browser/password_manager/native_backend_gnome_x_unittest.cc
@@ -10,7 +10,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/password_manager/native_backend_gnome_x.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_profile.h"
diff --git a/chrome/browser/password_manager/native_backend_kwallet_x.h b/chrome/browser/password_manager/native_backend_kwallet_x.h
index e19bc3d..8029e61 100644
--- a/chrome/browser/password_manager/native_backend_kwallet_x.h
+++ b/chrome/browser/password_manager/native_backend_kwallet_x.h
@@ -9,7 +9,7 @@
 
 #include "base/basictypes.h"
 #include "base/memory/ref_counted.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/password_manager/password_store_factory.h"
 #include "chrome/browser/password_manager/password_store_x.h"
 #include "chrome/browser/profiles/profile.h"
diff --git a/chrome/browser/password_manager/password_form_manager.cc b/chrome/browser/password_manager/password_form_manager.cc
index 1bf3d7d..59c5a6a 100644
--- a/chrome/browser/password_manager/password_form_manager.cc
+++ b/chrome/browser/password_manager/password_form_manager.cc
@@ -13,7 +13,7 @@
 #include "chrome/browser/password_manager/password_store.h"
 #include "chrome/browser/password_manager/password_store_factory.h"
 #include "chrome/browser/profiles/profile.h"
-#include "components/autofill/browser/validation.h"
+#include "components/autofill/core/browser/validation.h"
 #include "components/autofill/core/common/autofill_messages.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
@@ -153,6 +153,10 @@
   return is_new_login_;
 }
 
+bool PasswordFormManager::IsPendingCredentialsPublicSuffixMatch() {
+  return pending_credentials_.IsPublicSuffixMatch();
+}
+
 void PasswordFormManager::SetHasGeneratedPassword() {
   has_generated_password_ = true;
 }
@@ -189,7 +193,10 @@
   if (it != best_matches_.end()) {
     // The user signed in with a login we autofilled.
     pending_credentials_ = *it->second;
-    is_new_login_ = false;
+
+    // Public suffix matches should always be new logins, since we want to store
+    // them so they can automatically be filled in later.
+    is_new_login_ = IsPendingCredentialsPublicSuffixMatch();
 
     // Check to see if we're using a known username but a new password.
     if (pending_credentials_.password_value != credentials.password_value)
@@ -337,12 +344,14 @@
   SendNotBlacklistedToRenderer();
 
   // Proceed to autofill.
-  // Note that we provide the choices but don't actually prefill a value if
-  // either: (1) we are in Incognito mode, or (2) the ACTION paths don't match.
+  // Note that we provide the choices but don't actually prefill a value if:
+  // (1) we are in Incognito mode, (2) the ACTION paths don't match,
+  // or (3) if it matched using public suffix domain matching.
   bool wait_for_username =
       profile_->IsOffTheRecord() ||
       observed_form_.action.GetWithEmptyPath() !=
-          preferred_match_->action.GetWithEmptyPath();
+          preferred_match_->action.GetWithEmptyPath() ||
+          preferred_match_->IsPublicSuffixMatch();
   if (wait_for_username)
     manager_action_ = kManagerActionNone;
   else
@@ -528,19 +537,21 @@
   // The most important element that should match is the origin, followed by
   // the action, the password name, the submit button name, and finally the
   // username input field name.
-  // Exact origin match gives an addition of 32 (1 << 5) + # of matching url
+  // Exact origin match gives an addition of 64 (1 << 6) + # of matching url
   // dirs.
-  // Partial match gives an addition of 16 (1 << 4) + # matching url dirs
+  // Partial match gives an addition of 32 (1 << 5) + # matching url dirs
   // That way, a partial match cannot trump an exact match even if
   // the partial one matches all other attributes (action, elements) (and
   // regardless of the matching depth in the URL path).
+  // If public suffix origin match was not used, it gives an addition of
+  // 16 (1 << 4).
   int score = 0;
   if (candidate.origin == observed_form_.origin) {
     // This check is here for the most common case which
     // is we have a single match in the db for the given host,
     // so we don't generally need to walk the entire URL path (the else
     // clause).
-    score += (1 << 5) + static_cast<int>(form_path_tokens_.size());
+    score += (1 << 6) + static_cast<int>(form_path_tokens_.size());
   } else {
     // Walk the origin URL paths one directory at a time to see how
     // deep the two match.
@@ -555,9 +566,11 @@
       score++;
     }
     // do we have a partial match?
-    score += (depth > 0) ? 1 << 4 : 0;
+    score += (depth > 0) ? 1 << 5 : 0;
   }
   if (observed_form_.scheme == PasswordForm::SCHEME_HTML) {
+    if (!candidate.IsPublicSuffixMatch())
+      score += 1 << 4;
     if (candidate.action == observed_form_.action)
       score += 1 << 3;
     if (candidate.password_element == observed_form_.password_element)
diff --git a/chrome/browser/password_manager/password_form_manager.h b/chrome/browser/password_manager/password_form_manager.h
index cd5cf3e..8777299 100644
--- a/chrome/browser/password_manager/password_form_manager.h
+++ b/chrome/browser/password_manager/password_form_manager.h
@@ -79,6 +79,11 @@
   // managed by this.
   bool IsNewLogin();
 
+  // Returns true if the current pending credentials were found using
+  // origin matching of the public suffix, instead of the signon realm of the
+  // form.
+  bool IsPendingCredentialsPublicSuffixMatch();
+
   // Checks if the form is a valid password form. Forms which lack either
   // login or password field are not considered valid.
   bool HasValidPasswordForm();
diff --git a/chrome/browser/password_manager/password_generation_manager.cc b/chrome/browser/password_manager/password_generation_manager.cc
index 4742d21..4c8051b 100644
--- a/chrome/browser/password_manager/password_generation_manager.cc
+++ b/chrome/browser/password_manager/password_generation_manager.cc
@@ -13,7 +13,7 @@
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/common/pref_names.h"
-#include "components/autofill/browser/password_generator.h"
+#include "components/autofill/core/browser/password_generator.h"
 #include "components/autofill/core/common/autofill_messages.h"
 #include "components/user_prefs/pref_registry_syncable.h"
 #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/password_manager/password_manager.cc b/chrome/browser/password_manager/password_manager.cc
index a262a18..2affc0b 100644
--- a/chrome/browser/password_manager/password_manager.cc
+++ b/chrome/browser/password_manager/password_manager.cc
@@ -268,6 +268,12 @@
   }
 }
 
+bool PasswordManager::ShouldShowSavePasswordInfoBar() const {
+  return provisional_save_manager_->IsNewLogin() &&
+      !provisional_save_manager_->HasGeneratedPassword() &&
+      !provisional_save_manager_->IsPendingCredentialsPublicSuffixMatch();
+}
+
 void PasswordManager::OnPasswordFormsRendered(
     const std::vector<PasswordForm>& visible_forms) {
   if (!provisional_save_manager_.get())
@@ -302,8 +308,7 @@
   provisional_save_manager_->SubmitPassed();
   if (provisional_save_manager_->HasGeneratedPassword())
     UMA_HISTOGRAM_COUNTS("PasswordGeneration.Submitted", 1);
-  if (provisional_save_manager_->IsNewLogin() &&
-      !provisional_save_manager_->HasGeneratedPassword()) {
+  if (ShouldShowSavePasswordInfoBar()) {
     delegate_->AddSavePasswordInfoBarIfPermitted(
         provisional_save_manager_.release());
   } else {
diff --git a/chrome/browser/password_manager/password_manager.h b/chrome/browser/password_manager/password_manager.h
index eda8654..f2a84e4 100644
--- a/chrome/browser/password_manager/password_manager.h
+++ b/chrome/browser/password_manager/password_manager.h
@@ -102,6 +102,10 @@
   // the username for the form is ambigious.
   bool OtherPossibleUsernamesEnabled() const;
 
+  // Returns true if we should show an infobar instead of automatically saving
+  // the password, based on inspecting the state of |provisional_save_manager_|.
+  bool ShouldShowSavePasswordInfoBar() const;
+
   // Note about how a PasswordFormManager can transition from
   // pending_login_managers_ to provisional_save_manager_ and the infobar.
   //
diff --git a/chrome/browser/password_manager/password_manager_delegate_impl.cc b/chrome/browser/password_manager/password_manager_delegate_impl.cc
index 822f983..1df2755 100644
--- a/chrome/browser/password_manager/password_manager_delegate_impl.cc
+++ b/chrome/browser/password_manager/password_manager_delegate_impl.cc
@@ -13,8 +13,8 @@
 #include "chrome/browser/password_manager/password_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/sync/one_click_signin_helper.h"
-#include "components/autofill/browser/autofill_manager.h"
 #include "components/autofill/content/browser/autofill_driver_impl.h"
+#include "components/autofill/core/browser/autofill_manager.h"
 #include "components/autofill/core/common/autofill_messages.h"
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/render_view_host.h"
@@ -167,16 +167,10 @@
 
 void PasswordManagerDelegateImpl::FillPasswordForm(
     const autofill::PasswordFormFillData& form_data) {
-  autofill::AutofillDriverImpl* autofill_driver =
-      autofill::AutofillDriverImpl::FromWebContents(web_contents_);
-  // Browser process will own popup UI, so renderer should not show the popup.
-  bool disable_popup = autofill_driver->autofill_manager()->IsNativeUiEnabled();
-
   web_contents_->GetRenderViewHost()->Send(
       new AutofillMsg_FillPasswordForm(
           web_contents_->GetRenderViewHost()->GetRoutingID(),
-          form_data,
-          disable_popup));
+          form_data));
 }
 
 void PasswordManagerDelegateImpl::AddSavePasswordInfoBarIfPermitted(
diff --git a/chrome/browser/password_manager/password_store.h b/chrome/browser/password_manager/password_store.h
index 04fdffc..4d6079f 100644
--- a/chrome/browser/password_manager/password_store.h
+++ b/chrome/browser/password_manager/password_store.h
@@ -11,7 +11,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/observer_list.h"
 #include "base/threading/thread.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/common/cancelable_request.h"
 #include "chrome/common/cancelable_task_tracker.h"
 #include "components/browser_context_keyed_service/refcounted_browser_context_keyed_service.h"
diff --git a/chrome/browser/password_manager/password_store_default_unittest.cc b/chrome/browser/password_manager/password_store_default_unittest.cc
index 99c6ad4..a949061 100644
--- a/chrome/browser/password_manager/password_store_default_unittest.cc
+++ b/chrome/browser/password_manager/password_store_default_unittest.cc
@@ -10,7 +10,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/waitable_event.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/password_manager/password_form_data.h"
 #include "chrome/browser/password_manager/password_store_change.h"
 #include "chrome/browser/password_manager/password_store_consumer.h"
diff --git a/chrome/browser/password_manager/password_store_unittest.cc b/chrome/browser/password_manager/password_store_unittest.cc
index a4b695a..458d222 100644
--- a/chrome/browser/password_manager/password_store_unittest.cc
+++ b/chrome/browser/password_manager/password_store_unittest.cc
@@ -7,7 +7,7 @@
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/synchronization/waitable_event.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/password_manager/password_form_data.h"
 #include "chrome/browser/password_manager/password_store_consumer.h"
 #include "chrome/browser/password_manager/password_store_default.h"
diff --git a/chrome/browser/password_manager/password_store_win_unittest.cc b/chrome/browser/password_manager/password_store_win_unittest.cc
index 488cb09..dfbe3c5 100644
--- a/chrome/browser/password_manager/password_store_win_unittest.cc
+++ b/chrome/browser/password_manager/password_store_win_unittest.cc
@@ -15,7 +15,7 @@
 #include "base/prefs/pref_service.h"
 #include "base/stl_util.h"
 #include "base/synchronization/waitable_event.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/password_manager/password_form_data.h"
 #include "chrome/browser/password_manager/password_store_consumer.h"
 #include "chrome/browser/password_manager/password_store_win.h"
diff --git a/chrome/browser/password_manager/password_store_x.h b/chrome/browser/password_manager/password_store_x.h
index 80c8527..05e0351 100644
--- a/chrome/browser/password_manager/password_store_x.h
+++ b/chrome/browser/password_manager/password_store_x.h
@@ -8,7 +8,7 @@
 #include <vector>
 
 #include "base/memory/scoped_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/password_manager/password_store_default.h"
 
 class LoginDatabase;
diff --git a/chrome/browser/password_manager/password_store_x_unittest.cc b/chrome/browser/password_manager/password_store_x_unittest.cc
index 22b7467..8b5cb44 100644
--- a/chrome/browser/password_manager/password_store_x_unittest.cc
+++ b/chrome/browser/password_manager/password_store_x_unittest.cc
@@ -14,7 +14,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/waitable_event.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/password_manager/password_form_data.h"
 #include "chrome/browser/password_manager/password_store_change.h"
 #include "chrome/browser/password_manager/password_store_consumer.h"
diff --git a/chrome/browser/pepper_broker_infobar_delegate.h b/chrome/browser/pepper_broker_infobar_delegate.h
index 9b5bdb3..fa5a936 100644
--- a/chrome/browser/pepper_broker_infobar_delegate.h
+++ b/chrome/browser/pepper_broker_infobar_delegate.h
@@ -8,7 +8,7 @@
 #include "base/callback.h"
 #include "base/files/file_path.h"
 #include "chrome/browser/infobars/confirm_infobar_delegate.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 class HostContentSettingsMap;
 class InfoBarService;
diff --git a/chrome/browser/pepper_flash_settings_manager.cc b/chrome/browser/pepper_flash_settings_manager.cc
index fbf0c84..c6454bd 100644
--- a/chrome/browser/pepper_flash_settings_manager.cc
+++ b/chrome/browser/pepper_flash_settings_manager.cc
@@ -24,10 +24,10 @@
 #include "content/public/browser/pepper_flash_settings_helper.h"
 #include "content/public/browser/plugin_service.h"
 #include "content/public/common/content_constants.h"
-#include "googleurl/src/gurl.h"
 #include "ipc/ipc_channel.h"
 #include "ipc/ipc_listener.h"
 #include "ppapi/proxy/ppapi_messages.h"
+#include "url/gurl.h"
 #include "webkit/plugins/plugin_constants.h"
 #include "webkit/plugins/webplugininfo.h"
 
@@ -461,7 +461,7 @@
   // Wipe that file.
   const base::FilePath& device_id_path =
       chrome::DeviceIDFetcher::GetLegacyDeviceIDPath(profile_path);
-  bool success = file_util::Delete(device_id_path, false);
+  bool success = base::Delete(device_id_path, false);
 
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
diff --git a/chrome/browser/performance_monitor/constants.h b/chrome/browser/performance_monitor/constants.h
index 5face47..168baf2 100644
--- a/chrome/browser/performance_monitor/constants.h
+++ b/chrome/browser/performance_monitor/constants.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_PERFORMANCE_MONITOR_CONSTANTS_H_
 
 #include "base/basictypes.h"
-#include "base/time.h"
+#include "base/time/time.h"
 
 namespace performance_monitor {
 
@@ -34,7 +34,7 @@
 const int64 kBytesPerGigabyte = kBytesPerMegabyte * (1 << 10);
 const int64 kBytesPerTerabyte = kBytesPerGigabyte * (1 << 10);
 
-// Time measurements - Most of these are imported from base/time.h
+// Time measurements - Most of these are imported from base/time/time.h
 // These units are used for display (and it's related calculations), not for
 // any mathematical analysis. Thus we can estimate for values without an exact
 // conversion.
diff --git a/chrome/browser/performance_monitor/database.cc b/chrome/browser/performance_monitor/database.cc
index a109f3b..36bc93c 100644
--- a/chrome/browser/performance_monitor/database.cc
+++ b/chrome/browser/performance_monitor/database.cc
@@ -13,7 +13,7 @@
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/performance_monitor/key_builder.h"
 #include "chrome/common/chrome_paths.h"
 #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/performance_monitor/database.h b/chrome/browser/performance_monitor/database.h
index 0ac1fb8..87082cd 100644
--- a/chrome/browser/performance_monitor/database.h
+++ b/chrome/browser/performance_monitor/database.h
@@ -13,7 +13,7 @@
 #include "base/gtest_prod_util.h"
 #include "base/memory/linked_ptr.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/performance_monitor/constants.h"
 #include "chrome/browser/performance_monitor/event.h"
 #include "chrome/browser/performance_monitor/metric.h"
diff --git a/chrome/browser/performance_monitor/database_unittest.cc b/chrome/browser/performance_monitor/database_unittest.cc
index f92505a..bde1fe3 100644
--- a/chrome/browser/performance_monitor/database_unittest.cc
+++ b/chrome/browser/performance_monitor/database_unittest.cc
@@ -9,7 +9,7 @@
 #include "base/files/file_path.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/performance_monitor/database.h"
 #include "chrome/browser/performance_monitor/key_builder.h"
 #include "chrome/browser/performance_monitor/metric.h"
diff --git a/chrome/browser/performance_monitor/event.h b/chrome/browser/performance_monitor/event.h
index 1dbbe3b..b7666b4 100644
--- a/chrome/browser/performance_monitor/event.h
+++ b/chrome/browser/performance_monitor/event.h
@@ -5,9 +5,9 @@
 #ifndef CHROME_BROWSER_PERFORMANCE_MONITOR_EVENT_H_
 #define CHROME_BROWSER_PERFORMANCE_MONITOR_EVENT_H_
 
-#include "base/values.h"
-#include "base/time.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/time/time.h"
+#include "base/values.h"
 
 namespace performance_monitor {
 
diff --git a/chrome/browser/performance_monitor/events.json b/chrome/browser/performance_monitor/events.json
index ab5ffc6..3b04c35 100644
--- a/chrome/browser/performance_monitor/events.json
+++ b/chrome/browser/performance_monitor/events.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "events",
+    "description": "Performance monitor events",
     "types": [
       {
         "id": "ExtensionEvent",
diff --git a/chrome/browser/performance_monitor/metric.cc b/chrome/browser/performance_monitor/metric.cc
index de50cb3..2699c41 100644
--- a/chrome/browser/performance_monitor/metric.cc
+++ b/chrome/browser/performance_monitor/metric.cc
@@ -7,7 +7,7 @@
 #include "base/basictypes.h"
 #include "base/logging.h"
 #include "base/strings/string_number_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/performance_monitor/constants.h"
 
 namespace performance_monitor {
diff --git a/chrome/browser/performance_monitor/metric.h b/chrome/browser/performance_monitor/metric.h
index a7772ec..ab9da9f 100644
--- a/chrome/browser/performance_monitor/metric.h
+++ b/chrome/browser/performance_monitor/metric.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_PERFORMANCE_MONITOR_METRIC_H_
 
 #include <string>
-#include "base/time.h"
+#include "base/time/time.h"
 
 namespace performance_monitor {
 
diff --git a/chrome/browser/performance_monitor/performance_monitor.cc b/chrome/browser/performance_monitor/performance_monitor.cc
index 643c4c1..6d7ed4f 100644
--- a/chrome/browser/performance_monitor/performance_monitor.cc
+++ b/chrome/browser/performance_monitor/performance_monitor.cc
@@ -14,7 +14,7 @@
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/threading/worker_pool.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_shutdown.h"
 #include "chrome/browser/extensions/crx_installer.h"
@@ -618,23 +618,19 @@
       details.status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED ?
       EVENT_RENDERER_KILLED : EVENT_RENDERER_CRASH;
 
-  content::RenderProcessHost::RenderWidgetHostsIterator iter =
-      host->GetRenderWidgetHostsIterator();
-
   // A RenderProcessHost may contain multiple render views - for each valid
   // render view, extract the url, and append it to the string, comma-separating
   // the entries.
   std::string url_list;
-  for (; !iter.IsAtEnd(); iter.Advance()) {
-    const content::RenderWidgetHost* widget = iter.GetCurrentValue();
-    DCHECK(widget);
-    if (!widget || !widget->IsRenderView())
+  content::RenderWidgetHost::List widgets =
+      content::RenderWidgetHost::GetRenderWidgetHosts();
+  for (size_t i = 0; i < widgets.size(); ++i) {
+    if (widgets[i]->GetProcess()->GetID() != host->GetID())
+      continue;
+    if (!widgets[i]->IsRenderView())
       continue;
 
-    content::RenderViewHost* view =
-        content::RenderViewHost::From(
-            const_cast<content::RenderWidgetHost*>(widget));
-
+    content::RenderViewHost* view = content::RenderViewHost::From(widgets[i]);
     std::string url;
     if (!MaybeGetURLFromRenderView(view, &url))
       continue;
diff --git a/chrome/browser/performance_monitor/performance_monitor.h b/chrome/browser/performance_monitor/performance_monitor.h
index 652b4ea..d8cd74e 100644
--- a/chrome/browser/performance_monitor/performance_monitor.h
+++ b/chrome/browser/performance_monitor/performance_monitor.h
@@ -15,7 +15,7 @@
 #include "base/memory/singleton.h"
 #include "base/process.h"
 #include "base/process_util.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/performance_monitor/database.h"
 #include "chrome/browser/performance_monitor/event.h"
 #include "content/public/browser/notification_details.h"
diff --git a/chrome/browser/performance_monitor/performance_monitor_browsertest.cc b/chrome/browser/performance_monitor/performance_monitor_browsertest.cc
index 535bb34..3d2c95c 100644
--- a/chrome/browser/performance_monitor/performance_monitor_browsertest.cc
+++ b/chrome/browser/performance_monitor/performance_monitor_browsertest.cc
@@ -374,7 +374,7 @@
     content::TestNavigationObserver restore_observer(NULL, expected_tab_count);
     restore_observer.StartWatchingNewWebContents();
     ui_test_utils::BrowserAddedObserver window_observer;
-    chrome::NewEmptyWindow(profile, chrome::HOST_DESKTOP_TYPE_NATIVE);
+    chrome::NewEmptyWindow(profile, chrome::GetActiveDesktop());
     Browser* new_browser = window_observer.WaitForSingleNewBrowser();
     restore_observer.Wait();
     g_browser_process->ReleaseModule();
diff --git a/chrome/browser/performance_monitor/performance_monitor_util.cc b/chrome/browser/performance_monitor/performance_monitor_util.cc
index 2682240..7f94a01 100644
--- a/chrome/browser/performance_monitor/performance_monitor_util.cc
+++ b/chrome/browser/performance_monitor/performance_monitor_util.cc
@@ -8,7 +8,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/threading/sequenced_worker_pool.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/performance_monitor/events.h"
 #include "content/public/browser/browser_thread.h"
 
diff --git a/chrome/browser/performance_monitor/performance_monitor_util.h b/chrome/browser/performance_monitor/performance_monitor_util.h
index b1052db..7ad35bc 100644
--- a/chrome/browser/performance_monitor/performance_monitor_util.h
+++ b/chrome/browser/performance_monitor/performance_monitor_util.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_PERFORMANCE_MONITOR_PERFORMANCE_MONITOR_UTIL_H_
 
 #include "base/callback.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/tracked_objects.h"
 #include "chrome/browser/performance_monitor/database.h"
 #include "chrome/browser/performance_monitor/event.h"
diff --git a/chrome/browser/performance_monitor/startup_timer.h b/chrome/browser/performance_monitor/startup_timer.h
index 2bab4db..fc32a32 100644
--- a/chrome/browser/performance_monitor/startup_timer.h
+++ b/chrome/browser/performance_monitor/startup_timer.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_PERFORMANCE_MONITOR_STARTUP_TIMER_H_
 #define CHROME_BROWSER_PERFORMANCE_MONITOR_STARTUP_TIMER_H_
 
-#include "base/time.h"
+#include "base/time/time.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 
diff --git a/chrome/browser/platform_util_chromeos.cc b/chrome/browser/platform_util_chromeos.cc
index 1d68cab..ae27115 100644
--- a/chrome/browser/platform_util_chromeos.cc
+++ b/chrome/browser/platform_util_chromeos.cc
@@ -12,7 +12,7 @@
 #include "chrome/browser/ui/host_desktop.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "content/public/browser/browser_thread.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 using content::BrowserThread;
 
@@ -29,6 +29,7 @@
   chrome::NavigateParams params(
       browser, GURL(url), content::PAGE_TRANSITION_LINK);
   params.disposition = NEW_FOREGROUND_TAB;
+  params.window_action = chrome::NavigateParams::SHOW_WINDOW;
   chrome::Navigate(&params);
 }
 
@@ -61,6 +62,9 @@
     string_url.append(url.spec());
     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
                             base::Bind(OpenURL, string_url));
+  } else if (url.is_valid()) {
+    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+                            base::Bind(OpenURL, url.spec()));
   }
 }
 
diff --git a/chrome/browser/platform_util_linux.cc b/chrome/browser/platform_util_linux.cc
index 5bae77f..9ac22d7 100644
--- a/chrome/browser/platform_util_linux.cc
+++ b/chrome/browser/platform_util_linux.cc
@@ -9,7 +9,7 @@
 #include "base/process_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "content/public/browser/browser_thread.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 using content::BrowserThread;
 
diff --git a/chrome/browser/platform_util_mac.mm b/chrome/browser/platform_util_mac.mm
index 5a97ecf..fad64e6 100644
--- a/chrome/browser/platform_util_mac.mm
+++ b/chrome/browser/platform_util_mac.mm
@@ -13,10 +13,10 @@
 #include "base/mac/mac_logging.h"
 #include "base/mac/scoped_aedesc.h"
 #include "base/strings/sys_string_conversions.h"
-#include "googleurl/src/gurl.h"
 #include "grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/l10n/l10n_util_mac.h"
+#include "url/gurl.h"
 
 namespace platform_util {
 
diff --git a/chrome/browser/platform_util_win.cc b/chrome/browser/platform_util_win.cc
index 90c02c0..2a6a8d7 100644
--- a/chrome/browser/platform_util_win.cc
+++ b/chrome/browser/platform_util_win.cc
@@ -20,9 +20,9 @@
 #include "base/win/scoped_comptr.h"
 #include "base/win/windows_version.h"
 #include "content/public/browser/browser_thread.h"
-#include "googleurl/src/gurl.h"
 #include "ui/base/win/shell.h"
 #include "ui/gfx/native_widget_types.h"
+#include "url/gurl.h"
 
 using content::BrowserThread;
 
diff --git a/chrome/browser/plugins/chrome_plugin_service_filter.cc b/chrome/browser/plugins/chrome_plugin_service_filter.cc
index ac639b7..853018e 100644
--- a/chrome/browser/plugins/chrome_plugin_service_filter.cc
+++ b/chrome/browser/plugins/chrome_plugin_service_filter.cc
@@ -59,8 +59,7 @@
     const GURL& origin) {
   base::AutoLock auto_lock(lock_);
   restricted_plugins_[plugin_path] =
-      std::make_pair(PluginPrefs::GetForProfile(profile),
-                     origin);
+      std::make_pair(PluginPrefs::GetForProfile(profile).get(), origin);
 }
 
 void ChromePluginServiceFilter::UnrestrictPlugin(
diff --git a/chrome/browser/plugins/chrome_plugin_service_filter.h b/chrome/browser/plugins/chrome_plugin_service_filter.h
index 2ef01d4..5b61c3a 100644
--- a/chrome/browser/plugins/chrome_plugin_service_filter.h
+++ b/chrome/browser/plugins/chrome_plugin_service_filter.h
@@ -17,7 +17,7 @@
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "content/public/browser/plugin_service_filter.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 #include "webkit/plugins/webplugininfo.h"
 
 class PluginPrefs;
diff --git a/chrome/browser/plugins/plugin_finder.cc b/chrome/browser/plugins/plugin_finder.cc
index f32efcb..9dbfa30 100644
--- a/chrome/browser/plugins/plugin_finder.cc
+++ b/chrome/browser/plugins/plugin_finder.cc
@@ -18,9 +18,9 @@
 #include "chrome/common/pref_names.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/plugin_service.h"
-#include "googleurl/src/gurl.h"
 #include "grit/browser_resources.h"
 #include "ui/base/resource/resource_bundle.h"
+#include "url/gurl.h"
 
 #if defined(ENABLE_PLUGIN_INSTALLATION)
 #include "chrome/browser/plugins/plugin_installer.h"
diff --git a/chrome/browser/plugins/plugin_info_message_filter.cc b/chrome/browser/plugins/plugin_info_message_filter.cc
index d04c90a..cb19888 100644
--- a/chrome/browser/plugins/plugin_info_message_filter.cc
+++ b/chrome/browser/plugins/plugin_info_message_filter.cc
@@ -22,7 +22,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/plugin_service.h"
 #include "content/public/browser/plugin_service_filter.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 #include "webkit/plugins/npapi/plugin_list.h"
 
 #include "widevine_cdm_version.h"  // In SHARED_INTERMEDIATE_DIR.
@@ -47,13 +47,13 @@
   if (plugin.name == ASCIIToUTF16(chrome::ChromeContentClient::kNaClPluginName))
     return true;
 
-#if defined(WIDEVINE_CDM_AVAILABLE)
+#if defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
   // Treat CDM invocations like JavaScript.
   if (plugin.name == ASCIIToUTF16(kWidevineCdmDisplayName)) {
     DCHECK(plugin.type == WebPluginInfo::PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS);
     return true;
   }
-#endif  // WIDEVINE_CDM_AVAILABLE
+#endif  // defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
 
   return false;
 }
diff --git a/chrome/browser/plugins/plugin_infobar_delegates.h b/chrome/browser/plugins/plugin_infobar_delegates.h
index fcb261f..5e4cb31 100644
--- a/chrome/browser/plugins/plugin_infobar_delegates.h
+++ b/chrome/browser/plugins/plugin_infobar_delegates.h
@@ -7,7 +7,7 @@
 
 #include "base/callback.h"
 #include "chrome/browser/infobars/confirm_infobar_delegate.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 #if defined(ENABLE_PLUGIN_INSTALLATION)
 #include "chrome/browser/plugins/plugin_installer_observer.h"
diff --git a/chrome/browser/plugins/plugin_installer.cc b/chrome/browser/plugins/plugin_installer.cc
index 6cc1b39..bd68407 100644
--- a/chrome/browser/plugins/plugin_installer.cc
+++ b/chrome/browser/plugins/plugin_installer.cc
@@ -23,6 +23,7 @@
 #include "content/public/browser/resource_context.h"
 #include "content/public/browser/resource_dispatcher_host.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/common/referrer.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_context.h"
 
@@ -46,6 +47,7 @@
       resource_context->GetRequestContext()->CreateRequest(url, NULL));
   net::Error error = rdh->BeginDownload(
       request.Pass(),
+      content::Referrer(),
       false,  // is_content_initiated
       resource_context,
       render_process_host_id,
diff --git a/chrome/browser/plugins/plugin_installer.h b/chrome/browser/plugins/plugin_installer.h
index 196007e..36a4261 100644
--- a/chrome/browser/plugins/plugin_installer.h
+++ b/chrome/browser/plugins/plugin_installer.h
@@ -10,8 +10,8 @@
 #include "base/version.h"
 #include "chrome/browser/plugins/plugin_metadata.h"
 #include "content/public/browser/download_item.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/net_errors.h"
+#include "url/gurl.h"
 
 class PluginInstallerObserver;
 class WeakPluginInstallerObserver;
diff --git a/chrome/browser/plugins/plugin_metadata.h b/chrome/browser/plugins/plugin_metadata.h
index b457e6a..69019a7 100644
--- a/chrome/browser/plugins/plugin_metadata.h
+++ b/chrome/browser/plugins/plugin_metadata.h
@@ -10,7 +10,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/string16.h"
 #include "base/version.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 namespace webkit {
 struct WebPluginInfo;
diff --git a/chrome/browser/plugins/plugins_resource_service.cc b/chrome/browser/plugins/plugins_resource_service.cc
index 348ad13..e8ce1ab 100644
--- a/chrome/browser/plugins/plugins_resource_service.cc
+++ b/chrome/browser/plugins/plugins_resource_service.cc
@@ -10,7 +10,7 @@
 #include "chrome/browser/plugins/plugin_finder.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 namespace {
 
diff --git a/chrome/browser/policy/async_policy_loader.h b/chrome/browser/policy/async_policy_loader.h
index bd787bf..ce7b05b 100644
--- a/chrome/browser/policy/async_policy_loader.h
+++ b/chrome/browser/policy/async_policy_loader.h
@@ -11,7 +11,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/policy/policy_service.h"
 
 namespace policy {
diff --git a/chrome/browser/policy/browser_policy_connector.cc b/chrome/browser/policy/browser_policy_connector.cc
index 2e16c0e..18ad7af 100644
--- a/chrome/browser/policy/browser_policy_connector.cc
+++ b/chrome/browser/policy/browser_policy_connector.cc
@@ -207,6 +207,22 @@
           base::MessageLoop::current()->message_loop_proxy()));
   policy_statistics_collector_->Initialize();
 
+#if defined(OS_CHROMEOS)
+  if (command_line->HasSwitch(
+          chromeos::switches::kUseNewNetworkConfigurationHandlers)) {
+    network_configuration_updater_.reset(
+        new NetworkConfigurationUpdaterImpl(
+            GetPolicyService(),
+            make_scoped_ptr(new chromeos::CertificateHandler)));
+  } else {
+    network_configuration_updater_.reset(
+        new NetworkConfigurationUpdaterImplCros(
+            GetPolicyService(),
+            chromeos::CrosLibrary::Get()->GetNetworkLibrary(),
+            make_scoped_ptr(new chromeos::CertificateHandler)));
+  }
+#endif
+
   is_initialized_ = true;
 }
 
@@ -332,30 +348,9 @@
   return app_pack_updater_.get();
 }
 
-NetworkConfigurationUpdater*
-    BrowserPolicyConnector::GetNetworkConfigurationUpdater() {
-  if (!network_configuration_updater_) {
-    CommandLine* command_line = CommandLine::ForCurrentProcess();
-    if (command_line->HasSwitch(
-            chromeos::switches::kUseNewNetworkConfigurationHandlers)) {
-      network_configuration_updater_.reset(
-          new NetworkConfigurationUpdaterImpl(
-              GetPolicyService(),
-              make_scoped_ptr(new chromeos::CertificateHandler)));
-    } else {
-      network_configuration_updater_.reset(
-          new NetworkConfigurationUpdaterImplCros(
-              GetPolicyService(),
-              chromeos::CrosLibrary::Get()->GetNetworkLibrary(),
-              make_scoped_ptr(new chromeos::CertificateHandler)));
-    }
-  }
-  return network_configuration_updater_.get();
-}
-
 net::CertTrustAnchorProvider*
-    BrowserPolicyConnector::GetCertTrustAnchorProvider() {
-  return GetNetworkConfigurationUpdater()->GetCertTrustAnchorProvider();
+BrowserPolicyConnector::GetCertTrustAnchorProvider() {
+  return network_configuration_updater()->GetCertTrustAnchorProvider();
 }
 
 void BrowserPolicyConnector::SetUserPolicyDelegate(
diff --git a/chrome/browser/policy/browser_policy_connector.h b/chrome/browser/policy/browser_policy_connector.h
index 0f6a2c1..1c067b4 100644
--- a/chrome/browser/policy/browser_policy_connector.h
+++ b/chrome/browser/policy/browser_policy_connector.h
@@ -111,7 +111,9 @@
 #if defined(OS_CHROMEOS)
   AppPackUpdater* GetAppPackUpdater();
 
-  NetworkConfigurationUpdater* GetNetworkConfigurationUpdater();
+  NetworkConfigurationUpdater* network_configuration_updater() {
+    return network_configuration_updater_.get();
+  }
 
   net::CertTrustAnchorProvider* GetCertTrustAnchorProvider();
 
diff --git a/chrome/browser/policy/cloud/cloud_policy_browsertest.cc b/chrome/browser/policy/cloud/cloud_policy_browsertest.cc
index 9f6e7f4..0327d98 100644
--- a/chrome/browser/policy/cloud/cloud_policy_browsertest.cc
+++ b/chrome/browser/policy/cloud/cloud_policy_browsertest.cc
@@ -31,12 +31,12 @@
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_source.h"
 #include "content/public/test/test_utils.h"
-#include "googleurl/src/gurl.h"
 #include "policy/policy_constants.h"
 #include "policy/proto/chrome_settings.pb.h"
 #include "policy/proto/cloud_policy.pb.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/login/user_manager.h"
diff --git a/chrome/browser/policy/cloud/cloud_policy_client.h b/chrome/browser/policy/cloud/cloud_policy_client.h
index 010fe69..f30fcc1 100644
--- a/chrome/browser/policy/cloud/cloud_policy_client.h
+++ b/chrome/browser/policy/cloud/cloud_policy_client.h
@@ -13,7 +13,7 @@
 #include "base/callback.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/observer_list.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/policy/cloud/cloud_policy_constants.h"
 #include "chrome/browser/policy/proto/cloud/device_management_backend.pb.h"
 
diff --git a/chrome/browser/policy/cloud/cloud_policy_client_registration_helper.cc b/chrome/browser/policy/cloud/cloud_policy_client_registration_helper.cc
new file mode 100644
index 0000000..7f0b36e
--- /dev/null
+++ b/chrome/browser/policy/cloud/cloud_policy_client_registration_helper.cc
@@ -0,0 +1,167 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/policy/cloud/cloud_policy_client_registration_helper.h"
+
+#include <vector>
+
+#include "base/logging.h"
+#include "base/time/time.h"
+#include "base/values.h"
+#include "google_apis/gaia/gaia_constants.h"
+#include "google_apis/gaia/gaia_urls.h"
+#include "google_apis/gaia/google_service_auth_error.h"
+#include "google_apis/gaia/oauth2_access_token_fetcher.h"
+
+namespace policy {
+
+namespace {
+
+// OAuth2 scope for the userinfo service.
+const char kServiceScopeGetUserInfo[] =
+    "https://www.googleapis.com/auth/userinfo.email";
+
+// The key under which the hosted-domain value is stored in the UserInfo
+// response.
+const char kGetHostedDomainKey[] = "hd";
+
+}  // namespace
+
+CloudPolicyClientRegistrationHelper::CloudPolicyClientRegistrationHelper(
+    net::URLRequestContextGetter* context,
+    CloudPolicyClient* client,
+    bool should_force_load_policy,
+    enterprise_management::DeviceRegisterRequest::Type registration_type)
+    : context_(context),
+      client_(client),
+      should_force_load_policy_(should_force_load_policy),
+      registration_type_(registration_type) {
+  DCHECK(context_);
+  DCHECK(client_);
+}
+
+CloudPolicyClientRegistrationHelper::~CloudPolicyClientRegistrationHelper() {
+  // Clean up any pending observers in case the browser is shutdown while
+  // trying to register for policy.
+  if (client_)
+    client_->RemoveObserver(this);
+}
+
+void CloudPolicyClientRegistrationHelper::StartRegistrationWithLoginToken(
+    const std::string& login_refresh_token,
+    const base::Closure& callback) {
+  DVLOG(1) << "Starting registration process with login token";
+  DCHECK(!client_->is_registered());
+  callback_ = callback;
+  client_->AddObserver(this);
+
+  // Start fetching an OAuth2 access token for the device management and
+  // userinfo services.
+  oauth2_access_token_fetcher_.reset(
+      new OAuth2AccessTokenFetcher(this, context_));
+  std::vector<std::string> scopes;
+  scopes.push_back(GaiaConstants::kDeviceManagementServiceOAuth);
+  scopes.push_back(kServiceScopeGetUserInfo);
+  GaiaUrls* gaia_urls = GaiaUrls::GetInstance();
+  oauth2_access_token_fetcher_->Start(
+      gaia_urls->oauth2_chrome_client_id(),
+      gaia_urls->oauth2_chrome_client_secret(),
+      login_refresh_token,
+      scopes);
+}
+
+void CloudPolicyClientRegistrationHelper::StartRegistrationWithServicesToken(
+    const std::string& services_token,
+    const base::Closure& callback) {
+  DVLOG(1) << "Starting registration process with services token";
+  DCHECK(!client_->is_registered());
+  callback_ = callback;
+  client_->AddObserver(this);
+  OnGetTokenSuccess(services_token, base::Time());
+}
+
+void CloudPolicyClientRegistrationHelper::OnGetTokenFailure(
+    const GoogleServiceAuthError& error) {
+  DLOG(WARNING) << "Could not fetch access token for "
+                << GaiaConstants::kDeviceManagementServiceOAuth;
+  oauth2_access_token_fetcher_.reset();
+
+  // Invoke the callback to let them know the fetch failed.
+  RequestCompleted();
+}
+
+void CloudPolicyClientRegistrationHelper::OnGetTokenSuccess(
+    const std::string& access_token,
+    const base::Time& expiration_time) {
+  // Cache the access token to be used after the GetUserInfo call.
+  oauth_access_token_ = access_token;
+  DVLOG(1) << "Fetched new scoped OAuth token:" << oauth_access_token_;
+  oauth2_access_token_fetcher_.reset();
+  // Now we've gotten our access token - contact GAIA to see if this is a
+  // hosted domain.
+  user_info_fetcher_.reset(new UserInfoFetcher(this, context_));
+  user_info_fetcher_->Start(oauth_access_token_);
+}
+
+void CloudPolicyClientRegistrationHelper::OnGetUserInfoFailure(
+    const GoogleServiceAuthError& error) {
+  DVLOG(1) << "Failed to fetch user info from GAIA: " << error.state();
+  user_info_fetcher_.reset();
+  RequestCompleted();
+}
+
+void CloudPolicyClientRegistrationHelper::OnGetUserInfoSuccess(
+    const base::DictionaryValue* data) {
+  user_info_fetcher_.reset();
+  if (!data->HasKey(kGetHostedDomainKey) && !should_force_load_policy_) {
+    DVLOG(1) << "User not from a hosted domain - skipping registration";
+    RequestCompleted();
+    return;
+  }
+  DVLOG(1) << "Registering CloudPolicyClient for user from hosted domain";
+  // The user is from a hosted domain, so it's OK to register the
+  // CloudPolicyClient and make requests to DMServer.
+  if (client_->is_registered()) {
+    // Client should not be registered yet.
+    NOTREACHED();
+    RequestCompleted();
+    return;
+  }
+
+  // Kick off registration of the CloudPolicyClient with our newly minted
+  // oauth_access_token_.
+  client_->Register(registration_type_, oauth_access_token_,
+                    std::string(), false, std::string());
+}
+
+void CloudPolicyClientRegistrationHelper::OnPolicyFetched(
+    CloudPolicyClient* client) {
+  // Ignored.
+}
+
+void CloudPolicyClientRegistrationHelper::OnRegistrationStateChanged(
+    CloudPolicyClient* client) {
+  DVLOG(1) << "Client registration succeeded";
+  DCHECK_EQ(client, client_);
+  DCHECK(client->is_registered());
+  RequestCompleted();
+}
+
+void CloudPolicyClientRegistrationHelper::OnClientError(
+    CloudPolicyClient* client) {
+  DVLOG(1) << "Client registration failed";
+  DCHECK_EQ(client, client_);
+  RequestCompleted();
+}
+
+void CloudPolicyClientRegistrationHelper::RequestCompleted() {
+  if (client_) {
+    client_->RemoveObserver(this);
+    // |client_| may be freed by the callback so clear it now.
+    client_ = NULL;
+    callback_.Run();
+  }
+}
+
+}  // namespace policy
diff --git a/chrome/browser/policy/cloud/cloud_policy_client_registration_helper.h b/chrome/browser/policy/cloud/cloud_policy_client_registration_helper.h
new file mode 100644
index 0000000..4dc3568
--- /dev/null
+++ b/chrome/browser/policy/cloud/cloud_policy_client_registration_helper.h
@@ -0,0 +1,98 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_POLICY_CLOUD_CLOUD_POLICY_CLIENT_REGISTRATION_HELPER_H_
+#define CHROME_BROWSER_POLICY_CLOUD_CLOUD_POLICY_CLIENT_REGISTRATION_HELPER_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/compiler_specific.h"
+#include "chrome/browser/policy/cloud/cloud_policy_client.h"
+#include "chrome/browser/policy/cloud/user_info_fetcher.h"
+#include "chrome/browser/policy/proto/cloud/device_management_backend.pb.h"
+#include "google_apis/gaia/oauth2_access_token_consumer.h"
+
+class OAuth2AccessTokenFetcher;
+
+namespace net {
+class URLRequestContextGetter;
+}
+
+namespace policy {
+
+// Helper class that registers a CloudPolicyClient. It fetches an OAuth2 token
+// for the DM service if needed, and checks with Gaia if the account has policy
+// management enabled.
+class CloudPolicyClientRegistrationHelper : public OAuth2AccessTokenConsumer,
+                                            public UserInfoFetcher::Delegate,
+                                            public CloudPolicyClient::Observer {
+ public:
+  // |context| and |client| are not owned and must outlive this object.
+  // If |should_force_load_policy| then the cloud policy registration is
+  // performed even if Gaia indicates that this account doesn't have management
+  // enabled.
+  CloudPolicyClientRegistrationHelper(
+      net::URLRequestContextGetter* context,
+      CloudPolicyClient* client,
+      bool should_force_load_policy,
+      enterprise_management::DeviceRegisterRequest::Type registration_type);
+  virtual ~CloudPolicyClientRegistrationHelper();
+
+  // Starts the client registration process. The |login_refresh_token| is used
+  // to mint a new token for the userinfo and DM services.
+  // |callback| is invoked when the registration is complete.
+  void StartRegistrationWithLoginToken(const std::string& login_refresh_token,
+                                       const base::Closure& callback);
+
+  // Starts the client registration process. The |services_token| is an OAuth2
+  // token scoped for the userinfo and DM services.
+  // |callback| is invoked when the registration is complete.
+  void StartRegistrationWithServicesToken(const std::string& services_token,
+                                          const base::Closure& callback);
+
+ private:
+  // OAuth2AccessTokenConsumer implementation:
+  virtual void OnGetTokenSuccess(const std::string& access_token,
+                                 const base::Time& expiration_time) OVERRIDE;
+  virtual void OnGetTokenFailure(const GoogleServiceAuthError& error) OVERRIDE;
+
+  // UserInfoFetcher::Delegate implementation:
+  virtual void OnGetUserInfoSuccess(
+      const base::DictionaryValue* response) OVERRIDE;
+  virtual void OnGetUserInfoFailure(
+      const GoogleServiceAuthError& error) OVERRIDE;
+
+  // CloudPolicyClient::Observer implementation:
+  virtual void OnPolicyFetched(CloudPolicyClient* client) OVERRIDE;
+  virtual void OnRegistrationStateChanged(CloudPolicyClient* client) OVERRIDE;
+  virtual void OnClientError(CloudPolicyClient* client) OVERRIDE;
+
+  // Invoked when the registration request has been completed.
+  void RequestCompleted();
+
+  // Fetcher used while obtaining an OAuth token for client registration.
+  scoped_ptr<OAuth2AccessTokenFetcher> oauth2_access_token_fetcher_;
+
+  // Helper class for fetching information from GAIA about the currently
+  // signed-in user.
+  scoped_ptr<UserInfoFetcher> user_info_fetcher_;
+
+  // Access token used to register the CloudPolicyClient and also access
+  // GAIA to get information about the signed in user.
+  std::string oauth_access_token_;
+
+  net::URLRequestContextGetter* context_;
+  CloudPolicyClient* client_;
+  bool should_force_load_policy_;
+  enterprise_management::DeviceRegisterRequest::Type registration_type_;
+  base::Closure callback_;
+
+  DISALLOW_COPY_AND_ASSIGN(CloudPolicyClientRegistrationHelper);
+};
+
+}  // namespace policy
+
+#endif  // CHROME_BROWSER_POLICY_CLOUD_CLOUD_POLICY_CLIENT_REGISTRATION_HELPER_H_
diff --git a/chrome/browser/policy/cloud/cloud_policy_constants.cc b/chrome/browser/policy/cloud/cloud_policy_constants.cc
index 865c3c6..905ddab 100644
--- a/chrome/browser/policy/cloud/cloud_policy_constants.cc
+++ b/chrome/browser/policy/cloud/cloud_policy_constants.cc
@@ -32,6 +32,8 @@
 const char kValueUserAffiliationNone[] = "none";
 
 const char kChromeDevicePolicyType[] = "google/chromeos/device";
+// TODO(joaodasilva): add a new constant for Android here.
+// http://crbug.com/248527
 #if defined(OS_CHROMEOS)
 const char kChromeUserPolicyType[] = "google/chromeos/user";
 #else
diff --git a/chrome/browser/policy/cloud/cloud_policy_refresh_scheduler.h b/chrome/browser/policy/cloud/cloud_policy_refresh_scheduler.h
index 3c8da4d..c58580a 100644
--- a/chrome/browser/policy/cloud/cloud_policy_refresh_scheduler.h
+++ b/chrome/browser/policy/cloud/cloud_policy_refresh_scheduler.h
@@ -8,7 +8,7 @@
 #include "base/basictypes.h"
 #include "base/cancelable_callback.h"
 #include "base/memory/ref_counted.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/policy/cloud/cloud_policy_client.h"
 #include "chrome/browser/policy/cloud/cloud_policy_store.h"
 #include "chrome/browser/policy/cloud/rate_limiter.h"
diff --git a/chrome/browser/policy/cloud/cloud_policy_validator.h b/chrome/browser/policy/cloud/cloud_policy_validator.h
index 1a41840..d53a0c6 100644
--- a/chrome/browser/policy/cloud/cloud_policy_validator.h
+++ b/chrome/browser/policy/cloud/cloud_policy_validator.h
@@ -13,7 +13,7 @@
 #include "base/callback.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/policy/proto/cloud/chrome_extension_policy.pb.h"
 #include "policy/proto/cloud_policy.pb.h"
 
diff --git a/chrome/browser/policy/cloud/component_cloud_policy_service_unittest.cc b/chrome/browser/policy/cloud/component_cloud_policy_service_unittest.cc
index d4e54d6..1a229c5 100644
--- a/chrome/browser/policy/cloud/component_cloud_policy_service_unittest.cc
+++ b/chrome/browser/policy/cloud/component_cloud_policy_service_unittest.cc
@@ -106,7 +106,6 @@
   virtual void SetUp() OVERRIDE {
     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
     cache_ = new ResourceCache(temp_dir_.path());
-    ASSERT_TRUE(cache_->IsOpen());
     service_.reset(new ComponentCloudPolicyService(
         &delegate_, &store_, make_scoped_ptr(cache_)));
 
diff --git a/chrome/browser/policy/cloud/component_cloud_policy_store.cc b/chrome/browser/policy/cloud/component_cloud_policy_store.cc
index 57b7b2d..afd627a 100644
--- a/chrome/browser/policy/cloud/component_cloud_policy_store.cc
+++ b/chrome/browser/policy/cloud/component_cloud_policy_store.cc
@@ -15,7 +15,7 @@
 #include "chrome/browser/policy/policy_map.h"
 #include "chrome/browser/policy/proto/cloud/chrome_extension_policy.pb.h"
 #include "chrome/browser/policy/proto/cloud/device_management_backend.pb.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 namespace em = enterprise_management;
 
diff --git a/chrome/browser/policy/cloud/component_cloud_policy_updater_unittest.cc b/chrome/browser/policy/cloud/component_cloud_policy_updater_unittest.cc
index 6cdecb9..11a73b5 100644
--- a/chrome/browser/policy/cloud/component_cloud_policy_updater_unittest.cc
+++ b/chrome/browser/policy/cloud/component_cloud_policy_updater_unittest.cc
@@ -21,12 +21,12 @@
 #include "chrome/browser/policy/policy_types.h"
 #include "chrome/browser/policy/proto/cloud/chrome_extension_policy.pb.h"
 #include "chrome/browser/policy/proto/cloud/device_management_backend.pb.h"
-#include "googleurl/src/gurl.h"
 #include "net/url_request/test_url_fetcher_factory.h"
 #include "net/url_request/url_fetcher_delegate.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 namespace em = enterprise_management;
 
diff --git a/chrome/browser/policy/cloud/device_management_service.cc b/chrome/browser/policy/cloud/device_management_service.cc
index 2a781b6..2892488 100644
--- a/chrome/browser/policy/cloud/device_management_service.cc
+++ b/chrome/browser/policy/cloud/device_management_service.cc
@@ -18,7 +18,6 @@
 #include "chrome/common/chrome_version_info.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/common/content_client.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/escape.h"
 #include "net/base/load_flags.h"
 #include "net/base/net_errors.h"
@@ -32,6 +31,7 @@
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "net/url_request/url_request_status.h"
+#include "url/gurl.h"
 
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/system/statistics_provider.h"
diff --git a/chrome/browser/policy/cloud/external_policy_data_updater.cc b/chrome/browser/policy/cloud/external_policy_data_updater.cc
index c5675a8..fcac402 100644
--- a/chrome/browser/policy/cloud/external_policy_data_updater.cc
+++ b/chrome/browser/policy/cloud/external_policy_data_updater.cc
@@ -13,7 +13,6 @@
 #include "base/sequenced_task_runner.h"
 #include "base/sha1.h"
 #include "base/stl_util.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/backoff_entry.h"
 #include "net/base/load_flags.h"
 #include "net/base/net_errors.h"
@@ -21,6 +20,7 @@
 #include "net/url_request/url_fetcher_delegate.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "net/url_request/url_request_status.h"
+#include "url/gurl.h"
 
 namespace policy {
 
diff --git a/chrome/browser/policy/cloud/external_policy_data_updater_unittest.cc b/chrome/browser/policy/cloud/external_policy_data_updater_unittest.cc
index a07a088..57325f8 100644
--- a/chrome/browser/policy/cloud/external_policy_data_updater_unittest.cc
+++ b/chrome/browser/policy/cloud/external_policy_data_updater_unittest.cc
@@ -12,8 +12,7 @@
 #include "base/sha1.h"
 #include "base/test/test_pending_task.h"
 #include "base/test/test_simple_task_runner.h"
-#include "base/time.h"
-#include "googleurl/src/gurl.h"
+#include "base/time/time.h"
 #include "net/base/net_errors.h"
 #include "net/url_request/test_url_fetcher_factory.h"
 #include "net/url_request/url_fetcher_delegate.h"
@@ -21,6 +20,7 @@
 #include "net/url_request/url_request_status.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 using testing::Mock;
 using testing::Return;
diff --git a/chrome/browser/policy/cloud/policy_builder.cc b/chrome/browser/policy/cloud/policy_builder.cc
index 67d94d1..94ff451 100644
--- a/chrome/browser/policy/cloud/policy_builder.cc
+++ b/chrome/browser/policy/cloud/policy_builder.cc
@@ -95,6 +95,7 @@
 const int64 PolicyBuilder::kFakeTimestamp = 365LL * 24 * 60 * 60 * 1000;
 const char PolicyBuilder::kFakeToken[] = "token";
 const char PolicyBuilder::kFakeUsername[] = "username@example.com";
+const char PolicyBuilder::kFakeServiceAccountIdentity[] = "robot4test@g.com";
 
 PolicyBuilder::PolicyBuilder()
     : policy_data_(new em::PolicyData()),
@@ -107,6 +108,7 @@
   policy_data_->set_username(kFakeUsername);
   policy_data_->set_device_id(kFakeDeviceId);
   policy_data_->set_state(em::PolicyData::ACTIVE);
+  policy_data_->set_service_account_identity(kFakeServiceAccountIdentity);
 }
 
 PolicyBuilder::~PolicyBuilder() {}
diff --git a/chrome/browser/policy/cloud/policy_builder.h b/chrome/browser/policy/cloud/policy_builder.h
index 628483a..2daac43 100644
--- a/chrome/browser/policy/cloud/policy_builder.h
+++ b/chrome/browser/policy/cloud/policy_builder.h
@@ -35,6 +35,7 @@
   static const int64 kFakeTimestamp;
   static const char kFakeToken[];
   static const char kFakeUsername[];
+  static const char kFakeServiceAccountIdentity[];
 
   // Creates a policy builder. The builder will have all PolicyData fields
   // initialized to dummy values and use the test signing keys.
diff --git a/chrome/browser/policy/cloud/rate_limiter.h b/chrome/browser/policy/cloud/rate_limiter.h
index f532a29..00af48d 100644
--- a/chrome/browser/policy/cloud/rate_limiter.h
+++ b/chrome/browser/policy/cloud/rate_limiter.h
@@ -13,7 +13,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/threading/non_thread_safe.h"
-#include "base/time.h"
+#include "base/time/time.h"
 
 namespace base {
 class SequencedTaskRunner;
diff --git a/chrome/browser/policy/cloud/resource_cache.cc b/chrome/browser/policy/cloud/resource_cache.cc
index 74323ce..2214a2e 100644
--- a/chrome/browser/policy/cloud/resource_cache.cc
+++ b/chrome/browser/policy/cloud/resource_cache.cc
@@ -4,46 +4,43 @@
 
 #include "chrome/browser/policy/cloud/resource_cache.h"
 
-#include <string.h>
-
+#include "base/base64.h"
 #include "base/file_util.h"
-#include "base/files/file_path.h"
+#include "base/files/file_enumerator.h"
 #include "base/logging.h"
-#include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
-#include "base/threading/thread_restrictions.h"
-#include "third_party/leveldatabase/src/include/leveldb/db.h"
-#include "third_party/leveldatabase/src/include/leveldb/iterator.h"
-#include "third_party/leveldatabase/src/include/leveldb/options.h"
-#include "third_party/leveldatabase/src/include/leveldb/slice.h"
-#include "third_party/leveldatabase/src/include/leveldb/status.h"
-#include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
 
 namespace policy {
 
-ResourceCache::ResourceCache(const base::FilePath& cache_path) {
-  // Allow the cache to be created in a different thread than the thread that's
+namespace {
+
+// Verifies that |value| is not empty and encodes it into base64url format,
+// which is safe to use as a file name on all platforms.
+bool Base64Encode(const std::string& value, std::string* encoded) {
+  DCHECK(!value.empty());
+  if (value.empty() || !base::Base64Encode(value, encoded))
+    return false;
+  ReplaceChars(*encoded, "+", "-", encoded);
+  ReplaceChars(*encoded, "/", "_", encoded);
+  return true;
+}
+
+// Decodes |encoded| from base64url format and verifies that the result is not
+// emtpy.
+bool Base64Decode(const std::string& encoded, std::string* value) {
+  std::string buffer;
+  ReplaceChars(encoded, "-", "+", &buffer);
+  ReplaceChars(buffer, "_", "/", &buffer);
+  return base::Base64Decode(buffer, value) && !value->empty();
+}
+
+}  // namespace
+
+ResourceCache::ResourceCache(const base::FilePath& cache_dir)
+    : cache_dir_(cache_dir) {
+  // Allow the cache to be created in a different thread than the thread that is
   // going to use it.
   DetachFromThread();
-
-  file_util::CreateDirectory(cache_path.DirName());
-  leveldb::Options options;
-  options.create_if_missing = true;
-  leveldb::DB* db = NULL;
-  leveldb::Status status =
-      leveldb::DB::Open(options, cache_path.AsUTF8Unsafe(), &db);
-  if (!status.ok()) {
-    LOG(WARNING) << "Failed to open leveldb at " << cache_path.AsUTF8Unsafe()
-                 << ": " << status.ToString();
-    // Maybe the database is busted; drop everything and try to create it again.
-    file_util::Delete(cache_path, true);
-    status = leveldb::DB::Open(options, cache_path.AsUTF8Unsafe(), &db);
-
-    if (!status.ok())
-      LOG(WARNING) << "Failed to open a new leveldb after wiping: "
-                   << status.ToString();
-  }
-  db_.reset(db);
 }
 
 ResourceCache::~ResourceCache() {
@@ -54,135 +51,125 @@
                           const std::string& subkey,
                           const std::string& data) {
   DCHECK(CalledOnValidThread());
-  base::ThreadRestrictions::AssertIOAllowed();
-
-  if (!IsOpen())
-    return false;
-
-  std::string path(CreatePath(key, subkey));
-  return db_->Put(leveldb::WriteOptions(), path, data).ok();
+  base::FilePath subkey_path;
+  // Delete the file before writing to it. This ensures that the write does not
+  // follow a symlink planted at |subkey_path|, clobbering a file outside the
+  // cache directory. The mechanism is meant to foil file-system-level attacks
+  // where a symlink is planted in the cache directory before Chrome has
+  // started. An attacker controlling a process running concurrently with Chrome
+  // would be able to race against the protection by re-creating the symlink
+  // between these two calls. There is nothing in file_util that could be used
+  // to protect against such races, especially as the cache is cross-platform
+  // and therefore cannot use any POSIX-only tricks.
+  return VerifyKeyPathAndGetSubkeyPath(key, true, subkey, &subkey_path) &&
+         base::Delete(subkey_path, false) &&
+         file_util::WriteFile(subkey_path, data.data(), data.size());
 }
 
 bool ResourceCache::Load(const std::string& key,
                          const std::string& subkey,
                          std::string* data) {
   DCHECK(CalledOnValidThread());
-  base::ThreadRestrictions::AssertIOAllowed();
-  if (!IsOpen())
+  base::FilePath subkey_path;
+  // Only read from |subkey_path| if it is not a symlink.
+  if (!VerifyKeyPathAndGetSubkeyPath(key, false, subkey, &subkey_path) ||
+      file_util::IsLink(subkey_path)) {
     return false;
-
-  leveldb::ReadOptions options;
-  options.fill_cache = false;
-  std::string path(CreatePath(key, subkey));
-  return db_->Get(options, path, data).ok();
+  }
+  data->clear();
+  return file_util::ReadFileToString(subkey_path, data);
 }
 
 void ResourceCache::LoadAllSubkeys(
     const std::string& key,
     std::map<std::string, std::string>* contents) {
   DCHECK(CalledOnValidThread());
-  base::ThreadRestrictions::AssertIOAllowed();
-  if (!IsOpen())
+  contents->clear();
+  base::FilePath key_path;
+  if (!VerifyKeyPath(key, false, &key_path))
     return;
 
-  contents->clear();
-
-  const std::string prefix(CreatePathPrefix(key));
-  leveldb::ReadOptions options;
-  options.fill_cache = false;
-  scoped_ptr<leveldb::Iterator> it(db_->NewIterator(options));
-  for (it->Seek(prefix); it->Valid(); it->Next()) {
-    if (!it->key().starts_with(prefix))
-      break;
-    const std::string subkey(GetSubkey(it->key().ToString()));
-    leveldb::Slice slice = it->value();
-    (*contents)[subkey].assign(slice.data(), slice.size());
+  base::FileEnumerator enumerator(key_path, false, base::FileEnumerator::FILES);
+  for (base::FilePath path = enumerator.Next(); !path.empty();
+       path = enumerator.Next()) {
+    const std::string encoded_subkey = path.BaseName().MaybeAsASCII();
+    std::string subkey;
+    std::string data;
+    // Only read from |subkey_path| if it is not a symlink and its name is
+    // a base64-encoded string.
+    if (!file_util::IsLink(path) &&
+        Base64Decode(encoded_subkey, &subkey) &&
+        file_util::ReadFileToString(path, &data)) {
+      (*contents)[subkey].swap(data);
+    }
   }
 }
 
 void ResourceCache::Delete(const std::string& key, const std::string& subkey) {
   DCHECK(CalledOnValidThread());
-  base::ThreadRestrictions::AssertIOAllowed();
-  if (!IsOpen())
-    return;
-
-  const std::string path(CreatePath(key, subkey));
-  leveldb::Status status = db_->Delete(leveldb::WriteOptions(), path);
-  if (!status.ok()) {
-    LOG(WARNING) << "Failed to Delete \"" << path << "\" from leveldb: "
-                 << status.ToString();
-  }
+  base::FilePath subkey_path;
+  if (VerifyKeyPathAndGetSubkeyPath(key, false, subkey, &subkey_path))
+    base::Delete(subkey_path, false);
+  // Delete() does nothing if the directory given to it is not empty. Hence, the
+  // call below deletes the directory representing |key| if its last subkey was
+  // just removed and does nothing otherwise.
+  base::Delete(subkey_path.DirName(), false);
 }
 
 void ResourceCache::PurgeOtherSubkeys(
     const std::string& key,
     const std::set<std::string>& subkeys_to_keep) {
   DCHECK(CalledOnValidThread());
-  base::ThreadRestrictions::AssertIOAllowed();
-  if (!IsOpen())
+  base::FilePath key_path;
+  if (!VerifyKeyPath(key, false, &key_path))
     return;
 
-  leveldb::WriteBatch batch;
-  const std::string prefix(CreatePathPrefix(key));
-  leveldb::ReadOptions options;
-  options.fill_cache = false;
-  scoped_ptr<leveldb::Iterator> it(db_->NewIterator(options));
-  for (it->Seek(prefix); it->Valid(); it->Next()) {
-    if (!it->key().starts_with(prefix))
-      break;
-    const std::string subkey(GetSubkey(it->key().ToString()));
-    if (subkeys_to_keep.find(subkey) == subkeys_to_keep.end())
-      batch.Delete(it->key());
+  std::set<std::string> encoded_subkeys_to_keep;
+  for (std::set<std::string>::const_iterator it = subkeys_to_keep.begin();
+       it != subkeys_to_keep.end(); ++it) {
+    std::string encoded;
+    if (!Base64Encode(*it, &encoded))
+      return;
+    encoded_subkeys_to_keep.insert(encoded);
   }
 
-  leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch);
-  if (!status.ok()) {
-    LOG(WARNING) << "Purge of leveldb subkeys of " << key << " failed: "
-                 << status.ToString();
+  base::FileEnumerator enumerator(key_path, false, base::FileEnumerator::FILES);
+  for (base::FilePath path = enumerator.Next(); !path.empty();
+       path = enumerator.Next()) {
+    const std::string name(path.BaseName().MaybeAsASCII());
+    if (encoded_subkeys_to_keep.find(name) == encoded_subkeys_to_keep.end())
+      base::Delete(path, false);
   }
+  // Delete() does nothing if the directory given to it is not empty. Hence, the
+  // call below deletes the directory representing |key| if all of its subkeys
+  // were just removed and does nothing otherwise.
+  base::Delete(key_path, false);
 }
 
-std::string ResourceCache::GetStringWithPrefix(const std::string& s) {
-  char buffer[sizeof(size_t)];
-  size_t size = s.size();
-  memcpy(buffer, &size, sizeof(size_t));
-  return std::string(buffer, sizeof(size_t)) + s;
+bool ResourceCache::VerifyKeyPath(const std::string& key,
+                                  bool allow_create,
+                                  base::FilePath* path) {
+  std::string encoded;
+  if (!Base64Encode(key, &encoded))
+    return false;
+  *path = cache_dir_.AppendASCII(encoded);
+  return allow_create ? file_util::CreateDirectory(*path) :
+                        file_util::DirectoryExists(*path);
 }
 
-std::string ResourceCache::CreatePathPrefix(const std::string& key) {
-  return GetStringWithPrefix(key);
-}
-
-std::string ResourceCache::CreatePath(const std::string& key,
-                                      const std::string& subkey) {
-  return GetStringWithPrefix(key) + GetStringWithPrefix(subkey);
-}
-
-std::string ResourceCache::GetSubkey(const std::string& path) {
-  // |path| was produced by CreatePath(). Skip the first key, then skip the
-  // size of the subkey.
-  if (path.size() < sizeof(size_t)) {
-    NOTREACHED();
-    return EmptyString();
+bool ResourceCache::VerifyKeyPathAndGetSubkeyPath(const std::string& key,
+                                                  bool allow_create_key,
+                                                  const std::string& subkey,
+                                                  base::FilePath* path) {
+  base::FilePath key_path;
+  std::string encoded;
+  if (!VerifyKeyPath(key, allow_create_key, &key_path) ||
+      !Base64Encode(subkey, &encoded)) {
+    return false;
   }
-
-  // Skip the first string. |offset| is the start of the second string,
-  // immediately preceded by its size.
-  const size_t* size = reinterpret_cast<const size_t*>(path.data());
-  size_t offset = sizeof(size_t) + *size + sizeof(size_t);
-  if (path.size() < offset) {
-    NOTREACHED();
-    return EmptyString();
-  }
-
-  // Skip the size of the second string.
-  size = reinterpret_cast<const size_t*>(path.data() + offset - sizeof(size_t));
-  if (*size != path.size() - offset) {
-    NOTREACHED();
-    return EmptyString();
-  }
-
-  return path.substr(offset, *size);
+  *path = key_path.AppendASCII(encoded);
+  return true;
 }
 
+
 }  // namespace policy
diff --git a/chrome/browser/policy/cloud/resource_cache.h b/chrome/browser/policy/cloud/resource_cache.h
index 40d3a38..8465e8c 100644
--- a/chrome/browser/policy/cloud/resource_cache.h
+++ b/chrome/browser/policy/cloud/resource_cache.h
@@ -10,17 +10,9 @@
 #include <string>
 
 #include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
+#include "base/files/file_path.h"
 #include "base/threading/non_thread_safe.h"
 
-namespace base {
-class FilePath;
-}
-
-namespace leveldb {
-class DB;
-}
-
 namespace policy {
 
 // Manages storage of data at a given path. The data is keyed by a key and
@@ -32,11 +24,7 @@
 class ResourceCache : public base::NonThreadSafe {
  public:
   explicit ResourceCache(const base::FilePath& cache_path);
-  ~ResourceCache();
-
-  // Returns true if the underlying database was opened, and false otherwise.
-  // When this returns false then all the other operations will fail.
-  bool IsOpen() const { return db_; }
+  virtual ~ResourceCache();
 
   // Stores |data| under (key, subkey). Returns true if the store suceeded, and
   // false otherwise.
@@ -63,12 +51,23 @@
                          const std::set<std::string>& subkeys_to_keep);
 
  private:
-  std::string GetStringWithPrefix(const std::string& s);
-  std::string CreatePathPrefix(const std::string& key);
-  std::string CreatePath(const std::string& key, const std::string& subkey);
-  std::string GetSubkey(const std::string& path);
+  // Points |path| at the cache directory for |key| and returns whether the
+  // directory exists. If |allow_create| is |true|, the directory is created if
+  // it did not exist yet.
+  bool VerifyKeyPath(const std::string& key,
+                     bool allow_create,
+                     base::FilePath* path);
 
-  scoped_ptr<leveldb::DB> db_;
+  // Points |path| at the file in which data for (key, subkey) should be stored
+  // and returns whether the parent directory of this file exists. If
+  // |allow_create_key| is |true|, the directory is created if it did not exist
+  // yet. This method does not check whether the file at |path| exists or not.
+  bool VerifyKeyPathAndGetSubkeyPath(const std::string& key,
+                                     bool allow_create_key,
+                                     const std::string& subkey,
+                                     base::FilePath* subkey_path);
+
+  base::FilePath cache_dir_;
 
   DISALLOW_COPY_AND_ASSIGN(ResourceCache);
 };
diff --git a/chrome/browser/policy/cloud/resource_cache_unittest.cc b/chrome/browser/policy/cloud/resource_cache_unittest.cc
index d006c5c..fc772e6 100644
--- a/chrome/browser/policy/cloud/resource_cache_unittest.cc
+++ b/chrome/browser/policy/cloud/resource_cache_unittest.cc
@@ -28,7 +28,7 @@
 TEST(ResourceCacheTest, StoreAndLoad) {
   base::ScopedTempDir temp_dir;
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-  ResourceCache cache(temp_dir.path().AppendASCII("db"));
+  ResourceCache cache(temp_dir.path());
 
   // No data initially.
   std::string data;
diff --git a/chrome/browser/policy/cloud/test_request_interceptor.cc b/chrome/browser/policy/cloud/test_request_interceptor.cc
index b36b63d..9e254a4 100644
--- a/chrome/browser/policy/cloud/test_request_interceptor.cc
+++ b/chrome/browser/policy/cloud/test_request_interceptor.cc
@@ -13,7 +13,6 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/test/test_utils.h"
 #include "content/test/net/url_request_mock_http_job.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/net_errors.h"
 #include "net/base/upload_bytes_element_reader.h"
 #include "net/base/upload_data_stream.h"
@@ -22,6 +21,7 @@
 #include "net/url_request/url_request_filter.h"
 #include "net/url_request/url_request_job_factory.h"
 #include "net/url_request/url_request_test_job.h"
+#include "url/gurl.h"
 
 namespace em = enterprise_management;
 
diff --git a/chrome/browser/policy/cloud/user_cloud_policy_manager.cc b/chrome/browser/policy/cloud/user_cloud_policy_manager.cc
index 9775b28..edaf8be 100644
--- a/chrome/browser/policy/cloud/user_cloud_policy_manager.cc
+++ b/chrome/browser/policy/cloud/user_cloud_policy_manager.cc
@@ -58,13 +58,4 @@
   return client() && client()->is_registered();
 }
 
-void UserCloudPolicyManager::RegisterClient(const std::string& access_token) {
-  DCHECK(client()) << "Callers must invoke Initialize() first";
-  if (!client()->is_registered()) {
-    DVLOG(1) << "Registering client with access token: " << access_token;
-    client()->Register(em::DeviceRegisterRequest::BROWSER,
-                       access_token, std::string(), false, std::string());
-  }
-}
-
 }  // namespace policy
diff --git a/chrome/browser/policy/cloud/user_cloud_policy_manager.h b/chrome/browser/policy/cloud/user_cloud_policy_manager.h
index ddfdae3..b66be9a 100644
--- a/chrome/browser/policy/cloud/user_cloud_policy_manager.h
+++ b/chrome/browser/policy/cloud/user_cloud_policy_manager.h
@@ -46,10 +46,6 @@
   // Virtual for mocking.
   virtual bool IsClientRegistered() const;
 
-  // Register the CloudPolicyClient using the passed OAuth token. This contacts
-  // the DMServer to mint a new DMToken.
-  void RegisterClient(const std::string& access_token);
-
   // Creates a CloudPolicyClient for this client. Used in situations where
   // callers want to create a DMToken without actually initializing the
   // profile's policy infrastructure.
diff --git a/chrome/browser/policy/cloud/user_cloud_policy_store.cc b/chrome/browser/policy/cloud/user_cloud_policy_store.cc
index cef3adb..1381d98 100644
--- a/chrome/browser/policy/cloud/user_cloud_policy_store.cc
+++ b/chrome/browser/policy/cloud/user_cloud_policy_store.cc
@@ -122,7 +122,7 @@
 void UserCloudPolicyStore::Clear() {
   content::BrowserThread::PostTask(
       content::BrowserThread::FILE, FROM_HERE,
-      base::Bind(base::IgnoreResult(&file_util::Delete),
+      base::Bind(base::IgnoreResult(&base::Delete),
                  backing_file_path_,
                  false));
   policy_.reset();
diff --git a/chrome/browser/policy/cloud/user_info_fetcher.cc b/chrome/browser/policy/cloud/user_info_fetcher.cc
index 4aaed1e..996e442 100644
--- a/chrome/browser/policy/cloud/user_info_fetcher.cc
+++ b/chrome/browser/policy/cloud/user_info_fetcher.cc
@@ -10,11 +10,11 @@
 #include "base/values.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "google_apis/gaia/google_service_auth_error.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/load_flags.h"
 #include "net/http/http_status_code.h"
 #include "net/url_request/url_fetcher.h"
 #include "net/url_request/url_request_status.h"
+#include "url/gurl.h"
 
 namespace {
 
diff --git a/chrome/browser/policy/cloud/user_policy_signin_service.cc b/chrome/browser/policy/cloud/user_policy_signin_service.cc
index 46b60ca..542e458 100644
--- a/chrome/browser/policy/cloud/user_policy_signin_service.cc
+++ b/chrome/browser/policy/cloud/user_policy_signin_service.cc
@@ -4,18 +4,13 @@
 
 #include "chrome/browser/policy/cloud/user_policy_signin_service.h"
 
-#include <vector>
-
-#include "base/command_line.h"
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/callback.h"
 #include "base/prefs/pref_service.h"
-#include "base/values.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/policy/browser_policy_connector.h"
-#include "chrome/browser/policy/cloud/cloud_policy_client.h"
-#include "chrome/browser/policy/cloud/cloud_policy_service.h"
+#include "chrome/browser/policy/cloud/cloud_policy_client_registration_helper.h"
 #include "chrome/browser/policy/cloud/user_cloud_policy_manager.h"
-#include "chrome/browser/policy/cloud/user_cloud_policy_manager_factory.h"
-#include "chrome/browser/policy/cloud/user_info_fetcher.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/signin/signin_manager.h"
@@ -23,285 +18,77 @@
 #include "chrome/browser/signin/token_service.h"
 #include "chrome/browser/signin/token_service_factory.h"
 #include "chrome/common/chrome_notification_types.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "content/public/browser/notification_details.h"
-#include "content/public/browser/notification_source.h"
 #include "google_apis/gaia/gaia_constants.h"
-#include "google_apis/gaia/gaia_urls.h"
-#include "google_apis/gaia/oauth2_access_token_consumer.h"
-#include "google_apis/gaia/oauth2_access_token_fetcher.h"
 
-namespace em = enterprise_management;
-
-namespace {
-
-const char kServiceScopeGetUserInfo[] =
-    "https://www.googleapis.com/auth/userinfo.email";
-
-// The key under which the hosted-domain value is stored in the UserInfo
-// response.
-const char kGetHostedDomainKey[] = "hd";
-
-bool ShouldForceLoadPolicy() {
-  return CommandLine::ForCurrentProcess()->HasSwitch(
-      switches::kForceLoadCloudPolicy);
-}
-
-}  // namespace
+#if defined(ENABLE_MANAGED_USERS)
+#include "chrome/browser/managed_mode/managed_user_service.h"
+#endif
 
 namespace policy {
 
-// Helper class that registers a CloudPolicyClient and returns the associated
-// DMToken to the caller.
-class CloudPolicyClientRegistrationHelper
-    : public policy::CloudPolicyClient::Observer,
-      public OAuth2AccessTokenConsumer,
-      public policy::UserInfoFetcher::Delegate {
- public:
-  explicit CloudPolicyClientRegistrationHelper(
-      net::URLRequestContextGetter* context);
-
-  virtual ~CloudPolicyClientRegistrationHelper();
-
-  // Starts the client registration process. Callback is invoked when the
-  // registration is complete.
-  void StartRegistration(policy::CloudPolicyClient* client,
-                         const std::string& oauth2_login_token,
-                         base::Closure callback);
-
-  // OAuth2AccessTokenConsumer implementation.
-  virtual void OnGetTokenSuccess(const std::string& access_token,
-                                 const base::Time& expiration_time) OVERRIDE;
-  virtual void OnGetTokenFailure(const GoogleServiceAuthError& error) OVERRIDE;
-
-  // UserInfoFetcher::Delegate implementation:
-  virtual void OnGetUserInfoSuccess(const DictionaryValue* response) OVERRIDE;
-  virtual void OnGetUserInfoFailure(
-      const GoogleServiceAuthError& error) OVERRIDE;
-
-  // CloudPolicyClient::Observer implementation.
-  virtual void OnPolicyFetched(policy::CloudPolicyClient* client) OVERRIDE {}
-  virtual void OnRegistrationStateChanged(
-      policy::CloudPolicyClient* client) OVERRIDE;
-  virtual void OnClientError(policy::CloudPolicyClient* client) OVERRIDE;
-
- private:
-  // Invoked when the registration request has been completed.
-  void RequestCompleted();
-
-  // Fetcher used while obtaining an OAuth token for client registration.
-  scoped_ptr<OAuth2AccessTokenFetcher> oauth2_access_token_fetcher_;
-
-  // Helper class for fetching information from GAIA about the currently
-  // signed-in user.
-  scoped_ptr<policy::UserInfoFetcher> user_info_fetcher_;
-
-  // Access token used to register the CloudPolicyClient and also access
-  // GAIA to get information about the signed in user.
-  std::string oauth_access_token_;
-
-  net::URLRequestContextGetter* context_;
-  policy::CloudPolicyClient* client_;
-  base::Closure callback_;
-};
-
-CloudPolicyClientRegistrationHelper::CloudPolicyClientRegistrationHelper(
-    net::URLRequestContextGetter* context) : context_(context) {
-  DCHECK(context_);
-}
-
-CloudPolicyClientRegistrationHelper::~CloudPolicyClientRegistrationHelper() {
-  // Clean up any pending observers in case the browser is shutdown while
-  // trying to register for policy.
-  if (client_)
-    client_->RemoveObserver(this);
-}
-
-void CloudPolicyClientRegistrationHelper::RequestCompleted() {
-  if (client_) {
-    client_->RemoveObserver(this);
-    // |client_| may be freed by the callback so clear it now.
-    client_ = NULL;
-    callback_.Run();
-  }
-}
-
-void CloudPolicyClientRegistrationHelper::StartRegistration(
-    policy::CloudPolicyClient* client,
-    const std::string& login_token,
-    base::Closure callback) {
-  DVLOG(1) << "Starting registration process";
-  DCHECK(client);
-  DCHECK(!client->is_registered());
-  client_ = client;
-  callback_ = callback;
-  client_->AddObserver(this);
-
-  // Start fetching an OAuth2 access token for the device management and
-  // userinfo services.
-  oauth2_access_token_fetcher_.reset(
-      new OAuth2AccessTokenFetcher(this, context_));
-  std::vector<std::string> scopes;
-  scopes.push_back(GaiaConstants::kDeviceManagementServiceOAuth);
-  scopes.push_back(kServiceScopeGetUserInfo);
-  GaiaUrls* gaia_urls = GaiaUrls::GetInstance();
-  oauth2_access_token_fetcher_->Start(
-      gaia_urls->oauth2_chrome_client_id(),
-      gaia_urls->oauth2_chrome_client_secret(),
-      login_token,
-      scopes);
-}
-
-void CloudPolicyClientRegistrationHelper::OnGetTokenFailure(
-    const GoogleServiceAuthError& error) {
-  DLOG(WARNING) << "Could not fetch access token for "
-                << GaiaConstants::kDeviceManagementServiceOAuth;
-  oauth2_access_token_fetcher_.reset();
-
-  // Invoke the callback to let them know the fetch failed.
-  RequestCompleted();
-}
-
-void CloudPolicyClientRegistrationHelper::OnGetTokenSuccess(
-    const std::string& access_token,
-    const base::Time& expiration_time) {
-  // Cache the access token to be used after the GetUserInfo call.
-  oauth_access_token_ = access_token;
-  DVLOG(1) << "Fetched new scoped OAuth token:" << oauth_access_token_;
-  oauth2_access_token_fetcher_.reset();
-  // Now we've gotten our access token - contact GAIA to see if this is a
-  // hosted domain.
-  user_info_fetcher_.reset(new policy::UserInfoFetcher(this, context_));
-  user_info_fetcher_->Start(oauth_access_token_);
-}
-
-void CloudPolicyClientRegistrationHelper::OnGetUserInfoFailure(
-    const GoogleServiceAuthError& error) {
-  DVLOG(1) << "Failed to fetch user info from GAIA: " << error.state();
-  user_info_fetcher_.reset();
-  RequestCompleted();
-}
-
-void CloudPolicyClientRegistrationHelper::OnGetUserInfoSuccess(
-    const DictionaryValue* data) {
-  user_info_fetcher_.reset();
-  if (!data->HasKey(kGetHostedDomainKey) && !ShouldForceLoadPolicy()) {
-    DVLOG(1) << "User not from a hosted domain - skipping registration";
-    RequestCompleted();
-    return;
-  }
-  DVLOG(1) << "Registering CloudPolicyClient for user from hosted domain";
-  // The user is from a hosted domain, so it's OK to register the
-  // CloudPolicyClient and make requests to DMServer.
-  if (client_->is_registered()) {
-    // Client should not be registered yet.
-    NOTREACHED();
-    RequestCompleted();
-    return;
-  }
-
-  // Kick off registration of the CloudPolicyClient with our newly minted
-  // oauth_access_token_.
-  client_->Register(em::DeviceRegisterRequest::BROWSER, oauth_access_token_,
-                    std::string(), false, std::string());
-}
-
-void CloudPolicyClientRegistrationHelper::OnRegistrationStateChanged(
-    policy::CloudPolicyClient* client) {
-  DVLOG(1) << "Client registration succeeded";
-  DCHECK_EQ(client, client_);
-  DCHECK(client->is_registered());
-  RequestCompleted();
-}
-
-void CloudPolicyClientRegistrationHelper::OnClientError(
-    policy::CloudPolicyClient* client) {
-  DVLOG(1) << "Client registration failed";
-  DCHECK_EQ(client, client_);
-  RequestCompleted();
-}
-
 UserPolicySigninService::UserPolicySigninService(
-    Profile* profile)
-    : profile_(profile),
-      weak_factory_(this) {
-  if (profile_->GetPrefs()->GetBoolean(prefs::kDisableCloudPolicyOnSignin))
+    Profile* profile) : UserPolicySigninServiceBase(profile) {
+  if (profile->GetPrefs()->GetBoolean(prefs::kDisableCloudPolicyOnSignin))
     return;
 
-  // Initialize/shutdown the UserCloudPolicyManager when the user signs out.
-  registrar_.Add(this,
-                 chrome::NOTIFICATION_GOOGLE_SIGNED_OUT,
-                 content::Source<Profile>(profile));
-
   // Listen for an OAuth token to become available so we can register a client
   // if for some reason the client is not already registered (for example, if
   // the policy load failed during initial signin).
-  registrar_.Add(this,
-                 chrome::NOTIFICATION_TOKEN_AVAILABLE,
-                 content::Source<TokenService>(
-                     TokenServiceFactory::GetForProfile(profile)));
+  registrar()->Add(this,
+                   chrome::NOTIFICATION_TOKEN_AVAILABLE,
+                   content::Source<TokenService>(
+                       TokenServiceFactory::GetForProfile(profile)));
 
   // TokenService should not yet have loaded its tokens since this happens in
   // the background after PKS initialization - so this service should always be
   // created before the oauth token is available.
-  DCHECK(!TokenServiceFactory::GetForProfile(profile_)->HasOAuthLoginToken());
-
-  // Register a listener to be called back once the current profile has finished
-  // initializing, so we can startup the UserCloudPolicyManager.
-  registrar_.Add(this,
-                 chrome::NOTIFICATION_PROFILE_ADDED,
-                 content::Source<Profile>(profile));
+  DCHECK(!TokenServiceFactory::GetForProfile(profile)->HasOAuthLoginToken());
 
   // Register a listener for the import finished notification in a first run
   // scenario, which indicates the profile is ready to be further initialized.
-  registrar_.Add(this,
-                 chrome::NOTIFICATION_IMPORT_FINISHED,
-                 content::Source<Profile>(profile));
+  registrar()->Add(this,
+                   chrome::NOTIFICATION_IMPORT_FINISHED,
+                   content::Source<Profile>(profile));
 }
 
 UserPolicySigninService::~UserPolicySigninService() {}
 
+void UserPolicySigninService::Shutdown() {
+  // Stop any pending registration helper activity. We do this here instead of
+  // in the destructor because we want to shutdown the registration helper
+  // before UserCloudPolicyManager shuts down the CloudPolicyClient.
+  registration_helper_.reset();
+  UserPolicySigninServiceBase::Shutdown();
+}
+
 void UserPolicySigninService::RegisterPolicyClient(
     const std::string& username,
     const std::string& oauth2_refresh_token,
     const PolicyRegistrationCallback& callback) {
-  DCHECK(!username.empty());
   DCHECK(!oauth2_refresh_token.empty());
-  // We should not be called with a client already initialized.
-  DCHECK(!GetManager() || !GetManager()->core()->client());
 
-  // If the user should not get policy, just bail out.
-  if (!GetManager() || !ShouldLoadPolicyForUser(username)) {
-    DVLOG(1) << "Signed in user is not in the whitelist";
-    callback.Run(scoped_ptr<CloudPolicyClient>().Pass());
+  // Create a new CloudPolicyClient for fetching the DMToken.
+  scoped_ptr<CloudPolicyClient> policy_client = PrepareToRegister(username);
+  if (!policy_client) {
+    callback.Run(policy_client.Pass());
     return;
   }
 
-  // If the DeviceManagementService is not yet initialized, start it up now.
-  g_browser_process->browser_policy_connector()->
-      ScheduleServiceInitialization(0);
-
-  // Create a new CloudPolicyClient for fetching the DMToken.
-  scoped_ptr<CloudPolicyClient> policy_client(
-      UserCloudPolicyManager::CreateCloudPolicyClient(
-          g_browser_process->browser_policy_connector()->
-          device_management_service()));
-
-  registration_helper_.reset(
-      new CloudPolicyClientRegistrationHelper(profile_->GetRequestContext()));
-
   // Fire off the registration process. Callback keeps the CloudPolicyClient
   // alive for the length of the registration process.
-  // Grab a pointer to the client before base::Bind() clears the reference in
-  // |policy_client|.
-  CloudPolicyClient* client = policy_client.get();
-  base::Closure registration_callback =
+  registration_helper_.reset(new CloudPolicyClientRegistrationHelper(
+      profile()->GetRequestContext(),
+      policy_client.get(),
+      ShouldForceLoadPolicy(),
+      enterprise_management::DeviceRegisterRequest::BROWSER));
+  registration_helper_->StartRegistrationWithLoginToken(
+      oauth2_refresh_token,
       base::Bind(&UserPolicySigninService::CallPolicyRegistrationCallback,
-                 base::Unretained(this), base::Passed(&policy_client),
-                 callback);
-  registration_helper_->StartRegistration(
-      client, oauth2_refresh_token, registration_callback);
+                 base::Unretained(this),
+                 base::Passed(&policy_client),
+                 callback));
 }
 
 void UserPolicySigninService::CallPolicyRegistrationCallback(
@@ -315,42 +102,6 @@
   callback.Run(client.Pass());
 }
 
-void UserPolicySigninService::FetchPolicyForSignedInUser(
-    scoped_ptr<CloudPolicyClient> client,
-    const PolicyFetchCallback& callback) {
-  DCHECK(client);
-  DCHECK(client->is_registered());
-  // The user has just signed in, so the UserCloudPolicyManager should not yet
-  // be initialized. This routine will initialize the UserCloudPolicyManager
-  // with the passed client and will proactively ask the client to fetch
-  // policy without waiting for the CloudPolicyService to finish initialization.
-  UserCloudPolicyManager* manager = GetManager();
-  DCHECK(manager);
-  DCHECK(!manager->core()->client());
-  InitializeUserCloudPolicyManager(client.Pass());
-  DCHECK(manager->IsClientRegistered());
-
-  // Now initiate a policy fetch.
-  manager->core()->service()->RefreshPolicy(callback);
-}
-
-void UserPolicySigninService::StopObserving() {
-  UserCloudPolicyManager* manager = GetManager();
-  if (manager && manager->core()->service())
-    manager->core()->service()->RemoveObserver(this);
-  if (manager && manager->core()->client())
-    manager->core()->client()->RemoveObserver(this);
-}
-
-void UserPolicySigninService::StartObserving() {
-  UserCloudPolicyManager* manager = GetManager();
-  // Manager should be fully initialized by now.
-  DCHECK(manager);
-  DCHECK(manager->core()->service());
-  manager->core()->service()->AddObserver(this);
-  manager->core()->client()->AddObserver(this);
-}
-
 void UserPolicySigninService::Observe(
     int type,
     const content::NotificationSource& source,
@@ -364,128 +115,59 @@
     return;
   }
 
+#if defined(ENABLE_MANAGED_USERS)
+  if (ManagedUserService::ProfileIsManaged(profile())) {
+    registrar()->RemoveAll();
+    return;
+  }
+#endif
+
   // If using a TestingProfile with no SigninManager or UserCloudPolicyManager,
   // skip initialization.
-  if (!GetManager() || !SigninManagerFactory::GetForProfile(profile_)) {
+  if (!GetManager() || !SigninManagerFactory::GetForProfile(profile())) {
     DVLOG(1) << "Skipping initialization for tests due to missing components.";
     return;
   }
 
   switch (type) {
-    case chrome::NOTIFICATION_GOOGLE_SIGNED_OUT:
-      ShutdownUserCloudPolicyManager();
-      break;
     case chrome::NOTIFICATION_IMPORT_FINISHED:
-    case chrome::NOTIFICATION_PROFILE_ADDED: {
-      // A new profile has been loaded - if it's signed in, then initialize the
-      // UCPM, otherwise shut down the UCPM (which deletes any cached policy
-      // data). This must be done here instead of at constructor time because
-      // the Profile is not fully initialized when this object is constructed
-      // (DoFinalInit() has not yet been called, so ProfileIOData and
-      // SSLConfigServiceManager have not been created yet).
-      // TODO(atwilson): Switch to using a timer instead, to avoid contention
-      // with other services at startup (http://crbug.com/165468).
-      SigninManager* signin_manager =
-          SigninManagerFactory::GetForProfile(profile_);
-      std::string username = signin_manager->GetAuthenticatedUsername();
-      if (username.empty())
-        ShutdownUserCloudPolicyManager();
-      else
-        InitializeForSignedInUser();
+      InitializeOnProfileReady();
       break;
-    }
     case chrome::NOTIFICATION_TOKEN_AVAILABLE: {
       const TokenService::TokenAvailableDetails& token_details =
           *(content::Details<const TokenService::TokenAvailableDetails>(
               details).ptr());
       if (token_details.service() ==
-          GaiaConstants::kGaiaOAuth2LoginRefreshToken) {
+              GaiaConstants::kGaiaOAuth2LoginRefreshToken) {
         SigninManager* signin_manager =
-            SigninManagerFactory::GetForProfile(profile_);
+            SigninManagerFactory::GetForProfile(profile());
         std::string username = signin_manager->GetAuthenticatedUsername();
         // Should not have GAIA tokens if the user isn't signed in.
         DCHECK(!username.empty());
         // TokenService now has a refresh token (implying that the user is
         // signed in) so initialize the UserCloudPolicyManager.
-        InitializeForSignedInUser();
+        InitializeForSignedInUser(username);
       }
       break;
     }
     default:
-      NOTREACHED();
+      UserPolicySigninServiceBase::Observe(type, source, details);
   }
 }
 
-bool UserPolicySigninService::ShouldLoadPolicyForUser(
-    const std::string& username) {
-  if (profile_->GetPrefs()->GetBoolean(prefs::kDisableCloudPolicyOnSignin))
-    return false; // Cloud policy is disabled.
-
-  if (username.empty())
-    return false; // Not signed in.
-
-  if (ShouldForceLoadPolicy())
-    return true;
-
-  return !BrowserPolicyConnector::IsNonEnterpriseUser(username);
-}
-
 void UserPolicySigninService::InitializeUserCloudPolicyManager(
     scoped_ptr<CloudPolicyClient> client) {
-  UserCloudPolicyManager* manager = GetManager();
-  DCHECK(!manager->core()->client());
-  // If there is no cached DMToken then we can detect this below (or when
-  // the OnInitializationCompleted() callback is invoked).
-  manager->Connect(g_browser_process->local_state(), client.Pass());
-  DCHECK(manager->core()->service());
-  StartObserving();
+  UserPolicySigninServiceBase::InitializeUserCloudPolicyManager(client.Pass());
   ProhibitSignoutIfNeeded();
 }
 
-void UserPolicySigninService::InitializeForSignedInUser() {
-  SigninManager* signin_manager =
-      SigninManagerFactory::GetForProfile(profile_);
-  std::string username = signin_manager->GetAuthenticatedUsername();
-
-  if (!ShouldLoadPolicyForUser(username)) {
-    DVLOG(1) << "Policy load not enabled for user: " << username;
-    return;
-  }
-  DCHECK(!username.empty());
-
-  UserCloudPolicyManager* manager = GetManager();
-  // Initialize the UCPM if it is not already initialized.
-  if (!manager->core()->service()) {
-    // If there is no cached DMToken then we can detect this when the
-    // OnInitializationCompleted() callback is invoked and this will
-    // initiate a policy fetch.
-    BrowserPolicyConnector* connector =
-        g_browser_process->browser_policy_connector();
-    InitializeUserCloudPolicyManager(
-        UserCloudPolicyManager::CreateCloudPolicyClient(
-            connector->device_management_service()).Pass());
-  }
-
-  // If the CloudPolicyService is initialized, kick off registration. If the
-  // TokenService doesn't have an OAuth token yet (e.g. this is during initial
-  // signin, or when dynamically loading a signed-in policy) this does nothing
-  // until the OAuth token is loaded.
-  if (manager->core()->service()->IsInitializationComplete())
-    OnInitializationCompleted(manager->core()->service());
-}
-
 void UserPolicySigninService::ShutdownUserCloudPolicyManager() {
-  // Stop any in-progress token fetch.
-  registration_helper_.reset();
-
-  StopObserving();
-
   UserCloudPolicyManager* manager = GetManager();
-  if (manager) {  // Can be null in unit tests.
-    manager->DisconnectAndRemovePolicy();
+  if (manager) {
     // Allow the user to signout again.
-    SigninManagerFactory::GetForProfile(profile_)->ProhibitSignout(false);
+    SigninManagerFactory::GetForProfile(profile())->ProhibitSignout(false);
   }
+  UserPolicySigninServiceBase::ShutdownUserCloudPolicyManager();
 }
 
 void UserPolicySigninService::OnInitializationCompleted(
@@ -499,7 +181,7 @@
   DVLOG_IF(1, manager->IsClientRegistered())
       << "Client already registered - not fetching DMToken";
   if (!manager->IsClientRegistered()) {
-    std::string token = TokenServiceFactory::GetForProfile(profile_)->
+    std::string token = TokenServiceFactory::GetForProfile(profile())->
         GetOAuth2LoginRefreshToken();
     if (token.empty()) {
       // No token yet - this class listens for NOTIFICATION_TOKEN_AVAILABLE
@@ -513,38 +195,8 @@
   ProhibitSignoutIfNeeded();
 }
 
-void UserPolicySigninService::OnPolicyFetched(CloudPolicyClient* client) {
-}
-
-void UserPolicySigninService::OnRegistrationStateChanged(
-    CloudPolicyClient* client) {
-}
-
-void UserPolicySigninService::OnClientError(CloudPolicyClient* client) {
-  if (client->is_registered()) {
-    // If the client is already registered, it means this error must have
-    // come from a policy fetch.
-    if (client->status() ==
-        policy::DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED) {
-      // OK, policy fetch failed with MANAGEMENT_NOT_SUPPORTED - this is our
-      // trigger to revert to "unmanaged" mode (we will check for management
-      // being re-enabled on the next restart and/or login).
-      DVLOG(1) << "DMServer returned NOT_SUPPORTED error - removing policy";
-
-      // Can't shutdown now because we're in the middle of a callback from
-      // the CloudPolicyClient, so queue up a task to do the shutdown.
-      base::MessageLoop::current()->PostTask(
-          FROM_HERE,
-          base::Bind(&UserPolicySigninService::ShutdownUserCloudPolicyManager,
-                     weak_factory_.GetWeakPtr()));
-    } else {
-      DVLOG(1) << "Error fetching policy: " << client->status();
-    }
-  }
-}
-
 void UserPolicySigninService::RegisterCloudPolicyService(
-    std::string login_token) {
+    const std::string& login_token) {
   DCHECK(!GetManager()->IsClientRegistered());
   DVLOG(1) << "Fetching new DM Token";
   // Do nothing if already starting the registration process.
@@ -553,10 +205,12 @@
 
   // Start the process of registering the CloudPolicyClient. Once it completes,
   // policy fetch will automatically happen.
-  registration_helper_.reset(
-      new CloudPolicyClientRegistrationHelper(profile_->GetRequestContext()));
-  registration_helper_->StartRegistration(
+  registration_helper_.reset(new CloudPolicyClientRegistrationHelper(
+      profile()->GetRequestContext(),
       GetManager()->core()->client(),
+      ShouldForceLoadPolicy(),
+      enterprise_management::DeviceRegisterRequest::BROWSER));
+  registration_helper_->StartRegistrationWithLoginToken(
       login_token,
       base::Bind(&UserPolicySigninService::OnRegistrationComplete,
                  base::Unretained(this)));
@@ -571,21 +225,9 @@
   if (GetManager()->IsClientRegistered()) {
     DVLOG(1) << "User is registered for policy - prohibiting signout";
     SigninManager* signin_manager =
-        SigninManagerFactory::GetForProfile(profile_);
+        SigninManagerFactory::GetForProfile(profile());
     signin_manager->ProhibitSignout(true);
   }
 }
 
-void UserPolicySigninService::Shutdown() {
-  // Stop any pending registration helper activity. We do this here instead of
-  // in the destructor because we want to shutdown the registration helper
-  // before UserCloudPolicyManager shuts down the CloudPolicyClient.
-  registration_helper_.reset();
-  StopObserving();
-}
-
-UserCloudPolicyManager* UserPolicySigninService::GetManager() {
-  return UserCloudPolicyManagerFactory::GetForProfile(profile_);
-}
-
 }  // namespace policy
diff --git a/chrome/browser/policy/cloud/user_policy_signin_service.h b/chrome/browser/policy/cloud/user_policy_signin_service.h
index fda278f..221c226 100644
--- a/chrome/browser/policy/cloud/user_policy_signin_service.h
+++ b/chrome/browser/policy/cloud/user_policy_signin_service.h
@@ -5,55 +5,23 @@
 #ifndef CHROME_BROWSER_POLICY_CLOUD_USER_POLICY_SIGNIN_SERVICE_H_
 #define CHROME_BROWSER_POLICY_CLOUD_USER_POLICY_SIGNIN_SERVICE_H_
 
+#include <string>
+
 #include "base/basictypes.h"
-#include "base/callback.h"
+#include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "chrome/browser/policy/cloud/cloud_policy_service.h"
-#include "chrome/browser/policy/cloud/user_info_fetcher.h"
-#include "components/browser_context_keyed_service/browser_context_keyed_service.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
+#include "chrome/browser/policy/cloud/user_policy_signin_service_base.h"
 
 class Profile;
 
-namespace base {
-class Time;
-}
-
 namespace policy {
 
 class CloudPolicyClientRegistrationHelper;
-class CloudPolicyClient;
-class UserCloudPolicyManager;
 
-// The UserPolicySigninService is responsible for interacting with the policy
-// infrastructure (mainly UserCloudPolicyManager) to load policy for the signed
-// in user.
-//
-// At signin time, this class initializes the UCPM and loads policy before any
-// other signed in services are initialized. After each restart, this class
-// ensures that the CloudPolicyClient is registered (in case the policy server
-// was offline during the initial policy fetch) and if not it initiates a fresh
-// registration process.
-//
-// Finally, if the user signs out, this class is responsible for shutting down
-// the policy infrastructure to ensure that any cached policy is cleared.
-class UserPolicySigninService
-    : public BrowserContextKeyedService,
-      public CloudPolicyClient::Observer,
-      public CloudPolicyService::Observer,
-      public content::NotificationObserver {
+// A specialization of the UserPolicySigninServiceBase for the desktop
+// platforms (Windows, Mac and Linux).
+class UserPolicySigninService : public UserPolicySigninServiceBase {
  public:
-  // The callback invoked once policy registration is complete. Passed
-  // CloudPolicyClient parameter is null if DMToken fetch failed.
-  typedef base::Callback<void(scoped_ptr<CloudPolicyClient>)>
-      PolicyRegistrationCallback;
-
-  // The callback invoked once policy fetch is complete. Passed boolean
-  // parameter is set to true if the policy fetch succeeded.
-  typedef base::Callback<void(bool)> PolicyFetchCallback;
-
   // Creates a UserPolicySigninService associated with the passed |profile|.
   explicit UserPolicySigninService(Profile* profile);
   virtual ~UserPolicySigninService();
@@ -66,47 +34,28 @@
                             const std::string& oauth2_login_token,
                             const PolicyRegistrationCallback& callback);
 
-  // Initiates a policy fetch as part of user signin, using a CloudPolicyClient
-  // previously initialized via RegisterPolicyClient. |callback| is invoked
-  // once the policy fetch is complete, passing true if the policy fetch
-  // succeeded.
-  void FetchPolicyForSignedInUser(scoped_ptr<CloudPolicyClient> client,
-                                  const PolicyFetchCallback& callback);
-
-  // content::NotificationObserver implementation.
+  // content::NotificationObserver implementation:
   virtual void Observe(int type,
                        const content::NotificationSource& source,
                        const content::NotificationDetails& details) OVERRIDE;
 
-  // CloudPolicyService::Observer implementation.
+  // CloudPolicyService::Observer implementation:
   virtual void OnInitializationCompleted(CloudPolicyService* service) OVERRIDE;
 
-  // CloudPolicyClient::Observer implementation.
-  virtual void OnPolicyFetched(CloudPolicyClient* client) OVERRIDE;
-  virtual void OnRegistrationStateChanged(CloudPolicyClient* client) OVERRIDE;
-  virtual void OnClientError(CloudPolicyClient* client) OVERRIDE;
-
   // BrowserContextKeyedService implementation:
   virtual void Shutdown() OVERRIDE;
 
+  // UserPolicySigninServiceBase implementation:
+  virtual void InitializeUserCloudPolicyManager(
+      scoped_ptr<CloudPolicyClient> client) OVERRIDE;
+  virtual void ShutdownUserCloudPolicyManager() OVERRIDE;
+
  private:
-  // Returns false if cloud policy is disabled or if the passed |email_address|
-  // is definitely not from a hosted domain (according to the blacklist in
-  // BrowserPolicyConnector::IsNonEnterpriseUser()).
-  bool ShouldLoadPolicyForUser(const std::string& email_address);
-
-  // Initializes the UserCloudPolicyManager using the passed CloudPolicyClient.
-  void InitializeUserCloudPolicyManager(scoped_ptr<CloudPolicyClient> client);
-
-  // Initializes the UserCloudPolicyManager with policy for the currently
-  // signed-in user.
-  void InitializeForSignedInUser();
-
   // Fetches an OAuth token to allow the cloud policy service to register with
   // the cloud policy server. |oauth_login_token| should contain an OAuth login
   // refresh token that can be downscoped to get an access token for the
   // device_management service.
-  void RegisterCloudPolicyService(std::string oauth_login_token);
+  void RegisterCloudPolicyService(const std::string& oauth_login_token);
 
   // Callback invoked when policy registration has finished.
   void OnRegistrationComplete();
@@ -115,31 +64,12 @@
   // cloud policy.
   void ProhibitSignoutIfNeeded();
 
-  // Helper routines to (un)register for CloudPolicyService and
-  // CloudPolicyClient notifications.
-  void StartObserving();
-  void StopObserving();
-
-  // Shuts down the UserCloudPolicyManager (for example, after the user signs
-  // out) and deletes any cached policy.
-  void ShutdownUserCloudPolicyManager();
-
   // Invoked when a policy registration request is complete.
   void CallPolicyRegistrationCallback(scoped_ptr<CloudPolicyClient> client,
                                       PolicyRegistrationCallback callback);
 
-  // Convenience helper to get the UserCloudPolicyManager for |profile_|.
-  UserCloudPolicyManager* GetManager();
-
-  // Weak pointer to the profile this service is associated with.
-  Profile* profile_;
-
-  content::NotificationRegistrar registrar_;
-
   scoped_ptr<CloudPolicyClientRegistrationHelper> registration_helper_;
 
-  base::WeakPtrFactory<UserPolicySigninService> weak_factory_;
-
   DISALLOW_COPY_AND_ASSIGN(UserPolicySigninService);
 };
 
diff --git a/chrome/browser/policy/cloud/user_policy_signin_service_android.cc b/chrome/browser/policy/cloud/user_policy_signin_service_android.cc
new file mode 100644
index 0000000..80bed74
--- /dev/null
+++ b/chrome/browser/policy/cloud/user_policy_signin_service_android.cc
@@ -0,0 +1,88 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/policy/cloud/user_policy_signin_service_android.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/callback.h"
+#include "base/logging.h"
+#include "chrome/browser/policy/cloud/cloud_policy_client_registration_helper.h"
+#include "chrome/browser/policy/cloud/user_cloud_policy_manager.h"
+#include "chrome/browser/policy/proto/cloud/device_management_backend.pb.h"
+#include "chrome/browser/profiles/profile.h"
+
+namespace policy {
+
+UserPolicySigninService::UserPolicySigninService(Profile* profile)
+    : UserPolicySigninServiceBase(profile) {}
+
+UserPolicySigninService::~UserPolicySigninService() {}
+
+void UserPolicySigninService::RegisterPolicyClient(
+    const std::string& username,
+    const std::string& services_token,
+    const PolicyRegistrationCallback& callback) {
+  DCHECK(!services_token.empty());
+
+  // Create a new CloudPolicyClient for fetching the DMToken.
+  scoped_ptr<CloudPolicyClient> policy_client = PrepareToRegister(username);
+  if (!policy_client) {
+    callback.Run(policy_client.Pass());
+    return;
+  }
+
+  // Fire off the registration process. Callback keeps the CloudPolicyClient
+  // alive for the length of the registration process.
+  // TODO(joaodasilva): use DeviceRegisterRequest::ANDROID_BROWSER here once
+  // the server is ready. http://crbug.com/248527
+  const bool force_load_policy = false;
+  registration_helper_.reset(new CloudPolicyClientRegistrationHelper(
+      profile()->GetRequestContext(),
+      policy_client.get(),
+      force_load_policy,
+      enterprise_management::DeviceRegisterRequest::BROWSER));
+  registration_helper_->StartRegistrationWithServicesToken(
+      services_token,
+      base::Bind(&UserPolicySigninService::CallPolicyRegistrationCallback,
+                 base::Unretained(this),
+                 base::Passed(&policy_client),
+                 callback));
+}
+
+void UserPolicySigninService::CallPolicyRegistrationCallback(
+    scoped_ptr<CloudPolicyClient> client,
+    PolicyRegistrationCallback callback) {
+  registration_helper_.reset();
+  if (!client->is_registered()) {
+    // Registration failed, so free the client and pass NULL to the callback.
+    client.reset();
+  }
+  callback.Run(client.Pass());
+}
+
+void UserPolicySigninService::Shutdown() {
+  registration_helper_.reset();
+  UserPolicySigninServiceBase::Shutdown();
+}
+
+void UserPolicySigninService::OnInitializationCompleted(
+    CloudPolicyService* service) {
+  UserCloudPolicyManager* manager = GetManager();
+  DCHECK_EQ(service, manager->core()->service());
+  DCHECK(service->IsInitializationComplete());
+  // The service is now initialized - if the client is not yet registered, then
+  // it means that there is no cached policy and so we need to initiate a new
+  // client registration.
+  if (manager->IsClientRegistered()) {
+    DVLOG(1) << "Client already registered - not fetching DMToken";
+  } else {
+    // TODO(joaodasilva): figure out what to do in this case: a signed-in user
+    // just started Chrome but hasn't registered for policy yet.
+    // If a registration attempt is started from here then make sure this
+    // doesn't happen on every startup.
+  }
+}
+
+}  // namespace policy
diff --git a/chrome/browser/policy/cloud/user_policy_signin_service_android.h b/chrome/browser/policy/cloud/user_policy_signin_service_android.h
new file mode 100644
index 0000000..0cabf6a
--- /dev/null
+++ b/chrome/browser/policy/cloud/user_policy_signin_service_android.h
@@ -0,0 +1,53 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_POLICY_CLOUD_USER_POLICY_SIGNIN_SERVICE_ANDROID_H_
+#define CHROME_BROWSER_POLICY_CLOUD_USER_POLICY_SIGNIN_SERVICE_ANDROID_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "chrome/browser/policy/cloud/user_policy_signin_service_base.h"
+
+class Profile;
+
+namespace policy {
+
+class CloudPolicyClientRegistrationHelper;
+
+// A specialization of the UserPolicySigninServiceBase for Android.
+class UserPolicySigninService : public UserPolicySigninServiceBase {
+ public:
+  // Creates a UserPolicySigninService associated with the passed |profile|.
+  explicit UserPolicySigninService(Profile* profile);
+  virtual ~UserPolicySigninService();
+
+  // Registers a CloudPolicyClient for fetching policy for |username|.
+  // |services_token| is an OAuth2 token for the userinfo and DM services.
+  // |callback| is invoked once the CloudPolicyClient is ready to fetch policy,
+  // or once it is determined that |username| is not a managed account.
+  void RegisterPolicyClient(const std::string& username,
+                            const std::string& services_token,
+                            const PolicyRegistrationCallback& callback);
+
+ private:
+  void CallPolicyRegistrationCallback(scoped_ptr<CloudPolicyClient> client,
+                                      PolicyRegistrationCallback callback);
+
+  // BrowserContextKeyedService implementation:
+  virtual void Shutdown() OVERRIDE;
+
+  // CloudPolicyService::Observer implementation:
+  virtual void OnInitializationCompleted(CloudPolicyService* service) OVERRIDE;
+
+  scoped_ptr<CloudPolicyClientRegistrationHelper> registration_helper_;
+
+  DISALLOW_COPY_AND_ASSIGN(UserPolicySigninService);
+};
+
+}  // namespace policy
+
+#endif  // CHROME_BROWSER_POLICY_CLOUD_USER_POLICY_SIGNIN_SERVICE_ANDROID_H_
diff --git a/chrome/browser/policy/cloud/user_policy_signin_service_base.cc b/chrome/browser/policy/cloud/user_policy_signin_service_base.cc
new file mode 100644
index 0000000..de3f7b2
--- /dev/null
+++ b/chrome/browser/policy/cloud/user_policy_signin_service_base.cc
@@ -0,0 +1,242 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/policy/cloud/user_policy_signin_service_base.h"
+
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/message_loop.h"
+#include "base/prefs/pref_service.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/policy/browser_policy_connector.h"
+#include "chrome/browser/policy/cloud/user_cloud_policy_manager.h"
+#include "chrome/browser/policy/cloud/user_cloud_policy_manager_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/signin/signin_manager.h"
+#include "chrome/browser/signin/signin_manager_factory.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
+
+namespace policy {
+
+UserPolicySigninServiceBase::UserPolicySigninServiceBase(
+    Profile* profile)
+    : profile_(profile),
+      weak_factory_(this) {
+  if (profile_->GetPrefs()->GetBoolean(prefs::kDisableCloudPolicyOnSignin))
+    return;
+
+  // Initialize/shutdown the UserCloudPolicyManager when the user signs out.
+  registrar_.Add(this,
+                 chrome::NOTIFICATION_GOOGLE_SIGNED_OUT,
+                 content::Source<Profile>(profile));
+
+  // Register a listener to be called back once the current profile has finished
+  // initializing, so we can startup the UserCloudPolicyManager.
+  registrar_.Add(this,
+                 chrome::NOTIFICATION_PROFILE_ADDED,
+                 content::Source<Profile>(profile));
+}
+
+UserPolicySigninServiceBase::~UserPolicySigninServiceBase() {}
+
+void UserPolicySigninServiceBase::FetchPolicyForSignedInUser(
+    scoped_ptr<CloudPolicyClient> client,
+    const PolicyFetchCallback& callback) {
+  DCHECK(client);
+  DCHECK(client->is_registered());
+  // The user has just signed in, so the UserCloudPolicyManager should not yet
+  // be initialized. This routine will initialize the UserCloudPolicyManager
+  // with the passed client and will proactively ask the client to fetch
+  // policy without waiting for the CloudPolicyService to finish initialization.
+  UserCloudPolicyManager* manager = GetManager();
+  DCHECK(manager);
+  DCHECK(!manager->core()->client());
+  InitializeUserCloudPolicyManager(client.Pass());
+  DCHECK(manager->IsClientRegistered());
+
+  // Now initiate a policy fetch.
+  manager->core()->service()->RefreshPolicy(callback);
+}
+
+void UserPolicySigninServiceBase::Observe(
+    int type,
+    const content::NotificationSource& source,
+    const content::NotificationDetails& details) {
+  // If using a TestingProfile with no SigninManager or UserCloudPolicyManager,
+  // skip initialization.
+  if (!GetManager() || !SigninManagerFactory::GetForProfile(profile_)) {
+    DVLOG(1) << "Skipping initialization for tests due to missing components.";
+    return;
+  }
+
+  switch (type) {
+    case chrome::NOTIFICATION_GOOGLE_SIGNED_OUT:
+      ShutdownUserCloudPolicyManager();
+      break;
+    case chrome::NOTIFICATION_PROFILE_ADDED:
+      // A new profile has been loaded - if it's signed in, then initialize the
+      // UCPM, otherwise shut down the UCPM (which deletes any cached policy
+      // data). This must be done here instead of at constructor time because
+      // the Profile is not fully initialized when this object is constructed
+      // (DoFinalInit() has not yet been called, so ProfileIOData and
+      // SSLConfigServiceManager have not been created yet).
+      // TODO(atwilson): Switch to using a timer instead, to avoid contention
+      // with other services at startup (http://crbug.com/165468).
+      InitializeOnProfileReady();
+      break;
+    default:
+      NOTREACHED();
+  }
+}
+
+void UserPolicySigninServiceBase::OnInitializationCompleted(
+    CloudPolicyService* service) {
+  // This is meant to be overridden by subclasses. Starting and stopping to
+  // observe the CloudPolicyService from this base class avoids the need for
+  // more virtuals.
+}
+
+void UserPolicySigninServiceBase::OnPolicyFetched(CloudPolicyClient* client) {}
+
+void UserPolicySigninServiceBase::OnRegistrationStateChanged(
+    CloudPolicyClient* client) {}
+
+void UserPolicySigninServiceBase::OnClientError(CloudPolicyClient* client) {
+  if (client->is_registered()) {
+    // If the client is already registered, it means this error must have
+    // come from a policy fetch.
+    if (client->status() == DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED) {
+      // OK, policy fetch failed with MANAGEMENT_NOT_SUPPORTED - this is our
+      // trigger to revert to "unmanaged" mode (we will check for management
+      // being re-enabled on the next restart and/or login).
+      DVLOG(1) << "DMServer returned NOT_SUPPORTED error - removing policy";
+
+      // Can't shutdown now because we're in the middle of a callback from
+      // the CloudPolicyClient, so queue up a task to do the shutdown.
+      base::MessageLoop::current()->PostTask(
+          FROM_HERE,
+          base::Bind(
+              &UserPolicySigninServiceBase::ShutdownUserCloudPolicyManager,
+              weak_factory_.GetWeakPtr()));
+    } else {
+      DVLOG(1) << "Error fetching policy: " << client->status();
+    }
+  }
+}
+
+void UserPolicySigninServiceBase::Shutdown() {
+  UserCloudPolicyManager* manager = GetManager();
+  if (manager && manager->core()->client())
+    manager->core()->client()->RemoveObserver(this);
+  if (manager && manager->core()->service())
+    manager->core()->service()->RemoveObserver(this);
+}
+
+// static
+bool UserPolicySigninServiceBase::ShouldForceLoadPolicy() {
+  return CommandLine::ForCurrentProcess()->HasSwitch(
+      switches::kForceLoadCloudPolicy);
+}
+
+scoped_ptr<CloudPolicyClient> UserPolicySigninServiceBase::PrepareToRegister(
+    const std::string& username) {
+  DCHECK(!username.empty());
+  // We should not be called with a client already initialized.
+  DCHECK(!GetManager() || !GetManager()->core()->client());
+
+  // If the user should not get policy, just bail out.
+  if (!GetManager() || !ShouldLoadPolicyForUser(username)) {
+    DVLOG(1) << "Signed in user is not in the whitelist";
+    return scoped_ptr<CloudPolicyClient>();
+  }
+
+  // If the DeviceManagementService is not yet initialized, start it up now.
+  BrowserPolicyConnector* connector =
+      g_browser_process->browser_policy_connector();
+  connector->ScheduleServiceInitialization(0);
+
+  // Create a new CloudPolicyClient for fetching the DMToken.
+  return UserCloudPolicyManager::CreateCloudPolicyClient(
+      connector->device_management_service());
+}
+
+bool UserPolicySigninServiceBase::ShouldLoadPolicyForUser(
+    const std::string& username) {
+  if (profile_->GetPrefs()->GetBoolean(prefs::kDisableCloudPolicyOnSignin))
+    return false;  // Cloud policy is disabled.
+
+  if (username.empty())
+    return false;  // Not signed in.
+
+  if (ShouldForceLoadPolicy())
+    return true;
+
+  return !BrowserPolicyConnector::IsNonEnterpriseUser(username);
+}
+
+void UserPolicySigninServiceBase::InitializeOnProfileReady() {
+  SigninManager* signin_manager =
+      SigninManagerFactory::GetForProfile(profile_);
+  std::string username = signin_manager->GetAuthenticatedUsername();
+  if (username.empty())
+    ShutdownUserCloudPolicyManager();
+  else
+    InitializeForSignedInUser(username);
+}
+
+void UserPolicySigninServiceBase::InitializeForSignedInUser(
+    const std::string& username) {
+  DCHECK(!username.empty());
+  if (!ShouldLoadPolicyForUser(username)) {
+    DVLOG(1) << "Policy load not enabled for user: " << username;
+    return;
+  }
+
+  UserCloudPolicyManager* manager = GetManager();
+  // Initialize the UCPM if it is not already initialized.
+  if (!manager->core()->service()) {
+    // If there is no cached DMToken then we can detect this when the
+    // OnInitializationCompleted() callback is invoked and this will
+    // initiate a policy fetch.
+    BrowserPolicyConnector* connector =
+        g_browser_process->browser_policy_connector();
+    InitializeUserCloudPolicyManager(
+        UserCloudPolicyManager::CreateCloudPolicyClient(
+            connector->device_management_service()).Pass());
+  }
+
+  // If the CloudPolicyService is initialized, kick off registration.
+  // Otherwise OnInitializationCompleted is invoked as soon as the service
+  // finishes its initialization.
+  if (manager->core()->service()->IsInitializationComplete())
+    OnInitializationCompleted(manager->core()->service());
+}
+
+void UserPolicySigninServiceBase::InitializeUserCloudPolicyManager(
+    scoped_ptr<CloudPolicyClient> client) {
+  UserCloudPolicyManager* manager = GetManager();
+  DCHECK(!manager->core()->client());
+  manager->Connect(g_browser_process->local_state(), client.Pass());
+  DCHECK(manager->core()->service());
+
+  // Observe the client to detect errors fetching policy.
+  manager->core()->client()->AddObserver(this);
+  // Observe the service to determine when it's initialized.
+  manager->core()->service()->AddObserver(this);
+}
+
+void UserPolicySigninServiceBase::ShutdownUserCloudPolicyManager() {
+  Shutdown();
+  UserCloudPolicyManager* manager = GetManager();
+  if (manager)
+    manager->DisconnectAndRemovePolicy();
+}
+
+UserCloudPolicyManager* UserPolicySigninServiceBase::GetManager() {
+  return UserCloudPolicyManagerFactory::GetForProfile(profile_);
+}
+
+}  // namespace policy
diff --git a/chrome/browser/policy/cloud/user_policy_signin_service_base.h b/chrome/browser/policy/cloud/user_policy_signin_service_base.h
new file mode 100644
index 0000000..2f68e62
--- /dev/null
+++ b/chrome/browser/policy/cloud/user_policy_signin_service_base.h
@@ -0,0 +1,137 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_POLICY_CLOUD_USER_POLICY_SIGNIN_SERVICE_BASE_H_
+#define CHROME_BROWSER_POLICY_CLOUD_USER_POLICY_SIGNIN_SERVICE_BASE_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/policy/cloud/cloud_policy_client.h"
+#include "chrome/browser/policy/cloud/cloud_policy_service.h"
+#include "components/browser_context_keyed_service/browser_context_keyed_service.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+
+class Profile;
+
+namespace policy {
+
+class UserCloudPolicyManager;
+
+// The UserPolicySigninService is responsible for interacting with the policy
+// infrastructure (mainly UserCloudPolicyManager) to load policy for the signed
+// in user. This is the base class that contains shared behavior.
+//
+// At signin time, this class initializes the UCPM and loads policy before any
+// other signed in services are initialized. After each restart, this class
+// ensures that the CloudPolicyClient is registered (in case the policy server
+// was offline during the initial policy fetch) and if not it initiates a fresh
+// registration process.
+//
+// Finally, if the user signs out, this class is responsible for shutting down
+// the policy infrastructure to ensure that any cached policy is cleared.
+class UserPolicySigninServiceBase : public BrowserContextKeyedService,
+                                    public CloudPolicyClient::Observer,
+                                    public CloudPolicyService::Observer,
+                                    public content::NotificationObserver {
+ public:
+  // The callback invoked once policy registration is complete. Passed
+  // CloudPolicyClient parameter is null if DMToken fetch failed.
+  typedef base::Callback<void(scoped_ptr<CloudPolicyClient>)>
+      PolicyRegistrationCallback;
+
+  // The callback invoked once policy fetch is complete. Passed boolean
+  // parameter is set to true if the policy fetch succeeded.
+  typedef base::Callback<void(bool)> PolicyFetchCallback;
+
+  // Creates a UserPolicySigninServiceBase associated with the passed |profile|.
+  explicit UserPolicySigninServiceBase(Profile* profile);
+  virtual ~UserPolicySigninServiceBase();
+
+  // Initiates a policy fetch as part of user signin, using a CloudPolicyClient
+  // previously initialized via RegisterPolicyClient. |callback| is invoked
+  // once the policy fetch is complete, passing true if the policy fetch
+  // succeeded.
+  void FetchPolicyForSignedInUser(scoped_ptr<CloudPolicyClient> client,
+                                  const PolicyFetchCallback& callback);
+
+  // content::NotificationObserver implementation:
+  virtual void Observe(int type,
+                       const content::NotificationSource& source,
+                       const content::NotificationDetails& details) OVERRIDE;
+
+  // CloudPolicyService::Observer implementation:
+  virtual void OnInitializationCompleted(CloudPolicyService* service) OVERRIDE;
+
+  // CloudPolicyClient::Observer implementation:
+  virtual void OnPolicyFetched(CloudPolicyClient* client) OVERRIDE;
+  virtual void OnRegistrationStateChanged(CloudPolicyClient* client) OVERRIDE;
+  virtual void OnClientError(CloudPolicyClient* client) OVERRIDE;
+
+  // BrowserContextKeyedService implementation:
+  virtual void Shutdown() OVERRIDE;
+
+ protected:
+  // Returns true if policy should be loaded even when Gaia reports that the
+  // account doesn't have management enabled.
+  static bool ShouldForceLoadPolicy();
+
+  // Returns a CloudPolicyClient to perform a registration with the DM server,
+  // or NULL if |username| shouldn't register for policy management.
+  scoped_ptr<CloudPolicyClient> PrepareToRegister(const std::string& username);
+
+  // Returns false if cloud policy is disabled or if the passed |email_address|
+  // is definitely not from a hosted domain (according to the blacklist in
+  // BrowserPolicyConnector::IsNonEnterpriseUser()).
+  bool ShouldLoadPolicyForUser(const std::string& email_address);
+
+  // Invoked to initialize the UserPolicySigninService once its owning Profile
+  // becomes ready. If the Profile has a signed-in account associated with it
+  // at startup then this initializes the cloud policy manager by calling
+  // InitializeForSignedInUser(); otherwise it clears any stored policies.
+  void InitializeOnProfileReady();
+
+  // Invoked to initialize the cloud policy service for |username|, which is the
+  // account associated with the Profile that owns this service. This is invoked
+  // from InitializeOnProfileReady() if the Profile already has a signed-in
+  // account at startup, or (on the desktop platforms) as soon as the user
+  // signs-in and an OAuth2 login refresh token becomes available.
+  void InitializeForSignedInUser(const std::string& username);
+
+  // Initializes the cloud policy manager with the passed |client|. This is
+  // called from InitializeForSignedInUser() when the Profile already has a
+  // signed in account at startup, and from FetchPolicyForSignedInUser() during
+  // the initial policy fetch after signing in.
+  virtual void InitializeUserCloudPolicyManager(
+      scoped_ptr<CloudPolicyClient> client);
+
+  // Shuts down the UserCloudPolicyManager (for example, after the user signs
+  // out) and deletes any cached policy.
+  virtual void ShutdownUserCloudPolicyManager();
+
+  // Convenience helper to get the UserCloudPolicyManager for |profile_|.
+  UserCloudPolicyManager* GetManager();
+
+  Profile* profile() { return profile_; }
+  content::NotificationRegistrar* registrar() { return &registrar_; }
+
+ private:
+  // Weak pointer to the profile this service is associated with.
+  Profile* profile_;
+
+  content::NotificationRegistrar registrar_;
+
+  base::WeakPtrFactory<UserPolicySigninServiceBase> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(UserPolicySigninServiceBase);
+};
+
+}  // namespace policy
+
+#endif  // CHROME_BROWSER_POLICY_CLOUD_USER_POLICY_SIGNIN_SERVICE_BASE_H_
diff --git a/chrome/browser/policy/cloud/user_policy_signin_service_factory.cc b/chrome/browser/policy/cloud/user_policy_signin_service_factory.cc
index 3125feb..8461391 100644
--- a/chrome/browser/policy/cloud/user_policy_signin_service_factory.cc
+++ b/chrome/browser/policy/cloud/user_policy_signin_service_factory.cc
@@ -6,21 +6,28 @@
 
 #include "base/prefs/pref_service.h"
 #include "chrome/browser/policy/cloud/user_cloud_policy_manager_factory.h"
-#include "chrome/browser/policy/cloud/user_policy_signin_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
-#include "chrome/browser/signin/token_service_factory.h"
 #include "chrome/common/pref_names.h"
 #include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
 #include "components/user_prefs/pref_registry_syncable.h"
 
+#if defined(OS_ANDROID)
+#include "chrome/browser/policy/cloud/user_policy_signin_service_android.h"
+#else
+#include "chrome/browser/policy/cloud/user_policy_signin_service.h"
+#include "chrome/browser/signin/token_service_factory.h"
+#endif
+
 namespace policy {
 
 UserPolicySigninServiceFactory::UserPolicySigninServiceFactory()
     : BrowserContextKeyedServiceFactory(
         "UserPolicySigninService",
         BrowserContextDependencyManager::GetInstance()) {
+#if !defined(OS_ANDROID)
   DependsOn(TokenServiceFactory::GetInstance());
+#endif
   DependsOn(SigninManagerFactory::GetInstance());
   DependsOn(UserCloudPolicyManagerFactory::GetInstance());
 }
diff --git a/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc b/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc
index 1dc0afd..7954e17 100644
--- a/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc
+++ b/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc
@@ -2,27 +2,23 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/command_line.h"
 #include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
 #include "base/message_loop.h"
 #include "base/prefs/pref_service.h"
 #include "base/run_loop.h"
+#include "chrome/browser/browser_process.h"
 #include "chrome/browser/policy/browser_policy_connector.h"
 #include "chrome/browser/policy/cloud/cloud_policy_constants.h"
 #include "chrome/browser/policy/cloud/mock_device_management_service.h"
 #include "chrome/browser/policy/cloud/mock_user_cloud_policy_store.h"
 #include "chrome/browser/policy/cloud/user_cloud_policy_manager.h"
-#include "chrome/browser/policy/cloud/user_policy_signin_service.h"
 #include "chrome/browser/policy/cloud/user_policy_signin_service_factory.h"
 #include "chrome/browser/prefs/browser_prefs.h"
 #include "chrome/browser/signin/fake_signin_manager.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
-#include "chrome/browser/signin/token_service.h"
-#include "chrome/browser/signin/token_service_factory.h"
 #include "chrome/common/chrome_notification_types.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_pref_service_syncable.h"
 #include "chrome/test/base/testing_profile.h"
@@ -38,6 +34,14 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+#if defined(OS_ANDROID)
+#include "chrome/browser/policy/cloud/user_policy_signin_service_android.h"
+#else
+#include "chrome/browser/policy/cloud/user_policy_signin_service.h"
+#include "chrome/browser/signin/token_service.h"
+#include "chrome/browser/signin/token_service_factory.h"
+#endif
+
 namespace em = enterprise_management;
 
 using testing::AnyNumber;
@@ -48,19 +52,18 @@
 
 namespace {
 
-static const char kValidTokenResponse[] =
+const char kValidTokenResponse[] =
     "{"
     "  \"access_token\": \"at1\","
     "  \"expires_in\": 3600,"
     "  \"token_type\": \"Bearer\""
     "}";
 
-static const char kHostedDomainResponse[] =
+const char kHostedDomainResponse[] =
     "{"
     "  \"hd\": \"test.com\""
     "}";
 
-namespace {
 class SigninManagerFake : public FakeSigninManager {
  public:
   explicit SigninManagerFake(Profile* profile)
@@ -78,7 +81,6 @@
     return new SigninManagerFake(static_cast<Profile*>(profile));
   }
 };
-}  // namespace
 
 class UserPolicySigninServiceTest : public testing::Test {
  public:
@@ -90,6 +92,7 @@
         register_completed_(false) {}
 
   MOCK_METHOD1(OnPolicyRefresh, void(bool));
+
   void OnRegisterCompleted(scoped_ptr<CloudPolicyClient> client) {
     register_completed_ = true;
     created_client_.swap(client);
@@ -112,8 +115,7 @@
 
     local_state_.reset(new TestingPrefServiceSimple);
     chrome::RegisterLocalState(local_state_->registry());
-    TestingBrowserProcess::GetGlobal()->SetLocalState(
-        local_state_.get());
+    TestingBrowserProcess::GetGlobal()->SetLocalState(local_state_.get());
 
     scoped_refptr<net::URLRequestContextGetter> system_request_context;
     g_browser_process->browser_policy_connector()->Init(
@@ -181,8 +183,10 @@
     EXPECT_CALL(*this, OnPolicyRefresh(true)).Times(0);
     RegisterPolicyClientWithCallback(signin_service);
 
+#if !defined(OS_ANDROID)
     // Mimic successful oauth token fetch.
     MakeOAuthTokenFetchSucceed();
+#endif
 
     // When the user is from a hosted domain, this should kick off client
     // registration.
@@ -303,6 +307,11 @@
   ASSERT_FALSE(manager_->core()->service());
 }
 
+  // TODO(joaodasilva): these tests rely on issuing the OAuth2 login refresh
+  // token after signin. Revisit this after figuring how to handle that on
+  // Android.
+#if !defined(OS_ANDROID)
+
 TEST_F(UserPolicySigninServiceTest, InitWhileSignedIn) {
   // Set the user as signed in.
   SigninManagerFactory::GetForProfile(profile_.get())->SetAuthenticatedUsername(
@@ -465,6 +474,8 @@
   ASSERT_FALSE(IsRequestActive());
 }
 
+#endif  // !defined(OS_ANDROID)
+
 TEST_F(UserPolicySigninServiceTest, SignOutAfterInit) {
   EXPECT_CALL(*mock_store_, Clear());
   // Set the user as signed in.
@@ -516,12 +527,15 @@
   ASSERT_FALSE(manager_->core()->service());
   ASSERT_TRUE(IsRequestActive());
 
+#if !defined(OS_ANDROID)
   // Cause the access token request to succeed.
   MakeOAuthTokenFetchSucceed();
 
   // Should be a follow-up fetch to check the hosted-domain status.
   ASSERT_TRUE(IsRequestActive());
   Mock::VerifyAndClearExpectations(this);
+#endif
+
   EXPECT_FALSE(register_completed_);
 
   // Report that the user is not on a hosted domain - callback should be
@@ -543,8 +557,11 @@
   // UserCloudPolicyManager should not be initialized.
   ASSERT_FALSE(manager_->core()->service());
 
+#if !defined(OS_ANDROID)
   // Mimic successful oauth token fetch.
   MakeOAuthTokenFetchSucceed();
+#endif
+
   EXPECT_FALSE(register_completed_);
 
   // When the user is from a hosted domain, this should kick off client
@@ -578,8 +595,10 @@
       UserPolicySigninServiceFactory::GetForProfile(profile_.get());
   RegisterPolicyClientWithCallback(signin_service);
 
+#if !defined(OS_ANDROID)
   // Mimic successful oauth token fetch.
   MakeOAuthTokenFetchSucceed();
+#endif
 
   // When the user is from a hosted domain, this should kick off client
   // registration.
@@ -643,21 +662,22 @@
 }
 
 TEST_F(UserPolicySigninServiceTest, FetchPolicySuccess) {
-  TestSuccessfulSignin();
+  ASSERT_NO_FATAL_FAILURE(TestSuccessfulSignin());
 }
 
 TEST_F(UserPolicySigninServiceTest, SignOutThenSignInAgain) {
-  TestSuccessfulSignin();
+  ASSERT_NO_FATAL_FAILURE(TestSuccessfulSignin());
 
+  EXPECT_CALL(*mock_store_, Clear());
   signin_manager_->ForceSignOut();
   ASSERT_FALSE(manager_->core()->service());
 
   // Now sign in again.
-  TestSuccessfulSignin();
+  ASSERT_NO_FATAL_FAILURE(TestSuccessfulSignin());
 }
 
 TEST_F(UserPolicySigninServiceTest, PolicyFetchFailureTemporary) {
-  TestSuccessfulSignin();
+  ASSERT_NO_FATAL_FAILURE(TestSuccessfulSignin());
 
   ASSERT_TRUE(manager_->IsClientRegistered());
 
@@ -680,10 +700,12 @@
 }
 
 TEST_F(UserPolicySigninServiceTest, PolicyFetchFailureDisableManagement) {
-  TestSuccessfulSignin();
+  ASSERT_NO_FATAL_FAILURE(TestSuccessfulSignin());
 
   EXPECT_TRUE(manager_->IsClientRegistered());
+#if !defined(OS_ANDROID)
   EXPECT_TRUE(signin_manager_->IsSignoutProhibited());
+#endif
 
   // Kick off another policy fetch.
   MockDeviceManagementJob* fetch_request = NULL;
@@ -703,7 +725,9 @@
                               em::DeviceManagementResponse());
   base::RunLoop().RunUntilIdle();
   EXPECT_FALSE(manager_->IsClientRegistered());
+#if !defined(OS_ANDROID)
   EXPECT_FALSE(signin_manager_->IsSignoutProhibited());
+#endif
 }
 
 }  // namespace
diff --git a/chrome/browser/policy/configuration_policy_handler.cc b/chrome/browser/policy/configuration_policy_handler.cc
index be6524f..d3e2c89 100644
--- a/chrome/browser/policy/configuration_policy_handler.cc
+++ b/chrome/browser/policy/configuration_policy_handler.cc
@@ -29,9 +29,9 @@
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/pref_names.h"
 #include "content/public/browser/notification_service.h"
-#include "googleurl/src/gurl.h"
 #include "grit/generated_resources.h"
 #include "policy/policy_constants.h"
+#include "url/gurl.h"
 
 #if !defined(OS_ANDROID)
 #include "chrome/browser/policy/policy_path_parser.h"
@@ -292,6 +292,8 @@
 void StringToIntEnumListPolicyHandler::ApplyPolicySettings(
     const PolicyMap& policies,
     PrefValueMap* prefs) {
+  if (!pref_path_)
+    return;
   const base::Value* value = policies.GetValue(policy_name());
   scoped_ptr<base::ListValue> list(new base::ListValue());
   if (value && Convert(value, list.get(), NULL))
@@ -360,6 +362,8 @@
 
 void IntRangePolicyHandler::ApplyPolicySettings(const PolicyMap& policies,
                                                 PrefValueMap* prefs) {
+  if (!pref_path_)
+    return;
   const base::Value* value = policies.GetValue(policy_name());
   int value_in_range;
   if (value && EnsureInRange(value, &value_in_range, NULL)) {
@@ -386,6 +390,8 @@
 void IntPercentageToDoublePolicyHandler::ApplyPolicySettings(
     const PolicyMap& policies,
     PrefValueMap* prefs) {
+  if (!pref_path_)
+    return;
   const base::Value* value = policies.GetValue(policy_name());
   int percentage;
   if (value && EnsureInRange(value, &percentage, NULL)) {
@@ -616,6 +622,8 @@
 void ExtensionURLPatternListPolicyHandler::ApplyPolicySettings(
     const PolicyMap& policies,
     PrefValueMap* prefs) {
+  if (!pref_path_)
+    return;
   const Value* value = policies.GetValue(policy_name());
   if (value)
     prefs->SetValue(pref_path_, value->DeepCopy());
@@ -636,6 +644,8 @@
 
 void SimplePolicyHandler::ApplyPolicySettings(const PolicyMap& policies,
                                               PrefValueMap* prefs) {
+  if (!pref_path_)
+    return;
   const Value* value = policies.GetValue(policy_name());
   if (value)
     prefs->SetValue(pref_path_, value->DeepCopy());
diff --git a/chrome/browser/policy/configuration_policy_handler_list.cc b/chrome/browser/policy/configuration_policy_handler_list.cc
index 2baabf1..c0b3fc5 100644
--- a/chrome/browser/policy/configuration_policy_handler_list.cc
+++ b/chrome/browser/policy/configuration_policy_handler_list.cc
@@ -18,6 +18,7 @@
 #include "policy/policy_constants.h"
 
 #if defined(OS_CHROMEOS)
+#include "ash/magnifier/magnifier_constants.h"
 #include "chrome/browser/chromeos/policy/configuration_policy_handler_chromeos.h"
 #endif  // defined(OS_CHROMEOS)
 
@@ -330,6 +331,9 @@
   { key::kContentPackManualBehaviorURLs,
     prefs::kManagedModeManualURLs,
     Value::TYPE_DICTIONARY },
+  { key::kSupervisedUserCreationEnabled,
+    prefs::kManagedUserCreationAllowed,
+    Value::TYPE_BOOLEAN },
 
 #if defined(OS_CHROMEOS)
   { key::kChromeOsLockOnIdleSuspend,
@@ -383,6 +387,15 @@
   { key::kHighContrastEnabled,
     prefs::kHighContrastEnabled,
     Value::TYPE_BOOLEAN },
+  { key::kDeviceLoginScreenDefaultLargeCursorEnabled,
+    NULL,
+    Value::TYPE_BOOLEAN },
+  { key::kDeviceLoginScreenDefaultSpokenFeedbackEnabled,
+    NULL,
+    Value::TYPE_BOOLEAN },
+  { key::kDeviceLoginScreenDefaultHighContrastEnabled,
+    NULL,
+    Value::TYPE_BOOLEAN },
   { key::kRebootAfterUpdate,
     prefs::kRebootAfterUpdate,
     Value::TYPE_BOOLEAN },
@@ -517,8 +530,13 @@
           0, INT_MAX, true));
   handlers_.push_back(
       new IntRangePolicyHandler(
-          key::kIdleAction,
-          prefs::kPowerIdleAction,
+          key::kIdleActionAC,
+          prefs::kPowerAcIdleAction,
+          0, 3, false));
+  handlers_.push_back(
+      new IntRangePolicyHandler(
+          key::kIdleActionBattery,
+          prefs::kPowerBatteryIdleAction,
           0, 3, false));
   handlers_.push_back(
       new IntRangePolicyHandler(
@@ -527,8 +545,8 @@
           0, 3, false));
   handlers_.push_back(
       new IntPercentageToDoublePolicyHandler(
-          key::kPresentationIdleDelayScale,
-          prefs::kPowerPresentationIdleDelayFactor,
+          key::kPresentationScreenDimDelayScale,
+          prefs::kPowerPresentationScreenDimDelayFactor,
           100, INT_MAX, true));
   handlers_.push_back(
       new IntPercentageToDoublePolicyHandler(
@@ -538,6 +556,10 @@
   handlers_.push_back(new IntRangePolicyHandler(key::kUptimeLimit,
                                                 prefs::kUptimeLimit,
                                                 3600, INT_MAX, true));
+  handlers_.push_back(new IntRangePolicyHandler(
+      key::kDeviceLoginScreenDefaultScreenMagnifierType,
+      NULL,
+      0, ash::MAGNIFIER_FULL, false));
 #endif  // defined(OS_CHROMEOS)
 }
 
diff --git a/chrome/browser/policy/managed_mode_policy_provider.cc b/chrome/browser/policy/managed_mode_policy_provider.cc
index ecd51c9..ec6fba6 100644
--- a/chrome/browser/policy/managed_mode_policy_provider.cc
+++ b/chrome/browser/policy/managed_mode_policy_provider.cc
@@ -7,7 +7,7 @@
 #include "base/json/json_reader.h"
 #include "base/json/json_writer.h"
 #include "base/prefs/json_pref_store.h"
-#include "base/string_util.h"
+#include "base/strings/string_util.h"
 #include "base/threading/sequenced_worker_pool.h"
 #include "chrome/browser/managed_mode/managed_mode_url_filter.h"
 #include "chrome/browser/policy/policy_bundle.h"
diff --git a/chrome/browser/policy/managed_mode_policy_provider_unittest.cc b/chrome/browser/policy/managed_mode_policy_provider_unittest.cc
index 685f3ff..5b0d661 100644
--- a/chrome/browser/policy/managed_mode_policy_provider_unittest.cc
+++ b/chrome/browser/policy/managed_mode_policy_provider_unittest.cc
@@ -67,7 +67,10 @@
 syncer::SyncError MockSyncErrorFactory::CreateAndUploadError(
     const tracked_objects::Location& location,
     const std::string& message) {
-  return syncer::SyncError(location, message, type_);
+  return syncer::SyncError(location,
+                           syncer::SyncError::DATATYPE_ERROR,
+                           message,
+                           type_);
 }
 
 class TestHarness : public PolicyProviderTestHarness {
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc
index 6e87fb7..f10972e 100644
--- a/chrome/browser/policy/policy_browsertest.cc
+++ b/chrome/browser/policy/policy_browsertest.cc
@@ -22,7 +22,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/test_file_util.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/autocomplete/autocomplete_controller.h"
@@ -101,7 +101,6 @@
 #include "content/public/test/test_utils.h"
 #include "content/test/net/url_request_failed_job.h"
 #include "content/test/net/url_request_mock_http_job.h"
-#include "googleurl/src/gurl.h"
 #include "grit/generated_resources.h"
 #include "net/base/net_errors.h"
 #include "net/base/net_util.h"
@@ -115,6 +114,7 @@
 #include "third_party/WebKit/public/web/WebInputEvent.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
+#include "url/gurl.h"
 #include "webkit/plugins/npapi/plugin_utils.h"
 #include "webkit/plugins/plugin_constants.h"
 #include "webkit/plugins/webplugininfo.h"
@@ -1499,20 +1499,19 @@
 IN_PROC_BROWSER_TEST_F(PolicyTest, IncognitoEnabled) {
   // Verifies that incognito windows can't be opened when disabled by policy.
 
-  // Only test this on the native desktop.
-  const BrowserList* native_browser_list =
-      BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_NATIVE);
+  const BrowserList* active_browser_list =
+      BrowserList::GetInstance(chrome::GetActiveDesktop());
 
   // Disable incognito via policy and verify that incognito windows can't be
   // opened.
-  EXPECT_EQ(1u, native_browser_list->size());
+  EXPECT_EQ(1u, active_browser_list->size());
   EXPECT_FALSE(BrowserList::IsOffTheRecordSessionActive());
   PolicyMap policies;
   policies.Set(key::kIncognitoEnabled, POLICY_LEVEL_MANDATORY,
                POLICY_SCOPE_USER, base::Value::CreateBooleanValue(false));
   UpdateProviderPolicy(policies);
   EXPECT_FALSE(chrome::ExecuteCommand(browser(), IDC_NEW_INCOGNITO_WINDOW));
-  EXPECT_EQ(1u, native_browser_list->size());
+  EXPECT_EQ(1u, active_browser_list->size());
   EXPECT_FALSE(BrowserList::IsOffTheRecordSessionActive());
 
   // Enable via policy and verify that incognito windows can be opened.
@@ -1520,7 +1519,7 @@
                POLICY_SCOPE_USER, base::Value::CreateBooleanValue(true));
   UpdateProviderPolicy(policies);
   EXPECT_TRUE(chrome::ExecuteCommand(browser(), IDC_NEW_INCOGNITO_WINDOW));
-  EXPECT_EQ(2u, native_browser_list->size());
+  EXPECT_EQ(2u, active_browser_list->size());
   EXPECT_TRUE(BrowserList::IsOffTheRecordSessionActive());
 }
 
diff --git a/chrome/browser/policy/policy_loader_mac.cc b/chrome/browser/policy/policy_loader_mac.cc
index 761a7a6..0cbb519 100644
--- a/chrome/browser/policy/policy_loader_mac.cc
+++ b/chrome/browser/policy/policy_loader_mac.cc
@@ -23,7 +23,7 @@
 #include "policy/policy_constants.h"
 
 using base::mac::CFCast;
-using base::mac::ScopedCFTypeRef;
+using base::ScopedCFTypeRef;
 
 namespace policy {
 
@@ -108,9 +108,9 @@
   bool policy_present = false;
   const PolicyDefinitionList::Entry* current;
   for (current = policy_list_->begin; current != policy_list_->end; ++current) {
-    base::mac::ScopedCFTypeRef<CFStringRef> name(
+    base::ScopedCFTypeRef<CFStringRef> name(
         base::SysUTF8ToCFStringRef(current->name));
-    base::mac::ScopedCFTypeRef<CFPropertyListRef> value(
+    base::ScopedCFTypeRef<CFPropertyListRef> value(
         preferences_->CopyAppValue(name, kCFPreferencesCurrentApplication));
     if (!value.get())
       continue;
@@ -234,7 +234,7 @@
   if (!schema)
     return;
 
-  base::mac::ScopedCFTypeRef<CFStringRef> bundle_id(
+  base::ScopedCFTypeRef<CFStringRef> bundle_id(
       base::SysUTF8ToCFStringRef(bundle_id_string));
   preferences_->AppSynchronize(bundle_id);
 
@@ -246,9 +246,9 @@
 
   for (PolicySchemaMap::const_iterator it = map->begin();
        it != map->end(); ++it) {
-    base::mac::ScopedCFTypeRef<CFStringRef> pref_name(
+    base::ScopedCFTypeRef<CFStringRef> pref_name(
         base::SysUTF8ToCFStringRef(it->first));
-    base::mac::ScopedCFTypeRef<CFPropertyListRef> value(
+    base::ScopedCFTypeRef<CFPropertyListRef> value(
         preferences_->CopyAppValue(pref_name, bundle_id));
     if (!value.get())
       continue;
diff --git a/chrome/browser/policy/policy_loader_mac_unittest.cc b/chrome/browser/policy/policy_loader_mac_unittest.cc
index a5b1f6a..12c21bd 100644
--- a/chrome/browser/policy/policy_loader_mac_unittest.cc
+++ b/chrome/browser/policy/policy_loader_mac_unittest.cc
@@ -17,7 +17,7 @@
 #include "policy/policy_constants.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-using base::mac::ScopedCFTypeRef;
+using base::ScopedCFTypeRef;
 
 namespace policy {
 
diff --git a/chrome/browser/policy/policy_map.h b/chrome/browser/policy/policy_map.h
index 60524bb..3d12fc3 100644
--- a/chrome/browser/policy/policy_map.h
+++ b/chrome/browser/policy/policy_map.h
@@ -23,7 +23,7 @@
   struct Entry {
     PolicyLevel level;
     PolicyScope scope;
-    Value* value;
+    base::Value* value;
 
     Entry()
         : level(POLICY_LEVEL_RECOMMENDED),
@@ -50,14 +50,14 @@
   // Returns a weak reference to the value currently stored for key |policy|,
   // or NULL if not found. Ownership is retained by the PolicyMap.
   // This is equivalent to Get(policy)->value, when it doesn't return NULL.
-  const Value* GetValue(const std::string& policy) const;
+  const base::Value* GetValue(const std::string& policy) const;
 
   // Takes ownership of |value|. Overwrites any existing value stored in the
   // map for the key |policy|.
   void Set(const std::string& policy,
            PolicyLevel level,
            PolicyScope scope,
-           Value* value);
+           base::Value* value);
 
   // Erase the given |policy|, if it exists in this map.
   void Erase(const std::string& policy);
@@ -80,7 +80,7 @@
   // Loads the values in |policies| into this PolicyMap. All policies loaded
   // will have |level| and |scope| in their entries. Existing entries are
   // replaced.
-  void LoadFrom(const DictionaryValue* policies,
+  void LoadFrom(const base::DictionaryValue* policies,
                 PolicyLevel level,
                 PolicyScope scope);
 
diff --git a/chrome/browser/policy/policy_prefs_browsertest.cc b/chrome/browser/policy/policy_prefs_browsertest.cc
index 01ceece..689b40a 100644
--- a/chrome/browser/policy/policy_prefs_browsertest.cc
+++ b/chrome/browser/policy/policy_prefs_browsertest.cc
@@ -32,10 +32,10 @@
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test_utils.h"
-#include "googleurl/src/gurl.h"
 #include "policy/policy_constants.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 using testing::AnyNumber;
 using testing::Return;
diff --git a/chrome/browser/policy/policy_service_impl_unittest.cc b/chrome/browser/policy/policy_service_impl_unittest.cc
index 68026ca..f5efb78 100644
--- a/chrome/browser/policy/policy_service_impl_unittest.cc
+++ b/chrome/browser/policy/policy_service_impl_unittest.cc
@@ -630,10 +630,10 @@
 }
 
 TEST_F(PolicyServiceTest, RegisterPolicyDomain) {
-  EXPECT_FALSE(
-      policy_service_->GetPolicyDomainDescriptor(POLICY_DOMAIN_CHROME));
-  EXPECT_FALSE(
-      policy_service_->GetPolicyDomainDescriptor(POLICY_DOMAIN_EXTENSIONS));
+  EXPECT_FALSE(policy_service_->GetPolicyDomainDescriptor(POLICY_DOMAIN_CHROME)
+                   .get());
+  EXPECT_FALSE(policy_service_->GetPolicyDomainDescriptor(
+      POLICY_DOMAIN_EXTENSIONS).get());
 
   EXPECT_CALL(provider1_, RegisterPolicyDomain(_)).Times(AnyNumber());
   EXPECT_CALL(provider2_, RegisterPolicyDomain(_)).Times(AnyNumber());
@@ -644,9 +644,10 @@
   policy_service_->RegisterPolicyDomain(chrome_descriptor);
   Mock::VerifyAndClearExpectations(&provider0_);
 
-  EXPECT_TRUE(policy_service_->GetPolicyDomainDescriptor(POLICY_DOMAIN_CHROME));
-  EXPECT_FALSE(
-      policy_service_->GetPolicyDomainDescriptor(POLICY_DOMAIN_EXTENSIONS));
+  EXPECT_TRUE(policy_service_->GetPolicyDomainDescriptor(POLICY_DOMAIN_CHROME)
+                  .get());
+  EXPECT_FALSE(policy_service_->GetPolicyDomainDescriptor(
+      POLICY_DOMAIN_EXTENSIONS).get());
 
   // Register another namespace.
   std::string error;
@@ -672,9 +673,10 @@
   policy_service_->RegisterPolicyDomain(extensions_descriptor);
   Mock::VerifyAndClearExpectations(&provider0_);
 
-  EXPECT_TRUE(policy_service_->GetPolicyDomainDescriptor(POLICY_DOMAIN_CHROME));
-  EXPECT_TRUE(
-      policy_service_->GetPolicyDomainDescriptor(POLICY_DOMAIN_EXTENSIONS));
+  EXPECT_TRUE(policy_service_->GetPolicyDomainDescriptor(POLICY_DOMAIN_CHROME)
+                  .get());
+  EXPECT_TRUE(policy_service_->GetPolicyDomainDescriptor(
+      POLICY_DOMAIN_EXTENSIONS).get());
 
   // Remove those components.
   scoped_refptr<PolicyDomainDescriptor> empty_extensions_descriptor =
diff --git a/chrome/browser/policy/policy_statistics_collector.h b/chrome/browser/policy/policy_statistics_collector.h
index 08a7c92..352a591 100644
--- a/chrome/browser/policy/policy_statistics_collector.h
+++ b/chrome/browser/policy/policy_statistics_collector.h
@@ -8,7 +8,7 @@
 #include "base/basictypes.h"
 #include "base/cancelable_callback.h"
 #include "base/memory/ref_counted.h"
-#include "base/time.h"
+#include "base/time/time.h"
 
 class PrefService;
 class PrefRegistrySimple;
diff --git a/chrome/browser/policy/policy_statistics_collector_unittest.cc b/chrome/browser/policy/policy_statistics_collector_unittest.cc
index 20e1319..06a68ca 100644
--- a/chrome/browser/policy/policy_statistics_collector_unittest.cc
+++ b/chrome/browser/policy/policy_statistics_collector_unittest.cc
@@ -10,7 +10,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/prefs/testing_pref_service.h"
 #include "base/test/test_simple_task_runner.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/policy/mock_policy_service.h"
 #include "chrome/browser/policy/policy_map.h"
diff --git a/chrome/browser/policy/preferences_mock_mac.h b/chrome/browser/policy/preferences_mock_mac.h
index 02a4d92..0f6fef1 100644
--- a/chrome/browser/policy/preferences_mock_mac.h
+++ b/chrome/browser/policy/preferences_mock_mac.h
@@ -26,8 +26,8 @@
   void AddTestItem(CFStringRef key, CFPropertyListRef value, bool is_forced);
 
  private:
-  base::mac::ScopedCFTypeRef<CFMutableDictionaryRef> values_;
-  base::mac::ScopedCFTypeRef<CFMutableSetRef> forced_;
+  base::ScopedCFTypeRef<CFMutableDictionaryRef> values_;
+  base::ScopedCFTypeRef<CFMutableSetRef> forced_;
 };
 
 #endif  // CHROME_BROWSER_POLICY_PREFERENCES_MOCK_MAC_H_
diff --git a/chrome/browser/policy/profile_policy_connector.cc b/chrome/browser/policy/profile_policy_connector.cc
index f9f339a..65b95e5 100644
--- a/chrome/browser/policy/profile_policy_connector.cc
+++ b/chrome/browser/policy/profile_policy_connector.cc
@@ -22,10 +22,12 @@
 #include "chrome/browser/chromeos/login/user.h"
 #include "chrome/browser/chromeos/login/user_manager.h"
 #include "chrome/browser/chromeos/policy/device_local_account_policy_provider.h"
+#include "chrome/browser/chromeos/policy/login_profile_policy_provider.h"
 #include "chrome/browser/chromeos/policy/network_configuration_updater.h"
 #include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h"
 #include "chrome/browser/chromeos/policy/user_cloud_policy_manager_factory_chromeos.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chrome/browser/policy/policy_service.h"
 #include "chrome/common/pref_names.h"
 #include "chromeos/dbus/cryptohome_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
@@ -60,26 +62,33 @@
   if (cloud_policy_manager)
     providers.push_back(cloud_policy_manager);
 
-  bool is_managed = false;
+  bool allow_trusted_certs_from_policy = false;
   std::string username;
-  if (!chromeos::ProfileHelper::IsSigninProfile(profile_)) {
+  if (chromeos::ProfileHelper::IsSigninProfile(profile_)) {
+    special_user_policy_provider_.reset(new LoginProfilePolicyProvider(
+        connector->GetPolicyService()));
+    special_user_policy_provider_->Init();
+  } else {
     // |user| should never be NULL except for the signin profile.
     // TODO(joaodasilva): get the |user| that corresponds to the |profile_|
     // from the ProfileHelper, once that's ready.
     chromeos::UserManager* user_manager = chromeos::UserManager::Get();
     chromeos::User* user = user_manager->GetActiveUser();
     CHECK(user);
-    // Check if |user| is managed, and if it's a public account.
     username = user->email();
-    is_managed =
-        connector->GetUserAffiliation(username) == USER_AFFILIATION_MANAGED;
     is_primary_user_ =
         chromeos::UserManager::Get()->GetLoggedInUsers().size() == 1;
     if (user->GetType() == chromeos::User::USER_TYPE_PUBLIC_ACCOUNT)
       InitializeDeviceLocalAccountPolicyProvider(username);
-    if (device_local_account_policy_provider_)
-      providers.push_back(device_local_account_policy_provider_.get());
+    // Allow trusted certs from policy only for managed regular accounts.
+    const bool is_managed =
+        connector->GetUserAffiliation(username) == USER_AFFILIATION_MANAGED;
+    if (is_managed && user->GetType() == chromeos::User::USER_TYPE_REGULAR)
+      allow_trusted_certs_from_policy = true;
   }
+  if (special_user_policy_provider_)
+    providers.push_back(special_user_policy_provider_.get());
+
 #else
   UserCloudPolicyManager* cloud_policy_manager =
       UserCloudPolicyManagerFactory::GetForProfile(profile_);
@@ -98,12 +107,10 @@
 
 #if defined(OS_CHROMEOS)
   if (is_primary_user_) {
-    if (cloud_policy_manager) {
+    if (cloud_policy_manager)
       connector->SetUserPolicyDelegate(cloud_policy_manager);
-    } else if (device_local_account_policy_provider_) {
-      connector->SetUserPolicyDelegate(
-          device_local_account_policy_provider_.get());
-    }
+    else if (special_user_policy_provider_)
+      connector->SetUserPolicyDelegate(special_user_policy_provider_.get());
 
     chromeos::CryptohomeClient* cryptohome_client =
         chromeos::DBusThreadManager::Get()->GetCryptohomeClient();
@@ -112,7 +119,7 @@
         base::Bind(
             &ProfilePolicyConnector::InitializeNetworkConfigurationUpdater,
             weak_ptr_factory_.GetWeakPtr(),
-            is_managed));
+            allow_trusted_certs_from_policy));
   }
 #endif
 }
@@ -127,12 +134,10 @@
     BrowserPolicyConnector* connector =
         g_browser_process->browser_policy_connector();
     connector->SetUserPolicyDelegate(NULL);
-    NetworkConfigurationUpdater* network_updater =
-        connector->GetNetworkConfigurationUpdater();
-    network_updater->UnsetUserPolicyService();
+    connector->network_configuration_updater()->UnsetUserPolicyService();
   }
-  if (device_local_account_policy_provider_)
-    device_local_account_policy_provider_->Shutdown();
+  if (special_user_policy_provider_)
+    special_user_policy_provider_->Shutdown();
 #endif
 
 #if defined(ENABLE_MANAGED_USERS)
@@ -158,25 +163,21 @@
       connector->GetDeviceLocalAccountPolicyService();
   if (!device_local_account_policy_service)
     return;
-  device_local_account_policy_provider_.reset(
-      new DeviceLocalAccountPolicyProvider(
-          username, device_local_account_policy_service));
-  device_local_account_policy_provider_->Init();
+  special_user_policy_provider_.reset(new DeviceLocalAccountPolicyProvider(
+      username, device_local_account_policy_service));
+  special_user_policy_provider_->Init();
 }
 
 void ProfilePolicyConnector::InitializeNetworkConfigurationUpdater(
-    bool is_managed,
+    bool allow_trusted_certs_from_policy,
     chromeos::DBusMethodCallStatus status,
     const std::string& hashed_username) {
   // TODO(joaodasilva): create the NetworkConfigurationUpdater for user ONC
   // here, after splitting that class into an instance for device policy and
   // another per profile for user policy.
-  BrowserPolicyConnector* connector =
-      g_browser_process->browser_policy_connector();
-  NetworkConfigurationUpdater* network_updater =
-      connector->GetNetworkConfigurationUpdater();
-  network_updater->SetUserPolicyService(
-      is_managed, hashed_username, policy_service());
+  g_browser_process->browser_policy_connector()->
+      network_configuration_updater()->SetUserPolicyService(
+          allow_trusted_certs_from_policy, hashed_username, policy_service());
 }
 #endif
 
diff --git a/chrome/browser/policy/profile_policy_connector.h b/chrome/browser/policy/profile_policy_connector.h
index 0669c7d..a7d726d 100644
--- a/chrome/browser/policy/profile_policy_connector.h
+++ b/chrome/browser/policy/profile_policy_connector.h
@@ -24,7 +24,7 @@
 
 namespace policy {
 
-class DeviceLocalAccountPolicyProvider;
+class ConfigurationPolicyProvider;
 class ManagedModePolicyProvider;
 class PolicyService;
 
@@ -82,8 +82,7 @@
   // local state.
   bool is_primary_user_;
 
-  scoped_ptr<DeviceLocalAccountPolicyProvider>
-      device_local_account_policy_provider_;
+  scoped_ptr<ConfigurationPolicyProvider> special_user_policy_provider_;
 #endif
 
 #if defined(ENABLE_MANAGED_USERS) && defined(ENABLE_CONFIGURATION_POLICY)
diff --git a/chrome/browser/policy/proto/chromeos/chrome_device_policy.proto b/chrome/browser/policy/proto/chromeos/chrome_device_policy.proto
index 5d83a8a..65fe798 100644
--- a/chrome/browser/policy/proto/chromeos/chrome_device_policy.proto
+++ b/chrome/browser/policy/proto/chromeos/chrome_device_policy.proto
@@ -347,6 +347,72 @@
   optional bool attestation_enabled = 1;
 }
 
+message AccessibilitySettingsProto {
+  // Sets the default state of the large cursor accessibility feature on the
+  // login screen. If this policy is set to true, the large cursor will be
+  // enabled when the login screen is shown. If this policy is set to false, the
+  // large cursor will be disabled when the login screen is shown. Users can
+  // temporarily override this setting by enabling or disabling the large
+  // cursor. However, the user's choice is not persistent and the default is
+  // restored whenever the login screen is shown anew or the user remains idle
+  // on the login screen for a minute. If this policy is left unset, the large
+  // cursor is disabled when the login screen is first shown. Users can enable
+  // or disable the large cursor anytime and its status on the login screen is
+  // persisted between users.
+  optional bool login_screen_default_large_cursor_enabled = 1;
+
+  // Sets the default state of the spoken feedback accessibility feature on the
+  // login screen. If this policy is set to true, spoken feedback will be
+  // enabled when the login screen is shown. If this policy is set to false,
+  // spoken feedback will be disabled when the login screen is shown. Users can
+  // temporarily override this setting by enabling or disabling spoken feedback.
+  // However, the user's choice is not persistent and the default is restored
+  // whenever the login screen is shown anew or the user remains idle on the
+  // login screen for a minute. If this policy is left unset, spoken feedback is
+  // disabled when the login screen is first shown. Users can enable or disable
+  // spoken feedback anytime and its status on the login screen is persisted
+  // between users.
+  optional bool login_screen_default_spoken_feedback_enabled = 2;
+
+  // Sets the default state of the high contrast mode accessibility feature on
+  // the login screen. If this policy is set to true, high contrast mode will be
+  // enabled when the login screen is shown. If this policy is set to false,
+  // high contrast mode will be disabled when the login screen is shown. Users
+  // can temporarily override this setting by enabling or disabling high
+  // contrast mode. However, the user's choice is not persistent and the default
+  // is restored whenever the login screen is shown anew or the user remains
+  // idle on the login screen for a minute. If this policy is left unset, high
+  // contrast mode is disabled when the login screen is first shown. Users can
+  // enable or disable high contrast mode anytime and its status on the login
+  // screen is persisted between users.
+  optional bool login_screen_default_high_contrast_enabled = 3;
+
+  // Enumerates the screen magnifier types.
+  enum ScreenMagnifierType {
+    // Screen magnifier disabled.
+    SCREEN_MAGNIFIER_TYPE_NONE = 0;
+    // Full-screen magnifier enabled.
+    SCREEN_MAGNIFIER_TYPE_FULL = 1;
+  };
+
+  // Sets the default type of screen magnifier that is enabled on the login
+  // screen. If this policy is set, it controls the type of screen magnifier
+  // that is enabled when the login screen is shown. Users can temporarily
+  // override this setting by enabling or disabling the screen magnifier.
+  // However, the user's choice is not persistent and the default is restored
+  // whenever the login screen is shown anew or the user remains idle on the
+  // login screen for a minute. If this policy is left unset, the screen
+  // magnifier is disabled when the login screen is first shown. Users can
+  // enable or disable the screen magnifier anytime and its status on the login
+  // screen is persisted between users.
+  optional ScreenMagnifierType login_screen_default_screen_magnifier_type = 4;
+}
+
+message SupervisedUsersSettingsProto {
+  // Defines whether supervised users can be created on the device.
+  optional bool supervised_users_enabled = 1;
+}
+
 message ChromeDeviceSettingsProto {
   optional DevicePolicyRefreshRateProto device_policy_refresh_rate = 1;
   optional UserWhitelistProto user_whitelist = 2;
@@ -374,4 +440,6 @@
   optional UptimeLimitProto uptime_limit = 24;
   optional VariationsParameterProto variations_parameter = 25;
   optional AttestationSettingsProto attestation_settings = 26;
+  optional AccessibilitySettingsProto accessibility_settings = 27;
+  optional SupervisedUsersSettingsProto supervised_users_settings = 28;
 }
diff --git a/chrome/browser/policy/proto/cloud/device_management_backend.proto b/chrome/browser/policy/proto/cloud/device_management_backend.proto
index ab31bfe..2d1e856 100644
--- a/chrome/browser/policy/proto/cloud/device_management_backend.proto
+++ b/chrome/browser/policy/proto/cloud/device_management_backend.proto
@@ -238,6 +238,10 @@
   // Indicates which public account or extension/plug-in this policy data is
   // for. See PolicyFetchRequest.settings_entity_id for more details.
   optional string settings_entity_id = 11;
+
+  // Indicates the identity the device service account is associated with.
+  // This is only sent as part of device policy fetch.
+  optional string service_account_identity = 12;
 }
 
 message PolicyFetchResponse {
diff --git a/chrome/browser/policy/test/local_policy_test_server.h b/chrome/browser/policy/test/local_policy_test_server.h
index aaf6da0..7dbd2ef 100644
--- a/chrome/browser/policy/test/local_policy_test_server.h
+++ b/chrome/browser/policy/test/local_policy_test_server.h
@@ -12,8 +12,8 @@
 #include "base/files/file_path.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/values.h"
-#include "googleurl/src/gurl.h"
 #include "net/test/spawned_test_server/local_test_server.h"
+#include "url/gurl.h"
 
 namespace crypto {
 class RSAPrivateKey;
diff --git a/chrome/browser/policy/url_blacklist_manager.cc b/chrome/browser/policy/url_blacklist_manager.cc
index dd070b7..66a496e 100644
--- a/chrome/browser/policy/url_blacklist_manager.cc
+++ b/chrome/browser/policy/url_blacklist_manager.cc
@@ -20,10 +20,10 @@
 #include "content/public/browser/notification_source.h"
 #include "content/public/common/url_constants.h"
 #include "google_apis/gaia/gaia_urls.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/load_flags.h"
 #include "net/base/net_util.h"
 #include "net/url_request/url_request.h"
+#include "url/gurl.h"
 
 #if !defined(OS_CHROMEOS)
 #include "chrome/browser/signin/signin_manager.h"
diff --git a/chrome/browser/policy/url_blacklist_manager_unittest.cc b/chrome/browser/policy/url_blacklist_manager_unittest.cc
index a5afd49..977c659 100644
--- a/chrome/browser/policy/url_blacklist_manager_unittest.cc
+++ b/chrome/browser/policy/url_blacklist_manager_unittest.cc
@@ -13,10 +13,10 @@
 #include "chrome/common/pref_names.h"
 #include "content/public/test/test_browser_thread.h"
 #include "google_apis/gaia/gaia_urls.h"
-#include "googleurl/src/gurl.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_test_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 namespace policy {
 
diff --git a/chrome/browser/predictors/autocomplete_action_predictor.h b/chrome/browser/predictors/autocomplete_action_predictor.h
index 56adfa8..b1c4f97 100644
--- a/chrome/browser/predictors/autocomplete_action_predictor.h
+++ b/chrome/browser/predictors/autocomplete_action_predictor.h
@@ -18,7 +18,7 @@
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 struct AutocompleteMatch;
 class AutocompleteResult;
diff --git a/chrome/browser/predictors/autocomplete_action_predictor_table.h b/chrome/browser/predictors/autocomplete_action_predictor_table.h
index d6204c6..edde92b 100644
--- a/chrome/browser/predictors/autocomplete_action_predictor_table.h
+++ b/chrome/browser/predictors/autocomplete_action_predictor_table.h
@@ -10,7 +10,7 @@
 
 #include "base/strings/string16.h"
 #include "chrome/browser/predictors/predictor_table_base.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 namespace predictors {
 
diff --git a/chrome/browser/predictors/autocomplete_action_predictor_table_unittest.cc b/chrome/browser/predictors/autocomplete_action_predictor_table_unittest.cc
index f1f2b9e..d29086c 100644
--- a/chrome/browser/predictors/autocomplete_action_predictor_table_unittest.cc
+++ b/chrome/browser/predictors/autocomplete_action_predictor_table_unittest.cc
@@ -6,7 +6,7 @@
 
 #include "base/message_loop.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/predictors/autocomplete_action_predictor_table.h"
 #include "chrome/browser/predictors/predictor_database.h"
 #include "chrome/browser/predictors/predictor_database_factory.h"
diff --git a/chrome/browser/predictors/autocomplete_action_predictor_unittest.cc b/chrome/browser/predictors/autocomplete_action_predictor_unittest.cc
index 009234b..c6ffa7b 100644
--- a/chrome/browser/predictors/autocomplete_action_predictor_unittest.cc
+++ b/chrome/browser/predictors/autocomplete_action_predictor_unittest.cc
@@ -11,7 +11,7 @@
 #include "base/message_loop.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/autocomplete/autocomplete_match.h"
 #include "chrome/browser/history/history_service.h"
 #include "chrome/browser/history/history_service_factory.h"
diff --git a/chrome/browser/predictors/logged_in_predictor_table.h b/chrome/browser/predictors/logged_in_predictor_table.h
index 9cdbd15..30d1495 100644
--- a/chrome/browser/predictors/logged_in_predictor_table.h
+++ b/chrome/browser/predictors/logged_in_predictor_table.h
@@ -8,9 +8,9 @@
 #include <string>
 
 #include "base/containers/hash_tables.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/predictors/predictor_table_base.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 namespace sql {
 class Statement;
diff --git a/chrome/browser/predictors/predictor_database.cc b/chrome/browser/predictors/predictor_database.cc
index 36b713b..a9db8a3 100644
--- a/chrome/browser/predictors/predictor_database.cc
+++ b/chrome/browser/predictors/predictor_database.cc
@@ -72,6 +72,7 @@
       autocomplete_table_(new AutocompleteActionPredictorTable()),
       logged_in_table_(new LoggedInPredictorTable()),
       resource_prefetch_tables_(new ResourcePrefetchPredictorTables()) {
+  db_->set_histogram_tag("Predictor");
   ResourcePrefetchPredictorConfig config;
   is_resource_prefetch_predictor_enabled_ =
       IsSpeculativeResourcePrefetchingEnabled(profile, &config);
diff --git a/chrome/browser/predictors/resource_prefetch_common.h b/chrome/browser/predictors/resource_prefetch_common.h
index ab90972..47243dc 100644
--- a/chrome/browser/predictors/resource_prefetch_common.h
+++ b/chrome/browser/predictors/resource_prefetch_common.h
@@ -5,8 +5,8 @@
 #ifndef CHROME_BROWSER_PREDICTORS_RESOURCE_PREFETCH_COMMON_H_
 #define CHROME_BROWSER_PREDICTORS_RESOURCE_PREFETCH_COMMON_H_
 
-#include "base/time.h"
-#include "googleurl/src/gurl.h"
+#include "base/time/time.h"
+#include "url/gurl.h"
 
 class Profile;
 
diff --git a/chrome/browser/predictors/resource_prefetch_predictor.cc b/chrome/browser/predictors/resource_prefetch_predictor.cc
index 4bce05e..7453009 100644
--- a/chrome/browser/predictors/resource_prefetch_predictor.cc
+++ b/chrome/browser/predictors/resource_prefetch_predictor.cc
@@ -13,7 +13,7 @@
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/history/history_database.h"
 #include "chrome/browser/history/history_db_task.h"
 #include "chrome/browser/history/history_notifications.h"
diff --git a/chrome/browser/predictors/resource_prefetch_predictor.h b/chrome/browser/predictors/resource_prefetch_predictor.h
index fcf54b7..3776241 100644
--- a/chrome/browser/predictors/resource_prefetch_predictor.h
+++ b/chrome/browser/predictors/resource_prefetch_predictor.h
@@ -13,7 +13,7 @@
 #include "base/memory/linked_ptr.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/common/cancelable_request.h"
 #include "chrome/browser/history/history_types.h"
 #include "chrome/browser/predictors/resource_prefetch_common.h"
@@ -22,7 +22,7 @@
 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 #include "webkit/glue/resource_type.h"
 
 class PredictorsHandler;
diff --git a/chrome/browser/predictors/resource_prefetch_predictor_tables.h b/chrome/browser/predictors/resource_prefetch_predictor_tables.h
index 9e7e18a..f8a965e 100644
--- a/chrome/browser/predictors/resource_prefetch_predictor_tables.h
+++ b/chrome/browser/predictors/resource_prefetch_predictor_tables.h
@@ -10,10 +10,10 @@
 #include <string>
 #include <vector>
 
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/predictors/predictor_table_base.h"
 #include "chrome/browser/predictors/resource_prefetch_common.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 #include "webkit/glue/resource_type.h"
 
 namespace sql {
diff --git a/chrome/browser/predictors/resource_prefetch_predictor_unittest.cc b/chrome/browser/predictors/resource_prefetch_predictor_unittest.cc
index d438964..0221767 100644
--- a/chrome/browser/predictors/resource_prefetch_predictor_unittest.cc
+++ b/chrome/browser/predictors/resource_prefetch_predictor_unittest.cc
@@ -7,7 +7,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/message_loop.h"
 #include "base/run_loop.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/history/history_service.h"
 #include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/history/history_types.h"
diff --git a/chrome/browser/predictors/resource_prefetcher.h b/chrome/browser/predictors/resource_prefetcher.h
index 81e9481..bd77808 100644
--- a/chrome/browser/predictors/resource_prefetcher.h
+++ b/chrome/browser/predictors/resource_prefetcher.h
@@ -5,8 +5,8 @@
 #ifndef CHROME_BROWSER_PREDICTORS_RESOURCE_PREFETCHER_H_
 #define CHROME_BROWSER_PREDICTORS_RESOURCE_PREFETCHER_H_
 
-#include <map>
 #include <list>
+#include <map>
 #include <vector>
 
 #include "base/gtest_prod_util.h"
@@ -14,8 +14,8 @@
 #include "base/memory/scoped_vector.h"
 #include "base/threading/non_thread_safe.h"
 #include "chrome/browser/predictors/resource_prefetch_common.h"
-#include "googleurl/src/gurl.h"
 #include "net/url_request/url_request.h"
+#include "url/gurl.h"
 
 namespace net {
 class URLRequestContext;
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 82199f4..d70c205 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -33,7 +33,6 @@
 #include "chrome/browser/gpu/gl_string_manager.h"
 #include "chrome/browser/gpu/gpu_mode_manager.h"
 #include "chrome/browser/intranet_redirect_detector.h"
-#include "chrome/browser/invalidation/invalidator_storage.h"
 #include "chrome/browser/io_thread.h"
 #include "chrome/browser/media/media_capture_devices_dispatcher.h"
 #include "chrome/browser/media/media_stream_devices_controller.h"
@@ -77,6 +76,7 @@
 #include "chrome/browser/ui/search_engines/keyword_editor_controller.h"
 #include "chrome/browser/ui/startup/autolaunch_prompt.h"
 #include "chrome/browser/ui/startup/default_browser_prompt.h"
+#include "chrome/browser/ui/sync/sync_promo_ui.h"
 #include "chrome/browser/ui/tabs/pinned_tab_codec.h"
 #include "chrome/browser/ui/webui/extensions/extension_settings_handler.h"
 #include "chrome/browser/ui/webui/flags_ui.h"
@@ -84,13 +84,12 @@
 #include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
 #include "chrome/browser/ui/webui/plugins_ui.h"
 #include "chrome/browser/ui/webui/print_preview/sticky_settings.h"
-#include "chrome/browser/ui/webui/sync_promo/sync_promo_ui.h"
 #include "chrome/browser/ui/window_snapshot/window_snapshot.h"
 #include "chrome/browser/upgrade_detector.h"
 #include "chrome/browser/web_resource/promo_resource_service.h"
 #include "chrome/common/metrics/entropy_provider.h"
 #include "chrome/common/pref_names.h"
-#include "components/autofill/browser/autofill_manager.h"
+#include "components/autofill/core/browser/autofill_manager.h"
 #include "components/user_prefs/pref_registry_syncable.h"
 #include "content/public/browser/render_process_host.h"
 
@@ -284,6 +283,7 @@
   TRACE_EVENT0("browser", "chrome::RegisterUserPrefs");
   // User prefs. Please keep this list alphabetized.
   AlternateErrorPageTabObserver::RegisterUserPrefs(registry);
+  apps::RegisterUserPrefs(registry);
   autofill::AutofillDialogControllerImpl::RegisterUserPrefs(registry);
   autofill::AutofillManager::RegisterUserPrefs(registry);
   BookmarkPromptPrefs::RegisterUserPrefs(registry);
@@ -302,7 +302,6 @@
   HostContentSettingsMap::RegisterUserPrefs(registry);
   IncognitoModePrefs::RegisterUserPrefs(registry);
   InstantUI::RegisterUserPrefs(registry);
-  invalidation::InvalidatorStorage::RegisterUserPrefs(registry);
   MediaCaptureDevicesDispatcher::RegisterUserPrefs(registry);
   MediaStreamDevicesController::RegisterUserPrefs(registry);
   NetPrefObserver::RegisterUserPrefs(registry);
diff --git a/chrome/browser/prefs/command_line_pref_store.cc b/chrome/browser/prefs/command_line_pref_store.cc
index 9638dea..8e20f13 100644
--- a/chrome/browser/prefs/command_line_pref_store.cc
+++ b/chrome/browser/prefs/command_line_pref_store.cc
@@ -76,6 +76,7 @@
           prefs::kDisableCloudPolicyOnSignin, true },
       { switches::kDisableAsyncDns, prefs::kBuiltInDnsClientEnabled, false },
       { switches::kEnableAsyncDns, prefs::kBuiltInDnsClientEnabled, true },
+      { switches::kEnableSyncFavicons, prefs::kSyncFaviconsEnabled, false },
 };
 
 const CommandLinePrefStore::IntegerSwitchToPreferenceMapEntry
diff --git a/chrome/browser/prefs/pref_model_associator.cc b/chrome/browser/prefs/pref_model_associator.cc
index c49f10c..07792cb 100644
--- a/chrome/browser/prefs/pref_model_associator.cc
+++ b/chrome/browser/prefs/pref_model_associator.cc
@@ -348,8 +348,9 @@
     const syncer::SyncChangeList& change_list) {
   if (!models_associated_) {
     syncer::SyncError error(FROM_HERE,
-                    "Models not yet associated.",
-                    PREFERENCES);
+                            syncer::SyncError::DATATYPE_ERROR,
+                            "Models not yet associated.",
+                            PREFERENCES);
     return error;
   }
   base::AutoReset<bool> processing_changes(&processing_syncer_changes_, true);
diff --git a/chrome/browser/prefs/scoped_user_pref_update.h b/chrome/browser/prefs/scoped_user_pref_update.h
index 24942f1..e83595b 100644
--- a/chrome/browser/prefs/scoped_user_pref_update.h
+++ b/chrome/browser/prefs/scoped_user_pref_update.h
@@ -98,8 +98,10 @@
   DISALLOW_COPY_AND_ASSIGN(ScopedUserPrefUpdate);
 };
 
-typedef ScopedUserPrefUpdate<base::DictionaryValue, Value::TYPE_DICTIONARY>
+typedef ScopedUserPrefUpdate<base::DictionaryValue,
+                             base::Value::TYPE_DICTIONARY>
     DictionaryPrefUpdate;
-typedef ScopedUserPrefUpdate<base::ListValue, Value::TYPE_LIST> ListPrefUpdate;
+typedef ScopedUserPrefUpdate<base::ListValue, base::Value::TYPE_LIST>
+    ListPrefUpdate;
 
 #endif  // CHROME_BROWSER_PREFS_SCOPED_USER_PREF_UPDATE_H_
diff --git a/chrome/browser/prefs/session_startup_pref.h b/chrome/browser/prefs/session_startup_pref.h
index a31380f..379451e 100644
--- a/chrome/browser/prefs/session_startup_pref.h
+++ b/chrome/browser/prefs/session_startup_pref.h
@@ -7,7 +7,7 @@
 
 #include <vector>
 
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 class PrefService;
 class Profile;
diff --git a/chrome/browser/prerender/prerender_browsertest.cc b/chrome/browser/prerender/prerender_browsertest.cc
index a91f33f..47117f1 100644
--- a/chrome/browser/prerender/prerender_browsertest.cc
+++ b/chrome/browser/prerender/prerender_browsertest.cc
@@ -54,7 +54,6 @@
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_navigation_observer.h"
 #include "content/public/test/test_utils.h"
-#include "googleurl/src/gurl.h"
 #include "grit/generated_resources.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/url_request/url_request_context.h"
@@ -62,6 +61,7 @@
 #include "net/url_request/url_request_filter.h"
 #include "net/url_request/url_request_job.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "url/gurl.h"
 
 using content::BrowserThread;
 using content::DevToolsAgentHost;
@@ -1884,7 +1884,7 @@
 // See crbug.com/131836.
 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, DISABLED_PrerenderTaskManager) {
   // Show the task manager. This populates the model.
-  chrome::OpenTaskManager(current_browser(), false);
+  chrome::OpenTaskManager(current_browser());
   // Wait for the model of task manager to start.
   TaskManagerBrowserTestUtil::WaitForWebResourceChange(1);
 
@@ -2737,11 +2737,6 @@
 class PrerenderBrowserTestWithExtensions : public PrerenderBrowserTest,
                                            public ExtensionApiTest {
  public:
-  PrerenderBrowserTestWithExtensions() {
-    autostart_test_server_ = false;
-  }
-  virtual ~PrerenderBrowserTestWithExtensions() {}
-
   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
     PrerenderBrowserTest::SetUpCommandLine(command_line);
     ExtensionApiTest::SetUpCommandLine(command_line);
@@ -2765,7 +2760,7 @@
 // http://crbug.com/177163
 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTestWithExtensions,
                        DISABLED_WebNavigation) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   extensions::FrameNavigationState::set_allow_extension_scheme(true);
 
   CommandLine::ForCurrentProcess()->AppendSwitch(
@@ -2796,7 +2791,7 @@
 #define MAYBE_TabsApi TabsApi
 #endif  // defined(OS_WIN)
 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTestWithExtensions, MAYBE_TabsApi) {
-  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(StartEmbeddedTestServer());
   extensions::FrameNavigationState::set_allow_extension_scheme(true);
 
   // Wait for the extension to set itself up and return control to us.
diff --git a/chrome/browser/prerender/prerender_config.h b/chrome/browser/prerender/prerender_config.h
index f31d62d..11729a1 100644
--- a/chrome/browser/prerender/prerender_config.h
+++ b/chrome/browser/prerender/prerender_config.h
@@ -7,7 +7,7 @@
 
 #include <string>
 
-#include "base/time.h"
+#include "base/time/time.h"
 #include "ui/gfx/rect.h"
 
 namespace prerender {
diff --git a/chrome/browser/prerender/prerender_contents.h b/chrome/browser/prerender/prerender_contents.h
index 4b3422c..fca0c8f 100644
--- a/chrome/browser/prerender/prerender_contents.h
+++ b/chrome/browser/prerender/prerender_contents.h
@@ -13,7 +13,7 @@
 #include "base/memory/scoped_vector.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/prerender/prerender_final_status.h"
 #include "chrome/browser/prerender/prerender_origin.h"
diff --git a/chrome/browser/prerender/prerender_histograms.h b/chrome/browser/prerender/prerender_histograms.h
index ade1340..5c9a2d8 100644
--- a/chrome/browser/prerender/prerender_histograms.h
+++ b/chrome/browser/prerender/prerender_histograms.h
@@ -7,12 +7,12 @@
 
 #include <string>
 
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/prerender/prerender_contents.h"
 #include "chrome/browser/prerender/prerender_final_status.h"
 #include "chrome/browser/prerender/prerender_local_predictor.h"
 #include "chrome/browser/prerender/prerender_origin.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 namespace prerender {
 
diff --git a/chrome/browser/prerender/prerender_history.h b/chrome/browser/prerender/prerender_history.h
index 31dcbd4..dff22e2 100644
--- a/chrome/browser/prerender/prerender_history.h
+++ b/chrome/browser/prerender/prerender_history.h
@@ -8,10 +8,10 @@
 #include <list>
 
 #include "base/threading/non_thread_safe.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/prerender/prerender_final_status.h"
 #include "chrome/browser/prerender/prerender_origin.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 namespace base {
 class Value;
diff --git a/chrome/browser/prerender/prerender_link_manager.cc b/chrome/browser/prerender/prerender_link_manager.cc
index 14cdc6e..04dcf82 100644
--- a/chrome/browser/prerender/prerender_link_manager.cc
+++ b/chrome/browser/prerender/prerender_link_manager.cc
@@ -19,8 +19,8 @@
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/session_storage_namespace.h"
 #include "content/public/common/referrer.h"
-#include "googleurl/src/gurl.h"
 #include "ui/gfx/size.h"
+#include "url/gurl.h"
 
 using base::TimeDelta;
 using base::TimeTicks;
diff --git a/chrome/browser/prerender/prerender_link_manager.h b/chrome/browser/prerender/prerender_link_manager.h
index b9987d8..59d00c1 100644
--- a/chrome/browser/prerender/prerender_link_manager.h
+++ b/chrome/browser/prerender/prerender_link_manager.h
@@ -9,10 +9,10 @@
 
 #include "base/basictypes.h"
 #include "base/gtest_prod_util.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/prerender/prerender_handle.h"
 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 class Profile;
 
diff --git a/chrome/browser/prerender/prerender_local_predictor.cc b/chrome/browser/prerender/prerender_local_predictor.cc
index 34f1500..93525f6 100644
--- a/chrome/browser/prerender/prerender_local_predictor.cc
+++ b/chrome/browser/prerender/prerender_local_predictor.cc
@@ -14,7 +14,7 @@
 
 #include "base/metrics/field_trial.h"
 #include "base/metrics/histogram.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/history/history_database.h"
 #include "chrome/browser/history/history_db_task.h"
@@ -35,9 +35,9 @@
 #include "content/public/browser/web_contents_view.h"
 #include "content/public/common/page_transition_types.h"
 #include "crypto/secure_hash.h"
-#include "googleurl/src/url_canon.h"
 #include "grit/browser_resources.h"
 #include "ui/base/resource/resource_bundle.h"
+#include "url/url_canon.h"
 
 using content::BrowserThread;
 using content::PageTransition;
diff --git a/chrome/browser/prerender/prerender_local_predictor.h b/chrome/browser/prerender/prerender_local_predictor.h
index 590eeb8..ebd8e03 100644
--- a/chrome/browser/prerender/prerender_local_predictor.h
+++ b/chrome/browser/prerender/prerender_local_predictor.h
@@ -10,10 +10,10 @@
 #include "base/containers/hash_tables.h"
 #include "base/memory/scoped_vector.h"
 #include "base/memory/weak_ptr.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/common/cancelable_request.h"
 #include "chrome/browser/history/visit_database.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 class HistoryService;
 
diff --git a/chrome/browser/prerender/prerender_manager.cc b/chrome/browser/prerender/prerender_manager.cc
index 40fc8e2..b54d8d0 100644
--- a/chrome/browser/prerender/prerender_manager.cc
+++ b/chrome/browser/prerender/prerender_manager.cc
@@ -17,7 +17,7 @@
 #include "base/prefs/pref_service.h"
 #include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/common/cancelable_request.h"
@@ -887,7 +887,9 @@
 
 // static
 bool PrerenderManager::DoesURLHaveValidScheme(const GURL& url) {
-  return IsWebURL(url) || url.SchemeIs(extensions::kExtensionScheme);
+  return (IsWebURL(url) ||
+          url.SchemeIs(extensions::kExtensionScheme) ||
+          url.SchemeIs("data"));
 }
 
 DictionaryValue* PrerenderManager::GetAsValue() const {
diff --git a/chrome/browser/prerender/prerender_manager.h b/chrome/browser/prerender/prerender_manager.h
index 9cbba47..67ff3f3 100644
--- a/chrome/browser/prerender/prerender_manager.h
+++ b/chrome/browser/prerender/prerender_manager.h
@@ -17,8 +17,8 @@
 #include "base/memory/scoped_vector.h"
 #include "base/memory/weak_ptr.h"
 #include "base/threading/non_thread_safe.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/predictors/logged_in_predictor_table.h"
 #include "chrome/browser/prerender/prerender_config.h"
 #include "chrome/browser/prerender/prerender_contents.h"
@@ -27,8 +27,8 @@
 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
-#include "googleurl/src/gurl.h"
 #include "net/cookies/cookie_monster.h"
+#include "url/gurl.h"
 
 class Profile;
 struct ChromeCookieDetails;
diff --git a/chrome/browser/prerender/prerender_manager_factory.cc b/chrome/browser/prerender/prerender_manager_factory.cc
index 08b17ad..4a3d5d8 100644
--- a/chrome/browser/prerender/prerender_manager_factory.cc
+++ b/chrome/browser/prerender/prerender_manager_factory.cc
@@ -4,6 +4,10 @@
 
 #include "chrome/browser/prerender/prerender_manager_factory.h"
 
+#if defined(OS_ANDROID)
+#include "base/android/sys_utils.h"
+#endif
+
 #include "base/debug/trace_event.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/extensions/extension_system_factory.h"
@@ -52,6 +56,11 @@
 BrowserContextKeyedService* PrerenderManagerFactory::BuildServiceInstanceFor(
     content::BrowserContext* profile) const {
   CHECK(g_browser_process->prerender_tracker());
+#if defined(OS_ANDROID)
+  if (base::android::SysUtils::IsLowEndDevice())
+    return NULL;
+#endif
+
   PrerenderManager* prerender_manager = new PrerenderManager(
       static_cast<Profile*>(profile), g_browser_process->prerender_tracker());
 #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/prerender/prerender_message_filter.h b/chrome/browser/prerender/prerender_message_filter.h
index d8ed3bb..0d5eb06 100644
--- a/chrome/browser/prerender/prerender_message_filter.h
+++ b/chrome/browser/prerender/prerender_message_filter.h
@@ -7,7 +7,7 @@
 
 #include "base/compiler_specific.h"
 #include "content/public/browser/browser_message_filter.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 class Profile;
 
diff --git a/chrome/browser/prerender/prerender_tab_helper.cc b/chrome/browser/prerender/prerender_tab_helper.cc
index 50075f0..5203148 100644
--- a/chrome/browser/prerender/prerender_tab_helper.cc
+++ b/chrome/browser/prerender/prerender_tab_helper.cc
@@ -6,7 +6,7 @@
 
 #include "base/metrics/histogram.h"
 #include "base/strings/string_number_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/predictors/logged_in_predictor_table.h"
 #include "chrome/browser/prerender/prerender_histograms.h"
 #include "chrome/browser/prerender/prerender_local_predictor.h"
diff --git a/chrome/browser/prerender/prerender_tab_helper.h b/chrome/browser/prerender/prerender_tab_helper.h
index f20368f..1e889ce 100644
--- a/chrome/browser/prerender/prerender_tab_helper.h
+++ b/chrome/browser/prerender/prerender_tab_helper.h
@@ -7,10 +7,10 @@
 
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/browser/web_contents_user_data.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 namespace predictors {
 class LoggedInPredictorTable;
diff --git a/chrome/browser/prerender/prerender_tracker.h b/chrome/browser/prerender/prerender_tracker.h
index 15bfd2a..81557f3 100644
--- a/chrome/browser/prerender/prerender_tracker.h
+++ b/chrome/browser/prerender/prerender_tracker.h
@@ -15,7 +15,7 @@
 #include "base/threading/non_thread_safe.h"
 #include "chrome/browser/prerender/prerender_contents.h"
 #include "chrome/browser/prerender/prerender_final_status.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 namespace prerender {
 
diff --git a/chrome/browser/prerender/prerender_unittest.cc b/chrome/browser/prerender/prerender_unittest.cc
index aeed782..5b60f9d 100644
--- a/chrome/browser/prerender/prerender_unittest.cc
+++ b/chrome/browser/prerender/prerender_unittest.cc
@@ -7,7 +7,7 @@
 #include "base/memory/scoped_vector.h"
 #include "base/message_loop.h"
 #include "base/strings/stringprintf.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/prerender/prerender_contents.h"
 #include "chrome/browser/prerender/prerender_handle.h"
 #include "chrome/browser/prerender/prerender_link_manager.h"
@@ -18,9 +18,9 @@
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/test/test_browser_thread.h"
-#include "googleurl/src/gurl.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/gfx/size.h"
+#include "url/gurl.h"
 
 using base::Time;
 using base::TimeDelta;
diff --git a/chrome/browser/prerender/prerender_util.cc b/chrome/browser/prerender/prerender_util.cc
index 6a4dc49..ca25418 100644
--- a/chrome/browser/prerender/prerender_util.cc
+++ b/chrome/browser/prerender/prerender_util.cc
@@ -5,14 +5,14 @@
 #include "chrome/browser/prerender/prerender_util.h"
 
 #include "base/logging.h"
-#include "base/metrics/histogram.h"
+#include "base/metrics/sparse_histogram.h"
 #include "base/strings/string_util.h"
 #include "content/public/browser/resource_request_info.h"
-#include "googleurl/src/url_canon.h"
-#include "googleurl/src/url_parse.h"
-#include "googleurl/src/url_util.h"
 #include "net/http/http_response_headers.h"
 #include "net/url_request/url_request.h"
+#include "url/url_canon.h"
+#include "url/url_parse.h"
+#include "url/url_util.h"
 
 namespace prerender {
 
@@ -101,10 +101,10 @@
   // Gather histogram information about the X-Mod-Pagespeed header.
   if (info->GetResourceType() == ResourceType::MAIN_FRAME &&
       IsWebURL(request->url())) {
-    UMA_HISTOGRAM_ENUMERATION(kModPagespeedHistogram, 0, 101);
+    UMA_HISTOGRAM_SPARSE_SLOWLY(kModPagespeedHistogram, 0);
     if (request->response_headers() &&
         request->response_headers()->HasHeader(kModPagespeedHeader)) {
-      UMA_HISTOGRAM_ENUMERATION(kModPagespeedHistogram, 1, 101);
+      UMA_HISTOGRAM_SPARSE_SLOWLY(kModPagespeedHistogram, 1);
 
       // Attempt to parse the version number, and encode it in buckets
       // 2 through 99. 0 and 1 are used to store all pageviews and
@@ -126,7 +126,7 @@
             output++;
           if (output < 2 || output >= 99)
             output = 99;
-          UMA_HISTOGRAM_ENUMERATION(kModPagespeedHistogram, output, 101);
+          UMA_HISTOGRAM_SPARSE_SLOWLY(kModPagespeedHistogram, output);
         }
       }
     }
diff --git a/chrome/browser/prerender/prerender_util.h b/chrome/browser/prerender/prerender_util.h
index 417c951..1c0626e 100644
--- a/chrome/browser/prerender/prerender_util.h
+++ b/chrome/browser/prerender/prerender_util.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_PRERENDER_PRERENDER_UTIL_H_
 
 #include "base/basictypes.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 namespace net {
 class URLRequest;
diff --git a/chrome/browser/printing/OWNERS b/chrome/browser/printing/OWNERS
index f8be0e6..e0b3fde 100644
--- a/chrome/browser/printing/OWNERS
+++ b/chrome/browser/printing/OWNERS
@@ -1,5 +1,4 @@
 abodenha@chromium.org
-dpapad@chromium.org
 gene@chromium.org
 kmadhusu@chromium.org
 scottbyer@chromium.org
diff --git a/chrome/browser/printing/cloud_print/cloud_print_proxy_service.cc b/chrome/browser/printing/cloud_print/cloud_print_proxy_service.cc
index 816f7b5..6e5976e 100644
--- a/chrome/browser/printing/cloud_print/cloud_print_proxy_service.cc
+++ b/chrome/browser/printing/cloud_print/cloud_print_proxy_service.cc
@@ -20,7 +20,6 @@
 #include "chrome/browser/notifications/desktop_notification_service.h"
 #include "chrome/browser/notifications/notification.h"
 #include "chrome/browser/notifications/notification_ui_manager.h"
-#include "chrome/browser/printing/cloud_print/cloud_print_setup_flow.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/service/service_process_control.h"
 #include "chrome/common/chrome_notification_types.h"
@@ -78,15 +77,6 @@
   return false;
 }
 
-void CloudPrintProxyService::EnableForUser(const std::string& lsid,
-                                           const std::string& email) {
-  if (profile_->GetPrefs()->GetBoolean(prefs::kCloudPrintProxyEnabled)) {
-    InvokeServiceTask(
-        base::Bind(&CloudPrintProxyService::EnableCloudPrintProxy,
-                   weak_factory_.GetWeakPtr(), lsid, email));
-  }
-}
-
 void CloudPrintProxyService::EnableForUserWithRobot(
     const std::string& robot_auth_code,
     const std::string& robot_email,
@@ -128,11 +118,6 @@
   return true;
 }
 
-void CloudPrintProxyService::OnCloudPrintSetupClosed() {
-  base::MessageLoop::current()->PostTask(FROM_HERE,
-                                         base::Bind(&chrome::EndKeepAlive));
-}
-
 void CloudPrintProxyService::GetPrintersAvalibleForRegistration(
       std::vector<std::string>* printers) {
   base::FilePath list_path(
@@ -172,15 +157,6 @@
   process_control->GetCloudPrintProxyInfo(callback);
 }
 
-void CloudPrintProxyService::EnableCloudPrintProxy(const std::string& lsid,
-                                                   const std::string& email) {
-  ServiceProcessControl* process_control = GetServiceProcessControl();
-  DCHECK(process_control->IsConnected());
-  process_control->Send(new ServiceMsg_EnableCloudPrintProxy(lsid));
-  // Assume the IPC worked.
-  profile_->GetPrefs()->SetString(prefs::kCloudPrintEmail, email);
-}
-
 void CloudPrintProxyService::EnableCloudPrintProxyWithRobot(
     const std::string& robot_auth_code,
     const std::string& robot_email,
diff --git a/chrome/browser/printing/cloud_print/cloud_print_proxy_service.h b/chrome/browser/printing/cloud_print/cloud_print_proxy_service.h
index 7d8a54a..3426b16 100644
--- a/chrome/browser/printing/cloud_print/cloud_print_proxy_service.h
+++ b/chrome/browser/printing/cloud_print/cloud_print_proxy_service.h
@@ -13,21 +13,22 @@
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "base/prefs/pref_change_registrar.h"
-#include "chrome/browser/printing/cloud_print/cloud_print_setup_handler.h"
 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
 
 class Profile;
 class ServiceProcessControl;
 
+namespace base {
+class DictionaryValue;
+}  // namespace base
+
 namespace cloud_print {
 struct CloudPrintProxyInfo;
 }  // namespace cloud_print
 
 // Layer between the browser user interface and the cloud print proxy code
 // running in the service process.
-class CloudPrintProxyService
-    : public CloudPrintSetupHandlerDelegate,
-      public BrowserContextKeyedService {
+class CloudPrintProxyService : public BrowserContextKeyedService {
  public:
   explicit CloudPrintProxyService(Profile* profile);
   virtual ~CloudPrintProxyService();
@@ -37,7 +38,6 @@
   void Initialize();
 
   // Enables/disables cloud printing for the user
-  virtual void EnableForUser(const std::string& lsid, const std::string& email);
   virtual void EnableForUserWithRobot(
       const std::string& robot_auth_code,
       const std::string& robot_email,
@@ -56,9 +56,6 @@
 
   std::string proxy_id() const { return proxy_id_; }
 
-  // CloudPrintSetupHandler::Delegate implementation.
-  virtual void OnCloudPrintSetupClosed() OVERRIDE;
-
   // Returns list of printer names available for registration.
   static void GetPrintersAvalibleForRegistration(
       std::vector<std::string>* printers);
@@ -70,7 +67,6 @@
 
   // Methods that send an IPC to the service.
   void RefreshCloudPrintProxyStatus();
-  void EnableCloudPrintProxy(const std::string& lsid, const std::string& email);
   void EnableCloudPrintProxyWithRobot(
       const std::string& robot_auth_code,
       const std::string& robot_email,
diff --git a/chrome/browser/printing/cloud_print/cloud_print_proxy_service_unittest.cc b/chrome/browser/printing/cloud_print/cloud_print_proxy_service_unittest.cc
index ce27b95..964b0c7 100644
--- a/chrome/browser/printing/cloud_print/cloud_print_proxy_service_unittest.cc
+++ b/chrome/browser/printing/cloud_print/cloud_print_proxy_service_unittest.cc
@@ -136,10 +136,10 @@
 }
 
 void MockServiceProcessControl::SetWillBeEnabledExpectations() {
+  int32 message_id = ServiceMsg_EnableCloudPrintProxyWithRobot::ID;
   EXPECT_CALL(
       *this,
-      Send(Property(&IPC::Message::type,
-                    static_cast<int32>(ServiceMsg_EnableCloudPrintProxy::ID))))
+      Send(Property(&IPC::Message::type, message_id)))
       .Times(1).WillOnce(DoAll(DeleteArg<0>(), Return(true)));
 }
 
@@ -177,6 +177,12 @@
     return &process_control_;
   }
 
+  void EnableForUser() {
+    EnableForUserWithRobot("123", "123@gmail.com",
+                           MockServiceProcessControl::EnabledUserId(),
+                           base::DictionaryValue());
+  }
+
  private:
   MockServiceProcessControl process_control_;
 };
@@ -383,8 +389,7 @@
   EXPECT_EQ(std::string(), prefs->GetString(prefs::kCloudPrintEmail));
 
   service.GetMockServiceProcessControl()->SetWillBeEnabledExpectations();
-  service.EnableForUser(std::string(),
-                        MockServiceProcessControl::EnabledUserId());
+  service.EnableForUser();
 
   EXPECT_EQ(MockServiceProcessControl::EnabledUserId(),
             prefs->GetString(prefs::kCloudPrintEmail));
@@ -407,16 +412,14 @@
   service.Initialize();
 
   EXPECT_EQ(std::string(), prefs->GetString(prefs::kCloudPrintEmail));
-  service.EnableForUser(std::string(),
-                        MockServiceProcessControl::EnabledUserId());
+  service.EnableForUser();
   EXPECT_EQ(std::string(), prefs->GetString(prefs::kCloudPrintEmail));
 
   prefs->RemoveManagedPref(prefs::kCloudPrintProxyEnabled);
   EXPECT_EQ(std::string(), prefs->GetString(prefs::kCloudPrintEmail));
 
   service.GetMockServiceProcessControl()->SetWillBeEnabledExpectations();
-  service.EnableForUser(std::string(),
-                        MockServiceProcessControl::EnabledUserId());
+  service.EnableForUser();
 
   EXPECT_EQ(MockServiceProcessControl::EnabledUserId(),
             prefs->GetString(prefs::kCloudPrintEmail));
diff --git a/chrome/browser/printing/cloud_print/cloud_print_setup_flow.cc b/chrome/browser/printing/cloud_print/cloud_print_setup_flow.cc
deleted file mode 100644
index 780d4cb..0000000
--- a/chrome/browser/printing/cloud_print/cloud_print_setup_flow.cc
+++ /dev/null
@@ -1,343 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/printing/cloud_print/cloud_print_setup_flow.h"
-
-#include "base/json/json_writer.h"
-#include "base/memory/singleton.h"
-#include "base/prefs/pref_service.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/values.h"
-#include "chrome/browser/printing/cloud_print/cloud_print_proxy_service.h"
-#include "chrome/browser/printing/cloud_print/cloud_print_proxy_service_factory.h"
-#include "chrome/browser/printing/cloud_print/cloud_print_setup_message_handler.h"
-#include "chrome/browser/printing/cloud_print/cloud_print_setup_source.h"
-#include "chrome/browser/printing/cloud_print/cloud_print_url.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/service/service_process_control.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_dialogs.h"
-#include "chrome/browser/ui/browser_finder.h"
-#include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/host_desktop.h"
-#include "chrome/common/pref_names.h"
-#include "chrome/common/service_messages.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/url_data_source.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_ui.h"
-#include "google_apis/gaia/gaia_auth_fetcher.h"
-#include "google_apis/gaia/gaia_constants.h"
-#include "google_apis/gaia/google_service_auth_error.h"
-#include "grit/chromium_strings.h"
-#include "grit/locale_settings.h"
-#include "ui/base/l10n/l10n_font_util.h"
-#include "ui/gfx/font.h"
-
-using content::OpenURLParams;
-using content::Referrer;
-using content::WebContents;
-using content::WebUIMessageHandler;
-
-namespace {
-
-string16 SetupIframeXPath() {
-  return ASCIIToUTF16("//iframe[@id='cloudprintsetup']");
-}
-
-string16 DoneIframeXPath() {
-  return ASCIIToUTF16("//iframe[@id='setupdone']");
-}
-
-}  // end namespace
-
-////////////////////////////////////////////////////////////////////////////////
-// CloudPrintSetupFlow implementation.
-
-// static
-CloudPrintSetupFlow* CloudPrintSetupFlow::OpenDialog(
-    Profile* profile,
-    const base::WeakPtr<Delegate>& delegate,
-    gfx::NativeWindow parent_window) {
-  DCHECK(profile);
-  Browser* browser = chrome::FindLastActiveWithProfile(profile,
-      chrome::GetActiveDesktop());
-  // Set the arguments for showing the gaia login page.
-  DictionaryValue args;
-  args.SetString("user", std::string());
-  args.SetInteger("error", 0);
-  args.SetBoolean("editable_user", true);
-
-  bool setup_done = false;
-  if (profile->GetPrefs()->HasPrefPath(prefs::kCloudPrintEmail) &&
-      !profile->GetPrefs()->GetString(prefs::kCloudPrintEmail).empty())
-    setup_done = true;
-  args.SetString("pageToShow", setup_done ? "setupdone" : "cloudprintsetup");
-
-  std::string json_args;
-  base::JSONWriter::Write(&args, &json_args);
-
-  CloudPrintSetupFlow* flow = new CloudPrintSetupFlow(json_args, profile,
-                                                      delegate, setup_done);
-  // We may not always have a browser. This can happen when we are being
-  // invoked in the context of a "token expired" notfication. If we don't have
-  // a brower, use the underlying dialog system to show the dialog without
-  // using a browser.
-  if (!parent_window && browser && browser->window())
-    parent_window = browser->window()->GetNativeWindow();
-  chrome::ShowWebDialog(parent_window, profile, flow);
-  return flow;
-}
-
-CloudPrintSetupFlow::CloudPrintSetupFlow(
-    const std::string& args,
-    Profile* profile,
-    const base::WeakPtr<Delegate>& delegate,
-    bool setup_done)
-    : web_ui_(NULL),
-      dialog_start_args_(args),
-      last_auth_error_(GoogleServiceAuthError::AuthErrorNone()),
-      setup_done_(setup_done),
-      process_control_(NULL),
-      delegate_(delegate) {
-  // TODO(hclam): The data source should be added once.
-  profile_ = profile;
-  content::URLDataSource::Add(profile, new CloudPrintSetupSource());
-}
-
-CloudPrintSetupFlow::~CloudPrintSetupFlow() {
-}
-
-void CloudPrintSetupFlow::Focus() {
-  // TODO(pranavk): implement this method.
-  NOTIMPLEMENTED();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// ui::WebDialogDelegate implementation.
-GURL CloudPrintSetupFlow::GetDialogContentURL() const {
-  return GURL("chrome://cloudprintsetup/setupflow");
-}
-
-void CloudPrintSetupFlow::GetWebUIMessageHandlers(
-    std::vector<WebUIMessageHandler*>* handlers) const {
-  // Create the message handler only after we are asked, the caller is
-  // responsible for deleting the objects.
-  handlers->push_back(
-      new CloudPrintSetupMessageHandler(
-          const_cast<CloudPrintSetupFlow*>(this)));
-}
-
-void CloudPrintSetupFlow::GetDialogSize(gfx::Size* size) const {
-  PrefService* prefs = profile_->GetPrefs();
-  gfx::Font approximate_web_font(
-      prefs->GetString(prefs::kWebKitSansSerifFontFamily),
-      prefs->GetInteger(prefs::kWebKitDefaultFontSize));
-
-  if (setup_done_) {
-    *size = ui::GetLocalizedContentsSizeForFont(
-        IDS_CLOUD_PRINT_SETUP_WIZARD_DONE_WIDTH_CHARS,
-        IDS_CLOUD_PRINT_SETUP_WIZARD_DONE_HEIGHT_LINES,
-        approximate_web_font);
-  } else {
-    *size = ui::GetLocalizedContentsSizeForFont(
-        IDS_CLOUD_PRINT_SETUP_WIZARD_WIDTH_CHARS,
-        IDS_CLOUD_PRINT_SETUP_WIZARD_HEIGHT_LINES,
-        approximate_web_font);
-  }
-
-#if !defined(OS_WIN)
-  // NOTE(scottbyer):The following comment comes from
-  // SyncSetupFlow::GetDialogSize, where this hack was copied from. By starting
-  // off development of the UI on Windows, the hack is seemingly backwards.
-
-  // NOTE(akalin): This is a hack to work around a problem with font height on
-  // windows.  Basically font metrics are incorrectly returned in logical units
-  // instead of pixels on Windows.  Logical units are very commonly 96 DPI
-  // so our localized char/line counts are too small by a factor of 96/72.
-  // So we compensate for this on non-windows platform.
-
-  // TODO(scottbyer): Fix the root cause, kill the hacks.
-  float scale_hack = 96.f/72.f;
-  size->set_width(size->width() * scale_hack);
-  size->set_height(size->height() * scale_hack);
-#endif
-}
-
-// A callback to notify the delegate that the dialog closed.
-void CloudPrintSetupFlow::OnDialogClosed(const std::string& json_retval) {
-  // If we are fetching the token then cancel the request.
-  if (authenticator_.get())
-    authenticator_->CancelRequest();
-
-  if (delegate_.get())
-    delegate_->OnDialogClosed();
-  delete this;
-}
-
-std::string CloudPrintSetupFlow::GetDialogArgs() const {
-  return dialog_start_args_;
-}
-
-void CloudPrintSetupFlow::OnCloseContents(WebContents* source,
-                                          bool* out_close_dialog) {
-}
-
-string16 CloudPrintSetupFlow::GetDialogTitle() const {
-  return l10n_util::GetStringFUTF16(IDS_CLOUD_PRINT_SETUP_DIALOG_TITLE,
-      l10n_util::GetStringUTF16(IDS_GOOGLE_CLOUD_PRINT));
-}
-
-ui::ModalType CloudPrintSetupFlow::GetDialogModalType() const {
-  // We are always modeless.
-  return ui::MODAL_TYPE_NONE;
-}
-
-bool CloudPrintSetupFlow::ShouldShowDialogTitle() const {
-  return true;
-}
-
-bool CloudPrintSetupFlow::HandleContextMenu(
-    const content::ContextMenuParams& params) {
-  return true;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// GaiaAuthConsumer implementation.
-void CloudPrintSetupFlow::OnClientLoginSuccess(
-    const GaiaAuthConsumer::ClientLoginResult& credentials) {
-  // Save the token for the cloud print proxy.
-  lsid_ = credentials.lsid;
-
-  // Show that Gaia login has succeeded.
-  ShowGaiaSuccessAndSettingUp();
-  authenticator_.reset();
-
-  CloudPrintProxyServiceFactory::GetForProfile(profile_)->EnableForUser(
-      credentials.lsid, login_);
-  // TODO(sanjeevr): Should we wait and verify that the enable succeeded?
-  ShowSetupDone();
-}
-
-void CloudPrintSetupFlow::OnClientLoginFailure(
-    const GoogleServiceAuthError& error) {
-  last_auth_error_ = error;
-  ShowGaiaFailed(error);
-  authenticator_.reset();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Methods called by CloudPrintSetupMessageHandler
-void CloudPrintSetupFlow::Attach(content::WebUI* web_ui) {
-  web_ui_ = web_ui;
-}
-
-void CloudPrintSetupFlow::OnUserSubmittedAuth(const std::string& user,
-                                              const std::string& password,
-                                              const std::string& captcha,
-                                              const std::string& access_code) {
-  // Save the login name only.
-  login_ = user;
-
-  // Start the authenticator.
-  authenticator_.reset(
-      new GaiaAuthFetcher(this, GaiaConstants::kChromeSource,
-                          profile_->GetRequestContext()));
-
-  if (!access_code.empty()) {
-    authenticator_->StartClientLogin(user, access_code,
-                                     GaiaConstants::kCloudPrintService,
-                                     std::string(), std::string(),
-                                     GaiaAuthFetcher::HostedAccountsAllowed);
-  } else {
-    authenticator_->StartClientLogin(user, password,
-                                     GaiaConstants::kCloudPrintService,
-                                     last_auth_error_.captcha().token, captcha,
-                                     GaiaAuthFetcher::HostedAccountsAllowed);
-  }
-}
-
-void CloudPrintSetupFlow::OnUserClickedLearnMore() {
-  OpenURLParams params(CloudPrintURL::GetCloudPrintLearnMoreURL(),
-                       Referrer(), NEW_FOREGROUND_TAB,
-                       content::PAGE_TRANSITION_LINK, false);
-  web_ui_->GetWebContents()->OpenURL(params);
-}
-
-void CloudPrintSetupFlow::OnUserClickedPrintTestPage() {
-  OpenURLParams params(CloudPrintURL::GetCloudPrintTestPageURL(),
-                       Referrer(), NEW_FOREGROUND_TAB,
-                       content::PAGE_TRANSITION_LINK, false);
-  web_ui_->GetWebContents()->OpenURL(params);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Helper methods for showing contents of the Web UI
-void CloudPrintSetupFlow::ShowGaiaLogin(const DictionaryValue& args) {
-  if (web_ui_)
-    web_ui_->CallJavascriptFunction("cloudprint.showSetupLogin");
-
-  std::string json;
-  base::JSONWriter::Write(&args, &json);
-  string16 javascript = UTF8ToUTF16("cloudprint.showGaiaLogin(" + json + ");");
-
-  ExecuteJavascriptInIFrame(SetupIframeXPath(), javascript);
-}
-
-void CloudPrintSetupFlow::ShowGaiaSuccessAndSettingUp() {
-  ExecuteJavascriptInIFrame(
-      SetupIframeXPath(),
-      ASCIIToUTF16("cloudprint.showGaiaSuccessAndSettingUp();"));
-}
-
-void CloudPrintSetupFlow::ShowGaiaFailed(const GoogleServiceAuthError& error) {
-  DictionaryValue args;
-  args.SetString("pageToShow", "cloudprintsetup");
-  args.SetString("user", login_);
-  args.SetInteger("error", error.state());
-  args.SetBoolean("editable_user", true);
-  args.SetString("captchaUrl", error.captcha().image_url.spec());
-  ShowGaiaLogin(args);
-}
-
-void CloudPrintSetupFlow::ShowSetupDone() {
-  setup_done_ = true;
-  string16 product_name = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
-  string16 message = l10n_util::GetStringFUTF16(IDS_CLOUD_PRINT_SETUP_DONE,
-                                                product_name,
-                                                UTF8ToUTF16(login_));
-  string16 javascript(ASCIIToUTF16("cloudprint.setMessage('") + message +
-                      ASCIIToUTF16("');"));
-  ExecuteJavascriptInIFrame(DoneIframeXPath(), javascript);
-
-  if (web_ui_) {
-    PrefService* prefs = profile_->GetPrefs();
-    gfx::Font approximate_web_font(
-        prefs->GetString(prefs::kWebKitSansSerifFontFamily),
-        prefs->GetInteger(prefs::kWebKitDefaultFontSize));
-    gfx::Size done_size = ui::GetLocalizedContentsSizeForFont(
-        IDS_CLOUD_PRINT_SETUP_WIZARD_DONE_WIDTH_CHARS,
-        IDS_CLOUD_PRINT_SETUP_WIZARD_DONE_HEIGHT_LINES,
-        approximate_web_font);
-
-    base::FundamentalValue new_width(done_size.width());
-    base::FundamentalValue new_height(done_size.height());
-    web_ui_->CallJavascriptFunction("cloudprint.showSetupDone",
-                                    new_width, new_height);
-  }
-
-  ExecuteJavascriptInIFrame(DoneIframeXPath(),
-                            ASCIIToUTF16("cloudprint.onPageShown();"));
-}
-
-void CloudPrintSetupFlow::ExecuteJavascriptInIFrame(
-    const string16& iframe_xpath,
-    const string16& js) {
-  if (web_ui_) {
-    content::RenderViewHost* rvh =
-        web_ui_->GetWebContents()->GetRenderViewHost();
-    rvh->ExecuteJavascriptInWebFrame(iframe_xpath, js);
-  }
-}
diff --git a/chrome/browser/printing/cloud_print/cloud_print_setup_flow.h b/chrome/browser/printing/cloud_print/cloud_print_setup_flow.h
deleted file mode 100644
index abaaf9f..0000000
--- a/chrome/browser/printing/cloud_print/cloud_print_setup_flow.h
+++ /dev/null
@@ -1,156 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_PRINTING_CLOUD_PRINT_CLOUD_PRINT_SETUP_FLOW_H_
-#define CHROME_BROWSER_PRINTING_CLOUD_PRINT_CLOUD_PRINT_SETUP_FLOW_H_
-
-#include <string>
-#include <vector>
-
-#include "base/memory/weak_ptr.h"
-#include "google_apis/gaia/gaia_auth_consumer.h"
-#include "google_apis/gaia/gaia_auth_fetcher.h"
-#include "google_apis/gaia/google_service_auth_error.h"
-#include "grit/generated_resources.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/web_dialogs/web_dialog_delegate.h"
-
-class CloudPrintServiceProcessHelper;
-class CloudPrintSetupMessageHandler;
-class GaiaAuthFetcher;
-class GoogleServiceAuthError;
-class Profile;
-class ServiceProcessControl;
-
-namespace base {
-class DictionaryValue;
-}
-
-namespace content {
-class WebUI;
-}
-
-// This class is responsible for showing a cloud print setup dialog
-// and perform operations to fill the content of the dialog and handle
-// user actions in the dialog.
-//
-// It is responsible for:
-// 1. Showing the setup dialog.
-// 2. Providing the URL for the content of the dialog.
-// 3. Providing a data source to provide the content HTML files.
-// 4. Providing a message handler to handle user actions in the Web UI.
-// 5. Responding to actions received in the message handler.
-//
-// The architecture for WebUI is designed such that only the message handler
-// can access the WebUI. This splits the flow control across the message
-// handler and this class. In order to centralize all the flow control and
-// content in the WebUI, the WebUI object is given to this object by the
-// message handler through the Attach(WebUI*) method.
-class CloudPrintSetupFlow : public ui::WebDialogDelegate,
-                            public GaiaAuthConsumer {
- public:
-  class Delegate {
-   public:
-    virtual ~Delegate() {}
-    // Called when the setup dialog is closed.
-    virtual void OnDialogClosed() = 0;
-  };
-  virtual ~CloudPrintSetupFlow();
-
-  // Runs a flow from |start| to |end|, and does the work of actually showing
-  // the HTML dialog.  |container| is kept up-to-date with the lifetime of the
-  // flow (e.g it is emptied on dialog close).
-  static CloudPrintSetupFlow* OpenDialog(
-      Profile* service,
-      const base::WeakPtr<Delegate>& delegate,
-      gfx::NativeWindow parent_window);
-
-  // Focuses the dialog.  This is useful in cases where the dialog has been
-  // obscured by a browser window.
-  void Focus();
-
-  // ui::WebDialogDelegate implementation.
-  virtual GURL GetDialogContentURL() const OVERRIDE;
-  virtual void GetWebUIMessageHandlers(
-      std::vector<content::WebUIMessageHandler*>* handlers) const OVERRIDE;
-  virtual void GetDialogSize(gfx::Size* size) const OVERRIDE;
-  virtual std::string GetDialogArgs() const OVERRIDE;
-  virtual void OnDialogClosed(const std::string& json_retval) OVERRIDE;
-  virtual void OnCloseContents(content::WebContents* source,
-                               bool* out_close_dialog) OVERRIDE;
-  virtual string16 GetDialogTitle() const OVERRIDE;
-  virtual ui::ModalType GetDialogModalType() const OVERRIDE;
-  virtual bool ShouldShowDialogTitle() const OVERRIDE;
-  virtual bool HandleContextMenu(
-      const content::ContextMenuParams& params) OVERRIDE;
-
-  // GaiaAuthConsumer implementation.
-  virtual void OnClientLoginSuccess(
-      const GaiaAuthConsumer::ClientLoginResult& credentials) OVERRIDE;
-  virtual void OnClientLoginFailure(
-      const GoogleServiceAuthError& error) OVERRIDE;
-
- private:
-  friend class CloudPrintServiceProcessHelper;
-  friend class CloudPrintSetupMessageHandler;
-
-  // Use static Run method to get an instance.
-  CloudPrintSetupFlow(const std::string& args,
-                      Profile* profile,
-                      const base::WeakPtr<Delegate>& delegate, bool setup_done);
-
-  // Called CloudPrintSetupMessageHandler when a DOM is attached. This method
-  // is called when the HTML page is fully loaded. We then operate on this
-  // WebUI object directly.
-  void Attach(content::WebUI* web_ui);
-
-  // Called by CloudPrintSetupMessageHandler when user authentication is
-  // registered.
-  void OnUserSubmittedAuth(const std::string& user,
-                           const std::string& password,
-                           const std::string& captcha,
-                           const std::string& access_code);
-
-  // Called by CloudPrintSetupMessageHandler when the user clicks on various
-  // pieces of UI during setup.
-  void OnUserClickedLearnMore();
-  void OnUserClickedPrintTestPage();
-
-  // The following methods control which iframe is visible.
-  void ShowGaiaLogin(const base::DictionaryValue& args);
-  void ShowGaiaSuccessAndSettingUp();
-  void ShowGaiaFailed(const GoogleServiceAuthError& error);
-  void ShowSetupDone();
-  void ExecuteJavascriptInIFrame(const string16& iframe_xpath,
-                                 const string16& js);
-
-  // Pointer to the Web UI. This is provided by CloudPrintSetupMessageHandler
-  // when attached. We do not own the pointer, instead WebUI owns its delegate
-  // (us) and controls our lifetime.
-  content::WebUI* web_ui_;
-
-  // The args to pass to the initial page.
-  std::string dialog_start_args_;
-  Profile* profile_;
-
-  // Fetcher to obtain the Cloud Print token.
-  scoped_ptr<GaiaAuthFetcher> authenticator_;
-  std::string login_;
-  std::string lsid_;
-
-  // The last captcha or error state encountered.
-  GoogleServiceAuthError last_auth_error_;
-
-  // Are we in the done state?
-  bool setup_done_;
-
-  // Handle to the ServiceProcessControl which talks to the service process.
-  ServiceProcessControl* process_control_;
-  base::WeakPtr<Delegate> delegate_;
-
-  DISALLOW_COPY_AND_ASSIGN(CloudPrintSetupFlow);
-};
-
-#endif  // CHROME_BROWSER_PRINTING_CLOUD_PRINT_CLOUD_PRINT_SETUP_FLOW_H_
diff --git a/chrome/browser/printing/cloud_print/cloud_print_setup_handler.cc b/chrome/browser/printing/cloud_print/cloud_print_setup_handler.cc
deleted file mode 100644
index f0a0cba..0000000
--- a/chrome/browser/printing/cloud_print/cloud_print_setup_handler.cc
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/printing/cloud_print/cloud_print_setup_handler.h"
-
-CloudPrintSetupHandler::CloudPrintSetupHandler(Delegate* handler)
-    : handler_(handler) {}
-
-CloudPrintSetupHandler::~CloudPrintSetupHandler() {}
-
-void CloudPrintSetupHandler::OnDialogClosed() {
-  DCHECK(handler_);
-  handler_->OnCloudPrintSetupClosed();
-}
diff --git a/chrome/browser/printing/cloud_print/cloud_print_setup_handler.h b/chrome/browser/printing/cloud_print/cloud_print_setup_handler.h
deleted file mode 100644
index eeab734..0000000
--- a/chrome/browser/printing/cloud_print/cloud_print_setup_handler.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_PRINTING_CLOUD_PRINT_CLOUD_PRINT_SETUP_HANDLER_H_
-#define CHROME_BROWSER_PRINTING_CLOUD_PRINT_CLOUD_PRINT_SETUP_HANDLER_H_
-
-#include "base/memory/weak_ptr.h"
-#include "chrome/browser/printing/cloud_print/cloud_print_setup_flow.h"
-
-// Cloud Print setup handler.
-// Provides a weak pointer adapter so that callers of
-// CloudPrintSetupFlow::OpenDialog can still be notified when the dialog
-// completes, but don't have to stick around until the end. Lifetime should be
-// shorter than that of its owner.
-class CloudPrintSetupHandler
-    : public CloudPrintSetupFlow::Delegate,
-      public base::SupportsWeakPtr<CloudPrintSetupHandler> {
- public:
-  class Delegate {
-   public:
-    virtual ~Delegate() {}
-    // Called when the setup dialog is closed.
-    virtual void OnCloudPrintSetupClosed() = 0;
-  };
-
-  explicit CloudPrintSetupHandler(Delegate* handler);
-  virtual ~CloudPrintSetupHandler();
-
-  // CloudPrintSetupFlow::Delegate implementation.
-  virtual void OnDialogClosed() OVERRIDE;
-
- private:
-  Delegate* handler_;
-
-  DISALLOW_COPY_AND_ASSIGN(CloudPrintSetupHandler);
-};
-
-// Workaround for MSVC 2005 not handling inheritance from nested classes well.
-typedef CloudPrintSetupHandler::Delegate CloudPrintSetupHandlerDelegate;
-
-#endif  // CHROME_BROWSER_PRINTING_CLOUD_PRINT_CLOUD_PRINT_SETUP_HANDLER_H_
diff --git a/chrome/browser/printing/cloud_print/cloud_print_setup_message_handler.cc b/chrome/browser/printing/cloud_print/cloud_print_setup_message_handler.cc
deleted file mode 100644
index fb34458..0000000
--- a/chrome/browser/printing/cloud_print/cloud_print_setup_message_handler.cc
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/printing/cloud_print/cloud_print_setup_message_handler.h"
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/json/json_reader.h"
-#include "base/json/json_writer.h"
-#include "base/memory/scoped_ptr.h"
-#include "chrome/browser/printing/cloud_print/cloud_print_setup_flow.h"
-#include "content/public/browser/web_ui.h"
-
-void CloudPrintSetupMessageHandler::RegisterMessages() {
-  // Pass the WebUI object to the setup flow.
-  flow_->Attach(web_ui());
-
-  web_ui()->RegisterMessageCallback("SubmitAuth",
-      base::Bind(&CloudPrintSetupMessageHandler::HandleSubmitAuth,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("PrintTestPage",
-      base::Bind(&CloudPrintSetupMessageHandler::HandlePrintTestPage,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("LearnMore",
-      base::Bind(&CloudPrintSetupMessageHandler::HandleLearnMore,
-                 base::Unretained(this)));
-}
-
-void CloudPrintSetupMessageHandler::HandleSubmitAuth(const ListValue* args) {
-  std::string json;
-  bool ret = args->GetString(0, &json);
-  std::string username, password, captcha, access_code;
-  if (!ret || json.empty()) {
-    NOTREACHED() << "Empty json string";
-    return;
-  }
-
-  scoped_ptr<Value> parsed_value(base::JSONReader::Read(json));
-  if (!parsed_value.get() || !parsed_value->IsType(Value::TYPE_DICTIONARY)) {
-    NOTREACHED() << "Unable to parse auth data";
-    return;
-  }
-
-  DictionaryValue* result = static_cast<DictionaryValue*>(parsed_value.get());
-  if (!result->GetString("user", &username) ||
-      !result->GetString("pass", &password) ||
-      !result->GetString("captcha", &captcha) ||
-      !result->GetString("access_code", &access_code)) {
-    NOTREACHED() << "Unable to parse auth data";
-    return;
-  }
-
-  // Pass the information to the flow.
-  if (flow_)
-    flow_->OnUserSubmittedAuth(username, password, captcha, access_code);
-}
-
-void CloudPrintSetupMessageHandler::HandlePrintTestPage(const ListValue* args) {
-  if (flow_)
-    flow_->OnUserClickedPrintTestPage();
-}
-
-void CloudPrintSetupMessageHandler::HandleLearnMore(const ListValue* args) {
-  if (flow_)
-    flow_->OnUserClickedLearnMore();
-}
diff --git a/chrome/browser/printing/cloud_print/cloud_print_setup_message_handler.h b/chrome/browser/printing/cloud_print/cloud_print_setup_message_handler.h
deleted file mode 100644
index 05ff5c2..0000000
--- a/chrome/browser/printing/cloud_print/cloud_print_setup_message_handler.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_PRINTING_CLOUD_PRINT_CLOUD_PRINT_SETUP_MESSAGE_HANDLER_H_
-#define CHROME_BROWSER_PRINTING_CLOUD_PRINT_CLOUD_PRINT_SETUP_MESSAGE_HANDLER_H_
-
-#include <string>
-
-#include "base/values.h"
-#include "content/public/browser/web_ui_message_handler.h"
-
-class CloudPrintSetupFlow;
-
-// This class is used to handle DOM messages from the setup dialog.
-class CloudPrintSetupMessageHandler : public content::WebUIMessageHandler {
- public:
-  explicit CloudPrintSetupMessageHandler(CloudPrintSetupFlow* flow)
-    : flow_(flow) {}
-  virtual ~CloudPrintSetupMessageHandler() {}
-
- protected:
-  // WebUIMessageHandler implementation.
-  virtual void RegisterMessages() OVERRIDE;
-
-  // Callbacks from the page.
-  void HandleSubmitAuth(const ListValue* args);
-  void HandlePrintTestPage(const ListValue* args);
-  void HandleLearnMore(const ListValue* args);
-
- private:
-  CloudPrintSetupFlow* flow_;
-
-  DISALLOW_COPY_AND_ASSIGN(CloudPrintSetupMessageHandler);
-};
-
-#endif  // CHROME_BROWSER_PRINTING_CLOUD_PRINT_CLOUD_PRINT_SETUP_MESSAGE_HANDLER_H_
diff --git a/chrome/browser/printing/cloud_print/cloud_print_setup_source.cc b/chrome/browser/printing/cloud_print/cloud_print_setup_source.cc
deleted file mode 100644
index d098e61..0000000
--- a/chrome/browser/printing/cloud_print/cloud_print_setup_source.cc
+++ /dev/null
@@ -1,152 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/printing/cloud_print/cloud_print_setup_source.h"
-
-#include "base/memory/ref_counted_memory.h"
-#include "base/message_loop.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/values.h"
-#include "chrome/browser/google/google_util.h"
-#include "chrome/common/url_constants.h"
-#include "googleurl/src/gurl.h"
-#include "grit/browser_resources.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-#include "grit/locale_settings.h"
-#include "grit/ui_resources.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/base/resource/resource_bundle.h"
-#include "ui/webui/jstemplate_builder.h"
-#include "ui/webui/web_ui_util.h"
-
-// Define the values of standard URLs.
-const char CloudPrintSetupSource::kInvalidPasswordHelpUrl[] =
-  "https://www.google.com/support/accounts/bin/answer.py?ctx=ch&answer=27444";
-const char CloudPrintSetupSource::kCanNotAccessAccountUrl[] =
-  "https://www.google.com/support/accounts/bin/answer.py?answer=48598";
-const char CloudPrintSetupSource::kCreateNewAccountUrl[] =
-  "https://accounts.google.com/NewAccount?service=chromiumsync";
-
-namespace {
-
-// Utility method to keep dictionary population code streamlined.
-void AddString(DictionaryValue* dictionary,
-               const std::string& key,
-               int resource_id) {
-  dictionary->SetString(key, l10n_util::GetStringUTF16(resource_id));
-}
-
-}  // namespace
-
-CloudPrintSetupSource::CloudPrintSetupSource() {
-}
-
-std::string CloudPrintSetupSource::GetSource() const {
-  return chrome::kChromeUICloudPrintSetupHost;
-}
-
-void CloudPrintSetupSource::StartDataRequest(
-    const std::string& path_raw,
-    int render_process_id,
-    int render_view_id,
-    const content::URLDataSource::GotDataCallback& callback) {
-  const char kCloudPrintSetupPath[] = "cloudprintsetup";
-  const char kCloudPrintGaiaLoginPath[] = "gaialogin";
-  const char kCloudPrintSetupFlowPath[] = "setupflow";
-  const char kCloudPrintSetupDonePath[] = "setupdone";
-
-  DictionaryValue localized_strings;
-  DictionaryValue* dict = &localized_strings;
-
-  std::string response;
-  if (path_raw == kCloudPrintSetupPath) {
-    dict->SetString("header",
-        l10n_util::GetStringFUTF16(IDS_CLOUD_PRINT_SETUP_HEADER,
-        l10n_util::GetStringUTF16(IDS_GOOGLE_CLOUD_PRINT)));
-    AddString(dict, "explain", IDS_CLOUD_PRINT_SETUP_EXPLAIN);
-    AddString(dict, "anywhereheader", IDS_CLOUD_PRINT_SETUP_ANYWHERE_HEADER);
-    AddString(dict, "anywhereexplain", IDS_CLOUD_PRINT_SETUP_ANYWHERE_EXPLAIN);
-    AddString(dict, "printerheader", IDS_CLOUD_PRINT_SETUP_PRINTER_HEADER);
-    AddString(dict, "printerexplain", IDS_CLOUD_PRINT_SETUP_PRINTER_EXPLAIN);
-    AddString(dict, "sharingheader", IDS_CLOUD_PRINT_SETUP_SHARING_HEADER);
-    AddString(dict, "sharingexplain", IDS_CLOUD_PRINT_SETUP_SHARING_EXPLAIN);
-
-    static const base::StringPiece html(ResourceBundle::GetSharedInstance()
-        .GetRawDataResource(IDR_CLOUD_PRINT_SETUP_LOGIN_HTML));
-    webui::SetFontAndTextDirection(dict);
-    response = webui::GetI18nTemplateHtml(html, dict);
-  } else if (path_raw == kCloudPrintGaiaLoginPath) {
-    // Start by setting the per-locale URLs we show on the setup wizard.
-    dict->SetString("invalidpasswordhelpurl",
-                   GetLocalizedUrl(kInvalidPasswordHelpUrl));
-    dict->SetString("cannotaccessaccounturl",
-                   GetLocalizedUrl(kCanNotAccessAccountUrl));
-    dict->SetString("createnewaccounturl",
-                   GetLocalizedUrl(kCreateNewAccountUrl));
-
-    // None of the strings used here currently have sync-specific wording in
-    // them.  There is a unit test to catch if that happens.
-    dict->SetString("introduction", std::string());
-    AddString(dict, "signinprefix", IDS_CLOUD_PRINT_LOGIN_SIGNIN_PREFIX);
-    AddString(dict, "signinsuffix", IDS_CLOUD_PRINT_LOGIN_SIGNIN_SUFFIX);
-    AddString(dict, "cannotbeblank", IDS_CLOUD_PRINT_CANNOT_BE_BLANK);
-    AddString(dict, "emaillabel", IDS_CLOUD_PRINT_LOGIN_EMAIL_SAME_LINE);
-    AddString(dict, "passwordlabel", IDS_CLOUD_PRINT_LOGIN_PASSWORD_SAME_LINE);
-    AddString(dict, "invalidcredentials", IDS_SYNC_INVALID_USER_CREDENTIALS);
-    AddString(dict, "signin", IDS_CLOUD_PRINT_SIGNIN);
-    AddString(dict, "couldnotconnect", IDS_CLOUD_PRINT_LOGIN_COULD_NOT_CONNECT);
-    AddString(dict, "cannotaccessaccount",
-              IDS_CLOUD_PRINT_CANNOT_ACCESS_ACCOUNT);
-    AddString(dict, "createaccount", IDS_CLOUD_PRINT_CREATE_ACCOUNT);
-    AddString(dict, "cancel", IDS_CANCEL);
-    AddString(dict, "settingup", IDS_SYNC_LOGIN_SETTING_UP);
-    AddString(dict, "success", IDS_SYNC_SUCCESS);
-    AddString(dict, "errorsigningin", IDS_SYNC_ERROR_SIGNING_IN);
-    AddString(dict, "captchainstructions",
-              IDS_CLOUD_PRINT_GAIA_CAPTCHA_INSTRUCTIONS);
-    AddString(dict, "invalidaccesscode",
-              IDS_CLOUD_PRINT_INVALID_ACCESS_CODE_LABEL);
-    AddString(dict, "enteraccesscode", IDS_CLOUD_PRINT_ENTER_ACCESS_CODE_LABEL);
-    AddString(dict, "getaccesscodehelp",
-              IDS_CLOUD_PRINT_ACCESS_CODE_HELP_LABEL);
-    AddString(dict, "getaccesscodeurl", IDS_CLOUD_PRINT_GET_ACCESS_CODE_URL);
-
-    static const base::StringPiece html(ResourceBundle::GetSharedInstance()
-        .GetRawDataResource(IDR_GAIA_LOGIN_HTML));
-    webui::SetFontAndTextDirection(dict);
-    response = webui::GetI18nTemplateHtml(html, dict);
-  } else if (path_raw == kCloudPrintSetupDonePath) {
-    AddString(dict, "testpage", IDS_CLOUD_PRINT_SETUP_TEST_PAGE);
-    AddString(dict, "success", IDS_SYNC_SUCCESS);
-    AddString(dict, "okay", IDS_CLOUD_PRINT_SETUP_OK_BUTTON_LABEL);
-    static const base::StringPiece html(ResourceBundle::GetSharedInstance()
-        .GetRawDataResource(IDR_CLOUD_PRINT_SETUP_DONE_HTML));
-    webui::SetFontAndTextDirection(dict);
-    response = webui::GetI18nTemplateHtml(html, dict);
-  } else if (path_raw == kCloudPrintSetupFlowPath) {
-    static const base::StringPiece html(
-        ResourceBundle::GetSharedInstance()
-        .GetRawDataResource(IDR_CLOUD_PRINT_SETUP_FLOW_HTML));
-    response = html.as_string();
-  }
-
-  callback.Run(base::RefCountedString::TakeString(&response));
-}
-
-std::string CloudPrintSetupSource::GetMimeType(const std::string& path) const {
-  return "text/html";
-}
-
-bool CloudPrintSetupSource::ShouldAddContentSecurityPolicy() const {
-  return false;
-}
-
-std::string CloudPrintSetupSource::GetLocalizedUrl(
-    const std::string& url) const {
-  GURL original_url(url);
-  DCHECK(original_url.is_valid());
-  GURL localized_url = google_util::AppendGoogleLocaleParam(original_url);
-  return localized_url.spec();
-}
diff --git a/chrome/browser/printing/cloud_print/cloud_print_setup_source.h b/chrome/browser/printing/cloud_print/cloud_print_setup_source.h
deleted file mode 100644
index ebd8e28..0000000
--- a/chrome/browser/printing/cloud_print/cloud_print_setup_source.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_PRINTING_CLOUD_PRINT_CLOUD_PRINT_SETUP_SOURCE_H_
-#define CHROME_BROWSER_PRINTING_CLOUD_PRINT_CLOUD_PRINT_SETUP_SOURCE_H_
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "content/public/browser/url_data_source.h"
-
-class CloudPrintSetupSource : public content::URLDataSource {
- public:
-  CloudPrintSetupSource();
-
-  // content::URLDataSource implementation.
-  virtual std::string GetSource() const OVERRIDE;
-  virtual void StartDataRequest(
-      const std::string& path,
-      int render_process_id,
-      int render_view_id,
-      const content::URLDataSource::GotDataCallback& callback) OVERRIDE;
-  virtual std::string GetMimeType(const std::string& path) const OVERRIDE;
-  virtual bool ShouldAddContentSecurityPolicy() const OVERRIDE;
-
-  static const char kInvalidPasswordHelpUrl[];
-  static const char kCanNotAccessAccountUrl[];
-  static const char kCreateNewAccountUrl[];
-
- private:
-  virtual ~CloudPrintSetupSource() {}
-
-  // Takes a string containing an URL and returns an URL containing a CGI
-  // parameter of the form "&hl=xy" where 'xy' is the language code of the
-  // current locale.
-  std::string GetLocalizedUrl(const std::string& url) const;
-
-  DISALLOW_COPY_AND_ASSIGN(CloudPrintSetupSource);
-};
-
-#endif  // CHROME_BROWSER_PRINTING_CLOUD_PRINT_CLOUD_PRINT_SETUP_SOURCE_H_
diff --git a/chrome/browser/printing/cloud_print/cloud_print_setup_source_unittest.cc b/chrome/browser/printing/cloud_print/cloud_print_setup_source_unittest.cc
deleted file mode 100644
index 2df7f82..0000000
--- a/chrome/browser/printing/cloud_print/cloud_print_setup_source_unittest.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-#include "grit/locale_settings.h"
-#include "grit/ui_resources.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/base/l10n/l10n_util.h"
-
-using testing::HasSubstr;
-using testing::Not;
-
-void TestStringStillOkForCloudPrint(int resource_id) {
-  std::string resource_string = l10n_util::GetStringUTF8(resource_id);
-  EXPECT_THAT(resource_string, Not(HasSubstr("Sync")));
-  EXPECT_THAT(resource_string, Not(HasSubstr("sync")));
-}
-
-// This set of strings to test was generated from
-// CloudPrintSetupSource::StartDataRequest.  If any of these trip, notify the
-// cloud printing team and we'll split the strings.
-TEST(CloudPrintResources, SharedStringsCheck) {
-  TestStringStillOkForCloudPrint(IDS_CLOUD_PRINT_LOGIN_SIGNIN_PREFIX);
-  TestStringStillOkForCloudPrint(IDS_CLOUD_PRINT_LOGIN_SIGNIN_SUFFIX);
-  TestStringStillOkForCloudPrint(IDS_CLOUD_PRINT_CANNOT_BE_BLANK);
-  TestStringStillOkForCloudPrint(IDS_CLOUD_PRINT_LOGIN_EMAIL_SAME_LINE);
-  TestStringStillOkForCloudPrint(IDS_CLOUD_PRINT_LOGIN_PASSWORD_SAME_LINE);
-  TestStringStillOkForCloudPrint(IDS_SYNC_INVALID_USER_CREDENTIALS);
-  TestStringStillOkForCloudPrint(IDS_CLOUD_PRINT_SIGNIN);
-  TestStringStillOkForCloudPrint(IDS_CLOUD_PRINT_LOGIN_COULD_NOT_CONNECT);
-  TestStringStillOkForCloudPrint(IDS_CLOUD_PRINT_CANNOT_ACCESS_ACCOUNT);
-  TestStringStillOkForCloudPrint(IDS_CLOUD_PRINT_CREATE_ACCOUNT);
-  TestStringStillOkForCloudPrint(IDS_SYNC_LOGIN_SETTING_UP);
-  TestStringStillOkForCloudPrint(IDS_SYNC_SUCCESS);
-  TestStringStillOkForCloudPrint(IDS_SYNC_ERROR_SIGNING_IN);
-  TestStringStillOkForCloudPrint(IDS_CLOUD_PRINT_GAIA_CAPTCHA_INSTRUCTIONS);
-  TestStringStillOkForCloudPrint(IDS_CLOUD_PRINT_INVALID_ACCESS_CODE_LABEL);
-  TestStringStillOkForCloudPrint(IDS_CLOUD_PRINT_ENTER_ACCESS_CODE_LABEL);
-  TestStringStillOkForCloudPrint(IDS_CLOUD_PRINT_ACCESS_CODE_HELP_LABEL);
-  TestStringStillOkForCloudPrint(IDS_CLOUD_PRINT_GET_ACCESS_CODE_URL);
-  TestStringStillOkForCloudPrint(IDS_SYNC_SUCCESS);
-  TestStringStillOkForCloudPrint(IDS_CLOUD_PRINT_SETUP_OK_BUTTON_LABEL);
-}
diff --git a/chrome/browser/printing/cloud_print/cloud_print_url.cc b/chrome/browser/printing/cloud_print/cloud_print_url.cc
index d056316..2e46123 100644
--- a/chrome/browser/printing/cloud_print/cloud_print_url.cc
+++ b/chrome/browser/printing/cloud_print/cloud_print_url.cc
@@ -14,8 +14,8 @@
 #include "chrome/common/pref_names.h"
 #include "components/user_prefs/pref_registry_syncable.h"
 #include "google_apis/gaia/gaia_urls.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/escape.h"
+#include "url/gurl.h"
 
 // Url must not be matched by "urls" section of
 // cloud_print_app/manifest.json. If it's matched, print driver dialog will
diff --git a/chrome/browser/printing/cloud_print/test/cloud_print_proxy_process_browsertest.cc b/chrome/browser/printing/cloud_print/test/cloud_print_proxy_process_browsertest.cc
index 9fdeaa5..d7a18bc 100644
--- a/chrome/browser/printing/cloud_print/test/cloud_print_proxy_process_browsertest.cc
+++ b/chrome/browser/printing/cloud_print/test/cloud_print_proxy_process_browsertest.cc
@@ -13,7 +13,7 @@
 #include "base/rand_util.h"
 #include "base/test/multiprocess_test.h"
 #include "base/test/test_timeouts.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/printing/cloud_print/cloud_print_proxy_service.h"
 #include "chrome/browser/printing/cloud_print/cloud_print_proxy_service_factory.h"
 #include "chrome/browser/service/service_process_control.h"
diff --git a/chrome/browser/printing/print_dialog_cloud.cc b/chrome/browser/printing/print_dialog_cloud.cc
index 9f16cee..984a4e7 100644
--- a/chrome/browser/printing/print_dialog_cloud.cc
+++ b/chrome/browser/printing/print_dialog_cloud.cc
@@ -682,7 +682,7 @@
                  browser_context, modal_parent, data, print_job_title,
                  print_ticket, file_type));
   if (delete_on_close)
-    file_util::Delete(path_to_file, false);
+    base::Delete(path_to_file, false);
 }
 
 }  // namespace internal_cloud_print_helpers
diff --git a/chrome/browser/printing/print_dialog_gtk.cc b/chrome/browser/printing/print_dialog_gtk.cc
index e4a6e5d..a7bf21c 100644
--- a/chrome/browser/printing/print_dialog_gtk.cc
+++ b/chrome/browser/printing/print_dialog_gtk.cc
@@ -275,7 +275,7 @@
 
   if (!error && !metafile->SaveTo(path_to_pdf_)) {
     LOG(ERROR) << "Saving metafile failed";
-    file_util::Delete(path_to_pdf_, false);
+    base::Delete(path_to_pdf_, false);
     error = true;
   }
 
diff --git a/chrome/browser/printing/print_job.cc b/chrome/browser/printing/print_job.cc
index f71bc39..65b8d3e77 100644
--- a/chrome/browser/printing/print_job.cc
+++ b/chrome/browser/printing/print_job.cc
@@ -9,7 +9,7 @@
 #include "base/message_loop.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/threading/worker_pool.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/printing/print_job_worker.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "content/public/browser/notification_service.h"
diff --git a/chrome/browser/printing/print_preview_dialog_controller.cc b/chrome/browser/printing/print_preview_dialog_controller.cc
index b9413a0..f5d8a57 100644
--- a/chrome/browser/printing/print_preview_dialog_controller.cc
+++ b/chrome/browser/printing/print_preview_dialog_controller.cc
@@ -402,7 +402,7 @@
     // create the popup on the native desktop.
     Browser* current_browser = new Browser(
         Browser::CreateParams(Browser::TYPE_POPUP, profile,
-                              chrome::HOST_DESKTOP_TYPE_NATIVE));
+                              chrome::GetActiveDesktop()));
     if (!current_browser) {
       NOTREACHED() << "Failed to create popup browser window";
       return NULL;
diff --git a/chrome/browser/printing/print_preview_dialog_controller_browsertest.cc b/chrome/browser/printing/print_preview_dialog_controller_browsertest.cc
index ee17e94..9cecc56 100644
--- a/chrome/browser/printing/print_preview_dialog_controller_browsertest.cc
+++ b/chrome/browser/printing/print_preview_dialog_controller_browsertest.cc
@@ -15,7 +15,7 @@
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_types.h"
 #include "content/public/browser/web_contents_observer.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 using content::WebContents;
 
diff --git a/chrome/browser/printing/print_view_manager.cc b/chrome/browser/printing/print_view_manager.cc
index f5efeb7..17666df 100644
--- a/chrome/browser/printing/print_view_manager.cc
+++ b/chrome/browser/printing/print_view_manager.cc
@@ -13,7 +13,7 @@
 #include "base/metrics/histogram.h"
 #include "base/prefs/pref_service.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/printing/print_error_dialog.h"
 #include "chrome/browser/printing/print_job.h"
diff --git a/chrome/browser/printing/printing_layout_browsertest.cc b/chrome/browser/printing/printing_layout_browsertest.cc
index 696cfa7..5ba5b83 100644
--- a/chrome/browser/printing/printing_layout_browsertest.cc
+++ b/chrome/browser/printing/printing_layout_browsertest.cc
@@ -53,7 +53,7 @@
 
   virtual void TearDown() OVERRIDE {
     InProcessBrowserTest::TearDown();
-    file_util::Delete(emf_path_, true);
+    base::Delete(emf_path_, true);
   }
 
   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
@@ -221,7 +221,7 @@
               "\" when looking for \"" << verification_name << "\"";
           prn_file = file.value();
           found_prn = true;
-          file_util::Delete(file, false);
+          base::Delete(file, false);
           continue;
         }
         EXPECT_TRUE(false);
diff --git a/chrome/browser/process_singleton_linux.cc b/chrome/browser/process_singleton_linux.cc
index 2164ea0..b68e56d 100644
--- a/chrome/browser/process_singleton_linux.cc
+++ b/chrome/browser/process_singleton_linux.cc
@@ -76,8 +76,8 @@
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/platform_thread.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #if defined(TOOLKIT_GTK)
 #include "chrome/browser/ui/gtk/process_singleton_dialog.h"
 #endif
diff --git a/chrome/browser/process_singleton_win.cc b/chrome/browser/process_singleton_win.cc
index cff14fb..237004a 100644
--- a/chrome/browser/process_singleton_win.cc
+++ b/chrome/browser/process_singleton_win.cc
@@ -15,7 +15,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/win/metro.h"
 #include "base/win/registry.h"
 #include "base/win/scoped_handle.h"
@@ -288,7 +288,7 @@
     return PROCESS_NONE;
   }
 
-  switch (chrome::AttemptToNotifyRunningChrome(remote_window_)) {
+  switch (chrome::AttemptToNotifyRunningChrome(remote_window_, false)) {
     case chrome::NOTIFY_SUCCESS:
       return PROCESS_NOTIFIED;
     case chrome::NOTIFY_FAILED:
diff --git a/chrome/browser/profile_resetter/profile_resetter.cc b/chrome/browser/profile_resetter/profile_resetter.cc
index ea601c0..513719f 100644
--- a/chrome/browser/profile_resetter/profile_resetter.cc
+++ b/chrome/browser/profile_resetter/profile_resetter.cc
@@ -5,6 +5,8 @@
 #include "chrome/browser/profile_resetter/profile_resetter.h"
 
 #include "base/prefs/pref_service.h"
+#include "chrome/browser/browsing_data/browsing_data_helper.h"
+#include "chrome/browser/content_settings/host_content_settings_map.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_system.h"
 #include "chrome/browser/extensions/management_policy.h"
@@ -24,14 +26,18 @@
 ProfileResetter::ProfileResetter(Profile* profile)
     : profile_(profile),
       template_url_service_(TemplateURLServiceFactory::GetForProfile(profile_)),
-      pending_reset_flags_(0) {
+      pending_reset_flags_(0),
+      cookies_remover_(NULL) {
   DCHECK(CalledOnValidThread());
   DCHECK(profile_);
   registrar_.Add(this, chrome::NOTIFICATION_TEMPLATE_URL_SERVICE_LOADED,
                  content::Source<TemplateURLService>(template_url_service_));
 }
 
-ProfileResetter::~ProfileResetter() {}
+ProfileResetter::~ProfileResetter() {
+  if (cookies_remover_)
+    cookies_remover_->RemoveObserver(this);
+}
 
 void ProfileResetter::Reset(ProfileResetter::ResettableFlags resettable_flags,
                             const base::Closure& callback) {
@@ -130,16 +136,35 @@
 
 void ProfileResetter::ResetContentSettings() {
   DCHECK(CalledOnValidThread());
-  NOTIMPLEMENTED();
-  // TODO(battre/vabr): Implement
+  PrefService* prefs = profile_->GetPrefs();
+  HostContentSettingsMap* map = profile_->GetHostContentSettingsMap();
+
+  for (int type = 0; type < CONTENT_SETTINGS_NUM_TYPES; ++type) {
+    map->ClearSettingsForOneType(static_cast<ContentSettingsType>(type));
+    if (HostContentSettingsMap::IsSettingAllowedForType(
+            prefs,
+            CONTENT_SETTING_DEFAULT,
+            static_cast<ContentSettingsType>(type)))
+      map->SetDefaultContentSetting(static_cast<ContentSettingsType>(type),
+                                    CONTENT_SETTING_DEFAULT);
+  }
   MarkAsDone(CONTENT_SETTINGS);
 }
 
 void ProfileResetter::ResetCookiesAndSiteData() {
   DCHECK(CalledOnValidThread());
-  NOTIMPLEMENTED();
-  // TODO(battre/vabr): Implement
-  MarkAsDone(COOKIES_AND_SITE_DATA);
+  DCHECK(!cookies_remover_);
+
+  cookies_remover_ = BrowsingDataRemover::CreateForUnboundedRange(profile_);
+  cookies_remover_->AddObserver(this);
+  int remove_mask = BrowsingDataRemover::REMOVE_SITE_DATA |
+                    BrowsingDataRemover::REMOVE_CACHE;
+  PrefService* prefs = profile_->GetPrefs();
+  DCHECK(prefs);
+  // Don't try to clear LSO data if it's not supported.
+  if (!prefs->GetBoolean(prefs::kClearPluginLSODataEnabled))
+    remove_mask &= ~BrowsingDataRemover::REMOVE_PLUGIN_DATA;
+  cookies_remover_->Remove(remove_mask, BrowsingDataHelper::UNPROTECTED_WEB);
 }
 
 void ProfileResetter::ResetExtensions() {
@@ -187,3 +212,8 @@
   if (pending_reset_flags_ & DEFAULT_SEARCH_ENGINE)
     ResetDefaultSearchEngine();
 }
+
+void ProfileResetter::OnBrowsingDataRemoverDone() {
+  cookies_remover_ = NULL;
+  MarkAsDone(COOKIES_AND_SITE_DATA);
+}
diff --git a/chrome/browser/profile_resetter/profile_resetter.h b/chrome/browser/profile_resetter/profile_resetter.h
index 9031f74..492d6f6 100644
--- a/chrome/browser/profile_resetter/profile_resetter.h
+++ b/chrome/browser/profile_resetter/profile_resetter.h
@@ -8,6 +8,7 @@
 #include "base/basictypes.h"
 #include "base/callback.h"
 #include "base/threading/non_thread_safe.h"
+#include "chrome/browser/browsing_data/browsing_data_remover.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 
@@ -18,7 +19,8 @@
 // It is used in case the profile has been damaged due to malware or bad user
 // settings.
 class ProfileResetter : public base::NonThreadSafe,
-                        public content::NotificationObserver {
+                        public content::NotificationObserver,
+                        public BrowsingDataRemover::Observer {
  public:
   // Flags indicating what aspects of a profile shall be reset.
   enum Resettable {
@@ -70,6 +72,9 @@
                        const content::NotificationSource& source,
                        const content::NotificationDetails& details) OVERRIDE;
 
+  // BrowsingDataRemover::Observer:
+  virtual void OnBrowsingDataRemoverDone() OVERRIDE;
+
   Profile* profile_;
   TemplateURLService* template_url_service_;
 
@@ -82,6 +87,10 @@
 
   content::NotificationRegistrar registrar_;
 
+  // If non-null it means removal is in progress. BrowsingDataRemover takes care
+  // of deleting itself when done.
+  BrowsingDataRemover* cookies_remover_;
+
   DISALLOW_COPY_AND_ASSIGN(ProfileResetter);
 };
 
diff --git a/chrome/browser/profile_resetter/profile_resetter_browsertest.cc b/chrome/browser/profile_resetter/profile_resetter_browsertest.cc
new file mode 100644
index 0000000..f8e0144
--- /dev/null
+++ b/chrome/browser/profile_resetter/profile_resetter_browsertest.cc
@@ -0,0 +1,177 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/profile_resetter/profile_resetter.h"
+
+#include "base/bind.h"
+#include "chrome/browser/profile_resetter/profile_resetter_test_base.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "content/public/test/test_utils.h"
+#include "net/cookies/cookie_store.h"
+#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_context_getter.h"
+
+namespace {
+
+const char kCookieDefinition[] = "A=1";
+const char kCookieHostname[] = "http://host1";
+
+using content::BrowserThread;
+
+// RemoveCookieTester provides the user with the ability to set and get a
+// cookie for given profile.
+class RemoveCookieTester {
+ public:
+  explicit RemoveCookieTester(Profile* profile);
+  ~RemoveCookieTester();
+
+  std::string GetCookie(const std::string& host);
+  void AddCookie(const std::string& host, const std::string& definition);
+
+ private:
+  void GetCookieOnIOThread(net::URLRequestContextGetter* context_getter,
+                           const std::string& host);
+  void SetCookieOnIOThread(net::URLRequestContextGetter* context_getter,
+                           const std::string& host,
+                           const std::string& definition);
+  void GetCookieCallback(const std::string& cookies);
+  void SetCookieCallback(bool result);
+
+  void BlockUntilNotified();
+  void Notify();
+
+  std::string last_cookies_;
+  bool waiting_callback_;
+  Profile* profile_;
+  scoped_refptr<content::MessageLoopRunner> runner_;
+
+  DISALLOW_COPY_AND_ASSIGN(RemoveCookieTester);
+};
+
+RemoveCookieTester::RemoveCookieTester(Profile* profile)
+    : waiting_callback_(false),
+      profile_(profile) {
+}
+
+RemoveCookieTester::~RemoveCookieTester() {}
+
+// Returns true, if the given cookie exists in the cookie store.
+std::string RemoveCookieTester::GetCookie(const std::string& host) {
+  last_cookies_.clear();
+  DCHECK(!waiting_callback_);
+  waiting_callback_ = true;
+  BrowserThread::PostTask(
+      BrowserThread::IO, FROM_HERE,
+      base::Bind(&RemoveCookieTester::GetCookieOnIOThread,
+                 base::Unretained(this),
+                 base::Unretained(profile_->GetRequestContext()),
+                 host));
+  BlockUntilNotified();
+  return last_cookies_;
+}
+
+void RemoveCookieTester::AddCookie(const std::string& host,
+                                   const std::string& definition) {
+  DCHECK(!waiting_callback_);
+  waiting_callback_ = true;
+  BrowserThread::PostTask(
+      BrowserThread::IO, FROM_HERE,
+      base::Bind(&RemoveCookieTester::SetCookieOnIOThread,
+                 base::Unretained(this),
+                 base::Unretained(profile_->GetRequestContext()),
+                 host,
+                 definition));
+  BlockUntilNotified();
+}
+
+void RemoveCookieTester::GetCookieOnIOThread(
+    net::URLRequestContextGetter* context_getter,
+    const std::string& host) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  net::CookieStore* cookie_store = context_getter->
+      GetURLRequestContext()->cookie_store();
+  cookie_store->GetCookiesWithOptionsAsync(
+      GURL(host), net::CookieOptions(),
+      base::Bind(&RemoveCookieTester::GetCookieCallback,
+                 base::Unretained(this)));
+}
+
+void RemoveCookieTester::SetCookieOnIOThread(
+    net::URLRequestContextGetter* context_getter,
+    const std::string& host,
+    const std::string& definition) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  net::CookieStore* cookie_store = context_getter->
+      GetURLRequestContext()->cookie_store();
+  cookie_store->SetCookieWithOptionsAsync(
+      GURL(host), definition, net::CookieOptions(),
+      base::Bind(&RemoveCookieTester::SetCookieCallback,
+                 base::Unretained(this)));
+}
+
+void RemoveCookieTester::GetCookieCallback(const std::string& cookies) {
+  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+    BrowserThread::PostTask(
+        BrowserThread::UI, FROM_HERE,
+        base::Bind(&RemoveCookieTester::GetCookieCallback,
+                   base::Unretained(this), cookies));
+    return;
+  }
+  last_cookies_ = cookies;
+  Notify();
+}
+
+void RemoveCookieTester::SetCookieCallback(bool result) {
+  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+    BrowserThread::PostTask(
+        BrowserThread::UI, FROM_HERE,
+        base::Bind(&RemoveCookieTester::SetCookieCallback,
+                   base::Unretained(this), result));
+    return;
+  }
+  ASSERT_TRUE(result);
+  Notify();
+}
+
+void RemoveCookieTester::BlockUntilNotified() {
+  DCHECK(!runner_.get());
+  if (waiting_callback_) {
+    runner_ = new content::MessageLoopRunner;
+    runner_->Run();
+    runner_ = NULL;
+  }
+}
+
+void RemoveCookieTester::Notify() {
+  DCHECK(waiting_callback_);
+  waiting_callback_ = false;
+  if (runner_.get())
+    runner_->Quit();
+}
+
+class ProfileResetTest : public InProcessBrowserTest,
+                         public ProfileResetterTestBase {
+ protected:
+  virtual void SetUpOnMainThread() OVERRIDE {
+    resetter_.reset(new ProfileResetter(browser()->profile()));
+  }
+};
+
+
+IN_PROC_BROWSER_TEST_F(ProfileResetTest, ResetCookiesAndSiteData) {
+  RemoveCookieTester tester(browser()->profile());
+  tester.AddCookie(kCookieHostname, kCookieDefinition);
+  ASSERT_EQ(kCookieDefinition, tester.GetCookie(kCookieHostname));
+
+  resetter_->Reset(ProfileResetter::COOKIES_AND_SITE_DATA,
+                   base::Bind(&ProfileResetterMockObject::StopLoop,
+                              base::Unretained(&mock_object_)));
+  mock_object_.RunLoop();
+
+  EXPECT_EQ("", tester.GetCookie(kCookieHostname));
+}
+
+}  // namespace
diff --git a/chrome/browser/profile_resetter/profile_resetter_test_base.cc b/chrome/browser/profile_resetter/profile_resetter_test_base.cc
new file mode 100644
index 0000000..b239618
--- /dev/null
+++ b/chrome/browser/profile_resetter/profile_resetter_test_base.cc
@@ -0,0 +1,27 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/profile_resetter/profile_resetter_test_base.h"
+
+#include "chrome/browser/profile_resetter/profile_resetter.h"
+
+ProfileResetterMockObject::ProfileResetterMockObject() {}
+
+ProfileResetterMockObject::~ProfileResetterMockObject() {}
+
+void ProfileResetterMockObject::RunLoop() {
+  EXPECT_CALL(*this, Callback());
+  runner_ = new content::MessageLoopRunner;
+  runner_->Run();
+}
+
+void ProfileResetterMockObject::StopLoop() {
+  DCHECK(runner_.get());
+  Callback();
+  runner_->Quit();
+}
+
+ProfileResetterTestBase::ProfileResetterTestBase() {}
+
+ProfileResetterTestBase::~ProfileResetterTestBase() {}
diff --git a/chrome/browser/profile_resetter/profile_resetter_test_base.h b/chrome/browser/profile_resetter/profile_resetter_test_base.h
new file mode 100644
index 0000000..ef5744f
--- /dev/null
+++ b/chrome/browser/profile_resetter/profile_resetter_test_base.h
@@ -0,0 +1,51 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PROFILE_RESETTER_PROFILE_RESETTER_TEST_BASE_H_
+#define CHROME_BROWSER_PROFILE_RESETTER_PROFILE_RESETTER_TEST_BASE_H_
+
+#include "content/public/test/test_utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+class ProfileResetter;
+
+// The ProfileResetterMockObject is used to block the thread until
+// ProfileResetter::Reset has completed:
+
+// ProfileResetterMockObject mock_object;
+// resetter_->Reset(ProfileResetter::ALL,
+//                  base::Bind(&ProfileResetterMockObject::StopLoop,
+//                             base::Unretained(&mock_object)));
+// mock_object.RunLoop();
+class ProfileResetterMockObject {
+ public:
+  ProfileResetterMockObject();
+  ~ProfileResetterMockObject();
+
+  void RunLoop();
+  void StopLoop();
+
+ private:
+  MOCK_METHOD0(Callback, void(void));
+
+  scoped_refptr<content::MessageLoopRunner> runner_;
+
+  DISALLOW_COPY_AND_ASSIGN(ProfileResetterMockObject);
+};
+
+// Base class for all ProfileResetter unit tests.
+class ProfileResetterTestBase {
+ public:
+  ProfileResetterTestBase();
+  ~ProfileResetterTestBase();
+
+ protected:
+  testing::StrictMock<ProfileResetterMockObject> mock_object_;
+  scoped_ptr<ProfileResetter> resetter_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ProfileResetterTestBase);
+};
+
+#endif  // CHROME_BROWSER_PROFILE_RESETTER_PROFILE_RESETTER_TEST_BASE_H_
diff --git a/chrome/browser/profile_resetter/profile_resetter_unittest.cc b/chrome/browser/profile_resetter/profile_resetter_unittest.cc
index 8127d75..b625384 100644
--- a/chrome/browser/profile_resetter/profile_resetter_unittest.cc
+++ b/chrome/browser/profile_resetter/profile_resetter_unittest.cc
@@ -4,11 +4,14 @@
 
 #include "chrome/browser/profile_resetter/profile_resetter.h"
 
-#include "base/bind.h"
 #include "base/prefs/pref_service.h"
+#include "chrome/browser/content_settings/host_content_settings_map.h"
 #include "chrome/browser/extensions/extension_service_unittest.h"
 #include "chrome/browser/extensions/tab_helper.h"
+#include "chrome/browser/notifications/desktop_notification_service.h"
+#include "chrome/browser/notifications/desktop_notification_service_factory.h"
 #include "chrome/browser/prefs/session_startup_pref.h"
+#include "chrome/browser/profile_resetter/profile_resetter_test_base.h"
 #include "chrome/browser/search_engines/template_url_service_test_util.h"
 #include "chrome/browser/themes/theme_service.h"
 #include "chrome/browser/themes/theme_service_factory.h"
@@ -17,52 +20,14 @@
 #include "chrome/common/extensions/extension_manifest_constants.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/browser_with_test_window_test.h"
-#include "chrome/test/base/testing_profile.h"
 #include "content/public/browser/web_contents.h"
-#include "content/public/test/test_utils.h"
-#include "testing/gmock/include/gmock/gmock.h"
+
 
 namespace {
 
 using extensions::Extension;
 using extensions::Manifest;
 
-class MockObject {
- public:
-  void RunLoop() {
-    EXPECT_CALL(*this, Callback());
-    runner_ = new content::MessageLoopRunner;
-    runner_->Run();
-  }
-
-  void StopLoop() {
-    DCHECK(runner_.get());
-    Callback();
-    runner_->Quit();
-  }
-
- private:
-  MOCK_METHOD0(Callback, void(void));
-
-  scoped_refptr<content::MessageLoopRunner> runner_;
-};
-
-class ProfileResetterTestBase {
- public:
-  ProfileResetterTestBase();
-  ~ProfileResetterTestBase();
- protected:
-  testing::StrictMock<MockObject> mock_object_;
-  scoped_ptr<ProfileResetter> resetter_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ProfileResetterTestBase);
-};
-
-ProfileResetterTestBase::ProfileResetterTestBase() {}
-
-ProfileResetterTestBase::~ProfileResetterTestBase() {}
-
 class ProfileResetterTest : public testing::Test,
                             public ProfileResetterTestBase {
  protected:
@@ -95,9 +60,6 @@
   resetter_.reset(new ProfileResetter(profile_.get()));
 }
 
-// Returns a barebones test Extension object with the specified |name|.  The
-// returned extension will include background permission iff
-// |background_permission| is true.
 scoped_refptr<Extension> CreateExtension(const std::string& name,
                                          const base::FilePath& path,
                                          Manifest::Location location,
@@ -140,10 +102,17 @@
 /********************* Tests *********************/
 
 TEST_F(ProfileResetterTest, ResetDefaultSearchEngine) {
+  PrefService* prefs = test_util_.profile()->GetPrefs();
+  DCHECK(prefs);
+  prefs->SetString(prefs::kLastPromptedGoogleURL, "http://www.foo.com/");
+
   resetter_->Reset(
       ProfileResetter::DEFAULT_SEARCH_ENGINE,
-      base::Bind(&MockObject::StopLoop, base::Unretained(&mock_object_)));
+      base::Bind(&ProfileResetterMockObject::StopLoop,
+                 base::Unretained(&mock_object_)));
   mock_object_.RunLoop();
+
+  EXPECT_EQ("", prefs->GetString(prefs::kLastPromptedGoogleURL));
 }
 
 TEST_F(ProfileResetterTest, ResetHomepage) {
@@ -155,7 +124,8 @@
 
   resetter_->Reset(
       ProfileResetter::HOMEPAGE,
-      base::Bind(&MockObject::StopLoop, base::Unretained(&mock_object_)));
+      base::Bind(&ProfileResetterMockObject::StopLoop,
+                 base::Unretained(&mock_object_)));
   mock_object_.RunLoop();
 
   EXPECT_TRUE(prefs->GetBoolean(prefs::kHomePageIsNewTabPage));
@@ -164,17 +134,102 @@
 }
 
 TEST_F(ProfileResetterTest, ResetContentSettings) {
+  HostContentSettingsMap* host_content_settings_map =
+      test_util_.profile()->GetHostContentSettingsMap();
+  DesktopNotificationService* notification_service =
+      DesktopNotificationServiceFactory::GetForProfile(test_util_.profile());
+  ContentSettingsPattern pattern =
+      ContentSettingsPattern::FromString("[*.]example.org");
+  std::map<ContentSettingsType, ContentSetting> default_settings;
+
+  for (int type = 0; type < CONTENT_SETTINGS_NUM_TYPES; ++type) {
+    if (type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) {
+      notification_service->SetDefaultContentSetting(CONTENT_SETTING_BLOCK);
+      notification_service->GrantPermission(GURL("http://foo.de"));
+    } else if (type == CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE ||
+               type == CONTENT_SETTINGS_TYPE_MIXEDSCRIPT ||
+               type == CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS) {
+      // These types are excluded because one can't call
+      // GetDefaultContentSetting() for them.
+    } else {
+      ContentSettingsType content_type = static_cast<ContentSettingsType>(type);
+      ContentSetting default_setting =
+          host_content_settings_map->GetDefaultContentSetting(content_type,
+                                                              NULL);
+      default_settings[content_type] = default_setting;
+      ContentSetting wildcard_setting =
+          default_setting == CONTENT_SETTING_BLOCK ? CONTENT_SETTING_ALLOW
+                                                   : CONTENT_SETTING_BLOCK;
+      ContentSetting site_setting =
+          default_setting == CONTENT_SETTING_ALLOW ? CONTENT_SETTING_ALLOW
+                                                   : CONTENT_SETTING_BLOCK;
+      if (HostContentSettingsMap::IsSettingAllowedForType(
+              test_util_.profile()->GetPrefs(),
+              wildcard_setting,
+              content_type)) {
+        host_content_settings_map->SetDefaultContentSetting(
+            content_type,
+            wildcard_setting);
+      }
+      if (!HostContentSettingsMap::ContentTypeHasCompoundValue(content_type) &&
+          HostContentSettingsMap::IsValueAllowedForType(
+              test_util_.profile()->GetPrefs(),
+              Value::CreateIntegerValue(site_setting),
+              content_type)) {
+        host_content_settings_map->SetContentSetting(
+            pattern,
+            ContentSettingsPattern::Wildcard(),
+            content_type,
+            std::string(),
+            site_setting);
+        ContentSettingsForOneType host_settings;
+        host_content_settings_map->GetSettingsForOneType(
+            content_type, std::string(), &host_settings);
+        EXPECT_EQ(2U, host_settings.size());
+      }
+    }
+  }
+
   resetter_->Reset(
       ProfileResetter::CONTENT_SETTINGS,
-      base::Bind(&MockObject::StopLoop, base::Unretained(&mock_object_)));
+      base::Bind(&ProfileResetterMockObject::StopLoop,
+                 base::Unretained(&mock_object_)));
   mock_object_.RunLoop();
-}
 
-TEST_F(ProfileResetterTest, ResetCookiesAndSiteData) {
-  resetter_->Reset(
-      ProfileResetter::COOKIES_AND_SITE_DATA,
-      base::Bind(&MockObject::StopLoop, base::Unretained(&mock_object_)));
-  mock_object_.RunLoop();
+  for (int type = 0; type < CONTENT_SETTINGS_NUM_TYPES; ++type) {
+    if (type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) {
+      EXPECT_EQ(CONTENT_SETTING_ASK,
+                notification_service->GetDefaultContentSetting(NULL));
+      EXPECT_EQ(CONTENT_SETTING_ASK,
+                notification_service->GetContentSetting(GURL("http://foo.de")));
+    } else {
+      ContentSettingsType content_type = static_cast<ContentSettingsType>(type);
+      if (HostContentSettingsMap::ContentTypeHasCompoundValue(content_type) ||
+          type == CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE ||
+          content_type == CONTENT_SETTINGS_TYPE_MIXEDSCRIPT ||
+          content_type == CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS)
+        continue;
+      ContentSetting default_setting =
+          host_content_settings_map->GetDefaultContentSetting(content_type,
+                                                              NULL);
+      EXPECT_TRUE(default_settings.count(content_type));
+      EXPECT_EQ(default_settings[content_type], default_setting);
+      if (!HostContentSettingsMap::ContentTypeHasCompoundValue(content_type)) {
+        ContentSetting site_setting =
+            host_content_settings_map->GetContentSetting(
+                GURL("example.org"),
+                GURL(),
+                content_type,
+                std::string());
+        EXPECT_EQ(default_setting, site_setting);
+      }
+
+      ContentSettingsForOneType host_settings;
+      host_content_settings_map->GetSettingsForOneType(
+          content_type, std::string(), &host_settings);
+      EXPECT_EQ(1U, host_settings.size());
+    }
+  }
 }
 
 TEST_F(ExtensionsResetTest, ResetExtensionsByDisabling) {
@@ -216,7 +271,8 @@
 
   resetter_->Reset(
       ProfileResetter::EXTENSIONS,
-      base::Bind(&MockObject::StopLoop, base::Unretained(&mock_object_)));
+      base::Bind(&ProfileResetterMockObject::StopLoop,
+                 base::Unretained(&mock_object_)));
   mock_object_.RunLoop();
 
   EXPECT_EQ(2u, service_->extensions()->size());
@@ -236,7 +292,8 @@
 
   resetter_->Reset(
       ProfileResetter::STARTUP_PAGES,
-      base::Bind(&MockObject::StopLoop, base::Unretained(&mock_object_)));
+      base::Bind(&ProfileResetterMockObject::StopLoop,
+                 base::Unretained(&mock_object_)));
   mock_object_.RunLoop();
 
   startup_pref = SessionStartupPref::GetStartupPref(prefs);
@@ -250,20 +307,20 @@
       base::FilePath(FILE_PATH_LITERAL("//nonexistent")),
       Manifest::INVALID_LOCATION,
       false);
-  content::WebContents* contents1 = CreateWebContents();
-  extensions::TabHelper::CreateForWebContents(contents1);
-  extensions::TabHelper::FromWebContents(contents1)->
+  scoped_ptr<content::WebContents> contents1(CreateWebContents());
+  extensions::TabHelper::CreateForWebContents(contents1.get());
+  extensions::TabHelper::FromWebContents(contents1.get())->
       SetExtensionApp(extension_app.get());
-  content::WebContents* contents2 = CreateWebContents();
-  content::WebContents* contents3 = CreateWebContents();
-  content::WebContents* contents4 = CreateWebContents();
+  scoped_ptr<content::WebContents> contents2(CreateWebContents());
+  scoped_ptr<content::WebContents> contents3(CreateWebContents());
+  scoped_ptr<content::WebContents> contents4(CreateWebContents());
   TabStripModel* tab_strip_model = browser()->tab_strip_model();
 
-  tab_strip_model->AppendWebContents(contents4, true);
-  tab_strip_model->AppendWebContents(contents3, true);
-  tab_strip_model->AppendWebContents(contents2, true);
+  tab_strip_model->AppendWebContents(contents4.get(), true);
+  tab_strip_model->AppendWebContents(contents3.get(), true);
+  tab_strip_model->AppendWebContents(contents2.get(), true);
   tab_strip_model->SetTabPinned(2, true);
-  tab_strip_model->AppendWebContents(contents1, true);
+  tab_strip_model->AppendWebContents(contents1.get(), true);
   tab_strip_model->SetTabPinned(3, true);
 
   EXPECT_EQ(contents2, tab_strip_model->GetWebContentsAt(0));
@@ -274,7 +331,8 @@
 
   resetter_->Reset(
       ProfileResetter::PINNED_TABS,
-      base::Bind(&MockObject::StopLoop, base::Unretained(&mock_object_)));
+      base::Bind(&ProfileResetterMockObject::StopLoop,
+                 base::Unretained(&mock_object_)));
   mock_object_.RunLoop();
 
   EXPECT_EQ(contents1, tab_strip_model->GetWebContentsAt(0));
@@ -288,7 +346,8 @@
   // mock_object_ is a StrictMock, so we verify that it is called only once.
   resetter_->Reset(
       ProfileResetter::DEFAULT_SEARCH_ENGINE | ProfileResetter::HOMEPAGE,
-      base::Bind(&MockObject::StopLoop, base::Unretained(&mock_object_)));
+      base::Bind(&ProfileResetterMockObject::StopLoop,
+                 base::Unretained(&mock_object_)));
   mock_object_.RunLoop();
 }
 
diff --git a/chrome/browser/profiles/avatar_menu_model.cc b/chrome/browser/profiles/avatar_menu_model.cc
index bc9767d..a7e535b 100644
--- a/chrome/browser/profiles/avatar_menu_model.cc
+++ b/chrome/browser/profiles/avatar_menu_model.cc
@@ -238,7 +238,7 @@
   ManagedUserService* service = ManagedUserServiceFactory::GetForProfile(
       browser_->profile());
   if (service->ProfileIsManaged()) {
-    base::string16 custodian = UTF8ToUTF16(service->GetCustodianEmailAddress());
+    base::string16 custodian = UTF8ToUTF16(service->GetCustodianName());
     return l10n_util::GetStringFUTF16(IDS_MANAGED_USER_INFO, custodian);
   }
 #endif
diff --git a/chrome/browser/profiles/avatar_menu_model_browsertest.cc b/chrome/browser/profiles/avatar_menu_model_browsertest.cc
index 816f801..634fe75 100644
--- a/chrome/browser/profiles/avatar_menu_model_browsertest.cc
+++ b/chrome/browser/profiles/avatar_menu_model_browsertest.cc
@@ -30,7 +30,7 @@
   AvatarMenuModel model(&cache, NULL, browser());
 
   BrowserList* browser_list =
-      BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_NATIVE);
+      BrowserList::GetInstance(chrome::GetActiveDesktop());
   EXPECT_EQ(1U, browser_list->size());
   content::WindowedNotificationObserver window_close_observer(
       chrome::NOTIFICATION_BROWSER_CLOSED,
diff --git a/chrome/browser/profiles/avatar_menu_model_unittest.cc b/chrome/browser/profiles/avatar_menu_model_unittest.cc
index fcb5b14..b012827 100644
--- a/chrome/browser/profiles/avatar_menu_model_unittest.cc
+++ b/chrome/browser/profiles/avatar_menu_model_unittest.cc
@@ -4,9 +4,11 @@
 
 #include "chrome/browser/profiles/avatar_menu_model.h"
 
+#include "base/memory/scoped_ptr.h"
 #include "base/metrics/field_trial.h"
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/prefs/pref_service_syncable.h"
 #include "chrome/browser/profiles/avatar_menu_model_observer.h"
 #include "chrome/browser/profiles/profile_info_cache.h"
 #include "chrome/browser/profiles/profile_manager.h"
@@ -60,8 +62,10 @@
   string16 name1(ASCIIToUTF16("Test 1"));
   string16 name2(ASCIIToUTF16("Test 2"));
 
-  manager()->CreateTestingProfile("p1", name1, 0);
-  manager()->CreateTestingProfile("p2", name2, 0);
+  manager()->CreateTestingProfile("p1", scoped_ptr<PrefServiceSyncable>(),
+                                  name1, 0);
+  manager()->CreateTestingProfile("p2", scoped_ptr<PrefServiceSyncable>(),
+                                  name2, 0);
 
   MockObserver observer;
   EXPECT_EQ(0, observer.change_count());
@@ -84,8 +88,10 @@
   string16 name1(ASCIIToUTF16("Test 1"));
   string16 name2(ASCIIToUTF16("Test 2"));
 
-  manager()->CreateTestingProfile("p1", name1, 0);
-  manager()->CreateTestingProfile("p2", name2, 0);
+  manager()->CreateTestingProfile("p1", scoped_ptr<PrefServiceSyncable>(),
+                                  name1, 0);
+  manager()->CreateTestingProfile("p2", scoped_ptr<PrefServiceSyncable>(),
+                                  name2, 0);
 
   MockObserver observer;
   AvatarMenuModel model(manager()->profile_info_cache(), &observer, browser());
@@ -100,8 +106,10 @@
   string16 name2(ASCIIToUTF16("Beta"));
   string16 newname1(ASCIIToUTF16("Gamma"));
 
-  manager()->CreateTestingProfile("p1", name1, 0);
-  manager()->CreateTestingProfile("p2", name2, 0);
+  manager()->CreateTestingProfile("p1", scoped_ptr<PrefServiceSyncable>(),
+                                  name1, 0);
+  manager()->CreateTestingProfile("p2", scoped_ptr<PrefServiceSyncable>(),
+                                  name2, 0);
 
   MockObserver observer;
   AvatarMenuModel model(manager()->profile_info_cache(), &observer, browser());
@@ -134,8 +142,10 @@
   string16 name1(ASCIIToUTF16("Test 1"));
   string16 name2(ASCIIToUTF16("Test 2"));
 
-  manager()->CreateTestingProfile("p1", name1, 0);
-  manager()->CreateTestingProfile("p2", name2, 0);
+  manager()->CreateTestingProfile("p1", scoped_ptr<PrefServiceSyncable>(),
+                                  name1, 0);
+  manager()->CreateTestingProfile("p2", scoped_ptr<PrefServiceSyncable>(),
+                                  name2, 0);
 
   MockObserver observer;
   EXPECT_EQ(0, observer.change_count());
@@ -145,7 +155,8 @@
   EXPECT_EQ(2U, model.GetNumberOfItems());
 
   string16 name3(ASCIIToUTF16("Test 3"));
-  manager()->CreateTestingProfile("p3", name3, 0);
+  manager()->CreateTestingProfile("p3", scoped_ptr<PrefServiceSyncable>(),
+                                  name3, 0);
 
   // Four changes happened via the call to CreateTestingProfile: adding the
   // profile to the cache, setting the user name, rebuilding the list of
@@ -186,7 +197,8 @@
 
 TEST_F(AvatarMenuModelTest, DontShowAvatarMenu) {
   string16 name1(ASCIIToUTF16("Test 1"));
-  manager()->CreateTestingProfile("p1", name1, 0);
+  manager()->CreateTestingProfile("p1", scoped_ptr<PrefServiceSyncable>(),
+                                  name1, 0);
 
   EXPECT_FALSE(AvatarMenuModel::ShouldShowAvatarMenu());
 
@@ -196,7 +208,8 @@
     return;
 
   string16 name2(ASCIIToUTF16("Test 2"));
-  manager()->CreateTestingProfile("p2", name2, 0);
+  manager()->CreateTestingProfile("p2", scoped_ptr<PrefServiceSyncable>(),
+                                  name2, 0);
 
   EXPECT_FALSE(AvatarMenuModel::ShouldShowAvatarMenu());
 }
@@ -209,8 +222,10 @@
   string16 name1(ASCIIToUTF16("Test 1"));
   string16 name2(ASCIIToUTF16("Test 2"));
 
-  manager()->CreateTestingProfile("p1", name1, 0);
-  manager()->CreateTestingProfile("p2", name2, 0);
+  manager()->CreateTestingProfile("p1", scoped_ptr<PrefServiceSyncable>(),
+                                  name1, 0);
+  manager()->CreateTestingProfile("p2", scoped_ptr<PrefServiceSyncable>(),
+                                  name2, 0);
 
 #if defined(OS_CHROMEOS)
   EXPECT_FALSE(AvatarMenuModel::ShouldShowAvatarMenu());
@@ -224,7 +239,8 @@
   if (!ProfileManager::IsMultipleProfilesEnabled())
     return;
 
-  manager()->CreateTestingProfile("p1", ASCIIToUTF16("Test 1"), 0);
+  manager()->CreateTestingProfile("p1", scoped_ptr<PrefServiceSyncable>(),
+                                  ASCIIToUTF16("Test 1"), 0);
 
   // Add a managed user profile.
   ProfileInfoCache* cache = manager()->profile_info_cache();
diff --git a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
index dffbdbe..e5ca157 100644
--- a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
+++ b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
@@ -25,6 +25,7 @@
 #include "chrome/browser/extensions/api/bookmarks/bookmarks_api.h"
 #include "chrome/browser/extensions/api/commands/command_service.h"
 #include "chrome/browser/extensions/api/cookies/cookies_api.h"
+#include "chrome/browser/extensions/api/developer_private/developer_private_api_factory.h"
 #include "chrome/browser/extensions/api/dial/dial_api_factory.h"
 #include "chrome/browser/extensions/api/discovery/suggested_links_registry_factory.h"
 #include "chrome/browser/extensions/api/extension_action/extension_action_api.h"
@@ -62,6 +63,8 @@
 #include "chrome/browser/google/google_url_tracker_factory.h"
 #include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/history/shortcuts_backend_factory.h"
+#include "chrome/browser/invalidation/invalidation_service_factory.h"
+#include "chrome/browser/media_galleries/media_galleries_preferences_factory.h"
 #include "chrome/browser/notifications/desktop_notification_service_factory.h"
 #include "chrome/browser/password_manager/password_store_factory.h"
 #include "chrome/browser/plugins/plugin_prefs_factory.h"
@@ -100,6 +103,7 @@
 
 #if defined(ENABLE_CONFIGURATION_POLICY)
 #if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/policy/recommendation_restorer_factory.h"
 #include "chrome/browser/chromeos/policy/user_cloud_policy_manager_factory_chromeos.h"
 #include "chrome/browser/chromeos/policy/user_cloud_policy_token_forwarder_factory.h"
 #else
@@ -202,6 +206,7 @@
   extensions::BluetoothAPIFactory::GetInstance();
   extensions::CommandService::GetFactoryInstance();
   extensions::CookiesAPI::GetFactoryInstance();
+  extensions::DeveloperPrivateAPIFactory::GetInstance();
   extensions::DialAPIFactory::GetInstance();
   extensions::ExtensionActionAPI::GetFactoryInstance();
   extensions::ExtensionPrefsFactory::GetInstance();
@@ -255,6 +260,7 @@
   GlobalErrorServiceFactory::GetInstance();
   GoogleURLTrackerFactory::GetInstance();
   HistoryServiceFactory::GetInstance();
+  invalidation::InvalidationServiceFactory::GetInstance();
 #if defined(ENABLE_MANAGED_USERS)
   ManagedUserServiceFactory::GetInstance();
 #endif
@@ -273,6 +279,7 @@
   policy::ProfilePolicyConnectorFactory::GetInstance();
 #if defined(ENABLE_CONFIGURATION_POLICY)
 #if defined(OS_CHROMEOS)
+  policy::RecommendationRestorerFactory::GetInstance();
   policy::UserCloudPolicyManagerFactoryChromeOS::GetInstance();
   policy::UserCloudPolicyTokenForwarderFactory::GetInstance();
 #else
diff --git a/chrome/browser/profiles/gaia_info_update_service.h b/chrome/browser/profiles/gaia_info_update_service.h
index 797cc75..51d54f4 100644
--- a/chrome/browser/profiles/gaia_info_update_service.h
+++ b/chrome/browser/profiles/gaia_info_update_service.h
@@ -9,7 +9,7 @@
 #include "base/gtest_prod_util.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/prefs/pref_member.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/profiles/profile_downloader.h"
 #include "chrome/browser/profiles/profile_downloader_delegate.h"
 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
diff --git a/chrome/browser/profiles/profile.h b/chrome/browser/profiles/profile.h
index d811021..3364332 100644
--- a/chrome/browser/profiles/profile.h
+++ b/chrome/browser/profiles/profile.h
@@ -67,6 +67,9 @@
 class PrefRegistrySyncable;
 }
 
+// Instead of adding more members to Profile, consider creating a
+// BrowserContextKeyedService. See
+// http://dev.chromium.org/developers/design-documents/profile-architecture
 class Profile : public content::BrowserContext {
  public:
   // Profile services are accessed with the following parameter. This parameter
diff --git a/chrome/browser/profiles/profile_destroyer.h b/chrome/browser/profiles/profile_destroyer.h
index 70a4752..b258377 100644
--- a/chrome/browser/profiles/profile_destroyer.h
+++ b/chrome/browser/profiles/profile_destroyer.h
@@ -8,7 +8,7 @@
 #include <vector>
 
 #include "base/memory/ref_counted.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 
diff --git a/chrome/browser/profiles/profile_downloader.cc b/chrome/browser/profiles/profile_downloader.cc
index 56ebaf6..1cb0b1f 100644
--- a/chrome/browser/profiles/profile_downloader.cc
+++ b/chrome/browser/profiles/profile_downloader.cc
@@ -28,11 +28,11 @@
 #include "google_apis/gaia/gaia_constants.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "google_apis/gaia/oauth2_access_token_fetcher.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/load_flags.h"
 #include "net/url_request/url_fetcher.h"
 #include "net/url_request/url_request_status.h"
 #include "skia/ext/image_operations.h"
+#include "url/gurl.h"
 
 using content::BrowserThread;
 
diff --git a/chrome/browser/profiles/profile_downloader.h b/chrome/browser/profiles/profile_downloader.h
index 39483d9..6921618 100644
--- a/chrome/browser/profiles/profile_downloader.h
+++ b/chrome/browser/profiles/profile_downloader.h
@@ -15,9 +15,9 @@
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "google_apis/gaia/oauth2_access_token_consumer.h"
-#include "googleurl/src/gurl.h"
 #include "net/url_request/url_fetcher_delegate.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "url/gurl.h"
 
 class ProfileDownloaderDelegate;
 class OAuth2AccessTokenFetcher;
diff --git a/chrome/browser/profiles/profile_impl.h b/chrome/browser/profiles/profile_impl.h
index 4ac54a5..9f24987 100644
--- a/chrome/browser/profiles/profile_impl.h
+++ b/chrome/browser/profiles/profile_impl.h
@@ -14,7 +14,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/prefs/pref_change_registrar.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_impl_io_data.h"
 #include "content/public/browser/content_browser_client.h"
diff --git a/chrome/browser/profiles/profile_info_cache.cc b/chrome/browser/profiles/profile_info_cache.cc
index f189844..92398d8 100644
--- a/chrome/browser/profiles/profile_info_cache.cc
+++ b/chrome/browser/profiles/profile_info_cache.cc
@@ -165,7 +165,7 @@
 
 void DeleteBitmap(const base::FilePath& image_path) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-  file_util::Delete(image_path, false);
+  base::Delete(image_path, false);
 }
 
 }  // namespace
diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc
index 0a0d95b..bca79c5 100644
--- a/chrome/browser/profiles/profile_io_data.cc
+++ b/chrome/browser/profiles/profile_io_data.cc
@@ -569,6 +569,14 @@
   // future to more accurately capture this state.
   chromeos::CrosSettings::Get()->GetBoolean(chromeos::kStatsReportingPref,
                                             &enable_metrics_);
+#elif defined(OS_ANDROID)
+  // TODO(dwkang): rename or unify the pref for UMA once we have conclusion
+  // in crbugs.com/246495.
+  // Android has it's own preferences for metrics / crash uploading.
+  enable_metrics_.Init(prefs::kCrashReportingEnabled,
+                       g_browser_process->local_state());
+  enable_metrics_.MoveToThread(
+      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
 #else
   // Prep the PrefMember and send it to the IO thread, since this value will be
   // read from there.
diff --git a/chrome/browser/profiles/profile_loader.cc b/chrome/browser/profiles/profile_loader.cc
new file mode 100644
index 0000000..f7ada5e
--- /dev/null
+++ b/chrome/browser/profiles/profile_loader.cc
@@ -0,0 +1,99 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/profiles/profile_loader.h"
+
+#include "base/bind.h"
+#include "base/files/file_path.h"
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/lifetime/application_lifetime.h"
+#include "chrome/browser/profiles/profile_manager.h"
+
+ProfileLoader::ProfileLoader(ProfileManager* profile_manager)
+  : profile_manager_(profile_manager),
+    profile_load_sequence_id_(0),
+    pending_profile_loads_(0),
+    weak_factory_(this) {
+}
+
+ProfileLoader::~ProfileLoader() {
+}
+
+bool ProfileLoader::IsAnyProfileLoading() const {
+  return pending_profile_loads_ > 0;
+}
+
+void ProfileLoader::InvalidatePendingProfileLoads() {
+  ++profile_load_sequence_id_;
+}
+
+void ProfileLoader::LoadProfileInvalidatingOtherLoads(
+    const base::FilePath& profile_file_path,
+    base::Callback<void(Profile*)> callback) {
+  InvalidatePendingProfileLoads();
+
+  Profile* profile = GetProfileByPath(profile_file_path);
+  if (profile) {
+    callback.Run(profile);
+    return;
+  }
+
+  IncrementPendingProfileLoads();
+  CreateProfileAsync(
+      profile_file_path,
+      base::Bind(&ProfileLoader::OnProfileLoaded,
+                 weak_factory_.GetWeakPtr(),
+                 profile_load_sequence_id_,
+                 callback),
+      string16(), string16(), false);
+}
+
+Profile* ProfileLoader::GetProfileByPath(const base::FilePath& path) {
+  return profile_manager_->GetProfileByPath(path);
+}
+
+void ProfileLoader::CreateProfileAsync(
+    const base::FilePath& profile_path,
+    const ProfileManager::CreateCallback& callback,
+    const string16& name,
+    const string16& icon_url,
+    bool is_managed) {
+  profile_manager_->CreateProfileAsync(
+      profile_path, callback, name, icon_url, is_managed);
+}
+
+void ProfileLoader::OnProfileLoaded(int profile_load_sequence_id,
+                                    base::Callback<void(Profile*)> callback,
+                                    Profile* profile,
+                                    Profile::CreateStatus status) {
+  switch (status) {
+    case Profile::CREATE_STATUS_CREATED:
+      break;
+    case Profile::CREATE_STATUS_INITIALIZED:
+      if (profile_load_sequence_id == profile_load_sequence_id_)
+        callback.Run(profile);
+      DecrementPendingProfileLoads();
+      break;
+    case Profile::CREATE_STATUS_LOCAL_FAIL:
+    case Profile::CREATE_STATUS_REMOTE_FAIL:
+    case Profile::CREATE_STATUS_CANCELED:
+      DecrementPendingProfileLoads();
+      break;
+    case Profile::MAX_CREATE_STATUS:
+      NOTREACHED();
+      break;
+  }
+}
+
+void ProfileLoader::IncrementPendingProfileLoads() {
+  pending_profile_loads_++;
+  if (pending_profile_loads_ == 1)
+    chrome::StartKeepAlive();
+}
+
+void ProfileLoader::DecrementPendingProfileLoads() {
+  pending_profile_loads_--;
+  if (pending_profile_loads_ == 0)
+    chrome::EndKeepAlive();
+}
diff --git a/chrome/browser/profiles/profile_loader.h b/chrome/browser/profiles/profile_loader.h
new file mode 100644
index 0000000..b9b9038
--- /dev/null
+++ b/chrome/browser/profiles/profile_loader.h
@@ -0,0 +1,65 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PROFILES_PROFILE_LOADER_H_
+#define CHROME_BROWSER_PROFILES_PROFILE_LOADER_H_
+
+#include "base/callback.h"
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_manager.h"
+
+namespace base {
+class FilePath;
+}
+
+class ProfileManager;
+
+// This class loads profiles asynchronously and calls the provided callback once
+// the profile is ready. Only the callback for the most recent load request is
+// called, and only if the load was successful.
+//
+// This is useful for loading profiles in response to user interaction where
+// only the latest requested profile is required.
+class ProfileLoader {
+ public:
+  explicit ProfileLoader(ProfileManager* profile_manager);
+  ~ProfileLoader();
+
+  bool IsAnyProfileLoading() const;
+  void InvalidatePendingProfileLoads();
+  void LoadProfileInvalidatingOtherLoads(
+      const base::FilePath& profile_file_path,
+      base::Callback<void(Profile*)> callback);
+
+ protected:
+  // These just call through to the ProfileManager.
+  // Virtual so they can be mocked out in tests.
+  virtual Profile* GetProfileByPath(const base::FilePath& path);
+  virtual void CreateProfileAsync(
+      const base::FilePath& profile_path,
+      const ProfileManager::CreateCallback& callback,
+      const string16& name,
+      const string16& icon_url,
+      bool is_managed);
+
+ private:
+  void OnProfileLoaded(int profile_load_sequence_id,
+                       base::Callback<void(Profile*)> callback,
+                       Profile* profile,
+                       Profile::CreateStatus status);
+
+  void IncrementPendingProfileLoads();
+  void DecrementPendingProfileLoads();
+
+  ProfileManager* profile_manager_;
+  int profile_load_sequence_id_;
+  int pending_profile_loads_;
+
+  base::WeakPtrFactory<ProfileLoader> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(ProfileLoader);
+};
+
+#endif  // CHROME_BROWSER_PROFILES_PROFILE_LOADER_H_
diff --git a/chrome/browser/profiles/profile_loader_unittest.cc b/chrome/browser/profiles/profile_loader_unittest.cc
new file mode 100644
index 0000000..3c3598b
--- /dev/null
+++ b/chrome/browser/profiles/profile_loader_unittest.cc
@@ -0,0 +1,132 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/profiles/profile_loader.h"
+
+#include <map>
+
+#include "base/bind.h"
+#include "base/files/file_path.h"
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/lifetime/application_lifetime.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_loader.h"
+#include "chrome/test/base/testing_profile.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+using ::testing::_;
+using ::testing::Invoke;
+using ::testing::Return;
+using ::testing::StrictMock;
+using ::testing::WithArgs;
+
+class TestProfileLoader : public ProfileLoader {
+ public:
+  TestProfileLoader() : ProfileLoader(NULL) {}
+  virtual ~TestProfileLoader() {}
+
+  MOCK_METHOD1(GetProfileByPath, Profile*(const base::FilePath&));
+  MOCK_METHOD5(CreateProfileAsync, void(const base::FilePath&,
+                                        const ProfileManager::CreateCallback&,
+                                        const string16&,
+                                        const string16&,
+                                        bool));
+
+  void SetCreateCallback(const base::FilePath& path,
+                         const ProfileManager::CreateCallback& callback) {
+    callbacks_[path] = callback;
+  }
+
+  void RunCreateCallback(const base::FilePath& path,
+                         Profile* profile,
+                         Profile::CreateStatus status) {
+    callbacks_[path].Run(profile, status);
+  }
+
+ private:
+  std::map<base::FilePath, ProfileManager::CreateCallback> callbacks_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestProfileLoader);
+};
+
+class MockCallback : public base::RefCountedThreadSafe<MockCallback> {
+ public:
+  MockCallback();
+  MOCK_METHOD1(Run, void(Profile*));
+
+ protected:
+  friend class base::RefCountedThreadSafe<MockCallback>;
+  virtual ~MockCallback();
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockCallback);
+};
+
+MockCallback::MockCallback() {}
+MockCallback::~MockCallback() {}
+
+TEST(ProfileLoaderTest, LoadProfileInvalidatingOtherLoads) {
+  TestingProfile profile;
+  base::FilePath fake_profile_path_1 =
+      base::FilePath::FromUTF8Unsafe("fake/profile 1");
+  base::FilePath fake_profile_path_2 =
+      base::FilePath::FromUTF8Unsafe("fake/profile 2");
+
+  TestProfileLoader loader;
+  EXPECT_FALSE(loader.IsAnyProfileLoading());
+
+  // path_1 never loads.
+  EXPECT_CALL(loader, GetProfileByPath(fake_profile_path_1))
+      .WillRepeatedly(Return(static_cast<Profile*>(NULL)));
+  EXPECT_CALL(loader, CreateProfileAsync(fake_profile_path_1, _, _, _, false))
+      .WillRepeatedly(WithArgs<0, 1>(
+          Invoke(&loader, &TestProfileLoader::SetCreateCallback)));
+
+  // path_2 loads after the first request.
+  EXPECT_CALL(loader, GetProfileByPath(fake_profile_path_2))
+      .WillOnce(Return(static_cast<Profile*>(NULL)))
+      .WillRepeatedly(Return(&profile));
+  EXPECT_CALL(loader, CreateProfileAsync(fake_profile_path_2, _, _, _, false))
+      .WillRepeatedly(WithArgs<0, 1>(
+          Invoke(&loader, &TestProfileLoader::SetCreateCallback)));
+
+  // Try to load both paths twice.
+  // path_1_load is never called because it is first invalidated by the load
+  // request for (path_2), and then invalidated manually.
+  // path_2_load is called both times.
+  StrictMock<MockCallback>* path_1_load = new StrictMock<MockCallback>();
+  StrictMock<MockCallback>* path_2_load = new StrictMock<MockCallback>();
+  EXPECT_CALL(*path_2_load, Run(&profile))
+      .Times(2);
+
+  // Try to load path_1.
+  loader.LoadProfileInvalidatingOtherLoads(
+      fake_profile_path_1, base::Bind(&MockCallback::Run, path_1_load));
+  EXPECT_TRUE(loader.IsAnyProfileLoading());
+
+  // Try to load path_2, this invalidates the previous request.
+  loader.LoadProfileInvalidatingOtherLoads(
+      fake_profile_path_2, base::Bind(&MockCallback::Run, path_2_load));
+
+  // Finish the load request for path_1, then for path_2.
+  loader.RunCreateCallback(fake_profile_path_1, &profile,
+                           Profile::CREATE_STATUS_INITIALIZED);
+  loader.RunCreateCallback(fake_profile_path_2, &profile,
+                           Profile::CREATE_STATUS_INITIALIZED);
+  EXPECT_FALSE(loader.IsAnyProfileLoading());
+
+  // The second request for path_2 should return immediately.
+  loader.LoadProfileInvalidatingOtherLoads(
+      fake_profile_path_2, base::Bind(&MockCallback::Run, path_2_load));
+
+  // Make a second request for path_1, and invalidate it.
+  loader.LoadProfileInvalidatingOtherLoads(
+      fake_profile_path_1, base::Bind(&MockCallback::Run, path_1_load));
+  loader.InvalidatePendingProfileLoads();
+}
+
+}  // namespace
diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc
index 5a06c72..7be5e41 100644
--- a/chrome/browser/profiles/profile_manager.cc
+++ b/chrome/browser/profiles/profile_manager.cc
@@ -34,7 +34,7 @@
 #include "chrome/browser/sync/profile_sync_service.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/webui/sync_promo/sync_promo_ui.h"
+#include "chrome/browser/ui/sync/sync_promo_ui.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "chrome/common/chrome_paths_internal.h"
@@ -161,6 +161,11 @@
   ProfilesToDelete().push_back(path);
 }
 
+bool IsProfileMarkedForDeletion(const base::FilePath& profile_path) {
+  return std::find(ProfilesToDelete().begin(), ProfilesToDelete().end(),
+      profile_path) != ProfilesToDelete().end();
+}
+
 #if defined(OS_CHROMEOS)
 void CheckCryptohomeIsMounted(chromeos::DBusMethodCallStatus call_status,
                               bool is_mounted) {
@@ -197,8 +202,8 @@
     // Delete both the profile directory and its corresponding cache.
     base::FilePath cache_path;
     chrome::GetUserCacheDirectory(*it, &cache_path);
-    file_util::Delete(*it, true);
-    file_util::Delete(cache_path, true);
+    base::Delete(*it, true);
+    base::Delete(cache_path, true);
   }
   ProfilesToDelete().clear();
 }
@@ -494,8 +499,7 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   // Make sure that this profile is not pending deletion.
-  if (std::find(ProfilesToDelete().begin(), ProfilesToDelete().end(),
-      profile_path) != ProfilesToDelete().end()) {
+  if (IsProfileMarkedForDeletion(profile_path)) {
     if (!callback.is_null())
       callback.Run(NULL, Profile::CREATE_STATUS_LOCAL_FAIL);
     return;
@@ -1042,23 +1046,28 @@
     const base::FilePath& profile_dir,
     const CreateCallback& callback) {
   DCHECK(IsMultipleProfilesEnabled());
-
   PrefService* local_state = g_browser_process->local_state();
   ProfileInfoCache& cache = GetProfileInfoCache();
+
   if (profile_dir.BaseName().MaybeAsASCII() ==
       local_state->GetString(prefs::kProfileLastUsed)) {
     // Update the last used profile pref before closing browser windows. This
     // way the correct last used profile is set for any notification observers.
-    std::string last_non_managed_profile;
+    base::FilePath last_non_managed_profile_path;
     for (size_t i = 0; i < cache.GetNumberOfProfiles(); ++i) {
       base::FilePath cur_path = cache.GetPathOfProfileAtIndex(i);
-      if (cur_path != profile_dir && !cache.ProfileIsManagedAtIndex(i)) {
-        last_non_managed_profile = cur_path.BaseName().MaybeAsASCII();
+      // Make sure that this profile is not pending deletion.
+      if (cur_path != profile_dir && !cache.ProfileIsManagedAtIndex(i) &&
+          !IsProfileMarkedForDeletion(cur_path)) {
+        last_non_managed_profile_path = cur_path;
         break;
       }
     }
+
     // If we're deleting the last (non-managed) profile, then create a new
     // profile in its place.
+    const std::string last_non_managed_profile =
+        last_non_managed_profile_path.BaseName().MaybeAsASCII();
     if (last_non_managed_profile.empty()) {
       base::FilePath new_path = GenerateNextProfileDirectoryPath();
       // Make sure the last used profile path is pointing at it. This way the
@@ -1071,13 +1080,62 @@
                          string16(),
                          false);
     } else {
+      // On the Mac, the browser process is not killed when all browser windows
+      // are closed, so just in case we are deleting the active profile, and no
+      // other profile has been loaded, we must pre-load a next one.
+#if defined(OS_MACOSX)
+      CreateProfileAsync(last_non_managed_profile_path,
+                         base::Bind(&ProfileManager::OnNewActiveProfileLoaded,
+                                    base::Unretained(this),
+                                    profile_dir,
+                                    last_non_managed_profile_path,
+                                    callback),
+                         string16(),
+                         string16(),
+                         false);
+      return;
+#else
+      // For OS_MACOSX the pref is updated in the callback to make sure that
+      // it isn't used before the profile is actually loaded.
       local_state->SetString(prefs::kProfileLastUsed, last_non_managed_profile);
+#endif
     }
   }
+  FinishDeletingProfile(profile_dir);
+}
 
+void ProfileManager::OnNewActiveProfileLoaded(
+    const base::FilePath& profile_to_delete_path,
+    const base::FilePath& last_non_managed_profile_path,
+    const CreateCallback& original_callback,
+    Profile* loaded_profile,
+    Profile::CreateStatus status) {
+  DCHECK(status != Profile::CREATE_STATUS_LOCAL_FAIL &&
+         status != Profile::CREATE_STATUS_REMOTE_FAIL);
+
+  // Only run the code if the profile initialization has finished completely.
+  if (status == Profile::CREATE_STATUS_INITIALIZED) {
+    if (IsProfileMarkedForDeletion(last_non_managed_profile_path)) {
+      // If the profile we tried to load as the next active profile has been
+      // deleted, then retry deleting this profile to redo the logic to load
+      // the next available profile.
+      ScheduleProfileForDeletion(profile_to_delete_path, original_callback);
+    } else {
+      // Update the local state as promised in the ScheduleProfileForDeletion.
+      g_browser_process->local_state()->SetString(
+          prefs::kProfileLastUsed,
+          last_non_managed_profile_path.BaseName().MaybeAsASCII());
+      FinishDeletingProfile(profile_to_delete_path);
+    }
+  }
+}
+
+void ProfileManager::FinishDeletingProfile(const base::FilePath& profile_dir) {
+  ProfileInfoCache& cache = GetProfileInfoCache();
   // TODO(sail): Due to bug 88586 we don't delete the profile instance. Once we
   // start deleting the profile instance we need to close background apps too.
   Profile* profile = GetProfileByPath(profile_dir);
+
   if (profile) {
     BrowserList::CloseAllBrowsersWithProfile(profile);
 
diff --git a/chrome/browser/profiles/profile_manager.h b/chrome/browser/profiles/profile_manager.h
index 21f4033..1b2ba42 100644
--- a/chrome/browser/profiles/profile_manager.h
+++ b/chrome/browser/profiles/profile_manager.h
@@ -289,6 +289,9 @@
   // Returns true if the profile was added, false otherwise.
   bool AddProfile(Profile* profile);
 
+  // Schedules the profile at the given path to be deleted on shutdown.
+  void FinishDeletingProfile(const base::FilePath& profile_dir);
+
   // Registers profile with given info. Returns pointer to created ProfileInfo
   // entry.
   ProfileInfo* RegisterProfile(Profile* profile, bool created);
@@ -326,6 +329,17 @@
                     Profile* profile,
                     Profile::CreateStatus status);
 
+  // If the |loaded_profile| has been loaded succesfully (according to |status|)
+  // and isn't already scheduled for deletion, then finishes adding
+  // |profile_to_delete_dir| to the queue of profiles to be deleted, and updates
+  // the kProfileLastUsed preference based on |last_non_managed_profile_path|.
+  void OnNewActiveProfileLoaded(
+      const base::FilePath& profile_to_delete_path,
+      const base::FilePath& last_non_managed_profile_path,
+      const CreateCallback& original_callback,
+      Profile* loaded_profile,
+      Profile::CreateStatus status);
+
   content::NotificationRegistrar registrar_;
 
   // The path to the user data directory (DIR_USER_DATA).
diff --git a/chrome/browser/profiles/profile_manager_unittest.cc b/chrome/browser/profiles/profile_manager_unittest.cc
index adaf53a..dd46660 100644
--- a/chrome/browser/profiles/profile_manager_unittest.cc
+++ b/chrome/browser/profiles/profile_manager_unittest.cc
@@ -15,7 +15,6 @@
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
-#include "chrome/browser/extensions/event_router_forwarder.h"
 #include "chrome/browser/history/history_service.h"
 #include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/io_thread.h"
@@ -97,7 +96,6 @@
 
   ProfileManagerTest()
       : local_state_(TestingBrowserProcess::GetGlobal()),
-        extension_event_router_forwarder_(new extensions::EventRouterForwarder),
         ui_thread_(BrowserThread::UI, &message_loop_),
         db_thread_(BrowserThread::DB, &message_loop_),
         file_thread_(BrowserThread::FILE, &message_loop_) {
@@ -120,6 +118,19 @@
     message_loop_.RunUntilIdle();
   }
 
+  // Helper function to create a profile with |name| for a profile |manager|.
+  void CreateProfileAsync(ProfileManager* manager,
+                          const std::string& name,
+                          MockObserver* mock_observer) {
+    manager->CreateProfileAsync(
+        temp_dir_.path().AppendASCII(name),
+        base::Bind(&MockObserver::OnProfileCreated,
+                   base::Unretained(mock_observer)),
+        UTF8ToUTF16(name),
+        string16(),
+        false);
+  }
+
 #if defined(OS_CHROMEOS)
   chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
   chromeos::ScopedTestCrosSettings test_cros_settings_;
@@ -128,9 +139,6 @@
   // The path to temporary directory used to contain the test operations.
   base::ScopedTempDir temp_dir_;
   ScopedTestingLocalState local_state_;
-  scoped_refptr<extensions::EventRouterForwarder>
-      extension_event_router_forwarder_;
-
   base::MessageLoopForUI message_loop_;
   content::TestBrowserThread ui_thread_;
   content::TestBrowserThread db_thread_;
@@ -240,17 +248,12 @@
 // Tests asynchronous profile creation mechanism.
 // Crashes: http://crbug.com/89421
 TEST_F(ProfileManagerTest, DISABLED_CreateProfileAsync) {
-  base::FilePath dest_path =
-      temp_dir_.path().Append(FILE_PATH_LITERAL("New Profile"));
-
   MockObserver mock_observer;
   EXPECT_CALL(mock_observer, OnProfileCreated(
       testing::NotNull(), NotFail())).Times(testing::AtLeast(1));
 
-  g_browser_process->profile_manager()->CreateProfileAsync(dest_path,
-      base::Bind(&MockObserver::OnProfileCreated,
-                 base::Unretained(&mock_observer)),
-      string16(), string16(), false);
+  CreateProfileAsync(g_browser_process->profile_manager(),
+                     "New Profile", &mock_observer);
 
   message_loop_.RunUntilIdle();
 }
@@ -262,9 +265,6 @@
 }
 
 TEST_F(ProfileManagerTest, CreateProfileAsyncMultipleRequests) {
-  base::FilePath dest_path =
-      temp_dir_.path().Append(FILE_PATH_LITERAL("New Profile"));
-
   g_created_profile = NULL;
 
   MockObserver mock_observer1;
@@ -278,28 +278,17 @@
       SameNotNull(), NotFail())).Times(testing::AtLeast(1));
 
   ProfileManager* profile_manager = g_browser_process->profile_manager();
-
-  profile_manager->CreateProfileAsync(dest_path,
-      base::Bind(&MockObserver::OnProfileCreated,
-                 base::Unretained(&mock_observer1)),
-                 string16(), string16(), false);
-  profile_manager->CreateProfileAsync(dest_path,
-      base::Bind(&MockObserver::OnProfileCreated,
-                 base::Unretained(&mock_observer2)),
-                 string16(), string16(), false);
-  profile_manager->CreateProfileAsync(dest_path,
-      base::Bind(&MockObserver::OnProfileCreated,
-                 base::Unretained(&mock_observer3)),
-                 string16(), string16(), false);
+  const std::string profile_name = "New Profile";
+  CreateProfileAsync(profile_manager, profile_name, &mock_observer1);
+  CreateProfileAsync(profile_manager, profile_name, &mock_observer2);
+  CreateProfileAsync(profile_manager, profile_name, &mock_observer3);
 
   message_loop_.RunUntilIdle();
 }
 
 TEST_F(ProfileManagerTest, CreateProfilesAsync) {
-  base::FilePath dest_path1 =
-      temp_dir_.path().Append(FILE_PATH_LITERAL("New Profile 1"));
-  base::FilePath dest_path2 =
-      temp_dir_.path().Append(FILE_PATH_LITERAL("New Profile 2"));
+  const std::string profile_name1 = "New Profile 1";
+  const std::string profile_name2 = "New Profile 2";
 
   MockObserver mock_observer;
   EXPECT_CALL(mock_observer, OnProfileCreated(
@@ -307,14 +296,8 @@
 
   ProfileManager* profile_manager = g_browser_process->profile_manager();
 
-  profile_manager->CreateProfileAsync(dest_path1,
-      base::Bind(&MockObserver::OnProfileCreated,
-                 base::Unretained(&mock_observer)),
-                 string16(), string16(), false);
-  profile_manager->CreateProfileAsync(dest_path2,
-      base::Bind(&MockObserver::OnProfileCreated,
-                 base::Unretained(&mock_observer)),
-                 string16(), string16(), false);
+  CreateProfileAsync(profile_manager, profile_name1, &mock_observer);
+  CreateProfileAsync(profile_manager, profile_name2, &mock_observer);
 
   message_loop_.RunUntilIdle();
 }
@@ -475,8 +458,7 @@
   ASSERT_EQ(0U, last_opened_profiles.size());
 
   // Create a browser for profile1.
-  Browser::CreateParams profile1_params(profile1,
-                                        chrome::HOST_DESKTOP_TYPE_NATIVE);
+  Browser::CreateParams profile1_params(profile1, chrome::GetActiveDesktop());
   scoped_ptr<Browser> browser1a(
       chrome::CreateBrowserWithTestWindowForParams(&profile1_params));
 
@@ -485,8 +467,7 @@
   EXPECT_EQ(profile1, last_opened_profiles[0]);
 
   // And for profile2.
-  Browser::CreateParams profile2_params(profile2,
-                                        chrome::HOST_DESKTOP_TYPE_NATIVE);
+  Browser::CreateParams profile2_params(profile2, chrome::GetActiveDesktop());
   scoped_ptr<Browser> browser2(
       chrome::CreateBrowserWithTestWindowForParams(&profile2_params));
 
@@ -539,14 +520,12 @@
   ASSERT_TRUE(profile2);
 
   // Create a browser for profile1.
-  Browser::CreateParams profile1_params(profile1,
-                                        chrome::HOST_DESKTOP_TYPE_NATIVE);
+  Browser::CreateParams profile1_params(profile1, chrome::GetActiveDesktop());
   scoped_ptr<Browser> browser1(
       chrome::CreateBrowserWithTestWindowForParams(&profile1_params));
 
   // And for profile2.
-  Browser::CreateParams profile2_params(profile2,
-                                        chrome::HOST_DESKTOP_TYPE_NATIVE);
+  Browser::CreateParams profile2_params(profile2, chrome::GetActiveDesktop());
   scoped_ptr<Browser> browser2(
       chrome::CreateBrowserWithTestWindowForParams(&profile2_params));
 
@@ -598,8 +577,7 @@
   ASSERT_EQ(0U, last_opened_profiles.size());
 
   // Create a browser for profile1.
-  Browser::CreateParams profile1_params(profile1,
-                                        chrome::HOST_DESKTOP_TYPE_NATIVE);
+  Browser::CreateParams profile1_params(profile1, chrome::GetActiveDesktop());
   scoped_ptr<Browser> browser1(
       chrome::CreateBrowserWithTestWindowForParams(&profile1_params));
 
@@ -608,8 +586,7 @@
   EXPECT_EQ(profile1, last_opened_profiles[0]);
 
   // And for profile2.
-  Browser::CreateParams profile2_params(profile2,
-                                        chrome::HOST_DESKTOP_TYPE_NATIVE);
+  Browser::CreateParams profile2_params(profile2, chrome::GetActiveDesktop());
   scoped_ptr<Browser> browser2a(
       chrome::CreateBrowserWithTestWindowForParams(&profile2_params));
 
@@ -640,3 +617,155 @@
   ASSERT_EQ(0U, last_opened_profiles.size());
 }
 #endif  // !defined(OS_ANDROID)
+
+#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+// There's no Browser object on Android and there's no multi-profiles on Chrome.
+TEST_F(ProfileManagerTest, ActiveProfileDeleted) {
+  ProfileManager* profile_manager = g_browser_process->profile_manager();
+  ASSERT_TRUE(profile_manager);
+
+  // Create and load two profiles.
+  const std::string profile_name1 = "New Profile 1";
+  const std::string profile_name2 = "New Profile 2";
+  base::FilePath dest_path1 =
+      temp_dir_.path().AppendASCII(profile_name1);
+  base::FilePath dest_path2 =
+      temp_dir_.path().AppendASCII(profile_name2);
+
+  MockObserver mock_observer;
+  EXPECT_CALL(mock_observer, OnProfileCreated(
+      testing::NotNull(), NotFail())).Times(testing::AtLeast(3));
+
+  CreateProfileAsync(profile_manager, profile_name1, &mock_observer);
+  CreateProfileAsync(profile_manager, profile_name2, &mock_observer);
+  message_loop_.RunUntilIdle();
+
+  EXPECT_EQ(2u, profile_manager->GetLoadedProfiles().size());
+  EXPECT_EQ(2u, profile_manager->GetProfileInfoCache().GetNumberOfProfiles());
+
+  // Set the active profile.
+  PrefService* local_state = g_browser_process->local_state();
+  local_state->SetString(prefs::kProfileLastUsed, profile_name1);
+
+  // Delete the active profile.
+  profile_manager->ScheduleProfileForDeletion(dest_path1,
+                                              ProfileManager::CreateCallback());
+  // Spin the message loop so that all the callbacks can finish running.
+  message_loop_.RunUntilIdle();
+
+  EXPECT_EQ(dest_path2, profile_manager->GetLastUsedProfile()->GetPath());
+  EXPECT_EQ(profile_name2, local_state->GetString(prefs::kProfileLastUsed));
+}
+#endif  // !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+
+#if defined(OS_MACOSX)
+// These tests are for a Mac-only code path that assumes the browser
+// process isn't killed when all browser windows are closed.
+TEST_F(ProfileManagerTest, ActiveProfileDeletedNeedsToLoadNextProfile) {
+  ProfileManager* profile_manager = g_browser_process->profile_manager();
+  ASSERT_TRUE(profile_manager);
+
+  // Create and load one profile, and just create a second profile.
+  const std::string profile_name1 = "New Profile 1";
+  const std::string profile_name2 = "New Profile 2";
+  base::FilePath dest_path1 =
+      temp_dir_.path().AppendASCII(profile_name1);
+  base::FilePath dest_path2 =
+      temp_dir_.path().AppendASCII(profile_name2);
+
+  MockObserver mock_observer;
+  EXPECT_CALL(mock_observer, OnProfileCreated(
+      testing::NotNull(), NotFail())).Times(testing::AtLeast(2));
+  CreateProfileAsync(profile_manager, profile_name1, &mock_observer);
+  message_loop_.RunUntilIdle();
+
+  // Track the profile, but don't load it.
+  ProfileInfoCache& cache = profile_manager->GetProfileInfoCache();
+  cache.AddProfileToCache(dest_path2, ASCIIToUTF16(profile_name2),
+                          string16(), 0, false);
+  message_loop_.RunUntilIdle();
+
+  EXPECT_EQ(1u, profile_manager->GetLoadedProfiles().size());
+  EXPECT_EQ(2u, cache.GetNumberOfProfiles());
+
+  // Set the active profile.
+  PrefService* local_state = g_browser_process->local_state();
+  local_state->SetString(prefs::kProfileLastUsed,
+                         dest_path1.BaseName().MaybeAsASCII());
+
+  // Delete the active profile. This should switch and load the unloaded
+  // profile.
+  profile_manager->ScheduleProfileForDeletion(dest_path1,
+                                              ProfileManager::CreateCallback());
+
+  // Spin the message loop so that all the callbacks can finish running.
+  message_loop_.RunUntilIdle();
+
+  EXPECT_EQ(dest_path2, profile_manager->GetLastUsedProfile()->GetPath());
+  EXPECT_EQ(profile_name2, local_state->GetString(prefs::kProfileLastUsed));
+}
+
+// This tests the recursive call in ProfileManager::OnNewActiveProfileLoaded
+// by simulating a scenario in which the profile that is being loaded as
+// the next active profile has also been marked for deletion, so the
+// ProfileManager needs to recursively select a different next profile.
+TEST_F(ProfileManagerTest, ActiveProfileDeletedNextProfileDeletedToo) {
+  ProfileManager* profile_manager = g_browser_process->profile_manager();
+  ASSERT_TRUE(profile_manager);
+
+  // Create and load one profile, and create two more profiles.
+  const std::string profile_name1 = "New Profile 1";
+  const std::string profile_name2 = "New Profile 2";
+  const std::string profile_name3 = "New Profile 3";
+  base::FilePath dest_path1 =
+      temp_dir_.path().AppendASCII(profile_name1);
+  base::FilePath dest_path2 =
+      temp_dir_.path().AppendASCII(profile_name2);
+  base::FilePath dest_path3 =
+      temp_dir_.path().AppendASCII(profile_name3);
+
+  MockObserver mock_observer;
+  EXPECT_CALL(mock_observer, OnProfileCreated(
+      testing::NotNull(), NotFail())).Times(testing::AtLeast(2));
+  CreateProfileAsync(profile_manager, profile_name1, &mock_observer);
+  message_loop_.RunUntilIdle();
+
+  // Create the other profiles, but don't load them. Assign a fake avatar icon
+  // to ensure that profiles in the info cache are sorted by the profile name,
+  // and not randomly by the avatar name.
+  ProfileInfoCache& cache = profile_manager->GetProfileInfoCache();
+  cache.AddProfileToCache(dest_path2, ASCIIToUTF16(profile_name2),
+                          ASCIIToUTF16(profile_name2), 1, false);
+  cache.AddProfileToCache(dest_path3, ASCIIToUTF16(profile_name3),
+                          ASCIIToUTF16(profile_name3), 2, false);
+
+  message_loop_.RunUntilIdle();
+
+  EXPECT_EQ(1u, profile_manager->GetLoadedProfiles().size());
+  EXPECT_EQ(3u, cache.GetNumberOfProfiles());
+
+  // Set the active profile.
+  PrefService* local_state = g_browser_process->local_state();
+  local_state->SetString(prefs::kProfileLastUsed,
+                         dest_path1.BaseName().MaybeAsASCII());
+
+  // Delete the active profile, Profile1.
+  // This will post a CreateProfileAsync message, that tries to load Profile2,
+  // which checks that the profile is not being deleted, and then calls back
+  // FinishDeletingProfile for Profile1.
+  // Try to break this flow by setting the active profile to Profile2 in the
+  // middle (so after the first posted message), and trying to delete Profile2,
+  // so that the ProfileManager has to look for a different profile to load.
+  profile_manager->ScheduleProfileForDeletion(dest_path1,
+                                              ProfileManager::CreateCallback());
+  local_state->SetString(prefs::kProfileLastUsed,
+                         dest_path2.BaseName().MaybeAsASCII());
+  profile_manager->ScheduleProfileForDeletion(dest_path2,
+                                              ProfileManager::CreateCallback());
+  // Spin the message loop so that all the callbacks can finish running.
+  message_loop_.RunUntilIdle();
+
+  EXPECT_EQ(dest_path3, profile_manager->GetLastUsedProfile()->GetPath());
+  EXPECT_EQ(profile_name3, local_state->GetString(prefs::kProfileLastUsed));
+}
+#endif  // !defined(OS_MACOSX)
diff --git a/chrome/browser/profiles/profile_shortcut_manager_unittest_win.cc b/chrome/browser/profiles/profile_shortcut_manager_unittest_win.cc
index c918574..e4eb340 100644
--- a/chrome/browser/profiles/profile_shortcut_manager_unittest_win.cc
+++ b/chrome/browser/profiles/profile_shortcut_manager_unittest_win.cc
@@ -391,7 +391,7 @@
       GetDefaultShortcutPathForProfile(profile_2_name_);
 
   // Delete the shortcut for the first profile, but keep the one for the 2nd.
-  ASSERT_TRUE(file_util::Delete(profile_1_shortcut_path, false));
+  ASSERT_TRUE(base::Delete(profile_1_shortcut_path, false));
   ASSERT_FALSE(file_util::PathExists(profile_1_shortcut_path));
   ASSERT_TRUE(file_util::PathExists(profile_2_shortcut_path));
 
@@ -415,7 +415,7 @@
       GetDefaultShortcutPathForProfile(profile_2_name_);
 
   // Delete the shortcut for the first profile, but keep the one for the 2nd.
-  ASSERT_TRUE(file_util::Delete(profile_1_shortcut_path, false));
+  ASSERT_TRUE(base::Delete(profile_1_shortcut_path, false));
   ASSERT_FALSE(file_util::PathExists(profile_1_shortcut_path));
   ASSERT_TRUE(file_util::PathExists(profile_2_shortcut_path));
 
@@ -444,8 +444,8 @@
       GetDefaultShortcutPathForProfile(profile_3_name_);
 
   // Delete shortcuts for the first two profiles.
-  ASSERT_TRUE(file_util::Delete(profile_1_shortcut_path, false));
-  ASSERT_TRUE(file_util::Delete(profile_2_shortcut_path, false));
+  ASSERT_TRUE(base::Delete(profile_1_shortcut_path, false));
+  ASSERT_TRUE(base::Delete(profile_2_shortcut_path, false));
 
   // Only the shortcut to the third profile should exist.
   ASSERT_FALSE(file_util::PathExists(profile_1_shortcut_path));
@@ -492,7 +492,7 @@
       GetDefaultShortcutPathForProfile(profile_2_name_);
   const base::FilePath profile_2_shortcut_path_2 =
       GetUserShortcutsDirectory().Append(L"MyChrome.lnk");
-  ASSERT_TRUE(file_util::Move(profile_2_shortcut_path_1,
+  ASSERT_TRUE(base::Move(profile_2_shortcut_path_1,
                               profile_2_shortcut_path_2));
 
   // Ensure that a new shortcut does not get made if the old one was renamed.
@@ -503,7 +503,7 @@
                                 profile_2_path_);
 
   // Delete the renamed shortcut and try to create it again, which should work.
-  ASSERT_TRUE(file_util::Delete(profile_2_shortcut_path_2, false));
+  ASSERT_TRUE(base::Delete(profile_2_shortcut_path_2, false));
   EXPECT_FALSE(file_util::PathExists(profile_2_shortcut_path_2));
   profile_shortcut_manager_->CreateProfileShortcut(profile_2_path_);
   RunPendingTasks();
@@ -574,7 +574,7 @@
 
   // Delete the shortcut that got created for this profile and instead make
   // a new one without any command-line flags.
-  ASSERT_TRUE(file_util::Delete(GetDefaultShortcutPathForProfile(string16()),
+  ASSERT_TRUE(base::Delete(GetDefaultShortcutPathForProfile(string16()),
                                 false));
   const base::FilePath regular_shortcut_path =
       CreateRegularShortcutWithName(FROM_HERE,
@@ -592,7 +592,7 @@
 
   // Delete the shortcut that got created for this profile and instead make
   // two new ones without any command-line flags.
-  ASSERT_TRUE(file_util::Delete(GetDefaultShortcutPathForProfile(string16()),
+  ASSERT_TRUE(base::Delete(GetDefaultShortcutPathForProfile(string16()),
                                 false));
   const base::FilePath regular_shortcut_path =
       CreateRegularShortcutWithName(FROM_HERE,
@@ -664,7 +664,7 @@
   // Delete the shortcut and check that the function returns false.
   const base::FilePath profile_2_shortcut_path =
       GetDefaultShortcutPathForProfile(profile_2_name_);
-  ASSERT_TRUE(file_util::Delete(profile_2_shortcut_path, false));
+  ASSERT_TRUE(base::Delete(profile_2_shortcut_path, false));
   EXPECT_FALSE(file_util::PathExists(profile_2_shortcut_path));
   profile_shortcut_manager_->HasProfileShortcuts(profile_2_path_, callback);
   RunPendingTasks();
@@ -752,7 +752,7 @@
       GetDefaultShortcutPathForProfile(profile_2_name_);
 
   // Delete the shortcut for the first profile, but keep the one for the 2nd.
-  ASSERT_TRUE(file_util::Delete(profile_1_shortcut_path, false));
+  ASSERT_TRUE(base::Delete(profile_1_shortcut_path, false));
   ASSERT_FALSE(file_util::PathExists(profile_1_shortcut_path));
   ASSERT_TRUE(file_util::PathExists(profile_2_shortcut_path));
 
diff --git a/chrome/browser/profiles/profile_shortcut_manager_win.cc b/chrome/browser/profiles/profile_shortcut_manager_win.cc
index abfb1d6..239a54e 100644
--- a/chrome/browser/profiles/profile_shortcut_manager_win.cc
+++ b/chrome/browser/profiles/profile_shortcut_manager_win.cc
@@ -255,7 +255,7 @@
 // Renames the given desktop shortcut and informs the shell of this change.
 bool RenameDesktopShortcut(const base::FilePath& old_shortcut_path,
                            const base::FilePath& new_shortcut_path) {
-  if (!file_util::Move(old_shortcut_path, new_shortcut_path))
+  if (!base::Move(old_shortcut_path, new_shortcut_path))
     return false;
 
   // Notify the shell of the rename, which allows the icon to keep its position
@@ -292,7 +292,7 @@
     const base::FilePath possible_new_system_shortcut =
         system_shortcuts_directory.Append(new_shortcut_filename);
     if (file_util::PathExists(possible_new_system_shortcut))
-      file_util::Delete(old_shortcut_path, false);
+      base::Delete(old_shortcut_path, false);
     else if (!RenameDesktopShortcut(old_shortcut_path, new_shortcut_path))
       DLOG(ERROR) << "Could not rename Windows profile desktop shortcut.";
   } else {
@@ -437,9 +437,9 @@
 
   BrowserDistribution* distribution = BrowserDistribution::GetDistribution();
   for (size_t i = 0; i < shortcuts.size(); ++i) {
-    // Use file_util::Delete() instead of ShellUtil::RemoveShortcut(), as the
+    // Use base::Delete() instead of ShellUtil::RemoveShortcut(), as the
     // latter causes non-profile taskbar shortcuts to be unpinned.
-    file_util::Delete(shortcuts[i], false);
+    base::Delete(shortcuts[i], false);
     // Notify the shell that the shortcut was deleted to ensure desktop refresh.
     SHChangeNotify(SHCNE_DELETE, SHCNF_PATH, shortcuts[i].value().c_str(),
                    NULL);
@@ -447,7 +447,7 @@
 
   const base::FilePath icon_path =
       profile_path.AppendASCII(profiles::internal::kProfileIconFileName);
-  file_util::Delete(icon_path, false);
+  base::Delete(icon_path, false);
 
   // If |ensure_shortcuts_remain| is true and deleting this profile caused the
   // last shortcuts to be removed, re-create a regular non-profile shortcut.
@@ -557,8 +557,7 @@
 // static
 bool ProfileShortcutManager::IsFeatureEnabled() {
   return BrowserDistribution::GetDistribution()->CanCreateDesktopShortcuts() &&
-      !CommandLine::ForCurrentProcess()->HasSwitch(switches::kUserDataDir) &&
-      !CommandLine::ForCurrentProcess()->HasSwitch(switches::kShowAppList);
+      !CommandLine::ForCurrentProcess()->HasSwitch(switches::kUserDataDir);
 }
 
 // static
diff --git a/chrome/browser/renderer_host/chrome_render_message_filter.cc b/chrome/browser/renderer_host/chrome_render_message_filter.cc
index 7166497..5ab3fe8 100644
--- a/chrome/browser/renderer_host/chrome_render_message_filter.cc
+++ b/chrome/browser/renderer_host/chrome_render_message_filter.cc
@@ -44,7 +44,7 @@
 #include "content/public/browser/resource_dispatcher_host.h"
 #include "content/public/common/process_type.h"
 #include "extensions/common/constants.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 #if defined(USE_TCMALLOC)
 #include "chrome/browser/browser_about_handler.h"
diff --git a/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate.h b/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate.h
index b13a4e0..b23dcad 100644
--- a/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate.h
+++ b/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate.h
@@ -58,7 +58,6 @@
 - (void)setHasHorizontalScrollbar:(BOOL)hasHorizontalScrollbar;
 - (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item
                       isValidItem:(BOOL*)valid;
-- (void)compositingIOSurfaceCreated;
 
 @end
 
diff --git a/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate.mm b/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate.mm
index 17dac1b..2961093 100644
--- a/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate.mm
+++ b/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate.mm
@@ -17,7 +17,6 @@
 #include "chrome/browser/ui/browser_finder.h"
 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
 #import "chrome/browser/ui/cocoa/history_overlay_controller.h"
-#import "chrome/browser/ui/cocoa/tab_contents/overlayable_contents_controller.h"
 #import "chrome/browser/ui/cocoa/view_id_util.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/spellcheck_messages.h"
@@ -280,14 +279,6 @@
   return NO;
 }
 
-- (void)compositingIOSurfaceCreated {
-  NSView* nativeView = renderWidgetHost_->GetView()->GetNativeView();
-  BrowserWindowController* windowController =
-      [BrowserWindowController browserWindowControllerForView:nativeView];
-  [[windowController overlayableContentsController]
-        activeContentsCompositingIOSurfaceCreated];
-}
-
 // Spellchecking methods
 // The next five methods are implemented here since this class is the first
 // responder for anything in the browser.
diff --git a/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate_browsertest.cc b/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate_browsertest.cc
index 1a0949e..615b577 100644
--- a/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate_browsertest.cc
+++ b/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate_browsertest.cc
@@ -16,8 +16,8 @@
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test_utils.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/net_util.h"
+#include "url/gurl.h"
 
 class ChromeRenderWidgetHostViewMacDelegateTest : public InProcessBrowserTest {
  public:
diff --git a/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc b/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc
index 2f33ef2..93df87e 100644
--- a/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc
+++ b/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc
@@ -207,8 +207,7 @@
     const std::string& method,
     const GURL& url,
     ResourceType::Type resource_type,
-    content::ResourceContext* resource_context,
-    const content::Referrer& referrer) {
+    content::ResourceContext* resource_context) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 
   // Handle a PREFETCH resource type. If prefetch is disabled, squelch the
diff --git a/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.h b/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.h
index 9afd08a..5e81a17 100644
--- a/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.h
+++ b/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.h
@@ -42,8 +42,7 @@
       const std::string& method,
       const GURL& url,
       ResourceType::Type resource_type,
-      content::ResourceContext* resource_context,
-      const content::Referrer& referrer) OVERRIDE;
+      content::ResourceContext* resource_context) OVERRIDE;
   virtual void RequestBeginning(
       net::URLRequest* request,
       content::ResourceContext* resource_context,
diff --git a/chrome/browser/renderer_host/pepper/OWNERS b/chrome/browser/renderer_host/pepper/OWNERS
index 3abceff..dc19a03 100644
--- a/chrome/browser/renderer_host/pepper/OWNERS
+++ b/chrome/browser/renderer_host/pepper/OWNERS
@@ -1,2 +1,3 @@
+dmichael@chromium.org
 raymes@chromium.org
 yzshen@chromium.org
diff --git a/chrome/browser/renderer_host/pepper/pepper_broker_message_filter.cc b/chrome/browser/renderer_host/pepper/pepper_broker_message_filter.cc
index f5d7dd8..60ffa5c 100644
--- a/chrome/browser/renderer_host/pepper/pepper_broker_message_filter.cc
+++ b/chrome/browser/renderer_host/pepper/pepper_broker_message_filter.cc
@@ -12,11 +12,11 @@
 #include "content/public/browser/browser_ppapi_host.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_process_host.h"
-#include "googleurl/src/gurl.h"
 #include "ipc/ipc_message_macros.h"
 #include "ppapi/c/pp_errors.h"
 #include "ppapi/host/dispatch_host_message.h"
 #include "ppapi/proxy/ppapi_messages.h"
+#include "url/gurl.h"
 
 using content::BrowserPpapiHost;
 using content::BrowserThread;
diff --git a/chrome/browser/renderer_host/pepper/pepper_broker_message_filter.h b/chrome/browser/renderer_host/pepper/pepper_broker_message_filter.h
index d59f505..95b40fd 100644
--- a/chrome/browser/renderer_host/pepper/pepper_broker_message_filter.h
+++ b/chrome/browser/renderer_host/pepper/pepper_broker_message_filter.h
@@ -6,9 +6,9 @@
 #define CHROME_BROWSER_RENDERER_HOST_PEPPER_PEPPER_BROKER_MESSAGE_FILTER_H_
 
 #include "base/compiler_specific.h"
-#include "googleurl/src/gurl.h"
 #include "ppapi/c/pp_instance.h"
 #include "ppapi/host/resource_message_filter.h"
+#include "url/gurl.h"
 
 namespace content {
 class BrowserPpapiHost;
diff --git a/chrome/browser/renderer_host/pepper/pepper_crx_file_system_message_filter.h b/chrome/browser/renderer_host/pepper/pepper_crx_file_system_message_filter.h
index b970d11..0ab0c43 100644
--- a/chrome/browser/renderer_host/pepper/pepper_crx_file_system_message_filter.h
+++ b/chrome/browser/renderer_host/pepper/pepper_crx_file_system_message_filter.h
@@ -9,11 +9,11 @@
 #include <string>
 
 #include "base/files/file_path.h"
-#include "googleurl/src/gurl.h"
 #include "ppapi/c/pp_instance.h"
 #include "ppapi/c/pp_resource.h"
 #include "ppapi/host/resource_host.h"
 #include "ppapi/host/resource_message_filter.h"
+#include "url/gurl.h"
 
 class Profile;
 
diff --git a/chrome/browser/renderer_host/pepper/pepper_extensions_common_message_filter.h b/chrome/browser/renderer_host/pepper/pepper_extensions_common_message_filter.h
index d9dae5c..832e859 100644
--- a/chrome/browser/renderer_host/pepper/pepper_extensions_common_message_filter.h
+++ b/chrome/browser/renderer_host/pepper/pepper_extensions_common_message_filter.h
@@ -13,9 +13,9 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/string16.h"
 #include "chrome/browser/extensions/extension_function.h"
-#include "googleurl/src/gurl.h"
 #include "ppapi/c/pp_instance.h"
 #include "ppapi/host/resource_message_filter.h"
+#include "url/gurl.h"
 
 struct ExtensionHostMsg_Request_Params;
 
diff --git a/chrome/browser/renderer_host/pepper/pepper_flash_browser_host.cc b/chrome/browser/renderer_host/pepper/pepper_flash_browser_host.cc
index 186bca3..85849cf 100644
--- a/chrome/browser/renderer_host/pepper/pepper_flash_browser_host.cc
+++ b/chrome/browser/renderer_host/pepper/pepper_flash_browser_host.cc
@@ -4,14 +4,13 @@
 
 #include "chrome/browser/renderer_host/pepper/pepper_flash_browser_host.h"
 
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/content_settings/cookie_settings.h"
 #include "chrome/browser/profiles/profile.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_ppapi_host.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_process_host.h"
-#include "googleurl/src/gurl.h"
 #include "ipc/ipc_message_macros.h"
 #include "ppapi/c/pp_errors.h"
 #include "ppapi/c/private/ppb_flash.h"
@@ -19,6 +18,7 @@
 #include "ppapi/proxy/ppapi_messages.h"
 #include "ppapi/proxy/resource_message_params.h"
 #include "ppapi/shared_impl/time_conversion.h"
+#include "url/gurl.h"
 
 #if defined(OS_WIN)
 #include <windows.h>
diff --git a/chrome/browser/renderer_host/pepper/pepper_talk_host.cc b/chrome/browser/renderer_host/pepper/pepper_talk_host.cc
index 5251578..3151e69 100644
--- a/chrome/browser/renderer_host/pepper/pepper_talk_host.cc
+++ b/chrome/browser/renderer_host/pepper/pepper_talk_host.cc
@@ -19,6 +19,7 @@
 #if defined(USE_ASH)
 #include "ash/shell.h"
 #include "ash/shell_window_ids.h"
+#include "ash/system/tray/system_tray_notifier.h"
 #include "chrome/browser/ui/simple_message_box.h"
 #include "ui/aura/window.h"
 #endif
@@ -28,6 +29,7 @@
 namespace {
 
 ppapi::host::ReplyMessageContext GetPermissionOnUIThread(
+    PP_TalkPermission permission,
     int render_process_id,
     int render_view_id,
     ppapi::host::ReplyMessageContext reply) {
@@ -40,13 +42,32 @@
     return reply;  // RVH destroyed while task was pending.
 
 #if defined(USE_ASH)
+  string16 title;
+  string16 message;
+
+  switch (permission) {
+    case PP_TALKPERMISSION_SCREENCAST:
+      title = l10n_util::GetStringUTF16(IDS_GTALK_SCREEN_SHARE_DIALOG_TITLE);
+      message = l10n_util::GetStringUTF16(
+          IDS_GTALK_SCREEN_SHARE_DIALOG_MESSAGE);
+      break;
+    case PP_TALKPERMISSION_REMOTING:
+      title = l10n_util::GetStringUTF16(IDS_GTALK_REMOTING_DIALOG_TITLE);
+      message = l10n_util::GetStringUTF16(
+          IDS_GTALK_REMOTING_DIALOG_MESSAGE);
+      break;
+    case PP_TALKPERMISSION_REMOTING_CONTINUE:
+      title = l10n_util::GetStringUTF16(IDS_GTALK_REMOTING_DIALOG_TITLE);
+      message = l10n_util::GetStringUTF16(
+          IDS_GTALK_REMOTING_CONTINUE_DIALOG_MESSAGE);
+      break;
+    default:
+      NOTREACHED();
+      return reply;
+  }
+
   // TODO(brettw). We should not be grabbing the active toplevel window, we
   // should use the toplevel window associated with the render view.
-  const string16 title = l10n_util::GetStringUTF16(
-      IDS_GTALK_SCREEN_SHARE_DIALOG_TITLE);
-  const string16 message = l10n_util::GetStringUTF16(
-      IDS_GTALK_SCREEN_SHARE_DIALOG_MESSAGE);
-
   aura::Window* parent = ash::Shell::GetContainer(
       ash::Shell::GetActiveRootWindow(),
       ash::internal::kShellWindowId_SystemModalContainer);
@@ -60,6 +81,57 @@
   return reply;
 }
 
+void OnTerminateRemotingEventOnUIThread(const base::Closure& stop_callback) {
+  content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
+                                   stop_callback);
+}
+
+ppapi::host::ReplyMessageContext StartRemotingOnUIThread(
+    const base::Closure& stop_callback,
+    int render_process_id,
+    int render_view_id,
+    ppapi::host::ReplyMessageContext reply) {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  content::RenderViewHost* render_view_host =
+      content::RenderViewHost::FromID(render_process_id, render_view_id);
+  if (!render_view_host) {
+    reply.params.set_result(PP_ERROR_FAILED);
+    return reply;  // RVH destroyed while task was pending.
+  }
+
+#if defined(USE_ASH) && defined(OS_CHROMEOS)
+  base::Closure stop_callback_ui_thread = base::Bind(
+      &OnTerminateRemotingEventOnUIThread,
+      stop_callback);
+
+  ash::Shell::GetInstance()->system_tray_notifier()->NotifyScreenShareStart(
+      stop_callback_ui_thread, base::string16());
+  reply.params.set_result(PP_OK);
+#else
+  NOTIMPLEMENTED();
+  reply.params.set_result(PP_ERROR_NOTSUPPORTED);
+#endif
+  return reply;
+}
+
+void StopRemotingOnUIThread() {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+#if defined(USE_ASH) && defined(OS_CHROMEOS)
+  if (ash::Shell::GetInstance()) {
+    ash::Shell::GetInstance()->system_tray_notifier()->NotifyScreenShareStop();
+  }
+#else
+  NOTIMPLEMENTED();
+#endif
+}
+
+ppapi::host::ReplyMessageContext StopRemotingOnUIThreadWithResult(
+    ppapi::host::ReplyMessageContext reply) {
+  reply.params.set_result(PP_OK);
+  StopRemotingOnUIThread();
+  return reply;
+}
+
 }  // namespace
 
 PepperTalkHost::PepperTalkHost(content::BrowserPpapiHost* host,
@@ -67,10 +139,16 @@
                                PP_Resource resource)
     : ppapi::host::ResourceHost(host->GetPpapiHost(), instance, resource),
       weak_factory_(this),
-      browser_ppapi_host_(host) {
+      browser_ppapi_host_(host),
+      remoting_started_(false) {
 }
 
 PepperTalkHost::~PepperTalkHost() {
+  if (remoting_started_) {
+    content::BrowserThread::PostTask(
+        content::BrowserThread::UI, FROM_HERE,
+        base::Bind(&StopRemotingOnUIThread));
+  }
 }
 
 int32_t PepperTalkHost::OnResourceMessageReceived(
@@ -90,8 +168,8 @@
 int32_t PepperTalkHost::OnRequestPermission(
     ppapi::host::HostMessageContext* context,
     PP_TalkPermission permission) {
-  // TODO(dcaiafa): Implement support for other permission types.
-  if (permission != PP_TALKPERMISSION_SCREENCAST)
+  if (permission < PP_TALKPERMISSION_SCREENCAST ||
+      permission >= PP_TALKPERMISSION_NUM_PERMISSIONS)
     return PP_ERROR_BADARGUMENT;
 
   int render_process_id = 0;
@@ -101,31 +179,73 @@
 
   content::BrowserThread::PostTaskAndReplyWithResult(
       content::BrowserThread::UI, FROM_HERE,
-      base::Bind(&GetPermissionOnUIThread, render_process_id, render_view_id,
-                 context->MakeReplyMessageContext()),
-      base::Bind(&PepperTalkHost::GotTalkPermission,
+      base::Bind(&GetPermissionOnUIThread, permission, render_process_id,
+                 render_view_id, context->MakeReplyMessageContext()),
+      base::Bind(&PepperTalkHost::OnRequestPermissionCompleted,
                  weak_factory_.GetWeakPtr()));
   return PP_OK_COMPLETIONPENDING;
 }
 
-void PepperTalkHost::GotTalkPermission(
+int32_t PepperTalkHost::OnStartRemoting(
+    ppapi::host::HostMessageContext* context) {
+  int render_process_id = 0;
+  int render_view_id = 0;
+  browser_ppapi_host_->GetRenderViewIDsForInstance(
+      pp_instance(), &render_process_id, &render_view_id);
+
+  base::Closure remoting_stop_callback = base::Bind(
+      &PepperTalkHost::OnRemotingStopEvent,
+      weak_factory_.GetWeakPtr());
+
+  content::BrowserThread::PostTaskAndReplyWithResult(
+      content::BrowserThread::UI, FROM_HERE,
+      base::Bind(&StartRemotingOnUIThread, remoting_stop_callback,
+                 render_process_id, render_view_id,
+                 context->MakeReplyMessageContext()),
+      base::Bind(&PepperTalkHost::OnStartRemotingCompleted,
+                 weak_factory_.GetWeakPtr()));
+  return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperTalkHost::OnStopRemoting(
+    ppapi::host::HostMessageContext* context) {
+  content::BrowserThread::PostTaskAndReplyWithResult(
+      content::BrowserThread::UI, FROM_HERE,
+      base::Bind(&StopRemotingOnUIThreadWithResult,
+                 context->MakeReplyMessageContext()),
+      base::Bind(&PepperTalkHost::OnStopRemotingCompleted,
+                 weak_factory_.GetWeakPtr()));
+  return PP_OK_COMPLETIONPENDING;
+}
+
+void PepperTalkHost::OnRemotingStopEvent() {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+  remoting_started_ = false;
+  host()->SendUnsolicitedReply(
+      pp_resource(), PpapiPluginMsg_Talk_NotifyEvent(PP_TALKEVENT_TERMINATE));
+}
+
+void PepperTalkHost::OnRequestPermissionCompleted(
     ppapi::host::ReplyMessageContext reply) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
   host()->SendReply(reply, PpapiPluginMsg_Talk_RequestPermissionReply());
 }
 
-int32_t PepperTalkHost::OnStartRemoting(
-    ppapi::host::HostMessageContext* context) {
-  // TODO(dcaiafa): Request IPC audit when this is implemented
-  NOTIMPLEMENTED();
-  return PP_ERROR_FAILED;
+void PepperTalkHost::OnStartRemotingCompleted(
+    ppapi::host::ReplyMessageContext reply) {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+  // Remember to hide remoting UI when resource is deleted.
+  if (reply.params.result() == PP_OK)
+    remoting_started_ = true;
+
+  host()->SendReply(reply, PpapiPluginMsg_Talk_StartRemotingReply());
 }
 
-int32_t PepperTalkHost::OnStopRemoting(
-    ppapi::host::HostMessageContext* context) {
-  // TODO(dcaiafa): Request IPC audit when this is implemented
-  NOTIMPLEMENTED();
-  return PP_ERROR_FAILED;
+void PepperTalkHost::OnStopRemotingCompleted(
+    ppapi::host::ReplyMessageContext reply) {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+  remoting_started_ = false;
+  host()->SendReply(reply, PpapiPluginMsg_Talk_StopRemotingReply());
 }
 
 }  // namespace chrome
diff --git a/chrome/browser/renderer_host/pepper/pepper_talk_host.h b/chrome/browser/renderer_host/pepper/pepper_talk_host.h
index 3b754fd..c5ca13b 100644
--- a/chrome/browser/renderer_host/pepper/pepper_talk_host.h
+++ b/chrome/browser/renderer_host/pepper/pepper_talk_host.h
@@ -29,25 +29,25 @@
                  PP_Resource resource);
   virtual ~PepperTalkHost();
 
+ private:
   // ResourceHost override.
   virtual int32_t OnResourceMessageReceived(
       const IPC::Message& msg,
       ppapi::host::HostMessageContext* context) OVERRIDE;
 
-  // Sends the reply.
-  void GotTalkPermission(ppapi::host::ReplyMessageContext reply);
+  int32_t OnRequestPermission(ppapi::host::HostMessageContext* context,
+                              PP_TalkPermission permission);
+  int32_t OnStartRemoting(ppapi::host::HostMessageContext* context);
+  int32_t OnStopRemoting(ppapi::host::HostMessageContext* context);
+  void OnRemotingStopEvent();
 
- private:
-  int32_t OnRequestPermission(
-      ppapi::host::HostMessageContext* context,
-      PP_TalkPermission permission);
-  int32_t OnStartRemoting(
-      ppapi::host::HostMessageContext* context);
-  int32_t OnStopRemoting(
-      ppapi::host::HostMessageContext* context);
+  void OnRequestPermissionCompleted(ppapi::host::ReplyMessageContext reply);
+  void OnStartRemotingCompleted(ppapi::host::ReplyMessageContext reply);
+  void OnStopRemotingCompleted(ppapi::host::ReplyMessageContext reply);
 
   base::WeakPtrFactory<PepperTalkHost> weak_factory_;
   content::BrowserPpapiHost* browser_ppapi_host_;
+  bool remoting_started_;
 
   DISALLOW_COPY_AND_ASSIGN(PepperTalkHost);
 };
diff --git a/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc b/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc
index d92ec09..cdc9e9e 100644
--- a/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc
+++ b/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc
@@ -3,11 +3,13 @@
 // found in the LICENSE file.
 
 #include "base/command_line.h"
+#include "base/process_util.h"
 #include "chrome/browser/devtools/devtools_window.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/singleton_tabs.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/chrome_notification_types.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/base/in_process_browser_test.h"
@@ -16,6 +18,7 @@
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_observer.h"
 
 using content::RenderViewHost;
 using content::RenderWidgetHost;
@@ -36,27 +39,17 @@
 }
 
 RenderViewHost* FindFirstDevToolsHost() {
-  content::RenderProcessHost::iterator hosts =
-      content::RenderProcessHost::AllHostsIterator();
-  for (; !hosts.IsAtEnd(); hosts.Advance()) {
-    content::RenderProcessHost* render_process_host = hosts.GetCurrentValue();
-    DCHECK(render_process_host);
-    if (!render_process_host->HasConnection())
+  RenderWidgetHost::List widgets = RenderWidgetHost::GetRenderWidgetHosts();
+  for (size_t i = 0; i < widgets.size(); ++i) {
+    if (!widgets[i]->GetProcess()->HasConnection())
       continue;
-    content::RenderProcessHost::RenderWidgetHostsIterator iter(
-        render_process_host->GetRenderWidgetHostsIterator());
-    for (; !iter.IsAtEnd(); iter.Advance()) {
-      const RenderWidgetHost* widget = iter.GetCurrentValue();
-      DCHECK(widget);
-      if (!widget || !widget->IsRenderView())
-        continue;
-      RenderViewHost* host =
-          RenderViewHost::From(const_cast<RenderWidgetHost*>(widget));
-      WebContents* contents = WebContents::FromRenderViewHost(host);
-      GURL url = contents->GetURL();
-      if (url.SchemeIs(chrome::kChromeDevToolsScheme))
-        return host;
-    }
+    if (!widgets[i]->IsRenderView())
+      continue;
+    RenderViewHost* host = RenderViewHost::From(widgets[i]);
+    WebContents* contents = WebContents::FromRenderViewHost(host);
+    GURL url = contents->GetURL();
+    if (url.SchemeIs(chrome::kChromeDevToolsScheme))
+      return host;
   }
   return NULL;
 }
@@ -362,3 +355,66 @@
   EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
   EXPECT_EQ(host_count, RenderProcessHostCount());
 }
+
+// This class's goal is to close the browser window when a renderer process has
+// crashed. It does so by monitoring WebContents for RenderViewGone event and
+// closing the passed in TabStripModel. This is used in the following test case.
+class WindowDestroyer : public content::WebContentsObserver {
+ public:
+  WindowDestroyer(content::WebContents* web_contents, TabStripModel* model)
+      : content::WebContentsObserver(web_contents),
+        tab_strip_model_(model) {
+  }
+
+  virtual void RenderViewGone(base::TerminationStatus status) OVERRIDE {
+    // Wait for the window to be destroyed, which will ensure all other
+    // RenderViewHost objects are deleted before we return and proceed with
+    // the next iteration of notifications.
+    content::WindowedNotificationObserver observer(
+        chrome::NOTIFICATION_BROWSER_CLOSED,
+        content::NotificationService::AllSources());
+    tab_strip_model_->CloseAllTabs();
+    observer.Wait();
+  }
+
+ private:
+  TabStripModel* tab_strip_model_;
+
+  DISALLOW_COPY_AND_ASSIGN(WindowDestroyer);
+};
+
+// Test to ensure that while iterating through all listeners in
+// RenderProcessHost and invalidating them, we remove them properly and don't
+// access already freed objects. See http://crbug.com/255524.
+IN_PROC_BROWSER_TEST_F(ChromeRenderProcessHostTest,
+                       CloseAllTabsDuringProcessDied) {
+  GURL url(chrome::kChromeUINewTabURL);
+
+  ui_test_utils::NavigateToURL(browser(), url);
+  ui_test_utils::NavigateToURLWithDisposition(
+      browser(), url, NEW_BACKGROUND_TAB,
+      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+
+  EXPECT_EQ(2, browser()->tab_strip_model()->count());
+
+  WebContents* wc1 = browser()->tab_strip_model()->GetWebContentsAt(0);
+  WebContents* wc2 = browser()->tab_strip_model()->GetWebContentsAt(1);
+  EXPECT_EQ(wc1->GetRenderProcessHost(), wc2->GetRenderProcessHost());
+
+  // Create an object that will close the window on a process crash.
+  WindowDestroyer destroyer(wc1, browser()->tab_strip_model());
+
+  // Use NOTIFICATION_BROWSER_CLOSED instead of NOTIFICATION_WINDOW_CLOSED,
+  // since the latter is not implemented on OSX and the test will timeout,
+  // causing it to fail.
+  content::WindowedNotificationObserver observer(
+      chrome::NOTIFICATION_BROWSER_CLOSED,
+      content::NotificationService::AllSources());
+
+  // Kill the renderer process, simulating a crash. This should the ProcessDied
+  // method to be called. Alternatively, RenderProcessHost::OnChannelError can
+  // be called to directly force a call to ProcessDied.
+  base::KillProcess(wc1->GetRenderProcessHost()->GetHandle(), -1, true);
+
+  observer.Wait();
+}
diff --git a/chrome/browser/renderer_host/safe_browsing_resource_throttle.h b/chrome/browser/renderer_host/safe_browsing_resource_throttle.h
index 9d46fcc..3a0a16a 100644
--- a/chrome/browser/renderer_host/safe_browsing_resource_throttle.h
+++ b/chrome/browser/renderer_host/safe_browsing_resource_throttle.h
@@ -9,8 +9,8 @@
 #include <vector>
 
 #include "base/memory/ref_counted.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/safe_browsing/database_manager.h"
 #include "chrome/browser/safe_browsing/ui_manager.h"
 #include "content/public/browser/resource_throttle.h"
diff --git a/chrome/browser/renderer_host/web_cache_manager.cc b/chrome/browser/renderer_host/web_cache_manager.cc
index 812fcca..0136501 100644
--- a/chrome/browser/renderer_host/web_cache_manager.cc
+++ b/chrome/browser/renderer_host/web_cache_manager.cc
@@ -14,7 +14,7 @@
 #include "base/prefs/pref_registry_simple.h"
 #include "base/prefs/pref_service.h"
 #include "base/sys_info.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_notification_types.h"
diff --git a/chrome/browser/renderer_host/web_cache_manager.h b/chrome/browser/renderer_host/web_cache_manager.h
index c190752..d142dcc 100644
--- a/chrome/browser/renderer_host/web_cache_manager.h
+++ b/chrome/browser/renderer_host/web_cache_manager.h
@@ -16,7 +16,7 @@
 #include "base/compiler_specific.h"
 #include "base/gtest_prod_util.h"
 #include "base/memory/weak_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "third_party/WebKit/public/web/WebCache.h"
diff --git a/chrome/browser/renderer_preferences_util.cc b/chrome/browser/renderer_preferences_util.cc
index c948cd3..a0f57f9 100644
--- a/chrome/browser/renderer_preferences_util.cc
+++ b/chrome/browser/renderer_preferences_util.cc
@@ -108,12 +108,13 @@
 #elif defined(USE_DEFAULT_RENDER_THEME)
   prefs->focus_ring_color = SkColorSetRGB(0x4D, 0x90, 0xFE);
 
+#if !defined(OS_WIN)
   // This color is 0x544d90fe modulated with 0xffffff.
   prefs->active_selection_bg_color = SkColorSetRGB(0xCB, 0xE4, 0xFA);
   prefs->active_selection_fg_color = SK_ColorBLACK;
   prefs->inactive_selection_bg_color = SkColorSetRGB(0xEA, 0xEA, 0xEA);
   prefs->inactive_selection_fg_color = SK_ColorBLACK;
-
+#endif
   // WebKit accepts a single parameter to control the interval over which the
   // cursor is shown or hidden, so divide Views's time for the full cycle by two
   // and then convert to seconds.
diff --git a/chrome/browser/resources/2x/downloads_section.png b/chrome/browser/resources/2x/downloads_section.png
index 9e11256..60d7089 100644
--- a/chrome/browser/resources/2x/downloads_section.png
+++ b/chrome/browser/resources/2x/downloads_section.png
Binary files differ
diff --git a/chrome/browser/resources/2x/ssl_roadblock_icon.png b/chrome/browser/resources/2x/ssl_roadblock_icon.png
index 4c3e693..1182d99 100644
--- a/chrome/browser/resources/2x/ssl_roadblock_icon.png
+++ b/chrome/browser/resources/2x/ssl_roadblock_icon.png
Binary files differ
diff --git a/chrome/browser/resources/2x/twisty_closed.png b/chrome/browser/resources/2x/twisty_closed.png
index 0a186b9..f55c41d 100644
--- a/chrome/browser/resources/2x/twisty_closed.png
+++ b/chrome/browser/resources/2x/twisty_closed.png
Binary files differ
diff --git a/chrome/browser/resources/2x/twisty_closed_rtl.png b/chrome/browser/resources/2x/twisty_closed_rtl.png
index 81ec960..3f5548a 100644
--- a/chrome/browser/resources/2x/twisty_closed_rtl.png
+++ b/chrome/browser/resources/2x/twisty_closed_rtl.png
Binary files differ
diff --git a/chrome/browser/resources/2x/twisty_open.png b/chrome/browser/resources/2x/twisty_open.png
index fc4c976..055eb3b 100644
--- a/chrome/browser/resources/2x/twisty_open.png
+++ b/chrome/browser/resources/2x/twisty_open.png
Binary files differ
diff --git a/chrome/browser/resources/about_welcome_android/images/holo_logo_150.png b/chrome/browser/resources/about_welcome_android/images/holo_logo_150.png
index 5fc9c69..5815344 100644
--- a/chrome/browser/resources/about_welcome_android/images/holo_logo_150.png
+++ b/chrome/browser/resources/about_welcome_android/images/holo_logo_150.png
Binary files differ
diff --git a/chrome/browser/resources/about_welcome_android/images/holo_logo_200.png b/chrome/browser/resources/about_welcome_android/images/holo_logo_200.png
index 2a7ff1b..a3e111d9 100644
--- a/chrome/browser/resources/about_welcome_android/images/holo_logo_200.png
+++ b/chrome/browser/resources/about_welcome_android/images/holo_logo_200.png
Binary files differ
diff --git a/chrome/browser/resources/apps_debugger/images/dev-icon-128.png b/chrome/browser/resources/apps_debugger/images/dev-icon-128.png
index 2c1d6c6..3b046e9 100644
--- a/chrome/browser/resources/apps_debugger/images/dev-icon-128.png
+++ b/chrome/browser/resources/apps_debugger/images/dev-icon-128.png
Binary files differ
diff --git a/chrome/browser/resources/apps_debugger/images/dev-icon-16.png b/chrome/browser/resources/apps_debugger/images/dev-icon-16.png
index dc29b7b..865c23c 100644
--- a/chrome/browser/resources/apps_debugger/images/dev-icon-16.png
+++ b/chrome/browser/resources/apps_debugger/images/dev-icon-16.png
Binary files differ
diff --git a/chrome/browser/resources/apps_debugger/images/run.png b/chrome/browser/resources/apps_debugger/images/run.png
index e0f46ba..811bc92 100644
--- a/chrome/browser/resources/apps_debugger/images/run.png
+++ b/chrome/browser/resources/apps_debugger/images/run.png
Binary files differ
diff --git a/chrome/browser/resources/apps_debugger/js/items_list.js b/chrome/browser/resources/apps_debugger/js/items_list.js
index 01ab1fe..74ddfc8 100644
--- a/chrome/browser/resources/apps_debugger/js/items_list.js
+++ b/chrome/browser/resources/apps_debugger/js/items_list.js
@@ -239,7 +239,7 @@
       if (!item.terminated)
         this.setEnabledCheckbox_(item, node);
       else
-        this.setTerminatedReloadLink_(node, item);
+        this.setTerminatedReloadLink_(item, node);
 
       // Set remove button handler.
       this.setRemoveButton_(item, node);
@@ -312,10 +312,12 @@
      */
     setTerminatedReloadLink_: function(item, el) {
       var terminatedReload = el.querySelector('.terminated-reload-link');
-      terminatedReload.hidden = false;
-      chrome.developerPrivate.reload(item.id, function() {
-        ItemsList.loadItemsInfo();
+      terminatedReload.addEventListener('click', function(e) {
+        chrome.developerPrivate.reload(item.id, function() {
+          ItemsList.loadItemsInfo();
+        });
       });
+      terminatedReload.hidden = false;
     },
 
     /**
diff --git a/chrome/browser/resources/apps_debugger/js/main.js b/chrome/browser/resources/apps_debugger/js/main.js
index 7623db6..2590f8b 100644
--- a/chrome/browser/resources/apps_debugger/js/main.js
+++ b/chrome/browser/resources/apps_debugger/js/main.js
@@ -24,3 +24,7 @@
 chrome.management.onUninstalled.addListener(function() {
   ItemList.loadItemsInfo();
 });
+
+chrome.developerPrivate.onItemStateChanged.addListener(function(response) {
+  ItemList.loadItemsInfo();
+});
diff --git a/chrome/browser/resources/bookmark_manager/images/2x/bookmark_manager_recent.png b/chrome/browser/resources/bookmark_manager/images/2x/bookmark_manager_recent.png
index 697163c..d39e505 100644
--- a/chrome/browser/resources/bookmark_manager/images/2x/bookmark_manager_recent.png
+++ b/chrome/browser/resources/bookmark_manager/images/2x/bookmark_manager_recent.png
Binary files differ
diff --git a/chrome/browser/resources/bookmark_manager/images/2x/bookmark_manager_search.png b/chrome/browser/resources/bookmark_manager/images/2x/bookmark_manager_search.png
index c10e4c0..438c678 100644
--- a/chrome/browser/resources/bookmark_manager/images/2x/bookmark_manager_search.png
+++ b/chrome/browser/resources/bookmark_manager/images/2x/bookmark_manager_search.png
Binary files differ
diff --git a/chrome/browser/resources/bookmark_manager/images/2x/bookmark_manager_search_rtl.png b/chrome/browser/resources/bookmark_manager/images/2x/bookmark_manager_search_rtl.png
index ed38fd3..439055b 100644
--- a/chrome/browser/resources/bookmark_manager/images/2x/bookmark_manager_search_rtl.png
+++ b/chrome/browser/resources/bookmark_manager/images/2x/bookmark_manager_search_rtl.png
Binary files differ
diff --git a/chrome/browser/resources/bookmark_manager/images/2x/bookmarks_section_32.png b/chrome/browser/resources/bookmark_manager/images/2x/bookmarks_section_32.png
index 078f9c0..29cef47 100644
--- a/chrome/browser/resources/bookmark_manager/images/2x/bookmarks_section_32.png
+++ b/chrome/browser/resources/bookmark_manager/images/2x/bookmarks_section_32.png
Binary files differ
diff --git a/chrome/browser/resources/bookmark_manager/images/bookmark_manager_recent.png b/chrome/browser/resources/bookmark_manager/images/bookmark_manager_recent.png
index 01e363a..245042a 100644
--- a/chrome/browser/resources/bookmark_manager/images/bookmark_manager_recent.png
+++ b/chrome/browser/resources/bookmark_manager/images/bookmark_manager_recent.png
Binary files differ
diff --git a/chrome/browser/resources/bookmark_manager/images/bookmark_manager_search.png b/chrome/browser/resources/bookmark_manager/images/bookmark_manager_search.png
index bb0475a..46b88a7 100644
--- a/chrome/browser/resources/bookmark_manager/images/bookmark_manager_search.png
+++ b/chrome/browser/resources/bookmark_manager/images/bookmark_manager_search.png
Binary files differ
diff --git a/chrome/browser/resources/bookmark_manager/images/bookmark_manager_search_rtl.png b/chrome/browser/resources/bookmark_manager/images/bookmark_manager_search_rtl.png
index c2ff6ba..2ad7968 100644
--- a/chrome/browser/resources/bookmark_manager/images/bookmark_manager_search_rtl.png
+++ b/chrome/browser/resources/bookmark_manager/images/bookmark_manager_search_rtl.png
Binary files differ
diff --git a/chrome/browser/resources/bookmark_manager/images/bookmarks_section_32.png b/chrome/browser/resources/bookmark_manager/images/bookmarks_section_32.png
index 5b51a9b..555d340 100644
--- a/chrome/browser/resources/bookmark_manager/images/bookmarks_section_32.png
+++ b/chrome/browser/resources/bookmark_manager/images/bookmarks_section_32.png
Binary files differ
diff --git a/chrome/browser/resources/chrome-logo-faded.png b/chrome/browser/resources/chrome-logo-faded.png
index 7f00073..cc35d42 100644
--- a/chrome/browser/resources/chrome-logo-faded.png
+++ b/chrome/browser/resources/chrome-logo-faded.png
Binary files differ
diff --git a/chrome/browser/resources/chromeos/access_chromevox/manifest.json b/chrome/browser/resources/chromeos/access_chromevox/manifest.json
index f1976fe..2ec96d9 100644
--- a/chrome/browser/resources/chromeos/access_chromevox/manifest.json
+++ b/chrome/browser/resources/chromeos/access_chromevox/manifest.json
@@ -21,8 +21,7 @@
       "all_frames": true,
       "js": [
         "chromeVoxChromePageScript.js"
-      ],
-      "run_at": "document_start"
+      ]
     }
   ],
   "web_accessible_resources": [
diff --git a/chrome/browser/resources/chromeos/detected_sd.png b/chrome/browser/resources/chromeos/detected_sd.png
index f7c475f..fe3cf30 100644
--- a/chrome/browser/resources/chromeos/detected_sd.png
+++ b/chrome/browser/resources/chromeos/detected_sd.png
Binary files differ
diff --git a/chrome/browser/resources/chromeos/detected_usb.png b/chrome/browser/resources/chromeos/detected_usb.png
index e84c44f..653613e 100644
--- a/chrome/browser/resources/chromeos/detected_usb.png
+++ b/chrome/browser/resources/chromeos/detected_usb.png
Binary files differ
diff --git a/chrome/browser/resources/chromeos/images/broken_robot.png b/chrome/browser/resources/chromeos/images/broken_robot.png
index e3bdb6e..78439f2 100644
--- a/chrome/browser/resources/chromeos/images/broken_robot.png
+++ b/chrome/browser/resources/chromeos/images/broken_robot.png
Binary files differ
diff --git a/chrome/browser/resources/chromeos/insert.png b/chrome/browser/resources/chromeos/insert.png
index 37e5f26..829a595 100644
--- a/chrome/browser/resources/chromeos/insert.png
+++ b/chrome/browser/resources/chromeos/insert.png
Binary files differ
diff --git a/chrome/browser/resources/chromeos/keyboard_overlay.js b/chrome/browser/resources/chromeos/keyboard_overlay.js
index 3c19cec..d28515f 100644
--- a/chrome/browser/resources/chromeos/keyboard_overlay.js
+++ b/chrome/browser/resources/chromeos/keyboard_overlay.js
@@ -141,51 +141,6 @@
     delete shortcutDataCache['0<>CTRL<>SHIFT'];
   }
 
-  // TODO(mazda): Clean this up and move these out to the data js.
-  var searchModifierAddShortcuts = {
-    '1<>SEARCH': 'keyboardOverlayF1',
-    '2<>SEARCH': 'keyboardOverlayF2',
-    '3<>SEARCH': 'keyboardOverlayF3',
-    '4<>SEARCH': 'keyboardOverlayF4',
-    '5<>SEARCH': 'keyboardOverlayF5',
-    '6<>SEARCH': 'keyboardOverlayF6',
-    '7<>SEARCH': 'keyboardOverlayF7',
-    '8<>SEARCH': 'keyboardOverlayF8',
-    '9<>SEARCH': 'keyboardOverlayF9',
-    '0<>SEARCH': 'keyboardOverlayF10',
-    '-<>SEARCH': 'keyboardOverlayF11',
-    '=<>SEARCH': 'keyboardOverlayF12',
-    'F1<>SEARCH': 'keyboardOverlayF1',
-    'F2<>SEARCH': 'keyboardOverlayF2',
-    'F3<>SEARCH': 'keyboardOverlayF3',
-    'F4<>SEARCH': 'keyboardOverlayF4',
-    'F5<>SEARCH': 'keyboardOverlayF5',
-    'F6<>SEARCH': 'keyboardOverlayF6',
-    'F7<>SEARCH': 'keyboardOverlayF7',
-    'F8<>SEARCH': 'keyboardOverlayF8',
-    'F9<>SEARCH': 'keyboardOverlayF9',
-    'F10<>SEARCH': 'keyboardOverlayF10',
-    'F11<>SEARCH': 'keyboardOverlayF11',
-    'F12<>SEARCH': 'keyboardOverlayF12',
-    'back<>SEARCH': 'keyboardOverlayF1',
-    'forward<>SEARCH': 'keyboardOverlayF2',
-    'reload<>SEARCH': 'keyboardOverlayF3',
-    'full screen<>SEARCH': 'keyboardOverlayF4',
-    'switch window<>SEARCH': 'keyboardOverlayF5',
-    'bright down<>SEARCH': 'keyboardOverlayF6',
-    'bright up<>SEARCH': 'keyboardOverlayF7',
-    'mute<>SEARCH': 'keyboardOverlayF8',
-    'vol. down<>SEARCH': 'keyboardOverlayF9',
-    'vol. up<>SEARCH': 'keyboardOverlayF10',
-    'backspace<>SEARCH': 'keyboardOverlayDelete',
-    'down<>SEARCH': 'keyboardOverlayPageDown',
-    'right<>SEARCH': 'keyboardOverlayEnd',
-    'up<>SEARCH': 'keyboardOverlayPageUp',
-    'left<>SEARCH': 'keyboardOverlayHome',
-    '.<>SEARCH': 'keyboardOverlayInsert'
-  };
-  for (var key in searchModifierAddShortcuts)
-    shortcutDataCache[key] = searchModifierAddShortcuts[key];
   return shortcutDataCache;
 }
 
diff --git a/chrome/browser/resources/chromeos/keyboard_overlay_data.js b/chrome/browser/resources/chromeos/keyboard_overlay_data.js
index 097d891..235420e 100644
--- a/chrome/browser/resources/chromeos/keyboard_overlay_data.js
+++ b/chrome/browser/resources/chromeos/keyboard_overlay_data.js
@@ -15767,31 +15767,44 @@
     '-<>ALT': 'keyboardOverlayMinimizeWindow',
     '-<>CTRL': 'keyboardOverlayZoomOut',
     '-<>CTRL<>SHIFT': 'keyboardOverlayZoomScreenOut',
+    '-<>SEARCH': 'keyboardOverlayF11',
     '.<>CTRL<>SHIFT': 'keyboardOverlayToggleSpeechInput',
+    '.<>SEARCH': 'keyboardOverlayInsert',
     '/<>ALT<>CTRL': 'keyboardOverlayViewKeyboardOverlay',
     '/<>ALT<>CTRL<>SHIFT': 'keyboardOverlayViewKeyboardOverlay',
     '/<>CTRL': 'keyboardOverlayHelp',
     '/<>CTRL<>SHIFT': 'keyboardOverlayHelp',
     '0<>CTRL': 'keyboardOverlayResetZoom',
     '0<>CTRL<>SHIFT': 'keyboardOverlayResetScreenZoom',
+    '0<>SEARCH': 'keyboardOverlayF10',
     '1<>ALT': 'keyboardOverlayActivateLauncherItem1',
     '1<>CTRL': 'keyboardOverlayActivateTab1',
+    '1<>SEARCH': 'keyboardOverlayF1',
     '2<>ALT': 'keyboardOverlayActivateLauncherItem2',
     '2<>CTRL': 'keyboardOverlayActivateTab2',
+    '2<>SEARCH': 'keyboardOverlayF2',
     '3<>ALT': 'keyboardOverlayActivateLauncherItem3',
     '3<>CTRL': 'keyboardOverlayActivateTab3',
+    '3<>SEARCH': 'keyboardOverlayF3',
     '4<>ALT': 'keyboardOverlayActivateLauncherItem4',
     '4<>CTRL': 'keyboardOverlayActivateTab4',
+    '4<>SEARCH': 'keyboardOverlayF4',
     '5<>ALT': 'keyboardOverlayActivateLauncherItem5',
     '5<>CTRL': 'keyboardOverlayActivateTab5',
+    '5<>SEARCH': 'keyboardOverlayF5',
     '6<>ALT': 'keyboardOverlayActivateLauncherItem6',
     '6<>CTRL': 'keyboardOverlayActivateTab6',
+    '6<>SEARCH': 'keyboardOverlayF6',
     '7<>ALT': 'keyboardOverlayActivateLauncherItem7',
     '7<>CTRL': 'keyboardOverlayActivateTab7',
+    '7<>SEARCH': 'keyboardOverlayF7',
     '8<>ALT': 'keyboardOverlayActivateLauncherItem8',
     '8<>CTRL': 'keyboardOverlayActivateTab8',
+    '8<>SEARCH': 'keyboardOverlayF8',
     '9<>ALT': 'keyboardOverlayActivateLastLauncherItem',
     '9<>CTRL': 'keyboardOverlayActivateLastTab',
+    '9<>SEARCH': 'keyboardOverlayF9',
+    '=<>SEARCH': 'keyboardOverlayF12',
     'ALT<>SEARCH': 'keyboardOverlayToggleCapsLock',
     'ALT<>SHIFT': 'keyboardOverlayCycleThroughInputMethods',
     '[<>ALT': 'keyboardOverlayDockWindowLeft',
@@ -15801,15 +15814,19 @@
     'b<>ALT<>SHIFT': 'keyboardOverlayFocusBookmarks',
     'b<>CTRL<>SHIFT': 'keyboardOverlayToggleBookmarkBar',
     'back<>CTRL': 'keyboardOverlayFocusPreviousPane',
+    'back<>SEARCH': 'keyboardOverlayF1',
     'backspace': 'keyboardOverlayGoBack',
     'backspace<>ALT': 'keyboardOverlayDelete',
     'backspace<>CTRL': 'keyboardOverlayDeleteWord',
     'backspace<>CTRL<>SHIFT': 'keyboardOverlayClearBrowsingDataDialog',
+    'backspace<>SEARCH': 'keyboardOverlayDelete',
     'backspace<>SHIFT': 'keyboardOverlayGoForward',
     'bright down<>ALT': 'keyboardOverlayDecreaseKeyBrightness',
     'bright down<>ALT<>CTRL': 'keyboardOverlayMagnifierDecreaseZoom',
+    'bright down<>SEARCH': 'keyboardOverlayF6',
     'bright up<>ALT': 'keyboardOverlayIncreaseKeyBrightness',
     'bright up<>ALT<>CTRL': 'keyboardOverlayMagnifierIncreaseZoom',
+    'bright up<>SEARCH': 'keyboardOverlayF7',
     'c<>CTRL': 'keyboardOverlayCopy',
     'c<>CTRL<>SHIFT': 'keyboardOverlayDomInspector',
     'd<>ALT': 'keyboardOverlayFocusAddressBar',
@@ -15817,6 +15834,7 @@
     'd<>CTRL<>SHIFT': 'keyboardOverlayBookmarkAllTabs',
     'down<>ALT': 'keyboardOverlayPageDown',
     'down<>ALT<>CTRL': 'keyboardOverlayEnd',
+    'down<>SEARCH': 'keyboardOverlayPageDown',
     'e<>ALT': 'keyboardOverlayShowWrenchMenu',
     'e<>CTRL': 'keyboardOverlayFocusAddressBarInSearchMode',
     'enter<>ALT': 'keyboardOverlayOpenAddressInNewTab',
@@ -15826,6 +15844,8 @@
     'f<>ALT': 'keyboardOverlayShowWrenchMenu',
     'f<>CTRL': 'keyboardOverlayFindText',
     'forward<>CTRL': 'keyboardOverlayFocusNextPane',
+    'forward<>SEARCH': 'keyboardOverlayF2',
+    'full screen<>SEARCH': 'keyboardOverlayF4',
     'g<>CTRL': 'keyboardOverlayFindTextAgain',
     'g<>CTRL<>SHIFT': 'keyboardOverlayFindPreviousText',
     'h<>CTRL': 'keyboardOverlayHistory',
@@ -15840,11 +15860,13 @@
     'left<>ALT': 'keyboardOverlayGoBack',
     'left<>CTRL': 'keyboardOverlayPreviousWord',
     'left<>CTRL<>SHIFT': 'keyboardOverlaySelectWordAtATime',
+    'left<>SEARCH': 'keyboardOverlayEnd',
     'm<>ALT<>SHIFT': 'keyboardOverlayOpenFileManager',
     'm<>CTRL': 'keyboardOverlayMinimizeWindow',
     'maximize<>ALT': 'keyboardOverlaySwapPrimaryMonitor',
     'maximize<>CTRL': 'keyboardOverlayMirrorMonitors',
     'maximize<>SHIFT': 'keyboardOverlayFullScreen',
+    'mute<>SEARCH': 'keyboardOverlayF8',
     'n<>ALT<>SHIFT': 'keyboardOverlayShowMessageCenter',
     'n<>CTRL': 'keyboardOverlayNewWindow',
     'n<>CTRL<>SHIFT': 'keyboardOverlayNewIncognitoWindow',
@@ -15856,15 +15878,18 @@
     'r<>CTRL': 'keyboardOverlayReloadCurrentPage',
     'r<>CTRL<>SHIFT': 'keyboardOverlayReloadIgnoringCache',
     'reload<>CTRL<>SHIFT': 'keyboardOverlayRotateScreen',
+    'reload<>SEARCH': 'keyboardOverlayF3',
     'right<>ALT': 'keyboardOverlayGoForward',
     'right<>CTRL': 'keyboardOverlayNextWord',
     'right<>CTRL<>SHIFT': 'keyboardOverlaySelectWordAtATime',
+    'right<>SEARCH': 'keyboardOverlayHome',
     's<>ALT<>SHIFT': 'keyboardOverlayShowStatusMenu',
     's<>CTRL': 'keyboardOverlaySave',
     'space<>CTRL': 'keyboardOverlaySelectPreviousInputMethod',
     'space<>SHIFT': 'keyboardOverlayScrollUpOnePage',
     'switch window<>CTRL': 'keyboardOverlayTakeScreenshot',
     'switch window<>CTRL<>SHIFT': 'keyboardOverlayScreenshotRegion',
+    'switch window<>SEARCH': 'keyboardOverlayF5',
     't<>ALT<>CTRL': 'keyboardOverlayNewTerminal',
     't<>ALT<>SHIFT': 'keyboardOverlayFocusToolbar',
     't<>CTRL': 'keyboardOverlayNewTab',
@@ -15877,8 +15902,11 @@
     'u<>CTRL<>SHIFT': 'keyboardOverlayInputUnicodeCharacters',
     'up<>ALT': 'keyboardOverlayPageUp',
     'up<>ALT<>CTRL': 'keyboardOverlayHome',
+    'up<>SEARCH': 'keyboardOverlayPageUp',
     'v<>CTRL': 'keyboardOverlayPaste',
     'v<>CTRL<>SHIFT': 'keyboardOverlayPasteAsPlainText',
+    'vol. down<>SEARCH': 'keyboardOverlayF9',
+    'vol. up<>SEARCH': 'keyboardOverlayF10',
     'w<>CTRL': 'keyboardOverlayCloseTab',
     'w<>CTRL<>SHIFT': 'keyboardOverlayCloseWindow',
     'x<>CTRL': 'keyboardOverlayCut',
diff --git a/chrome/browser/resources/chromeos/login/display_manager.js b/chrome/browser/resources/chromeos/login/display_manager.js
index 8539a76..eb87f87 100644
--- a/chrome/browser/resources/chromeos/login/display_manager.js
+++ b/chrome/browser/resources/chromeos/login/display_manager.js
@@ -305,6 +305,8 @@
               innerContainer.classList.remove('animation');
               oldStep.classList.add('hidden');
             }
+            // Refresh defaultControl. It could have changed.
+            var defaultControl = newStep.defaultControl;
             if (defaultControl)
               defaultControl.focus();
           });
@@ -323,6 +325,8 @@
                 innerContainer.removeEventListener('webkitTransitionEnd', f);
                 $('progress-dots').classList.remove('down');
                 chrome.send('loginVisible', ['oobe']);
+                // Refresh defaultControl. It could have changed.
+                var defaultControl = newStep.defaultControl;
                 if (defaultControl)
                   defaultControl.focus();
               });
diff --git a/chrome/browser/resources/chromeos/login/images/chrome_retail_login.png b/chrome/browser/resources/chromeos/login/images/chrome_retail_login.png
index 3b4d9f3..9799d38 100644
--- a/chrome/browser/resources/chromeos/login/images/chrome_retail_login.png
+++ b/chrome/browser/resources/chromeos/login/images/chrome_retail_login.png
Binary files differ
diff --git a/chrome/browser/resources/chromeos/login/login.js b/chrome/browser/resources/chromeos/login/login.js
index 7fcb7a6..edfaef2 100644
--- a/chrome/browser/resources/chromeos/login/login.js
+++ b/chrome/browser/resources/chromeos/login/login.js
@@ -41,7 +41,6 @@
     handleSpokenFeedbackClick: function(e) {},
     handleHighContrastClick: function(e) {},
     handleScreenMagnifierClick: function(e) {},
-    enableContinueButton: function(enable) {},
     setUsageStats: function(checked) {},
     setOemEulaUrl: function(oemEulaUrl) {},
     setUpdateProgress: function(progress) {},
diff --git a/chrome/browser/resources/chromeos/login/oobe.css b/chrome/browser/resources/chromeos/login/oobe.css
index cdad406..a898675 100644
--- a/chrome/browser/resources/chromeos/login/oobe.css
+++ b/chrome/browser/resources/chromeos/login/oobe.css
@@ -37,7 +37,8 @@
   color: buttontext !important;
 }
 
-button.custom-appearance:focus {
+/* ':focus' used twice to increase specificity. */
+button.custom-appearance:focus:focus {
   border-color: rgb(77, 144, 254);
 }
 
@@ -48,6 +49,7 @@
 button.button-fancy {
   min-width: 72px !important;
 }
+
 button.button-blue {
   background-image: -webkit-linear-gradient(rgb(93, 154, 255),
                                             rgb(93, 154, 255) 38%,
diff --git a/chrome/browser/resources/chromeos/login/oobe.js b/chrome/browser/resources/chromeos/login/oobe.js
index 9e41fc3..addeec6 100644
--- a/chrome/browser/resources/chromeos/login/oobe.js
+++ b/chrome/browser/resources/chromeos/login/oobe.js
@@ -160,14 +160,6 @@
     },
 
     /**
-     * Enables/disables continue button.
-     * @param {boolean} enable Should the button be enabled?
-     */
-    enableContinueButton: function(enable) {
-      $('continue-button').disabled = !enable;
-    },
-
-    /**
      * Sets usage statistics checkbox.
      * @param {boolean} checked Is the checkbox checked?
      */
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_enable_kiosk.js b/chrome/browser/resources/chromeos/login/oobe_screen_enable_kiosk.js
index 4fcf2df..e9ad0b8 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screen_enable_kiosk.js
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_enable_kiosk.js
@@ -67,7 +67,6 @@
       $('kiosk-ok-button').hidden = true;
       $('kiosk-enable-details').textContent =
           loadTimeData.getString('kioskEnableWarningDetails');
-      chrome.send('kioskEnableVisible');
     },
 
     /**
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_network.js b/chrome/browser/resources/chromeos/login/oobe_screen_network.js
index 37dab68..b6b2798 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screen_network.js
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_network.js
@@ -9,6 +9,7 @@
 login.createScreen('NetworkScreen', 'connect', function() {
   return {
     EXTERNAL_API: [
+      'enableContinueButton',
       'showError'
     ],
 
@@ -37,6 +38,7 @@
 
     onBeforeHide: function() {
       cr.ui.DropDown.hide('networks-list');
+      this.enableContinueButton(false);
     },
 
     /**
@@ -55,8 +57,10 @@
       var buttons = [];
 
       var continueButton = this.ownerDocument.createElement('button');
+      continueButton.disabled = true;
       continueButton.id = 'continue-button';
       continueButton.textContent = loadTimeData.getString('continueButton');
+      continueButton.classList.add('preserve-disabled-state');
       continueButton.addEventListener('click', function(e) {
         chrome.send('networkOnExit');
         e.stopPropagation();
@@ -74,6 +78,14 @@
     },
 
     /**
+     * Enables/disables continue button.
+     * @param {boolean} enable Should the button be enabled?
+     */
+    enableContinueButton: function(enable) {
+      $('continue-button').disabled = !enable;
+    },
+
+    /**
      * Shows the network error message.
      * @param {string} message Message to be shown.
      */
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.js b/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.js
index be76d57..2f53251 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.js
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.js
@@ -168,10 +168,6 @@
     onBeforeShow: function(data) {
       var url = data.signin_url;
       url += '?gaiaUrl=' + encodeURIComponent(data.gaiaUrl);
-      if (data.test_email) {
-        url += '&test_email=' + encodeURIComponent(data.test_email);
-        url += '&test_password=' + encodeURIComponent(data.test_password);
-      }
       this.signInUrl_ = url;
       this.setIsAutoEnrollment(data.is_auto_enrollment);
       this.preventCancellation_ = data.prevent_cancellation;
diff --git a/chrome/browser/resources/chromeos/login/screen_locally_managed_user_creation.css b/chrome/browser/resources/chromeos/login/screen_locally_managed_user_creation.css
index d46a293..2aa3962 100644
--- a/chrome/browser/resources/chromeos/login/screen_locally_managed_user_creation.css
+++ b/chrome/browser/resources/chromeos/login/screen_locally_managed_user_creation.css
@@ -45,29 +45,6 @@
   line-height: 24px;
 }
 
-#managed-user-creation .progress-dots {
-  position: absolute;
-  text-align: center;
-  top: 560px;
-  width: 100%;
-}
-
-#managed-user-creation .dot-on {
-  background-color: gray;
-  border-radius: 50%;
-  display: inline-block;
-  height: 6px;
-  width: 6px;
-}
-
-#managed-user-creation .dot-off {
-  background-color: lightgray;
-  border-radius: 50%;
-  display: inline-block;
-  height: 6px;
-  width: 6px;
-}
-
 #managed-user-creation strong {
   color: #000;
   font-weight: normal;
@@ -107,25 +84,16 @@
   text-align: center;
 }
 
-#managed-user-creation-intro-text-1,
-#managed-user-creation-intro-text-2 {
-  margin-top: 25px;
-}
-
 #managed-user-creation-intro .below-marketing {
   margin: 40px 40px 0;
 }
 
-#managed-user-creation-created-1 .below-marketing,
-#managed-user-creation-created-2 .below-marketing,
-#managed-user-creation-created-3 .below-marketing {
+#managed-user-creation-created-1 .below-marketing {
   margin: 55px 100px 0;
 }
 
-#managed-user-creation-created-1-text-3,
-#managed-user-creation-created-2-text-2,
-#managed-user-creation-created-3-text-2,
-#managed-user-creation-created-3-text-3 {
+#managed-user-creation-created-1-text-2,
+#managed-user-creation-created-1-text-3 {
   margin-top: 20px;
 }
 
@@ -147,13 +115,11 @@
   padding: 4px 6px;
 }
 
-#managed-user-creation-name-error,
-#managed-user-creation-password-error {
+#managed-user-creation-name-error {
   visibility: hidden;
 }
 
-#managed-user-creation-name-error.error,
-#managed-user-creation-password-error.error {
+#managed-user-creation-name-error.error {
   color: rgb(207, 93, 70);
   padding-left: 28px;
   visibility: visible;
@@ -173,10 +139,19 @@
 }
 
 #managed-user-creation-error {
-  padding: 100px 50px;
+  padding: 175px 120px 0;
   text-align: center;
 }
 
+#managed-user-creation-error .error-icon {
+  -webkit-margin-after: 50px;
+}
+
+#managed-user-creation-error  .error-message-paragraph {
+  -webkit-margin-after: 40px;
+  -webkit-margin-before: 30px;
+}
+
 .screen-control-button {
   margin-left: 10px !important;
 }
@@ -225,11 +200,6 @@
   color: #000;
   font-size: small;
 }
-.manager-pod .managed-user-creation-manager-wrong-password {
-  background: url('chrome://theme/IDR_WARNING') left top /24px no-repeat;
-  color: red;
-  padding-left: 28px;
-}
 
 #managed-user-creation-status {
   margin: 4px 10px;
@@ -256,3 +226,185 @@
   color: #fff;
 }
 
+.manager-pod .password-error,
+#managed-user-creation .password-error,
+#managed-user-creation .duplicate-name {
+  border: 1px solid red !important;
+}
+
+#managed-user-creation-image-picker {
+  margin-top: 16px;
+}
+
+#managed-user-creation-image-grid {
+  -webkit-user-drag: none;
+  -webkit-user-select: none;
+  display: inline-block;
+  height: 264px;
+  margin: 0;
+  outline: none;
+  overflow: hidden;
+  padding: 0;
+  width: 400px;
+}
+
+#managed-user-creation-image-grid img {
+  background-color: white;
+  height: 50px;
+  vertical-align: middle;
+  width: 50px;
+}
+
+#managed-user-creation-image-grid > li {
+  border: 1px solid rgba(0, 0, 0, 0.15);
+  border-radius: 4px;
+  display: inline-block;
+  margin: 4px;
+  padding: 3px;
+}
+
+#managed-user-creation-image-grid [selected] {
+  border: 2px solid rgb(0, 102, 204);
+  padding: 2px;
+}
+
+#managed-user-creation-image-preview {
+  float: right;
+  margin: 4px;
+  max-width: 220px;
+  position: relative;
+}
+
+html[dir=rtl] #managed-user-creation-image-preview {
+  float: left;
+}
+
+#managed-user-creation-image-preview-img {
+  -webkit-transition: -webkit-transform 200ms linear;
+  display: block;
+  max-height: 220px;
+  max-width: 220px;
+}
+
+.camera.live #managed-user-creation-image-preview-img {
+  display: none;
+}
+
+.camera.flip-x #managed-user-creation-image-preview-img {
+  -webkit-transform: rotateY(180deg);
+}
+
+.default-image #managed-user-creation-image-preview-img {
+  background: white;
+  border: solid 1px #cacaca;
+  border-radius: 4px;
+  padding: 2px;
+}
+
+.managed-user-creation-image-stream-area {
+  display: none;
+  padding: 0;
+  position: relative;
+}
+
+.camera.live .managed-user-creation-image-stream-area {
+  display: block;
+}
+
+#managed-user-creation-image-stream-crop {
+  -webkit-transition: -webkit-transform 200ms linear;
+  height: 220px;
+  overflow: hidden;
+  position: relative;
+  width: 220px;
+}
+
+.flip-x #managed-user-creation-image-stream-crop {
+  -webkit-transform: rotateY(180deg);
+}
+
+.managed-user-creation-image-stream {
+  border: solid 1px #cacaca;
+  height: 220px;
+  /* Center image for 4:3 aspect ratio. */
+  left: -16.6%;
+  position: absolute;
+  visibility: hidden;
+}
+
+.online .managed-user-creation-image-stream {
+  visibility: visible;
+}
+
+#managed-user-creation-image-preview-caption {
+  color: dimGray;
+  font-size: smaller;
+  margin: 8px 4px;
+}
+
+.camera #managed-user-creation-image-preview-caption {
+  display: none;
+}
+
+#managed-user-creation-flip-photo {
+  -webkit-transition: opacity 75ms linear;
+  background: url('chrome://theme/IDR_MIRROR_FLIP') no-repeat;
+  border: none;
+  bottom: 44px;  /* 8px + image bottom. */
+  display: block;
+  height: 32px;
+  opacity: 0;
+  position: absolute;
+  right: 8px;
+  width: 32px;
+}
+
+html[dir=rtl] #managed-user-creation-flip-photo {
+  left: 8px;
+  right: auto;
+}
+
+/* "Flip photo" button is hidden during flip animation. */
+.camera.online:not(.animation) #managed-user-creation-flip-photo {
+  opacity: 0.75;
+}
+
+#managed-user-creation-discard-photo,
+#managed-user-creation-take-photo {
+  display: none;
+  height: 25px;
+  margin: 4px 1px;
+  padding: 0;
+  width: 220px;
+}
+
+.camera:not(.live) #managed-user-creation-discard-photo {
+  background: url('chrome://theme/IDR_USER_IMAGE_RECYCLE')
+      no-repeat center 0;
+  display: block;
+}
+
+.camera.live.online #managed-user-creation-take-photo {
+  background: url('chrome://theme/IDR_USER_IMAGE_CAPTURE')
+      no-repeat center -1px;
+  display: block;
+}
+
+#managed-user-creation-image-preview .perspective-box {
+  -webkit-perspective: 600px;
+}
+
+.managed-user-creation-image-stream-area .spinner {
+  display: none;
+  height: 44px;
+  left: 50%;
+  margin-left: -22px;
+  margin-top: -22px;
+  position: absolute;
+  top: 50%;
+  width: 44px;
+}
+
+.camera.live:not(.online) .managed-user-creation-image-stream-area .spinner {
+  display: block;
+}
diff --git a/chrome/browser/resources/chromeos/login/screen_locally_managed_user_creation.html b/chrome/browser/resources/chromeos/login/screen_locally_managed_user_creation.html
index 5bc7010..b912d46 100644
--- a/chrome/browser/resources/chromeos/login/screen_locally_managed_user_creation.html
+++ b/chrome/browser/resources/chromeos/login/screen_locally_managed_user_creation.html
@@ -3,7 +3,7 @@
     <div id="managed-user-creation-intro" class="step-no-logo">
       <div id="managed-user-creation-marketing-intro"
           class="marketing">
-        Marketing placeholder.
+        <img src="chrome://theme/IDR_SUPERVISED_ILLUSTRATION_START">
       </div>
       <div class="below-marketing">
         <div i18n-content="createManagedUserIntroText1"></div>
@@ -48,81 +48,61 @@
           <div class="page-title-explanation inline"
               i18n-content="createManagedUserPasswordExplanation"></div>
         </div>
-      <div id="managed-user-creation-password-block">
-          <div>
-            <input id="managed-user-creation-password" type="password"
-                i18n-values="placeholder:createManagedUserPasswordHint" />
-            <span id="managed-user-creation-password-error" class="no-error">
-            </span>
+        <div id="managed-user-creation-password-block">
+            <div>
+              <input id="managed-user-creation-password" type="password"
+                  i18n-values="placeholder:createManagedUserPasswordHint" />
+            </div>
+            <div>
+              <input id="managed-user-creation-password-confirm"
+                  type="password"
+                  i18n-values="
+                      placeholder:createManagedUserPasswordConfirmHint" />
+            </div>
           </div>
-          <div>
-            <input id="managed-user-creation-password-confirm"
-                type="password"
-                i18n-values="placeholder:createManagedUserPasswordConfirmHint" />
+      </div>
+      <div id="managed-user-creation-image-picker" class="logo-padded-text">
+        <grid id="managed-user-creation-image-grid">
+        </grid>
+        <div id="managed-user-creation-image-preview">
+          <img id="managed-user-creation-image-preview-img" alt="">
+          <div class="managed-user-creation-image-stream-area">
+            <div class="perspective-box">
+              <div id="managed-user-creation-image-stream-crop">
+                <video class="managed-user-creation-image-stream" autoplay>
+                </video>
+              </div>
+            </div>
+            <div class="spinner"></div>
           </div>
+          <p id="managed-user-creation-image-preview-caption"></p>
+          <button id="managed-user-creation-flip-photo"
+              class="custom-appearance"
+              i18n-values="title:flipPhoto"></button>
+          <button id="managed-user-creation-discard-photo"
+              i18n-values="title:discardPhoto"></button>
+          <button id="managed-user-creation-take-photo"
+              i18n-values="title:takePhoto"></button>
         </div>
       </div>
     </div>
     <div id="managed-user-creation-created-1" class="step-no-logo" hidden>
       <div class="marketing">
+        <img src="chrome://theme/IDR_SUPERVISED_ILLUSTRATION_DONE">
       </div>
       <div class="below-marketing">
         <div>
           <div id="managed-user-creation-created-1-text-1"
               class="page-title centred"></div>
-          <div i18n-content="createManagedUserCreated1Text2"
+          <div id="managed-user-creation-created-1-text-2"
               class="page-title centred"></div>
           <div id="managed-user-creation-created-1-text-3"
               class="page-title-explanation centred"></div>
         </div>
       </div>
-      <div class="progress-dots">
-        <div class="dot-on"></div>
-        <div class="dot-off"></div>
-        <div class="dot-off"></div>
-      </div>
-    </div>
-    <div id="managed-user-creation-created-2" class="step-no-logo" hidden>
-      <div class="marketing">
-        Marketing placeholder 2.
-      </div>
-      <div class="below-marketing">
-        <div>
-          <div i18n-content="createManagedUserCreated2Text1"
-              class="page-title centred"></div>
-          <div id="managed-user-creation-created-2-text-2"
-              i18n-content="createManagedUserCreated2Text2"
-              class="page-title-explanation centred"></div>
-        </div>
-      </div>
-      <div class="progress-dots">
-        <div class="dot-off"></div>
-        <div class="dot-on"></div>
-        <div class="dot-off"></div>
-      </div>
-    </div>
-    <div id="managed-user-creation-created-3" class="step-no-logo" hidden>
-      <div class="marketing">
-        Marketing placeholder 3.
-      </div>
-      <div class="below-marketing">
-        <div>
-          <div i18n-content="createManagedUserCreated3Text1"
-              class="page-title centred"></div>
-          <div id="managed-user-creation-created-3-text-2"
-              class="page-title-explanation centred"></div>
-          <div id="managed-user-creation-created-3-text-3"
-              class="page-title-explanation centred"></div>
-        </div>
-      </div>
-      <div class="progress-dots">
-        <div class="dot-off"></div>
-        <div class="dot-off"></div>
-        <div class="dot-on"></div>
-      </div>
     </div>
     <div id="managed-user-creation-error" hidden>
-      <img alt class="error-icon" src="chrome://theme/IDR_FATAL_ERROR">
+      <img alt class="error-icon" src="chrome://theme/IDR_TECHNICAL_ERROR">
       <div id="managed-user-creation-error-title" class="error-title"></div>
       <div id="managed-user-creation-error-text"
           class="error-message-paragraph"></div>
@@ -151,9 +131,6 @@
     <div class="password-block" hidden>
       <input class="managed-user-creation-manager-password" type="password"
           i18n-values="placeholder:createManagedUserManagerPasswordHint" />
-      <span class="managed-user-creation-manager-wrong-password"
-          i18n-content="createManagedUserWrongManagerPasswordText"
-          hidden />
     </div>
   </div>
 </div>
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/login/screen_locally_managed_user_creation.js b/chrome/browser/resources/chromeos/login/screen_locally_managed_user_creation.js
index 56e2880..6cec377 100644
--- a/chrome/browser/resources/chromeos/login/screen_locally_managed_user_creation.js
+++ b/chrome/browser/resources/chromeos/login/screen_locally_managed_user_creation.js
@@ -8,6 +8,8 @@
 
 login.createScreen('LocallyManagedUserCreationScreen',
                    'managed-user-creation', function() {
+  var UserImagesGrid = options.UserImagesGrid;
+
   var ManagerPod = cr.ui.define(function() {
     var node = $('managed-user-creation-manager-template').cloneNode(true);
     node.removeAttribute('id');
@@ -34,7 +36,8 @@
       var screen = $('managed-user-creation');
       var managerPod = this;
       var hideManagerPasswordError = function(element) {
-        managerPod.passwordErrorElement.hidden = true;
+        managerPod.passwordElement.classList.remove('password-error');
+        $('bubble').hide();
       };
 
       screen.configureTextInput(
@@ -59,7 +62,12 @@
     },
 
     showPasswordError: function() {
-      this.passwordErrorElement.hidden = false;
+      this.passwordElement.classList.add('password-error');
+      $('bubble').showTextForElement(
+          this.passwordElement,
+          loadTimeData.getString('createManagedUserWrongManagerPasswordText'),
+          cr.ui.Bubble.Attachment.BOTTOM,
+          24, 4);
     },
 
     /**
@@ -102,15 +110,6 @@
     },
 
     /**
-     * Gets password error element.
-     * @type {!HTMLDivElement}
-     */
-    get passwordErrorElement() {
-      return this.
-          querySelector('.managed-user-creation-manager-wrong-password');
-    },
-
-    /**
      * Gets password enclosing block.
      * @type {!HTMLDivElement}
      */
@@ -210,6 +209,8 @@
       'showStatusError',
       'showTutorialPage',
       'showUsernamePage',
+      'setDefaultImages',
+      'setCameraPresent',
     ],
 
     lastVerifiedName_: null,
@@ -234,7 +235,8 @@
       var creationScreen = this;
 
       var hideUserPasswordError = function(element) {
-        creationScreen.passwordErrorVisible = false;
+        $('bubble').hide();
+        $('managed-user-creation-password').classList.remove('password-error');
       };
 
       this.configureTextInput(userNameField,
@@ -244,7 +246,6 @@
                                 passwordField.focus();
                               },
                               this.clearUserNameError_.bind(this));
-
       this.configureTextInput(passwordField,
                               this.updateNextButtonForUser_.bind(this),
                               this.validIfNotEmpty_.bind(this),
@@ -264,6 +265,53 @@
         creationScreen.handleErrorButtonPressed_();
         e.stopPropagation();
       });
+
+      /*
+      TODO(antrim) : this is an explicit code duplications with UserImageScreen.
+      It should be removed by issue 251179.
+      */
+      var imageGrid = this.getScreenElement('image-grid');
+      UserImagesGrid.decorate(imageGrid);
+
+      // Preview image will track the selected item's URL.
+      var previewElement = this.getScreenElement('image-preview');
+      previewElement.oncontextmenu = function(e) { e.preventDefault(); };
+
+      imageGrid.previewElement = previewElement;
+      imageGrid.selectionType = 'default';
+
+      imageGrid.addEventListener('select',
+                                 this.handleSelect_.bind(this));
+      imageGrid.addEventListener('phototaken',
+                                 this.handlePhotoTaken_.bind(this));
+      imageGrid.addEventListener('photoupdated',
+                                 this.handlePhotoUpdated_.bind(this));
+
+      // Set the title for camera item in the grid.
+      imageGrid.setCameraTitles(
+          loadTimeData.getString('takePhoto'),
+          loadTimeData.getString('photoFromCamera'));
+
+      this.getScreenElement('take-photo').addEventListener(
+          'click', this.handleTakePhoto_.bind(this));
+      this.getScreenElement('discard-photo').addEventListener(
+          'click', this.handleDiscardPhoto_.bind(this));
+
+      // Toggle 'animation' class for the duration of WebKit transition.
+      this.getScreenElement('flip-photo').addEventListener(
+          'click', function(e) {
+            previewElement.classList.add('animation');
+            imageGrid.flipPhoto = !imageGrid.flipPhoto;
+          });
+      this.getScreenElement('image-stream-crop').addEventListener(
+          'webkitTransitionEnd', function(e) {
+            previewElement.classList.remove('animation');
+          });
+      this.getScreenElement('image-preview-img').addEventListener(
+          'webkitTransitionEnd', function(e) {
+            previewElement.classList.remove('animation');
+          });
+      chrome.send('supervisedUserGetImages');
     },
 
     buttonIds: [],
@@ -422,7 +470,7 @@
           'gotit',
           'managedUserCreationFlow',
           this.gotItButtonPressed_.bind(this),
-          ['created-1', 'created-2', 'created-3'],
+          ['created-1'],
           ['custom-appearance', 'button-fancy', 'button-blue']));
       return buttons;
     },
@@ -517,8 +565,11 @@
       var userNameField = $('managed-user-creation-name');
       if (userNameField.value == this.lastIncorrectUserName_) {
         this.nameErrorVisible = true;
-        $('managed-user-creation-name-error').textContent = errorText;
-
+        $('bubble').showTextForElement(
+            $('managed-user-creation-name'),
+            errorText,
+            cr.ui.Bubble.Attachment.RIGHT,
+            24, 4);
         this.setButtonDisabledStatus('next', true);
       }
     },
@@ -541,10 +592,14 @@
      * @param {string} errorText - reason why this password is invalid.
      */
     showPasswordError: function(errorText) {
-      $('managed-user-creation-password-error').textContent = errorText;
-      this.passwordErrorVisible = true;
+      $('bubble').showTextForElement(
+          $('managed-user-creation-password'),
+          errorText,
+          cr.ui.Bubble.Attachment.RIGHT,
+          24, 4);
+      $('managed-user-creation-password').classList.add('password-error');
       $('managed-user-creation-password').focus();
-
+      this.disabled = false;
       this.setButtonDisabledStatus('next', true);
     },
 
@@ -553,23 +608,10 @@
      * @type {boolean}
      */
     set nameErrorVisible(value) {
-      $('managed-user-creation-name-error').
-          classList.toggle('error', value);
       $('managed-user-creation-name').
           classList.toggle('duplicate-name', value);
       if (!value)
-        $('managed-user-creation-name-error').textContent = '';
-    },
-
-    /**
-     * True if user name error should be displayed.
-     * @type {boolean}
-     */
-    set passwordErrorVisible(value) {
-      $('managed-user-creation-password-error').
-          classList.toggle('error', value);
-      if (!value)
-        $('managed-user-creation-password-error').textContent = '';
+        $('bubble').hide();
     },
 
     /**
@@ -626,14 +668,10 @@
                        'manager',
                        'username',
                        'error',
-                       'created-1',
-                       'created-2',
-                       'created-3'];
+                       'created-1'];
       var pageButtons = {'intro' : 'start',
                          'error' : 'error',
-                         'created-1' : 'gotit',
-                         'created-2' : 'gotit',
-                         'created-3' : 'gotit'};
+                         'created-1' : 'gotit'};
       this.hideStatus_();
       for (i in pageNames) {
         var pageName = pageNames[i];
@@ -658,6 +696,17 @@
         this.getScreenButton(pageButtons[visiblePage]).focus();
 
       this.currentPage_ = visiblePage;
+
+      if (visiblePage == 'username') {
+        var imageGrid = this.getScreenElement('image-grid');
+        // select some image.
+        var selected = this.imagesData_[
+            Math.floor(Math.random() * this.imagesData_.length)];
+        imageGrid.selectedItemUrl = selected.url;
+        chrome.send('supervisedUserSelectImage',
+                    [selected.url, 'default']);
+        this.getScreenElement('image-grid').redraw();
+      }
     },
 
     setButtonDisabledStatus: function(buttonName, status) {
@@ -666,14 +715,6 @@
     },
 
     gotItButtonPressed_: function() {
-      if (this.currentPage_ == 'created-1') {
-        this.setVisiblePage_('created-2');
-        return;
-      }
-      if (this.currentPage_ == 'created-2') {
-        this.setVisiblePage_('created-3');
-        return;
-      }
       chrome.send('finishLocalManagedUserCreation');
     },
 
@@ -731,6 +772,8 @@
       if (data['managers']) {
         this.loadManagers(data['managers']);
       }
+      var imageGrid = this.getScreenElement('image-grid');
+      imageGrid.updateAndFocus();
     },
 
     /**
@@ -738,6 +781,7 @@
      */
     onBeforeHide: function() {
       $('login-header-bar').signinUIState = SIGNIN_UI_STATE.HIDDEN;
+      this.getScreenElement('image-grid').stopCamera();
     },
 
     /**
@@ -784,7 +828,7 @@
      */
     cancel: function() {
       var notSignedInPages = ['intro', 'manager'];
-      var postCreationPages = ['created-1', 'created-2', 'created-3'];
+      var postCreationPages = ['created-1'];
       if (notSignedInPages.indexOf(this.currentPage_) >= 0) {
         // Make sure no manager password is kept:
         this.managerList_.clearPods();
@@ -807,24 +851,22 @@
       this.updateElementText_('created-1-text-1',
           'createManagedUserCreated1Text1',
           this.context_.managedName);
+      this.updateElementText_('created-1-text-2',
+          'createManagedUserCreated1Text2',
+          loadTimeData.getString('managementURL'), this.context_.managedName);
       this.updateElementText_('created-1-text-3',
           'createManagedUserCreated1Text3',
           managerId);
-      this.updateElementText_('created-3-text-2',
-          'createManagedUserCreated3Text2',
-          loadTimeData.getStringF('managementURL'),
-          managerId);
-      this.updateElementText_('created-3-text-3',
-          'createManagedUserCreated3Text3',
-          managerId);
       this.updateElementText_('name-explanation',
           'createManagedUserNameExplanation',
           managerId);
     },
 
-    updateElementText_: function(localId, templateName, value) {
+    updateElementText_: function(localId, templateName) {
+      var args = Array.prototype.slice.call(arguments);
+      args.shift();
       this.getScreenElement(localId).innerHTML =
-          loadTimeData.getStringF(templateName, value);
+          loadTimeData.getStringF.apply(loadTimeData, args);
     },
 
     showIntroPage: function() {
@@ -835,6 +877,7 @@
       this.lastVerifiedName_ = null;
       this.lastIncorrectUserName_ = null;
       this.passwordErrorVisible = false;
+      $('managed-user-creation-password').classList.remove('password-error');
       this.nameErrorVisible = false;
 
       this.setVisiblePage_('intro');
@@ -863,7 +906,89 @@
     showManagerPasswordError: function() {
       this.disabled = false;
       this.showSelectedManagerPasswordError_();
-    }
+    },
+
+    /*
+    TODO(antrim) : this is an explicit code duplications with UserImageScreen.
+    It should be removed by issue 251179.
+    */
+    /**
+     * Currently selected user image index (take photo button is with zero
+     * index).
+     * @type {number}
+     */
+    selectedUserImage_: -1,
+    imagesData: [],
+
+    setDefaultImages: function(imagesData) {
+      var imageGrid = this.getScreenElement('image-grid');
+      for (var i = 0, data; data = imagesData[i]; i++) {
+        var item = imageGrid.addItem(data.url, data.title);
+        item.type = 'default';
+        item.author = data.author || '';
+        item.website = data.website || '';
+      }
+      this.imagesData_ = imagesData;
+    },
+
+    /**
+     * Handles selection change.
+     * @param {cr.Event} e Selection change event.
+     * @private
+     */
+    handleSelect_: function(e) {
+      var imageGrid = this.getScreenElement('image-grid');
+      if (!(imageGrid.selectionType == 'camera' && imageGrid.cameraLive)) {
+        chrome.send('supervisedUserSelectImage',
+                    [imageGrid.selectedItemUrl, imageGrid.selectionType]);
+      }
+      // Start/stop camera on (de)selection.
+      if (!imageGrid.inProgramSelection &&
+          imageGrid.selectionType != e.oldSelectionType) {
+        if (imageGrid.selectionType == 'camera') {
+          // Programmatic selection of camera item is done in
+          // startCamera callback where streaming is started by itself.
+          imageGrid.startCamera(
+              function() {
+                // Start capture if camera is still the selected item.
+                return imageGrid.selectedItem == imageGrid.cameraImage;
+              });
+        } else {
+          imageGrid.stopCamera();
+        }
+      }
+    },
+
+    /**
+     * Handle photo capture from the live camera stream.
+     */
+    handleTakePhoto_: function(e) {
+      this.getScreenElement('image-grid').takePhoto();
+    },
+
+    handlePhotoTaken_: function(e) {
+      chrome.send('supervisedUserPhotoTaken', [e.dataURL]);
+    },
+
+    /**
+     * Handle photo updated event.
+     * @param {cr.Event} e Event with 'dataURL' property containing a data URL.
+     */
+    handlePhotoUpdated_: function(e) {
+      chrome.send('supervisedUserPhotoTaken', [e.dataURL]);
+    },
+
+    /**
+     * Handle discarding the captured photo.
+     */
+    handleDiscardPhoto_: function(e) {
+      var imageGrid = this.getScreenElement('image-grid');
+      imageGrid.discardPhoto();
+    },
+
+    setCameraPresent: function(present) {
+      this.getScreenElement('image-grid').cameraPresent = present;
+    },
   };
 });
 
diff --git a/chrome/browser/resources/chromeos/login/user_pod_row.css b/chrome/browser/resources/chromeos/login/user_pod_row.css
index 238418d..33d7135 100644
--- a/chrome/browser/resources/chromeos/login/user_pod_row.css
+++ b/chrome/browser/resources/chromeos/login/user_pod_row.css
@@ -14,6 +14,8 @@
   display: -webkit-box;
   max-height: 650px;
   overflow: visible;
+  position: relative;
+  z-index: 0;
 }
 
 podrow[ncolumns='4'] {
@@ -46,8 +48,10 @@
   display: inline-block;
   margin: 0 20px;
   padding: 10px 10px 3px;
+  position: relative;
   vertical-align: middle;
   width: 160px;
+  z-index: 0;
 }
 
 .pod .main-pane {
@@ -65,6 +69,7 @@
   /* Focused pod has the same size no matter how many pods. */
   -webkit-transform: scale(1.0) !important;
   cursor: default;
+  z-index: 1;
 }
 
 .pod .user-image {
@@ -154,11 +159,10 @@
 }
 
 .pod .capslock-hint {
+  bottom: 13px;
   cursor: text;
-  padding: 4px 8px;
   position: absolute;
-  right: 10px;
-  top: 180px;
+  right: 6px;
   visibility: hidden;
   z-index: 1;
 }
@@ -319,13 +323,6 @@
   width: 100%;
 }
 
-html[oobe=old] .pod.focused .action-box-area {
-  /* Track shifting of .user-image on pod focus. */
-  -webkit-transform: translateY(-1px);
-  -webkit-transition: -webkit-transform 140ms ease;
-  opacity: 1;
-}
-
 .signed-in-indicator {
   -webkit-transition: all 140ms ease;
   background: rgba(0, 0, 0, 0.5);
diff --git a/chrome/browser/resources/chromeos/login/user_pod_row.js b/chrome/browser/resources/chromeos/login/user_pod_row.js
index 29a8ab5..5d62216 100644
--- a/chrome/browser/resources/chromeos/login/user_pod_row.js
+++ b/chrome/browser/resources/chromeos/login/user_pod_row.js
@@ -407,7 +407,7 @@
         return;
 
       if (active) {
-        this.actionBoxMenuRemoveElement.hidden = false;
+        this.actionBoxMenuRemoveElement.hidden = !this.user_.canRemove;
         this.actionBoxRemoveManagedUserWarningElement.hidden = true;
 
         // Clear focus first if another pod is focused.
diff --git a/chrome/browser/resources/chromeos/salsa.css b/chrome/browser/resources/chromeos/salsa.css
new file mode 100644
index 0000000..f2c3485
--- /dev/null
+++ b/chrome/browser/resources/chromeos/salsa.css
@@ -0,0 +1,60 @@
+/* Copyright 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+#entry-list {
+  list-style-type: none;
+  width: 900px;
+}
+
+.entry {
+  width: 100%;
+}
+
+.entry-key {
+  font-size: small;
+}
+
+.entry-value {
+  font-size: small;
+}
+
+.bold {
+  font-weight: bold;
+}
+
+#treatment-header {
+  display: table-cell;
+  padding-right: 20px;
+  vertical-align: middle;
+}
+
+.treatment {
+  display: table-cell;
+  height: 40px;
+  text-align: center;
+  vertical-align: middle;
+  width: 40px;
+}
+
+.selected {
+  border: 2px solid black;
+  border-radius: 20px;
+}
+
+#bounding-box {
+  border: 1px solid black;
+  border-radius: 10px;
+  margin: 50px;
+  padding: 15px;
+  text-align: center;
+  width: 600px;
+}
+
+#instructions {
+  text-align: left;
+}
+
+#treatment-list {
+  display: inline-block;
+}
diff --git a/chrome/browser/resources/chromeos/salsa.html b/chrome/browser/resources/chromeos/salsa.html
new file mode 100644
index 0000000..22cbfb1
--- /dev/null
+++ b/chrome/browser/resources/chromeos/salsa.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Salsa</title>
+  <link rel="stylesheet" href="salsa.css">
+  <script src="salsa.js"></script>
+</head>
+
+<body>
+<div id="bounding-box">
+  <h1 class="title">Salsa</h1>
+
+  <div id="invalid_treatment_info" hidden>
+    I'm afraid there has been some problem determining which treatments to use
+    for your experiment.  Please try to copy/paste the URL again and refresh
+    this page.  If the problem persists please contact the person running the
+    experiment.
+  </div>
+
+  <div id="valid_treatment_info">
+    <div id="treatment-list">
+      <div id="treatment-header">Available Treatments:</div>
+      <div id="treatment-template" class="treatment" hidden></div>
+    </div>
+  
+    <p class='bold'>Instructions</p>
+  
+    <ul id="instructions">
+      <li> <span class='bold'>Click</span> or use your <span class='bold'>arrow
+      keys</span> to change the selected treatment.
+  
+      <li> Treatments are ordered randomly, so there is no special significance
+      to their labels.
+  
+      <li> When you navigate away from this page your settings will be returned
+      to normal.  If the browser crashes, and/or you experience unusual behavior
+      after this experiment, you can manually reset your settings to their
+      default values at <a href="chrome://gesture">http://gesture</a>.
+    </ul>
+  
+    <p class='bold'>Thank you for your participation!</p>
+  </div>
+</div>
+
+</body>
+</html>
diff --git a/chrome/browser/resources/chromeos/salsa.js b/chrome/browser/resources/chromeos/salsa.js
new file mode 100644
index 0000000..4525b1c
--- /dev/null
+++ b/chrome/browser/resources/chromeos/salsa.js
@@ -0,0 +1,147 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Redefine '$' here rather than including 'cr.js', since this is
+// the only function needed.  This allows this file to be loaded
+// in a browser directly for layout and some testing purposes.
+var $ = function(id) { return document.getElementById(id); };
+
+var currentTreatment = 0;
+var treatments = [];
+
+/**
+ * Take a string of hex like '74657374' and return the ascii version 'test'.
+ * @param {string} str The string of hex characters to convert to ascii
+ * @return {string} The ASCII values of those hex encoded characters
+ */
+function hexToChars(str) {
+  var decoded = '';
+  if (str.length % 2 == 0) {
+    for (var pos = str.length; pos > 0; pos = pos - 2) {
+      var c = String.fromCharCode(parseInt(str.substring(pos - 2, pos), 16));
+      decoded = c + decoded;
+    }
+  }
+  return decoded;
+}
+
+/**
+ * Extract the experiment information out of the encoded URL string.
+ * The format is as follows:
+ * chrome://salsa/#HEX_ENCODED_EXPERIMENT
+ * Experiments are encoded as:
+ *    treatment1+treatment2+...+treatmentn
+ * Each treatment is of the form:
+ *    preference1,preference2,...,preferencen
+ * Each preference is of the form:
+ *    name:value
+ * This function returns an object storing all the parsed data.
+ * @param {string} url The URL to parse the experiment from
+ * @return {list} a list of objects, each representing a single treatment
+ *     and consisting of a set of preference name -> value pairs
+ */
+function parseURL(url) {
+  var match = url.match('#([0-9ABCDEFabcdef]*)');
+  var experimentString = match ? match[1] : '';
+  experimentString = hexToChars(experimentString);
+
+  var treatmentsFound = [];
+  if (experimentString == '')
+    return treatmentsFound;
+
+  var treatmentStrings = experimentString.split('+');
+  for (var i = 0; i < treatmentStrings.length; i++) {
+    var prefStrings = treatmentStrings[i].split(',');
+    treatment = [];
+    for (var j = 0; j < prefStrings.length; j++) {
+      var key = prefStrings[j].split(':')[0];
+      var value = prefStrings[j].split(':')[1];
+      treatment.push({'key': key, 'value': value});
+    }
+    treatmentsFound.push(treatment);
+  }
+
+  return treatmentsFound;
+}
+
+function setPreferenceValue(key, value) {
+  chrome.send('salsaSetPreferenceValue', [key, parseFloat(value)]);
+}
+
+function backupPreferenceValue(key) {
+  chrome.send('salsaBackupPreferenceValue', [key]);
+}
+
+function handleKeyPress(e) {
+  e = e || window.event;
+  var selectedTreatment = currentTreatment;
+
+  if (e.keyCode == '37' || e.keyCode == '38') {
+    selectedTreatment = currentTreatment - 1;
+    if (selectedTreatment < 0)
+      selectedTreatment = 0;
+  } else if (e.keyCode == '39' || e.keyCode == '40') {
+    selectedTreatment = currentTreatment + 1;
+    if (selectedTreatment >= treatments.length)
+      selectedTreatment = treatments.length - 1;
+  }
+
+  if (selectedTreatment != currentTreatment)
+    applyTreatment(selectedTreatment);
+}
+
+function applyTreatment(treatment_number) {
+  if (treatment_number < 0)
+    treatment_number = 0;
+  if (treatment_number >= treatments.length)
+    treatment_number = treatments.length;
+
+  $('treatment' + currentTreatment).className = 'treatment';
+  currentTreatment = treatment_number;
+  $('treatment' + currentTreatment).className = 'selected treatment';
+
+  for (var i = 0; i < treatments[treatment_number].length; i++) {
+    var key = treatments[treatment_number][i].key;
+    var value = treatments[treatment_number][i].value;
+    setPreferenceValue(key, value);
+  }
+}
+
+function initialize() {
+  // Parse the experiment string in the URL.
+  treatments = parseURL(document.URL);
+
+  // Update the available treatments list.
+  for (var i = 0; i < treatments.length; i++) {
+    var newTreatment = $('treatment-template').cloneNode(true);
+    newTreatment.id = 'treatment' + i.toString();
+    newTreatment.removeAttribute('hidden');
+    newTreatment.onclick = function() {
+      applyTreatment(parseInt(this.textContent));
+    };
+    newTreatment.textContent = i.toString();
+    $('treatment-list').appendChild(newTreatment);
+  }
+
+  if (treatments.length > 0) {
+    // Store a copy of the settings right now so you can reset them afterwards.
+    for (var i = 0; i < treatments[0].length; i++)
+      backupPreferenceValue(treatments[0][i].key);
+
+    // Select Treatment 0 to start
+    applyTreatment(0);
+  } else {
+    // Make the error message visible and hide everything else
+    $('invalid_treatment_info').removeAttribute('hidden');
+    var div = $('valid_treatment_info');
+    div.parentNode.removeChild(div);
+  }
+}
+
+/**
+ * A key handler so the user can use the arrow keys to select their treatments.
+ * This should fire any time they press a key
+ */
+document.onkeydown = handleKeyPress;
+document.addEventListener('DOMContentLoaded', initialize);
diff --git a/chrome/browser/resources/chromeos/speech_synthesis/manifest.json b/chrome/browser/resources/chromeos/speech_synthesis/manifest.json
index 6222c68..a756710 100644
--- a/chrome/browser/resources/chromeos/speech_synthesis/manifest.json
+++ b/chrome/browser/resources/chromeos/speech_synthesis/manifest.json
@@ -1,11 +1,16 @@
 {
   "name": "Chrome OS built-in text-to-speech extension",
-  "version": "0.0.1",
+  "version": "0.0.2",
   "description": "Text-to-speech (TTS) voice extension using Native Client technology.",
   "manifest_version": 2,
   "background": {
     "scripts": [
+      "voice_data_hmm_de-DE.js",
+      "voice_data_hmm_en-GB.js",
       "voice_data_hmm_en-US.js",
+      "voice_data_hmm_es-ES.js",
+      "voice_data_hmm_fr-FR.js",
+      "voice_data_hmm_it-IT.js",
       "tts_main.js"
     ]
   },
@@ -17,40 +22,40 @@
   "tts_engine": {
     "voices": [
       {
-        "voice_name": "Chrome OS US English Voice",
-        "lang": "en-US",
-        "gender": "female",
-        "event_types": [ "start", "word", "end", "error" ]
-      },
-      {
-        "voice_name": "Chrome OS UK English Voice",
-        "lang": "en-GB",
-        "gender": "female",
-        "event_types": [ "start", "word", "end", "error" ]
-      },
-      {
-        "voice_name": "Chrome OS French Voice",
+        "voice_name": "Chrome OS French",
         "lang": "fr-FR",
         "gender": "female",
         "event_types": [ "start", "word", "end", "error" ]
       },
       {
-        "voice_name": "Chrome OS Spanish Voice",
-        "lang": "es-ES",
-        "gender": "female",
-        "event_types": [ "start", "word", "end", "error" ]
-      },
-      {
-        "voice_name": "Chrome OS German Voice",
+        "voice_name": "Chrome OS German",
         "lang": "de-DE",
         "gender": "female",
         "event_types": [ "start", "word", "end", "error" ]
       },
       {
-        "voice_name": "Chrome OS Italian Voice",
+        "voice_name": "Chrome OS Italian",
         "lang": "it-IT",
         "gender": "female",
         "event_types": [ "start", "word", "end", "error" ]
+      },
+      {
+        "voice_name": "Chrome OS US English",
+        "lang": "en-US",
+        "gender": "female",
+        "event_types": [ "start", "word", "end", "error" ]
+      },
+      {
+        "voice_name": "Chrome OS British English",
+        "lang": "en-GB",
+        "gender": "female",
+        "event_types": [ "start", "word", "end", "error" ]
+      },
+      {
+        "voice_name": "Chrome OS Spanish",
+        "lang": "es-ES",
+        "gender": "female",
+        "event_types": [ "start", "word", "end", "error" ]
       }
     ]
   }
diff --git a/chrome/browser/resources/chromeos/user_images_grid.js b/chrome/browser/resources/chromeos/user_images_grid.js
index 8e8fc0c..3479d58 100644
--- a/chrome/browser/resources/chromeos/user_images_grid.js
+++ b/chrome/browser/resources/chromeos/user_images_grid.js
@@ -382,8 +382,10 @@
       }
 
       // Set focus to the grid, unless focus is on the OK button.
-      if (!document.activeElement || document.activeElement.tagName != 'BUTTON')
+      if ((!document.activeElement ||
+           document.activeElement.tagName != 'BUTTON') && imageUrl) {
         this.focus();
+      }
     },
 
     /**
diff --git a/chrome/browser/resources/chromeos/wallpaper_manager/images/icon128.png b/chrome/browser/resources/chromeos/wallpaper_manager/images/icon128.png
index 6d973d3..c0abfaf 100644
--- a/chrome/browser/resources/chromeos/wallpaper_manager/images/icon128.png
+++ b/chrome/browser/resources/chromeos/wallpaper_manager/images/icon128.png
Binary files differ
diff --git a/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/2x/add-wallpaper-thumbnail-hover.png b/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/2x/add-wallpaper-thumbnail-hover.png
index c979377..3cbf6aa 100644
--- a/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/2x/add-wallpaper-thumbnail-hover.png
+++ b/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/2x/add-wallpaper-thumbnail-hover.png
Binary files differ
diff --git a/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/2x/add-wallpaper-thumbnail.png b/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/2x/add-wallpaper-thumbnail.png
index 245ab71..710a959 100644
--- a/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/2x/add-wallpaper-thumbnail.png
+++ b/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/2x/add-wallpaper-thumbnail.png
Binary files differ
diff --git a/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/2x/check.png b/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/2x/check.png
index 1612db3..f11047e 100644
--- a/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/2x/check.png
+++ b/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/2x/check.png
Binary files differ
diff --git a/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/2x/close-error-hover.png b/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/2x/close-error-hover.png
index 72d6268..c49f563 100644
--- a/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/2x/close-error-hover.png
+++ b/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/2x/close-error-hover.png
Binary files differ
diff --git a/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/2x/close-error.png b/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/2x/close-error.png
index a65fcfa..efb23e7 100644
--- a/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/2x/close-error.png
+++ b/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/2x/close-error.png
Binary files differ
diff --git a/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/2x/close-white-hover.png b/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/2x/close-white-hover.png
index e3b9421..548fdf4 100644
--- a/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/2x/close-white-hover.png
+++ b/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/2x/close-white-hover.png
Binary files differ
diff --git a/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/2x/close-white.png b/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/2x/close-white.png
index 5c00c56..3e87fa3 100644
--- a/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/2x/close-white.png
+++ b/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/2x/close-white.png
Binary files differ
diff --git a/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/2x/close_bar.png b/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/2x/close_bar.png
index 98ae94c..142adb8 100644
--- a/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/2x/close_bar.png
+++ b/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/2x/close_bar.png
Binary files differ
diff --git a/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/add-wallpaper-thumbnail-hover.png b/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/add-wallpaper-thumbnail-hover.png
index 533decb..7cfb59d 100644
--- a/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/add-wallpaper-thumbnail-hover.png
+++ b/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/add-wallpaper-thumbnail-hover.png
Binary files differ
diff --git a/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/add-wallpaper-thumbnail.png b/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/add-wallpaper-thumbnail.png
index d57a149..0c19c02 100644
--- a/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/add-wallpaper-thumbnail.png
+++ b/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/add-wallpaper-thumbnail.png
Binary files differ
diff --git a/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/check.png b/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/check.png
index 30143d1..d0bb12d 100644
--- a/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/check.png
+++ b/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/check.png
Binary files differ
diff --git a/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/checkbox_checked.png b/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/checkbox_checked.png
index ad8e943..238ce2f 100644
--- a/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/checkbox_checked.png
+++ b/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/checkbox_checked.png
Binary files differ
diff --git a/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/close-error-hover.png b/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/close-error-hover.png
index fe896f9..c3ce1dc 100644
--- a/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/close-error-hover.png
+++ b/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/close-error-hover.png
Binary files differ
diff --git a/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/close-error.png b/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/close-error.png
index 793f60e..02e1f91 100644
--- a/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/close-error.png
+++ b/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/close-error.png
Binary files differ
diff --git a/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/close-white-hover.png b/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/close-white-hover.png
index dd51c6c..e90252b 100644
--- a/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/close-white-hover.png
+++ b/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/close-white-hover.png
Binary files differ
diff --git a/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/close-white.png b/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/close-white.png
index ff9b143..4ac41b2 100644
--- a/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/close-white.png
+++ b/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/close-white.png
Binary files differ
diff --git a/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/close_bar.png b/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/close_bar.png
index 69c9017..e70e5b6 100644
--- a/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/close_bar.png
+++ b/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/close_bar.png
Binary files differ
diff --git a/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/remember.png b/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/remember.png
index e1aeab7..e4381bc 100644
--- a/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/remember.png
+++ b/chrome/browser/resources/chromeos/wallpaper_manager/images/ui/remember.png
Binary files differ
diff --git a/chrome/browser/resources/cloud_print/cell_phone.png b/chrome/browser/resources/cloud_print/cell_phone.png
deleted file mode 100644
index 9925290..0000000
--- a/chrome/browser/resources/cloud_print/cell_phone.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/cloud_print/cloud_print_setup_done.css b/chrome/browser/resources/cloud_print/cloud_print_setup_done.css
deleted file mode 100644
index 5883c75..0000000
--- a/chrome/browser/resources/cloud_print/cloud_print_setup_done.css
+++ /dev/null
@@ -1,47 +0,0 @@
-/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file. */
-
-body {
-  -webkit-user-select: none;
-  background: white;
-  margin: 10px 15px;
-}
-
-.cloudprint-success-header {
-  font-size: 1.4em;
-  font-weight: bold;
-}
-
-.cloudprint-success-image {
-  margin: 20px;
-  text-align: center;
-}
-
-#message {
-  font-weight: bold;
-}
-
-.cloudprint-success-footer {
-  bottom: 0;
-  font-size: 1.2em;
-  margin-bottom: 10px;
-  margin-right: 10px;
-  position: fixed;
-  right: 0;
-}
-
-html[dir='rtl'] .cloudprint-success-footer {
-  bottom: 0;
-  left: 0;
-  margin-left: 20px;
-  text-align: left;
-}
-
-.button {
-<if expr="is_macosx">
-  font-size: 12pt;
-</if>
-  min-height: 26px;
-  min-width: 87px;
-}
diff --git a/chrome/browser/resources/cloud_print/cloud_print_setup_done.html b/chrome/browser/resources/cloud_print/cloud_print_setup_done.html
deleted file mode 100644
index 0bfec33..0000000
--- a/chrome/browser/resources/cloud_print/cloud_print_setup_done.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!DOCTYPE HTML>
-<html i18n-values="dir:textdirection;">
-<head>
-<link rel="stylesheet" type="text/css" href="cloud_print_setup_done.css">
-<script src="chrome://resources/js/cr.js"></script>
-<script src="chrome://resources/js/util.js"></script>
-<script type="text/javascript" src="cloud_print_setup_done.js"></script>
-</head>
-<body i18n-values=".style.fontFamily:fontfamily;.style.fontSize:fontsize">
-  <div class="cloudprint-success-header" i18n-content="success"></div>
-  <div class="cloudprint-success-image">
-    <img src="../../../../ui/webui/resources/images/success.png">
-  </div>
-  <div id="msg-content"></div>
-  <div class="cloudprint-success-footer">
-    <input id="testpage" type="button" class="button" value="Test"
-        i18n-values="value:testpage" onclick="cloudprint.printTestPage()">
-    <input id="close" type="submit" class="button" i18n-values="value:okay"
-        onclick="chrome.send('DialogClose')">
-  </div>
-</body>
-</html>
diff --git a/chrome/browser/resources/cloud_print/cloud_print_setup_done.js b/chrome/browser/resources/cloud_print/cloud_print_setup_done.js
deleted file mode 100644
index aaadabc..0000000
--- a/chrome/browser/resources/cloud_print/cloud_print_setup_done.js
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-cr.define('cloudprint', function() {
-  function printTestPage() {
-    chrome.send('PrintTestPage');
-    chrome.send('DialogClose');
-  }
-
-  function setMessage(msg) {
-    $('msg-content').innerHTML = msg;
-  }
-
-  function onPageShown() {
-    $('close').focus();
-  }
-
-  return {
-    printTestPage: printTestPage,
-    setMessage: setMessage,
-    onPageShown: onPageShown
-  };
-});
diff --git a/chrome/browser/resources/cloud_print/cloud_print_setup_flow.html b/chrome/browser/resources/cloud_print/cloud_print_setup_flow.html
deleted file mode 100644
index be8a657..0000000
--- a/chrome/browser/resources/cloud_print/cloud_print_setup_flow.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!DOCTYPE HTML>
-<html i18n-values="dir:textdirection;">
-<head>
-<title></title>
-<script src="chrome://resources/js/cr.js"></script>
-<script src="chrome://resources/js/util.js"></script>
-<script type="text/javascript" src="cloud_print_setup_flow.js"></script>
-</head>
-<body style="margin:0; border:0;" onload="cloudprint.showInitialPage();">
-  <iframe id="cloudprintsetup"
-          src="chrome://cloudprintsetup/cloudprintsetup"
-          frameborder="0" width="100%" scrolling="no" height="100%"
-          style="display:none" tabindex="-1"></iframe>
-  <iframe id="setupdone"
-          src="chrome://cloudprintsetup/setupdone"
-          frameborder="0" width="100%" scrolling="no" height="100%"
-          style="display:none" tabindex="-1"></iframe>
-</body>
-</html>
diff --git a/chrome/browser/resources/cloud_print/cloud_print_setup_flow.js b/chrome/browser/resources/cloud_print/cloud_print_setup_flow.js
deleted file mode 100644
index 25758f1..0000000
--- a/chrome/browser/resources/cloud_print/cloud_print_setup_flow.js
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-cr.define('cloudprint', function() {
-  function hideAllPages() {
-    var pages = ['cloudprintsetup', 'setupdone'];
-    for (var i = 0; i < pages.length; ++i) {
-      $(pages[i]).style.display = 'none';
-      $(pages[i]).tabIndex = -1;
-    }
-  }
-
-  function showPage(page) {
-    hideAllPages();
-    $(page).style.display = 'block';
-    $(page).tabIndex = 0;
-  }
-
-  function showInitialPage() {
-    var args = JSON.parse(chrome.getVariableValue('dialogArguments'));
-    showPage(args.pageToShow);
-  }
-
-  function showSetupLogin() {
-    showPage('cloudprintsetup');
-  }
-
-  function showSetupDone(width, height) {
-    hideAllPages();
-    var moveByX = (window.innerWidth - width) / 2;
-    var moveByY = (window.innerHeight - height) / 2;
-    var sizeByX = width - window.innerWidth;
-    var sizeByY = height - window.innerHeight;
-    window.moveBy(moveByX, moveByY);
-    window.resizeBy(sizeByX, sizeByY);
-    showPage('setupdone');
-  }
-
-  return {
-    hideAllPages: hideAllPages,
-    showPage: showPage,
-    showInitialPage: showInitialPage,
-    showSetupLogin: showSetupLogin,
-    showSetupDone: showSetupDone
-  };
-});
diff --git a/chrome/browser/resources/cloud_print/cloud_print_setup_login.css b/chrome/browser/resources/cloud_print/cloud_print_setup_login.css
deleted file mode 100644
index 6338db1..0000000
--- a/chrome/browser/resources/cloud_print/cloud_print_setup_login.css
+++ /dev/null
@@ -1,37 +0,0 @@
-/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file. */
-
-body {
-  -webkit-user-select: none;
-  background: white;
-  margin: 10px 15px;
-}
-
-.cloudprint-signup {
-  vertical-align: top;
-  width: 60%;
-}
-
-.cloudprint-login {
-  border: 2px;
-  width: 40%;
-}
-
-.cloudprint-header {
-  font-weight: bold;
-}
-
-.cloudprint-item-header {
-  font-size: 0.9em;
-  font-weight: bold;
-}
-
-.cloudprint-item-explain {
-  font-size: 0.9em;
-}
-
-.cloudprint-item-image {
-  padding: 8px;
-  text-align: center;
-}
diff --git a/chrome/browser/resources/cloud_print/cloud_print_setup_login.html b/chrome/browser/resources/cloud_print/cloud_print_setup_login.html
deleted file mode 100644
index 7bfe5b9..0000000
--- a/chrome/browser/resources/cloud_print/cloud_print_setup_login.html
+++ /dev/null
@@ -1,65 +0,0 @@
-<!DOCTYPE HTML>
-<html i18n-values="dir:textdirection;">
-<head>
-<title></title>
-<link rel="stylesheet" type="text/css" href="cloud_print_setup_login.css">
-<script src="chrome://resources/js/cr.js"></script>
-<script src="chrome://resources/js/util.js"></script>
-<script type="text/javascript" src="cloud_print_setup_login.js"></script>
-</head>
-<body i18n-values=".style.fontFamily:fontfamily;.style.fontSize:fontsize"
-      onload="cloudprint.fixUpTemplateLink();">
-  <table class="cloudprint-contents" id="cloudprint-contents">
-    <tbody>
-      <tr>
-        <td class="cloudprint-signup" id="cloudprint-signup">
-          <table class="cloudprint-intro">
-            <tbody>
-              <tr><td><div class="cloudprint-header" id="header"
-                           i18n-content="header"></div></td></tr>
-              <tr><td><div class="cloudprint-explain" id="explain"
-                           i18n-content="explain"></div></td></tr>
-            </tbody>
-          </table>
-          <table class="cloudprint-body">
-            <tbody>
-              <tr>
-                <td class="cloudprint-item-image">
-                  <img src="cell_phone.png"></td>
-                <td>
-                  <div class="cloudprint-item-header" id="anywhere-header"
-                       i18n-content="anywhereheader"></div>
-                  <div class="cloudprint-item-explain" id="anywhere-explain"
-                       i18n-content="anywhereexplain"></div></td>
-              </tr>
-              <tr>
-                <td class="cloudprint-item-image">
-                  <img src="cloud_printer.png"></td>
-                <td>
-                  <div class="cloudprint-item-header" id="printer-header"
-                       i18n-content="printerheader"></div>
-                  <div class="cloudprint-item-explain" id="printer-explain"
-                       i18n-content="printerexplain"></div></td>
-              </tr>
-              <tr>
-                <td class="cloudprint-item-image">
-                  <img src="sharing.png"></td>
-                <td>
-                  <div class="cloudprint-item-header" id="sharing-header"
-                       i18n-content="sharingheader"></div>
-                  <div class="cloudprint-item-explain" id="sharing-explain"
-                       i18n-content="sharingexplain"></div></td>
-              </tr>
-            </tbody>
-          </table>
-        </td>
-        <td class="cloudprint-login">
-          <iframe id="gaialogin" frameborder="0"
-                  width="100%" scrolling="no" height="100%"
-                  src="chrome://cloudprintsetup/gaialogin"></iframe>
-        </td>
-      </tr>
-    </tbody>
-  </table>
-</body>
-</html>
diff --git a/chrome/browser/resources/cloud_print/cloud_print_setup_login.js b/chrome/browser/resources/cloud_print/cloud_print_setup_login.js
deleted file mode 100644
index 13472f2..0000000
--- a/chrome/browser/resources/cloud_print/cloud_print_setup_login.js
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-cr.define('cloudprint', function() {
-  function learnMore() {
-    chrome.send('LearnMore', ['']);
-    chrome.send('DialogClose', ['']);
-  }
-
-  function fixUpTemplateLink() {
-    var elm = $('anywhere-explain');
-    if (elm)
-      elm.innerHTML = elm.textContent;
-  }
-
-  function showGaiaLogin(args) {
-    frames['gaialogin'].showGaiaLogin(args);
-    new_height = $('cloudprint-signup').offsetHeight;
-    login_height = frames['gaialogin'].document.body.scrollHeight;
-    if (login_height > new_height) {
-      new_height = login_height;
-    }
-    $('cloudprint-contents').style.height = new_height + 4 + 'px';
-  }
-
-  function showGaiaSuccessAndSettingUp() {
-    frames['gaialogin'].showGaiaSuccessAndSettingUp()
-  }
-
-  return {
-    learnMore: learnMore,
-    fixUpTemplateLink: fixUpTemplateLink,
-    showGaiaLogin: showGaiaLogin,
-    showGaiaSuccessAndSettingUp: showGaiaSuccessAndSettingUp
-  };
-});
diff --git a/chrome/browser/resources/cloud_print/cloud_printer.png b/chrome/browser/resources/cloud_print/cloud_printer.png
deleted file mode 100644
index 6f84682..0000000
--- a/chrome/browser/resources/cloud_print/cloud_printer.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/cloud_print/sharing.png b/chrome/browser/resources/cloud_print/sharing.png
deleted file mode 100644
index 6a91ac8..0000000
--- a/chrome/browser/resources/cloud_print/sharing.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/component_extension_resources.grd b/chrome/browser/resources/component_extension_resources.grd
index 067092a..6b254b8 100644
--- a/chrome/browser/resources/component_extension_resources.grd
+++ b/chrome/browser/resources/component_extension_resources.grd
@@ -38,7 +38,6 @@
       <include name="IDR_GAIA_AUTH_SUCCESS" file="gaia_auth/success.html" allowexternalscript="true" type="BINDATA" />
       <include name="IDR_GAIA_AUTH_SUCCESS_JS" file="gaia_auth/success.js" type="BINDATA" />
       <include name="IDR_GAIA_AUTH_UTIL_JS" file="gaia_auth/util.js" type="BINDATA" />
-      <include name="IDR_GAIA_AUTH_TEST_CONTENT_JS" file="gaia_auth/test/content.js" type="BINDATA" />
       <if expr="pp_ifdef('chromeos')">
         <!-- Background page loader  -->
         <include name="IDR_BACKLOADER_BACKGROUND_HTML" file="backloader/background.html" type="BINDATA" />
@@ -87,7 +86,11 @@
         <!-- Images referenced from the manifest or the code -->
         <include name="IDR_FILE_MANAGER_ICON_16" file="file_manager/images/icon16.png" type="BINDATA" />
         <include name="IDR_FILE_MANAGER_ICON_32" file="file_manager/images/icon32.png" type="BINDATA" />
+        <include name="IDR_FILE_MANAGER_ICON_48" file="file_manager/images/icon48.png" type="BINDATA" />
+        <include name="IDR_FILE_MANAGER_ICON_64" file="file_manager/images/icon64.png" type="BINDATA" />
+        <include name="IDR_FILE_MANAGER_ICON_96" file="file_manager/images/icon96.png" type="BINDATA" />
         <include name="IDR_FILE_MANAGER_ICON_128" file="file_manager/images/icon128.png" type="BINDATA" />
+        <include name="IDR_FILE_MANAGER_ICON_256" file="file_manager/images/icon256.png" type="BINDATA" />
 
         <!-- Resources used for non-flattened HTML files. -->
         <include name="IDR_FILE_MANAGER_DRIVE_WELCOME_STYLE" file="file_manager/css/drive_welcome.css" type="BINDATA" />
@@ -111,8 +114,12 @@
         <include name="IDR_FILE_MANAGER_IMG_GALLERY_2X_CURSOR_UPDOWN" file="file_manager/images/gallery/2x/cursor_updown.png" type="BINDATA" />
       </if>
       <if expr="pp_ifdef('image_loader_extension')">
-        <include name="IDR_IMAGE_LOADER_MAIN_JS" file="image_loader/image_loader.js" type="BINDATA" />
-        <include name="IDR_IMAGE_LOADER_CLIENT_JS" file="image_loader/client.js" type="BINDATA" />
+        <include name="IDR_IMAGE_LOADER_IMAGE_LOADER_JS" file="image_loader/image_loader.js" type="BINDATA" />
+        <include name="IDR_IMAGE_LOADER_CACHE_JS" file="image_loader/cache.js" type="BINDATA" />
+        <include name="IDR_IMAGE_LOADER_WORKER_JS" file="image_loader/worker.js" type="BINDATA" />
+        <include name="IDR_IMAGE_LOADER_REQUEST_JS" file="image_loader/request.js" type="BINDATA" />
+        <include name="IDR_IMAGE_LOADER_BACKGROUND_JS" file="image_loader/background.js" type="BINDATA" />
+        <include name="IDR_IMAGE_LOADER_CLIENT_JS" file="image_loader/image_loader_client.js" type="BINDATA" />
       </if>
       <if expr="pp_ifdef('enable_google_now')">
         <include name="IDR_GOOGLE_NOW_BACKGROUND_JS" file="google_now/background.js" type="BINDATA" />
diff --git a/chrome/browser/resources/downloads_section.png b/chrome/browser/resources/downloads_section.png
index 6d82a40..1f59297 100644
--- a/chrome/browser/resources/downloads_section.png
+++ b/chrome/browser/resources/downloads_section.png
Binary files differ
diff --git a/chrome/browser/resources/extensions/extension_list.js b/chrome/browser/resources/extensions/extension_list.js
index ea232a5..f689263 100644
--- a/chrome/browser/resources/extensions/extension_list.js
+++ b/chrome/browser/resources/extensions/extension_list.js
@@ -97,7 +97,10 @@
         node.classList.add('extension-highlight');
 
       var item = node.querySelector('.extension-list-item');
-      item.style.backgroundImage = 'url(' + extension.icon + ')';
+      var extensionIconUrl = extension.icon;
+      if (extension.allow_reload)
+        extensionIconUrl = extension.icon + '?' + Date.now();
+      item.style.backgroundImage = 'url(' + extensionIconUrl + ')';
 
       var title = node.querySelector('.extension-title');
       title.textContent = extension.name;
@@ -239,6 +242,7 @@
       var trash = trashTemplate.cloneNode(true);
       trash.title = loadTimeData.getString('extensionUninstall');
       trash.addEventListener('click', function(e) {
+        butterBarVisibility[extension.id] = false;
         chrome.send('extensionSettingsUninstall', [extension.id]);
       });
       node.querySelector('.enable-controls').appendChild(trash);
diff --git a/chrome/browser/resources/extensions/extensions.js b/chrome/browser/resources/extensions/extensions.js
index 6af2665..e2010cd 100644
--- a/chrome/browser/resources/extensions/extensions.js
+++ b/chrome/browser/resources/extensions/extensions.js
@@ -153,11 +153,6 @@
      */
     handleLoadUnpackedExtension_: function(e) {
       chrome.send('extensionSettingsLoadUnpackedExtension');
-
-      // TODO(jhawkins): Refactor metrics support out of options and use it
-      // in extensions.html.
-      chrome.send('coreOptionsUserMetricsAction',
-                  ['Options_LoadUnpackedExtension']);
     },
 
     /**
@@ -167,7 +162,7 @@
      */
     handlePackExtension_: function(e) {
       ExtensionSettings.showOverlay($('packExtensionOverlay'));
-      chrome.send('coreOptionsUserMetricsAction', ['Options_PackExtension']);
+      chrome.send('metricsHandler:recordAction', ['Options_PackExtension']);
     },
 
     /**
@@ -177,7 +172,7 @@
      */
     showExtensionCommandsConfigUi_: function(e) {
       ExtensionSettings.showOverlay($('extensionCommandsOverlay'));
-      chrome.send('coreOptionsUserMetricsAction',
+      chrome.send('metricsHandler:recordAction',
                   ['Options_ExtensionCommands']);
     },
 
diff --git a/chrome/browser/resources/file_manager/action_choice.html b/chrome/browser/resources/file_manager/action_choice.html
index 91fbd11..4df5eb6 100644
--- a/chrome/browser/resources/file_manager/action_choice.html
+++ b/chrome/browser/resources/file_manager/action_choice.html
@@ -21,7 +21,7 @@
     <!-- Keep the list in sync with action_choice_scripts.js. -->
 
     <!-- Loads the client of the image loader extension -->
-    <script src="chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/client.js"></script>
+    <script src="chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/image_loader_client.js"></script>
 
     <script src="chrome://resources/js/load_time_data.js"></script>
     <script src="chrome://resources/js/util.js"></script>
diff --git a/chrome/browser/resources/file_manager/css/common.css b/chrome/browser/resources/file_manager/css/common.css
index 832b47a..03eea6c 100644
--- a/chrome/browser/resources/file_manager/css/common.css
+++ b/chrome/browser/resources/file_manager/css/common.css
@@ -2,6 +2,11 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file. */
 
+/* Special attribute to hide elements. */
+[hidden] {
+  display: none !important;
+}
+
 /* This file contains "borrowed" copy of standard styles. To simplify merging,
  * when altering, please preserve original property value by adding comments. */
 input.common[type='checkbox'],
@@ -112,12 +117,7 @@
 
 .buttonbar {
   display: -webkit-box;
-  height: 35px;
-}
-
-.buttonbar.right {
-  -webkit-box-flex: 1.0;
-  -webkit-box-pack: end;
+  height: 31px;
 }
 
 .buttonbar button:active img {
@@ -176,7 +176,7 @@
 }
 
 menu.chrome-menu[hidden] {
-  display: block;
+  display: block !important;  /* Overrides default [hidden] for animation. */
   opacity: 0;
   pointer-events: none;
   visibility: hidden;
@@ -246,7 +246,10 @@
   display: none;
 }
 
-/* Ok/Cancel style buttons */
+/**
+ * Ok/Cancel style buttons
+ * Height: 31px (content:21px + border:5px * 2)
+ **/
 button,
 input[type='button'],
 input[type='submit'],
@@ -258,16 +261,15 @@
   border: 5px solid transparent;
   border-image: -webkit-image-set(
     url('../images/common/button.png') 1x,
-    url('../images/common/2x/button.png') 2x) 5 5 repeat;
-  box-shadow: inset 0 1px 1px 0 rgb(255, 255, 255);
+    url('../images/common/2x/button.png') 2x) 5 / 5px / 2px repeat;
   box-sizing: content-box;
   color: rgb(34, 34, 34);
   cursor: default;
-  height: 25px;
-  line-height: 25px;
+  height: 21px;
+  line-height: 21px;
   margin: 0;
-  min-height: 25px;
-  min-width: 60px;
+  min-height: 21px;
+  min-width: 55px;
   padding: 0 10px;
   position: relative;
   text-align: center;
@@ -275,7 +277,7 @@
 }
 
 .buttonbar button {
-  -webkit-margin-start: 8px;
+  -webkit-margin-start: 10px;
 }
 
 button:hover,
@@ -284,8 +286,7 @@
 select:hover {
   border-image: -webkit-image-set(
     url('../images/common/button_hover.png') 1x,
-    url('../images/common/2x/button_hover.png') 2x) 5 5 repeat;
-  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
+    url('../images/common/2x/button_hover.png') 2x) 5 / 5px / 2px repeat;
   color: #222;
 }
 
@@ -294,8 +295,7 @@
 input[type='submit']:active {
   border-image: -webkit-image-set(
     url('../images/common/button_pressed.png') 1x,
-    url('../images/common/2x/button_pressed.png') 2x) 5 5 repeat;
-  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
+    url('../images/common/2x/button_pressed.png') 2x) 5 / 5px / 2px repeat;
   color: #333;
 }
 
@@ -307,12 +307,9 @@
 input[type='submit'][disabled]:hover {
   background-color: rgb(250, 250, 250);
   background-image: none;
-  border: 1px solid rgb(255, 255, 255);
-  border-bottom: 1px solid rgb(180, 180, 180);
-  border-left: 1px solid rgb(220, 220, 220);
-  border-right: 1px solid rgb(200, 200, 200);
-  border-top: 1px solid rgb(220, 220, 220);
-  box-shadow: inset 0 1px 1px 0 rgb(255, 255, 255);
+  border-image: -webkit-image-set(
+    url('../images/common/button.png') 1x,
+    url('../images/common/2x/button.png') 2x) 5 / 5px / 2px repeat;
   color: rgb(150, 150, 150);
 }
 
@@ -441,10 +438,6 @@
   transition: opacity 500ms;
 }
 
-[hidden] {
-  display: none;
-}
-
 .cr-dialog-title {
   -webkit-margin-after: 10px;
   -webkit-margin-end: 20px;
diff --git a/chrome/browser/resources/file_manager/css/drive_welcome.css b/chrome/browser/resources/file_manager/css/drive_welcome.css
index 8f4332c..a3c5ddb 100644
--- a/chrome/browser/resources/file_manager/css/drive_welcome.css
+++ b/chrome/browser/resources/file_manager/css/drive_welcome.css
@@ -125,7 +125,7 @@
   left: 0;
   position: absolute;
   right: 0;
-  top: 28px;  /* Leave room for the file list header. */
+  top: 0;
 }
 
 .dialog-container:not([drive-welcome='page']) .drive-welcome.page {
@@ -139,7 +139,6 @@
 .drive-welcome.page .drive-welcome-wrapper {
   -webkit-box-align: center;
   -webkit-box-orient: vertical;
-  background-position: 0 50px;
   background-size: 520px 173px;
   bottom: 0;
   display: -webkit-box;
diff --git a/chrome/browser/resources/file_manager/css/file_manager.css b/chrome/browser/resources/file_manager/css/file_manager.css
index 1e758ad..184f4f3 100644
--- a/chrome/browser/resources/file_manager/css/file_manager.css
+++ b/chrome/browser/resources/file_manager/css/file_manager.css
@@ -2,6 +2,21 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file. */
 
+/* Special attribute used in HTML to hide elements. */
+body[type='folder'] [invisibleif~='folder'],
+body[type='saveas-file'] [invisibleif~='saveas-file'],
+body[type='open-file'] [invisibleif~='open-file'],
+body[type='open-multi-file'] [invisibleif~='open-multi-file'],
+body[type='full-page'] [invisibleif~='full-page'],
+
+body[type='folder'] [visibleif]:not([visibleif~='folder']),
+body[type='saveas-file'] [visibleif]:not([visibleif~='saveas-file']),
+body[type='open-file'] [visibleif]:not([visibleif~='open-file']),
+body[type='open-multi-file'] [visibleif]:not([visibleif~='open-multi-file']),
+body[type='full-page'] [visibleif]:not([visibleif~='full-page']) {
+  display: none !important;
+}
+
 html {
   height: 100%;
 }
@@ -131,20 +146,6 @@
   white-space: nowrap;
 }
 
-/* The top title of the dialog. */
-.dialog-title {
-  -webkit-padding-start: 15px;
-  background-image: linear-gradient(to bottom, #fff, #f6f6f6);
-  border-bottom: 1px rgb(214, 217, 227) solid;
-  box-sizing: border-box;
-  color: rgb(66, 80, 108);
-  font-size: 15px;
-  font-weight: bold;
-  height: 32px;
-  padding-bottom: 8px;
-  padding-top: 8px;
-}
-
 /* Main part of the dialog between header and footer. */
 .dialog-container {
   -webkit-box-align: stretch;
@@ -223,11 +224,7 @@
 }
 
 #volume-list > * {
-  background-color: rgb(240, 240, 240);
-  background-image: none;
-  border: none;
   height: 40px;
-  margin: 0;
   padding: 0 5px;
 }
 
@@ -250,7 +247,6 @@
 
 #volume-list li.root-item {
   -webkit-box-align: center;
-  border-radius: 0;
   display: -webkit-box;
   line-height: 22px;  /* To accomodate for icons. */
   padding-left: 11px;
@@ -278,7 +274,9 @@
   color: rgb(100, 100, 100);
   height: 47px;
   line-height: 40px;
+  overflow-x: hidden;
   position: absolute;
+  text-overflow: ellipsis;
   width: 100%;
 }
 
@@ -295,14 +293,9 @@
 }
 
 #directory-tree .tree-row {
-  background-color: white;
-  background-image: none;
-  border: none;
-  border-radius: 0;
   cursor: pointer;
   display: -webkit-box;
   line-height: 29px;
-  margin: 0;
   padding: 0 3px;
 }
 
@@ -315,7 +308,6 @@
   height: 37px;
   left: 3px;
   margin: -13px;
-  opacity: 1;
   top: 0;
   vertical-align: middle;
   width: 37px;
@@ -375,8 +367,6 @@
 }
 
 #volume-list .root-item > div.root-eject {
-  /* The transition commented out to work around crbug.com/157813 */
-  /* transition: opacity 70ms linear; */
   background-image: -webkit-image-set(
     url('../images/files/ui/eject.png') 1x,
     url('../images/files/ui/2x/eject.png') 2x);
@@ -386,15 +376,14 @@
   height: 20px;
   margin-right: 6px;
   opacity: 0.7;
+  transition: opacity 70ms linear;
   vertical-align: middle;
   width: 20px;
 }
 
-#directory-tree .tree-row > div.root-eject[hidden] {
-  /* [hidden] has alredy set in dialog.css, but it is overridden by the
-   * selector '.tree-item > .tree-row > * 'in tree.js, hence we need to
-   * override it again. */
-  display: none;
+#volume-list:focus .root-item[selected] > div.root-eject {
+  -webkit-filter: brightness(0) invert();
+  opacity: 1;
 }
 
 #directory-tree .tree-row > div.root-eject:hover {
@@ -438,25 +427,20 @@
 
 .dialog-header #gear-button {
   background-image: -webkit-image-set(
-    url('../images/files/ui/new-ui/topbar_button_settings.png') 1x,
-    url('../images/files/ui/new-ui/2x/topbar_button_settings.png') 2x);
+    url('../images/files/ui/topbar_button_settings.png') 1x,
+    url('../images/files/ui/2x/topbar_button_settings.png') 2x);
 }
 
 .dialog-header #maximize-button {
   background-image: -webkit-image-set(
-    url('../images/files/ui/new-ui/topbar_button_maximize.png') 1x,
-    url('../images/files/ui/new-ui/2x/topbar_button_maximize.png') 2x);
+    url('../images/files/ui/topbar_button_maximize.png') 1x,
+    url('../images/files/ui/2x/topbar_button_maximize.png') 2x);
 }
 
 .dialog-header #close-button {
   background-image: -webkit-image-set(
-    url('../images/files/ui/new-ui/topbar_button_close.png') 1x,
-    url('../images/files/ui/new-ui/2x/topbar_button_close.png') 2x);
-}
-
-body:not([type='full-page']) .dialog-header #close-button,
-body:not([type='full-page']) .dialog-header #maximize-button {
-  display: none;
+    url('../images/files/ui/topbar_button_close.png') 1x,
+    url('../images/files/ui/2x/topbar_button_close.png') 2x);
 }
 
 /* Container for the detail and thumbnail list views. */
@@ -493,18 +477,19 @@
   padding: 10px;
 }
 
-.dialog-footer:not([progress]) .progress-bar,
-.dialog-footer:not([progress]) .preparing-label {
+.progressable:not([progress]) .progress-bar,
+.progressable:not([progress]) .preparing-label {
   display: none;
 }
 
-.dialog-footer[progress] .ok,
-.dialog-footer[progress] #filename-input-box,
-.dialog-footer[progress] #file-type {
+.progressable[progress] .ok,
+.progressable[progress] #filename-input-box,
+.progressable[progress] #preview-lines,
+.progressable[progress] .file-type {
   display: none;
 }
 
-.dialog-footer .progress-bar {
+.progressable .progress-bar {
   -webkit-box-flex: 1;
   -webkit-margin-end: 20px;
   -webkit-margin-start: 20px;
@@ -582,10 +567,6 @@
   white-space: nowrap;
 }
 
-.breadcrumb-path:hover {
-  color: #666;
-}
-
 /* The final breadcrumb, representing the current directory. */
 #search-breadcrumbs .breadcrumb-path.breadcrumb-last {
   color: #141414;
@@ -641,10 +622,11 @@
 
 #search-box,
 #filename-input-box input {
-  border: 1px solid #d9d9d9;
+  border: 1px solid #c8c8c8;
   border-radius: 1px;
-  border-top: 1px solid #c0c0c0;
   box-sizing: border-box;
+  height: 31px;  /* border-box */
+  margin-right: 30px;
 }
 
 #search-box {
@@ -676,10 +658,6 @@
   pointer-events: auto;
 }
 
-#search-box[hidden] {
-  display: none;  /* Required, since overriden by #search-box. */
-}
-
 #search-box::-webkit-search-cancel-button {
   -webkit-appearance: none;
 }
@@ -694,8 +672,8 @@
   -webkit-margin-start: 10px;
   -webkit-order: -1;
   background-image: -webkit-image-set(
-    url('../images/files/ui/new-ui/search_icon_inactive.png') 1x,
-    url('../images/files/ui/new-ui/2x/search_icon_inactive.png') 2x);
+    url('../images/files/ui/search_icon_inactive.png') 1x,
+    url('../images/files/ui/2x/search_icon_inactive.png') 2x);
   background-position: center;
   background-repeat: no-repeat;
   height: 32px;
@@ -707,16 +685,16 @@
 #search-box:focus + #search-icon,
 .has-text #search-icon {
   background: -webkit-image-set(
-    url('../images/files/ui/new-ui/search_icon_active.png') 1x,
-    url('../images/files/ui/new-ui/2x/search_icon_active.png') 2x);
+    url('../images/files/ui/search_icon_active.png') 1x,
+    url('../images/files/ui/2x/search_icon_active.png') 2x);
 }
 
 #search-clear-button {
   -webkit-margin-end: 30px;
   -webkit-margin-start: 10px;
   background-image: -webkit-image-set(
-    url('../images/files/ui/new-ui/search_clear.png') 1x,
-    url('../images/files/ui/new-ui/2x/search_clear.png') 2x);
+    url('../images/files/ui/search_clear.png') 1x,
+    url('../images/files/ui/2x/search_clear.png') 2x);
   background-position: center;
   background-repeat: no-repeat;
   display: none;
@@ -734,14 +712,14 @@
 
 #search-clear-button:hover {
   background-image: -webkit-image-set(
-    url('../images/files/ui/new-ui/search_clear_hover.png') 1x,
-    url('../images/files/ui/new-ui/2x/search_clear_hover.png') 2x);
+    url('../images/files/ui/search_clear_hover.png') 1x,
+    url('../images/files/ui/2x/search_clear_hover.png') 2x);
 }
 
 #search-clear-button:active {
   background-image: -webkit-image-set(
-    url('../images/files/ui/new-ui/search_clear_pressed.png') 1x,
-    url('../images/files/ui/new-ui/2x/search_clear_pressed.png') 2x);
+    url('../images/files/ui/search_clear_pressed.png') 1x,
+    url('../images/files/ui/2x/search_clear_pressed.png') 2x);
 }
 
 .filelist-panel {
@@ -773,9 +751,7 @@
   -webkit-box-sizing: border-box;
   background-color: rgba(255, 255, 255, 0.3);
   border: 2px solid rgba(255, 255, 255, 0.6);
-  border-radius: 0; /* Override the style of cr.ui.List */
   outline: 1px solid rgba(0, 0, 0, 0.1);
-  padding: 0; /* Override the style of cr.ui.List */
   position: absolute;
   z-index: 2;
 }
@@ -834,6 +810,7 @@
 }
 
 .downloads-warning[hidden] {
+  display: -webkit-box !important;  /* Overrides [hidden] for animation. */
   height: 0;
 }
 
@@ -852,7 +829,6 @@
   background-image: url(chrome://resources/images/clouds.png);
   background-repeat: repeat-x;
   background-size: 150px 44px;
-  border-top: 1px solid rgba(0, 0, 0, 0.1);
   color: #333;
   display: -webkit-box;
   font-size: 13px;
@@ -863,9 +839,6 @@
 
 .volume-warning[hidden] {
   border-top-width: 0;
-  /* [hidden] has already set in dialog.css, but it is overridden by the
-   * selector ".volume-warning", hence we need to override it again. */
-  display: none;
   height: 0;
 }
 
@@ -900,31 +873,13 @@
   cursor: pointer;
 }
 
-.breadcrumb-path:not(.breadcrumb-last):hover,
-.breadcrumb-path.accepts {
-  color: rgb(17, 85, 204);
-  text-decoration: underline;
-}
-
-.breadcrumb-path.accepts {
-  -webkit-animation: acceptsBlinkText 200ms linear 1s 3;
-}
-
-@-webkit-keyframes acceptsBlinkText {
-  0% {
-    color: white;
-  }
-  50% {
-  }
-}
-
 .img-container > img {
   -webkit-user-drag: none;
   position: absolute;
 }
 
-.img-container > img:not(.cached) {
-  -webkit-animation: fadeIn 500ms ease-in;
+.img-container > img:not(.cached):not(.drag-thumbnail) {
+  -webkit-animation: fadeIn 250ms linear;
 }
 
 .thumbnail-bottom {
@@ -950,7 +905,6 @@
   -webkit-margin-start: 8px;
   border: 3px solid transparent;  /* Selection will make the border visible. */
   margin-top: 7px;
-  padding: 0;
   position: relative;
 }
 
@@ -1006,19 +960,9 @@
   background-position: 5px center;
   background-repeat: no-repeat;
   background-size: 16px 16px;
-  line-height: 39px;
   padding-left: 26px;
 }
 
-#list-container list > li,
-#list-container grid > *,
-#default-actions-list > * {
-  background-color: transparent;
-  background-image: none;
-  border-color: transparent;
-  border-radius: 0;
-}
-
 #list-container list > li[selected],
 #list-container grid > li[selected],
 #default-actions-list > li[selected] {
@@ -1117,7 +1061,6 @@
 
 /* The cr.ui.Table representing the detailed file list. */
 .detail-table {
-  border: 0;
   width: 100%;
 }
 
@@ -1134,7 +1077,7 @@
   height: 51px;
   left: 0;
   opacity: 1;
-  padding: 0 12px 0 7px;
+  padding: 0 10px 0 7px;
   position: absolute;
   right: 0;
   z-index: 3;
@@ -1152,6 +1095,27 @@
   opacity: 0;
 }
 
+.preview-panel > .left,
+.dialog-footer > .left {
+  -webkit-box-align: center;
+  -webkit-box-flex: 1;
+  -webkit-box-orient: horizontal;
+  display: -webkit-box;
+}
+
+.preview-panel > .right,
+.dialog-footer > .right {
+  -webkit-box-pack: end;
+}
+
+.preview-panel .preparing-label {
+  -webkit-margin-start: 30px;
+}
+
+.preview-panel .progress-bar {
+  -webkit-box-flex: 1;
+}
+
 .preview-thumbnails {
   -webkit-box-orient: horizontal;
   display: -webkit-box;
@@ -1220,21 +1184,13 @@
   opacity: 0;
 }
 
-/* cr.ui.Table has a black focus border by default, which we don't want. */
-.detail-table:focus {
-  border: 0;
-}
-
 /* Table splitter element */
 .table-header-splitter {
-  -webkit-border-start: 1px #d4d4d4 solid;
-  background-color: inherit;
   background-image: -webkit-image-set(
-    url('../images/files/ui/new-ui/vertical_separator.png') 1x,
-    url('../images/files/ui/new-ui/2x/vertical_separator.png') 2x);
+    url('../images/files/ui/vertical_separator.png') 1x,
+    url('../images/files/ui/2x/vertical_separator.png') 2x);
   background-position: center;
   background-repeat: repeat-y;
-  border: none;
   height: 20px;
   top: 10px;
   width: 5px;
@@ -1246,8 +1202,6 @@
 
 /* Container for a table header. */
 .table-header {
-  background-color: transparent;
-  border-bottom: none;
   box-sizing: border-box;
   height: 47px;
 }
@@ -1286,13 +1240,13 @@
 .table-header-label {
   color: rgb(100, 100, 100);
   line-height: 40px;
+  margin: 0 7px;
 }
 
 .table-row-cell > * {
   -webkit-box-align: center;
   -webkit-box-flex: 1;
   -webkit-box-orient: horizontal;
-  margin: 0;
   padding: 0 10px;
 }
 
@@ -1337,8 +1291,8 @@
 #list-container li.table-row .file-checkbox {
   -webkit-appearance: none;
   background-image: -webkit-image-set(
-    url('../images/files/ui/new-ui/select_checkbox.png') 1x,
-    url('../images/files/ui/new-ui/2x/select_checkbox.png') 2x);
+    url('../images/files/ui/select_checkbox.png') 1x,
+    url('../images/files/ui/2x/select_checkbox.png') 2x);
   background-position: center;
   background-repeat: no-repeat;
   border-style: none;
@@ -1358,8 +1312,8 @@
 #list-container .table-header #select-all-checkbox:checked,
 #list-container li.table-row .file-checkbox:checked {
   background-image: -webkit-image-set(
-    url('../images/files/ui/new-ui/select_checkbox_checked.png') 1x,
-    url('../images/files/ui/new-ui/2x/select_checkbox_checked.png') 2x);
+    url('../images/files/ui/select_checkbox_checked.png') 1x,
+    url('../images/files/ui/2x/select_checkbox_checked.png') 2x);
 }
 
 #list-container .table-header #select-all-checkbox:checked,
@@ -1373,14 +1327,8 @@
 
 #list-container li.table-row,
 #default-actions-list li {
-  border-left-width: 0;
-  border-right-width: 0;
-  border-style: none;
   height: 29px;
   line-height: 29px;
-  margin: 0;
-  padding-bottom: 0;
-  padding-top: 0;
 }
 
 /* The icon in the name column. See file_types.css for specific icons. */
@@ -1389,6 +1337,11 @@
   width: 24px;
 }
 
+#detail-table .detail-icon {
+  /* To shift the icon position. */
+  margin-bottom: 2px;
+}
+
 .metadata-item {
   -webkit-box-flex: 1;
   -webkit-box-orient: horizontal;
@@ -1406,13 +1359,13 @@
 
 #delete-button {
   background-image: -webkit-image-set(
-    url('../images/files/ui/new-ui/onbutton_trash.png') 1x,
-    url('../images/files/ui/new-ui/2x/onbutton_trash.png') 2x);
+    url('../images/files/ui/onbutton_trash.png') 1x,
+    url('../images/files/ui/2x/onbutton_trash.png') 2x);
   background-position: center;
   background-repeat: no-repeat;
-  min-width: 25px;  /* overrride */
+  min-width: 21px;  /* overrride */
   padding: 0;  /* overrride */
-  width: 25px;
+  width: 21px;
 }
 
 #delete-button[disabled] {
@@ -1497,13 +1450,6 @@
   display: none;
 }
 
-/* A horizontal spring. */
-.horizontal-spacer {
-  -webkit-box-flex: 1;
-  -webkit-box-orient: horizontal;
-  display: -webkit-box;
-}
-
 /* A vertical spring. */
 .vertical-spacer {
   -webkit-box-flex: 1;
@@ -1514,8 +1460,7 @@
 /* Dimmed items */
 
 body[type='folder'] .file,
-body[drive] .dialog-container[connection='offline'] .dim-offline,
-body[drive] .dialog-container[connection='metered'] .dim-metered {
+body[drive] .dialog-container[connection='offline'] .dim-offline {
   opacity: 0.4;
 }
 
@@ -1558,16 +1503,25 @@
   transition: opacity 200ms ease-in;
 }
 
+#drag-container .drag-contents.for-image  {
+  padding: 2px;
+}
+
 #drag-container .thumbnail-item {
   -webkit-box-orient: horizontal;
   display: -webkit-box;
 }
 
+/* When changing these properties please preserve these conditions:
+   1. width == height (so that the rotated thumbnail does not look off-center)
+   2. width % 8 == 0 (to minimize rounding errors in the centering code) */
 #drag-container .img-container {
   -webkit-box-flex: 0;
   display: -webkit-box;
+  height: 64px;
   overflow: hidden;
   position: relative;
+  width: 64px;
 }
 
 #drag-container .label {
@@ -1581,18 +1535,6 @@
   white-space: nowrap;
 }
 
-#drag-container .drag-contents.drag-image-thumbnail  {
-  padding: 2px;
-}
-
-/* When changing these properties please preserve these conditions:
-   1. width == height (so that the rotated thumbnail does not look off-center)
-   2. width % 8 == 0 (to minimize rounding errors in the centering code) */
-#drag-container .img-container {
-  height: 64px;
-  width: 64px;
-}
-
 menu.file-context-menu {
   z-index: 4;
 }
@@ -1602,13 +1544,6 @@
   font-size: 0;
 }
 
-input.common.pin[type='checkbox']:checked::after {
-  background-image: -webkit-image-set(
-    url('../images/files/ui/pin.png') 1x,
-    url('../images/files/ui/2x/pin.png') 2x);
-  background-position: 4px 0;
-}
-
 div.offline {
   -webkit-box-pack: center;
   display: -webkit-box;
@@ -1700,22 +1635,6 @@
   text-decoration: none;
 }
 
-body[ash] .dialog-title,
-
-body[type='folder'] [invisibleif~='folder'],
-body[type='saveas-file'] [invisibleif~='saveas-file'],
-body[type='open-file'] [invisibleif~='open-file'],
-body[type='open-multi-file'] [invisibleif~='open-multi-file'],
-body[type='full-page'] [invisibleif~='full-page'],
-
-body[type='folder'] [visibleif]:not([visibleif~='folder']),
-body[type='saveas-file'] [visibleif]:not([visibleif~='saveas-file']),
-body[type='open-file'] [visibleif]:not([visibleif~='open-file']),
-body[type='open-multi-file'] [visibleif]:not([visibleif~='open-multi-file']),
-body[type='full-page'] [visibleif]:not([visibleif~='full-page']) {
-  display: none;
-}
-
 .buttonbar > * {
   position: relative;
 }
@@ -1860,12 +1779,7 @@
 
 list.autocomplete-suggestions > li {
   -webkit-box-align: center;
-  background-color: transparent;
-  background-image: none;
-  border: none;
-  border-radius: 0;
   display: -webkit-box;
-  margin: 0;  /* To prevent vertical overflow. */
   padding: 3px 0;
 }
 
@@ -1887,8 +1801,8 @@
 
 list.autocomplete-suggestions > li > div[search-icon] {
   background: -webkit-image-set(
-    url('../images/files/ui/new-ui/search_icon_active.png') 1x,
-    url('../images/files/ui/new-ui/2x/search_icon_active.png') 2x);
+    url('../images/files/ui/search_icon_active.png') 1x,
+    url('../images/files/ui/2x/search_icon_active.png') 2x);
   background-position: center;
   background-repeat: no-repeat;
 }
@@ -1921,28 +1835,28 @@
 
 menuitem#detail-view {
   background-image: -webkit-image-set(
-    url('../images/files/ui/new-ui/button_list_view.png') 1x,
-    url('../images/files/ui/new-ui/2x/button_list_view.png') 2x);
+    url('../images/files/ui/button_list_view.png') 1x,
+    url('../images/files/ui/2x/button_list_view.png') 2x);
 }
 
 menuitem#detail-view[selected]:not([disabled]),
 menuitem#detail-view[lead]:not([disabled]) {
   background-image: -webkit-image-set(
-    url('../images/files/ui/new-ui/button_list_view_white.png') 1x,
-    url('../images/files/ui/new-ui/2x/button_list_view_white.png') 2x);
+    url('../images/files/ui/button_list_view_white.png') 1x,
+    url('../images/files/ui/2x/button_list_view_white.png') 2x);
 }
 
 menuitem#thumbnail-view {
   background-image: -webkit-image-set(
-    url('../images/files/ui/new-ui/button_mosaic_view.png') 1x,
-    url('../images/files/ui/new-ui/2x/button_mosaic_view.png') 2x);
+    url('../images/files/ui/button_mosaic_view.png') 1x,
+    url('../images/files/ui/2x/button_mosaic_view.png') 2x);
 }
 
 menuitem#thumbnail-view[selected]:not([disabled]),
 menuitem#thumbnail-view[lead]:not([disabled]) {
   background-image: -webkit-image-set(
-    url('../images/files/ui/new-ui/button_mosaic_view_white.png') 1x,
-    url('../images/files/ui/new-ui/2x/button_mosaic_view_white.png') 2x);
+    url('../images/files/ui/button_mosaic_view_white.png') 1x,
+    url('../images/files/ui/2x/button_mosaic_view_white.png') 2x);
 }
 
 #iframe-drag-area {
diff --git a/chrome/browser/resources/file_manager/css/file_types.css b/chrome/browser/resources/file_manager/css/file_types.css
index d8e331e..91f5be1 100644
--- a/chrome/browser/resources/file_manager/css/file_types.css
+++ b/chrome/browser/resources/file_manager/css/file_types.css
@@ -5,22 +5,270 @@
 /* Small icons for file types, used in lists and menus. */
 [file-type-icon] {
   background-image: -webkit-image-set(
-    url('chrome://theme/IDR_FILE_MANAGER_IMG_FILETYPE_GENERIC') 1x,
-    url('chrome://theme/IDR_FILE_MANAGER_IMG_FILETYPE_GENERIC@2x') 2x);
+      url('../images/files/file_types/100/generic.png') 1x,
+      url('../images/files/file_types/200/generic.png') 2x);
   background-position: center;
   background-repeat: no-repeat;
 }
 
+tree:focus .tree-item[selected] > .tree-row > [file-type-icon],
+list:focus [selected] [file-type-icon],
+list.autocomplete-suggestions [selected] [file-type-icon] {
+  background-image: -webkit-image-set(
+    url('../images/files/file_types/100/generic_white.png') 1x,
+    url('../images/files/file_types/200/generic_white.png') 2x);
+}
+
 [file-type-icon='archive'] {
   background-image: -webkit-image-set(
-    url('chrome://theme/IDR_FILE_MANAGER_IMG_FILETYPE_ARCHIVE') 1x,
-    url('chrome://theme/IDR_FILE_MANAGER_IMG_FILETYPE_ARCHIVE@2x') 2x);
+    url('../images/files/file_types/100/archive.png') 1x,
+    url('../images/files/file_types/200/archive.png') 2x);
+}
+
+tree:focus .tree-item[selected] > .tree-row > [file-type-icon='archive'],
+list:focus [selected] [file-type-icon='archive'],
+list.autocomplete-suggestions [selected] [file-type-icon='archive'] {
+  background-image: -webkit-image-set(
+    url('../images/files/file_types/100/archive_white.png') 1x,
+    url('../images/files/file_types/200/archive_white.png') 2x);
 }
 
 [file-type-icon='audio'] {
   background-image: -webkit-image-set(
-    url('chrome://theme/IDR_FILE_MANAGER_IMG_FILETYPE_AUDIO') 1x,
-    url('chrome://theme/IDR_FILE_MANAGER_IMG_FILETYPE_AUDIO@2x') 2x);
+    url('../images/files/file_types/100/audio.png') 1x,
+    url('../images/files/file_types/200/audio.png') 2x);
+}
+
+tree:focus .tree-item[selected] > .tree-row > [file-type-icon='audio'],
+list:focus [selected] [file-type-icon='audio'],
+list.autocomplete-suggestions [selected] [file-type-icon='audio'] {
+  background-image: -webkit-image-set(
+    url('../images/files/file_types/100/audio_white.png') 1x,
+    url('../images/files/file_types/200/audio_white.png') 2x);
+}
+
+[file-type-icon='excel'] {
+  background-image: -webkit-image-set(
+    url('../images/files/file_types/100/excel.png') 1x,
+    url('../images/files/file_types/200/excel.png') 2x);
+}
+
+tree:focus .tree-item[selected] > .tree-row > [file-type-icon='excel'],
+list:focus [selected] [file-type-icon='excel'],
+list.autocomplete-suggestions [selected] [file-type-icon='excel'] {
+  background-image: -webkit-image-set(
+    url('../images/files/file_types/100/excel_white.png') 1x,
+    url('../images/files/file_types/200/excel_white.png') 2x);
+}
+
+[file-type-icon='folder'] {
+  background-image: -webkit-image-set(
+    url('../images/files/file_types/100/folder.png') 1x,
+    url('../images/files/file_types/200/folder.png') 2x);
+}
+
+tree:focus .tree-item[selected] > .tree-row > [file-type-icon='folder'],
+list:focus [selected] [file-type-icon='folder'],
+list.autocomplete-suggestions [selected] [file-type-icon='folder'] {
+  background-image: -webkit-image-set(
+    url('../images/files/file_types/100/folder_white.png') 1x,
+    url('../images/files/file_types/200/folder_white.png') 2x);
+}
+
+[file-type-icon='form'] {
+  background-image: -webkit-image-set(
+    url('../images/files/file_types/100/form.png') 1x,
+    url('../images/files/file_types/200/form.png') 2x);
+}
+
+tree:focus .tree-item[selected] > .tree-row > [file-type-icon='form'],
+list:focus [selected] [file-type-icon='form'],
+list.autocomplete-suggestions [selected] [file-type-icon='form'] {
+  background-image: -webkit-image-set(
+    url('../images/files/file_types/100/form_white.png') 1x,
+    url('../images/files/file_types/200/form_white.png') 2x);
+}
+
+[file-type-icon='gdoc'] {
+  background-image: -webkit-image-set(
+    url('../images/files/file_types/100/gdoc.png') 1x,
+    url('../images/files/file_types/200/gdoc.png') 2x);
+}
+
+tree:focus .tree-item[selected] > .tree-row > [file-type-icon='gdoc'],
+list:focus [selected] [file-type-icon='gdoc'],
+list.autocomplete-suggestions [selected] [file-type-icon='gdoc'] {
+  background-image: -webkit-image-set(
+    url('../images/files/file_types/100/gdoc_white.png') 1x,
+    url('../images/files/file_types/200/gdoc_white.png') 2x);
+}
+
+[file-type-icon='gdraw'] {
+  background-image: -webkit-image-set(
+    url('../images/files/file_types/100/gdraw.png') 1x,
+    url('../images/files/file_types/200/gdraw.png') 2x);
+}
+
+tree:focus .tree-item[selected] > .tree-row > [file-type-icon='gdraw'],
+list:focus [selected] [file-type-icon='gdraw'],
+list.autocomplete-suggestions [selected] [file-type-icon='gdraw'] {
+  background-image: -webkit-image-set(
+    url('../images/files/file_types/100/gdraw_white.png') 1x,
+    url('../images/files/file_types/200/gdraw_white.png') 2x);
+}
+
+[file-type-icon='glink'] {
+  background-image: -webkit-image-set(
+    url('../images/files/file_types/100/glink.png') 1x,
+    url('../images/files/file_types/200/glink.png') 2x);
+}
+
+tree:focus .tree-item[selected] > .tree-row > [file-type-icon='glink'],
+list:focus [selected] [file-type-icon='glink'],
+list.autocomplete-suggestions [selected] [file-type-icon='glink'] {
+  background-image: -webkit-image-set(
+    url('../images/files/file_types/100/glink_white.png') 1x,
+    url('../images/files/file_types/200/glink_white.png') 2x);
+}
+
+[file-type-icon='gsheet'] {
+  background-image: -webkit-image-set(
+    url('../images/files/file_types/100/gsheet.png') 1x,
+    url('../images/files/file_types/200/gsheet.png') 2x);
+}
+
+tree:focus .tree-item[selected] > .tree-row > [file-type-icon='gsheet'],
+list:focus [selected] [file-type-icon='gsheet'],
+list.autocomplete-suggestions [selected] [file-type-icon='gsheet'] {
+  background-image: -webkit-image-set(
+    url('../images/files/file_types/100/gsheet_white.png') 1x,
+    url('../images/files/file_types/200/gsheet_white.png') 2x);
+}
+
+[file-type-icon='gslides'] {
+  background-image: -webkit-image-set(
+    url('../images/files/file_types/100/gslides.png') 1x,
+    url('../images/files/file_types/200/gslides.png') 2x);
+}
+
+tree:focus .tree-item[selected] > .tree-row > [file-type-icon='gslides'],
+list:focus [selected] [file-type-icon='gslides'],
+list.autocomplete-suggestions [selected] [file-type-icon='gslides'] {
+  background-image: -webkit-image-set(
+    url('../images/files/file_types/100/gslides_white.png') 1x,
+    url('../images/files/file_types/200/gslides_white.png') 2x);
+}
+
+[file-type-icon='gtable'] {
+  background-image: -webkit-image-set(
+    url('../images/files/file_types/100/gtable.png') 1x,
+    url('../images/files/file_types/200/gtable.png') 2x);
+}
+
+tree:focus .tree-item[selected] > .tree-row > [file-type-icon='gtable'],
+list:focus [selected] [file-type-icon='gtable'],
+list.autocomplete-suggestions [selected] [file-type-icon='gtable'] {
+  background-image: -webkit-image-set(
+    url('../images/files/file_types/100/gtable_white.png') 1x,
+    url('../images/files/file_types/200/gtable_white.png') 2x);
+}
+
+[file-type-icon='image'] {
+  background-image: -webkit-image-set(
+    url('../images/files/file_types/100/image.png') 1x,
+    url('../images/files/file_types/200/image.png') 2x);
+}
+
+tree:focus .tree-item[selected] > .tree-row > [file-type-icon='image'],
+list:focus [selected] [file-type-icon='image'],
+list.autocomplete-suggestions [selected] [file-type-icon='image'] {
+  background-image: -webkit-image-set(
+    url('../images/files/file_types/100/image_white.png') 1x,
+    url('../images/files/file_types/200/image_white.png') 2x);
+}
+
+[file-type-icon='pdf'] {
+  background-image: -webkit-image-set(
+    url('../images/files/file_types/100/pdf.png') 1x,
+    url('../images/files/file_types/200/pdf.png') 2x);
+}
+
+tree:focus .tree-item[selected] > .tree-row > [file-type-icon='pdf'],
+list:focus [selected] [file-type-icon='pdf'],
+list.autocomplete-suggestions [selected] [file-type-icon='pdf'] {
+  background-image: -webkit-image-set(
+    url('../images/files/file_types/100/pdf_white.png') 1x,
+    url('../images/files/file_types/200/pdf_white.png') 2x);
+}
+
+[file-type-icon='ppt'] {
+  background-image: -webkit-image-set(
+    url('../images/files/file_types/100/ppt.png') 1x,
+    url('../images/files/file_types/200/ppt.png') 2x);
+}
+
+tree:focus .tree-item[selected] > .tree-row > [file-type-icon='ppt'],
+list:focus [selected] [file-type-icon='ppt'],
+list.autocomplete-suggestions [selected] [file-type-icon='ppt'] {
+  background-image: -webkit-image-set(
+    url('../images/files/file_types/100/ppt_white.png') 1x,
+    url('../images/files/file_types/200/ppt_white.png') 2x);
+}
+
+[file-type-icon='script'] {
+  background-image: -webkit-image-set(
+    url('../images/files/file_types/100/script.png') 1x,
+    url('../images/files/file_types/200/script.png') 2x);
+}
+
+tree:focus .tree-item[selected] > .tree-row > [file-type-icon='script'],
+list:focus [selected] [file-type-icon='script'],
+list.autocomplete-suggestions [selected] [file-type-icon='script'] {
+  background-image: -webkit-image-set(
+    url('../images/files/file_types/100/script_white.png') 1x,
+    url('../images/files/file_types/200/script_white.png') 2x);
+}
+
+[file-type-icon='sites'] {
+  background-image: -webkit-image-set(
+    url('../images/files/file_types/100/sites.png') 1x,
+    url('../images/files/file_types/200/sites.png') 2x);
+}
+
+tree:focus .tree-item[selected] > .tree-row > [file-type-icon='sites'],
+list:focus [selected] [file-type-icon='sites'],
+list.autocomplete-suggestions [selected] [file-type-icon='sites'] {
+  background-image: -webkit-image-set(
+    url('../images/files/file_types/100/sites_white.png') 1x,
+    url('../images/files/file_types/200/sites_white.png') 2x);
+}
+
+[file-type-icon='video'] {
+  background-image: -webkit-image-set(
+    url('../images/files/file_types/100/video.png') 1x,
+    url('../images/files/file_types/200/video.png') 2x);
+}
+
+tree:focus .tree-item[selected] > .tree-row > [file-type-icon='video'],
+list:focus [selected] [file-type-icon='video'],
+list.autocomplete-suggestions [selected] [file-type-icon='video'] {
+  background-image: -webkit-image-set(
+    url('../images/files/file_types/100/video_white.png') 1x,
+    url('../images/files/file_types/200/video_white.png') 2x);
+}
+
+[file-type-icon='word'] {
+  background-image: -webkit-image-set(
+    url('../images/files/file_types/100/word.png') 1x,
+    url('../images/files/file_types/200/word.png') 2x);
+}
+
+tree:focus .tree-item[selected] > .tree-row > [file-type-icon='word'],
+list:focus [selected] [file-type-icon='word'],
+list.autocomplete-suggestions [selected] [file-type-icon='word'] {
+  background-image: -webkit-image-set(
+    url('../images/files/file_types/100/word_white.png') 1x,
+    url('../images/files/file_types/200/word_white.png') 2x);
 }
 
 [file-type-icon='drive'] {
@@ -29,88 +277,6 @@
     url('chrome://theme/IDR_FILE_MANAGER_IMG_FILETYPE_DRIVE@2x') 2x);
 }
 
-[file-type-icon='excel'] {
-  background-image: -webkit-image-set(
-    url('chrome://theme/IDR_FILE_MANAGER_IMG_FILETYPE_EXCEL') 1x,
-    url('chrome://theme/IDR_FILE_MANAGER_IMG_FILETYPE_EXCEL@2x') 2x);
-}
-
-/* TODO(mtomasz): Move all assets from themes to local resources. */
-/* TODO(mtomasz): Add inverted icons for other file types. */
-[file-type-icon='folder'] {
-  background-image: -webkit-image-set(
-    url('../images/files/ui/new-ui/black_folder.png') 1x,
-    url('../images/files/ui/new-ui/2x/black_folder.png') 2x);
-}
-
-tree:focus .tree-item[selected] > .tree-row > [file-type-icon='folder'],
-list.autocomplete-suggestions li[selected] [file-type-icon='folder'],
-list:focus li[selected] [file-type-icon='folder'] {
-  background-image: -webkit-image-set(
-    url('../images/files/ui/new-ui/white_folder.png') 1x,
-    url('../images/files/ui/new-ui/2x/white_folder.png') 2x);
-}
-
-[file-type-icon='gdoc'] {
-  background-image: -webkit-image-set(
-    url('chrome://theme/IDR_FILE_MANAGER_IMG_FILETYPE_GDOC') 1x,
-    url('chrome://theme/IDR_FILE_MANAGER_IMG_FILETYPE_GDOC@2x') 2x);
-}
-
-[file-type-icon='gdraw'] {
-  background-image: -webkit-image-set(
-    url('chrome://theme/IDR_FILE_MANAGER_IMG_FILETYPE_GDRAW') 1x,
-    url('chrome://theme/IDR_FILE_MANAGER_IMG_FILETYPE_GDRAW@2x') 2x);
-}
-
-[file-type-icon='gsheet'] {
-  background-image: -webkit-image-set(
-    url('chrome://theme/IDR_FILE_MANAGER_IMG_FILETYPE_GSHEET') 1x,
-    url('chrome://theme/IDR_FILE_MANAGER_IMG_FILETYPE_GSHEET@2x') 2x);
-}
-
-[file-type-icon='gslides'] {
-  background-image: -webkit-image-set(
-    url('chrome://theme/IDR_FILE_MANAGER_IMG_FILETYPE_GSLIDES') 1x,
-    url('chrome://theme/IDR_FILE_MANAGER_IMG_FILETYPE_GSLIDES@2x') 2x);
-}
-
-[file-type-icon='gtable'] {
-  background-image: -webkit-image-set(
-    url('chrome://theme/IDR_FILE_MANAGER_IMG_FILETYPE_GTABLE') 1x,
-    url('chrome://theme/IDR_FILE_MANAGER_IMG_FILETYPE_GTABLE@2x') 2x);
-}
-
-[file-type-icon='image'] {
-  background-image: -webkit-image-set(
-    url('chrome://theme/IDR_FILE_MANAGER_IMG_FILETYPE_IMAGE') 1x,
-    url('chrome://theme/IDR_FILE_MANAGER_IMG_FILETYPE_IMAGE@2x') 2x);
-}
-
-[file-type-icon='pdf'] {
-  background-image: -webkit-image-set(
-    url('chrome://theme/IDR_FILE_MANAGER_IMG_FILETYPE_PDF') 1x,
-    url('chrome://theme/IDR_FILE_MANAGER_IMG_FILETYPE_PDF@2x') 2x);
-}
-
-[file-type-icon='ppt'] {
-  background-image: -webkit-image-set(
-    url('chrome://theme/IDR_FILE_MANAGER_IMG_FILETYPE_PPT') 1x,
-    url('chrome://theme/IDR_FILE_MANAGER_IMG_FILETYPE_PPT@2x') 2x);
-}
-
-[file-type-icon='video'] {
-  background-image: -webkit-image-set(
-    url('chrome://theme/IDR_FILE_MANAGER_IMG_FILETYPE_VIDEO') 1x,
-    url('chrome://theme/IDR_FILE_MANAGER_IMG_FILETYPE_VIDEO@2x') 2x);
-}
-
-[file-type-icon='word'] {
-  background-image: -webkit-image-set(
-    url('chrome://theme/IDR_FILE_MANAGER_IMG_FILETYPE_WORD') 1x,
-    url('chrome://theme/IDR_FILE_MANAGER_IMG_FILETYPE_WORD@2x') 2x);
-}
-
 /* Large generic thumbnails, used when a file does not have a thumbnail. */
 [generic-thumbnail] {
   background-image: -webkit-image-set(
@@ -145,181 +311,120 @@
 }
 
 /* Icons for volume types. */
-[volume-type-icon='archive'] {
-  background-image: -webkit-image-set(
-    url('../images/files/volumes/archive.png') 1x,
-    url('../images/files/volumes/2x/archive.png') 2x);
-}
-
-[volume-type-icon='downloads'] {
-  background-image: -webkit-image-set(
-    url('../images/files/volumes/downloads.png') 1x,
-    url('../images/files/volumes/2x/downloads.png') 2x);
-}
-
-[volume-type-icon='drive'] {
-  background-image: -webkit-image-set(
-    url('../images/files/volumes/drive.png') 1x,
-    url('../images/files/volumes/2x/drive.png') 2x);
-}
-
-[volume-type-icon='drive_offline'] {
-  background-image: -webkit-image-set(
-    url('../images/files/volumes/drive_offline.png') 1x,
-    url('../images/files/volumes/2x/drive_offline.png') 2x);
-}
-
-[volume-type-icon='drive_shared_with_me'] {
-  background-image: -webkit-image-set(
-    url('../images/files/volumes/drive_shared.png') 1x,
-    url('../images/files/volumes/2x/drive_shared.png') 2x);
-}
-
-[volume-type-icon='drive_recent'] {
-  background-image: -webkit-image-set(
-    url('../images/files/volumes/drive_recent.png') 1x,
-    url('../images/files/volumes/2x/drive_recent.png') 2x);
-}
-
-[volume-type-icon='removable'] {
-  background-image: -webkit-image-set(
-    url('../images/files/volumes/device_usb.png') 1x,
-    url('../images/files/volumes/2x/device_usb.png') 2x);
-}
-
-[volume-type-icon='removable'][volume-subtype='sd'] {
-  background-image: -webkit-image-set(
-    url('../images/files/volumes/device_sd.png') 1x,
-    url('../images/files/volumes/2x/device_sd.png') 2x);
-}
-
-[volume-type-icon='removable'][volume-subtype='optical'] {
-  background-image: -webkit-image-set(
-    url('../images/files/volumes/device_optical.png') 1x,
-    url('../images/files/volumes/2x/device_optical.png') 2x);
-}
-
-/* TODO(kaznacheev): consider a better icon for volume-subtype=unknown.
-   Also find out if we need an icon for volume-subtype=mobile */
-[volume-type-icon='removable'][volume-subtype='unknown'] {
-  background-image: -webkit-image-set(
-    url('../images/files/volumes/device_hd.png') 1x,
-    url('../images/files/volumes/2x/device_hd.png') 2x);
-}
 
 [volume-type-icon='archive'] {
   background-image: -webkit-image-set(
-    url('../images/files/volumes/new-ui/black_archive.png') 1x,
-    url('../images/files/volumes/new-ui/2x/black_archive.png') 2x);
+    url('../images/files/volumes/black_archive.png') 1x,
+    url('../images/files/volumes/2x/black_archive.png') 2x);
 }
 
 list:focus li[selected] [volume-type-icon='archive'],
 tree:focus .tree-item[selected] > .tree-row > [volume-type-icon='archive'] {
   background-image: -webkit-image-set(
-    url('../images/files/volumes/new-ui/white_archive.png') 1x,
-    url('../images/files/volumes/new-ui/2x/white_archive.png') 2x);
+    url('../images/files/volumes/white_archive.png') 1x,
+    url('../images/files/volumes/2x/white_archive.png') 2x);
 }
 
 [volume-type-icon='downloads'] {
   background-image: -webkit-image-set(
-    url('../images/files/volumes/new-ui/black_downloads.png') 1x,
-    url('../images/files/volumes/new-ui/2x/black_downloads.png') 2x);
+    url('../images/files/volumes/black_downloads.png') 1x,
+    url('../images/files/volumes/2x/black_downloads.png') 2x);
 }
 
 list:focus li[selected] [volume-type-icon='downloads'],
 tree:focus .tree-item[selected] > .tree-row > [volume-type-icon='downloads'] {
   background-image: -webkit-image-set(
-    url('../images/files/volumes/new-ui/white_downloads.png') 1x,
-    url('../images/files/volumes/new-ui/2x/white_downloads.png') 2x);
+    url('../images/files/volumes/white_downloads.png') 1x,
+    url('../images/files/volumes/2x/white_downloads.png') 2x);
 }
 
 [volume-type-icon='drive'] {
   background-image: -webkit-image-set(
-    url('../images/files/volumes/new-ui/black_drive.png') 1x,
-    url('../images/files/volumes/new-ui/2x/black_drive.png') 2x);
+    url('../images/files/volumes/black_drive.png') 1x,
+    url('../images/files/volumes/2x/black_drive.png') 2x);
 }
 
 list:focus li[selected] [volume-type-icon='drive'],
 tree:focus .tree-item[selected] > .tree-row > [volume-type-icon='drive'] {
   background-image: -webkit-image-set(
-    url('../images/files/volumes/new-ui/white_drive.png') 1x,
-    url('../images/files/volumes/new-ui/2x/white_drive.png') 2x);
+    url('../images/files/volumes/white_drive.png') 1x,
+    url('../images/files/volumes/2x/white_drive.png') 2x);
 }
 
 [volume-type-icon='drive_offline'] {
   background-image: -webkit-image-set(
-    url('../images/files/volumes/new-ui/black_offline.png') 1x,
-    url('../images/files/volumes/new-ui/2x/black_offline.png') 2x);
+    url('../images/files/volumes/black_offline.png') 1x,
+    url('../images/files/volumes/2x/black_offline.png') 2x);
 }
 
 list:focus li[selected] [volume-type-icon='drive_offline'],
 tree:focus .tree-item[selected] > .tree-row >
     [volume-type-icon='drive_offline'] {
   background-image: -webkit-image-set(
-    url('../images/files/volumes/new-ui/white_offline.png') 1x,
-    url('../images/files/volumes/new-ui/2x/white_offline.png') 2x);
+    url('../images/files/volumes/white_offline.png') 1x,
+    url('../images/files/volumes/2x/white_offline.png') 2x);
 }
 
 [volume-type-icon='drive_shared_with_me'] {
   background-image: -webkit-image-set(
-    url('../images/files/volumes/new-ui/black_shared.png') 1x,
-    url('../images/files/volumes/new-ui/2x/black_shared.png') 2x);
+    url('../images/files/volumes/black_shared.png') 1x,
+    url('../images/files/volumes/2x/black_shared.png') 2x);
 }
 
 list:focus li[selected] [volume-type-icon='drive_shared_with_me'],
 tree:focus .tree-item[selected] > .tree-row >
     [volume-type-icon='drive_shared_with_me'] {
   background-image: -webkit-image-set(
-    url('../images/files/volumes/new-ui/white_shared.png') 1x,
-    url('../images/files/volumes/new-ui/2x/white_shared.png') 2x);
+    url('../images/files/volumes/white_shared.png') 1x,
+    url('../images/files/volumes/2x/white_shared.png') 2x);
 }
 
 [volume-type-icon='drive_recent'] {
   background-image: -webkit-image-set(
-    url('../images/files/volumes/new-ui/black_recent.png') 1x,
-    url('../images/files/volumes/new-ui/2x/black_recent.png') 2x);
+    url('../images/files/volumes/black_recent.png') 1x,
+    url('../images/files/volumes/2x/black_recent.png') 2x);
 }
 
 list:focus li[selected] [volume-type-icon='drive_recent'],
 tree:focus .tree-item[selected] > .tree-row >
     [volume-type-icon='drive_recent'] {
   background-image: -webkit-image-set(
-    url('../images/files/volumes/new-ui/white_recent.png') 1x,
-    url('../images/files/volumes/new-ui/2x/white_recent.png') 2x);
+    url('../images/files/volumes/white_recent.png') 1x,
+    url('../images/files/volumes/2x/white_recent.png') 2x);
 }
 
 [volume-type-icon='removable'] {
   background-image: -webkit-image-set(
-    url('../images/files/volumes/new-ui/black_usb.png') 1x,
-    url('../images/files/volumes/new-ui/2x/black_usb.png') 2x);
+    url('../images/files/volumes/black_usb.png') 1x,
+    url('../images/files/volumes/2x/black_usb.png') 2x);
 }
 
 list:focus li[selected] [volume-type-icon='removable'],
 tree:focus .tree-item[selected] > .tree-row >
     [volume-type-icon='removable'] {
   background-image: -webkit-image-set(
-    url('../images/files/volumes/new-ui/white_usb.png') 1x,
-    url('../images/files/volumes/new-ui/2x/white_usb.png') 2x);
+    url('../images/files/volumes/white_usb.png') 1x,
+    url('../images/files/volumes/2x/white_usb.png') 2x);
 }
 
 [volume-type-icon='removable'][volume-subtype='sd'] {
   background-image: -webkit-image-set(
-    url('../images/files/volumes/new-ui/black_sd.png') 1x,
-    url('../images/files/volumes/new-ui/2x/black_sd.png') 2x);
+    url('../images/files/volumes/black_sd.png') 1x,
+    url('../images/files/volumes/2x/black_sd.png') 2x);
 }
 
 list:focus li[selected] [volume-type-icon='removable'][volume-subtype='sd'],
 tree:focus .tree-item[selected] > .tree-row >
     [volume-type-icon='removable'][volume-subtype='sd'] {
   background-image: -webkit-image-set(
-    url('../images/files/volumes/new-ui/white_sd.png') 1x,
-    url('../images/files/volumes/new-ui/2x/white_sd.png') 2x);
+    url('../images/files/volumes/white_sd.png') 1x,
+    url('../images/files/volumes/2x/white_sd.png') 2x);
 }
 
 [volume-type-icon='removable'][volume-subtype='optical'] {
   background-image: -webkit-image-set(
-    url('../images/files/volumes/new-ui/black_optical.png') 1x,
-    url('../images/files/volumes/new-ui/2x/black_optical.png') 2x);
+    url('../images/files/volumes/black_optical.png') 1x,
+    url('../images/files/volumes/2x/black_optical.png') 2x);
 }
 
 list:focus div[selected]
@@ -327,8 +432,8 @@
 tree:focus .tree-item[selected] > .tree-row >
     [volume-type-icon='removable'][volume-subtype='optical'] {
   background-image: -webkit-image-set(
-    url('../images/files/volumes/new-ui/white_optical.png') 1x,
-    url('../images/files/volumes/new-ui/2x/white_optical.png') 2x);
+    url('../images/files/volumes/white_optical.png') 1x,
+    url('../images/files/volumes/2x/white_optical.png') 2x);
 }
 
 list:focus li[selected]
@@ -336,16 +441,16 @@
 tree:focus .tree-item[selected] > .tree-row >
     [volume-type-icon='removable'][volume-subtype='optical'] {
   background-image: -webkit-image-set(
-    url('../images/files/volumes/new-ui/white_optical.png') 1x,
-    url('../images/files/volumes/new-ui/2x/white_optical.png') 2x);
+    url('../images/files/volumes/white_optical.png') 1x,
+    url('../images/files/volumes/2x/white_optical.png') 2x);
 }
 
 /* TODO(kaznacheev): consider a better icon for volume-subtype=unknown.
    Also find out if we need an icon for volume-subtype=mobile */
 [volume-type-icon='removable'][volume-subtype='unknown'] {
   background-image: -webkit-image-set(
-    url('../images/files/volumes/new-ui/black_hdd.png') 1x,
-    url('../images/files/volumes/new-ui/2x/black_hdd.png') 2x);
+    url('../images/files/volumes/black_hdd.png') 1x,
+    url('../images/files/volumes/2x/black_hdd.png') 2x);
 }
 
 list:focus li[selected]
@@ -353,6 +458,6 @@
 tree:focus .tree-item[selected] > .tree-row >
     [volume-type-icon='removable'][volume-subtype='unknown'] {
   background-image: -webkit-image-set(
-    url('../images/files/volumes/new-ui/white_hdd.png') 1x,
-    url('../images/files/volumes/new-ui/2x/white_hdd.png') 2x);
+    url('../images/files/volumes/white_hdd.png') 1x,
+    url('../images/files/volumes/2x/white_hdd.png') 2x);
 }
diff --git a/chrome/browser/resources/file_manager/css/gallery.css b/chrome/browser/resources/file_manager/css/gallery.css
index ea005c8..5d2a20a 100644
--- a/chrome/browser/resources/file_manager/css/gallery.css
+++ b/chrome/browser/resources/file_manager/css/gallery.css
@@ -787,14 +787,30 @@
     url('../images/gallery/2x/icon_edit_selected.png') 2x);
 }
 
+.gallery > .toolbar > button.print {
+  background-image: -webkit-image-set(
+    url('../images/gallery/icon_print.png') 1x,
+    url('../images/gallery/2x/icon_print.png') 2x);
+}
+
+.gallery > .toolbar > button.print:active,
+.gallery > .toolbar > button.print[pressed] {
+  background-image: -webkit-image-set(
+    url('../images/gallery/icon_print_selected.png') 1x,
+    url('../images/gallery/2x/icon_print_selected.png') 2x);
+}
+
 .gallery > .toolbar > button.share {
   background-image: -webkit-image-set(
     url('../images/gallery/icon_share.png') 1x,
     url('../images/gallery/2x/icon_share.png') 2x);
 }
 
-.gallery > .toolbar > button.share:hover {
-  background-color: rgba(31, 31, 31, 1);
+.gallery > .toolbar > button.share:active,
+.gallery > .toolbar > button.share[pressed] {
+  background-image: -webkit-image-set(
+    url('../images/gallery/icon_share_selected.png') 1x,
+    url('../images/gallery/2x/icon_share_selected.png') 2x);
 }
 
 .gallery[error] > .toolbar button.edit,
@@ -1352,12 +1368,12 @@
 
 .gallery > .header > .maximize-button {
   background-image: -webkit-image-set(
-    url('../images/files/ui/new-ui/topbar_button_maximize.png') 1x,
-    url('../images/files/ui/new-ui/2x/topbar_button_maximize.png') 2x);
+    url('../images/files/ui/topbar_button_maximize.png') 1x,
+    url('../images/files/ui/2x/topbar_button_maximize.png') 2x);
 }
 
 .gallery > .header > .close-button {
   background-image: -webkit-image-set(
-    url('../images/files/ui/new-ui/topbar_button_close.png') 1x,
-    url('../images/files/ui/new-ui/2x/topbar_button_close.png') 2x);
+    url('../images/files/ui/topbar_button_close.png') 1x,
+    url('../images/files/ui/2x/topbar_button_close.png') 2x);
 }
diff --git a/chrome/browser/resources/file_manager/css/list.css b/chrome/browser/resources/file_manager/css/list.css
new file mode 100644
index 0000000..d102d69
--- /dev/null
+++ b/chrome/browser/resources/file_manager/css/list.css
@@ -0,0 +1,73 @@
+/* Copyright 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+/* Derived from /ui/webui/resources/css/list.css. */
+
+list,
+grid {
+  display: block;
+  outline: none;
+  overflow: auto;
+  position: relative; /* Make sure that item offsets are relative to the
+                         list. */
+}
+
+list > *,
+grid > * {
+  -webkit-user-select: none;
+  position: relative; /* to allow overlap */
+  text-overflow: ellipsis;
+  white-space: pre;
+}
+
+list > * {
+  display: block;
+}
+
+grid > * {
+  display: inline-block;
+}
+
+list:focus > [lead],
+grid:focus > [lead] {
+  z-index: 2;
+}
+
+list:not([disabled]) > :hover,
+grid:not([disabled]) > :hover {
+  z-index: 1;
+}
+
+list > [selected],
+grid > [selected] {
+  z-index: 2;
+}
+
+list > .spacer,
+grid > .spacer {
+  box-sizing: border-box;
+  display: block;
+  overflow: hidden;
+  visibility: hidden;
+}
+
+list :-webkit-any(
+    input[type='input'],
+    input[type='password'],
+    input[type='search'],
+    input[type='text'],
+    input[type='url']),
+list :-webkit-any(
+    button,
+    input[type='button'],
+    input[type='submit'],
+    select):not(.custom-appearance):not(.link-button) {
+  line-height: normal;
+  vertical-align: middle;
+}
+
+list > [hidden],
+grid > [hidden] {
+  display: none;
+}
diff --git a/chrome/browser/resources/file_manager/css/media_controls.css b/chrome/browser/resources/file_manager/css/media_controls.css
index 7b56adb..98745a0 100644
--- a/chrome/browser/resources/file_manager/css/media_controls.css
+++ b/chrome/browser/resources/file_manager/css/media_controls.css
@@ -536,6 +536,28 @@
   z-index: 2;
 }
 
+.text-banner {
+  background-color: black;
+  border-radius: 10px;
+  color: white;
+  font-size: 18px;
+  left: 50%;
+  margin-left: -250px;
+  opacity: 0;
+  padding: 10px;
+  pointer-events: none;
+  position: absolute;
+  text-align: center;
+  text-shadow: 0 0 10px black;
+  top: 20%;
+  width: 500px;
+  z-index: 2;
+}
+
+.text-banner[visible] {
+  -webkit-animation: text-banner-blowup 3000ms;
+}
+
 .playback-state-icon[state] {
   -webkit-animation: blowup 500ms;
 }
@@ -550,6 +572,25 @@
   }
 }
 
+@-webkit-keyframes text-banner-blowup {
+  from {
+    -webkit-transform: scale(0.5);
+    opacity: 0;
+  }
+  20% {
+    -webkit-transform: scale(1);
+    opacity: 0.75;
+  }
+  80% {
+    -webkit-transform: scale(1);
+    opacity: 0.75;
+  }
+  to {
+    -webkit-transform: scale(3);
+    opacity: 0;
+  }
+}
+
 .playback-state-icon[state='play'] {
   background-image: -webkit-image-set(
     url('../images/media/media_play.png') 1x,
diff --git a/chrome/browser/resources/file_manager/css/table.css b/chrome/browser/resources/file_manager/css/table.css
new file mode 100644
index 0000000..8351699
--- /dev/null
+++ b/chrome/browser/resources/file_manager/css/table.css
@@ -0,0 +1,64 @@
+/* Copyright 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+/* Derived from /ui/webui/resources/css/table.css. */
+
+html.col-resize * {
+  cursor: col-resize !important;
+}
+
+.table[hasElementFocus] > list > [lead] {
+  z-index: 2;
+}
+
+.table-row {
+  display: -webkit-box;
+  text-align: start;
+  width: 100%;
+}
+
+.table-row-cell {
+  display: -webkit-box;
+  overflow: hidden;
+}
+
+.table-row-cell > * {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.table-header {
+  overflow: hidden;
+  position: relative;
+}
+
+.table-header-inner {
+  -webkit-user-select: none;
+  cursor: default;
+  display: -webkit-box;
+  position: relative;
+  text-align: start;
+}
+
+.table-header-cell {
+  font-weight: normal;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.table-header-label {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.table-header-splitter {
+  cursor: col-resize;
+  height: 100%;
+  left: 0;
+  position: absolute;
+  top: 0;
+}
diff --git a/chrome/browser/resources/file_manager/css/tree.css b/chrome/browser/resources/file_manager/css/tree.css
new file mode 100644
index 0000000..e151977
--- /dev/null
+++ b/chrome/browser/resources/file_manager/css/tree.css
@@ -0,0 +1,83 @@
+/* Copyright 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+/* Derived from /ui/webui/resources/css/table.css. */
+
+tree {
+  display: block;
+  outline: none;
+  overflow: auto;
+}
+
+.tree-item > .tree-row {
+  -webkit-user-select: none;
+  cursor: default;
+  position: relative;
+  white-space: nowrap;
+}
+
+.expand-icon {
+  -webkit-transform: rotate(-90deg);
+  -webkit-transition: all 150ms;
+  background-image: -webkit-canvas(tree-triangle);
+  background-position: 50% 50%;
+  background-repeat: no-repeat;
+  background-size: 8px 5px;
+  display: inline-block;
+  height: 16px;
+  position: relative;
+  vertical-align: top;
+}
+
+html[dir=rtl] .expand-icon {
+  -webkit-transform: rotate(90deg);
+}
+
+.tree-item[expanded] > .tree-row > .expand-icon {
+  -webkit-transform: rotate(0);
+  background-image: -webkit-canvas(tree-triangle);
+}
+
+.tree-row .expand-icon {
+  visibility: hidden;
+}
+
+.tree-row[may-have-children] .expand-icon {
+  visibility: visible;
+}
+
+.tree-row[has-children=false] .expand-icon {
+  visibility: hidden;
+}
+
+.tree-row[selected] {
+  z-index: 2;
+}
+
+.tree-children[expanded] {
+  display: block;
+}
+
+.tree-children {
+  display: none;
+}
+
+.tree-item > .tree-row > * {
+  display: inline-block;
+}
+
+.tree-label {
+  white-space: pre;
+}
+
+/* We need to ensure that even empty labels take up space */
+.tree-label:empty::after {
+  content: ' ';
+  white-space: pre;
+}
+
+.tree-rename > .tree-row > .tree-label {
+  -webkit-user-modify: read-write-plaintext-only;
+  -webkit-user-select: auto;
+}
diff --git a/chrome/browser/resources/file_manager/gallery.html b/chrome/browser/resources/file_manager/gallery.html
index f31450c..dfa6941 100644
--- a/chrome/browser/resources/file_manager/gallery.html
+++ b/chrome/browser/resources/file_manager/gallery.html
@@ -24,7 +24,7 @@
     <script src="js/metrics.js"></script>
 
     <!-- Loads the client of the image loader extension -->
-    <script src="chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/client.js"></script>
+    <script src="chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/image_loader_client.js"></script>
 
     <script src="chrome://resources/js/cr.js"></script>
     <script src="chrome://resources/js/event_tracker.js"></script>
diff --git a/chrome/browser/resources/file_manager/images/common/2x/bubble_point_white.png b/chrome/browser/resources/file_manager/images/common/2x/bubble_point_white.png
index 970a4bf..643847b 100644
--- a/chrome/browser/resources/file_manager/images/common/2x/bubble_point_white.png
+++ b/chrome/browser/resources/file_manager/images/common/2x/bubble_point_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/common/2x/button.png b/chrome/browser/resources/file_manager/images/common/2x/button.png
index 08cef2f..d185c7b 100644
--- a/chrome/browser/resources/file_manager/images/common/2x/button.png
+++ b/chrome/browser/resources/file_manager/images/common/2x/button.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/common/2x/button_hover.png b/chrome/browser/resources/file_manager/images/common/2x/button_hover.png
index cd1dbcd..5de5c7e 100644
--- a/chrome/browser/resources/file_manager/images/common/2x/button_hover.png
+++ b/chrome/browser/resources/file_manager/images/common/2x/button_hover.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/common/2x/button_pressed.png b/chrome/browser/resources/file_manager/images/common/2x/button_pressed.png
index 70b2375..eee68dd 100644
--- a/chrome/browser/resources/file_manager/images/common/2x/button_pressed.png
+++ b/chrome/browser/resources/file_manager/images/common/2x/button_pressed.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/common/2x/check_blue.png b/chrome/browser/resources/file_manager/images/common/2x/check_blue.png
index baae1aa..6f55f5a 100644
--- a/chrome/browser/resources/file_manager/images/common/2x/check_blue.png
+++ b/chrome/browser/resources/file_manager/images/common/2x/check_blue.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/common/2x/check_circled.png b/chrome/browser/resources/file_manager/images/common/2x/check_circled.png
index 67d1c77..5567ac2 100644
--- a/chrome/browser/resources/file_manager/images/common/2x/check_circled.png
+++ b/chrome/browser/resources/file_manager/images/common/2x/check_circled.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/common/2x/check_no_box.png b/chrome/browser/resources/file_manager/images/common/2x/check_no_box.png
index 5c4a1aa..8dddff8 100644
--- a/chrome/browser/resources/file_manager/images/common/2x/check_no_box.png
+++ b/chrome/browser/resources/file_manager/images/common/2x/check_no_box.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/common/2x/checkbox_white_checked.png b/chrome/browser/resources/file_manager/images/common/2x/checkbox_white_checked.png
index 0055b5f..466fa22 100644
--- a/chrome/browser/resources/file_manager/images/common/2x/checkbox_white_checked.png
+++ b/chrome/browser/resources/file_manager/images/common/2x/checkbox_white_checked.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/common/2x/checkbox_white_unchecked.png b/chrome/browser/resources/file_manager/images/common/2x/checkbox_white_unchecked.png
index aa4fbea..88d97d7 100644
--- a/chrome/browser/resources/file_manager/images/common/2x/checkbox_white_unchecked.png
+++ b/chrome/browser/resources/file_manager/images/common/2x/checkbox_white_unchecked.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/common/2x/close_x_gray.png b/chrome/browser/resources/file_manager/images/common/2x/close_x_gray.png
index 0a16850..8a2930a 100644
--- a/chrome/browser/resources/file_manager/images/common/2x/close_x_gray.png
+++ b/chrome/browser/resources/file_manager/images/common/2x/close_x_gray.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/common/2x/disclosure_arrow_dk_grey.png b/chrome/browser/resources/file_manager/images/common/2x/disclosure_arrow_dk_grey.png
index 93c5a31..8f35319 100644
--- a/chrome/browser/resources/file_manager/images/common/2x/disclosure_arrow_dk_grey.png
+++ b/chrome/browser/resources/file_manager/images/common/2x/disclosure_arrow_dk_grey.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/common/bubble_point_white.png b/chrome/browser/resources/file_manager/images/common/bubble_point_white.png
index 0c7d52a..ec5dbe9 100644
--- a/chrome/browser/resources/file_manager/images/common/bubble_point_white.png
+++ b/chrome/browser/resources/file_manager/images/common/bubble_point_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/common/button.png b/chrome/browser/resources/file_manager/images/common/button.png
index 997799a..4de5ff0 100644
--- a/chrome/browser/resources/file_manager/images/common/button.png
+++ b/chrome/browser/resources/file_manager/images/common/button.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/common/button_hover.png b/chrome/browser/resources/file_manager/images/common/button_hover.png
index d185e09..c24d7cc 100644
--- a/chrome/browser/resources/file_manager/images/common/button_hover.png
+++ b/chrome/browser/resources/file_manager/images/common/button_hover.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/common/button_pressed.png b/chrome/browser/resources/file_manager/images/common/button_pressed.png
index 782b883..c54d6fe 100644
--- a/chrome/browser/resources/file_manager/images/common/button_pressed.png
+++ b/chrome/browser/resources/file_manager/images/common/button_pressed.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/common/check_blue.png b/chrome/browser/resources/file_manager/images/common/check_blue.png
index 2fb8be2..deff101 100644
--- a/chrome/browser/resources/file_manager/images/common/check_blue.png
+++ b/chrome/browser/resources/file_manager/images/common/check_blue.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/common/check_circled.png b/chrome/browser/resources/file_manager/images/common/check_circled.png
index 7f6fb30..ee787be 100644
--- a/chrome/browser/resources/file_manager/images/common/check_circled.png
+++ b/chrome/browser/resources/file_manager/images/common/check_circled.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/common/check_no_box.png b/chrome/browser/resources/file_manager/images/common/check_no_box.png
index 7af1470..3006dcd 100644
--- a/chrome/browser/resources/file_manager/images/common/check_no_box.png
+++ b/chrome/browser/resources/file_manager/images/common/check_no_box.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/common/checkbox_white_checked.png b/chrome/browser/resources/file_manager/images/common/checkbox_white_checked.png
index ad8e943..c095d6c 100644
--- a/chrome/browser/resources/file_manager/images/common/checkbox_white_checked.png
+++ b/chrome/browser/resources/file_manager/images/common/checkbox_white_checked.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/common/close_x_gray.png b/chrome/browser/resources/file_manager/images/common/close_x_gray.png
index 4a95e5a..3ee375a 100644
--- a/chrome/browser/resources/file_manager/images/common/close_x_gray.png
+++ b/chrome/browser/resources/file_manager/images/common/close_x_gray.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/archive.png b/chrome/browser/resources/file_manager/images/files/file_types/100/archive.png
new file mode 100644
index 0000000..2a054b3
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/archive.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/archive_white.png b/chrome/browser/resources/file_manager/images/files/file_types/100/archive_white.png
new file mode 100644
index 0000000..94ffaf0
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/archive_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/audio.png b/chrome/browser/resources/file_manager/images/files/file_types/100/audio.png
new file mode 100644
index 0000000..a5b4ac9
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/audio.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/audio_white.png b/chrome/browser/resources/file_manager/images/files/file_types/100/audio_white.png
new file mode 100644
index 0000000..819e406
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/audio_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/chart.png b/chrome/browser/resources/file_manager/images/files/file_types/100/chart.png
new file mode 100644
index 0000000..4f7bfa1
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/chart.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/chart_white.png b/chrome/browser/resources/file_manager/images/files/file_types/100/chart_white.png
new file mode 100644
index 0000000..7500f3f
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/chart_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/excel.png b/chrome/browser/resources/file_manager/images/files/file_types/100/excel.png
new file mode 100644
index 0000000..cb27f5c
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/excel.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/excel_white.png b/chrome/browser/resources/file_manager/images/files/file_types/100/excel_white.png
new file mode 100644
index 0000000..0900b09
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/excel_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/folder.png b/chrome/browser/resources/file_manager/images/files/file_types/100/folder.png
new file mode 100644
index 0000000..3f6e17f
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/folder.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/folder_white.png b/chrome/browser/resources/file_manager/images/files/file_types/100/folder_white.png
new file mode 100644
index 0000000..9a56eb9
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/folder_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/form.png b/chrome/browser/resources/file_manager/images/files/file_types/100/form.png
new file mode 100644
index 0000000..c3d2087
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/form.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/form_white.png b/chrome/browser/resources/file_manager/images/files/file_types/100/form_white.png
new file mode 100644
index 0000000..21c18ad
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/form_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/gdoc.png b/chrome/browser/resources/file_manager/images/files/file_types/100/gdoc.png
new file mode 100644
index 0000000..102f1c0
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/gdoc.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/gdoc_white.png b/chrome/browser/resources/file_manager/images/files/file_types/100/gdoc_white.png
new file mode 100644
index 0000000..a66a338
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/gdoc_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/gdraw.png b/chrome/browser/resources/file_manager/images/files/file_types/100/gdraw.png
new file mode 100644
index 0000000..b112041
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/gdraw.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/gdraw_white.png b/chrome/browser/resources/file_manager/images/files/file_types/100/gdraw_white.png
new file mode 100644
index 0000000..f92f18b
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/gdraw_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/generic.png b/chrome/browser/resources/file_manager/images/files/file_types/100/generic.png
new file mode 100644
index 0000000..bff3cda
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/generic.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/generic_white.png b/chrome/browser/resources/file_manager/images/files/file_types/100/generic_white.png
new file mode 100644
index 0000000..a369f66
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/generic_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/glink.png b/chrome/browser/resources/file_manager/images/files/file_types/100/glink.png
new file mode 100644
index 0000000..bff3cda
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/glink.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/glink_white.png b/chrome/browser/resources/file_manager/images/files/file_types/100/glink_white.png
new file mode 100644
index 0000000..a369f66
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/glink_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/gsheet.png b/chrome/browser/resources/file_manager/images/files/file_types/100/gsheet.png
new file mode 100644
index 0000000..6fbd46b
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/gsheet.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/gsheet_white.png b/chrome/browser/resources/file_manager/images/files/file_types/100/gsheet_white.png
new file mode 100644
index 0000000..39cf43d
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/gsheet_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/gslides.png b/chrome/browser/resources/file_manager/images/files/file_types/100/gslides.png
new file mode 100644
index 0000000..76523cc
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/gslides.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/gslides_white.png b/chrome/browser/resources/file_manager/images/files/file_types/100/gslides_white.png
new file mode 100644
index 0000000..ea14b91
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/gslides_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/gtable.png b/chrome/browser/resources/file_manager/images/files/file_types/100/gtable.png
new file mode 100644
index 0000000..a78b26e
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/gtable.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/gtable_white.png b/chrome/browser/resources/file_manager/images/files/file_types/100/gtable_white.png
new file mode 100644
index 0000000..f534641
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/gtable_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/image.png b/chrome/browser/resources/file_manager/images/files/file_types/100/image.png
new file mode 100644
index 0000000..9ec2dbd
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/image.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/image_white.png b/chrome/browser/resources/file_manager/images/files/file_types/100/image_white.png
new file mode 100644
index 0000000..739614f
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/image_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/pdf.png b/chrome/browser/resources/file_manager/images/files/file_types/100/pdf.png
new file mode 100644
index 0000000..ec6d679
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/pdf.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/pdf_white.png b/chrome/browser/resources/file_manager/images/files/file_types/100/pdf_white.png
new file mode 100644
index 0000000..0768204
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/pdf_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/ppt.png b/chrome/browser/resources/file_manager/images/files/file_types/100/ppt.png
new file mode 100644
index 0000000..0a83445
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/ppt.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/ppt_white.png b/chrome/browser/resources/file_manager/images/files/file_types/100/ppt_white.png
new file mode 100644
index 0000000..f18491d
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/ppt_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/script.png b/chrome/browser/resources/file_manager/images/files/file_types/100/script.png
new file mode 100644
index 0000000..054f59a
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/script.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/script_white.png b/chrome/browser/resources/file_manager/images/files/file_types/100/script_white.png
new file mode 100644
index 0000000..2760eb8
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/script_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/sites.png b/chrome/browser/resources/file_manager/images/files/file_types/100/sites.png
new file mode 100644
index 0000000..e4e0ffe
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/sites.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/sites_white.png b/chrome/browser/resources/file_manager/images/files/file_types/100/sites_white.png
new file mode 100644
index 0000000..11646f8
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/sites_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/video.png b/chrome/browser/resources/file_manager/images/files/file_types/100/video.png
new file mode 100644
index 0000000..73b70f6
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/video.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/video_white.png b/chrome/browser/resources/file_manager/images/files/file_types/100/video_white.png
new file mode 100644
index 0000000..ac1c080
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/video_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/word.png b/chrome/browser/resources/file_manager/images/files/file_types/100/word.png
new file mode 100644
index 0000000..a2bf315
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/word.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/100/word_white.png b/chrome/browser/resources/file_manager/images/files/file_types/100/word_white.png
new file mode 100644
index 0000000..9bc0f21
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/100/word_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/archive.png b/chrome/browser/resources/file_manager/images/files/file_types/200/archive.png
new file mode 100644
index 0000000..f514181
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/archive.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/archive_white.png b/chrome/browser/resources/file_manager/images/files/file_types/200/archive_white.png
new file mode 100644
index 0000000..6b522cf
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/archive_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/audio.png b/chrome/browser/resources/file_manager/images/files/file_types/200/audio.png
new file mode 100644
index 0000000..ad2f540
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/audio.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/audio_white.png b/chrome/browser/resources/file_manager/images/files/file_types/200/audio_white.png
new file mode 100644
index 0000000..997d610
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/audio_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/chart.png b/chrome/browser/resources/file_manager/images/files/file_types/200/chart.png
new file mode 100644
index 0000000..5b03c36
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/chart.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/chart_white.png b/chrome/browser/resources/file_manager/images/files/file_types/200/chart_white.png
new file mode 100644
index 0000000..16a75ee
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/chart_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/excel.png b/chrome/browser/resources/file_manager/images/files/file_types/200/excel.png
new file mode 100644
index 0000000..22a4eb5
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/excel.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/excel_white.png b/chrome/browser/resources/file_manager/images/files/file_types/200/excel_white.png
new file mode 100644
index 0000000..bf0a61c
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/excel_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/folder.png b/chrome/browser/resources/file_manager/images/files/file_types/200/folder.png
new file mode 100644
index 0000000..782227f
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/folder.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/folder_white.png b/chrome/browser/resources/file_manager/images/files/file_types/200/folder_white.png
new file mode 100644
index 0000000..9124621
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/folder_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/form.png b/chrome/browser/resources/file_manager/images/files/file_types/200/form.png
new file mode 100644
index 0000000..7908b55
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/form.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/form_white.png b/chrome/browser/resources/file_manager/images/files/file_types/200/form_white.png
new file mode 100644
index 0000000..540fdc2
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/form_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/gdoc.png b/chrome/browser/resources/file_manager/images/files/file_types/200/gdoc.png
new file mode 100644
index 0000000..80ae026
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/gdoc.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/gdoc_white.png b/chrome/browser/resources/file_manager/images/files/file_types/200/gdoc_white.png
new file mode 100644
index 0000000..366180c
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/gdoc_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/gdraw.png b/chrome/browser/resources/file_manager/images/files/file_types/200/gdraw.png
new file mode 100644
index 0000000..c36fca6
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/gdraw.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/gdraw_white.png b/chrome/browser/resources/file_manager/images/files/file_types/200/gdraw_white.png
new file mode 100644
index 0000000..98401d9
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/gdraw_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/generic.png b/chrome/browser/resources/file_manager/images/files/file_types/200/generic.png
new file mode 100644
index 0000000..8df85a3
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/generic.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/generic_white.png b/chrome/browser/resources/file_manager/images/files/file_types/200/generic_white.png
new file mode 100644
index 0000000..9b9b295
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/generic_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/glink.png b/chrome/browser/resources/file_manager/images/files/file_types/200/glink.png
new file mode 100644
index 0000000..8df85a3
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/glink.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/glink_white.png b/chrome/browser/resources/file_manager/images/files/file_types/200/glink_white.png
new file mode 100644
index 0000000..d9a2070
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/glink_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/gsheet.png b/chrome/browser/resources/file_manager/images/files/file_types/200/gsheet.png
new file mode 100644
index 0000000..0545e69
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/gsheet.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/gsheet_white.png b/chrome/browser/resources/file_manager/images/files/file_types/200/gsheet_white.png
new file mode 100644
index 0000000..801de01
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/gsheet_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/gslides.png b/chrome/browser/resources/file_manager/images/files/file_types/200/gslides.png
new file mode 100644
index 0000000..207b0f2
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/gslides.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/gslides_white.png b/chrome/browser/resources/file_manager/images/files/file_types/200/gslides_white.png
new file mode 100644
index 0000000..b6c24ab
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/gslides_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/gtable.png b/chrome/browser/resources/file_manager/images/files/file_types/200/gtable.png
new file mode 100644
index 0000000..fec2061
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/gtable.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/gtable_white.png b/chrome/browser/resources/file_manager/images/files/file_types/200/gtable_white.png
new file mode 100644
index 0000000..8c695c5
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/gtable_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/image.png b/chrome/browser/resources/file_manager/images/files/file_types/200/image.png
new file mode 100644
index 0000000..df61101
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/image.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/image_white.png b/chrome/browser/resources/file_manager/images/files/file_types/200/image_white.png
new file mode 100644
index 0000000..46017e6
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/image_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/pdf.png b/chrome/browser/resources/file_manager/images/files/file_types/200/pdf.png
new file mode 100644
index 0000000..0f62d9e
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/pdf.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/pdf_white.png b/chrome/browser/resources/file_manager/images/files/file_types/200/pdf_white.png
new file mode 100644
index 0000000..e53bda7
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/pdf_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/ppt.png b/chrome/browser/resources/file_manager/images/files/file_types/200/ppt.png
new file mode 100644
index 0000000..31fcd8f
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/ppt.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/ppt_white.png b/chrome/browser/resources/file_manager/images/files/file_types/200/ppt_white.png
new file mode 100644
index 0000000..9824222
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/ppt_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/script.png b/chrome/browser/resources/file_manager/images/files/file_types/200/script.png
new file mode 100644
index 0000000..01a2a1a
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/script.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/script_white.png b/chrome/browser/resources/file_manager/images/files/file_types/200/script_white.png
new file mode 100644
index 0000000..b04a210
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/script_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/sites.png b/chrome/browser/resources/file_manager/images/files/file_types/200/sites.png
new file mode 100644
index 0000000..541c328
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/sites.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/sites_white.png b/chrome/browser/resources/file_manager/images/files/file_types/200/sites_white.png
new file mode 100644
index 0000000..613e517
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/sites_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/video.png b/chrome/browser/resources/file_manager/images/files/file_types/200/video.png
new file mode 100644
index 0000000..a8346a3
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/video.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/video_white.png b/chrome/browser/resources/file_manager/images/files/file_types/200/video_white.png
new file mode 100644
index 0000000..3cbcdba
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/video_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/word.png b/chrome/browser/resources/file_manager/images/files/file_types/200/word.png
new file mode 100644
index 0000000..23b78f6
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/word.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/file_types/200/word_white.png b/chrome/browser/resources/file_manager/images/files/file_types/200/word_white.png
new file mode 100644
index 0000000..424ea80
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/file_types/200/word_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/2x/black_folder.png b/chrome/browser/resources/file_manager/images/files/ui/2x/black_folder.png
new file mode 100644
index 0000000..febe300
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/ui/2x/black_folder.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/2x/breadcrumb-separator.png b/chrome/browser/resources/file_manager/images/files/ui/2x/breadcrumb-separator.png
index 4d7fe00..dce1f1a 100644
--- a/chrome/browser/resources/file_manager/images/files/ui/2x/breadcrumb-separator.png
+++ b/chrome/browser/resources/file_manager/images/files/ui/2x/breadcrumb-separator.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/2x/button_list_view.png b/chrome/browser/resources/file_manager/images/files/ui/2x/button_list_view.png
new file mode 100644
index 0000000..09aa2fd
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/ui/2x/button_list_view.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/2x/button_list_view_white.png b/chrome/browser/resources/file_manager/images/files/ui/2x/button_list_view_white.png
new file mode 100644
index 0000000..f89199a
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/ui/2x/button_list_view_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/2x/button_mosaic_view.png b/chrome/browser/resources/file_manager/images/files/ui/2x/button_mosaic_view.png
new file mode 100644
index 0000000..1961e46
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/ui/2x/button_mosaic_view.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/2x/button_mosaic_view_white.png b/chrome/browser/resources/file_manager/images/files/ui/2x/button_mosaic_view_white.png
new file mode 100644
index 0000000..ad6f856
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/ui/2x/button_mosaic_view_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/2x/close_bar.png b/chrome/browser/resources/file_manager/images/files/ui/2x/close_bar.png
index 98ae94c..3f9e452 100644
--- a/chrome/browser/resources/file_manager/images/files/ui/2x/close_bar.png
+++ b/chrome/browser/resources/file_manager/images/files/ui/2x/close_bar.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/2x/disclosure_arrow_dk_grey.png b/chrome/browser/resources/file_manager/images/files/ui/2x/disclosure_arrow_dk_grey.png
deleted file mode 100644
index 93c5a31..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/2x/disclosure_arrow_dk_grey.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/2x/disclosure_arrow_dk_grey_down.png b/chrome/browser/resources/file_manager/images/files/ui/2x/disclosure_arrow_dk_grey_down.png
deleted file mode 100644
index 55a5f96..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/2x/disclosure_arrow_dk_grey_down.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/2x/drive_logo.png b/chrome/browser/resources/file_manager/images/files/ui/2x/drive_logo.png
index 6b7ec74..316e8a0 100644
--- a/chrome/browser/resources/file_manager/images/files/ui/2x/drive_logo.png
+++ b/chrome/browser/resources/file_manager/images/files/ui/2x/drive_logo.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/2x/eject.png b/chrome/browser/resources/file_manager/images/files/ui/2x/eject.png
index d9274a2..f764c0c 100644
--- a/chrome/browser/resources/file_manager/images/files/ui/2x/eject.png
+++ b/chrome/browser/resources/file_manager/images/files/ui/2x/eject.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/2x/icon_search.png b/chrome/browser/resources/file_manager/images/files/ui/2x/icon_search.png
index cc95446..99e1053 100644
--- a/chrome/browser/resources/file_manager/images/files/ui/2x/icon_search.png
+++ b/chrome/browser/resources/file_manager/images/files/ui/2x/icon_search.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/2x/offline.png b/chrome/browser/resources/file_manager/images/files/ui/2x/offline.png
index 5f97295..6fe2d25 100644
--- a/chrome/browser/resources/file_manager/images/files/ui/2x/offline.png
+++ b/chrome/browser/resources/file_manager/images/files/ui/2x/offline.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/2x/onbutton_trash.png b/chrome/browser/resources/file_manager/images/files/ui/2x/onbutton_trash.png
new file mode 100644
index 0000000..593f53f
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/ui/2x/onbutton_trash.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/2x/pin.png b/chrome/browser/resources/file_manager/images/files/ui/2x/pin.png
deleted file mode 100644
index e2fc20d..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/2x/pin.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/2x/recent.png b/chrome/browser/resources/file_manager/images/files/ui/2x/recent.png
deleted file mode 100644
index 3dab9f5..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/2x/recent.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/2x/search_clear.png b/chrome/browser/resources/file_manager/images/files/ui/2x/search_clear.png
index 1818bb2..a76574a 100644
--- a/chrome/browser/resources/file_manager/images/files/ui/2x/search_clear.png
+++ b/chrome/browser/resources/file_manager/images/files/ui/2x/search_clear.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/2x/search_clear_hover.png b/chrome/browser/resources/file_manager/images/files/ui/2x/search_clear_hover.png
index 04624df..ed7155a 100644
--- a/chrome/browser/resources/file_manager/images/files/ui/2x/search_clear_hover.png
+++ b/chrome/browser/resources/file_manager/images/files/ui/2x/search_clear_hover.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/2x/search_clear_pressed.png b/chrome/browser/resources/file_manager/images/files/ui/2x/search_clear_pressed.png
index 4d0b267..2237a08 100644
--- a/chrome/browser/resources/file_manager/images/files/ui/2x/search_clear_pressed.png
+++ b/chrome/browser/resources/file_manager/images/files/ui/2x/search_clear_pressed.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/2x/search_icon_active.png b/chrome/browser/resources/file_manager/images/files/ui/2x/search_icon_active.png
new file mode 100644
index 0000000..80d733b
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/ui/2x/search_icon_active.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/2x/search_icon_inactive.png b/chrome/browser/resources/file_manager/images/files/ui/2x/search_icon_inactive.png
new file mode 100644
index 0000000..d9e9064
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/ui/2x/search_icon_inactive.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/2x/select_checkbox.png b/chrome/browser/resources/file_manager/images/files/ui/2x/select_checkbox.png
new file mode 100644
index 0000000..e85e010
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/ui/2x/select_checkbox.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/2x/select_checkbox_checked.png b/chrome/browser/resources/file_manager/images/files/ui/2x/select_checkbox_checked.png
new file mode 100644
index 0000000..e879248
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/ui/2x/select_checkbox_checked.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/2x/shared.png b/chrome/browser/resources/file_manager/images/files/ui/2x/shared.png
deleted file mode 100644
index ed4c204..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/2x/shared.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/2x/sort_asc.png b/chrome/browser/resources/file_manager/images/files/ui/2x/sort_asc.png
index e70f0ba..419b29e 100644
--- a/chrome/browser/resources/file_manager/images/files/ui/2x/sort_asc.png
+++ b/chrome/browser/resources/file_manager/images/files/ui/2x/sort_asc.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/2x/sort_desc.png b/chrome/browser/resources/file_manager/images/files/ui/2x/sort_desc.png
index 51b2b49..a0bfe7a 100644
--- a/chrome/browser/resources/file_manager/images/files/ui/2x/sort_desc.png
+++ b/chrome/browser/resources/file_manager/images/files/ui/2x/sort_desc.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/2x/topbar_button_close.png b/chrome/browser/resources/file_manager/images/files/ui/2x/topbar_button_close.png
new file mode 100644
index 0000000..7a28084
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/ui/2x/topbar_button_close.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/2x/topbar_button_maximize.png b/chrome/browser/resources/file_manager/images/files/ui/2x/topbar_button_maximize.png
new file mode 100644
index 0000000..59377a4
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/ui/2x/topbar_button_maximize.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/2x/topbar_button_settings.png b/chrome/browser/resources/file_manager/images/files/ui/2x/topbar_button_settings.png
new file mode 100644
index 0000000..b474c4c
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/ui/2x/topbar_button_settings.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/vertical_separator.png b/chrome/browser/resources/file_manager/images/files/ui/2x/vertical_separator.png
similarity index 100%
rename from chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/vertical_separator.png
rename to chrome/browser/resources/file_manager/images/files/ui/2x/vertical_separator.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/2x/view_list_black.png b/chrome/browser/resources/file_manager/images/files/ui/2x/view_list_black.png
deleted file mode 100644
index 63daca8..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/2x/view_list_black.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/2x/view_thumbs_black.png b/chrome/browser/resources/file_manager/images/files/ui/2x/view_thumbs_black.png
deleted file mode 100644
index a92e47d..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/2x/view_thumbs_black.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/2x/warning_icon_square.png b/chrome/browser/resources/file_manager/images/files/ui/2x/warning_icon_square.png
index d151661..52a8b5a 100644
--- a/chrome/browser/resources/file_manager/images/files/ui/2x/warning_icon_square.png
+++ b/chrome/browser/resources/file_manager/images/files/ui/2x/warning_icon_square.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/2x/white_folder.png b/chrome/browser/resources/file_manager/images/files/ui/2x/white_folder.png
new file mode 100644
index 0000000..9124621
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/ui/2x/white_folder.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/black_folder.png b/chrome/browser/resources/file_manager/images/files/ui/black_folder.png
new file mode 100644
index 0000000..539f677
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/ui/black_folder.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/breadcrumb-separator.png b/chrome/browser/resources/file_manager/images/files/ui/breadcrumb-separator.png
index e7ed818..ed94127 100644
--- a/chrome/browser/resources/file_manager/images/files/ui/breadcrumb-separator.png
+++ b/chrome/browser/resources/file_manager/images/files/ui/breadcrumb-separator.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/new-ui/button_list_view.png b/chrome/browser/resources/file_manager/images/files/ui/button_list_view.png
similarity index 100%
rename from chrome/browser/resources/file_manager/images/files/ui/new-ui/button_list_view.png
rename to chrome/browser/resources/file_manager/images/files/ui/button_list_view.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/button_list_view_white.png b/chrome/browser/resources/file_manager/images/files/ui/button_list_view_white.png
new file mode 100644
index 0000000..798df51
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/ui/button_list_view_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/new-ui/button_mosaic_view.png b/chrome/browser/resources/file_manager/images/files/ui/button_mosaic_view.png
similarity index 100%
rename from chrome/browser/resources/file_manager/images/files/ui/new-ui/button_mosaic_view.png
rename to chrome/browser/resources/file_manager/images/files/ui/button_mosaic_view.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/button_mosaic_view_white.png b/chrome/browser/resources/file_manager/images/files/ui/button_mosaic_view_white.png
new file mode 100644
index 0000000..9d4d518
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/ui/button_mosaic_view_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/close_bar.png b/chrome/browser/resources/file_manager/images/files/ui/close_bar.png
index 69c9017..f723201 100644
--- a/chrome/browser/resources/file_manager/images/files/ui/close_bar.png
+++ b/chrome/browser/resources/file_manager/images/files/ui/close_bar.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/disclosure_arrow_dk_grey.png b/chrome/browser/resources/file_manager/images/files/ui/disclosure_arrow_dk_grey.png
deleted file mode 100644
index dd2f925..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/disclosure_arrow_dk_grey.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/disclosure_arrow_dk_grey_down.png b/chrome/browser/resources/file_manager/images/files/ui/disclosure_arrow_dk_grey_down.png
deleted file mode 100644
index b1ceb84..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/disclosure_arrow_dk_grey_down.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/eject.png b/chrome/browser/resources/file_manager/images/files/ui/eject.png
index 731ccdf..dbbdb7f 100644
--- a/chrome/browser/resources/file_manager/images/files/ui/eject.png
+++ b/chrome/browser/resources/file_manager/images/files/ui/eject.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/icon_search.png b/chrome/browser/resources/file_manager/images/files/ui/icon_search.png
deleted file mode 100644
index 505347a..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/icon_search.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/black_folder.png b/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/black_folder.png
deleted file mode 100644
index f4f1d59..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/black_folder.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/button_list_view.png b/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/button_list_view.png
deleted file mode 100644
index d2185ce..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/button_list_view.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/button_list_view_white.png b/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/button_list_view_white.png
deleted file mode 100644
index 6f637c4..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/button_list_view_white.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/button_mosaic_view.png b/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/button_mosaic_view.png
deleted file mode 100644
index 86313ae..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/button_mosaic_view.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/button_mosaic_view_white.png b/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/button_mosaic_view_white.png
deleted file mode 100644
index ee31e82..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/button_mosaic_view_white.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/onbutton_trash.png b/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/onbutton_trash.png
deleted file mode 100644
index b295f79..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/onbutton_trash.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/search_clear.png b/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/search_clear.png
deleted file mode 100644
index c42a884..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/search_clear.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/search_clear_hover.png b/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/search_clear_hover.png
deleted file mode 100644
index c7166cb..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/search_clear_hover.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/search_clear_pressed.png b/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/search_clear_pressed.png
deleted file mode 100644
index d151fbf..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/search_clear_pressed.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/search_icon_active.png b/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/search_icon_active.png
deleted file mode 100644
index 9791fe6..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/search_icon_active.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/search_icon_inactive.png b/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/search_icon_inactive.png
deleted file mode 100644
index 930ef89..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/search_icon_inactive.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/select_checkbox.png b/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/select_checkbox.png
deleted file mode 100644
index 6504fc1..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/select_checkbox.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/select_checkbox_checked.png b/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/select_checkbox_checked.png
deleted file mode 100644
index e4e477e..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/select_checkbox_checked.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/topbar_button_close.png b/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/topbar_button_close.png
deleted file mode 100644
index 16a0915..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/topbar_button_close.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/topbar_button_maximize.png b/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/topbar_button_maximize.png
deleted file mode 100644
index 4571d62..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/topbar_button_maximize.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/topbar_button_settings.png b/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/topbar_button_settings.png
deleted file mode 100644
index 1905b51..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/topbar_button_settings.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/white_folder.png b/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/white_folder.png
deleted file mode 100644
index 6c16ad9..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/new-ui/2x/white_folder.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/new-ui/black_folder.png b/chrome/browser/resources/file_manager/images/files/ui/new-ui/black_folder.png
deleted file mode 100644
index 720e832..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/new-ui/black_folder.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/new-ui/button_list_view_white.png b/chrome/browser/resources/file_manager/images/files/ui/new-ui/button_list_view_white.png
deleted file mode 100644
index 2c5a32c..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/new-ui/button_list_view_white.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/new-ui/button_mosaic_view_white.png b/chrome/browser/resources/file_manager/images/files/ui/new-ui/button_mosaic_view_white.png
deleted file mode 100644
index 5af9a32..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/new-ui/button_mosaic_view_white.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/new-ui/onbutton_trash.png b/chrome/browser/resources/file_manager/images/files/ui/new-ui/onbutton_trash.png
deleted file mode 100644
index d704cb2..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/new-ui/onbutton_trash.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/new-ui/search_clear.png b/chrome/browser/resources/file_manager/images/files/ui/new-ui/search_clear.png
deleted file mode 100644
index 69929d3..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/new-ui/search_clear.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/new-ui/search_clear_hover.png b/chrome/browser/resources/file_manager/images/files/ui/new-ui/search_clear_hover.png
deleted file mode 100644
index 56df4d5..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/new-ui/search_clear_hover.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/new-ui/search_clear_pressed.png b/chrome/browser/resources/file_manager/images/files/ui/new-ui/search_clear_pressed.png
deleted file mode 100644
index 7c726b1..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/new-ui/search_clear_pressed.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/new-ui/search_icon_active.png b/chrome/browser/resources/file_manager/images/files/ui/new-ui/search_icon_active.png
deleted file mode 100644
index a61e72d..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/new-ui/search_icon_active.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/new-ui/search_icon_inactive.png b/chrome/browser/resources/file_manager/images/files/ui/new-ui/search_icon_inactive.png
deleted file mode 100644
index e574e7d..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/new-ui/search_icon_inactive.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/new-ui/topbar_button_close.png b/chrome/browser/resources/file_manager/images/files/ui/new-ui/topbar_button_close.png
deleted file mode 100644
index c38b61c..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/new-ui/topbar_button_close.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/new-ui/topbar_button_maximize.png b/chrome/browser/resources/file_manager/images/files/ui/new-ui/topbar_button_maximize.png
deleted file mode 100644
index f2904ae..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/new-ui/topbar_button_maximize.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/new-ui/topbar_button_settings.png b/chrome/browser/resources/file_manager/images/files/ui/new-ui/topbar_button_settings.png
deleted file mode 100644
index b935d41..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/new-ui/topbar_button_settings.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/new-ui/white_folder.png b/chrome/browser/resources/file_manager/images/files/ui/new-ui/white_folder.png
deleted file mode 100644
index 36df268..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/new-ui/white_folder.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/offline.png b/chrome/browser/resources/file_manager/images/files/ui/offline.png
index 9ebc535..259d3b2 100644
--- a/chrome/browser/resources/file_manager/images/files/ui/offline.png
+++ b/chrome/browser/resources/file_manager/images/files/ui/offline.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/onbutton_trash.png b/chrome/browser/resources/file_manager/images/files/ui/onbutton_trash.png
new file mode 100644
index 0000000..20ab756
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/ui/onbutton_trash.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/pin.png b/chrome/browser/resources/file_manager/images/files/ui/pin.png
deleted file mode 100644
index 38f23cb..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/pin.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/recent.png b/chrome/browser/resources/file_manager/images/files/ui/recent.png
deleted file mode 100644
index 7f30cfa..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/recent.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/search_clear.png b/chrome/browser/resources/file_manager/images/files/ui/search_clear.png
index 912df05..6755c4e 100644
--- a/chrome/browser/resources/file_manager/images/files/ui/search_clear.png
+++ b/chrome/browser/resources/file_manager/images/files/ui/search_clear.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/search_clear_hover.png b/chrome/browser/resources/file_manager/images/files/ui/search_clear_hover.png
index c5e1481..bbfd15f 100644
--- a/chrome/browser/resources/file_manager/images/files/ui/search_clear_hover.png
+++ b/chrome/browser/resources/file_manager/images/files/ui/search_clear_hover.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/search_clear_pressed.png b/chrome/browser/resources/file_manager/images/files/ui/search_clear_pressed.png
index cc5bbbe..85f8c11 100644
--- a/chrome/browser/resources/file_manager/images/files/ui/search_clear_pressed.png
+++ b/chrome/browser/resources/file_manager/images/files/ui/search_clear_pressed.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/search_icon_active.png b/chrome/browser/resources/file_manager/images/files/ui/search_icon_active.png
new file mode 100644
index 0000000..f59dfe3
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/ui/search_icon_active.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/search_icon_inactive.png b/chrome/browser/resources/file_manager/images/files/ui/search_icon_inactive.png
new file mode 100644
index 0000000..2f17e7c
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/ui/search_icon_inactive.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/new-ui/select_checkbox.png b/chrome/browser/resources/file_manager/images/files/ui/select_checkbox.png
similarity index 100%
rename from chrome/browser/resources/file_manager/images/files/ui/new-ui/select_checkbox.png
rename to chrome/browser/resources/file_manager/images/files/ui/select_checkbox.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/new-ui/select_checkbox_checked.png b/chrome/browser/resources/file_manager/images/files/ui/select_checkbox_checked.png
similarity index 100%
rename from chrome/browser/resources/file_manager/images/files/ui/new-ui/select_checkbox_checked.png
rename to chrome/browser/resources/file_manager/images/files/ui/select_checkbox_checked.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/settings.svg b/chrome/browser/resources/file_manager/images/files/ui/settings.svg
deleted file mode 100644
index 5e719db..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/settings.svg
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In  -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
-	<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
-]>
-<svg version="1.1"
-	 xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
-	 x="0px" y="0px" width="21px" height="21px" viewBox="0 0 21 21" overflow="visible" enable-background="new 0 0 21 21"
-	 xml:space="preserve">
-<defs>
-</defs>
-<path d="M16.895,11.64C16.96,11.269,17,10.89,17,10.5s-0.04-0.77-0.106-1.14l1.535-1.129l0.183-0.683l-1.5-2.598l-0.684-0.184
-	l-1.738,0.762c-0.581-0.49-1.25-0.875-1.979-1.138L12.5,2.5L12,2H9L8.5,2.499L8.29,4.395C7.562,4.658,6.896,5.043,6.314,5.531
-	L4.571,4.768L3.889,4.951l-1.5,2.598l0.183,0.684l1.535,1.129C4.04,9.731,4,10.111,4,10.5s0.04,0.769,0.106,1.139l-1.535,1.129
-	l-0.183,0.684l1.5,2.598l0.682,0.184l1.744-0.764c0.58,0.488,1.248,0.873,1.975,1.137l0.21,1.896L9,19h3l0.5-0.5l0.21-1.892
-	c0.729-0.263,1.398-0.648,1.979-1.138l1.738,0.762l0.684-0.184l1.499-2.598l-0.181-0.683L16.895,11.64z M14.15,10.5
-	c0,2.016-1.635,3.65-3.65,3.65c-2.016,0-3.65-1.635-3.65-3.65s1.635-3.65,3.65-3.65C12.515,6.85,14.15,8.484,14.15,10.5z"/>
-<rect opacity="0" fill="#4387FD" width="21" height="21"/>
-</svg>
diff --git a/chrome/browser/resources/file_manager/images/files/ui/shared.png b/chrome/browser/resources/file_manager/images/files/ui/shared.png
deleted file mode 100644
index 2c0e161..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/shared.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/topbar_button_close.png b/chrome/browser/resources/file_manager/images/files/ui/topbar_button_close.png
new file mode 100644
index 0000000..b902560
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/ui/topbar_button_close.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/topbar_button_maximize.png b/chrome/browser/resources/file_manager/images/files/ui/topbar_button_maximize.png
new file mode 100644
index 0000000..3bd557f
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/ui/topbar_button_maximize.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/topbar_button_settings.png b/chrome/browser/resources/file_manager/images/files/ui/topbar_button_settings.png
new file mode 100644
index 0000000..ef0724a
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/ui/topbar_button_settings.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/new-ui/vertical_separator.png b/chrome/browser/resources/file_manager/images/files/ui/vertical_separator.png
similarity index 100%
rename from chrome/browser/resources/file_manager/images/files/ui/new-ui/vertical_separator.png
rename to chrome/browser/resources/file_manager/images/files/ui/vertical_separator.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/view_list_black.png b/chrome/browser/resources/file_manager/images/files/ui/view_list_black.png
deleted file mode 100644
index b350ef1..0000000
--- a/chrome/browser/resources/file_manager/images/files/ui/view_list_black.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/warning_icon_square.png b/chrome/browser/resources/file_manager/images/files/ui/warning_icon_square.png
index d324919..90d6b60 100644
--- a/chrome/browser/resources/file_manager/images/files/ui/warning_icon_square.png
+++ b/chrome/browser/resources/file_manager/images/files/ui/warning_icon_square.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/ui/white_folder.png b/chrome/browser/resources/file_manager/images/files/ui/white_folder.png
new file mode 100644
index 0000000..07b6aa2
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/ui/white_folder.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/2x/archive.png b/chrome/browser/resources/file_manager/images/files/volumes/2x/archive.png
index 681b6a6..b5821d4 100644
--- a/chrome/browser/resources/file_manager/images/files/volumes/2x/archive.png
+++ b/chrome/browser/resources/file_manager/images/files/volumes/2x/archive.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/2x/black_archive.png b/chrome/browser/resources/file_manager/images/files/volumes/2x/black_archive.png
new file mode 100644
index 0000000..6927bdd
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/2x/black_archive.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/2x/black_downloads.png b/chrome/browser/resources/file_manager/images/files/volumes/2x/black_downloads.png
new file mode 100644
index 0000000..ab37f07
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/2x/black_downloads.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/2x/black_drive.png b/chrome/browser/resources/file_manager/images/files/volumes/2x/black_drive.png
new file mode 100644
index 0000000..a17a0b1
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/2x/black_drive.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/2x/black_hdd.png b/chrome/browser/resources/file_manager/images/files/volumes/2x/black_hdd.png
new file mode 100644
index 0000000..e0ec696
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/2x/black_hdd.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/2x/black_offline.png b/chrome/browser/resources/file_manager/images/files/volumes/2x/black_offline.png
new file mode 100644
index 0000000..87029a9
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/2x/black_offline.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/2x/black_optical.png b/chrome/browser/resources/file_manager/images/files/volumes/2x/black_optical.png
new file mode 100644
index 0000000..5077474
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/2x/black_optical.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/2x/black_phone.png b/chrome/browser/resources/file_manager/images/files/volumes/2x/black_phone.png
new file mode 100644
index 0000000..c4521de
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/2x/black_phone.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/2x/black_recent.png b/chrome/browser/resources/file_manager/images/files/volumes/2x/black_recent.png
new file mode 100644
index 0000000..e1b8621
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/2x/black_recent.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/2x/black_sd.png b/chrome/browser/resources/file_manager/images/files/volumes/2x/black_sd.png
new file mode 100644
index 0000000..5679089
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/2x/black_sd.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/2x/black_shared.png b/chrome/browser/resources/file_manager/images/files/volumes/2x/black_shared.png
new file mode 100644
index 0000000..79b9edc
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/2x/black_shared.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/2x/black_trash.png b/chrome/browser/resources/file_manager/images/files/volumes/2x/black_trash.png
new file mode 100644
index 0000000..67f261f
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/2x/black_trash.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/2x/black_usb.png b/chrome/browser/resources/file_manager/images/files/volumes/2x/black_usb.png
new file mode 100644
index 0000000..2cceca6
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/2x/black_usb.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/2x/device_hd.png b/chrome/browser/resources/file_manager/images/files/volumes/2x/device_hd.png
index 6d9dac8..e0ec696 100644
--- a/chrome/browser/resources/file_manager/images/files/volumes/2x/device_hd.png
+++ b/chrome/browser/resources/file_manager/images/files/volumes/2x/device_hd.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/2x/device_optical.png b/chrome/browser/resources/file_manager/images/files/volumes/2x/device_optical.png
index 56b9aa0..5077474 100644
--- a/chrome/browser/resources/file_manager/images/files/volumes/2x/device_optical.png
+++ b/chrome/browser/resources/file_manager/images/files/volumes/2x/device_optical.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/2x/device_sd.png b/chrome/browser/resources/file_manager/images/files/volumes/2x/device_sd.png
index 1b1e941..5679089 100644
--- a/chrome/browser/resources/file_manager/images/files/volumes/2x/device_sd.png
+++ b/chrome/browser/resources/file_manager/images/files/volumes/2x/device_sd.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/2x/device_sd_large.png b/chrome/browser/resources/file_manager/images/files/volumes/2x/device_sd_large.png
index ec69757..6fa0c75 100644
--- a/chrome/browser/resources/file_manager/images/files/volumes/2x/device_sd_large.png
+++ b/chrome/browser/resources/file_manager/images/files/volumes/2x/device_sd_large.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/2x/device_usb.png b/chrome/browser/resources/file_manager/images/files/volumes/2x/device_usb.png
index c3e9921..70e9686 100644
--- a/chrome/browser/resources/file_manager/images/files/volumes/2x/device_usb.png
+++ b/chrome/browser/resources/file_manager/images/files/volumes/2x/device_usb.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/2x/device_usb_large.png b/chrome/browser/resources/file_manager/images/files/volumes/2x/device_usb_large.png
index 4133faf..17a8fee 100644
--- a/chrome/browser/resources/file_manager/images/files/volumes/2x/device_usb_large.png
+++ b/chrome/browser/resources/file_manager/images/files/volumes/2x/device_usb_large.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/2x/downloads.png b/chrome/browser/resources/file_manager/images/files/volumes/2x/downloads.png
index a3c0390..22e6617 100644
--- a/chrome/browser/resources/file_manager/images/files/volumes/2x/downloads.png
+++ b/chrome/browser/resources/file_manager/images/files/volumes/2x/downloads.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/2x/drive.png b/chrome/browser/resources/file_manager/images/files/volumes/2x/drive.png
index fbf0675..a17a0b1 100644
--- a/chrome/browser/resources/file_manager/images/files/volumes/2x/drive.png
+++ b/chrome/browser/resources/file_manager/images/files/volumes/2x/drive.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/2x/drive_offline.png b/chrome/browser/resources/file_manager/images/files/volumes/2x/drive_offline.png
index 800e21d..7598185 100644
--- a/chrome/browser/resources/file_manager/images/files/volumes/2x/drive_offline.png
+++ b/chrome/browser/resources/file_manager/images/files/volumes/2x/drive_offline.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/2x/drive_recent.png b/chrome/browser/resources/file_manager/images/files/volumes/2x/drive_recent.png
index 3dab9f5..756e36a 100644
--- a/chrome/browser/resources/file_manager/images/files/volumes/2x/drive_recent.png
+++ b/chrome/browser/resources/file_manager/images/files/volumes/2x/drive_recent.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/2x/drive_shared.png b/chrome/browser/resources/file_manager/images/files/volumes/2x/drive_shared.png
index ed4c204..c2eb5da 100644
--- a/chrome/browser/resources/file_manager/images/files/volumes/2x/drive_shared.png
+++ b/chrome/browser/resources/file_manager/images/files/volumes/2x/drive_shared.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/2x/folder.png b/chrome/browser/resources/file_manager/images/files/volumes/2x/folder.png
index f4f1d59..01ac492 100644
--- a/chrome/browser/resources/file_manager/images/files/volumes/2x/folder.png
+++ b/chrome/browser/resources/file_manager/images/files/volumes/2x/folder.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/2x/white_archive.png b/chrome/browser/resources/file_manager/images/files/volumes/2x/white_archive.png
new file mode 100644
index 0000000..481c40b
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/2x/white_archive.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/2x/white_downloads.png b/chrome/browser/resources/file_manager/images/files/volumes/2x/white_downloads.png
new file mode 100644
index 0000000..44a93d5
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/2x/white_downloads.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/2x/white_drive.png b/chrome/browser/resources/file_manager/images/files/volumes/2x/white_drive.png
new file mode 100644
index 0000000..5f43989
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/2x/white_drive.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/2x/white_hdd.png b/chrome/browser/resources/file_manager/images/files/volumes/2x/white_hdd.png
new file mode 100644
index 0000000..bc5e8c4
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/2x/white_hdd.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/2x/white_offline.png b/chrome/browser/resources/file_manager/images/files/volumes/2x/white_offline.png
new file mode 100644
index 0000000..9d65b39
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/2x/white_offline.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/2x/white_optical.png b/chrome/browser/resources/file_manager/images/files/volumes/2x/white_optical.png
new file mode 100644
index 0000000..c675377
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/2x/white_optical.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/2x/white_phone.png b/chrome/browser/resources/file_manager/images/files/volumes/2x/white_phone.png
new file mode 100644
index 0000000..2dfb8f2
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/2x/white_phone.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/2x/white_recent.png b/chrome/browser/resources/file_manager/images/files/volumes/2x/white_recent.png
new file mode 100644
index 0000000..a80eae2
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/2x/white_recent.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/2x/white_sd.png b/chrome/browser/resources/file_manager/images/files/volumes/2x/white_sd.png
new file mode 100644
index 0000000..282de9a
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/2x/white_sd.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/2x/white_shared.png b/chrome/browser/resources/file_manager/images/files/volumes/2x/white_shared.png
new file mode 100644
index 0000000..24ea167
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/2x/white_shared.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/2x/white_trash.png b/chrome/browser/resources/file_manager/images/files/volumes/2x/white_trash.png
new file mode 100644
index 0000000..f6c5ccb
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/2x/white_trash.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/2x/white_usb.png b/chrome/browser/resources/file_manager/images/files/volumes/2x/white_usb.png
new file mode 100644
index 0000000..f296f4e
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/2x/white_usb.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/archive.png b/chrome/browser/resources/file_manager/images/files/volumes/archive.png
deleted file mode 100644
index 168be60..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/archive.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/black_archive.png b/chrome/browser/resources/file_manager/images/files/volumes/black_archive.png
new file mode 100644
index 0000000..e451420
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/black_archive.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/black_downloads.png b/chrome/browser/resources/file_manager/images/files/volumes/black_downloads.png
new file mode 100644
index 0000000..e25c875
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/black_downloads.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/black_drive.png b/chrome/browser/resources/file_manager/images/files/volumes/black_drive.png
new file mode 100644
index 0000000..891ec48
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/black_drive.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/black_folder.png b/chrome/browser/resources/file_manager/images/files/volumes/black_folder.png
new file mode 100644
index 0000000..539f677
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/black_folder.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/black_hdd.png b/chrome/browser/resources/file_manager/images/files/volumes/black_hdd.png
new file mode 100644
index 0000000..53c02b4
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/black_hdd.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/black_offline.png b/chrome/browser/resources/file_manager/images/files/volumes/black_offline.png
new file mode 100644
index 0000000..a07ef0c
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/black_offline.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/black_optical.png b/chrome/browser/resources/file_manager/images/files/volumes/black_optical.png
new file mode 100644
index 0000000..30a905f
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/black_optical.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/black_phone.png b/chrome/browser/resources/file_manager/images/files/volumes/black_phone.png
new file mode 100644
index 0000000..aa3aa9d
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/black_phone.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/black_recent.png b/chrome/browser/resources/file_manager/images/files/volumes/black_recent.png
new file mode 100644
index 0000000..6e5d363
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/black_recent.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/black_sd.png b/chrome/browser/resources/file_manager/images/files/volumes/black_sd.png
new file mode 100644
index 0000000..f24b4ce
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/black_sd.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/black_shared.png b/chrome/browser/resources/file_manager/images/files/volumes/black_shared.png
new file mode 100644
index 0000000..63a882f
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/black_shared.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/black_trash.png b/chrome/browser/resources/file_manager/images/files/volumes/black_trash.png
new file mode 100644
index 0000000..7708ae5
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/black_trash.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/black_usb.png b/chrome/browser/resources/file_manager/images/files/volumes/black_usb.png
new file mode 100644
index 0000000..ba7ef47
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/black_usb.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/device_hd.png b/chrome/browser/resources/file_manager/images/files/volumes/device_hd.png
deleted file mode 100644
index cd06b99..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/device_hd.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/device_optical.png b/chrome/browser/resources/file_manager/images/files/volumes/device_optical.png
deleted file mode 100644
index 7754c4a..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/device_optical.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/device_sd.png b/chrome/browser/resources/file_manager/images/files/volumes/device_sd.png
deleted file mode 100644
index 05c035b..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/device_sd.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/device_sd_large.png b/chrome/browser/resources/file_manager/images/files/volumes/device_sd_large.png
index 2026d42..39d2fe9 100644
--- a/chrome/browser/resources/file_manager/images/files/volumes/device_sd_large.png
+++ b/chrome/browser/resources/file_manager/images/files/volumes/device_sd_large.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/device_usb.png b/chrome/browser/resources/file_manager/images/files/volumes/device_usb.png
deleted file mode 100644
index 4d6ca21..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/device_usb.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/device_usb_large.png b/chrome/browser/resources/file_manager/images/files/volumes/device_usb_large.png
index e700b9d..6b68508 100644
--- a/chrome/browser/resources/file_manager/images/files/volumes/device_usb_large.png
+++ b/chrome/browser/resources/file_manager/images/files/volumes/device_usb_large.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/downloads.png b/chrome/browser/resources/file_manager/images/files/volumes/downloads.png
deleted file mode 100644
index 49b00a6..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/downloads.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/drive.png b/chrome/browser/resources/file_manager/images/files/volumes/drive.png
deleted file mode 100644
index 6f97e26..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/drive.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/drive_offline.png b/chrome/browser/resources/file_manager/images/files/volumes/drive_offline.png
deleted file mode 100644
index e3f5ded..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/drive_offline.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/drive_recent.png b/chrome/browser/resources/file_manager/images/files/volumes/drive_recent.png
deleted file mode 100644
index 7f30cfa..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/drive_recent.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/drive_shared.png b/chrome/browser/resources/file_manager/images/files/volumes/drive_shared.png
deleted file mode 100644
index 2c0e161..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/drive_shared.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/folder.png b/chrome/browser/resources/file_manager/images/files/volumes/folder.png
deleted file mode 100644
index 720e832..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/folder.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/black_archive.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/black_archive.png
deleted file mode 100644
index 681b6a6..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/black_archive.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/black_downloads.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/black_downloads.png
deleted file mode 100644
index a3c0390..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/black_downloads.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/black_drive.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/black_drive.png
deleted file mode 100644
index fbf0675..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/black_drive.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/black_hdd.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/black_hdd.png
deleted file mode 100644
index 6d9dac8..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/black_hdd.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/black_offline.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/black_offline.png
deleted file mode 100644
index 9a49109..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/black_offline.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/black_optical.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/black_optical.png
deleted file mode 100644
index 56b9aa0..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/black_optical.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/black_phone.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/black_phone.png
deleted file mode 100644
index 4305569..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/black_phone.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/black_recent.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/black_recent.png
deleted file mode 100644
index 3dab9f5..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/black_recent.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/black_sd.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/black_sd.png
deleted file mode 100644
index 1b1e941..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/black_sd.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/black_shared.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/black_shared.png
deleted file mode 100644
index eacc3c3..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/black_shared.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/black_trash.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/black_trash.png
deleted file mode 100644
index ea0edd2..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/black_trash.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/black_usb.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/black_usb.png
deleted file mode 100644
index c3e9921..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/black_usb.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/white_archive.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/white_archive.png
deleted file mode 100644
index ebbde23..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/white_archive.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/white_downloads.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/white_downloads.png
deleted file mode 100644
index 5adea77..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/white_downloads.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/white_drive.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/white_drive.png
deleted file mode 100644
index 3037bf6..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/white_drive.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/white_hdd.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/white_hdd.png
deleted file mode 100644
index 1f79d83..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/white_hdd.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/white_offline.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/white_offline.png
deleted file mode 100644
index 64b1bf0..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/white_offline.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/white_optical.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/white_optical.png
deleted file mode 100644
index 71835a8..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/white_optical.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/white_phone.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/white_phone.png
deleted file mode 100644
index e9a671e..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/white_phone.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/white_recent.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/white_recent.png
deleted file mode 100644
index 085129b..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/white_recent.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/white_sd.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/white_sd.png
deleted file mode 100644
index a464785..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/white_sd.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/white_shared.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/white_shared.png
deleted file mode 100644
index 83a97d9..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/white_shared.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/white_trash.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/white_trash.png
deleted file mode 100644
index d84d457..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/white_trash.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/white_usb.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/white_usb.png
deleted file mode 100644
index be3d6b6..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/2x/white_usb.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_archive.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_archive.png
deleted file mode 100644
index 168be60..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_archive.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_downloads.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_downloads.png
deleted file mode 100644
index 49b00a6..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_downloads.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_drive.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_drive.png
deleted file mode 100644
index 6f97e26..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_drive.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_folder.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_folder.png
deleted file mode 100644
index 720e832..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_folder.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_hdd.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_hdd.png
deleted file mode 100644
index cd06b99..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_hdd.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_offline.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_offline.png
deleted file mode 100644
index e3f5ded..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_offline.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_optical.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_optical.png
deleted file mode 100644
index 7754c4a..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_optical.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_phone.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_phone.png
deleted file mode 100644
index 879f357..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_phone.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_recent.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_recent.png
deleted file mode 100644
index 7f30cfa..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_recent.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_sd.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_sd.png
deleted file mode 100644
index 05c035b..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_sd.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_shared.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_shared.png
deleted file mode 100644
index 2c0e161..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_shared.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_trash.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_trash.png
deleted file mode 100644
index c8884a2..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_trash.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_usb.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_usb.png
deleted file mode 100644
index 4d6ca21..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/black_usb.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/white_archive.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/white_archive.png
deleted file mode 100644
index d1d5ec5..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/white_archive.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/white_downloads.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/white_downloads.png
deleted file mode 100644
index 425a409..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/white_downloads.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/white_drive.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/white_drive.png
deleted file mode 100644
index 5c82040..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/white_drive.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/white_folder.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/white_folder.png
deleted file mode 100644
index 36df268..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/white_folder.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/white_hdd.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/white_hdd.png
deleted file mode 100644
index ec4e69a..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/white_hdd.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/white_offline.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/white_offline.png
deleted file mode 100644
index 1c6b78e..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/white_offline.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/white_optical.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/white_optical.png
deleted file mode 100644
index 9a634ad..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/white_optical.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/white_recent.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/white_recent.png
deleted file mode 100644
index 389b5dd..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/white_recent.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/white_shared.png b/chrome/browser/resources/file_manager/images/files/volumes/new-ui/white_shared.png
deleted file mode 100644
index 7c6ae4f..0000000
--- a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/white_shared.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/white_archive.png b/chrome/browser/resources/file_manager/images/files/volumes/white_archive.png
new file mode 100644
index 0000000..3b542de
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/white_archive.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/white_downloads.png b/chrome/browser/resources/file_manager/images/files/volumes/white_downloads.png
new file mode 100644
index 0000000..8b1cfdf
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/white_downloads.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/white_drive.png b/chrome/browser/resources/file_manager/images/files/volumes/white_drive.png
new file mode 100644
index 0000000..0226fbd
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/white_drive.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/white_folder.png b/chrome/browser/resources/file_manager/images/files/volumes/white_folder.png
new file mode 100644
index 0000000..07b6aa2
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/white_folder.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/white_hdd.png b/chrome/browser/resources/file_manager/images/files/volumes/white_hdd.png
new file mode 100644
index 0000000..b7c4a48
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/white_hdd.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/white_offline.png b/chrome/browser/resources/file_manager/images/files/volumes/white_offline.png
new file mode 100644
index 0000000..503ed67
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/white_offline.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/white_optical.png b/chrome/browser/resources/file_manager/images/files/volumes/white_optical.png
new file mode 100644
index 0000000..3f13f72
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/white_optical.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/white_phone.png b/chrome/browser/resources/file_manager/images/files/volumes/white_phone.png
similarity index 100%
rename from chrome/browser/resources/file_manager/images/files/volumes/new-ui/white_phone.png
rename to chrome/browser/resources/file_manager/images/files/volumes/white_phone.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/white_recent.png b/chrome/browser/resources/file_manager/images/files/volumes/white_recent.png
new file mode 100644
index 0000000..23c526a
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/white_recent.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/white_sd.png b/chrome/browser/resources/file_manager/images/files/volumes/white_sd.png
similarity index 100%
rename from chrome/browser/resources/file_manager/images/files/volumes/new-ui/white_sd.png
rename to chrome/browser/resources/file_manager/images/files/volumes/white_sd.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/white_shared.png b/chrome/browser/resources/file_manager/images/files/volumes/white_shared.png
new file mode 100644
index 0000000..051191e
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/files/volumes/white_shared.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/white_trash.png b/chrome/browser/resources/file_manager/images/files/volumes/white_trash.png
similarity index 100%
rename from chrome/browser/resources/file_manager/images/files/volumes/new-ui/white_trash.png
rename to chrome/browser/resources/file_manager/images/files/volumes/white_trash.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/files/volumes/new-ui/white_usb.png b/chrome/browser/resources/file_manager/images/files/volumes/white_usb.png
similarity index 100%
rename from chrome/browser/resources/file_manager/images/files/volumes/new-ui/white_usb.png
rename to chrome/browser/resources/file_manager/images/files/volumes/white_usb.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/arrow_left.png b/chrome/browser/resources/file_manager/images/gallery/2x/arrow_left.png
index a53ba28..6e4fb66 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/arrow_left.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/arrow_left.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/arrow_right.png b/chrome/browser/resources/file_manager/images/gallery/2x/arrow_right.png
index cbc2bd1..6b999c1 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/arrow_right.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/arrow_right.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/back_to_files.png b/chrome/browser/resources/file_manager/images/gallery/2x/back_to_files.png
index cba6dec..e04d9d3 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/back_to_files.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/back_to_files.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/bubble_point.png b/chrome/browser/resources/file_manager/images/gallery/2x/bubble_point.png
index 0703116..161e4c0 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/bubble_point.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/bubble_point.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/butterbar_close_button.png b/chrome/browser/resources/file_manager/images/gallery/2x/butterbar_close_button.png
index 4ec0122..aa6c816 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/butterbar_close_button.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/butterbar_close_button.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/cursor_crop.png b/chrome/browser/resources/file_manager/images/gallery/2x/cursor_crop.png
index 60816e9..6490950 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/cursor_crop.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/cursor_crop.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/cursor_leftright.png b/chrome/browser/resources/file_manager/images/gallery/2x/cursor_leftright.png
index 1b7232f..a7ee09c 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/cursor_leftright.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/cursor_leftright.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/cursor_move.png b/chrome/browser/resources/file_manager/images/gallery/2x/cursor_move.png
index 2f93347..faa3c8a 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/cursor_move.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/cursor_move.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/cursor_nwse.png b/chrome/browser/resources/file_manager/images/gallery/2x/cursor_nwse.png
index b34ed28..0cd6399 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/cursor_nwse.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/cursor_nwse.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/cursor_swne.png b/chrome/browser/resources/file_manager/images/gallery/2x/cursor_swne.png
index cc5e2b9..5bdae73 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/cursor_swne.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/cursor_swne.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/cursor_updown.png b/chrome/browser/resources/file_manager/images/gallery/2x/cursor_updown.png
index e20d130..1e9adfb 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/cursor_updown.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/cursor_updown.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/icon_1up.png b/chrome/browser/resources/file_manager/images/gallery/2x/icon_1up.png
index d41c095..58cbc28 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/icon_1up.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/icon_1up.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/icon_1up_selected.png b/chrome/browser/resources/file_manager/images/gallery/2x/icon_1up_selected.png
index 221cc49..a0ca726 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/icon_1up_selected.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/icon_1up_selected.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/icon_autofix.png b/chrome/browser/resources/file_manager/images/gallery/2x/icon_autofix.png
index b1d7f9f..8ce4917 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/icon_autofix.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/icon_autofix.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/icon_autofix_selected.png b/chrome/browser/resources/file_manager/images/gallery/2x/icon_autofix_selected.png
index 400826f..8838d5c 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/icon_autofix_selected.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/icon_autofix_selected.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/icon_brightness.png b/chrome/browser/resources/file_manager/images/gallery/2x/icon_brightness.png
index 65c36c2..ffcd385 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/icon_brightness.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/icon_brightness.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/icon_brightness_selected.png b/chrome/browser/resources/file_manager/images/gallery/2x/icon_brightness_selected.png
index 007809b..90bf03b 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/icon_brightness_selected.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/icon_brightness_selected.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/icon_contrast.png b/chrome/browser/resources/file_manager/images/gallery/2x/icon_contrast.png
index 90aec57..eec931d 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/icon_contrast.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/icon_contrast.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/icon_crop.png b/chrome/browser/resources/file_manager/images/gallery/2x/icon_crop.png
index 1da69fd..7c12fb5 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/icon_crop.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/icon_crop.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/icon_crop_selected.png b/chrome/browser/resources/file_manager/images/gallery/2x/icon_crop_selected.png
index e9eece7..bb2e9e6 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/icon_crop_selected.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/icon_crop_selected.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/icon_delete.png b/chrome/browser/resources/file_manager/images/gallery/2x/icon_delete.png
index 2da2506..a55ac6c 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/icon_delete.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/icon_delete.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/icon_delete_selected.png b/chrome/browser/resources/file_manager/images/gallery/2x/icon_delete_selected.png
index ea00a1b..af54168 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/icon_delete_selected.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/icon_delete_selected.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/icon_edit.png b/chrome/browser/resources/file_manager/images/gallery/2x/icon_edit.png
index 0502a5d..288bc5b 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/icon_edit.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/icon_edit.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/icon_edit_selected.png b/chrome/browser/resources/file_manager/images/gallery/2x/icon_edit_selected.png
index a608823..bcf9933 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/icon_edit_selected.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/icon_edit_selected.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/icon_mosaic.png b/chrome/browser/resources/file_manager/images/gallery/2x/icon_mosaic.png
index eed8a8e..3e1a621 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/icon_mosaic.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/icon_mosaic.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/icon_mosaic_selected.png b/chrome/browser/resources/file_manager/images/gallery/2x/icon_mosaic_selected.png
index 06214f1..d9e329d 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/icon_mosaic_selected.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/icon_mosaic_selected.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/icon_print.png b/chrome/browser/resources/file_manager/images/gallery/2x/icon_print.png
new file mode 100644
index 0000000..95923a9
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/icon_print.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/icon_print_selected.png b/chrome/browser/resources/file_manager/images/gallery/2x/icon_print_selected.png
new file mode 100644
index 0000000..d4ac79f
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/icon_print_selected.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/icon_redo.png b/chrome/browser/resources/file_manager/images/gallery/2x/icon_redo.png
index 911bb2b..075275d 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/icon_redo.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/icon_redo.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/icon_redo_selected.png b/chrome/browser/resources/file_manager/images/gallery/2x/icon_redo_selected.png
index fc8c5cb..beed584 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/icon_redo_selected.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/icon_redo_selected.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/icon_rotate.png b/chrome/browser/resources/file_manager/images/gallery/2x/icon_rotate.png
index eb91968..e7bf684 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/icon_rotate.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/icon_rotate.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/icon_rotate_left.png b/chrome/browser/resources/file_manager/images/gallery/2x/icon_rotate_left.png
index 4ecb97c..4ebbb68 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/icon_rotate_left.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/icon_rotate_left.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/icon_rotate_left_selected.png b/chrome/browser/resources/file_manager/images/gallery/2x/icon_rotate_left_selected.png
index 45ba86f..d1b00a7 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/icon_rotate_left_selected.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/icon_rotate_left_selected.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/icon_rotate_selected.png b/chrome/browser/resources/file_manager/images/gallery/2x/icon_rotate_selected.png
index d60999d..1990a63 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/icon_rotate_selected.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/icon_rotate_selected.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/icon_share.png b/chrome/browser/resources/file_manager/images/gallery/2x/icon_share.png
index c30463e..b1da6d9 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/icon_share.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/icon_share.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/icon_share_selected.png b/chrome/browser/resources/file_manager/images/gallery/2x/icon_share_selected.png
index fee6052..b3cd00f 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/icon_share_selected.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/icon_share_selected.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/icon_slideshow.png b/chrome/browser/resources/file_manager/images/gallery/2x/icon_slideshow.png
index 5b92943..fec87c0 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/icon_slideshow.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/icon_slideshow.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/icon_slideshow_selected.png b/chrome/browser/resources/file_manager/images/gallery/2x/icon_slideshow_selected.png
index b0a20f4..bde2e41 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/icon_slideshow_selected.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/icon_slideshow_selected.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/icon_undo.png b/chrome/browser/resources/file_manager/images/gallery/2x/icon_undo.png
index dde66b1..c51fd62 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/icon_undo.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/icon_undo.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/icon_undo_selected.png b/chrome/browser/resources/file_manager/images/gallery/2x/icon_undo_selected.png
index 4723408..3c838c6 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/icon_undo_selected.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/icon_undo_selected.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/slider_thumb.png b/chrome/browser/resources/file_manager/images/gallery/2x/slider_thumb.png
index 2554aca..e100da6 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/slider_thumb.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/slider_thumb.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/slideshow-end.png b/chrome/browser/resources/file_manager/images/gallery/2x/slideshow-end.png
index a1510da..5e19f8d 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/slideshow-end.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/slideshow-end.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/slideshow-pause.png b/chrome/browser/resources/file_manager/images/gallery/2x/slideshow-pause.png
index 0702bfe..13457d9 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/slideshow-pause.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/slideshow-pause.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/2x/slideshow-play.png b/chrome/browser/resources/file_manager/images/gallery/2x/slideshow-play.png
index 105573e..aa9bd88 100644
--- a/chrome/browser/resources/file_manager/images/gallery/2x/slideshow-play.png
+++ b/chrome/browser/resources/file_manager/images/gallery/2x/slideshow-play.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/arrow_left.png b/chrome/browser/resources/file_manager/images/gallery/arrow_left.png
index 098a286..85e687a 100644
--- a/chrome/browser/resources/file_manager/images/gallery/arrow_left.png
+++ b/chrome/browser/resources/file_manager/images/gallery/arrow_left.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/arrow_right.png b/chrome/browser/resources/file_manager/images/gallery/arrow_right.png
index 9b7076d..0361556 100644
--- a/chrome/browser/resources/file_manager/images/gallery/arrow_right.png
+++ b/chrome/browser/resources/file_manager/images/gallery/arrow_right.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/back_to_files.png b/chrome/browser/resources/file_manager/images/gallery/back_to_files.png
index c2e898b..96e420a 100644
--- a/chrome/browser/resources/file_manager/images/gallery/back_to_files.png
+++ b/chrome/browser/resources/file_manager/images/gallery/back_to_files.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/bubble_point.png b/chrome/browser/resources/file_manager/images/gallery/bubble_point.png
index d38ffcf..494ddb4 100644
--- a/chrome/browser/resources/file_manager/images/gallery/bubble_point.png
+++ b/chrome/browser/resources/file_manager/images/gallery/bubble_point.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/butterbar_close_button.png b/chrome/browser/resources/file_manager/images/gallery/butterbar_close_button.png
index fe93aa6..bc26727 100644
--- a/chrome/browser/resources/file_manager/images/gallery/butterbar_close_button.png
+++ b/chrome/browser/resources/file_manager/images/gallery/butterbar_close_button.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/cursor_crop.png b/chrome/browser/resources/file_manager/images/gallery/cursor_crop.png
index 63472a5..6084188 100644
--- a/chrome/browser/resources/file_manager/images/gallery/cursor_crop.png
+++ b/chrome/browser/resources/file_manager/images/gallery/cursor_crop.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/cursor_leftright.png b/chrome/browser/resources/file_manager/images/gallery/cursor_leftright.png
index 4b6542f..30eeb03 100644
--- a/chrome/browser/resources/file_manager/images/gallery/cursor_leftright.png
+++ b/chrome/browser/resources/file_manager/images/gallery/cursor_leftright.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/cursor_move.png b/chrome/browser/resources/file_manager/images/gallery/cursor_move.png
index 0f372b8..d1a756d 100644
--- a/chrome/browser/resources/file_manager/images/gallery/cursor_move.png
+++ b/chrome/browser/resources/file_manager/images/gallery/cursor_move.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/cursor_nwse.png b/chrome/browser/resources/file_manager/images/gallery/cursor_nwse.png
index 3067fc1..3f3e33c 100644
--- a/chrome/browser/resources/file_manager/images/gallery/cursor_nwse.png
+++ b/chrome/browser/resources/file_manager/images/gallery/cursor_nwse.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/cursor_swne.png b/chrome/browser/resources/file_manager/images/gallery/cursor_swne.png
index 62276f9..5e34475 100644
--- a/chrome/browser/resources/file_manager/images/gallery/cursor_swne.png
+++ b/chrome/browser/resources/file_manager/images/gallery/cursor_swne.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/cursor_updown.png b/chrome/browser/resources/file_manager/images/gallery/cursor_updown.png
index 09400f4..f3a4224 100644
--- a/chrome/browser/resources/file_manager/images/gallery/cursor_updown.png
+++ b/chrome/browser/resources/file_manager/images/gallery/cursor_updown.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/icon_1up.png b/chrome/browser/resources/file_manager/images/gallery/icon_1up.png
index d8c31fd..546e87a 100644
--- a/chrome/browser/resources/file_manager/images/gallery/icon_1up.png
+++ b/chrome/browser/resources/file_manager/images/gallery/icon_1up.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/icon_1up_selected.png b/chrome/browser/resources/file_manager/images/gallery/icon_1up_selected.png
index 01cc25c..a3043a8 100644
--- a/chrome/browser/resources/file_manager/images/gallery/icon_1up_selected.png
+++ b/chrome/browser/resources/file_manager/images/gallery/icon_1up_selected.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/icon_autofix.png b/chrome/browser/resources/file_manager/images/gallery/icon_autofix.png
index 786cfa2..0fb5b82 100644
--- a/chrome/browser/resources/file_manager/images/gallery/icon_autofix.png
+++ b/chrome/browser/resources/file_manager/images/gallery/icon_autofix.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/icon_autofix_selected.png b/chrome/browser/resources/file_manager/images/gallery/icon_autofix_selected.png
index c55265e..fb5972d 100644
--- a/chrome/browser/resources/file_manager/images/gallery/icon_autofix_selected.png
+++ b/chrome/browser/resources/file_manager/images/gallery/icon_autofix_selected.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/icon_brightness.png b/chrome/browser/resources/file_manager/images/gallery/icon_brightness.png
index 9754fb0..ec9c114 100644
--- a/chrome/browser/resources/file_manager/images/gallery/icon_brightness.png
+++ b/chrome/browser/resources/file_manager/images/gallery/icon_brightness.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/icon_brightness_selected.png b/chrome/browser/resources/file_manager/images/gallery/icon_brightness_selected.png
index 3781f03..6cd4462 100644
--- a/chrome/browser/resources/file_manager/images/gallery/icon_brightness_selected.png
+++ b/chrome/browser/resources/file_manager/images/gallery/icon_brightness_selected.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/icon_contrast.png b/chrome/browser/resources/file_manager/images/gallery/icon_contrast.png
index 7a58059..0188d48 100644
--- a/chrome/browser/resources/file_manager/images/gallery/icon_contrast.png
+++ b/chrome/browser/resources/file_manager/images/gallery/icon_contrast.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/icon_crop.png b/chrome/browser/resources/file_manager/images/gallery/icon_crop.png
index 111b550..efff5ba 100644
--- a/chrome/browser/resources/file_manager/images/gallery/icon_crop.png
+++ b/chrome/browser/resources/file_manager/images/gallery/icon_crop.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/icon_crop_selected.png b/chrome/browser/resources/file_manager/images/gallery/icon_crop_selected.png
index 90c0d31..18b8317 100644
--- a/chrome/browser/resources/file_manager/images/gallery/icon_crop_selected.png
+++ b/chrome/browser/resources/file_manager/images/gallery/icon_crop_selected.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/icon_delete.png b/chrome/browser/resources/file_manager/images/gallery/icon_delete.png
index 5a32b6a..efb132a 100644
--- a/chrome/browser/resources/file_manager/images/gallery/icon_delete.png
+++ b/chrome/browser/resources/file_manager/images/gallery/icon_delete.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/icon_delete_selected.png b/chrome/browser/resources/file_manager/images/gallery/icon_delete_selected.png
index 45fe59e..f2f88d8 100644
--- a/chrome/browser/resources/file_manager/images/gallery/icon_delete_selected.png
+++ b/chrome/browser/resources/file_manager/images/gallery/icon_delete_selected.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/icon_edit.png b/chrome/browser/resources/file_manager/images/gallery/icon_edit.png
index 599dd43..fc72ecf 100644
--- a/chrome/browser/resources/file_manager/images/gallery/icon_edit.png
+++ b/chrome/browser/resources/file_manager/images/gallery/icon_edit.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/icon_edit_selected.png b/chrome/browser/resources/file_manager/images/gallery/icon_edit_selected.png
index 060e41c..61540b5 100644
--- a/chrome/browser/resources/file_manager/images/gallery/icon_edit_selected.png
+++ b/chrome/browser/resources/file_manager/images/gallery/icon_edit_selected.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/icon_mosaic.png b/chrome/browser/resources/file_manager/images/gallery/icon_mosaic.png
index 5291a42..6e49d3c 100644
--- a/chrome/browser/resources/file_manager/images/gallery/icon_mosaic.png
+++ b/chrome/browser/resources/file_manager/images/gallery/icon_mosaic.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/icon_mosaic_selected.png b/chrome/browser/resources/file_manager/images/gallery/icon_mosaic_selected.png
index a17b4c0..86edb6e 100644
--- a/chrome/browser/resources/file_manager/images/gallery/icon_mosaic_selected.png
+++ b/chrome/browser/resources/file_manager/images/gallery/icon_mosaic_selected.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/icon_print.png b/chrome/browser/resources/file_manager/images/gallery/icon_print.png
new file mode 100644
index 0000000..ec5418e
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/gallery/icon_print.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/icon_print_selected.png b/chrome/browser/resources/file_manager/images/gallery/icon_print_selected.png
new file mode 100644
index 0000000..89e302e
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/gallery/icon_print_selected.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/icon_redo.png b/chrome/browser/resources/file_manager/images/gallery/icon_redo.png
index 113a8ea..7b4703b 100644
--- a/chrome/browser/resources/file_manager/images/gallery/icon_redo.png
+++ b/chrome/browser/resources/file_manager/images/gallery/icon_redo.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/icon_redo_selected.png b/chrome/browser/resources/file_manager/images/gallery/icon_redo_selected.png
index b0d6b9b..0022a13 100644
--- a/chrome/browser/resources/file_manager/images/gallery/icon_redo_selected.png
+++ b/chrome/browser/resources/file_manager/images/gallery/icon_redo_selected.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/icon_rotate.png b/chrome/browser/resources/file_manager/images/gallery/icon_rotate.png
index d474022..c60f258 100644
--- a/chrome/browser/resources/file_manager/images/gallery/icon_rotate.png
+++ b/chrome/browser/resources/file_manager/images/gallery/icon_rotate.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/icon_rotate_left.png b/chrome/browser/resources/file_manager/images/gallery/icon_rotate_left.png
index 3fcbe71..3f102f3 100644
--- a/chrome/browser/resources/file_manager/images/gallery/icon_rotate_left.png
+++ b/chrome/browser/resources/file_manager/images/gallery/icon_rotate_left.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/icon_rotate_left_selected.png b/chrome/browser/resources/file_manager/images/gallery/icon_rotate_left_selected.png
index ebd9f16..1e4c1d6 100644
--- a/chrome/browser/resources/file_manager/images/gallery/icon_rotate_left_selected.png
+++ b/chrome/browser/resources/file_manager/images/gallery/icon_rotate_left_selected.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/icon_rotate_selected.png b/chrome/browser/resources/file_manager/images/gallery/icon_rotate_selected.png
index a346263..445350f 100644
--- a/chrome/browser/resources/file_manager/images/gallery/icon_rotate_selected.png
+++ b/chrome/browser/resources/file_manager/images/gallery/icon_rotate_selected.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/icon_share.png b/chrome/browser/resources/file_manager/images/gallery/icon_share.png
index 637b706..36bb221 100644
--- a/chrome/browser/resources/file_manager/images/gallery/icon_share.png
+++ b/chrome/browser/resources/file_manager/images/gallery/icon_share.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/icon_share_selected.png b/chrome/browser/resources/file_manager/images/gallery/icon_share_selected.png
index 19c9207..438e8a2 100644
--- a/chrome/browser/resources/file_manager/images/gallery/icon_share_selected.png
+++ b/chrome/browser/resources/file_manager/images/gallery/icon_share_selected.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/icon_slideshow.png b/chrome/browser/resources/file_manager/images/gallery/icon_slideshow.png
index 6dd5018..72763d4 100644
--- a/chrome/browser/resources/file_manager/images/gallery/icon_slideshow.png
+++ b/chrome/browser/resources/file_manager/images/gallery/icon_slideshow.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/icon_slideshow_selected.png b/chrome/browser/resources/file_manager/images/gallery/icon_slideshow_selected.png
index 1fad233..4f80a48 100644
--- a/chrome/browser/resources/file_manager/images/gallery/icon_slideshow_selected.png
+++ b/chrome/browser/resources/file_manager/images/gallery/icon_slideshow_selected.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/icon_undo.png b/chrome/browser/resources/file_manager/images/gallery/icon_undo.png
index 14d9f92..333c455 100644
--- a/chrome/browser/resources/file_manager/images/gallery/icon_undo.png
+++ b/chrome/browser/resources/file_manager/images/gallery/icon_undo.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/icon_undo_selected.png b/chrome/browser/resources/file_manager/images/gallery/icon_undo_selected.png
index 2c0dd0e..d5d13a7 100644
--- a/chrome/browser/resources/file_manager/images/gallery/icon_undo_selected.png
+++ b/chrome/browser/resources/file_manager/images/gallery/icon_undo_selected.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/slider_thumb.png b/chrome/browser/resources/file_manager/images/gallery/slider_thumb.png
index 0914856..cb2d712 100644
--- a/chrome/browser/resources/file_manager/images/gallery/slider_thumb.png
+++ b/chrome/browser/resources/file_manager/images/gallery/slider_thumb.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/slideshow-end.png b/chrome/browser/resources/file_manager/images/gallery/slideshow-end.png
index d0a4ce3..f437111 100644
--- a/chrome/browser/resources/file_manager/images/gallery/slideshow-end.png
+++ b/chrome/browser/resources/file_manager/images/gallery/slideshow-end.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/slideshow-pause.png b/chrome/browser/resources/file_manager/images/gallery/slideshow-pause.png
index bbf6181..ad3633f 100644
--- a/chrome/browser/resources/file_manager/images/gallery/slideshow-pause.png
+++ b/chrome/browser/resources/file_manager/images/gallery/slideshow-pause.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/gallery/slideshow-play.png b/chrome/browser/resources/file_manager/images/gallery/slideshow-play.png
index 4e5ac86..f949121 100644
--- a/chrome/browser/resources/file_manager/images/gallery/slideshow-play.png
+++ b/chrome/browser/resources/file_manager/images/gallery/slideshow-play.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/icon128.png b/chrome/browser/resources/file_manager/images/icon128.png
index 2c6acb6..d4c6c55 100644
--- a/chrome/browser/resources/file_manager/images/icon128.png
+++ b/chrome/browser/resources/file_manager/images/icon128.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/icon16.png b/chrome/browser/resources/file_manager/images/icon16.png
index e05944e..dc3b8d8 100644
--- a/chrome/browser/resources/file_manager/images/icon16.png
+++ b/chrome/browser/resources/file_manager/images/icon16.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/icon256.png b/chrome/browser/resources/file_manager/images/icon256.png
new file mode 100644
index 0000000..2e50e0f
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/icon256.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/icon32.png b/chrome/browser/resources/file_manager/images/icon32.png
index 739aa02..47b8a55 100644
--- a/chrome/browser/resources/file_manager/images/icon32.png
+++ b/chrome/browser/resources/file_manager/images/icon32.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/icon48.png b/chrome/browser/resources/file_manager/images/icon48.png
new file mode 100644
index 0000000..b3c7dbf
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/icon48.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/icon64.png b/chrome/browser/resources/file_manager/images/icon64.png
index 941073a..3130c1c 100644
--- a/chrome/browser/resources/file_manager/images/icon64.png
+++ b/chrome/browser/resources/file_manager/images/icon64.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/icon96.png b/chrome/browser/resources/file_manager/images/icon96.png
new file mode 100644
index 0000000..fdc1ab1
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/icon96.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/audio_player.png b/chrome/browser/resources/file_manager/images/media/2x/audio_player.png
index c78b24c..ce5fa1a 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/audio_player.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/audio_player.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/drive.png b/chrome/browser/resources/file_manager/images/media/2x/drive.png
index 1cb63a3..e3b7973 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/drive.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/drive.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/error.png b/chrome/browser/resources/file_manager/images/media/2x/error.png
index 1e08991..3c3213e 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/error.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/error.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_close.png b/chrome/browser/resources/file_manager/images/media/2x/media_close.png
index c6f9014..2e19603 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_close.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_close.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_collapse.png b/chrome/browser/resources/file_manager/images/media/2x/media_collapse.png
index df85111..a940061 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_collapse.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_collapse.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_expand.png b/chrome/browser/resources/file_manager/images/media/2x/media_expand.png
index 5abe382..20c2340 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_expand.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_expand.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_fullscreen.png b/chrome/browser/resources/file_manager/images/media/2x/media_fullscreen.png
index c91381e..090c825 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_fullscreen.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_fullscreen.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_fullscreen_disabled.png b/chrome/browser/resources/file_manager/images/media/2x/media_fullscreen_disabled.png
index 256ce8e..96b3f63 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_fullscreen_disabled.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_fullscreen_disabled.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_fullscreen_down.png b/chrome/browser/resources/file_manager/images/media/2x/media_fullscreen_down.png
index ed5bf65..17da8eb 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_fullscreen_down.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_fullscreen_down.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_fullscreen_hover.png b/chrome/browser/resources/file_manager/images/media/2x/media_fullscreen_hover.png
index ba2bad5..25daa4f 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_fullscreen_hover.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_fullscreen_hover.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_loop.png b/chrome/browser/resources/file_manager/images/media/2x/media_loop.png
index 4a9a00a..6bea029 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_loop.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_loop.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_loop_down.png b/chrome/browser/resources/file_manager/images/media/2x/media_loop_down.png
index 411669d..9559554 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_loop_down.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_loop_down.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_loop_hover.png b/chrome/browser/resources/file_manager/images/media/2x/media_loop_hover.png
index a4af6db..cb2af67 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_loop_hover.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_loop_hover.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_next.png b/chrome/browser/resources/file_manager/images/media/2x/media_next.png
index e656e25..012af92 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_next.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_next.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_next_down.png b/chrome/browser/resources/file_manager/images/media/2x/media_next_down.png
index 235a325..79a370b 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_next_down.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_next_down.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_next_hover.png b/chrome/browser/resources/file_manager/images/media/2x/media_next_hover.png
index c9f053b..8705d69 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_next_hover.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_next_hover.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_pause.png b/chrome/browser/resources/file_manager/images/media/2x/media_pause.png
index c254581..acebff9 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_pause.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_pause.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_pause_audio.png b/chrome/browser/resources/file_manager/images/media/2x/media_pause_audio.png
index 15c96c5..7489a7e 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_pause_audio.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_pause_audio.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_pause_audio_down.png b/chrome/browser/resources/file_manager/images/media/2x/media_pause_audio_down.png
index f481c70..eb22b95 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_pause_audio_down.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_pause_audio_down.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_pause_audio_hover.png b/chrome/browser/resources/file_manager/images/media/2x/media_pause_audio_hover.png
index 028792e..944b189 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_pause_audio_hover.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_pause_audio_hover.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_pause_down.png b/chrome/browser/resources/file_manager/images/media/2x/media_pause_down.png
index 02d3d94..6f8f494 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_pause_down.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_pause_down.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_pause_hover.png b/chrome/browser/resources/file_manager/images/media/2x/media_pause_hover.png
index 876963c..beb86f2 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_pause_hover.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_pause_hover.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_play.png b/chrome/browser/resources/file_manager/images/media/2x/media_play.png
index 23fe41c..28e8a25 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_play.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_play.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_play_audio.png b/chrome/browser/resources/file_manager/images/media/2x/media_play_audio.png
index 6e4da5a..b175762 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_play_audio.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_play_audio.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_play_audio_down.png b/chrome/browser/resources/file_manager/images/media/2x/media_play_audio_down.png
index 8bee6e6..01dcc46 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_play_audio_down.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_play_audio_down.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_play_audio_hover.png b/chrome/browser/resources/file_manager/images/media/2x/media_play_audio_hover.png
index 4c4e18a..c64070f 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_play_audio_hover.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_play_audio_hover.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_play_disabled.png b/chrome/browser/resources/file_manager/images/media/2x/media_play_disabled.png
index 114db5a..9d0dd93 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_play_disabled.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_play_disabled.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_play_down.png b/chrome/browser/resources/file_manager/images/media/2x/media_play_down.png
index 21d0ea4..7c68787 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_play_down.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_play_down.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_play_hover.png b/chrome/browser/resources/file_manager/images/media/2x/media_play_hover.png
index 41a7fae..28ca18b 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_play_hover.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_play_hover.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_previous.png b/chrome/browser/resources/file_manager/images/media/2x/media_previous.png
index 6b38df8..6c8d640 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_previous.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_previous.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_previous_down.png b/chrome/browser/resources/file_manager/images/media/2x/media_previous_down.png
index 7143915..9474158 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_previous_down.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_previous_down.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_previous_hover.png b/chrome/browser/resources/file_manager/images/media/2x/media_previous_hover.png
index b481be9..05f5b4a 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_previous_hover.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_previous_hover.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_slider_thumb.png b/chrome/browser/resources/file_manager/images/media/2x/media_slider_thumb.png
index c84ca8c..5a130bd 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_slider_thumb.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_slider_thumb.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_slider_thumb_down.png b/chrome/browser/resources/file_manager/images/media/2x/media_slider_thumb_down.png
index 67a1be4..931850f 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_slider_thumb_down.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_slider_thumb_down.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_slider_thumb_hover.png b/chrome/browser/resources/file_manager/images/media/2x/media_slider_thumb_hover.png
index 6a374f3..9fe30ef 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_slider_thumb_hover.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_slider_thumb_hover.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_sound_disabled.png b/chrome/browser/resources/file_manager/images/media/2x/media_sound_disabled.png
index f1f6a2d..acbaa71 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_sound_disabled.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_sound_disabled.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_sound_disabled_down.png b/chrome/browser/resources/file_manager/images/media/2x/media_sound_disabled_down.png
index 4204819..f594f47 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_sound_disabled_down.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_sound_disabled_down.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_sound_disabled_hover.png b/chrome/browser/resources/file_manager/images/media/2x/media_sound_disabled_hover.png
index f5ae65c..f4cc7b3 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_sound_disabled_hover.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_sound_disabled_hover.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_sound_full.png b/chrome/browser/resources/file_manager/images/media/2x/media_sound_full.png
index 0dd6111..a093e9f 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_sound_full.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_sound_full.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_sound_full_disabled.png b/chrome/browser/resources/file_manager/images/media/2x/media_sound_full_disabled.png
index 142093e..56635f1 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_sound_full_disabled.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_sound_full_disabled.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_sound_full_down.png b/chrome/browser/resources/file_manager/images/media/2x/media_sound_full_down.png
index b7e8e40..90a41ba 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_sound_full_down.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_sound_full_down.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_sound_full_hover.png b/chrome/browser/resources/file_manager/images/media/2x/media_sound_full_hover.png
index 1491a48..e617eab 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_sound_full_hover.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_sound_full_hover.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_sound_level1.png b/chrome/browser/resources/file_manager/images/media/2x/media_sound_level1.png
index abe4ad6..25904c0 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_sound_level1.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_sound_level1.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_sound_level1_down.png b/chrome/browser/resources/file_manager/images/media/2x/media_sound_level1_down.png
index b79992b..0ba2886 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_sound_level1_down.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_sound_level1_down.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_sound_level1_hover.png b/chrome/browser/resources/file_manager/images/media/2x/media_sound_level1_hover.png
index 1fc2f7c..be56fc1 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_sound_level1_hover.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_sound_level1_hover.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_sound_level2.png b/chrome/browser/resources/file_manager/images/media/2x/media_sound_level2.png
index d0f307f..24f7ea8 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_sound_level2.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_sound_level2.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_sound_level2_down.png b/chrome/browser/resources/file_manager/images/media/2x/media_sound_level2_down.png
index cf45b23..34fce54 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_sound_level2_down.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_sound_level2_down.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_sound_level2_hover.png b/chrome/browser/resources/file_manager/images/media/2x/media_sound_level2_hover.png
index d572491..9966a5e 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_sound_level2_hover.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_sound_level2_hover.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_volume_slider_thumb.png b/chrome/browser/resources/file_manager/images/media/2x/media_volume_slider_thumb.png
index 42f7813..c518743 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_volume_slider_thumb.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_volume_slider_thumb.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_volume_slider_thumb_down.png b/chrome/browser/resources/file_manager/images/media/2x/media_volume_slider_thumb_down.png
index fc24add..7967b2d 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_volume_slider_thumb_down.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_volume_slider_thumb_down.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/media_volume_slider_thumb_hover.png b/chrome/browser/resources/file_manager/images/media/2x/media_volume_slider_thumb_hover.png
index 349665e..ae16119 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/media_volume_slider_thumb_hover.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/media_volume_slider_thumb_hover.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/2x/watch.png b/chrome/browser/resources/file_manager/images/media/2x/watch.png
index 732d4dd..f47751b 100644
--- a/chrome/browser/resources/file_manager/images/media/2x/watch.png
+++ b/chrome/browser/resources/file_manager/images/media/2x/watch.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/audio_player.png b/chrome/browser/resources/file_manager/images/media/audio_player.png
index 68d4a06..9134bde 100644
--- a/chrome/browser/resources/file_manager/images/media/audio_player.png
+++ b/chrome/browser/resources/file_manager/images/media/audio_player.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/drive.png b/chrome/browser/resources/file_manager/images/media/drive.png
index 8d09e30..8f4b64e 100644
--- a/chrome/browser/resources/file_manager/images/media/drive.png
+++ b/chrome/browser/resources/file_manager/images/media/drive.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/error.png b/chrome/browser/resources/file_manager/images/media/error.png
index ee2a851..125c0b7 100644
--- a/chrome/browser/resources/file_manager/images/media/error.png
+++ b/chrome/browser/resources/file_manager/images/media/error.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_close.png b/chrome/browser/resources/file_manager/images/media/media_close.png
index d15a815..5980ea7 100644
--- a/chrome/browser/resources/file_manager/images/media/media_close.png
+++ b/chrome/browser/resources/file_manager/images/media/media_close.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_collapse.png b/chrome/browser/resources/file_manager/images/media/media_collapse.png
index 4e173c7..3ab1add 100644
--- a/chrome/browser/resources/file_manager/images/media/media_collapse.png
+++ b/chrome/browser/resources/file_manager/images/media/media_collapse.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_expand.png b/chrome/browser/resources/file_manager/images/media/media_expand.png
index 31df0d2..a228fbd 100644
--- a/chrome/browser/resources/file_manager/images/media/media_expand.png
+++ b/chrome/browser/resources/file_manager/images/media/media_expand.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_fullscreen.png b/chrome/browser/resources/file_manager/images/media/media_fullscreen.png
index 900e0f5..24f2ecf 100644
--- a/chrome/browser/resources/file_manager/images/media/media_fullscreen.png
+++ b/chrome/browser/resources/file_manager/images/media/media_fullscreen.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_fullscreen_disabled.png b/chrome/browser/resources/file_manager/images/media/media_fullscreen_disabled.png
index 7c56e0d..bf74390 100644
--- a/chrome/browser/resources/file_manager/images/media/media_fullscreen_disabled.png
+++ b/chrome/browser/resources/file_manager/images/media/media_fullscreen_disabled.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_fullscreen_down.png b/chrome/browser/resources/file_manager/images/media/media_fullscreen_down.png
index ff4e453..dd318ce 100644
--- a/chrome/browser/resources/file_manager/images/media/media_fullscreen_down.png
+++ b/chrome/browser/resources/file_manager/images/media/media_fullscreen_down.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_fullscreen_hover.png b/chrome/browser/resources/file_manager/images/media/media_fullscreen_hover.png
index 4f675f6..4232739 100644
--- a/chrome/browser/resources/file_manager/images/media/media_fullscreen_hover.png
+++ b/chrome/browser/resources/file_manager/images/media/media_fullscreen_hover.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_loop.png b/chrome/browser/resources/file_manager/images/media/media_loop.png
index 51a1b61..f3e35dd 100644
--- a/chrome/browser/resources/file_manager/images/media/media_loop.png
+++ b/chrome/browser/resources/file_manager/images/media/media_loop.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_loop_down.png b/chrome/browser/resources/file_manager/images/media/media_loop_down.png
index 4846da6..dda8af5 100644
--- a/chrome/browser/resources/file_manager/images/media/media_loop_down.png
+++ b/chrome/browser/resources/file_manager/images/media/media_loop_down.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_loop_hover.png b/chrome/browser/resources/file_manager/images/media/media_loop_hover.png
index 2eae2a4..805d293 100644
--- a/chrome/browser/resources/file_manager/images/media/media_loop_hover.png
+++ b/chrome/browser/resources/file_manager/images/media/media_loop_hover.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_next.png b/chrome/browser/resources/file_manager/images/media/media_next.png
index 3daba60..aec4ee6 100644
--- a/chrome/browser/resources/file_manager/images/media/media_next.png
+++ b/chrome/browser/resources/file_manager/images/media/media_next.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_next_down.png b/chrome/browser/resources/file_manager/images/media/media_next_down.png
index 4213f20..53cc106 100644
--- a/chrome/browser/resources/file_manager/images/media/media_next_down.png
+++ b/chrome/browser/resources/file_manager/images/media/media_next_down.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_next_hover.png b/chrome/browser/resources/file_manager/images/media/media_next_hover.png
index b01dfca..bea50b5 100644
--- a/chrome/browser/resources/file_manager/images/media/media_next_hover.png
+++ b/chrome/browser/resources/file_manager/images/media/media_next_hover.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_pause.png b/chrome/browser/resources/file_manager/images/media/media_pause.png
index f4a7982..0a304e4 100644
--- a/chrome/browser/resources/file_manager/images/media/media_pause.png
+++ b/chrome/browser/resources/file_manager/images/media/media_pause.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_pause_audio.png b/chrome/browser/resources/file_manager/images/media/media_pause_audio.png
index 45f7d7a..8e2e87b 100644
--- a/chrome/browser/resources/file_manager/images/media/media_pause_audio.png
+++ b/chrome/browser/resources/file_manager/images/media/media_pause_audio.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_pause_audio_down.png b/chrome/browser/resources/file_manager/images/media/media_pause_audio_down.png
index 335ba91..1178984 100644
--- a/chrome/browser/resources/file_manager/images/media/media_pause_audio_down.png
+++ b/chrome/browser/resources/file_manager/images/media/media_pause_audio_down.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_pause_audio_hover.png b/chrome/browser/resources/file_manager/images/media/media_pause_audio_hover.png
index 33e9b79..52b6bbc 100644
--- a/chrome/browser/resources/file_manager/images/media/media_pause_audio_hover.png
+++ b/chrome/browser/resources/file_manager/images/media/media_pause_audio_hover.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_pause_down.png b/chrome/browser/resources/file_manager/images/media/media_pause_down.png
index 36788b8..6e65195 100644
--- a/chrome/browser/resources/file_manager/images/media/media_pause_down.png
+++ b/chrome/browser/resources/file_manager/images/media/media_pause_down.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_pause_hover.png b/chrome/browser/resources/file_manager/images/media/media_pause_hover.png
index 612ba37..adf0b28 100644
--- a/chrome/browser/resources/file_manager/images/media/media_pause_hover.png
+++ b/chrome/browser/resources/file_manager/images/media/media_pause_hover.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_play.png b/chrome/browser/resources/file_manager/images/media/media_play.png
index a85d940..47bcdc2 100644
--- a/chrome/browser/resources/file_manager/images/media/media_play.png
+++ b/chrome/browser/resources/file_manager/images/media/media_play.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_play_audio.png b/chrome/browser/resources/file_manager/images/media/media_play_audio.png
index db8518c..eceaa5b 100644
--- a/chrome/browser/resources/file_manager/images/media/media_play_audio.png
+++ b/chrome/browser/resources/file_manager/images/media/media_play_audio.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_play_audio_down.png b/chrome/browser/resources/file_manager/images/media/media_play_audio_down.png
index deb0206..98ebeea 100644
--- a/chrome/browser/resources/file_manager/images/media/media_play_audio_down.png
+++ b/chrome/browser/resources/file_manager/images/media/media_play_audio_down.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_play_audio_hover.png b/chrome/browser/resources/file_manager/images/media/media_play_audio_hover.png
index a4a849f..c0867fa 100644
--- a/chrome/browser/resources/file_manager/images/media/media_play_audio_hover.png
+++ b/chrome/browser/resources/file_manager/images/media/media_play_audio_hover.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_play_disabled.png b/chrome/browser/resources/file_manager/images/media/media_play_disabled.png
index a0f6a2c..6e96d4c 100644
--- a/chrome/browser/resources/file_manager/images/media/media_play_disabled.png
+++ b/chrome/browser/resources/file_manager/images/media/media_play_disabled.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_play_down.png b/chrome/browser/resources/file_manager/images/media/media_play_down.png
index c55d526..1759ec3 100644
--- a/chrome/browser/resources/file_manager/images/media/media_play_down.png
+++ b/chrome/browser/resources/file_manager/images/media/media_play_down.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_play_hover.png b/chrome/browser/resources/file_manager/images/media/media_play_hover.png
index fb12b4c..3942d46 100644
--- a/chrome/browser/resources/file_manager/images/media/media_play_hover.png
+++ b/chrome/browser/resources/file_manager/images/media/media_play_hover.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_previous.png b/chrome/browser/resources/file_manager/images/media/media_previous.png
index 755ca5e..4fded35 100644
--- a/chrome/browser/resources/file_manager/images/media/media_previous.png
+++ b/chrome/browser/resources/file_manager/images/media/media_previous.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_previous_down.png b/chrome/browser/resources/file_manager/images/media/media_previous_down.png
index 1e36380..2c63184 100644
--- a/chrome/browser/resources/file_manager/images/media/media_previous_down.png
+++ b/chrome/browser/resources/file_manager/images/media/media_previous_down.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_previous_hover.png b/chrome/browser/resources/file_manager/images/media/media_previous_hover.png
index edfec5a..45ea61b 100644
--- a/chrome/browser/resources/file_manager/images/media/media_previous_hover.png
+++ b/chrome/browser/resources/file_manager/images/media/media_previous_hover.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_slider_thumb.png b/chrome/browser/resources/file_manager/images/media/media_slider_thumb.png
index 652f07c..e55b2c2 100644
--- a/chrome/browser/resources/file_manager/images/media/media_slider_thumb.png
+++ b/chrome/browser/resources/file_manager/images/media/media_slider_thumb.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_slider_thumb_down.png b/chrome/browser/resources/file_manager/images/media/media_slider_thumb_down.png
index 30198b7..f0b2be7 100644
--- a/chrome/browser/resources/file_manager/images/media/media_slider_thumb_down.png
+++ b/chrome/browser/resources/file_manager/images/media/media_slider_thumb_down.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_slider_thumb_hover.png b/chrome/browser/resources/file_manager/images/media/media_slider_thumb_hover.png
index 042ceb1..e216ae6 100644
--- a/chrome/browser/resources/file_manager/images/media/media_slider_thumb_hover.png
+++ b/chrome/browser/resources/file_manager/images/media/media_slider_thumb_hover.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_sound_disabled.png b/chrome/browser/resources/file_manager/images/media/media_sound_disabled.png
index 549a826..42126de 100644
--- a/chrome/browser/resources/file_manager/images/media/media_sound_disabled.png
+++ b/chrome/browser/resources/file_manager/images/media/media_sound_disabled.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_sound_disabled_down.png b/chrome/browser/resources/file_manager/images/media/media_sound_disabled_down.png
index a5bcc90..2b494b9 100644
--- a/chrome/browser/resources/file_manager/images/media/media_sound_disabled_down.png
+++ b/chrome/browser/resources/file_manager/images/media/media_sound_disabled_down.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_sound_disabled_hover.png b/chrome/browser/resources/file_manager/images/media/media_sound_disabled_hover.png
index 8b7b522..5040f80 100644
--- a/chrome/browser/resources/file_manager/images/media/media_sound_disabled_hover.png
+++ b/chrome/browser/resources/file_manager/images/media/media_sound_disabled_hover.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_sound_full.png b/chrome/browser/resources/file_manager/images/media/media_sound_full.png
index 9b72b5c..4a03402 100644
--- a/chrome/browser/resources/file_manager/images/media/media_sound_full.png
+++ b/chrome/browser/resources/file_manager/images/media/media_sound_full.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_sound_full_disabled.png b/chrome/browser/resources/file_manager/images/media/media_sound_full_disabled.png
index e3d55b0..cef4bc4 100644
--- a/chrome/browser/resources/file_manager/images/media/media_sound_full_disabled.png
+++ b/chrome/browser/resources/file_manager/images/media/media_sound_full_disabled.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_sound_full_down.png b/chrome/browser/resources/file_manager/images/media/media_sound_full_down.png
index 558c176..1a185ed 100644
--- a/chrome/browser/resources/file_manager/images/media/media_sound_full_down.png
+++ b/chrome/browser/resources/file_manager/images/media/media_sound_full_down.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_sound_full_hover.png b/chrome/browser/resources/file_manager/images/media/media_sound_full_hover.png
index 1dccc1c..d285c01 100644
--- a/chrome/browser/resources/file_manager/images/media/media_sound_full_hover.png
+++ b/chrome/browser/resources/file_manager/images/media/media_sound_full_hover.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_sound_level1.png b/chrome/browser/resources/file_manager/images/media/media_sound_level1.png
index 0e1b4f8..2f7ceea 100644
--- a/chrome/browser/resources/file_manager/images/media/media_sound_level1.png
+++ b/chrome/browser/resources/file_manager/images/media/media_sound_level1.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_sound_level1_down.png b/chrome/browser/resources/file_manager/images/media/media_sound_level1_down.png
index 19ff4b9..9777c9b 100644
--- a/chrome/browser/resources/file_manager/images/media/media_sound_level1_down.png
+++ b/chrome/browser/resources/file_manager/images/media/media_sound_level1_down.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_sound_level1_hover.png b/chrome/browser/resources/file_manager/images/media/media_sound_level1_hover.png
index 94dde01..fdf3bc1 100644
--- a/chrome/browser/resources/file_manager/images/media/media_sound_level1_hover.png
+++ b/chrome/browser/resources/file_manager/images/media/media_sound_level1_hover.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_sound_level2.png b/chrome/browser/resources/file_manager/images/media/media_sound_level2.png
index b241d0f..9e69e8b 100644
--- a/chrome/browser/resources/file_manager/images/media/media_sound_level2.png
+++ b/chrome/browser/resources/file_manager/images/media/media_sound_level2.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_sound_level2_down.png b/chrome/browser/resources/file_manager/images/media/media_sound_level2_down.png
index 43cf801..422b435 100644
--- a/chrome/browser/resources/file_manager/images/media/media_sound_level2_down.png
+++ b/chrome/browser/resources/file_manager/images/media/media_sound_level2_down.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_sound_level2_hover.png b/chrome/browser/resources/file_manager/images/media/media_sound_level2_hover.png
index 6e0bbe8..8bf6157 100644
--- a/chrome/browser/resources/file_manager/images/media/media_sound_level2_hover.png
+++ b/chrome/browser/resources/file_manager/images/media/media_sound_level2_hover.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_volume_slider_thumb.png b/chrome/browser/resources/file_manager/images/media/media_volume_slider_thumb.png
index e6ef1d3..a1bf057 100644
--- a/chrome/browser/resources/file_manager/images/media/media_volume_slider_thumb.png
+++ b/chrome/browser/resources/file_manager/images/media/media_volume_slider_thumb.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_volume_slider_thumb_down.png b/chrome/browser/resources/file_manager/images/media/media_volume_slider_thumb_down.png
index 6a884e6..a4560f0 100644
--- a/chrome/browser/resources/file_manager/images/media/media_volume_slider_thumb_down.png
+++ b/chrome/browser/resources/file_manager/images/media/media_volume_slider_thumb_down.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/media_volume_slider_thumb_hover.png b/chrome/browser/resources/file_manager/images/media/media_volume_slider_thumb_hover.png
index 129e495..159e2e7 100644
--- a/chrome/browser/resources/file_manager/images/media/media_volume_slider_thumb_hover.png
+++ b/chrome/browser/resources/file_manager/images/media/media_volume_slider_thumb_hover.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/images/media/watch.png b/chrome/browser/resources/file_manager/images/media/watch.png
index 28d49b2..92b6284 100644
--- a/chrome/browser/resources/file_manager/images/media/watch.png
+++ b/chrome/browser/resources/file_manager/images/media/watch.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/js/action_choice_scripts.js b/chrome/browser/resources/file_manager/js/action_choice_scripts.js
index ce3090e..2cf5cd8 100644
--- a/chrome/browser/resources/file_manager/js/action_choice_scripts.js
+++ b/chrome/browser/resources/file_manager/js/action_choice_scripts.js
@@ -8,7 +8,7 @@
 // included file but that's all right since any javascript file should start
 // with a copyright comment anyway.
 
-//<include src="../../image_loader/client.js"/>
+//<include src="../../image_loader/image_loader_client.js"/>
 
 //<include src="../../../../../ui/webui/resources/js/load_time_data.js"/>
 //<include src="../../../../../ui/webui/resources/js/util.js"/>
diff --git a/chrome/browser/resources/file_manager/js/background.js b/chrome/browser/resources/file_manager/js/background.js
index c6f057f..294af04 100644
--- a/chrome/browser/resources/file_manager/js/background.js
+++ b/chrome/browser/resources/file_manager/js/background.js
@@ -315,8 +315,12 @@
         // The isFocused() method should always be available, but in case
         // Files.app's failed on some error, wrap it with try catch.
         try {
-          if (appWindows[key].contentWindow.isFocused())
-            return key;
+          if (appWindows[key].contentWindow.isFocused()) {
+            if (opt_callback)
+              opt_callback(key);
+            onTaskCompleted();
+            return;
+          }
         } catch (e) {
           console.error(e.message);
         }
@@ -383,10 +387,12 @@
 }
 
 /**
+ * Executes a file browser task.
+ *
  * @param {string} action Task id.
  * @param {Object} details Details object.
  */
-function executeFileBrowserTask(action, details) {
+function onExecute(action, details) {
   var urls = details.entries.map(function(e) { return e.toURL() });
 
   switch (action) {
@@ -465,9 +471,9 @@
 }
 
 /**
- * Launch the app.
+ * Launches the app.
  */
-function launch() {
+function onLaunched() {
   if (nextFileManagerWindowID == 0) {
     // The app just launched. Remove window state records that are not needed
     // any more.
@@ -487,13 +493,41 @@
 /**
  * Restarted the app, restore windows.
  */
-function restart() {
+function onRestarted() {
   reopenFileManagers();
   audioPlayer.reopen();
   videoPlayer.reopen();
 }
 
 /**
+ * Handles clicks on a custom item on the launcher context menu.
+ * @param {OnClickData} info Event details.
+ */
+function onContextMenuClicked(info) {
+  if (info.menuItemId == 'new-window') {
+    // Find the focused window (if any) and use it's current path for the
+    // new window. If not found, then launch with the default path.
+    for (var key in appWindows) {
+      try {
+        if (appWindows[key].contentWindow.isFocused()) {
+          var appState = {
+            defaultPath: appWindows[key].contentWindow.appState.defaultPath
+          };
+          launchFileManager(appState);
+          return;
+        }
+      } catch (ignore) {
+        // The isFocused method may not be defined during initialization.
+        // Therefore, wrapped with a try-catch block.
+      }
+    }
+
+    // Launch with the default path.
+    launchFileManager();
+  }
+}
+
+/**
  * Closes the background page, if it is not needed.
  */
 function maybeCloseBackgroundPage() {
@@ -502,11 +536,42 @@
     close();
 }
 
-chrome.app.runtime.onLaunched.addListener(launch);
-chrome.app.runtime.onRestarted.addListener(restart);
-
-function addExecuteHandler() {
-  chrome.fileBrowserHandler.onExecute.addListener(executeFileBrowserTask);
+/**
+ * Initializes the context menu. Recreates if already exists.
+ * @param {Object} strings Hash array of strings.
+ */
+function initContextMenu(strings) {
+  try {
+    chrome.contextMenus.remove('new-window');
+  } catch (ignore) {
+    // There is no way to detect if the context menu is already added, therefore
+    // try to recreate it every time.
+  }
+  chrome.contextMenus.create({
+    id: 'new-window',
+    contexts: ['launcher'],
+    title: strings['NEW_WINDOW_BUTTON_LABEL']
+  });
 }
 
-addExecuteHandler();
+/**
+ * Initializes the background page of Files.app.
+ */
+function initApp() {
+  // Initialize handlers.
+  chrome.fileBrowserHandler.onExecute.addListener(onExecute);
+  chrome.app.runtime.onLaunched.addListener(onLaunched);
+  chrome.app.runtime.onRestarted.addListener(onRestarted);
+  chrome.contextMenus.onClicked.addListener(onContextMenuClicked);
+
+  // Fetch strings and initialize the context menu.
+  queue.run(function(callback) {
+    chrome.fileBrowserPrivate.getStrings(function(strings) {
+      initContextMenu(strings);
+      chrome.storage.local.set({strings: strings}, callback);
+    });
+  });
+}
+
+// Initialize Files.app.
+initApp();
diff --git a/chrome/browser/resources/file_manager/js/breadcrumbs_controller.js b/chrome/browser/resources/file_manager/js/breadcrumbs_controller.js
index 5bbb33d..a4df354 100644
--- a/chrome/browser/resources/file_manager/js/breadcrumbs_controller.js
+++ b/chrome/browser/resources/file_manager/js/breadcrumbs_controller.js
@@ -247,7 +247,7 @@
  * @param {string} path Path to directory.
  */
 BreadcrumbsController.prototype.show = function(rootPath, path) {
-  this.bc_.style.display = '-webkit-box';
+  this.bc_.hidden = false;
   this.update(rootPath, path);
 };
 
@@ -255,7 +255,7 @@
  * Hide breadcrumbs div.
  */
 BreadcrumbsController.prototype.hide = function() {
-  this.bc_.style.display = 'none';
+  this.bc_.hidden = true;
 };
 
 /**
diff --git a/chrome/browser/resources/file_manager/js/butter_bar.js b/chrome/browser/resources/file_manager/js/butter_bar.js
index 5557440..69d8187 100644
--- a/chrome/browser/resources/file_manager/js/butter_bar.js
+++ b/chrome/browser/resources/file_manager/js/butter_bar.js
@@ -5,11 +5,6 @@
 'use strict';
 
 /**
- * The amount of time, before a butter bar will hide after the last update.
- */
-var HIDE_DELAY_TIME_MS = 2000;
-
-/**
  * Butter bar is shown on top of the file list and is used to show the copy
  * progress and other messages.
  * @param {HTMLElement} dialogDom FileManager top-level div.
@@ -39,6 +34,15 @@
 }
 
 /**
+ * The default amount of milliseconds time, before a butter bar will hide after
+ * the last update.
+ * @type {number}
+ * @private
+ * @const
+ */
+ButterBar.HIDE_DELAY_TIME_MS_ = 2000;
+
+/**
  * Name of action which should be displayed as an 'x' button instead of
  * link with text.
  * @const
@@ -66,7 +70,9 @@
  * Show butter bar.
  * @param {ButterBar.Mode} mode Butter bar mode.
  * @param {string} message The message to be shown.
- * @param {Object=} opt_options Options: 'actions', 'progress', 'timeout'.
+ * @param {Object=} opt_options Options: 'actions', 'progress', 'timeout'. If
+ *     'timeout' is not specified, HIDE_DELAY_TIME_MS_ is used. If 'timeout' is
+ *     false, the butter bar will not be hidden.
  */
 ButterBar.prototype.show = function(mode, message, opt_options) {
   this.currentMode_ = mode;
@@ -111,9 +117,9 @@
 ButterBar.prototype.showError_ = function(message) {
   // Wait in case there are previous dialogs being closed.
   setTimeout(function() {
-    this.hide_();
     this.alert_.showHtml('',  // Title.
                          message);
+    this.hide_();
   }.bind(this), cr.ui.dialogs.BaseDialog.ANIMATE_STABLE_DURATION);
 };
 
@@ -129,14 +135,6 @@
 
   this.clearHideTimeout_();
 
-  var timeout = ('timeout' in opt_options) ? opt_options.timeout : 10 * 1000;
-  if (timeout) {
-    this.hideTimeout_ = setTimeout(function() {
-      this.hideTimeout_ = null;
-      this.hide_();
-    }.bind(this), timeout);
-  }
-
   var butterMessage = this.butter_.querySelector('.butter-message');
    butterMessage.textContent = message;
   if (message && !this.isVisible_()) {
@@ -157,22 +155,28 @@
   } else {
     butterMessage.classList.remove('single-line');
   }
+
+  if (opt_options.timeout !== false)
+    this.hide_(opt_options.timeout);
 };
 
 /**
- * Hide butter bar. There might be some delay before hiding so that butter bar
+ * Hide butter bar. There might be the delay before hiding so that butter bar
  * would be shown for no less than the minimal time.
- * @param {boolean=} opt_force If true hide immediately, default false.
+ * @param {number=} opt_timeout Delay time in milliseconds before hidding. If it
+ *     is zero, butter bar is hidden immediatelly. If it is not specified,
+ *     HIDE_DELAY_TIME_MS_ is used.
  * @private
  */
-ButterBar.prototype.hide_ = function(opt_force) {
+ButterBar.prototype.hide_ = function(opt_timeout) {
   this.clearHideTimeout_();
 
   if (!this.isVisible_())
     return;
 
-  var delay = HIDE_DELAY_TIME_MS;
-  if (opt_force || delay <= 0) {
+  var delay = typeof opt_timeout != 'undefined' ?
+    opt_timeout : ButterBar.HIDE_DELAY_TIME_MS_;
+  if (delay <= 0) {
     this.currentMode_ = null;
     this.butter_.classList.remove('visible');
     this.butter_.querySelector('.progress-bar').hidden = true;
@@ -180,7 +184,7 @@
     // Reschedule hide to comply with the minimal display time.
     this.hideTimeout_ = setTimeout(function() {
       this.hideTimeout_ = null;
-      this.hide_(true);
+      this.hide_(0);
     }.bind(this), delay);
   }
 };
@@ -237,7 +241,11 @@
  */
 ButterBar.prototype.showProgress_ = function() {
   this.progress_ = this.copyManager_.getStatus();
-  var options = {progress: this.progress_.percentage, actions: {}, timeout: 0};
+  var options = {
+    progress: this.progress_.percentage,
+    actions: {},
+    timeout: false
+  };
 
   var type = this.transferType_();
   var progressString = (this.progress_.pendingItems === 1) ?
@@ -284,7 +292,7 @@
 
     case 'CANCELLED':
       this.show(ButterBar.Mode.DELETE,
-                str(this.transferType_() + '_CANCELLED'), { timeout: 1000 });
+                str(this.transferType_() + '_CANCELLED'));
       break;
 
     case 'ERROR':
@@ -345,7 +353,7 @@
       if (this.currentMode_ == ButterBar.Mode.DELETE)
         this.update_(title);
       else
-        this.show(ButterBar.Mode.DELETE, title, {timeout: 0});
+        this.show(ButterBar.Mode.DELETE, title);
       break;
 
     case 'SUCCESS':
diff --git a/chrome/browser/resources/file_manager/js/directory_model.js b/chrome/browser/resources/file_manager/js/directory_model.js
index 8780e0e..7520201 100644
--- a/chrome/browser/resources/file_manager/js/directory_model.js
+++ b/chrome/browser/resources/file_manager/js/directory_model.js
@@ -803,12 +803,13 @@
 /**
  * Resolves absolute directory path. Handles Drive stub. If the drive is
  * mounting, callbacks will be called after the mount is completed.
+ *
  * @param {string} path Path to the directory.
  * @param {function(DirectoryEntry} successCallback Success callback.
  * @param {function(FileError} errorCallback Error callback.
  */
-DirectoryModel.prototype.resolveDirectory = function(path, successCallback,
-                                                     errorCallback) {
+DirectoryModel.prototype.resolveDirectory = function(
+    path, successCallback, errorCallback) {
   if (PathUtil.getRootType(path) == RootType.DRIVE) {
     var driveStatus = this.volumeManager_.getDriveStatus();
     if (!this.isDriveMounted() &&
@@ -826,8 +827,24 @@
     return;
   }
 
+  var onError = function(error) {
+    // Handle the special case, when in offline mode, and there are no cached
+    // contents on the C++ side. In such case, let's display the stub.
+    // The INVALID_STATE_ERR error code is returned from the drive filesystem
+    // in such situation.
+    //
+    // TODO(mtomasz, hashimoto): Consider rewriting this logic.
+    //     crbug.com/253464.
+    if (PathUtil.getRootType(path) == RootType.DRIVE &&
+        error.code == FileError.INVALID_STATE_ERR) {
+      successCallback(DirectoryModel.fakeDriveEntry_);
+      return;
+    }
+    errorCallback(error);
+  }.bind(this);
+
   this.root_.getDirectory(path, {create: false},
-                          successCallback, errorCallback);
+                          successCallback, onError);
 };
 
 /**
diff --git a/chrome/browser/resources/file_manager/js/directory_tree.js b/chrome/browser/resources/file_manager/js/directory_tree.js
new file mode 100644
index 0000000..69710fb
--- /dev/null
+++ b/chrome/browser/resources/file_manager/js/directory_tree.js
@@ -0,0 +1,723 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+'use strict';
+
+////////////////////////////////////////////////////////////////////////////////
+// DirectoryTreeUtil
+
+/**
+ * Utility methods. They are intended for use only in this file.
+ */
+var DirectoryTreeUtil = {};
+
+/**
+ * Updates sub-elements of {@code parentElement} reading {@code DirectoryEntry}
+ * with calling {@code iterator}.
+ *
+ * @param {string} changedDirectryPath The path of the changed directory.
+ * @param {DirectoryItem|DirectoryTree} currentDirectoryItem An item to be
+ *     started traversal from.
+ */
+DirectoryTreeUtil.updateChangedDirectoryItem = function(
+    changedDirectryPath, currentDirectoryItem) {
+  if (changedDirectryPath === currentDirectoryItem.entry.fullPath) {
+    currentDirectoryItem.updateSubDirectories(false /* recursive */);
+    return;
+  }
+
+  for (var i = 0; i < currentDirectoryItem.items.length; i++) {
+    var item = currentDirectoryItem.items[i];
+    if (PathUtil.isParentPath(item.entry.fullPath, changedDirectryPath)) {
+      DirectoryTreeUtil.updateChangedDirectoryItem(changedDirectryPath, item);
+      break;
+    }
+  }
+};
+
+/**
+ * Updates sub-elements of {@code parentElement} reading {@code DirectoryEntry}
+ * with calling {@code iterator}.
+ *
+ * @param {DirectoryItem|DirectoryTree} parentElement Parent element of newly
+ *     created items.
+ * @param {function(number): DirectoryEntry} iterator Function which returns
+ *     the n-th Entry in the directory.
+ * @param {DirectoryModel} directoryModel Current DirectoryModel.
+ * @param {boolean} recursive True if the all visible sub-directories are
+ *     updated recursively including left arrows. If false, the update walks
+ *     only immediate child directories without arrows.
+ */
+DirectoryTreeUtil.updateSubElementsFromList = function(
+    parentElement, iterator, directoryModel, recursive) {
+  var index = 0;
+  while (iterator(index)) {
+    var currentEntry = iterator(index);
+    var currentElement = parentElement.items[index];
+
+    if (index >= parentElement.items.length) {
+      var item = new DirectoryItem(currentEntry, parentElement, directoryModel);
+      parentElement.add(item);
+      index++;
+    } else if (currentEntry.fullPath == currentElement.fullPath) {
+      if (recursive && parentElement.expanded)
+        currentElement.updateSubDirectories(true /* recursive */);
+
+      index++;
+    } else if (currentEntry.fullPath < currentElement.fullPath) {
+      var item = new DirectoryItem(currentEntry, parentElement, directoryModel);
+      parentElement.addAt(item, index);
+      index++;
+    } else if (currentEntry.fullPath > currentElement.fullPath) {
+      parentElement.remove(currentElement);
+    }
+  }
+
+  var removedChild;
+  while (removedChild = parentElement.items[index]) {
+    parentElement.remove(removedChild);
+  }
+
+  if (index == 0) {
+    parentElement.hasChildren = false;
+    parentElement.expanded = false;
+  } else {
+    parentElement.hasChildren = true;
+  }
+};
+
+/**
+ * Returns true if the given directory entry is dummy.
+ * @param {DirectoryEntry|Object} dirEntry DirectoryEntry to be checked.
+ * @return {boolean} True if the given directory entry is dummy.
+ */
+DirectoryTreeUtil.isDummyEntry = function(dirEntry) {
+  return !('createReader' in dirEntry);
+};
+
+/**
+ * Finds a parent directory of the {@code path} from the {@code items}, and
+ * invokes the DirectoryItem.selectPath() of the found directory.
+ *
+ * @param {Array.<DirectoryItem>} items Items to be searched.
+ * @param {string} path Path to be searched for.
+ * @return {boolean} True if the parent item is found.
+ */
+DirectoryTreeUtil.searchAndSelectPath = function(items, path) {
+  for (var i = 0; i < items.length; i++) {
+    var item = items[i];
+    if (PathUtil.isParentPath(item.entry.fullPath, path)) {
+      item.selectPath(path);
+      return true;
+    }
+  }
+  return false;
+};
+
+/**
+ * Modifies a list of the directory entries to match the new UI sepc.
+ *
+ * TODO(yoshiki): remove this after the old UI is removed.
+ *
+ * @param {Array.<DirectoryEntry>} entries The list of entty.
+ * @return {Array.<DirectoryEntries>} Modified entries.
+ */
+DirectoryTreeUtil.addAndRemoveDriveSpecialDirs = function(entries) {
+  var modifiedEntries = [];
+  for (var i in entries) {
+    // Removes '/drive/other'.
+    var entry = entries[i];
+    if (entry.fullPath ==
+        (RootDirectory.DRIVE + '/' + DriveSubRootDirectory.OTHER)) {
+      continue;
+    }
+
+    // Changes the label of '/drive/root' to 'My Drive'.
+    if (entry.fullPath == DirectoryModel.fakeDriveEntry_.fullPath) {
+      entry.label = str('DRIVE_MY_DRIVE_LABEL');
+    }
+
+    modifiedEntries.push(entry);
+  }
+
+  // Adds the special directories.
+  var specialDirs = DirectoryModel.FAKE_DRIVE_SPECIAL_SEARCH_ENTRIES;
+  for (var i in specialDirs) {
+    var dir = specialDirs[i];
+    dir['label'] = PathUtil.getRootLabel(dir.fullPath);
+    modifiedEntries.push(dir);
+  }
+  return modifiedEntries;
+};
+
+/**
+ * Retrieves the file list with the latest information.
+ *
+ * @param {DirectoryTree|DirectoryItem} item Parent to be reloaded.
+ * @param {DirectoryModel} dm The directory model.
+ * @param {function(Array.<Entry>)} successCallback Callback on success.
+ * @param {function()=} opt_errorCallback Callback on failure.
+ */
+DirectoryTreeUtil.updateSubDirectories = function(
+    item, dm, successCallback, opt_errorCallback) {
+  // Tries to retrieve new entry if the cached entry is dummy.
+  if (DirectoryTreeUtil.isDummyEntry(item.entry)) {
+    // Fake Drive root.
+    dm.resolveDirectory(
+        item.fullPath,
+        function(entry) {
+          item.dirEntry_ = entry;
+
+          // If the retrieved entry is dummy again, returns with an error.
+          if (DirectoryTreeUtil.isDummyEntry(entry)) {
+            if (opt_errorCallback)
+              opt_errorCallback();
+            return;
+          }
+
+          DirectoryTreeUtil.updateSubDirectories(
+              item, dm, successCallback, opt_errorCallback);
+        },
+        opt_errorCallback || function() {});
+    return;
+  }
+
+  var reader = item.entry.createReader();
+  var entries = [];
+  var readEntry = function() {
+    reader.readEntries(function(results) {
+      if (!results.length) {
+        if (item.entry.fullPath == RootDirectory.DRIVE)
+          successCallback(
+              DirectoryTreeUtil.addAndRemoveDriveSpecialDirs(entries));
+        else
+          successCallback(
+              DirectoryTreeUtil.sortEntries(item.fileFilter_, entries));
+        return;
+      }
+
+      for (var i = 0; i < results.length; i++) {
+        var entry = results[i];
+        if (entry.isDirectory)
+          entries.push(entry);
+      }
+      readEntry();
+    });
+  };
+  readEntry();
+};
+
+/**
+ * Sorts a list of entries.
+ *
+ * @param {FileFilter} fileFilter The file filter.
+ * @param {Array.<Entries>} entries Entries to be sorted.
+ * @return {Array.<Entries>} Sorted entries.
+ */
+DirectoryTreeUtil.sortEntries = function(fileFilter, entries) {
+  entries.sort(function(a, b) {
+    return (a.name.toLowerCase() > b.name.toLowerCase()) ? 1 : -1;
+  });
+  return entries.filter(fileFilter.filter.bind(fileFilter));
+};
+
+/**
+ * Checks if tre tree should be hidden on the given directory.
+ *
+ * @param {string} path Path to be checked.
+ * @return {boolean} True if the tree should NOT be visible on the given
+ *     directory. Otherwise, false.
+ */
+DirectoryTreeUtil.shouldHideTree = function(path) {
+  return !PathUtil.isDriveBasedPath(path);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// DirectoryItem
+
+/**
+ * A directory in the tree. Each element represents one directory.
+ *
+ * @param {DirectoryEntry} dirEntry DirectoryEntry of this item.
+ * @param {DirectoryItem|DirectoryTree} parentDirItem Parent of this item.
+ * @param {DirectoryModel} directoryModel Current DirectoryModel.
+ * @extends {cr.ui.TreeItem}
+ * @constructor
+ */
+function DirectoryItem(dirEntry, parentDirItem, directoryModel) {
+  var item = cr.doc.createElement('div');
+  DirectoryItem.decorate(item, dirEntry, parentDirItem, directoryModel);
+  return item;
+}
+
+/**
+ * @param {HTMLElement} el Element to be DirectoryItem.
+ * @param {DirectoryEntry} dirEntry DirectoryEntry of this item.
+ * @param {DirectoryItem|DirectoryTree} parentDirItem Parent of this item.
+ * @param {DirectoryModel} directoryModel Current DirectoryModel.
+ */
+DirectoryItem.decorate =
+    function(el, dirEntry, parentDirItem, directoryModel) {
+  el.__proto__ = DirectoryItem.prototype;
+  (/** @type {DirectoryItem} */ el).decorate(
+      dirEntry, parentDirItem, directoryModel);
+};
+
+DirectoryItem.prototype = {
+  __proto__: cr.ui.TreeItem.prototype,
+
+  /**
+   * The DirectoryEntry corresponding to this DirectoryItem. This may be
+   * a dummy DirectoryEntry.
+   * @type {DirectoryEntry|Object}
+   * @override
+   **/
+  get entry() {
+      return this.dirEntry_;
+  },
+
+  /**
+   * The element containing the label text and the icon.
+   * @type {!HTMLElement}
+   * @override
+   **/
+  get labelElement() {
+      return this.firstElementChild.querySelector('.label');
+  }
+};
+
+/**
+ * @param {DirectoryEntry} dirEntry DirectoryEntry of this item.
+ * @param {DirectoryItem|DirectoryTree} parentDirItem Parent of this item.
+ * @param {DirectoryModel} directoryModel Current DirectoryModel.
+ */
+DirectoryItem.prototype.decorate = function(
+    dirEntry, parentDirItem, directoryModel) {
+  var path = dirEntry.fullPath;
+  var label;
+  label = dirEntry.label ? dirEntry.label : dirEntry.name;
+
+  this.className = 'tree-item';
+  this.innerHTML =
+      '<div class="tree-row">' +
+      ' <span class="expand-icon"></span>' +
+      ' <span class="icon"></span>' +
+      ' <span class="label"></span>' +
+      ' <div class="root-eject"></div>' +
+      '</div>' +
+      '<div class="tree-children"></div>';
+  this.setAttribute('role', 'treeitem');
+
+  this.directoryModel_ = directoryModel;
+  this.parent_ = parentDirItem;
+  this.label = label;
+  this.fullPath = path;
+  this.dirEntry_ = dirEntry;
+  this.fileFilter_ = this.directoryModel_.getFileFilter();
+
+  // Sets hasChildren=false tentatively. This will be overridden after
+  // scanning sub-directories in DirectoryTreeUtil.updateSubElementsFromList.
+  this.hasChildren = false;
+
+  this.addEventListener('expand', this.onExpand_.bind(this), false);
+  var volumeManager = VolumeManager.getInstance();
+  var icon = this.querySelector('.icon');
+  icon.classList.add('volume-icon');
+  var iconType = PathUtil.getRootType(path);
+  if (iconType && PathUtil.isRootPath(path))
+    icon.setAttribute('volume-type-icon', iconType);
+  else
+    icon.setAttribute('file-type-icon', 'folder');
+
+  var eject = this.querySelector('.root-eject');
+  eject.hidden = !PathUtil.isUnmountableByUser(path);
+  eject.addEventListener('click',
+      function(event) {
+        event.stopPropagation();
+        if (!PathUtil.isUnmountableByUser(path))
+          return;
+
+        volumeManager.unmount(path, function() {}, function() {});
+      }.bind(this));
+
+  if (parentDirItem.expanded)
+    this.updateSubDirectories(false /* recursive */);
+};
+
+/**
+ * Overrides WebKit's scrollIntoViewIfNeeded, which doesn't work well with
+ * a complex layout. This call is not necessary, so we are ignoring it.
+ *
+ * @param {boolean} unused Unused.
+ * @override
+ */
+DirectoryItem.prototype.scrollIntoViewIfNeeded = function(unused) {
+};
+
+/**
+ * Removes the child node, but without selecting the parent item, to avoid
+ * unintended changing of directories. Removing is done externally, and other
+ * code will navigate to another directory.
+ *
+ * @param {!cr.ui.TreeItem} child The tree item child to remove.
+ * @override
+ */
+DirectoryItem.prototype.remove = function(child) {
+  this.lastElementChild.removeChild(child);
+  if (this.items.length == 0)
+    this.hasChildren = false;
+};
+
+/**
+ * Invoked when the item is being expanded.
+ * @param {!UIEvent} e Event.
+ * @private
+ **/
+DirectoryItem.prototype.onExpand_ = function(e) {
+  this.updateSubDirectories(
+      true /* recursive */,
+      function() {},
+      function() {
+        this.expanded = false;
+      }.bind(this));
+
+  e.stopPropagation();
+};
+
+/**
+ * Retrieves the latest subdirectories and update them on the tree.
+ * @param {boolean} recursive True if the update is recursively.
+ * @param {function()=} opt_successCallback Callback called on success.
+ * @param {function()=} opt_errorCallback Callback called on error.
+ */
+DirectoryItem.prototype.updateSubDirectories = function(
+    recursive, opt_successCallback, opt_errorCallback) {
+  DirectoryTreeUtil.updateSubDirectories(
+      this,
+      this.directoryModel_,
+      function(entries) {
+        this.entries_ = entries;
+        this.redrawSubDirectoryList_(recursive);
+        opt_successCallback && opt_successCallback();
+      }.bind(this),
+      opt_errorCallback);
+};
+
+/**
+ * Redraw subitems with the latest information. The items are sorted in
+ * alphabetical order, case insensitive.
+ * @param {boolean} recursive True if the update is recursively.
+ * @private
+ */
+DirectoryItem.prototype.redrawSubDirectoryList_ = function(recursive) {
+  DirectoryTreeUtil.updateSubElementsFromList(
+      this,
+      function(i) { return this.entries_[i]; }.bind(this),
+      this.directoryModel_,
+      recursive);
+};
+
+/**
+ * Select the item corresponding to the given {@code path}.
+ * @param {string} path Path to be selected.
+ */
+DirectoryItem.prototype.selectPath = function(path) {
+  if (path == this.fullPath) {
+    this.selected = true;
+    return;
+  }
+
+  if (DirectoryTreeUtil.searchAndSelectPath(this.items, path))
+    return;
+
+  // If the path doesn't exist, updates sub directories and tryes again.
+  this.updateSubDirectories(
+      false /* recursive */,
+      DirectoryTreeUtil.searchAndSelectPath.bind(null, this.items, path));
+};
+
+/**
+ * Executes the assigned action as a drop target.
+ */
+DirectoryItem.prototype.doDropTargetAction = function() {
+  this.expanded = true;
+};
+
+/**
+ * Executes the assigned action. DirectoryItem performs changeDirectory.
+ */
+DirectoryItem.prototype.doAction = function() {
+  if (this.fullPath != this.directoryModel_.getCurrentDirPath())
+    this.directoryModel_.changeDirectory(this.fullPath);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// DirectoryTree
+
+/**
+ * Tree of directories on the sidebar. This element is also the root of items,
+ * in other words, this is the parent of the top-level items.
+ *
+ * @constructor
+ * @extends {cr.ui.Tree}
+ */
+function DirectoryTree() {}
+
+/**
+ * Decorates an element.
+ * @param {HTMLElement} el Element to be DirectoryTree.
+ * @param {DirectoryModel} directoryModel Current DirectoryModel.
+ */
+DirectoryTree.decorate = function(el, directoryModel) {
+  el.__proto__ = DirectoryTree.prototype;
+  (/** @type {DirectoryTree} */ el).decorate(directoryModel);
+};
+
+DirectoryTree.prototype = {
+  __proto__: cr.ui.Tree.prototype,
+
+  // DirectoryTree is always expanded.
+  get expanded() { return true; },
+  /**
+   * @param {boolean} value Not used.
+   */
+  set expanded(value) {},
+
+  /**
+   * The DirectoryEntry corresponding to this DirectoryItem. This may be
+   * a dummy DirectoryEntry.
+   * @type {DirectoryEntry|Object}
+   * @override
+   **/
+  get entry() {
+      return this.dirEntry_;
+  }
+};
+
+/**
+ * Decorates an element.
+ * @param {DirectoryModel} directoryModel Current DirectoryModel.
+ */
+DirectoryTree.prototype.decorate = function(directoryModel) {
+  cr.ui.Tree.prototype.decorate.call(this);
+
+  this.directoryModel_ = directoryModel;
+  this.entries_ = [];
+
+  this.fileFilter_ = this.directoryModel_.getFileFilter();
+  this.fileFilter_.addEventListener('changed',
+                                    this.onFilterChanged_.bind(this));
+  /**
+   * The path of the root directory.
+   * @type {string}
+   */
+  this.fullPath = '/';
+  this.dirEntry_ = null;
+
+  /**
+   * The path of the current directory.
+   * @type {string}
+   */
+  this.currentPath_ = null;
+
+  this.directoryModel_.addEventListener('directory-changed',
+      this.onCurrentDirectoryChanged_.bind(this));
+
+  // Add a handler for directory change.
+  this.addEventListener('change', function() {
+    if (this.selectedItem && this.currentPath_ != this.selectedItem.fullPath) {
+      this.currentPath_ = this.selectedItem.fullPath;
+      this.selectedItem.doAction();
+      return;
+    }
+  }.bind(this));
+
+  this.privateOnDirectoryChangedBound_ =
+      this.onDirectoryContentChanged_.bind(this);
+  chrome.fileBrowserPrivate.onDirectoryChanged.addListener(
+      this.privateOnDirectoryChangedBound_);
+
+  this.scrollBar_ = MainPanelScrollBar();
+  this.scrollBar_.initialize(this.parentNode, this);
+};
+
+/**
+ * Select the item corresponding to the given path.
+ * @param {string} path Path to be selected.
+ */
+DirectoryTree.prototype.selectPath = function(path) {
+  if ((this.entry && this.entry.fullPath == path) || this.currentPath_ == path)
+    return;
+  this.currentPath_ = path;
+  if (DirectoryTreeUtil.shouldHideTree(path))
+    return;
+
+  this.selectPathInternal_(path);
+};
+
+/**
+ * Select the item corresponding to the given path. This method is used
+ * internally.
+ * @param {string} path Path to be selected.
+ * @private
+ */
+DirectoryTree.prototype.selectPathInternal_ = function(path) {
+  var rootDirPath = PathUtil.getRootPath(path);
+
+  if (PathUtil.isSpecialSearchRoot(rootDirPath) ||
+      PathUtil.getRootType(rootDirPath) == RootType.DRIVE) {
+    rootDirPath = RootDirectory.DRIVE;
+  }
+
+  var onError = function() {
+    this.clearTree_(true);
+  }.bind(this);
+
+  if (this.fullPath != rootDirPath || !this.dirEntry_) {
+    this.fullPath = rootDirPath;
+
+    this.directoryModel_.resolveDirectory(
+        rootDirPath,
+        function(entry) {
+          if (this.fullPath != rootDirPath)
+            return;
+
+          this.dirEntry_ = entry;
+          this.selectPathInternal_(path);
+        }.bind(this),
+        onError);
+  } else {
+    if (this.selectedItem && path == this.selectedItem.fullPath)
+      return;
+
+    if (DirectoryTreeUtil.searchAndSelectPath(this.items, path))
+      return;
+
+    this.selectedItem = null;
+    this.updateSubDirectories(
+        false /* recursive */,
+        function() {
+          if (!DirectoryTreeUtil.searchAndSelectPath(
+              this.items, this.currentPath_))
+            this.selectedItem = null;
+          cr.dispatchSimpleEvent(this, 'content-updated');
+        }.bind(this),
+        onError);
+  }
+};
+
+/**
+ * Retrieves the latest subdirectories and update them on the tree.
+ * @param {boolean} recursive True if the update is recursively.
+ * @param {function()=} opt_successCallback Callback called on success.
+ * @param {function()=} opt_errorCallback Callback called on error.
+ */
+DirectoryTree.prototype.updateSubDirectories = function(
+    recursive, opt_successCallback, opt_errorCallback) {
+  if (!this.currentPath_)
+    return;
+
+  DirectoryTreeUtil.updateSubDirectories(
+      this,
+      this.directoryModel_,
+      function(entries) {
+        this.entries_ = entries;
+        this.redraw(recursive);
+        if (opt_successCallback)
+          opt_successCallback();
+      }.bind(this),
+      opt_errorCallback);
+};
+
+/**
+ * Redraw the list.
+ * @param {boolean} recursive True if the update is recursively. False if the
+ *     only root items are updated.
+ */
+DirectoryTree.prototype.redraw = function(recursive) {
+  DirectoryTreeUtil.updateSubElementsFromList(
+      this,
+      function(i) { return this.entries_[i]; }.bind(this),
+      this.directoryModel_,
+      recursive);
+};
+
+/**
+ * Invoked when the filter is changed.
+ * @private
+ */
+DirectoryTree.prototype.onFilterChanged_ = function() {
+  // Returns immediately, if the tree is hidden.
+  if (!this.currentPath_ || DirectoryTreeUtil.shouldHideTree(this.currentPath_))
+    return;
+
+  this.redraw(true /* recursive */);
+  cr.dispatchSimpleEvent(this, 'content-updated');
+};
+
+/**
+ * Invoked when a directory is changed.
+ * @param {!UIEvent} event Event.
+ * @private
+ */
+DirectoryTree.prototype.onDirectoryContentChanged_ = function(event) {
+  // Returns immediately, if the tree is hidden.
+  if (!this.currentPath_ || DirectoryTreeUtil.shouldHideTree(this.currentPath_))
+    return;
+
+  if (event.eventType == 'changed') {
+    var path = util.extractFilePath(event.directoryUrl);
+    DirectoryTreeUtil.updateChangedDirectoryItem(path, this);
+  }
+};
+
+/**
+ * Invoked when the current directory is changed.
+ * @param {!UIEvent} event Event.
+ * @private
+ */
+DirectoryTree.prototype.onCurrentDirectoryChanged_ = function(event) {
+  this.selectPath(event.newDirEntry.fullPath);
+};
+
+/**
+ * Returns the path of the selected item.
+ * @return {string} The current path.
+ */
+DirectoryTree.prototype.getCurrentPath = function() {
+  return this.selectedItem ? this.selectedItem.fullPath : null;
+};
+
+/**
+ * Clears the tree.
+ * @param {boolean} redraw Redraw the tree if true.
+ * @private
+ */
+DirectoryTree.prototype.clearTree_ = function(redraw) {
+  this.dirEntry_ = null;
+  this.fullPath = '';
+  this.selectedItem = null;
+  this.entries_ = [];
+
+  if (redraw) {
+    this.redraw(false);
+    cr.dispatchSimpleEvent(this, 'content-updated');
+  }
+};
+
+/**
+ * Sets the margin height for the transparent preview panel at the bottom.
+ * @param {number} margin Margin to be set in px.
+ */
+DirectoryTree.prototype.setBottomMarginForPanel = function(margin) {
+  this.style.paddingBottom = margin + 'px';
+  this.scrollBar_.setBottomMarginForPanel(margin);
+};
+
+/**
+ * Updates the UI after the layout has changed.
+ */
+DirectoryTree.prototype.relayout = function() {
+  cr.dispatchSimpleEvent(this, 'relayout');
+};
diff --git a/chrome/browser/resources/file_manager/js/drag_selector.js b/chrome/browser/resources/file_manager/js/drag_selector.js
index 93bf1c5..9766c6e 100644
--- a/chrome/browser/resources/file_manager/js/drag_selector.js
+++ b/chrome/browser/resources/file_manager/js/drag_selector.js
@@ -238,7 +238,10 @@
       'mousemove', this.onMouseMoveBound_, true);
   this.target_.ownerDocument.removeEventListener(
       'mouseup', this.onMouseUpBound_, true);
+  cr.dispatchSimpleEvent(this.target_, 'dragselectionend');
   this.target_.cachedBounds = null;
-  event.stopPropagation();
   this.target_ = null;
+  // The target may select an item by reacting to the mouseup event.
+  // This surpress to the selecting behavior.
+  event.stopPropagation();
 };
diff --git a/chrome/browser/resources/file_manager/js/file_copy_manager.js b/chrome/browser/resources/file_manager/js/file_copy_manager.js
index d4dbc83..1cf24d7 100644
--- a/chrome/browser/resources/file_manager/js/file_copy_manager.js
+++ b/chrome/browser/resources/file_manager/js/file_copy_manager.js
@@ -120,7 +120,7 @@
     // traversal order, we just keep the ordering.
     if (this.pendingDirectories.length)
       nextEntry = this.pendingDirectories[0];
-    if (this.pendingFiles.length)
+    else if (this.pendingFiles.length)
       nextEntry = this.pendingFiles[0];
   }
   if (nextEntry)
diff --git a/chrome/browser/resources/file_manager/js/file_grid.js b/chrome/browser/resources/file_manager/js/file_grid.js
index afe0c50..281c466 100644
--- a/chrome/browser/resources/file_manager/js/file_grid.js
+++ b/chrome/browser/resources/file_manager/js/file_grid.js
@@ -144,8 +144,10 @@
         new ThumbnailLoader(imageUrl,
                             ThumbnailLoader.LoaderType.IMAGE,
                             metadata,
-                            undefined,
-                            ThumbnailLoader.UseEmbedded.NO_EMBEDDED).
+                            undefined,  // opt_mediaType
+                            FileType.isOnDrive(imageUrl) ?
+                                ThumbnailLoader.UseEmbedded.USE_EMBEDDED :
+                                ThumbnailLoader.UseEmbedded.NO_EMBEDDED).
             load(box,
                 fillMode,
                 ThumbnailLoader.OptimizationMode.DISCARD_DETACHED,
diff --git a/chrome/browser/resources/file_manager/js/file_manager.js b/chrome/browser/resources/file_manager/js/file_manager.js
index fb53dd0..07ce252 100644
--- a/chrome/browser/resources/file_manager/js/file_manager.js
+++ b/chrome/browser/resources/file_manager/js/file_manager.js
@@ -193,9 +193,9 @@
       spaceInnerBar.style.width =
           (100 * usedSpace / sizeStatsResult.totalSizeKB) + '%';
 
-      spaceOuterBar.style.display = '';
+      spaceOuterBar.hidden = false;
     } else {
-      spaceOuterBar.style.display = 'none';
+      spaceOuterBar.hidden = true;
       spaceInfoLabel.textContent = str('FAILED_SPACE_INFO');
     }
   };
@@ -320,9 +320,6 @@
               this.viewOptions_[key] = window.appState.viewOptions[key];
           }
         }
-        // TODO(hirono): Remove this line after the user test.
-        // crbug.com/249242
-        this.noCheckboxes_ = !!this.viewOptions_.noCheckboxes;
         done();
       }.bind(this));
     }.bind(this));
@@ -330,10 +327,8 @@
     // Get the command line option.
     group.add(function(done) {
       chrome.commandLinePrivate.hasSwitch(
-          'file-manager-no-checkboxes', function(flag) {
-        // TODO(hirono): Update this line after the user test.
-        // crbug.com/249242
-        this.noCheckboxes_ = this.noCheckboxes_ || flag;
+          'file-manager-show-checkboxes', function(flag) {
+        this.showCheckboxes_ = flag;
         done();
       }.bind(this));
     }.bind(this));
@@ -583,6 +578,14 @@
     this.hostedButton.checkable = true;
     this.detailViewButton_.checkable = true;
     this.thumbnailViewButton_.checkable = true;
+
+    if (util.platform.runningInBrowser()) {
+      // Supresses the default context menu.
+      this.dialogDom_.addEventListener('contextmenu', function(e) {
+        e.preventDefault();
+        e.stopPropagation();
+      });
+    }
   };
 
   FileManager.prototype.onMaximize = function() {
@@ -630,7 +633,7 @@
         Commands.newFolderCommand, this, this.directoryModel_);
 
     CommandUtil.registerCommand(doc, 'newwindow',
-        Commands.newWindowCommand, this);
+        Commands.newWindowCommand, this, this.directoryModel_);
 
     CommandUtil.registerCommand(doc, 'change-default-app',
         Commands.changeDefaultAppCommand, this);
@@ -678,6 +681,8 @@
     CommandUtil.registerCommand(doc, 'zip-selection',
         Commands.zipSelectionCommand, this, this.directoryModel_);
 
+    CommandUtil.registerCommand(doc, 'share', Commands.shareCommand, this);
+
     CommandUtil.registerCommand(doc, 'search', Commands.searchCommand, this,
         this.dialogDom_.querySelector('#search-box'));
 
@@ -691,6 +696,10 @@
                                   i);
     }
 
+    CommandUtil.registerCommand(doc, 'zoom-in', Commands.zoomInCommand);
+    CommandUtil.registerCommand(doc, 'zoom-out', Commands.zoomOutCommand);
+    CommandUtil.registerCommand(doc, 'zoom-reset', Commands.zoomResetCommand);
+
     CommandUtil.registerCommand(doc, 'cut', Commands.defaultCommand, doc);
     CommandUtil.registerCommand(doc, 'copy', Commands.defaultCommand, doc);
 
@@ -789,11 +798,19 @@
    * @private
    */
   FileManager.prototype.initStrings_ = function(callback) {
-    chrome.fileBrowserPrivate.getStrings(function(strings) {
-      loadTimeData.data = strings;
-      this.loadTimeDataAvailable = true;
-      callback();
-    });
+    // Fetch the strings via the private api if running in the browser window.
+    // Otherwise, read cached strings from the local storage.
+    if (util.platform.runningInBrowser()) {
+      chrome.fileBrowserPrivate.getStrings(function(strings) {
+        loadTimeData.data = strings;
+        callback();
+      });
+    } else {
+      chrome.storage.local.get('strings', function(items) {
+        loadTimeData.data = items['strings'];
+        callback();
+      });
+    }
   };
 
   /**
@@ -832,8 +849,18 @@
 
     this.metadataCache_ = MetadataCache.createFull();
 
-    this.okButton_ = this.dialogDom_.querySelector('.ok');
-    this.cancelButton_ = this.dialogDom_.querySelector('.cancel');
+    this.hasFooterPanel_ =
+        this.dialogType == DialogType.SELECT_SAVEAS_FILE ||
+        this.dialogType == DialogType.SELECT_FOLDER;
+
+    // If the footer panel exists, the buttons are placed there. Otherwise,
+    // the buttons are on the preview panel.
+    var parentPanelOfButtons = this.dialogDom_.querySelector(
+        !this.hasFooterPanel_ ? '.preview-panel' : '.dialog-footer');
+    parentPanelOfButtons.classList.add('button-panel');
+    this.fileTypeSelector_ = parentPanelOfButtons.querySelector('.file-type');
+    this.okButton_ = parentPanelOfButtons.querySelector('.ok');
+    this.cancelButton_ = parentPanelOfButtons.querySelector('.cancel');
 
     // Pre-populate the static localized strings.
     i18nTemplate.process(this.document_, loadTimeData);
@@ -896,7 +923,7 @@
     this.table_ = dom.querySelector('.detail-table');
     this.grid_ = dom.querySelector('.thumbnail-grid');
     this.spinner_ = dom.querySelector('#spinner-with-text');
-    this.showSpinner_(false);
+    this.showSpinner_(true);
 
     this.searchBreadcrumbs_ = new BreadcrumbsController(
          dom.querySelector('#search-breadcrumbs'), this.metadataCache_);
@@ -905,7 +932,7 @@
     this.searchBreadcrumbs_.setHideLast(false);
 
     // Check the option to hide the selecting checkboxes.
-    this.table_.noCheckboxes = this.noCheckboxes_;
+    this.table_.showCheckboxes = this.showCheckboxes_;
 
     var fullPage = this.dialogType == DialogType.FULL_PAGE;
     FileTable.decorate(this.table_, this.metadataCache_, fullPage);
@@ -977,9 +1004,6 @@
     this.dialogDom_.ownerDocument.defaultView.addEventListener(
         'resize', this.onResize_.bind(this));
 
-    if (loadTimeData.getBoolean('ASH'))
-      this.dialogDom_.setAttribute('ash', 'true');
-
     this.filePopup_ = null;
 
     this.searchBoxWrapper_ =
@@ -1066,7 +1090,6 @@
     this.defaultActionMenuItem_.addEventListener('activate',
         this.dispatchSelectionAction_.bind(this));
 
-    this.fileTypeSelector_ = this.dialogDom_.querySelector('#file-type');
     this.initFileTypeFilter_();
 
     util.addIsFocusedMethod();
@@ -1163,6 +1186,9 @@
     var dragEndBound = this.onDragEnd_.bind(this);
     this.table_.list.addEventListener('dragend', dragEndBound);
     this.grid_.addEventListener('dragend', dragEndBound);
+    // This event is published by DragSelector because drag end event is not
+    // published at the end of drag selection.
+    this.table_.list.addEventListener('dragselectionend', dragEndBound);
 
     // TODO(mtomasz, yoshiki): Create sidebar earlier, and here just attach
     // the directory model.
@@ -1250,9 +1276,7 @@
       sortField: sortStatus.field,
       sortDirection: sortStatus.direction,
       columns: [],
-      listType: this.listType_,
-      // TODO(hirono): Remove this line after the user test. crbug.com/249242
-      noCheckboxes: !!this.noCheckboxes_
+      listType: this.listType_
     };
     var cm = this.table_.columnModel;
     for (var i = 0; i < cm.totalSize; i++) {
@@ -1333,11 +1357,11 @@
     if (type == FileManager.ListType.DETAIL) {
       this.table_.dataModel = this.directoryModel_.getFileList();
       this.table_.selectionModel = this.directoryModel_.getFileListSelection();
-      this.table_.style.display = '';
-      this.grid_.style.display = 'none';
+      this.table_.hidden = false;
+      this.grid_.hidden = true;
       this.grid_.selectionModel = this.emptySelectionModel_;
       this.grid_.dataModel = this.emptyDataModel_;
-      this.table_.style.display = '';
+      this.table_.hidden = false;
       /** @type {cr.ui.List} */
       this.currentList_ = this.table_.list;
       this.detailViewButton_.setAttribute('checked', '');
@@ -1347,11 +1371,11 @@
     } else if (type == FileManager.ListType.THUMBNAIL) {
       this.grid_.dataModel = this.directoryModel_.getFileList();
       this.grid_.selectionModel = this.directoryModel_.getFileListSelection();
-      this.grid_.style.display = '';
-      this.table_.style.display = 'none';
+      this.grid_.hidden = false;
+      this.table_.hidden = true;
       this.table_.selectionModel = this.emptySelectionModel_;
       this.table_.dataModel = this.emptyDataModel_;
-      this.grid_.style.display = '';
+      this.grid_.hidden = false;
       /** @type {cr.ui.List} */
       this.currentList_ = this.grid_;
       this.thumbnailViewButton_.setAttribute('checked', '');
@@ -1537,7 +1561,10 @@
       this.grid_.relayout();
     else
       this.table_.relayout();
-    this.directoryTree_.relayout();
+
+    // May not be available during initialization.
+    if (this.directoryTree_)
+      this.directoryTree_.relayout();
 
     // TODO(mtomasz, yoshiki): Initialize volume list earlier, before
     // file system is available.
@@ -1558,11 +1585,8 @@
    */
   FileManager.prototype.onPreviewPanelVisibilityChanged_ = function(visible) {
     var panelHeight = visible ? this.getPreviewPanelHeight_() : 0;
-
-    if (this.listType_ == FileManager.ListType.THUMBNAIL)
-      this.grid_.setBottomMarginForPanel(panelHeight);
-    else
-      this.table_.setBottomMarginForPanel(panelHeight);
+    this.grid_.setBottomMarginForPanel(panelHeight);
+    this.table_.setBottomMarginForPanel(panelHeight);
     this.directoryTree_.setBottomMarginForPanel(panelHeight);
   };
 
@@ -1770,10 +1794,6 @@
     }
 
     this.okButton_.textContent = okLabel;
-
-    var dialogTitle = this.params_.title || defaultTitle;
-    this.dialogDom_.querySelector('.dialog-title').textContent = dialogTitle;
-
     this.dialogDom_.setAttribute('type', this.dialogType);
   };
 
@@ -2164,6 +2184,9 @@
         this.directoryModel_.getCurrentDirEntry();
   };
 
+  /**
+   * Deletes the selected file and directories recursively.
+   */
   FileManager.prototype.deleteSelection = function() {
     // TODO(mtomasz): Remove this temporary dialog. crbug.com/167364
     var entries = this.getSelection().entries;
@@ -2175,6 +2198,17 @@
     }.bind(this));
   };
 
+  /**
+   * Shows the share dialog for the selected file.
+   */
+  FileManager.prototype.shareSelection = function() {
+    // TODO(mtomasz): Implement it. crbug.com/141396
+  };
+
+  /**
+   * Blinks the selection. Used to give feedback when copying or cutting the
+   * selection.
+   */
   FileManager.prototype.blinkSelection = function() {
     var selection = this.getSelection();
     if (!selection || selection.totalCount == 0)
@@ -2615,15 +2649,18 @@
       clearTimeout(this.scanCompletedTimer_);
       this.scanCompletedTimer_ = null;
     }
+
     if (this.scanUpdatedTimer_) {
       clearTimeout(this.scanUpdatedTimer_);
       this.scanUpdatedTimer_ = null;
     }
 
-    this.cancelSpinnerTimeout_();
-    this.showSpinner_(false);
-    this.showSpinnerTimeout_ =
-        setTimeout(this.showSpinner_.bind(this, true), 500);
+    if (!this.spinner_.hidden) {
+      this.cancelSpinnerTimeout_();
+      this.showSpinner_(false);
+      this.showSpinnerTimeout_ =
+          setTimeout(this.showSpinner_.bind(this, true), 500);
+    }
   };
 
   /**
@@ -3072,7 +3109,7 @@
 
     var shade = this.document_.createElement('div');
     shade.className = 'shade';
-    var footer = this.document_.querySelector('.dialog-footer');
+    var footer = this.dialogDom_.querySelector('.button-panel');
     var progress = footer.querySelector('.progress-track');
     progress.style.width = '0%';
     var cancelled = false;
@@ -3802,15 +3839,4 @@
     this.document_.querySelector('#drive-clear-local-cache').canExecuteChange();
     this.document_.querySelector('#drive-reload').canExecuteChange();
   };
-
-  /**
-   * Set the flag to hide the selecting checkboxes.
-   * This is the alternative for about:flags and to be removed.
-   * TODO(hirono): Remove this function after the user test.
-   * @param {boolean} flag If it's true, the selecting checkboxes are hidden.
-   */
-  window.setNoCheckboxesFlag = function(flag) {
-    fileManager.noCheckboxes_ = flag;
-    fileManager.updateStartupPrefs_();
-  };
 })();
diff --git a/chrome/browser/resources/file_manager/js/file_manager_commands.js b/chrome/browser/resources/file_manager/js/file_manager_commands.js
index b05960e..5e1e0b7 100644
--- a/chrome/browser/resources/file_manager/js/file_manager_commands.js
+++ b/chrome/browser/resources/file_manager/js/file_manager_commands.js
@@ -71,6 +71,14 @@
 };
 
 /**
+ * Sets as the command as always enabled.
+ * @param {Event} event Command event to mark.
+ */
+CommandUtil.canExecuteAlways = function(event) {
+  event.canExecute = true;
+};
+
+/**
  * Returns a single selected/passed entry or null.
  * @param {Event} event Command event.
  * @param {FileManager} fileManager FileManager to use.
@@ -239,8 +247,9 @@
   },
   canExecute: function(event, fileManager, directoryModel) {
     event.canExecute = !fileManager.isOnReadonlyDirectory() &&
+                       !fileManager.isRenamingInProgress() &&
                        !directoryModel.isSearching() &&
-                       !fileManager.isRenamingInProgress();
+                       !directoryModel.isScanning();
   }
 };
 
@@ -248,8 +257,13 @@
  * Initiates new window creation.
  */
 Commands.newWindowCommand = {
-  execute: function(event, fileManager) {
-    chrome.fileBrowserPrivate.openNewWindow(document.location.href);
+  execute: function(event, fileManager, directoryModel) {
+    chrome.runtime.getBackgroundPage(function(background) {
+      var appState = {
+        defaultPath: directoryModel.getCurrentDirPath()
+      };
+      background.launchFileManager(appState);
+    });
   },
   canExecute: function(event, fileManager) {
     event.canExecute = (fileManager.dialogType == DialogType.FULL_PAGE);
@@ -263,9 +277,7 @@
   execute: function(event, fileManager) {
     fileManager.showChangeDefaultAppPicker();
   },
-  canExecute: function(event, fileManager) {
-    event.canExecute = true;
-  }
+  canExecute: CommandUtil.canExecuteAlways
 };
 
 /**
@@ -317,13 +329,11 @@
 Commands.volumeHelpCommand = {
   execute: function() {
     if (fileManager.isOnDrive())
-      chrome.tabs.create({ url: FileManager.GOOGLE_DRIVE_HELP });
+      chrome.windows.create({url: FileManager.GOOGLE_DRIVE_HELP});
     else
-      chrome.tabs.create({ url: FileManager.FILES_APP_HELP });
+      chrome.windows.create({url: FileManager.FILES_APP_HELP});
   },
-  canExecute: function(event, fileManager) {
-    event.canExecute = true;
-  }
+  canExecute: CommandUtil.canExecuteAlways
 };
 
 /**
@@ -331,7 +341,7 @@
  */
 Commands.driveBuySpaceCommand = {
   execute: function() {
-    chrome.tabs.create({ url: FileManager.GOOGLE_DRIVE_BUY_STORAGE });
+    chrome.windows.create({url: FileManager.GOOGLE_DRIVE_BUY_STORAGE});
   },
   canExecute: CommandUtil.canExecuteVisibleOnDriveOnly
 };
@@ -361,7 +371,7 @@
  */
 Commands.driveGoToDriveCommand = {
   execute: function() {
-    chrome.tabs.create({ url: FileManager.GOOGLE_DRIVE_ROOT });
+    chrome.windows.create({url: FileManager.GOOGLE_DRIVE_ROOT});
   },
   canExecute: CommandUtil.canExecuteVisibleOnDriveOnly
 };
@@ -418,42 +428,93 @@
 Commands.togglePinnedCommand = {
   execute: function(event, fileManager) {
     var pin = !event.command.checked;
-    var entry = CommandUtil.getSingleEntry(event, fileManager);
-
-    var showError = function(filesystem) {
-      fileManager.alert.showHtml(str('DRIVE_OUT_OF_SPACE_HEADER'),
-          strf('DRIVE_OUT_OF_SPACE_MESSAGE',
-               unescape(entry.name),
-               util.bytesToString(filesystem.size)));
-    };
-
-    var callback = function() {
-      if (chrome.runtime.lastError && pin) {
-        fileManager.metadataCache_.get(entry, 'filesystem', showError);
-      }
-      // We don't have update events yet, so clear the cached data.
-      fileManager.metadataCache_.clear(entry, 'drive');
-      fileManager.metadataCache_.get(entry, 'drive', function(drive) {
-        fileManager.updateMetadataInUI_('drive', [entry.toURL()], [drive]);
-      });
-    };
-
-    chrome.fileBrowserPrivate.pinDriveFile(entry.toURL(), pin, callback);
     event.command.checked = pin;
-  },
-  canExecute: function(event, fileManager) {
-    var entry = CommandUtil.getSingleEntry(event, fileManager);
-    var drive = entry && fileManager.metadataCache_.getCached(entry, 'drive');
+    var entries = this.getTargetEntries_();
+    var currentEntry;
+    var error = false;
+    var steps = {
+      // Pick an entry and pin it.
+      start: function() {
+        // Check if all the entries are pinned or not.
+        if (entries.length == 0)
+          return;
+        currentEntry = entries.shift();
+        chrome.fileBrowserPrivate.pinDriveFile(
+            currentEntry.toURL(),
+            pin,
+            steps.entryPinned);
+      },
 
-    if (!fileManager.isOnDrive() || !entry || entry.isDirectory || !drive ||
-        drive.hosted) {
-      event.canExecute = false;
-      event.command.setHidden(true);
-    } else {
+      // Check the result of pinning
+      entryPinned: function() {
+        // Convert to boolean.
+        error = !!chrome.runtime.lastError;
+        if (error && pin) {
+          fileManager.metadataCache_.get(
+              currentEntry, 'filesystem', steps.showError);
+        }
+        fileManager.metadataCache_.clear(currentEntry, 'drive');
+        fileManager.metadataCache_.get(
+            currentEntry, 'drive', steps.updateUI.bind(this));
+      },
+
+      // Update the user interface accoding to the cache state.
+      updateUI: function(drive) {
+        fileManager.updateMetadataInUI_(
+            'drive', [currentEntry.toURL()], [drive]);
+        if (!error)
+          steps.start();
+      },
+
+      // Show the error
+      showError: function(filesystem) {
+        fileManager.alert.showHtml(str('DRIVE_OUT_OF_SPACE_HEADER'),
+                                   strf('DRIVE_OUT_OF_SPACE_MESSAGE',
+                                        unescape(currentEntry.name),
+                                        util.bytesToString(filesystem.size)));
+      }
+    };
+    steps.start();
+  },
+
+  canExecute: function(event, fileManager) {
+    var entries = this.getTargetEntries_();
+    var checked = true;
+    for (var i = 0; i < entries.length; i++) {
+      checked = checked && entries[i].pinned;
+    }
+    if (entries.length > 0) {
       event.canExecute = true;
       event.command.setHidden(false);
-      event.command.checked = drive.pinned;
+      event.command.checked = checked;
+    } else {
+      event.canExecute = false;
+      event.command.setHidden(true);
     }
+  },
+
+  /**
+   * Obtains target entries from the selection.
+   * If directories are included in the selection, it just returns an empty
+   * array to avoid confusing because pinning directory is not supported
+   * currently.
+   *
+   * @return {Array.<Entry>} Target entries.
+   * @private
+   */
+  getTargetEntries_: function() {
+    var hasDirectory = false;
+    var results = fileManager.getSelection().entries.filter(function(entry) {
+      hasDirectory = hasDirectory || entry.isDirectory;
+      if (!entry || hasDirectory)
+        return false;
+      var metadata = fileManager.metadataCache_.getCached(entry, 'drive');
+        if (!metadata || metadata.hosted)
+          return false;
+      entry.pinned = metadata.pinned;
+      return true;
+    });
+    return hasDirectory ? [] : results;
   }
 };
 
@@ -474,3 +535,49 @@
         selection && selection.totalCount > 0;
   }
 };
+
+/**
+ * Shows the share dialog for the current selection (single only).
+ */
+Commands.shareCommand = {
+  execute: function(event, fileManager) {
+    fileManager.shareSelection();
+  },
+  canExecute: function(event, fileManager) {
+    var selection = fileManager.getSelection();
+    event.canExecute = fileManager.isOnDrive() &&
+        !fileManager.isDriveOffline() &&
+        selection && selection.totalCount == 1;
+    event.command.setHidden(!fileManager.isOnDrive());
+  }
+};
+
+/**
+ * Zoom in to the Files.app.
+ */
+Commands.zoomInCommand = {
+  execute: function(event) {
+    chrome.fileBrowserPrivate.zoom('in');
+  },
+  canExecute: CommandUtil.canExecuteAlways
+};
+
+/**
+ * Zoom out from the Files.app.
+ */
+Commands.zoomOutCommand = {
+  execute: function(event) {
+    chrome.fileBrowserPrivate.zoom('out');
+  },
+  canExecute: CommandUtil.canExecuteAlways
+};
+
+/**
+ * Reset the zoom factor.
+ */
+Commands.zoomResetCommand = {
+  execute: function(event) {
+    chrome.fileBrowserPrivate.zoom('reset');
+  },
+  canExecute: CommandUtil.canExecuteAlways
+};
diff --git a/chrome/browser/resources/file_manager/js/file_selection.js b/chrome/browser/resources/file_manager/js/file_selection.js
index cd7b1ee..5228dca 100644
--- a/chrome/browser/resources/file_manager/js/file_selection.js
+++ b/chrome/browser/resources/file_manager/js/file_selection.js
@@ -325,8 +325,14 @@
 FileSelectionHandler.prototype.updatePreviewPanelVisibility_ = function() {
   var panel = this.previewPanel_;
   var state = panel.getAttribute('visibility');
-  var mustBeVisible = (this.selection.totalCount > 0 ||
-      !PathUtil.isRootPath(this.fileManager_.getCurrentDirectory()));
+  var mustBeVisible =
+       // If one or more files are selected, show the file info.
+      (this.selection.totalCount > 0 ||
+       // If the directory is not root dir, show the directory info.
+       !PathUtil.isRootPath(this.fileManager_.getCurrentDirectory()) ||
+       // On Open File dialog, the preview panel is always shown.
+       this.fileManager_.dialogType == DialogType.SELECT_OPEN_FILE ||
+       this.fileManager_.dialogType == DialogType.SELECT_OPEN_MULTI_FILE);
 
   var stopHidingAndShow = function() {
     clearTimeout(this.hidingTimeout_);
@@ -375,7 +381,7 @@
  * @private
  */
 FileSelectionHandler.prototype.isPreviewPanelVisibile_ = function() {
-  return this.previewPanel_.getAttribute('visibility') != 'hidden';
+  return this.previewPanel_.getAttribute('visibility') == 'visible';
 };
 
 /**
@@ -512,9 +518,10 @@
   if (selection.totalCount == 1) {
     // Shows the breadcrumb list when a file is selected.
     updateTarget = selection.entries[0].fullPath;
-  } else if (selection.totalCount == 0 && !PathUtil.isRootPath(path)) {
-    // Shows the breadcrumb list when no file is selected and the current
-    // directory is non-root path.
+  } else if (selection.totalCount == 0 &&
+             this.isPreviewPanelVisibile_()) {
+    // Shows the breadcrumb list when no file is selected and the preview
+    // panel is visible.
     updateTarget = path;
   }
   this.updatePreviewPanelBreadcrumbs_(updateTarget);
diff --git a/chrome/browser/resources/file_manager/js/file_table.js b/chrome/browser/resources/file_manager/js/file_table.js
index 70dcea8..57f870e 100644
--- a/chrome/browser/resources/file_manager/js/file_table.js
+++ b/chrome/browser/resources/file_manager/js/file_table.js
@@ -240,7 +240,7 @@
 
   var tableColumnModelClass;
   tableColumnModelClass = FileTableColumnModel;
-  if (!self.noCheckboxes) {
+  if (self.showCheckboxes) {
     columns.push(new cr.ui.table.TableColumn('selection',
                                              '',
                                              50, true));
@@ -971,10 +971,9 @@
       li.classList.remove('dim-offline');
     else
       li.classList.add('dim-offline');
-    if (driveProps.availableWhenMetered)
-      li.classList.remove('dim-metered');
-    else
-      li.classList.add('dim-metered');
+    // TODO(mtomasz): Consider adding some vidual indication for files which
+    // are not cached on LTE. Currently we show them as normal files.
+    // crbug.com/246611.
   }
 
   if (driveProps.driveApps.length > 0) {
diff --git a/chrome/browser/resources/file_manager/js/file_tasks.js b/chrome/browser/resources/file_manager/js/file_tasks.js
index 988e50c..329b29b 100644
--- a/chrome/browser/resources/file_manager/js/file_tasks.js
+++ b/chrome/browser/resources/file_manager/js/file_tasks.js
@@ -274,8 +274,10 @@
           if (props && props[0] && props[0].contentMimeType)
             mimeType = props[0].contentMimeType;
 
+          var messageString = extension == 'exe' ? 'NO_ACTION_FOR_EXECUTABLE' :
+                                                   'NO_ACTION_FOR_FILE';
           var webStoreUrl = FileTasks.createWebStoreLink(extension, mimeType);
-          var text = loadTimeData.getStringF('NO_ACTION_FOR_FILE',
+          var text = loadTimeData.getStringF(messageString,
                                              webStoreUrl,
                                              FileTasks.NO_ACTION_FOR_FILE_URL);
           this.fileManager_.alert.showHtml(filename, text, function() {});
diff --git a/chrome/browser/resources/file_manager/js/file_transfer_controller.js b/chrome/browser/resources/file_manager/js/file_transfer_controller.js
index 7424267..1d5a90a 100644
--- a/chrome/browser/resources/file_manager/js/file_transfer_controller.js
+++ b/chrome/browser/resources/file_manager/js/file_transfer_controller.js
@@ -263,7 +263,8 @@
     // Option 2. Thumbnail image available, then render it without
     // a label.
     if (thumbnailImage) {
-      contents.classList.add('drag-image-thumbnail');
+      thumbnailImage.classList.add('drag-thumbnail');
+      contents.classList.add('for-image');
       contents.appendChild(this.preloadedThumbnailImageNode_);
       return container;
     }
@@ -289,7 +290,7 @@
   onDragStart_: function(list, event) {
     // Check if a drag selection should be initiated or not.
     // TODO(hirono): Support drag selection on the grid view. crbug.com/247278
-    if (list.id == 'file-list') {
+    if (list.id == 'file-list' && list.parentNode.id == 'detail-table') {
       if (list.parentNode.shouldStartDragSelection(event)) {
         this.dragSelector_.startDragSelection(list, event);
         return;
@@ -398,22 +399,6 @@
 
   /**
    * @this {FileTransferController}
-   * @param {HTMLElement} breadcrumbsContainer Element which contains target
-   *     breadcrumbs.
-   * @param {Event} event A dragenter event of DOM.
-   */
-  onDragEnterBreadcrumbs_: function(breadcrumbsContainer, event) {
-    event.preventDefault();  // Required to prevent the cursor flicker.
-    this.lastEnteredTarget_ = event.target;
-    var path = breadcrumbsContainer.getTargetPath(event);
-    if (!path)
-      return;
-
-    this.setDropTarget_(event.target, true, event.dataTransfer, path);
-  },
-
-  /**
-   * @this {FileTransferController}
    * @param {cr.ui.List} list Drop target list.
    * @param {Event} event A dragleave event of DOM.
    */
diff --git a/chrome/browser/resources/file_manager/js/image_editor/image_adjust.js b/chrome/browser/resources/file_manager/js/image_editor/image_adjust.js
index 76d70e8..e29aca0 100644
--- a/chrome/browser/resources/file_manager/js/image_editor/image_adjust.js
+++ b/chrome/browser/resources/file_manager/js/image_editor/image_adjust.js
@@ -135,7 +135,7 @@
  * @constructor
  */
 ImageEditor.Mode.Exposure = function() {
-  ImageEditor.Mode.ColorFilter.call(this, 'exposure');
+  ImageEditor.Mode.ColorFilter.call(this, 'exposure', 'GALLERY_EXPOSURE');
 };
 
 ImageEditor.Mode.Exposure.prototype =
@@ -146,8 +146,8 @@
  * @param {ImageEditor.Toolbar} toolbar The toolbar to populate.
  */
 ImageEditor.Mode.Exposure.prototype.createTools = function(toolbar) {
-  toolbar.addRange('brightness', -1, 0, 1, 100);
-  toolbar.addRange('contrast', -1, 0, 1, 100);
+  toolbar.addRange('brightness', 'GALLERY_BRIGHTNESS', -1, 0, 1, 100);
+  toolbar.addRange('contrast', 'GALLERY_CONTRAST', -1, 0, 1, 100);
 };
 
 /**
@@ -155,7 +155,7 @@
  * @constructor
  */
 ImageEditor.Mode.Autofix = function() {
-  ImageEditor.Mode.ColorFilter.call(this, 'autofix');
+  ImageEditor.Mode.ColorFilter.call(this, 'autofix', 'GALLERY_AUTOFIX');
   this.doneMessage_ = 'fixed';
 };
 
@@ -223,8 +223,8 @@
  * @param {ImageEditor.Toolbar} toolbar The toolbar to populate.
  */
 ImageEditor.Mode.Blur.prototype.createTools = function(toolbar) {
-  toolbar.addRange('strength', 0, 0, 1, 100);
-  toolbar.addRange('radius', 1, 1, 3);
+  toolbar.addRange('strength', 'GALLERY_STRENGTH', 0, 0, 1, 100);
+  toolbar.addRange('radius', 'GALLERY_RADIUS', 1, 1, 3);
 };
 
 /**
@@ -243,6 +243,6 @@
  * @param {ImageEditor.Toolbar} toolbar The toolbar to populate.
  */
 ImageEditor.Mode.Sharpen.prototype.createTools = function(toolbar) {
-  toolbar.addRange('strength', 0, 0, 1, 100);
-  toolbar.addRange('radius', 1, 1, 3);
+  toolbar.addRange('strength', 'GALLERY_STRENGTH', 0, 0, 1, 100);
+  toolbar.addRange('radius', 'GALLERY_RADIUS', 1, 1, 3);
 };
diff --git a/chrome/browser/resources/file_manager/js/image_editor/image_editor.js b/chrome/browser/resources/file_manager/js/image_editor/image_editor.js
index 1f42ed0..440a26a 100644
--- a/chrome/browser/resources/file_manager/js/image_editor/image_editor.js
+++ b/chrome/browser/resources/file_manager/js/image_editor/image_editor.js
@@ -261,15 +261,18 @@
 
 /**
  * ImageEditor.Mode represents a modal state dedicated to a specific operation.
- * Inherits from ImageBuffer.Overlay to simplify the drawing of
- * mode-specific tools.
+ * Inherits from ImageBuffer. Overlay to simplify the drawing of mode-specific
+ * tools.
+ *
  * @param {string} name The mode name.
+ * @param {string} title The mode title.
  * @constructor
  */
 
-ImageEditor.Mode = function(name) {
+ImageEditor.Mode = function(name, title) {
   this.name = name;
-  this.message_ = 'enter_when_done';
+  this.title = title;
+  this.message_ = 'GALLERY_ENTER_WHEN_DONE';
 };
 
 ImageEditor.Mode.prototype = {__proto__: ImageBuffer.Overlay.prototype };
@@ -365,12 +368,14 @@
 
 /**
  * One-click editor tool, requires no interaction, just executes the command.
+ *
  * @param {string} name The mode name.
+ * @param {string} title The mode title.
  * @param {Command} command The command to execute on click.
  * @constructor
  */
-ImageEditor.Mode.OneClick = function(name, command) {
-  ImageEditor.Mode.call(this, name);
+ImageEditor.Mode.OneClick = function(name, title, command) {
+  ImageEditor.Mode.call(this, name, title);
   this.instant = true;
   this.command_ = command;
 };
@@ -401,19 +406,28 @@
   this.actionNames_ = [];
 
   var self = this;
-  function createButton(name, handler) {
-    return self.mainToolbar_.addButton(name, handler, name);
+  function createButton(name, title, handler) {
+    return self.mainToolbar_.addButton(name,
+                                       title,
+                                       handler,
+                                       name /* opt_className */);
   }
 
   for (var i = 0; i != this.modes_.length; i++) {
     var mode = this.modes_[i];
-    mode.bind(this, createButton(mode.name, this.enterMode.bind(this, mode)));
+    mode.bind(this, createButton(mode.name,
+                                 mode.title,
+                                 this.enterMode.bind(this, mode)));
   }
 
-  this.undoButton_ = createButton('undo', this.undo.bind(this));
+  this.undoButton_ = createButton('undo',
+                                  'GALLERY_UNDO',
+                                  this.undo.bind(this));
   this.registerAction_('undo');
 
-  this.redoButton_ = createButton('redo', this.redo.bind(this));
+  this.redoButton_ = createButton('redo',
+                                  'GALLERY_REDO',
+                                  this.redo.bind(this));
   this.registerAction_('redo');
 };
 
@@ -921,19 +935,21 @@
 
 /**
  * Add a button.
+ *
  * @param {string} name Button name.
+ * @param {string} title Button title.
  * @param {function} handler onClick handler.
  * @param {string=} opt_class Extra class name.
  * @return {HTMLElement} The added button.
  */
 ImageEditor.Toolbar.prototype.addButton = function(
-    name, handler, opt_class) {
+    name, title, handler, opt_class) {
   var button = this.create_('button');
   if (opt_class) button.classList.add(opt_class);
   var label = this.create_('span');
-  label.textContent = this.displayStringFunction_(name);
+  label.textContent = this.displayStringFunction_(title);
   button.appendChild(label);
-  button.label = this.displayStringFunction_(name);
+  button.label = this.displayStringFunction_(title);
   button.addEventListener('click', handler, false);
   return this.add(button);
 };
@@ -942,6 +958,7 @@
  * Add a range control (scalar value picker).
  *
  * @param {string} name An option name.
+ * @param {string} title An option title.
  * @param {number} min Min value of the option.
  * @param {number} value Default value of the option.
  * @param {number} max Max value of the options.
@@ -951,7 +968,7 @@
  * @return {HTMLElement} Range element.
  */
 ImageEditor.Toolbar.prototype.addRange = function(
-    name, min, value, max, scale, opt_showNumeric) {
+    name, title, min, value, max, scale, opt_showNumeric) {
   var self = this;
 
   scale = scale || 1;
@@ -993,7 +1010,7 @@
   range.setValue(value);
 
   var label = this.create_('div');
-  label.textContent = this.displayStringFunction_(name);
+  label.textContent = this.displayStringFunction_(title);
   label.className = 'label ' + name;
   this.add(label);
   this.add(range);
diff --git a/chrome/browser/resources/file_manager/js/image_editor/image_transform.js b/chrome/browser/resources/file_manager/js/image_editor/image_transform.js
index 8b58e73..de8409f 100644
--- a/chrome/browser/resources/file_manager/js/image_editor/image_transform.js
+++ b/chrome/browser/resources/file_manager/js/image_editor/image_transform.js
@@ -9,7 +9,7 @@
  * @constructor
  */
 ImageEditor.Mode.Crop = function() {
-  ImageEditor.Mode.call(this, 'crop');
+  ImageEditor.Mode.call(this, 'crop', 'GALLERY_CROP');
 };
 
 ImageEditor.Mode.Crop.prototype = {__proto__: ImageEditor.Mode.prototype};
diff --git a/chrome/browser/resources/file_manager/js/image_editor/image_view.js b/chrome/browser/resources/file_manager/js/image_editor/image_view.js
index 4b1f7da..08e6bd7 100644
--- a/chrome/browser/resources/file_manager/js/image_editor/image_view.js
+++ b/chrome/browser/resources/file_manager/js/image_editor/image_view.js
@@ -429,9 +429,8 @@
   }
 
   function displayMainImage(loadType, previewShown, content, opt_error) {
-    if (opt_error) {
+    if (opt_error)
       loadType = ImageView.LOAD_TYPE_ERROR;
-    }
 
     // If we already displayed the preview we should not replace the content if:
     //   1. The full content failed to load.
@@ -550,6 +549,8 @@
     this.videoElement_ = content;
     this.screenImage_ = content;
     this.screenImage_.className = 'image';
+    this.container_.appendChild(this.screenImage_);
+    this.videoElement_.play();
     return;
   }
 
@@ -646,7 +647,6 @@
   if (oldScreenImage)
     ImageUtil.setAttribute(newScreenImage, 'fade', true);
   this.setTransform(newScreenImage, opt_effect, 0 /* instant */);
-  this.container_.appendChild(newScreenImage);
 
   setTimeout(function() {
     this.setTransform(newScreenImage, null,
diff --git a/chrome/browser/resources/file_manager/js/main_scripts.js b/chrome/browser/resources/file_manager/js/main_scripts.js
index dcb39ce..a99f813 100644
--- a/chrome/browser/resources/file_manager/js/main_scripts.js
+++ b/chrome/browser/resources/file_manager/js/main_scripts.js
@@ -24,7 +24,7 @@
 // //so we want to parse it as early as possible.
 //<include src="metrics.js"/>
 //
-//<include src="../../image_loader/client.js"/>
+//<include src="../../image_loader/image_loader_client.js"/>
 //
 //<include src="../../../../../ui/webui/resources/js/load_time_data.js"/>
 //<include src="../../../../../ui/webui/resources/js/cr.js"/>
@@ -77,6 +77,7 @@
 //<include src="butter_bar.js"/>
 //<include src="directory_contents.js"/>
 //<include src="directory_model.js"/>
+//<include src="directory_tree.js"/>
 //<include src="drag_selector.js"/>
 //<include src="drive_banners.js" />
 //<include src="error_dialog.js"/>
@@ -90,7 +91,6 @@
 //<include src="file_transfer_controller.js"/>
 //<include src="file_type.js"/>
 //<include src="scrollbar.js"/>
-//<include src="sidebar.js"/>
 //<include src="tree.css.js"/>
 //<include src="volume_list.js"/>
 //<include src="volume_manager.js"/>
diff --git a/chrome/browser/resources/file_manager/js/media/media_controls.js b/chrome/browser/resources/file_manager/js/media/media_controls.js
index 670900d..ba07c3d 100644
--- a/chrome/browser/resources/file_manager/js/media/media_controls.js
+++ b/chrome/browser/resources/file_manager/js/media/media_controls.js
@@ -161,11 +161,21 @@
 };
 
 /**
+ * Toggle play/pause state on a mouse click on the play/pause button. Can be
+ * called externally. TODO(mtomasz): Remove it. http://www.crbug.com/254318.
+ *
+ * @param {Event=} opt_event Mouse click event.
+ */
+MediaControls.prototype.onPlayButtonClicked = function(opt_event) {
+  this.togglePlayState();
+};
+
+/**
  * @param {HTMLElement=} opt_parent Parent container.
  */
 MediaControls.prototype.initPlayButton = function(opt_parent) {
   this.playButton_ = this.createButton('play media-control',
-      this.togglePlayState.bind(this), opt_parent, 3 /* States. */);
+      this.onPlayButtonClicked.bind(this), opt_parent, 3 /* States. */);
 };
 
 /*
@@ -961,21 +971,21 @@
  *
  * @param {HTMLElement} containerElement The container for the controls.
  * @param {function} onMediaError Function to display an error message.
+ * @param {function(string):string} stringFunction Function providing localized
+ *     strings.
  * @param {function=} opt_fullScreenToggle Function to toggle fullscreen mode.
  * @param {HTMLElement=} opt_stateIconParent The parent for the icon that
  *     gives visual feedback when the playback state changes.
  * @constructor
  */
-function VideoControls(containerElement, onMediaError,
+function VideoControls(containerElement, onMediaError, stringFunction,
    opt_fullScreenToggle, opt_stateIconParent) {
   MediaControls.call(this, containerElement, onMediaError);
+  this.stringFunction_ = stringFunction;
 
   this.container_.classList.add('video-controls');
-
   this.initPlayButton();
-
   this.initTimeControls(true /* show seek mark */);
-
   this.initVolumeControls();
 
   if (opt_fullScreenToggle) {
@@ -986,6 +996,7 @@
   if (opt_stateIconParent) {
     this.stateIcon_ = this.createControl(
         'playback-state-icon', opt_stateIconParent);
+    this.textBanner_ = this.createControl('text-banner', opt_stateIconParent);
   }
 
   var videoControls = this;
@@ -1011,6 +1022,47 @@
 VideoControls.prototype = { __proto__: MediaControls.prototype };
 
 /**
+ * Shows icon feedback for the current state of the video player.
+ * @private
+ */
+VideoControls.prototype.showIconFeedback_ = function() {
+  this.stateIcon_.removeAttribute('state');
+  setTimeout(function() {
+    this.stateIcon_.setAttribute('state', this.isPlaying() ? 'play' : 'pause');
+  }.bind(this), 0);
+};
+
+/**
+ * Shows a text banner.
+ *
+ * @param {string} identifier String identifier.
+ * @private
+ */
+VideoControls.prototype.showTextBanner_ = function(identifier) {
+  this.textBanner_.removeAttribute('visible');
+  this.textBanner_.textContent = this.stringFunction_(identifier);
+  setTimeout(function() {
+    this.textBanner_.setAttribute('visible', 'true');
+  }.bind(this), 0);
+};
+
+/**
+ * Toggle play/pause state on a mouse click on the play/pause button. Can be
+ * called externally.
+ *
+ * @param {Event} event Mouse click event.
+ */
+VideoControls.prototype.onPlayButtonClicked = function(event) {
+  if (event.ctrlKey) {
+    this.toggleLoopedModeWithFeedback(true);
+    if (!this.isPlaying())
+      this.togglePlayState();
+  } else {
+    this.togglePlayState();
+  }
+};
+
+/**
  * Media completion handler.
  */
 VideoControls.prototype.onMediaComplete = function() {
@@ -1019,33 +1071,52 @@
 };
 
 /**
- * Toggle play/pause state and flash an icon over the video.
+ * Toggles the looped mode with feedback.
+ * @param {boolean} on Whether enabled or not.
+ */
+VideoControls.prototype.toggleLoopedModeWithFeedback = function(on) {
+  if (!this.getMedia().duration)
+    return;
+  this.toggleLoopedMode(on);
+  if (on) {
+    // TODO(mtomasz): Simplify, crbug.com/254318.
+    this.showTextBanner_('GALLERY_VIDEO_LOOPED_MODE');
+  }
+};
+
+/**
+ * Toggles the looped mode.
+ * @param {boolean} on Whether enabled or not.
+ */
+VideoControls.prototype.toggleLoopedMode = function(on) {
+  this.getMedia().loop = on;
+};
+
+/**
+ * Toggles play/pause state and flash an icon over the video.
  */
 VideoControls.prototype.togglePlayStateWithFeedback = function() {
   if (!this.getMedia().duration)
     return;
 
   this.togglePlayState();
-
-  this.stateIcon_.removeAttribute('state');
-  setTimeout(function() {
-    this.stateIcon_.setAttribute('state', this.isPlaying() ? 'play' : 'pause');
-  }.bind(this), 0);
+  this.showIconFeedback_();
 };
 
 /**
- * Toggle play/pause state.
+ * Toggles play/pause state.
  */
 VideoControls.prototype.togglePlayState = function() {
   if (this.isPlaying()) {
-    // User gave the Pause command.
+    // User gave the Pause command. Save the state and reset the loop mode.
+    this.toggleLoopedMode(false);
     this.savePosition();
   }
   MediaControls.prototype.togglePlayState.apply(this, arguments);
 };
 
 /**
- * Save the playback position to the persistent storage.
+ * Saves the playback position to the persistent storage.
  * @param {boolean=} opt_sync True if the position must be saved synchronously
  *     (required when closing app windows).
  */
@@ -1079,7 +1150,7 @@
 };
 
 /**
- * Resume the playback position saved in the persistent storage.
+ * Resumes the playback position saved in the persistent storage.
  */
 VideoControls.prototype.restorePlayState = function() {
   if (this.media_.duration >= VideoControls.RESUME_THRESHOLD) {
@@ -1091,7 +1162,7 @@
 };
 
 /**
- * Update style to best fit the size of the container.
+ * Updates style to best fit the size of the container.
  */
 VideoControls.prototype.updateStyle = function() {
   // We assume that the video controls element fills the parent container.
@@ -1115,7 +1186,7 @@
 };
 
 /**
- * Create audio controls.
+ * Creates audio controls.
  *
  * @param {HTMLElement} container Parent container.
  * @param {function(boolean)} advanceTrack Parameter: true=forward.
diff --git a/chrome/browser/resources/file_manager/js/media/media_util.js b/chrome/browser/resources/file_manager/js/media/media_util.js
index db09006..af77c9c 100644
--- a/chrome/browser/resources/file_manager/js/media/media_util.js
+++ b/chrome/browser/resources/file_manager/js/media/media_util.js
@@ -205,6 +205,7 @@
     this.image_.onload = function() {};
     this.image_.onerror = function() {};
     util.cancelLoadImage(this.taskId_);
+    this.taskId_ = null;
   }
 };
 
diff --git a/chrome/browser/resources/file_manager/js/media/util.js b/chrome/browser/resources/file_manager/js/media/util.js
index bddd709..4d3c953 100644
--- a/chrome/browser/resources/file_manager/js/media/util.js
+++ b/chrome/browser/resources/file_manager/js/media/util.js
@@ -44,6 +44,11 @@
   });
 
   this.container_.addEventListener('mousemove', this.onMouseMove_.bind(this));
+  var tools = this.container_.querySelector('.tool');
+  for (var i = 0; i < tools.length; i++) {
+    tools[i].addEventListener('mouseover', this.onToolMouseOver_.bind(this));
+    tools[i].addEventListener('mouseout', this.onToolMouseOut_.bind(this));
+  }
 
   // Show tools when the user touches the screen.
   this.container_.addEventListener(
@@ -69,15 +74,6 @@
 };
 
 /**
- * @param {Element} element DOM element.
- * @return {boolean} True if the element is a tool. Tools should never be hidden
- *   while the mouse is over one of them.
- */
-MouseInactivityWatcher.prototype.isToolElement = function(element) {
-  return element.classList.contains('tool');
-};
-
-/**
  * To be called when the user started activity. Shows the tools
  * and cancels the countdown.
  * @private
@@ -142,19 +138,34 @@
   this.clientX_ = e.clientX;
   this.clientY_ = e.clientY;
 
-  this.mouseOverTool_ = false;
-  for (var elem = e.target; elem != this.container_; elem = elem.parentNode) {
-    if (this.isToolElement(elem)) {
-      this.mouseOverTool_ = true;
-      break;
-    }
-  }
-
   if (this.disabled_)
     return;
 
-  this.activityStarted_();
-  this.activityStopped_();
+  this.kick();
+};
+
+/**
+ * Mouse over handler on a tool element.
+ *
+ * @param {Event} e Event.
+ * @private
+ */
+MouseInactivityWatcher.prototype.onToolMouseOver_ = function(e) {
+  this.mouseOverTool_ = true;
+  if (!this.disabled_)
+    this.kick();
+};
+
+/**
+ * Mouse out handler on a tool element.
+ *
+ * @param {Event} e Event.
+ * @private
+ */
+MouseInactivityWatcher.prototype.onToolMouseOut_ = function(e) {
+  this.mouseOverTool_ = false;
+  if (!this.disabled_)
+    this.kick();
 };
 
 /**
diff --git a/chrome/browser/resources/file_manager/js/media/video_player.js b/chrome/browser/resources/file_manager/js/media/video_player.js
index 040b08f..2a0ca66 100644
--- a/chrome/browser/resources/file_manager/js/media/video_player.js
+++ b/chrome/browser/resources/file_manager/js/media/video_player.js
@@ -50,6 +50,7 @@
   VideoControls.call(this,
       controlsContainer,
       onPlaybackError,
+      loadTimeData.getString.bind(loadTimeData),
       this.toggleFullScreen_.bind(this),
       videoContainer);
 
@@ -71,8 +72,16 @@
     }
   }.bind(this));
 
-  videoContainer.addEventListener('click',
-      this.togglePlayStateWithFeedback.bind(this));
+  // TODO(mtomasz): Simplify. crbug.com/254318.
+  videoContainer.addEventListener('click', function(e) {
+    if (e.ctrlKey) {
+      this.toggleLoopedModeWithFeedback(true);
+      if (!this.isPlaying())
+        this.togglePlayStateWithFeedback();
+    } else {
+      this.togglePlayStateWithFeedback();
+    }
+  }.bind(this));
 
   this.inactivityWatcher_ = new MouseInactivityWatcher(playerContainer);
   this.__defineGetter__('inactivityWatcher', function() {
diff --git a/chrome/browser/resources/file_manager/js/metadata/metadata_dispatcher.js b/chrome/browser/resources/file_manager/js/metadata/metadata_dispatcher.js
index ffa9a39..270282f 100644
--- a/chrome/browser/resources/file_manager/js/metadata/metadata_dispatcher.js
+++ b/chrome/browser/resources/file_manager/js/metadata/metadata_dispatcher.js
@@ -214,7 +214,7 @@
 // the 'this' keyword in lambdas.
 var global = self;
 
-if (global.constructor.name == 'SharedWorkerContext') {
+if (global.constructor.name == 'SharedWorkerGlobalScope') {
   global.addEventListener('connect', function(e) {
     var port = e.ports[0];
     new MetadataDispatcher(port);
diff --git a/chrome/browser/resources/file_manager/js/photo/gallery.js b/chrome/browser/resources/file_manager/js/photo/gallery.js
index 2b1cc2c..c942d75 100644
--- a/chrome/browser/resources/file_manager/js/photo/gallery.js
+++ b/chrome/browser/resources/file_manager/js/photo/gallery.js
@@ -56,16 +56,10 @@
 
   this.dataModel_ = new cr.ui.ArrayDataModel([]);
   this.selectionModel_ = new cr.ui.ListSelectionModel();
+  this.displayStringFunction_ = context.displayStringFunction;
 
-  var strf = context.displayStringFunction;
-  this.displayStringFunction_ = function(id, formatArgs) {
-    var args = Array.prototype.slice.call(arguments);
-    args[0] = 'GALLERY_' + id.toUpperCase();
-    return strf.apply(null, args);
-  };
-
-  this.initListeners_();
   this.initDom_();
+  this.initListeners_();
 }
 
 /**
@@ -326,10 +320,14 @@
     cr.dispatchSimpleEvent(this, 'image-saved');
   }.bind(this));
 
-  var deleteButton = this.createToolbarButton_('delete', 'delete');
-  deleteButton.addEventListener('click', this.onDelete_.bind(this));
+  this.printButton_ = this.createToolbarButton_('print', 'GALLERY_PRINT');
+  this.printButton_.setAttribute('disabled', '');
+  this.printButton_.addEventListener('click', this.print_.bind(this));
 
-  this.shareButton_ = this.createToolbarButton_('share', 'share');
+  var deleteButton = this.createToolbarButton_('delete', 'GALLERY_DELETE');
+  deleteButton.addEventListener('click', this.delete_.bind(this));
+
+  this.shareButton_ = this.createToolbarButton_('share', 'GALLERY_SHARE');
   this.shareButton_.setAttribute('disabled', '');
   this.shareButton_.addEventListener('click', this.toggleShare_.bind(this));
 
@@ -341,22 +339,19 @@
   this.dataModel_.addEventListener('content', this.onContentChange_.bind(this));
 
   this.selectionModel_.addEventListener('change', this.onSelection_.bind(this));
-
   this.slideMode_.addEventListener('useraction', this.onUserAction_.bind(this));
-
-  document.body.setAttribute('new-ui', '');
 };
 
 /**
  * Creates toolbar button.
  *
- * @param {string} clazz Class to add.
+ * @param {string} className Class to add.
  * @param {string} title Button title.
  * @return {HTMLElement} Newly created button.
  * @private
  */
-Gallery.prototype.createToolbarButton_ = function(clazz, title) {
-  var button = util.createChild(this.toolbar_, clazz, 'button');
+Gallery.prototype.createToolbarButton_ = function(className, title) {
+  var button = util.createChild(this.toolbar_, className, 'button');
   button.title = this.displayStringFunction_(title);
   return button;
 };
@@ -506,8 +501,15 @@
     var oppositeMode =
         mode == this.slideMode_ ? this.mosaicMode_ : this.slideMode_;
     this.modeButton_.title =
-        this.displayStringFunction_(oppositeMode.getName());
+        this.displayStringFunction_(oppositeMode.getTitle());
   }
+
+  // Printing is available only in the slide view.
+  if (mode == this.slideMode_)
+    this.printButton_.removeAttribute('disabled');
+  else
+    this.printButton_.setAttribute('disabled', '');
+
   this.container_.setAttribute('mode', this.currentMode_.getName());
   this.updateSelectionAndState_();
 };
@@ -564,10 +566,10 @@
 };
 
 /**
- * Delete event handler.
+ * Deletes the selected items.
  * @private
  */
-Gallery.prototype.onDelete_ = function() {
+Gallery.prototype.delete_ = function() {
   this.onUserAction_();
 
   // Clone the sorted selected indexes array.
@@ -600,12 +602,14 @@
     this.document_.body.addEventListener('keydown', this.keyDownBound_);
   }.bind(this);
 
-  cr.ui.dialogs.BaseDialog.OK_LABEL = this.displayStringFunction_('OK_LABEL');
+  cr.ui.dialogs.BaseDialog.OK_LABEL = this.displayStringFunction_(
+      'GALLERY_OK_LABEL');
   cr.ui.dialogs.BaseDialog.CANCEL_LABEL =
-      this.displayStringFunction_('CANCEL_LABEL');
+      this.displayStringFunction_('GALLERY_CANCEL_LABEL');
   var confirm = new cr.ui.dialogs.ConfirmDialog(this.container_);
-  confirm.show(this.displayStringFunction_(
-      plural ? 'CONFIRM_DELETE_SOME' : 'CONFIRM_DELETE_ONE', param),
+  confirm.show(
+      this.displayStringFunction_(plural ? 'GALLERY_CONFIRM_DELETE_SOME' :
+          'GALLERY_CONFIRM_DELETE_ONE', param),
       function() {
         restoreListener();
         this.selectionModel_.unselectAll();
@@ -623,6 +627,15 @@
 };
 
 /**
+ * Prints the current item.
+ * @private
+ */
+Gallery.prototype.print_ = function() {
+  this.onUserAction_();
+  window.print();
+};
+
+/**
  * @return {Array.<Gallery.Item>} Current selection.
  */
 Gallery.prototype.getSelectedItems = function() {
@@ -709,11 +722,16 @@
 
     case 'U+0056':  // 'v'
       this.slideMode_.startSlideshow(SlideMode.SLIDESHOW_INTERVAL_FIRST, event);
-      return;
+      break;
+
+    case 'Ctrl-U+0050':  // Ctrl+'p' prints the current image.
+      if (this.currentMode_ == this.slideMode_)
+        this.print_();
+      break;
 
     case 'U+007F':  // Delete
     case 'Shift-U+0033':  // Shift+'3' (Delete key might be missing).
-      this.onDelete_();
+      this.delete_();
       break;
   }
 };
@@ -743,7 +761,8 @@
     path = this.context_.curDirEntry.fullPath;
     window.top.document.title = this.context_.curDirEntry.name;
     displayName =
-        this.displayStringFunction_('ITEMS_SELECTED', selectedItems.length);
+        this.displayStringFunction_('GALLERY_ITEMS_SELECTED',
+                                    selectedItems.length);
   }
 
   window.top.util.updateAppState(path,
diff --git a/chrome/browser/resources/file_manager/js/photo/gallery_scripts.js b/chrome/browser/resources/file_manager/js/photo/gallery_scripts.js
index 5725911..6548dd0 100644
--- a/chrome/browser/resources/file_manager/js/photo/gallery_scripts.js
+++ b/chrome/browser/resources/file_manager/js/photo/gallery_scripts.js
@@ -10,7 +10,7 @@
 
 //<include src="../metrics.js">
 
-//<include src="../../../image_loader/client.js"/>
+//<include src="../../../image_loader/image_loader_client.js"/>
 
 //<include src="../../../../../../ui/webui/resources/js/cr.js">
 //<include src="../../../../../../ui/webui/resources/js/event_tracker.js">
diff --git a/chrome/browser/resources/file_manager/js/photo/mosaic_mode.js b/chrome/browser/resources/file_manager/js/photo/mosaic_mode.js
index 9eae8fb..3e6d419 100644
--- a/chrome/browser/resources/file_manager/js/photo/mosaic_mode.js
+++ b/chrome/browser/resources/file_manager/js/photo/mosaic_mode.js
@@ -33,6 +33,11 @@
 MosaicMode.prototype.getName = function() { return 'mosaic' };
 
 /**
+ * @return {string} Mode title.
+ */
+MosaicMode.prototype.getTitle = function() { return 'GALLERY_MOSAIC' };
+
+/**
  * Execute an action (this mode has no busy state).
  * @param {function} action Action to execute.
  */
diff --git a/chrome/browser/resources/file_manager/js/photo/photo_import_scripts.js b/chrome/browser/resources/file_manager/js/photo/photo_import_scripts.js
index 0638e46..c9db07d 100644
--- a/chrome/browser/resources/file_manager/js/photo/photo_import_scripts.js
+++ b/chrome/browser/resources/file_manager/js/photo/photo_import_scripts.js
@@ -8,7 +8,7 @@
 // included file but that's all right since any javascript file should start
 // with a copyright comment anyway.
 
-//<include src="../../../image_loader/client.js"/>
+//<include src="../../../image_loader/image_loader_client.js"/>
 
 //<include src="../../../../../../ui/webui/resources/js/load_time_data.js"/>
 //<include src="../../../../../../ui/webui/resources/js/util.js"/>
diff --git a/chrome/browser/resources/file_manager/js/photo/slide_mode.js b/chrome/browser/resources/file_manager/js/photo/slide_mode.js
index 1cdd6a8..06c2228 100644
--- a/chrome/browser/resources/file_manager/js/photo/slide_mode.js
+++ b/chrome/browser/resources/file_manager/js/photo/slide_mode.js
@@ -63,8 +63,10 @@
   new ImageEditor.Mode.InstantAutofix(),
   new ImageEditor.Mode.Crop(),
   new ImageEditor.Mode.Exposure(),
-  new ImageEditor.Mode.OneClick('rotate_left', new Command.Rotate(-1)),
-  new ImageEditor.Mode.OneClick('rotate_right', new Command.Rotate(1))
+  new ImageEditor.Mode.OneClick(
+      'rotate_left', 'GALLERY_ROTATE_LEFT', new Command.Rotate(-1)),
+  new ImageEditor.Mode.OneClick(
+      'rotate_right', 'GALLERY_ROTATE_RIGHT', new Command.Rotate(1))
 ];
 
 /**
@@ -73,6 +75,11 @@
 SlideMode.prototype.getName = function() { return 'slide' };
 
 /**
+ * @return {string} Mode title.
+ */
+SlideMode.prototype.getTitle = function() { return 'GALLERY_SLIDE' };
+
+/**
  * Initialize the listeners.
  * @private
  */
@@ -97,7 +104,7 @@
       this.toolbar_.querySelector('.filename-spacer'), 'options');
 
   this.savedLabel_ = util.createChild(this.options_, 'saved');
-  this.savedLabel_.textContent = this.displayStringFunction_('saved');
+  this.savedLabel_.textContent = this.displayStringFunction_('GALLERY_SAVED');
 
   var overwriteOriginalBox =
       util.createChild(this.options_, 'overwrite-original');
@@ -116,14 +123,15 @@
 
   var overwriteLabel = util.createChild(overwriteOriginalBox, '', 'label');
   overwriteLabel.textContent =
-      this.displayStringFunction_('overwrite_original');
+      this.displayStringFunction_('GALLERY_OVERWRITE_ORIGINAL');
   overwriteLabel.setAttribute('for', 'overwrite-checkbox');
 
   this.bubble_ = util.createChild(this.toolbar_, 'bubble');
   this.bubble_.hidden = true;
 
   var bubbleContent = util.createChild(this.bubble_);
-  bubbleContent.innerHTML = this.displayStringFunction_('overwrite_bubble');
+  bubbleContent.innerHTML = this.displayStringFunction_(
+      'GALLERY_OVERWRITE_BUBBLE');
 
   util.createChild(this.bubble_, 'pointer bottom', 'span');
 
@@ -136,7 +144,8 @@
   this.mediaToolbar_ = util.createChild(this.mediaSpacer_, 'tool');
   this.mediaControls_ = new VideoControls(
       this.mediaToolbar_,
-      this.showErrorBanner_.bind(this, 'VIDEO_ERROR'),
+      this.showErrorBanner_.bind(this, 'GALLERY_VIDEO_ERROR'),
+      this.displayStringFunction_.bind(this),
       this.toggleFullScreen_.bind(this),
       this.container_);
 
@@ -172,7 +181,7 @@
 
   var slideShowButton = util.createChild(this.toolbar_,
       'button slideshow', 'button');
-  slideShowButton.title = this.displayStringFunction_('slideshow');
+  slideShowButton.title = this.displayStringFunction_('GALLERY_SLIDESHOW');
   slideShowButton.addEventListener('click',
       this.startSlideshow.bind(this, SlideMode.SLIDESHOW_INTERVAL_FIRST));
 
@@ -186,7 +195,7 @@
   // Editor.
 
   this.editButton_ = util.createChild(this.toolbar_, 'button edit', 'button');
-  this.editButton_.title = this.displayStringFunction_('edit');
+  this.editButton_.title = this.displayStringFunction_('GALLERY_EDIT');
   this.editButton_.addEventListener('click', this.toggleEditor.bind(this));
 
   this.editBarSpacer_ = util.createChild(this.toolbar_, 'edit-bar-spacer');
@@ -255,7 +264,7 @@
   if (this.getItemCount_() == 0) {
     this.displayedIndex_ = -1;
     //TODO(kaznacheev) Show this message in the grid mode too.
-    this.showErrorBanner_('NO_IMAGES');
+    this.showErrorBanner_('GALLERY_NO_IMAGES');
     loadDone();
   } else {
     // Remember the selection if it is empty or multiple. It will be restored
@@ -533,7 +542,7 @@
       // No items left. Unload the image and show the banner.
       this.commitItem_(function() {
         this.unloadImage_();
-        this.showErrorBanner_('NO_IMAGES');
+        this.showErrorBanner_('GALLERY_NO_IMAGES');
       }.bind(this));
     }
   }.bind(this), 0);
@@ -636,13 +645,15 @@
     if (loadType == ImageView.LOAD_TYPE_ERROR) {
       // if we have a specific error, then display it
       if (error) {
-        this.showErrorBanner_(error);
+        this.showErrorBanner_('GALLERY_' + error);
       } else {
         // otherwise try to infer general error
-        this.showErrorBanner_(video ? 'VIDEO_ERROR' : 'IMAGE_ERROR');
+        this.showErrorBanner_(
+            video ? 'GALLERY_VIDEO_ERROR' : 'GALLERY_IMAGE_ERROR');
       }
     } else if (loadType == ImageView.LOAD_TYPE_OFFLINE) {
-      this.showErrorBanner_(video ? 'VIDEO_OFFLINE' : 'IMAGE_OFFLINE');
+      this.showErrorBanner_(
+          video ? 'GALLERY_VIDEO_OFFLINE' : 'GALLERY_IMAGE_OFFLINE');
     }
 
     if (video) {
@@ -755,17 +766,26 @@
  */
 SlideMode.prototype.onBeforeUnload = function() {
   if (this.editor_.isBusy())
-    return this.displayStringFunction_('unsaved_changes');
+    return this.displayStringFunction_('GALLERY_UNSAVED_CHANGES');
   return null;
 };
 
 /**
  * Click handler for the image container.
+ *
+ * @param {Event} event Mouse click event.
  * @private
  */
-SlideMode.prototype.onClick_ = function() {
-  if (this.isShowingVideo_())
+SlideMode.prototype.onClick_ = function(event) {
+  if (!this.isShowingVideo_())
+    return;
+  if (event.ctrlKey) {
+    this.mediaControls_.toggleLoopedModeWithFeedback(true);
+    if (!this.mediaControls_.isPlaying())
+      this.mediaControls_.togglePlayStateWithFeedback();
+  } else {
     this.mediaControls_.togglePlayStateWithFeedback();
+  }
 };
 
 /**
@@ -823,7 +843,7 @@
       }
       break;
 
-    case 'U+0045':  // 'e' toggles the editor
+    case 'U+0045':  // 'e' toggles the editor.
       this.toggleEditor(event);
       break;
 
diff --git a/chrome/browser/resources/file_manager/js/scrollbar.js b/chrome/browser/resources/file_manager/js/scrollbar.js
index 8fba774..a81fe8d 100644
--- a/chrome/browser/resources/file_manager/js/scrollbar.js
+++ b/chrome/browser/resources/file_manager/js/scrollbar.js
@@ -79,7 +79,7 @@
   this.view_ = view;
   this.view_.addEventListener('scroll', this.onScroll_.bind(this));
   this.view_.addEventListener('relayout', this.onRelayout_.bind(this));
-  this.domObserver_ = new WebKitMutationObserver(this.onDomChanged_.bind(this));
+  this.domObserver_ = new MutationObserver(this.onDomChanged_.bind(this));
   this.domObserver_.observe(this.view_, {subtree: true, attributes: true});
   this.onRelayout_();
 };
@@ -147,14 +147,20 @@
   }
   var clientSize = this.getClientHeight();
   var totalSize = this.getTotalHeight();
+  // TODO(hirono): Fix the geometric calculation.  crbug.com/253779
   var buttonSize = Math.max(50, clientSize / totalSize * clientSize);
-
   var buttonPosition = this.buttonPressedPosition_ +
       (event.screenY - this.buttonPressedEvent_.screenY);
   // Ensures the scrollbar is in the view.
   buttonPosition =
       Math.max(0, Math.min(buttonPosition, clientSize - buttonSize));
-  var scrollPosition = totalSize * (buttonPosition / clientSize);
+  var scrollPosition;
+  if (clientSize > buttonSize) {
+    scrollPosition = Math.max(totalSize - clientSize, 0) *
+        buttonPosition / (clientSize - buttonSize);
+  } else {
+    scrollPosition = 0;
+  }
 
   this.scrollTop_ = scrollPosition;
   this.view_.scrollTop = scrollPosition;
@@ -191,8 +197,13 @@
   var hidden = totalSize <= clientSize;
 
   var buttonSize = Math.max(50, clientSize / totalSize * clientSize);
-  var buttonPosition = scrollPosition / (totalSize - clientSize) *
-      (clientSize - buttonSize);
+  var buttonPosition;
+  if (clientSize - buttonSize > 0) {
+    buttonPosition = scrollPosition / (totalSize - clientSize) *
+        (clientSize - buttonSize);
+  } else {
+    buttonPosition = 0;
+  }
   var buttonTop = buttonPosition + clientTop;
 
   var time = Date.now();
diff --git a/chrome/browser/resources/file_manager/js/sidebar.js b/chrome/browser/resources/file_manager/js/sidebar.js
deleted file mode 100644
index f38c7a1..0000000
--- a/chrome/browser/resources/file_manager/js/sidebar.js
+++ /dev/null
@@ -1,727 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-'use strict';
-
-// TODO(yoshiki): rename this sidebar.js to directory_tree.js.
-
-////////////////////////////////////////////////////////////////////////////////
-// DirectoryTreeUtil
-
-/**
- * Utility methods. They are intended for use only in this file.
- */
-var DirectoryTreeUtil = {};
-
-/**
- * Updates sub-elements of {@code parentElement} reading {@code DirectoryEntry}
- * with calling {@code iterator}.
- *
- * @param {string} changedDirectryPath The path of the changed directory.
- * @param {DirectoryItem|DirectoryTree} currentDirectoryItem An item to be
- *     started traversal from.
- */
-DirectoryTreeUtil.updateChangedDirectoryItem = function(
-    changedDirectryPath, currentDirectoryItem) {
-  if (changedDirectryPath === currentDirectoryItem.entry.fullPath) {
-    currentDirectoryItem.updateSubDirectories(false /* recursive */);
-    return;
-  }
-
-  for (var i = 0; i < currentDirectoryItem.items.length; i++) {
-    var item = currentDirectoryItem.items[i];
-    if (PathUtil.isParentPath(item.entry.fullPath, changedDirectryPath)) {
-      DirectoryTreeUtil.updateChangedDirectoryItem(changedDirectryPath, item);
-      break;
-    }
-  }
-};
-
-/**
- * Updates sub-elements of {@code parentElement} reading {@code DirectoryEntry}
- * with calling {@code iterator}.
- *
- * @param {DirectoryItem|DirectoryTree} parentElement Parent element of newly
- *     created items.
- * @param {function(number): DirectoryEntry} iterator Function which returns
- *     the n-th Entry in the directory.
- * @param {DirectoryModel} directoryModel Current DirectoryModel.
- * @param {boolean} recursive True if the all visible sub-directories are
- *     updated recursively including left arrows. If false, the update walks
- *     only immediate child directories without arrows.
- */
-DirectoryTreeUtil.updateSubElementsFromList = function(
-    parentElement, iterator, directoryModel, recursive) {
-  var index = 0;
-  while (iterator(index)) {
-    var currentEntry = iterator(index);
-    var currentElement = parentElement.items[index];
-
-    if (index >= parentElement.items.length) {
-      var item = new DirectoryItem(currentEntry, parentElement, directoryModel);
-      parentElement.add(item);
-      index++;
-    } else if (currentEntry.fullPath == currentElement.fullPath) {
-      if (recursive && parentElement.expanded)
-        currentElement.updateSubDirectories(true /* recursive */);
-
-      index++;
-    } else if (currentEntry.fullPath < currentElement.fullPath) {
-      var item = new DirectoryItem(currentEntry, parentElement, directoryModel);
-      parentElement.addAt(item, index);
-      index++;
-    } else if (currentEntry.fullPath > currentElement.fullPath) {
-      parentElement.remove(currentElement);
-    }
-  }
-
-  var removedChild;
-  while (removedChild = parentElement.items[index]) {
-    parentElement.remove(removedChild);
-  }
-
-  if (index == 0) {
-    parentElement.hasChildren = false;
-    parentElement.expanded = false;
-  } else {
-    parentElement.hasChildren = true;
-  }
-};
-
-/**
- * Returns true if the given directory entry is dummy.
- * @param {DirectoryEntry|Object} dirEntry DirectoryEntry to be checked.
- * @return {boolean} True if the given directory entry is dummy.
- */
-DirectoryTreeUtil.isDummyEntry = function(dirEntry) {
-  return !('createReader' in dirEntry);
-};
-
-/**
- * Finds a parent directory of the {@code path} from the {@code items}, and
- * invokes the DirectoryItem.selectPath() of the found directory.
- *
- * @param {Array.<DirectoryItem>} items Items to be searched.
- * @param {string} path Path to be searched for.
- * @return {boolean} True if the parent item is found.
- */
-DirectoryTreeUtil.searchAndSelectPath = function(items, path) {
-  for (var i = 0; i < items.length; i++) {
-    var item = items[i];
-    if (PathUtil.isParentPath(item.entry.fullPath, path)) {
-      item.selectPath(path);
-      return true;
-    }
-  }
-  return false;
-};
-
-/**
- * Modifies a list of the directory entries to match the new UI sepc.
- *
- * TODO(yoshiki): remove this after the old UI is removed.
- *
- * @param {Array.<DirectoryEntry>} entries The list of entty.
- * @return {Array.<DirectoryEntries>} Modified entries.
- */
-DirectoryTreeUtil.addAndRemoveDriveSpecialDirs = function(entries) {
-  var modifiedEntries = [];
-  for (var i in entries) {
-    // Removes '/drive/other'.
-    var entry = entries[i];
-    if (entry.fullPath ==
-        (RootDirectory.DRIVE + '/' + DriveSubRootDirectory.OTHER)) {
-      continue;
-    }
-
-    // Changes the label of '/drive/root' to 'My Drive'.
-    if (entry.fullPath == DirectoryModel.fakeDriveEntry_.fullPath) {
-      entry.label = str('DRIVE_MY_DRIVE_LABEL');
-    }
-
-    modifiedEntries.push(entry);
-  }
-
-  // Adds the special directories.
-  var specialDirs = DirectoryModel.FAKE_DRIVE_SPECIAL_SEARCH_ENTRIES;
-  for (var i in specialDirs) {
-    var dir = specialDirs[i];
-    dir['label'] = PathUtil.getRootLabel(dir.fullPath);
-    modifiedEntries.push(dir);
-  }
-  return modifiedEntries;
-};
-
-/**
- * Retrieves the file list with the latest information.
- *
- * @param {DirectoryTree|DirectoryItem} item Parent to be reloaded.
- * @param {DirectoryModel} dm The directory model.
- * @param {function(Array.<Entry>)} successCallback Callback on success.
- * @param {function()=} opt_errorCallback Callback on failure.
- */
-DirectoryTreeUtil.updateSubDirectories = function(
-    item, dm, successCallback, opt_errorCallback) {
-  // Tries to retrieve new entry if the cached entry is dummy.
-  if (DirectoryTreeUtil.isDummyEntry(item.entry)) {
-    // Fake Drive root.
-    dm.resolveDirectory(
-        item.fullPath,
-        function(entry) {
-          item.dirEntry_ = entry;
-
-          // If the retrieved entry is dummy again, returns with an error.
-          if (DirectoryTreeUtil.isDummyEntry(entry)) {
-            if (opt_errorCallback)
-              opt_errorCallback();
-            return;
-          }
-
-          DirectoryTreeUtil.updateSubDirectories(
-              item, dm, successCallback, opt_errorCallback);
-        },
-        opt_errorCallback);
-    return;
-  }
-
-  var reader = item.entry.createReader();
-  var entries = [];
-  var readEntry = function() {
-    reader.readEntries(function(results) {
-      if (!results.length) {
-        if (item.entry.fullPath == RootDirectory.DRIVE)
-          successCallback(
-              DirectoryTreeUtil.addAndRemoveDriveSpecialDirs(entries));
-        else
-          successCallback(
-              DirectoryTreeUtil.sortEntries(item.fileFilter_, entries));
-        return;
-      }
-
-      for (var i = 0; i < results.length; i++) {
-        var entry = results[i];
-        if (entry.isDirectory)
-          entries.push(entry);
-      }
-      readEntry();
-    });
-  };
-  readEntry();
-};
-
-/**
- * Sorts a list of entries.
- *
- * @param {FileFilter} fileFilter The file filter.
- * @param {Array.<Entries>} entries Entries to be sorted.
- * @return {Array.<Entries>} Sorted entries.
- */
-DirectoryTreeUtil.sortEntries = function(fileFilter, entries) {
-  entries.sort(function(a, b) {
-    return (a.name.toLowerCase() > b.name.toLowerCase()) ? 1 : -1;
-  });
-  return entries.filter(fileFilter.filter.bind(fileFilter));
-};
-
-/**
- * Checks if tre tree should be hidden on the given directory.
- *
- * @param {string} path Path to be checked.
- * @return {boolean} True if the tree should NOT be visible on the given
- *     directory. Otherwise, false.
- */
-DirectoryTreeUtil.shouldHideTree = function(path) {
-  return !PathUtil.isDriveBasedPath(path);
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// DirectoryItem
-
-/**
- * A directory in the tree. Each element represents one directory.
- *
- * @param {DirectoryEntry} dirEntry DirectoryEntry of this item.
- * @param {DirectoryItem|DirectoryTree} parentDirItem Parent of this item.
- * @param {DirectoryModel} directoryModel Current DirectoryModel.
- * @extends {cr.ui.TreeItem}
- * @constructor
- */
-function DirectoryItem(dirEntry, parentDirItem, directoryModel) {
-  var item = cr.doc.createElement('div');
-  DirectoryItem.decorate(item, dirEntry, parentDirItem, directoryModel);
-  return item;
-}
-
-/**
- * @param {HTMLElement} el Element to be DirectoryItem.
- * @param {DirectoryEntry} dirEntry DirectoryEntry of this item.
- * @param {DirectoryItem|DirectoryTree} parentDirItem Parent of this item.
- * @param {DirectoryModel} directoryModel Current DirectoryModel.
- */
-DirectoryItem.decorate =
-    function(el, dirEntry, parentDirItem, directoryModel) {
-  el.__proto__ = DirectoryItem.prototype;
-  (/** @type {DirectoryItem} */ el).decorate(
-      dirEntry, parentDirItem, directoryModel);
-};
-
-DirectoryItem.prototype = {
-  __proto__: cr.ui.TreeItem.prototype,
-
-  /**
-   * The DirectoryEntry corresponding to this DirectoryItem. This may be
-   * a dummy DirectoryEntry.
-   * @type {DirectoryEntry|Object}
-   * @override
-   **/
-  get entry() {
-      return this.dirEntry_;
-  },
-
-  /**
-   * The element containing the label text and the icon.
-   * @type {!HTMLElement}
-   * @override
-   **/
-  get labelElement() {
-      return this.firstElementChild.querySelector('.label');
-  }
-};
-
-/**
- * @param {DirectoryEntry} dirEntry DirectoryEntry of this item.
- * @param {DirectoryItem|DirectoryTree} parentDirItem Parent of this item.
- * @param {DirectoryModel} directoryModel Current DirectoryModel.
- */
-DirectoryItem.prototype.decorate = function(
-    dirEntry, parentDirItem, directoryModel) {
-  var path = dirEntry.fullPath;
-  var label;
-  label = dirEntry.label ? dirEntry.label : dirEntry.name;
-
-  this.className = 'tree-item';
-  this.innerHTML =
-      '<div class="tree-row">' +
-      ' <span class="expand-icon"></span>' +
-      ' <span class="icon"></span>' +
-      ' <span class="label"></span>' +
-      ' <div class="root-eject"></div>' +
-      '</div>' +
-      '<div class="tree-children"></div>';
-  this.setAttribute('role', 'treeitem');
-
-  this.directoryModel_ = directoryModel;
-  this.parent_ = parentDirItem;
-  this.label = label;
-  this.fullPath = path;
-  this.dirEntry_ = dirEntry;
-  this.fileFilter_ = this.directoryModel_.getFileFilter();
-
-  // Sets hasChildren=false tentatively. This will be overridden after
-  // scanning sub-directories in DirectoryTreeUtil.updateSubElementsFromList.
-  this.hasChildren = false;
-
-  this.addEventListener('expand', this.onExpand_.bind(this), false);
-  var volumeManager = VolumeManager.getInstance();
-  var icon = this.querySelector('.icon');
-  icon.classList.add('volume-icon');
-  var iconType = PathUtil.getRootType(path);
-  if (iconType && PathUtil.isRootPath(path))
-    icon.setAttribute('volume-type-icon', iconType);
-  else
-    icon.setAttribute('file-type-icon', 'folder');
-
-  var eject = this.querySelector('.root-eject');
-  eject.hidden = !PathUtil.isUnmountableByUser(path);
-  eject.addEventListener('click',
-      function(event) {
-        event.stopPropagation();
-        if (!PathUtil.isUnmountableByUser(path))
-          return;
-
-        volumeManager.unmount(path, function() {}, function() {});
-      }.bind(this));
-
-  if (parentDirItem.expanded)
-    this.updateSubDirectories(false /* recursive */);
-};
-
-/**
- * Overrides WebKit's scrollIntoViewIfNeeded, which doesn't work well with
- * a complex layout. This call is not necessary, so we are ignoring it.
- *
- * @param {boolean} unused Unused.
- * @override
- */
-DirectoryItem.prototype.scrollIntoViewIfNeeded = function(unused) {
-};
-
-/**
- * Removes the child node, but without selecting the parent item, to avoid
- * unintended changing of directories. Removing is done externally, and other
- * code will navigate to another directory.
- *
- * @param {!cr.ui.TreeItem} child The tree item child to remove.
- * @override
- */
-DirectoryItem.prototype.remove = function(child) {
-  this.lastElementChild.removeChild(child);
-  if (this.items.length == 0)
-    this.hasChildren = false;
-};
-
-/**
- * Invoked when the item is being expanded.
- * @param {!UIEvent} e Event.
- * @private
- **/
-DirectoryItem.prototype.onExpand_ = function(e) {
-  this.updateSubDirectories(
-      true /* recursive */,
-      function() {},
-      function() {
-        this.expanded = false;
-      }.bind(this));
-
-  e.stopPropagation();
-};
-
-/**
- * Retrieves the latest subdirectories and update them on the tree.
- * @param {boolean} recursive True if the update is recursively.
- * @param {function()=} opt_successCallback Callback called on success.
- * @param {function()=} opt_errorCallback Callback called on error.
- */
-DirectoryItem.prototype.updateSubDirectories = function(
-    recursive, opt_successCallback, opt_errorCallback) {
-  DirectoryTreeUtil.updateSubDirectories(
-      this,
-      this.directoryModel_,
-      function(entries) {
-        this.entries_ = entries;
-        this.redrawSubDirectoryList_(recursive);
-        opt_successCallback && opt_successCallback();
-      }.bind(this),
-      opt_errorCallback);
-};
-
-/**
- * Redraw subitems with the latest information. The items are sorted in
- * alphabetical order, case insensitive.
- * @param {boolean} recursive True if the update is recursively.
- * @private
- */
-DirectoryItem.prototype.redrawSubDirectoryList_ = function(recursive) {
-  DirectoryTreeUtil.updateSubElementsFromList(
-      this,
-      function(i) { return this.entries_[i]; }.bind(this),
-      this.directoryModel_,
-      recursive);
-};
-
-/**
- * Select the item corresponding to the given {@code path}.
- * @param {string} path Path to be selected.
- */
-DirectoryItem.prototype.selectPath = function(path) {
-  if (path == this.fullPath) {
-    this.selected = true;
-    return;
-  }
-
-  if (DirectoryTreeUtil.searchAndSelectPath(this.items, path))
-    return;
-
-  // If the path doesn't exist, updates sub directories and tryes again.
-  this.updateSubDirectories(
-      false /* recursive */,
-      DirectoryTreeUtil.searchAndSelectPath.bind(null, this.items, path));
-};
-
-/**
- * Executes the assigned action as a drop target.
- */
-DirectoryItem.prototype.doDropTargetAction = function() {
-  this.expanded = true;
-};
-
-/**
- * Executes the assigned action. DirectoryItem performs changeDirectory.
- */
-DirectoryItem.prototype.doAction = function() {
-  if (this.fullPath != this.directoryModel_.getCurrentDirPath())
-    this.directoryModel_.changeDirectory(this.fullPath);
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// DirectoryTree
-
-/**
- * Tree of directories on the sidebar. This element is also the root of items,
- * in other words, this is the parent of the top-level items.
- *
- * @constructor
- * @extends {cr.ui.Tree}
- */
-function DirectoryTree() {}
-
-/**
- * Decorates an element.
- * @param {HTMLElement} el Element to be DirectoryTree.
- * @param {DirectoryModel} directoryModel Current DirectoryModel.
- */
-DirectoryTree.decorate = function(el, directoryModel) {
-  el.__proto__ = DirectoryTree.prototype;
-  (/** @type {DirectoryTree} */ el).decorate(directoryModel);
-};
-
-DirectoryTree.prototype = {
-  __proto__: cr.ui.Tree.prototype,
-
-  // DirectoryTree is always expanded.
-  get expanded() { return true; },
-  /**
-   * @param {boolean} value Not used.
-   */
-  set expanded(value) {},
-
-  /**
-   * The DirectoryEntry corresponding to this DirectoryItem. This may be
-   * a dummy DirectoryEntry.
-   * @type {DirectoryEntry|Object}
-   * @override
-   **/
-  get entry() {
-      return this.dirEntry_;
-  }
-};
-
-/**
- * Decorates an element.
- * @param {DirectoryModel} directoryModel Current DirectoryModel.
- */
-DirectoryTree.prototype.decorate = function(directoryModel) {
-  cr.ui.Tree.prototype.decorate.call(this);
-
-  this.directoryModel_ = directoryModel;
-  this.entries_ = [];
-
-  this.fileFilter_ = this.directoryModel_.getFileFilter();
-  this.fileFilter_.addEventListener('changed',
-                                    this.onFilterChanged_.bind(this));
-  /**
-   * The path of the root directory.
-   * @type {string}
-   */
-  this.fullPath = '/';
-  this.dirEntry_ = null;
-
-  /**
-   * The path of the current directory.
-   * @type {string}
-   */
-  this.currentPath_ = null;
-
-  this.directoryModel_.addEventListener('directory-changed',
-      this.onCurrentDirectoryChanged_.bind(this));
-
-  // Add a handler for directory change.
-  this.addEventListener('change', function() {
-    if (this.selectedItem && this.currentPath_ != this.selectedItem.fullPath) {
-      this.currentPath_ = this.selectedItem.fullPath;
-      this.selectedItem.doAction();
-      return;
-    }
-  }.bind(this));
-
-  this.privateOnDirectoryChangedBound_ =
-      this.onDirectoryContentChanged_.bind(this);
-  chrome.fileBrowserPrivate.onDirectoryChanged.addListener(
-      this.privateOnDirectoryChangedBound_);
-
-  this.scrollBar_ = MainPanelScrollBar();
-  this.scrollBar_.initialize(this.parentNode, this);
-};
-
-/**
- * Select the item corresponding to the given path.
- * @param {string} path Path to be selected.
- */
-DirectoryTree.prototype.selectPath = function(path) {
-  if ((this.entry && this.entry.fullPath == path) || this.currentPath_ == path)
-    return;
-  this.currentPath_ = path;
-  if (DirectoryTreeUtil.shouldHideTree(path)) {
-    this.clearTree_(true);
-    return;
-  }
-
-  this.selectPathInternal_(path);
-};
-
-/**
- * Select the item corresponding to the given path. This method is used
- * internally.
- * @param {string} path Path to be selected.
- * @private
- */
-DirectoryTree.prototype.selectPathInternal_ = function(path) {
-  var rootDirPath = PathUtil.getRootPath(path);
-
-  if (PathUtil.isSpecialSearchRoot(rootDirPath) ||
-      PathUtil.getRootType(rootDirPath) == RootType.DRIVE) {
-    rootDirPath = RootDirectory.DRIVE;
-  }
-
-  var onError = function() {
-    this.clearTree_(true);
-  }.bind(this);
-
-  if (this.fullPath != rootDirPath || !this.dirEntry_) {
-    this.fullPath = rootDirPath;
-
-    this.directoryModel_.resolveDirectory(
-        rootDirPath,
-        function(entry) {
-          if (this.fullPath != rootDirPath)
-            return;
-
-          this.dirEntry_ = entry;
-          this.selectPathInternal_(path);
-        }.bind(this),
-        onError);
-  } else {
-    if (this.selectedItem && path == this.selectedItem.fullPath)
-      return;
-
-    if (DirectoryTreeUtil.searchAndSelectPath(this.items, path))
-      return;
-
-    this.selectedItem = null;
-    this.updateSubDirectories(
-        false /* recursive */,
-        function() {
-          if (!DirectoryTreeUtil.searchAndSelectPath(
-              this.items, this.currentPath_))
-            this.selectedItem = null;
-          cr.dispatchSimpleEvent(this, 'content-updated');
-        }.bind(this),
-        onError);
-  }
-};
-
-/**
- * Retrieves the latest subdirectories and update them on the tree.
- * @param {boolean} recursive True if the update is recursively.
- * @param {function()=} opt_successCallback Callback called on success.
- * @param {function()=} opt_errorCallback Callback called on error.
- */
-DirectoryTree.prototype.updateSubDirectories = function(
-    recursive, opt_successCallback, opt_errorCallback) {
-  if (!this.currentPath_)
-    return;
-
-  DirectoryTreeUtil.updateSubDirectories(
-      this,
-      this.directoryModel_,
-      function(entries) {
-        this.entries_ = entries;
-        this.redraw(recursive);
-        if (opt_successCallback)
-          opt_successCallback();
-      }.bind(this),
-      opt_errorCallback);
-};
-
-/**
- * Redraw the list.
- * @param {boolean} recursive True if the update is recursively. False if the
- *     only root items are updated.
- */
-DirectoryTree.prototype.redraw = function(recursive) {
-  DirectoryTreeUtil.updateSubElementsFromList(
-      this,
-      function(i) { return this.entries_[i]; }.bind(this),
-      this.directoryModel_,
-      recursive);
-};
-
-/**
- * Invoked when the filter is changed.
- * @private
- */
-DirectoryTree.prototype.onFilterChanged_ = function() {
-  // Returns immediately, if the tree is hidden.
-  if (!this.currentPath_ || DirectoryTreeUtil.shouldHideTree(this.currentPath_))
-    return;
-
-  this.redraw(true /* recursive */);
-  cr.dispatchSimpleEvent(this, 'content-updated');
-};
-
-/**
- * Invoked when a directory is changed.
- * @param {!UIEvent} event Event.
- * @private
- */
-DirectoryTree.prototype.onDirectoryContentChanged_ = function(event) {
-  // Returns immediately, if the tree is hidden.
-  if (!this.currentPath_ || DirectoryTreeUtil.shouldHideTree(this.currentPath_))
-    return;
-
-  if (event.eventType == 'changed') {
-    var path = util.extractFilePath(event.directoryUrl);
-    DirectoryTreeUtil.updateChangedDirectoryItem(path, this);
-  }
-};
-
-/**
- * Invoked when the current directory is changed.
- * @param {!UIEvent} event Event.
- * @private
- */
-DirectoryTree.prototype.onCurrentDirectoryChanged_ = function(event) {
-  this.selectPath(event.newDirEntry.fullPath);
-};
-
-/**
- * Returns the path of the selected item.
- * @return {string} The current path.
- */
-DirectoryTree.prototype.getCurrentPath = function() {
-  return this.selectedItem ? this.selectedItem.fullPath : null;
-};
-
-/**
- * Clears the tree.
- * @param {boolean} redraw Redraw the tree if true.
- * @private
- */
-DirectoryTree.prototype.clearTree_ = function(redraw) {
-  this.dirEntry_ = null;
-  this.fullPath = '';
-  this.selectedItem = null;
-  this.entries_ = [];
-
-  if (redraw) {
-    this.redraw(false);
-    cr.dispatchSimpleEvent(this, 'content-updated');
-  }
-};
-
-/**
- * Sets the margin height for the transparent preview panel at the bottom.
- * @param {number} margin Margin to be set in px.
- */
-DirectoryTree.prototype.setBottomMarginForPanel = function(margin) {
-  this.style.paddingBottom = margin + 'px';
-  this.scrollBar_.setBottomMarginForPanel(margin);
-};
-
-/**
- * Updates the UI after the layout has changed.
- */
-DirectoryTree.prototype.relayout = function() {
-  cr.dispatchSimpleEvent(this, 'relayout');
-};
diff --git a/chrome/browser/resources/file_manager/js/util.js b/chrome/browser/resources/file_manager/js/util.js
index 490e736..59ce54e 100644
--- a/chrome/browser/resources/file_manager/js/util.js
+++ b/chrome/browser/resources/file_manager/js/util.js
@@ -755,7 +755,8 @@
  */
 util.platform = {
   /**
-   * @return {boolean} True if Files.app is running via "chrome://files".
+   * @return {boolean} True if Files.app is running via "chrome://files", open
+   * files or select folder dialog. False otherwise.
    */
   runningInBrowser: function() {
     return !window.appID;
@@ -943,12 +944,12 @@
  *     cache.
  */
 util.loadImage = function(image, url, opt_options, opt_isValid) {
-  return ImageLoader.Client.loadToImage(url,
-                                        image,
-                                        opt_options || {},
-                                        function() { },
-                                        function() { image.onerror(); },
-                                        opt_isValid);
+  return ImageLoaderClient.loadToImage(url,
+                                      image,
+                                      opt_options || {},
+                                      function() {},
+                                      function() { image.onerror(); },
+                                      opt_isValid);
 };
 
 /**
@@ -956,7 +957,7 @@
  * @param {number} taskId Task identifier returned by util.loadImage().
  */
 util.cancelLoadImage = function(taskId) {
-  ImageLoader.Client.getInstance().cancel(taskId);
+  ImageLoaderClient.getInstance().cancel(taskId);
 };
 
 /**
diff --git a/chrome/browser/resources/file_manager/main.html b/chrome/browser/resources/file_manager/main.html
index ec4d133..f483621 100644
--- a/chrome/browser/resources/file_manager/main.html
+++ b/chrome/browser/resources/file_manager/main.html
@@ -14,11 +14,11 @@
 
     <meta name="google" value="notranslate">
 
-    <link rel="stylesheet" href="chrome://resources/css/list.css"></link>
-    <link rel="stylesheet" href="chrome://resources/css/tree.css"></link>
-    <link rel="stylesheet" href="chrome://resources/css/table.css"></link>
     <link rel="stylesheet" href="chrome://resources/css/menu.css"></link>
 
+    <link rel="stylesheet" href="css/list.css"></link>
+    <link rel="stylesheet" href="css/table.css"></link>
+    <link rel="stylesheet" href="css/tree.css"></link>
     <link rel="stylesheet" href="css/combobutton.css"></link>
     <link rel="stylesheet" href="css/file_manager.css"></link>
     <link rel="stylesheet" href="css/file_types.css"></link>
@@ -39,7 +39,7 @@
       <script src="js/metrics.js"></script>
 
       <!-- Loads the client of the image loader extension -->
-      <script src="chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/client.js"></script>
+      <script src="chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/image_loader_client.js"></script>
 
       <script src="chrome://resources/js/load_time_data.js"></script>
       <script src="chrome://resources/js/cr.js"></script>
@@ -89,6 +89,7 @@
       <script src="js/butter_bar.js"></script>
       <script src="js/directory_contents.js"></script>
       <script src="js/directory_model.js"></script>
+      <script src="js/directory_tree.js"></script>
       <script src="js/drag_selector.js"></script>
       <script src="js/drive_banners.js"></script>
       <script src="js/error_dialog.js"></script>
@@ -102,7 +103,6 @@
       <script src="js/file_transfer_controller.js"></script>
       <script src="js/file_type.js"></script>
       <script src="js/scrollbar.js"></script>
-      <script src="js/sidebar.js"></script>
       <script src="js/tree.css.js"></script>
       <script src="js/volume_manager.js"></script>
       <script src="js/volume_list.js"></script>
@@ -118,7 +118,7 @@
 
   </head>
   <body i18n-values=".style.fontFamily:WEB_FONT_FAMILY;
-                     .style.fontSize:WEB_FONT_SIZE" new-ui>
+                     .style.fontSize:WEB_FONT_SIZE">
     <commands>
       <!-- We have to use U+XXXX notation here according to event.keyIdentifier
            property -->
@@ -168,6 +168,11 @@
       <command id="open-with" i18n-values="label:OPEN_WITH_BUTTON_LABEL">
       <command id="zip-selection"
                i18n-values="label:ZIP_SELECTION_BUTTON_LABEL">
+      <command id="share" i18n-values="label:SHARE_BUTTON_LABEL">
+
+      <command id="zoom-in" shortcut="U+00BB-Ctrl">
+      <command id="zoom-out" shortcut="U+00BD-Ctrl">
+      <command id="zoom-reset" shortcut="U+0030-Ctrl">
     </commands>
 
     <menu id="file-context-menu" class="chrome-menu" showShortcuts>
@@ -177,7 +182,8 @@
                 visibleif="full-page" hidden></menuitem>
       <hr id="default-action-separator" visibleif="full-page" hidden>
       <menuitem command="#toggle-pinned" checkable></menuitem>
-      <hr command="#toggle-pinned">
+      <menuitem command="#share"></menuitem>
+      <hr command="#share">
       <menuitem command="#cut" visibleif="full-page"></menuitem>
       <menuitem command="#copy" visibleif="full-page"></menuitem>
       <menuitem command="#paste" visibleif="full-page"></menuitem>
@@ -239,10 +245,9 @@
         <menuitem command="#cut"></menuitem>
         <menuitem command="#copy"></menuitem>
         <menuitem command="#paste"></menuitem>
-        <menuitem command="#delete"></menuitem>
+        <menuitem command="#delete" i18n-content=DELETE_BUTTON_LABEL></menuitem>
     </menu>
 
-    <div class=dialog-title invisibleif="full-page"></div>
     <div class=dialog-container>
       <div class=dialog-sidebar>
         <div class=dialog-sidebar-header>
@@ -314,16 +319,18 @@
               <div class=downloads-warning hidden></div>
             </div>
           </div>
-          <div class="preview-panel" visibility="hidden">
-            <div>
-              <div class="preview-thumbnails"></div>
-            </div>
-            <div id="preview-lines">
-              <div class="preview-summary">
-                <span class="preview-text"></span>
-                <span class="calculating-size" hidden></span>
+          <div class="preview-panel progressable" visibility="hidden">
+            <div class="left">
+              <div>
+                <div class="preview-thumbnails"></div>
               </div>
-              <div id="search-breadcrumbs" class="breadcrumbs"></div>
+              <div id="preview-lines">
+                <div class="preview-summary">
+                  <span class="preview-text"></span>
+                  <span class="calculating-size" hidden></span>
+                </div>
+                <div id="search-breadcrumbs" class="breadcrumbs"></div>
+              </div>
             </div>
             <div class="right buttonbar" visibleif="full-page">
               <button id="tasks" class="combobutton" menu="#tasks-menu"
@@ -332,30 +339,41 @@
               <button id="delete-button" command="#delete" tabindex="3"
                       i18n-values="aria-label:DELETE_BUTTON_LABEL"></button>
             </div>
+            <div class=preparing-label i18n-content=PREPARING_LABEL></div>
+            <div class=progress-bar>
+              <div class=progress-track></div>
+            </div>
+            <div class="right buttonbar" id="open-panel" visibleif="open-file open-multi-file">
+              <select class="file-type"></select>
+              <button class=ok disabled tabindex="6"></button>
+              <button class=cancel i18n-content=CANCEL_LABEL tabindex="7"></button>
+            </div>
           </div>
           <div id="unmounted-panel"></div>
           <div id="format-panel">
-              <div class="error"></div>
-              <button id="format-button" command="#format"></button>
+            <div class="error"></div>
+            <button id="format-button" command="#format"></button>
           </div>
         </div>
       </div>
     </div>
-    <div class=dialog-footer invisibleif="full-page">
-      <button id="new-folder" i18n-content=NEW_FOLDER_BUTTON_LABEL
-              visibleif="saveas-file folder" command="#newfolder" tabindex="4">
-      </button>
-      <div id="filename-input-box">
-        <div class=filename-label i18n-content=FILENAME_LABEL></div>
-        <input type=text spellcheck=false tabindex="5">
-      </div>
-      <div class=horizontal-spacer></div>
-      <div class=preparing-label i18n-content=PREPARING_LABEL></div>
-      <div class=progress-bar>
-        <div class=progress-track></div>
+    <div class="dialog-footer progressable" visibleif="saveas-file folder">
+      <div class="left">
+        <button id="new-folder" i18n-content=NEW_FOLDER_BUTTON_LABEL
+                visibleif="saveas-file folder" command="#newfolder"
+                tabindex="4">
+        </button>
+        <div id="filename-input-box">
+          <div class=filename-label i18n-content=FILENAME_LABEL></div>
+          <input type=text spellcheck=false tabindex="5">
+        </div>
+        <div class=preparing-label i18n-content=PREPARING_LABEL></div>
+        <div class=progress-bar>
+          <div class=progress-track></div>
+        </div>
       </div>
       <div class="right buttonbar">
-        <select id="file-type"></select>
+        <select class="file-type"></select>
         <button class=ok disabled tabindex="6"></button>
         <button class=cancel i18n-content=CANCEL_LABEL tabindex="7"></button>
       </div>
diff --git a/chrome/browser/resources/file_manager/manifest.json b/chrome/browser/resources/file_manager/manifest.json
index 31d203b..32bbcf8 100644
--- a/chrome/browser/resources/file_manager/manifest.json
+++ b/chrome/browser/resources/file_manager/manifest.json
@@ -8,9 +8,15 @@
   "incognito" : "split",
   "icons": {
     "16": "images/icon16.png",
-    "128": "images/icon128.png"
+    "32": "images/icon32.png",
+    "48": "images/icon48.png",
+    "64": "images/icon64.png",
+    "96": "images/icon96.png",
+    "128": "images/icon128.png",
+    "256": "images/icon256.png"
   },
   "permissions": [
+    "contextMenus",
     "experimental",
     "storage",
     "fileBrowserHandler",
diff --git a/chrome/browser/resources/file_manager/photo_import.html b/chrome/browser/resources/file_manager/photo_import.html
index b59134f..31e1b35 100644
--- a/chrome/browser/resources/file_manager/photo_import.html
+++ b/chrome/browser/resources/file_manager/photo_import.html
@@ -27,7 +27,7 @@
     <!-- Keep the list in sync with photo_import_scripts.js. -->
 
     <!-- Loads the client of the image loader extension -->
-    <script src="chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/client.js"></script>
+    <script src="chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/image_loader_client.js"></script>
 
     <script src="chrome://resources/js/load_time_data.js"></script>
     <script src="chrome://resources/js/util.js"></script>
diff --git a/chrome/browser/resources/gaia_auth/main.js b/chrome/browser/resources/gaia_auth/main.js
index eaeec8b..f17f48a 100644
--- a/chrome/browser/resources/gaia_auth/main.js
+++ b/chrome/browser/resources/gaia_auth/main.js
@@ -39,8 +39,6 @@
     this.gaiaUrl_ = params['gaiaUrl'] || this.GAIA_URL;
     this.inputLang_ = params['hl'];
     this.inputEmail_ = params['email'];
-    this.testEmail_ = params['test_email'];
-    this.testPassword_ = params['test_password'];
 
     document.addEventListener('DOMContentLoaded', this.onPageLoad.bind(this));
   },
@@ -64,10 +62,6 @@
       url += '&hl=' + encodeURIComponent(this.inputLang_);
     if (this.inputEmail_)
       url += '&Email=' + encodeURIComponent(this.inputEmail_);
-    if (this.testEmail_)
-      url += '&test_email=' + encodeURIComponent(this.testEmail_);
-    if (this.testPassword_)
-      url += '&test_pwd=' + encodeURIComponent(this.testPassword_);
     return url;
   },
 
diff --git a/chrome/browser/resources/gaia_auth/manifest_test.json b/chrome/browser/resources/gaia_auth/manifest_test.json
deleted file mode 100644
index 7a075de..0000000
--- a/chrome/browser/resources/gaia_auth/manifest_test.json
+++ /dev/null
@@ -1,42 +0,0 @@
-{
-  // chrome-extension://mfffpogegjflfpflabcdkioaeobkgjik/
-  "key": "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC4L17nAfeTd6Xhtx96WhQ6DSr8KdHeQmfzgCkieKLCgUkWdwB9G1DCuh0EPMDn1MdtSwUAT7xE36APEzi0X/UpKjOVyX8tCC3aQcLoRAE0aJAvCcGwK7qIaQaczHmHKvPC2lrRdzSoMMTC5esvHX+ZqIBMi123FOL0dGW6OPKzIwIBIw==",
-  "name": "GaiaTestAuthExtension",
-  "version": "0.0.1",
-  "manifest_version": 2,
-  "content_security_policy": "default-src 'self'; script-src 'self'; frame-src 'self' https://insecure.com https://www.google.com/accounts/ https://accounts.google.com https://accounts.youtube.com https://gaiastaging.corp.google.com http://localhost:*",
-  "description": "GAIA Test Component Extension",
-  "content_scripts": [
-    {
-      "matches": [
-          "https://www.google.com/accounts/*",
-          "https://accounts.google.com/*",
-          "https://gaiastaging.corp.google.com/*",
-          "https://insecure.com/*",
-          "http://localhost:*/*"
-      ],
-      "js": ["test/content.js"],
-      "all_frames": true
-    }
-  ],
-  "web_accessible_resources": [
-    "main.css",
-    "main.html",
-    "main.js",
-    "offline.css",
-    "offline.html",
-    "offline.js",
-    "success.html",
-    "success.js",
-    "util.js",
-    "test/content.js"
-  ],
-  "permissions": [
-      "https://insecure.com/*",
-      "https://www.google.com/accounts/*",
-      "https://accounts.google.com/*",
-      "https://gaiastaging.corp.google.com/*",
-      "chrome://oobe/",
-      "http://localhost:*/*"
-  ]
-}
diff --git a/chrome/browser/resources/gaia_auth/test/content.js b/chrome/browser/resources/gaia_auth/test/content.js
deleted file mode 100644
index 1bf055f..0000000
--- a/chrome/browser/resources/gaia_auth/test/content.js
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-console.log('Test script injected!');
-
-function getQueryParam(key, defaultVal) {
-  if (!defaultVal) defaultVal = '';
-  key = key.replace(/[\[]/, '\\\[').replace(/[\]]/, '\\\]');
-  var regex = new RegExp('[\\?&]' + key + '=([^&#]*)');
-  var qs = regex.exec(window.location.href);
-  if (qs == null)
-    return defaultVal;
-  else
-    return qs[1];
-}
-
-console.log(document.URL);
-if (document.URL.match(/https\:\/\/www\.google\.com\/accounts\/ServiceLogin/) ||
-    document.URL.match(/https\:\/\/accounts\.google\.com\/ServiceLogin/) ||
-    document.URL.match(
-        /https\:\/\/gaiastaging\.corp\.google\.com\/ServiceLogin/) ||
-    document.URL.match(/https\:\/\/insecure\.com\/accounts\/ServiceLogin/) ||
-  document.URL.match(/http\:\/\/localhost(:[0-9]*)?\/ServiceLogin/)) {
-  var testEmail = unescape(getQueryParam('test_email'));
-  var testPassword = unescape(getQueryParam('test_pwd'));
-  var testContinue = unescape(getQueryParam('continue'));
-  console.log('Got test account info: ' + testEmail + '/' + testPassword);
-  document.getElementById('Email').value = testEmail;
-  document.getElementById('Passwd').value = testPassword;
-  document.getElementById('continue').value = testContinue;
-  console.log('Form field changed!');
-  if (testEmail != '') {
-    document.getElementById('signIn').click();
-    console.log('Form submitted!');
-  }
-}
diff --git a/chrome/browser/resources/gaia_auth_host/gaia_auth_host.js b/chrome/browser/resources/gaia_auth_host/gaia_auth_host.js
index 642d5b4..5c421db 100644
--- a/chrome/browser/resources/gaia_auth_host/gaia_auth_host.js
+++ b/chrome/browser/resources/gaia_auth_host/gaia_auth_host.js
@@ -43,9 +43,7 @@
   var SUPPORTED_PARAMS = [
     'gaiaUrl',       // Gaia url to use;
     'hl',            // Language code for the user interface;
-    'email',         // Pre-fill the email field in Gaia UI;
-    'test_email',    // Used for test;
-    'test_password'  // Used for test;
+    'email'          // Pre-fill the email field in Gaia UI;
   ];
 
   /**
diff --git a/chrome/browser/resources/gesture_config.js b/chrome/browser/resources/gesture_config.js
index af6d855..9a28531 100644
--- a/chrome/browser/resources/gesture_config.js
+++ b/chrome/browser/resources/gesture_config.js
@@ -54,7 +54,7 @@
       var units = row.querySelector('.row-units');
 
       label.setAttribute('for', field.key);
-      label.textContent = field.label;
+      label.innerHTML = field.label;
       input.id = field.key;
       input.min = field.min || 0;
 
@@ -227,6 +227,14 @@
       units: ''
     },
     {
+      key: 'scroll_prediction_seconds',
+      label: 'Scroll prediction interval<br>' +
+          '(Enable scroll prediction in ' +
+              '<a href="chrome://flags">chrome://flags</a>)',
+      units: 'seconds',
+      step: 0.01
+    },
+    {
       key: 'min_swipe_speed',
       label: 'Minimum Swipe Speed',
       units: 'pixels/sec.'
diff --git a/chrome/browser/resources/google_now/background.js b/chrome/browser/resources/google_now/background.js
index bd76627..d52d18d 100644
--- a/chrome/browser/resources/google_now/background.js
+++ b/chrome/browser/resources/google_now/background.js
@@ -32,6 +32,9 @@
  */
 var HTTP_OK = 200;
 
+var HTTP_UNAUTHORIZED = 401;
+var HTTP_FORBIDDEN = 403;
+
 /**
  * Initial period for polling for Google Now Notifications cards to use when the
  * period from the server is not available.
@@ -68,6 +71,20 @@
 
 var LOCATION_WATCH_NAME = 'location-watch';
 
+var WELCOME_TOAST_NOTIFICATION_ID = 'enable-now-toast';
+
+/**
+ * The indices of the buttons that are displayed on the welcome toast.
+ * @enum {number}
+ */
+var ToastButtonIndex = {YES: 0, NO: 1};
+
+/**
+ * The action that the user performed on the welcome toast.
+ * @enum {number}
+ */
+var ToastOptionResponse = {CHOSE_YES: 1, CHOSE_NO: 2};
+
 /**
  * Checks if a new task can't be scheduled when another task is already
  * scheduled.
@@ -98,6 +115,8 @@
 var tasks = buildTaskManager(areTasksConflicting);
 
 // Add error processing to API calls.
+tasks.instrumentApiFunction(chrome.identity, 'getAuthToken', 1);
+tasks.instrumentApiFunction(chrome.identity, 'removeCachedAuthToken', 1);
 tasks.instrumentApiFunction(chrome.location.onLocationUpdate, 'addListener', 0);
 tasks.instrumentApiFunction(chrome.notifications, 'create', 2);
 tasks.instrumentApiFunction(chrome.notifications, 'update', 2);
@@ -134,7 +153,9 @@
   DISMISS_REQUEST_SUCCESS: 4,
   LOCATION_REQUEST: 5,
   LOCATION_UPDATE: 6,
-  EVENTS_TOTAL: 7  // EVENTS_TOTAL is not an event; all new events need to be
+  EXTENSION_START: 7,
+  SHOW_WELCOME_TOAST: 8,
+  EVENTS_TOTAL: 9  // EVENTS_TOTAL is not an event; all new events need to be
                    // added before it.
 };
 
@@ -155,6 +176,47 @@
 }
 
 /**
+ * Adds authorization behavior to the request.
+ * @param {XMLHttpRequest} request Server request.
+ * @param {function(boolean)} callbackBoolean Completion callback with 'success'
+ *     parameter.
+ */
+function setAuthorization(request, callbackBoolean) {
+  tasks.debugSetStepName('setAuthorization-getAuthToken');
+  chrome.identity.getAuthToken({interactive: false}, function(token) {
+    var errorMessage =
+        chrome.runtime.lastError && chrome.runtime.lastError.message;
+    console.log('setAuthorization: error=' + errorMessage +
+                ', token=' + (token && 'non-empty'));
+    if (chrome.runtime.lastError || !token) {
+      callbackBoolean(false);
+      return;
+    }
+
+    request.setRequestHeader('Authorization', 'Bearer ' + token);
+
+    // Instrument onloadend to remove stale auth tokens.
+    var originalOnLoadEnd = request.onloadend;
+    request.onloadend = tasks.wrapCallback(function(event) {
+      if (request.status == HTTP_FORBIDDEN ||
+          request.status == HTTP_UNAUTHORIZED) {
+        tasks.debugSetStepName('setAuthorization-removeCachedAuthToken');
+        chrome.identity.removeCachedAuthToken({token: token}, function() {
+          // After purging the token cache, call getAuthToken() again to let
+          // Chrome know about the problem with the token.
+          chrome.identity.getAuthToken({interactive: false}, function() {});
+          originalOnLoadEnd(event);
+        });
+      } else {
+        originalOnLoadEnd(event);
+      }
+    });
+
+    callbackBoolean(true);
+  });
+}
+
+/**
  * Shows a notification and remembers information associated with it.
  * @param {Object} card Google Now card represented as a set of parameters for
  *     showing a Chrome notification.
@@ -343,10 +405,9 @@
       ',' + position.coords.longitude +
       ',' + position.coords.accuracy;
 
-  // TODO(vadimt): Figure out how to send user's identity to the server.
   var request = buildServerRequest('notifications');
 
-  request.onloadend = tasks.wrapCallback(function(event) {
+  request.onloadend = function(event) {
     console.log('requestNotificationCards-onloadend ' + request.status);
     if (request.status == HTTP_OK) {
       recordEvent(DiagnosticEvent.REQUEST_FOR_CARDS_SUCCESS);
@@ -354,10 +415,16 @@
     } else {
       callback();
     }
-  });
+  };
 
-  tasks.debugSetStepName('requestNotificationCards-send-request');
-  request.send(requestParameters);
+  setAuthorization(request, function(success) {
+    if (success) {
+      tasks.debugSetStepName('requestNotificationCards-send-request');
+      request.send(requestParameters);
+    } else {
+      callback();
+    }
+  });
 }
 
 /**
@@ -411,16 +478,22 @@
   var requestParameters = 'id=' + notificationId +
                           '&dismissalAge=' + (Date.now() - dismissalTimeMs);
   var request = buildServerRequest('dismiss');
-  request.onloadend = tasks.wrapCallback(function(event) {
+  request.onloadend = function(event) {
     console.log('requestDismissingCard-onloadend ' + request.status);
     if (request.status == HTTP_OK)
       recordEvent(DiagnosticEvent.DISMISS_REQUEST_SUCCESS);
 
     callbackBoolean(request.status == HTTP_OK);
-  });
+  };
 
-  tasks.debugSetStepName('requestCardDismissal-send-request');
-  request.send(requestParameters);
+  setAuthorization(request, function(success) {
+    if (success) {
+      tasks.debugSetStepName('requestCardDismissal-send-request');
+      request.send(requestParameters);
+    } else {
+      callbackBoolean(false);
+    }
+  });
 }
 
 /**
@@ -522,6 +595,28 @@
 }
 
 /**
+ * Responds to a click of one of the buttons on the welcome toast.
+ * @param {number} buttonIndex The index of the button which was clicked.
+ */
+function onToastNotificationClicked(buttonIndex) {
+  if (buttonIndex == ToastButtonIndex.YES) {
+    chrome.metricsPrivate.recordUserAction('GoogleNow.WelcomeToastClickedYes');
+    storage.set({toastState: ToastOptionResponse.CHOSE_YES});
+
+    // TODO(zturner): Update chrome geolocation setting once the settings
+    // API is in place.
+    startPollingCards();
+  } else {
+    chrome.metricsPrivate.recordUserAction('GoogleNow.WelcomeToastClickedNo');
+    storage.set({toastState: ToastOptionResponse.CHOSE_NO});
+  }
+
+  chrome.notifications.clear(
+      WELCOME_TOAST_NOTIFICATION_ID,
+      function(wasCleared) {});
+}
+
+/**
  * Callback for chrome.notifications.onClosed event.
  * @param {string} notificationId Unique identifier of the notification.
  * @param {boolean} byUser Whether the notification was closed by the user.
@@ -530,6 +625,15 @@
   if (!byUser)
     return;
 
+  if (notificationId == WELCOME_TOAST_NOTIFICATION_ID) {
+    // Even though they only closed the notification without clicking no, treat
+    // it as though they clicked No anwyay, and don't show the toast again.
+    chrome.metricsPrivate.recordUserAction('GoogleNow.WelcomeToastDismissed');
+    storage.set({toastState: ToastOptionResponse.CHOSE_NO});
+    return;
+  }
+
+  // At this point we are guaranteed that the notification is a now card.
   chrome.metricsPrivate.recordUserAction('GoogleNow.Dismissed');
 
   tasks.add(DISMISS_CARD_TASK_NAME, function(callback) {
@@ -557,9 +661,10 @@
 }
 
 /**
- * Initializes the event page on install or on browser startup.
+ * Initializes the polling system to start monitoring location and fetching
+ * cards.
  */
-function initialize() {
+function startPollingCards() {
   // Create an update timer for a case when for some reason location request
   // gets stuck.
   updateCardsAttempts.start(MAXIMUM_POLLING_PERIOD_SECONDS);
@@ -567,6 +672,47 @@
   requestLocation();
 }
 
+/**
+ * Initializes the event page on install or on browser startup.
+ */
+function initialize() {
+  recordEvent(DiagnosticEvent.EXTENSION_START);
+  storage.get('toastState', function(items) {
+    // The toast state might be undefined (e.g. not in storage yet) if this is
+    // the first time ever being prompted.
+
+    // TODO(zturner): Get the value of isGeolocationEnabled from the settings
+    // api and additionally make sure it is true.
+    if (!items.toastState) {
+      showWelcomeToast();
+    } else if (items.toastState == ToastOptionResponse.CHOSE_YES) {
+      startPollingCards();
+    }
+  });
+}
+
+/**
+ * Displays a toast to the user asking if they want to opt in to receiving
+ * Google Now cards.
+ */
+function showWelcomeToast() {
+  recordEvent(DiagnosticEvent.SHOW_WELCOME_TOAST);
+  // TODO(zturner): Localize this once the component extension localization
+  // api is complete.
+  // TODO(zturner): Add icons.
+  var buttons = [{title: 'Yes'}, {title: 'No'}];
+  var options = {
+    type: 'basic',
+    title: 'Enable Google Now Cards',
+    message: 'Would you like to be shown Google Now cards?',
+    iconUrl: 'http://www.gstatic.com/googlenow/chrome/default.png',
+    priority: 2,
+    buttons: buttons
+  };
+  chrome.notifications.create(WELCOME_TOAST_NOTIFICATION_ID, options,
+      function(notificationId) {});
+}
+
 chrome.runtime.onInstalled.addListener(function(details) {
   console.log('onInstalled ' + JSON.stringify(details));
   if (details.reason != 'chrome_update') {
@@ -589,14 +735,18 @@
 
 chrome.notifications.onButtonClicked.addListener(
     function(notificationId, buttonIndex) {
-      chrome.metricsPrivate.recordUserAction(
-          'GoogleNow.ButtonClicked' + buttonIndex);
-      onNotificationClicked(notificationId, function(actionUrls) {
-        if (!Array.isArray(actionUrls.buttonUrls))
-          return undefined;
+      if (notificationId == WELCOME_TOAST_NOTIFICATION_ID) {
+        onToastNotificationClicked(buttonIndex);
+      } else {
+        chrome.metricsPrivate.recordUserAction(
+            'GoogleNow.ButtonClicked' + buttonIndex);
+        onNotificationClicked(notificationId, function(actionUrls) {
+          if (!Array.isArray(actionUrls.buttonUrls))
+            return undefined;
 
-        return actionUrls.buttonUrls[buttonIndex];
-      });
+          return actionUrls.buttonUrls[buttonIndex];
+        });
+      }
     });
 
 chrome.notifications.onClosed.addListener(onNotificationClosed);
diff --git a/chrome/browser/resources/google_now/background_test_util.js b/chrome/browser/resources/google_now/background_test_util.js
new file mode 100644
index 0000000..f59c34e
--- /dev/null
+++ b/chrome/browser/resources/google_now/background_test_util.js
@@ -0,0 +1,25 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Mocks for globals needed for loading background.js.
+
+function emptyMock() {}
+function buildTaskManager() {
+  return {instrumentApiFunction: emptyMock};
+}
+var instrumentApiFunction = emptyMock;
+var buildAttemptManager = emptyMock;
+var emptyListener = {addListener: emptyMock};
+chrome['location'] = {onLocationUpdate: emptyListener};
+chrome['notifications'] = {
+  onButtonClicked: emptyListener,
+  onClicked: emptyListener,
+  onClosed: emptyListener
+};
+chrome['omnibox'] = {onInputEntered: emptyListener};
+chrome['runtime'] = {
+  onInstalled: emptyListener,
+  onStartup: emptyListener
+};
+var storage = {};
diff --git a/chrome/browser/resources/google_now/background_unittest.gtestjs b/chrome/browser/resources/google_now/background_unittest.gtestjs
new file mode 100644
index 0000000..149c51c
--- /dev/null
+++ b/chrome/browser/resources/google_now/background_unittest.gtestjs
@@ -0,0 +1,42 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * Test fixture for ../background.js.
+ * @constructor
+ * @extends {testing.Test}
+ */
+function GoogleNowBackgroundUnitTest () {
+  testing.Test.call(this);
+}
+
+GoogleNowBackgroundUnitTest.prototype = {
+  __proto__: testing.Test.prototype,
+
+  /** @override */
+  extraLibraries: [
+    'background_test_util.js',
+    'background.js'
+  ]
+};
+
+TEST_F('GoogleNowBackgroundUnitTest', 'AreTasksConflicting', function() {
+  function testTaskPair(newTaskName, scheduledTaskName, expected) {
+    assertTrue(areTasksConflicting(newTaskName, scheduledTaskName) == expected,
+               '(' + newTaskName + ', ' + scheduledTaskName + ')');
+  }
+
+  testTaskPair(UPDATE_CARDS_TASK_NAME, UPDATE_CARDS_TASK_NAME, true);
+  testTaskPair(UPDATE_CARDS_TASK_NAME, DISMISS_CARD_TASK_NAME, false);
+  testTaskPair(UPDATE_CARDS_TASK_NAME, RETRY_DISMISS_TASK_NAME, false);
+
+  testTaskPair(DISMISS_CARD_TASK_NAME, UPDATE_CARDS_TASK_NAME, false);
+  testTaskPair(DISMISS_CARD_TASK_NAME, DISMISS_CARD_TASK_NAME, false);
+  testTaskPair(DISMISS_CARD_TASK_NAME, RETRY_DISMISS_TASK_NAME, false);
+
+  testTaskPair(RETRY_DISMISS_TASK_NAME, UPDATE_CARDS_TASK_NAME, true);
+  testTaskPair(RETRY_DISMISS_TASK_NAME, DISMISS_CARD_TASK_NAME, true);
+  testTaskPair(RETRY_DISMISS_TASK_NAME, RETRY_DISMISS_TASK_NAME, true);
+});
+
diff --git a/chrome/browser/resources/google_now/manifest.json b/chrome/browser/resources/google_now/manifest.json
index 0e92514..21e465e 100644
--- a/chrome/browser/resources/google_now/manifest.json
+++ b/chrome/browser/resources/google_now/manifest.json
@@ -14,7 +14,8 @@
     "tabs",
     // TODO(vadimt): Replace <all_urls> with real URL patterns once we know
     // them.
-    "<all_urls>"
+    "<all_urls>",
+    "identity"
   ],
   "manifest_version": 2,
   "background": {
@@ -22,5 +23,9 @@
     "persistent": false
   },
   // TODO(vadimt): Remove using chrome.omnibox.
-  "omnibox": { "keyword" : "gn_url" }
+  "omnibox": { "keyword" : "gn_url" },
+  "oauth2": {
+    "auto_approve": true,
+    "scopes": ["https://www.googleapis.com/auth/googlenow"]
+  }
 }
diff --git a/chrome/browser/resources/google_now/utility.js b/chrome/browser/resources/google_now/utility.js
index 3ada667..9405bde 100644
--- a/chrome/browser/resources/google_now/utility.js
+++ b/chrome/browser/resources/google_now/utility.js
@@ -152,11 +152,32 @@
    * @param {Error} error Error to report.
    */
   function sendErrorReport(error) {
-    var filteredStack = error.stack.replace(/.*\n/, '');
+    var filteredStack = error.stack.replace(/.*\n/, '\n');
+    var file;
+    var line;
+    var topFrameMatches = filteredStack.match(/\(.*\)/);
+    // topFrameMatches's example:
+    // (chrome-extension://pmofbkohncoogjjhahejjfbppikbjigm/utility.js:308:19)
+    var crashLocation = topFrameMatches && topFrameMatches[0];
+    if (crashLocation) {
+      var topFrameElements =
+          crashLocation.substring(1, crashLocation.length - 1).split(':');
+      // topFrameElements for the above example will look like:
+      // [0] chrome-extension
+      // [1] //pmofbkohncoogjjhahejjfbppikbjigm/utility.js
+      // [2] 308
+      // [3] 19
+      if (topFrameElements.length >= 3) {
+        file = topFrameElements[0] + ':' + topFrameElements[1];
+        line = topFrameElements[2];
+      }
+    }
     var requestParameters =
-        'name=' + escape(error.name) +
-        '&stack=' + escape(filteredStack);
-    var request = buildServerRequest('exception');
+        'error=' + encodeURIComponent(error.name) +
+        '&script=' + encodeURIComponent(file) +
+        '&line=' + encodeURIComponent(line) +
+        '&trace=' + encodeURIComponent(filteredStack);
+    var request = buildServerRequest('jserror');
     request.onloadend = function(event) {
       console.log('sendErrorReport status: ' + request.status);
     };
diff --git a/chrome/browser/resources/help/channel_change_page.css b/chrome/browser/resources/help/channel_change_page.css
new file mode 100644
index 0000000..3ee2f50
--- /dev/null
+++ b/chrome/browser/resources/help/channel_change_page.css
@@ -0,0 +1,34 @@
+/* Copyright 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#channel-change-page {
+  min-height: 200px;
+  width: 500px;
+}
+
+.channel-change-page-channel label {
+  margin-left: 10px;
+}
+
+.channel-change-page-channel {
+  display: block;
+  margin: 15px 25px;
+}
+
+.show-when-selected-channel-requires-powerwash,
+.show-when-selected-channel-requires-delayed-update,
+.show-when-selected-channel-good,
+.show-when-selected-channel-unstable {
+  display: none !important;
+}
+
+.selected-channel-requires-powerwash
+.show-when-selected-channel-requires-powerwash,
+.selected-channel-requires-delayed-update
+.show-when-selected-channel-requires-delayed-update,
+.selected-channel-good .show-when-selected-channel-good,
+.selected-channel-unstable .show-when-selected-channel-unstable {
+  display: block !important;
+}
diff --git a/chrome/browser/resources/help/channel_change_page.html b/chrome/browser/resources/help/channel_change_page.html
new file mode 100644
index 0000000..0b4de9f
--- /dev/null
+++ b/chrome/browser/resources/help/channel_change_page.html
@@ -0,0 +1,54 @@
+<div id="channel-change-page" class="page">
+  <div class="close-button"></div>
+  <h1 i18n-content="channelChangePageTitle"></h1>
+  <div class="content-area">
+    <div class="channel-change-page-channel">
+      <input id="channel-change-page-stable-optiop"
+          type="radio" name="channel" value="stable-channel">
+      <label for="channel-change-page-stable-optiop" i18n-content="stable">
+      </label>
+    </div>
+    <div class="channel-change-page-channel">
+      <input id="channel-change-page-beta-option"
+          type="radio" name="channel" value="beta-channel">
+      <label for="channel-change-page-beta-option" i18n-content="beta"></label>
+    </div>
+    <div class="channel-change-page-channel">
+      <input id="channel-change-page-dev-option"
+          type="radio" name="channel" value="dev-channel">
+      <label for="channel-change-page-dev-option" i18n-content="dev"></label>
+    </div>
+  </div>
+  <div class="content-area">
+    <div class="show-when-selected-channel-requires-powerwash">
+      <h2 i18n-content="channelChangePagePowerwashTitle"></h2>
+      <div i18n-content="channelChangePagePowerwashMessage"></div>
+    </div>
+    <div class="show-when-selected-channel-requires-delayed-update">
+      <h2 i18n-content="channelChangePageDelayedChangeTitle"></h2>
+      <div i18n-content="channelChangePageDelayedChangeMessage"></div>
+    </div>
+    <div class="show-when-selected-channel-unstable">
+      <h2 i18n-content="channelChangePageUnstableTitle"></h2>
+      <div i18n-content="channelChangePageUnstableMessage"></div>
+    </div>
+  </div>
+  <div class="action-area">
+    <div class="button-strip">
+      <button id="channel-change-page-powerwash-button"
+          class="show-when-selected-channel-requires-powerwash"
+          i18n-content="channelChangePagePowerwashButton">
+      </button>
+      <button id="channel-change-page-change-button"
+          class="show-when-selected-channel-requires-delayed-update
+                 show-when-selected-channel-good
+                 show-when-selected-channel-unstable"
+          i18n-content="channelChangePageChangeButton">
+      </button>
+      <button id="channel-change-page-cancel-button"
+          class="default-button"
+          i18n-content="channelChangePageCancelButton">
+      </button>
+    </div>
+  </div>
+</div>
diff --git a/chrome/browser/resources/help/channel_change_page.js b/chrome/browser/resources/help/channel_change_page.js
new file mode 100644
index 0000000..4f22ce8
--- /dev/null
+++ b/chrome/browser/resources/help/channel_change_page.js
@@ -0,0 +1,237 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+cr.define('help', function() {
+  /**
+   * Encapsulated handling of the channel change overlay.
+   */
+  function ChannelChangePage() {}
+
+  cr.addSingletonGetter(ChannelChangePage);
+
+  ChannelChangePage.prototype = {
+    __proto__: HTMLDivElement.prototype,
+
+    /**
+     * Name of the channel the device is currently on.
+     * @private
+     */
+    currentChannel_: null,
+
+    /**
+     * Name of the channel the device is supposed to be on.
+     * @private
+     */
+    targetChannel_: null,
+
+    /**
+     * True iff the device is enterprise-managed.
+     * @private
+     */
+    isEnterpriseManaged_: undefined,
+
+    /**
+     * List of the channels names, from the least stable to the most stable.
+     * @private
+     */
+    channelList_: ['dev-channel', 'beta-channel', 'stable-channel'],
+
+    /**
+     * List of the possible ui states.
+     * @private
+     */
+    uiClassTable_: ['selected-channel-requires-powerwash',
+                    'selected-channel-requires-delayed-update',
+                    'selected-channel-good',
+                    'selected-channel-unstable'],
+
+    /**
+     * Perform initial setup.
+     */
+    initialize: function() {
+      var self = this;
+
+      $('channel-change-page-cancel-button').onclick = function() {
+        help.HelpPage.cancelOverlay();
+      };
+
+      var options = this.getAllChannelOptions_();
+      for (var i = 0; i < options.length; i++) {
+        var option = options[i];
+        option.onclick = function() {
+          self.updateUI_(this.value);
+        };
+      }
+
+      $('channel-change-page-powerwash-button').onclick = function() {
+        self.setChannel_(self.getSelectedOption_(), true);
+        help.HelpPage.cancelOverlay();
+      };
+
+      $('channel-change-page-change-button').onclick = function() {
+        self.setChannel_(self.getSelectedOption_(), false);
+        help.HelpPage.cancelOverlay();
+      };
+    },
+
+    /**
+     * Returns the list of all radio buttons responsible for channel selection.
+     * @return {Array.<HTMLInputElement>} Array of radio buttons
+     * @private
+     */
+    getAllChannelOptions_: function() {
+      return $('channel-change-page').querySelectorAll('input[type="radio"]');
+    },
+
+    /**
+     * Returns value of the selected option.
+     * @return {string} Selected channel name or null, if neither
+     *     option is selected.
+     * @private
+     */
+    getSelectedOption_: function() {
+      var options = this.getAllChannelOptions_();
+      for (var i = 0; i < options.length; i++) {
+        var option = options[i];
+        if (option.checked)
+          return option.value;
+      }
+      return null;
+    },
+
+    /**
+     * Updates UI according to selected channel.
+     * @param {string} selectedChannel Selected channel
+     * @private
+     */
+    updateUI_: function(selectedChannel) {
+      var currentStability = this.channelList_.indexOf(this.currentChannel_);
+      var newStability = this.channelList_.indexOf(selectedChannel);
+
+      var newOverlayClass = null;
+
+      if (selectedChannel == this.currentChannel_) {
+        if (this.currentChannel_ != this.targetChannel_) {
+          // Allow user to switch back to the current channel.
+          newOverlayClass = 'selected-channel-good';
+        }
+      } else if (selectedChannel != this.targetChannel_) {
+        // Selected channel isn't equal to the current and target channel.
+        if (newStability > currentStability) {
+          // More stable channel is selected. For customer devices
+          // notify user about powerwash.
+          if (this.isEnterpriseManaged_)
+            newOverlayClass = 'selected-channel-requires-delayed-update';
+          else
+            newOverlayClass = 'selected-channel-requires-powerwash';
+        } else if (selectedChannel == 'dev-channel') {
+          // Warn user about unstable channel.
+          newOverlayClass = 'selected-channel-unstable';
+        } else {
+          // Switching to the less stable channel.
+          newOverlayClass = 'selected-channel-good';
+        }
+      }
+
+      // Switch to the new UI state.
+      for (var i = 0; i < this.uiClassTable_.length; i++)
+          $('channel-change-page').classList.remove(this.uiClassTable_[i]);
+
+      if (newOverlayClass)
+        $('channel-change-page').classList.add(newOverlayClass);
+    },
+
+    /**
+     * Sets the device target channel.
+     * @param {string} channel The name of the target channel
+     * @param {boolean} isPowerwashAllowed True iff powerwash is allowed
+     * @private
+     */
+    setChannel_: function(channel, isPowerwashAllowed) {
+      this.targetChannel_ = channel;
+      this.updateUI_(channel);
+      help.HelpPage.setChannel(channel, isPowerwashAllowed);
+    },
+
+    /**
+     * Updates page UI according to device owhership policy.
+     * @param {boolean} isEnterpriseManaged True if the device is
+     *     enterprise managed
+     * @private
+     */
+    updateIsEnterpriseManaged_: function(isEnterpriseManaged) {
+      this.isEnterpriseManaged_ = isEnterpriseManaged;
+      help.HelpPage.updateChannelChangePageContainerVisibility();
+    },
+
+    /**
+     * Updates name of the current channel, i.e. the name of the
+     * channel the device is currently on.
+     * @param {string} channel The name of the current channel
+     * @private
+     */
+    updateCurrentChannel_: function(channel) {
+     if (this.channelList_.indexOf(channel) < 0)
+        return;
+      this.currentChannel_ = channel;
+
+      var options = this.getAllChannelOptions_();
+      for (var i = 0; i < options.length; i++) {
+        var option = options[i];
+        if (option.value == channel)
+          option.checked = true;
+      }
+      help.HelpPage.updateChannelChangePageContainerVisibility();
+    },
+
+    /**
+     * Updates name of the target channel, i.e. the name of the
+     * channel the device is supposed to be in case of a pending
+     * channel change.
+     * @param {string} channel The name of the target channel
+     * @private
+     */
+    updateTargetChannel_: function(channel) {
+      if (this.channelList_.indexOf(channel) < 0)
+        return;
+      this.targetChannel_ = channel;
+      help.HelpPage.updateChannelChangePageContainerVisibility();
+    },
+
+    /**
+     * @return {boolean} True if the page is ready and can be
+     *     displayed, false otherwise
+     * @private
+     */
+    isPageReady_: function() {
+      if (typeof this.isEnterpriseManaged_ == 'undefined')
+        return false;
+      if (!this.currentChannel_ || !this.targetChannel_)
+        return false;
+      return true;
+    },
+  };
+
+  ChannelChangePage.updateIsEnterpriseManaged = function(isEnterpriseManaged) {
+    ChannelChangePage.getInstance().updateIsEnterpriseManaged_(
+        isEnterpriseManaged);
+  };
+
+  ChannelChangePage.updateCurrentChannel = function(channel) {
+    ChannelChangePage.getInstance().updateCurrentChannel_(channel);
+  };
+
+  ChannelChangePage.updateTargetChannel = function(channel) {
+    ChannelChangePage.getInstance().updateTargetChannel_(channel);
+  };
+
+  ChannelChangePage.isPageReady = function() {
+    return ChannelChangePage.getInstance().isPageReady_();
+  };
+
+  // Export
+  return {
+    ChannelChangePage: ChannelChangePage
+  };
+});
diff --git a/chrome/browser/resources/help/help.css b/chrome/browser/resources/help/help.css
index dff7612..f82eed0 100644
--- a/chrome/browser/resources/help/help.css
+++ b/chrome/browser/resources/help/help.css
@@ -7,6 +7,10 @@
   -webkit-user-select: text;
 }
 
+#overlay .page:not(.showing) {
+  display: none;
+}
+
 #about-container {
   -webkit-box-align: center;
   display: -webkit-box;
@@ -51,15 +55,24 @@
   margin-top: 200px;
 }
 
-#update-status-icon {
+.help-page-icon,
+.help-page-icon-large {
   background-repeat: no-repeat;
   display: inline-block;
-  height: 17px;
   margin-right: 4px;
   vertical-align: top;
+}
+
+.help-page-icon {
+  height: 17px;
   width: 17px;
 }
 
+.help-page-icon-large {
+  height: 22px;
+  width: 22px;
+}
+
 #update-status-icon.up-to-date {
   background-image: url('chrome://theme/IDR_UPDATE_UPTODATE');
   background-size: 17px;
@@ -101,3 +114,33 @@
 #channel-change-confirmation {
   margin-top: 5px;
 }
+
+#change-channel {
+  margin-top: 8px;
+}
+
+#channel-change-disallowed-icon {
+  -webkit-margin-start: 4px;
+  background-image: url('chrome://theme/IDR_CONTROLLED_SETTING_MANDATORY_GRAY');
+  background-size: 17px;
+  vertical-align: middle;
+}
+
+.channel-change-error-bubble {
+  display: -webkit-box;
+}
+
+.channel-change-error-icon {
+  -webkit-margin-start: 4px;
+  background-image:
+      url('chrome://theme/IDR_CONTROLLED_SETTING_MANDATORY_LARGE');
+  background-size: 22px;
+  vertical-align: top;
+}
+
+.channel-change-error-text {
+  -webkit-margin-start: 4px;
+  display: block;
+  vertical-align: top;
+  width: 240px;
+}
diff --git a/chrome/browser/resources/help/help.html b/chrome/browser/resources/help/help.html
index 3f1dbdd..40658fd 100644
--- a/chrome/browser/resources/help/help.html
+++ b/chrome/browser/resources/help/help.html
@@ -6,13 +6,31 @@
   <link rel="stylesheet" href="chrome://resources/css/chrome_shared.css">
   <link rel="stylesheet" href="../uber/uber_shared.css">
   <link rel="stylesheet" href="help.css">
+<if expr="pp_ifdef('chromeos')">
+  <link rel="stylesheet" href="chrome://resources/css/bubble.css">
+  <link rel="stylesheet" href="chrome://resources/css/overlay.css">
+  <link rel="stylesheet" href="channel_change_page.css">
+</if>
+
   <script src="chrome://resources/js/cr.js"></script>
   <script src="chrome://resources/js/load_time_data.js"></script>
   <script src="chrome://resources/js/util.js"></script>
+<if expr="pp_ifdef('chromeos')">
+  <script src="chrome://resources/js/cr/ui.js"></script>
+  <script src="chrome://resources/js/cr/ui/bubble.js"></script>
+  <script src="chrome://resources/js/cr/ui/overlay.js"></script>
+  <script src="chrome://resources/js/event_tracker.js"></script>
+  <script src="chrome://help-frame/channel_change_page.js"></script>
+</if>
   <script src="chrome://help-frame/help.js"></script>
 </head>
 <body class="uber-frame"
     i18n-values=".style.fontFamily:fontfamily;.style.fontSize:fontsize">
+  <div id="overlay-container" class="overlay" hidden>
+<if expr="pp_ifdef('chromeos')">
+    <include src="channel_change_page.html">
+</if>
+  </div>
   <div class="page">
     <header>
       <h1 i18n-content="aboutTitle"></h1>
@@ -40,7 +58,7 @@
 </if>
 <if expr="pp_ifdef('chromeos') or pp_ifdef('_google_chrome') or is_linux">
       <div id="update-status-container" hidden>
-        <div id="update-status-icon" class="up-to-date"></div>
+        <div id="update-status-icon" class="help-page-icon up-to-date"></div>
         <div id="update-status-message-container">
           <div id="update-status-message" i18n-content="updateCheckStarted">
           </div>
@@ -53,11 +71,16 @@
         <button id="promote" i18n-content="promote" hidden></button>
 </if>
         <button id="relaunch" i18n-content="relaunch" hidden></button>
+<if expr="pp_ifdef('chromeos')">
+        <button id="relaunch-and-powerwash"
+            i18n-content="relaunchAndPowerwash" hidden>
+        </button>
+</if>
       </div>
 </if>
 <if expr="pp_ifdef('chromeos')">
       <div id="more-info-container">
-        <section id="channel-changer-container">
+        <section id="channel-changer-container" hidden>
           <h3 i18n-content="channel"></h3>
           <select id="channel-changer">
             <option value="stable-channel" i18n-content="stable"></option>
@@ -66,6 +89,16 @@
           </select>
           <div id="channel-change-confirmation" hidden></div>
         </section>
+        <section id="channel-change-page-container" hidden>
+          <h3 i18n-content="channel"></h3>
+          <div id="current-channel"></div>
+          <button id="change-channel"
+              i18n-content="channelChangeButton" disabled>
+          </button>
+          <div id="channel-change-disallowed-icon"
+              class="help-page-icon" hidden>
+          </div>
+        </section>
         <section>
           <h3 i18n-content="webkit"></h3>
           <div i18n-content="webkitVersion" dir="ltr"></div>
diff --git a/chrome/browser/resources/help/help.js b/chrome/browser/resources/help/help.js
index 7aa3e52..2ed56c1 100644
--- a/chrome/browser/resources/help/help.js
+++ b/chrome/browser/resources/help/help.js
@@ -16,9 +16,41 @@
     __proto__: HTMLDivElement.prototype,
 
     /**
+     * True if after update powerwash button should be displayed.
+     * @private
+     */
+    powerwashAfterUpdate_: false,
+
+    /**
+     * List of the channels names.
+     * @private
+     */
+    channelList_: ['dev-channel', 'beta-channel', 'stable-channel'],
+
+    /**
+     * Bubble for error messages and notifications.
+     * @private
+     */
+    bubble_: null,
+
+    /**
+     * Name of the channel the device is currently on.
+     * @private
+     */
+    currentChannel_: null,
+
+    /**
+     * Name of the channel the device is supposed to be on.
+     * @private
+     */
+    targetChannel_: null,
+
+    /**
      * Perform initial setup.
      */
     initialize: function() {
+      var self = this;
+
       uber.onContentFrameLoaded();
 
       // Set the title.
@@ -51,18 +83,65 @@
       this.maybeSetOnClick_($('relaunch'), function() {
         chrome.send('relaunchNow');
       });
+      if (cr.isChromeOS) {
+        this.maybeSetOnClick_($('relaunch-and-powerwash'), function() {
+          chrome.send('relaunchAndPowerwash');
+        });
+
+        this.channelTable_ = {
+          'stable-channel': {
+              'name': loadTimeData.getString('stable'),
+              'label': loadTimeData.getString('currentChannelStable'),
+          },
+          'beta-channel': {
+              'name': loadTimeData.getString('beta'),
+              'label': loadTimeData.getString('currentChannelBeta')
+          },
+          'dev-channel': {
+              'name': loadTimeData.getString('dev'),
+              'label': loadTimeData.getString('currentChannelDev')
+          }
+        };
+      }
 
       var channelChanger = $('channel-changer');
       if (channelChanger) {
-        this.channelName_ = {
-            'stable-channel': loadTimeData.getString('stable'),
-            'beta-channel': loadTimeData.getString('beta'),
-            'dev-channel': loadTimeData.getString('dev')
-        };
-        var self = this;
         channelChanger.onchange = function(event) {
-          self.setReleaseChannel_(event.target.value);
-        }
+          self.setChannel_(event.target.value, false);
+        };
+      }
+
+      if (cr.isChromeOS) {
+        cr.ui.overlay.globalInitialization();
+        cr.ui.overlay.setupOverlay($('overlay-container'));
+        $('overlay-container').addEventListener('cancelOverlay', function() {
+          self.showOverlay_(null);
+        });
+
+        $('change-channel').onclick = function() {
+          self.showOverlay_($('channel-change-page'));
+        };
+
+        var channelChangeDisallowedError = document.createElement('div');
+        channelChangeDisallowedError.className = 'channel-change-error-bubble';
+
+        var channelChangeDisallowedIcon = document.createElement('div');
+        channelChangeDisallowedIcon.classList.add('help-page-icon-large');
+        channelChangeDisallowedIcon.classList.add('channel-change-error-icon');
+        channelChangeDisallowedError.appendChild(channelChangeDisallowedIcon);
+
+        var channelChangeDisallowedText = document.createElement('div');
+        channelChangeDisallowedText.className = 'channel-change-error-text';
+        channelChangeDisallowedText.textContent =
+            loadTimeData.getString('channelChangeDisallowedMessage');
+        channelChangeDisallowedError.appendChild(channelChangeDisallowedText);
+
+        $('channel-change-disallowed-icon').onclick = function() {
+            self.showBubble_(channelChangeDisallowedError,
+                             $('help-container'),
+                             $('channel-change-disallowed-icon'),
+                             cr.ui.ArrowLocation.TOP_END);
+        };
       }
 
       // Attempt to update.
@@ -70,6 +149,39 @@
     },
 
     /**
+     * Shows the bubble.
+     * @param {HTMLDivElement} content The content of the bubble.
+     * @param {HTMLElement} target The element at which the bubble points.
+     * @param {HTMLElement} domSibling The element after which the bubble is
+     *     added to the DOM.
+     * @param {cr.ui.ArrowLocation} location The arrow location.
+     * @private
+     */
+    showBubble_: function(content, domSibling, target, location) {
+      if (!cr.isChromeOS)
+        return;
+      this.hideBubble_();
+      var bubble = new cr.ui.AutoCloseBubble;
+      bubble.anchorNode = target;
+      bubble.domSibling = domSibling;
+      bubble.arrowLocation = location;
+      bubble.content = content;
+      bubble.show();
+      this.bubble_ = bubble;
+    },
+
+    /**
+     * Hides the bubble.
+     * @private
+     */
+    hideBubble_: function() {
+      if (!cr.isChromeOS)
+        return;
+      if (this.bubble_)
+        this.bubble_.hide();
+    },
+
+    /**
      * Toggles the visible state of the 'More Info' section.
      * @private
      */
@@ -98,25 +210,66 @@
      * @private
      */
     setUpdateImage_: function(state) {
-      $('update-status-icon').className = 'update-icon ' + state;
+      $('update-status-icon').className = 'help-page-icon ' + state;
+    },
+
+    /**
+     * Returns current overlay.
+     * @return {HTMLElement} Current overlay
+     * @private
+     */
+    getCurrentOverlay_: function() {
+      return document.querySelector('#overlay .page.showing');
+    },
+
+    /**
+     * @return {boolean} True, if new channel switcher UI is used,
+     *    false otherwise.
+     * @private
+     */
+    isNewChannelSwitcherUI_: function() {
+      return !loadTimeData.valueExists('disableNewChannelSwitcherUI');
+    },
+
+    /**
+     * @return {boolean} True if target and current channels are not
+     *     null and not equals
+     * @private
+     */
+    channelsDiffer_: function() {
+      var current = this.currentChannel_;
+      var target = this.targetChannel_;
+      return (current != null && target != null && current != target);
     },
 
     /**
      * @private
      */
     setUpdateStatus_: function(status, message) {
+      var channel = this.targetChannel_;
       if (status == 'checking') {
         this.setUpdateImage_('working');
         $('update-status-message').innerHTML =
             loadTimeData.getString('updateCheckStarted');
       } else if (status == 'updating') {
         this.setUpdateImage_('working');
-        $('update-status-message').innerHTML =
-            loadTimeData.getString('updating');
+        if (this.channelsDiffer_()) {
+          $('update-status-message').innerHTML =
+              loadTimeData.getStringF('updatingChannelSwitch',
+                                      this.channelTable_[channel].label);
+        } else {
+          $('update-status-message').innerHTML =
+              loadTimeData.getStringF('updating');
+        }
       } else if (status == 'nearly_updated') {
         this.setUpdateImage_('up-to-date');
-        $('update-status-message').innerHTML =
-            loadTimeData.getString('updateAlmostDone');
+        if (this.channelsDiffer_()) {
+          $('update-status-message').innerHTML =
+              loadTimeData.getString('successfulChannelSwitch');
+        } else {
+          $('update-status-message').innerHTML =
+              loadTimeData.getString('updateAlmostDone');
+        }
       } else if (status == 'updated') {
         this.setUpdateImage_('up-to-date');
         $('update-status-message').innerHTML =
@@ -134,6 +287,14 @@
         if (!cr.isMac)
           $('update-percentage').hidden = status != 'updating';
       }
+
+      if ($('relaunch-and-powerwash')) {
+        // It's allowed to do powerwash only for customer devices,
+        // when user explicitly decides to update to a more stable
+        // channel.
+        $('relaunch-and-powerwash').hidden =
+            !this.powerwashAfterUpdate_ || status != 'nearly_updated';
+      }
     },
 
     /**
@@ -201,14 +362,27 @@
      *     overlays are hidden.
      */
     showOverlay_: function(node) {
-      var currentlyShowingOverlay =
-        document.querySelector('#overlay .page.showing');
+      var currentlyShowingOverlay = this.getCurrentOverlay_();
       if (currentlyShowingOverlay)
         currentlyShowingOverlay.classList.remove('showing');
-
       if (node)
         node.classList.add('showing');
-      $('overlay').hidden = !node;
+      $('overlay-container').hidden = !node;
+    },
+
+    /**
+     * Updates name of the current channel, i.e. the name of the
+     * channel the device is currently on.
+     * @param {string} channel The name of the current channel
+     * @private
+     */
+    updateCurrentChannel_: function(channel) {
+      if (this.channelList_.indexOf(channel) < 0)
+        return;
+      $('current-channel').textContent = loadTimeData.getStringF(
+          'currentChannel', this.channelTable_[channel].label);
+      this.currentChannel_ = channel;
+      help.ChannelChangePage.updateCurrentChannel(channel);
     },
 
     /**
@@ -216,29 +390,24 @@
      * @private
      */
     updateEnableReleaseChannel_: function(enabled) {
-      $('channel-changer-container').hidden = !enabled;
+      this.updateChannelChangerContainerVisibility_(enabled);
+      $('change-channel').disabled = !enabled;
+      $('channel-change-disallowed-icon').hidden = enabled;
     },
 
     /**
+     * Sets the device target channel.
+     * @param {string} channel The name of the target channel
+     * @param {boolean} isPowerwashAllowed True iff powerwash is allowed
      * @private
      */
-    updateSelectedChannel_: function(value) {
-      var options = $('channel-changer').querySelectorAll('option');
-      for (var i = 0; i < options.length; i++) {
-        var option = options[i];
-        if (option.value == value)
-          option.selected = true;
-      }
-    },
-
-    /**
-     * @private
-     */
-    setReleaseChannel_: function(channel) {
-      chrome.send('setReleaseTrack', [channel]);
+    setChannel_: function(channel, isPowerwashAllowed) {
+      this.powerwashAfterUpdate_ = isPowerwashAllowed;
+      this.targetChannel_ = channel;
+      chrome.send('setChannel', [channel, isPowerwashAllowed]);
       $('channel-change-confirmation').hidden = false;
       $('channel-change-confirmation').textContent = loadTimeData.getStringF(
-          'channel-changed', this.channelName_[channel]);
+          'channel-changed', this.channelTable_[channel].name);
     },
 
     /**
@@ -250,6 +419,35 @@
       $('build-date-container').classList.remove('empty');
       $('build-date').textContent = buildDate;
     },
+
+    /**
+     * Updates channel-change-page-container visibility according to
+     * internal state.
+     * @private
+     */
+    updateChannelChangePageContainerVisibility_: function() {
+      if (!this.isNewChannelSwitcherUI_()) {
+        $('channel-change-page-container').hidden = true;
+        return;
+      }
+      $('channel-change-page-container').hidden =
+          !help.ChannelChangePage.isPageReady();
+    },
+
+    /**
+     * Updates channel-changer dropdown visibility if |visible| is
+     * true and new channel switcher UI is disallowed.
+     * @param {boolean} visible True if channel-changer should be
+     *     displayed, false otherwise.
+     * @private
+     */
+    updateChannelChangerContainerVisibility_: function(visible) {
+      if (this.isNewChannelSwitcherUI_()) {
+        $('channel-changer').hidden = true;
+        return;
+      }
+      $('channel-changer').hidden = !visible;
+    },
   };
 
   HelpPage.setUpdateStatus = function(status, message) {
@@ -289,21 +487,43 @@
     HelpPage.getInstance().showOverlay_(node);
   };
 
-  HelpPage.updateSelectedChannel = function(channel) {
-    HelpPage.getInstance().updateSelectedChannel_(channel);
+  HelpPage.cancelOverlay = function() {
+    HelpPage.getInstance().showOverlay_(null);
+  };
+
+  HelpPage.updateIsEnterpriseManaged = function(isEnterpriseManaged) {
+    if (!cr.isChromeOS)
+      return;
+    help.ChannelChangePage.updateIsEnterpriseManaged(isEnterpriseManaged);
+  };
+
+  HelpPage.updateCurrentChannel = function(channel) {
+    if (!cr.isChromeOS)
+      return;
+    HelpPage.getInstance().updateCurrentChannel_(channel);
+  };
+
+  HelpPage.updateTargetChannel = function(channel) {
+    if (!cr.isChromeOS)
+      return;
+    help.ChannelChangePage.updateTargetChannel(channel);
   };
 
   HelpPage.updateEnableReleaseChannel = function(enabled) {
     HelpPage.getInstance().updateEnableReleaseChannel_(enabled);
   };
 
-  HelpPage.setReleaseChannel = function(channel) {
-    HelpPage.getInstance().setReleaseChannel_(channel);
+  HelpPage.setChannel = function(channel, isPowerwashAllowed) {
+    HelpPage.getInstance().setChannel_(channel, isPowerwashAllowed);
   };
 
   HelpPage.setBuildDate = function(buildDate) {
     HelpPage.getInstance().setBuildDate_(buildDate);
-  }
+  };
+
+  HelpPage.updateChannelChangePageContainerVisibility = function() {
+    HelpPage.getInstance().updateChannelChangePageContainerVisibility_();
+  };
 
   // Export
   return {
@@ -316,4 +536,6 @@
  */
 window.onload = function() {
   help.HelpPage.getInstance().initialize();
+  if (cr.isChromeOS)
+    help.ChannelChangePage.getInstance().initialize();
 };
diff --git a/chrome/browser/resources/history/history.css b/chrome/browser/resources/history/history.css
index 9abc363..c929298 100644
--- a/chrome/browser/resources/history/history.css
+++ b/chrome/browser/resources/history/history.css
@@ -342,12 +342,12 @@
 }
 
 .no-checkboxes .entry .time {
-  min-width: 68px;
+  min-width: 73px;
 }
 
 .entry .time {
   color: rgb(151, 156, 160);
-  min-width: 55px;
+  min-width: 60px;
   overflow: hidden;
   text-align: right;
   text-overflow: ellipsis;
diff --git a/chrome/browser/resources/history/history.js b/chrome/browser/resources/history/history.js
index 892cce1..f1eac1f 100644
--- a/chrome/browser/resources/history/history.js
+++ b/chrome/browser/resources/history/history.js
@@ -12,6 +12,10 @@
 // measured in milliseconds.
 /** @const */ var BROWSING_GAP_TIME = 15 * 60 * 1000;
 
+// The largest bucket value for UMA histogram, based on entry ID. All entries
+// with IDs greater than this will be included in this bucket.
+/** @const */ var UMA_MAX_BUCKET_VALUE = 1000;
+
 // TODO(glen): Get rid of these global references, replace with a controller
 //     or just make the classes own more of the page.
 var historyModel;
@@ -53,6 +57,20 @@
   chrome.send('metricsHandler:recordAction', [actionDesc]);
 }
 
+/**
+ * Record a histogram value in UMA. If specified value is larger than the max
+ * bucket value, record the value in the largest bucket.
+ * @param {string} histogram The name of the histogram to be recorded in.
+ * @param {integer} value The value to record in the histogram.
+ */
+
+function recordUmaHistogram(histogram, value) {
+  chrome.send('metricsHandler:recordInHistogram',
+              [histogram,
+              ((value > UMA_MAX_BUCKET_VALUE) ? UMA_MAX_BUCKET_VALUE : value),
+              UMA_MAX_BUCKET_VALUE]);
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // Visit:
 
@@ -76,7 +94,7 @@
   this.deviceName = result.deviceName;
   this.deviceType = result.deviceType;
 
-  // The id will be set according to when the visit was displayed, not
+  // The ID will be set according to when the visit was displayed, not
   // received. Set to -1 to show that it has not been set yet.
   this.id_ = -1;
 
@@ -180,7 +198,7 @@
     visitEntryWrapper.classList.add('blocked-indicator');
     visitEntryWrapper.appendChild(this.getVisitAttemptDOM_());
   } else {
-    visitEntryWrapper.appendChild(this.getTitleDOM_());
+    visitEntryWrapper.appendChild(this.getTitleDOM_(isSearchResult));
     if (addTitleFavicon)
       this.addFaviconToElement_(visitEntryWrapper);
     visitEntryWrapper.appendChild(domain);
@@ -308,22 +326,33 @@
 /**
  * Returns the DOM element containing a link on the title of the URL for the
  * current visit.
+ * @param {boolean} isSearchResult Whether or not the entry is a search result.
  * @return {Element} DOM representation for the title block.
  * @private
  */
-Visit.prototype.getTitleDOM_ = function() {
+Visit.prototype.getTitleDOM_ = function(isSearchResult) {
   var node = createElementWithClassName('div', 'title');
   var link = document.createElement('a');
   link.href = this.url_;
   link.id = 'id-' + this.id_;
   link.target = '_top';
+  var integerId = parseInt(this.id_, 10);
   link.addEventListener('click', function() {
     recordUmaAction('EntryLinkClick_HistoryPage');
+    // Record the ID of the entry to signify how many entries are above this
+    // link on the page.
+    recordUmaHistogram('HistoryPage.ClickPosition', integerId);
   });
   link.addEventListener('contextmenu', function() {
     recordUmaAction('EntryLinkRightClick_HistoryPage');
   });
 
+  if (isSearchResult) {
+    link.addEventListener('click', function() {
+      recordUmaAction('SearchResultClick_HistoryPage');
+    });
+  }
+
   // Add a tooltip, since it might be ellipsized.
   // TODO(dubroy): Find a way to show the tooltip only when necessary.
   link.title = this.title_;
@@ -1619,6 +1648,12 @@
     checkbox.disabled = true;
     link.classList.add('to-be-removed');
     disabledItems.push(checkbox);
+    var integerId = parseInt(entry.visit.id_, 10);
+    // Record the ID of the entry to signify how many entries are above this
+    // link on the page.
+    recordUmaHistogram('HistoryPage.RemoveEntryPosition', integerId);
+    if (entry.parentNode.className == 'search-results')
+      recordUmaAction('SearchResultRemove_HistoryPage');
   }
 
   function onConfirmRemove() {
diff --git a/chrome/browser/resources/history/history_mobile.css b/chrome/browser/resources/history/history_mobile.css
index f5ee26e..a65c9d5 100644
--- a/chrome/browser/resources/history/history_mobile.css
+++ b/chrome/browser/resources/history/history_mobile.css
@@ -195,7 +195,7 @@
   display: none;
 }
 
-.entry .title-and-domain {
+.entry .visit-entry {
   -webkit-flex: auto;
   -webkit-flex-flow: column;
   -webkit-padding-start: 48px;
@@ -229,7 +229,7 @@
   display: -webkit-box;
 }
 
-.entry .title-and-domain {
+.entry .visit-entry {
   -webkit-box-flex: 1;
   -webkit-box-orient: vertical;
   -webkit-box-pack: center;
@@ -237,6 +237,10 @@
 }
 </if>
 
+.entry .bookmark-section {
+  display: none;
+}
+
 @media only screen and (max-width:600px) {
 
 /* Omit the time on very small screens. */
diff --git a/chrome/browser/resources/identity_internals.js b/chrome/browser/resources/identity_internals.js
index 4e1ea16..7e7a01f 100644
--- a/chrome/browser/resources/identity_internals.js
+++ b/chrome/browser/resources/identity_internals.js
@@ -7,7 +7,7 @@
 
   /**
    * Creates an identity token item.
-   * @param {Object} tokenInfo Object containing token information.
+   * @param {!Object} tokenInfo Object containing token information.
    * @constructor
    */
   function TokenListItem(tokenInfo) {
@@ -24,12 +24,12 @@
     /** @override */
     decorate: function() {
       this.textContent = '';
-      this.id = this.data_.tokenId;
+      this.id = this.data_.accessToken;
 
       var table = this.ownerDocument.createElement('table');
       var tbody = this.ownerDocument.createElement('tbody');
       tbody.appendChild(this.createEntry_(
-          'tokenId', this.data_.tokenId, 'token-id'));
+          'accessToken', this.data_.accessToken, 'access-token'));
       tbody.appendChild(this.createEntry_(
           'extensionName', this.data_.extensionName, 'extension-name'));
       tbody.appendChild(this.createEntry_(
@@ -114,7 +114,7 @@
       revokeButton.classList.add('revoke-button');
       revokeButton.addEventListener('click', function() {
         chrome.send('identityInternalsRevokeToken',
-                    [this.data_.extensionId, this.data_.tokenId]);
+                    [this.data_.extensionId, this.data_.accessToken]);
       }.bind(this));
       revokeButton.textContent = loadTimeData.getString('revoke');
       return revokeButton;
@@ -150,13 +150,13 @@
     /**
      * Removes a token node related to the specifed token ID from both the
      * internals data source as well as the user internface.
-     * @param {string} tokenId The id of the token to remove.
+     * @param {string} accessToken The id of the token to remove.
      * @private
      */
-    removeTokenNode_: function(tokenId) {
+    removeTokenNode_: function(accessToken) {
       var tokenIndex;
       for (var index = 0; index < this.data_.length; index++) {
-        if (this.data_[index].tokenId == tokenId) {
+        if (this.data_[index].accessToken == accessToken) {
           tokenIndex = index;
           break;
         }
@@ -167,7 +167,7 @@
         this.data_.splice(tokenIndex, 1);
 
       // Remove from the user interface.
-      var tokenNode = $(tokenId);
+      var tokenNode = $(accessToken);
       if (tokenNode)
         this.removeChild(tokenNode);
     },
@@ -188,7 +188,7 @@
 
   /**
    * Callback function accepting a list of tokens to be displayed.
-   * @param {Token[]} tokens A list of tokens to be displayed
+   * @param {!Token[]} tokens A list of tokens to be displayed
    */
   function returnTokens(tokens) {
     tokenList_.data_ = tokens;
@@ -197,12 +197,12 @@
 
   /**
    * Callback function that removes a token from UI once it has been revoked.
-   * @param {!Array.<string>} tokenIds Array with a single element, which is a
-   * token ID, of the token to be removed.
+   * @param {!Array.<string>} accessTokens Array with a single element, which is
+   * an access token to be removed.
    */
-  function tokenRevokeDone(tokenIds) {
-    assert(tokenIds.length > 0);
-    tokenList_.removeTokenNode_(tokenIds[0]);
+  function tokenRevokeDone(accessTokens) {
+    assert(accessTokens.length > 0);
+    tokenList_.removeTokenNode_(accessTokens[0]);
   }
 
   // Return an object with all of the exports.
diff --git a/chrome/browser/resources/image_loader/background.js b/chrome/browser/resources/image_loader/background.js
new file mode 100644
index 0000000..028a082
--- /dev/null
+++ b/chrome/browser/resources/image_loader/background.js
@@ -0,0 +1,8 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+'use strict';
+
+// Load the extension.
+ImageLoader.getInstance();
diff --git a/chrome/browser/resources/image_loader/cache.js b/chrome/browser/resources/image_loader/cache.js
new file mode 100644
index 0000000..dde287c
--- /dev/null
+++ b/chrome/browser/resources/image_loader/cache.js
@@ -0,0 +1,410 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+'use strict';
+
+/**
+ * Persistent cache storing images in an indexed database on the hard disk.
+ * @constructor
+ */
+function Cache() {
+  /**
+   * IndexedDB database handle.
+   * @type {IDBDatabase}
+   * @private
+   */
+  this.db_ = null;
+}
+
+/**
+ * Cache database name.
+ * @type {string}
+ * @const
+ */
+Cache.DB_NAME = 'image-loader';
+
+/**
+ * Cache database version.
+ * @type {number}
+ * @const
+ */
+Cache.DB_VERSION = 11;
+
+/**
+ * Memory limit for images data in bytes.
+ *
+ * @const
+ * @type {number}
+ */
+Cache.MEMORY_LIMIT = 250 * 1024 * 1024;  // 250 MB.
+
+/**
+ * Minimal amount of memory freed per eviction. Used to limit number of
+ * evictions which are expensive.
+ *
+ * @const
+ * @type {number}
+ */
+Cache.EVICTION_CHUNK_SIZE = 50 * 1024 * 1024;  // 50 MB.
+
+/**
+ * Creates a cache key.
+ *
+ * @param {Object} request Request options.
+ * @return {string} Cache key.
+ */
+Cache.createKey = function(request) {
+  return JSON.stringify({url: request.url,
+                         scale: request.scale,
+                         width: request.width,
+                         height: request.height,
+                         maxWidth: request.maxWidth,
+                         maxHeight: request.maxHeight});
+};
+
+/**
+ * Initializes the cache database.
+ * @param {function()} callback Completion callback.
+ */
+Cache.prototype.initialize = function(callback) {
+  // Establish a connection to the database or (re)create it if not available
+  // or not up to date. After changing the database's schema, increment
+  // Cache.DB_VERSION to force database recreating.
+  var openRequest = window.webkitIndexedDB.open(Cache.DB_NAME,
+                                                Cache.DB_VERSION);
+
+  openRequest.onsuccess = function(e) {
+    this.db_ = e.target.result;
+    callback();
+  }.bind(this);
+
+  openRequest.onerror = callback;
+
+  openRequest.onupgradeneeded = function(e) {
+    console.info('Cache database creating or upgrading.');
+    var db = e.target.result;
+    if (db.objectStoreNames.contains('metadata'))
+      db.deleteObjectStore('metadata');
+    if (db.objectStoreNames.contains('data'))
+      db.deleteObjectStore('data');
+    if (db.objectStoreNames.contains('settings'))
+      db.deleteObjectStore('settings');
+    db.createObjectStore('metadata', {keyPath: 'key'});
+    db.createObjectStore('data', {keyPath: 'key'});
+    db.createObjectStore('settings', {keyPath: 'key'});
+  };
+};
+
+/**
+ * Sets size of the cache.
+ *
+ * @param {number} size Size in bytes.
+ * @param {IDBTransaction=} opt_transaction Transaction to be reused. If not
+ *     provided, then a new one is created.
+ * @private
+ */
+Cache.prototype.setCacheSize_ = function(size, opt_transaction) {
+  var transaction = opt_transaction ||
+      this.db_.transaction(['settings'], 'readwrite');
+  var settingsStore = transaction.objectStore('settings');
+
+  settingsStore.put({key: 'size', value: size});  // Update asynchronously.
+};
+
+/**
+ * Fetches current size of the cache.
+ *
+ * @param {function(number)} onSuccess Callback to return the size.
+ * @param {function()} onFailure Failure callback.
+ * @param {IDBTransaction=} opt_transaction Transaction to be reused. If not
+ *     provided, then a new one is created.
+ * @private
+ */
+Cache.prototype.fetchCacheSize_ = function(
+    onSuccess, onFailure, opt_transaction) {
+  var transaction = opt_transaction ||
+      this.db_.transaction(['settings', 'metadata', 'data'], 'readwrite');
+  var settingsStore = transaction.objectStore('settings');
+  var sizeRequest = settingsStore.get('size');
+
+  sizeRequest.onsuccess = function(e) {
+    if (e.target.result)
+      onSuccess(e.target.result.value);
+    else
+      onSuccess(0);
+  };
+
+  sizeRequest.onerror = function() {
+    console.error('Failed to fetch size from the database.');
+    onFailure();
+  };
+};
+
+/**
+ * Evicts the least used elements in cache to make space for a new image and
+ * updates size of the cache taking into account the upcoming item.
+ *
+ * @param {number} size Requested size.
+ * @param {function()} onSuccess Success callback.
+ * @param {function()} onFailure Failure callback.
+ * @param {IDBTransaction=} opt_transaction Transaction to be reused. If not
+ *     provided, then a new one is created.
+ * @private
+ */
+Cache.prototype.evictCache_ = function(
+    size, onSuccess, onFailure, opt_transaction) {
+  var transaction = opt_transaction ||
+      this.db_.transaction(['settings', 'metadata', 'data'], 'readwrite');
+
+  // Check if the requested size is smaller than the cache size.
+  if (size > Cache.MEMORY_LIMIT) {
+    onFailure();
+    return;
+  }
+
+  var onCacheSize = function(cacheSize) {
+    if (size < Cache.MEMORY_LIMIT - cacheSize) {
+      // Enough space, no need to evict.
+      this.setCacheSize_(cacheSize + size, transaction);
+      onSuccess();
+      return;
+    }
+
+    var bytesToEvict = Math.max(size, Cache.EVICTION_CHUNK_SIZE);
+
+    // Fetch all metadata.
+    var metadataEntries = [];
+    var metadataStore = transaction.objectStore('metadata');
+    var dataStore = transaction.objectStore('data');
+
+    var onEntriesFetched = function() {
+      metadataEntries.sort(function(a, b) {
+        return b.lastLoadTimestamp - a.lastLoadTimestamp;
+      });
+
+      var totalEvicted = 0;
+      while (bytesToEvict > 0) {
+        var entry = metadataEntries.pop();
+        totalEvicted += entry.size;
+        bytesToEvict -= entry.size;
+        metadataStore.delete(entry.key);  // Remove asynchronously.
+        dataStore.delete(entry.key);  // Remove asynchronously.
+      }
+
+      this.setCacheSize_(cacheSize - totalEvicted + size, transaction);
+    }.bind(this);
+
+    metadataStore.openCursor().onsuccess = function(e) {
+      var cursor = event.target.result;
+      if (cursor) {
+        metadataEntries.push(cursor.value);
+        cursor.continue();
+      } else {
+        onEntriesFetched();
+      }
+    };
+  }.bind(this);
+
+  this.fetchCacheSize_(onCacheSize, onFailure, transaction);
+};
+
+/**
+ * Saves an image in the cache.
+ *
+ * @param {string} key Cache key.
+ * @param {string} data Image data.
+ * @param {number} timestamp Last modification timestamp. Used to detect
+ *     if the cache entry becomes out of date.
+ */
+Cache.prototype.saveImage = function(key, data, timestamp) {
+  if (!this.db_) {
+    console.warn('Cache database not available.');
+    return;
+  }
+
+  var onNotFoundInCache = function() {
+    var metadataEntry = {key: key,
+                         timestamp: timestamp,
+                         size: data.length,
+                         lastLoadTimestamp: Date.now()};
+    var dataEntry = {key: key,
+                     data: data};
+
+    var transaction = this.db_.transaction(['settings', 'metadata', 'data'],
+                                          'readwrite');
+    var metadataStore = transaction.objectStore('metadata');
+    var dataStore = transaction.objectStore('data');
+
+    var onCacheEvicted = function() {
+      metadataStore.put(metadataEntry);  // Add asynchronously.
+      dataStore.put(dataEntry);  // Add asynchronously.
+    };
+
+    // Make sure there is enough space in the cache.
+    this.evictCache_(data.length, onCacheEvicted, function() {}, transaction);
+  }.bind(this);
+
+  // Check if the image is already in cache. If not, then save it to cache.
+  this.loadImage(key, timestamp, function() {}, onNotFoundInCache);
+};
+
+/**
+ * Loads an image from the cache (if available) or returns null.
+ *
+ * @param {string} key Cache key.
+ * @param {number} timestamp Last modification timestamp. If different
+ *     that the one in cache, then the entry will be invalidated.
+ * @param {function(<string>)} onSuccess Success callback with the image's data.
+ * @param {function()} onFailure Failure callback.
+ */
+Cache.prototype.loadImage = function(key, timestamp, onSuccess, onFailure) {
+  if (!this.db_) {
+    console.warn('Cache database not available.');
+    onFailure();
+    return;
+  }
+
+  var transaction = this.db_.transaction(['settings', 'metadata', 'data'],
+                                         'readwrite');
+  var metadataStore = transaction.objectStore('metadata');
+  var dataStore = transaction.objectStore('data');
+  var metadataRequest = metadataStore.get(key);
+  var dataRequest = dataStore.get(key);
+
+  var metadataEntry = null;
+  var metadataReceived = false;
+  var dataEntry = null;
+  var dataReceived = false;
+
+  var onPartialSuccess = function() {
+    // Check if all sub-requests have finished.
+    if (!metadataReceived || !dataReceived)
+      return;
+
+    // Check if both entries are available or both unavailable.
+    if (!!metadataEntry != !!dataEntry) {
+      console.warn('Incosistent cache database.');
+      onFailure();
+      return;
+    }
+
+    // Process the responses.
+    if (!metadataEntry) {
+      // The image not found.
+      onFailure();
+    } else if (metadataEntry.timestamp != timestamp) {
+      // The image is not up to date, so remove it.
+      this.removeImage(key, function() {}, function() {}, transaction);
+      onFailure();
+    } else {
+      // The image is available. Update the last load time and return the
+      // image data.
+      metadataEntry.lastLoadTimestamp = Date.now();
+      metadataStore.put(metadataEntry);  // Added asynchronously.
+      onSuccess(dataEntry.data);
+    }
+  }.bind(this);
+
+  metadataRequest.onsuccess = function(e) {
+    if (e.target.result)
+      metadataEntry = e.target.result;
+    metadataReceived = true;
+    onPartialSuccess();
+  };
+
+  dataRequest.onsuccess = function(e) {
+    if (e.target.result)
+      dataEntry = e.target.result;
+    dataReceived = true;
+    onPartialSuccess();
+  };
+
+  metadataRequest.onerror = function() {
+    console.error('Failed to fetch metadata from the database.');
+    metadataReceived = true;
+    onPartialSuccess();
+  };
+
+  dataRequest.onerror = function() {
+    console.error('Failed to fetch image data from the database.');
+    dataReceived = true;
+    onPartialSuccess();
+  };
+};
+
+/**
+ * Removes the image from the cache.
+ *
+ * @param {string} key Cache key.
+ * @param {function()=} opt_onSuccess Success callback.
+ * @param {function()=} opt_onFailure Failure callback.
+ * @param {IDBTransaction=} opt_transaction Transaction to be reused. If not
+ *     provided, then a new one is created.
+ */
+Cache.prototype.removeImage = function(
+    key, opt_onSuccess, opt_onFailure, opt_transaction) {
+  if (!this.db_) {
+    console.warn('Cache database not available.');
+    return;
+  }
+
+  var transaction = opt_transaction ||
+      this.db_.transaction(['settings', 'metadata', 'data'], 'readwrite');
+  var metadataStore = transaction.objectStore('metadata');
+  var dataStore = transaction.objectStore('data');
+
+  var cacheSize = null;
+  var cacheSizeReceived = false;
+  var metadataEntry = null;
+  var metadataReceived = false;
+
+  var onPartialSuccess = function() {
+    if (!cacheSizeReceived || !metadataReceived)
+      return;
+
+    // If either cache size or metadata entry is not available, then it is
+    // an error.
+    if (cacheSize === null || !metadataEntry) {
+      if (opt_onFailure)
+        onFailure();
+      return;
+    }
+
+    if (opt_onSuccess)
+      opt_onSuccess();
+
+    this.setCacheSize_(cacheSize - metadataEntry.size, transaction);
+    metadataStore.delete(key);  // Delete asynchronously.
+    dataStore.delete(key);  // Delete asynchronously.
+  }.bind(this);
+
+  var onCacheSizeFailure = function() {
+    cacheSizeReceived = true;
+  };
+
+  var onCacheSizeSuccess = function(result) {
+    cacheSize = result;
+    cacheSizeReceived = true;
+    onPartialSuccess();
+  };
+
+  // Fetch the current cache size.
+  this.fetchCacheSize_(onCacheSizeSuccess, onCacheSizeFailure, transaction);
+
+  // Receive image's metadata.
+  var metadataRequest = metadataStore.get(key);
+
+  metadataRequest.onsuccess = function(e) {
+    if (e.target.result)
+      metadataEntry = e.target.result;
+    metadataReceived = true;
+    onPartialSuccess();
+  };
+
+  metadataRequest.onerror = function() {
+    console.error('Failed to remove an image.');
+    metadataReceived = true;
+    onPartialSuccess();
+  };
+};
diff --git a/chrome/browser/resources/image_loader/client.js b/chrome/browser/resources/image_loader/client.js
deleted file mode 100644
index 8d80ec7..0000000
--- a/chrome/browser/resources/image_loader/client.js
+++ /dev/null
@@ -1,366 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-var ImageLoader = ImageLoader || {};
-
-/**
- * Image loader's extension id.
- * @const
- * @type {string}
- */
-ImageLoader.EXTENSION_ID = 'pmfjbimdmchhbnneeidfognadeopoehp';
-
-/**
- * Client used to connect to the remote ImageLoader extension. Client class runs
- * in the extension, where the client.js is included (eg. Files.app).
- * It sends remote requests using IPC to the ImageLoader class and forwards
- * its responses.
- *
- * Implements cache, which is stored in the calling extension.
- *
- * @constructor
- */
-ImageLoader.Client = function() {
-  /**
-   * Hash array with active tasks.
-   * @type {Object}
-   * @private
-   */
-  this.tasks_ = {};
-
-  /**
-   * @type {number}
-   * @private
-   */
-  this.lastTaskId_ = 0;
-
-  /**
-   * LRU cache for images.
-   * @type {ImageLoader.Client.Cache}
-   * @private
-   */
-  this.cache_ = new ImageLoader.Client.Cache();
-};
-
-/**
- * Returns a singleton instance.
- * @return {ImageLoader.Client} ImageLoader.Client instance.
- */
-ImageLoader.Client.getInstance = function() {
-  if (!ImageLoader.Client.instance_)
-    ImageLoader.Client.instance_ = new ImageLoader.Client();
-  return ImageLoader.Client.instance_;
-};
-
-/**
- * Records binary metrics. Counts for true and false are stored as a histogram.
- * @param {string} name Histogram's name.
- * @param {boolean} value True or false.
- */
-ImageLoader.Client.recordBinary = function(name, value) {
-  chrome.metricsPrivate.recordValue(
-      { metricName: 'ImageLoader.Client.' + name,
-        type: 'histogram-linear',
-        min: 1,  // According to histogram.h, this should be 1 for enums.
-        max: 2,  // Maximum should be exclusive.
-        buckets: 3 },  // Number of buckets: 0, 1 and overflowing 2.
-      value ? 1 : 0);
-};
-
-/**
- * Records percent metrics, stored as a histogram.
- * @param {string} name Histogram's name.
- * @param {number} value Value (0..100).
- */
-ImageLoader.Client.recordPercentage = function(name, value) {
-  chrome.metricsPrivate.recordPercentage('ImageLoader.Client.' + name,
-                                         Math.round(value));
-};
-
-/**
- * Sends a message to the Image Loader extension.
- * @param {Object} request Hash array with request data.
- * @param {function(Object)=} opt_callback Response handling callback.
- *     The response is passed as a hash array.
- * @private
- */
-ImageLoader.Client.sendMessage_ = function(request, opt_callback) {
-  opt_callback = opt_callback || function(response) {};
-  var sendMessage = chrome.runtime ? chrome.runtime.sendMessage :
-                                     chrome.extension.sendMessage;
-  sendMessage(ImageLoader.EXTENSION_ID, request, opt_callback);
-};
-
-/**
- * Handles a message from the remote image loader and calls the registered
- * callback to pass the response back to the requester.
- *
- * @param {Object} message Response message as a hash array.
- * @private
- */
-ImageLoader.Client.prototype.handleMessage_ = function(message) {
-  if (!(message.taskId in this.tasks_)) {
-    // This task has been canceled, but was already fetched, so it's result
-    // should be discarded anyway.
-    return;
-  }
-
-  var task = this.tasks_[message.taskId];
-
-  // Check if the task is still valid.
-  if (task.isValid())
-    task.accept(message);
-
-  delete this.tasks_[message.taskId];
-};
-
-/**
- * Loads and resizes and image. Use opt_isValid to easily cancel requests
- * which are not valid anymore, which will reduce cpu consumption.
- *
- * @param {string} url Url of the requested image.
- * @param {function} callback Callback used to return response.
- * @param {Object=} opt_options Loader options, such as: scale, maxHeight,
- *     width, height and/or cache.
- * @param {function=} opt_isValid Function returning false in case
- *     a request is not valid anymore, eg. parent node has been detached.
- * @return {?number} Remote task id or null if loaded from cache.
- */
-ImageLoader.Client.prototype.load = function(
-    url, callback, opt_options, opt_isValid) {
-  opt_options = opt_options || {};
-  opt_isValid = opt_isValid || function() { return true; };
-
-  // Record cache usage.
-  ImageLoader.Client.recordPercentage('Cache.Usage', this.cache_.getUsage());
-
-  // Cancel old, invalid tasks.
-  var taskKeys = Object.keys(this.tasks_);
-  for (var index = 0; index < taskKeys.length; index++) {
-    var taskKey = taskKeys[index];
-    var task = this.tasks_[taskKey];
-    if (!task.isValid()) {
-      // Cancel this task since it is not valid anymore.
-      this.cancel(taskKey);
-      delete this.tasks_[taskKey];
-    }
-  }
-
-  // Replace the extension id.
-  var sourceId = chrome.i18n.getMessage('@@extension_id');
-  var targetId = ImageLoader.EXTENSION_ID;
-
-  url = url.replace('filesystem:chrome-extension://' + sourceId,
-                    'filesystem:chrome-extension://' + targetId);
-
-  // Try to load from cache, if available.
-  var cacheKey = ImageLoader.Client.Cache.createKey(url, opt_options);
-  if (opt_options.cache) {
-    // Load from cache.
-    ImageLoader.Client.recordBinary('Cached', 1);
-    var cachedData = this.cache_.loadImage(cacheKey, opt_options.timestamp);
-    if (cachedData) {
-      ImageLoader.Client.recordBinary('Cache.HitMiss', 1);
-      callback({status: 'success', data: cachedData});
-      return null;
-    } else {
-      ImageLoader.Client.recordBinary('Cache.HitMiss', 0);
-    }
-  } else {
-    // Remove from cache.
-    ImageLoader.Client.recordBinary('Cached', 0);
-    this.cache_.removeImage(cacheKey);
-  }
-
-  // Not available in cache, performing a request to a remote extension.
-  var request = opt_options;
-  this.lastTaskId_++;
-  var task = {isValid: opt_isValid};
-  this.tasks_[this.lastTaskId_] = task;
-
-  request.url = url;
-  request.taskId = this.lastTaskId_;
-  request.timestamp = opt_options.timestamp;
-
-  ImageLoader.Client.sendMessage_(
-      request,
-      function(result) {
-        // Save to cache.
-        if (result.status == 'success' && opt_options.cache)
-          this.cache_.saveImage(cacheKey, result.data, opt_options.timestamp);
-        callback(result);
-      }.bind(this));
-  return request.taskId;
-};
-
-/**
- * Cancels the request.
- * @param {number} taskId Task id returned by ImageLoader.Client.load().
- */
-ImageLoader.Client.prototype.cancel = function(taskId) {
-  ImageLoader.Client.sendMessage_({taskId: taskId, cancel: true});
-};
-
-/**
- * Least Recently Used (LRU) cache implementation to be used by
- * ImageLoader.Client class. It has memory constraints, so it will never
- * exceed specified memory limit defined in MEMORY_LIMIT.
- *
- * @constructor
- */
-ImageLoader.Client.Cache = function() {
-  this.images_ = [];
-  this.size_ = 0;
-};
-
-/**
- * Memory limit for images data in bytes.
- *
- * @const
- * @type {number}
- */
-ImageLoader.Client.Cache.MEMORY_LIMIT = 20 * 1024 * 1024;  // 20 MB.
-
-/**
- * Creates a cache key.
- *
- * @param {string} url Image url.
- * @param {Object=} opt_options Loader options as a hash array.
- * @return {string} Cache key.
- */
-ImageLoader.Client.Cache.createKey = function(url, opt_options) {
-  opt_options = opt_options || {};
-  return JSON.stringify({url: url,
-                         orientation: opt_options.orientation,
-                         scale: opt_options.scale,
-                         width: opt_options.width,
-                         height: opt_options.height,
-                         maxWidth: opt_options.maxWidth,
-                         maxHeight: opt_options.maxHeight});
-};
-
-/**
- * Evicts the least used elements in cache to make space for a new image.
- *
- * @param {number} size Requested size.
- * @private
- */
-ImageLoader.Client.Cache.prototype.evictCache_ = function(size) {
-  // Sort from the most recent to the oldest.
-  this.images_.sort(function(a, b) {
-    return b.lastLoadTimestamp - a.lastLoadTimestamp;
-  });
-
-  while (this.images_.length > 0 &&
-         (ImageLoader.Client.Cache.MEMORY_LIMIT - this.size_ < size)) {
-    var entry = this.images_.pop();
-    this.size_ -= entry.data.length;
-  }
-};
-
-/**
- * Saves an image in the cache.
- *
- * @param {string} key Cache key.
- * @param {string} data Image data.
- * @param {number=} opt_timestamp Last modification timestamp. Used to detect
- *     if the cache entry becomes out of date.
- */
-ImageLoader.Client.Cache.prototype.saveImage = function(
-    key, data, opt_timestamp) {
-  // If the image is currently in cache, then remove it.
-  if (this.images_[key])
-    this.removeImage(key);
-
-  if (ImageLoader.Client.Cache.MEMORY_LIMIT - this.size_ < data.length) {
-    ImageLoader.Client.recordBinary('Evicted', 1);
-    this.evictCache_(data.length);
-  } else {
-    ImageLoader.Client.recordBinary('Evicted', 0);
-  }
-
-  if (ImageLoader.Client.Cache.MEMORY_LIMIT - this.size_ >= data.length) {
-    this.images_[key] = {lastLoadTimestamp: Date.now(),
-                         timestamp: opt_timestamp ? opt_timestamp : null,
-                         data: data};
-    this.size_ += data.length;
-  }
-};
-
-/**
- * Loads an image from the cache (if available) or returns null.
- *
- * @param {string} key Cache key.
- * @param {number=} opt_timestamp Last modification timestamp. If different
- *     that the one in cache, then the entry will be invalidated.
- * @return {?string} Data of the loaded image or null.
- */
-ImageLoader.Client.Cache.prototype.loadImage = function(key, opt_timestamp) {
-  if (!(key in this.images_))
-    return null;
-
-  var entry = this.images_[key];
-  entry.lastLoadTimestamp = Date.now();
-
-  // Check if the image in cache is up to date. If not, then remove it and
-  // return null.
-  if (entry.timestamp != opt_timestamp) {
-    this.removeImage(key);
-    return null;
-  }
-
-  return entry.data;
-};
-
-/**
- * Returns cache usage.
- * @return {number} Value in percent points (0..100).
- */
-ImageLoader.Client.Cache.prototype.getUsage = function() {
-  return this.size_ / ImageLoader.Client.Cache.MEMORY_LIMIT * 100.0;
-};
-
-/**
- * Removes the image from the cache.
- * @param {string} key Cache key.
- */
-ImageLoader.Client.Cache.prototype.removeImage = function(key) {
-  if (!(key in this.images_))
-    return;
-
-  var entry = this.images_[key];
-  this.size_ -= entry.data.length;
-  delete this.images_[key];
-};
-
-// Helper functions.
-
-/**
- * Loads and resizes and image. Use opt_isValid to easily cancel requests
- * which are not valid anymore, which will reduce cpu consumption.
- *
- * @param {string} url Url of the requested image.
- * @param {Image} image Image node to load the requested picture into.
- * @param {Object} options Loader options, such as: orientation, scale,
- *     maxHeight, width, height and/or cache.
- * @param {function=} onSuccess Callback for success.
- * @param {function=} onError Callback for failure.
- * @param {function=} opt_isValid Function returning false in case
- *     a request is not valid anymore, eg. parent node has been detached.
- * @return {?number} Remote task id or null if loaded from cache.
- */
-ImageLoader.Client.loadToImage = function(url, image, options, onSuccess,
-    onError, opt_isValid) {
-  var callback = function(result) {
-    if (result.status == 'error') {
-      onError();
-      return;
-    }
-    image.src = result.data;
-    onSuccess();
-  };
-
-  return ImageLoader.Client.getInstance().load(
-      url, callback, options, opt_isValid);
-};
diff --git a/chrome/browser/resources/image_loader/image_loader.js b/chrome/browser/resources/image_loader/image_loader.js
index 0424642..3a88d8e 100644
--- a/chrome/browser/resources/image_loader/image_loader.js
+++ b/chrome/browser/resources/image_loader/image_loader.js
@@ -2,40 +2,32 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+'use strict';
+
 /**
  * Loads and resizes an image.
  * @constructor
  */
-var ImageLoader = function() {
-  /**
-   * Hash array of active requests.
-   * @type {Object}
-   * @private
-   */
-  this.requests_ = {};
-
+function ImageLoader() {
   /**
    * Persistent cache object.
-   * @type {ImageLoader.Cache}
+   * @type {Cache}
    * @private
    */
-  this.cache_ = new ImageLoader.Cache();
+  this.cache_ = new Cache();
 
   /**
    * Manages pending requests and runs them in order of priorities.
-   * @type {ImageLoader.Worker}
+   * @type {Worker}
    * @private
    */
-  this.worker_ = new ImageLoader.Worker();
+  this.worker_ = new Worker();
 
-  // Grant permissions to the local file system.
+  // Grant permissions to the local file system and initialize the cache.
   chrome.fileBrowserPrivate.requestFileSystem(function(filesystem) {
-    // TODO(mtomasz): Handle.
-  });
-
-  // Initialize the cache database, then start handling requests.
-  this.cache_.initialize(function() {
-    this.worker_.start();
+    this.cache_.initialize(function() {
+      this.worker_.start();
+    }.bind(this));
   }.bind(this));
 
   chrome.extension.onMessageExternal.addListener(function(request,
@@ -55,7 +47,7 @@
       return this.onMessage_(sender.id, request, failSafeSendResponse);
     }
   }.bind(this));
-};
+}
 
 /**
  * List of extensions allowed to perform image requests.
@@ -81,15 +73,11 @@
   var requestId = senderId + ':' + request.taskId;
   if (request.cancel) {
     // Cancel a task.
-    if (requestId in this.requests_) {
-      this.requests_[requestId].cancel();
-      delete this.requests_[requestId];
-    }
+    this.worker_.remove(requestId);
     return false;  // No callback calls.
   } else {
     // Create a request task and add it to the worker (queue).
-    var requestTask = new ImageLoader.Request(this.cache_, request, callback);
-    this.requests_[requestId] = requestTask;
+    var requestTask = new Request(requestId, this.cache_, request, callback);
     this.worker_.add(requestTask);
     return true;  // Request will call the callback.
   }
@@ -106,6 +94,29 @@
 };
 
 /**
+ * Checks if the options contain any image processing.
+ *
+ * @param {number} width Source width.
+ * @param {number} height Source height.
+ * @param {Object} options Resizing options as a hash array.
+ * @return {boolean} True if yes, false if not.
+ */
+ImageLoader.shouldProcess = function(width, height, options) {
+  var targetDimensions = ImageLoader.resizeDimensions(width, height, options);
+
+  // Dimensions has to be adjusted.
+  if (targetDimensions.width != width || targetDimensions.height != height)
+    return true;
+
+  // Orientation has to be adjusted.
+  if (options.orientation)
+    return true;
+
+  // No changes required.
+  return false;
+};
+
+/**
  * Calculates dimensions taking into account resize options, such as:
  * - scale: for scaling,
  * - maxWidth, maxHeight: for maximum dimensions,
@@ -179,6 +190,8 @@
   var orientation = options.orientation || 0;
 
   // For odd orientation values: 1 (90deg) and 3 (270deg) flip dimensions.
+  var drawImageWidth;
+  var drawImageHeight;
   if (orientation % 2) {
     drawImageWidth = target.height;
     drawImageHeight = target.width;
@@ -199,838 +212,3 @@
       drawImageWidth, drawImageHeight);
   targetContext.restore();
 };
-
-/**
- * Creates and starts downloading and then resizing of the image. Finally,
- * returns the image using the callback.
- *
- * @param {ImageLoader.Cache} cache Cache object.
- * @param {Object} request Request message as a hash array.
- * @param {function} callback Callback used to send the response.
- * @constructor
- */
-ImageLoader.Request = function(cache, request, callback) {
-  /**
-   * @type {ImageLoader.Cache}
-   * @private
-   */
-  this.cache_ = cache;
-
-  /**
-   * @type {Object}
-   * @private
-   */
-  this.request_ = request;
-
-  /**
-   * @type {function}
-   * @private
-   */
-  this.sendResponse_ = callback;
-
-  /**
-   * Temporary image used to download images.
-   * @type {Image}
-   * @private
-   */
-  this.image_ = new Image();
-
-  /**
-   * Used to download remote images using http:// or https:// protocols.
-   * @type {XMLHttpRequest}
-   * @private
-   */
-  this.xhr_ = new XMLHttpRequest();
-
-  /**
-   * Temporary canvas used to resize and compress the image.
-   * @type {HTMLCanvasElement}
-   * @private
-   */
-  this.canvas_ = document.createElement('canvas');
-
-  /**
-   * @type {CanvasRenderingContext2D}
-   * @private
-   */
-  this.context_ = this.canvas_.getContext('2d');
-
-  /**
-   * Callback to be called once downloading is finished.
-   * @type {function()}
-   * @private
-   */
-  this.downloadCallback_ = null;
-};
-
-/**
- * Returns priority of the request. The higher priority, the faster it will
- * be handled. The highest priority is 0. The default one is 2.
- *
- * @return {number} Priority.
- */
-ImageLoader.Request.prototype.getPriority = function() {
-  return (this.request_.priority !== undefined) ? this.request_.priority : 2;
-};
-
-/**
- * Tries to load the image from cache if exists and sends the response.
- *
- * @param {function()} onSuccess Success callback.
- * @param {function()} onFailure Failure callback.
- */
-ImageLoader.Request.prototype.loadFromCacheAndProcess = function(
-    onSuccess, onFailure) {
-  this.loadFromCache_(
-      function(data) {  // Found in cache.
-        this.sendImageData_(data);
-        onSuccess();
-      }.bind(this),
-      onFailure);  // Not found in cache.
-};
-
-/**
- * Tries to download the image, resizes and sends the response.
- * @param {function()} callback Completion callback.
- */
-ImageLoader.Request.prototype.downloadAndProcess = function(callback) {
-  if (this.downloadCallback_)
-    throw new Error('Downloading already started.');
-
-  this.downloadCallback_ = callback;
-  this.downloadOriginal_(this.onImageLoad_.bind(this),
-                         this.onImageError_.bind(this));
-};
-
-/**
- * Fetches the image from the persistent cache.
- *
- * @param {function()} onSuccess Success callback.
- * @param {function()} onFailure Failure callback.
- * @private
- */
-ImageLoader.Request.prototype.loadFromCache_ = function(onSuccess, onFailure) {
-  var cacheKey = ImageLoader.Cache.createKey(this.request_);
-
-  if (!this.request_.cache) {
-    // Cache is disabled for this request; therefore, remove it from cache
-    // if existed.
-    this.cache_.removeImage(cacheKey);
-    onFailure();
-    return;
-  }
-
-  if (!this.request_.timestamp) {
-    // Persistent cache is available only when a timestamp is provided.
-    onFailure();
-    return;
-  }
-
-  this.cache_.loadImage(cacheKey,
-                        this.request_.timestamp,
-                        onSuccess,
-                        onFailure);
-};
-
-/**
- * Saves the image to the persistent cache.
- *
- * @param {string} data The image's data.
- * @private
- */
-ImageLoader.Request.prototype.saveToCache_ = function(data) {
-  if (!this.request_.cache || !this.request_.timestamp) {
-    // Persistent cache is available only when a timestamp is provided.
-    return;
-  }
-
-  var cacheKey = ImageLoader.Cache.createKey(this.request_);
-  this.cache_.saveImage(cacheKey,
-                        data,
-                        this.request_.timestamp);
-};
-
-/**
- * Downloads an image directly or for remote resources using the XmlHttpRequest.
- *
- * @param {function()} onSuccess Success callback.
- * @param {function()} onFailure Failure callback.
- * @private
- */
-ImageLoader.Request.prototype.downloadOriginal_ = function(
-    onSuccess, onFailure) {
-  this.image_.onload = onSuccess;
-  this.image_.onerror = onFailure;
-
-  if (!this.request_.url.match(/^https?:/)) {
-    // Download directly.
-    this.image_.src = this.request_.url;
-    return;
-  }
-
-  // Download using an xhr request.
-  this.xhr_.responseType = 'blob';
-
-  this.xhr_.onerror = this.image_.onerror;
-  this.xhr_.onload = function() {
-    if (this.xhr_.status != 200) {
-      this.image_.onerror();
-      return;
-    }
-
-    // Process returnes data.
-    var reader = new FileReader();
-    reader.onerror = this.image_.onerror;
-    reader.onload = function(e) {
-      this.image_.src = e.target.result;
-    }.bind(this);
-
-    // Load the data to the image as a data url.
-    reader.readAsDataURL(this.xhr_.response);
-  }.bind(this);
-
-  // Perform a xhr request.
-  try {
-    this.xhr_.open('GET', this.request_.url, true);
-    this.xhr_.send();
-  } catch (e) {
-    this.image_.onerror();
-  }
-};
-
-/**
- * Sends the resized image via the callback.
- * @private
- */
-ImageLoader.Request.prototype.sendImage_ = function() {
-  // TODO(mtomasz): Keep format. Never compress using jpeg codec for lossless
-  // images such as png, gif.
-  var pngData = this.canvas_.toDataURL('image/png');
-  var jpegData = this.canvas_.toDataURL('image/jpeg', 0.9);
-  var imageData = pngData.length < jpegData.length * 2 ? pngData : jpegData;
-
-  // Send and store in the persistent cache.
-  this.sendImageData_(imageData);
-  this.saveToCache_(imageData);
-};
-
-/**
- * Sends the resized image via the callback.
- * @param {string} data Compressed image data.
- * @private
- */
-ImageLoader.Request.prototype.sendImageData_ = function(data) {
-  this.sendResponse_({status: 'success',
-                      data: data,
-                      taskId: this.request_.taskId});
-};
-
-/**
- * Handler, when contents are loaded into the image element. Performs resizing
- * and finalizes the request process.
- *
- * @param {function()} callback Completion callback.
- * @private
- */
-ImageLoader.Request.prototype.onImageLoad_ = function(callback) {
-  ImageLoader.resize(this.image_, this.canvas_, this.request_);
-  this.sendImage_();
-  this.cleanup_();
-  this.downloadCallback_();
-};
-
-/**
- * Handler, when loading of the image fails. Sends a failure response and
- * finalizes the request process.
- *
- * @param {function()} callback Completion callback.
- * @private
- */
-ImageLoader.Request.prototype.onImageError_ = function(callback) {
-  this.sendResponse_({status: 'error',
-                      taskId: this.request_.taskId});
-  this.cleanup_();
-  this.downloadCallback_();
-};
-
-/**
- * Cancels the request.
- */
-ImageLoader.Request.prototype.cancel = function() {
-  this.cleanup_();
-
-  // If downloading has started, then call the callback.
-  if (this.downloadCallback_)
-    this.downloadCallback_();
-};
-
-/**
- * Cleans up memory used by this request.
- * @private
- */
-ImageLoader.Request.prototype.cleanup_ = function() {
-  this.image_.onerror = function() {};
-  this.image_.onload = function() {};
-
-  // Transparent 1x1 pixel gif, to force garbage collecting.
-  this.image_.src = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAA' +
-      'ABAAEAAAICTAEAOw==';
-
-  this.xhr_.onerror = function() {};
-  this.xhr_.onload = function() {};
-  this.xhr_.abort();
-
-  // Dispose memory allocated by Canvas.
-  this.canvas_.width = 0;
-  this.canvas_.height = 0;
-};
-
-/**
- * Worker for requests. Fetches requests from a queue and processes them
- * synchronously, taking into account priorities. The highest priority is 0.
- */
-ImageLoader.Worker = function() {
-  /**
-   * List of requests waiting to be checked. If these items are available in
-   * cache, then they are processed immediately after starting the worker.
-   * However, if they have to be downloaded, then these requests are moved
-   * to pendingRequests_.
-   *
-   * @type {ImageLoader.Request}
-   * @private
-   */
-  this.newRequests_ = [];
-
-  /**
-   * List of pending requests for images to be downloaded.
-   * @type {ImageLoader.Request}
-   * @private
-   */
-  this.pendingRequests_ = [];
-
-  /**
-   * List of requests being processed.
-   * @type {ImageLoader.Request}
-   * @private
-   */
-  this.activeRequests_ = [];
-
-  /**
-   * If the worker has been started.
-   * @type {boolean}
-   * @private
-   */
-  this.started_ = false;
-};
-
-/**
- * Maximum download requests to be run in parallel.
- * @type {number}
- * @const
- */
-ImageLoader.Worker.MAXIMUM_IN_PARALLEL = 5;
-
-/**
- * Adds a request to the internal priority queue and executes it when requests
- * with higher priorities are finished. If the result is cached, then it is
- * processed immediately once the worker is started.
- *
- * @param {ImageLoader.Request} request Request object.
- */
-ImageLoader.Worker.prototype.add = function(request) {
-  if (!this.started_) {
-    this.newRequests_.push(request);
-    return;
-  }
-
-  // Already started, so cache is available. Items available in cache will
-  // be served immediately, other enqueued.
-  this.serveCachedOrEnqueue_(request);
-};
-
-/**
- * Serves cached image or adds the request to the pending list.
- *
- * @param {ImageLoader.Request} request Request object.
- * @private
- */
-ImageLoader.Worker.prototype.serveCachedOrEnqueue_ = function(request) {
-  request.loadFromCacheAndProcess(function() {}, function() {
-    // Not available in cache.
-    this.pendingRequests_.push(request);
-
-    // Sort requests by priorities.
-    this.pendingRequests_.sort(function(a, b) {
-      return a.getPriority() - b.getPriority();
-    });
-
-    // Continue handling the most important requests (if started).
-    if (this.started_)
-      this.continue_();
-  }.bind(this));
-};
-
-/**
- * Starts handling requests.
- */
-ImageLoader.Worker.prototype.start = function() {
-  this.started_ = true;
-
-  // Process tasks added before worker has been started.
-  for (var index = 0; index < this.newRequests_.length; index++) {
-    this.serveCachedOrEnqueue_(this.newRequests_[index]);
-  }
-  this.newRequests_ = [];
-
-  // Start serving enqueued requests.
-  this.continue_();
-};
-
-/**
- * Processes pending requests from the queue. There is no guarantee that
- * all of the tasks will be processed at once.
- *
- * @private
- */
-ImageLoader.Worker.prototype.continue_ = function() {
-  for (var index = 0; index < this.pendingRequests_.length; index++) {
-    var request = this.pendingRequests_[index];
-
-    // Run only up to MAXIMUM_IN_PARALLEL in the same time.
-    if (Object.keys(this.activeRequests_).length ==
-        ImageLoader.Worker.MAXIMUM_IN_PARALLEL) {
-      return;
-    }
-
-    delete this.pendingRequests_.splice(index, 1);
-    this.activeRequests_.push(request);
-
-    request.downloadAndProcess(this.finish_.bind(this, request));
-  }
-};
-
-/**
- * Handles finished requests.
- *
- * @param {ImageLoader.Request} request Finished request.
- * @private
- */
-ImageLoader.Worker.prototype.finish_ = function(request) {
-  var index = this.activeRequests_.indexOf(request);
-  if (index < 0)
-    console.warn('Request not found.');
-  delete this.activeRequests_.splice(index, 1);
-
-  // Continue handling the most important requests (if started).
-  if (this.started_)
-    this.continue_();
-};
-
-/**
- * Persistent cache storing images in an indexed database on the hard disk.
- * @constructor
- */
-ImageLoader.Cache = function() {
-  /**
-   * IndexedDB database handle.
-   * @type {IDBDatabase}
-   * @private
-   */
-  this.db_ = null;
-};
-
-/**
- * Cache database name.
- * @type {string}
- * @const
- */
-ImageLoader.Cache.DB_NAME = 'image-loader';
-
-/**
- * Cache database version.
- * @type {number}
- * @const
- */
-ImageLoader.Cache.DB_VERSION = 11;
-
-/**
- * Memory limit for images data in bytes.
- *
- * @const
- * @type {number}
- */
-ImageLoader.Cache.MEMORY_LIMIT = 250 * 1024 * 1024;  // 250 MB.
-
-/**
- * Minimal amount of memory freed per eviction. Used to limit number of
- * evictions which are expensive.
- *
- * @const
- * @type {number}
- */
-ImageLoader.Cache.EVICTION_CHUNK_SIZE = 50 * 1024 * 1024;  // 50 MB.
-
-/**
- * Creates a cache key.
- *
- * @param {Object} request Request options.
- * @return {string} Cache key.
- */
-ImageLoader.Cache.createKey = function(request) {
-  return JSON.stringify({url: request.url,
-                         scale: request.scale,
-                         width: request.width,
-                         height: request.height,
-                         maxWidth: request.maxWidth,
-                         maxHeight: request.maxHeight});
-};
-
-/**
- * Initializes the cache database.
- * @param {function()} callback Completion callback.
- */
-ImageLoader.Cache.prototype.initialize = function(callback) {
-  // Establish a connection to the database or (re)create it if not available
-  // or not up to date. After changing the database's schema, increment
-  // ImageLoader.Cache.DB_VERSION to force database recreating.
-  var openRequest = window.webkitIndexedDB.open(ImageLoader.Cache.DB_NAME,
-                                                ImageLoader.Cache.DB_VERSION);
-
-  openRequest.onsuccess = function(e) {
-    this.db_ = e.target.result;
-    callback();
-  }.bind(this);
-
-  openRequest.onerror = callback;
-
-  openRequest.onupgradeneeded = function(e) {
-    console.info('Cache database creating or upgrading.');
-    var db = e.target.result;
-    if (db.objectStoreNames.contains('metadata'))
-      db.deleteObjectStore('metadata');
-    if (db.objectStoreNames.contains('data'))
-      db.deleteObjectStore('data');
-    if (db.objectStoreNames.contains('settings'))
-      db.deleteObjectStore('settings');
-    db.createObjectStore('metadata', {keyPath: 'key'});
-    db.createObjectStore('data', {keyPath: 'key'});
-    db.createObjectStore('settings', {keyPath: 'key'});
-  };
-};
-
-/**
- * Sets size of the cache.
- *
- * @param {number} size Size in bytes.
- * @param {IDBTransaction=} opt_transaction Transaction to be reused. If not
- *     provided, then a new one is created.
- * @private
- */
-ImageLoader.Cache.prototype.setCacheSize_ = function(size, opt_transaction) {
-  var transaction = opt_transaction ||
-      this.db_.transaction(['settings'], 'readwrite');
-  var settingsStore = transaction.objectStore('settings');
-
-  settingsStore.put({key: 'size', value: size});  // Update asynchronously.
-};
-
-/**
- * Fetches current size of the cache.
- *
- * @param {function(number)} onSuccess Callback to return the size.
- * @param {function()} onFailure Failure callback.
- * @param {IDBTransaction=} opt_transaction Transaction to be reused. If not
- *     provided, then a new one is created.
- * @private
- */
-ImageLoader.Cache.prototype.fetchCacheSize_ = function(
-    onSuccess, onFailure, opt_transaction) {
-  var transaction = opt_transaction ||
-      this.db_.transaction(['settings', 'metadata', 'data'], 'readwrite');
-  var settingsStore = transaction.objectStore('settings');
-  var sizeRequest = settingsStore.get('size');
-
-  sizeRequest.onsuccess = function(e) {
-    if (e.target.result)
-      onSuccess(e.target.result.value);
-    else
-      onSuccess(0);
-  };
-
-  sizeRequest.onerror = function() {
-    console.error('Failed to fetch size from the database.');
-    onFailure();
-  };
-};
-
-/**
- * Evicts the least used elements in cache to make space for a new image and
- * updates size of the cache taking into account the upcoming item.
- *
- * @param {number} size Requested size.
- * @param {function()} onSuccess Success callback.
- * @param {function()} onFailure Failure callback.
- * @param {IDBTransaction=} opt_transaction Transaction to be reused. If not
- *     provided, then a new one is created.
- * @private
- */
-ImageLoader.Cache.prototype.evictCache_ = function(
-    size, onSuccess, onFailure, opt_transaction) {
-  var transaction = opt_transaction ||
-      this.db_.transaction(['settings', 'metadata', 'data'], 'readwrite');
-
-  // Check if the requested size is smaller than the cache size.
-  if (size > ImageLoader.Cache.MEMORY_LIMIT) {
-    onFailure();
-    return;
-  }
-
-  var onCacheSize = function(cacheSize) {
-    if (size < ImageLoader.Cache.MEMORY_LIMIT - cacheSize) {
-      // Enough space, no need to evict.
-      this.setCacheSize_(cacheSize + size, transaction);
-      onSuccess();
-      return;
-    }
-
-    var bytesToEvict = Math.max(size,
-                                ImageLoader.Cache.EVICTION_CHUNK_SIZE);
-
-    // Fetch all metadata.
-    var metadataEntries = [];
-    var metadataStore = transaction.objectStore('metadata');
-    var dataStore = transaction.objectStore('data');
-
-    var onEntriesFetched = function() {
-      metadataEntries.sort(function(a, b) {
-        return b.lastLoadTimestamp - a.lastLoadTimestamp;
-      });
-
-      var totalEvicted = 0;
-      while (bytesToEvict > 0) {
-        var entry = metadataEntries.pop();
-        totalEvicted += entry.size;
-        bytesToEvict -= entry.size;
-        metadataStore.delete(entry.key);  // Remove asynchronously.
-        dataStore.delete(entry.key);  // Remove asynchronously.
-      }
-
-      this.setCacheSize_(cacheSize - totalEvicted + size, transaction);
-    }.bind(this);
-
-    metadataStore.openCursor().onsuccess = function(e) {
-      var cursor = event.target.result;
-      if (cursor) {
-        metadataEntries.push(cursor.value);
-        cursor.continue();
-      } else {
-        onEntriesFetched();
-      }
-    };
-  }.bind(this);
-
-  this.fetchCacheSize_(onCacheSize, onFailure, transaction);
-};
-
-/**
- * Saves an image in the cache.
- *
- * @param {string} key Cache key.
- * @param {string} data Image data.
- * @param {number} timestamp Last modification timestamp. Used to detect
- *     if the cache entry becomes out of date.
- */
-ImageLoader.Cache.prototype.saveImage = function(key, data, timestamp) {
-  if (!this.db_) {
-    console.warn('Cache database not available.');
-    return;
-  }
-
-  var onNotFoundInCache = function() {
-    var metadataEntry = {key: key,
-                         timestamp: timestamp,
-                         size: data.length,
-                         lastLoadTimestamp: Date.now()};
-    var dataEntry = {key: key,
-                     data: data};
-
-    var transaction = this.db_.transaction(['settings', 'metadata', 'data'],
-                                          'readwrite');
-    var metadataStore = transaction.objectStore('metadata');
-    var dataStore = transaction.objectStore('data');
-
-    var onCacheEvicted = function() {
-      metadataStore.put(metadataEntry);  // Add asynchronously.
-      dataStore.put(dataEntry);  // Add asynchronously.
-    };
-
-    // Make sure there is enough space in the cache.
-    this.evictCache_(data.length, onCacheEvicted, function() {}, transaction);
-  }.bind(this);
-
-  // Check if the image is already in cache. If not, then save it to cache.
-  this.loadImage(key, timestamp, function() {}, onNotFoundInCache);
-};
-
-/**
- * Loads an image from the cache (if available) or returns null.
- *
- * @param {string} key Cache key.
- * @param {number} timestamp Last modification timestamp. If different
- *     that the one in cache, then the entry will be invalidated.
- * @param {function(<string>)} onSuccess Success callback with the image's data.
- * @param {function()} onFailure Failure callback.
- */
-ImageLoader.Cache.prototype.loadImage = function(
-    key, timestamp, onSuccess, onFailure) {
-  if (!this.db_) {
-    console.warn('Cache database not available.');
-    onFailure();
-    return;
-  }
-
-  var transaction = this.db_.transaction(['settings', 'metadata', 'data'],
-                                         'readwrite');
-  var metadataStore = transaction.objectStore('metadata');
-  var dataStore = transaction.objectStore('data');
-  var metadataRequest = metadataStore.get(key);
-  var dataRequest = dataStore.get(key);
-
-  var metadataEntry = null;
-  var metadataReceived = false;
-  var dataEntry = null;
-  var dataReceived = false;
-
-  var onPartialSuccess = function() {
-    // Check if all sub-requests have finished.
-    if (!metadataReceived || !dataReceived)
-      return;
-
-    // Check if both entries are available or both unavailable.
-    if (!!metadataEntry != !!dataEntry) {
-      console.warn('Incosistent cache database.');
-      onFailure();
-      return;
-    }
-
-    // Process the responses.
-    if (!metadataEntry) {
-      // The image not found.
-      onFailure();
-    } else if (metadataEntry.timestamp != timestamp) {
-      // The image is not up to date, so remove it.
-      this.removeImage(key, function() {}, function() {}, transaction);
-      onFailure();
-    } else {
-      // The image is available. Update the last load time and return the
-      // image data.
-      metadataEntry.lastLoadTimestamp = Date.now();
-      metadataStore.put(metadataEntry);  // Added asynchronously.
-      onSuccess(dataEntry.data);
-    }
-  }.bind(this);
-
-  metadataRequest.onsuccess = function(e) {
-    if (e.target.result)
-      metadataEntry = e.target.result;
-    metadataReceived = true;
-    onPartialSuccess();
-  };
-
-  dataRequest.onsuccess = function(e) {
-    if (e.target.result)
-      dataEntry = e.target.result;
-    dataReceived = true;
-    onPartialSuccess();
-  };
-
-  metadataRequest.onerror = function() {
-    console.error('Failed to fetch metadata from the database.');
-    metadataReceived = true;
-    onPartialSuccess();
-  };
-
-  dataRequest.onerror = function() {
-    console.error('Failed to fetch image data from the database.');
-    dataReceived = true;
-    onPartialSuccess();
-  };
-};
-
-/**
- * Removes the image from the cache.
- * @param {string} key Cache key.
- * @param {function()=} opt_onSuccess Success callback.
- * @param {function()=} opt_onFailure Failure callback.
- * @param {IDBTransaction=} opt_transaction Transaction to be reused. If not
- *     provided, then a new one is created.
- */
-ImageLoader.Cache.prototype.removeImage = function(
-    key, opt_onSuccess, opt_onFailure, opt_transaction) {
-  if (!this.db_) {
-    console.warn('Cache database not available.');
-    return;
-  }
-
-  var transaction = opt_transaction ||
-      this.db_.transaction(['settings', 'metadata', 'data'], 'readwrite');
-  var metadataStore = transaction.objectStore('metadata');
-  var dataStore = transaction.objectStore('data');
-
-  var cacheSize = null;
-  var cacheSizeReceived = false;
-  var metadataEntry = null;
-  var metadataReceived = false;
-
-  var onPartialSuccess = function() {
-    if (!cacheSizeReceived || !metadataReceived)
-      return;
-
-    // If either cache size or metadata entry is not available, then it is
-    // an error.
-    if (cacheSize === null || !metadataEntry) {
-      if (opt_onFailure)
-        onFailure();
-      return;
-    }
-
-    if (opt_onSuccess)
-      opt_onSuccess();
-
-    this.setCacheSize_(cacheSize - metadataEntry.size, transaction);
-    metadataStore.delete(key);  // Delete asynchronously.
-    dataStore.delete(key);  // Delete asynchronously.
-  }.bind(this);
-
-  var onCacheSizeFailure = function() {
-    cacheSizeReceived = true;
-  };
-
-  var onCacheSizeSuccess = function(result) {
-    cacheSize = result;
-    cacheSizeReceived = true;
-    onPartialSuccess();
-  };
-
-  // Fetch the current cache size.
-  this.fetchCacheSize_(onCacheSizeSuccess, onCacheSizeFailure, transaction);
-
-  // Receive image's metadata.
-  var metadataRequest = metadataStore.get(key);
-
-  metadataRequest.onsuccess = function(e) {
-    if (e.target.result)
-      metadataEntry = e.target.result;
-    metadataReceived = true;
-    onPartialSuccess();
-  };
-
-  metadataRequest.onerror = function() {
-    console.error('Failed to remove an image.');
-    metadataReceived = true;
-    onPartialSuccess();
-  };
-};
-
-// Load the extension.
-ImageLoader.getInstance();
diff --git a/chrome/browser/resources/image_loader/image_loader_client.js b/chrome/browser/resources/image_loader/image_loader_client.js
new file mode 100644
index 0000000..9baba59
--- /dev/null
+++ b/chrome/browser/resources/image_loader/image_loader_client.js
@@ -0,0 +1,366 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+'use strict';
+
+/**
+ * Client used to connect to the remote ImageLoader extension. Client class runs
+ * in the extension, where the client.js is included (eg. Files.app).
+ * It sends remote requests using IPC to the ImageLoader class and forwards
+ * its responses.
+ *
+ * Implements cache, which is stored in the calling extension.
+ *
+ * @constructor
+ */
+function ImageLoaderClient() {
+  /**
+   * Hash array with active tasks.
+   * @type {Object}
+   * @private
+   */
+  this.tasks_ = {};
+
+  /**
+   * @type {number}
+   * @private
+   */
+  this.lastTaskId_ = 0;
+
+  /**
+   * LRU cache for images.
+   * @type {ImageLoaderClient.Cache}
+   * @private
+   */
+  this.cache_ = new ImageLoaderClient.Cache();
+}
+
+/**
+ * Image loader's extension id.
+ * @const
+ * @type {string}
+ */
+ImageLoaderClient.EXTENSION_ID = 'pmfjbimdmchhbnneeidfognadeopoehp';
+
+/**
+ * Returns a singleton instance.
+ * @return {Client} Client instance.
+ */
+ImageLoaderClient.getInstance = function() {
+  if (!ImageLoaderClient.instance_)
+    ImageLoaderClient.instance_ = new ImageLoaderClient();
+  return ImageLoaderClient.instance_;
+};
+
+/**
+ * Records binary metrics. Counts for true and false are stored as a histogram.
+ * @param {string} name Histogram's name.
+ * @param {boolean} value True or false.
+ */
+ImageLoaderClient.recordBinary = function(name, value) {
+  chrome.metricsPrivate.recordValue(
+      { metricName: 'ImageLoader.Client.' + name,
+        type: 'histogram-linear',
+        min: 1,  // According to histogram.h, this should be 1 for enums.
+        max: 2,  // Maximum should be exclusive.
+        buckets: 3 },  // Number of buckets: 0, 1 and overflowing 2.
+      value ? 1 : 0);
+};
+
+/**
+ * Records percent metrics, stored as a histogram.
+ * @param {string} name Histogram's name.
+ * @param {number} value Value (0..100).
+ */
+ImageLoaderClient.recordPercentage = function(name, value) {
+  chrome.metricsPrivate.recordPercentage('ImageLoader.Client.' + name,
+                                         Math.round(value));
+};
+
+/**
+ * Sends a message to the Image Loader extension.
+ * @param {Object} request Hash array with request data.
+ * @param {function(Object)=} opt_callback Response handling callback.
+ *     The response is passed as a hash array.
+ * @private
+ */
+ImageLoaderClient.sendMessage_ = function(request, opt_callback) {
+  opt_callback = opt_callback || function(response) {};
+  var sendMessage = chrome.runtime ? chrome.runtime.sendMessage :
+                                     chrome.extension.sendMessage;
+  sendMessage(ImageLoaderClient.EXTENSION_ID, request, opt_callback);
+};
+
+/**
+ * Handles a message from the remote image loader and calls the registered
+ * callback to pass the response back to the requester.
+ *
+ * @param {Object} message Response message as a hash array.
+ * @private
+ */
+ImageLoaderClient.prototype.handleMessage_ = function(message) {
+  if (!(message.taskId in this.tasks_)) {
+    // This task has been canceled, but was already fetched, so it's result
+    // should be discarded anyway.
+    return;
+  }
+
+  var task = this.tasks_[message.taskId];
+
+  // Check if the task is still valid.
+  if (task.isValid())
+    task.accept(message);
+
+  delete this.tasks_[message.taskId];
+};
+
+/**
+ * Loads and resizes and image. Use opt_isValid to easily cancel requests
+ * which are not valid anymore, which will reduce cpu consumption.
+ *
+ * @param {string} url Url of the requested image.
+ * @param {function} callback Callback used to return response.
+ * @param {Object=} opt_options Loader options, such as: scale, maxHeight,
+ *     width, height and/or cache.
+ * @param {function=} opt_isValid Function returning false in case
+ *     a request is not valid anymore, eg. parent node has been detached.
+ * @return {?number} Remote task id or null if loaded from cache.
+ */
+ImageLoaderClient.prototype.load = function(
+    url, callback, opt_options, opt_isValid) {
+  opt_options = opt_options || {};
+  opt_isValid = opt_isValid || function() { return true; };
+
+  // Record cache usage.
+  ImageLoaderClient.recordPercentage('Cache.Usage', this.cache_.getUsage());
+
+  // Cancel old, invalid tasks.
+  var taskKeys = Object.keys(this.tasks_);
+  for (var index = 0; index < taskKeys.length; index++) {
+    var taskKey = taskKeys[index];
+    var task = this.tasks_[taskKey];
+    if (!task.isValid()) {
+      // Cancel this task since it is not valid anymore.
+      this.cancel(taskKey);
+      delete this.tasks_[taskKey];
+    }
+  }
+
+  // Replace the extension id.
+  var sourceId = chrome.i18n.getMessage('@@extension_id');
+  var targetId = ImageLoaderClient.EXTENSION_ID;
+
+  url = url.replace('filesystem:chrome-extension://' + sourceId,
+                    'filesystem:chrome-extension://' + targetId);
+
+  // Try to load from cache, if available.
+  var cacheKey = ImageLoaderClient.Cache.createKey(url, opt_options);
+  if (opt_options.cache) {
+    // Load from cache.
+    ImageLoaderClient.recordBinary('Cached', 1);
+    var cachedData = this.cache_.loadImage(cacheKey, opt_options.timestamp);
+    if (cachedData) {
+      ImageLoaderClient.recordBinary('Cache.HitMiss', 1);
+      callback({status: 'success', data: cachedData});
+      return null;
+    } else {
+      ImageLoaderClient.recordBinary('Cache.HitMiss', 0);
+    }
+  } else {
+    // Remove from cache.
+    ImageLoaderClient.recordBinary('Cached', 0);
+    this.cache_.removeImage(cacheKey);
+  }
+
+  // Not available in cache, performing a request to a remote extension.
+  var request = opt_options;
+  this.lastTaskId_++;
+  var task = {isValid: opt_isValid};
+  this.tasks_[this.lastTaskId_] = task;
+
+  request.url = url;
+  request.taskId = this.lastTaskId_;
+  request.timestamp = opt_options.timestamp;
+
+  ImageLoaderClient.sendMessage_(
+      request,
+      function(result) {
+        // Save to cache.
+        if (result.status == 'success' && opt_options.cache)
+          this.cache_.saveImage(cacheKey, result.data, opt_options.timestamp);
+        callback(result);
+      }.bind(this));
+  return request.taskId;
+};
+
+/**
+ * Cancels the request.
+ * @param {number} taskId Task id returned by ImageLoaderClient.load().
+ */
+ImageLoaderClient.prototype.cancel = function(taskId) {
+  ImageLoaderClient.sendMessage_({taskId: taskId, cancel: true});
+};
+
+/**
+ * Least Recently Used (LRU) cache implementation to be used by
+ * Client class. It has memory constraints, so it will never
+ * exceed specified memory limit defined in MEMORY_LIMIT.
+ *
+ * @constructor
+ */
+ImageLoaderClient.Cache = function() {
+  this.images_ = [];
+  this.size_ = 0;
+};
+
+/**
+ * Memory limit for images data in bytes.
+ *
+ * @const
+ * @type {number}
+ */
+ImageLoaderClient.Cache.MEMORY_LIMIT = 20 * 1024 * 1024;  // 20 MB.
+
+/**
+ * Creates a cache key.
+ *
+ * @param {string} url Image url.
+ * @param {Object=} opt_options Loader options as a hash array.
+ * @return {string} Cache key.
+ */
+ImageLoaderClient.Cache.createKey = function(url, opt_options) {
+  opt_options = opt_options || {};
+  return JSON.stringify({url: url,
+                         orientation: opt_options.orientation,
+                         scale: opt_options.scale,
+                         width: opt_options.width,
+                         height: opt_options.height,
+                         maxWidth: opt_options.maxWidth,
+                         maxHeight: opt_options.maxHeight});
+};
+
+/**
+ * Evicts the least used elements in cache to make space for a new image.
+ *
+ * @param {number} size Requested size.
+ * @private
+ */
+ImageLoaderClient.Cache.prototype.evictCache_ = function(size) {
+  // Sort from the most recent to the oldest.
+  this.images_.sort(function(a, b) {
+    return b.lastLoadTimestamp - a.lastLoadTimestamp;
+  });
+
+  while (this.images_.length > 0 &&
+         (ImageLoaderClient.Cache.MEMORY_LIMIT - this.size_ < size)) {
+    var entry = this.images_.pop();
+    this.size_ -= entry.data.length;
+  }
+};
+
+/**
+ * Saves an image in the cache.
+ *
+ * @param {string} key Cache key.
+ * @param {string} data Image data.
+ * @param {number=} opt_timestamp Last modification timestamp. Used to detect
+ *     if the cache entry becomes out of date.
+ */
+ImageLoaderClient.Cache.prototype.saveImage = function(
+    key, data, opt_timestamp) {
+  // If the image is currently in cache, then remove it.
+  if (this.images_[key])
+    this.removeImage(key);
+
+  if (ImageLoaderClient.Cache.MEMORY_LIMIT - this.size_ < data.length) {
+    ImageLoaderClient.recordBinary('Evicted', 1);
+    this.evictCache_(data.length);
+  } else {
+    ImageLoaderClient.recordBinary('Evicted', 0);
+  }
+
+  if (ImageLoaderClient.Cache.MEMORY_LIMIT - this.size_ >= data.length) {
+    this.images_[key] = {lastLoadTimestamp: Date.now(),
+                         timestamp: opt_timestamp ? opt_timestamp : null,
+                         data: data};
+    this.size_ += data.length;
+  }
+};
+
+/**
+ * Loads an image from the cache (if available) or returns null.
+ *
+ * @param {string} key Cache key.
+ * @param {number=} opt_timestamp Last modification timestamp. If different
+ *     that the one in cache, then the entry will be invalidated.
+ * @return {?string} Data of the loaded image or null.
+ */
+ImageLoaderClient.Cache.prototype.loadImage = function(key, opt_timestamp) {
+  if (!(key in this.images_))
+    return null;
+
+  var entry = this.images_[key];
+  entry.lastLoadTimestamp = Date.now();
+
+  // Check if the image in cache is up to date. If not, then remove it and
+  // return null.
+  if (entry.timestamp != opt_timestamp) {
+    this.removeImage(key);
+    return null;
+  }
+
+  return entry.data;
+};
+
+/**
+ * Returns cache usage.
+ * @return {number} Value in percent points (0..100).
+ */
+ImageLoaderClient.Cache.prototype.getUsage = function() {
+  return this.size_ / ImageLoaderClient.Cache.MEMORY_LIMIT * 100.0;
+};
+
+/**
+ * Removes the image from the cache.
+ * @param {string} key Cache key.
+ */
+ImageLoaderClient.Cache.prototype.removeImage = function(key) {
+  if (!(key in this.images_))
+    return;
+
+  var entry = this.images_[key];
+  this.size_ -= entry.data.length;
+  delete this.images_[key];
+};
+
+// Helper functions.
+
+/**
+ * Loads and resizes and image. Use opt_isValid to easily cancel requests
+ * which are not valid anymore, which will reduce cpu consumption.
+ *
+ * @param {string} url Url of the requested image.
+ * @param {Image} image Image node to load the requested picture into.
+ * @param {Object} options Loader options, such as: orientation, scale,
+ *     maxHeight, width, height and/or cache.
+ * @param {function=} onSuccess Callback for success.
+ * @param {function=} onError Callback for failure.
+ * @param {function=} opt_isValid Function returning false in case
+ *     a request is not valid anymore, eg. parent node has been detached.
+ * @return {?number} Remote task id or null if loaded from cache.
+ */
+ImageLoaderClient.loadToImage = function(
+    url, image, options, onSuccess, onError, opt_isValid) {
+  var callback = function(result) {
+    if (result.status == 'error') {
+      onError();
+      return;
+    }
+    image.src = result.data;
+    onSuccess();
+  };
+
+  return ImageLoaderClient.getInstance().load(
+      url, callback, options, opt_isValid);
+};
diff --git a/chrome/browser/resources/image_loader/manifest.json b/chrome/browser/resources/image_loader/manifest.json
index 712851a..aed686d 100644
--- a/chrome/browser/resources/image_loader/manifest.json
+++ b/chrome/browser/resources/image_loader/manifest.json
@@ -12,10 +12,16 @@
     "https://*.googleusercontent.com",
     "https://drive.google.com"
   ],
-  "content_security_policy": "default-src 'none'; script-src 'self'; style-src 'self' 'unsafe-inline'; frame-src 'self' about:; img-src 'self' chrome://resources chrome://theme data: https://docs.google.com https://*.googleusercontent.com chrome://extension-icon; media-src 'self' https://*.googleusercontent.com; connect-src https://drive.google.com https://*.googleusercontent.com",
+  "content_security_policy": "default-src 'none'; script-src 'self'; style-src 'self' 'unsafe-inline'; frame-src 'self' about:; img-src 'self' chrome://resources chrome://theme data: https://docs.google.com https://*.googleusercontent.com chrome://extension-icon; media-src 'self' https://*.googleusercontent.com; connect-src 'self' https://drive.google.com https://*.googleusercontent.com",
   "background": {
-    "scripts": [ "image_loader.js" ],
+    "scripts": [
+      "image_loader.js",
+      "cache.js",
+      "worker.js",
+      "request.js",
+      "background.js"
+    ],
     "persistent": false
   },
-  "web_accessible_resources": ["client.js"]
+  "web_accessible_resources": ["image_loader_client.js"]
 }
diff --git a/chrome/browser/resources/image_loader/request.js b/chrome/browser/resources/image_loader/request.js
new file mode 100644
index 0000000..46eadc5
--- /dev/null
+++ b/chrome/browser/resources/image_loader/request.js
@@ -0,0 +1,337 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+'use strict';
+
+/**
+ * Creates and starts downloading and then resizing of the image. Finally,
+ * returns the image using the callback.
+ *
+ * @param {string} id Request ID.
+ * @param {Cache} cache Cache object.
+ * @param {Object} request Request message as a hash array.
+ * @param {function} callback Callback used to send the response.
+ * @constructor
+ */
+function Request(id, cache, request, callback) {
+  /**
+   * @type {string}
+   * @private
+   */
+  this.id_ = id;
+
+  /**
+   * @type {Cache}
+   * @private
+   */
+  this.cache_ = cache;
+
+  /**
+   * @type {Object}
+   * @private
+   */
+  this.request_ = request;
+
+  /**
+   * @type {function}
+   * @private
+   */
+  this.sendResponse_ = callback;
+
+  /**
+   * Temporary image used to download images.
+   * @type {Image}
+   * @private
+   */
+  this.image_ = new Image();
+
+  /**
+   * MIME type of the fetched image.
+   * @type {string}
+   * @private
+   */
+  this.contentType_ = null;
+
+  /**
+   * Used to download remote images using http:// or https:// protocols.
+   * @type {XMLHttpRequest}
+   * @private
+   */
+  this.xhr_ = new XMLHttpRequest();
+
+  /**
+   * Temporary canvas used to resize and compress the image.
+   * @type {HTMLCanvasElement}
+   * @private
+   */
+  this.canvas_ = document.createElement('canvas');
+
+  /**
+   * @type {CanvasRenderingContext2D}
+   * @private
+   */
+  this.context_ = this.canvas_.getContext('2d');
+
+  /**
+   * Callback to be called once downloading is finished.
+   * @type {function()}
+   * @private
+   */
+  this.downloadCallback_ = null;
+}
+
+/**
+ * Returns ID of the request.
+ * @return {string} Request ID.
+ */
+Request.prototype.getId = function() {
+  return this.id_;
+};
+
+/**
+ * Returns priority of the request. The higher priority, the faster it will
+ * be handled. The highest priority is 0. The default one is 2.
+ *
+ * @return {number} Priority.
+ */
+Request.prototype.getPriority = function() {
+  return (this.request_.priority !== undefined) ? this.request_.priority : 2;
+};
+
+/**
+ * Tries to load the image from cache if exists and sends the response.
+ *
+ * @param {function()} onSuccess Success callback.
+ * @param {function()} onFailure Failure callback.
+ */
+Request.prototype.loadFromCacheAndProcess = function(onSuccess, onFailure) {
+  this.loadFromCache_(
+      function(data) {  // Found in cache.
+        this.sendImageData_(data);
+        onSuccess();
+      }.bind(this),
+      onFailure);  // Not found in cache.
+};
+
+/**
+ * Tries to download the image, resizes and sends the response.
+ * @param {function()} callback Completion callback.
+ */
+Request.prototype.downloadAndProcess = function(callback) {
+  if (this.downloadCallback_)
+    throw new Error('Downloading already started.');
+
+  this.downloadCallback_ = callback;
+  this.downloadOriginal_(this.onImageLoad_.bind(this),
+                         this.onImageError_.bind(this));
+};
+
+/**
+ * Fetches the image from the persistent cache.
+ *
+ * @param {function()} onSuccess Success callback.
+ * @param {function()} onFailure Failure callback.
+ * @private
+ */
+Request.prototype.loadFromCache_ = function(onSuccess, onFailure) {
+  var cacheKey = Cache.createKey(this.request_);
+
+  if (!this.request_.cache) {
+    // Cache is disabled for this request; therefore, remove it from cache
+    // if existed.
+    this.cache_.removeImage(cacheKey);
+    onFailure();
+    return;
+  }
+
+  if (!this.request_.timestamp) {
+    // Persistent cache is available only when a timestamp is provided.
+    onFailure();
+    return;
+  }
+
+  this.cache_.loadImage(cacheKey,
+                        this.request_.timestamp,
+                        onSuccess,
+                        onFailure);
+};
+
+/**
+ * Saves the image to the persistent cache.
+ *
+ * @param {string} data The image's data.
+ * @private
+ */
+Request.prototype.saveToCache_ = function(data) {
+  if (!this.request_.cache || !this.request_.timestamp) {
+    // Persistent cache is available only when a timestamp is provided.
+    return;
+  }
+
+  var cacheKey = Cache.createKey(this.request_);
+  this.cache_.saveImage(cacheKey,
+                        data,
+                        this.request_.timestamp);
+};
+
+/**
+ * Downloads an image directly or for remote resources using the XmlHttpRequest.
+ *
+ * @param {function()} onSuccess Success callback.
+ * @param {function()} onFailure Failure callback.
+ * @private
+ */
+Request.prototype.downloadOriginal_ = function(onSuccess, onFailure) {
+  this.image_.onload = onSuccess;
+  this.image_.onerror = onFailure;
+
+  // Download data urls directly since they are not supported by XmlHttpRequest.
+  var dataUrlMatches = this.request_.url.match(/^data:([^,;]*)[,;]/);
+  if (dataUrlMatches) {
+    this.image_.src = this.request_.url;
+    this.contentType_ = dataUrlMatches[1];
+    return;
+  }
+
+  // Download using an xhr request.
+  this.xhr_.responseType = 'blob';
+
+  this.xhr_.onerror = this.image_.onerror;
+  this.xhr_.onload = function() {
+    if (this.xhr_.status != 200) {
+      this.image_.onerror();
+      return;
+    }
+
+    // Process returned data, including the mime type.
+    this.contentType_ = this.xhr_.getResponseHeader('Content-Type');
+    var reader = new FileReader();
+    reader.onerror = this.image_.onerror;
+    reader.onload = function(e) {
+      this.image_.src = e.target.result;
+    }.bind(this);
+
+    // Load the data to the image as a data url.
+    reader.readAsDataURL(this.xhr_.response);
+  }.bind(this);
+
+  // Perform a xhr request.
+  try {
+    this.xhr_.open('GET', this.request_.url, true);
+    this.xhr_.send();
+  } catch (e) {
+    this.image_.onerror();
+  }
+};
+
+/**
+ * Sends the resized image via the callback. If the image has been changed,
+ * then packs the canvas contents, otherwise sends the raw image data.
+ *
+ * @param {boolean} imageChanged Whether the image has been changed.
+ * @private
+ */
+Request.prototype.sendImage_ = function(imageChanged) {
+  var imageData;
+  if (!imageChanged) {
+    // The image hasn't been processed, so the raw data can be directly
+    // forwarded for speed (no need to encode the image again).
+    imageData = this.image_.src;
+  } else {
+    // The image has been resized or rotated, therefore the canvas has to be
+    // encoded to get the correct compressed image data.
+    switch (this.contentType_) {
+      case 'image/gif':
+      case 'image/png':
+      case 'image/svg':
+      case 'image/bmp':
+        imageData = this.canvas_.toDataURL('image/png');
+        break;
+      case 'image/jpeg':
+      default:
+        imageData = this.canvas_.toDataURL('image/jpeg', 0.9);
+    }
+  }
+
+  // Send and store in the persistent cache.
+  this.sendImageData_(imageData);
+  this.saveToCache_(imageData);
+};
+
+/**
+ * Sends the resized image via the callback.
+ * @param {string} data Compressed image data.
+ * @private
+ */
+Request.prototype.sendImageData_ = function(data) {
+  this.sendResponse_({status: 'success',
+                      data: data,
+                      taskId: this.request_.taskId});
+};
+
+/**
+ * Handler, when contents are loaded into the image element. Performs resizing
+ * and finalizes the request process.
+ *
+ * @param {function()} callback Completion callback.
+ * @private
+ */
+Request.prototype.onImageLoad_ = function(callback) {
+  if (ImageLoader.shouldProcess(this.image_.width,
+                                this.image_.height,
+                                this.request_)) {
+    ImageLoader.resize(this.image_, this.canvas_, this.request_);
+    this.sendImage_(true);  // Image changed.
+  } else {
+    this.sendImage_(false);  // Image not changed.
+  }
+  this.cleanup_();
+  this.downloadCallback_();
+};
+
+/**
+ * Handler, when loading of the image fails. Sends a failure response and
+ * finalizes the request process.
+ *
+ * @param {function()} callback Completion callback.
+ * @private
+ */
+Request.prototype.onImageError_ = function(callback) {
+  this.sendResponse_({status: 'error',
+                      taskId: this.request_.taskId});
+  this.cleanup_();
+  this.downloadCallback_();
+};
+
+/**
+ * Cancels the request.
+ */
+Request.prototype.cancel = function() {
+  this.cleanup_();
+
+  // If downloading has started, then call the callback.
+  if (this.downloadCallback_)
+    this.downloadCallback_();
+};
+
+/**
+ * Cleans up memory used by this request.
+ * @private
+ */
+Request.prototype.cleanup_ = function() {
+  this.image_.onerror = function() {};
+  this.image_.onload = function() {};
+
+  // Transparent 1x1 pixel gif, to force garbage collecting.
+  this.image_.src = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAA' +
+      'ABAAEAAAICTAEAOw==';
+
+  this.xhr_.onerror = function() {};
+  this.xhr_.onload = function() {};
+  this.xhr_.abort();
+
+  // Dispose memory allocated by Canvas.
+  this.canvas_.width = 0;
+  this.canvas_.height = 0;
+};
diff --git a/chrome/browser/resources/image_loader/worker.js b/chrome/browser/resources/image_loader/worker.js
new file mode 100644
index 0000000..c0c29e2
--- /dev/null
+++ b/chrome/browser/resources/image_loader/worker.js
@@ -0,0 +1,175 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+'use strict';
+
+/**
+ * Worker for requests. Fetches requests from a queue and processes them
+ * synchronously, taking into account priorities. The highest priority is 0.
+ */
+function Worker() {
+  /**
+   * List of requests waiting to be checked. If these items are available in
+   * cache, then they are processed immediately after starting the worker.
+   * However, if they have to be downloaded, then these requests are moved
+   * to pendingRequests_.
+   *
+   * @type {Array.<Request>}
+   * @private
+   */
+  this.newRequests_ = [];
+
+  /**
+   * List of pending requests for images to be downloaded.
+   * @type {Array.<Request>}
+   * @private
+   */
+  this.pendingRequests_ = [];
+
+  /**
+   * List of requests being processed.
+   * @type {Array.<Request>}
+   * @private
+   */
+  this.activeRequests_ = [];
+
+  /**
+   * Hash array of requests being added to the queue, but not finalized yet.
+   * @type {Object}
+   * @private
+   */
+  this.requests_ = {};
+
+  /**
+   * If the worker has been started.
+   * @type {boolean}
+   * @private
+   */
+  this.started_ = false;
+}
+
+/**
+ * Maximum download requests to be run in parallel.
+ * @type {number}
+ * @const
+ */
+Worker.MAXIMUM_IN_PARALLEL = 5;
+
+/**
+ * Adds a request to the internal priority queue and executes it when requests
+ * with higher priorities are finished. If the result is cached, then it is
+ * processed immediately once the worker is started.
+ *
+ * @param {Request} request Request object.
+ */
+Worker.prototype.add = function(request) {
+  if (!this.started_) {
+    this.newRequests_.push(request);
+    this.requests_[request.getId()] = request;
+    return;
+  }
+
+  // Enqueue the request, since already started.
+  this.pendingRequests_.push(request);
+  this.sortPendingRequests_();
+
+  this.continue_();
+};
+
+/**
+ * Removes a request from the worker (if exists).
+ * @param {string} requestId Unique ID of the request.
+ */
+Worker.prototype.remove = function(requestId) {
+  var request = this.requests_[requestId];
+  if (!request)
+    return;
+
+  // Remove from the internal queues with pending tasks.
+  var newIndex = this.pendingRequests_.indexOf(request);
+  if (newIndex != -1)
+    this.newRequests_.splice(newIndex, 1);
+  var cacheCheckIndex = this.cacheCheckRequests_.indexOf(request);
+  if (cacheCheckIndex != -1)
+    this.cacheCheckRequests_.splice(cacheCheckIndex, 1);
+  var pendingIndex = this.pendingRequests_.indexOf(request);
+  if (pendingIndex != -1)
+    this.pendingRequests_.splice(pendingIndex, 1);
+
+  // Cancel the request.
+  request.cancel();
+  delete this.requests_[requestId];
+};
+
+/**
+ * Starts handling requests.
+ */
+Worker.prototype.start = function() {
+  this.started_ = true;
+
+  // Process tasks added before worker has been started.
+  this.pendingRequests_.concat(this.newRequests_);
+  this.sortPendingRequests_();
+  this.newRequests_ = [];
+
+  // Start serving enqueued requests.
+  this.continue_();
+};
+
+/**
+ * Sorts pending requests by priorities.
+ * @private
+ */
+Worker.prototype.sortPendingRequests_ = function() {
+  this.pendingRequests_.sort(function(a, b) {
+    return a.getPriority() - b.getPriority();
+  });
+};
+
+/**
+ * Processes pending requests from the queue. There is no guarantee that
+ * all of the tasks will be processed at once.
+ *
+ * @private
+ */
+Worker.prototype.continue_ = function() {
+  var index = 0;
+  while (index < this.pendingRequests_.length) {
+    var request = this.pendingRequests_[index];
+
+    // Run only up to MAXIMUM_IN_PARALLEL in the same time.
+    if (this.activeRequests_.length == Worker.MAXIMUM_IN_PARALLEL)
+      return;
+
+    this.pendingRequests_.splice(index, 1);
+    this.activeRequests_.push(request);
+
+    // Try to load from cache. If doesn't exist, then download.
+    var currentRequest = request;
+    currentRequest.loadFromCacheAndProcess(
+        this.finish_.bind(this, currentRequest),
+        function() {
+          currentRequest.downloadAndProcess(
+              this.finish_.bind(this, currentRequest));
+        }.bind(this));
+  }
+};
+
+/**
+ * Handles finished requests.
+ *
+ * @param {Request} request Finished request.
+ * @private
+ */
+Worker.prototype.finish_ = function(request) {
+  var index = this.activeRequests_.indexOf(request);
+  if (index < 0)
+    console.warn('Request not found.');
+  this.activeRequests_.splice(index, 1);
+  delete this.requests_[request.getId()];
+
+  // Continue handling the most important requests (if started).
+  if (this.started_)
+    this.continue_();
+};
diff --git a/chrome/browser/resources/local_ntp/images/2x/ntp_google_logo.png b/chrome/browser/resources/local_ntp/images/2x/ntp_google_logo.png
index 9578ee8..ff60013 100644
--- a/chrome/browser/resources/local_ntp/images/2x/ntp_google_logo.png
+++ b/chrome/browser/resources/local_ntp/images/2x/ntp_google_logo.png
Binary files differ
diff --git a/chrome/browser/resources/local_ntp/images/2x/ntp_white_google_logo.png b/chrome/browser/resources/local_ntp/images/2x/ntp_white_google_logo.png
index 9c600b6..2ed4bc9 100644
--- a/chrome/browser/resources/local_ntp/images/2x/ntp_white_google_logo.png
+++ b/chrome/browser/resources/local_ntp/images/2x/ntp_white_google_logo.png
Binary files differ
diff --git a/chrome/browser/resources/local_ntp/images/ntp_google_logo.png b/chrome/browser/resources/local_ntp/images/ntp_google_logo.png
deleted file mode 100644
index 378cffc..0000000
--- a/chrome/browser/resources/local_ntp/images/ntp_google_logo.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/local_ntp/images/ntp_white_google_logo.png b/chrome/browser/resources/local_ntp/images/ntp_white_google_logo.png
deleted file mode 100644
index b42a10f..0000000
--- a/chrome/browser/resources/local_ntp/images/ntp_white_google_logo.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/local_ntp/local_ntp.css b/chrome/browser/resources/local_ntp/local_ntp.css
index 8b80ec2..bd4f319 100644
--- a/chrome/browser/resources/local_ntp/local_ntp.css
+++ b/chrome/browser/resources/local_ntp/local_ntp.css
@@ -12,9 +12,7 @@
 }
 
 #ntp-contents {
-  position: absolute;
   text-align: -webkit-center;
-  width: 100%;
 }
 
 .non-google-page #ntp-contents {
@@ -36,9 +34,9 @@
 }
 
 #logo {
-  background: -webkit-image-set(
-      url(images/google_logo.png) 1x,
-      url(images/2x/google_logo.png) 2x) no-repeat;
+  background-image: url(images/2x/google_logo.png);
+  background-repeat: no-repeat;
+  background-size: 275px 95px;
   height: 95px;
   margin-bottom: 24px;
   margin-top: 157px;
@@ -46,9 +44,7 @@
 }
 
 body.custom-theme #logo {
-  background: -webkit-image-set(
-      url(images/white_google_logo.png) 1x,
-      url(images/2x/white_google_logo.png) 2x) no-repeat;
+  background-image: url(images/2x/white_google_logo.png);
 }
 
 #fakebox {
@@ -313,7 +309,8 @@
 }
 
 #mv-notice-links span:hover,
-#mv-notice-links span:focus {
+#mv-notice-links span:focus,
+#recent-tabs:hover {
   text-decoration: underline;
 }
 
@@ -338,13 +335,34 @@
   bottom: 0;
   color: #fff;
   cursor: default;
+  display: inline-block;
   font-size: 13px;
-  position: absolute;
-  right: 13px;
+  position: fixed;
+  right: 8px;
   text-align: left;
   z-index: -1;
 }
 
-#attribution img {
-  display: block;
+body.rtl #attribution {
+  text-align: right;
 }
+
+#recent-tabs {
+  background: #fff;
+  border: 1px solid #c0c0c0;
+  border-radius: 2px;
+  bottom: 0;
+  color: rgb(17, 85, 204);
+  cursor: pointer;
+  font-family: Arial;
+  font-size: 14px;
+  opacity: 0.9;
+  padding: 3px;
+  position: fixed;
+  right: 8px;
+}
+
+body.rtl #attribution,body.rtl #recent-tabs {
+  left: 8px;
+  right: auto;
+}
\ No newline at end of file
diff --git a/chrome/browser/resources/local_ntp/local_ntp.html b/chrome/browser/resources/local_ntp/local_ntp.html
index 3874aa0..b1c3360 100644
--- a/chrome/browser/resources/local_ntp/local_ntp.html
+++ b/chrome/browser/resources/local_ntp/local_ntp.html
@@ -24,7 +24,7 @@
         </span>
       </div>
     </div>
+    <div id="attribution"><div id="attribution-text"></div></div>
   </div>
-  <div id="attribution"></div>
 </body>
 </html>
diff --git a/chrome/browser/resources/local_ntp/local_ntp.js b/chrome/browser/resources/local_ntp/local_ntp.js
index f5c92d3..6cdd6c5 100644
--- a/chrome/browser/resources/local_ntp/local_ntp.js
+++ b/chrome/browser/resources/local_ntp/local_ntp.js
@@ -53,12 +53,14 @@
  */
 var IDS = {
   ATTRIBUTION: 'attribution',
+  ATTRIBUTION_TEXT: 'attribution-text',
   FAKEBOX: 'fakebox',
   LOGO: 'logo',
   NOTIFICATION: 'mv-notice',
   NOTIFICATION_CLOSE_BUTTON: 'mv-notice-x',
   NOTIFICATION_MESSAGE: 'mv-msg',
   NTP_CONTENTS: 'ntp-contents',
+  RECENT_TABS: 'recent-tabs',
   RESTORE_ALL_LINK: 'mv-restore',
   TILES: 'mv-tiles',
   UNDO_LINK: 'mv-undo'
@@ -89,6 +91,24 @@
 
 
 /**
+ * The JavaScript button event value for a middle click.
+ * @type {number}
+ * @const
+ */
+var MIDDLE_MOUSE_BUTTON = 1;
+
+
+/**
+ * Possible behaviors for navigateContentWindow.
+ * @enum {number}
+ */
+var WindowOpenDisposition = {
+  CURRENT_TAB: 1,
+  NEW_BACKGROUND_TAB: 2
+};
+
+
+/**
  * The container for the tile elements.
  * @type {Element}
  */
@@ -290,6 +310,14 @@
 
 
 /**
+ * Hide most visited tiles for at most this many milliseconds while painting.
+ * @type {number}
+ * @const
+ */
+var MOST_VISITED_PAINT_TIMEOUT_MSEC = 500;
+
+
+/**
  * A Tile is either a rendering of a Most Visited page or "filler" used to
  * pad out the section when not enough pages exist.
  *
@@ -373,8 +401,14 @@
     for (var i = 0; i < MAX_NUM_TILES_TO_SHOW; ++i) {
       tiles.push(createTile(pages[i], i));
     }
-    if (!userInitiatedMostVisitedChange)
+    if (!userInitiatedMostVisitedChange) {
       tilesContainer.hidden = true;
+      window.setTimeout(function() {
+        if (tilesContainer) {
+          tilesContainer.hidden = false;
+        }
+      }, MOST_VISITED_PAINT_TIMEOUT_MSEC);
+    }
     renderTiles();
   }
 }
@@ -409,10 +443,10 @@
       break;
     }
   }
-  if (!userInitiatedMostVisitedChange)
-    tilesContainer.hidden = !ready;
-  if (ready)
+  if (ready) {
+    tilesContainer.hidden = false;
     userInitiatedMostVisitedChange = false;
+  }
 }
 
 
@@ -849,13 +883,24 @@
 
 
 /**
+ * Extract the desired navigation behavior from a click button.
+ * @param {number} button The Event#button property of a click event.
+ * @return {WindowOpenDisposition} The desired behavior for
+ *     navigateContentWindow.
+ */
+function getDispositionFromClickButton(button) {
+  if (button == MIDDLE_MOUSE_BUTTON)
+    return WindowOpenDisposition.NEW_BACKGROUND_TAB;
+  return WindowOpenDisposition.CURRENT_TAB;
+}
+
+
+/**
  * Prepares the New Tab Page by adding listeners, rendering the current
  * theme, the most visited pages section, and Google-specific elements for a
  * Google-provided page.
  */
 function init() {
-  document.title = templateData.title;
-
   tilesContainer = $(IDS.TILES);
   notification = $(IDS.NOTIFICATION);
   attribution = $(IDS.ATTRIBUTION);
@@ -883,6 +928,19 @@
     document.body.classList.add(CLASSES.NON_GOOGLE_PAGE);
   }
 
+  var recentTabsText = templateData.recentTabs;
+  if (recentTabsText) {
+    var recentTabsLink = document.createElement('span');
+    recentTabsLink.id = IDS.RECENT_TABS;
+    recentTabsLink.addEventListener('click', function(event) {
+      ntpApiHandle.navigateContentWindow(
+          'chrome://history', getDispositionFromClickButton(event.button));
+    });
+    recentTabsLink.textContent = recentTabsText;
+    ntpContents.appendChild(recentTabsLink);
+    // Move the attribution up to prevent it from overlapping.
+    attribution.style.bottom = '28px';
+  }
 
   var notificationMessage = $(IDS.NOTIFICATION_MESSAGE);
   notificationMessage.textContent = templateData.thumbnailRemovedNotification;
@@ -894,7 +952,7 @@
   restoreAllLink.addEventListener('click', onRestoreAll);
   registerKeyHandler(restoreAllLink, KEYCODE.ENTER, onUndo);
   restoreAllLink.textContent = templateData.restoreThumbnailsShort;
-  attribution.textContent = templateData.attributionIntro;
+  $(IDS.ATTRIBUTION_TEXT).textContent = templateData.attributionIntro;
 
   var notificationCloseButton = $(IDS.NOTIFICATION_CLOSE_BUTTON);
   notificationCloseButton.addEventListener('click', hideNotification);
diff --git a/chrome/browser/resources/local_omnibox_popup/images/2x/history_icon.png b/chrome/browser/resources/local_omnibox_popup/images/2x/history_icon.png
index bf98e2c..ec5e4ba 100644
--- a/chrome/browser/resources/local_omnibox_popup/images/2x/history_icon.png
+++ b/chrome/browser/resources/local_omnibox_popup/images/2x/history_icon.png
Binary files differ
diff --git a/chrome/browser/resources/local_omnibox_popup/images/2x/page_icon.png b/chrome/browser/resources/local_omnibox_popup/images/2x/page_icon.png
index 0759be8..a7cf3cc 100644
--- a/chrome/browser/resources/local_omnibox_popup/images/2x/page_icon.png
+++ b/chrome/browser/resources/local_omnibox_popup/images/2x/page_icon.png
Binary files differ
diff --git a/chrome/browser/resources/local_omnibox_popup/images/2x/search_icon.png b/chrome/browser/resources/local_omnibox_popup/images/2x/search_icon.png
index c4848be..ac74fd7 100644
--- a/chrome/browser/resources/local_omnibox_popup/images/2x/search_icon.png
+++ b/chrome/browser/resources/local_omnibox_popup/images/2x/search_icon.png
Binary files differ
diff --git a/chrome/browser/resources/local_omnibox_popup/images/history_icon.png b/chrome/browser/resources/local_omnibox_popup/images/history_icon.png
index 1d97f39..6e7f731 100644
--- a/chrome/browser/resources/local_omnibox_popup/images/history_icon.png
+++ b/chrome/browser/resources/local_omnibox_popup/images/history_icon.png
Binary files differ
diff --git a/chrome/browser/resources/local_omnibox_popup/images/page_icon.png b/chrome/browser/resources/local_omnibox_popup/images/page_icon.png
index f5efac3..b782547 100644
--- a/chrome/browser/resources/local_omnibox_popup/images/page_icon.png
+++ b/chrome/browser/resources/local_omnibox_popup/images/page_icon.png
Binary files differ
diff --git a/chrome/browser/resources/local_omnibox_popup/images/search_icon.png b/chrome/browser/resources/local_omnibox_popup/images/search_icon.png
index 33e874e..ed89c7b 100644
--- a/chrome/browser/resources/local_omnibox_popup/images/search_icon.png
+++ b/chrome/browser/resources/local_omnibox_popup/images/search_icon.png
Binary files differ
diff --git a/chrome/browser/resources/managed_mode_block_interstitial.css b/chrome/browser/resources/managed_mode_block_interstitial.css
index 57ac15d..3aded39 100644
--- a/chrome/browser/resources/managed_mode_block_interstitial.css
+++ b/chrome/browser/resources/managed_mode_block_interstitial.css
@@ -26,7 +26,7 @@
 
 h1 {
   color: rgb(102, 102, 102);
-  font-size: 1.5em;
+  font-size: 1.3em;
   font-weight: normal;
   margin: 10px 0 30px 0;
 }
@@ -48,6 +48,7 @@
       url('../../app/theme/default_100_percent/common/error_managed_mode_blocked_page.png') 1x,
       url('../../app/theme/default_200_percent/common/error_managed_mode_blocked_page.png') 2x);
   margin-bottom: 10px;
+  margin-top: 10px;
 }
 
 #content-top {
diff --git a/chrome/browser/resources/media/webrtc_logs.css b/chrome/browser/resources/media/webrtc_logs.css
new file mode 100644
index 0000000..49e6aa9
--- /dev/null
+++ b/chrome/browser/resources/media/webrtc_logs.css
@@ -0,0 +1,48 @@
+/* Copyright 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+body {
+  margin: 20px;
+}
+
+h1 {
+  font-size: 156%;
+  font-weight: bold;
+  margin: 0;
+  padding-bottom: 20px;
+  padding-top: 20px;
+}
+
+html[dir=rtl] h1 {
+  background-position: right;
+}
+
+#log-banner {
+  background-color: rgb(235, 239, 250);
+  border: 1px solid #bbb;
+  border-radius: 2px;
+  font-size: 100%;
+  padding: 4px;
+}
+
+#log-list h3 {
+  font-size: 100%;
+}
+
+#log-list > div > * {
+  margin: 0.75em 0;
+}
+
+#log-list a:visited {
+  color: #666;
+}
+
+#log-list > div:not(:last-child) {
+  border-bottom: 1px solid #bbb;
+}
+
+#disabled-mode h2 {
+  color: rgb(141, 51, 42);
+  font-size: 125%;
+}
diff --git a/chrome/browser/resources/media/webrtc_logs.html b/chrome/browser/resources/media/webrtc_logs.html
new file mode 100644
index 0000000..59517c2
--- /dev/null
+++ b/chrome/browser/resources/media/webrtc_logs.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML>
+<html i18n-values="dir:textdirection;">
+<head>
+  <meta charset="utf-8">
+  <title i18n-content="webrtcLogsTitle"></title>
+  <link rel="stylesheet" href="webrtc_logs.css">
+  <script src="chrome://resources/js/load_time_data.js"></script>
+  <script src="chrome://resources/js/util.js"></script>
+  <script src="chrome://webrtc-logs/strings.js"></script>
+  <script src="chrome://webrtc-logs/webrtc_logs.js"></script>
+</head>
+<body i18n-values=".style.fontFamily:fontfamily;.style.fontSize:fontsize">
+  <header><h1 i18n-content="webrtcLogsTitle"></h1></header>
+  <div id="enabled-mode">
+    <h2 id="log-banner"></h2>
+    <div id="log-list"></div>
+    <p id="no-logs" i18n-content="noLogsMessage" hidden></p>
+  </div>
+  <div id="disabled-mode" hidden>
+    <h2 i18n-content="disabledHeader"></h2>
+    <p i18n-values=".innerHTML:disabledMessage"></p>
+  </div>
+  <script src="chrome://resources/js/i18n_template2.js"></script>
+  <script src="chrome://resources/js/jstemplate_compiled.js"></script>
+</body>
+</html>
diff --git a/chrome/browser/resources/media/webrtc_logs.js b/chrome/browser/resources/media/webrtc_logs.js
new file mode 100644
index 0000000..8537551
--- /dev/null
+++ b/chrome/browser/resources/media/webrtc_logs.js
@@ -0,0 +1,86 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * Requests the list of uploads from the backend.
+ */
+function requestUploads() {
+  chrome.send('requestWebRtcLogsList');
+}
+
+/**
+ * Callback from backend with the list of uploads. Builds the UI.
+ * @param {boolean} enabled Whether or not uploading is enabled.
+ * @param {array} uploads The list of uploads.
+ * @param {string} version The browser version.
+ */
+function updateWebRtcLogsList(enabled, uploads, version) {
+  $('log-banner').textContent = loadTimeData.getStringF('webrtcLogCountFormat',
+                                                        uploads.length);
+
+  var logSection = $('log-list');
+
+  $('enabled-mode').hidden = !enabled;
+  $('disabled-mode').hidden = enabled;
+
+  if (!enabled)
+    return;
+
+  // Clear any previous list.
+  logSection.textContent = '';
+
+  for (var i = 0; i < uploads.length; i++) {
+    var upload = uploads[i];
+
+    var logBlock = document.createElement('div');
+    var title = document.createElement('h3');
+    title.textContent = loadTimeData.getStringF('webrtcLogHeaderFormat',
+                                                upload['id']);
+    logBlock.appendChild(title);
+    var date = document.createElement('p');
+    date.textContent = loadTimeData.getStringF('webrtcLogTimeFormat',
+                                               upload['time']);
+    logBlock.appendChild(date);
+    var linkBlock = document.createElement('p');
+    var link = document.createElement('a');
+    var commentLines = [
+      'Chrome Version: ' + version,
+      // TODO(tbreisacher): fill in the OS automatically?
+      'Operating System: e.g., "Windows 7", "Mac OSX 10.6"',
+      '',
+      'URL (if applicable) where the problem occurred:',
+      '',
+      'Can you reproduce this problem?',
+      '',
+      'What steps will reproduce this problem? (or if it\'s not ' +
+      'reproducible, what were you doing just before the problem)?',
+      '',
+      '1.', '2.', '3.',
+      '',
+      '*Please note that issues filed with no information filled in ' +
+      'above will be marked as WontFix*',
+      '',
+      '****DO NOT CHANGE BELOW THIS LINE****',
+      'report_id:' + upload.id
+    ];
+    var params = {
+      template: 'Defect report from user',
+      comment: commentLines.join('\n'),
+    };
+    var href = 'http://code.google.com/p/chromium/issues/entry';
+    for (var param in params) {
+      href = appendParam(href, param, params[param]);
+    }
+    link.href = href;
+    link.target = '_blank';
+    link.textContent = loadTimeData.getString('bugLinkText');
+    linkBlock.appendChild(link);
+    logBlock.appendChild(linkBlock);
+    logSection.appendChild(logBlock);
+  }
+
+  $('no-logs').hidden = uploads.length != 0;
+}
+
+document.addEventListener('DOMContentLoaded', requestUploads);
diff --git a/chrome/browser/resources/memory_internals/extension_view.css b/chrome/browser/resources/memory_internals/extension_view.css
index 5087d71..98463bc 100644
--- a/chrome/browser/resources/memory_internals/extension_view.css
+++ b/chrome/browser/resources/memory_internals/extension_view.css
@@ -3,19 +3,38 @@
  * found in the LICENSE file. */
 
 #extension-view {
+  border-spacing: 2px;
   width: 100%;
 }
 
-#extension-view tr:nth-child(odd) {
+#extension-view tr:nth-child(odd):not([class='header']) {
   background: rgb(239, 243, 255);
 }
 
 #extension-view td {
+  padding: 0.35em 0.5em 0;
   vertical-align: top;
 }
 
-#extension-view .extension-memory {
+#extension-view .header th {
+  border-bottom: 1px solid rgb(181, 198, 222);
+  padding: 0.35em 0.5em 0;
+  vertical-align: bottom;
+}
+
+#extension-view .extension-id {
   text-align: right;
+  width: 4em;
+}
+
+#extension-view .extension-info {
+  text-align: left;
+}
+
+#extension-view .extension-memory {
+  border-left: 1px solid rgb(181, 198, 222);
+  text-align: right;
+  width: 7em;
 }
 
 #extension-view #extension-template {
diff --git a/chrome/browser/resources/memory_internals/extension_view.html b/chrome/browser/resources/memory_internals/extension_view.html
index 76ddbeb..d142f99 100644
--- a/chrome/browser/resources/memory_internals/extension_view.html
+++ b/chrome/browser/resources/memory_internals/extension_view.html
@@ -3,10 +3,10 @@
      found in the LICENSE file. -->
 <h2>Extensions</h2>
 <table id="extension-view">
-  <tr>
-    <th>PID
-    <th>Name
-    <th>Private Memory [KB]
+  <tr class="header">
+    <th class="extension-id">PID
+    <th class="extension-info">Name
+    <th class="extension-memory">Private Memory [KB]
   <tr id="extension-template">
     <td class="extension-id">
     <td class="extension-info">
diff --git a/chrome/browser/resources/memory_internals/memory_internals.css b/chrome/browser/resources/memory_internals/memory_internals.css
index e13e3ab..fd6ef69 100644
--- a/chrome/browser/resources/memory_internals/memory_internals.css
+++ b/chrome/browser/resources/memory_internals/memory_internals.css
@@ -3,7 +3,7 @@
  * found in the LICENSE file. */
 
 body {
-  font-size: 84%;
+  font-size: 70%;
   margin: 0;
   min-width: 45em;
   padding: 0.75em;
diff --git a/chrome/browser/resources/memory_internals/memory_internals.js b/chrome/browser/resources/memory_internals/memory_internals.js
index 233feb8..c448a6b 100644
--- a/chrome/browser/resources/memory_internals/memory_internals.js
+++ b/chrome/browser/resources/memory_internals/memory_internals.js
@@ -64,9 +64,15 @@
           case 'process-info':
             value = process['type'] + '<br>' + process['titles'].join('<br>');
             break;
-          case 'process-memory':
+          case 'process-memory-private':
             value = process['memory_private'];
             break;
+          case 'process-memory-v8':
+            if (process['v8_alloc'] !== undefined) {
+              value = 'Used : ' + process['v8_used'] + '<br>' +
+                  'Allocated : ' + process['v8_alloc'];
+            }
+            break;
           }
           var col = row.insertCell(-1);
           col.innerHTML = value;
diff --git a/chrome/browser/resources/memory_internals/snapshot_view.css b/chrome/browser/resources/memory_internals/snapshot_view.css
index 4e8edac..4e57b21 100644
--- a/chrome/browser/resources/memory_internals/snapshot_view.css
+++ b/chrome/browser/resources/memory_internals/snapshot_view.css
@@ -3,19 +3,51 @@
  * found in the LICENSE file. */
 
 #snapshot-view {
+  border-spacing: 2px;
   width: 100%;
 }
 
-#snapshot-view tr:nth-child(odd) {
+#snapshot-view tr:nth-child(odd):not([class='header']) {
   background: rgb(239, 243, 255);
 }
 
 #snapshot-view td {
+  padding: 0.35em 0.5em 0;
   vertical-align: top;
 }
 
-#snapshot-view .process-memory {
+#snapshot-view .header th {
+  padding: 0.35em 0.5em 0;
+  vertical-align: bottom;
+}
+
+#snapshot-view .bottom th {
+  border-bottom: 1px solid rgb(181, 198, 222);
+}
+
+#snapshot-view .process-id {
   text-align: right;
+  width: 4em;
+}
+
+#snapshot-view .process-info {
+  text-align: left;
+}
+
+#snapshot-view .process-memory {
+  border-left: 1px solid rgb(181, 198, 222);
+  width: 16em;
+}
+
+#snapshot-view .process-memory-private {
+  border-left: 1px solid rgb(181, 198, 222);
+  text-align: right;
+  width: 6em;
+}
+
+#snapshot-view .process-memory-v8 {
+  text-align: right;
+  width: 10em;
 }
 
 #snapshot-view #process-template {
diff --git a/chrome/browser/resources/memory_internals/snapshot_view.html b/chrome/browser/resources/memory_internals/snapshot_view.html
index cc3b25b..43d041d 100644
--- a/chrome/browser/resources/memory_internals/snapshot_view.html
+++ b/chrome/browser/resources/memory_internals/snapshot_view.html
@@ -6,12 +6,16 @@
 <div id="uptime-view">Uptime: <span id="uptime-value">unknown</span></div>
 
 <table id="snapshot-view">
-  <tr>
-    <th>PID
-    <th>Name
-    <th>Private Memory [KB]
+  <tr class="header">
+    <th rowspan="2" class="process-id">PID
+    <th rowspan="2" class="process-info">Name
+    <th colspan="2" class="process-memory">Memory [KB]
+  <tr class="header bottom">
+    <th class="process-memory-private">Private
+    <th class="process-memory-v8">V8
   <tr id="process-template">
     <td class="process-id">
     <td class="process-info">
-    <td class="process-memory">
+    <td class="process-memory-private">
+    <td class="process-memory-v8">
 </table>
diff --git a/chrome/browser/resources/net_internals/browser_bridge.js b/chrome/browser/resources/net_internals/browser_bridge.js
index f982279..574d4fc 100644
--- a/chrome/browser/resources/net_internals/browser_bridge.js
+++ b/chrome/browser/resources/net_internals/browser_bridge.js
@@ -713,8 +713,10 @@
      *   observer.onSystemLogChanged(systemLogInfo)
      */
     addSystemLogObserver: function(observer, ignoreWhenUnchanged) {
-      this.pollableDataHelpers_.systemLog.addObserver(
-          observer, ignoreWhenUnchanged);
+      if (this.pollableDataHelpers_.systemLog) {
+        this.pollableDataHelpers_.systemLog.addObserver(
+            observer, ignoreWhenUnchanged);
+      }
     },
 
     /**
diff --git a/chrome/browser/resources/net_internals/cros_log_analyzer_view.css b/chrome/browser/resources/net_internals/cros_log_analyzer_view.css
new file mode 100644
index 0000000..098190c
--- /dev/null
+++ b/chrome/browser/resources/net_internals/cros_log_analyzer_view.css
@@ -0,0 +1,234 @@
+ /* Copyright 2013 The Chromium Authors. All rights reserved.
+  * Use of this source code is governed by a BSD-style license that can be
+  * found in the LICENSE file.
+  */
+
+ #cros-log-analyzer-header {
+  margin-bottom: 20px;
+ }
+
+.cros-log-analyzer-container {
+  background-color: rgb(242, 242, 242);
+  border: 1px solid rgb(220, 220, 220);
+}
+
+#cros-log-analyzer-log-content {
+  border: 1px solid rgb(220, 220, 220);
+  font-size: 11px;
+  height: 300px;
+  line-height: 18px;
+  margin-bottom: -1px;
+  overflow: scroll;
+  padding: 10px;
+  width: 1000px;
+ }
+
+#cros-log-analyzer-filter-container {
+  font-size: 12px;
+  margin-bottom: 5px;
+  padding: 5px 10px;
+  width: 1000px;
+}
+
+#cros-log-analyzer-filter-container p {
+  margin: 10px 0;
+}
+
+#cros-log-analyzer-log-table {
+  table-layout: fixed;
+  width: 950px;
+}
+
+#cros-log-analyzer-log-table td {
+  overflow: hidden;
+  table-layout: fixed;
+  word-wrap: break-word;
+}
+
+.cros-log-analyzer-td-time {
+  width: 100px;
+}
+
+#cros-log-analyzer-log-header-table {
+  font-size: 12px;
+  font-weight: bold;
+  margin-bottom: -1px;
+  text-align: center;
+  width: 1000px;
+}
+
+.cros-log-analyzer-td-pname {
+  text-align: center;
+  width: 120px;
+}
+
+.cros-log-analyzer-td-level {
+  width: 70px;
+}
+
+.cros-log-analyzer-td-level p {
+  border: 1px solid;
+  border-radius: 5px;
+  margin: 0 3px;
+  text-align: center;
+  width: 58px;
+}
+
+.cros-log-analyzer-td-level-error {
+  background-color: rgb(255, 153, 163);
+  color: red;
+}
+
+.cros-log-analyzer-td-level-info {
+  background-color: rgb(195, 227, 250);
+  color: rgb(10, 147, 245);
+  width: 120px;
+}
+
+.cros-log-analyzer-td-level-warning {
+  background-color: rgb(250, 229, 195);
+  color: darkorange;
+}
+
+.cros-log-analyzer-td-level-unknown {
+  color: gray;
+}
+
+.cros-log-analyzer-td-pid {
+  width: 60px;
+}
+
+#cros-log-analyzer-filter-pname {
+  border-bottom: 1px solid rgb(209, 209, 209);
+  padding: 5px 0 10px 0;
+}
+
+#cros-log-analyzer-filter-level {
+  padding: 5px 0 10px 0;
+}
+
+#cros-log-analyzer-search-container {
+  -webkit-margin-start: 760px;
+  border-radius: 5px;
+  font-size: 12px;
+  margin-bottom: 5px;
+  margin-left: 720px;
+  margin-top: -40px;
+  padding: 5px;
+  width: 280px;
+}
+
+#cros-log-analyzer-search-container input {
+  border: 1px solid rgb(220, 220, 220);
+}
+
+#cros-log-analyzer-visualizer-container {
+  border: 1px solid rgb(211, 211, 211);
+  height: 100px;
+  position: relative;
+  width: 1002px;
+}
+
+#cros-log-analyzer-visualizer-timeline {
+  background: gray;
+  opacity: 0.5;
+  position: absolute;
+  top: 0;
+  width: 2px;
+}
+
+.cros-log-analyzer-visualizer-time-display {
+  font-size: 10px;
+  position: absolute;
+  width: 50px;
+}
+
+#cros-log-analyzer-visualizer-reset-btn {
+  border: 1px solid rgb(211, 211, 211);
+  border-radius: 2px;
+  position: absolute;
+  right: 5px;
+  top: 5px;
+}
+
+#cros-log-analyzer-visualizer-tracking-layer {
+  background: none;
+  height: 100%;
+  left: 0;
+  position: absolute;
+  top: 0;
+  width: 100%;
+}
+
+.cros-log-analyzer-visualizer-canvas {
+  left: 0;
+  position: absolute;
+  top: 0;
+}
+
+.cros-log-analyzer-flash {
+  -webkit-animation: fade 1s linear 1;
+}
+
+#cros-log-analyzer-marker-container {
+  background-color: rgb(242, 242, 242);
+  border: 1px solid rgb(211, 211, 211);
+  left: 1030px;
+  min-height: 320px;
+  padding: 10px;
+  position: absolute;
+  top: 63px;
+  width: 200px;
+}
+
+.cros-log-analyzer-marker-history-entry {
+  display: -webkit-flex;
+  height: 20px;
+}
+
+
+.cros-log-analyzer-marker-history-entry * {
+  display: block;
+}
+
+.cros-log-analyzer-marker-history-entry p {
+  font-size: 13px;
+  height: 15px;
+  margin: 0;
+  width: 98px;
+}
+
+.cros-log-analyzer-marker-history-entry a {
+  color: grey;
+  font-size: 11px;
+}
+
+.cros-log-analyzer-marker-history-color-tag {
+  border-radius: 10px;
+  height: 10px;
+  margin: 4px;
+  width: 10px;
+}
+
+.cros-log-analyzer-marker-highlight {
+  font-weight: bold;
+}
+
+#cros-log-analyzer-save-btn {
+  background-color: rgb(211, 211, 211);
+}
+
+@-webkit-keyframes fade {
+  0%
+  {
+    opacity: 1;
+  }
+  50%
+  {
+    opacity: 0;
+  }
+  100%
+  {
+    opacity: 1;
+  }
+}
diff --git a/chrome/browser/resources/net_internals/cros_log_analyzer_view.html b/chrome/browser/resources/net_internals/cros_log_analyzer_view.html
new file mode 100644
index 0000000..a23543c
--- /dev/null
+++ b/chrome/browser/resources/net_internals/cros_log_analyzer_view.html
@@ -0,0 +1,55 @@
+<!-- Log Analyzer -->
+<div id="cros-log-analyzer-tab-content" class="content-box">
+  <div id="cros-log-analyzer-header">
+    Network Log
+  </div>
+  <div id='cros-log-analyzer-search-container'
+      class='cros-log-analyzer-container'>
+    Search:
+    <input type='text' id='cros-log-analyzer-search-input'>
+    <span id='cros-log-analyzer-save-btn'>Save</span>
+  </div>
+  <table id="cros-log-analyzer-log-header-table"
+      class="cros-log-analyzer-container">
+    <tr>
+      <td class="cros-log-analyzer-td-level">Level</td>
+      <td class="cros-log-analyzer-td-time">Time</td>
+      <td class="cros-log-analyzer-td-pname">Process</td>
+      <td class="cros-log-analyzer-td-pid">PID</td>
+      <td class="cros-log-analyzer-td-description">Description</td>
+    </tr>
+  </table>
+  <div id="cros-log-analyzer-log-content">
+    <table id="cros-log-analyzer-log-table">
+    </table>
+  </div>
+  <div id='cros-log-analyzer-marker-container'>
+  </div>
+  <div id='cros-log-analyzer-filter-container'
+      class='cros-log-analyzer-container'>
+    <div id='cros-log-analyzer-filter-pname'>
+    </div>
+    <div id='cros-log-analyzer-filter-level'>
+      Level:
+      <span class="cros-log-analyzer-filter-level-block">
+        <input type='checkbox' id='checkbox-error' checked=true>
+        <label for="checkbox-error">Error</label>
+      </span>
+      <span class="cros-log-analyzer-filter-level-block">
+        <input type='checkbox' id='checkbox-warning' checked=true>
+        <label for="checkbox-warning">Warning</label>
+      </span>
+      <span class="cros-log-analyzer-filter-level-block">
+        <input type='checkbox' id='checkbox-info' checked=true>
+        <label for="checkbox-info">Info</label>
+      </span>
+      <span class="cros-log-analyzer-filter-level-block">
+        <input type='checkbox' id='checkbox-unknown'checked=true>
+        <label for="checkbox-unknown">Unknown</label>
+      </span>
+    </div>
+  </div>
+  <div id="cros-log-analyzer-visualizer-container">
+    <div id="cros-log-analyzer-visualizer-tracking-layer"></div>
+  </div>
+</div>
diff --git a/chrome/browser/resources/net_internals/cros_log_analyzer_view.js b/chrome/browser/resources/net_internals/cros_log_analyzer_view.js
new file mode 100644
index 0000000..fa6927a
--- /dev/null
+++ b/chrome/browser/resources/net_internals/cros_log_analyzer_view.js
@@ -0,0 +1,371 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * This view displays the log messages from various resources in an
+ * interactive log analyzer
+ *
+ *   - Filter checkboxes
+ *   - Filter text inputs
+ *   - Display the log by different sections: time|level|process|description
+ *
+ */
+var CrosLogAnalyzerView = (function() {
+  'use strict';
+
+  // Inherits from DivView.
+  var superClass = DivView;
+
+  // Special classes (defined in log_analyzer_view.css)
+  var LOG_CONTAINER_CLASSNAME = 'cros-log-analyzer-container';
+  var LOG_FILTER_PNAME_BLOCK_CLASSNAME = 'cros-log-analyzer-filter-pname-block';
+  var LOG_CELL_HEADER_CLASSNAME = 'cros-log-analyzer-td-head';
+  var LOG_CELL_TIME_CLASSNAME = 'cros-log-analyzer-td-time';
+  var LOG_CELL_PNAME_CLASSNAME = 'cros-log-analyzer-td-pname';
+  var LOG_CELL_PID_CLASSNAME = 'cros-log-analyzer-td-pid';
+  var LOG_CELL_DESCRIPTION_CLASSNAME = 'cros-log-analyzer-td-description';
+  var LOG_CELL_LEVEL_CLASSNAME = 'cros-log-analyzer-td-level';
+  var LOG_CELL_LEVEL_CLASSNAME_LIST = {
+    'Error': 'cros-log-analyzer-td-level-error',
+    'Warning': 'cros-log-analyzer-td-level-warning',
+    'Info': 'cros-log-analyzer-td-level-info',
+    'Unknown': 'cros-log-analyzer-td-level-unknown'
+  };
+
+  /**
+   * @constructor
+   */
+  function CrosLogAnalyzerView() {
+    assertFirstConstructorCall(CrosLogAnalyzerView);
+
+    // Call superclass's constructor.
+    superClass.call(this, CrosLogAnalyzerView.MAIN_BOX_ID);
+
+    // Stores log entry objects
+    this.logEntries = [];
+    // Stores current search query
+    this.currentQuery = '';
+    // Stores raw text data of log
+    this.logData = '';
+    // Stores all the unique process names
+    this.pNames = [];
+    // References to special HTML elements in log_analyzer_view.html
+    this.pNameCheckboxes = {};
+    this.levelCheckboxes = {};
+    this.tableEntries = [];
+
+    this.initialize();
+  }
+
+  CrosLogAnalyzerView.TAB_ID = 'tab-handle-cros-log-analyzer';
+  CrosLogAnalyzerView.TAB_NAME = 'Log Analyzer';
+  CrosLogAnalyzerView.TAB_HASH = '#analyzer';
+
+  // IDs for special HTML elements in log_analyzer_view.html
+  CrosLogAnalyzerView.MAIN_BOX_ID = 'cros-log-analyzer-tab-content';
+  CrosLogAnalyzerView.LOG_TABLE_ID = 'cros-log-analyzer-log-table';
+  CrosLogAnalyzerView.LOG_FILTER_PNAME_ID = 'cros-log-analyzer-filter-pname';
+  CrosLogAnalyzerView.LOG_SEARCH_INPUT_ID = 'cros-log-analyzer-search-input';
+  CrosLogAnalyzerView.LOG_SEARCH_SAVE_BTN_ID = 'cros-log-analyzer-save-btn';
+  CrosLogAnalyzerView.LOG_VISUALIZER_CONTAINER_ID =
+      'cros-log-analyzer-visualizer-container';
+
+  cr.addSingletonGetter(CrosLogAnalyzerView);
+
+  /**
+   * Contains types of logs we are interested in
+   */
+  var LOGS_LIST = {
+    'NETWORK_LOG': 1,
+    'SYSTEM_LOG': 2
+  };
+
+  /**
+   * Contains headers of the log table
+   */
+  var TABLE_HEADERS_LIST = ['Level', 'Time', 'Process', 'PID', 'Description'];
+
+  CrosLogAnalyzerView.prototype = {
+    // Inherit the superclass's methods.
+    __proto__: superClass.prototype,
+
+    /**
+     * Called during the initialization of the View. Adds the system log
+     * listener into Browser_Bridge so that the system log can be retrieved.
+     */
+    initialize: function() {
+      g_browser.addSystemLogObserver(this);
+      $(CrosLogAnalyzerView.LOG_SEARCH_INPUT_ID).addEventListener('keyup',
+          this.onSearchQueryChange_.bind(this));
+      $(CrosLogAnalyzerView.LOG_SEARCH_SAVE_BTN_ID).addEventListener(
+          'click', this.onSaveBtnClicked_.bind(this));
+    },
+
+    /**
+     * Called when the save button is clicked. Saves the current filter query
+     * to the mark history. And highlights the matched text with colors.
+     */
+    onSaveBtnClicked_: function() {
+      this.marker.addMarkHistory(this.currentQuery);
+      // Clears the filter query
+      $(CrosLogAnalyzerView.LOG_SEARCH_INPUT_ID).value = '';
+      this.currentQuery = '';
+      // Refresh the table
+      this.populateTable();
+      this.filterLog();
+    },
+
+    onSearchQueryChange_: function() {
+      var inputField = $(CrosLogAnalyzerView.LOG_SEARCH_INPUT_ID);
+      this.currentQuery = inputField.value;
+      this.filterLog();
+    },
+
+    /**
+     * Creates the log table where each row represents a entry of log.
+     * This function is called if and only if the log is received from system
+     * level.
+     */
+    populateTable: function() {
+      var logTable = $(CrosLogAnalyzerView.LOG_TABLE_ID);
+      logTable.innerHTML = '';
+      this.tableEntries.length = 0;
+      // Create entries
+      for (var i = 0; i < this.logEntries.length; i++) {
+        this.logEntries[i].rowNum = i;
+        var row = this.createTableRow(this.logEntries[i]);
+        logTable.appendChild(row);
+      }
+    },
+
+    /**
+     * Creates the single row of the table where each row is a representation
+     * of the logEntry object.
+     */
+    createTableRow: function(entry) {
+      var row = document.createElement('tr');
+      for (var i = 0; i < 5; i++) {
+        // Creates rows
+        addNode(row, 'td');
+      }
+      var cells = row.childNodes;
+      // Level cell
+      cells[0].className = LOG_CELL_LEVEL_CLASSNAME;
+      var levelTag = addNodeWithText(cells[0], 'p', entry.level);
+      levelTag.className = LOG_CELL_LEVEL_CLASSNAME_LIST[entry.level];
+
+      // Time cell
+      cells[1].className = LOG_CELL_TIME_CLASSNAME;
+      cells[1].textContent = entry.getTime();
+
+      // Process name cell
+      cells[2].className = LOG_CELL_PNAME_CLASSNAME;
+      this.marker.getHighlightedEntry(entry, 'processName', cells[2]);
+
+      // Process ID cell
+      cells[3].className = LOG_CELL_PID_CLASSNAME;
+      this.marker.getHighlightedEntry(entry, 'processID', cells[3]);
+
+      // Description cell
+      cells[4].className = LOG_CELL_DESCRIPTION_CLASSNAME;
+      this.marker.getHighlightedEntry(entry, 'description', cells[4]);
+
+      // Add the row into this.tableEntries for future reference
+      this.tableEntries.push(row);
+      return row;
+    },
+
+    /**
+     * Regenerates the table and filter.
+     */
+    refresh: function() {
+      this.createFilter();
+      this.createLogMaker();
+      this.populateTable();
+      this.createVisualizer();
+    },
+
+    /**
+     * Uses the search query to match the pattern in different fields of entry.
+     */
+    patternMatch: function(entry, pattern) {
+      return entry.processID.match(pattern) ||
+             entry.processName.match(pattern) ||
+             entry.level.match(pattern) ||
+             entry.description.match(pattern);
+    },
+
+    /**
+     * Filters the log to show/hide the rows in the table.
+     * Each logEntry instance has a visibility property. This function
+     * shows or hides the row only based on this property.
+     */
+    filterLog: function() {
+      // Supports regular expression
+      var pattern = new RegExp(this.currentQuery, 'i');
+      for (var i = 0; i < this.logEntries.length; i++) {
+        var entry = this.logEntries[i];
+        // Filters the result by pname and level
+        var pNameCheckbox = this.pNameCheckboxes[entry.processName];
+        var levelCheckbox = this.levelCheckboxes[entry.level];
+        entry.visibility = pNameCheckbox.checked && levelCheckbox.checked &&
+            !this.visualizer.isOutOfBound(entry);
+        if (this.currentQuery) {
+          // If the search query is not empty, filter the result by query
+          entry.visibility = entry.visibility &&
+              this.patternMatch(entry, pattern);
+        }
+        // Changes style of HTML row based on the visibility of logEntry
+        if (entry.visibility) {
+          this.tableEntries[i].style.display = 'table-row';
+        } else {
+          this.tableEntries[i].style.display = 'none';
+        }
+      }
+      this.filterVisualizer();
+    },
+
+    /**
+     * Initializes filter tags and checkboxes. There are two types of filters:
+     * Level and Process. Level filters are static that we have only 4 levels
+     * in total but process filters are dynamically changing based on the log.
+     * The filter layout looks like:
+     *  |-----------------------------------------------------------------|
+     *  |                                                                 |
+     *  |                     Section of process filter                   |
+     *  |                                                                 |
+     *  |-----------------------------------------------------------------|
+     *  |                                                                 |
+     *  |                      Section of level filter                    |
+     *  |                                                                 |
+     *  |-----------------------------------------------------------------|
+     */
+    createFilter: function() {
+      this.createFilterByPName();
+      this.levelCheckboxes = {
+        'Error': $('checkbox-error'),
+        'Warning': $('checkbox-warning'),
+        'Info': $('checkbox-info'),
+        'Unknown': $('checkbox-unknown')
+      };
+
+      for (var level in this.levelCheckboxes) {
+        this.levelCheckboxes[level].addEventListener(
+            'change', this.onFilterChange_.bind(this));
+      }
+    },
+
+    /**
+     * Helper function of createFilter(). Create filter section of
+     * process filters.
+     */
+    createFilterByPName: function() {
+      var filterContainerDiv = $(CrosLogAnalyzerView.LOG_FILTER_PNAME_ID);
+      filterContainerDiv.innerHTML = 'Process: ';
+      for (var i = 0; i < this.pNames.length; i++) {
+        var pNameBlock = this.createPNameBlock(this.pNames[i]);
+        filterContainerDiv.appendChild(pNameBlock);
+      }
+    },
+
+    /**
+     * Helper function of createFilterByPName(). Create a single filter block in
+     * the section of process filters.
+     */
+    createPNameBlock: function(pName) {
+      var block = document.createElement('span');
+      block.className = LOG_FILTER_PNAME_BLOCK_CLASSNAME;
+
+      var tag = document.createElement('label');
+      var span = document.createElement('span');
+      span.textContent = pName;
+
+      var checkbox = document.createElement('input');
+      checkbox.type = 'checkbox';
+      checkbox.name = pName;
+      checkbox.value = pName;
+      checkbox.checked = true;
+      checkbox.addEventListener('change', this.onFilterChange_.bind(this));
+      this.pNameCheckboxes[pName] = checkbox;
+
+      tag.appendChild(checkbox);
+      tag.appendChild(span);
+      block.appendChild(tag);
+
+      return block;
+    },
+
+    /**
+     * Click handler for filter checkboxes. Everytime a checkbox is clicked,
+     * the visibility of related logEntries are changed.
+     */
+    onFilterChange_: function() {
+      this.filterLog();
+    },
+
+    /**
+     * Creates a visualizer that visualizes the logs as a timeline graph
+     * during the initialization of the View.
+     */
+    createVisualizer: function() {
+      this.visualizer = new CrosLogVisualizer(this,
+          CrosLogAnalyzerView.LOG_VISUALIZER_CONTAINER_ID);
+      this.visualizer.updateEvents(this.logEntries);
+    },
+
+    /**
+     * Sync the visibility of log entries with the visualizer.
+     */
+    filterVisualizer: function() {
+      this.visualizer.updateEvents(this.logEntries);
+    },
+
+    /**
+     * Called during the initialization. It creates the log marker that
+     * highlights log text.
+     */
+    createLogMaker: function() {
+      this.marker = new CrosLogMarker(this);
+    },
+
+    /**
+     * Given a row text line of log, a logEntry instance is initialized and used
+     * for parsing. After the text is parsed, we put the instance into
+     * logEntries which is an array for storing. This function is called when
+     * the data is received from Browser Bridge.
+     */
+    addLogEntry: function(logType, textEntry) {
+      var newEntry = new CrosLogEntry();
+      if (logType == LOGS_LIST.NETWORK_LOG) {
+        newEntry.tokenizeNetworkLog(textEntry);
+      } else {
+        //TODO(shinfan): Add more if cases here
+      }
+      this.logEntries.push(newEntry);
+
+      // Record pname
+      var pName = newEntry.processName;
+      if (this.pNames.indexOf(pName) == -1) {
+        this.pNames.push(pName);
+      }
+    },
+
+    /*
+     * Asynchronous call back function from Browser Bridge.
+     */
+    onSystemLogChanged: function(callback) {
+      if (callback.log == this.logData) return;
+      this.logData = callback.log;
+      // Clear the old array by setting length to zero
+      this.logEntries.length = 0;
+      var entries = callback.log.split('\n');
+      for (var i = 1; i < entries.length; i++) {
+        this.addLogEntry(LOGS_LIST.NETWORK_LOG, entries[i]);
+      }
+      this.refresh();
+    }
+  };
+
+  return CrosLogAnalyzerView;
+})();
diff --git a/chrome/browser/resources/net_internals/cros_log_entry.js b/chrome/browser/resources/net_internals/cros_log_entry.js
new file mode 100644
index 0000000..70822a0
--- /dev/null
+++ b/chrome/browser/resources/net_internals/cros_log_entry.js
@@ -0,0 +1,102 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * This class stores information of one single entry of log
+ */
+
+var CrosLogEntry = function() {
+
+  /**
+    * @constructor
+    */
+  function CrosLogEntry() {
+    // The entry is visible by default
+    this.visibility = true;
+  }
+
+  CrosLogEntry.prototype = {
+    //------------------------------------------------------------------------
+    // Log input text parser
+    // Parses network log into tokens like time, name, pid
+    // and description.
+    //--------------------------------------------------------------------------
+    tokenizeNetworkLog: function(NetworkLogEntry) {
+      var tokens = NetworkLogEntry.split(' ');
+      var timeTokens = tokens[0].split(/[\s|\:|\-|T|\.]/);
+
+      // List of all parameters for Date Object
+      var year = timeTokens[0];
+      var month = timeTokens[1];
+      var day = timeTokens[2];
+      var hour = timeTokens[3];
+      var minute = timeTokens[4];
+      var second = timeTokens[5];
+      var millisecond = (parseInt(timeTokens[6]) / 1000).toFixed(0);
+      this.time = new Date(year, month, day, hour, minute,
+                           second, millisecond);
+
+      // Parses for process name and ID.
+      var process = tokens[2];
+      if (hasProcessID(process)) {
+        var processTokens = process.split(/[\[|\]]/);
+        this.processName = processTokens[0];
+        this.processID = processTokens[1];
+      } else {
+        this.processName = process.split(/\:/)[0];
+        this.processID = 'Unknown';
+      }
+
+      // Gets level of the log: error|warning|info|unknown if failed.
+      this.level = hasLevelInfo(tokens[3]);
+
+      // Treats the rest of the entry as description.
+      var descriptionStartPoint = NetworkLogEntry.indexOf(tokens[2]) +
+          tokens[2].length;
+      this.description = NetworkLogEntry.substr(descriptionStartPoint);
+    },
+
+    // Represents the Date object as a string.
+    getTime: function() {
+      return this.time.getMonth() + '/' + this.time.getDate() +
+          ' ' + this.time.getHours() + ':' + this.time.getMinutes() +
+          ':' + this.time.getSeconds() + ':' + this.time.getMilliseconds();
+    }
+  };
+
+  /**
+   * Helper function
+   * Takes a token as input and searches for '['.
+   * We assume if the token contains '[' it contains a process ID.
+   *
+   * @param {string} token A token from log
+   * @return {boolean} true if '[' is found
+   */
+  var hasProcessID = function(token) {
+    return token != undefined && token.indexOf('[') != -1;
+  }
+
+  /**
+   * Helper function
+   * Checks if the input token contains level information.
+   *
+   * @param {string} token A token from log
+   * @return {string} Level found in the token
+   */
+  var hasLevelInfo = function(token) {
+    if (token == undefined)
+      return 'Unknown';
+    if (token.toLowerCase().indexOf('err') != -1) {
+      return 'Error';
+    } else if (token.toLowerCase().indexOf('warn') != -1) {
+      return 'Warning';
+    } else if (token.toLowerCase().indexOf('info') != -1) {
+      return 'Info';
+    } else {
+      return 'Unknown';
+    }
+  }
+
+  return CrosLogEntry;
+}();
diff --git a/chrome/browser/resources/net_internals/cros_log_marker.js b/chrome/browser/resources/net_internals/cros_log_marker.js
new file mode 100644
index 0000000..71201e3
--- /dev/null
+++ b/chrome/browser/resources/net_internals/cros_log_marker.js
@@ -0,0 +1,394 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+/**
+ * This class stores the filter queries as history and highlight the log text
+ * to increase the readability of the log
+ *
+ *   - Enable / Disable highlights
+ *   - Highlights text with multiple colors
+ *   - Resolve hghlight conficts (A text highlighted by multiple colors) so that
+ *     the latest added highlight always has highest priority to display.
+ *
+ */
+var CrosLogMarker = (function() {
+  'use strict';
+
+  // Special classes (defined in log_analyzer_view.css)
+  var LOG_MARKER_HIGHLIGHT_CLASS = 'cros-log-analyzer-marker-highlight';
+  var LOG_MARKER_CONTAINER_ID = 'cros-log-analyzer-marker-container';
+  var LOG_MARKER_HISTORY_ENTRY_CLASS = 'cros-log-analyzer-marker-history-entry';
+  var LOG_MARKER_HISTORY_COLOR_TAG_CLASS =
+          'cros-log-analyzer-marker-history-color-tag';
+
+  /**
+   * Colors used for highlighting. (Current we support 6 colors)
+   * TODO(shinfan): Add more supoorted colors.
+   */
+  var COLOR_USAGE_SET = {
+    'Crimson': false,
+    'DeepSkyBlue': false,
+    'DarkSeaGreen': false,
+    'GoldenRod': false,
+    'IndianRed': false,
+    'Orange': false
+  };
+  var COLOR_NUMBER = Object.keys(COLOR_USAGE_SET).length;
+
+
+  /**
+   * CrosHighlightTag represents a single highlight tag in text.
+   */
+  var CrosHighlightTag = (function() {
+    /**
+     * @constructor
+     */
+    function CrosHighlightTag(color, field, range, priority) {
+      this.color = color;
+      this.field = field;
+      this.range = range;
+      this.priority = priority;
+      this.enabled = true;
+    }
+
+    return CrosHighlightTag;
+  })();
+
+  /**
+   * @constructor
+   * @param {CrosLogAnalyzerView} logAnalyzerView A reference to
+   *     CrosLogAnalyzerView.
+   */
+  function CrosLogMarker(logAnalyzerView) {
+    this.container = $(LOG_MARKER_CONTAINER_ID);
+    // Stores highlight objects for each entry.
+    this.entryHighlights = [];
+    // Stores all the filter queries.
+    this.markHistory = {};
+    // Object references from CrosLogAnalyzerView.
+    this.logEntries = logAnalyzerView.logEntries;
+    this.logAnalyzerView = logAnalyzerView;
+    // Counts how many highlights are created.
+    this.markCount = 0;
+    for (var i = 0; i < this.logEntries.length; i++) {
+      this.entryHighlights.push([]);
+    }
+  }
+
+  CrosLogMarker.prototype = {
+    /**
+     * Saves the query to the mark history and highlights the text
+     * based on the query.
+     */
+    addMarkHistory: function(query) {
+      // Increases the counter
+      this.markCount += 1;
+
+      // Find an avaiable color.
+      var color = this.pickColor();
+      if (!color) {
+        // If all colors are occupied.
+        alert('You can only add at most ' + COLOR_NUMBER + 'markers.');
+        return;
+      }
+
+      // Updates HTML elements.
+      var historyEntry = addNode(this.container, 'div');
+      historyEntry.className = LOG_MARKER_HISTORY_ENTRY_CLASS;
+
+      // A color tag that indicats the color used.
+      var colorTag = addNode(historyEntry, 'div');
+      colorTag.className = LOG_MARKER_HISTORY_COLOR_TAG_CLASS;
+      colorTag.style.background = color;
+
+      // Displays the query text.
+      var queryText = addNodeWithText(historyEntry, 'p', query);
+      queryText.style.color = color;
+
+      // Adds a button to remove the marker.
+      var removeBtn = addNodeWithText(historyEntry, 'a', 'Remove');
+      removeBtn.addEventListener(
+          'click', this.onRemoveBtnClicked_.bind(this, historyEntry, color));
+
+      // A checkbox that lets user enable and disable the marker.
+      var enableCheckbox = addNode(historyEntry, 'input');
+      enableCheckbox.type = 'checkbox';
+      enableCheckbox.checked = true;
+      enableCheckbox.color = color;
+      enableCheckbox.addEventListener('change',
+          this.onEnableCheckboxChange_.bind(this, enableCheckbox), false);
+
+      // Searches log text for matched patterns and highlights them.
+      this.patternMatch(query, color);
+    },
+
+    /**
+     * Search the text for matched strings
+     */
+    patternMatch: function(query, color) {
+      var pattern = new RegExp(query, 'i');
+      for (var i = 0; i < this.logEntries.length; i++) {
+        var entry = this.logEntries[i];
+        // Search description of each log entry
+        // TODO(shinfan): Add more search fields
+        var positions = this.findPositions(
+            pattern, entry.description);
+        for (var j = 0; j < positions.length; j++) {
+            var pos = positions[j];
+            this.mark(entry, pos, 'description', color);
+        }
+        this.sortHighlightsByStartPosition_(this.entryHighlights[i]);
+      }
+    },
+
+    /**
+     * Highlights the text.
+     * @param {CrosLogEntry} entry The log entry to be highlighted
+     * @param {int|Array} position [start, end]
+     * @param {string} field The field of entry to be highlighted
+     * @param {string} color color used for highlighting
+     */
+    mark: function(entry, position, field, color) {
+      // Creates the highlight object
+      var tag = new CrosHighlightTag(color, field, position, this.markCount);
+      // Add the highlight into entryHighlights
+      this.entryHighlights[entry.rowNum].push(tag);
+    },
+
+    /**
+     * Find the highlight objects that covers the given position
+     * @param {CrosHighlightTag|Array} highlights highlights of a log entry
+     * @param {int} position The target index
+     * @param {string} field The target field
+     * @return {CrosHighlightTag|Array} Highlights that cover the position
+     */
+    getHighlight: function(highlights, index, field) {
+      var res = [];
+      for (var j = 0; j < highlights.length; j++) {
+        var highlight = highlights[j];
+        if (highlight.range[0] <= index &&
+            highlight.range[1] > index &&
+            highlight.field == field &&
+            highlight.enabled) {
+          res.push(highlight);
+        }
+      }
+      /**
+       * Sorts the result by priority so that the highlight with
+       * highest priority comes first.
+       */
+      this.sortHighlightsByPriority_(res);
+      return res;
+    },
+
+    /**
+     * This function highlights the entry by going through the text from left
+     * to right and searching for "key" positions.
+     * A "key" position is a position that one (or more) highlight
+     * starts or ends. We only care about "key" positions because this is where
+     * the text highlight status changes.
+     * At each key position, the function decides if the text between this
+     * position and previous position need to be highlighted and resolves
+     * highlight conflicts.
+     *
+     * @param {CrosLogEntry} entry The entry going to be highlighted.
+     * @param {string} field The specified field of the entry.
+     * @param {DOMElement} parent Parent node.
+     */
+    getHighlightedEntry: function(entry, field, parent) {
+      var rowNum = entry.rowNum;
+      // Get the original text content of the entry (without any highlights).
+      var content = this.logEntries[rowNum][field];
+      var index = 0;
+      while (index < content.length) {
+        var nextIndex = this.getNextIndex(
+            this.entryHighlights[rowNum], index, field, content);
+        // Searches for highlights that have the position in range.
+        var highlights = this.getHighlight(
+            this.entryHighlights[rowNum], index, field);
+        var text = content.substr(index, nextIndex - index);
+        if (highlights.length > 0) {
+          // Always picks the highlight with highest priority.
+          this.addSpan(text, highlights[0].color, parent);
+        } else {
+          addNodeWithText(parent, 'span', text);
+        }
+        index = nextIndex;
+      }
+    },
+
+    /**
+     * A helper function that is used by this.getHightlightedEntry
+     * It returns the first index where a highlight begins or ends from
+     * the given index.
+     * @param {CrosHighlightTag|Array} highlights An array of highlights
+     *     of a log entry.
+     * @param {int} index The start position.
+     * @param {string} field The specified field of entry.
+     *     Other fields are ignored.
+     * @param {string} content The text content of the log entry.
+     * @return {int} The first index where a highlight begins or ends.
+     */
+    getNextIndex: function(highlights, index, field, content) {
+      var minGap = Infinity;
+      var res = -1;
+      for (var i = 0; i < highlights.length; i++) {
+        if (highlights[i].field != field || !highlights[i].enabled)
+          continue;
+        // Distance between current index and the start index of highlight.
+        var gap1 = highlights[i].range[0] - index;
+        // Distance between current index and the end index of highlight.
+        var gap2 = highlights[i].range[1] - index;
+        if (gap1 > 0 && gap1 < minGap) {
+          minGap = gap1;
+          res = highlights[i].range[0];
+        }
+        if (gap2 > 0 && gap2 < minGap) {
+          minGap = gap2;
+          res = highlights[i].range[1];
+        }
+      }
+      // Returns |res| if found. Otherwise returns the end position of the text.
+      return res > 0 ? res : content.length;
+    },
+
+    /**
+     * A helper function that is used by this.getHightlightedEntry.
+     * It adds the HTML label to the text.
+     */
+    addSpan: function(text, color, parent) {
+      var span = addNodeWithText(parent, 'span', text);
+      span.style.color = color;
+      span.className = LOG_MARKER_HIGHLIGHT_CLASS;
+    },
+
+    /**
+     * A helper function that is used by this.getHightlightedEntry.
+     * It adds the HTML label to the text.
+     */
+    pickColor: function() {
+      for (var color in COLOR_USAGE_SET) {
+        if (!COLOR_USAGE_SET[color]) {
+          COLOR_USAGE_SET[color] = true;
+          return color;
+        }
+      }
+      return false;
+    },
+
+    /**
+     * A event handler that enables and disables the corresponding marker.
+     * @private
+     */
+    onEnableCheckboxChange_: function(checkbox) {
+      for (var i = 0; i < this.entryHighlights.length; i++) {
+        for (var j = 0; j < this.entryHighlights[i].length; j++) {
+          if (this.entryHighlights[i][j].color == checkbox.color) {
+            this.entryHighlights[i][j].enabled = checkbox.checked;
+           }
+        }
+      }
+      this.refreshLogTable();
+    },
+
+    /**
+     * A event handlier that removes the marker from history.
+     * @private
+     */
+    onRemoveBtnClicked_: function(entry, color) {
+      entry.parentNode.removeChild(entry);
+      COLOR_USAGE_SET[color] = false;
+      for (var i = 0; i < this.entryHighlights.length; i++) {
+        var highlights = this.entryHighlights[i];
+        while (true) {
+          var index = this.findHighlightByColor_(highlights, color);
+          if (index == -1)
+            break;
+          highlights.splice(index, 1);
+        }
+      }
+      this.refreshLogTable();
+    },
+
+    /**
+     * A helper function that returns the index of first highlight that
+     * has the target color. Otherwise returns -1.
+     * @private
+     */
+    findHighlightByColor_: function(highlights, color) {
+      for (var i = 0; i < highlights.length; i++) {
+        if (highlights[i].color == color)
+          return i;
+      }
+      return -1;
+    },
+
+    /**
+     * Refresh the log table in the CrosLogAnalyzerView.
+     */
+    refreshLogTable: function() {
+      this.logAnalyzerView.populateTable();
+      this.logAnalyzerView.filterLog();
+    },
+
+    /**
+     * A pattern can appear multiple times in a string.
+     * Returns positions of all the appearance.
+     */
+    findPositions: function(pattern, str) {
+      var res = [];
+      str = str.toLowerCase();
+      var match = str.match(pattern);
+      if (!match)
+        return res;
+      for (var i = 0; i < match.length; i++) {
+        var index = 0;
+        while (true) {
+          var start = str.indexOf(match[i].toLowerCase(), index);
+          if (start == -1)
+            break;
+          var end = start + match[i].length;
+          res.push([start, end]);
+          index = end + 1;
+        }
+      }
+      return res;
+    },
+
+    /**
+     * A helper function used in sorting highlights by start position.
+     * @param {HighlightTag} h1, h2 Two highlight tags in the array.
+     * @private
+     */
+    compareStartPosition_: function(h1, h2) {
+      return h1.range[0] - h2.range[0];
+    },
+
+    /**
+     * A helper function used in sorting highlights by priority.
+     * @param {HighlightTag} h1, h2 Two highlight tags in the array.
+     * @private
+     */
+    comparePriority_: function(h1, h2) {
+      return h2.priority - h1.priority;
+    },
+
+    /**
+     * A helper function that sorts the highlights array by start position.
+     * @private
+     */
+    sortHighlightsByStartPosition_: function(highlights) {
+      highlights.sort(this.compareStartPosition_);
+    },
+
+    /**
+     * A helper function that sorts the highlights array by priority.
+     * @private
+     */
+    sortHighlightsByPriority_: function(highlights) {
+      highlights.sort(this.comparePriority_);
+    }
+  };
+
+  return CrosLogMarker;
+})();
diff --git a/chrome/browser/resources/net_internals/cros_log_visualizer.js b/chrome/browser/resources/net_internals/cros_log_visualizer.js
new file mode 100644
index 0000000..40b5475
--- /dev/null
+++ b/chrome/browser/resources/net_internals/cros_log_visualizer.js
@@ -0,0 +1,376 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * This visualizer displays the log in a timeline graph
+ *
+ *   - Use HTML5 canvas
+ *   - Can zoom in result by select time range
+ *   - Display different levels of logs in different layers of canvases
+ *
+ */
+var CrosLogVisualizer = (function() {
+  'use strict';
+
+  // HTML attributes of canvas
+  var LOG_VISUALIZER_CANVAS_CLASS = 'cros-log-analyzer-visualizer-canvas';
+  var LOG_VISUALIZER_CANVAS_WIDTH = 980;
+  var LOG_VISUALIZER_CANVAS_HEIGHT = 100;
+
+  // Special HTML classes
+  var LOG_VISUALIZER_TIMELINE_ID = 'cros-log-analyzer-visualizer-timeline';
+  var LOG_VISUALIZER_TIME_DISPLAY_CLASS =
+      'cros-log-analyzer-visualizer-time-display';
+  var LOG_VISUALIZER_RESET_BTN_ID =
+      'cros-log-analyzer-visualizer-reset-btn';
+  var LOG_VISUALIZER_TRACKING_LAYER_ID =
+      'cros-log-analyzer-visualizer-tracking-layer';
+
+  /**
+   * Event level list
+   * This list is used for intialization of canvases. And the canvas
+   * with lowest priority should be created first. Hence the list is
+   * sorted in decreasing order.
+   */
+  var LOG_EVENT_LEVEL_PRIORITY_LIST = {
+    'Unknown': 4,
+    'Warning': 2,
+    'Info': 3,
+    'Error': 1
+  };
+
+  // Color mapping of different levels
+  var LOG_EVENT_COLORS_LIST = {
+    'Error': '#FF99A3',
+    'Warning': '#FAE5C3',
+    'Info': '#C3E3FA',
+    'Unknown': 'gray'
+  };
+
+  /**
+   * @constructor
+   */
+  function CrosLogVisualizer(logAnalyzer, containerID) {
+    /**
+     * Pass the LogAnalyzer in as a reference so the visualizer can
+     * synchrous with the log filter.
+     */
+    this.logAnalyzer = logAnalyzer;
+
+    // If the data is initialized
+    this.dataIntialized = false;
+    // Stores all the log entries as events
+    this.events = [];
+    // A front layer that handles control events
+    this.trackingLayer = this.createTrackingLayer();
+
+    // References to HTML elements
+    this.container = document.getElementById(containerID);
+    this.timeline = this.createTimeline();
+    this.timeDisplay = this.createTimeDisplay();
+    this.btnReset = this.createBtnReset();
+    // Canvases
+    this.canvases = {};
+    for (var level in LOG_EVENT_LEVEL_PRIORITY_LIST) {
+      this.canvases[level] = this.createCanvas();
+      this.container.appendChild(this.canvases[level]);
+    }
+
+    // Append all the elements to the container
+    this.container.appendChild(this.timeline);
+    this.container.appendChild(this.timeDisplay);
+    this.container.appendChild(this.trackingLayer);
+    this.container.appendChild(this.btnReset);
+
+    this.container.addEventListener('webkitAnimationEnd', function() {
+      this.container.classList.remove('cros-log-analyzer-flash');
+    }.bind(this), false);
+  }
+
+  CrosLogVisualizer.prototype = {
+    /**
+     * Called during the initialization of the View. Create a overlay
+     * DIV on top of the canvas that handles the mouse events
+     */
+    createTrackingLayer: function() {
+      var trackingLayer = document.createElement('div');
+      trackingLayer.setAttribute('id', LOG_VISUALIZER_TRACKING_LAYER_ID);
+      trackingLayer.addEventListener('mousemove', this.onHovered_.bind(this));
+      trackingLayer.addEventListener('mousedown', this.onMouseDown_.bind(this));
+      trackingLayer.addEventListener('mouseup', this.onMouseUp_.bind(this));
+      return trackingLayer;
+    },
+
+    /**
+     * This function is called during the initialization of the view.
+     * It creates the timeline that moves along with the mouse on canvas.
+     * When user click, a rectangle can be dragged out to select the range
+     * to zoom.
+     */
+    createTimeline: function() {
+      var timeline = document.createElement('div');
+      timeline.setAttribute('id', LOG_VISUALIZER_TIMELINE_ID);
+      timeline.style.height = LOG_VISUALIZER_CANVAS_HEIGHT + 'px';
+      timeline.addEventListener('mousedown', function(event) { return false; });
+      return timeline;
+    },
+
+    /**
+     * This function is called during the initialization of the view.
+     * It creates a time display that moves with the timeline
+     */
+    createTimeDisplay: function() {
+      var timeDisplay = document.createElement('p');
+      timeDisplay.className = LOG_VISUALIZER_TIME_DISPLAY_CLASS;
+      timeDisplay.style.top = LOG_VISUALIZER_CANVAS_HEIGHT + 'px';
+      return timeDisplay;
+    },
+
+    /**
+     * Called during the initialization of the View. Create a button that
+     * resets the canvas to initial status (without zoom)
+     */
+    createBtnReset: function() {
+      var btnReset = document.createElement('input');
+      btnReset.setAttribute('type', 'button');
+      btnReset.setAttribute('value', 'Reset');
+      btnReset.setAttribute('id', LOG_VISUALIZER_RESET_BTN_ID);
+      btnReset.addEventListener('click', this.reset.bind(this));
+      return btnReset;
+    },
+
+    /**
+     * Called during the initialization of the View. Create a empty canvas
+     * that visualizes log when the data is ready
+     */
+    createCanvas: function() {
+      var canvas = document.createElement('canvas');
+      canvas.width = LOG_VISUALIZER_CANVAS_WIDTH;
+      canvas.height = LOG_VISUALIZER_CANVAS_HEIGHT;
+      canvas.className = LOG_VISUALIZER_CANVAS_CLASS;
+      return canvas;
+    },
+
+    /**
+     * Returns the context of corresponding canvas based on level
+     */
+    getContext: function(level) {
+      return this.canvases[level].getContext('2d');
+    },
+
+    /**
+     * Erases everything from all the canvases
+     */
+    clearCanvas: function() {
+      for (var level in LOG_EVENT_LEVEL_PRIORITY_LIST) {
+        var ctx = this.getContext(level);
+        ctx.clearRect(0, 0, LOG_VISUALIZER_CANVAS_WIDTH,
+            LOG_VISUALIZER_CANVAS_HEIGHT);
+      }
+    },
+
+    /**
+     * Initializes the parameters needed for drawing:
+     *  - lower/upperBound: Time range (Events out of range will be skipped)
+     *  - totalDuration: The length of time range
+     *  - unitDuration: The unit time length per pixel
+     */
+    initialize: function() {
+      if (this.events.length == 0)
+        return;
+      this.dragMode = false;
+      this.dataIntialized = true;
+      this.events.sort(this.compareTime);
+      this.lowerBound = this.events[0].time;
+      this.upperBound = this.events[this.events.length - 1].time;
+      this.totalDuration = Math.abs(this.upperBound.getTime() -
+          this.lowerBound.getTime());
+      this.unitDuration = this.totalDuration / LOG_VISUALIZER_CANVAS_WIDTH;
+    },
+
+    /**
+     * CSS3 fadeIn/fadeOut effects
+     */
+    flashEffect: function() {
+      this.container.classList.add('cros-log-analyzer-flash');
+    },
+
+    /**
+     * Reset the canvas to the initial time range
+     * Redraw everything on the canvas
+     * Fade in/out effects while redrawing
+     */
+    reset: function() {
+      // Reset all the parameters as initial
+      this.initialize();
+      // Reset the visibility of the entries in the log table
+      this.logAnalyzer.filterLog();
+      this.flashEffect();
+     },
+
+    /**
+     * A wrapper function for drawing
+     */
+    drawEvents: function() {
+      if (this.events.length == 0)
+        return;
+      for (var i in this.events) {
+        this.drawEvent(this.events[i]);
+      }
+    },
+
+    /**
+     * The main function that handles drawing on the canvas.
+     * Every event is represented as a vertical line.
+     */
+    drawEvent: function(event) {
+      if (!event.visibility) {
+        // Skip hidden events
+        return;
+      }
+      var ctx = this.getContext(event.level);
+      ctx.beginPath();
+      // Get the x-coordinate of the line
+      var startPosition = this.getPosition(event.time);
+      if (startPosition != this.old) {
+        this.old = startPosition;
+      }
+      ctx.rect(startPosition, 0, 2, LOG_VISUALIZER_CANVAS_HEIGHT);
+      // Get the color of the line
+      ctx.fillStyle = LOG_EVENT_COLORS_LIST[event.level];
+      ctx.fill();
+      ctx.closePath();
+    },
+
+    /**
+     * This function is called every time the graph is zoomed.
+     * It recalculates all the parameters based on the distance and direction
+     * of dragging.
+     */
+    reCalculate: function() {
+      if (this.dragDistance >= 0) {
+        // if user drags to right
+        this.upperBound = new Date((this.timelineLeft + this.dragDistance) *
+            this.unitDuration + this.lowerBound.getTime());
+        this.lowerBound = new Date(this.timelineLeft * this.unitDuration +
+            this.lowerBound.getTime());
+      } else {
+        // if user drags to left
+        this.upperBound = new Date(this.timelineLeft * this.unitDuration +
+            this.lowerBound.getTime());
+        this.lowerBound = new Date((this.timelineLeft + this.dragDistance) *
+            this.unitDuration + this.lowerBound.getTime());
+      }
+      this.totalDuration = this.upperBound.getTime() -
+          this.lowerBound.getTime();
+      this.unitDuration = this.totalDuration / LOG_VISUALIZER_CANVAS_WIDTH;
+    },
+
+    /**
+     * Check if the time of a event is out of bound
+     */
+    isOutOfBound: function(event) {
+      return event.time.getTime() < this.lowerBound.getTime() ||
+              event.time.getTime() > this.upperBound.getTime();
+    },
+
+    /**
+     * This function returns the offset on x-coordinate of canvas based on
+     * the time
+     */
+    getPosition: function(time) {
+      return (time.getTime() - this.lowerBound.getTime()) / this.unitDuration;
+    },
+
+    /**
+     * This function updates the events array and refresh the canvas.
+     */
+    updateEvents: function(newEvents) {
+      this.events.length = 0;
+      for (var i in newEvents) {
+        this.events.push(newEvents[i]);
+      }
+      if (!this.dataIntialized) {
+        this.initialize();
+      }
+      this.clearCanvas();
+      this.drawEvents();
+    },
+
+    /**
+     * This is a helper function that returns the time object based on the
+     * offset of x-coordinate on the canvs.
+     */
+    getOffsetTime: function(offset) {
+      return new Date(this.lowerBound.getTime() + offset * this.unitDuration);
+    },
+
+    /**
+     * This function is triggered when the hovering event is detected
+     * When the mouse is hovering we have two control mode:
+     *  - If it is in drag mode, we need to resize the width of the timeline
+     *  - If not, we need to move the timeline and time display to the
+     * x-coordinate position of the mouse
+     */
+    onHovered_: function(event) {
+      var offsetX = event.offsetX;
+      if (this.lastOffsetX == offsetX) {
+        // If the mouse does not move, we just skip the event
+        return;
+      }
+
+      if (this.dragMode == true) {
+        // If the mouse is in drag mode
+        this.dragDistance = offsetX - this.timelineLeft;
+        if (this.dragDistance >= 0) {
+          // If the mouse is moving right
+          this.timeline.style.width = this.dragDistance + 'px';
+        } else {
+          // If the mouse is moving left
+          this.timeline.style.width = -this.dragDistance + 'px';
+          this.timeline.style.left = offsetX + 'px';
+        }
+      } else {
+        // If the mouse is not in drag mode we just move the timeline
+        this.timeline.style.width = '2px';
+        this.timeline.style.left = offsetX + 'px';
+      }
+
+      // update time display
+      this.timeDisplay.style.left = offsetX + 'px';
+      this.timeDisplay.textContent =
+          this.getOffsetTime(offsetX).toTimeString().substr(0, 8);
+      // update the last offset
+      this.lastOffsetX = offsetX;
+    },
+
+    /**
+     * This function is the handler for the onMouseDown event on the canvas
+     */
+    onMouseDown_: function(event) {
+      // Enter drag mode which let user choose a time range to zoom in
+      this.dragMode = true;
+      this.timelineLeft = event.offsetX;
+      // Create a duration display to indicate the duration of range.
+      this.timeDurationDisplay = this.createTimeDisplay();
+      this.container.appendChild(this.timeDurationDisplay);
+    },
+
+    /**
+     * This function is the handler for the onMouseUp event on the canvas
+     */
+    onMouseUp_: function(event) {
+      // Remove the duration display
+      this.container.removeChild(this.timeDurationDisplay);
+      // End the drag mode
+      this.dragMode = false;
+      // Recalculate the pamameter based on the range user select
+      this.reCalculate();
+      // Filter the log table and hide the entries that are not in the range
+      this.logAnalyzer.filterLog();
+    },
+  };
+
+  return CrosLogVisualizer;
+})();
diff --git a/chrome/browser/resources/net_internals/index.html b/chrome/browser/resources/net_internals/index.html
index 774dbf2..6771cb4 100644
--- a/chrome/browser/resources/net_internals/index.html
+++ b/chrome/browser/resources/net_internals/index.html
@@ -15,6 +15,7 @@
     <link rel="stylesheet" href="timeline_view.css">
     <link rel="stylesheet" href="logs_view.css">
     <link rel="stylesheet" href="chromeos_view.css">
+    <link rel="stylesheet" href="cros_log_analyzer_view.css">
     <script src="chrome://resources/js/util.js"></script>
     <script src="chrome://resources/js/cr.js"></script>
     <script src="chrome://net-internals/index.js"></script>
@@ -43,6 +44,7 @@
       <include src="timeline_view.html"/>
       <include src="logs_view.html"/>
       <include src="chromeos_view.html"/>
+      <include src="cros_log_analyzer_view.html"/>
     </div>
 
     <script src="chrome://resources/js/i18n_template.js"></script>
diff --git a/chrome/browser/resources/net_internals/index.js b/chrome/browser/resources/net_internals/index.js
index f8d7f36..44465fd 100644
--- a/chrome/browser/resources/net_internals/index.js
+++ b/chrome/browser/resources/net_internals/index.js
@@ -48,6 +48,10 @@
 <include src="chromeos_view.js"/>
 <include src="http_pipeline_view.js"/>
 <include src="bandwidth_view.js"/>
+<include src="cros_log_analyzer_view.js"/>
+<include src="cros_log_entry.js"/>
+<include src="cros_log_visualizer.js" />
+<include src="cros_log_marker.js" />
 
 document.addEventListener('DOMContentLoaded', function() {
   MainView.getInstance();  // from main.js
diff --git a/chrome/browser/resources/net_internals/log_view_painter.js b/chrome/browser/resources/net_internals/log_view_painter.js
index 52f2921..eec71b5 100644
--- a/chrome/browser/resources/net_internals/log_view_painter.js
+++ b/chrome/browser/resources/net_internals/log_view_painter.js
@@ -329,6 +329,18 @@
     return;
   }
 
+  if (key == 'quic_error' && typeof value == 'number') {
+    var valueStr = value + ' (' + quicErrorToString(value) + ')';
+    out.writeArrowKeyValue(key, valueStr);
+    return;
+  }
+
+  if (key == 'quic_rst_stream_error' && typeof value == 'number') {
+    var valueStr = value + ' (' + quicRstStreamErrorToString(value) + ')';
+    out.writeArrowKeyValue(key, valueStr);
+    return;
+  }
+
   if (key == 'load_flags' && typeof value == 'number') {
     var valueStr = value + ' (' + getLoadFlagSymbolicString(value) + ')';
     out.writeArrowKeyValue(key, valueStr);
diff --git a/chrome/browser/resources/net_internals/main.js b/chrome/browser/resources/net_internals/main.js
index 22221ae..8cbd37c 100644
--- a/chrome/browser/resources/net_internals/main.js
+++ b/chrome/browser/resources/net_internals/main.js
@@ -15,6 +15,8 @@
 var LogLevelType = null;
 var ClientInfo = null;
 var NetError = null;
+var QuicError = null;
+var QuicRstStreamError = null;
 var LoadFlag = null;
 var LoadState = null;
 var AddressFamily = null;
@@ -192,6 +194,7 @@
       addTab(HttpCacheView);
       addTab(ModulesView);
       addTab(TestView);
+      addTab(CrosLogAnalyzerView);
       addTab(HSTSView);
       addTab(LogsView);
       addTab(BandwidthView);
@@ -200,6 +203,7 @@
 
       this.tabSwitcher_.showMenuItem(LogsView.TAB_ID, cr.isChromeOS);
       this.tabSwitcher_.showMenuItem(CrosView.TAB_ID, cr.isChromeOS);
+      this.tabSwitcher_.showMenuItem(CrosLogAnalyzerView.TAB_ID, cr.isChromeOS);
     },
 
     /**
@@ -301,6 +305,8 @@
   ClientInfo = Constants.clientInfo;
   LoadFlag = Constants.loadFlag;
   NetError = Constants.netError;
+  QuicError = Constants.quicError;
+  QuicRstStreamError = Constants.quicRstStreamError;
   AddressFamily = Constants.addressFamily;
   LoadState = Constants.loadState;
 
@@ -329,7 +335,7 @@
 /**
  * Returns the name for netError.
  *
- * Example: netErrorToString(-105) would return
+ * Example: netErrorToString(-105) should return
  * "ERR_NAME_NOT_RESOLVED".
  * @param {number} netError The net error code.
  * @return {string} The name of the given error.
@@ -342,6 +348,30 @@
 }
 
 /**
+ * Returns the name for quicError.
+ *
+ * Example: quicErrorToString(25) should return
+ * "TIMED_OUT".
+ * @param {number} quicError The QUIC error code.
+ * @return {string} The name of the given error.
+ */
+function quicErrorToString(quicError) {
+  return getKeyWithValue(QuicError, quicError);
+}
+
+/**
+ * Returns the name for quicRstStreamError.
+ *
+ * Example: quicRstStreamErrorToString(3) should return
+ * "BAD_APPLICATION_PAYLOAD".
+ * @param {number} quicRstStreamError The QUIC RST_STREAM error code.
+ * @return {string} The name of the given error.
+ */
+function quicRstStreamErrorToString(quicRstStreamError) {
+  return getKeyWithValue(QuicRstStreamError, quicRstStreamError);
+}
+
+/**
  * Returns a string representation of |family|.
  * @param {number} family An AddressFamily
  * @return {string} A representation of the given family.
diff --git a/chrome/browser/resources/ntp4/app_launcher_promo.png b/chrome/browser/resources/ntp4/app_launcher_promo.png
index 488e17b..79805ed 100644
--- a/chrome/browser/resources/ntp4/app_launcher_promo.png
+++ b/chrome/browser/resources/ntp4/app_launcher_promo.png
Binary files differ
diff --git a/chrome/browser/resources/ntp4/images/2x/app_promo_button.png b/chrome/browser/resources/ntp4/images/2x/app_promo_button.png
index 1439fe7..87a9ac1 100644
--- a/chrome/browser/resources/ntp4/images/2x/app_promo_button.png
+++ b/chrome/browser/resources/ntp4/images/2x/app_promo_button.png
Binary files differ
diff --git a/chrome/browser/resources/ntp4/images/2x/closed_window.png b/chrome/browser/resources/ntp4/images/2x/closed_window.png
index 6e3f93c..ca1fdd8 100644
--- a/chrome/browser/resources/ntp4/images/2x/closed_window.png
+++ b/chrome/browser/resources/ntp4/images/2x/closed_window.png
Binary files differ
diff --git a/chrome/browser/resources/ntp4/images/2x/disclosure_triangle_mask.png b/chrome/browser/resources/ntp4/images/2x/disclosure_triangle_mask.png
index 6b7c478..72b4f2b 100644
--- a/chrome/browser/resources/ntp4/images/2x/disclosure_triangle_mask.png
+++ b/chrome/browser/resources/ntp4/images/2x/disclosure_triangle_mask.png
Binary files differ
diff --git a/chrome/browser/resources/ntp4/images/closed_window.png b/chrome/browser/resources/ntp4/images/closed_window.png
index 04eba16..eab8191 100644
--- a/chrome/browser/resources/ntp4/images/closed_window.png
+++ b/chrome/browser/resources/ntp4/images/closed_window.png
Binary files differ
diff --git a/chrome/browser/resources/ntp4/new_tab.html b/chrome/browser/resources/ntp4/new_tab.html
index 8e81efe..78d921c 100644
--- a/chrome/browser/resources/ntp4/new_tab.html
+++ b/chrome/browser/resources/ntp4/new_tab.html
@@ -96,7 +96,8 @@
   <div id="app-launcher-promo" hidden>
     <div class="apps-promo-text" i18n-content="appsPromoTitle"></div>
     <a href="https://chrome.google.com/webstore/launcher"
-       class="apps-promo-learn-more" i18n-content="learn_more">
+       id="apps-promo-learn-more" class="apps-promo-learn-more"
+       i18n-content="learn_more">
     </a>
     <img src="app_launcher_promo.png">
     <button class="close-button custom-appearance"
diff --git a/chrome/browser/resources/ntp4/new_tab.js b/chrome/browser/resources/ntp4/new_tab.js
index 25643ae..621e044 100644
--- a/chrome/browser/resources/ntp4/new_tab.js
+++ b/chrome/browser/resources/ntp4/new_tab.js
@@ -122,6 +122,8 @@
       if (loadTimeData.getBoolean('showAppLauncherPromo')) {
         $('app-launcher-promo-close-button').addEventListener('click',
             function() { chrome.send('stopShowingAppLauncherPromo'); });
+        $('apps-promo-learn-more').addEventListener('click',
+            function() { chrome.send('onLearnMore'); });
       }
     }
     if (loadTimeData.getBoolean('isDiscoveryInNTPEnabled'))
@@ -244,7 +246,8 @@
 
     var loginContainer = getRequiredElement('login-container');
     loginContainer.addEventListener('click', showSyncLoginUI);
-    chrome.send('initializeSyncLogin');
+    if (loadTimeData.getBoolean('shouldShowSyncLogin'))
+      chrome.send('initializeSyncLogin');
 
     doWhenAllSectionsReady(function() {
       // Tell the slider about the pages.
diff --git a/chrome/browser/resources/ntp_android/OWNERS b/chrome/browser/resources/ntp_android/OWNERS
index d28a429..c7eba94 100644
--- a/chrome/browser/resources/ntp_android/OWNERS
+++ b/chrome/browser/resources/ntp_android/OWNERS
@@ -1,4 +1,2 @@
-jcivelli@chromium.org
-nileshagrawal@chromium.org
 tedchoc@chromium.org
 yfriedman@chromium.org
diff --git a/chrome/browser/resources/ntp_android/images/bookmark_bg_hdpi.png b/chrome/browser/resources/ntp_android/images/bookmark_bg_hdpi.png
index e47df28..cfa6c7b 100644
--- a/chrome/browser/resources/ntp_android/images/bookmark_bg_hdpi.png
+++ b/chrome/browser/resources/ntp_android/images/bookmark_bg_hdpi.png
Binary files differ
diff --git a/chrome/browser/resources/ntp_android/images/bookmark_bg_mdpi.png b/chrome/browser/resources/ntp_android/images/bookmark_bg_mdpi.png
index 382479a..b26489a 100644
--- a/chrome/browser/resources/ntp_android/images/bookmark_bg_mdpi.png
+++ b/chrome/browser/resources/ntp_android/images/bookmark_bg_mdpi.png
Binary files differ
diff --git a/chrome/browser/resources/ntp_android/images/bookmark_bg_tvdpi.png b/chrome/browser/resources/ntp_android/images/bookmark_bg_tvdpi.png
index ad67898..fbd0758 100644
--- a/chrome/browser/resources/ntp_android/images/bookmark_bg_tvdpi.png
+++ b/chrome/browser/resources/ntp_android/images/bookmark_bg_tvdpi.png
Binary files differ
diff --git a/chrome/browser/resources/ntp_android/images/bookmark_bg_xhdpi.png b/chrome/browser/resources/ntp_android/images/bookmark_bg_xhdpi.png
index 3f8d937..a50dbb5 100644
--- a/chrome/browser/resources/ntp_android/images/bookmark_bg_xhdpi.png
+++ b/chrome/browser/resources/ntp_android/images/bookmark_bg_xhdpi.png
Binary files differ
diff --git a/chrome/browser/resources/ntp_android/images/bookmark_border_hdpi.png b/chrome/browser/resources/ntp_android/images/bookmark_border_hdpi.png
index 44fc9ca..6c37481 100644
--- a/chrome/browser/resources/ntp_android/images/bookmark_border_hdpi.png
+++ b/chrome/browser/resources/ntp_android/images/bookmark_border_hdpi.png
Binary files differ
diff --git a/chrome/browser/resources/ntp_android/images/bookmark_border_mdpi.png b/chrome/browser/resources/ntp_android/images/bookmark_border_mdpi.png
index 3381212..3a42c37 100644
--- a/chrome/browser/resources/ntp_android/images/bookmark_border_mdpi.png
+++ b/chrome/browser/resources/ntp_android/images/bookmark_border_mdpi.png
Binary files differ
diff --git a/chrome/browser/resources/ntp_android/images/bookmark_border_tvdpi.png b/chrome/browser/resources/ntp_android/images/bookmark_border_tvdpi.png
index 18a4ca1..175c28c 100644
--- a/chrome/browser/resources/ntp_android/images/bookmark_border_tvdpi.png
+++ b/chrome/browser/resources/ntp_android/images/bookmark_border_tvdpi.png
Binary files differ
diff --git a/chrome/browser/resources/ntp_android/images/bookmark_border_xhdpi.png b/chrome/browser/resources/ntp_android/images/bookmark_border_xhdpi.png
index 62199d9..bf092ef 100644
--- a/chrome/browser/resources/ntp_android/images/bookmark_border_xhdpi.png
+++ b/chrome/browser/resources/ntp_android/images/bookmark_border_xhdpi.png
Binary files differ
diff --git a/chrome/browser/resources/ntp_android/images/bookmark_folder_hdpi.png b/chrome/browser/resources/ntp_android/images/bookmark_folder_hdpi.png
index 1194588..60ed460 100644
--- a/chrome/browser/resources/ntp_android/images/bookmark_folder_hdpi.png
+++ b/chrome/browser/resources/ntp_android/images/bookmark_folder_hdpi.png
Binary files differ
diff --git a/chrome/browser/resources/ntp_android/images/bookmark_folder_mdpi.png b/chrome/browser/resources/ntp_android/images/bookmark_folder_mdpi.png
index 7805a69..d908689 100644
--- a/chrome/browser/resources/ntp_android/images/bookmark_folder_mdpi.png
+++ b/chrome/browser/resources/ntp_android/images/bookmark_folder_mdpi.png
Binary files differ
diff --git a/chrome/browser/resources/ntp_android/images/bookmark_folder_tvdpi.png b/chrome/browser/resources/ntp_android/images/bookmark_folder_tvdpi.png
index 4628b98..1f5d802 100644
--- a/chrome/browser/resources/ntp_android/images/bookmark_folder_tvdpi.png
+++ b/chrome/browser/resources/ntp_android/images/bookmark_folder_tvdpi.png
Binary files differ
diff --git a/chrome/browser/resources/ntp_android/images/bookmark_folder_xhdpi.png b/chrome/browser/resources/ntp_android/images/bookmark_folder_xhdpi.png
index 676bc55..87a8dd3 100644
--- a/chrome/browser/resources/ntp_android/images/bookmark_folder_xhdpi.png
+++ b/chrome/browser/resources/ntp_android/images/bookmark_folder_xhdpi.png
Binary files differ
diff --git a/chrome/browser/resources/ntp_android/images/breadcrumb_hdpi.png b/chrome/browser/resources/ntp_android/images/breadcrumb_hdpi.png
index a75c2e8..faae43a 100644
--- a/chrome/browser/resources/ntp_android/images/breadcrumb_hdpi.png
+++ b/chrome/browser/resources/ntp_android/images/breadcrumb_hdpi.png
Binary files differ
diff --git a/chrome/browser/resources/ntp_android/images/breadcrumb_mdpi.png b/chrome/browser/resources/ntp_android/images/breadcrumb_mdpi.png
index a2c56ca..b9a0305 100644
--- a/chrome/browser/resources/ntp_android/images/breadcrumb_mdpi.png
+++ b/chrome/browser/resources/ntp_android/images/breadcrumb_mdpi.png
Binary files differ
diff --git a/chrome/browser/resources/ntp_android/images/breadcrumb_tvdpi.png b/chrome/browser/resources/ntp_android/images/breadcrumb_tvdpi.png
index 607f2cf..0990077 100644
--- a/chrome/browser/resources/ntp_android/images/breadcrumb_tvdpi.png
+++ b/chrome/browser/resources/ntp_android/images/breadcrumb_tvdpi.png
Binary files differ
diff --git a/chrome/browser/resources/ntp_android/images/breadcrumb_xhdpi.png b/chrome/browser/resources/ntp_android/images/breadcrumb_xhdpi.png
index f698f7e..45edcee 100644
--- a/chrome/browser/resources/ntp_android/images/breadcrumb_xhdpi.png
+++ b/chrome/browser/resources/ntp_android/images/breadcrumb_xhdpi.png
Binary files differ
diff --git a/chrome/browser/resources/ntp_android/images/default_thumbnail.png b/chrome/browser/resources/ntp_android/images/default_thumbnail.png
index 2991999..e2534e0 100644
--- a/chrome/browser/resources/ntp_android/images/default_thumbnail.png
+++ b/chrome/browser/resources/ntp_android/images/default_thumbnail.png
Binary files differ
diff --git a/chrome/browser/resources/ntp_android/images/disclosure_closed_hdpi.png b/chrome/browser/resources/ntp_android/images/disclosure_closed_hdpi.png
index 225a0f3..a0a086a 100644
--- a/chrome/browser/resources/ntp_android/images/disclosure_closed_hdpi.png
+++ b/chrome/browser/resources/ntp_android/images/disclosure_closed_hdpi.png
Binary files differ
diff --git a/chrome/browser/resources/ntp_android/images/disclosure_closed_mdpi.png b/chrome/browser/resources/ntp_android/images/disclosure_closed_mdpi.png
index d2ce368..42e633e 100644
--- a/chrome/browser/resources/ntp_android/images/disclosure_closed_mdpi.png
+++ b/chrome/browser/resources/ntp_android/images/disclosure_closed_mdpi.png
Binary files differ
diff --git a/chrome/browser/resources/ntp_android/images/disclosure_closed_xhdpi.png b/chrome/browser/resources/ntp_android/images/disclosure_closed_xhdpi.png
index 68ba55e..55eab9a 100644
--- a/chrome/browser/resources/ntp_android/images/disclosure_closed_xhdpi.png
+++ b/chrome/browser/resources/ntp_android/images/disclosure_closed_xhdpi.png
Binary files differ
diff --git a/chrome/browser/resources/ntp_android/images/disclosure_open_hdpi.png b/chrome/browser/resources/ntp_android/images/disclosure_open_hdpi.png
index 9f03830..ed5022f 100644
--- a/chrome/browser/resources/ntp_android/images/disclosure_open_hdpi.png
+++ b/chrome/browser/resources/ntp_android/images/disclosure_open_hdpi.png
Binary files differ
diff --git a/chrome/browser/resources/ntp_android/images/disclosure_open_mdpi.png b/chrome/browser/resources/ntp_android/images/disclosure_open_mdpi.png
index 7e33377..b1218a5 100644
--- a/chrome/browser/resources/ntp_android/images/disclosure_open_mdpi.png
+++ b/chrome/browser/resources/ntp_android/images/disclosure_open_mdpi.png
Binary files differ
diff --git a/chrome/browser/resources/ntp_android/images/disclosure_open_xhdpi.png b/chrome/browser/resources/ntp_android/images/disclosure_open_xhdpi.png
index 419ebc4..5a5b56c 100644
--- a/chrome/browser/resources/ntp_android/images/disclosure_open_xhdpi.png
+++ b/chrome/browser/resources/ntp_android/images/disclosure_open_xhdpi.png
Binary files differ
diff --git a/chrome/browser/resources/ntp_android/images/sent_hdpi.png b/chrome/browser/resources/ntp_android/images/sent_hdpi.png
index b9f77e1..4ef1e01 100644
--- a/chrome/browser/resources/ntp_android/images/sent_hdpi.png
+++ b/chrome/browser/resources/ntp_android/images/sent_hdpi.png
Binary files differ
diff --git a/chrome/browser/resources/ntp_android/images/sent_mdpi.png b/chrome/browser/resources/ntp_android/images/sent_mdpi.png
index 351a519..e8631c8 100644
--- a/chrome/browser/resources/ntp_android/images/sent_mdpi.png
+++ b/chrome/browser/resources/ntp_android/images/sent_mdpi.png
Binary files differ
diff --git a/chrome/browser/resources/ntp_android/images/sent_xhdpi.png b/chrome/browser/resources/ntp_android/images/sent_xhdpi.png
index a54a0ec..1f024cb 100644
--- a/chrome/browser/resources/ntp_android/images/sent_xhdpi.png
+++ b/chrome/browser/resources/ntp_android/images/sent_xhdpi.png
Binary files differ
diff --git a/chrome/browser/resources/ntp_android/images/syncfographic_hdpi.png b/chrome/browser/resources/ntp_android/images/syncfographic_hdpi.png
index f54608e..b7f337a 100644
--- a/chrome/browser/resources/ntp_android/images/syncfographic_hdpi.png
+++ b/chrome/browser/resources/ntp_android/images/syncfographic_hdpi.png
Binary files differ
diff --git a/chrome/browser/resources/ntp_android/images/syncfographic_mdpi.png b/chrome/browser/resources/ntp_android/images/syncfographic_mdpi.png
index 580a19c..7bc97e8 100644
--- a/chrome/browser/resources/ntp_android/images/syncfographic_mdpi.png
+++ b/chrome/browser/resources/ntp_android/images/syncfographic_mdpi.png
Binary files differ
diff --git a/chrome/browser/resources/ntp_android/images/syncfographic_sw600dp_hdpi.png b/chrome/browser/resources/ntp_android/images/syncfographic_sw600dp_hdpi.png
index 144fea2..c6c4391 100644
--- a/chrome/browser/resources/ntp_android/images/syncfographic_sw600dp_hdpi.png
+++ b/chrome/browser/resources/ntp_android/images/syncfographic_sw600dp_hdpi.png
Binary files differ
diff --git a/chrome/browser/resources/ntp_android/images/syncfographic_sw600dp_mdpi.png b/chrome/browser/resources/ntp_android/images/syncfographic_sw600dp_mdpi.png
index cc75415..d23a041 100644
--- a/chrome/browser/resources/ntp_android/images/syncfographic_sw600dp_mdpi.png
+++ b/chrome/browser/resources/ntp_android/images/syncfographic_sw600dp_mdpi.png
Binary files differ
diff --git a/chrome/browser/resources/ntp_android/images/syncfographic_sw600dp_xhdpi.png b/chrome/browser/resources/ntp_android/images/syncfographic_sw600dp_xhdpi.png
index 60a8ee4..8ec1bde 100644
--- a/chrome/browser/resources/ntp_android/images/syncfographic_sw600dp_xhdpi.png
+++ b/chrome/browser/resources/ntp_android/images/syncfographic_sw600dp_xhdpi.png
Binary files differ
diff --git a/chrome/browser/resources/ntp_android/images/syncfographic_xhdpi.png b/chrome/browser/resources/ntp_android/images/syncfographic_xhdpi.png
index 51ec233..d6aa146 100644
--- a/chrome/browser/resources/ntp_android/images/syncfographic_xhdpi.png
+++ b/chrome/browser/resources/ntp_android/images/syncfographic_xhdpi.png
Binary files differ
diff --git a/chrome/browser/resources/ntp_android/images/welcome_thumb.png b/chrome/browser/resources/ntp_android/images/welcome_thumb.png
index 7265f13..9997667 100644
--- a/chrome/browser/resources/ntp_android/images/welcome_thumb.png
+++ b/chrome/browser/resources/ntp_android/images/welcome_thumb.png
Binary files differ
diff --git a/chrome/browser/resources/ntp_android/ntp_android.js b/chrome/browser/resources/ntp_android/ntp_android.js
index 4e61603..6fe4548 100644
--- a/chrome/browser/resources/ntp_android/ntp_android.js
+++ b/chrome/browser/resources/ntp_android/ntp_android.js
@@ -373,6 +373,12 @@
 
   function setIncognitoMode(incognito) {
     isIncognito = incognito;
+    if (!isIncognito) {
+      chrome.send('getMostVisited');
+      chrome.send('getRecentlyClosedTabs');
+      chrome.send('getForeignSessions');
+      chrome.send('getPromotions');
+    }
   }
 
   /**
@@ -447,11 +453,6 @@
     // Initialize virtual computers for the sync promo.
     createPromoVirtualComputers();
 
-    chrome.send('getMostVisited');
-    chrome.send('getRecentlyClosedTabs');
-    chrome.send('getForeignSessions');
-    chrome.send('getPromotions');
-
     setCurrentBookmarkFolderData(
         localStorage.getItem(DEFAULT_BOOKMARK_FOLDER_KEY));
 
@@ -707,9 +708,7 @@
       image.onload = function() {
         var w = image.width;
         var h = image.height;
-        var wDip = w / window.devicePixelRatio;
-        var hDip = h / window.devicePixelRatio;
-        if (Math.floor(wDip) <= 16 || Math.floor(hDip) <= 16) {
+        if (Math.floor(w) <= 16 || Math.floor(h) <= 16) {
           // it's a standard favicon (or at least it's small).
           faviconBox.classList.add('document');
 
@@ -740,13 +739,13 @@
         } else {
           // It's an html5 icon (or at least it's larger).
           // Rescale it to be no bigger than 64x64 dip.
-          var maxDip = 64; // DIP
-          if (wDip > maxDip || hDip > maxDip) {
-            var scale = (wDip > hDip) ? (maxDip / wDip) : (maxDip / hDip);
-            wDip *= scale;
-            hDip *= scale;
+          var max = 64;
+          if (w > max || h > max) {
+            var scale = (w > h) ? (max / w) : (max / h);
+            w *= scale;
+            h *= scale;
           }
-          faviconIcon.style.backgroundSize = wDip + 'px ' + hDip + 'px';
+          faviconIcon.style.backgroundSize = w + 'px ' + h + 'px';
         }
       };
       faviconBox.appendChild(faviconIcon);
@@ -1796,6 +1795,9 @@
           // use a section divider.
           var needSectionDivider =
               (tabNum + 1 == tabs.length) && (winNum + 1 < windows.length);
+          tab.icon = tab.icon ||
+            'chrome://session-favicon/size/16@1x/' + tab.url;
+
           openTabsList.push({
             timestamp: tab.timestamp,
             title: tab.title,
@@ -1804,7 +1806,7 @@
             winNum: winNum,
             sessionId: tab.sessionId,
             icon: tab.icon,
-            iconSize: 32,
+            iconSize: 16,
             divider: needSectionDivider ? 'section' : 'standard',
           });
         }
@@ -2202,7 +2204,7 @@
     // 'natural' height and width of the thumbnail
     var thumbHeight = 72;
     var thumbWidth = 108;
-    var labelHeight = 20;
+    var labelHeight = 25;
     var labelWidth = thumbWidth + 20;
     var labelLeft = (thumbWidth - labelWidth) / 2;
     var itemHeight = thumbHeight + labelHeight;
@@ -2214,9 +2216,6 @@
     var itemMarginRight = 20;
 
     var listHeight = 0;
-    // set it to the unscaled size so centerGrid works correctly
-    modifyCssRule('body[device="phone"] .thumbnail-cell',
-        'width', thumbWidth + 'px');
 
     var screenHeight =
         document.documentElement.offsetHeight -
@@ -2225,7 +2224,9 @@
     if (isPortrait()) {
       mostVisitedList.setAttribute(GRID_COLUMNS, '2');
       listHeight = screenHeight * .85;
-      listHeight = listHeight >= 420 ? 420 : listHeight;
+      // Ensure that listHeight is not too small and not too big.
+      listHeight = Math.max(listHeight, (itemHeight * 3) + 20);
+      listHeight = Math.min(listHeight, 420);
       // Size for 3 rows (4 gutters)
       itemMarginTop = (listHeight - (itemHeight * 3)) / 4;
     } else {
@@ -2241,8 +2242,8 @@
         var scale = (screenHeight - 2 * labelHeight -
             targetRemainder) / (2 * thumbHeight);
         // update values based on scale
-        thumbWidth *= scale;
-        thumbHeight *= scale;
+        thumbWidth = Math.round(thumbWidth * scale);
+        thumbHeight = Math.round(thumbHeight * scale);
         labelWidth = thumbWidth + 20;
         itemHeight = thumbHeight + labelHeight;
       }
diff --git a/chrome/browser/resources/options/arrow_next.png b/chrome/browser/resources/options/arrow_next.png
index 2cbf8e6..7d626c0 100644
--- a/chrome/browser/resources/options/arrow_next.png
+++ b/chrome/browser/resources/options/arrow_next.png
Binary files differ
diff --git a/chrome/browser/resources/options/browser_options.html b/chrome/browser/resources/options/browser_options.html
index 19a0c92..d6bfa99 100644
--- a/chrome/browser/resources/options/browser_options.html
+++ b/chrome/browser/resources/options/browser_options.html
@@ -27,18 +27,18 @@
   <section>
     <h3 i18n-content="sectionTitleAppearance"></h3>
     <div class="settings-row">
-      <if expr="pp_ifdef('chromeos')">
+<if expr="pp_ifdef('chromeos')">
       <button id="set-wallpaper" i18n-content="setWallpaper"
           guest-visibility="disabled"></button>
 </if>
-<if expr="not pp_ifdef('toolkit_views') and is_posix and not is_macosx">
+<if expr="not pp_ifdef('chromeos') and is_posix and not is_macosx">
       <button id="themes-gallery" i18n-content="themesGallery"></button>
-      <button id="themes-GTK-button"
-          i18n-content="themesGTKButton"></button>
+      <button id="themes-native-button"
+          i18n-content="themesNativeButton"></button>
       <button id="themes-reset"
           i18n-content="themesSetClassic"></button>
 </if>
-<if expr="pp_ifdef('toolkit_views') or is_win or is_macosx">
+<if expr="pp_ifdef('chromeos') or is_win or is_macosx">
       <button id="themes-gallery" i18n-content="themesGallery"></button>
       <button id="themes-reset" i18n-content="themesReset"></button>
 </if>
@@ -527,7 +527,7 @@
         </span>
       </div>
 <if expr="pp_ifdef('chromeos')">
-      <div class="checkbox" guest-visibility="disabled">
+      <div class="checkbox" id="disable-drive-row" guest-visibility="disabled">
         <span class="controlled-setting-with-label">
           <input id="drive-disabled" type="checkbox"
               pref="gdata.disabled"
@@ -645,22 +645,6 @@
       <div class="option-name">
         <div class="checkbox">
           <span class="controlled-setting-with-label">
-            <input id="accessibility-spoken-feedback-check"
-                pref="settings.accessibility" type="checkbox">
-            <span>
-              <label for="accessibility-spoken-feedback-check"
-                  i18n-content="accessibilitySpokenFeedback">
-              </label>
-              <span class="controlled-setting-indicator"
-                  pref="settings.accessibility">
-              </span>
-            </span>
-          </span>
-        </div>
-      </div>
-      <div class="option-name">
-        <div class="checkbox">
-          <span class="controlled-setting-with-label">
             <input id="accessibility-high-contrast-check"
                 pref="settings.a11y.high_contrast_enabled" type="checkbox">
             <span>
@@ -677,6 +661,22 @@
       <div class="option-name">
         <div class="checkbox">
           <span class="controlled-setting-with-label">
+            <input id="accessibility-spoken-feedback-check"
+                pref="settings.accessibility" type="checkbox">
+            <span>
+              <label for="accessibility-spoken-feedback-check"
+                  i18n-content="accessibilitySpokenFeedback">
+              </label>
+              <span class="controlled-setting-indicator"
+                  pref="settings.accessibility">
+              </span>
+            </span>
+          </span>
+        </div>
+      </div>
+      <div class="option-name">
+        <div class="checkbox">
+          <span class="controlled-setting-with-label">
             <input id="accessibility-screen-magnifier-check"
                 pref="settings.a11y.screen_magnifier" type="checkbox">
             <span>
diff --git a/chrome/browser/resources/options/browser_options.js b/chrome/browser/resources/options/browser_options.js
index 5e4a8fc..ec737b8 100644
--- a/chrome/browser/resources/options/browser_options.js
+++ b/chrome/browser/resources/options/browser_options.js
@@ -148,6 +148,13 @@
         chrome.send('themesReset');
       };
 
+      if (loadTimeData.getBoolean('profileIsManaged')) {
+        if ($('themes-GTK-button'))
+          $('themes-GTK-button').disabled = true;
+        $('themes-reset').disabled = true;
+        $('themes-gallery').disabled = true;
+      }
+
       // Device section (ChromeOS only).
       if (cr.isChromeOS) {
         $('keyboard-settings-button').onclick = function(evt) {
@@ -231,9 +238,9 @@
           chrome.send('coreOptionsUserMetricsAction', ['Import_ShowDlg']);
         };
 
-        if ($('themes-GTK-button')) {
-          $('themes-GTK-button').onclick = function(event) {
-            chrome.send('themesSetGTK');
+        if ($('themes-native-button')) {
+          $('themes-native-button').onclick = function(event) {
+            chrome.send('themesSetNative');
           };
         }
       }
@@ -378,6 +385,9 @@
         $('autoOpenFileTypesResetToDefault').onclick = function(event) {
           chrome.send('autoOpenFileTypesAction');
         };
+      } else {
+        $('disable-drive-row').hidden =
+            UIAccountTweaks.loggedInAsLocallyManagedUser();
       }
 
       // HTTPS/SSL section.
@@ -1072,7 +1082,7 @@
     },
 
     /**
-    * Reports a remote error (e.g., a network error during limited-user
+    * Reports a remote error (e.g., a network error during managed-user
     * registration) to the "create" overlay during profile creation.
     * @private
     */
@@ -1110,9 +1120,10 @@
              'There should always be a current profile, but none found.');
     },
 
-    setGtkThemeButtonEnabled_: function(enabled) {
-      if (!cr.isChromeOS && navigator.platform.match(/linux|BSD/i))
-        $('themes-GTK-button').disabled = !enabled;
+    setNativeThemeButtonEnabled_: function(enabled) {
+      var button = $('themes-native-button');
+      if (button)
+        button.disabled = !enabled;
     },
 
     setThemesResetButtonEnabled_: function(enabled) {
@@ -1461,7 +1472,7 @@
     'setAutoOpenFileTypesDisplayed',
     'setBluetoothState',
     'setFontSize',
-    'setGtkThemeButtonEnabled',
+    'setNativeThemeButtonEnabled',
     'setHighContrastCheckboxState',
     'setMetricsReportingCheckboxState',
     'setMetricsReportingSettingVisibility',
diff --git a/chrome/browser/resources/options/chromeos/2x/warning.png b/chrome/browser/resources/options/chromeos/2x/warning.png
index ac7f050..b28ab36 100644
--- a/chrome/browser/resources/options/chromeos/2x/warning.png
+++ b/chrome/browser/resources/options/chromeos/2x/warning.png
Binary files differ
diff --git a/chrome/browser/resources/options/chromeos/accounts_user_name_edit.js b/chrome/browser/resources/options/chromeos/accounts_user_name_edit.js
index e6e5276..27580e3 100644
--- a/chrome/browser/resources/options/chromeos/accounts_user_name_edit.js
+++ b/chrome/browser/resources/options/chromeos/accounts_user_name_edit.js
@@ -51,7 +51,7 @@
       this.pattern = format1String + '|' + format2String + '|' +
                      format3String;
 
-      this.onkeypress = this.handleKeyPress_.bind(this);
+      this.onkeydown = this.handleKeyDown_.bind(this);
     },
 
 
@@ -104,21 +104,21 @@
     },
 
     /**
-     * Handler for key press event.
+     * Handler for key down event.
      * @private
-     * @param {!Event} e The keypress event object.
+     * @param {!Event} e The keydown event object.
      */
-    handleKeyPress_: function(e) {
-      // Enter
-      if (e.keyCode == 13) {
+    handleKeyDown_: function(e) {
+      if (e.keyIdentifier == 'Enter') {
         var user = this.parse(this.value);
         if (user) {
-          var e = new Event('add');
-          e.user = user;
-          this.dispatchEvent(e);
+          var event = new Event('add');
+          event.user = user;
+          this.dispatchEvent(event);
         }
-
         this.select();
+        // Avoid double-handling so the dialog doesn't close.
+        e.stopPropagation();
       }
     }
   };
diff --git a/chrome/browser/resources/options/chromeos/internet_detail.html b/chrome/browser/resources/options/chromeos/internet_detail.html
index c5287c3..893dbdd 100644
--- a/chrome/browser/resources/options/chromeos/internet_detail.html
+++ b/chrome/browser/resources/options/chromeos/internet_detail.html
@@ -596,8 +596,8 @@
                 </td>
                 <td>
                   <span i18n-content="proxyPort"></span>
-                  <input id="proxy-host-single-port" type="text" data-type="number"
-                      size="4" pref="cros.session.proxy.singlehttpport" disabled>
+                  <input id="proxy-host-single-port" size="4"
+                      pref="cros.session.proxy.singlehttpport" disabled>
                 </td>
               </tr>
             </table>
@@ -616,8 +616,8 @@
                   <span i18n-content="proxyPort"></span>
                 </td>
                 <td>
-                  <input id="proxy-host-port" type="text" data-type="number"
-                       size="4" pref="cros.session.proxy.httpport" disabled>
+                  <input id="proxy-host-port" size="4"
+                      pref="cros.session.proxy.httpport" disabled>
                 </td>
               </tr>
               <tr>
@@ -632,8 +632,8 @@
                   <span i18n-content="proxyPort"></span>
                 </td>
                 <td>
-                  <input id="secure-proxy-port" type="text" data-type="number"
-                       size="4" pref="cros.session.proxy.httpsport" disabled>
+                  <input id="secure-proxy-port" size="4"
+                      pref="cros.session.proxy.httpsport" disabled>
                 </td>
               </tr>
               <tr>
@@ -648,8 +648,8 @@
                   <span i18n-content="proxyPort"></span>
                   </td>
                 <td>
-                  <input id="ftp-proxy-port" type="text" data-type="number"
-                       size="4" pref="cros.session.proxy.ftpport" disabled>
+                  <input id="ftp-proxy-port" size="4"
+                      pref="cros.session.proxy.ftpport" disabled>
                 </td>
               </tr>
               <tr>
@@ -664,7 +664,7 @@
                   <span i18n-content="proxyPort"></span>
                 </td>
                 <td>
-                  <input id="socks-port" type="text" data-type="number" size="4"
+                  <input id="socks-port" size="4"
                       pref="cros.session.proxy.socksport" disabled>
                 </td>
               </tr>
diff --git a/chrome/browser/resources/options/chromeos/internet_detail.js b/chrome/browser/resources/options/chromeos/internet_detail.js
index 6436c5a..4ff8dac 100644
--- a/chrome/browser/resources/options/chromeos/internet_detail.js
+++ b/chrome/browser/resources/options/chromeos/internet_detail.js
@@ -252,6 +252,15 @@
       });
 
       // Proxy
+      ['proxy-host-single-port',
+       'secure-proxy-port',
+       'socks-port',
+       'ftp-proxy-port',
+       'proxy-host-port'
+      ].forEach(function(id) {
+        options.PrefPortNumber.decorate($(id));
+      });
+
       options.proxyexceptions.ProxyExceptions.decorate($('ignored-host-list'));
       $('remove-host').addEventListener('click',
                                         this.handleRemoveProxyExceptions_);
diff --git a/chrome/browser/resources/options/chromeos/overscan_arrows.png b/chrome/browser/resources/options/chromeos/overscan_arrows.png
index 03ad12f..6f3e394 100644
--- a/chrome/browser/resources/options/chromeos/overscan_arrows.png
+++ b/chrome/browser/resources/options/chromeos/overscan_arrows.png
Binary files differ
diff --git a/chrome/browser/resources/options/chromeos/overscan_arrows_2x.png b/chrome/browser/resources/options/chromeos/overscan_arrows_2x.png
index 470c0f0..10171c6 100644
--- a/chrome/browser/resources/options/chromeos/overscan_arrows_2x.png
+++ b/chrome/browser/resources/options/chromeos/overscan_arrows_2x.png
Binary files differ
diff --git a/chrome/browser/resources/options/chromeos/overscan_shift.png b/chrome/browser/resources/options/chromeos/overscan_shift.png
index a5664c8..acdfa07 100644
--- a/chrome/browser/resources/options/chromeos/overscan_shift.png
+++ b/chrome/browser/resources/options/chromeos/overscan_shift.png
Binary files differ
diff --git a/chrome/browser/resources/options/chromeos/overscan_shift_2x.png b/chrome/browser/resources/options/chromeos/overscan_shift_2x.png
index 9391dc7..7d23fdf 100644
--- a/chrome/browser/resources/options/chromeos/overscan_shift_2x.png
+++ b/chrome/browser/resources/options/chromeos/overscan_shift_2x.png
Binary files differ
diff --git a/chrome/browser/resources/options/chromeos/overscan_shift_rtl.png b/chrome/browser/resources/options/chromeos/overscan_shift_rtl.png
index fc2f9ca..0ca89a2 100644
--- a/chrome/browser/resources/options/chromeos/overscan_shift_rtl.png
+++ b/chrome/browser/resources/options/chromeos/overscan_shift_rtl.png
Binary files differ
diff --git a/chrome/browser/resources/options/chromeos/overscan_shift_rtl_2x.png b/chrome/browser/resources/options/chromeos/overscan_shift_rtl_2x.png
index 0e3909f..fb89e2f 100644
--- a/chrome/browser/resources/options/chromeos/overscan_shift_rtl_2x.png
+++ b/chrome/browser/resources/options/chromeos/overscan_shift_rtl_2x.png
Binary files differ
diff --git a/chrome/browser/resources/options/chromeos/warning.png b/chrome/browser/resources/options/chromeos/warning.png
index 18c5821..53713ba 100644
--- a/chrome/browser/resources/options/chromeos/warning.png
+++ b/chrome/browser/resources/options/chromeos/warning.png
Binary files differ
diff --git a/chrome/browser/resources/options/content_settings.js b/chrome/browser/resources/options/content_settings.js
index eeaec37..81f111d 100644
--- a/chrome/browser/resources/options/content_settings.js
+++ b/chrome/browser/resources/options/content_settings.js
@@ -29,8 +29,6 @@
     initializePage: function() {
       OptionsPage.prototype.initializePage.call(this);
 
-      chrome.send('getContentFilterSettings');
-
       var exceptionsButtons =
           this.pageDiv.querySelectorAll('.exceptions-list-button');
       for (var i = 0; i < exceptionsButtons.length; i++) {
diff --git a/chrome/browser/resources/options/language_options.css b/chrome/browser/resources/options/language_options.css
index 6a6eb46..21817c9 100644
--- a/chrome/browser/resources/options/language_options.css
+++ b/chrome/browser/resources/options/language_options.css
@@ -8,7 +8,7 @@
 }
 
 .language-options-lower-left button,
-.language-options-right button {
+#language-options-details button {
   min-width: 70px;
 }
 
@@ -37,22 +37,17 @@
   margin: 10px 0;
 }
 
-.language-options-left,
-.language-options-right {
+#language-options-languages,
+#language-options-details {
   border: 1px solid #ccc;
   height: 400px;
   padding: 0;
   vertical-align: top;
 }
 
-.language-options-left {
+#language-options-languages {
   -webkit-box-orient: vertical;
-<if expr="not is_macosx">
   background-color: rgb(235, 239, 249);
-</if>
-<if expr="is_macosx">
-  background-color: white;
-</if>
   display: -webkit-box;
   width: 300px;
 }
@@ -63,13 +58,13 @@
   padding-bottom: 10px;
 }
 
-.language-options-right {
+#language-options-details {
   /* To share the center line with the left pane. */
   -webkit-margin-start: -1px;
   width: 360px;
 }
 
-.language-options-right h3:not(:first-of-type) {
+#language-options-details h3:not(:first-of-type) {
   margin-top: 24px;
 }
 
@@ -127,6 +122,16 @@
   z-index: 10;
 }
 
+<if expr="is_macosx">
+.language-options[enabled='false'] #language-options-details {
+  display: none;
+}
+
+.language-options[enabled='false'] #language-options-languages {
+  background-color: transparent !important;
+}
+</if>
+
 /* TODO(kochi): This is temporary copy from new_tab.css */
 /* Notification */
 
diff --git a/chrome/browser/resources/options/language_options.html b/chrome/browser/resources/options/language_options.html
index 9a95eab..b9d77c4 100644
--- a/chrome/browser/resources/options/language_options.html
+++ b/chrome/browser/resources/options/language_options.html
@@ -12,8 +12,8 @@
       <div i18n-content="inputMethodInstructions"></div>
 </if>
     </div>
-    <div class="language-options">
-      <div class="language-options-left">
+    <div class="language-options" i18n-values="enabled:enableTranslateSettings">
+      <div id="language-options-languages">
         <h3 i18n-content="languages"></h3>
         <list id="language-options-list"></list>
         <div class="language-options-lower-left">
@@ -23,7 +23,7 @@
         </div>
         <div id="language-options-list-dropmarker"></div>
       </div>
-      <div class="language-options-right">
+      <div id="language-options-details">
         <h3 id="language-options-language-name"></h3>
 <if expr="os == 'win32' or pp_ifdef('chromeos')">
         <div class="language-options-contents">
diff --git a/chrome/browser/resources/options/language_options.js b/chrome/browser/resources/options/language_options.js
index de7e6a1..5250ced 100644
--- a/chrome/browser/resources/options/language_options.js
+++ b/chrome/browser/resources/options/language_options.js
@@ -58,7 +58,7 @@
    * @type {string}
    * @const
    */
-  var TRANSLATE_LANGUAGE_BLACKLIST_PREF = 'translate_language_blacklist';
+  var TRANSLATE_BLOCKED_LANGUAGES_PREF = 'translate_blocked_languages';
 
   /**
    * The preference key that is a string that describes the spell check
@@ -127,7 +127,7 @@
      * @type {Array}
      * @private
      */
-    translateLanguageBlacklist_: [],
+    translateBlockedLanguages_: [],
 
     /**
      * The list of the languages supported by Translate server
@@ -186,8 +186,8 @@
           this.handleDontTranslateCheckboxClick_.bind(this));
 
       Preferences.getInstance().addEventListener(
-          TRANSLATE_LANGUAGE_BLACKLIST_PREF,
-          this.handleTranslateLanguageBlacklistPrefChange_.bind(this));
+          TRANSLATE_BLOCKED_LANGUAGES_PREF,
+          this.handleTranslateBlockedLanguagesPrefChange_.bind(this));
       Preferences.getInstance().addEventListener(SPELL_CHECK_DICTIONARY_PREF,
           this.handleSpellCheckDictionaryPrefChange_.bind(this));
       this.translateSupportedLanguages_ =
@@ -201,10 +201,11 @@
         if (match) {
           var addLanguageCode = match[1];
           $('language-options-list').addLanguage(addLanguageCode);
+          this.addBlockedLanguage_(addLanguageCode);
         } else {
           OptionsPage.navigateToPage('addLanguage');
         }
-      };
+      }.bind(this);
 
       if (!cr.isMac) {
         // Set up the button for editing custom spelling dictionary.
@@ -366,6 +367,42 @@
     },
 
     /**
+     * Adds a language to the preference 'translate_blocked_languages'. If
+     * |langCode| is already added, nothing happens. |langCode| is converted
+     * to a Translate language synonym before added.
+     * @param {string} langCode A language code like 'en'
+     * @private
+     */
+    addBlockedLanguage_: function(langCode) {
+      langCode = this.convertLangCodeForTranslation_(langCode);
+      if (this.translateBlockedLanguages_.indexOf(langCode) == -1) {
+        this.translateBlockedLanguages_.push(langCode);
+        Preferences.setListPref(TRANSLATE_BLOCKED_LANGUAGES_PREF,
+                                this.translateBlockedLanguages_, true);
+      }
+    },
+
+    /**
+     * Removes a language from the preference 'translate_blocked_languages'.
+     * If |langCode| doesn't exist in the preference, nothing happens.
+     * |langCode| is converted to a Translate language synonym before removed.
+     * @param {string} langCode A language code like 'en'
+     * @private
+     */
+    removeBlockedLanguage_: function(langCode) {
+      langCode = this.convertLangCodeForTranslation_(langCode);
+      if (this.translateBlockedLanguages_.indexOf(langCode) != -1) {
+        this.translateBlockedLanguages_ =
+            this.translateBlockedLanguages_.filter(
+                function(langCodeNotTranslated) {
+                  return langCodeNotTranslated != langCode;
+                });
+        Preferences.setListPref(TRANSLATE_BLOCKED_LANGUAGES_PREF,
+                                this.translateBlockedLanguages_, true);
+      }
+    },
+
+    /**
      * Handles OptionsPage's visible property change event.
      * @param {Event} e Property change event.
      * @private
@@ -670,8 +707,22 @@
       }
 
       var checkbox = $('dont-translate-in-this-language');
-      var blacklist = this.translateLanguageBlacklist_;
-      var checked = blacklist.indexOf(convertedLangCode) != -1;
+
+      // If the language corresponds to the default target language (in most
+      // cases, the user's locale language), "Don't Translate" checkbox should
+      // be always checked.
+      var defaultTargetLanguage =
+          loadTimeData.getString('defaultTargetLanguage');
+      if (convertedLangCode == defaultTargetLanguage) {
+        checkbox.disabled = true;
+        checkbox.checked = true;
+        return;
+      }
+
+      checkbox.disabled = false;
+
+      var blockedLanguages = this.translateBlockedLanguages_;
+      var checked = blockedLanguages.indexOf(convertedLangCode) != -1;
       checkbox.checked = checked;
     },
 
@@ -781,19 +832,10 @@
       var languageOptionsList = $('language-options-list');
       var selectedLanguageCode = languageOptionsList.getSelectedLanguageCode();
 
-      var langCode = this.convertLangCodeForTranslation_(selectedLanguageCode);
-      var blacklist = this.translateLanguageBlacklist_;
-      if (checked && blacklist.indexOf(langCode) == -1) {
-        blacklist.push(langCode);
-      } else if (!checked && blacklist.indexOf(langCode) != -1) {
-        blacklist = blacklist.filter(function(blacklistedLangCode) {
-          return blacklistedLangCode != langCode;
-        });
-      }
-      this.translateLanguageBlacklist_ = blacklist;
-
-      Preferences.setListPref(TRANSLATE_LANGUAGE_BLACKLIST_PREF,
-                              this.translateLanguageBlacklist_, true);
+      if (checked)
+        this.addBlockedLanguage_(selectedLanguageCode);
+      else
+        this.removeBlockedLanguage_(selectedLanguageCode);
     },
 
     /**
@@ -832,7 +874,9 @@
       var selectedIndex = languagesSelect.selectedIndex;
       if (selectedIndex >= 0) {
         var selection = languagesSelect.options[selectedIndex];
-        $('language-options-list').addLanguage(String(selection.value));
+        var langCode = String(selection.value);
+        $('language-options-list').addLanguage(langCode);
+        this.addBlockedLanguage_(langCode);
         OptionsPage.closeOverlay();
       }
     },
@@ -862,15 +906,14 @@
      },
 
     /**
-     * Handles translateLanguageBlacklistPref change.
+     * Handles translateBlockedLanguagesPref change.
      * @param {Event} e Change event.
      * @private
      */
-    handleTranslateLanguageBlacklistPrefChange_: function(e) {
+    handleTranslateBlockedLanguagesPrefChange_: function(e) {
       var languageOptionsList = $('language-options-list');
       var selectedLanguageCode = languageOptionsList.getSelectedLanguageCode();
-      this.translateLanguageBlacklist_ = e.value.value;
-
+      this.translateBlockedLanguages_ = e.value.value;
       this.updateDontTranslateCheckbox_(selectedLanguageCode);
     },
 
diff --git a/chrome/browser/resources/options/manage_profile_overlay.css b/chrome/browser/resources/options/manage_profile_overlay.css
index 9596ba3..5b5f093 100644
--- a/chrome/browser/resources/options/manage_profile_overlay.css
+++ b/chrome/browser/resources/options/manage_profile_overlay.css
@@ -102,20 +102,25 @@
   -webkit-margin-end: 10px;
 }
 
-#delete-profile-message {
+#delete-profile-message,
+#delete-managed-profile-addendum {
   -webkit-padding-start: 48px;
   background-repeat: no-repeat;
 }
 
+#delete-managed-profile-addendum {
+  margin-top: 10px;
+}
+
 html[dir='rtl'] #delete-profile-message {
   background-position: right;
 }
 
-#create-profile-limited-not-signed-in {
+#create-profile-managed-not-signed-in {
   color: #999;
 }
 
-#create-profile-limited-not-signed-in-label {
+#create-profile-managed-not-signed-in-label {
   white-space: pre-wrap;
   word-wrap: break-word;
 }
diff --git a/chrome/browser/resources/options/manage_profile_overlay.html b/chrome/browser/resources/options/manage_profile_overlay.html
index f4acc97..39cf3f6 100644
--- a/chrome/browser/resources/options/manage_profile_overlay.html
+++ b/chrome/browser/resources/options/manage_profile_overlay.html
@@ -39,6 +39,9 @@
     <h1 i18n-content="deleteProfileTitle"></h1>
     <div class="content-area">
       <div id="delete-profile-message"></div>
+      <div id="delete-managed-profile-addendum"
+          i18n-values=".innerHTML:deleteManagedProfileAddendum" hidden>
+      </div>
     </div>
     <div class="action-area button-strip">
       <button id="delete-profile-cancel" i18n-content="cancel"></button>
@@ -71,25 +74,28 @@
           </span>
         </label>
       </div>
-      <div id="create-profile-limited-container" class="checkbox" hidden>
+      <div id="create-profile-managed-container" class="checkbox" hidden>
         <label>
-          <input id="create-profile-limited" type="checkbox">
-          <span id="create-profile-limited-signed-in">
-            <span id="create-profile-limited-signed-in-label"></span>
-            <button id="create-profile-limited-signed-in-link"
+          <input id="create-profile-managed" type="checkbox">
+          <span id="create-profile-managed-signed-in">
+            <span id="create-profile-managed-signed-in-label"></span>
+            <button id="create-profile-managed-signed-in-link"
                 class="link-button" i18n-content="learnMore">
             </button>
           </span>
-          <span id="create-profile-limited-not-signed-in" hidden>
-            <span id="create-profile-limited-not-signed-in-label"
-                i18n-content="manageProfilesLimitedNotSignedInLabel">
+          <span id="create-profile-managed-not-signed-in" hidden>
+            <span id="create-profile-managed-not-signed-in-label"
+                i18n-content="manageProfilesManagedNotSignedInLabel">
             </span>
-            <button id="create-profile-limited-not-signed-in-link"
+            <button id="create-profile-managed-not-signed-in-link"
                 class="link-button"
-                i18n-content="manageProfilesLimitedNotSignedInLink">
+                i18n-content="manageProfilesManagedNotSignedInLink">
             </button>
           </span>
         </label>
+        <span id="create-profile-managed-indicator"
+            class="bubble-button controlled-setting-indicator">
+        </span>
       </div>
     </div>
     <div class="action-area">
diff --git a/chrome/browser/resources/options/manage_profile_overlay.js b/chrome/browser/resources/options/manage_profile_overlay.js
index b3b83d4..d27a979 100644
--- a/chrome/browser/resources/options/manage_profile_overlay.js
+++ b/chrome/browser/resources/options/manage_profile_overlay.js
@@ -59,8 +59,9 @@
       };
 
       if (loadTimeData.getBoolean('managedUsersEnabled')) {
-        $('create-profile-limited-container').hidden = false;
+        $('create-profile-managed-container').hidden = false;
       }
+
       $('manage-profile-cancel').onclick =
           $('delete-profile-cancel').onclick = function(event) {
         OptionsPage.closeOverlay();
@@ -76,12 +77,12 @@
         chrome.send('removeProfileShortcut', [self.profileInfo_.filePath]);
       };
 
-      $('create-profile-limited-signed-in-link').onclick = function(event) {
+      $('create-profile-managed-signed-in-link').onclick = function(event) {
         OptionsPage.navigateToPage('managedUserLearnMore');
         return false;
       };
 
-      $('create-profile-limited-not-signed-in-link').onclick = function(event) {
+      $('create-profile-managed-not-signed-in-link').onclick = function(event) {
         // The signin process will open an overlay to configure sync, which
         // would replace this overlay. It's smoother to close this one now.
         // TODO(pamg): Move the sync-setup overlay to a higher layer so this one
@@ -143,8 +144,9 @@
      *     profileInfo = {
      *       name: "Profile Name",
      *       iconURL: "chrome://path/to/icon/image",
-     *       filePath: "/path/to/profile/data/on/disk"
+     *       filePath: "/path/to/profile/data/on/disk",
      *       isCurrentProfile: false,
+     *       isManaged: false
      *     };
      * @param {string} mode A label that specifies the type of dialog
      *     box which is currently being viewed (i.e. 'create' or
@@ -308,7 +310,7 @@
       var name = $('create-profile-name').value;
       var iconUrl = $('create-profile-icon-grid').selectedItem;
       var createShortcut = $('create-shortcut').checked;
-      var isManaged = $('create-profile-limited').checked;
+      var isManaged = $('create-profile-managed').checked;
 
       // 'createProfile' is handled by the BrowserOptionsHandler.
       chrome.send('createProfile',
@@ -370,6 +372,7 @@
           loadTimeData.getStringF('deleteProfileMessage', profileInfo.name);
       $('delete-profile-message').style.backgroundImage = 'url("' +
           profileInfo.iconURL + '")';
+      $('delete-managed-profile-addendum').hidden = !profileInfo.isManaged;
 
       // Because this dialog isn't useful when refreshing or as part of the
       // history, don't create a history entry for it when showing.
@@ -415,12 +418,16 @@
     // Inherit from ManageProfileOverlay.
     __proto__: ManageProfileOverlay.prototype,
 
+    // The signed-in email address of the current profile, or empty if they're
+    // not signed in.
+    signedInEmail_: '',
+
     /**
      * Configures the overlay to the "create user" mode.
      * @override
      */
     didShowPage: function() {
-      chrome.send('requestSignedInText');
+      chrome.send('requestCreateProfileUpdate');
       chrome.send('requestDefaultProfileIcons');
       chrome.send('requestNewProfileDefaults');
 
@@ -439,6 +446,9 @@
       $('create-profile-name-label').hidden = true;
       $('create-profile-name').hidden = true;
       $('create-profile-ok').disabled = true;
+      $('create-profile-managed-signed-in').disabled = true;
+      $('create-profile-managed-signed-in').hidden = true;
+      $('create-profile-managed-not-signed-in').hidden = true;
     },
 
     /** @override */
@@ -470,7 +480,7 @@
       $('create-profile-icon-grid').disabled = inProgress;
       $('create-profile-name').disabled = inProgress;
       $('create-shortcut').disabled = inProgress;
-      $('create-profile-limited').disabled = inProgress;
+      $('create-profile-managed').disabled = inProgress;
       $('create-profile-ok').disabled = inProgress;
 
       $('create-profile-throbber').hidden = !inProgress;
@@ -511,7 +521,7 @@
     },
 
     /**
-     * For new limited users, shows a confirmation page after successfully
+     * For new supervised users, shows a confirmation page after successfully
      * creating a new profile; otherwise, the handler will open a new window.
      * @param {Object} profileInfo An object of the form:
      *     profileInfo = {
@@ -525,6 +535,7 @@
       this.updateCreateInProgress_(false);
       OptionsPage.closeOverlay();
       if (profileInfo.isManaged) {
+        profileInfo.custodianEmail = this.signedInEmail_;
         ManagedUserCreateConfirmOverlay.setProfileInfo(profileInfo);
         OptionsPage.navigateToPage('managedUserCreateConfirm');
       }
@@ -532,20 +543,47 @@
 
     /**
      * Updates the signed-in or not-signed-in UI when in create mode. Called by
-     * the handler in response to the 'requestSignedInText' message.
-     * @param {string} text The text to show for a signed-in user. An empty
-     *     string indicates that the user is not signed in.
+     * the handler in response to the 'requestCreateProfileUpdate' message.
+     * @param {string} email The email address of the currently signed-in user.
+     *     An empty string indicates that the user is not signed in.
      * @private
      */
-    updateSignedInStatus_: function(text) {
-      var isSignedIn = text !== '';
-      $('create-profile-limited-signed-in').hidden = !isSignedIn;
-      $('create-profile-limited-not-signed-in').hidden = isSignedIn;
-      $('create-profile-limited').disabled = !isSignedIn;
-      if (!isSignedIn)
-        $('create-profile-limited').checked = false;
+    updateSignedInStatus_: function(email) {
+      this.signedInEmail_ = email;
+      var isSignedIn = email !== '';
+      $('create-profile-managed-signed-in').hidden = !isSignedIn;
+      $('create-profile-managed-not-signed-in').hidden = isSignedIn;
 
-      $('create-profile-limited-signed-in-label').textContent = text;
+      if (isSignedIn) {
+        $('create-profile-managed-signed-in-label').textContent =
+            loadTimeData.getStringF(
+                'manageProfilesManagedSignedInLabel', email);
+      } else {
+        $('create-profile-managed').checked = false;
+      }
+    },
+
+    /**
+     * Updates the status of the "create managed user" checkbox. Called by the
+     * handler in response to the 'requestCreateProfileUpdate' message or a
+     * change in the (policy-controlled) pref that prohibits creating managed
+     * users, after the signed-in status has been updated.
+     * @param {boolean} allowed True if creating managed users should be
+     *     allowed.
+     * @private
+     */
+    updateManagedUsersAllowed_: function(allowed) {
+      var isSignedIn = this.signedInEmail_ !== '';
+      $('create-profile-managed').disabled = !isSignedIn || !allowed;
+
+      $('create-profile-managed-not-signed-in-link').hidden = !allowed;
+      if (!allowed) {
+        $('create-profile-managed').checked = false;
+        $('create-profile-managed-indicator').setAttribute('controlled-by',
+                                                           'policy');
+      } else {
+        $('create-profile-managed-indicator').removeAttribute('controlled-by');
+      }
     },
   };
 
@@ -556,6 +594,7 @@
     'onRemoteError',
     'onSuccess',
     'updateCreateInProgress',
+    'updateManagedUsersAllowed',
     'updateSignedInStatus',
   ].forEach(function(name) {
     CreateProfileOverlay[name] = function() {
diff --git a/chrome/browser/resources/options/managed_user.png b/chrome/browser/resources/options/managed_user.png
index 1c3446a..e84d850 100644
--- a/chrome/browser/resources/options/managed_user.png
+++ b/chrome/browser/resources/options/managed_user.png
Binary files differ
diff --git a/chrome/browser/resources/options/managed_user_create_confirm.css b/chrome/browser/resources/options/managed_user_create_confirm.css
index 425b103..718d346 100644
--- a/chrome/browser/resources/options/managed_user_create_confirm.css
+++ b/chrome/browser/resources/options/managed_user_create_confirm.css
@@ -3,110 +3,18 @@
  * found in the LICENSE file. */
 
 #managed-user-created {
-  width: 612px;
+  width: 722px;
 }
 
-/* Carousel slides. The way the carousel works is by looking at the currently
- * selected radio box, which tells us which slide is visible now. */
+#managed-user-created-image {
+  background-image: -webkit-image-set(
+      url('../../../../ui/resources/default_100_percent/supervised_illustration_done.png') 1x,
+      url('../../../../ui/resources/default_200_percent/supervised_illustration_done.png') 2x);
+  height: 344px;
+}
 
-.managed-user-created-slide-text {
+#managed-user-created-text {
   margin-top: 10px;
   white-space: pre-wrap;
   word-wrap: break-word;
 }
-
-.managed-user-created-slide-image {
-  height: 177px;  /* Placeholder value */
-}
-
-.managed-user-created-slide:nth-child(1) .managed-user-created-slide-image {
-  background-image: url('managed_user_create_confirm_1.png');
-}
-
-.managed-user-created-slide:nth-child(2) .managed-user-created-slide-image {
-  background-image: url('managed_user_create_confirm_2.png');
-}
-
-.managed-user-created-slide:nth-child(3) .managed-user-created-slide-image {
-  background-image: url('managed_user_create_confirm_3.png');
-}
-
-/* Need to be adjusted to the number of slides. */
-#managed-user-created-slide-deck {
-  /* Number of slides multiplied by 100%. */
-  width: 300%;
-}
-
-#managed-user-created-slide-deck .managed-user-created-slide {
-  float: left;
-  /* 100% divided by number of slides. */
-  width: 33.334%;
-}
-
-#managed-user-created-viewport {
-  overflow: hidden;
-  width: 100%;
-}
-
-html[dir='rtl'] #managed-user-created-slide-deck .managed-user-created-slide {
-  float: right;
-}
-
-.content-area #managed-user-created-slide-deck {
-  -webkit-transition: all 750ms cubic-bezier(0.75, 0.00, 0.25, 1.00);
-}
-
-/* The small circular buttons/indicators. They are labels for the radio boxes
- * that control the slides, so clicking them will actually check the proper
- * radio box for that slide and change the slide. */
-
-#managed-user-created-small-buttons {
-  -webkit-box-flex: 1;
-  -webkit-margin-start: 274px;
-}
-
-#managed-user-created-small-buttons button {
-  background: rgb(186, 186, 186);
-  border-radius: 4px;
-  border-width: 0;
-  display: inline-block;
-  min-height: 8px;
-  min-width: 8px;
-  padding: 0;
-}
-
-#managed-user-created-small-buttons
-    .managed-user-created-small-button-selected {
-  background: rgb(67, 67, 67);
-}
-
-/* Next and previous arrows. */
-
-#managed-user-created-slide-arrows {
-  height: 30px;
-  position: absolute;
-  /* Needs to be adjusted according to the slide image size. */
-  top: 122px;
-  width: 100%;
-}
-
-#managed-user-created-slide-arrows button {
-  border-radius: 15px;
-  border-width: 0;
-  box-shadow: none;
-  height: 30px;
-  min-height: 30px;
-  min-width: 30px;
-  width: 30px;
-}
-
-#managed-user-created-left-slide-arrow {
-  -webkit-transform: scaleX(-1);
-  background: url('arrow_next.png') no-repeat center, white;
-  float: left;
-}
-
-#managed-user-created-right-slide-arrow {
-  background: url('arrow_next.png') no-repeat center, white;
-  float: right;
-}
diff --git a/chrome/browser/resources/options/managed_user_create_confirm.html b/chrome/browser/resources/options/managed_user_create_confirm.html
index e7fdd1f..c7c9b90 100644
--- a/chrome/browser/resources/options/managed_user_create_confirm.html
+++ b/chrome/browser/resources/options/managed_user_create_confirm.html
@@ -1,40 +1,14 @@
 <div id="managed-user-created" class="page" hidden>
   <div class="close-button"></div>
-  <!-- Overlay for the confirmation after creating a limited user. -->
+  <!-- Overlay for the confirmation after creating a supervised user. -->
   <h1 id="managed-user-created-title"></h1>
   <div class="content-area">
-    <div id="managed-user-created-viewport">
-      <div id="managed-user-created-slide-deck">
-        <div class="managed-user-created-slide">
-          <div class="managed-user-created-slide-image"></div>
-          <div class="managed-user-created-slide-text"
-              i18n-values=".innerHTML:managedUserCreateConfirmTextSlide1">
-          </div>
-        </div>
-        <div class="managed-user-created-slide">
-          <div class="managed-user-created-slide-image"></div>
-          <div class="managed-user-created-slide-text"
-              i18n-values=".innerHTML:managedUserCreateConfirmTextSlide2">
-          </div>
-        </div>
-        <div class="managed-user-created-slide">
-          <div class="managed-user-created-slide-image"></div>
-          <div class="managed-user-created-slide-text"
-              i18n-values=".innerHTML:managedUserCreateConfirmTextSlide3">
-          </div>
-        </div>
-      </div>
-    </div>
-  </div>
-  <div id="managed-user-created-slide-arrows">
-    <button id="managed-user-created-left-slide-arrow"></button>
-    <button id="managed-user-created-right-slide-arrow"></button>
+    <div id="managed-user-created-image"></div>
+    <div id="managed-user-created-text"></div>
   </div>
   <div class="action-area button-strip">
-    <div id="managed-user-created-small-buttons">
-    </div>
     <button id="managed-user-created-done"
-        i18n-content="managedUserCreateConfirmDone">
+        i18n-content="managedUserCreatedDone">
     </button>
     <button id="managed-user-created-switch"></button>
   </div>
diff --git a/chrome/browser/resources/options/managed_user_create_confirm.js b/chrome/browser/resources/options/managed_user_create_confirm.js
index 77374d4..88e4701 100644
--- a/chrome/browser/resources/options/managed_user_create_confirm.js
+++ b/chrome/browser/resources/options/managed_user_create_confirm.js
@@ -27,9 +27,6 @@
     // Info about the newly created profile.
     profileInfo_: null,
 
-    // Current shown slide.
-    currentSlide_: 0,
-
     /**
      * Initialize the page.
      */
@@ -46,80 +43,6 @@
         OptionsPage.closeOverlay();
         chrome.send('switchToProfile', [self.profileInfo_.filePath]);
       };
-
-      // Create a small dot button for each slide in the deck and make the
-      // first button active.
-      var numberOfSlides = $('managed-user-created-slide-deck').children.length;
-      for (var i = 0; i < numberOfSlides; i++) {
-        var smallButton = document.createElement('button');
-        $('managed-user-created-small-buttons').appendChild(smallButton);
-        smallButton.onclick = this.setCurrentSlide_.bind(this, i);
-      }
-      $('managed-user-created-small-buttons').children[0].classList.add(
-          'managed-user-created-small-button-selected');
-
-      // Changes the slide in |direction|, where |direction| can be 'Left' or
-      // 'Right'. Changing to the left goes back in LTR and forward in RTL and
-      // vice versa for right.
-      function changeSlide(direction) {
-        // Ignore all events we get while not visible.
-        if (!self.visible)
-          return;
-
-        // Ignore anything other than left and right arrow press.
-        if (direction != 'Left' && direction != 'Right')
-          return;
-
-        var container = $('managed-user-created');
-        var rtl = getComputedStyle(container).direction == 'rtl';
-
-        if ((direction == 'Right' && !rtl) || (direction == 'Left' && rtl))
-          self.setCurrentSlide_(self.currentSlide_ + 1);
-        else
-          self.setCurrentSlide_(self.currentSlide_ - 1);
-      };
-
-      $('managed-user-created-left-slide-arrow').onclick =
-          changeSlide.bind(undefined, 'Left');
-      $('managed-user-created-right-slide-arrow').onclick =
-          changeSlide.bind(undefined, 'Right');
-
-      document.onkeydown = function(event) {
-        changeSlide(event.keyIdentifier);
-      };
-    },
-
-    /**
-     * Reset to slide 1 for the next time this gets opened.
-     * @override
-     */
-    didShowPage: function() {
-      this.setCurrentSlide_(0);
-    },
-
-    /**
-     * Sets the current visible slide to |slide|, where |slide| is the index
-     * and starts from 0.
-     * @param {number} slide The slide to set.
-     * @private
-     */
-    setCurrentSlide_: function(slide) {
-      var numberOfSlides =
-          $('managed-user-created-slide-deck').children.length;
-      var newSlide = (numberOfSlides + slide) % numberOfSlides;
-      // Show the respective slide. The slide is shown by setting the
-      // appropriate negative margin on the slide deck.
-      var margin = '0';
-      if (slide != 0)
-        margin = '-' + newSlide * 100 + '%';
-      $('managed-user-created-slide-deck').style.webkitMarginStart = margin;
-
-      // Update the bottom buttons.
-      $('managed-user-created-small-buttons').children[this.currentSlide_]
-          .classList.toggle('managed-user-created-small-button-selected');
-      $('managed-user-created-small-buttons').children[newSlide]
-          .classList.toggle('managed-user-created-small-button-selected');
-      this.currentSlide_ = newSlide;
     },
 
     /**
@@ -129,17 +52,34 @@
      * @param {Object} info An object of the form:
      *     info = {
      *       name: "Profile Name",
-     *       filePath: "/path/to/profile/data/on/disk"
-     *       isManaged: (true|false),
+     *       filePath: "/path/to/profile/data/on/disk",
+     *       isManaged: (true|false)
+     *       custodianEmail: "example@gmail.com"
      *     };
      * @private
      */
     setProfileInfo_: function(info) {
+      function HTMLEscape(original) {
+        return original.replace(/&/g, '&amp;')
+                       .replace(/</g, '&lt;')
+                       .replace(/>/g, '&gt;')
+                       .replace(/"/g, '&quot;')
+                       .replace(/'/g, '&#39;');
+      }
+
       this.profileInfo_ = info;
       $('managed-user-created-title').textContent =
-          loadTimeData.getStringF('managedUserCreateConfirmTitle', info.name);
+          loadTimeData.getStringF('managedUserCreatedTitle', info.name);
       $('managed-user-created-switch').textContent =
-          loadTimeData.getStringF('managedUserCreateConfirmSwitch', info.name);
+          loadTimeData.getStringF('managedUserCreatedSwitch', info.name);
+
+      // HTML-escape the user-supplied strings before putting them into
+      // innerHTML. This is probably excessive for the email address, but
+      // belt-and-suspenders is cheap here.
+      $('managed-user-created-text').innerHTML =
+          loadTimeData.getStringF('managedUserCreatedText',
+                                  HTMLEscape(info.name),
+                                  HTMLEscape(info.custodianEmail));
     },
   };
 
diff --git a/chrome/browser/resources/options/managed_user_create_confirm.png b/chrome/browser/resources/options/managed_user_create_confirm.png
new file mode 100644
index 0000000..58c2331
--- /dev/null
+++ b/chrome/browser/resources/options/managed_user_create_confirm.png
Binary files differ
diff --git a/chrome/browser/resources/options/managed_user_create_confirm_1.png b/chrome/browser/resources/options/managed_user_create_confirm_1.png
deleted file mode 100644
index 7f40e88..0000000
--- a/chrome/browser/resources/options/managed_user_create_confirm_1.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/options/managed_user_create_confirm_2.png b/chrome/browser/resources/options/managed_user_create_confirm_2.png
deleted file mode 100644
index e230ba4..0000000
--- a/chrome/browser/resources/options/managed_user_create_confirm_2.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/options/managed_user_create_confirm_3.png b/chrome/browser/resources/options/managed_user_create_confirm_3.png
deleted file mode 100644
index 4bdbeec..0000000
--- a/chrome/browser/resources/options/managed_user_create_confirm_3.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/options/managed_user_learn_more.css b/chrome/browser/resources/options/managed_user_learn_more.css
index 6811487..79878ee 100644
--- a/chrome/browser/resources/options/managed_user_learn_more.css
+++ b/chrome/browser/resources/options/managed_user_learn_more.css
@@ -3,7 +3,7 @@
  * found in the LICENSE file. */
 
 #managed-user-learn-more {
-  width: 612px;
+  width: 722px;
 }
 
 #managed-user-learn-more-text {
@@ -13,6 +13,8 @@
 }
 
 #managed-user-learn-more-image {
-  background-image: url('managed_user_learn_more.png');
-  height: 177px;  /* Placeholder value */
+  background-image: -webkit-image-set(
+      url('../../../../ui/resources/default_100_percent/supervised_illustration_start.png') 1x,
+      url('../../../../ui/resources/default_200_percent/supervised_illustration_start.png') 2x);
+  height: 344px;
 }
diff --git a/chrome/browser/resources/options/managed_user_learn_more.html b/chrome/browser/resources/options/managed_user_learn_more.html
index f7cabe6..e0b2c62 100644
--- a/chrome/browser/resources/options/managed_user_learn_more.html
+++ b/chrome/browser/resources/options/managed_user_learn_more.html
@@ -1,6 +1,6 @@
 <div id="managed-user-learn-more" class="page" hidden>
   <div class="close-button"></div>
-  <!-- Overlay for the 'Learn more' link when creating a limited user. -->
+  <!-- Overlay for the 'Learn more' link when creating a supervised user. -->
   <h1 i18n-content="managedUserLearnMoreTitle"></h1>
   <div class="content-area">
     <div id="managed-user-learn-more-image"></div>
diff --git a/chrome/browser/resources/options/managed_user_learn_more.png b/chrome/browser/resources/options/managed_user_learn_more.png
index 4588ef5..8adc52a 100644
--- a/chrome/browser/resources/options/managed_user_learn_more.png
+++ b/chrome/browser/resources/options/managed_user_learn_more.png
Binary files differ
diff --git a/chrome/browser/resources/options/password_manager.html b/chrome/browser/resources/options/password_manager.html
index 9eae961..dfecba6 100644
--- a/chrome/browser/resources/options/password_manager.html
+++ b/chrome/browser/resources/options/password_manager.html
@@ -29,9 +29,7 @@
   </div>
   <div class="action-area">
     <div class="button-strip">
-        <button id="password-manager-confirm" class="default-button"
-            i18n-content="done">
-        </button>
+      <button id="password-manager-confirm" i18n-content="done"></button>
     </div>
   </div>
 </div>
diff --git a/chrome/browser/resources/options/pref_ui.js b/chrome/browser/resources/options/pref_ui.js
index dd33c72..1970800 100644
--- a/chrome/browser/resources/options/pref_ui.js
+++ b/chrome/browser/resources/options/pref_ui.js
@@ -463,6 +463,36 @@
   };
 
   /////////////////////////////////////////////////////////////////////////////
+  // PrefPortNumber class:
+
+  // Define a constructor that uses an input element as its underlying element.
+  var PrefPortNumber = cr.ui.define('input');
+
+  PrefPortNumber.prototype = {
+    // Set up the prototype chain
+    __proto__: PrefTextField.prototype,
+
+    /**
+     * Initialization function for the cr.ui framework.
+     */
+    decorate: function() {
+      var self = this;
+      self.type = 'text';
+      self.dataType = 'text';
+      PrefTextField.prototype.decorate.call(this);
+      self.oninput = function() {
+        // Note that using <input type="number"> is insufficient to restrict
+        // the input as it allows negative numbers and does not limit the
+        // number of charactes typed even if a range is set.  Furthermore,
+        // it sometimes produces strange repaint artifacts.
+        var filtered = self.value.replace(/[^0-9]/g, '');
+        if (filtered != self.value)
+          self.value = filtered;
+      };
+    }
+  };
+
+  /////////////////////////////////////////////////////////////////////////////
   // PrefButton class:
 
   // Define a constructor that uses a button element as its underlying element.
@@ -520,6 +550,7 @@
     PrefRange: PrefRange,
     PrefSelect: PrefSelect,
     PrefTextField: PrefTextField,
+    PrefPortNumber: PrefPortNumber,
     PrefButton: PrefButton
   };
 
diff --git a/chrome/browser/resources/policy.css b/chrome/browser/resources/policy.css
index 990d55f..cdf701d 100644
--- a/chrome/browser/resources/policy.css
+++ b/chrome/browser/resources/policy.css
@@ -56,24 +56,52 @@
 }
 
 #show-unset-container {
+  float: right;
   text-align: right;
 }
 
 html[dir='rtl'] #show-unset-container {
+  float: left;
   text-align: left;
 }
 
+div.reload-policies-button {
+  float: left;
+}
+
+html[dir='rtl'] div.reload-policies-button {
+  float: right;
+}
+
+div.show-unset-checkbox {
+  float: right;
+}
+
+html[dir='rtl'] div.show-unset-checkbox {
+  float: left;
+}
+
+section.reload-show-unset-section {
+  padding-bottom: 30px;
+  padding-top: 15px;
+}
+
+section.status-box-section {
+  clear: both;
+}
+
+div.table-description {
+  color: rgb(100, 100, 100);
+}
+
 div.no-policies-set {
   color: rgb(180, 180, 180);
   font-size: 125%;
-  margin-top: 70px;
+  margin-bottom: 10px;
+  margin-top: 20px;
   text-align: center;
 }
 
-section:not(.empty) > div.no-policies-set {
-  display: none;
-}
-
 table {
   border-collapse: collapse;
   margin-bottom: 5px;
@@ -86,6 +114,14 @@
   display: none;
 }
 
+section:not(.empty) > div.no-policies-set {
+  display: none;
+}
+
+section.policy-table-section {
+  padding-bottom: 10px;
+}
+
 th,
 td {
   border: 1px solid rgb(217, 217, 217);
diff --git a/chrome/browser/resources/policy.html b/chrome/browser/resources/policy.html
index bba2afc..fff1829 100644
--- a/chrome/browser/resources/policy.html
+++ b/chrome/browser/resources/policy.html
@@ -29,33 +29,23 @@
     <header>
       <h1 i18n-content="title"></h1>
     </header>
-    <section>
-      <button id="reload-policies" i18n-content="reloadPolicies"></button>
-    </section>
-    <section id="status" hidden>
-      <h3 i18n-content="status"></h3>
-      <div id="status-box-container"></span>
-    </section>
-    <section class="empty">
-      <h3 i18n-content="title"></h3>
-      <div id="show-unset-container">
+    <section class="reload-show-unset-section">
+      <div class="reload-policies-button">
+        <button id="reload-policies" i18n-content="reloadPolicies"></button>
+      </div>
+      <div id="show-unset-container" class="show-unset-checkbox">
         <label>
           <input id="show-unset" type="checkbox"></input>
           <span i18n-content="showUnset"></span>
         </label>
       </div>
-      <div class="no-policies-set" i18n-content="noPoliciesSet"></div>
-      <table id="policy-table">
-        <thead>
-          <tr>
-            <th i18n-content="headerScope"></th>
-            <th i18n-content="headerLevel"></th>
-            <th i18n-content="headerName"></th>
-            <th i18n-content="headerValue"></th>
-            <th i18n-content="headerStatus"></th>
-          </tr>
-        </thead>
-      </table>
+    </section>
+    <section id="status-section" class="status-box-section" hidden>
+      <h3 i18n-content="status"></h3>
+      <div id="status-box-container"></div>
+    </section>
+    <section id="main-section" class="empty">
+      <!--  This is where policy tables get dynamically added. -->
     </section>
   </div>
   <div hidden>
@@ -104,7 +94,7 @@
               <button class="toggle-expanded-value link-button"></button>
             </div>
           </td>
-          <td>
+          <td class="status-container">
             <div class="status elide"></div>
           </td>
         </tr>
diff --git a/chrome/browser/resources/policy.js b/chrome/browser/resources/policy.js
index 2c52c61..0e1f87d 100644
--- a/chrome/browser/resources/policy.js
+++ b/chrome/browser/resources/policy.js
@@ -155,9 +155,10 @@
       // Determine whether the contents of the value column overflows. The
       // visibility of the contents, replacement link and additional row
       // containing the complete value that depend on this are handled by CSS.
-      this.classList.toggle(
-          'has-overflowed-value',
-          valueContainer.offsetWidth < valueContainer.valueWidth);
+      if (valueContainer.offsetWidth < valueContainer.valueWidth)
+        this.classList.add('has-overflowed-value');
+      else
+        this.classList.remove('has-overflowed-value');
     },
 
     /**
@@ -272,8 +273,10 @@
             policy.unset && !showUnset ||
             policy.name.toLowerCase().indexOf(this.filterPattern_) == -1;
       }
-      this.parentElement.classList.toggle(
-          'empty', !this.querySelector('tbody:not([hidden])'));
+      if (this.querySelector('tbody:not([hidden])'))
+        this.parentElement.classList.remove('empty');
+      else
+        this.parentElement.classList.add('empty');
       setTimeout(this.checkOverflow_.bind(this), 0);
     },
 
@@ -319,7 +322,25 @@
    * @param {Object} names Dictionary containing all known policy names.
    */
   Page.setPolicyNames = function(names) {
-    this.getInstance().policyTable.setPolicyNames(names);
+    var page = this.getInstance();
+
+    // Clear all policy tables.
+    page.mainSection.innerHTML = '';
+    page.policyTables = {};
+
+    // Create tables and set known policy names for Chrome and extensions.
+    if (names.hasOwnProperty('chromePolicyNames')) {
+      var table = page.appendNewTable('chrome', 'Chrome policies', '');
+      table.setPolicyNames(names.chromePolicyNames);
+    }
+
+    if (names.hasOwnProperty('extensionPolicyNames')) {
+      for (var ext in names.extensionPolicyNames) {
+        var table = page.appendNewTable('extension-' + ext,
+            names.extensionPolicyNames[ext].name, 'ID: ' + ext);
+        table.setPolicyNames(names.extensionPolicyNames[ext].policyNames);
+      }
+    }
   };
 
   /**
@@ -329,7 +350,19 @@
    * @param {Object} values Dictionary containing the current policy values.
    */
   Page.setPolicyValues = function(values) {
-    this.getInstance().policyTable.setPolicyValues(values);
+    var page = this.getInstance();
+    if (values.hasOwnProperty('chromePolicies')) {
+      var table = page.policyTables['chrome'];
+      table.setPolicyValues(values.chromePolicies);
+    }
+
+    if (values.hasOwnProperty('extensionPolicies')) {
+      for (var extensionId in values.extensionPolicies) {
+        var table = page.policyTables['extension-' + extensionId];
+        if (table)
+          table.setPolicyValues(values.extensionPolicies[extensionId]);
+      }
+    }
   };
 
   /**
@@ -355,21 +388,29 @@
      */
     initialize: function() {
       uber.onContentFrameLoaded();
-      this.policyTable = $('policy-table');
-      cr.ui.decorate(this.policyTable, PolicyTable);
+
+      this.mainSection = $('main-section');
+      this.policyTables = {};
 
       // Place the initial focus on the filter input field.
       $('filter').focus();
 
       var self = this;
       $('filter').onsearch = function(event) {
-        self.policyTable.setFilterPattern(this.value);
+        for (policyTable in self.policyTables) {
+          self.policyTables[policyTable].setFilterPattern(this.value);
+        }
       };
       $('reload-policies').onclick = function(event) {
         this.disabled = true;
         chrome.send('reloadPolicies');
       };
-      $('show-unset').onchange = this.policyTable.filter.bind(this.policyTable);
+
+      $('show-unset').onchange = function() {
+        for (policyTable in self.policyTables) {
+          self.policyTables[policyTable].filter();
+        }
+      };
 
       // Notify the browser that the page has loaded, causing it to send the
       // list of all known policies, the current policy values and the cloud
@@ -377,6 +418,80 @@
       chrome.send('initialized');
     },
 
+   /**
+     * Creates a new policy table section, adds the section to the page,
+     * and returns the new table from that section.
+     * @param {string} id The key for storing the new table in policyTables.
+     * @param {string} label_title Title for this policy table.
+     * @param {string} label_content Description for the policy table.
+     * @return {Element} The newly created table.
+     */
+    appendNewTable: function(id, label_title, label_content) {
+      var newSection = this.createPolicyTableSection(id, label_title,
+          label_content);
+      this.mainSection.appendChild(newSection);
+      return this.policyTables[id];
+    },
+
+    /**
+     * Creates a new section containing a title, description and table of
+     * policies.
+     * @param {id} id The key for storing the new table in policyTables.
+     * @param {string} label_title Title for this policy table.
+     * @param {string} label_content Description for the policy table.
+     * @return {Element} The newly created section.
+     */
+    createPolicyTableSection: function(id, label_title, label_content) {
+      var section = document.createElement('section');
+      section.setAttribute('class', 'policy-table-section');
+
+      // Add title and description.
+      var title = window.document.createElement('h3');
+      title.textContent = label_title;
+      section.appendChild(title);
+
+      if (label_content) {
+        var description = window.document.createElement('div');
+        description.classList.add('table-description');
+        description.textContent = label_content;
+        section.appendChild(description);
+      }
+
+      // Add 'No Policies Set' element.
+      var noPolicies = window.document.createElement('div');
+      noPolicies.classList.add('no-policies-set');
+      noPolicies.textContent = loadTimeData.getString('noPoliciesSet');
+      section.appendChild(noPolicies);
+
+      // Add table of policies.
+      var newTable = this.createPolicyTable();
+      this.policyTables[id] = newTable;
+      section.appendChild(newTable);
+
+      return section;
+    },
+
+    /**
+     * Creates a new table for displaying policies.
+     * @return {Element} The newly created table.
+     */
+    createPolicyTable: function() {
+      var newTable = window.document.createElement('table');
+      var tableHead = window.document.createElement('thead');
+      var tableRow = window.document.createElement('tr');
+      var tableHeadings = ['headerScope', 'headerLevel',
+                           'headerName', 'headerValue', 'headerStatus'];
+      for (var i = 0; i < tableHeadings.length; i++) {
+        var tableHeader = window.document.createElement('th');
+        tableHeader.textContent = loadTimeData.getString(tableHeadings[i]);
+        tableRow.appendChild(tableHeader);
+      }
+      tableHead.appendChild(tableRow);
+      newTable.appendChild(tableHead);
+      cr.ui.decorate(newTable, PolicyTable);
+      return newTable;
+    },
+
     /**
      * Update the status section of the page to show the current cloud policy
      * status.
@@ -388,7 +503,7 @@
       while (container.firstChild)
         container.removeChild(container.firstChild);
       // Hide the status section.
-      var section = $('status');
+      var section = $('status-section');
       section.hidden = true;
 
       // Add a status box for each scope that has a cloud policy status.
diff --git a/chrome/browser/resources/print_preview/images/cloud.png b/chrome/browser/resources/print_preview/images/cloud.png
index c84d343..0c414ae 100644
--- a/chrome/browser/resources/print_preview/images/cloud.png
+++ b/chrome/browser/resources/print_preview/images/cloud.png
Binary files differ
diff --git a/chrome/browser/resources/print_preview/images/gcp_logo.png b/chrome/browser/resources/print_preview/images/gcp_logo.png
index 1f14375..6c485ba 100644
--- a/chrome/browser/resources/print_preview/images/gcp_logo.png
+++ b/chrome/browser/resources/print_preview/images/gcp_logo.png
Binary files differ
diff --git a/chrome/browser/resources/print_preview/images/google_doc.png b/chrome/browser/resources/print_preview/images/google_doc.png
index 81a0ee6..50e1b7e 100644
--- a/chrome/browser/resources/print_preview/images/google_doc.png
+++ b/chrome/browser/resources/print_preview/images/google_doc.png
Binary files differ
diff --git a/chrome/browser/resources/print_preview/images/mobile.png b/chrome/browser/resources/print_preview/images/mobile.png
index e804e49..8263091 100644
--- a/chrome/browser/resources/print_preview/images/mobile.png
+++ b/chrome/browser/resources/print_preview/images/mobile.png
Binary files differ
diff --git a/chrome/browser/resources/print_preview/images/mobile_shared.png b/chrome/browser/resources/print_preview/images/mobile_shared.png
index d5f9576..33b02de 100644
--- a/chrome/browser/resources/print_preview/images/mobile_shared.png
+++ b/chrome/browser/resources/print_preview/images/mobile_shared.png
Binary files differ
diff --git a/chrome/browser/resources/print_preview/images/pdf.png b/chrome/browser/resources/print_preview/images/pdf.png
index 3ae5c9b..bf49abb 100644
--- a/chrome/browser/resources/print_preview/images/pdf.png
+++ b/chrome/browser/resources/print_preview/images/pdf.png
Binary files differ
diff --git a/chrome/browser/resources/print_preview/images/printer.png b/chrome/browser/resources/print_preview/images/printer.png
index b78cc52..341e47f 100644
--- a/chrome/browser/resources/print_preview/images/printer.png
+++ b/chrome/browser/resources/print_preview/images/printer.png
Binary files differ
diff --git a/chrome/browser/resources/print_preview/images/printer_shared.png b/chrome/browser/resources/print_preview/images/printer_shared.png
index 4b07714..026ed45 100644
--- a/chrome/browser/resources/print_preview/images/printer_shared.png
+++ b/chrome/browser/resources/print_preview/images/printer_shared.png
Binary files differ
diff --git a/chrome/browser/resources/print_preview/images/search.png b/chrome/browser/resources/print_preview/images/search.png
index 2b4b77c..de504e8 100644
--- a/chrome/browser/resources/print_preview/images/search.png
+++ b/chrome/browser/resources/print_preview/images/search.png
Binary files differ
diff --git a/chrome/browser/resources/print_preview/images/third_party.png b/chrome/browser/resources/print_preview/images/third_party.png
index 104ac88..c12de3f 100644
--- a/chrome/browser/resources/print_preview/images/third_party.png
+++ b/chrome/browser/resources/print_preview/images/third_party.png
Binary files differ
diff --git a/chrome/browser/resources/print_preview/images/third_party_fedex.png b/chrome/browser/resources/print_preview/images/third_party_fedex.png
index a87ece3..03d7da8 100644
--- a/chrome/browser/resources/print_preview/images/third_party_fedex.png
+++ b/chrome/browser/resources/print_preview/images/third_party_fedex.png
Binary files differ
diff --git a/chrome/browser/resources/print_preview/print_preview.css b/chrome/browser/resources/print_preview/print_preview.css
index 41cc8fa..ed5424c 100644
--- a/chrome/browser/resources/print_preview/print_preview.css
+++ b/chrome/browser/resources/print_preview/print_preview.css
@@ -4,6 +4,7 @@
 
 html {
   height: 100%;
+  overflow: hidden;
 }
 
 body {
diff --git a/chrome/browser/resources/quick_office/manifest.json b/chrome/browser/resources/quick_office/manifest.json
index 1b08600..e2bb7f6 100644
--- a/chrome/browser/resources/quick_office/manifest.json
+++ b/chrome/browser/resources/quick_office/manifest.json
@@ -59,7 +59,21 @@
     "metricsPrivate",
     "streamsPrivate",
     "unlimitedStorage"],
-  "version": "2.9.2.14",
+  "platforms": [
+    {
+      "nacl_arch": "x86-32",
+      "sub_package_path": "_platform_specific/x86_32/"
+    },
+    {
+      "nacl_arch": "x86-64",
+      "sub_package_path": "_platform_specific/x86_64/"
+    },
+    {
+      "nacl_arch": "arm",
+      "sub_package_path": "_platform_specific/arm/"
+    }
+  ],
+  "version": "2.9.2.35",
   "web_accessible_resources": [
     "views/qowt.html"]
 }
diff --git a/chrome/browser/resources/quick_office/manifest_experimental.json b/chrome/browser/resources/quick_office/manifest_experimental.json
index 69de531..d6de353 100644
--- a/chrome/browser/resources/quick_office/manifest_experimental.json
+++ b/chrome/browser/resources/quick_office/manifest_experimental.json
@@ -60,7 +60,21 @@
     "metricsPrivate",
     "streamsPrivate",
     "unlimitedStorage"],
-  "version": "2.9.2.14",
+  "platforms": [
+    {
+      "nacl_arch": "x86-32",
+      "sub_package_path": "_platform_specific/x86_32/"
+    },
+    {
+      "nacl_arch": "x86-64",
+      "sub_package_path": "_platform_specific/x86_64/"
+    },
+    {
+      "nacl_arch": "arm",
+      "sub_package_path": "_platform_specific/arm/"
+    }
+  ],
+  "version": "2.9.2.35",
   "web_accessible_resources": [
     "views/qowt.html"]
 }
diff --git a/chrome/browser/resources/robot.png b/chrome/browser/resources/robot.png
index d913a52..ea4188a 100644
--- a/chrome/browser/resources/robot.png
+++ b/chrome/browser/resources/robot.png
Binary files differ
diff --git a/chrome/browser/resources/safe_browsing/images/2x/malware_icon_v2.png b/chrome/browser/resources/safe_browsing/images/2x/malware_icon_v2.png
index 8a2db13..a7687b5 100644
--- a/chrome/browser/resources/safe_browsing/images/2x/malware_icon_v2.png
+++ b/chrome/browser/resources/safe_browsing/images/2x/malware_icon_v2.png
Binary files differ
diff --git a/chrome/browser/resources/safe_browsing/images/2x/phishing_icon.png b/chrome/browser/resources/safe_browsing/images/2x/phishing_icon.png
index 83d1c80..b537a01 100644
--- a/chrome/browser/resources/safe_browsing/images/2x/phishing_icon.png
+++ b/chrome/browser/resources/safe_browsing/images/2x/phishing_icon.png
Binary files differ
diff --git a/chrome/browser/resources/safe_browsing/images/2x/subresource_icon.png b/chrome/browser/resources/safe_browsing/images/2x/subresource_icon.png
index a14cf20..c624628 100644
--- a/chrome/browser/resources/safe_browsing/images/2x/subresource_icon.png
+++ b/chrome/browser/resources/safe_browsing/images/2x/subresource_icon.png
Binary files differ
diff --git a/chrome/browser/resources/safe_browsing/images/malware_icon_v2.png b/chrome/browser/resources/safe_browsing/images/malware_icon_v2.png
index edf24b3..15c42ec 100644
--- a/chrome/browser/resources/safe_browsing/images/malware_icon_v2.png
+++ b/chrome/browser/resources/safe_browsing/images/malware_icon_v2.png
Binary files differ
diff --git a/chrome/browser/resources/safe_browsing/images/phishing_icon.png b/chrome/browser/resources/safe_browsing/images/phishing_icon.png
index 4f7db71..e8796a8 100644
--- a/chrome/browser/resources/safe_browsing/images/phishing_icon.png
+++ b/chrome/browser/resources/safe_browsing/images/phishing_icon.png
Binary files differ
diff --git a/chrome/browser/resources/safe_browsing/images/stripe.png b/chrome/browser/resources/safe_browsing/images/stripe.png
index d6bef14..b70145b 100644
--- a/chrome/browser/resources/safe_browsing/images/stripe.png
+++ b/chrome/browser/resources/safe_browsing/images/stripe.png
Binary files differ
diff --git a/chrome/browser/resources/safe_browsing/images/subresource_icon.png b/chrome/browser/resources/safe_browsing/images/subresource_icon.png
index b6a111c..a33c2ca 100644
--- a/chrome/browser/resources/safe_browsing/images/subresource_icon.png
+++ b/chrome/browser/resources/safe_browsing/images/subresource_icon.png
Binary files differ
diff --git a/chrome/browser/resources/ssl/badguy.png b/chrome/browser/resources/ssl/badguy.png
index ad670da..1af24cd 100644
--- a/chrome/browser/resources/ssl/badguy.png
+++ b/chrome/browser/resources/ssl/badguy.png
Binary files differ
diff --git a/chrome/browser/resources/ssl/firefox_fancy_twisty_closed.png b/chrome/browser/resources/ssl/firefox_fancy_twisty_closed.png
index ec15780..1025aea 100644
--- a/chrome/browser/resources/ssl/firefox_fancy_twisty_closed.png
+++ b/chrome/browser/resources/ssl/firefox_fancy_twisty_closed.png
Binary files differ
diff --git a/chrome/browser/resources/ssl/firefox_fancy_twisty_open.png b/chrome/browser/resources/ssl/firefox_fancy_twisty_open.png
index c520db5..7fac7da 100644
--- a/chrome/browser/resources/ssl/firefox_fancy_twisty_open.png
+++ b/chrome/browser/resources/ssl/firefox_fancy_twisty_open.png
Binary files differ
diff --git a/chrome/browser/resources/ssl/firefox_icon.png b/chrome/browser/resources/ssl/firefox_icon.png
index e8ad586..6fdf1e9 100644
--- a/chrome/browser/resources/ssl/firefox_icon.png
+++ b/chrome/browser/resources/ssl/firefox_icon.png
Binary files differ
diff --git a/chrome/browser/resources/ssl/firefox_twisty_closed.png b/chrome/browser/resources/ssl/firefox_twisty_closed.png
index 7da463f..cf17c46 100644
--- a/chrome/browser/resources/ssl/firefox_twisty_closed.png
+++ b/chrome/browser/resources/ssl/firefox_twisty_closed.png
Binary files differ
diff --git a/chrome/browser/resources/ssl/firefox_twisty_open.png b/chrome/browser/resources/ssl/firefox_twisty_open.png
index 44faeed..4e5016f 100644
--- a/chrome/browser/resources/ssl/firefox_twisty_open.png
+++ b/chrome/browser/resources/ssl/firefox_twisty_open.png
Binary files differ
diff --git a/chrome/browser/resources/ssl/policeman.png b/chrome/browser/resources/ssl/policeman.png
index 5dffd35..22a6f64 100644
--- a/chrome/browser/resources/ssl/policeman.png
+++ b/chrome/browser/resources/ssl/policeman.png
Binary files differ
diff --git a/chrome/browser/resources/ssl/roadblock.html b/chrome/browser/resources/ssl/roadblock.html
index 28b77f5..edec5f5 100644
--- a/chrome/browser/resources/ssl/roadblock.html
+++ b/chrome/browser/resources/ssl/roadblock.html
@@ -61,6 +61,18 @@
     text-decoration: underline;
   }
 
+  .test-image {
+    float: right;
+    height: 140px;
+    padding-left: 30px;
+    padding-right: 30px;
+    width: 140px;
+  }
+
+  html[dir='rtl'] .test-image {
+    float: left;
+  }
+
   .title {
     color: #660000;
     font-size: 18pt;
@@ -73,7 +85,7 @@
     display: inline;
   }
   </style>
-
+  <script src="../../../../ui/webui/resources/js/assert.js"></script>
   <script>
     // Should match SSLBlockingPageCommands in ssl_blocking_page.cc.
     var CMD_DONT_PROCEED = 0;
@@ -84,6 +96,7 @@
     var showedMore = false;
     var keyPressState = 0;
     var gainFocus = false;
+    var setupExperiment = false;
 
     function $(o) {
       return document.getElementById(o);
@@ -160,8 +173,21 @@
       });
     }
 
+    function setupIconExperiments() {
+      if (templateData.trialType == '') return;
+      assert(!setupExperiment);
+      setupExperiment = true;
+      var condition = templateData.trialType.split('SSL')[1].toLowerCase();
+      if (/policeman|stoplight|badguy/.test(condition)) {
+        $('trial-' + condition).hidden = false;
+        $('more-info-short').style.webkitMarginEnd = '30px';
+        $('more-info-long').style.webkitMarginEnd = '30px';
+      }
+    }
+
     window.addEventListener('focus', handleFocusEvent);
     document.addEventListener('DOMContentLoaded', setupEvents);
+    document.addEventListener('DOMContentLoaded', setupIconExperiments);
   </script>
 </head>
 <body>
@@ -170,6 +196,18 @@
       <img src="roadblock_icon.png" alt="SSL Error Icon" id="roadblock-icon">
     </div>
     <div class="title" i18n-content="headLine"></div>
+
+    <!-- RHS images for the field trial. -->
+    <div id="trial-badguy" class="test-image" hidden>
+      <img src="badguy.png" alt="Bad guy">
+    </div>
+    <div id="trial-policeman" class="test-image" hidden>
+      <img src="policeman.png" alt="Policeman">
+    </div>
+    <div id="trial-stoplight" class="test-image" hidden>
+      <img src="stoplight.png" alt="Stoplight">
+    </div>
+
     <div class="main" i18n-values=".innerHTML:description;dir:textdirection"></div>
     <div class="main" i18n-values=".innerHTML:reasonForNotProceeding"></div>
     <div class="main">
diff --git a/chrome/browser/resources/ssl/roadblock_background.png b/chrome/browser/resources/ssl/roadblock_background.png
index 61851c1..d562dff 100644
--- a/chrome/browser/resources/ssl/roadblock_background.png
+++ b/chrome/browser/resources/ssl/roadblock_background.png
Binary files differ
diff --git a/chrome/browser/resources/ssl/roadblock_icon.png b/chrome/browser/resources/ssl/roadblock_icon.png
index 7907d24..feab348 100644
--- a/chrome/browser/resources/ssl/roadblock_icon.png
+++ b/chrome/browser/resources/ssl/roadblock_icon.png
Binary files differ
diff --git a/chrome/browser/resources/ssl/stoplight.png b/chrome/browser/resources/ssl/stoplight.png
index c311882..b1eec06 100644
--- a/chrome/browser/resources/ssl/stoplight.png
+++ b/chrome/browser/resources/ssl/stoplight.png
Binary files differ
diff --git a/chrome/browser/resources/ssl/twisty_closed.png b/chrome/browser/resources/ssl/twisty_closed.png
index bb748b8..c19c69e 100644
--- a/chrome/browser/resources/ssl/twisty_closed.png
+++ b/chrome/browser/resources/ssl/twisty_closed.png
Binary files differ
diff --git a/chrome/browser/resources/ssl/twisty_closed_rtl.png b/chrome/browser/resources/ssl/twisty_closed_rtl.png
index 0e9961a..7e796e1 100644
--- a/chrome/browser/resources/ssl/twisty_closed_rtl.png
+++ b/chrome/browser/resources/ssl/twisty_closed_rtl.png
Binary files differ
diff --git a/chrome/browser/resources/ssl/twisty_open.png b/chrome/browser/resources/ssl/twisty_open.png
index 0902be0..6647ea3 100644
--- a/chrome/browser/resources/ssl/twisty_open.png
+++ b/chrome/browser/resources/ssl/twisty_open.png
Binary files differ
diff --git a/chrome/browser/resources/sync_file_system_internals/extension_statuses.html b/chrome/browser/resources/sync_file_system_internals/extension_statuses.html
index a445a7d..51e6871 100644
--- a/chrome/browser/resources/sync_file_system_internals/extension_statuses.html
+++ b/chrome/browser/resources/sync_file_system_internals/extension_statuses.html
@@ -4,7 +4,8 @@
 <table>
   <thead>
     <tr>
-      <td>Extension ID</td>
+      <td>Extension Name</td>
+      <td>ID</td>
       <td>Sync Status</td>
     </tr>
   </thead>
diff --git a/chrome/browser/resources/sync_file_system_internals/extension_statuses.js b/chrome/browser/resources/sync_file_system_internals/extension_statuses.js
index f194312..a31de23 100644
--- a/chrome/browser/resources/sync_file_system_internals/extension_statuses.js
+++ b/chrome/browser/resources/sync_file_system_internals/extension_statuses.js
@@ -33,7 +33,8 @@
 
 /**
  * Handles callback from onGetExtensionStatuses.
- * @param {Array} list of dictionaries containing 'extensionID' and 'status'.
+ * @param {Array} list of dictionaries containing 'extensionName',
+ *     'extensionID, 'status'.
  */
 ExtensionStatuses.onGetExtensionStatuses = function(extensionStatuses) {
   var itemContainer = $('extension-entries');
@@ -42,6 +43,7 @@
   for (var i = 0; i < extensionStatuses.length; i++) {
     var originEntry = extensionStatuses[i];
     var tr = document.createElement('tr');
+    tr.appendChild(createElementFromText('td', originEntry.extensionName));
     tr.appendChild(createElementFromText('td', originEntry.extensionID));
     tr.appendChild(createElementFromText('td', originEntry.status));
     itemContainer.appendChild(tr);
diff --git a/chrome/browser/resources/sync_file_system_internals/file_metadata.html b/chrome/browser/resources/sync_file_system_internals/file_metadata.html
index 40e317e..5c9d3a5 100644
--- a/chrome/browser/resources/sync_file_system_internals/file_metadata.html
+++ b/chrome/browser/resources/sync_file_system_internals/file_metadata.html
@@ -1,17 +1,9 @@
 <script src="chrome://syncfs-internals/file_metadata.js"></script>
 
-<!-- Extension ID Drop down to go here -->
+<select id="extensions-select"></select>
+<button id="refresh-metadata-button">Refresh</button>
 
-<button id="refresh-file-metadata">Refresh</button>
 <table>
-  <thead>
-    <tr>
-      <td>Extension</td>
-      <td>Status</td>
-      <td>Type</td>
-      <td>Title</td>
-      <td>Details</td>
-    </tr>
-  </thead>
+  <thead id="file-metadata-header"></thead>
   <tbody id="file-metadata-entries"></tbody>
 </table>
diff --git a/chrome/browser/resources/sync_file_system_internals/file_metadata.js b/chrome/browser/resources/sync_file_system_internals/file_metadata.js
index 85d2484..efc2196 100644
--- a/chrome/browser/resources/sync_file_system_internals/file_metadata.js
+++ b/chrome/browser/resources/sync_file_system_internals/file_metadata.js
@@ -11,23 +11,89 @@
 var FileMetadata = {};
 
 /**
- * Get File Metadata from handler.
+ * Gets extension data so the select drop down can be filled.
+ */
+function getExtensions() {
+  chrome.send('getExtensions');
+}
+
+/**
+ * Renders result of getFileMetadata as a table.
+ * @param {Array} list of dictionaries containing 'extensionName',
+ *     'extensionID', 'status'.
+ */
+FileMetadata.onGetExtensions = function(extensionStatuses) {
+  var select = $('extensions-select');
+
+  // Record existing drop down extension ID. If it's still there after the
+  // refresh then keep it as the selected value.
+  var oldSelectedExtension = getSelectedExtensionId();
+
+  select.textContent = '';
+  for (var i = 0; i < extensionStatuses.length; i++) {
+    var originEntry = extensionStatuses[i];
+    var tr = document.createElement('tr');
+    var title = originEntry.extensionName + ' [' + originEntry.status + ']';
+    select.options.add(new Option(title, originEntry.extensionID));
+
+    // If option was the previously only selected, make it selected again.
+    if (originEntry.extensionID != oldSelectedExtension)
+      continue;
+    select.options[select.options.length - 1].selected = true;
+  }
+
+  // After drop down has been loaded with options, file metadata can be loaded
+  getFileMetadata();
+}
+
+/**
+ * @return {string} extension ID that's currently selected in drop down box.
+ */
+function getSelectedExtensionId() {
+  var dropDown = $('extensions-select').options;
+  if (dropDown.selectedIndex >= 0)
+    return dropDown[dropDown.selectedIndex].value;
+
+  return null;
+}
+
+/**
+ * Get File Metadata depending on which extension is selected from the drop down
+ * if any.
  */
 function getFileMetadata() {
-  chrome.send('getFileMetadata');
+  var dropDown = $('extensions-select');
+  if (dropDown.options.length === 0) {
+    $('file-metadata-header').textContent = '';
+    $('file-metadata-entries').textContent = 'No file metadata available.';
+    return;
+  }
+
+  var selectedExtensionId = getSelectedExtensionId();
+  chrome.send('getFileMetadata', [selectedExtensionId]);
 }
 
 /**
  * Renders result of getFileMetadata as a table.
  */
 FileMetadata.onGetFileMetadata = function(fileMetadataMap) {
+  var header = $('file-metadata-header');
+  // Only draw the header if it hasn't been drawn yet
+  if (header.children.length === 0) {
+    var tr = document.createElement('tr');
+    tr.appendChild(createElementFromText('td', 'Status'));
+    tr.appendChild(createElementFromText('td', 'Type'));
+    tr.appendChild(createElementFromText('td', 'Title'));
+    tr.appendChild(createElementFromText('td', 'Details'));
+    header.appendChild(tr);
+  }
+
+  // Add row entries.
   var itemContainer = $('file-metadata-entries');
   itemContainer.textContent = '';
-
   for (var i = 0; i < fileMetadataMap.length; i++) {
     var metadatEntry = fileMetadataMap[i];
     var tr = document.createElement('tr');
-    tr.appendChild(createElementFromText('td', metadatEntry.origin));
     tr.appendChild(createElementFromText('td', metadatEntry.status));
     tr.appendChild(createElementFromText('td', metadatEntry.type));
     tr.appendChild(createElementFromText('td', metadatEntry.title));
@@ -50,8 +116,9 @@
 }
 
 function main() {
-  getFileMetadata();
-  $('refresh-file-metadata').addEventListener('click', getFileMetadata);
+  getExtensions();
+  $('refresh-metadata-button').addEventListener('click', getExtensions);
+  $('extensions-select').addEventListener('change', getFileMetadata);
 }
 
 document.addEventListener('DOMContentLoaded', main);
diff --git a/chrome/browser/resources/sync_file_system_internals/main.css b/chrome/browser/resources/sync_file_system_internals/main.css
index 23db141..090c730 100644
--- a/chrome/browser/resources/sync_file_system_internals/main.css
+++ b/chrome/browser/resources/sync_file_system_internals/main.css
@@ -2,6 +2,10 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file. */
 
+* {
+  font-family: Ubuntu, Arial, sans-serif;
+}
+
 tabbox {
   min-height: 650px;
 }
@@ -12,15 +16,25 @@
 
 th,
 td {
+  font-size: 14px;
   padding-left: 0.5em;
   padding-right: 0.5em;
   text-align: left;
 }
 
 thead tr {
+  font-size: 14px;
   font-weight: bold;
 }
 
 tbody tr:nth-child(odd) {
   background: rgb(238, 238, 255);
 }
+
+.log-time {
+  white-space: nowrap;
+}
+
+.log-event.error {
+  background: rgb(255, 220, 220);
+}
diff --git a/chrome/browser/resources/sync_file_system_internals/sync_service.html b/chrome/browser/resources/sync_file_system_internals/sync_service.html
index d8e6ba6..bd45841 100644
--- a/chrome/browser/resources/sync_file_system_internals/sync_service.html
+++ b/chrome/browser/resources/sync_file_system_internals/sync_service.html
@@ -18,8 +18,8 @@
 <table>
   <thead>
     <tr>
-      <td>Time</td>
-      <td>Log Event</td>
+      <td class="log-time">Time</td>
+      <td class="log-event">Log Event</td>
     </tr>
   </thead>
   <tbody id="log-entries"></tbody>
diff --git a/chrome/browser/resources/sync_file_system_internals/sync_service.js b/chrome/browser/resources/sync_file_system_internals/sync_service.js
index 6b49e78..6a8e732 100644
--- a/chrome/browser/resources/sync_file_system_internals/sync_service.js
+++ b/chrome/browser/resources/sync_file_system_internals/sync_service.js
@@ -44,11 +44,16 @@
  * Creates an element named |elementName| containing the content |text|.
  * @param {string} elementName Name of the new element to be created.
  * @param {string} text Text to be contained in the new element.
+ * @param {Object} opt_attributes Optional attribute dictionary for the element.
  * @return {HTMLElement} The newly created HTML element.
  */
-function createElementFromText(elementName, text) {
+function createElementFromText(elementName, text, opt_attributes) {
   var element = document.createElement(elementName);
   element.appendChild(document.createTextNode(text));
+  if (opt_attributes) {
+    for (var key in opt_attributes)
+      element.setAttribute(key, opt_attributes[key]);
+  }
   return element;
 }
 
@@ -68,8 +73,11 @@
   for (var i = 0; i < logEntries.length; i++) {
     var logEntry = logEntries[i];
     var tr = document.createElement('tr');
-    tr.appendChild(createElementFromText('td', logEntry.time));
-    tr.appendChild(createElementFromText('td', logEntry.logEvent));
+    var error = /ERROR/.test(logEntry.logEvent) ? ' error' : '';
+    tr.appendChild(createElementFromText('td', logEntry.time,
+                                         {class: 'log-time'}));
+    tr.appendChild(createElementFromText('td', logEntry.logEvent,
+                                         {class: 'log-event' + error}));
     itemContainer.appendChild(tr);
   }
 }
diff --git a/chrome/browser/resources/sync_internals/data.html b/chrome/browser/resources/sync_internals/data.html
index ed31498..ec3f237 100644
--- a/chrome/browser/resources/sync_internals/data.html
+++ b/chrome/browser/resources/sync_internals/data.html
@@ -13,6 +13,8 @@
 
 <button id="dump-to-file">Dump sync nodes to file</button>
 
+<input type="checkbox" id="include-specifics">include node content <font color="red">WARNING: This is likely to include personal information.</font><br>
+
 <a style="display: none" id="dump-to-file-anchor"></a>
 
 <script src="chrome://sync-internals/data.js"></script>
diff --git a/chrome/browser/resources/sync_internals/data.js b/chrome/browser/resources/sync_internals/data.js
index e2c6045..1e68887 100644
--- a/chrome/browser/resources/sync_internals/data.js
+++ b/chrome/browser/resources/sync_internals/data.js
@@ -32,7 +32,6 @@
   dataDump.textContent = data;
 });
 
-// TODO(mmontgomery): add SPECIFICS as an opt-in.
 var allFields = [
   'ID',
   'IS_UNSYNCED',
@@ -46,6 +45,8 @@
   'IS_DEL',
   'SERVER_IS_DEL',
   'serverModelType',
+  'SERVER_SPECIFICS',
+  'SPECIFICS',
 ];
 
 function versionToDateString(version) {
@@ -65,6 +66,9 @@
     } if (field == 'BASE_VERSION_TIME') {
       var version = node['BASE_VERSION'];
       fieldVal = versionToDateString(version);
+    } else if ((field == 'SERVER_SPECIFICS' || field == 'SPECIFICS') &&
+            $('include-specifics').checked) {
+      fieldVal = JSON.stringify(node[field]);
     } else {
       fieldVal = node[field];
     }
diff --git a/chrome/browser/resources/sync_setup_overlay.html b/chrome/browser/resources/sync_setup_overlay.html
index 3aa0d3e..f0bdfd3 100644
--- a/chrome/browser/resources/sync_setup_overlay.html
+++ b/chrome/browser/resources/sync_setup_overlay.html
@@ -34,7 +34,11 @@
             <select id="sync-select-datatypes">
               <option i18n-content="syncAllDataTypes" selected></option>
               <option i18n-content="chooseDataTypes"></option>
-              <option i18n-content="syncNothing"></option>
+              <!-- The syncNothing element is to be hidden for M29.
+                   TODO(rsimha): Revisit this for M30.
+                   See http://crbug.com/252049.
+              -->
+              <option i18n-content="syncNothing" hidden></option>
             </select>
             <div id="choose-data-types-body">
               <div id="apps-item" class="sync-type-checkbox checkbox">
diff --git a/chrome/browser/resources/task_manager/main.js b/chrome/browser/resources/task_manager/main.js
index 154d399..6a6a046 100644
--- a/chrome/browser/resources/task_manager/main.js
+++ b/chrome/browser/resources/task_manager/main.js
@@ -429,8 +429,6 @@
     var listItem = new cr.ui.ListItem({label: ''});
 
     listItem.className = 'table-row';
-    if (this.opt_.isBackgroundMode && data.isBackgroundResource)
-      listItem.className += ' table-background-row';
 
     for (var i = 0; i < cm.size; i++) {
       var cell = document.createElement('div');
@@ -690,7 +688,6 @@
 function init() {
   var params = parseQueryParams(window.location);
   var opt = {};
-  opt['isBackgroundMode'] = params.background;
   opt['isShowCloseButton'] = params.showclose;
   taskmanager.initialize(document.body, opt);
 }
diff --git a/chrome/browser/resources/task_manager/task_manager.css b/chrome/browser/resources/task_manager/task_manager.css
index e050d56..e77055f 100644
--- a/chrome/browser/resources/task_manager/task_manager.css
+++ b/chrome/browser/resources/task_manager/task_manager.css
@@ -77,13 +77,6 @@
   width: 6px;
 }
 
-.table-background-row {
-  background-color: hsl(34, 91%, 87%);
-  background-image: -webkit-linear-gradient(rgba(255, 255, 255, 0.8),
-                                            rgba(255, 255, 255, 0));
-  border-color: hsl(34, 91%, 65%);
-}
-
 /* Cells in table. */
 .table-row-cell {
   -webkit-box-orient: horizontal;
diff --git a/chrome/browser/resources/translate_internals/prefs.html b/chrome/browser/resources/translate_internals/prefs.html
index 7aba1ad..e04030d 100644
--- a/chrome/browser/resources/translate_internals/prefs.html
+++ b/chrome/browser/resources/translate_internals/prefs.html
@@ -4,8 +4,12 @@
 found in the LICENSE file.
 -->
 <div>
+  <section id="prefs-blocked-languages">
+    <h2>Languages not translated (New)</h2>
+    <ul></ul>
+  </section>
   <section id="prefs-language-blacklist">
-    <h2>Languages not translated</h2>
+    <h2>Languages not translated<span> (Old)</span></h2>
     <ul></ul>
   </section>
   <section id="prefs-site-blacklist">
diff --git a/chrome/browser/resources/translate_internals/translate_internals.js b/chrome/browser/resources/translate_internals/translate_internals.js
index c409715..a0553a6 100644
--- a/chrome/browser/resources/translate_internals/translate_internals.js
+++ b/chrome/browser/resources/translate_internals/translate_internals.js
@@ -25,6 +25,12 @@
 
       var button = $('detection-logs-dump');
       button.addEventListener('click', onDetectionLogsDump);
+
+      var enableTranslateSettings = templateData['enable-translate-settings'];
+      if (!enableTranslateSettings) {
+        $('prefs-blocked-languages').hidden = true;
+        $('prefs-language-blacklist').querySelector('h2 span').hidden = true;
+      }
     }
 
     /**
@@ -101,6 +107,24 @@
      */
     function onPrefsUpdated(detail) {
       var ul;
+
+      ul = document.querySelector('#prefs-blocked-languages ul');
+      ul.innerHTML = '';
+
+      if ('translate_blocked_languages' in detail) {
+        var langs = detail['translate_blocked_languages'];
+
+        langs.forEach(function(langCode) {
+          var text = formatLanguageCode(langCode);
+
+          var li = createLIWithDismissingButton(text, function() {
+            chrome.send('removePrefItem',
+                        ['blocked_languages', langCode]);
+          });
+          ul.appendChild(li);
+        });
+      }
+
       ul = document.querySelector('#prefs-language-blacklist ul');
       ul.innerHTML = '';
 
diff --git a/chrome/browser/resources/twisty_closed.png b/chrome/browser/resources/twisty_closed.png
index bb748b8..c19c69e 100644
--- a/chrome/browser/resources/twisty_closed.png
+++ b/chrome/browser/resources/twisty_closed.png
Binary files differ
diff --git a/chrome/browser/resources/twisty_closed_rtl.png b/chrome/browser/resources/twisty_closed_rtl.png
index 0e9961a..7e796e1 100644
--- a/chrome/browser/resources/twisty_closed_rtl.png
+++ b/chrome/browser/resources/twisty_closed_rtl.png
Binary files differ
diff --git a/chrome/browser/resources/twisty_open.png b/chrome/browser/resources/twisty_open.png
index 0902be0..6647ea3 100644
--- a/chrome/browser/resources/twisty_open.png
+++ b/chrome/browser/resources/twisty_open.png
Binary files differ
diff --git a/chrome/browser/rlz/rlz.cc b/chrome/browser/rlz/rlz.cc
index 968a33c..fc4e7ba 100644
--- a/chrome/browser/rlz/rlz.cc
+++ b/chrome/browser/rlz/rlz.cc
@@ -63,10 +63,6 @@
 const base::TimeDelta kMaxInitDelay = base::TimeDelta::FromSeconds(200);
 const base::TimeDelta kMinInitDelay = base::TimeDelta::FromSeconds(20);
 
-bool IsGoogleUrl(const GURL& url) {
-  return google_util::IsGoogleHomePageUrl(url.possibly_invalid_spec());
-}
-
 bool IsBrandOrganic(const std::string& brand) {
   return brand.empty() || google_util::IsOrganic(brand);
 }
@@ -232,16 +228,17 @@
 
   PrefService* pref_service = profile->GetPrefs();
   bool is_google_homepage = google_util::IsGoogleHomePageUrl(
-      pref_service->GetString(prefs::kHomePage));
+      GURL(pref_service->GetString(prefs::kHomePage)));
 
   bool is_google_in_startpages = false;
   SessionStartupPref session_startup_prefs =
       StartupBrowserCreator::GetSessionStartupPref(
           *CommandLine::ForCurrentProcess(), profile);
   if (session_startup_prefs.type == SessionStartupPref::URLS) {
-    is_google_in_startpages = std::count_if(session_startup_prefs.urls.begin(),
-                                            session_startup_prefs.urls.end(),
-                                            IsGoogleUrl) > 0;
+    is_google_in_startpages =
+        std::count_if(session_startup_prefs.urls.begin(),
+                      session_startup_prefs.urls.end(),
+                      google_util::IsGoogleHomePageUrl) > 0;
   }
 
   if (!InitRlzDelayed(first_run, send_ping_immediately, delay,
diff --git a/chrome/browser/rlz/rlz.h b/chrome/browser/rlz/rlz.h
index e4a361c..d55e05c 100644
--- a/chrome/browser/rlz/rlz.h
+++ b/chrome/browser/rlz/rlz.h
@@ -16,7 +16,7 @@
 #include "base/memory/singleton.h"
 #include "base/strings/string16.h"
 #include "base/threading/sequenced_worker_pool.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "rlz/lib/rlz_lib.h"
diff --git a/chrome/browser/safe_browsing/browser_feature_extractor.cc b/chrome/browser/safe_browsing/browser_feature_extractor.cc
index 1ebf378..6cfb98f 100644
--- a/chrome/browser/safe_browsing/browser_feature_extractor.cc
+++ b/chrome/browser/safe_browsing/browser_feature_extractor.cc
@@ -12,7 +12,7 @@
 #include "base/format_macros.h"
 #include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/common/cancelable_request.h"
 #include "chrome/browser/history/history_service.h"
 #include "chrome/browser/history/history_service_factory.h"
@@ -26,7 +26,7 @@
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/page_transition_types.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 using content::BrowserThread;
 using content::NavigationController;
diff --git a/chrome/browser/safe_browsing/browser_feature_extractor.h b/chrome/browser/safe_browsing/browser_feature_extractor.h
index 6ea8bf1..086e9bb 100644
--- a/chrome/browser/safe_browsing/browser_feature_extractor.h
+++ b/chrome/browser/safe_browsing/browser_feature_extractor.h
@@ -21,12 +21,12 @@
 #include "base/containers/hash_tables.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/sequenced_task_runner_helpers.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/common/cancelable_request.h"
 #include "chrome/browser/history/history_types.h"
 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
 #include "chrome/browser/safe_browsing/ui_manager.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 class HistoryService;
 
diff --git a/chrome/browser/safe_browsing/browser_feature_extractor_unittest.cc b/chrome/browser/safe_browsing/browser_feature_extractor_unittest.cc
index e52cbfd..9c2d444 100644
--- a/chrome/browser/safe_browsing/browser_feature_extractor_unittest.cc
+++ b/chrome/browser/safe_browsing/browser_feature_extractor_unittest.cc
@@ -11,7 +11,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/message_loop.h"
 #include "base/strings/stringprintf.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/history/history_backend.h"
 #include "chrome/browser/history/history_service.h"
 #include "chrome/browser/history/history_service_factory.h"
@@ -28,9 +28,9 @@
 #include "content/public/common/referrer.h"
 #include "content/public/test/test_browser_thread.h"
 #include "content/public/test/web_contents_tester.h"
-#include "googleurl/src/gurl.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 using content::WebContentsTester;
 using testing::Return;
diff --git a/chrome/browser/safe_browsing/client_side_detection_host.cc b/chrome/browser/safe_browsing/client_side_detection_host.cc
index 81cb917..5c5a781 100644
--- a/chrome/browser/safe_browsing/client_side_detection_host.cc
+++ b/chrome/browser/safe_browsing/client_side_detection_host.cc
@@ -35,7 +35,7 @@
 #include "content/public/browser/resource_request_details.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/frame_navigate_params.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 using content::BrowserThread;
 using content::NavigationEntry;
diff --git a/chrome/browser/safe_browsing/client_side_detection_host.h b/chrome/browser/safe_browsing/client_side_detection_host.h
index 70dbbbe..7329f52 100644
--- a/chrome/browser/safe_browsing/client_side_detection_host.h
+++ b/chrome/browser/safe_browsing/client_side_detection_host.h
@@ -17,7 +17,7 @@
 #include "content/public/browser/notification_registrar.h"
 #include "content/public/browser/resource_request_details.h"
 #include "content/public/browser/web_contents_observer.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 namespace safe_browsing {
 class ClientPhishingRequest;
diff --git a/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc b/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc
index 9c2aeed..3a696b5 100644
--- a/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc
+++ b/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc
@@ -23,10 +23,10 @@
 #include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/test_browser_thread.h"
 #include "content/public/test/test_renderer_host.h"
-#include "googleurl/src/gurl.h"
 #include "ipc/ipc_test_sink.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 using ::testing::_;
 using ::testing::DeleteArg;
diff --git a/chrome/browser/safe_browsing/client_side_detection_service.cc b/chrome/browser/safe_browsing/client_side_detection_service.cc
index 87503a6..b0514b3 100644
--- a/chrome/browser/safe_browsing/client_side_detection_service.cc
+++ b/chrome/browser/safe_browsing/client_side_detection_service.cc
@@ -13,7 +13,7 @@
 #include "base/prefs/pref_service.h"
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/chrome_switches.h"
@@ -27,7 +27,6 @@
 #include "content/public/browser/render_process_host.h"
 #include "crypto/sha2.h"
 #include "google_apis/google_api_keys.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/escape.h"
 #include "net/base/load_flags.h"
 #include "net/http/http_response_headers.h"
@@ -35,6 +34,7 @@
 #include "net/url_request/url_fetcher.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "net/url_request/url_request_status.h"
+#include "url/gurl.h"
 
 using content::BrowserThread;
 
diff --git a/chrome/browser/safe_browsing/client_side_detection_service.h b/chrome/browser/safe_browsing/client_side_detection_service.h
index f89de22..ccc3c66 100644
--- a/chrome/browser/safe_browsing/client_side_detection_service.h
+++ b/chrome/browser/safe_browsing/client_side_detection_service.h
@@ -27,12 +27,12 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/net_util.h"
 #include "net/url_request/url_fetcher_delegate.h"
+#include "url/gurl.h"
 
 class SafeBrowsingService;
 
diff --git a/chrome/browser/safe_browsing/client_side_detection_service_unittest.cc b/chrome/browser/safe_browsing/client_side_detection_service_unittest.cc
index 87d471e..eb74147 100644
--- a/chrome/browser/safe_browsing/client_side_detection_service_unittest.cc
+++ b/chrome/browser/safe_browsing/client_side_detection_service_unittest.cc
@@ -11,17 +11,17 @@
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/message_loop.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/safe_browsing/client_side_detection_service.h"
 #include "chrome/common/safe_browsing/client_model.pb.h"
 #include "chrome/common/safe_browsing/csd.pb.h"
 #include "content/public/test/test_browser_thread.h"
 #include "crypto/sha2.h"
-#include "googleurl/src/gurl.h"
 #include "net/url_request/test_url_fetcher_factory.h"
 #include "net/url_request/url_request_status.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 using ::testing::_;
 using ::testing::Invoke;
diff --git a/chrome/browser/safe_browsing/database_manager.h b/chrome/browser/safe_browsing/database_manager.h
index 5e9520f..09f64bd 100644
--- a/chrome/browser/safe_browsing/database_manager.h
+++ b/chrome/browser/safe_browsing/database_manager.h
@@ -19,10 +19,10 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/synchronization/lock.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/safe_browsing/protocol_manager.h"
 #include "chrome/browser/safe_browsing/safe_browsing_util.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 class SafeBrowsingService;
 class SafeBrowsingDatabase;
diff --git a/chrome/browser/safe_browsing/download_feedback.cc b/chrome/browser/safe_browsing/download_feedback.cc
index fef426a..6748d2d 100644
--- a/chrome/browser/safe_browsing/download_feedback.cc
+++ b/chrome/browser/safe_browsing/download_feedback.cc
@@ -108,7 +108,9 @@
     uploader_.reset();
   }
 
-  base::FileUtilProxy::Delete(file_task_runner_, file_path_, false,
+  base::FileUtilProxy::Delete(file_task_runner_.get(),
+                              file_path_,
+                              false,
                               base::FileUtilProxy::StatusCallback());
 }
 
@@ -135,15 +137,16 @@
   std::string metadata_string;
   bool ok = report_metadata.SerializeToString(&metadata_string);
   DCHECK(ok);
-  uploader_.reset(TwoPhaseUploader::Create(
-      request_context_getter_,
-      file_task_runner_,
-      url,
-      metadata_string,
-      file_path_,
-      TwoPhaseUploader::ProgressCallback(),
-      base::Bind(&DownloadFeedbackImpl::FinishedUpload, base::Unretained(this),
-                 finish_callback)));
+  uploader_.reset(
+      TwoPhaseUploader::Create(request_context_getter_.get(),
+                               file_task_runner_.get(),
+                               url,
+                               metadata_string,
+                               file_path_,
+                               TwoPhaseUploader::ProgressCallback(),
+                               base::Bind(&DownloadFeedbackImpl::FinishedUpload,
+                                          base::Unretained(this),
+                                          finish_callback)));
   uploader_->Start();
 }
 
diff --git a/chrome/browser/safe_browsing/download_feedback_service.cc b/chrome/browser/safe_browsing/download_feedback_service.cc
index 3e5b378..8c189aa 100644
--- a/chrome/browser/safe_browsing/download_feedback_service.cc
+++ b/chrome/browser/safe_browsing/download_feedback_service.cc
@@ -177,7 +177,9 @@
   if (service) {
     service->BeginFeedback(ping_request, ping_response, path);
   } else {
-    base::FileUtilProxy::Delete(file_task_runner, path, false,
+    base::FileUtilProxy::Delete(file_task_runner.get(),
+                                path,
+                                false,
                                 base::FileUtilProxy::StatusCallback());
   }
 }
@@ -193,9 +195,12 @@
     const std::string& ping_response,
     const base::FilePath& path) {
   DCHECK(CalledOnValidThread());
-  DownloadFeedback* feedback = DownloadFeedback::Create(
-      request_context_getter_, file_task_runner_, path,
-      ping_request, ping_response);
+  DownloadFeedback* feedback =
+      DownloadFeedback::Create(request_context_getter_.get(),
+                               file_task_runner_.get(),
+                               path,
+                               ping_request,
+                               ping_response);
   active_feedback_.push_back(feedback);
   UMA_HISTOGRAM_COUNTS_100("SBDownloadFeedback.ActiveFeedbacks",
                            active_feedback_.size());
diff --git a/chrome/browser/safe_browsing/download_feedback_service_unittest.cc b/chrome/browser/safe_browsing/download_feedback_service_unittest.cc
index 8f0a874..a912a3f 100644
--- a/chrome/browser/safe_browsing/download_feedback_service_unittest.cc
+++ b/chrome/browser/safe_browsing/download_feedback_service_unittest.cc
@@ -208,7 +208,8 @@
   EXPECT_CALL(item, StealDangerousDownload(_))
       .WillOnce(SaveArg<0>(&download_discarded_callback));
 
-  DownloadFeedbackService service(request_context_getter_, file_task_runner_);
+  DownloadFeedbackService service(request_context_getter_.get(),
+                                  file_task_runner_.get());
   service.MaybeStorePingsForDownload(
       DownloadProtectionService::UNCOMMON, &item, ping_request, ping_response);
   ASSERT_TRUE(DownloadFeedbackService::IsEnabledForDownload(item));
@@ -255,7 +256,8 @@
   }
 
   {
-    DownloadFeedbackService service(request_context_getter_, file_task_runner_);
+    DownloadFeedbackService service(request_context_getter_.get(),
+                                    file_task_runner_.get());
     for (size_t i = 0; i < num_downloads; ++i) {
       SCOPED_TRACE(i);
       service.BeginFeedbackForDownload(&item[i]);
@@ -323,7 +325,8 @@
   }
 
   {
-    DownloadFeedbackService service(request_context_getter_, file_task_runner_);
+    DownloadFeedbackService service(request_context_getter_.get(),
+                                    file_task_runner_.get());
     for (size_t i = 0; i < num_downloads; ++i) {
       SCOPED_TRACE(i);
       service.BeginFeedbackForDownload(&item[i]);
diff --git a/chrome/browser/safe_browsing/download_feedback_unittest.cc b/chrome/browser/safe_browsing/download_feedback_unittest.cc
index 4a83868..0054a69 100644
--- a/chrome/browser/safe_browsing/download_feedback_unittest.cc
+++ b/chrome/browser/safe_browsing/download_feedback_unittest.cc
@@ -169,12 +169,12 @@
   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
       switches::kSbDownloadFeedbackURL, kTestFeedbackURL);
 
-  DownloadFeedback* feedback = DownloadFeedback::Create(
-      url_request_context_getter_,
-      file_task_runner_,
-      upload_file_path_,
-      ping_request,
-      ping_response);
+  DownloadFeedback* feedback =
+      DownloadFeedback::Create(url_request_context_getter_.get(),
+                               file_task_runner_.get(),
+                               upload_file_path_,
+                               ping_request,
+                               ping_response);
   EXPECT_FALSE(uploader());
 
   feedback->Start(base::Bind(&DownloadFeedbackTest::FinishCallback,
@@ -216,12 +216,12 @@
   std::string ping_response(
       expected_report_metadata.download_response().SerializeAsString());
 
-  DownloadFeedback* feedback = DownloadFeedback::Create(
-      url_request_context_getter_,
-      file_task_runner_,
-      upload_file_path_,
-      ping_request,
-      ping_response);
+  DownloadFeedback* feedback =
+      DownloadFeedback::Create(url_request_context_getter_.get(),
+                               file_task_runner_.get(),
+                               upload_file_path_,
+                               ping_request,
+                               ping_response);
   EXPECT_FALSE(uploader());
 
   feedback->Start(base::Bind(&DownloadFeedbackTest::FinishCallback,
diff --git a/chrome/browser/safe_browsing/download_protection_service.cc b/chrome/browser/safe_browsing/download_protection_service.cc
index 9fe8380..2c5f590 100644
--- a/chrome/browser/safe_browsing/download_protection_service.cc
+++ b/chrome/browser/safe_browsing/download_protection_service.cc
@@ -16,7 +16,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/sequenced_worker_pool.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/safe_browsing/download_feedback_service.h"
 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
 #include "chrome/browser/safe_browsing/sandboxed_zip_analyzer.h"
diff --git a/chrome/browser/safe_browsing/download_protection_service.h b/chrome/browser/safe_browsing/download_protection_service.h
index 045bb2f..48ab04a 100644
--- a/chrome/browser/safe_browsing/download_protection_service.h
+++ b/chrome/browser/safe_browsing/download_protection_service.h
@@ -19,7 +19,7 @@
 #include "base/memory/ref_counted.h"
 #include "chrome/browser/safe_browsing/database_manager.h"
 #include "chrome/browser/safe_browsing/ui_manager.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 
 namespace content {
diff --git a/chrome/browser/safe_browsing/download_protection_service_unittest.cc b/chrome/browser/safe_browsing/download_protection_service_unittest.cc
index e5baf4c..1862107 100644
--- a/chrome/browser/safe_browsing/download_protection_service_unittest.cc
+++ b/chrome/browser/safe_browsing/download_protection_service_unittest.cc
@@ -28,13 +28,13 @@
 #include "chrome/common/safe_browsing/csd.pb.h"
 #include "content/public/test/mock_download_item.h"
 #include "content/public/test/test_browser_thread.h"
-#include "googleurl/src/gurl.h"
 #include "net/cert/x509_certificate.h"
 #include "net/url_request/test_url_fetcher_factory.h"
 #include "net/url_request/url_fetcher_delegate.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/zlib/google/zip.h"
+#include "url/gurl.h"
 
 using ::testing::Assign;
 using ::testing::ContainerEq;
diff --git a/chrome/browser/safe_browsing/malware_details_unittest.cc b/chrome/browser/safe_browsing/malware_details_unittest.cc
index 31f662d..37ada0c 100644
--- a/chrome/browser/safe_browsing/malware_details_unittest.cc
+++ b/chrome/browser/safe_browsing/malware_details_unittest.cc
@@ -7,7 +7,7 @@
 #include "base/bind.h"
 #include "base/pickle.h"
 #include "base/run_loop.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/history/history_backend.h"
 #include "chrome/browser/history/history_service.h"
 #include "chrome/browser/history/history_service_factory.h"
diff --git a/chrome/browser/safe_browsing/ping_manager.h b/chrome/browser/safe_browsing/ping_manager.h
index bdee022..f976cff 100644
--- a/chrome/browser/safe_browsing/ping_manager.h
+++ b/chrome/browser/safe_browsing/ping_manager.h
@@ -15,8 +15,8 @@
 #include "base/memory/scoped_ptr.h"
 #include "chrome/browser/safe_browsing/protocol_manager_helper.h"
 #include "chrome/browser/safe_browsing/safe_browsing_util.h"
-#include "googleurl/src/gurl.h"
 #include "net/url_request/url_fetcher_delegate.h"
+#include "url/gurl.h"
 
 namespace net {
 class URLRequestContextGetter;
diff --git a/chrome/browser/safe_browsing/ping_manager_unittest.cc b/chrome/browser/safe_browsing/ping_manager_unittest.cc
index 8673c24..585b31b 100644
--- a/chrome/browser/safe_browsing/ping_manager_unittest.cc
+++ b/chrome/browser/safe_browsing/ping_manager_unittest.cc
@@ -5,7 +5,7 @@
 
 #include "base/logging.h"
 #include "base/strings/stringprintf.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/safe_browsing/ping_manager.h"
 #include "google_apis/google_api_keys.h"
 #include "net/base/escape.h"
diff --git a/chrome/browser/safe_browsing/protocol_manager.cc b/chrome/browser/safe_browsing/protocol_manager.cc
index ff8856c..6c13779 100644
--- a/chrome/browser/safe_browsing/protocol_manager.cc
+++ b/chrome/browser/safe_browsing/protocol_manager.cc
@@ -14,7 +14,7 @@
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/safe_browsing/protocol_parser.h"
 #include "chrome/common/chrome_version_info.h"
 #include "chrome/common/env_vars.h"
diff --git a/chrome/browser/safe_browsing/protocol_manager.h b/chrome/browser/safe_browsing/protocol_manager.h
index 9fa2d95..f5555e3 100644
--- a/chrome/browser/safe_browsing/protocol_manager.h
+++ b/chrome/browser/safe_browsing/protocol_manager.h
@@ -22,14 +22,14 @@
 #include "base/gtest_prod_util.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/threading/non_thread_safe.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/safe_browsing/chunk_range.h"
 #include "chrome/browser/safe_browsing/protocol_manager_helper.h"
 #include "chrome/browser/safe_browsing/protocol_parser.h"
 #include "chrome/browser/safe_browsing/safe_browsing_util.h"
-#include "googleurl/src/gurl.h"
 #include "net/url_request/url_fetcher_delegate.h"
+#include "url/gurl.h"
 
 namespace net {
 class URLFetcher;
diff --git a/chrome/browser/safe_browsing/protocol_manager_unittest.cc b/chrome/browser/safe_browsing/protocol_manager_unittest.cc
index 06af5ad..22854f6 100644
--- a/chrome/browser/safe_browsing/protocol_manager_unittest.cc
+++ b/chrome/browser/safe_browsing/protocol_manager_unittest.cc
@@ -6,7 +6,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/test/test_simple_task_runner.h"
 #include "base/thread_task_runner_handle.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/safe_browsing/protocol_manager.h"
 #include "google_apis/google_api_keys.h"
 #include "net/base/escape.h"
diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
index e724f31..720836f 100644
--- a/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
@@ -18,7 +18,7 @@
 #include "base/strings/string_piece.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/google/google_util.h"
diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page.h b/chrome/browser/safe_browsing/safe_browsing_blocking_page.h
index b625714..f208d3b 100644
--- a/chrome/browser/safe_browsing/safe_browsing_blocking_page.h
+++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page.h
@@ -33,10 +33,10 @@
 #include <vector>
 
 #include "base/gtest_prod_util.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/safe_browsing/ui_manager.h"
 #include "content/public/browser/interstitial_page_delegate.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 class MalwareDetails;
 class SafeBrowsingBlockingPageFactory;
diff --git a/chrome/browser/safe_browsing/safe_browsing_database.cc b/chrome/browser/safe_browsing/safe_browsing_database.cc
index 39954d6..ce2483c 100644
--- a/chrome/browser/safe_browsing/safe_browsing_database.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_database.cc
@@ -13,12 +13,12 @@
 #include "base/metrics/histogram.h"
 #include "base/metrics/stats_counters.h"
 #include "base/process_util.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/safe_browsing/prefix_set.h"
 #include "chrome/browser/safe_browsing/safe_browsing_store_file.h"
 #include "content/public/browser/browser_thread.h"
 #include "crypto/sha2.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 #if defined(OS_MACOSX)
 #include "base/mac/mac_util.h"
@@ -1486,7 +1486,7 @@
   // TODO(shess): Track failure to delete?
   base::FilePath bloom_filter_filename =
       BloomFilterForFilename(browse_filename_);
-  file_util::Delete(bloom_filter_filename, false);
+  base::Delete(bloom_filter_filename, false);
 
   const base::TimeTicks before = base::TimeTicks::Now();
   browse_prefix_set_.reset(safe_browsing::PrefixSet::LoadFile(
@@ -1522,24 +1522,24 @@
 
   base::FilePath bloom_filter_filename =
       BloomFilterForFilename(browse_filename_);
-  const bool r5 = file_util::Delete(bloom_filter_filename, false);
+  const bool r5 = base::Delete(bloom_filter_filename, false);
   if (!r5)
     RecordFailure(FAILURE_DATABASE_FILTER_DELETE);
 
-  const bool r6 = file_util::Delete(browse_prefix_set_filename_, false);
+  const bool r6 = base::Delete(browse_prefix_set_filename_, false);
   if (!r6)
     RecordFailure(FAILURE_BROWSE_PREFIX_SET_DELETE);
 
-  const bool r7 = file_util::Delete(extension_blacklist_filename_, false);
+  const bool r7 = base::Delete(extension_blacklist_filename_, false);
   if (!r7)
     RecordFailure(FAILURE_EXTENSION_BLACKLIST_DELETE);
 
-  const bool r8 = file_util::Delete(side_effect_free_whitelist_filename_,
+  const bool r8 = base::Delete(side_effect_free_whitelist_filename_,
                                     false);
   if (!r8)
     RecordFailure(FAILURE_SIDE_EFFECT_FREE_WHITELIST_DELETE);
 
-  const bool r9 = file_util::Delete(
+  const bool r9 = base::Delete(
       side_effect_free_whitelist_prefix_set_filename_,
       false);
   if (!r9)
diff --git a/chrome/browser/safe_browsing/safe_browsing_database_unittest.cc b/chrome/browser/safe_browsing/safe_browsing_database_unittest.cc
index ca61644..3b61ce7 100644
--- a/chrome/browser/safe_browsing/safe_browsing_database_unittest.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_database_unittest.cc
@@ -8,17 +8,17 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/logging.h"
 #include "base/message_loop.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/safe_browsing/safe_browsing_database.h"
 #include "chrome/browser/safe_browsing/safe_browsing_store_file.h"
 #include "chrome/browser/safe_browsing/safe_browsing_store_unittest_helper.h"
 #include "content/public/test/test_browser_thread.h"
 #include "crypto/sha2.h"
-#include "googleurl/src/gurl.h"
 #include "sql/connection.h"
 #include "sql/statement.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
+#include "url/gurl.h"
 
 using base::Time;
 using content::BrowserThread;
@@ -1658,7 +1658,7 @@
       &matching_list, &prefix_hits, &full_hashes, now));
 
   // If there is no filter file, the database cannot find malware urls.
-  file_util::Delete(filter_file, false);
+  base::Delete(filter_file, false);
   ASSERT_FALSE(file_util::PathExists(filter_file));
   database_.reset(new SafeBrowsingDatabaseNew);
   database_->Init(database_filename_);
diff --git a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
index 3254a6c..17522f6 100644
--- a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
@@ -17,7 +17,7 @@
 #include "base/prefs/pref_service.h"
 #include "base/strings/string_split.h"
 #include "base/test/thread_test_helper.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/prerender/prerender_manager.h"
 #include "chrome/browser/profiles/profile.h"
diff --git a/chrome/browser/safe_browsing/safe_browsing_store.h b/chrome/browser/safe_browsing/safe_browsing_store.h
index 196f6c1..917e357 100644
--- a/chrome/browser/safe_browsing/safe_browsing_store.h
+++ b/chrome/browser/safe_browsing/safe_browsing_store.h
@@ -11,7 +11,7 @@
 #include "base/basictypes.h"
 #include "base/callback_forward.h"
 #include "base/containers/hash_tables.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/safe_browsing/safe_browsing_util.h"
 
 namespace base {
diff --git a/chrome/browser/safe_browsing/safe_browsing_store_file.cc b/chrome/browser/safe_browsing/safe_browsing_store_file.cc
index bdc5232..234716c 100644
--- a/chrome/browser/safe_browsing/safe_browsing_store_file.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_store_file.cc
@@ -186,7 +186,7 @@
                            static_cast<int>(size / 1024));
     }
 
-    if (file_util::Delete(original_filename, false)) {
+    if (base::Delete(original_filename, false)) {
       RecordFormatEvent(FORMAT_EVENT_DELETED_ORIGINAL);
     } else {
       RecordFormatEvent(FORMAT_EVENT_DELETED_ORIGINAL_FAILED);
@@ -196,7 +196,7 @@
     // the weeds.
     const base::FilePath journal_filename(
         current_filename.DirName().AppendASCII("Safe Browsing-journal"));
-    file_util::Delete(journal_filename, false);
+    base::Delete(journal_filename, false);
   }
 }
 
@@ -654,12 +654,12 @@
 
   // Close the file handle and swizzle the file into place.
   new_file_.reset();
-  if (!file_util::Delete(filename_, false) &&
+  if (!base::Delete(filename_, false) &&
       file_util::PathExists(filename_))
     return false;
 
   const base::FilePath new_filename = TemporaryFileForFilename(filename_);
-  if (!file_util::Move(new_filename, filename_))
+  if (!base::Move(new_filename, filename_))
     return false;
 
   // Record counts before swapping to caller.
@@ -735,14 +735,14 @@
 
 // static
 bool SafeBrowsingStoreFile::DeleteStore(const base::FilePath& basename) {
-  if (!file_util::Delete(basename, false) &&
+  if (!base::Delete(basename, false) &&
       file_util::PathExists(basename)) {
     NOTREACHED();
     return false;
   }
 
   const base::FilePath new_filename = TemporaryFileForFilename(basename);
-  if (!file_util::Delete(new_filename, false) &&
+  if (!base::Delete(new_filename, false) &&
       file_util::PathExists(new_filename)) {
     NOTREACHED();
     return false;
@@ -754,7 +754,7 @@
   const base::FilePath journal_filename(
       basename.value() + FILE_PATH_LITERAL("-journal"));
   if (file_util::PathExists(journal_filename))
-    file_util::Delete(journal_filename, false);
+    base::Delete(journal_filename, false);
 
   return true;
 }
diff --git a/chrome/browser/safe_browsing/safe_browsing_test.cc b/chrome/browser/safe_browsing/safe_browsing_test.cc
index b33bc2e..fe2e14e 100644
--- a/chrome/browser/safe_browsing/safe_browsing_test.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_test.cc
@@ -29,7 +29,7 @@
 #include "base/test/test_timeouts.h"
 #include "base/threading/platform_thread.h"
 #include "base/threading/thread.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/safe_browsing/database_manager.h"
diff --git a/chrome/browser/safe_browsing/safe_browsing_util.cc b/chrome/browser/safe_browsing/safe_browsing_util.cc
index c979f2f..53d5a99 100644
--- a/chrome/browser/safe_browsing/safe_browsing_util.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_util.cc
@@ -9,9 +9,9 @@
 #include "base/strings/stringprintf.h"
 #include "chrome/browser/google/google_util.h"
 #include "crypto/sha2.h"
-#include "googleurl/src/gurl.h"
-#include "googleurl/src/url_util.h"
 #include "net/base/escape.h"
+#include "url/gurl.h"
+#include "url/url_util.h"
 
 #if defined(OS_WIN)
 #include "chrome/installer/util/browser_distribution.h"
diff --git a/chrome/browser/safe_browsing/safe_browsing_util_unittest.cc b/chrome/browser/safe_browsing/safe_browsing_util_unittest.cc
index d43c20e..20b033b 100644
--- a/chrome/browser/safe_browsing/safe_browsing_util_unittest.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_util_unittest.cc
@@ -7,8 +7,8 @@
 #include "base/strings/stringprintf.h"
 #include "chrome/browser/safe_browsing/safe_browsing_util.h"
 #include "crypto/sha2.h"
-#include "googleurl/src/gurl.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 namespace {
 
diff --git a/chrome/browser/safe_browsing/sandboxed_zip_analyzer.cc b/chrome/browser/safe_browsing/sandboxed_zip_analyzer.cc
index 3d93e67..6e97585 100644
--- a/chrome/browser/safe_browsing/sandboxed_zip_analyzer.cc
+++ b/chrome/browser/safe_browsing/sandboxed_zip_analyzer.cc
@@ -26,7 +26,10 @@
 SandboxedZipAnalyzer::SandboxedZipAnalyzer(
     const base::FilePath& zip_file,
     const ResultCallback& result_callback)
-    : zip_file_(zip_file), callback_(result_callback) {}
+    : zip_file_(zip_file),
+      callback_(result_callback),
+      callback_called_(false) {
+}
 
 void SandboxedZipAnalyzer::Start() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -103,14 +106,11 @@
 void SandboxedZipAnalyzer::OnAnalyzeZipFileFinished(
     const zip_analyzer::Results& results) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      base::Bind(&SandboxedZipAnalyzer::RunCallback, this, results));
-}
-
-void SandboxedZipAnalyzer::RunCallback(const zip_analyzer::Results& results) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  callback_.Run(results);
+  if (callback_called_)
+    return;
+  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+                          base::Bind(callback_, results));
+  callback_called_ = true;
 }
 
 void SandboxedZipAnalyzer::StartProcessOnIOThread() {
diff --git a/chrome/browser/safe_browsing/sandboxed_zip_analyzer.h b/chrome/browser/safe_browsing/sandboxed_zip_analyzer.h
index 5936bc0..81c1b90 100644
--- a/chrome/browser/safe_browsing/sandboxed_zip_analyzer.h
+++ b/chrome/browser/safe_browsing/sandboxed_zip_analyzer.h
@@ -19,9 +19,6 @@
 #include "content/public/browser/utility_process_host.h"
 #include "content/public/browser/utility_process_host_client.h"
 
-namespace base {
-class FilePath;
-}
 namespace IPC {
 class Message;
 }
@@ -64,15 +61,14 @@
   // Launches the utility process.  Must run on the IO thread.
   void StartProcessOnIOThread();
 
-  // Runs the caller-supplied callback.
-  void RunCallback(const zip_analyzer::Results& results);
-
   const base::FilePath zip_file_;
   // Once we have opened the file, we store the handle so that we can use it
   // once the utility process has launched.
   base::PlatformFile zip_platform_file_;
   base::WeakPtr<content::UtilityProcessHost> utility_process_host_;
   const ResultCallback callback_;
+  // Initialized on the UI thread, but only accessed on the IO thread.
+  bool callback_called_;
 
   DISALLOW_COPY_AND_ASSIGN(SandboxedZipAnalyzer);
 };
diff --git a/chrome/browser/safe_browsing/two_phase_uploader.h b/chrome/browser/safe_browsing/two_phase_uploader.h
index c10cf7b..1055529 100644
--- a/chrome/browser/safe_browsing/two_phase_uploader.h
+++ b/chrome/browser/safe_browsing/two_phase_uploader.h
@@ -12,8 +12,8 @@
 #include "base/files/file_path.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/threading/non_thread_safe.h"
-#include "googleurl/src/gurl.h"
 #include "net/url_request/url_request_context_getter.h"
+#include "url/gurl.h"
 
 namespace base {
 class TaskRunner;
diff --git a/chrome/browser/safe_browsing/ui_manager.h b/chrome/browser/safe_browsing/ui_manager.h
index b2e394f..5c896ca 100644
--- a/chrome/browser/safe_browsing/ui_manager.h
+++ b/chrome/browser/safe_browsing/ui_manager.h
@@ -15,10 +15,10 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/observer_list.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/safe_browsing/safe_browsing_util.h"
 #include "content/public/browser/notification_observer.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 class SafeBrowsingService;
 
diff --git a/chrome/browser/search/iframe_source.cc b/chrome/browser/search/iframe_source.cc
index d204ee7..58a5c06 100644
--- a/chrome/browser/search/iframe_source.cc
+++ b/chrome/browser/search/iframe_source.cc
@@ -12,10 +12,10 @@
 #include "chrome/common/url_constants.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
-#include "googleurl/src/gurl.h"
 #include "grit/browser_resources.h"
 #include "net/url_request/url_request.h"
 #include "ui/base/resource/resource_bundle.h"
+#include "url/gurl.h"
 
 IframeSource::IframeSource() {
 }
diff --git a/chrome/browser/search/iframe_source_unittest.cc b/chrome/browser/search/iframe_source_unittest.cc
index b560c02..ceb80f4 100644
--- a/chrome/browser/search/iframe_source_unittest.cc
+++ b/chrome/browser/search/iframe_source_unittest.cc
@@ -13,11 +13,11 @@
 #include "content/public/browser/resource_request_info.h"
 #include "content/public/test/mock_resource_context.h"
 #include "content/public/test/test_browser_thread.h"
-#include "googleurl/src/gurl.h"
 #include "grit/browser_resources.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_context.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 const int kNonInstantRendererPID = 0;
 const char kNonInstantOrigin[] = "http://evil";
diff --git a/chrome/browser/search/instant_extended_context_menu_observer.cc b/chrome/browser/search/instant_extended_context_menu_observer.cc
deleted file mode 100644
index fa42b67..0000000
--- a/chrome/browser/search/instant_extended_context_menu_observer.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/search/instant_extended_context_menu_observer.h"
-
-#include "base/logging.h"
-#include "chrome/app/chrome_command_ids.h"
-#include "chrome/browser/search/search.h"
-
-InstantExtendedContextMenuObserver::InstantExtendedContextMenuObserver(
-    content::WebContents* contents)
-    : is_instant_overlay_(chrome::IsInstantOverlay(contents)) {
-}
-
-InstantExtendedContextMenuObserver::~InstantExtendedContextMenuObserver() {
-}
-
-bool InstantExtendedContextMenuObserver::IsCommandIdSupported(int command_id) {
-  switch (command_id) {
-    case IDC_BACK:
-    case IDC_FORWARD:
-    case IDC_PRINT:
-    case IDC_RELOAD:
-      return is_instant_overlay_;
-    default:
-      return false;
-  }
-}
-
-bool InstantExtendedContextMenuObserver::IsCommandIdEnabled(int command_id) {
-  DCHECK(IsCommandIdSupported(command_id));
-  return false;
-}
diff --git a/chrome/browser/search/instant_extended_context_menu_observer.h b/chrome/browser/search/instant_extended_context_menu_observer.h
deleted file mode 100644
index 4685ce6..0000000
--- a/chrome/browser/search/instant_extended_context_menu_observer.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_SEARCH_INSTANT_EXTENDED_CONTEXT_MENU_OBSERVER_H_
-#define CHROME_BROWSER_SEARCH_INSTANT_EXTENDED_CONTEXT_MENU_OBSERVER_H_
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "chrome/browser/tab_contents/render_view_context_menu_observer.h"
-
-namespace content {
-class WebContents;
-}
-
-// This class disables menu items which perform poorly in instant extended mode.
-class InstantExtendedContextMenuObserver
-    : public RenderViewContextMenuObserver {
- public:
-  explicit InstantExtendedContextMenuObserver(content::WebContents* contents);
-  virtual ~InstantExtendedContextMenuObserver();
-
-  // RenderViewContextMenuObserver implementation.
-  virtual bool IsCommandIdSupported(int command_id) OVERRIDE;
-  virtual bool IsCommandIdEnabled(int command_id) OVERRIDE;
-
- private:
-  // Whether the source web contents of the context menu corresponds to an
-  // Instant overlay.
-  const bool is_instant_overlay_;
-
-  DISALLOW_COPY_AND_ASSIGN(InstantExtendedContextMenuObserver);
-};
-
-#endif  // CHROME_BROWSER_SEARCH_INSTANT_EXTENDED_CONTEXT_MENU_OBSERVER_H_
diff --git a/chrome/browser/search/instant_io_context.cc b/chrome/browser/search/instant_io_context.cc
index c579f96..650618a 100644
--- a/chrome/browser/search/instant_io_context.cc
+++ b/chrome/browser/search/instant_io_context.cc
@@ -7,8 +7,8 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/resource_context.h"
 #include "content/public/browser/resource_request_info.h"
-#include "googleurl/src/gurl.h"
 #include "net/url_request/url_request.h"
+#include "url/gurl.h"
 
 using content::BrowserThread;
 
diff --git a/chrome/browser/search/instant_service.cc b/chrome/browser/search/instant_service.cc
index ccf8c88..7718bc1 100644
--- a/chrome/browser/search/instant_service.cc
+++ b/chrome/browser/search/instant_service.cc
@@ -8,21 +8,19 @@
 
 #include "base/logging.h"
 #include "base/strings/string_number_conversions.h"
-#include "build/build_config.h"
 #include "chrome/browser/history/history_notifications.h"
 #include "chrome/browser/history/top_sites.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search/instant_io_context.h"
 #include "chrome/browser/search/instant_service_factory.h"
+#include "chrome/browser/search/instant_service_observer.h"
 #include "chrome/browser/search/local_ntp_source.h"
 #include "chrome/browser/search/most_visited_iframe_source.h"
 #include "chrome/browser/search/search.h"
 #include "chrome/browser/search/suggestion_iframe_source.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_instant_controller.h"
-#include "chrome/browser/ui/browser_list.h"
-#include "chrome/browser/ui/host_desktop.h"
-#include "chrome/browser/ui/search/instant_controller.h"
+#include "chrome/browser/themes/theme_properties.h"
+#include "chrome/browser/themes/theme_service.h"
+#include "chrome/browser/themes/theme_service_factory.h"
 #include "chrome/browser/ui/webui/favicon_source.h"
 #include "chrome/browser/ui/webui/ntp/thumbnail_source.h"
 #include "chrome/browser/ui/webui/theme_source.h"
@@ -32,8 +30,12 @@
 #include "content/public/browser/notification_types.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/url_data_source.h"
-#include "googleurl/src/gurl.h"
+#include "grit/theme_resources.h"
 #include "net/url_request/url_request.h"
+#include "ui/gfx/color_utils.h"
+#include "ui/gfx/image/image_skia.h"
+#include "ui/gfx/sys_color_change_listener.h"
+#include "url/gurl.h"
 
 using content::BrowserThread;
 
@@ -65,8 +67,14 @@
 
   // Set up the data sources that Instant uses on the NTP.
 #if defined(ENABLE_THEMES)
+  // Listen for theme installation.
+  registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
+                 content::Source<ThemeService>(
+                     ThemeServiceFactory::GetForProfile(profile_)));
+
   content::URLDataSource::Add(profile, new ThemeSource(profile));
-#endif
+#endif  // defined(ENABLE_THEMES)
+
   content::URLDataSource::Add(profile, new ThumbnailSource(profile));
   content::URLDataSource::Add(profile, new FaviconSource(
       profile, FaviconSource::FAVICON));
@@ -94,6 +102,14 @@
   return process_ids_.find(process_id) != process_ids_.end();
 }
 
+void InstantService::AddObserver(InstantServiceObserver* observer) {
+  observers_.AddObserver(observer);
+}
+
+void InstantService::RemoveObserver(InstantServiceObserver* observer) {
+  observers_.RemoveObserver(observer);
+}
+
 void InstantService::DeleteMostVisitedItem(const GURL& url) {
   history::TopSites* top_sites = profile_->GetTopSites();
   if (!top_sites)
@@ -118,9 +134,17 @@
   top_sites->ClearBlacklistedURLs();
 }
 
-void InstantService::GetCurrentMostVisitedItems(
-    std::vector<InstantMostVisitedItem>* items) const {
-  *items = most_visited_items_;
+void InstantService::UpdateThemeInfo() {
+  // Update theme background info.
+  // Initialize |theme_info| if necessary.
+  if (!theme_info_)
+    OnThemeChanged(ThemeServiceFactory::GetForProfile(profile_));
+  else
+    OnThemeChanged(NULL);
+}
+
+void InstantService::UpdateMostVisitedItemsInfo() {
+  NotifyAboutMostVisitedItems();
 }
 
 void InstantService::Shutdown() {
@@ -164,6 +188,12 @@
       }
       break;
     }
+#if defined(ENABLE_THEMES)
+    case chrome::NOTIFICATION_BROWSER_THEME_CHANGED: {
+      OnThemeChanged(content::Source<ThemeService>(source).ptr());
+      break;
+    }
+#endif  // defined(ENABLE_THEMES)
     default:
       NOTREACHED() << "Unexpected notification type in InstantService.";
   }
@@ -171,8 +201,6 @@
 
 void InstantService::OnMostVisitedItemsReceived(
     const history::MostVisitedURLList& data) {
-  // Android doesn't use Browser/BrowserList. Do nothing for Android platform.
-#if !defined(OS_ANDROID)
   history::MostVisitedURLList reordered_data(data);
   history::TopSites::MaybeShuffle(&reordered_data);
 
@@ -184,27 +212,90 @@
     item.title = url.title;
     new_most_visited_items.push_back(item);
   }
-  if (chrome::AreMostVisitedItemsEqual(new_most_visited_items,
-                                       most_visited_items_)) {
+
+  most_visited_items_ = new_most_visited_items;
+  NotifyAboutMostVisitedItems();
+}
+
+void InstantService::NotifyAboutMostVisitedItems() {
+  FOR_EACH_OBSERVER(InstantServiceObserver, observers_,
+                    MostVisitedItemsChanged(most_visited_items_));
+}
+
+void InstantService::OnThemeChanged(ThemeService* theme_service) {
+  if (!theme_service) {
+    DCHECK(theme_info_.get());
+    FOR_EACH_OBSERVER(InstantServiceObserver, observers_,
+                      ThemeInfoChanged(*theme_info_));
     return;
   }
 
-  most_visited_items_ = new_most_visited_items;
+  // Get theme information from theme service.
+  theme_info_.reset(new ThemeBackgroundInfo());
 
-  const BrowserList* browser_list =
-      BrowserList::GetInstance(chrome::GetActiveDesktop());
-  for (BrowserList::const_iterator it = browser_list->begin();
-       it != browser_list->end(); ++it) {
-    if ((*it)->profile() != profile_ || !((*it)->instant_controller()))
-      continue;
+  // Set theme background color.
+  SkColor background_color =
+      theme_service->GetColor(ThemeProperties::COLOR_NTP_BACKGROUND);
+  if (gfx::IsInvertedColorScheme())
+    background_color = color_utils::InvertColor(background_color);
 
-    InstantController* controller = (*it)->instant_controller()->instant();
-    if (!controller)
-      continue;
-    // TODO(kmadhusu): It would be cleaner to have each InstantController
-    // register itself as an InstantServiceObserver and push out updates that
-    // way. Refer to crbug.com/246355 for more details.
-    controller->UpdateMostVisitedItems();
+  theme_info_->color_r = SkColorGetR(background_color);
+  theme_info_->color_g = SkColorGetG(background_color);
+  theme_info_->color_b = SkColorGetB(background_color);
+  theme_info_->color_a = SkColorGetA(background_color);
+
+  if (theme_service->HasCustomImage(IDR_THEME_NTP_BACKGROUND)) {
+    // Set theme id for theme background image url.
+    theme_info_->theme_id = theme_service->GetThemeID();
+
+    // Set theme background image horizontal alignment.
+    int alignment = 0;
+    theme_service->GetDisplayProperty(
+        ThemeProperties::NTP_BACKGROUND_ALIGNMENT, &alignment);
+    if (alignment & ThemeProperties::ALIGN_LEFT)
+      theme_info_->image_horizontal_alignment = THEME_BKGRND_IMAGE_ALIGN_LEFT;
+    else if (alignment & ThemeProperties::ALIGN_RIGHT)
+      theme_info_->image_horizontal_alignment = THEME_BKGRND_IMAGE_ALIGN_RIGHT;
+    else
+      theme_info_->image_horizontal_alignment = THEME_BKGRND_IMAGE_ALIGN_CENTER;
+
+    // Set theme background image vertical alignment.
+    if (alignment & ThemeProperties::ALIGN_TOP)
+      theme_info_->image_vertical_alignment = THEME_BKGRND_IMAGE_ALIGN_TOP;
+    else if (alignment & ThemeProperties::ALIGN_BOTTOM)
+      theme_info_->image_vertical_alignment = THEME_BKGRND_IMAGE_ALIGN_BOTTOM;
+    else
+      theme_info_->image_vertical_alignment = THEME_BKGRND_IMAGE_ALIGN_CENTER;
+
+    // Set theme backgorund image tiling.
+    int tiling = 0;
+    theme_service->GetDisplayProperty(ThemeProperties::NTP_BACKGROUND_TILING,
+                                      &tiling);
+    switch (tiling) {
+      case ThemeProperties::NO_REPEAT:
+        theme_info_->image_tiling = THEME_BKGRND_IMAGE_NO_REPEAT;
+        break;
+      case ThemeProperties::REPEAT_X:
+        theme_info_->image_tiling = THEME_BKGRND_IMAGE_REPEAT_X;
+        break;
+      case ThemeProperties::REPEAT_Y:
+        theme_info_->image_tiling = THEME_BKGRND_IMAGE_REPEAT_Y;
+        break;
+      case ThemeProperties::REPEAT:
+        theme_info_->image_tiling = THEME_BKGRND_IMAGE_REPEAT;
+        break;
+    }
+
+    // Set theme background image height.
+    gfx::ImageSkia* image = theme_service->GetImageSkiaNamed(
+        IDR_THEME_NTP_BACKGROUND);
+    DCHECK(image);
+    theme_info_->image_height = image->height();
+
+    theme_info_->has_attribution =
+       theme_service->HasCustomImage(IDR_THEME_NTP_ATTRIBUTION);
   }
-#endif
+
+  FOR_EACH_OBSERVER(InstantServiceObserver, observers_,
+                    ThemeInfoChanged(*theme_info_));
 }
diff --git a/chrome/browser/search/instant_service.h b/chrome/browser/search/instant_service.h
index 4832ded..1e0d6f3 100644
--- a/chrome/browser/search/instant_service.h
+++ b/chrome/browser/search/instant_service.h
@@ -13,7 +13,9 @@
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
+#include "base/observer_list.h"
 #include "chrome/browser/history/history_types.h"
 #include "chrome/common/instant_types.h"
 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
@@ -22,7 +24,9 @@
 
 class GURL;
 class InstantIOContext;
+class InstantServiceObserver;
 class Profile;
+class ThemeService;
 
 namespace net {
 class URLRequest;
@@ -40,6 +44,10 @@
   void AddInstantProcess(int process_id);
   bool IsInstantProcess(int process_id) const;
 
+  // Adds/Removes InstantService observers.
+  void AddObserver(InstantServiceObserver* observer);
+  void RemoveObserver(InstantServiceObserver* observer);
+
 #if defined(UNIT_TEST)
   int GetInstantProcessCount() const {
     return process_ids_.size();
@@ -60,9 +68,15 @@
   // Most Visited deletions.
   void UndoAllMostVisitedDeletions();
 
-  // Returns the last added InstantMostVisitedItems.
-  void GetCurrentMostVisitedItems(
-      std::vector<InstantMostVisitedItem>* items) const;
+  // Invoked by the InstantController to update theme information for NTP.
+  //
+  // TODO(kmadhusu): Invoking this from InstantController shouldn't be
+  // necessary. Investigate more and remove this from here.
+  void UpdateThemeInfo();
+
+  // Invoked by the InstantController to update most visited items details for
+  // NTP.
+  void UpdateMostVisitedItemsInfo();
 
  private:
   // Overridden from BrowserContextKeyedService:
@@ -78,6 +92,12 @@
   // SendMostVisitedItems.
   void OnMostVisitedItemsReceived(const history::MostVisitedURLList& data);
 
+  // Notifies the observer about the last known most visited items.
+  void NotifyAboutMostVisitedItems();
+
+  // Theme changed notification handler.
+  void OnThemeChanged(ThemeService* theme_service);
+
   Profile* const profile_;
 
   // The process ids associated with Instant processes.
@@ -86,6 +106,11 @@
   // InstantMostVisitedItems sent to the Instant Pages.
   std::vector<InstantMostVisitedItem> most_visited_items_;
 
+  // Theme-related data for NTP overlay to adopt themes.
+  scoped_ptr<ThemeBackgroundInfo> theme_info_;
+
+  ObserverList<InstantServiceObserver> observers_;
+
   content::NotificationRegistrar registrar_;
 
   scoped_refptr<InstantIOContext> instant_io_context_;
diff --git a/chrome/browser/search/instant_service_observer.h b/chrome/browser/search/instant_service_observer.h
new file mode 100644
index 0000000..c282c93
--- /dev/null
+++ b/chrome/browser/search/instant_service_observer.h
@@ -0,0 +1,27 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SEARCH_INSTANT_SERVICE_OBSERVER_H_
+#define CHROME_BROWSER_SEARCH_INSTANT_SERVICE_OBSERVER_H_
+
+#include <vector>
+
+struct InstantMostVisitedItem;
+struct ThemeBackgroundInfo;
+
+// InstantServiceObserver defines the observer interface for InstantService.
+class InstantServiceObserver {
+ public:
+  // Indicates that the user's custom theme has changed in some way.
+  virtual void ThemeInfoChanged(const ThemeBackgroundInfo&) = 0;
+
+  // Indicates that the most visited items has changed.
+  virtual void MostVisitedItemsChanged(
+      const std::vector<InstantMostVisitedItem>&) = 0;
+
+ protected:
+  virtual ~InstantServiceObserver() {}
+};
+
+#endif  // CHROME_BROWSER_SEARCH_INSTANT_SERVICE_OBSERVER_H_
diff --git a/chrome/browser/search/local_ntp_source.cc b/chrome/browser/search/local_ntp_source.cc
index 6c92cbe..3281a64 100644
--- a/chrome/browser/search/local_ntp_source.cc
+++ b/chrome/browser/search/local_ntp_source.cc
@@ -9,8 +9,9 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/values.h"
+#include "chrome/browser/search/instant_io_context.h"
+#include "chrome/browser/search/search.h"
 #include "chrome/common/url_constants.h"
-#include "googleurl/src/gurl.h"
 #include "grit/browser_resources.h"
 #include "grit/generated_resources.h"
 #include "grit/ui_resources.h"
@@ -18,6 +19,7 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/webui/jstemplate_builder.h"
+#include "url/gurl.h"
 
 namespace {
 
@@ -47,11 +49,8 @@
     IDR_LOCAL_OMNIBOX_POPUP_IMAGES_SEARCH_ICON_PNG, "image/png" },
   { "images/2x/search_icon.png",
     IDR_LOCAL_OMNIBOX_POPUP_IMAGES_2X_SEARCH_ICON_PNG, "image/png" },
-  { "images/google_logo.png", IDR_LOCAL_NTP_IMAGES_LOGO_PNG, "image/png" },
   { "images/2x/google_logo.png",
     IDR_LOCAL_NTP_IMAGES_2X_LOGO_PNG, "image/png" },
-  { "images/white_google_logo.png",
-    IDR_LOCAL_NTP_IMAGES_WHITE_LOGO_PNG, "image/png" },
   { "images/2x/white_google_logo.png",
     IDR_LOCAL_NTP_IMAGES_2X_WHITE_LOGO_PNG, "image/png" },
 };
@@ -71,6 +70,8 @@
 // Returns a JS dictionary of translated strings for the local NTP.
 std::string GetTranslatedStrings() {
   base::DictionaryValue translated_strings;
+  if (chrome::ShouldShowRecentTabsOnNTP())
+    AddString(&translated_strings, "recentTabs", IDS_RECENT_TABS_MENU);
   AddString(&translated_strings, "thumbnailRemovedNotification",
             IDS_NEW_TAB_THUMBNAIL_REMOVED_NOTIFICATION);
   AddString(&translated_strings, "removeThumbnailTooltip",
@@ -135,6 +136,8 @@
 bool LocalNtpSource::ShouldServiceRequest(
     const net::URLRequest* request) const {
   DCHECK(request->url().host() == chrome::kChromeSearchLocalNtpHost);
+  if (!InstantIOContext::ShouldServiceRequest(request))
+    return false;
 
   if (request->url().SchemeIs(chrome::kChromeSearchScheme)) {
     DCHECK(StartsWithASCII(request->url().path(), "/", true));
diff --git a/chrome/browser/search/most_visited_iframe_source.cc b/chrome/browser/search/most_visited_iframe_source.cc
index 132383b..5f9fed9 100644
--- a/chrome/browser/search/most_visited_iframe_source.cc
+++ b/chrome/browser/search/most_visited_iframe_source.cc
@@ -7,9 +7,9 @@
 #include "base/metrics/histogram.h"
 #include "base/strings/string_number_conversions.h"
 #include "chrome/common/url_constants.h"
-#include "googleurl/src/gurl.h"
 #include "grit/browser_resources.h"
 #include "net/base/url_util.h"
+#include "url/gurl.h"
 
 namespace {
 
diff --git a/chrome/browser/search/search.cc b/chrome/browser/search/search.cc
index 1765cee..30cf8be 100644
--- a/chrome/browser/search/search.cc
+++ b/chrome/browser/search/search.cc
@@ -11,6 +11,7 @@
 #include "base/rand_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
+#include "chrome/browser/google/google_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search/instant_service.h"
 #include "chrome/browser/search/instant_service_factory.h"
@@ -20,6 +21,8 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_instant_controller.h"
 #include "chrome/browser/ui/browser_iterator.h"
+#include "chrome/browser/ui/search/search_model.h"
+#include "chrome/browser/ui/search/search_tab_helper.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
@@ -62,9 +65,9 @@
 // Sets the default state for the Instant checkbox.
 const char kInstantSearchResultsFlagName[] = "instant";
 
-const char kLocalOnlyFlagName[] = "local_only";
-const char kPreloadLocalOnlyNTPFlagName[] = "preload_local_only_ntp";
 const char kUseRemoteNTPOnStartupFlagName[] = "use_remote_ntp_on_startup";
+const char kShowNtpFlagName[] = "show_ntp";
+const char kRecentTabsOnNTPFlagName[] = "show_recent_tabs";
 
 // Constants for the field trial name and group prefix.
 const char kInstantExtendedFieldTrialName[] = "InstantExtended";
@@ -85,10 +88,13 @@
   return NULL;
 }
 
-GURL TemplateURLRefToGURL(const TemplateURLRef& ref, int start_margin) {
+GURL TemplateURLRefToGURL(const TemplateURLRef& ref,
+                          int start_margin,
+                          bool append_extra_query_params) {
   TemplateURLRef::SearchTermsArgs search_terms_args =
       TemplateURLRef::SearchTermsArgs(string16());
   search_terms_args.omnibox_start_margin = start_margin;
+  search_terms_args.append_extra_query_params = append_extra_query_params;
   return GURL(ref.ReplaceSearchTerms(search_terms_args));
 }
 
@@ -100,22 +106,16 @@
            other_url.SchemeIs(chrome::kHttpScheme)));
 }
 
-bool IsCommandLineInstantURL(const GURL& url) {
-  const CommandLine* cl = CommandLine::ForCurrentProcess();
-  const GURL instant_url(cl->GetSwitchValueASCII(switches::kInstantURL));
-  return instant_url.is_valid() && MatchesOrigin(url, instant_url);
-}
-
 bool MatchesAnySearchURL(const GURL& url, TemplateURL* template_url) {
   GURL search_url =
-      TemplateURLRefToGURL(template_url->url_ref(), kDisableStartMargin);
+      TemplateURLRefToGURL(template_url->url_ref(), kDisableStartMargin, false);
   if (search_url.is_valid() && MatchesOriginAndPath(url, search_url))
     return true;
 
   // "URLCount() - 1" because we already tested url_ref above.
   for (size_t i = 0; i < template_url->URLCount() - 1; ++i) {
     TemplateURLRef ref(template_url, i);
-    search_url = TemplateURLRefToGURL(ref, kDisableStartMargin);
+    search_url = TemplateURLRefToGURL(ref, kDisableStartMargin, false);
     if (search_url.is_valid() && MatchesOriginAndPath(url, search_url))
       return true;
   }
@@ -124,36 +124,121 @@
 }
 
 void RecordInstantExtendedOptInState() {
-  if (!instant_extended_opt_in_state_gate) {
-    instant_extended_opt_in_state_gate = true;
-    OptInState state = INSTANT_EXTENDED_NOT_SET;
-    const CommandLine* command_line = CommandLine::ForCurrentProcess();
-    if (command_line->HasSwitch(
-        switches::kDisableLocalOnlyInstantExtendedAPI)) {
-      if (command_line->HasSwitch(switches::kDisableInstantExtendedAPI)) {
-        state = INSTANT_EXTENDED_OPT_OUT_BOTH;
-      } else {
-        state = INSTANT_EXTENDED_OPT_OUT_LOCAL;
-      }
-    } else if (command_line->HasSwitch(switches::kDisableInstantExtendedAPI)) {
-      state = INSTANT_EXTENDED_OPT_OUT;
-    } else if (command_line->HasSwitch(
-        switches::kEnableLocalOnlyInstantExtendedAPI)) {
-      state = INSTANT_EXTENDED_OPT_IN_LOCAL;
-    } else if (command_line->HasSwitch(switches::kEnableInstantExtendedAPI)) {
-      state = INSTANT_EXTENDED_OPT_IN;
-    }
+  if (instant_extended_opt_in_state_gate)
+    return;
 
-    UMA_HISTOGRAM_ENUMERATION("InstantExtended.OptInState", state,
-                              INSTANT_EXTENDED_OPT_IN_STATE_ENUM_COUNT);
-  }
+  instant_extended_opt_in_state_gate = true;
+  OptInState state = INSTANT_EXTENDED_NOT_SET;
+  const CommandLine* command_line = CommandLine::ForCurrentProcess();
+  if (command_line->HasSwitch(switches::kDisableInstantExtendedAPI))
+    state = INSTANT_EXTENDED_OPT_OUT;
+  else if (command_line->HasSwitch(switches::kEnableInstantExtendedAPI))
+    state = INSTANT_EXTENDED_OPT_IN;
+
+  UMA_HISTOGRAM_ENUMERATION("InstantExtended.NewOptInState", state,
+                            INSTANT_EXTENDED_OPT_IN_STATE_ENUM_COUNT);
 }
 
-// Helper for EmbeddedSearchPageVersion. Does not check if in incognito mode.
-uint64 EmbeddedSearchPageVersionHelper() {
-  // No server-side changes if the local-only Instant Extended is enabled.
-  if (IsLocalOnlyInstantExtendedAPIEnabled())
-    return kEmbeddedPageVersionDisabled;
+// Returns true if |contents| is rendered inside the Instant process for
+// |profile|.
+bool IsRenderedInInstantProcess(const content::WebContents* contents,
+                                Profile* profile) {
+  const content::RenderProcessHost* process_host =
+      contents->GetRenderProcessHost();
+  if (!process_host)
+    return false;
+
+  const InstantService* instant_service =
+      InstantServiceFactory::GetForProfile(profile);
+  if (!instant_service)
+    return false;
+
+  return instant_service->IsInstantProcess(process_host->GetID());
+}
+
+// Returns true if |url| passes some basic checks that must succeed for it to be
+// usable as an instant URL:
+// (1) It contains the search terms replacement key of |template_url|, which is
+//     expected to be the TemplateURL* for the default search provider.
+// (2) Either it has a secure scheme, or else the user has manually specified a
+//     --google-base-url and it uses that base URL.  (This allows testers to use
+//     --google-base-url to point at non-HTTPS servers, which eases testing.)
+bool IsSuitableURLForInstant(const GURL& url, const TemplateURL* template_url) {
+  return template_url->HasSearchTermsReplacementKey(url) &&
+      (url.SchemeIsSecure() ||
+       google_util::StartsWithCommandLineGoogleBaseURL(url));
+}
+
+// Returns true if |url| can be used as an Instant URL for |profile|.
+bool IsInstantURL(const GURL& url, Profile* profile) {
+  if (!url.is_valid())
+    return false;
+
+  TemplateURL* template_url = GetDefaultSearchProviderTemplateURL(profile);
+  if (!template_url)
+    return false;
+
+  const bool extended_api_enabled = IsInstantExtendedAPIEnabled();
+  if (extended_api_enabled && !IsSuitableURLForInstant(url, template_url))
+    return false;
+
+  const TemplateURLRef& instant_url_ref = template_url->instant_url_ref();
+  const GURL instant_url =
+      TemplateURLRefToGURL(instant_url_ref, kDisableStartMargin, false);
+  return instant_url.is_valid() &&
+      (MatchesOriginAndPath(url, instant_url) ||
+       (extended_api_enabled && MatchesAnySearchURL(url, template_url)));
+}
+
+string16 GetSearchTermsImpl(const content::WebContents* contents,
+                            const content::NavigationEntry* entry) {
+  if (!contents || !IsQueryExtractionEnabled())
+    return string16();
+
+  // For security reasons, don't extract search terms if the page is not being
+  // rendered in the privileged Instant renderer process. This is to protect
+  // against a malicious page somehow scripting the search results page and
+  // faking search terms in the URL. Random pages can't get into the Instant
+  // renderer and scripting doesn't work cross-process, so if the page is in
+  // the Instant process, we know it isn't being exploited.
+  // Since iOS and Android doesn't use the instant framework, these checks are
+  // disabled for the two platforms.
+  Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext());
+#if !defined(OS_IOS) && !defined(OS_ANDROID)
+  if (!IsRenderedInInstantProcess(contents, profile) &&
+      ((entry == contents->GetController().GetLastCommittedEntry()) ||
+       !ShouldAssignURLToInstantRenderer(entry->GetURL(), profile)))
+    return string16();
+#endif  // !defined(OS_IOS) && !defined(OS_ANDROID)
+  // Check to see if search terms have already been extracted.
+  string16 search_terms = GetSearchTermsFromNavigationEntry(entry);
+  if (!search_terms.empty())
+    return search_terms;
+
+  // Otherwise, extract from the URL.
+  return GetSearchTermsFromURL(profile, entry->GetVirtualURL());
+}
+
+}  // namespace
+
+// Negative start-margin values prevent the "es_sm" parameter from being used.
+const int kDisableStartMargin = -1;
+
+bool IsInstantExtendedAPIEnabled() {
+#if defined(OS_IOS) || defined(OS_ANDROID)
+  return false;
+#else
+  // On desktop, query extraction is part of Instant extended, so if one is
+  // enabled, the other is too.
+  RecordInstantExtendedOptInState();
+  return IsQueryExtractionEnabled();
+#endif  // defined(OS_IOS) || defined(OS_ANDROID)
+}
+
+// Determine what embedded search page version to request from the user's
+// default search provider. If 0, the embedded search UI should not be enabled.
+uint64 EmbeddedSearchPageVersion() {
+  RecordInstantExtendedOptInState();
 
   // Check the command-line/about:flags setting first, which should have
   // precedence and allows the trial to not be reported (if it's never queried).
@@ -177,156 +262,15 @@
   return kEmbeddedPageVersionDisabled;
 }
 
-// Returns true if |contents| is rendered inside the Instant process for
-// |profile|.
-bool IsRenderedInInstantProcess(const content::WebContents* contents,
-                                Profile* profile) {
-  const content::RenderProcessHost* process_host =
-      contents->GetRenderProcessHost();
-  if (!process_host)
-    return false;
-
-  const InstantService* instant_service =
-      InstantServiceFactory::GetForProfile(profile);
-  if (!instant_service)
-    return false;
-
-  return instant_service->IsInstantProcess(process_host->GetID());
+bool IsQueryExtractionEnabled() {
+  return EmbeddedSearchPageVersion() != kEmbeddedPageVersionDisabled;
 }
 
-// Returns true if |url| can be used as an Instant URL for |profile|.
-bool IsInstantURL(const GURL& url, Profile* profile) {
-  TemplateURL* template_url = GetDefaultSearchProviderTemplateURL(profile);
-  if (!template_url)
-    return false;
-
-  const TemplateURLRef& instant_url_ref = template_url->instant_url_ref();
-  const bool extended_api_enabled = IsInstantExtendedAPIEnabled();
-  GURL effective_url = url;
-
-  if (IsCommandLineInstantURL(url))
-    effective_url = CoerceCommandLineURLToTemplateURL(url, instant_url_ref,
-                                                      kDisableStartMargin);
-
-  if (!effective_url.is_valid())
-    return false;
-
-  if (extended_api_enabled && !effective_url.SchemeIsSecure())
-    return false;
-
-  if (extended_api_enabled &&
-      !template_url->HasSearchTermsReplacementKey(effective_url))
-    return false;
-
-  const GURL instant_url =
-      TemplateURLRefToGURL(instant_url_ref, kDisableStartMargin);
-  if (!instant_url.is_valid())
-    return false;
-
-  if (MatchesOriginAndPath(effective_url, instant_url))
-    return true;
-
-  if (extended_api_enabled && MatchesAnySearchURL(effective_url, template_url))
-    return true;
-
-  return false;
-}
-
-string16 GetSearchTermsImpl(const content::WebContents* contents,
-                            const content::NavigationEntry* entry) {
-  // For security reasons, don't extract search terms if the page is not being
-  // rendered in the privileged Instant renderer process. This is to protect
-  // against a malicious page somehow scripting the search results page and
-  // faking search terms in the URL. Random pages can't get into the Instant
-  // renderer and scripting doesn't work cross-process, so if the page is in
-  // the Instant process, we know it isn't being exploited.
-  // Since iOS and Android doesn't use the instant framework, these checks are
-  // disabled for the two platforms.
-  Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext());
-
-  if (!IsQueryExtractionEnabled(profile))
-    return string16();
-
-#if !defined(OS_IOS) && !defined(OS_ANDROID)
-  if (!IsRenderedInInstantProcess(contents, profile) &&
-      (contents->GetController().GetLastCommittedEntry() == entry ||
-       !ShouldAssignURLToInstantRenderer(entry->GetURL(), profile)))
-    return string16();
-#endif  // !defined(OS_IOS) && !defined(OS_ANDROID)
-  // Check to see if search terms have already been extracted.
-  string16 search_terms = GetSearchTermsFromNavigationEntry(entry);
-  if (!search_terms.empty())
-    return search_terms;
-
-  // Otherwise, extract from the URL.
-  return GetSearchTermsFromURL(profile, entry->GetVirtualURL());
-}
-
-}  // namespace
-
-// Negative start-margin values prevent the "es_sm" parameter from being used.
-const int kDisableStartMargin = -1;
-
-bool IsInstantExtendedAPIEnabled() {
-#if defined(OS_IOS) || defined(OS_ANDROID)
-  return false;
-#else
-  // TODO(dougw): Switch to EmbeddedSearchPageVersion after the proper
-  // solution to Issue 232065 has been implemented.
-  return EmbeddedSearchPageVersionHelper() ||
-      IsLocalOnlyInstantExtendedAPIEnabled();
-#endif  // defined(OS_IOS) || defined(OS_ANDROID)
-}
-
-// Determine what embedded search page version to request from the user's
-// default search provider. If 0, the embedded search UI should not be enabled.
-uint64 EmbeddedSearchPageVersion(Profile* profile) {
-  // Disable for incognito. Temporary fix for Issue 232065.
-#if !defined(OS_IOS) && !defined(OS_ANDROID)
-  if (!profile || profile->IsOffTheRecord())
-    return kEmbeddedPageVersionDisabled;
-#endif  // !defined(OS_IOS) && !defined(OS_ANDROID)
-  return EmbeddedSearchPageVersionHelper();
-}
-
-bool IsQueryExtractionEnabled(Profile* profile) {
-  return EmbeddedSearchPageVersion(profile) != kEmbeddedPageVersionDisabled;
-}
-
-bool IsLocalOnlyInstantExtendedAPIEnabled() {
-  RecordInstantExtendedOptInState();
-  const CommandLine* command_line = CommandLine::ForCurrentProcess();
-  if (command_line->HasSwitch(switches::kDisableLocalOnlyInstantExtendedAPI) ||
-      command_line->HasSwitch(switches::kDisableInstantExtendedAPI)) {
-    return false;
-  }
-  if (command_line->HasSwitch(switches::kEnableLocalOnlyInstantExtendedAPI))
-    return true;
-
-  FieldTrialFlags flags;
-  if (GetFieldTrialInfo(
-          base::FieldTrialList::FindFullName(kInstantExtendedFieldTrialName),
-          &flags, NULL)) {
-    return GetBoolValueForFlagWithDefault(kLocalOnlyFlagName, false, flags);
-  }
-  return false;
-}
-
-string16 GetSearchTermsFromURL(Profile* profile, const GURL& in_url) {
-  GURL url(in_url);
+string16 GetSearchTermsFromURL(Profile* profile, const GURL& url) {
   string16 search_terms;
-
   TemplateURL* template_url = GetDefaultSearchProviderTemplateURL(profile);
-  if (!template_url)
-    return string16();
-
-  if (IsCommandLineInstantURL(url))
-    url = CoerceCommandLineURLToTemplateURL(url, template_url->url_ref(),
-                                            kDisableStartMargin);
-
-  if (url.SchemeIsSecure() && template_url->HasSearchTermsReplacementKey(url))
+  if (template_url && IsSuitableURLForInstant(url, template_url))
     template_url->ExtractSearchTermsFromURL(url, &search_terms);
-
   return search_terms;
 }
 
@@ -347,6 +291,15 @@
   if (!entry)
     return string16();
 
+  // Return immediately if the page does not support Instant.
+  const SearchTabHelper* search_tab_helper =
+      SearchTabHelper::FromWebContents(contents);
+  if (search_tab_helper) {
+    const SearchModel* search_model = search_tab_helper->model();
+    if (search_model && search_model->instant_support() == INSTANT_SUPPORT_NO)
+      return string16();
+  }
+
   return GetSearchTermsImpl(contents, entry);
 }
 
@@ -372,11 +325,17 @@
     return false;
 
   Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext());
-  return IsInstantExtendedAPIEnabled() &&
-         IsRenderedInInstantProcess(contents, profile) &&
-         (IsInstantURL(entry->GetVirtualURL(), profile) ||
-          entry->GetVirtualURL() == GetLocalInstantURL(profile)) &&
-         GetSearchTermsImpl(contents, entry).empty();
+  bool is_instant_url = IsInstantURL(entry->GetVirtualURL(), profile);
+  bool is_local_ntp = entry->GetVirtualURL() == GetLocalInstantURL(profile);
+  if (!IsInstantExtendedAPIEnabled() ||
+      !IsRenderedInInstantProcess(contents, profile) ||
+      !(is_instant_url || is_local_ntp)) {
+    return false;
+  }
+
+  bool has_search_terms = !GetSearchTermsImpl(contents, entry).empty();
+  bool is_online_ntp = is_instant_url && !has_search_terms;
+  return is_online_ntp || is_local_ntp;
 }
 
 void RegisterInstantUserPrefs(user_prefs::PrefRegistrySyncable* registry) {
@@ -424,8 +383,8 @@
 }
 
 bool IsInstantCheckboxEnabled(Profile* profile) {
+  RecordInstantExtendedOptInState();
   return IsInstantExtendedAPIEnabled() &&
-         !IsLocalOnlyInstantExtendedAPIEnabled() &&
          DefaultSearchProviderSupportsInstant(profile) &&
          IsSuggestPrefEnabled(profile);
 }
@@ -451,11 +410,6 @@
   if (!IsInstantExtendedAPIEnabled())
     return l10n_util::GetStringUTF16(IDS_INSTANT_CHECKBOX_NO_EXTENDED_API);
 
-  if (IsLocalOnlyInstantExtendedAPIEnabled()) {
-    return l10n_util::GetStringUTF16(
-        IDS_INSTANT_CHECKBOX_LOCAL_ONLY_EXTENDED_API);
-  }
-
   if (!DefaultSearchProviderSupportsInstant(profile)) {
     const TemplateURL* provider = GetDefaultSearchProviderTemplateURL(profile);
     if (!provider) {
@@ -484,37 +438,25 @@
   if (!IsInstantCheckboxEnabled(profile))
     return GURL();
 
-  const bool extended_api_enabled = IsInstantExtendedAPIEnabled();
-
   // In non-extended mode, the checkbox must be checked.
+  const bool extended_api_enabled = IsInstantExtendedAPIEnabled();
   if (!extended_api_enabled && !IsInstantCheckboxChecked(profile))
     return GURL();
 
   TemplateURL* template_url = GetDefaultSearchProviderTemplateURL(profile);
-  CommandLine* cl = CommandLine::ForCurrentProcess();
-  if (cl->HasSwitch(switches::kInstantURL)) {
-    GURL instant_url(cl->GetSwitchValueASCII(switches::kInstantURL));
-    if (extended_api_enabled) {
-      // Extended mode won't work if the search terms replacement key is absent.
-      GURL coerced_url = CoerceCommandLineURLToTemplateURL(
-          instant_url, template_url->instant_url_ref(), start_margin);
-      if (!template_url->HasSearchTermsReplacementKey(coerced_url))
-        return GURL();
-    }
-    return instant_url;
-  }
-
   GURL instant_url =
-      TemplateURLRefToGURL(template_url->instant_url_ref(), start_margin);
-  if (extended_api_enabled && !instant_url.SchemeIsSecure()) {
-    // Extended mode requires HTTPS. Force it if necessary.
-    const std::string secure_scheme = chrome::kHttpsScheme;
-    GURL::Replacements replacements;
-    replacements.SetSchemeStr(secure_scheme);
-    instant_url = instant_url.ReplaceComponents(replacements);
-  }
+      TemplateURLRefToGURL(template_url->instant_url_ref(), start_margin, true);
 
-  return instant_url;
+  // Extended mode requires HTTPS.  Force it unless the base URL was overridden
+  // on the command line, in which case we allow HTTP (see comments on
+  // IsSuitableURLForInstant()).
+  if (!extended_api_enabled || instant_url.SchemeIsSecure() ||
+      google_util::StartsWithCommandLineGoogleBaseURL(instant_url))
+    return instant_url;
+  GURL::Replacements replacements;
+  const std::string secure_scheme(chrome::kHttpsScheme);
+  replacements.SetSchemeStr(secure_scheme);
+  return instant_url.ReplaceComponents(replacements);
 }
 
 GURL GetLocalInstantURL(Profile* profile) {
@@ -538,7 +480,6 @@
   // precedence and allows the trial to not be reported (if it's never queried).
   const CommandLine* command_line = CommandLine::ForCurrentProcess();
   if (command_line->HasSwitch(switches::kDisableInstantExtendedAPI) ||
-      command_line->HasSwitch(switches::kEnableLocalOnlyInstantExtendedAPI) ||
       command_line->HasSwitch(switches::kEnableLocalFirstLoadNTP)) {
     return false;
   }
@@ -555,17 +496,28 @@
   return false;
 }
 
-bool ShouldPreloadLocalOnlyNTP() {
+bool ShouldShowInstantNTP() {
   FieldTrialFlags flags;
   if (GetFieldTrialInfo(
           base::FieldTrialList::FindFullName(kInstantExtendedFieldTrialName),
           &flags, NULL)) {
-    return GetBoolValueForFlagWithDefault(kPreloadLocalOnlyNTPFlagName, false,
-                                          flags);
+    return GetBoolValueForFlagWithDefault(kShowNtpFlagName, true, flags);
   }
   return true;
 }
 
+bool ShouldShowRecentTabsOnNTP() {
+  FieldTrialFlags flags;
+  if (GetFieldTrialInfo(
+          base::FieldTrialList::FindFullName(kInstantExtendedFieldTrialName),
+          &flags, NULL)) {
+    return GetBoolValueForFlagWithDefault(
+        kRecentTabsOnNTPFlagName, false, flags);
+  }
+
+  return false;
+}
+
 bool MatchesOriginAndPath(const GURL& my_url, const GURL& other_url) {
   return MatchesOrigin(my_url, other_url) && my_url.path() == other_url.path();
 }
@@ -614,16 +566,6 @@
   return timeout_sec;
 }
 
-bool IsInstantOverlay(const content::WebContents* contents) {
-  for (chrome::BrowserIterator it; !it.done(); it.Next()) {
-    if (it->instant_controller() &&
-        it->instant_controller()->instant()->GetOverlayContents() == contents) {
-      return true;
-    }
-  }
-  return false;
-}
-
 bool IsPreloadedInstantExtendedNTP(const content::WebContents* contents) {
   for (chrome::BrowserIterator it; !it.done(); it.Next()) {
     if (it->instant_controller() &&
@@ -714,34 +656,13 @@
   return !!GetUInt64ValueForFlagWithDefault(flag, default_value ? 1 : 0, flags);
 }
 
-// Coerces the commandline Instant URL to look like a template URL, so that we
-// can extract search terms from it.
-GURL CoerceCommandLineURLToTemplateURL(const GURL& instant_url,
-                                       const TemplateURLRef& ref,
-                                       int start_margin) {
-  GURL search_url = TemplateURLRefToGURL(ref, start_margin);
-
-  // NOTE(samarth): GURL returns temporaries which we must save because
-  // GURL::Replacements expects the replacements to live until
-  // ReplaceComponents is called.
-  const std::string search_scheme = chrome::kHttpsScheme;
-  const std::string search_host = search_url.host();
-  const std::string search_port = search_url.port();
-
-  GURL::Replacements replacements;
-  replacements.SetSchemeStr(search_scheme);
-  replacements.SetHostStr(search_host);
-  replacements.SetPortStr(search_port);
-  return instant_url.ReplaceComponents(replacements);
-}
-
 bool DefaultSearchProviderSupportsInstant(Profile* profile) {
   TemplateURL* template_url = GetDefaultSearchProviderTemplateURL(profile);
   if (!template_url)
     return false;
 
   GURL instant_url = TemplateURLRefToGURL(template_url->instant_url_ref(),
-                                          kDisableStartMargin);
+                                          kDisableStartMargin, false);
   // Extended mode instant requires a search terms replacement key.
   return instant_url.is_valid() &&
          (!IsInstantExtendedAPIEnabled() ||
@@ -752,19 +673,4 @@
   instant_extended_opt_in_state_gate = false;
 }
 
-bool AreMostVisitedItemsEqual(
-    const std::vector<InstantMostVisitedItem>& items_a,
-    const std::vector<InstantMostVisitedItem>& items_b) {
-  if (items_a.size() != items_b.size())
-    return false;
-
-  for (size_t i = 0; i < items_b.size(); ++i) {
-    if (items_b[i].url != items_a[i].url ||
-        items_b[i].title != items_a[i].title) {
-      return false;
-    }
-  }
-  return true;
-}
-
 }  // namespace chrome
diff --git a/chrome/browser/search/search.h b/chrome/browser/search/search.h
index d8ae0e5..313f164 100644
--- a/chrome/browser/search/search.h
+++ b/chrome/browser/search/search.h
@@ -11,7 +11,6 @@
 
 #include "base/basictypes.h"
 #include "base/strings/string16.h"
-#include "chrome/common/instant_types.h"
 
 class GURL;
 class Profile;
@@ -30,20 +29,12 @@
 namespace chrome {
 
 enum OptInState {
-  // The user has not manually opted in/out of InstantExtended,
-  // either local or regular. The in/out for local or not may
-  // occur concurrently, but only once for each (local or not).
+  // The user has not manually opted in/out of InstantExtended.
   INSTANT_EXTENDED_NOT_SET,
   // The user has opted-in to InstantExtended.
   INSTANT_EXTENDED_OPT_IN,
   // The user has opted-out of InstantExtended.
   INSTANT_EXTENDED_OPT_OUT,
-  // The user has opted-in to Local InstantExtended.
-  INSTANT_EXTENDED_OPT_IN_LOCAL,
-  // The user has opted-out of Local InstantExtended.
-  INSTANT_EXTENDED_OPT_OUT_LOCAL,
-  // The user has opted-out of both Local and regular InstantExtended.
-  INSTANT_EXTENDED_OPT_OUT_BOTH,
   INSTANT_EXTENDED_OPT_IN_STATE_ENUM_COUNT,
 };
 
@@ -55,16 +46,12 @@
 bool IsInstantExtendedAPIEnabled();
 
 // Returns the value to pass to the &espv CGI parameter when loading the
-// embedded search page from the user's default search provider. Will be
-// 0 if the Instant Extended API is not enabled, or if the local-only Instant
-// Extended API is enabled, or if in incognito mode.
-uint64 EmbeddedSearchPageVersion(Profile* profile);
+// embedded search page from the user's default search provider. Returns 0 if
+// the Instant Extended API is not enabled.
+uint64 EmbeddedSearchPageVersion();
 
 // Returns whether query extraction is enabled.
-bool IsQueryExtractionEnabled(Profile* profile);
-
-// Returns whether the local-only version of Instant Extended API is enabled.
-bool IsLocalOnlyInstantExtendedAPIEnabled();
+bool IsQueryExtractionEnabled();
 
 // Extracts and returns search terms from |url|. Returns empty string if the URL
 // is not secure or doesn't have a search term replacement key.  Does not
@@ -149,8 +136,12 @@
 // to always show the remote NTP on browser startup.
 bool ShouldPreferRemoteNTPOnStartup();
 
-// Should the Instant NTP be preloaded if local-only InstantExtended is enabled.
-bool ShouldPreloadLocalOnlyNTP();
+// Returns true if the Instant NTP should be shown and false if not.
+bool ShouldShowInstantNTP();
+
+// Returns true if the recent tabs link should be shown on the local NTP in
+// field trials.
+bool ShouldShowRecentTabsOnNTP();
 
 // Returns true if |my_url| matches |other_url|.
 bool MatchesOriginAndPath(const GURL& my_url, const GURL& other_url);
@@ -177,9 +168,6 @@
 // InstantLoader.
 int GetInstantLoaderStalenessTimeoutSec();
 
-// Returns true if |contents| corresponds to an Instant overlay.
-bool IsInstantOverlay(const content::WebContents* contents);
-
 // Returns true if |contents| corresponds to a preloaded instant extended NTP.
 bool IsPreloadedInstantExtendedNTP(const content::WebContents* contents);
 
@@ -227,12 +215,6 @@
                                     bool default_value,
                                     const FieldTrialFlags& flags);
 
-// Coerces the commandline Instant URL to look like a template URL, so that we
-// can extract search terms from it. Exposed for testing only.
-GURL CoerceCommandLineURLToTemplateURL(const GURL& instant_url,
-                                       const TemplateURLRef& ref,
-                                       int start_margin);
-
 // Returns whether the default search provider has a valid Instant URL in its
 // template. Exposed for testing only.
 bool DefaultSearchProviderSupportsInstant(Profile* profile);
@@ -241,11 +223,6 @@
 // once.
 void ResetInstantExtendedOptInStateGateForTest();
 
-// Returns true if |items_a| and |items_b| are equal.
-bool AreMostVisitedItemsEqual(
-    const std::vector<InstantMostVisitedItem>& items_a,
-    const std::vector<InstantMostVisitedItem>& items_b);
-
 }  // namespace chrome
 
 #endif  // CHROME_BROWSER_SEARCH_SEARCH_H_
diff --git a/chrome/browser/search/search_unittest.cc b/chrome/browser/search/search_unittest.cc
index d730621..91c6cfc 100644
--- a/chrome/browser/search/search_unittest.cc
+++ b/chrome/browser/search/search_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/metrics/statistics_recorder.h"
 #include "base/prefs/pref_service.h"
 #include "chrome/browser/search/search.h"
+#include "chrome/browser/search_engines/search_terms_data.h"
 #include "chrome/browser/search_engines/template_url_service.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
@@ -80,17 +81,14 @@
   EXPECT_EQ(ZERO, flags.size());
 }
 
-class InstantExtendedAPIEnabledTest : public BrowserWithTestWindowTest {
+class InstantExtendedAPIEnabledTest : public testing::Test {
  public:
   InstantExtendedAPIEnabledTest() : histogram_(NULL) {
   }
  protected:
-  virtual void SetUp() OVERRIDE {
-    BrowserWithTestWindowTest::SetUp();
-
+  virtual void SetUp() {
     field_trial_list_.reset(new base::FieldTrialList(
         new metrics::SHA1EntropyProvider("42")));
-
     base::StatisticsRecorder::Initialize();
     ResetInstantExtendedOptInStateGateForTest();
     previous_metrics_count_.resize(INSTANT_EXTENDED_OPT_IN_STATE_ENUM_COUNT, 0);
@@ -144,135 +142,31 @@
 TEST_F(InstantExtendedAPIEnabledTest, EnabledViaCommandLineFlag) {
   GetCommandLine()->AppendSwitch(switches::kEnableInstantExtendedAPI);
   EXPECT_TRUE(IsInstantExtendedAPIEnabled());
-  EXPECT_FALSE(IsLocalOnlyInstantExtendedAPIEnabled());
 #if defined(OS_IOS) || defined(OS_ANDROID)
-  EXPECT_EQ(1ul, EmbeddedSearchPageVersion(profile()));
+  EXPECT_EQ(1ul, EmbeddedSearchPageVersion());
 #else
-  EXPECT_EQ(2ul, EmbeddedSearchPageVersion(profile()));
+  EXPECT_EQ(2ul, EmbeddedSearchPageVersion());
 #endif
   ValidateMetrics(INSTANT_EXTENDED_OPT_IN);
 }
 
 TEST_F(InstantExtendedAPIEnabledTest, EnabledViaFinchFlag) {
-  ASSERT_TRUE(base::FieldTrialList::CreateTrialsFromString(
-      "InstantExtended/Group1 espv:42/"));
+  ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("InstantExtended",
+                                                     "Group1 espv:42"));
   EXPECT_TRUE(IsInstantExtendedAPIEnabled());
-  EXPECT_FALSE(IsLocalOnlyInstantExtendedAPIEnabled());
-  EXPECT_EQ(42ul, EmbeddedSearchPageVersion(profile()));
+  EXPECT_EQ(42ul, EmbeddedSearchPageVersion());
   ValidateMetrics(INSTANT_EXTENDED_NOT_SET);
 }
 
 TEST_F(InstantExtendedAPIEnabledTest, DisabledViaCommandLineFlag) {
   GetCommandLine()->AppendSwitch(switches::kDisableInstantExtendedAPI);
-  ASSERT_TRUE(base::FieldTrialList::CreateTrialsFromString(
-      "InstantExtended/Group1 espv:2/"));
+  ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("InstantExtended",
+                                                     "Group1 espv:2"));
   EXPECT_FALSE(IsInstantExtendedAPIEnabled());
-  EXPECT_FALSE(IsLocalOnlyInstantExtendedAPIEnabled());
-  EXPECT_EQ(0ul, EmbeddedSearchPageVersion(profile()));
+  EXPECT_EQ(0ul, EmbeddedSearchPageVersion());
   ValidateMetrics(INSTANT_EXTENDED_OPT_OUT);
 }
 
-TEST_F(InstantExtendedAPIEnabledTest, LocalOnlyEnabledViaCommandLineFlag) {
-  GetCommandLine()->AppendSwitch(switches::kEnableLocalOnlyInstantExtendedAPI);
-  EXPECT_TRUE(IsInstantExtendedAPIEnabled());
-  EXPECT_TRUE(IsLocalOnlyInstantExtendedAPIEnabled());
-  EXPECT_EQ(0ul, EmbeddedSearchPageVersion(profile()));
-  ValidateMetrics(INSTANT_EXTENDED_OPT_IN_LOCAL);
-}
-
-TEST_F(InstantExtendedAPIEnabledTest, LocalOnlyEnabledViaFinch) {
-  ASSERT_TRUE(base::FieldTrialList::CreateTrialsFromString(
-      "InstantExtended/Group1 local_only:1/"));
-  EXPECT_TRUE(IsInstantExtendedAPIEnabled());
-  EXPECT_TRUE(IsLocalOnlyInstantExtendedAPIEnabled());
-  EXPECT_EQ(0ul, EmbeddedSearchPageVersion(profile()));
-  ValidateMetrics(INSTANT_EXTENDED_NOT_SET);
-}
-
-TEST_F(InstantExtendedAPIEnabledTest, BothLocalAndRegularOptOutCommandLine) {
-  GetCommandLine()->AppendSwitch(switches::kDisableLocalOnlyInstantExtendedAPI);
-  GetCommandLine()->AppendSwitch(switches::kDisableInstantExtendedAPI);
-  EXPECT_FALSE(IsInstantExtendedAPIEnabled());
-  EXPECT_FALSE(IsLocalOnlyInstantExtendedAPIEnabled());
-  ValidateMetrics(INSTANT_EXTENDED_OPT_OUT_BOTH);
-}
-
-TEST_F(InstantExtendedAPIEnabledTest, BothLocalAndRegularOptInCommandLine) {
-  GetCommandLine()->AppendSwitch(switches::kEnableLocalOnlyInstantExtendedAPI);
-  GetCommandLine()->AppendSwitch(switches::kEnableInstantExtendedAPI);
-  EXPECT_TRUE(IsInstantExtendedAPIEnabled());
-  EXPECT_TRUE(IsLocalOnlyInstantExtendedAPIEnabled());
-  ValidateMetrics(INSTANT_EXTENDED_OPT_IN_LOCAL);
-}
-
-TEST_F(InstantExtendedAPIEnabledTest,
-       LocalOnlyCommandLineTrumpedByCommandLine) {
-  GetCommandLine()->AppendSwitch(switches::kEnableLocalOnlyInstantExtendedAPI);
-  GetCommandLine()->AppendSwitch(switches::kDisableInstantExtendedAPI);
-  EXPECT_FALSE(IsInstantExtendedAPIEnabled());
-  EXPECT_FALSE(IsLocalOnlyInstantExtendedAPIEnabled());
-  EXPECT_EQ(0ul, EmbeddedSearchPageVersion(profile()));
-  ValidateMetrics(INSTANT_EXTENDED_OPT_OUT);
-}
-
-TEST_F(InstantExtendedAPIEnabledTest, LocalOnlyCommandLineTrumpsFinch) {
-  GetCommandLine()->AppendSwitch(switches::kEnableLocalOnlyInstantExtendedAPI);
-  ASSERT_TRUE(base::FieldTrialList::CreateTrialsFromString(
-      "InstantExtended/Group1 espv:2/"));
-  EXPECT_TRUE(IsInstantExtendedAPIEnabled());
-  EXPECT_TRUE(IsLocalOnlyInstantExtendedAPIEnabled());
-  EXPECT_EQ(0ul, EmbeddedSearchPageVersion(profile()));
-  ValidateMetrics(INSTANT_EXTENDED_OPT_IN_LOCAL);
-}
-
-TEST_F(InstantExtendedAPIEnabledTest, LocalOnlyFinchTrumpedByCommandLine) {
-  ASSERT_TRUE(base::FieldTrialList::CreateTrialsFromString(
-      "InstantExtended/Group1 local_only:1/"));
-  GetCommandLine()->AppendSwitch(switches::kDisableInstantExtendedAPI);
-  EXPECT_FALSE(IsInstantExtendedAPIEnabled());
-  EXPECT_FALSE(IsLocalOnlyInstantExtendedAPIEnabled());
-  EXPECT_EQ(0ul, EmbeddedSearchPageVersion(profile()));
-  ValidateMetrics(INSTANT_EXTENDED_OPT_OUT);
-}
-
-TEST_F(InstantExtendedAPIEnabledTest, LocalOnlyFinchTrumpsFinch) {
-  ASSERT_TRUE(base::FieldTrialList::CreateTrialsFromString(
-      "InstantExtended/Group1 espv:1 local_only:1/"));
-  EXPECT_TRUE(IsInstantExtendedAPIEnabled());
-  EXPECT_TRUE(IsLocalOnlyInstantExtendedAPIEnabled());
-  EXPECT_EQ(0ul, EmbeddedSearchPageVersion(profile()));
-  ValidateMetrics(INSTANT_EXTENDED_NOT_SET);
-}
-
-TEST_F(InstantExtendedAPIEnabledTest, LocalOnlyDisabledViaCommandLineFlag) {
-  GetCommandLine()->AppendSwitch(switches::kDisableLocalOnlyInstantExtendedAPI);
-  ASSERT_TRUE(base::FieldTrialList::CreateTrialsFromString(
-      "InstantExtended/Group1 espv:2/"));
-  EXPECT_TRUE(IsInstantExtendedAPIEnabled());
-  EXPECT_FALSE(IsLocalOnlyInstantExtendedAPIEnabled());
-  EXPECT_EQ(2ul, EmbeddedSearchPageVersion(profile()));
-  ValidateMetrics(INSTANT_EXTENDED_OPT_OUT_LOCAL);
-}
-
-class ShouldPreloadLocalOnlyNTPtest : public InstantExtendedAPIEnabledTest {
-};
-
-TEST_F(ShouldPreloadLocalOnlyNTPtest, PreloadByDefault) {
-  EXPECT_TRUE(ShouldPreloadLocalOnlyNTP());
-}
-
-TEST_F(ShouldPreloadLocalOnlyNTPtest, SuppressPreload) {
-  ASSERT_TRUE(base::FieldTrialList::CreateTrialsFromString(
-      "InstantExtended/Group1 preload_local_only_ntp:0/"));
-  EXPECT_FALSE(ShouldPreloadLocalOnlyNTP());
-}
-
-TEST_F(ShouldPreloadLocalOnlyNTPtest, ForcePreload) {
-  ASSERT_TRUE(base::FieldTrialList::CreateTrialsFromString(
-      "InstantExtended/Group1 preload_local_only_ntp:1/"));
-  EXPECT_TRUE(ShouldPreloadLocalOnlyNTP());
-}
-
 class SearchTest : public BrowserWithTestWindowTest {
  protected:
   virtual void SetUp() OVERRIDE {
@@ -398,17 +292,6 @@
   }
 }
 
-TEST_F(SearchTest, CoerceCommandLineURLToTemplateURL) {
-  TemplateURL* template_url =
-      TemplateURLServiceFactory::GetForProfile(profile())->
-          GetDefaultSearchProvider();
-  EXPECT_EQ(
-      GURL("https://foo.com/dev?bar=bar#bar=bar"),
-      CoerceCommandLineURLToTemplateURL(
-          GURL("http://myserver.com:9000/dev?bar=bar#bar=bar"),
-          template_url->instant_url_ref(), kDisableStartMargin));
-}
-
 const SearchTestCase kInstantNTPTestCases[] = {
   {"https://foo.com/instant?strk",         true,  "Valid Instant URL"},
   {"https://foo.com/instant#strk",         true,  "Valid Instant URL"},
@@ -429,16 +312,6 @@
   {"https://bar.com/instant?strk=1",       false, "Random non-search page"},
 };
 
-TEST_F(SearchTest, InstantExtendedEmbeddedSearchDisabledForIncognito) {
-#if !defined(OS_IOS) && !defined(OS_ANDROID)
-  EnableInstantExtendedAPIForTesting();
-  profile()->set_incognito(true);
-  EXPECT_TRUE(IsInstantExtendedAPIEnabled());
-  EXPECT_EQ(0ul, EmbeddedSearchPageVersion(profile()));
-  EXPECT_FALSE(IsQueryExtractionEnabled(profile()));
-#endif  // !defined(OS_IOS) && !defined(OS_ANDROID)
-}
-
 TEST_F(SearchTest, InstantNTPExtendedEnabled) {
   EnableInstantExtendedAPIForTesting();
   AddTab(browser(), GURL("chrome://blank"));
@@ -517,19 +390,6 @@
   EXPECT_EQ(GURL("https://foo.com/instant?foo=foo#foo=foo&strk"),
             GetInstantURL(profile(), kDisableStartMargin));
 
-  // Override the Instant URL on the commandline. Oops, forgot "strk".
-  CommandLine::ForCurrentProcess()->AppendSwitchASCII(
-      switches::kInstantURL,
-      "http://myserver.com:9000/dev?bar=bar#bar=bar");
-  EXPECT_EQ(GURL(), GetInstantURL(profile(), kDisableStartMargin));
-
-  // Override with "strk". For fun, put it in the query, instead of the ref.
-  CommandLine::ForCurrentProcess()->AppendSwitchASCII(
-      switches::kInstantURL,
-      "http://myserver.com:9000/dev?bar=bar&strk#bar=bar");
-  EXPECT_EQ(GURL("http://myserver.com:9000/dev?bar=bar&strk#bar=bar"),
-            GetInstantURL(profile(), kDisableStartMargin));
-
   // Disable suggest. No Instant URL.
   profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled, false);
   EXPECT_EQ(GURL(), GetInstantURL(profile(), kDisableStartMargin));
@@ -573,15 +433,6 @@
   profile()->GetPrefs()->SetBoolean(prefs::kSearchInstantEnabled, false);
   EXPECT_TRUE(DefaultSearchProviderSupportsInstant(profile()));
 
-  // Override the Instant URL on the commandline. Oops, forgot "strk".
-  CommandLine::ForCurrentProcess()->AppendSwitchASCII(
-      switches::kInstantURL,
-      "http://myserver.com:9000/dev?bar=bar#bar=bar");
-  EXPECT_EQ(GURL(), GetInstantURL(profile(), kDisableStartMargin));
-
-  // Check that command line overrides don't affect the default search provider.
-  EXPECT_TRUE(DefaultSearchProviderSupportsInstant(profile()));
-
   // Disable suggest. No Instant URL.
   profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled, false);
   EXPECT_EQ(GURL(), GetInstantURL(profile(), kDisableStartMargin));
@@ -600,8 +451,8 @@
   EnableInstantExtendedAPIForTesting();
 
   // Enable Instant.
-  ASSERT_TRUE(base::FieldTrialList::CreateTrialsFromString(
-      "InstantExtended/Group1 allow_instant:1/"));
+  ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("InstantExtended",
+                                                     "Group1 allow_instant:1"));
   ASSERT_TRUE(IsInstantCheckboxVisible());
 
   // Enable suggest.
@@ -691,5 +542,55 @@
   EXPECT_FALSE(IsInstantCheckboxChecked(profile()));
 }
 
+TEST_F(SearchTest, CommandLineOverrides) {
+  EnableInstantExtendedAPIForTesting();
+  profile()->GetPrefs()->SetBoolean(prefs::kSearchInstantEnabled, true);
+
+  // GetLocalInstantURL() should default to the non-Google local NTP.
+  SetSearchProvider(false);
+  GURL local_instant_url(GetLocalInstantURL(profile()));
+  EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl), local_instant_url);
+
+  TemplateURLService* template_url_service =
+      TemplateURLServiceFactory::GetForProfile(profile());
+  TemplateURLData data;
+  data.SetURL("{google:baseURL}search?q={searchTerms}");
+  data.instant_url = "{google:baseURL}webhp?strk";
+  data.search_terms_replacement_key = "strk";
+  TemplateURL* template_url = new TemplateURL(profile(), data);
+  // Takes ownership of |template_url|.
+  template_url_service->Add(template_url);
+  template_url_service->SetDefaultSearchProvider(template_url);
+
+  // By default, Instant Extended forces the instant URL to be HTTPS, so even if
+  // we set a Google base URL that is HTTP, we should get an HTTPS URL.
+  UIThreadSearchTermsData::SetGoogleBaseURL("http://www.foo.com/");
+  GURL instant_url(GetInstantURL(profile(), kDisableStartMargin));
+  ASSERT_TRUE(instant_url.is_valid());
+  EXPECT_EQ("https://www.foo.com/webhp?strk", instant_url.spec());
+
+  // However, if the Google base URL is specified on the command line, the
+  // instant URL should just use it, even if it's HTTP.
+  UIThreadSearchTermsData::SetGoogleBaseURL(std::string());
+  CommandLine::ForCurrentProcess()->AppendSwitchASCII(switches::kGoogleBaseURL,
+                                                      "http://www.bar.com/");
+  instant_url = GetInstantURL(profile(), kDisableStartMargin);
+  ASSERT_TRUE(instant_url.is_valid());
+  EXPECT_EQ("http://www.bar.com/webhp?strk", instant_url.spec());
+
+  // Similarly, setting a Google base URL on the command line should allow you
+  // to get the Google version of the local NTP, even though search provider's
+  // URL doesn't contain "google".
+  local_instant_url = GetLocalInstantURL(profile());
+  EXPECT_EQ(GURL(chrome::kChromeSearchLocalGoogleNtpUrl), local_instant_url);
+
+  // If we specify extra search query params, they should be inserted into the
+  // query portion of the instant URL.
+  CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+      switches::kExtraSearchQueryParams, "a=b");
+  instant_url = GetInstantURL(profile(), kDisableStartMargin);
+  ASSERT_TRUE(instant_url.is_valid());
+  EXPECT_EQ("http://www.bar.com/webhp?a=b&strk", instant_url.spec());
+}
 
 }  // namespace chrome
diff --git a/chrome/browser/search_engines/OWNERS b/chrome/browser/search_engines/OWNERS
index ac2ccb7..00102bf 100644
--- a/chrome/browser/search_engines/OWNERS
+++ b/chrome/browser/search_engines/OWNERS
@@ -1,3 +1,5 @@
 pkasting@chromium.org
 sky@chromium.org
-stevet@chromium.org
\ No newline at end of file
+stevet@chromium.org
+
+per-file *_android.*=yfriedman@chromium.org
\ No newline at end of file
diff --git a/chrome/browser/search_engines/prepopulated_engines.json b/chrome/browser/search_engines/prepopulated_engines.json
index 7aac2ff..5b16823 100644
--- a/chrome/browser/search_engines/prepopulated_engines.json
+++ b/chrome/browser/search_engines/prepopulated_engines.json
@@ -26,7 +26,7 @@
 
     // Increment this if you change the data in ways that mean users with
     // existing data should get a new version.
-    "kCurrentDataVersion": 56
+    "kCurrentDataVersion": 57
   },
 
   // The following engines are included in country lists and are added to the
@@ -848,7 +848,7 @@
       "keyword": "google.com",
       "favicon_url": "http://www.google.com/favicon.ico",
       "search_url": "{google:baseURL}search?q={searchTerms}&{google:RLZ}{google:originalQueryForSuggestion}{google:assistedQueryStats}{google:searchFieldtrialParameter}{google:searchClient}{google:sourceId}{google:instantExtendedEnabledParameter}{google:omniboxStartMarginParameter}ie={inputEncoding}",
-      "suggest_url": "{google:baseSuggestURL}search?{google:searchFieldtrialParameter}client=chrome&q={searchTerms}&{google:cursorPosition}{google:zeroPrefixUrl}sugkey={google:suggestAPIKeyParameter}",
+      "suggest_url": "{google:baseSuggestURL}search?{google:searchFieldtrialParameter}client={google:suggestClient}&q={searchTerms}&{google:cursorPosition}{google:zeroPrefixUrl}sugkey={google:suggestAPIKeyParameter}",
       "instant_url": "{google:baseURL}webhp?sourceid=chrome-instant&{google:RLZ}{google:instantEnabledParameter}{google:instantExtendedEnabledParameter}{google:ntpIsThemedParameter}{google:omniboxStartMarginParameter}ie={inputEncoding}",
       "alternate_urls": [
         "{google:baseURL}#q={searchTerms}",
diff --git a/chrome/browser/search_engines/search_provider_install_state_message_filter.cc b/chrome/browser/search_engines/search_provider_install_state_message_filter.cc
index 8dd0d78..0704140 100644
--- a/chrome/browser/search_engines/search_provider_install_state_message_filter.cc
+++ b/chrome/browser/search_engines/search_provider_install_state_message_filter.cc
@@ -12,7 +12,7 @@
 #include "content/public/browser/notification_types.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 using content::BrowserThread;
 
diff --git a/chrome/browser/search_engines/search_terms_data.cc b/chrome/browser/search_engines/search_terms_data.cc
index 1d1b3d8..32b6100 100644
--- a/chrome/browser/search_engines/search_terms_data.cc
+++ b/chrome/browser/search_engines/search_terms_data.cc
@@ -19,7 +19,7 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "content/public/browser/browser_thread.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 #if defined(ENABLE_RLZ)
 #include "chrome/browser/rlz/rlz.h"
@@ -38,11 +38,6 @@
 }
 
 std::string SearchTermsData::GoogleBaseSuggestURLValue() const {
-  std::string base_suggest_url = CommandLine::ForCurrentProcess()->
-      GetSwitchValueASCII(switches::kGoogleBaseSuggestURL);
-  if (!base_suggest_url.empty())
-    return base_suggest_url;
-
   // Start with the Google base URL.
   const GURL base_url(GoogleBaseURLValue());
   DCHECK(base_url.is_valid());
@@ -74,6 +69,10 @@
   return std::string();
 }
 
+std::string SearchTermsData::GetSuggestClient() const {
+  return std::string();
+}
+
 std::string SearchTermsData::InstantEnabledParam() const {
   return std::string();
 }
@@ -100,6 +99,10 @@
       BrowserThread::CurrentlyOn(BrowserThread::UI));
   if (google_base_url_)
     return *google_base_url_;
+  std::string base_url = CommandLine::ForCurrentProcess()->
+      GetSwitchValueASCII(switches::kGoogleBaseURL);
+  if (!base_url.empty())
+    return base_url;
   return profile_ ? GoogleURLTracker::GoogleURL(profile_).spec() :
       SearchTermsData::GoogleBaseURLValue();
 }
@@ -141,6 +144,12 @@
 }
 #endif
 
+std::string UIThreadSearchTermsData::GetSuggestClient() const {
+  DCHECK(!BrowserThread::IsWellKnownThread(BrowserThread::UI) ||
+      BrowserThread::CurrentlyOn(BrowserThread::UI));
+  return chrome::IsInstantExtendedAPIEnabled() ? "chrome-omni" : "chrome";
+}
+
 std::string UIThreadSearchTermsData::InstantEnabledParam() const {
   DCHECK(!BrowserThread::IsWellKnownThread(BrowserThread::UI) ||
          BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -150,8 +159,7 @@
 std::string UIThreadSearchTermsData::InstantExtendedEnabledParam() const {
   DCHECK(!BrowserThread::IsWellKnownThread(BrowserThread::UI) ||
          BrowserThread::CurrentlyOn(BrowserThread::UI));
-  uint64 instant_extended_api_version =
-      chrome::EmbeddedSearchPageVersion(profile_);
+  uint64 instant_extended_api_version = chrome::EmbeddedSearchPageVersion();
   if (instant_extended_api_version) {
     return std::string(google_util::kInstantExtendedAPIParam) + "=" +
         base::Uint64ToString(instant_extended_api_version) + "&";
diff --git a/chrome/browser/search_engines/search_terms_data.h b/chrome/browser/search_engines/search_terms_data.h
index 2a13fc4..cbd1e7d 100644
--- a/chrome/browser/search_engines/search_terms_data.h
+++ b/chrome/browser/search_engines/search_terms_data.h
@@ -40,6 +40,10 @@
   // implementation returns the empty string.
   virtual std::string GetSearchClient() const;
 
+  // The client parameter passed with Google suggest requests.  This
+  // implementation returns the empty string.
+  virtual std::string GetSuggestClient() const;
+
   // Returns a string indicating whether Instant (in the visible-preview mode)
   // is enabled, suitable for adding as a query string param to the homepage
   // (instant_url) request. Returns an empty string if Instant is disabled, or
@@ -78,6 +82,7 @@
   virtual std::string GetApplicationLocale() const OVERRIDE;
   virtual string16 GetRlzParameterValue() const OVERRIDE;
   virtual std::string GetSearchClient() const OVERRIDE;
+  virtual std::string GetSuggestClient() const OVERRIDE;
   virtual std::string InstantEnabledParam() const OVERRIDE;
   virtual std::string InstantExtendedEnabledParam() const OVERRIDE;
   virtual std::string NTPIsThemedParam() const OVERRIDE;
diff --git a/chrome/browser/search_engines/template_url.cc b/chrome/browser/search_engines/template_url.cc
index 686429c..1ccf6dc 100644
--- a/chrome/browser/search_engines/template_url.cc
+++ b/chrome/browser/search_engines/template_url.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/search_engines/template_url.h"
 
+#include "base/command_line.h"
 #include "base/format_macros.h"
 #include "base/guid.h"
 #include "base/i18n/case_conversion.h"
@@ -18,6 +19,7 @@
 #include "chrome/browser/google/google_util.h"
 #include "chrome/browser/search_engines/search_terms_data.h"
 #include "chrome/browser/search_engines/template_url_service.h"
+#include "chrome/common/chrome_switches.h"
 #include "chrome/common/url_constants.h"
 #include "extensions/common/constants.h"
 #include "google_apis/google_api_keys.h"
@@ -72,6 +74,7 @@
     "google:searchFieldtrialParameter";
 const char kGoogleSourceIdParameter[] = "google:sourceId";
 const char kGoogleSuggestAPIKeyParameter[] = "google:suggestAPIKeyParameter";
+const char kGoogleSuggestClient[] = "google:suggestClient";
 const char kGoogleZeroPrefixUrlParameter[] = "google:zeroPrefixUrl";
 
 // Same as kSearchTermsParameter, with no escaping.
@@ -154,7 +157,8 @@
     : search_terms(search_terms),
       accepted_suggestion(NO_SUGGESTIONS_AVAILABLE),
       cursor_position(string16::npos),
-      omnibox_start_margin(-1) {
+      omnibox_start_margin(-1),
+      append_extra_query_params(false) {
 }
 
 TemplateURLRef::SearchTermsArgs::~SearchTermsArgs() {
@@ -226,155 +230,21 @@
   if (!valid_)
     return std::string();
 
-  if (replacements_.empty())
-    return parsed_url_;
+  std::string url(HandleReplacements(search_terms_args, search_terms_data));
 
-  // Determine if the search terms are in the query or before. We're escaping
-  // space as '+' in the former case and as '%20' in the latter case.
-  bool is_in_query = true;
-  for (Replacements::iterator i = replacements_.begin();
-       i != replacements_.end(); ++i) {
-    if (i->type == SEARCH_TERMS) {
-      string16::size_type query_start = parsed_url_.find('?');
-      is_in_query = query_start != string16::npos &&
-          (static_cast<string16::size_type>(i->index) > query_start);
-      break;
-    }
-  }
-
-  std::string input_encoding;
-  string16 encoded_terms;
-  string16 encoded_original_query;
-  owner_->EncodeSearchTerms(search_terms_args, is_in_query, &input_encoding,
-      &encoded_terms, &encoded_original_query);
-
-  std::string url = parsed_url_;
-
-  // replacements_ is ordered in ascending order, as such we need to iterate
-  // from the back.
-  for (Replacements::reverse_iterator i = replacements_.rbegin();
-       i != replacements_.rend(); ++i) {
-    switch (i->type) {
-      case ENCODING:
-        url.insert(i->index, input_encoding);
-        break;
-
-      case GOOGLE_ASSISTED_QUERY_STATS:
-        if (!search_terms_args.assisted_query_stats.empty()) {
-          // Get the base URL without substituting AQS to avoid infinite
-          // recursion.  We need the URL to find out if it meets all
-          // AQS requirements (e.g. HTTPS protocol check).
-          // See TemplateURLRef::SearchTermsArgs for more details.
-          SearchTermsArgs search_terms_args_without_aqs(search_terms_args);
-          search_terms_args_without_aqs.assisted_query_stats.clear();
-          GURL base_url(ReplaceSearchTermsUsingTermsData(
-              search_terms_args_without_aqs, search_terms_data));
-          if (base_url.SchemeIs(chrome::kHttpsScheme)) {
-            url.insert(i->index,
-                       "aqs=" + search_terms_args.assisted_query_stats + "&");
-          }
-        }
-        break;
-
-      case GOOGLE_BASE_URL:
-        url.insert(i->index, search_terms_data.GoogleBaseURLValue());
-        break;
-
-      case GOOGLE_BASE_SUGGEST_URL:
-        url.insert(i->index, search_terms_data.GoogleBaseSuggestURLValue());
-        break;
-
-      case GOOGLE_CURSOR_POSITION:
-        if (search_terms_args.cursor_position != string16::npos)
-          url.insert(i->index,
-                     base::StringPrintf("cp=%" PRIuS "&",
-                                        search_terms_args.cursor_position));
-        break;
-
-      case GOOGLE_INSTANT_ENABLED:
-        url.insert(i->index, search_terms_data.InstantEnabledParam());
-        break;
-
-      case GOOGLE_INSTANT_EXTENDED_ENABLED:
-        url.insert(i->index, search_terms_data.InstantExtendedEnabledParam());
-        break;
-
-      case GOOGLE_NTP_IS_THEMED:
-        url.insert(i->index, search_terms_data.NTPIsThemedParam());
-        break;
-
-      case GOOGLE_OMNIBOX_START_MARGIN:
-        if (search_terms_args.omnibox_start_margin >= 0) {
-          url.insert(i->index, "es_sm=" +
-              base::IntToString(search_terms_args.omnibox_start_margin) + "&");
-        }
-        break;
-
-      case GOOGLE_ORIGINAL_QUERY_FOR_SUGGESTION:
-        if (search_terms_args.accepted_suggestion >= 0 ||
-            !search_terms_args.assisted_query_stats.empty()) {
-          url.insert(i->index, "oq=" + UTF16ToUTF8(encoded_original_query) +
-                               "&");
-        }
-        break;
-
-      case GOOGLE_RLZ: {
-        // On platforms that don't have RLZ, we still want this branch
-        // to happen so that we replace the RLZ template with the
-        // empty string.  (If we don't handle this case, we hit a
-        // NOTREACHED below.)
-        string16 rlz_string = search_terms_data.GetRlzParameterValue();
-        if (!rlz_string.empty()) {
-          url.insert(i->index, "rlz=" + UTF16ToUTF8(rlz_string) + "&");
-        }
-        break;
-      }
-
-      case GOOGLE_SEARCH_CLIENT: {
-        std::string client = search_terms_data.GetSearchClient();
-        if (!client.empty())
-          url.insert(i->index, "client=" + client + "&");
-        break;
-      }
-
-      case GOOGLE_SEARCH_FIELDTRIAL_GROUP:
-        // We are not currently running any fieldtrials that modulate the search
-        // url.  If we do, then we'd have some conditional insert such as:
-        // url.insert(i->index, used_www ? "gcx=w&" : "gcx=c&");
-        break;
-
-      case GOOGLE_UNESCAPED_SEARCH_TERMS: {
-        std::string unescaped_terms;
-        base::UTF16ToCodepage(search_terms_args.search_terms,
-                              input_encoding.c_str(),
-                              base::OnStringConversionError::SKIP,
-                              &unescaped_terms);
-        url.insert(i->index, std::string(unescaped_terms.begin(),
-                                         unescaped_terms.end()));
-        break;
-      }
-
-      case GOOGLE_ZERO_PREFIX_URL:
-        if (!search_terms_args.zero_prefix_url.empty()) {
-          const std::string& escaped_zero_prefix_url =
-              net::EscapeQueryParamValue(search_terms_args.zero_prefix_url,
-                                         true);
-          url.insert(i->index, "url=" + escaped_zero_prefix_url + "&");
-        }
-
-        break;
-
-      case LANGUAGE:
-        url.insert(i->index, search_terms_data.GetApplicationLocale());
-        break;
-
-      case SEARCH_TERMS:
-        url.insert(i->index, UTF16ToUTF8(encoded_terms));
-        break;
-
-      default:
-        NOTREACHED();
-        break;
+  // If the user specified additional query params on the command line, add
+  // them.
+  if (search_terms_args.append_extra_query_params) {
+    std::string query_params(CommandLine::ForCurrentProcess()->
+        GetSwitchValueASCII(switches::kExtraSearchQueryParams));
+    GURL gurl(url);
+    if (!query_params.empty() && gurl.is_valid()) {
+      GURL::Replacements replacements;
+      const std::string existing_query_params(gurl.query());
+      if (!existing_query_params.empty())
+        query_params += "&" + existing_query_params;
+      replacements.SetQueryStr(query_params);
+      return gurl.ReplaceComponents(replacements).possibly_invalid_spec();
     }
   }
 
@@ -606,6 +476,8 @@
     replacements->push_back(Replacement(GOOGLE_SEARCH_CLIENT, start));
   } else if (parameter == kGoogleSearchFieldtrialParameter) {
     replacements->push_back(Replacement(GOOGLE_SEARCH_FIELDTRIAL_GROUP, start));
+  } else if (parameter == kGoogleSuggestClient) {
+    replacements->push_back(Replacement(GOOGLE_SUGGEST_CLIENT, start));
   } else if (parameter == kGoogleZeroPrefixUrlParameter) {
     replacements->push_back(Replacement(GOOGLE_ZERO_PREFIX_URL, start));
   } else if (parameter == kGoogleSuggestAPIKeyParameter) {
@@ -726,6 +598,168 @@
   path_ = url.path();
 }
 
+std::string TemplateURLRef::HandleReplacements(
+    const SearchTermsArgs& search_terms_args,
+    const SearchTermsData& search_terms_data) const {
+  if (replacements_.empty())
+    return parsed_url_;
+
+  // Determine if the search terms are in the query or before. We're escaping
+  // space as '+' in the former case and as '%20' in the latter case.
+  bool is_in_query = true;
+  for (Replacements::iterator i = replacements_.begin();
+       i != replacements_.end(); ++i) {
+    if (i->type == SEARCH_TERMS) {
+      string16::size_type query_start = parsed_url_.find('?');
+      is_in_query = query_start != string16::npos &&
+          (static_cast<string16::size_type>(i->index) > query_start);
+      break;
+    }
+  }
+
+  std::string input_encoding;
+  string16 encoded_terms;
+  string16 encoded_original_query;
+  owner_->EncodeSearchTerms(search_terms_args, is_in_query, &input_encoding,
+      &encoded_terms, &encoded_original_query);
+
+  std::string url = parsed_url_;
+
+  // replacements_ is ordered in ascending order, as such we need to iterate
+  // from the back.
+  for (Replacements::reverse_iterator i = replacements_.rbegin();
+       i != replacements_.rend(); ++i) {
+    switch (i->type) {
+      case ENCODING:
+        url.insert(i->index, input_encoding);
+        break;
+
+      case GOOGLE_ASSISTED_QUERY_STATS:
+        if (!search_terms_args.assisted_query_stats.empty()) {
+          // Get the base URL without substituting AQS to avoid infinite
+          // recursion.  We need the URL to find out if it meets all
+          // AQS requirements (e.g. HTTPS protocol check).
+          // See TemplateURLRef::SearchTermsArgs for more details.
+          SearchTermsArgs search_terms_args_without_aqs(search_terms_args);
+          search_terms_args_without_aqs.assisted_query_stats.clear();
+          GURL base_url(ReplaceSearchTermsUsingTermsData(
+              search_terms_args_without_aqs, search_terms_data));
+          if (base_url.SchemeIs(chrome::kHttpsScheme)) {
+            url.insert(i->index,
+                       "aqs=" + search_terms_args.assisted_query_stats + "&");
+          }
+        }
+        break;
+
+      case GOOGLE_BASE_URL:
+        url.insert(i->index, search_terms_data.GoogleBaseURLValue());
+        break;
+
+      case GOOGLE_BASE_SUGGEST_URL:
+        url.insert(i->index, search_terms_data.GoogleBaseSuggestURLValue());
+        break;
+
+      case GOOGLE_CURSOR_POSITION:
+        if (search_terms_args.cursor_position != string16::npos)
+          url.insert(i->index,
+                     base::StringPrintf("cp=%" PRIuS "&",
+                                        search_terms_args.cursor_position));
+        break;
+
+      case GOOGLE_INSTANT_ENABLED:
+        url.insert(i->index, search_terms_data.InstantEnabledParam());
+        break;
+
+      case GOOGLE_INSTANT_EXTENDED_ENABLED:
+        url.insert(i->index, search_terms_data.InstantExtendedEnabledParam());
+        break;
+
+      case GOOGLE_NTP_IS_THEMED:
+        url.insert(i->index, search_terms_data.NTPIsThemedParam());
+        break;
+
+      case GOOGLE_OMNIBOX_START_MARGIN:
+        if (search_terms_args.omnibox_start_margin >= 0) {
+          url.insert(i->index, "es_sm=" +
+              base::IntToString(search_terms_args.omnibox_start_margin) + "&");
+        }
+        break;
+
+      case GOOGLE_ORIGINAL_QUERY_FOR_SUGGESTION:
+        if (search_terms_args.accepted_suggestion >= 0 ||
+            !search_terms_args.assisted_query_stats.empty()) {
+          url.insert(i->index, "oq=" + UTF16ToUTF8(encoded_original_query) +
+                               "&");
+        }
+        break;
+
+      case GOOGLE_RLZ: {
+        // On platforms that don't have RLZ, we still want this branch
+        // to happen so that we replace the RLZ template with the
+        // empty string.  (If we don't handle this case, we hit a
+        // NOTREACHED below.)
+        string16 rlz_string = search_terms_data.GetRlzParameterValue();
+        if (!rlz_string.empty()) {
+          url.insert(i->index, "rlz=" + UTF16ToUTF8(rlz_string) + "&");
+        }
+        break;
+      }
+
+      case GOOGLE_SEARCH_CLIENT: {
+        std::string client = search_terms_data.GetSearchClient();
+        if (!client.empty())
+          url.insert(i->index, "client=" + client + "&");
+        break;
+      }
+
+      case GOOGLE_SEARCH_FIELDTRIAL_GROUP:
+        // We are not currently running any fieldtrials that modulate the search
+        // url.  If we do, then we'd have some conditional insert such as:
+        // url.insert(i->index, used_www ? "gcx=w&" : "gcx=c&");
+        break;
+
+      case GOOGLE_SUGGEST_CLIENT:
+        url.insert(i->index, search_terms_data.GetSuggestClient());
+        break;
+
+      case GOOGLE_UNESCAPED_SEARCH_TERMS: {
+        std::string unescaped_terms;
+        base::UTF16ToCodepage(search_terms_args.search_terms,
+                              input_encoding.c_str(),
+                              base::OnStringConversionError::SKIP,
+                              &unescaped_terms);
+        url.insert(i->index, std::string(unescaped_terms.begin(),
+                                         unescaped_terms.end()));
+        break;
+      }
+
+      case GOOGLE_ZERO_PREFIX_URL:
+        if (!search_terms_args.zero_prefix_url.empty()) {
+          const std::string& escaped_zero_prefix_url =
+              net::EscapeQueryParamValue(search_terms_args.zero_prefix_url,
+                                         true);
+          url.insert(i->index, "url=" + escaped_zero_prefix_url + "&");
+        }
+
+        break;
+
+      case LANGUAGE:
+        url.insert(i->index, search_terms_data.GetApplicationLocale());
+        break;
+
+      case SEARCH_TERMS:
+        url.insert(i->index, UTF16ToUTF8(encoded_terms));
+        break;
+
+      default:
+        NOTREACHED();
+        break;
+    }
+  }
+
+  return url;
+}
+
 
 // TemplateURLData ------------------------------------------------------------
 
diff --git a/chrome/browser/search_engines/template_url.h b/chrome/browser/search_engines/template_url.h
index 61b5c45..3eb9f4d 100644
--- a/chrome/browser/search_engines/template_url.h
+++ b/chrome/browser/search_engines/template_url.h
@@ -9,10 +9,10 @@
 #include <vector>
 
 #include "base/gtest_prod_util.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/search_engines/template_url_id.h"
-#include "googleurl/src/gurl.h"
-#include "googleurl/src/url_parse.h"
+#include "url/gurl.h"
+#include "url/url_parse.h"
 
 class Profile;
 class SearchTermsData;
@@ -58,9 +58,11 @@
     ~SearchTermsArgs();
 
     // The search terms (query).
-    const string16 search_terms;
+    string16 search_terms;
+
     // The original (input) query.
     string16 original_query;
+
     // The optional assisted query stats, aka AQS, used for logging purposes.
     // This string contains impressions of all autocomplete matches shown
     // at the query submission time.  For privacy reasons, we require the
@@ -83,6 +85,15 @@
     // The URL of the current webpage to be used for experimental zero-prefix
     // suggestions.
     std::string zero_prefix_url;
+
+    // If set, ReplaceSearchTerms() will automatically append any extra query
+    // params specified via the --extra-search-query-params command-line
+    // argument.  Generally, this should be set when dealing with the search or
+    // instant TemplateURLRefs of the default search engine and the caller cares
+    // about the query portion of the URL.  Since neither TemplateURLRef nor
+    // indeed TemplateURL know whether a TemplateURL is the default search
+    // engine, callers instead must set this manually.
+    bool append_extra_query_params;
   };
 
   TemplateURLRef(TemplateURL* owner, Type type);
@@ -186,6 +197,7 @@
     GOOGLE_RLZ,
     GOOGLE_SEARCH_CLIENT,
     GOOGLE_SEARCH_FIELDTRIAL_GROUP,
+    GOOGLE_SUGGEST_CLIENT,
     GOOGLE_UNESCAPED_SEARCH_TERMS,
     GOOGLE_ZERO_PREFIX_URL,
     LANGUAGE,
@@ -243,6 +255,13 @@
   void ParseHostAndSearchTermKey(
       const SearchTermsData& search_terms_data) const;
 
+  // Replaces all replacements in |parsed_url_| with their actual values and
+  // returns the result.  This is the main functionality of
+  // ReplaceSearchTermsUsingTermsData().
+  std::string HandleReplacements(
+      const SearchTermsArgs& search_terms_args,
+      const SearchTermsData& search_terms_data) const;
+
   // The TemplateURL that contains us.  This should outlive us.
   TemplateURL* const owner_;
 
diff --git a/chrome/browser/search_engines/template_url_fetcher_unittest.cc b/chrome/browser/search_engines/template_url_fetcher_unittest.cc
index c174a51..9120251 100644
--- a/chrome/browser/search_engines/template_url_fetcher_unittest.cc
+++ b/chrome/browser/search_engines/template_url_fetcher_unittest.cc
@@ -15,9 +15,9 @@
 #include "chrome/browser/search_engines/template_url_service_test_util.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/test/base/testing_profile.h"
-#include "googleurl/src/gurl.h"
-#include "net/test/spawned_test_server/spawned_test_server.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 class TemplateURLFetcherTest;
 
@@ -53,10 +53,11 @@
 
     profile->CreateRequestContext();
     ASSERT_TRUE(profile->GetRequestContext());
-    ASSERT_TRUE(test_server_.Start());
+    ASSERT_TRUE(test_server_.InitializeAndWaitUntilReady());
   }
 
   virtual void TearDown() OVERRIDE {
+    ASSERT_TRUE(test_server_.ShutdownAndWaitUntilComplete());
     test_util_.TearDown();
   }
 
@@ -78,7 +79,7 @@
   void WaitForDownloadToFinish();
 
   TemplateURLServiceTestUtil test_util_;
-  net::SpawnedTestServer test_server_;
+  net::test_server::EmbeddedTestServer test_server_;
 
   // The last TemplateURL to come from a callback.
   scoped_ptr<TemplateURL> last_callback_template_url_;
@@ -108,12 +109,16 @@
 }
 
 TemplateURLFetcherTest::TemplateURLFetcherTest()
-    : test_server_(net::SpawnedTestServer::TYPE_HTTP,
-                   net::SpawnedTestServer::kLocalhost,
-                   base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))),
+    : test_server_(
+        content::BrowserThread::GetMessageLoopProxyForThread(
+            content::BrowserThread::IO)),
       callbacks_destroyed_(0),
       add_provider_called_(0),
       waiting_for_download_(false) {
+  base::FilePath src_dir;
+  CHECK(PathService::Get(base::DIR_SOURCE_ROOT, &src_dir));
+  test_server_.ServeFilesFromDirectory(
+      src_dir.AppendASCII("chrome/test/data"));
 }
 
 void TemplateURLFetcherTest::DestroyedCallback(
@@ -145,7 +150,7 @@
   }
 
   // Start the fetch.
-  GURL osdd_url = test_server_.GetURL("files/" + osdd_file_name);
+  GURL osdd_url = test_server_.GetURL("/" + osdd_file_name);
   GURL favicon_url;
   TemplateURLFetcherFactory::GetForProfile(
       test_util_.profile())->ScheduleDownload(
diff --git a/chrome/browser/search_engines/template_url_parser.cc b/chrome/browser/search_engines/template_url_parser.cc
index 121e539..64978a7 100644
--- a/chrome/browser/search_engines/template_url_parser.cc
+++ b/chrome/browser/search_engines/template_url_parser.cc
@@ -17,10 +17,10 @@
 #include "chrome/browser/search_engines/template_url.h"
 #include "chrome/browser/search_engines/template_url_service.h"
 #include "chrome/common/url_constants.h"
-#include "googleurl/src/gurl.h"
 #include "libxml/parser.h"
 #include "libxml/xmlwriter.h"
 #include "ui/gfx/favicon_size.h"
+#include "url/gurl.h"
 
 namespace {
 
diff --git a/chrome/browser/search_engines/template_url_prepopulate_data.cc b/chrome/browser/search_engines/template_url_prepopulate_data.cc
index 07438a9..aa3032e 100644
--- a/chrome/browser/search_engines/template_url_prepopulate_data.cc
+++ b/chrome/browser/search_engines/template_url_prepopulate_data.cc
@@ -28,10 +28,10 @@
 #include "chrome/common/pref_names.h"
 #include "components/user_prefs/pref_registry_syncable.h"
 #include "content/public/browser/browser_thread.h"
-#include "googleurl/src/gurl.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "url/gurl.h"
 
 #if defined(OS_WIN)
 #undef IN  // On Windows, windef.h defines this, which screws up "India" cases.
@@ -618,7 +618,7 @@
 #elif defined(OS_MACOSX)
 
 int GetCurrentCountryID() {
-  base::mac::ScopedCFTypeRef<CFLocaleRef> locale(CFLocaleCopyCurrent());
+  base::ScopedCFTypeRef<CFLocaleRef> locale(CFLocaleCopyCurrent());
   CFStringRef country = (CFStringRef)CFLocaleGetValue(locale.get(),
                                                       kCFLocaleCountryCode);
   if (!country)
diff --git a/chrome/browser/search_engines/template_url_prepopulate_data_unittest.cc b/chrome/browser/search_engines/template_url_prepopulate_data_unittest.cc
index 115abc7..1c1245b 100644
--- a/chrome/browser/search_engines/template_url_prepopulate_data_unittest.cc
+++ b/chrome/browser/search_engines/template_url_prepopulate_data_unittest.cc
@@ -304,15 +304,25 @@
               TemplateURLPrepopulateData::GetEngineType(kYahooURLs[i]));
   }
   // URLs for engines not present in country-specific lists.
-  std::string kNigmaURL = "http://www.nigma.ru/?s={searchTerms}&arg1=value1";
   EXPECT_EQ(SEARCH_ENGINE_NIGMA,
-            TemplateURLPrepopulateData::GetEngineType(kNigmaURL));
+            TemplateURLPrepopulateData::GetEngineType(
+                "http://www.nigma.ru/?s={searchTerms}&arg1=value1"));
   // Search URL for which no prepopulated search provider exists.
-  std::string kExampleSearchURL = "http://example.net/search?q={searchTerms}";
   EXPECT_EQ(SEARCH_ENGINE_OTHER,
-            TemplateURLPrepopulateData::GetEngineType(kExampleSearchURL));
+            TemplateURLPrepopulateData::GetEngineType(
+                "http://example.net/search?q={searchTerms}"));
   EXPECT_EQ(SEARCH_ENGINE_OTHER,
             TemplateURLPrepopulateData::GetEngineType("invalid:search:url"));
+
+  // URL that doesn't look Google-related, but matches a Google base URL
+  // specified on the command line.
+  const std::string foo_url("http://www.foo.com/search?q={searchTerms}");
+  EXPECT_EQ(SEARCH_ENGINE_OTHER,
+            TemplateURLPrepopulateData::GetEngineType(foo_url));
+  CommandLine::ForCurrentProcess()->AppendSwitchASCII(switches::kGoogleBaseURL,
+                                                      "http://www.foo.com/");
+  EXPECT_EQ(SEARCH_ENGINE_GOOGLE,
+            TemplateURLPrepopulateData::GetEngineType(foo_url));
 }
 
 TEST(TemplateURLPrepopulateDataTest, GetLogoURLGoogle) {
diff --git a/chrome/browser/search_engines/template_url_service.cc b/chrome/browser/search_engines/template_url_service.cc
index 9c5ab3c..b809632 100644
--- a/chrome/browser/search_engines/template_url_service.cc
+++ b/chrome/browser/search_engines/template_url_service.cc
@@ -18,7 +18,7 @@
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/google/google_url_tracker.h"
 #include "chrome/browser/history/history_notifications.h"
 #include "chrome/browser/history/history_service.h"
@@ -410,7 +410,7 @@
 void TemplateURLService::FindMatchingKeywords(
     const string16& prefix,
     bool support_replacement_only,
-    std::vector<string16>* matches) const {
+    TemplateURLVector* matches) const {
   // Sanity check args.
   if (prefix.empty())
     return;
@@ -434,7 +434,7 @@
   for (KeywordToTemplateMap::const_iterator i(match_range.first);
        i != match_range.second; ++i) {
     if (!support_replacement_only || i->second->url_ref().SupportsReplacement())
-      matches->push_back(i->first);
+      matches->push_back(i->second);
   }
 }
 
@@ -890,8 +890,10 @@
     const tracked_objects::Location& from_here,
     const syncer::SyncChangeList& change_list) {
   if (!models_associated_) {
-    syncer::SyncError error(FROM_HERE, "Models not yet associated.",
-                    syncer::SEARCH_ENGINES);
+    syncer::SyncError error(FROM_HERE,
+                            syncer::SyncError::DATATYPE_ERROR,
+                            "Models not yet associated.",
+                            syncer::SEARCH_ENGINES);
     return error;
   }
   DCHECK(loaded_);
@@ -1391,7 +1393,12 @@
       data.short_name = UTF8ToUTF16(initializers[i].content);
       data.SetKeyword(UTF8ToUTF16(initializers[i].keyword));
       data.SetURL(osd_url);
-      AddNoNotify(new TemplateURL(profile_, data), true);
+      TemplateURL* template_url = new TemplateURL(profile_, data);
+      AddNoNotify(template_url, true);
+
+      // Set the first provided identifier to be the default.
+      if (i == 0)
+        SetDefaultSearchProviderNoNotify(template_url);
     }
   }
 
diff --git a/chrome/browser/search_engines/template_url_service.h b/chrome/browser/search_engines/template_url_service.h
index 83826d5..724f771 100644
--- a/chrome/browser/search_engines/template_url_service.h
+++ b/chrome/browser/search_engines/template_url_service.h
@@ -118,12 +118,12 @@
                          const GURL& url,
                          TemplateURL** template_url_to_replace);
 
-  // Returns (in |matches|) all keywords beginning with |prefix|, sorted
-  // shortest-first. If support_replacement_only is true, only keywords that
-  // support replacement are returned.
+  // Returns (in |matches|) all TemplateURLs whose keywords begin with |prefix|,
+  // sorted shortest keyword-first. If |support_replacement_only| is true, only
+  // TemplateURLs that support replacement are returned.
   void FindMatchingKeywords(const string16& prefix,
                             bool support_replacement_only,
-                            std::vector<string16>* matches) const;
+                            TemplateURLVector* matches) const;
 
   // Looks up |keyword| and returns the element it maps to.  Returns NULL if
   // the keyword was not found.
diff --git a/chrome/browser/search_engines/template_url_service_android.cc b/chrome/browser/search_engines/template_url_service_android.cc
index 6229549..1081a03 100644
--- a/chrome/browser/search_engines/template_url_service_android.cc
+++ b/chrome/browser/search_engines/template_url_service_android.cc
@@ -95,12 +95,18 @@
   return template_url_service_->GetTemplateURLs().size();
 }
 
+jboolean TemplateUrlServiceAndroid::IsSearchProviderManaged(JNIEnv* env,
+                                                            jobject obj) {
+  return template_url_service_->is_default_search_managed();
+}
+
 base::android::ScopedJavaLocalRef<jobject>
 TemplateUrlServiceAndroid::GetPrepopulatedTemplateUrlAt(JNIEnv* env,
                                                         jobject obj,
                                                         jint index) {
   TemplateURL* template_url = template_url_service_->GetTemplateURLs()[index];
-  if (!IsPrepopulatedTemplate(template_url))
+  if (!IsPrepopulatedTemplate(template_url) &&
+      !template_url->created_by_policy())
    return ScopedJavaLocalRef<jobject>();
 
   return Java_TemplateUrl_create(
diff --git a/chrome/browser/search_engines/template_url_service_android.h b/chrome/browser/search_engines/template_url_service_android.h
index b02cf76..97336e8 100644
--- a/chrome/browser/search_engines/template_url_service_android.h
+++ b/chrome/browser/search_engines/template_url_service_android.h
@@ -28,6 +28,7 @@
   jboolean IsLoaded(JNIEnv* env, jobject obj);
   base::android::ScopedJavaLocalRef<jobject>
       GetPrepopulatedTemplateUrlAt(JNIEnv* env, jobject obj, jint index);
+  jboolean IsSearchProviderManaged(JNIEnv* env, jobject obj);
 
   // NotificationObserver:
   virtual void Observe(int type,
diff --git a/chrome/browser/search_engines/template_url_service_factory.cc b/chrome/browser/search_engines/template_url_service_factory.cc
index 3b1c8d7..30391fe 100644
--- a/chrome/browser/search_engines/template_url_service_factory.cc
+++ b/chrome/browser/search_engines/template_url_service_factory.cc
@@ -102,11 +102,7 @@
 
 content::BrowserContext* TemplateURLServiceFactory::GetBrowserContextToUse(
     content::BrowserContext* context) const {
-  // TODO(dougw): We need a separate instance of TemplateURLService in
-  // incognito profiles so that search-term-replacement can be disabled in
-  // incognito (see crbug.com/232065). Switch back to a shared instance once
-  // this is no longer necessary.
-  return chrome::GetBrowserContextOwnInstanceInIncognito(context);
+  return chrome::GetBrowserContextRedirectedInIncognito(context);
 }
 
 bool TemplateURLServiceFactory::ServiceIsNULLWhileTesting() const {
diff --git a/chrome/browser/search_engines/template_url_service_sync_unittest.cc b/chrome/browser/search_engines/template_url_service_sync_unittest.cc
index 72fc3a0..0e0c549 100644
--- a/chrome/browser/search_engines/template_url_service_sync_unittest.cc
+++ b/chrome/browser/search_engines/template_url_service_sync_unittest.cc
@@ -6,7 +6,7 @@
 #include "base/memory/scoped_vector.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/search_engines/search_terms_data.h"
 #include "chrome/browser/search_engines/template_url.h"
 #include "chrome/browser/search_engines/template_url_prepopulate_data.h"
@@ -124,7 +124,10 @@
     const syncer::SyncChangeList& change_list) {
   if (erroneous_)
     return syncer::SyncError(
-        FROM_HERE, "Some error.", syncer::SEARCH_ENGINES);
+        FROM_HERE,
+        syncer::SyncError::DATATYPE_ERROR,
+        "Some error.",
+        syncer::SEARCH_ENGINES);
 
   change_map_.erase(change_map_.begin(), change_map_.end());
   for (syncer::SyncChangeList::const_iterator iter = change_list.begin();
diff --git a/chrome/browser/search_engines/template_url_service_unittest.cc b/chrome/browser/search_engines/template_url_service_unittest.cc
index 68e845f..94026be 100644
--- a/chrome/browser/search_engines/template_url_service_unittest.cc
+++ b/chrome/browser/search_engines/template_url_service_unittest.cc
@@ -12,7 +12,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/mock_time_provider.h"
 #include "base/threading/thread.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/history/history_notifications.h"
 #include "chrome/browser/history/history_service.h"
 #include "chrome/browser/history/history_service_factory.h"
diff --git a/chrome/browser/search_engines/template_url_unittest.cc b/chrome/browser/search_engines/template_url_unittest.cc
index cffbb59..2f8b6c4 100644
--- a/chrome/browser/search_engines/template_url_unittest.cc
+++ b/chrome/browser/search_engines/template_url_unittest.cc
@@ -3,12 +3,14 @@
 // found in the LICENSE file.
 
 #include "base/base_paths.h"
+#include "base/command_line.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/rlz/rlz.h"
 #include "chrome/browser/search_engines/search_terms_data.h"
 #include "chrome/browser/search_engines/template_url.h"
+#include "chrome/common/chrome_switches.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 #if defined(ENABLE_RLZ)
@@ -1032,3 +1034,38 @@
       GURL("http://google.com/alt/?q=#q=123"), search_terms, &result));
   EXPECT_EQ(GURL("http://google.com/alt/?q=#q=Bob Morane"), result);
 }
+
+// Test the |append_extra_query_params| field of SearchTermsArgs.
+TEST_F(TemplateURLTest, ExtraQueryParams) {
+  UIThreadSearchTermsData::SetGoogleBaseURL("http://www.google.com/");
+  TemplateURLData data;
+  // Pick a URL with replacements before, during, and after the query, to ensure
+  // we don't goof up any of them.
+  data.SetURL("{google:baseURL}search?q={searchTerms}"
+      "#{google:originalQueryForSuggestion}x");
+  TemplateURL url(NULL, data);
+
+  // Baseline: no command-line args, no |append_extra_query_params| flag.
+  TemplateURLRef::SearchTermsArgs search_terms(ASCIIToUTF16("abc"));
+  search_terms.original_query = ASCIIToUTF16("def");
+  search_terms.accepted_suggestion = 0;
+  EXPECT_EQ("http://www.google.com/search?q=abc#oq=def&x",
+            url.url_ref().ReplaceSearchTerms(search_terms));
+
+  // Set the flag.  Since there are no command-line args, this should have no
+  // effect.
+  search_terms.append_extra_query_params = true;
+  EXPECT_EQ("http://www.google.com/search?q=abc#oq=def&x",
+            url.url_ref().ReplaceSearchTerms(search_terms));
+
+  // Now append the command-line arg.  This should be inserted into the query.
+  CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+      switches::kExtraSearchQueryParams, "a=b");
+  EXPECT_EQ("http://www.google.com/search?a=b&q=abc#oq=def&x",
+            url.url_ref().ReplaceSearchTerms(search_terms));
+
+  // Turn off the flag.  Now the command-line arg should be ignored again.
+  search_terms.append_extra_query_params = false;
+  EXPECT_EQ("http://www.google.com/search?q=abc#oq=def&x",
+            url.url_ref().ReplaceSearchTerms(search_terms));
+}
diff --git a/chrome/browser/search_engines/util.cc b/chrome/browser/search_engines/util.cc
index 5e7d285..6aa478e 100644
--- a/chrome/browser/search_engines/util.cc
+++ b/chrome/browser/search_engines/util.cc
@@ -12,7 +12,7 @@
 #include "base/logging.h"
 #include "base/memory/scoped_vector.h"
 #include "base/prefs/pref_service.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search_engines/template_url.h"
 #include "chrome/browser/search_engines/template_url_prepopulate_data.h"
@@ -39,6 +39,21 @@
   return default_provider->short_name();
 }
 
+GURL GetDefaultSearchURLForSearchTerms(Profile* profile,
+                                       const string16& terms) {
+  DCHECK(profile);
+  const TemplateURL* default_provider =
+      TemplateURLServiceFactory::GetForProfile(profile)->
+      GetDefaultSearchProvider();
+  if (!default_provider)
+    return GURL();
+  const TemplateURLRef& search_url = default_provider->url_ref();
+  DCHECK(search_url.SupportsReplacement());
+  TemplateURLRef::SearchTermsArgs search_terms_args(terms);
+  search_terms_args.append_extra_query_params = true;
+  return GURL(search_url.ReplaceSearchTerms(search_terms_args));
+}
+
 void RemoveDuplicatePrepopulateIDs(
     WebDataService* service,
     const ScopedVector<TemplateURL>& prepopulated_urls,
diff --git a/chrome/browser/search_engines/util.h b/chrome/browser/search_engines/util.h
index 912748d..b496e2a 100644
--- a/chrome/browser/search_engines/util.h
+++ b/chrome/browser/search_engines/util.h
@@ -23,6 +23,10 @@
 // none is set. |profile| may be NULL.
 string16 GetDefaultSearchEngineName(Profile* profile);
 
+// Returns a GURL that searches for |terms| using the default search engine of
+// |profile|.
+GURL GetDefaultSearchURLForSearchTerms(Profile* profile, const string16& terms);
+
 // Modifies |prepopulated_url| so that it contains user-modified fields from
 // |original_turl|. Both URLs must have the same prepopulate_id.
 void MergeIntoPrepopulatedEngineData(TemplateURLData* prepopulated_url,
diff --git a/chrome/browser/service/service_process_control_mac.mm b/chrome/browser/service/service_process_control_mac.mm
index 5cd05d6..96c0e8b 100644
--- a/chrome/browser/service/service_process_control_mac.mm
+++ b/chrome/browser/service/service_process_control_mac.mm
@@ -14,7 +14,7 @@
 using content::BrowserThread;
 
 void ServiceProcessControl::Launcher::DoRun() {
-  base::mac::ScopedCFTypeRef<CFDictionaryRef> launchd_plist(
+  base::ScopedCFTypeRef<CFDictionaryRef> launchd_plist(
       CreateServiceProcessLaunchdPlist(cmd_line_.get(), false));
   CFErrorRef error = NULL;
   if (!GTMSMJobSubmit(launchd_plist, &error)) {
diff --git a/chrome/browser/sessions/base_session_service.h b/chrome/browser/sessions/base_session_service.h
index 67175a5..be2c258 100644
--- a/chrome/browser/sessions/base_session_service.h
+++ b/chrome/browser/sessions/base_session_service.h
@@ -16,7 +16,7 @@
 #include "chrome/browser/common/cancelable_request.h"
 #include "chrome/browser/sessions/session_id.h"
 #include "chrome/common/cancelable_task_tracker.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 class Profile;
 class SessionBackend;
diff --git a/chrome/browser/sessions/persistent_tab_restore_service.cc b/chrome/browser/sessions/persistent_tab_restore_service.cc
index 39ae99f..d02f25a 100644
--- a/chrome/browser/sessions/persistent_tab_restore_service.cc
+++ b/chrome/browser/sessions/persistent_tab_restore_service.cc
@@ -15,7 +15,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_vector.h"
 #include "base/stl_util.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/common/cancelable_request.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sessions/base_session_service.h"
diff --git a/chrome/browser/sessions/session_backend.cc b/chrome/browser/sessions/session_backend.cc
index 9492b75..90e6a38 100644
--- a/chrome/browser/sessions/session_backend.cc
+++ b/chrome/browser/sessions/session_backend.cc
@@ -265,7 +265,7 @@
 
 void SessionBackend::DeleteLastSession() {
   Init();
-  file_util::Delete(GetLastSessionPath(), false);
+  base::Delete(GetLastSessionPath(), false);
 }
 
 void SessionBackend::MoveCurrentSessionToLastSession() {
@@ -275,7 +275,7 @@
   const base::FilePath current_session_path = GetCurrentSessionPath();
   const base::FilePath last_session_path = GetLastSessionPath();
   if (file_util::PathExists(last_session_path))
-    file_util::Delete(last_session_path, false);
+    base::Delete(last_session_path, false);
   if (file_util::PathExists(current_session_path)) {
     int64 file_size;
     if (file_util::GetFileSize(current_session_path, &file_size)) {
@@ -287,12 +287,11 @@
                              static_cast<int>(file_size / 1024));
       }
     }
-    last_session_valid_ = file_util::Move(current_session_path,
-                                          last_session_path);
+    last_session_valid_ = base::Move(current_session_path, last_session_path);
   }
 
   if (file_util::PathExists(current_session_path))
-    file_util::Delete(current_session_path, false);
+    base::Delete(current_session_path, false);
 
   // Create and open the file for the current session.
   ResetFile();
diff --git a/chrome/browser/sessions/session_id.h b/chrome/browser/sessions/session_id.h
index f4d103b..dd9d02d 100644
--- a/chrome/browser/sessions/session_id.h
+++ b/chrome/browser/sessions/session_id.h
@@ -7,8 +7,6 @@
 
 #include "base/basictypes.h"
 
-class Browser;
-
 namespace content {
 class WebContents;
 }
diff --git a/chrome/browser/sessions/session_restore_browsertest.cc b/chrome/browser/sessions/session_restore_browsertest.cc
index 81790e8..a5b0e8e 100644
--- a/chrome/browser/sessions/session_restore_browsertest.cc
+++ b/chrome/browser/sessions/session_restore_browsertest.cc
@@ -5,7 +5,7 @@
 #include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/defaults.h"
 #include "chrome/browser/first_run/first_run.h"
@@ -52,10 +52,7 @@
 
 class SessionRestoreTest : public InProcessBrowserTest {
  public:
-  SessionRestoreTest()
-      : native_browser_list(BrowserList::GetInstance(
-                                chrome::HOST_DESKTOP_TYPE_NATIVE)) {
-  }
+  SessionRestoreTest() : active_browser_list_(NULL) {}
 
  protected:
 #if defined(OS_CHROMEOS)
@@ -67,6 +64,8 @@
 #endif
 
   virtual void SetUpOnMainThread() OVERRIDE {
+    active_browser_list_ = BrowserList::GetInstance(chrome::GetActiveDesktop());
+
     SessionStartupPref pref(SessionStartupPref::LAST);
     SessionStartupPref::SetStartupPref(browser()->profile(), pref);
 #if defined(OS_CHROMEOS) || defined(OS_MACOSX)
@@ -81,6 +80,8 @@
       helper.ReleaseService();
     }
 #endif
+
+    InProcessBrowserTest::SetUpOnMainThread();
   }
 
   virtual bool SetUpUserDataDirectory() OVERRIDE {
@@ -165,7 +166,7 @@
   }
 
   void AssertOneWindowWithOneTab(Browser* browser) {
-    ASSERT_EQ(1u, native_browser_list->size());
+    ASSERT_EQ(1u, active_browser_list_->size());
     ASSERT_EQ(1, browser->tab_strip_model()->count());
   }
 
@@ -185,8 +186,7 @@
   GURL url2_;
   GURL url3_;
 
-  // The SessionRestore browser tests only uses the native desktop for now.
-  const BrowserList* native_browser_list;
+  const BrowserList* active_browser_list_;
 };
 
 #if defined(OS_CHROMEOS)
@@ -582,7 +582,7 @@
       profile, browser()->host_desktop_type(), session.begin(), session.end());
   Browser* new_browser = window_observer.WaitForSingleNewBrowser();
   ASSERT_TRUE(new_browser);
-  ASSERT_EQ(2u, native_browser_list->size());
+  ASSERT_EQ(2u, active_browser_list_->size());
   ASSERT_EQ(2, new_browser->tab_strip_model()->count());
 
   content::WebContents* web_contents_1 =
@@ -615,7 +615,7 @@
   ui_test_utils::NavigateToURL(browser(), url2_);
 
   Browser* new_browser = QuitBrowserAndRestore(browser(), 1);
-  ASSERT_EQ(1u, native_browser_list->size());
+  ASSERT_EQ(1u, active_browser_list_->size());
   ASSERT_EQ(url2_,
             new_browser->tab_strip_model()->GetActiveWebContents()->GetURL());
   GoBack(new_browser);
@@ -632,7 +632,7 @@
             old_tab->GetRenderViewHost()->GetEnabledBindings());
 
   Browser* new_browser = QuitBrowserAndRestore(browser(), 1);
-  ASSERT_EQ(1u, native_browser_list->size());
+  ASSERT_EQ(1u, active_browser_list_->size());
   const content::WebContents* new_tab =
       new_browser->tab_strip_model()->GetActiveWebContents();
   EXPECT_EQ(webui_url, new_tab->GetURL());
@@ -649,7 +649,7 @@
             old_tab->GetRenderViewHost()->GetEnabledBindings());
 
   Browser* new_browser = QuitBrowserAndRestore(browser(), 1);
-  ASSERT_EQ(1u, native_browser_list->size());
+  ASSERT_EQ(1u, active_browser_list_->size());
   const content::WebContents* new_tab =
       new_browser->tab_strip_model()->GetActiveWebContents();
   EXPECT_EQ(webui_url, new_tab->GetURL());
@@ -664,7 +664,7 @@
 
   GoBack(browser());
   Browser* new_browser = QuitBrowserAndRestore(browser(), 1);
-  ASSERT_EQ(1u, native_browser_list->size());
+  ASSERT_EQ(1u, active_browser_list_->size());
   ASSERT_EQ(url2_,
             new_browser->tab_strip_model()->GetActiveWebContents()->GetURL());
   GoForward(new_browser);
@@ -698,7 +698,7 @@
 
   GoBack(browser());
   Browser* new_browser = QuitBrowserAndRestore(browser(), 1);
-  ASSERT_EQ(1u, native_browser_list->size());
+  ASSERT_EQ(1u, active_browser_list_->size());
   ASSERT_EQ(1, new_browser->tab_strip_model()->count());
 
   // Check that back and forward work as expected.
@@ -729,7 +729,7 @@
 
   Browser* new_browser = QuitBrowserAndRestore(browser(), 2);
 
-  ASSERT_EQ(1u, native_browser_list->size());
+  ASSERT_EQ(1u, active_browser_list_->size());
   ASSERT_EQ(2, new_browser->tab_strip_model()->count());
   ASSERT_EQ(1, new_browser->tab_strip_model()->active_index());
   ASSERT_EQ(url2_,
@@ -811,7 +811,7 @@
       Browser::CreateParams(Browser::TYPE_POPUP, browser()->profile(),
                             browser()->host_desktop_type()));
   popup->window()->Show();
-  ASSERT_EQ(2u, native_browser_list->size());
+  ASSERT_EQ(2u, active_browser_list_->size());
 
   ui_test_utils::NavigateToURL(popup, url1_);
 
@@ -823,10 +823,10 @@
   // Restart and make sure we have two windows.
   QuitBrowserAndRestore(browser(), 1);
 
-  ASSERT_EQ(2u, native_browser_list->size());
+  ASSERT_EQ(2u, active_browser_list_->size());
 
-  Browser* browser1 = native_browser_list->get(0);
-  Browser* browser2 = native_browser_list->get(1);
+  Browser* browser1 = active_browser_list_->get(0);
+  Browser* browser2 = active_browser_list_->get(1);
 
   Browser::Type type1 = browser1->type();
   Browser::Type type2 = browser2->type();
@@ -862,7 +862,7 @@
   base::LaunchProcess(app_launch_arguments, base::LaunchOptions(), NULL);
 
   Browser* app_window = window_observer.WaitForSingleNewBrowser();
-  ASSERT_EQ(2u, native_browser_list->size());
+  ASSERT_EQ(2u, active_browser_list_->size());
 
   // Close the first window. The only window left is the App window.
   CloseBrowserSynchronously(browser());
@@ -887,10 +887,10 @@
       browser(), GURL(content::kAboutBlankURL), NEW_WINDOW,
       ui_test_utils::BROWSER_TEST_WAIT_FOR_BROWSER);
 
-  ASSERT_EQ(2u, native_browser_list->size());
+  ASSERT_EQ(2u, active_browser_list_->size());
 
   // Close it.
-  Browser* new_window = native_browser_list->get(1);
+  Browser* new_window = active_browser_list_->get(1);
   CloseBrowserSynchronously(new_window);
 
   // Restart and make sure we have only one window with one tab and the url
@@ -949,7 +949,7 @@
 
   // Kill the original browser then open a new one to trigger a restore.
   Browser* new_browser = QuitBrowserAndRestore(browser(), 1);
-  ASSERT_EQ(1u, native_browser_list->size());
+  ASSERT_EQ(1u, active_browser_list_->size());
   ASSERT_EQ(2, new_browser->tab_strip_model()->count());
   ASSERT_EQ(1, new_browser->tab_strip_model()->active_index());
 
@@ -983,7 +983,7 @@
 
   // This will also initiate a session restore, but we're not interested in it.
   Browser* new_browser = QuitBrowserAndRestore(browser(), 1);
-  ASSERT_EQ(1u, native_browser_list->size());
+  ASSERT_EQ(1u, active_browser_list_->size());
   ASSERT_EQ(2, new_browser->tab_strip_model()->count());
   ASSERT_EQ(0, new_browser->tab_strip_model()->active_index());
   // Close the pinned tab.
@@ -1021,7 +1021,7 @@
 
   // Restore the session by calling chrome::Navigate().
   Browser* new_browser = QuitBrowserAndRestoreWithURL(browser(), 3, url3_);
-  ASSERT_EQ(1u, native_browser_list->size());
+  ASSERT_EQ(1u, active_browser_list_->size());
   ASSERT_EQ(3, new_browser->tab_strip_model()->count());
   // Navigated url should be the active tab.
   ASSERT_EQ(url3_,
@@ -1042,7 +1042,7 @@
 
   // This will also initiate a session restore, but we're not interested in it.
   Browser* new_browser = QuitBrowserAndRestore(browser(), 1);
-  ASSERT_EQ(1u, native_browser_list->size());
+  ASSERT_EQ(1u, active_browser_list_->size());
   ASSERT_EQ(2, new_browser->tab_strip_model()->count());
   ASSERT_EQ(1, new_browser->tab_strip_model()->active_index());
   // Close the first tab.
@@ -1077,7 +1077,7 @@
   std::string session_storage_persistent_id =
       controller->GetDefaultSessionStorageNamespace()->persistent_id();
   Browser* new_browser = QuitBrowserAndRestore(browser(), 1);
-  ASSERT_EQ(1u, native_browser_list->size());
+  ASSERT_EQ(1u, active_browser_list_->size());
   ASSERT_EQ(url1_,
             new_browser->tab_strip_model()->GetActiveWebContents()->GetURL());
   content::NavigationController* new_controller =
@@ -1122,6 +1122,6 @@
 
   // Quit and restore. Check that no extra tabs were created.
   Browser* new_browser = QuitBrowserAndRestore(browser(), 1);
-  ASSERT_EQ(1u, native_browser_list->size());
+  ASSERT_EQ(1u, active_browser_list_->size());
   EXPECT_EQ(1, new_browser->tab_strip_model()->count());
 }
diff --git a/chrome/browser/sessions/session_service.h b/chrome/browser/sessions/session_service.h
index 69992e4..9e8b0ca 100644
--- a/chrome/browser/sessions/session_service.h
+++ b/chrome/browser/sessions/session_service.h
@@ -11,7 +11,7 @@
 #include "base/basictypes.h"
 #include "base/callback.h"
 #include "base/memory/scoped_vector.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/defaults.h"
 #include "chrome/browser/sessions/base_session_service.h"
 #include "chrome/browser/sessions/session_id.h"
diff --git a/chrome/browser/sessions/session_service_unittest.cc b/chrome/browser/sessions/session_service_unittest.cc
index b878b3d..4ed982b 100644
--- a/chrome/browser/sessions/session_service_unittest.cc
+++ b/chrome/browser/sessions/session_service_unittest.cc
@@ -12,7 +12,7 @@
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/defaults.h"
 #include "chrome/browser/sessions/session_backend.h"
 #include "chrome/browser/sessions/session_service.h"
@@ -29,9 +29,6 @@
 #include "content/public/browser/notification_service.h"
 #include "content/public/common/page_state.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/public/platform/WebData.h"
-#include "third_party/WebKit/public/platform/WebHTTPBody.h"
-#include "third_party/WebKit/public/web/WebHistoryItem.h"
 
 using content::NavigationEntry;
 using sessions::SerializedNavigationEntry;
diff --git a/chrome/browser/sessions/session_types.h b/chrome/browser/sessions/session_types.h
index c83c104..ac664d6 100644
--- a/chrome/browser/sessions/session_types.h
+++ b/chrome/browser/sessions/session_types.h
@@ -11,14 +11,14 @@
 
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/string16.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/sessions/session_id.h"
 #include "components/sessions/serialized_navigation_entry.h"
 #include "content/public/common/page_transition_types.h"
-#include "googleurl/src/gurl.h"
 #include "sync/protocol/session_specifics.pb.h"
 #include "ui/base/ui_base_types.h"
 #include "ui/gfx/rect.h"
+#include "url/gurl.h"
 
 namespace content {
 class BrowserContext;
diff --git a/chrome/browser/sessions/session_types_unittest.cc b/chrome/browser/sessions/session_types_unittest.cc
index 90ae78d..6442fbe 100644
--- a/chrome/browser/sessions/session_types_unittest.cc
+++ b/chrome/browser/sessions/session_types_unittest.cc
@@ -11,7 +11,7 @@
 #include "base/strings/string16.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/search/search.h"
 #include "chrome/browser/sessions/session_types.h"
 #include "components/sessions/serialized_navigation_entry_test_helper.h"
@@ -19,11 +19,11 @@
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/common/page_transition_types.h"
 #include "content/public/common/referrer.h"
-#include "googleurl/src/gurl.h"
 #include "sync/protocol/session_specifics.pb.h"
 #include "sync/util/time.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
+#include "url/gurl.h"
 
 namespace {
 
diff --git a/chrome/browser/sessions/tab_restore_browsertest.cc b/chrome/browser/sessions/tab_restore_browsertest.cc
index 9d9389c..1dfa94b 100644
--- a/chrome/browser/sessions/tab_restore_browsertest.cc
+++ b/chrome/browser/sessions/tab_restore_browsertest.cc
@@ -26,16 +26,14 @@
 #include "content/public/browser/page_navigator.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/net_util.h"
-#include "net/test/spawned_test_server/spawned_test_server.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
 #include "third_party/WebKit/public/web/WebFindOptions.h"
+#include "url/gurl.h"
 
 class TabRestoreTest : public InProcessBrowserTest {
  public:
-  TabRestoreTest()
-      : native_browser_list(BrowserList::GetInstance(
-                                chrome::HOST_DESKTOP_TYPE_NATIVE)) {
+  TabRestoreTest() : active_browser_list_(NULL) {
     url1_ = ui_test_utils::GetTestUrl(
         base::FilePath().AppendASCII("session_history"),
         base::FilePath().AppendASCII("bot1.html"));
@@ -45,10 +43,15 @@
   }
 
  protected:
+  virtual void SetUpOnMainThread() OVERRIDE {
+    active_browser_list_ = BrowserList::GetInstance(chrome::GetActiveDesktop());
+    InProcessBrowserTest::SetUpOnMainThread();
+  }
+
   Browser* GetBrowser(int index) {
 
-    CHECK(static_cast<int>(native_browser_list->size()) > index);
-    return native_browser_list->get(index);
+    CHECK(static_cast<int>(active_browser_list_->size()) > index);
+    return active_browser_list_->get(index);
   }
 
   // Adds tabs to the given browser, all navigated to url1_. Returns
@@ -83,14 +86,14 @@
   // window (since the index is 0-based).
   void RestoreTab(int expected_window_index,
                   int expected_tabstrip_index) {
-    int window_count = static_cast<int>(native_browser_list->size());
+    int window_count = static_cast<int>(active_browser_list_->size());
     ASSERT_GT(window_count, 0);
 
     bool expect_new_window = (expected_window_index == window_count);
 
     Browser* browser;
     if (expect_new_window) {
-      browser = native_browser_list->get(0);
+      browser = active_browser_list_->get(0);
     } else {
       browser = GetBrowser(expected_window_index);
     }
@@ -109,7 +112,7 @@
     tab_loaded_observer.Wait();
 
     if (expect_new_window) {
-      int new_window_count = static_cast<int>(native_browser_list->size());
+      int new_window_count = static_cast<int>(active_browser_list_->size());
       EXPECT_EQ(++window_count, new_window_count);
       browser = GetBrowser(expected_window_index);
     } else {
@@ -147,8 +150,7 @@
   GURL url1_;
   GURL url2_;
 
-  // The TabRestore browser tests only uses the native desktop for now.
-  const BrowserList* native_browser_list;
+  const BrowserList* active_browser_list_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(TabRestoreTest);
@@ -208,7 +210,7 @@
   ui_test_utils::NavigateToURLWithDisposition(
       browser(), GURL(chrome::kChromeUINewTabURL), NEW_WINDOW,
       ui_test_utils::BROWSER_TEST_WAIT_FOR_BROWSER);
-  EXPECT_EQ(2u, native_browser_list->size());
+  EXPECT_EQ(2u, active_browser_list_->size());
 
   // Restore tab into original browser.
   ASSERT_NO_FATAL_FAILURE(RestoreTab(0, closed_tab_index));
@@ -232,7 +234,7 @@
   ui_test_utils::NavigateToURLWithDisposition(
       browser(), GURL(chrome::kChromeUINewTabURL), NEW_WINDOW,
       ui_test_utils::BROWSER_TEST_WAIT_FOR_BROWSER);
-  EXPECT_EQ(2u, native_browser_list->size());
+  EXPECT_EQ(2u, active_browser_list_->size());
 
   // Close the final tab in the first browser.
   content::WindowedNotificationObserver window_observer(
@@ -295,7 +297,7 @@
   ui_test_utils::NavigateToURLWithDisposition(
       browser(), GURL(chrome::kChromeUINewTabURL), NEW_WINDOW,
       ui_test_utils::BROWSER_TEST_WAIT_FOR_BROWSER);
-  EXPECT_EQ(2u, native_browser_list->size());
+  EXPECT_EQ(2u, active_browser_list_->size());
 
   // Close the first browser.
   content::WindowedNotificationObserver observer(
@@ -303,7 +305,7 @@
       content::NotificationService::AllSources());
   chrome::CloseWindow(browser());
   observer.Wait();
-  EXPECT_EQ(1u, native_browser_list->size());
+  EXPECT_EQ(1u, active_browser_list_->size());
 
   // Restore the first window. The expected_tabstrip_index (second argument)
   // indicates the expected active tab.
@@ -333,7 +335,7 @@
   ui_test_utils::NavigateToURLWithDisposition(
       browser(), GURL(chrome::kChromeUINewTabURL), NEW_WINDOW,
       ui_test_utils::BROWSER_TEST_WAIT_FOR_BROWSER);
-  EXPECT_EQ(2u, native_browser_list->size());
+  EXPECT_EQ(2u, active_browser_list_->size());
 
   // Close all but one tab in the first browser, left to right.
   while (browser()->tab_strip_model()->count() > 1)
@@ -345,7 +347,7 @@
       content::NotificationService::AllSources());
   CloseTab(0);
   observer.Wait();
-  EXPECT_EQ(1u, native_browser_list->size());
+  EXPECT_EQ(1u, active_browser_list_->size());
 
   // Restore the last-closed tab into a new window.
   ASSERT_NO_FATAL_FAILURE(RestoreTab(1, 0));
@@ -364,10 +366,10 @@
 // Tests that a duplicate history entry is not created when we restore a page
 // to an existing SiteInstance.  (Bug 1230446)
 IN_PROC_BROWSER_TEST_F(TabRestoreTest, RestoreWithExistingSiteInstance) {
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
-  GURL http_url1(test_server()->GetURL("files/title1.html"));
-  GURL http_url2(test_server()->GetURL("files/title2.html"));
+  GURL http_url1(embedded_test_server()->GetURL("/title1.html"));
+  GURL http_url2(embedded_test_server()->GetURL("/title2.html"));
   int tab_count = browser()->tab_strip_model()->count();
 
   // Add a tab
@@ -421,10 +423,10 @@
 // already exists.  (Bug 1204135)
 IN_PROC_BROWSER_TEST_F(TabRestoreTest,
                        MAYBE_RestoreCrossSiteWithExistingSiteInstance) {
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
-  GURL http_url1(test_server()->GetURL("files/title1.html"));
-  GURL http_url2(test_server()->GetURL("files/title2.html"));
+  GURL http_url1(embedded_test_server()->GetURL("/title1.html"));
+  GURL http_url2(embedded_test_server()->GetURL("/title2.html"));
 
   int tab_count = browser()->tab_strip_model()->count();
 
@@ -477,11 +479,11 @@
 
 IN_PROC_BROWSER_TEST_F(TabRestoreTest, RestoreWindow) {
   // Create a new window.
-  size_t window_count = native_browser_list->size();
+  size_t window_count = active_browser_list_->size();
   ui_test_utils::NavigateToURLWithDisposition(
       browser(), GURL(chrome::kChromeUINewTabURL), NEW_WINDOW,
       ui_test_utils::BROWSER_TEST_WAIT_FOR_BROWSER);
-  EXPECT_EQ(++window_count, native_browser_list->size());
+  EXPECT_EQ(++window_count, active_browser_list_->size());
 
   // Create two more tabs, one with url1, the other url2.
   int initial_tab_count = browser()->tab_strip_model()->count();
@@ -498,7 +500,7 @@
       content::NotificationService::AllSources());
   chrome::CloseWindow(browser());
   close_window_observer.Wait();
-  EXPECT_EQ(window_count - 1, native_browser_list->size());
+  EXPECT_EQ(window_count - 1, active_browser_list_->size());
 
   // Restore the window.
   content::WindowedNotificationObserver open_window_observer(
@@ -507,9 +509,9 @@
   content::WindowedNotificationObserver load_stop_observer(
       content::NOTIFICATION_LOAD_STOP,
       content::NotificationService::AllSources());
-  chrome::RestoreTab(native_browser_list->get(0));
+  chrome::RestoreTab(active_browser_list_->get(0));
   open_window_observer.Wait();
-  EXPECT_EQ(window_count, native_browser_list->size());
+  EXPECT_EQ(window_count, active_browser_list_->size());
 
   Browser* browser = GetBrowser(1);
   EXPECT_EQ(initial_tab_count + 2, browser->tab_strip_model()->count());
@@ -552,9 +554,9 @@
 // Restore tab with special URL in its navigation history, go back to that
 // entry and see that it loads properly. See http://crbug.com/31905
 IN_PROC_BROWSER_TEST_F(TabRestoreTest, RestoreTabWithSpecialURLOnBack) {
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
-  const GURL http_url(test_server()->GetURL("files/title1.html"));
+  const GURL http_url(embedded_test_server()->GetURL("/title1.html"));
 
   // Navigate new tab to a special URL.
   ui_test_utils::NavigateToURLWithDisposition(
diff --git a/chrome/browser/sessions/tab_restore_service.h b/chrome/browser/sessions/tab_restore_service.h
index 210ba2f..e230def 100644
--- a/chrome/browser/sessions/tab_restore_service.h
+++ b/chrome/browser/sessions/tab_restore_service.h
@@ -10,7 +10,7 @@
 #include <vector>
 
 #include "base/memory/ref_counted.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/sessions/session_id.h"
 #include "chrome/browser/sessions/session_types.h"
 #include "chrome/browser/ui/host_desktop.h"
diff --git a/chrome/browser/sessions/tab_restore_service_helper.h b/chrome/browser/sessions/tab_restore_service_helper.h
index f173648..3eacc60 100644
--- a/chrome/browser/sessions/tab_restore_service_helper.h
+++ b/chrome/browser/sessions/tab_restore_service_helper.h
@@ -9,7 +9,7 @@
 
 #include "base/basictypes.h"
 #include "base/observer_list.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/sessions/session_id.h"
 #include "chrome/browser/sessions/session_types.h"
 #include "chrome/browser/sessions/tab_restore_service.h"
diff --git a/chrome/browser/shell_integration.h b/chrome/browser/shell_integration.h
index 09a7945..9abd195 100644
--- a/chrome/browser/shell_integration.h
+++ b/chrome/browser/shell_integration.h
@@ -11,8 +11,8 @@
 #include "base/files/file_path.h"
 #include "base/memory/ref_counted.h"
 #include "base/strings/string16.h"
-#include "googleurl/src/gurl.h"
 #include "ui/gfx/image/image_family.h"
+#include "url/gurl.h"
 
 class CommandLine;
 
diff --git a/chrome/browser/shell_integration_linux.cc b/chrome/browser/shell_integration_linux.cc
index b843abc..8ef3320 100644
--- a/chrome/browser/shell_integration_linux.cc
+++ b/chrome/browser/shell_integration_linux.cc
@@ -36,8 +36,8 @@
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/common/chrome_constants.h"
 #include "content/public/browser/browser_thread.h"
-#include "googleurl/src/gurl.h"
 #include "ui/gfx/image/image_family.h"
+#include "url/gurl.h"
 
 using content::BrowserThread;
 
@@ -170,7 +170,7 @@
 void DeleteShortcutOnDesktop(const base::FilePath& shortcut_filename) {
   base::FilePath desktop_path;
   if (PathService::Get(base::DIR_USER_DESKTOP, &desktop_path))
-    file_util::Delete(desktop_path.Append(shortcut_filename), false);
+    base::Delete(desktop_path.Append(shortcut_filename), false);
 }
 
 // Creates a shortcut with |shortcut_filename| and |contents| in the system
@@ -438,6 +438,22 @@
   return nodisplay;
 }
 
+// Gets the path to the Chrome executable or wrapper script.
+// Returns an empty path if the executable path could not be found.
+base::FilePath GetChromeExePath() {
+  // Try to get the name of the wrapper script that launched Chrome.
+  scoped_ptr<base::Environment> environment(base::Environment::Create());
+  std::string wrapper_script;
+  if (environment->GetVar("CHROME_WRAPPER", &wrapper_script)) {
+    return base::FilePath(wrapper_script);
+  }
+
+  // Just return the name of the executable path for Chrome.
+  base::FilePath chrome_exe_path;
+  PathService::Get(base::FILE_EXE, &chrome_exe_path);
+  return chrome_exe_path;
+}
+
 } // namespace
 
 // static
@@ -786,9 +802,8 @@
 
   bool success = true;
 
-  // Get the path to the Chrome executable.
-  base::FilePath chrome_exe_path;
-  if (!PathService::Get(base::FILE_EXE, &chrome_exe_path)) {
+  base::FilePath chrome_exe_path = GetChromeExePath();
+  if (chrome_exe_path.empty()) {
     LOG(WARNING) << "Could not get executable path.";
     return false;
   }
diff --git a/chrome/browser/shell_integration_linux.h b/chrome/browser/shell_integration_linux.h
index 4cf64c9..2618cf8 100644
--- a/chrome/browser/shell_integration_linux.h
+++ b/chrome/browser/shell_integration_linux.h
@@ -10,7 +10,7 @@
 #include "base/basictypes.h"
 #include "base/files/file_path.h"
 #include "chrome/browser/shell_integration.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 namespace base {
 class Environment;
diff --git a/chrome/browser/shell_integration_unittest.cc b/chrome/browser/shell_integration_unittest.cc
index 141daee..2d524a4 100644
--- a/chrome/browser/shell_integration_unittest.cc
+++ b/chrome/browser/shell_integration_unittest.cc
@@ -19,8 +19,8 @@
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/common/chrome_constants.h"
 #include "content/public/test/test_browser_thread.h"
-#include "googleurl/src/gurl.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 #if defined(OS_POSIX) && !defined(OS_MACOSX)
 #include "base/environment.h"
diff --git a/chrome/browser/shell_integration_win.cc b/chrome/browser/shell_integration_win.cc
index 8184442..c30dc78 100644
--- a/chrome/browser/shell_integration_win.cc
+++ b/chrome/browser/shell_integration_win.cc
@@ -23,6 +23,7 @@
 #include "base/win/scoped_propvariant.h"
 #include "base/win/shortcut.h"
 #include "base/win/windows_version.h"
+#include "chrome/browser/policy/policy_path_parser.h"
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_paths_internal.h"
@@ -96,6 +97,8 @@
     user_data_dir = command_line.GetSwitchValuePath(switches::kUserDataDir);
   else
     chrome::GetDefaultUserDataDirectory(&user_data_dir);
+  // Adjust with any policy that overrides any other way to set the path.
+  policy::path_parser::CheckUserDataDirPolicy(&user_data_dir);
   DCHECK(!user_data_dir.empty());
 
   base::FilePath profile_subdir;
diff --git a/chrome/browser/signin/DEPS b/chrome/browser/signin/DEPS
index 26c5415..05965ba 100644
--- a/chrome/browser/signin/DEPS
+++ b/chrome/browser/signin/DEPS
@@ -35,7 +35,6 @@
   "!chrome/common/chrome_notification_types.h",
   "!chrome/common/chrome_switches.h",
   "!chrome/common/chrome_version_info.h",
-  "!chrome/common/extensions/extension_messages.h",
   "!chrome/common/pref_names.h",
   "!chrome/common/url_constants.h",
 ]
@@ -48,8 +47,8 @@
     "!chrome/browser/sync/profile_sync_service_mock.h",
     "!chrome/browser/ui/browser.h",
     "!chrome/browser/ui/singleton_tabs.h",
+    "!chrome/browser/ui/sync/sync_promo_ui.h",
     "!chrome/browser/ui/tabs/tab_strip_model.h",
-    "!chrome/browser/ui/webui/sync_promo/sync_promo_ui.h",
   ],
 
   # These files are staying in //chrome so no need to limit.
diff --git a/chrome/browser/signin/chrome_signin_manager_delegate.cc b/chrome/browser/signin/chrome_signin_manager_delegate.cc
index 71689b9..3354d98 100644
--- a/chrome/browser/signin/chrome_signin_manager_delegate.cc
+++ b/chrome/browser/signin/chrome_signin_manager_delegate.cc
@@ -5,7 +5,7 @@
 #include "chrome/browser/signin/chrome_signin_manager_delegate.h"
 
 #include "chrome/browser/content_settings/cookie_settings.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 namespace {
 
diff --git a/chrome/browser/signin/oauth2_token_service.cc b/chrome/browser/signin/oauth2_token_service.cc
index e21911d..8564175 100644
--- a/chrome/browser/signin/oauth2_token_service.cc
+++ b/chrome/browser/signin/oauth2_token_service.cc
@@ -11,8 +11,8 @@
 #include "base/message_loop.h"
 #include "base/rand_util.h"
 #include "base/stl_util.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "content/public/browser/browser_thread.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "google_apis/gaia/google_service_auth_error.h"
@@ -20,21 +20,7 @@
 #include "google_apis/gaia/oauth2_access_token_fetcher.h"
 #include "net/url_request/url_request_context_getter.h"
 
-namespace {
-
-// Maximum number of retries in fetching an OAuth2 access token.
-const int kMaxFetchRetryNum = 5;
-
-// Returns an exponential backoff in milliseconds including randomness less than
-// 1000 ms when retrying fetching an OAuth2 access token.
-int64 ComputeExponentialBackOffMilliseconds(int retry_num) {
-  DCHECK(retry_num < kMaxFetchRetryNum);
-  int64 exponential_backoff_in_seconds = 1 << retry_num;
-  // Returns a backoff with randomness < 1000ms
-  return (exponential_backoff_in_seconds + base::RandDouble()) * 1000;
-}
-
-}  // namespace
+int OAuth2TokenService::max_fetch_retry_num_ = 5;
 
 OAuth2TokenService::RequestImpl::RequestImpl(
     OAuth2TokenService::Consumer* consumer)
@@ -119,7 +105,9 @@
           base::WeakPtr<RequestImpl> waiting_request);
   void Start();
   void InformWaitingRequests();
+  void InformWaitingRequestsAndDelete();
   static bool ShouldRetry(const GoogleServiceAuthError& error);
+  int64 ComputeExponentialBackOffMilliseconds(int retry_num);
 
   // |oauth2_token_service_| remains valid for the life of this Fetcher, since
   // this Fetcher is destructed in the dtor of the OAuth2TokenService or is
@@ -209,18 +197,14 @@
                                             scopes_,
                                             access_token_,
                                             expiration_date_);
-  // Deregisters itself from the service to prevent more waiting requests to
-  // be added when it calls back the waiting requests.
-  oauth2_token_service_->OnFetchComplete(this);
-  InformWaitingRequests();
-  base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+  InformWaitingRequestsAndDelete();
 }
 
 void OAuth2TokenService::Fetcher::OnGetTokenFailure(
     const GoogleServiceAuthError& error) {
   fetcher_.reset();
 
-  if (ShouldRetry(error) && retry_number_ < kMaxFetchRetryNum) {
+  if (ShouldRetry(error) && retry_number_ < max_fetch_retry_num_) {
     int64 backoff = ComputeExponentialBackOffMilliseconds(retry_number_);
     ++retry_number_;
     retry_timer_.Stop();
@@ -231,14 +215,18 @@
     return;
   }
 
-  // Fetch completes.
   error_ = error;
+  InformWaitingRequestsAndDelete();
+}
 
-  // Deregisters itself from the service to prevent more waiting requests to be
-  // added when it calls back the waiting requests.
-  oauth2_token_service_->OnFetchComplete(this);
-  InformWaitingRequests();
-  base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+// Returns an exponential backoff in milliseconds including randomness less than
+// 1000 ms when retrying fetching an OAuth2 access token.
+int64 OAuth2TokenService::Fetcher::ComputeExponentialBackOffMilliseconds(
+    int retry_num) {
+  DCHECK(retry_num < max_fetch_retry_num_);
+  int64 exponential_backoff_in_seconds = 1 << retry_num;
+  // Returns a backoff with randomness < 1000ms
+  return (exponential_backoff_in_seconds + base::RandDouble()) * 1000;
 }
 
 // static
@@ -261,6 +249,14 @@
   waiting_requests_.clear();
 }
 
+void OAuth2TokenService::Fetcher::InformWaitingRequestsAndDelete() {
+  // Deregisters itself from the service to prevent more waiting requests to
+  // be added when it calls back the waiting requests.
+  oauth2_token_service_->OnFetchComplete(this);
+  InformWaitingRequests();
+  base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+}
+
 void OAuth2TokenService::Fetcher::AddWaitingRequest(
     base::WeakPtr<OAuth2TokenService::RequestImpl> waiting_request) {
   waiting_requests_.push_back(waiting_request);
@@ -325,9 +321,9 @@
   if (HasCacheEntry(scopes))
     return StartCacheLookupRequest(scopes, consumer);
 
-  // Makes sure there is a pending fetcher for |scopes| and |refresh_token|.
-  // Adds |request| to the waiting request list of this fetcher so |request|
-  // will be called back when this fetcher finishes fetching.
+  // If there is already a pending fetcher for |scopes| and |refresh_token|,
+  // simply register this |request| for those results rather than starting
+  // a new fetcher.
   FetchParameters fetch_parameters = std::make_pair(refresh_token, scopes);
   std::map<FetchParameters, Fetcher*>::iterator iter =
       pending_fetchers_.find(fetch_parameters);
@@ -335,6 +331,7 @@
     iter->second->AddWaitingRequest(request->AsWeakPtr());
     return request.PassAs<Request>();
   }
+
   pending_fetchers_[fetch_parameters] =
       Fetcher::CreateAndStart(this,
                               request_context_getter_.get(),
@@ -463,3 +460,9 @@
 int OAuth2TokenService::cache_size_for_testing() const {
   return token_cache_.size();
 }
+
+void OAuth2TokenService::set_max_authorization_token_fetch_retries_for_testing(
+    int max_retries) {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  max_fetch_retry_num_ = max_retries;
+}
diff --git a/chrome/browser/signin/oauth2_token_service.h b/chrome/browser/signin/oauth2_token_service.h
index e96b9c1..150e6ca 100644
--- a/chrome/browser/signin/oauth2_token_service.h
+++ b/chrome/browser/signin/oauth2_token_service.h
@@ -13,7 +13,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
 
 namespace base {
 class Time;
@@ -100,8 +100,29 @@
 
   // Return the current number of entries in the cache.
   int cache_size_for_testing() const;
+  void set_max_authorization_token_fetch_retries_for_testing(int max_retries);
 
  protected:
+  // Implements a cancelable |OAuth2TokenService::Request|, which should be
+  // operated on the UI thread.
+  // TODO(davidroche): move this out of header file.
+  class RequestImpl : public base::SupportsWeakPtr<RequestImpl>,
+                      public Request {
+   public:
+    // |consumer| is required to outlive this.
+    explicit RequestImpl(Consumer* consumer);
+    virtual ~RequestImpl();
+
+    // Informs |consumer_| that this request is completed.
+    void InformConsumer(const GoogleServiceAuthError& error,
+                        const std::string& access_token,
+                        const base::Time& expiration_date);
+
+   private:
+    // |consumer_| to call back when this request completes.
+    Consumer* const consumer_;
+  };
+
   // Subclasses should return the refresh token maintained.
   // If no token is available, return an empty string.
   virtual std::string GetRefreshToken() = 0;
@@ -122,32 +143,13 @@
   bool HasCacheEntry(const ScopeSet& scopes);
 
   // Posts a task to fire the Consumer callback with the cached token.  Must
-  // only be called if HasCacheEntry() returns true.
+  // Must only be called if HasCacheEntry() returns true.
   scoped_ptr<Request> StartCacheLookupRequest(const ScopeSet& scopes,
                                               Consumer* consumer);
 
   // Clears the internal token cache.
   void ClearCache();
 
-  // Implements a cancelable |OAuth2TokenService::Request|, which should be
-  // operated on the UI thread.
-  class RequestImpl : public base::SupportsWeakPtr<RequestImpl>,
-                      public Request {
-   public:
-    // |consumer| is required to outlive this.
-    explicit RequestImpl(Consumer* consumer);
-    virtual ~RequestImpl();
-
-    // Informs |consumer_| that this request is completed.
-    void InformConsumer(const GoogleServiceAuthError& error,
-                        const std::string& access_token,
-                        const base::Time& expiration_date);
-
-   private:
-    // |consumer_| to call back when this request completes.
-    Consumer* const consumer_;
-  };
-
  private:
   // Class that fetches an OAuth2 access token for a given set of scopes and
   // OAuth2 refresh token.
@@ -189,6 +191,8 @@
   // A map from fetch parameters to a fetcher that is fetching an OAuth2 access
   // token using these parameters.
   std::map<FetchParameters, Fetcher*> pending_fetchers_;
+  // Maximum number of retries in fetching an OAuth2 access token.
+  static int max_fetch_retry_num_;
 
   DISALLOW_COPY_AND_ASSIGN(OAuth2TokenService);
 };
diff --git a/chrome/browser/signin/profile_oauth2_token_service.cc b/chrome/browser/signin/profile_oauth2_token_service.cc
index 7d34b2d..fd6799b 100644
--- a/chrome/browser/signin/profile_oauth2_token_service.cc
+++ b/chrome/browser/signin/profile_oauth2_token_service.cc
@@ -7,7 +7,7 @@
 #include "base/bind.h"
 #include "base/message_loop.h"
 #include "base/stl_util.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
diff --git a/chrome/browser/signin/signin_browsertest.cc b/chrome/browser/signin/signin_browsertest.cc
index ca8e34f..14ee972 100644
--- a/chrome/browser/signin/signin_browsertest.cc
+++ b/chrome/browser/signin/signin_browsertest.cc
@@ -5,20 +5,22 @@
 #ifndef CHROME_BROWSER_SIGNIN_SIGNIN_BROWSERTEST_H_
 #define CHROME_BROWSER_SIGNIN_SIGNIN_BROWSERTEST_H_
 
+#include "base/command_line.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/singleton_tabs.h"
+#include "chrome/browser/ui/sync/sync_promo_ui.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/webui/signin/login_ui_service.h"
 #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
-#include "chrome/browser/ui/webui/sync_promo/sync_promo_ui.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/common/content_switches.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "net/url_request/test_url_fetcher_factory.h"
 
@@ -28,6 +30,23 @@
 
 class SigninBrowserTest : public InProcessBrowserTest {
  public:
+  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+    https_server_.reset(new net::SpawnedTestServer(
+        net::SpawnedTestServer::TYPE_HTTPS,
+        net::SpawnedTestServer::kLocalhost,
+        base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))));
+    ASSERT_TRUE(https_server_->Start());
+
+    // Add a host resolver rule to map all outgoing requests to the test server.
+    // This allows us to use "real" hostnames in URLs, which we can use to
+    // create arbitrary SiteInstances.
+    command_line->AppendSwitchASCII(
+        switches::kHostResolverRules,
+        "MAP * " + https_server_->host_port_pair().ToString() +
+            ",EXCLUDE localhost");
+    command_line->AppendSwitch(switches::kIgnoreCertificateErrors);
+  }
+
   virtual void SetUp() OVERRIDE {
     factory_.reset(new net::URLFetcherImplFactory());
     fake_factory_.reset(new net::FakeURLFetcherFactory(factory_.get()));
@@ -59,8 +78,18 @@
 
   // The URLFetcherImplFactory instance used to instantiate |fake_factory_|.
   scoped_ptr<net::URLFetcherImplFactory> factory_;
+
+  scoped_ptr<net::SpawnedTestServer> https_server_;
 };
 
+// If the one-click-signin feature is not enabled (e.g Chrome OS), we
+// never grant signin privileges to any renderer processes.
+#if defined(ENABLE_ONE_CLICK_SIGNIN)
+const bool kOneClickSigninEnabled = true;
+#else
+const bool kOneClickSigninEnabled = false;
+#endif
+
 // Disabled on Windows due to flakiness. http://crbug.com/249055
 #if defined(OS_WIN)
 #define MAYBE_ProcessIsolation DISABLED_ProcessIsolation
@@ -68,14 +97,6 @@
 #define MAYBE_ProcessIsolation ProcessIsolation
 #endif
 IN_PROC_BROWSER_TEST_F(SigninBrowserTest, MAYBE_ProcessIsolation) {
-  // If the one-click-signin feature is not enabled (e.g Chrome OS), we
-  // never grant signin privileges to any renderer processes.
-#if defined(ENABLE_ONE_CLICK_SIGNIN)
-  const bool kOneClickSigninEnabled = true;
-#else
-  const bool kOneClickSigninEnabled = false;
-#endif
-
   SigninManager* signin = SigninManagerFactory::GetForProfile(
       browser()->profile());
   EXPECT_FALSE(signin->HasSigninProcess());
@@ -118,4 +139,26 @@
       active_tab->GetRenderProcessHost()->GetID()));
 }
 
+IN_PROC_BROWSER_TEST_F(SigninBrowserTest, NotTrustedAfterRedirect) {
+  SigninManager* signin = SigninManagerFactory::GetForProfile(
+      browser()->profile());
+  EXPECT_FALSE(signin->HasSigninProcess());
+
+  GURL url = SyncPromoUI::GetSyncPromoURL(SyncPromoUI::SOURCE_NTP_LINK, true);
+  ui_test_utils::NavigateToURL(browser(), url);
+  EXPECT_EQ(kOneClickSigninEnabled, signin->HasSigninProcess());
+
+  // Navigating in a different tab should not affect the sign-in process.
+  ui_test_utils::NavigateToURLWithDisposition(
+      browser(), GURL(kNonSigninURL), NEW_BACKGROUND_TAB,
+      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+  EXPECT_EQ(kOneClickSigninEnabled, signin->HasSigninProcess());
+
+  // Navigating away should clear the sign-in process.
+  GURL redirect_url("https://accounts.google.com/server-redirect?"
+      "https://foo.com?service=chromiumsync");
+  ui_test_utils::NavigateToURL(browser(), redirect_url);
+  EXPECT_FALSE(signin->HasSigninProcess());
+}
+
 #endif  // CHROME_BROWSER_SIGNIN_SIGNIN_BROWSERTEST_H_
diff --git a/chrome/browser/signin/signin_global_error_unittest.cc b/chrome/browser/signin/signin_global_error_unittest.cc
index 51b96e2..e0aeba0 100644
--- a/chrome/browser/signin/signin_global_error_unittest.cc
+++ b/chrome/browser/signin/signin_global_error_unittest.cc
@@ -107,6 +107,8 @@
     { GoogleServiceAuthError::TWO_FACTOR, true },
     { GoogleServiceAuthError::REQUEST_CANCELED, true },
     { GoogleServiceAuthError::HOSTED_NOT_ALLOWED, true },
+    { GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE, true },
+    { GoogleServiceAuthError::SERVICE_ERROR, true },
   };
   COMPILE_ASSERT(ARRAYSIZE_UNSAFE(table) == GoogleServiceAuthError::NUM_STATES,
       kTable_size_does_not_match_number_of_auth_error_types);
diff --git a/chrome/browser/signin/signin_internals_util.cc b/chrome/browser/signin/signin_internals_util.cc
index 0fa8863..00737b6 100644
--- a/chrome/browser/signin/signin_internals_util.cc
+++ b/chrome/browser/signin/signin_internals_util.cc
@@ -8,9 +8,9 @@
 
 #include "base/logging.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/common/chrome_version_info.h"
-#include "chrome/common/extensions/extension_messages.h"
 #include "chrome/common/url_constants.h"
 #include "content/public/browser/web_contents.h"
 #include "crypto/sha2.h"
diff --git a/chrome/browser/signin/signin_manager.cc b/chrome/browser/signin/signin_manager.cc
index 68479d4..4ca5da1 100644
--- a/chrome/browser/signin/signin_manager.cc
+++ b/chrome/browser/signin/signin_manager.cc
@@ -13,7 +13,7 @@
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/profiles/profile_io_data.h"
 #include "chrome/browser/signin/about_signin_internals.h"
 #include "chrome/browser/signin/about_signin_internals_factory.h"
@@ -103,6 +103,10 @@
                  content::Source<content::RenderProcessHost>(process));
 }
 
+void SigninManager::ClearSigninProcess() {
+  signin_process_id_ = kInvalidProcessId;
+}
+
 bool SigninManager::IsSigninProcess(int process_id) const {
   return process_id == signin_process_id_;
 }
diff --git a/chrome/browser/signin/signin_manager.h b/chrome/browser/signin/signin_manager.h
index 9a8d3dc..4ae4c2f 100644
--- a/chrome/browser/signin/signin_manager.h
+++ b/chrome/browser/signin/signin_manager.h
@@ -186,6 +186,7 @@
   // OneClickSigninHelper).  All of this tracking state is reset once the
   // renderer process terminates.
   void SetSigninProcess(int process_id);
+  void ClearSigninProcess();
   bool IsSigninProcess(int process_id) const;
   bool HasSigninProcess() const;
 
diff --git a/chrome/browser/signin/signin_ui_util.cc b/chrome/browser/signin/signin_ui_util.cc
index 9bb6499..95396be 100644
--- a/chrome/browser/signin/signin_ui_util.cc
+++ b/chrome/browser/signin/signin_ui_util.cc
@@ -28,13 +28,22 @@
 namespace signin_ui_util {
 
 GlobalError* GetSignedInServiceError(Profile* profile) {
+  std::vector<GlobalError*> errors = GetSignedInServiceErrors(profile);
+  if (errors.empty())
+    return NULL;
+  return errors[0];
+}
+
+std::vector<GlobalError*> GetSignedInServiceErrors(Profile* profile) {
+  std::vector<GlobalError*> errors;
+
   // Auth errors have the highest priority - after that, individual service
   // errors.
   SigninManagerBase* signin_manager =
       SigninManagerFactory::GetForProfile(profile);
   SigninGlobalError* signin_error = signin_manager->signin_global_error();
   if (signin_error && signin_error->HasMenuItem())
-    return signin_error;
+    errors.push_back(signin_error);
 
   // No auth error - now try other services. Currently the list is just hard-
   // coded but in the future if we add more we can create some kind of
@@ -44,9 +53,10 @@
         ProfileSyncServiceFactory::GetForProfile(profile);
     SyncGlobalError* error = service->sync_global_error();
     if (error && error->HasMenuItem())
-      return error;
+      errors.push_back(error);
   }
-  return NULL;
+
+  return errors;
 }
 
 string16 GetSigninMenuLabel(Profile* profile) {
diff --git a/chrome/browser/signin/signin_ui_util.h b/chrome/browser/signin/signin_ui_util.h
index decae32..3e63e1a 100644
--- a/chrome/browser/signin/signin_ui_util.h
+++ b/chrome/browser/signin/signin_ui_util.h
@@ -5,6 +5,8 @@
 #ifndef CHROME_BROWSER_SIGNIN_SIGNIN_UI_UTIL_H_
 #define CHROME_BROWSER_SIGNIN_SIGNIN_UI_UTIL_H_
 
+#include <vector>
+
 #include "base/strings/string16.h"
 
 class GlobalError;
@@ -19,6 +21,9 @@
 // object associated with that service, or NULL if no errors are reported.
 GlobalError* GetSignedInServiceError(Profile* profile);
 
+// Returns all errors reported by signed in services.
+std::vector<GlobalError*> GetSignedInServiceErrors(Profile* profile);
+
 // Return the label that should be displayed in the signin menu (i.e.
 // "Sign in to Chromium", "Signin Error...", etc).
 string16 GetSigninMenuLabel(Profile* profile);
diff --git a/chrome/browser/signin/ubertoken_fetcher.cc b/chrome/browser/signin/ubertoken_fetcher.cc
index b722f12..4cf5d39 100644
--- a/chrome/browser/signin/ubertoken_fetcher.cc
+++ b/chrome/browser/signin/ubertoken_fetcher.cc
@@ -2,12 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "chrome/browser/signin/ubertoken_fetcher.h"
+
+#include <vector>
+
 #include "base/logging.h"
 #include "base/strings/stringprintf.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/token_service.h"
 #include "chrome/browser/signin/token_service_factory.h"
-#include "chrome/browser/signin/ubertoken_fetcher.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "google_apis/gaia/gaia_constants.h"
 #include "google_apis/gaia/gaia_urls.h"
@@ -47,9 +50,11 @@
   client_info.client_id = urls->oauth2_chrome_client_id();
   client_info.client_secret = urls->oauth2_chrome_client_secret();
   gaia_oauth_client_.reset(new gaia::GaiaOAuthClient(
-      urls->oauth2_token_url(), profile_->GetRequestContext()));
+      profile_->GetRequestContext()));
+  std::vector<std::string> empty_scope_list;  // (Use scope from refresh token.)
   gaia_oauth_client_->RefreshToken(
-      client_info, token_service->GetOAuth2LoginRefreshToken(), 1, this);
+      client_info, token_service->GetOAuth2LoginRefreshToken(),
+      empty_scope_list, 1, this);
 }
 
 void UbertokenFetcher::Observe(int type,
diff --git a/chrome/browser/speech/tts_controller.h b/chrome/browser/speech/tts_controller.h
index b55600a..18cbcd9 100644
--- a/chrome/browser/speech/tts_controller.h
+++ b/chrome/browser/speech/tts_controller.h
@@ -12,7 +12,7 @@
 
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/singleton.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 class Utterance;
 class TtsPlatformImpl;
diff --git a/chrome/browser/speech/tts_mac.mm b/chrome/browser/speech/tts_mac.mm
index bdb9b1c..a5a8aec 100644
--- a/chrome/browser/speech/tts_mac.mm
+++ b/chrome/browser/speech/tts_mac.mm
@@ -4,7 +4,7 @@
 
 #include <string>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/singleton.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/values.h"
@@ -38,7 +38,7 @@
 //    crash when trying to call willSpeakWord.
 @interface SingleUseSpeechSynthesizer : NSSpeechSynthesizer {
  @private
-  scoped_nsobject<NSString> utterance_;
+  base::scoped_nsobject<NSString> utterance_;
   bool didSpeak_;
 }
 
@@ -85,8 +85,8 @@
   TtsPlatformImplMac();
   virtual ~TtsPlatformImplMac();
 
-  scoped_nsobject<SingleUseSpeechSynthesizer> speech_synthesizer_;
-  scoped_nsobject<ChromeTtsDelegate> delegate_;
+  base::scoped_nsobject<SingleUseSpeechSynthesizer> speech_synthesizer_;
+  base::scoped_nsobject<ChromeTtsDelegate> delegate_;
   int utterance_id_;
   std::string utterance_;
   bool sent_start_event_;
diff --git a/chrome/browser/spellchecker/feedback_sender.cc b/chrome/browser/spellchecker/feedback_sender.cc
index 3b72c69..c250cf4 100644
--- a/chrome/browser/spellchecker/feedback_sender.cc
+++ b/chrome/browser/spellchecker/feedback_sender.cc
@@ -155,6 +155,8 @@
 
 void FeedbackSender::SelectedSuggestion(uint32 hash, int suggestion_index) {
   Misspelling* misspelling = feedback_.GetMisspelling(hash);
+  // GetMisspelling() returns null for flushed feedback. Feedback is flushed
+  // when the session expires every |kSessionHours| hours.
   if (!misspelling)
     return;
   misspelling->action.type = SpellcheckAction::TYPE_SELECT;
@@ -164,6 +166,8 @@
 
 void FeedbackSender::AddedToDictionary(uint32 hash) {
   Misspelling* misspelling = feedback_.GetMisspelling(hash);
+  // GetMisspelling() returns null for flushed feedback. Feedback is flushed
+  // when the session expires every |kSessionHours| hours.
   if (!misspelling)
     return;
   misspelling->action.type = SpellcheckAction::TYPE_ADD_TO_DICT;
@@ -181,8 +185,19 @@
   }
 }
 
+void FeedbackSender::RecordInDictionary(uint32 hash) {
+  Misspelling* misspelling = feedback_.GetMisspelling(hash);
+  // GetMisspelling() returns null for flushed feedback. Feedback is flushed
+  // when the session expires every |kSessionHours| hours.
+  if (!misspelling)
+    return;
+  misspelling->action.type = SpellcheckAction::TYPE_IN_DICTIONARY;
+}
+
 void FeedbackSender::IgnoredSuggestions(uint32 hash) {
   Misspelling* misspelling = feedback_.GetMisspelling(hash);
+  // GetMisspelling() returns null for flushed feedback. Feedback is flushed
+  // when the session expires every |kSessionHours| hours.
   if (!misspelling)
     return;
   misspelling->action.type = SpellcheckAction::TYPE_PENDING_IGNORE;
@@ -192,6 +207,8 @@
 void FeedbackSender::ManuallyCorrected(uint32 hash,
                                        const string16& correction) {
   Misspelling* misspelling = feedback_.GetMisspelling(hash);
+  // GetMisspelling() returns null for flushed feedback. Feedback is flushed
+  // when the session expires every |kSessionHours| hours.
   if (!misspelling)
     return;
   misspelling->action.type = SpellcheckAction::TYPE_MANUALLY_CORRECTED;
diff --git a/chrome/browser/spellchecker/feedback_sender.h b/chrome/browser/spellchecker/feedback_sender.h
index dbcaba2..286008f 100644
--- a/chrome/browser/spellchecker/feedback_sender.h
+++ b/chrome/browser/spellchecker/feedback_sender.h
@@ -11,14 +11,13 @@
 
 #include "base/memory/scoped_vector.h"
 #include "base/memory/weak_ptr.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/spellchecker/feedback.h"
 #include "chrome/browser/spellchecker/misspelling.h"
-#include "googleurl/src/gurl.h"
 #include "net/url_request/url_fetcher_delegate.h"
+#include "url/gurl.h"
 
 class SpellCheckMarker;
-class SpellingServiceFeedbackTest;
 struct SpellCheckResult;
 
 namespace net {
@@ -58,6 +57,10 @@
   // the list of suggestions.
   void ManuallyCorrected(uint32 hash, const string16& correction);
 
+  // Records that user has the misspelling in the custom dictionary. The user
+  // will never see the spellcheck suggestions for the misspelling.
+  void RecordInDictionary(uint32 hash);
+
   // Receives document markers for renderer with process ID |render_process_id|
   // when the renderer responds to a RequestDocumentMarkers() call. Finalizes
   // feedback for the markers that are gone from the renderer. Sends feedback
diff --git a/chrome/browser/spellchecker/feedback_sender_unittest.cc b/chrome/browser/spellchecker/feedback_sender_unittest.cc
index 262b009..5504005 100644
--- a/chrome/browser/spellchecker/feedback_sender_unittest.cc
+++ b/chrome/browser/spellchecker/feedback_sender_unittest.cc
@@ -43,6 +43,18 @@
                           ASCIIToUTF16("Hello"));
 }
 
+// Returns the number of times that |needle| appears in |haystack| without
+// overlaps. For example, CountOccurences("bananana", "nana") returns 1.
+int CountOccurences(const std::string& haystack, const std::string& needle) {
+  int number_of_occurrences = 0;
+  for (size_t pos = haystack.find(needle);
+       pos != std::string::npos;
+       pos = haystack.find(needle, pos + needle.length())) {
+    ++number_of_occurrences;
+  }
+  return number_of_occurrences;
+}
+
 }  // namespace
 
 class FeedbackSenderTest : public testing::Test {
@@ -70,6 +82,7 @@
   content::TestBrowserThread ui_thread_;
   scoped_ptr<base::FieldTrialList> field_trial_list_;
   scoped_refptr<base::FieldTrial> field_trial_;
+  net::TestURLFetcherFactory fetchers_;
 
  protected:
   uint32 AddPendingFeedback() {
@@ -85,30 +98,55 @@
         base::TimeDelta::FromHours(chrome::spellcheck_common::kSessionHours);
   }
 
-  net::TestURLFetcher* GetFetcher() {
-    return fetchers_.GetFetcherByID(kUrlFetcherId);
+  bool UploadDataContains(const std::string& data) const {
+    const net::TestURLFetcher* fetcher =
+        fetchers_.GetFetcherByID(kUrlFetcherId);
+    return fetcher && CountOccurences(fetcher->upload_data(), data) > 0;
   }
 
-  net::TestURLFetcherFactory fetchers_;
+  bool UploadDataContains(const std::string& data,
+                          int number_of_occurrences) const {
+    const net::TestURLFetcher* fetcher =
+        fetchers_.GetFetcherByID(kUrlFetcherId);
+    return fetcher && CountOccurences(fetcher->upload_data(), data) ==
+                          number_of_occurrences;
+  }
+
+  // Returns true if the feedback sender would be uploading data now. Otherwise
+  // returns false. The test does not open network connections.
+  bool IsUploadingData() const {
+    return !!fetchers_.GetFetcherByID(kUrlFetcherId);
+  }
+
+  void ClearUploadData() {
+    fetchers_.RemoveFetcherFromMap(kUrlFetcherId);
+  }
+
+  std::string GetUploadData() const {
+    const net::TestURLFetcher* fetcher =
+        fetchers_.GetFetcherByID(kUrlFetcherId);
+    return fetcher ? fetcher->upload_data() : std::string();
+  }
+
   scoped_ptr<spellcheck::FeedbackSender> feedback_;
 };
 
 // Do not send data if there's no feedback.
 TEST_F(FeedbackSenderTest, NoFeedback) {
-  EXPECT_EQ(NULL, GetFetcher());
+  EXPECT_FALSE(IsUploadingData());
   feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
                                       std::vector<uint32>());
-  EXPECT_EQ(NULL, GetFetcher());
+  EXPECT_FALSE(IsUploadingData());
 }
 
 // Do not send data if not aware of which markers are still in the document.
 TEST_F(FeedbackSenderTest, NoDocumentMarkersReceived) {
-  EXPECT_EQ(NULL, GetFetcher());
+  EXPECT_FALSE(IsUploadingData());
   uint32 hash = AddPendingFeedback();
-  EXPECT_EQ(NULL, GetFetcher());
+  EXPECT_FALSE(IsUploadingData());
   static const int kSuggestionIndex = 1;
   feedback_->SelectedSuggestion(hash, kSuggestionIndex);
-  EXPECT_EQ(NULL, GetFetcher());
+  EXPECT_FALSE(IsUploadingData());
 }
 
 // Send PENDING feedback message if the marker is still in the document, and the
@@ -117,10 +155,7 @@
   uint32 hash = AddPendingFeedback();
   feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
                                       std::vector<uint32>(1, hash));
-  net::TestURLFetcher* fetcher = GetFetcher();
-  EXPECT_NE(std::string::npos,
-            fetcher->upload_data().find("\"actionType\":\"PENDING\""))
-      << fetcher->upload_data();
+  EXPECT_TRUE(UploadDataContains("\"actionType\":\"PENDING\""));
 }
 
 // Send NO_ACTION feedback message if the marker has been removed from the
@@ -129,26 +164,18 @@
   AddPendingFeedback();
   feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
                                       std::vector<uint32>());
-  net::TestURLFetcher* fetcher = GetFetcher();
-  EXPECT_NE(std::string::npos,
-            fetcher->upload_data().find("\"actionType\":\"NO_ACTION\""))
-      << fetcher->upload_data();
+  EXPECT_TRUE(UploadDataContains("\"actionType\":\"NO_ACTION\""));
 }
 
 // Send SELECT feedback message if the user has selected a spelling suggestion.
 TEST_F(FeedbackSenderTest, SelectFeedback) {
   uint32 hash = AddPendingFeedback();
-  static const int kSuggestion = 0;
-  feedback_->SelectedSuggestion(hash, kSuggestion);
+  static const int kSuggestionIndex = 0;
+  feedback_->SelectedSuggestion(hash, kSuggestionIndex);
   feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
                                       std::vector<uint32>());
-  net::TestURLFetcher* fetcher = GetFetcher();
-  EXPECT_NE(std::string::npos,
-            fetcher->upload_data().find("\"actionType\":\"SELECT\""))
-      << fetcher->upload_data();
-  EXPECT_NE(std::string::npos,
-            fetcher->upload_data().find("\"actionTargetIndex\":" + kSuggestion))
-      << fetcher->upload_data();
+  EXPECT_TRUE(UploadDataContains("\"actionType\":\"SELECT\""));
+  EXPECT_TRUE(UploadDataContains("\"actionTargetIndex\":" + kSuggestionIndex));
 }
 
 // Send ADD_TO_DICT feedback message if the user has added the misspelled word
@@ -158,10 +185,17 @@
   feedback_->AddedToDictionary(hash);
   feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
                                       std::vector<uint32>());
-  net::TestURLFetcher* fetcher = GetFetcher();
-  EXPECT_NE(std::string::npos,
-            fetcher->upload_data().find("\"actionType\":\"ADD_TO_DICT\""))
-      << fetcher->upload_data();
+  EXPECT_TRUE(UploadDataContains("\"actionType\":\"ADD_TO_DICT\""));
+}
+
+// Send IN_DICTIONARY feedback message if the user has the misspelled word in
+// the custom dictionary.
+TEST_F(FeedbackSenderTest, InDictionaryFeedback) {
+  uint32 hash = AddPendingFeedback();
+  feedback_->RecordInDictionary(hash);
+  feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
+                                      std::vector<uint32>());
+  EXPECT_TRUE(UploadDataContains("\"actionType\":\"IN_DICTIONARY\""));
 }
 
 // Send PENDING feedback message if the user saw the spelling suggestion, but
@@ -171,10 +205,7 @@
   feedback_->IgnoredSuggestions(hash);
   feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
                                       std::vector<uint32>(1, hash));
-  net::TestURLFetcher* fetcher = GetFetcher();
-  EXPECT_NE(std::string::npos,
-            fetcher->upload_data().find("\"actionType\":\"PENDING\""))
-      << fetcher->upload_data();
+  EXPECT_TRUE(UploadDataContains("\"actionType\":\"PENDING\""));
 }
 
 // Send IGNORE feedback message if the user saw the spelling suggestion, but
@@ -184,10 +215,7 @@
   feedback_->IgnoredSuggestions(hash);
   feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
                                       std::vector<uint32>());
-  net::TestURLFetcher* fetcher = GetFetcher();
-  EXPECT_NE(std::string::npos,
-            fetcher->upload_data().find("\"actionType\":\"IGNORE\""))
-      << fetcher->upload_data();
+  EXPECT_TRUE(UploadDataContains("\"actionType\":\"IGNORE\""));
 }
 
 // Send MANUALLY_CORRECTED feedback message if the user manually corrected the
@@ -198,15 +226,9 @@
   feedback_->ManuallyCorrected(hash, ASCIIToUTF16(kManualCorrection));
   feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
                                       std::vector<uint32>());
-  net::TestURLFetcher* fetcher = GetFetcher();
-  EXPECT_NE(
-      std::string::npos,
-      fetcher->upload_data().find("\"actionType\":\"MANUALLY_CORRECTED\""))
-      << fetcher->upload_data();
-  EXPECT_NE(std::string::npos,
-            fetcher->upload_data().find("\"actionTargetValue\":\"" +
-                                        kManualCorrection + "\""))
-      << fetcher->upload_data();
+  EXPECT_TRUE(UploadDataContains("\"actionType\":\"MANUALLY_CORRECTED\""));
+  EXPECT_TRUE(UploadDataContains("\"actionTargetValue\":\"" +
+                                 kManualCorrection + "\""));
 }
 
 // Send feedback messages in batch.
@@ -226,11 +248,7 @@
       &results, kRendererProcessId, kText, std::vector<SpellCheckMarker>());
   feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
                                       std::vector<uint32>());
-  net::TestURLFetcher* fetcher = GetFetcher();
-  size_t pos = fetcher->upload_data().find("\"actionType\":\"NO_ACTION\"");
-  EXPECT_NE(std::string::npos, pos) << fetcher->upload_data();
-  pos = fetcher->upload_data().find("\"actionType\":\"NO_ACTION\"", pos + 1);
-  EXPECT_NE(std::string::npos, pos) << fetcher->upload_data();
+  EXPECT_TRUE(UploadDataContains("\"actionType\":\"NO_ACTION\"", 2));
 }
 
 // Send a series of PENDING feedback messages and one final NO_ACTION feedback
@@ -240,37 +258,25 @@
   std::vector<uint32> remaining_markers(1, hash);
 
   feedback_->OnReceiveDocumentMarkers(kRendererProcessId, remaining_markers);
-  net::TestURLFetcher* fetcher = GetFetcher();
-  EXPECT_NE(std::string::npos,
-            fetcher->upload_data().find("\"actionType\":\"PENDING\""))
-      << fetcher->upload_data();
+  EXPECT_TRUE(UploadDataContains("\"actionType\":\"PENDING\""));
   std::string hash_string = base::StringPrintf("\"suggestionId\":\"%u\"", hash);
-  EXPECT_NE(std::string::npos, fetcher->upload_data().find(hash_string))
-      << fetcher->upload_data();
-  fetchers_.RemoveFetcherFromMap(kUrlFetcherId);
+  EXPECT_TRUE(UploadDataContains(hash_string));
+  ClearUploadData();
 
   feedback_->OnReceiveDocumentMarkers(kRendererProcessId, remaining_markers);
-  fetcher = GetFetcher();
-  EXPECT_NE(std::string::npos,
-            fetcher->upload_data().find("\"actionType\":\"PENDING\""))
-      << fetcher->upload_data();
-  EXPECT_NE(std::string::npos, fetcher->upload_data().find(hash_string))
-      << fetcher->upload_data();
-  fetchers_.RemoveFetcherFromMap(kUrlFetcherId);
+  EXPECT_TRUE(UploadDataContains("\"actionType\":\"PENDING\""));
+  EXPECT_TRUE(UploadDataContains(hash_string));
+  ClearUploadData();
 
   feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
                                       std::vector<uint32>());
-  fetcher = GetFetcher();
-  EXPECT_NE(std::string::npos,
-            fetcher->upload_data().find("\"actionType\":\"NO_ACTION\""))
-      << fetcher->upload_data();
-  EXPECT_NE(std::string::npos, fetcher->upload_data().find(hash_string))
-      << fetcher->upload_data();
-  fetchers_.RemoveFetcherFromMap(kUrlFetcherId);
+  EXPECT_TRUE(UploadDataContains("\"actionType\":\"NO_ACTION\""));
+  EXPECT_TRUE(UploadDataContains(hash_string));
+  ClearUploadData();
 
   feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
                                       std::vector<uint32>());
-  EXPECT_EQ(NULL, GetFetcher());
+  EXPECT_FALSE(IsUploadingData());
 }
 
 // When a session expires:
@@ -291,40 +297,26 @@
   std::vector<uint32> remaining_markers(1, original_hash);
 
   feedback_->OnReceiveDocumentMarkers(kRendererProcessId, remaining_markers);
-  net::TestURLFetcher* fetcher = GetFetcher();
-  EXPECT_EQ(std::string::npos,
-            fetcher->upload_data().find("\"actionType\":\"NO_ACTION\""))
-      << fetcher->upload_data();
-  EXPECT_NE(std::string::npos,
-            fetcher->upload_data().find("\"actionType\":\"PENDING\""))
-      << fetcher->upload_data();
+  EXPECT_FALSE(UploadDataContains("\"actionType\":\"NO_ACTION\""));
+  EXPECT_TRUE(UploadDataContains("\"actionType\":\"PENDING\""));
   std::string original_hash_string =
       base::StringPrintf("\"suggestionId\":\"%u\"", original_hash);
-  EXPECT_NE(std::string::npos,
-            fetcher->upload_data().find(original_hash_string))
-      << fetcher->upload_data();
-  fetchers_.RemoveFetcherFromMap(kUrlFetcherId);
+  EXPECT_TRUE(UploadDataContains(original_hash_string));
+  ClearUploadData();
 
   ExpireSession();
 
   // Last message batch in the current session has only finalized messages.
   feedback_->OnReceiveDocumentMarkers(kRendererProcessId, remaining_markers);
-  fetcher = GetFetcher();
-  EXPECT_NE(std::string::npos,
-            fetcher->upload_data().find("\"actionType\":\"NO_ACTION\""))
-      << fetcher->upload_data();
-  EXPECT_EQ(std::string::npos,
-            fetcher->upload_data().find("\"actionType\":\"PENDING\""))
-      << fetcher->upload_data();
-  EXPECT_NE(std::string::npos,
-            fetcher->upload_data().find(original_hash_string))
-      << fetcher->upload_data();
-  fetchers_.RemoveFetcherFromMap(kUrlFetcherId);
+  EXPECT_TRUE(UploadDataContains("\"actionType\":\"NO_ACTION\""));
+  EXPECT_FALSE(UploadDataContains("\"actionType\":\"PENDING\""));
+  EXPECT_TRUE(UploadDataContains(original_hash_string));
+  ClearUploadData();
 
   // The next session starts on the next spellchecker request. Until then,
   // there's no more feedback sent.
   feedback_->OnReceiveDocumentMarkers(kRendererProcessId, remaining_markers);
-  EXPECT_EQ(NULL, GetFetcher());
+  EXPECT_FALSE(IsUploadingData());
 
   // The first spellcheck request after session expiration creates different
   // document marker hash identifiers.
@@ -343,20 +335,12 @@
   // The first feedback message batch in session |i + 1| has the new document
   // marker hash identifiers.
   feedback_->OnReceiveDocumentMarkers(kRendererProcessId, remaining_markers);
-  fetcher = GetFetcher();
-  EXPECT_EQ(std::string::npos,
-            fetcher->upload_data().find("\"actionType\":\"NO_ACTION\""))
-      << fetcher->upload_data();
-  EXPECT_NE(std::string::npos,
-            fetcher->upload_data().find("\"actionType\":\"PENDING\""))
-      << fetcher->upload_data();
-  EXPECT_EQ(std::string::npos,
-            fetcher->upload_data().find(original_hash_string))
-      << fetcher->upload_data();
+  EXPECT_FALSE(UploadDataContains("\"actionType\":\"NO_ACTION\""));
+  EXPECT_TRUE(UploadDataContains("\"actionType\":\"PENDING\""));
+  EXPECT_FALSE(UploadDataContains(original_hash_string));
   std::string updated_hash_string =
       base::StringPrintf("\"suggestionId\":\"%u\"", updated_hash);
-  EXPECT_NE(std::string::npos, fetcher->upload_data().find(updated_hash_string))
-      << fetcher->upload_data();
+  EXPECT_TRUE(UploadDataContains(updated_hash_string));
 }
 
 // First message in session has an indicator.
@@ -365,19 +349,13 @@
   AddPendingFeedback();
   feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
                                       std::vector<uint32>());
-  net::TestURLFetcher* fetcher = GetFetcher();
-  EXPECT_NE(std::string::npos,
-            fetcher->upload_data().find("\"isFirstInSession\":true"))
-      << fetcher->upload_data();
+  EXPECT_TRUE(UploadDataContains("\"isFirstInSession\":true"));
 
   // Session 1, message 2
   AddPendingFeedback();
   feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
                                       std::vector<uint32>());
-  fetcher = GetFetcher();
-  EXPECT_NE(std::string::npos,
-            fetcher->upload_data().find("\"isFirstInSession\":false"))
-      << fetcher->upload_data();
+  EXPECT_TRUE(UploadDataContains("\"isFirstInSession\":false"));
 
   ExpireSession();
 
@@ -385,45 +363,29 @@
   AddPendingFeedback();
   feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
                                       std::vector<uint32>());
-  fetcher = GetFetcher();
-  EXPECT_NE(std::string::npos,
-            fetcher->upload_data().find("\"isFirstInSession\":false"))
-      << fetcher->upload_data();
+  EXPECT_TRUE(UploadDataContains("\"isFirstInSession\":false"));
 
   // Session 2, message 1
   AddPendingFeedback();
   feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
                                       std::vector<uint32>());
-  fetcher = GetFetcher();
-  EXPECT_NE(std::string::npos,
-            fetcher->upload_data().find("\"isFirstInSession\":true"))
-      << fetcher->upload_data();
+  EXPECT_TRUE(UploadDataContains("\"isFirstInSession\":true"));
 
   // Session 2, message 2
   AddPendingFeedback();
   feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
                                       std::vector<uint32>());
-  fetcher = GetFetcher();
-  EXPECT_NE(std::string::npos,
-            fetcher->upload_data().find("\"isFirstInSession\":false"))
-      << fetcher->upload_data();
+  EXPECT_TRUE(UploadDataContains("\"isFirstInSession\":false"));
 }
 
 // Flush all feedback when the spellcheck language and country change.
 TEST_F(FeedbackSenderTest, OnLanguageCountryChange) {
   AddPendingFeedback();
   feedback_->OnLanguageCountryChange("pt", "BR");
-  net::TestURLFetcher* fetcher = GetFetcher();
-  EXPECT_NE(std::string::npos,
-            fetcher->upload_data().find("\"language\":\"en\""))
-      << fetcher->upload_data();
-
+  EXPECT_TRUE(UploadDataContains("\"language\":\"en\""));
   AddPendingFeedback();
   feedback_->OnLanguageCountryChange("en", "US");
-  fetcher = GetFetcher();
-  EXPECT_NE(std::string::npos,
-            fetcher->upload_data().find("\"language\":\"pt\""))
-      << fetcher->upload_data();
+  EXPECT_TRUE(UploadDataContains("\"language\":\"pt\""));
 }
 
 // The field names and types should correspond to the API.
@@ -431,7 +393,7 @@
   AddPendingFeedback();
   feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
                                       std::vector<uint32>());
-  std::string actual_data = GetFetcher()->upload_data();
+  std::string actual_data = GetUploadData();
   scoped_ptr<base::DictionaryValue> actual(
       static_cast<base::DictionaryValue*>(base::JSONReader::Read(actual_data)));
   actual->SetString("params.key", "TestDummyKey");
@@ -481,22 +443,6 @@
   EXPECT_EQ(hash, results[0].hash);
 }
 
-namespace {
-
-// Returns the number of times that |needle| appears in |haystack| without
-// overlaps. For example, CountOccurences("bananana", "nana") returns 1.
-int CountOccurences(const std::string& haystack, const std::string& needle) {
-  int number_of_occurences = 0;
-  size_t pos = haystack.find(needle);
-  while (pos != std::string::npos) {
-    ++number_of_occurences;
-    pos = haystack.find(needle, pos + needle.length());
-  }
-  return number_of_occurences;
-}
-
-}  // namespace
-
 // Adding a word to dictionary should trigger ADD_TO_DICT feedback for every
 // occurrence of that word.
 TEST_F(FeedbackSenderTest, MultipleAddToDictFeedback) {
@@ -525,20 +471,14 @@
     remaining_markers.push_back(results[i].hash);
   feedback_->OnReceiveDocumentMarkers(last_renderer_process_id,
                                       remaining_markers);
-  net::TestURLFetcher* fetcher = GetFetcher();
-  EXPECT_EQ(2, CountOccurences(fetcher->upload_data(), "PENDING"))
-      << fetcher->upload_data();
-  EXPECT_EQ(0, CountOccurences(fetcher->upload_data(), "ADD_TO_DICT"))
-      << fetcher->upload_data();
+  EXPECT_TRUE(UploadDataContains("PENDING", 2));
+  EXPECT_FALSE(UploadDataContains("ADD_TO_DICT"));
 
   feedback_->AddedToDictionary(results[0].hash);
   feedback_->OnReceiveDocumentMarkers(last_renderer_process_id,
                                       remaining_markers);
-  fetcher = GetFetcher();
-  EXPECT_EQ(0, CountOccurences(fetcher->upload_data(), "PENDING"))
-      << fetcher->upload_data();
-  EXPECT_EQ(2, CountOccurences(fetcher->upload_data(), "ADD_TO_DICT"))
-      << fetcher->upload_data();
+  EXPECT_FALSE(UploadDataContains("PENDING"));
+  EXPECT_TRUE(UploadDataContains("ADD_TO_DICT", 2));
 }
 
 // ADD_TO_DICT feedback for multiple occurrences of a word should trigger only
@@ -551,11 +491,8 @@
   feedback_->AddedToDictionary(add_to_dict_hash);
   feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
                                       std::vector<uint32>());
-  net::TestURLFetcher* fetcher = GetFetcher();
-  EXPECT_EQ(1, CountOccurences(fetcher->upload_data(), "SELECT"))
-      << fetcher->upload_data();
-  EXPECT_EQ(2, CountOccurences(fetcher->upload_data(), "ADD_TO_DICT"))
-      << fetcher->upload_data();
+  EXPECT_TRUE(UploadDataContains("SELECT", 1));
+  EXPECT_TRUE(UploadDataContains("ADD_TO_DICT", 2));
 }
 
 }  // namespace spellcheck
diff --git a/chrome/browser/spellchecker/misspelling.h b/chrome/browser/spellchecker/misspelling.h
index 9a9d0fe..7cd331b 100644
--- a/chrome/browser/spellchecker/misspelling.h
+++ b/chrome/browser/spellchecker/misspelling.h
@@ -7,7 +7,7 @@
 
 #include <vector>
 
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/spellchecker/spellcheck_action.h"
 
 // Spellcheck misspelling.
diff --git a/chrome/browser/spellchecker/spellcheck_custom_dictionary.cc b/chrome/browser/spellchecker/spellcheck_custom_dictionary.cc
index 0cd0c7c..c3d2484 100644
--- a/chrome/browser/spellchecker/spellcheck_custom_dictionary.cc
+++ b/chrome/browser/spellchecker/spellcheck_custom_dictionary.cc
@@ -261,7 +261,7 @@
   return result == VALID_CHANGE;
 }
 
-bool SpellcheckCustomDictionary::HasWord(const std::string& word) {
+bool SpellcheckCustomDictionary::HasWord(const std::string& word) const {
   return !!words_.count(word);
 }
 
diff --git a/chrome/browser/spellchecker/spellcheck_custom_dictionary.h b/chrome/browser/spellchecker/spellcheck_custom_dictionary.h
index e54b6fa..848022a 100644
--- a/chrome/browser/spellchecker/spellcheck_custom_dictionary.h
+++ b/chrome/browser/spellchecker/spellcheck_custom_dictionary.h
@@ -91,7 +91,7 @@
   bool RemoveWord(const std::string& word);
 
   // Returns true if the dictionary contains |word|. Otherwise returns false.
-  bool HasWord(const std::string& word);
+  bool HasWord(const std::string& word) const;
 
   // Adds |observer| to be notified of dictionary events and changes.
   void AddObserver(Observer* observer);
diff --git a/chrome/browser/spellchecker/spellcheck_custom_dictionary_unittest.cc b/chrome/browser/spellchecker/spellcheck_custom_dictionary_unittest.cc
index d196f65..58c3d1b 100644
--- a/chrome/browser/spellchecker/spellcheck_custom_dictionary_unittest.cc
+++ b/chrome/browser/spellchecker/spellcheck_custom_dictionary_unittest.cc
@@ -154,7 +154,10 @@
       const tracked_objects::Location& location,
       const std::string& message) OVERRIDE {
     (*error_counter_)++;
-    return syncer::SyncError(location, message, syncer::DICTIONARY);
+    return syncer::SyncError(location,
+                             syncer::SyncError::DATATYPE_ERROR,
+                             message,
+                             syncer::DICTIONARY);
   }
 
  private:
diff --git a/chrome/browser/spellchecker/spellcheck_host_metrics.h b/chrome/browser/spellchecker/spellcheck_host_metrics.h
index bc36792..53f4e42 100644
--- a/chrome/browser/spellchecker/spellcheck_host_metrics.h
+++ b/chrome/browser/spellchecker/spellcheck_host_metrics.h
@@ -9,8 +9,8 @@
 #include <vector>
 
 #include "base/containers/hash_tables.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 
 // A helper object for recording spell-check related histograms.
 // This class encapsulates histogram names and metrics API.
diff --git a/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc b/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc
index 44a166d..a6f5169 100644
--- a/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc
+++ b/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc
@@ -9,18 +9,18 @@
 #include "base/logging.h"
 #include "base/message_loop.h"
 #include "base/path_service.h"
-#include "chrome/browser/spellchecker/spellcheck_service.h"
 #include "chrome/browser/spellchecker/spellcheck_platform_mac.h"
+#include "chrome/browser/spellchecker/spellcheck_service.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/spellcheck_common.h"
 #include "chrome/common/spellcheck_messages.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_process_host.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/load_flags.h"
 #include "net/url_request/url_fetcher.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "third_party/hunspell/google/bdict.h"
+#include "url/gurl.h"
 
 using content::BrowserThread;
 
@@ -101,7 +101,7 @@
         NULL,
         NULL);
   } else {
-    file_util::Delete(file->path, false);
+    base::Delete(file->path, false);
   }
 
   return file.Pass();
@@ -148,7 +148,7 @@
 #endif
 
     if (!success) {
-      file_util::Delete(path, false);
+      base::Delete(path, false);
       return false;
     }
   }
diff --git a/chrome/browser/spellchecker/spellcheck_message_filter.cc b/chrome/browser/spellchecker/spellcheck_message_filter.cc
index 091a66e..e58be59 100644
--- a/chrome/browser/spellchecker/spellcheck_message_filter.cc
+++ b/chrome/browser/spellchecker/spellcheck_message_filter.cc
@@ -9,6 +9,7 @@
 
 #include "base/bind.h"
 #include "base/prefs/pref_service.h"
+#include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/spellchecker/spellcheck_factory.h"
 #include "chrome/browser/spellchecker/spellcheck_host_metrics.h"
@@ -87,23 +88,18 @@
 
 void SpellCheckMessageFilter::OnNotifyChecked(const string16& word,
                                               bool misspelled) {
-  content::RenderProcessHost* host =
-      content::RenderProcessHost::FromID(render_process_id_);
-  if (!host)
-    return;  // Teardown.
-  // Delegates to SpellCheckHost which tracks the stats of our spellchecker.
-  Profile* profile = Profile::FromBrowserContext(host->GetBrowserContext());
-  SpellcheckService* spellcheck_service =
-      SpellcheckServiceFactory::GetForProfile(profile);
-  DCHECK(spellcheck_service);
-  if (spellcheck_service->GetMetrics())
-    spellcheck_service->GetMetrics()->RecordCheckedWordStats(word, misspelled);
+  SpellcheckService* spellcheck = GetSpellcheckService();
+  // Spellcheck service may not be available for a renderer process that is
+  // shutting down.
+  if (!spellcheck)
+    return;
+  if (spellcheck->GetMetrics())
+    spellcheck->GetMetrics()->RecordCheckedWordStats(word, misspelled);
 }
 
 void SpellCheckMessageFilter::OnRespondDocumentMarkers(
     const std::vector<uint32>& markers) {
-  SpellcheckService* spellcheck =
-      SpellcheckServiceFactory::GetForRenderProcessId(render_process_id_);
+  SpellcheckService* spellcheck = GetSpellcheckService();
   // Spellcheck service may not be available for a renderer process that is
   // shutting down.
   if (!spellcheck)
@@ -137,12 +133,34 @@
     bool success,
     const string16& text,
     const std::vector<SpellCheckResult>& results) {
-  SpellcheckService* spellcheck =
-      SpellcheckServiceFactory::GetForRenderProcessId(render_process_id_);
-  DCHECK(spellcheck);
+  SpellcheckService* spellcheck = GetSpellcheckService();
+  // Spellcheck service may not be available for a renderer process that is
+  // shutting down.
+  if (!spellcheck)
+    return;
   std::vector<SpellCheckResult> results_copy = results;
   spellcheck->GetFeedbackSender()->OnSpellcheckResults(
       &results_copy, render_process_id_, text, markers);
+
+  // Erase custom dictionary words from the spellcheck results and record
+  // in-dictionary feedback.
+  std::vector<SpellCheckResult>::iterator write_iter;
+  std::vector<SpellCheckResult>::iterator iter;
+  std::string text_copy = UTF16ToUTF8(text);
+  for (iter = write_iter = results_copy.begin();
+       iter != results_copy.end();
+       ++iter) {
+    if (spellcheck->GetCustomDictionary()->HasWord(
+            text_copy.substr(iter->location, iter->length))) {
+      spellcheck->GetFeedbackSender()->RecordInDictionary(iter->hash);
+    } else {
+      if (write_iter != iter)
+        *write_iter = *iter;
+      ++write_iter;
+    }
+  }
+  results_copy.erase(write_iter, results_copy.end());
+
   Send(new SpellCheckMsg_RespondSpellingService(
       route_id, identifier, success, text, results_copy));
 }
@@ -171,3 +189,7 @@
                markers));
 }
 #endif
+
+SpellcheckService* SpellCheckMessageFilter::GetSpellcheckService() const {
+  return SpellcheckServiceFactory::GetForRenderProcessId(render_process_id_);
+}
diff --git a/chrome/browser/spellchecker/spellcheck_message_filter.h b/chrome/browser/spellchecker/spellcheck_message_filter.h
index 77c8306..885aab1 100644
--- a/chrome/browser/spellchecker/spellcheck_message_filter.h
+++ b/chrome/browser/spellchecker/spellcheck_message_filter.h
@@ -11,6 +11,7 @@
 #include "content/public/browser/browser_message_filter.h"
 
 class SpellCheckMarker;
+class SpellcheckService;
 struct SpellCheckResult;
 
 // A message filter implementation that receives spell checker requests from
@@ -27,6 +28,8 @@
                                  bool* message_was_ok) OVERRIDE;
 
  private:
+  friend class TestingSpellCheckMessageFilter;
+
   virtual ~SpellCheckMessageFilter();
 
   void OnSpellCheckerRequestDictionary();
@@ -61,6 +64,9 @@
       const std::vector<SpellCheckMarker>& markers);
 #endif
 
+  // Can be overridden for testing.
+  virtual SpellcheckService* GetSpellcheckService() const;
+
   int render_process_id_;
 
   // A JSON-RPC client that calls the Spelling service in the background.
diff --git a/chrome/browser/spellchecker/spellcheck_message_filter_unittest.cc b/chrome/browser/spellchecker/spellcheck_message_filter_unittest.cc
index 3407dbd..d0fb26f 100644
--- a/chrome/browser/spellchecker/spellcheck_message_filter_unittest.cc
+++ b/chrome/browser/spellchecker/spellcheck_message_filter_unittest.cc
@@ -2,12 +2,58 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/spellchecker/spellcheck_factory.h"
 #include "chrome/browser/spellchecker/spellcheck_message_filter.h"
+#include "chrome/browser/spellchecker/spellcheck_service.h"
+#include "chrome/common/spellcheck_marker.h"
 #include "chrome/common/spellcheck_messages.h"
-#include "content/public/browser/browser_thread.h"
+#include "chrome/test/base/testing_profile.h"
+#include "content/public/test/test_browser_thread.h"
 #include "ipc/ipc_message.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+class TestingSpellCheckMessageFilter : public SpellCheckMessageFilter {
+ public:
+  TestingSpellCheckMessageFilter()
+      : SpellCheckMessageFilter(0),
+        ui_thread_(content::BrowserThread::UI, &message_loop_),
+        spellcheck_(new SpellcheckService(&profile_)) {}
+
+  virtual bool Send(IPC::Message* message) OVERRIDE {
+    sent_messages.push_back(message);
+    return true;
+  }
+
+  virtual SpellcheckService* GetSpellcheckService() const OVERRIDE {
+    return spellcheck_.get();
+  }
+
+#if !defined(OS_MACOSX)
+  void OnTextCheckComplete(int route_id,
+                           int identifier,
+                           const std::vector<SpellCheckMarker>& markers,
+                           bool success,
+                           const string16& text,
+                           const std::vector<SpellCheckResult>& results) {
+    SpellCheckMessageFilter::OnTextCheckComplete(
+        route_id, identifier, markers, success, text, results);
+  }
+#endif
+
+  ScopedVector<IPC::Message> sent_messages;
+
+ private:
+  virtual ~TestingSpellCheckMessageFilter() {}
+
+  base::MessageLoop message_loop_;
+  content::TestBrowserThread ui_thread_;
+  TestingProfile profile_;
+  scoped_ptr<SpellcheckService> spellcheck_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestingSpellCheckMessageFilter);
+};
+
 TEST(SpellCheckMessageFilterTest, TestOverrideThread) {
   static const uint32 kSpellcheckMessages[] = {
     SpellCheckHostMsg_RequestDictionary::ID,
@@ -17,9 +63,10 @@
     SpellCheckHostMsg_CallSpellingService::ID,
 #endif
   };
-  scoped_refptr<SpellCheckMessageFilter> filter(new SpellCheckMessageFilter(0));
   content::BrowserThread::ID thread;
   IPC::Message message;
+  scoped_refptr<TestingSpellCheckMessageFilter> filter(
+      new TestingSpellCheckMessageFilter);
   for (size_t i = 0; i < arraysize(kSpellcheckMessages); ++i) {
     message.SetHeaderValues(
         0, kSpellcheckMessages[i], IPC::Message::PRIORITY_NORMAL);
@@ -28,3 +75,75 @@
     EXPECT_EQ(content::BrowserThread::UI, thread);
   }
 }
+
+#if !defined(OS_MACOSX)
+TEST(SpellCheckMessageFilterTest, OnTextCheckCompleteTestCustomDictionary) {
+  static const std::string kCustomWord = "Helllo";
+  static const int kRouteId = 0;
+  static const int kCallbackId = 0;
+  static const std::vector<SpellCheckMarker> kMarkers;
+  static const string16 kText = ASCIIToUTF16("Helllo warld.");
+  static const bool kSuccess = true;
+  static const SpellCheckResult::Type kType = SpellCheckResult::SPELLING;
+  static const int kLocation = 7;
+  static const int kLength = 5;
+  static const string16 kReplacement = ASCIIToUTF16("world");
+
+  std::vector<SpellCheckResult> results;
+  results.push_back(SpellCheckResult(
+      SpellCheckResult::SPELLING, 0, 6, ASCIIToUTF16("Hello")));
+  results.push_back(SpellCheckResult(kType, kLocation, kLength, kReplacement));
+
+  scoped_refptr<TestingSpellCheckMessageFilter> filter(
+      new TestingSpellCheckMessageFilter);
+  filter->GetSpellcheckService()->GetCustomDictionary()->AddWord(kCustomWord);
+  filter->OnTextCheckComplete(
+      kRouteId, kCallbackId, kMarkers, kSuccess, kText, results);
+  EXPECT_EQ(static_cast<size_t>(1), filter->sent_messages.size());
+
+  int sent_identifier = -1;
+  bool sent_success = false;
+  string16 sent_text;
+  std::vector<SpellCheckResult> sent_results;
+  bool ok = SpellCheckMsg_RespondSpellingService::Read(filter->sent_messages[0],
+                                                       &sent_identifier,
+                                                       &sent_success,
+                                                       &sent_text,
+                                                       &sent_results);
+  EXPECT_TRUE(ok);
+  EXPECT_EQ(kCallbackId, sent_identifier);
+  EXPECT_EQ(kSuccess, sent_success);
+  EXPECT_EQ(kText, sent_text);
+  EXPECT_EQ(static_cast<size_t>(1), sent_results.size());
+  EXPECT_EQ(kType, sent_results[0].type);
+  EXPECT_EQ(kLocation, sent_results[0].location);
+  EXPECT_EQ(kLength, sent_results[0].length);
+  EXPECT_EQ(kReplacement, sent_results[0].replacement);
+}
+
+TEST(SpellCheckMessageFilterTest, OnTextCheckCompleteTest) {
+  std::vector<SpellCheckResult> results;
+  results.push_back(SpellCheckResult(
+      SpellCheckResult::SPELLING, 0, 6, ASCIIToUTF16("Hello")));
+  results.push_back(SpellCheckResult(
+      SpellCheckResult::SPELLING, 7, 7, ASCIIToUTF16("world")));
+
+  scoped_refptr<TestingSpellCheckMessageFilter> filter(
+      new TestingSpellCheckMessageFilter);
+  filter->OnTextCheckComplete(1, 1, std::vector<SpellCheckMarker>(),
+      true,  ASCIIToUTF16("Helllo walrd"), results);
+  EXPECT_EQ(static_cast<size_t>(1), filter->sent_messages.size());
+
+  int sent_identifier = -1;
+  bool sent_success = false;
+  string16 sent_text;
+  std::vector<SpellCheckResult> sent_results;
+  bool ok = SpellCheckMsg_RespondSpellingService::Read(filter->sent_messages[0],
+                                                       &sent_identifier,
+                                                       &sent_success,
+                                                       &sent_text,
+                                                       &sent_results);
+  EXPECT_TRUE(ok);
+  EXPECT_EQ(static_cast<size_t>(2), sent_results.size());
+}
+#endif
diff --git a/chrome/browser/spellchecker/spellcheck_platform_mac.mm b/chrome/browser/spellchecker/spellcheck_platform_mac.mm
index d64238c..297219a 100644
--- a/chrome/browser/spellchecker/spellcheck_platform_mac.mm
+++ b/chrome/browser/spellchecker/spellcheck_platform_mac.mm
@@ -15,7 +15,7 @@
 #include "base/mac/scoped_nsexception_enabler.h"
 #include "base/metrics/histogram.h"
 #include "base/strings/sys_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/common/spellcheck_common.h"
 #include "chrome/common/spellcheck_messages.h"
 #include "chrome/common/spellcheck_result.h"
diff --git a/chrome/browser/spellchecker/spellcheck_service_browsertest.cc b/chrome/browser/spellchecker/spellcheck_service_browsertest.cc
index cf7b64f..5130600 100644
--- a/chrome/browser/spellchecker/spellcheck_service_browsertest.cc
+++ b/chrome/browser/spellchecker/spellcheck_service_browsertest.cc
@@ -12,7 +12,7 @@
 #include "chrome/common/spellcheck_common.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 namespace {
 
@@ -80,6 +80,6 @@
             SpellcheckService::GetStatusEvent());
   if (file_util::PathExists(bdict_path)) {
     ADD_FAILURE();
-    EXPECT_TRUE(file_util::Delete(bdict_path, true));
+    EXPECT_TRUE(base::Delete(bdict_path, true));
   }
 }
diff --git a/chrome/browser/ssl/ssl_add_cert_handler_mac.mm b/chrome/browser/ssl/ssl_add_cert_handler_mac.mm
index d12e477..a2906f9 100644
--- a/chrome/browser/ssl/ssl_add_cert_handler_mac.mm
+++ b/chrome/browser/ssl/ssl_add_cert_handler_mac.mm
@@ -8,7 +8,6 @@
 #include <SecurityInterface/SFCertificateView.h>
 
 #include "base/logging.h"
-#include "base/memory/scoped_nsobject.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/cocoa/last_active_browser_cocoa.h"
diff --git a/chrome/browser/ssl/ssl_blocking_page.cc b/chrome/browser/ssl/ssl_blocking_page.cc
index 625dab8..5b45b35 100644
--- a/chrome/browser/ssl/ssl_blocking_page.cc
+++ b/chrome/browser/ssl/ssl_blocking_page.cc
@@ -158,6 +158,9 @@
 const char kCondition16Firefox[] = "Condition16SSLFirefox";
 const char kCondition17FancyFirefox[] = "Condition17SSLFancyFirefox";
 const char kCondition18NoImages[] = "Condition18SSLNoImages";
+const char kCondition19Policeman[] = "Condition19SSLPoliceman";
+const char kCondition20Stoplight[] = "Condition20SSLStoplight";
+const char kCondition21Badguy[] = "Condition21SSLBadguy";
 
 }  // namespace
 
diff --git a/chrome/browser/ssl/ssl_blocking_page.h b/chrome/browser/ssl/ssl_blocking_page.h
index bf22613..e0e6d61 100644
--- a/chrome/browser/ssl/ssl_blocking_page.h
+++ b/chrome/browser/ssl/ssl_blocking_page.h
@@ -10,10 +10,10 @@
 
 #include "base/callback.h"
 #include "base/strings/string16.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "content/public/browser/interstitial_page_delegate.h"
-#include "googleurl/src/gurl.h"
 #include "net/ssl/ssl_info.h"
+#include "url/gurl.h"
 
 namespace base {
 class DictionaryValue;
diff --git a/chrome/browser/ssl/ssl_browser_tests.cc b/chrome/browser/ssl/ssl_browser_tests.cc
index 8399a03..1c0c5e1 100644
--- a/chrome/browser/ssl/ssl_browser_tests.cc
+++ b/chrome/browser/ssl/ssl_browser_tests.cc
@@ -8,7 +8,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/content_settings/host_content_settings_map.h"
 #include "chrome/browser/profiles/profile.h"
diff --git a/chrome/browser/ssl/ssl_client_certificate_selector_test.cc b/chrome/browser/ssl/ssl_client_certificate_selector_test.cc
index 8ac9321..da8e463 100644
--- a/chrome/browser/ssl/ssl_client_certificate_selector_test.cc
+++ b/chrome/browser/ssl/ssl_client_certificate_selector_test.cc
@@ -81,8 +81,7 @@
   url_request_ = MakeURLRequest(url_request_context_getter_.get());
 
   auth_requestor_ = new StrictMock<SSLClientAuthRequestorMock>(
-      url_request_,
-      cert_request_info_);
+      url_request_, cert_request_info_.get());
 
   io_loop_finished_event_.Signal();
 }
diff --git a/chrome/browser/ssl/ssl_error_info.cc b/chrome/browser/ssl/ssl_error_info.cc
index 0d1cfe8..a6860dd 100644
--- a/chrome/browser/ssl/ssl_error_info.cc
+++ b/chrome/browser/ssl/ssl_error_info.cc
@@ -8,7 +8,6 @@
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/common/time_format.h"
 #include "content/public/browser/cert_store.h"
-#include "googleurl/src/gurl.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "net/base/escape.h"
@@ -16,6 +15,7 @@
 #include "net/cert/cert_status_flags.h"
 #include "net/ssl/ssl_info.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "url/gurl.h"
 
 SSLErrorInfo::SSLErrorInfo(const string16& title,
                            const string16& details,
diff --git a/chrome/browser/status_icons/status_icon.cc b/chrome/browser/status_icons/status_icon.cc
index 5398f74..00270d2 100644
--- a/chrome/browser/status_icons/status_icon.cc
+++ b/chrome/browser/status_icons/status_icon.cc
@@ -29,7 +29,16 @@
   FOR_EACH_OBSERVER(StatusIconObserver, observers_, OnStatusIconClicked());
 }
 
+#if defined(OS_WIN)
+void StatusIcon::DispatchBalloonClickEvent() {
+  FOR_EACH_OBSERVER(StatusIconObserver, observers_, OnBalloonClicked());
+}
+#endif
+
 void StatusIcon::SetContextMenu(ui::MenuModel* menu) {
+  // The UI may been showing a menu for the current model, don't destroy it
+  // until we've notified the UI of the change.
+  scoped_ptr<ui::MenuModel> old_menu = context_menu_contents_.Pass();
   context_menu_contents_.reset(menu);
   UpdatePlatformContextMenu(menu);
 }
diff --git a/chrome/browser/status_icons/status_icon.h b/chrome/browser/status_icons/status_icon.h
index 0303946..8d846a5 100644
--- a/chrome/browser/status_icons/status_icon.h
+++ b/chrome/browser/status_icons/status_icon.h
@@ -56,6 +56,9 @@
 
   // Dispatches a click event to the observers.
   void DispatchClickEvent();
+#if defined(OS_WIN)
+  void DispatchBalloonClickEvent();
+#endif
 
  protected:
   // Invoked after a call to SetContextMenu() to let the platform-specific
diff --git a/chrome/browser/status_icons/status_icon_observer.h b/chrome/browser/status_icons/status_icon_observer.h
index 28ee3d8..4183567 100644
--- a/chrome/browser/status_icons/status_icon_observer.h
+++ b/chrome/browser/status_icons/status_icon_observer.h
@@ -16,6 +16,13 @@
   // This will only be fired for this platform if no context menu is present.
   virtual void OnStatusIconClicked() = 0;
 
+#if defined(OS_WIN)
+  // Called when the user clicks on a balloon generated for a system tray icon.
+  // TODO(dewittj): Implement on platforms other than Windows.  Currently this
+  // event will never fire on non-Windows platforms.
+  virtual void OnBalloonClicked() {}
+#endif
+
  protected:
   virtual ~StatusIconObserver() {}
 };
diff --git a/chrome/browser/storage_monitor/image_capture_device.h b/chrome/browser/storage_monitor/image_capture_device.h
index 0860d9d..82fd1b5 100644
--- a/chrome/browser/storage_monitor/image_capture_device.h
+++ b/chrome/browser/storage_monitor/image_capture_device.h
@@ -11,8 +11,8 @@
 #include "base/files/file_path.h"
 #include "base/mac/cocoa_protocols.h"
 #include "base/mac/foundation_util.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/ref_counted.h"
-#include "base/memory/scoped_nsobject.h"
 #include "base/memory/weak_ptr.h"
 #include "base/platform_file.h"
 #include "base/strings/string_util.h"
@@ -58,7 +58,7 @@
 @interface ImageCaptureDevice
     : NSObject<ICCameraDeviceDelegate, ICCameraDeviceDownloadDelegate> {
  @private
-  scoped_nsobject<ICCameraDevice> camera_;
+  base::scoped_nsobject<ICCameraDevice> camera_;
   base::WeakPtr<ImageCaptureDeviceListener> listener_;
   bool closing_;
 }
diff --git a/chrome/browser/storage_monitor/image_capture_device.mm b/chrome/browser/storage_monitor/image_capture_device.mm
index 15fb913..7a4fe86 100644
--- a/chrome/browser/storage_monitor/image_capture_device.mm
+++ b/chrome/browser/storage_monitor/image_capture_device.mm
@@ -13,7 +13,7 @@
                 const base::FilePath& desired_filename,
                 base::PlatformFileError* result) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
-  bool success = file_util::ReplaceFile(downloaded_filename, desired_filename);
+  bool success = base::ReplaceFile(downloaded_filename, desired_filename, NULL);
   *result = success ? base::PLATFORM_FILE_OK
                     : base::PLATFORM_FILE_ERROR_NOT_FOUND;
 }
diff --git a/chrome/browser/storage_monitor/image_capture_device_manager.h b/chrome/browser/storage_monitor/image_capture_device_manager.h
index 22297c9..bc8c09e 100644
--- a/chrome/browser/storage_monitor/image_capture_device_manager.h
+++ b/chrome/browser/storage_monitor/image_capture_device_manager.h
@@ -8,7 +8,7 @@
 #import <Foundation/Foundation.h>
 #include <string>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/storage_monitor/storage_monitor.h"
 
 @protocol ICDeviceBrowserDelegate;
@@ -39,7 +39,7 @@
   void SetNotifications(StorageMonitor::Receiver* notifications);
 
  private:
-  scoped_nsobject<ImageCaptureDeviceManagerImpl> device_browser_;
+  base::scoped_nsobject<ImageCaptureDeviceManagerImpl> device_browser_;
 };
 
 }  // namespace chrome
diff --git a/chrome/browser/storage_monitor/image_capture_device_manager.mm b/chrome/browser/storage_monitor/image_capture_device_manager.mm
index cfd5057..91191b4 100644
--- a/chrome/browser/storage_monitor/image_capture_device_manager.mm
+++ b/chrome/browser/storage_monitor/image_capture_device_manager.mm
@@ -25,8 +25,8 @@
 @interface ImageCaptureDeviceManagerImpl
     : NSObject<ICDeviceBrowserDelegate> {
  @private
-  scoped_nsobject<ICDeviceBrowser> deviceBrowser_;
-  scoped_nsobject<NSMutableArray> cameras_;
+  base::scoped_nsobject<ICDeviceBrowser> deviceBrowser_;
+  base::scoped_nsobject<NSMutableArray> cameras_;
 
   // Guaranteed to outlive this class.
   // TODO(gbillock): Update when ownership chains go up through
diff --git a/chrome/browser/storage_monitor/image_capture_device_manager_unittest.mm b/chrome/browser/storage_monitor/image_capture_device_manager_unittest.mm
index 2b3a16a..f55576f 100644
--- a/chrome/browser/storage_monitor/image_capture_device_manager_unittest.mm
+++ b/chrome/browser/storage_monitor/image_capture_device_manager_unittest.mm
@@ -45,7 +45,7 @@
 
 @interface MockICCameraDevice : ICCameraDevice {
  @private
-  scoped_nsobject<NSMutableArray> allMediaFiles_;
+  base::scoped_nsobject<NSMutableArray> allMediaFiles_;
 }
 
 - (void)addMediaFile:(ICCameraFile*)file;
@@ -129,7 +129,7 @@
 
 @interface MockICCameraFolder : ICCameraFolder {
  @private
-  scoped_nsobject<NSString> name_;
+  base::scoped_nsobject<NSString> name_;
 }
 
 - (id)initWithName:(NSString*)name;
@@ -157,9 +157,9 @@
 
 @interface MockICCameraFile : ICCameraFile {
  @private
-  scoped_nsobject<NSString> name_;
-  scoped_nsobject<NSDate> date_;
-  scoped_nsobject<MockICCameraFolder> parent_;
+  base::scoped_nsobject<NSString> name_;
+  base::scoped_nsobject<NSDate> date_;
+  base::scoped_nsobject<MockICCameraFolder> parent_;
 }
 
 - (id)init:(NSString*)name;
@@ -262,7 +262,7 @@
   MockICCameraDevice* AttachDevice(
       chrome::ImageCaptureDeviceManager* manager) {
     // Ownership will be passed to the device browser delegate.
-    scoped_nsobject<MockICCameraDevice> device(
+    base::scoped_nsobject<MockICCameraDevice> device(
         [[MockICCameraDevice alloc] init]);
     id<ICDeviceBrowserDelegate> delegate = manager->device_browser();
     [delegate deviceBrowser:nil didAddDevice:device moreComing:NO];
@@ -305,17 +305,16 @@
   EXPECT_FALSE(chrome::ImageCaptureDeviceManager::deviceForUUID(
       "nonexistent"));
 
-  scoped_nsobject<ImageCaptureDevice> camera(
-      [chrome::ImageCaptureDeviceManager::deviceForUUID(kDeviceId)
-          retain]);
+  base::scoped_nsobject<ImageCaptureDevice> camera(
+      [chrome::ImageCaptureDeviceManager::deviceForUUID(kDeviceId) retain]);
 
   [camera setListener:listener_.AsWeakPtr()];
   [camera open];
 
-  scoped_nsobject<MockICCameraFile> picture1(
+  base::scoped_nsobject<MockICCameraFile> picture1(
       [[MockICCameraFile alloc] init:@"pic1"]);
   [camera cameraDevice:nil didAddItem:picture1];
-  scoped_nsobject<MockICCameraFile> picture2(
+  base::scoped_nsobject<MockICCameraFile> picture2(
       [[MockICCameraFile alloc] init:@"pic2"]);
   [camera cameraDevice:nil didAddItem:picture2];
   ASSERT_EQ(2U, listener_.items().size());
@@ -339,9 +338,8 @@
   manager.SetNotifications(monitor_.receiver());
   ICCameraDevice* device = AttachDevice(&manager);
 
-  scoped_nsobject<ImageCaptureDevice> camera(
-      [chrome::ImageCaptureDeviceManager::deviceForUUID(kDeviceId)
-          retain]);
+  base::scoped_nsobject<ImageCaptureDevice> camera(
+      [chrome::ImageCaptureDeviceManager::deviceForUUID(kDeviceId) retain]);
 
   [camera setListener:listener_.AsWeakPtr()];
   [camera open];
@@ -359,18 +357,16 @@
   manager.SetNotifications(monitor_.receiver());
   MockICCameraDevice* device = AttachDevice(&manager);
 
-  scoped_nsobject<ImageCaptureDevice> camera(
-      [chrome::ImageCaptureDeviceManager::deviceForUUID(kDeviceId)
-          retain]);
+  base::scoped_nsobject<ImageCaptureDevice> camera(
+      [chrome::ImageCaptureDeviceManager::deviceForUUID(kDeviceId) retain]);
 
   [camera setListener:listener_.AsWeakPtr()];
   [camera open];
 
   std::string kTestFileName("pic1");
 
-  scoped_nsobject<MockICCameraFile> picture1(
-      [[MockICCameraFile alloc]
-          init:base::SysUTF8ToNSString(kTestFileName)]);
+  base::scoped_nsobject<MockICCameraFile> picture1(
+      [[MockICCameraFile alloc] init:base::SysUTF8ToNSString(kTestFileName)]);
   [device addMediaFile:picture1];
   [camera cameraDevice:nil didAddItem:picture1];
 
@@ -417,17 +413,15 @@
   manager.SetNotifications(monitor_.receiver());
   MockICCameraDevice* device = AttachDevice(&manager);
 
-  scoped_nsobject<ImageCaptureDevice> camera(
-      [chrome::ImageCaptureDeviceManager::deviceForUUID(kDeviceId)
-          retain]);
+  base::scoped_nsobject<ImageCaptureDevice> camera(
+      [chrome::ImageCaptureDeviceManager::deviceForUUID(kDeviceId) retain]);
 
   [camera setListener:listener_.AsWeakPtr()];
   [camera open];
 
   std::string kTestFileName("pic1");
-  scoped_nsobject<MockICCameraFile> picture1(
-      [[MockICCameraFile alloc]
-          init:base::SysUTF8ToNSString(kTestFileName)]);
+  base::scoped_nsobject<MockICCameraFile> picture1(
+      [[MockICCameraFile alloc] init:base::SysUTF8ToNSString(kTestFileName)]);
   [picture1 setParent:base::SysUTF8ToNSString("dir")];
   [device addMediaFile:picture1];
   [camera cameraDevice:nil didAddItem:picture1];
diff --git a/chrome/browser/storage_monitor/media_storage_util.cc b/chrome/browser/storage_monitor/media_storage_util.cc
index 9b1e812..785440c 100644
--- a/chrome/browser/storage_monitor/media_storage_util.cc
+++ b/chrome/browser/storage_monitor/media_storage_util.cc
@@ -49,17 +49,6 @@
 
 typedef std::vector<StorageInfo> StorageInfoList;
 
-bool IsRemovableStorageAttached(const std::string& id) {
-  StorageInfoList devices =
-      StorageMonitor::GetInstance()->GetAllAvailableStorages();
-  for (StorageInfoList::const_iterator it = devices.begin();
-       it != devices.end(); ++it) {
-    if (StorageInfo::IsRemovableDevice(id) && it->device_id() == id)
-      return true;
-  }
-  return false;
-}
-
 base::FilePath::StringType FindRemovableStorageLocationById(
     const std::string& device_id) {
   StorageInfoList devices =
@@ -95,7 +84,7 @@
       continue;
     }
 
-    if (!IsRemovableStorageAttached(*it))
+    if (!MediaStorageUtil::IsRemovableStorageAttached(*it))
       missing_devices.insert(*it);
   }
 
@@ -252,4 +241,15 @@
                             DEVICE_INFO_BUCKET_BOUNDARY);
 }
 
+bool MediaStorageUtil::IsRemovableStorageAttached(const std::string& id) {
+  StorageInfoList devices =
+      StorageMonitor::GetInstance()->GetAllAvailableStorages();
+  for (StorageInfoList::const_iterator it = devices.begin();
+       it != devices.end(); ++it) {
+    if (StorageInfo::IsRemovableDevice(id) && it->device_id() == id)
+      return true;
+  }
+  return false;
+}
+
 }  // namespace chrome
diff --git a/chrome/browser/storage_monitor/media_storage_util.h b/chrome/browser/storage_monitor/media_storage_util.h
index d1f7d7d..c627403 100644
--- a/chrome/browser/storage_monitor/media_storage_util.h
+++ b/chrome/browser/storage_monitor/media_storage_util.h
@@ -57,6 +57,10 @@
                                         const std::string& device_uuid,
                                         const string16& device_label);
 
+  // Returns true if the |id| is both a removable device and also
+  // currently attached.
+  static bool IsRemovableStorageAttached(const std::string& id);
+
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(MediaStorageUtil);
 };
diff --git a/chrome/browser/storage_monitor/storage_monitor.cc b/chrome/browser/storage_monitor/storage_monitor.cc
index 0513739..6d27d3b 100644
--- a/chrome/browser/storage_monitor/storage_monitor.cc
+++ b/chrome/browser/storage_monitor/storage_monitor.cc
@@ -61,7 +61,7 @@
   return results;
 }
 
-void StorageMonitor::Initialize(base::Closure callback) {
+void StorageMonitor::EnsureInitialized(base::Closure callback) {
   DCHECK(thread_checker_.CalledOnValidThread());
   if (initialized_) {
     if (!callback.is_null())
diff --git a/chrome/browser/storage_monitor/storage_monitor.h b/chrome/browser/storage_monitor/storage_monitor.h
index dfed9e8..5661c80 100644
--- a/chrome/browser/storage_monitor/storage_monitor.h
+++ b/chrome/browser/storage_monitor/storage_monitor.h
@@ -72,14 +72,14 @@
   // somewhat shorter than a process Singleton.
   static StorageMonitor* GetInstance();
 
-  // Initialize the storage monitor. The provided callback, if non-null,
-  // will be called when initialization is complete. If initialization has
-  // already completed, this callback will be invoked within the calling stack.
-  // Before the callback is run, calls to |GetAllAvailableStorages| and
+  // Ensures that the storage monitor is initialized. The provided callback, If
+  // non-null, will be called when initialization is complete. If initialization
+  // has already completed, this callback will be invoked within the calling
+  // stack. Before the callback is run, calls to |GetAllAvailableStorages| and
   // |GetStorageInfoForPath| may not return the correct results. In addition,
   // registered observers will not be notified on device attachment/detachment.
   // Should be invoked on the UI thread; callbacks will be run on the UI thread.
-  void Initialize(base::Closure callback);
+  void EnsureInitialized(base::Closure callback);
 
   // Return true if the storage monitor has already been initialized.
   bool IsInitialized();
diff --git a/chrome/browser/storage_monitor/storage_monitor_linux_unittest.cc b/chrome/browser/storage_monitor/storage_monitor_linux_unittest.cc
index 55fc877..a8c82a5 100644
--- a/chrome/browser/storage_monitor/storage_monitor_linux_unittest.cc
+++ b/chrome/browser/storage_monitor/storage_monitor_linux_unittest.cc
@@ -235,7 +235,7 @@
   void RemoveDCIMDirFromMountPoint(const std::string& dir) {
     base::FilePath dcim =
         scoped_temp_dir_.path().AppendASCII(dir).Append(kDCIMDirectoryName);
-    file_util::Delete(dcim, false);
+    base::Delete(dcim, false);
   }
 
   MockRemovableStorageObserver& observer() {
@@ -558,7 +558,7 @@
   MtabTestData test_data5[] = {
     MtabTestData(kDeviceNoDCIM, test_path_b.value(), kValidFS),
   };
-  file_util::Delete(test_path_b.Append(kDCIMDirectoryName), false);
+  base::Delete(test_path_b.Append(kDCIMDirectoryName), false);
   AppendToMtabAndRunLoop(test_data5, arraysize(test_data5));
   EXPECT_EQ(4, observer().attach_calls());
   EXPECT_EQ(2, observer().detach_calls());
diff --git a/chrome/browser/storage_monitor/storage_monitor_mac.h b/chrome/browser/storage_monitor/storage_monitor_mac.h
index 383f089..e313119 100644
--- a/chrome/browser/storage_monitor/storage_monitor_mac.h
+++ b/chrome/browser/storage_monitor/storage_monitor_mac.h
@@ -58,7 +58,7 @@
   bool FindDiskWithMountPoint(const base::FilePath& mount_point,
                               StorageInfo* info) const;
 
-  base::mac::ScopedCFTypeRef<DASessionRef> session_;
+  base::ScopedCFTypeRef<DASessionRef> session_;
   // Maps disk bsd names to disk info objects. This map tracks all mountable
   // devices on the system, though only notifications for removable devices are
   // posted.
diff --git a/chrome/browser/storage_monitor/storage_monitor_mac.mm b/chrome/browser/storage_monitor/storage_monitor_mac.mm
index 9c5ca63..346f958 100644
--- a/chrome/browser/storage_monitor/storage_monitor_mac.mm
+++ b/chrome/browser/storage_monitor/storage_monitor_mac.mm
@@ -74,7 +74,7 @@
       dict, kDADiskDescriptionVolumeUUIDKey);
   std::string unique_id;
   if (uuid) {
-    base::mac::ScopedCFTypeRef<CFStringRef> uuid_string(
+    base::ScopedCFTypeRef<CFStringRef> uuid_string(
         CFUUIDCreateString(NULL, uuid));
     if (uuid_string.get())
       unique_id = base::SysCFStringRefToUTF8(uuid_string);
@@ -105,7 +105,7 @@
 
 void GetDiskInfoAndUpdateOnFileThread(
     const base::WeakPtr<StorageMonitorMac>& monitor,
-    base::mac::ScopedCFTypeRef<CFDictionaryRef> dict,
+    base::ScopedCFTypeRef<CFDictionaryRef> dict,
     StorageMonitorMac::UpdateType update_type) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
 
@@ -125,7 +125,7 @@
 struct EjectDiskOptions {
   std::string bsd_name;
   base::Callback<void(StorageMonitor::EjectStatus)> callback;
-  base::mac::ScopedCFTypeRef<DADiskRef> disk;
+  base::ScopedCFTypeRef<DADiskRef> disk;
 };
 
 void PostEjectCallback(DADiskRef disk,
@@ -289,7 +289,7 @@
 
   receiver()->ProcessDetach(device_id);
 
-  base::mac::ScopedCFTypeRef<DADiskRef> disk(
+  base::ScopedCFTypeRef<DADiskRef> disk(
       DADiskCreateFromBSDName(NULL, session_, bsd_name.c_str()));
   if (!disk.get()) {
     callback.Run(StorageMonitor::EJECT_FAILURE);
@@ -337,7 +337,7 @@
 
   pending_disk_updates_++;
 
-  base::mac::ScopedCFTypeRef<CFDictionaryRef> dict(DADiskCopyDescription(disk));
+  base::ScopedCFTypeRef<CFDictionaryRef> dict(DADiskCopyDescription(disk));
   content::BrowserThread::PostTask(
       content::BrowserThread::FILE,
       FROM_HERE,
diff --git a/chrome/browser/storage_monitor/storage_monitor_unittest.cc b/chrome/browser/storage_monitor/storage_monitor_unittest.cc
index 8acce30..9be3a50 100644
--- a/chrome/browser/storage_monitor/storage_monitor_unittest.cc
+++ b/chrome/browser/storage_monitor/storage_monitor_unittest.cc
@@ -17,8 +17,8 @@
   EXPECT_FALSE(monitor.init_called_);
 
   base::WaitableEvent event(false, false);
-  monitor.Initialize(base::Bind(&base::WaitableEvent::Signal,
-                                base::Unretained(&event)));
+  monitor.EnsureInitialized(base::Bind(&base::WaitableEvent::Signal,
+                                       base::Unretained(&event)));
   EXPECT_TRUE(monitor.init_called_);
   EXPECT_FALSE(event.IsSignaled());
   monitor.MarkInitialized();
diff --git a/chrome/browser/storage_monitor/test_storage_monitor_win.cc b/chrome/browser/storage_monitor/test_storage_monitor_win.cc
index dafb597..e78b5e6 100644
--- a/chrome/browser/storage_monitor/test_storage_monitor_win.cc
+++ b/chrome/browser/storage_monitor/test_storage_monitor_win.cc
@@ -32,5 +32,9 @@
   return volume_mount_watcher_.get();
 }
 
+StorageMonitor::Receiver* TestStorageMonitorWin::receiver() const {
+  return StorageMonitor::receiver();
+}
+
 }  // namespace test
 }  // namespace chrome
diff --git a/chrome/browser/storage_monitor/test_storage_monitor_win.h b/chrome/browser/storage_monitor/test_storage_monitor_win.h
index bb29d9f..f7608eb 100644
--- a/chrome/browser/storage_monitor/test_storage_monitor_win.h
+++ b/chrome/browser/storage_monitor/test_storage_monitor_win.h
@@ -31,6 +31,8 @@
 
   VolumeMountWatcherWin* volume_mount_watcher();
 
+  virtual Receiver* receiver() const OVERRIDE;
+
  private:
   DISALLOW_COPY_AND_ASSIGN(TestStorageMonitorWin);
 };
diff --git a/chrome/browser/storage_monitor/volume_mount_watcher_win.cc b/chrome/browser/storage_monitor/volume_mount_watcher_win.cc
index 121c3ce..a4e19f2 100644
--- a/chrome/browser/storage_monitor/volume_mount_watcher_win.cc
+++ b/chrome/browser/storage_monitor/volume_mount_watcher_win.cc
@@ -18,7 +18,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task_runner_util.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/win/scoped_handle.h"
 #include "chrome/browser/storage_monitor/media_storage_util.h"
 #include "chrome/browser/storage_monitor/storage_info.h"
diff --git a/chrome/browser/sync/glue/android_invalidator_bridge.cc b/chrome/browser/sync/glue/android_invalidator_bridge.cc
deleted file mode 100644
index 31cd87e..0000000
--- a/chrome/browser/sync/glue/android_invalidator_bridge.cc
+++ /dev/null
@@ -1,219 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/sync/glue/android_invalidator_bridge.h"
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "chrome/common/chrome_notification_types.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/notification_service.h"
-#include "sync/internal_api/public/base/model_type.h"
-#include "sync/notifier/invalidation_handler.h"
-#include "sync/notifier/invalidator_registrar.h"
-
-using content::BrowserThread;
-
-namespace browser_sync {
-
-class AndroidInvalidatorBridge::Core
-    : public base::RefCountedThreadSafe<Core> {
- public:
-  // Created on UI thread.
-  explicit Core(
-      const scoped_refptr<base::SequencedTaskRunner>& sync_task_runner);
-
-  // All member functions below must be called on the sync task runner.
-
-  void InitializeOnSyncThread();
-  void CleanupOnSyncThread();
-
-  void RegisterHandler(syncer::InvalidationHandler* handler);
-  void UpdateRegisteredIds(syncer::InvalidationHandler* handler,
-                           const syncer::ObjectIdSet& ids);
-  void UnregisterHandler(syncer::InvalidationHandler* handler);
-
-  void EmitInvalidation(
-      const syncer::ObjectIdInvalidationMap& invalidation_map);
-
-  bool IsHandlerRegisteredForTest(syncer::InvalidationHandler* handler) const;
-  syncer::ObjectIdSet GetRegisteredIdsForTest(
-      syncer::InvalidationHandler* handler) const;
-
- private:
-  friend class base::RefCountedThreadSafe<Core>;
-
-  // Destroyed on the UI thread or on |sync_task_runner_|.
-  ~Core();
-
-  const scoped_refptr<base::SequencedTaskRunner> sync_task_runner_;
-
-  // Used only on |sync_task_runner_|.
-  scoped_ptr<syncer::InvalidatorRegistrar> invalidator_registrar_;
-};
-
-AndroidInvalidatorBridge::Core::Core(
-    const scoped_refptr<base::SequencedTaskRunner>& sync_task_runner)
-    : sync_task_runner_(sync_task_runner) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  DCHECK(sync_task_runner_.get());
-}
-
-AndroidInvalidatorBridge::Core::~Core() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) ||
-         sync_task_runner_->RunsTasksOnCurrentThread());
-  DCHECK(!invalidator_registrar_.get());
-}
-
-void AndroidInvalidatorBridge::Core::InitializeOnSyncThread() {
-  invalidator_registrar_.reset(new syncer::InvalidatorRegistrar());
-}
-
-void AndroidInvalidatorBridge::Core::CleanupOnSyncThread() {
-  invalidator_registrar_.reset();
-}
-
-void AndroidInvalidatorBridge::Core::RegisterHandler(
-    syncer::InvalidationHandler* handler) {
-  DCHECK(sync_task_runner_->RunsTasksOnCurrentThread());
-  invalidator_registrar_->RegisterHandler(handler);
-}
-
-void AndroidInvalidatorBridge::Core::UpdateRegisteredIds(
-    syncer::InvalidationHandler* handler,
-    const syncer::ObjectIdSet& ids) {
-  DCHECK(sync_task_runner_->RunsTasksOnCurrentThread());
-  invalidator_registrar_->UpdateRegisteredIds(handler, ids);
-}
-
-void AndroidInvalidatorBridge::Core::UnregisterHandler(
-    syncer::InvalidationHandler* handler) {
-  DCHECK(sync_task_runner_->RunsTasksOnCurrentThread());
-  invalidator_registrar_->UnregisterHandler(handler);
-}
-
-void AndroidInvalidatorBridge::Core::EmitInvalidation(
-    const syncer::ObjectIdInvalidationMap& invalidation_map) {
-  DCHECK(sync_task_runner_->RunsTasksOnCurrentThread());
-  const syncer::ObjectIdInvalidationMap& effective_invalidation_map =
-      invalidation_map.empty() ?
-      ObjectIdSetToInvalidationMap(
-          invalidator_registrar_->GetAllRegisteredIds(), std::string()) :
-      invalidation_map;
-
-  invalidator_registrar_->DispatchInvalidationsToHandlers(
-      effective_invalidation_map);
-}
-
-bool AndroidInvalidatorBridge::Core::IsHandlerRegisteredForTest(
-    syncer::InvalidationHandler* handler) const {
-  DCHECK(sync_task_runner_->RunsTasksOnCurrentThread());
-  return invalidator_registrar_->IsHandlerRegisteredForTest(handler);
-}
-
-syncer::ObjectIdSet
-AndroidInvalidatorBridge::Core::GetRegisteredIdsForTest(
-    syncer::InvalidationHandler* handler) const {
-  DCHECK(sync_task_runner_->RunsTasksOnCurrentThread());
-  return invalidator_registrar_->GetRegisteredIds(handler);
-}
-
-AndroidInvalidatorBridge::AndroidInvalidatorBridge(
-    const Profile* profile,
-    const scoped_refptr<base::SequencedTaskRunner>& sync_task_runner)
-    : sync_task_runner_(sync_task_runner),
-      core_(new Core(sync_task_runner_)) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  DCHECK(profile);
-  registrar_.Add(this, chrome::NOTIFICATION_SYNC_REFRESH_REMOTE,
-                 content::Source<Profile>(profile));
-
-  if (!sync_task_runner_->PostTask(
-          FROM_HERE, base::Bind(&Core::InitializeOnSyncThread, core_))) {
-    NOTREACHED();
-  }
-}
-
-AndroidInvalidatorBridge::~AndroidInvalidatorBridge() {}
-
-void AndroidInvalidatorBridge::StopForShutdown() {
-  if (!sync_task_runner_->PostTask(
-          FROM_HERE, base::Bind(&Core::CleanupOnSyncThread, core_))) {
-    NOTREACHED();
-  }
-}
-
-void AndroidInvalidatorBridge::RegisterHandler(
-    syncer::InvalidationHandler* handler) {
-  DCHECK(sync_task_runner_->RunsTasksOnCurrentThread());
-  core_->RegisterHandler(handler);
-}
-
-void AndroidInvalidatorBridge::UpdateRegisteredIds(
-    syncer::InvalidationHandler* handler,
-    const syncer::ObjectIdSet& ids) {
-  DCHECK(sync_task_runner_->RunsTasksOnCurrentThread());
-  core_->UpdateRegisteredIds(handler, ids);
-}
-
-void AndroidInvalidatorBridge::UnregisterHandler(
-    syncer::InvalidationHandler* handler) {
-  DCHECK(sync_task_runner_->RunsTasksOnCurrentThread());
-  core_->UnregisterHandler(handler);
-}
-
-void AndroidInvalidatorBridge::Acknowledge(
-    const invalidation::ObjectId& id, const syncer::AckHandle& ack_handle) {
-  // Do nothing.
-}
-
-syncer::InvalidatorState AndroidInvalidatorBridge::GetInvalidatorState() const {
-  return syncer::INVALIDATIONS_ENABLED;
-}
-
-void AndroidInvalidatorBridge::UpdateCredentials(
-    const std::string& email, const std::string& token) { }
-
-void AndroidInvalidatorBridge::SendInvalidation(
-    const syncer::ObjectIdInvalidationMap& invalidation_map) { }
-
-bool AndroidInvalidatorBridge::IsHandlerRegisteredForTest(
-    syncer::InvalidationHandler* handler) const {
-  DCHECK(sync_task_runner_->RunsTasksOnCurrentThread());
-  return core_->IsHandlerRegisteredForTest(handler);
-}
-
-syncer::ObjectIdSet AndroidInvalidatorBridge::GetRegisteredIdsForTest(
-    syncer::InvalidationHandler* handler) const {
-  DCHECK(sync_task_runner_->RunsTasksOnCurrentThread());
-  return core_->GetRegisteredIdsForTest(handler);
-}
-
-void AndroidInvalidatorBridge::Observe(
-    int type,
-    const content::NotificationSource& source,
-    const content::NotificationDetails& details) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  DCHECK_EQ(type, chrome::NOTIFICATION_SYNC_REFRESH_REMOTE);
-
-  // TODO(akalin): Use ObjectIdInvalidationMap here instead.  We'll have to
-  // make sure all emitters of the relevant notifications also use
-  // ObjectIdInvalidationMap.
-  content::Details<const syncer::ModelTypeInvalidationMap>
-      state_details(details);
-  const syncer::ModelTypeInvalidationMap& invalidation_map =
-      *(state_details.ptr());
-  if (!sync_task_runner_->PostTask(
-          FROM_HERE,
-          base::Bind(&Core::EmitInvalidation,
-                     core_,
-                     ModelTypeInvalidationMapToObjectIdInvalidationMap(
-                         invalidation_map)))) {
-    NOTREACHED();
-  }
-}
-
-}  // namespace browser_sync
diff --git a/chrome/browser/sync/glue/android_invalidator_bridge.h b/chrome/browser/sync/glue/android_invalidator_bridge.h
deleted file mode 100644
index ec1baae..0000000
--- a/chrome/browser/sync/glue/android_invalidator_bridge.h
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_SYNC_GLUE_ANDROID_INVALIDATOR_BRIDGE_H_
-#define CHROME_BROWSER_SYNC_GLUE_ANDROID_INVALIDATOR_BRIDGE_H_
-
-#include "base/compiler_specific.h"
-#include "base/memory/ref_counted.h"
-#include "base/sequenced_task_runner.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
-#include "sync/notifier/invalidator.h"
-
-class Profile;
-
-namespace syncer {
-class InvalidationHandler;
-}  // namespace
-
-namespace browser_sync {
-
-// A bridge that converts Chrome events on the UI thread to sync
-// notifications on the sync task runner.
-//
-// Listens to NOTIFICATION_SYNC_REFRESH_REMOTE (on the UI thread) and triggers
-// each observer's OnIncomingNotification method on these notifications (on the
-// sync task runner).  Android clients receive invalidations through this
-// mechanism exclusively, hence the name.
-class AndroidInvalidatorBridge
-    : public content::NotificationObserver, syncer::Invalidator {
- public:
-  // Must be created and destroyed on the UI thread.
-  AndroidInvalidatorBridge(
-      const Profile* profile,
-      const scoped_refptr<base::SequencedTaskRunner>& sync_task_runner);
-  virtual ~AndroidInvalidatorBridge();
-
-  // Must be called on the UI thread while the sync task runner is still
-  // around.  No other member functions on the sync thread may be called after
-  // this is called.
-  void StopForShutdown();
-
-  // Invalidator implementation.  Must be called on the sync task runner.
-  virtual void RegisterHandler(syncer::InvalidationHandler* handler) OVERRIDE;
-  virtual void UpdateRegisteredIds(syncer::InvalidationHandler* handler,
-                                   const syncer::ObjectIdSet& ids) OVERRIDE;
-  virtual void UnregisterHandler(syncer::InvalidationHandler* handler) OVERRIDE;
-  virtual void Acknowledge(const invalidation::ObjectId& id,
-                           const syncer::AckHandle& ack_handle) OVERRIDE;
-  virtual syncer::InvalidatorState GetInvalidatorState() const OVERRIDE;
-
-  // The following members of the Invalidator interface are not applicable to
-  // this invalidator and are implemented as no-ops.
-  virtual void UpdateCredentials(
-      const std::string& email, const std::string& token) OVERRIDE;
-  virtual void SendInvalidation(
-      const syncer::ObjectIdInvalidationMap& invalidation_map) OVERRIDE;
-
-  bool IsHandlerRegisteredForTest(
-      syncer::InvalidationHandler* handler) const;
-  syncer::ObjectIdSet GetRegisteredIdsForTest(
-      syncer::InvalidationHandler* handler) const;
-
-  // NotificationObserver implementation. Called on UI thread.
-  virtual void Observe(int type,
-                       const content::NotificationSource& source,
-                       const content::NotificationDetails& details) OVERRIDE;
-
- private:
-  // Inner class to hold all the bits used on |sync_task_runner_|.
-  class Core;
-
-  const scoped_refptr<base::SequencedTaskRunner> sync_task_runner_;
-
-  // Created on the UI thread, used only on |sync_task_runner_|.
-  const scoped_refptr<Core> core_;
-
-  // Used only on the UI thread.
-  content::NotificationRegistrar registrar_;
-};
-
-}  // namespace browser_sync
-
-#endif  // CHROME_BROWSER_SYNC_GLUE_ANDROID_INVALIDATOR_BRIDGE_H_
diff --git a/chrome/browser/sync/glue/android_invalidator_bridge_proxy.cc b/chrome/browser/sync/glue/android_invalidator_bridge_proxy.cc
deleted file mode 100644
index 8ed4053..0000000
--- a/chrome/browser/sync/glue/android_invalidator_bridge_proxy.cc
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/sync/glue/android_invalidator_bridge_proxy.h"
-
-#include "chrome/browser/sync/glue/android_invalidator_bridge.h"
-
-using std::string;
-using syncer::InvalidatorState;
-
-namespace browser_sync {
-
-AndroidInvalidatorBridgeProxy::AndroidInvalidatorBridgeProxy(
-    AndroidInvalidatorBridge* bridge)
-    : bridge_(bridge) {
-  DCHECK(bridge_);
-}
-
-AndroidInvalidatorBridgeProxy::~AndroidInvalidatorBridgeProxy() {
-}
-
-void AndroidInvalidatorBridgeProxy::RegisterHandler(
-    syncer::InvalidationHandler* handler) {
-  bridge_->RegisterHandler(handler);
-}
-
-void AndroidInvalidatorBridgeProxy::UpdateRegisteredIds(
-    syncer::InvalidationHandler* handler,
-    const syncer::ObjectIdSet& ids) {
-  bridge_->UpdateRegisteredIds(handler, ids);
-}
-
-InvalidatorState AndroidInvalidatorBridgeProxy::GetInvalidatorState() const {
-  return bridge_->GetInvalidatorState();
-}
-
-void AndroidInvalidatorBridgeProxy::UnregisterHandler(
-    syncer::InvalidationHandler* handler) {
-  bridge_->UnregisterHandler(handler);
-}
-
-void AndroidInvalidatorBridgeProxy::Acknowledge(
-    const invalidation::ObjectId& id,
-    const syncer::AckHandle& ack_handle) {
-  bridge_->Acknowledge(id, ack_handle);
-}
-
-void AndroidInvalidatorBridgeProxy::UpdateCredentials(
-    const string& email, const string& token) {
-  bridge_->UpdateCredentials(email, token);
-}
-
-void AndroidInvalidatorBridgeProxy::SendInvalidation(
-    const syncer::ObjectIdInvalidationMap& invalidation_map) {
-  bridge_->SendInvalidation(invalidation_map);
-}
-
-}  // namespace browser_sync
diff --git a/chrome/browser/sync/glue/android_invalidator_bridge_proxy.h b/chrome/browser/sync/glue/android_invalidator_bridge_proxy.h
deleted file mode 100644
index 98c623e..0000000
--- a/chrome/browser/sync/glue/android_invalidator_bridge_proxy.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_SYNC_GLUE_ANDROID_INVALIDATOR_BRIDGE_PROXY_H_
-#define CHROME_BROWSER_SYNC_GLUE_ANDROID_INVALIDATOR_BRIDGE_PROXY_H_
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "sync/notifier/invalidator.h"
-
-namespace browser_sync {
-
-class AndroidInvalidatorBridge;
-
-// This class implements the Invalidator interface by wrapping (but not taking
-// ownership of) an AndroidInvalidatorBridge.  This is useful because the
-// SyncManager currently expects to take ownership of its invalidator, but it is
-// not prepared to take ownership of the UI-thread-owned
-// AndroidInvalidatorBridge.  So we use this class to wrap the
-// AndroidInvalidator and allow the SyncManager to own it instead.
-class AndroidInvalidatorBridgeProxy : public syncer::Invalidator {
- public:
-  // Does not take ownership of |bridge|.
-  explicit AndroidInvalidatorBridgeProxy(AndroidInvalidatorBridge* bridge);
-  virtual ~AndroidInvalidatorBridgeProxy();
-
-  // Invalidator implementation. Passes through all calls to the bridge.
-  virtual void RegisterHandler(syncer::InvalidationHandler* handler) OVERRIDE;
-  virtual void UpdateRegisteredIds(syncer::InvalidationHandler * handler,
-                                   const syncer::ObjectIdSet& ids) OVERRIDE;
-  virtual void UnregisterHandler(syncer::InvalidationHandler* handler) OVERRIDE;
-  virtual void Acknowledge(const invalidation::ObjectId& id,
-                           const syncer::AckHandle& ack_handle) OVERRIDE;
-  virtual syncer::InvalidatorState GetInvalidatorState() const OVERRIDE;
-  virtual void UpdateCredentials(
-      const std::string& email, const std::string& token) OVERRIDE;
-  virtual void SendInvalidation(
-      const syncer::ObjectIdInvalidationMap& invalidation_map) OVERRIDE;
-
- private:
-  // The notification bridge that we forward to but don't own.
-  AndroidInvalidatorBridge* const bridge_;
-
-  DISALLOW_COPY_AND_ASSIGN(AndroidInvalidatorBridgeProxy);
-};
-
-}  // namespace browser_sync
-
-#endif  // CHROME_BROWSER_SYNC_GLUE_ANDROID_INVALIDATOR_BRIDGE_PROXY_H_
diff --git a/chrome/browser/sync/glue/autofill_data_type_controller.cc b/chrome/browser/sync/glue/autofill_data_type_controller.cc
index 6703779..3c8f0cf 100644
--- a/chrome/browser/sync/glue/autofill_data_type_controller.cc
+++ b/chrome/browser/sync/glue/autofill_data_type_controller.cc
@@ -11,7 +11,7 @@
 #include "chrome/browser/sync/profile_sync_service.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/webdata/autocomplete_syncable_service.h"
-#include "components/autofill/browser/webdata/autofill_webdata_service.h"
+#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
 #include "content/public/browser/browser_thread.h"
 #include "sync/api/sync_error.h"
 #include "sync/internal_api/public/util/experiments.h"
diff --git a/chrome/browser/sync/glue/autofill_data_type_controller_unittest.cc b/chrome/browser/sync/glue/autofill_data_type_controller_unittest.cc
index ce020f9..a52c3a4 100644
--- a/chrome/browser/sync/glue/autofill_data_type_controller_unittest.cc
+++ b/chrome/browser/sync/glue/autofill_data_type_controller_unittest.cc
@@ -19,7 +19,7 @@
 #include "chrome/browser/webdata/web_data_service_factory.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "chrome/test/base/profile_mock.h"
-#include "components/autofill/browser/webdata/autofill_webdata_service.h"
+#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
 #include "components/webdata/common/web_data_service_test_util.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_source.h"
diff --git a/chrome/browser/sync/glue/autofill_profile_data_type_controller.cc b/chrome/browser/sync/glue/autofill_profile_data_type_controller.cc
index a508a84..e089532 100644
--- a/chrome/browser/sync/glue/autofill_profile_data_type_controller.cc
+++ b/chrome/browser/sync/glue/autofill_profile_data_type_controller.cc
@@ -10,8 +10,8 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sync/profile_sync_components_factory.h"
 #include "chrome/browser/sync/profile_sync_service.h"
-#include "components/autofill/browser/personal_data_manager.h"
-#include "components/autofill/browser/webdata/autofill_webdata_service.h"
+#include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
 #include "content/public/browser/browser_thread.h"
 #include "sync/api/sync_error.h"
 #include "sync/api/syncable_service.h"
diff --git a/chrome/browser/sync/glue/autofill_profile_data_type_controller.h b/chrome/browser/sync/glue/autofill_profile_data_type_controller.h
index 3e00748..b4a175e 100644
--- a/chrome/browser/sync/glue/autofill_profile_data_type_controller.h
+++ b/chrome/browser/sync/glue/autofill_profile_data_type_controller.h
@@ -9,7 +9,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/scoped_observer.h"
 #include "chrome/browser/sync/glue/non_ui_data_type_controller.h"
-#include "components/autofill/browser/personal_data_manager_observer.h"
+#include "components/autofill/core/browser/personal_data_manager_observer.h"
 
 namespace autofill {
 class PersonalDataManager;
diff --git a/chrome/browser/sync/glue/backend_data_type_configurer.h b/chrome/browser/sync/glue/backend_data_type_configurer.h
index 308dee6..eb4d93e 100644
--- a/chrome/browser/sync/glue/backend_data_type_configurer.h
+++ b/chrome/browser/sync/glue/backend_data_type_configurer.h
@@ -24,6 +24,8 @@
     CONFIGURE_INACTIVE,   // Already configured or to be configured in future.
                           // Data of such types is left as it is, no
                           // downloading or purging.
+    CONFIGURE_CLEAN,      // Actively being configured but requiring unapply
+                          // and GetUpdates first (e.g. for persistence errors).
     DISABLED,             // Not syncing. Disabled by user.
     FATAL,                // Not syncing due to unrecoverable error.
     CRYPTO,               // Not syncing due to a cryptographer error.
diff --git a/chrome/browser/sync/glue/bookmark_data_type_controller_unittest.cc b/chrome/browser/sync/glue/bookmark_data_type_controller_unittest.cc
index 2703dbc..e581409 100644
--- a/chrome/browser/sync/glue/bookmark_data_type_controller_unittest.cc
+++ b/chrome/browser/sync/glue/bookmark_data_type_controller_unittest.cc
@@ -259,8 +259,9 @@
       WillRepeatedly(DoAll(SetArgumentPointee<0>(true), Return(true)));
   EXPECT_CALL(*model_associator_, AssociateModels(_, _)).
       WillRepeatedly(Return(syncer::SyncError(FROM_HERE,
-                                     "error",
-                                     syncer::BOOKMARKS)));
+                                              syncer::SyncError::DATATYPE_ERROR,
+                                              "error",
+                                              syncer::BOOKMARKS)));
 
   EXPECT_CALL(start_callback_,
               Run(DataTypeController::ASSOCIATION_FAILED, _, _));
diff --git a/chrome/browser/sync/glue/bookmark_model_associator.cc b/chrome/browser/sync/glue/bookmark_model_associator.cc
index 846d3e2..c5b5434 100644
--- a/chrome/browser/sync/glue/bookmark_model_associator.cc
+++ b/chrome/browser/sync/glue/bookmark_model_associator.cc
@@ -9,9 +9,11 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/containers/hash_tables.h"
+#include "base/format_macros.h"
 #include "base/location.h"
 #include "base/message_loop.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/profiles/profile.h"
@@ -364,7 +366,10 @@
 syncer::SyncError BookmarkModelAssociator::AssociateModels(
     syncer::SyncMergeResult* local_merge_result,
     syncer::SyncMergeResult* syncer_merge_result) {
-  CheckModelSyncState(local_merge_result, syncer_merge_result);
+  syncer::SyncError error = CheckModelSyncState(local_merge_result,
+                                                syncer_merge_result);
+  if (error.IsSet())
+    return error;
 
   scoped_ptr<ScopedAssociationUpdater> association_updater(
       new ScopedAssociationUpdater(bookmark_model_));
@@ -702,16 +707,16 @@
       trans.GetCryptographer()->is_ready();
 }
 
-void BookmarkModelAssociator::CheckModelSyncState(
+syncer::SyncError BookmarkModelAssociator::CheckModelSyncState(
     syncer::SyncMergeResult* local_merge_result,
     syncer::SyncMergeResult* syncer_merge_result) const {
   std::string version_str;
   if (bookmark_model_->root_node()->GetMetaInfo(kBookmarkTransactionVersionKey,
                                                 &version_str)) {
     syncer::ReadTransaction trans(FROM_HERE, user_share_);
-    int64 native_version;
+    int64 native_version = syncer::syncable::kInvalidTransactionVersion;
     if (!base::StringToInt64(version_str, &native_version))
-      return;
+      return syncer::SyncError();
     local_merge_result->set_pre_association_version(native_version);
 
     int64 sync_version = trans.GetModelVersion(syncer::BOOKMARKS);
@@ -721,11 +726,27 @@
       UMA_HISTOGRAM_ENUMERATION("Sync.LocalModelOutOfSync",
                                 ModelTypeToHistogramInt(syncer::BOOKMARKS),
                                 syncer::MODEL_TYPE_COUNT);
+
       // Clear version on bookmark model so that we only report error once.
       bookmark_model_->DeleteNodeMetaInfo(bookmark_model_->root_node(),
                                           kBookmarkTransactionVersionKey);
+
+      // If the native version is higher, there was a sync persistence failure,
+      // and we need to delay association until after a GetUpdates.
+      if (sync_version < native_version) {
+        std::string message = base::StringPrintf(
+            "Native version (%" PRId64 ") does not match sync version (%"
+                PRId64 ")",
+            native_version,
+            sync_version);
+        return syncer::SyncError(FROM_HERE,
+                                 syncer::SyncError::PERSISTENCE_ERROR,
+                                 message,
+                                 syncer::BOOKMARKS);
+      }
     }
   }
+  return syncer::SyncError();
 }
 
 }  // namespace browser_sync
diff --git a/chrome/browser/sync/glue/bookmark_model_associator.h b/chrome/browser/sync/glue/bookmark_model_associator.h
index 8a0ff5f..cf348b7 100644
--- a/chrome/browser/sync/glue/bookmark_model_associator.h
+++ b/chrome/browser/sync/glue/bookmark_model_associator.h
@@ -141,8 +141,11 @@
 
   // Check whether bookmark model and sync model are synced by comparing
   // their transaction versions.
-  void CheckModelSyncState(syncer::SyncMergeResult* local_merge_result,
-                           syncer::SyncMergeResult* syncer_merge_result) const;
+  // Returns a PERSISTENCE_ERROR if a transaction mismatch was detected where
+  // the native model has a newer transaction verison.
+  syncer::SyncError CheckModelSyncState(
+      syncer::SyncMergeResult* local_merge_result,
+      syncer::SyncMergeResult* syncer_merge_result) const;
 
   BookmarkModel* bookmark_model_;
   Profile* profile_;
diff --git a/chrome/browser/sync/glue/browser_thread_model_worker_unittest.cc b/chrome/browser/sync/glue/browser_thread_model_worker_unittest.cc
index aa6f4b7..031bcb1 100644
--- a/chrome/browser/sync/glue/browser_thread_model_worker_unittest.cc
+++ b/chrome/browser/sync/glue/browser_thread_model_worker_unittest.cc
@@ -9,7 +9,7 @@
 #include "base/message_loop.h"
 #include "base/test/test_timeouts.h"
 #include "base/threading/thread.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/sync/glue/browser_thread_model_worker.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/sync/glue/data_type_controller.cc b/chrome/browser/sync/glue/data_type_controller.cc
index 71095ab..cb56478 100644
--- a/chrome/browser/sync/glue/data_type_controller.cc
+++ b/chrome/browser/sync/glue/data_type_controller.cc
@@ -23,7 +23,10 @@
     const std::string& message,
     syncer::ModelType type) {
   ChromeReportUnrecoverableError();
-  return syncer::SyncError(location, message, type);
+  return syncer::SyncError(location,
+                           syncer::SyncError::DATATYPE_ERROR,
+                           message,
+                           type);
 }
 
 void DataTypeController::RecordUnrecoverableError(
diff --git a/chrome/browser/sync/glue/data_type_manager_impl.cc b/chrome/browser/sync/glue/data_type_manager_impl.cc
index 01f8fcb..87daedb 100644
--- a/chrome/browser/sync/glue/data_type_manager_impl.cc
+++ b/chrome/browser/sync/glue/data_type_manager_impl.cc
@@ -35,9 +35,11 @@
   FailedDataTypesHandler::TypeErrorMap crypto_errors;
   for (syncer::ModelTypeSet::Iterator iter = encrypted_types.First();
          iter.Good(); iter.Inc()) {
-    crypto_errors[iter.Get()] = syncer::SyncError(FROM_HERE,
-                                                  "Cryptographer not ready.",
-                                                  iter.Get());
+    crypto_errors[iter.Get()] = syncer::SyncError(
+        FROM_HERE,
+        syncer::SyncError::CRYPTO_ERROR,
+        "",
+        iter.Get());
   }
   return crypto_errors;
 }
@@ -139,13 +141,21 @@
   // 3. Flip |types_being_configured| to CONFIGURE_ACTIVE.
   // 4. Set non-enabled user types as DISABLED.
   // 5. Set the fatal and crypto types to their respective states.
-  syncer::ModelTypeSet fatal_types;
-  syncer::ModelTypeSet crypto_types;
-  fatal_types = failed_data_types_handler_->GetFatalErrorTypes();
-  crypto_types = failed_data_types_handler_->GetCryptoErrorTypes();
+  syncer::ModelTypeSet error_types =
+      failed_data_types_handler_->GetFailedTypes();
+  syncer::ModelTypeSet fatal_types =
+      failed_data_types_handler_->GetFatalErrorTypes();
+  syncer::ModelTypeSet crypto_types =
+      failed_data_types_handler_->GetCryptoErrorTypes();
+
+  // Types with persistence errors are only purged/resynced when they're
+  // actively being configured.
+  syncer::ModelTypeSet persistence_types =
+      failed_data_types_handler_->GetPersistenceErrorTypes();
+  persistence_types.RetainAll(types_being_configured);
+
   syncer::ModelTypeSet enabled_types = last_requested_types_;
-  enabled_types.RemoveAll(fatal_types);
-  enabled_types.RemoveAll(crypto_types);
+  enabled_types.RemoveAll(error_types);
   syncer::ModelTypeSet disabled_types =
       syncer::Difference(
           syncer::Union(syncer::UserTypes(), syncer::ControlTypes()),
@@ -164,6 +174,9 @@
       BackendDataTypeConfigurer::CONFIGURE_ACTIVE, to_configure,
       &config_state_map);
   BackendDataTypeConfigurer::SetDataTypesState(
+      BackendDataTypeConfigurer::CONFIGURE_CLEAN, persistence_types,
+        &config_state_map);
+  BackendDataTypeConfigurer::SetDataTypesState(
       BackendDataTypeConfigurer::DISABLED, disabled_types,
       &config_state_map);
   BackendDataTypeConfigurer::SetDataTypesState(
@@ -187,9 +200,7 @@
         failed_data_types_handler_->GetCryptoErrorTypes());
     FailedDataTypesHandler::TypeErrorMap crypto_errors =
         GenerateCryptoErrorsForTypes(encrypted_types);
-    failed_data_types_handler_->UpdateFailedDataTypes(
-        crypto_errors,
-        FailedDataTypesHandler::CRYPTO);
+    failed_data_types_handler_->UpdateFailedDataTypes(crypto_errors);
   } else {
     failed_data_types_handler_->ResetCryptoErrors();
   }
@@ -222,16 +233,23 @@
       BuildDataTypeConfigStateMap(download_types_queue_.front()),
       base::Bind(&DataTypeManagerImpl::DownloadReady,
                  weak_ptr_factory_.GetWeakPtr(),
-                 base::Time::Now(), syncer::ModelTypeSet()),
+                 base::Time::Now(),
+                 download_types_queue_.front(),
+                 syncer::ModelTypeSet()),
       base::Bind(&DataTypeManagerImpl::OnDownloadRetry,
                  weak_ptr_factory_.GetWeakPtr()));
 }
 
-TypeSetPriorityList DataTypeManagerImpl::PrioritizeTypes(
-    const syncer::ModelTypeSet& types) {
+syncer::ModelTypeSet DataTypeManagerImpl::GetPriorityTypes() const {
   syncer::ModelTypeSet high_priority_types;
   high_priority_types.PutAll(syncer::ControlTypes());
   high_priority_types.PutAll(syncer::PriorityUserTypes());
+  return high_priority_types;
+}
+
+TypeSetPriorityList DataTypeManagerImpl::PrioritizeTypes(
+    const syncer::ModelTypeSet& types) {
+  syncer::ModelTypeSet high_priority_types = GetPriorityTypes();
   high_priority_types.RetainAll(types);
 
   syncer::ModelTypeSet low_priority_types =
@@ -280,11 +298,16 @@
 
 void DataTypeManagerImpl::DownloadReady(
     base::Time download_start_time,
+    syncer::ModelTypeSet types_to_download,
     syncer::ModelTypeSet high_priority_types_before,
     syncer::ModelTypeSet first_sync_types,
     syncer::ModelTypeSet failed_configuration_types) {
   DCHECK(state_ == DOWNLOAD_PENDING || state_ == CONFIGURING);
 
+  // Persistence errors are reset after each backend configuration attempt
+  // during which they would have been purged.
+  failed_data_types_handler_->ResetPersistenceErrorsFrom(types_to_download);
+
   // Ignore |failed_configuration_types| if we need to reconfigure
   // anyway.
   if (needs_reconfigure_) {
@@ -298,7 +321,9 @@
     std::string error_msg =
         "Configuration failed for types " +
         syncer::ModelTypeSetToString(failed_configuration_types);
-    syncer::SyncError error(FROM_HERE, error_msg,
+    syncer::SyncError error(FROM_HERE,
+                            syncer::SyncError::UNRECOVERABLE_ERROR,
+                            error_msg,
                             failed_configuration_types.First().Get());
     Abort(UNRECOVERABLE_ERROR, error);
     return;
@@ -307,8 +332,11 @@
   state_ = CONFIGURING;
 
   // Pop and associate download-ready types.
-  syncer::ModelTypeSet ready_types = download_types_queue_.front();
+  syncer::ModelTypeSet ready_types = types_to_download;
   download_types_queue_.pop();
+  syncer::ModelTypeSet new_types_to_download;
+  if (!download_types_queue_.empty())
+    new_types_to_download = download_types_queue_.front();
 
   AssociationTypesInfo association_info;
   association_info.types = ready_types;
@@ -321,13 +349,14 @@
     StartNextAssociation();
 
   // Download types of low priority while configuring types of high priority.
-  if (!download_types_queue_.empty()) {
+  if (!new_types_to_download.Empty()) {
     configurer_->ConfigureDataTypes(
         last_configure_reason_,
-        BuildDataTypeConfigStateMap(download_types_queue_.front()),
+        BuildDataTypeConfigStateMap(new_types_to_download),
         base::Bind(&DataTypeManagerImpl::DownloadReady,
                    weak_ptr_factory_.GetWeakPtr(),
                    base::Time::Now(),
+                   new_types_to_download,
                    syncer::Union(ready_types, high_priority_types_before)),
         base::Bind(&DataTypeManagerImpl::OnDownloadRetry,
                    weak_ptr_factory_.GetWeakPtr()));
@@ -394,15 +423,12 @@
           failed_data_types_handler_->GetCryptoErrorTypes());
       FailedDataTypesHandler::TypeErrorMap crypto_errors =
           GenerateCryptoErrorsForTypes(encrypted_types);
-      failed_data_types_handler_->UpdateFailedDataTypes(
-          crypto_errors,
-          FailedDataTypesHandler::CRYPTO);
+      failed_data_types_handler_->UpdateFailedDataTypes(crypto_errors);
     }
     if (!result.failed_data_types.empty()) {
       needs_reconfigure_ = true;
       failed_data_types_handler_->UpdateFailedDataTypes(
-          result.failed_data_types,
-          FailedDataTypesHandler::STARTUP);
+          result.failed_data_types);
     }
   }
 
@@ -489,7 +515,7 @@
   DCHECK_NE(OK, status);
   std::map<syncer::ModelType, syncer::SyncError> errors;
   if (error.IsSet())
-    errors[error.type()] = error;
+    errors[error.model_type()] = error;
   ConfigureResult result(status,
                          last_requested_types_,
                          errors,
diff --git a/chrome/browser/sync/glue/data_type_manager_impl.h b/chrome/browser/sync/glue/data_type_manager_impl.h
index c2fb91b..762e34e 100644
--- a/chrome/browser/sync/glue/data_type_manager_impl.h
+++ b/chrome/browser/sync/glue/data_type_manager_impl.h
@@ -14,7 +14,7 @@
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "base/memory/weak_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/sync/glue/backend_data_type_configurer.h"
 #include "chrome/browser/sync/glue/model_association_manager.h"
 
@@ -73,22 +73,27 @@
     return &model_association_manager_;
   }
 
- protected:
-  // Divide |types| into sets by their priorities and return the sets from
-  // high priority to low priority.
-  virtual TypeSetPriorityList PrioritizeTypes(
-      const syncer::ModelTypeSet& types);
-
  private:
+  friend class TestDataTypeManager;
+
   // Abort configuration and stop all data types due to configuration errors.
   void Abort(ConfigureStatus status,
              const syncer::SyncError& error);
 
+  // Returns the priority types (control + priority user types).
+  // Virtual for overriding during tests.
+  virtual syncer::ModelTypeSet GetPriorityTypes() const;
+
+  // Divide |types| into sets by their priorities and return the sets from
+  // high priority to low priority.
+  TypeSetPriorityList PrioritizeTypes(const syncer::ModelTypeSet& types);
+
   // Post a task to reconfigure when no downloading or association are running.
   void ProcessReconfigure();
 
   void Restart(syncer::ConfigureReason reason);
   void DownloadReady(base::Time download_start_time,
+                     syncer::ModelTypeSet types_to_download,
                      syncer::ModelTypeSet high_priority_types_before,
                      syncer::ModelTypeSet first_sync_types,
                      syncer::ModelTypeSet failed_configuration_types);
diff --git a/chrome/browser/sync/glue/data_type_manager_impl_unittest.cc b/chrome/browser/sync/glue/data_type_manager_impl_unittest.cc
index a341d61..999c684 100644
--- a/chrome/browser/sync/glue/data_type_manager_impl_unittest.cc
+++ b/chrome/browser/sync/glue/data_type_manager_impl_unittest.cc
@@ -41,6 +41,19 @@
   return result.status;
 }
 
+syncer::ModelTypeSet PriorityTypes() {
+  syncer::ModelTypeSet result = syncer::ControlTypes();
+  result.Put(syncer::MANAGED_USERS);
+  return result;
+}
+
+// Helper for unioning with control types.
+syncer::ModelTypeSet AddPriorityTypesTo(syncer::ModelTypeSet types) {
+  syncer::ModelTypeSet result = PriorityTypes();
+  result.PutAll(types);
+  return result;
+}
+
 // Fake BackendDataTypeConfigurer implementation that simply stores away the
 // callback passed into ConfigureDataTypes.
 class FakeBackendDataTypeConfigurer : public BackendDataTypeConfigurer {
@@ -124,6 +137,8 @@
   return encrypted_types_;
 }
 
+} // namespace
+
 class TestDataTypeManager : public DataTypeManagerImpl {
  public:
   TestDataTypeManager(
@@ -139,26 +154,19 @@
                             encryption_handler,
                             configurer,
                             observer,
-                            failed_data_types_handler) {}
+                            failed_data_types_handler),
+        custom_priority_types_(PriorityTypes()) {}
 
-  void set_priority_list(const TypeSetPriorityList& list) {
-    priority_list_ = list;
-  }
-
- protected:
-  virtual TypeSetPriorityList PrioritizeTypes(
-      const syncer::ModelTypeSet& types) OVERRIDE {
-    TypeSetPriorityList result;
-    if (priority_list_.empty()) {
-      result.push(types);
-    } else {
-      result = priority_list_;
-    }
-    return result;
+  void set_priority_types(const syncer::ModelTypeSet& priority_types) {
+    custom_priority_types_ = priority_types;
   }
 
  private:
-  TypeSetPriorityList priority_list_;
+  virtual syncer::ModelTypeSet GetPriorityTypes() const OVERRIDE {
+    return custom_priority_types_;
+  }
+
+  syncer::ModelTypeSet custom_priority_types_;
 };
 
 // The actual test harness class, parametrized on nigori state (i.e., tests are
@@ -264,6 +272,7 @@
 // downloading, finish starting the controller, and then stop the DTM.
 TEST_F(SyncDataTypeManagerImplTest, ConfigureOne) {
   AddController(BOOKMARKS);
+  dtm_->set_priority_types(AddPriorityTypesTo(syncer::ModelTypeSet(BOOKMARKS)));
 
   SetConfigureStartExpectation();
   SetConfigureDoneExpectation(DataTypeManager::OK);
@@ -286,6 +295,8 @@
 TEST_F(SyncDataTypeManagerImplTest, ConfigureSlowLoadingType) {
   AddController(BOOKMARKS);
   AddController(APPS);
+  dtm_->set_priority_types(
+      AddPriorityTypesTo(syncer::ModelTypeSet(BOOKMARKS, APPS)));
 
   GetController(BOOKMARKS)->SetDelayModelLoad();
 
@@ -331,6 +342,7 @@
 // download callback even after the DTM is stopped and destroyed.
 TEST_F(SyncDataTypeManagerImplTest, ConfigureOneStopWhileDownloadPending) {
   AddController(BOOKMARKS);
+  dtm_->set_priority_types(AddPriorityTypesTo(syncer::ModelTypeSet(BOOKMARKS)));
 
   {
     SetConfigureStartExpectation();
@@ -352,6 +364,7 @@
 // controller even after the DTM is stopped and destroyed.
 TEST_F(SyncDataTypeManagerImplTest, ConfigureOneStopWhileStartingModel) {
   AddController(BOOKMARKS);
+  dtm_->set_priority_types(AddPriorityTypesTo(syncer::ModelTypeSet(BOOKMARKS)));
 
   {
     SetConfigureStartExpectation();
@@ -378,6 +391,8 @@
 // destroyed.
 TEST_F(SyncDataTypeManagerImplTest, ConfigureOneStopWhileAssociating) {
   AddController(BOOKMARKS);
+  dtm_->set_priority_types(AddPriorityTypesTo(syncer::ModelTypeSet(BOOKMARKS)));
+
   {
     SetConfigureStartExpectation();
     SetConfigureDoneExpectation(DataTypeManager::ABORTED);
@@ -405,6 +420,7 @@
 //   5) Stop the DTM.
 TEST_F(SyncDataTypeManagerImplTest, OneWaitingForCrypto) {
   AddController(PASSWORDS);
+  dtm_->set_priority_types(AddPriorityTypesTo(syncer::ModelTypeSet(PASSWORDS)));
 
   SetConfigureStartExpectation();
   SetConfigureDoneExpectation(DataTypeManager::PARTIAL_SUCCESS);
@@ -445,6 +461,8 @@
 TEST_F(SyncDataTypeManagerImplTest, ConfigureOneThenBoth) {
   AddController(BOOKMARKS);
   AddController(PREFERENCES);
+  dtm_->set_priority_types(
+      AddPriorityTypesTo(syncer::ModelTypeSet(BOOKMARKS, PREFERENCES)));
 
   SetConfigureStartExpectation();
   SetConfigureDoneExpectation(DataTypeManager::OK);
@@ -494,6 +512,8 @@
 TEST_F(SyncDataTypeManagerImplTest, ConfigureOneThenSwitch) {
   AddController(BOOKMARKS);
   AddController(PREFERENCES);
+  dtm_->set_priority_types(
+      AddPriorityTypesTo(syncer::ModelTypeSet(BOOKMARKS, PREFERENCES)));
 
   SetConfigureStartExpectation();
   SetConfigureDoneExpectation(DataTypeManager::OK);
@@ -543,6 +563,8 @@
 TEST_F(SyncDataTypeManagerImplTest, ConfigureWhileOneInFlight) {
   AddController(BOOKMARKS);
   AddController(PREFERENCES);
+  dtm_->set_priority_types(
+      AddPriorityTypesTo(syncer::ModelTypeSet(BOOKMARKS, PREFERENCES)));
 
   SetConfigureStartExpectation();
   SetConfigureDoneExpectation(DataTypeManager::OK);
@@ -581,6 +603,7 @@
 // The unrecoverable error should cause the DTM to stop.
 TEST_F(SyncDataTypeManagerImplTest, OneFailingController) {
   AddController(BOOKMARKS);
+  dtm_->set_priority_types(AddPriorityTypesTo(syncer::ModelTypeSet(BOOKMARKS)));
 
   SetConfigureStartExpectation();
   SetConfigureDoneExpectation(DataTypeManager::UNRECOVERABLE_ERROR);
@@ -607,6 +630,8 @@
 TEST_F(SyncDataTypeManagerImplTest, SecondControllerFails) {
   AddController(BOOKMARKS);
   AddController(PREFERENCES);
+  dtm_->set_priority_types(
+      AddPriorityTypesTo(syncer::ModelTypeSet(BOOKMARKS, PREFERENCES)));
 
   SetConfigureStartExpectation();
   SetConfigureDoneExpectation(DataTypeManager::UNRECOVERABLE_ERROR);
@@ -645,6 +670,8 @@
 TEST_F(SyncDataTypeManagerImplTest, OneControllerFailsAssociation) {
   AddController(BOOKMARKS);
   AddController(PREFERENCES);
+  dtm_->set_priority_types(
+      AddPriorityTypesTo(syncer::ModelTypeSet(BOOKMARKS, PREFERENCES)));
 
   SetConfigureStartExpectation();
   SetConfigureDoneExpectation(DataTypeManager::PARTIAL_SUCCESS);
@@ -686,6 +713,8 @@
 TEST_F(SyncDataTypeManagerImplTest, ConfigureWhileDownloadPending) {
   AddController(BOOKMARKS);
   AddController(PREFERENCES);
+  dtm_->set_priority_types(
+      AddPriorityTypesTo(syncer::ModelTypeSet(BOOKMARKS, PREFERENCES)));
 
   SetConfigureStartExpectation();
   SetConfigureDoneExpectation(DataTypeManager::OK);
@@ -731,6 +760,8 @@
 TEST_F(SyncDataTypeManagerImplTest, ConfigureWhileDownloadPendingWithFailure) {
   AddController(BOOKMARKS);
   AddController(PREFERENCES);
+  dtm_->set_priority_types(
+      AddPriorityTypesTo(syncer::ModelTypeSet(BOOKMARKS, PREFERENCES)));
 
   SetConfigureStartExpectation();
   SetConfigureDoneExpectation(DataTypeManager::OK);
@@ -766,6 +797,7 @@
 // operations that would be invoked by the BackendMigrator.
 TEST_F(SyncDataTypeManagerImplTest, MigrateAll) {
   AddController(BOOKMARKS);
+  dtm_->set_priority_types(AddPriorityTypesTo(syncer::ModelTypeSet(BOOKMARKS)));
 
   SetConfigureStartExpectation();
   SetConfigureDoneExpectation(DataTypeManager::OK);
@@ -808,6 +840,8 @@
 TEST_F(SyncDataTypeManagerImplTest, ConfigureDuringPurge) {
   AddController(BOOKMARKS);
   AddController(PREFERENCES);
+  dtm_->set_priority_types(
+      AddPriorityTypesTo(syncer::ModelTypeSet(BOOKMARKS, PREFERENCES)));
 
   // Initial configure.
   SetConfigureStartExpectation();
@@ -855,18 +889,19 @@
 TEST_F(SyncDataTypeManagerImplTest, PrioritizedConfiguration) {
   AddController(BOOKMARKS);
   AddController(PREFERENCES);
+  dtm_->set_priority_types(
+      AddPriorityTypesTo(syncer::ModelTypeSet(BOOKMARKS, PREFERENCES)));
 
-  TypeSetPriorityList priority_list;
-  priority_list.push(ModelTypeSet(PREFERENCES));
-  priority_list.push(ModelTypeSet(BOOKMARKS));
-  dtm_->set_priority_list(priority_list);
+  dtm_->set_priority_types(
+      AddPriorityTypesTo(syncer::ModelTypeSet(PREFERENCES)));
 
   // Initial configure.
   SetConfigureStartExpectation();
   SetConfigureDoneExpectation(DataTypeManager::OK);
 
   // Initially only PREFERENCES is configured.
-  configurer_.set_expected_configure_types(ModelTypeSet(PREFERENCES));
+  configurer_.set_expected_configure_types(
+      AddPriorityTypesTo(ModelTypeSet(PREFERENCES)));
   Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES));
   EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
 
@@ -888,17 +923,16 @@
   AddController(PREFERENCES);
   AddController(APPS);
 
-  TypeSetPriorityList priority_list;
-  priority_list.push(ModelTypeSet(PREFERENCES));
-  priority_list.push(ModelTypeSet(BOOKMARKS));
-  dtm_->set_priority_list(priority_list);
+  dtm_->set_priority_types(
+      AddPriorityTypesTo(syncer::ModelTypeSet(PREFERENCES)));
 
   // Initial configure.
   SetConfigureStartExpectation();
   SetConfigureDoneExpectation(DataTypeManager::OK);
 
   // Reconfigure while associating PREFERENCES and downloading BOOKMARKS.
-  configurer_.set_expected_configure_types(ModelTypeSet(PREFERENCES));
+  configurer_.set_expected_configure_types(
+      AddPriorityTypesTo(ModelTypeSet(PREFERENCES)));
   Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES));
   EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
 
@@ -907,14 +941,13 @@
   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
 
   // Enable syncing for APPS.
-  priority_list.back() = ModelTypeSet(BOOKMARKS, APPS);
-  dtm_->set_priority_list(priority_list);
   Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES, APPS));
   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
 
   // Reconfiguration starts after downloading and association of previous
   // types finish.
-  configurer_.set_expected_configure_types(ModelTypeSet(PREFERENCES));
+  configurer_.set_expected_configure_types(
+      AddPriorityTypesTo(ModelTypeSet(PREFERENCES)));
   FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
   GetController(PREFERENCES)->FinishStart(DataTypeController::OK);
   EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
@@ -937,17 +970,16 @@
   AddController(BOOKMARKS);
   AddController(PREFERENCES);
 
-  TypeSetPriorityList priority_list;
-  priority_list.push(ModelTypeSet(PREFERENCES));
-  priority_list.push(ModelTypeSet(BOOKMARKS));
-  dtm_->set_priority_list(priority_list);
+  dtm_->set_priority_types(
+      AddPriorityTypesTo(syncer::ModelTypeSet(PREFERENCES)));
 
   // Initial configure.
   SetConfigureStartExpectation();
   SetConfigureDoneExpectation(DataTypeManager::ABORTED);
 
   // Initially only PREFERENCES is configured.
-  configurer_.set_expected_configure_types(ModelTypeSet(PREFERENCES));
+  configurer_.set_expected_configure_types(
+      AddPriorityTypesTo(ModelTypeSet(PREFERENCES)));
   Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES));
   EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
 
@@ -972,17 +1004,16 @@
   AddController(BOOKMARKS);
   AddController(PREFERENCES);
 
-  TypeSetPriorityList priority_list;
-  priority_list.push(ModelTypeSet(PREFERENCES));
-  priority_list.push(ModelTypeSet(BOOKMARKS));
-  dtm_->set_priority_list(priority_list);
+  dtm_->set_priority_types(
+      AddPriorityTypesTo(syncer::ModelTypeSet(PREFERENCES)));
 
   // Initial configure.
   SetConfigureStartExpectation();
   SetConfigureDoneExpectation(DataTypeManager::UNRECOVERABLE_ERROR);
 
   // Initially only PREFERENCES is configured.
-  configurer_.set_expected_configure_types(ModelTypeSet(PREFERENCES));
+  configurer_.set_expected_configure_types(
+      AddPriorityTypesTo(ModelTypeSet(PREFERENCES)));
   Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES));
   EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
 
@@ -1004,21 +1035,20 @@
   EXPECT_EQ(DataTypeController::NOT_RUNNING, GetController(BOOKMARKS)->state());
 }
 
-TEST_F(SyncDataTypeManagerImplTest, PrioritizedConfigurationAssociationError) {
-  AddController(BOOKMARKS);
-  AddController(PREFERENCES);
+TEST_F(SyncDataTypeManagerImplTest, HighPriorityAssociationFailure) {
+  AddController(PREFERENCES);   // Will fail.
+  AddController(BOOKMARKS);     // Will succeed.
 
-  TypeSetPriorityList priority_list;
-  priority_list.push(ModelTypeSet(PREFERENCES));
-  priority_list.push(ModelTypeSet(BOOKMARKS));
-  dtm_->set_priority_list(priority_list);
+  dtm_->set_priority_types(
+      AddPriorityTypesTo(syncer::ModelTypeSet(PREFERENCES)));
 
   // Initial configure.
   SetConfigureStartExpectation();
-  SetConfigureDoneExpectation(DataTypeManager::UNRECOVERABLE_ERROR);
+  SetConfigureDoneExpectation(DataTypeManager::PARTIAL_SUCCESS);
 
   // Initially only PREFERENCES is configured.
-  configurer_.set_expected_configure_types(ModelTypeSet(PREFERENCES));
+  configurer_.set_expected_configure_types(
+      AddPriorityTypesTo(ModelTypeSet(PREFERENCES)));
   Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES));
   EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
 
@@ -1034,13 +1064,76 @@
 
   // Make PREFERENCES association fail.
   GetController(PREFERENCES)->FinishStart(
-      DataTypeController::UNRECOVERABLE_ERROR);
-  EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
+      DataTypeController::ASSOCIATION_FAILED);
+  EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
+
+  // Reconfigure without PREFERENCES after the BOOKMARKS download completes,
+  // then reconfigure with BOOKMARKS.
+  configurer_.set_expected_configure_types(PriorityTypes());
+  FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
+  configurer_.set_expected_configure_types(ModelTypeSet(BOOKMARKS));
+  FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
+
+  // Reconfigure with BOOKMARKS.
+  FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
+  EXPECT_EQ(DataTypeController::ASSOCIATING,
+            GetController(BOOKMARKS)->state());
+  GetController(BOOKMARKS)->FinishStart(DataTypeController::OK);
+
+  EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
   EXPECT_EQ(DataTypeController::NOT_RUNNING,
             GetController(PREFERENCES)->state());
-  EXPECT_EQ(DataTypeController::NOT_RUNNING, GetController(BOOKMARKS)->state());
+  EXPECT_EQ(DataTypeController::RUNNING, GetController(BOOKMARKS)->state());
 }
 
-}  // namespace
+TEST_F(SyncDataTypeManagerImplTest, LowPriorityAssociationFailure) {
+  AddController(PREFERENCES);  // Will succeed.
+  AddController(BOOKMARKS);    // Will fail.
+
+  dtm_->set_priority_types(
+      AddPriorityTypesTo(syncer::ModelTypeSet(PREFERENCES)));
+
+  // Initial configure.
+  SetConfigureStartExpectation();
+  SetConfigureDoneExpectation(DataTypeManager::PARTIAL_SUCCESS);
+
+  // Initially only PREFERENCES is configured.
+  configurer_.set_expected_configure_types(
+      AddPriorityTypesTo(ModelTypeSet(PREFERENCES)));
+  Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES));
+  EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
+
+  // BOOKMARKS is configured after download of PREFERENCES finishes.
+  configurer_.set_expected_configure_types(ModelTypeSet(BOOKMARKS));
+  FinishDownload(*dtm_, ModelTypeSet(PREFERENCES), ModelTypeSet());
+  EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
+
+  // PERFERENCES controller is associating while BOOKMARKS is downloading.
+  EXPECT_EQ(DataTypeController::ASSOCIATING,
+            GetController(PREFERENCES)->state());
+  EXPECT_EQ(DataTypeController::NOT_RUNNING, GetController(BOOKMARKS)->state());
+
+  // BOOKMARKS finishes downloading and PREFERENCES finishes associating.
+  FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
+  GetController(PREFERENCES)->FinishStart(DataTypeController::OK);
+  EXPECT_EQ(DataTypeController::RUNNING, GetController(PREFERENCES)->state());
+
+  // Make BOOKMARKS association fail, which triggers reconfigure with only
+  // PREFERENCES.
+  configurer_.set_expected_configure_types(
+      AddPriorityTypesTo(ModelTypeSet(PREFERENCES)));
+  GetController(BOOKMARKS)->FinishStart(
+      DataTypeController::ASSOCIATION_FAILED);
+  EXPECT_EQ(DataTypeController::NOT_RUNNING,
+            GetController(BOOKMARKS)->state());
+  EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
+
+  // Finish configuration with only PREFERENCES.
+  FinishDownload(*dtm_, ModelTypeSet(PREFERENCES), ModelTypeSet());
+  EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
+  EXPECT_EQ(DataTypeController::RUNNING, GetController(PREFERENCES)->state());
+  EXPECT_EQ(DataTypeController::NOT_RUNNING,
+            GetController(BOOKMARKS)->state());
+}
 
 }  // namespace browser_sync
diff --git a/chrome/browser/sync/glue/failed_data_types_handler.cc b/chrome/browser/sync/glue/failed_data_types_handler.cc
index 594911f..ada738c 100644
--- a/chrome/browser/sync/glue/failed_data_types_handler.cc
+++ b/chrome/browser/sync/glue/failed_data_types_handler.cc
@@ -30,40 +30,57 @@
 FailedDataTypesHandler::~FailedDataTypesHandler() {
 }
 
-bool FailedDataTypesHandler::UpdateFailedDataTypes(
-    const TypeErrorMap& errors,
-    FailureType failure_type) {
-  if (failure_type == RUNTIME) {
-    runtime_errors_.insert(errors.begin(), errors.end());
-  } else if (failure_type == STARTUP) {
-    startup_errors_.insert(errors.begin(), errors.end());
-  } else if (failure_type == CRYPTO) {
-    crypto_errors_.insert(errors.begin(), errors.end());
-  } else {
-    NOTREACHED();
-  }
+bool FailedDataTypesHandler::UpdateFailedDataTypes(const TypeErrorMap& errors) {
+  if (errors.empty())
+    return false;
 
-  return !errors.empty();
+  for (TypeErrorMap::const_iterator iter = errors.begin(); iter != errors.end();
+       ++iter) {
+    syncer::SyncError::ErrorType failure_type = iter->second.error_type();
+    switch (failure_type) {
+      case syncer::SyncError::UNRECOVERABLE_ERROR:
+      case syncer::SyncError::DATATYPE_ERROR:
+        fatal_errors_.insert(*iter);
+        break;
+      case syncer::SyncError::CRYPTO_ERROR:
+        crypto_errors_.insert(*iter);
+        break;
+      case syncer::SyncError::PERSISTENCE_ERROR:
+        persistence_errors_.insert(*iter);
+        break;
+      default:
+        NOTREACHED();
+    }
+  }
+  return true;
 }
 
 void FailedDataTypesHandler::Reset() {
-  startup_errors_.clear();
-  runtime_errors_.clear();
+  fatal_errors_.clear();
   crypto_errors_.clear();
+  persistence_errors_.clear();
 }
 
 void FailedDataTypesHandler::ResetCryptoErrors() {
   crypto_errors_.clear();
 }
 
+void FailedDataTypesHandler::ResetPersistenceErrorsFrom(
+    syncer::ModelTypeSet purged_types) {
+  for (syncer::ModelTypeSet::Iterator iter = purged_types.First(); iter.Good();
+       iter.Inc()) {
+    persistence_errors_.erase(iter.Get());
+  }
+}
+
 FailedDataTypesHandler::TypeErrorMap FailedDataTypesHandler::GetAllErrors()
     const {
   TypeErrorMap result;
 
   if (AnyFailedDataType()) {
-    result = startup_errors_;
-    result.insert(runtime_errors_.begin(), runtime_errors_.end());
+    result = fatal_errors_;
     result.insert(crypto_errors_.begin(), crypto_errors_.end());
+    result.insert(persistence_errors_.begin(), persistence_errors_.end());
   }
   return result;
 }
@@ -75,9 +92,7 @@
 }
 
 syncer::ModelTypeSet FailedDataTypesHandler::GetFatalErrorTypes() const {
-  syncer::ModelTypeSet result = GetTypesFromErrorMap(startup_errors_);
-  result.PutAll(GetTypesFromErrorMap(runtime_errors_));
-  return result;
+  return GetTypesFromErrorMap(fatal_errors_);;
 }
 
 syncer::ModelTypeSet FailedDataTypesHandler::GetCryptoErrorTypes() const {
@@ -85,9 +100,15 @@
   return result;
 }
 
+syncer::ModelTypeSet FailedDataTypesHandler::GetPersistenceErrorTypes() const {
+  syncer::ModelTypeSet result = GetTypesFromErrorMap(persistence_errors_);
+  return result;
+}
+
 bool FailedDataTypesHandler::AnyFailedDataType() const {
-  return (!startup_errors_.empty() || !runtime_errors_.empty() ||
-          !crypto_errors_.empty());
+  // Note: persistence errors are not failed types. They just trigger automatic
+  // unapply + getupdates, at which point they are associated like normal.
+  return !fatal_errors_.empty() || !crypto_errors_.empty();
 }
 
 }  // namespace browser_sync
diff --git a/chrome/browser/sync/glue/failed_data_types_handler.h b/chrome/browser/sync/glue/failed_data_types_handler.h
index 1998cd8..0b86fd8 100644
--- a/chrome/browser/sync/glue/failed_data_types_handler.h
+++ b/chrome/browser/sync/glue/failed_data_types_handler.h
@@ -14,25 +14,14 @@
 // Class to keep track of data types that have encountered an error during sync.
 class FailedDataTypesHandler {
  public:
-  enum FailureType {
-    // The dataype failed at startup.
-    STARTUP,
-
-    // The datatype encountered a runtime error.
-    RUNTIME,
-
-    // The datatype encountered a cryptographer related error.
-    CRYPTO
-  };
   typedef std::map<syncer::ModelType, syncer::SyncError> TypeErrorMap;
 
   explicit FailedDataTypesHandler();
   ~FailedDataTypesHandler();
 
-  // Called with the result of sync configuration. The types with errors
-  // are obtained from the |result|.
-  bool UpdateFailedDataTypes(const TypeErrorMap& errors,
-                             FailureType failure_type);
+  // Update the failed datatypes. Types will be added to their corresponding
+  // error map based on their |error_type()|.
+  bool UpdateFailedDataTypes(const TypeErrorMap& errors);
 
   // Resets the current set of data type errors.
   void Reset();
@@ -40,6 +29,9 @@
   // Resets the set of types with cryptographer errors.
   void ResetCryptoErrors();
 
+  // Resets those persistence errors that intersect with |purged_types|.
+  void ResetPersistenceErrorsFrom(syncer::ModelTypeSet purged_types);
+
   // Returns a list of all the errors this class has recorded.
   TypeErrorMap GetAllErrors() const;
 
@@ -52,19 +44,24 @@
   // Returns the types that are failing due to cryptographer errors.
   syncer::ModelTypeSet GetCryptoErrorTypes() const;
 
+  // Returns the types that are failing due to persistence errors.
+  syncer::ModelTypeSet GetPersistenceErrorTypes() const;
+
  private:
   // Returns true if there are any types with errors.
   bool AnyFailedDataType() const;
 
-  // List of data types that failed at startup due to association errors.
-  TypeErrorMap startup_errors_;
-
-  // List of data types that failed at runtime.
-  TypeErrorMap runtime_errors_;
+  // List of data types that failed at startup due to association errors or
+  // runtime due to data type errors.
+  TypeErrorMap fatal_errors_;
 
   // List of data types that failed due to the cryptographer not being ready.
   TypeErrorMap crypto_errors_;
 
+  // List of data type that failed because sync did not persist the newest
+  // version of their data.
+  TypeErrorMap persistence_errors_;
+
   DISALLOW_COPY_AND_ASSIGN(FailedDataTypesHandler);
 };
 
diff --git a/chrome/browser/sync/glue/fake_data_type_controller.cc b/chrome/browser/sync/glue/fake_data_type_controller.cc
index d424a1a..f21f27b 100644
--- a/chrome/browser/sync/glue/fake_data_type_controller.cc
+++ b/chrome/browser/sync/glue/fake_data_type_controller.cc
@@ -64,11 +64,17 @@
   } else if (result == ASSOCIATION_FAILED) {
     state_ = DISABLED;
     local_merge_result.set_error(
-        syncer::SyncError(FROM_HERE, "Association failed", type()));
+        syncer::SyncError(FROM_HERE,
+                          syncer::SyncError::DATATYPE_ERROR,
+                          "Association failed",
+                          type()));
   } else {
     state_ = NOT_RUNNING;
     local_merge_result.set_error(
-        syncer::SyncError(FROM_HERE, "Fake error", type()));
+        syncer::SyncError(FROM_HERE,
+                          syncer::SyncError::DATATYPE_ERROR,
+                          "Fake error",
+                          type()));
   }
   StartCallback start_callback = last_start_callback_;
   last_start_callback_.Reset();
@@ -89,7 +95,10 @@
 
   // The DTM still expects |last_start_callback_| to be called back.
   if (!last_start_callback_.is_null()) {
-    syncer::SyncError error(FROM_HERE, "Fake error", type_);
+    syncer::SyncError error(FROM_HERE,
+                            syncer::SyncError::DATATYPE_ERROR,
+                            "Fake error",
+                            type_);
     syncer::SyncMergeResult local_merge_result(type_);
     local_merge_result.set_error(error);
     last_start_callback_.Run(ABORTED,
diff --git a/chrome/browser/sync/glue/favicon_cache.cc b/chrome/browser/sync/glue/favicon_cache.cc
index 4111f32..58416fc 100644
--- a/chrome/browser/sync/glue/favicon_cache.cc
+++ b/chrome/browser/sync/glue/favicon_cache.cc
@@ -326,6 +326,7 @@
   if (!favicon_images_sync_processor_.get() ||
       !favicon_tracking_sync_processor_.get()) {
     return syncer::SyncError(FROM_HERE,
+                             syncer::SyncError::DATATYPE_ERROR,
                              "One or both favicon types disabled.",
                              change_list[0].sync_data().GetDataType());
   }
diff --git a/chrome/browser/sync/glue/favicon_cache.h b/chrome/browser/sync/glue/favicon_cache.h
index 4dea3c7..a273aa0 100644
--- a/chrome/browser/sync/glue/favicon_cache.h
+++ b/chrome/browser/sync/glue/favicon_cache.h
@@ -20,10 +20,10 @@
 #include "chrome/common/cancelable_task_tracker.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
-#include "googleurl/src/gurl.h"
 #include "sync/api/sync_change.h"
 #include "sync/api/sync_error_factory.h"
 #include "sync/api/syncable_service.h"
+#include "url/gurl.h"
 
 class Profile;
 
diff --git a/chrome/browser/sync/glue/favicon_cache_unittest.cc b/chrome/browser/sync/glue/favicon_cache_unittest.cc
index cde093c..697f371 100644
--- a/chrome/browser/sync/glue/favicon_cache_unittest.cc
+++ b/chrome/browser/sync/glue/favicon_cache_unittest.cc
@@ -77,7 +77,10 @@
     const syncer::SyncChangeList& change_list) {
   if (erroneous_) {
     return syncer::SyncError(
-        FROM_HERE, "Some error.", change_list[0].sync_data().GetDataType());
+        FROM_HERE,
+        syncer::SyncError::DATATYPE_ERROR,
+        "Some error.",
+        change_list[0].sync_data().GetDataType());
   }
 
   change_list_.insert(change_list_.end(),
diff --git a/chrome/browser/sync/glue/frontend_data_type_controller.cc b/chrome/browser/sync/glue/frontend_data_type_controller.cc
index c3b0cf6..043ca23 100644
--- a/chrome/browser/sync/glue/frontend_data_type_controller.cc
+++ b/chrome/browser/sync/glue/frontend_data_type_controller.cc
@@ -40,7 +40,9 @@
   DCHECK(!model_load_callback.is_null());
 
   if (state_ != NOT_RUNNING) {
-    model_load_callback.Run(type(), syncer::SyncError(FROM_HERE,
+    model_load_callback.Run(type(),
+                            syncer::SyncError(FROM_HERE,
+                                              syncer::SyncError::DATATYPE_ERROR,
                                               "Model already running",
                                               type()));
     return;
@@ -170,7 +172,10 @@
 
   bool sync_has_nodes = false;
   if (!model_associator()->SyncModelHasUserCreatedNodes(&sync_has_nodes)) {
-    syncer::SyncError error(FROM_HERE, "Failed to load sync nodes", type());
+    syncer::SyncError error(FROM_HERE,
+                            syncer::SyncError::UNRECOVERABLE_ERROR,
+                            "Failed to load sync nodes",
+                            type());
     local_merge_result.set_error(error);
     StartDone(UNRECOVERABLE_ERROR, local_merge_result, syncer_merge_result);
     return false;
@@ -223,7 +228,9 @@
   state_ = NOT_RUNNING;
   ModelLoadCallback model_load_callback = model_load_callback_;
   model_load_callback_.Reset();
-  model_load_callback.Run(type(), syncer::SyncError(FROM_HERE,
+  model_load_callback.Run(type(),
+                          syncer::SyncError(FROM_HERE,
+                                            syncer::SyncError::DATATYPE_ERROR,
                                             "Aborted",
                                             type()));
 }
diff --git a/chrome/browser/sync/glue/frontend_data_type_controller_unittest.cc b/chrome/browser/sync/glue/frontend_data_type_controller_unittest.cc
index c9422a3..12c1923 100644
--- a/chrome/browser/sync/glue/frontend_data_type_controller_unittest.cc
+++ b/chrome/browser/sync/glue/frontend_data_type_controller_unittest.cc
@@ -209,8 +209,9 @@
       WillOnce(DoAll(SetArgumentPointee<0>(true), Return(true)));
   EXPECT_CALL(*model_associator_, AssociateModels(_, _)).
       WillOnce(Return(syncer::SyncError(FROM_HERE,
-                                "error",
-                                syncer::BOOKMARKS)));
+                                        syncer::SyncError::DATATYPE_ERROR,
+                                        "error",
+                                        syncer::BOOKMARKS)));
 
   EXPECT_CALL(*dtc_mock_.get(), RecordAssociationTime(_));
   SetStartFailExpectations(DataTypeController::ASSOCIATION_FAILED);
diff --git a/chrome/browser/sync/glue/generic_change_processor.cc b/chrome/browser/sync/glue/generic_change_processor.cc
index cf1daa8..591e717 100644
--- a/chrome/browser/sync/glue/generic_change_processor.cc
+++ b/chrome/browser/sync/glue/generic_change_processor.cc
@@ -83,7 +83,10 @@
     return;
   if (!local_service_.get()) {
     syncer::ModelType type = syncer_changes_[0].sync_data().GetDataType();
-    syncer::SyncError error(FROM_HERE, "Local service destroyed.", type);
+    syncer::SyncError error(FROM_HERE,
+                            syncer::SyncError::DATATYPE_ERROR,
+                            "Local service destroyed.",
+                            type);
     error_handler()->OnSingleDatatypeUnrecoverableError(error.location(),
                                                         error.message());
     return;
@@ -107,9 +110,11 @@
   if (root.InitByTagLookup(syncer::ModelTypeToRootTag(type)) !=
           syncer::BaseNode::INIT_OK) {
     syncer::SyncError error(FROM_HERE,
-                    "Server did not create the top-level " + type_name +
-                    " node. We might be running against an out-of-date server.",
-                    type);
+                            syncer::SyncError::DATATYPE_ERROR,
+                            "Server did not create the top-level " + type_name +
+                                " node. We might be running against an out-of-"
+                                "date server.",
+                            type);
     return error;
   }
 
@@ -125,8 +130,10 @@
     if (sync_child_node.InitByIdLookup(*it) !=
             syncer::BaseNode::INIT_OK) {
       syncer::SyncError error(FROM_HERE,
-                      "Failed to fetch child node for type " + type_name + ".",
-                       type);
+                              syncer::SyncError::DATATYPE_ERROR,
+                              "Failed to fetch child node for type " +
+                                  type_name + ".",
+                              type);
       return error;
     }
     current_sync_data->push_back(syncer::SyncData::CreateRemoteData(
@@ -221,6 +228,7 @@
     if (tag.empty()) {
       syncer::SyncError error(
           FROM_HERE,
+          syncer::SyncError::DATATYPE_ERROR,
           "Failed to delete " + type_str + " node. Local data, empty tag. " +
               change.location().ToString(),
           type);
@@ -297,8 +305,10 @@
               syncer::ModelTypeToRootTag(change.sync_data().GetDataType())) !=
                   syncer::BaseNode::INIT_OK) {
         syncer::SyncError error(FROM_HERE,
-                        "Failed to look up root node for type " + type_str,
-                        type);
+                                syncer::SyncError::DATATYPE_ERROR,
+                                "Failed to look up root node for type " +
+                                    type_str,
+                                type);
         error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE,
                                                             error.message());
         NOTREACHED();
@@ -461,6 +471,7 @@
     } else {
       syncer::SyncError error(
           FROM_HERE,
+          syncer::SyncError::DATATYPE_ERROR,
           "Received unset SyncChange in the change processor, " +
               change.location().ToString(),
           type);
diff --git a/chrome/browser/sync/glue/generic_change_processor_unittest.cc b/chrome/browser/sync/glue/generic_change_processor_unittest.cc
index d245a8b..bb90a50 100644
--- a/chrome/browser/sync/glue/generic_change_processor_unittest.cc
+++ b/chrome/browser/sync/glue/generic_change_processor_unittest.cc
@@ -29,7 +29,7 @@
   static const syncer::ModelType kType = syncer::PREFERENCES;
 
   GenericChangeProcessorTest() :
-      loop(base::MessageLoop::TYPE_UI),
+      loop_(base::MessageLoop::TYPE_UI),
       sync_merge_result_(kType),
       merge_result_ptr_factory_(&sync_merge_result_),
       syncable_service_ptr_factory_(&fake_syncable_service_) {
@@ -70,7 +70,7 @@
   }
 
  private:
-  base::MessageLoop loop;
+  base::MessageLoop loop_;
 
   syncer::SyncMergeResult sync_merge_result_;
   base::WeakPtrFactory<syncer::SyncMergeResult> merge_result_ptr_factory_;
diff --git a/chrome/browser/sync/glue/model_association_manager.cc b/chrome/browser/sync/glue/model_association_manager.cc
index 4049523..28f245e 100644
--- a/chrome/browser/sync/glue/model_association_manager.cc
+++ b/chrome/browser/sync/glue/model_association_manager.cc
@@ -150,7 +150,8 @@
   needs_crypto_types_.Clear();
   state_ = INITIALIZED_TO_CONFIGURE;
 
-  DVLOG(1) << "ModelAssociationManager: Initializing";
+  DVLOG(1) << "ModelAssociationManager: Initializing for "
+           << syncer::ModelTypeSetToString(desired_types);
 
   // Stop the types that are still loading from the previous configuration.
   // If they are enabled we will start them here once again.
@@ -217,7 +218,6 @@
 }
 
 void ModelAssociationManager::StopDisabledTypes() {
-  DCHECK_EQ(state_, INITIALIZED_TO_CONFIGURE);
   DVLOG(1) << "ModelAssociationManager: Stopping disabled types.";
   // Stop requested data types.
   for (size_t i = 0; i < needs_stop_.size(); ++i) {
@@ -231,7 +231,7 @@
   bool need_to_call_model_association_done = false;
   DVLOG(1) << "ModelAssociationManager: Stopping MAM";
   if (state_ == CONFIGURING) {
-    DVLOG(1) << "ModelAssociationManager: In the middle of configuratio while"
+    DVLOG(1) << "ModelAssociationManager: In the middle of configuration while"
              << " stopping";
     state_ = ABORTED;
     DCHECK(currently_associating_ != NULL ||
@@ -311,11 +311,11 @@
 void ModelAssociationManager::AppendToFailedDatatypesAndLogError(
     DataTypeController::StartResult result,
     const syncer::SyncError& error) {
-  failed_data_types_info_[error.type()] = error;
+  failed_data_types_info_[error.model_type()] = error;
   LOG(ERROR) << "Failed to associate models for "
-             << syncer::ModelTypeToString(error.type());
+             << syncer::ModelTypeToString(error.model_type());
   UMA_HISTOGRAM_ENUMERATION("Sync.ConfigureFailed",
-                            ModelTypeToHistogramInt(error.type()),
+                            ModelTypeToHistogramInt(error.model_type()),
                             syncer::MODEL_TYPE_COUNT);
 }
 
@@ -386,7 +386,7 @@
   // Any other result requires reconfiguration. Pass it on through the callback.
   LOG(ERROR) << "Failed to configure " << started_dtc->name();
   DCHECK(local_merge_result.error().IsSet());
-  DCHECK_EQ(started_dtc->type(), local_merge_result.error().type());
+  DCHECK_EQ(started_dtc->type(), local_merge_result.error().model_type());
   DataTypeManager::ConfigureStatus configure_status =
       DataTypeManager::ABORTED;
   switch (start_result) {
@@ -435,7 +435,7 @@
     return;
   }
 
-  DVLOG(1) << "ModelAssociationManager: All types have models loaded."
+  DVLOG(1) << "ModelAssociationManager: All types have models loaded. "
           << "Moving on to StartAssociatingNextType.";
 
   // If all controllers have their |LoadModels| invoked then pass onto
@@ -490,7 +490,7 @@
     NOTREACHED();
     return;
   } else if (state_ == IDLE) {
-    DVLOG(1) << "ModelAssociationManager: Models loaded after configure cycle"
+    DVLOG(1) << "ModelAssociationManager: Models loaded after configure cycle. "
             << "Informing DTM";
     // This datatype finished loading after the deadline imposed by the
     // originating configuration cycle. Inform the DataTypeManager that the
@@ -526,7 +526,19 @@
     return;
   }
 
-  // We are done with this cycle of association.
+  // We are done with this cycle of association. Stop any failed types now.
+  needs_stop_.clear();
+  for (DataTypeController::TypeMap::const_iterator it = controllers_->begin();
+       it != controllers_->end(); ++it) {
+    DataTypeController* dtc = (*it).second.get();
+    if (failed_data_types_info_.count(dtc->type()) > 0 &&
+        dtc->state() != DataTypeController::NOT_RUNNING) {
+      needs_stop_.push_back(dtc);
+      DVLOG(1) << "ModelTypeToString: Will stop " << dtc->name();
+    }
+  }
+  StopDisabledTypes();
+
   state_ = IDLE;
 
   DataTypeManager::ConfigureStatus configure_status = DataTypeManager::OK;
diff --git a/chrome/browser/sync/glue/model_association_manager.h b/chrome/browser/sync/glue/model_association_manager.h
index 5d4ed25..94576c8 100644
--- a/chrome/browser/sync/glue/model_association_manager.h
+++ b/chrome/browser/sync/glue/model_association_manager.h
@@ -8,7 +8,7 @@
 #include <map>
 
 #include "base/memory/weak_ptr.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 
 #include "chrome/browser/sync/glue/data_type_manager.h"
 #include "sync/internal_api/public/data_type_association_stats.h"
diff --git a/chrome/browser/sync/glue/model_association_manager_unittest.cc b/chrome/browser/sync/glue/model_association_manager_unittest.cc
index a36596f..2d9c131 100644
--- a/chrome/browser/sync/glue/model_association_manager_unittest.cc
+++ b/chrome/browser/sync/glue/model_association_manager_unittest.cc
@@ -171,7 +171,10 @@
   syncer::ModelTypeSet types;
   types.Put(syncer::BOOKMARKS);
   std::map<syncer::ModelType, syncer::SyncError> errors;
-  syncer::SyncError error(FROM_HERE, "Failed", syncer::BOOKMARKS);
+  syncer::SyncError error(FROM_HERE,
+                          syncer::SyncError::DATATYPE_ERROR,
+                          "Failed",
+                          syncer::BOOKMARKS);
   errors[syncer::BOOKMARKS] = error;
   DataTypeManager::ConfigureResult expected_result(
       DataTypeManager::PARTIAL_SUCCESS,
@@ -190,6 +193,8 @@
             DataTypeController::ASSOCIATING);
   GetController(controllers_, syncer::BOOKMARKS)->FinishStart(
       DataTypeController::ASSOCIATION_FAILED);
+  EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(),
+            DataTypeController::NOT_RUNNING);
 }
 
 // Ensure configuring stops when a type returns a unrecoverable error.
@@ -202,7 +207,10 @@
   syncer::ModelTypeSet types;
   types.Put(syncer::BOOKMARKS);
   std::map<syncer::ModelType, syncer::SyncError> errors;
-  syncer::SyncError error(FROM_HERE, "Failed", syncer::BOOKMARKS);
+  syncer::SyncError error(FROM_HERE,
+                          syncer::SyncError::DATATYPE_ERROR,
+                          "Failed",
+                          syncer::BOOKMARKS);
   errors[syncer::BOOKMARKS] = error;
   DataTypeManager::ConfigureResult expected_result(
       DataTypeManager::UNRECOVERABLE_ERROR,
diff --git a/chrome/browser/sync/glue/non_frontend_data_type_controller.cc b/chrome/browser/sync/glue/non_frontend_data_type_controller.cc
index 1ff03e4..56a07f3 100644
--- a/chrome/browser/sync/glue/non_frontend_data_type_controller.cc
+++ b/chrome/browser/sync/glue/non_frontend_data_type_controller.cc
@@ -48,7 +48,9 @@
   start_association_called_.Reset();
   start_models_failed_ = false;
   if (state_ != NOT_RUNNING) {
-    model_load_callback.Run(type(), syncer::SyncError(FROM_HERE,
+    model_load_callback.Run(type(),
+                            syncer::SyncError(FROM_HERE,
+                                              syncer::SyncError::DATATYPE_ERROR,
                                               "Model already loaded",
                                               type()));
     return;
@@ -63,7 +65,9 @@
     // get a false it means they failed.
     DCHECK(state_ == NOT_RUNNING || state_ == MODEL_STARTING
            || state_ == DISABLED);
-    model_load_callback.Run(type(), syncer::SyncError(FROM_HERE,
+    model_load_callback.Run(type(),
+                            syncer::SyncError(FROM_HERE,
+                                              syncer::SyncError::DATATYPE_ERROR,
                                               "Failed loading",
                                               type()));
     return;
@@ -88,7 +92,9 @@
   start_callback_ = start_callback;
   if (!StartAssociationAsync()) {
     syncer::SyncError error(
-        FROM_HERE, "Failed to post StartAssociation", type());
+        FROM_HERE,
+        syncer::SyncError::DATATYPE_ERROR,
+        "Failed to post StartAssociation", type());
     syncer::SyncMergeResult local_merge_result(type());
     local_merge_result.set_error(error);
     StartDoneImpl(ASSOCIATION_FAILED,
@@ -418,7 +424,10 @@
 
   bool sync_has_nodes = false;
   if (!model_associator_->SyncModelHasUserCreatedNodes(&sync_has_nodes)) {
-    syncer::SyncError error(FROM_HERE, "Failed to load sync nodes", type());
+    syncer::SyncError error(FROM_HERE,
+                            syncer::SyncError::UNRECOVERABLE_ERROR,
+                            "Failed to load sync nodes",
+                            type());
     local_merge_result.set_error(error);
     StartDone(UNRECOVERABLE_ERROR,
               local_merge_result,
diff --git a/chrome/browser/sync/glue/non_frontend_data_type_controller_unittest.cc b/chrome/browser/sync/glue/non_frontend_data_type_controller_unittest.cc
index fa64025..2c6a1d6 100644
--- a/chrome/browser/sync/glue/non_frontend_data_type_controller_unittest.cc
+++ b/chrome/browser/sync/glue/non_frontend_data_type_controller_unittest.cc
@@ -250,7 +250,10 @@
       WillOnce(DoAll(SetArgumentPointee<0>(true), Return(true)));
   EXPECT_CALL(*model_associator_, AssociateModels(_, _)).
       WillOnce(
-          Return(syncer::SyncError(FROM_HERE, "Error", syncer::BOOKMARKS)));
+          Return(syncer::SyncError(FROM_HERE,
+                                   syncer::SyncError::DATATYPE_ERROR,
+                                   "Error",
+                                   syncer::BOOKMARKS)));
   EXPECT_CALL(*dtc_mock_.get(), RecordAssociationTime(_));
   SetStartFailExpectations(DataTypeController::ASSOCIATION_FAILED);
   // Set up association to fail with an association failed error.
diff --git a/chrome/browser/sync/glue/non_ui_data_type_controller.cc b/chrome/browser/sync/glue/non_ui_data_type_controller.cc
index 6cb7516..48c3023 100644
--- a/chrome/browser/sync/glue/non_ui_data_type_controller.cc
+++ b/chrome/browser/sync/glue/non_ui_data_type_controller.cc
@@ -35,9 +35,11 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(!model_load_callback.is_null());
   if (state() != NOT_RUNNING) {
-    model_load_callback.Run(type(), syncer::SyncError(FROM_HERE,
-                                                      "Model already running",
-                                                      type()));
+    model_load_callback.Run(type(),
+                            syncer::SyncError(FROM_HERE,
+                                              syncer::SyncError::DATATYPE_ERROR,
+                                              "Model already running",
+                                              type()));
     return;
   }
 
@@ -92,7 +94,10 @@
   start_callback_ = start_callback;
   if (!StartAssociationAsync()) {
     syncer::SyncError error(
-        FROM_HERE, "Failed to post StartAssociation", type());
+        FROM_HERE,
+        syncer::SyncError::DATATYPE_ERROR,
+        "Failed to post StartAssociation",
+        type());
     syncer::SyncMergeResult local_merge_result(type());
     local_merge_result.set_error(error);
     StartDoneImpl(ASSOCIATION_FAILED,
@@ -273,9 +278,11 @@
   StopModels();
   ModelLoadCallback model_load_callback = model_load_callback_;
   model_load_callback_.Reset();
-  model_load_callback.Run(type(), syncer::SyncError(FROM_HERE,
-                                                    "ABORTED",
-                                                    type()));
+  model_load_callback.Run(type(),
+                          syncer::SyncError(FROM_HERE,
+                                            syncer::SyncError::DATATYPE_ERROR,
+                                            "ABORTED",
+                                            type()));
 }
 
 void NonUIDataTypeController::DisableImpl(
@@ -323,7 +330,10 @@
       type(),
       weak_ptr_factory.GetWeakPtr());
   if (!local_service_.get()) {
-    syncer::SyncError error(FROM_HERE, "Failed to connect to syncer.", type());
+    syncer::SyncError error(FROM_HERE,
+                            syncer::SyncError::DATATYPE_ERROR,
+                            "Failed to connect to syncer.",
+                            type());
     local_merge_result.set_error(error);
     StartDone(ASSOCIATION_FAILED,
               local_merge_result,
@@ -340,7 +350,10 @@
 
   bool sync_has_nodes = false;
   if (!shared_change_processor->SyncModelHasUserCreatedNodes(&sync_has_nodes)) {
-    syncer::SyncError error(FROM_HERE, "Failed to load sync nodes", type());
+    syncer::SyncError error(FROM_HERE,
+                            syncer::SyncError::UNRECOVERABLE_ERROR,
+                            "Failed to load sync nodes",
+                            type());
     local_merge_result.set_error(error);
     StartDone(UNRECOVERABLE_ERROR,
               local_merge_result,
@@ -418,4 +431,4 @@
   local_service_.reset();
 }
 
-}  // namepsace browser_sync
+}  // namespace browser_sync
diff --git a/chrome/browser/sync/glue/non_ui_data_type_controller_unittest.cc b/chrome/browser/sync/glue/non_ui_data_type_controller_unittest.cc
index 43107da..f546bf6 100644
--- a/chrome/browser/sync/glue/non_ui_data_type_controller_unittest.cc
+++ b/chrome/browser/sync/glue/non_ui_data_type_controller_unittest.cc
@@ -323,7 +323,9 @@
   EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
   syncable_service_.set_merge_data_and_start_syncing_error(
       syncer::SyncError(FROM_HERE,
-                        "Sync Error", non_ui_dtc_->type()));
+                        syncer::SyncError::DATATYPE_ERROR,
+                        "Sync Error",
+                        non_ui_dtc_->type()));
   Start();
   WaitForDTC();
   EXPECT_EQ(DataTypeController::DISABLED, non_ui_dtc_->state());
@@ -381,7 +383,10 @@
                       SetArgumentPointee<0>(true),
                       Return(true)));
   EXPECT_CALL(*change_processor_.get(), GetSyncData(_)).WillOnce(
-      Return(syncer::SyncError(FROM_HERE, "Disconnected.", AUTOFILL_PROFILE)));
+      Return(syncer::SyncError(FROM_HERE,
+                               syncer::SyncError::DATATYPE_ERROR,
+                               "Disconnected.",
+                               AUTOFILL_PROFILE)));
   EXPECT_CALL(*change_processor_.get(), Disconnect())
       .WillOnce(DoAll(SignalEvent(&pause_db_thread), Return(true)));
   EXPECT_CALL(service_, DeactivateDataType(_));
diff --git a/chrome/browser/sync/glue/password_model_associator.cc b/chrome/browser/sync/glue/password_model_associator.cc
index 118d9af..f034c47 100644
--- a/chrome/browser/sync/glue/password_model_associator.cc
+++ b/chrome/browser/sync/glue/password_model_associator.cc
@@ -7,6 +7,7 @@
 #include <set>
 
 #include "base/location.h"
+#include "base/metrics/histogram.h"
 #include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/password_manager/password_store.h"
@@ -63,10 +64,16 @@
   if (!password_store_->FillAutofillableLogins(&passwords) ||
       !password_store_->FillBlacklistLogins(&passwords)) {
     STLDeleteElements(&passwords);
-    return error_handler_->CreateAndUploadError(
-        FROM_HERE,
-        "Could not get the password entries.",
-        model_type());
+
+    // Password store often fails to load passwords. Track failures with UMA.
+    // (http://crbug.com/249000)
+    UMA_HISTOGRAM_ENUMERATION("Sync.LocalDataFailedToLoad",
+                              ModelTypeToHistogramInt(syncer::PASSWORDS),
+                              syncer::MODEL_TYPE_COUNT);
+    return syncer::SyncError(FROM_HERE,
+                             syncer::SyncError::DATATYPE_ERROR,
+                             "Could not get the password entries.",
+                             model_type());
   }
 
   std::set<std::string> current_passwords;
diff --git a/chrome/browser/sync/glue/search_engine_data_type_controller_unittest.cc b/chrome/browser/sync/glue/search_engine_data_type_controller_unittest.cc
index 978c329..1e2a360 100644
--- a/chrome/browser/sync/glue/search_engine_data_type_controller_unittest.cc
+++ b/chrome/browser/sync/glue/search_engine_data_type_controller_unittest.cc
@@ -164,7 +164,10 @@
   EXPECT_CALL(start_callback_,
               Run(DataTypeController::ASSOCIATION_FAILED, _, _));
   syncable_service_.set_merge_data_and_start_syncing_error(
-      syncer::SyncError(FROM_HERE, "Error", syncer::SEARCH_ENGINES));
+      syncer::SyncError(FROM_HERE,
+                        syncer::SyncError::DATATYPE_ERROR,
+                        "Error",
+                        syncer::SEARCH_ENGINES));
 
   Start();
   EXPECT_EQ(DataTypeController::DISABLED, search_engine_dtc_->state());
diff --git a/chrome/browser/sync/glue/session_model_associator.h b/chrome/browser/sync/glue/session_model_associator.h
index 615a1d1..4778c44 100644
--- a/chrome/browser/sync/glue/session_model_associator.h
+++ b/chrome/browser/sync/glue/session_model_associator.h
@@ -16,7 +16,7 @@
 #include "base/memory/linked_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/threading/non_thread_safe.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/sessions/session_id.h"
 #include "chrome/browser/sessions/session_service.h"
 #include "chrome/browser/sessions/session_types.h"
diff --git a/chrome/browser/sync/glue/session_model_associator_unittest.cc b/chrome/browser/sync/glue/session_model_associator_unittest.cc
index f63e44b..34c01a1 100644
--- a/chrome/browser/sync/glue/session_model_associator_unittest.cc
+++ b/chrome/browser/sync/glue/session_model_associator_unittest.cc
@@ -20,11 +20,11 @@
 #include "content/public/browser/notification_service.h"
 #include "content/public/common/page_transition_types.h"
 #include "content/public/test/test_browser_thread.h"
-#include "googleurl/src/gurl.h"
 #include "sync/protocol/session_specifics.pb.h"
 #include "sync/util/time.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 using content::BrowserThread;
 using sessions::SerializedNavigationEntry;
diff --git a/chrome/browser/sync/glue/shared_change_processor.cc b/chrome/browser/sync/glue/shared_change_processor.cc
index 0dd0833..abe7070 100644
--- a/chrome/browser/sync/glue/shared_change_processor.cc
+++ b/chrome/browser/sync/glue/shared_change_processor.cc
@@ -95,7 +95,10 @@
   DCHECK(backend_loop_->BelongsToCurrentThread());
   AutoLock lock(monitor_lock_);
   if (disconnected_) {
-    syncer::SyncError error(FROM_HERE, "Change processor disconnected.", type_);
+    syncer::SyncError error(FROM_HERE,
+                            syncer::SyncError::DATATYPE_ERROR,
+                            "Change processor disconnected.",
+                            type_);
     return error;
   }
   return generic_change_processor_->GetSyncDataForType(type_,
@@ -122,7 +125,10 @@
   if (disconnected_) {
     // The DTC that disconnects us must ensure it posts a StopSyncing task.
     // If we reach this, it means it just hasn't executed yet.
-    syncer::SyncError error(FROM_HERE, "Change processor disconnected.", type_);
+    syncer::SyncError error(FROM_HERE,
+                            syncer::SyncError::DATATYPE_ERROR,
+                            "Change processor disconnected.",
+                            type_);
     return error;
   }
   return generic_change_processor_->ProcessSyncChanges(
@@ -173,7 +179,10 @@
   if (!disconnected_) {
     return error_handler_->CreateAndUploadError(location, message, type_);
   } else {
-    return syncer::SyncError(location, message, type_);
+    return syncer::SyncError(location,
+                             syncer::SyncError::DATATYPE_ERROR,
+                             message,
+                             type_);
   }
 }
 
diff --git a/chrome/browser/sync/glue/sync_backend_host.cc b/chrome/browser/sync/glue/sync_backend_host.cc
index 907b176..870c4d5 100644
--- a/chrome/browser/sync/glue/sync_backend_host.cc
+++ b/chrome/browser/sync/glue/sync_backend_host.cc
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "build/build_config.h"
-
 #include "chrome/browser/sync/glue/sync_backend_host.h"
 
 #include <algorithm>
@@ -18,16 +16,15 @@
 #include "base/metrics/histogram.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_restrictions.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "base/tracked_objects.h"
 #include "build/build_config.h"
-#include "chrome/browser/invalidation/invalidator_storage.h"
+#include "chrome/browser/invalidation/invalidation_service.h"
+#include "chrome/browser/invalidation/invalidation_service_factory.h"
 #include "chrome/browser/net/network_time_tracker.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/token_service.h"
 #include "chrome/browser/signin/token_service_factory.h"
-#include "chrome/browser/sync/glue/android_invalidator_bridge.h"
-#include "chrome/browser/sync/glue/android_invalidator_bridge_proxy.h"
 #include "chrome/browser/sync/glue/change_processor.h"
 #include "chrome/browser/sync/glue/chrome_encryptor.h"
 #include "chrome/browser/sync/glue/device_info.h"
@@ -56,11 +53,14 @@
 #include "sync/internal_api/public/sync_manager_factory.h"
 #include "sync/internal_api/public/util/experiments.h"
 #include "sync/internal_api/public/util/sync_string_conversions.h"
-#include "sync/notifier/invalidator.h"
 #include "sync/protocol/encryption.pb.h"
 #include "sync/protocol/sync.pb.h"
 #include "sync/util/nigori.h"
 
+#if defined(ENABLE_MANAGED_USERS)
+#include "chrome/browser/managed_mode/managed_user_service.h"
+#endif
+
 static const int kSaveChangesIntervalSeconds = 10;
 static const base::FilePath::CharType kSyncDataFolderName[] =
     FILE_PATH_LITERAL("Sync Data");
@@ -85,9 +85,9 @@
   DoConfigureSyncerTypes() {}
   ~DoConfigureSyncerTypes() {}
   syncer::ModelTypeSet to_download;
+  syncer::ModelTypeSet to_purge;
   syncer::ModelTypeSet to_journal;
   syncer::ModelTypeSet to_unapply;
-  syncer::ModelTypeSet to_ignore;
 };
 
 }  // namespace
@@ -102,8 +102,7 @@
 class SyncBackendHost::Core
     : public base::RefCountedThreadSafe<SyncBackendHost::Core>,
       public syncer::SyncEncryptionHandler::Observer,
-      public syncer::SyncManager::Observer,
-      public syncer::InvalidationHandler {
+      public syncer::SyncManager::Observer {
  public:
   Core(const std::string& name,
        const base::FilePath& sync_data_folder_path,
@@ -144,11 +143,12 @@
   virtual void OnPassphraseTypeChanged(syncer::PassphraseType type,
                                        base::Time passphrase_time) OVERRIDE;
 
-  // syncer::InvalidationHandler implementation.
-  virtual void OnInvalidatorStateChange(
-      syncer::InvalidatorState state) OVERRIDE;
-  virtual void OnIncomingInvalidation(
-      const syncer::ObjectIdInvalidationMap& invalidation_map) OVERRIDE;
+  // Forwards an invalidation state change to the sync manager.
+  void DoOnInvalidatorStateChange(syncer::InvalidatorState state);
+
+  // Forwards an invalidation to the sync manager.
+  void DoOnIncomingInvalidation(
+      syncer::ObjectIdInvalidationMap invalidation_map);
 
   // Note:
   //
@@ -165,15 +165,6 @@
   // SyncBackendHost::UpdateCredentials.
   void DoUpdateCredentials(const syncer::SyncCredentials& credentials);
 
-  // Called to update the given registered ids on behalf of
-  // SyncBackendHost::UpdateRegisteredInvalidationIds.
-  void DoUpdateRegisteredInvalidationIds(const syncer::ObjectIdSet& ids);
-
-  // Called to acknowledge an invalidation on behalf of
-  // SyncBackendHost::AcknowledgeInvalidation.
-  void DoAcknowledgeInvalidation(const invalidation::ObjectId& id,
-                                 const syncer::AckHandle& ack_handle);
-
   // Called to tell the syncapi to start syncing (generally after
   // initialization and authentication).
   void DoStartSyncing(const syncer::ModelSafeRoutingInfo& routing_info);
@@ -304,69 +295,13 @@
   // The top-level syncapi entry point.  Lives on the sync thread.
   scoped_ptr<syncer::SyncManager> sync_manager_;
 
-  // Whether or not we registered with |sync_manager_| as an invalidation
-  // handler.  Necessary since we may end up trying to unregister before we
-  // register in tests (in synchronous initialization mode).
-  //
-  // TODO(akalin): Fix this behavior (see http://crbug.com/140354).
-  bool registered_as_invalidation_handler_;
-
   DISALLOW_COPY_AND_ASSIGN(Core);
 };
 
-namespace {
-
-// Parses the given command line for notifier options.
-notifier::NotifierOptions ParseNotifierOptions(
-    const CommandLine& command_line,
-    const scoped_refptr<net::URLRequestContextGetter>&
-        request_context_getter) {
-  notifier::NotifierOptions notifier_options;
-  notifier_options.request_context_getter = request_context_getter;
-  if (!command_line.HasSwitch(switches::kSyncDisableOAuth2Token))
-    notifier_options.auth_mechanism = "X-OAUTH2";
-
-  if (command_line.HasSwitch(switches::kSyncNotificationHostPort)) {
-    notifier_options.xmpp_host_port =
-        net::HostPortPair::FromString(
-            command_line.GetSwitchValueASCII(
-                switches::kSyncNotificationHostPort));
-    DVLOG(1) << "Using " << notifier_options.xmpp_host_port.ToString()
-             << " for test sync notification server.";
-  }
-
-  notifier_options.try_ssltcp_first =
-      command_line.HasSwitch(switches::kSyncTrySsltcpFirstForXmpp);
-  DVLOG_IF(1, notifier_options.try_ssltcp_first)
-      << "Trying SSL/TCP port before XMPP port for notifications.";
-
-  notifier_options.invalidate_xmpp_login =
-      command_line.HasSwitch(switches::kSyncInvalidateXmppLogin);
-  DVLOG_IF(1, notifier_options.invalidate_xmpp_login)
-      << "Invalidating sync XMPP login.";
-
-  notifier_options.allow_insecure_connection =
-      command_line.HasSwitch(switches::kSyncAllowInsecureXmppConnection);
-  DVLOG_IF(1, notifier_options.allow_insecure_connection)
-      << "Allowing insecure XMPP connections.";
-
-  if (command_line.HasSwitch(switches::kSyncNotificationMethod)) {
-    const std::string notification_method_str(
-        command_line.GetSwitchValueASCII(switches::kSyncNotificationMethod));
-    notifier_options.notification_method =
-        notifier::StringToNotificationMethod(notification_method_str);
-  }
-
-  return notifier_options;
-}
-
-}  // namespace
-
 SyncBackendHost::SyncBackendHost(
     const std::string& name,
     Profile* profile,
-    const base::WeakPtr<SyncPrefs>& sync_prefs,
-    const base::WeakPtr<invalidation::InvalidatorStorage>& invalidator_storage)
+    const base::WeakPtr<SyncPrefs>& sync_prefs)
     : weak_ptr_factory_(this),
       sync_thread_("Chrome_SyncThread"),
       frontend_loop_(base::MessageLoop::current()),
@@ -376,13 +311,10 @@
                      weak_ptr_factory_.GetWeakPtr())),
       initialization_state_(NOT_ATTEMPTED),
       sync_prefs_(sync_prefs),
-      invalidator_factory_(
-          ParseNotifierOptions(*CommandLine::ForCurrentProcess(),
-                               profile_->GetRequestContext()),
-          content::GetUserAgent(GURL()),
-          invalidator_storage),
       frontend_(NULL),
-      cached_passphrase_type_(syncer::IMPLICIT_PASSPHRASE) {
+      cached_passphrase_type_(syncer::IMPLICIT_PASSPHRASE),
+      invalidator_(
+          invalidation::InvalidationServiceFactory::GetForProfile(profile)) {
 }
 
 SyncBackendHost::SyncBackendHost(Profile* profile)
@@ -392,18 +324,12 @@
       profile_(profile),
       name_("Unknown"),
       initialization_state_(NOT_ATTEMPTED),
-      invalidator_factory_(
-          ParseNotifierOptions(*CommandLine::ForCurrentProcess(),
-                               profile_->GetRequestContext()),
-          content::GetUserAgent(GURL()),
-          base::WeakPtr<syncer::InvalidationStateTracker>()),
       frontend_(NULL),
       cached_passphrase_type_(syncer::IMPLICIT_PASSPHRASE) {
 }
 
 SyncBackendHost::~SyncBackendHost() {
   DCHECK(!core_.get() && !frontend_) << "Must call Shutdown before destructor.";
-  DCHECK(!android_invalidator_bridge_.get());
   DCHECK(!registrar_.get());
 }
 
@@ -435,10 +361,6 @@
   if (!sync_thread_.Start())
     return;
 
-  android_invalidator_bridge_.reset(
-      new AndroidInvalidatorBridge(
-          profile_, sync_thread_.message_loop_proxy()));
-
   frontend_ = frontend;
   DCHECK(frontend);
 
@@ -461,6 +383,8 @@
         InternalComponentsFactoryImpl::BACKOFF_SHORT_INITIAL_RETRY_OVERRIDE;
   }
 
+  invalidator_->RegisterInvalidationHandler(this);
+
   initialization_state_ = CREATING_SYNC_MANAGER;
   InitCore(DoInitializeOptions(
       sync_thread_.message_loop(),
@@ -474,8 +398,7 @@
                  make_scoped_refptr(profile_->GetRequestContext()),
                  NetworkTimeTracker::BuildNotifierUpdateCallback()),
       credentials,
-      android_invalidator_bridge_.get(),
-      &invalidator_factory_,
+      invalidator_->GetInvalidatorClientId(),
       sync_manager_factory,
       delete_sync_data_folder,
       sync_prefs_->GetEncryptionBootstrapToken(),
@@ -493,24 +416,6 @@
                  credentials));
 }
 
-void SyncBackendHost::UpdateRegisteredInvalidationIds(
-    const syncer::ObjectIdSet& ids) {
-  DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
-  DCHECK(sync_thread_.IsRunning());
-  sync_thread_.message_loop()->PostTask(FROM_HERE,
-      base::Bind(&SyncBackendHost::Core::DoUpdateRegisteredInvalidationIds,
-                 core_.get(), ids));
-}
-
-void SyncBackendHost::AcknowledgeInvalidation(
-    const invalidation::ObjectId& id, const syncer::AckHandle& ack_handle) {
-  DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
-  DCHECK(sync_thread_.IsRunning());
-  sync_thread_.message_loop()->PostTask(FROM_HERE,
-      base::Bind(&SyncBackendHost::Core::DoAcknowledgeInvalidation,
-                 core_.get(), id, ack_handle));
-}
-
 void SyncBackendHost::StartSyncingWithServer() {
   SDVLOG(1) << "SyncBackendHost::StartSyncingWithServer called.";
 
@@ -654,14 +559,17 @@
   // StopSyncingForShutdown() (which nulls out |frontend_|) should be
   // called first.
   DCHECK(!frontend_);
+
+  if (sync_disabled)
+    invalidator_->UpdateRegisteredInvalidationIds(this, syncer::ObjectIdSet());
+  invalidator_->UnregisterInvalidationHandler(this);
+  invalidator_ = NULL;
+
   // TODO(tim): DCHECK(registrar_->StoppedOnUIThread()) would be nice.
   if (sync_thread_.IsRunning()) {
     sync_thread_.message_loop()->PostTask(FROM_HERE,
         base::Bind(&SyncBackendHost::Core::DoShutdown, core_.get(),
                    sync_disabled));
-
-    if (android_invalidator_bridge_)
-      android_invalidator_bridge_->StopForShutdown();
   }
 
   // Stop will return once the thread exits, which will be after DoShutdown
@@ -687,7 +595,6 @@
 
   registrar_.reset();
   js_backend_.Reset();
-  android_invalidator_bridge_.reset();
   core_ = NULL;  // Releases reference to core_.
 }
 
@@ -720,6 +627,8 @@
   // backend because configuration requests are never aborted; they are retried
   // until they succeed or the backend is shut down.
 
+  syncer::ModelTypeSet previous_types = registrar_->GetLastConfiguredTypes();
+
   syncer::ModelTypeSet disabled_types =
       GetDataTypesInState(DISABLED, config_state_map);
   syncer::ModelTypeSet fatal_types =
@@ -728,11 +637,14 @@
       GetDataTypesInState(CRYPTO, config_state_map);
   disabled_types.PutAll(fatal_types);
   disabled_types.PutAll(crypto_types);
+  syncer::ModelTypeSet active_types =
+      GetDataTypesInState(CONFIGURE_ACTIVE, config_state_map);
+  syncer::ModelTypeSet clean_first_types =
+      GetDataTypesInState(CONFIGURE_CLEAN, config_state_map);
   syncer::ModelTypeSet types_to_download = registrar_->ConfigureDataTypes(
-      GetDataTypesInState(CONFIGURE_ACTIVE, config_state_map),
+      syncer::Union(active_types, clean_first_types),
       disabled_types);
-  syncer::ModelTypeSet inactive_types =
-      GetDataTypesInState(CONFIGURE_INACTIVE, config_state_map);
+  types_to_download.PutAll(clean_first_types);
   types_to_download.RemoveAll(syncer::ProxyTypes());
   if (!types_to_download.Empty())
     types_to_download.Put(syncer::NIGORI);
@@ -762,6 +674,17 @@
   syncer::ModelSafeRoutingInfo routing_info;
   registrar_->GetModelSafeRoutingInfo(&routing_info);
 
+  syncer::ModelTypeSet current_types = registrar_->GetLastConfiguredTypes();
+  syncer::ModelTypeSet types_to_purge =
+      syncer::Difference(previous_types, current_types);
+  syncer::ModelTypeSet inactive_types =
+      GetDataTypesInState(CONFIGURE_INACTIVE, config_state_map);
+  types_to_purge.RemoveAll(inactive_types);
+
+  DCHECK(syncer::Intersection(current_types, fatal_types).Empty());
+  DCHECK(syncer::Intersection(current_types, crypto_types).Empty());
+  DCHECK(current_types.HasAll(types_to_download));
+
   SDVLOG(1) << "Types "
             << syncer::ModelTypeSetToString(types_to_download)
             << " added; calling DoConfigureSyncer";
@@ -779,8 +702,9 @@
   //   touched.
   RequestConfigureSyncer(reason,
                          types_to_download,
+                         types_to_purge,
                          fatal_types,
-                         crypto_types,
+                         syncer::Union(crypto_types, clean_first_types),
                          inactive_types,
                          routing_info,
                          ready_task,
@@ -862,6 +786,7 @@
 void SyncBackendHost::RequestConfigureSyncer(
     syncer::ConfigureReason reason,
     syncer::ModelTypeSet to_download,
+    syncer::ModelTypeSet to_purge,
     syncer::ModelTypeSet to_journal,
     syncer::ModelTypeSet to_unapply,
     syncer::ModelTypeSet to_ignore,
@@ -871,9 +796,9 @@
     const base::Closure& retry_callback) {
   DoConfigureSyncerTypes config_types;
   config_types.to_download = to_download;
+  config_types.to_purge = to_purge;
   config_types.to_journal = to_journal;
   config_types.to_unapply = to_unapply;
-  config_types.to_ignore = to_ignore;
   sync_thread_.message_loop()->PostTask(FROM_HERE,
        base::Bind(&SyncBackendHost::Core::DoConfigureSyncer,
                   core_.get(),
@@ -885,13 +810,18 @@
 }
 
 void SyncBackendHost::FinishConfigureDataTypesOnFrontendLoop(
+    const syncer::ModelTypeSet enabled_types,
     const syncer::ModelTypeSet succeeded_configuration_types,
     const syncer::ModelTypeSet failed_configuration_types,
     const base::Callback<void(syncer::ModelTypeSet,
                               syncer::ModelTypeSet)>& ready_task) {
   if (!frontend_)
     return;
-  DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
+
+  invalidator_->UpdateRegisteredInvalidationIds(
+      this,
+      ModelTypeSetToObjectIdSet(enabled_types));
+
   if (!ready_task.is_null())
     ready_task.Run(succeeded_configuration_types, failed_configuration_types);
 }
@@ -922,6 +852,10 @@
        syncer::CONFIGURE_REASON_NEWLY_ENABLED_DATA_TYPE :
        syncer::CONFIGURE_REASON_NEW_CLIENT);
 
+  // Fake a state change to initialize the SyncManager's cached invalidator
+  // state.
+  OnInvalidatorStateChange(invalidator_->GetInvalidatorState());
+
   // Kick off the next step in SyncBackendHost initialization by downloading
   // any necessary control types.
   sync_thread_.message_loop()->PostTask(
@@ -958,8 +892,7 @@
     const GURL& service_url,
     MakeHttpBridgeFactoryFn make_http_bridge_factory_fn,
     const syncer::SyncCredentials& credentials,
-    AndroidInvalidatorBridge* android_invalidator_bridge,
-    syncer::InvalidatorFactory* invalidator_factory,
+    const std::string& invalidator_client_id,
     syncer::SyncManagerFactory* sync_manager_factory,
     bool delete_sync_data_folder,
     const std::string& restored_key_for_bootstrapping,
@@ -978,8 +911,7 @@
       service_url(service_url),
       make_http_bridge_factory_fn(make_http_bridge_factory_fn),
       credentials(credentials),
-      android_invalidator_bridge(android_invalidator_bridge),
-      invalidator_factory(invalidator_factory),
+      invalidator_client_id(invalidator_client_id),
       sync_manager_factory(sync_manager_factory),
       delete_sync_data_folder(delete_sync_data_folder),
       restored_key_for_bootstrapping(restored_key_for_bootstrapping),
@@ -1001,8 +933,7 @@
       sync_data_folder_path_(sync_data_folder_path),
       host_(backend),
       sync_loop_(NULL),
-      registrar_(NULL),
-      registered_as_invalidation_handler_(false) {
+      registrar_(NULL) {
   DCHECK(backend.get());
 }
 
@@ -1033,10 +964,14 @@
             << syncer::ModelTypeSetToString(new_control_types)
             << " added; calling ConfigureSyncer";
 
+  syncer::ModelTypeSet types_to_purge =
+      syncer::Difference(syncer::ModelTypeSet::All(),
+                         GetRoutingInfoTypes(routing_info));
+
   sync_manager_->ConfigureSyncer(
       reason,
       new_control_types,
-      syncer::ModelTypeSet(),
+      types_to_purge,
       syncer::ModelTypeSet(),
       syncer::ModelTypeSet(),
       routing_info,
@@ -1197,24 +1132,16 @@
       sync_error);
 }
 
-void SyncBackendHost::Core::OnInvalidatorStateChange(
+void SyncBackendHost::Core::DoOnInvalidatorStateChange(
     syncer::InvalidatorState state) {
-  if (!sync_loop_)
-    return;
   DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
-  host_.Call(FROM_HERE,
-             &SyncBackendHost::HandleInvalidatorStateChangeOnFrontendLoop,
-             state);
+  sync_manager_->OnInvalidatorStateChange(state);
 }
 
-void SyncBackendHost::Core::OnIncomingInvalidation(
-    const syncer::ObjectIdInvalidationMap& invalidation_map) {
-  if (!sync_loop_)
-    return;
+void SyncBackendHost::Core::DoOnIncomingInvalidation(
+    syncer::ObjectIdInvalidationMap invalidation_map) {
   DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
-  host_.Call(FROM_HERE,
-             &SyncBackendHost::HandleIncomingInvalidationOnFrontendLoop,
-             invalidation_map);
+  sync_manager_->OnIncomingInvalidation(invalidation_map);
 }
 
 void SyncBackendHost::Core::DoInitialize(const DoInitializeOptions& options) {
@@ -1240,43 +1167,31 @@
 
   sync_manager_ = options.sync_manager_factory->CreateSyncManager(name_);
   sync_manager_->AddObserver(this);
-  sync_manager_->Init(
-      sync_data_folder_path_,
-      options.event_handler,
-      options.service_url.host() + options.service_url.path(),
-      options.service_url.EffectiveIntPort(),
-      options.service_url.SchemeIsSecure(),
-      options.make_http_bridge_factory_fn.Run().Pass(),
-      options.workers,
-      options.extensions_activity_monitor,
-      options.registrar /* as SyncManager::ChangeDelegate */,
-      options.credentials,
-#if defined(OS_ANDROID)
-      scoped_ptr<syncer::Invalidator>(
-          new AndroidInvalidatorBridgeProxy(
-              options.android_invalidator_bridge)),
-#else
-      scoped_ptr<syncer::Invalidator>(
-          options.invalidator_factory->CreateInvalidator()),
-#endif
-      options.invalidator_factory->GetInvalidatorClientId(),
-      options.restored_key_for_bootstrapping,
-      options.restored_keystore_key_for_bootstrapping,
-      scoped_ptr<InternalComponentsFactory>(
-          options.internal_components_factory),
-      &encryptor_,
-      options.unrecoverable_error_handler,
-      options.report_unrecoverable_error_function,
-      options.use_oauth2_token);
+  sync_manager_->Init(sync_data_folder_path_,
+                      options.event_handler,
+                      options.service_url.host() + options.service_url.path(),
+                      options.service_url.EffectiveIntPort(),
+                      options.service_url.SchemeIsSecure(),
+                      options.make_http_bridge_factory_fn.Run().Pass(),
+                      options.workers,
+                      options.extensions_activity_monitor,
+                      options.registrar /* as SyncManager::ChangeDelegate */,
+                      options.credentials,
+                      options.invalidator_client_id,
+                      options.restored_key_for_bootstrapping,
+                      options.restored_keystore_key_for_bootstrapping,
+                      scoped_ptr<InternalComponentsFactory>(
+                          options.internal_components_factory),
+                      &encryptor_,
+                      options.unrecoverable_error_handler,
+                      options.report_unrecoverable_error_function,
+                      options.use_oauth2_token);
 
   // |sync_manager_| may end up being NULL here in tests (in
   // synchronous initialization mode).
   //
   // TODO(akalin): Fix this behavior (see http://crbug.com/140354).
   if (sync_manager_) {
-    sync_manager_->RegisterInvalidationHandler(this);
-    registered_as_invalidation_handler_ = true;
-
     // Now check the command line to see if we need to simulate an
     // unrecoverable error for testing purpose. Note the error is thrown
     // only if the initialization succeeded. Also it makes sense to use this
@@ -1302,31 +1217,6 @@
   }
 }
 
-void SyncBackendHost::Core::DoUpdateRegisteredInvalidationIds(
-    const syncer::ObjectIdSet& ids) {
-  DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
-  // |sync_manager_| may end up being NULL here in tests (in
-  // synchronous initialization mode) since this is called during
-  // shutdown.
-  //
-  // TODO(akalin): Fix this behavior (see http://crbug.com/140354).
-  if (sync_manager_) {
-    sync_manager_->UpdateRegisteredInvalidationIds(this, ids);
-  }
-}
-
-void SyncBackendHost::Core::DoAcknowledgeInvalidation(
-    const invalidation::ObjectId& id, const syncer::AckHandle& ack_handle) {
-  DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
-  // |sync_manager_| may end up being NULL here in tests (in
-  // synchronous initialization mode).
-  //
-  // TODO(akalin): Fix this behavior (see http://crbug.com/140354).
-  if (sync_manager_) {
-    sync_manager_->AcknowledgeInvalidation(id, ack_handle);
-  }
-}
-
 void SyncBackendHost::Core::DoStartSyncing(
     const syncer::ModelSafeRoutingInfo& routing_info) {
   DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
@@ -1436,10 +1326,6 @@
   DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
   if (sync_manager_) {
     save_changes_timer_.reset();
-    if (registered_as_invalidation_handler_) {
-      sync_manager_->UnregisterInvalidationHandler(this);
-      registered_as_invalidation_handler_ = false;
-    }
     sync_manager_->RemoveObserver(this);
     sync_manager_->ShutdownOnSyncThread();
     sync_manager_.reset();
@@ -1457,9 +1343,9 @@
   sync_manager_->ConfigureSyncer(
       reason,
       config_types.to_download,
+      config_types.to_purge,
       config_types.to_journal,
       config_types.to_unapply,
-      config_types.to_ignore,
       routing_info,
       base::Bind(&SyncBackendHost::Core::DoFinishConfigureDataTypes,
                  this,
@@ -1481,7 +1367,6 @@
   registrar_->GetModelSafeRoutingInfo(&routing_info);
   syncer::ModelTypeSet enabled_types = GetRoutingInfoTypes(routing_info);
   enabled_types.RemoveAll(syncer::ProxyTypes());
-  sync_manager_->UpdateEnabledTypes(enabled_types);
 
   const syncer::ModelTypeSet failed_configuration_types =
       Difference(types_to_config, sync_manager_->InitialSyncEndedTypes());
@@ -1489,7 +1374,9 @@
       Difference(types_to_config, failed_configuration_types);
   host_.Call(FROM_HERE,
              &SyncBackendHost::FinishConfigureDataTypesOnFrontendLoop,
-             succeeded_configuration_types, failed_configuration_types,
+             enabled_types,
+             succeeded_configuration_types,
+             failed_configuration_types,
              ready_task);
 }
 
@@ -1504,7 +1391,7 @@
 void SyncBackendHost::Core::DeleteSyncDataFolder() {
   DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
   if (file_util::DirectoryExists(sync_data_folder_path_)) {
-    if (!file_util::Delete(sync_data_folder_path_, true))
+    if (!base::Delete(sync_data_folder_path_, true))
       SLOG(DFATAL) << "Could not delete the Sync Data folder.";
   }
 }
@@ -1619,20 +1506,30 @@
   frontend_->OnActionableError(sync_error);
 }
 
-void SyncBackendHost::HandleInvalidatorStateChangeOnFrontendLoop(
-    syncer::InvalidatorState state) {
-  if (!frontend_)
-    return;
-  DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
-  frontend_->OnInvalidatorStateChange(state);
+void SyncBackendHost::OnInvalidatorStateChange(syncer::InvalidatorState state) {
+  sync_thread_.message_loop()->PostTask(
+      FROM_HERE,
+      base::Bind(&SyncBackendHost::Core::DoOnInvalidatorStateChange,
+                 core_.get(),
+                 state));
 }
 
-void SyncBackendHost::HandleIncomingInvalidationOnFrontendLoop(
+void SyncBackendHost::OnIncomingInvalidation(
     const syncer::ObjectIdInvalidationMap& invalidation_map) {
-  if (!frontend_)
-    return;
-  DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
-  frontend_->OnIncomingInvalidation(invalidation_map);
+  // TODO(dcheng): Acknowledge immediately for now. Fix this once the
+  // invalidator doesn't repeatedly ping for unacknowledged invaliations, since
+  // it conflicts with the sync scheduler's internal backoff algorithm.
+  // See http://crbug.com/124149 for more information.
+  for (syncer::ObjectIdInvalidationMap::const_iterator it =
+       invalidation_map.begin(); it != invalidation_map.end(); ++it) {
+    invalidator_->AcknowledgeInvalidation(it->first, it->second.ack_handle);
+  }
+
+  sync_thread_.message_loop()->PostTask(
+      FROM_HERE,
+      base::Bind(&SyncBackendHost::Core::DoOnIncomingInvalidation,
+                 core_.get(),
+                 invalidation_map));
 }
 
 bool SyncBackendHost::CheckPassphraseAgainstCachedPendingKeys(
diff --git a/chrome/browser/sync/glue/sync_backend_host.h b/chrome/browser/sync/glue/sync_backend_host.h
index fa5a46c..7b054a8 100644
--- a/chrome/browser/sync/glue/sync_backend_host.h
+++ b/chrome/browser/sync/glue/sync_backend_host.h
@@ -14,12 +14,12 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/threading/thread.h"
+#include "chrome/browser/invalidation/invalidation_service.h"
 #include "chrome/browser/sync/glue/backend_data_type_configurer.h"
 #include "chrome/browser/sync/glue/chrome_extensions_activity_monitor.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "google_apis/gaia/google_service_auth_error.h"
-#include "googleurl/src/gurl.h"
 #include "sync/internal_api/public/base/model_type.h"
 #include "sync/internal_api/public/configure_reason.h"
 #include "sync/internal_api/public/engine/model_safe_worker.h"
@@ -30,9 +30,9 @@
 #include "sync/internal_api/public/util/unrecoverable_error_handler.h"
 #include "sync/internal_api/public/util/weak_handle.h"
 #include "sync/notifier/invalidation_handler.h"
-#include "sync/notifier/invalidator_factory.h"
 #include "sync/protocol/encryption.pb.h"
 #include "sync/protocol/sync_protocol_error.h"
+#include "url/gurl.h"
 
 class Profile;
 
@@ -44,14 +44,10 @@
 class SyncManagerFactory;
 }
 
-namespace invalidation {
-class InvalidatorStorage;
-}
-
 namespace browser_sync {
 
-class AndroidInvalidatorBridge;
 class ChangeProcessor;
+class InvalidatorStorage;
 class SyncBackendRegistrar;
 class SyncPrefs;
 class SyncedDeviceTracker;
@@ -62,7 +58,7 @@
 // activity.
 // NOTE: All methods will be invoked by a SyncBackendHost on the same thread
 // used to create that SyncBackendHost.
-class SyncFrontend : public syncer::InvalidationHandler {
+class SyncFrontend {
  public:
   SyncFrontend() {}
 
@@ -153,7 +149,8 @@
 // that the SyncFrontend is only accessed on the UI loop.
 class SyncBackendHost
     : public BackendDataTypeConfigurer,
-      public content::NotificationObserver {
+      public content::NotificationObserver,
+      public syncer::InvalidationHandler {
  public:
   typedef syncer::SyncStatus Status;
 
@@ -164,10 +161,7 @@
   SyncBackendHost(
       const std::string& name,
       Profile* profile,
-      const base::WeakPtr<SyncPrefs>& sync_prefs,
-      // TODO(tim): Temporary, remove when bug 124137 finished.
-      const base::WeakPtr<invalidation::InvalidatorStorage>&
-          invalidator_storage);
+      const base::WeakPtr<SyncPrefs>& sync_prefs);
 
   // For testing.
   // TODO(skrul): Extract an interface so this is not needed.
@@ -194,14 +188,6 @@
   // Called on |frontend_loop| to update SyncCredentials.
   virtual void UpdateCredentials(const syncer::SyncCredentials& credentials);
 
-  // Registers the underlying frontend for the given IDs to the underlying
-  // notifier.  This lasts until StopSyncingForShutdown() is called.
-  void UpdateRegisteredInvalidationIds(const syncer::ObjectIdSet& ids);
-
-  // Forwards an invalidation acknowledgement to the underlying notifier.
-  void AcknowledgeInvalidation(const invalidation::ObjectId& id,
-                               const syncer::AckHandle& ack_handle);
-
   // This starts the SyncerThread running a Syncer object to communicate with
   // sync servers.  Until this is called, no changes will leave or enter this
   // browser from the cloud / sync servers.
@@ -325,8 +311,7 @@
         const GURL& service_url,
         MakeHttpBridgeFactoryFn make_http_bridge_factory_fn,
         const syncer::SyncCredentials& credentials,
-        AndroidInvalidatorBridge* android_invalidator_bridge,
-        syncer::InvalidatorFactory* invalidator_factory,
+        const std::string& invalidator_client_id,
         syncer::SyncManagerFactory* sync_manager_factory,
         bool delete_sync_data_folder,
         const std::string& restored_key_for_bootstrapping,
@@ -348,8 +333,7 @@
     // Overridden by tests.
     MakeHttpBridgeFactoryFn make_http_bridge_factory_fn;
     syncer::SyncCredentials credentials;
-    AndroidInvalidatorBridge* const android_invalidator_bridge;
-    syncer::InvalidatorFactory* const invalidator_factory;
+    const std::string invalidator_client_id;
     syncer::SyncManagerFactory* const sync_manager_factory;
     std::string lsid;
     bool delete_sync_data_folder;
@@ -370,6 +354,7 @@
   virtual void RequestConfigureSyncer(
       syncer::ConfigureReason reason,
       syncer::ModelTypeSet to_download,
+      syncer::ModelTypeSet to_purge,
       syncer::ModelTypeSet to_journal,
       syncer::ModelTypeSet to_unapply,
       syncer::ModelTypeSet to_ignore,
@@ -380,6 +365,7 @@
 
   // Called when the syncer has finished performing a configuration.
   void FinishConfigureDataTypesOnFrontendLoop(
+      const syncer::ModelTypeSet enabled_types,
       const syncer::ModelTypeSet succeeded_configuration_types,
       const syncer::ModelTypeSet failed_configuration_types,
       const base::Callback<void(syncer::ModelTypeSet,
@@ -512,6 +498,12 @@
     const content::NotificationSource& source,
     const content::NotificationDetails& details) OVERRIDE;
 
+  // InvalidationHandler implementation.
+  virtual void OnInvalidatorStateChange(
+      syncer::InvalidatorState state) OVERRIDE;
+  virtual void OnIncomingInvalidation(
+      const syncer::ObjectIdInvalidationMap& invalidation_map) OVERRIDE;
+
   // Handles stopping the core's SyncManager, accounting for whether
   // initialization is done yet.
   void StopSyncManagerForShutdown(const base::Closure& closure);
@@ -539,10 +531,6 @@
 
   const base::WeakPtr<SyncPrefs> sync_prefs_;
 
-  scoped_ptr<AndroidInvalidatorBridge> android_invalidator_bridge_;
-
-  syncer::InvalidatorFactory invalidator_factory_;
-
   ChromeExtensionsActivityMonitor extensions_activity_monitor_;
 
   scoped_ptr<SyncBackendRegistrar> registrar_;
@@ -580,6 +568,8 @@
   syncer::WeakHandle<syncer::JsBackend> js_backend_;
   syncer::WeakHandle<syncer::DataTypeDebugInfoListener> debug_info_listener_;
 
+  invalidation::InvalidationService* invalidator_;
+
   DISALLOW_COPY_AND_ASSIGN(SyncBackendHost);
 };
 
diff --git a/chrome/browser/sync/glue/sync_backend_host_unittest.cc b/chrome/browser/sync/glue/sync_backend_host_unittest.cc
index da3cc97..9f8542b 100644
--- a/chrome/browser/sync/glue/sync_backend_host_unittest.cc
+++ b/chrome/browser/sync/glue/sync_backend_host_unittest.cc
@@ -22,7 +22,6 @@
 #include "content/public/browser/notification_service.h"
 #include "content/public/test/test_browser_thread.h"
 #include "google/cacheinvalidation/include/types.h"
-#include "googleurl/src/gurl.h"
 #include "net/url_request/test_url_fetcher_factory.h"
 #include "sync/internal_api/public/base/model_type.h"
 #include "sync/internal_api/public/engine/model_safe_worker.h"
@@ -36,6 +35,7 @@
 #include "sync/util/test_unrecoverable_error_handler.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 using content::BrowserThread;
 using syncer::FakeSyncManager;
@@ -146,13 +146,10 @@
     profile_.reset(new TestingProfile());
     profile_->CreateRequestContext();
     sync_prefs_.reset(new SyncPrefs(profile_->GetPrefs()));
-    invalidator_storage_.reset(new invalidation::InvalidatorStorage(
-        profile_->GetPrefs()));
     backend_.reset(new SyncBackendHost(
         profile_->GetDebugName(),
         profile_.get(),
-        sync_prefs_->AsWeakPtr(),
-        invalidator_storage_->AsWeakPtr()));
+        sync_prefs_->AsWeakPtr()));
     credentials_.email = "user@example.com";
     credentials_.sync_token = "sync_token";
 
@@ -178,7 +175,6 @@
     }
     backend_.reset();
     sync_prefs_.reset();
-    invalidator_storage_.reset();
     profile_.reset();
     // Pump messages posted by the sync thread (which may end up
     // posting on the IO thread).
@@ -266,7 +262,6 @@
   syncer::TestUnrecoverableErrorHandler handler_;
   scoped_ptr<TestingProfile> profile_;
   scoped_ptr<SyncPrefs> sync_prefs_;
-  scoped_ptr<invalidation::InvalidatorStorage> invalidator_storage_;
   scoped_ptr<SyncBackendHost> backend_;
   FakeSyncManager* fake_manager_;
   FakeSyncManagerFactory fake_manager_factory_;
@@ -594,76 +589,6 @@
       enabled_types_).Empty());
 }
 
-// Register for some IDs and trigger an invalidation.  This should
-// propagate all the way to the frontend.
-TEST_F(SyncBackendHostTest, Invalidate) {
-  InitializeBackend(true);
-
-  syncer::ObjectIdSet ids;
-  ids.insert(invalidation::ObjectId(1, "id1"));
-  ids.insert(invalidation::ObjectId(2, "id2"));
-  const syncer::ObjectIdInvalidationMap& invalidation_map =
-      syncer::ObjectIdSetToInvalidationMap(ids, "payload");
-
-  EXPECT_CALL(
-      mock_frontend_,
-      OnIncomingInvalidation(invalidation_map))
-      .WillOnce(InvokeWithoutArgs(QuitMessageLoop));
-
-  backend_->UpdateRegisteredInvalidationIds(ids);
-  fake_manager_->Invalidate(invalidation_map);
-  ui_loop_.PostDelayedTask(
-      FROM_HERE, ui_loop_.QuitClosure(), TestTimeouts::action_timeout());
-  ui_loop_.Run();
-}
-
-// Register for some IDs and update the invalidator state.  This
-// should propagate all the way to the frontend.
-TEST_F(SyncBackendHostTest, UpdateInvalidatorState) {
-  InitializeBackend(true);
-
-  EXPECT_CALL(mock_frontend_,
-              OnInvalidatorStateChange(syncer::INVALIDATIONS_ENABLED))
-      .WillOnce(InvokeWithoutArgs(QuitMessageLoop));
-
-  syncer::ObjectIdSet ids;
-  ids.insert(invalidation::ObjectId(3, "id3"));
-  backend_->UpdateRegisteredInvalidationIds(ids);
-  fake_manager_->UpdateInvalidatorState(syncer::INVALIDATIONS_ENABLED);
-  ui_loop_.PostDelayedTask(
-      FROM_HERE, ui_loop_.QuitClosure(), TestTimeouts::action_timeout());
-  ui_loop_.Run();
-}
-
-// Call StopSyncingForShutdown() on the backend and fire some invalidations
-// before calling Shutdown().  Then start up and shut down the backend again.
-// Those notifications shouldn't propagate to the frontend.
-TEST_F(SyncBackendHostTest, InvalidationsAfterStopSyncingForShutdown) {
-  InitializeBackend(true);
-
-  syncer::ObjectIdSet ids;
-  ids.insert(invalidation::ObjectId(5, "id5"));
-  backend_->UpdateRegisteredInvalidationIds(ids);
-
-  backend_->StopSyncingForShutdown();
-
-  // Should not trigger anything.
-  fake_manager_->UpdateInvalidatorState(syncer::TRANSIENT_INVALIDATION_ERROR);
-  fake_manager_->UpdateInvalidatorState(syncer::INVALIDATIONS_ENABLED);
-  const syncer::ObjectIdInvalidationMap& invalidation_map =
-      syncer::ObjectIdSetToInvalidationMap(ids, "payload");
-  fake_manager_->Invalidate(invalidation_map);
-
-  // Make sure the above calls take effect before we continue.
-  fake_manager_->WaitForSyncThread();
-
-  backend_->Shutdown(false);
-  backend_.reset();
-
-  TearDown();
-  SetUp();
-}
-
 // Ensure the device info tracker is initialized properly on startup.
 TEST_F(SyncBackendHostTest, InitializeDeviceInfo) {
   ASSERT_EQ(NULL, backend_->GetSyncedDeviceTracker());
@@ -691,8 +616,9 @@
   // any old types.
   InitializeBackend(true);
   EXPECT_TRUE(fake_manager_->GetAndResetDownloadedTypes().Equals(new_types));
-  EXPECT_TRUE(Intersection(fake_manager_->GetAndResetCleanedTypes(),
-                           enabled_types_).Empty());
+  EXPECT_TRUE(fake_manager_->GetAndResetCleanedTypes().Equals(
+                  Difference(syncer::ModelTypeSet::All(),
+                             enabled_types_)));
   EXPECT_TRUE(fake_manager_->InitialSyncEndedTypes().Equals(enabled_types_));
   EXPECT_TRUE(fake_manager_->GetTypesWithEmptyProgressMarkerToken(
       enabled_types_).Empty());
diff --git a/chrome/browser/sync/glue/sync_backend_registrar.cc b/chrome/browser/sync/glue/sync_backend_registrar.cc
index 5d99b0d..69898b1 100644
--- a/chrome/browser/sync/glue/sync_backend_registrar.cc
+++ b/chrome/browser/sync/glue/sync_backend_registrar.cc
@@ -85,6 +85,11 @@
   }
 }
 
+SyncBackendRegistrar::~SyncBackendRegistrar() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(stopped_on_ui_thread_);
+}
+
 void SyncBackendRegistrar::SetInitialTypes(syncer::ModelTypeSet initial_types) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   base::AutoLock lock(lock_);
@@ -112,11 +117,8 @@
         << "Password store not initialized, cannot sync passwords";
     routing_info_.erase(syncer::PASSWORDS);
   }
-}
 
-SyncBackendRegistrar::~SyncBackendRegistrar() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  DCHECK(stopped_on_ui_thread_);
+  last_configured_types_ = syncer::GetRoutingInfoTypes(routing_info_);
 }
 
 bool SyncBackendRegistrar::IsNigoriEnabled() const {
@@ -165,10 +167,15 @@
            << syncer::ModelTypeSetToString(types_to_remove)
            << " to get new routing info "
            <<syncer::ModelSafeRoutingInfoToString(routing_info_);
+  last_configured_types_ = syncer::GetRoutingInfoTypes(routing_info_);
 
   return newly_added_types;
 }
 
+syncer::ModelTypeSet SyncBackendRegistrar::GetLastConfiguredTypes() const {
+  return last_configured_types_;
+}
+
 void SyncBackendRegistrar::StopOnUIThread() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(!stopped_on_ui_thread_);
diff --git a/chrome/browser/sync/glue/sync_backend_registrar.h b/chrome/browser/sync/glue/sync_backend_registrar.h
index 31b1310..f7ea1fb 100644
--- a/chrome/browser/sync/glue/sync_backend_registrar.h
+++ b/chrome/browser/sync/glue/sync_backend_registrar.h
@@ -43,11 +43,6 @@
                        Profile* profile,
                        base::MessageLoop* sync_loop);
 
-  // Informs the SyncBackendRegistrar of the currently enabled set of types.
-  // These types will be placed in the passive group.  This function should be
-  // called exactly once during startup.
-  void SetInitialTypes(syncer::ModelTypeSet initial_types);
-
   // SyncBackendRegistrar must be destroyed as follows:
   //
   //   1) On the sync thread, call OnSyncerShutdownComplete() after
@@ -61,6 +56,11 @@
   // thread which the syncer pushes changes to).
   virtual ~SyncBackendRegistrar();
 
+  // Informs the SyncBackendRegistrar of the currently enabled set of types.
+  // These types will be placed in the passive group.  This function should be
+  // called exactly once during startup.
+  void SetInitialTypes(syncer::ModelTypeSet initial_types);
+
   // Returns whether or not we are currently syncing encryption keys.
   // Must be called on the UI thread.
   bool IsNigoriEnabled() const;
@@ -74,6 +74,11 @@
       syncer::ModelTypeSet types_to_add,
       syncer::ModelTypeSet types_to_remove);
 
+  // Returns the set of enabled types as of the last configuration. Note that
+  // this might be different from the current types in the routing info due
+  // to DeactiveDataType being called separately from ConfigureDataTypes.
+  syncer::ModelTypeSet GetLastConfiguredTypes() const;
+
   // Must be called from the UI thread. (See destructor comment.)
   void StopOnUIThread();
 
@@ -160,6 +165,10 @@
   // The change processors that handle the different data types.
   std::map<syncer::ModelType, ChangeProcessor*> processors_;
 
+  // The types that were enabled as of the last configuration. Updated on each
+  // call to ConfigureDataTypes as well as SetInitialTypes.
+  syncer::ModelTypeSet last_configured_types_;
+
   DISALLOW_COPY_AND_ASSIGN(SyncBackendRegistrar);
 };
 
diff --git a/chrome/browser/sync/glue/sync_backend_registrar_unittest.cc b/chrome/browser/sync/glue/sync_backend_registrar_unittest.cc
index 3761067..979f9a5 100644
--- a/chrome/browser/sync/glue/sync_backend_registrar_unittest.cc
+++ b/chrome/browser/sync/glue/sync_backend_registrar_unittest.cc
@@ -128,6 +128,7 @@
     ExpectRoutingInfo(&registrar, expected_routing_info);
   }
   ExpectHasProcessorsForTypes(registrar, ModelTypeSet());
+  EXPECT_TRUE(types1.Equals(registrar.GetLastConfiguredTypes()));
 
   // Add and remove.
   const ModelTypeSet types2(PREFERENCES, THEMES);
@@ -139,11 +140,13 @@
     ExpectRoutingInfo(&registrar, expected_routing_info);
   }
   ExpectHasProcessorsForTypes(registrar, ModelTypeSet());
+  EXPECT_TRUE(types2.Equals(registrar.GetLastConfiguredTypes()));
 
   // Remove.
   EXPECT_TRUE(registrar.ConfigureDataTypes(ModelTypeSet(), types2).Empty());
   ExpectRoutingInfo(&registrar, syncer::ModelSafeRoutingInfo());
   ExpectHasProcessorsForTypes(registrar, ModelTypeSet());
+  EXPECT_TRUE(ModelTypeSet().Equals(registrar.GetLastConfiguredTypes()));
 
   registrar.OnSyncerShutdownComplete();
   registrar.StopOnUIThread();
diff --git a/chrome/browser/sync/glue/synced_device_tracker.cc b/chrome/browser/sync/glue/synced_device_tracker.cc
index d502541..59fa12a 100644
--- a/chrome/browser/sync/glue/synced_device_tracker.cc
+++ b/chrome/browser/sync/glue/synced_device_tracker.cc
@@ -91,6 +91,44 @@
                      specifics.device_type()));
 }
 
+void SyncedDeviceTracker::GetAllSyncedDeviceInfo(
+    ScopedVector<DeviceInfo>* device_info) const {
+  if (device_info == NULL)
+    return;
+
+  device_info->clear();
+
+  syncer::ReadTransaction trans(FROM_HERE, user_share_);
+  syncer::ReadNode root_node(&trans);
+
+  if (root_node.InitByTagLookup(
+          syncer::ModelTypeToRootTag(syncer::DEVICE_INFO)) !=
+      syncer::BaseNode::INIT_OK) {
+    return;
+  }
+
+  // Get all the children of the root node and use the child id to read
+  // device info for devices.
+  std::vector<int64> children;
+  root_node.GetChildIds(&children);
+
+  for (std::vector<int64>::const_iterator it = children.begin();
+       it != children.end(); ++it) {
+    syncer::ReadNode node(&trans);
+    if (node.InitByIdLookup(*it) != syncer::BaseNode::INIT_OK)
+      return;
+
+    const sync_pb::DeviceInfoSpecifics& specifics =
+        node.GetDeviceInfoSpecifics();
+    device_info->push_back(
+        new DeviceInfo(specifics.client_name(),
+                       specifics.chrome_version(),
+                       specifics.sync_user_agent(),
+                       specifics.device_type()));
+
+  }
+}
+
 void SyncedDeviceTracker::InitLocalDeviceInfo(const base::Closure& callback) {
   DeviceInfo::CreateLocalDeviceInfo(
       base::Bind(&SyncedDeviceTracker::InitLocalDeviceInfoContinuation,
@@ -111,10 +149,16 @@
   specifics.set_sync_user_agent(info.sync_user_agent());
   specifics.set_device_type(info.device_type());
 
+  WriteDeviceInfo(specifics, local_device_info_tag_);
+}
+
+void SyncedDeviceTracker::WriteDeviceInfo(
+    const sync_pb::DeviceInfoSpecifics& specifics,
+    const std::string& tag) {
   syncer::WriteTransaction trans(FROM_HERE, user_share_);
   syncer::WriteNode node(&trans);
 
-  if (node.InitByClientTagLookup(syncer::DEVICE_INFO, local_device_info_tag_) ==
+  if (node.InitByClientTagLookup(syncer::DEVICE_INFO, tag) ==
       syncer::BaseNode::INIT_OK) {
     node.SetDeviceInfoSpecifics(specifics);
     node.SetTitle(UTF8ToWide(specifics.client_name()));
@@ -128,7 +172,7 @@
     syncer::WriteNode::InitUniqueByCreationResult create_result =
         new_node.InitUniqueByCreation(syncer::DEVICE_INFO,
                                       type_root,
-                                      local_device_info_tag_);
+                                      tag);
     DCHECK_EQ(syncer::WriteNode::INIT_SUCCESS, create_result);
     new_node.SetDeviceInfoSpecifics(specifics);
     new_node.SetTitle(UTF8ToWide(specifics.client_name()));
diff --git a/chrome/browser/sync/glue/synced_device_tracker.h b/chrome/browser/sync/glue/synced_device_tracker.h
index 929591f..877d833 100644
--- a/chrome/browser/sync/glue/synced_device_tracker.h
+++ b/chrome/browser/sync/glue/synced_device_tracker.h
@@ -9,6 +9,7 @@
 
 #include "base/basictypes.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/sync/glue/change_processor.h"
 
@@ -42,6 +43,8 @@
   virtual void InitLocalDeviceInfo(const base::Closure& callback);
   virtual scoped_ptr<DeviceInfo> ReadDeviceInfo(
       const std::string& client_id) const;
+  virtual void GetAllSyncedDeviceInfo(
+      ScopedVector<DeviceInfo>* device_info) const;
 
  private:
   friend class SyncedDeviceTrackerTest;
@@ -52,6 +55,11 @@
   // Helper to write specifics into our node.  Also useful for testing.
   void WriteLocalDeviceInfo(const DeviceInfo& info);
 
+  // Helper to write arbitrary device info. Useful for writing local device
+  // info and also used by test cases to write arbitrary device infos.
+  void WriteDeviceInfo(const sync_pb::DeviceInfoSpecifics& specifics,
+                       const std::string& tag);
+
   base::WeakPtrFactory<SyncedDeviceTracker> weak_factory_;
 
   syncer::UserShare* user_share_;
diff --git a/chrome/browser/sync/glue/synced_device_tracker_unittest.cc b/chrome/browser/sync/glue/synced_device_tracker_unittest.cc
index 2af2780..94e79f0 100644
--- a/chrome/browser/sync/glue/synced_device_tracker_unittest.cc
+++ b/chrome/browser/sync/glue/synced_device_tracker_unittest.cc
@@ -4,7 +4,9 @@
 
 #include <string>
 
+#include "base/guid.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
 #include "base/message_loop.h"
 #include "base/run_loop.h"
 #include "chrome/browser/sync/glue/device_info.h"
@@ -18,6 +20,21 @@
 
 namespace browser_sync {
 
+namespace {
+
+void ConvertDeviceInfoSpecifics(
+    const DeviceInfo& device_info,
+    const std::string& guid,
+    sync_pb::DeviceInfoSpecifics* specifics) {
+  specifics->set_cache_guid(guid);
+  specifics->set_client_name(device_info.client_name());
+  specifics->set_chrome_version(device_info.chrome_version());
+  specifics->set_sync_user_agent(device_info.sync_user_agent());
+  specifics->set_device_type(device_info.device_type());
+}
+
+}  // namespace
+
 class SyncedDeviceTrackerTest : public ::testing::Test {
  protected:
   SyncedDeviceTrackerTest() : transaction_count_baseline_(0) { }
@@ -52,6 +69,13 @@
     synced_device_tracker_->WriteLocalDeviceInfo(info);
   }
 
+  void WriteDeviceInfo(const DeviceInfo& device_info,
+                       const std::string& guid) {
+    sync_pb::DeviceInfoSpecifics specifics;
+    ConvertDeviceInfoSpecifics(device_info, guid, &specifics);
+    synced_device_tracker_->WriteDeviceInfo(specifics, guid);
+  }
+
   void ResetObservedChangesCounter() {
     transaction_count_baseline_ = GetTotalTransactionsCount();
   }
@@ -155,6 +179,31 @@
   EXPECT_EQ(1, GetObservedChangesCounter());
 }
 
+// Test retrieving DeviceInfos for all the syncing devices.
+TEST_F(SyncedDeviceTrackerTest, GetAllDeviceInfo) {
+  DeviceInfo device_info1(
+      "abc Device", "XYZ v1", "XYZ SyncAgent v1",
+      sync_pb::SyncEnums_DeviceType_TYPE_LINUX);
+
+  std::string guid1 = base::GenerateGUID();
+
+  DeviceInfo device_info2(
+      "def Device", "XYZ v2", "XYZ SyncAgent v2",
+      sync_pb::SyncEnums_DeviceType_TYPE_LINUX);
+
+  std::string guid2 = base::GenerateGUID();
+
+  WriteDeviceInfo(device_info1, guid1);
+  WriteDeviceInfo(device_info2, guid2);
+
+  ScopedVector<DeviceInfo> device_info;
+  synced_device_tracker_->GetAllSyncedDeviceInfo(&device_info);
+
+  EXPECT_EQ(device_info.size(), 2U);
+  EXPECT_TRUE(device_info[0]->Equals(device_info1));
+  EXPECT_TRUE(device_info[1]->Equals(device_info2));
+}
+
 }  // namespace
 
 }  // namespace browser_sync
diff --git a/chrome/browser/sync/glue/synced_session.h b/chrome/browser/sync/glue/synced_session.h
index 80ff9be..5582945 100644
--- a/chrome/browser/sync/glue/synced_session.h
+++ b/chrome/browser/sync/glue/synced_session.h
@@ -8,7 +8,7 @@
 #include <map>
 #include <string>
 
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/sessions/session_id.h"
 #include "chrome/browser/sessions/session_types.h"
 
diff --git a/chrome/browser/sync/glue/typed_url_model_associator_unittest.cc b/chrome/browser/sync/glue/typed_url_model_associator_unittest.cc
index f3d1849..39d3de2 100644
--- a/chrome/browser/sync/glue/typed_url_model_associator_unittest.cc
+++ b/chrome/browser/sync/glue/typed_url_model_associator_unittest.cc
@@ -8,14 +8,14 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/test/test_timeouts.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/history/history_types.h"
 #include "chrome/browser/sync/glue/typed_url_model_associator.h"
 #include "chrome/browser/sync/profile_sync_service_mock.h"
 #include "content/public/test/test_browser_thread.h"
-#include "googleurl/src/gurl.h"
 #include "sync/protocol/typed_url_specifics.pb.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 using browser_sync::TypedUrlModelAssociator;
 using content::BrowserThread;
diff --git a/chrome/browser/sync/glue/ui_data_type_controller.cc b/chrome/browser/sync/glue/ui_data_type_controller.cc
index 830999e..1ed6b86 100644
--- a/chrome/browser/sync/glue/ui_data_type_controller.cc
+++ b/chrome/browser/sync/glue/ui_data_type_controller.cc
@@ -55,7 +55,9 @@
   DCHECK(!model_load_callback.is_null());
   DCHECK(syncer::IsRealDataType(type_));
   if (state_ != NOT_RUNNING) {
-    model_load_callback.Run(type(), syncer::SyncError(FROM_HERE,
+    model_load_callback.Run(type(),
+                            syncer::SyncError(FROM_HERE,
+                                              syncer::SyncError::DATATYPE_ERROR,
                                               "Model already loaded",
                                               type()));
     return;
@@ -131,7 +133,10 @@
       type(),
       weak_ptr_factory.GetWeakPtr());
   if (!local_service_.get()) {
-    syncer::SyncError error(FROM_HERE, "Failed to connect to syncer.", type());
+    syncer::SyncError error(FROM_HERE,
+                            syncer::SyncError::DATATYPE_ERROR,
+                            "Failed to connect to syncer.",
+                            type());
     local_merge_result.set_error(error);
     StartDone(ASSOCIATION_FAILED,
               local_merge_result,
@@ -149,7 +154,10 @@
   bool sync_has_nodes = false;
   if (!shared_change_processor_->SyncModelHasUserCreatedNodes(
           &sync_has_nodes)) {
-    syncer::SyncError error(FROM_HERE, "Failed to load sync nodes", type());
+    syncer::SyncError error(FROM_HERE,
+                            syncer::SyncError::UNRECOVERABLE_ERROR,
+                            "Failed to load sync nodes",
+                            type());
     local_merge_result.set_error(error);
     StartDone(UNRECOVERABLE_ERROR,
               local_merge_result,
@@ -207,7 +215,9 @@
 
   ModelLoadCallback model_load_callback = model_load_callback_;
   model_load_callback_.Reset();
-  model_load_callback.Run(type(), syncer::SyncError(FROM_HERE,
+  model_load_callback.Run(type(),
+                          syncer::SyncError(FROM_HERE,
+                                            syncer::SyncError::DATATYPE_ERROR,
                                             "Aborted",
                                             type()));
 }
diff --git a/chrome/browser/sync/glue/ui_data_type_controller_unittest.cc b/chrome/browser/sync/glue/ui_data_type_controller_unittest.cc
index ce64106..5edb108 100644
--- a/chrome/browser/sync/glue/ui_data_type_controller_unittest.cc
+++ b/chrome/browser/sync/glue/ui_data_type_controller_unittest.cc
@@ -166,7 +166,10 @@
   EXPECT_CALL(start_callback_,
               Run(DataTypeController::ASSOCIATION_FAILED, _, _));
   syncable_service_.set_merge_data_and_start_syncing_error(
-      syncer::SyncError(FROM_HERE, "Error", type_));
+      syncer::SyncError(FROM_HERE,
+                        syncer::SyncError::DATATYPE_ERROR,
+                        "Error",
+                        type_));
 
   EXPECT_EQ(DataTypeController::NOT_RUNNING, preference_dtc_->state());
   EXPECT_FALSE(syncable_service_.syncing());
diff --git a/chrome/browser/sync/profile_sync_components_factory_impl.cc b/chrome/browser/sync/profile_sync_components_factory_impl.cc
index 5c997c3..8a4cbec 100644
--- a/chrome/browser/sync/profile_sync_components_factory_impl.cc
+++ b/chrome/browser/sync/profile_sync_components_factory_impl.cc
@@ -4,13 +4,16 @@
 
 #include "base/command_line.h"
 #include "build/build_config.h"
+#include "chrome/browser/about_flags.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
+#include "chrome/browser/browser_process.h"
 #include "chrome/browser/extensions/api/storage/settings_frontend.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_system.h"
 #include "chrome/browser/extensions/extension_system_factory.h"
 #include "chrome/browser/history/history_service.h"
 #include "chrome/browser/history/history_service_factory.h"
+#include "chrome/browser/pref_service_flags_storage.h"
 #include "chrome/browser/prefs/pref_model_associator.h"
 #include "chrome/browser/prefs/pref_service_syncable.h"
 #include "chrome/browser/profiles/profile.h"
@@ -55,7 +58,7 @@
 #include "chrome/browser/webdata/autofill_profile_syncable_service.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
-#include "components/autofill/browser/webdata/autofill_webdata_service.h"
+#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
 #include "content/public/browser/browser_thread.h"
 #include "sync/api/syncable_service.h"
 
@@ -103,20 +106,6 @@
 using browser_sync::UIDataTypeController;
 using content::BrowserThread;
 
-namespace {
-// Based on command line switches, make the call to use SyncedNotifications or
-// not.
-// TODO(petewil): Remove this when the SyncedNotifications feature is ready
-// to be turned on by default, and just use a disable switch instead then.
-bool UseSyncedNotifications(CommandLine* command_line) {
-  if (command_line->HasSwitch(switches::kDisableSyncSyncedNotifications))
-    return false;
-  if (command_line->HasSwitch(switches::kEnableSyncSyncedNotifications))
-    return true;
-  return false;
-}
-}  // namespace
-
 ProfileSyncComponentsFactoryImpl::ProfileSyncComponentsFactoryImpl(
     Profile* profile, CommandLine* command_line)
     : profile_(profile),
@@ -185,7 +174,19 @@
         new SessionDataTypeController(this, profile_, pss));
   }
 
+  // Migrate sync flags that should be prefs.
+  // TODO(pastarmovj): Remove this code once enough time has passed to not need
+  // to migrate anymore.
+  about_flags::PrefServiceFlagsStorage flags_storage(
+      g_browser_process->local_state());
   if (command_line_->HasSwitch(switches::kEnableSyncFavicons)) {
+    profile_->GetPrefs()->SetBoolean(prefs::kSyncFaviconsEnabled, true);
+    about_flags::SetExperimentEnabled(&flags_storage,
+                                      syncer::kFaviconSyncFlag,
+                                      false);
+  }
+
+  if (profile_->GetPrefs()->GetBoolean(prefs::kSyncFaviconsEnabled)) {
     pss->RegisterDataTypeController(
         new UIDataTypeController(syncer::FAVICON_IMAGES,
                                  this,
@@ -268,13 +269,16 @@
             syncer::APP_SETTINGS, this, profile_, pss));
   }
 
+#if !defined(OS_ANDROID)
   // Synced Notifications sync datatype is disabled by default.
   // TODO(petewil): Switch to enabled by default once datatype support is done.
-  if (UseSyncedNotifications(command_line_)) {
+  if (notifier::ChromeNotifierServiceFactory::UseSyncedNotifications(
+          command_line_)) {
     pss->RegisterDataTypeController(
         new UIDataTypeController(
             syncer::SYNCED_NOTIFICATIONS, this, profile_, pss));
   }
+#endif
 
 #if defined(OS_LINUX) || defined(OS_WIN) || defined(OS_CHROMEOS)
   // Dictionary sync is enabled by default.
diff --git a/chrome/browser/sync/profile_sync_components_factory_impl.h b/chrome/browser/sync/profile_sync_components_factory_impl.h
index 03295c2..2de940b 100644
--- a/chrome/browser/sync/profile_sync_components_factory_impl.h
+++ b/chrome/browser/sync/profile_sync_components_factory_impl.h
@@ -10,7 +10,7 @@
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "chrome/browser/sync/profile_sync_components_factory.h"
-#include "components/autofill/browser/webdata/autofill_webdata_service.h"
+#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
 
 
 class CommandLine;
diff --git a/chrome/browser/sync/profile_sync_service.cc b/chrome/browser/sync/profile_sync_service.cc
index bbc69cf..26f26d1 100644
--- a/chrome/browser/sync/profile_sync_service.cc
+++ b/chrome/browser/sync/profile_sync_service.cc
@@ -22,11 +22,9 @@
 #include "base/strings/stringprintf.h"
 #include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"
-#include "chrome/browser/about_flags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/defaults.h"
 #include "chrome/browser/net/chrome_cookie_notification_details.h"
-#include "chrome/browser/pref_service_flags_storage.h"
 #include "chrome/browser/prefs/pref_service_syncable.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/about_signin_internals.h"
@@ -68,6 +66,7 @@
 #include "google_apis/gaia/gaia_constants.h"
 #include "grit/generated_resources.h"
 #include "net/cookies/cookie_monster.h"
+#include "net/url_request/url_request_context_getter.h"
 #include "sync/api/sync_error.h"
 #include "sync/internal_api/public/configure_reason.h"
 #include "sync/internal_api/public/sync_encryption_handler.h"
@@ -75,8 +74,6 @@
 #include "sync/internal_api/public/util/sync_string_conversions.h"
 #include "sync/js/js_arg_list.h"
 #include "sync/js/js_event_details.h"
-#include "sync/notifier/invalidator_registrar.h"
-#include "sync/notifier/invalidator_state.h"
 #include "sync/util/cryptographer.h"
 #include "ui/base/l10n/l10n_util.h"
 
@@ -116,10 +113,11 @@
 
 static const char* kOAuth2Scopes[] = {
   GaiaConstants::kChromeSyncOAuth2Scope,
-  // GoogleTalk scope is needed for notifications.
-  GaiaConstants::kGoogleTalkOAuth2Scope
 };
 
+static const char* kManagedOAuth2Scopes[] = {
+  GaiaConstants::kChromeSyncManagedOAuth2Scope
+};
 
 static const char* kSyncUnrecoverableErrorHistogram =
     "Sync.UnrecoverableErrors";
@@ -169,7 +167,6 @@
       profile_(profile),
       // |profile| may be NULL in unit tests.
       sync_prefs_(profile_ ? profile_->GetPrefs() : NULL),
-      invalidator_storage_(profile_ ? profile_->GetPrefs(): NULL),
       sync_service_url_(kDevServerUrl),
       data_type_requested_sync_startup_(false),
       is_first_time_sync_configure_(false),
@@ -186,7 +183,6 @@
       auto_start_enabled_(start_behavior == AUTO_START),
       configure_status_(DataTypeManager::UNKNOWN),
       setup_in_progress_(false),
-      invalidator_state_(syncer::DEFAULT_INVALIDATION_ERROR),
       request_access_token_backoff_(&kRequestAccessTokenBackoffPolicy) {
   // By default, dev, canary, and unbranded Chromium users will go to the
   // development servers. Development servers have more features than standard
@@ -239,9 +235,6 @@
 }
 
 void ProfileSyncService::Initialize() {
-  DCHECK(!invalidator_registrar_.get());
-  invalidator_registrar_.reset(new syncer::InvalidatorRegistrar());
-
   InitSettings();
 
   // We clear this here (vs Shutdown) because we want to remember that an error
@@ -506,8 +499,7 @@
 void ProfileSyncService::CreateBackend() {
   backend_.reset(
       new SyncBackendHost(profile_->GetDebugName(),
-                          profile_, sync_prefs_.AsWeakPtr(),
-                          invalidator_storage_.AsWeakPtr()));
+                          profile_, sync_prefs_.AsWeakPtr()));
 }
 
 bool ProfileSyncService::IsEncryptedDatatypeEnabled() const {
@@ -633,60 +625,6 @@
   // we'll want to start from a fresh SyncDB, so delete any old one that might
   // be there.
   InitializeBackend(!HasSyncSetupCompleted());
-
-  // |backend_| may end up being NULL here in tests (in synchronous
-  // initialization mode).
-  //
-  // TODO(akalin): Fix this horribly non-intuitive behavior (see
-  // http://crbug.com/140354).
-  if (backend_) {
-    backend_->UpdateRegisteredInvalidationIds(
-        invalidator_registrar_->GetAllRegisteredIds());
-    for (AckHandleReplayQueue::const_iterator it = ack_replay_queue_.begin();
-         it != ack_replay_queue_.end(); ++it) {
-      backend_->AcknowledgeInvalidation(it->first, it->second);
-    }
-    ack_replay_queue_.clear();
-  }
-}
-
-void ProfileSyncService::RegisterInvalidationHandler(
-    syncer::InvalidationHandler* handler) {
-  invalidator_registrar_->RegisterHandler(handler);
-}
-
-void ProfileSyncService::UpdateRegisteredInvalidationIds(
-    syncer::InvalidationHandler* handler,
-    const syncer::ObjectIdSet& ids) {
-  invalidator_registrar_->UpdateRegisteredIds(handler, ids);
-
-  // If |backend_| is NULL, its registered IDs will be updated when
-  // it's created and initialized.
-  if (backend_) {
-    backend_->UpdateRegisteredInvalidationIds(
-        invalidator_registrar_->GetAllRegisteredIds());
-  }
-}
-
-void ProfileSyncService::UnregisterInvalidationHandler(
-    syncer::InvalidationHandler* handler) {
-  invalidator_registrar_->UnregisterHandler(handler);
-}
-
-void ProfileSyncService::AcknowledgeInvalidation(
-    const invalidation::ObjectId& id,
-    const syncer::AckHandle& ack_handle) {
-  if (backend_) {
-    backend_->AcknowledgeInvalidation(id, ack_handle);
-  } else {
-    // If |backend_| is NULL, save the acknowledgements to replay when
-    // it's created and initialized.
-    ack_replay_queue_.push_back(std::make_pair(id, ack_handle));
-  }
-}
-
-syncer::InvalidatorState ProfileSyncService::GetInvalidatorState() const {
-  return invalidator_registrar_->GetInvalidatorState();
 }
 
 void ProfileSyncService::OnGetTokenSuccess(
@@ -750,23 +688,7 @@
   }
 }
 
-void ProfileSyncService::EmitInvalidationForTest(
-    const invalidation::ObjectId& id,
-    const std::string& payload) {
-  syncer::ObjectIdSet notify_ids;
-  notify_ids.insert(id);
-
-  const syncer::ObjectIdInvalidationMap& invalidation_map =
-      ObjectIdSetToInvalidationMap(notify_ids, payload);
-  OnIncomingInvalidation(invalidation_map);
-}
-
 void ProfileSyncService::Shutdown() {
-  DCHECK(invalidator_registrar_.get());
-  // Reset |invalidator_registrar_| first so that ShutdownImpl cannot
-  // use it.
-  invalidator_registrar_.reset();
-
   if (signin_)
     signin_->signin_global_error()->RemoveProvider(this);
 
@@ -821,9 +743,6 @@
   expect_sync_configuration_aborted_ = false;
   is_auth_in_progress_ = false;
   backend_initialized_ = false;
-  // NULL if we're called from Shutdown().
-  if (invalidator_registrar_)
-    UpdateInvalidatorRegistrarState();
   cached_passphrase_.clear();
   encryption_pending_ = false;
   encrypt_everything_ = false;
@@ -848,7 +767,6 @@
   // Clear prefs (including SyncSetupHasCompleted) before shutting down so
   // PSS clients don't think we're set up while we're shutting down.
   sync_prefs_.ClearPreferences();
-  invalidator_storage_.Clear();
   ClearUnrecoverableError();
   ShutdownImpl(true);
 }
@@ -870,6 +788,11 @@
   FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
   // TODO(akalin): Make an Observer subclass that listens and does the
   // event routing.
+  sync_js_controller_.HandleJsEvent("onServiceStateChanged", JsEventDetails());
+}
+
+void ProfileSyncService::NotifySyncCycleCompleted() {
+  FOR_EACH_OBSERVER(Observer, observers_, OnSyncCycleCompleted());
   sync_js_controller_.HandleJsEvent(
       "onServiceStateChanged", JsEventDetails());
 }
@@ -887,14 +810,6 @@
   unrecoverable_error_location_ = tracked_objects::Location();
 }
 
-// static
-// TODO(sync): Consider having syncer::Experiments provide this.
-std::string ProfileSyncService::GetExperimentNameForDataType(
-    syncer::ModelType data_type) {
-  NOTREACHED();
-  return std::string();
-}
-
 void ProfileSyncService::RegisterNewDataType(syncer::ModelType data_type) {
   if (data_type_controllers_.count(data_type) > 0)
     return;
@@ -945,33 +860,23 @@
   // passed onto the change processor.
   DeactivateDataType(type);
 
-  syncer::SyncError error(from_here, message, type);
+  syncer::SyncError error(from_here,
+                          syncer::SyncError::DATATYPE_ERROR,
+                          message,
+                          type);
 
   std::map<syncer::ModelType, syncer::SyncError> errors;
   errors[type] = error;
 
   // Update this before posting a task. So if a configure happens before
   // the task that we are going to post, this type would still be disabled.
-  failed_data_types_handler_.UpdateFailedDataTypes(
-      errors,
-      FailedDataTypesHandler::RUNTIME);
+  failed_data_types_handler_.UpdateFailedDataTypes(errors);
 
   base::MessageLoop::current()->PostTask(FROM_HERE,
       base::Bind(&ProfileSyncService::ReconfigureDatatypeManager,
                  weak_factory_.GetWeakPtr()));
 }
 
-void ProfileSyncService::OnInvalidatorStateChange(
-    syncer::InvalidatorState state) {
-  invalidator_state_ = state;
-  UpdateInvalidatorRegistrarState();
-}
-
-void ProfileSyncService::OnIncomingInvalidation(
-    const syncer::ObjectIdInvalidationMap& invalidation_map) {
-  invalidator_registrar_->DispatchInvalidationsToHandlers(invalidation_map);
-}
-
 void ProfileSyncService::OnBackendInitialized(
     const syncer::WeakHandle<syncer::JsBackend>& js_backend,
     const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>&
@@ -1015,7 +920,6 @@
   }
 
   backend_initialized_ = true;
-  UpdateInvalidatorRegistrarState();
 
   sync_js_controller_.AttachJsBackend(js_backend);
   debug_info_listener_ = debug_info_listener;
@@ -1064,7 +968,7 @@
                    GetSessionModelAssociator()->AsWeakPtr()));
   }
   DVLOG(2) << "Notifying observers sync cycle completed";
-  NotifyObservers();
+  NotifySyncCycleCompleted();
 }
 
 void ProfileSyncService::OnExperimentsChanged(
@@ -1091,24 +995,11 @@
            << syncer::ModelTypeSetToString(to_add);
   DVLOG(2) << "Enabling types: " << syncer::ModelTypeSetToString(to_register);
 
-  about_flags::PrefServiceFlagsStorage flags_storage_(
-      g_browser_process->local_state());
-
   for (syncer::ModelTypeSet::Iterator it = to_register.First();
        it.Good(); it.Inc()) {
     // Received notice to enable experimental type. Check if the type is
     // registered, and if not register a new datatype controller.
     RegisterNewDataType(it.Get());
-    // Enable the about:flags switch for the experimental type so we don't have
-    // to always perform this reconfiguration. Once we set this, the type will
-    // remain registered on restart, so we will no longer go down this code
-    // path.
-    std::string experiment_name = GetExperimentNameForDataType(it.Get());
-    if (experiment_name.empty())
-      continue;
-    about_flags::SetExperimentEnabled(&flags_storage_,
-                                      experiment_name,
-                                      true);
   }
 
   // Check if the user has "Keep Everything Synced" enabled. If so, we want
@@ -1130,18 +1021,8 @@
     }
   }
 
-  // Now enable any non-datatype features.
-  if (experiments.keystore_encryption) {
-    about_flags::SetExperimentEnabled(&flags_storage_,
-                                      syncer::kKeystoreEncryptionFlag,
-                                      true);
-  }
-
-  if (experiments.favicon_sync) {
-    about_flags::SetExperimentEnabled(&flags_storage_,
-                                      syncer::kFaviconSyncFlag,
-                                      true);
-  }
+  if (experiments.favicon_sync)
+    profile_->GetPrefs()->SetBoolean(prefs::kSyncFaviconsEnabled, true);
 
   current_experiments_ = experiments;
 }
@@ -1183,10 +1064,10 @@
 void ProfileSyncService::OnConnectionStatusChange(
     syncer::ConnectionStatus status) {
   if (use_oauth2_token_ && status == syncer::CONNECTION_AUTH_ERROR) {
-    // Sync or Tango server returned error indicating that access token is
-    // invalid. It could be either expired or access is revoked. Let's request
-    // another access token and if access is revoked then request for token will
-    // fail with corresponding error.
+    // Sync server returned error indicating that access token is invalid. It
+    // could be either expired or access is revoked. Let's request another
+    // access token and if access is revoked then request for token will fail
+    // with corresponding error.
     RequestAccessToken();
   } else {
     const GoogleServiceAuthError auth_error =
@@ -1321,8 +1202,12 @@
       break;
     case syncer::DISABLE_SYNC_ON_CLIENT:
       OnStopSyncingPermanently();
-      // TODO(rsimha): Re-evaluate whether to also sign out the user here after
-      // a dashboard clear. See http://crbug.com/240436.
+#if !defined(OS_CHROMEOS)
+      // On desktop Chrome, sign out the user after a dashboard clear.
+      // TODO(rsimha): Revisit this for M30. See http://crbug.com/252049.
+      if (!auto_start_enabled_)  // Skip sign out on ChromeOS/Android.
+        SigninManagerFactory::GetForProfile(profile_)->SignOut();
+#endif
       break;
     case syncer::STOP_SYNC_FOR_DISABLED_ACCOUNT:
       // Sync disabled by domain admin. we should stop syncing until next
@@ -1393,7 +1278,7 @@
     std::string message =
         "Sync configuration failed with status " +
         DataTypeManager::ConfigureStatusToString(configure_status_) +
-        " during " + syncer::ModelTypeToString(error.type()) +
+        " during " + syncer::ModelTypeToString(error.model_type()) +
         ": " + error.message();
     LOG(ERROR) << "ProfileSyncService error: " << message;
     OnInternalUnrecoverableError(error.location(),
@@ -1923,8 +1808,18 @@
     return;
   request_access_token_retry_timer_.Stop();
   OAuth2TokenService::ScopeSet oauth2_scopes;
-  for (size_t i = 0; i < arraysize(kOAuth2Scopes); i++)
-    oauth2_scopes.insert(kOAuth2Scopes[i]);
+  bool is_managed = false;
+#if defined(ENABLE_MANAGED_USERS)
+  is_managed = ManagedUserService::ProfileIsManaged(profile_);
+#endif
+  if (is_managed) {
+    for (size_t i = 0; i < arraysize(kManagedOAuth2Scopes); i++)
+      oauth2_scopes.insert(kManagedOAuth2Scopes[i]);
+  } else {
+    for (size_t i = 0; i < arraysize(kOAuth2Scopes); i++)
+      oauth2_scopes.insert(kOAuth2Scopes[i]);
+  }
+
   OAuth2TokenService* token_service =
       ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
   // Invalidate previous token, otherwise token service will return the same
@@ -2201,17 +2096,6 @@
   OnUnrecoverableErrorImpl(from_here, message, delete_sync_database);
 }
 
-void ProfileSyncService::UpdateInvalidatorRegistrarState() {
-  const syncer::InvalidatorState effective_state =
-      backend_initialized_ ?
-      invalidator_state_ : syncer::TRANSIENT_INVALIDATION_ERROR;
-  DVLOG(1) << "New invalidator state: "
-           << syncer::InvalidatorStateToString(invalidator_state_)
-           << ", effective state: "
-           << syncer::InvalidatorStateToString(effective_state);
-  invalidator_registrar_->UpdateInvalidatorState(effective_state);
-}
-
 std::string ProfileSyncService::GetEffectiveUsername() {
 #if defined(ENABLE_MANAGED_USERS)
   if (ManagedUserService::ProfileIsManaged(profile_)) {
diff --git a/chrome/browser/sync/profile_sync_service.h b/chrome/browser/sync/profile_sync_service.h
index 6dd6797..18dc129 100644
--- a/chrome/browser/sync/profile_sync_service.h
+++ b/chrome/browser/sync/profile_sync_service.h
@@ -17,10 +17,8 @@
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "base/strings/string16.h"
-#include "base/time.h"
-#include "base/timer.h"
-#include "chrome/browser/invalidation/invalidation_frontend.h"
-#include "chrome/browser/invalidation/invalidator_storage.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/signin/oauth2_token_service.h"
 #include "chrome/browser/signin/signin_global_error.h"
 #include "chrome/browser/sync/backend_unrecoverable_error_handler.h"
@@ -38,7 +36,6 @@
 #include "content/public/browser/notification_registrar.h"
 #include "content/public/browser/notification_types.h"
 #include "google_apis/gaia/google_service_auth_error.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/backoff_entry.h"
 #include "sync/internal_api/public/base/model_type.h"
 #include "sync/internal_api/public/engine/model_safe_worker.h"
@@ -46,6 +43,7 @@
 #include "sync/internal_api/public/util/experiments.h"
 #include "sync/internal_api/public/util/unrecoverable_error_handler.h"
 #include "sync/js/sync_js_controller.h"
+#include "url/gurl.h"
 
 class Profile;
 class ProfileSyncComponentsFactory;
@@ -65,7 +63,6 @@
 
 namespace syncer {
 class BaseTransaction;
-class InvalidatorRegistrar;
 struct SyncCredentials;
 struct UserShare;
 }
@@ -165,7 +162,6 @@
                            public syncer::UnrecoverableErrorHandler,
                            public content::NotificationObserver,
                            public BrowserContextKeyedService,
-                           public invalidation::InvalidationFrontend,
                            public browser_sync::DataTypeEncryptionHandler,
                            public OAuth2TokenService::Consumer {
  public:
@@ -288,12 +284,6 @@
   // Disables sync for user. Use ShowLoginDialog to enable.
   virtual void DisableForUser();
 
-  // syncer::InvalidationHandler implementation (via SyncFrontend).
-  virtual void OnInvalidatorStateChange(
-      syncer::InvalidatorState state) OVERRIDE;
-  virtual void OnIncomingInvalidation(
-      const syncer::ObjectIdInvalidationMap& invalidation_map) OVERRIDE;
-
   // SyncFrontend implementation.
   virtual void OnBackendInitialized(
       const syncer::WeakHandle<syncer::JsBackend>& js_backend,
@@ -600,21 +590,6 @@
   // The set of currently enabled sync experiments.
   const syncer::Experiments& current_experiments() const;
 
-  // InvalidationFrontend implementation.  It is an error to have
-  // registered handlers when Shutdown() is called.
-  virtual void RegisterInvalidationHandler(
-      syncer::InvalidationHandler* handler) OVERRIDE;
-  virtual void UpdateRegisteredInvalidationIds(
-      syncer::InvalidationHandler* handler,
-      const syncer::ObjectIdSet& ids) OVERRIDE;
-  virtual void UnregisterInvalidationHandler(
-      syncer::InvalidationHandler* handler) OVERRIDE;
-  virtual void AcknowledgeInvalidation(
-      const invalidation::ObjectId& id,
-      const syncer::AckHandle& ack_handle) OVERRIDE;
-
-  virtual syncer::InvalidatorState GetInvalidatorState() const OVERRIDE;
-
   // OAuth2TokenService::Consumer implementation
   virtual void OnGetTokenSuccess(
       const OAuth2TokenService::Request* request,
@@ -628,11 +603,6 @@
   // once (before this object is destroyed).
   virtual void Shutdown() OVERRIDE;
 
-  // Simulate an incoming notification for the given id and payload.
-  void EmitInvalidationForTest(
-      const invalidation::ObjectId& id,
-      const std::string& payload);
-
   // Called when a datatype (SyncableService) has a need for sync to start
   // ASAP, presumably because a local change event has occurred but we're
   // still in deferred start mode, meaning the SyncableService hasn't been
@@ -703,8 +673,6 @@
     ERROR_REASON_ACTIONABLE_ERROR,
     ERROR_REASON_LIMIT
   };
-  typedef std::vector<std::pair<invalidation::ObjectId,
-                                syncer::AckHandle> > AckHandleReplayQueue;
   friend class ProfileSyncServicePasswordTest;
   friend class SyncTest;
   friend class TestProfileSyncService;
@@ -751,6 +719,7 @@
   void UpdateLastSyncedTime();
 
   void NotifyObservers();
+  void NotifySyncCycleCompleted();
 
   void ClearStaleErrors();
 
@@ -800,11 +769,6 @@
                                     bool delete_sync_database,
                                     UnrecoverableErrorReason reason);
 
-  // Must be called every time |backend_initialized_| or
-  // |invalidator_state_| is changed (but only if
-  // |invalidator_registrar_| is not NULL).
-  void UpdateInvalidatorRegistrarState();
-
   // Returns the username (in form of an email address) that should be used in
   // the credentials.
   std::string GetEffectiveUsername();
@@ -819,9 +783,6 @@
   // preferences.
   browser_sync::SyncPrefs sync_prefs_;
 
-  // TODO(tim): Move this to InvalidationService, once it exists. Bug 124137.
-  invalidation::InvalidatorStorage invalidator_storage_;
-
   // TODO(ncarter): Put this in a profile, once there is UI for it.
   // This specifies where to find the sync server.
   GURL sync_service_url_;
@@ -942,18 +903,6 @@
   // Factory the backend will use to build the SyncManager.
   syncer::SyncManagerFactory sync_manager_factory_;
 
-  // Holds the current invalidator state as updated by
-  // OnInvalidatorStateChange().  Note that this is different from the
-  // state known by |invalidator_registrar_| (See
-  // UpdateInvalidatorState()).
-  syncer::InvalidatorState invalidator_state_;
-
-  // Dispatches invalidations to handlers.  Set in Initialize() and
-  // unset in Shutdown().
-  scoped_ptr<syncer::InvalidatorRegistrar> invalidator_registrar_;
-  // Queues any acknowledgements received while the backend is uninitialized.
-  AckHandleReplayQueue ack_replay_queue_;
-
   // Sync's internal debug info listener. Used to record datatype configuration
   // and association information.
   syncer::WeakHandle<syncer::DataTypeDebugInfoListener> debug_info_listener_;
diff --git a/chrome/browser/sync/profile_sync_service_android.cc b/chrome/browser/sync/profile_sync_service_android.cc
index b6edff6..7886477 100644
--- a/chrome/browser/sync/profile_sync_service_android.cc
+++ b/chrome/browser/sync/profile_sync_service_android.cc
@@ -13,7 +13,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/prefs/pref_service.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/signin/oauth2_token_service.h"
@@ -60,7 +60,6 @@
 ProfileSyncServiceAndroid::ProfileSyncServiceAndroid(JNIEnv* env, jobject obj)
     : profile_(NULL),
       sync_service_(NULL),
-      sync_prefs_(NULL),
       weak_java_profile_sync_service_(env, obj) {
   if (g_browser_process == NULL ||
       g_browser_process->profile_manager() == NULL) {
diff --git a/chrome/browser/sync/profile_sync_service_android.h b/chrome/browser/sync/profile_sync_service_android.h
index d16a530..b8027b4 100644
--- a/chrome/browser/sync/profile_sync_service_android.h
+++ b/chrome/browser/sync/profile_sync_service_android.h
@@ -11,7 +11,7 @@
 #include "base/android/jni_helper.h"
 #include "base/callback.h"
 #include "base/compiler_specific.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/sync/profile_sync_service_observer.h"
 #include "chrome/browser/sync/sync_prefs.h"
 #include "google_apis/gaia/google_service_auth_error.h"
diff --git a/chrome/browser/sync/profile_sync_service_autofill_unittest.cc b/chrome/browser/sync/profile_sync_service_autofill_unittest.cc
index 8fa2fea..9868af7 100644
--- a/chrome/browser/sync/profile_sync_service_autofill_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_autofill_unittest.cc
@@ -19,7 +19,7 @@
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/waitable_event.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/autofill/personal_data_manager_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
@@ -38,12 +38,12 @@
 #include "chrome/browser/webdata/autocomplete_syncable_service.h"
 #include "chrome/browser/webdata/autofill_profile_syncable_service.h"
 #include "chrome/browser/webdata/web_data_service_factory.h"
-#include "components/autofill/browser/autofill_common_test.h"
-#include "components/autofill/browser/personal_data_manager.h"
-#include "components/autofill/browser/webdata/autofill_change.h"
-#include "components/autofill/browser/webdata/autofill_entry.h"
-#include "components/autofill/browser/webdata/autofill_table.h"
-#include "components/autofill/browser/webdata/autofill_webdata_service.h"
+#include "components/autofill/core/browser/autofill_common_test.h"
+#include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/autofill/core/browser/webdata/autofill_change.h"
+#include "components/autofill/core/browser/webdata/autofill_entry.h"
+#include "components/autofill/core/browser/webdata/autofill_table.h"
+#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
 #include "components/webdata/common/web_data_service_test_util.h"
 #include "components/webdata/common/web_database.h"
 #include "content/public/test/test_browser_thread.h"
@@ -565,7 +565,7 @@
     AbstractAutofillFactory* factory = GetFactory(type);
     SigninManagerBase* signin =
         SigninManagerFactory::GetForProfile(profile_.get());
-    signin->SetAuthenticatedUsername("test_user");
+    signin->SetAuthenticatedUsername("test_user@gmail.com");
     sync_service_ = static_cast<TestProfileSyncService*>(
         ProfileSyncServiceFactory::GetInstance()->SetTestingFactoryAndUse(
             profile_.get(), &TestProfileSyncService::BuildAutoStartAsyncInit));
diff --git a/chrome/browser/sync/profile_sync_service_bookmark_unittest.cc b/chrome/browser/sync/profile_sync_service_bookmark_unittest.cc
index d620f91..7991284 100644
--- a/chrome/browser/sync/profile_sync_service_bookmark_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_bookmark_unittest.cc
@@ -21,7 +21,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/bookmarks/base_bookmark_model_observer.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
@@ -427,10 +427,8 @@
     return true;
   }
 
-  void StartSync() {
-    test_user_share_.Reload();
-
-    ASSERT_TRUE(CreatePermanentBookmarkNodes());
+  bool AssociateModels() {
+    DCHECK(!model_associator_);
 
     // Set up model associator.
     model_associator_.reset(new BookmarkModelAssociator(
@@ -448,7 +446,10 @@
     syncer::SyncError error = model_associator_->AssociateModels(
         &local_merge_result_,
         &syncer_merge_result_);
-    EXPECT_FALSE(error.IsSet());
+    if (error.IsSet())
+      return false;
+
+    base::MessageLoop::current()->RunUntilIdle();
 
     // Verify the merge results were calculated properly.
     EXPECT_EQ(local_count_before,
@@ -467,8 +468,14 @@
               local_merge_result_.num_items_after_association());
     EXPECT_EQ(GetSyncBookmarkCount(),
               syncer_merge_result_.num_items_after_association());
+    return true;
+  }
 
-    base::MessageLoop::current()->RunUntilIdle();
+  void StartSync() {
+    test_user_share_.Reload();
+
+    ASSERT_TRUE(CreatePermanentBookmarkNodes());
+    ASSERT_TRUE(AssociateModels());
 
     // Set up change processor.
     change_processor_.reset(
@@ -1744,7 +1751,15 @@
   TearDown();
   SetUp();
 
-  StartSync();
+  // First attempt fails due to a persistence error.
+  EXPECT_TRUE(CreatePermanentBookmarkNodes());
+  EXPECT_FALSE(AssociateModels());
+
+  // Second attempt succeeds due to the previous error resetting the native
+  // transaction version.
+  model_associator_.reset();
+  EXPECT_TRUE(CreatePermanentBookmarkNodes());
+  EXPECT_TRUE(AssociateModels());
 
   // Make sure we're back in sync.  In real life, the user would need
   // to reauthenticate before this happens, but in the test, authentication
@@ -1918,6 +1933,43 @@
   ExpectTransactionVersionMatch(model_->mobile_node(), initial_versions);
 }
 
+// Test that sync persistence errors are detected and trigger a failed
+// association.
+TEST_F(ProfileSyncServiceBookmarkTestWithData, PersistenceError) {
+  LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE);
+  StartSync();
+  WriteTestDataToBookmarkModel();
+  base::MessageLoop::current()->RunUntilIdle();
+
+  BookmarkNodeVersionMap initial_versions;
+
+  // Verify transaction versions in sync model and bookmark model (saved as
+  // transaction version of root node) are equal after
+  // WriteTestDataToBookmarkModel() created bookmarks.
+  {
+    syncer::ReadTransaction trans(FROM_HERE, test_user_share_.user_share());
+    EXPECT_GT(trans.GetModelVersion(syncer::BOOKMARKS), 0);
+    GetTransactionVersions(model_->root_node(), &initial_versions);
+    EXPECT_EQ(trans.GetModelVersion(syncer::BOOKMARKS),
+              initial_versions[model_->root_node()->id()]);
+  }
+  ExpectTransactionVersionMatch(model_->bookmark_bar_node(),
+                                BookmarkNodeVersionMap());
+  ExpectTransactionVersionMatch(model_->other_node(),
+                                BookmarkNodeVersionMap());
+  ExpectTransactionVersionMatch(model_->mobile_node(),
+                                BookmarkNodeVersionMap());
+
+  // Now shut down sync and artificially increment the native model's version.
+  StopSync();
+  int64 root_version = initial_versions[model_->root_node()->id()];
+  model_->SetNodeMetaInfo(model_->root_node(), kBookmarkTransactionVersionKey,
+                          base::Int64ToString(root_version+1));
+
+  // Upon association, bookmarks should fail to associate.
+  EXPECT_FALSE(AssociateModels());
+}
+
 }  // namespace
 
 }  // namespace browser_sync
diff --git a/chrome/browser/sync/profile_sync_service_factory.cc b/chrome/browser/sync/profile_sync_service_factory.cc
index f43c988..d41da39 100644
--- a/chrome/browser/sync/profile_sync_service_factory.cc
+++ b/chrome/browser/sync/profile_sync_service_factory.cc
@@ -12,6 +12,7 @@
 #include "chrome/browser/defaults.h"
 #include "chrome/browser/extensions/extension_system_factory.h"
 #include "chrome/browser/history/history_service_factory.h"
+#include "chrome/browser/invalidation/invalidation_service_factory.h"
 #include "chrome/browser/password_manager/password_store_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
@@ -64,6 +65,7 @@
   DependsOn(HistoryServiceFactory::GetInstance());
   DependsOn(BookmarkModelFactory::GetInstance());
   DependsOn(AboutSigninInternalsFactory::GetInstance());
+  DependsOn(invalidation::InvalidationServiceFactory::GetInstance());
 
   // The following have not been converted to BrowserContextKeyedServices yet,
   // and for now they are explicitly destroyed after the
diff --git a/chrome/browser/sync/profile_sync_service_harness.cc b/chrome/browser/sync/profile_sync_service_harness.cc
index ee77cb7..47b7434 100644
--- a/chrome/browser/sync/profile_sync_service_harness.cc
+++ b/chrome/browser/sync/profile_sync_service_harness.cc
@@ -21,6 +21,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/message_loop.h"
 #include "base/prefs/pref_service.h"
+#include "chrome/browser/invalidation/p2p_invalidation_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/signin_manager_base.h"
 #include "chrome/browser/signin/token_service.h"
@@ -38,6 +39,7 @@
 #include "sync/internal_api/public/util/sync_string_conversions.h"
 
 using syncer::sessions::SyncSessionSnapshot;
+using invalidation::P2PInvalidationService;
 
 // TODO(rsimha): Remove the following lines once crbug.com/91863 is fixed.
 // The amount of time for which we wait for a live sync operation to complete.
@@ -106,14 +108,36 @@
   return !did_timeout_;
 }
 
+// static
+ProfileSyncServiceHarness* ProfileSyncServiceHarness::Create(
+    Profile* profile,
+    const std::string& username,
+    const std::string& password) {
+  return new ProfileSyncServiceHarness(profile, username, password, NULL);
+}
+
+// static
+ProfileSyncServiceHarness* ProfileSyncServiceHarness::CreateForIntegrationTest(
+    Profile* profile,
+    const std::string& username,
+    const std::string& password,
+    P2PInvalidationService* p2p_invalidation_service) {
+  return new ProfileSyncServiceHarness(profile,
+                                       username,
+                                       password,
+                                       p2p_invalidation_service);
+}
+
 ProfileSyncServiceHarness::ProfileSyncServiceHarness(
     Profile* profile,
     const std::string& username,
-    const std::string& password)
+    const std::string& password,
+    P2PInvalidationService* p2p_invalidation_service)
     : waiting_for_encryption_type_(syncer::UNSPECIFIED),
       wait_state_(INITIAL_WAIT_STATE),
       profile_(profile),
       service_(NULL),
+      p2p_invalidation_service_(p2p_invalidation_service),
       progress_marker_partner_(NULL),
       username_(username),
       password_(password),
@@ -133,17 +157,6 @@
     service_->RemoveObserver(this);
 }
 
-// static
-ProfileSyncServiceHarness* ProfileSyncServiceHarness::CreateAndAttach(
-    Profile* profile) {
-  ProfileSyncServiceFactory* f = ProfileSyncServiceFactory::GetInstance();
-  if (!f->HasProfileSyncService(profile)) {
-    NOTREACHED() << "Profile has never signed into sync.";
-    return NULL;
-  }
-  return new ProfileSyncServiceHarness(profile, std::string(), std::string());
-}
-
 void ProfileSyncServiceHarness::SetCredentials(const std::string& username,
                                                const std::string& password) {
   username_ = username;
@@ -482,6 +495,21 @@
   RunStateChangeMachine();
 }
 
+void ProfileSyncServiceHarness::OnSyncCycleCompleted() {
+  // Integration tests still use p2p notifications.
+  const SyncSessionSnapshot& snap = GetLastSessionSnapshot();
+  bool is_notifiable_commit =
+      (snap.model_neutral_state().num_successful_commits > 0);
+  if (is_notifiable_commit && p2p_invalidation_service_) {
+    const syncer::ObjectIdInvalidationMap& invalidation_map =
+        ModelTypeInvalidationMapToObjectIdInvalidationMap(
+            snap.source().types);
+    p2p_invalidation_service_->SendInvalidation(invalidation_map);
+  }
+
+  OnStateChanged();
+}
+
 void ProfileSyncServiceHarness::OnMigrationStateChange() {
   // Update migration state.
   if (HasPendingBackendMigration()) {
diff --git a/chrome/browser/sync/profile_sync_service_harness.h b/chrome/browser/sync/profile_sync_service_harness.h
index 42594ba..a43e8a6 100644
--- a/chrome/browser/sync/profile_sync_service_harness.h
+++ b/chrome/browser/sync/profile_sync_service_harness.h
@@ -18,6 +18,10 @@
 
 class Profile;
 
+namespace invalidation {
+class P2PInvalidationService;
+}
+
 namespace browser_sync {
 namespace sessions {
 class SyncSessionSnapshot;
@@ -33,17 +37,19 @@
     : public ProfileSyncServiceObserver,
       public browser_sync::MigrationObserver {
  public:
-  ProfileSyncServiceHarness(Profile* profile,
-                            const std::string& username,
-                            const std::string& password);
+  static ProfileSyncServiceHarness* Create(
+      Profile* profile,
+      const std::string& username,
+      const std::string& password);
+
+  static ProfileSyncServiceHarness* CreateForIntegrationTest(
+      Profile* profile,
+      const std::string& username,
+      const std::string& password,
+      invalidation::P2PInvalidationService* invalidation_service);
 
   virtual ~ProfileSyncServiceHarness();
 
-  // Creates a ProfileSyncServiceHarness object and attaches it to |profile|, a
-  // profile that is assumed to have been signed into sync in the past. Caller
-  // takes ownership.
-  static ProfileSyncServiceHarness* CreateAndAttach(Profile* profile);
-
   // Sets the GAIA credentials with which to sign in to sync.
   void SetCredentials(const std::string& username, const std::string& password);
 
@@ -62,6 +68,7 @@
 
   // ProfileSyncServiceObserver implementation.
   virtual void OnStateChanged() OVERRIDE;
+  virtual void OnSyncCycleCompleted() OVERRIDE;
 
   // MigrationObserver implementation.
   virtual void OnMigrationStateChange() OVERRIDE;
@@ -270,6 +277,12 @@
     NUMBER_OF_STATES,
   };
 
+  ProfileSyncServiceHarness(
+      Profile* profile,
+      const std::string& username,
+      const std::string& password,
+      invalidation::P2PInvalidationService* invalidation_service);
+
   // Listen to migration events if the migrator has been initialized
   // and we're not already listening.  Returns true if we started
   // listening.
@@ -334,6 +347,9 @@
   // ProfileSyncService object associated with |profile_|.
   ProfileSyncService* service_;
 
+  // P2PInvalidationService associated with |profile_|.
+  invalidation::P2PInvalidationService* p2p_invalidation_service_;
+
   // The harness of the client whose update progress marker we're expecting
   // eventually match.
   ProfileSyncServiceHarness* progress_marker_partner_;
diff --git a/chrome/browser/sync/profile_sync_service_observer.cc b/chrome/browser/sync/profile_sync_service_observer.cc
new file mode 100644
index 0000000..9a8bde7
--- /dev/null
+++ b/chrome/browser/sync/profile_sync_service_observer.cc
@@ -0,0 +1,9 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/sync/profile_sync_service_observer.h"
+
+void ProfileSyncServiceObserver::OnSyncCycleCompleted() {
+  OnStateChanged();
+}
diff --git a/chrome/browser/sync/profile_sync_service_observer.h b/chrome/browser/sync/profile_sync_service_observer.h
index de8c997..9916c5d 100644
--- a/chrome/browser/sync/profile_sync_service_observer.h
+++ b/chrome/browser/sync/profile_sync_service_observer.h
@@ -16,6 +16,11 @@
   // - The sync servers are unavailable at this time.
   // - Credentials are now in flight for authentication.
   virtual void OnStateChanged() = 0;
+
+  // If a client wishes to handle sync cycle completed events in a special way,
+  // they can use this function.  By default, it re-routes to OnStateChanged().
+  virtual void OnSyncCycleCompleted();
+
  protected:
   virtual ~ProfileSyncServiceObserver() { }
 };
diff --git a/chrome/browser/sync/profile_sync_service_password_unittest.cc b/chrome/browser/sync/profile_sync_service_password_unittest.cc
index b8fd5d7..22686b4 100644
--- a/chrome/browser/sync/profile_sync_service_password_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_password_unittest.cc
@@ -12,7 +12,8 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/test/test_timeouts.h"
-#include "base/time.h"
+#include "base/time/time.h"
+#include "chrome/browser/invalidation/invalidation_service_factory.h"
 #include "chrome/browser/password_manager/mock_password_store.h"
 #include "chrome/browser/password_manager/password_store.h"
 #include "chrome/browser/password_manager/password_store_factory.h"
@@ -153,18 +154,22 @@
 
   virtual void SetUp() {
     AbstractProfileSyncServiceTest::SetUp();
-    profile_.CreateRequestContext();
+    profile_.reset(new ProfileMock);
+    profile_->CreateRequestContext();
+    invalidation::InvalidationServiceFactory::GetInstance()->
+        SetBuildOnlyFakeInvalidatorsForTest(true);
     password_store_ = static_cast<MockPasswordStore*>(
         PasswordStoreFactory::GetInstance()->SetTestingFactoryAndUse(
-            &profile_, MockPasswordStore::Build).get());
+            profile_.get(), MockPasswordStore::Build).get());
   }
 
   virtual void TearDown() {
     if (password_store_.get())
       password_store_->ShutdownOnUIThread();
       ProfileSyncServiceFactory::GetInstance()->SetTestingFactory(
-          &profile_, NULL);
-      profile_.ResetRequestContext();
+          profile_.get(), NULL);
+      profile_->ResetRequestContext();
+      profile_.reset();
       AbstractProfileSyncServiceTest::TearDown();
   }
 
@@ -184,18 +189,18 @@
                         const base::Closure& node_callback) {
     if (!sync_service_) {
       SigninManagerBase* signin =
-          SigninManagerFactory::GetForProfile(&profile_);
-      signin->SetAuthenticatedUsername("test_user");
+          SigninManagerFactory::GetForProfile(profile_.get());
+      signin->SetAuthenticatedUsername("test_user@gmail.com");
       token_service_ = static_cast<TokenService*>(
           TokenServiceFactory::GetInstance()->SetTestingFactoryAndUse(
-              &profile_, BuildTokenService));
+              profile_.get(), BuildTokenService));
       ProfileOAuth2TokenServiceFactory::GetInstance()->SetTestingFactory(
-          &profile_, FakeOAuth2TokenService::BuildTokenService);
+          profile_.get(), FakeOAuth2TokenService::BuildTokenService);
 
       PasswordTestProfileSyncService* sync =
           static_cast<PasswordTestProfileSyncService*>(
               ProfileSyncServiceFactory::GetInstance()->
-                  SetTestingFactoryAndUse(&profile_,
+                  SetTestingFactoryAndUse(profile_.get(),
                       &PasswordTestProfileSyncService::Build));
       sync->set_backend_init_callback(root_callback);
       sync->set_passphrase_accept_callback(node_callback);
@@ -207,7 +212,7 @@
       sync_service_->ChangePreferredDataTypes(preferred_types);
       PasswordDataTypeController* data_type_controller =
           new PasswordDataTypeController(sync_service_->factory(),
-                                         &profile_,
+                                         profile_.get(),
                                          sync_service_);
       ProfileSyncComponentsFactoryMock* components =
           sync_service_->components_factory_mock();
@@ -311,7 +316,7 @@
   }
 
   content::MockNotificationObserver observer_;
-  ProfileMock profile_;
+  scoped_ptr<ProfileMock> profile_;
   scoped_refptr<MockPasswordStore> password_store_;
   content::NotificationRegistrar registrar_;
 };
@@ -353,7 +358,7 @@
 TEST_F(ProfileSyncServicePasswordTest, MAYBE_FailPasswordStoreLoad) {
   password_store_ = static_cast<NullPasswordStore*>(
       PasswordStoreFactory::GetInstance()->SetTestingFactoryAndUse(
-          &profile_, NullPasswordStore::Build).get());
+          profile_.get(), NullPasswordStore::Build).get());
   StartSyncService(base::Closure(), base::Closure());
   EXPECT_FALSE(sync_service_->HasUnrecoverableError());
   syncer::ModelTypeSet failed_types =
diff --git a/chrome/browser/sync/profile_sync_service_preference_unittest.cc b/chrome/browser/sync/profile_sync_service_preference_unittest.cc
index 66bc938..076a7fb 100644
--- a/chrome/browser/sync/profile_sync_service_preference_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_preference_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/location.h"
 #include "base/stl_util.h"
 #include "base/strings/string_piece.h"
+#include "chrome/browser/invalidation/invalidation_service_factory.h"
 #include "chrome/browser/prefs/pref_model_associator.h"
 #include "chrome/browser/prefs/scoped_user_pref_update.h"
 #include "chrome/browser/signin/signin_manager.h"
@@ -124,6 +125,8 @@
     AbstractProfileSyncServiceTest::SetUp();
     profile_.reset(new TestingProfile());
     profile_->CreateRequestContext();
+    invalidation::InvalidationServiceFactory::GetInstance()->
+        SetBuildOnlyFakeInvalidatorsForTest(true);
     prefs_ = profile_->GetTestingPrefService();
 
     prefs_->registry()->RegisterStringPref(
diff --git a/chrome/browser/sync/profile_sync_service_session_unittest.cc b/chrome/browser/sync/profile_sync_service_session_unittest.cc
index beb23f5..c42edc2 100644
--- a/chrome/browser/sync/profile_sync_service_session_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_session_unittest.cc
@@ -15,7 +15,8 @@
 #include "base/message_loop.h"
 #include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
+#include "chrome/browser/invalidation/invalidation_service_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/signin/token_service_factory.h"
@@ -41,7 +42,6 @@
 #include "content/public/browser/notification_service.h"
 #include "content/public/test/test_browser_thread.h"
 #include "google_apis/gaia/gaia_constants.h"
-#include "googleurl/src/gurl.h"
 #include "sync/internal_api/public/base/model_type.h"
 #include "sync/internal_api/public/change_record.h"
 #include "sync/internal_api/public/read_node.h"
@@ -54,6 +54,7 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/ui_base_types.h"
+#include "url/gurl.h"
 
 using browser_sync::SessionChangeProcessor;
 using browser_sync::SessionDataTypeController;
@@ -205,6 +206,8 @@
     // Don't want the profile to create a real ProfileSyncService.
     ProfileSyncServiceFactory::GetInstance()->SetTestingFactory(profile,
                                                                 NULL);
+    invalidation::InvalidationServiceFactory::GetInstance()->
+        SetBuildOnlyFakeInvalidatorsForTest(true);
     return profile;
   }
 
diff --git a/chrome/browser/sync/profile_sync_service_startup_unittest.cc b/chrome/browser/sync/profile_sync_service_startup_unittest.cc
index 2bb87ab..dc58aa8 100644
--- a/chrome/browser/sync/profile_sync_service_startup_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_startup_unittest.cc
@@ -168,7 +168,7 @@
     SigninManagerBase* signin =
         SigninManagerFactory::GetForProfile(profile);
     profile->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
-                                   "test_user");
+                                   "test_user@gmail.com");
     signin->Initialize(profile, NULL);
     EXPECT_FALSE(signin->GetAuthenticatedUsername().empty());
     return new TestProfileSyncService(
@@ -216,9 +216,9 @@
 
   // Simulate successful signin as test_user.
   profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
-                                  "test_user");
-  sync_->signin()->SetAuthenticatedUsername("test_user");
-  GoogleServiceSigninSuccessDetails details("test_user", "");
+                                  "test_user@gmail.com");
+  sync_->signin()->SetAuthenticatedUsername("test_user@gmail.com");
+  GoogleServiceSigninSuccessDetails details("test_user@gmail.com", "");
   content::NotificationService::current()->Notify(
       chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL,
       content::Source<Profile>(profile_.get()),
@@ -263,9 +263,9 @@
 
   // Simulate successful signin as test_user.
   profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
-                                  "test_user");
-  sync_->signin()->SetAuthenticatedUsername("test_user");
-  GoogleServiceSigninSuccessDetails details("test_user", "");
+                                  "test_user@gmail.com");
+  sync_->signin()->SetAuthenticatedUsername("test_user@gmail.com");
+  GoogleServiceSigninSuccessDetails details("test_user@gmail.com", "");
   content::NotificationService::current()->Notify(
       chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL,
       content::Source<Profile>(profile_.get()),
@@ -284,7 +284,7 @@
 // TODO(pavely): Reenable test once android is switched to oauth2.
 TEST_F(ProfileSyncServiceStartupTest, DISABLED_StartInvalidCredentials) {
   profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
-                                  "test_user");
+                                  "test_user@gmail.com");
   SigninManagerFactory::GetForProfile(
       profile_.get())->Initialize(profile_.get(), NULL);
   CreateSyncService();
@@ -313,7 +313,8 @@
   sync_->SetSetupInProgress(true);
 
   // Simulate successful signin.
-  GoogleServiceSigninSuccessDetails details("test_user", std::string());
+  GoogleServiceSigninSuccessDetails details("test_user@gmail.com",
+                                            std::string());
   content::NotificationService::current()->Notify(
         chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL,
         content::Source<Profile>(profile_.get()),
@@ -367,7 +368,8 @@
 
 TEST_F(ProfileSyncServiceStartupTest, StartNormal) {
   // Pre load the tokens
-  profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername, "test_user");
+  profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
+                                  "test_user@gmail.com");
   SigninManagerFactory::GetForProfile(profile_.get())->Initialize(
       profile_.get(), NULL);
   CreateSyncService();
@@ -400,7 +402,8 @@
   }
 
   // Pre load the tokens
-  profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername, "test_user");
+  profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
+                                  "test_user@gmail.com");
   SigninManagerFactory::GetForProfile(profile_.get())->Initialize(
       profile_.get(), NULL);
   CreateSyncService();
@@ -429,7 +432,8 @@
   profile_->GetPrefs()->SetBoolean(prefs::kSyncKeepEverythingSynced, false);
 
   // Pre load the tokens
-  profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername, "test_user");
+  profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
+                                  "test_user@gmail.com");
   SigninManagerFactory::GetForProfile(profile_.get())->Initialize(
       profile_.get(), NULL);
   CreateSyncService();
@@ -451,7 +455,8 @@
 
 TEST_F(ProfileSyncServiceStartupTest, ManagedStartup) {
   // Service should not be started by Initialize() since it's managed.
-  profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername, "test_user");
+  profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
+                                  "test_user@gmail.com");
   SigninManagerFactory::GetForProfile(profile_.get())->Initialize(
       profile_.get(), NULL);
   CreateSyncService();
@@ -468,7 +473,8 @@
 }
 
 TEST_F(ProfileSyncServiceStartupTest, SwitchManaged) {
-  profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername, "test_user");
+  profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
+                                  "test_user@gmail.com");
   SigninManagerFactory::GetForProfile(profile_.get())->Initialize(
       profile_.get(), NULL);
   CreateSyncService();
@@ -499,14 +505,18 @@
 }
 
 TEST_F(ProfileSyncServiceStartupTest, StartFailure) {
-  profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername, "test_user");
+  profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
+                                  "test_user@gmail.com");
   SigninManagerFactory::GetForProfile(profile_.get())->Initialize(
       profile_.get(), NULL);
   CreateSyncService();
   DataTypeManagerMock* data_type_manager = SetUpDataTypeManager();
   DataTypeManager::ConfigureStatus status = DataTypeManager::ABORTED;
   syncer::SyncError error(
-      FROM_HERE, "Association failed.", syncer::BOOKMARKS);
+      FROM_HERE,
+      syncer::SyncError::DATATYPE_ERROR,
+      "Association failed.",
+      syncer::BOOKMARKS);
   std::map<syncer::ModelType, syncer::SyncError> errors;
   errors[syncer::BOOKMARKS] = error;
   DataTypeManager::ConfigureResult result(
@@ -532,7 +542,8 @@
 
 TEST_F(ProfileSyncServiceStartupTest, StartDownloadFailed) {
   // Pre load the tokens
-  profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername, "test_user");
+  profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
+                                  "test_user@gmail.com");
   SigninManagerFactory::GetForProfile(profile_.get())->Initialize(
       profile_.get(), NULL);
   CreateSyncService();
diff --git a/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc b/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc
index 47808bc..aedffb0 100644
--- a/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc
@@ -14,13 +14,14 @@
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/history/history_backend.h"
 #include "chrome/browser/history/history_db_task.h"
 #include "chrome/browser/history/history_notifications.h"
 #include "chrome/browser/history/history_service.h"
 #include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/history/history_types.h"
+#include "chrome/browser/invalidation/invalidation_service_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/signin/token_service_factory.h"
@@ -42,13 +43,13 @@
 #include "components/browser_context_keyed_service/refcounted_browser_context_keyed_service.h"
 #include "content/public/browser/notification_service.h"
 #include "google_apis/gaia/gaia_constants.h"
-#include "googleurl/src/gurl.h"
 #include "sync/internal_api/public/read_node.h"
 #include "sync/internal_api/public/read_transaction.h"
 #include "sync/internal_api/public/write_node.h"
 #include "sync/internal_api/public/write_transaction.h"
 #include "sync/protocol/typed_url_specifics.pb.h"
 #include "testing/gmock/include/gmock/gmock.h"
+#include "url/gurl.h"
 
 using base::Time;
 using base::Thread;
@@ -173,11 +174,14 @@
 
   virtual void SetUp() {
     AbstractProfileSyncServiceTest::SetUp();
-    profile_.CreateRequestContext();
+    profile_.reset(new ProfileMock);
+    profile_->CreateRequestContext();
+    invalidation::InvalidationServiceFactory::GetInstance()->
+        SetBuildOnlyFakeInvalidatorsForTest(true);
     history_backend_ = new HistoryBackendMock();
     history_service_ = static_cast<HistoryServiceMock*>(
         HistoryServiceFactory::GetInstance()->SetTestingFactoryAndUse(
-            &profile_, BuildHistoryService));
+            profile_.get(), BuildHistoryService));
     EXPECT_CALL((*history_service_), ScheduleDBTask(_, _))
         .WillRepeatedly(RunTaskOnDBThread(&history_thread_,
                                           history_backend_.get()));
@@ -188,9 +192,10 @@
     history_backend_ = NULL;
     history_service_ = NULL;
     ProfileSyncServiceFactory::GetInstance()->SetTestingFactory(
-        &profile_, NULL);
+        profile_.get(), NULL);
     history_thread_.Stop();
-    profile_.ResetRequestContext();
+    profile_->ResetRequestContext();
+    profile_.reset();
     AbstractProfileSyncServiceTest::TearDown();
   }
 
@@ -198,26 +203,27 @@
     TypedUrlModelAssociator* model_associator = NULL;
     if (!sync_service_) {
       SigninManagerBase* signin =
-          SigninManagerFactory::GetForProfile(&profile_);
+          SigninManagerFactory::GetForProfile(profile_.get());
       signin->SetAuthenticatedUsername("test");
       token_service_ = static_cast<TokenService*>(
           TokenServiceFactory::GetInstance()->SetTestingFactoryAndUse(
-              &profile_, BuildTokenService));
+              profile_.get(), BuildTokenService));
       ProfileOAuth2TokenServiceFactory::GetInstance()->SetTestingFactory(
-          &profile_, FakeOAuth2TokenService::BuildTokenService);
+          profile_.get(), FakeOAuth2TokenService::BuildTokenService);
       sync_service_ = static_cast<TestProfileSyncService*>(
           ProfileSyncServiceFactory::GetInstance()->SetTestingFactoryAndUse(
-              &profile_, &TestProfileSyncService::BuildAutoStartAsyncInit));
+              profile_.get(),
+              &TestProfileSyncService::BuildAutoStartAsyncInit));
       sync_service_->set_backend_init_callback(callback);
       ProfileSyncComponentsFactoryMock* components =
           sync_service_->components_factory_mock();
       TypedUrlDataTypeController* data_type_controller =
           new TypedUrlDataTypeController(components,
-                                         &profile_,
+                                         profile_.get(),
                                          sync_service_);
 
       EXPECT_CALL(*components, CreateTypedUrlSyncComponents(_, _, _)).
-          WillOnce(MakeTypedUrlSyncComponents(&profile_,
+          WillOnce(MakeTypedUrlSyncComponents(profile_.get(),
                                               sync_service_,
                                               history_backend_.get(),
                                               data_type_controller,
@@ -310,7 +316,7 @@
 
   Thread history_thread_;
 
-  ProfileMock profile_;
+  scoped_ptr<ProfileMock> profile_;
   scoped_refptr<HistoryBackendMock> history_backend_;
   HistoryServiceMock* history_service_;
   browser_sync::DataTypeErrorHandlerMock error_handler_;
@@ -560,7 +566,7 @@
   details.changed_urls.push_back(added_entry);
   scoped_refptr<ThreadNotifier> notifier(new ThreadNotifier(&history_thread_));
   notifier->Notify(chrome::NOTIFICATION_HISTORY_URLS_MODIFIED,
-                   content::Source<Profile>(&profile_),
+                   content::Source<Profile>(profile_.get()),
                    content::Details<history::URLsModifiedDetails>(&details));
 
   history::URLRows new_sync_entries;
@@ -590,7 +596,7 @@
   details.changed_urls.push_back(added_entry);
   scoped_refptr<ThreadNotifier> notifier(new ThreadNotifier(&history_thread_));
   notifier->Notify(chrome::NOTIFICATION_HISTORY_URLS_MODIFIED,
-                   content::Source<Profile>(&profile_),
+                   content::Source<Profile>(profile_.get()),
                    content::Details<history::URLsModifiedDetails>(&details));
 
   std::vector<history::URLRow> new_sync_entries;
@@ -627,7 +633,7 @@
   details.changed_urls.push_back(updated_entry);
   scoped_refptr<ThreadNotifier> notifier(new ThreadNotifier(&history_thread_));
   notifier->Notify(chrome::NOTIFICATION_HISTORY_URLS_MODIFIED,
-                   content::Source<Profile>(&profile_),
+                   content::Source<Profile>(profile_.get()),
                    content::Details<history::URLsModifiedDetails>(&details));
 
   history::URLRows new_sync_entries;
@@ -655,7 +661,7 @@
   details.transition = content::PAGE_TRANSITION_TYPED;
   scoped_refptr<ThreadNotifier> notifier(new ThreadNotifier(&history_thread_));
   notifier->Notify(chrome::NOTIFICATION_HISTORY_URL_VISITED,
-                   content::Source<Profile>(&profile_),
+                   content::Source<Profile>(profile_.get()),
                    content::Details<history::URLVisitedDetails>(&details));
 
   history::URLRows new_sync_entries;
@@ -693,7 +699,7 @@
   details.transition = content::PAGE_TRANSITION_TYPED;
   scoped_refptr<ThreadNotifier> notifier(new ThreadNotifier(&history_thread_));
   notifier->Notify(chrome::NOTIFICATION_HISTORY_URL_VISITED,
-                   content::Source<Profile>(&profile_),
+                   content::Source<Profile>(profile_.get()),
                    content::Details<history::URLVisitedDetails>(&details));
 
   history::URLRows new_sync_entries;
@@ -733,7 +739,7 @@
   details.transition = content::PAGE_TRANSITION_RELOAD;
   scoped_refptr<ThreadNotifier> notifier(new ThreadNotifier(&history_thread_));
   notifier->Notify(chrome::NOTIFICATION_HISTORY_URL_VISITED,
-                   content::Source<Profile>(&profile_),
+                   content::Source<Profile>(profile_.get()),
                    content::Details<history::URLVisitedDetails>(&details));
 
   GetTypedUrlsFromSyncDB(&new_sync_entries);
@@ -750,7 +756,7 @@
   details.row = twelve_visits;
   details.transition = content::PAGE_TRANSITION_TYPED;
   notifier->Notify(chrome::NOTIFICATION_HISTORY_URL_VISITED,
-                   content::Source<Profile>(&profile_),
+                   content::Source<Profile>(profile_.get()),
                    content::Details<history::URLVisitedDetails>(&details));
   GetTypedUrlsFromSyncDB(&new_sync_entries);
   // Should be no changes to the sync DB from this notification.
@@ -765,7 +771,7 @@
   details.row = twenty_visits;
   details.transition = content::PAGE_TRANSITION_TYPED;
   notifier->Notify(chrome::NOTIFICATION_HISTORY_URL_VISITED,
-                   content::Source<Profile>(&profile_),
+                   content::Source<Profile>(profile_.get()),
                    content::Details<history::URLVisitedDetails>(&details));
   GetTypedUrlsFromSyncDB(&new_sync_entries);
   ASSERT_EQ(1U, new_sync_entries.size());
@@ -799,7 +805,7 @@
   changes.rows.push_back(history::URLRow(GURL("http://mine.com")));
   scoped_refptr<ThreadNotifier> notifier(new ThreadNotifier(&history_thread_));
   notifier->Notify(chrome::NOTIFICATION_HISTORY_URLS_DELETED,
-                   content::Source<Profile>(&profile_),
+                   content::Source<Profile>(profile_.get()),
                    content::Details<history::URLsDeletedDetails>(&changes));
 
   history::URLRows new_sync_entries;
@@ -837,7 +843,7 @@
   changes.rows.push_back(history::URLRow(GURL("http://mine.com")));
   scoped_refptr<ThreadNotifier> notifier(new ThreadNotifier(&history_thread_));
   notifier->Notify(chrome::NOTIFICATION_HISTORY_URLS_DELETED,
-                   content::Source<Profile>(&profile_),
+                   content::Source<Profile>(profile_.get()),
                    content::Details<history::URLsDeletedDetails>(&changes));
 
   history::URLRows new_sync_entries;
@@ -876,7 +882,7 @@
   changes.all_history = true;
   scoped_refptr<ThreadNotifier> notifier(new ThreadNotifier(&history_thread_));
   notifier->Notify(chrome::NOTIFICATION_HISTORY_URLS_DELETED,
-                   content::Source<Profile>(&profile_),
+                   content::Source<Profile>(profile_.get()),
                    content::Details<history::URLsDeletedDetails>(&changes));
 
   GetTypedUrlsFromSyncDB(&new_sync_entries);
@@ -937,9 +943,11 @@
   sync_entries.push_back(sync_entry);
 
   EXPECT_CALL(error_handler_, CreateAndUploadError(_, _, _)).
-              WillOnce(Return(syncer::SyncError(FROM_HERE,
-                                        "Unit test",
-                                        syncer::TYPED_URLS)));
+              WillOnce(Return(syncer::SyncError(
+                                  FROM_HERE,
+                                  syncer::SyncError::DATATYPE_ERROR,
+                                  "Unit test",
+                                  syncer::TYPED_URLS)));
   StartSyncService(base::Bind(&AddTypedUrlEntries, this, sync_entries));
   // Errors getting typed URLs will cause an unrecoverable error (since we can
   // do *nothing* in that case).
@@ -991,7 +999,7 @@
   details.changed_urls.push_back(new_file_entry);
   scoped_refptr<ThreadNotifier> notifier(new ThreadNotifier(&history_thread_));
   notifier->Notify(chrome::NOTIFICATION_HISTORY_URLS_MODIFIED,
-                   content::Source<Profile>(&profile_),
+                   content::Source<Profile>(profile_.get()),
                    content::Details<history::URLsModifiedDetails>(&details));
 
   history::URLRows new_sync_entries;
@@ -1044,7 +1052,7 @@
   details.changed_urls.push_back(localhost_ip_entry);
   scoped_refptr<ThreadNotifier> notifier(new ThreadNotifier(&history_thread_));
   notifier->Notify(chrome::NOTIFICATION_HISTORY_URLS_MODIFIED,
-                   content::Source<Profile>(&profile_),
+                   content::Source<Profile>(profile_.get()),
                    content::Details<history::URLsModifiedDetails>(&details));
 
   history::URLRows new_sync_entries;
diff --git a/chrome/browser/sync/profile_sync_service_unittest.cc b/chrome/browser/sync/profile_sync_service_unittest.cc
index 3280634..6e7bbe7 100644
--- a/chrome/browser/sync/profile_sync_service_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_unittest.cc
@@ -8,6 +8,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/message_loop.h"
 #include "base/values.h"
+#include "chrome/browser/invalidation/invalidation_service_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/signin/token_service.h"
@@ -26,10 +27,6 @@
 #include "sync/js/js_arg_list.h"
 #include "sync/js/js_event_details.h"
 #include "sync/js/js_test_util.h"
-#include "sync/notifier/fake_invalidation_handler.h"
-#include "sync/notifier/invalidator.h"
-#include "sync/notifier/invalidator_test_template.h"
-#include "sync/notifier/object_id_invalidation_map_test_util.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -64,6 +61,8 @@
     io_thread_.StartIOThread();
     profile.reset(new TestingProfile());
     profile->CreateRequestContext();
+    invalidation::InvalidationServiceFactory::GetInstance()->
+        SetBuildOnlyFakeInvalidatorsForTest(true);
   }
 
   void TearDown() {
@@ -357,7 +356,7 @@
   StrictMock<syncer::MockJsReplyHandler> reply_handler;
 
   ListValue arg_list1;
-  arg_list1.Append(Value::CreateStringValue("TRANSIENT_INVALIDATION_ERROR"));
+  arg_list1.Append(Value::CreateStringValue("INVALIDATIONS_ENABLED"));
   syncer::JsArgList args1(&arg_list1);
   EXPECT_CALL(reply_handler,
               HandleJsReply("getNotificationState", HasArgs(args1)));
@@ -381,7 +380,7 @@
   StrictMock<syncer::MockJsReplyHandler> reply_handler;
 
   ListValue arg_list1;
-  arg_list1.Append(Value::CreateStringValue("TRANSIENT_INVALIDATION_ERROR"));
+  arg_list1.Append(Value::CreateStringValue("INVALIDATIONS_ENABLED"));
   syncer::JsArgList args1(&arg_list1);
   EXPECT_CALL(reply_handler,
               HandleJsReply("getNotificationState", HasArgs(args1)));
@@ -467,178 +466,5 @@
   EXPECT_FALSE(harness_.service->sync_initialized());
 }
 
-// Register a handler with the ProfileSyncService, and disable and
-// reenable sync.  The handler should get notified of the state
-// changes.
-// Flaky on all platforms. http://crbug.com/154491
-TEST_F(ProfileSyncServiceTest, DISABLED_DisableInvalidationsOnStop) {
-  harness_.StartSyncServiceAndSetInitialSyncEnded(
-      true, true, true, true, syncer::STORAGE_IN_MEMORY);
-
-  syncer::FakeInvalidationHandler handler;
-  harness_.service->RegisterInvalidationHandler(&handler);
-
-  SyncBackendHostForProfileSyncTest* const backend =
-      harness_.service->GetBackendForTest();
-
-  backend->EmitOnInvalidatorStateChange(syncer::INVALIDATIONS_ENABLED);
-  EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler.GetInvalidatorState());
-
-  harness_.service->StopAndSuppress();
-  EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
-            handler.GetInvalidatorState());
-
-  harness_.service->UnsuppressAndStart();
-  EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler.GetInvalidatorState());
-
-  harness_.service->UnregisterInvalidationHandler(&handler);
-}
-
-// Register for some IDs with the ProfileSyncService, restart sync,
-// and trigger some invalidation messages.  They should still be
-// received by the handler.
-TEST_F(ProfileSyncServiceTest, UpdateRegisteredInvalidationIdsPersistence) {
-  harness_.StartSyncService();
-
-  syncer::ObjectIdSet ids;
-  ids.insert(invalidation::ObjectId(3, "id3"));
-  const syncer::ObjectIdInvalidationMap& states =
-      syncer::ObjectIdSetToInvalidationMap(ids, "payload");
-
-  syncer::FakeInvalidationHandler handler;
-
-  harness_.service->RegisterInvalidationHandler(&handler);
-  harness_.service->UpdateRegisteredInvalidationIds(&handler, ids);
-
-  harness_.service->StopAndSuppress();
-  harness_.service->UnsuppressAndStart();
-
-  SyncBackendHostForProfileSyncTest* const backend =
-      harness_.service->GetBackendForTest();
-
-  backend->EmitOnInvalidatorStateChange(syncer::INVALIDATIONS_ENABLED);
-  EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler.GetInvalidatorState());
-
-  backend->EmitOnIncomingInvalidation(states);
-  EXPECT_THAT(states, Eq(handler.GetLastInvalidationMap()));
-
-  backend->EmitOnInvalidatorStateChange(syncer::TRANSIENT_INVALIDATION_ERROR);
-  EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
-            handler.GetInvalidatorState());
-
-  harness_.service->UnregisterInvalidationHandler(&handler);
-}
-
-// Thin Invalidator wrapper around ProfileSyncService.
-class ProfileSyncServiceInvalidator : public syncer::Invalidator {
- public:
-  explicit ProfileSyncServiceInvalidator(ProfileSyncService* service)
-      : service_(service) {}
-
-  virtual ~ProfileSyncServiceInvalidator() {}
-
-  // Invalidator implementation.
-  virtual void RegisterHandler(syncer::InvalidationHandler* handler) OVERRIDE {
-    service_->RegisterInvalidationHandler(handler);
-  }
-
-  virtual void UpdateRegisteredIds(syncer::InvalidationHandler* handler,
-                                   const syncer::ObjectIdSet& ids) OVERRIDE {
-    service_->UpdateRegisteredInvalidationIds(handler, ids);
-  }
-
-  virtual void UnregisterHandler(
-      syncer::InvalidationHandler* handler) OVERRIDE {
-    service_->UnregisterInvalidationHandler(handler);
-  }
-
-  virtual void Acknowledge(const invalidation::ObjectId& id,
-                           const syncer::AckHandle& ack_handle) OVERRIDE {
-    // Do nothing.
-  }
-
-  virtual syncer::InvalidatorState GetInvalidatorState() const OVERRIDE {
-    return service_->GetInvalidatorState();
-  }
-
-  virtual void UpdateCredentials(
-      const std::string& email, const std::string& token) OVERRIDE {
-    // Do nothing.
-  }
-
-  virtual void SendInvalidation(
-      const syncer::ObjectIdInvalidationMap& invalidation_map) OVERRIDE {
-    // Do nothing.
-  }
-
- private:
-  ProfileSyncService* const service_;
-
-  DISALLOW_COPY_AND_ASSIGN(ProfileSyncServiceInvalidator);
-};
-
 }  // namespace
-
-
-// ProfileSyncServiceInvalidatorTestDelegate has to be visible from
-// the syncer namespace (where InvalidatorTest lives).
-class ProfileSyncServiceInvalidatorTestDelegate {
- public:
-  ProfileSyncServiceInvalidatorTestDelegate() {}
-
-  ~ProfileSyncServiceInvalidatorTestDelegate() {
-    DestroyInvalidator();
-  }
-
-  void CreateInvalidator(
-      const std::string& invalidation_client_id,
-      const std::string& initial_state,
-      const base::WeakPtr<syncer::InvalidationStateTracker>&
-          invalidation_state_tracker) {
-    DCHECK(!invalidator_.get());
-    harness_.SetUp();
-    harness_.StartSyncService();
-    invalidator_.reset(
-        new ProfileSyncServiceInvalidator(harness_.service.get()));
-  }
-
-  ProfileSyncServiceInvalidator* GetInvalidator() {
-    return invalidator_.get();
-  }
-
-  void DestroyInvalidator() {
-    invalidator_.reset();
-    harness_.TearDown();
-  }
-
-  void WaitForInvalidator() {
-    // Do nothing.
-  }
-
-  void TriggerOnInvalidatorStateChange(syncer::InvalidatorState state) {
-    harness_.service->GetBackendForTest()->EmitOnInvalidatorStateChange(state);
-  }
-
-  void TriggerOnIncomingInvalidation(
-      const syncer::ObjectIdInvalidationMap& invalidation_map) {
-    harness_.service->GetBackendForTest()->EmitOnIncomingInvalidation(
-        invalidation_map);
-  }
-
- private:
-  ProfileSyncServiceTestHarness harness_;
-  scoped_ptr<ProfileSyncServiceInvalidator> invalidator_;
-};
-
 }  // namespace browser_sync
-
-namespace syncer {
-namespace {
-
-// ProfileSyncService should behave just like an invalidator.
-INSTANTIATE_TYPED_TEST_CASE_P(
-    ProfileSyncServiceInvalidatorTest, InvalidatorTest,
-    ::browser_sync::ProfileSyncServiceInvalidatorTestDelegate);
-
-}  // namespace
-}  // namespace syncer
diff --git a/chrome/browser/sync/resources/gaia_login.css b/chrome/browser/sync/resources/gaia_login.css
deleted file mode 100644
index b59959a..0000000
--- a/chrome/browser/sync/resources/gaia_login.css
+++ /dev/null
@@ -1,163 +0,0 @@
-body {
-  -webkit-user-select: none;
-  background-color: #fff;
-  margin-bottom: 6px;
-  margin-top: 6px;
-}
-
-a:link {
-  color: #00c;
-}
-
-a:visited {
-  color: #551a8b;
-}
-
-a:active {
-  color: #f00;
-}
-
-hr {
-  background-color: #ddd;
-  border: 0;
-  height: 1px;
-  margin: 5px;
-  text-align: left;
-  width: 100%;
-}
-
-input[type='button'],
-input[type='submit'] {
-  min-height: 26px;
-  min-width: 87px;
-}
-
-.end-aligned {
-  text-align: end;
-}
-
-#gaia-account-text {
-  font-weight: bold;
-  position: relative;
-  top: -7px;
-}
-
-#email-readonly {
-  font-size: 10pt;
-  font-weight: bold;
-}
-
-div.errormsg {
-  color: red;
-  font-size: smaller;
-}
-
-font.errormsg {
-  color: red;
-  font-size: smaller;
-}
-
-div.errormsgspacer {
-  min-height: 1em;
-}
-
-font.errormsgspacer {
-  font-size: smaller;
-}
-
-#gaia-login-form {
-  margin-bottom: 0;
-}
-
-#captcha-wrapper {
-  background: no-repeat;
-  background-color: #e8eefa;
-  background-position: center;
-  background-size: 200px 70px;
-  display: block;
-}
-
-#captcha-image {
-  height: 70px;
-  width: 200px;
-}
-
-#logging-in-throbber {
-  margin: 0 10px;
-}
-
-.bottom-padded-cell {
-  padding-bottom: 3px;
-}
-
-.no-vertical-padding {
-  padding-bottom: 0;
-  padding-top: 0;
-}
-
-#cancel-space-no-captcha {
-  height: 22px;
-}
-
-#top-blurb {
-  font-size: 11pt;
-  line-height: 1.5em;
-}
-
-#top-blurb-error {
-  background-color: #eeb939;
-  border-radius: 4px;
-  font-size: 11pt;
-  font-weight: bold;
-  margin-bottom: 10px;
-  margin-left: auto;
-  margin-right: auto;
-  padding: 4px 10px;
-  text-align: center;
-  visibility: hidden;
-  width: 70%;
-}
-
-#content-table {
-  background-color: #fff;
-  border: #c3d9ff 1px solid;
-  padding: 2px;
-}
-
-.access-code-row > td {
-  padding-bottom: 1px;
-  text-align: center;
-}
-
-#access-code-label-row > td {
-  padding-top: 6px;
-}
-
-.gaia-le-lbl,
-.gaia-le-val,
-.gaia-le-rem,
-.gaia-captchahtml-desc
-.gaia-captchahtml-cmt {
-  font-size: smaller;
-}
-
-.gaia-captchahtml-cmt {
-  font-style: italic;
-}
-
-.gaia-le-fpwd,
-.gaia-le-chusr {
-  font-size: 70%;
-}
-
-#password-row {
-  margin-top: 2px;
-}
-
-#action-area {
-  margin-top: 2px;
-}
-
-#errormsg-0-access-code {
-  text-align: center;
-}
diff --git a/chrome/browser/sync/resources/gaia_login.html b/chrome/browser/sync/resources/gaia_login.html
deleted file mode 100644
index 41be8b7..0000000
--- a/chrome/browser/sync/resources/gaia_login.html
+++ /dev/null
@@ -1,207 +0,0 @@
-<html i18n-values="dir:textdirection;">
-<head>
-<link rel="stylesheet" href="gaia_login.css">
-<link rel="stylesheet" href="chrome://resources/css/throbber.css">
-<script src="gaia_login.js"></script>
-</head>
-<body i18n-values=".style.fontFamily:fontfamily;.style.fontSize:fontsize">
-<div>
-  <div>
-    <div id="top-blurb-error">
-      <span id="error-signing-in" i18n-content="errorsigningin"></span>
-      <span id="error-custom" hidden></span>
-    </div>
-    <form id="gaia-login-form">
-      <div id="gaia-login-box">
-        <table id="content-table" cellspacing="0"
-            cellpadding="5" width="75%" border="0" align="center">
-          <tr>
-            <td valign="top" style="text-align:center" nowrap="nowrap"
-                bgcolor="#e8eefa">
-              <div>
-                <table id="gaia-table" align="center" border="0"
-                    cellpadding="1" cellspacing="0">
-                  <tr>
-                    <td colspan="2" align="center">
-                      <div>
-                        <div>
-                          <span class="gaia-le-lbl" i18n-content="signinprefix">
-                          </span>
-                        </div>
-                        <div>
-                          <span id="gaia-logo">
-                            <img src="google_transparent.png" alt="Google">
-                          </span>
-                          <span id="gaia-account-text"
-                              i18n-content="signinsuffix"></span>
-                        </div>
-                      </div>
-                    </td>
-                  </tr>
-                  <tr>
-                    <td colspan="2" align="center"> </td>
-                  </tr>
-                  <tr id="email-row">
-                    <td nowrap="nowrap">
-                      <div class="end-aligned">
-                        <span class="gaia-le-lbl" i18n-content="emaillabel">
-                        </span>
-                      </div>
-                    </td>
-                    <td>
-                      <input id="email" type="text" name="email" size="18"
-                          value="" class='gaia-le-val'>
-                      <span id="email-readonly" hidden></span>
-                    </td>
-                  </tr>
-                  <tr id="access-code-label-row" class="access-code-row" hidden>
-                    <td colspan="2">
-                      <span class="gaia-le-lbl"
-                          i18n-content="enteraccesscode"></span>
-                    </td>
-                  </tr>
-                  <tr id="access-code-help-row" class="access-code-row" hidden>
-                    <td colspan="2" class="gaia-le-fpwd">
-                      <a i18n-values="href:getaccesscodeurl"
-                          i18n-content="getaccesscodehelp" target="_blank">
-                      </a>
-                    </td>
-                  <tr>
-                    <td></td>
-                    <td>
-                      <div id="errormsg-0-email" class="errormsg" hidden
-                          i18n-content="cannotbeblank">
-                      </div>
-                    </td>
-                  </tr>
-                  <tr id="password-row">
-                    <td class="end-aligned">
-                      <span class="gaia-le-lbl"
-                          i18n-content="passwordlabel"></span>
-                    </td>
-                    <td>
-                      <input id="passwd" type="password" name="passwd" size="18"
-                          class="gaia-le-val">
-                    </td>
-                  </tr>
-                  <tr id="access-code-input-row" class="access-code-row" hidden>
-                    <td colspan="2">
-                      <input id="access-code" type="password" name="accessCode"
-                          size="18" class="gaia-le-val">
-                    </td>
-                  </tr>
-                  <tr>
-                    <td></td>
-                    <td>
-                      <div class="errormsgspacer">
-                        <div id="errormsg-0-password" class="errormsg" hidden
-                            i18n-content="cannotbeblank">
-                        </div>
-                        <div id="errormsg-1-password" class="errormsg" hidden>
-                          <span i18n-content="invalidcredentials"></span>
-                          <!-- Brackets are intentional -->
-                          [<a i18n-values="href:invalidpasswordhelpurl"
-                               target="_blank">?</a>]
-                        </div>
-                        <div id="errormsg-0-access-code" class="errormsg" hidden
-                            i18n-content="invalidaccesscode">
-                        </div>
-                      </div>
-                    </td>
-                  </tr>
-                  <tr>
-                    <td colspan="2">
-                      <div id="captcha-div" hidden>
-                        <table cellpadding="1" cellspacing="0" border="0">
-                          <tbody>
-                            <tr>
-                              <td colspan="2" align="center"
-                                  class="bottom-padded-cell">
-                                <font size="-1">
-                                  <span i18n-content="captchainstructions">
-                                  </span>
-                                </font>
-                              </td>
-                            </tr>
-                            <tr>
-                              <td colspan="2" align="center"
-                                  class="bottom-padded-cell">
-                                <span id="captcha-wrapper">
-                                  <div id="captcha-image"></div>
-                                </span>
-                              </td>
-                            </tr>
-                            <tr>
-                              <td colspan="2" align="center">
-                                <input id="captcha-value" type="text"
-                                    name="captchaValue" size="18" value=""
-                                    class="gaia-le-val">
-                              </td>
-                            </tr>
-                          </tbody>
-                        </table>
-                      </div>
-                    </td>
-                  </tr>
-                  <tr>
-                    <td colspan="2" align="center">
-                      <div id="errormsg-0-connection" class="errormsg" hidden
-                          i18n-content="couldnotconnect">
-                      </div>
-                    </td>
-                  </tr>
-                  <tr id="action-area">
-                    <td colspan="2">
-                      <table align="center" cellpadding="0"
-                          cellspacing="0">
-                        <tr>
-                          <td>
-                            <div id="logging-in-throbber" hidden>
-                              <div class="throbber"></div>
-                            </div>
-                          </td>
-                          <td class="no-vertical-padding">
-                            <input id="sign-in" type="submit" name="signIn"
-                                i18n-values="value:signin">
-                            <input id="gaia-cancel" type="button"
-                                name="cancel"
-                                i18n-values="value:cancel">
-                          </td>
-                        </tr>
-                      </table>
-                    </td>
-                  </tr>
-                  <tr id="ga-fprow">
-                    <td colspan="2" height="16.0" class="gaia-le-fpwd"
-                        align="center" valign="bottom">
-                      <a i18n-values="href:cannotaccessaccounturl"
-                          target="_blank"
-                          i18n-content="cannotaccessaccount">
-                      </a>
-                    </td>
-                  </tr>
-                  <tr>
-                    <td id="create-account-cell" colspan="2" height="16.0"
-                        class="gaia-le-fpwd" align="center" valign="bottom">
-                      <div id="create-account-div">
-                        <a i18n-values="href:createnewaccounturl"
-                            i18n-content="createaccount" target="_blank">
-                        </a>
-                      </div>
-                   </td>
-                  </tr>
-                </table>
-              </div>
-            </td>
-          </tr>
-        </table>
-      </div>
-    </form>
-  </div>
-  <div>
-    <div id="cancel-space-no-captcha" colspan="2">
-    </div>
-  </div>
-</div>
-</body>
-</html>
diff --git a/chrome/browser/sync/resources/gaia_login.js b/chrome/browser/sync/resources/gaia_login.js
deleted file mode 100644
index 5ce1b48..0000000
--- a/chrome/browser/sync/resources/gaia_login.js
+++ /dev/null
@@ -1,249 +0,0 @@
-// Copyright (c) 2011 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.
-
-// Variable to track if a captcha challenge was issued. If this gets set to
-// true, it stays that way until we are told about successful login from
-// the browser.  This means subsequent errors (like invalid password) are
-// rendered in the captcha state, which is basically identical except we
-// don't show the top error blurb "Error Signing in" or the "Create
-// account" link.
-var g_is_captcha_challenge_active = false;
-
-// Taken from new_tab.js.
-// TODO(tim): Can this be unified?
-function url(s) {
-  // http://www.w3.org/TR/css3-values/#uris
-  // Parentheses, commas, whitespace characters, single quotes (') and
-  // double quotes (") appearing in a URI must be escaped with a backslash
-  var s2 = s.replace(/(\(|\)|\,|\s|\'|\"|\\)/g, '\\$1');
-  // WebKit has a bug when it comes to URLs that end with \
-  // https://bugs.webkit.org/show_bug.cgi?id=28885
-  if (/\\\\$/.test(s2)) {
-    // Add a space to work around the WebKit bug.
-    s2 += ' ';
-  }
-  return 'url("' + s2 + '")';
-}
-
-function gaia_setFocus() {
-  var form = document.getElementById('gaia-login-form');
-  if (form.email && (form.email.value == null || form.email.value == '')) {
-    form.email.focus();
-  } else if (form.passwd) {
-    form.passwd.focus();
-  }
-}
-
-function showGaiaLogin(args) {
-  document.getElementById('logging-in-throbber').hidden = true;
-
-  document.getElementById('email').disabled = false;
-  document.getElementById('passwd').disabled = false;
-
-  var f = document.getElementById('gaia-login-form');
-  if (f) {
-    if (args.user != undefined) {
-      if (f.email.value != args.user)
-        f.passwd.value = ''; // Reset the password field
-      f.email.value = args.user;
-    }
-
-    var editable_user = args.editable_user;
-    f.email.hidden = !editable_user;
-    var emailReadonly = document.getElementById('email-readonly');
-    emailReadonly.hidden = editable_user;
-    emailReadonly.textContent = f.email.value;
-    setElementVisible('create-account-div', editable_user);
-    f.accessCode.disabled = true;
-  }
-
-  if (1 == args.error) {
-    var access_code = document.getElementById('access-code');
-    if (access_code.value && access_code.value != '') {
-      setElementVisible('errormsg-0-access-code', true);
-      showAccessCodeRequired();
-    } else {
-      setElementVisible('errormsg-1-password', true);
-    }
-    setBlurbError(args.error_message);
-  } else if (3 == args.error) {
-    setElementVisible('errormsg-0-connection', true);
-    setBlurbError(args.error_message);
-  } else if (4 == args.error) {
-    showCaptcha(args);
-  } else if (8 == args.error) {
-    showAccessCodeRequired();
-  } else if (args.error_message) {
-    setBlurbError(args.error_message);
-  }
-
-  document.getElementById('sign-in').disabled = false;
-  document.getElementById('sign-in').value = templateData['signin'];
-  gaia_setFocus();
-}
-
-function showCaptcha(args) {
-  g_is_captcha_challenge_active = true;
-
-  // The captcha takes up lots of space, so make room.
-  $('top-blurb-error').hidden = true;
-  setElementVisible('top-blurb', false);
-  setElementVisible('create-account-div', false);
-  document.getElementById('create-account-cell').height = 0;
-
-  // It's showtime for the captcha now.
-  setElementVisible('captcha-div', true);
-  document.getElementById('email').disabled = true;
-  document.getElementById('passwd').disabled = false;
-  document.getElementById('captcha-value').disabled = false;
-  document.getElementById('captcha-wrapper').style.backgroundImage =
-      url(args.captchaUrl);
-}
-
-function showAccessCodeRequired() {
-  setElementVisible('password-row', false);
-  setElementVisible('email-row', false);
-  document.getElementById('create-account-cell').style.visibility = 'hidden';
-
-  setElementVisible('access-code-label-row', true);
-  setElementVisible('access-code-input-row', true);
-  setElementVisible('access-code-help-row', true);
-  document.getElementById('access-code').disabled = false;
-}
-
-function CloseDialog() {
-  chrome.send('DialogClose', ['']);
-}
-
-function showGaiaSuccessAndClose() {
-  document.getElementById('sign-in').value = templateData['success'];
-  setTimeout(CloseDialog, 1600);
-}
-
-function showGaiaSuccessAndSettingUp() {
-  document.getElementById('sign-in').value = templateData['settingup'];
-}
-
-/**
- * DOMContentLoaded handler, sets up the page.
- */
-function load() {
-  var acct_text = document.getElementById('gaia-account-text');
-  var translated_text = acct_text.textContent;
-  var posGoogle = translated_text.indexOf('Google');
-  if (posGoogle != -1) {
-    var ltr = templateData['textdirection'] == 'ltr';
-    var googleIsAtEndOfSentence = posGoogle != 0;
-    if (googleIsAtEndOfSentence == ltr) {
-      // We're in ltr and in the translation the word 'Google' is AFTER the
-      // word 'Account' OR we're in rtl and 'Google' is BEFORE 'Account'.
-      var logo_div = document.getElementById('gaia-logo');
-      logo_div.parentNode.appendChild(logo_div);
-    }
-    acct_text.textContent = translated_text.replace('Google','');
-  }
-
-  var loginForm = document.getElementById('gaia-login-form');
-  loginForm.onsubmit = function() {
-    sendCredentialsAndClose();
-    return false;
-  };
-
-  var gaiaCancel = document.getElementById('gaia-cancel');
-  gaiaCancel.onclick = function() {
-    CloseDialog();
-  };
-
-  var args = JSON.parse(chrome.getVariableValue("dialogArguments"));
-  showGaiaLogin(args);
-}
-
-function sendCredentialsAndClose() {
-  if (!setErrorVisibility())
-    return false;
-
-  document.getElementById('email').disabled = true;
-  document.getElementById('passwd').disabled = true;
-  document.getElementById('captcha-value').disabled = true;
-  document.getElementById('access-code').disabled = true;
-
-  document.getElementById('logging-in-throbber').hidden = false;
-
-  var f = document.getElementById('gaia-login-form');
-  var result = JSON.stringify({'user' : f.email.value,
-                               'pass' : f.passwd.value,
-                               'captcha' : f.captchaValue.value,
-                               'access_code' : f.accessCode.value});
-  document.getElementById('sign-in').disabled = true;
-  chrome.send('SubmitAuth', [result]);
-}
-
-function setElementVisible(id, display) {
-  var d = document.getElementById(id);
-  if (d)
-    d.hidden = !display;
-}
-
-function hideBlurb() {
-  setElementVisible('top-blurb', false);
-}
-
-function setBlurbError(error_message) {
-  if (g_is_captcha_challenge_active)
-    return;  // No blurb in captcha challenge mode.
-  if (error_message) {
-    document.getElementById('error-signing-in').hidden = true;
-    document.getElementById('error-custom').hidden = false;
-    document.getElementById('error-custom').textContent = error_message;
-  } else {
-    document.getElementById('error-signing-in').hidden = false;
-    document.getElementById('error-custom').hidden = true;
-  }
-  document.getElementById('top-blurb-error').hidden = false;
-  document.getElementById('email').disabled = false;
-  document.getElementById('passwd').disabled = false;
-}
-
-function resetErrorVisibility() {
-  setElementVisible('errormsg-0-email', false);
-  setElementVisible('errormsg-0-password', false);
-  setElementVisible('errormsg-1-password', false);
-  setElementVisible('errormsg-0-connection', false);
-  setElementVisible('errormsg-0-access-code', false);
-}
-
-function setErrorVisibility() {
-  resetErrorVisibility();
-  var f = document.getElementById('gaia-login-form');
-  if (null == f.email.value || '' == f.email.value) {
-    setElementVisible('errormsg-0-email', true);
-    setBlurbError();
-    return false;
-  }
-  if (null == f.passwd.value || '' == f.passwd.value) {
-    setElementVisible('errormsg-0-password', true);
-    setBlurbError();
-    return false;
-  }
-  if (!f.accessCode.disabled && (null == f.accessCode.value ||
-      '' == f.accessCode.value)) {
-    setElementVisible('errormsg-0-password', true);
-    return false;
-  }
-  return true;
-}
-
-function onPreCreateAccount() {
-  return true;
-}
-
-function onPreLogin() {
-  if (window['onlogin'] != null) {
-    return onlogin();
-  } else {
-    return true;
-  }
-}
-
-document.addEventListener('DOMContentLoaded', load);
diff --git a/chrome/browser/sync/resources/gaia_login_test.html b/chrome/browser/sync/resources/gaia_login_test.html
deleted file mode 100644
index c3b5875..0000000
--- a/chrome/browser/sync/resources/gaia_login_test.html
+++ /dev/null
@@ -1,123 +0,0 @@
-<!DOCTYPE html>
-<html>
-<!--
-This page is a simple testing environment for gaia_login.html to help
-iterate on the design without having to compile and launch the
-browser.  Note that you must supply the "--allow-file-access-from-files"
-for the chrome you are using to load this page for this to work.
--->
-<style>
-body {
-  background-color: #d0d0d0;
-}
-
-#iframe {
-  height: 375px;
-  width: 421px;
-  border: 0px;
-  float: left;
-}
-#options {
-  float: left;
-}
-
-</style>
-<script>
-function gel(id) {
-  return document.getElementById(id);
-}
-
-function get_selected_value(el) {
-  for (var i = 0; i < el.length; ++i) {
-    if (el[i].checked)
-      return el[i].value;
-  }
-  return null;
-}
-
-function set_up_testing() {
-  var win = window.frames[0];
-  var doc = win.document;
-  var form = gel("form");
-  form.addEventListener("change", function() { update(); }, true);
-
-  win.JSON = {};
-  win.JSON.parse = function() {
-    return {
-      error: get_selected_value(form.error),
-      user: "homer@gmail.com",
-      captchaUrl: "https://accounts.google.com/Captcha"
-    };
-  };
-
-  console.log(win.JSON.parse());
-
-  set_text("introduction",
-           "Chromium sync makes it easy to share your data (such as " +
-           "bookmarks and preferences) between your computers. Chromium " +
-           "synchronizes your data by storing it online with Google when " +
-           "you login with your Google Account.");
-  set_text("settingupsync", "Setting up sync");
-  set_text("errorsigningin", "Error signing in.");
-  set_text("signinsuffix", "Account");
-  set_text("emaillabel", "Email:");
-  set_text("cannotbeblank", "cannotbeblank");
-  set_text("passwordlabel", "Password:");
-  set_text("invalidcredentials", "Invalid user name or password.");
-  set_text("captchainstructions",
-           "Enter the correct password above and then type the characters " +
-           "you see in the picture below.");
-  set_text("couldnotconnect", "Could not connect to the server");
-  set_text("value:signin", "Sign in");
-  set_text("href:cannotaccessaccounturl", "href:cannotaccessaccounturl");
-  set_text("cannotaccessaccount", "I cannot access my account");
-  set_text("href:createnewaccounturl", "href:createnewaccounturl");
-  set_text("createaccount", "Create a Google account");
-  set_text("value:cancel", "Cancel");
-
-  function set_text(id, text) {
-    if (id.indexOf(":") >= 0) {
-      var node = doc.evaluate("//*[@i18n-values='" + id + "']",
-                              doc,
-                              null,
-                              XPathResult.FIRST_ORDERED_NODE_TYPE,
-                              null).singleNodeValue;
-      node.setAttribute(id.split(":")[0], text);
-    } else {
-      var node = doc.evaluate("//*[@i18n-content='" + id + "']",
-                              doc,
-                              null,
-                              XPathResult.FIRST_ORDERED_NODE_TYPE,
-                              null).singleNodeValue;
-      node.innerHTML = text;
-    }
-  }
-
-  win.initForm();
-}
-
-function update() {
-  window.frames[0].document.location.reload();
-}
-
-</script>
-<body>
-<div>
-<iframe
-  id="iframe"
-  src="gaia_login.html"
-  onload="set_up_testing()">
-</iframe>
-<div id="options">
-<form id="form" name="form">
-<p>
-  <input type="radio" name="error" value="" checked> No Error
-  <input type="radio" name="error" value="1"> Bad Password
-  <input type="radio" name="error" value="3"> Lost Connection
-  <input type="radio" name="error" value="4"> Captcha
-</p>
-</form>
-</div>
-</div>
-</body>
-</html>
diff --git a/chrome/browser/sync/resources/google_transparent.png b/chrome/browser/sync/resources/google_transparent.png
deleted file mode 100644
index 026969e..0000000
--- a/chrome/browser/sync/resources/google_transparent.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/sync/retry_verifier.h b/chrome/browser/sync/retry_verifier.h
index 77219bf..7d8d3e9 100644
--- a/chrome/browser/sync/retry_verifier.h
+++ b/chrome/browser/sync/retry_verifier.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_SYNC_RETRY_VERIFIER_H_
 #define CHROME_BROWSER_SYNC_RETRY_VERIFIER_H_
 
-#include "base/time.h"
+#include "base/time/time.h"
 
 // TODO(akalin): Move this to somewhere in sync/ and make
 // sync/engine/polling_constants.h private.
diff --git a/chrome/browser/sync/sync_prefs.cc b/chrome/browser/sync/sync_prefs.cc
index 2bfbc71..66fd680 100644
--- a/chrome/browser/sync/sync_prefs.cc
+++ b/chrome/browser/sync/sync_prefs.cc
@@ -111,6 +111,12 @@
       std::string(),
       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
 
+  // Keeps track whether server experiments have been switched on for that user.
+  registry->RegisterBooleanPref(
+      prefs::kSyncFaviconsEnabled,
+      false,
+      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+
   // We will start prompting people about new data types after the launch of
   // SESSIONS - all previously launched data types are treated as if they are
   // already acknowledged.
diff --git a/chrome/browser/sync/sync_prefs.h b/chrome/browser/sync/sync_prefs.h
index 4fa9cee..21ae4e8 100644
--- a/chrome/browser/sync/sync_prefs.h
+++ b/chrome/browser/sync/sync_prefs.h
@@ -11,7 +11,7 @@
 #include "base/observer_list.h"
 #include "base/prefs/pref_member.h"
 #include "base/threading/non_thread_safe.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "sync/internal_api/public/base/model_type.h"
 #include "sync/notifier/invalidation_state_tracker.h"
 
diff --git a/chrome/browser/sync/sync_prefs_unittest.cc b/chrome/browser/sync/sync_prefs_unittest.cc
index 042df83..2320726 100644
--- a/chrome/browser/sync/sync_prefs_unittest.cc
+++ b/chrome/browser/sync/sync_prefs_unittest.cc
@@ -6,7 +6,7 @@
 
 #include "base/command_line.h"
 #include "base/message_loop.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_pref_service_syncable.h"
diff --git a/chrome/browser/sync/sync_ui_util.cc b/chrome/browser/sync/sync_ui_util.cc
index 46aebd5..645bc4c 100644
--- a/chrome/browser/sync/sync_ui_util.cc
+++ b/chrome/browser/sync/sync_ui_util.cc
@@ -56,10 +56,8 @@
                                         user_name);
     } else if (service->IsStartSuppressed()) {
       // User is signed in, but sync has been stopped.
-      return l10n_util::GetStringFUTF16(
-          IDS_SIGNED_IN_WITH_SYNC_SUPPRESSED,
-          user_name,
-          ASCIIToUTF16(chrome::kSyncGoogleDashboardURL));
+      return l10n_util::GetStringFUTF16(IDS_SIGNED_IN_WITH_SYNC_SUPPRESSED,
+                                        user_name);
     }
   }
 
@@ -253,8 +251,7 @@
       if (status_label) {
         string16 label = l10n_util::GetStringFUTF16(
                              IDS_SIGNED_IN_WITH_SYNC_SUPPRESSED,
-                             UTF8ToUTF16(signin.GetAuthenticatedUsername()),
-                             ASCIIToUTF16(chrome::kSyncGoogleDashboardURL));
+                             UTF8ToUTF16(signin.GetAuthenticatedUsername()));
         status_label->assign(label);
         result_type = PRE_SYNCED;
       }
diff --git a/chrome/browser/sync/test/integration/autofill_helper.cc b/chrome/browser/sync/test/integration/autofill_helper.cc
index 944e8fa..bc9bf3e 100644
--- a/chrome/browser/sync/test/integration/autofill_helper.cc
+++ b/chrome/browser/sync/test/integration/autofill_helper.cc
@@ -11,14 +11,14 @@
 #include "chrome/browser/sync/test/integration/sync_datatype_helper.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
 #include "chrome/common/chrome_notification_types.h"
-#include "components/autofill/browser/autofill_common_test.h"
-#include "components/autofill/browser/autofill_profile.h"
-#include "components/autofill/browser/autofill_type.h"
-#include "components/autofill/browser/personal_data_manager.h"
-#include "components/autofill/browser/personal_data_manager_observer.h"
-#include "components/autofill/browser/webdata/autofill_entry.h"
-#include "components/autofill/browser/webdata/autofill_table.h"
-#include "components/autofill/browser/webdata/autofill_webdata_service.h"
+#include "components/autofill/core/browser/autofill_common_test.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/autofill_type.h"
+#include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/autofill/core/browser/personal_data_manager_observer.h"
+#include "components/autofill/core/browser/webdata/autofill_entry.h"
+#include "components/autofill/core/browser/webdata/autofill_table.h"
+#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
 #include "components/autofill/core/common/form_field_data.h"
 #include "components/webdata/common/web_database.h"
 
diff --git a/chrome/browser/sync/test/integration/bookmarks_helper.h b/chrome/browser/sync/test/integration/bookmarks_helper.h
index 286974f..f1a62e8 100644
--- a/chrome/browser/sync/test/integration/bookmarks_helper.h
+++ b/chrome/browser/sync/test/integration/bookmarks_helper.h
@@ -11,9 +11,9 @@
 
 #include "base/compiler_specific.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
-#include "googleurl/src/gurl.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "url/gurl.h"
 
 class GURL;
 
diff --git a/chrome/browser/sync/test/integration/passwords_helper.cc b/chrome/browser/sync/test/integration/passwords_helper.cc
index e72133f..739d294 100644
--- a/chrome/browser/sync/test/integration/passwords_helper.cc
+++ b/chrome/browser/sync/test/integration/passwords_helper.cc
@@ -8,7 +8,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/waitable_event.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/password_manager/password_form_data.h"
 #include "chrome/browser/password_manager/password_store.h"
 #include "chrome/browser/password_manager/password_store_consumer.h"
diff --git a/chrome/browser/sync/test/integration/performance/autofill_sync_perf_test.cc b/chrome/browser/sync/test/integration/performance/autofill_sync_perf_test.cc
index 5f97f2b..49d79ad 100644
--- a/chrome/browser/sync/test/integration/performance/autofill_sync_perf_test.cc
+++ b/chrome/browser/sync/test/integration/performance/autofill_sync_perf_test.cc
@@ -9,9 +9,9 @@
 #include "chrome/browser/sync/test/integration/bookmarks_helper.h"
 #include "chrome/browser/sync/test/integration/performance/sync_timing_helper.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
-#include "components/autofill/browser/autofill_common_test.h"
-#include "components/autofill/browser/autofill_profile.h"
-#include "components/autofill/browser/webdata/autofill_entry.h"
+#include "components/autofill/core/browser/autofill_common_test.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/webdata/autofill_entry.h"
 
 using autofill::AutofillFieldType;
 using autofill::AutofillKey;
diff --git a/chrome/browser/sync/test/integration/performance/sync_timing_helper.cc b/chrome/browser/sync/test/integration/performance/sync_timing_helper.cc
index 6a0b4ee..5e7eb26 100644
--- a/chrome/browser/sync/test/integration/performance/sync_timing_helper.cc
+++ b/chrome/browser/sync/test/integration/performance/sync_timing_helper.cc
@@ -5,7 +5,7 @@
 #include "chrome/browser/sync/test/integration/performance/sync_timing_helper.h"
 
 #include "base/strings/string_number_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/sync/profile_sync_service_harness.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/chrome/browser/sync/test/integration/search_engines_helper.cc b/chrome/browser/sync/test/integration/search_engines_helper.cc
index 8e82def..3838d22 100644
--- a/chrome/browser/sync/test/integration/search_engines_helper.cc
+++ b/chrome/browser/sync/test/integration/search_engines_helper.cc
@@ -9,7 +9,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search_engines/template_url.h"
 #include "chrome/browser/search_engines/template_url_service.h"
diff --git a/chrome/browser/sync/test/integration/sessions_helper.cc b/chrome/browser/sync/test/integration/sessions_helper.cc
index da843cb..fa90917 100644
--- a/chrome/browser/sync/test/integration/sessions_helper.cc
+++ b/chrome/browser/sync/test/integration/sessions_helper.cc
@@ -8,7 +8,7 @@
 
 #include "base/stl_util.h"
 #include "base/test/test_timeouts.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sync/glue/session_model_associator.h"
 #include "chrome/browser/sync/profile_sync_service.h"
@@ -18,7 +18,7 @@
 #include "chrome/browser/sync/test/integration/sync_test.h"
 #include "chrome/browser/ui/singleton_tabs.h"
 #include "chrome/test/base/ui_test_utils.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 using sync_datatype_helper::test;
 
diff --git a/chrome/browser/sync/test/integration/sync_test.cc b/chrome/browser/sync/test/integration/sync_test.cc
index cdbe54c..8d75d64 100644
--- a/chrome/browser/sync/test/integration/sync_test.cc
+++ b/chrome/browser/sync/test/integration/sync_test.cc
@@ -21,6 +21,8 @@
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/browser/google/google_url_tracker.h"
 #include "chrome/browser/history/history_service_factory.h"
+#include "chrome/browser/invalidation/invalidation_service_factory.h"
+#include "chrome/browser/invalidation/p2p_invalidation_service.h"
 #include "chrome/browser/lifetime/application_lifetime.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
@@ -41,7 +43,6 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/test_browser_thread.h"
 #include "google_apis/gaia/gaia_urls.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/escape.h"
 #include "net/base/load_flags.h"
 #include "net/base/network_change_notifier.h"
@@ -58,8 +59,10 @@
 #include "sync/engine/sync_scheduler_impl.h"
 #include "sync/notifier/p2p_invalidator.h"
 #include "sync/protocol/sync.pb.h"
+#include "url/gurl.h"
 
 using content::BrowserThread;
+using invalidation::InvalidationServiceFactory;
 
 namespace switches {
 const char kPasswordFileForTest[] = "password-file-for-test";
@@ -196,19 +199,10 @@
 }
 
 void SyncTest::AddTestSwitches(CommandLine* cl) {
-  // TODO(rsimha): Until we implement a fake Tango server against which tests
-  // can run, we need to set the --sync-notification-method to "p2p".
-  if (!cl->HasSwitch(switches::kSyncNotificationMethod))
-    cl->AppendSwitchASCII(switches::kSyncNotificationMethod, "p2p");
-
   // Disable non-essential access of external network resources.
   if (!cl->HasSwitch(switches::kDisableBackgroundNetworking))
     cl->AppendSwitch(switches::kDisableBackgroundNetworking);
 
-  // TODO(sync): remove this once keystore encryption is enabled by default.
-  if (!cl->HasSwitch(switches::kSyncKeystoreEncryption))
-    cl->AppendSwitch(switches::kSyncKeystoreEncryption);
-
   if (!cl->HasSwitch(switches::kSyncShortInitialRetryOverride))
     cl->AppendSwitch(switches::kSyncShortInitialRetryOverride);
 
@@ -306,18 +300,26 @@
                                           << index << ".";
 
   browsers_[index] = new Browser(Browser::CreateParams(
-      GetProfile(index), chrome::HOST_DESKTOP_TYPE_NATIVE));
+      GetProfile(index), chrome::GetActiveDesktop()));
   EXPECT_FALSE(GetBrowser(index) == NULL) << "Could not create Browser "
                                           << index << ".";
 
+  invalidation::P2PInvalidationService* p2p_invalidation_service =
+      InvalidationServiceFactory::GetInstance()->
+          BuildAndUseP2PInvalidationServiceForTest(GetProfile(index));
+  p2p_invalidation_service->UpdateCredentials(username_, password_);
+
   // Make sure the ProfileSyncService has been created before creating the
   // ProfileSyncServiceHarness - some tests expect the ProfileSyncService to
   // already exist.
   ProfileSyncServiceFactory::GetForProfile(GetProfile(index));
 
-  clients_[index] = new ProfileSyncServiceHarness(GetProfile(index),
-                                                  username_,
-                                                  password_);
+  clients_[index] =
+      ProfileSyncServiceHarness::CreateForIntegrationTest(
+          GetProfile(index),
+          username_,
+          password_,
+          p2p_invalidation_service);
   EXPECT_FALSE(GetClient(index) == NULL) << "Could not create Client "
                                          << index << ".";
 
diff --git a/chrome/browser/sync/test/integration/two_client_autofill_sync_test.cc b/chrome/browser/sync/test/integration/two_client_autofill_sync_test.cc
index 412ffa9..49ea529 100644
--- a/chrome/browser/sync/test/integration/two_client_autofill_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_autofill_sync_test.cc
@@ -7,11 +7,11 @@
 #include "chrome/browser/sync/test/integration/autofill_helper.h"
 #include "chrome/browser/sync/test/integration/bookmarks_helper.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
-#include "components/autofill/browser/autofill_profile.h"
-#include "components/autofill/browser/credit_card.h"
-#include "components/autofill/browser/personal_data_manager.h"
-#include "components/autofill/browser/webdata/autofill_entry.h"
-#include "components/autofill/browser/webdata/autofill_table.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/credit_card.h"
+#include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/autofill/core/browser/webdata/autofill_entry.h"
+#include "components/autofill/core/browser/webdata/autofill_table.h"
 
 using autofill::AutofillKey;
 using autofill::AutofillTable;
diff --git a/chrome/browser/sync/test/integration/two_client_preferences_sync_test.cc b/chrome/browser/sync/test/integration/two_client_preferences_sync_test.cc
index 83e6936..8ed733c5 100644
--- a/chrome/browser/sync/test/integration/two_client_preferences_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_preferences_sync_test.cc
@@ -401,18 +401,18 @@
 
   TranslatePrefs translate_client0_prefs(GetPrefs(0));
   TranslatePrefs translate_client1_prefs(GetPrefs(1));
-  ASSERT_FALSE(translate_client0_prefs.IsLanguageBlacklisted("fr"));
-  translate_client0_prefs.BlacklistLanguage("fr");
-  ASSERT_TRUE(translate_client0_prefs.IsLanguageBlacklisted("fr"));
+  ASSERT_FALSE(translate_client0_prefs.IsBlockedLanguage("fr"));
+  translate_client0_prefs.BlockLanguage("fr");
+  ASSERT_TRUE(translate_client0_prefs.IsBlockedLanguage("fr"));
 
   ASSERT_TRUE(GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1)));
-  ASSERT_TRUE(translate_client1_prefs.IsLanguageBlacklisted("fr"));
+  ASSERT_TRUE(translate_client1_prefs.IsBlockedLanguage("fr"));
 
-  translate_client0_prefs.RemoveLanguageFromBlacklist("fr");
-  ASSERT_FALSE(translate_client0_prefs.IsLanguageBlacklisted("fr"));
+  translate_client0_prefs.UnblockLanguage("fr");
+  ASSERT_FALSE(translate_client0_prefs.IsBlockedLanguage("fr"));
 
   ASSERT_TRUE(GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1)));
-  ASSERT_FALSE(translate_client1_prefs.IsLanguageBlacklisted("fr"));
+  ASSERT_FALSE(translate_client1_prefs.IsBlockedLanguage("fr"));
 }
 
 // TCM ID - 7307195.
diff --git a/chrome/browser/sync/test/integration/typed_urls_helper.cc b/chrome/browser/sync/test/integration/typed_urls_helper.cc
index 205dec0..c297fef 100644
--- a/chrome/browser/sync/test/integration/typed_urls_helper.cc
+++ b/chrome/browser/sync/test/integration/typed_urls_helper.cc
@@ -7,7 +7,7 @@
 #include "base/compiler_specific.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/waitable_event.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/common/cancelable_request.h"
 #include "chrome/browser/history/history_backend.h"
 #include "chrome/browser/history/history_db_task.h"
diff --git a/chrome/browser/sync/test_profile_sync_service.cc b/chrome/browser/sync/test_profile_sync_service.cc
index 0937065..dac67f2 100644
--- a/chrome/browser/sync/test_profile_sync_service.cc
+++ b/chrome/browser/sync/test_profile_sync_service.cc
@@ -36,7 +36,6 @@
 SyncBackendHostForProfileSyncTest::SyncBackendHostForProfileSyncTest(
     Profile* profile,
     const base::WeakPtr<SyncPrefs>& sync_prefs,
-    const base::WeakPtr<invalidation::InvalidatorStorage>& invalidator_storage,
     syncer::TestIdFactory& id_factory,
     base::Closure& callback,
     bool set_initial_sync_ended_on_init,
@@ -44,7 +43,7 @@
     bool fail_initial_download,
     syncer::StorageOption storage_option)
     : browser_sync::SyncBackendHost(
-        profile->GetDebugName(), profile, sync_prefs, invalidator_storage),
+        profile->GetDebugName(), profile, sync_prefs),
       weak_ptr_factory_(this),
       id_factory_(id_factory),
       callback_(callback),
@@ -104,6 +103,7 @@
 void SyncBackendHostForProfileSyncTest::RequestConfigureSyncer(
     syncer::ConfigureReason reason,
     syncer::ModelTypeSet to_download,
+    syncer::ModelTypeSet to_purge,
     syncer::ModelTypeSet to_journal,
     syncer::ModelTypeSet to_unapply,
     syncer::ModelTypeSet to_ignore,
@@ -115,8 +115,13 @@
   if (fail_initial_download_)
     failed_configuration_types = to_download;
 
+  // The first parameter there should be the set of enabled types.  That's not
+  // something we have access to from this strange test harness.  We'll just
+  // send back the list of newly configured types instead and hope it doesn't
+  // break anything.
   FinishConfigureDataTypesOnFrontendLoop(
       syncer::Difference(to_download, failed_configuration_types),
+      syncer::Difference(to_download, failed_configuration_types),
       failed_configuration_types,
       ready_task);
 }
@@ -178,16 +183,6 @@
   }
 }
 
-void SyncBackendHostForProfileSyncTest::EmitOnInvalidatorStateChange(
-    syncer::InvalidatorState state) {
-  frontend()->OnInvalidatorStateChange(state);
-}
-
-void SyncBackendHostForProfileSyncTest::EmitOnIncomingInvalidation(
-    const syncer::ObjectIdInvalidationMap& invalidation_map) {
-  frontend()->OnIncomingInvalidation(invalidation_map);
-}
-
 void SyncBackendHostForProfileSyncTest::ContinueInitialization(
     const syncer::WeakHandle<syncer::JsBackend>& js_backend,
     const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>&
@@ -310,7 +305,6 @@
   backend_.reset(new browser_sync::SyncBackendHostForProfileSyncTest(
       profile(),
       sync_prefs_.AsWeakPtr(),
-      invalidator_storage_.AsWeakPtr(),
       id_factory_,
       callback_,
       set_initial_sync_ended_on_init_,
diff --git a/chrome/browser/sync/test_profile_sync_service.h b/chrome/browser/sync/test_profile_sync_service.h
index dd76f2c..41d2687 100644
--- a/chrome/browser/sync/test_profile_sync_service.h
+++ b/chrome/browser/sync/test_profile_sync_service.h
@@ -46,8 +46,6 @@
   SyncBackendHostForProfileSyncTest(
       Profile* profile,
       const base::WeakPtr<SyncPrefs>& sync_prefs,
-      const base::WeakPtr<invalidation::InvalidatorStorage>&
-          invalidator_storage,
       syncer::TestIdFactory& id_factory,
       base::Closure& callback,
       bool set_initial_sync_ended_on_init,
@@ -64,6 +62,7 @@
   virtual void RequestConfigureSyncer(
       syncer::ConfigureReason reason,
       syncer::ModelTypeSet to_download,
+      syncer::ModelTypeSet to_purge,
       syncer::ModelTypeSet to_journal,
       syncer::ModelTypeSet to_unapply,
       syncer::ModelTypeSet to_ignore,
@@ -80,10 +79,6 @@
 
   static void SetHistoryServiceExpectations(ProfileMock* profile);
 
-  void EmitOnInvalidatorStateChange(syncer::InvalidatorState state);
-  void EmitOnIncomingInvalidation(
-      const syncer::ObjectIdInvalidationMap& invalidation_map);
-
  protected:
   virtual void InitCore(const DoInitializeOptions& options) OVERRIDE;
 
diff --git a/chrome/browser/sync_file_system/conflict_resolution_policy.h b/chrome/browser/sync_file_system/conflict_resolution_policy.h
index 2fee089..648ed2c 100644
--- a/chrome/browser/sync_file_system/conflict_resolution_policy.h
+++ b/chrome/browser/sync_file_system/conflict_resolution_policy.h
@@ -9,15 +9,15 @@
 
 enum ConflictResolutionPolicy {
   // Resolution policy unknown or not initialized. Usually indicates an error.
-  CONFLICT_RESOLUTION_UNKNOWN,
+  CONFLICT_RESOLUTION_POLICY_UNKNOWN,
 
   // The service automatically resolves a conflict by choosing the one
   // that is updated more recently.
-  CONFLICT_RESOLUTION_LAST_WRITE_WIN,
+  CONFLICT_RESOLUTION_POLICY_LAST_WRITE_WIN,
 
   // The service does nothing and just leaves conflicting files in
   // 'conflicted' state.
-  CONFLICT_RESOLUTION_MANUAL,
+  CONFLICT_RESOLUTION_POLICY_MANUAL,
 };
 
 }  // namespace sync_file_system
diff --git a/chrome/browser/sync_file_system/conflict_resolution_resolver.cc b/chrome/browser/sync_file_system/conflict_resolution_resolver.cc
new file mode 100644
index 0000000..50fed10
--- /dev/null
+++ b/chrome/browser/sync_file_system/conflict_resolution_resolver.cc
@@ -0,0 +1,47 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/sync_file_system/conflict_resolution_resolver.h"
+
+#include "base/logging.h"
+#include "base/time/time.h"
+
+namespace sync_file_system {
+
+ConflictResolutionResolver::ConflictResolutionResolver(
+    ConflictResolutionPolicy policy)
+    : policy_(policy) {}
+
+ConflictResolutionResolver::~ConflictResolutionResolver() {}
+
+ConflictResolution ConflictResolutionResolver::Resolve(
+      SyncFileType local_file_type,
+      const base::Time& local_update_time,
+      SyncFileType remote_file_type,
+      const base::Time& remote_update_time) {
+  // Currently we always prioritize directories over files regardless of
+  // conflict resolution policy.
+  if (remote_file_type == SYNC_FILE_TYPE_DIRECTORY)
+    return CONFLICT_RESOLUTION_REMOTE_WIN;
+
+  if (policy_ == CONFLICT_RESOLUTION_POLICY_MANUAL)
+    return CONFLICT_RESOLUTION_MARK_CONFLICT;
+
+  // Remote time is null, cannot determine the resolution.
+  if (remote_update_time.is_null())
+    return CONFLICT_RESOLUTION_UNKNOWN;
+
+  // Local time should be always given.
+  DCHECK(!local_update_time.is_null());
+
+  DCHECK_EQ(CONFLICT_RESOLUTION_POLICY_LAST_WRITE_WIN, policy_);
+  if (local_update_time >= remote_update_time ||
+      remote_file_type == SYNC_FILE_TYPE_UNKNOWN) {
+    return CONFLICT_RESOLUTION_LOCAL_WIN;
+  }
+
+  return CONFLICT_RESOLUTION_REMOTE_WIN;
+}
+
+}  // namespace sync_file_system
diff --git a/chrome/browser/sync_file_system/conflict_resolution_resolver.h b/chrome/browser/sync_file_system/conflict_resolution_resolver.h
new file mode 100644
index 0000000..da07149
--- /dev/null
+++ b/chrome/browser/sync_file_system/conflict_resolution_resolver.h
@@ -0,0 +1,48 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SYNC_FILE_SYSTEM_CONFLICT_RESOLUTION_RESOLVER_H_
+#define CHROME_BROWSER_SYNC_FILE_SYSTEM_CONFLICT_RESOLUTION_RESOLVER_H_
+
+#include "chrome/browser/sync_file_system/conflict_resolution_policy.h"
+#include "webkit/browser/fileapi/syncable/sync_file_type.h"
+
+namespace base {
+class Time;
+}
+
+namespace sync_file_system {
+
+enum ConflictResolution {
+  CONFLICT_RESOLUTION_UNKNOWN,
+  CONFLICT_RESOLUTION_MARK_CONFLICT,
+  CONFLICT_RESOLUTION_LOCAL_WIN,
+  CONFLICT_RESOLUTION_REMOTE_WIN,
+};
+
+class ConflictResolutionResolver {
+ public:
+  explicit ConflictResolutionResolver(ConflictResolutionPolicy policy);
+  ~ConflictResolutionResolver();
+
+  // Determine the ConflictResolution.
+  // This may return CONFLICT_RESOLUTION_UNKNOWN if NULL |remote_update_time|
+  // is given.
+  // It is invalid to give NULL |local_update_time|.
+  ConflictResolution Resolve(
+        SyncFileType local_file_type,
+        const base::Time& local_update_time,
+        SyncFileType remote_file_type,
+        const base::Time& remote_update_time);
+
+  ConflictResolutionPolicy policy() const { return policy_; }
+  void set_policy(ConflictResolutionPolicy policy) { policy_ = policy; }
+
+ private:
+  ConflictResolutionPolicy policy_;
+};
+
+}  // namespace sync_file_system
+
+#endif  // CHROME_BROWSER_SYNC_FILE_SYSTEM_CONFLICT_RESOLUTION_RESOLVER_H_
diff --git a/chrome/browser/sync_file_system/drive/api_util.cc b/chrome/browser/sync_file_system/drive/api_util.cc
deleted file mode 100644
index 01aaa41..0000000
--- a/chrome/browser/sync_file_system/drive/api_util.cc
+++ /dev/null
@@ -1,1077 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/sync_file_system/drive/api_util.h"
-
-#include <algorithm>
-#include <functional>
-#include <sstream>
-#include <string>
-
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/values.h"
-#include "chrome/browser/drive/drive_api_service.h"
-#include "chrome/browser/drive/drive_uploader.h"
-#include "chrome/browser/drive/gdata_wapi_service.h"
-#include "chrome/browser/google_apis/drive_api_parser.h"
-#include "chrome/browser/google_apis/drive_api_util.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/sync_file_system/drive_file_sync_util.h"
-#include "chrome/browser/sync_file_system/logger.h"
-#include "chrome/common/extensions/extension.h"
-#include "extensions/common/constants.h"
-#include "net/base/mime_util.h"
-#include "webkit/browser/fileapi/syncable/syncable_file_system_util.h"
-
-namespace sync_file_system {
-namespace drive {
-
-namespace {
-
-enum ParentType {
-  PARENT_TYPE_ROOT_OR_EMPTY,
-  PARENT_TYPE_DIRECTORY,
-};
-
-const char kSyncRootDirectoryName[] = "Chrome Syncable FileSystem";
-const char kSyncRootDirectoryNameDev[] = "Chrome Syncable FileSystem Dev";
-const char kMimeTypeOctetStream[] = "application/octet-stream";
-
-// This path is not actually used but is required by DriveUploaderInterface.
-const base::FilePath::CharType kDummyDrivePath[] =
-    FILE_PATH_LITERAL("/dummy/drive/path");
-
-const char kFakeServerBaseUrl[] = "https://fake_server/";
-
-void EmptyGDataErrorCodeCallback(google_apis::GDataErrorCode error) {}
-
-bool HasParentLinkTo(const ScopedVector<google_apis::Link>& links,
-                     const std::string& parent_resource_id,
-                     ParentType parent_type) {
-  bool has_parent = false;
-
-  for (ScopedVector<google_apis::Link>::const_iterator itr = links.begin();
-       itr != links.end(); ++itr) {
-    if ((*itr)->type() == google_apis::Link::LINK_PARENT) {
-      has_parent = true;
-      if (google_apis::drive::util::ExtractResourceIdFromUrl((*itr)->href()) ==
-          parent_resource_id)
-        return true;
-    }
-  }
-
-  return parent_type == PARENT_TYPE_ROOT_OR_EMPTY && !has_parent;
-}
-
-struct TitleAndParentQuery
-    : std::unary_function<const google_apis::ResourceEntry*, bool> {
-  TitleAndParentQuery(const std::string& title,
-                      const std::string& parent_resource_id,
-                      ParentType parent_type)
-      : title(title),
-        parent_resource_id(parent_resource_id),
-        parent_type(parent_type) {}
-
-  bool operator()(const google_apis::ResourceEntry* entry) const {
-    return entry->title() == title &&
-           HasParentLinkTo(entry->links(), parent_resource_id, parent_type);
-  }
-
-  const std::string& title;
-  const std::string& parent_resource_id;
-  ParentType parent_type;
-};
-
-void FilterEntriesByTitleAndParent(
-    ScopedVector<google_apis::ResourceEntry>* entries,
-    const std::string& title,
-    const std::string& parent_resource_id,
-    ParentType parent_type) {
-  typedef ScopedVector<google_apis::ResourceEntry>::iterator iterator;
-  iterator itr = std::partition(entries->begin(),
-                                entries->end(),
-                                TitleAndParentQuery(title,
-                                                    parent_resource_id,
-                                                    parent_type));
-  entries->erase(itr, entries->end());
-}
-
-google_apis::ResourceEntry* GetDocumentByTitleAndParent(
-    const ScopedVector<google_apis::ResourceEntry>& entries,
-    const std::string& title,
-    const std::string& parent_resource_id,
-    ParentType parent_type) {
-  typedef ScopedVector<google_apis::ResourceEntry>::const_iterator iterator;
-  iterator found =
-      std::find_if(entries.begin(),
-                   entries.end(),
-                   TitleAndParentQuery(title, parent_resource_id, parent_type));
-  if (found != entries.end())
-    return *found;
-  return NULL;
-}
-
-void EntryAdapterForEnsureTitleUniqueness(
-    scoped_ptr<google_apis::ResourceEntry> entry,
-    const APIUtil::EnsureUniquenessCallback& callback,
-    APIUtil::EnsureUniquenessStatus status,
-    google_apis::GDataErrorCode error) {
-  callback.Run(error, status, entry.Pass());
-}
-
-void UploadResultAdapter(const APIUtil::ResourceEntryCallback& callback,
-                         google_apis::GDataErrorCode error,
-                         const GURL& upload_location,
-                         scoped_ptr<google_apis::ResourceEntry> entry) {
-  callback.Run(error, entry.Pass());
-}
-
-}  // namespace
-
-APIUtil::APIUtil(Profile* profile)
-    : wapi_url_generator_(
-          GURL(google_apis::GDataWapiUrlGenerator::kBaseUrlForProduction)),
-      drive_api_url_generator_(
-          GURL(google_apis::DriveApiUrlGenerator::kBaseUrlForProduction)),
-      upload_next_key_(0) {
-  if (IsDriveAPIDisabled()) {
-    drive_service_.reset(new google_apis::GDataWapiService(
-        profile->GetRequestContext(),
-        GURL(google_apis::GDataWapiUrlGenerator::kBaseUrlForProduction),
-        std::string() /* custom_user_agent */));
-  } else {
-    drive_service_.reset(new google_apis::DriveAPIService(
-        profile->GetRequestContext(),
-        GURL(google_apis::DriveApiUrlGenerator::kBaseUrlForProduction),
-        std::string() /* custom_user_agent */));
-  }
-
-  drive_service_->Initialize(profile);
-  drive_service_->AddObserver(this);
-  net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
-
-  drive_uploader_.reset(new google_apis::DriveUploader(drive_service_.get()));
-}
-
-scoped_ptr<APIUtil> APIUtil::CreateForTesting(
-    Profile* profile,
-    scoped_ptr<google_apis::DriveServiceInterface> drive_service,
-    scoped_ptr<google_apis::DriveUploaderInterface> drive_uploader) {
-  return make_scoped_ptr(new APIUtil(
-      profile,
-      GURL(kFakeServerBaseUrl),
-      drive_service.Pass(),
-      drive_uploader.Pass()));
-}
-
-APIUtil::APIUtil(Profile* profile,
-                 const GURL& base_url,
-                 scoped_ptr<google_apis::DriveServiceInterface> drive_service,
-                 scoped_ptr<google_apis::DriveUploaderInterface> drive_uploader)
-    : wapi_url_generator_(base_url),
-      drive_api_url_generator_(base_url),
-      upload_next_key_(0) {
-  drive_service_ = drive_service.Pass();
-  drive_service_->Initialize(profile);
-  drive_service_->AddObserver(this);
-  net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
-
-  drive_uploader_ = drive_uploader.Pass();
-}
-
-APIUtil::~APIUtil() {
-  DCHECK(CalledOnValidThread());
-  net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
-  drive_service_->RemoveObserver(this);
-}
-
-void APIUtil::AddObserver(APIUtilObserver* observer) {
-  DCHECK(CalledOnValidThread());
-  observers_.AddObserver(observer);
-}
-
-void APIUtil::RemoveObserver(APIUtilObserver* observer) {
-  DCHECK(CalledOnValidThread());
-  observers_.RemoveObserver(observer);
-}
-
-void APIUtil::GetDriveRootResourceId(const GDataErrorCallback& callback) {
-  DCHECK(CalledOnValidThread());
-  DCHECK(!IsDriveAPIDisabled());
-  DVLOG(2) << "Getting resource id for Drive root";
-
-  drive_service_->GetAboutResource(
-      base::Bind(&APIUtil::DidGetDriveRootResourceId, AsWeakPtr(), callback));
-}
-
-void APIUtil::DidGetDriveRootResourceId(
-    const GDataErrorCallback& callback,
-    google_apis::GDataErrorCode error,
-    scoped_ptr<google_apis::AboutResource> about_resource) {
-  DCHECK(CalledOnValidThread());
-
-  if (error != google_apis::HTTP_SUCCESS) {
-    DVLOG(2) << "Error on getting resource id for Drive root: " << error;
-    callback.Run(error);
-    return;
-  }
-
-  DCHECK(about_resource);
-  root_resource_id_ = about_resource->root_folder_id();
-  DCHECK(!root_resource_id_.empty());
-  DVLOG(2) << "Got resource id for Drive root: " << root_resource_id_;
-  callback.Run(error);
-}
-
-void APIUtil::GetDriveDirectoryForSyncRoot(const ResourceIdCallback& callback) {
-  DCHECK(CalledOnValidThread());
-
-  if (GetRootResourceId().empty()) {
-    GetDriveRootResourceId(
-        base::Bind(&APIUtil::DidGetDriveRootResourceIdForGetSyncRoot,
-                   AsWeakPtr(), callback));
-    return;
-  }
-
-  DVLOG(2) << "Getting Drive directory for SyncRoot";
-  std::string directory_name(GetSyncRootDirectoryName());
-  SearchByTitle(directory_name,
-                std::string(),
-                base::Bind(&APIUtil::DidGetDirectory,
-                           AsWeakPtr(),
-                           std::string(),
-                           directory_name,
-                           callback));
-}
-
-void APIUtil::DidGetDriveRootResourceIdForGetSyncRoot(
-    const ResourceIdCallback& callback,
-    google_apis::GDataErrorCode error) {
-  DCHECK(CalledOnValidThread());
-  if (error != google_apis::HTTP_SUCCESS) {
-    DVLOG(2) << "Error on getting Drive directory for SyncRoot: " << error;
-    callback.Run(error, std::string());
-    return;
-  }
-  GetDriveDirectoryForSyncRoot(callback);
-}
-
-void APIUtil::GetDriveDirectoryForOrigin(
-    const std::string& sync_root_resource_id,
-    const GURL& origin,
-    const ResourceIdCallback& callback) {
-  DCHECK(CalledOnValidThread());
-  DVLOG(2) << "Getting Drive directory for Origin: " << origin;
-
-  std::string directory_name(OriginToDirectoryTitle(origin));
-  SearchByTitle(directory_name,
-                sync_root_resource_id,
-                base::Bind(&APIUtil::DidGetDirectory,
-                           AsWeakPtr(),
-                           sync_root_resource_id,
-                           directory_name,
-                           callback));
-}
-
-void APIUtil::DidGetDirectory(const std::string& parent_resource_id,
-                              const std::string& directory_name,
-                              const ResourceIdCallback& callback,
-                              google_apis::GDataErrorCode error,
-                              scoped_ptr<google_apis::ResourceList> feed) {
-  DCHECK(CalledOnValidThread());
-  DCHECK(IsStringASCII(directory_name));
-
-  if (error != google_apis::HTTP_SUCCESS) {
-    DVLOG(2) << "Error on getting Drive directory: " << error;
-    callback.Run(error, std::string());
-    return;
-  }
-
-  std::string resource_id;
-  ParentType parent_type = PARENT_TYPE_DIRECTORY;
-  if (parent_resource_id.empty()) {
-    resource_id = GetRootResourceId();
-    DCHECK(!resource_id.empty());
-    parent_type = PARENT_TYPE_ROOT_OR_EMPTY;
-  } else {
-    resource_id = parent_resource_id;
-  }
-  std::string title(directory_name);
-  google_apis::ResourceEntry* entry = GetDocumentByTitleAndParent(
-      feed->entries(), title, resource_id, parent_type);
-  if (!entry) {
-    DVLOG(2) << "Directory not found. Creating: " << directory_name;
-    drive_service_->AddNewDirectory(resource_id,
-                                    directory_name,
-                                    base::Bind(&APIUtil::DidCreateDirectory,
-                                               AsWeakPtr(),
-                                               parent_resource_id,
-                                               title,
-                                               callback));
-    return;
-  }
-  DVLOG(2) << "Found Drive directory.";
-
-  // TODO(tzik): Handle error.
-  DCHECK_EQ(google_apis::ENTRY_KIND_FOLDER, entry->kind());
-  DCHECK_EQ(directory_name, entry->title());
-
-  if (entry->title() == GetSyncRootDirectoryName())
-    EnsureSyncRootIsNotInMyDrive(entry->resource_id());
-
-  callback.Run(error, entry->resource_id());
-}
-
-void APIUtil::DidCreateDirectory(const std::string& parent_resource_id,
-                                 const std::string& title,
-                                 const ResourceIdCallback& callback,
-                                 google_apis::GDataErrorCode error,
-                                 scoped_ptr<google_apis::ResourceEntry> entry) {
-  DCHECK(CalledOnValidThread());
-
-  if (error != google_apis::HTTP_SUCCESS &&
-      error != google_apis::HTTP_CREATED) {
-    DVLOG(2) << "Error on creating Drive directory: " << error;
-    callback.Run(error, std::string());
-    return;
-  }
-  DVLOG(2) << "Created Drive directory.";
-
-  DCHECK(entry);
-  // Check if any other client creates a directory with same title.
-  EnsureTitleUniqueness(
-      parent_resource_id,
-      title,
-      base::Bind(&APIUtil::DidEnsureUniquenessForCreateDirectory,
-                 AsWeakPtr(),
-                 callback));
-}
-
-void APIUtil::DidEnsureUniquenessForCreateDirectory(
-    const ResourceIdCallback& callback,
-    google_apis::GDataErrorCode error,
-    EnsureUniquenessStatus status,
-    scoped_ptr<google_apis::ResourceEntry> entry) {
-  DCHECK(CalledOnValidThread());
-
-  if (error != google_apis::HTTP_SUCCESS) {
-    callback.Run(error, std::string());
-    return;
-  }
-
-  if (status == NO_DUPLICATES_FOUND)
-    error = google_apis::HTTP_CREATED;
-
-  DCHECK(entry) << "No entry: " << error;
-
-  if (!entry->is_folder()) {
-    // TODO(kinuko): Fix this. http://crbug.com/237090
-    util::Log(
-        logging::LOG_ERROR,
-        FROM_HERE,
-        "A file is left for CreateDirectory due to file-folder conflict!");
-    callback.Run(google_apis::HTTP_CONFLICT, std::string());
-    return;
-  }
-
-  if (entry->title() == GetSyncRootDirectoryName())
-    EnsureSyncRootIsNotInMyDrive(entry->resource_id());
-
-  callback.Run(error, entry->resource_id());
-}
-
-void APIUtil::GetLargestChangeStamp(const ChangeStampCallback& callback) {
-  DCHECK(CalledOnValidThread());
-  DVLOG(2) << "Getting largest change id";
-
-  drive_service_->GetAboutResource(
-      base::Bind(&APIUtil::DidGetLargestChangeStamp, AsWeakPtr(), callback));
-}
-
-void APIUtil::GetResourceEntry(const std::string& resource_id,
-                               const ResourceEntryCallback& callback) {
-  DCHECK(CalledOnValidThread());
-  DVLOG(2) << "Getting ResourceEntry for: " << resource_id;
-
-  drive_service_->GetResourceEntry(
-      resource_id,
-      base::Bind(&APIUtil::DidGetResourceEntry, AsWeakPtr(), callback));
-}
-
-void APIUtil::DidGetLargestChangeStamp(
-    const ChangeStampCallback& callback,
-    google_apis::GDataErrorCode error,
-    scoped_ptr<google_apis::AboutResource> about_resource) {
-  DCHECK(CalledOnValidThread());
-
-  int64 largest_change_id = 0;
-  if (error == google_apis::HTTP_SUCCESS) {
-    DCHECK(about_resource);
-    largest_change_id = about_resource->largest_change_id();
-    root_resource_id_ = about_resource->root_folder_id();
-    DVLOG(2) << "Got largest change id: " << largest_change_id;
-  } else {
-    DVLOG(2) << "Error on getting largest change id: " << error;
-  }
-
-  callback.Run(error, largest_change_id);
-}
-
-void APIUtil::SearchByTitle(const std::string& title,
-                            const std::string& directory_resource_id,
-                            const ResourceListCallback& callback) {
-  DCHECK(CalledOnValidThread());
-  DCHECK(!title.empty());
-  DVLOG(2) << "Searching resources in the directory [" << directory_resource_id
-           << "] with title [" << title << "]";
-
-  drive_service_->SearchByTitle(
-      title,
-      directory_resource_id,
-      base::Bind(&APIUtil::DidGetResourceList, AsWeakPtr(), callback));
-}
-
-void APIUtil::ListFiles(const std::string& directory_resource_id,
-                        const ResourceListCallback& callback) {
-  DCHECK(CalledOnValidThread());
-  DVLOG(2) << "Listing resources in the directory [" << directory_resource_id
-           << "]";
-
-  drive_service_->GetResourceListInDirectory(directory_resource_id, callback);
-}
-
-void APIUtil::ListChanges(int64 start_changestamp,
-                          const ResourceListCallback& callback) {
-  DCHECK(CalledOnValidThread());
-  DVLOG(2) << "Listing changes since: " << start_changestamp;
-
-  drive_service_->GetChangeList(
-      start_changestamp,
-      base::Bind(&APIUtil::DidGetResourceList, AsWeakPtr(), callback));
-}
-
-void APIUtil::ContinueListing(const GURL& feed_url,
-                              const ResourceListCallback& callback) {
-  DCHECK(CalledOnValidThread());
-  DVLOG(2) << "Continue listing on feed: " << feed_url;
-
-  drive_service_->ContinueGetResourceList(
-      feed_url,
-      base::Bind(&APIUtil::DidGetResourceList, AsWeakPtr(), callback));
-}
-
-void APIUtil::DownloadFile(const std::string& resource_id,
-                           const std::string& local_file_md5,
-                           const base::FilePath& local_file_path,
-                           const DownloadFileCallback& callback) {
-  DCHECK(CalledOnValidThread());
-  DVLOG(2) << "Downloading file [" << resource_id << "]";
-
-  drive_service_->GetResourceEntry(
-      resource_id,
-      base::Bind(&APIUtil::DidGetResourceEntry,
-                 AsWeakPtr(),
-                 base::Bind(&APIUtil::DownloadFileInternal,
-                            AsWeakPtr(),
-                            local_file_md5,
-                            local_file_path,
-                            callback)));
-}
-
-void APIUtil::UploadNewFile(const std::string& directory_resource_id,
-                            const base::FilePath& local_file_path,
-                            const std::string& title,
-                            const UploadFileCallback& callback) {
-  DCHECK(CalledOnValidThread());
-  DVLOG(2) << "Uploading new file into the directory [" << directory_resource_id
-           << "] with title [" << title << "]";
-
-  std::string mime_type;
-  if (!net::GetWellKnownMimeTypeFromExtension(local_file_path.Extension(),
-                                              &mime_type))
-    mime_type = kMimeTypeOctetStream;
-
-  UploadKey upload_key = RegisterUploadCallback(callback);
-  ResourceEntryCallback did_upload_callback =
-      base::Bind(&APIUtil::DidUploadNewFile,
-                 AsWeakPtr(),
-                 directory_resource_id,
-                 title,
-                 upload_key);
-  drive_uploader_->UploadNewFile(
-      directory_resource_id,
-      base::FilePath(kDummyDrivePath),
-      local_file_path,
-      title,
-      mime_type,
-      base::Bind(&UploadResultAdapter, did_upload_callback),
-      google_apis::ProgressCallback());
-}
-
-void APIUtil::UploadExistingFile(const std::string& resource_id,
-                                 const std::string& remote_file_md5,
-                                 const base::FilePath& local_file_path,
-                                 const UploadFileCallback& callback) {
-  DCHECK(CalledOnValidThread());
-  DVLOG(2) << "Uploading existing file [" << resource_id << "]";
-  drive_service_->GetResourceEntry(
-      resource_id,
-      base::Bind(&APIUtil::DidGetResourceEntry,
-                 AsWeakPtr(),
-                 base::Bind(&APIUtil::UploadExistingFileInternal,
-                            AsWeakPtr(),
-                            remote_file_md5,
-                            local_file_path,
-                            callback)));
-}
-
-void APIUtil::CreateDirectory(const std::string& parent_resource_id,
-                              const std::string& title,
-                              const ResourceIdCallback& callback) {
-  DCHECK(CalledOnValidThread());
-  // TODO(kinuko): This will call EnsureTitleUniqueness and will delete
-  // directories if there're duplicated directories. This must be ok
-  // for current design but we'll need to merge directories when we support
-  // 'real' directories.
-  drive_service_->AddNewDirectory(parent_resource_id,
-                                  title,
-                                  base::Bind(&APIUtil::DidCreateDirectory,
-                                             AsWeakPtr(),
-                                             parent_resource_id,
-                                             title,
-                                             callback));
-}
-
-void APIUtil::DeleteFile(const std::string& resource_id,
-                         const std::string& remote_file_md5,
-                         const GDataErrorCallback& callback) {
-  DCHECK(CalledOnValidThread());
-  DVLOG(2) << "Deleting file: " << resource_id;
-
-  // Load actual remote_file_md5 to check for conflict before deletion.
-  if (!remote_file_md5.empty()) {
-    drive_service_->GetResourceEntry(
-        resource_id,
-        base::Bind(&APIUtil::DidGetResourceEntry,
-                   AsWeakPtr(),
-                   base::Bind(&APIUtil::DeleteFileInternal,
-                              AsWeakPtr(),
-                              remote_file_md5,
-                              callback)));
-    return;
-  }
-
-  // Expected remote_file_md5 is empty so do a force delete.
-  drive_service_->DeleteResource(
-      resource_id,
-      std::string(),
-      base::Bind(&APIUtil::DidDeleteFile, AsWeakPtr(), callback));
-  return;
-}
-
-GURL APIUtil::ResourceIdToResourceLink(const std::string& resource_id) const {
-  return IsDriveAPIDisabled()
-      ? wapi_url_generator_.GenerateEditUrl(resource_id)
-      : drive_api_url_generator_.GetFileUrl(resource_id);
-}
-
-void APIUtil::EnsureSyncRootIsNotInMyDrive(
-    const std::string& sync_root_resource_id) {
-  DCHECK(CalledOnValidThread());
-
-  if (GetRootResourceId().empty()) {
-    GetDriveRootResourceId(
-        base::Bind(&APIUtil::DidGetDriveRootResourceIdForEnsureSyncRoot,
-                   AsWeakPtr(), sync_root_resource_id));
-    return;
-  }
-
-  DVLOG(2) << "Ensuring the sync root directory is not in 'My Drive'.";
-  drive_service_->RemoveResourceFromDirectory(
-      GetRootResourceId(),
-      sync_root_resource_id,
-      base::Bind(&EmptyGDataErrorCodeCallback));
-}
-
-void APIUtil::DidGetDriveRootResourceIdForEnsureSyncRoot(
-    const std::string& sync_root_resource_id,
-    google_apis::GDataErrorCode error) {
-  DCHECK(CalledOnValidThread());
-
-  if (error != google_apis::HTTP_SUCCESS) {
-    DVLOG(2) << "Error on ensuring the sync root directory is not in"
-             << " 'My Drive': " << error;
-    // Give up ensuring the sync root directory is not in 'My Drive'. This will
-    // be retried at some point.
-    return;
-  }
-
-  DCHECK(!GetRootResourceId().empty());
-  EnsureSyncRootIsNotInMyDrive(sync_root_resource_id);
-}
-
-// static
-// TODO(calvinlo): Delete this when Sync Directory Operations are supported by
-// default.
-std::string APIUtil::GetSyncRootDirectoryName() {
-  return IsSyncFSDirectoryOperationEnabled() ? kSyncRootDirectoryNameDev
-                                             : kSyncRootDirectoryName;
-}
-
-// static
-std::string APIUtil::OriginToDirectoryTitle(const GURL& origin) {
-  DCHECK(origin.SchemeIs(extensions::kExtensionScheme));
-  return origin.host();
-}
-
-// static
-GURL APIUtil::DirectoryTitleToOrigin(const std::string& title) {
-  return extensions::Extension::GetBaseURLFromExtensionId(title);
-}
-
-void APIUtil::OnReadyToSendRequests() {
-  DCHECK(CalledOnValidThread());
-  FOR_EACH_OBSERVER(APIUtilObserver, observers_, OnAuthenticated());
-}
-
-void APIUtil::OnConnectionTypeChanged(
-    net::NetworkChangeNotifier::ConnectionType type) {
-  DCHECK(CalledOnValidThread());
-  if (type != net::NetworkChangeNotifier::CONNECTION_NONE) {
-    FOR_EACH_OBSERVER(APIUtilObserver, observers_, OnNetworkConnected());
-    return;
-  }
-  // We're now disconnected, reset the drive_uploader_ to force stop
-  // uploading, otherwise the uploader may get stuck.
-  // TODO(kinuko): Check the uploader behavior if it's the expected behavior
-  // (http://crbug.com/223818)
-  CancelAllUploads(google_apis::GDATA_NO_CONNECTION);
-}
-
-void APIUtil::DidGetResourceList(
-    const ResourceListCallback& callback,
-    google_apis::GDataErrorCode error,
-    scoped_ptr<google_apis::ResourceList> resource_list) {
-  DCHECK(CalledOnValidThread());
-
-  if (error != google_apis::HTTP_SUCCESS) {
-    DVLOG(2) << "Error on listing resource: " << error;
-    callback.Run(error, scoped_ptr<google_apis::ResourceList>());
-    return;
-  }
-
-  DVLOG(2) << "Got resource list";
-  DCHECK(resource_list);
-  callback.Run(error, resource_list.Pass());
-}
-
-void APIUtil::DidGetResourceEntry(
-    const ResourceEntryCallback& callback,
-    google_apis::GDataErrorCode error,
-    scoped_ptr<google_apis::ResourceEntry> entry) {
-  DCHECK(CalledOnValidThread());
-
-  if (error != google_apis::HTTP_SUCCESS) {
-    DVLOG(2) << "Error on getting resource entry:" << error;
-    callback.Run(error, scoped_ptr<google_apis::ResourceEntry>());
-    return;
-  }
-
-  DVLOG(2) << "Got resource entry";
-  DCHECK(entry);
-  callback.Run(error, entry.Pass());
-}
-
-void APIUtil::DownloadFileInternal(
-    const std::string& local_file_md5,
-    const base::FilePath& local_file_path,
-    const DownloadFileCallback& callback,
-    google_apis::GDataErrorCode error,
-    scoped_ptr<google_apis::ResourceEntry> entry) {
-  DCHECK(CalledOnValidThread());
-
-  if (error != google_apis::HTTP_SUCCESS) {
-    DVLOG(2) << "Error on getting resource entry for download";
-    callback.Run(error, std::string(), 0, base::Time());
-    return;
-  }
-  DCHECK(entry);
-
-  DVLOG(2) << "Got resource entry for download";
-  // If local file and remote file are same, cancel the download.
-  if (local_file_md5 == entry->file_md5()) {
-    callback.Run(google_apis::HTTP_NOT_MODIFIED,
-                 local_file_md5,
-                 entry->file_size(),
-                 entry->updated_time());
-    return;
-  }
-
-  DVLOG(2) << "Downloading file: " << entry->resource_id();
-  const GURL& download_url = entry->download_url();
-  drive_service_->DownloadFile(base::FilePath(kDummyDrivePath),
-                               local_file_path,
-                               download_url,
-                               base::Bind(&APIUtil::DidDownloadFile,
-                                          AsWeakPtr(),
-                                          base::Passed(&entry),
-                                          callback),
-                               google_apis::GetContentCallback(),
-                               google_apis::ProgressCallback());
-}
-
-void APIUtil::DidDownloadFile(scoped_ptr<google_apis::ResourceEntry> entry,
-                              const DownloadFileCallback& callback,
-                              google_apis::GDataErrorCode error,
-                              const base::FilePath& downloaded_file_path) {
-  DCHECK(CalledOnValidThread());
-  if (error == google_apis::HTTP_SUCCESS)
-    DVLOG(2) << "Download completed";
-  else
-    DVLOG(2) << "Error on downloading file: " << error;
-
-  callback.Run(
-      error, entry->file_md5(), entry->file_size(), entry->updated_time());
-}
-
-void APIUtil::DidUploadNewFile(const std::string& parent_resource_id,
-                               const std::string& title,
-                               UploadKey upload_key,
-                               google_apis::GDataErrorCode error,
-                               scoped_ptr<google_apis::ResourceEntry> entry) {
-  UploadFileCallback callback = GetAndUnregisterUploadCallback(upload_key);
-  DCHECK(!callback.is_null());
-  if (error != google_apis::HTTP_SUCCESS &&
-      error != google_apis::HTTP_CREATED) {
-    DVLOG(2) << "Error on uploading new file: " << error;
-    callback.Run(error, std::string(), std::string());
-    return;
-  }
-
-  DVLOG(2) << "Upload completed";
-  EnsureTitleUniqueness(parent_resource_id,
-                        title,
-                        base::Bind(&APIUtil::DidEnsureUniquenessForCreateFile,
-                                   AsWeakPtr(),
-                                   entry->resource_id(),
-                                   callback));
-}
-
-void APIUtil::DidEnsureUniquenessForCreateFile(
-    const std::string& expected_resource_id,
-    const UploadFileCallback& callback,
-    google_apis::GDataErrorCode error,
-    EnsureUniquenessStatus status,
-    scoped_ptr<google_apis::ResourceEntry> entry) {
-  if (error != google_apis::HTTP_SUCCESS) {
-    DVLOG(2) << "Error on uploading new file: " << error;
-    callback.Run(error, std::string(), std::string());
-    return;
-  }
-
-  switch (status) {
-    case NO_DUPLICATES_FOUND:
-      // The file was uploaded successfully and no conflict was detected.
-      DCHECK(entry);
-      DVLOG(2) << "No conflict detected on uploading new file";
-      callback.Run(
-          google_apis::HTTP_CREATED, entry->resource_id(), entry->file_md5());
-      return;
-
-    case RESOLVED_DUPLICATES:
-      // The file was uploaded successfully but a conflict was detected.
-      // The duplicated file was deleted successfully.
-      DCHECK(entry);
-      if (entry->resource_id() != expected_resource_id) {
-        // TODO(kinuko): We should check local vs remote md5 here.
-        DVLOG(2) << "Conflict detected on uploading new file";
-        callback.Run(google_apis::HTTP_CONFLICT,
-                     entry->resource_id(),
-                     entry->file_md5());
-        return;
-      }
-
-      DVLOG(2) << "Conflict detected on uploading new file and resolved";
-      callback.Run(
-          google_apis::HTTP_CREATED, entry->resource_id(), entry->file_md5());
-      return;
-
-    default:
-      NOTREACHED() << "Unknown status from EnsureTitleUniqueness:" << status
-                   << " for " << expected_resource_id;
-  }
-}
-
-void APIUtil::UploadExistingFileInternal(
-    const std::string& remote_file_md5,
-    const base::FilePath& local_file_path,
-    const UploadFileCallback& callback,
-    google_apis::GDataErrorCode error,
-    scoped_ptr<google_apis::ResourceEntry> entry) {
-  DCHECK(CalledOnValidThread());
-
-  if (error != google_apis::HTTP_SUCCESS) {
-    DVLOG(2) << "Error on uploading existing file: " << error;
-    callback.Run(error, std::string(), std::string());
-    return;
-  }
-  DCHECK(entry);
-
-  // If remote file's hash value is different from the expected one, conflict
-  // might have occurred.
-  if (!remote_file_md5.empty() && remote_file_md5 != entry->file_md5()) {
-    DVLOG(2) << "Conflict detected before uploading existing file";
-    callback.Run(google_apis::HTTP_CONFLICT, std::string(), std::string());
-    return;
-  }
-
-  std::string mime_type;
-  if (!net::GetWellKnownMimeTypeFromExtension(local_file_path.Extension(),
-                                              &mime_type))
-    mime_type = kMimeTypeOctetStream;
-
-  UploadKey upload_key = RegisterUploadCallback(callback);
-  ResourceEntryCallback did_upload_callback =
-      base::Bind(&APIUtil::DidUploadExistingFile, AsWeakPtr(), upload_key);
-  drive_uploader_->UploadExistingFile(
-      entry->resource_id(),
-      base::FilePath(kDummyDrivePath),
-      local_file_path,
-      mime_type,
-      entry->etag(),
-      base::Bind(&UploadResultAdapter, did_upload_callback),
-      google_apis::ProgressCallback());
-}
-
-bool APIUtil::IsAuthenticated() const {
-  return drive_service_->HasRefreshToken();
-}
-
-void APIUtil::DidUploadExistingFile(
-    UploadKey upload_key,
-    google_apis::GDataErrorCode error,
-    scoped_ptr<google_apis::ResourceEntry> entry) {
-  DCHECK(CalledOnValidThread());
-  UploadFileCallback callback = GetAndUnregisterUploadCallback(upload_key);
-  DCHECK(!callback.is_null());
-  if (error != google_apis::HTTP_SUCCESS) {
-    DVLOG(2) << "Error on uploading existing file: " << error;
-    callback.Run(error, std::string(), std::string());
-    return;
-  }
-
-  DCHECK(entry);
-  DVLOG(2) << "Upload completed";
-  callback.Run(error, entry->resource_id(), entry->file_md5());
-}
-
-void APIUtil::DeleteFileInternal(const std::string& remote_file_md5,
-                                 const GDataErrorCallback& callback,
-                                 google_apis::GDataErrorCode error,
-                                 scoped_ptr<google_apis::ResourceEntry> entry) {
-  DCHECK(CalledOnValidThread());
-
-  if (error != google_apis::HTTP_SUCCESS) {
-    DVLOG(2) << "Error on getting resource entry for deleting file: " << error;
-    callback.Run(error);
-    return;
-  }
-  DCHECK(entry);
-
-  // If remote file's hash value is different from the expected one, conflict
-  // might have occurred.
-  if (!remote_file_md5.empty() && remote_file_md5 != entry->file_md5()) {
-    DVLOG(2) << "Conflict detected before deleting file";
-    callback.Run(google_apis::HTTP_CONFLICT);
-    return;
-  }
-  DVLOG(2) << "Got resource entry for deleting file";
-
-  // Move the file to trash (don't delete it completely).
-  drive_service_->DeleteResource(
-      entry->resource_id(),
-      entry->etag(),
-      base::Bind(&APIUtil::DidDeleteFile, AsWeakPtr(), callback));
-}
-
-void APIUtil::DidDeleteFile(const GDataErrorCallback& callback,
-                            google_apis::GDataErrorCode error) {
-  DCHECK(CalledOnValidThread());
-  if (error == google_apis::HTTP_SUCCESS)
-    DVLOG(2) << "Deletion completed";
-  else
-    DVLOG(2) << "Error on deleting file: " << error;
-
-  callback.Run(error);
-}
-
-void APIUtil::EnsureTitleUniqueness(const std::string& parent_resource_id,
-                                    const std::string& expected_title,
-                                    const EnsureUniquenessCallback& callback) {
-  DCHECK(CalledOnValidThread());
-  DVLOG(2) << "Checking if there's no conflict on entry creation";
-
-  const google_apis::GetResourceListCallback& bound_callback =
-      base::Bind(&APIUtil::DidListEntriesToEnsureUniqueness,
-                 AsWeakPtr(),
-                 parent_resource_id,
-                 expected_title,
-                 callback);
-
-  SearchByTitle(expected_title, parent_resource_id, bound_callback);
-}
-
-void APIUtil::DidListEntriesToEnsureUniqueness(
-    const std::string& parent_resource_id,
-    const std::string& expected_title,
-    const EnsureUniquenessCallback& callback,
-    google_apis::GDataErrorCode error,
-    scoped_ptr<google_apis::ResourceList> feed) {
-  DCHECK(CalledOnValidThread());
-
-  if (error != google_apis::HTTP_SUCCESS) {
-    DVLOG(2) << "Error on listing resource for ensuring title uniqueness";
-    callback.Run(
-        error, NO_DUPLICATES_FOUND, scoped_ptr<google_apis::ResourceEntry>());
-    return;
-  }
-  DVLOG(2) << "Got resource list for ensuring title uniqueness";
-
-  // This filtering is needed only on WAPI. Once we move to Drive API we can
-  // drop this.
-  std::string resource_id;
-  ParentType parent_type = PARENT_TYPE_DIRECTORY;
-  if (parent_resource_id.empty()) {
-    resource_id = GetRootResourceId();
-    DCHECK(!resource_id.empty());
-    parent_type = PARENT_TYPE_ROOT_OR_EMPTY;
-  } else {
-    resource_id = parent_resource_id;
-  }
-  ScopedVector<google_apis::ResourceEntry> entries;
-  entries.swap(*feed->mutable_entries());
-  FilterEntriesByTitleAndParent(
-      &entries, expected_title, resource_id, parent_type);
-
-  if (entries.empty()) {
-    DVLOG(2) << "Uploaded file is not found";
-    callback.Run(google_apis::HTTP_NOT_FOUND,
-                 NO_DUPLICATES_FOUND,
-                 scoped_ptr<google_apis::ResourceEntry>());
-    return;
-  }
-
-  if (entries.size() >= 2) {
-    DVLOG(2) << "Conflict detected on creating entry";
-    for (size_t i = 0; i < entries.size() - 1; ++i) {
-      // TODO(tzik): Replace published_time with creation time after we move to
-      // Drive API.
-      if (entries[i]->published_time() < entries.back()->published_time())
-        std::swap(entries[i], entries.back());
-    }
-
-    scoped_ptr<google_apis::ResourceEntry> earliest_entry(entries.back());
-    entries.back() = NULL;
-    entries.get().pop_back();
-
-    DeleteEntriesForEnsuringTitleUniqueness(
-        entries.Pass(),
-        base::Bind(&EntryAdapterForEnsureTitleUniqueness,
-                   base::Passed(&earliest_entry),
-                   callback,
-                   RESOLVED_DUPLICATES));
-    return;
-  }
-
-  DVLOG(2) << "no conflict detected";
-  DCHECK_EQ(1u, entries.size());
-  scoped_ptr<google_apis::ResourceEntry> entry(entries.front());
-  entries.weak_clear();
-
-  callback.Run(google_apis::HTTP_SUCCESS, NO_DUPLICATES_FOUND, entry.Pass());
-}
-
-void APIUtil::DeleteEntriesForEnsuringTitleUniqueness(
-    ScopedVector<google_apis::ResourceEntry> entries,
-    const GDataErrorCallback& callback) {
-  DCHECK(CalledOnValidThread());
-  DVLOG(2) << "Cleaning up conflict on entry creation";
-
-  if (entries.empty()) {
-    callback.Run(google_apis::HTTP_SUCCESS);
-    return;
-  }
-
-  scoped_ptr<google_apis::ResourceEntry> entry(entries.back());
-  entries.back() = NULL;
-  entries.get().pop_back();
-
-  // We don't care conflicts here as other clients may be also deleting this
-  // file, so passing an empty etag.
-  drive_service_->DeleteResource(
-      entry->resource_id(),
-      std::string(),  // empty etag
-      base::Bind(&APIUtil::DidDeleteEntriesForEnsuringTitleUniqueness,
-                 AsWeakPtr(),
-                 base::Passed(&entries),
-                 callback));
-}
-
-void APIUtil::DidDeleteEntriesForEnsuringTitleUniqueness(
-    ScopedVector<google_apis::ResourceEntry> entries,
-    const GDataErrorCallback& callback,
-    google_apis::GDataErrorCode error) {
-  DCHECK(CalledOnValidThread());
-
-  if (error != google_apis::HTTP_SUCCESS &&
-      error != google_apis::HTTP_NOT_FOUND) {
-    DVLOG(2) << "Error on deleting file: " << error;
-    callback.Run(error);
-    return;
-  }
-
-  DVLOG(2) << "Deletion completed";
-  DeleteEntriesForEnsuringTitleUniqueness(entries.Pass(), callback);
-}
-
-APIUtil::UploadKey APIUtil::RegisterUploadCallback(
-    const UploadFileCallback& callback) {
-  const bool inserted = upload_callback_map_.insert(
-      std::make_pair(upload_next_key_, callback)).second;
-  CHECK(inserted);
-  return upload_next_key_++;
-}
-
-APIUtil::UploadFileCallback APIUtil::GetAndUnregisterUploadCallback(
-    UploadKey key) {
-  UploadFileCallback callback;
-  UploadCallbackMap::iterator found = upload_callback_map_.find(key);
-  if (found == upload_callback_map_.end())
-    return callback;
-  callback = found->second;
-  upload_callback_map_.erase(found);
-  return callback;
-}
-
-void APIUtil::CancelAllUploads(google_apis::GDataErrorCode error) {
-  if (upload_callback_map_.empty())
-    return;
-  for (UploadCallbackMap::iterator iter = upload_callback_map_.begin();
-       iter != upload_callback_map_.end();
-       ++iter) {
-    iter->second.Run(error, std::string(), std::string());
-  }
-  upload_callback_map_.clear();
-  drive_uploader_.reset(new google_apis::DriveUploader(drive_service_.get()));
-}
-
-std::string APIUtil::GetRootResourceId() const {
-  if (IsDriveAPIDisabled())
-    return drive_service_->GetRootResourceId();
-  return root_resource_id_;
-}
-
-}  // namespace drive
-}  // namespace sync_file_system
diff --git a/chrome/browser/sync_file_system/drive/api_util.h b/chrome/browser/sync_file_system/drive/api_util.h
deleted file mode 100644
index 23359a0..0000000
--- a/chrome/browser/sync_file_system/drive/api_util.h
+++ /dev/null
@@ -1,255 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_API_UTIL_H_
-#define CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_API_UTIL_H_
-
-#include <map>
-#include <string>
-
-#include "base/memory/weak_ptr.h"
-#include "chrome/browser/drive/drive_service_interface.h"
-#include "chrome/browser/google_apis/drive_api_url_generator.h"
-#include "chrome/browser/google_apis/gdata_wapi_url_generator.h"
-#include "chrome/browser/sync_file_system/drive/api_util_interface.h"
-#include "net/base/network_change_notifier.h"
-
-class GURL;
-class Profile;
-
-namespace google_apis { class DriveUploaderInterface; }
-
-namespace sync_file_system {
-namespace drive {
-
-// This class is responsible for talking to the Drive service to get and put
-// Drive directories, files and metadata.
-// This class is owned by DriveFileSyncService.
-class APIUtil : public drive::APIUtilInterface,
-                public google_apis::DriveServiceObserver,
-                public net::NetworkChangeNotifier::ConnectionTypeObserver,
-                public base::NonThreadSafe,
-                public base::SupportsWeakPtr<APIUtil> {
- public:
-  // The resulting status of EnsureTitleUniqueness.
-  enum EnsureUniquenessStatus {
-    NO_DUPLICATES_FOUND,
-    RESOLVED_DUPLICATES,
-  };
-
-  typedef base::Callback<void(google_apis::GDataErrorCode,
-                              EnsureUniquenessStatus status,
-                              scoped_ptr<google_apis::ResourceEntry> entry)>
-      EnsureUniquenessCallback;
-
-  explicit APIUtil(Profile* profile);
-  virtual ~APIUtil();
-
-  virtual void AddObserver(APIUtilObserver* observer) OVERRIDE;
-  virtual void RemoveObserver(APIUtilObserver* observer) OVERRIDE;
-
-  static scoped_ptr<APIUtil> CreateForTesting(
-      Profile* profile,
-      scoped_ptr<google_apis::DriveServiceInterface> drive_service,
-      scoped_ptr<google_apis::DriveUploaderInterface> drive_uploader);
-
-  // APIUtilInterface overrides.
-  virtual void GetDriveDirectoryForSyncRoot(const ResourceIdCallback& callback)
-      OVERRIDE;
-  virtual void GetDriveDirectoryForOrigin(
-      const std::string& sync_root_resource_id,
-      const GURL& origin,
-      const ResourceIdCallback& callback) OVERRIDE;
-  virtual void GetLargestChangeStamp(const ChangeStampCallback& callback)
-      OVERRIDE;
-  virtual void GetResourceEntry(const std::string& resource_id,
-                                const ResourceEntryCallback& callback) OVERRIDE;
-  virtual void ListFiles(const std::string& directory_resource_id,
-                         const ResourceListCallback& callback) OVERRIDE;
-  virtual void ListChanges(int64 start_changestamp,
-                           const ResourceListCallback& callback) OVERRIDE;
-  virtual void ContinueListing(const GURL& feed_url,
-                               const ResourceListCallback& callback) OVERRIDE;
-  virtual void DownloadFile(const std::string& resource_id,
-                            const std::string& local_file_md5,
-                            const base::FilePath& local_file_path,
-                            const DownloadFileCallback& callback) OVERRIDE;
-  virtual void UploadNewFile(const std::string& directory_resource_id,
-                             const base::FilePath& local_file_path,
-                             const std::string& title,
-                             const UploadFileCallback& callback) OVERRIDE;
-  virtual void UploadExistingFile(const std::string& resource_id,
-                                  const std::string& remote_file_md5,
-                                  const base::FilePath& local_file_path,
-                                  const UploadFileCallback& callback) OVERRIDE;
-  virtual void CreateDirectory(const std::string& parent_resource_id,
-                               const std::string& title,
-                               const ResourceIdCallback& callback) OVERRIDE;
-  virtual bool IsAuthenticated() const OVERRIDE;
-  virtual void DeleteFile(const std::string& resource_id,
-                          const std::string& remote_file_md5,
-                          const GDataErrorCallback& callback) OVERRIDE;
-  virtual GURL ResourceIdToResourceLink(const std::string& resource_id) const
-      OVERRIDE;
-  virtual void EnsureSyncRootIsNotInMyDrive(
-      const std::string& sync_root_resource_id) OVERRIDE;
-
-  static std::string GetSyncRootDirectoryName();
-  static std::string OriginToDirectoryTitle(const GURL& origin);
-  static GURL DirectoryTitleToOrigin(const std::string& title);
-
-  // DriveServiceObserver overrides.
-  virtual void OnReadyToSendRequests() OVERRIDE;
-
-  // ConnectionTypeObserver overrides.
-  virtual void OnConnectionTypeChanged(
-      net::NetworkChangeNotifier::ConnectionType type) OVERRIDE;
-
- private:
-  typedef int64 UploadKey;
-  typedef std::map<UploadKey, UploadFileCallback> UploadCallbackMap;
-
-  friend class APIUtilTest;
-  friend class DriveFileSyncServiceMockTest;
-
-  // Constructor for test use.
-  APIUtil(Profile* profile,
-          const GURL& base_url,
-          scoped_ptr<google_apis::DriveServiceInterface> drive_service,
-          scoped_ptr<google_apis::DriveUploaderInterface> drive_uploader);
-
-  void GetDriveRootResourceId(const GDataErrorCallback& callback);
-  void DidGetDriveRootResourceId(
-      const GDataErrorCallback& callback,
-      google_apis::GDataErrorCode error,
-      scoped_ptr<google_apis::AboutResource> about_resource);
-
-  void DidGetDriveRootResourceIdForGetSyncRoot(
-      const ResourceIdCallback& callback,
-      google_apis::GDataErrorCode error);
-
-  void DidGetDirectory(const std::string& parent_resource_id,
-                       const std::string& directory_name,
-                       const ResourceIdCallback& callback,
-                       google_apis::GDataErrorCode error,
-                       scoped_ptr<google_apis::ResourceList> feed);
-
-  void DidCreateDirectory(const std::string& parent_resource_id,
-                          const std::string& title,
-                          const ResourceIdCallback& callback,
-                          google_apis::GDataErrorCode error,
-                          scoped_ptr<google_apis::ResourceEntry> entry);
-
-  void DidEnsureUniquenessForCreateDirectory(
-      const ResourceIdCallback& callback,
-      google_apis::GDataErrorCode error,
-      EnsureUniquenessStatus status,
-      scoped_ptr<google_apis::ResourceEntry> entry);
-
-  void SearchByTitle(const std::string& title,
-                     const std::string& directory_resource_id,
-                     const ResourceListCallback& callback);
-
-  void DidGetLargestChangeStamp(
-      const ChangeStampCallback& callback,
-      google_apis::GDataErrorCode error,
-      scoped_ptr<google_apis::AboutResource> about_resource);
-
-  void DidGetDriveRootResourceIdForEnsureSyncRoot(
-      const std::string& sync_root_resource_id,
-      google_apis::GDataErrorCode error);
-
-  void DidGetResourceList(const ResourceListCallback& callback,
-                          google_apis::GDataErrorCode error,
-                          scoped_ptr<google_apis::ResourceList> resource_list);
-
-  void DidGetResourceEntry(const ResourceEntryCallback& callback,
-                           google_apis::GDataErrorCode error,
-                           scoped_ptr<google_apis::ResourceEntry> entry);
-
-  void DownloadFileInternal(const std::string& local_file_md5,
-                            const base::FilePath& local_file_path,
-                            const DownloadFileCallback& callback,
-                            google_apis::GDataErrorCode error,
-                            scoped_ptr<google_apis::ResourceEntry> entry);
-
-  void DidDownloadFile(scoped_ptr<google_apis::ResourceEntry> entry,
-                       const DownloadFileCallback& callback,
-                       google_apis::GDataErrorCode error,
-                       const base::FilePath& downloaded_file_path);
-
-  void DidUploadNewFile(const std::string& parent_resource_id,
-                        const std::string& title,
-                        UploadKey upload_key,
-                        google_apis::GDataErrorCode error,
-                        scoped_ptr<google_apis::ResourceEntry> entry);
-
-  void DidEnsureUniquenessForCreateFile(
-      const std::string& expected_resource_id,
-      const UploadFileCallback& callback,
-      google_apis::GDataErrorCode error,
-      EnsureUniquenessStatus status,
-      scoped_ptr<google_apis::ResourceEntry> entry);
-
-  void UploadExistingFileInternal(const std::string& remote_file_md5,
-                                  const base::FilePath& local_file_path,
-                                  const UploadFileCallback& callback,
-                                  google_apis::GDataErrorCode error,
-                                  scoped_ptr<google_apis::ResourceEntry> entry);
-
-  void DidUploadExistingFile(UploadKey upload_key,
-                             google_apis::GDataErrorCode error,
-                             scoped_ptr<google_apis::ResourceEntry> entry);
-
-  void DeleteFileInternal(const std::string& remote_file_md5,
-                          const GDataErrorCallback& callback,
-                          google_apis::GDataErrorCode error,
-                          scoped_ptr<google_apis::ResourceEntry> entry);
-
-  void DidDeleteFile(const GDataErrorCallback& callback,
-                     google_apis::GDataErrorCode error);
-
-  void EnsureTitleUniqueness(const std::string& parent_resource_id,
-                             const std::string& expected_title,
-                             const EnsureUniquenessCallback& callback);
-  void DidListEntriesToEnsureUniqueness(
-      const std::string& parent_resource_id,
-      const std::string& expected_title,
-      const EnsureUniquenessCallback& callback,
-      google_apis::GDataErrorCode error,
-      scoped_ptr<google_apis::ResourceList> feed);
-  void DeleteEntriesForEnsuringTitleUniqueness(
-      ScopedVector<google_apis::ResourceEntry> entries,
-      const GDataErrorCallback& callback);
-  void DidDeleteEntriesForEnsuringTitleUniqueness(
-      ScopedVector<google_apis::ResourceEntry> entries,
-      const GDataErrorCallback& callback,
-      google_apis::GDataErrorCode error);
-
-  UploadKey RegisterUploadCallback(const UploadFileCallback& callback);
-  UploadFileCallback GetAndUnregisterUploadCallback(UploadKey key);
-  void CancelAllUploads(google_apis::GDataErrorCode error);
-
-  std::string GetRootResourceId() const;
-
-  scoped_ptr<google_apis::DriveServiceInterface> drive_service_;
-  scoped_ptr<google_apis::DriveUploaderInterface> drive_uploader_;
-
-  google_apis::GDataWapiUrlGenerator wapi_url_generator_;
-  google_apis::DriveApiUrlGenerator drive_api_url_generator_;
-
-  UploadCallbackMap upload_callback_map_;
-  UploadKey upload_next_key_;
-
-  std::string root_resource_id_;
-
-  ObserverList<APIUtilObserver> observers_;
-
-  DISALLOW_COPY_AND_ASSIGN(APIUtil);
-};
-
-}  // namespace drive
-}  // namespace sync_file_system
-
-#endif  // CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_API_UTIL_H_
diff --git a/chrome/browser/sync_file_system/drive/api_util_interface.h b/chrome/browser/sync_file_system/drive/api_util_interface.h
deleted file mode 100644
index 0758774..0000000
--- a/chrome/browser/sync_file_system/drive/api_util_interface.h
+++ /dev/null
@@ -1,198 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_API_UTIL_INTERFACE_H_
-#define CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_API_UTIL_INTERFACE_H_
-
-#include <string>
-
-#include "base/callback_forward.h"
-#include "chrome/browser/google_apis/gdata_errorcode.h"
-#include "chrome/browser/google_apis/gdata_wapi_parser.h"
-
-class GURL;
-class Profile;
-
-namespace base {
-class Time;
-}
-
-namespace google_apis {
-class DriveUploaderInterface;
-}
-
-namespace sync_file_system {
-namespace drive {
-
-class APIUtilObserver {
- public:
-  APIUtilObserver() {}
-  virtual ~APIUtilObserver() {}
-  virtual void OnAuthenticated() = 0;
-  virtual void OnNetworkConnected() = 0;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(APIUtilObserver);
-};
-
-// The implementation of this class is responsible for talking to the Drive
-// service to get and put Drive directories, files and metadata.
-// This class is owned by DriveFileSyncService.
-class APIUtilInterface {
- public:
-  typedef base::Callback<void(google_apis::GDataErrorCode error)>
-      GDataErrorCallback;
-  typedef base::Callback<void(google_apis::GDataErrorCode error,
-                              const std::string& file_md5,
-                              int64 file_size,
-                              const base::Time& last_updated)>
-      DownloadFileCallback;
-  typedef base::Callback<void(google_apis::GDataErrorCode error,
-                              const std::string& resource_id,
-                              const std::string& file_md5)> UploadFileCallback;
-  typedef base::Callback<
-      void(google_apis::GDataErrorCode error, const std::string& resource_id)>
-      ResourceIdCallback;
-  typedef base::Callback<void(google_apis::GDataErrorCode error,
-                              int64 changestamp)> ChangeStampCallback;
-  typedef base::Callback<void(google_apis::GDataErrorCode error,
-                              scoped_ptr<google_apis::ResourceList> feed)>
-      ResourceListCallback;
-  typedef base::Callback<void(google_apis::GDataErrorCode error,
-                              scoped_ptr<google_apis::ResourceEntry> entry)>
-      ResourceEntryCallback;
-
-  APIUtilInterface() {}
-  virtual ~APIUtilInterface() {}
-
-  virtual void AddObserver(APIUtilObserver* observer) = 0;
-  virtual void RemoveObserver(APIUtilObserver* observer) = 0;
-
-  // Fetches Resource ID of the directory where we should place all files to
-  // sync.  Upon completion, invokes |callback|.
-  // If the directory does not exist on the server this also creates
-  // the directory.
-  //
-  // Returns HTTP_SUCCESS if the directory already exists.
-  // Returns HTTP_CREATED if the directory was not found and created.
-  virtual void GetDriveDirectoryForSyncRoot(
-      const ResourceIdCallback& callback) = 0;
-
-  // Fetches Resource ID of the directory for the |origin|.
-  // Upon completion, invokes |callback|.
-  // If the directory does not exist on the server this also creates
-  // the directory.
-  //
-  // Returns HTTP_SUCCESS if the directory already exists.
-  // Returns HTTP_CREATED if the directory was not found and created.
-  virtual void GetDriveDirectoryForOrigin(
-      const std::string& sync_root_resource_id,
-      const GURL& origin,
-      const ResourceIdCallback& callback) = 0;
-
-  // Fetches the largest changestamp for the signed-in account.
-  // Upon completion, invokes |callback|.
-  virtual void GetLargestChangeStamp(const ChangeStampCallback& callback) = 0;
-
-  // Fetches the resource entry for the file identified by |resource_id|.
-  // Upon completion, invokes |callback|.
-  virtual void GetResourceEntry(const std::string& resource_id,
-                                const ResourceEntryCallback& callback) = 0;
-
-  // Lists files in the directory identified by |resource_id|.
-  // Upon completion, invokes |callback|.
-  // The result may be chunked and may have successive results. The caller needs
-  // to call ContunueListing with the result of GetNextFeedURL to get complete
-  // list of files.
-  virtual void ListFiles(const std::string& directory_resource_id,
-                         const ResourceListCallback& callback) = 0;
-
-  // Lists changes that happened after |start_changestamp|.
-  // Upon completion, invokes |callback|.
-  // The result may be chunked and may have successive results. The caller needs
-  // to call ContunueListing with the result of GetNextFeedURL to get complete
-  // list of changes.
-  virtual void ListChanges(int64 start_changestamp,
-                           const ResourceListCallback& callback) = 0;
-
-  // Fetches the next chunk of ResourceList identified by |feed_url|.
-  // Upon completion, invokes |callback|.
-  virtual void ContinueListing(const GURL& feed_url,
-                               const ResourceListCallback& callback) = 0;
-
-  // Downloads the file identified by |resource_id| from Drive to
-  // |local_file_path|.
-  // |local_file_md5| represents the hash value of the local file to be updated.
-  // If |local_file_md5| is equal to remote file's value, cancels the download
-  // and invokes |callback| with GDataErrorCode::HTTP_NOT_MODIFIED immediately.
-  // When there is no local file to be updated, |local_file_md5| should be
-  // empty.
-  virtual void DownloadFile(const std::string& resource_id,
-                            const std::string& local_file_md5,
-                            const base::FilePath& local_file_path,
-                            const DownloadFileCallback& callback) = 0;
-
-  // Uploads the new file |local_file_path| with specified |title| into the
-  // directory identified by |directory_resource_id|.
-  // Upon completion, invokes |callback| and returns HTTP_CREATED if the file
-  // is created.
-  virtual void UploadNewFile(const std::string& directory_resource_id,
-                             const base::FilePath& local_file_path,
-                             const std::string& title,
-                             const UploadFileCallback& callback) = 0;
-
-  // Uploads the existing file identified by |local_file_path|.
-  // |remote_file_md5| represents the expected hash value of the file to be
-  // updated on Drive. If |remote_file_md5| is different from the actual value,
-  // cancels the upload and invokes |callback| with
-  // GDataErrorCode::HTTP_CONFLICT immediately.
-  // Returns HTTP_SUCCESS if the file uploaded successfully.
-  virtual void UploadExistingFile(const std::string& resource_id,
-                                  const std::string& remote_file_md5,
-                                  const base::FilePath& local_file_path,
-                                  const UploadFileCallback& callback) = 0;
-
-  // Creates a new directory with specified |title| into the directory
-  // identified by |parent_resource_id|.
-  // Upon completion, invokes |callback| and returns HTTP_CREATED if
-  // the directory is created.
-  virtual void CreateDirectory(const std::string& parent_resource_id,
-                               const std::string& title,
-                               const ResourceIdCallback& callback) = 0;
-
-  // Returns true if the user is authenticated.
-  virtual bool IsAuthenticated() const = 0;
-
-  // Deletes the file identified by |resource_id|.
-  // A directory is considered a file and will cause a recursive delete if
-  // given as the |resource_id|.
-  // TODO(tzik): Rename this function to DeleteResource.
-  //
-  // |remote_file_md5| represents the expected hash value of the file to be
-  // deleted from Drive. If |remote_file_md5| is empty, then it's implied that
-  // the file should be deleted on the remote side regardless. If
-  // |remote_file_md5| is not empty and is different from the actual value,
-  // the deletion operation is canceled and the |callback| with
-  // GDataErrorCode::HTTP_CONFLICT is invoked immediately.
-  virtual void DeleteFile(const std::string& resource_id,
-                          const std::string& remote_file_md5,
-                          const GDataErrorCallback& callback) = 0;
-
-  // Converts |resource_id| to corresponing resource link.
-  virtual GURL ResourceIdToResourceLink(
-      const std::string& resource_id) const = 0;
-
-  // Ensures the sync root directory is not in 'My Drive'. Even if the directory
-  // is in directories other than 'My Drive', it will not be removed from there.
-  virtual void EnsureSyncRootIsNotInMyDrive(
-      const std::string& sync_root_resource_id) = 0;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(APIUtilInterface);
-};
-
-}  // namespace drive
-}  // namespace sync_file_system
-
-#endif  // CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_API_UTIL_INTERFACE_H_
diff --git a/chrome/browser/sync_file_system/drive/api_util_unittest.cc b/chrome/browser/sync_file_system/drive/api_util_unittest.cc
deleted file mode 100644
index f67f054..0000000
--- a/chrome/browser/sync_file_system/drive/api_util_unittest.cc
+++ /dev/null
@@ -1,849 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/sync_file_system/drive/api_util.h"
-
-#include "base/json/json_reader.h"
-#include "base/location.h"
-#include "base/message_loop.h"
-#include "base/message_loop/message_loop_proxy.h"
-#include "base/values.h"
-#include "chrome/browser/drive/drive_uploader.h"
-#include "chrome/browser/drive/fake_drive_service.h"
-#include "chrome/browser/google_apis/drive_api_parser.h"
-#include "chrome/browser/google_apis/gdata_errorcode.h"
-#include "chrome/browser/google_apis/test_util.h"
-#include "chrome/browser/sync_file_system/drive_file_sync_util.h"
-#include "chrome/test/base/testing_profile.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/test/test_browser_thread.h"
-#include "net/base/escape.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#define FPL(x) FILE_PATH_LITERAL(x)
-
-using google_apis::FakeDriveService;
-using google_apis::ResourceEntry;
-using google_apis::ResourceList;
-using google_apis::DriveServiceInterface;
-using google_apis::DriveUploaderInterface;
-using google_apis::GDataErrorCode;
-using google_apis::Link;
-using google_apis::test_util::LoadJSONFile;
-
-namespace sync_file_system {
-namespace drive {
-
-namespace {
-
-const char kOrigin[] = "chrome-extension://example";
-const char kOriginDirectoryName[] = "example";
-const char kOriginDirectoryResourceId[] = "folder:origin_directory_resource_id";
-const char kSyncRootResourceId[] = "folder:sync_root_resource_id";
-
-void EmptyResourceEntryCallback(GDataErrorCode error,
-                                scoped_ptr<ResourceEntry> entry) {}
-
-void VerifyTitleUniqueness(const tracked_objects::Location& from_here,
-                           const std::string& resource_id,
-                           google_apis::DriveEntryKind kind,
-                           GDataErrorCode error,
-                           scoped_ptr<ResourceList> resource_list) {
-  std::string location(" failed at " + from_here.ToString());
-  ASSERT_FALSE(resource_id.empty()) << location;
-  ASSERT_EQ(google_apis::HTTP_SUCCESS, error) << location;
-  ASSERT_TRUE(resource_list) << location;
-
-  const ScopedVector<ResourceEntry>& entries = resource_list->entries();
-  ASSERT_EQ(1u, entries.size());
-  EXPECT_EQ(resource_id, entries[0]->resource_id());
-  switch (kind) {
-    case google_apis::ENTRY_KIND_FOLDER:
-      EXPECT_TRUE(entries[0]->is_folder()) << location;
-      return;
-    case google_apis::ENTRY_KIND_FILE:
-      EXPECT_TRUE(entries[0]->is_file()) << location;
-      return;
-    default:
-      NOTREACHED() << "Unexpected DriveEntryKind: " << kind << location;
-      return;
-  }
-}
-
-void VerifyFileDeletion(const tracked_objects::Location& from_here,
-                        GDataErrorCode error,
-                        scoped_ptr<ResourceList> resource_list) {
-  std::string location(" failed at " + from_here.ToString());
-  ASSERT_EQ(google_apis::HTTP_SUCCESS, error) << location;
-  ASSERT_TRUE(resource_list) << location;
-  EXPECT_TRUE(resource_list->entries().empty()) << location;
-}
-
-class FakeDriveServiceWrapper : public FakeDriveService {
- public:
-  FakeDriveServiceWrapper() : make_directory_conflict_(false) {};
-  virtual ~FakeDriveServiceWrapper() {};
-
-  // DriveServiceInterface overrides.
-  virtual google_apis::CancelCallback AddNewDirectory(
-      const std::string& parent_resource_id,
-      const std::string& directory_name,
-      const google_apis::GetResourceEntryCallback& callback) OVERRIDE {
-    if (make_directory_conflict_) {
-      FakeDriveService::AddNewDirectory(
-          parent_resource_id,
-          directory_name,
-          base::Bind(&EmptyResourceEntryCallback));
-    }
-    return FakeDriveService::AddNewDirectory(
-        parent_resource_id, directory_name, callback);
-  }
-
-  void set_make_directory_conflict(bool enable) {
-    make_directory_conflict_ = enable;
-  }
-
- private:
-  bool make_directory_conflict_;
-
-  DISALLOW_COPY_AND_ASSIGN(FakeDriveServiceWrapper);
-};
-
-// A fake implementation of DriveUploaderInterface, which provides fake
-// behaviors for file uploading.
-class FakeDriveUploader : public DriveUploaderInterface {
- public:
-  explicit FakeDriveUploader(FakeDriveServiceWrapper* fake_drive_service)
-      : fake_drive_service_(fake_drive_service),
-        make_file_conflict_(false) {}
-  virtual ~FakeDriveUploader() {}
-
-  // DriveUploaderInterface overrides.
-
-  // Pretends that a new file was uploaded successfully, and returns the
-  // contents of "chromeos/gdata/file_entry.json" to the caller.
-  virtual google_apis::CancelCallback UploadNewFile(
-      const std::string& parent_resource_id,
-      const base::FilePath& drive_file_path,
-      const base::FilePath& local_file_path,
-      const std::string& title,
-      const std::string& content_type,
-      const google_apis::UploadCompletionCallback& callback,
-      const google_apis::ProgressCallback& progress_callback) OVERRIDE {
-    DCHECK(!callback.is_null());
-
-    scoped_ptr<base::Value> file_entry_data(
-        LoadJSONFile("chromeos/gdata/file_entry.json"));
-    scoped_ptr<ResourceEntry> file_entry(
-        ResourceEntry::ExtractAndParse(*file_entry_data));
-
-    if (make_file_conflict_) {
-      fake_drive_service_->LoadResourceListForWapi(
-          "chromeos/sync_file_system/conflict_with_file.json");
-    } else {
-      fake_drive_service_->LoadResourceListForWapi(
-          "chromeos/sync_file_system/upload_new_file.json");
-    }
-
-    base::MessageLoopProxy::current()->PostTask(
-        FROM_HERE,
-        base::Bind(callback,
-                   google_apis::HTTP_SUCCESS,
-                   GURL(),
-                   base::Passed(&file_entry)));
-    return google_apis::CancelCallback();
-  }
-
-  // Pretends that an existing file ("file:resource_id") was uploaded
-  // successfully, and returns the contents of "chromeos/gdata/file_entry.json"
-  // to the caller.
-  virtual google_apis::CancelCallback UploadExistingFile(
-      const std::string& resource_id,
-      const base::FilePath& drive_file_path,
-      const base::FilePath& local_file_path,
-      const std::string& content_type,
-      const std::string& etag,
-      const google_apis::UploadCompletionCallback& callback,
-      const google_apis::ProgressCallback& progress_callback) OVERRIDE {
-    DCHECK(!callback.is_null());
-
-    scoped_ptr<base::Value> file_entry_data(
-        LoadJSONFile("chromeos/gdata/file_entry.json"));
-    scoped_ptr<ResourceEntry> file_entry(
-        ResourceEntry::ExtractAndParse(*file_entry_data));
-
-    base::MessageLoopProxy::current()->PostTask(
-        FROM_HERE,
-        base::Bind(callback,
-                   google_apis::HTTP_SUCCESS,
-                   GURL(),
-                   base::Passed(&file_entry)));
-    return google_apis::CancelCallback();
-  }
-
-  // At the moment, sync file system doesn't support resuming of the uploading.
-  // So this method shouldn't be reached.
-  virtual google_apis::CancelCallback ResumeUploadFile(
-      const GURL& upload_location,
-      const base::FilePath& drive_file_path,
-      const base::FilePath& local_file_path,
-      const std::string& content_type,
-      const google_apis::UploadCompletionCallback& callback,
-      const google_apis::ProgressCallback& progress_callback) OVERRIDE {
-    NOTREACHED();
-    return google_apis::CancelCallback();
-  }
-
-  void set_make_file_conflict(bool enable) {
-    make_file_conflict_ = enable;
-  }
-
- private:
-  FakeDriveServiceWrapper* fake_drive_service_;
-  bool make_file_conflict_;
-
-  DISALLOW_COPY_AND_ASSIGN(FakeDriveUploader);
-};
-
-}  // namespace
-
-class APIUtilTest : public testing::Test {
- public:
-  APIUtilTest() : ui_thread_(content::BrowserThread::UI, &message_loop_),
-                  fake_drive_service_(NULL),
-                  fake_drive_uploader_(NULL) {}
-
-  virtual void SetUp() OVERRIDE {
-    SetDisableDriveAPI(true);
-
-    fake_drive_service_ = new FakeDriveServiceWrapper;
-    fake_drive_uploader_ = new FakeDriveUploader(fake_drive_service_);
-
-    api_util_ = APIUtil::CreateForTesting(
-        &profile_,
-        scoped_ptr<DriveServiceInterface>(fake_drive_service_),
-        scoped_ptr<DriveUploaderInterface>(fake_drive_uploader_));
-  }
-
-  virtual void TearDown() OVERRIDE {
-    api_util_.reset();
-    SetDisableDriveAPI(false);
-  }
-
- protected:
-  std::string GetRootResourceId() { return api_util_->GetRootResourceId(); }
-
-  APIUtil* api_util() { return api_util_.get(); }
-
-  FakeDriveServiceWrapper* fake_drive_service() {
-    return fake_drive_service_;
-  }
-
-  FakeDriveUploader* fake_drive_uploader() {
-    return fake_drive_uploader_;
-  }
-
-  base::MessageLoop* message_loop() { return &message_loop_; }
-
- private:
-  base::MessageLoop message_loop_;
-  content::TestBrowserThread ui_thread_;
-
-  TestingProfile profile_;
-  scoped_ptr<APIUtil> api_util_;
-  FakeDriveServiceWrapper* fake_drive_service_;
-  FakeDriveUploader* fake_drive_uploader_;
-
-  DISALLOW_COPY_AND_ASSIGN(APIUtilTest);
-};
-
-void DidGetResourceID(bool* done_out,
-                      GDataErrorCode* error_out,
-                      std::string* resource_id_out,
-                      GDataErrorCode error,
-                      const std::string& resource_id) {
-  EXPECT_FALSE(*done_out);
-  *done_out = true;
-  *error_out = error;
-  *resource_id_out = resource_id;
-}
-
-#if !defined(OS_ANDROID)
-
-void DidGetLargestChangeStamp(bool* done_out,
-                              GDataErrorCode* error_out,
-                              int64* largest_changestamp_out,
-                              GDataErrorCode error,
-                              int64 largest_changestamp) {
-  EXPECT_FALSE(*done_out);
-  *done_out = true;
-  *error_out = error;
-  *largest_changestamp_out = largest_changestamp;
-}
-
-void DidGetResourceList(bool* done_out,
-                        GDataErrorCode* error_out,
-                        scoped_ptr<ResourceList>* document_feed_out,
-                        GDataErrorCode error,
-                        scoped_ptr<ResourceList> document_feed) {
-  EXPECT_FALSE(*done_out);
-  *done_out = true;
-  *error_out = error;
-  *document_feed_out = document_feed.Pass();
-}
-
-void DidDownloadFile(bool* done_out,
-                     std::string* expected_file_md5_out,
-                     GDataErrorCode* error_out,
-                     GDataErrorCode error,
-                     const std::string& file_md5,
-                     int64 file_size,
-                     const base::Time& updated_time) {
-  EXPECT_FALSE(*done_out);
-  *done_out = true;
-  *error_out = error;
-  *expected_file_md5_out = file_md5;
-}
-
-void DidUploadFile(bool* done_out,
-                   GDataErrorCode* error_out,
-                   std::string* resource_id_out,
-                   GDataErrorCode error,
-                   const std::string& resource_id,
-                   const std::string& file_md5) {
-  EXPECT_FALSE(*done_out);
-  *done_out = true;
-  *error_out = error;
-  *resource_id_out = resource_id;
-}
-
-void DidDeleteFile(bool* done_out,
-                   GDataErrorCode* error_out,
-                   GDataErrorCode error) {
-  EXPECT_FALSE(*done_out);
-  *done_out = true;
-  *error_out = error;
-}
-
-TEST_F(APIUtilTest, GetSyncRoot) {
-  fake_drive_service()->LoadResourceListForWapi(
-      "chromeos/sync_file_system/sync_root_found.json");
-
-  bool done = false;
-  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
-  std::string resource_id;
-  api_util()->GetDriveDirectoryForSyncRoot(
-      base::Bind(&DidGetResourceID, &done, &error, &resource_id));
-  message_loop()->RunUntilIdle();
-
-  EXPECT_TRUE(done);
-  EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
-  EXPECT_EQ(kSyncRootResourceId, resource_id);
-}
-
-TEST_F(APIUtilTest, CreateSyncRoot) {
-  fake_drive_service()->LoadResourceListForWapi(
-      "chromeos/sync_file_system/sync_root_not_found.json");
-
-  bool done = false;
-  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
-  std::string resource_id;
-  api_util()->GetDriveDirectoryForSyncRoot(
-      base::Bind(&DidGetResourceID, &done, &error, &resource_id));
-  message_loop()->RunUntilIdle();
-
-  EXPECT_TRUE(done);
-  EXPECT_EQ(google_apis::HTTP_CREATED, error);
-  EXPECT_FALSE(resource_id.empty());
-
-  fake_drive_service()->SearchByTitle(
-      APIUtil::GetSyncRootDirectoryName(),
-      std::string(),  // directory_resource_id
-      base::Bind(&VerifyTitleUniqueness,
-                 FROM_HERE,
-                 resource_id,
-                 google_apis::ENTRY_KIND_FOLDER));
-  message_loop()->RunUntilIdle();
-}
-
-TEST_F(APIUtilTest, CreateSyncRoot_Conflict) {
-  fake_drive_service()->LoadResourceListForWapi(
-      "chromeos/sync_file_system/sync_root_not_found.json");
-  fake_drive_service()->set_make_directory_conflict(true);
-
-  bool done = false;
-  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
-  std::string resource_id;
-  api_util()->GetDriveDirectoryForSyncRoot(
-      base::Bind(&DidGetResourceID, &done, &error, &resource_id));
-  message_loop()->RunUntilIdle();
-
-  EXPECT_TRUE(done);
-  EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
-  EXPECT_FALSE(resource_id.empty());
-
-  // Verify that there is no duplicated directory on the remote side.
-  fake_drive_service()->SearchByTitle(
-      APIUtil::GetSyncRootDirectoryName(),
-      std::string(),  // directory_resource_id
-      base::Bind(&VerifyTitleUniqueness,
-                 FROM_HERE,
-                 resource_id,
-                 google_apis::ENTRY_KIND_FOLDER));
-  message_loop()->RunUntilIdle();
-}
-
-TEST_F(APIUtilTest, GetOriginDirectory) {
-  fake_drive_service()->LoadResourceListForWapi(
-      "chromeos/sync_file_system/origin_directory_found.json");
-
-  bool done = false;
-  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
-  std::string resource_id;
-  api_util()->GetDriveDirectoryForOrigin(
-      kSyncRootResourceId,
-      GURL(kOrigin),
-      base::Bind(&DidGetResourceID, &done, &error, &resource_id));
-  message_loop()->RunUntilIdle();
-
-  EXPECT_TRUE(done);
-  EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
-  EXPECT_EQ(kOriginDirectoryResourceId, resource_id);
-}
-
-TEST_F(APIUtilTest, CreateOriginDirectory) {
-  fake_drive_service()->LoadResourceListForWapi(
-      "chromeos/sync_file_system/sync_root_found.json");
-
-  bool done = false;
-  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
-  std::string resource_id;
-  api_util()->GetDriveDirectoryForOrigin(
-      kSyncRootResourceId,
-      GURL(kOrigin),
-      base::Bind(&DidGetResourceID, &done, &error, &resource_id));
-  message_loop()->RunUntilIdle();
-
-  EXPECT_TRUE(done);
-  EXPECT_EQ(google_apis::HTTP_CREATED, error);
-  EXPECT_FALSE(resource_id.empty());
-
-  fake_drive_service()->SearchByTitle(
-      kOriginDirectoryName,
-      kSyncRootResourceId,
-      base::Bind(&VerifyTitleUniqueness,
-                 FROM_HERE,
-                 resource_id,
-                 google_apis::ENTRY_KIND_FOLDER));
-  message_loop()->RunUntilIdle();
-}
-
-TEST_F(APIUtilTest, CreateOriginDirectory_Conflict) {
-  fake_drive_service()->LoadResourceListForWapi(
-      "chromeos/sync_file_system/sync_root_found.json");
-  fake_drive_service()->set_make_directory_conflict(true);
-
-  bool done = false;
-  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
-  std::string resource_id;
-  api_util()->GetDriveDirectoryForOrigin(
-      kSyncRootResourceId,
-      GURL(kOrigin),
-      base::Bind(&DidGetResourceID, &done, &error, &resource_id));
-  message_loop()->RunUntilIdle();
-
-  EXPECT_TRUE(done);
-  EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
-  EXPECT_FALSE(resource_id.empty());
-
-  // Verify that there is no duplicated directory on the remote side.
-  fake_drive_service()->SearchByTitle(
-      kOriginDirectoryName,
-      kSyncRootResourceId,
-      base::Bind(&VerifyTitleUniqueness,
-                 FROM_HERE,
-                 resource_id,
-                 google_apis::ENTRY_KIND_FOLDER));
-  message_loop()->RunUntilIdle();
-}
-
-TEST_F(APIUtilTest, GetLargestChangeStamp) {
-  fake_drive_service()->LoadAccountMetadataForWapi(
-      "chromeos/sync_file_system/account_metadata.json");
-
-  bool done = false;
-  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
-  int64 largest_changestamp = -1;
-  api_util()->GetLargestChangeStamp(base::Bind(
-      &DidGetLargestChangeStamp, &done, &error, &largest_changestamp));
-  message_loop()->RunUntilIdle();
-
-  EXPECT_TRUE(done);
-  EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
-  EXPECT_EQ(654321, largest_changestamp);
-}
-
-TEST_F(APIUtilTest, ListFiles) {
-  fake_drive_service()->LoadResourceListForWapi(
-      "chromeos/sync_file_system/listing_files_in_directory.json");
-
-  fake_drive_service()->set_default_max_results(1);
-
-  bool done = false;
-  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
-  scoped_ptr<ResourceList> document_feed;
-  api_util()->ListFiles(
-      kOriginDirectoryResourceId,
-      base::Bind(&DidGetResourceList, &done, &error, &document_feed));
-  message_loop()->RunUntilIdle();
-
-  EXPECT_TRUE(done);
-  EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
-  EXPECT_FALSE(document_feed->entries().empty());
-
-  GURL feed_url;
-  ASSERT_TRUE(document_feed->GetNextFeedURL(&feed_url));
-
-  done = false;
-  error = google_apis::GDATA_OTHER_ERROR;
-  document_feed.reset();
-
-  api_util()->ContinueListing(
-      feed_url, base::Bind(&DidGetResourceList, &done, &error, &document_feed));
-  message_loop()->RunUntilIdle();
-
-  EXPECT_TRUE(done);
-  EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
-  EXPECT_FALSE(document_feed->entries().empty());
-}
-
-TEST_F(APIUtilTest, ListChanges) {
-  const int64 kStartChangestamp = 123456;
-
-  fake_drive_service()->LoadResourceListForWapi(
-      "chromeos/sync_file_system/listing_files_in_directory.json");
-
-  bool done = false;
-  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
-  scoped_ptr<ResourceList> document_feed;
-  api_util()->ListFiles(
-      kOriginDirectoryResourceId,
-      base::Bind(&DidGetResourceList, &done, &error, &document_feed));
-  message_loop()->RunUntilIdle();
-
-  EXPECT_TRUE(done);
-  EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
-  EXPECT_FALSE(document_feed->entries().empty());
-
-  done = false;
-  error = google_apis::GDATA_OTHER_ERROR;
-  document_feed.reset();
-  api_util()->ListChanges(
-      kStartChangestamp,
-      base::Bind(&DidGetResourceList, &done, &error, &document_feed));
-  message_loop()->RunUntilIdle();
-
-  EXPECT_TRUE(done);
-  EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
-  EXPECT_FALSE(document_feed->entries().empty());
-}
-
-TEST_F(APIUtilTest, DownloadFile) {
-  const std::string kResourceId = "file:file_resource_id";
-  const std::string kLocalFileMD5 = "123456";
-  const std::string kExpectedFileMD5 = "3b4382ebefec6e743578c76bbd0575ce";
-
-  fake_drive_service()->LoadResourceListForWapi(
-      "chromeos/sync_file_system/listing_files_in_directory.json");
-
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-  const base::FilePath kOutputFilePath = temp_dir.path().AppendASCII("file");
-
-  bool done = false;
-  std::string file_md5;
-  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
-  api_util()->DownloadFile(
-      kResourceId,
-      kLocalFileMD5,
-      kOutputFilePath,
-      base::Bind(&DidDownloadFile, &done, &file_md5, &error));
-  message_loop()->RunUntilIdle();
-
-  EXPECT_TRUE(done);
-  EXPECT_EQ(kExpectedFileMD5, file_md5);
-  EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
-}
-
-TEST_F(APIUtilTest, DownloadFileInNotModified) {
-  const std::string kResourceId = "file:file_resource_id";
-
-  // Since local file's hash value is equal to remote file's one, it is expected
-  // to cancel download the file and to return NOT_MODIFIED status code.
-  const std::string kLocalFileMD5 = "3b4382ebefec6e743578c76bbd0575ce";
-
-  fake_drive_service()->LoadResourceListForWapi(
-      "chromeos/sync_file_system/listing_files_in_directory.json");
-
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-  const base::FilePath kOutputFilePath = temp_dir.path().AppendASCII("file");
-
-  bool done = false;
-  std::string file_md5;
-  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
-  api_util()->DownloadFile(
-      kResourceId,
-      kLocalFileMD5,
-      kOutputFilePath,
-      base::Bind(&DidDownloadFile, &done, &file_md5, &error));
-  message_loop()->RunUntilIdle();
-
-  EXPECT_TRUE(done);
-  EXPECT_EQ(kLocalFileMD5, file_md5);
-  EXPECT_EQ(google_apis::HTTP_NOT_MODIFIED, error);
-}
-
-TEST_F(APIUtilTest, UploadNewFile) {
-  const base::FilePath kLocalFilePath(FPL("/tmp/dir/file"));
-
-  fake_drive_service()->LoadResourceListForWapi(
-      "chromeos/sync_file_system/listing_files_in_directory.json");
-
-  scoped_ptr<base::Value> file_entry_data(
-      LoadJSONFile("chromeos/gdata/file_entry.json"));
-  scoped_ptr<ResourceEntry> expected_file_entry(
-      ResourceEntry::ExtractAndParse(*file_entry_data));
-
-  bool done = false;
-  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
-  std::string resource_id;
-  api_util()->UploadNewFile(
-      kOriginDirectoryResourceId,
-      kLocalFilePath,
-      expected_file_entry->title(),
-      base::Bind(&DidUploadFile, &done, &error, &resource_id));
-  message_loop()->RunUntilIdle();
-
-  EXPECT_TRUE(done);
-  EXPECT_EQ(google_apis::HTTP_CREATED, error);
-  EXPECT_EQ(expected_file_entry->resource_id(), resource_id);
-
-  fake_drive_service()->SearchByTitle(
-      expected_file_entry->title(),
-      kOriginDirectoryResourceId,
-      base::Bind(&VerifyTitleUniqueness,
-                 FROM_HERE,
-                 expected_file_entry->resource_id(),
-                 google_apis::ENTRY_KIND_FILE));
-  message_loop()->RunUntilIdle();
-}
-
-TEST_F(APIUtilTest, UploadNewFile_ConflictWithFile) {
-  const base::FilePath kLocalFilePath(FPL("/tmp/dir/file"));
-
-  fake_drive_service()->LoadResourceListForWapi(
-      "chromeos/sync_file_system/upload_new_file.json");
-
-  scoped_ptr<base::Value> file_entry_data(
-      LoadJSONFile("chromeos/gdata/file_entry.json"));
-  scoped_ptr<ResourceEntry> expected_file_entry(
-      ResourceEntry::ExtractAndParse(*file_entry_data));
-
-  fake_drive_uploader()->set_make_file_conflict(true);
-
-  bool done = false;
-  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
-  std::string resource_id;
-  api_util()->UploadNewFile(
-      kOriginDirectoryResourceId,
-      kLocalFilePath,
-      expected_file_entry->title(),
-      base::Bind(&DidUploadFile, &done, &error, &resource_id));
-  message_loop()->RunUntilIdle();
-
-  // HTTP_CONFLICT error must be returned with empty resource_id.
-  EXPECT_TRUE(done);
-  EXPECT_EQ(google_apis::HTTP_CONFLICT, error);
-  EXPECT_EQ("file:file_duplicated_resource_id", resource_id);
-
-  // Verify that there is no duplicated file on the remote side.
-  fake_drive_service()->SearchByTitle(
-      expected_file_entry->title(),
-      kOriginDirectoryResourceId,
-      base::Bind(&VerifyTitleUniqueness,
-                 FROM_HERE,
-                 resource_id,
-                 google_apis::ENTRY_KIND_FILE));
-  message_loop()->RunUntilIdle();
-}
-
-TEST_F(APIUtilTest, UploadExistingFile) {
-  const base::FilePath kLocalFilePath(FPL("/tmp/dir/file"));
-
-  fake_drive_service()->LoadResourceListForWapi(
-      "chromeos/sync_file_system/upload_new_file.json");
-
-  scoped_ptr<base::Value> file_entry_data(
-      LoadJSONFile("chromeos/gdata/file_entry.json"));
-  scoped_ptr<ResourceEntry> existing_file_entry(
-      ResourceEntry::ExtractAndParse(*file_entry_data));
-
-  bool done = false;
-  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
-  std::string resource_id;
-  api_util()->UploadExistingFile(
-      existing_file_entry->resource_id(),
-      existing_file_entry->file_md5(),
-      kLocalFilePath,
-      base::Bind(&DidUploadFile, &done, &error, &resource_id));
-  message_loop()->RunUntilIdle();
-
-  EXPECT_TRUE(done);
-  EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
-  EXPECT_EQ(existing_file_entry->resource_id(), resource_id);
-
-  fake_drive_service()->SearchByTitle(
-      existing_file_entry->title(),
-      kOriginDirectoryResourceId,
-      base::Bind(&VerifyTitleUniqueness,
-                 FROM_HERE,
-                 existing_file_entry->resource_id(),
-                 google_apis::ENTRY_KIND_FILE));
-  message_loop()->RunUntilIdle();
-}
-
-TEST_F(APIUtilTest, UploadExistingFileInConflict) {
-  const std::string kResourceId = "file:resource_id";
-  const base::FilePath kLocalFilePath(FPL("/tmp/dir/file"));
-
-  // Since remote file's hash value is different from the expected one, it is
-  // expected to cancel upload the file and to return CONFLICT status code.
-  const std::string kExpectedRemoteFileMD5 = "123456";
-
-  fake_drive_service()->LoadResourceListForWapi(
-      "chromeos/sync_file_system/upload_new_file.json");
-
-  scoped_ptr<base::Value> file_entry_data(
-      LoadJSONFile("chromeos/gdata/file_entry.json"));
-  scoped_ptr<ResourceEntry> existing_file_entry(
-      ResourceEntry::ExtractAndParse(*file_entry_data));
-
-  bool done = false;
-  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
-  std::string resource_id;
-  api_util()->UploadExistingFile(
-      existing_file_entry->resource_id(),
-      kExpectedRemoteFileMD5,
-      kLocalFilePath,
-      base::Bind(&DidUploadFile, &done, &error, &resource_id));
-  message_loop()->RunUntilIdle();
-
-  EXPECT_TRUE(done);
-  EXPECT_EQ(google_apis::HTTP_CONFLICT, error);
-  EXPECT_TRUE(resource_id.empty());
-
-  // Verify that there is no duplicated file on the remote side.
-  fake_drive_service()->SearchByTitle(
-      existing_file_entry->title(),
-      kOriginDirectoryResourceId,
-      base::Bind(&VerifyTitleUniqueness,
-                 FROM_HERE,
-                 existing_file_entry->resource_id(),
-                 google_apis::ENTRY_KIND_FILE));
-  message_loop()->RunUntilIdle();
-}
-
-TEST_F(APIUtilTest, DeleteFile) {
-  const std::string kFileTitle = "testfile";
-  const std::string kResourceId = "file:file_resource_id";
-  const std::string kExpectedRemoteFileMD5 = "3b4382ebefec6e743578c76bbd0575ce";
-
-  fake_drive_service()->LoadResourceListForWapi(
-      "chromeos/sync_file_system/listing_files_in_directory.json");
-
-  bool done = false;
-  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
-  std::string resource_id;
-  api_util()->DeleteFile(kResourceId,
-                         kExpectedRemoteFileMD5,
-                         base::Bind(&DidDeleteFile, &done, &error));
-  message_loop()->RunUntilIdle();
-
-  EXPECT_TRUE(done);
-  EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
-
-  fake_drive_service()->SearchByTitle(
-      kFileTitle,
-      kOriginDirectoryResourceId,
-      base::Bind(&VerifyFileDeletion, FROM_HERE));
-  message_loop()->RunUntilIdle();
-}
-
-TEST_F(APIUtilTest, DeleteFileInConflict) {
-  const std::string kFileTitle = "testfile";
-  const std::string kResourceId = "file:file_resource_id";
-
-  fake_drive_service()->LoadResourceListForWapi(
-      "chromeos/sync_file_system/listing_files_in_directory.json");
-
-  // Since remote file's hash value is different from the expected one, it is
-  // expected to cancel delete the file and to return CONFLICT status code.
-  const std::string kExpectedRemoteFileMD5 = "123456";
-
-  bool done = false;
-  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
-  std::string resource_id;
-  api_util()->DeleteFile(kResourceId,
-                         kExpectedRemoteFileMD5,
-                         base::Bind(&DidDeleteFile, &done, &error));
-  message_loop()->RunUntilIdle();
-
-  EXPECT_TRUE(done);
-  EXPECT_EQ(google_apis::HTTP_CONFLICT, error);
-
-  // Verify that the conflict file was not deleted on the remote side.
-  fake_drive_service()->SearchByTitle(
-      kFileTitle,
-      kOriginDirectoryResourceId,
-      base::Bind(&VerifyTitleUniqueness,
-                 FROM_HERE,
-                 kResourceId,
-                 google_apis::ENTRY_KIND_FILE));
-  message_loop()->RunUntilIdle();
-}
-
-TEST_F(APIUtilTest, CreateDirectory) {
-  const std::string kDirectoryTitle("directory");
-
-  fake_drive_service()->LoadResourceListForWapi(
-      "chromeos/sync_file_system/origin_directory_found.json");
-
-  bool done = false;
-  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
-  std::string resource_id;
-  api_util()->CreateDirectory(
-      kOriginDirectoryResourceId,
-      kDirectoryTitle,
-      base::Bind(&DidGetResourceID, &done, &error, &resource_id));
-  message_loop()->RunUntilIdle();
-
-  EXPECT_TRUE(done);
-  EXPECT_EQ(google_apis::HTTP_CREATED, error);
-  EXPECT_FALSE(resource_id.empty());
-
-  fake_drive_service()->SearchByTitle(
-      kDirectoryTitle,
-      kOriginDirectoryResourceId,
-      base::Bind(&VerifyTitleUniqueness,
-                 FROM_HERE,
-                 resource_id,
-                 google_apis::ENTRY_KIND_FOLDER));
-  message_loop()->RunUntilIdle();
-}
-
-#endif  // !defined(OS_ANDROID)
-
-}  // namespace drive
-}  // namespace sync_file_system
diff --git a/chrome/browser/sync_file_system/drive/fake_api_util.cc b/chrome/browser/sync_file_system/drive/fake_api_util.cc
deleted file mode 100644
index f7e21b4..0000000
--- a/chrome/browser/sync_file_system/drive/fake_api_util.cc
+++ /dev/null
@@ -1,272 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/sync_file_system/drive/fake_api_util.h"
-
-#include <algorithm>
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/message_loop/message_loop_proxy.h"
-#include "chrome/browser/google_apis/drive_entry_kinds.h"
-
-namespace sync_file_system {
-namespace drive {
-
-bool FakeAPIUtil::RemoteResourceComparator::operator()(
-    const RemoteResource& left,
-    const RemoteResource& right) {
-  if (left.parent_resource_id != right.parent_resource_id)
-    return left.parent_resource_id < right.parent_resource_id;
-  if (left.parent_title != right.parent_title)
-    return left.parent_title < right.parent_title;
-  if (left.title != right.title)
-    return left.title < right.title;
-  if (left.resource_id != right.resource_id)
-    return left.resource_id < right.resource_id;
-  if (left.md5_checksum != right.md5_checksum)
-    return left.md5_checksum < right.md5_checksum;
-  if (left.deleted != right.deleted)
-    return left.deleted < right.deleted;
-  return left.changestamp < right.changestamp;
-}
-
-struct FakeAPIUtil::ChangeStampComparator {
-  bool operator()(const google_apis::ResourceEntry* left,
-                  const google_apis::ResourceEntry* right) {
-    return left->changestamp() < right->changestamp();
-  }
-};
-
-FakeAPIUtil::RemoteResource::RemoteResource()
-    : type(SYNC_FILE_TYPE_UNKNOWN), deleted(false), changestamp(0) {}
-
-FakeAPIUtil::RemoteResource::RemoteResource(
-    const std::string& parent_resource_id,
-    const std::string& parent_title,
-    const std::string& title,
-    const std::string& resource_id,
-    const std::string& md5_checksum,
-    SyncFileType type,
-    bool deleted,
-    int64 changestamp)
-    : parent_resource_id(parent_resource_id),
-      parent_title(parent_title),
-      title(title),
-      resource_id(resource_id),
-      md5_checksum(md5_checksum),
-      type(type),
-      deleted(deleted),
-      changestamp(changestamp) {}
-
-FakeAPIUtil::RemoteResource::~RemoteResource() {}
-
-FakeAPIUtil::FakeAPIUtil()
-    : largest_changestamp_(0),
-      url_generator_(
-          GURL(google_apis::GDataWapiUrlGenerator::kBaseUrlForProduction)) {}
-
-FakeAPIUtil::~FakeAPIUtil() {}
-
-void FakeAPIUtil::AddObserver(APIUtilObserver* observer) {}
-
-void FakeAPIUtil::RemoveObserver(APIUtilObserver* observer) {}
-
-void FakeAPIUtil::GetDriveDirectoryForSyncRoot(
-    const ResourceIdCallback& callback) {
-  base::MessageLoopProxy::current()->PostTask(
-      FROM_HERE,
-      base::Bind(callback,
-                 google_apis::HTTP_SUCCESS,
-                 "folder: sync_root_resource_id"));
-}
-
-void FakeAPIUtil::GetDriveDirectoryForOrigin(
-    const std::string& sync_root_resource_id,
-    const GURL& origin,
-    const ResourceIdCallback& callback) {
-  base::MessageLoopProxy::current()->PostTask(
-      FROM_HERE,
-      base::Bind(callback,
-                 google_apis::HTTP_SUCCESS,
-                 "folder resource_id for " + origin.host()));
-}
-
-void FakeAPIUtil::GetLargestChangeStamp(const ChangeStampCallback& callback) {
-  base::MessageLoopProxy::current()->PostTask(
-      FROM_HERE,
-      base::Bind(callback, google_apis::HTTP_SUCCESS, largest_changestamp_));
-}
-
-void FakeAPIUtil::GetResourceEntry(const std::string& resource_id,
-                                   const ResourceEntryCallback& callback) {
-  NOTREACHED();
-}
-
-void FakeAPIUtil::ListFiles(const std::string& directory_resource_id,
-                            const ResourceListCallback& callback) {
-  ListChanges(0, callback);
-}
-
-void FakeAPIUtil::ListChanges(int64 start_changestamp,
-                              const ResourceListCallback& callback) {
-  scoped_ptr<google_apis::ResourceList> change_feed(
-      new google_apis::ResourceList());
-
-  ScopedVector<google_apis::ResourceEntry> entries;
-  typedef RemoteResourceByResourceId::const_iterator iterator;
-  for (iterator itr = remote_resources_.begin();
-       itr != remote_resources_.end(); ++itr) {
-    if (itr->second.changestamp < start_changestamp)
-      continue;
-    scoped_ptr<google_apis::ResourceEntry> entry(
-        CreateResourceEntry(itr->second));
-    entries.push_back(entry.release());
-  }
-
-  std::sort(entries.begin(), entries.end(), ChangeStampComparator());
-
-  change_feed->set_entries(&entries);
-  change_feed->set_largest_changestamp(largest_changestamp_);
-
-  base::MessageLoopProxy::current()->PostTask(
-      FROM_HERE,
-      base::Bind(
-          callback, google_apis::HTTP_SUCCESS, base::Passed(&change_feed)));
-}
-
-void FakeAPIUtil::ContinueListing(const GURL& feed_url,
-                                  const ResourceListCallback& callback) {
-  NOTREACHED();
-}
-
-void FakeAPIUtil::DownloadFile(const std::string& resource_id,
-                               const std::string& local_file_md5,
-                               const base::FilePath& local_file_path,
-                               const DownloadFileCallback& callback) {
-  RemoteResourceByResourceId::iterator found =
-      remote_resources_.find(resource_id);
-  std::string file_md5;
-  int64 file_size = 0;
-  base::Time updated_time;
-  google_apis::GDataErrorCode error = google_apis::HTTP_NOT_FOUND;
-
-  if (found != remote_resources_.end() && !found->second.deleted) {
-    scoped_ptr<google_apis::ResourceEntry> entry(
-        CreateResourceEntry(found->second));
-    file_md5 = entry->file_md5();
-    file_size = entry->file_size();
-    updated_time = entry->updated_time();
-    error = google_apis::HTTP_SUCCESS;
-  }
-
-  base::MessageLoopProxy::current()->PostTask(
-      FROM_HERE,
-      base::Bind(callback, error, file_md5, file_size, updated_time));
-}
-
-void FakeAPIUtil::UploadNewFile(const std::string& directory_resource_id,
-                                const base::FilePath& local_file_path,
-                                const std::string& title,
-                                const UploadFileCallback& callback) {
-  NOTREACHED();
-}
-
-void FakeAPIUtil::UploadExistingFile(const std::string& resource_id,
-                                     const std::string& remote_file_md5,
-                                     const base::FilePath& local_file_path,
-                                     const UploadFileCallback& callback) {
-  NOTREACHED();
-}
-
-void FakeAPIUtil::CreateDirectory(const std::string& parent_resource_id,
-                                  const std::string& title,
-                                  const ResourceIdCallback& callback) {
-  NOTREACHED();
-}
-
-bool FakeAPIUtil::IsAuthenticated() const { return true; }
-
-void FakeAPIUtil::DeleteFile(const std::string& resource_id,
-                             const std::string& remote_file_md5,
-                             const GDataErrorCallback& callback) {
-  if (!ContainsKey(remote_resources_, resource_id)) {
-    base::MessageLoopProxy::current()->PostTask(
-        FROM_HERE,
-        base::Bind(callback, google_apis::HTTP_NOT_FOUND));
-    return;
-  }
-
-  const RemoteResource& deleted_directory = remote_resources_[resource_id];
-  PushRemoteChange(deleted_directory.parent_resource_id,
-                   deleted_directory.parent_title,
-                   deleted_directory.title,
-                   deleted_directory.resource_id,
-                   deleted_directory.md5_checksum,
-                   SYNC_FILE_TYPE_UNKNOWN,
-                   true /* deleted */);
-
-  base::MessageLoopProxy::current()->PostTask(
-      FROM_HERE,
-      base::Bind(callback, google_apis::HTTP_SUCCESS));
-}
-
-GURL FakeAPIUtil::ResourceIdToResourceLink(
-    const std::string& resource_id) const {
-  return url_generator_.GenerateEditUrl(resource_id);
-}
-
-void FakeAPIUtil::EnsureSyncRootIsNotInMyDrive(
-    const std::string& sync_root_resource_id) {
-  // Nothing to do.
-}
-
-void FakeAPIUtil::PushRemoteChange(const std::string& parent_resource_id,
-                                   const std::string& parent_title,
-                                   const std::string& title,
-                                   const std::string& resource_id,
-                                   const std::string& md5,
-                                   SyncFileType type,
-                                   bool deleted) {
-  remote_resources_[resource_id] = RemoteResource(
-      parent_resource_id, parent_title, title, resource_id,
-      md5, type, deleted, ++largest_changestamp_);
-}
-
-scoped_ptr<google_apis::ResourceEntry> FakeAPIUtil::CreateResourceEntry(
-    const RemoteResource& resource) const {
-  scoped_ptr<google_apis::ResourceEntry> entry(
-      new google_apis::ResourceEntry());
-  ScopedVector<google_apis::Link> parent_links;
-  scoped_ptr<google_apis::Link> link(new google_apis::Link());
-
-  link->set_type(google_apis::Link::LINK_PARENT);
-  link->set_href(ResourceIdToResourceLink(resource.parent_resource_id));
-  link->set_title(resource.parent_title);
-  parent_links.push_back(link.release());
-
-  entry->set_links(&parent_links);
-  entry->set_title(resource.title);
-  entry->set_resource_id(resource.resource_id);
-  entry->set_file_md5(resource.md5_checksum);
-  entry->set_deleted(resource.deleted);
-  entry->set_changestamp(resource.changestamp);
-
-  switch (resource.type) {
-    case SYNC_FILE_TYPE_FILE:
-      entry->set_kind(google_apis::ENTRY_KIND_FILE);
-      break;
-    case SYNC_FILE_TYPE_DIRECTORY:
-      entry->set_kind(google_apis::ENTRY_KIND_FOLDER);
-      break;
-    case SYNC_FILE_TYPE_UNKNOWN:
-      entry->set_kind(google_apis::ENTRY_KIND_UNKNOWN);
-      break;
-  }
-
-  return entry.Pass();
-}
-
-}  // namespace drive
-}  // namespace sync_file_system
diff --git a/chrome/browser/sync_file_system/drive/fake_api_util.h b/chrome/browser/sync_file_system/drive/fake_api_util.h
deleted file mode 100644
index 17096fd..0000000
--- a/chrome/browser/sync_file_system/drive/fake_api_util.h
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_FAKE_API_UTIL_H_
-#define CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_FAKE_API_UTIL_H_
-
-#include <map>
-#include <string>
-
-#include "chrome/browser/google_apis/drive_api_parser.h"
-#include "chrome/browser/google_apis/gdata_wapi_parser.h"
-#include "chrome/browser/google_apis/gdata_wapi_url_generator.h"
-#include "chrome/browser/sync_file_system/drive/api_util_interface.h"
-#include "webkit/browser/fileapi/syncable/sync_file_type.h"
-
-class GURL;
-class Profile;
-
-namespace google_apis {
-class ResourceEntry;
-}
-
-namespace sync_file_system {
-namespace drive {
-
-class FakeAPIUtil : public APIUtilInterface {
- public:
-  struct RemoteResource {
-    std::string parent_resource_id;
-    std::string parent_title;
-    std::string title;
-    std::string resource_id;
-    std::string md5_checksum;
-    SyncFileType type;
-    bool deleted;
-    int64 changestamp;
-
-    RemoteResource();
-    RemoteResource(const std::string& parent_resource_id,
-                   const std::string& parent_title,
-                   const std::string& title,
-                   const std::string& resource_id,
-                   const std::string& md5_checksum,
-                   SyncFileType type,
-                   bool deleted,
-                   int64 changestamp);
-    ~RemoteResource();
-  };
-
-  struct RemoteResourceComparator {
-    // Returns lexicographical order referring all members.
-    bool operator()(const RemoteResource& left, const RemoteResource& right);
-  };
-
-  typedef std::map<std::string, RemoteResource> RemoteResourceByResourceId;
-
-  FakeAPIUtil();
-  virtual ~FakeAPIUtil();
-
-  // APIUtilInterface overrides.
-  virtual void AddObserver(APIUtilObserver* observer) OVERRIDE;
-  virtual void RemoveObserver(APIUtilObserver* observer) OVERRIDE;
-  virtual void GetDriveDirectoryForSyncRoot(
-      const ResourceIdCallback& callback) OVERRIDE;
-  virtual void GetDriveDirectoryForOrigin(
-      const std::string& sync_root_resource_id,
-      const GURL& origin,
-      const ResourceIdCallback& callback) OVERRIDE;
-  virtual void GetLargestChangeStamp(
-      const ChangeStampCallback& callback) OVERRIDE;
-  virtual void GetResourceEntry(const std::string& resource_id,
-                                const ResourceEntryCallback& callback) OVERRIDE;
-  virtual void ListFiles(const std::string& directory_resource_id,
-                         const ResourceListCallback& callback) OVERRIDE;
-  virtual void ListChanges(int64 start_changestamp,
-                           const ResourceListCallback& callback) OVERRIDE;
-  virtual void ContinueListing(const GURL& feed_url,
-                               const ResourceListCallback& callback) OVERRIDE;
-  virtual void DownloadFile(const std::string& resource_id,
-                            const std::string& local_file_md5,
-                            const base::FilePath& local_file_path,
-                            const DownloadFileCallback& callback) OVERRIDE;
-  virtual void UploadNewFile(const std::string& directory_resource_id,
-                             const base::FilePath& local_file_path,
-                             const std::string& title,
-                             const UploadFileCallback& callback) OVERRIDE;
-  virtual void UploadExistingFile(const std::string& resource_id,
-                                  const std::string& remote_file_md5,
-                                  const base::FilePath& local_file_path,
-                                  const UploadFileCallback& callback) OVERRIDE;
-  virtual void CreateDirectory(const std::string& parent_resource_id,
-                               const std::string& title,
-                               const ResourceIdCallback& callback) OVERRIDE;
-  virtual bool IsAuthenticated() const OVERRIDE;
-  virtual void DeleteFile(const std::string& resource_id,
-                          const std::string& remote_file_md5,
-                          const GDataErrorCallback& callback) OVERRIDE;
-  virtual GURL ResourceIdToResourceLink(
-      const std::string& resource_id) const OVERRIDE;
-  virtual void EnsureSyncRootIsNotInMyDrive(
-      const std::string& sync_root_resource_id) OVERRIDE;
-
-  void PushRemoteChange(const std::string& parent_resource_id,
-                        const std::string& parent_title,
-                        const std::string& title,
-                        const std::string& resource_id,
-                        const std::string& md5,
-                        SyncFileType type,
-                        bool deleted);
-
-  const RemoteResourceByResourceId& remote_resources() const {
-    return remote_resources_;
-  }
-
- private:
-  struct ChangeStampComparator;
-  RemoteResourceByResourceId remote_resources_;
-
-  scoped_ptr<google_apis::ResourceEntry> CreateResourceEntry(
-      const RemoteResource& resource_id) const;
-
-  int64 largest_changestamp_;
-  google_apis::GDataWapiUrlGenerator url_generator_;
-
-  DISALLOW_COPY_AND_ASSIGN(FakeAPIUtil);
-};
-
-}  // namespace drive
-}  // namespace sync_file_system
-
-#endif  // CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_FAKE_API_UTIL_H_
diff --git a/chrome/browser/sync_file_system/drive/fake_api_util_unittest.cc b/chrome/browser/sync_file_system/drive/fake_api_util_unittest.cc
deleted file mode 100644
index ba146a2..0000000
--- a/chrome/browser/sync_file_system/drive/fake_api_util_unittest.cc
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/sync_file_system/drive/fake_api_util.h"
-
-#include <string>
-
-#include "base/bind.h"
-#include "base/files/file_path.h"
-#include "base/message_loop.h"
-#include "chrome/browser/google_apis/gdata_errorcode.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace sync_file_system {
-namespace drive {
-
-namespace {
-
-void DidDownloadFile(google_apis::GDataErrorCode* error_out,
-                     std::string* file_md5_out,
-                     google_apis::GDataErrorCode error,
-                     const std::string& file_md5,
-                     int64 file_size,
-                     const base::Time& updated_time) {
-  *error_out = error;
-  *file_md5_out = file_md5;
-}
-
-void DidGetChangeList(google_apis::GDataErrorCode* error_out,
-                      scoped_ptr<google_apis::ResourceList>* change_list_out,
-                      google_apis::GDataErrorCode error,
-                      scoped_ptr<google_apis::ResourceList> change_list) {
-  *error_out = error;
-  *change_list_out = change_list.Pass();
-}
-
-void DidDeleteFile(google_apis::GDataErrorCode* error_out,
-                   google_apis::GDataErrorCode error) {
-  *error_out = error;
-}
-
-}  // namespace
-
-TEST(FakeAPIUtilTest, ChangeSquashTest) {
-  base::MessageLoop message_loop;
-  FakeAPIUtil api_util;
-  std::string kParentResourceId("parent resource id");
-  std::string kParentTitle("app-id");
-  std::string kTitle1("title 1");
-  std::string kTitle2("title 2");
-  std::string kTitle3("title 3");
-  std::string kResourceId1("resource id 1");
-  std::string kResourceId2("resource id 2");
-  std::string kMD5_1("md5 1");
-  std::string kMD5_2("md5 2");
-  std::string kMD5_3("md5 3");
-  base::FilePath kTempFilePath(FILE_PATH_LITERAL("tmp_file"));
-
-  api_util.PushRemoteChange(kParentResourceId,
-                            kParentTitle,
-                            kTitle1,
-                            kResourceId1,
-                            kMD5_1,
-                            SYNC_FILE_TYPE_FILE,
-                            false /* deleted */);
-  api_util.PushRemoteChange(kParentResourceId,
-                            kParentTitle,
-                            kTitle1,
-                            kResourceId1,
-                            kMD5_1,
-                            SYNC_FILE_TYPE_FILE,
-                            false /* deleted */);
-  api_util.PushRemoteChange(kParentResourceId,
-                            kParentTitle,
-                            kTitle1,
-                            kResourceId1,
-                            kMD5_1,
-                            SYNC_FILE_TYPE_FILE,
-                            true /* deleted */);
-  api_util.PushRemoteChange(kParentResourceId,
-                            kParentTitle,
-                            kTitle2,
-                            kResourceId2,
-                            kMD5_2,
-                            SYNC_FILE_TYPE_FILE,
-                            false /* deleted */);
-  api_util.PushRemoteChange(kParentResourceId,
-                            kParentTitle,
-                            kTitle3,
-                            kResourceId2,
-                            kMD5_3,
-                            SYNC_FILE_TYPE_FILE,
-                            false /* deleted */);
-
-  google_apis::GDataErrorCode error;
-  std::string md5;
-  api_util.DownloadFile(kResourceId1,
-                        kMD5_1,
-                        kTempFilePath,
-                        base::Bind(DidDownloadFile, &error, &md5));
-  message_loop.RunUntilIdle();
-  EXPECT_EQ(google_apis::HTTP_NOT_FOUND, error);
-  EXPECT_TRUE(md5.empty());
-
-  scoped_ptr<google_apis::ResourceList> change_list;
-  api_util.ListChanges(0, base::Bind(&DidGetChangeList, &error, &change_list));
-  message_loop.RunUntilIdle();
-  EXPECT_EQ(2u, change_list->entries().size());
-
-  EXPECT_EQ(kResourceId1, change_list->entries()[0]->resource_id());
-  EXPECT_TRUE(change_list->entries()[0]->deleted());
-
-  EXPECT_EQ(kResourceId2, change_list->entries()[1]->resource_id());
-  EXPECT_EQ(kMD5_3, change_list->entries()[1]->file_md5());
-  EXPECT_FALSE(change_list->entries()[1]->deleted());
-}
-
-TEST(FakeAPIUtilTest, DeleteFile) {
-  base::MessageLoop message_loop;
-  FakeAPIUtil api_util;
-  std::string resource_id = "resource_id_to_be_deleted";
-  api_util.PushRemoteChange("parent_id",
-                            "parent_title",
-                            "resource_title",
-                            resource_id,
-                            "resource_md5",
-                            SYNC_FILE_TYPE_FILE,
-                            false /* deleted */);
-
-  google_apis::GDataErrorCode error = google_apis::HTTP_NOT_FOUND;
-  api_util.DeleteFile(
-      resource_id, std::string(), base::Bind(&DidDeleteFile, &error));
-  message_loop.RunUntilIdle();
-
-  EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
-  EXPECT_TRUE(api_util.remote_resources().find(resource_id)->second.deleted);
-}
-
-}  // namespace drive
-}  // namespace sync_file_system
diff --git a/chrome/browser/sync_file_system/drive/local_change_processor_delegate.cc b/chrome/browser/sync_file_system/drive/local_change_processor_delegate.cc
deleted file mode 100644
index 4c1d5f5..0000000
--- a/chrome/browser/sync_file_system/drive/local_change_processor_delegate.cc
+++ /dev/null
@@ -1,591 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/sync_file_system/drive/local_change_processor_delegate.h"
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "chrome/browser/sync_file_system/drive/api_util.h"
-#include "chrome/browser/sync_file_system/drive_file_sync_service.h"
-#include "chrome/browser/sync_file_system/drive_metadata_store.h"
-#include "chrome/browser/sync_file_system/logger.h"
-#include "webkit/browser/fileapi/syncable/syncable_file_system_util.h"
-
-namespace sync_file_system {
-namespace drive {
-
-LocalChangeProcessorDelegate::LocalChangeProcessorDelegate(
-    DriveFileSyncService* sync_service,
-    const FileChange& local_change,
-    const base::FilePath& local_path,
-    const SyncFileMetadata& local_metadata,
-    const fileapi::FileSystemURL& url)
-    : sync_service_(sync_service),
-      operation_(SYNC_OPERATION_NONE),
-      url_(url),
-      local_change_(local_change),
-      local_path_(local_path),
-      local_metadata_(local_metadata),
-      has_drive_metadata_(false),
-      has_remote_change_(false),
-      weak_factory_(this) {}
-
-LocalChangeProcessorDelegate::~LocalChangeProcessorDelegate() {}
-
-void LocalChangeProcessorDelegate::Run(const SyncStatusCallback& callback) {
-  // TODO(nhiroki): support directory operations (http://crbug.com/161442).
-  DCHECK(IsSyncFSDirectoryOperationEnabled() || !local_change_.IsDirectory());
-  operation_ = SYNC_OPERATION_NONE;
-
-  has_drive_metadata_ =
-      metadata_store()->ReadEntry(url_, &drive_metadata_) == SYNC_STATUS_OK;
-
-  if (!has_drive_metadata_)
-    drive_metadata_.set_md5_checksum(std::string());
-
-  sync_service_->EnsureOriginRootDirectory(
-      url_.origin(),
-      base::Bind(&LocalChangeProcessorDelegate::DidGetOriginRoot,
-                 weak_factory_.GetWeakPtr(),
-                 callback));
-}
-
-void LocalChangeProcessorDelegate::DidGetOriginRoot(
-    const SyncStatusCallback& callback,
-    SyncStatusCode status,
-    const std::string& origin_resource_id) {
-  if (status != SYNC_STATUS_OK) {
-    callback.Run(status);
-    return;
-  }
-
-  origin_resource_id_ = origin_resource_id;
-
-  has_remote_change_ =
-      remote_change_handler()->GetChangeForURL(url_, &remote_change_);
-  if (has_remote_change_ && drive_metadata_.resource_id().empty())
-    drive_metadata_.set_resource_id(remote_change_.resource_id);
-
-  SyncFileType remote_file_type =
-      has_remote_change_ ? remote_change_.change.file_type() :
-      has_drive_metadata_ ?
-          DriveFileSyncService::DriveMetadataResourceTypeToSyncFileType(
-              drive_metadata_.type())
-      : SYNC_FILE_TYPE_UNKNOWN;
-
-  DCHECK_EQ(SYNC_OPERATION_NONE, operation_);
-  operation_ = LocalSyncOperationResolver::Resolve(
-      local_change_,
-      has_remote_change_ ? &remote_change_.change : NULL,
-      has_drive_metadata_ ? &drive_metadata_ : NULL);
-
-  util::Log(logging::LOG_VERBOSE, FROM_HERE,
-            "ApplyLocalChange for %s local_change:%s ===> %s",
-            url_.DebugString().c_str(),
-            local_change_.DebugString().c_str(),
-            SyncOperationTypeToString(operation_));
-
-  switch (operation_) {
-    case SYNC_OPERATION_ADD_FILE:
-      UploadNewFile(callback);
-      return;
-    case SYNC_OPERATION_ADD_DIRECTORY:
-      CreateDirectory(callback);
-      return;
-    case SYNC_OPERATION_UPDATE_FILE:
-      UploadExistingFile(callback);
-      return;
-    case SYNC_OPERATION_DELETE:
-      Delete(callback);
-      return;
-    case SYNC_OPERATION_NONE:
-      callback.Run(SYNC_STATUS_OK);
-      return;
-    case SYNC_OPERATION_CONFLICT:
-      HandleConflict(callback);
-      return;
-    case SYNC_OPERATION_RESOLVE_TO_LOCAL:
-      ResolveToLocal(callback);
-      return;
-    case SYNC_OPERATION_RESOLVE_TO_REMOTE:
-      ResolveToRemote(callback, remote_file_type);
-      return;
-    case SYNC_OPERATION_DELETE_METADATA:
-      DeleteMetadata(base::Bind(
-          &LocalChangeProcessorDelegate::DidApplyLocalChange,
-          weak_factory_.GetWeakPtr(), callback, google_apis::HTTP_SUCCESS));
-      return;
-    case SYNC_OPERATION_FAIL: {
-      callback.Run(SYNC_STATUS_FAILED);
-      return;
-    }
-  }
-  NOTREACHED();
-  callback.Run(SYNC_STATUS_FAILED);
-}
-
-void LocalChangeProcessorDelegate::UploadNewFile(
-    const SyncStatusCallback& callback) {
-  api_util()->UploadNewFile(
-      origin_resource_id_,
-      local_path_,
-      DriveFileSyncService::PathToTitle(url_.path()),
-      base::Bind(&LocalChangeProcessorDelegate::DidUploadNewFile,
-                 weak_factory_.GetWeakPtr(), callback));
-}
-
-void LocalChangeProcessorDelegate::DidUploadNewFile(
-    const SyncStatusCallback& callback,
-    google_apis::GDataErrorCode error,
-    const std::string& resource_id,
-    const std::string& md5) {
-  switch (error) {
-    case google_apis::HTTP_CREATED:
-      UpdateMetadata(
-          resource_id, md5, DriveMetadata::RESOURCE_TYPE_FILE,
-          base::Bind(&LocalChangeProcessorDelegate::DidApplyLocalChange,
-                     weak_factory_.GetWeakPtr(), callback, error));
-      sync_service_->NotifyObserversFileStatusChanged(
-          url_,
-          SYNC_FILE_STATUS_SYNCED,
-          SYNC_ACTION_ADDED,
-          SYNC_DIRECTION_LOCAL_TO_REMOTE);
-      return;
-    case google_apis::HTTP_CONFLICT:
-      HandleCreationConflict(resource_id, DriveMetadata::RESOURCE_TYPE_FILE,
-                             callback);
-      return;
-    default:
-      callback.Run(GDataErrorCodeToSyncStatusCodeWrapper(error));
-  }
-}
-
-void LocalChangeProcessorDelegate::CreateDirectory(
-    const SyncStatusCallback& callback) {
-  DCHECK(IsSyncFSDirectoryOperationEnabled());
-  api_util()->CreateDirectory(
-      origin_resource_id_,
-      DriveFileSyncService::PathToTitle(url_.path()),
-      base::Bind(&LocalChangeProcessorDelegate::DidCreateDirectory,
-                 weak_factory_.GetWeakPtr(), callback));
-}
-
-void LocalChangeProcessorDelegate::DidCreateDirectory(
-    const SyncStatusCallback& callback,
-    google_apis::GDataErrorCode error,
-    const std::string& resource_id) {
-  switch (error) {
-    case google_apis::HTTP_SUCCESS:
-    case google_apis::HTTP_CREATED: {
-      UpdateMetadata(
-          resource_id, std::string(), DriveMetadata::RESOURCE_TYPE_FOLDER,
-          base::Bind(&LocalChangeProcessorDelegate::DidApplyLocalChange,
-                     weak_factory_.GetWeakPtr(), callback, error));
-      sync_service_->NotifyObserversFileStatusChanged(
-          url_,
-          SYNC_FILE_STATUS_SYNCED,
-          SYNC_ACTION_ADDED,
-          SYNC_DIRECTION_LOCAL_TO_REMOTE);
-      return;
-    }
-
-    case google_apis::HTTP_CONFLICT:
-      // There were conflicts and a file was left.
-      // TODO(kinuko): Handle the latter case (http://crbug.com/237090).
-      // Fall-through
-
-    default:
-      callback.Run(GDataErrorCodeToSyncStatusCodeWrapper(error));
-  }
-}
-
-void LocalChangeProcessorDelegate::UploadExistingFile(
-    const SyncStatusCallback& callback) {
-  DCHECK(has_drive_metadata_);
-  if (drive_metadata_.resource_id().empty()) {
-    UploadNewFile(callback);
-    return;
-  }
-
-  api_util()->UploadExistingFile(
-      drive_metadata_.resource_id(),
-      drive_metadata_.md5_checksum(),
-      local_path_,
-      base::Bind(&LocalChangeProcessorDelegate::DidUploadExistingFile,
-                 weak_factory_.GetWeakPtr(), callback));
-}
-
-void LocalChangeProcessorDelegate::DidUploadExistingFile(
-    const SyncStatusCallback& callback,
-    google_apis::GDataErrorCode error,
-    const std::string& resource_id,
-    const std::string& md5) {
-  DCHECK(has_drive_metadata_);
-  switch (error) {
-    case google_apis::HTTP_SUCCESS:
-      UpdateMetadata(
-          resource_id, md5, DriveMetadata::RESOURCE_TYPE_FILE,
-          base::Bind(&LocalChangeProcessorDelegate::DidApplyLocalChange,
-                     weak_factory_.GetWeakPtr(), callback, error));
-      sync_service_->NotifyObserversFileStatusChanged(
-          url_,
-          SYNC_FILE_STATUS_SYNCED,
-          SYNC_ACTION_UPDATED,
-          SYNC_DIRECTION_LOCAL_TO_REMOTE);
-      return;
-    case google_apis::HTTP_CONFLICT:
-      HandleConflict(callback);
-      return;
-    case google_apis::HTTP_NOT_MODIFIED:
-      DidApplyLocalChange(callback,
-                          google_apis::HTTP_SUCCESS, SYNC_STATUS_OK);
-      return;
-    case google_apis::HTTP_NOT_FOUND:
-      UploadNewFile(callback);
-      return;
-    default: {
-      const SyncStatusCode status =
-          GDataErrorCodeToSyncStatusCodeWrapper(error);
-      DCHECK_NE(SYNC_STATUS_OK, status);
-      callback.Run(status);
-      return;
-    }
-  }
-}
-
-void LocalChangeProcessorDelegate::Delete(
-    const SyncStatusCallback& callback) {
-  if (!has_drive_metadata_) {
-    callback.Run(SYNC_STATUS_OK);
-    return;
-  }
-
-  if (drive_metadata_.resource_id().empty()) {
-    DidDelete(callback, google_apis::HTTP_NOT_FOUND);
-    return;
-  }
-
-  api_util()->DeleteFile(
-      drive_metadata_.resource_id(),
-      drive_metadata_.md5_checksum(),
-      base::Bind(&LocalChangeProcessorDelegate::DidDelete,
-                 weak_factory_.GetWeakPtr(), callback));
-}
-
-void LocalChangeProcessorDelegate::DidDelete(
-    const SyncStatusCallback& callback,
-    google_apis::GDataErrorCode error) {
-  DCHECK(has_drive_metadata_);
-
-  switch (error) {
-    case google_apis::HTTP_SUCCESS:
-    case google_apis::HTTP_NOT_FOUND:
-      DeleteMetadata(base::Bind(
-          &LocalChangeProcessorDelegate::DidApplyLocalChange,
-          weak_factory_.GetWeakPtr(), callback, google_apis::HTTP_SUCCESS));
-      sync_service_->NotifyObserversFileStatusChanged(
-          url_,
-          SYNC_FILE_STATUS_SYNCED,
-          SYNC_ACTION_DELETED,
-          SYNC_DIRECTION_LOCAL_TO_REMOTE);
-      return;
-    case google_apis::HTTP_PRECONDITION:
-    case google_apis::HTTP_CONFLICT:
-      // Delete |drive_metadata| on the conflict case.
-      // Conflicted remote change should be applied as a future remote change.
-      DeleteMetadata(base::Bind(
-          &LocalChangeProcessorDelegate::DidDeleteMetadataForDeletionConflict,
-          weak_factory_.GetWeakPtr(), callback));
-      sync_service_->NotifyObserversFileStatusChanged(
-          url_,
-          SYNC_FILE_STATUS_SYNCED,
-          SYNC_ACTION_DELETED,
-          SYNC_DIRECTION_LOCAL_TO_REMOTE);
-      return;
-    default: {
-      const SyncStatusCode status =
-          GDataErrorCodeToSyncStatusCodeWrapper(error);
-      DCHECK_NE(SYNC_STATUS_OK, status);
-      callback.Run(status);
-      return;
-    }
-  }
-}
-
-void LocalChangeProcessorDelegate::DidDeleteMetadataForDeletionConflict(
-    const SyncStatusCallback& callback,
-    SyncStatusCode status) {
-  callback.Run(SYNC_STATUS_OK);
-}
-
-void LocalChangeProcessorDelegate::ResolveToLocal(
-    const SyncStatusCallback& callback) {
-  if (drive_metadata_.resource_id().empty()) {
-    DidDeleteFileToResolveToLocal(callback, google_apis::HTTP_NOT_FOUND);
-    return;
-  }
-
-  api_util()->DeleteFile(
-      drive_metadata_.resource_id(),
-      drive_metadata_.md5_checksum(),
-      base::Bind(
-          &LocalChangeProcessorDelegate::DidDeleteFileToResolveToLocal,
-          weak_factory_.GetWeakPtr(), callback));
-}
-
-void LocalChangeProcessorDelegate::DidDeleteFileToResolveToLocal(
-    const SyncStatusCallback& callback,
-    google_apis::GDataErrorCode error) {
-  if (error != google_apis::HTTP_SUCCESS &&
-      error != google_apis::HTTP_NOT_FOUND) {
-    callback.Run(GDataErrorCodeToSyncStatusCodeWrapper(error));
-    return;
-  }
-
-  DCHECK_NE(SYNC_FILE_TYPE_UNKNOWN, local_metadata_.file_type);
-  if (local_metadata_.file_type == SYNC_FILE_TYPE_FILE) {
-    UploadNewFile(callback);
-    return;
-  }
-
-  DCHECK(IsSyncFSDirectoryOperationEnabled());
-  DCHECK_EQ(SYNC_FILE_TYPE_DIRECTORY, local_metadata_.file_type);
-  CreateDirectory(callback);
-}
-
-void LocalChangeProcessorDelegate::ResolveToRemote(
-    const SyncStatusCallback& callback,
-    SyncFileType remote_file_type) {
-  // Mark the file as to-be-fetched.
-  DCHECK(!drive_metadata_.resource_id().empty());
-
-  SetMetadataToBeFetched(
-      DriveFileSyncService::SyncFileTypeToDriveMetadataResourceType(
-          remote_file_type),
-      base::Bind(&LocalChangeProcessorDelegate::DidResolveToRemote,
-                 weak_factory_.GetWeakPtr(), callback));
-  // The synced notification will be dispatched when the remote file is
-  // downloaded.
-}
-
-void LocalChangeProcessorDelegate::DidResolveToRemote(
-    const SyncStatusCallback& callback,
-    SyncStatusCode status) {
-  DCHECK(has_drive_metadata_);
-  if (status != SYNC_STATUS_OK) {
-    callback.Run(status);
-    return;
-  }
-
-  SyncFileType file_type = SYNC_FILE_TYPE_FILE;
-  if (drive_metadata_.type() == DriveMetadata::RESOURCE_TYPE_FOLDER)
-    file_type = SYNC_FILE_TYPE_DIRECTORY;
-  sync_service_->AppendFetchChange(
-      url_.origin(), url_.path(), drive_metadata_.resource_id(), file_type);
-  callback.Run(status);
-}
-
-void LocalChangeProcessorDelegate::DidApplyLocalChange(
-    const SyncStatusCallback& callback,
-    const google_apis::GDataErrorCode error,
-    SyncStatusCode status) {
-  if ((operation_ == SYNC_OPERATION_DELETE ||
-       operation_ == SYNC_OPERATION_DELETE_METADATA) &&
-      (status == SYNC_FILE_ERROR_NOT_FOUND ||
-       status == SYNC_DATABASE_ERROR_NOT_FOUND)) {
-    status = SYNC_STATUS_OK;
-  }
-
-  if (status == SYNC_STATUS_OK) {
-    remote_change_handler()->RemoveChangeForURL(url_);
-    status = GDataErrorCodeToSyncStatusCodeWrapper(error);
-  }
-  callback.Run(status);
-}
-
-void LocalChangeProcessorDelegate::UpdateMetadata(
-    const std::string& resource_id,
-    const std::string& md5,
-    DriveMetadata::ResourceType type,
-    const SyncStatusCallback& callback) {
-  has_drive_metadata_ = true;
-  drive_metadata_.set_resource_id(resource_id);
-  drive_metadata_.set_md5_checksum(md5);
-  drive_metadata_.set_conflicted(false);
-  drive_metadata_.set_to_be_fetched(false);
-  drive_metadata_.set_type(type);
-  metadata_store()->UpdateEntry(url_, drive_metadata_, callback);
-}
-
-void LocalChangeProcessorDelegate::ResetMetadataMD5(
-    const SyncStatusCallback& callback) {
-  has_drive_metadata_ = true;
-  drive_metadata_.set_md5_checksum(std::string());
-  metadata_store()->UpdateEntry(url_, drive_metadata_, callback);
-}
-
-void LocalChangeProcessorDelegate::SetMetadataToBeFetched(
-    DriveMetadata::ResourceType type,
-    const SyncStatusCallback& callback) {
-  has_drive_metadata_ = true;
-  drive_metadata_.set_md5_checksum(std::string());
-  drive_metadata_.set_conflicted(false);
-  drive_metadata_.set_to_be_fetched(true);
-  drive_metadata_.set_type(type);
-  metadata_store()->UpdateEntry(url_, drive_metadata_, callback);
-}
-
-void LocalChangeProcessorDelegate::SetMetadataConflict(
-    const SyncStatusCallback& callback) {
-  has_drive_metadata_ = true;
-  drive_metadata_.set_conflicted(true);
-  drive_metadata_.set_to_be_fetched(false);
-  metadata_store()->UpdateEntry(url_, drive_metadata_, callback);
-}
-
-void LocalChangeProcessorDelegate::DeleteMetadata(
-    const SyncStatusCallback& callback) {
-  metadata_store()->DeleteEntry(url_, callback);
-}
-
-void LocalChangeProcessorDelegate::HandleCreationConflict(
-    const std::string& resource_id,
-    DriveMetadata::ResourceType type,
-    const SyncStatusCallback& callback) {
-  // File-file conflict is found.
-  // Populates a fake drive_metadata and set has_drive_metadata = true.
-  // In HandleConflictLocalSync:
-  // - If conflict_resolution is manual, we'll change conflicted to true
-  //   and save the metadata.
-  // - Otherwise we'll save the metadata with empty md5 and will start
-  //   over local sync as UploadExistingFile.
-  drive_metadata_.set_resource_id(resource_id);
-  drive_metadata_.set_md5_checksum(std::string());
-  drive_metadata_.set_conflicted(false);
-  drive_metadata_.set_to_be_fetched(false);
-  drive_metadata_.set_type(type);
-  has_drive_metadata_ = true;
-  HandleConflict(callback);
-}
-
-void LocalChangeProcessorDelegate::HandleConflict(
-    const SyncStatusCallback& callback) {
-  DCHECK(!drive_metadata_.resource_id().empty());
-  api_util()->GetResourceEntry(
-      drive_metadata_.resource_id(),
-      base::Bind(
-          &LocalChangeProcessorDelegate::DidGetEntryForConflictResolution,
-          weak_factory_.GetWeakPtr(), callback));
-}
-
-void LocalChangeProcessorDelegate::DidGetEntryForConflictResolution(
-    const SyncStatusCallback& callback,
-    google_apis::GDataErrorCode error,
-    scoped_ptr<google_apis::ResourceEntry> entry) {
-  SyncFileType remote_file_type = SYNC_FILE_TYPE_UNKNOWN;
-  DriveFileSyncService::ConflictResolutionResult resolution;
-
-  if (error != google_apis::HTTP_SUCCESS) {
-    resolution = DriveFileSyncService::CONFLICT_RESOLUTION_LOCAL_WIN;
-  } else {
-    SyncFileType local_file_type = local_metadata_.file_type;
-    base::Time local_modification_time = local_metadata_.last_modified;
-
-    base::Time remote_modification_time = entry->updated_time();
-    if (entry->is_file())
-      remote_file_type = SYNC_FILE_TYPE_FILE;
-    else if (entry->is_folder())
-      remote_file_type = SYNC_FILE_TYPE_DIRECTORY;
-    else
-      remote_file_type = SYNC_FILE_TYPE_UNKNOWN;
-
-    resolution = sync_service_->ResolveConflictForLocalSync(
-        local_file_type, local_modification_time,
-        remote_file_type, remote_modification_time);
-  }
-
-  switch (resolution) {
-    case DriveFileSyncService::CONFLICT_RESOLUTION_MARK_CONFLICT:
-      HandleManualResolutionCase(callback);
-      return;
-    case DriveFileSyncService::CONFLICT_RESOLUTION_LOCAL_WIN:
-      HandleLocalWinCase(callback);
-      return;
-    case DriveFileSyncService::CONFLICT_RESOLUTION_REMOTE_WIN:
-      HandleRemoteWinCase(callback, remote_file_type);
-      return;
-  }
-  NOTREACHED();
-  callback.Run(SYNC_STATUS_FAILED);
-}
-
-void LocalChangeProcessorDelegate::HandleManualResolutionCase(
-    const SyncStatusCallback& callback) {
-  if (drive_metadata_.conflicted()) {
-    callback.Run(SYNC_STATUS_HAS_CONFLICT);
-    return;
-  }
-
-  SetMetadataConflict(
-      base::Bind(&LocalChangeProcessorDelegate::DidApplyLocalChange,
-                 weak_factory_.GetWeakPtr(), callback,
-                 google_apis::HTTP_CONFLICT));
-}
-
-void LocalChangeProcessorDelegate::HandleLocalWinCase(
-    const SyncStatusCallback& callback) {
-  util::Log(logging::LOG_VERBOSE, FROM_HERE,
-            "Resolving conflict for local sync: %s: LOCAL WIN",
-            url_.DebugString().c_str());
-
-  DCHECK(!drive_metadata_.resource_id().empty());
-  if (!has_drive_metadata_) {
-    StartOver(callback, SYNC_STATUS_OK);
-    return;
-  }
-
-  ResetMetadataMD5(base::Bind(&LocalChangeProcessorDelegate::StartOver,
-                              weak_factory_.GetWeakPtr(), callback));
-}
-
-void LocalChangeProcessorDelegate::HandleRemoteWinCase(
-    const SyncStatusCallback& callback,
-    SyncFileType remote_file_type) {
-  util::Log(logging::LOG_VERBOSE, FROM_HERE,
-            "Resolving conflict for local sync: %s: REMOTE WIN",
-            url_.DebugString().c_str());
-  ResolveToRemote(callback, remote_file_type);
-}
-
-void LocalChangeProcessorDelegate::StartOver(const SyncStatusCallback& callback,
-                                             SyncStatusCode status) {
-  if (status != SYNC_STATUS_OK) {
-    callback.Run(status);
-    return;
-  }
-
-  remote_change_handler()->RemoveChangeForURL(url_);
-  Run(callback);
-}
-
-SyncStatusCode
-LocalChangeProcessorDelegate::GDataErrorCodeToSyncStatusCodeWrapper(
-    google_apis::GDataErrorCode error) {
-  return sync_service_->GDataErrorCodeToSyncStatusCodeWrapper(error);
-}
-
-DriveMetadataStore* LocalChangeProcessorDelegate::metadata_store() {
-  return sync_service_->metadata_store_.get();
-}
-
-APIUtilInterface* LocalChangeProcessorDelegate::api_util() {
-  return sync_service_->api_util_.get();
-}
-
-RemoteChangeHandler* LocalChangeProcessorDelegate::remote_change_handler() {
-  return &sync_service_->remote_change_handler_;
-}
-
-}  // namespace drive
-}  // namespace sync_file_system
diff --git a/chrome/browser/sync_file_system/drive/local_change_processor_delegate.h b/chrome/browser/sync_file_system/drive/local_change_processor_delegate.h
deleted file mode 100644
index d9450cf..0000000
--- a/chrome/browser/sync_file_system/drive/local_change_processor_delegate.h
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_LOCAL_CHANGE_PROCESSOR_DELEGATE_H_
-#define CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_LOCAL_CHANGE_PROCESSOR_DELEGATE_H_
-
-#include "base/callback.h"
-#include "base/memory/weak_ptr.h"
-#include "chrome/browser/sync_file_system/drive_file_sync_service.h"
-#include "chrome/browser/sync_file_system/sync_file_system.pb.h"
-#include "webkit/browser/fileapi/file_system_url.h"
-#include "webkit/browser/fileapi/syncable/file_change.h"
-#include "webkit/browser/fileapi/syncable/sync_callbacks.h"
-#include "webkit/browser/fileapi/syncable/sync_file_metadata.h"
-
-namespace sync_file_system {
-
-class DriveMetadataStore;
-
-namespace drive {
-
-class APIUtil;
-
-// This class handles ApplyLocalChange in LocalChangeProcessor, and its instance
-// represents single ApplyLocalChange operation.
-// The caller is responsible to own the instance, and can cancel operation by
-// deleting the instance or |sync_service|.
-class LocalChangeProcessorDelegate {
- public:
-  typedef RemoteChangeHandler::RemoteChange RemoteChange;
-
-  LocalChangeProcessorDelegate(
-      DriveFileSyncService* sync_service,
-      const FileChange& change,
-      const base::FilePath& local_file_path,
-      const SyncFileMetadata& local_file_metadata,
-      const fileapi::FileSystemURL& url);
-  ~LocalChangeProcessorDelegate();
-
-  void Run(const SyncStatusCallback& callback);
-
- private:
-  void DidGetOriginRoot(const SyncStatusCallback& callback,
-                        SyncStatusCode status,
-                        const std::string& resource_id);
-  void UploadNewFile(const SyncStatusCallback& callback);
-  void DidUploadNewFile(const SyncStatusCallback& callback,
-                        google_apis::GDataErrorCode error,
-                        const std::string& resource_id,
-                        const std::string& md5);
-  void CreateDirectory(const SyncStatusCallback& callback);
-  void DidCreateDirectory(
-      const SyncStatusCallback& callback,
-      google_apis::GDataErrorCode error,
-      const std::string& resource_id);
-  void UploadExistingFile(const SyncStatusCallback& callback);
-  void DidUploadExistingFile(
-      const SyncStatusCallback& callback,
-      google_apis::GDataErrorCode error,
-      const std::string& resource_id,
-      const std::string& md5);
-  void Delete(const SyncStatusCallback& callback);
-  void DidDelete(const SyncStatusCallback& callback,
-                 google_apis::GDataErrorCode error);
-  void DidDeleteMetadataForDeletionConflict(
-      const SyncStatusCallback& callback,
-      SyncStatusCode status);
-  void ResolveToLocal(const SyncStatusCallback& callback);
-  void DidDeleteFileToResolveToLocal(
-      const SyncStatusCallback& callback,
-      google_apis::GDataErrorCode error);
-  void ResolveToRemote(const SyncStatusCallback& callback,
-                       SyncFileType remote_file_type);
-  void DidResolveToRemote(const SyncStatusCallback& callback,
-                          SyncStatusCode status);
-  void DidApplyLocalChange(
-      const SyncStatusCallback& callback,
-      const google_apis::GDataErrorCode error,
-      SyncStatusCode status);
-
-  // Metadata manipulation.
-  void UpdateMetadata(const std::string& resource_id,
-                      const std::string& md5,
-                      DriveMetadata::ResourceType type,
-                      const SyncStatusCallback& callback);
-  void ResetMetadataMD5(const SyncStatusCallback& callback);
-  void SetMetadataToBeFetched(DriveMetadata::ResourceType type,
-                              const SyncStatusCallback& callback);
-  void DeleteMetadata(const SyncStatusCallback& callback);
-  void SetMetadataConflict(const SyncStatusCallback& callback);
-
-  // Conflict handling.
-  void HandleCreationConflict(
-      const std::string& resource_id,
-      DriveMetadata::ResourceType type,
-      const SyncStatusCallback& callback);
-  void HandleConflict(const SyncStatusCallback& callback);
-  void DidGetEntryForConflictResolution(
-      const SyncStatusCallback& callback,
-      google_apis::GDataErrorCode error,
-      scoped_ptr<google_apis::ResourceEntry> entry);
-
-  void HandleManualResolutionCase(const SyncStatusCallback& callback);
-  void HandleLocalWinCase(const SyncStatusCallback& callback);
-  void HandleRemoteWinCase(const SyncStatusCallback& callback,
-                           SyncFileType remote_file_type);
-  void StartOver(const SyncStatusCallback& callback, SyncStatusCode status);
-
-  SyncStatusCode GDataErrorCodeToSyncStatusCodeWrapper(
-      google_apis::GDataErrorCode error);
-
-  DriveMetadataStore* metadata_store();
-  drive::APIUtilInterface* api_util();
-  RemoteChangeHandler* remote_change_handler();
-
-  DriveFileSyncService* sync_service_;  // Not owned.
-
-  SyncOperationType operation_;
-
-  fileapi::FileSystemURL url_;
-  FileChange local_change_;
-  base::FilePath local_path_;
-  SyncFileMetadata local_metadata_;
-  DriveMetadata drive_metadata_;
-  bool has_drive_metadata_;
-  RemoteChange remote_change_;
-  bool has_remote_change_;
-
-  std::string origin_resource_id_;
-
-  base::WeakPtrFactory<LocalChangeProcessorDelegate> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(LocalChangeProcessorDelegate);
-};
-
-}  // namespace drive
-}  // namespace sync_file_system
-
-#endif  // CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_LOCAL_CHANGE_PROCESSOR_DELEGATE_H_
diff --git a/chrome/browser/sync_file_system/drive/metadata_db_migration_util.cc b/chrome/browser/sync_file_system/drive/metadata_db_migration_util.cc
deleted file mode 100644
index 96099c1..0000000
--- a/chrome/browser/sync_file_system/drive/metadata_db_migration_util.cc
+++ /dev/null
@@ -1,251 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/sync_file_system/drive/metadata_db_migration_util.h"
-
-#include "base/files/file_path.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/strings/string_util.h"
-#include "googleurl/src/gurl.h"
-#include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
-#include "webkit/browser/fileapi/file_system_url.h"
-#include "webkit/common/fileapi/file_system_types.h"
-
-namespace sync_file_system {
-namespace drive {
-
-namespace {
-
-const base::FilePath::CharType kV0FormatPathPrefix[] =
-    FILE_PATH_LITERAL("drive/");
-const char kWapiFileIdPrefix[] = "file:";
-const char kWapiFolderIdPrefix[] = "folder:";
-
-std::string RemovePrefix(const std::string& str, const std::string& prefix) {
-  if (StartsWithASCII(str, prefix, true))
-    return std::string(str.begin() + prefix.size(), str.end());
-  return str;
-}
-
-}  // namespace
-
-bool ParseV0FormatFileSystemURL(const GURL& url,
-                                GURL* origin,
-                                base::FilePath* path) {
-  fileapi::FileSystemType mount_type;
-  base::FilePath virtual_path;
-
-  if (!fileapi::FileSystemURL::ParseFileSystemSchemeURL(
-          url, origin, &mount_type, &virtual_path) ||
-      mount_type != fileapi::kFileSystemTypeExternal) {
-    NOTREACHED() << "Failed to parse filesystem scheme URL " << url.spec();
-    return false;
-  }
-
-  base::FilePath::StringType prefix =
-      base::FilePath(kV0FormatPathPrefix).NormalizePathSeparators().value();
-  if (virtual_path.value().substr(0, prefix.size()) != prefix)
-    return false;
-
-  *path = base::FilePath(virtual_path.value().substr(prefix.size()));
-  return true;
-}
-
-std::string AddWapiFilePrefix(const std::string& resource_id) {
-  DCHECK(!StartsWithASCII(resource_id, kWapiFileIdPrefix, true));
-  DCHECK(!StartsWithASCII(resource_id, kWapiFolderIdPrefix, true));
-
-  if (resource_id.empty() ||
-      StartsWithASCII(resource_id, kWapiFileIdPrefix, true) ||
-      StartsWithASCII(resource_id, kWapiFolderIdPrefix, true))
-    return resource_id;
-  return kWapiFileIdPrefix + resource_id;
-}
-
-std::string AddWapiFolderPrefix(const std::string& resource_id) {
-  DCHECK(!StartsWithASCII(resource_id, kWapiFileIdPrefix, true));
-  DCHECK(!StartsWithASCII(resource_id, kWapiFolderIdPrefix, true));
-
-  if (resource_id.empty() ||
-      StartsWithASCII(resource_id, kWapiFileIdPrefix, true) ||
-      StartsWithASCII(resource_id, kWapiFolderIdPrefix, true))
-    return resource_id;
-  return kWapiFolderIdPrefix + resource_id;
-}
-
-std::string AddWapiIdPrefix(const std::string& resource_id,
-                            DriveMetadata_ResourceType type) {
-  switch (type) {
-    case DriveMetadata_ResourceType_RESOURCE_TYPE_FILE:
-      return AddWapiFilePrefix(resource_id);
-    case DriveMetadata_ResourceType_RESOURCE_TYPE_FOLDER:
-      return AddWapiFolderPrefix(resource_id);
-  }
-  NOTREACHED();
-  return resource_id;
-}
-
-std::string RemoveWapiIdPrefix(const std::string& resource_id) {
-  if (StartsWithASCII(resource_id, kWapiFileIdPrefix, true))
-    return RemovePrefix(resource_id, kWapiFileIdPrefix);
-  if (StartsWithASCII(resource_id, kWapiFolderIdPrefix, true))
-    return RemovePrefix(resource_id, kWapiFolderIdPrefix);
-  return resource_id;
-}
-
-SyncStatusCode MigrateDatabaseFromV0ToV1(leveldb::DB* db) {
-  // Version 0 database format:
-  //   key: "CHANGE_STAMP"
-  //   value: <Largest Changestamp>
-  //
-  //   key: "SYNC_ROOT_DIR"
-  //   value: <Resource ID of the sync root directory>
-  //
-  //   key: "METADATA: " +
-  //        <FileSystemURL serialized by SerializeSyncableFileSystemURL>
-  //   value: <Serialized DriveMetadata>
-  //
-  //   key: "BSYNC_ORIGIN: " + <URL string of a batch sync origin>
-  //   value: <Resource ID of the drive directory for the origin>
-  //
-  //   key: "ISYNC_ORIGIN: " + <URL string of a incremental sync origin>
-  //   value: <Resource ID of the drive directory for the origin>
-  //
-  // Version 1 database format (changed keys/fields are marked with '*'):
-  // * key: "VERSION" (new)
-  // * value: 1
-  //
-  //   key: "CHANGE_STAMP"
-  //   value: <Largest Changestamp>
-  //
-  //   key: "SYNC_ROOT_DIR"
-  //   value: <Resource ID of the sync root directory>
-  //
-  // * key: "METADATA: " + <Origin and URL> (changed)
-  // * value: <Serialized DriveMetadata>
-  //
-  //   key: "BSYNC_ORIGIN: " + <URL string of a batch sync origin>
-  //   value: <Resource ID of the drive directory for the origin>
-  //
-  //   key: "ISYNC_ORIGIN: " + <URL string of a incremental sync origin>
-  //   value: <Resource ID of the drive directory for the origin>
-  //
-  //   key: "DISABLED_ORIGIN: " + <URL string of a disabled origin>
-  //   value: <Resource ID of the drive directory for the origin>
-
-  const char kDatabaseVersionKey[] = "VERSION";
-  const char kDriveMetadataKeyPrefix[] = "METADATA: ";
-  const char kMetadataKeySeparator = ' ';
-
-  leveldb::WriteBatch write_batch;
-  write_batch.Put(kDatabaseVersionKey, "1");
-
-  scoped_ptr<leveldb::Iterator> itr(db->NewIterator(leveldb::ReadOptions()));
-  for (itr->Seek(kDriveMetadataKeyPrefix); itr->Valid(); itr->Next()) {
-    std::string key = itr->key().ToString();
-    if (!StartsWithASCII(key, kDriveMetadataKeyPrefix, true))
-      break;
-    std::string serialized_url(RemovePrefix(key, kDriveMetadataKeyPrefix));
-
-    GURL origin;
-    base::FilePath path;
-    bool success = ParseV0FormatFileSystemURL(
-        GURL(serialized_url), &origin, &path);
-    DCHECK(success) << serialized_url;
-    std::string new_key = kDriveMetadataKeyPrefix + origin.spec() +
-        kMetadataKeySeparator + path.AsUTF8Unsafe();
-
-    write_batch.Put(new_key, itr->value());
-    write_batch.Delete(key);
-  }
-
-  return LevelDBStatusToSyncStatusCode(
-      db->Write(leveldb::WriteOptions(), &write_batch));
-}
-
-SyncStatusCode MigrateDatabaseFromV1ToV2(leveldb::DB* db) {
-  // Strips prefix of WAPI resource ID, and discards batch sync origins.
-  // (i.e. "file:xxxx" => "xxxx", "folder:yyyy" => "yyyy")
-  //
-  // Version 2 database format (changed keys/fields are marked with '*'):
-  //   key: "VERSION"
-  // * value: 2
-  //
-  //   key: "CHANGE_STAMP"
-  //   value: <Largest Changestamp>
-  //
-  //   key: "SYNC_ROOT_DIR"
-  // * value: <Resource ID of the sync root directory> (striped)
-  //
-  //   key: "METADATA: " + <Origin and URL>
-  // * value: <Serialized DriveMetadata> (stripped)
-  //
-  // * key: "BSYNC_ORIGIN: " + <URL string of a batch sync origin> (deleted)
-  // * value: <Resource ID of the drive directory for the origin> (deleted)
-  //
-  //   key: "ISYNC_ORIGIN: " + <URL string of a incremental sync origin>
-  // * value: <Resource ID of the drive directory for the origin> (stripped)
-  //
-  //   key: "DISABLED_ORIGIN: " + <URL string of a disabled origin>
-  // * value: <Resource ID of the drive directory for the origin> (stripped)
-
-  const char kDatabaseVersionKey[] = "VERSION";
-  const char kSyncRootDirectoryKey[] = "SYNC_ROOT_DIR";
-  const char kDriveMetadataKeyPrefix[] = "METADATA: ";
-  const char kDriveBatchSyncOriginKeyPrefix[] = "BSYNC_ORIGIN: ";
-  const char kDriveIncrementalSyncOriginKeyPrefix[] = "ISYNC_ORIGIN: ";
-  const char kDriveDisabledOriginKeyPrefix[] = "DISABLED_ORIGIN: ";
-
-  leveldb::WriteBatch write_batch;
-  write_batch.Put(kDatabaseVersionKey, "2");
-
-  scoped_ptr<leveldb::Iterator> itr(db->NewIterator(leveldb::ReadOptions()));
-  for (itr->SeekToFirst(); itr->Valid(); itr->Next()) {
-    std::string key = itr->key().ToString();
-
-    // Strip resource id for the sync root directory.
-    if (StartsWithASCII(key, kSyncRootDirectoryKey, true)) {
-      write_batch.Put(key, RemoveWapiIdPrefix(itr->value().ToString()));
-      continue;
-    }
-
-    // Strip resource ids in the drive metadata.
-    if (StartsWithASCII(key, kDriveMetadataKeyPrefix, true)) {
-      DriveMetadata metadata;
-      bool success = metadata.ParseFromString(itr->value().ToString());
-      DCHECK(success);
-
-      metadata.set_resource_id(RemoveWapiIdPrefix(metadata.resource_id()));
-      std::string metadata_string;
-      metadata.SerializeToString(&metadata_string);
-
-      write_batch.Put(key, metadata_string);
-      continue;
-    }
-
-    // Deprecate legacy batch sync origin entries that are no longer needed.
-    if (StartsWithASCII(key, kDriveBatchSyncOriginKeyPrefix, true)) {
-      write_batch.Delete(key);
-      continue;
-    }
-
-    // Strip resource ids of the incremental sync origins.
-    if (StartsWithASCII(key, kDriveIncrementalSyncOriginKeyPrefix, true)) {
-      write_batch.Put(key, RemoveWapiIdPrefix(itr->value().ToString()));
-      continue;
-    }
-
-    // Strip resource ids of the disabled sync origins.
-    if (StartsWithASCII(key, kDriveDisabledOriginKeyPrefix, true)) {
-      write_batch.Put(key, RemoveWapiIdPrefix(itr->value().ToString()));
-      continue;
-    }
-  }
-
-  return LevelDBStatusToSyncStatusCode(
-      db->Write(leveldb::WriteOptions(), &write_batch));
-}
-
-}  // namespace drive
-}  // namespace sync_file_system
diff --git a/chrome/browser/sync_file_system/drive/metadata_db_migration_util.h b/chrome/browser/sync_file_system/drive/metadata_db_migration_util.h
deleted file mode 100644
index 62f5a6d..0000000
--- a/chrome/browser/sync_file_system/drive/metadata_db_migration_util.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_METADATA_DB_MIGRATION_UTIL_H_
-#define CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_METADATA_DB_MIGRATION_UTIL_H_
-
-#include <string>
-
-#include "chrome/browser/sync_file_system/sync_file_system.pb.h"
-#include "third_party/leveldatabase/src/include/leveldb/db.h"
-#include "webkit/browser/fileapi/syncable/sync_status_code.h"
-
-class GURL;
-
-namespace sync_file_system {
-namespace drive {
-
-// Parses a filesystem URL which contains 'drive' as a service name
-// (a.k.a. V0-format filesystem URL).
-//
-// When you parse V0-format filesystem URL, you should use this function instead
-// of DeserializeSyncableFileSystemURL() since 'drive' service name is no longer
-// used and the deserializer cannot parse the unregistered service name.
-//
-// EXAMPLE:
-// Assume following argument is given.
-//   url: 'filesystem:http://www.example.com/external/drive/foo/bar'
-// returns
-//   origin: 'http://www.example.com/'
-//   path:   'foo/bar'
-bool ParseV0FormatFileSystemURL(const GURL& url,
-                                GURL* origin,
-                                base::FilePath* path);
-
-// Adds "file:" prefix to WAPI resource ID.
-// EXAMPLE:  "xxx" => "file:xxx"
-std::string AddWapiFilePrefix(const std::string& resource_id);
-
-// Adds "folder:" prefix to WAPI resource ID.
-// EXAMPLE:  "xxx" => "folder:xxx"
-std::string AddWapiFolderPrefix(const std::string& resource_id);
-
-// Adds a prefix corresponding to the given |type|.
-std::string AddWapiIdPrefix(const std::string& resource_id,
-                            DriveMetadata_ResourceType type);
-
-// Removes a prefix from WAPI resource ID.
-// EXAMPLE:
-//   "file:xxx"    =>  "xxx"
-//   "folder:yyy"  =>  "yyy"
-//   "zzz"         =>  "zzz"
-std::string RemoveWapiIdPrefix(const std::string& resource_id);
-
-// Migrate |db| schema from version 0 to version 1.
-SyncStatusCode MigrateDatabaseFromV0ToV1(leveldb::DB* db);
-
-// Migrate |db| schema from version 1 to version 2.
-SyncStatusCode MigrateDatabaseFromV1ToV2(leveldb::DB* db);
-
-}  // namespace drive
-}  // namespace sync_file_system
-
-#endif  // CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_METADATA_DB_MIGRATION_UTIL_H_
diff --git a/chrome/browser/sync_file_system/drive/metadata_db_migration_util_unittest.cc b/chrome/browser/sync_file_system/drive/metadata_db_migration_util_unittest.cc
deleted file mode 100644
index 52769b6..0000000
--- a/chrome/browser/sync_file_system/drive/metadata_db_migration_util_unittest.cc
+++ /dev/null
@@ -1,309 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/sync_file_system/drive/metadata_db_migration_util.h"
-
-#include "base/files/scoped_temp_dir.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "chrome/browser/sync_file_system/drive_metadata_store.h"
-#include "googleurl/src/gurl.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/leveldatabase/src/include/leveldb/db.h"
-#include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
-#include "webkit/browser/fileapi/external_mount_points.h"
-#include "webkit/browser/fileapi/syncable/syncable_file_system_util.h"
-#include "webkit/common/fileapi/file_system_util.h"
-
-#define FPL FILE_PATH_LITERAL
-
-namespace sync_file_system {
-namespace drive {
-
-namespace {
-
-const char kV0ServiceName[] = "drive";
-
-bool CreateV0SerializedSyncableFileSystemURL(
-    const GURL& origin,
-    const base::FilePath& path,
-    std::string* serialized_url) {
-  fileapi::ScopedExternalFileSystem scoped_fs(
-      kV0ServiceName, fileapi::kFileSystemTypeSyncable, base::FilePath());
-
-  fileapi::FileSystemURL url =
-      fileapi::ExternalMountPoints::GetSystemInstance()->
-          CreateExternalFileSystemURL(origin, kV0ServiceName, path);
-  if (!url.is_valid())
-    return false;
-  *serialized_url = fileapi::GetExternalFileSystemRootURIString(
-        origin, kV0ServiceName) + url.path().AsUTF8Unsafe();
-  return true;
-}
-
-}  // namespace
-
-TEST(DriveMetadataDBMigrationUtilTest, ParseV0FormatFileSystemURL) {
-  const GURL kOrigin("chrome-extension://example");
-  const base::FilePath kFile(FPL("foo bar"));
-
-  std::string serialized_url;
-  ASSERT_TRUE(CreateV0SerializedSyncableFileSystemURL(
-      kOrigin, kFile, &serialized_url));
-
-  GURL origin;
-  base::FilePath path;
-  EXPECT_TRUE(ParseV0FormatFileSystemURL(GURL(serialized_url), &origin, &path));
-  EXPECT_EQ(kOrigin, origin);
-  EXPECT_EQ(kFile, path);
-}
-
-TEST(DriveMetadataDBMigrationUtilTest, AddWapiIdPrefix) {
-  DriveMetadata_ResourceType type_file =
-      DriveMetadata_ResourceType_RESOURCE_TYPE_FILE;
-  DriveMetadata_ResourceType type_folder =
-      DriveMetadata_ResourceType_RESOURCE_TYPE_FOLDER;
-
-  EXPECT_EQ("file:xxx", AddWapiFilePrefix("xxx"));
-  EXPECT_EQ("folder:yyy", AddWapiFolderPrefix("yyy"));
-  EXPECT_EQ("file:xxx", AddWapiIdPrefix("xxx", type_file));
-  EXPECT_EQ("folder:yyy", AddWapiIdPrefix("yyy", type_folder));
-
-  EXPECT_EQ("", AddWapiFilePrefix(""));
-  EXPECT_EQ("", AddWapiFolderPrefix(""));
-  EXPECT_EQ("", AddWapiIdPrefix("", type_file));
-  EXPECT_EQ("", AddWapiIdPrefix("", type_folder));
-}
-
-TEST(DriveMetadataDBMigrationUtilTest, RemoveWapiIdPrefix) {
-  EXPECT_EQ("xxx", RemoveWapiIdPrefix("xxx"));
-  EXPECT_EQ("yyy", RemoveWapiIdPrefix("file:yyy"));
-  EXPECT_EQ("zzz", RemoveWapiIdPrefix("folder:zzz"));
-
-  EXPECT_EQ("", RemoveWapiIdPrefix(""));
-  EXPECT_EQ("foo:xxx", RemoveWapiIdPrefix("foo:xxx"));
-}
-
-TEST(DriveMetadataDBMigrationUtilTest, MigrationFromV0) {
-  const char kDatabaseVersionKey[] = "VERSION";
-  const char kChangeStampKey[] = "CHANGE_STAMP";
-  const char kSyncRootDirectoryKey[] = "SYNC_ROOT_DIR";
-  const char kDriveMetadataKeyPrefix[] = "METADATA: ";
-  const char kDriveBatchSyncOriginKeyPrefix[] = "BSYNC_ORIGIN: ";
-  const char kDriveIncrementalSyncOriginKeyPrefix[] = "ISYNC_ORIGIN: ";
-
-  const GURL kOrigin1("chrome-extension://example1");
-  const GURL kOrigin2("chrome-extension://example2");
-  const std::string kSyncRootResourceId("folder:sync_root_resource_id");
-  const std::string kResourceId1("folder:hoge");
-  const std::string kResourceId2("folder:fuga");
-  const std::string kFileResourceId("file:piyo");
-  const base::FilePath kFile(FPL("foo bar"));
-  const std::string kFileMD5("file_md5");
-
-  base::ScopedTempDir base_dir;
-  ASSERT_TRUE(base_dir.CreateUniqueTempDir());
-
-  leveldb::Options options;
-  options.create_if_missing = true;
-  leveldb::DB* db_ptr = NULL;
-  std::string db_dir = fileapi::FilePathToString(
-      base_dir.path().Append(DriveMetadataStore::kDatabaseName));
-  leveldb::Status status = leveldb::DB::Open(options, db_dir, &db_ptr);
-
-  scoped_ptr<leveldb::DB> db(db_ptr);
-  ASSERT_TRUE(status.ok());
-
-  // Setup the database with the schema version 0.
-  leveldb::WriteBatch batch;
-  batch.Put(kChangeStampKey, "1");
-  batch.Put(kSyncRootDirectoryKey, kSyncRootResourceId);
-
-  // Setup drive metadata.
-  DriveMetadata drive_metadata;
-  drive_metadata.set_resource_id(kFileResourceId);
-  drive_metadata.set_md5_checksum(kFileMD5);
-  drive_metadata.set_conflicted(false);
-  drive_metadata.set_to_be_fetched(false);
-
-  std::string serialized_url;
-  ASSERT_TRUE(CreateV0SerializedSyncableFileSystemURL(
-      kOrigin1, kFile, &serialized_url));
-  std::string metadata_string;
-  drive_metadata.SerializeToString(&metadata_string);
-  batch.Put(kDriveMetadataKeyPrefix + serialized_url, metadata_string);
-
-  // Setup batch sync origin and incremental sync origin.
-  batch.Put(kDriveBatchSyncOriginKeyPrefix + kOrigin1.spec(), kResourceId1);
-  batch.Put(kDriveIncrementalSyncOriginKeyPrefix + kOrigin2.spec(),
-            kResourceId2);
-
-  status = db->Write(leveldb::WriteOptions(), &batch);
-  EXPECT_EQ(SYNC_STATUS_OK, LevelDBStatusToSyncStatusCode(status));
-
-  // Migrate the database.
-  drive::MigrateDatabaseFromV0ToV1(db.get());
-
-  scoped_ptr<leveldb::Iterator> itr(db->NewIterator(leveldb::ReadOptions()));
-
-  // Verify DB schema version.
-  int64 database_version = 0;
-  itr->Seek(kDatabaseVersionKey);
-  EXPECT_TRUE(itr->Valid());
-  EXPECT_TRUE(base::StringToInt64(itr->value().ToString(), &database_version));
-  EXPECT_EQ(1, database_version);
-
-  // Verify the largest changestamp.
-  int64 changestamp = 0;
-  itr->Seek(kChangeStampKey);
-  EXPECT_TRUE(itr->Valid());
-  EXPECT_TRUE(base::StringToInt64(itr->value().ToString(), &changestamp));
-  EXPECT_EQ(1, changestamp);
-
-  // Verify the sync root directory.
-  itr->Seek(kSyncRootDirectoryKey);
-  EXPECT_TRUE(itr->Valid());
-  EXPECT_EQ(kSyncRootResourceId, itr->value().ToString());
-
-  // Verify the metadata.
-  itr->Seek(kDriveMetadataKeyPrefix);
-  EXPECT_TRUE(itr->Valid());
-  DriveMetadata metadata;
-  EXPECT_TRUE(metadata.ParseFromString(itr->value().ToString()));
-  EXPECT_EQ(kFileResourceId, metadata.resource_id());
-  EXPECT_EQ(kFileMD5, metadata.md5_checksum());
-  EXPECT_FALSE(metadata.conflicted());
-  EXPECT_FALSE(metadata.to_be_fetched());
-
-  // Verify the batch sync origin.
-  itr->Seek(kDriveBatchSyncOriginKeyPrefix);
-  EXPECT_TRUE(itr->Valid());
-  EXPECT_EQ(kResourceId1, itr->value().ToString());
-
-  // Verify the incremental sync origin.
-  itr->Seek(kDriveIncrementalSyncOriginKeyPrefix);
-  EXPECT_TRUE(itr->Valid());
-  EXPECT_EQ(kResourceId2, itr->value().ToString());
-}
-
-TEST(DriveMetadataDBMigrationUtilTest, MigrationFromV1) {
-  const char kDatabaseVersionKey[] = "VERSION";
-  const char kChangeStampKey[] = "CHANGE_STAMP";
-  const char kSyncRootDirectoryKey[] = "SYNC_ROOT_DIR";
-  const char kDriveMetadataKeyPrefix[] = "METADATA: ";
-  const char kMetadataKeySeparator = ' ';
-  const char kDriveBatchSyncOriginKeyPrefix[] = "BSYNC_ORIGIN: ";
-  const char kDriveIncrementalSyncOriginKeyPrefix[] = "ISYNC_ORIGIN: ";
-  const char kDriveDisabledOriginKeyPrefix[] = "DISABLED_ORIGIN: ";
-
-  const GURL kOrigin1("chrome-extension://example1");
-  const GURL kOrigin2("chrome-extension://example2");
-  const GURL kOrigin3("chrome-extension://example3");
-
-  const std::string kSyncRootResourceId("folder:sync_root_resource_id");
-  const std::string kResourceId1("folder:hoge");
-  const std::string kResourceId2("folder:fuga");
-  const std::string kResourceId3("folder:hogera");
-  const std::string kFileResourceId("file:piyo");
-  const base::FilePath kFile(FPL("foo bar"));
-  const std::string kFileMD5("file_md5");
-
-  RegisterSyncableFileSystem();
-
-  base::ScopedTempDir base_dir;
-  ASSERT_TRUE(base_dir.CreateUniqueTempDir());
-
-  leveldb::Options options;
-  options.create_if_missing = true;
-  leveldb::DB* db_ptr = NULL;
-  std::string db_dir = fileapi::FilePathToString(
-      base_dir.path().Append(DriveMetadataStore::kDatabaseName));
-  leveldb::Status status = leveldb::DB::Open(options, db_dir, &db_ptr);
-
-  scoped_ptr<leveldb::DB> db(db_ptr);
-  ASSERT_TRUE(status.ok());
-
-  // Setup the database with the schema version 1.
-  leveldb::WriteBatch batch;
-  batch.Put(kDatabaseVersionKey, "1");
-  batch.Put(kChangeStampKey, "1");
-  batch.Put(kSyncRootDirectoryKey, kSyncRootResourceId);
-
-  fileapi::FileSystemURL url = CreateSyncableFileSystemURL(kOrigin1, kFile);
-
-  // Setup drive metadata.
-  DriveMetadata drive_metadata;
-  drive_metadata.set_resource_id(kFileResourceId);
-  drive_metadata.set_md5_checksum(kFileMD5);
-  drive_metadata.set_conflicted(false);
-  drive_metadata.set_to_be_fetched(false);
-  std::string metadata_string;
-  drive_metadata.SerializeToString(&metadata_string);
-  std::string metadata_key = kDriveMetadataKeyPrefix + kOrigin1.spec() +
-                             kMetadataKeySeparator + url.path().AsUTF8Unsafe();
-  batch.Put(metadata_key, metadata_string);
-
-  // Setup origins.
-  batch.Put(kDriveBatchSyncOriginKeyPrefix + kOrigin1.spec(), kResourceId1);
-  batch.Put(kDriveIncrementalSyncOriginKeyPrefix + kOrigin2.spec(),
-            kResourceId2);
-  batch.Put(kDriveDisabledOriginKeyPrefix + kOrigin3.spec(), kResourceId3);
-
-  status = db->Write(leveldb::WriteOptions(), &batch);
-  EXPECT_EQ(SYNC_STATUS_OK, LevelDBStatusToSyncStatusCode(status));
-
-  RevokeSyncableFileSystem();
-
-  // Migrate the database.
-  drive::MigrateDatabaseFromV1ToV2(db.get());
-
-  scoped_ptr<leveldb::Iterator> itr(db->NewIterator(leveldb::ReadOptions()));
-
-  // Verify DB schema version.
-  int64 database_version = 0;
-  itr->Seek(kDatabaseVersionKey);
-  EXPECT_TRUE(itr->Valid());
-  EXPECT_TRUE(base::StringToInt64(itr->value().ToString(), &database_version));
-  EXPECT_EQ(2, database_version);
-
-  // Verify the largest changestamp.
-  int64 changestamp = 0;
-  itr->Seek(kChangeStampKey);
-  EXPECT_TRUE(itr->Valid());
-  EXPECT_TRUE(base::StringToInt64(itr->value().ToString(), &changestamp));
-  EXPECT_EQ(1, changestamp);
-
-  // Verify the sync root directory.
-  itr->Seek(kSyncRootDirectoryKey);
-  EXPECT_TRUE(itr->Valid());
-  EXPECT_EQ(RemoveWapiIdPrefix(kSyncRootResourceId), itr->value().ToString());
-
-  // Verify the metadata.
-  itr->Seek(kDriveMetadataKeyPrefix);
-  EXPECT_TRUE(itr->Valid());
-  DriveMetadata metadata;
-  EXPECT_TRUE(metadata.ParseFromString(itr->value().ToString()));
-  EXPECT_EQ(RemoveWapiIdPrefix(kFileResourceId), metadata.resource_id());
-  EXPECT_EQ(kFileMD5, metadata.md5_checksum());
-  EXPECT_FALSE(metadata.conflicted());
-  EXPECT_FALSE(metadata.to_be_fetched());
-
-  // Verify the batch sync origin.
-  itr->Seek(kDriveBatchSyncOriginKeyPrefix);
-  EXPECT_FALSE(StartsWithASCII(kDriveBatchSyncOriginKeyPrefix,
-                               itr->key().ToString(), true));
-
-  // Verify the incremental sync origin.
-  itr->Seek(kDriveIncrementalSyncOriginKeyPrefix);
-  EXPECT_TRUE(itr->Valid());
-  EXPECT_EQ(RemoveWapiIdPrefix(kResourceId2), itr->value().ToString());
-
-  // Verify the disabled origin.
-  itr->Seek(kDriveDisabledOriginKeyPrefix);
-  EXPECT_TRUE(itr->Valid());
-  EXPECT_EQ(RemoveWapiIdPrefix(kResourceId3), itr->value().ToString());
-}
-
-}  // namespace drive
-}  // namespace sync_file_system
diff --git a/chrome/browser/sync_file_system/drive_backend/OWNERS b/chrome/browser/sync_file_system/drive_backend/OWNERS
new file mode 100644
index 0000000..25402fd
--- /dev/null
+++ b/chrome/browser/sync_file_system/drive_backend/OWNERS
@@ -0,0 +1 @@
+nhiroki@chromium.org
diff --git a/chrome/browser/sync_file_system/drive_backend/api_util.cc b/chrome/browser/sync_file_system/drive_backend/api_util.cc
new file mode 100644
index 0000000..e131b82
--- /dev/null
+++ b/chrome/browser/sync_file_system/drive_backend/api_util.cc
@@ -0,0 +1,1087 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/sync_file_system/drive_backend/api_util.h"
+
+#include <algorithm>
+#include <functional>
+#include <sstream>
+#include <string>
+
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/threading/sequenced_worker_pool.h"
+#include "base/values.h"
+#include "chrome/browser/drive/drive_api_service.h"
+#include "chrome/browser/drive/drive_api_util.h"
+#include "chrome/browser/drive/drive_uploader.h"
+#include "chrome/browser/drive/gdata_wapi_service.h"
+#include "chrome/browser/google_apis/drive_api_parser.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/sync_file_system/drive_file_sync_util.h"
+#include "chrome/browser/sync_file_system/logger.h"
+#include "chrome/common/extensions/extension.h"
+#include "content/public/browser/browser_thread.h"
+#include "extensions/common/constants.h"
+#include "net/base/mime_util.h"
+#include "webkit/browser/fileapi/syncable/syncable_file_system_util.h"
+
+namespace sync_file_system {
+namespace drive_backend {
+
+namespace {
+
+enum ParentType {
+  PARENT_TYPE_ROOT_OR_EMPTY,
+  PARENT_TYPE_DIRECTORY,
+};
+
+const char kSyncRootDirectoryName[] = "Chrome Syncable FileSystem";
+const char kSyncRootDirectoryNameDev[] = "Chrome Syncable FileSystem Dev";
+const char kMimeTypeOctetStream[] = "application/octet-stream";
+
+const char kFakeServerBaseUrl[] = "https://fake_server/";
+const char kFakeDownloadServerBaseUrl[] = "https://fake_download_server/";
+
+void EmptyGDataErrorCodeCallback(google_apis::GDataErrorCode error) {}
+
+bool HasParentLinkTo(const ScopedVector<google_apis::Link>& links,
+                     const std::string& parent_resource_id,
+                     ParentType parent_type) {
+  bool has_parent = false;
+
+  for (ScopedVector<google_apis::Link>::const_iterator itr = links.begin();
+       itr != links.end(); ++itr) {
+    if ((*itr)->type() == google_apis::Link::LINK_PARENT) {
+      has_parent = true;
+      if (drive::util::ExtractResourceIdFromUrl((*itr)->href()) ==
+          parent_resource_id)
+        return true;
+    }
+  }
+
+  return parent_type == PARENT_TYPE_ROOT_OR_EMPTY && !has_parent;
+}
+
+struct TitleAndParentQuery
+    : std::unary_function<const google_apis::ResourceEntry*, bool> {
+  TitleAndParentQuery(const std::string& title,
+                      const std::string& parent_resource_id,
+                      ParentType parent_type)
+      : title(title),
+        parent_resource_id(parent_resource_id),
+        parent_type(parent_type) {}
+
+  bool operator()(const google_apis::ResourceEntry* entry) const {
+    return entry->title() == title &&
+           HasParentLinkTo(entry->links(), parent_resource_id, parent_type);
+  }
+
+  const std::string& title;
+  const std::string& parent_resource_id;
+  ParentType parent_type;
+};
+
+void FilterEntriesByTitleAndParent(
+    ScopedVector<google_apis::ResourceEntry>* entries,
+    const std::string& title,
+    const std::string& parent_resource_id,
+    ParentType parent_type) {
+  typedef ScopedVector<google_apis::ResourceEntry>::iterator iterator;
+  iterator itr = std::partition(entries->begin(),
+                                entries->end(),
+                                TitleAndParentQuery(title,
+                                                    parent_resource_id,
+                                                    parent_type));
+  entries->erase(itr, entries->end());
+}
+
+google_apis::ResourceEntry* GetDocumentByTitleAndParent(
+    const ScopedVector<google_apis::ResourceEntry>& entries,
+    const std::string& title,
+    const std::string& parent_resource_id,
+    ParentType parent_type) {
+  typedef ScopedVector<google_apis::ResourceEntry>::const_iterator iterator;
+  iterator found =
+      std::find_if(entries.begin(),
+                   entries.end(),
+                   TitleAndParentQuery(title, parent_resource_id, parent_type));
+  if (found != entries.end())
+    return *found;
+  return NULL;
+}
+
+void EntryAdapterForEnsureTitleUniqueness(
+    scoped_ptr<google_apis::ResourceEntry> entry,
+    const APIUtil::EnsureUniquenessCallback& callback,
+    APIUtil::EnsureUniquenessStatus status,
+    google_apis::GDataErrorCode error) {
+  callback.Run(error, status, entry.Pass());
+}
+
+void UploadResultAdapter(const APIUtil::ResourceEntryCallback& callback,
+                         google_apis::GDataErrorCode error,
+                         const GURL& upload_location,
+                         scoped_ptr<google_apis::ResourceEntry> entry) {
+  callback.Run(error, entry.Pass());
+}
+
+std::string GetMimeTypeFromTitle(const std::string& title) {
+  base::FilePath::StringType extension =
+      base::FilePath::FromUTF8Unsafe(title).Extension();
+  std::string mime_type;
+  if (extension.empty() ||
+      !net::GetWellKnownMimeTypeFromExtension(extension.substr(1), &mime_type))
+    return kMimeTypeOctetStream;
+  return mime_type;
+}
+
+}  // namespace
+
+APIUtil::APIUtil(Profile* profile)
+    : wapi_url_generator_(
+          GURL(google_apis::GDataWapiUrlGenerator::kBaseUrlForProduction),
+          GURL(google_apis::GDataWapiUrlGenerator::
+               kBaseDownloadUrlForProduction)),
+      drive_api_url_generator_(
+          GURL(google_apis::DriveApiUrlGenerator::kBaseUrlForProduction),
+          GURL(google_apis::DriveApiUrlGenerator::
+               kBaseDownloadUrlForProduction)),
+      upload_next_key_(0) {
+  if (IsDriveAPIDisabled()) {
+    drive_service_.reset(new drive::GDataWapiService(
+        profile->GetRequestContext(),
+        content::BrowserThread::GetBlockingPool(),
+        GURL(google_apis::GDataWapiUrlGenerator::kBaseUrlForProduction),
+        GURL(google_apis::GDataWapiUrlGenerator::kBaseDownloadUrlForProduction),
+        std::string() /* custom_user_agent */));
+  } else {
+    drive_service_.reset(new drive::DriveAPIService(
+        profile->GetRequestContext(),
+        content::BrowserThread::GetBlockingPool(),
+        GURL(google_apis::DriveApiUrlGenerator::kBaseUrlForProduction),
+        GURL(google_apis::DriveApiUrlGenerator::kBaseDownloadUrlForProduction),
+        std::string() /* custom_user_agent */));
+  }
+
+  drive_service_->Initialize(profile);
+  drive_service_->AddObserver(this);
+  net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
+
+  drive_uploader_.reset(new drive::DriveUploader(
+      drive_service_.get(), content::BrowserThread::GetBlockingPool()));
+}
+
+scoped_ptr<APIUtil> APIUtil::CreateForTesting(
+    Profile* profile,
+    scoped_ptr<drive::DriveServiceInterface> drive_service,
+    scoped_ptr<drive::DriveUploaderInterface> drive_uploader) {
+  return make_scoped_ptr(new APIUtil(
+      profile,
+      GURL(kFakeServerBaseUrl),
+      GURL(kFakeDownloadServerBaseUrl),
+      drive_service.Pass(),
+      drive_uploader.Pass()));
+}
+
+APIUtil::APIUtil(Profile* profile,
+                 const GURL& base_url,
+                 const GURL& base_download_url,
+                 scoped_ptr<drive::DriveServiceInterface> drive_service,
+                 scoped_ptr<drive::DriveUploaderInterface> drive_uploader)
+    : wapi_url_generator_(base_url, base_download_url),
+      drive_api_url_generator_(base_url, base_download_url),
+      upload_next_key_(0) {
+  drive_service_ = drive_service.Pass();
+  drive_service_->Initialize(profile);
+  drive_service_->AddObserver(this);
+  net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
+
+  drive_uploader_ = drive_uploader.Pass();
+}
+
+APIUtil::~APIUtil() {
+  DCHECK(CalledOnValidThread());
+  net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
+  drive_service_->RemoveObserver(this);
+}
+
+void APIUtil::AddObserver(APIUtilObserver* observer) {
+  DCHECK(CalledOnValidThread());
+  observers_.AddObserver(observer);
+}
+
+void APIUtil::RemoveObserver(APIUtilObserver* observer) {
+  DCHECK(CalledOnValidThread());
+  observers_.RemoveObserver(observer);
+}
+
+void APIUtil::GetDriveRootResourceId(const GDataErrorCallback& callback) {
+  DCHECK(CalledOnValidThread());
+  DCHECK(!IsDriveAPIDisabled());
+  DVLOG(2) << "Getting resource id for Drive root";
+
+  drive_service_->GetAboutResource(
+      base::Bind(&APIUtil::DidGetDriveRootResourceId, AsWeakPtr(), callback));
+}
+
+void APIUtil::DidGetDriveRootResourceId(
+    const GDataErrorCallback& callback,
+    google_apis::GDataErrorCode error,
+    scoped_ptr<google_apis::AboutResource> about_resource) {
+  DCHECK(CalledOnValidThread());
+
+  if (error != google_apis::HTTP_SUCCESS) {
+    DVLOG(2) << "Error on getting resource id for Drive root: " << error;
+    callback.Run(error);
+    return;
+  }
+
+  DCHECK(about_resource);
+  root_resource_id_ = about_resource->root_folder_id();
+  DCHECK(!root_resource_id_.empty());
+  DVLOG(2) << "Got resource id for Drive root: " << root_resource_id_;
+  callback.Run(error);
+}
+
+void APIUtil::GetDriveDirectoryForSyncRoot(const ResourceIdCallback& callback) {
+  DCHECK(CalledOnValidThread());
+
+  if (GetRootResourceId().empty()) {
+    GetDriveRootResourceId(
+        base::Bind(&APIUtil::DidGetDriveRootResourceIdForGetSyncRoot,
+                   AsWeakPtr(), callback));
+    return;
+  }
+
+  DVLOG(2) << "Getting Drive directory for SyncRoot";
+  std::string directory_name(GetSyncRootDirectoryName());
+  SearchByTitle(directory_name,
+                std::string(),
+                base::Bind(&APIUtil::DidGetDirectory,
+                           AsWeakPtr(),
+                           std::string(),
+                           directory_name,
+                           callback));
+}
+
+void APIUtil::DidGetDriveRootResourceIdForGetSyncRoot(
+    const ResourceIdCallback& callback,
+    google_apis::GDataErrorCode error) {
+  DCHECK(CalledOnValidThread());
+  if (error != google_apis::HTTP_SUCCESS) {
+    DVLOG(2) << "Error on getting Drive directory for SyncRoot: " << error;
+    callback.Run(error, std::string());
+    return;
+  }
+  GetDriveDirectoryForSyncRoot(callback);
+}
+
+void APIUtil::GetDriveDirectoryForOrigin(
+    const std::string& sync_root_resource_id,
+    const GURL& origin,
+    const ResourceIdCallback& callback) {
+  DCHECK(CalledOnValidThread());
+  DVLOG(2) << "Getting Drive directory for Origin: " << origin;
+
+  std::string directory_name(OriginToDirectoryTitle(origin));
+  SearchByTitle(directory_name,
+                sync_root_resource_id,
+                base::Bind(&APIUtil::DidGetDirectory,
+                           AsWeakPtr(),
+                           sync_root_resource_id,
+                           directory_name,
+                           callback));
+}
+
+void APIUtil::DidGetDirectory(const std::string& parent_resource_id,
+                              const std::string& directory_name,
+                              const ResourceIdCallback& callback,
+                              google_apis::GDataErrorCode error,
+                              scoped_ptr<google_apis::ResourceList> feed) {
+  DCHECK(CalledOnValidThread());
+  DCHECK(IsStringASCII(directory_name));
+
+  if (error != google_apis::HTTP_SUCCESS) {
+    DVLOG(2) << "Error on getting Drive directory: " << error;
+    callback.Run(error, std::string());
+    return;
+  }
+
+  std::string resource_id;
+  ParentType parent_type = PARENT_TYPE_DIRECTORY;
+  if (parent_resource_id.empty()) {
+    resource_id = GetRootResourceId();
+    DCHECK(!resource_id.empty());
+    parent_type = PARENT_TYPE_ROOT_OR_EMPTY;
+  } else {
+    resource_id = parent_resource_id;
+  }
+  std::string title(directory_name);
+  google_apis::ResourceEntry* entry = GetDocumentByTitleAndParent(
+      feed->entries(), title, resource_id, parent_type);
+  if (!entry) {
+    DVLOG(2) << "Directory not found. Creating: " << directory_name;
+    drive_service_->AddNewDirectory(resource_id,
+                                    directory_name,
+                                    base::Bind(&APIUtil::DidCreateDirectory,
+                                               AsWeakPtr(),
+                                               parent_resource_id,
+                                               title,
+                                               callback));
+    return;
+  }
+  DVLOG(2) << "Found Drive directory.";
+
+  // TODO(tzik): Handle error.
+  DCHECK_EQ(google_apis::ENTRY_KIND_FOLDER, entry->kind());
+  DCHECK_EQ(directory_name, entry->title());
+
+  if (entry->title() == GetSyncRootDirectoryName())
+    EnsureSyncRootIsNotInMyDrive(entry->resource_id());
+
+  callback.Run(error, entry->resource_id());
+}
+
+void APIUtil::DidCreateDirectory(const std::string& parent_resource_id,
+                                 const std::string& title,
+                                 const ResourceIdCallback& callback,
+                                 google_apis::GDataErrorCode error,
+                                 scoped_ptr<google_apis::ResourceEntry> entry) {
+  DCHECK(CalledOnValidThread());
+
+  if (error != google_apis::HTTP_SUCCESS &&
+      error != google_apis::HTTP_CREATED) {
+    DVLOG(2) << "Error on creating Drive directory: " << error;
+    callback.Run(error, std::string());
+    return;
+  }
+  DVLOG(2) << "Created Drive directory.";
+
+  DCHECK(entry);
+  // Check if any other client creates a directory with same title.
+  EnsureTitleUniqueness(
+      parent_resource_id,
+      title,
+      base::Bind(&APIUtil::DidEnsureUniquenessForCreateDirectory,
+                 AsWeakPtr(),
+                 callback));
+}
+
+void APIUtil::DidEnsureUniquenessForCreateDirectory(
+    const ResourceIdCallback& callback,
+    google_apis::GDataErrorCode error,
+    EnsureUniquenessStatus status,
+    scoped_ptr<google_apis::ResourceEntry> entry) {
+  DCHECK(CalledOnValidThread());
+
+  if (error != google_apis::HTTP_SUCCESS) {
+    callback.Run(error, std::string());
+    return;
+  }
+
+  if (status == NO_DUPLICATES_FOUND)
+    error = google_apis::HTTP_CREATED;
+
+  DCHECK(entry) << "No entry: " << error;
+
+  if (!entry->is_folder()) {
+    // TODO(kinuko): Fix this. http://crbug.com/237090
+    util::Log(
+        logging::LOG_ERROR,
+        FROM_HERE,
+        "A file is left for CreateDirectory due to file-folder conflict!");
+    callback.Run(google_apis::HTTP_CONFLICT, std::string());
+    return;
+  }
+
+  if (entry->title() == GetSyncRootDirectoryName())
+    EnsureSyncRootIsNotInMyDrive(entry->resource_id());
+
+  callback.Run(error, entry->resource_id());
+}
+
+void APIUtil::GetLargestChangeStamp(const ChangeStampCallback& callback) {
+  DCHECK(CalledOnValidThread());
+  DVLOG(2) << "Getting largest change id";
+
+  drive_service_->GetAboutResource(
+      base::Bind(&APIUtil::DidGetLargestChangeStamp, AsWeakPtr(), callback));
+}
+
+void APIUtil::GetResourceEntry(const std::string& resource_id,
+                               const ResourceEntryCallback& callback) {
+  DCHECK(CalledOnValidThread());
+  DVLOG(2) << "Getting ResourceEntry for: " << resource_id;
+
+  drive_service_->GetResourceEntry(
+      resource_id,
+      base::Bind(&APIUtil::DidGetResourceEntry, AsWeakPtr(), callback));
+}
+
+void APIUtil::DidGetLargestChangeStamp(
+    const ChangeStampCallback& callback,
+    google_apis::GDataErrorCode error,
+    scoped_ptr<google_apis::AboutResource> about_resource) {
+  DCHECK(CalledOnValidThread());
+
+  int64 largest_change_id = 0;
+  if (error == google_apis::HTTP_SUCCESS) {
+    DCHECK(about_resource);
+    largest_change_id = about_resource->largest_change_id();
+    root_resource_id_ = about_resource->root_folder_id();
+    DVLOG(2) << "Got largest change id: " << largest_change_id;
+  } else {
+    DVLOG(2) << "Error on getting largest change id: " << error;
+  }
+
+  callback.Run(error, largest_change_id);
+}
+
+void APIUtil::SearchByTitle(const std::string& title,
+                            const std::string& directory_resource_id,
+                            const ResourceListCallback& callback) {
+  DCHECK(CalledOnValidThread());
+  DCHECK(!title.empty());
+  DVLOG(2) << "Searching resources in the directory [" << directory_resource_id
+           << "] with title [" << title << "]";
+
+  drive_service_->SearchByTitle(
+      title,
+      directory_resource_id,
+      base::Bind(&APIUtil::DidGetResourceList, AsWeakPtr(), callback));
+}
+
+void APIUtil::ListFiles(const std::string& directory_resource_id,
+                        const ResourceListCallback& callback) {
+  DCHECK(CalledOnValidThread());
+  DVLOG(2) << "Listing resources in the directory [" << directory_resource_id
+           << "]";
+
+  drive_service_->GetResourceListInDirectory(directory_resource_id, callback);
+}
+
+void APIUtil::ListChanges(int64 start_changestamp,
+                          const ResourceListCallback& callback) {
+  DCHECK(CalledOnValidThread());
+  DVLOG(2) << "Listing changes since: " << start_changestamp;
+
+  drive_service_->GetChangeList(
+      start_changestamp,
+      base::Bind(&APIUtil::DidGetResourceList, AsWeakPtr(), callback));
+}
+
+void APIUtil::ContinueListing(const GURL& feed_url,
+                              const ResourceListCallback& callback) {
+  DCHECK(CalledOnValidThread());
+  DVLOG(2) << "Continue listing on feed: " << feed_url;
+
+  drive_service_->ContinueGetResourceList(
+      feed_url,
+      base::Bind(&APIUtil::DidGetResourceList, AsWeakPtr(), callback));
+}
+
+void APIUtil::DownloadFile(const std::string& resource_id,
+                           const std::string& local_file_md5,
+                           const base::FilePath& local_file_path,
+                           const DownloadFileCallback& callback) {
+  DCHECK(CalledOnValidThread());
+  DVLOG(2) << "Downloading file [" << resource_id << "]";
+
+  drive_service_->GetResourceEntry(
+      resource_id,
+      base::Bind(&APIUtil::DidGetResourceEntry,
+                 AsWeakPtr(),
+                 base::Bind(&APIUtil::DownloadFileInternal,
+                            AsWeakPtr(),
+                            local_file_md5,
+                            local_file_path,
+                            callback)));
+}
+
+void APIUtil::UploadNewFile(const std::string& directory_resource_id,
+                            const base::FilePath& local_file_path,
+                            const std::string& title,
+                            const UploadFileCallback& callback) {
+  DCHECK(CalledOnValidThread());
+  DVLOG(2) << "Uploading new file into the directory [" << directory_resource_id
+           << "] with title [" << title << "]";
+
+  std::string mime_type = GetMimeTypeFromTitle(title);
+  UploadKey upload_key = RegisterUploadCallback(callback);
+  ResourceEntryCallback did_upload_callback =
+      base::Bind(&APIUtil::DidUploadNewFile,
+                 AsWeakPtr(),
+                 directory_resource_id,
+                 title,
+                 upload_key);
+  drive_uploader_->UploadNewFile(
+      directory_resource_id,
+      local_file_path,
+      title,
+      mime_type,
+      base::Bind(&UploadResultAdapter, did_upload_callback),
+      google_apis::ProgressCallback());
+}
+
+void APIUtil::UploadExistingFile(const std::string& resource_id,
+                                 const std::string& remote_file_md5,
+                                 const base::FilePath& local_file_path,
+                                 const UploadFileCallback& callback) {
+  DCHECK(CalledOnValidThread());
+  DVLOG(2) << "Uploading existing file [" << resource_id << "]";
+  drive_service_->GetResourceEntry(
+      resource_id,
+      base::Bind(&APIUtil::DidGetResourceEntry,
+                 AsWeakPtr(),
+                 base::Bind(&APIUtil::UploadExistingFileInternal,
+                            AsWeakPtr(),
+                            remote_file_md5,
+                            local_file_path,
+                            callback)));
+}
+
+void APIUtil::CreateDirectory(const std::string& parent_resource_id,
+                              const std::string& title,
+                              const ResourceIdCallback& callback) {
+  DCHECK(CalledOnValidThread());
+  // TODO(kinuko): This will call EnsureTitleUniqueness and will delete
+  // directories if there're duplicated directories. This must be ok
+  // for current design but we'll need to merge directories when we support
+  // 'real' directories.
+  drive_service_->AddNewDirectory(parent_resource_id,
+                                  title,
+                                  base::Bind(&APIUtil::DidCreateDirectory,
+                                             AsWeakPtr(),
+                                             parent_resource_id,
+                                             title,
+                                             callback));
+}
+
+void APIUtil::DeleteFile(const std::string& resource_id,
+                         const std::string& remote_file_md5,
+                         const GDataErrorCallback& callback) {
+  DCHECK(CalledOnValidThread());
+  DVLOG(2) << "Deleting file: " << resource_id;
+
+  // Load actual remote_file_md5 to check for conflict before deletion.
+  if (!remote_file_md5.empty()) {
+    drive_service_->GetResourceEntry(
+        resource_id,
+        base::Bind(&APIUtil::DidGetResourceEntry,
+                   AsWeakPtr(),
+                   base::Bind(&APIUtil::DeleteFileInternal,
+                              AsWeakPtr(),
+                              remote_file_md5,
+                              callback)));
+    return;
+  }
+
+  // Expected remote_file_md5 is empty so do a force delete.
+  drive_service_->DeleteResource(
+      resource_id,
+      std::string(),
+      base::Bind(&APIUtil::DidDeleteFile, AsWeakPtr(), callback));
+  return;
+}
+
+GURL APIUtil::ResourceIdToResourceLink(const std::string& resource_id) const {
+  return IsDriveAPIDisabled()
+      ? wapi_url_generator_.GenerateEditUrl(resource_id)
+      : drive_api_url_generator_.GetFileUrl(resource_id);
+}
+
+void APIUtil::EnsureSyncRootIsNotInMyDrive(
+    const std::string& sync_root_resource_id) {
+  DCHECK(CalledOnValidThread());
+
+  if (GetRootResourceId().empty()) {
+    GetDriveRootResourceId(
+        base::Bind(&APIUtil::DidGetDriveRootResourceIdForEnsureSyncRoot,
+                   AsWeakPtr(), sync_root_resource_id));
+    return;
+  }
+
+  DVLOG(2) << "Ensuring the sync root directory is not in 'My Drive'.";
+  drive_service_->RemoveResourceFromDirectory(
+      GetRootResourceId(),
+      sync_root_resource_id,
+      base::Bind(&EmptyGDataErrorCodeCallback));
+}
+
+void APIUtil::DidGetDriveRootResourceIdForEnsureSyncRoot(
+    const std::string& sync_root_resource_id,
+    google_apis::GDataErrorCode error) {
+  DCHECK(CalledOnValidThread());
+
+  if (error != google_apis::HTTP_SUCCESS) {
+    DVLOG(2) << "Error on ensuring the sync root directory is not in"
+             << " 'My Drive': " << error;
+    // Give up ensuring the sync root directory is not in 'My Drive'. This will
+    // be retried at some point.
+    return;
+  }
+
+  DCHECK(!GetRootResourceId().empty());
+  EnsureSyncRootIsNotInMyDrive(sync_root_resource_id);
+}
+
+// static
+// TODO(calvinlo): Delete this when Sync Directory Operations are supported by
+// default.
+std::string APIUtil::GetSyncRootDirectoryName() {
+  return IsSyncFSDirectoryOperationEnabled() ? kSyncRootDirectoryNameDev
+                                             : kSyncRootDirectoryName;
+}
+
+// static
+std::string APIUtil::OriginToDirectoryTitle(const GURL& origin) {
+  DCHECK(origin.SchemeIs(extensions::kExtensionScheme));
+  return origin.host();
+}
+
+// static
+GURL APIUtil::DirectoryTitleToOrigin(const std::string& title) {
+  return extensions::Extension::GetBaseURLFromExtensionId(title);
+}
+
+void APIUtil::OnReadyToSendRequests() {
+  DCHECK(CalledOnValidThread());
+  FOR_EACH_OBSERVER(APIUtilObserver, observers_, OnAuthenticated());
+}
+
+void APIUtil::OnConnectionTypeChanged(
+    net::NetworkChangeNotifier::ConnectionType type) {
+  DCHECK(CalledOnValidThread());
+  if (type != net::NetworkChangeNotifier::CONNECTION_NONE) {
+    FOR_EACH_OBSERVER(APIUtilObserver, observers_, OnNetworkConnected());
+    return;
+  }
+  // We're now disconnected, reset the drive_uploader_ to force stop
+  // uploading, otherwise the uploader may get stuck.
+  // TODO(kinuko): Check the uploader behavior if it's the expected behavior
+  // (http://crbug.com/223818)
+  CancelAllUploads(google_apis::GDATA_NO_CONNECTION);
+}
+
+void APIUtil::DidGetResourceList(
+    const ResourceListCallback& callback,
+    google_apis::GDataErrorCode error,
+    scoped_ptr<google_apis::ResourceList> resource_list) {
+  DCHECK(CalledOnValidThread());
+
+  if (error != google_apis::HTTP_SUCCESS) {
+    DVLOG(2) << "Error on listing resource: " << error;
+    callback.Run(error, scoped_ptr<google_apis::ResourceList>());
+    return;
+  }
+
+  DVLOG(2) << "Got resource list";
+  DCHECK(resource_list);
+  callback.Run(error, resource_list.Pass());
+}
+
+void APIUtil::DidGetResourceEntry(
+    const ResourceEntryCallback& callback,
+    google_apis::GDataErrorCode error,
+    scoped_ptr<google_apis::ResourceEntry> entry) {
+  DCHECK(CalledOnValidThread());
+
+  if (error != google_apis::HTTP_SUCCESS) {
+    DVLOG(2) << "Error on getting resource entry:" << error;
+    callback.Run(error, scoped_ptr<google_apis::ResourceEntry>());
+    return;
+  }
+
+  DVLOG(2) << "Got resource entry";
+  DCHECK(entry);
+  callback.Run(error, entry.Pass());
+}
+
+void APIUtil::DownloadFileInternal(
+    const std::string& local_file_md5,
+    const base::FilePath& local_file_path,
+    const DownloadFileCallback& callback,
+    google_apis::GDataErrorCode error,
+    scoped_ptr<google_apis::ResourceEntry> entry) {
+  DCHECK(CalledOnValidThread());
+
+  if (error != google_apis::HTTP_SUCCESS) {
+    DVLOG(2) << "Error on getting resource entry for download";
+    callback.Run(error, std::string(), 0, base::Time());
+    return;
+  }
+  DCHECK(entry);
+
+  DVLOG(2) << "Got resource entry for download";
+  // If local file and remote file are same, cancel the download.
+  if (local_file_md5 == entry->file_md5()) {
+    callback.Run(google_apis::HTTP_NOT_MODIFIED,
+                 local_file_md5,
+                 entry->file_size(),
+                 entry->updated_time());
+    return;
+  }
+
+  DVLOG(2) << "Downloading file: " << entry->resource_id();
+  const std::string& resource_id = entry->resource_id();
+  drive_service_->DownloadFile(local_file_path,
+                               resource_id,
+                               base::Bind(&APIUtil::DidDownloadFile,
+                                          AsWeakPtr(),
+                                          base::Passed(&entry),
+                                          callback),
+                               google_apis::GetContentCallback(),
+                               google_apis::ProgressCallback());
+}
+
+void APIUtil::DidDownloadFile(scoped_ptr<google_apis::ResourceEntry> entry,
+                              const DownloadFileCallback& callback,
+                              google_apis::GDataErrorCode error,
+                              const base::FilePath& downloaded_file_path) {
+  DCHECK(CalledOnValidThread());
+  if (error == google_apis::HTTP_SUCCESS)
+    DVLOG(2) << "Download completed";
+  else
+    DVLOG(2) << "Error on downloading file: " << error;
+
+  callback.Run(
+      error, entry->file_md5(), entry->file_size(), entry->updated_time());
+}
+
+void APIUtil::DidUploadNewFile(const std::string& parent_resource_id,
+                               const std::string& title,
+                               UploadKey upload_key,
+                               google_apis::GDataErrorCode error,
+                               scoped_ptr<google_apis::ResourceEntry> entry) {
+  UploadFileCallback callback = GetAndUnregisterUploadCallback(upload_key);
+  DCHECK(!callback.is_null());
+  if (error != google_apis::HTTP_SUCCESS &&
+      error != google_apis::HTTP_CREATED) {
+    DVLOG(2) << "Error on uploading new file: " << error;
+    callback.Run(error, std::string(), std::string());
+    return;
+  }
+
+  DVLOG(2) << "Upload completed";
+  EnsureTitleUniqueness(parent_resource_id,
+                        title,
+                        base::Bind(&APIUtil::DidEnsureUniquenessForCreateFile,
+                                   AsWeakPtr(),
+                                   entry->resource_id(),
+                                   callback));
+}
+
+void APIUtil::DidEnsureUniquenessForCreateFile(
+    const std::string& expected_resource_id,
+    const UploadFileCallback& callback,
+    google_apis::GDataErrorCode error,
+    EnsureUniquenessStatus status,
+    scoped_ptr<google_apis::ResourceEntry> entry) {
+  if (error != google_apis::HTTP_SUCCESS) {
+    DVLOG(2) << "Error on uploading new file: " << error;
+    callback.Run(error, std::string(), std::string());
+    return;
+  }
+
+  switch (status) {
+    case NO_DUPLICATES_FOUND:
+      // The file was uploaded successfully and no conflict was detected.
+      DCHECK(entry);
+      DVLOG(2) << "No conflict detected on uploading new file";
+      callback.Run(
+          google_apis::HTTP_CREATED, entry->resource_id(), entry->file_md5());
+      return;
+
+    case RESOLVED_DUPLICATES:
+      // The file was uploaded successfully but a conflict was detected.
+      // The duplicated file was deleted successfully.
+      DCHECK(entry);
+      if (entry->resource_id() != expected_resource_id) {
+        // TODO(kinuko): We should check local vs remote md5 here.
+        DVLOG(2) << "Conflict detected on uploading new file";
+        callback.Run(google_apis::HTTP_CONFLICT,
+                     entry->resource_id(),
+                     entry->file_md5());
+        return;
+      }
+
+      DVLOG(2) << "Conflict detected on uploading new file and resolved";
+      callback.Run(
+          google_apis::HTTP_CREATED, entry->resource_id(), entry->file_md5());
+      return;
+
+    default:
+      NOTREACHED() << "Unknown status from EnsureTitleUniqueness:" << status
+                   << " for " << expected_resource_id;
+  }
+}
+
+void APIUtil::UploadExistingFileInternal(
+    const std::string& remote_file_md5,
+    const base::FilePath& local_file_path,
+    const UploadFileCallback& callback,
+    google_apis::GDataErrorCode error,
+    scoped_ptr<google_apis::ResourceEntry> entry) {
+  DCHECK(CalledOnValidThread());
+
+  if (error != google_apis::HTTP_SUCCESS) {
+    DVLOG(2) << "Error on uploading existing file: " << error;
+    callback.Run(error, std::string(), std::string());
+    return;
+  }
+  DCHECK(entry);
+
+  // If remote file's hash value is different from the expected one, conflict
+  // might have occurred.
+  if (!remote_file_md5.empty() && remote_file_md5 != entry->file_md5()) {
+    DVLOG(2) << "Conflict detected before uploading existing file";
+    callback.Run(google_apis::HTTP_CONFLICT, std::string(), std::string());
+    return;
+  }
+
+  std::string mime_type = GetMimeTypeFromTitle(entry->title());
+  UploadKey upload_key = RegisterUploadCallback(callback);
+  ResourceEntryCallback did_upload_callback =
+      base::Bind(&APIUtil::DidUploadExistingFile, AsWeakPtr(), upload_key);
+  drive_uploader_->UploadExistingFile(
+      entry->resource_id(),
+      local_file_path,
+      mime_type,
+      entry->etag(),
+      base::Bind(&UploadResultAdapter, did_upload_callback),
+      google_apis::ProgressCallback());
+}
+
+bool APIUtil::IsAuthenticated() const {
+  return drive_service_->HasRefreshToken();
+}
+
+void APIUtil::DidUploadExistingFile(
+    UploadKey upload_key,
+    google_apis::GDataErrorCode error,
+    scoped_ptr<google_apis::ResourceEntry> entry) {
+  DCHECK(CalledOnValidThread());
+  UploadFileCallback callback = GetAndUnregisterUploadCallback(upload_key);
+  DCHECK(!callback.is_null());
+  if (error != google_apis::HTTP_SUCCESS) {
+    DVLOG(2) << "Error on uploading existing file: " << error;
+    callback.Run(error, std::string(), std::string());
+    return;
+  }
+
+  DCHECK(entry);
+  DVLOG(2) << "Upload completed";
+  callback.Run(error, entry->resource_id(), entry->file_md5());
+}
+
+void APIUtil::DeleteFileInternal(const std::string& remote_file_md5,
+                                 const GDataErrorCallback& callback,
+                                 google_apis::GDataErrorCode error,
+                                 scoped_ptr<google_apis::ResourceEntry> entry) {
+  DCHECK(CalledOnValidThread());
+
+  if (error != google_apis::HTTP_SUCCESS) {
+    DVLOG(2) << "Error on getting resource entry for deleting file: " << error;
+    callback.Run(error);
+    return;
+  }
+  DCHECK(entry);
+
+  // If remote file's hash value is different from the expected one, conflict
+  // might have occurred.
+  if (!remote_file_md5.empty() && remote_file_md5 != entry->file_md5()) {
+    DVLOG(2) << "Conflict detected before deleting file";
+    callback.Run(google_apis::HTTP_CONFLICT);
+    return;
+  }
+  DVLOG(2) << "Got resource entry for deleting file";
+
+  // Move the file to trash (don't delete it completely).
+  drive_service_->DeleteResource(
+      entry->resource_id(),
+      entry->etag(),
+      base::Bind(&APIUtil::DidDeleteFile, AsWeakPtr(), callback));
+}
+
+void APIUtil::DidDeleteFile(const GDataErrorCallback& callback,
+                            google_apis::GDataErrorCode error) {
+  DCHECK(CalledOnValidThread());
+  if (error == google_apis::HTTP_SUCCESS)
+    DVLOG(2) << "Deletion completed";
+  else
+    DVLOG(2) << "Error on deleting file: " << error;
+
+  callback.Run(error);
+}
+
+void APIUtil::EnsureTitleUniqueness(const std::string& parent_resource_id,
+                                    const std::string& expected_title,
+                                    const EnsureUniquenessCallback& callback) {
+  DCHECK(CalledOnValidThread());
+  DVLOG(2) << "Checking if there's no conflict on entry creation";
+
+  const google_apis::GetResourceListCallback& bound_callback =
+      base::Bind(&APIUtil::DidListEntriesToEnsureUniqueness,
+                 AsWeakPtr(),
+                 parent_resource_id,
+                 expected_title,
+                 callback);
+
+  SearchByTitle(expected_title, parent_resource_id, bound_callback);
+}
+
+void APIUtil::DidListEntriesToEnsureUniqueness(
+    const std::string& parent_resource_id,
+    const std::string& expected_title,
+    const EnsureUniquenessCallback& callback,
+    google_apis::GDataErrorCode error,
+    scoped_ptr<google_apis::ResourceList> feed) {
+  DCHECK(CalledOnValidThread());
+
+  if (error != google_apis::HTTP_SUCCESS) {
+    DVLOG(2) << "Error on listing resource for ensuring title uniqueness";
+    callback.Run(
+        error, NO_DUPLICATES_FOUND, scoped_ptr<google_apis::ResourceEntry>());
+    return;
+  }
+  DVLOG(2) << "Got resource list for ensuring title uniqueness";
+
+  // This filtering is needed only on WAPI. Once we move to Drive API we can
+  // drop this.
+  std::string resource_id;
+  ParentType parent_type = PARENT_TYPE_DIRECTORY;
+  if (parent_resource_id.empty()) {
+    resource_id = GetRootResourceId();
+    DCHECK(!resource_id.empty());
+    parent_type = PARENT_TYPE_ROOT_OR_EMPTY;
+  } else {
+    resource_id = parent_resource_id;
+  }
+  ScopedVector<google_apis::ResourceEntry> entries;
+  entries.swap(*feed->mutable_entries());
+  FilterEntriesByTitleAndParent(
+      &entries, expected_title, resource_id, parent_type);
+
+  if (entries.empty()) {
+    DVLOG(2) << "Uploaded file is not found";
+    callback.Run(google_apis::HTTP_NOT_FOUND,
+                 NO_DUPLICATES_FOUND,
+                 scoped_ptr<google_apis::ResourceEntry>());
+    return;
+  }
+
+  if (entries.size() >= 2) {
+    DVLOG(2) << "Conflict detected on creating entry";
+    for (size_t i = 0; i < entries.size() - 1; ++i) {
+      // TODO(tzik): Replace published_time with creation time after we move to
+      // Drive API.
+      if (entries[i]->published_time() < entries.back()->published_time())
+        std::swap(entries[i], entries.back());
+    }
+
+    scoped_ptr<google_apis::ResourceEntry> earliest_entry(entries.back());
+    entries.back() = NULL;
+    entries.get().pop_back();
+
+    DeleteEntriesForEnsuringTitleUniqueness(
+        entries.Pass(),
+        base::Bind(&EntryAdapterForEnsureTitleUniqueness,
+                   base::Passed(&earliest_entry),
+                   callback,
+                   RESOLVED_DUPLICATES));
+    return;
+  }
+
+  DVLOG(2) << "no conflict detected";
+  DCHECK_EQ(1u, entries.size());
+  scoped_ptr<google_apis::ResourceEntry> entry(entries.front());
+  entries.weak_clear();
+
+  callback.Run(google_apis::HTTP_SUCCESS, NO_DUPLICATES_FOUND, entry.Pass());
+}
+
+void APIUtil::DeleteEntriesForEnsuringTitleUniqueness(
+    ScopedVector<google_apis::ResourceEntry> entries,
+    const GDataErrorCallback& callback) {
+  DCHECK(CalledOnValidThread());
+  DVLOG(2) << "Cleaning up conflict on entry creation";
+
+  if (entries.empty()) {
+    callback.Run(google_apis::HTTP_SUCCESS);
+    return;
+  }
+
+  scoped_ptr<google_apis::ResourceEntry> entry(entries.back());
+  entries.back() = NULL;
+  entries.get().pop_back();
+
+  // We don't care conflicts here as other clients may be also deleting this
+  // file, so passing an empty etag.
+  drive_service_->DeleteResource(
+      entry->resource_id(),
+      std::string(),  // empty etag
+      base::Bind(&APIUtil::DidDeleteEntriesForEnsuringTitleUniqueness,
+                 AsWeakPtr(),
+                 base::Passed(&entries),
+                 callback));
+}
+
+void APIUtil::DidDeleteEntriesForEnsuringTitleUniqueness(
+    ScopedVector<google_apis::ResourceEntry> entries,
+    const GDataErrorCallback& callback,
+    google_apis::GDataErrorCode error) {
+  DCHECK(CalledOnValidThread());
+
+  if (error != google_apis::HTTP_SUCCESS &&
+      error != google_apis::HTTP_NOT_FOUND) {
+    DVLOG(2) << "Error on deleting file: " << error;
+    callback.Run(error);
+    return;
+  }
+
+  DVLOG(2) << "Deletion completed";
+  DeleteEntriesForEnsuringTitleUniqueness(entries.Pass(), callback);
+}
+
+APIUtil::UploadKey APIUtil::RegisterUploadCallback(
+    const UploadFileCallback& callback) {
+  const bool inserted = upload_callback_map_.insert(
+      std::make_pair(upload_next_key_, callback)).second;
+  CHECK(inserted);
+  return upload_next_key_++;
+}
+
+APIUtil::UploadFileCallback APIUtil::GetAndUnregisterUploadCallback(
+    UploadKey key) {
+  UploadFileCallback callback;
+  UploadCallbackMap::iterator found = upload_callback_map_.find(key);
+  if (found == upload_callback_map_.end())
+    return callback;
+  callback = found->second;
+  upload_callback_map_.erase(found);
+  return callback;
+}
+
+void APIUtil::CancelAllUploads(google_apis::GDataErrorCode error) {
+  if (upload_callback_map_.empty())
+    return;
+  for (UploadCallbackMap::iterator iter = upload_callback_map_.begin();
+       iter != upload_callback_map_.end();
+       ++iter) {
+    iter->second.Run(error, std::string(), std::string());
+  }
+  upload_callback_map_.clear();
+  drive_uploader_.reset(new drive::DriveUploader(
+      drive_service_.get(), content::BrowserThread::GetBlockingPool()));
+}
+
+std::string APIUtil::GetRootResourceId() const {
+  if (IsDriveAPIDisabled())
+    return drive_service_->GetRootResourceId();
+  return root_resource_id_;
+}
+
+}  // namespace drive_backend
+}  // namespace sync_file_system
diff --git a/chrome/browser/sync_file_system/drive_backend/api_util.h b/chrome/browser/sync_file_system/drive_backend/api_util.h
new file mode 100644
index 0000000..8c17628
--- /dev/null
+++ b/chrome/browser/sync_file_system/drive_backend/api_util.h
@@ -0,0 +1,256 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_API_UTIL_H_
+#define CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_API_UTIL_H_
+
+#include <map>
+#include <string>
+
+#include "base/memory/weak_ptr.h"
+#include "base/threading/non_thread_safe.h"
+#include "chrome/browser/drive/drive_service_interface.h"
+#include "chrome/browser/google_apis/drive_api_url_generator.h"
+#include "chrome/browser/google_apis/gdata_wapi_url_generator.h"
+#include "chrome/browser/sync_file_system/drive_backend/api_util_interface.h"
+#include "net/base/network_change_notifier.h"
+
+class GURL;
+class Profile;
+
+namespace drive { class DriveUploaderInterface; }
+
+namespace sync_file_system {
+namespace drive_backend {
+
+// This class is responsible for talking to the Drive service to get and put
+// Drive directories, files and metadata.
+// This class is owned by DriveFileSyncService.
+class APIUtil : public APIUtilInterface,
+                public drive::DriveServiceObserver,
+                public net::NetworkChangeNotifier::ConnectionTypeObserver,
+                public base::NonThreadSafe,
+                public base::SupportsWeakPtr<APIUtil> {
+ public:
+  // The resulting status of EnsureTitleUniqueness.
+  enum EnsureUniquenessStatus {
+    NO_DUPLICATES_FOUND,
+    RESOLVED_DUPLICATES,
+  };
+
+  typedef base::Callback<void(google_apis::GDataErrorCode,
+                              EnsureUniquenessStatus status,
+                              scoped_ptr<google_apis::ResourceEntry> entry)>
+      EnsureUniquenessCallback;
+
+  explicit APIUtil(Profile* profile);
+  virtual ~APIUtil();
+
+  virtual void AddObserver(APIUtilObserver* observer) OVERRIDE;
+  virtual void RemoveObserver(APIUtilObserver* observer) OVERRIDE;
+
+  static scoped_ptr<APIUtil> CreateForTesting(
+      Profile* profile,
+      scoped_ptr<drive::DriveServiceInterface> drive_service,
+      scoped_ptr<drive::DriveUploaderInterface> drive_uploader);
+
+  // APIUtilInterface overrides.
+  virtual void GetDriveDirectoryForSyncRoot(const ResourceIdCallback& callback)
+      OVERRIDE;
+  virtual void GetDriveDirectoryForOrigin(
+      const std::string& sync_root_resource_id,
+      const GURL& origin,
+      const ResourceIdCallback& callback) OVERRIDE;
+  virtual void GetLargestChangeStamp(const ChangeStampCallback& callback)
+      OVERRIDE;
+  virtual void GetResourceEntry(const std::string& resource_id,
+                                const ResourceEntryCallback& callback) OVERRIDE;
+  virtual void ListFiles(const std::string& directory_resource_id,
+                         const ResourceListCallback& callback) OVERRIDE;
+  virtual void ListChanges(int64 start_changestamp,
+                           const ResourceListCallback& callback) OVERRIDE;
+  virtual void ContinueListing(const GURL& feed_url,
+                               const ResourceListCallback& callback) OVERRIDE;
+  virtual void DownloadFile(const std::string& resource_id,
+                            const std::string& local_file_md5,
+                            const base::FilePath& local_file_path,
+                            const DownloadFileCallback& callback) OVERRIDE;
+  virtual void UploadNewFile(const std::string& directory_resource_id,
+                             const base::FilePath& local_file_path,
+                             const std::string& title,
+                             const UploadFileCallback& callback) OVERRIDE;
+  virtual void UploadExistingFile(const std::string& resource_id,
+                                  const std::string& remote_file_md5,
+                                  const base::FilePath& local_file_path,
+                                  const UploadFileCallback& callback) OVERRIDE;
+  virtual void CreateDirectory(const std::string& parent_resource_id,
+                               const std::string& title,
+                               const ResourceIdCallback& callback) OVERRIDE;
+  virtual bool IsAuthenticated() const OVERRIDE;
+  virtual void DeleteFile(const std::string& resource_id,
+                          const std::string& remote_file_md5,
+                          const GDataErrorCallback& callback) OVERRIDE;
+  virtual GURL ResourceIdToResourceLink(const std::string& resource_id) const
+      OVERRIDE;
+  virtual void EnsureSyncRootIsNotInMyDrive(
+      const std::string& sync_root_resource_id) OVERRIDE;
+
+  static std::string GetSyncRootDirectoryName();
+  static std::string OriginToDirectoryTitle(const GURL& origin);
+  static GURL DirectoryTitleToOrigin(const std::string& title);
+
+  // DriveServiceObserver overrides.
+  virtual void OnReadyToSendRequests() OVERRIDE;
+
+  // ConnectionTypeObserver overrides.
+  virtual void OnConnectionTypeChanged(
+      net::NetworkChangeNotifier::ConnectionType type) OVERRIDE;
+
+ private:
+  typedef int64 UploadKey;
+  typedef std::map<UploadKey, UploadFileCallback> UploadCallbackMap;
+
+  friend class APIUtilTest;
+
+  // Constructor for test use.
+  APIUtil(Profile* profile,
+          const GURL& base_url,
+          const GURL& base_download_url,
+          scoped_ptr<drive::DriveServiceInterface> drive_service,
+          scoped_ptr<drive::DriveUploaderInterface> drive_uploader);
+
+  void GetDriveRootResourceId(const GDataErrorCallback& callback);
+  void DidGetDriveRootResourceId(
+      const GDataErrorCallback& callback,
+      google_apis::GDataErrorCode error,
+      scoped_ptr<google_apis::AboutResource> about_resource);
+
+  void DidGetDriveRootResourceIdForGetSyncRoot(
+      const ResourceIdCallback& callback,
+      google_apis::GDataErrorCode error);
+
+  void DidGetDirectory(const std::string& parent_resource_id,
+                       const std::string& directory_name,
+                       const ResourceIdCallback& callback,
+                       google_apis::GDataErrorCode error,
+                       scoped_ptr<google_apis::ResourceList> feed);
+
+  void DidCreateDirectory(const std::string& parent_resource_id,
+                          const std::string& title,
+                          const ResourceIdCallback& callback,
+                          google_apis::GDataErrorCode error,
+                          scoped_ptr<google_apis::ResourceEntry> entry);
+
+  void DidEnsureUniquenessForCreateDirectory(
+      const ResourceIdCallback& callback,
+      google_apis::GDataErrorCode error,
+      EnsureUniquenessStatus status,
+      scoped_ptr<google_apis::ResourceEntry> entry);
+
+  void SearchByTitle(const std::string& title,
+                     const std::string& directory_resource_id,
+                     const ResourceListCallback& callback);
+
+  void DidGetLargestChangeStamp(
+      const ChangeStampCallback& callback,
+      google_apis::GDataErrorCode error,
+      scoped_ptr<google_apis::AboutResource> about_resource);
+
+  void DidGetDriveRootResourceIdForEnsureSyncRoot(
+      const std::string& sync_root_resource_id,
+      google_apis::GDataErrorCode error);
+
+  void DidGetResourceList(const ResourceListCallback& callback,
+                          google_apis::GDataErrorCode error,
+                          scoped_ptr<google_apis::ResourceList> resource_list);
+
+  void DidGetResourceEntry(const ResourceEntryCallback& callback,
+                           google_apis::GDataErrorCode error,
+                           scoped_ptr<google_apis::ResourceEntry> entry);
+
+  void DownloadFileInternal(const std::string& local_file_md5,
+                            const base::FilePath& local_file_path,
+                            const DownloadFileCallback& callback,
+                            google_apis::GDataErrorCode error,
+                            scoped_ptr<google_apis::ResourceEntry> entry);
+
+  void DidDownloadFile(scoped_ptr<google_apis::ResourceEntry> entry,
+                       const DownloadFileCallback& callback,
+                       google_apis::GDataErrorCode error,
+                       const base::FilePath& downloaded_file_path);
+
+  void DidUploadNewFile(const std::string& parent_resource_id,
+                        const std::string& title,
+                        UploadKey upload_key,
+                        google_apis::GDataErrorCode error,
+                        scoped_ptr<google_apis::ResourceEntry> entry);
+
+  void DidEnsureUniquenessForCreateFile(
+      const std::string& expected_resource_id,
+      const UploadFileCallback& callback,
+      google_apis::GDataErrorCode error,
+      EnsureUniquenessStatus status,
+      scoped_ptr<google_apis::ResourceEntry> entry);
+
+  void UploadExistingFileInternal(const std::string& remote_file_md5,
+                                  const base::FilePath& local_file_path,
+                                  const UploadFileCallback& callback,
+                                  google_apis::GDataErrorCode error,
+                                  scoped_ptr<google_apis::ResourceEntry> entry);
+
+  void DidUploadExistingFile(UploadKey upload_key,
+                             google_apis::GDataErrorCode error,
+                             scoped_ptr<google_apis::ResourceEntry> entry);
+
+  void DeleteFileInternal(const std::string& remote_file_md5,
+                          const GDataErrorCallback& callback,
+                          google_apis::GDataErrorCode error,
+                          scoped_ptr<google_apis::ResourceEntry> entry);
+
+  void DidDeleteFile(const GDataErrorCallback& callback,
+                     google_apis::GDataErrorCode error);
+
+  void EnsureTitleUniqueness(const std::string& parent_resource_id,
+                             const std::string& expected_title,
+                             const EnsureUniquenessCallback& callback);
+  void DidListEntriesToEnsureUniqueness(
+      const std::string& parent_resource_id,
+      const std::string& expected_title,
+      const EnsureUniquenessCallback& callback,
+      google_apis::GDataErrorCode error,
+      scoped_ptr<google_apis::ResourceList> feed);
+  void DeleteEntriesForEnsuringTitleUniqueness(
+      ScopedVector<google_apis::ResourceEntry> entries,
+      const GDataErrorCallback& callback);
+  void DidDeleteEntriesForEnsuringTitleUniqueness(
+      ScopedVector<google_apis::ResourceEntry> entries,
+      const GDataErrorCallback& callback,
+      google_apis::GDataErrorCode error);
+
+  UploadKey RegisterUploadCallback(const UploadFileCallback& callback);
+  UploadFileCallback GetAndUnregisterUploadCallback(UploadKey key);
+  void CancelAllUploads(google_apis::GDataErrorCode error);
+
+  std::string GetRootResourceId() const;
+
+  scoped_ptr<drive::DriveServiceInterface> drive_service_;
+  scoped_ptr<drive::DriveUploaderInterface> drive_uploader_;
+
+  google_apis::GDataWapiUrlGenerator wapi_url_generator_;
+  google_apis::DriveApiUrlGenerator drive_api_url_generator_;
+
+  UploadCallbackMap upload_callback_map_;
+  UploadKey upload_next_key_;
+
+  std::string root_resource_id_;
+
+  ObserverList<APIUtilObserver> observers_;
+
+  DISALLOW_COPY_AND_ASSIGN(APIUtil);
+};
+
+}  // namespace drive_backend
+}  // namespace sync_file_system
+
+#endif  // CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_API_UTIL_H_
diff --git a/chrome/browser/sync_file_system/drive_backend/api_util_interface.h b/chrome/browser/sync_file_system/drive_backend/api_util_interface.h
new file mode 100644
index 0000000..46867f2
--- /dev/null
+++ b/chrome/browser/sync_file_system/drive_backend/api_util_interface.h
@@ -0,0 +1,198 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_API_UTIL_INTERFACE_H_
+#define CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_API_UTIL_INTERFACE_H_
+
+#include <string>
+
+#include "base/callback_forward.h"
+#include "chrome/browser/google_apis/gdata_errorcode.h"
+#include "chrome/browser/google_apis/gdata_wapi_parser.h"
+
+class GURL;
+class Profile;
+
+namespace base {
+class Time;
+}
+
+namespace google_apis {
+class DriveUploaderInterface;
+}
+
+namespace sync_file_system {
+namespace drive_backend {
+
+class APIUtilObserver {
+ public:
+  APIUtilObserver() {}
+  virtual ~APIUtilObserver() {}
+  virtual void OnAuthenticated() = 0;
+  virtual void OnNetworkConnected() = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(APIUtilObserver);
+};
+
+// The implementation of this class is responsible for talking to the Drive
+// service to get and put Drive directories, files and metadata.
+// This class is owned by DriveFileSyncService.
+class APIUtilInterface {
+ public:
+  typedef base::Callback<void(google_apis::GDataErrorCode error)>
+      GDataErrorCallback;
+  typedef base::Callback<void(google_apis::GDataErrorCode error,
+                              const std::string& file_md5,
+                              int64 file_size,
+                              const base::Time& last_updated)>
+      DownloadFileCallback;
+  typedef base::Callback<void(google_apis::GDataErrorCode error,
+                              const std::string& resource_id,
+                              const std::string& file_md5)> UploadFileCallback;
+  typedef base::Callback<
+      void(google_apis::GDataErrorCode error, const std::string& resource_id)>
+      ResourceIdCallback;
+  typedef base::Callback<void(google_apis::GDataErrorCode error,
+                              int64 changestamp)> ChangeStampCallback;
+  typedef base::Callback<void(google_apis::GDataErrorCode error,
+                              scoped_ptr<google_apis::ResourceList> feed)>
+      ResourceListCallback;
+  typedef base::Callback<void(google_apis::GDataErrorCode error,
+                              scoped_ptr<google_apis::ResourceEntry> entry)>
+      ResourceEntryCallback;
+
+  APIUtilInterface() {}
+  virtual ~APIUtilInterface() {}
+
+  virtual void AddObserver(APIUtilObserver* observer) = 0;
+  virtual void RemoveObserver(APIUtilObserver* observer) = 0;
+
+  // Fetches Resource ID of the directory where we should place all files to
+  // sync.  Upon completion, invokes |callback|.
+  // If the directory does not exist on the server this also creates
+  // the directory.
+  //
+  // Returns HTTP_SUCCESS if the directory already exists.
+  // Returns HTTP_CREATED if the directory was not found and created.
+  virtual void GetDriveDirectoryForSyncRoot(
+      const ResourceIdCallback& callback) = 0;
+
+  // Fetches Resource ID of the directory for the |origin|.
+  // Upon completion, invokes |callback|.
+  // If the directory does not exist on the server this also creates
+  // the directory.
+  //
+  // Returns HTTP_SUCCESS if the directory already exists.
+  // Returns HTTP_CREATED if the directory was not found and created.
+  virtual void GetDriveDirectoryForOrigin(
+      const std::string& sync_root_resource_id,
+      const GURL& origin,
+      const ResourceIdCallback& callback) = 0;
+
+  // Fetches the largest changestamp for the signed-in account.
+  // Upon completion, invokes |callback|.
+  virtual void GetLargestChangeStamp(const ChangeStampCallback& callback) = 0;
+
+  // Fetches the resource entry for the file identified by |resource_id|.
+  // Upon completion, invokes |callback|.
+  virtual void GetResourceEntry(const std::string& resource_id,
+                                const ResourceEntryCallback& callback) = 0;
+
+  // Lists files in the directory identified by |resource_id|.
+  // Upon completion, invokes |callback|.
+  // The result may be chunked and may have successive results. The caller needs
+  // to call ContunueListing with the result of GetNextFeedURL to get complete
+  // list of files.
+  virtual void ListFiles(const std::string& directory_resource_id,
+                         const ResourceListCallback& callback) = 0;
+
+  // Lists changes that happened after |start_changestamp|.
+  // Upon completion, invokes |callback|.
+  // The result may be chunked and may have successive results. The caller needs
+  // to call ContunueListing with the result of GetNextFeedURL to get complete
+  // list of changes.
+  virtual void ListChanges(int64 start_changestamp,
+                           const ResourceListCallback& callback) = 0;
+
+  // Fetches the next chunk of ResourceList identified by |feed_url|.
+  // Upon completion, invokes |callback|.
+  virtual void ContinueListing(const GURL& feed_url,
+                               const ResourceListCallback& callback) = 0;
+
+  // Downloads the file identified by |resource_id| from Drive to
+  // |local_file_path|.
+  // |local_file_md5| represents the hash value of the local file to be updated.
+  // If |local_file_md5| is equal to remote file's value, cancels the download
+  // and invokes |callback| with GDataErrorCode::HTTP_NOT_MODIFIED immediately.
+  // When there is no local file to be updated, |local_file_md5| should be
+  // empty.
+  virtual void DownloadFile(const std::string& resource_id,
+                            const std::string& local_file_md5,
+                            const base::FilePath& local_file_path,
+                            const DownloadFileCallback& callback) = 0;
+
+  // Uploads the new file |local_file_path| with specified |title| into the
+  // directory identified by |directory_resource_id|.
+  // Upon completion, invokes |callback| and returns HTTP_CREATED if the file
+  // is created.
+  virtual void UploadNewFile(const std::string& directory_resource_id,
+                             const base::FilePath& local_file_path,
+                             const std::string& title,
+                             const UploadFileCallback& callback) = 0;
+
+  // Uploads the existing file identified by |local_file_path|.
+  // |remote_file_md5| represents the expected hash value of the file to be
+  // updated on Drive. If |remote_file_md5| is different from the actual value,
+  // cancels the upload and invokes |callback| with
+  // GDataErrorCode::HTTP_CONFLICT immediately.
+  // Returns HTTP_SUCCESS if the file uploaded successfully.
+  virtual void UploadExistingFile(const std::string& resource_id,
+                                  const std::string& remote_file_md5,
+                                  const base::FilePath& local_file_path,
+                                  const UploadFileCallback& callback) = 0;
+
+  // Creates a new directory with specified |title| into the directory
+  // identified by |parent_resource_id|.
+  // Upon completion, invokes |callback| and returns HTTP_CREATED if
+  // the directory is created.
+  virtual void CreateDirectory(const std::string& parent_resource_id,
+                               const std::string& title,
+                               const ResourceIdCallback& callback) = 0;
+
+  // Returns true if the user is authenticated.
+  virtual bool IsAuthenticated() const = 0;
+
+  // Deletes the file identified by |resource_id|.
+  // A directory is considered a file and will cause a recursive delete if
+  // given as the |resource_id|.
+  // TODO(tzik): Rename this function to DeleteResource.
+  //
+  // |remote_file_md5| represents the expected hash value of the file to be
+  // deleted from Drive. If |remote_file_md5| is empty, then it's implied that
+  // the file should be deleted on the remote side regardless. If
+  // |remote_file_md5| is not empty and is different from the actual value,
+  // the deletion operation is canceled and the |callback| with
+  // GDataErrorCode::HTTP_CONFLICT is invoked immediately.
+  virtual void DeleteFile(const std::string& resource_id,
+                          const std::string& remote_file_md5,
+                          const GDataErrorCallback& callback) = 0;
+
+  // Converts |resource_id| to corresponing resource link.
+  virtual GURL ResourceIdToResourceLink(
+      const std::string& resource_id) const = 0;
+
+  // Ensures the sync root directory is not in 'My Drive'. Even if the directory
+  // is in directories other than 'My Drive', it will not be removed from there.
+  virtual void EnsureSyncRootIsNotInMyDrive(
+      const std::string& sync_root_resource_id) = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(APIUtilInterface);
+};
+
+}  // namespace drive_backend
+}  // namespace sync_file_system
+
+#endif  // CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_API_UTIL_INTERFACE_H_
diff --git a/chrome/browser/sync_file_system/drive_backend/api_util_unittest.cc b/chrome/browser/sync_file_system/drive_backend/api_util_unittest.cc
new file mode 100644
index 0000000..af75d06
--- /dev/null
+++ b/chrome/browser/sync_file_system/drive_backend/api_util_unittest.cc
@@ -0,0 +1,1161 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/sync_file_system/drive_backend/api_util.h"
+
+#include "base/location.h"
+#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/strings/stringprintf.h"
+#include "base/values.h"
+#include "chrome/browser/drive/drive_uploader.h"
+#include "chrome/browser/drive/fake_drive_service.h"
+#include "chrome/browser/google_apis/drive_api_parser.h"
+#include "chrome/browser/google_apis/gdata_errorcode.h"
+#include "chrome/browser/google_apis/test_util.h"
+#include "chrome/browser/sync_file_system/drive_file_sync_util.h"
+#include "chrome/test/base/testing_profile.h"
+#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "net/base/escape.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#define FPL(x) FILE_PATH_LITERAL(x)
+
+using drive::DriveServiceInterface;
+using drive::DriveUploaderInterface;
+using drive::FakeDriveService;
+using drive::UploadCompletionCallback;
+using google_apis::GDataErrorCode;
+using google_apis::ProgressCallback;
+using google_apis::ResourceEntry;
+using google_apis::ResourceList;
+
+namespace sync_file_system {
+namespace drive_backend {
+
+namespace {
+
+const char kOrigin[] = "chrome-extension://example";
+const char kOriginDirectoryName[] = "example";
+
+void DidRemoveResourceFromDirectory(GDataErrorCode error) {
+  ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
+}
+
+void DidAddFileOrDirectoryForMakingConflict(GDataErrorCode error,
+                                            scoped_ptr<ResourceEntry> entry) {
+  ASSERT_EQ(google_apis::HTTP_CREATED, error);
+  ASSERT_TRUE(entry);
+}
+
+void DidAddNewDirectory(std::string* resource_id_out,
+                        GDataErrorCode error,
+                        scoped_ptr<ResourceEntry> entry) {
+  ASSERT_TRUE(resource_id_out);
+  ASSERT_EQ(google_apis::HTTP_CREATED, error);
+  ASSERT_TRUE(entry);
+  *resource_id_out = entry->resource_id();
+}
+
+void DidAddNewFile(std::string* resource_id_out,
+                   std::string* file_md5_out,
+                   GDataErrorCode error,
+                   scoped_ptr<ResourceEntry> entry) {
+  ASSERT_TRUE(resource_id_out);
+  ASSERT_TRUE(file_md5_out);
+  ASSERT_EQ(google_apis::HTTP_CREATED, error);
+  ASSERT_TRUE(entry);
+  *resource_id_out = entry->resource_id();
+  *file_md5_out = entry->file_md5();
+}
+
+void DidAddFileForUploadNew(
+    const UploadCompletionCallback& callback,
+    GDataErrorCode error,
+    scoped_ptr<ResourceEntry> entry) {
+  ASSERT_EQ(google_apis::HTTP_CREATED, error);
+  ASSERT_TRUE(entry);
+  base::MessageLoopProxy::current()->PostTask(
+      FROM_HERE,
+      base::Bind(callback,
+                 google_apis::HTTP_SUCCESS,
+                 GURL(),
+                 base::Passed(&entry)));
+}
+
+void DidGetResourceEntryForUploadExisting(
+    const UploadCompletionCallback& callback,
+    GDataErrorCode error,
+    scoped_ptr<ResourceEntry> entry) {
+  ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
+  ASSERT_TRUE(entry);
+  base::MessageLoopProxy::current()->PostTask(
+      FROM_HERE,
+      base::Bind(callback,
+                 google_apis::HTTP_SUCCESS,
+                 GURL(),
+                 base::Passed(&entry)));
+}
+
+void VerifyTitleUniqueness(const tracked_objects::Location& from_here,
+                           const std::string& resource_id,
+                           google_apis::DriveEntryKind kind,
+                           GDataErrorCode error,
+                           scoped_ptr<ResourceList> resource_list) {
+  std::string location(" failed at " + from_here.ToString());
+  ASSERT_FALSE(resource_id.empty()) << location;
+  ASSERT_EQ(google_apis::HTTP_SUCCESS, error) << location;
+  ASSERT_TRUE(resource_list) << location;
+
+  const ScopedVector<ResourceEntry>& entries = resource_list->entries();
+  ASSERT_EQ(1u, entries.size());
+  EXPECT_EQ(resource_id, entries[0]->resource_id());
+  switch (kind) {
+    case google_apis::ENTRY_KIND_FOLDER:
+      EXPECT_TRUE(entries[0]->is_folder()) << location;
+      return;
+    case google_apis::ENTRY_KIND_FILE:
+      EXPECT_TRUE(entries[0]->is_file()) << location;
+      return;
+    default:
+      NOTREACHED() << "Unexpected DriveEntryKind: " << kind << location;
+      return;
+  }
+}
+
+void VerifyFileDeletion(const tracked_objects::Location& from_here,
+                        GDataErrorCode error,
+                        scoped_ptr<ResourceList> resource_list) {
+  std::string location(" failed at " + from_here.ToString());
+  ASSERT_EQ(google_apis::HTTP_SUCCESS, error) << location;
+  ASSERT_TRUE(resource_list) << location;
+  EXPECT_TRUE(resource_list->entries().empty()) << location;
+}
+
+class FakeDriveServiceWrapper : public FakeDriveService {
+ public:
+  FakeDriveServiceWrapper() : make_directory_conflict_(false) {};
+  virtual ~FakeDriveServiceWrapper() {};
+
+  // DriveServiceInterface overrides.
+  virtual google_apis::CancelCallback AddNewDirectory(
+      const std::string& parent_resource_id,
+      const std::string& directory_name,
+      const google_apis::GetResourceEntryCallback& callback) OVERRIDE {
+    if (make_directory_conflict_) {
+      FakeDriveService::AddNewDirectory(
+          parent_resource_id,
+          directory_name,
+          base::Bind(&DidAddFileOrDirectoryForMakingConflict));
+    }
+    return FakeDriveService::AddNewDirectory(
+        parent_resource_id, directory_name, callback);
+  }
+
+  void set_make_directory_conflict(bool enable) {
+    make_directory_conflict_ = enable;
+  }
+
+ private:
+  bool make_directory_conflict_;
+
+  DISALLOW_COPY_AND_ASSIGN(FakeDriveServiceWrapper);
+};
+
+// A fake implementation of DriveUploaderInterface, which provides fake
+// behaviors for file uploading.
+class FakeDriveUploader : public DriveUploaderInterface {
+ public:
+  explicit FakeDriveUploader(FakeDriveServiceWrapper* fake_drive_service)
+      : fake_drive_service_(fake_drive_service),
+        make_file_conflict_(false) {}
+  virtual ~FakeDriveUploader() {}
+
+  // DriveUploaderInterface overrides.
+
+  // Proxies a request to upload a new file to FakeDriveService, and returns the
+  // resource entry to the caller.
+  virtual google_apis::CancelCallback UploadNewFile(
+      const std::string& parent_resource_id,
+      const base::FilePath& local_file_path,
+      const std::string& title,
+      const std::string& content_type,
+      const UploadCompletionCallback& callback,
+      const ProgressCallback& progress_callback) OVERRIDE {
+    DCHECK(!callback.is_null());
+    const std::string kFileContent = "test content";
+
+    if (make_file_conflict_) {
+      fake_drive_service_->AddNewFile(
+          content_type,
+          kFileContent,
+          parent_resource_id,
+          title,
+          false,  // shared_with_me
+          base::Bind(&DidAddFileOrDirectoryForMakingConflict));
+    }
+
+    fake_drive_service_->AddNewFile(
+        content_type,
+        kFileContent,
+        parent_resource_id,
+        title,
+        false,  // shared_with_me
+        base::Bind(&DidAddFileForUploadNew, callback));
+    base::MessageLoop::current()->RunUntilIdle();
+
+    return google_apis::CancelCallback();
+  }
+
+  // Pretends that an existing file |resource_id| was uploaded successfully, and
+  // returns a resource entry to the caller.
+  virtual google_apis::CancelCallback UploadExistingFile(
+      const std::string& resource_id,
+      const base::FilePath& local_file_path,
+      const std::string& content_type,
+      const std::string& etag,
+      const UploadCompletionCallback& callback,
+      const ProgressCallback& progress_callback) OVERRIDE {
+    DCHECK(!callback.is_null());
+    return fake_drive_service_->GetResourceEntry(
+        resource_id,
+        base::Bind(&DidGetResourceEntryForUploadExisting, callback));
+  }
+
+  // At the moment, sync file system doesn't support resuming of the uploading.
+  // So this method shouldn't be reached.
+  virtual google_apis::CancelCallback ResumeUploadFile(
+      const GURL& upload_location,
+      const base::FilePath& local_file_path,
+      const std::string& content_type,
+      const UploadCompletionCallback& callback,
+      const ProgressCallback& progress_callback) OVERRIDE {
+    NOTREACHED();
+    return google_apis::CancelCallback();
+  }
+
+  void set_make_file_conflict(bool enable) {
+    make_file_conflict_ = enable;
+  }
+
+ private:
+  FakeDriveServiceWrapper* fake_drive_service_;
+  bool make_file_conflict_;
+
+  DISALLOW_COPY_AND_ASSIGN(FakeDriveUploader);
+};
+
+}  // namespace
+
+class APIUtilTest : public testing::Test {
+ public:
+  APIUtilTest() : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
+                  fake_drive_service_(NULL),
+                  fake_drive_uploader_(NULL) {}
+
+  virtual void SetUp() OVERRIDE {
+    fake_drive_service_ = new FakeDriveServiceWrapper;
+    fake_drive_uploader_ = new FakeDriveUploader(fake_drive_service_);
+
+    api_util_ = APIUtil::CreateForTesting(
+        &profile_,
+        scoped_ptr<DriveServiceInterface>(fake_drive_service_),
+        scoped_ptr<DriveUploaderInterface>(fake_drive_uploader_));
+
+    fake_drive_service_->LoadResourceListForWapi(
+        "sync_file_system/initialize.json");
+  }
+
+  virtual void TearDown() OVERRIDE {
+    api_util_.reset();
+  }
+
+ protected:
+  void SetUpSyncRootDirectory() {
+    fake_drive_service()->AddNewDirectory(
+        fake_drive_service_->GetRootResourceId(),
+        APIUtil::GetSyncRootDirectoryName(),
+        base::Bind(&DidAddNewDirectory, &sync_root_resource_id_));
+    base::MessageLoop::current()->RunUntilIdle();
+
+    ASSERT_TRUE(!sync_root_resource_id_.empty());
+    fake_drive_service()->RemoveResourceFromDirectory(
+        fake_drive_service_->GetRootResourceId(),
+        sync_root_resource_id_,
+        base::Bind(&DidRemoveResourceFromDirectory));
+    base::MessageLoop::current()->RunUntilIdle();
+  }
+
+  void SetUpOriginRootDirectory() {
+    ASSERT_TRUE(!sync_root_resource_id_.empty());
+    fake_drive_service()->AddNewDirectory(
+        GetSyncRootResourceId(),
+        kOriginDirectoryName,
+        base::Bind(&DidAddNewDirectory, &origin_root_resource_id_));
+    base::MessageLoop::current()->RunUntilIdle();
+  }
+
+  void SetUpFile(const std::string& content_data,
+                 const std::string& title,
+                 std::string* resource_id_out,
+                 std::string* file_md5_out) {
+    ASSERT_TRUE(!origin_root_resource_id_.empty());
+    ASSERT_TRUE(resource_id_out);
+    ASSERT_TRUE(file_md5_out);
+    fake_drive_service()->AddNewFile(
+        "text/plain",
+        content_data,
+        origin_root_resource_id_,
+        title,
+        false,  // shared_with_me
+        base::Bind(&DidAddNewFile, resource_id_out, file_md5_out));
+    base::MessageLoop::current()->RunUntilIdle();
+  }
+
+  std::string GetSyncRootResourceId() {
+    DCHECK(!sync_root_resource_id_.empty());
+    return sync_root_resource_id_;
+  }
+
+  std::string GetOriginRootResourceId() {
+    DCHECK(!origin_root_resource_id_.empty());
+    return origin_root_resource_id_;
+  }
+
+  APIUtil* api_util() { return api_util_.get(); }
+
+  FakeDriveServiceWrapper* fake_drive_service() {
+    return fake_drive_service_;
+  }
+
+  FakeDriveUploader* fake_drive_uploader() {
+    return fake_drive_uploader_;
+  }
+
+  void TestGetSyncRoot();
+  void TestCreateSyncRoot();
+  void TestCreateSyncRoot_Conflict();
+  void TestGetOriginDirectory();
+  void TestCreateOriginDirectory();
+  void TestCreateOriginDirectory_Conflict();
+  void TestGetLargestChangeStamp();
+  void TestListFiles();
+  void TestListChanges();
+  void TestDownloadFile();
+  void TestDownloadFileInNotModified();
+  void TestUploadNewFile();
+  void TestUploadNewFile_ConflictWithFile();
+  void TestUploadExistingFile();
+  void TestUploadExistingFileInConflict();
+  void TestDeleteFile();
+  void TestDeleteFileInConflict();
+  void TestCreateDirectory();
+
+ private:
+  content::TestBrowserThreadBundle thread_bundle_;
+
+  std::string sync_root_resource_id_;
+  std::string origin_root_resource_id_;
+
+  TestingProfile profile_;
+  scoped_ptr<APIUtil> api_util_;
+  FakeDriveServiceWrapper* fake_drive_service_;
+  FakeDriveUploader* fake_drive_uploader_;
+
+  DISALLOW_COPY_AND_ASSIGN(APIUtilTest);
+};
+
+void DidGetResourceID(bool* done_out,
+                      GDataErrorCode* error_out,
+                      std::string* resource_id_out,
+                      GDataErrorCode error,
+                      const std::string& resource_id) {
+  EXPECT_FALSE(*done_out);
+  *done_out = true;
+  *error_out = error;
+  *resource_id_out = resource_id;
+}
+
+#if !defined(OS_ANDROID)
+
+void DidGetLargestChangeStamp(bool* done_out,
+                              GDataErrorCode* error_out,
+                              int64* largest_changestamp_out,
+                              GDataErrorCode error,
+                              int64 largest_changestamp) {
+  EXPECT_FALSE(*done_out);
+  *done_out = true;
+  *error_out = error;
+  *largest_changestamp_out = largest_changestamp;
+}
+
+void DidGetResourceList(bool* done_out,
+                        GDataErrorCode* error_out,
+                        scoped_ptr<ResourceList>* document_feed_out,
+                        GDataErrorCode error,
+                        scoped_ptr<ResourceList> document_feed) {
+  EXPECT_FALSE(*done_out);
+  *done_out = true;
+  *error_out = error;
+  *document_feed_out = document_feed.Pass();
+}
+
+void DidDownloadFile(bool* done_out,
+                     std::string* expected_file_md5_out,
+                     GDataErrorCode* error_out,
+                     GDataErrorCode error,
+                     const std::string& file_md5,
+                     int64 file_size,
+                     const base::Time& updated_time) {
+  EXPECT_FALSE(*done_out);
+  *done_out = true;
+  *error_out = error;
+  *expected_file_md5_out = file_md5;
+}
+
+void DidUploadFile(bool* done_out,
+                   GDataErrorCode* error_out,
+                   std::string* resource_id_out,
+                   GDataErrorCode error,
+                   const std::string& resource_id,
+                   const std::string& file_md5) {
+  EXPECT_FALSE(*done_out);
+  *done_out = true;
+  *error_out = error;
+  *resource_id_out = resource_id;
+}
+
+void DidDeleteFile(bool* done_out,
+                   GDataErrorCode* error_out,
+                   GDataErrorCode error) {
+  EXPECT_FALSE(*done_out);
+  *done_out = true;
+  *error_out = error;
+}
+
+void APIUtilTest::TestGetSyncRoot() {
+  fake_drive_service()->LoadAccountMetadataForWapi(
+      "sync_file_system/account_metadata.json");
+  SetUpSyncRootDirectory();
+
+  bool done = false;
+  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
+  std::string resource_id;
+  api_util()->GetDriveDirectoryForSyncRoot(
+      base::Bind(&DidGetResourceID, &done, &error, &resource_id));
+  base::MessageLoop::current()->RunUntilIdle();
+
+  EXPECT_TRUE(done);
+  EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
+  EXPECT_EQ(GetSyncRootResourceId(), resource_id);
+}
+
+void APIUtilTest::TestCreateSyncRoot() {
+  fake_drive_service()->LoadAccountMetadataForWapi(
+      "sync_file_system/account_metadata.json");
+  bool done = false;
+  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
+  std::string resource_id;
+  api_util()->GetDriveDirectoryForSyncRoot(
+      base::Bind(&DidGetResourceID, &done, &error, &resource_id));
+  base::MessageLoop::current()->RunUntilIdle();
+
+  EXPECT_TRUE(done);
+  EXPECT_EQ(google_apis::HTTP_CREATED, error);
+  EXPECT_FALSE(resource_id.empty());
+
+  fake_drive_service()->SearchByTitle(
+      APIUtil::GetSyncRootDirectoryName(),
+      std::string(),  // directory_resource_id
+      base::Bind(&VerifyTitleUniqueness,
+                 FROM_HERE,
+                 resource_id,
+                 google_apis::ENTRY_KIND_FOLDER));
+  base::MessageLoop::current()->RunUntilIdle();
+}
+
+void APIUtilTest::TestCreateSyncRoot_Conflict() {
+  fake_drive_service()->LoadAccountMetadataForWapi(
+      "sync_file_system/account_metadata.json");
+  fake_drive_service()->set_make_directory_conflict(true);
+
+  bool done = false;
+  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
+  std::string resource_id;
+  api_util()->GetDriveDirectoryForSyncRoot(
+      base::Bind(&DidGetResourceID, &done, &error, &resource_id));
+  base::MessageLoop::current()->RunUntilIdle();
+
+  EXPECT_TRUE(done);
+  EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
+  EXPECT_FALSE(resource_id.empty());
+
+  // Verify that there is no duplicated directory on the remote side.
+  fake_drive_service()->SearchByTitle(
+      APIUtil::GetSyncRootDirectoryName(),
+      std::string(),  // directory_resource_id
+      base::Bind(&VerifyTitleUniqueness,
+                 FROM_HERE,
+                 resource_id,
+                 google_apis::ENTRY_KIND_FOLDER));
+  base::MessageLoop::current()->RunUntilIdle();
+}
+
+void APIUtilTest::TestGetOriginDirectory() {
+  SetUpSyncRootDirectory();
+  SetUpOriginRootDirectory();
+
+  bool done = false;
+  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
+  std::string resource_id;
+  api_util()->GetDriveDirectoryForOrigin(
+      GetSyncRootResourceId(),
+      GURL(kOrigin),
+      base::Bind(&DidGetResourceID, &done, &error, &resource_id));
+  base::MessageLoop::current()->RunUntilIdle();
+
+  EXPECT_TRUE(done);
+  EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
+  EXPECT_EQ(GetOriginRootResourceId(), resource_id);
+}
+
+void APIUtilTest::TestCreateOriginDirectory() {
+  SetUpSyncRootDirectory();
+
+  bool done = false;
+  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
+  std::string resource_id;
+  api_util()->GetDriveDirectoryForOrigin(
+      GetSyncRootResourceId(),
+      GURL(kOrigin),
+      base::Bind(&DidGetResourceID, &done, &error, &resource_id));
+  base::MessageLoop::current()->RunUntilIdle();
+
+  EXPECT_TRUE(done);
+  EXPECT_EQ(google_apis::HTTP_CREATED, error);
+  EXPECT_FALSE(resource_id.empty());
+
+  fake_drive_service()->SearchByTitle(
+      kOriginDirectoryName,
+      GetSyncRootResourceId(),
+      base::Bind(&VerifyTitleUniqueness,
+                 FROM_HERE,
+                 resource_id,
+                 google_apis::ENTRY_KIND_FOLDER));
+  base::MessageLoop::current()->RunUntilIdle();
+}
+
+void APIUtilTest::TestCreateOriginDirectory_Conflict() {
+  SetUpSyncRootDirectory();
+  fake_drive_service()->set_make_directory_conflict(true);
+
+  bool done = false;
+  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
+  std::string resource_id;
+  api_util()->GetDriveDirectoryForOrigin(
+      GetSyncRootResourceId(),
+      GURL(kOrigin),
+      base::Bind(&DidGetResourceID, &done, &error, &resource_id));
+  base::MessageLoop::current()->RunUntilIdle();
+
+  EXPECT_TRUE(done);
+  EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
+  EXPECT_FALSE(resource_id.empty());
+
+  // Verify that there is no duplicated directory on the remote side.
+  fake_drive_service()->SearchByTitle(
+      kOriginDirectoryName,
+      GetSyncRootResourceId(),
+      base::Bind(&VerifyTitleUniqueness,
+                 FROM_HERE,
+                 resource_id,
+                 google_apis::ENTRY_KIND_FOLDER));
+  base::MessageLoop::current()->RunUntilIdle();
+}
+
+void APIUtilTest::TestGetLargestChangeStamp() {
+  fake_drive_service()->LoadAccountMetadataForWapi(
+      "sync_file_system/account_metadata.json");
+
+  bool done = false;
+  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
+  int64 largest_changestamp = -1;
+  api_util()->GetLargestChangeStamp(base::Bind(
+      &DidGetLargestChangeStamp, &done, &error, &largest_changestamp));
+  base::MessageLoop::current()->RunUntilIdle();
+
+  EXPECT_TRUE(done);
+  EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
+  EXPECT_EQ(654321, largest_changestamp);
+}
+
+void APIUtilTest::TestListFiles() {
+  fake_drive_service()->set_default_max_results(3);
+
+  SetUpSyncRootDirectory();
+  SetUpOriginRootDirectory();
+
+  int kNumberOfFiles = 5;
+  for (int i = 0; i < kNumberOfFiles; ++i) {
+    std::string file_resource_id;
+    std::string file_md5;
+    std::string file_content = base::StringPrintf("test content %d", i);
+    std::string file_title = base::StringPrintf("test_%d.txt", i);
+    SetUpFile(file_content, file_title, &file_resource_id, &file_md5);
+  }
+
+  bool done = false;
+  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
+  scoped_ptr<ResourceList> document_feed;
+  api_util()->ListFiles(
+      GetOriginRootResourceId(),
+      base::Bind(&DidGetResourceList, &done, &error, &document_feed));
+  base::MessageLoop::current()->RunUntilIdle();
+
+  EXPECT_TRUE(done);
+  EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
+  EXPECT_EQ(3U, document_feed->entries().size());
+
+  GURL feed_url;
+  ASSERT_TRUE(document_feed->GetNextFeedURL(&feed_url));
+
+  done = false;
+  error = google_apis::GDATA_OTHER_ERROR;
+  document_feed.reset();
+
+  api_util()->ContinueListing(
+      feed_url, base::Bind(&DidGetResourceList, &done, &error, &document_feed));
+  base::MessageLoop::current()->RunUntilIdle();
+
+  EXPECT_TRUE(done);
+  EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
+  EXPECT_EQ(2U, document_feed->entries().size());
+}
+
+void APIUtilTest::TestListChanges() {
+  const int64 kStartChangestamp = 6;
+
+  SetUpSyncRootDirectory();
+  SetUpOriginRootDirectory();
+
+  // Files should have changestamp #4+ since creating the sync root directory is
+  // #1, moving it out of 'My Drive' is #2, and creating the origin root
+  // directory is #3.
+  const int kNumberOfFiles = 5;
+  for (int i = 0; i < kNumberOfFiles; ++i) {
+    std::string file_resource_id;
+    std::string file_md5;
+    std::string file_content = base::StringPrintf("test content %d", i);
+    std::string file_title = base::StringPrintf("test_%d.txt", i);
+    SetUpFile(file_content, file_title, &file_resource_id, &file_md5);
+  }
+
+  bool done = false;
+  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
+  scoped_ptr<ResourceList> document_feed;
+  api_util()->ListFiles(
+      GetOriginRootResourceId(),
+      base::Bind(&DidGetResourceList, &done, &error, &document_feed));
+  base::MessageLoop::current()->RunUntilIdle();
+
+  EXPECT_TRUE(done);
+  EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
+  EXPECT_EQ(5U, document_feed->entries().size());
+
+  done = false;
+  error = google_apis::GDATA_OTHER_ERROR;
+  document_feed.reset();
+  api_util()->ListChanges(
+      kStartChangestamp,
+      base::Bind(&DidGetResourceList, &done, &error, &document_feed));
+  base::MessageLoop::current()->RunUntilIdle();
+
+  // There should be 3 files which have changestamp #6+.
+  EXPECT_TRUE(done);
+  EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
+  EXPECT_EQ(3U, document_feed->entries().size());
+}
+
+void APIUtilTest::TestDownloadFile() {
+  const std::string kFileContent = "test content";
+  const std::string kFileTitle = "test.txt";
+
+  SetUpSyncRootDirectory();
+  SetUpOriginRootDirectory();
+  std::string file_resource_id;
+  std::string file_md5;
+  SetUpFile(kFileContent, kFileTitle, &file_resource_id, &file_md5);
+
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+  const base::FilePath kOutputFilePath =
+      temp_dir.path().AppendASCII(kFileTitle);
+
+  bool done = false;
+  std::string downloaded_file_md5;
+  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
+  api_util()->DownloadFile(
+      file_resource_id,
+      "",  // local_file_md5
+      kOutputFilePath,
+      base::Bind(&DidDownloadFile, &done, &downloaded_file_md5, &error));
+  base::MessageLoop::current()->RunUntilIdle();
+
+  EXPECT_TRUE(done);
+  EXPECT_EQ(file_md5, downloaded_file_md5);
+  EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
+}
+
+void APIUtilTest::TestDownloadFileInNotModified() {
+  const std::string kFileContent = "test content";
+  const std::string kFileTitle = "test.txt";
+
+  SetUpSyncRootDirectory();
+  SetUpOriginRootDirectory();
+  std::string file_resource_id;
+  std::string file_md5;
+  SetUpFile(kFileContent, kFileTitle, &file_resource_id, &file_md5);
+
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+  const base::FilePath kOutputFilePath =
+      temp_dir.path().AppendASCII(kFileTitle);
+
+  bool done = false;
+  std::string downloaded_file_md5;
+  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
+
+  // Since local file's hash value is equal to remote file's one, it is expected
+  // to cancel download the file and to return NOT_MODIFIED status code.
+  api_util()->DownloadFile(
+      file_resource_id,
+      file_md5,
+      kOutputFilePath,
+      base::Bind(&DidDownloadFile, &done, &downloaded_file_md5, &error));
+  base::MessageLoop::current()->RunUntilIdle();
+
+  EXPECT_TRUE(done);
+  EXPECT_EQ(google_apis::HTTP_NOT_MODIFIED, error);
+  // TODO(nhiroki): Compare |file_md5| and |downloaded_file_md5| after making
+  // FakeDriveService::AddNewEntry set the correct MD5.
+}
+
+void APIUtilTest::TestUploadNewFile() {
+  const std::string kFileTitle = "test.txt";
+  const base::FilePath kLocalFilePath(FPL("/tmp/dir/file"));
+
+  SetUpSyncRootDirectory();
+  SetUpOriginRootDirectory();
+
+  bool done = false;
+  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
+  std::string resource_id;
+  api_util()->UploadNewFile(
+      GetOriginRootResourceId(),
+      kLocalFilePath,
+      kFileTitle,
+      base::Bind(&DidUploadFile, &done, &error, &resource_id));
+  base::MessageLoop::current()->RunUntilIdle();
+
+  EXPECT_TRUE(done);
+  EXPECT_EQ(google_apis::HTTP_CREATED, error);
+  EXPECT_TRUE(!resource_id.empty());
+
+  fake_drive_service()->SearchByTitle(
+      kFileTitle,
+      GetOriginRootResourceId(),
+      base::Bind(&VerifyTitleUniqueness,
+                 FROM_HERE,
+                 resource_id,
+                 google_apis::ENTRY_KIND_FILE));
+  base::MessageLoop::current()->RunUntilIdle();
+}
+
+void APIUtilTest::TestUploadNewFile_ConflictWithFile() {
+  const std::string kFileTitle = "test.txt";
+  const base::FilePath kLocalFilePath(FPL("/tmp/dir/file"));
+
+  fake_drive_uploader()->set_make_file_conflict(true);
+
+  SetUpSyncRootDirectory();
+  SetUpOriginRootDirectory();
+
+  bool done = false;
+  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
+  std::string resource_id;
+  api_util()->UploadNewFile(
+      GetOriginRootResourceId(),
+      kLocalFilePath,
+      kFileTitle,
+      base::Bind(&DidUploadFile, &done, &error, &resource_id));
+  base::MessageLoop::current()->RunUntilIdle();
+
+  // HTTP_CONFLICT error must be returned with empty resource_id.
+  EXPECT_TRUE(done);
+  EXPECT_EQ(google_apis::HTTP_CONFLICT, error);
+  EXPECT_TRUE(!resource_id.empty());
+
+  // Verify that there is no duplicated file on the remote side.
+  fake_drive_service()->SearchByTitle(
+      kFileTitle,
+      GetOriginRootResourceId(),
+      base::Bind(&VerifyTitleUniqueness,
+                 FROM_HERE,
+                 resource_id,
+                 google_apis::ENTRY_KIND_FILE));
+  base::MessageLoop::current()->RunUntilIdle();
+}
+
+void APIUtilTest::TestUploadExistingFile() {
+  const base::FilePath kLocalFilePath(FPL("/tmp/dir/file"));
+  const std::string kFileContent = "test content";
+  const std::string kFileTitle = "test.txt";
+
+  SetUpSyncRootDirectory();
+  SetUpOriginRootDirectory();
+  std::string file_resource_id;
+  std::string file_md5;
+  SetUpFile(kFileContent, kFileTitle, &file_resource_id, &file_md5);
+
+  bool done = false;
+  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
+  std::string resource_id;
+  api_util()->UploadExistingFile(
+      file_resource_id,
+      file_md5,
+      kLocalFilePath,
+      base::Bind(&DidUploadFile, &done, &error, &resource_id));
+  base::MessageLoop::current()->RunUntilIdle();
+
+  EXPECT_TRUE(done);
+  EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
+  EXPECT_EQ(file_resource_id, resource_id);
+
+  fake_drive_service()->SearchByTitle(
+      kFileTitle,
+      GetOriginRootResourceId(),
+      base::Bind(&VerifyTitleUniqueness,
+                 FROM_HERE,
+                 file_resource_id,
+                 google_apis::ENTRY_KIND_FILE));
+  base::MessageLoop::current()->RunUntilIdle();
+}
+
+void APIUtilTest::TestUploadExistingFileInConflict() {
+  const base::FilePath kLocalFilePath(FPL("/tmp/dir/file"));
+  const std::string kFileContent = "test content";
+  const std::string kFileTitle = "test.txt";
+
+  SetUpSyncRootDirectory();
+  SetUpOriginRootDirectory();
+  std::string file_resource_id;
+  std::string file_md5;
+  SetUpFile(kFileContent, kFileTitle, &file_resource_id, &file_md5);
+
+  // Since remote file's hash value is different from the expected one, it is
+  // expected to cancel upload the file and to return CONFLICT status code.
+  const std::string kExpectedRemoteFileMD5 = "123456";
+
+  bool done = false;
+  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
+  std::string resource_id;
+  api_util()->UploadExistingFile(
+      file_resource_id,
+      kExpectedRemoteFileMD5,
+      kLocalFilePath,
+      base::Bind(&DidUploadFile, &done, &error, &resource_id));
+  base::MessageLoop::current()->RunUntilIdle();
+
+  EXPECT_TRUE(done);
+  EXPECT_EQ(google_apis::HTTP_CONFLICT, error);
+  EXPECT_TRUE(resource_id.empty());
+
+  // Verify that there is no duplicated file on the remote side.
+  fake_drive_service()->SearchByTitle(
+      kFileTitle,
+      GetOriginRootResourceId(),
+      base::Bind(&VerifyTitleUniqueness,
+                 FROM_HERE,
+                 file_resource_id,
+                 google_apis::ENTRY_KIND_FILE));
+  base::MessageLoop::current()->RunUntilIdle();
+}
+
+void APIUtilTest::TestDeleteFile() {
+  const std::string kFileContent = "test content";
+  const std::string kFileTitle = "test.txt";
+
+  SetUpSyncRootDirectory();
+  SetUpOriginRootDirectory();
+  std::string file_resource_id;
+  std::string file_md5;
+  SetUpFile(kFileContent, kFileTitle, &file_resource_id, &file_md5);
+
+  bool done = false;
+  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
+  std::string resource_id;
+  api_util()->DeleteFile(file_resource_id,
+                         file_md5,
+                         base::Bind(&DidDeleteFile, &done, &error));
+  base::MessageLoop::current()->RunUntilIdle();
+
+  EXPECT_TRUE(done);
+  EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
+
+  fake_drive_service()->SearchByTitle(
+      kFileTitle,
+      GetOriginRootResourceId(),
+      base::Bind(&VerifyFileDeletion, FROM_HERE));
+  base::MessageLoop::current()->RunUntilIdle();
+}
+
+void APIUtilTest::TestDeleteFileInConflict() {
+  const std::string kFileContent = "test content";
+  const std::string kFileTitle = "test.txt";
+
+  SetUpSyncRootDirectory();
+  SetUpOriginRootDirectory();
+  std::string file_resource_id;
+  std::string file_md5;
+  SetUpFile(kFileContent, kFileTitle, &file_resource_id, &file_md5);
+
+  // Since remote file's hash value is different from the expected one, it is
+  // expected to cancel delete the file and to return CONFLICT status code.
+  const std::string kExpectedRemoteFileMD5 = "123456";
+
+  bool done = false;
+  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
+  api_util()->DeleteFile(file_resource_id,
+                         kExpectedRemoteFileMD5,
+                         base::Bind(&DidDeleteFile, &done, &error));
+  base::MessageLoop::current()->RunUntilIdle();
+
+  EXPECT_TRUE(done);
+  EXPECT_EQ(google_apis::HTTP_CONFLICT, error);
+
+  // Verify that the conflict file was not deleted on the remote side.
+  fake_drive_service()->SearchByTitle(
+      kFileTitle,
+      GetOriginRootResourceId(),
+      base::Bind(&VerifyTitleUniqueness,
+                 FROM_HERE,
+                 file_resource_id,
+                 google_apis::ENTRY_KIND_FILE));
+  base::MessageLoop::current()->RunUntilIdle();
+}
+
+void APIUtilTest::TestCreateDirectory() {
+  const std::string kDirectoryTitle("directory");
+
+  SetUpSyncRootDirectory();
+  SetUpOriginRootDirectory();
+
+  bool done = false;
+  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
+  std::string resource_id;
+  api_util()->CreateDirectory(
+      GetOriginRootResourceId(),
+      kDirectoryTitle,
+      base::Bind(&DidGetResourceID, &done, &error, &resource_id));
+  base::MessageLoop::current()->RunUntilIdle();
+
+  EXPECT_TRUE(done);
+  EXPECT_EQ(google_apis::HTTP_CREATED, error);
+  EXPECT_FALSE(resource_id.empty());
+
+  fake_drive_service()->SearchByTitle(
+      kDirectoryTitle,
+      GetOriginRootResourceId(),
+      base::Bind(&VerifyTitleUniqueness,
+                 FROM_HERE,
+                 resource_id,
+                 google_apis::ENTRY_KIND_FOLDER));
+  base::MessageLoop::current()->RunUntilIdle();
+}
+
+TEST_F(APIUtilTest, GetSyncRoot) {
+  ASSERT_FALSE(IsDriveAPIDisabled());
+  TestGetSyncRoot();
+}
+
+TEST_F(APIUtilTest, GetSyncRoot_WAPI) {
+  ScopedDisableDriveAPI disable_drive_api;
+  TestGetSyncRoot();
+}
+
+TEST_F(APIUtilTest, CreateSyncRoot) {
+  ASSERT_FALSE(IsDriveAPIDisabled());
+  TestCreateSyncRoot();
+}
+
+TEST_F(APIUtilTest, CreateSyncRoot_WAPI) {
+  ScopedDisableDriveAPI disable_drive_api;
+  TestCreateSyncRoot();
+}
+
+TEST_F(APIUtilTest, CreateSyncRoot_Conflict) {
+  ASSERT_FALSE(IsDriveAPIDisabled());
+  TestCreateSyncRoot_Conflict();
+}
+
+TEST_F(APIUtilTest, CreateSyncRoot_Conflict_WAPI) {
+  ScopedDisableDriveAPI disable_drive_api;
+  TestCreateSyncRoot_Conflict();
+}
+
+TEST_F(APIUtilTest, GetOriginDirectory) {
+  ASSERT_FALSE(IsDriveAPIDisabled());
+  TestGetOriginDirectory();
+}
+
+TEST_F(APIUtilTest, GetOriginDirectory_WAPI) {
+  ScopedDisableDriveAPI disable_drive_api;
+  TestGetOriginDirectory();
+}
+
+TEST_F(APIUtilTest, CreateOriginDirectory) {
+  ASSERT_FALSE(IsDriveAPIDisabled());
+  TestCreateOriginDirectory();
+}
+
+TEST_F(APIUtilTest, CreateOriginDirectory_WAPI) {
+  ScopedDisableDriveAPI disable_drive_api;
+  TestCreateOriginDirectory();
+}
+
+TEST_F(APIUtilTest, CreateOriginDirectory_Conflict) {
+  ASSERT_FALSE(IsDriveAPIDisabled());
+  TestCreateOriginDirectory_Conflict();
+}
+
+TEST_F(APIUtilTest, CreateOriginDirectory_Conflict_WAPI) {
+  ScopedDisableDriveAPI disable_drive_api;
+  TestCreateOriginDirectory_Conflict();
+}
+
+TEST_F(APIUtilTest, GetLargestChangeStamp) {
+  ASSERT_FALSE(IsDriveAPIDisabled());
+  TestGetLargestChangeStamp();
+}
+
+TEST_F(APIUtilTest, GetLargestChangeStamp_WAPI) {
+  ScopedDisableDriveAPI disable_drive_api;
+  TestGetLargestChangeStamp();
+}
+
+TEST_F(APIUtilTest, ListFiles) {
+  ASSERT_FALSE(IsDriveAPIDisabled());
+  TestListFiles();
+}
+
+TEST_F(APIUtilTest, ListFiles_WAPI) {
+  ScopedDisableDriveAPI disable_drive_api;
+  TestListFiles();
+}
+
+TEST_F(APIUtilTest, ListChanges) {
+  ASSERT_FALSE(IsDriveAPIDisabled());
+  TestListChanges();
+}
+
+TEST_F(APIUtilTest, ListChanges_WAPI) {
+  ScopedDisableDriveAPI disable_drive_api;
+  TestListChanges();
+}
+
+TEST_F(APIUtilTest, DownloadFile) {
+  ASSERT_FALSE(IsDriveAPIDisabled());
+  TestDownloadFile();
+}
+
+TEST_F(APIUtilTest, DownloadFile_WAPI) {
+  ScopedDisableDriveAPI disable_drive_api;
+  TestDownloadFile();
+}
+
+TEST_F(APIUtilTest, DownloadFileInNotModified) {
+  ASSERT_FALSE(IsDriveAPIDisabled());
+  TestDownloadFileInNotModified();
+}
+
+TEST_F(APIUtilTest, DownloadFileInNotModified_WAPI) {
+  ScopedDisableDriveAPI disable_drive_api;
+  TestDownloadFileInNotModified();
+}
+
+TEST_F(APIUtilTest, UploadNewFile) {
+  ASSERT_FALSE(IsDriveAPIDisabled());
+  TestUploadNewFile();
+}
+
+TEST_F(APIUtilTest, UploadNewFile_WAPI) {
+  ScopedDisableDriveAPI disable_drive_api;
+  TestUploadNewFile();
+}
+
+TEST_F(APIUtilTest, UploadNewFile_ConflictWithFile) {
+  ASSERT_FALSE(IsDriveAPIDisabled());
+  TestUploadNewFile_ConflictWithFile();
+}
+
+TEST_F(APIUtilTest, UploadNewFile_ConflictWithFile_WAPI) {
+  ScopedDisableDriveAPI disable_drive_api;
+  TestUploadNewFile_ConflictWithFile();
+}
+
+TEST_F(APIUtilTest, UploadExistingFile) {
+  ASSERT_FALSE(IsDriveAPIDisabled());
+  TestUploadExistingFile();
+}
+
+TEST_F(APIUtilTest, UploadExistingFile_WAPI) {
+  ScopedDisableDriveAPI disable_drive_api;
+  TestUploadExistingFile();
+}
+
+TEST_F(APIUtilTest, UploadExistingFileInConflict) {
+  ASSERT_FALSE(IsDriveAPIDisabled());
+  TestUploadExistingFileInConflict();
+}
+
+TEST_F(APIUtilTest, UploadExistingFileInConflict_WAPI) {
+  ScopedDisableDriveAPI disable_drive_api;
+  TestUploadExistingFileInConflict();
+}
+
+TEST_F(APIUtilTest, DeleteFile) {
+  ASSERT_FALSE(IsDriveAPIDisabled());
+  TestDeleteFile();
+}
+
+TEST_F(APIUtilTest, DeleteFile_WAPI) {
+  ScopedDisableDriveAPI disable_drive_api;
+  TestDeleteFile();
+}
+
+TEST_F(APIUtilTest, DeleteFileInConflict) {
+  ASSERT_FALSE(IsDriveAPIDisabled());
+  TestDeleteFileInConflict();
+}
+
+TEST_F(APIUtilTest, DeleteFileInConflict_WAPI) {
+  ScopedDisableDriveAPI disable_drive_api;
+  TestDeleteFileInConflict();
+}
+
+TEST_F(APIUtilTest, CreateDirectory) {
+  ASSERT_FALSE(IsDriveAPIDisabled());
+  TestCreateDirectory();
+}
+
+TEST_F(APIUtilTest, CreateDirectory_WAPI) {
+  ScopedDisableDriveAPI disable_drive_api;
+  TestCreateDirectory();
+}
+
+#endif  // !defined(OS_ANDROID)
+
+}  // namespace drive_backend
+}  // namespace sync_file_system
diff --git a/chrome/browser/sync_file_system/drive_backend/fake_api_util.cc b/chrome/browser/sync_file_system/drive_backend/fake_api_util.cc
new file mode 100644
index 0000000..c8e01a1
--- /dev/null
+++ b/chrome/browser/sync_file_system/drive_backend/fake_api_util.cc
@@ -0,0 +1,274 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/sync_file_system/drive_backend/fake_api_util.h"
+
+#include <algorithm>
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "chrome/browser/google_apis/drive_entry_kinds.h"
+
+namespace sync_file_system {
+namespace drive_backend {
+
+bool FakeAPIUtil::RemoteResourceComparator::operator()(
+    const RemoteResource& left,
+    const RemoteResource& right) {
+  if (left.parent_resource_id != right.parent_resource_id)
+    return left.parent_resource_id < right.parent_resource_id;
+  if (left.parent_title != right.parent_title)
+    return left.parent_title < right.parent_title;
+  if (left.title != right.title)
+    return left.title < right.title;
+  if (left.resource_id != right.resource_id)
+    return left.resource_id < right.resource_id;
+  if (left.md5_checksum != right.md5_checksum)
+    return left.md5_checksum < right.md5_checksum;
+  if (left.deleted != right.deleted)
+    return left.deleted < right.deleted;
+  return left.changestamp < right.changestamp;
+}
+
+struct FakeAPIUtil::ChangeStampComparator {
+  bool operator()(const google_apis::ResourceEntry* left,
+                  const google_apis::ResourceEntry* right) {
+    return left->changestamp() < right->changestamp();
+  }
+};
+
+FakeAPIUtil::RemoteResource::RemoteResource()
+    : type(SYNC_FILE_TYPE_UNKNOWN), deleted(false), changestamp(0) {}
+
+FakeAPIUtil::RemoteResource::RemoteResource(
+    const std::string& parent_resource_id,
+    const std::string& parent_title,
+    const std::string& title,
+    const std::string& resource_id,
+    const std::string& md5_checksum,
+    SyncFileType type,
+    bool deleted,
+    int64 changestamp)
+    : parent_resource_id(parent_resource_id),
+      parent_title(parent_title),
+      title(title),
+      resource_id(resource_id),
+      md5_checksum(md5_checksum),
+      type(type),
+      deleted(deleted),
+      changestamp(changestamp) {}
+
+FakeAPIUtil::RemoteResource::~RemoteResource() {}
+
+FakeAPIUtil::FakeAPIUtil()
+    : largest_changestamp_(0),
+      url_generator_(
+          GURL(google_apis::GDataWapiUrlGenerator::kBaseUrlForProduction),
+          GURL(google_apis::GDataWapiUrlGenerator::
+               kBaseDownloadUrlForProduction)) {}
+
+FakeAPIUtil::~FakeAPIUtil() {}
+
+void FakeAPIUtil::AddObserver(APIUtilObserver* observer) {}
+
+void FakeAPIUtil::RemoveObserver(APIUtilObserver* observer) {}
+
+void FakeAPIUtil::GetDriveDirectoryForSyncRoot(
+    const ResourceIdCallback& callback) {
+  base::MessageLoopProxy::current()->PostTask(
+      FROM_HERE,
+      base::Bind(callback,
+                 google_apis::HTTP_SUCCESS,
+                 "folder: sync_root_resource_id"));
+}
+
+void FakeAPIUtil::GetDriveDirectoryForOrigin(
+    const std::string& sync_root_resource_id,
+    const GURL& origin,
+    const ResourceIdCallback& callback) {
+  base::MessageLoopProxy::current()->PostTask(
+      FROM_HERE,
+      base::Bind(callback,
+                 google_apis::HTTP_SUCCESS,
+                 "folder resource_id for " + origin.host()));
+}
+
+void FakeAPIUtil::GetLargestChangeStamp(const ChangeStampCallback& callback) {
+  base::MessageLoopProxy::current()->PostTask(
+      FROM_HERE,
+      base::Bind(callback, google_apis::HTTP_SUCCESS, largest_changestamp_));
+}
+
+void FakeAPIUtil::GetResourceEntry(const std::string& resource_id,
+                                   const ResourceEntryCallback& callback) {
+  NOTREACHED();
+}
+
+void FakeAPIUtil::ListFiles(const std::string& directory_resource_id,
+                            const ResourceListCallback& callback) {
+  ListChanges(0, callback);
+}
+
+void FakeAPIUtil::ListChanges(int64 start_changestamp,
+                              const ResourceListCallback& callback) {
+  scoped_ptr<google_apis::ResourceList> change_feed(
+      new google_apis::ResourceList());
+
+  ScopedVector<google_apis::ResourceEntry> entries;
+  typedef RemoteResourceByResourceId::const_iterator iterator;
+  for (iterator itr = remote_resources_.begin();
+       itr != remote_resources_.end(); ++itr) {
+    if (itr->second.changestamp < start_changestamp)
+      continue;
+    scoped_ptr<google_apis::ResourceEntry> entry(
+        CreateResourceEntry(itr->second));
+    entries.push_back(entry.release());
+  }
+
+  std::sort(entries.begin(), entries.end(), ChangeStampComparator());
+
+  change_feed->set_entries(&entries);
+  change_feed->set_largest_changestamp(largest_changestamp_);
+
+  base::MessageLoopProxy::current()->PostTask(
+      FROM_HERE,
+      base::Bind(
+          callback, google_apis::HTTP_SUCCESS, base::Passed(&change_feed)));
+}
+
+void FakeAPIUtil::ContinueListing(const GURL& feed_url,
+                                  const ResourceListCallback& callback) {
+  NOTREACHED();
+}
+
+void FakeAPIUtil::DownloadFile(const std::string& resource_id,
+                               const std::string& local_file_md5,
+                               const base::FilePath& local_file_path,
+                               const DownloadFileCallback& callback) {
+  RemoteResourceByResourceId::iterator found =
+      remote_resources_.find(resource_id);
+  std::string file_md5;
+  int64 file_size = 0;
+  base::Time updated_time;
+  google_apis::GDataErrorCode error = google_apis::HTTP_NOT_FOUND;
+
+  if (found != remote_resources_.end() && !found->second.deleted) {
+    scoped_ptr<google_apis::ResourceEntry> entry(
+        CreateResourceEntry(found->second));
+    file_md5 = entry->file_md5();
+    file_size = entry->file_size();
+    updated_time = entry->updated_time();
+    error = google_apis::HTTP_SUCCESS;
+  }
+
+  base::MessageLoopProxy::current()->PostTask(
+      FROM_HERE,
+      base::Bind(callback, error, file_md5, file_size, updated_time));
+}
+
+void FakeAPIUtil::UploadNewFile(const std::string& directory_resource_id,
+                                const base::FilePath& local_file_path,
+                                const std::string& title,
+                                const UploadFileCallback& callback) {
+  NOTREACHED();
+}
+
+void FakeAPIUtil::UploadExistingFile(const std::string& resource_id,
+                                     const std::string& remote_file_md5,
+                                     const base::FilePath& local_file_path,
+                                     const UploadFileCallback& callback) {
+  NOTREACHED();
+}
+
+void FakeAPIUtil::CreateDirectory(const std::string& parent_resource_id,
+                                  const std::string& title,
+                                  const ResourceIdCallback& callback) {
+  NOTREACHED();
+}
+
+bool FakeAPIUtil::IsAuthenticated() const { return true; }
+
+void FakeAPIUtil::DeleteFile(const std::string& resource_id,
+                             const std::string& remote_file_md5,
+                             const GDataErrorCallback& callback) {
+  if (!ContainsKey(remote_resources_, resource_id)) {
+    base::MessageLoopProxy::current()->PostTask(
+        FROM_HERE,
+        base::Bind(callback, google_apis::HTTP_NOT_FOUND));
+    return;
+  }
+
+  const RemoteResource& deleted_directory = remote_resources_[resource_id];
+  PushRemoteChange(deleted_directory.parent_resource_id,
+                   deleted_directory.parent_title,
+                   deleted_directory.title,
+                   deleted_directory.resource_id,
+                   deleted_directory.md5_checksum,
+                   SYNC_FILE_TYPE_UNKNOWN,
+                   true /* deleted */);
+
+  base::MessageLoopProxy::current()->PostTask(
+      FROM_HERE,
+      base::Bind(callback, google_apis::HTTP_SUCCESS));
+}
+
+GURL FakeAPIUtil::ResourceIdToResourceLink(
+    const std::string& resource_id) const {
+  return url_generator_.GenerateEditUrl(resource_id);
+}
+
+void FakeAPIUtil::EnsureSyncRootIsNotInMyDrive(
+    const std::string& sync_root_resource_id) {
+  // Nothing to do.
+}
+
+void FakeAPIUtil::PushRemoteChange(const std::string& parent_resource_id,
+                                   const std::string& parent_title,
+                                   const std::string& title,
+                                   const std::string& resource_id,
+                                   const std::string& md5,
+                                   SyncFileType type,
+                                   bool deleted) {
+  remote_resources_[resource_id] = RemoteResource(
+      parent_resource_id, parent_title, title, resource_id,
+      md5, type, deleted, ++largest_changestamp_);
+}
+
+scoped_ptr<google_apis::ResourceEntry> FakeAPIUtil::CreateResourceEntry(
+    const RemoteResource& resource) const {
+  scoped_ptr<google_apis::ResourceEntry> entry(
+      new google_apis::ResourceEntry());
+  ScopedVector<google_apis::Link> parent_links;
+  scoped_ptr<google_apis::Link> link(new google_apis::Link());
+
+  link->set_type(google_apis::Link::LINK_PARENT);
+  link->set_href(ResourceIdToResourceLink(resource.parent_resource_id));
+  link->set_title(resource.parent_title);
+  parent_links.push_back(link.release());
+
+  entry->set_links(&parent_links);
+  entry->set_title(resource.title);
+  entry->set_resource_id(resource.resource_id);
+  entry->set_file_md5(resource.md5_checksum);
+  entry->set_deleted(resource.deleted);
+  entry->set_changestamp(resource.changestamp);
+
+  switch (resource.type) {
+    case SYNC_FILE_TYPE_FILE:
+      entry->set_kind(google_apis::ENTRY_KIND_FILE);
+      break;
+    case SYNC_FILE_TYPE_DIRECTORY:
+      entry->set_kind(google_apis::ENTRY_KIND_FOLDER);
+      break;
+    case SYNC_FILE_TYPE_UNKNOWN:
+      entry->set_kind(google_apis::ENTRY_KIND_UNKNOWN);
+      break;
+  }
+
+  return entry.Pass();
+}
+
+}  // namespace drive_backend
+}  // namespace sync_file_system
diff --git a/chrome/browser/sync_file_system/drive_backend/fake_api_util.h b/chrome/browser/sync_file_system/drive_backend/fake_api_util.h
new file mode 100644
index 0000000..52c201e
--- /dev/null
+++ b/chrome/browser/sync_file_system/drive_backend/fake_api_util.h
@@ -0,0 +1,132 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_FAKE_API_UTIL_H_
+#define CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_FAKE_API_UTIL_H_
+
+#include <map>
+#include <string>
+
+#include "chrome/browser/google_apis/drive_api_parser.h"
+#include "chrome/browser/google_apis/gdata_wapi_parser.h"
+#include "chrome/browser/google_apis/gdata_wapi_url_generator.h"
+#include "chrome/browser/sync_file_system/drive_backend/api_util_interface.h"
+#include "webkit/browser/fileapi/syncable/sync_file_type.h"
+
+class GURL;
+class Profile;
+
+namespace google_apis {
+class ResourceEntry;
+}
+
+namespace sync_file_system {
+namespace drive_backend {
+
+class FakeAPIUtil : public APIUtilInterface {
+ public:
+  struct RemoteResource {
+    std::string parent_resource_id;
+    std::string parent_title;
+    std::string title;
+    std::string resource_id;
+    std::string md5_checksum;
+    SyncFileType type;
+    bool deleted;
+    int64 changestamp;
+
+    RemoteResource();
+    RemoteResource(const std::string& parent_resource_id,
+                   const std::string& parent_title,
+                   const std::string& title,
+                   const std::string& resource_id,
+                   const std::string& md5_checksum,
+                   SyncFileType type,
+                   bool deleted,
+                   int64 changestamp);
+    ~RemoteResource();
+  };
+
+  struct RemoteResourceComparator {
+    // Returns lexicographical order referring all members.
+    bool operator()(const RemoteResource& left, const RemoteResource& right);
+  };
+
+  typedef std::map<std::string, RemoteResource> RemoteResourceByResourceId;
+
+  FakeAPIUtil();
+  virtual ~FakeAPIUtil();
+
+  // APIUtilInterface overrides.
+  virtual void AddObserver(APIUtilObserver* observer) OVERRIDE;
+  virtual void RemoveObserver(APIUtilObserver* observer) OVERRIDE;
+  virtual void GetDriveDirectoryForSyncRoot(
+      const ResourceIdCallback& callback) OVERRIDE;
+  virtual void GetDriveDirectoryForOrigin(
+      const std::string& sync_root_resource_id,
+      const GURL& origin,
+      const ResourceIdCallback& callback) OVERRIDE;
+  virtual void GetLargestChangeStamp(
+      const ChangeStampCallback& callback) OVERRIDE;
+  virtual void GetResourceEntry(const std::string& resource_id,
+                                const ResourceEntryCallback& callback) OVERRIDE;
+  virtual void ListFiles(const std::string& directory_resource_id,
+                         const ResourceListCallback& callback) OVERRIDE;
+  virtual void ListChanges(int64 start_changestamp,
+                           const ResourceListCallback& callback) OVERRIDE;
+  virtual void ContinueListing(const GURL& feed_url,
+                               const ResourceListCallback& callback) OVERRIDE;
+  virtual void DownloadFile(const std::string& resource_id,
+                            const std::string& local_file_md5,
+                            const base::FilePath& local_file_path,
+                            const DownloadFileCallback& callback) OVERRIDE;
+  virtual void UploadNewFile(const std::string& directory_resource_id,
+                             const base::FilePath& local_file_path,
+                             const std::string& title,
+                             const UploadFileCallback& callback) OVERRIDE;
+  virtual void UploadExistingFile(const std::string& resource_id,
+                                  const std::string& remote_file_md5,
+                                  const base::FilePath& local_file_path,
+                                  const UploadFileCallback& callback) OVERRIDE;
+  virtual void CreateDirectory(const std::string& parent_resource_id,
+                               const std::string& title,
+                               const ResourceIdCallback& callback) OVERRIDE;
+  virtual bool IsAuthenticated() const OVERRIDE;
+  virtual void DeleteFile(const std::string& resource_id,
+                          const std::string& remote_file_md5,
+                          const GDataErrorCallback& callback) OVERRIDE;
+  virtual GURL ResourceIdToResourceLink(
+      const std::string& resource_id) const OVERRIDE;
+  virtual void EnsureSyncRootIsNotInMyDrive(
+      const std::string& sync_root_resource_id) OVERRIDE;
+
+  void PushRemoteChange(const std::string& parent_resource_id,
+                        const std::string& parent_title,
+                        const std::string& title,
+                        const std::string& resource_id,
+                        const std::string& md5,
+                        SyncFileType type,
+                        bool deleted);
+
+  const RemoteResourceByResourceId& remote_resources() const {
+    return remote_resources_;
+  }
+
+ private:
+  struct ChangeStampComparator;
+  RemoteResourceByResourceId remote_resources_;
+
+  scoped_ptr<google_apis::ResourceEntry> CreateResourceEntry(
+      const RemoteResource& resource_id) const;
+
+  int64 largest_changestamp_;
+  google_apis::GDataWapiUrlGenerator url_generator_;
+
+  DISALLOW_COPY_AND_ASSIGN(FakeAPIUtil);
+};
+
+}  // namespace drive_backend
+}  // namespace sync_file_system
+
+#endif  // CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_FAKE_API_UTIL_H_
diff --git a/chrome/browser/sync_file_system/drive_backend/fake_api_util_unittest.cc b/chrome/browser/sync_file_system/drive_backend/fake_api_util_unittest.cc
new file mode 100644
index 0000000..641505f
--- /dev/null
+++ b/chrome/browser/sync_file_system/drive_backend/fake_api_util_unittest.cc
@@ -0,0 +1,141 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/sync_file_system/drive_backend/fake_api_util.h"
+
+#include <string>
+
+#include "base/bind.h"
+#include "base/files/file_path.h"
+#include "base/message_loop.h"
+#include "chrome/browser/google_apis/gdata_errorcode.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace sync_file_system {
+namespace drive_backend {
+
+namespace {
+
+void DidDownloadFile(google_apis::GDataErrorCode* error_out,
+                     std::string* file_md5_out,
+                     google_apis::GDataErrorCode error,
+                     const std::string& file_md5,
+                     int64 file_size,
+                     const base::Time& updated_time) {
+  *error_out = error;
+  *file_md5_out = file_md5;
+}
+
+void DidGetChangeList(google_apis::GDataErrorCode* error_out,
+                      scoped_ptr<google_apis::ResourceList>* change_list_out,
+                      google_apis::GDataErrorCode error,
+                      scoped_ptr<google_apis::ResourceList> change_list) {
+  *error_out = error;
+  *change_list_out = change_list.Pass();
+}
+
+void DidDeleteFile(google_apis::GDataErrorCode* error_out,
+                   google_apis::GDataErrorCode error) {
+  *error_out = error;
+}
+
+}  // namespace
+
+TEST(FakeAPIUtilTest, ChangeSquashTest) {
+  base::MessageLoop message_loop;
+  FakeAPIUtil api_util;
+  std::string kParentResourceId("parent resource id");
+  std::string kParentTitle("app-id");
+  std::string kTitle1("title 1");
+  std::string kTitle2("title 2");
+  std::string kTitle3("title 3");
+  std::string kResourceId1("resource id 1");
+  std::string kResourceId2("resource id 2");
+  std::string kMD5_1("md5 1");
+  std::string kMD5_2("md5 2");
+  std::string kMD5_3("md5 3");
+  base::FilePath kTempFilePath(FILE_PATH_LITERAL("tmp_file"));
+
+  api_util.PushRemoteChange(kParentResourceId,
+                            kParentTitle,
+                            kTitle1,
+                            kResourceId1,
+                            kMD5_1,
+                            SYNC_FILE_TYPE_FILE,
+                            false /* deleted */);
+  api_util.PushRemoteChange(kParentResourceId,
+                            kParentTitle,
+                            kTitle1,
+                            kResourceId1,
+                            kMD5_1,
+                            SYNC_FILE_TYPE_FILE,
+                            false /* deleted */);
+  api_util.PushRemoteChange(kParentResourceId,
+                            kParentTitle,
+                            kTitle1,
+                            kResourceId1,
+                            kMD5_1,
+                            SYNC_FILE_TYPE_FILE,
+                            true /* deleted */);
+  api_util.PushRemoteChange(kParentResourceId,
+                            kParentTitle,
+                            kTitle2,
+                            kResourceId2,
+                            kMD5_2,
+                            SYNC_FILE_TYPE_FILE,
+                            false /* deleted */);
+  api_util.PushRemoteChange(kParentResourceId,
+                            kParentTitle,
+                            kTitle3,
+                            kResourceId2,
+                            kMD5_3,
+                            SYNC_FILE_TYPE_FILE,
+                            false /* deleted */);
+
+  google_apis::GDataErrorCode error;
+  std::string md5;
+  api_util.DownloadFile(kResourceId1,
+                        kMD5_1,
+                        kTempFilePath,
+                        base::Bind(DidDownloadFile, &error, &md5));
+  message_loop.RunUntilIdle();
+  EXPECT_EQ(google_apis::HTTP_NOT_FOUND, error);
+  EXPECT_TRUE(md5.empty());
+
+  scoped_ptr<google_apis::ResourceList> change_list;
+  api_util.ListChanges(0, base::Bind(&DidGetChangeList, &error, &change_list));
+  message_loop.RunUntilIdle();
+  EXPECT_EQ(2u, change_list->entries().size());
+
+  EXPECT_EQ(kResourceId1, change_list->entries()[0]->resource_id());
+  EXPECT_TRUE(change_list->entries()[0]->deleted());
+
+  EXPECT_EQ(kResourceId2, change_list->entries()[1]->resource_id());
+  EXPECT_EQ(kMD5_3, change_list->entries()[1]->file_md5());
+  EXPECT_FALSE(change_list->entries()[1]->deleted());
+}
+
+TEST(FakeAPIUtilTest, DeleteFile) {
+  base::MessageLoop message_loop;
+  FakeAPIUtil api_util;
+  std::string resource_id = "resource_id_to_be_deleted";
+  api_util.PushRemoteChange("parent_id",
+                            "parent_title",
+                            "resource_title",
+                            resource_id,
+                            "resource_md5",
+                            SYNC_FILE_TYPE_FILE,
+                            false /* deleted */);
+
+  google_apis::GDataErrorCode error = google_apis::HTTP_NOT_FOUND;
+  api_util.DeleteFile(
+      resource_id, std::string(), base::Bind(&DidDeleteFile, &error));
+  message_loop.RunUntilIdle();
+
+  EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
+  EXPECT_TRUE(api_util.remote_resources().find(resource_id)->second.deleted);
+}
+
+}  // namespace drive_backend
+}  // namespace sync_file_system
diff --git a/chrome/browser/sync_file_system/drive_backend/fake_drive_service_helper.cc b/chrome/browser/sync_file_system/drive_backend/fake_drive_service_helper.cc
new file mode 100644
index 0000000..89924b9
--- /dev/null
+++ b/chrome/browser/sync_file_system/drive_backend/fake_drive_service_helper.cc
@@ -0,0 +1,313 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/sync_file_system/drive_backend/fake_drive_service_helper.h"
+
+#include "base/bind.h"
+#include "base/file_util.h"
+#include "base/message_loop.h"
+#include "base/threading/sequenced_worker_pool.h"
+#include "chrome/browser/sync_file_system/drive_backend/api_util.h"
+#include "content/public/test/test_browser_thread.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/browser/fileapi/file_system_url.h"
+#include "webkit/browser/fileapi/syncable/sync_status_code.h"
+
+#define FPL(path) FILE_PATH_LITERAL(path)
+
+using google_apis::GDataErrorCode;
+using google_apis::ResourceEntry;
+using google_apis::ResourceList;
+
+namespace sync_file_system {
+namespace drive_backend {
+
+namespace {
+
+void ResourceEntryResultCallback(GDataErrorCode* error_out,
+                                 scoped_ptr<ResourceEntry>* entry_out,
+                                 GDataErrorCode error,
+                                 scoped_ptr<ResourceEntry> entry) {
+  ASSERT_TRUE(error_out);
+  ASSERT_TRUE(entry_out);
+  *error_out = error;
+  *entry_out = entry.Pass();
+}
+
+void UploadResultCallback(GDataErrorCode* error_out,
+                          scoped_ptr<ResourceEntry>* entry_out,
+                          GDataErrorCode error,
+                          const GURL& upload_location,
+                          scoped_ptr<ResourceEntry> entry) {
+  ASSERT_TRUE(error_out);
+  ASSERT_TRUE(entry_out);
+  *error_out = error;
+  *entry_out = entry.Pass();
+}
+
+void ResourceListResultCallback(GDataErrorCode* error_out,
+                                scoped_ptr<ResourceList>* list_out,
+                                GDataErrorCode error,
+                                scoped_ptr<ResourceList> list) {
+  ASSERT_TRUE(error_out);
+  ASSERT_TRUE(list_out);
+  *error_out = error;
+  *list_out = list.Pass();
+}
+
+void GDataErrorResultCallback(GDataErrorCode* error_out,
+                              GDataErrorCode error) {
+  ASSERT_TRUE(error_out);
+  *error_out = error;
+}
+
+void DownloadResultCallback(GDataErrorCode* error_out,
+                            GDataErrorCode error,
+                            const base::FilePath& local_file) {
+  ASSERT_TRUE(error_out);
+  *error_out = error;
+}
+
+}  // namespace
+
+FakeDriveServiceHelper::FakeDriveServiceHelper(
+    drive::FakeDriveService* fake_drive_service,
+    drive::DriveUploaderInterface* drive_uploader)
+    : fake_drive_service_(fake_drive_service),
+      drive_uploader_(drive_uploader) {
+  Initialize();
+}
+
+FakeDriveServiceHelper::~FakeDriveServiceHelper() {
+}
+
+GDataErrorCode FakeDriveServiceHelper::AddOrphanedFolder(
+    const std::string& title,
+    std::string* folder_id) {
+  EXPECT_TRUE(folder_id);
+
+  std::string root_folder_id = fake_drive_service_->GetRootResourceId();
+  GDataErrorCode error = AddFolder(root_folder_id, title, folder_id);
+  if (error != google_apis::HTTP_CREATED)
+    return error;
+
+  error = google_apis::GDATA_OTHER_ERROR;
+  fake_drive_service_->RemoveResourceFromDirectory(
+      root_folder_id, *folder_id,
+      base::Bind(&GDataErrorResultCallback, &error));
+  FlushMessageLoop();
+
+  if (error != google_apis::HTTP_SUCCESS)
+    return error;
+  return google_apis::HTTP_CREATED;
+}
+
+GDataErrorCode FakeDriveServiceHelper::AddFolder(
+    const std::string& parent_folder_id,
+    const std::string& title,
+    std::string* folder_id) {
+  EXPECT_TRUE(folder_id);
+
+  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
+  scoped_ptr<ResourceEntry> folder;
+  fake_drive_service_->AddNewDirectory(
+      parent_folder_id, title,
+      base::Bind(&ResourceEntryResultCallback, &error, &folder));
+  FlushMessageLoop();
+
+  if (error == google_apis::HTTP_CREATED)
+    *folder_id = folder->resource_id();
+  return error;
+}
+
+GDataErrorCode FakeDriveServiceHelper::AddFile(
+    const std::string& parent_folder_id,
+    const std::string& title,
+    const std::string& content,
+    std::string* file_id) {
+  EXPECT_TRUE(file_id);
+  base::FilePath temp_file = WriteToTempFile(content);
+
+  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
+  scoped_ptr<ResourceEntry> file;
+  drive_uploader_->UploadNewFile(
+      parent_folder_id, temp_file, title,
+      "application/octet-stream",
+      base::Bind(&UploadResultCallback, &error, &file),
+      google_apis::ProgressCallback());
+  FlushMessageLoop();
+
+  if (error == google_apis::HTTP_SUCCESS)
+    *file_id = file->resource_id();
+  return error;
+}
+
+GDataErrorCode FakeDriveServiceHelper::UpdateFile(
+    const std::string& file_id,
+    const std::string& content) {
+  base::FilePath temp_file = WriteToTempFile(content);
+  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
+  scoped_ptr<ResourceEntry> file;
+  drive_uploader_->UploadExistingFile(
+      file_id, temp_file,
+      "application/octet-stream",
+      std::string(),  // etag
+      base::Bind(&UploadResultCallback, &error, &file),
+      google_apis::ProgressCallback());
+  FlushMessageLoop();
+  return error;
+}
+
+GDataErrorCode FakeDriveServiceHelper::RemoveResource(
+    const std::string& file_id) {
+  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
+  fake_drive_service_->DeleteResource(
+      file_id,
+      std::string(), // etag
+      base::Bind(&GDataErrorResultCallback, &error));
+  FlushMessageLoop();
+  return error;
+}
+
+GDataErrorCode FakeDriveServiceHelper::GetSyncRootFolderID(
+    std::string* sync_root_folder_id) {
+  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
+  scoped_ptr<ResourceList> resource_list;
+  fake_drive_service_->SearchByTitle(
+      APIUtil::GetSyncRootDirectoryName(), std::string(),
+      base::Bind(&ResourceListResultCallback, &error, &resource_list));
+  FlushMessageLoop();
+  if (error != google_apis::HTTP_SUCCESS)
+    return error;
+
+  const ScopedVector<ResourceEntry>& entries = resource_list->entries();
+  for (ScopedVector<ResourceEntry>::const_iterator itr = entries.begin();
+       itr != entries.end(); ++itr) {
+    const ResourceEntry& entry = **itr;
+    if (!entry.GetLinkByType(google_apis::Link::LINK_PARENT)) {
+      *sync_root_folder_id = entry.resource_id();
+      return google_apis::HTTP_SUCCESS;
+    }
+  }
+  return google_apis::HTTP_NOT_FOUND;
+}
+
+GDataErrorCode FakeDriveServiceHelper::ListFilesInFolder(
+    const std::string& folder_id,
+    ScopedVector<ResourceEntry>* entries) {
+  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
+  scoped_ptr<ResourceList> list;
+  fake_drive_service_->GetResourceListInDirectory(
+      folder_id,
+      base::Bind(&ResourceListResultCallback, &error, &list));
+  FlushMessageLoop();
+  if (error != google_apis::HTTP_SUCCESS)
+    return error;
+
+  return CompleteListing(list.Pass(), entries);
+}
+
+GDataErrorCode FakeDriveServiceHelper::SearchByTitle(
+    const std::string& folder_id,
+    const std::string& title,
+    ScopedVector<ResourceEntry>* entries) {
+  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
+  scoped_ptr<ResourceList> list;
+  fake_drive_service_->SearchByTitle(
+      title, folder_id,
+      base::Bind(&ResourceListResultCallback, &error, &list));
+  FlushMessageLoop();
+  if (error != google_apis::HTTP_SUCCESS)
+    return error;
+
+  return CompleteListing(list.Pass(), entries);
+}
+
+GDataErrorCode FakeDriveServiceHelper::GetResourceEntry(
+    const std::string& file_id,
+    scoped_ptr<ResourceEntry>* entry) {
+  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
+  fake_drive_service_->GetResourceEntry(
+      file_id,
+      base::Bind(&ResourceEntryResultCallback, &error, entry));
+  FlushMessageLoop();
+  return error;
+}
+
+GDataErrorCode FakeDriveServiceHelper::ReadFile(
+    const std::string& file_id,
+    std::string* file_content) {
+  scoped_ptr<google_apis::ResourceEntry> file;
+  GDataErrorCode error = GetResourceEntry(file_id, &file);
+  if (error != google_apis::HTTP_SUCCESS)
+    return error;
+  if (!file)
+    return google_apis::GDATA_PARSE_ERROR;
+
+  error = google_apis::GDATA_OTHER_ERROR;
+  base::FilePath temp_file;
+  EXPECT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir_, &temp_file));
+  fake_drive_service_->DownloadFile(
+      temp_file, file->resource_id(),
+      base::Bind(&DownloadResultCallback, &error),
+      google_apis::GetContentCallback(),
+      google_apis::ProgressCallback());
+  FlushMessageLoop();
+  if (error != google_apis::HTTP_SUCCESS)
+    return error;
+
+  return file_util::ReadFileToString(temp_file, file_content)
+      ? google_apis::HTTP_SUCCESS : google_apis::GDATA_FILE_ERROR;
+}
+
+GDataErrorCode FakeDriveServiceHelper::CompleteListing(
+    scoped_ptr<ResourceList> list,
+    ScopedVector<ResourceEntry>* entries) {
+  while (true) {
+    entries->reserve(entries->size() + list->entries().size());
+    for (ScopedVector<ResourceEntry>::iterator itr =
+         list->mutable_entries()->begin();
+         itr != list->mutable_entries()->end(); ++itr) {
+      entries->push_back(*itr);
+      *itr = NULL;
+    }
+
+    GURL next_feed;
+    if (!list->GetNextFeedURL(&next_feed))
+      return google_apis::HTTP_SUCCESS;
+
+    GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
+    list.reset();
+    fake_drive_service_->ContinueGetResourceList(
+        next_feed,
+        base::Bind(&ResourceListResultCallback, &error, &list));
+    FlushMessageLoop();
+    if (error != google_apis::HTTP_SUCCESS)
+      return error;
+  }
+}
+
+void FakeDriveServiceHelper::Initialize() {
+  ASSERT_TRUE(base_dir_.CreateUniqueTempDir());
+  temp_dir_ = base_dir_.path().Append(FPL("tmp"));
+  ASSERT_TRUE(file_util::CreateDirectory(temp_dir_));
+}
+
+base::FilePath FakeDriveServiceHelper::WriteToTempFile(
+    const std::string& content) {
+  base::FilePath temp_file;
+  EXPECT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir_, &temp_file));
+  EXPECT_EQ(static_cast<int>(content.size()),
+            file_util::WriteFile(temp_file, content.data(), content.size()));
+  return temp_file;
+}
+
+void FakeDriveServiceHelper::FlushMessageLoop() {
+  base::MessageLoop::current()->RunUntilIdle();
+  content::BrowserThread::GetBlockingPool()->FlushForTesting();
+  base::MessageLoop::current()->RunUntilIdle();
+}
+
+}  // namespace drive_backend
+}  // namespace sync_file_system
diff --git a/chrome/browser/sync_file_system/drive_backend/fake_drive_service_helper.h b/chrome/browser/sync_file_system/drive_backend/fake_drive_service_helper.h
new file mode 100644
index 0000000..6e1b6c0
--- /dev/null
+++ b/chrome/browser/sync_file_system/drive_backend/fake_drive_service_helper.h
@@ -0,0 +1,84 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_FAKE_DRIVE_SERVICE_HELPER_H_
+#define CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_FAKE_DRIVE_SERVICE_HELPER_H_
+
+#include <string>
+
+#include "base/files/scoped_temp_dir.h"
+#include "chrome/browser/drive/drive_uploader.h"
+#include "chrome/browser/drive/fake_drive_service.h"
+#include "chrome/browser/google_apis/gdata_wapi_parser.h"
+
+namespace base {
+class FilePath;
+}
+
+namespace sync_file_system {
+namespace drive_backend {
+
+class FakeDriveServiceHelper {
+ public:
+  FakeDriveServiceHelper(drive::FakeDriveService* fake_drive_service,
+                         drive::DriveUploaderInterface* drive_uploader);
+  virtual ~FakeDriveServiceHelper();
+
+  google_apis::GDataErrorCode AddOrphanedFolder(
+      const std::string& title,
+      std::string* folder_id);
+  google_apis::GDataErrorCode AddFolder(
+      const std::string& parent_folder_id,
+      const std::string& title,
+      std::string* folder_id);
+  google_apis::GDataErrorCode AddFile(
+      const std::string& parent_folder_id,
+      const std::string& title,
+      const std::string& content,
+      std::string* file_id);
+  google_apis::GDataErrorCode UpdateFile(
+      const std::string& file_id,
+      const std::string& content);
+  google_apis::GDataErrorCode RemoveResource(
+      const std::string& file_id);
+  google_apis::GDataErrorCode GetSyncRootFolderID(
+      std::string* sync_root_folder_id);
+  google_apis::GDataErrorCode ListFilesInFolder(
+      const std::string& folder_id,
+      ScopedVector<google_apis::ResourceEntry>* entries);
+  google_apis::GDataErrorCode SearchByTitle(
+      const std::string& folder_id,
+      const std::string& title,
+      ScopedVector<google_apis::ResourceEntry>* entries);
+  google_apis::GDataErrorCode GetResourceEntry(
+      const std::string& file_id,
+      scoped_ptr<google_apis::ResourceEntry>* entry);
+  google_apis::GDataErrorCode ReadFile(
+      const std::string& file_id,
+      std::string* file_content);
+
+  base::FilePath base_dir_path() { return base_dir_.path(); }
+
+ private:
+  google_apis::GDataErrorCode CompleteListing(
+      scoped_ptr<google_apis::ResourceList> list,
+      ScopedVector<google_apis::ResourceEntry> * entries);
+
+  void Initialize();
+
+  base::FilePath WriteToTempFile(const std::string& content);
+  void FlushMessageLoop();
+
+  base::ScopedTempDir base_dir_;
+  base::FilePath temp_dir_;
+
+  // Not own.
+  drive::FakeDriveService* fake_drive_service_;
+  drive::DriveUploaderInterface* drive_uploader_;
+};
+
+}  // namespace drive_backend
+}  // namespace sync_file_system
+
+#endif  // CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_FAKE_DRIVE_SERVICE_HELPER_H_
diff --git a/chrome/browser/sync_file_system/drive_backend/local_sync_delegate.cc b/chrome/browser/sync_file_system/drive_backend/local_sync_delegate.cc
new file mode 100644
index 0000000..b85adcd
--- /dev/null
+++ b/chrome/browser/sync_file_system/drive_backend/local_sync_delegate.cc
@@ -0,0 +1,604 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/sync_file_system/drive_backend/local_sync_delegate.h"
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "chrome/browser/sync_file_system/conflict_resolution_resolver.h"
+#include "chrome/browser/sync_file_system/drive_backend/api_util.h"
+#include "chrome/browser/sync_file_system/drive_file_sync_service.h"
+#include "chrome/browser/sync_file_system/drive_metadata_store.h"
+#include "chrome/browser/sync_file_system/logger.h"
+#include "webkit/browser/fileapi/syncable/syncable_file_system_util.h"
+
+namespace sync_file_system {
+namespace drive_backend {
+
+LocalSyncDelegate::LocalSyncDelegate(
+    DriveFileSyncService* sync_service,
+    const FileChange& local_change,
+    const base::FilePath& local_path,
+    const SyncFileMetadata& local_metadata,
+    const fileapi::FileSystemURL& url)
+    : sync_service_(sync_service),
+      operation_(SYNC_OPERATION_NONE),
+      url_(url),
+      local_change_(local_change),
+      local_path_(local_path),
+      local_metadata_(local_metadata),
+      has_drive_metadata_(false),
+      has_remote_change_(false),
+      weak_factory_(this) {}
+
+LocalSyncDelegate::~LocalSyncDelegate() {}
+
+void LocalSyncDelegate::Run(const SyncStatusCallback& callback) {
+  // TODO(nhiroki): support directory operations (http://crbug.com/161442).
+  DCHECK(IsSyncFSDirectoryOperationEnabled() || !local_change_.IsDirectory());
+  operation_ = SYNC_OPERATION_NONE;
+
+  has_drive_metadata_ =
+      metadata_store()->ReadEntry(url_, &drive_metadata_) == SYNC_STATUS_OK;
+
+  if (!has_drive_metadata_)
+    drive_metadata_.set_md5_checksum(std::string());
+
+  sync_service_->EnsureOriginRootDirectory(
+      url_.origin(),
+      base::Bind(&LocalSyncDelegate::DidGetOriginRoot,
+                 weak_factory_.GetWeakPtr(),
+                 callback));
+}
+
+void LocalSyncDelegate::DidGetOriginRoot(
+    const SyncStatusCallback& callback,
+    SyncStatusCode status,
+    const std::string& origin_resource_id) {
+  if (status != SYNC_STATUS_OK) {
+    callback.Run(status);
+    return;
+  }
+
+  origin_resource_id_ = origin_resource_id;
+
+  has_remote_change_ =
+      remote_change_handler()->GetChangeForURL(url_, &remote_change_);
+  if (has_remote_change_ && drive_metadata_.resource_id().empty())
+    drive_metadata_.set_resource_id(remote_change_.resource_id);
+
+  SyncFileType remote_file_type =
+      has_remote_change_ ? remote_change_.change.file_type() :
+      has_drive_metadata_ ?
+          DriveFileSyncService::DriveMetadataResourceTypeToSyncFileType(
+              drive_metadata_.type())
+      : SYNC_FILE_TYPE_UNKNOWN;
+
+  DCHECK_EQ(SYNC_OPERATION_NONE, operation_);
+  operation_ = LocalSyncOperationResolver::Resolve(
+      local_change_,
+      has_remote_change_ ? &remote_change_.change : NULL,
+      has_drive_metadata_ ? &drive_metadata_ : NULL);
+
+  util::Log(logging::LOG_VERBOSE, FROM_HERE,
+            "ApplyLocalChange for %s local_change:%s ===> %s",
+            url_.DebugString().c_str(),
+            local_change_.DebugString().c_str(),
+            SyncOperationTypeToString(operation_));
+
+  switch (operation_) {
+    case SYNC_OPERATION_ADD_FILE:
+      UploadNewFile(callback);
+      return;
+    case SYNC_OPERATION_ADD_DIRECTORY:
+      CreateDirectory(callback);
+      return;
+    case SYNC_OPERATION_UPDATE_FILE:
+      UploadExistingFile(callback);
+      return;
+    case SYNC_OPERATION_DELETE:
+      Delete(callback);
+      return;
+    case SYNC_OPERATION_NONE:
+      callback.Run(SYNC_STATUS_OK);
+      return;
+    case SYNC_OPERATION_CONFLICT:
+      HandleConflict(callback);
+      return;
+    case SYNC_OPERATION_RESOLVE_TO_LOCAL:
+      ResolveToLocal(callback);
+      return;
+    case SYNC_OPERATION_RESOLVE_TO_REMOTE:
+      ResolveToRemote(callback, remote_file_type);
+      return;
+    case SYNC_OPERATION_DELETE_METADATA:
+      DeleteMetadata(base::Bind(
+          &LocalSyncDelegate::DidApplyLocalChange,
+          weak_factory_.GetWeakPtr(), callback, google_apis::HTTP_SUCCESS));
+      return;
+    case SYNC_OPERATION_FAIL: {
+      callback.Run(SYNC_STATUS_FAILED);
+      return;
+    }
+  }
+  NOTREACHED();
+  callback.Run(SYNC_STATUS_FAILED);
+}
+
+void LocalSyncDelegate::UploadNewFile(const SyncStatusCallback& callback) {
+  api_util()->UploadNewFile(
+      origin_resource_id_,
+      local_path_,
+      DriveFileSyncService::PathToTitle(url_.path()),
+      base::Bind(&LocalSyncDelegate::DidUploadNewFile,
+                 weak_factory_.GetWeakPtr(), callback));
+}
+
+void LocalSyncDelegate::DidUploadNewFile(
+    const SyncStatusCallback& callback,
+    google_apis::GDataErrorCode error,
+    const std::string& resource_id,
+    const std::string& md5) {
+  switch (error) {
+    case google_apis::HTTP_CREATED:
+      UpdateMetadata(
+          resource_id, md5, DriveMetadata::RESOURCE_TYPE_FILE,
+          base::Bind(&LocalSyncDelegate::DidApplyLocalChange,
+                     weak_factory_.GetWeakPtr(), callback, error));
+      sync_service_->NotifyObserversFileStatusChanged(
+          url_,
+          SYNC_FILE_STATUS_SYNCED,
+          SYNC_ACTION_ADDED,
+          SYNC_DIRECTION_LOCAL_TO_REMOTE);
+      return;
+    case google_apis::HTTP_CONFLICT:
+      HandleCreationConflict(resource_id, DriveMetadata::RESOURCE_TYPE_FILE,
+                             callback);
+      return;
+    default:
+      callback.Run(GDataErrorCodeToSyncStatusCodeWrapper(error));
+  }
+}
+
+void LocalSyncDelegate::CreateDirectory(const SyncStatusCallback& callback) {
+  DCHECK(IsSyncFSDirectoryOperationEnabled());
+  api_util()->CreateDirectory(
+      origin_resource_id_,
+      DriveFileSyncService::PathToTitle(url_.path()),
+      base::Bind(&LocalSyncDelegate::DidCreateDirectory,
+                 weak_factory_.GetWeakPtr(), callback));
+}
+
+void LocalSyncDelegate::DidCreateDirectory(
+    const SyncStatusCallback& callback,
+    google_apis::GDataErrorCode error,
+    const std::string& resource_id) {
+  switch (error) {
+    case google_apis::HTTP_SUCCESS:
+    case google_apis::HTTP_CREATED: {
+      UpdateMetadata(
+          resource_id, std::string(), DriveMetadata::RESOURCE_TYPE_FOLDER,
+          base::Bind(&LocalSyncDelegate::DidApplyLocalChange,
+                     weak_factory_.GetWeakPtr(), callback, error));
+      sync_service_->NotifyObserversFileStatusChanged(
+          url_,
+          SYNC_FILE_STATUS_SYNCED,
+          SYNC_ACTION_ADDED,
+          SYNC_DIRECTION_LOCAL_TO_REMOTE);
+      return;
+    }
+
+    case google_apis::HTTP_CONFLICT:
+      // There were conflicts and a file was left.
+      // TODO(kinuko): Handle the latter case (http://crbug.com/237090).
+      // Fall-through
+
+    default:
+      callback.Run(GDataErrorCodeToSyncStatusCodeWrapper(error));
+  }
+}
+
+void LocalSyncDelegate::UploadExistingFile(const SyncStatusCallback& callback) {
+  DCHECK(has_drive_metadata_);
+  if (drive_metadata_.resource_id().empty()) {
+    UploadNewFile(callback);
+    return;
+  }
+
+  api_util()->UploadExistingFile(
+      drive_metadata_.resource_id(),
+      drive_metadata_.md5_checksum(),
+      local_path_,
+      base::Bind(&LocalSyncDelegate::DidUploadExistingFile,
+                 weak_factory_.GetWeakPtr(), callback));
+}
+
+void LocalSyncDelegate::DidUploadExistingFile(
+    const SyncStatusCallback& callback,
+    google_apis::GDataErrorCode error,
+    const std::string& resource_id,
+    const std::string& md5) {
+  DCHECK(has_drive_metadata_);
+  switch (error) {
+    case google_apis::HTTP_SUCCESS:
+      UpdateMetadata(
+          resource_id, md5, DriveMetadata::RESOURCE_TYPE_FILE,
+          base::Bind(&LocalSyncDelegate::DidApplyLocalChange,
+                     weak_factory_.GetWeakPtr(), callback, error));
+      sync_service_->NotifyObserversFileStatusChanged(
+          url_,
+          SYNC_FILE_STATUS_SYNCED,
+          SYNC_ACTION_UPDATED,
+          SYNC_DIRECTION_LOCAL_TO_REMOTE);
+      return;
+    case google_apis::HTTP_CONFLICT:
+      HandleConflict(callback);
+      return;
+    case google_apis::HTTP_NOT_MODIFIED:
+      DidApplyLocalChange(callback,
+                          google_apis::HTTP_SUCCESS, SYNC_STATUS_OK);
+      return;
+    case google_apis::HTTP_NOT_FOUND:
+      UploadNewFile(callback);
+      return;
+    default: {
+      const SyncStatusCode status =
+          GDataErrorCodeToSyncStatusCodeWrapper(error);
+      DCHECK_NE(SYNC_STATUS_OK, status);
+      callback.Run(status);
+      return;
+    }
+  }
+}
+
+void LocalSyncDelegate::Delete(const SyncStatusCallback& callback) {
+  if (!has_drive_metadata_) {
+    callback.Run(SYNC_STATUS_OK);
+    return;
+  }
+
+  if (drive_metadata_.resource_id().empty()) {
+    DidDelete(callback, google_apis::HTTP_NOT_FOUND);
+    return;
+  }
+
+  api_util()->DeleteFile(
+      drive_metadata_.resource_id(),
+      drive_metadata_.md5_checksum(),
+      base::Bind(&LocalSyncDelegate::DidDelete,
+                 weak_factory_.GetWeakPtr(), callback));
+}
+
+void LocalSyncDelegate::DidDelete(
+    const SyncStatusCallback& callback,
+    google_apis::GDataErrorCode error) {
+  DCHECK(has_drive_metadata_);
+
+  switch (error) {
+    case google_apis::HTTP_SUCCESS:
+    case google_apis::HTTP_NOT_FOUND:
+      DeleteMetadata(base::Bind(
+          &LocalSyncDelegate::DidApplyLocalChange,
+          weak_factory_.GetWeakPtr(), callback, google_apis::HTTP_SUCCESS));
+      sync_service_->NotifyObserversFileStatusChanged(
+          url_,
+          SYNC_FILE_STATUS_SYNCED,
+          SYNC_ACTION_DELETED,
+          SYNC_DIRECTION_LOCAL_TO_REMOTE);
+      return;
+    case google_apis::HTTP_PRECONDITION:
+    case google_apis::HTTP_CONFLICT:
+      // Delete |drive_metadata| on the conflict case.
+      // Conflicted remote change should be applied as a future remote change.
+      DeleteMetadata(base::Bind(
+          &LocalSyncDelegate::DidDeleteMetadataForDeletionConflict,
+          weak_factory_.GetWeakPtr(), callback));
+      sync_service_->NotifyObserversFileStatusChanged(
+          url_,
+          SYNC_FILE_STATUS_SYNCED,
+          SYNC_ACTION_DELETED,
+          SYNC_DIRECTION_LOCAL_TO_REMOTE);
+      return;
+    default: {
+      const SyncStatusCode status =
+          GDataErrorCodeToSyncStatusCodeWrapper(error);
+      DCHECK_NE(SYNC_STATUS_OK, status);
+      callback.Run(status);
+      return;
+    }
+  }
+}
+
+void LocalSyncDelegate::DidDeleteMetadataForDeletionConflict(
+    const SyncStatusCallback& callback,
+    SyncStatusCode status) {
+  callback.Run(SYNC_STATUS_OK);
+}
+
+void LocalSyncDelegate::ResolveToLocal(const SyncStatusCallback& callback) {
+  if (drive_metadata_.resource_id().empty()) {
+    DidDeleteFileToResolveToLocal(callback, google_apis::HTTP_NOT_FOUND);
+    return;
+  }
+
+  api_util()->DeleteFile(
+      drive_metadata_.resource_id(),
+      drive_metadata_.md5_checksum(),
+      base::Bind(
+          &LocalSyncDelegate::DidDeleteFileToResolveToLocal,
+          weak_factory_.GetWeakPtr(), callback));
+}
+
+void LocalSyncDelegate::DidDeleteFileToResolveToLocal(
+    const SyncStatusCallback& callback,
+    google_apis::GDataErrorCode error) {
+  if (error != google_apis::HTTP_SUCCESS &&
+      error != google_apis::HTTP_NOT_FOUND) {
+    callback.Run(GDataErrorCodeToSyncStatusCodeWrapper(error));
+    return;
+  }
+
+  DCHECK_NE(SYNC_FILE_TYPE_UNKNOWN, local_metadata_.file_type);
+  if (local_metadata_.file_type == SYNC_FILE_TYPE_FILE) {
+    UploadNewFile(callback);
+    return;
+  }
+
+  DCHECK(IsSyncFSDirectoryOperationEnabled());
+  DCHECK_EQ(SYNC_FILE_TYPE_DIRECTORY, local_metadata_.file_type);
+  CreateDirectory(callback);
+}
+
+void LocalSyncDelegate::ResolveToRemote(
+    const SyncStatusCallback& callback,
+    SyncFileType remote_file_type) {
+  // Mark the file as to-be-fetched.
+  DCHECK(!drive_metadata_.resource_id().empty());
+
+  SetMetadataToBeFetched(
+      DriveFileSyncService::SyncFileTypeToDriveMetadataResourceType(
+          remote_file_type),
+      base::Bind(&LocalSyncDelegate::DidResolveToRemote,
+                 weak_factory_.GetWeakPtr(), callback));
+  // The synced notification will be dispatched when the remote file is
+  // downloaded.
+}
+
+void LocalSyncDelegate::DidResolveToRemote(
+    const SyncStatusCallback& callback,
+    SyncStatusCode status) {
+  DCHECK(has_drive_metadata_);
+  if (status != SYNC_STATUS_OK) {
+    callback.Run(status);
+    return;
+  }
+
+  SyncFileType file_type = SYNC_FILE_TYPE_FILE;
+  if (drive_metadata_.type() == DriveMetadata::RESOURCE_TYPE_FOLDER)
+    file_type = SYNC_FILE_TYPE_DIRECTORY;
+  sync_service_->AppendFetchChange(
+      url_.origin(), url_.path(), drive_metadata_.resource_id(), file_type);
+  callback.Run(status);
+}
+
+void LocalSyncDelegate::DidApplyLocalChange(
+    const SyncStatusCallback& callback,
+    const google_apis::GDataErrorCode error,
+    SyncStatusCode status) {
+  if ((operation_ == SYNC_OPERATION_DELETE ||
+       operation_ == SYNC_OPERATION_DELETE_METADATA) &&
+      (status == SYNC_FILE_ERROR_NOT_FOUND ||
+       status == SYNC_DATABASE_ERROR_NOT_FOUND)) {
+    status = SYNC_STATUS_OK;
+  }
+
+  if (status == SYNC_STATUS_OK) {
+    remote_change_handler()->RemoveChangeForURL(url_);
+    status = GDataErrorCodeToSyncStatusCodeWrapper(error);
+  }
+  callback.Run(status);
+}
+
+void LocalSyncDelegate::UpdateMetadata(
+    const std::string& resource_id,
+    const std::string& md5,
+    DriveMetadata::ResourceType type,
+    const SyncStatusCallback& callback) {
+  has_drive_metadata_ = true;
+  drive_metadata_.set_resource_id(resource_id);
+  drive_metadata_.set_md5_checksum(md5);
+  drive_metadata_.set_conflicted(false);
+  drive_metadata_.set_to_be_fetched(false);
+  drive_metadata_.set_type(type);
+  metadata_store()->UpdateEntry(url_, drive_metadata_, callback);
+}
+
+void LocalSyncDelegate::ResetMetadataMD5(const SyncStatusCallback& callback) {
+  has_drive_metadata_ = true;
+  drive_metadata_.set_md5_checksum(std::string());
+  metadata_store()->UpdateEntry(url_, drive_metadata_, callback);
+}
+
+void LocalSyncDelegate::SetMetadataToBeFetched(
+    DriveMetadata::ResourceType type,
+    const SyncStatusCallback& callback) {
+  has_drive_metadata_ = true;
+  drive_metadata_.set_md5_checksum(std::string());
+  drive_metadata_.set_conflicted(false);
+  drive_metadata_.set_to_be_fetched(true);
+  drive_metadata_.set_type(type);
+  metadata_store()->UpdateEntry(url_, drive_metadata_, callback);
+}
+
+void LocalSyncDelegate::SetMetadataConflict(
+    const SyncStatusCallback& callback) {
+  has_drive_metadata_ = true;
+  drive_metadata_.set_conflicted(true);
+  drive_metadata_.set_to_be_fetched(false);
+  metadata_store()->UpdateEntry(url_, drive_metadata_, callback);
+}
+
+void LocalSyncDelegate::DeleteMetadata(const SyncStatusCallback& callback) {
+  metadata_store()->DeleteEntry(url_, callback);
+}
+
+void LocalSyncDelegate::HandleCreationConflict(
+    const std::string& resource_id,
+    DriveMetadata::ResourceType type,
+    const SyncStatusCallback& callback) {
+  // File-file conflict is found.
+  // Populates a fake drive_metadata and set has_drive_metadata = true.
+  // In HandleConflictLocalSync:
+  // - If conflict_resolution is manual, we'll change conflicted to true
+  //   and save the metadata.
+  // - Otherwise we'll save the metadata with empty md5 and will start
+  //   over local sync as UploadExistingFile.
+  drive_metadata_.set_resource_id(resource_id);
+  drive_metadata_.set_md5_checksum(std::string());
+  drive_metadata_.set_conflicted(false);
+  drive_metadata_.set_to_be_fetched(false);
+  drive_metadata_.set_type(type);
+  has_drive_metadata_ = true;
+  HandleConflict(callback);
+}
+
+void LocalSyncDelegate::HandleConflict(const SyncStatusCallback& callback) {
+  DCHECK(!drive_metadata_.resource_id().empty());
+  api_util()->GetResourceEntry(
+      drive_metadata_.resource_id(),
+      base::Bind(
+          &LocalSyncDelegate::DidGetEntryForConflictResolution,
+          weak_factory_.GetWeakPtr(), callback));
+}
+
+void LocalSyncDelegate::DidGetEntryForConflictResolution(
+    const SyncStatusCallback& callback,
+    google_apis::GDataErrorCode error,
+    scoped_ptr<google_apis::ResourceEntry> entry) {
+  SyncFileType remote_file_type = SYNC_FILE_TYPE_UNKNOWN;
+  ConflictResolution resolution = CONFLICT_RESOLUTION_UNKNOWN;
+
+  if (error != google_apis::HTTP_SUCCESS ||
+      entry->updated_time().is_null()) {
+    resolution = CONFLICT_RESOLUTION_LOCAL_WIN;
+  } else {
+    SyncFileType local_file_type = local_metadata_.file_type;
+    base::Time local_modification_time = local_metadata_.last_modified;
+    base::Time remote_modification_time = entry->updated_time();
+    if (entry->is_file())
+      remote_file_type = SYNC_FILE_TYPE_FILE;
+    else if (entry->is_folder())
+      remote_file_type = SYNC_FILE_TYPE_DIRECTORY;
+    else
+      remote_file_type = SYNC_FILE_TYPE_UNKNOWN;
+
+    resolution = conflict_resolution_resolver()->Resolve(
+        local_file_type, local_modification_time,
+        remote_file_type, remote_modification_time);
+  }
+
+  switch (resolution) {
+    case CONFLICT_RESOLUTION_MARK_CONFLICT:
+      HandleManualResolutionCase(callback);
+      return;
+    case CONFLICT_RESOLUTION_LOCAL_WIN:
+      HandleLocalWinCase(callback);
+      return;
+    case CONFLICT_RESOLUTION_REMOTE_WIN:
+      HandleRemoteWinCase(callback, remote_file_type);
+      return;
+    case CONFLICT_RESOLUTION_UNKNOWN:
+      NOTREACHED();
+  }
+  NOTREACHED();
+  callback.Run(SYNC_STATUS_FAILED);
+}
+
+void LocalSyncDelegate::HandleManualResolutionCase(
+    const SyncStatusCallback& callback) {
+  if (drive_metadata_.conflicted()) {
+    callback.Run(SYNC_STATUS_HAS_CONFLICT);
+    return;
+  }
+
+  SetMetadataConflict(base::Bind(&LocalSyncDelegate::NotifyConflict,
+                                 weak_factory_.GetWeakPtr(), callback));
+}
+
+void LocalSyncDelegate::NotifyConflict(const SyncStatusCallback& callback,
+                                       SyncStatusCode status) {
+  if (status != SYNC_STATUS_OK) {
+    callback.Run(status);
+    return;
+  }
+
+  sync_service_->NotifyObserversFileStatusChanged(
+      url_,
+      SYNC_FILE_STATUS_CONFLICTING,
+      SYNC_ACTION_NONE,
+      SYNC_DIRECTION_NONE);
+
+  DidApplyLocalChange(callback, google_apis::HTTP_CONFLICT, status);
+}
+
+void LocalSyncDelegate::HandleLocalWinCase(
+    const SyncStatusCallback& callback) {
+  util::Log(logging::LOG_VERBOSE, FROM_HERE,
+            "Resolving conflict for local sync: %s: LOCAL WIN",
+            url_.DebugString().c_str());
+
+  DCHECK(!drive_metadata_.resource_id().empty());
+  if (!has_drive_metadata_) {
+    StartOver(callback, SYNC_STATUS_OK);
+    return;
+  }
+
+  ResetMetadataMD5(base::Bind(&LocalSyncDelegate::StartOver,
+                              weak_factory_.GetWeakPtr(), callback));
+}
+
+void LocalSyncDelegate::HandleRemoteWinCase(
+    const SyncStatusCallback& callback,
+    SyncFileType remote_file_type) {
+  util::Log(logging::LOG_VERBOSE, FROM_HERE,
+            "Resolving conflict for local sync: %s: REMOTE WIN",
+            url_.DebugString().c_str());
+  ResolveToRemote(callback, remote_file_type);
+}
+
+void LocalSyncDelegate::StartOver(const SyncStatusCallback& callback,
+                                             SyncStatusCode status) {
+  if (status != SYNC_STATUS_OK) {
+    callback.Run(status);
+    return;
+  }
+
+  remote_change_handler()->RemoveChangeForURL(url_);
+  Run(callback);
+}
+
+SyncStatusCode
+LocalSyncDelegate::GDataErrorCodeToSyncStatusCodeWrapper(
+    google_apis::GDataErrorCode error) {
+  return sync_service_->GDataErrorCodeToSyncStatusCodeWrapper(error);
+}
+
+DriveMetadataStore* LocalSyncDelegate::metadata_store() {
+  return sync_service_->metadata_store_.get();
+}
+
+APIUtilInterface* LocalSyncDelegate::api_util() {
+  return sync_service_->api_util_.get();
+}
+
+RemoteChangeHandler* LocalSyncDelegate::remote_change_handler() {
+  return &sync_service_->remote_change_handler_;
+}
+
+ConflictResolutionResolver* LocalSyncDelegate::conflict_resolution_resolver() {
+  return &sync_service_->conflict_resolution_resolver_;
+}
+
+}  // namespace drive_backend
+}  // namespace sync_file_system
diff --git a/chrome/browser/sync_file_system/drive_backend/local_sync_delegate.h b/chrome/browser/sync_file_system/drive_backend/local_sync_delegate.h
new file mode 100644
index 0000000..6ba2089
--- /dev/null
+++ b/chrome/browser/sync_file_system/drive_backend/local_sync_delegate.h
@@ -0,0 +1,144 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_LOCAL_SYNC_DELEGATE_H_
+#define CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_LOCAL_SYNC_DELEGATE_H_
+
+#include "base/callback.h"
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/sync_file_system/drive_file_sync_service.h"
+#include "chrome/browser/sync_file_system/sync_file_system.pb.h"
+#include "webkit/browser/fileapi/file_system_url.h"
+#include "webkit/browser/fileapi/syncable/file_change.h"
+#include "webkit/browser/fileapi/syncable/sync_callbacks.h"
+#include "webkit/browser/fileapi/syncable/sync_file_metadata.h"
+
+namespace sync_file_system {
+
+class ConflictResolutionResolver;
+class DriveMetadataStore;
+
+namespace drive_backend {
+
+class APIUtil;
+
+// This class handles ApplyLocalChange in LocalChangeProcessor, and its instance
+// represents single ApplyLocalChange operation.
+// The caller is responsible to own the instance, and can cancel operation by
+// deleting the instance or |sync_service|.
+class LocalSyncDelegate {
+ public:
+  typedef RemoteChangeHandler::RemoteChange RemoteChange;
+
+  LocalSyncDelegate(DriveFileSyncService* sync_service,
+                    const FileChange& change,
+                    const base::FilePath& local_file_path,
+                    const SyncFileMetadata& local_file_metadata,
+                    const fileapi::FileSystemURL& url);
+  ~LocalSyncDelegate();
+
+  void Run(const SyncStatusCallback& callback);
+
+ private:
+  void DidGetOriginRoot(const SyncStatusCallback& callback,
+                        SyncStatusCode status,
+                        const std::string& resource_id);
+  void UploadNewFile(const SyncStatusCallback& callback);
+  void DidUploadNewFile(const SyncStatusCallback& callback,
+                        google_apis::GDataErrorCode error,
+                        const std::string& resource_id,
+                        const std::string& md5);
+  void CreateDirectory(const SyncStatusCallback& callback);
+  void DidCreateDirectory(
+      const SyncStatusCallback& callback,
+      google_apis::GDataErrorCode error,
+      const std::string& resource_id);
+  void UploadExistingFile(const SyncStatusCallback& callback);
+  void DidUploadExistingFile(
+      const SyncStatusCallback& callback,
+      google_apis::GDataErrorCode error,
+      const std::string& resource_id,
+      const std::string& md5);
+  void Delete(const SyncStatusCallback& callback);
+  void DidDelete(const SyncStatusCallback& callback,
+                 google_apis::GDataErrorCode error);
+  void DidDeleteMetadataForDeletionConflict(
+      const SyncStatusCallback& callback,
+      SyncStatusCode status);
+  void ResolveToLocal(const SyncStatusCallback& callback);
+  void DidDeleteFileToResolveToLocal(
+      const SyncStatusCallback& callback,
+      google_apis::GDataErrorCode error);
+  void ResolveToRemote(const SyncStatusCallback& callback,
+                       SyncFileType remote_file_type);
+  void DidResolveToRemote(const SyncStatusCallback& callback,
+                          SyncStatusCode status);
+  void DidApplyLocalChange(
+      const SyncStatusCallback& callback,
+      const google_apis::GDataErrorCode error,
+      SyncStatusCode status);
+
+  // Metadata manipulation.
+  void UpdateMetadata(const std::string& resource_id,
+                      const std::string& md5,
+                      DriveMetadata::ResourceType type,
+                      const SyncStatusCallback& callback);
+  void ResetMetadataMD5(const SyncStatusCallback& callback);
+  void SetMetadataToBeFetched(DriveMetadata::ResourceType type,
+                              const SyncStatusCallback& callback);
+  void DeleteMetadata(const SyncStatusCallback& callback);
+  void SetMetadataConflict(const SyncStatusCallback& callback);
+
+  // Conflict handling.
+  void HandleCreationConflict(
+      const std::string& resource_id,
+      DriveMetadata::ResourceType type,
+      const SyncStatusCallback& callback);
+  void HandleConflict(const SyncStatusCallback& callback);
+  void DidGetEntryForConflictResolution(
+      const SyncStatusCallback& callback,
+      google_apis::GDataErrorCode error,
+      scoped_ptr<google_apis::ResourceEntry> entry);
+
+  void HandleManualResolutionCase(const SyncStatusCallback& callback);
+  void NotifyConflict(const SyncStatusCallback& callback,
+                      SyncStatusCode status);
+
+  void HandleLocalWinCase(const SyncStatusCallback& callback);
+  void HandleRemoteWinCase(const SyncStatusCallback& callback,
+                           SyncFileType remote_file_type);
+  void StartOver(const SyncStatusCallback& callback, SyncStatusCode status);
+
+  SyncStatusCode GDataErrorCodeToSyncStatusCodeWrapper(
+      google_apis::GDataErrorCode error);
+
+  DriveMetadataStore* metadata_store();
+  APIUtilInterface* api_util();
+  RemoteChangeHandler* remote_change_handler();
+  ConflictResolutionResolver* conflict_resolution_resolver();
+
+  DriveFileSyncService* sync_service_;  // Not owned.
+
+  SyncOperationType operation_;
+
+  fileapi::FileSystemURL url_;
+  FileChange local_change_;
+  base::FilePath local_path_;
+  SyncFileMetadata local_metadata_;
+  DriveMetadata drive_metadata_;
+  bool has_drive_metadata_;
+  RemoteChange remote_change_;
+  bool has_remote_change_;
+
+  std::string origin_resource_id_;
+
+  base::WeakPtrFactory<LocalSyncDelegate> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(LocalSyncDelegate);
+};
+
+}  // namespace drive_backend
+}  // namespace sync_file_system
+
+#endif  // CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_LOCAL_SYNC_DELEGATE_H_
diff --git a/chrome/browser/sync_file_system/drive_backend/metadata_database.cc b/chrome/browser/sync_file_system/drive_backend/metadata_database.cc
new file mode 100644
index 0000000..6e52b51
--- /dev/null
+++ b/chrome/browser/sync_file_system/drive_backend/metadata_database.cc
@@ -0,0 +1,105 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
+
+#include "chrome/browser/google_apis/drive_api_parser.h"
+
+namespace sync_file_system {
+namespace drive_backend {
+
+MetadataDatabase::MetadataDatabase(base::SequencedTaskRunner* task_runner) {
+  NOTIMPLEMENTED();
+}
+
+MetadataDatabase::~MetadataDatabase() {
+}
+
+void MetadataDatabase::Initialize(const base::FilePath& database_dir,
+                                  const SyncStatusCallback& callback) {
+  NOTIMPLEMENTED();
+}
+
+int64 MetadataDatabase::GetLargestChangeID() const {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+void MetadataDatabase::RegisterApp(const std::string& app_id,
+                                   const std::string& folder_id,
+                                   const SyncStatusCallback& callback) {
+  NOTIMPLEMENTED();
+}
+
+void MetadataDatabase::DisableApp(const std::string& app_id,
+                                 const SyncStatusCallback& callback) {
+  NOTIMPLEMENTED();
+}
+
+void MetadataDatabase::EnableApp(const std::string& app_id,
+                                 const SyncStatusCallback& callback) {
+  NOTIMPLEMENTED();
+}
+
+void MetadataDatabase::UnregisterApp(const std::string& app_id,
+                                     const SyncStatusCallback& callback) {
+  NOTIMPLEMENTED();
+}
+
+bool MetadataDatabase::FindAppRootFolder(const std::string& app_id,
+                                         DriveFileMetadata* folder) const {
+  NOTIMPLEMENTED();
+  return false;
+}
+
+bool MetadataDatabase::FindFileByFileID(const std::string& file_id,
+                                        DriveFileMetadata* metadata) const {
+  NOTIMPLEMENTED();
+  return false;
+}
+
+size_t MetadataDatabase::FindFilesByParentAndTitle(
+    const std::string& file_id,
+    const std::string& title,
+    ScopedVector<DriveFileMetadata>* files) const {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+bool MetadataDatabase::FindActiveFileByParentAndTitle(
+    const std::string& folder_id,
+    const std::string& title,
+    DriveFileMetadata* file) const {
+  NOTIMPLEMENTED();
+  return false;
+}
+
+bool MetadataDatabase::FindActiveFileByPath(const std::string& app_id,
+                                            const base::FilePath& path,
+                                            DriveFileMetadata* file) const {
+  NOTIMPLEMENTED();
+  return false;
+}
+
+bool MetadataDatabase::ConstructPathForFile(const std::string& file_id,
+                                            base::FilePath* path) const {
+  NOTIMPLEMENTED();
+  return false;
+}
+
+void MetadataDatabase::UpdateByChangeList(
+    ScopedVector<google_apis::ChangeResource> changes,
+    const SyncStatusCallback& callback) {
+  NOTIMPLEMENTED();
+}
+
+void MetadataDatabase::PopulateFolder(
+    const std::string& folder_id,
+    ScopedVector<google_apis::ResourceEntry> children,
+    const SyncStatusCallback& callback) {
+  NOTIMPLEMENTED();
+}
+
+}  // namespace drive_backend
+}  // namespace sync_file_system
diff --git a/chrome/browser/sync_file_system/drive_backend/metadata_database.h b/chrome/browser/sync_file_system/drive_backend/metadata_database.h
new file mode 100644
index 0000000..967950a
--- /dev/null
+++ b/chrome/browser/sync_file_system/drive_backend/metadata_database.h
@@ -0,0 +1,133 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_METADATA_DATABASE_H_
+#define CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_METADATA_DATABASE_H_
+
+#include "base/callback_forward.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
+#include "webkit/browser/fileapi/syncable/sync_callbacks.h"
+#include "webkit/browser/fileapi/syncable/sync_status_code.h"
+
+namespace base {
+class FilePath;
+class SequencedTaskRunner;
+}
+
+namespace leveldb {
+class DB;
+class WriteBatch;
+}
+
+namespace google_apis {
+class ChangeResource;
+class FileResource;
+class ResourceEntry;
+}
+
+namespace sync_file_system {
+namespace drive_backend {
+
+class ServiceMetadata;
+class DriveFileMetadata;
+struct InitializeInfo;
+
+// This class holds a snapshot of the server side metadata.
+class MetadataDatabase {
+ public:
+  explicit MetadataDatabase(base::SequencedTaskRunner* task_runner);
+  ~MetadataDatabase();
+
+  // Initializes the internal database and loads its content to memory.
+  // This function works asynchronously.
+  void Initialize(const base::FilePath& database_path,
+                  const SyncStatusCallback& callback);
+
+  int64 GetLargestChangeID() const;
+
+  // Registers existing folder as the app-root for |app_id|.  The folder
+  // must be an inactive folder that does not yet associated to any App.
+  // This method associates the folder with |app_id| and activates it.
+  void RegisterApp(const std::string& app_id,
+                   const std::string& folder_id,
+                   const SyncStatusCallback& callback);
+
+  // Inactivates the folder associated to the app to disable |app_id|.
+  // Does nothing if |app_id| is already disabled.
+  void DisableApp(const std::string& app_id,
+                  const SyncStatusCallback& callback);
+
+  // Activates the folder associated to |app_id| to enable |app_id|.
+  // Does nothing if |app_id| is already enabled.
+  void EnableApp(const std::string& app_id,
+                 const SyncStatusCallback& callback);
+
+  // Unregister the folder as the app-root for |app_id|.  If |app_id| does not
+  // exist, does nothing.
+  void UnregisterApp(const std::string& app_id,
+                     const SyncStatusCallback& callback);
+
+  // Finds the app-root folder for |app_id|.  Returns true if exists.
+  // Copies the result to |folder| if it is non-NULL.
+  bool FindAppRootFolder(const std::string& app_id,
+                         DriveFileMetadata* folder) const;
+
+  // Finds file by |file_id|.  Returns true if the file was found.
+  // Copies the DriveFileMetadata instance identified by |file_id| into
+  // |file| if exists and |file| is non-NULL.
+  bool FindFileByFileID(const std::string& file_id,
+                        DriveFileMetadata* file) const;
+
+  // Finds files by |title| under the folder identified by |folder_id|, and
+  // returns the number of the files.
+  // Copies the DriveFileMetadata instances to |files| if it is non-NULL.
+  size_t FindFilesByParentAndTitle(
+      const std::string& folder_id,
+      const std::string& title,
+      ScopedVector<DriveFileMetadata>* files) const;
+
+  // Finds active file by |title| under the folder identified by |folder_id|.
+  // Returns true if the file exists.
+  bool FindActiveFileByParentAndTitle(
+      const std::string& folder_id,
+      const std::string& title,
+      DriveFileMetadata* file) const;
+
+  // Finds the active file identified by |app_id| and |path|, which must be
+  // unique.  Returns true if the file was found.
+  // Copies the DriveFileMetadata instance into |file| if the file is found and
+  // |file| is non-NULL.
+  // |path| must be an absolute path in |app_id|. (i.e. relative to the app-root
+  // folder.)
+  bool FindActiveFileByPath(const std::string& app_id,
+                            const base::FilePath& path,
+                            DriveFileMetadata* file) const;
+
+  // Looks up FilePath from FileID.  Returns true on success.
+  // |path| must be non-NULL.
+  bool ConstructPathForFile(const std::string& file_id,
+                            base::FilePath* path) const;
+
+  // Updates database by |changes|.
+  // Marks dirty for each changed file if the file has the metadata in the
+  // database.  Adds new metadata to track the file if the file doesn't have
+  // the metadata and its parent folder has the active metadata.
+  void UpdateByChangeList(ScopedVector<google_apis::ChangeResource> changes,
+                          const SyncStatusCallback& callback);
+
+  // Populates |folder| with |children|.  Each |children| initially has empty
+  // |synced_details| and |remote_details|.
+  void PopulateFolder(const std::string& folder_id,
+                      ScopedVector<google_apis::ResourceEntry> children,
+                      const SyncStatusCallback& callback);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MetadataDatabase);
+};
+
+}  // namespace drive_backend
+}  // namespace sync_file_system
+
+#endif  // CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_METADATA_DATABASE_H_
diff --git a/chrome/browser/sync_file_system/drive_backend/metadata_database.proto b/chrome/browser/sync_file_system/drive_backend/metadata_database.proto
new file mode 100644
index 0000000..05a9c81
--- /dev/null
+++ b/chrome/browser/sync_file_system/drive_backend/metadata_database.proto
@@ -0,0 +1,71 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Protocol buffer definitions for Drive backend of Syncable FileSystem.
+
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+
+package sync_file_system.drive_backend;
+
+enum FileKind {
+  KIND_UNSUPPORTED = 0;
+  KIND_FILE = 1;
+  KIND_FOLDER = 2;
+}
+
+message ServiceMetadata {
+  optional int64 largest_change_id = 1 [default = 0];
+  optional string sync_root_folder_id = 2;
+}
+
+message DriveFileMetadata {
+  // File ID of the remote file/folder which the DriveFileMetadata tracks.
+  required string file_id = 1;
+  required string parent_folder_id = 2;
+
+  optional string app_id = 3;
+  optional bool is_app_root = 4;
+
+  // Holds details of file/folder metadata.
+  message Details {
+    repeated string parent_folder_id = 1;
+    optional string title = 2;
+    optional FileKind kind = 3;
+    optional string md5 = 4;
+    optional string etag = 5;
+
+    // Creation time and modification time of the resource.
+    // Serialized by Time::ToInternalValue.
+    optional int64 creation_time = 6;
+    optional int64 modification_time = 7;
+
+    optional bool deleted = 8;
+    optional int64 change_id = 9;
+  }
+
+  // |synced_details| holds the file details snapshot when the file was
+  // fetched through remote-to-local update.
+  // This should contain same value as remote_details if |dirty| is false.
+  optional Details synced_details = 5;
+
+  // |remote_details| holds the latest file details that may not yet be
+  // applied to local metadata.
+  // This should be updated by each listed ChangeResource.
+  optional Details remote_details = 6;
+
+  // True if the file is changed since the last update for this file.
+  optional bool dirty = 7;
+
+  // True if the DriveFileMetadata is active.
+  // Remote file content update should only be applied for active
+  // DriveFileMetadata.
+  // Active DriveFileMetadata must have a unique title under its parent.
+  optional bool active = 8;
+
+  // Valid only for folders.
+  // True indicates the folder contents has not yet been fetched.
+  optional bool needs_folder_listing = 9;
+}
diff --git a/chrome/browser/sync_file_system/drive_backend/metadata_db_migration_util.cc b/chrome/browser/sync_file_system/drive_backend/metadata_db_migration_util.cc
new file mode 100644
index 0000000..d7dda53
--- /dev/null
+++ b/chrome/browser/sync_file_system/drive_backend/metadata_db_migration_util.cc
@@ -0,0 +1,251 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/sync_file_system/drive_backend/metadata_db_migration_util.h"
+
+#include "base/files/file_path.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_util.h"
+#include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
+#include "url/gurl.h"
+#include "webkit/browser/fileapi/file_system_url.h"
+#include "webkit/common/fileapi/file_system_types.h"
+
+namespace sync_file_system {
+namespace drive_backend {
+
+namespace {
+
+const base::FilePath::CharType kV0FormatPathPrefix[] =
+    FILE_PATH_LITERAL("drive/");
+const char kWapiFileIdPrefix[] = "file:";
+const char kWapiFolderIdPrefix[] = "folder:";
+
+std::string RemovePrefix(const std::string& str, const std::string& prefix) {
+  if (StartsWithASCII(str, prefix, true))
+    return std::string(str.begin() + prefix.size(), str.end());
+  return str;
+}
+
+}  // namespace
+
+bool ParseV0FormatFileSystemURL(const GURL& url,
+                                GURL* origin,
+                                base::FilePath* path) {
+  fileapi::FileSystemType mount_type;
+  base::FilePath virtual_path;
+
+  if (!fileapi::FileSystemURL::ParseFileSystemSchemeURL(
+          url, origin, &mount_type, &virtual_path) ||
+      mount_type != fileapi::kFileSystemTypeExternal) {
+    NOTREACHED() << "Failed to parse filesystem scheme URL " << url.spec();
+    return false;
+  }
+
+  base::FilePath::StringType prefix =
+      base::FilePath(kV0FormatPathPrefix).NormalizePathSeparators().value();
+  if (virtual_path.value().substr(0, prefix.size()) != prefix)
+    return false;
+
+  *path = base::FilePath(virtual_path.value().substr(prefix.size()));
+  return true;
+}
+
+std::string AddWapiFilePrefix(const std::string& resource_id) {
+  DCHECK(!StartsWithASCII(resource_id, kWapiFileIdPrefix, true));
+  DCHECK(!StartsWithASCII(resource_id, kWapiFolderIdPrefix, true));
+
+  if (resource_id.empty() ||
+      StartsWithASCII(resource_id, kWapiFileIdPrefix, true) ||
+      StartsWithASCII(resource_id, kWapiFolderIdPrefix, true))
+    return resource_id;
+  return kWapiFileIdPrefix + resource_id;
+}
+
+std::string AddWapiFolderPrefix(const std::string& resource_id) {
+  DCHECK(!StartsWithASCII(resource_id, kWapiFileIdPrefix, true));
+  DCHECK(!StartsWithASCII(resource_id, kWapiFolderIdPrefix, true));
+
+  if (resource_id.empty() ||
+      StartsWithASCII(resource_id, kWapiFileIdPrefix, true) ||
+      StartsWithASCII(resource_id, kWapiFolderIdPrefix, true))
+    return resource_id;
+  return kWapiFolderIdPrefix + resource_id;
+}
+
+std::string AddWapiIdPrefix(const std::string& resource_id,
+                            DriveMetadata_ResourceType type) {
+  switch (type) {
+    case DriveMetadata_ResourceType_RESOURCE_TYPE_FILE:
+      return AddWapiFilePrefix(resource_id);
+    case DriveMetadata_ResourceType_RESOURCE_TYPE_FOLDER:
+      return AddWapiFolderPrefix(resource_id);
+  }
+  NOTREACHED();
+  return resource_id;
+}
+
+std::string RemoveWapiIdPrefix(const std::string& resource_id) {
+  if (StartsWithASCII(resource_id, kWapiFileIdPrefix, true))
+    return RemovePrefix(resource_id, kWapiFileIdPrefix);
+  if (StartsWithASCII(resource_id, kWapiFolderIdPrefix, true))
+    return RemovePrefix(resource_id, kWapiFolderIdPrefix);
+  return resource_id;
+}
+
+SyncStatusCode MigrateDatabaseFromV0ToV1(leveldb::DB* db) {
+  // Version 0 database format:
+  //   key: "CHANGE_STAMP"
+  //   value: <Largest Changestamp>
+  //
+  //   key: "SYNC_ROOT_DIR"
+  //   value: <Resource ID of the sync root directory>
+  //
+  //   key: "METADATA: " +
+  //        <FileSystemURL serialized by SerializeSyncableFileSystemURL>
+  //   value: <Serialized DriveMetadata>
+  //
+  //   key: "BSYNC_ORIGIN: " + <URL string of a batch sync origin>
+  //   value: <Resource ID of the drive directory for the origin>
+  //
+  //   key: "ISYNC_ORIGIN: " + <URL string of a incremental sync origin>
+  //   value: <Resource ID of the drive directory for the origin>
+  //
+  // Version 1 database format (changed keys/fields are marked with '*'):
+  // * key: "VERSION" (new)
+  // * value: 1
+  //
+  //   key: "CHANGE_STAMP"
+  //   value: <Largest Changestamp>
+  //
+  //   key: "SYNC_ROOT_DIR"
+  //   value: <Resource ID of the sync root directory>
+  //
+  // * key: "METADATA: " + <Origin and URL> (changed)
+  // * value: <Serialized DriveMetadata>
+  //
+  //   key: "BSYNC_ORIGIN: " + <URL string of a batch sync origin>
+  //   value: <Resource ID of the drive directory for the origin>
+  //
+  //   key: "ISYNC_ORIGIN: " + <URL string of a incremental sync origin>
+  //   value: <Resource ID of the drive directory for the origin>
+  //
+  //   key: "DISABLED_ORIGIN: " + <URL string of a disabled origin>
+  //   value: <Resource ID of the drive directory for the origin>
+
+  const char kDatabaseVersionKey[] = "VERSION";
+  const char kDriveMetadataKeyPrefix[] = "METADATA: ";
+  const char kMetadataKeySeparator = ' ';
+
+  leveldb::WriteBatch write_batch;
+  write_batch.Put(kDatabaseVersionKey, "1");
+
+  scoped_ptr<leveldb::Iterator> itr(db->NewIterator(leveldb::ReadOptions()));
+  for (itr->Seek(kDriveMetadataKeyPrefix); itr->Valid(); itr->Next()) {
+    std::string key = itr->key().ToString();
+    if (!StartsWithASCII(key, kDriveMetadataKeyPrefix, true))
+      break;
+    std::string serialized_url(RemovePrefix(key, kDriveMetadataKeyPrefix));
+
+    GURL origin;
+    base::FilePath path;
+    bool success = ParseV0FormatFileSystemURL(
+        GURL(serialized_url), &origin, &path);
+    DCHECK(success) << serialized_url;
+    std::string new_key = kDriveMetadataKeyPrefix + origin.spec() +
+        kMetadataKeySeparator + path.AsUTF8Unsafe();
+
+    write_batch.Put(new_key, itr->value());
+    write_batch.Delete(key);
+  }
+
+  return LevelDBStatusToSyncStatusCode(
+      db->Write(leveldb::WriteOptions(), &write_batch));
+}
+
+SyncStatusCode MigrateDatabaseFromV1ToV2(leveldb::DB* db) {
+  // Strips prefix of WAPI resource ID, and discards batch sync origins.
+  // (i.e. "file:xxxx" => "xxxx", "folder:yyyy" => "yyyy")
+  //
+  // Version 2 database format (changed keys/fields are marked with '*'):
+  //   key: "VERSION"
+  // * value: 2
+  //
+  //   key: "CHANGE_STAMP"
+  //   value: <Largest Changestamp>
+  //
+  //   key: "SYNC_ROOT_DIR"
+  // * value: <Resource ID of the sync root directory> (striped)
+  //
+  //   key: "METADATA: " + <Origin and URL>
+  // * value: <Serialized DriveMetadata> (stripped)
+  //
+  // * key: "BSYNC_ORIGIN: " + <URL string of a batch sync origin> (deleted)
+  // * value: <Resource ID of the drive directory for the origin> (deleted)
+  //
+  //   key: "ISYNC_ORIGIN: " + <URL string of a incremental sync origin>
+  // * value: <Resource ID of the drive directory for the origin> (stripped)
+  //
+  //   key: "DISABLED_ORIGIN: " + <URL string of a disabled origin>
+  // * value: <Resource ID of the drive directory for the origin> (stripped)
+
+  const char kDatabaseVersionKey[] = "VERSION";
+  const char kSyncRootDirectoryKey[] = "SYNC_ROOT_DIR";
+  const char kDriveMetadataKeyPrefix[] = "METADATA: ";
+  const char kDriveBatchSyncOriginKeyPrefix[] = "BSYNC_ORIGIN: ";
+  const char kDriveIncrementalSyncOriginKeyPrefix[] = "ISYNC_ORIGIN: ";
+  const char kDriveDisabledOriginKeyPrefix[] = "DISABLED_ORIGIN: ";
+
+  leveldb::WriteBatch write_batch;
+  write_batch.Put(kDatabaseVersionKey, "2");
+
+  scoped_ptr<leveldb::Iterator> itr(db->NewIterator(leveldb::ReadOptions()));
+  for (itr->SeekToFirst(); itr->Valid(); itr->Next()) {
+    std::string key = itr->key().ToString();
+
+    // Strip resource id for the sync root directory.
+    if (StartsWithASCII(key, kSyncRootDirectoryKey, true)) {
+      write_batch.Put(key, RemoveWapiIdPrefix(itr->value().ToString()));
+      continue;
+    }
+
+    // Strip resource ids in the drive metadata.
+    if (StartsWithASCII(key, kDriveMetadataKeyPrefix, true)) {
+      DriveMetadata metadata;
+      bool success = metadata.ParseFromString(itr->value().ToString());
+      DCHECK(success);
+
+      metadata.set_resource_id(RemoveWapiIdPrefix(metadata.resource_id()));
+      std::string metadata_string;
+      metadata.SerializeToString(&metadata_string);
+
+      write_batch.Put(key, metadata_string);
+      continue;
+    }
+
+    // Deprecate legacy batch sync origin entries that are no longer needed.
+    if (StartsWithASCII(key, kDriveBatchSyncOriginKeyPrefix, true)) {
+      write_batch.Delete(key);
+      continue;
+    }
+
+    // Strip resource ids of the incremental sync origins.
+    if (StartsWithASCII(key, kDriveIncrementalSyncOriginKeyPrefix, true)) {
+      write_batch.Put(key, RemoveWapiIdPrefix(itr->value().ToString()));
+      continue;
+    }
+
+    // Strip resource ids of the disabled sync origins.
+    if (StartsWithASCII(key, kDriveDisabledOriginKeyPrefix, true)) {
+      write_batch.Put(key, RemoveWapiIdPrefix(itr->value().ToString()));
+      continue;
+    }
+  }
+
+  return LevelDBStatusToSyncStatusCode(
+      db->Write(leveldb::WriteOptions(), &write_batch));
+}
+
+}  // namespace drive_backend
+}  // namespace sync_file_system
diff --git a/chrome/browser/sync_file_system/drive_backend/metadata_db_migration_util.h b/chrome/browser/sync_file_system/drive_backend/metadata_db_migration_util.h
new file mode 100644
index 0000000..9379d0a
--- /dev/null
+++ b/chrome/browser/sync_file_system/drive_backend/metadata_db_migration_util.h
@@ -0,0 +1,64 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_METADATA_DB_MIGRATION_UTIL_H_
+#define CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_METADATA_DB_MIGRATION_UTIL_H_
+
+#include <string>
+
+#include "chrome/browser/sync_file_system/sync_file_system.pb.h"
+#include "third_party/leveldatabase/src/include/leveldb/db.h"
+#include "webkit/browser/fileapi/syncable/sync_status_code.h"
+
+class GURL;
+
+namespace sync_file_system {
+namespace drive_backend {
+
+// Parses a filesystem URL which contains 'drive' as a service name
+// (a.k.a. V0-format filesystem URL).
+//
+// When you parse V0-format filesystem URL, you should use this function instead
+// of DeserializeSyncableFileSystemURL() since 'drive' service name is no longer
+// used and the deserializer cannot parse the unregistered service name.
+//
+// EXAMPLE:
+// Assume following argument is given.
+//   url: 'filesystem:http://www.example.com/external/drive/foo/bar'
+// returns
+//   origin: 'http://www.example.com/'
+//   path:   'foo/bar'
+bool ParseV0FormatFileSystemURL(const GURL& url,
+                                GURL* origin,
+                                base::FilePath* path);
+
+// Adds "file:" prefix to WAPI resource ID.
+// EXAMPLE:  "xxx" => "file:xxx"
+std::string AddWapiFilePrefix(const std::string& resource_id);
+
+// Adds "folder:" prefix to WAPI resource ID.
+// EXAMPLE:  "xxx" => "folder:xxx"
+std::string AddWapiFolderPrefix(const std::string& resource_id);
+
+// Adds a prefix corresponding to the given |type|.
+std::string AddWapiIdPrefix(const std::string& resource_id,
+                            DriveMetadata_ResourceType type);
+
+// Removes a prefix from WAPI resource ID.
+// EXAMPLE:
+//   "file:xxx"    =>  "xxx"
+//   "folder:yyy"  =>  "yyy"
+//   "zzz"         =>  "zzz"
+std::string RemoveWapiIdPrefix(const std::string& resource_id);
+
+// Migrate |db| schema from version 0 to version 1.
+SyncStatusCode MigrateDatabaseFromV0ToV1(leveldb::DB* db);
+
+// Migrate |db| schema from version 1 to version 2.
+SyncStatusCode MigrateDatabaseFromV1ToV2(leveldb::DB* db);
+
+}  // namespace drive_backend
+}  // namespace sync_file_system
+
+#endif  // CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_METADATA_DB_MIGRATION_UTIL_H_
diff --git a/chrome/browser/sync_file_system/drive_backend/metadata_db_migration_util_unittest.cc b/chrome/browser/sync_file_system/drive_backend/metadata_db_migration_util_unittest.cc
new file mode 100644
index 0000000..71099ff
--- /dev/null
+++ b/chrome/browser/sync_file_system/drive_backend/metadata_db_migration_util_unittest.cc
@@ -0,0 +1,309 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/sync_file_system/drive_backend/metadata_db_migration_util.h"
+
+#include "base/files/scoped_temp_dir.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "chrome/browser/sync_file_system/drive_metadata_store.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/leveldatabase/src/include/leveldb/db.h"
+#include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
+#include "url/gurl.h"
+#include "webkit/browser/fileapi/external_mount_points.h"
+#include "webkit/browser/fileapi/syncable/syncable_file_system_util.h"
+#include "webkit/common/fileapi/file_system_util.h"
+
+#define FPL FILE_PATH_LITERAL
+
+namespace sync_file_system {
+namespace drive_backend {
+
+namespace {
+
+const char kV0ServiceName[] = "drive";
+
+bool CreateV0SerializedSyncableFileSystemURL(
+    const GURL& origin,
+    const base::FilePath& path,
+    std::string* serialized_url) {
+  fileapi::ScopedExternalFileSystem scoped_fs(
+      kV0ServiceName, fileapi::kFileSystemTypeSyncable, base::FilePath());
+
+  fileapi::FileSystemURL url =
+      fileapi::ExternalMountPoints::GetSystemInstance()->
+          CreateExternalFileSystemURL(origin, kV0ServiceName, path);
+  if (!url.is_valid())
+    return false;
+  *serialized_url = fileapi::GetExternalFileSystemRootURIString(
+        origin, kV0ServiceName) + url.path().AsUTF8Unsafe();
+  return true;
+}
+
+}  // namespace
+
+TEST(DriveMetadataDBMigrationUtilTest, ParseV0FormatFileSystemURL) {
+  const GURL kOrigin("chrome-extension://example");
+  const base::FilePath kFile(FPL("foo bar"));
+
+  std::string serialized_url;
+  ASSERT_TRUE(CreateV0SerializedSyncableFileSystemURL(
+      kOrigin, kFile, &serialized_url));
+
+  GURL origin;
+  base::FilePath path;
+  EXPECT_TRUE(ParseV0FormatFileSystemURL(GURL(serialized_url), &origin, &path));
+  EXPECT_EQ(kOrigin, origin);
+  EXPECT_EQ(kFile, path);
+}
+
+TEST(DriveMetadataDBMigrationUtilTest, AddWapiIdPrefix) {
+  DriveMetadata_ResourceType type_file =
+      DriveMetadata_ResourceType_RESOURCE_TYPE_FILE;
+  DriveMetadata_ResourceType type_folder =
+      DriveMetadata_ResourceType_RESOURCE_TYPE_FOLDER;
+
+  EXPECT_EQ("file:xxx", AddWapiFilePrefix("xxx"));
+  EXPECT_EQ("folder:yyy", AddWapiFolderPrefix("yyy"));
+  EXPECT_EQ("file:xxx", AddWapiIdPrefix("xxx", type_file));
+  EXPECT_EQ("folder:yyy", AddWapiIdPrefix("yyy", type_folder));
+
+  EXPECT_EQ("", AddWapiFilePrefix(""));
+  EXPECT_EQ("", AddWapiFolderPrefix(""));
+  EXPECT_EQ("", AddWapiIdPrefix("", type_file));
+  EXPECT_EQ("", AddWapiIdPrefix("", type_folder));
+}
+
+TEST(DriveMetadataDBMigrationUtilTest, RemoveWapiIdPrefix) {
+  EXPECT_EQ("xxx", RemoveWapiIdPrefix("xxx"));
+  EXPECT_EQ("yyy", RemoveWapiIdPrefix("file:yyy"));
+  EXPECT_EQ("zzz", RemoveWapiIdPrefix("folder:zzz"));
+
+  EXPECT_EQ("", RemoveWapiIdPrefix(""));
+  EXPECT_EQ("foo:xxx", RemoveWapiIdPrefix("foo:xxx"));
+}
+
+TEST(DriveMetadataDBMigrationUtilTest, MigrationFromV0) {
+  const char kDatabaseVersionKey[] = "VERSION";
+  const char kChangeStampKey[] = "CHANGE_STAMP";
+  const char kSyncRootDirectoryKey[] = "SYNC_ROOT_DIR";
+  const char kDriveMetadataKeyPrefix[] = "METADATA: ";
+  const char kDriveBatchSyncOriginKeyPrefix[] = "BSYNC_ORIGIN: ";
+  const char kDriveIncrementalSyncOriginKeyPrefix[] = "ISYNC_ORIGIN: ";
+
+  const GURL kOrigin1("chrome-extension://example1");
+  const GURL kOrigin2("chrome-extension://example2");
+  const std::string kSyncRootResourceId("folder:sync_root_resource_id");
+  const std::string kResourceId1("folder:hoge");
+  const std::string kResourceId2("folder:fuga");
+  const std::string kFileResourceId("file:piyo");
+  const base::FilePath kFile(FPL("foo bar"));
+  const std::string kFileMD5("file_md5");
+
+  base::ScopedTempDir base_dir;
+  ASSERT_TRUE(base_dir.CreateUniqueTempDir());
+
+  leveldb::Options options;
+  options.create_if_missing = true;
+  leveldb::DB* db_ptr = NULL;
+  std::string db_dir = fileapi::FilePathToString(
+      base_dir.path().Append(DriveMetadataStore::kDatabaseName));
+  leveldb::Status status = leveldb::DB::Open(options, db_dir, &db_ptr);
+
+  scoped_ptr<leveldb::DB> db(db_ptr);
+  ASSERT_TRUE(status.ok());
+
+  // Setup the database with the schema version 0.
+  leveldb::WriteBatch batch;
+  batch.Put(kChangeStampKey, "1");
+  batch.Put(kSyncRootDirectoryKey, kSyncRootResourceId);
+
+  // Setup drive metadata.
+  DriveMetadata drive_metadata;
+  drive_metadata.set_resource_id(kFileResourceId);
+  drive_metadata.set_md5_checksum(kFileMD5);
+  drive_metadata.set_conflicted(false);
+  drive_metadata.set_to_be_fetched(false);
+
+  std::string serialized_url;
+  ASSERT_TRUE(CreateV0SerializedSyncableFileSystemURL(
+      kOrigin1, kFile, &serialized_url));
+  std::string metadata_string;
+  drive_metadata.SerializeToString(&metadata_string);
+  batch.Put(kDriveMetadataKeyPrefix + serialized_url, metadata_string);
+
+  // Setup batch sync origin and incremental sync origin.
+  batch.Put(kDriveBatchSyncOriginKeyPrefix + kOrigin1.spec(), kResourceId1);
+  batch.Put(kDriveIncrementalSyncOriginKeyPrefix + kOrigin2.spec(),
+            kResourceId2);
+
+  status = db->Write(leveldb::WriteOptions(), &batch);
+  EXPECT_EQ(SYNC_STATUS_OK, LevelDBStatusToSyncStatusCode(status));
+
+  // Migrate the database.
+  MigrateDatabaseFromV0ToV1(db.get());
+
+  scoped_ptr<leveldb::Iterator> itr(db->NewIterator(leveldb::ReadOptions()));
+
+  // Verify DB schema version.
+  int64 database_version = 0;
+  itr->Seek(kDatabaseVersionKey);
+  EXPECT_TRUE(itr->Valid());
+  EXPECT_TRUE(base::StringToInt64(itr->value().ToString(), &database_version));
+  EXPECT_EQ(1, database_version);
+
+  // Verify the largest changestamp.
+  int64 changestamp = 0;
+  itr->Seek(kChangeStampKey);
+  EXPECT_TRUE(itr->Valid());
+  EXPECT_TRUE(base::StringToInt64(itr->value().ToString(), &changestamp));
+  EXPECT_EQ(1, changestamp);
+
+  // Verify the sync root directory.
+  itr->Seek(kSyncRootDirectoryKey);
+  EXPECT_TRUE(itr->Valid());
+  EXPECT_EQ(kSyncRootResourceId, itr->value().ToString());
+
+  // Verify the metadata.
+  itr->Seek(kDriveMetadataKeyPrefix);
+  EXPECT_TRUE(itr->Valid());
+  DriveMetadata metadata;
+  EXPECT_TRUE(metadata.ParseFromString(itr->value().ToString()));
+  EXPECT_EQ(kFileResourceId, metadata.resource_id());
+  EXPECT_EQ(kFileMD5, metadata.md5_checksum());
+  EXPECT_FALSE(metadata.conflicted());
+  EXPECT_FALSE(metadata.to_be_fetched());
+
+  // Verify the batch sync origin.
+  itr->Seek(kDriveBatchSyncOriginKeyPrefix);
+  EXPECT_TRUE(itr->Valid());
+  EXPECT_EQ(kResourceId1, itr->value().ToString());
+
+  // Verify the incremental sync origin.
+  itr->Seek(kDriveIncrementalSyncOriginKeyPrefix);
+  EXPECT_TRUE(itr->Valid());
+  EXPECT_EQ(kResourceId2, itr->value().ToString());
+}
+
+TEST(DriveMetadataDBMigrationUtilTest, MigrationFromV1) {
+  const char kDatabaseVersionKey[] = "VERSION";
+  const char kChangeStampKey[] = "CHANGE_STAMP";
+  const char kSyncRootDirectoryKey[] = "SYNC_ROOT_DIR";
+  const char kDriveMetadataKeyPrefix[] = "METADATA: ";
+  const char kMetadataKeySeparator = ' ';
+  const char kDriveBatchSyncOriginKeyPrefix[] = "BSYNC_ORIGIN: ";
+  const char kDriveIncrementalSyncOriginKeyPrefix[] = "ISYNC_ORIGIN: ";
+  const char kDriveDisabledOriginKeyPrefix[] = "DISABLED_ORIGIN: ";
+
+  const GURL kOrigin1("chrome-extension://example1");
+  const GURL kOrigin2("chrome-extension://example2");
+  const GURL kOrigin3("chrome-extension://example3");
+
+  const std::string kSyncRootResourceId("folder:sync_root_resource_id");
+  const std::string kResourceId1("folder:hoge");
+  const std::string kResourceId2("folder:fuga");
+  const std::string kResourceId3("folder:hogera");
+  const std::string kFileResourceId("file:piyo");
+  const base::FilePath kFile(FPL("foo bar"));
+  const std::string kFileMD5("file_md5");
+
+  RegisterSyncableFileSystem();
+
+  base::ScopedTempDir base_dir;
+  ASSERT_TRUE(base_dir.CreateUniqueTempDir());
+
+  leveldb::Options options;
+  options.create_if_missing = true;
+  leveldb::DB* db_ptr = NULL;
+  std::string db_dir = fileapi::FilePathToString(
+      base_dir.path().Append(DriveMetadataStore::kDatabaseName));
+  leveldb::Status status = leveldb::DB::Open(options, db_dir, &db_ptr);
+
+  scoped_ptr<leveldb::DB> db(db_ptr);
+  ASSERT_TRUE(status.ok());
+
+  // Setup the database with the schema version 1.
+  leveldb::WriteBatch batch;
+  batch.Put(kDatabaseVersionKey, "1");
+  batch.Put(kChangeStampKey, "1");
+  batch.Put(kSyncRootDirectoryKey, kSyncRootResourceId);
+
+  fileapi::FileSystemURL url = CreateSyncableFileSystemURL(kOrigin1, kFile);
+
+  // Setup drive metadata.
+  DriveMetadata drive_metadata;
+  drive_metadata.set_resource_id(kFileResourceId);
+  drive_metadata.set_md5_checksum(kFileMD5);
+  drive_metadata.set_conflicted(false);
+  drive_metadata.set_to_be_fetched(false);
+  std::string metadata_string;
+  drive_metadata.SerializeToString(&metadata_string);
+  std::string metadata_key = kDriveMetadataKeyPrefix + kOrigin1.spec() +
+                             kMetadataKeySeparator + url.path().AsUTF8Unsafe();
+  batch.Put(metadata_key, metadata_string);
+
+  // Setup origins.
+  batch.Put(kDriveBatchSyncOriginKeyPrefix + kOrigin1.spec(), kResourceId1);
+  batch.Put(kDriveIncrementalSyncOriginKeyPrefix + kOrigin2.spec(),
+            kResourceId2);
+  batch.Put(kDriveDisabledOriginKeyPrefix + kOrigin3.spec(), kResourceId3);
+
+  status = db->Write(leveldb::WriteOptions(), &batch);
+  EXPECT_EQ(SYNC_STATUS_OK, LevelDBStatusToSyncStatusCode(status));
+
+  RevokeSyncableFileSystem();
+
+  // Migrate the database.
+  MigrateDatabaseFromV1ToV2(db.get());
+
+  scoped_ptr<leveldb::Iterator> itr(db->NewIterator(leveldb::ReadOptions()));
+
+  // Verify DB schema version.
+  int64 database_version = 0;
+  itr->Seek(kDatabaseVersionKey);
+  EXPECT_TRUE(itr->Valid());
+  EXPECT_TRUE(base::StringToInt64(itr->value().ToString(), &database_version));
+  EXPECT_EQ(2, database_version);
+
+  // Verify the largest changestamp.
+  int64 changestamp = 0;
+  itr->Seek(kChangeStampKey);
+  EXPECT_TRUE(itr->Valid());
+  EXPECT_TRUE(base::StringToInt64(itr->value().ToString(), &changestamp));
+  EXPECT_EQ(1, changestamp);
+
+  // Verify the sync root directory.
+  itr->Seek(kSyncRootDirectoryKey);
+  EXPECT_TRUE(itr->Valid());
+  EXPECT_EQ(RemoveWapiIdPrefix(kSyncRootResourceId), itr->value().ToString());
+
+  // Verify the metadata.
+  itr->Seek(kDriveMetadataKeyPrefix);
+  EXPECT_TRUE(itr->Valid());
+  DriveMetadata metadata;
+  EXPECT_TRUE(metadata.ParseFromString(itr->value().ToString()));
+  EXPECT_EQ(RemoveWapiIdPrefix(kFileResourceId), metadata.resource_id());
+  EXPECT_EQ(kFileMD5, metadata.md5_checksum());
+  EXPECT_FALSE(metadata.conflicted());
+  EXPECT_FALSE(metadata.to_be_fetched());
+
+  // Verify the batch sync origin.
+  itr->Seek(kDriveBatchSyncOriginKeyPrefix);
+  EXPECT_FALSE(StartsWithASCII(kDriveBatchSyncOriginKeyPrefix,
+                               itr->key().ToString(), true));
+
+  // Verify the incremental sync origin.
+  itr->Seek(kDriveIncrementalSyncOriginKeyPrefix);
+  EXPECT_TRUE(itr->Valid());
+  EXPECT_EQ(RemoveWapiIdPrefix(kResourceId2), itr->value().ToString());
+
+  // Verify the disabled origin.
+  itr->Seek(kDriveDisabledOriginKeyPrefix);
+  EXPECT_TRUE(itr->Valid());
+  EXPECT_EQ(RemoveWapiIdPrefix(kResourceId3), itr->value().ToString());
+}
+
+}  // namespace drive_backend
+}  // namespace sync_file_system
diff --git a/chrome/browser/sync_file_system/drive_backend/remote_sync_delegate.cc b/chrome/browser/sync_file_system/drive_backend/remote_sync_delegate.cc
new file mode 100644
index 0000000..511b3d8
--- /dev/null
+++ b/chrome/browser/sync_file_system/drive_backend/remote_sync_delegate.cc
@@ -0,0 +1,518 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/sync_file_system/drive_backend/remote_sync_delegate.h"
+
+#include "base/file_util.h"
+#include "chrome/browser/sync_file_system/logger.h"
+#include "chrome/browser/sync_file_system/remote_change_processor.h"
+#include "chrome/browser/sync_file_system/remote_sync_operation_resolver.h"
+#include "content/public/browser/browser_thread.h"
+#include "webkit/browser/fileapi/syncable/syncable_file_system_util.h"
+
+using fileapi::FileSystemURL;
+
+namespace {
+
+bool CreateTemporaryFile(const base::FilePath& dir_path,
+                         webkit_blob::ScopedFile* temp_file) {
+  base::FilePath temp_file_path;
+  const bool success = file_util::CreateDirectory(dir_path) &&
+      file_util::CreateTemporaryFileInDir(dir_path, &temp_file_path);
+  if (!success)
+    return success;
+  *temp_file =
+      webkit_blob::ScopedFile(temp_file_path,
+                              webkit_blob::ScopedFile::DELETE_ON_SCOPE_OUT,
+                              base::MessageLoopProxy::current().get());
+  return success;
+}
+
+void EmptyStatusCallback(sync_file_system::SyncStatusCode status) {}
+
+}  // namespace
+
+namespace sync_file_system {
+namespace drive_backend {
+
+RemoteSyncDelegate::RemoteSyncDelegate(
+    DriveFileSyncService* sync_service,
+    const RemoteChange& remote_change)
+    : sync_service_(sync_service),
+      remote_change_(remote_change),
+      sync_action_(SYNC_ACTION_NONE),
+      metadata_updated_(false),
+      clear_local_changes_(true) {
+}
+
+RemoteSyncDelegate::~RemoteSyncDelegate() {}
+
+void RemoteSyncDelegate::Run(const SyncStatusCallback& callback) {
+  util::Log(logging::LOG_VERBOSE, FROM_HERE,
+            "ProcessRemoteChange for %s change:%s",
+            url().DebugString().c_str(),
+            remote_file_change().DebugString().c_str());
+
+  remote_change_processor()->PrepareForProcessRemoteChange(
+      url(),
+      base::Bind(&RemoteSyncDelegate::DidPrepareForProcessRemoteChange,
+                 AsWeakPtr(), callback));
+}
+
+void RemoteSyncDelegate::DidPrepareForProcessRemoteChange(
+    const SyncStatusCallback& callback,
+    SyncStatusCode status,
+    const SyncFileMetadata& metadata,
+    const FileChangeList& local_changes) {
+  if (status != SYNC_STATUS_OK) {
+    AbortSync(callback, status);
+    return;
+  }
+
+  local_metadata_ = metadata;
+  status = metadata_store()->ReadEntry(url(), &drive_metadata_);
+  DCHECK(status == SYNC_STATUS_OK || status == SYNC_DATABASE_ERROR_NOT_FOUND);
+
+  bool missing_db_entry = (status != SYNC_STATUS_OK);
+  if (missing_db_entry) {
+    drive_metadata_.set_resource_id(remote_change_.resource_id);
+    drive_metadata_.set_md5_checksum(std::string());
+    drive_metadata_.set_conflicted(false);
+    drive_metadata_.set_to_be_fetched(false);
+  }
+  bool missing_local_file = (metadata.file_type == SYNC_FILE_TYPE_UNKNOWN);
+
+  if (drive_metadata_.resource_id().empty()) {
+    // This (missing_db_entry is false but resource_id is empty) could
+    // happen when the remote file gets deleted (this clears resource_id
+    // in drive_metadata) but then a file is added with the same name.
+    drive_metadata_.set_resource_id(remote_change_.resource_id);
+  }
+
+  SyncOperationType operation =
+      RemoteSyncOperationResolver::Resolve(remote_file_change(),
+                                           local_changes,
+                                           local_metadata_.file_type,
+                                           drive_metadata_.conflicted());
+
+  util::Log(logging::LOG_VERBOSE, FROM_HERE,
+            "ProcessRemoteChange for %s %s%sremote_change: %s ==> %s",
+            url().DebugString().c_str(),
+            drive_metadata_.conflicted() ? " (conflicted)" : " ",
+            missing_local_file ? " (missing local file)" : " ",
+            remote_file_change().DebugString().c_str(),
+            SyncOperationTypeToString(operation));
+  DCHECK_NE(SYNC_OPERATION_FAIL, operation);
+
+  switch (operation) {
+    case SYNC_OPERATION_ADD_FILE:
+    case SYNC_OPERATION_ADD_DIRECTORY:
+      sync_action_ = SYNC_ACTION_ADDED;
+      break;
+    case SYNC_OPERATION_UPDATE_FILE:
+      sync_action_ = SYNC_ACTION_UPDATED;
+      break;
+    case SYNC_OPERATION_DELETE:
+      sync_action_ = SYNC_ACTION_DELETED;
+      break;
+    case SYNC_OPERATION_NONE:
+    case SYNC_OPERATION_DELETE_METADATA:
+      sync_action_ = SYNC_ACTION_NONE;
+      break;
+    default:
+      break;
+  }
+
+  switch (operation) {
+    case SYNC_OPERATION_ADD_FILE:
+    case SYNC_OPERATION_UPDATE_FILE:
+      DownloadFile(callback);
+      return;
+    case SYNC_OPERATION_ADD_DIRECTORY:
+    case SYNC_OPERATION_DELETE:
+      ApplyRemoteChange(callback);
+      return;
+    case SYNC_OPERATION_NONE:
+      CompleteSync(callback, SYNC_STATUS_OK);
+      return;
+    case SYNC_OPERATION_CONFLICT:
+      HandleConflict(callback, remote_file_change().file_type());
+      return;
+    case SYNC_OPERATION_RESOLVE_TO_LOCAL:
+      ResolveToLocal(callback);
+      return;
+    case SYNC_OPERATION_RESOLVE_TO_REMOTE:
+      ResolveToRemote(callback);
+      return;
+    case SYNC_OPERATION_DELETE_METADATA:
+      if (missing_db_entry)
+        CompleteSync(callback, SYNC_STATUS_OK);
+      else
+        DeleteMetadata(callback);
+      return;
+    case SYNC_OPERATION_FAIL:
+      AbortSync(callback, SYNC_STATUS_FAILED);
+      return;
+  }
+  NOTREACHED();
+  AbortSync(callback, SYNC_STATUS_FAILED);
+}
+
+void RemoteSyncDelegate::ApplyRemoteChange(const SyncStatusCallback& callback) {
+  remote_change_processor()->ApplyRemoteChange(
+      remote_file_change(), temporary_file_.path(), url(),
+      base::Bind(&RemoteSyncDelegate::DidApplyRemoteChange, AsWeakPtr(),
+                 callback));
+}
+
+void RemoteSyncDelegate::DidApplyRemoteChange(
+    const SyncStatusCallback& callback,
+    SyncStatusCode status) {
+  if (status != SYNC_STATUS_OK) {
+    AbortSync(callback, status);
+    return;
+  }
+
+  if (remote_file_change().IsDelete()) {
+    DeleteMetadata(callback);
+    return;
+  }
+
+  drive_metadata_.set_resource_id(remote_change_.resource_id);
+  drive_metadata_.set_conflicted(false);
+  if (remote_file_change().IsFile()) {
+    drive_metadata_.set_type(DriveMetadata::RESOURCE_TYPE_FILE);
+  } else {
+    DCHECK(IsSyncFSDirectoryOperationEnabled());
+    drive_metadata_.set_type(DriveMetadata::RESOURCE_TYPE_FOLDER);
+  }
+
+  metadata_store()->UpdateEntry(
+      url(), drive_metadata_,
+      base::Bind(&RemoteSyncDelegate::CompleteSync,
+                 AsWeakPtr(), callback));
+}
+
+void RemoteSyncDelegate::DeleteMetadata(const SyncStatusCallback& callback) {
+  metadata_store()->DeleteEntry(
+      url(),
+      base::Bind(&RemoteSyncDelegate::CompleteSync, AsWeakPtr(), callback));
+}
+
+void RemoteSyncDelegate::DownloadFile(const SyncStatusCallback& callback) {
+  content::BrowserThread::PostTaskAndReplyWithResult(
+      content::BrowserThread::FILE, FROM_HERE,
+      base::Bind(&CreateTemporaryFile,
+                 sync_service_->temporary_file_dir_,
+                 &temporary_file_),
+      base::Bind(&RemoteSyncDelegate::DidGetTemporaryFileForDownload,
+                 AsWeakPtr(), callback));
+}
+
+void RemoteSyncDelegate::DidGetTemporaryFileForDownload(
+    const SyncStatusCallback& callback,
+    bool success) {
+  if (!success) {
+    AbortSync(callback, SYNC_FILE_ERROR_FAILED);
+    return;
+  }
+
+  DCHECK(!temporary_file_.path().empty());
+
+  // We should not use the md5 in metadata for FETCH type to avoid the download
+  // finishes due to NOT_MODIFIED.
+  std::string md5_checksum;
+  if (!drive_metadata_.to_be_fetched())
+    md5_checksum = drive_metadata_.md5_checksum();
+
+  api_util()->DownloadFile(
+      remote_change_.resource_id,
+      md5_checksum,
+      temporary_file_.path(),
+      base::Bind(&RemoteSyncDelegate::DidDownloadFile,
+                 AsWeakPtr(),
+                 callback));
+}
+
+void RemoteSyncDelegate::DidDownloadFile(
+    const SyncStatusCallback& callback,
+    google_apis::GDataErrorCode error,
+    const std::string& md5_checksum,
+    int64 file_size,
+    const base::Time& updated_time) {
+  if (error == google_apis::HTTP_NOT_MODIFIED) {
+    sync_action_ = SYNC_ACTION_NONE;
+    DidApplyRemoteChange(callback, SYNC_STATUS_OK);
+    return;
+  }
+
+  SyncStatusCode status = GDataErrorCodeToSyncStatusCodeWrapper(error);
+  if (status != SYNC_STATUS_OK) {
+    AbortSync(callback, status);
+    return;
+  }
+
+  drive_metadata_.set_md5_checksum(md5_checksum);
+  remote_change_processor()->ApplyRemoteChange(
+      remote_file_change(), temporary_file_.path(), url(),
+      base::Bind(&RemoteSyncDelegate::DidApplyRemoteChange,
+                 AsWeakPtr(), callback));
+}
+
+void RemoteSyncDelegate::HandleConflict(
+    const SyncStatusCallback& callback,
+    SyncFileType remote_file_type) {
+  ConflictResolution resolution = conflict_resolution_resolver()->Resolve(
+      remote_file_type,
+      remote_change_.updated_time,
+      local_metadata_.file_type,
+      local_metadata_.last_modified);
+
+  switch (resolution) {
+    case CONFLICT_RESOLUTION_LOCAL_WIN:
+      HandleLocalWin(callback);
+      return;
+    case CONFLICT_RESOLUTION_REMOTE_WIN:
+      HandleRemoteWin(callback, remote_file_type);
+      return;
+    case CONFLICT_RESOLUTION_MARK_CONFLICT:
+      HandleManualResolutionCase(callback);
+      return;
+    case CONFLICT_RESOLUTION_UNKNOWN:
+      // Get remote file time and call this method again.
+      api_util()->GetResourceEntry(
+          remote_change_.resource_id,
+          base::Bind(
+              &RemoteSyncDelegate::DidGetEntryForConflictResolution,
+              AsWeakPtr(), callback));
+      return;
+  }
+  NOTREACHED();
+  AbortSync(callback, SYNC_STATUS_FAILED);
+}
+
+void RemoteSyncDelegate::HandleLocalWin(
+    const SyncStatusCallback& callback) {
+  util::Log(logging::LOG_VERBOSE, FROM_HERE,
+            "Resolving conflict for remote sync: %s: LOCAL WIN",
+            url().DebugString().c_str());
+  ResolveToLocal(callback);
+}
+
+void RemoteSyncDelegate::HandleRemoteWin(
+    const SyncStatusCallback& callback,
+    SyncFileType remote_file_type) {
+  // Make sure we reset the conflict flag and start over the remote sync
+  // with empty local changes.
+  util::Log(logging::LOG_VERBOSE, FROM_HERE,
+            "Resolving conflict for remote sync: %s: REMOTE WIN",
+            url().DebugString().c_str());
+
+  drive_metadata_.set_conflicted(false);
+  drive_metadata_.set_to_be_fetched(false);
+  drive_metadata_.set_type(
+      DriveFileSyncService::SyncFileTypeToDriveMetadataResourceType(
+          remote_file_type));
+  metadata_store()->UpdateEntry(
+      url(), drive_metadata_,
+      base::Bind(&RemoteSyncDelegate::StartOver, AsWeakPtr(), callback));
+}
+
+void RemoteSyncDelegate::HandleManualResolutionCase(
+    const SyncStatusCallback& callback) {
+  sync_action_ = SYNC_ACTION_NONE;
+  sync_service_->MarkConflict(
+      url(), &drive_metadata_,
+      base::Bind(&RemoteSyncDelegate::CompleteSync, AsWeakPtr(), callback));
+}
+
+void RemoteSyncDelegate::DidGetEntryForConflictResolution(
+    const SyncStatusCallback& callback,
+    google_apis::GDataErrorCode error,
+    scoped_ptr<google_apis::ResourceEntry> entry) {
+  SyncStatusCode status = GDataErrorCodeToSyncStatusCodeWrapper(error);
+  if (status != SYNC_STATUS_OK || entry->updated_time().is_null()) {
+    HandleLocalWin(callback);
+    return;
+  }
+
+  SyncFileType file_type = SYNC_FILE_TYPE_UNKNOWN;
+  if (entry->is_file())
+    file_type = SYNC_FILE_TYPE_FILE;
+  if (entry->is_folder())
+    file_type = SYNC_FILE_TYPE_DIRECTORY;
+
+  remote_change_.updated_time = entry->updated_time();
+  HandleConflict(callback, file_type);
+}
+
+void RemoteSyncDelegate::ResolveToLocal(
+    const SyncStatusCallback& callback) {
+  sync_action_ = SYNC_ACTION_NONE;
+  clear_local_changes_ = false;
+
+  // Re-add a fake local change to resolve it later in next LocalSync.
+  remote_change_processor()->RecordFakeLocalChange(
+      url(),
+      FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
+                 local_metadata_.file_type),
+      base::Bind(&RemoteSyncDelegate::DidResolveToLocal,
+                 AsWeakPtr(), callback));
+}
+
+void RemoteSyncDelegate::DidResolveToLocal(
+    const SyncStatusCallback& callback,
+    SyncStatusCode status) {
+  if (status != SYNC_STATUS_OK) {
+    DCHECK_NE(SYNC_STATUS_HAS_CONFLICT, status);
+    AbortSync(callback, status);
+    return;
+  }
+
+  if (remote_file_change().IsDelete()) {
+    metadata_store()->DeleteEntry(
+        url(),
+        base::Bind(&RemoteSyncDelegate::CompleteSync,
+                   AsWeakPtr(), callback));
+  } else {
+    DCHECK(!remote_change_.resource_id.empty());
+    drive_metadata_.set_resource_id(remote_change_.resource_id);
+    drive_metadata_.set_conflicted(false);
+    drive_metadata_.set_to_be_fetched(false);
+    drive_metadata_.set_md5_checksum(std::string());
+    metadata_store()->UpdateEntry(
+        url(), drive_metadata_,
+        base::Bind(&RemoteSyncDelegate::CompleteSync,
+                   AsWeakPtr(), callback));
+  }
+}
+
+void RemoteSyncDelegate::ResolveToRemote(
+    const SyncStatusCallback& callback) {
+  drive_metadata_.set_conflicted(false);
+  drive_metadata_.set_to_be_fetched(true);
+  metadata_store()->UpdateEntry(
+      url(), drive_metadata_,
+      base::Bind(&RemoteSyncDelegate::DidResolveToRemote,
+                 AsWeakPtr(), callback));
+}
+
+void RemoteSyncDelegate::DidResolveToRemote(
+    const SyncStatusCallback& callback,
+    SyncStatusCode status) {
+  if (status != SYNC_STATUS_OK) {
+    AbortSync(callback, status);
+    return;
+  }
+
+  sync_action_ = SYNC_ACTION_ADDED;
+  if (remote_file_change().file_type() == SYNC_FILE_TYPE_FILE) {
+    DownloadFile(callback);
+    return;
+  }
+
+  // ApplyRemoteChange should replace any existing local file or
+  // directory with remote_change_.
+  ApplyRemoteChange(callback);
+}
+
+void RemoteSyncDelegate::StartOver(
+    const SyncStatusCallback& callback,
+    SyncStatusCode status) {
+  DidPrepareForProcessRemoteChange(
+      callback, status, local_metadata_, FileChangeList());
+}
+
+void RemoteSyncDelegate::CompleteSync(
+    const SyncStatusCallback& callback,
+    SyncStatusCode status) {
+  if (status != SYNC_STATUS_OK) {
+    AbortSync(callback, status);
+    return;
+  }
+
+  sync_service_->RemoveRemoteChange(url());
+
+  if (drive_metadata_.to_be_fetched()) {
+    // Clear |to_be_fetched| flag since we completed fetching the remote change
+    // and applying it to the local file.
+    DCHECK(!drive_metadata_.conflicted());
+    drive_metadata_.set_conflicted(false);
+    drive_metadata_.set_to_be_fetched(false);
+    metadata_store()->UpdateEntry(url(), drive_metadata_,
+                                  base::Bind(&EmptyStatusCallback));
+  }
+
+  if (remote_change_.changestamp > 0) {
+    DCHECK(metadata_store()->IsIncrementalSyncOrigin(url().origin()));
+    metadata_store()->SetLargestChangeStamp(
+        remote_change_.changestamp,
+        base::Bind(&RemoteSyncDelegate::DidFinish, AsWeakPtr(), callback));
+    return;
+  }
+
+  if (drive_metadata_.conflicted())
+    status = SYNC_STATUS_HAS_CONFLICT;
+
+  DidFinish(callback, status);
+}
+
+void RemoteSyncDelegate::AbortSync(
+    const SyncStatusCallback& callback,
+    SyncStatusCode status) {
+  DidFinish(callback, status);
+}
+
+void RemoteSyncDelegate::DidFinish(
+    const SyncStatusCallback& callback,
+    SyncStatusCode status) {
+  // Clear the local changes. If the operation was resolve-to-local, we should
+  // not clear them here since we added the fake local change to sync with the
+  // remote file.
+  if (clear_local_changes_) {
+    clear_local_changes_ = false;
+    remote_change_processor()->ClearLocalChanges(
+        url(), base::Bind(&RemoteSyncDelegate::DidFinish,
+                          AsWeakPtr(), callback, status));
+    return;
+  }
+
+  if (status == SYNC_STATUS_OK && sync_action_ != SYNC_ACTION_NONE) {
+    sync_service_->NotifyObserversFileStatusChanged(
+        url(),
+        SYNC_FILE_STATUS_SYNCED,
+        sync_action_,
+        SYNC_DIRECTION_REMOTE_TO_LOCAL);
+  }
+
+  callback.Run(status);
+}
+
+SyncStatusCode RemoteSyncDelegate::GDataErrorCodeToSyncStatusCodeWrapper(
+    google_apis::GDataErrorCode error) {
+  return sync_service_->GDataErrorCodeToSyncStatusCodeWrapper(error);
+}
+
+DriveMetadataStore* RemoteSyncDelegate::metadata_store() {
+  return sync_service_->metadata_store_.get();
+}
+
+APIUtilInterface* RemoteSyncDelegate::api_util() {
+  return sync_service_->api_util_.get();
+}
+
+RemoteChangeHandler* RemoteSyncDelegate::remote_change_handler() {
+  return &sync_service_->remote_change_handler_;
+}
+
+RemoteChangeProcessor* RemoteSyncDelegate::remote_change_processor() {
+  return sync_service_->remote_change_processor_;
+}
+
+ConflictResolutionResolver* RemoteSyncDelegate::conflict_resolution_resolver() {
+  return &sync_service_->conflict_resolution_resolver_;
+}
+
+}  // namespace drive_backend
+}  // namespace sync_file_system
diff --git a/chrome/browser/sync_file_system/drive_backend/remote_sync_delegate.h b/chrome/browser/sync_file_system/drive_backend/remote_sync_delegate.h
new file mode 100644
index 0000000..3037c90
--- /dev/null
+++ b/chrome/browser/sync_file_system/drive_backend/remote_sync_delegate.h
@@ -0,0 +1,121 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_REMOTE_SYNC_DELEGATE_H_
+#define CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_REMOTE_SYNC_DELEGATE_H_
+
+#include "base/callback.h"
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/sync_file_system/drive_backend/api_util.h"
+#include "chrome/browser/sync_file_system/drive_file_sync_service.h"
+#include "chrome/browser/sync_file_system/drive_metadata_store.h"
+#include "chrome/browser/sync_file_system/sync_action.h"
+#include "chrome/browser/sync_file_system/sync_file_system.pb.h"
+#include "webkit/browser/fileapi/file_system_url.h"
+#include "webkit/browser/fileapi/syncable/file_change.h"
+#include "webkit/browser/fileapi/syncable/sync_callbacks.h"
+#include "webkit/browser/fileapi/syncable/sync_file_metadata.h"
+#include "webkit/common/blob/scoped_file.h"
+
+namespace sync_file_system {
+
+class DriveMetadataStore;
+class RemoteChangeProcessor;
+
+namespace drive_backend {
+
+class APIUtil;
+
+// This class handles RemoteFileSyncService::ProcessRemoteChange for drive
+// backend, and its instance represents single ProcessRemoteChange operation.
+// The caller is responsible to own the instance, and can cancel operation by
+// deleting the instance.
+class RemoteSyncDelegate : public base::SupportsWeakPtr<RemoteSyncDelegate> {
+ public:
+  typedef RemoteChangeHandler::RemoteChange RemoteChange;
+
+  RemoteSyncDelegate(
+      DriveFileSyncService* sync_service,
+      const RemoteChange& remote_change);
+  virtual ~RemoteSyncDelegate();
+
+  void Run(const SyncStatusCallback& callback);
+
+  const fileapi::FileSystemURL& url() const { return remote_change_.url; }
+
+ private:
+  void DidPrepareForProcessRemoteChange(const SyncStatusCallback& callback,
+                                        SyncStatusCode status,
+                                        const SyncFileMetadata& metadata,
+                                        const FileChangeList& local_changes);
+  void ApplyRemoteChange(const SyncStatusCallback& callback);
+  void DidApplyRemoteChange(const SyncStatusCallback& callback,
+                            SyncStatusCode status);
+  void DeleteMetadata(const SyncStatusCallback& callback);
+  void DownloadFile(const SyncStatusCallback& callback);
+  void DidGetTemporaryFileForDownload(const SyncStatusCallback& callback,
+                                      bool success);
+  void DidDownloadFile(const SyncStatusCallback& callback,
+                       google_apis::GDataErrorCode error,
+                       const std::string& md5_checksum,
+                       int64 file_size,
+                       const base::Time& updated_time);
+  void HandleConflict(const SyncStatusCallback& callback,
+                      SyncFileType remote_file_type);
+  void HandleLocalWin(const SyncStatusCallback& callback);
+  void HandleRemoteWin(const SyncStatusCallback& callback,
+                       SyncFileType remote_file_type);
+  void HandleManualResolutionCase(const SyncStatusCallback& callback);
+  void DidGetEntryForConflictResolution(
+      const SyncStatusCallback& callback,
+      google_apis::GDataErrorCode error,
+      scoped_ptr<google_apis::ResourceEntry> entry);
+  void ResolveToLocal(const SyncStatusCallback& callback);
+  void DidResolveToLocal(const SyncStatusCallback& callback,
+                         SyncStatusCode status);
+  void ResolveToRemote(const SyncStatusCallback& callback);
+  void DidResolveToRemote(const SyncStatusCallback& callback,
+                          SyncStatusCode status);
+  void StartOver(const SyncStatusCallback& callback,
+                 SyncStatusCode status);
+
+  void CompleteSync(const SyncStatusCallback& callback,
+                    SyncStatusCode status);
+  void AbortSync(const SyncStatusCallback& callback,
+                 SyncStatusCode status);
+  void DidFinish(const SyncStatusCallback& callback,
+                 SyncStatusCode status);
+
+  SyncStatusCode GDataErrorCodeToSyncStatusCodeWrapper(
+      google_apis::GDataErrorCode error);
+
+  DriveMetadataStore* metadata_store();
+  APIUtilInterface* api_util();
+  RemoteChangeHandler* remote_change_handler();
+  RemoteChangeProcessor* remote_change_processor();
+  ConflictResolutionResolver* conflict_resolution_resolver();
+
+  const FileChange& remote_file_change() const { return remote_change_.change; }
+
+  DriveFileSyncService* sync_service_;  // Not owned.
+
+  RemoteChange remote_change_;
+  DriveMetadata drive_metadata_;
+  SyncFileMetadata local_metadata_;
+  webkit_blob::ScopedFile temporary_file_;
+  std::string md5_checksum_;
+  SyncAction sync_action_;
+  bool metadata_updated_;
+  bool clear_local_changes_;
+
+  std::string origin_resource_id_;
+
+  DISALLOW_COPY_AND_ASSIGN(RemoteSyncDelegate);
+};
+
+}  // namespace drive_backend
+
+}  // namespace sync_file_system
+
+#endif  // CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_REMOTE_SYNC_DELEGATE_H_
diff --git a/chrome/browser/sync_file_system/drive_file_sync_service.cc b/chrome/browser/sync_file_system/drive_file_sync_service.cc
index 8659491..ce50f1c 100644
--- a/chrome/browser/sync_file_system/drive_file_sync_service.cc
+++ b/chrome/browser/sync_file_system/drive_file_sync_service.cc
@@ -15,22 +15,20 @@
 #include "base/message_loop/message_loop_proxy.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
+#include "chrome/browser/drive/drive_api_util.h"
 #include "chrome/browser/drive/drive_notification_manager.h"
 #include "chrome/browser/drive/drive_notification_manager_factory.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_system.h"
-#include "chrome/browser/google_apis/drive_api_util.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/sync_file_system/conflict_resolution_policy.h"
-#include "chrome/browser/sync_file_system/drive/api_util.h"
-#include "chrome/browser/sync_file_system/drive/local_change_processor_delegate.h"
+#include "chrome/browser/sync_file_system/drive_backend/api_util.h"
+#include "chrome/browser/sync_file_system/drive_backend/local_sync_delegate.h"
+#include "chrome/browser/sync_file_system/drive_backend/remote_sync_delegate.h"
 #include "chrome/browser/sync_file_system/drive_file_sync_util.h"
 #include "chrome/browser/sync_file_system/drive_metadata_store.h"
 #include "chrome/browser/sync_file_system/file_status_observer.h"
 #include "chrome/browser/sync_file_system/logger.h"
 #include "chrome/browser/sync_file_system/remote_change_handler.h"
-#include "chrome/browser/sync_file_system/remote_change_processor.h"
-#include "chrome/browser/sync_file_system/remote_sync_operation_resolver.h"
 #include "chrome/browser/sync_file_system/sync_file_system.pb.h"
 #include "chrome/common/extensions/extension.h"
 #include "content/public/browser/browser_thread.h"
@@ -46,7 +44,6 @@
 
 namespace sync_file_system {
 
-typedef DriveFileSyncService::ConflictResolutionResult ConflictResolutionResult;
 typedef RemoteFileSyncService::OriginStatusMap OriginStatusMap;
 
 namespace {
@@ -78,42 +75,10 @@
 
 void EmptyStatusCallback(SyncStatusCode status) {}
 
-void SyncFileCallbackAdapter(
-    const SyncStatusCallback& status_callback,
-    const SyncFileCallback& callback,
-    SyncStatusCode status,
-    const FileSystemURL& url) {
-  status_callback.Run(status);
-  callback.Run(status, url);
-}
-
 }  // namespace
 
 ConflictResolutionPolicy DriveFileSyncService::kDefaultPolicy =
-    CONFLICT_RESOLUTION_LAST_WRITE_WIN;
-
-struct DriveFileSyncService::ProcessRemoteChangeParam {
-  RemoteChangeHandler::RemoteChange remote_change;
-  SyncFileCallback callback;
-
-  DriveMetadata drive_metadata;
-  SyncFileMetadata local_metadata;
-  bool metadata_updated;
-  webkit_blob::ScopedFile temporary_file;
-  std::string md5_checksum;
-  SyncAction sync_action;
-  bool clear_local_changes;
-
-  ProcessRemoteChangeParam(
-      const RemoteChangeHandler::RemoteChange& remote_change,
-      const SyncFileCallback& callback)
-      : remote_change(remote_change),
-        callback(callback),
-        metadata_updated(false),
-        sync_action(SYNC_ACTION_NONE),
-        clear_local_changes(true) {
-  }
-};
+    CONFLICT_RESOLUTION_POLICY_LAST_WRITE_WIN;
 
 // DriveFileSyncService ------------------------------------------------------
 
@@ -121,8 +86,8 @@
   if (api_util_)
     api_util_->RemoveObserver(this);
 
-  google_apis::DriveNotificationManager* drive_notification_manager =
-      google_apis::DriveNotificationManagerFactory::GetForProfile(profile_);
+  ::drive::DriveNotificationManager* drive_notification_manager =
+      ::drive::DriveNotificationManagerFactory::GetForProfile(profile_);
   if (drive_notification_manager)
     drive_notification_manager->RemoveObserver(this);
 }
@@ -141,7 +106,7 @@
 scoped_ptr<DriveFileSyncService> DriveFileSyncService::CreateForTesting(
     Profile* profile,
     const base::FilePath& base_dir,
-    scoped_ptr<drive::APIUtilInterface> api_util,
+    scoped_ptr<drive_backend::APIUtilInterface> api_util,
     scoped_ptr<DriveMetadataStore> metadata_store) {
   scoped_ptr<DriveFileSyncService> service(new DriveFileSyncService(profile));
   scoped_ptr<SyncTaskManager> task_manager(
@@ -156,7 +121,7 @@
   return service.Pass();
 }
 
-scoped_ptr<drive::APIUtilInterface>
+scoped_ptr<drive_backend::APIUtilInterface>
 DriveFileSyncService::DestroyAndPassAPIUtilForTesting(
     scoped_ptr<DriveFileSyncService> sync_service) {
   return sync_service->api_util_.Pass();
@@ -271,9 +236,10 @@
 }
 
 void DriveFileSyncService::GetFileMetadataMap(
-    OriginFileMetadataMap* metadata_map) {
+    const GURL& origin,
+    FileMetadataMap* metadata_map) {
   DCHECK(metadata_map);
-  metadata_store_->GetFileMetadataMap(metadata_map);
+  metadata_store_->GetFileMetadataMap(origin, metadata_map);
 }
 
 void DriveFileSyncService::SetSyncEnabled(bool enabled) {
@@ -292,14 +258,14 @@
 }
 
 SyncStatusCode DriveFileSyncService::SetConflictResolutionPolicy(
-    ConflictResolutionPolicy resolution) {
-  conflict_resolution_ = resolution;
+    ConflictResolutionPolicy policy) {
+  conflict_resolution_resolver_.set_policy(policy);
   return SYNC_STATUS_OK;
 }
 
 ConflictResolutionPolicy
 DriveFileSyncService::GetConflictResolutionPolicy() const {
-  return conflict_resolution_;
+  return conflict_resolution_resolver_.policy();
 }
 
 void DriveFileSyncService::ApplyLocalChange(
@@ -347,7 +313,7 @@
       may_have_unfetched_changes_(false),
       remote_change_processor_(NULL),
       last_gdata_error_(google_apis::HTTP_SUCCESS),
-      conflict_resolution_(kDefaultPolicy) {
+      conflict_resolution_resolver_(kDefaultPolicy) {
 }
 
 void DriveFileSyncService::Initialize(
@@ -362,7 +328,7 @@
   temporary_file_dir_ =
       profile_->GetPath().Append(GetSyncFileSystemDir()).Append(kTempDirName);
 
-  api_util_.reset(new drive::APIUtil(profile_));
+  api_util_.reset(new drive_backend::APIUtil(profile_));
   api_util_->AddObserver(this);
 
   metadata_store_.reset(new DriveMetadataStore(
@@ -378,7 +344,7 @@
 void DriveFileSyncService::InitializeForTesting(
     scoped_ptr<SyncTaskManager> task_manager,
     const base::FilePath& base_dir,
-    scoped_ptr<drive::APIUtilInterface> api_util,
+    scoped_ptr<drive_backend::APIUtilInterface> api_util,
     scoped_ptr<DriveMetadataStore> metadata_store,
     const SyncStatusCallback& callback) {
   DCHECK(!metadata_store_);
@@ -437,8 +403,8 @@
   callback.Run(status);
   may_have_unfetched_changes_ = true;
 
-  google_apis::DriveNotificationManager* drive_notification_manager =
-      google_apis::DriveNotificationManagerFactory::GetForProfile(profile_);
+  ::drive::DriveNotificationManager* drive_notification_manager =
+      ::drive::DriveNotificationManagerFactory::GetForProfile(profile_);
   if (drive_notification_manager)
     drive_notification_manager->AddObserver(this);
 }
@@ -595,16 +561,17 @@
     const SyncStatusCallback& completion_callback) {
   DCHECK(remote_change_processor_);
 
-  SyncFileCallback callback =
-      base::Bind(&SyncFileCallbackAdapter, completion_callback, sync_callback);
+  SyncStatusCallback callback = base::Bind(
+      &DriveFileSyncService::DidProcessRemoteChange, AsWeakPtr(),
+      sync_callback, completion_callback);
 
-  if (!remote_change_handler_.HasChanges()) {
-    callback.Run(SYNC_STATUS_NO_CHANGE_TO_SYNC, FileSystemURL());
+  if (GetCurrentState() == REMOTE_SERVICE_DISABLED) {
+    callback.Run(SYNC_STATUS_SYNC_DISABLED);
     return;
   }
 
-  if (GetCurrentState() == REMOTE_SERVICE_DISABLED) {
-    callback.Run(SYNC_STATUS_SYNC_DISABLED, FileSystemURL());
+  if (!remote_change_handler_.HasChanges()) {
+    callback.Run(SYNC_STATUS_NO_CHANGE_TO_SYNC);
     return;
   }
 
@@ -613,17 +580,10 @@
       remote_change_handler_.GetChange(&remote_change);
   DCHECK(has_remote_change);
 
-  util::Log(logging::LOG_VERBOSE, FROM_HERE,
-            "ProcessRemoteChange for %s change:%s",
-            remote_change.url.DebugString().c_str(),
-            remote_change.change.DebugString().c_str());
-
-  scoped_ptr<ProcessRemoteChangeParam> param(new ProcessRemoteChangeParam(
-      remote_change, callback));
-  remote_change_processor_->PrepareForProcessRemoteChange(
-      remote_change.url,
-      base::Bind(&DriveFileSyncService::DidPrepareForProcessRemoteChange,
-                 AsWeakPtr(), base::Passed(&param)));
+  DCHECK(!running_remote_sync_task_);
+  running_remote_sync_task_.reset(new drive_backend::RemoteSyncDelegate(
+      this, remote_change));
+  running_remote_sync_task_->Run(callback);
 }
 
 void DriveFileSyncService::DoApplyLocalChange(
@@ -646,7 +606,7 @@
   }
 
   DCHECK(!running_local_sync_task_);
-  running_local_sync_task_.reset(new drive::LocalChangeProcessorDelegate(
+  running_local_sync_task_.reset(new drive_backend::LocalSyncDelegate(
       this, local_file_change, local_file_path, local_file_metadata, url));
   running_local_sync_task_->Run(base::Bind(
       &DriveFileSyncService::DidApplyLocalChange, AsWeakPtr(), callback));
@@ -847,27 +807,17 @@
   callback.Run(SYNC_STATUS_OK);
 }
 
-// TODO(tzik): Factor out this conflict resolution function.
-ConflictResolutionResult DriveFileSyncService::ResolveConflictForLocalSync(
-    SyncFileType local_file_type,
-    const base::Time& local_updated_time,
-    SyncFileType remote_file_type,
-    const base::Time& remote_updated_time) {
-  // Currently we always prioritize directories over files regardless of
-  // conflict resolution policy.
-  if (remote_file_type == SYNC_FILE_TYPE_DIRECTORY)
-    return CONFLICT_RESOLUTION_REMOTE_WIN;
+void DriveFileSyncService::DidProcessRemoteChange(
+    const SyncFileCallback& sync_callback,
+    const SyncStatusCallback& completion_callback,
+    SyncStatusCode status) {
+  fileapi::FileSystemURL url;
+  if (running_remote_sync_task_)
+    url = running_remote_sync_task_->url();
+  running_remote_sync_task_.reset();
 
-  if (conflict_resolution_ == CONFLICT_RESOLUTION_MANUAL)
-    return CONFLICT_RESOLUTION_MARK_CONFLICT;
-
-  DCHECK_EQ(CONFLICT_RESOLUTION_LAST_WRITE_WIN, conflict_resolution_);
-  if (local_updated_time >= remote_updated_time ||
-      remote_file_type == SYNC_FILE_TYPE_UNKNOWN) {
-    return CONFLICT_RESOLUTION_LOCAL_WIN;
-  }
-
-  return CONFLICT_RESOLUTION_REMOTE_WIN;
+  completion_callback.Run(status);
+  sync_callback.Run(status, url);
 }
 
 void DriveFileSyncService::DidApplyLocalChange(
@@ -877,414 +827,6 @@
   callback.Run(status);
 }
 
-void DriveFileSyncService::DidPrepareForProcessRemoteChange(
-    scoped_ptr<ProcessRemoteChangeParam> param,
-    SyncStatusCode status,
-    const SyncFileMetadata& metadata,
-    const FileChangeList& local_changes) {
-  if (status != SYNC_STATUS_OK) {
-    AbortRemoteSync(param.Pass(), status);
-    return;
-  }
-
-  param->local_metadata = metadata;
-  const FileSystemURL& url = param->remote_change.url;
-  const DriveMetadata& drive_metadata = param->drive_metadata;
-  const FileChange& remote_file_change = param->remote_change.change;
-
-  status = metadata_store_->ReadEntry(param->remote_change.url,
-                                      &param->drive_metadata);
-  DCHECK(status == SYNC_STATUS_OK || status == SYNC_DATABASE_ERROR_NOT_FOUND);
-
-  bool missing_db_entry = (status != SYNC_STATUS_OK);
-  if (missing_db_entry) {
-    param->drive_metadata.set_resource_id(param->remote_change.resource_id);
-    param->drive_metadata.set_md5_checksum(std::string());
-    param->drive_metadata.set_conflicted(false);
-    param->drive_metadata.set_to_be_fetched(false);
-  }
-  bool missing_local_file = (metadata.file_type == SYNC_FILE_TYPE_UNKNOWN);
-
-  SyncOperationType operation =
-      RemoteSyncOperationResolver::Resolve(remote_file_change,
-                                           local_changes,
-                                           param->local_metadata.file_type,
-                                           param->drive_metadata.conflicted());
-
-  util::Log(logging::LOG_VERBOSE, FROM_HERE,
-            "ProcessRemoteChange for %s %s%sremote_change: %s ==> %s",
-            url.DebugString().c_str(),
-            param->drive_metadata.conflicted() ? " (conflicted)" : " ",
-            missing_local_file ? " (missing local file)" : " ",
-            remote_file_change.DebugString().c_str(),
-            SyncOperationTypeToString(operation));
-  DCHECK_NE(SYNC_OPERATION_FAIL, operation);
-
-  switch (operation) {
-    case SYNC_OPERATION_ADD_FILE:
-    case SYNC_OPERATION_ADD_DIRECTORY:
-      param->sync_action = SYNC_ACTION_ADDED;
-      break;
-    case SYNC_OPERATION_UPDATE_FILE:
-      param->sync_action = SYNC_ACTION_UPDATED;
-      break;
-    case SYNC_OPERATION_DELETE:
-      param->sync_action = SYNC_ACTION_DELETED;
-      break;
-    case SYNC_OPERATION_NONE:
-    case SYNC_OPERATION_DELETE_METADATA:
-      param->sync_action = SYNC_ACTION_NONE;
-      break;
-    default:
-      break;
-  }
-
-  switch (operation) {
-    case SYNC_OPERATION_ADD_FILE:
-    case SYNC_OPERATION_UPDATE_FILE:
-      DownloadForRemoteSync(param.Pass());
-      return;
-    case SYNC_OPERATION_ADD_DIRECTORY:
-    case SYNC_OPERATION_DELETE: {
-      const FileChange& file_change = remote_file_change;
-      remote_change_processor_->ApplyRemoteChange(
-          file_change, base::FilePath(), url,
-          base::Bind(&DriveFileSyncService::DidApplyRemoteChange, AsWeakPtr(),
-                     base::Passed(&param)));
-      return;
-    }
-    case SYNC_OPERATION_NONE:
-      CompleteRemoteSync(param.Pass(), SYNC_STATUS_OK);
-      return;
-    case SYNC_OPERATION_CONFLICT:
-      HandleConflictForRemoteSync(param.Pass(), base::Time(),
-                                  remote_file_change.file_type(),
-                                  SYNC_STATUS_OK);
-      return;
-    case SYNC_OPERATION_RESOLVE_TO_LOCAL:
-      ResolveConflictToLocalForRemoteSync(param.Pass());
-      return;
-    case SYNC_OPERATION_RESOLVE_TO_REMOTE: {
-      const FileSystemURL& url = param->remote_change.url;
-      param->drive_metadata.set_conflicted(false);
-      param->drive_metadata.set_to_be_fetched(true);
-      metadata_store_->UpdateEntry(
-          url, drive_metadata, base::Bind(&EmptyStatusCallback));
-      param->sync_action = SYNC_ACTION_ADDED;
-      if (param->remote_change.change.file_type() == SYNC_FILE_TYPE_FILE) {
-        DownloadForRemoteSync(param.Pass());
-        return;
-      }
-
-      // |remote_change_processor| should replace any existing file or directory
-      // on ApplyRemoteChange call.
-      const FileChange& file_change = remote_file_change;
-      remote_change_processor_->ApplyRemoteChange(
-          file_change, base::FilePath(), url,
-          base::Bind(&DriveFileSyncService::DidApplyRemoteChange, AsWeakPtr(),
-                     base::Passed(&param)));
-      return;
-    }
-    case SYNC_OPERATION_DELETE_METADATA:
-      if (missing_db_entry)
-        CompleteRemoteSync(param.Pass(), SYNC_STATUS_OK);
-      else
-        DeleteMetadataForRemoteSync(param.Pass());
-      return;
-    case SYNC_OPERATION_FAIL:
-      AbortRemoteSync(param.Pass(), SYNC_STATUS_FAILED);
-      return;
-  }
-  NOTREACHED();
-  AbortRemoteSync(param.Pass(), SYNC_STATUS_FAILED);
-}
-
-void DriveFileSyncService::DidResolveConflictToLocalChange(
-    scoped_ptr<ProcessRemoteChangeParam> param,
-    SyncStatusCode status) {
-  if (status != SYNC_STATUS_OK) {
-    DCHECK_NE(SYNC_STATUS_HAS_CONFLICT, status);
-    AbortRemoteSync(param.Pass(), status);
-    return;
-  }
-
-  const FileSystemURL& url = param->remote_change.url;
-  if (param->remote_change.change.IsDelete()) {
-    metadata_store_->DeleteEntry(
-        url,
-        base::Bind(&DriveFileSyncService::CompleteRemoteSync,
-                   AsWeakPtr(), base::Passed(&param)));
-  } else {
-    DriveMetadata& drive_metadata = param->drive_metadata;
-    DCHECK(!param->remote_change.resource_id.empty());
-    drive_metadata.set_resource_id(param->remote_change.resource_id);
-    drive_metadata.set_conflicted(false);
-    drive_metadata.set_to_be_fetched(false);
-    drive_metadata.set_md5_checksum(std::string());
-    metadata_store_->UpdateEntry(
-        url, drive_metadata,
-        base::Bind(&DriveFileSyncService::CompleteRemoteSync,
-                   AsWeakPtr(), base::Passed(&param)));
-  }
-}
-
-void DriveFileSyncService::DownloadForRemoteSync(
-    scoped_ptr<ProcessRemoteChangeParam> param) {
-  webkit_blob::ScopedFile* temporary_file = &param->temporary_file;
-  content::BrowserThread::PostTaskAndReplyWithResult(
-      content::BrowserThread::FILE, FROM_HERE,
-      base::Bind(&CreateTemporaryFile, temporary_file_dir_, temporary_file),
-      base::Bind(&DriveFileSyncService::DidGetTemporaryFileForDownload,
-                 AsWeakPtr(), base::Passed(&param)));
-}
-
-void DriveFileSyncService::DidGetTemporaryFileForDownload(
-    scoped_ptr<ProcessRemoteChangeParam> param,
-    bool success) {
-  if (!success) {
-    AbortRemoteSync(param.Pass(), SYNC_FILE_ERROR_FAILED);
-    return;
-  }
-
-  const base::FilePath& temporary_file_path = param->temporary_file.path();
-  std::string resource_id = param->remote_change.resource_id;
-  DCHECK(!temporary_file_path.empty());
-
-  // We should not use the md5 in metadata for FETCH type to avoid the download
-  // finishes due to NOT_MODIFIED.
-  std::string md5_checksum;
-  if (!param->drive_metadata.to_be_fetched())
-    md5_checksum = param->drive_metadata.md5_checksum();
-  api_util_->DownloadFile(
-      resource_id,
-      md5_checksum,
-      temporary_file_path,
-      base::Bind(&DriveFileSyncService::DidDownloadFileForRemoteSync,
-                 AsWeakPtr(),
-                 base::Passed(&param)));
-}
-
-void DriveFileSyncService::DidDownloadFileForRemoteSync(
-    scoped_ptr<ProcessRemoteChangeParam> param,
-    google_apis::GDataErrorCode error,
-    const std::string& md5_checksum,
-    int64 file_size,
-    const base::Time& updated_time) {
-  if (error == google_apis::HTTP_NOT_MODIFIED) {
-    param->sync_action = SYNC_ACTION_NONE;
-    DidApplyRemoteChange(param.Pass(), SYNC_STATUS_OK);
-    return;
-  }
-
-  SyncStatusCode status = GDataErrorCodeToSyncStatusCodeWrapper(error);
-  if (status != SYNC_STATUS_OK) {
-    AbortRemoteSync(param.Pass(), status);
-    return;
-  }
-
-  param->drive_metadata.set_md5_checksum(md5_checksum);
-  const FileChange& change = param->remote_change.change;
-  const base::FilePath& temporary_file_path = param->temporary_file.path();
-  const FileSystemURL& url = param->remote_change.url;
-  remote_change_processor_->ApplyRemoteChange(
-      change, temporary_file_path, url,
-      base::Bind(&DriveFileSyncService::DidApplyRemoteChange,
-                 AsWeakPtr(), base::Passed(&param)));
-}
-
-void DriveFileSyncService::DidApplyRemoteChange(
-    scoped_ptr<ProcessRemoteChangeParam> param,
-    SyncStatusCode status) {
-  if (status != SYNC_STATUS_OK) {
-    AbortRemoteSync(param.Pass(), status);
-    return;
-  }
-
-  fileapi::FileSystemURL url = param->remote_change.url;
-  if (param->remote_change.change.IsDelete()) {
-    DeleteMetadataForRemoteSync(param.Pass());
-    return;
-  }
-
-  const DriveMetadata& drive_metadata = param->drive_metadata;
-  param->drive_metadata.set_resource_id(param->remote_change.resource_id);
-  param->drive_metadata.set_conflicted(false);
-  if (param->remote_change.change.IsFile()) {
-    param->drive_metadata.set_type(DriveMetadata::RESOURCE_TYPE_FILE);
-  } else {
-    DCHECK(IsSyncFSDirectoryOperationEnabled());
-    param->drive_metadata.set_type(DriveMetadata::RESOURCE_TYPE_FOLDER);
-  }
-
-  metadata_store_->UpdateEntry(
-      url, drive_metadata,
-      base::Bind(&DriveFileSyncService::CompleteRemoteSync,
-                 AsWeakPtr(), base::Passed(&param)));
-}
-
-void DriveFileSyncService::DeleteMetadataForRemoteSync(
-    scoped_ptr<ProcessRemoteChangeParam> param) {
-  fileapi::FileSystemURL url = param->remote_change.url;
-  metadata_store_->DeleteEntry(
-      url,
-      base::Bind(&DriveFileSyncService::CompleteRemoteSync,
-                 AsWeakPtr(), base::Passed(&param)));
-}
-
-void DriveFileSyncService::CompleteRemoteSync(
-    scoped_ptr<ProcessRemoteChangeParam> param,
-    SyncStatusCode status) {
-  if (status != SYNC_STATUS_OK) {
-    AbortRemoteSync(param.Pass(), status);
-    return;
-  }
-
-  RemoveRemoteChange(param->remote_change.url);
-
-  if (param->drive_metadata.to_be_fetched()) {
-    // Clear |to_be_fetched| flag since we completed fetching the remote change
-    // and applying it to the local file.
-    DCHECK(!param->drive_metadata.conflicted());
-    param->drive_metadata.set_conflicted(false);
-    param->drive_metadata.set_to_be_fetched(false);
-    metadata_store_->UpdateEntry(
-        param->remote_change.url, param->drive_metadata,
-        base::Bind(&EmptyStatusCallback));
-  }
-
-  GURL origin = param->remote_change.url.origin();
-  int64 changestamp = param->remote_change.changestamp;
-  if (changestamp > 0) {
-    DCHECK(metadata_store_->IsIncrementalSyncOrigin(origin));
-    metadata_store_->SetLargestChangeStamp(
-        changestamp,
-        base::Bind(&DriveFileSyncService::FinalizeRemoteSync,
-                   AsWeakPtr(), base::Passed(&param)));
-    return;
-  }
-
-  if (param->drive_metadata.conflicted())
-    status = SYNC_STATUS_HAS_CONFLICT;
-
-  FinalizeRemoteSync(param.Pass(), status);
-}
-
-void DriveFileSyncService::AbortRemoteSync(
-    scoped_ptr<ProcessRemoteChangeParam> param,
-    SyncStatusCode status) {
-  FinalizeRemoteSync(param.Pass(), status);
-}
-
-void DriveFileSyncService::FinalizeRemoteSync(
-    scoped_ptr<ProcessRemoteChangeParam> param,
-    SyncStatusCode status) {
-  // Clear the local changes. If the operation was resolve-to-local, we should
-  // not clear them here since we added the fake local change to sync with the
-  // remote file.
-  if (param->clear_local_changes) {
-    const FileSystemURL& url = param->remote_change.url;
-    param->clear_local_changes = false;
-    remote_change_processor_->ClearLocalChanges(
-        url, base::Bind(&DriveFileSyncService::FinalizeRemoteSync,
-                        AsWeakPtr(), base::Passed(&param), status));
-    return;
-  }
-
-  param->callback.Run(status, param->remote_change.url);
-  if (status == SYNC_STATUS_OK && param->sync_action != SYNC_ACTION_NONE) {
-    NotifyObserversFileStatusChanged(param->remote_change.url,
-                                     SYNC_FILE_STATUS_SYNCED,
-                                     param->sync_action,
-                                     SYNC_DIRECTION_REMOTE_TO_LOCAL);
-  }
-}
-
-void DriveFileSyncService::HandleConflictForRemoteSync(
-    scoped_ptr<ProcessRemoteChangeParam> param,
-    const base::Time& remote_updated_time,
-    SyncFileType remote_file_type,
-    SyncStatusCode status) {
-  if (status != SYNC_STATUS_OK) {
-    AbortRemoteSync(param.Pass(), status);
-    return;
-  }
-  if (!remote_updated_time.is_null())
-    param->remote_change.updated_time = remote_updated_time;
-  DCHECK(param);
-  const FileSystemURL& url = param->remote_change.url;
-  SyncFileMetadata& local_metadata = param->local_metadata;
-  DriveMetadata& drive_metadata = param->drive_metadata;
-  if (conflict_resolution_ == CONFLICT_RESOLUTION_MANUAL) {
-    param->sync_action = SYNC_ACTION_NONE;
-    MarkConflict(url, &drive_metadata,
-                 base::Bind(&DriveFileSyncService::CompleteRemoteSync,
-                            AsWeakPtr(), base::Passed(&param)));
-    return;
-  }
-
-  DCHECK_EQ(CONFLICT_RESOLUTION_LAST_WRITE_WIN, conflict_resolution_);
-  if (param->remote_change.updated_time.is_null()) {
-    // Get remote file time and call this method again.
-    api_util_->GetResourceEntry(
-        param->remote_change.resource_id,
-        base::Bind(
-            &DriveFileSyncService::DidGetRemoteFileMetadataForRemoteUpdatedTime,
-            AsWeakPtr(),
-            base::Bind(&DriveFileSyncService::HandleConflictForRemoteSync,
-                       AsWeakPtr(),
-                       base::Passed(&param))));
-    return;
-  }
-  if (local_metadata.last_modified >= param->remote_change.updated_time) {
-    // Local win case.
-    util::Log(logging::LOG_VERBOSE, FROM_HERE,
-              "Resolving conflict for remote sync: %s: LOCAL WIN",
-              url.DebugString().c_str());
-    ResolveConflictToLocalForRemoteSync(param.Pass());
-    return;
-  }
-  // Remote win case.
-  // Make sure we reset the conflict flag and start over the remote sync
-  // with empty local changes.
-  util::Log(logging::LOG_VERBOSE, FROM_HERE,
-            "Resolving conflict for remote sync: %s: REMOTE WIN",
-            url.DebugString().c_str());
-  drive_metadata.set_conflicted(false);
-  drive_metadata.set_to_be_fetched(false);
-  drive_metadata.set_type(
-      SyncFileTypeToDriveMetadataResourceType(remote_file_type));
-  metadata_store_->UpdateEntry(
-      url, drive_metadata,
-      base::Bind(&DriveFileSyncService::StartOverRemoteSync,
-                 AsWeakPtr(), base::Passed(&param)));
-  return;
-}
-
-void DriveFileSyncService::ResolveConflictToLocalForRemoteSync(
-    scoped_ptr<ProcessRemoteChangeParam> param) {
-  DCHECK(param);
-  const FileSystemURL& url = param->remote_change.url;
-  param->sync_action = SYNC_ACTION_NONE;
-  param->clear_local_changes = false;
-
-  // Re-add a fake local change to resolve it later in next LocalSync.
-  SyncFileType local_file_type = param->local_metadata.file_type;
-  remote_change_processor_->RecordFakeLocalChange(
-      url,
-      FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, local_file_type),
-      base::Bind(&DriveFileSyncService::DidResolveConflictToLocalChange,
-                 AsWeakPtr(), base::Passed(&param)));
-}
-
-void DriveFileSyncService::StartOverRemoteSync(
-    scoped_ptr<ProcessRemoteChangeParam> param,
-    SyncStatusCode status) {
-  DCHECK(param);
-  SyncFileMetadata& local_metadata = param->local_metadata;
-  DidPrepareForProcessRemoteChange(
-      param.Pass(), status, local_metadata, FileChangeList());
-}
-
 bool DriveFileSyncService::AppendRemoteChange(
     const GURL& origin,
     const google_apis::ResourceEntry& entry,
@@ -1427,46 +969,28 @@
     DriveMetadata* drive_metadata,
     const SyncStatusCallback& callback) {
   DCHECK(drive_metadata);
-  if (drive_metadata->resource_id().empty()) {
-    // If the file does not have valid drive_metadata in the metadata store
-    // we must have a pending remote change entry.
-    RemoteChangeHandler::RemoteChange remote_change;
-    const bool has_remote_change =
-        remote_change_handler_.GetChangeForURL(url, &remote_change);
-    DCHECK(has_remote_change);
-    drive_metadata->set_resource_id(remote_change.resource_id);
-    drive_metadata->set_md5_checksum(std::string());
-  }
+  DCHECK(!drive_metadata->resource_id().empty());
   drive_metadata->set_conflicted(true);
   drive_metadata->set_to_be_fetched(false);
-  metadata_store_->UpdateEntry(url, *drive_metadata, callback);
+  metadata_store_->UpdateEntry(
+      url, *drive_metadata, base::Bind(
+          &DriveFileSyncService::NotifyConflict,
+          AsWeakPtr(), url, callback));
+}
+
+void DriveFileSyncService::NotifyConflict(
+    const fileapi::FileSystemURL& url,
+    const SyncStatusCallback& callback,
+    SyncStatusCode status) {
+  if (status != SYNC_STATUS_OK) {
+    callback.Run(status);
+    return;
+  }
   NotifyObserversFileStatusChanged(url,
                                    SYNC_FILE_STATUS_CONFLICTING,
                                    SYNC_ACTION_NONE,
                                    SYNC_DIRECTION_NONE);
-}
-
-void DriveFileSyncService::DidGetRemoteFileMetadataForRemoteUpdatedTime(
-    const UpdatedTimeCallback& callback,
-    google_apis::GDataErrorCode error,
-    scoped_ptr<google_apis::ResourceEntry> entry) {
-  SyncStatusCode status = GDataErrorCodeToSyncStatusCodeWrapper(error);
-  if (status == SYNC_FILE_ERROR_NOT_FOUND) {
-    // Returns with very old (time==0.0) last modified date
-    // so that last-write-win policy will just use the other (local) version.
-    callback.Run(base::Time::FromDoubleT(0.0),
-                 SYNC_FILE_TYPE_UNKNOWN, SYNC_STATUS_OK);
-    return;
-  }
-
-  SyncFileType file_type = SYNC_FILE_TYPE_UNKNOWN;
-  if (entry->is_file())
-    file_type = SYNC_FILE_TYPE_FILE;
-  if (entry->is_folder())
-    file_type = SYNC_FILE_TYPE_DIRECTORY;
-
-  // If |file_type| is unknown, just use the other (local) version.
-  callback.Run(entry->updated_time(), file_type, status);
+  callback.Run(status);
 }
 
 SyncStatusCode DriveFileSyncService::GDataErrorCodeToSyncStatusCodeWrapper(
@@ -1500,9 +1024,7 @@
 }
 
 void DriveFileSyncService::OnNotificationReceived() {
-  util::Log(logging::LOG_INFO,
-            FROM_HERE,
-            "Notification received to check for Google Drive updates");
+  VLOG(2) << "Notification received to check for Google Drive updates";
 
   // Likely indicating the network is enabled again.
   UpdateServiceState(REMOTE_SERVICE_OK, "Got push notification for Drive.");
@@ -1513,10 +1035,7 @@
 }
 
 void DriveFileSyncService::OnPushNotificationEnabled(bool enabled) {
-  const char* status = (enabled ? "enabled" : "disabled");
-  util::Log(logging::LOG_INFO,
-            FROM_HERE,
-            "XMPP Push notification is %s", status);
+  VLOG(2) << "XMPP Push notification is " << (enabled ? "enabled" : "disabled");
 }
 
 void DriveFileSyncService::MaybeScheduleNextTask() {
@@ -1684,7 +1203,7 @@
       continue;
 
     std::string resource_id(
-        google_apis::drive::util::ExtractResourceIdFromUrl((*itr)->href()));
+        ::drive::util::ExtractResourceIdFromUrl((*itr)->href()));
     if (resource_id.empty())
       continue;
 
diff --git a/chrome/browser/sync_file_system/drive_file_sync_service.h b/chrome/browser/sync_file_system/drive_file_sync_service.h
index 70b2013..d892ed4 100644
--- a/chrome/browser/sync_file_system/drive_file_sync_service.h
+++ b/chrome/browser/sync_file_system/drive_file_sync_service.h
@@ -16,19 +16,20 @@
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "base/threading/non_thread_safe.h"
-#include "chrome/browser/google_apis/drive_notification_observer.h"
-#include "chrome/browser/sync_file_system/drive/api_util_interface.h"
+#include "chrome/browser/drive/drive_notification_observer.h"
+#include "chrome/browser/sync_file_system/conflict_resolution_resolver.h"
+#include "chrome/browser/sync_file_system/drive_backend/api_util_interface.h"
 #include "chrome/browser/sync_file_system/drive_metadata_store.h"
 #include "chrome/browser/sync_file_system/local_change_processor.h"
 #include "chrome/browser/sync_file_system/local_sync_operation_resolver.h"
 #include "chrome/browser/sync_file_system/remote_change_handler.h"
 #include "chrome/browser/sync_file_system/remote_file_sync_service.h"
+#include "chrome/browser/sync_file_system/sync_action.h"
+#include "chrome/browser/sync_file_system/sync_direction.h"
 #include "chrome/browser/sync_file_system/sync_file_system.pb.h"
 #include "chrome/browser/sync_file_system/sync_task_manager.h"
 #include "webkit/browser/fileapi/syncable/file_change.h"
-#include "webkit/browser/fileapi/syncable/sync_action.h"
 #include "webkit/browser/fileapi/syncable/sync_callbacks.h"
-#include "webkit/browser/fileapi/syncable/sync_direction.h"
 #include "webkit/browser/fileapi/syncable/sync_status_code.h"
 
 class ExtensionService;
@@ -43,8 +44,9 @@
 
 namespace sync_file_system {
 
-namespace drive {
-class LocalChangeProcessorDelegate;
+namespace drive_backend {
+class LocalSyncDelegate;
+class RemoteSyncDelegate;
 }
 
 class SyncTaskManager;
@@ -53,18 +55,12 @@
 // Owned by SyncFileSystemService (which is a per-profile object).
 class DriveFileSyncService : public RemoteFileSyncService,
                              public LocalChangeProcessor,
-                             public drive::APIUtilObserver,
+                             public drive_backend::APIUtilObserver,
                              public SyncTaskManager::Client,
                              public base::NonThreadSafe,
                              public base::SupportsWeakPtr<DriveFileSyncService>,
-                             public google_apis::DriveNotificationObserver {
+                             public ::drive::DriveNotificationObserver {
  public:
-  enum ConflictResolutionResult {
-    CONFLICT_RESOLUTION_MARK_CONFLICT,
-    CONFLICT_RESOLUTION_LOCAL_WIN,
-    CONFLICT_RESOLUTION_REMOTE_WIN,
-  };
-
   typedef base::Callback<void(const SyncStatusCallback& callback)> Task;
 
   static ConflictResolutionPolicy kDefaultPolicy;
@@ -79,13 +75,14 @@
   static scoped_ptr<DriveFileSyncService> CreateForTesting(
       Profile* profile,
       const base::FilePath& base_dir,
-      scoped_ptr<drive::APIUtilInterface> api_util,
+      scoped_ptr<drive_backend::APIUtilInterface> api_util,
       scoped_ptr<DriveMetadataStore> metadata_store);
 
   // Destroys |sync_service| and passes the ownership of |sync_client| to caller
   // for testing.
-  static scoped_ptr<drive::APIUtilInterface> DestroyAndPassAPIUtilForTesting(
-      scoped_ptr<DriveFileSyncService> sync_service);
+  static scoped_ptr<drive_backend::APIUtilInterface>
+      DestroyAndPassAPIUtilForTesting(
+          scoped_ptr<DriveFileSyncService> sync_service);
 
   // RemoteFileSyncService overrides.
   virtual void AddServiceObserver(Observer* observer) OVERRIDE;
@@ -112,10 +109,11 @@
   virtual bool IsConflicting(const fileapi::FileSystemURL& url) OVERRIDE;
   virtual RemoteServiceState GetCurrentState() const OVERRIDE;
   virtual void GetOriginStatusMap(OriginStatusMap* status_map) OVERRIDE;
-  virtual void GetFileMetadataMap(OriginFileMetadataMap* metadata_map) OVERRIDE;
+  virtual void GetFileMetadataMap(const GURL& origin,
+                                  FileMetadataMap* metadata_map) OVERRIDE;
   virtual void SetSyncEnabled(bool enabled) OVERRIDE;
   virtual SyncStatusCode SetConflictResolutionPolicy(
-      ConflictResolutionPolicy resolution) OVERRIDE;
+      ConflictResolutionPolicy policy) OVERRIDE;
   virtual ConflictResolutionPolicy GetConflictResolutionPolicy() const OVERRIDE;
 
   // LocalChangeProcessor overrides.
@@ -130,7 +128,7 @@
   virtual void OnAuthenticated() OVERRIDE;
   virtual void OnNetworkConnected() OVERRIDE;
 
-  // google_apis::DriveNotificationObserver implementation.
+  // ::drive::DriveNotificationObserver implementation.
   virtual void OnNotificationReceived() OVERRIDE;
   virtual void OnPushNotificationEnabled(bool enabled) OVERRIDE;
 
@@ -147,17 +145,15 @@
 
  private:
   friend class SyncTaskManager;
-  friend class drive::LocalChangeProcessorDelegate;
+  friend class drive_backend::LocalSyncDelegate;
+  friend class drive_backend::RemoteSyncDelegate;
 
-  friend class DriveFileSyncServiceMockTest;
+  friend class DriveFileSyncServiceFakeTest;
   friend class DriveFileSyncServiceSyncTest;
   friend class DriveFileSyncServiceTest;
   struct ApplyLocalChangeParam;
   struct ProcessRemoteChangeParam;
 
-  typedef base::Callback<void(const base::Time& time,
-                              SyncFileType remote_file_type,
-                              SyncStatusCode status)> UpdatedTimeCallback;
   typedef base::Callback<
       void(SyncStatusCode status,
            const std::string& resource_id)> ResourceIdCallback;
@@ -166,11 +162,12 @@
 
   void Initialize(scoped_ptr<SyncTaskManager> task_manager,
                   const SyncStatusCallback& callback);
-  void InitializeForTesting(scoped_ptr<SyncTaskManager> task_manager,
-                            const base::FilePath& base_dir,
-                            scoped_ptr<drive::APIUtilInterface> sync_client,
-                            scoped_ptr<DriveMetadataStore> metadata_store,
-                            const SyncStatusCallback& callback);
+  void InitializeForTesting(
+      scoped_ptr<SyncTaskManager> task_manager,
+      const base::FilePath& base_dir,
+      scoped_ptr<drive_backend::APIUtilInterface> sync_client,
+      scoped_ptr<DriveMetadataStore> metadata_store,
+      const SyncStatusCallback& callback);
 
   void DidInitializeMetadataStore(const SyncStatusCallback& callback,
                                   SyncStatusCode status,
@@ -213,15 +210,6 @@
       const fileapi::FileSystemURL& url,
       const SyncStatusCallback& callback);
 
-  // Local synchronization related methods.
-  ConflictResolutionResult ResolveConflictForLocalSync(
-      SyncFileType local_file_type,
-      const base::Time& local_update_time,
-      SyncFileType remote_file_type,
-      const base::Time& remote_update_time);
-  void DidApplyLocalChange(const SyncStatusCallback& callback,
-                           SyncStatusCode status);
-
   void UpdateRegisteredOrigins();
 
   void StartBatchSync(const SyncStatusCallback& callback);
@@ -249,53 +237,11 @@
       google_apis::GDataErrorCode error,
       scoped_ptr<google_apis::ResourceList> feed);
 
-  // Remote synchronization related methods.
-  void DidPrepareForProcessRemoteChange(
-      scoped_ptr<ProcessRemoteChangeParam> param,
-      SyncStatusCode status,
-      const SyncFileMetadata& metadata,
-      const FileChangeList& changes);
-  void DidResolveConflictToLocalChange(
-      scoped_ptr<ProcessRemoteChangeParam> param,
-      SyncStatusCode status);
-  void DownloadForRemoteSync(
-      scoped_ptr<ProcessRemoteChangeParam> param);
-  void DidGetTemporaryFileForDownload(
-      scoped_ptr<ProcessRemoteChangeParam> param,
-      bool success);
-  void DidDownloadFileForRemoteSync(
-      scoped_ptr<ProcessRemoteChangeParam> param,
-      google_apis::GDataErrorCode error,
-      const std::string& md5_checksum,
-      int64 file_size,
-      const base::Time& updated_time);
-  void DidApplyRemoteChange(
-      scoped_ptr<ProcessRemoteChangeParam> param,
-      SyncStatusCode status);
-  void DidCleanUpForRemoteSync(
-      scoped_ptr<ProcessRemoteChangeParam> param,
-      bool success);
-  void DeleteMetadataForRemoteSync(
-      scoped_ptr<ProcessRemoteChangeParam> param);
-  void CompleteRemoteSync(
-      scoped_ptr<ProcessRemoteChangeParam> param,
-      SyncStatusCode status);
-  void AbortRemoteSync(
-      scoped_ptr<ProcessRemoteChangeParam> param,
-      SyncStatusCode status);
-  void FinalizeRemoteSync(
-      scoped_ptr<ProcessRemoteChangeParam> param,
-      SyncStatusCode status);
-  void HandleConflictForRemoteSync(
-      scoped_ptr<ProcessRemoteChangeParam> param,
-      const base::Time& remote_updated_time,
-      SyncFileType remote_file_change,
-      SyncStatusCode status);
-  void ResolveConflictToLocalForRemoteSync(
-      scoped_ptr<ProcessRemoteChangeParam> param);
-  void StartOverRemoteSync(
-      scoped_ptr<ProcessRemoteChangeParam> param,
-      SyncStatusCode status);
+  void DidProcessRemoteChange(const SyncFileCallback& sync_callback,
+                              const SyncStatusCallback& completion_callback,
+                              SyncStatusCode status);
+  void DidApplyLocalChange(const SyncStatusCallback& callback,
+                           SyncStatusCode status);
 
   // Returns true if |pending_changes_| was updated.
   bool AppendRemoteChange(
@@ -319,14 +265,15 @@
   void RemoveRemoteChange(const fileapi::FileSystemURL& url);
   void MaybeMarkAsIncrementalSyncOrigin(const GURL& origin);
 
+  // TODO(kinuko,tzik): Move this out of DriveFileSyncService.
   void MarkConflict(
       const fileapi::FileSystemURL& url,
       DriveMetadata* drive_metadata,
       const SyncStatusCallback& callback);
-  void DidGetRemoteFileMetadataForRemoteUpdatedTime(
-      const UpdatedTimeCallback& callback,
-      google_apis::GDataErrorCode error,
-      scoped_ptr<google_apis::ResourceEntry> entry);
+  void NotifyConflict(
+      const fileapi::FileSystemURL& url,
+      const SyncStatusCallback& callback,
+      SyncStatusCode status);
 
   // A wrapper implementation to GDataErrorCodeToSyncStatusCode which returns
   // authentication error if the user is not signed in.
@@ -380,13 +327,14 @@
   std::string sync_root_resource_id();
 
   scoped_ptr<DriveMetadataStore> metadata_store_;
-  scoped_ptr<drive::APIUtilInterface> api_util_;
+  scoped_ptr<drive_backend::APIUtilInterface> api_util_;
 
   Profile* profile_;
 
   scoped_ptr<SyncTaskManager> task_manager_;
 
-  scoped_ptr<drive::LocalChangeProcessorDelegate> running_local_sync_task_;
+  scoped_ptr<drive_backend::LocalSyncDelegate> running_local_sync_task_;
+  scoped_ptr<drive_backend::RemoteSyncDelegate> running_remote_sync_task_;
 
   // The current remote service state. This does NOT reflect the
   // sync_enabled_ flag, while GetCurrentState() DOES reflect the flag
@@ -424,7 +372,7 @@
 
   google_apis::GDataErrorCode last_gdata_error_;
 
-  ConflictResolutionPolicy conflict_resolution_;
+  ConflictResolutionResolver conflict_resolution_resolver_;
 
   DISALLOW_COPY_AND_ASSIGN(DriveFileSyncService);
 };
diff --git a/chrome/browser/sync_file_system/drive_file_sync_service_fake_unittest.cc b/chrome/browser/sync_file_system/drive_file_sync_service_fake_unittest.cc
new file mode 100644
index 0000000..4eb71c7
--- /dev/null
+++ b/chrome/browser/sync_file_system/drive_file_sync_service_fake_unittest.cc
@@ -0,0 +1,844 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/sync_file_system/drive_file_sync_service.h"
+
+#include <utility>
+
+#include "base/command_line.h"
+#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "chrome/browser/drive/drive_uploader.h"
+#include "chrome/browser/drive/fake_drive_service.h"
+#include "chrome/browser/extensions/test_extension_service.h"
+#include "chrome/browser/extensions/test_extension_system.h"
+#include "chrome/browser/google_apis/drive_api_parser.h"
+#include "chrome/browser/google_apis/gdata_errorcode.h"
+#include "chrome/browser/google_apis/gdata_wapi_parser.h"
+#include "chrome/browser/google_apis/test_util.h"
+#include "chrome/browser/sync_file_system/drive_backend/api_util.h"
+#include "chrome/browser/sync_file_system/drive_backend/fake_drive_service_helper.h"
+#include "chrome/browser/sync_file_system/drive_file_sync_util.h"
+#include "chrome/browser/sync_file_system/drive_metadata_store.h"
+#include "chrome/browser/sync_file_system/file_status_observer.h"
+#include "chrome/browser/sync_file_system/mock_remote_change_processor.h"
+#include "chrome/browser/sync_file_system/sync_direction.h"
+#include "chrome/browser/sync_file_system/sync_file_system.pb.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/extension_builder.h"
+#include "chrome/test/base/testing_profile.h"
+#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "extensions/common/id_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/browser/fileapi/syncable/sync_file_metadata.h"
+#include "webkit/browser/fileapi/syncable/syncable_file_system_util.h"
+#include "webkit/common/fileapi/file_system_util.h"
+
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/login/user_manager.h"
+#include "chrome/browser/chromeos/settings/cros_settings.h"
+#include "chrome/browser/chromeos/settings/device_settings_service.h"
+#endif
+
+#define FPL(x) FILE_PATH_LITERAL(x)
+
+using ::testing::StrictMock;
+using ::testing::_;
+
+using ::drive::DriveServiceInterface;
+using ::drive::DriveUploaderInterface;
+using ::drive::FakeDriveService;
+
+using extensions::Extension;
+using extensions::DictionaryBuilder;
+using google_apis::GDataErrorCode;
+using google_apis::ResourceEntry;
+
+namespace sync_file_system {
+
+using drive_backend::APIUtil;
+using drive_backend::APIUtilInterface;
+using drive_backend::FakeDriveServiceHelper;
+
+namespace {
+
+const char kExtensionName1[] = "example1";
+const char kExtensionName2[] = "example2";
+
+void DidInitialize(bool* done, SyncStatusCode status, bool created) {
+  EXPECT_FALSE(*done);
+  *done = true;
+  EXPECT_EQ(SYNC_STATUS_OK, status);
+  EXPECT_TRUE(created);
+}
+
+void DidProcessRemoteChange(SyncStatusCode* status_out,
+                            fileapi::FileSystemURL* url_out,
+                            SyncStatusCode status,
+                            const fileapi::FileSystemURL& url) {
+  ASSERT_TRUE(status_out);
+  ASSERT_TRUE(url_out);
+  *status_out = status;
+  *url_out = url;
+}
+
+void ExpectEqStatus(bool* done,
+                    SyncStatusCode expected,
+                    SyncStatusCode actual) {
+  EXPECT_FALSE(*done);
+  *done = true;
+  EXPECT_EQ(expected, actual);
+}
+
+// Mocks adding an installed extension to ExtensionService.
+scoped_refptr<const extensions::Extension> AddTestExtension(
+    ExtensionService* extension_service,
+    const base::FilePath::StringType& extension_name) {
+  std::string id = extensions::id_util::GenerateIdForPath(
+      base::FilePath(extension_name));
+
+  scoped_refptr<const Extension> extension =
+      extensions::ExtensionBuilder().SetManifest(
+          DictionaryBuilder()
+            .Set("name", extension_name)
+            .Set("version", "1.0"))
+          .SetID(id)
+      .Build();
+  extension_service->AddExtension(extension.get());
+  return extension;
+}
+
+// Converts extension_name to extension ID.
+std::string ExtensionNameToId(const std::string& extension_name) {
+  base::FilePath path = base::FilePath::FromUTF8Unsafe(extension_name);
+  return extensions::id_util::GenerateIdForPath(path);
+}
+
+// Converts extension_name to GURL version.
+GURL ExtensionNameToGURL(const std::string& extension_name) {
+  return extensions::Extension::GetBaseURLFromExtensionId(
+      ExtensionNameToId(extension_name));
+}
+
+ACTION(InvokeCompletionCallback) {
+  base::MessageLoopProxy::current()->PostTask(FROM_HERE, arg1);
+}
+
+ACTION(PrepareForRemoteChange_Busy) {
+  base::MessageLoopProxy::current()->PostTask(
+      FROM_HERE,
+      base::Bind(arg1,
+                 SYNC_STATUS_FILE_BUSY,
+                 SyncFileMetadata(),
+                 FileChangeList()));
+}
+
+ACTION(PrepareForRemoteChange_NotFound) {
+  base::MessageLoopProxy::current()->PostTask(
+      FROM_HERE,
+      base::Bind(arg1,
+                 SYNC_STATUS_OK,
+                 SyncFileMetadata(SYNC_FILE_TYPE_UNKNOWN, 0, base::Time()),
+                 FileChangeList()));
+}
+
+ACTION(PrepareForRemoteChange_NotModified) {
+  base::MessageLoopProxy::current()->PostTask(
+      FROM_HERE,
+      base::Bind(arg1,
+                 SYNC_STATUS_OK,
+                 SyncFileMetadata(SYNC_FILE_TYPE_FILE, 0, base::Time()),
+                 FileChangeList()));
+}
+
+ACTION(InvokeDidApplyRemoteChange) {
+  base::MessageLoopProxy::current()->PostTask(
+      FROM_HERE, base::Bind(arg3, SYNC_STATUS_OK));
+}
+
+}  // namespace
+
+class MockFileStatusObserver: public FileStatusObserver {
+ public:
+  MockFileStatusObserver() {}
+  virtual ~MockFileStatusObserver() {}
+
+  MOCK_METHOD4(OnFileStatusChanged,
+               void(const fileapi::FileSystemURL& url,
+                    SyncFileStatus sync_status,
+                    SyncAction action_taken,
+                    SyncDirection direction));
+};
+
+class DriveFileSyncServiceFakeTest : public testing::Test {
+ public:
+  DriveFileSyncServiceFakeTest()
+      : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
+        fake_drive_service_(NULL) {
+  }
+
+  virtual void SetUp() OVERRIDE {
+    profile_.reset(new TestingProfile());
+
+    // Add TestExtensionSystem with registered ExtensionIds used in tests.
+    extensions::TestExtensionSystem* extension_system(
+        static_cast<extensions::TestExtensionSystem*>(
+            extensions::ExtensionSystem::Get(profile_.get())));
+    extension_system->CreateExtensionService(
+        CommandLine::ForCurrentProcess(), base::FilePath(), false);
+    extension_service_ = extension_system->Get(
+        profile_.get())->extension_service();
+
+    AddTestExtension(extension_service_, FPL("example1"));
+    AddTestExtension(extension_service_, FPL("example2"));
+
+    RegisterSyncableFileSystem();
+
+    fake_drive_service_ = new FakeDriveService;
+    DriveUploaderInterface* drive_uploader = new ::drive::DriveUploader(
+        fake_drive_service_, base::MessageLoopProxy::current().get());
+
+    fake_drive_helper_.reset(new FakeDriveServiceHelper(
+        fake_drive_service_, drive_uploader));
+
+    api_util_ = APIUtil::CreateForTesting(
+        profile_.get(),
+        scoped_ptr<DriveServiceInterface>(fake_drive_service_),
+        scoped_ptr<DriveUploaderInterface>(drive_uploader)).Pass();
+    metadata_store_.reset(new DriveMetadataStore(
+        fake_drive_helper_->base_dir_path(),
+        base::MessageLoopProxy::current().get()));
+
+    bool done = false;
+    metadata_store_->Initialize(base::Bind(&DidInitialize, &done));
+    base::MessageLoop::current()->RunUntilIdle();
+    EXPECT_TRUE(done);
+
+    fake_drive_service_->LoadResourceListForWapi(
+        "sync_file_system/initialize.json");
+    fake_drive_service()->LoadAccountMetadataForWapi(
+        "sync_file_system/account_metadata.json");
+
+    // Setup the sync root directory.
+    EXPECT_EQ(google_apis::HTTP_CREATED,
+              fake_drive_helper_->AddOrphanedFolder(
+                  APIUtil::GetSyncRootDirectoryName(),
+                  &sync_root_resource_id_));
+    metadata_store()->SetSyncRootDirectory(sync_root_resource_id_);
+  }
+
+  void SetUpDriveSyncService(bool enabled) {
+    sync_service_ = DriveFileSyncService::CreateForTesting(
+        profile_.get(),
+        fake_drive_helper_->base_dir_path(),
+        api_util_.PassAs<APIUtilInterface>(),
+        metadata_store_.Pass()).Pass();
+    sync_service_->AddFileStatusObserver(&mock_file_status_observer_);
+    sync_service_->SetRemoteChangeProcessor(mock_remote_processor());
+    sync_service_->SetSyncEnabled(enabled);
+    base::MessageLoop::current()->RunUntilIdle();
+  }
+
+  virtual void TearDown() OVERRIDE {
+    if (sync_service_) {
+      sync_service_.reset();
+    }
+
+    metadata_store_.reset();
+    api_util_.reset();
+    fake_drive_service_ = NULL;
+
+    RevokeSyncableFileSystem();
+
+    extension_service_ = NULL;
+    profile_.reset();
+    base::MessageLoop::current()->RunUntilIdle();
+  }
+
+  void SetSyncEnabled(bool enabled) {
+    sync_service_->SetSyncEnabled(enabled);
+  }
+
+ protected:
+  void EnableExtension(const std::string& extension_id) {
+    extension_service_->EnableExtension(extension_id);
+  }
+
+  void DisableExtension(const std::string& extension_id) {
+    extension_service_->DisableExtension(
+        extension_id, extensions::Extension::DISABLE_NONE);
+  }
+
+  void UninstallExtension(const std::string& extension_id) {
+    // Call UnloadExtension instead of UninstallExtension since it does
+    // unnecessary cleanup (e.g. deleting extension data) and emits warnings.
+    extension_service_->UnloadExtension(
+        extension_id, extension_misc::UNLOAD_REASON_UNINSTALL);
+  }
+
+  void UpdateRegisteredOrigins() {
+    sync_service_->UpdateRegisteredOrigins();
+    // Wait for completion of uninstalling origin.
+    base::MessageLoop::current()->RunUntilIdle();
+  }
+
+  void VerifySizeOfRegisteredOrigins(size_t b_size,
+                                     size_t i_size,
+                                     size_t d_size) {
+    EXPECT_EQ(b_size, pending_batch_sync_origins()->size());
+    EXPECT_EQ(i_size, metadata_store()->incremental_sync_origins().size());
+    EXPECT_EQ(d_size, metadata_store()->disabled_origins().size());
+  }
+
+  APIUtilInterface* api_util() {
+    if (api_util_)
+      return api_util_.get();
+    return sync_service_->api_util_.get();
+  }
+
+  DriveMetadataStore* metadata_store() {
+    if (metadata_store_)
+      return metadata_store_.get();
+    return sync_service_->metadata_store_.get();
+  }
+
+  FakeDriveService* fake_drive_service() {
+    return fake_drive_service_;
+  }
+
+  StrictMock<MockFileStatusObserver>* mock_file_status_observer() {
+    return &mock_file_status_observer_;
+  }
+
+  StrictMock<MockRemoteChangeProcessor>* mock_remote_processor() {
+    return &mock_remote_processor_;
+  }
+
+  DriveFileSyncService* sync_service() { return sync_service_.get(); }
+  std::map<GURL, std::string>* pending_batch_sync_origins() {
+    return &(sync_service()->pending_batch_sync_origins_);
+  }
+
+  const RemoteChangeHandler& remote_change_handler() const {
+    return sync_service_->remote_change_handler_;
+  }
+
+  fileapi::FileSystemURL CreateURL(const GURL& origin,
+                                   const std::string& filename) {
+    return CreateSyncableFileSystemURL(
+        origin, base::FilePath::FromUTF8Unsafe(filename));
+  }
+
+  void ProcessRemoteChange(SyncStatusCode expected_status,
+                           const fileapi::FileSystemURL& expected_url,
+                           SyncFileStatus expected_sync_file_status,
+                           SyncAction expected_sync_action,
+                           SyncDirection expected_sync_direction) {
+    SyncStatusCode actual_status = SYNC_STATUS_UNKNOWN;
+    fileapi::FileSystemURL actual_url;
+
+    if (expected_sync_file_status != SYNC_FILE_STATUS_UNKNOWN) {
+      EXPECT_CALL(*mock_file_status_observer(),
+                  OnFileStatusChanged(expected_url,
+                                      expected_sync_file_status,
+                                      expected_sync_action,
+                                      expected_sync_direction))
+          .Times(1);
+    }
+
+    sync_service_->ProcessRemoteChange(
+        base::Bind(&DidProcessRemoteChange, &actual_status, &actual_url));
+    base::MessageLoop::current()->RunUntilIdle();
+
+    EXPECT_EQ(expected_status, actual_status);
+    EXPECT_EQ(expected_url, actual_url);
+  }
+
+  bool AppendIncrementalRemoteChangeByResourceId(
+      const std::string& resource_id,
+      const GURL& origin) {
+    scoped_ptr<ResourceEntry> entry;
+    EXPECT_EQ(google_apis::HTTP_SUCCESS,
+              fake_drive_helper_->GetResourceEntry(resource_id, &entry));
+    return sync_service_->AppendRemoteChange(origin, *entry, 12345);
+  }
+
+  bool AppendIncrementalRemoteChange(
+      const GURL& origin,
+      const base::FilePath& path,
+      bool is_deleted,
+      const std::string& resource_id,
+      int64 changestamp,
+      const std::string& remote_file_md5) {
+    return sync_service_->AppendRemoteChangeInternal(
+        origin, path, is_deleted, resource_id,
+        changestamp, remote_file_md5, base::Time(),
+        SYNC_FILE_TYPE_FILE);
+  }
+
+  std::string SetUpOriginRootDirectory(const char* extension_name) {
+    EXPECT_TRUE(!sync_root_resource_id_.empty());
+
+    std::string origin_root_resource_id;
+    EXPECT_EQ(google_apis::HTTP_CREATED,
+              fake_drive_helper_->AddFolder(
+                  sync_root_resource_id_,
+                  ExtensionNameToId(extension_name),
+                  &origin_root_resource_id));
+
+    metadata_store()->AddIncrementalSyncOrigin(
+        ExtensionNameToGURL(extension_name), origin_root_resource_id);
+    return origin_root_resource_id;
+  }
+
+  void TestRegisterNewOrigin();
+  void TestRegisterExistingOrigin();
+  void TestRegisterOriginWithSyncDisabled();
+  void TestUnregisterOrigin();
+  void TestUpdateRegisteredOrigins();
+  void TestRemoteChange_NoChange();
+  void TestRemoteChange_Busy();
+  void TestRemoteChange_NewFile();
+  void TestRemoteChange_UpdateFile();
+  void TestRemoteChange_Override();
+  void TestRemoteChange_Folder();
+
+ private:
+  content::TestBrowserThreadBundle thread_bundle_;
+
+  scoped_ptr<TestingProfile> profile_;
+
+  std::string sync_root_resource_id_;
+
+#if defined OS_CHROMEOS
+  chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
+  chromeos::ScopedTestCrosSettings test_cros_settings_;
+  chromeos::ScopedTestUserManager test_user_manager_;
+#endif
+
+  scoped_ptr<DriveFileSyncService> sync_service_;
+
+  // Not owned.
+  ExtensionService* extension_service_;
+
+  FakeDriveService* fake_drive_service_;
+  scoped_ptr<FakeDriveServiceHelper> fake_drive_helper_;
+
+  StrictMock<MockFileStatusObserver> mock_file_status_observer_;
+  StrictMock<MockRemoteChangeProcessor> mock_remote_processor_;
+
+  scoped_ptr<APIUtil> api_util_;
+  scoped_ptr<DriveMetadataStore> metadata_store_;
+
+  DISALLOW_COPY_AND_ASSIGN(DriveFileSyncServiceFakeTest);
+};
+
+#if !defined(OS_ANDROID)
+
+void DriveFileSyncServiceFakeTest::TestRegisterNewOrigin() {
+  SetUpDriveSyncService(true);
+  bool done = false;
+  sync_service()->RegisterOriginForTrackingChanges(
+      ExtensionNameToGURL(kExtensionName1),
+      base::Bind(&ExpectEqStatus, &done, SYNC_STATUS_OK));
+  base::MessageLoop::current()->RunUntilIdle();
+  EXPECT_TRUE(done);
+
+  VerifySizeOfRegisteredOrigins(0u, 1u, 0u);
+  EXPECT_TRUE(!remote_change_handler().HasChanges());
+}
+
+void DriveFileSyncServiceFakeTest::TestRegisterExistingOrigin() {
+  const std::string origin_resource_id =
+      SetUpOriginRootDirectory(kExtensionName1);
+
+  std::string file_id;
+  EXPECT_EQ(google_apis::HTTP_SUCCESS,
+            fake_drive_helper_->AddFile(
+                origin_resource_id, "1.txt", "data1", &file_id));
+  EXPECT_EQ(google_apis::HTTP_SUCCESS,
+            fake_drive_helper_->AddFile(
+                origin_resource_id, "2.txt", "data2", &file_id));
+  EXPECT_EQ(google_apis::HTTP_SUCCESS,
+            fake_drive_helper_->AddFile(
+                origin_resource_id, "3.txt", "data3", &file_id));
+
+  SetUpDriveSyncService(true);
+
+  bool done = false;
+  sync_service()->RegisterOriginForTrackingChanges(
+      ExtensionNameToGURL(kExtensionName1),
+      base::Bind(&ExpectEqStatus, &done, SYNC_STATUS_OK));
+  base::MessageLoop::current()->RunUntilIdle();
+  EXPECT_TRUE(done);
+
+  // The origin should be registered as an incremental sync origin.
+  VerifySizeOfRegisteredOrigins(0u, 1u, 0u);
+
+  // There are 3 items to sync.
+  EXPECT_EQ(3u, remote_change_handler().ChangesSize());
+}
+
+void DriveFileSyncServiceFakeTest::TestRegisterOriginWithSyncDisabled() {
+  // Usually the sync service starts here, but since we're setting up a drive
+  // service with sync disabled sync doesn't start (while register origin should
+  // still return OK).
+  SetUpDriveSyncService(false);
+
+  bool done = false;
+  sync_service()->RegisterOriginForTrackingChanges(
+      ExtensionNameToGURL(kExtensionName1),
+      base::Bind(&ExpectEqStatus, &done, SYNC_STATUS_OK));
+  base::MessageLoop::current()->RunUntilIdle();
+  EXPECT_TRUE(done);
+
+  // We must not have started batch sync for the newly registered origin,
+  // so it should still be in the batch_sync_origins.
+  VerifySizeOfRegisteredOrigins(1u, 0u, 0u);
+  EXPECT_TRUE(!remote_change_handler().HasChanges());
+}
+
+void DriveFileSyncServiceFakeTest::TestUnregisterOrigin() {
+  SetUpOriginRootDirectory(kExtensionName1);
+  SetUpOriginRootDirectory(kExtensionName2);
+
+  SetUpDriveSyncService(true);
+
+  VerifySizeOfRegisteredOrigins(0u, 2u, 0u);
+  EXPECT_EQ(0u, remote_change_handler().ChangesSize());
+
+  bool done = false;
+  sync_service()->UnregisterOriginForTrackingChanges(
+      ExtensionNameToGURL(kExtensionName1),
+      base::Bind(&ExpectEqStatus, &done, SYNC_STATUS_OK));
+  base::MessageLoop::current()->RunUntilIdle();
+  EXPECT_TRUE(done);
+
+  VerifySizeOfRegisteredOrigins(0u, 1u, 0u);
+  EXPECT_TRUE(!remote_change_handler().HasChanges());
+}
+
+void DriveFileSyncServiceFakeTest::TestUpdateRegisteredOrigins() {
+  SetUpOriginRootDirectory(kExtensionName1);
+  SetUpOriginRootDirectory(kExtensionName2);
+  SetUpDriveSyncService(true);
+
+  // [1] Both extensions and origins are enabled. Nothing to do.
+  VerifySizeOfRegisteredOrigins(0u, 2u, 0u);
+  UpdateRegisteredOrigins();
+  VerifySizeOfRegisteredOrigins(0u, 2u, 0u);
+
+  // [2] Extension 1 should move to disabled list.
+  DisableExtension(ExtensionNameToId(kExtensionName1));
+  UpdateRegisteredOrigins();
+  VerifySizeOfRegisteredOrigins(0u, 1u, 1u);
+
+  // [3] Make sure that state remains the same, nothing should change.
+  UpdateRegisteredOrigins();
+  VerifySizeOfRegisteredOrigins(0u, 1u, 1u);
+
+  // [4] Uninstall Extension 2.
+  UninstallExtension(ExtensionNameToId(kExtensionName2));
+  UpdateRegisteredOrigins();
+  VerifySizeOfRegisteredOrigins(0u, 0u, 1u);
+
+  // [5] Re-enable Extension 1. It moves back to batch and not to incremental.
+  EnableExtension(ExtensionNameToId(kExtensionName1));
+  UpdateRegisteredOrigins();
+  VerifySizeOfRegisteredOrigins(1u, 0u, 0u);
+}
+
+void DriveFileSyncServiceFakeTest::TestRemoteChange_NoChange() {
+  SetUpDriveSyncService(true);
+
+  ProcessRemoteChange(SYNC_STATUS_NO_CHANGE_TO_SYNC,
+                      fileapi::FileSystemURL(),
+                      SYNC_FILE_STATUS_UNKNOWN,
+                      SYNC_ACTION_NONE,
+                      SYNC_DIRECTION_NONE);
+  VerifySizeOfRegisteredOrigins(0u, 0u, 0u);
+  EXPECT_TRUE(!remote_change_handler().HasChanges());
+}
+
+void DriveFileSyncServiceFakeTest::TestRemoteChange_Busy() {
+  const char kFileName[] = "File 1.txt";
+  const GURL origin = ExtensionNameToGURL(kExtensionName1);
+
+  const std::string origin_resource_id =
+      SetUpOriginRootDirectory(kExtensionName1);
+
+  EXPECT_CALL(*mock_remote_processor(),
+              PrepareForProcessRemoteChange(CreateURL(origin, kFileName), _))
+      .WillOnce(PrepareForRemoteChange_Busy());
+  EXPECT_CALL(*mock_remote_processor(),
+              ClearLocalChanges(CreateURL(origin, kFileName), _))
+      .WillOnce(InvokeCompletionCallback());
+
+  SetUpDriveSyncService(true);
+
+  std::string resource_id;
+  EXPECT_EQ(google_apis::HTTP_SUCCESS,
+            fake_drive_helper_->AddFile(
+                origin_resource_id, kFileName, "test data", &resource_id));
+  EXPECT_TRUE(AppendIncrementalRemoteChangeByResourceId(resource_id, origin));
+
+  ProcessRemoteChange(SYNC_STATUS_FILE_BUSY,
+                      CreateURL(origin, kFileName),
+                      SYNC_FILE_STATUS_UNKNOWN,
+                      SYNC_ACTION_NONE,
+                      SYNC_DIRECTION_NONE);
+}
+
+void DriveFileSyncServiceFakeTest::TestRemoteChange_NewFile() {
+  const char kFileName[] = "File 1.txt";
+  const GURL origin = ExtensionNameToGURL(kExtensionName1);
+
+  const std::string origin_resource_id =
+      SetUpOriginRootDirectory(kExtensionName1);
+
+  EXPECT_CALL(*mock_remote_processor(),
+              PrepareForProcessRemoteChange(CreateURL(origin, kFileName), _))
+      .WillOnce(PrepareForRemoteChange_NotFound());
+  EXPECT_CALL(*mock_remote_processor(),
+              ClearLocalChanges(CreateURL(origin, kFileName), _))
+      .WillOnce(InvokeCompletionCallback());
+
+  EXPECT_CALL(*mock_remote_processor(),
+              ApplyRemoteChange(_, _, CreateURL(origin, kFileName), _))
+      .WillOnce(InvokeDidApplyRemoteChange());
+
+  SetUpDriveSyncService(true);
+
+  std::string resource_id;
+  EXPECT_EQ(google_apis::HTTP_SUCCESS,
+            fake_drive_helper_->AddFile(
+                origin_resource_id, kFileName, "test data", &resource_id));
+  EXPECT_TRUE(AppendIncrementalRemoteChangeByResourceId(resource_id, origin));
+
+  ProcessRemoteChange(SYNC_STATUS_OK,
+                      CreateURL(origin, kFileName),
+                      SYNC_FILE_STATUS_SYNCED,
+                      SYNC_ACTION_ADDED,
+                      SYNC_DIRECTION_REMOTE_TO_LOCAL);
+}
+
+void DriveFileSyncServiceFakeTest::TestRemoteChange_UpdateFile() {
+  const char kFileName[] = "File 1.txt";
+  const GURL origin = ExtensionNameToGURL(kExtensionName1);
+
+  const std::string origin_resource_id =
+      SetUpOriginRootDirectory(kExtensionName1);
+
+  EXPECT_CALL(*mock_remote_processor(),
+              PrepareForProcessRemoteChange(CreateURL(origin, kFileName), _))
+      .WillOnce(PrepareForRemoteChange_NotModified());
+  EXPECT_CALL(*mock_remote_processor(),
+              ClearLocalChanges(CreateURL(origin, kFileName), _))
+      .WillOnce(InvokeCompletionCallback());
+
+  EXPECT_CALL(*mock_remote_processor(),
+              ApplyRemoteChange(_, _, CreateURL(origin, kFileName), _))
+      .WillOnce(InvokeDidApplyRemoteChange());
+
+  SetUpDriveSyncService(true);
+
+  std::string resource_id;
+  EXPECT_EQ(google_apis::HTTP_SUCCESS,
+            fake_drive_helper_->AddFile(
+                origin_resource_id, kFileName, "test data", &resource_id));
+  EXPECT_TRUE(AppendIncrementalRemoteChangeByResourceId(resource_id, origin));
+
+  ProcessRemoteChange(SYNC_STATUS_OK,
+                      CreateURL(origin, kFileName),
+                      SYNC_FILE_STATUS_SYNCED,
+                      SYNC_ACTION_UPDATED,
+                      SYNC_DIRECTION_REMOTE_TO_LOCAL);
+}
+
+void DriveFileSyncServiceFakeTest::TestRemoteChange_Override() {
+  const base::FilePath kFilePath(FPL("File 1.txt"));
+  const std::string kFileResourceId("file:2_file_resource_id");
+  const std::string kFileResourceId2("file:2_file_resource_id_2");
+  const GURL origin = ExtensionNameToGURL(kExtensionName1);
+
+  SetUpOriginRootDirectory(kExtensionName1);
+  SetUpDriveSyncService(true);
+
+  EXPECT_TRUE(AppendIncrementalRemoteChange(
+      origin, kFilePath, false /* is_deleted */,
+      kFileResourceId, 2, "remote_file_md5"));
+
+  // Expect to drop this change since there is another newer change on the
+  // queue.
+  EXPECT_FALSE(AppendIncrementalRemoteChange(
+      origin, kFilePath, false /* is_deleted */,
+      kFileResourceId, 1, "remote_file_md5_2"));
+
+  // Expect to drop this change since it has the same md5 with the previous one.
+  EXPECT_FALSE(AppendIncrementalRemoteChange(
+      origin, kFilePath, false /* is_deleted */,
+      kFileResourceId, 4, "remote_file_md5"));
+
+  // This should not cause browser crash.
+  EXPECT_FALSE(AppendIncrementalRemoteChange(
+      origin, kFilePath, false /* is_deleted */,
+      kFileResourceId, 4, "remote_file_md5"));
+
+  // Expect to drop these changes since they have different resource IDs with
+  // the previous ones.
+  EXPECT_FALSE(AppendIncrementalRemoteChange(
+      origin, kFilePath, false /* is_deleted */,
+      kFileResourceId2, 5, "updated_file_md5"));
+  EXPECT_FALSE(AppendIncrementalRemoteChange(
+      origin, kFilePath, true /* is_deleted */,
+      kFileResourceId2, 5, "deleted_file_md5"));
+
+  // Push delete change.
+  EXPECT_TRUE(AppendIncrementalRemoteChange(
+      origin, kFilePath, true /* is_deleted */,
+      kFileResourceId, 6, "deleted_file_md5"));
+
+  // Expect to drop this delete change since it has a different resource ID with
+  // the previous one.
+  EXPECT_FALSE(AppendIncrementalRemoteChange(
+      origin, kFilePath, true /* is_deleted */,
+      kFileResourceId2, 7, "deleted_file_md5"));
+
+  // Expect not to drop this change even if it has a different resource ID with
+  // the previous one.
+  EXPECT_TRUE(AppendIncrementalRemoteChange(
+      origin, kFilePath, false /* is_deleted */,
+      kFileResourceId2, 8, "updated_file_md5"));
+}
+
+void DriveFileSyncServiceFakeTest::TestRemoteChange_Folder() {
+  const std::string origin_resource_id =
+      SetUpOriginRootDirectory(kExtensionName1);
+  SetUpDriveSyncService(true);
+
+  std::string resource_id;
+  EXPECT_EQ(google_apis::HTTP_CREATED,
+            fake_drive_helper_->AddFolder(
+                origin_resource_id, "test_dir", &resource_id));
+
+  // Expect to drop this change for file.
+  EXPECT_FALSE(AppendIncrementalRemoteChangeByResourceId(
+      resource_id, ExtensionNameToGURL(kExtensionName1)));
+}
+
+TEST_F(DriveFileSyncServiceFakeTest, RegisterNewOrigin) {
+  ASSERT_FALSE(IsDriveAPIDisabled());
+  TestRegisterNewOrigin();
+}
+
+TEST_F(DriveFileSyncServiceFakeTest, RegisterNewOrigin_WAPI) {
+  ScopedDisableDriveAPI disable_drive_api;
+  TestRegisterNewOrigin();
+}
+
+TEST_F(DriveFileSyncServiceFakeTest, RegisterExistingOrigin) {
+  ASSERT_FALSE(IsDriveAPIDisabled());
+  TestRegisterExistingOrigin();
+}
+
+TEST_F(DriveFileSyncServiceFakeTest, RegisterExistingOrigin_WAPI) {
+  ScopedDisableDriveAPI disable_drive_api;
+  TestRegisterExistingOrigin();
+}
+
+TEST_F(DriveFileSyncServiceFakeTest, RegisterOriginWithSyncDisabled) {
+  ASSERT_FALSE(IsDriveAPIDisabled());
+  TestRegisterOriginWithSyncDisabled();
+}
+
+TEST_F(DriveFileSyncServiceFakeTest, RegisterOriginWithSyncDisabled_WAPI) {
+  ScopedDisableDriveAPI disable_drive_api;
+  TestRegisterOriginWithSyncDisabled();
+}
+
+TEST_F(DriveFileSyncServiceFakeTest, UnregisterOrigin) {
+  ASSERT_FALSE(IsDriveAPIDisabled());
+  TestUnregisterOrigin();
+}
+
+TEST_F(DriveFileSyncServiceFakeTest, UnregisterOrigin_WAPI) {
+  ScopedDisableDriveAPI disable_drive_api;
+  TestUnregisterOrigin();
+}
+
+TEST_F(DriveFileSyncServiceFakeTest, UpdateRegisteredOrigins) {
+  ASSERT_FALSE(IsDriveAPIDisabled());
+  TestUpdateRegisteredOrigins();
+}
+
+TEST_F(DriveFileSyncServiceFakeTest, UpdateRegisteredOrigins_WAPI) {
+  ScopedDisableDriveAPI disable_drive_api;
+  TestUpdateRegisteredOrigins();
+}
+
+TEST_F(DriveFileSyncServiceFakeTest, RemoteChange_NoChange) {
+  ASSERT_FALSE(IsDriveAPIDisabled());
+  TestRemoteChange_NoChange();
+}
+
+TEST_F(DriveFileSyncServiceFakeTest, RemoteChange_NoChange_WAPI) {
+  ScopedDisableDriveAPI disable_drive_api;
+  TestRemoteChange_NoChange();
+}
+
+TEST_F(DriveFileSyncServiceFakeTest, RemoteChange_Busy) {
+  ASSERT_FALSE(IsDriveAPIDisabled());
+  TestRemoteChange_Busy();
+}
+
+TEST_F(DriveFileSyncServiceFakeTest, RemoteChange_Busy_WAPI) {
+  ScopedDisableDriveAPI disable_drive_api;
+  TestRemoteChange_Busy();
+}
+
+TEST_F(DriveFileSyncServiceFakeTest, RemoteChange_NewFile) {
+  ASSERT_FALSE(IsDriveAPIDisabled());
+  TestRemoteChange_NewFile();
+}
+
+TEST_F(DriveFileSyncServiceFakeTest, RemoteChange_NewFile_WAPI) {
+  ScopedDisableDriveAPI disable_drive_api;
+  TestRemoteChange_NewFile();
+}
+
+TEST_F(DriveFileSyncServiceFakeTest, RemoteChange_UpdateFile) {
+  ASSERT_FALSE(IsDriveAPIDisabled());
+  TestRemoteChange_UpdateFile();
+}
+
+TEST_F(DriveFileSyncServiceFakeTest, RemoteChange_UpdateFile_WAPI) {
+  ScopedDisableDriveAPI disable_drive_api;
+  TestRemoteChange_UpdateFile();
+}
+
+TEST_F(DriveFileSyncServiceFakeTest, RemoteChange_Override) {
+  ASSERT_FALSE(IsDriveAPIDisabled());
+  TestRemoteChange_Override();
+}
+
+TEST_F(DriveFileSyncServiceFakeTest, RemoteChange_Override_WAPI) {
+  ScopedDisableDriveAPI disable_drive_api;
+  TestRemoteChange_Override();
+}
+
+TEST_F(DriveFileSyncServiceFakeTest, RemoteChange_Folder) {
+  ASSERT_FALSE(IsDriveAPIDisabled());
+  TestRemoteChange_Folder();
+}
+
+TEST_F(DriveFileSyncServiceFakeTest, RemoteChange_Folder_WAPI) {
+  ScopedDisableDriveAPI disable_drive_api;
+  TestRemoteChange_Folder();
+}
+
+#endif  // !defined(OS_ANDROID)
+
+}  // namespace sync_file_system
diff --git a/chrome/browser/sync_file_system/drive_file_sync_service_mock_unittest.cc b/chrome/browser/sync_file_system/drive_file_sync_service_mock_unittest.cc
deleted file mode 100644
index 94d7d10..0000000
--- a/chrome/browser/sync_file_system/drive_file_sync_service_mock_unittest.cc
+++ /dev/null
@@ -1,1023 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/sync_file_system/drive_file_sync_service.h"
-
-#include <utility>
-
-#include "base/command_line.h"
-#include "base/message_loop.h"
-#include "base/message_loop/message_loop_proxy.h"
-#include "chrome/browser/drive/drive_uploader.h"
-#include "chrome/browser/drive/mock_drive_service.h"
-#include "chrome/browser/extensions/test_extension_service.h"
-#include "chrome/browser/extensions/test_extension_system.h"
-#include "chrome/browser/google_apis/drive_api_parser.h"
-#include "chrome/browser/google_apis/gdata_errorcode.h"
-#include "chrome/browser/google_apis/gdata_wapi_parser.h"
-#include "chrome/browser/google_apis/test_util.h"
-#include "chrome/browser/sync_file_system/drive/api_util.h"
-#include "chrome/browser/sync_file_system/drive_file_sync_util.h"
-#include "chrome/browser/sync_file_system/drive_metadata_store.h"
-#include "chrome/browser/sync_file_system/file_status_observer.h"
-#include "chrome/browser/sync_file_system/mock_remote_change_processor.h"
-#include "chrome/browser/sync_file_system/sync_file_system.pb.h"
-#include "chrome/common/extensions/extension.h"
-#include "chrome/common/extensions/extension_builder.h"
-#include "chrome/test/base/testing_profile.h"
-#include "content/public/test/test_browser_thread.h"
-#include "extensions/common/id_util.h"
-#include "net/base/escape.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/fileapi/syncable/sync_direction.h"
-#include "webkit/browser/fileapi/syncable/sync_file_metadata.h"
-#include "webkit/browser/fileapi/syncable/syncable_file_system_util.h"
-#include "webkit/common/fileapi/file_system_util.h"
-
-#if defined(OS_CHROMEOS)
-#include "chrome/browser/chromeos/login/user_manager.h"
-#include "chrome/browser/chromeos/settings/cros_settings.h"
-#include "chrome/browser/chromeos/settings/device_settings_service.h"
-#endif
-
-#define FPL(x) FILE_PATH_LITERAL(x)
-
-using ::testing::AnyNumber;
-using ::testing::AtLeast;
-using ::testing::AtMost;
-using ::testing::InSequence;
-using ::testing::Return;
-using ::testing::NiceMock;
-using ::testing::Sequence;
-using ::testing::StrictMock;
-using ::testing::_;
-
-using google_apis::ResourceEntry;
-using google_apis::DriveServiceInterface;
-using google_apis::DriveUploaderInterface;
-using google_apis::test_util::LoadJSONFile;
-
-using extensions::Extension;
-using extensions::DictionaryBuilder;
-using extensions::ListBuilder;
-
-namespace sync_file_system {
-
-namespace {
-
-const char kRootResourceId[] = "folder:root";
-
-base::FilePath::StringType ASCIIToFilePathString(const std::string& path) {
-  return base::FilePath().AppendASCII(path).value();
-}
-
-void DidInitialize(bool* done, SyncStatusCode status, bool created) {
-  EXPECT_FALSE(*done);
-  *done = true;
-  EXPECT_EQ(SYNC_STATUS_OK, status);
-  EXPECT_TRUE(created);
-}
-
-void DidGetSyncRoot(bool* done,
-                    SyncStatusCode status,
-                    const std::string& resource_id) {
-  EXPECT_FALSE(*done);
-  *done = true;
-}
-
-void ExpectEqStatus(bool* done,
-                    SyncStatusCode expected,
-                    SyncStatusCode actual) {
-  EXPECT_FALSE(*done);
-  *done = true;
-  EXPECT_EQ(expected, actual);
-}
-
-void ExpectOkStatus(SyncStatusCode status) {
-  EXPECT_EQ(SYNC_STATUS_OK, status);
-}
-
-// Mocks adding an installed extension to ExtensionService.
-scoped_refptr<const extensions::Extension> AddTestExtension(
-    ExtensionService* extension_service,
-    const base::FilePath::StringType& extension_name) {
-  std::string id = extensions::id_util::GenerateIdForPath(
-      base::FilePath(extension_name));
-
-  scoped_refptr<const Extension> extension =
-      extensions::ExtensionBuilder().SetManifest(
-          DictionaryBuilder()
-            .Set("name", extension_name)
-            .Set("version", "1.0"))
-          .SetID(id)
-      .Build();
-  extension_service->AddExtension(extension.get());
-  return extension;
-}
-
-// Converts extension_name to GURL version.
-GURL ExtensionNameToGURL(const base::FilePath::StringType& extension_name) {
-  std::string id = extensions::id_util::GenerateIdForPath(
-      base::FilePath(extension_name));
-  return extensions::Extension::GetBaseURLFromExtensionId(id);
-}
-
-ACTION(InvokeCompletionCallback) {
-  base::MessageLoopProxy::current()->PostTask(FROM_HERE, arg1);
-}
-
-// Invoke |arg2| as a EntryActionCallback.
-ACTION_P(InvokeEntryActionCallback, error) {
-  base::MessageLoopProxy::current()->PostTask(
-      FROM_HERE, base::Bind(arg2, error));
-  return google_apis::CancelCallback();
-}
-
-// Invokes |arg0| as a GetDataCallback.
-ACTION_P2(InvokeGetAboutResourceCallback0, error, result) {
-  scoped_ptr<google_apis::AboutResource> about_resource(result.Pass());
-  base::MessageLoopProxy::current()->PostTask(
-      FROM_HERE,
-      base::Bind(arg0, error, base::Passed(&about_resource)));
-  return google_apis::CancelCallback();
-}
-
-// Invokes |arg1| as a GetResourceEntryCallback.
-ACTION_P2(InvokeGetResourceEntryCallback1, error, result) {
-  scoped_ptr<google_apis::ResourceEntry> entry(result.Pass());
-  base::MessageLoopProxy::current()->PostTask(
-      FROM_HERE,
-      base::Bind(arg1, error, base::Passed(&entry)));
-  return google_apis::CancelCallback();
-}
-
-// Invokes |arg2| as a GetResourceEntryCallback.
-ACTION_P2(InvokeGetResourceEntryCallback2, error, result) {
-  scoped_ptr<google_apis::ResourceEntry> entry(result.Pass());
-  base::MessageLoopProxy::current()->PostTask(
-      FROM_HERE,
-      base::Bind(arg2, error, base::Passed(&entry)));
-  return google_apis::CancelCallback();
-}
-
-// Invokes |arg1| as a GetResourceListCallback.
-ACTION_P2(InvokeGetResourceListCallback1, error, result) {
-  scoped_ptr<google_apis::ResourceList> resource_list(result.Pass());
-  base::MessageLoopProxy::current()->PostTask(
-      FROM_HERE,
-      base::Bind(arg1, error, base::Passed(&resource_list)));
-  return google_apis::CancelCallback();
-}
-
-// Invokes |arg2| as a GetResourceListCallback.
-ACTION_P2(InvokeGetResourceListCallback2, error, result) {
-  scoped_ptr<google_apis::ResourceList> resource_list(result.Pass());
-  base::MessageLoopProxy::current()->PostTask(
-      FROM_HERE,
-      base::Bind(arg2, error, base::Passed(&resource_list)));
-  return google_apis::CancelCallback();
-}
-
-ACTION(PrepareForRemoteChange_Busy) {
-  base::MessageLoopProxy::current()->PostTask(
-      FROM_HERE,
-      base::Bind(arg1,
-                 SYNC_STATUS_FILE_BUSY,
-                 SyncFileMetadata(),
-                 FileChangeList()));
-}
-
-ACTION(PrepareForRemoteChange_NotFound) {
-  base::MessageLoopProxy::current()->PostTask(
-      FROM_HERE,
-      base::Bind(arg1,
-                 SYNC_STATUS_OK,
-                 SyncFileMetadata(SYNC_FILE_TYPE_UNKNOWN, 0, base::Time()),
-                 FileChangeList()));
-}
-
-ACTION(PrepareForRemoteChange_NotModified) {
-  base::MessageLoopProxy::current()->PostTask(
-      FROM_HERE,
-      base::Bind(arg1,
-                 SYNC_STATUS_OK,
-                 SyncFileMetadata(SYNC_FILE_TYPE_FILE, 0, base::Time()),
-                 FileChangeList()));
-}
-
-ACTION(InvokeDidDownloadFile) {
-  base::MessageLoopProxy::current()->PostTask(
-      FROM_HERE, base::Bind(arg3, google_apis::HTTP_SUCCESS, arg1));
-  return google_apis::CancelCallback();
-}
-
-ACTION(InvokeDidApplyRemoteChange) {
-  base::MessageLoopProxy::current()->PostTask(
-      FROM_HERE, base::Bind(arg3, SYNC_STATUS_OK));
-}
-
-}  // namespace
-
-class MockRemoteServiceObserver : public RemoteFileSyncService::Observer {
- public:
-  MockRemoteServiceObserver() {}
-  virtual ~MockRemoteServiceObserver() {}
-
-  // LocalChangeProcessor override.
-  MOCK_METHOD1(OnRemoteChangeQueueUpdated,
-               void(int64 pending_changes));
-  MOCK_METHOD2(OnRemoteServiceStateUpdated,
-               void(RemoteServiceState state,
-                    const std::string& description));
-};
-
-class MockFileStatusObserver: public FileStatusObserver {
- public:
-  MockFileStatusObserver() {}
-  virtual ~MockFileStatusObserver() {}
-
-  MOCK_METHOD4(OnFileStatusChanged,
-               void(const fileapi::FileSystemURL& url,
-                    SyncFileStatus sync_status,
-                    SyncAction action_taken,
-                    SyncDirection direction));
-};
-
-class DriveFileSyncServiceMockTest : public testing::Test {
- public:
-  DriveFileSyncServiceMockTest()
-      : ui_thread_(content::BrowserThread::UI, &message_loop_),
-        file_thread_(content::BrowserThread::FILE, &message_loop_),
-        mock_drive_service_(NULL) {
-  }
-
-  virtual void SetUp() OVERRIDE {
-    profile_.reset(new TestingProfile());
-
-    // Add TestExtensionSystem with registered ExtensionIds used in tests.
-    extensions::TestExtensionSystem* extension_system(
-        static_cast<extensions::TestExtensionSystem*>(
-            extensions::ExtensionSystem::Get(profile_.get())));
-    extension_system->CreateExtensionService(
-        CommandLine::ForCurrentProcess(), base::FilePath(), false);
-    extension_service_ = extension_system->Get(
-        profile_.get())->extension_service();
-
-    AddTestExtension(extension_service_, FPL("example1"));
-    AddTestExtension(extension_service_, FPL("example2"));
-
-    SetDisableDriveAPI(true);
-    RegisterSyncableFileSystem();
-
-    mock_drive_service_ = new NiceMock<google_apis::MockDriveService>;
-
-    EXPECT_CALL(*mock_drive_service(), Initialize(profile_.get()));
-    EXPECT_CALL(*mock_drive_service(), AddObserver(_));
-
-    // Expect to call GetRootResourceId and RemoveResourceFromDirectory to
-    // ensure the sync root directory is not in 'My Drive' directory.
-    EXPECT_CALL(*mock_drive_service(), GetRootResourceId())
-        .WillRepeatedly(Return(kRootResourceId));
-    EXPECT_CALL(*mock_drive_service(),
-                RemoveResourceFromDirectory(kRootResourceId, _, _))
-        .Times(AnyNumber());
-
-    api_util_ = drive::APIUtil::CreateForTesting(
-        profile_.get(),
-        scoped_ptr<DriveServiceInterface>(mock_drive_service_),
-        scoped_ptr<DriveUploaderInterface>()).Pass();
-    ASSERT_TRUE(base_dir_.CreateUniqueTempDir());
-    metadata_store_.reset(new DriveMetadataStore(
-        base_dir_.path(), base::MessageLoopProxy::current().get()));
-
-    bool done = false;
-    metadata_store_->Initialize(base::Bind(&DidInitialize, &done));
-    message_loop_.RunUntilIdle();
-    EXPECT_TRUE(done);
-  }
-
-  void SetUpDriveSyncService(bool enabled) {
-    sync_service_ = DriveFileSyncService::CreateForTesting(
-        profile_.get(),
-        base_dir_.path(),
-        api_util_.PassAs<drive::APIUtilInterface>(),
-        metadata_store_.Pass()).Pass();
-    sync_service_->AddServiceObserver(&mock_remote_observer_);
-    sync_service_->AddFileStatusObserver(&mock_file_status_observer_);
-    sync_service_->SetRemoteChangeProcessor(mock_remote_processor());
-    sync_service_->SetSyncEnabled(enabled);
-    message_loop_.RunUntilIdle();
-  }
-
-  virtual void TearDown() OVERRIDE {
-    EXPECT_CALL(*mock_drive_service(), RemoveObserver(_));
-
-    if (sync_service_) {
-      sync_service_.reset();
-    }
-
-    metadata_store_.reset();
-    api_util_.reset();
-    mock_drive_service_ = NULL;
-
-    RevokeSyncableFileSystem();
-    SetDisableDriveAPI(false);
-
-    extension_service_ = NULL;
-    profile_.reset();
-    message_loop_.RunUntilIdle();
-  }
-
-  void SetSyncEnabled(bool enabled) {
-    sync_service_->SetSyncEnabled(enabled);
-  }
-
- protected:
-  void EnableExtension(const std::string& extension_id) {
-    extension_service_->EnableExtension(extension_id);
-  }
-
-  void DisableExtension(const std::string& extension_id) {
-    extension_service_->DisableExtension(
-        extension_id, extensions::Extension::DISABLE_NONE);
-  }
-
-  void UninstallExtension(const std::string& extension_id) {
-    // Call UnloadExtension instead of UninstallExtension since it does
-    // unnecessary cleanup (e.g. deleting extension data) and emits warnings.
-    extension_service_->UnloadExtension(
-        extension_id, extension_misc::UNLOAD_REASON_UNINSTALL);
-  }
-
-  void UpdateRegisteredOrigins() {
-    sync_service_->UpdateRegisteredOrigins();
-    // Wait for completion of uninstalling origin.
-    message_loop()->RunUntilIdle();
-  }
-
-  void VerifySizeOfRegisteredOrigins(size_t b_size,
-                                     size_t i_size,
-                                     size_t d_size) {
-    EXPECT_EQ(b_size, pending_batch_sync_origins()->size());
-    EXPECT_EQ(i_size, metadata_store()->incremental_sync_origins().size());
-    EXPECT_EQ(d_size, metadata_store()->disabled_origins().size());
-  }
-
-  drive::APIUtilInterface* api_util() {
-    if (api_util_)
-      return api_util_.get();
-    return sync_service_->api_util_.get();
-  }
-
-  DriveMetadataStore* metadata_store() {
-    if (metadata_store_)
-      return metadata_store_.get();
-    return sync_service_->metadata_store_.get();
-  }
-
-  NiceMock<google_apis::MockDriveService>* mock_drive_service() {
-    return mock_drive_service_;
-  }
-
-  StrictMock<MockRemoteServiceObserver>* mock_remote_observer() {
-    return &mock_remote_observer_;
-  }
-
-  StrictMock<MockFileStatusObserver>* mock_file_status_observer() {
-    return &mock_file_status_observer_;
-  }
-
-  StrictMock<MockRemoteChangeProcessor>* mock_remote_processor() {
-    return &mock_remote_processor_;
-  }
-
-  base::MessageLoop* message_loop() { return &message_loop_; }
-  DriveFileSyncService* sync_service() { return sync_service_.get(); }
-  std::map<GURL, std::string>* pending_batch_sync_origins() {
-    return &(sync_service()->pending_batch_sync_origins_);
-  }
-
-  const RemoteChangeHandler& remote_change_handler() const {
-    return sync_service_->remote_change_handler_;
-  }
-
-  fileapi::FileSystemURL CreateURL(const GURL& origin,
-                                   const base::FilePath::StringType& path) {
-    return CreateSyncableFileSystemURL(origin, base::FilePath(path));
-  }
-
-  void ProcessRemoteChange(SyncStatusCode expected_status,
-                           const fileapi::FileSystemURL& expected_url,
-                           SyncFileStatus expected_sync_file_status,
-                           SyncAction expected_sync_action,
-                           SyncDirection expected_sync_direction) {
-    SyncStatusCode actual_status = SYNC_STATUS_UNKNOWN;
-    fileapi::FileSystemURL actual_url;
-
-    if (expected_sync_file_status != SYNC_FILE_STATUS_UNKNOWN) {
-      EXPECT_CALL(*mock_file_status_observer(),
-                  OnFileStatusChanged(expected_url,
-                                      expected_sync_file_status,
-                                      expected_sync_action,
-                                      expected_sync_direction))
-          .Times(1);
-    }
-
-    sync_service_->ProcessRemoteChange(
-        base::Bind(&DriveFileSyncServiceMockTest::DidProcessRemoteChange,
-                   base::Unretained(this),
-                   &actual_status, &actual_url));
-    message_loop_.RunUntilIdle();
-
-    EXPECT_EQ(expected_status, actual_status);
-    EXPECT_EQ(expected_url, actual_url);
-  }
-
-  void DidProcessRemoteChange(SyncStatusCode* status_out,
-                              fileapi::FileSystemURL* url_out,
-                              SyncStatusCode status,
-                              const fileapi::FileSystemURL& url) {
-    *status_out = status;
-    *url_out = url;
-  }
-
-  bool AppendIncrementalRemoteChangeByEntry(
-      const GURL& origin,
-      const google_apis::ResourceEntry& entry,
-      int64 changestamp) {
-    return sync_service_->AppendRemoteChange(origin, entry, changestamp);
-  }
-
-  bool AppendIncrementalRemoteChange(
-      const GURL& origin,
-      const base::FilePath& path,
-      bool is_deleted,
-      const std::string& resource_id,
-      int64 changestamp,
-      const std::string& remote_file_md5) {
-    return sync_service_->AppendRemoteChangeInternal(
-        origin, path, is_deleted, resource_id,
-        changestamp, remote_file_md5, base::Time(),
-        SYNC_FILE_TYPE_FILE);
-  }
-
-  // Mock setup helpers ------------------------------------------------------
-  void SetUpDriveServiceExpectCallsForSearchByTitle(
-      const std::string& result_mock_json_name,
-      const std::string& title,
-      const std::string& search_directory) {
-    scoped_ptr<Value> result_value(LoadJSONFile(
-        result_mock_json_name));
-    scoped_ptr<google_apis::ResourceList> result(
-        google_apis::ResourceList::ExtractAndParse(*result_value));
-    EXPECT_CALL(*mock_drive_service(),
-                SearchByTitle(title, search_directory, _))
-        .WillOnce(InvokeGetResourceListCallback2(
-            google_apis::HTTP_SUCCESS,
-            base::Passed(&result)))
-        .RetiresOnSaturation();
-  }
-
-  void SetUpDriveServiceExpectCallsForGetResourceListInDirectory(
-      const std::string& result_mock_json_name,
-      const std::string& search_directory) {
-    scoped_ptr<Value> result_value(LoadJSONFile(
-        result_mock_json_name));
-    scoped_ptr<google_apis::ResourceList> result(
-        google_apis::ResourceList::ExtractAndParse(*result_value));
-    EXPECT_CALL(*mock_drive_service(),
-                GetResourceListInDirectory(search_directory, _))
-        .WillOnce(InvokeGetResourceListCallback1(
-            google_apis::HTTP_SUCCESS,
-            base::Passed(&result)))
-        .RetiresOnSaturation();
-  }
-
-  void SetUpDriveServiceExpectCallsForIncrementalSync() {
-    scoped_ptr<Value> result_value(LoadJSONFile(
-        "chromeos/sync_file_system/origin_directory_not_found.json"));
-    scoped_ptr<google_apis::ResourceList> result(
-        google_apis::ResourceList::ExtractAndParse(*result_value));
-    EXPECT_CALL(*mock_drive_service(), GetChangeList(1, _))
-        .WillOnce(InvokeGetResourceListCallback1(
-            google_apis::HTTP_SUCCESS,
-            base::Passed(&result)))
-        .RetiresOnSaturation();
-  }
-
-  void SetUpDriveServiceExpectCallsForGetSyncRoot() {
-    scoped_ptr<Value> result_value(LoadJSONFile(
-        "chromeos/sync_file_system/sync_root_found.json"));
-    scoped_ptr<google_apis::ResourceList> result(
-        google_apis::ResourceList::ExtractAndParse(*result_value));
-    EXPECT_CALL(
-        *mock_drive_service(),
-        SearchByTitle(
-            drive::APIUtil::GetSyncRootDirectoryName(), std::string(), _))
-        .Times(AtMost(1)).WillOnce(InvokeGetResourceListCallback2(
-             google_apis::HTTP_SUCCESS, base::Passed(&result)))
-        .RetiresOnSaturation();
-  }
-
-  void SetUpDriveServiceExpectCallsForGetAboutResource() {
-    scoped_ptr<Value> account_metadata_value(LoadJSONFile(
-        "chromeos/gdata/account_metadata.json"));
-    scoped_ptr<google_apis::AboutResource> about_resource(
-        google_apis::AboutResource::CreateFromAccountMetadata(
-            *google_apis::AccountMetadata::CreateFrom(*account_metadata_value),
-            kRootResourceId));
-    EXPECT_CALL(*mock_drive_service(), GetAboutResource(_))
-        .WillOnce(InvokeGetAboutResourceCallback0(
-            google_apis::HTTP_SUCCESS,
-            base::Passed(&about_resource)))
-        .RetiresOnSaturation();
-  }
-
-  void SetUpDriveServiceExpectCallsForDownloadFile(
-      const std::string& file_resource_id) {
-    scoped_ptr<Value> file_entry_value(
-        LoadJSONFile("chromeos/gdata/file_entry.json").Pass());
-    scoped_ptr<google_apis::ResourceEntry> file_entry
-        = google_apis::ResourceEntry::ExtractAndParse(*file_entry_value);
-    EXPECT_CALL(*mock_drive_service(),
-                GetResourceEntry(file_resource_id, _))
-        .WillOnce(InvokeGetResourceEntryCallback1(
-            google_apis::HTTP_SUCCESS,
-            base::Passed(&file_entry)))
-        .RetiresOnSaturation();
-
-    EXPECT_CALL(*mock_drive_service(),
-                DownloadFile(_, _, GURL("https://file_content_url"), _, _, _))
-        .WillOnce(InvokeDidDownloadFile())
-        .RetiresOnSaturation();
-  }
-
-  // End of mock setup helpers -----------------------------------------------
-
- private:
-  base::MessageLoop message_loop_;
-  content::TestBrowserThread ui_thread_;
-  content::TestBrowserThread file_thread_;
-
-  base::ScopedTempDir base_dir_;
-  scoped_ptr<TestingProfile> profile_;
-
-#if defined OS_CHROMEOS
-  chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
-  chromeos::ScopedTestCrosSettings test_cros_settings_;
-  chromeos::ScopedTestUserManager test_user_manager_;
-#endif
-
-  scoped_ptr<DriveFileSyncService> sync_service_;
-
-  // Not owned.
-  ExtensionService* extension_service_;
-
-  // Owned by |api_util_|.
-  NiceMock<google_apis::MockDriveService>* mock_drive_service_;
-
-  StrictMock<MockRemoteServiceObserver> mock_remote_observer_;
-  StrictMock<MockFileStatusObserver> mock_file_status_observer_;
-  StrictMock<MockRemoteChangeProcessor> mock_remote_processor_;
-
-  scoped_ptr<drive::APIUtil> api_util_;
-  scoped_ptr<DriveMetadataStore> metadata_store_;
-
-  DISALLOW_COPY_AND_ASSIGN(DriveFileSyncServiceMockTest);
-};
-
-#if !defined(OS_ANDROID)
-
-TEST_F(DriveFileSyncServiceMockTest, RegisterNewOrigin) {
-  const GURL kOrigin("chrome-extension://example");
-  const std::string kDirectoryResourceId("folder:origin_directory_resource_id");
-  // The root id is in the "sync_root_entry.json" file.
-  const std::string kSyncRootResourceId("folder:sync_root_resource_id");
-
-  metadata_store()->SetSyncRootDirectory(kSyncRootResourceId);
-
-  EXPECT_CALL(*mock_remote_observer(), OnRemoteChangeQueueUpdated(0))
-      .Times(AnyNumber());
-
-  // Expect to call GetResourceList for the sync root from
-  // RegisterOriginForTrackingChanges.
-  SetUpDriveServiceExpectCallsForGetSyncRoot();
-
-  SetUpDriveServiceExpectCallsForSearchByTitle(
-      "chromeos/sync_file_system/origin_directory_found.json",
-      drive::APIUtil::OriginToDirectoryTitle(kOrigin),
-      kSyncRootResourceId);
-  SetUpDriveServiceExpectCallsForSearchByTitle(
-      "chromeos/sync_file_system/origin_directory_not_found.json",
-      drive::APIUtil::OriginToDirectoryTitle(kOrigin),
-      kSyncRootResourceId);
-
-  // Once the directory is created GetAboutResource should be called to get
-  // the largest changestamp for the origin as a prepariation of the batch sync.
-  SetUpDriveServiceExpectCallsForGetAboutResource();
-
-  SetUpDriveServiceExpectCallsForGetResourceListInDirectory(
-      "chromeos/sync_file_system/listing_files_in_empty_directory.json",
-      kDirectoryResourceId);
-
-  SetUpDriveSyncService(true);
-  bool done = false;
-  sync_service()->RegisterOriginForTrackingChanges(
-      kOrigin, base::Bind(&ExpectEqStatus, &done, SYNC_STATUS_OK));
-  message_loop()->RunUntilIdle();
-  EXPECT_TRUE(done);
-
-  VerifySizeOfRegisteredOrigins(0u, 1u, 0u);
-  EXPECT_TRUE(!remote_change_handler().HasChanges());
-}
-
-TEST_F(DriveFileSyncServiceMockTest, RegisterExistingOrigin) {
-  const GURL kOrigin("chrome-extension://example");
-  const std::string kDirectoryResourceId("folder:origin_directory_resource_id");
-  const std::string kSyncRootResourceId("folder:sync_root_resource_id");
-
-  metadata_store()->SetSyncRootDirectory(kSyncRootResourceId);
-
-  EXPECT_CALL(*mock_remote_observer(), OnRemoteChangeQueueUpdated(_))
-      .Times(AnyNumber());
-
-  InSequence sequence;
-
-  // Expect to call GetResourceList for the sync root from
-  // RegisterOriginForTrackingChanges.
-  SetUpDriveServiceExpectCallsForGetSyncRoot();
-
-  // We already have a directory for the origin.
-  SetUpDriveServiceExpectCallsForSearchByTitle(
-      "chromeos/sync_file_system/origin_directory_found.json",
-      drive::APIUtil::OriginToDirectoryTitle(kOrigin),
-      kSyncRootResourceId);
-
-  SetUpDriveServiceExpectCallsForGetAboutResource();
-
-  // DriveFileSyncService should fetch the list of the directory content
-  // to start the batch sync.
-  SetUpDriveServiceExpectCallsForGetResourceListInDirectory(
-      "chromeos/sync_file_system/listing_files_in_directory.json",
-      kDirectoryResourceId);
-
-  SetUpDriveSyncService(true);
-  bool done = false;
-  sync_service()->RegisterOriginForTrackingChanges(
-      kOrigin, base::Bind(&ExpectEqStatus, &done, SYNC_STATUS_OK));
-  message_loop()->RunUntilIdle();
-  EXPECT_TRUE(done);
-
-  // The origin should be registered as an incremental sync origin.
-  VerifySizeOfRegisteredOrigins(0u, 1u, 0u);
-
-  // |listing_files_in_directory| contains 4 items to sync.
-  EXPECT_EQ(1u, remote_change_handler().ChangesSize());
-}
-
-TEST_F(DriveFileSyncServiceMockTest, UnregisterOrigin) {
-  const GURL kOrigin1 = ExtensionNameToGURL(FPL("example1"));
-  const GURL kOrigin2 = ExtensionNameToGURL(FPL("example2"));
-  const std::string kDirectoryResourceId1(
-      "folder:origin_directory_resource_id");
-  const std::string kDirectoryResourceId2(
-      "folder:origin_directory_resource_id2");
-  const std::string kSyncRootResourceId("folder:sync_root_resource_id");
-
-  metadata_store()->SetSyncRootDirectory(kSyncRootResourceId);
-  metadata_store()->AddIncrementalSyncOrigin(kOrigin1, kDirectoryResourceId1);
-  metadata_store()->AddIncrementalSyncOrigin(kOrigin2, kDirectoryResourceId2);
-
-  EXPECT_CALL(*mock_remote_observer(), OnRemoteChangeQueueUpdated(_))
-      .Times(AnyNumber());
-
-  SetUpDriveSyncService(true);
-  message_loop()->RunUntilIdle();
-
-  VerifySizeOfRegisteredOrigins(0u, 2u, 0u);
-  EXPECT_EQ(0u, remote_change_handler().ChangesSize());
-
-  bool done = false;
-  sync_service()->UnregisterOriginForTrackingChanges(
-      kOrigin1, base::Bind(&ExpectEqStatus, &done, SYNC_STATUS_OK));
-  message_loop()->RunUntilIdle();
-  EXPECT_TRUE(done);
-
-  VerifySizeOfRegisteredOrigins(0u, 1u, 0u);
-  EXPECT_TRUE(!remote_change_handler().HasChanges());
-}
-
-TEST_F(DriveFileSyncServiceMockTest, UpdateRegisteredOrigins) {
-  const GURL kOrigin1 = ExtensionNameToGURL(FPL("example1"));
-  const GURL kOrigin2 = ExtensionNameToGURL(FPL("example2"));
-  const std::string kDirectoryResourceId1(
-      "folder:origin_directory_resource_id");
-  const std::string kDirectoryResourceId2(
-      "folder:origin_directory_resource_id2");
-  const std::string kSyncRootResourceId("folder:sync_root_resource_id");
-  const std::string extension_id1 =
-      extensions::id_util::GenerateIdForPath(base::FilePath(FPL("example1")));
-  const std::string extension_id2 =
-      extensions::id_util::GenerateIdForPath(base::FilePath(FPL("example2")));
-
-  metadata_store()->SetSyncRootDirectory(kSyncRootResourceId);
-  metadata_store()->AddIncrementalSyncOrigin(kOrigin1, kDirectoryResourceId1);
-  metadata_store()->AddIncrementalSyncOrigin(kOrigin2, kDirectoryResourceId2);
-
-  EXPECT_CALL(*mock_remote_observer(), OnRemoteChangeQueueUpdated(_))
-      .Times(AnyNumber());
-
-  SetUpDriveSyncService(true);
-  message_loop()->RunUntilIdle();
-
-  // [1] Both extensions and origins are enabled. Nothing to do.
-  VerifySizeOfRegisteredOrigins(0u, 2u, 0u);
-  UpdateRegisteredOrigins();
-  VerifySizeOfRegisteredOrigins(0u, 2u, 0u);
-
-  // [2] Extension 1 should move to disabled list.
-  DisableExtension(extension_id1);
-  UpdateRegisteredOrigins();
-  VerifySizeOfRegisteredOrigins(0u, 1u, 1u);
-
-  // [3] Make sure that state remains the same, nothing should change.
-  UpdateRegisteredOrigins();
-  VerifySizeOfRegisteredOrigins(0u, 1u, 1u);
-
-  // [4] Uninstall Extension 2.
-  UninstallExtension(extension_id2);
-  UpdateRegisteredOrigins();
-  VerifySizeOfRegisteredOrigins(0u, 0u, 1u);
-
-  // [5] Re-enable Extension 1. It moves back to batch and not to incremental.
-  EnableExtension(extension_id1);
-  UpdateRegisteredOrigins();
-  VerifySizeOfRegisteredOrigins(1u, 0u, 0u);
-}
-
-TEST_F(DriveFileSyncServiceMockTest, RemoteChange_NoChange) {
-  const std::string kSyncRootResourceId("folder:sync_root_resource_id");
-
-  metadata_store()->SetSyncRootDirectory(kSyncRootResourceId);
-
-  EXPECT_CALL(*mock_remote_observer(), OnRemoteChangeQueueUpdated(_))
-      .Times(AnyNumber());
-
-  SetUpDriveSyncService(true);
-
-  ProcessRemoteChange(SYNC_STATUS_NO_CHANGE_TO_SYNC,
-                      fileapi::FileSystemURL(),
-                      SYNC_FILE_STATUS_UNKNOWN,
-                      SYNC_ACTION_NONE,
-                      SYNC_DIRECTION_NONE);
-  VerifySizeOfRegisteredOrigins(0u, 0u, 0u);
-  EXPECT_TRUE(!remote_change_handler().HasChanges());
-}
-
-TEST_F(DriveFileSyncServiceMockTest, RemoteChange_Busy) {
-  const GURL kOrigin = ExtensionNameToGURL(FPL("example1"));
-  const std::string kDirectoryResourceId("folder:origin_directory_resource_id");
-  const std::string kSyncRootResourceId("folder:sync_root_resource_id");
-  const base::FilePath::StringType kFileName(FPL("File 1.mp3"));
-
-  metadata_store()->SetSyncRootDirectory(kSyncRootResourceId);
-  metadata_store()->AddIncrementalSyncOrigin(kOrigin, kDirectoryResourceId);
-
-  EXPECT_CALL(*mock_remote_observer(), OnRemoteChangeQueueUpdated(_))
-      .Times(AnyNumber());
-
-  EXPECT_CALL(*mock_remote_processor(),
-              PrepareForProcessRemoteChange(CreateURL(kOrigin, kFileName), _))
-      .WillOnce(PrepareForRemoteChange_Busy());
-  EXPECT_CALL(*mock_remote_processor(),
-              ClearLocalChanges(CreateURL(kOrigin, kFileName), _))
-      .WillOnce(InvokeCompletionCallback());
-
-  SetUpDriveServiceExpectCallsForIncrementalSync();
-
-  SetUpDriveSyncService(true);
-
-  scoped_ptr<ResourceEntry> entry(ResourceEntry::ExtractAndParse(
-      *LoadJSONFile("chromeos/gdata/file_entry.json")));
-  AppendIncrementalRemoteChangeByEntry(kOrigin, *entry, 12345);
-
-  ProcessRemoteChange(SYNC_STATUS_FILE_BUSY,
-                      CreateURL(kOrigin, kFileName),
-                      SYNC_FILE_STATUS_UNKNOWN,
-                      SYNC_ACTION_NONE,
-                      SYNC_DIRECTION_NONE);
-}
-
-TEST_F(DriveFileSyncServiceMockTest, RemoteChange_NewFile) {
-  const GURL kOrigin = ExtensionNameToGURL(FPL("example1"));
-  const std::string kDirectoryResourceId("folder:origin_directory_resource_id");
-  const std::string kSyncRootResourceId("folder:sync_root_resource_id");
-  const base::FilePath::StringType kFileName(FPL("File 1.mp3"));
-  const std::string kFileResourceId("file:2_file_resource_id");
-
-  metadata_store()->SetSyncRootDirectory(kSyncRootResourceId);
-  metadata_store()->AddIncrementalSyncOrigin(kOrigin, kDirectoryResourceId);
-
-  EXPECT_CALL(*mock_remote_observer(), OnRemoteChangeQueueUpdated(_))
-      .Times(AnyNumber());
-
-  EXPECT_CALL(*mock_remote_processor(),
-              PrepareForProcessRemoteChange(CreateURL(kOrigin, kFileName), _))
-      .WillOnce(PrepareForRemoteChange_NotFound());
-  EXPECT_CALL(*mock_remote_processor(),
-              ClearLocalChanges(CreateURL(kOrigin, kFileName), _))
-      .WillOnce(InvokeCompletionCallback());
-
-  SetUpDriveServiceExpectCallsForDownloadFile(kFileResourceId);
-
-  EXPECT_CALL(*mock_remote_processor(),
-              ApplyRemoteChange(_, _, CreateURL(kOrigin, kFileName), _))
-      .WillOnce(InvokeDidApplyRemoteChange());
-
-  SetUpDriveServiceExpectCallsForIncrementalSync();
-
-  SetUpDriveSyncService(true);
-
-  scoped_ptr<ResourceEntry> entry(ResourceEntry::ExtractAndParse(
-      *LoadJSONFile("chromeos/gdata/file_entry.json")));
-  AppendIncrementalRemoteChangeByEntry(kOrigin, *entry, 12345);
-
-  ProcessRemoteChange(SYNC_STATUS_OK,
-                      CreateURL(kOrigin, kFileName),
-                      SYNC_FILE_STATUS_SYNCED,
-                      SYNC_ACTION_ADDED,
-                      SYNC_DIRECTION_REMOTE_TO_LOCAL);
-}
-
-TEST_F(DriveFileSyncServiceMockTest, RemoteChange_UpdateFile) {
-  const GURL kOrigin = ExtensionNameToGURL(FPL("example1"));
-  const std::string kDirectoryResourceId("folder:origin_directory_resource_id");
-  const std::string kSyncRootResourceId("folder:sync_root_resource_id");
-  const base::FilePath::StringType kFileName(FPL("File 1.mp3"));
-  const std::string kFileResourceId("file:2_file_resource_id");
-
-  metadata_store()->SetSyncRootDirectory(kSyncRootResourceId);
-  metadata_store()->AddIncrementalSyncOrigin(kOrigin, kDirectoryResourceId);
-
-  EXPECT_CALL(*mock_remote_observer(), OnRemoteChangeQueueUpdated(_))
-      .Times(AnyNumber());
-
-  EXPECT_CALL(*mock_remote_processor(),
-              PrepareForProcessRemoteChange(CreateURL(kOrigin, kFileName), _))
-      .WillOnce(PrepareForRemoteChange_NotModified());
-  EXPECT_CALL(*mock_remote_processor(),
-              ClearLocalChanges(CreateURL(kOrigin, kFileName), _))
-      .WillOnce(InvokeCompletionCallback());
-
-  SetUpDriveServiceExpectCallsForDownloadFile(kFileResourceId);
-
-  EXPECT_CALL(*mock_remote_processor(),
-              ApplyRemoteChange(_, _, CreateURL(kOrigin, kFileName), _))
-      .WillOnce(InvokeDidApplyRemoteChange());
-
-  SetUpDriveServiceExpectCallsForIncrementalSync();
-
-  SetUpDriveSyncService(true);
-
-  scoped_ptr<ResourceEntry> entry(ResourceEntry::ExtractAndParse(
-      *LoadJSONFile("chromeos/gdata/file_entry.json")));
-  AppendIncrementalRemoteChangeByEntry(kOrigin, *entry, 12345);
-  ProcessRemoteChange(SYNC_STATUS_OK,
-                      CreateURL(kOrigin, kFileName),
-                      SYNC_FILE_STATUS_SYNCED,
-                      SYNC_ACTION_UPDATED,
-                      SYNC_DIRECTION_REMOTE_TO_LOCAL);
-}
-
-TEST_F(DriveFileSyncServiceMockTest, RegisterOriginWithSyncDisabled) {
-  const GURL kOrigin("chrome-extension://example");
-  const std::string kDirectoryResourceId("folder:origin_directory_resource_id");
-  const std::string kSyncRootResourceId("folder:sync_root_resource_id");
-
-  metadata_store()->SetSyncRootDirectory(kSyncRootResourceId);
-
-  EXPECT_CALL(*mock_remote_observer(),
-              OnRemoteServiceStateUpdated(REMOTE_SERVICE_DISABLED, _))
-      .Times(AtLeast(1));
-  EXPECT_CALL(*mock_remote_observer(), OnRemoteChangeQueueUpdated(0))
-      .Times(AnyNumber());
-
-  InSequence sequence;
-
-  // Expect to call GetResourceList for the sync root from
-  // RegisterOriginForTrackingChanges.
-  SetUpDriveServiceExpectCallsForGetSyncRoot();
-
-  SetUpDriveServiceExpectCallsForSearchByTitle(
-      "chromeos/sync_file_system/origin_directory_found.json",
-      drive::APIUtil::OriginToDirectoryTitle(kOrigin),
-      kSyncRootResourceId);
-
-  // Usually the sync service starts batch sync here, but since we're
-  // setting up a drive service with sync disabled batch sync doesn't
-  // start (while register origin should still return OK).
-
-  SetUpDriveSyncService(false);
-  bool done = false;
-  sync_service()->RegisterOriginForTrackingChanges(
-      kOrigin, base::Bind(&ExpectEqStatus, &done, SYNC_STATUS_OK));
-  message_loop()->RunUntilIdle();
-  EXPECT_TRUE(done);
-
-  // We must not have started batch sync for the newly registered origin,
-  // so it should still be in the batch_sync_origins.
-  VerifySizeOfRegisteredOrigins(1u, 0u, 0u);
-  EXPECT_TRUE(!remote_change_handler().HasChanges());
-}
-
-TEST_F(DriveFileSyncServiceMockTest, RemoteChange_Override) {
-  const GURL kOrigin = ExtensionNameToGURL(FPL("example1"));
-  const std::string kDirectoryResourceId("folder:origin_directory_resource_id");
-  const std::string kSyncRootResourceId("folder:sync_root_resource_id");
-  const base::FilePath kFilePath(FPL("File 1.mp3"));
-  const std::string kFileResourceId("file:2_file_resource_id");
-  const std::string kFileResourceId2("file:2_file_resource_id_2");
-  const fileapi::FileSystemURL kURL(CreateURL(kOrigin, kFilePath.value()));
-
-  metadata_store()->SetSyncRootDirectory(kSyncRootResourceId);
-  metadata_store()->AddIncrementalSyncOrigin(kOrigin, kDirectoryResourceId);
-
-  EXPECT_CALL(*mock_remote_observer(), OnRemoteChangeQueueUpdated(_))
-      .Times(AnyNumber());
-
-  SetUpDriveSyncService(true);
-
-  EXPECT_TRUE(AppendIncrementalRemoteChange(
-      kOrigin, kFilePath, false /* is_deleted */,
-      kFileResourceId, 2, "remote_file_md5"));
-
-  // Expect to drop this change since there is another newer change on the
-  // queue.
-  EXPECT_FALSE(AppendIncrementalRemoteChange(
-      kOrigin, kFilePath, false /* is_deleted */,
-      kFileResourceId, 1, "remote_file_md5_2"));
-
-  // Expect to drop this change since it has the same md5 with the previous one.
-  EXPECT_FALSE(AppendIncrementalRemoteChange(
-      kOrigin, kFilePath, false /* is_deleted */,
-      kFileResourceId, 4, "remote_file_md5"));
-
-  // This should not cause browser crash.
-  EXPECT_FALSE(AppendIncrementalRemoteChange(
-      kOrigin, kFilePath, false /* is_deleted */,
-      kFileResourceId, 4, "remote_file_md5"));
-
-  // Expect to drop these changes since they have different resource IDs with
-  // the previous ones.
-  EXPECT_FALSE(AppendIncrementalRemoteChange(
-      kOrigin, kFilePath, false /* is_deleted */,
-      kFileResourceId2, 5, "updated_file_md5"));
-  EXPECT_FALSE(AppendIncrementalRemoteChange(
-      kOrigin, kFilePath, true /* is_deleted */,
-      kFileResourceId2, 5, "deleted_file_md5"));
-
-  // Push delete change.
-  EXPECT_TRUE(AppendIncrementalRemoteChange(
-      kOrigin, kFilePath, true /* is_deleted */,
-      kFileResourceId, 6, "deleted_file_md5"));
-
-  // Expect to drop this delete change since it has a different resource ID with
-  // the previous one.
-  EXPECT_FALSE(AppendIncrementalRemoteChange(
-      kOrigin, kFilePath, true /* is_deleted */,
-      kFileResourceId2, 7, "deleted_file_md5"));
-
-  // Expect not to drop this change even if it has a different resource ID with
-  // the previous one.
-  EXPECT_TRUE(AppendIncrementalRemoteChange(
-      kOrigin, kFilePath, false /* is_deleted */,
-      kFileResourceId2, 8, "updated_file_md5"));
-}
-
-TEST_F(DriveFileSyncServiceMockTest, RemoteChange_Folder) {
-  const GURL kOrigin = ExtensionNameToGURL(FPL("example1"));
-  const std::string kDirectoryResourceId("folder:origin_directory_resource_id");
-  const std::string kSyncRootResourceId("folder:sync_root_resource_id");
-
-  metadata_store()->SetSyncRootDirectory(kSyncRootResourceId);
-  metadata_store()->AddIncrementalSyncOrigin(kOrigin, kDirectoryResourceId);
-
-  EXPECT_CALL(*mock_remote_observer(), OnRemoteChangeQueueUpdated(_))
-      .Times(AnyNumber());
-
-  SetUpDriveSyncService(true);
-
-  scoped_ptr<ResourceEntry> entry(ResourceEntry::ExtractAndParse(
-      *LoadJSONFile("chromeos/gdata/file_entry.json")));
-  entry->set_kind(google_apis::ENTRY_KIND_FOLDER);
-
-  // Expect to drop this change for file.
-  EXPECT_FALSE(AppendIncrementalRemoteChangeByEntry(
-      kOrigin, *entry, 1));
-}
-
-#endif  // !defined(OS_ANDROID)
-
-}  // namespace sync_file_system
diff --git a/chrome/browser/sync_file_system/drive_file_sync_service_sync_unittest.cc b/chrome/browser/sync_file_system/drive_file_sync_service_sync_unittest.cc
index d4ca730..60eb89f 100644
--- a/chrome/browser/sync_file_system/drive_file_sync_service_sync_unittest.cc
+++ b/chrome/browser/sync_file_system/drive_file_sync_service_sync_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,541 +6,629 @@
 
 #include <algorithm>
 
-#include "base/format_macros.h"
+#include "base/file_util.h"
 #include "base/message_loop.h"
-#include "base/rand_util.h"
+#include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/sync_file_system/drive/fake_api_util.h"
-#include "chrome/browser/sync_file_system/drive/metadata_db_migration_util.h"
+#include "base/threading/sequenced_worker_pool.h"
+#include "chrome/browser/drive/drive_uploader.h"
+#include "chrome/browser/drive/fake_drive_service.h"
+#include "chrome/browser/sync_file_system/drive_backend/api_util.h"
+#include "chrome/browser/sync_file_system/drive_backend/fake_drive_service_helper.h"
 #include "chrome/browser/sync_file_system/drive_file_sync_util.h"
 #include "chrome/browser/sync_file_system/drive_metadata_store.h"
 #include "chrome/browser/sync_file_system/fake_remote_change_processor.h"
-#include "chrome/browser/sync_file_system/sync_file_system.pb.h"
+#include "chrome/browser/sync_file_system/local_file_sync_service.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/browser/fileapi/file_system_context.h"
+#include "webkit/browser/fileapi/syncable/canned_syncable_file_system.h"
+#include "webkit/browser/fileapi/syncable/local_file_sync_context.h"
 #include "webkit/browser/fileapi/syncable/syncable_file_system_util.h"
 
+#define FPL(path) FILE_PATH_LITERAL(path)
+
+using content::BrowserThread;
+
+using google_apis::GDataErrorCode;
+using google_apis::ResourceEntry;
+
 namespace sync_file_system {
 
+using drive_backend::APIUtil;
+using drive_backend::APIUtilInterface;
+using drive_backend::FakeDriveServiceHelper;
+
 namespace {
 
-const char kAppId[] = "app-id";
-const char kAppOrigin[] = "chrome-extension://app-id";
-
-std::string GetSyncRootResourceId() {
-  const std::string kSyncRootResourceId("folder:sync_root_resource_id");
-  return IsDriveAPIDisabled() ? kSyncRootResourceId
-                              : drive::RemoveWapiIdPrefix(kSyncRootResourceId);
-}
-
-std::string GetParentResourceId() {
-  const std::string kParentResourceId("folder:parent_resource_id");
-  return IsDriveAPIDisabled() ? kParentResourceId
-                              : drive::RemoveWapiIdPrefix(kParentResourceId);
-}
-
-void DidInitialize(bool* done, SyncStatusCode status, bool created) {
-  EXPECT_EQ(SYNC_STATUS_OK, status);
+void SyncResultCallback(bool* done,
+                        SyncStatusCode* status_out,
+                        fileapi::FileSystemURL* url_out,
+                        SyncStatusCode status,
+                        const fileapi::FileSystemURL& url) {
+  EXPECT_FALSE(*done);
+  *status_out = status;
+  *url_out = url;
   *done = true;
 }
 
-void DidProcessRemoteChange(bool* done,
-                            SyncStatusCode* status_out,
-                            SyncStatusCode status,
-                            const fileapi::FileSystemURL& url) {
+void SyncStatusResultCallback(bool* done,
+                              SyncStatusCode* status_out,
+                              SyncStatusCode status) {
+  EXPECT_FALSE(*done);
   *status_out = status;
   *done = true;
 }
 
+void DatabaseInitResultCallback(bool* done,
+                                SyncStatusCode* status_out,
+                                bool* created_out,
+                                SyncStatusCode status,
+                                bool created) {
+  EXPECT_FALSE(*done);
+  *status_out = status;
+  *created_out = created;
+  *done = true;
+}
+
 }  // namespace
 
 class DriveFileSyncServiceSyncTest : public testing::Test {
  public:
   DriveFileSyncServiceSyncTest()
-      : ui_thread_(content::BrowserThread::UI, &message_loop_),
-        file_thread_(content::BrowserThread::FILE, &message_loop_),
-        fake_api_util_(NULL),
-        metadata_store_(NULL),
-        resource_count_(0) {}
+      : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {}
 
   virtual ~DriveFileSyncServiceSyncTest() {
   }
 
   virtual void SetUp() OVERRIDE {
-    SetEnableSyncFSDirectoryOperation(true);
+    // TODO(tzik): Set up TestExtensionSystem to support simulated relaunch.
+
     RegisterSyncableFileSystem();
+    local_sync_service_.reset(new LocalFileSyncService(&profile_));
+
+    fake_drive_service_ = new ::drive::FakeDriveService();
+    fake_drive_service_->Initialize(&profile_);
+    ASSERT_TRUE(fake_drive_service_->LoadAccountMetadataForWapi(
+        "sync_file_system/account_metadata.json"));
+    ASSERT_TRUE(fake_drive_service_->LoadResourceListForWapi(
+        "gdata/root_feed.json"));
+
+    drive_uploader_ = new ::drive::DriveUploader(
+        fake_drive_service_, base::MessageLoopProxy::current().get());
+
+    fake_drive_helper_.reset(new FakeDriveServiceHelper(
+        fake_drive_service_, drive_uploader_));
+
+    bool done = false;
+    SyncStatusCode status = SYNC_STATUS_UNKNOWN;
+    bool created = false;
+    scoped_ptr<DriveMetadataStore> metadata_store(
+        new DriveMetadataStore(fake_drive_helper_->base_dir_path(),
+                               base::MessageLoopProxy::current().get()));
+    metadata_store->Initialize(
+        base::Bind(&DatabaseInitResultCallback, &done, &status, &created));
+    FlushMessageLoop();
+    EXPECT_TRUE(done);
+    EXPECT_EQ(SYNC_STATUS_OK, status);
+    EXPECT_TRUE(created);
+
+    scoped_ptr<APIUtil> api_util(APIUtil::CreateForTesting(
+        &profile_,
+        scoped_ptr< ::drive::DriveServiceInterface>(fake_drive_service_),
+        scoped_ptr< ::drive::DriveUploaderInterface>(drive_uploader_)));
+
+    remote_sync_service_ = DriveFileSyncService::CreateForTesting(
+        &profile_,
+        fake_drive_helper_->base_dir_path(),
+        api_util.PassAs<APIUtilInterface>(),
+        metadata_store.Pass());
+
+    local_sync_service_->SetLocalChangeProcessor(remote_sync_service_.get());
+    remote_sync_service_->SetRemoteChangeProcessor(local_sync_service_.get());
   }
 
   virtual void TearDown() OVERRIDE {
-    SetDisableDriveAPI(false);
+    drive_uploader_ = NULL;
+    fake_drive_service_ = NULL;
+    remote_sync_service_.reset();
+    local_sync_service_.reset();
+    FlushMessageLoop();
+
+    typedef std::map<GURL, CannedSyncableFileSystem*>::iterator iterator;
+    for (iterator itr = file_systems_.begin();
+         itr != file_systems_.end(); ++itr) {
+      itr->second->TearDown();
+      delete itr->second;
+    }
+    file_systems_.clear();
+
+    FlushMessageLoop();
     RevokeSyncableFileSystem();
-    SetEnableSyncFSDirectoryOperation(false);
   }
 
  protected:
-  struct SyncEvent {
-    std::string description;
-    base::Closure callback;
+  void RegisterOrigin(const GURL& origin) {
+    if (!ContainsKey(file_systems_, origin)) {
+      CannedSyncableFileSystem* file_system = new CannedSyncableFileSystem(
+          origin,
+          BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO).get(),
+          BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)
+              .get());
 
-    SyncEvent(const std::string& description,
-              base::Closure callback)
-        : description(description),
-          callback(callback) {
+      bool done = false;
+      SyncStatusCode status = SYNC_STATUS_UNKNOWN;
+      file_system->SetUp();
+      local_sync_service_->MaybeInitializeFileSystemContext(
+          origin, file_system->file_system_context(),
+          base::Bind(&SyncStatusResultCallback, &done, &status));
+      FlushMessageLoop();
+      EXPECT_TRUE(done);
+      EXPECT_EQ(SYNC_STATUS_OK, status);
+
+      file_system->file_system_context()->sync_context()->
+          set_mock_notify_changes_duration_in_sec(0);
+
+      EXPECT_EQ(base::PLATFORM_FILE_OK, file_system->OpenFileSystem());
+      file_systems_[origin] = file_system;
     }
-  };
 
-  SyncEvent CreateRemoteFileAddOrUpdateEvent(const std::string& title) {
-    return SyncEvent(
-        "SyncEvent: Add or Update remote file [" + title + "]",
-        base::Bind(&DriveFileSyncServiceSyncTest::AddOrUpdateResource,
-                   base::Unretained(this), title, SYNC_FILE_TYPE_FILE));
-  }
-
-  SyncEvent CreateRemoteDirectoryAddEvent(const std::string& title) {
-    return SyncEvent(
-        "SyncEvent: Add remote directory [" + title + "]",
-        base::Bind(&DriveFileSyncServiceSyncTest::AddOrUpdateResource,
-                   base::Unretained(this), title, SYNC_FILE_TYPE_DIRECTORY));
-  }
-
-  SyncEvent CreateRemoteFileDeleteEvent(const std::string& title) {
-    return SyncEvent(
-        "SyncEvent: Delete remote file [" + title + "]",
-        base::Bind(&DriveFileSyncServiceSyncTest::DeleteResource,
-                   base::Unretained(this), title));
-  }
-
-  SyncEvent CreateRelaunchEvent() {
-    return SyncEvent(
-        "SyncEvent: Relaunch service",
-        base::Bind(&DriveFileSyncServiceSyncTest::RelaunchService,
-                   base::Unretained(this)));
-  }
-
-  SyncEvent CreateFetchEvent() {
-    return SyncEvent(
-        "SyncEvent: Fetch remote changes",
-        base::Bind(&DriveFileSyncServiceSyncTest::FetchRemoteChange,
-                   base::Unretained(this)));
-  }
-
-  SyncEvent CreateProcessRemoteChangeEvent() {
-    return SyncEvent(
-        "SyncEvent: Process remote change",
-        base::Bind(
-            base::IgnoreResult(
-                &DriveFileSyncServiceSyncTest::ProcessRemoteChange),
-            base::Unretained(this)));
-  }
-
-  template <size_t array_size>
-  std::vector<SyncEvent> CreateTestCase(const SyncEvent (&events)[array_size]) {
-    return std::vector<SyncEvent>(events, events + array_size);
-  }
-
-  void ShuffleTestCase(std::vector<SyncEvent>* events) {
-    std::random_shuffle(events->begin(), events->end(), base::RandGenerator);
-  }
-
-  void RunTest(const std::vector<SyncEvent>& events) {
-    base::ScopedTempDir scoped_base_dir_;
-    ASSERT_TRUE(scoped_base_dir_.CreateUniqueTempDir());
-    base_dir_ = scoped_base_dir_.path();
-
-    SetUpForTestCase();
-
-    typedef std::vector<SyncEvent>::const_iterator iterator;
-    std::ostringstream out;
-    out << '\n';
-    for (iterator itr = events.begin(); itr != events.end(); ++itr)
-      out << itr->description << '\n';
-    SCOPED_TRACE(out.str());
-
-    for (iterator itr = events.begin(); itr != events.end(); ++itr)
-      itr->callback.Run();
-
-    FetchRemoteChange();
-    while (ProcessRemoteChange()) {}
-
-    VerifyResult();
-    TearDownForTestCase();
-
-    base_dir_ = base::FilePath();
-  }
-
-  void AddFileTest_Body();
-  void UpdateFileTest_Body();
-  void DeleteFileTest_Body();
-  void RelaunchTest_Body();
-  void SquashedFileAddTest_Body();
-  void RelaunchTestWithSquashedDeletion_Body();
-  void CreateDirectoryTest_Body();
-  void DeleteDirectoryTest_Body();
-
- private:
-  void SetUpForTestCase() {
-    fake_api_util_ = new drive::FakeAPIUtil;
-    fake_remote_processor_.reset(new FakeRemoteChangeProcessor);
-
-    metadata_store_ = new DriveMetadataStore(
-        base_dir_, base::MessageLoopProxy::current().get());
-
-    bool done = false;
-    metadata_store_->Initialize(base::Bind(&DidInitialize, &done));
-    message_loop_.RunUntilIdle();
-    EXPECT_TRUE(done);
-
-    metadata_store_->SetSyncRootDirectory(GetSyncRootResourceId());
-    metadata_store_->AddIncrementalSyncOrigin(GURL(kAppOrigin),
-                                              GetParentResourceId());
-
-    sync_service_ = DriveFileSyncService::CreateForTesting(
-        &profile_,
-        base_dir_,
-        scoped_ptr<drive::APIUtilInterface>(fake_api_util_),
-        scoped_ptr<DriveMetadataStore>(metadata_store_)).Pass();
-    sync_service_->SetRemoteChangeProcessor(fake_remote_processor_.get());
-  }
-
-  void TearDownForTestCase() {
-    metadata_store_ = NULL;
-    fake_api_util_ = NULL;
-    sync_service_.reset();
-    fake_remote_processor_.reset();
-    message_loop_.RunUntilIdle();
-  }
-
-  void AddOrUpdateResource(const std::string& title,
-                           SyncFileType type) {
-    typedef ResourceIdByTitle::iterator iterator;
-    std::pair<iterator, bool> inserted =
-        resources_.insert(std::make_pair(title, std::string()));
-    if (inserted.second) {
-      switch (type) {
-        case SYNC_FILE_TYPE_UNKNOWN:
-          NOTREACHED();
-          break;
-        case SYNC_FILE_TYPE_FILE:
-          inserted.first->second = IsDriveAPIDisabled()
-              ? base::StringPrintf("file:%" PRId64, ++resource_count_)
-              : base::StringPrintf("%" PRId64, ++resource_count_);
-          break;
-        case SYNC_FILE_TYPE_DIRECTORY:
-          inserted.first->second = IsDriveAPIDisabled()
-              ? base::StringPrintf("folder:%" PRId64, ++resource_count_)
-              : base::StringPrintf("%" PRId64, ++resource_count_);
-          break;
-      }
-    }
-    std::string resource_id = inserted.first->second;
-    std::string md5_checksum;
-    if (type == SYNC_FILE_TYPE_FILE)
-      md5_checksum = base::StringPrintf("%" PRIx64, base::RandUint64());
-
-    fake_api_util_->PushRemoteChange(GetParentResourceId(),
-                                     kAppId,
-                                     title,
-                                     resource_id,
-                                     md5_checksum,
-                                     type,
-                                     false /* deleted */);
-    message_loop_.RunUntilIdle();
-  }
-
-  void DeleteResource(const std::string& title) {
-    ResourceIdByTitle::iterator found = resources_.find(title);
-    if (found == resources_.end())
-      return;
-    std::string resource_id = found->second;
-    resources_.erase(found);
-    fake_api_util_->PushRemoteChange(GetParentResourceId(),
-                                     kAppId,
-                                     title,
-                                     resource_id,
-                                     std::string(),
-                                     SYNC_FILE_TYPE_UNKNOWN,
-                                     true /* deleted */);
-    message_loop_.RunUntilIdle();
-  }
-
-  void RelaunchService() {
-    metadata_store_ = NULL;
-    scoped_ptr<drive::APIUtilInterface> api_util =
-        DriveFileSyncService::DestroyAndPassAPIUtilForTesting(
-            sync_service_.Pass());
-    message_loop_.RunUntilIdle();
-
-    metadata_store_ = new DriveMetadataStore(
-        base_dir_, base::MessageLoopProxy::current().get());
-
-    bool done = false;
-    metadata_store_->Initialize(base::Bind(&DidInitialize, &done));
-    message_loop_.RunUntilIdle();
-    EXPECT_TRUE(done);
-
-    sync_service_ = DriveFileSyncService::CreateForTesting(
-        &profile_,
-        base_dir_,
-        api_util.Pass(),
-        scoped_ptr<DriveMetadataStore>(metadata_store_)).Pass();
-    sync_service_->SetRemoteChangeProcessor(fake_remote_processor_.get());
-  }
-
-  void FetchRemoteChange() {
-    sync_service_->may_have_unfetched_changes_ = true;
-    sync_service_->MaybeStartFetchChanges();
-    message_loop_.RunUntilIdle();
-  }
-
-  bool ProcessRemoteChange() {
     bool done = false;
     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
-    sync_service_->ProcessRemoteChange(
-        base::Bind(&DidProcessRemoteChange, &done, &status));
-    message_loop_.RunUntilIdle();
+    remote_sync_service_->RegisterOriginForTrackingChanges(
+        origin, base::Bind(&SyncStatusResultCallback, &done, &status));
+    FlushMessageLoop();
     EXPECT_TRUE(done);
-    return status != SYNC_STATUS_NO_CHANGE_TO_SYNC;
+    EXPECT_EQ(SYNC_STATUS_OK, status);
   }
 
+  void AddLocalFolder(const GURL& origin,
+                      const base::FilePath& path) {
+    ASSERT_TRUE(ContainsKey(file_systems_, origin));
+    EXPECT_EQ(base::PLATFORM_FILE_OK,
+              file_systems_[origin]->CreateDirectory(
+                  CreateSyncableFileSystemURL(origin, path)));
+  }
 
-  void VerifyResult() {
-    typedef drive::FakeAPIUtil::RemoteResourceByResourceId RemoteResourceMap;
-    typedef drive::FakeAPIUtil::RemoteResource RemoteResource;
-    typedef FakeRemoteChangeProcessor::URLToFileChangesMap
-        AppliedRemoteChangeMap;
+  void AddOrUpdateLocalFile(const GURL& origin,
+                            const base::FilePath& path,
+                            const std::string& content) {
+    fileapi::FileSystemURL url(CreateSyncableFileSystemURL(origin, path));
+    ASSERT_TRUE(ContainsKey(file_systems_, origin));
+    EXPECT_EQ(base::PLATFORM_FILE_OK, file_systems_[origin]->CreateFile(url));
+    int64 bytes_written = file_systems_[origin]->WriteString(url, content);
+    EXPECT_EQ(static_cast<int64>(content.size()), bytes_written);
+    FlushMessageLoop();
+  }
 
-    const RemoteResourceMap& remote_resources =
-        fake_api_util_->remote_resources();
-    const AppliedRemoteChangeMap applied_changes =
-        fake_remote_processor_->GetAppliedRemoteChanges();
+  void UpdateLocalFile(const GURL& origin,
+                       const base::FilePath& path,
+                       const std::string& content) {
+    ASSERT_TRUE(ContainsKey(file_systems_, origin));
+    int64 bytes_written = file_systems_[origin]->WriteString(
+        CreateSyncableFileSystemURL(origin, path), content);
+    EXPECT_EQ(static_cast<int64>(content.size()), bytes_written);
+    FlushMessageLoop();
+  }
 
-    std::set<std::string> local_resources;
-    for (AppliedRemoteChangeMap::const_iterator itr = applied_changes.begin();
-         itr != applied_changes.end(); ++itr) {
-      const fileapi::FileSystemURL& url = itr->first;
-      const FileChange& applied_change = itr->second.back();
+  void RemoveLocal(const GURL& origin, const base::FilePath& path) {
+    ASSERT_TRUE(ContainsKey(file_systems_, origin));
+    EXPECT_EQ(base::PLATFORM_FILE_OK,
+              file_systems_[origin]->Remove(
+                  CreateSyncableFileSystemURL(origin, path),
+                  true /* recursive */));
+    FlushMessageLoop();
+  }
 
-      DriveMetadata metadata;
-      SyncStatusCode status = metadata_store_->ReadEntry(itr->first, &metadata);
-      if (applied_change.IsDelete()) {
-        EXPECT_EQ(SYNC_DATABASE_ERROR_NOT_FOUND, status);
-        continue;
+  SyncStatusCode ProcessLocalChange() {
+    bool done = false;
+    SyncStatusCode status = SYNC_STATUS_UNKNOWN;
+    fileapi::FileSystemURL url;
+    local_sync_service_->ProcessLocalChange(
+        base::Bind(&SyncResultCallback, &done, &status, &url));
+    FlushMessageLoop();
+    EXPECT_TRUE(done);
+    if (status != SYNC_STATUS_NO_CHANGE_TO_SYNC)
+      local_sync_service_->ClearSyncFlagForURL(url);
+    return status;
+  }
+
+  SyncStatusCode ProcessRemoteChange() {
+    bool done = false;
+    SyncStatusCode status = SYNC_STATUS_UNKNOWN;
+    fileapi::FileSystemURL url;
+    remote_sync_service_->ProcessRemoteChange(
+        base::Bind(&SyncResultCallback, &done, &status, &url));
+    FlushMessageLoop();
+    EXPECT_TRUE(done);
+    if (status != SYNC_STATUS_NO_CHANGE_TO_SYNC)
+      local_sync_service_->ClearSyncFlagForURL(url);
+    return status;
+  }
+
+  SyncStatusCode ProcessChangesUntilDone() {
+    remote_sync_service_->OnNotificationReceived();
+    FlushMessageLoop();
+
+    SyncStatusCode local_sync_status;
+    SyncStatusCode remote_sync_status;
+    do {
+      local_sync_status = ProcessLocalChange();
+      if (local_sync_status != SYNC_STATUS_OK &&
+          local_sync_status != SYNC_STATUS_NO_CHANGE_TO_SYNC)
+        return local_sync_status;
+
+      remote_sync_status = ProcessRemoteChange();
+      if (remote_sync_status != SYNC_STATUS_OK &&
+          remote_sync_status != SYNC_STATUS_NO_CHANGE_TO_SYNC)
+        return remote_sync_status;
+    } while (local_sync_status != SYNC_STATUS_NO_CHANGE_TO_SYNC &&
+             remote_sync_status != SYNC_STATUS_NO_CHANGE_TO_SYNC);
+    return SYNC_STATUS_OK;
+  }
+
+  // Verifies local and remote files/folders are consistent.
+  // This function checks:
+  //  - Each registered origin has corresponding remote folder.
+  //  - Each local file/folder has corresponding remote one.
+  //  - Each remote file/folder has corresponding local one.
+  // TODO(tzik): Handle conflict case. i.e. allow remote file has different
+  // file content if the corresponding local file conflicts to it.
+  void VerifyConsistency() {
+    std::string sync_root_folder_id;
+    GDataErrorCode error =
+        fake_drive_helper_->GetSyncRootFolderID(&sync_root_folder_id);
+    if (sync_root_folder_id.empty()) {
+      EXPECT_EQ(google_apis::HTTP_NOT_FOUND, error);
+      EXPECT_TRUE(file_systems_.empty());
+      return;
+    }
+    EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
+
+    ScopedVector<ResourceEntry> remote_entries;
+    EXPECT_EQ(google_apis::HTTP_SUCCESS,
+              fake_drive_helper_->ListFilesInFolder(
+                  sync_root_folder_id, &remote_entries));
+    std::map<std::string, const ResourceEntry*> origin_root_by_title;
+    for (ScopedVector<ResourceEntry>::iterator itr = remote_entries.begin();
+         itr != remote_entries.end();
+         ++itr) {
+      const ResourceEntry& remote_entry = **itr;
+      EXPECT_FALSE(ContainsKey(origin_root_by_title, remote_entry.title()));
+      origin_root_by_title[remote_entry.title()] = *itr;
+    }
+
+    for (std::map<GURL, CannedSyncableFileSystem*>::const_iterator itr =
+             file_systems_.begin();
+         itr != file_systems_.end(); ++itr) {
+      const GURL& origin = itr->first;
+      SCOPED_TRACE(testing::Message() << "Verifying origin: " << origin);
+      CannedSyncableFileSystem* file_system = itr->second;
+      ASSERT_TRUE(ContainsKey(origin_root_by_title, origin.host()));
+      VerifyConsistencyForFolder(
+          origin, base::FilePath(),
+          origin_root_by_title[origin.host()]->resource_id(),
+          file_system);
+    }
+  }
+
+  void VerifyConsistencyForOrigin(const GURL& origin) {
+    std::string sync_root_folder_id;
+    ASSERT_EQ(google_apis::HTTP_SUCCESS,
+              fake_drive_helper_->GetSyncRootFolderID(&sync_root_folder_id));
+    ASSERT_FALSE(sync_root_folder_id.empty());
+
+    ScopedVector<ResourceEntry> origin_folder;
+    EXPECT_EQ(google_apis::HTTP_SUCCESS,
+              fake_drive_helper_->SearchByTitle(
+                  sync_root_folder_id, origin.host(), &origin_folder));
+    ASSERT_EQ(1u, origin_folder.size());
+
+    ASSERT_TRUE(ContainsKey(file_systems_, origin));
+    VerifyConsistencyForFolder(
+        origin, base::FilePath(),
+        origin_folder[0]->resource_id(),
+        file_systems_[origin]);
+  }
+
+  void VerifyConsistencyForFolder(const GURL& origin,
+                                  const base::FilePath& path,
+                                  const std::string& folder_id,
+                                  CannedSyncableFileSystem* file_system) {
+    SCOPED_TRACE(testing::Message() << "Verifying path: " << path.value());
+
+    ScopedVector<ResourceEntry> remote_entries;
+    EXPECT_EQ(google_apis::HTTP_SUCCESS,
+              fake_drive_helper_->ListFilesInFolder(
+                  folder_id, &remote_entries));
+    std::map<std::string, const ResourceEntry*> remote_entry_by_title;
+    for (ScopedVector<ResourceEntry>::iterator itr = remote_entries.begin();
+         itr != remote_entries.end();
+         ++itr) {
+      const ResourceEntry& remote_entry = **itr;
+      EXPECT_FALSE(ContainsKey(remote_entry_by_title, remote_entry.title()));
+      remote_entry_by_title[remote_entry.title()] = *itr;
+    }
+
+    fileapi::FileSystemURL url(CreateSyncableFileSystemURL(origin, path));
+    CannedSyncableFileSystem::FileEntryList local_entries;
+    EXPECT_EQ(base::PLATFORM_FILE_OK,
+              file_system->ReadDirectory(url, &local_entries));
+    for (CannedSyncableFileSystem::FileEntryList::iterator itr =
+             local_entries.begin();
+         itr != local_entries.end();
+         ++itr) {
+      const fileapi::DirectoryEntry& local_entry = *itr;
+      fileapi::FileSystemURL entry_url(
+          CreateSyncableFileSystemURL(origin, path.Append(local_entry.name)));
+      std::string title = DriveFileSyncService::PathToTitle(entry_url.path());
+      ASSERT_TRUE(ContainsKey(remote_entry_by_title, title));
+      const ResourceEntry& remote_entry = *remote_entry_by_title[title];
+      if (local_entry.is_directory) {
+        ASSERT_TRUE(remote_entry.is_folder());
+        VerifyConsistencyForFolder(origin, entry_url.path(),
+                                   remote_entry.resource_id(),
+                                   file_system);
+      } else {
+        ASSERT_TRUE(remote_entry.is_file());
+        VerifyConsistencyForFile(origin, entry_url.path(),
+                                 remote_entry.resource_id(),
+                                 file_system);
       }
-
-      EXPECT_EQ(SYNC_STATUS_OK, status);
-      EXPECT_FALSE(metadata.resource_id().empty());
-      EXPECT_FALSE(metadata.conflicted());
-      EXPECT_FALSE(metadata.to_be_fetched());
-      EXPECT_TRUE(metadata.type() == DriveMetadata::RESOURCE_TYPE_FOLDER ||
-                  !metadata.md5_checksum().empty());
-
-      RemoteResourceMap::const_iterator found =
-          remote_resources.find(metadata.resource_id());
-      ASSERT_TRUE(found != remote_resources.end());
-      const RemoteResource& remote_resource = found->second;
-
-      EXPECT_EQ(base::FilePath::FromUTF8Unsafe(remote_resource.title),
-                url.path());
-      EXPECT_EQ(remote_resource.md5_checksum, metadata.md5_checksum());
-      EXPECT_FALSE(remote_resource.deleted);
-
-      EXPECT_TRUE(local_resources.insert(metadata.resource_id()).second);
+      remote_entry_by_title.erase(title);
     }
 
-    for (RemoteResourceMap::const_iterator itr = remote_resources.begin();
-         itr != remote_resources.end(); ++itr) {
-      if (!itr->second.deleted)
-        EXPECT_TRUE(ContainsKey(local_resources, itr->first));
-      else
-        EXPECT_FALSE(ContainsKey(local_resources, itr->first));
-    }
+    EXPECT_TRUE(remote_entry_by_title.empty());
   }
 
-  base::MessageLoop message_loop_;
-  content::TestBrowserThread ui_thread_;
-  content::TestBrowserThread file_thread_;
+  void VerifyConsistencyForFile(const GURL& origin,
+                                const base::FilePath& path,
+                                const std::string& file_id,
+                                CannedSyncableFileSystem* file_system) {
+    fileapi::FileSystemURL url(CreateSyncableFileSystemURL(origin, path));
+    std::string file_content;
+    EXPECT_EQ(google_apis::HTTP_SUCCESS,
+              fake_drive_helper_->ReadFile(file_id, &file_content));
+    EXPECT_EQ(base::PLATFORM_FILE_OK,
+              file_system->VerifyFile(url, file_content));
+  }
+
+  void FlushMessageLoop() {
+    base::MessageLoop::current()->RunUntilIdle();
+    BrowserThread::GetBlockingPool()->FlushForTesting();
+    base::MessageLoop::current()->RunUntilIdle();
+  }
+
+  void TestInitialization();
+  void TestLocalToRemoteBasic();
+  void TestRemoteToLocalBasic();
+  void TestLocalFileUpdate();
+  void TestRemoteFileUpdate();
+  void TestLocalFileDeletion();
+  void TestRemoteFileDeletion();
+
+  content::TestBrowserThreadBundle thread_bundle_;
 
   TestingProfile profile_;
-  base::FilePath base_dir_;
 
-  drive::FakeAPIUtil* fake_api_util_;  // Owned by |sync_service_|.
-  scoped_ptr<FakeRemoteChangeProcessor> fake_remote_processor_;
-  DriveMetadataStore* metadata_store_;  // Owned by |sync_service_|.
+  ::drive::FakeDriveService* fake_drive_service_;
+  ::drive::DriveUploader* drive_uploader_;
+  scoped_ptr<FakeDriveServiceHelper> fake_drive_helper_;
+  std::map<GURL, CannedSyncableFileSystem*> file_systems_;
 
-  scoped_ptr<DriveFileSyncService> sync_service_;
-
-  typedef std::map<std::string, std::string> ResourceIdByTitle;
-  ResourceIdByTitle resources_;
-  int64 resource_count_;
+  scoped_ptr<DriveFileSyncService> remote_sync_service_;
+  scoped_ptr<LocalFileSyncService> local_sync_service_;
 
   DISALLOW_COPY_AND_ASSIGN(DriveFileSyncServiceSyncTest);
 };
 
-void DriveFileSyncServiceSyncTest::AddFileTest_Body() {
-  std::string kFile1 = "file title 1";
-  SyncEvent sync_event[] = {
-    CreateRemoteFileAddOrUpdateEvent(kFile1),
-  };
-
-  RunTest(CreateTestCase(sync_event));
+void DriveFileSyncServiceSyncTest::TestInitialization() {
+  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
+  VerifyConsistency();
 }
 
-void DriveFileSyncServiceSyncTest::UpdateFileTest_Body() {
-  std::string kFile1 = "file title 1";
-  SyncEvent sync_event[] = {
-    CreateRemoteFileAddOrUpdateEvent(kFile1),
-    CreateRemoteFileAddOrUpdateEvent(kFile1),
-  };
+void DriveFileSyncServiceSyncTest::TestLocalToRemoteBasic() {
+  const GURL kOrigin("chrome-extension://example");
 
-  RunTest(CreateTestCase(sync_event));
+  RegisterOrigin(kOrigin);
+  AddOrUpdateLocalFile(kOrigin, base::FilePath(FPL("file")), "abcde");
+
+  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
+  VerifyConsistency();
 }
 
-void DriveFileSyncServiceSyncTest::DeleteFileTest_Body() {
-  std::string kFile1 = "file title 1";
-  SyncEvent sync_event[] = {
-    CreateRemoteFileAddOrUpdateEvent(kFile1),
-    CreateFetchEvent(),
-    CreateProcessRemoteChangeEvent(),
-    CreateRemoteFileDeleteEvent(kFile1),
-  };
+void DriveFileSyncServiceSyncTest::TestRemoteToLocalBasic() {
+  const GURL kOrigin("chrome-extension://example");
 
-  RunTest(CreateTestCase(sync_event));
+  std::string sync_root_folder_id;
+  EXPECT_EQ(google_apis::HTTP_CREATED,
+            fake_drive_helper_->AddOrphanedFolder(
+                APIUtil::GetSyncRootDirectoryName(),
+                &sync_root_folder_id));
+
+  std::string origin_root_folder_id;
+  EXPECT_EQ(google_apis::HTTP_CREATED,
+            fake_drive_helper_->AddFolder(
+                sync_root_folder_id, kOrigin.host(), &origin_root_folder_id));
+
+  RegisterOrigin(kOrigin);
+
+  std::string file_id;
+  EXPECT_EQ(google_apis::HTTP_SUCCESS,
+            fake_drive_helper_->AddFile(
+                origin_root_folder_id, "file", "abcde", &file_id));
+
+  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
+  VerifyConsistency();
 }
 
-void DriveFileSyncServiceSyncTest::RelaunchTest_Body() {
-  SyncEvent sync_event[] = {
-    CreateRelaunchEvent(),
-  };
+void DriveFileSyncServiceSyncTest::TestLocalFileUpdate() {
+  const GURL kOrigin("chrome-extension://example");
+  const base::FilePath kPath(FPL("file"));
 
-  RunTest(CreateTestCase(sync_event));
+  RegisterOrigin(kOrigin);
+  AddOrUpdateLocalFile(kOrigin, kPath, "abcde");
+
+  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
+  VerifyConsistencyForOrigin(kOrigin);
+
+  UpdateLocalFile(kOrigin, kPath, "1234567890");
+
+  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
+  VerifyConsistency();
 }
 
-void DriveFileSyncServiceSyncTest::SquashedFileAddTest_Body() {
-  std::string kFile1 = "file title 1";
-  SyncEvent sync_event[] = {
-    CreateRemoteFileAddOrUpdateEvent(kFile1),
-    CreateFetchEvent(),
-    CreateRemoteFileDeleteEvent(kFile1),
-  };
-  RunTest(CreateTestCase(sync_event));
+void DriveFileSyncServiceSyncTest::TestRemoteFileUpdate() {
+  const GURL kOrigin("chrome-extension://example");
+  const base::FilePath kPath(FPL("file"));
+  const std::string kTitle(DriveFileSyncService::PathToTitle(kPath));
+
+  std::string sync_root_folder_id;
+  EXPECT_EQ(google_apis::HTTP_CREATED,
+            fake_drive_helper_->AddOrphanedFolder(
+                APIUtil::GetSyncRootDirectoryName(),
+                &sync_root_folder_id));
+
+  std::string origin_root_folder_id;
+  EXPECT_EQ(google_apis::HTTP_CREATED,
+            fake_drive_helper_->AddFolder(
+                sync_root_folder_id, kOrigin.host(), &origin_root_folder_id));
+
+  std::string remote_file_id;
+  EXPECT_EQ(google_apis::HTTP_SUCCESS,
+            fake_drive_helper_->AddFile(
+                origin_root_folder_id, kTitle, "abcde", &remote_file_id));
+
+  RegisterOrigin(kOrigin);
+  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
+  VerifyConsistencyForOrigin(kOrigin);
+
+  EXPECT_EQ(google_apis::HTTP_SUCCESS,
+            fake_drive_helper_->UpdateFile(remote_file_id, "1234567890"));
+
+  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
+  VerifyConsistency();
 }
 
-void DriveFileSyncServiceSyncTest::RelaunchTestWithSquashedDeletion_Body() {
-  std::string kFile1 = "file title 1";
-  std::string kFile2 = "file title 2";
-  SyncEvent sync_event[] = {
-    CreateRemoteFileAddOrUpdateEvent(kFile1),
-    CreateFetchEvent(),
-    CreateProcessRemoteChangeEvent(),
+void DriveFileSyncServiceSyncTest::TestLocalFileDeletion() {
+  const GURL kOrigin("chrome-extension://example");
+  const base::FilePath kPath(FPL("file"));
 
-    CreateRemoteFileDeleteEvent(kFile1),
-    CreateRemoteFileAddOrUpdateEvent(kFile2),
-    CreateRemoteFileAddOrUpdateEvent(kFile1),
+  RegisterOrigin(kOrigin);
+  AddOrUpdateLocalFile(kOrigin, kPath, "abcde");
 
-    CreateFetchEvent(),
-    CreateProcessRemoteChangeEvent(),
-    CreateRelaunchEvent(),
-  };
-  RunTest(CreateTestCase(sync_event));
+  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
+  VerifyConsistencyForOrigin(kOrigin);
+
+  RemoveLocal(kOrigin, kPath);
+
+  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
+  VerifyConsistency();
 }
 
-void DriveFileSyncServiceSyncTest::CreateDirectoryTest_Body() {
-  std::string kDir = "dir title";
-  SyncEvent sync_event[] = {
-    CreateRemoteDirectoryAddEvent(kDir),
-  };
-  RunTest(CreateTestCase(sync_event));
+void DriveFileSyncServiceSyncTest::TestRemoteFileDeletion() {
+  const GURL kOrigin("chrome-extension://example");
+  const base::FilePath kPath(FPL("file"));
+  const std::string kTitle(DriveFileSyncService::PathToTitle(kPath));
+
+  std::string sync_root_folder_id;
+  EXPECT_EQ(google_apis::HTTP_CREATED,
+            fake_drive_helper_->AddOrphanedFolder(
+                APIUtil::GetSyncRootDirectoryName(),
+                &sync_root_folder_id));
+
+  std::string origin_root_folder_id;
+  EXPECT_EQ(google_apis::HTTP_CREATED,
+            fake_drive_helper_->AddFolder(
+                sync_root_folder_id, kOrigin.host(), &origin_root_folder_id));
+
+  std::string remote_file_id;
+  EXPECT_EQ(google_apis::HTTP_SUCCESS,
+            fake_drive_helper_->AddFile(
+                origin_root_folder_id, kTitle, "abcde", &remote_file_id));
+
+  RegisterOrigin(kOrigin);
+  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
+  VerifyConsistencyForOrigin(kOrigin);
+
+  EXPECT_EQ(google_apis::HTTP_SUCCESS,
+            fake_drive_helper_->RemoveResource(remote_file_id));
+
+  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
+  VerifyConsistency();
 }
 
-void DriveFileSyncServiceSyncTest::DeleteDirectoryTest_Body() {
-  std::string kDir = "dir title";
-  SyncEvent sync_event[] = {
-    CreateRemoteDirectoryAddEvent(kDir),
-    CreateRemoteFileDeleteEvent(kDir),
-  };
-  RunTest(CreateTestCase(sync_event));
-}
-
-TEST_F(DriveFileSyncServiceSyncTest, AddFileTest) {
+TEST_F(DriveFileSyncServiceSyncTest, InitializationTest) {
   ASSERT_FALSE(IsDriveAPIDisabled());
-  AddFileTest_Body();
+  TestInitialization();
 }
 
-TEST_F(DriveFileSyncServiceSyncTest, AddFileTest_WAPI) {
-  SetDisableDriveAPI(true);
-  AddFileTest_Body();
+TEST_F(DriveFileSyncServiceSyncTest, InitializationTest_WAPI) {
+  ScopedDisableDriveAPI disable_drive_api;
+  TestInitialization();
 }
 
-TEST_F(DriveFileSyncServiceSyncTest, UpdateFileTest) {
+TEST_F(DriveFileSyncServiceSyncTest, LocalToRemoteBasicTest) {
   ASSERT_FALSE(IsDriveAPIDisabled());
-  UpdateFileTest_Body();
+  TestLocalToRemoteBasic();
 }
 
-TEST_F(DriveFileSyncServiceSyncTest, UpdateFileTest_WAPI) {
-  SetDisableDriveAPI(true);
-  UpdateFileTest_Body();
+TEST_F(DriveFileSyncServiceSyncTest, LocalToRemoteBasicTest_WAPI) {
+  ScopedDisableDriveAPI disable_drive_api;
+  TestLocalToRemoteBasic();
 }
 
-TEST_F(DriveFileSyncServiceSyncTest, DeleteFileTest) {
+TEST_F(DriveFileSyncServiceSyncTest, RemoteToLocalBasicTest) {
   ASSERT_FALSE(IsDriveAPIDisabled());
-  DeleteFileTest_Body();
+  TestRemoteToLocalBasic();
 }
 
-TEST_F(DriveFileSyncServiceSyncTest, DeleteFileTest_WAPI) {
-  SetDisableDriveAPI(true);
-  DeleteFileTest_Body();
+TEST_F(DriveFileSyncServiceSyncTest, RemoteToLocalBasicTest_WAPI) {
+  ScopedDisableDriveAPI disable_drive_api;
+  TestRemoteToLocalBasic();
 }
 
-TEST_F(DriveFileSyncServiceSyncTest, RelaunchTest) {
+TEST_F(DriveFileSyncServiceSyncTest, LocalFileUpdateTest) {
   ASSERT_FALSE(IsDriveAPIDisabled());
-  RelaunchTest_Body();
+  TestLocalFileUpdate();
 }
 
-TEST_F(DriveFileSyncServiceSyncTest, RelaunchTest_WAPI) {
-  SetDisableDriveAPI(true);
-  RelaunchTest_Body();
+TEST_F(DriveFileSyncServiceSyncTest, LocalFileUpdateTest_WAPI) {
+  ScopedDisableDriveAPI disable_drive_api;
+  TestLocalFileUpdate();
 }
 
-TEST_F(DriveFileSyncServiceSyncTest, SquashedFileAddTest) {
+TEST_F(DriveFileSyncServiceSyncTest, RemoteFileUpdateTest) {
   ASSERT_FALSE(IsDriveAPIDisabled());
-  SquashedFileAddTest_Body();
+  TestRemoteFileUpdate();
 }
 
-TEST_F(DriveFileSyncServiceSyncTest, SquashedFileAddTest_WAPI) {
-  SetDisableDriveAPI(true);
-  SquashedFileAddTest_Body();
+TEST_F(DriveFileSyncServiceSyncTest, RemoteFileUpdateTest_WAPI) {
+  ScopedDisableDriveAPI disable_drive_api;
+  TestRemoteFileUpdate();
 }
 
-TEST_F(DriveFileSyncServiceSyncTest, RelaunchTestWithSquashedDeletion) {
+TEST_F(DriveFileSyncServiceSyncTest, LocalFileDeletionTest) {
   ASSERT_FALSE(IsDriveAPIDisabled());
-  RelaunchTestWithSquashedDeletion_Body();
+  TestLocalFileDeletion();
 }
 
-TEST_F(DriveFileSyncServiceSyncTest, RelaunchTestWithSquashedDeletion_WAPI) {
-  SetDisableDriveAPI(true);
-  RelaunchTestWithSquashedDeletion_Body();
+TEST_F(DriveFileSyncServiceSyncTest, LocalFileDeletionTest_WAPI) {
+  ScopedDisableDriveAPI disable_drive_api;
+  TestLocalFileDeletion();
 }
 
-TEST_F(DriveFileSyncServiceSyncTest, CreateDirectoryTest) {
+TEST_F(DriveFileSyncServiceSyncTest, RemoteFileDeletionTest) {
   ASSERT_FALSE(IsDriveAPIDisabled());
-  CreateDirectoryTest_Body();
+  TestRemoteFileDeletion();
 }
 
-TEST_F(DriveFileSyncServiceSyncTest, CreateDirectoryTest_WAPI) {
-  SetDisableDriveAPI(true);
-  CreateDirectoryTest_Body();
-}
-
-TEST_F(DriveFileSyncServiceSyncTest, DeleteDirectoryTest) {
-  ASSERT_FALSE(IsDriveAPIDisabled());
-  DeleteDirectoryTest_Body();
-}
-
-TEST_F(DriveFileSyncServiceSyncTest, DeleteDirectoryTest_WAPI) {
-  SetDisableDriveAPI(true);
-  DeleteDirectoryTest_Body();
+TEST_F(DriveFileSyncServiceSyncTest, RemoteFileDeletionTest_WAPI) {
+  ScopedDisableDriveAPI disable_drive_api;
+  TestRemoteFileDeletion();
 }
 
 }  // namespace sync_file_system
diff --git a/chrome/browser/sync_file_system/drive_file_sync_service_unittest.cc b/chrome/browser/sync_file_system/drive_file_sync_service_unittest.cc
index c063e41..a95685e 100644
--- a/chrome/browser/sync_file_system/drive_file_sync_service_unittest.cc
+++ b/chrome/browser/sync_file_system/drive_file_sync_service_unittest.cc
@@ -4,17 +4,22 @@
 
 #include "chrome/browser/sync_file_system/drive_file_sync_service.h"
 
-#include "base/message_loop.h"
-#include "chrome/browser/sync_file_system/drive/fake_api_util.h"
+#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "chrome/browser/sync_file_system/drive_backend/fake_api_util.h"
 #include "chrome/browser/sync_file_system/drive_metadata_store.h"
 #include "chrome/browser/sync_file_system/sync_file_system.pb.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "webkit/browser/fileapi/syncable/syncable_file_system_util.h"
 
 namespace sync_file_system {
 
+using drive_backend::APIUtilInterface;
+using drive_backend::FakeAPIUtil;
+
 namespace {
 
 const char kSyncRootResourceId[] = "folder:sync_root_resource_id";
@@ -41,14 +46,13 @@
 class DriveFileSyncServiceTest : public testing::Test {
  public:
   DriveFileSyncServiceTest()
-      : ui_thread_(content::BrowserThread::UI, &message_loop_),
-        file_thread_(content::BrowserThread::FILE, &message_loop_),
+      : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
         fake_api_util_(NULL),
         metadata_store_(NULL) {}
 
   virtual void SetUp() OVERRIDE {
     RegisterSyncableFileSystem();
-    fake_api_util_ = new drive::FakeAPIUtil;
+    fake_api_util_ = new FakeAPIUtil;
 
     ASSERT_TRUE(scoped_base_dir_.CreateUniqueTempDir());
     base_dir_ = scoped_base_dir_.path();
@@ -56,23 +60,23 @@
         base_dir_, base::MessageLoopProxy::current().get());
     bool done = false;
     metadata_store_->Initialize(base::Bind(&DidInitialize, &done));
-    message_loop_.RunUntilIdle();
+    base::MessageLoop::current()->RunUntilIdle();
     metadata_store_->SetSyncRootDirectory(kSyncRootResourceId);
     EXPECT_TRUE(done);
 
     sync_service_ = DriveFileSyncService::CreateForTesting(
         &profile_,
         base_dir_,
-        scoped_ptr<drive::APIUtilInterface>(fake_api_util_),
+        scoped_ptr<APIUtilInterface>(fake_api_util_),
         scoped_ptr<DriveMetadataStore>(metadata_store_)).Pass();
-    message_loop_.RunUntilIdle();
+    base::MessageLoop::current()->RunUntilIdle();
   }
 
   virtual void TearDown() OVERRIDE {
     metadata_store_ = NULL;
     fake_api_util_ = NULL;
     sync_service_.reset();
-    message_loop_.RunUntilIdle();
+    base::MessageLoop::current()->RunUntilIdle();
 
     base_dir_ = base::FilePath();
     RevokeSyncableFileSystem();
@@ -82,8 +86,7 @@
   }
 
  protected:
-  base::MessageLoop* message_loop() { return &message_loop_; }
-  drive::FakeAPIUtil* fake_api_util() { return fake_api_util_; }
+  FakeAPIUtil* fake_api_util() { return fake_api_util_; }
   DriveMetadataStore* metadata_store() { return metadata_store_; }
   DriveFileSyncService* sync_service() { return sync_service_.get(); }
   std::map<GURL, std::string>* pending_batch_sync_origins() {
@@ -135,14 +138,12 @@
 
  private:
   base::ScopedTempDir scoped_base_dir_;
-  base::MessageLoop message_loop_;
-  content::TestBrowserThread ui_thread_;
-  content::TestBrowserThread file_thread_;
+  content::TestBrowserThreadBundle thread_bundle_;
 
   TestingProfile profile_;
   base::FilePath base_dir_;
 
-  drive::FakeAPIUtil* fake_api_util_;   // Owned by |sync_service_|.
+  FakeAPIUtil* fake_api_util_;          // Owned by |sync_service_|.
   DriveMetadataStore* metadata_store_;  // Owned by |sync_service_|.
 
   scoped_ptr<DriveFileSyncService> sync_service_;
@@ -171,7 +172,7 @@
   sync_service()->UninstallOrigin(
       origin_gurl,
       base::Bind(&ExpectEqStatus, &done, SYNC_STATUS_OK));
-  message_loop()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   EXPECT_TRUE(done);
 
   // Assert the App's origin folder was marked as deleted.
@@ -193,11 +194,11 @@
   sync_service()->UninstallOrigin(
       origin_gurl,
       base::Bind(&ExpectEqStatus, &done, SYNC_STATUS_OK));
-  message_loop()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   EXPECT_TRUE(done);
 
   // Assert the App's origin folder does not exist.
-  const drive::FakeAPIUtil::RemoteResourceByResourceId& remote_resources =
+  const FakeAPIUtil::RemoteResourceByResourceId& remote_resources =
       fake_api_util()->remote_resources();
   EXPECT_TRUE(remote_resources.find(origin_dir_resource_id) ==
               remote_resources.end());
@@ -214,7 +215,7 @@
   // Pending origins that are disabled are dropped and do not go to disabled.
   sync_service()->DisableOriginForTrackingChanges(origin,
                                                   base::Bind(&ExpectOkStatus));
-  message_loop()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   ASSERT_TRUE(VerifyOriginStatusCount(0u, 0u, 0u));
 }
 
@@ -228,7 +229,7 @@
 
   sync_service()->DisableOriginForTrackingChanges(origin,
                                                   base::Bind(&ExpectOkStatus));
-  message_loop()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   ASSERT_TRUE(VerifyOriginStatusCount(0u, 0u, 1u));
 }
 
@@ -245,7 +246,7 @@
   // origins > 0.
   sync_service()->EnableOriginForTrackingChanges(origin,
                                                  base::Bind(&ExpectOkStatus));
-  message_loop()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   ASSERT_TRUE(VerifyOriginStatusCount(0u, 1u, 0u));
 }
 
diff --git a/chrome/browser/sync_file_system/drive_file_sync_util.cc b/chrome/browser/sync_file_system/drive_file_sync_util.cc
index 25389e9..8999771 100644
--- a/chrome/browser/sync_file_system/drive_file_sync_util.cc
+++ b/chrome/browser/sync_file_system/drive_file_sync_util.cc
@@ -96,4 +96,14 @@
       CommandLine::ForCurrentProcess()->HasSwitch(kDisableDriveAPI);
 }
 
+ScopedDisableDriveAPI::ScopedDisableDriveAPI()
+    : was_disabled_(IsDriveAPIDisabled()) {
+  SetDisableDriveAPI(true);
+}
+
+ScopedDisableDriveAPI::~ScopedDisableDriveAPI() {
+  DCHECK(IsDriveAPIDisabled());
+  SetDisableDriveAPI(was_disabled_);
+}
+
 }  // namespace sync_file_system
diff --git a/chrome/browser/sync_file_system/drive_file_sync_util.h b/chrome/browser/sync_file_system/drive_file_sync_util.h
index 007122c..5df4ce5 100644
--- a/chrome/browser/sync_file_system/drive_file_sync_util.h
+++ b/chrome/browser/sync_file_system/drive_file_sync_util.h
@@ -26,6 +26,17 @@
 // DriveAPI. (http://crbug.com/234557)
 bool IsDriveAPIDisabled();
 
+class ScopedDisableDriveAPI {
+ public:
+  ScopedDisableDriveAPI();
+  ~ScopedDisableDriveAPI();
+
+ private:
+  bool was_disabled_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedDisableDriveAPI);
+};
+
 }  // namespace sync_file_system
 
 #endif  // CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_FILE_SYNC_UTIL_H_
diff --git a/chrome/browser/sync_file_system/drive_metadata_store.cc b/chrome/browser/sync_file_system/drive_metadata_store.cc
index da343e3..65f125b 100644
--- a/chrome/browser/sync_file_system/drive_metadata_store.cc
+++ b/chrome/browser/sync_file_system/drive_metadata_store.cc
@@ -14,20 +14,19 @@
 #include "base/message_loop/message_loop_proxy.h"
 #include "base/sequenced_task_runner.h"
 #include "base/stl_util.h"
-#include "base/string_util.h"
-#include "base/stringprintf.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
 #include "base/task_runner_util.h"
-#include "chrome/browser/sync_file_system/drive/metadata_db_migration_util.h"
+#include "chrome/browser/sync_file_system/drive_backend/metadata_db_migration_util.h"
 #include "chrome/browser/sync_file_system/drive_file_sync_service.h"
 #include "chrome/browser/sync_file_system/drive_file_sync_util.h"
 #include "chrome/browser/sync_file_system/file_metadata.h"
 #include "chrome/browser/sync_file_system/logger.h"
 #include "chrome/browser/sync_file_system/sync_file_system.pb.h"
-#include "googleurl/src/gurl.h"
 #include "third_party/leveldatabase/src/include/leveldb/db.h"
 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
+#include "url/gurl.h"
 #include "webkit/browser/fileapi/file_system_url.h"
 #include "webkit/browser/fileapi/syncable/syncable_file_system_util.h"
 #include "webkit/common/fileapi/file_system_util.h"
@@ -174,10 +173,10 @@
 
   switch (version) {
     case 0:
-      drive::MigrateDatabaseFromV0ToV1(db);
+      drive_backend::MigrateDatabaseFromV0ToV1(db);
       // fall-through
     case 1:
-      drive::MigrateDatabaseFromV1ToV2(db);
+      drive_backend::MigrateDatabaseFromV1ToV2(db);
       // fall-through
     case 2:
       DCHECK_EQ(2, kCurrentDatabaseVersion);
@@ -209,7 +208,7 @@
     if (key == kSyncRootDirectoryKey) {
       std::string resource_id = itr->value().ToString();
       if (IsDriveAPIDisabled())
-        resource_id = drive::AddWapiFolderPrefix(resource_id);
+        resource_id = drive_backend::AddWapiFolderPrefix(resource_id);
       contents->sync_root_directory_resource_id = resource_id;
       continue;
     }
@@ -224,8 +223,8 @@
       DCHECK(success);
 
       if (IsDriveAPIDisabled()) {
-        metadata.set_resource_id(
-            drive::AddWapiIdPrefix(metadata.resource_id(), metadata.type()));
+        metadata.set_resource_id(drive_backend::AddWapiIdPrefix(
+            metadata.resource_id(), metadata.type()));
       }
 
       success = contents->metadata_map[origin].insert(
@@ -239,7 +238,7 @@
       DCHECK(origin.is_valid());
 
       std::string origin_resource_id = IsDriveAPIDisabled()
-          ? drive::AddWapiFolderPrefix(itr->value().ToString())
+          ? drive_backend::AddWapiFolderPrefix(itr->value().ToString())
           : itr->value().ToString();
 
       DCHECK(!ContainsKey(contents->incremental_sync_origins, origin));
@@ -252,7 +251,7 @@
       DCHECK(origin.is_valid());
 
       std::string origin_resource_id = IsDriveAPIDisabled()
-          ? drive::AddWapiFolderPrefix(itr->value().ToString())
+          ? drive_backend::AddWapiFolderPrefix(itr->value().ToString())
           : itr->value().ToString();
 
       DCHECK(!ContainsKey(contents->disabled_origins, origin));
@@ -444,7 +443,7 @@
   if (IsDriveAPIDisabled()) {
     DriveMetadata metadata_in_db(metadata);
     metadata_in_db.set_resource_id(
-        drive::RemoveWapiIdPrefix(metadata.resource_id()));
+        drive_backend::RemoveWapiIdPrefix(metadata.resource_id()));
     bool success = metadata_in_db.SerializeToString(&value);
     DCHECK(success);
   } else {
@@ -512,7 +511,7 @@
   scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
   batch->Delete(CreateKeyForOriginRoot(origin, DISABLED_ORIGIN));
   batch->Put(CreateKeyForOriginRoot(origin, INCREMENTAL_SYNC_ORIGIN),
-             drive::RemoveWapiIdPrefix(resource_id));
+             drive_backend::RemoveWapiIdPrefix(resource_id));
   WriteToDB(batch.Pass(),
             base::Bind(&DriveMetadataStore::UpdateDBStatus, AsWeakPtr()));
 }
@@ -523,7 +522,8 @@
   sync_root_directory_resource_id_ = resource_id;
 
   scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
-  batch->Put(kSyncRootDirectoryKey, drive::RemoveWapiIdPrefix(resource_id));
+  batch->Put(kSyncRootDirectoryKey,
+             drive_backend::RemoveWapiIdPrefix(resource_id));
   return WriteToDB(batch.Pass(),
                    base::Bind(&DriveMetadataStore::UpdateDBStatus,
                               AsWeakPtr()));
@@ -551,7 +551,7 @@
   DCHECK(!key.empty());
 
   scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
-  batch->Put(key, drive::RemoveWapiIdPrefix(resource_id));
+  batch->Put(key, drive_backend::RemoveWapiIdPrefix(resource_id));
   WriteToDB(batch.Pass(),
             base::Bind(&DriveMetadataStore::UpdateDBStatus, AsWeakPtr()));
 }
@@ -609,7 +609,7 @@
   scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
   batch->Delete(CreateKeyForOriginRoot(origin, INCREMENTAL_SYNC_ORIGIN));
   batch->Put(CreateKeyForOriginRoot(origin, DISABLED_ORIGIN),
-             drive::RemoveWapiIdPrefix(resource_id));
+             drive_backend::RemoveWapiIdPrefix(resource_id));
   AppendMetadataDeletionToBatch(metadata_map_, origin, batch.get());
   metadata_map_.erase(origin);
 
@@ -769,28 +769,29 @@
 }
 
 void DriveMetadataStore::GetFileMetadataMap(
-    OriginToFileMetadataMap* output_map) {
+    const GURL& origin,
+    FileMetadataMap* output_map) {
   DCHECK(CalledOnValidThread());
+  DCHECK(!origin.is_empty());
   DCHECK(output_map);
 
-  for (MetadataMap::const_iterator origin_itr = metadata_map_.begin();
-       origin_itr != metadata_map_.end();
-       ++origin_itr) {
-    for (PathToMetadata::const_iterator itr = origin_itr->second.begin();
-         itr != origin_itr->second.end();
-         ++itr) {
-      // Convert Drive specific metadata to Common File metadata object.
-      const GURL& origin = origin_itr->first;
-      const std::string title = itr->first.BaseName().AsUTF8Unsafe();
-      const DriveMetadata& metadata = itr->second;
-      const FileType type = DriveTypeToFileMetadataType(metadata.type());
-      std::ostringstream details;
-      details << "resource_id=" << metadata.resource_id() << ", "
-              << "md5_checksum=" << metadata.md5_checksum() << ", "
-              << "to_be_fetched=" << metadata.to_be_fetched();
-      FileMetadata file_metadata(title, type, details.str());
-      (*output_map)[origin][itr->first] = file_metadata;
-    }
+  MetadataMap::const_iterator origin_itr = metadata_map_.find(origin);
+  if (origin_itr == metadata_map_.end())
+    return;
+
+  for (PathToMetadata::const_iterator itr = origin_itr->second.begin();
+       itr != origin_itr->second.end();
+       ++itr) {
+    // Convert Drive specific metadata to Common File metadata object.
+    const std::string title = itr->first.BaseName().AsUTF8Unsafe();
+    const DriveMetadata& metadata = itr->second;
+    const FileType type = DriveTypeToFileMetadataType(metadata.type());
+    std::ostringstream details;
+    details << "resource_id=" << metadata.resource_id() << ", "
+            << "md5_checksum=" << metadata.md5_checksum() << ", "
+            << "to_be_fetched=" << metadata.to_be_fetched();
+    FileMetadata file_metadata(title, type, details.str());
+    (*output_map)[itr->first] = file_metadata;
   }
 }
 
diff --git a/chrome/browser/sync_file_system/drive_metadata_store.h b/chrome/browser/sync_file_system/drive_metadata_store.h
index da2a8c4..b243a5e 100644
--- a/chrome/browser/sync_file_system/drive_metadata_store.h
+++ b/chrome/browser/sync_file_system/drive_metadata_store.h
@@ -147,10 +147,9 @@
   bool GetOriginByOriginRootDirectoryId(const std::string& resource_id,
                                         GURL* origin);
 
-  // Returns all file metadata grouped by origin.
+  // Returns all file metadata for the given origin.
   typedef std::map<base::FilePath, FileMetadata> FileMetadataMap;
-  typedef std::map<GURL, FileMetadataMap> OriginToFileMetadataMap;
-  void GetFileMetadataMap(OriginToFileMetadataMap* output_map);
+  void GetFileMetadataMap(const GURL& origin, FileMetadataMap* output_map);
 
  private:
   friend class DriveMetadataStoreTest;
diff --git a/chrome/browser/sync_file_system/drive_metadata_store_unittest.cc b/chrome/browser/sync_file_system/drive_metadata_store_unittest.cc
index fddb38a..dc119bb 100644
--- a/chrome/browser/sync_file_system/drive_metadata_store_unittest.cc
+++ b/chrome/browser/sync_file_system/drive_metadata_store_unittest.cc
@@ -14,7 +14,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/threading/thread.h"
-#include "chrome/browser/sync_file_system/drive/metadata_db_migration_util.h"
+#include "chrome/browser/sync_file_system/drive_backend/metadata_db_migration_util.h"
 #include "chrome/browser/sync_file_system/drive_file_sync_service.h"
 #include "chrome/browser/sync_file_system/drive_file_sync_util.h"
 #include "chrome/browser/sync_file_system/file_metadata.h"
@@ -53,7 +53,7 @@
 
 std::string CreateResourceId(const std::string& resource_id) {
   return IsDriveAPIDisabled() ? resource_id
-                              : drive::RemoveWapiIdPrefix(resource_id);
+                              : drive_backend::RemoveWapiIdPrefix(resource_id);
 }
 
 DriveMetadata CreateMetadata(const std::string& resource_id,
@@ -588,60 +588,42 @@
 
 void DriveMetadataStoreTest::GetFileMetadataMap_Body() {
   InitializeDatabase();
-  DriveMetadataStore::OriginToFileMetadataMap metadata_map;
-  metadata_store()->GetFileMetadataMap(&metadata_map);
-  EXPECT_TRUE(metadata_map.empty());
 
-  // Add 2 files to one origin and 1 folder to another origin.
-  const GURL origin_a = GURL("chrome-extension://app_a");
-  const GURL origin_b = GURL("chrome-extension://app_b");
-  const base::FilePath origin_a_file_0 = base::FilePath(FPL("origin_a_file_0"));
-  const base::FilePath origin_a_file_1 = base::FilePath(FPL("origin_a_file_1"));
-  const base::FilePath origin_b_folder_0 = base::FilePath(FPL(
-      "origin_b_folder_0"));
+  // Save one file and folder to the origin.
+  const base::FilePath file_path = base::FilePath(FPL("file_0"));
+  const base::FilePath folder_path = base::FilePath(FPL("folder_0"));
 
-  const fileapi::FileSystemURL url_a_0 = CreateSyncableFileSystemURL(
-      origin_a, origin_a_file_0);
-  const fileapi::FileSystemURL url_a_1 = CreateSyncableFileSystemURL(
-      origin_a, origin_a_file_1);
-  const fileapi::FileSystemURL url_b_0 = CreateSyncableFileSystemURL(
-      origin_b, origin_b_folder_0);
+  const GURL origin = GURL("chrome-extension://app_a");
+  const fileapi::FileSystemURL url_0 = CreateSyncableFileSystemURL(
+      origin, file_path);
+  const fileapi::FileSystemURL url_1 = CreateSyncableFileSystemURL(
+      origin, folder_path);
 
   // Insert DrivaMetadata objects.
   EXPECT_EQ(SYNC_STATUS_OK, UpdateEntry(
-      url_a_0,
+      url_0,
       CreateMetadata("file:0", "1", false, false,
                      DriveMetadata_ResourceType_RESOURCE_TYPE_FILE)));
   EXPECT_EQ(SYNC_STATUS_OK, UpdateEntry(
-      url_a_1,
-      CreateMetadata("file:1", "2", false, true,
-                     DriveMetadata_ResourceType_RESOURCE_TYPE_FILE)));
-  EXPECT_EQ(SYNC_STATUS_OK, UpdateEntry(
-      url_b_0,
-      CreateMetadata("folder:0", "3", false, true,
+      url_1,
+      CreateMetadata("folder:0", "2", false, true,
                      DriveMetadata_ResourceType_RESOURCE_TYPE_FOLDER)));
 
   // Check that DriveMetadata objects get mapped back to generalized
   // FileMetadata objects.
-  metadata_store()->GetFileMetadataMap(&metadata_map);
+  DriveMetadataStore::FileMetadataMap metadata_map;
+  metadata_store()->GetFileMetadataMap(origin, &metadata_map);
   ASSERT_EQ(2U, metadata_map.size());
-  ASSERT_EQ(2U, metadata_map[origin_a].size());
-  ASSERT_EQ(1U, metadata_map[origin_b].size());
 
-  FileMetadata metadata_a_0 = metadata_map[origin_a][origin_a_file_0];
-  EXPECT_EQ("origin_a_file_0", metadata_a_0.title);
-  EXPECT_EQ(TYPE_FILE, metadata_a_0.type);
-  EXPECT_TRUE(!metadata_a_0.service_specific_metadata.empty());
+  FileMetadata metadata_0 = metadata_map[file_path];
+  EXPECT_EQ("file_0", metadata_0.title);
+  EXPECT_EQ(TYPE_FILE, metadata_0.type);
+  EXPECT_TRUE(!metadata_0.service_specific_metadata.empty());
 
-  FileMetadata metadata_a_1 = metadata_map[origin_a][origin_a_file_1];
-  EXPECT_EQ("origin_a_file_1", metadata_a_1.title);
-  EXPECT_EQ(TYPE_FILE, metadata_a_1.type);
-  EXPECT_TRUE(!metadata_a_1.service_specific_metadata.empty());
-
-  FileMetadata metadata_b_0 = metadata_map[origin_b][origin_b_folder_0];
-  EXPECT_EQ("origin_b_folder_0", metadata_b_0.title);
-  EXPECT_EQ(TYPE_FOLDER, metadata_b_0.type);
-  EXPECT_TRUE(!metadata_b_0.service_specific_metadata.empty());
+  FileMetadata metadata_1 = metadata_map[folder_path];
+  EXPECT_EQ("folder_0", metadata_1.title);
+  EXPECT_EQ(TYPE_FOLDER, metadata_1.type);
+  EXPECT_TRUE(!metadata_1.service_specific_metadata.empty());
 }
 
 TEST_F(DriveMetadataStoreTest, Initialization) {
diff --git a/chrome/browser/sync_file_system/file_status_observer.h b/chrome/browser/sync_file_system/file_status_observer.h
index 4c2af44..6fc667b 100644
--- a/chrome/browser/sync_file_system/file_status_observer.h
+++ b/chrome/browser/sync_file_system/file_status_observer.h
@@ -6,8 +6,8 @@
 #define CHROME_BROWSER_SYNC_FILE_SYSTEM_FILE_STATUS_OBSERVER_H_
 
 #include "base/basictypes.h"
-#include "webkit/browser/fileapi/syncable/sync_action.h"
-#include "webkit/browser/fileapi/syncable/sync_direction.h"
+#include "chrome/browser/sync_file_system/sync_action.h"
+#include "chrome/browser/sync_file_system/sync_direction.h"
 #include "webkit/browser/fileapi/syncable/sync_file_status.h"
 
 namespace fileapi {
diff --git a/chrome/browser/sync_file_system/local_file_sync_service.cc b/chrome/browser/sync_file_system/local_file_sync_service.cc
index ff8804c..13cbefb 100644
--- a/chrome/browser/sync_file_system/local_file_sync_service.cc
+++ b/chrome/browser/sync_file_system/local_file_sync_service.cc
@@ -14,7 +14,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/site_instance.h"
 #include "content/public/browser/storage_partition.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 #include "webkit/browser/fileapi/file_system_context.h"
 #include "webkit/browser/fileapi/file_system_url.h"
 #include "webkit/browser/fileapi/syncable/file_change.h"
diff --git a/chrome/browser/sync_file_system/local_file_sync_service_unittest.cc b/chrome/browser/sync_file_system/local_file_sync_service_unittest.cc
index 09c500b..59722dc 100644
--- a/chrome/browser/sync_file_system/local_file_sync_service_unittest.cc
+++ b/chrome/browser/sync_file_system/local_file_sync_service_unittest.cc
@@ -173,6 +173,7 @@
     return file_system_->file_system_context()->change_tracker()->num_changes();
   }
 
+  ScopedEnableSyncFSDirectoryOperation enable_directory_operation_;
   TestingProfile profile_;
 
   MultiThreadTestHelper thread_helper_;
diff --git a/chrome/browser/sync_file_system/logger.cc b/chrome/browser/sync_file_system/logger.cc
index 2257c8d..9c825e8 100644
--- a/chrome/browser/sync_file_system/logger.cc
+++ b/chrome/browser/sync_file_system/logger.cc
@@ -8,13 +8,13 @@
 #include "base/lazy_instance.h"
 #include "base/location.h"
 #include "base/strings/stringprintf.h"
-#include "chrome/browser/google_apis/event_logger.h"
+#include "chrome/browser/drive/event_logger.h"
 
 namespace sync_file_system {
 namespace util {
 namespace {
 
-static base::LazyInstance<google_apis::EventLogger> g_logger =
+static base::LazyInstance<drive::EventLogger> g_logger =
     LAZY_INSTANCE_INITIALIZER;
 
 const char* LogSeverityToString(logging::LogSeverity level) {
@@ -36,7 +36,7 @@
 }  // namespace
 
 void ClearLog() {
-  g_logger.Pointer()->SetHistorySize(google_apis::kDefaultHistorySize);
+  g_logger.Pointer()->SetHistorySize(::drive::kDefaultHistorySize);
 }
 
 void Log(logging::LogSeverity severity,
@@ -50,20 +50,11 @@
   base::StringAppendV(&what, format, args);
   va_end(args);
 
-  // Use same output format as normal console logger.
-  base::FilePath path = base::FilePath::FromUTF8Unsafe(location.file_name());
-  std::string log_output = base::StringPrintf(
-      "[%s: %s(%d)] %s",
-      LogSeverityToString(severity),
-      path.BaseName().AsUTF8Unsafe().c_str(),
-      location.line_number(),
-      what.c_str());
-
   // Log to WebUI regardless of LogSeverity (e.g. ignores command line flags).
   // On thread-safety: LazyInstance guarantees thread-safety for the object
   // creation. EventLogger::Log() internally maintains the lock.
-  google_apis::EventLogger* ptr = g_logger.Pointer();
-  ptr->Log("%s", log_output.c_str());
+  drive::EventLogger* ptr = g_logger.Pointer();
+  ptr->Log("[%s] %s", LogSeverityToString(severity), what.c_str());
 
   // Log to console if the severity is at or above the min level.
   // LOG_VERBOSE logs are also output if the verbosity of this module
@@ -76,8 +67,8 @@
       .stream() << what;
 }
 
-std::vector<google_apis::EventLogger::Event> GetLogHistory() {
-  google_apis::EventLogger* ptr = g_logger.Pointer();
+std::vector<drive::EventLogger::Event> GetLogHistory() {
+  drive::EventLogger* ptr = g_logger.Pointer();
   return ptr->GetHistory();
 }
 
diff --git a/chrome/browser/sync_file_system/logger.h b/chrome/browser/sync_file_system/logger.h
index 9eac379..fbd3d4c 100644
--- a/chrome/browser/sync_file_system/logger.h
+++ b/chrome/browser/sync_file_system/logger.h
@@ -10,7 +10,7 @@
 
 #include "base/location.h"
 #include "base/logging.h"
-#include "chrome/browser/google_apis/event_logger.h"
+#include "chrome/browser/drive/event_logger.h"
 
 namespace sync_file_system {
 // Originally wanted to use 'logging' here, but it conflicts with
@@ -30,7 +30,7 @@
 
 // Returns the log history.
 // This function can be called from any thread.
-std::vector<google_apis::EventLogger::Event> GetLogHistory();
+std::vector< ::drive::EventLogger::Event> GetLogHistory();
 
 }  // namespace util
 }  // namespace sync_file_system
diff --git a/chrome/browser/sync_file_system/logger_unittest.cc b/chrome/browser/sync_file_system/logger_unittest.cc
index 8739183..157828c 100644
--- a/chrome/browser/sync_file_system/logger_unittest.cc
+++ b/chrome/browser/sync_file_system/logger_unittest.cc
@@ -5,7 +5,7 @@
 #include "chrome/browser/sync_file_system/logger.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-using google_apis::EventLogger;
+using drive::EventLogger;
 
 namespace sync_file_system {
 
diff --git a/chrome/browser/sync_file_system/mock_remote_file_sync_service.cc b/chrome/browser/sync_file_system/mock_remote_file_sync_service.cc
index f274dfe..0f41b15 100644
--- a/chrome/browser/sync_file_system/mock_remote_file_sync_service.cc
+++ b/chrome/browser/sync_file_system/mock_remote_file_sync_service.cc
@@ -9,7 +9,7 @@
 #include "base/bind.h"
 #include "base/location.h"
 #include "base/message_loop/message_loop_proxy.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 #include "webkit/browser/fileapi/file_system_url.h"
 
 using ::testing::_;
@@ -19,7 +19,7 @@
 namespace sync_file_system {
 
 MockRemoteFileSyncService::MockRemoteFileSyncService()
-    : conflict_resolution_policy_(CONFLICT_RESOLUTION_MANUAL) {
+    : conflict_resolution_policy_(CONFLICT_RESOLUTION_POLICY_MANUAL) {
   typedef MockRemoteFileSyncService self;
   ON_CALL(*this, AddServiceObserver(_))
       .WillByDefault(Invoke(this, &self::AddServiceObserverStub));
diff --git a/chrome/browser/sync_file_system/mock_remote_file_sync_service.h b/chrome/browser/sync_file_system/mock_remote_file_sync_service.h
index ae23d7c..e1df6a7 100644
--- a/chrome/browser/sync_file_system/mock_remote_file_sync_service.h
+++ b/chrome/browser/sync_file_system/mock_remote_file_sync_service.h
@@ -13,10 +13,10 @@
 #include "chrome/browser/sync_file_system/mock_local_change_processor.h"
 #include "chrome/browser/sync_file_system/remote_change_processor.h"
 #include "chrome/browser/sync_file_system/remote_file_sync_service.h"
-#include "googleurl/src/gurl.h"
+#include "chrome/browser/sync_file_system/sync_direction.h"
 #include "testing/gmock/include/gmock/gmock.h"
+#include "url/gurl.h"
 #include "webkit/browser/fileapi/syncable/sync_callbacks.h"
-#include "webkit/browser/fileapi/syncable/sync_direction.h"
 #include "webkit/browser/fileapi/syncable/sync_file_metadata.h"
 
 namespace sync_file_system {
@@ -51,9 +51,9 @@
                      RemoteServiceState());
   MOCK_METHOD1(GetOriginStatusMap,
                void(RemoteFileSyncService::OriginStatusMap* status_map));
-  MOCK_METHOD1(
-      GetFileMetadataMap,
-      void(RemoteFileSyncService::OriginFileMetadataMap* metadata_map));
+  MOCK_METHOD2(GetFileMetadataMap,
+               void(const GURL& origin,
+                    RemoteFileSyncService::FileMetadataMap* metadata_map));
   MOCK_METHOD1(SetSyncEnabled, void(bool));
   MOCK_METHOD1(SetConflictResolutionPolicy,
                SyncStatusCode(ConflictResolutionPolicy));
diff --git a/chrome/browser/sync_file_system/remote_change_handler.h b/chrome/browser/sync_file_system/remote_change_handler.h
index 4820833..96be8c3 100644
--- a/chrome/browser/sync_file_system/remote_change_handler.h
+++ b/chrome/browser/sync_file_system/remote_change_handler.h
@@ -12,7 +12,7 @@
 
 #include "base/files/file_path.h"
 #include "base/stl_util.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "webkit/browser/fileapi/file_system_url.h"
 #include "webkit/browser/fileapi/syncable/file_change.h"
 
diff --git a/chrome/browser/sync_file_system/remote_file_sync_service.h b/chrome/browser/sync_file_system/remote_file_sync_service.h
index 69d4bae..c4f32b7 100644
--- a/chrome/browser/sync_file_system/remote_file_sync_service.h
+++ b/chrome/browser/sync_file_system/remote_file_sync_service.h
@@ -145,10 +145,10 @@
   typedef std::map<GURL, std::string> OriginStatusMap;
   virtual void GetOriginStatusMap(OriginStatusMap* status_map) = 0;
 
-  // Returns all file metadata grouped by origin.
+  // Returns file metadata for one origin.
   typedef std::map<base::FilePath, FileMetadata> FileMetadataMap;
-  typedef std::map<GURL, FileMetadataMap> OriginFileMetadataMap;
-  virtual void GetFileMetadataMap(OriginFileMetadataMap* metadata_map) = 0;
+  virtual void GetFileMetadataMap(const GURL& origin,
+                                  FileMetadataMap* metadata_map) = 0;
 
   // Enables or disables the background sync.
   // Setting this to false should disable the synchronization (and make
diff --git a/chrome/browser/sync_file_system/sync_action.h b/chrome/browser/sync_file_system/sync_action.h
new file mode 100644
index 0000000..1941288
--- /dev/null
+++ b/chrome/browser/sync_file_system/sync_action.h
@@ -0,0 +1,26 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SYNC_FILE_SYSTEM_SYNC_ACTION_H_
+#define CHROME_BROWSER_SYNC_FILE_SYSTEM_SYNC_ACTION_H_
+
+namespace sync_file_system {
+
+enum SyncAction {
+  // Indicates no action has been made.
+  SYNC_ACTION_NONE,
+
+  // Indicates a new file or directory has been added.
+  SYNC_ACTION_ADDED,
+
+  // Indicates an existing file or directory has been updated.
+  SYNC_ACTION_UPDATED,
+
+  // Indicates a file or directory has been deleted.
+  SYNC_ACTION_DELETED,
+};
+
+}  // namespace sync_file_system
+
+#endif  // CHROME_BROWSER_SYNC_FILE_SYSTEM_SYNC_ACTION_H_
diff --git a/chrome/browser/sync_file_system/sync_direction.h b/chrome/browser/sync_file_system/sync_direction.h
new file mode 100644
index 0000000..cffe640
--- /dev/null
+++ b/chrome/browser/sync_file_system/sync_direction.h
@@ -0,0 +1,18 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SYNC_FILE_SYSTEM_SYNC_DIRECTION_H_
+#define CHROME_BROWSER_SYNC_FILE_SYSTEM_SYNC_DIRECTION_H_
+
+namespace sync_file_system {
+
+enum SyncDirection {
+  SYNC_DIRECTION_NONE,
+  SYNC_DIRECTION_LOCAL_TO_REMOTE,
+  SYNC_DIRECTION_REMOTE_TO_LOCAL,
+};
+
+}  // namespace sync_file_system
+
+#endif  // CHROME_BROWSER_SYNC_FILE_SYSTEM_SYNC_DIRECTION_H_
diff --git a/chrome/browser/sync_file_system/sync_file_system.proto b/chrome/browser/sync_file_system/sync_file_system.proto
index d9a6ed5..9b37584 100644
--- a/chrome/browser/sync_file_system/sync_file_system.proto
+++ b/chrome/browser/sync_file_system/sync_file_system.proto
@@ -28,59 +28,3 @@
 
   optional ResourceType type = 5 [default = RESOURCE_TYPE_FILE];
 }
-
-enum DriveResourceKind {
-  KIND_UNSUPPORTED = 0;
-  KIND_FILE = 1;
-  KIND_FOLDER = 2;
-}
-
-message DriveEntryMetadata {
-  // Resource ID of the remote resource which the DriveFileMetadata tracks.
-  required string resource_id = 1;
-
-  optional string app_id = 2;
-  optional bool is_app_root = 3;
-
-  // Holds details of file/folder metadata.
-  message Details {
-    optional string parent_resource_id = 1;
-    optional string title = 2;
-    optional DriveResourceKind kind = 3;
-    optional string md5 = 4;
-    optional string etag = 5;
-
-    // Creation time and modification time of the resource.
-    // Serialized by Time::ToInternalValue.
-    optional int64 creation_time = 6;
-    optional int64 modification_time = 7;
-
-    optional bool deleted = 8;
-    optional int64 change_id = 9;
-  }
-
-  // |synced_details| holds the file details snapshot when the file was
-  // fetched through remote-to-local update.
-  // This should contain same value if |dirty| is false.
-  optional Details synced_details = 4;
-
-  // |remote_details| holds the latest file details that may not yet be
-  // applied to local metadata.
-  // This should be updated by each listed ChangeResource.
-  optional Details remote_details = 5;
-
-  // True if the file is changed since last update for this file.
-  optional bool dirty = 6;
-
-  // True if the DriveFileMetadata is active.
-  // Remote file content update should only be applied for active
-  // DriveFileMetadata.
-  // Active DriveFileMetadata must have a unique title under its parent.
-  optional bool active = 7;
-
-  // Valid only for folders.
-  // True indicates the folder contents has not yet been fetched.
-  optional bool needs_folder_listing = 8;
-
-  optional bool conflicted = 9;
-}
diff --git a/chrome/browser/sync_file_system/sync_file_system_service.cc b/chrome/browser/sync_file_system/sync_file_system_service.cc
index 787c265..0278b36 100644
--- a/chrome/browser/sync_file_system/sync_file_system_service.cc
+++ b/chrome/browser/sync_file_system/sync_file_system_service.cc
@@ -18,6 +18,7 @@
 #include "chrome/browser/sync_file_system/drive_file_sync_service.h"
 #include "chrome/browser/sync_file_system/local_file_sync_service.h"
 #include "chrome/browser/sync_file_system/logger.h"
+#include "chrome/browser/sync_file_system/sync_direction.h"
 #include "chrome/browser/sync_file_system/sync_event_observer.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "chrome/common/extensions/extension.h"
@@ -25,9 +26,8 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_service.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 #include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/syncable/sync_direction.h"
 #include "webkit/browser/fileapi/syncable/sync_file_metadata.h"
 #include "webkit/browser/fileapi/syncable/sync_status_code.h"
 #include "webkit/browser/fileapi/syncable/syncable_file_system_util.h"
@@ -180,43 +180,31 @@
 }
 
 void SyncFileSystemService::GetFileMetadataMap(
-    RemoteFileSyncService::OriginFileMetadataMap* metadata_map,
+    const GURL& origin,
+    RemoteFileSyncService::FileMetadataMap* metadata_map,
     size_t* num_results,
     const SyncStatusCallback& callback) {
   DCHECK(metadata_map);
+  DCHECK(!origin.is_empty());
   DCHECK(num_results);
-  remote_file_service_->GetFileMetadataMap(metadata_map);
+  remote_file_service_->GetFileMetadataMap(origin, metadata_map);
 
   // Figure out how many results have to be waited on before callback.
-  size_t expected_results = 0;
-  RemoteFileSyncService::OriginFileMetadataMap::iterator origin_itr;
-  for (origin_itr = metadata_map->begin();
-       origin_itr != metadata_map->end();
-       ++origin_itr)
-    expected_results += origin_itr->second.size();
-  if (expected_results == 0) {
-    callback.Run(SYNC_STATUS_OK);
-    return;
-  }
+  size_t expected_results = metadata_map->size();
 
   // After all metadata loaded, sync status can be added to each entry.
-  for (origin_itr = metadata_map->begin();
-       origin_itr != metadata_map->end();
-       ++origin_itr) {
-    RemoteFileSyncService::FileMetadataMap::iterator file_path_itr;
-    for (file_path_itr = origin_itr->second.begin();
-         file_path_itr != origin_itr->second.end();
-         ++file_path_itr) {
-      const GURL& origin = origin_itr->first;
-      const base::FilePath& file_path = file_path_itr->first;
-      const FileSystemURL url = CreateSyncableFileSystemURL(origin, file_path);
-      FileMetadata& metadata = file_path_itr->second;
-      GetFileSyncStatus(url, base::Bind(&DidGetFileSyncStatus,
-                                        callback,
-                                        &metadata,
-                                        expected_results,
-                                        num_results));
-    }
+  RemoteFileSyncService::FileMetadataMap::iterator file_path_itr;
+  for (file_path_itr = metadata_map->begin();
+       file_path_itr != metadata_map->end();
+       ++file_path_itr) {
+    const base::FilePath& file_path = file_path_itr->first;
+    const FileSystemURL url = CreateSyncableFileSystemURL(origin, file_path);
+    FileMetadata& metadata = file_path_itr->second;
+    GetFileSyncStatus(url, base::Bind(&DidGetFileSyncStatus,
+                                      callback,
+                                      &metadata,
+                                      expected_results,
+                                      num_results));
   }
 }
 
diff --git a/chrome/browser/sync_file_system/sync_file_system_service.h b/chrome/browser/sync_file_system/sync_file_system_service.h
index cde4a6f..fbcadb9 100644
--- a/chrome/browser/sync_file_system/sync_file_system_service.h
+++ b/chrome/browser/sync_file_system/sync_file_system_service.h
@@ -13,7 +13,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/sync/profile_sync_service_observer.h"
 #include "chrome/browser/sync_file_system/conflict_resolution_policy.h"
 #include "chrome/browser/sync_file_system/file_status_observer.h"
@@ -23,7 +23,7 @@
 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 #include "webkit/browser/fileapi/syncable/sync_callbacks.h"
 
 class ProfileSyncServiceBase;
@@ -56,7 +56,8 @@
   SyncServiceState GetSyncServiceState();
   void GetExtensionStatusMap(std::map<GURL, std::string>* status_map);
   void GetFileMetadataMap(
-      RemoteFileSyncService::OriginFileMetadataMap* metadata_map,
+      const GURL& origin,
+      RemoteFileSyncService::FileMetadataMap* metadata_map,
       size_t* num_results,
       const SyncStatusCallback& callback);
 
diff --git a/chrome/browser/sync_file_system/sync_file_system_service_factory.cc b/chrome/browser/sync_file_system/sync_file_system_service_factory.cc
index f8885ea..d01b5e4 100644
--- a/chrome/browser/sync_file_system/sync_file_system_service_factory.cc
+++ b/chrome/browser/sync_file_system/sync_file_system_service_factory.cc
@@ -40,7 +40,7 @@
     : BrowserContextKeyedServiceFactory(
         "SyncFileSystemService",
         BrowserContextDependencyManager::GetInstance()) {
-  DependsOn(google_apis::DriveNotificationManagerFactory::GetInstance());
+  DependsOn(::drive::DriveNotificationManagerFactory::GetInstance());
 }
 
 SyncFileSystemServiceFactory::~SyncFileSystemServiceFactory() {}
@@ -68,7 +68,7 @@
 
   if (CommandLine::ForCurrentProcess()->HasSwitch(kDisableLastWriteWin)) {
     remote_file_service->SetConflictResolutionPolicy(
-        CONFLICT_RESOLUTION_MANUAL);
+        CONFLICT_RESOLUTION_POLICY_MANUAL);
   }
 
   service->Initialize(local_file_service.Pass(),
diff --git a/chrome/browser/sync_file_system/sync_file_system_service_unittest.cc b/chrome/browser/sync_file_system/sync_file_system_service_unittest.cc
index 18222e2..6661bb1 100644
--- a/chrome/browser/sync_file_system/sync_file_system_service_unittest.cc
+++ b/chrome/browser/sync_file_system/sync_file_system_service_unittest.cc
@@ -235,6 +235,8 @@
     sync_service_->SetSyncEnabledForTesting(true);
   }
 
+  ScopedEnableSyncFSDirectoryOperation enable_directory_operation_;
+
   MultiThreadTestHelper thread_helper_;
   TestingProfile profile_;
   scoped_ptr<CannedSyncableFileSystem> file_system_;
diff --git a/chrome/browser/tab_contents/render_view_context_menu.cc b/chrome/browser/tab_contents/render_view_context_menu.cc
index e5a8f01..eb4b728 100644
--- a/chrome/browser/tab_contents/render_view_context_menu.cc
+++ b/chrome/browser/tab_contents/render_view_context_menu.cc
@@ -17,7 +17,7 @@
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/app_mode/app_mode_utils.h"
 #include "chrome/browser/autocomplete/autocomplete_classifier.h"
@@ -40,7 +40,6 @@
 #include "chrome/browser/printing/print_view_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_io_data.h"
-#include "chrome/browser/search/instant_extended_context_menu_observer.h"
 #include "chrome/browser/search/search.h"
 #include "chrome/browser/search_engines/template_url.h"
 #include "chrome/browser/search_engines/template_url_service.h"
@@ -596,7 +595,8 @@
     }
   }
 
-  if (has_link) {
+  // Do not show link related items for guest.
+  if (has_link && !is_guest_) {
     AppendLinkItems();
     if (params_.media_type != WebContextMenuData::MediaTypeNone)
       menu_model_.AddSeparator(ui::NORMAL_SEPARATOR);
@@ -644,13 +644,8 @@
       print_preview_menu_observer_.reset(
           new PrintPreviewContextMenuObserver(source_web_contents_));
     }
-    if (!instant_extended_observer_.get()) {
-      instant_extended_observer_.reset(
-          new InstantExtendedContextMenuObserver(source_web_contents_));
-    }
 
     observers_.AddObserver(print_preview_menu_observer_.get());
-    observers_.AddObserver(instant_extended_observer_.get());
   }
 }
 
@@ -732,12 +727,15 @@
 
   bool has_selection = !params_.selection_text.empty();
 
+  // Checking link should take precedence before checking selection since on Mac
+  // right-clicking a link will also make it selected.
+  if (params_.unfiltered_link_url.is_valid())
+    AppendLinkItems();
+
   if (params_.is_editable)
     AppendEditableItems();
   else if (has_selection)
     AppendCopyItem();
-  else if (params_.unfiltered_link_url.is_valid())
-    AppendLinkItems();
 
   // Only add extension items from this extension.
   int index = 0;
@@ -1777,7 +1775,7 @@
       // Since the user decided to translate for that language and site, clears
       // any preferences for not translating them.
       TranslatePrefs prefs(profile_->GetPrefs());
-      prefs.RemoveLanguageFromBlacklist(original_lang);
+      prefs.UnblockLanguage(original_lang);
       prefs.RemoveSiteFromBlacklist(params_.page_url.HostNoBrackets());
       TranslateManager::GetInstance()->TranslatePage(
           source_web_contents_, original_lang, target_lang);
diff --git a/chrome/browser/tab_contents/render_view_context_menu.h b/chrome/browser/tab_contents/render_view_context_menu.h
index a1179a2..6f2d0b4 100644
--- a/chrome/browser/tab_contents/render_view_context_menu.h
+++ b/chrome/browser/tab_contents/render_view_context_menu.h
@@ -22,7 +22,6 @@
 #include "ui/base/models/simple_menu_model.h"
 #include "ui/base/window_open_disposition.h"
 
-class InstantExtendedContextMenuObserver;
 class PrintPreviewContextMenuObserver;
 class Profile;
 class SpellingMenuObserver;
@@ -277,9 +276,6 @@
   // An observer that disables menu items when print preview is active.
   scoped_ptr<PrintPreviewContextMenuObserver> print_preview_menu_observer_;
 
-  // An observer that disables menu items for instant extended mode.
-  scoped_ptr<InstantExtendedContextMenuObserver> instant_extended_observer_;
-
   // Our observers.
   mutable ObserverList<RenderViewContextMenuObserver> observers_;
 
diff --git a/chrome/browser/tab_contents/render_view_context_menu_unittest.cc b/chrome/browser/tab_contents/render_view_context_menu_unittest.cc
index be937f2..1728e70 100644
--- a/chrome/browser/tab_contents/render_view_context_menu_unittest.cc
+++ b/chrome/browser/tab_contents/render_view_context_menu_unittest.cc
@@ -14,9 +14,9 @@
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/browser/web_contents.h"
 #include "extensions/common/url_pattern.h"
-#include "googleurl/src/gurl.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/WebKit/public/web/WebContextMenuData.h"
+#include "url/gurl.h"
 
 using extensions::MenuItem;
 using extensions::URLPatternSet;
diff --git a/chrome/browser/tab_contents/retargeting_details.h b/chrome/browser/tab_contents/retargeting_details.h
index ffbd274..108b6a6 100644
--- a/chrome/browser/tab_contents/retargeting_details.h
+++ b/chrome/browser/tab_contents/retargeting_details.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_TAB_CONTENTS_RETARGETING_DETAILS_H_
 #define CHROME_BROWSER_TAB_CONTENTS_RETARGETING_DETAILS_H_
 
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 namespace content {
 class WebContents;
diff --git a/chrome/browser/tab_contents/spelling_menu_observer.h b/chrome/browser/tab_contents/spelling_menu_observer.h
index 3f2194e..9490c30 100644
--- a/chrome/browser/tab_contents/spelling_menu_observer.h
+++ b/chrome/browser/tab_contents/spelling_menu_observer.h
@@ -11,7 +11,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/prefs/pref_member.h"
 #include "base/strings/string16.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/spellchecker/spelling_service_client.h"
 #include "chrome/browser/tab_contents/render_view_context_menu_observer.h"
 
diff --git a/chrome/browser/tab_contents/tab_util.cc b/chrome/browser/tab_contents/tab_util.cc
index f855d6a..9d82f22 100644
--- a/chrome/browser/tab_contents/tab_util.cc
+++ b/chrome/browser/tab_contents/tab_util.cc
@@ -11,7 +11,7 @@
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/site_instance.h"
 #include "content/public/browser/web_contents.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 using content::RenderViewHost;
 using content::SiteInstance;
diff --git a/chrome/browser/tab_contents/view_source_browsertest.cc b/chrome/browser/tab_contents/view_source_browsertest.cc
index 9066db3..83f43b9 100644
--- a/chrome/browser/tab_contents/view_source_browsertest.cc
+++ b/chrome/browser/tab_contents/view_source_browsertest.cc
@@ -16,11 +16,11 @@
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test_utils.h"
-#include "googleurl/src/gurl.h"
-#include "net/test/spawned_test_server/spawned_test_server.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "url/gurl.h"
 
 namespace {
-const char kTestHtml[] = "files/viewsource/test.html";
+const char kTestHtml[] = "/viewsource/test.html";
 const char kTestMedia[] = "files/media/pink_noise_140ms.wav";
 }
 
@@ -31,11 +31,11 @@
 // page in view source).
 // Flaky; see http://crbug.com/72201.
 IN_PROC_BROWSER_TEST_F(ViewSourceTest, DoesBrowserRenderInViewSource) {
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   // First we navigate to our view-source test page.
   GURL url(content::kViewSourceScheme + std::string(":") +
-           test_server()->GetURL(kTestHtml).spec());
+           embedded_test_server()->GetURL(kTestHtml).spec());
   ui_test_utils::NavigateToURL(browser(), url);
 
   // Check that the title didn't get set.  It should not be there (because we
@@ -49,10 +49,10 @@
 // implementation of the view-source: prefix being consumed (removed from the
 // URL) if the URL was not changed (apart from adding the view-source prefix)
 IN_PROC_BROWSER_TEST_F(ViewSourceTest, DoesBrowserConsumeViewSourcePrefix) {
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   // First we navigate to google.html.
-  GURL url(test_server()->GetURL(kTestHtml));
+  GURL url(embedded_test_server()->GetURL(kTestHtml));
   ui_test_utils::NavigateToURL(browser(), url);
 
   // Then we navigate to the same url but with the "view-source:" prefix.
@@ -69,9 +69,9 @@
 // Make sure that when looking at the actual page, we can select "View Source"
 // from the menu.
 IN_PROC_BROWSER_TEST_F(ViewSourceTest, ViewSourceInMenuEnabledOnANormalPage) {
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
-  GURL url(test_server()->GetURL(kTestHtml));
+  GURL url(embedded_test_server()->GetURL(kTestHtml));
   ui_test_utils::NavigateToURL(browser(), url);
 
   EXPECT_TRUE(chrome::CanViewSource(browser()));
@@ -96,10 +96,10 @@
 // from the menu.
 IN_PROC_BROWSER_TEST_F(ViewSourceTest,
                        ViewSourceInMenuDisabledWhileViewingSource) {
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   GURL url_viewsource(content::kViewSourceScheme + std::string(":") +
-                      test_server()->GetURL(kTestHtml).spec());
+                      embedded_test_server()->GetURL(kTestHtml).spec());
   ui_test_utils::NavigateToURL(browser(), url_viewsource);
 
   EXPECT_FALSE(chrome::CanViewSource(browser()));
@@ -109,10 +109,10 @@
 // the page in view-source mode.
 // Times out on Mac, Windows, ChromeOS Linux: crbug.com/162080
 IN_PROC_BROWSER_TEST_F(ViewSourceTest, DISABLED_TestViewSourceReload) {
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   GURL url_viewsource(content::kViewSourceScheme + std::string(":") +
-                      test_server()->GetURL(kTestHtml).spec());
+                      embedded_test_server()->GetURL(kTestHtml).spec());
 
   content::WindowedNotificationObserver observer(
       content::NOTIFICATION_LOAD_STOP,
diff --git a/chrome/browser/task_manager/child_process_resource_provider.cc b/chrome/browser/task_manager/child_process_resource_provider.cc
index 67b0918..03bea05 100644
--- a/chrome/browser/task_manager/child_process_resource_provider.cc
+++ b/chrome/browser/task_manager/child_process_resource_provider.cc
@@ -135,8 +135,6 @@
       return Resource::SANDBOX_HELPER;
     case content::PROCESS_TYPE_GPU:
       return Resource::GPU;
-    case PROCESS_TYPE_PROFILE_IMPORT:
-      return Resource::PROFILE_IMPORT;
     case PROCESS_TYPE_NACL_LOADER:
     case PROCESS_TYPE_NACL_BROKER:
       return Resource::NACL;
@@ -185,8 +183,6 @@
     case content::PROCESS_TYPE_PPAPI_BROKER:
       return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_PLUGIN_BROKER_PREFIX,
                                         title);
-    case PROCESS_TYPE_PROFILE_IMPORT:
-      return l10n_util::GetStringUTF16(IDS_TASK_MANAGER_UTILITY_PREFIX);
     case PROCESS_TYPE_NACL_BROKER:
       return l10n_util::GetStringUTF16(IDS_TASK_MANAGER_NACL_BROKER_PREFIX);
     case PROCESS_TYPE_NACL_LOADER:
diff --git a/chrome/browser/task_manager/guest_resource_provider.cc b/chrome/browser/task_manager/guest_resource_provider.cc
index 1d7e016..5dcedf1 100644
--- a/chrome/browser/task_manager/guest_resource_provider.cc
+++ b/chrome/browser/task_manager/guest_resource_provider.cc
@@ -132,19 +132,12 @@
   updating_ = true;
 
   // Add all the existing guest WebContents.
-  for (RenderProcessHost::iterator i(
-           RenderProcessHost::AllHostsIterator());
-       !i.IsAtEnd(); i.Advance()) {
-    RenderProcessHost::RenderWidgetHostsIterator iter =
-        i.GetCurrentValue()->GetRenderWidgetHostsIterator();
-    for (; !iter.IsAtEnd(); iter.Advance()) {
-      const RenderWidgetHost* widget = iter.GetCurrentValue();
-      if (widget->IsRenderView()) {
-        RenderViewHost* rvh =
-            RenderViewHost::From(const_cast<RenderWidgetHost*>(widget));
-        if (rvh->IsSubframe())
-          Add(rvh);
-      }
+  RenderWidgetHost::List widgets = RenderWidgetHost::GetRenderWidgetHosts();
+  for (size_t i = 0; i < widgets.size(); ++i) {
+    if (widgets[i]->IsRenderView()) {
+      RenderViewHost* rvh = RenderViewHost::From(widgets[i]);
+      if (rvh->IsSubframe())
+        Add(rvh);
     }
   }
 
diff --git a/chrome/browser/task_manager/resource_provider.h b/chrome/browser/task_manager/resource_provider.h
index 8608f71..243730d 100644
--- a/chrome/browser/task_manager/resource_provider.h
+++ b/chrome/browser/task_manager/resource_provider.h
@@ -38,7 +38,6 @@
     def(WORKER)          /* A web worker process. */ \
     def(NACL)            /* A NativeClient loader or broker process. */ \
     def(UTILITY)         /* A browser utility process. */ \
-    def(PROFILE_IMPORT)  /* A profile import process. */ \
     def(ZYGOTE)          /* A Linux zygote process. */ \
     def(SANDBOX_HELPER)  /* A sandbox helper process. */ \
     def(GPU)             /* A graphics process. */
@@ -170,6 +169,6 @@
   virtual ~ResourceProvider() {}
 };
 
-}  // namepace task_manager
+}  // namespace task_manager
 
 #endif  // CHROME_BROWSER_TASK_MANAGER_RESOURCE_PROVIDER_H_
diff --git a/chrome/browser/task_manager/tab_contents_resource_provider.cc b/chrome/browser/task_manager/tab_contents_resource_provider.cc
index 6b185ff..de3a008 100644
--- a/chrome/browser/task_manager/tab_contents_resource_provider.cc
+++ b/chrome/browser/task_manager/tab_contents_resource_provider.cc
@@ -64,10 +64,6 @@
   explicit TabContentsResource(content::WebContents* web_contents);
   virtual ~TabContentsResource();
 
-  // Called when the underlying web_contents has been committed and is no
-  // longer an Instant overlay.
-  void InstantCommitted();
-
   // Resource methods:
   virtual Type GetType() const OVERRIDE;
   virtual string16 GetTitle() const OVERRIDE;
@@ -83,7 +79,7 @@
   static gfx::ImageSkia* prerender_icon_;
   content::WebContents* web_contents_;
   Profile* profile_;
-  bool is_instant_overlay_;
+  bool is_instant_ntp_;
 
   DISALLOW_COPY_AND_ASSIGN(TabContentsResource);
 };
@@ -96,8 +92,7 @@
                        web_contents->GetRenderViewHost()),
       web_contents_(web_contents),
       profile_(Profile::FromBrowserContext(web_contents->GetBrowserContext())),
-      is_instant_overlay_(chrome::IsInstantOverlay(web_contents) ||
-                          chrome::IsPreloadedInstantExtendedNTP(web_contents)) {
+      is_instant_ntp_(chrome::IsPreloadedInstantExtendedNTP(web_contents)) {
   if (!prerender_icon_) {
     ResourceBundle& rb = ResourceBundle::GetSharedInstance();
     prerender_icon_ = rb.GetImageSkiaNamed(IDR_PRERENDER);
@@ -107,11 +102,6 @@
 TabContentsResource::~TabContentsResource() {
 }
 
-void TabContentsResource::InstantCommitted() {
-  DCHECK(is_instant_overlay_);
-  is_instant_overlay_ = false;
-}
-
 bool TabContentsResource::HostsExtension() const {
   return web_contents_->GetURL().SchemeIs(extensions::kExtensionScheme);
 }
@@ -138,7 +128,7 @@
       HostsExtension(),
       profile_->IsOffTheRecord(),
       IsContentsPrerendering(web_contents_),
-      is_instant_overlay_,
+      is_instant_ntp_,
       false);  // is_background
   return l10n_util::GetStringFUTF16(message_id, tab_title);
 }
@@ -220,8 +210,6 @@
   // Add all the Instant pages.
   for (chrome::BrowserIterator it; !it.done(); it.Next()) {
     if (it->instant_controller()) {
-      if (it->instant_controller()->instant()->GetOverlayContents())
-        Add(it->instant_controller()->instant()->GetOverlayContents());
       if (it->instant_controller()->instant()->GetNTPContents())
         Add(it->instant_controller()->instant()->GetNTPContents());
     }
@@ -257,8 +245,6 @@
                  content::NotificationService::AllBrowserContextsAndSources());
   registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
                  content::NotificationService::AllBrowserContextsAndSources());
-  registrar_.Add(this, chrome::NOTIFICATION_INSTANT_COMMITTED,
-                 content::NotificationService::AllBrowserContextsAndSources());
 }
 
 void TabContentsResourceProvider::StopUpdating() {
@@ -272,8 +258,6 @@
       content::NotificationService::AllBrowserContextsAndSources());
   registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
       content::NotificationService::AllBrowserContextsAndSources());
-  registrar_.Remove(this, chrome::NOTIFICATION_INSTANT_COMMITTED,
-      content::NotificationService::AllBrowserContextsAndSources());
 
   // Delete all the resources.
   STLDeleteContainerPairSecondPointers(resources_.begin(), resources_.end());
@@ -296,7 +280,6 @@
   // pages, prerender pages, and background printed pages.
   if (!chrome::FindBrowserWithWebContents(web_contents) &&
       !IsContentsPrerendering(web_contents) &&
-      !chrome::IsInstantOverlay(web_contents) &&
       !chrome::IsPreloadedInstantExtendedNTP(web_contents) &&
       !IsContentsBackgroundPrinted(web_contents)) {
     return;
@@ -340,16 +323,6 @@
   delete resource;
 }
 
-void TabContentsResourceProvider::InstantCommitted(WebContents* web_contents) {
-  if (!updating_)
-    return;
-  std::map<WebContents*, TabContentsResource*>::iterator
-      iter = resources_.find(web_contents);
-  DCHECK(iter != resources_.end());
-  if (iter != resources_.end())
-    iter->second->InstantCommitted();
-}
-
 void TabContentsResourceProvider::Observe(
     int type,
     const content::NotificationSource& source,
@@ -367,9 +340,6 @@
     case content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED:
       Remove(web_contents);
       break;
-    case chrome::NOTIFICATION_INSTANT_COMMITTED:
-      InstantCommitted(web_contents);
-      break;
     default:
       NOTREACHED() << "Unexpected notification.";
       return;
diff --git a/chrome/browser/task_manager/tab_contents_resource_provider.h b/chrome/browser/task_manager/tab_contents_resource_provider.h
index 66da6ad..3795e25 100644
--- a/chrome/browser/task_manager/tab_contents_resource_provider.h
+++ b/chrome/browser/task_manager/tab_contents_resource_provider.h
@@ -47,7 +47,6 @@
 
   void Add(content::WebContents* web_contents);
   void Remove(content::WebContents* web_contents);
-  void InstantCommitted(content::WebContents* web_contents);
 
   void AddToTaskManager(content::WebContents* web_contents);
 
diff --git a/chrome/browser/task_manager/task_manager.cc b/chrome/browser/task_manager/task_manager.cc
index f0e3408..be9a3b9 100644
--- a/chrome/browser/task_manager/task_manager.cc
+++ b/chrome/browser/task_manager/task_manager.cc
@@ -15,8 +15,6 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/background/background_contents_service.h"
-#include "chrome/browser/background/background_contents_service_factory.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/extensions/extension_process_manager.h"
 #include "chrome/browser/extensions/extension_system.h"
@@ -1545,36 +1543,6 @@
   chrome::Navigate(&params);
 }
 
-// static
-int TaskManager::GetBackgroundPageCount() {
-  int count = 0;
-  ProfileManager* profile_manager = g_browser_process->profile_manager();
-  if (!profile_manager)  // Null when running unit tests.
-    return count;
-  std::vector<Profile*> profiles(profile_manager->GetLoadedProfiles());
-  for (std::vector<Profile*>::const_iterator iter = profiles.begin();
-       iter != profiles.end();
-       ++iter) {
-    Profile* profile = *iter;
-    // Count the number of Background Contents (background pages for hosted
-    // apps). Incognito windows do not support hosted apps, so just check the
-    // main profile.
-    BackgroundContentsService* background_contents_service =
-        BackgroundContentsServiceFactory::GetForProfile(profile);
-    if (background_contents_service)
-      count += background_contents_service->GetBackgroundContents().size();
-
-    // Count the number of extensions with background pages (including
-    // incognito).
-    count += CountExtensionBackgroundPagesForProfile(profile);
-    if (profile->HasOffTheRecordProfile()) {
-      count += CountExtensionBackgroundPagesForProfile(
-          profile->GetOffTheRecordProfile());
-    }
-  }
-  return count;
-}
-
 TaskManager::TaskManager()
     : model_(new TaskManagerModel(this)) {
 }
diff --git a/chrome/browser/task_manager/task_manager.h b/chrome/browser/task_manager/task_manager.h
index 31ea9a8..7554747 100644
--- a/chrome/browser/task_manager/task_manager.h
+++ b/chrome/browser/task_manager/task_manager.h
@@ -15,7 +15,7 @@
 #include "base/observer_list.h"
 #include "base/process_util.h"
 #include "base/strings/string16.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/renderer_host/web_cache_manager.h"
 #include "chrome/browser/task_manager/resource_provider.h"
 #include "chrome/browser/ui/host_desktop.h"
@@ -83,11 +83,6 @@
 
   void OpenAboutMemory(chrome::HostDesktopType desktop_type);
 
-  // Returns the number of background pages that will be displayed in the
-  // TaskManager. Used by the wrench menu code to display a count of background
-  // pages in the "View Background Pages" menu item.
-  static int GetBackgroundPageCount();
-
  private:
   FRIEND_TEST_ALL_PREFIXES(TaskManagerTest, Basic);
   FRIEND_TEST_ALL_PREFIXES(TaskManagerTest, Resources);
diff --git a/chrome/browser/task_manager/task_manager_browsertest.cc b/chrome/browser/task_manager/task_manager_browsertest.cc
index 73584ca..a4f2a93 100644
--- a/chrome/browser/task_manager/task_manager_browsertest.cc
+++ b/chrome/browser/task_manager/task_manager_browsertest.cc
@@ -7,8 +7,6 @@
 #include "base/files/file_path.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/background/background_contents_service.h"
-#include "chrome/browser/background/background_contents_service_factory.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/extensions/extension_browsertest.h"
 #include "chrome/browser/extensions/extension_service.h"
@@ -41,6 +39,7 @@
 #include "content/public/test/browser_test_utils.h"
 #include "grit/generated_resources.h"
 #include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/l10n/l10n_util.h"
 
@@ -78,11 +77,9 @@
 
     EXPECT_EQ(0, model()->ResourceCount());
 
-    EXPECT_EQ(0, TaskManager::GetBackgroundPageCount());
-
     // Show the task manager. This populates the model, and helps with debugging
     // (you see the task manager).
-    chrome::ShowTaskManager(browser(), false);
+    chrome::ShowTaskManager(browser());
 
     // New Tab Page.
     TaskManagerBrowserTestUtil::WaitForWebResourceChange(1);
@@ -189,67 +186,6 @@
   TaskManagerBrowserTestUtil::WaitForWebResourceChange(1);
 }
 
-IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, NoticeBGContentsChanges) {
-  // Open a new background contents and make sure we notice that.
-  GURL url(ui_test_utils::GetTestUrl(base::FilePath(
-      base::FilePath::kCurrentDirectory), base::FilePath(kTitle1File)));
-
-  BackgroundContentsService* service =
-      BackgroundContentsServiceFactory::GetForProfile(browser()->profile());
-  string16 application_id(ASCIIToUTF16("test_app_id"));
-  service->LoadBackgroundContents(browser()->profile(),
-                                  url,
-                                  ASCIIToUTF16("background_page"),
-                                  application_id);
-  TaskManagerBrowserTestUtil::WaitForWebResourceChange(2);
-  EXPECT_EQ(1, TaskManager::GetBackgroundPageCount());
-
-  // Close the background contents and verify that we notice.
-  service->ShutdownAssociatedBackgroundContents(application_id);
-  TaskManagerBrowserTestUtil::WaitForWebResourceChange(1);
-  EXPECT_EQ(0, TaskManager::GetBackgroundPageCount());
-}
-
-IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, KillBGContents) {
-  int resource_count = TaskManager::GetInstance()->model()->ResourceCount();
-
-  // Open a new background contents and make sure we notice that.
-  GURL url(ui_test_utils::GetTestUrl(base::FilePath(
-      base::FilePath::kCurrentDirectory), base::FilePath(kTitle1File)));
-
-  content::WindowedNotificationObserver observer(
-      chrome::NOTIFICATION_BACKGROUND_CONTENTS_NAVIGATED,
-      content::Source<Profile>(browser()->profile()));
-
-  BackgroundContentsService* service =
-      BackgroundContentsServiceFactory::GetForProfile(browser()->profile());
-  string16 application_id(ASCIIToUTF16("test_app_id"));
-  service->LoadBackgroundContents(browser()->profile(),
-                                  url,
-                                  ASCIIToUTF16("background_page"),
-                                  application_id);
-
-  // Wait for the background contents process to finish loading.
-  observer.Wait();
-
-  EXPECT_EQ(resource_count + 1, model()->ResourceCount());
-  EXPECT_EQ(1, TaskManager::GetBackgroundPageCount());
-
-  // Kill the background contents process and verify that it disappears from the
-  // model.
-  bool found = false;
-  for (int i = 0; i < model()->ResourceCount(); ++i) {
-    if (model()->IsBackgroundResource(i)) {
-      TaskManager::GetInstance()->KillProcess(i);
-      found = true;
-      break;
-    }
-  }
-  ASSERT_TRUE(found);
-  TaskManagerBrowserTestUtil::WaitForWebResourceChange(1);
-  EXPECT_EQ(0, TaskManager::GetBackgroundPageCount());
-}
-
 #if defined(USE_ASH) || defined(OS_WIN)
 // This test fails on Ash because task manager treats view type
 // Panels differently for Ash.
@@ -288,20 +224,6 @@
   TaskManagerBrowserTestUtil::WaitForWebResourceChange(1);
 }
 
-IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, NoticeExtensionChanges) {
-  // Loading an extension with a background page should result in a new
-  // resource being created for it.
-  ASSERT_TRUE(LoadExtension(
-      test_data_dir_.AppendASCII("common").AppendASCII("background_page")));
-  TaskManagerBrowserTestUtil::WaitForWebResourceChange(2);
-  EXPECT_EQ(1, TaskManager::GetBackgroundPageCount());
-
-  // Unload extension to avoid crash on Windows (see http://crbug.com/31663).
-  UnloadExtension(last_loaded_extension_id_);
-  TaskManagerBrowserTestUtil::WaitForWebResourceChange(1);
-  EXPECT_EQ(0, TaskManager::GetBackgroundPageCount());
-}
-
 IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, NoticeExtensionTabs) {
   int resource_count = TaskManager::GetInstance()->model()->ResourceCount();
   ASSERT_TRUE(LoadExtension(
@@ -381,12 +303,12 @@
   // The app under test acts on URLs whose host is "localhost",
   // so the URLs we navigate to must have host "localhost".
   host_resolver()->AddRule("*", "127.0.0.1");
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
   GURL::Replacements replace_host;
   std::string host_str("localhost");  // must stay in scope with replace_host
   replace_host.SetHostStr(host_str);
-  GURL base_url = test_server()->GetURL(
-      "files/extensions/api_test/app_process/");
+  GURL base_url = embedded_test_server()->GetURL(
+      "/extensions/api_test/app_process/");
   base_url = base_url.ReplaceComponents(replace_host);
 
   // Open a new tab to an app URL before the app is loaded.
@@ -436,27 +358,6 @@
                          tab_prefix, true));
 }
 
-IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, MAYBE_KillExtension) {
-  int resource_count = TaskManager::GetInstance()->model()->ResourceCount();
-
-  ASSERT_TRUE(LoadExtension(
-      test_data_dir_.AppendASCII("common").AppendASCII("background_page")));
-
-  // Wait until we see the loaded extension in the task manager (the three
-  // resources are: the browser process, New Tab Page, and the extension).
-  TaskManagerBrowserTestUtil::WaitForWebResourceChange(2);
-  EXPECT_EQ(1, TaskManager::GetBackgroundPageCount());
-
-  EXPECT_TRUE(model()->GetResourceExtension(0) == NULL);
-  EXPECT_TRUE(model()->GetResourceExtension(1) == NULL);
-  ASSERT_TRUE(model()->GetResourceExtension(resource_count) != NULL);
-
-  // Kill the extension process and make sure we notice it.
-  TaskManager::GetInstance()->KillProcess(resource_count);
-  TaskManagerBrowserTestUtil::WaitForWebResourceChange(1);
-  EXPECT_EQ(0, TaskManager::GetBackgroundPageCount());
-}
-
 // Disabled, http://crbug.com/66957.
 IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest,
                        DISABLED_KillExtensionAndReload) {
diff --git a/chrome/browser/task_manager/task_manager_browsertest_util.cc b/chrome/browser/task_manager/task_manager_browsertest_util.cc
index f711d28..327b31a 100644
--- a/chrome/browser/task_manager/task_manager_browsertest_util.cc
+++ b/chrome/browser/task_manager/task_manager_browsertest_util.cc
@@ -29,7 +29,6 @@
         type == task_manager::Resource::NACL ||
         type == task_manager::Resource::GPU ||
         type == task_manager::Resource::UTILITY ||
-        type == task_manager::Resource::PROFILE_IMPORT ||
         type == task_manager::Resource::ZYGOTE ||
         type == task_manager::Resource::SANDBOX_HELPER) {
       continue;
diff --git a/chrome/browser/task_manager/task_manager_notification_browsertest.cc b/chrome/browser/task_manager/task_manager_notification_browsertest.cc
index 2dcacf3..76ad825 100644
--- a/chrome/browser/task_manager/task_manager_notification_browsertest.cc
+++ b/chrome/browser/task_manager/task_manager_notification_browsertest.cc
@@ -53,7 +53,7 @@
   EXPECT_EQ(0, model()->ResourceCount());
 
   // Show the task manager.
-  chrome::ShowTaskManager(browser(), false);
+  chrome::ShowTaskManager(browser());
   // Expect to see the browser and the New Tab Page renderer.
   TaskManagerBrowserTestUtil::WaitForWebResourceChange(1);
 
diff --git a/chrome/browser/task_profiler/task_profiler_data_serializer.cc b/chrome/browser/task_profiler/task_profiler_data_serializer.cc
index 4ad2fa0..8e93744 100644
--- a/chrome/browser/task_profiler/task_profiler_data_serializer.cc
+++ b/chrome/browser/task_profiler/task_profiler_data_serializer.cc
@@ -7,11 +7,11 @@
 #include "base/file_util.h"
 #include "base/files/file_path.h"
 #include "base/json/json_string_value_serializer.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/tracked_objects.h"
 #include "content/public/common/content_client.h"
 #include "content/public/common/process_type.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 using base::DictionaryValue;
 using base::ListValue;
diff --git a/chrome/browser/themes/browser_theme_pack.cc b/chrome/browser/themes/browser_theme_pack.cc
index 3a8fb68..d6340cb 100644
--- a/chrome/browser/themes/browser_theme_pack.cc
+++ b/chrome/browser/themes/browser_theme_pack.cc
@@ -444,6 +444,30 @@
       *src_image, hsl_shift));
 }
 
+// Computes a bitmap at one scale from a bitmap at a different scale.
+SkBitmap CreateLowQualityResizedBitmap(const SkBitmap& source_bitmap,
+                                       ui::ScaleFactor source_scale_factor,
+                                       ui::ScaleFactor desired_scale_factor) {
+  gfx::Size scaled_size = gfx::ToCeiledSize(
+      gfx::ScaleSize(gfx::Size(source_bitmap.width(),
+                               source_bitmap.height()),
+                     ui::GetScaleFactorScale(desired_scale_factor) /
+                     ui::GetScaleFactorScale(source_scale_factor)));
+  SkBitmap scaled_bitmap;
+  scaled_bitmap.setConfig(SkBitmap::kARGB_8888_Config,
+                          scaled_size.width(),
+                          scaled_size.height());
+  if (!scaled_bitmap.allocPixels())
+    SK_CRASH();
+  scaled_bitmap.eraseARGB(0, 0, 0, 0);
+  SkCanvas canvas(scaled_bitmap);
+  SkRect scaled_bounds = RectToSkRect(gfx::Rect(scaled_size));
+  // Note(oshima): The following scaling code doesn't work with
+  // a mask image.
+  canvas.drawBitmapRect(source_bitmap, NULL, scaled_bounds);
+  return scaled_bitmap;
+}
+
 // A ImageSkiaSource that scales 100P image to the target scale factor
 // if the ImageSkiaRep for the target scale factor isn't available.
 class ThemeImageSource: public gfx::ImageSkiaSource {
@@ -458,20 +482,11 @@
       return source_.GetRepresentation(scale_factor);
     const gfx::ImageSkiaRep& rep_100p =
         source_.GetRepresentation(ui::SCALE_FACTOR_100P);
-    float scale = ui::GetScaleFactorScale(scale_factor);
-    gfx::Size size(rep_100p.GetWidth() * scale, rep_100p.GetHeight() * scale);
-    SkBitmap resized_bitmap;
-    resized_bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(),
-                             size.height());
-    if (!resized_bitmap.allocPixels())
-      SK_CRASH();
-    resized_bitmap.eraseARGB(0, 0, 0, 0);
-    SkCanvas canvas(resized_bitmap);
-    SkRect resized_bounds = RectToSkRect(gfx::Rect(size));
-    // Note(oshima): The following scaling code doesn't work with
-    // a mask image.
-    canvas.drawBitmapRect(rep_100p.sk_bitmap(), NULL, resized_bounds);
-    return gfx::ImageSkiaRep(resized_bitmap, scale_factor);
+    SkBitmap scaled_bitmap = CreateLowQualityResizedBitmap(
+        rep_100p.sk_bitmap(),
+        ui::SCALE_FACTOR_100P,
+        scale_factor);
+    return gfx::ImageSkiaRep(scaled_bitmap, scale_factor);
   }
 
  private:
@@ -480,6 +495,92 @@
   DISALLOW_COPY_AND_ASSIGN(ThemeImageSource);
 };
 
+// An ImageSkiaSource that delays decoding PNG data into bitmaps until
+// needed. Missing data for a scale factor is computed by scaling data for an
+// available scale factor. Computed bitmaps are stored for future look up.
+class ThemeImagePngSource : public gfx::ImageSkiaSource {
+ public:
+  typedef std::map<ui::ScaleFactor,
+                   scoped_refptr<base::RefCountedMemory> > PngMap;
+
+  explicit ThemeImagePngSource(const PngMap& png_map) : png_map_(png_map) {}
+
+  virtual ~ThemeImagePngSource() {}
+
+ private:
+  virtual gfx::ImageSkiaRep GetImageForScale(
+      ui::ScaleFactor scale_factor) OVERRIDE {
+    // Look up the bitmap for |scale factor| in the bitmap map. If found
+    // return it.
+    BitmapMap::const_iterator exact_bitmap_it = bitmap_map_.find(scale_factor);
+    if (exact_bitmap_it != bitmap_map_.end())
+      return gfx::ImageSkiaRep(exact_bitmap_it->second, scale_factor);
+
+    // Look up the raw PNG data for |scale_factor| in the png map. If found,
+    // decode it, store the result in the bitmap map and return it.
+    PngMap::const_iterator exact_png_it = png_map_.find(scale_factor);
+    if (exact_png_it != png_map_.end()) {
+      SkBitmap bitmap;
+      if (!gfx::PNGCodec::Decode(exact_png_it->second->front(),
+                                 exact_png_it->second->size(),
+                                 &bitmap)) {
+        NOTREACHED();
+        return gfx::ImageSkiaRep();
+      }
+      bitmap_map_[scale_factor] = bitmap;
+      return gfx::ImageSkiaRep(bitmap, scale_factor);
+    }
+
+    // Find an available PNG for another scale factor. We want to use the
+    // highest available scale factor.
+    PngMap::const_iterator available_png_it = png_map_.end();
+    for (PngMap::const_iterator png_it = png_map_.begin();
+         png_it != png_map_.end(); ++png_it) {
+      if (available_png_it == png_map_.end() ||
+          ui::GetScaleFactorScale(png_it->first) >
+          ui::GetScaleFactorScale(available_png_it->first)) {
+        available_png_it = png_it;
+      }
+    }
+    if (available_png_it == png_map_.end())
+      return gfx::ImageSkiaRep();
+    ui::ScaleFactor available_scale_factor = available_png_it->first;
+
+    // Look up the bitmap for |available_scale_factor| in the bitmap map.
+    // If not found, decode the corresponging png data, store the result
+    // in the bitmap map.
+    BitmapMap::const_iterator available_bitmap_it =
+        bitmap_map_.find(available_scale_factor);
+    if (available_bitmap_it == bitmap_map_.end()) {
+      SkBitmap available_bitmap;
+      if (!gfx::PNGCodec::Decode(available_png_it->second->front(),
+                                 available_png_it->second->size(),
+                                 &available_bitmap)) {
+        NOTREACHED();
+        return gfx::ImageSkiaRep();
+      }
+      bitmap_map_[available_scale_factor] = available_bitmap;
+      available_bitmap_it = bitmap_map_.find(available_scale_factor);
+    }
+
+    // Scale the available bitmap to the desired scale factor, store the result
+    // in the bitmap map and return it.
+    SkBitmap scaled_bitmap = CreateLowQualityResizedBitmap(
+        available_bitmap_it->second,
+        available_scale_factor,
+        scale_factor);
+    bitmap_map_[scale_factor] = scaled_bitmap;
+    return gfx::ImageSkiaRep(scaled_bitmap, scale_factor);
+  }
+
+  PngMap png_map_;
+
+  typedef std::map<ui::ScaleFactor, SkBitmap> BitmapMap;
+  BitmapMap bitmap_map_;
+
+  DISALLOW_COPY_AND_ASSIGN(ThemeImagePngSource);
+};
+
 class TabBackgroundImageSource: public gfx::CanvasImageSource {
  public:
   TabBackgroundImageSource(const gfx::ImageSkia& image_to_tint,
@@ -749,34 +850,22 @@
   if (image_iter != images_on_ui_thread_.end())
     return image_iter->second;
 
-  // TODO(pkotwicz): Do something better than loading the bitmaps
-  // for all the scale factors associated with |idr_id|.
-  // See crbug.com/243831.
-  gfx::ImageSkia source_image_skia;
+  ThemeImagePngSource::PngMap png_map;
   for (size_t i = 0; i < scale_factors_.size(); ++i) {
     scoped_refptr<base::RefCountedMemory> memory =
         GetRawData(idr_id, scale_factors_[i]);
-    if (memory.get()) {
-      // Decode the PNG.
-      SkBitmap bitmap;
-      if (!gfx::PNGCodec::Decode(memory->front(), memory->size(),
-                                 &bitmap)) {
-        NOTREACHED() << "Unable to decode theme image resource " << idr_id
-                     << " from saved DataPack.";
-        continue;
-      }
-      source_image_skia.AddRepresentation(
-          gfx::ImageSkiaRep(bitmap, scale_factors_[i]));
-    }
+    if (memory.get())
+      png_map[scale_factors_[i]] = memory;
   }
-
-  if (!source_image_skia.isNull()) {
-    ThemeImageSource* source = new ThemeImageSource(source_image_skia);
-    gfx::ImageSkia image_skia(source, source_image_skia.size());
+  if (!png_map.empty()) {
+    gfx::ImageSkia image_skia(new ThemeImagePngSource(png_map),
+                              ui::SCALE_FACTOR_100P);
+    // |image_skia| takes ownership of ThemeImagePngSource.
     gfx::Image ret = gfx::Image(image_skia);
     images_on_ui_thread_[prs_id] = ret;
     return ret;
   }
+
   return gfx::Image();
 }
 
@@ -1475,29 +1564,29 @@
     return;
 
   // Find available scale factor with highest scale.
-  ui::ScaleFactor available = ui::SCALE_FACTOR_NONE;
+  ui::ScaleFactor available_scale_factor = ui::SCALE_FACTOR_NONE;
   for (size_t i = 0; i < scale_factors_.size(); ++i) {
     int raw_id = GetRawIDByPersistentID(prs_id, scale_factors_[i]);
-    if ((available == ui::SCALE_FACTOR_NONE ||
+    if ((available_scale_factor == ui::SCALE_FACTOR_NONE ||
          (ui::GetScaleFactorScale(scale_factors_[i]) >
-          ui::GetScaleFactorScale(available))) &&
+          ui::GetScaleFactorScale(available_scale_factor))) &&
         image_memory_.find(raw_id) != image_memory_.end()) {
-      available = scale_factors_[i];
+      available_scale_factor = scale_factors_[i];
     }
   }
   // If no scale factor is available, we're done.
-  if (available == ui::SCALE_FACTOR_NONE)
+  if (available_scale_factor == ui::SCALE_FACTOR_NONE)
     return;
 
   // Get bitmap for the available scale factor.
-  int available_raw_id = GetRawIDByPersistentID(prs_id, available);
+  int available_raw_id = GetRawIDByPersistentID(prs_id, available_scale_factor);
   RawImages::const_iterator it = image_memory_.find(available_raw_id);
   SkBitmap available_bitmap;
   if (!gfx::PNGCodec::Decode(it->second->front(),
                              it->second->size(),
                              &available_bitmap)) {
     NOTREACHED() << "Unable to decode theme image for prs_id="
-                 << prs_id << " for scale_factor=" << available;
+                 << prs_id << " for scale_factor=" << available_scale_factor;
     return;
   }
 
@@ -1506,21 +1595,10 @@
     int scaled_raw_id = GetRawIDByPersistentID(prs_id, scale_factors_[i]);
     if (image_memory_.find(scaled_raw_id) != image_memory_.end())
       continue;
-    gfx::Size scaled_size = gfx::ToCeiledSize(
-        gfx::ScaleSize(gfx::Size(available_bitmap.width(),
-                                 available_bitmap.height()),
-                       ui::GetScaleFactorScale(scale_factors_[i]) /
-                       ui::GetScaleFactorScale(available)));
-    SkBitmap scaled_bitmap;
-    scaled_bitmap.setConfig(SkBitmap::kARGB_8888_Config,
-                            scaled_size.width(),
-                            scaled_size.height());
-    if (!scaled_bitmap.allocPixels())
-      SK_CRASH();
-    scaled_bitmap.eraseARGB(0, 0, 0, 0);
-    SkCanvas canvas(scaled_bitmap);
-    SkRect scaled_bounds = RectToSkRect(gfx::Rect(scaled_size));
-    canvas.drawBitmapRect(available_bitmap, NULL, scaled_bounds);
+    SkBitmap scaled_bitmap =
+        CreateLowQualityResizedBitmap(available_bitmap,
+                                      available_scale_factor,
+                                      scale_factors_[i]);
     std::vector<unsigned char> bitmap_data;
     if (!gfx::PNGCodec::EncodeBGRASkBitmap(scaled_bitmap,
                                            false,
diff --git a/chrome/browser/themes/theme_properties.cc b/chrome/browser/themes/theme_properties.cc
index ec777b6..0390af4 100644
--- a/chrome/browser/themes/theme_properties.cc
+++ b/chrome/browser/themes/theme_properties.cc
@@ -30,6 +30,9 @@
 const SkColor kDefaultColorFrameIncognito = SkColorSetRGB(83, 106, 139);
 const SkColor kDefaultColorFrameIncognitoInactive =
     SkColorSetRGB(126, 139, 156);
+const SkColor kDefaultColorFrameManagedUser = SkColorSetRGB(165, 197, 225);
+const SkColor kDefaultColorFrameManagedUserInactive =
+    SkColorSetRGB(180, 225, 247);
 #if defined(OS_MACOSX)
 const SkColor kDefaultColorToolbar = SkColorSetRGB(230, 230, 230);
 #else
@@ -249,6 +252,10 @@
       return kDefaultColorFrameIncognito;
     case COLOR_FRAME_INCOGNITO_INACTIVE:
       return kDefaultColorFrameIncognitoInactive;
+    case COLOR_FRAME_MANAGED_USER:
+      return kDefaultColorFrameManagedUser;
+    case COLOR_FRAME_MANAGED_USER_INACTIVE:
+      return kDefaultColorFrameManagedUserInactive;
     case COLOR_TOOLBAR:
       return kDefaultColorToolbar;
     case COLOR_TAB_TEXT:
diff --git a/chrome/browser/themes/theme_properties.h b/chrome/browser/themes/theme_properties.h
index 2eaa1ed..0f503c9 100644
--- a/chrome/browser/themes/theme_properties.h
+++ b/chrome/browser/themes/theme_properties.h
@@ -80,6 +80,8 @@
   enum NotOverwritableByUserThemeProperty {
     COLOR_CONTROL_BACKGROUND = 1000,
     COLOR_TOOLBAR_SEPARATOR,
+    COLOR_FRAME_MANAGED_USER,
+    COLOR_FRAME_MANAGED_USER_INACTIVE,
 
     // These colors don't have constant default values. They are derived from
     // the runtime value of other colors.
diff --git a/chrome/browser/themes/theme_service.cc b/chrome/browser/themes/theme_service.cc
index 6a90368..fb594d8 100644
--- a/chrome/browser/themes/theme_service.cc
+++ b/chrome/browser/themes/theme_service.cc
@@ -32,8 +32,8 @@
 #include "ui/base/win/shell.h"
 #endif
 
-#if defined(USE_AURA) && !defined(USE_ASH) && defined(OS_LINUX)
-#include "ui/linux_ui/linux_ui.h"
+#if defined(ENABLE_MANAGED_USERS)
+#include "chrome/browser/managed_mode/managed_user_service.h"
 #endif
 
 using content::BrowserThread;
@@ -104,16 +104,21 @@
 gfx::Image ThemeService::GetImageNamed(int id) const {
   DCHECK(CalledOnValidThread());
 
+  // For a managed user, use the special frame instead of the default one.
+  // TODO(akuegel): Remove this once we have the default managed user theme.
+  if (IsManagedUser()) {
+    if (id == IDR_THEME_FRAME)
+      id = IDR_MANAGED_USER_THEME_FRAME;
+    else if (id == IDR_THEME_FRAME_INACTIVE)
+      id = IDR_MANAGED_USER_THEME_FRAME_INACTIVE;
+    else if (id == IDR_THEME_TAB_BACKGROUND || id == IDR_THEME_TAB_BACKGROUND_V)
+      id = IDR_MANAGED_USER_THEME_TAB_BACKGROUND;
+  }
+
   gfx::Image image;
   if (theme_pack_.get())
     image = theme_pack_->GetImageNamed(id);
 
-#if defined(USE_AURA) && !defined(USE_ASH) && defined(OS_LINUX)
-  const ui::LinuxUI* linux_ui = ui::LinuxUI::instance();
-  if (image.IsEmpty() && linux_ui)
-    image = linux_ui->GetThemeImageNamed(id);
-#endif
-
   if (image.IsEmpty())
     image = rb_.GetNativeImageNamed(id);
 
@@ -132,16 +137,18 @@
 SkColor ThemeService::GetColor(int id) const {
   DCHECK(CalledOnValidThread());
 
+  // TODO(akuegel): Remove this once we have the default managed user theme.
+  if (IsManagedUser()) {
+    if (id == Properties::COLOR_FRAME)
+      id = Properties::COLOR_FRAME_MANAGED_USER;
+    else if (id == Properties::COLOR_FRAME_INACTIVE)
+      id = Properties::COLOR_FRAME_MANAGED_USER_INACTIVE;
+  }
+
   SkColor color;
   if (theme_pack_.get() && theme_pack_->GetColor(id, &color))
     return color;
 
-#if defined(USE_AURA) && !defined(USE_ASH) && defined(OS_LINUX)
-  const ui::LinuxUI* linux_ui = ui::LinuxUI::instance();
-  if (linux_ui && linux_ui->GetColor(id, &color))
-    return color;
-#endif
-
   // For backward compat with older themes, some newer colors are generated from
   // older ones if they are missing.
   switch (id) {
@@ -156,12 +163,14 @@
     case Properties::COLOR_NTP_TEXT_LIGHT:
       return IncreaseLightness(GetColor(Properties::COLOR_NTP_TEXT), 0.40);
     case Properties::COLOR_MANAGED_USER_LABEL:
-      return color_utils::GetReadableColor(
-          SK_ColorWHITE,
-          GetColor(Properties::COLOR_MANAGED_USER_LABEL_BACKGROUND));
+      // TODO(akuegel): Use GetReadableColor() once we want to support other
+      // themes as well.
+      return SkColorSetRGB(231, 245, 255);
     case Properties::COLOR_MANAGED_USER_LABEL_BACKGROUND:
-      return color_utils::BlendTowardOppositeLuminance(
-          GetColor(Properties::COLOR_FRAME), 0x80);
+      // TODO(akuegel): Replace this constant by a color calculated from the
+      // frame color once the default managed user theme is finished and we
+      // allow managed users to install other themes.
+      return SkColorSetRGB(108, 167, 210);
   }
 
   return Properties::GetDefaultColor(id);
@@ -419,6 +428,13 @@
   theme_pack_ = pack;
 }
 
+bool ThemeService::IsManagedUser() const {
+#if defined(ENABLE_MANAGED_USERS)
+  return ManagedUserService::ProfileIsManaged(profile_);
+#endif
+  return false;
+}
+
 void ThemeService::OnInfobarDisplayed() {
   number_of_infobars_++;
 }
diff --git a/chrome/browser/themes/theme_service.h b/chrome/browser/themes/theme_service.h
index 48f320d..b6d8869 100644
--- a/chrome/browser/themes/theme_service.h
+++ b/chrome/browser/themes/theme_service.h
@@ -163,7 +163,7 @@
   // from ClearCaches().
   virtual void FreePlatformCaches();
 
-  Profile* profile() { return profile_; }
+  Profile* profile() const { return profile_; }
 
   void set_ready() { ready_ = true; }
 
@@ -184,6 +184,9 @@
   // case we don't have a theme pack).
   void BuildFromExtension(const extensions::Extension* extension);
 
+  // Returns true if the profile belongs to a managed user.
+  bool IsManagedUser() const;
+
 #if defined(TOOLKIT_GTK)
   // Loads an image and flips it horizontally if |rtl_enabled| is true.
   GdkPixbuf* GetPixbufImpl(int id, bool rtl_enabled) const;
diff --git a/chrome/browser/themes/theme_service_aurax11.cc b/chrome/browser/themes/theme_service_aurax11.cc
new file mode 100644
index 0000000..fe1c3de
--- /dev/null
+++ b/chrome/browser/themes/theme_service_aurax11.cc
@@ -0,0 +1,85 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/themes/theme_service_aurax11.h"
+
+#include "base/bind.h"
+#include "base/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/pref_names.h"
+#include "ui/gfx/image/image.h"
+#include "ui/linux_ui/linux_ui.h"
+
+ThemeServiceAuraX11::ThemeServiceAuraX11()
+    : use_system_theme_(false) {
+}
+
+ThemeServiceAuraX11::~ThemeServiceAuraX11() {}
+
+void ThemeServiceAuraX11::Init(Profile* profile) {
+  registrar_.Init(profile->GetPrefs());
+  registrar_.Add(prefs::kUsesSystemTheme,
+                 base::Bind(&ThemeServiceAuraX11::OnUsesSystemThemeChanged,
+                            base::Unretained(this)));
+  use_system_theme_ = profile->GetPrefs()->GetBoolean(prefs::kUsesSystemTheme);
+
+  ThemeService::Init(profile);
+}
+
+gfx::Image ThemeServiceAuraX11::GetImageNamed(int id) const {
+  const ui::LinuxUI* linux_ui = ui::LinuxUI::instance();
+  if (use_system_theme_ && linux_ui) {
+    gfx::Image image = linux_ui->GetThemeImageNamed(id);
+    if (!image.IsEmpty())
+      return image;
+  }
+
+  return ThemeService::GetImageNamed(id);
+}
+
+SkColor ThemeServiceAuraX11::GetColor(int id) const {
+  const ui::LinuxUI* linux_ui = ui::LinuxUI::instance();
+  SkColor color;
+  if (use_system_theme_ && linux_ui && linux_ui->GetColor(id, &color))
+    return color;
+
+  return ThemeService::GetColor(id);
+}
+
+bool ThemeServiceAuraX11::HasCustomImage(int id) const {
+  const ui::LinuxUI* linux_ui = ui::LinuxUI::instance();
+  if (use_system_theme_ && linux_ui)
+    return linux_ui->HasCustomImage(id);
+
+  return ThemeService::HasCustomImage(id);
+}
+
+void ThemeServiceAuraX11::SetTheme(const extensions::Extension* extension) {
+  profile()->GetPrefs()->SetBoolean(prefs::kUsesSystemTheme, false);
+  ThemeService::SetTheme(extension);
+}
+
+void ThemeServiceAuraX11::UseDefaultTheme() {
+  profile()->GetPrefs()->SetBoolean(prefs::kUsesSystemTheme, false);
+  ThemeService::UseDefaultTheme();
+}
+
+void ThemeServiceAuraX11::SetNativeTheme() {
+  profile()->GetPrefs()->SetBoolean(prefs::kUsesSystemTheme, true);
+  ClearAllThemeData();
+  NotifyThemeChanged();
+}
+
+bool ThemeServiceAuraX11::UsingDefaultTheme() const {
+  return !use_system_theme_ && ThemeService::UsingDefaultTheme();
+}
+
+bool ThemeServiceAuraX11::UsingNativeTheme() const {
+  return use_system_theme_;
+}
+
+void ThemeServiceAuraX11::OnUsesSystemThemeChanged() {
+  use_system_theme_ =
+      profile()->GetPrefs()->GetBoolean(prefs::kUsesSystemTheme);
+}
diff --git a/chrome/browser/themes/theme_service_aurax11.h b/chrome/browser/themes/theme_service_aurax11.h
new file mode 100644
index 0000000..96dce92
--- /dev/null
+++ b/chrome/browser/themes/theme_service_aurax11.h
@@ -0,0 +1,43 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_THEMES_THEME_SERVICE_AURAX11_H_
+#define CHROME_BROWSER_THEMES_THEME_SERVICE_AURAX11_H_
+
+#include "base/prefs/pref_change_registrar.h"
+#include "chrome/browser/themes/theme_service.h"
+
+// A subclass of ThemeService that queries the current ui::LinuxUI instance for
+// theme data.
+class ThemeServiceAuraX11 : public ThemeService {
+ public:
+  ThemeServiceAuraX11();
+  virtual ~ThemeServiceAuraX11();
+
+  // Overridden from ui::ThemeProvider:
+  virtual SkColor GetColor(int id) const OVERRIDE;
+  virtual bool HasCustomImage(int id) const OVERRIDE;
+
+  // Overridden from ThemeService:
+  virtual void Init(Profile* profile) OVERRIDE;
+  virtual gfx::Image GetImageNamed(int id) const OVERRIDE;
+  virtual void SetTheme(const extensions::Extension* extension) OVERRIDE;
+  virtual void UseDefaultTheme() OVERRIDE;
+  virtual void SetNativeTheme() OVERRIDE;
+  virtual bool UsingDefaultTheme() const OVERRIDE;
+  virtual bool UsingNativeTheme() const OVERRIDE;
+
+ private:
+  void OnUsesSystemThemeChanged();
+
+  // Whether we'll give the ui::LinuxUI object first shot at providing theme
+  // resources.
+  bool use_system_theme_;
+
+  PrefChangeRegistrar registrar_;
+
+  DISALLOW_COPY_AND_ASSIGN(ThemeServiceAuraX11);
+};
+
+#endif  // CHROME_BROWSER_THEMES_THEME_SERVICE_AURAX11_H_
diff --git a/chrome/browser/themes/theme_service_factory.cc b/chrome/browser/themes/theme_service_factory.cc
index 054d56c..adc424b 100644
--- a/chrome/browser/themes/theme_service_factory.cc
+++ b/chrome/browser/themes/theme_service_factory.cc
@@ -18,6 +18,11 @@
 #include "chrome/browser/ui/gtk/gtk_theme_service.h"
 #endif
 
+#if defined(USE_AURA) && defined(OS_LINUX) && !defined(OS_CHROMEOS)
+#include "chrome/browser/themes/theme_service_aurax11.h"
+#include "ui/linux_ui/linux_ui.h"
+#endif
+
 // static
 ThemeService* ThemeServiceFactory::GetForProfile(Profile* profile) {
   return static_cast<ThemeService*>(
@@ -51,6 +56,8 @@
   ThemeService* provider = NULL;
 #if defined(TOOLKIT_GTK)
   provider = new GtkThemeService;
+#elif defined(USE_AURA) && defined(OS_LINUX) && !defined(OS_CHROMEOS)
+  provider = new ThemeServiceAuraX11;
 #else
   provider = new ThemeService;
 #endif
@@ -61,10 +68,20 @@
 
 void ThemeServiceFactory::RegisterUserPrefs(
     user_prefs::PrefRegistrySyncable* registry) {
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+  bool default_uses_system_theme = false;
+
 #if defined(TOOLKIT_GTK)
+  default_uses_system_theme = GtkThemeService::DefaultUsesSystemTheme();
+#elif defined(USE_AURA) && defined(OS_LINUX) && !defined(OS_CHROMEOS)
+  const ui::LinuxUI* linux_ui = ui::LinuxUI::instance();
+  if (linux_ui)
+    default_uses_system_theme = linux_ui->GetDefaultUsesSystemTheme();
+#endif
+
   registry->RegisterBooleanPref(
       prefs::kUsesSystemTheme,
-      GtkThemeService::DefaultUsesSystemTheme(),
+      default_uses_system_theme,
       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
 #endif
   registry->RegisterFilePathPref(
diff --git a/chrome/browser/themes/theme_syncable_service.cc b/chrome/browser/themes/theme_syncable_service.cc
index bf414d6..3389443 100644
--- a/chrome/browser/themes/theme_syncable_service.cc
+++ b/chrome/browser/themes/theme_syncable_service.cc
@@ -135,6 +135,7 @@
 
   if (!sync_processor_.get()) {
     return syncer::SyncError(FROM_HERE,
+                             syncer::SyncError::DATATYPE_ERROR,
                              "Theme syncable service is not started.",
                              syncer::THEMES);
   }
@@ -180,8 +181,8 @@
   }
 
   return syncer::SyncError(FROM_HERE,
-                           base::StringPrintf(
-                               "Didn't find valid theme specifics."),
+                           syncer::SyncError::DATATYPE_ERROR,
+                           "Didn't find valid theme specifics",
                            syncer::THEMES);
 }
 
diff --git a/chrome/browser/themes/theme_syncable_service_unittest.cc b/chrome/browser/themes/theme_syncable_service_unittest.cc
index 4099223..5931a17 100644
--- a/chrome/browser/themes/theme_syncable_service_unittest.cc
+++ b/chrome/browser/themes/theme_syncable_service_unittest.cc
@@ -505,8 +505,9 @@
   // ProcessSyncChanges() should return error when sync has stopped.
   error = theme_sync_service_->ProcessSyncChanges(FROM_HERE, change_list);
   EXPECT_TRUE(error.IsSet());
-  EXPECT_EQ(syncer::THEMES, error.type());
-  EXPECT_EQ("Theme syncable service is not started.",
+  EXPECT_EQ(syncer::THEMES, error.model_type());
+  EXPECT_EQ("datatype error was encountered: Theme syncable service is not "
+                "started.",
             error.message());
 }
 
diff --git a/chrome/browser/three_d_api_observer.cc b/chrome/browser/three_d_api_observer.cc
index 02e52e9..61b39cf 100644
--- a/chrome/browser/three_d_api_observer.cc
+++ b/chrome/browser/three_d_api_observer.cc
@@ -11,9 +11,9 @@
 #include "content/public/browser/gpu_data_manager.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/three_d_api_types.h"
-#include "googleurl/src/gurl.h"
 #include "grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "url/gurl.h"
 
 
 // ThreeDAPIInfoBarDelegate ---------------------------------------------
diff --git a/chrome/browser/thumbnails/thumbnail_service.h b/chrome/browser/thumbnails/thumbnail_service.h
index 9c7e395..11da713 100644
--- a/chrome/browser/thumbnails/thumbnail_service.h
+++ b/chrome/browser/thumbnails/thumbnail_service.h
@@ -7,8 +7,8 @@
 
 #include "chrome/common/thumbnail_score.h"
 #include "components/browser_context_keyed_service/refcounted_browser_context_keyed_service.h"
-#include "googleurl/src/gurl.h"
 #include "ui/gfx/image/image.h"
+#include "url/gurl.h"
 
 namespace base {
 class RefCountedMemory;
diff --git a/chrome/browser/translate/translate_accept_languages.cc b/chrome/browser/translate/translate_accept_languages.cc
index 6de5225..df2f4cc 100644
--- a/chrome/browser/translate/translate_accept_languages.cc
+++ b/chrome/browser/translate/translate_accept_languages.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/translate/translate_accept_languages.h"
 
 #include "base/bind.h"
+#include "base/command_line.h"
 #include "base/prefs/pref_change_registrar.h"
 #include "base/prefs/pref_service.h"
 #include "base/strings/string_split.h"
@@ -13,6 +14,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/translate/translate_manager.h"
 #include "chrome/common/chrome_notification_types.h"
+#include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/translate/translate_util.h"
 #include "content/public/browser/notification_source.h"
@@ -89,6 +91,11 @@
   std::string app_locale = g_browser_process->GetApplicationLocale();
   std::string ui_lang = TranslateManager::GetLanguageCode(app_locale);
   bool is_ui_english = StartsWithASCII(ui_lang, "en-", false);
+
+  CommandLine* command_line = CommandLine::ForCurrentProcess();
+  bool enable_translate_settings =
+      command_line->HasSwitch(switches::kEnableTranslateSettings);
+
   for (iter = accept_langs_list.begin();
        iter != accept_langs_list.end(); ++iter) {
     // Get rid of the locale extension if any (ex: en-US -> en), but for Chinese
@@ -97,6 +104,7 @@
     size_t index = iter->find("-");
     if (index != std::string::npos && *iter != "zh-CN" && *iter != "zh-TW")
       accept_lang = iter->substr(0, index);
+
     // Special-case English until we resolve bug 36182 properly.
     // Add English only if the UI language is not English. This will annoy
     // users of non-English Chrome who can comprehend English until English is
@@ -104,8 +112,12 @@
     // TODO(jungshik): Once we determine that it's safe to remove English from
     // the default Accept-Language values for most locales, remove this
     // special-casing.
-    if (accept_lang != "en" || is_ui_english)
-      accept_langs_set.insert(accept_lang);
+    // TODO(hajimehoshi): We can remove this special-casing if the Translate
+    // settings UI is enabled by default.
+    if (!enable_translate_settings && accept_lang == "en" && !is_ui_english)
+      continue;
+
+    accept_langs_set.insert(accept_lang);
   }
   accept_languages_[prefs] = accept_langs_set;
 }
diff --git a/chrome/browser/translate/translate_browsertest.cc b/chrome/browser/translate/translate_browsertest.cc
index bb6ec05..f65093f 100644
--- a/chrome/browser/translate/translate_browsertest.cc
+++ b/chrome/browser/translate/translate_browsertest.cc
@@ -19,6 +19,7 @@
 #include "content/public/browser/notification_service.h"
 #include "content/public/test/browser_test_utils.h"
 #include "net/http/http_status_code.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
 #include "net/test/spawned_test_server/spawned_test_server.h"
 #include "net/url_request/test_url_fetcher_factory.h"
 #include "net/url_request/url_fetcher_delegate.h"
@@ -27,7 +28,7 @@
 
 const base::FilePath::CharType kTranslateRoot[] =
     FILE_PATH_LITERAL("chrome/test/data/translate");
-const char kNonSecurePrefix[] = "files/translate/";
+const char kNonSecurePrefix[] = "/translate/";
 const char kSecurePrefix[] = "files/";
 const char kFrenchTestPath[] = "fr_test.html";
 const char kRefreshMetaTagTestPath[] = "refresh_meta_tag.html";
@@ -56,7 +57,7 @@
  protected:
   GURL GetNonSecureURL(const std::string& path) const {
     std::string prefix(kNonSecurePrefix);
-    return test_server()->GetURL(prefix + path);
+    return embedded_test_server()->GetURL(prefix + path);
   }
 
   GURL GetSecureURL(const std::string& path) const {
@@ -73,7 +74,7 @@
 };
 
 IN_PROC_BROWSER_TEST_F(TranslateBrowserTest, Translate) {
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   content::WebContents* web_contents =
       browser()->tab_strip_model()->GetActiveWebContents();
@@ -141,7 +142,7 @@
 }
 
 IN_PROC_BROWSER_TEST_F(TranslateBrowserTest, IgnoreRefreshMetaTag) {
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   content::WebContents* web_contents =
       browser()->tab_strip_model()->GetActiveWebContents();
@@ -172,7 +173,7 @@
 
 IN_PROC_BROWSER_TEST_F(TranslateBrowserTest,
                        IgnoreRefreshMetaTagInCaseInsensitive) {
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   content::WebContents* web_contents =
       browser()->tab_strip_model()->GetActiveWebContents();
@@ -202,7 +203,7 @@
 }
 
 IN_PROC_BROWSER_TEST_F(TranslateBrowserTest, IgnoreRefreshMetaTagAtOnload) {
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   content::WebContents* web_contents =
       browser()->tab_strip_model()->GetActiveWebContents();
@@ -232,7 +233,7 @@
 }
 
 IN_PROC_BROWSER_TEST_F(TranslateBrowserTest, UpdateLocation) {
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   content::WebContents* web_contents =
       browser()->tab_strip_model()->GetActiveWebContents();
@@ -262,7 +263,7 @@
 }
 
 IN_PROC_BROWSER_TEST_F(TranslateBrowserTest, UpdateLocationAtOnload) {
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   content::WebContents* web_contents =
       browser()->tab_strip_model()->GetActiveWebContents();
diff --git a/chrome/browser/translate/translate_error_details.h b/chrome/browser/translate/translate_error_details.h
index bb2b0b6..b2b5506 100644
--- a/chrome/browser/translate/translate_error_details.h
+++ b/chrome/browser/translate/translate_error_details.h
@@ -5,9 +5,9 @@
 #ifndef CHROME_BROWSER_TRANSLATE_TRANSLATE_ERROR_DETAILS_H_
 #define CHROME_BROWSER_TRANSLATE_TRANSLATE_ERROR_DETAILS_H_
 
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/common/translate/translate_errors.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 struct TranslateErrorDetails {
   // The time when this was created
diff --git a/chrome/browser/translate/translate_event_details.h b/chrome/browser/translate/translate_event_details.h
index a788f41..0b98b6d 100644
--- a/chrome/browser/translate/translate_event_details.h
+++ b/chrome/browser/translate/translate_event_details.h
@@ -7,7 +7,7 @@
 
 #include <string>
 
-#include "base/time.h"
+#include "base/time/time.h"
 
 struct TranslateEventDetails {
   TranslateEventDetails(const std::string& in_filename,
diff --git a/chrome/browser/translate/translate_infobar_delegate.cc b/chrome/browser/translate/translate_infobar_delegate.cc
index ca9df4c..b1f1345 100644
--- a/chrome/browser/translate/translate_infobar_delegate.cc
+++ b/chrome/browser/translate/translate_infobar_delegate.cc
@@ -74,6 +74,16 @@
                                    original_language, target_language));
   infobar->UpdateBackgroundAnimation(old_delegate);
 
+  // Do not create the after translate infobar if we are auto translating.
+  if (infobar_type == TranslateInfoBarDelegate::AFTER_TRANSLATE ||
+      infobar_type == TranslateInfoBarDelegate::TRANSLATING) {
+    TranslateTabHelper* translate_tab_helper =
+      TranslateTabHelper::FromWebContents(infobar_service->web_contents());
+    if (!translate_tab_helper ||
+         translate_tab_helper->language_state().InTranslateNavigation())
+      return;
+  }
+
   // Add the new delegate if necessary.
   if (!old_delegate) {
     infobar_service->AddInfoBar(infobar.PassAs<InfoBarDelegate>());
@@ -126,14 +136,6 @@
   UMA_HISTOGRAM_BOOLEAN(kDeclineTranslate, true);
 }
 
-bool TranslateInfoBarDelegate::InTranslateNavigation() {
-  TranslateTabHelper* translate_tab_helper =
-      TranslateTabHelper::FromWebContents(web_contents());
-  if (!translate_tab_helper)
-    return false;
-  return translate_tab_helper->language_state().InTranslateNavigation();
-}
-
 bool TranslateInfoBarDelegate::IsTranslatableLanguageByPrefs() {
   Profile* profile =
       Profile::FromBrowserContext(web_contents()->GetBrowserContext());
@@ -144,10 +146,10 @@
 
 void TranslateInfoBarDelegate::ToggleTranslatableLanguageByPrefs() {
   const std::string& original_lang = original_language_code();
-  if (prefs_.IsLanguageBlacklisted(original_lang)) {
-    prefs_.RemoveLanguageFromBlacklist(original_lang);
+  if (prefs_.IsBlockedLanguage(original_lang)) {
+    prefs_.UnblockLanguage(original_lang);
   } else {
-    prefs_.BlacklistLanguage(original_lang);
+    prefs_.BlockLanguage(original_lang);
     RemoveSelf();
   }
 }
@@ -194,8 +196,8 @@
 
 void TranslateInfoBarDelegate::NeverTranslatePageLanguage() {
   std::string original_lang = original_language_code();
-  DCHECK(!prefs_.IsLanguageBlacklisted(original_lang));
-  prefs_.BlacklistLanguage(original_lang);
+  DCHECK(!prefs_.IsBlockedLanguage(original_lang));
+  prefs_.BlockLanguage(original_lang);
   RemoveSelf();
 }
 
diff --git a/chrome/browser/translate/translate_infobar_delegate.h b/chrome/browser/translate/translate_infobar_delegate.h
index 257a32d..066df9b 100644
--- a/chrome/browser/translate/translate_infobar_delegate.h
+++ b/chrome/browser/translate/translate_infobar_delegate.h
@@ -148,7 +148,6 @@
   string16 GetMessageInfoBarButtonText();
   void MessageInfoBarButtonPressed();
   bool ShouldShowMessageInfoBarButton();
-  bool InTranslateNavigation();
 
   // Called by the before translate infobar to figure-out if it should show
   // an extra shortcut to let the user black-list/white-list that language
diff --git a/chrome/browser/translate/translate_language_list.cc b/chrome/browser/translate/translate_language_list.cc
index af0f77f..88f0701 100644
--- a/chrome/browser/translate/translate_language_list.cc
+++ b/chrome/browser/translate/translate_language_list.cc
@@ -17,14 +17,11 @@
 #include "chrome/browser/translate/translate_browser_metrics.h"
 #include "chrome/browser/translate/translate_event_details.h"
 #include "chrome/browser/translate/translate_manager.h"
+#include "chrome/browser/translate/translate_url_fetcher.h"
 #include "chrome/browser/translate/translate_url_util.h"
-#include "googleurl/src/gurl.h"
-#include "net/base/load_flags.h"
 #include "net/base/url_util.h"
-#include "net/http/http_status_code.h"
-#include "net/url_request/url_fetcher.h"
-#include "net/url_request/url_request_status.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "url/gurl.h"
 
 namespace {
 
@@ -106,14 +103,17 @@
 const char kAlphaLanguageQueryName[] = "alpha";
 const char kAlphaLanguageQueryValue[] = "1";
 
-// Retry parameter for fetching supporting language list.
-const int kMaxRetryLanguageListFetch = 5;
-
 // Assign following IDs to URLFetchers so that tests can distinguish each
 // request in order to simiulate respectively.
 const int kFetcherIdForLanguageList = 1;
 const int kFetcherIdForAlphaLanguageList = 2;
 
+// Represent if the language list updater is disabled.
+bool update_is_disabled = false;
+
+// Retry parameter for fetching.
+const int kMaxRetryOn5xx = 5;
+
 // Show a message in chrome:://translate-internals Event Logs.
 void NotifyEvent(int line, const std::string& message) {
   TranslateManager* manager = TranslateManager::GetInstance();
@@ -187,83 +187,22 @@
   NotifyEvent(__LINE__, message);
 }
 
-}  // namespace
-
-TranslateLanguageList::LanguageListFetcher::LanguageListFetcher(
-    bool include_alpha_languages)
-  : include_alpha_languages_(include_alpha_languages),
-    state_(IDLE) {
-}
-
-TranslateLanguageList::LanguageListFetcher::~LanguageListFetcher() {
-}
-
-bool TranslateLanguageList::LanguageListFetcher::Request(
-    const TranslateLanguageList::LanguageListFetcher::Callback& callback) {
-  // This function is not supporsed to be called before previous operaion is not
-  // finished.
-  if (state_ == REQUESTING) {
-    NOTREACHED();
-    return false;
-  }
-
-  state_ = REQUESTING;
-  callback_ = callback;
-
+// Returns URL to fetch the language list.
+GURL GetLanguageListFetchURL(bool include_alpha_languages) {
   GURL url = GURL(kLanguageListFetchURL);
   url = TranslateURLUtil::AddHostLocaleToUrl(url);
   url = TranslateURLUtil::AddApiKeyToUrl(url);
-  if (include_alpha_languages_) {
+
+  if (include_alpha_languages) {
     url = net::AppendQueryParameter(url,
                                     kAlphaLanguageQueryName,
                                     kAlphaLanguageQueryValue);
   }
 
-  std::string message = base::StringPrintf(
-      "%s list fetch starts (URL: %s)",
-      include_alpha_languages_ ? "Language" : "Alpha language",
-      url.spec().c_str());
-  NotifyEvent(__LINE__, message);
-
-  fetcher_.reset(net::URLFetcher::Create(
-      include_alpha_languages_ ? kFetcherIdForAlphaLanguageList :
-                                 kFetcherIdForLanguageList,
-      url,
-      net::URLFetcher::GET,
-      this));
-  fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
-                         net::LOAD_DO_NOT_SAVE_COOKIES);
-  fetcher_->SetRequestContext(g_browser_process->system_request_context());
-  fetcher_->SetMaxRetriesOn5xx(kMaxRetryLanguageListFetch);
-  fetcher_->Start();
-
-  return true;
+  return url;
 }
 
-void TranslateLanguageList::LanguageListFetcher::OnURLFetchComplete(
-    const net::URLFetcher* source) {
-  DCHECK(fetcher_.get() == source);
-
-  std::string data;
-  if (source->GetStatus().status() == net::URLRequestStatus::SUCCESS &&
-      source->GetResponseCode() == net::HTTP_OK) {
-    state_ = COMPLETED;
-    source->GetResponseAsString(&data);
-    std::string message = base::StringPrintf(
-        "%s list is updated",
-        include_alpha_languages_ ? "Alpha language" : "Language");
-    NotifyEvent(__LINE__, message);
-  } else {
-    state_ = FAILED;
-    std::string message = base::StringPrintf(
-        "Failed to Fetch languages from: %s",
-        source->GetURL().spec().c_str());
-    NotifyEvent(__LINE__, message);
-  }
-
-  scoped_ptr<const net::URLFetcher> delete_ptr(fetcher_.release());
-  callback_.Run(include_alpha_languages_, state_ == COMPLETED, data);
-}
+}  // namespace
 
 // This must be kept in sync with the &cb= value in the kLanguageListFetchURL.
 const char TranslateLanguageList::kLanguageListCallbackName[] = "sl(";
@@ -277,8 +216,16 @@
     supported_languages_.insert(kDefaultSupportedLanguages[i]);
   UpdateSupportedLanguages();
 
-  language_list_fetcher_.reset(new LanguageListFetcher(false));
-  alpha_language_list_fetcher_.reset(new LanguageListFetcher(true));
+  if (update_is_disabled)
+    return;
+
+  language_list_fetcher_.reset(
+      new TranslateURLFetcher(kFetcherIdForLanguageList));
+  language_list_fetcher_->set_max_retry_on_5xx(kMaxRetryOn5xx);
+
+  alpha_language_list_fetcher_.reset(
+      new TranslateURLFetcher(kFetcherIdForAlphaLanguageList));
+  alpha_language_list_fetcher_->set_max_retry_on_5xx(kMaxRetryOn5xx);
 }
 
 TranslateLanguageList::~TranslateLanguageList() {
@@ -290,6 +237,11 @@
   std::set<std::string>::const_iterator iter = all_supported_languages_.begin();
   for (; iter != all_supported_languages_.end(); ++iter)
     languages->push_back(*iter);
+
+  // Update language lists if they are not updated after Chrome was launched
+  // for later requests.
+  if (language_list_fetcher_.get() || alpha_language_list_fetcher_.get())
+    RequestLanguageList();
 }
 
 std::string TranslateLanguageList::GetLanguageCode(
@@ -316,36 +268,89 @@
 }
 
 void TranslateLanguageList::RequestLanguageList() {
+  // If resource requests are not allowed, we'll get a callback when they are.
+  if (resource_request_allowed_notifier_.ResourceRequestsAllowed())
+    OnResourceRequestsAllowed();
+}
+
+void TranslateLanguageList::OnResourceRequestsAllowed() {
   if (language_list_fetcher_.get() &&
-      (language_list_fetcher_->state() == LanguageListFetcher::IDLE ||
-       language_list_fetcher_->state() == LanguageListFetcher::FAILED)) {
-    language_list_fetcher_->Request(
+      (language_list_fetcher_->state() == TranslateURLFetcher::IDLE ||
+       language_list_fetcher_->state() == TranslateURLFetcher::FAILED)) {
+    GURL url = GetLanguageListFetchURL(false);
+
+    std::string message = base::StringPrintf(
+        "Language list fetch starts (URL: %s)",
+        url.spec().c_str());
+    NotifyEvent(__LINE__, message);
+
+    bool result = language_list_fetcher_->Request(
+        url,
         base::Bind(&TranslateLanguageList::OnLanguageListFetchComplete,
                    base::Unretained(this)));
+    if (!result)
+      NotifyEvent(__LINE__, "Request is omitted due to retry limit");
   }
 
   if (alpha_language_list_fetcher_.get() &&
-      (alpha_language_list_fetcher_->state() == LanguageListFetcher::IDLE ||
-       alpha_language_list_fetcher_->state() == LanguageListFetcher::FAILED)) {
-    alpha_language_list_fetcher_->Request(
+      (alpha_language_list_fetcher_->state() == TranslateURLFetcher::IDLE ||
+       alpha_language_list_fetcher_->state() == TranslateURLFetcher::FAILED)) {
+    GURL url = GetLanguageListFetchURL(true);
+
+    std::string message = base::StringPrintf(
+        "Alpha language list fetch starts (URL: %s)",
+        url.spec().c_str());
+    NotifyEvent(__LINE__, message);
+
+    bool result = alpha_language_list_fetcher_->Request(
+        url,
         base::Bind(&TranslateLanguageList::OnLanguageListFetchComplete,
                    base::Unretained(this)));
+    if (!result)
+      NotifyEvent(__LINE__, "Request is omitted due to retry limit");
   }
 }
 
+// static
+void TranslateLanguageList::DisableUpdate() {
+  update_is_disabled = true;
+}
+
 void TranslateLanguageList::OnLanguageListFetchComplete(
-    bool include_alpha_languages,
+    int id,
     bool success,
     const std::string& data) {
-  if (!success)
+  if (!success) {
+    // Since it fails just now, omit to schedule resource requests if
+    // ResourceRequestAllowedNotifier think it's ready. Otherwise, a callback
+    // will be invoked later to request resources again.
+    // The TranslateURLFetcher has a limit for retried requests and aborts
+    // re-try not to invoke OnLanguageListFetchComplete anymore if it's asked to
+    // re-try too many times.
+    GURL url = GetLanguageListFetchURL(id == kFetcherIdForAlphaLanguageList);
+    std::string message = base::StringPrintf(
+        "Failed to Fetch languages from: %s", url.spec().c_str());
+    NotifyEvent(__LINE__, message);
     return;
+  }
 
-  if (!include_alpha_languages) {
-    SetSupportedLanguages(data, &supported_languages_);
-    language_list_fetcher_.reset();
-  } else {
-    SetSupportedLanguages(data, &supported_alpha_languages_);
-    alpha_language_list_fetcher_.reset();
+  std::string message = base::StringPrintf(
+      "%s list is updated",
+      id == kFetcherIdForLanguageList ? "Language" : "Alpha language");
+  NotifyEvent(__LINE__, message);
+
+  switch (id) {
+    case kFetcherIdForLanguageList:
+      SetSupportedLanguages(data, &supported_languages_);
+      language_list_fetcher_.reset();
+      break;
+    case kFetcherIdForAlphaLanguageList:
+      SetSupportedLanguages(data, &supported_alpha_languages_);
+      alpha_language_list_fetcher_.reset();
+      break;
+    default:
+      NOTREACHED();
+      break;
   }
   UpdateSupportedLanguages();
 
diff --git a/chrome/browser/translate/translate_language_list.h b/chrome/browser/translate/translate_language_list.h
index 4518eaf..a443817 100644
--- a/chrome/browser/translate/translate_language_list.h
+++ b/chrome/browser/translate/translate_language_list.h
@@ -9,20 +9,16 @@
 #include <string>
 #include <vector>
 
-#include "base/callback.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/time.h"
-#include "googleurl/src/gurl.h"
-#include "net/url_request/url_fetcher_delegate.h"
+#include "base/time/time.h"
+#include "chrome/browser/web_resource/resource_request_allowed_notifier.h"
 
-namespace net {
-class URLFetcher;
-}
+class TranslateURLFetcher;
 
 // The TranslateLanguageList class is responsible for maintaining the latest
 // supporting language list.
 // This class is defined to be owned only by TranslateManager.
-class TranslateLanguageList {
+class TranslateLanguageList : public ResourceRequestAllowedNotifier::Observer {
  public:
   TranslateLanguageList();
   virtual ~TranslateLanguageList();
@@ -47,68 +43,24 @@
   // alpha language.
   bool IsAlphaLanguage(const std::string& language);
 
-  // Fetches the language list from the translate server. It will not retry
-  // more than kMaxRetryLanguageListFetch times. Do nothing if the list is
-  // already updated.
+  // Fetches the language list from the translate server. It will retry
+  // automatically when a server return 5xx errors and retry count doesn't
+  // reach to limits.
   void RequestLanguageList();
 
+  // ResourceRequestAllowedNotifier::Observer implementation:
+  virtual void OnResourceRequestsAllowed() OVERRIDE;
+
+  // Disables the language list updater. This is used only for testing now.
+  static void DisableUpdate();
+
   // static const values shared with our browser tests.
   static const char kLanguageListCallbackName[];
   static const char kTargetLanguagesKey[];
 
  private:
-  // The LanguageListFetcher class implements a client to fetch a server
-  // supported language list. It also maintains the state to represent if the
-  // fetch is completed successfully to try again later.
-  class LanguageListFetcher : public net::URLFetcherDelegate {
-   public:
-    // Callback type for Request().
-    typedef base::Callback<void(bool, bool, const std::string&)> Callback;
-
-    // Represents internal state if the fetch is completed successfully.
-    enum State {
-      IDLE,        // No fetch request was issued.
-      REQUESTING,  // A fetch request was issued, but not finished yet.
-      COMPLETED,   // The last fetch request was finished successfully.
-      FAILED,      // The last fetch request was finished with a failure.
-    };
-
-    explicit LanguageListFetcher(bool include_alpha_languages);
-    virtual ~LanguageListFetcher();
-
-    // Requests to fetch a server supported language list. |callback| will be
-    // invoked when the function returns true, and the request is finished
-    // asynchronously.
-    // Returns false if the previous request is not finished, or the request
-    // is omitted due to retry limitation.
-    bool Request(const Callback& callback);
-
-    // Gets internal state.
-    State state() { return state_; }
-
-    // net::URLFetcherDelegate implementation:
-    virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
-
-   private:
-    // Represents if this instance should fetch a supported language list
-    // including alpha languages.
-    bool include_alpha_languages_;
-
-    // Internal state.
-    enum State state_;
-
-    // URLFetcher instance.
-    scoped_ptr<net::URLFetcher> fetcher_;
-
-    // Callback passed at Request(). It will be invoked when an asynchronous
-    // fetch operation is finished.
-    Callback callback_;
-
-    DISALLOW_COPY_AND_ASSIGN(LanguageListFetcher);
-  };
-
-  // Callback function called when LanguageListFetcher::Request() is finished.
-  void OnLanguageListFetchComplete(bool include_alpha_languages,
+  // Callback function called when TranslateURLFetcher::Request() is finished.
+  void OnLanguageListFetchComplete(int id,
                                    bool success,
                                    const std::string& data);
 
@@ -128,15 +80,18 @@
 
   // A LanguageListFetcher instance to fetch a server providing supported
   // language list.
-  scoped_ptr<LanguageListFetcher> language_list_fetcher_;
+  scoped_ptr<TranslateURLFetcher> language_list_fetcher_;
 
   // A LanguageListFetcher instance to fetch a server providing supported alpha
   // language list.
-  scoped_ptr<LanguageListFetcher> alpha_language_list_fetcher_;
+  scoped_ptr<TranslateURLFetcher> alpha_language_list_fetcher_;
 
   // The last-updated time when the language list is sent.
   base::Time last_updated_;
 
+  // Helper class to know if it's allowed to make network resource requests.
+  ResourceRequestAllowedNotifier resource_request_allowed_notifier_;
+
   DISALLOW_COPY_AND_ASSIGN(TranslateLanguageList);
 };
 
diff --git a/chrome/browser/translate/translate_manager.cc b/chrome/browser/translate/translate_manager.cc
index 8a2d93a..f071e4c 100644
--- a/chrome/browser/translate/translate_manager.cc
+++ b/chrome/browser/translate/translate_manager.cc
@@ -8,13 +8,12 @@
 #include "base/command_line.h"
 #include "base/compiler_specific.h"
 #include "base/memory/singleton.h"
-#include "base/message_loop.h"
 #include "base/metrics/histogram.h"
 #include "base/prefs/pref_service.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/infobars/infobar_service.h"
@@ -29,6 +28,7 @@
 #include "chrome/browser/translate/translate_infobar_delegate.h"
 #include "chrome/browser/translate/translate_language_list.h"
 #include "chrome/browser/translate/translate_prefs.h"
+#include "chrome/browser/translate/translate_script.h"
 #include "chrome/browser/translate/translate_tab_helper.h"
 #include "chrome/browser/translate/translate_url_util.h"
 #include "chrome/browser/ui/browser.h"
@@ -52,16 +52,10 @@
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
-#include "google_apis/google_api_keys.h"
-#include "grit/browser_resources.h"
-#include "net/base/escape.h"
 #include "net/base/load_flags.h"
 #include "net/base/url_util.h"
 #include "net/http/http_status_code.h"
-#include "net/url_request/url_fetcher.h"
-#include "net/url_request/url_request_status.h"
 #include "ui/base/l10n/l10n_util.h"
-#include "ui/base/resource/resource_bundle.h"
 
 #ifdef FILE_MANAGER_EXTENSION
 #include "chrome/browser/chromeos/extensions/file_manager/file_manager_util.h"
@@ -74,17 +68,9 @@
 
 namespace {
 
-const char kTranslateScriptURL[] =
-    "https://translate.google.com/translate_a/element.js";
-const char kTranslateScriptHeader[] = "Google-Translate-Element-Mode: library";
 const char kReportLanguageDetectionErrorURL[] =
     "https://translate.google.com/translate_error?client=cr&action=langidc";
 
-// Used in kTranslateScriptURL to specify a callback function name.
-const char kCallbackQueryName[] = "cb";
-const char kCallbackQueryValue[] =
-    "cr.googleTranslate.onTranslateElementLoad";
-
 // Used in kReportLanguageDetectionErrorURL to specify the original page
 // language.
 const char kSourceLanguageQueryName[] = "sl";
@@ -100,8 +86,6 @@
 // loading before giving up the translation
 const int kMaxTranslateLoadCheckAttempts = 20;
 
-const int kTranslateScriptExpirationDelayDays = 1;
-
 }  // namespace
 
 TranslateManager::~TranslateManager() {
@@ -187,6 +171,14 @@
   return false;
 }
 
+void TranslateManager::SetTranslateScriptExpirationDelay(int delay_ms) {
+  if (script_.get() == NULL) {
+    NOTREACHED();
+    return;
+  }
+  script_->set_expiration_delay(delay_ms);
+}
+
 void TranslateManager::Observe(int type,
                                const content::NotificationSource& source,
                                const content::NotificationDetails& details) {
@@ -284,89 +276,6 @@
   }
 }
 
-void TranslateManager::OnURLFetchComplete(const net::URLFetcher* source) {
-  if (translate_script_request_pending_.get() != source) {
-    // Looks like crash on Mac is possibly caused with callback entering here
-    // with unknown fetcher when network is refreshed.
-    scoped_ptr<const net::URLFetcher> delete_ptr(source);
-    return;
-  }
-
-  bool error =
-      source->GetStatus().status() != net::URLRequestStatus::SUCCESS ||
-      source->GetResponseCode() != net::HTTP_OK;
-  if (translate_script_request_pending_.get() == source) {
-    scoped_ptr<const net::URLFetcher> delete_ptr(
-        translate_script_request_pending_.release());
-    if (!error) {
-      base::StringPiece str = ResourceBundle::GetSharedInstance().
-          GetRawDataResource(IDR_TRANSLATE_JS);
-      DCHECK(translate_script_.empty());
-      str.CopyToString(&translate_script_);
-      std::string argument = "('";
-      std::string api_key = google_apis::GetAPIKey();
-      argument += net::EscapeQueryParamValue(api_key, true);
-      argument += "');\n";
-      std::string data;
-      source->GetResponseAsString(&data);
-      translate_script_ += argument + data;
-
-      // We'll expire the cached script after some time, to make sure long
-      // running browsers still get fixes that might get pushed with newer
-      // scripts.
-      base::MessageLoop::current()->PostDelayedTask(FROM_HERE,
-          base::Bind(&TranslateManager::ClearTranslateScript,
-                     weak_method_factory_.GetWeakPtr()),
-          translate_script_expiration_delay_);
-    }
-    // Process any pending requests.
-    std::vector<PendingRequest>::const_iterator iter;
-    for (iter = pending_requests_.begin(); iter != pending_requests_.end();
-         ++iter) {
-      const PendingRequest& request = *iter;
-      WebContents* web_contents =
-          tab_util::GetWebContentsByID(request.render_process_id,
-                                       request.render_view_id);
-      if (!web_contents) {
-        // The tab went away while we were retrieving the script.
-        continue;
-      }
-      NavigationEntry* entry = web_contents->GetController().GetActiveEntry();
-      if (!entry || entry->GetPageID() != request.page_id) {
-        // We navigated away from the page the translation was triggered on.
-        continue;
-      }
-
-      if (error) {
-        Profile* profile =
-            Profile::FromBrowserContext(web_contents->GetBrowserContext());
-        TranslateInfoBarDelegate::Create(
-            InfoBarService::FromWebContents(web_contents),
-            true,
-            TranslateInfoBarDelegate::TRANSLATION_ERROR,
-            TranslateErrors::NETWORK,
-            profile->GetPrefs(),
-            ShortcutConfig(),
-            request.source_lang,
-            request.target_lang);
-
-        if (!web_contents->GetBrowserContext()->IsOffTheRecord()) {
-          TranslateErrorDetails error_details;
-          error_details.time = base::Time::Now();
-          error_details.url = entry->GetURL();
-          error_details.error = TranslateErrors::NETWORK;
-          NotifyTranslateError(error_details);
-        }
-      } else {
-        // Translate the page.
-        DoTranslatePage(web_contents, translate_script_,
-                        request.source_lang, request.target_lang);
-      }
-    }
-    pending_requests_.clear();
-  }
-}
-
 void TranslateManager::AddObserver(Observer* obs) {
   observer_list_.AddObserver(obs);
 }
@@ -392,8 +301,6 @@
 
 TranslateManager::TranslateManager()
   : weak_method_factory_(this),
-    translate_script_expiration_delay_(base::TimeDelta::FromDays(
-        kTranslateScriptExpirationDelayDays)),
     max_reload_check_attempts_(kMaxTranslateLoadCheckAttempts) {
   notification_registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
                               content::NotificationService::AllSources());
@@ -404,6 +311,7 @@
                               content::NotificationService::AllSources());
   language_list_.reset(new TranslateLanguageList);
   accept_languages_.reset(new TranslateAcceptLanguages);
+  script_.reset(new TranslateScript);
 }
 
 void TranslateManager::InitiateTranslation(WebContents* web_contents,
@@ -438,17 +346,18 @@
     return;
   }
 
-  // Don't translate similar languages (ex: en-US to en).
   std::string target_lang = GetTargetLanguage(prefs);
   std::string language_code = GetLanguageCode(page_lang);
+
+  CommandLine* command_line = CommandLine::ForCurrentProcess();
+
+  // Don't translate similar languages (ex: en-US to en).
   if (language_code == target_lang) {
     TranslateBrowserMetrics::ReportInitiationStatus(
         TranslateBrowserMetrics::INITIATION_STATUS_SIMILAR_LANGUAGES);
     return;
   }
 
-  CommandLine* command_line = CommandLine::ForCurrentProcess();
-
   // Don't translate any language the user configured as accepted languages.
   // When the flag --enable-translate-settings is on, the condition is
   // different. In this case, even though a language is an Accept language,
@@ -586,8 +495,11 @@
       TranslateInfoBarDelegate::TRANSLATING, TranslateErrors::NONE,
       profile->GetPrefs(), ShortcutConfig(), source_lang, target_lang);
 
-  if (!translate_script_.empty()) {
-    DoTranslatePage(web_contents, translate_script_, source_lang, target_lang);
+  DCHECK(script_.get() != NULL);
+
+  const std::string& translate_script = script_->data();
+  if (!translate_script.empty()) {
+    DoTranslatePage(web_contents, translate_script, source_lang, target_lang);
     return;
   }
 
@@ -601,7 +513,13 @@
   request.source_lang = source_lang;
   request.target_lang = target_lang;
   pending_requests_.push_back(request);
-  RequestTranslateScript();
+
+  if (script_->HasPendingRequest())
+    return;
+
+  script_->Request(
+      base::Bind(&TranslateManager::OnTranslateScriptFetchComplete,
+                 base::Unretained(this)));
 }
 
 void TranslateManager::RevertTranslation(WebContents* web_contents) {
@@ -650,6 +568,14 @@
                                 content::PAGE_TRANSITION_AUTO_BOOKMARK);
 }
 
+void TranslateManager::ClearTranslateScript() {
+  if (script_.get() == NULL) {
+    NOTREACHED();
+    return;
+  }
+  script_->Clear();
+}
+
 void TranslateManager::DoTranslatePage(WebContents* web_contents,
                                        const std::string& translate_script,
                                        const std::string& source_lang,
@@ -718,51 +644,56 @@
 
 void TranslateManager::CleanupPendingUlrFetcher() {
   language_list_.reset();
-  translate_script_request_pending_.reset();
+  script_.reset();
 }
 
-void TranslateManager::RequestTranslateScript() {
-  if (translate_script_request_pending_.get() != NULL)
-    return;
+void TranslateManager::OnTranslateScriptFetchComplete(
+    bool success, const std::string& data) {
+  std::vector<PendingRequest>::const_iterator iter;
+  for (iter = pending_requests_.begin(); iter != pending_requests_.end();
+       ++iter) {
+    const PendingRequest& request = *iter;
+    WebContents* web_contents =
+        tab_util::GetWebContentsByID(request.render_process_id,
+                                     request.render_view_id);
+    if (!web_contents) {
+      // The tab went away while we were retrieving the script.
+      continue;
+    }
+    NavigationEntry* entry = web_contents->GetController().GetActiveEntry();
+    if (!entry || entry->GetPageID() != request.page_id) {
+      // We navigated away from the page the translation was triggered on.
+      continue;
+    }
 
-  GURL translate_script_url;
-  // Check if command-line contains an alternative URL for translate service.
-  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
-  if (command_line.HasSwitch(switches::kTranslateScriptURL)) {
-    translate_script_url = GURL(
-        command_line.GetSwitchValueASCII(switches::kTranslateScriptURL));
-    if (!translate_script_url.is_valid() ||
-        !translate_script_url.query().empty()) {
-      LOG(WARNING) << "The following translate URL specified at the "
-                   << "command-line is invalid: "
-                   << translate_script_url.spec();
-      translate_script_url = GURL();
+    if (success) {
+      // Translate the page.
+      const std::string& translate_script = script_->data();
+      DoTranslatePage(web_contents, translate_script,
+                      request.source_lang, request.target_lang);
+    } else {
+      Profile* profile =
+          Profile::FromBrowserContext(web_contents->GetBrowserContext());
+      TranslateInfoBarDelegate::Create(
+          InfoBarService::FromWebContents(web_contents),
+          true,
+          TranslateInfoBarDelegate::TRANSLATION_ERROR,
+          TranslateErrors::NETWORK,
+          profile->GetPrefs(),
+          ShortcutConfig(),
+          request.source_lang,
+          request.target_lang);
+
+      if (!web_contents->GetBrowserContext()->IsOffTheRecord()) {
+        TranslateErrorDetails error_details;
+        error_details.time = base::Time::Now();
+        error_details.url = entry->GetURL();
+        error_details.error = TranslateErrors::NETWORK;
+        NotifyTranslateError(error_details);
+      }
     }
   }
-  // Use default URL when command-line argument is not specified, or specified
-  // URL is invalid.
-  if (translate_script_url.is_empty())
-    translate_script_url = GURL(kTranslateScriptURL);
-
-  translate_script_url = net::AppendQueryParameter(
-      translate_script_url,
-      kCallbackQueryName,
-      kCallbackQueryValue);
-
-  translate_script_url =
-      TranslateURLUtil::AddHostLocaleToUrl(translate_script_url);
-  translate_script_url =
-      TranslateURLUtil::AddApiKeyToUrl(translate_script_url);
-
-  translate_script_request_pending_.reset(net::URLFetcher::Create(
-      0, translate_script_url, net::URLFetcher::GET, this));
-  translate_script_request_pending_->SetLoadFlags(
-      net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES);
-  translate_script_request_pending_->SetRequestContext(
-      g_browser_process->system_request_context());
-  translate_script_request_pending_->SetExtraRequestHeaders(
-      kTranslateScriptHeader);
-  translate_script_request_pending_->Start();
+  pending_requests_.clear();
 }
 
 // static
diff --git a/chrome/browser/translate/translate_manager.h b/chrome/browser/translate/translate_manager.h
index b00f444..8355ab1 100644
--- a/chrome/browser/translate/translate_manager.h
+++ b/chrome/browser/translate/translate_manager.h
@@ -13,11 +13,10 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/common/translate/translate_errors.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
-#include "net/url_request/url_fetcher_delegate.h"
 
 template <typename T> struct DefaultSingletonTraits;
 class GURL;
@@ -31,6 +30,7 @@
 struct TranslateEventDetails;
 class TranslateInfoBarDelegate;
 class TranslateLanguageList;
+class TranslateScript;
 
 namespace content {
 class WebContents;
@@ -45,8 +45,7 @@
 // page translation the user requests.
 // It is a singleton.
 
-class TranslateManager : public content::NotificationObserver,
-                         public net::URLFetcherDelegate {
+class TranslateManager : public content::NotificationObserver {
  public:
   // Returns the singleton instance.
   static TranslateManager* GetInstance();
@@ -78,6 +77,14 @@
   // Returns true if |language| is an Accept language for the user profile.
   static bool IsAcceptLanguage(Profile* profile, const std::string& language);
 
+  // Returns the language to translate to. The language returned is the
+  // first language found in the following list that is supported by the
+  // translation service:
+  //     the UI language
+  //     the accept-language list
+  // If no language is found then an empty string is returned.
+  static std::string GetTargetLanguage(PrefService* prefs);
+
   // Let the caller decide if and when we should fetch the language list from
   // the translate server. This is a NOOP if switches::kDisableTranslate is set
   // or if prefs::kEnableTranslate is set to false.
@@ -104,23 +111,17 @@
   void ReportLanguageDetectionError(content::WebContents* web_contents);
 
   // Clears the translate script, so it will be fetched next time we translate.
-  void ClearTranslateScript() { translate_script_.clear(); }
+  void ClearTranslateScript();
 
   // content::NotificationObserver implementation:
   virtual void Observe(int type,
                        const content::NotificationSource& source,
                        const content::NotificationDetails& details) OVERRIDE;
 
-  // net::URLFetcherDelegate implementation:
-  virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
-
   // Used by unit-tests to override some defaults:
   // Delay after which the translate script is fetched again from the
   // translation server.
-  void set_translate_script_expiration_delay(int delay_ms) {
-    translate_script_expiration_delay_ =
-        base::TimeDelta::FromMilliseconds(delay_ms);
-  }
+  void SetTranslateScriptExpirationDelay(int delay_ms);
 
   // Number of attempts before waiting for a page to be fully reloaded.
   void set_translate_max_reload_attemps(int attempts) {
@@ -182,9 +183,7 @@
   void PageTranslated(content::WebContents* web_contents,
                       PageTranslatedDetails* details);
 
-  // Fetches the JS translate script (the script that is injected in the page
-  // to translate it).
-  void RequestTranslateScript();
+  void OnTranslateScriptFetchComplete(bool success, const std::string& data);
 
   // Notifies to the observers when a language is detected.
   void NotifyLanguageDetection(const LanguageDetectionDetails& details);
@@ -192,14 +191,6 @@
   // Notifies to the observers when translate failed.
   void NotifyTranslateError(const TranslateErrorDetails& details);
 
-  // Returns the language to translate to. The language returned is the
-  // first language found in the following list that is supported by the
-  // translation service:
-  //     the UI language
-  //     the accept-language list
-  // If no language is found then an empty string is returned.
-  static std::string GetTargetLanguage(PrefService* prefs);
-
   // Returns the different parameters used to decide whether extra shortcuts
   // are needed.
   static ShortcutConfiguration ShortcutConfig();
@@ -208,19 +199,9 @@
 
   base::WeakPtrFactory<TranslateManager> weak_method_factory_;
 
-  // The JS injected in the page to do the translation.
-  std::string translate_script_;
-
-  // Delay after which the translate script is fetched again
-  // from the translate server.
-  base::TimeDelta translate_script_expiration_delay_;
-
   // Max number of attempts before checking if a page has been reloaded.
   int max_reload_check_attempts_;
 
-  // Set when the translate JS is currently being retrieved. NULL otherwise.
-  scoped_ptr<net::URLFetcher> translate_script_request_pending_;
-
   // The list of pending translate requests.  Translate requests are queued when
   // the translate script is not ready and has to be fetched from the translate
   // server.
@@ -232,6 +213,10 @@
   // An instance of TranslateLanguageList which manages supported language list.
   scoped_ptr<TranslateLanguageList> language_list_;
 
+  // An instance of TranslateScript which manages JavaScript source for
+  // Translate.
+  scoped_ptr<TranslateScript> script_;
+
   // An instance of TranslateAcceptLanguages which manages Accept languages of
   // each profiles.
   scoped_ptr<TranslateAcceptLanguages> accept_languages_;
diff --git a/chrome/browser/translate/translate_manager_browsertest.cc b/chrome/browser/translate/translate_manager_browsertest.cc
index 5de2bb8..d38b409 100644
--- a/chrome/browser/translate/translate_manager_browsertest.cc
+++ b/chrome/browser/translate/translate_manager_browsertest.cc
@@ -49,6 +49,7 @@
 #include "grit/generated_resources.h"
 #include "ipc/ipc_test_sink.h"
 #include "net/url_request/test_url_fetcher_factory.h"
+#include "net/url_request/url_fetcher_delegate.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "third_party/WebKit/public/web/WebContextMenuData.h"
 #include "third_party/WebKit/public/web/WebKit.h"
@@ -180,7 +181,7 @@
   }
 
   void ExpireTranslateScriptImmediately() {
-    TranslateManager::GetInstance()->set_translate_script_expiration_delay(0);
+    TranslateManager::GetInstance()->SetTranslateScriptExpirationDelay(0);
   }
 
   // If there is 1 infobar and it is a translate infobar, deny translation and
@@ -235,7 +236,7 @@
     // case it was zeroed in a previous test).
     TranslateManager::GetInstance()->ClearTranslateScript();
     TranslateManager::GetInstance()->
-        set_translate_script_expiration_delay(60 * 60 * 1000);
+        SetTranslateScriptExpirationDelay(60 * 60 * 1000);
     TranslateManager::GetInstance()->set_translate_max_reload_attemps(0);
 
     ChromeRenderViewHostTestHarness::SetUp();
@@ -632,17 +633,13 @@
   server_languages.push_back("fr-FR");
   server_languages.push_back("xx");
 
-  // First, get the default languages list:
+  // First, get the default languages list. Note that calling
+  // GetSupportedLanguages() invokes RequestLanguageList() internally.
   std::vector<std::string> default_supported_languages;
   TranslateManager::GetSupportedLanguages(&default_supported_languages);
   // To make sure we got the defaults and don't confuse them with the mocks.
   ASSERT_NE(default_supported_languages.size(), server_languages.size());
 
-  Profile* profile =
-      Profile::FromBrowserContext(web_contents()->GetBrowserContext());
-  PrefService* prefs = profile->GetPrefs();
-  TranslateManager::GetInstance()->FetchLanguageListFromTranslateServer(prefs);
-
   // Check that we still get the defaults until the URLFetch has completed.
   std::vector<std::string> current_supported_languages;
   TranslateManager::GetSupportedLanguages(&current_supported_languages);
@@ -655,7 +652,6 @@
   EXPECT_EQ(default_supported_languages, current_supported_languages);
 
   // Now check that we got the appropriate set of languages from the server.
-  TranslateManager::GetInstance()->FetchLanguageListFromTranslateServer(prefs);
   SimulateSupportedLanguagesURLFetch(true, server_languages);
   current_supported_languages.clear();
   TranslateManager::GetSupportedLanguages(&current_supported_languages);
@@ -1089,11 +1085,11 @@
   registrar.Add(TranslatePrefs::kPrefTranslateLanguageBlacklist,
                 pref_callback_);
   TranslatePrefs translate_prefs(prefs);
-  EXPECT_FALSE(translate_prefs.IsLanguageBlacklisted("fr"));
+  EXPECT_FALSE(translate_prefs.IsBlockedLanguage("fr"));
   EXPECT_TRUE(translate_prefs.CanTranslateLanguage(profile, "fr"));
   SetPrefObserverExpectation(TranslatePrefs::kPrefTranslateLanguageBlacklist);
-  translate_prefs.BlacklistLanguage("fr");
-  EXPECT_TRUE(translate_prefs.IsLanguageBlacklisted("fr"));
+  translate_prefs.BlockLanguage("fr");
+  EXPECT_TRUE(translate_prefs.IsBlockedLanguage("fr"));
   EXPECT_FALSE(translate_prefs.IsSiteBlacklisted(url.host()));
   EXPECT_FALSE(translate_prefs.CanTranslateLanguage(profile, "fr"));
 
@@ -1108,8 +1104,8 @@
 
   // Remove the language from the blacklist.
   SetPrefObserverExpectation(TranslatePrefs::kPrefTranslateLanguageBlacklist);
-  translate_prefs.RemoveLanguageFromBlacklist("fr");
-  EXPECT_FALSE(translate_prefs.IsLanguageBlacklisted("fr"));
+  translate_prefs.UnblockLanguage("fr");
+  EXPECT_FALSE(translate_prefs.IsBlockedLanguage("fr"));
   EXPECT_FALSE(translate_prefs.IsSiteBlacklisted(url.host()));
   EXPECT_TRUE(translate_prefs.CanTranslateLanguage(profile, "fr"));
 
@@ -1234,9 +1230,9 @@
   Profile* profile =
       Profile::FromBrowserContext(web_contents()->GetBrowserContext());
   TranslatePrefs translate_prefs(profile->GetPrefs());
-  translate_prefs.BlacklistLanguage("fr");
+  translate_prefs.BlockLanguage("fr");
   translate_prefs.BlacklistSite(url.host());
-  EXPECT_TRUE(translate_prefs.IsLanguageBlacklisted("fr"));
+  EXPECT_TRUE(translate_prefs.IsBlockedLanguage("fr"));
   EXPECT_TRUE(translate_prefs.IsSiteBlacklisted(url.host()));
 
   // Simulate navigating to a page in French. The translate menu should show but
@@ -1273,7 +1269,7 @@
   process()->sink().ClearMessages();
 
   // This should also have reverted the blacklisting of this site and language.
-  EXPECT_FALSE(translate_prefs.IsLanguageBlacklisted("fr"));
+  EXPECT_FALSE(translate_prefs.IsBlockedLanguage("fr"));
   EXPECT_FALSE(translate_prefs.IsSiteBlacklisted(url.host()));
 
   // Let's simulate the page being translated.
@@ -1413,7 +1409,7 @@
   }
   // Simulate the user pressing "Never translate French".
   infobar->NeverTranslatePageLanguage();
-  EXPECT_TRUE(translate_prefs.IsLanguageBlacklisted("de"));
+  EXPECT_TRUE(translate_prefs.IsBlockedLanguage("de"));
   // No translation should have occured and the infobar should be gone.
   EXPECT_FALSE(GetTranslateMessage(&page_id, &original_lang, &target_lang));
   process()->sink().ClearMessages();
diff --git a/chrome/browser/translate/translate_manager_unittest.cc b/chrome/browser/translate/translate_manager_unittest.cc
index 6b176a1..9073b3a 100644
--- a/chrome/browser/translate/translate_manager_unittest.cc
+++ b/chrome/browser/translate/translate_manager_unittest.cc
@@ -5,8 +5,8 @@
 #include "chrome/browser/translate/translate_manager.h"
 
 #include "content/public/common/url_constants.h"
-#include "googleurl/src/gurl.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 #ifdef FILE_MANAGER_EXTENSION
 #include "chrome/browser/chromeos/extensions/file_manager/file_manager_util.h"
diff --git a/chrome/browser/translate/translate_prefs.cc b/chrome/browser/translate/translate_prefs.cc
index ccb2790..8ec9736 100644
--- a/chrome/browser/translate/translate_prefs.cc
+++ b/chrome/browser/translate/translate_prefs.cc
@@ -27,6 +27,25 @@
     "translate_denied_count";
 const char TranslatePrefs::kPrefTranslateAcceptedCount[] =
     "translate_accepted_count";
+const char TranslatePrefs::kPrefTranslateBlockedLanguages[] =
+    "translate_blocked_languages";
+
+namespace {
+
+void GetBlacklistedLanguages(const PrefService* prefs,
+                             std::vector<std::string>* languages) {
+  DCHECK(languages->empty());
+
+  const char* key = TranslatePrefs::kPrefTranslateLanguageBlacklist;
+  const ListValue* list = prefs->GetList(key);
+  for (ListValue::const_iterator it = list->begin(); it != list->end(); ++it) {
+    std::string lang;
+    (*it)->GetAsString(&lang);
+    languages->push_back(lang);
+  }
+}
+
+}  // namespace
 
 namespace {
 
@@ -58,21 +77,45 @@
     : prefs_(user_prefs) {
 }
 
-bool TranslatePrefs::IsLanguageBlacklisted(
+bool TranslatePrefs::IsBlockedLanguage(
     const std::string& original_language) const {
-  return IsValueBlacklisted(kPrefTranslateLanguageBlacklist, original_language);
-}
-
-void TranslatePrefs::BlacklistLanguage(const std::string& original_language) {
-  BlacklistValue(kPrefTranslateLanguageBlacklist, original_language);
   CommandLine* command_line = CommandLine::ForCurrentProcess();
-  if (command_line->HasSwitch(switches::kEnableTranslateSettings))
-    AppendLanguageToAcceptLanguages(prefs_, original_language);
+  if (command_line->HasSwitch(switches::kEnableTranslateSettings)) {
+    return IsValueBlacklisted(kPrefTranslateBlockedLanguages,
+                              original_language);
+  } else {
+    return IsValueBlacklisted(kPrefTranslateLanguageBlacklist,
+                              original_language);
+  }
 }
 
-void TranslatePrefs::RemoveLanguageFromBlacklist(
+void TranslatePrefs::BlockLanguage(
     const std::string& original_language) {
-  RemoveValueFromBlacklist(kPrefTranslateLanguageBlacklist, original_language);
+  CommandLine* command_line = CommandLine::ForCurrentProcess();
+  if (command_line->HasSwitch(switches::kEnableTranslateSettings)) {
+    BlacklistValue(kPrefTranslateBlockedLanguages, original_language);
+    AppendLanguageToAcceptLanguages(prefs_, original_language);
+  } else {
+    BlacklistValue(kPrefTranslateLanguageBlacklist, original_language);
+  }
+}
+
+void TranslatePrefs::UnblockLanguage(
+    const std::string& original_language) {
+  CommandLine* command_line = CommandLine::ForCurrentProcess();
+  if (command_line->HasSwitch(switches::kEnableTranslateSettings)) {
+    RemoveValueFromBlacklist(kPrefTranslateBlockedLanguages,
+                             original_language);
+  } else {
+    RemoveValueFromBlacklist(kPrefTranslateLanguageBlacklist,
+                             original_language);
+  }
+}
+
+void TranslatePrefs::RemoveLanguageFromLegacyBlacklist(
+    const std::string& original_language) {
+  RemoveValueFromBlacklist(kPrefTranslateLanguageBlacklist,
+                           original_language);
 }
 
 bool TranslatePrefs::IsSiteBlacklisted(const std::string& site) const {
@@ -125,11 +168,19 @@
 }
 
 bool TranslatePrefs::HasBlacklistedLanguages() const {
-  return !IsListEmpty(kPrefTranslateLanguageBlacklist);
+  CommandLine* command_line = CommandLine::ForCurrentProcess();
+  if (command_line->HasSwitch(switches::kEnableTranslateSettings))
+    return !IsListEmpty(kPrefTranslateBlockedLanguages);
+  else
+    return !IsListEmpty(kPrefTranslateLanguageBlacklist);
 }
 
 void TranslatePrefs::ClearBlacklistedLanguages() {
-  prefs_->ClearPref(kPrefTranslateLanguageBlacklist);
+  CommandLine* command_line = CommandLine::ForCurrentProcess();
+  if (command_line->HasSwitch(switches::kEnableTranslateSettings))
+    prefs_->ClearPref(kPrefTranslateBlockedLanguages);
+  else
+    prefs_->ClearPref(kPrefTranslateLanguageBlacklist);
 }
 
 bool TranslatePrefs::HasBlacklistedSites() const {
@@ -199,7 +250,7 @@
 bool TranslatePrefs::CanTranslateLanguage(Profile* profile,
                                           const std::string& language) {
   TranslatePrefs translate_prefs(profile->GetPrefs());
-  bool blacklisted = translate_prefs.IsLanguageBlacklisted(language);
+  bool blocked = translate_prefs.IsBlockedLanguage(language);
 
   CommandLine* command_line = CommandLine::ForCurrentProcess();
   if (command_line->HasSwitch(switches::kEnableTranslateSettings)) {
@@ -215,11 +266,11 @@
     // is also necessary because some minor languages can't be selected in the
     // language preference even though the language is available in Translate
     // server.
-    if (blacklisted && (is_accept_language || !can_be_accept_language))
+    if (blocked && (is_accept_language || !can_be_accept_language))
       return false;
   } else {
     // Don't translate any user user selected language.
-    if (blacklisted)
+    if (blocked)
       return false;
   }
 
@@ -249,6 +300,8 @@
   registry->RegisterDictionaryPref(
       kPrefTranslateAcceptedCount,
       user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
+  registry->RegisterListPref(kPrefTranslateBlockedLanguages,
+                             user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
 }
 
 // static
@@ -271,28 +324,113 @@
   //   keep auto-translated.
   DictionaryPrefUpdate update(user_prefs, kPrefTranslateWhitelists);
   DictionaryValue* dict = update.Get();
-  if (!dict || dict->empty())
-    return;
-  DictionaryValue::Iterator iter(*dict);
-  while (!iter.IsAtEnd()) {
-    const ListValue* list = NULL;
-    if (!iter.value().GetAsList(&list) || !list)
-      break;  // Dictionary has either been migrated or new format.
-    std::string key = iter.key();
-    // Advance the iterator before removing the current element.
-    iter.Advance();
-    std::string target_lang;
-    if (list->empty() || !list->GetString(list->GetSize() - 1, &target_lang) ||
-        target_lang.empty()) {
-      dict->Remove(key, NULL);
-    } else {
-      dict->SetString(key, target_lang);
+  if (dict && !dict->empty()) {
+    DictionaryValue::Iterator iter(*dict);
+    while (!iter.IsAtEnd()) {
+      const ListValue* list = NULL;
+      if (!iter.value().GetAsList(&list) || !list)
+        break;  // Dictionary has either been migrated or new format.
+      std::string key = iter.key();
+      // Advance the iterator before removing the current element.
+      iter.Advance();
+      std::string target_lang;
+      if (list->empty() ||
+          !list->GetString(list->GetSize() - 1, &target_lang) ||
+          target_lang.empty()) {
+        dict->Remove(key, NULL);
+      } else {
+        dict->SetString(key, target_lang);
+      }
     }
   }
+
+  // Get the union of the blacklist and the Accept languages, and set this to
+  // the new language set 'translate_blocked_languages'. This is used for the
+  // settings UI for Translate and configration to determine which langauage
+  // should be translated instead of the blacklist. The blacklist is no longer
+  // used after launching the settings UI.
+  // After that, Set 'translate_languages_not_translate' to Accept languages to
+  // enable settings for users.
+  bool merged = user_prefs->HasPrefPath(kPrefTranslateBlockedLanguages);
+
+  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+  bool enabled_translate_settings =
+      command_line.HasSwitch(switches::kEnableTranslateSettings);
+
+  if (!merged && enabled_translate_settings) {
+    std::vector<std::string> blacklisted_languages;
+    GetBlacklistedLanguages(user_prefs, &blacklisted_languages);
+
+    std::string accept_languages_str =
+        user_prefs->GetString(prefs::kAcceptLanguages);
+    std::vector<std::string> accept_languages;
+    base::SplitString(accept_languages_str, ',', &accept_languages);
+
+    std::vector<std::string> blocked_languages;
+    CreateBlockedLanguages(&blocked_languages,
+                           blacklisted_languages,
+                           accept_languages);
+
+    // Create the new preference kPrefTranslateBlockedLanguages.
+    {
+      ListValue* blocked_languages_list = new ListValue();
+      for (std::vector<std::string>::const_iterator it =
+               blocked_languages.begin();
+           it != blocked_languages.end(); ++it) {
+        blocked_languages_list->Append(new StringValue(*it));
+      }
+      ListPrefUpdate update(user_prefs, kPrefTranslateBlockedLanguages);
+      ListValue* list = update.Get();
+      DCHECK(list != NULL);
+      list->Swap(blocked_languages_list);
+    }
+
+    // Update kAcceptLanguages
+    for (std::vector<std::string>::const_iterator it =
+             blocked_languages.begin();
+         it != blocked_languages.end(); ++it) {
+      std::string lang = *it;
+      TranslateUtil::ToChromeLanguageSynonym(&lang);
+      bool not_found =
+          std::find(accept_languages.begin(), accept_languages.end(), lang) ==
+          accept_languages.end();
+      if (not_found)
+        accept_languages.push_back(lang);
+    }
+
+    std::string new_accept_languages_str = JoinString(accept_languages, ",");
+    user_prefs->SetString(prefs::kAcceptLanguages, new_accept_languages_str);
+  }
 }
 
 // TranslatePrefs: private: ----------------------------------------------------
 
+// static
+void TranslatePrefs::CreateBlockedLanguages(
+    std::vector<std::string>* blocked_languages,
+    const std::vector<std::string>& blacklisted_languages,
+    const std::vector<std::string>& accept_languages) {
+  DCHECK(blocked_languages->empty());
+
+  std::set<std::string> result;
+
+  for (std::vector<std::string>::const_iterator it =
+           blacklisted_languages.begin();
+       it != blacklisted_languages.end(); ++it) {
+    result.insert(*it);
+  }
+
+  for (std::vector<std::string>::const_iterator it = accept_languages.begin();
+       it != accept_languages.end(); ++it) {
+    std::string lang = *it;
+    TranslateUtil::ToTranslateLanguageSynonym(&lang);
+    result.insert(lang);
+  }
+
+  blocked_languages->insert(blocked_languages->begin(),
+                            result.begin(), result.end());
+}
+
 bool TranslatePrefs::IsValueInList(const ListValue* list,
     const std::string& in_value) const {
   for (size_t i = 0; i < list->GetSize(); ++i) {
diff --git a/chrome/browser/translate/translate_prefs.h b/chrome/browser/translate/translate_prefs.h
index d049b05..f1ce6d4 100644
--- a/chrome/browser/translate/translate_prefs.h
+++ b/chrome/browser/translate/translate_prefs.h
@@ -6,8 +6,10 @@
 #define CHROME_BROWSER_TRANSLATE_TRANSLATE_PREFS_H_
 
 #include <string>
+#include <vector>
 
-#include "googleurl/src/gurl.h"
+#include "base/gtest_prod_util.h"
+#include "url/gurl.h"
 
 class PrefService;
 class Profile;
@@ -28,12 +30,18 @@
   static const char kPrefTranslateWhitelists[];
   static const char kPrefTranslateDeniedCount[];
   static const char kPrefTranslateAcceptedCount[];
+  static const char kPrefTranslateBlockedLanguages[];
 
   explicit TranslatePrefs(PrefService* user_prefs);
 
-  bool IsLanguageBlacklisted(const std::string& original_language) const;
-  void BlacklistLanguage(const std::string& original_language);
-  void RemoveLanguageFromBlacklist(const std::string& original_language);
+  bool IsBlockedLanguage(const std::string& original_language) const;
+  void BlockLanguage(const std::string& original_language);
+  void UnblockLanguage(const std::string& original_language);
+
+  // Removes a language from the old blacklist. This method is for
+  // chrome://translate-internals/.  Don't use this if there is no special
+  // reason.
+  void RemoveLanguageFromLegacyBlacklist(const std::string& original_language);
 
   bool IsSiteBlacklisted(const std::string& site) const;
   void BlacklistSite(const std::string& site);
@@ -79,6 +87,15 @@
   static void MigrateUserPrefs(PrefService* user_prefs);
 
  private:
+  friend class TranslatePrefsTest;
+  FRIEND_TEST_ALL_PREFIXES(TranslatePrefsTest, CreateBlockedLanguages);
+
+  // Merges two language sets to migrate to the language setting UI.
+  static void CreateBlockedLanguages(
+      std::vector<std::string>* blocked_languages,
+      const std::vector<std::string>& blacklisted_languages,
+      const std::vector<std::string>& accept_languages);
+
   bool IsValueBlacklisted(const char* pref_id, const std::string& value) const;
   void BlacklistValue(const char* pref_id, const std::string& value);
   void RemoveValueFromBlacklist(const char* pref_id, const std::string& value);
diff --git a/chrome/browser/translate/translate_prefs_unittest.cc b/chrome/browser/translate/translate_prefs_unittest.cc
new file mode 100644
index 0000000..a09aa61
--- /dev/null
+++ b/chrome/browser/translate/translate_prefs_unittest.cc
@@ -0,0 +1,61 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/translate/translate_prefs.h"
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+class TranslatePrefsTest : public testing::Test {
+ public:
+  TranslatePrefsTest() {}
+  virtual ~TranslatePrefsTest() {}
+};
+
+TEST_F(TranslatePrefsTest, CreateBlockedLanguages) {
+  std::vector<std::string> blacklisted_languages;
+  blacklisted_languages.push_back("en");
+  blacklisted_languages.push_back("fr");
+  // Hebrew: synonym to 'he'
+  blacklisted_languages.push_back("iw");
+  // Haitian is not used as Accept-Language
+  blacklisted_languages.push_back("ht");
+
+  std::vector<std::string> accept_languages;
+  accept_languages.push_back("en");
+  accept_languages.push_back("ja");
+  // Filippino: synonym to 'tl'
+  accept_languages.push_back("fil");
+  // General Chinese is not used as Translate language, but not filtered
+  // when merging.
+  accept_languages.push_back("zh");
+
+  std::vector<std::string> blocked_languages;
+
+  TranslatePrefs::CreateBlockedLanguages(&blocked_languages,
+                                         blacklisted_languages,
+                                         accept_languages);
+
+  // The order of the elements cannot be determined.
+  std::vector<std::string> expected;
+  expected.push_back("en");
+  expected.push_back("fr");
+  expected.push_back("iw");
+  expected.push_back("ht");
+  expected.push_back("ja");
+  expected.push_back("tl");
+  expected.push_back("zh");
+
+  EXPECT_EQ(expected.size(), blocked_languages.size());
+  for (std::vector<std::string>::const_iterator it = expected.begin();
+       it != expected.end(); ++it) {
+    EXPECT_NE(blocked_languages.end(),
+              std::find(blocked_languages.begin(),
+                        blocked_languages.end(),
+                        *it));
+  }
+}
diff --git a/chrome/browser/translate/translate_script.cc b/chrome/browser/translate/translate_script.cc
new file mode 100644
index 0000000..41ebdd6
--- /dev/null
+++ b/chrome/browser/translate/translate_script.cc
@@ -0,0 +1,121 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/translate/translate_script.h"
+
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/strings/string_util.h"
+#include "chrome/browser/translate/translate_url_fetcher.h"
+#include "chrome/browser/translate/translate_url_util.h"
+#include "chrome/common/chrome_switches.h"
+#include "google_apis/google_api_keys.h"
+#include "grit/browser_resources.h"
+#include "net/base/escape.h"
+#include "net/base/url_util.h"
+#include "ui/base/resource/resource_bundle.h"
+
+namespace {
+
+const int kExpirationDelayDays = 1;
+
+const char kScriptURL[] =
+    "https://translate.google.com/translate_a/element.js";
+const char kRequestHeader[] = "Google-Translate-Element-Mode: library";
+const int kFetcherId = 0;
+
+// Used in kTranslateScriptURL to specify a callback function name.
+const char kCallbackQueryName[] = "cb";
+const char kCallbackQueryValue[] =
+    "cr.googleTranslate.onTranslateElementLoad";
+
+}  // namespace
+
+TranslateScript::TranslateScript()
+    : weak_method_factory_(this),
+      expiration_delay_(base::TimeDelta::FromDays(kExpirationDelayDays)) {
+}
+
+TranslateScript::~TranslateScript() {
+  weak_method_factory_.InvalidateWeakPtrs();
+}
+
+void TranslateScript::Request(const Callback& callback) {
+  if (fetcher_.get() != NULL) {
+    NOTREACHED();
+    return;
+  }
+
+  callback_ = callback;
+
+  GURL translate_script_url;
+  // Check if command-line contains an alternative URL for translate service.
+  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+  if (command_line.HasSwitch(switches::kTranslateScriptURL)) {
+    translate_script_url = GURL(
+        command_line.GetSwitchValueASCII(switches::kTranslateScriptURL));
+    if (!translate_script_url.is_valid() ||
+        !translate_script_url.query().empty()) {
+      LOG(WARNING) << "The following translate URL specified at the "
+                   << "command-line is invalid: "
+                   << translate_script_url.spec();
+      translate_script_url = GURL();
+    }
+  }
+
+  // Use default URL when command-line argument is not specified, or specified
+  // URL is invalid.
+  if (translate_script_url.is_empty())
+    translate_script_url = GURL(kScriptURL);
+
+  translate_script_url = net::AppendQueryParameter(
+      translate_script_url,
+      kCallbackQueryName,
+      kCallbackQueryValue);
+
+  translate_script_url =
+      TranslateURLUtil::AddHostLocaleToUrl(translate_script_url);
+  translate_script_url =
+      TranslateURLUtil::AddApiKeyToUrl(translate_script_url);
+
+  fetcher_.reset(new TranslateURLFetcher(kFetcherId));
+  fetcher_->set_extra_request_header(kRequestHeader);
+  fetcher_->Request(
+      translate_script_url,
+      base::Bind(&TranslateScript::OnScriptFetchComplete,
+                 base::Unretained(this)));
+}
+
+
+void TranslateScript::OnScriptFetchComplete(
+    int id, bool success, const std::string& data) {
+  DCHECK_EQ(kFetcherId, id);
+
+  scoped_ptr<const TranslateURLFetcher> delete_ptr(fetcher_.release());
+
+  if (success) {
+    base::StringPiece str = ResourceBundle::GetSharedInstance().
+        GetRawDataResource(IDR_TRANSLATE_JS);
+    DCHECK(data_.empty());
+    str.CopyToString(&data_);
+    std::string argument = "('";
+    std::string api_key = google_apis::GetAPIKey();
+    argument += net::EscapeQueryParamValue(api_key, true);
+    argument += "');\n";
+    data_ += argument + data;
+
+    // We'll expire the cached script after some time, to make sure long
+    // running browsers still get fixes that might get pushed with newer
+    // scripts.
+    base::MessageLoop::current()->PostDelayedTask(
+        FROM_HERE,
+        base::Bind(&TranslateScript::Clear,
+                   weak_method_factory_.GetWeakPtr()),
+        expiration_delay_);
+  }
+
+  callback_.Run(success, data);
+}
diff --git a/chrome/browser/translate/translate_script.h b/chrome/browser/translate/translate_script.h
new file mode 100644
index 0000000..5fe0f61
--- /dev/null
+++ b/chrome/browser/translate/translate_script.h
@@ -0,0 +1,66 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_TRANSLATE_TRANSLATE_SCRIPT_H_
+#define CHROME_BROWSER_TRANSLATE_TRANSLATE_SCRIPT_H_
+
+#include <string>
+
+#include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
+
+class TranslateURLFetcher;
+
+class TranslateScript {
+ public:
+  typedef base::Callback<void(bool, const std::string&)> Callback;
+
+  TranslateScript();
+  virtual ~TranslateScript();
+
+  // Returns the feched the translate script.
+  const std::string& data() { return data_; }
+
+  // Used by unit-tests to override some defaults:
+  // Delay after which the translate script is fetched again from the
+  // translation server.
+  void set_expiration_delay(int delay_ms) {
+    expiration_delay_ = base::TimeDelta::FromMilliseconds(delay_ms);
+  }
+
+  // Clears the translate script, so it will be fetched next time we translate.
+  void Clear() { data_.clear(); }
+
+  // Fetches the JS translate script (the script that is injected in the page
+  // to translate it).
+  void Request(const Callback& callback);
+
+  // Returns true if this has a pending request.
+  bool HasPendingRequest() const { return fetcher_.get() != NULL; }
+
+ private:
+  // The callback when the script is fetched or a server error occured.
+  void OnScriptFetchComplete(int id, bool success, const std::string& data);
+
+  base::WeakPtrFactory<TranslateScript> weak_method_factory_;
+
+  // URL fetcher to fetch the translate script.
+  scoped_ptr<TranslateURLFetcher> fetcher_;
+
+  // The JS injected in the page to do the translation.
+  std::string data_;
+
+  // Delay after which the translate script is fetched again from the translate
+  // server.
+  base::TimeDelta expiration_delay_;
+
+  // The callback called when the server sends a response.
+  Callback callback_;
+
+  DISALLOW_COPY_AND_ASSIGN(TranslateScript);
+};
+
+#endif  // CHROME_BROWSER_TRANSLATE_TRANSLATE_SCRIPT_H_
diff --git a/chrome/browser/translate/translate_url_fetcher.cc b/chrome/browser/translate/translate_url_fetcher.cc
new file mode 100644
index 0000000..ba32046
--- /dev/null
+++ b/chrome/browser/translate/translate_url_fetcher.cc
@@ -0,0 +1,82 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/translate/translate_url_fetcher.h"
+
+#include "chrome/browser/browser_process.h"
+#include "net/base/load_flags.h"
+#include "net/http/http_status_code.h"
+#include "net/url_request/url_fetcher.h"
+#include "net/url_request/url_request_status.h"
+
+namespace {
+
+// Retry parameter for fetching.
+const int kMaxRetry = 16;
+
+}  // namespace
+
+TranslateURLFetcher::TranslateURLFetcher(int id)
+    : id_(id),
+      state_(IDLE),
+      retry_count_(0) {
+}
+
+TranslateURLFetcher::~TranslateURLFetcher() {
+}
+
+bool TranslateURLFetcher::Request(
+    const GURL& url,
+    const TranslateURLFetcher::Callback& callback) {
+  // This function is not supposed to be called before previous operaion is not
+  // finished.
+  if (state_ == REQUESTING) {
+    NOTREACHED();
+    return false;
+  }
+
+  if (retry_count_ >= kMaxRetry)
+    return false;
+  retry_count_++;
+
+  state_ = REQUESTING;
+  url_ = url;
+  callback_ = callback;
+
+  fetcher_.reset(net::URLFetcher::Create(
+      id_,
+      url_,
+      net::URLFetcher::GET,
+      this));
+  fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
+                         net::LOAD_DO_NOT_SAVE_COOKIES);
+  fetcher_->SetRequestContext(g_browser_process->system_request_context());
+  // Set retry parameter for HTTP status code 5xx. This doesn't work against
+  // 106 (net::ERR_INTERNET_DISCONNECTED) and so on.
+  // TranslateLanguageList handles network status, and implements retry.
+  fetcher_->SetMaxRetriesOn5xx(max_retry_on_5xx_);
+  if (!extra_request_header_.empty())
+    fetcher_->SetExtraRequestHeaders(extra_request_header_);
+
+  fetcher_->Start();
+
+  return true;
+}
+
+void TranslateURLFetcher::OnURLFetchComplete(const net::URLFetcher* source) {
+  DCHECK(fetcher_.get() == source);
+
+  std::string data;
+  if (source->GetStatus().status() == net::URLRequestStatus::SUCCESS &&
+      source->GetResponseCode() == net::HTTP_OK) {
+    state_ = COMPLETED;
+    source->GetResponseAsString(&data);
+  } else {
+    state_ = FAILED;
+  }
+
+  // Transfer URLFetcher's ownership before invoking a callback.
+  scoped_ptr<const net::URLFetcher> delete_ptr(fetcher_.release());
+  callback_.Run(id_, state_ == COMPLETED, data);
+}
diff --git a/chrome/browser/translate/translate_url_fetcher.h b/chrome/browser/translate/translate_url_fetcher.h
new file mode 100644
index 0000000..b7d8903
--- /dev/null
+++ b/chrome/browser/translate/translate_url_fetcher.h
@@ -0,0 +1,84 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_TRANSLATE_TRANSLATE_URL_FETCHER_H_
+#define CHROME_BROWSER_TRANSLATE_TRANSLATE_URL_FETCHER_H_
+
+#include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
+#include "net/url_request/url_fetcher_delegate.h"
+#include "url/gurl.h"
+
+class TranslateURLFetcher : public net::URLFetcherDelegate {
+ public:
+  // Callback type for Request().
+  typedef base::Callback<void(int, bool, const std::string&)> Callback;
+
+  // Represents internal state if the fetch is completed successfully.
+  enum State {
+    IDLE,        // No fetch request was issued.
+    REQUESTING,  // A fetch request was issued, but not finished yet.
+    COMPLETED,   // The last fetch request was finished successfully.
+    FAILED,      // The last fetch request was finished with a failure.
+  };
+
+  explicit TranslateURLFetcher(int id);
+  virtual ~TranslateURLFetcher();
+
+  int max_retry_on_5xx() {
+    return max_retry_on_5xx_;
+  }
+  void set_max_retry_on_5xx(int count) {
+    max_retry_on_5xx_ = count;
+  }
+
+  const std::string& extra_request_header() {
+    return extra_request_header_;
+  }
+  void set_extra_request_header(const std::string& header) {
+    extra_request_header_ = header;
+  }
+
+  // Requests to |url|. |callback| will be invoked when the function returns
+  // true, and the request is finished asynchronously.
+  // Returns false if the previous request is not finished, or the request
+  // is omitted due to retry limitation.
+  bool Request(const GURL& url, const Callback& callback);
+
+  // Gets internal state.
+  State state() { return state_; }
+
+  // net::URLFetcherDelegate implementation:
+  virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
+
+ private:
+  // URL to send the request.
+  GURL url_;
+
+  // ID which is assigned to the URLFetcher.
+  const int id_;
+
+  // Internal state.
+  enum State state_;
+
+  // URLFetcher instance.
+  scoped_ptr<net::URLFetcher> fetcher_;
+
+  // Callback passed at Request(). It will be invoked when an asynchronous
+  // fetch operation is finished.
+  Callback callback_;
+
+  // Counts how many times did it try to fetch the language list.
+  int retry_count_;
+
+  // Max number how many times to retry on the server error
+  int max_retry_on_5xx_;
+
+  // An extra HTTP request header
+  std::string extra_request_header_;
+
+  DISALLOW_COPY_AND_ASSIGN(TranslateURLFetcher);
+};
+
+#endif  // CHROME_BROWSER_TRANSLATE_TRANSLATE_URL_FETCHER_H_
diff --git a/chrome/browser/translate/translate_url_util.h b/chrome/browser/translate/translate_url_util.h
index 716903e..9709c0c 100644
--- a/chrome/browser/translate/translate_url_util.h
+++ b/chrome/browser/translate/translate_url_util.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_TRANSLATE_TRANSLATE_URL_UTIL_H_
 #define CHROME_BROWSER_TRANSLATE_TRANSLATE_URL_UTIL_H_
 
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 namespace TranslateURLUtil {
 
diff --git a/chrome/browser/ui/active_tab_tracker.h b/chrome/browser/ui/active_tab_tracker.h
index 9f69092..f58528c 100644
--- a/chrome/browser/ui/active_tab_tracker.h
+++ b/chrome/browser/ui/active_tab_tracker.h
@@ -7,8 +7,8 @@
 
 #include "base/logging.h"
 #include "base/memory/weak_ptr.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/idle.h"
 #include "chrome/browser/ui/browser_list_observer.h"
 #include "chrome/browser/ui/native_focus_tracker.h"
diff --git a/chrome/browser/ui/android/OWNERS b/chrome/browser/ui/android/OWNERS
index 3906ecc..04d1515 100644
--- a/chrome/browser/ui/android/OWNERS
+++ b/chrome/browser/ui/android/OWNERS
@@ -1,5 +1,4 @@
 aruslan@chromium.org
 bulach@chromium.org
-jcivelli@chromium.org
 tedchoc@chromium.org
 yfriedman@chromium.org
diff --git a/chrome/browser/ui/android/autofill/autofill_dialog_view_android.cc b/chrome/browser/ui/android/autofill/autofill_dialog_view_android.cc
index b5bd7f0..4b06e11 100644
--- a/chrome/browser/ui/android/autofill/autofill_dialog_view_android.cc
+++ b/chrome/browser/ui/android/autofill/autofill_dialog_view_android.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/ui/android/autofill/autofill_dialog_view_android.h"
+
 #include "base/android/jni_android.h"
 #include "base/android/jni_array.h"
 #include "base/android/jni_string.h"
@@ -11,9 +12,9 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/ui/android/window_android_helper.h"
 #include "chrome/browser/ui/autofill/data_model_wrapper.h"
-#include "components/autofill/browser/autofill_profile.h"
-#include "components/autofill/browser/autofill_type.h"
-#include "components/autofill/browser/credit_card.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/autofill_type.h"
+#include "components/autofill/core/browser/credit_card.h"
 #include "content/public/browser/web_contents.h"
 #include "grit/generated_resources.h"
 #include "jni/AutofillDialogGlue_jni.h"
@@ -134,6 +135,10 @@
   NOTIMPLEMENTED();
 }
 
+void AutofillDialogViewAndroid::UpdateAutocheckoutStepsArea() {
+  NOTIMPLEMENTED();
+}
+
 void AutofillDialogViewAndroid::UpdateSection(DialogSection section) {
   UpdateOrFillSectionToJava(section, true, UNKNOWN_TYPE);
 }
@@ -297,14 +302,6 @@
       controller_->LegalDocumentsText());
 }
 
-ScopedJavaLocalRef<jstring> AutofillDialogViewAndroid::GetProgressBarText(
-    JNIEnv* env,
-    jobject obj) {
-  return base::android::ConvertUTF16ToJavaString(
-      env,
-      controller_->ProgressBarText());
-}
-
 jboolean AutofillDialogViewAndroid::IsTheAddItem(
     JNIEnv* env,
     jobject obj,
diff --git a/chrome/browser/ui/android/autofill/autofill_dialog_view_android.h b/chrome/browser/ui/android/autofill/autofill_dialog_view_android.h
index 4b5b0d2..5a68739 100644
--- a/chrome/browser/ui/android/autofill/autofill_dialog_view_android.h
+++ b/chrome/browser/ui/android/autofill/autofill_dialog_view_android.h
@@ -29,6 +29,7 @@
   virtual void UpdateButtonStrip() OVERRIDE;
   virtual void UpdateDetailArea() OVERRIDE;
   virtual void UpdateForErrors() OVERRIDE;
+  virtual void UpdateAutocheckoutStepsArea() OVERRIDE;
   virtual void UpdateSection(DialogSection section) OVERRIDE;
   virtual void FillSection(DialogSection section,
                            const DetailInput& originating_input) OVERRIDE;
@@ -96,8 +97,6 @@
                                                                 jobject obj);
   base::android::ScopedJavaLocalRef<jstring> GetLegalDocumentsText(JNIEnv* env,
                                                                    jobject obj);
-  base::android::ScopedJavaLocalRef<jstring> GetProgressBarText(JNIEnv* env,
-                                                                jobject obj);
   jboolean IsTheAddItem(JNIEnv* env, jobject obj, jint section, jint index);
 
   static bool RegisterAutofillDialogViewAndroid(JNIEnv* env);
diff --git a/chrome/browser/ui/android/autofill/autofill_popup_view_android.cc b/chrome/browser/ui/android/autofill/autofill_popup_view_android.cc
index 6acc0c8..755947b 100644
--- a/chrome/browser/ui/android/autofill/autofill_popup_view_android.cc
+++ b/chrome/browser/ui/android/autofill/autofill_popup_view_android.cc
@@ -38,8 +38,6 @@
 }
 
 void AutofillPopupViewAndroid::Hide() {
-  AutofillPopupView::Hide();
-
   JNIEnv* env = base::android::AttachCurrentThread();
   Java_AutofillPopupGlue_hide(env, java_object_.obj());
   delete this;
diff --git a/chrome/browser/ui/app_list/app_context_menu.cc b/chrome/browser/ui/app_list/app_context_menu.cc
index 560117e..064516c 100644
--- a/chrome/browser/ui/app_list/app_context_menu.cc
+++ b/chrome/browser/ui/app_list/app_context_menu.cc
@@ -185,7 +185,7 @@
               IDS_APP_LIST_CONTEXT_MENU_PIN);
     }
 
-    if (controller_->CanShowCreateShortcutsDialog()) {
+    if (controller_->CanDoCreateShortcutsFlow(is_platform_app_)) {
       menu_model_->AddItemWithStringId(CREATE_SHORTCUTS,
                                        IDS_NEW_TAB_APP_CREATE_SHORTCUT);
     }
@@ -202,6 +202,12 @@
       if (!ash::Shell::IsForcedMaximizeMode())
 #endif
       {
+#if defined(OS_MACOSX)
+        // Mac does not support standalone web app browser windows or maximize.
+        menu_model_->AddCheckItemWithStringId(
+            LAUNCH_TYPE_FULLSCREEN,
+            IDS_APP_CONTEXT_MENU_OPEN_FULLSCREEN);
+#else
         menu_model_->AddCheckItemWithStringId(
             LAUNCH_TYPE_WINDOW,
             IDS_APP_CONTEXT_MENU_OPEN_WINDOW);
@@ -210,6 +216,7 @@
         menu_model_->AddCheckItemWithStringId(
             LAUNCH_TYPE_FULLSCREEN,
             IDS_APP_CONTEXT_MENU_OPEN_MAXIMIZED);
+#endif
       }
       menu_model_->AddSeparator(ui::NORMAL_SEPARATOR);
       menu_model_->AddItemWithStringId(OPTIONS, IDS_NEW_TAB_APP_OPTIONS);
@@ -346,7 +353,7 @@
     else
       controller_->PinApp(app_id_);
   } else if (command_id == CREATE_SHORTCUTS) {
-    controller_->ShowCreateShortcutsDialog(profile_, app_id_);
+    controller_->DoCreateShortcutsFlow(profile_, app_id_);
   } else if (command_id >= LAUNCH_TYPE_START &&
              command_id < LAUNCH_TYPE_LAST) {
     SetExtensionLaunchType(profile_,
diff --git a/chrome/browser/ui/app_list/app_list_controller_delegate.cc b/chrome/browser/ui/app_list/app_list_controller_delegate.cc
index dd747c6..23bff8d 100644
--- a/chrome/browser/ui/app_list/app_list_controller_delegate.cc
+++ b/chrome/browser/ui/app_list/app_list_controller_delegate.cc
@@ -27,7 +27,7 @@
 
 void AppListControllerDelegate::UnpinApp(const std::string& extension_id) {}
 
-void AppListControllerDelegate::ShowCreateShortcutsDialog(
+void AppListControllerDelegate::DoCreateShortcutsFlow(
     Profile* profile,
     const std::string& extension_id) {}
 
diff --git a/chrome/browser/ui/app_list/app_list_controller_delegate.h b/chrome/browser/ui/app_list/app_list_controller_delegate.h
index 0eb17cf..150d7c0 100644
--- a/chrome/browser/ui/app_list/app_list_controller_delegate.h
+++ b/chrome/browser/ui/app_list/app_list_controller_delegate.h
@@ -51,10 +51,10 @@
   virtual void OnShowExtensionPrompt() {}
   virtual void OnCloseExtensionPrompt() {}
 
-  // Whether the controller supports showing the Create Shortcuts dialog.
-  virtual bool CanShowCreateShortcutsDialog() = 0;
-  virtual void ShowCreateShortcutsDialog(Profile* profile,
-                                         const std::string& extension_id);
+  // Whether the controller supports a Create Shortcuts flow.
+  virtual bool CanDoCreateShortcutsFlow(bool is_platform_app) = 0;
+  virtual void DoCreateShortcutsFlow(Profile* profile,
+                                     const std::string& extension_id);
 
   // Handle the "create window" context menu items of Chrome App.
   // |incognito| is true to create an incognito window.
diff --git a/chrome/browser/ui/app_list/app_list_service.cc b/chrome/browser/ui/app_list/app_list_service.cc
index f02f45b..8ae72eb 100644
--- a/chrome/browser/ui/app_list/app_list_service.cc
+++ b/chrome/browser/ui/app_list/app_list_service.cc
@@ -9,7 +9,7 @@
 #include "base/prefs/pref_registry_simple.h"
 #include "base/process_info.h"
 #include "base/strings/string_number_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 
@@ -24,7 +24,7 @@
   return base::Time::Now() - base::Time::FromInternalValue(remote_start_time);
 }
 
-}
+}  // namespace
 
 // static
 void AppListService::RegisterPrefs(PrefRegistrySimple* registry) {
@@ -41,8 +41,11 @@
   // The presence of kOriginalProcessStartTime implies that another process
   // has sent us its command line to handle, ie: we are already running.
   if (command_line.HasSwitch(switches::kOriginalProcessStartTime)) {
-     UMA_HISTOGRAM_LONG_TIMES("Startup.ShowAppListWarmStart",
-                              GetTimeFromOriginalProcessStart(command_line));
+    base::TimeDelta elapsed = GetTimeFromOriginalProcessStart(command_line);
+    if (command_line.HasSwitch(switches::kFastStart))
+      UMA_HISTOGRAM_LONG_TIMES("Startup.ShowAppListWarmStartFast", elapsed);
+    else
+      UMA_HISTOGRAM_LONG_TIMES("Startup.ShowAppListWarmStart", elapsed);
   } else {
     // base::CurrentProcessInfo::CreationTime() is only defined on win/mac.
 #if defined(OS_WIN) || defined(OS_MACOSX)
diff --git a/chrome/browser/ui/app_list/app_list_service_impl.cc b/chrome/browser/ui/app_list/app_list_service_impl.cc
index f04b303..c763cdd 100644
--- a/chrome/browser/ui/app_list/app_list_service_impl.cc
+++ b/chrome/browser/ui/app_list/app_list_service_impl.cc
@@ -6,7 +6,7 @@
 
 #include "base/metrics/histogram.h"
 #include "base/prefs/pref_service.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/common/chrome_constants.h"
diff --git a/chrome/browser/ui/app_list/app_list_service_impl.h b/chrome/browser/ui/app_list/app_list_service_impl.h
index 91909cc..01cace7 100644
--- a/chrome/browser/ui/app_list/app_list_service_impl.h
+++ b/chrome/browser/ui/app_list/app_list_service_impl.h
@@ -13,8 +13,8 @@
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_info_cache_observer.h"
+#include "chrome/browser/profiles/profile_loader.h"
 #include "chrome/browser/ui/app_list/app_list_service.h"
-#include "chrome/browser/ui/app_list/profile_loader.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 
diff --git a/chrome/browser/ui/app_list/app_list_service_mac.mm b/chrome/browser/ui/app_list/app_list_service_mac.mm
index a22452b..2637424 100644
--- a/chrome/browser/ui/app_list/app_list_service_mac.mm
+++ b/chrome/browser/ui/app_list/app_list_service_mac.mm
@@ -2,20 +2,26 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <ApplicationServices/ApplicationServices.h>
+#import <Cocoa/Cocoa.h>
+
 #include "apps/app_shim/app_shim_handler_mac.h"
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/file_util.h"
 #include "base/lazy_instance.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/singleton.h"
 #include "base/message_loop.h"
 #include "base/observer_list.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/extension_system.h"
 #include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
 #include "chrome/browser/ui/app_list/app_list_service.h"
 #include "chrome/browser/ui/app_list/app_list_service_impl.h"
 #include "chrome/browser/ui/app_list/app_list_view_delegate.h"
 #include "chrome/browser/ui/extensions/application_launch.h"
+#include "chrome/browser/ui/web_applications/web_app_ui.h"
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/browser/web_applications/web_app_mac.h"
 #include "chrome/common/chrome_switches.h"
@@ -64,7 +70,10 @@
   virtual bool OnShimLaunch(apps::AppShimHandler::Host* host,
                             apps::AppShimLaunchType launch_type) OVERRIDE;
   virtual void OnShimClose(apps::AppShimHandler::Host* host) OVERRIDE;
-  virtual void OnShimFocus(apps::AppShimHandler::Host* host) OVERRIDE;
+  virtual void OnShimFocus(apps::AppShimHandler::Host* host,
+                           apps::AppShimFocusType focus_type) OVERRIDE;
+  virtual void OnShimSetHidden(apps::AppShimHandler::Host* host,
+                               bool hidden) OVERRIDE;
   virtual void OnShimQuit(apps::AppShimHandler::Host* host) OVERRIDE;
 
  private:
@@ -72,7 +81,7 @@
 
   AppListServiceMac() {}
 
-  scoped_nsobject<AppListWindowController> window_controller_;
+  base::scoped_nsobject<AppListWindowController> window_controller_;
 
   // App shim hosts observing when the app list is dismissed. In normal user
   // usage there should only be one. However, it can't be guaranteed, so use
@@ -92,7 +101,9 @@
   virtual void DismissView() OVERRIDE;
   virtual gfx::NativeWindow GetAppListWindow() OVERRIDE;
   virtual bool CanPin() OVERRIDE;
-  virtual bool CanShowCreateShortcutsDialog() OVERRIDE;
+  virtual bool CanDoCreateShortcutsFlow(bool is_platform_app) OVERRIDE;
+  virtual void DoCreateShortcutsFlow(Profile* profile,
+                                     const std::string& extension_id) OVERRIDE;
   virtual void ActivateApp(Profile* profile,
                            const extensions::Extension* extension,
                            int event_flags) OVERRIDE;
@@ -155,7 +166,8 @@
 
   // TODO(tapted): Create a dock icon using chrome/browser/mac/dock.h .
   web_app::CreateShortcuts(shortcut_info,
-                           ShellIntegration::ShortcutLocations());
+                           ShellIntegration::ShortcutLocations(),
+                           web_app::ALLOW_DUPLICATE_SHORTCUTS);
 }
 
 // Check that there is an app list shim. If enabling and there is not, make one.
@@ -178,7 +190,14 @@
 
   // Sanity check because deleting things recursively is scary.
   CHECK(install_path.MatchesExtension(".app"));
-  file_util::Delete(install_path, true /* recursive */);
+  base::Delete(install_path, true /* recursive */);
+}
+
+void CreateShortcutsInDefaultLocation(
+    const ShellIntegration::ShortcutInfo& shortcut_info) {
+  web_app::CreateShortcuts(shortcut_info,
+                           ShellIntegration::ShortcutLocations(),
+                           web_app::ALLOW_DUPLICATE_SHORTCUTS);
 }
 
 AppListControllerDelegateCocoa::AppListControllerDelegateCocoa() {}
@@ -197,9 +216,23 @@
   return false;
 }
 
-bool AppListControllerDelegateCocoa::CanShowCreateShortcutsDialog() {
-  // TODO(tapted): Return true when create shortcuts menu is tested on mac.
-  return false;
+bool AppListControllerDelegateCocoa::CanDoCreateShortcutsFlow(
+    bool is_platform_app) {
+  return is_platform_app &&
+      CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableAppShims);
+}
+
+void AppListControllerDelegateCocoa::DoCreateShortcutsFlow(
+    Profile* profile, const std::string& extension_id) {
+  ExtensionService* service =
+      extensions::ExtensionSystem::Get(profile)->extension_service();
+  DCHECK(service);
+  const extensions::Extension* extension =
+      service->GetInstalledExtension(extension_id);
+  DCHECK(extension);
+
+  web_app::UpdateShortcutInfoAndIconForApp(
+      *extension, profile, base::Bind(&CreateShortcutsInDefaultLocation));
 }
 
 void AppListControllerDelegateCocoa::ActivateApp(
@@ -220,7 +253,7 @@
   // The Objective C objects might be released at some unknown point in the
   // future, so explicitly clear references to C++ objects.
   [[window_controller_ appListViewController]
-      setDelegate:scoped_ptr<app_list::AppListViewDelegate>(NULL)];
+      setDelegate:scoped_ptr<app_list::AppListViewDelegate>()];
 
   SetProfile(requested_profile);
   scoped_ptr<app_list::AppListViewDelegate> delegate(
@@ -304,10 +337,14 @@
   DismissAppList();
 }
 
-void AppListServiceMac::OnShimFocus(apps::AppShimHandler::Host* host) {
+void AppListServiceMac::OnShimFocus(apps::AppShimHandler::Host* host,
+                                    apps::AppShimFocusType focus_type) {
   DismissAppList();
 }
 
+void AppListServiceMac::OnShimSetHidden(apps::AppShimHandler::Host* host,
+                                        bool hidden) {}
+
 void AppListServiceMac::OnShimQuit(apps::AppShimHandler::Host* host) {
   DismissAppList();
 }
@@ -336,25 +373,52 @@
   return DockLocationOtherDisplay;
 }
 
+// If |work_area_edge| is too close to the |screen_edge| (e.g. autohide dock),
+// adjust |anchor| away from the edge by a constant amount to reduce overlap and
+// ensure the dock icon can still be clicked to dismiss the app list.
+int AdjustPointForDynamicDock(int anchor, int screen_edge, int work_area_edge) {
+  const int kAutohideDockThreshold = 10;
+  const int kExtraDistance = 50;  // A dock with 40 items is about this size.
+  if (abs(work_area_edge - screen_edge) > kAutohideDockThreshold)
+    return anchor;
+
+  return anchor +
+      (screen_edge < work_area_edge ? kExtraDistance : -kExtraDistance);
+}
+
 NSPoint GetAppListWindowOrigin(NSWindow* window) {
   gfx::Screen* const screen = gfx::Screen::GetScreenFor([window contentView]);
+  // Ensure y coordinates are flipped back into AppKit's coordinate system.
+  const CGFloat max_y = NSMaxY([[[NSScreen screens] objectAtIndex:0] frame]);
+  if (!CGCursorIsVisible()) {
+    // If Chrome is the active application, display on the same display as
+    // Chrome's keyWindow since this will catch activations triggered, e.g, via
+    // WebStore install. If another application is active, OSX doesn't provide a
+    // reliable way to get the display in use. Fall back to the primary display
+    // since it has the menu bar and is likely to be correct, e.g., for
+    // activations from Spotlight.
+    const gfx::NativeView key_view = [[NSApp keyWindow] contentView];
+    const gfx::Rect work_area = key_view && [NSApp isActive] ?
+        screen->GetDisplayNearestWindow(key_view).work_area() :
+        screen->GetPrimaryDisplay().work_area();
+    return NSMakePoint(work_area.x(), max_y - work_area.bottom());
+  }
+
   gfx::Point anchor = screen->GetCursorScreenPoint();
   const gfx::Display display = screen->GetDisplayNearestPoint(anchor);
   const DockLocation dock_location = DockLocationInDisplay(display);
   const gfx::Rect display_bounds = display.bounds();
 
-  // Ensure y coordinates are flipped back into AppKit's coordinate system.
-  const CGFloat max_y = NSMaxY([[[NSScreen screens] objectAtIndex:0] frame]);
   if (dock_location == DockLocationOtherDisplay) {
     // Just display at the bottom-left of the display the cursor is on.
-    return NSMakePoint(display_bounds.x(),
-                       max_y - display_bounds.bottom());
+    return NSMakePoint(display_bounds.x(), max_y - display_bounds.bottom());
   }
 
   // Anchor the center of the window in a region that prevents the window
   // showing outside of the work area.
   const NSSize window_size = [window frame].size;
-  gfx::Rect anchor_area = display.work_area();
+  const gfx::Rect work_area = display.work_area();
+  gfx::Rect anchor_area = work_area;
   anchor_area.Inset(window_size.width / 2, window_size.height / 2);
   anchor.SetToMax(anchor_area.origin());
   anchor.SetToMin(anchor_area.bottom_right());
@@ -362,13 +426,16 @@
   // Move anchor to the dock, keeping the other axis aligned with the cursor.
   switch (dock_location) {
     case DockLocationBottom:
-      anchor.set_y(anchor_area.bottom());
+      anchor.set_y(AdjustPointForDynamicDock(
+          anchor_area.bottom(), display_bounds.bottom(), work_area.bottom()));
       break;
     case DockLocationLeft:
-      anchor.set_x(anchor_area.x());
+      anchor.set_x(AdjustPointForDynamicDock(
+          anchor_area.x(), display_bounds.x(), work_area.x()));
       break;
     case DockLocationRight:
-      anchor.set_x(anchor_area.right());
+      anchor.set_x(AdjustPointForDynamicDock(
+          anchor_area.right(), display_bounds.right(), work_area.right()));
       break;
     default:
       NOTREACHED();
diff --git a/chrome/browser/ui/app_list/app_list_service_mac_browsertest.mm b/chrome/browser/ui/app_list/app_list_service_mac_browsertest.mm
index 8566af4..f198d2b 100644
--- a/chrome/browser/ui/app_list/app_list_service_mac_browsertest.mm
+++ b/chrome/browser/ui/app_list/app_list_service_mac_browsertest.mm
@@ -32,7 +32,8 @@
 
   void FocusShim() {
     DCHECK(running_);
-    AppShimHandler::GetForAppMode(app_mode::kAppListModeId)->OnShimFocus(this);
+    AppShimHandler::GetForAppMode(app_mode::kAppListModeId)->
+        OnShimFocus(this, apps::APP_SHIM_FOCUS_REOPEN);
   }
 
   void QuitShim() {
@@ -46,8 +47,9 @@
     ++close_count_;
     QuitShim();
   }
-  virtual Profile* GetProfile() const OVERRIDE {
-    return NULL;  // Currently unused in this test.
+  virtual base::FilePath GetProfilePath() const OVERRIDE {
+    NOTREACHED();  // Currently unused in this test.
+    return base::FilePath();
   }
   virtual std::string GetAppId() const OVERRIDE {
     return app_mode::kAppListModeId;
diff --git a/chrome/browser/ui/app_list/app_list_view_delegate.cc b/chrome/browser/ui/app_list/app_list_view_delegate.cc
index 4c24cb2..ee4769f 100644
--- a/chrome/browser/ui/app_list/app_list_view_delegate.cc
+++ b/chrome/browser/ui/app_list/app_list_view_delegate.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/ui/app_list/app_list_view_delegate.h"
 
+#include "base/callback.h"
+#include "base/files/file_path.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/feedback/feedback_util.h"
@@ -16,8 +18,11 @@
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/host_desktop.h"
+#include "chrome/browser/ui/web_applications/web_app_ui.h"
+#include "chrome/browser/web_applications/web_app.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/common/url_constants.h"
+#include "content/public/browser/browser_thread.h"
 #include "content/public/browser/page_navigator.h"
 #include "content/public/browser/user_metrics.h"
 
@@ -25,6 +30,27 @@
 #include "chrome/browser/ui/ash/app_list/app_sync_ui_state_watcher.h"
 #endif
 
+#if defined(OS_WIN)
+#include "chrome/browser/web_applications/web_app_win.h"
+#endif
+
+namespace {
+
+#if defined(OS_WIN)
+void CreateShortcutInWebAppDir(
+    const base::FilePath& app_data_dir,
+    base::Callback<void(const base::FilePath&)> callback,
+    const ShellIntegration::ShortcutInfo& info) {
+  content::BrowserThread::PostTaskAndReplyWithResult(
+      content::BrowserThread::FILE,
+      FROM_HERE,
+      base::Bind(web_app::CreateShortcutInWebAppDir, app_data_dir, info),
+      callback);
+}
+#endif
+
+}  // namespace
+
 AppListViewDelegate::AppListViewDelegate(AppListControllerDelegate* controller,
                                          Profile* profile)
     : controller_(controller),
@@ -68,6 +94,33 @@
   static_cast<ChromeAppListItem*>(item)->Activate(event_flags);
 }
 
+void AppListViewDelegate::GetShortcutPathForApp(
+    const std::string& app_id,
+    const base::Callback<void(const base::FilePath&)>& callback) {
+#if defined(OS_WIN)
+  ExtensionService* service = profile_->GetExtensionService();
+  DCHECK(service);
+  const extensions::Extension* extension =
+      service->GetInstalledExtension(app_id);
+  if (!extension) {
+    callback.Run(base::FilePath());
+    return;
+  }
+
+  base::FilePath app_data_dir(
+      web_app::GetWebAppDataDirectory(profile_->GetPath(),
+                                      extension->id(),
+                                      GURL()));
+
+  web_app::UpdateShortcutInfoAndIconForApp(
+      *extension,
+      profile_,
+      base::Bind(CreateShortcutInWebAppDir, app_data_dir, callback));
+#else
+  callback.Run(base::FilePath());
+#endif
+}
+
 void AppListViewDelegate::StartSearch() {
   if (search_controller_.get())
     search_controller_->Start();
diff --git a/chrome/browser/ui/app_list/app_list_view_delegate.h b/chrome/browser/ui/app_list/app_list_view_delegate.h
index d2803c0..0b5d121 100644
--- a/chrome/browser/ui/app_list/app_list_view_delegate.h
+++ b/chrome/browser/ui/app_list/app_list_view_delegate.h
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "base/basictypes.h"
+#include "base/callback_forward.h"
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
 #include "ui/app_list/app_list_view_delegate.h"
@@ -20,6 +21,10 @@
 class SearchController;
 }
 
+namespace base {
+class FilePath;
+}
+
 namespace gfx {
 class ImageSkia;
 }
@@ -38,6 +43,9 @@
   // Overridden from app_list::AppListViewDelegate:
   virtual void SetModel(app_list::AppListModel* model) OVERRIDE;
   virtual app_list::SigninDelegate* GetSigninDelegate() OVERRIDE;
+  virtual void GetShortcutPathForApp(
+      const std::string& app_id,
+      const base::Callback<void(const base::FilePath&)>& callback) OVERRIDE;
   virtual void ActivateAppListItem(app_list::AppListItemModel* item,
                                    int event_flags) OVERRIDE;
   virtual void StartSearch() OVERRIDE;
diff --git a/chrome/browser/ui/app_list/chrome_signin_delegate.cc b/chrome/browser/ui/app_list/chrome_signin_delegate.cc
index a68db45..ed9639d 100644
--- a/chrome/browser/ui/app_list/chrome_signin_delegate.cc
+++ b/chrome/browser/ui/app_list/chrome_signin_delegate.cc
@@ -13,7 +13,7 @@
 #include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/extensions/application_launch.h"
 #include "chrome/browser/ui/host_desktop.h"
-#include "chrome/browser/ui/webui/sync_promo/sync_promo_ui.h"
+#include "chrome/browser/ui/sync/sync_promo_ui.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "content/public/common/page_transition_types.h"
 #include "grit/chromium_strings.h"
diff --git a/chrome/browser/ui/app_list/profile_loader.cc b/chrome/browser/ui/app_list/profile_loader.cc
deleted file mode 100644
index 4654cf2..0000000
--- a/chrome/browser/ui/app_list/profile_loader.cc
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/app_list/profile_loader.h"
-
-#include "base/bind.h"
-#include "base/files/file_path.h"
-#include "base/memory/weak_ptr.h"
-#include "chrome/browser/lifetime/application_lifetime.h"
-#include "chrome/browser/profiles/profile_manager.h"
-
-ProfileLoader::ProfileLoader(ProfileManager* profile_manager)
-  : profile_manager_(profile_manager),
-    profile_load_sequence_id_(0),
-    pending_profile_loads_(0),
-    weak_factory_(this) {
-}
-
-ProfileLoader::~ProfileLoader() {
-}
-
-bool ProfileLoader::AnyProfilesLoading() const {
-  return pending_profile_loads_ > 0;
-}
-
-void ProfileLoader::InvalidatePendingProfileLoads() {
-  profile_load_sequence_id_++;
-}
-
-void ProfileLoader::LoadProfileInvalidatingOtherLoads(
-    const base::FilePath& profile_file_path,
-    base::Callback<void(Profile*)> callback) {
-  Profile* profile = profile_manager_->GetProfileByPath(profile_file_path);
-  if (profile) {
-    callback.Run(profile);
-    return;
-  }
-
-  IncrementPendingProfileLoads();
-  profile_manager_->CreateProfileAsync(
-      profile_file_path,
-      base::Bind(&ProfileLoader::OnProfileLoaded,
-                 weak_factory_.GetWeakPtr(),
-                 profile_load_sequence_id_,
-                 callback),
-      string16(), string16(), false);
-}
-
-void ProfileLoader::OnProfileLoaded(int profile_load_sequence_id,
-                                    base::Callback<void(Profile*)> callback,
-                                    Profile* profile,
-                                    Profile::CreateStatus status) {
-  switch (status) {
-    case Profile::CREATE_STATUS_CREATED:
-      break;
-    case Profile::CREATE_STATUS_INITIALIZED:
-      if (profile_load_sequence_id == profile_load_sequence_id_)
-        callback.Run(profile);
-      DecrementPendingProfileLoads();
-      break;
-    case Profile::CREATE_STATUS_LOCAL_FAIL:
-    case Profile::CREATE_STATUS_REMOTE_FAIL:
-    case Profile::CREATE_STATUS_CANCELED:
-      DecrementPendingProfileLoads();
-      break;
-    case Profile::MAX_CREATE_STATUS:
-      NOTREACHED();
-      break;
-  }
-}
-
-void ProfileLoader::IncrementPendingProfileLoads() {
-  pending_profile_loads_++;
-  if (pending_profile_loads_ == 1)
-    chrome::StartKeepAlive();
-}
-
-void ProfileLoader::DecrementPendingProfileLoads() {
-  pending_profile_loads_--;
-  if (pending_profile_loads_ == 0)
-    chrome::EndKeepAlive();
-}
diff --git a/chrome/browser/ui/app_list/profile_loader.h b/chrome/browser/ui/app_list/profile_loader.h
deleted file mode 100644
index f2b12fd..0000000
--- a/chrome/browser/ui/app_list/profile_loader.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_APP_LIST_PROFILE_LOADER_H_
-#define CHROME_BROWSER_UI_APP_LIST_PROFILE_LOADER_H_
-
-#include "base/callback.h"
-#include "base/memory/weak_ptr.h"
-#include "chrome/browser/profiles/profile.h"
-
-namespace base {
-class FilePath;
-}
-
-class ProfileManager;
-
-class ProfileLoader {
- public:
-  explicit ProfileLoader(ProfileManager* profile_manager);
-  ~ProfileLoader();
-
-  bool AnyProfilesLoading() const;
-  void InvalidatePendingProfileLoads();
-  void LoadProfileInvalidatingOtherLoads(
-      const base::FilePath& profile_file_path,
-      base::Callback<void(Profile*)> callback);
-
- private:
-  void OnProfileLoaded(int profile_load_sequence_id,
-                       base::Callback<void(Profile*)> callback,
-                       Profile* profile,
-                       Profile::CreateStatus status);
-
-  void IncrementPendingProfileLoads();
-  void DecrementPendingProfileLoads();
-
- private:
-  ProfileManager* profile_manager_;
-  int profile_load_sequence_id_;
-  int pending_profile_loads_;
-
-  base::WeakPtrFactory<ProfileLoader> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(ProfileLoader);
-};
-
-#endif  // CHROME_BROWSER_UI_APP_LIST_PROFILE_LOADER_H_
diff --git a/chrome/browser/ui/app_list/search/app_result.cc b/chrome/browser/ui/app_list/search/app_result.cc
index c7d3f58..9301f5d 100644
--- a/chrome/browser/ui/app_list/search/app_result.cc
+++ b/chrome/browser/ui/app_list/search/app_result.cc
@@ -84,6 +84,10 @@
   return copy.Pass();
 }
 
+ChromeSearchResultType AppResult::GetType() {
+  return APP_SEARCH_RESULT;
+}
+
 ui::MenuModel* AppResult::GetContextMenuModel() {
   if (!context_menu_) {
     context_menu_.reset(new AppContextMenu(
diff --git a/chrome/browser/ui/app_list/search/app_result.h b/chrome/browser/ui/app_list/search/app_result.h
index 5165b21..f270058 100644
--- a/chrome/browser/ui/app_list/search/app_result.h
+++ b/chrome/browser/ui/app_list/search/app_result.h
@@ -38,6 +38,7 @@
   virtual void InvokeAction(int action_index, int event_flags) OVERRIDE;
   virtual scoped_ptr<ChromeSearchResult> Duplicate() OVERRIDE;
   virtual ui::MenuModel* GetContextMenuModel() OVERRIDE;
+  virtual ChromeSearchResultType GetType() OVERRIDE;
 
  private:
   // extensions::IconImage::Observer overrides:
diff --git a/chrome/browser/ui/app_list/search/chrome_search_result.h b/chrome/browser/ui/app_list/search/chrome_search_result.h
index 26e2264..2c00607 100644
--- a/chrome/browser/ui/app_list/search/chrome_search_result.h
+++ b/chrome/browser/ui/app_list/search/chrome_search_result.h
@@ -12,6 +12,20 @@
 
 namespace app_list {
 
+// The type of the search result. This is used for logging so do not change the
+// order of this enum.
+enum ChromeSearchResultType {
+  // A result that forwards an omnibox search result.
+  OMNIBOX_SEARCH_RESULT,
+  // An app result.
+  APP_SEARCH_RESULT,
+  // A search result from the webstore.
+  WEBSTORE_SEARCH_RESULT,
+  // A result that opens a webstore search.
+  SEARCH_WEBSTORE_SEARCH_RESULT,
+  SEARCH_RESULT_TYPE_BOUNDARY
+};
+
 // Base class of all search results. It provides an additional interface
 // for SearchController to mix the results, duplicate a result from a
 // SearchProvider and pass it to UI and invoke actions on the results when
@@ -30,6 +44,8 @@
   // Creates a copy of the result.
   virtual scoped_ptr<ChromeSearchResult> Duplicate() = 0;
 
+  virtual ChromeSearchResultType GetType() = 0;
+
   const std::string& id() const { return id_; }
   double relevance() { return relevance_; }
 
diff --git a/chrome/browser/ui/app_list/search/history_data.h b/chrome/browser/ui/app_list/search/history_data.h
index 806da4f..f9d5bc5 100644
--- a/chrome/browser/ui/app_list/search/history_data.h
+++ b/chrome/browser/ui/app_list/search/history_data.h
@@ -13,7 +13,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/ui/app_list/search/history_types.h"
 
 namespace app_list {
diff --git a/chrome/browser/ui/app_list/search/history_unittest.cc b/chrome/browser/ui/app_list/search/history_unittest.cc
index c498118..e7e34a3 100644
--- a/chrome/browser/ui/app_list/search/history_unittest.cc
+++ b/chrome/browser/ui/app_list/search/history_unittest.cc
@@ -9,7 +9,7 @@
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/platform_thread.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/ui/app_list/search/history.h"
 #include "chrome/browser/ui/app_list/search/history_data.h"
 #include "chrome/browser/ui/app_list/search/history_data_observer.h"
diff --git a/chrome/browser/ui/app_list/search/mixer_unittest.cc b/chrome/browser/ui/app_list/search/mixer_unittest.cc
index 2a242e3..592d7c8 100644
--- a/chrome/browser/ui/app_list/search/mixer_unittest.cc
+++ b/chrome/browser/ui/app_list/search/mixer_unittest.cc
@@ -35,6 +35,9 @@
     return scoped_ptr<ChromeSearchResult>(
         new TestSearchResult(id(), relevance())).Pass();
   }
+  virtual ChromeSearchResultType GetType() OVERRIDE {
+    return SEARCH_RESULT_TYPE_BOUNDARY;
+  }
 
   DISALLOW_COPY_AND_ASSIGN(TestSearchResult);
 };
diff --git a/chrome/browser/ui/app_list/search/omnibox_provider.cc b/chrome/browser/ui/app_list/search/omnibox_provider.cc
index 50c470f..0869c20 100644
--- a/chrome/browser/ui/app_list/search/omnibox_provider.cc
+++ b/chrome/browser/ui/app_list/search/omnibox_provider.cc
@@ -92,6 +92,10 @@
         new OmniboxResult(profile_, match_)).Pass();
   }
 
+  virtual ChromeSearchResultType GetType() OVERRIDE {
+    return OMNIBOX_SEARCH_RESULT;
+  }
+
  private:
   void UpdateIcon() {
     int resource_id = match_.starred ?
diff --git a/chrome/browser/ui/app_list/search/search_controller.cc b/chrome/browser/ui/app_list/search/search_controller.cc
index f105398..b2cd7fb 100644
--- a/chrome/browser/ui/app_list/search/search_controller.cc
+++ b/chrome/browser/ui/app_list/search/search_controller.cc
@@ -10,6 +10,7 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/metrics/histogram.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/profiles/profile.h"
@@ -27,6 +28,11 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
 
+namespace {
+  const char kAppListSearchResultOpenTypeHistogram[] =
+      "Apps.AppListSearchResultOpenType";
+}
+
 namespace app_list {
 
 SearchController::SearchController(Profile* profile,
@@ -57,7 +63,7 @@
   AddProvider(Mixer::OMNIBOX_GROUP, scoped_ptr<SearchProvider>(
       new OmniboxProvider(profile_)).Pass());
   AddProvider(Mixer::WEBSTORE_GROUP, scoped_ptr<SearchProvider>(
-      new WebstoreProvider(profile_)).Pass());
+      new WebstoreProvider(profile_, list_controller_)).Pass());
 }
 
 void SearchController::Start() {
@@ -100,6 +106,9 @@
 
   ChromeSearchResult* chrome_result =
       static_cast<app_list::ChromeSearchResult*>(result);
+  UMA_HISTOGRAM_ENUMERATION(kAppListSearchResultOpenTypeHistogram,
+                            chrome_result->GetType(),
+                            SEARCH_RESULT_TYPE_BOUNDARY);
   chrome_result->Open(event_flags);
 
   if (history_ && history_->IsReady()) {
diff --git a/chrome/browser/ui/app_list/search/search_controller.h b/chrome/browser/ui/app_list/search/search_controller.h
index fca4b61..cb4b922 100644
--- a/chrome/browser/ui/app_list/search/search_controller.h
+++ b/chrome/browser/ui/app_list/search/search_controller.h
@@ -8,7 +8,7 @@
 #include "base/basictypes.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/scoped_vector.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/ui/app_list/search/mixer.h"
 #include "ui/app_list/app_list_model.h"
 
diff --git a/chrome/browser/ui/app_list/search/search_webstore_result.cc b/chrome/browser/ui/app_list/search/search_webstore_result.cc
index b38df4c..3c0a7c8 100644
--- a/chrome/browser/ui/app_list/search/search_webstore_result.cc
+++ b/chrome/browser/ui/app_list/search/search_webstore_result.cc
@@ -55,4 +55,8 @@
       new SearchWebstoreResult(profile_, query_)).Pass();
 }
 
+ChromeSearchResultType SearchWebstoreResult::GetType() {
+  return WEBSTORE_SEARCH_RESULT;
+}
+
 }  // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/search_webstore_result.h b/chrome/browser/ui/app_list/search/search_webstore_result.h
index d577c75..4a0052e 100644
--- a/chrome/browser/ui/app_list/search/search_webstore_result.h
+++ b/chrome/browser/ui/app_list/search/search_webstore_result.h
@@ -25,6 +25,7 @@
   virtual void Open(int event_flags) OVERRIDE;
   virtual void InvokeAction(int action_index, int event_flags) OVERRIDE;
   virtual scoped_ptr<ChromeSearchResult> Duplicate() OVERRIDE;
+  virtual ChromeSearchResultType GetType() OVERRIDE;
 
  private:
   Profile* profile_;
diff --git a/chrome/browser/ui/app_list/search/webstore_installer.cc b/chrome/browser/ui/app_list/search/webstore_installer.cc
new file mode 100644
index 0000000..58c1ebb
--- /dev/null
+++ b/chrome/browser/ui/app_list/search/webstore_installer.cc
@@ -0,0 +1,34 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/app_list/search/webstore_installer.h"
+
+#include "chrome/browser/extensions/extension_install_prompt.h"
+#include "chrome/browser/ui/browser_finder.h"
+
+namespace app_list {
+
+WebstoreInstaller::WebstoreInstaller(const std::string& webstore_item_id,
+                                     Profile* profile,
+                                     gfx::NativeWindow parent_window,
+                                     const Callback& callback)
+    : WebstoreStartupInstaller(webstore_item_id, profile, true, callback),
+      profile_(profile),
+      parent_window_(parent_window) {}
+
+WebstoreInstaller::~WebstoreInstaller() {}
+
+scoped_ptr<ExtensionInstallPrompt> WebstoreInstaller::CreateInstallUI() {
+  return make_scoped_ptr(
+      new ExtensionInstallPrompt(profile_, parent_window_, this));
+}
+
+content::WebContents* WebstoreInstaller::OpenURL(
+    const content::OpenURLParams& params) {
+  Browser* browser = chrome::FindOrCreateTabbedBrowser(
+      profile_, chrome::GetActiveDesktop());
+  return browser->OpenURL(params);
+}
+
+}  // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/webstore_installer.h b/chrome/browser/ui/app_list/search/webstore_installer.h
new file mode 100644
index 0000000..16363c6
--- /dev/null
+++ b/chrome/browser/ui/app_list/search/webstore_installer.h
@@ -0,0 +1,49 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_WEBSTORE_INSTALLER_H_
+#define CHROME_BROWSER_UI_APP_LIST_SEARCH_WEBSTORE_INSTALLER_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "chrome/browser/extensions/webstore_startup_installer.h"
+#include "content/public/browser/page_navigator.h"
+
+class Profile;
+
+namespace app_list {
+
+// WebstoreInstaller handles install for web store search results.
+class WebstoreInstaller : public extensions::WebstoreStartupInstaller,
+                          public content::PageNavigator {
+ public:
+  typedef WebstoreStandaloneInstaller::Callback Callback;
+
+  WebstoreInstaller(const std::string& webstore_item_id,
+                    Profile* profile,
+                    gfx::NativeWindow parent_window,
+                    const Callback& callback);
+
+ private:
+  friend class base::RefCountedThreadSafe<WebstoreInstaller>;
+
+  virtual ~WebstoreInstaller();
+
+  // extensions::WebstoreStartupInstaller overrides:
+  virtual scoped_ptr<ExtensionInstallPrompt> CreateInstallUI() OVERRIDE;
+
+  // content::PageNavigator overrides:
+  virtual content::WebContents* OpenURL(
+      const content::OpenURLParams& params) OVERRIDE;
+
+  Profile* profile_;
+  gfx::NativeWindow parent_window_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebstoreInstaller);
+};
+
+}  // namespace app_list
+
+#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_WEBSTORE_INSTALLER_H_
diff --git a/chrome/browser/ui/app_list/search/webstore_provider.cc b/chrome/browser/ui/app_list/search/webstore_provider.cc
index 7f0cad1..16c2d30 100644
--- a/chrome/browser/ui/app_list/search/webstore_provider.cc
+++ b/chrome/browser/ui/app_list/search/webstore_provider.cc
@@ -28,7 +28,10 @@
 
 }  // namespace
 
-WebstoreProvider::WebstoreProvider(Profile* profile) : profile_(profile) {}
+WebstoreProvider::WebstoreProvider(Profile* profile,
+                                   AppListControllerDelegate* controller)
+  : profile_(profile),
+    controller_(controller) {}
 
 WebstoreProvider::~WebstoreProvider() {}
 
@@ -113,7 +116,8 @@
   if (!icon_url.is_valid())
     return result.Pass();
 
-  result.reset(new WebstoreResult(profile_, app_id, localized_name, icon_url));
+  result.reset(new WebstoreResult(
+      profile_, app_id, localized_name, icon_url, controller_));
   return result.Pass();
 }
 
diff --git a/chrome/browser/ui/app_list/search/webstore_provider.h b/chrome/browser/ui/app_list/search/webstore_provider.h
index cb0fba6..253111d 100644
--- a/chrome/browser/ui/app_list/search/webstore_provider.h
+++ b/chrome/browser/ui/app_list/search/webstore_provider.h
@@ -10,6 +10,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "chrome/browser/ui/app_list/search/search_provider.h"
 
+class AppListControllerDelegate;
 class Profile;
 
 namespace base {
@@ -30,7 +31,7 @@
 // return any results.
 class WebstoreProvider : public SearchProvider {
  public:
-  explicit WebstoreProvider(Profile* profile);
+  WebstoreProvider(Profile* profile, AppListControllerDelegate* controller);
   virtual ~WebstoreProvider();
 
   // SearchProvider overrides:
@@ -50,6 +51,7 @@
   }
 
   Profile* profile_;
+  AppListControllerDelegate* controller_;
   scoped_ptr<WebstoreSearchFetcher> webstore_search_;
   base::Closure webstore_search_fetched_callback_;
 
diff --git a/chrome/browser/ui/app_list/search/webstore_provider_browsertest.cc b/chrome/browser/ui/app_list/search/webstore_provider_browsertest.cc
index 9caf949..2399091 100644
--- a/chrome/browser/ui/app_list/search/webstore_provider_browsertest.cc
+++ b/chrome/browser/ui/app_list/search/webstore_provider_browsertest.cc
@@ -47,7 +47,7 @@
         switches::kAppsGalleryURL, test_server_->base_url().spec());
 
     webstore_provider_.reset(new WebstoreProvider(
-        ProfileManager::GetDefaultProfile()));
+        ProfileManager::GetDefaultProfile(), NULL));
     webstore_provider_->set_webstore_search_fetched_callback(
         base::Bind(&WebstoreProviderTest::OnSearchResultsFetched,
                    base::Unretained(this)));
@@ -98,11 +98,11 @@
 
     if (request.relative_url.find("/jsonsearch?") != std::string::npos) {
       if (mock_server_response_ == "404") {
-        response->set_code(net::test_server::NOT_FOUND);
+        response->set_code(net::HTTP_NOT_FOUND);
       } else if (mock_server_response_ == "500") {
-        response->set_code(net::test_server::ACCESS_DENIED);
+        response->set_code(net::HTTP_INTERNAL_SERVER_ERROR);
       } else {
-        response->set_code(net::test_server::SUCCESS);
+        response->set_code(net::HTTP_OK);
         response->set_content(mock_server_response_);
       }
     }
diff --git a/chrome/browser/ui/app_list/search/webstore_result.cc b/chrome/browser/ui/app_list/search/webstore_result.cc
index b7f55fc..1ceb310 100644
--- a/chrome/browser/ui/app_list/search/webstore_result.cc
+++ b/chrome/browser/ui/app_list/search/webstore_result.cc
@@ -7,11 +7,19 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/memory/ref_counted.h"
 #include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/extension_system.h"
+#include "chrome/browser/extensions/install_tracker.h"
+#include "chrome/browser/extensions/install_tracker_factory.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
+#include "chrome/browser/ui/app_list/search/webstore_installer.h"
 #include "chrome/browser/ui/app_list/search/webstore_result_icon_source.h"
-#include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/extensions/application_launch.h"
 #include "chrome/common/extensions/extension.h"
+#include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
 
@@ -20,18 +28,23 @@
 WebstoreResult::WebstoreResult(Profile* profile,
                                const std::string& app_id,
                                const std::string& localized_name,
-                               const GURL& icon_url)
+                               const GURL& icon_url,
+                               AppListControllerDelegate* controller)
     : profile_(profile),
       app_id_(app_id),
       localized_name_(localized_name),
       icon_url_(icon_url),
-      weak_factory_(this) {
+      weak_factory_(this),
+      controller_(controller),
+      install_tracker_(NULL) {
   set_id(extensions::Extension::GetBaseURLFromExtensionId(app_id_).spec());
   set_relevance(0.0);  // What is the right value to use?
 
   set_title(UTF8ToUTF16(localized_name_));
   SetDefaultDetails();
 
+  UpdateActions();
+
   const int kIconSize = 32;
   icon_ = gfx::ImageSkia(
       new WebstoreResultIconSource(
@@ -42,25 +55,50 @@
           kIconSize),
       gfx::Size(kIconSize, kIconSize));
   SetIcon(icon_);
+
+  StartObservingInstall();
 }
 
-WebstoreResult::~WebstoreResult() {}
+WebstoreResult::~WebstoreResult() {
+  StopObservingInstall();
+}
 
 void WebstoreResult::Open(int event_flags) {
-  const GURL store_url(extension_urls::GetWebstoreItemDetailURLPrefix() +
-                       app_id_);
-  chrome::NavigateParams params(profile_,
-                                store_url,
-                                content::PAGE_TRANSITION_LINK);
-  params.disposition = ui::DispositionFromEventFlags(event_flags);
-  chrome::Navigate(&params);
+  const extensions::Extension* extension =
+      extensions::ExtensionSystem::Get(profile_)->extension_service()
+          ->GetInstalledExtension(app_id_);
+  if (extension) {
+    controller_->ActivateApp(profile_, extension, event_flags);
+    return;
+  }
+
+  StartInstall();
 }
 
-void WebstoreResult::InvokeAction(int action_index, int event_flags) {}
+void WebstoreResult::InvokeAction(int action_index, int event_flags) {
+  DCHECK_EQ(0, action_index);
+  StartInstall();
+}
 
 scoped_ptr<ChromeSearchResult> WebstoreResult::Duplicate() {
-  return scoped_ptr<ChromeSearchResult>(
-      new WebstoreResult(profile_, app_id_, localized_name_, icon_url_)).Pass();
+  return scoped_ptr<ChromeSearchResult>(new WebstoreResult(
+      profile_, app_id_, localized_name_, icon_url_, controller_)).Pass();
+}
+
+void WebstoreResult::UpdateActions() {
+  Actions actions;
+
+  const bool is_otr = profile_->IsOffTheRecord();
+  const bool is_installed = !!extensions::ExtensionSystem::Get(profile_)->
+      extension_service()->GetInstalledExtension(app_id_);
+
+  if (!is_otr && !is_installed && !is_installing()) {
+    actions.push_back(Action(
+        l10n_util::GetStringUTF16(IDS_EXTENSION_INLINE_INSTALL_PROMPT_TITLE),
+        base::string16()));
+  }
+
+  SetActions(actions);
 }
 
 void WebstoreResult::SetDefaultDetails() {
@@ -83,4 +121,87 @@
   SetIcon(icon_);
 }
 
+void WebstoreResult::StartInstall() {
+  SetPercentDownloaded(0);
+  SetIsInstalling(true);
+
+  scoped_refptr<WebstoreInstaller> installer =
+      new WebstoreInstaller(
+          app_id_,
+          profile_,
+          controller_->GetAppListWindow(),
+          base::Bind(&WebstoreResult::InstallCallback,
+                     weak_factory_.GetWeakPtr()));
+  installer->BeginInstall();
+}
+
+void WebstoreResult::InstallCallback(bool success, const std::string& error) {
+  if (!success) {
+    LOG(ERROR) << "Failed to install app, error=" << error;
+    SetIsInstalling(false);
+    return;
+  }
+
+  // Success handling is continued in OnExtensionInstalled.
+  SetPercentDownloaded(100);
+}
+
+void WebstoreResult::StartObservingInstall() {
+  DCHECK(!install_tracker_);
+
+  install_tracker_ = extensions::InstallTrackerFactory::GetForProfile(profile_);
+  install_tracker_->AddObserver(this);
+}
+
+void WebstoreResult::StopObservingInstall() {
+  if (install_tracker_)
+    install_tracker_->RemoveObserver(this);
+
+  install_tracker_ = NULL;
+}
+
+void WebstoreResult::OnBeginExtensionInstall(
+    const std::string& extension_id,
+    const std::string& extension_name,
+    const gfx::ImageSkia& installing_icon,
+    bool is_app,
+    bool is_platform_app) {}
+
+void WebstoreResult::OnDownloadProgress(const std::string& extension_id,
+                                        int percent_downloaded) {
+  if (extension_id != app_id_ || percent_downloaded < 0)
+    return;
+
+  SetPercentDownloaded(percent_downloaded);
+}
+
+void WebstoreResult::OnInstallFailure(const std::string& extension_id) {}
+
+void WebstoreResult::OnExtensionInstalled(
+    const extensions::Extension* extension) {
+  if (extension->id() != app_id_)
+    return;
+
+  SetIsInstalling(false);
+  UpdateActions();
+}
+
+void WebstoreResult::OnExtensionUninstalled(
+    const extensions::Extension* extension) {}
+
+void WebstoreResult::OnExtensionDisabled(
+    const extensions::Extension* extension) {}
+
+void WebstoreResult::OnAppsReordered() {}
+
+void WebstoreResult::OnAppInstalledToAppList(const std::string& extension_id) {}
+
+void WebstoreResult::OnShutdown() {
+  StopObservingInstall();
+}
+
+ChromeSearchResultType WebstoreResult::GetType() {
+  return SEARCH_WEBSTORE_SEARCH_RESULT;
+}
+
 }  // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/webstore_result.h b/chrome/browser/ui/app_list/search/webstore_result.h
index 9704a13..8743cd5 100644
--- a/chrome/browser/ui/app_list/search/webstore_result.h
+++ b/chrome/browser/ui/app_list/search/webstore_result.h
@@ -9,30 +9,66 @@
 
 #include "base/basictypes.h"
 #include "base/memory/weak_ptr.h"
+#include "chrome/browser/extensions/install_observer.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
 #include "googleurl/src/gurl.h"
 
+class AppListControllerDelegate;
 class Profile;
 
+namespace extensions {
+class InstallTracker;
+}
+
 namespace app_list {
 
-class WebstoreResult : public ChromeSearchResult {
+class WebstoreResult : public ChromeSearchResult,
+                       public extensions::InstallObserver {
  public:
   WebstoreResult(Profile* profile,
                  const std::string& app_id,
                  const std::string& localized_name,
-                 const GURL& icon_url);
+                 const GURL& icon_url,
+                 AppListControllerDelegate* controller);
   virtual ~WebstoreResult();
 
   // ChromeSearchResult overides:
   virtual void Open(int event_flags) OVERRIDE;
   virtual void InvokeAction(int action_index, int event_flags) OVERRIDE;
   virtual scoped_ptr<ChromeSearchResult> Duplicate() OVERRIDE;
+  virtual ChromeSearchResultType GetType() OVERRIDE;
 
  private:
+  void UpdateActions();
   void SetDefaultDetails();
   void OnIconLoaded();
 
+  void StartInstall();
+  void InstallCallback(bool success, const std::string& error);
+
+  void StartObservingInstall();
+  void StopObservingInstall();
+
+  // extensions::InstallObserver overrides:
+  virtual void OnBeginExtensionInstall(const std::string& extension_id,
+                                       const std::string& extension_name,
+                                       const gfx::ImageSkia& installing_icon,
+                                       bool is_app,
+                                       bool is_platform_app) OVERRIDE;
+  virtual void OnDownloadProgress(const std::string& extension_id,
+                                  int percent_downloaded) OVERRIDE;
+  virtual void OnInstallFailure(const std::string& extension_id) OVERRIDE;
+  virtual void OnExtensionInstalled(
+      const extensions::Extension* extension) OVERRIDE;
+  virtual void OnExtensionUninstalled(
+      const extensions::Extension* extension) OVERRIDE;
+  virtual void OnExtensionDisabled(
+      const extensions::Extension* extension) OVERRIDE;
+  virtual void OnAppsReordered() OVERRIDE;
+  virtual void OnAppInstalledToAppList(
+      const std::string& extension_id) OVERRIDE;
+  virtual void OnShutdown() OVERRIDE;
+
   Profile* profile_;
   const std::string app_id_;
   const std::string localized_name_;
@@ -41,6 +77,9 @@
   gfx::ImageSkia icon_;
   base::WeakPtrFactory<WebstoreResult> weak_factory_;
 
+  AppListControllerDelegate* controller_;
+  extensions::InstallTracker* install_tracker_;  // Not owned.
+
   DISALLOW_COPY_AND_ASSIGN(WebstoreResult);
 };
 
diff --git a/chrome/browser/ui/app_modal_dialogs/javascript_app_modal_dialog.h b/chrome/browser/ui/app_modal_dialogs/javascript_app_modal_dialog.h
index 7ce8ac1..38153fc 100644
--- a/chrome/browser/ui/app_modal_dialogs/javascript_app_modal_dialog.h
+++ b/chrome/browser/ui/app_modal_dialogs/javascript_app_modal_dialog.h
@@ -9,7 +9,7 @@
 
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog.h"
 #include "content/public/browser/javascript_dialog_manager.h"
 
diff --git a/chrome/browser/ui/apps/chrome_shell_window_delegate.cc b/chrome/browser/ui/apps/chrome_shell_window_delegate.cc
new file mode 100644
index 0000000..255c416
--- /dev/null
+++ b/chrome/browser/ui/apps/chrome_shell_window_delegate.cc
@@ -0,0 +1,153 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/apps/chrome_shell_window_delegate.h"
+
+#include "base/strings/stringprintf.h"
+#include "chrome/browser/favicon/favicon_tab_helper.h"
+#include "chrome/browser/file_select_helper.h"
+#include "chrome/browser/media/media_capture_devices_dispatcher.h"
+#include "chrome/browser/platform_util.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_dialogs.h"
+#include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/browser_tabstrip.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/common/render_messages.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_view.h"
+
+#if defined(USE_ASH)
+#include "ash/launcher/launcher_types.h"
+#endif
+
+namespace chrome {
+
+namespace {
+
+bool disable_external_open_for_testing_ = false;
+
+class ShellWindowLinkDelegate : public content::WebContentsDelegate {
+ public:
+  ShellWindowLinkDelegate();
+
+ private:
+  virtual content::WebContents* OpenURLFromTab(
+      content::WebContents* source,
+      const content::OpenURLParams& params) OVERRIDE;
+
+  DISALLOW_COPY_AND_ASSIGN(ShellWindowLinkDelegate);
+};
+
+ShellWindowLinkDelegate::ShellWindowLinkDelegate() {}
+
+// TODO(rockot): Add a test that exercises this code. See
+// http://crbug.com/254260.
+content::WebContents* ShellWindowLinkDelegate::OpenURLFromTab(
+    content::WebContents* source,
+    const content::OpenURLParams& params) {
+  platform_util::OpenExternal(params.url);
+  delete source;
+  return NULL;
+}
+
+}  // namespace
+
+ChromeShellWindowDelegate::ChromeShellWindowDelegate() {}
+
+ChromeShellWindowDelegate::~ChromeShellWindowDelegate() {}
+
+void ChromeShellWindowDelegate::DisableExternalOpenForTesting() {
+  disable_external_open_for_testing_ = true;
+}
+
+void ChromeShellWindowDelegate::InitWebContents(
+    content::WebContents* web_contents) {
+  FaviconTabHelper::CreateForWebContents(web_contents);
+}
+
+content::WebContents* ChromeShellWindowDelegate::OpenURLFromTab(
+    Profile* profile,
+    content::WebContents* source,
+    const content::OpenURLParams& params) {
+  // Force all links to open in a new tab, even if they were trying to open a
+  // window.
+  chrome::NavigateParams new_tab_params(
+      static_cast<Browser*>(NULL), params.url, params.transition);
+  new_tab_params.disposition = params.disposition == NEW_BACKGROUND_TAB ?
+      params.disposition : NEW_FOREGROUND_TAB;
+  new_tab_params.initiating_profile = profile;
+  chrome::Navigate(&new_tab_params);
+
+  return new_tab_params.target_contents;
+}
+
+void ChromeShellWindowDelegate::AddNewContents(
+    Profile* profile,
+    content::WebContents* new_contents,
+    WindowOpenDisposition disposition,
+    const gfx::Rect& initial_pos,
+    bool user_gesture,
+    bool* was_blocked) {
+  if (!disable_external_open_for_testing_) {
+    new_contents->SetDelegate(new ShellWindowLinkDelegate());
+    return;
+  }
+  Browser* browser =
+      chrome::FindOrCreateTabbedBrowser(profile, chrome::GetActiveDesktop());
+  // Force all links to open in a new tab, even if they were trying to open a
+  // new window.
+  disposition =
+      disposition == NEW_BACKGROUND_TAB ? disposition : NEW_FOREGROUND_TAB;
+  chrome::AddWebContents(browser, NULL, new_contents, disposition, initial_pos,
+                         user_gesture, was_blocked);
+}
+
+content::ColorChooser* ChromeShellWindowDelegate::ShowColorChooser(
+    content::WebContents* web_contents,
+    SkColor initial_color) {
+  return chrome::ShowColorChooser(web_contents, initial_color);
+}
+
+void ChromeShellWindowDelegate::RunFileChooser(
+    content::WebContents* tab,
+    const content::FileChooserParams& params) {
+  FileSelectHelper::RunFileChooser(tab, params);
+}
+
+void ChromeShellWindowDelegate::RequestMediaAccessPermission(
+      content::WebContents* web_contents,
+      const content::MediaStreamRequest& request,
+      const content::MediaResponseCallback& callback,
+      const extensions::Extension* extension) {
+  MediaCaptureDevicesDispatcher::GetInstance()->ProcessMediaAccessRequest(
+      web_contents, request, callback, extension);
+}
+
+int ChromeShellWindowDelegate::PreferredIconSize() {
+#if defined(USE_ASH)
+  return ash::kLauncherPreferredSize;
+#else
+  return extension_misc::EXTENSION_ICON_SMALL;
+#endif
+}
+
+void ChromeShellWindowDelegate::SetWebContentsBlocked(
+    content::WebContents* web_contents,
+    bool blocked) {
+  // RenderViewHost may be NULL during shutdown.
+  content::RenderViewHost* host = web_contents->GetRenderViewHost();
+  if (host) {
+    host->Send(new ChromeViewMsg_SetVisuallyDeemphasized(
+        host->GetRoutingID(), blocked));
+  }
+}
+
+bool ChromeShellWindowDelegate::IsWebContentsVisible(
+    content::WebContents* web_contents) {
+  return platform_util::IsVisible(web_contents->GetView()->GetNativeView());
+}
+
+}  // namespace chrome
diff --git a/chrome/browser/ui/apps/chrome_shell_window_delegate.h b/chrome/browser/ui/apps/chrome_shell_window_delegate.h
new file mode 100644
index 0000000..4bad8b2
--- /dev/null
+++ b/chrome/browser/ui/apps/chrome_shell_window_delegate.h
@@ -0,0 +1,59 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_APPS_CHROME_SHELL_WINDOW_DELEGATE_H_
+#define CHROME_BROWSER_UI_APPS_CHROME_SHELL_WINDOW_DELEGATE_H_
+
+#include "apps/shell_window.h"
+#include "chrome/browser/profiles/profile.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_delegate.h"
+#include "ui/base/window_open_disposition.h"
+#include "ui/gfx/rect.h"
+
+namespace chrome {
+
+class ChromeShellWindowDelegate : public apps::ShellWindow::Delegate {
+ public:
+  ChromeShellWindowDelegate();
+  virtual ~ChromeShellWindowDelegate();
+
+  static void DisableExternalOpenForTesting();
+
+ private:
+  // apps::ShellWindow::Delegate:
+  virtual void InitWebContents(content::WebContents* web_contents) OVERRIDE;
+  virtual content::WebContents* OpenURLFromTab(
+      Profile* profile,
+      content::WebContents* source,
+      const content::OpenURLParams& params) OVERRIDE;
+  virtual void AddNewContents(Profile* profile,
+                              content::WebContents* new_contents,
+                              WindowOpenDisposition disposition,
+                              const gfx::Rect& initial_pos,
+                              bool user_gesture,
+                              bool* was_blocked) OVERRIDE;
+  virtual content::ColorChooser* ShowColorChooser(
+      content::WebContents* web_contents,
+      SkColor initial_color) OVERRIDE;
+  virtual void RunFileChooser(
+      content::WebContents* tab,
+      const content::FileChooserParams& params) OVERRIDE;
+  virtual void RequestMediaAccessPermission(
+      content::WebContents* web_contents,
+      const content::MediaStreamRequest& request,
+      const content::MediaResponseCallback& callback,
+      const extensions::Extension* extension) OVERRIDE;
+  virtual int PreferredIconSize() OVERRIDE;
+  virtual void SetWebContentsBlocked(content::WebContents* web_contents,
+                                     bool blocked) OVERRIDE;
+  virtual bool IsWebContentsVisible(
+      content::WebContents* web_contents) OVERRIDE;
+
+  DISALLOW_COPY_AND_ASSIGN(ChromeShellWindowDelegate);
+};
+
+}  // namespace chrome
+
+#endif  // CHROME_BROWSER_UI_APPS_CHROME_SHELL_WINDOW_DELEGATE_H_
diff --git a/chrome/browser/ui/ash/app_list/app_list_controller_ash.cc b/chrome/browser/ui/ash/app_list/app_list_controller_ash.cc
index a51a71a..7bf0587 100644
--- a/chrome/browser/ui/ash/app_list/app_list_controller_ash.cc
+++ b/chrome/browser/ui/ash/app_list/app_list_controller_ash.cc
@@ -39,7 +39,8 @@
   return ChromeLauncherController::instance()->CanPin();
 }
 
-bool AppListControllerDelegateAsh::CanShowCreateShortcutsDialog() {
+bool AppListControllerDelegateAsh::CanDoCreateShortcutsFlow(
+    bool is_platform_app) {
   return false;
 }
 
diff --git a/chrome/browser/ui/ash/app_list/app_list_controller_ash.h b/chrome/browser/ui/ash/app_list/app_list_controller_ash.h
index ad865f9..8df10a0 100644
--- a/chrome/browser/ui/ash/app_list/app_list_controller_ash.h
+++ b/chrome/browser/ui/ash/app_list/app_list_controller_ash.h
@@ -22,7 +22,7 @@
   virtual void PinApp(const std::string& extension_id) OVERRIDE;
   virtual void UnpinApp(const std::string& extension_id) OVERRIDE;
   virtual bool CanPin() OVERRIDE;
-  virtual bool CanShowCreateShortcutsDialog() OVERRIDE;
+  virtual bool CanDoCreateShortcutsFlow(bool is_platform_app) OVERRIDE;
   virtual void CreateNewWindow(Profile* profile, bool incognito) OVERRIDE;
   virtual void ActivateApp(Profile* profile,
                            const extensions::Extension* extension,
diff --git a/chrome/browser/ui/ash/app_sync_ui_state.h b/chrome/browser/ui/ash/app_sync_ui_state.h
index adad96a..55dc6c2 100644
--- a/chrome/browser/ui/ash/app_sync_ui_state.h
+++ b/chrome/browser/ui/ash/app_sync_ui_state.h
@@ -8,7 +8,7 @@
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "base/observer_list.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/sync/profile_sync_service_observer.h"
 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
 #include "content/public/browser/notification_observer.h"
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.cc b/chrome/browser/ui/ash/chrome_shell_delegate.cc
index 5b7cecc..c285804 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate.cc
+++ b/chrome/browser/ui/ash/chrome_shell_delegate.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/ui/ash/chrome_shell_delegate.h"
 
+#include "apps/shell_window.h"
 #include "ash/ash_switches.h"
 #include "ash/host/root_window_host_factory.h"
 #include "ash/launcher/launcher_types.h"
@@ -36,7 +37,6 @@
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/extensions/native_app_window.h"
-#include "chrome/browser/ui/extensions/shell_window.h"
 #include "chrome/browser/ui/host_desktop.h"
 #include "chrome/browser/ui/immersive_fullscreen_configuration.h"
 #include "chrome/common/chrome_notification_types.h"
@@ -159,17 +159,36 @@
   bool is_fullscreen = ash::wm::IsWindowFullscreen(window);
 
   // Windows which cannot be maximized should not be fullscreened.
-  if (is_fullscreen && !ash::wm::CanMaximizeWindow(window))
+  if (!is_fullscreen && !ash::wm::CanMaximizeWindow(window))
     return;
 
   Browser* browser = chrome::FindBrowserWithWindow(window);
   if (browser) {
-    chrome::ToggleFullscreenMode(browser);
+    // If a window is fullscreen, exit fullscreen.
+    if (is_fullscreen) {
+      chrome::ToggleFullscreenMode(browser);
+      return;
+    }
+
+    // AppNonClientFrameViewAsh shows only the window controls and no other
+    // window decorations which is pretty close to fullscreen. Put v1 apps
+    // into maximized mode instead of fullscreen to avoid showing the ugly
+    // fullscreen exit bubble.
+#if defined(OS_WIN)
+    if (browser->host_desktop_type() == chrome::HOST_DESKTOP_TYPE_NATIVE) {
+      chrome::ToggleFullscreenMode(browser);
+      return;
+    }
+#endif  // OS_WIN
+    if (browser->is_app() && browser->app_type() != Browser::APP_TYPE_CHILD)
+      ash::wm::ToggleMaximizedWindow(window);
+    else
+      chrome::ToggleFullscreenMode(browser);
     return;
   }
 
   // |window| may belong to a shell window.
-  ShellWindow* shell_window = extensions::ShellWindowRegistry::
+  apps::ShellWindow* shell_window = extensions::ShellWindowRegistry::
       GetShellWindowForNativeWindowAnyProfile(window);
   if (shell_window) {
     if (is_fullscreen)
@@ -185,13 +204,6 @@
   if (!window)
     return;
 
-  // TODO(pkotwicz): If immersive mode replaces fullscreen, bind fullscreen to
-  // F4 and find a different key binding for maximize.
-  if (ImmersiveFullscreenConfiguration::UseImmersiveFullscreen()) {
-    ToggleFullscreen();
-    return;
-  }
-
   // Get out of fullscreen when in fullscreen mode.
   if (ash::wm::IsWindowFullscreen(window)) {
     ToggleFullscreen();
@@ -226,7 +238,7 @@
 }
 
 void ChromeShellDelegate::ShowTaskManager() {
-  chrome::OpenTaskManager(NULL, false);
+  chrome::OpenTaskManager(NULL);
 }
 
 content::BrowserContext* ChromeShellDelegate::GetCurrentBrowserContext() {
@@ -244,10 +256,7 @@
 
 ash::LauncherDelegate* ChromeShellDelegate::CreateLauncherDelegate(
     ash::LauncherModel* model) {
-  // Defer Launcher creation until DefaultProfile is created.
-  if (!ProfileManager::IsGetDefaultProfileAllowed())
-    return NULL;
-
+  DCHECK(ProfileManager::IsGetDefaultProfileAllowed());
   // TODO(oshima): This is currently broken with multiple launchers.
   // Refactor so that there is just one launcher delegate in the
   // shell.
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate_browsertest.cc b/chrome/browser/ui/ash/chrome_shell_delegate_browsertest.cc
index 938d3f5..66a8927 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate_browsertest.cc
+++ b/chrome/browser/ui/ash/chrome_shell_delegate_browsertest.cc
@@ -4,16 +4,38 @@
 
 #include "chrome/browser/ui/ash/chrome_shell_delegate.h"
 
+#include "apps/shell_window.h"
 #include "ash/ash_switches.h"
 #include "ash/shell.h"
 #include "ash/shell_delegate.h"
+#include "ash/wm/window_properties.h"
 #include "ash/wm/window_util.h"
 #include "base/command_line.h"
+#include "chrome/browser/extensions/platform_app_browsertest_util.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/extensions/native_app_window.h"
 #include "chrome/browser/ui/immersive_fullscreen_configuration.h"
 #include "chrome/test/base/in_process_browser_test.h"
+#include "ui/aura/client/aura_constants.h"
+
+namespace {
+
+// Returns true if |window| is in immersive fullscreen. Infer whether |window|
+// is in immersive fullscreen based on whether kFullscreenUsesMinimalChromeKey
+// is set for |window| because DEPS does not allow the test to use BrowserView.
+// (This is not quite right because if a window is in both immersive browser
+// fullscreen and in tab fullscreen, kFullScreenUsesMinimalChromeKey will
+// not be set).
+bool IsInImmersiveFullscreen(BrowserWindow* browser_window) {
+  return browser_window->IsFullscreen() &&
+      browser_window->GetNativeWindow()->GetProperty(
+          ash::internal::kFullscreenUsesMinimalChromeKey);
+}
+
+}  // namespace
 
 typedef InProcessBrowserTest ChromeShellDelegateBrowserTest;
 
@@ -24,17 +46,6 @@
   aura::Window* window = ash::wm::GetActiveWindow();
   ASSERT_TRUE(window);
 
-  if (ImmersiveFullscreenConfiguration::UseImmersiveFullscreen()) {
-    // "ToggleMaximized" toggles immersive fullscreen.
-    EXPECT_FALSE(ash::wm::IsWindowMaximized(window));
-    EXPECT_FALSE(ash::wm::IsWindowFullscreen(window));
-    shell_delegate->ToggleMaximized();
-    EXPECT_TRUE(ash::wm::IsWindowFullscreen(window));
-    shell_delegate->ToggleMaximized();
-    EXPECT_FALSE(ash::wm::IsWindowFullscreen(window));
-    return;
-  }
-
   // When not in fullscreen, ShellDelegate::ToggleMaximized toggles Maximized.
   EXPECT_FALSE(ash::wm::IsWindowMaximized(window));
   shell_delegate->ToggleMaximized();
@@ -55,3 +66,126 @@
   EXPECT_FALSE(ash::wm::IsWindowFullscreen(window));
   EXPECT_TRUE(ash::wm::IsWindowMaximized(window));
 }
+
+// Confirm that toggling window fullscren works properly.
+IN_PROC_BROWSER_TEST_F(ChromeShellDelegateBrowserTest, ToggleFullscreen) {
+  ash::ShellDelegate* shell_delegate = ash::Shell::GetInstance()->delegate();
+  ASSERT_TRUE(shell_delegate);
+
+  // 1) ToggleFullscreen() should toggle whether a tabbed browser window is in
+  // immersive fullscreen.
+  ASSERT_TRUE(browser()->is_type_tabbed());
+  BrowserWindow* browser_window = browser()->window();
+  ASSERT_TRUE(browser_window->IsActive());
+  EXPECT_FALSE(browser_window->IsMaximized());
+  EXPECT_FALSE(browser_window->IsFullscreen());
+
+  shell_delegate->ToggleFullscreen();
+  EXPECT_TRUE(browser_window->IsFullscreen());
+  EXPECT_EQ(IsInImmersiveFullscreen(browser_window),
+      ImmersiveFullscreenConfiguration::UseImmersiveFullscreen());
+
+  shell_delegate->ToggleFullscreen();
+  EXPECT_FALSE(browser_window->IsMaximized());
+  EXPECT_FALSE(browser_window->IsFullscreen());
+
+  // 2) ToggleFullscreen() should have no effect on windows which cannot be
+  // maximized.
+  browser_window->GetNativeWindow()->SetProperty(aura::client::kCanMaximizeKey,
+                                                 false);
+  shell_delegate->ToggleFullscreen();
+  EXPECT_FALSE(browser_window->IsMaximized());
+  EXPECT_FALSE(browser_window->IsFullscreen());
+
+  // 3) ToggleFullscreen() should maximize v1 app browser windows which use
+  // AppNonClientFrameViewAsh.
+  // TODO(pkotwicz): Figure out if we actually want this behavior.
+  Browser::CreateParams browser_create_params(Browser::TYPE_POPUP,
+      browser()->profile(), chrome::HOST_DESKTOP_TYPE_NATIVE);
+#if defined(OS_WIN)
+  browser_create_params.host_desktop_type = chrome::HOST_DESKTOP_TYPE_ASH;
+#endif  // OS_WIN
+  browser_create_params.app_name = "Test";
+  browser_create_params.app_type = Browser::APP_TYPE_HOST;
+
+  Browser* app_host_browser = new Browser(browser_create_params);
+  ASSERT_TRUE(app_host_browser->is_app());
+  AddBlankTabAndShow(app_host_browser);
+  browser_window = app_host_browser->window();
+  ASSERT_TRUE(browser_window->IsActive());
+  EXPECT_FALSE(browser_window->IsMaximized());
+  EXPECT_FALSE(browser_window->IsFullscreen());
+
+  shell_delegate->ToggleFullscreen();
+  EXPECT_TRUE(browser_window->IsMaximized());
+
+  shell_delegate->ToggleFullscreen();
+  EXPECT_FALSE(browser_window->IsMaximized());
+  EXPECT_FALSE(browser_window->IsFullscreen());
+
+  // 4) ToggleFullscreen() should put child windows of v1 apps into
+  // non-immersive fullscreen.
+  browser_create_params.host_desktop_type = chrome::HOST_DESKTOP_TYPE_NATIVE;
+  browser_create_params.app_type = Browser::APP_TYPE_CHILD;
+  Browser* app_child_browser = new Browser(browser_create_params);
+  ASSERT_TRUE(app_child_browser->is_app());
+  AddBlankTabAndShow(app_child_browser);
+  browser_window = app_child_browser->window();
+  ASSERT_TRUE(browser_window->IsActive());
+  EXPECT_FALSE(browser_window->IsMaximized());
+  EXPECT_FALSE(browser_window->IsFullscreen());
+
+  shell_delegate->ToggleFullscreen();
+  EXPECT_TRUE(browser_window->IsFullscreen());
+  EXPECT_FALSE(IsInImmersiveFullscreen(browser_window));
+
+  shell_delegate->ToggleFullscreen();
+  EXPECT_FALSE(browser_window->IsMaximized());
+  EXPECT_FALSE(browser_window->IsFullscreen());
+
+  // 5) ToggleFullscreen() should put popup browser windows into non-immersive
+  // fullscreen.
+  browser_create_params.app_name = "";
+  Browser* popup_browser = new Browser(browser_create_params);
+  ASSERT_TRUE(popup_browser->is_type_popup());
+  ASSERT_FALSE(popup_browser->is_app());
+  AddBlankTabAndShow(popup_browser);
+  browser_window = popup_browser->window();
+  ASSERT_TRUE(browser_window->IsActive());
+  EXPECT_FALSE(browser_window->IsMaximized());
+  EXPECT_FALSE(browser_window->IsFullscreen());
+
+  shell_delegate->ToggleFullscreen();
+  EXPECT_TRUE(browser_window->IsFullscreen());
+  EXPECT_FALSE(IsInImmersiveFullscreen(browser_window));
+
+  shell_delegate->ToggleFullscreen();
+  EXPECT_FALSE(browser_window->IsMaximized());
+  EXPECT_FALSE(browser_window->IsFullscreen());
+}
+
+typedef extensions::PlatformAppBrowserTest
+    ChromeShellDelegatePlatformAppBrowserTest;
+
+// Test that ToggleFullscreen() toggles the platform app's fullscreen state.
+IN_PROC_BROWSER_TEST_F(ChromeShellDelegatePlatformAppBrowserTest,
+                       ToggleFullscreenPlatformApp) {
+  ash::ShellDelegate* shell_delegate = ash::Shell::GetInstance()->delegate();
+  ASSERT_TRUE(shell_delegate);
+
+  const extensions::Extension* extension = LoadAndLaunchPlatformApp("minimal");
+  apps::ShellWindow* shell_window = CreateShellWindow(extension);
+  NativeAppWindow* app_window = shell_window->GetBaseWindow();
+  ASSERT_TRUE(shell_window->GetBaseWindow()->IsActive());
+  EXPECT_FALSE(app_window->IsMaximized());
+  EXPECT_FALSE(app_window->IsFullscreen());
+
+  shell_delegate->ToggleFullscreen();
+  EXPECT_TRUE(app_window->IsFullscreen());
+
+  shell_delegate->ToggleFullscreen();
+  EXPECT_FALSE(app_window->IsMaximized());
+  EXPECT_FALSE(app_window->IsFullscreen());
+
+  CloseShellWindow(shell_window);
+}
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate_chromeos.cc b/chrome/browser/ui/ash/chrome_shell_delegate_chromeos.cc
index f13d629..09becbb 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate_chromeos.cc
+++ b/chrome/browser/ui/ash/chrome_shell_delegate_chromeos.cc
@@ -29,7 +29,6 @@
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/extensions/application_launch.h"
 #include "chrome/browser/ui/extensions/native_app_window.h"
-#include "chrome/browser/ui/extensions/shell_window.h"
 #include "chrome/browser/ui/webui/chrome_web_contents_handler.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "chrome/common/chrome_switches.h"
diff --git a/chrome/browser/ui/ash/event_rewriter.cc b/chrome/browser/ui/ash/event_rewriter.cc
index 76eea61..7f54cdf 100644
--- a/chrome/browser/ui/ash/event_rewriter.cc
+++ b/chrome/browser/ui/ash/event_rewriter.cc
@@ -27,6 +27,7 @@
 
 #include "base/chromeos/chromeos_version.h"
 #include "base/command_line.h"
+#include "chrome/browser/chromeos/keyboard_driven_event_rewriter.h"
 #include "chrome/browser/chromeos/login/login_display_host_impl.h"
 #include "chrome/browser/chromeos/login/user_manager.h"
 #include "chrome/browser/chromeos/xinput_hierarchy_changed_event_listener.h"
@@ -129,7 +130,6 @@
       chromeos::input_method::InputMethodManager::Get();
   return manager->GetCurrentInputMethod().id() == kNeo2LayoutId ||
       manager->GetCurrentInputMethod().id() == kCaMultixLayoutId;
-
 }
 #endif
 
@@ -146,6 +146,8 @@
     : last_device_id_(kBadDeviceId),
 #if defined(OS_CHROMEOS)
       xkeyboard_(NULL),
+      keyboard_driven_event_rewritter_(
+          new chromeos::KeyboardDrivenEventRewriter),
 #endif
       pref_service_(NULL) {
   // The ash shell isn't instantiated for our unit tests.
@@ -352,6 +354,11 @@
   // crbug.com/136465.
   if (event->native_event()->xkey.send_event)
     return;
+
+  // Keyboard driven rewriting needs to happen before RewriteExtendedKeys
+  // to handle Ctrl+Alt+Shift+(Up | Down) so that they are not translated
+  // to Home/End.
+  keyboard_driven_event_rewritter_->RewriteIfKeyboardDrivenOnLoginScreen(event);
 #endif
   RewriteModifiers(event);
   RewriteNumPadKeys(event);
@@ -449,11 +456,11 @@
   // restart chrome process. In future this is to be changed.
   // TODO(glotov): remove the following condition when we do not restart chrome
   // when user logs in as guest.
- #if defined(OS_CHROMEOS)
-   if (chromeos::UserManager::Get()->IsLoggedInAsGuest() &&
-       chromeos::LoginDisplayHostImpl::default_host())
-     return false;
- #endif  // defined(OS_CHROMEOS)
+#if defined(OS_CHROMEOS)
+  if (chromeos::UserManager::Get()->IsLoggedInAsGuest() &&
+      chromeos::LoginDisplayHostImpl::default_host())
+    return false;
+#endif  // defined(OS_CHROMEOS)
   const PrefService* pref_service =
       pref_service_ ? pref_service_ : GetPrefService();
   if (!pref_service)
diff --git a/chrome/browser/ui/ash/event_rewriter.h b/chrome/browser/ui/ash/event_rewriter.h
index f6add25..b819a00 100644
--- a/chrome/browser/ui/ash/event_rewriter.h
+++ b/chrome/browser/ui/ash/event_rewriter.h
@@ -12,6 +12,7 @@
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "base/containers/hash_tables.h"
+#include "base/memory/scoped_ptr.h"
 #include "ui/aura/root_window_observer.h"
 #include "ui/base/keycodes/keyboard_codes.h"
 
@@ -27,6 +28,9 @@
 
 #if defined(OS_CHROMEOS)
 namespace chromeos {
+
+class KeyboardDrivenEventRewriter;
+
 namespace input_method {
 class XKeyboard;
 }
@@ -209,6 +213,9 @@
   base::hash_map<unsigned long, unsigned long> keysym_to_keycode_map_;
 
   chromeos::input_method::XKeyboard* xkeyboard_;  // for testing.
+
+  scoped_ptr<chromeos::KeyboardDrivenEventRewriter>
+      keyboard_driven_event_rewritter_;
 #endif
 
   const PrefService* pref_service_;  // for testing.
diff --git a/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.cc b/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.cc
index 46cf429..fc743d6 100644
--- a/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.cc
+++ b/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.cc
@@ -28,6 +28,13 @@
 
 using extensions::Extension;
 
+namespace {
+
+// The time delta between clicks in which clicks to launch V2 apps are ignored.
+const int kClickSuppressionInMS = 1000;
+
+}  // namespace
+
 // Item controller for an app shortcut. Shortcuts track app and launcher ids,
 // but do not have any associated windows (opening a shortcut will replace the
 // item with the appropriate LauncherItemController type).
@@ -88,12 +95,17 @@
 void AppShortcutLauncherItemController::Activate() {
   content::WebContents* content = GetLRUApplication();
   if (!content) {
-    // The initial launch of a V2 app will be done by this controller. Starting
-    // a hosted application takes time and if the user clicks fast, he can come
-    // here multiple times before the ShellLauncherItemController takes control.
-    // To avoid that situation we check for running applications.
-    if (!IsV2AppAndRunning())
-      Launch(ui::EF_NONE);
+    if (IsV2App()) {
+      // Ideally we come here only once. After that ShellLauncherItemController
+      // will take over when the shell window gets opened. However there are
+      // apps which take a lot of time for pre-processing (like the files app)
+      // before they open a window. Since there is currently no other way to
+      // detect if an app was started we suppress any further clicks within a
+      // special time out.
+      if (!AllowNextLaunchAttempt())
+        return;
+    }
+    Launch(ui::EF_NONE);
     return;
   }
   ActivateContent(content);
@@ -282,12 +294,17 @@
   return false;
 }
 
-bool AppShortcutLauncherItemController::IsV2AppAndRunning() {
-  const Extension* extension =
-      app_controller_->GetExtensionForAppID(app_id());
-  extensions::ExtensionSystem* extension_system =
-      extensions::ExtensionSystem::Get(app_controller_->profile());
-  return extension && extension->is_platform_app() && extension_system &&
-         extension_system->process_manager()->GetBackgroundHostForExtension(
-             app_id());
+bool AppShortcutLauncherItemController::IsV2App() {
+  const Extension* extension = app_controller_->GetExtensionForAppID(app_id());
+  return extension && extension->is_platform_app();
+}
+
+bool AppShortcutLauncherItemController::AllowNextLaunchAttempt() {
+  if (last_launch_attempt_.is_null() ||
+      last_launch_attempt_ + base::TimeDelta::FromMilliseconds(
+          kClickSuppressionInMS) < base::Time::Now()) {
+    last_launch_attempt_ = base::Time::Now();
+    return true;
+  }
+  return false;
 }
diff --git a/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.h b/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.h
index be7a5ed..49a2e7b 100644
--- a/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.h
+++ b/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.h
@@ -7,6 +7,7 @@
 
 #include <string>
 
+#include "base/time/time.h"
 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app.h"
 #include "chrome/browser/ui/ash/launcher/launcher_item_controller.h"
 
@@ -71,12 +72,19 @@
   // will return true if it has sucessfully advanced.
   bool AdvanceToNextApp();
 
-  // Returns true if the application is a V2 app and it is running.
-  bool IsV2AppAndRunning();
+  // Returns true if the application is a V2 app.
+  bool IsV2App();
+
+  // Returns true if it is allowed to try starting a V2 app again.
+  bool AllowNextLaunchAttempt();
 
   GURL refocus_url_;
   ChromeLauncherControllerPerApp* app_controller_;
 
+  // Since V2 applications can be undetectable after launching, this timer is
+  // keeping track of the last launch attempt.
+  base::Time last_launch_attempt_;
+
   DISALLOW_COPY_AND_ASSIGN(AppShortcutLauncherItemController);
 };
 
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc
index e584338..8bcd379 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
 
+#include "apps/shell_window.h"
 #include "ash/ash_switches.h"
 #include "ash/launcher/launcher.h"
 #include "ash/launcher/launcher_model.h"
@@ -29,7 +30,6 @@
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/extensions/application_launch.h"
 #include "chrome/browser/ui/extensions/native_app_window.h"
-#include "chrome/browser/ui/extensions/shell_window.h"
 #include "chrome/browser/ui/host_desktop.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/chrome_notification_types.h"
@@ -43,6 +43,7 @@
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/window.h"
 
+using apps::ShellWindow;
 using extensions::Extension;
 using content::WebContents;
 
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app.cc
index 3425019..8c1220d 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app.cc
@@ -326,10 +326,18 @@
     const std::string& app_id,
     ash::LauncherItemStatus status) {
   CHECK(controller);
+  int index = 0;
+  // Panels are inserted on the left so as not to push all existing panels over.
+  if (controller->GetLauncherItemType() != ash::TYPE_APP_PANEL) {
+    index = model_->item_count();
+    // For the alternate shelf layout increment the index (after the app icon)
+    if (ash::switches::UseAlternateShelfLayout())
+      ++index;
+  }
   return InsertAppLauncherItem(controller,
                                app_id,
                                status,
-                               model_->item_count(),
+                               index,
                                controller->GetLauncherItemType());
 }
 
@@ -1390,13 +1398,19 @@
   // of iterators because of model mutations as part of the loop.
   std::vector<std::string>::const_iterator pref_app_id(pinned_apps.begin());
   int index = 0;
-  for (; index < model_->item_count() && pref_app_id != pinned_apps.end();
-       ++index) {
+  int max_index = model_->item_count();
+  // Using the alternate shelf layout the App Icon should be the first item in
+  // the list thus start adding items at slot 1 (instead of slot 0).
+  if(ash::switches::UseAlternateShelfLayout()) {
+    ++index;
+    ++max_index;
+  }
+  for (; index < max_index && pref_app_id != pinned_apps.end(); ++index) {
     // If the next app launcher according to the pref is present in the model,
     // delete all app launcher entries in between.
     if (*pref_app_id == extension_misc::kChromeAppId ||
         IsAppPinned(*pref_app_id)) {
-      for (; index < model_->item_count(); ++index) {
+      for (; index < max_index; ++index) {
         const ash::LauncherItem& item(model_->items()[index]);
         if (item.type != ash::TYPE_APP_SHORTCUT &&
             item.type != ash::TYPE_BROWSER_SHORTCUT)
@@ -1418,13 +1432,14 @@
             MoveItemWithoutPinnedStateChangeNotification(index, index + 1);
           } else {
             LauncherItemClosed(item.id);
+            --max_index;
           }
           --index;
         }
       }
       // If the item wasn't found, that means id_to_item_controller_map_
       // is out of sync.
-      DCHECK(index < model_->item_count());
+      DCHECK(index < max_index);
     } else {
       // This app wasn't pinned before, insert a new entry.
       ash::LauncherID id = CreateAppShortcutLauncherItem(*pref_app_id, index);
@@ -1631,6 +1646,9 @@
   size_t index = profile_->GetPrefs()->GetInteger(prefs::kShelfChromeIconIndex);
   const base::ListValue* pinned_apps_pref =
       profile_->GetPrefs()->GetList(prefs::kPinnedLauncherApps);
+  if (ash::switches::UseAlternateShelfLayout())
+    return std::max(static_cast<size_t>(1),
+                    std::min(pinned_apps_pref->GetSize(), index));
   return std::max(static_cast<size_t>(0),
                   std::min(pinned_apps_pref->GetSize(), index));
 }
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app_browsertest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app_browsertest.cc
index b31c8a7..621d225 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app_browsertest.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app_browsertest.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
 
+#include "apps/shell_window.h"
 #include "ash/ash_switches.h"
 #include "ash/display/display_controller.h"
 #include "ash/launcher/launcher.h"
@@ -35,7 +36,6 @@
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/extensions/application_launch.h"
 #include "chrome/browser/ui/extensions/native_app_window.h"
-#include "chrome/browser/ui/extensions/shell_window.h"
 #include "chrome/browser/ui/host_desktop.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/chrome_notification_types.h"
@@ -51,6 +51,7 @@
 #include "ui/aura/window.h"
 #include "ui/base/events/event.h"
 
+using apps::ShellWindow;
 using extensions::Extension;
 using content::WebContents;
 
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app_unittest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app_unittest.cc
index 7163777..c5516c8 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app_unittest.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app_unittest.cc
@@ -64,18 +64,22 @@
   // LauncherModelObserver
   virtual void LauncherItemAdded(int index) OVERRIDE {
     ++added_;
+    last_index_ = index;
   }
 
   virtual void LauncherItemRemoved(int index, ash::LauncherID id) OVERRIDE {
     ++removed_;
+    last_index_ = index;
   }
 
   virtual void LauncherItemChanged(int index,
                                    const ash::LauncherItem& old_item) OVERRIDE {
     ++changed_;
+    last_index_ = index;
   }
 
   virtual void LauncherItemMoved(int start_index, int target_index) OVERRIDE {
+    last_index_ = target_index;
   }
 
   virtual void LauncherStatusChanged() OVERRIDE {
@@ -85,16 +89,19 @@
     added_ = 0;
     removed_ = 0;
     changed_ = 0;
+    last_index_ = 0;
   }
 
   int added() const { return added_; }
   int removed() const { return removed_; }
   int changed() const { return changed_; }
+  int last_index() const { return last_index_; }
 
  private:
   int added_;
   int removed_;
   int changed_;
+  int last_index_;
 
   DISALLOW_COPY_AND_ASSIGN(TestLauncherModelObserver);
 };
@@ -1061,6 +1068,7 @@
       launcher_controller_.get());
   ash::LauncherID launcher_id1 = launcher_controller_->CreateAppLauncherItem(
       &app_panel_controller, app_id, ash::STATUS_RUNNING);
+  int panel_index = model_observer_->last_index();
   EXPECT_EQ(2, model_observer_->added());
   EXPECT_EQ(0, model_observer_->changed());
   EXPECT_EQ(1, app_icon_loader->fetch_count());
@@ -1074,9 +1082,19 @@
   gfx::ImageSkia image;
   launcher_controller_->SetAppImage(app_id, image);
   EXPECT_EQ(0, model_observer_->changed());
+  model_observer_->clear_counts();
 
+  // Add a second app panel and verify that it get the same index as the first
+  // one had, being added to the left of the existing panel.
+  ash::LauncherID launcher_id2 = launcher_controller_->CreateAppLauncherItem(
+      &app_panel_controller, app_id, ash::STATUS_RUNNING);
+  EXPECT_EQ(panel_index, model_observer_->last_index());
+  EXPECT_EQ(1, model_observer_->added());
+  model_observer_->clear_counts();
+
+  launcher_controller_->CloseLauncherItem(launcher_id2);
   launcher_controller_->CloseLauncherItem(launcher_id1);
-  EXPECT_EQ(1, model_observer_->removed());
+  EXPECT_EQ(2, model_observer_->removed());
 }
 
 // Tests that the Gmail extension matches more then the app itself claims with
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_browser.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_browser.cc
index 1bc7d35..447ab1d 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_browser.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_browser.cc
@@ -6,6 +6,7 @@
 
 #include <vector>
 
+#include "ash/ash_switches.h"
 #include "ash/launcher/launcher_model.h"
 #include "ash/root_window_controller.h"
 #include "ash/shelf/shelf_layout_manager.h"
@@ -383,8 +384,15 @@
     const std::string& app_id,
     ash::LauncherItemStatus status) {
   DCHECK(controller);
-  return InsertAppLauncherItem(controller, app_id, status,
-                               model_->item_count());
+  int index = 0;
+  // Panels are inserted on the left so as not to push all existing panels over.
+  if (controller->GetLauncherItemType() != ash::TYPE_APP_PANEL) {
+    index = model_->item_count();
+    // For the alternate shelf layout increment index (insert after app icon).
+    if (ash::switches::UseAlternateShelfLayout())
+      ++index;
+  }
+  return InsertAppLauncherItem(controller, app_id, status, index);
 }
 
 void ChromeLauncherControllerPerBrowser::SetItemStatus(
@@ -1227,6 +1235,11 @@
   // of iterators because of model mutations as part of the loop.
   std::vector<std::string>::const_iterator pref_app_id(pinned_apps.begin());
   int index = 0;
+  int max_index = model_->item_count();
+  if (ash::switches::UseAlternateShelfLayout()) {
+    ++index;
+    ++max_index;
+  }
   for (; index < model_->item_count() && pref_app_id != pinned_apps.end();
        ++index) {
     // If the next app launcher according to the pref is present in the model,
@@ -1255,6 +1268,7 @@
             MoveItemWithoutPinnedStateChangeNotification(index, index + 1);
           } else {
             LauncherItemClosed(item.id);
+            --max_index;
           }
           --index;
         }
@@ -1427,6 +1441,9 @@
   size_t index = profile_->GetPrefs()->GetInteger(prefs::kShelfChromeIconIndex);
   const base::ListValue* pinned_apps_pref =
   profile_->GetPrefs()->GetList(prefs::kPinnedLauncherApps);
+  if (ash::switches::UseAlternateShelfLayout())
+    return std::max(static_cast<size_t>(1),
+                    std::min(pinned_apps_pref->GetSize(), index));
   return std::max(static_cast<size_t>(0),
                   std::min(pinned_apps_pref->GetSize(), index));
 }
diff --git a/chrome/browser/ui/ash/launcher/launcher_favicon_loader.cc b/chrome/browser/ui/ash/launcher/launcher_favicon_loader.cc
index 051e468..ce196e4 100644
--- a/chrome/browser/ui/ash/launcher/launcher_favicon_loader.cc
+++ b/chrome/browser/ui/ash/launcher/launcher_favicon_loader.cc
@@ -110,7 +110,11 @@
     if (pending_requests_.find(*iter) != pending_requests_.end())
       continue;  // Skip already pending downloads.
     pending_requests_.insert(*iter);
-    web_contents_->DownloadImage(*iter, true, 0,
+    web_contents_->DownloadImage(
+        *iter,
+        true,  // is a favicon
+        0,     // no preferred size
+        0,     // no maximum size
         base::Bind(&FaviconBitmapHandler::DidDownloadFavicon,
                    weak_ptr_factory_.GetWeakPtr()));
   }
diff --git a/chrome/browser/ui/ash/launcher/shell_window_launcher_controller.cc b/chrome/browser/ui/ash/launcher/shell_window_launcher_controller.cc
index ffad984..779a8f9 100644
--- a/chrome/browser/ui/ash/launcher/shell_window_launcher_controller.cc
+++ b/chrome/browser/ui/ash/launcher/shell_window_launcher_controller.cc
@@ -4,15 +4,17 @@
 
 #include "chrome/browser/ui/ash/launcher/shell_window_launcher_controller.h"
 
+#include "apps/shell_window.h"
 #include "ash/shell.h"
 #include "ash/wm/window_util.h"
 #include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
 #include "chrome/browser/ui/ash/launcher/shell_window_launcher_item_controller.h"
-#include "chrome/browser/ui/extensions/shell_window.h"
 #include "ui/aura/client/activation_client.h"
 
+using apps::ShellWindow;
+
 namespace {
 
 std::string GetAppLauncherId(ShellWindow* shell_window) {
diff --git a/chrome/browser/ui/ash/launcher/shell_window_launcher_controller.h b/chrome/browser/ui/ash/launcher/shell_window_launcher_controller.h
index 9c279f6..c47c357 100644
--- a/chrome/browser/ui/ash/launcher/shell_window_launcher_controller.h
+++ b/chrome/browser/ui/ash/launcher/shell_window_launcher_controller.h
@@ -13,6 +13,10 @@
 #include "ui/aura/client/activation_change_observer.h"
 #include "ui/aura/window_observer.h"
 
+namespace apps {
+class ShellWindow;
+}
+
 namespace aura {
 
 class Window;
@@ -24,7 +28,6 @@
 }
 
 class ChromeLauncherController;
-class ShellWindow;
 class ShellWindowLauncherItemController;
 
 // ShellWindowLauncherController observes the Shell Window registry and the
@@ -39,9 +42,10 @@
   virtual ~ShellWindowLauncherController();
 
   // Overridden from ShellWindowRegistry::Observer:
-  virtual void OnShellWindowAdded(ShellWindow* shell_window) OVERRIDE;
-  virtual void OnShellWindowIconChanged(ShellWindow* shell_window) OVERRIDE;
-  virtual void OnShellWindowRemoved(ShellWindow* shell_window) OVERRIDE;
+  virtual void OnShellWindowAdded(apps::ShellWindow* shell_window) OVERRIDE;
+  virtual void OnShellWindowIconChanged(
+      apps::ShellWindow* shell_window) OVERRIDE;
+  virtual void OnShellWindowRemoved(apps::ShellWindow* shell_window) OVERRIDE;
 
   // Overriden from aura::WindowObserver:
   virtual void OnWindowDestroying(aura::Window* window) OVERRIDE;
diff --git a/chrome/browser/ui/ash/launcher/shell_window_launcher_item_controller.cc b/chrome/browser/ui/ash/launcher/shell_window_launcher_item_controller.cc
index 276f899..703a8e5 100644
--- a/chrome/browser/ui/ash/launcher/shell_window_launcher_item_controller.cc
+++ b/chrome/browser/ui/ash/launcher/shell_window_launcher_item_controller.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/ui/ash/launcher/shell_window_launcher_item_controller.h"
 
+#include "apps/shell_window.h"
 #include "ash/wm/window_properties.h"
 #include "ash/wm/window_util.h"
 #include "chrome/browser/ui/ash/launcher/chrome_launcher_app_menu_item.h"
@@ -12,13 +13,14 @@
 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app.h"
 #include "chrome/browser/ui/ash/launcher/launcher_item_controller.h"
 #include "chrome/browser/ui/extensions/native_app_window.h"
-#include "chrome/browser/ui/extensions/shell_window.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/window.h"
 #include "ui/base/events/event.h"
 #include "ui/views/corewm/window_animations.h"
 
+using apps::ShellWindow;
+
 namespace {
 
 // Functor for std::find_if used in AppLauncherItemController.
diff --git a/chrome/browser/ui/ash/launcher/shell_window_launcher_item_controller.h b/chrome/browser/ui/ash/launcher/shell_window_launcher_item_controller.h
index 182ca98..acf4308 100644
--- a/chrome/browser/ui/ash/launcher/shell_window_launcher_item_controller.h
+++ b/chrome/browser/ui/ash/launcher/shell_window_launcher_item_controller.h
@@ -13,6 +13,10 @@
 #include "chrome/browser/ui/ash/launcher/launcher_item_controller.h"
 #include "ui/aura/window_observer.h"
 
+namespace apps {
+class ShellWindow;
+}
+
 namespace aura {
 class Window;
 }
@@ -22,7 +26,6 @@
 }
 
 class ChromeLauncherController;
-class ShellWindow;
 
 // This is a ShellWindowItemLauncherController for shell windows. There is one
 // instance per app, per launcher id.
@@ -42,7 +45,7 @@
 
   virtual ~ShellWindowLauncherItemController();
 
-  void AddShellWindow(ShellWindow* shell_window,
+  void AddShellWindow(apps::ShellWindow* shell_window,
                       ash::LauncherItemStatus status);
 
   void RemoveShellWindowForWindow(aura::Window* window);
@@ -79,19 +82,19 @@
   void ActivateIndexedApp(size_t index);
 
  private:
-  typedef std::list<ShellWindow*> ShellWindowList;
+  typedef std::list<apps::ShellWindow*> ShellWindowList;
 
-  void ShowAndActivateOrMinimize(ShellWindow* shell_window);
+  void ShowAndActivateOrMinimize(apps::ShellWindow* shell_window);
 
   // Activate the given |window_to_show|, or - if already selected - advance to
   // the next window of similar type.
-  void ActivateOrAdvanceToNextShellWindow(ShellWindow* window_to_show);
+  void ActivateOrAdvanceToNextShellWindow(apps::ShellWindow* window_to_show);
 
   // List of associated shell windows
   ShellWindowList shell_windows_;
 
   // Pointer to the most recently active shell window
-  ShellWindow* last_active_shell_window_;
+  apps::ShellWindow* last_active_shell_window_;
 
   // The launcher id associated with this set of windows. There is one
   // AppLauncherItemController for each |app_launcher_id_|.
diff --git a/chrome/browser/ui/ash/screenshot_taker.cc b/chrome/browser/ui/ash/screenshot_taker.cc
index 5d2f7e2..a73c4b5 100644
--- a/chrome/browser/ui/ash/screenshot_taker.cc
+++ b/chrome/browser/ui/ash/screenshot_taker.cc
@@ -15,7 +15,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/sequenced_worker_pool.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/download/download_prefs.h"
 #include "chrome/browser/notifications/notification_ui_manager.h"
@@ -355,7 +355,8 @@
   // TODO(sschmitz): make this work for Windows.
   DesktopNotificationService* const service =
       DesktopNotificationServiceFactory::GetForProfile(GetProfile());
-  if (service->IsSystemComponentEnabled(message_center::Notifier::SCREENSHOT)) {
+  if (service->IsNotifierEnabled(
+          message_center::NotifierId(message_center::NotifierId::SCREENSHOT))) {
     scoped_ptr<Notification> notification(
         CreateNotification(screenshot_result, screenshot_path));
     g_browser_process->notification_ui_manager()->Add(*notification,
diff --git a/chrome/browser/ui/ash/screenshot_taker.h b/chrome/browser/ui/ash/screenshot_taker.h
index ecab08d..5411719 100644
--- a/chrome/browser/ui/ash/screenshot_taker.h
+++ b/chrome/browser/ui/ash/screenshot_taker.h
@@ -12,7 +12,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/notifications/notification.h"
 
 class Profile;
diff --git a/chrome/browser/ui/ash/session_state_delegate_chromeos.cc b/chrome/browser/ui/ash/session_state_delegate_chromeos.cc
index a44c892..faba973 100644
--- a/chrome/browser/ui/ash/session_state_delegate_chromeos.cc
+++ b/chrome/browser/ui/ash/session_state_delegate_chromeos.cc
@@ -44,8 +44,7 @@
   if (!CanLockScreen())
     return;
 
-  // TODO(antrim): Additional logging for http://crbug.com/173178.
-  LOG(WARNING) << "Requesting screen lock from SessionStateDelegate";
+  VLOG(1) << "Requesting screen lock from SessionStateDelegate";
   chromeos::DBusThreadManager::Get()->GetSessionManagerClient()->
       RequestLockScreen();
 }
diff --git a/chrome/browser/ui/aura/active_desktop_monitor.cc b/chrome/browser/ui/aura/active_desktop_monitor.cc
index c30cb2d..411aa3e 100644
--- a/chrome/browser/ui/aura/active_desktop_monitor.cc
+++ b/chrome/browser/ui/aura/active_desktop_monitor.cc
@@ -16,8 +16,9 @@
 // static
 ActiveDesktopMonitor* ActiveDesktopMonitor::g_instance_ = NULL;
 
-ActiveDesktopMonitor::ActiveDesktopMonitor()
-    : last_activated_desktop_(chrome::HOST_DESKTOP_TYPE_NATIVE) {
+ActiveDesktopMonitor::ActiveDesktopMonitor(
+    chrome::HostDesktopType initial_desktop)
+    : last_activated_desktop_(initial_desktop) {
   DCHECK(!g_instance_);
   g_instance_ = this;
   aura::Env::GetInstance()->AddObserver(this);
diff --git a/chrome/browser/ui/aura/active_desktop_monitor.h b/chrome/browser/ui/aura/active_desktop_monitor.h
index ff63984..1ae149b 100644
--- a/chrome/browser/ui/aura/active_desktop_monitor.h
+++ b/chrome/browser/ui/aura/active_desktop_monitor.h
@@ -14,7 +14,9 @@
 // RootWindowHost activations.
 class ActiveDesktopMonitor : public aura::EnvObserver {
  public:
-  ActiveDesktopMonitor();
+  // Constructs an ActiveDesktopMonitor which initially uses |initial_desktop|
+  // as the |last_activated_desktop_| until a root window is activated.
+  explicit ActiveDesktopMonitor(chrome::HostDesktopType initial_desktop);
   virtual ~ActiveDesktopMonitor();
 
   // Returns the host desktop type of the most-recently activated
diff --git a/chrome/browser/ui/aura/chrome_browser_main_extra_parts_aura.cc b/chrome/browser/ui/aura/chrome_browser_main_extra_parts_aura.cc
index 7a65e25..eb922f9 100644
--- a/chrome/browser/ui/aura/chrome_browser_main_extra_parts_aura.cc
+++ b/chrome/browser/ui/aura/chrome_browser_main_extra_parts_aura.cc
@@ -7,6 +7,7 @@
 #include "chrome/browser/chrome_browser_main.h"
 #include "chrome/browser/toolkit_extra_parts.h"
 #include "chrome/browser/ui/aura/active_desktop_monitor.h"
+#include "chrome/browser/ui/host_desktop.h"
 #include "ui/aura/env.h"
 #include "ui/gfx/screen.h"
 #include "ui/views/widget/desktop_aura/desktop_screen.h"
@@ -20,7 +21,27 @@
 
 #if defined(USE_ASH)
 #include "chrome/browser/ui/ash/ash_init.h"
+#if defined(OS_WIN)
+#include "base/command_line.h"
+#include "chrome/common/chrome_switches.h"
+#endif  // defined(OS_WIN)
+#endif  // defined(USE_ASH)
+
+namespace {
+
+// Returns the desktop this process was initially launched in.
+chrome::HostDesktopType GetInitialDesktop() {
+#if defined(OS_WIN) && defined(USE_ASH)
+  const CommandLine* command_line = CommandLine::ForCurrentProcess();
+  if (command_line->HasSwitch(switches::kViewerConnect) ||
+      command_line->HasSwitch(switches::kViewerLaunchViaAppId)) {
+    return chrome::HOST_DESKTOP_TYPE_ASH;
+  }
 #endif
+  return chrome::HOST_DESKTOP_TYPE_NATIVE;
+}
+
+}  // namespace
 
 ChromeBrowserMainExtraPartsAura::ChromeBrowserMainExtraPartsAura() {
 }
@@ -31,7 +52,7 @@
 void ChromeBrowserMainExtraPartsAura::ToolkitInitialized() {
 #if !defined(OS_CHROMEOS)
 #if defined(USE_ASH)
-  active_desktop_monitor_.reset(new ActiveDesktopMonitor);
+  active_desktop_monitor_.reset(new ActiveDesktopMonitor(GetInitialDesktop()));
   if (!chrome::ShouldOpenAshOnStartup())
 #endif
   {
diff --git a/chrome/browser/ui/aura/tab_contents/web_drag_bookmark_handler_aura.cc b/chrome/browser/ui/aura/tab_contents/web_drag_bookmark_handler_aura.cc
index b43eab5..7ea3102 100644
--- a/chrome/browser/ui/aura/tab_contents/web_drag_bookmark_handler_aura.cc
+++ b/chrome/browser/ui/aura/tab_contents/web_drag_bookmark_handler_aura.cc
@@ -11,7 +11,6 @@
 #include "chrome/browser/ui/bookmarks/bookmark_tab_helper.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/base/dragdrop/os_exchange_data.h"
-#include "webkit/common/webdropdata.h"
 
 using content::WebContents;
 
diff --git a/chrome/browser/ui/auto_login_infobar_delegate.cc b/chrome/browser/ui/auto_login_infobar_delegate.cc
index e075c7a..2cb853a 100644
--- a/chrome/browser/ui/auto_login_infobar_delegate.cc
+++ b/chrome/browser/ui/auto_login_infobar_delegate.cc
@@ -16,7 +16,7 @@
 #include "chrome/browser/infobars/infobar_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/ubertoken_fetcher.h"
-#include "chrome/browser/ui/webui/sync_promo/sync_promo_ui.h"
+#include "chrome/browser/ui/sync/sync_promo_ui.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
@@ -39,6 +39,10 @@
 #include "net/url_request/url_request.h"
 #include "ui/base/l10n/l10n_util.h"
 
+#if defined(OS_ANDROID)
+#include "chrome/browser/ui/auto_login_infobar_delegate_android.h"
+#endif
+
 using content::NavigationController;
 using content::NotificationSource;
 using content::NotificationDetails;
@@ -131,7 +135,7 @@
       std::string());
 }
 
-}  // namepsace
+}  // namespace
 
 
 // AutoLoginInfoBarDelegate::Params -------------------------------------------
@@ -146,13 +150,12 @@
 void AutoLoginInfoBarDelegate::Create(InfoBarService* infobar_service,
                                       const Params& params) {
   infobar_service->AddInfoBar(scoped_ptr<InfoBarDelegate>(
-      new AutoLoginInfoBarDelegate(infobar_service, params)));
-}
-
-string16 AutoLoginInfoBarDelegate::GetMessageText(
-    const std::string& username) const {
-  return l10n_util::GetStringFUTF16(IDS_AUTOLOGIN_INFOBAR_MESSAGE,
-                                    UTF8ToUTF16(username));
+#if defined(OS_ANDROID)
+      new AutoLoginInfoBarDelegateAndroid(infobar_service, params)
+#else
+      new AutoLoginInfoBarDelegate(infobar_service, params)
+#endif
+      ));
 }
 
 AutoLoginInfoBarDelegate::AutoLoginInfoBarDelegate(
@@ -192,7 +195,8 @@
 }
 
 string16 AutoLoginInfoBarDelegate::GetMessageText() const {
-  return GetMessageText(params_.username);
+  return l10n_util::GetStringFUTF16(IDS_AUTOLOGIN_INFOBAR_MESSAGE,
+                                    UTF8ToUTF16(params_.username));
 }
 
 string16 AutoLoginInfoBarDelegate::GetButtonLabel(
diff --git a/chrome/browser/ui/auto_login_infobar_delegate.h b/chrome/browser/ui/auto_login_infobar_delegate.h
index 540b26d..823fb6b 100644
--- a/chrome/browser/ui/auto_login_infobar_delegate.h
+++ b/chrome/browser/ui/auto_login_infobar_delegate.h
@@ -37,13 +37,12 @@
   // Creates an autologin delegate and adds it to |infobar_service|.
   static void Create(InfoBarService* infobar_service, const Params& params);
 
-  // All the methods below are used by the Android implementation of the
-  // AutoLogin bar on the app side.
-  string16 GetMessageText(const std::string& username) const;
+ protected:
+  AutoLoginInfoBarDelegate(InfoBarService* owner, const Params& params);
+  virtual ~AutoLoginInfoBarDelegate();
 
-  const std::string& realm() const { return params_.header.realm; }
-  const std::string& account() const { return params_.header.account; }
-  const std::string& args() const { return params_.header.args; }
+  // ConfirmInfoBarDelegate:
+  virtual string16 GetMessageText() const OVERRIDE;
 
  private:
   // Enum values used for UMA histograms.
@@ -57,15 +56,11 @@
     HISTOGRAM_MAX
   };
 
-  AutoLoginInfoBarDelegate(InfoBarService* owner, const Params& params);
-  virtual ~AutoLoginInfoBarDelegate();
-
   // ConfirmInfoBarDelegate:
   virtual void InfoBarDismissed() OVERRIDE;
   virtual int GetIconID() const OVERRIDE;
   virtual Type GetInfoBarType() const OVERRIDE;
   virtual AutoLoginInfoBarDelegate* AsAutoLoginInfoBarDelegate() OVERRIDE;
-  virtual string16 GetMessageText() const OVERRIDE;
   virtual string16 GetButtonLabel(InfoBarButton button) const OVERRIDE;
   virtual bool Accept() OVERRIDE;
   virtual bool Cancel() OVERRIDE;
diff --git a/chrome/browser/ui/auto_login_infobar_delegate_android.h b/chrome/browser/ui/auto_login_infobar_delegate_android.h
new file mode 100644
index 0000000..3f69e0f
--- /dev/null
+++ b/chrome/browser/ui/auto_login_infobar_delegate_android.h
@@ -0,0 +1,44 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef CHROME_BROWSER_UI_AUTO_LOGIN_INFOBAR_DELEGATE_ANDROID_H_
+#define CHROME_BROWSER_UI_AUTO_LOGIN_INFOBAR_DELEGATE_ANDROID_H_
+
+#include "base/android/jni_helper.h"
+#include "base/android/scoped_java_ref.h"
+#include "chrome/browser/ui/auto_login_infobar_delegate.h"
+
+class AutoLoginInfoBarDelegateAndroid : public AutoLoginInfoBarDelegate {
+ public:
+  AutoLoginInfoBarDelegateAndroid(InfoBarService* owner, const Params& params);
+  virtual ~AutoLoginInfoBarDelegateAndroid();
+
+  // ConfirmInfoBarDelegate:
+  virtual bool Accept() OVERRIDE;
+  virtual bool Cancel() OVERRIDE;
+  virtual string16 GetMessageText() const OVERRIDE;
+
+  // These methods are defined in downstream code.
+  bool AttachAccount(JavaObjectWeakGlobalRef weak_java_translate_helper);
+  void LoginSuccess(JNIEnv* env, jobject obj, jstring result);
+  void LoginFailed(JNIEnv* env, jobject obj);
+  void LoginDismiss(JNIEnv* env, jobject obj);
+
+  // Register Android JNI bindings.
+  static bool Register(JNIEnv* env);
+
+ private:
+  const std::string& realm() const { return params_.header.realm; }
+  const std::string& account() const { return params_.header.account; }
+  const std::string& args() const { return params_.header.args; }
+
+  JavaObjectWeakGlobalRef weak_java_auto_login_delegate_;
+  std::string user_;
+  const Params params_;
+
+  DISALLOW_COPY_AND_ASSIGN(AutoLoginInfoBarDelegateAndroid);
+};
+
+
+#endif  // CHROME_BROWSER_UI_AUTO_LOGIN_INFOBAR_DELEGATE_ANDROID_H_
+
diff --git a/chrome/browser/ui/autofill/account_chooser_model.cc b/chrome/browser/ui/autofill/account_chooser_model.cc
index be5f630..3c3bcb0 100644
--- a/chrome/browser/ui/autofill/account_chooser_model.cc
+++ b/chrome/browser/ui/autofill/account_chooser_model.cc
@@ -9,9 +9,9 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/common/pref_names.h"
-#include "components/autofill/browser/autofill_metrics.h"
+#include "components/autofill/core/browser/autofill_metrics.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "ui/base/l10n/l10n_util.h"
diff --git a/chrome/browser/ui/autofill/account_chooser_model.h b/chrome/browser/ui/autofill/account_chooser_model.h
index 940dccd..fd3f001 100644
--- a/chrome/browser/ui/autofill/account_chooser_model.h
+++ b/chrome/browser/ui/autofill/account_chooser_model.h
@@ -10,7 +10,7 @@
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "base/strings/string16.h"
-#include "components/autofill/browser/autofill_manager_delegate.h"
+#include "components/autofill/core/browser/autofill_manager_delegate.h"
 #include "ui/base/models/simple_menu_model.h"
 
 class AutofillMetrics;
diff --git a/chrome/browser/ui/autofill/account_chooser_model_unittest.cc b/chrome/browser/ui/autofill/account_chooser_model_unittest.cc
index 16f4010..f27c1be 100644
--- a/chrome/browser/ui/autofill/account_chooser_model_unittest.cc
+++ b/chrome/browser/ui/autofill/account_chooser_model_unittest.cc
@@ -7,7 +7,7 @@
 #include "chrome/browser/ui/autofill/account_chooser_model.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/autofill/browser/autofill_metrics.h"
+#include "components/autofill/core/browser/autofill_metrics.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/chrome/browser/ui/autofill/autocheckout_bubble_controller.cc b/chrome/browser/ui/autofill/autocheckout_bubble_controller.cc
index d3cab37..da502a7 100644
--- a/chrome/browser/ui/autofill/autocheckout_bubble_controller.cc
+++ b/chrome/browser/ui/autofill/autocheckout_bubble_controller.cc
@@ -4,7 +4,7 @@
 
 #include "chrome/browser/ui/autofill/autocheckout_bubble_controller.h"
 
-#include "components/autofill/browser/autofill_metrics.h"
+#include "components/autofill/core/browser/autofill_metrics.h"
 #include "grit/generated_resources.h"
 #include "grit/ui_resources.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -44,26 +44,20 @@
                         IDS_AUTOCHECKOUT_BUBBLE_PROMPT_NOT_SIGNED_IN);
 }
 
+// TODO(ahutter): Change these functions back to not returning a "Buy With
+// Google" button after UX has finalized the non-Google user experience. See
+// http://crbug.com/253681.
 gfx::Image AutocheckoutBubbleController::NormalImage() {
-  if (!is_google_user_)
-    return gfx::Image();
-
   ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
   return rb.GetImageNamed(IDR_BUY_WITH_GOOGLE_BUTTON);
 }
 
 gfx::Image AutocheckoutBubbleController::HoverImage() {
-  if (!is_google_user_)
-    return gfx::Image();
-
   ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
   return rb.GetImageNamed(IDR_BUY_WITH_GOOGLE_BUTTON_H);
 }
 
 gfx::Image AutocheckoutBubbleController::PressedImage() {
-  if (!is_google_user_)
-    return gfx::Image();
-
   ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
   return rb.GetImageNamed(IDR_BUY_WITH_GOOGLE_BUTTON_P);
 }
diff --git a/chrome/browser/ui/autofill/autocheckout_bubble_controller_unittest.cc b/chrome/browser/ui/autofill/autocheckout_bubble_controller_unittest.cc
index d7ed4e0..ca353ad 100644
--- a/chrome/browser/ui/autofill/autocheckout_bubble_controller_unittest.cc
+++ b/chrome/browser/ui/autofill/autocheckout_bubble_controller_unittest.cc
@@ -6,7 +6,7 @@
 #include "base/callback.h"
 #include "base/memory/scoped_ptr.h"
 #include "chrome/browser/ui/autofill/autocheckout_bubble_controller.h"
-#include "components/autofill/browser/autofill_metrics.h"
+#include "components/autofill/core/browser/autofill_metrics.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/gfx/rect.h"
 
diff --git a/chrome/browser/ui/autofill/autofill_dialog_controller.h b/chrome/browser/ui/autofill/autofill_dialog_controller.h
index f7c5ddb..6bc0508 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_controller.h
+++ b/chrome/browser/ui/autofill/autofill_dialog_controller.h
@@ -9,8 +9,8 @@
 
 #include "base/strings/string16.h"
 #include "chrome/browser/ui/autofill/autofill_dialog_types.h"
-#include "components/autofill/browser/field_types.h"
 #include "components/autofill/content/browser/wallet/required_action.h"
+#include "components/autofill/core/browser/field_types.h"
 #include "ui/base/range/range.h"
 #include "ui/base/ui_base_types.h"
 #include "ui/gfx/image/image.h"
@@ -46,7 +46,6 @@
   virtual string16 CancelButtonText() const = 0;
   virtual string16 ConfirmButtonText() const = 0;
   virtual string16 SaveLocallyText() const = 0;
-  virtual string16 ProgressBarText() const = 0;
   virtual string16 LegalDocumentsText() = 0;
 
   // State ---------------------------------------------------------------------
@@ -173,6 +172,11 @@
   // order from top to bottom.
   virtual std::vector<DialogNotification> CurrentNotifications() = 0;
 
+  // Returns Autocheckout steps that the view should currently be showing in
+  // order from first to last.
+  virtual std::vector<DialogAutocheckoutStep> CurrentAutocheckoutSteps()
+      const = 0;
+
   // Begins or aborts the flow to sign into Wallet.
   virtual void SignInLinkClicked() = 0;
 
diff --git a/chrome/browser/ui/autofill/autofill_dialog_controller_browsertest.cc b/chrome/browser/ui/autofill/autofill_dialog_controller_browsertest.cc
index 7a33c36..469655f 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_controller_browsertest.cc
+++ b/chrome/browser/ui/autofill/autofill_dialog_controller_browsertest.cc
@@ -7,24 +7,32 @@
 #include "base/memory/ref_counted.h"
 #include "base/message_loop.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
+#include "chrome/browser/autofill/personal_data_manager_factory.h"
 #include "chrome/browser/ui/autofill/autofill_dialog_controller_impl.h"
 #include "chrome/browser/ui/autofill/autofill_dialog_view.h"
 #include "chrome/browser/ui/autofill/data_model_wrapper.h"
+#include "chrome/browser/ui/autofill/tab_autofill_manager_delegate.h"
 #include "chrome/browser/ui/autofill/testable_autofill_dialog_view.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/test/base/in_process_browser_test.h"
-#include "components/autofill/browser/autofill_common_test.h"
-#include "components/autofill/browser/autofill_metrics.h"
-#include "components/autofill/browser/test_personal_data_manager.h"
-#include "components/autofill/browser/validation.h"
+#include "chrome/test/base/ui_test_utils.h"
 #include "components/autofill/content/browser/wallet/wallet_test_util.h"
+#include "components/autofill/core/browser/autofill_common_test.h"
+#include "components/autofill/core/browser/autofill_metrics.h"
+#include "components/autofill/core/browser/test_personal_data_manager.h"
+#include "components/autofill/core/browser/validation.h"
 #include "components/autofill/core/common/autofill_switches.h"
 #include "components/autofill/core/common/form_data.h"
 #include "components/autofill/core/common/form_field_data.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_delegate.h"
+#include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
 
 namespace autofill {
 
@@ -91,7 +99,8 @@
                                      dialog_type,
                                      base::Bind(&MockCallback)),
         metric_logger_(metric_logger),
-        message_loop_runner_(runner) {}
+        message_loop_runner_(runner),
+        use_validation_(false) {}
 
   virtual ~TestAutofillDialogController() {}
 
@@ -104,14 +113,20 @@
       DialogSection section,
       AutofillFieldType type,
       const string16& value) OVERRIDE {
-    return string16();
+    if (!use_validation_)
+      return string16();
+    return AutofillDialogControllerImpl::InputValidityMessage(
+        section, type, value);
   }
 
   virtual ValidityData InputsAreValid(
       DialogSection section,
       const DetailOutputMap& inputs,
       ValidationType validation_type) OVERRIDE {
-    return ValidityData();
+    if (!use_validation_)
+      return ValidityData();
+    return AutofillDialogControllerImpl::InputsAreValid(
+        section, inputs, validation_type);
   }
 
   // Saving to Chrome is tested in AutofillDialogController unit tests.
@@ -138,6 +153,11 @@
 
   using AutofillDialogControllerImpl::DisableWallet;
   using AutofillDialogControllerImpl::IsEditingExistingData;
+  using AutofillDialogControllerImpl::IsManuallyEditingSection;
+
+  void set_use_validation(bool use_validation) {
+    use_validation_ = use_validation;
+  }
 
  protected:
   virtual PersonalDataManager* GetManager() OVERRIDE {
@@ -153,6 +173,7 @@
   const AutofillMetrics& metric_logger_;
   TestPersonalDataManager test_manager_;
   scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
+  bool use_validation_;
 
   // A list of notifications to show in the notification area of the dialog.
   // This is used to control what |CurrentNotifications()| returns for testing.
@@ -177,7 +198,7 @@
     form.user_submitted = true;
 
     FormFieldData field;
-    field.autocomplete_attribute = "email";
+    field.autocomplete_attribute = "shipping tel";
     form.fields.push_back(field);
 
     message_loop_runner_ = new content::MessageLoopRunner;
@@ -201,10 +222,85 @@
     message_loop_runner_->Run();
   }
 
+  // Loads an HTML page in |GetActiveWebContents()| with markup as follows:
+  // <form>|form_inner_html|</form>. After loading, emulates a click event on
+  // the page as requestAutocomplete() must be in response to a user gesture.
+  // Returns the |AutofillDialogControllerImpl| created by this invocation.
+  AutofillDialogControllerImpl* SetUpHtmlAndInvoke(
+      const std::string& form_inner_html) {
+    content::WebContents* contents = GetActiveWebContents();
+    TabAutofillManagerDelegate* delegate =
+        TabAutofillManagerDelegate::FromWebContents(contents);
+    DCHECK(!delegate->GetDialogControllerForTesting());
+
+    ui_test_utils::NavigateToURL(
+        browser(), GURL(std::string("data:text/html,") +
+        "<!doctype html>"
+        "<html>"
+          "<body>"
+            "<form>" + form_inner_html + "</form>"
+            "<script>"
+              "function send(msg) {"
+                "domAutomationController.setAutomationId(0);"
+                "domAutomationController.send(msg);"
+              "}"
+              "document.forms[0].onautocompleteerror = function(e) {"
+                "send('error: ' + e.reason);"
+              "};"
+              "document.forms[0].onautocomplete = function() {"
+                "send('success');"
+              "};"
+              "window.onclick = function() {"
+                "document.forms[0].requestAutocomplete();"
+                "send('clicked');"
+              "};"
+            "</script>"
+          "</body>"
+        "</html>"));
+    content::WaitForLoadStop(contents);
+
+    dom_message_queue_.reset(new content::DOMMessageQueue);
+
+    // Triggers the onclick handler which invokes requestAutocomplete().
+    content::SimulateMouseClick(contents, 0, WebKit::WebMouseEvent::ButtonLeft);
+    ExpectDomMessage("clicked");
+
+    AutofillDialogControllerImpl* controller =
+        delegate->GetDialogControllerForTesting();
+    DCHECK(controller);
+    return controller;
+  }
+
+  // Wait for a message from the DOM automation controller (from JS in the
+  // page). Requires |SetUpHtmlAndInvoke()| be called first.
+  void ExpectDomMessage(const std::string& expected) {
+    std::string message;
+    ASSERT_TRUE(dom_message_queue_->WaitForMessage(&message));
+    dom_message_queue_->ClearQueue();
+    EXPECT_EQ("\"" + expected + "\"", message);
+  }
+
+  void AddCreditcardToProfile(Profile* profile, const CreditCard& card) {
+    PersonalDataManagerFactory::GetForProfile(profile)->AddCreditCard(card);
+    WaitForWebDB();
+  }
+
+  void AddAutofillProfileToProfile(Profile* profile,
+                                   const AutofillProfile& autofill_profile) {
+    PersonalDataManagerFactory::GetForProfile(profile)->AddProfile(
+        autofill_profile);
+    WaitForWebDB();
+  }
+
  private:
+  void WaitForWebDB() {
+    content::RunAllPendingInMessageLoop(content::BrowserThread::DB);
+  }
+
   MockAutofillMetrics metric_logger_;
   TestAutofillDialogController* controller_;  // Weak reference.
   scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
+  scoped_ptr<content::DOMMessageQueue> dom_message_queue_;
   DISALLOW_COPY_AND_ASSIGN(AutofillDialogControllerTest);
 };
 
@@ -214,7 +310,7 @@
 // Submit the form data.
 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, Submit) {
   InitializeControllerOfType(DIALOG_TYPE_REQUEST_AUTOCOMPLETE);
-  controller()->view()->GetTestableView()->SubmitForTesting();
+  controller()->GetTestableView()->SubmitForTesting();
 
   RunMessageLoop();
 
@@ -226,7 +322,7 @@
 // Cancel out of the dialog.
 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, Cancel) {
   InitializeControllerOfType(DIALOG_TYPE_REQUEST_AUTOCOMPLETE);
-  controller()->view()->GetTestableView()->CancelForTesting();
+  controller()->GetTestableView()->CancelForTesting();
 
   RunMessageLoop();
 
@@ -250,14 +346,14 @@
 // Test Autocheckout success metrics.
 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, AutocheckoutSuccess) {
   InitializeControllerOfType(DIALOG_TYPE_AUTOCHECKOUT);
-  controller()->view()->GetTestableView()->SubmitForTesting();
+  controller()->GetTestableView()->SubmitForTesting();
 
   EXPECT_EQ(AutofillMetrics::DIALOG_ACCEPTED,
             metric_logger().dialog_dismissal_action());
   EXPECT_EQ(DIALOG_TYPE_AUTOCHECKOUT, metric_logger().dialog_type());
 
   controller()->OnAutocheckoutSuccess();
-  controller()->view()->GetTestableView()->CancelForTesting();
+  controller()->GetTestableView()->CancelForTesting();
   RunMessageLoop();
 
   EXPECT_EQ(AutofillMetrics::AUTOCHECKOUT_SUCCEEDED,
@@ -272,14 +368,14 @@
 // Test Autocheckout failure metric.
 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, AutocheckoutError) {
   InitializeControllerOfType(DIALOG_TYPE_AUTOCHECKOUT);
-  controller()->view()->GetTestableView()->SubmitForTesting();
+  controller()->GetTestableView()->SubmitForTesting();
 
   EXPECT_EQ(AutofillMetrics::DIALOG_ACCEPTED,
             metric_logger().dialog_dismissal_action());
   EXPECT_EQ(DIALOG_TYPE_AUTOCHECKOUT, metric_logger().dialog_type());
 
   controller()->OnAutocheckoutError();
-  controller()->view()->GetTestableView()->CancelForTesting();
+  controller()->GetTestableView()->CancelForTesting();
   RunMessageLoop();
 
   EXPECT_EQ(AutofillMetrics::AUTOCHECKOUT_FAILED,
@@ -293,13 +389,13 @@
 
 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, AutocheckoutCancelled) {
   InitializeControllerOfType(DIALOG_TYPE_AUTOCHECKOUT);
-  controller()->view()->GetTestableView()->SubmitForTesting();
+  controller()->GetTestableView()->SubmitForTesting();
 
   EXPECT_EQ(AutofillMetrics::DIALOG_ACCEPTED,
             metric_logger().dialog_dismissal_action());
   EXPECT_EQ(DIALOG_TYPE_AUTOCHECKOUT, metric_logger().dialog_type());
 
-  controller()->view()->GetTestableView()->CancelForTesting();
+  controller()->GetTestableView()->CancelForTesting();
   RunMessageLoop();
 
   EXPECT_EQ(AutofillMetrics::AUTOCHECKOUT_CANCELLED,
@@ -322,7 +418,7 @@
       controller()->RequestedFieldsForSection(SECTION_SHIPPING);
   const DetailInput& triggering_input = inputs[0];
   string16 value = full_profile.GetRawInfo(triggering_input.type);
-  TestableAutofillDialogView* view = controller()->view()->GetTestableView();
+  TestableAutofillDialogView* view = controller()->GetTestableView();
   view->SetTextContentsOfInput(triggering_input,
                                value.substr(0, value.size() / 2));
   view->ActivateInput(triggering_input);
@@ -361,29 +457,37 @@
   }
 }
 
-// Test that the Autocheckout progress bar is showing after submitting the
+// Test that Autocheckout steps are shown after submitting the
 // dialog for controller with type DIALOG_TYPE_AUTOCHECKOUT.
 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
-                       AutocheckoutShowsProgressBar) {
+                       AutocheckoutShowsSteps) {
   InitializeControllerOfType(DIALOG_TYPE_AUTOCHECKOUT);
+  controller()->AddAutocheckoutStep(AUTOCHECKOUT_STEP_PROXY_CARD);
+
   EXPECT_TRUE(controller()->ShouldShowDetailArea());
+  EXPECT_TRUE(controller()->CurrentAutocheckoutSteps().empty());
   EXPECT_FALSE(controller()->ShouldShowProgressBar());
 
-  controller()->view()->GetTestableView()->SubmitForTesting();
+  controller()->GetTestableView()->SubmitForTesting();
   EXPECT_FALSE(controller()->ShouldShowDetailArea());
+  EXPECT_FALSE(controller()->CurrentAutocheckoutSteps().empty());
   EXPECT_TRUE(controller()->ShouldShowProgressBar());
 }
 
-// Test that the Autocheckout progress bar is not showing after submitting the
+// Test that Autocheckout steps are not showing after submitting the
 // dialog for controller with type DIALOG_TYPE_REQUEST_AUTOCOMPLETE.
 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
-                       RequestAutocompleteDoesntShowProgressBar) {
+                       RequestAutocompleteDoesntShowSteps) {
   InitializeControllerOfType(DIALOG_TYPE_REQUEST_AUTOCOMPLETE);
+  controller()->AddAutocheckoutStep(AUTOCHECKOUT_STEP_PROXY_CARD);
+
   EXPECT_TRUE(controller()->ShouldShowDetailArea());
+  EXPECT_TRUE(controller()->CurrentAutocheckoutSteps().empty());
   EXPECT_FALSE(controller()->ShouldShowProgressBar());
 
-  controller()->view()->GetTestableView()->SubmitForTesting();
+  controller()->GetTestableView()->SubmitForTesting();
   EXPECT_TRUE(controller()->ShouldShowDetailArea());
+  EXPECT_TRUE(controller()->CurrentAutocheckoutSteps().empty());
   EXPECT_FALSE(controller()->ShouldShowProgressBar());
 }
 
@@ -406,7 +510,7 @@
       controller()->RequestedFieldsForSection(SECTION_CC);
   const DetailInput& triggering_input = inputs[0];
   string16 value = card1.GetRawInfo(triggering_input.type);
-  TestableAutofillDialogView* view = controller()->view()->GetTestableView();
+  TestableAutofillDialogView* view = controller()->GetTestableView();
   view->SetTextContentsOfInput(triggering_input,
                                value.substr(0, value.size() / 2));
   view->ActivateInput(triggering_input);
@@ -549,7 +653,7 @@
   InitializeControllerOfType(DIALOG_TYPE_REQUEST_AUTOCOMPLETE);
 
   const gfx::Size no_notification_size =
-      controller()->view()->GetTestableView()->GetSize();
+      controller()->GetTestableView()->GetSize();
   ASSERT_GT(no_notification_size.width(), 0);
 
   std::vector<DialogNotification> notifications;
@@ -566,7 +670,140 @@
   controller()->view()->UpdateNotificationArea();
 
   EXPECT_EQ(no_notification_size.width(),
-            controller()->view()->GetTestableView()->GetSize().width());
+            controller()->GetTestableView()->GetSize().width());
+}
+
+IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, AutocompleteEvent) {
+  AutofillDialogControllerImpl* controller =
+      SetUpHtmlAndInvoke("<input autocomplete='cc-name'>");
+
+  AddCreditcardToProfile(controller->profile(), test::GetVerifiedCreditCard());
+  AddAutofillProfileToProfile(controller->profile(),
+                              test::GetVerifiedProfile());
+
+  TestableAutofillDialogView* view = controller->GetTestableView();
+  view->SetTextContentsOfSuggestionInput(SECTION_CC, ASCIIToUTF16("123"));
+  view->SubmitForTesting();
+  ExpectDomMessage("success");
+}
+
+IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
+                       AutocompleteErrorEventReasonInvalid) {
+  AutofillDialogControllerImpl* controller =
+      SetUpHtmlAndInvoke("<input autocomplete='cc-name' pattern='.*zebra.*'>");
+
+  const CreditCard& credit_card = test::GetVerifiedCreditCard();
+  ASSERT_TRUE(
+    credit_card.GetRawInfo(CREDIT_CARD_NAME).find(ASCIIToUTF16("zebra")) ==
+        base::string16::npos);
+  AddCreditcardToProfile(controller->profile(), credit_card);
+  AddAutofillProfileToProfile(controller->profile(),
+                              test::GetVerifiedProfile());
+
+  TestableAutofillDialogView* view = controller->GetTestableView();
+  view->SetTextContentsOfSuggestionInput(SECTION_CC, ASCIIToUTF16("123"));
+  view->SubmitForTesting();
+  ExpectDomMessage("error: invalid");
+}
+
+IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
+                       AutocompleteErrorEventReasonCancel) {
+  SetUpHtmlAndInvoke("<input autocomplete='cc-name'>")->GetTestableView()->
+      CancelForTesting();
+  ExpectDomMessage("error: cancel");
+}
+
+IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, NoCvcSegfault) {
+  InitializeControllerOfType(DIALOG_TYPE_REQUEST_AUTOCOMPLETE);
+  controller()->DisableWallet(wallet::WalletClient::UNKNOWN_ERROR);
+  controller()->set_use_validation(true);
+
+  CreditCard credit_card(test::GetVerifiedCreditCard());
+  controller()->GetTestingManager()->AddTestingCreditCard(&credit_card);
+  EXPECT_FALSE(controller()->IsEditingExistingData(SECTION_CC));
+
+  ASSERT_NO_FATAL_FAILURE(
+      controller()->GetTestableView()->SubmitForTesting());
+}
+
+IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, PreservedSections) {
+  InitializeControllerOfType(DIALOG_TYPE_REQUEST_AUTOCOMPLETE);
+  controller()->set_use_validation(true);
+
+  // Set up some Autofill state.
+  CreditCard credit_card(test::GetVerifiedCreditCard());
+  controller()->GetTestingManager()->AddTestingCreditCard(&credit_card);
+
+  AutofillProfile profile(test::GetVerifiedProfile());
+  controller()->GetTestingManager()->AddTestingProfile(&profile);
+
+  EXPECT_TRUE(controller()->SectionIsActive(SECTION_CC));
+  EXPECT_TRUE(controller()->SectionIsActive(SECTION_BILLING));
+  EXPECT_FALSE(controller()->SectionIsActive(SECTION_CC_BILLING));
+  EXPECT_TRUE(controller()->SectionIsActive(SECTION_SHIPPING));
+
+  EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_CC));
+  EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_BILLING));
+  EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_SHIPPING));
+
+  // Set up some Wallet state.
+  controller()->OnUserNameFetchSuccess("user@example.com");
+  controller()->OnDidGetWalletItems(wallet::GetTestWalletItems());
+
+  ui::MenuModel* account_chooser = controller()->MenuModelForAccountChooser();
+  ASSERT_TRUE(account_chooser->IsItemCheckedAt(0));
+
+  // Check that the view's in the state we expect before starting to simulate
+  // user input.
+  EXPECT_FALSE(controller()->SectionIsActive(SECTION_CC));
+  EXPECT_FALSE(controller()->SectionIsActive(SECTION_BILLING));
+  EXPECT_TRUE(controller()->SectionIsActive(SECTION_CC_BILLING));
+  EXPECT_TRUE(controller()->SectionIsActive(SECTION_SHIPPING));
+
+  EXPECT_TRUE(controller()->IsManuallyEditingSection(SECTION_CC_BILLING));
+
+  // Create some valid inputted billing data.
+  const DetailInput& cc_name =
+      controller()->RequestedFieldsForSection(SECTION_CC_BILLING)[4];
+  ASSERT_EQ(CREDIT_CARD_NAME, cc_name.type);
+  TestableAutofillDialogView* view = controller()->GetTestableView();
+  view->SetTextContentsOfInput(cc_name, ASCIIToUTF16("credit card name"));
+
+  // Select "Add new shipping info..." from suggestions menu.
+  ui::MenuModel* shipping_model =
+      controller()->MenuModelForSection(SECTION_SHIPPING);
+  shipping_model->ActivatedAt(shipping_model->GetItemCount() - 2);
+
+  EXPECT_TRUE(controller()->IsManuallyEditingSection(SECTION_SHIPPING));
+
+  // Create some invalid, manually inputted shipping data.
+  const DetailInput& shipping_zip =
+      controller()->RequestedFieldsForSection(SECTION_SHIPPING)[5];
+  ASSERT_EQ(ADDRESS_HOME_ZIP, shipping_zip.type);
+  view->SetTextContentsOfInput(shipping_zip, ASCIIToUTF16("shipping zip"));
+
+  // Switch to using Autofill.
+  account_chooser->ActivatedAt(1);
+
+  // Check that appropriate sections are preserved and in manually editing mode
+  // (or disabled, in the case of the combined cc + billing section).
+  EXPECT_TRUE(controller()->SectionIsActive(SECTION_CC));
+  EXPECT_TRUE(controller()->SectionIsActive(SECTION_BILLING));
+  EXPECT_FALSE(controller()->SectionIsActive(SECTION_CC_BILLING));
+  EXPECT_TRUE(controller()->SectionIsActive(SECTION_SHIPPING));
+
+  EXPECT_TRUE(controller()->IsManuallyEditingSection(SECTION_CC));
+  EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_BILLING));
+  EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_SHIPPING));
+
+  const DetailInput& new_cc_name =
+      controller()->RequestedFieldsForSection(SECTION_CC).back();
+  ASSERT_EQ(cc_name.type, new_cc_name.type);
+  EXPECT_EQ(ASCIIToUTF16("credit card name"),
+            view->GetTextContentsOfInput(new_cc_name));
+
+  EXPECT_NE(ASCIIToUTF16("shipping name"),
+            view->GetTextContentsOfInput(shipping_zip));
 }
 #endif  // defined(TOOLKIT_VIEWS)
 
diff --git a/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc b/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc
index 1b1c4b0..5e661c9 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc
+++ b/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc
@@ -8,6 +8,7 @@
 #include <map>
 #include <string>
 
+#include "apps/shell_window.h"
 #include "base/base64.h"
 #include "base/bind.h"
 #include "base/i18n/rtl.h"
@@ -17,7 +18,7 @@
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/autofill/personal_data_manager_factory.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/extensions/shell_window_registry.h"
@@ -30,17 +31,9 @@
 #include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/extensions/native_app_window.h"
-#include "chrome/browser/ui/extensions/shell_window.h"
 #include "chrome/common/chrome_version_info.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
-#include "components/autofill/browser/autofill_country.h"
-#include "components/autofill/browser/autofill_data_model.h"
-#include "components/autofill/browser/autofill_manager.h"
-#include "components/autofill/browser/autofill_type.h"
-#include "components/autofill/browser/personal_data_manager.h"
-#include "components/autofill/browser/phone_number_i18n.h"
-#include "components/autofill/browser/validation.h"
 #include "components/autofill/content/browser/risk/fingerprint.h"
 #include "components/autofill/content/browser/risk/proto/fingerprint.pb.h"
 #include "components/autofill/content/browser/wallet/form_field_error.h"
@@ -50,6 +43,13 @@
 #include "components/autofill/content/browser/wallet/wallet_items.h"
 #include "components/autofill/content/browser/wallet/wallet_service_url.h"
 #include "components/autofill/content/browser/wallet/wallet_signin_helper.h"
+#include "components/autofill/core/browser/autofill_country.h"
+#include "components/autofill/core/browser/autofill_data_model.h"
+#include "components/autofill/core/browser/autofill_manager.h"
+#include "components/autofill/core/browser/autofill_type.h"
+#include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/autofill/core/browser/phone_number_i18n.h"
+#include "components/autofill/core/browser/validation.h"
 #include "components/autofill/core/common/form_data.h"
 #include "components/user_prefs/pref_registry_syncable.h"
 #include "content/public/browser/browser_thread.h"
@@ -70,6 +70,7 @@
 #include "net/cert/cert_status_flags.h"
 #include "ui/base/base_window.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/models/combobox_model.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/color_utils.h"
@@ -225,7 +226,7 @@
 
   gfx::NativeWindow native_window =
       web_contents->GetView()->GetTopLevelNativeWindow();
-  ShellWindow* shell_window =
+  apps::ShellWindow* shell_window =
       extensions::ShellWindowRegistry::
           GetShellWindowForNativeWindowAnyProfile(native_window);
   return shell_window->GetBaseWindow();
@@ -313,6 +314,16 @@
   return true;
 }
 
+// Returns true if |profile| has an invalid address, i.e. an invalid state, zip
+// code, or phone number. Otherwise returns false. Profiles with invalid
+// addresses are not suggested in the dropdown menu for billing and shipping
+// addresses.
+bool HasInvalidAddress(const AutofillProfile& profile) {
+  return profile.IsPresentButInvalid(ADDRESS_HOME_STATE) ||
+         profile.IsPresentButInvalid(ADDRESS_HOME_ZIP) ||
+         profile.IsPresentButInvalid(PHONE_HOME_WHOLE_NUMBER);
+}
+
 // Loops through |addresses_| comparing to |address| ignoring ID. If a match
 // is not found, NULL is returned.
 const wallet::Address* FindDuplicateAddress(
@@ -566,10 +577,6 @@
     view_->Hide();
 }
 
-void AutofillDialogControllerImpl::UpdateProgressBar(double value) {
-  view_->UpdateProgressBar(value);
-}
-
 bool AutofillDialogControllerImpl::AutocheckoutIsRunning() const {
   return autocheckout_state_ == AUTOCHECKOUT_IN_PROGRESS;
 }
@@ -579,11 +586,8 @@
   GetMetricLogger().LogAutocheckoutDuration(
       base::Time::Now() - autocheckout_started_timestamp_,
       AutofillMetrics::AUTOCHECKOUT_FAILED);
-  autocheckout_state_ = AUTOCHECKOUT_ERROR;
+  SetAutocheckoutState(AUTOCHECKOUT_ERROR);
   autocheckout_started_timestamp_ = base::Time();
-  view_->UpdateNotificationArea();
-  view_->UpdateButtonStrip();
-  view_->UpdateDetailArea();
 }
 
 void AutofillDialogControllerImpl::OnAutocheckoutSuccess() {
@@ -591,10 +595,50 @@
   GetMetricLogger().LogAutocheckoutDuration(
       base::Time::Now() - autocheckout_started_timestamp_,
       AutofillMetrics::AUTOCHECKOUT_SUCCEEDED);
-  autocheckout_state_ = AUTOCHECKOUT_SUCCESS;
+  SetAutocheckoutState(AUTOCHECKOUT_SUCCESS);
   autocheckout_started_timestamp_ = base::Time();
-  view_->UpdateNotificationArea();
-  view_->UpdateButtonStrip();
+}
+
+
+TestableAutofillDialogView* AutofillDialogControllerImpl::GetTestableView() {
+  return view_ ? view_->GetTestableView() : NULL;
+}
+
+void AutofillDialogControllerImpl::AddAutocheckoutStep(
+    AutocheckoutStepType step_type) {
+  for (size_t i = 0; i < steps_.size(); ++i) {
+    if (steps_[i].type() == step_type)
+      return;
+  }
+  steps_.push_back(
+      DialogAutocheckoutStep(step_type, AUTOCHECKOUT_STEP_UNSTARTED));
+}
+
+void AutofillDialogControllerImpl::UpdateAutocheckoutStep(
+    AutocheckoutStepType step_type,
+    AutocheckoutStepStatus step_status) {
+  int total_steps = 0;
+  int completed_steps = 0;
+  for (size_t i = 0; i < steps_.size(); ++i) {
+    ++total_steps;
+    if (steps_[i].status() == AUTOCHECKOUT_STEP_COMPLETED)
+      ++completed_steps;
+    if (steps_[i].type() == step_type && steps_[i].status() != step_status)
+      steps_[i] = DialogAutocheckoutStep(step_type, step_status);
+  }
+  if (view_) {
+    view_->UpdateAutocheckoutStepsArea();
+    view_->UpdateProgressBar(1.0 * completed_steps / total_steps);
+  }
+}
+
+std::vector<DialogAutocheckoutStep>
+    AutofillDialogControllerImpl::CurrentAutocheckoutSteps() const {
+  if (autocheckout_state_ != AUTOCHECKOUT_NOT_STARTED)
+    return steps_;
+
+  std::vector<DialogAutocheckoutStep> empty_steps;
+  return empty_steps;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -625,13 +669,8 @@
   return l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_SAVE_LOCALLY_CHECKBOX);
 }
 
-string16 AutofillDialogControllerImpl::ProgressBarText() const {
-  return l10n_util::GetStringUTF16(
-      IDS_AUTOFILL_DIALOG_AUTOCHECKOUT_PROGRESS_BAR);
-}
-
 string16 AutofillDialogControllerImpl::LegalDocumentsText() {
-  if (!IsPayingWithWallet())
+  if (!IsPayingWithWallet() || autocheckout_state_ != AUTOCHECKOUT_NOT_STARTED)
     return string16();
 
   EnsureLegalDocumentsText();
@@ -678,14 +717,10 @@
 }
 
 bool AutofillDialogControllerImpl::ShouldOfferToSaveInChrome() const {
-  // If Autocheckout is running, hide this checkbox so the progress bar has some
-  // room. If Autocheckout had an error, neither the [X] Save details in chrome
-  // nor the progress bar should show.
   return !IsPayingWithWallet() &&
       !profile_->IsOffTheRecord() &&
       IsManuallyEditingAnySection() &&
-      !ShouldShowProgressBar() &&
-      autocheckout_state_ != AUTOCHECKOUT_ERROR;
+      ShouldShowDetailArea();
 }
 
 int AutofillDialogControllerImpl::GetDialogButtons() const {
@@ -741,6 +776,10 @@
 }
 
 void AutofillDialogControllerImpl::GetWalletItems() {
+  wallet_items_.reset();
+  // The "Loading..." page should be showing now, which should cause the
+  // account chooser to hide.
+  view_->UpdateAccountChooser();
   GetWalletClient()->GetWalletItems(source_url_);
 }
 
@@ -821,8 +860,7 @@
   if (!wallet_server_validation_recoverable_)
     DisableWallet(wallet::WalletClient::UNKNOWN_ERROR);
 
-  if (view_)
-    view_->UpdateForErrors();
+  UpdateForErrors();
 }
 
 void AutofillDialogControllerImpl::EnsureLegalDocumentsText() {
@@ -866,33 +904,125 @@
   legal_documents_text_ = text;
 }
 
-void AutofillDialogControllerImpl::PrepareDetailInputsForSection(
-    DialogSection section) {
+void AutofillDialogControllerImpl::ResetSectionInput(DialogSection section) {
   SetEditingExistingData(section, false);
+
+  DetailInputs* inputs = MutableRequestedFieldsForSection(section);
+  for (DetailInputs::iterator it = inputs->begin(); it != inputs->end(); ++it) {
+    it->initial_value.clear();
+  }
+}
+
+void AutofillDialogControllerImpl::ShowEditUiIfBadSuggestion(
+    DialogSection section) {
+  // |CreateWrapper()| returns an empty wrapper if |IsEditingExistingData()|, so
+  // get the wrapper before this potentially happens below.
   scoped_ptr<DataModelWrapper> wrapper = CreateWrapper(section);
 
   // If the chosen item in |model| yields an empty suggestion text, it is
-  // invalid. In this case, show the editing UI with invalid fields highlighted.
+  // invalid. In this case, show the edit UI and highlight invalid fields.
   SuggestionsMenuModel* model = SuggestionsMenuModelForSection(section);
   if (IsASuggestionItemKey(model->GetItemKeyForCheckedItem()) &&
       SuggestionTextForSection(section).empty()) {
     SetEditingExistingData(section, true);
   }
 
-  // Reset all previously entered data and stop editing |section|.
   DetailInputs* inputs = MutableRequestedFieldsForSection(section);
-  for (DetailInputs::iterator it = inputs->begin(); it != inputs->end(); ++it) {
-    it->initial_value.clear();
-    it->editable = InputIsEditable(*it, section);
-  }
-
   if (wrapper && IsEditingExistingData(section))
     wrapper->FillInputs(inputs);
 
+  for (DetailInputs::iterator it = inputs->begin(); it != inputs->end(); ++it) {
+    it->editable = InputIsEditable(*it, section);
+  }
+}
+
+bool AutofillDialogControllerImpl::InputWasEdited(const DetailInput& input,
+                                                  const base::string16& value) {
+  if (value.empty())
+    return false;
+
+  // If this is a combobox at the default value, don't preserve.
+  ui::ComboboxModel* model = ComboboxModelForAutofillType(input.type);
+  if (model && model->GetItemAt(model->GetDefaultIndex()) == value)
+    return false;
+
+  return true;
+}
+
+DetailOutputMap AutofillDialogControllerImpl::TakeUserInputSnapshot() {
+  DetailOutputMap snapshot;
+  if (!view_)
+    return snapshot;
+
+  for (size_t i = SECTION_MIN; i <= SECTION_MAX; ++i) {
+    DialogSection section = static_cast<DialogSection>(i);
+    SuggestionsMenuModel* model = SuggestionsMenuModelForSection(section);
+    if (model->GetItemKeyForCheckedItem() != kAddNewItemKey)
+      continue;
+
+    DetailOutputMap outputs;
+    view_->GetUserInput(section, &outputs);
+    // Remove fields that are empty, at their default values, or invalid.
+    for (DetailOutputMap::iterator it = outputs.begin(); it != outputs.end();
+         ++it) {
+      if (InputWasEdited(*it->first, it->second) &&
+          InputValidityMessage(section, it->first->type, it->second).empty()) {
+        snapshot.insert(std::make_pair(it->first, it->second));
+      }
+    }
+  }
+
+  return snapshot;
+}
+
+void AutofillDialogControllerImpl::RestoreUserInputFromSnapshot(
+    const DetailOutputMap& snapshot) {
+  if (snapshot.empty())
+    return;
+
+  DetailOutputWrapper wrapper(snapshot);
+  for (size_t i = SECTION_MIN; i <= SECTION_MAX; ++i) {
+    DialogSection section = static_cast<DialogSection>(i);
+    if (!SectionIsActive(section))
+      continue;
+
+    DetailInputs* inputs = MutableRequestedFieldsForSection(section);
+    wrapper.FillInputs(inputs);
+
+    for (size_t i = 0; i < inputs->size(); ++i) {
+      if (InputWasEdited((*inputs)[i], (*inputs)[i].initial_value)) {
+        SuggestionsMenuModelForSection(section)->SetCheckedItem(kAddNewItemKey);
+        break;
+      }
+    }
+  }
+}
+
+void AutofillDialogControllerImpl::UpdateSection(DialogSection section) {
   if (view_)
     view_->UpdateSection(section);
 }
 
+void AutofillDialogControllerImpl::UpdateForErrors() {
+  if (!view_)
+    return;
+
+  // Currently, the view should only need to be updated if there are
+  // |wallet_errors_| or validating a suggestion that's based on existing data.
+  bool should_update = !wallet_errors_.empty();
+  if (!should_update) {
+    for (size_t i = SECTION_MIN; i <= SECTION_MAX; ++i) {
+      if (IsEditingExistingData(static_cast<DialogSection>(i))) {
+        should_update = true;
+        break;
+      }
+    }
+  }
+
+  if (should_update)
+    view_->UpdateForErrors();
+}
+
 const DetailInputs& AutofillDialogControllerImpl::RequestedFieldsForSection(
     DialogSection section) const {
   switch (section) {
@@ -1045,10 +1175,8 @@
   if (!IsASuggestionItemKey(item_key))
     return string16();
 
-  if (section == SECTION_EMAIL) {
-    string16 email_address = model->GetLabelAt(model->checked_item());
-    return IsValidEmailAddress(email_address) ? email_address : string16();
-  }
+  if (section == SECTION_EMAIL)
+    return model->GetLabelAt(model->checked_item());
 
   scoped_ptr<DataModelWrapper> wrapper = CreateWrapper(section);
   return wrapper->GetDisplayText();
@@ -1208,7 +1336,7 @@
   }
   model->FillInputs(inputs);
 
-  view_->UpdateSection(section);
+  UpdateSection(section);
 
   GetMetricLogger().LogDialogUiEvent(
       GetDialogType(), DialogSectionToUiEditEvent(section));
@@ -1216,7 +1344,8 @@
 
 void AutofillDialogControllerImpl::EditCancelledForSection(
     DialogSection section) {
-  PrepareDetailInputsForSection(section);
+  ResetSectionInput(section);
+  UpdateSection(section);
 }
 
 gfx::Image AutofillDialogControllerImpl::IconForField(
@@ -1295,8 +1424,14 @@
       }
       break;
 
-    case CREDIT_CARD_NUMBER:
-      return CreditCardNumberValidityMessage(value);
+    case CREDIT_CARD_NUMBER: {
+      if (!value.empty()) {
+        base::string16 message = CreditCardNumberValidityMessage(value);
+        if (!message.empty())
+          return message;
+      }
+      break;
+    }
 
     case CREDIT_CARD_NAME:
       // Wallet requires a first and last name.
@@ -1517,9 +1652,8 @@
   int show_count =
       profile_->GetPrefs()->GetInteger(::prefs::kAutofillDialogShowCount);
   if (show_count <= 4) {
-    // TODO(estade): this logo is not the right size.
     return ui::ResourceBundle::GetSharedInstance().GetImageNamed(
-        IDR_PRODUCT_LOGO);
+        IDR_PRODUCT_LOGO_NAME_48);
   }
 
   return gfx::Image();
@@ -1538,30 +1672,10 @@
     CurrentNotifications() {
   std::vector<DialogNotification> notifications;
 
-  if (account_chooser_model_.HadWalletError()) {
-    // TODO(dbeam): figure out a way to dismiss this error after a while.
+  if (IsPayingWithWallet() && !wallet::IsUsingProd()) {
     notifications.push_back(DialogNotification(
-        DialogNotification::WALLET_ERROR,
-        l10n_util::GetStringFUTF16(
-            IDS_AUTOFILL_DIALOG_COMPLETE_WITHOUT_WALLET,
-            account_chooser_model_.wallet_error_message())));
-  } else if (should_show_wallet_promo_) {
-    if (IsPayingWithWallet() && HasCompleteWallet()) {
-      notifications.push_back(DialogNotification(
-          DialogNotification::EXPLANATORY_MESSAGE,
-          l10n_util::GetStringUTF16(
-              IDS_AUTOFILL_DIALOG_DETAILS_FROM_WALLET)));
-    } else if ((IsPayingWithWallet() && !HasCompleteWallet()) ||
-               has_shown_wallet_usage_confirmation_) {
-      DialogNotification notification(
-          DialogNotification::WALLET_USAGE_CONFIRMATION,
-          l10n_util::GetStringUTF16(
-              IDS_AUTOFILL_DIALOG_SAVE_DETAILS_IN_WALLET));
-      notification.set_checked(account_chooser_model_.WalletIsSelected());
-      notification.set_interactive(!is_submitting_);
-      notifications.push_back(notification);
-      has_shown_wallet_usage_confirmation_ = true;
-    }
+        DialogNotification::DEVELOPER_WARNING,
+        l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_NOT_PROD_WARNING)));
   }
 
   if (RequestingCreditCardInfo() && !TransmissionWillBeSecure()) {
@@ -1577,6 +1691,15 @@
                                    UTF8ToUTF16(source_url_.host()))));
   }
 
+  if (account_chooser_model_.HadWalletError()) {
+    // TODO(dbeam): figure out a way to dismiss this error after a while.
+    notifications.push_back(DialogNotification(
+        DialogNotification::WALLET_ERROR,
+        l10n_util::GetStringFUTF16(
+            IDS_AUTOFILL_DIALOG_COMPLETE_WITHOUT_WALLET,
+            account_chooser_model_.wallet_error_message())));
+  }
+
   if (IsSubmitPausedOn(wallet::VERIFY_CVV)) {
     notifications.push_back(DialogNotification(
         DialogNotification::REQUIRED_ACTION,
@@ -1602,18 +1725,32 @@
         ASCIIToUTF16("Could not save Wallet data")));
   }
 
-  if (IsPayingWithWallet() && !wallet::IsUsingProd()) {
-    notifications.push_back(DialogNotification(
-        DialogNotification::DEVELOPER_WARNING,
-        l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_NOT_PROD_WARNING)));
-  }
-
   if (choose_another_instrument_or_address_) {
     notifications.push_back(DialogNotification(
         DialogNotification::REQUIRED_ACTION,
         ASCIIToUTF16("We need more information to complete your purchase.")));
   }
 
+  if (should_show_wallet_promo_ && ShouldShowDetailArea() &&
+      notifications.empty()) {
+    if (IsPayingWithWallet() && HasCompleteWallet()) {
+      notifications.push_back(DialogNotification(
+          DialogNotification::EXPLANATORY_MESSAGE,
+          l10n_util::GetStringUTF16(
+              IDS_AUTOFILL_DIALOG_DETAILS_FROM_WALLET)));
+    } else if ((IsPayingWithWallet() && !HasCompleteWallet()) ||
+               has_shown_wallet_usage_confirmation_) {
+      DialogNotification notification(
+          DialogNotification::WALLET_USAGE_CONFIRMATION,
+          l10n_util::GetStringUTF16(
+              IDS_AUTOFILL_DIALOG_SAVE_DETAILS_IN_WALLET));
+      notification.set_checked(account_chooser_model_.WalletIsSelected());
+      notification.set_interactive(!is_submitting_);
+      notifications.push_back(notification);
+      has_shown_wallet_usage_confirmation_ = true;
+    }
+  }
+
   return notifications;
 }
 
@@ -1672,6 +1809,21 @@
   choose_another_instrument_or_address_ = false;
   wallet_server_validation_recoverable_ = true;
   HidePopup();
+  if (IsPayingWithWallet()) {
+    bool has_proxy_card_step = false;
+    for (size_t i = 0; i < steps_.size(); ++i) {
+      if (steps_[i].type() == AUTOCHECKOUT_STEP_PROXY_CARD) {
+        has_proxy_card_step = true;
+        break;
+      }
+    }
+    if (!has_proxy_card_step) {
+      steps_.insert(steps_.begin(),
+                    DialogAutocheckoutStep(AUTOCHECKOUT_STEP_PROXY_CARD,
+                                           AUTOCHECKOUT_STEP_UNSTARTED));
+    }
+  }
+
   SetIsSubmitting(true);
   if (IsSubmitPausedOn(wallet::VERIFY_CVV)) {
     DCHECK(!active_instrument_id_.empty());
@@ -1680,7 +1832,9 @@
         UTF16ToUTF8(view_->GetCvc()),
         wallet_items_->obfuscated_gaia_id());
   } else if (IsPayingWithWallet()) {
-    SubmitWithWallet();
+    // TODO(dbeam): disallow interacting with the dialog while submitting.
+    // http://crbug.com/230932
+    AcceptLegalDocuments();
   } else {
     FinishSubmit();
   }
@@ -1757,9 +1911,9 @@
       content::Details<content::LoadCommittedDetails>(details).ptr();
   if (wallet::IsSignInContinueUrl(load_details->entry->GetVirtualURL())) {
     should_show_wallet_promo_ = false;
-    HideSignIn();
     account_chooser_model_.SelectActiveWalletAccount();
     GetWalletItems();
+    HideSignIn();
   }
 }
 
@@ -1784,7 +1938,11 @@
   }
 
   model->SetCheckedIndex(index);
-  PrepareDetailInputsForSection(SectionForSuggestionsMenuModel(*model));
+  DialogSection section = SectionForSuggestionsMenuModel(*model);
+  ResetSectionInput(section);
+  ShowEditUiIfBadSuggestion(section);
+  UpdateSection(section);
+  UpdateForErrors();
 
   LogSuggestionItemSelectedMetric(*model);
 }
@@ -1801,12 +1959,12 @@
 }
 
 std::string AutofillDialogControllerImpl::GetRiskData() const {
-  return risk_data_.empty() ? "no pagers" : risk_data_;
+  DCHECK(!risk_data_.empty());
+  return risk_data_;
 }
 
 void AutofillDialogControllerImpl::OnDidAcceptLegalDocuments() {
   DCHECK(is_submitting_ && IsPayingWithWallet());
-
   has_accepted_legal_documents_ = true;
   LoadRiskFingerprintData();
 }
@@ -1815,10 +1973,12 @@
   DCHECK(is_submitting_ && IsPayingWithWallet());
 
   // TODO(dbeam): use the returned full wallet. b/8332329
-  if (success)
+  if (success) {
     GetFullWallet();
-  else
+  } else {
     DisableWallet(wallet::WalletClient::UNKNOWN_ERROR);
+    SuggestionsUpdated();
+  }
 }
 
 void AutofillDialogControllerImpl::OnDidGetFullWallet(
@@ -1828,23 +1988,25 @@
   full_wallet_ = full_wallet.Pass();
 
   if (full_wallet_->required_actions().empty()) {
+    UpdateAutocheckoutStep(AUTOCHECKOUT_STEP_PROXY_CARD,
+                           AUTOCHECKOUT_STEP_COMPLETED);
     FinishSubmit();
     return;
   }
 
+  SetAutocheckoutState(AUTOCHECKOUT_NOT_STARTED);
+
   switch (full_wallet_->required_actions()[0]) {
     case wallet::CHOOSE_ANOTHER_INSTRUMENT_OR_ADDRESS:
       choose_another_instrument_or_address_ = true;
       SetIsSubmitting(false);
+      GetWalletItems();
       view_->UpdateNotificationArea();
       view_->UpdateButtonStrip();
-      GetWalletItems();
       break;
 
     case wallet::VERIFY_CVV:
       SuggestionsUpdated();
-      view_->UpdateNotificationArea();
-      view_->UpdateButtonStrip();
       break;
 
     default:
@@ -2080,10 +2242,6 @@
 }
 
 void AutofillDialogControllerImpl::LoadRiskFingerprintData() {
-  DCHECK(AreLegalDocumentsCurrent());
-
-  // Clear potential stale data to ensure |GetFullWalletIfReady()| triggers only
-  // when a new fingerprint is loaded.
   risk_data_.clear();
 
   uint64 obfuscated_gaia_id = 0;
@@ -2123,7 +2281,7 @@
   bool success = base::Base64Encode(proto_data, &risk_data_);
   DCHECK(success);
 
-  GetFullWalletIfReady();
+  SubmitWithWallet();
 }
 
 void AutofillDialogControllerImpl::OpenTabWithUrl(const GURL& url) {
@@ -2139,6 +2297,18 @@
 #endif
 }
 
+bool AutofillDialogControllerImpl::IsEditingExistingData(
+    DialogSection section) const {
+  return section_editing_state_.count(section) > 0;
+}
+
+bool AutofillDialogControllerImpl::IsManuallyEditingSection(
+    DialogSection section) const {
+  return IsEditingExistingData(section) ||
+         SuggestionsMenuModelForSection(section)->
+             GetItemKeyForCheckedItem() == kAddNewItemKey;
+}
+
 void AutofillDialogControllerImpl::OnWalletSigninError() {
   signin_helper_.reset();
   account_chooser_model_.SetHadWalletSigninError();
@@ -2152,11 +2322,21 @@
   wallet_items_.reset();
   wallet_errors_.clear();
   GetWalletClient()->CancelRequests();
+  SetAutocheckoutState(AUTOCHECKOUT_NOT_STARTED);
+  for (std::vector<DialogAutocheckoutStep>::iterator it = steps_.begin();
+      it != steps_.end(); ++it) {
+    if (it->type() == AUTOCHECKOUT_STEP_PROXY_CARD) {
+      steps_.erase(it);
+      break;
+    }
+  }
   SetIsSubmitting(false);
   account_chooser_model_.SetHadWalletError(WalletErrorMessage(error_type));
 }
 
 void AutofillDialogControllerImpl::SuggestionsUpdated() {
+  const DetailOutputMap snapshot = TakeUserInputSnapshot();
+
   suggested_email_.Reset();
   suggested_cc_.Reset();
   suggested_billing_.Reset();
@@ -2257,14 +2437,17 @@
     const std::vector<AutofillProfile*>& profiles = manager->GetProfiles();
     const std::string app_locale = g_browser_process->GetApplicationLocale();
     for (size_t i = 0; i < profiles.size(); ++i) {
-      if (!HasCompleteAndVerifiedData(*profiles[i], requested_shipping_fields_))
+      if (!HasCompleteAndVerifiedData(*profiles[i],
+                                      requested_shipping_fields_) ||
+          HasInvalidAddress(*profiles[i])) {
         continue;
+      }
 
       // Add all email addresses.
       std::vector<string16> values;
       profiles[i]->GetMultiInfo(EMAIL_ADDRESS, app_locale, &values);
       for (size_t j = 0; j < values.size(); ++j) {
-        if (!values[j].empty())
+        if (IsValidEmailAddress(values[j]))
           suggested_email_.AddKeyedItem(profiles[i]->guid(), values[j]);
       }
 
@@ -2331,9 +2514,19 @@
   if (view_)
     view_->ModelChanged();
 
-  for (size_t section = SECTION_MIN; section <= SECTION_MAX; ++section) {
-    PrepareDetailInputsForSection(static_cast<DialogSection>(section));
+  for (size_t i = SECTION_MIN; i <= SECTION_MAX; ++i) {
+    ResetSectionInput(static_cast<DialogSection>(i));
   }
+
+  RestoreUserInputFromSnapshot(snapshot);
+
+  for (size_t i = SECTION_MIN; i <= SECTION_MAX; ++i) {
+    DialogSection section = static_cast<DialogSection>(i);
+    ShowEditUiIfBadSuggestion(section);
+    UpdateSection(section);
+  }
+
+  UpdateForErrors();
 }
 
 void AutofillDialogControllerImpl::FillOutputForSectionWithComparator(
@@ -2529,11 +2722,6 @@
   input_showing_popup_ = NULL;
 }
 
-bool AutofillDialogControllerImpl::IsEditingExistingData(
-    DialogSection section) const {
-  return section_editing_state_.count(section) > 0;
-}
-
 void AutofillDialogControllerImpl::SetEditingExistingData(
     DialogSection section, bool editing) {
   if (editing)
@@ -2542,13 +2730,6 @@
     section_editing_state_.erase(section);
 }
 
-bool AutofillDialogControllerImpl::IsManuallyEditingSection(
-    DialogSection section) const {
-  return IsEditingExistingData(section) ||
-         SuggestionsMenuModelForSection(section)->
-             GetItemKeyForCheckedItem() == kAddNewItemKey;
-}
-
 bool AutofillDialogControllerImpl::IsASuggestionItemKey(
     const std::string& key) const {
   return !key.empty() &&
@@ -2671,17 +2852,10 @@
       (wallet_items_ && wallet_items_->legal_documents().empty());
 }
 
-void AutofillDialogControllerImpl::SubmitWithWallet() {
-  // TODO(dbeam): disallow interacting with the dialog while submitting.
-  // http://crbug.com/230932
-
-  active_instrument_id_.clear();
-  active_address_id_.clear();
-  full_wallet_.reset();
-
+void AutofillDialogControllerImpl::AcceptLegalDocuments() {
   content::BrowserThread::PostTask(
-     content::BrowserThread::IO, FROM_HERE,
-     base::Bind(&UserDidOptIntoLocationServices));
+      content::BrowserThread::IO, FROM_HERE,
+      base::Bind(&UserDidOptIntoLocationServices));
 
   GetWalletClient()->AcceptLegalDocuments(
       wallet_items_->legal_documents(),
@@ -2690,6 +2864,12 @@
 
   if (AreLegalDocumentsCurrent())
     LoadRiskFingerprintData();
+}
+
+void AutofillDialogControllerImpl::SubmitWithWallet() {
+  active_instrument_id_.clear();
+  active_address_id_.clear();
+  full_wallet_.reset();
 
   const wallet::WalletItems::MaskedInstrument* active_instrument =
       ActiveInstrument();
@@ -2705,6 +2885,11 @@
     DCHECK(!active_address_id_.empty());
   }
 
+  if (GetDialogType() == DIALOG_TYPE_AUTOCHECKOUT) {
+    DCHECK_EQ(AUTOCHECKOUT_NOT_STARTED, autocheckout_state_);
+    SetAutocheckoutState(AUTOCHECKOUT_IN_PROGRESS);
+  }
+
   scoped_ptr<wallet::Instrument> inputted_instrument =
       CreateTransientInstrument();
   scoped_ptr<wallet::WalletClient::UpdateInstrumentRequest> update_request =
@@ -2740,8 +2925,10 @@
 
   // If there's neither an address nor instrument to save, |GetFullWallet()|
   // is called when the risk fingerprint is loaded.
-  if (!active_instrument_id_.empty() && !active_address_id_.empty())
+  if (!active_instrument_id_.empty() && !active_address_id_.empty()) {
+    GetFullWallet();
     return;
+  }
 
   // If instrument and address aren't based off of any existing data, save both.
   if (inputted_instrument && inputted_address && !update_request &&
@@ -2832,6 +3019,9 @@
   std::vector<wallet::WalletClient::RiskCapability> capabilities;
   capabilities.push_back(wallet::WalletClient::VERIFY_CVC);
 
+  UpdateAutocheckoutStep(AUTOCHECKOUT_STEP_PROXY_CARD,
+                         AUTOCHECKOUT_STEP_STARTED);
+
   GetWalletClient()->GetFullWallet(wallet::WalletClient::FullWalletRequest(
       active_instrument_id_,
       active_address_id_,
@@ -2844,10 +3034,8 @@
   DCHECK(is_submitting_);
   DCHECK(IsPayingWithWallet());
 
-  if (!active_instrument_id_.empty() && !active_address_id_.empty() &&
-      !risk_data_.empty()) {
+  if (!active_instrument_id_.empty() && !active_address_id_.empty())
     GetFullWallet();
-  }
 }
 
 void AutofillDialogControllerImpl::HandleSaveOrUpdateRequiredActions(
@@ -2864,7 +3052,7 @@
       DisableWallet(wallet::WalletClient::UNKNOWN_ERROR);
     }
   }
-
+  SetAutocheckoutState(AUTOCHECKOUT_NOT_STARTED);
   SetIsSubmitting(false);
 }
 
@@ -2922,11 +3110,7 @@
     // in an Autocheckout flow.
     GetManager()->RemoveObserver(this);
     autocheckout_started_timestamp_ = base::Time::Now();
-    DCHECK_EQ(AUTOCHECKOUT_NOT_STARTED, autocheckout_state_);
-    autocheckout_state_ = AUTOCHECKOUT_IN_PROGRESS;
-    view_->UpdateButtonStrip();
-    view_->UpdateDetailArea();
-    view_->UpdateNotificationArea();
+    SetAutocheckoutState(AUTOCHECKOUT_IN_PROGRESS);
   }
 
   LogOnFinishSubmitMetrics();
@@ -3076,6 +3260,20 @@
   was_ui_latency_logged_ = true;
 }
 
+void AutofillDialogControllerImpl::SetAutocheckoutState(
+    AutocheckoutState autocheckout_state) {
+  if (autocheckout_state_ == autocheckout_state)
+    return;
+
+  autocheckout_state_ = autocheckout_state;
+  if (view_) {
+    view_->UpdateDetailArea();
+    view_->UpdateButtonStrip();
+    view_->UpdateAutocheckoutStepsArea();
+    view_->UpdateNotificationArea();
+  }
+}
+
 AutofillMetrics::DialogInitialUserStateMetric
     AutofillDialogControllerImpl::GetInitialUserState() const {
   // Consider a user to be an Autofill user if the user has any credit cards
diff --git a/chrome/browser/ui/autofill/autofill_dialog_controller_impl.h b/chrome/browser/ui/autofill/autofill_dialog_controller_impl.h
index cf4587a..598c6e5 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_controller_impl.h
+++ b/chrome/browser/ui/autofill/autofill_dialog_controller_impl.h
@@ -12,24 +12,25 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/strings/string16.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/ui/autofill/account_chooser_model.h"
 #include "chrome/browser/ui/autofill/autofill_dialog_controller.h"
 #include "chrome/browser/ui/autofill/autofill_dialog_models.h"
 #include "chrome/browser/ui/autofill/autofill_dialog_types.h"
 #include "chrome/browser/ui/autofill/autofill_popup_controller_impl.h"
 #include "chrome/browser/ui/autofill/country_combobox_model.h"
-#include "components/autofill/browser/autofill_manager_delegate.h"
-#include "components/autofill/browser/autofill_metrics.h"
-#include "components/autofill/browser/autofill_popup_delegate.h"
-#include "components/autofill/browser/field_types.h"
-#include "components/autofill/browser/form_structure.h"
-#include "components/autofill/browser/personal_data_manager.h"
-#include "components/autofill/browser/personal_data_manager_observer.h"
+#include "components/autofill/content/browser/autocheckout_steps.h"
 #include "components/autofill/content/browser/wallet/wallet_client.h"
 #include "components/autofill/content/browser/wallet/wallet_client_delegate.h"
 #include "components/autofill/content/browser/wallet/wallet_items.h"
 #include "components/autofill/content/browser/wallet/wallet_signin_helper_delegate.h"
+#include "components/autofill/core/browser/autofill_manager_delegate.h"
+#include "components/autofill/core/browser/autofill_metrics.h"
+#include "components/autofill/core/browser/autofill_popup_delegate.h"
+#include "components/autofill/core/browser/field_types.h"
+#include "components/autofill/core/browser/form_structure.h"
+#include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/autofill/core/browser/personal_data_manager_observer.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "content/public/common/ssl_status.h"
@@ -53,6 +54,7 @@
 class AutofillDialogView;
 class AutofillPopupControllerImpl;
 class DataModelWrapper;
+class TestableAutofillDialogView;
 
 namespace risk {
 class Fingerprint;
@@ -88,19 +90,26 @@
   void Show();
   void Hide();
 
-  // Updates the progress bar based on the Autocheckout progress. |value| should
-  // be in [0.0, 1.0].
-  void UpdateProgressBar(double value);
-
   // Whether Autocheckout is currently running.
   bool AutocheckoutIsRunning() const;
 
+  // Adds a step in the flow to the Autocheckout UI.
+  void AddAutocheckoutStep(AutocheckoutStepType step_type);
+
+  // Updates the status of a step in the Autocheckout UI.
+  void UpdateAutocheckoutStep(AutocheckoutStepType step_type,
+                              AutocheckoutStepStatus step_status);
+
   // Called when there is an error in an active Autocheckout flow.
   void OnAutocheckoutError();
 
   // Called when an Autocheckout flow completes successfully.
   void OnAutocheckoutSuccess();
 
+  // Returns |view_| as a testable version of itself (if |view_| exists and
+  // actually implements |AutofillDialogView::GetTestableView()|).
+  TestableAutofillDialogView* GetTestableView();
+
   // AutofillDialogController implementation.
   virtual string16 DialogTitle() const OVERRIDE;
   virtual string16 AccountChooserText() const OVERRIDE;
@@ -109,7 +118,6 @@
   virtual string16 CancelButtonText() const OVERRIDE;
   virtual string16 ConfirmButtonText() const OVERRIDE;
   virtual string16 SaveLocallyText() const OVERRIDE;
-  virtual string16 ProgressBarText() const OVERRIDE;
   virtual string16 LegalDocumentsText() OVERRIDE;
   virtual DialogSignedInState SignedInState() const OVERRIDE;
   virtual bool ShouldShowSpinner() const OVERRIDE;
@@ -157,6 +165,8 @@
   virtual gfx::Image SplashPageImage() const OVERRIDE;
   virtual void ViewClosed() OVERRIDE;
   virtual std::vector<DialogNotification> CurrentNotifications() OVERRIDE;
+  virtual std::vector<DialogAutocheckoutStep> CurrentAutocheckoutSteps()
+      const OVERRIDE;
   virtual void SignInLinkClicked() OVERRIDE;
   virtual void NotificationCheckboxStateChanged(DialogNotification::Type type,
                                                 bool checked) OVERRIDE;
@@ -283,18 +293,22 @@
   // happens when a user clicks "Edit" or a suggestion is invalid.
   virtual bool IsEditingExistingData(DialogSection section) const;
 
+  // Whether the user has chosen to enter all new data in |section|. This
+  // happens via choosing "Add a new X..." from a section's suggestion menu.
+  bool IsManuallyEditingSection(DialogSection section) const;
+
   // Should be called on the Wallet sign-in error.
   virtual void OnWalletSigninError();
 
+  // Whether the information input in this dialog will be securely transmitted
+  // to the requesting site.
+  virtual bool TransmissionWillBeSecure() const;
+
  private:
   // Whether or not the current request wants credit info back.
   bool RequestingCreditCardInfo() const;
 
-  // Whether the information input in this dialog will be securely transmitted
-  // to the requesting site.
-  bool TransmissionWillBeSecure() const;
-
-  // Initializes |suggested_email_| et al.
+  // Initializes or updates |suggested_email_| et al.
   void SuggestionsUpdated();
 
   // Whether the user's wallet items have at least one address and instrument.
@@ -321,9 +335,32 @@
   // they have not already been calculated.
   void EnsureLegalDocumentsText();
 
-  // Clears previously entered manual input, shows editing UI if the current
-  // suggestion is invalid, and updates the |view_| (if it exists).
-  void PrepareDetailInputsForSection(DialogSection section);
+  // Clears previously entered manual input and removes |section| from
+  // |section_editing_state_|. Does not update the view.
+  void ResetSectionInput(DialogSection section);
+
+  // Force |section| into edit mode if the current suggestion is invalid.
+  void ShowEditUiIfBadSuggestion(DialogSection section);
+
+  // Whether the |value| of |input| should be preserved on account change.
+  bool InputWasEdited(const DetailInput& input,
+                      const base::string16& value);
+
+  // Takes a snapshot of the newly inputted user data in |view_| (if it exists).
+  DetailOutputMap TakeUserInputSnapshot();
+
+  // Fills the detail inputs from a previously taken user input snapshot. Does
+  // not update the view.
+  void RestoreUserInputFromSnapshot(const DetailOutputMap& snapshot);
+
+  // Tells the view to update |section|.
+  void UpdateSection(DialogSection section);
+
+  // Tells |view_| to update the validity status of its detail inputs (if
+  // |view_| is non-null). Currently this is used solely for highlighting
+  // invalid suggestions, so if no sections are based on existing data,
+  // |view_->UpdateForErrors()| is not called.
+  void UpdateForErrors();
 
   // Creates a DataModelWrapper item for the item that's checked in the
   // suggestion model for |section|. This may represent Autofill
@@ -403,10 +440,6 @@
   // existing Wallet or Autofill data.
   void SetEditingExistingData(DialogSection section, bool editing);
 
-  // Whether the user has chosen to enter all new data in |section|. This
-  // happens via choosing "Add a new X..." from a section's suggestion menu.
-  bool IsManuallyEditingSection(DialogSection section) const;
-
   // Whether the user has chosen to enter all new data in at least one section.
   bool IsManuallyEditingAnySection() const;
 
@@ -446,6 +479,9 @@
   // Whether the user has accepted all the current legal documents' terms.
   bool AreLegalDocumentsCurrent() const;
 
+  // Accepts any pending legal documents now that the user has pressed Submit.
+  void AcceptLegalDocuments();
+
   // Start the submit proccess to interact with Online Wallet (might do various
   // things like accept documents, save details, update details, respond to
   // required actions, etc.).
@@ -518,6 +554,9 @@
   // interact with it.
   void LogDialogLatencyToShow();
 
+  // Sets the state of the autocheckout flow.
+  void SetAutocheckoutState(AutocheckoutState autocheckout_state);
+
   // Returns the metric corresponding to the user's initial state when
   // interacting with this dialog.
   AutofillMetrics::DialogInitialUserStateMetric GetInitialUserState() const;
@@ -666,6 +705,10 @@
   // Whether the latency to display to the UI was logged to UMA yet.
   bool was_ui_latency_logged_;
 
+  // State of steps in the current Autocheckout flow, or empty if not an
+  // Autocheckout use case.
+  std::vector<DialogAutocheckoutStep> steps_;
+
   DISALLOW_COPY_AND_ASSIGN(AutofillDialogControllerImpl);
 };
 
diff --git a/chrome/browser/ui/autofill/autofill_dialog_controller_unittest.cc b/chrome/browser/ui/autofill/autofill_dialog_controller_unittest.cc
index ab4557d..6249f5d 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_controller_unittest.cc
+++ b/chrome/browser/ui/autofill/autofill_dialog_controller_unittest.cc
@@ -16,9 +16,6 @@
 #include "chrome/browser/ui/autofill/autofill_dialog_view.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/autofill/browser/autofill_common_test.h"
-#include "components/autofill/browser/autofill_metrics.h"
-#include "components/autofill/browser/test_personal_data_manager.h"
 #include "components/autofill/content/browser/risk/proto/fingerprint.pb.h"
 #include "components/autofill/content/browser/wallet/full_wallet.h"
 #include "components/autofill/content/browser/wallet/instrument.h"
@@ -26,6 +23,9 @@
 #include "components/autofill/content/browser/wallet/wallet_client.h"
 #include "components/autofill/content/browser/wallet/wallet_service_url.h"
 #include "components/autofill/content/browser/wallet/wallet_test_util.h"
+#include "components/autofill/core/browser/autofill_common_test.h"
+#include "components/autofill/core/browser/autofill_metrics.h"
+#include "components/autofill/core/browser/test_personal_data_manager.h"
 #include "components/autofill/core/common/autofill_switches.h"
 #include "components/autofill/core/common/form_data.h"
 #include "content/public/browser/web_contents.h"
@@ -91,6 +91,13 @@
   }
 }
 
+scoped_ptr<wallet::WalletItems> CompleteAndValidWalletItems() {
+  scoped_ptr<wallet::WalletItems> items = wallet::GetTestWalletItems();
+  items->AddInstrument(wallet::GetTestMaskedInstrument());
+  items->AddAddress(wallet::GetTestShippingAddress());
+  return items.Pass();
+}
+
 scoped_ptr<wallet::FullWallet> CreateFullWallet(const char* required_action) {
   base::DictionaryValue dict;
   scoped_ptr<base::ListValue> list(new base::ListValue());
@@ -118,6 +125,7 @@
   virtual void UpdateAccountChooser() OVERRIDE {}
   virtual void UpdateButtonStrip() OVERRIDE {}
   virtual void UpdateDetailArea() OVERRIDE {}
+  virtual void UpdateAutocheckoutStepsArea() OVERRIDE {}
   virtual void UpdateSection(DialogSection section) OVERRIDE {}
   virtual void FillSection(DialogSection section,
                            const DetailInput& originating_input) OVERRIDE {};
@@ -294,6 +302,12 @@
     open_tab_url_ = url;
   }
 
+  // Whether the information input in this dialog will be securely transmitted
+  // to the requesting site.
+  virtual bool TransmissionWillBeSecure() const OVERRIDE {
+    return true;
+  }
+
  private:
   // To specify our own metric logger.
   virtual const AutofillMetrics& GetMetricLogger() const OVERRIDE {
@@ -412,6 +426,16 @@
     EXPECT_EQ(should_pass ? 0U : 1U, validity_data.count(CREDIT_CARD_NUMBER));
   }
 
+  void SubmitWithWalletItems(scoped_ptr<wallet::WalletItems> wallet_items) {
+    controller()->OnDidGetWalletItems(wallet_items.Pass());
+    AcceptAndLoadFakeFingerprint();
+  }
+
+  void AcceptAndLoadFakeFingerprint() {
+    controller()->OnAccept();
+    controller()->OnDidLoadRiskFingerprintData(GetFakeFingerprint().Pass());
+  }
+
   TestAutofillDialogController* controller() { return controller_.get(); }
 
   TestingProfile* profile() { return &profile_; }
@@ -796,7 +820,7 @@
   EXPECT_EQ(1, email_suggestions->checked_item());
 }
 
-TEST_F(AutofillDialogControllerTest, ValidSavedEmail) {
+TEST_F(AutofillDialogControllerTest, SuggestValidEmail) {
   AutofillProfile profile(test::GetVerifiedProfile());
   const string16 kValidEmail = ASCIIToUTF16(kFakeEmail);
   profile.SetRawInfo(EMAIL_ADDRESS, kValidEmail);
@@ -807,14 +831,47 @@
             controller()->SuggestionStateForSection(SECTION_EMAIL).text);
 }
 
-TEST_F(AutofillDialogControllerTest, InvalidSavedEmail) {
+TEST_F(AutofillDialogControllerTest, DoNotSuggestInvalidEmail) {
   AutofillProfile profile(test::GetVerifiedProfile());
   profile.SetRawInfo(EMAIL_ADDRESS, ASCIIToUTF16(".!#$%&'*+/=?^_`-@-.."));
   controller()->GetTestingManager()->AddTestingProfile(&profile);
+  EXPECT_EQ(static_cast<ui::MenuModel*>(NULL),
+            controller()->MenuModelForSection(SECTION_EMAIL));
+}
 
-  controller()->MenuModelForSection(SECTION_EMAIL)->ActivatedAt(0);
-  EXPECT_TRUE(
-      controller()->SuggestionStateForSection(SECTION_EMAIL).text.empty());
+TEST_F(AutofillDialogControllerTest, DoNotSuggestEmailFromIncompleteProfile) {
+  AutofillProfile profile(test::GetVerifiedProfile());
+  profile.SetRawInfo(EMAIL_ADDRESS, ASCIIToUTF16(kFakeEmail));
+  profile.SetRawInfo(ADDRESS_HOME_STATE, base::string16());
+  controller()->GetTestingManager()->AddTestingProfile(&profile);
+  EXPECT_EQ(static_cast<ui::MenuModel*>(NULL),
+            controller()->MenuModelForSection(SECTION_EMAIL));
+}
+
+TEST_F(AutofillDialogControllerTest, DoNotSuggestEmailFromInvalidProfile) {
+  AutofillProfile profile(test::GetVerifiedProfile());
+  profile.SetRawInfo(EMAIL_ADDRESS, ASCIIToUTF16(kFakeEmail));
+  profile.SetRawInfo(ADDRESS_HOME_STATE, ASCIIToUTF16("C"));
+  controller()->GetTestingManager()->AddTestingProfile(&profile);
+  EXPECT_EQ(static_cast<ui::MenuModel*>(NULL),
+            controller()->MenuModelForSection(SECTION_EMAIL));
+}
+
+TEST_F(AutofillDialogControllerTest, SuggestValidAddress) {
+  AutofillProfile full_profile(test::GetVerifiedProfile());
+  full_profile.set_origin(kSettingsOrigin);
+  controller()->GetTestingManager()->AddTestingProfile(&full_profile);
+  EXPECT_EQ(
+      4, controller()->MenuModelForSection(SECTION_SHIPPING)->GetItemCount());
+}
+
+TEST_F(AutofillDialogControllerTest, DoNotSuggestInvalidAddress) {
+  AutofillProfile full_profile(test::GetVerifiedProfile());
+  full_profile.set_origin(kSettingsOrigin);
+  full_profile.SetRawInfo(ADDRESS_HOME_STATE, ASCIIToUTF16("C"));
+  controller()->GetTestingManager()->AddTestingProfile(&full_profile);
+  EXPECT_EQ(
+      3, controller()->MenuModelForSection(SECTION_SHIPPING)->GetItemCount());
 }
 
 TEST_F(AutofillDialogControllerTest, AutofillCreditCards) {
@@ -964,10 +1021,8 @@
               GetFullWallet(_)).Times(1);
   EXPECT_CALL(*controller(), LoadRiskFingerprintData()).Times(1);
 
-  scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
+  scoped_ptr<wallet::WalletItems> wallet_items = CompleteAndValidWalletItems();
   wallet_items->AddLegalDocument(wallet::GetTestLegalDocument());
-  wallet_items->AddInstrument(wallet::GetTestMaskedInstrument());
-  wallet_items->AddAddress(wallet::GetTestShippingAddress());
   controller()->OnDidGetWalletItems(wallet_items.Pass());
   controller()->OnAccept();
   controller()->OnDidAcceptLegalDocuments();
@@ -1063,7 +1118,7 @@
   ui::MenuModel* shipping_model =
       controller()->MenuModelForSection(SECTION_SHIPPING);
   shipping_model->ActivatedAt(shipping_model->GetItemCount() - 1);
-  controller()->OnAccept();
+  AcceptAndLoadFakeFingerprint();
 }
 
 TEST_F(AutofillDialogControllerTest, SaveInstrument) {
@@ -1073,8 +1128,7 @@
 
   scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
   wallet_items->AddAddress(wallet::GetTestShippingAddress());
-  controller()->OnDidGetWalletItems(wallet_items.Pass());
-  controller()->OnAccept();
+  SubmitWithWalletItems(wallet_items.Pass());
 }
 
 TEST_F(AutofillDialogControllerTest, SaveInstrumentWithInvalidInstruments) {
@@ -1085,8 +1139,7 @@
   scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
   wallet_items->AddAddress(wallet::GetTestShippingAddress());
   wallet_items->AddInstrument(wallet::GetTestMaskedInstrumentInvalid());
-  controller()->OnDidGetWalletItems(wallet_items.Pass());
-  controller()->OnAccept();
+  SubmitWithWalletItems(wallet_items.Pass());
 }
 
 TEST_F(AutofillDialogControllerTest, SaveInstrumentAndAddress) {
@@ -1094,7 +1147,7 @@
               SaveInstrumentAndAddress(_, _, _, _)).Times(1);
 
   controller()->OnDidGetWalletItems(wallet::GetTestWalletItems());
-  controller()->OnAccept();
+  AcceptAndLoadFakeFingerprint();
 }
 
 // Tests that editing an address (in wallet mode0 and submitting the dialog
@@ -1103,25 +1156,19 @@
   EXPECT_CALL(*controller()->GetTestingWalletClient(),
               UpdateAddress(_, _)).Times(1);
 
-  scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
-  wallet_items->AddInstrument(wallet::GetTestMaskedInstrument());
-  wallet_items->AddAddress(wallet::GetTestShippingAddress());
-  controller()->OnDidGetWalletItems(wallet_items.Pass());
+  controller()->OnDidGetWalletItems(CompleteAndValidWalletItems());
 
   controller()->EditClickedForSection(SECTION_SHIPPING);
-  controller()->OnAccept();
+  AcceptAndLoadFakeFingerprint();
 }
 
 // Tests that editing an instrument (CC + address) in wallet mode updates an
 // existing instrument on the server via WalletClient.
 TEST_F(AutofillDialogControllerTest, UpdateInstrument) {
-  scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
-  wallet_items->AddInstrument(wallet::GetTestMaskedInstrument());
-  wallet_items->AddAddress(wallet::GetTestShippingAddress());
-  controller()->OnDidGetWalletItems(wallet_items.Pass());
+  controller()->OnDidGetWalletItems(CompleteAndValidWalletItems());
 
   controller()->EditClickedForSection(SECTION_CC_BILLING);
-  controller()->OnAccept();
+  AcceptAndLoadFakeFingerprint();
 
   EXPECT_TRUE(
       controller()->GetTestingWalletClient()->updated_billing_address());
@@ -1138,7 +1185,7 @@
   controller()->OnDidGetWalletItems(wallet_items.Pass());
 
   controller()->EditClickedForSection(SECTION_CC_BILLING);
-  controller()->OnAccept();
+  AcceptAndLoadFakeFingerprint();
 
   EXPECT_TRUE(
       controller()->GetTestingWalletClient()->updated_billing_address());
@@ -1157,7 +1204,7 @@
   controller()->OnDidGetWalletItems(wallet_items.Pass());
 
   controller()->EditClickedForSection(SECTION_SHIPPING);
-  controller()->OnAccept();
+  AcceptAndLoadFakeFingerprint();
 }
 
 MATCHER(UsesLocalBillingAddress, "uses the local billing address") {
@@ -1170,15 +1217,11 @@
   EXPECT_CALL(*controller()->GetTestingWalletClient(),
               SaveAddress(_, _)).Times(1);
 
-  scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
-  wallet_items->AddInstrument(wallet::GetTestMaskedInstrument());
-  wallet_items->AddAddress(wallet::GetTestShippingAddress());
-
-  controller()->OnDidGetWalletItems(wallet_items.Pass());
+  controller()->OnDidGetWalletItems(CompleteAndValidWalletItems());
   // Select "Same as billing" in the address menu.
   UseBillingForShipping();
 
-  controller()->OnAccept();
+  AcceptAndLoadFakeFingerprint();
 }
 
 // Tests that when using billing address for shipping, and there is an exact
@@ -1202,7 +1245,7 @@
   // Select "Same as billing" in the address menu.
   UseBillingForShipping();
 
-  controller()->OnAccept();
+  AcceptAndLoadFakeFingerprint();
 }
 
 // Tests that adding new instrument and also using billing address for shipping,
@@ -1218,7 +1261,7 @@
   // Select "Same as billing" in the address menu.
   UseBillingForShipping();
 
-  controller()->OnAccept();
+  AcceptAndLoadFakeFingerprint();
 }
 
 // Test that the local view contents is used when saving a new instrument and
@@ -1243,7 +1286,7 @@
 
   EXPECT_CALL(*controller()->GetTestingWalletClient(),
               SaveAddress(UsesLocalBillingAddress(), _)).Times(1);
-  controller()->OnAccept();
+  AcceptAndLoadFakeFingerprint();
 
   EXPECT_TRUE(
       controller()->GetTestingWalletClient()->updated_billing_address());
@@ -1456,12 +1499,7 @@
   EXPECT_CALL(*controller()->GetTestingWalletClient(),
               AuthenticateInstrument(_, _, _)).Times(1);
 
-  scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
-  wallet_items->AddInstrument(wallet::GetTestMaskedInstrument());
-  wallet_items->AddAddress(wallet::GetTestShippingAddress());
-  controller()->OnDidGetWalletItems(wallet_items.Pass());
-  controller()->OnAccept();
-  controller()->OnDidLoadRiskFingerprintData(GetFakeFingerprint().Pass());
+  SubmitWithWalletItems(CompleteAndValidWalletItems());
 
   EXPECT_TRUE(NotificationsOfType(DialogNotification::REQUIRED_ACTION).empty());
   EXPECT_TRUE(controller()->SectionIsActive(SECTION_SHIPPING));
@@ -1495,12 +1533,7 @@
   EXPECT_CALL(*controller()->GetTestingWalletClient(),
               GetFullWallet(_)).Times(1);
 
-  scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
-  wallet_items->AddInstrument(wallet::GetTestMaskedInstrument());
-  wallet_items->AddAddress(wallet::GetTestShippingAddress());
-  controller()->OnDidGetWalletItems(wallet_items.Pass());
-  controller()->OnAccept();
-  controller()->OnDidLoadRiskFingerprintData(GetFakeFingerprint().Pass());
+  SubmitWithWalletItems(CompleteAndValidWalletItems());
 
   EXPECT_FALSE(controller()->IsDialogButtonEnabled(ui::DIALOG_BUTTON_OK));
   EXPECT_FALSE(controller()->IsDialogButtonEnabled(ui::DIALOG_BUTTON_CANCEL));
@@ -1516,12 +1549,7 @@
   EXPECT_CALL(*controller()->GetTestingWalletClient(),
               GetFullWallet(_)).Times(1);
 
-  scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
-  wallet_items->AddInstrument(wallet::GetTestMaskedInstrument());
-  wallet_items->AddAddress(wallet::GetTestShippingAddress());
-  controller()->OnDidGetWalletItems(wallet_items.Pass());
-  controller()->OnAccept();
-  controller()->OnDidLoadRiskFingerprintData(GetFakeFingerprint().Pass());
+  SubmitWithWalletItems(CompleteAndValidWalletItems());
 
   EXPECT_FALSE(controller()->IsDialogButtonEnabled(ui::DIALOG_BUTTON_OK));
   EXPECT_FALSE(controller()->IsDialogButtonEnabled(ui::DIALOG_BUTTON_CANCEL));
@@ -1537,12 +1565,7 @@
   EXPECT_CALL(*controller()->GetTestingWalletClient(),
               GetFullWallet(_)).Times(1);
 
-  scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
-  wallet_items->AddInstrument(wallet::GetTestMaskedInstrument());
-  wallet_items->AddAddress(wallet::GetTestShippingAddress());
-  controller()->OnDidGetWalletItems(wallet_items.Pass());
-  controller()->OnAccept();
-  controller()->OnDidLoadRiskFingerprintData(GetFakeFingerprint().Pass());
+  SubmitWithWalletItems(CompleteAndValidWalletItems());
   controller()->OnDidGetFullWallet(CreateFullWallet("verify_cvv"));
 
   ASSERT_TRUE(controller()->IsDialogButtonEnabled(ui::DIALOG_BUTTON_OK));
@@ -1559,12 +1582,7 @@
   EXPECT_CALL(*controller()->GetTestingWalletClient(),
               GetFullWallet(_)).Times(1);
 
-  scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
-  wallet_items->AddInstrument(wallet::GetTestMaskedInstrument());
-  wallet_items->AddAddress(wallet::GetTestShippingAddress());
-  controller()->OnDidGetWalletItems(wallet_items.Pass());
-  controller()->OnAccept();
-  controller()->OnDidLoadRiskFingerprintData(GetFakeFingerprint().Pass());
+  SubmitWithWalletItems(CompleteAndValidWalletItems());
   controller()->OnDidGetFullWallet(CreateFullWallet("verify_cvv"));
 
   ASSERT_TRUE(controller()->IsDialogButtonEnabled(ui::DIALOG_BUTTON_OK));
@@ -1613,7 +1631,6 @@
       wallet::FormFieldError(wallet::FormFieldError::UNKNOWN_ERROR,
                              wallet::FormFieldError::UNKNOWN_LOCATION));
 
-  EXPECT_CALL(*controller()->GetView(), UpdateForErrors()).Times(1);
   controller()->OnDidSaveAddress(std::string(), required_actions, form_errors);
 
   EXPECT_EQ(1U, NotificationsOfType(
@@ -1624,6 +1641,8 @@
 // where Chrome got the user's data (i.e. "Got details from Wallet") or promote
 // saving details into Wallet (i.e. "[x] Save details to Wallet").
 TEST_F(AutofillDialogControllerTest, WalletBanners) {
+  CommandLine* command_line = CommandLine::ForCurrentProcess();
+  command_line->AppendSwitch(switches::kWalletServiceUseProd);
   PrefService* prefs = controller()->profile()->GetPrefs();
   ASSERT_FALSE(prefs->GetBoolean(::prefs::kAutofillDialogHasPaidWithWallet));
 
@@ -1633,10 +1652,7 @@
       DialogNotification::WALLET_USAGE_CONFIRMATION).size());
 
   // Sign in a user with a completed account.
-  scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
-  wallet_items->AddInstrument(wallet::GetTestMaskedInstrument());
-  wallet_items->AddAddress(wallet::GetTestShippingAddress());
-  controller()->OnDidGetWalletItems(wallet_items.Pass());
+  controller()->OnDidGetWalletItems(CompleteAndValidWalletItems());
 
   // Full account; should show "Details from Wallet" message.
   EXPECT_EQ(1U, NotificationsOfType(
@@ -1657,7 +1673,7 @@
   prefs->SetBoolean(::prefs::kAutofillDialogHasPaidWithWallet, true);
 
   // Sign in a user with a incomplete account.
-  wallet_items = wallet::GetTestWalletItems();
+  scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
   wallet_items->AddInstrument(wallet::GetTestMaskedInstrument());
   controller()->OnDidGetWalletItems(wallet_items.Pass());
 
@@ -1695,10 +1711,7 @@
   EXPECT_EQ(0U, NotificationsOfType(
       DialogNotification::WALLET_USAGE_CONFIRMATION).size());
 
-  wallet_items = wallet::GetTestWalletItems();
-  wallet_items->AddInstrument(wallet::GetTestMaskedInstrument());
-  wallet_items->AddAddress(wallet::GetTestShippingAddress());
-  controller()->OnDidGetWalletItems(wallet_items.Pass());
+  controller()->OnDidGetWalletItems(CompleteAndValidWalletItems());
 
   EXPECT_EQ(0U, NotificationsOfType(
       DialogNotification::EXPLANATORY_MESSAGE).size());
@@ -1735,13 +1748,25 @@
 }
 
 TEST_F(AutofillDialogControllerTest, OnAutocheckoutSuccess) {
-  SwitchToAutofill();
+  CommandLine* command_line = CommandLine::ForCurrentProcess();
+  command_line->AppendSwitch(switches::kWalletServiceUseProd);
   controller()->set_dialog_type(DIALOG_TYPE_AUTOCHECKOUT);
 
-  // We also have to simulate CC inputs to keep the controller happy.
-  FillCreditCardInputs();
+  // Sign in a user with a completed account.
+  controller()->OnDidGetWalletItems(CompleteAndValidWalletItems());
 
-  controller()->OnAccept();
+  // Full account; should show "Details from Wallet" message.
+  EXPECT_EQ(1U, NotificationsOfType(
+      DialogNotification::EXPLANATORY_MESSAGE).size());
+  EXPECT_EQ(0U, NotificationsOfType(
+      DialogNotification::WALLET_USAGE_CONFIRMATION).size());
+
+  AcceptAndLoadFakeFingerprint();
+  controller()->OnDidGetFullWallet(wallet::GetTestFullWallet());
+
+  EXPECT_EQ(0U, NotificationsOfType(
+      DialogNotification::EXPLANATORY_MESSAGE).size());
+
   controller()->OnAutocheckoutSuccess();
 
   EXPECT_TRUE(controller()->IsDialogButtonEnabled(ui::DIALOG_BUTTON_CANCEL));
@@ -1750,6 +1775,8 @@
       DialogNotification::AUTOCHECKOUT_SUCCESS).size());
   EXPECT_EQ(0U, NotificationsOfType(
       DialogNotification::AUTOCHECKOUT_ERROR).size());
+  EXPECT_EQ(0U, NotificationsOfType(
+      DialogNotification::EXPLANATORY_MESSAGE).size());
 }
 
 TEST_F(AutofillDialogControllerTest, ViewCancelDoesntSetPref) {
@@ -1832,9 +1859,7 @@
   SwitchToWallet();
 
   // Setup some wallet state, submit, and get a full wallet to end the flow.
-  scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
-  wallet_items->AddInstrument(wallet::GetTestMaskedInstrument());
-  wallet_items->AddAddress(wallet::GetTestShippingAddress());
+  scoped_ptr<wallet::WalletItems> wallet_items = CompleteAndValidWalletItems();
 
   // Filling |form_structure()| depends on the current username and wallet items
   // being fetched. Until both of these have occurred, the user should not be
@@ -1897,6 +1922,10 @@
 
 // Tests that user is prompted when using instrument with minimal address.
 TEST_F(AutofillDialogControllerTest, UpgradeMinimalAddress) {
+  // A minimal address being selected should trigger error validation in the
+  // view. Called once for each incomplete suggestion.
+  EXPECT_CALL(*controller()->GetView(), UpdateForErrors()).Times(1);
+
   scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
   wallet_items->AddInstrument(wallet::GetTestMaskedInstrumentWithIdAndAddress(
       "id", wallet::GetTestMinimalAddress()));
@@ -1919,23 +1948,6 @@
   wallet_items->AddLegalDocument(wallet::GetTestLegalDocument());
   controller()->OnDidGetWalletItems(wallet_items.Pass());
   controller()->OnAccept();
-
-  EXPECT_EQ("no pagers", controller()->GetRiskData());
-}
-
-TEST_F(AutofillDialogControllerTest, RiskLoadsWithoutPendingLegalDocuments) {
-  EXPECT_CALL(*controller(), LoadRiskFingerprintData()).Times(1);
-
-  scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
-  wallet_items->AddInstrument(wallet::GetTestMaskedInstrument());
-  wallet_items->AddAddress(wallet::GetTestShippingAddress());
-  controller()->OnDidGetWalletItems(wallet_items.Pass());
-  controller()->OnAccept();
-
-  EXPECT_EQ("no pagers", controller()->GetRiskData());
-
-  controller()->OnDidLoadRiskFingerprintData(GetFakeFingerprint().Pass());
-  EXPECT_EQ(kFakeFingerprintEncoded, controller()->GetRiskData());
 }
 
 TEST_F(AutofillDialogControllerTest, RiskLoadsAfterAcceptingLegalDocuments) {
@@ -1949,7 +1961,6 @@
   EXPECT_CALL(*controller(), LoadRiskFingerprintData()).Times(1);
 
   controller()->OnAccept();
-  EXPECT_EQ("no pagers", controller()->GetRiskData());
 
   // Simulate a risk load and verify |GetRiskData()| matches the encoded value.
   controller()->OnDidAcceptLegalDocuments();
@@ -2059,26 +2070,112 @@
 }
 
 TEST_F(AutofillDialogControllerTest, ChooseAnotherInstrumentOrAddress) {
-  scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
-  wallet_items->AddInstrument(wallet::GetTestMaskedInstrument());
-  wallet_items->AddAddress(wallet::GetTestShippingAddress());
-  controller()->OnDidGetWalletItems(wallet_items.Pass());
-  controller()->OnAccept();
-  controller()->OnDidLoadRiskFingerprintData(GetFakeFingerprint().Pass());
+  SubmitWithWalletItems(CompleteAndValidWalletItems());
 
   EXPECT_EQ(0U, NotificationsOfType(
       DialogNotification::REQUIRED_ACTION).size());
-
   EXPECT_CALL(*controller()->GetTestingWalletClient(),
               GetWalletItems(_)).Times(1);
   controller()->OnDidGetFullWallet(
       CreateFullWallet("choose_another_instrument_or_address"));
   EXPECT_EQ(1U, NotificationsOfType(
       DialogNotification::REQUIRED_ACTION).size());
+  controller()->OnDidGetWalletItems(CompleteAndValidWalletItems());
 
   controller()->OnAccept();
   EXPECT_EQ(0U, NotificationsOfType(
       DialogNotification::REQUIRED_ACTION).size());
 }
 
+// Make sure detailed steps for Autocheckout are added
+// and updated correctly.
+TEST_F(AutofillDialogControllerTest, DetailedSteps) {
+  EXPECT_CALL(*controller()->GetTestingWalletClient(),
+            GetFullWallet(_)).Times(1);
+
+  controller()->set_dialog_type(DIALOG_TYPE_AUTOCHECKOUT);
+
+  // Add steps as would normally be done by the AutocheckoutManager.
+  controller()->AddAutocheckoutStep(AUTOCHECKOUT_STEP_SHIPPING);
+  controller()->AddAutocheckoutStep(AUTOCHECKOUT_STEP_DELIVERY);
+  controller()->AddAutocheckoutStep(AUTOCHECKOUT_STEP_BILLING);
+
+  scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
+  wallet_items->AddInstrument(wallet::GetTestMaskedInstrument());
+  wallet_items->AddAddress(wallet::GetTestShippingAddress());
+  controller()->OnDidGetWalletItems(wallet_items.Pass());
+  // Initiate flow - should add proxy card step since the user is using wallet
+  // data.
+  controller()->OnAccept();
+  controller()->OnDidLoadRiskFingerprintData(GetFakeFingerprint().Pass());
+
+  SuggestionState suggestion_state =
+      controller()->SuggestionStateForSection(SECTION_CC_BILLING);
+  EXPECT_TRUE(suggestion_state.extra_text.empty());
+
+  // There should be four steps total, with the first being the card generation
+  // step added by the dialog controller.
+  EXPECT_EQ(4U, controller()->CurrentAutocheckoutSteps().size());
+  EXPECT_EQ(AUTOCHECKOUT_STEP_PROXY_CARD,
+            controller()->CurrentAutocheckoutSteps()[0].type());
+  EXPECT_EQ(AUTOCHECKOUT_STEP_STARTED,
+            controller()->CurrentAutocheckoutSteps()[0].status());
+
+  // Simulate a wallet error. This should remove the card generation step from
+  // the flow, as we will have to proceed with local data.
+  controller()->OnWalletError(wallet::WalletClient::UNKNOWN_ERROR);
+
+  AutofillProfile shipping_profile(test::GetVerifiedProfile());
+  AutofillProfile billing_profile(test::GetVerifiedProfile2());
+  CreditCard credit_card(test::GetVerifiedCreditCard());
+  controller()->GetTestingManager()->AddTestingProfile(&shipping_profile);
+  controller()->GetTestingManager()->AddTestingProfile(&billing_profile);
+  controller()->GetTestingManager()->AddTestingCreditCard(&credit_card);
+  ui::MenuModel* billing_model =
+      controller()->MenuModelForSection(SECTION_BILLING);
+  billing_model->ActivatedAt(1);
+
+  // Re-initiate flow.
+  controller()->OnAccept();
+
+  // All steps should be initially unstarted.
+  EXPECT_EQ(3U, controller()->CurrentAutocheckoutSteps().size());
+  EXPECT_EQ(AUTOCHECKOUT_STEP_SHIPPING,
+            controller()->CurrentAutocheckoutSteps()[0].type());
+  EXPECT_EQ(AUTOCHECKOUT_STEP_UNSTARTED,
+            controller()->CurrentAutocheckoutSteps()[0].status());
+  EXPECT_EQ(AUTOCHECKOUT_STEP_DELIVERY,
+            controller()->CurrentAutocheckoutSteps()[1].type());
+  EXPECT_EQ(AUTOCHECKOUT_STEP_UNSTARTED,
+            controller()->CurrentAutocheckoutSteps()[1].status());
+  EXPECT_EQ(AUTOCHECKOUT_STEP_BILLING,
+            controller()->CurrentAutocheckoutSteps()[2].type());
+  EXPECT_EQ(AUTOCHECKOUT_STEP_UNSTARTED,
+            controller()->CurrentAutocheckoutSteps()[2].status());
+
+  // Update steps in the same manner that we would expect to see from the
+  // AutocheckoutManager while progressing through a flow.
+  controller()->UpdateAutocheckoutStep(AUTOCHECKOUT_STEP_SHIPPING,
+                                       AUTOCHECKOUT_STEP_STARTED);
+  controller()->UpdateAutocheckoutStep(AUTOCHECKOUT_STEP_SHIPPING,
+                                       AUTOCHECKOUT_STEP_COMPLETED);
+  controller()->UpdateAutocheckoutStep(AUTOCHECKOUT_STEP_DELIVERY,
+                                       AUTOCHECKOUT_STEP_STARTED);
+
+  // Verify that the steps were appropriately updated.
+  EXPECT_EQ(3U, controller()->CurrentAutocheckoutSteps().size());
+  EXPECT_EQ(AUTOCHECKOUT_STEP_SHIPPING,
+            controller()->CurrentAutocheckoutSteps()[0].type());
+  EXPECT_EQ(AUTOCHECKOUT_STEP_COMPLETED,
+            controller()->CurrentAutocheckoutSteps()[0].status());
+  EXPECT_EQ(AUTOCHECKOUT_STEP_DELIVERY,
+            controller()->CurrentAutocheckoutSteps()[1].type());
+  EXPECT_EQ(AUTOCHECKOUT_STEP_STARTED,
+            controller()->CurrentAutocheckoutSteps()[1].status());
+  EXPECT_EQ(AUTOCHECKOUT_STEP_BILLING,
+            controller()->CurrentAutocheckoutSteps()[2].type());
+  EXPECT_EQ(AUTOCHECKOUT_STEP_UNSTARTED,
+            controller()->CurrentAutocheckoutSteps()[2].status());
+}
+
 }  // namespace autofill
diff --git a/chrome/browser/ui/autofill/autofill_dialog_models.cc b/chrome/browser/ui/autofill/autofill_dialog_models.cc
index 89b76b0..f5c7849 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_models.cc
+++ b/chrome/browser/ui/autofill/autofill_dialog_models.cc
@@ -9,9 +9,9 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/common/pref_names.h"
-#include "components/autofill/browser/autofill_country.h"
+#include "components/autofill/core/browser/autofill_country.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "ui/base/l10n/l10n_util.h"
diff --git a/chrome/browser/ui/autofill/autofill_dialog_sign_in_delegate.cc b/chrome/browser/ui/autofill/autofill_dialog_sign_in_delegate.cc
index fab3ffd..ec3651c 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_sign_in_delegate.cc
+++ b/chrome/browser/ui/autofill/autofill_dialog_sign_in_delegate.cc
@@ -14,7 +14,8 @@
     AutofillDialogView* dialog_view,
     content::WebContents* web_contents)
     : WebContentsObserver(web_contents),
-      dialog_view_(dialog_view) {
+      dialog_view_(dialog_view),
+      min_width_(400) {
   web_contents->SetDelegate(this);
 }
 
@@ -25,15 +26,26 @@
 
 void AutofillDialogSignInDelegate::RenderViewCreated(
     content::RenderViewHost* render_view_host) {
-  // Sizes to be used for the sign-in Window.
-  const gfx::Size kSignInWindowMinSize(400, 331);
-  const gfx::Size kSignInWindowMaxSize(800, 600);
+  SetMinWidth(min_width_);
 
-  render_view_host->EnableAutoResize(kSignInWindowMinSize,
-                                     kSignInWindowMaxSize);
   // Set the initial size as soon as we have an RVH to avoid
   // bad size jumping.
-  dialog_view_->OnSignInResize(kSignInWindowMinSize);
+  dialog_view_->OnSignInResize(GetMinSize());
+}
+
+void AutofillDialogSignInDelegate::SetMinWidth(int width) {
+  min_width_ = width;
+  content::RenderViewHost* host = web_contents()->GetRenderViewHost();
+  if (host)
+    host->EnableAutoResize(GetMinSize(), GetMaxSize());
+}
+
+gfx::Size AutofillDialogSignInDelegate::GetMinSize() const {
+  return gfx::Size(min_width_, 331);
+}
+
+gfx::Size AutofillDialogSignInDelegate::GetMaxSize() const {
+  return gfx::Size(std::max(min_width_, 800), 600);
 }
 
 }  // namespace autofill
diff --git a/chrome/browser/ui/autofill/autofill_dialog_sign_in_delegate.h b/chrome/browser/ui/autofill/autofill_dialog_sign_in_delegate.h
index 82df831..12a876b 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_sign_in_delegate.h
+++ b/chrome/browser/ui/autofill/autofill_dialog_sign_in_delegate.h
@@ -32,8 +32,17 @@
   virtual void RenderViewCreated(
       content::RenderViewHost* render_view_host) OVERRIDE;
 
+  // Sets the minimum width for the render view. This should be set to the
+  // width of the host AutofillDialogView.
+  void SetMinWidth(int width);
+
  private:
+  // Gets the minimum and maximum size for the dialog.
+  gfx::Size GetMinSize() const;
+  gfx::Size GetMaxSize() const;
+
   AutofillDialogView* dialog_view_;
+  int min_width_;
 };
 
 }  // namespace autofill
diff --git a/chrome/browser/ui/autofill/autofill_dialog_types.cc b/chrome/browser/ui/autofill/autofill_dialog_types.cc
index 5052c3c..eb62c15 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_types.cc
+++ b/chrome/browser/ui/autofill/autofill_dialog_types.cc
@@ -5,6 +5,9 @@
 #include "chrome/browser/ui/autofill/autofill_dialog_types.h"
 
 #include "base/logging.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 namespace autofill {
 
@@ -73,6 +76,137 @@
   return type_ == DialogNotification::WALLET_USAGE_CONFIRMATION;
 }
 
+DialogAutocheckoutStep::DialogAutocheckoutStep(AutocheckoutStepType type,
+                                               AutocheckoutStepStatus status)
+    : type_(type),
+      status_(status) {}
+
+SkColor DialogAutocheckoutStep::GetTextColor() const {
+  switch (status_) {
+    case AUTOCHECKOUT_STEP_UNSTARTED:
+      return SK_ColorGRAY;
+
+    case AUTOCHECKOUT_STEP_STARTED:
+    case AUTOCHECKOUT_STEP_COMPLETED:
+      return SK_ColorBLACK;
+
+    case AUTOCHECKOUT_STEP_FAILED:
+      return SK_ColorRED;
+  }
+
+  NOTREACHED();
+  return SK_ColorTRANSPARENT;
+}
+
+gfx::Font DialogAutocheckoutStep::GetTextFont() const {
+  gfx::Font::FontStyle font_style = gfx::Font::NORMAL;
+  switch (status_) {
+    case AUTOCHECKOUT_STEP_UNSTARTED:
+    case AUTOCHECKOUT_STEP_STARTED:
+      font_style = gfx::Font::NORMAL;
+      break;
+
+    case AUTOCHECKOUT_STEP_COMPLETED:
+    case AUTOCHECKOUT_STEP_FAILED:
+      font_style = gfx::Font::BOLD;
+      break;
+  }
+
+  return ui::ResourceBundle::GetSharedInstance().GetFont(
+      ui::ResourceBundle::BaseFont).DeriveFont(0, font_style);
+}
+
+bool DialogAutocheckoutStep::IsIconVisible() const {
+  return status_ == AUTOCHECKOUT_STEP_COMPLETED;
+}
+
+string16 DialogAutocheckoutStep::GetDisplayText() const {
+  int description_id = -1;
+  switch (status_) {
+    case AUTOCHECKOUT_STEP_UNSTARTED:
+      switch (type_) {
+        case AUTOCHECKOUT_STEP_SHIPPING:
+          description_id = IDS_AUTOFILL_STEP_SHIPPING_DETAILS_UNSTARTED;
+          break;
+
+        case AUTOCHECKOUT_STEP_DELIVERY:
+          description_id = IDS_AUTOFILL_STEP_DELIVERY_DETAILS_UNSTARTED;
+          break;
+
+        case AUTOCHECKOUT_STEP_BILLING:
+          description_id = IDS_AUTOFILL_STEP_BILLING_DETAILS_UNSTARTED;
+          break;
+
+        case AUTOCHECKOUT_STEP_PROXY_CARD:
+          description_id = IDS_AUTOFILL_STEP_PROXY_CARD_UNSTARTED;
+          break;
+      }
+      break;
+
+    case AUTOCHECKOUT_STEP_STARTED:
+      switch (type_) {
+        case AUTOCHECKOUT_STEP_SHIPPING:
+          description_id = IDS_AUTOFILL_STEP_SHIPPING_DETAILS_STARTED;
+          break;
+
+        case AUTOCHECKOUT_STEP_DELIVERY:
+          description_id = IDS_AUTOFILL_STEP_DELIVERY_DETAILS_STARTED;
+          break;
+
+        case AUTOCHECKOUT_STEP_BILLING:
+          description_id = IDS_AUTOFILL_STEP_BILLING_DETAILS_STARTED;
+          break;
+
+        case AUTOCHECKOUT_STEP_PROXY_CARD:
+          description_id = IDS_AUTOFILL_STEP_PROXY_CARD_STARTED;
+          break;
+      }
+      break;
+
+    case AUTOCHECKOUT_STEP_COMPLETED:
+      switch (type_) {
+        case AUTOCHECKOUT_STEP_SHIPPING:
+          description_id = IDS_AUTOFILL_STEP_SHIPPING_DETAILS_COMPLETE;
+          break;
+
+        case AUTOCHECKOUT_STEP_DELIVERY:
+          description_id = IDS_AUTOFILL_STEP_DELIVERY_DETAILS_COMPLETE;
+          break;
+
+        case AUTOCHECKOUT_STEP_BILLING:
+          description_id = IDS_AUTOFILL_STEP_BILLING_DETAILS_COMPLETE;
+          break;
+
+        case AUTOCHECKOUT_STEP_PROXY_CARD:
+          description_id = IDS_AUTOFILL_STEP_PROXY_CARD_COMPLETE;
+          break;
+      }
+      break;
+
+    case AUTOCHECKOUT_STEP_FAILED:
+      switch (type_) {
+        case AUTOCHECKOUT_STEP_SHIPPING:
+          description_id = IDS_AUTOFILL_STEP_SHIPPING_DETAILS_FAILED;
+          break;
+
+        case AUTOCHECKOUT_STEP_DELIVERY:
+          description_id = IDS_AUTOFILL_STEP_DELIVERY_DETAILS_FAILED;
+          break;
+
+        case AUTOCHECKOUT_STEP_BILLING:
+          description_id = IDS_AUTOFILL_STEP_BILLING_DETAILS_FAILED;
+          break;
+
+        case AUTOCHECKOUT_STEP_PROXY_CARD:
+          description_id = IDS_AUTOFILL_STEP_PROXY_CARD_FAILED;
+          break;
+      }
+      break;
+  }
+
+  return l10n_util::GetStringUTF16(description_id);
+}
+
 SkColor const kWarningColor = SkColorSetRGB(0xde, 0x49, 0x32);
 
 SuggestionState::SuggestionState(const string16& text,
diff --git a/chrome/browser/ui/autofill/autofill_dialog_types.h b/chrome/browser/ui/autofill/autofill_dialog_types.h
index d18eca1..a65820b 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_types.h
+++ b/chrome/browser/ui/autofill/autofill_dialog_types.h
@@ -10,8 +10,8 @@
 
 #include "base/callback_forward.h"
 #include "base/strings/string16.h"
-#include "components/autofill/browser/autofill_metrics.h"
-#include "components/autofill/browser/field_types.h"
+#include "components/autofill/core/browser/autofill_metrics.h"
+#include "components/autofill/core/browser/field_types.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/gfx/font.h"
 #include "ui/gfx/image/image.h"
@@ -128,6 +128,35 @@
   bool interactive_;
 };
 
+// A notification to show in the autofill dialog. Ranges from information to
+// seriously scary security messages, and will give you the color it should be
+// displayed (if you ask it).
+class DialogAutocheckoutStep {
+ public:
+  DialogAutocheckoutStep(AutocheckoutStepType type,
+                         AutocheckoutStepStatus status);
+
+  // Returns the appropriate color for the display text based on |status_|.
+  SkColor GetTextColor() const;
+
+  // Returns the appropriate font for the display text based on |status_|.
+  gfx::Font GetTextFont() const;
+
+  // Returns whether the icon for the view should be visable based on |status_|.
+  bool IsIconVisible() const;
+
+  // Returns the display text based on |type_| and |status_|.
+  string16 GetDisplayText() const;
+
+  AutocheckoutStepStatus status() { return status_; }
+
+  AutocheckoutStepType type() { return type_; }
+
+ private:
+  AutocheckoutStepType type_;
+  AutocheckoutStepStatus status_;
+};
+
 extern SkColor const kWarningColor;
 
 enum DialogSignedInState {
diff --git a/chrome/browser/ui/autofill/autofill_dialog_view.h b/chrome/browser/ui/autofill/autofill_dialog_view.h
index b7548b8..12a7ddb 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_view.h
+++ b/chrome/browser/ui/autofill/autofill_dialog_view.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_DIALOG_VIEW_H_
 #define CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_DIALOG_VIEW_H_
 
-#include "chrome/browser/ui/autofill/autofill_dialog_types.h"
+#include "chrome/browser/ui/autofill/autofill_dialog_controller.h"
 
 namespace content {
 class NavigationController;
@@ -39,6 +39,10 @@
   // a new account, etc.).
   virtual void UpdateAccountChooser() = 0;
 
+  // Updates the container displaying detailed steps for Autocheckout. Called
+  // as progress is made through the buyflow.
+  virtual void UpdateAutocheckoutStepsArea() = 0;
+
   // Updates the button strip based on the current controller state.
   virtual void UpdateButtonStrip() = 0;
 
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_browsertest.cc b/chrome/browser/ui/autofill/autofill_popup_controller_browsertest.cc
index f9bd96b..35f6ecb 100644
--- a/chrome/browser/ui/autofill/autofill_popup_controller_browsertest.cc
+++ b/chrome/browser/ui/autofill/autofill_popup_controller_browsertest.cc
@@ -9,9 +9,9 @@
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/test/base/in_process_browser_test.h"
-#include "components/autofill/browser/autofill_manager.h"
-#include "components/autofill/browser/test_autofill_external_delegate.h"
 #include "components/autofill/content/browser/autofill_driver_impl.h"
+#include "components/autofill/core/browser/autofill_manager.h"
+#include "components/autofill/core/browser/test_autofill_external_delegate.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/test/test_utils.h"
@@ -97,11 +97,16 @@
   scoped_ptr<TestAutofillExternalDelegate> autofill_external_delegate_;
 };
 
+#if defined(OS_LINUX)
+#define MAYBE_HidePopupOnWindowConfiguration DISABLED_HidePopupOnWindowConfiguration
+#else
+#define MAYBE_HidePopupOnWindowConfiguration HidePopupOnWindowConfiguration
+#endif
 // Autofill UI isn't currently hidden on window move on Mac.
 // http://crbug.com/180566
 #if !defined(OS_MACOSX)
 IN_PROC_BROWSER_TEST_F(AutofillPopupControllerBrowserTest,
-                       HidePopupOnWindowConfiguration) {
+                       MAYBE_HidePopupOnWindowConfiguration) {
   GenerateTestAutofillPopup(autofill_external_delegate_.get());
 
   EXPECT_FALSE(autofill_external_delegate_->popup_hidden());
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc b/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
index 7ba2d93..681c2d8 100644
--- a/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
+++ b/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
@@ -10,7 +10,7 @@
 #include "base/logging.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/ui/autofill/autofill_popup_view.h"
-#include "components/autofill/browser/autofill_popup_delegate.h"
+#include "components/autofill/core/browser/autofill_popup_delegate.h"
 #include "content/public/browser/native_web_keyboard_event.h"
 #include "grit/webkit_resources.h"
 #include "third_party/WebKit/public/web/WebAutofillClient.h"
@@ -61,7 +61,6 @@
   { "genericCC", IDR_AUTOFILL_CC_GENERIC },
   { "jcbCC", IDR_AUTOFILL_CC_JCB },
   { "masterCardCC", IDR_AUTOFILL_CC_MASTERCARD },
-  { "soloCC", IDR_AUTOFILL_CC_SOLO },
   { "visaCC", IDR_AUTOFILL_CC_VISA },
 };
 
@@ -608,10 +607,9 @@
     const gfx::Display& left_display,
     const gfx::Display& right_display,
     int popup_required_width) const {
-  int leftmost_display_x = left_display.bounds().x() *
-      left_display.device_scale_factor();
-  int rightmost_display_x = right_display.GetSizeInPixel().width() +
-      right_display.bounds().x() * right_display.device_scale_factor();
+  int leftmost_display_x = left_display.bounds().x();
+  int rightmost_display_x =
+      right_display.GetSizeInPixel().width() + right_display.bounds().x();
 
   // Calculate the start coordinates for the popup if it is growing right or
   // the end position if it is growing to the left, capped to screen space.
@@ -640,11 +638,9 @@
     const gfx::Display& top_display,
     const gfx::Display& bottom_display,
     int popup_required_height) const {
-  int topmost_display_y = top_display.bounds().y() *
-      top_display.device_scale_factor();
-  int bottommost_display_y = bottom_display.GetSizeInPixel().height() +
-      (bottom_display.bounds().y() *
-       bottom_display.device_scale_factor());
+  int topmost_display_y = top_display.bounds().y();
+  int bottommost_display_y =
+      bottom_display.GetSizeInPixel().height() + bottom_display.bounds().y();
 
   // Calculate the start coordinates for the popup if it is growing down or
   // the end position if it is growing up, capped to screen space.
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_unittest.cc b/chrome/browser/ui/autofill/autofill_popup_controller_unittest.cc
index f64cfb4..a645863 100644
--- a/chrome/browser/ui/autofill/autofill_popup_controller_unittest.cc
+++ b/chrome/browser/ui/autofill/autofill_popup_controller_unittest.cc
@@ -10,11 +10,11 @@
 #include "chrome/browser/ui/autofill/autofill_popup_view.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/autofill/browser/autofill_external_delegate.h"
-#include "components/autofill/browser/autofill_manager.h"
-#include "components/autofill/browser/test_autofill_external_delegate.h"
-#include "components/autofill/browser/test_autofill_manager_delegate.h"
 #include "components/autofill/content/browser/autofill_driver_impl.h"
+#include "components/autofill/core/browser/autofill_external_delegate.h"
+#include "components/autofill/core/browser/autofill_manager.h"
+#include "components/autofill/core/browser/test_autofill_external_delegate.h"
+#include "components/autofill/core/browser/test_autofill_manager_delegate.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/WebKit/public/web/WebAutofillClient.h"
@@ -161,8 +161,7 @@
         web_contents(),
         manager_delegate_.get(),
         "en-US",
-        AutofillManager::ENABLE_AUTOFILL_DOWNLOAD_MANAGER,
-        false);
+        AutofillManager::ENABLE_AUTOFILL_DOWNLOAD_MANAGER);
     AutofillDriverImpl* driver =
         AutofillDriverImpl::FromWebContents(web_contents());
     external_delegate_.reset(
diff --git a/chrome/browser/ui/autofill/autofill_popup_view.cc b/chrome/browser/ui/autofill/autofill_popup_view.cc
deleted file mode 100644
index c2dc065..0000000
--- a/chrome/browser/ui/autofill/autofill_popup_view.cc
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/autofill/autofill_popup_view.h"
-
-namespace autofill {
-
-void AutofillPopupView::Hide() {
-  hide_called_ = true;
-}
-
-AutofillPopupView::AutofillPopupView() : hide_called_(false) {}
-
-AutofillPopupView::~AutofillPopupView() {
-  CHECK(hide_called_);
-}
-
-}  // namespace autofill
diff --git a/chrome/browser/ui/autofill/autofill_popup_view.h b/chrome/browser/ui/autofill/autofill_popup_view.h
index 1085095..1ef1869 100644
--- a/chrome/browser/ui/autofill/autofill_popup_view.h
+++ b/chrome/browser/ui/autofill/autofill_popup_view.h
@@ -52,9 +52,7 @@
   virtual void Show() = 0;
 
   // Hides the popup from view. This will cause the popup to be deleted.
-  // TODO(csharp): Make Hide a pure virtual function again, once hide_call_ is
-  // removed.
-  virtual void Hide();
+  virtual void Hide() = 0;
 
   // Invalidates the given row and redraw it.
   virtual void InvalidateRow(size_t row) = 0;
@@ -66,14 +64,7 @@
   static AutofillPopupView* Create(AutofillPopupController* controller);
 
  protected:
-  AutofillPopupView();
-  virtual ~AutofillPopupView();
-
- private:
-  // Used to check that the hide function was called, to check that the class
-  // is only destroyed through the Hide function. Remove after Dev channel
-  // release.
-  bool hide_called_;
+  virtual ~AutofillPopupView() {}
 };
 
 }  // namespace autofill
diff --git a/chrome/browser/ui/autofill/country_combobox_model.cc b/chrome/browser/ui/autofill/country_combobox_model.cc
index fe2eab2..6079e02 100644
--- a/chrome/browser/ui/autofill/country_combobox_model.cc
+++ b/chrome/browser/ui/autofill/country_combobox_model.cc
@@ -6,7 +6,7 @@
 
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/browser_process.h"
-#include "components/autofill/browser/autofill_country.h"
+#include "components/autofill/core/browser/autofill_country.h"
 #include "ui/base/l10n/l10n_util_collator.h"
 
 namespace autofill {
diff --git a/chrome/browser/ui/autofill/data_model_wrapper.cc b/chrome/browser/ui/autofill/data_model_wrapper.cc
index 4487650..40a0072 100644
--- a/chrome/browser/ui/autofill/data_model_wrapper.cc
+++ b/chrome/browser/ui/autofill/data_model_wrapper.cc
@@ -8,15 +8,15 @@
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/ui/autofill/autofill_dialog_models.h"
-#include "components/autofill/browser/autofill_data_model.h"
-#include "components/autofill/browser/autofill_profile.h"
-#include "components/autofill/browser/autofill_type.h"
-#include "components/autofill/browser/credit_card.h"
-#include "components/autofill/browser/form_structure.h"
-#include "components/autofill/browser/validation.h"
 #include "components/autofill/content/browser/wallet/full_wallet.h"
 #include "components/autofill/content/browser/wallet/wallet_address.h"
 #include "components/autofill/content/browser/wallet/wallet_items.h"
+#include "components/autofill/core/browser/autofill_data_model.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/autofill_type.h"
+#include "components/autofill/core/browser/credit_card.h"
+#include "components/autofill/core/browser/form_structure.h"
+#include "components/autofill/core/browser/validation.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/image/image.h"
 
@@ -140,12 +140,8 @@
 }
 
 string16 AutofillCreditCardWrapper::GetDisplayText() {
-  if (!autofill::IsValidCreditCardExpirationDate(
-           card_->GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR),
-           card_->GetRawInfo(CREDIT_CARD_EXP_MONTH),
-           base::Time::Now())) {
+  if (!card_->IsValid())
     return string16();
-  }
 
   return card_->TypeAndLastFourDigits();
 }
@@ -259,4 +255,18 @@
       type, g_browser_process->GetApplicationLocale());
 }
 
+DetailOutputWrapper::DetailOutputWrapper(const DetailOutputMap& outputs)
+    : outputs_(outputs) {}
+
+DetailOutputWrapper::~DetailOutputWrapper() {}
+
+base::string16 DetailOutputWrapper::GetInfo(AutofillFieldType type) const {
+  for (DetailOutputMap::const_iterator it = outputs_.begin();
+       it != outputs_.end(); ++it) {
+    if (type == it->first->type)
+      return it->second;
+  }
+  return base::string16();
+}
+
 }  // namespace autofill
diff --git a/chrome/browser/ui/autofill/data_model_wrapper.h b/chrome/browser/ui/autofill/data_model_wrapper.h
index a9302de..0e54ff8 100644
--- a/chrome/browser/ui/autofill/data_model_wrapper.h
+++ b/chrome/browser/ui/autofill/data_model_wrapper.h
@@ -8,8 +8,8 @@
 #include "base/compiler_specific.h"
 #include "base/strings/string16.h"
 #include "chrome/browser/ui/autofill/autofill_dialog_types.h"
-#include "components/autofill/browser/field_types.h"
 #include "components/autofill/content/browser/wallet/wallet_items.h"
+#include "components/autofill/core/browser/field_types.h"
 
 namespace gfx {
 class Image;
@@ -196,6 +196,20 @@
   DISALLOW_COPY_AND_ASSIGN(FullWalletShippingWrapper);
 };
 
+// A DataModelWrapper to copy the output of one section to the input of another.
+class DetailOutputWrapper : public DataModelWrapper {
+ public:
+  explicit DetailOutputWrapper(const DetailOutputMap& outputs);
+  virtual ~DetailOutputWrapper();
+
+  virtual base::string16 GetInfo(AutofillFieldType type) const OVERRIDE;
+
+ private:
+  const DetailOutputMap& outputs_;
+
+  DISALLOW_COPY_AND_ASSIGN(DetailOutputWrapper);
+};
+
 }  // namespace autofill
 
 #endif  // CHROME_BROWSER_UI_AUTOFILL_DATA_MODEL_WRAPPER_H_
diff --git a/chrome/browser/ui/autofill/data_model_wrapper_unittest.cc b/chrome/browser/ui/autofill/data_model_wrapper_unittest.cc
index 144a6c9..a1f27ce 100644
--- a/chrome/browser/ui/autofill/data_model_wrapper_unittest.cc
+++ b/chrome/browser/ui/autofill/data_model_wrapper_unittest.cc
@@ -4,14 +4,15 @@
 
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/ui/autofill/autofill_dialog_models.h"
 #include "chrome/browser/ui/autofill/data_model_wrapper.h"
-#include "components/autofill/browser/autofill_common_test.h"
-#include "components/autofill/browser/autofill_profile.h"
-#include "components/autofill/browser/credit_card.h"
-#include "components/autofill/browser/field_types.h"
 #include "components/autofill/content/browser/wallet/wallet_items.h"
 #include "components/autofill/content/browser/wallet/wallet_test_util.h"
+#include "components/autofill/core/browser/autofill_common_test.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/credit_card.h"
+#include "components/autofill/core/browser/field_types.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace autofill {
@@ -28,10 +29,31 @@
 
 TEST(AutofillCreditCardWrapperTest, GetDisplayTextEmptyWhenExpired) {
   CreditCard card;
+  card.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("1"));
+  card.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2010"));
+  card.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4111111111111111"));
   AutofillCreditCardWrapper wrapper(&card);
   EXPECT_TRUE(wrapper.GetDisplayText().empty());
 }
 
+TEST(AutofillCreditCardWrapperTest, GetDisplayTextEmptyWhenInvalid) {
+  CreditCard card;
+  card.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("12"));
+  card.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("9999"));
+  card.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("41111"));
+  AutofillCreditCardWrapper wrapper(&card);
+  EXPECT_TRUE(wrapper.GetDisplayText().empty());
+}
+
+TEST(AutofillCreditCardWrapperTest, GetDisplayTextNotEmptyWhenValid) {
+  CreditCard card;
+  card.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("12"));
+  card.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("9999"));
+  card.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4111111111111111"));
+  AutofillCreditCardWrapper wrapper(&card);
+  EXPECT_FALSE(wrapper.GetDisplayText().empty());
+}
+
 TEST(WalletInstrumentWrapperTest, GetInfoCreditCardExpMonth) {
   scoped_ptr<wallet::WalletItems::MaskedInstrument> instrument(
       wallet::GetTestMaskedInstrument());
@@ -71,4 +93,4 @@
   EXPECT_TRUE(address_wrapper.GetDisplayText().empty());
 }
 
-}  // autofill
+}  // namespace autofill
diff --git a/chrome/browser/ui/autofill/mock_autofill_dialog_controller.cc b/chrome/browser/ui/autofill/mock_autofill_dialog_controller.cc
index 2388028..006fa2b 100644
--- a/chrome/browser/ui/autofill/mock_autofill_dialog_controller.cc
+++ b/chrome/browser/ui/autofill/mock_autofill_dialog_controller.cc
@@ -45,10 +45,6 @@
   return string16();
 }
 
-string16 MockAutofillDialogController::ProgressBarText() const {
-  return string16();
-}
-
 string16 MockAutofillDialogController::LegalDocumentsText() {
   return string16();
 }
@@ -161,6 +157,11 @@
   return std::vector<DialogNotification>();
 }
 
+std::vector<DialogAutocheckoutStep> MockAutofillDialogController::
+    CurrentAutocheckoutSteps() const {
+  return std::vector<DialogAutocheckoutStep>();
+}
+
 void MockAutofillDialogController::SignInLinkClicked() {}
 
 void MockAutofillDialogController::NotificationCheckboxStateChanged(
diff --git a/chrome/browser/ui/autofill/mock_autofill_dialog_controller.h b/chrome/browser/ui/autofill/mock_autofill_dialog_controller.h
index 0d016f6..6da9ce8 100644
--- a/chrome/browser/ui/autofill/mock_autofill_dialog_controller.h
+++ b/chrome/browser/ui/autofill/mock_autofill_dialog_controller.h
@@ -22,7 +22,6 @@
   virtual string16 CancelButtonText() const OVERRIDE;
   virtual string16 ConfirmButtonText() const OVERRIDE;
   virtual string16 SaveLocallyText() const OVERRIDE;
-  virtual string16 ProgressBarText() const OVERRIDE;
   virtual string16 LegalDocumentsText() OVERRIDE;
   virtual DialogSignedInState SignedInState() const OVERRIDE;
   virtual bool ShouldShowSpinner() const OVERRIDE;
@@ -72,6 +71,9 @@
 
   virtual std::vector<DialogNotification> CurrentNotifications() OVERRIDE;
 
+  virtual std::vector<DialogAutocheckoutStep> CurrentAutocheckoutSteps()
+      const OVERRIDE;
+
   virtual void SignInLinkClicked() OVERRIDE;
   virtual void NotificationCheckboxStateChanged(DialogNotification::Type type,
                                                 bool checked) OVERRIDE;
diff --git a/chrome/browser/ui/autofill/tab_autofill_manager_delegate.cc b/chrome/browser/ui/autofill/tab_autofill_manager_delegate.cc
index 9d38578..c66528c 100644
--- a/chrome/browser/ui/autofill/tab_autofill_manager_delegate.cc
+++ b/chrome/browser/ui/autofill/tab_autofill_manager_delegate.cc
@@ -20,6 +20,7 @@
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/common/url_constants.h"
+#include "components/autofill/core/common/autofill_pref_names.h"
 #include "content/public/browser/navigation_details.h"
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/web_contents_view.h"
@@ -167,10 +168,20 @@
     popup_controller_->Hide();
 }
 
-void TabAutofillManagerDelegate::UpdateProgressBar(double value) {
-  // |dialog_controller_| is a WeakPtr, but we require it to be present when
-  // |UpdateProgressBar| is called, so we intentionally do not do NULL check.
-  dialog_controller_->UpdateProgressBar(value);
+void TabAutofillManagerDelegate::AddAutocheckoutStep(
+    AutocheckoutStepType step_type) {
+  dialog_controller_->AddAutocheckoutStep(step_type);
+}
+
+void TabAutofillManagerDelegate::UpdateAutocheckoutStep(
+    AutocheckoutStepType step_type,
+    AutocheckoutStepStatus step_status) {
+  dialog_controller_->UpdateAutocheckoutStep(step_type, step_status);
+}
+
+bool TabAutofillManagerDelegate::IsAutocompleteEnabled() {
+  // For browser, Autocomplete is always enabled as part of Autofill.
+  return GetPrefs()->GetBoolean(prefs::kAutofillEnabled);
 }
 
 void TabAutofillManagerDelegate::HideRequestAutocompleteDialog() {
diff --git a/chrome/browser/ui/autofill/tab_autofill_manager_delegate.h b/chrome/browser/ui/autofill/tab_autofill_manager_delegate.h
index 9864f1d..bb118bc 100644
--- a/chrome/browser/ui/autofill/tab_autofill_manager_delegate.h
+++ b/chrome/browser/ui/autofill/tab_autofill_manager_delegate.h
@@ -10,7 +10,8 @@
 #include "base/i18n/rtl.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/ui/autofill/autofill_dialog_types.h"
-#include "components/autofill/browser/autofill_manager_delegate.h"
+#include "components/autofill/content/browser/autocheckout_steps.h"
+#include "components/autofill/core/browser/autofill_manager_delegate.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/browser/web_contents_user_data.h"
 
@@ -68,13 +69,23 @@
       const std::vector<int>& identifiers,
       base::WeakPtr<AutofillPopupDelegate> delegate) OVERRIDE;
   virtual void HideAutofillPopup() OVERRIDE;
-  virtual void UpdateProgressBar(double value) OVERRIDE;
+  virtual bool IsAutocompleteEnabled() OVERRIDE;
+
+  virtual void AddAutocheckoutStep(AutocheckoutStepType step_type) OVERRIDE;
+  virtual void UpdateAutocheckoutStep(
+      AutocheckoutStepType step_type,
+      AutocheckoutStepStatus step_status) OVERRIDE;
 
   // content::WebContentsObserver implementation.
   virtual void DidNavigateMainFrame(
       const content::LoadCommittedDetails& details,
       const content::FrameNavigateParams& params) OVERRIDE;
 
+  // Exposed for testing.
+  AutofillDialogControllerImpl* GetDialogControllerForTesting() {
+    return dialog_controller_.get();
+  }
+
  private:
   explicit TabAutofillManagerDelegate(content::WebContents* web_contents);
   friend class content::WebContentsUserData<TabAutofillManagerDelegate>;
diff --git a/chrome/browser/ui/autofill/testable_autofill_dialog_view.h b/chrome/browser/ui/autofill/testable_autofill_dialog_view.h
index 984426e..7020e81 100644
--- a/chrome/browser/ui/autofill/testable_autofill_dialog_view.h
+++ b/chrome/browser/ui/autofill/testable_autofill_dialog_view.h
@@ -26,6 +26,10 @@
   virtual void SetTextContentsOfInput(const DetailInput& input,
                                       const string16& contents) = 0;
 
+  // Sets the content of the extra field for a section.
+  virtual void SetTextContentsOfSuggestionInput(DialogSection section,
+                                                const base::string16& text) = 0;
+
   // Simulates a user activatino of the input which is modelled by |input|.
   virtual void ActivateInput(const DetailInput& input) = 0;
 
diff --git a/chrome/browser/ui/bookmarks/bookmark_bar_constants.h b/chrome/browser/ui/bookmarks/bookmark_bar_constants.h
index 5f7ff84..7708e58 100644
--- a/chrome/browser/ui/bookmarks/bookmark_bar_constants.h
+++ b/chrome/browser/ui/bookmarks/bookmark_bar_constants.h
@@ -10,9 +10,9 @@
 namespace chrome {
 
 // The Bookmark bar height, when visible in "new tab page" mode.
-#if defined(OS_WIN) || defined(TOOLKIT_VIEWS) || defined(TOOLKIT_GTK)
+#if defined(TOOLKIT_GTK)
 const int kNTPBookmarkBarHeight = 57;
-#elif defined(OS_MACOSX)
+#elif defined(TOOLKIT_VIEWS) || defined(OS_MACOSX)
 const int kNTPBookmarkBarHeight = 40;
 #endif
 
diff --git a/chrome/browser/ui/bookmarks/bookmark_browsertest.cc b/chrome/browser/ui/bookmarks/bookmark_browsertest.cc
index 7fc4004..71217ed 100644
--- a/chrome/browser/ui/bookmarks/bookmark_browsertest.cc
+++ b/chrome/browser/ui/bookmarks/bookmark_browsertest.cc
@@ -4,7 +4,7 @@
 
 #include "base/bind.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
diff --git a/chrome/browser/ui/bookmarks/bookmark_context_menu_controller.cc b/chrome/browser/ui/bookmarks/bookmark_context_menu_controller.cc
index d2703c3..660050d 100644
--- a/chrome/browser/ui/bookmarks/bookmark_context_menu_controller.cc
+++ b/chrome/browser/ui/bookmarks/bookmark_context_menu_controller.cc
@@ -7,18 +7,17 @@
 #include "base/compiler_specific.h"
 #include "base/prefs/pref_service.h"
 #include "chrome/app/chrome_command_ids.h"
-#include "chrome/browser/bookmarks/bookmark_editor.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/browser/bookmarks/bookmark_utils.h"
 #include "chrome/browser/prefs/incognito_mode_prefs.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/bookmarks/bookmark_editor.h"
 #include "chrome/browser/ui/bookmarks/bookmark_utils.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/pref_names.h"
-#include "components/user_prefs/user_prefs.h"
 #include "content/public/browser/page_navigator.h"
 #include "content/public/browser/user_metrics.h"
 #include "grit/generated_resources.h"
@@ -265,7 +264,7 @@
 }
 
 bool BookmarkContextMenuController::IsCommandIdChecked(int command_id) const {
-  PrefService* prefs = user_prefs::UserPrefs::Get(profile_);
+  PrefService* prefs = profile_->GetPrefs();
   if (command_id == IDC_BOOKMARK_BAR_ALWAYS_SHOW)
     return prefs->GetBoolean(prefs::kShowBookmarkBar);
 
@@ -274,17 +273,17 @@
 }
 
 bool BookmarkContextMenuController::IsCommandIdEnabled(int command_id) const {
-  bool enabled;
+  bool enabled = false;
   if (IsPlatformCommandIdEnabled(command_id, &enabled))
     return enabled;
 
-  PrefService* prefs = user_prefs::UserPrefs::Get(profile_);
+  PrefService* prefs = profile_->GetPrefs();
 
   bool is_root_node = selection_.size() == 1 &&
                       selection_[0]->parent() == model_->root_node();
   bool can_edit = prefs->GetBoolean(prefs::kEditBookmarksEnabled);
   IncognitoModePrefs::Availability incognito_avail =
-      IncognitoModePrefs::GetAvailability(profile_->GetPrefs());
+      IncognitoModePrefs::GetAvailability(prefs);
   switch (command_id) {
     case IDC_BOOKMARK_BAR_OPEN_INCOGNITO:
       return !profile_->IsOffTheRecord() &&
diff --git a/chrome/browser/ui/bookmarks/bookmark_editor.cc b/chrome/browser/ui/bookmarks/bookmark_editor.cc
new file mode 100644
index 0000000..7338c91
--- /dev/null
+++ b/chrome/browser/ui/bookmarks/bookmark_editor.cc
@@ -0,0 +1,166 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/bookmarks/bookmark_editor.h"
+
+#include "base/logging.h"
+#include "grit/generated_resources.h"
+
+namespace {
+
+const BookmarkNode* CreateNewNode(BookmarkModel* model,
+                                  const BookmarkNode* parent,
+                                  const BookmarkEditor::EditDetails& details,
+                                  const base::string16& new_title,
+                                  const GURL& new_url) {
+  const BookmarkNode* node;
+  // When create the new one to right-clicked folder, add it to the next to the
+  // folder's position. Because |details.index| has a index of the folder when
+  // it was right-clicked, it might cause out of range exception when another
+  // bookmark manager edits contents of the folder.
+  // So we must check the range.
+  int child_count = parent->child_count();
+  int insert_index = (parent == details.parent_node && details.index >= 0 &&
+                      details.index <= child_count) ?
+                      details.index : child_count;
+  if (details.type == BookmarkEditor::EditDetails::NEW_URL) {
+    node = model->AddURL(parent, insert_index, new_title, new_url);
+  } else if (details.type == BookmarkEditor::EditDetails::NEW_FOLDER) {
+    node = model->AddFolder(parent, insert_index, new_title);
+    for (size_t i = 0; i < details.urls.size(); ++i) {
+      model->AddURL(node, node->child_count(), details.urls[i].second,
+                    details.urls[i].first);
+    }
+    model->SetDateFolderModified(parent, base::Time::Now());
+  } else {
+    NOTREACHED();
+    return NULL;
+  }
+
+  return node;
+}
+
+}  // namespace
+
+BookmarkEditor::EditDetails::EditDetails(Type node_type)
+    : type(node_type), existing_node(NULL), parent_node(NULL), index(-1) {
+}
+
+BookmarkNode::Type BookmarkEditor::EditDetails::GetNodeType() const {
+  BookmarkNode::Type node_type = BookmarkNode::URL;
+  switch (type) {
+    case EXISTING_NODE:
+      node_type = existing_node->type();
+      break;
+    case NEW_URL:
+      node_type = BookmarkNode::URL;
+      break;
+    case NEW_FOLDER:
+      node_type = BookmarkNode::FOLDER;
+      break;
+    default:
+      NOTREACHED();
+  }
+  return node_type;
+}
+
+int BookmarkEditor::EditDetails::GetWindowTitleId() const {
+  int dialog_title = IDS_BOOKMARK_EDITOR_TITLE;
+  switch (type) {
+    case EditDetails::EXISTING_NODE:
+    case EditDetails::NEW_URL:
+      dialog_title = (type == EditDetails::EXISTING_NODE &&
+                      existing_node->type() == BookmarkNode::FOLDER) ?
+          IDS_BOOKMARK_FOLDER_EDITOR_WINDOW_TITLE :
+          IDS_BOOKMARK_EDITOR_TITLE;
+      break;
+    case EditDetails::NEW_FOLDER:
+      dialog_title = urls.empty() ?
+          IDS_BOOKMARK_FOLDER_EDITOR_WINDOW_TITLE_NEW :
+          IDS_BOOKMARK_ALL_TABS_DIALOG_TITLE;
+      break;
+    default:
+      NOTREACHED();
+  }
+  return dialog_title;
+}
+
+BookmarkEditor::EditDetails BookmarkEditor::EditDetails::EditNode(
+    const BookmarkNode* node) {
+  EditDetails details(EXISTING_NODE);
+  details.existing_node = node;
+  if (node)
+    details.parent_node = node->parent();
+  return details;
+}
+
+BookmarkEditor::EditDetails BookmarkEditor::EditDetails::AddNodeInFolder(
+    const BookmarkNode* parent_node,
+    int index,
+    const GURL& url,
+    const string16& title) {
+  EditDetails details(NEW_URL);
+  details.parent_node = parent_node;
+  details.index = index;
+  details.url = url;
+  details.title = title;
+  return details;
+}
+
+BookmarkEditor::EditDetails BookmarkEditor::EditDetails::AddFolder(
+    const BookmarkNode* parent_node,
+    int index) {
+  EditDetails details(NEW_FOLDER);
+  details.parent_node = parent_node;
+  details.index = index;
+  return details;
+}
+
+BookmarkEditor::EditDetails::~EditDetails() {}
+
+// static
+const BookmarkNode* BookmarkEditor::ApplyEditsWithNoFolderChange(
+    BookmarkModel* model,
+    const BookmarkNode* parent,
+    const EditDetails& details,
+    const base::string16& new_title,
+    const GURL& new_url) {
+  if (details.type == EditDetails::NEW_URL ||
+      details.type == EditDetails::NEW_FOLDER) {
+    return CreateNewNode(model, parent, details, new_title, new_url);
+  }
+
+  const BookmarkNode* node = details.existing_node;
+  DCHECK(node);
+
+  if (node->is_url())
+    model->SetURL(node, new_url);
+  model->SetTitle(node, new_title);
+
+  return node;
+}
+
+// static
+const BookmarkNode* BookmarkEditor::ApplyEditsWithPossibleFolderChange(
+    BookmarkModel* model,
+    const BookmarkNode* new_parent,
+    const EditDetails& details,
+    const base::string16& new_title,
+    const GURL& new_url) {
+  if (details.type == EditDetails::NEW_URL ||
+      details.type == EditDetails::NEW_FOLDER) {
+    return CreateNewNode(model, new_parent, details, new_title, new_url);
+  }
+
+  const BookmarkNode* node = details.existing_node;
+  DCHECK(node);
+
+  if (new_parent != node->parent())
+    model->Move(node, new_parent, new_parent->child_count());
+  if (node->is_url())
+    model->SetURL(node, new_url);
+  model->SetTitle(node, new_title);
+
+  return node;
+}
diff --git a/chrome/browser/ui/bookmarks/bookmark_editor.h b/chrome/browser/ui/bookmarks/bookmark_editor.h
new file mode 100644
index 0000000..75f0f9b
--- /dev/null
+++ b/chrome/browser/ui/bookmarks/bookmark_editor.h
@@ -0,0 +1,129 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_BOOKMARKS_BOOKMARK_EDITOR_H_
+#define CHROME_BROWSER_UI_BOOKMARKS_BOOKMARK_EDITOR_H_
+
+#include <utility>
+#include <vector>
+
+#include "base/strings/string16.h"
+#include "chrome/browser/bookmarks/bookmark_model.h"
+#include "ui/gfx/native_widget_types.h"
+
+class GURL;
+class Profile;
+
+// Small, cross platform interface that shows the correct platform specific
+// bookmark editor dialog.
+class BookmarkEditor {
+ public:
+  // An enumeration of the possible configurations offered.
+  enum Configuration {
+    // If Configuration is SHOW_TREE, a tree is shown allowing the user to
+    // choose the parent of the node.
+    SHOW_TREE,
+    NO_TREE
+  };
+
+  // Describes what the user is editing.
+  class EditDetails {
+   public:
+    // Returns the type of the existing or new node.
+    BookmarkNode::Type GetNodeType() const;
+
+    // Returns the resource id for the string resource to use on the window
+    // title for this edit operation.
+    int GetWindowTitleId() const;
+
+    // Returns an EditDetails instance for the user editing the given bookmark.
+    static EditDetails EditNode(const BookmarkNode* node);
+
+    // Returns an EditDetails instance for the user adding a bookmark within
+    // a given parent node with a specified index.
+    static EditDetails AddNodeInFolder(const BookmarkNode* parent_node,
+                                       int index,
+                                       const GURL& url,
+                                       const string16& title);
+
+    // Returns an EditDetails instance for the user adding a folder within a
+    // given parent node with a specified index.
+    static EditDetails AddFolder(const BookmarkNode* parent_node,
+                                 int index);
+
+    enum Type {
+      // The user is editing an existing node in the model. The node the user
+      // is editing is set in |existing_node|.
+      EXISTING_NODE,
+
+      // A new bookmark should be created if the user accepts the edit.
+      // |existing_node| is null in this case.
+      NEW_URL,
+
+      // A new folder bookmark should be created if the user accepts the edit.
+      // The contents of the folder should be that of |urls|.
+      // |existing_node| is null in this case.
+      NEW_FOLDER
+    };
+
+    ~EditDetails();
+
+    // See description of enum value for details.
+    const Type type;
+
+    // If type == EXISTING_NODE this gives the existing node.
+    const BookmarkNode* existing_node;
+
+    // If type == NEW_URL or type == NEW_FOLDER this gives the initial parent
+    // node to place the new node in.
+    const BookmarkNode* parent_node;
+
+    // If type == NEW_URL or type == NEW_FOLDER this gives the index to insert
+    // the new node at.
+    int index;
+
+    // If type == NEW_URL this gives the URL/title.
+    GURL url;
+    string16 title;
+
+    // If type == NEW_FOLDER, this is the urls/title pairs to add to the
+    // folder.
+    std::vector<std::pair<GURL, string16> > urls;
+
+   private:
+    explicit EditDetails(Type node_type);
+  };
+
+  // Shows the bookmark editor. The bookmark editor allows editing an existing
+  // node or creating a new bookmark node (as determined by |details.type|).
+  // |details.parent_node| is only used if |details.existing_node| is null.
+  static void Show(gfx::NativeWindow parent_window,
+                   Profile* profile,
+                   const EditDetails& details,
+                   Configuration configuration);
+
+  // Modifies a bookmark node (assuming that there's no magic that needs to be
+  // done regarding moving from one folder to another).  If a new node is
+  // explicitly being added, returns a pointer to the new node that was created.
+  // Otherwise the return value is identically |node|.
+  static const BookmarkNode* ApplyEditsWithNoFolderChange(
+      BookmarkModel* model,
+      const BookmarkNode* parent,
+      const EditDetails& details,
+      const base::string16& new_title,
+      const GURL& new_url);
+
+  // Modifies a bookmark node assuming that the parent of the node may have
+  // changed and the node will need to be removed and reinserted.  If a new node
+  // is explicitly being added, returns a pointer to the new node that was
+  // created.  Otherwise the return value is identically |node|.
+  static const BookmarkNode* ApplyEditsWithPossibleFolderChange(
+      BookmarkModel* model,
+      const BookmarkNode* new_parent,
+      const EditDetails& details,
+      const base::string16& new_title,
+      const GURL& new_url);
+};
+
+#endif  // CHROME_BROWSER_UI_BOOKMARKS_BOOKMARK_EDITOR_H_
diff --git a/chrome/browser/ui/bookmarks/bookmark_editor_unittest.cc b/chrome/browser/ui/bookmarks/bookmark_editor_unittest.cc
new file mode 100644
index 0000000..83d16e6
--- /dev/null
+++ b/chrome/browser/ui/bookmarks/bookmark_editor_unittest.cc
@@ -0,0 +1,50 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/bookmarks/bookmark_editor.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+TEST(BookmarkEditorTest, ApplyEditsWithNoFolderChange) {
+  BookmarkModel model(NULL);
+  const BookmarkNode* bookmarkbar = model.bookmark_bar_node();
+  model.AddURL(bookmarkbar, 0, ASCIIToUTF16("url0"), GURL("chrome://newtab"));
+  model.AddURL(bookmarkbar, 1, ASCIIToUTF16("url1"), GURL("chrome://newtab"));
+
+  {
+    BookmarkEditor::EditDetails detail(
+        BookmarkEditor::EditDetails::AddFolder(bookmarkbar, 1));
+    BookmarkEditor::ApplyEditsWithNoFolderChange(&model,
+                                                 bookmarkbar,
+                                                 detail,
+                                                 ASCIIToUTF16("folder0"),
+                                                 GURL(std::string()));
+    EXPECT_EQ(ASCIIToUTF16("folder0"), bookmarkbar->GetChild(1)->GetTitle());
+  }
+  {
+    BookmarkEditor::EditDetails detail(
+        BookmarkEditor::EditDetails::AddFolder(bookmarkbar, -1));
+    BookmarkEditor::ApplyEditsWithNoFolderChange(&model,
+                                                 bookmarkbar,
+                                                 detail,
+                                                 ASCIIToUTF16("folder1"),
+                                                 GURL(std::string()));
+    EXPECT_EQ(ASCIIToUTF16("folder1"), bookmarkbar->GetChild(3)->GetTitle());
+  }
+  {
+    BookmarkEditor::EditDetails detail(
+        BookmarkEditor::EditDetails::AddFolder(bookmarkbar, 10));
+    BookmarkEditor::ApplyEditsWithNoFolderChange(&model,
+                                                 bookmarkbar,
+                                                 detail,
+                                                 ASCIIToUTF16("folder2"),
+                                                 GURL(std::string()));
+    EXPECT_EQ(ASCIIToUTF16("folder2"), bookmarkbar->GetChild(4)->GetTitle());
+  }
+}
+
+}  // namespace
diff --git a/chrome/browser/ui/bookmarks/bookmark_prompt_controller.h b/chrome/browser/ui/bookmarks/bookmark_prompt_controller.h
index 290f2fe..7b0d2a4 100644
--- a/chrome/browser/ui/bookmarks/bookmark_prompt_controller.h
+++ b/chrome/browser/ui/bookmarks/bookmark_prompt_controller.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_UI_BOOKMARKS_BOOKMARK_PROMPT_CONTROLLER_H_
 
 #include "base/basictypes.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/common/cancelable_request.h"
 #include "chrome/browser/history/history_types.h"
 #include "chrome/browser/ui/browser_list_observer.h"
diff --git a/chrome/browser/ui/bookmarks/bookmark_utils.cc b/chrome/browser/ui/bookmarks/bookmark_utils.cc
index dc63d7b..71c8ad0 100644
--- a/chrome/browser/ui/bookmarks/bookmark_utils.cc
+++ b/chrome/browser/ui/bookmarks/bookmark_utils.cc
@@ -9,11 +9,11 @@
 #include "base/logging.h"
 #include "base/prefs/pref_service.h"
 #include "base/strings/string_number_conversions.h"
-#include "chrome/browser/bookmarks/bookmark_editor.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search/search.h"
+#include "chrome/browser/ui/bookmarks/bookmark_editor.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/browser/ui/browser_window.h"
diff --git a/chrome/browser/ui/bookmarks/recently_used_folders_combo_model.cc b/chrome/browser/ui/bookmarks/recently_used_folders_combo_model.cc
index 879bb0d..a1775c4 100644
--- a/chrome/browser/ui/bookmarks/recently_used_folders_combo_model.cc
+++ b/chrome/browser/ui/bookmarks/recently_used_folders_combo_model.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/ui/bookmarks/recently_used_folders_combo_model.h"
 
+#include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/bookmarks/bookmark_utils.h"
 #include "content/public/browser/user_metrics.h"
 #include "grit/generated_resources.h"
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
index ceab9ef..5513be6 100644
--- a/chrome/browser/ui/browser.cc
+++ b/chrome/browser/ui/browser.cc
@@ -26,7 +26,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_restrictions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/app_mode/app_mode_utils.h"
 #include "chrome/browser/autofill/personal_data_manager_factory.h"
@@ -66,7 +66,6 @@
 #include "chrome/browser/notifications/notification_ui_manager.h"
 #include "chrome/browser/pepper_broker_infobar_delegate.h"
 #include "chrome/browser/prefs/incognito_mode_prefs.h"
-#include "chrome/browser/printing/cloud_print/cloud_print_setup_flow.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_destroyer.h"
 #include "chrome/browser/profiles/profile_manager.h"
@@ -108,7 +107,7 @@
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/chrome_select_file_policy.h"
-#include "chrome/browser/ui/extensions/shell_window.h"
+#include "chrome/browser/ui/fast_unload_controller.h"
 #include "chrome/browser/ui/find_bar/find_bar.h"
 #include "chrome/browser/ui/find_bar/find_bar_controller.h"
 #include "chrome/browser/ui/find_bar/find_tab_helper.h"
@@ -191,7 +190,7 @@
 #include "chrome/browser/ssl/ssl_error_info.h"
 #include "chrome/browser/task_manager/task_manager.h"
 #include "chrome/browser/ui/view_ids.h"
-#include "components/autofill/browser/autofill_ie_toolbar_import_win.h"
+#include "components/autofill/core/browser/autofill_ie_toolbar_import_win.h"
 #include "ui/base/win/shell.h"
 #include "ui/views/win/hwnd_util.h"
 #endif  // OS_WIN
@@ -234,6 +233,12 @@
   return BrowserWindow::CreateBrowserWindow(browser);
 }
 
+// Is the fast tab unload experiment enabled?
+bool IsFastTabUnloadEnabled() {
+  return CommandLine::ForCurrentProcess()->HasSwitch(
+        switches::kEnableFastUnload);
+}
+
 }  // namespace
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -333,7 +338,6 @@
       initial_show_state_(params.initial_show_state),
       is_session_restore_(params.is_session_restore),
       host_desktop_type_(params.host_desktop_type),
-      unload_controller_(new chrome::UnloadController(this)),
       weak_factory_(this),
       content_setting_bubble_model_delegate_(
           new BrowserContentSettingBubbleModelDelegate(this)),
@@ -349,6 +353,12 @@
   // from opening at all, but the path that triggered it should be fixed.
   CHECK(IncognitoModePrefs::CanOpenBrowser(profile_));
 
+  // TODO(jeremy): Move to initializer list once flag is removed.
+  if (IsFastTabUnloadEnabled())
+    fast_unload_controller_.reset(new chrome::FastUnloadController(this));
+  else
+    unload_controller_.reset(new chrome::UnloadController(this));
+
   if (!app_name_.empty())
     chrome::RegisterAppPrefs(app_name_, profile_);
   tab_strip_model_->AddObserver(this);
@@ -483,6 +493,10 @@
   // is destroyed to make sure the chrome.windows.onRemoved event is sent.
   extension_window_controller_.reset();
 
+  // Destroy BrowserInstantController before the incongnito profile is destroyed
+  // because the InstantController destructor depends on this profile.
+  instant_controller_.reset();
+
   if (profile_->IsOffTheRecord() &&
       !BrowserList::IsOffTheRecordSessionActiveForProfile(profile_)) {
     // An incognito profile is no longer needed, this indirectly frees
@@ -582,18 +596,19 @@
   if (!CanCloseWithInProgressDownloads())
     return false;
 
+  if (IsFastTabUnloadEnabled())
+    return fast_unload_controller_->ShouldCloseWindow();
   return unload_controller_->ShouldCloseWindow();
 }
 
-bool Browser::TabsNeedBeforeUnloadFired() {
-  return unload_controller_->TabsNeedBeforeUnloadFired();
-}
-
 bool Browser::HasCompletedUnloadProcessing() const {
-  return unload_controller_->HasCompletedUnloadProcessing();
+  DCHECK(IsFastTabUnloadEnabled());
+  return fast_unload_controller_->HasCompletedUnloadProcessing();
 }
 
 bool Browser::IsAttemptingToCloseBrowser() const {
+  if (IsFastTabUnloadEnabled())
+    return fast_unload_controller_->is_attempting_to_close_browser();
   return unload_controller_->is_attempting_to_close_browser();
 }
 
@@ -636,6 +651,9 @@
       chrome::NOTIFICATION_BROWSER_CLOSING,
       content::Source<Browser>(this),
       content::NotificationService::NoDetails());
+
+  if (!IsFastTabUnloadEnabled())
+    tab_strip_model_->CloseAllTabs();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -1083,6 +1101,7 @@
                             WebContents* new_contents,
                             int index) {
   TabDetachedAtImpl(old_contents, index, DETACH_TYPE_REPLACE);
+  fullscreen_controller_->OnTabClosing(old_contents);
   SessionService* session_service =
       SessionServiceFactory::GetForProfile(profile_);
   if (session_service)
@@ -1172,6 +1191,12 @@
   window()->HandleKeyboardEvent(event);
 }
 
+bool Browser::TabsNeedBeforeUnloadFired() {
+  if (IsFastTabUnloadEnabled())
+    return fast_unload_controller_->TabsNeedBeforeUnloadFired();
+  return unload_controller_->TabsNeedBeforeUnloadFired();
+}
+
 bool Browser::IsMouseLocked() const {
   return fullscreen_controller_->IsMouseLocked();
 }
@@ -1305,7 +1330,13 @@
 }
 
 void Browser::CloseContents(WebContents* source) {
-  if (unload_controller_->CanCloseContents(source))
+  bool can_close_contents;
+  if (IsFastTabUnloadEnabled())
+    can_close_contents = fast_unload_controller_->CanCloseContents(source);
+  else
+    can_close_contents = unload_controller_->CanCloseContents(source);
+
+  if (can_close_contents)
     chrome::CloseWebContents(this, source, true);
 }
 
@@ -1368,8 +1399,13 @@
 void Browser::BeforeUnloadFired(WebContents* web_contents,
                                 bool proceed,
                                 bool* proceed_to_fire_unload) {
-  *proceed_to_fire_unload =
-      unload_controller_->BeforeUnloadFired(web_contents, proceed);
+  if (IsFastTabUnloadEnabled()) {
+    *proceed_to_fire_unload =
+        fast_unload_controller_->BeforeUnloadFired(web_contents, proceed);
+  } else {
+    *proceed_to_fire_unload =
+        unload_controller_->BeforeUnloadFired(web_contents, proceed);
+  }
 }
 
 bool Browser::ShouldFocusLocationBarByDefault(WebContents* source) {
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h
index 60ac1ea..62f6ba6 100644
--- a/chrome/browser/ui/browser.h
+++ b/chrome/browser/ui/browser.h
@@ -66,6 +66,7 @@
 
 namespace chrome {
 class BrowserCommandController;
+class FastUnloadController;
 class UnloadController;
 }
 
@@ -869,6 +870,7 @@
   const chrome::HostDesktopType host_desktop_type_;
 
   scoped_ptr<chrome::UnloadController> unload_controller_;
+  scoped_ptr<chrome::FastUnloadController> fast_unload_controller_;
 
   // The following factory is used to close the frame at a later time.
   base::WeakPtrFactory<Browser> weak_factory_;
diff --git a/chrome/browser/ui/browser_browsertest.cc b/chrome/browser/ui/browser_browsertest.cc
index 74c466e..e8c2787 100644
--- a/chrome/browser/ui/browser_browsertest.cc
+++ b/chrome/browser/ui/browser_browsertest.cc
@@ -609,8 +609,7 @@
 
   // Open a second browser window at about:blank.
   ui_test_utils::BrowserAddedObserver browser_added_observer;
-  chrome::NewEmptyWindow(browser()->profile(),
-                         chrome::HOST_DESKTOP_TYPE_NATIVE);
+  chrome::NewEmptyWindow(browser()->profile(), chrome::GetActiveDesktop());
   Browser* second_window = browser_added_observer.WaitForSingleNewBrowser();
   ui_test_utils::NavigateToURL(second_window, GURL("about:blank"));
 
@@ -1888,7 +1887,7 @@
   EXPECT_EQ(0u, chrome::GetTotalBrowserCount());
 
   ui_test_utils::BrowserAddedObserver browser_added_observer;
-  chrome::NewEmptyWindow(profile, chrome::HOST_DESKTOP_TYPE_NATIVE);
+  chrome::NewEmptyWindow(profile, chrome::GetActiveDesktop());
   browser_added_observer.WaitForSingleNewBrowser();
 
   EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
diff --git a/chrome/browser/ui/browser_command_controller.cc b/chrome/browser/ui/browser_command_controller.cc
index c5d34be..b38cf57 100644
--- a/chrome/browser/ui/browser_command_controller.cc
+++ b/chrome/browser/ui/browser_command_controller.cc
@@ -23,9 +23,9 @@
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/chrome_pages.h"
+#include "chrome/browser/ui/sync/sync_promo_ui.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/tabs/tab_strip_model_utils.h"
-#include "chrome/browser/ui/webui/sync_promo/sync_promo_ui.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/profiling.h"
@@ -627,10 +627,7 @@
       ToggleDevToolsWindow(browser_, DEVTOOLS_TOGGLE_ACTION_TOGGLE);
       break;
     case IDC_TASK_MANAGER:
-      OpenTaskManager(browser_, false);
-      break;
-    case IDC_VIEW_BACKGROUND_PAGES:
-      OpenTaskManager(browser_, true);
+      OpenTaskManager(browser_);
       break;
     case IDC_FEEDBACK:
       OpenFeedbackDialog(browser_);
@@ -941,10 +938,6 @@
   command_updater_.UpdateCommandEnabled(IDC_UPGRADE_DIALOG, true);
   command_updater_.UpdateCommandEnabled(IDC_VIEW_INCOMPATIBILITIES, true);
 
-  // View Background Pages entry is always enabled, but is hidden if there are
-  // no background pages.
-  command_updater_.UpdateCommandEnabled(IDC_VIEW_BACKGROUND_PAGES, true);
-
   // Toggle speech input
   command_updater_.UpdateCommandEnabled(IDC_TOGGLE_SPEECH_INPUT, true);
 
diff --git a/chrome/browser/ui/browser_command_controller_unittest.cc b/chrome/browser/ui/browser_command_controller_unittest.cc
index 87e9be5..6d50522 100644
--- a/chrome/browser/ui/browser_command_controller_unittest.cc
+++ b/chrome/browser/ui/browser_command_controller_unittest.cc
@@ -301,8 +301,7 @@
   profile1->SetOffTheRecordProfile(profile2);
 
   // Create a new browser based on the off the record profile.
-  Browser::CreateParams profile_params(profile2,
-                                       chrome::HOST_DESKTOP_TYPE_NATIVE);
+  Browser::CreateParams profile_params(profile2, chrome::GetActiveDesktop());
   scoped_ptr<Browser> browser2(
       chrome::CreateBrowserWithTestWindowForParams(&profile_params));
 
diff --git a/chrome/browser/ui/browser_commands.cc b/chrome/browser/ui/browser_commands.cc
index 51c6169..d233e28 100644
--- a/chrome/browser/ui/browser_commands.cc
+++ b/chrome/browser/ui/browser_commands.cc
@@ -53,9 +53,9 @@
 #include "chrome/browser/ui/webui/ntp/app_launcher_handler.h"
 #include "chrome/browser/upgrade_detector.h"
 #include "chrome/browser/web_applications/web_app.h"
-#include "chrome/common/chrome_content_client.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "chrome/common/chrome_switches.h"
+#include "chrome/common/chrome_version_info.h"
 #include "chrome/common/pref_names.h"
 #include "components/web_modal/web_contents_modal_dialog_manager.h"
 #include "content/public/browser/devtools_agent_host.h"
@@ -375,8 +375,8 @@
   // If the home page is a Google home page, add the RLZ header to the request.
   PrefService* pref_service = browser->profile()->GetPrefs();
   if (pref_service) {
-    std::string home_page = pref_service->GetString(prefs::kHomePage);
-    if (google_util::IsGoogleHomePageUrl(home_page)) {
+    if (google_util::IsGoogleHomePageUrl(
+        GURL(pref_service->GetString(prefs::kHomePage)))) {
       extra_headers = RLZTracker::GetAccessPointHttpHeader(
           RLZTracker::CHROME_HOME_PAGE);
     }
@@ -892,9 +892,9 @@
 #endif
 }
 
-void OpenTaskManager(Browser* browser, bool highlight_background_resources) {
+void OpenTaskManager(Browser* browser) {
   content::RecordAction(UserMetricsAction("TaskManager"));
-  chrome::ShowTaskManager(browser, highlight_background_resources);
+  chrome::ShowTaskManager(browser);
 }
 
 void OpenFeedbackDialog(Browser* browser) {
@@ -964,10 +964,13 @@
     entry->SetIsOverridingUserAgent(false);
   } else {
     entry->SetIsOverridingUserAgent(true);
+    chrome::VersionInfo version_info;
+    std::string product;
+    if (version_info.is_valid())
+      product = version_info.ProductNameAndVersionForUserAgent();
     current_tab->SetUserAgentOverride(
         webkit_glue::BuildUserAgentFromOSAndProduct(
-            kOsOverrideForTabletSite,
-            ChromeContentClient::GetProductImpl()));
+            kOsOverrideForTabletSite, product));
   }
   controller.ReloadOriginalRequestURL(true);
 }
diff --git a/chrome/browser/ui/browser_commands.h b/chrome/browser/ui/browser_commands.h
index f144d8c..b64b212 100644
--- a/chrome/browser/ui/browser_commands.h
+++ b/chrome/browser/ui/browser_commands.h
@@ -132,7 +132,7 @@
 void FocusPreviousPane(Browser* browser);
 void ToggleDevToolsWindow(Browser* browser, DevToolsToggleAction action);
 bool CanOpenTaskManager();
-void OpenTaskManager(Browser* browser, bool highlight_background_resources);
+void OpenTaskManager(Browser* browser);
 void OpenFeedbackDialog(Browser* browser);
 void ToggleBookmarkBar(Browser* browser);
 void ShowAppMenu(Browser* browser);
diff --git a/chrome/browser/ui/browser_dialogs.h b/chrome/browser/ui/browser_dialogs.h
index 8ee472e..c3ad400 100644
--- a/chrome/browser/ui/browser_dialogs.h
+++ b/chrome/browser/ui/browser_dialogs.h
@@ -68,9 +68,8 @@
 void ShowHungRendererDialog(content::WebContents* contents);
 void HideHungRendererDialog(content::WebContents* contents);
 
-// Shows the Task Manager. If |highlight_background_resources| is set, the
-// backgroundpages will be shown. |browser| can be NULL when called from ASH.
-void ShowTaskManager(Browser* browser, bool highlight_background_resources);
+// Shows the Task Manager. |browser| can be NULL when called from Ash.
+void ShowTaskManager(Browser* browser);
 
 #if !defined(OS_MACOSX)
 // Shows the create web app shortcut dialog box.
diff --git a/chrome/browser/ui/browser_focus_uitest.cc b/chrome/browser/ui/browser_focus_uitest.cc
index e83c347..303d4c2 100644
--- a/chrome/browser/ui/browser_focus_uitest.cc
+++ b/chrome/browser/ui/browser_focus_uitest.cc
@@ -37,7 +37,7 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_view.h"
 #include "content/public/test/browser_test_utils.h"
-#include "net/test/spawned_test_server/spawned_test_server.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
 
 #if defined(TOOLKIT_VIEWS)
 #include "chrome/browser/ui/views/frame/browser_view.h"
@@ -87,9 +87,9 @@
 // Maxiumum time to wait until the focus is moved to expected view.
 const int kFocusChangeTimeoutMs = 500;
 
-const char kSimplePage[] = "files/focus/page_with_focus.html";
-const char kStealFocusPage[] = "files/focus/page_steals_focus.html";
-const char kTypicalPage[] = "files/focus/typical_page.html";
+const char kSimplePage[] = "/focus/page_with_focus.html";
+const char kStealFocusPage[] = "/focus/page_steals_focus.html";
+const char kTypicalPage[] = "/focus/typical_page.html";
 const char kTypicalPageName[] = "typical_page.html";
 
 // Test to make sure Chrome is in the foreground as we start testing. This is
@@ -238,10 +238,10 @@
 // Flaky, http://crbug.com/69034.
 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, DISABLED_BrowsersRememberFocus) {
   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   // First we navigate to our test page.
-  GURL url = test_server()->GetURL(kSimplePage);
+  GURL url = embedded_test_server()->GetURL(kSimplePage);
   ui_test_utils::NavigateToURL(browser(), url);
 
   gfx::NativeWindow window = browser()->window()->GetNativeWindow();
@@ -307,10 +307,10 @@
 // Disabled, http://crbug.com/62542.
 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, DISABLED_TabsRememberFocus) {
   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   // First we navigate to our test page.
-  GURL url = test_server()->GetURL(kSimplePage);
+  GURL url = embedded_test_server()->GetURL(kSimplePage);
   ui_test_utils::NavigateToURL(browser(), url);
 
   // Create several tabs.
@@ -376,10 +376,10 @@
 // Tabs remember focus with find-in-page box.
 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, MAYBE_TabsRememberFocusFindInPage) {
   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   // First we navigate to our test page.
-  GURL url = test_server()->GetURL(kSimplePage);
+  GURL url = embedded_test_server()->GetURL(kSimplePage);
   ui_test_utils::NavigateToURL(browser(), url);
 
   chrome::Find(browser());
@@ -417,7 +417,7 @@
 IN_PROC_BROWSER_TEST_F(BrowserFocusTest,
                        DISABLED_BackgroundBrowserDontStealFocus) {
   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   // Open a new browser window.
   Browser* browser2 =
@@ -450,7 +450,7 @@
   unfocused_browser = browser();
 #endif
 
-  GURL steal_focus_url = test_server()->GetURL(kStealFocusPage);
+  GURL steal_focus_url = embedded_test_server()->GetURL(kStealFocusPage);
   ui_test_utils::NavigateToURL(unfocused_browser, steal_focus_url);
 
   // Activate the first browser.
@@ -467,10 +467,10 @@
 // Page cannot steal focus when focus is on location bar.
 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, LocationBarLockFocus) {
   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   // Open the page that steals focus.
-  GURL url = test_server()->GetURL(kStealFocusPage);
+  GURL url = embedded_test_server()->GetURL(kStealFocusPage);
   ui_test_utils::NavigateToURL(browser(), url);
 
   chrome::FocusLocationBar(browser());
@@ -490,10 +490,10 @@
 // RenderWidget::didFocus()).
 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, MAYBE_FocusTraversal) {
   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   // First we navigate to our test page.
-  GURL url = test_server()->GetURL(kTypicalPage);
+  GURL url = embedded_test_server()->GetURL(kTypicalPage);
   ui_test_utils::NavigateToURL(browser(), url);
 
   chrome::FocusLocationBar(browser());
@@ -612,10 +612,10 @@
 // Focus traversal while an interstitial is showing.
 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, MAYBE_FocusTraversalOnInterstitial) {
   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   // First we navigate to our test page.
-  GURL url = test_server()->GetURL(kSimplePage);
+  GURL url = embedded_test_server()->GetURL(kSimplePage);
   ui_test_utils::NavigateToURL(browser(), url);
 
   // Focus should be on the page.
@@ -732,10 +732,10 @@
 // http://crbug.com/81451
 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, DISABLED_InterstitialFocus) {
   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   // First we navigate to our test page.
-  GURL url = test_server()->GetURL(kSimplePage);
+  GURL url = embedded_test_server()->GetURL(kSimplePage);
   ui_test_utils::NavigateToURL(browser(), url);
 
   // Page should have focus.
@@ -769,10 +769,10 @@
 // Disabled due to flakiness. http://crbug.com/67301.
 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, DISABLED_FindFocusTest) {
   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   // Open some page (any page that doesn't steal focus).
-  GURL url = test_server()->GetURL(kTypicalPage);
+  GURL url = embedded_test_server()->GetURL(kTypicalPage);
   ui_test_utils::NavigateToURL(browser(), url);
 
   EXPECT_TRUE(ChromeInForeground());
@@ -853,7 +853,7 @@
 // Tests that focus goes where expected when using reload.
 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, FocusOnReload) {
   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   // Open the new tab, reload.
   {
@@ -878,7 +878,8 @@
   ASSERT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
 
   // Open a regular page, focus the location bar, reload.
-  ui_test_utils::NavigateToURL(browser(), test_server()->GetURL(kSimplePage));
+  ui_test_utils::NavigateToURL(browser(),
+                               embedded_test_server()->GetURL(kSimplePage));
   chrome::FocusLocationBar(browser());
   ASSERT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
   {
@@ -899,10 +900,11 @@
 // Tests that focus goes where expected when using reload on a crashed tab.
 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, DISABLED_FocusOnReloadCrashedTab) {
   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   // Open a regular page, crash, reload.
-  ui_test_utils::NavigateToURL(browser(), test_server()->GetURL(kSimplePage));
+  ui_test_utils::NavigateToURL(browser(),
+                               embedded_test_server()->GetURL(kSimplePage));
   content::CrashTab(browser()->tab_strip_model()->GetActiveWebContents());
   {
     content::WindowedNotificationObserver observer(
diff --git a/chrome/browser/ui/browser_instant_controller.cc b/chrome/browser/ui/browser_instant_controller.cc
index 008753e..6203f51 100644
--- a/chrome/browser/ui/browser_instant_controller.cc
+++ b/chrome/browser/ui/browser_instant_controller.cc
@@ -15,27 +15,20 @@
 #include "chrome/browser/search_engines/template_url.h"
 #include "chrome/browser/search_engines/template_url_service.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
-#include "chrome/browser/themes/theme_properties.h"
-#include "chrome/browser/themes/theme_service.h"
-#include "chrome/browser/themes/theme_service_factory.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/omnibox/location_bar.h"
 #include "chrome/browser/ui/omnibox/omnibox_view.h"
+#include "chrome/browser/ui/search/search_model.h"
 #include "chrome/browser/ui/search/search_tab_helper.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/webui/ntp/app_launcher_handler.h"
-#include "chrome/common/chrome_notification_types.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
 #include "components/user_prefs/pref_registry_syncable.h"
-#include "content/public/browser/notification_service.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/user_metrics.h"
 #include "content/public/browser/web_contents.h"
-#include "grit/theme_resources.h"
-#include "ui/gfx/color_utils.h"
-#include "ui/gfx/sys_color_change_listener.h"
 
 using content::UserMetricsAction;
 
@@ -44,10 +37,8 @@
 
 BrowserInstantController::BrowserInstantController(Browser* browser)
     : browser_(browser),
-      instant_(this,
-               chrome::IsInstantExtendedAPIEnabled()),
-      instant_unload_handler_(browser),
-      initialized_theme_info_(false) {
+      instant_(this, chrome::IsInstantExtendedAPIEnabled()),
+      instant_unload_handler_(browser) {
 
   // TODO(sreeram): Perhaps this can be removed, if field trial info is
   // available before we need to register the pref.
@@ -68,17 +59,12 @@
                  base::Unretained(this)));
   ResetInstant(std::string());
   browser_->search_model()->AddObserver(this);
-
-#if defined(ENABLE_THEMES)
-  // Listen for theme installation.
-  registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
-                 content::Source<ThemeService>(
-                     ThemeServiceFactory::GetForProfile(profile())));
-#endif  // defined(ENABLE_THEMES)
+  net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
 }
 
 BrowserInstantController::~BrowserInstantController() {
   browser_->search_model()->RemoveObserver(this);
+  net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
 }
 
 bool BrowserInstantController::MaybeSwapInInstantNTPContents(
@@ -159,29 +145,6 @@
   return browser_->profile();
 }
 
-void BrowserInstantController::CommitInstant(
-    scoped_ptr<content::WebContents> overlay,
-    bool in_new_tab) {
-  const extensions::Extension* extension =
-      profile()->GetExtensionService()->GetInstalledApp(overlay->GetURL());
-  if (extension) {
-    AppLauncherHandler::RecordAppLaunchType(
-        extension_misc::APP_LAUNCH_OMNIBOX_INSTANT,
-        extension->GetType());
-  }
-  if (in_new_tab) {
-    // TabStripModel takes ownership of |overlay|.
-    browser_->tab_strip_model()->AddWebContents(overlay.release(), -1,
-        instant_.last_transition_type(), TabStripModel::ADD_ACTIVE);
-  } else {
-    content::WebContents* contents = overlay.get();
-    ReplaceWebContentsAt(
-        browser_->tab_strip_model()->active_index(),
-        overlay.Pass());
-    browser_->window()->GetLocationBar()->SaveStateToContents(contents);
-  }
-}
-
 void BrowserInstantController::ReplaceWebContentsAt(
     int index,
     scoped_ptr<content::WebContents> new_contents) {
@@ -192,20 +155,6 @@
                                                       index);
 }
 
-void BrowserInstantController::SetInstantSuggestion(
-    const InstantSuggestion& suggestion) {
-  browser_->window()->GetLocationBar()->SetInstantSuggestion(suggestion);
-}
-
-gfx::Rect BrowserInstantController::GetInstantBounds() {
-  return browser_->window()->GetInstantBounds();
-}
-
-void BrowserInstantController::InstantOverlayFocused() {
-  // NOTE: This is only invoked on aura.
-  browser_->window()->WebContentsFocused(instant_.GetOverlayContents());
-}
-
 void BrowserInstantController::FocusOmnibox(bool caret_visibility) {
   OmniboxView* omnibox_view = browser_->window()->GetLocationBar()->
       GetLocationEntry();
@@ -233,15 +182,6 @@
   instant_.TabDeactivated(contents);
 }
 
-void BrowserInstantController::UpdateThemeInfo() {
-  // Update theme background info.
-  // Initialize |theme_info| if necessary.
-  if (!initialized_theme_info_)
-    OnThemeChanged(ThemeServiceFactory::GetForProfile(profile()));
-  else
-    OnThemeChanged(NULL);
-}
-
 void BrowserInstantController::OpenURL(
     const GURL& url,
     content::PageTransition transition,
@@ -257,16 +197,16 @@
   instant_.SetOmniboxBounds(bounds);
 }
 
+void BrowserInstantController::UpdateLocationBar() {
+  browser_->window()->UpdateToolbar(GetActiveWebContents(), false);
+}
+
 void BrowserInstantController::ToggleVoiceSearch() {
   instant_.ToggleVoiceSearch();
 }
 
 void BrowserInstantController::ResetInstant(const std::string& pref_name) {
-  bool instant_checkbox_checked = chrome::IsInstantCheckboxChecked(profile());
-  bool use_local_overlay_only =
-      chrome::IsLocalOnlyInstantExtendedAPIEnabled() ||
-      !chrome::IsInstantCheckboxEnabled(profile());
-  instant_.SetInstantEnabled(instant_checkbox_checked, use_local_overlay_only);
+  instant_.ReloadStaleNTP();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -275,116 +215,33 @@
 void BrowserInstantController::ModelChanged(
     const SearchModel::State& old_state,
     const SearchModel::State& new_state) {
-  if (old_state.mode == new_state.mode)
-    return;
+  if (old_state.mode != new_state.mode) {
+    const SearchMode& new_mode = new_state.mode;
 
-  const SearchMode& new_mode = new_state.mode;
+    if (chrome::IsInstantExtendedAPIEnabled()) {
+      // Record some actions corresponding to the mode change. Note that to get
+      // the full story, it's necessary to look at other UMA actions as well,
+      // such as tab switches.
+      if (new_mode.is_search_results())
+        content::RecordAction(UserMetricsAction("InstantExtended.ShowSRP"));
+      else if (new_mode.is_ntp())
+        content::RecordAction(UserMetricsAction("InstantExtended.ShowNTP"));
+    }
 
-  if (chrome::IsInstantExtendedAPIEnabled()) {
-    // Record some actions corresponding to the mode change. Note that to get
-    // the full story, it's necessary to look at other UMA actions as well,
-    // such as tab switches.
-    if (new_mode.is_search_results())
-      content::RecordAction(UserMetricsAction("InstantExtended.ShowSRP"));
-    else if (new_mode.is_ntp())
-      content::RecordAction(UserMetricsAction("InstantExtended.ShowNTP"));
+    instant_.SearchModeChanged(old_state.mode, new_mode);
   }
 
-  // If mode is now |NTP|, send theme-related information to Instant.
-  if (new_mode.is_ntp())
-    UpdateThemeInfo();
-
-  instant_.SearchModeChanged(old_state.mode, new_mode);
+  if (old_state.instant_support != new_state.instant_support)
+    instant_.InstantSupportChanged(new_state.instant_support);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// BrowserInstantController, content::NotificationObserver implementation:
+// BrowserInstantController, net::NetworkChangeNotifier::NetworkChangeObserver
+// implementation:
 
-void BrowserInstantController::Observe(
-    int type,
-    const content::NotificationSource& source,
-    const content::NotificationDetails& details) {
-#if defined(ENABLE_THEMES)
-  DCHECK_EQ(chrome::NOTIFICATION_BROWSER_THEME_CHANGED, type);
-  OnThemeChanged(content::Source<ThemeService>(source).ptr());
-#endif  // defined(ENABLE_THEMES)
-}
-
-void BrowserInstantController::OnThemeChanged(ThemeService* theme_service) {
-  if (theme_service) {  // Get theme information from theme service.
-    theme_info_ = ThemeBackgroundInfo();
-
-    // Set theme background color.
-    SkColor background_color =
-        theme_service->GetColor(ThemeProperties::COLOR_NTP_BACKGROUND);
-    if (gfx::IsInvertedColorScheme())
-      background_color = color_utils::InvertColor(background_color);
-    theme_info_.color_r = SkColorGetR(background_color);
-    theme_info_.color_g = SkColorGetG(background_color);
-    theme_info_.color_b = SkColorGetB(background_color);
-    theme_info_.color_a = SkColorGetA(background_color);
-
-    if (theme_service->HasCustomImage(IDR_THEME_NTP_BACKGROUND)) {
-      // Set theme id for theme background image url.
-      theme_info_.theme_id = theme_service->GetThemeID();
-
-      // Set theme background image horizontal alignment.
-      int alignment = 0;
-      theme_service->GetDisplayProperty(
-          ThemeProperties::NTP_BACKGROUND_ALIGNMENT, &alignment);
-      if (alignment & ThemeProperties::ALIGN_LEFT) {
-        theme_info_.image_horizontal_alignment = THEME_BKGRND_IMAGE_ALIGN_LEFT;
-      } else if (alignment & ThemeProperties::ALIGN_RIGHT) {
-        theme_info_.image_horizontal_alignment = THEME_BKGRND_IMAGE_ALIGN_RIGHT;
-      } else {  // ALIGN_CENTER
-        theme_info_.image_horizontal_alignment =
-            THEME_BKGRND_IMAGE_ALIGN_CENTER;
-      }
-
-      // Set theme background image vertical alignment.
-      if (alignment & ThemeProperties::ALIGN_TOP)
-        theme_info_.image_vertical_alignment = THEME_BKGRND_IMAGE_ALIGN_TOP;
-      else if (alignment & ThemeProperties::ALIGN_BOTTOM)
-        theme_info_.image_vertical_alignment = THEME_BKGRND_IMAGE_ALIGN_BOTTOM;
-      else  // ALIGN_CENTER
-        theme_info_.image_vertical_alignment = THEME_BKGRND_IMAGE_ALIGN_CENTER;
-
-      // Set theme background image tiling.
-      int tiling = 0;
-      theme_service->GetDisplayProperty(ThemeProperties::NTP_BACKGROUND_TILING,
-                                        &tiling);
-      switch (tiling) {
-        case ThemeProperties::NO_REPEAT:
-            theme_info_.image_tiling = THEME_BKGRND_IMAGE_NO_REPEAT;
-            break;
-        case ThemeProperties::REPEAT_X:
-            theme_info_.image_tiling = THEME_BKGRND_IMAGE_REPEAT_X;
-            break;
-        case ThemeProperties::REPEAT_Y:
-            theme_info_.image_tiling = THEME_BKGRND_IMAGE_REPEAT_Y;
-            break;
-        case ThemeProperties::REPEAT:
-            theme_info_.image_tiling = THEME_BKGRND_IMAGE_REPEAT;
-            break;
-      }
-
-      // Set theme background image height.
-      gfx::ImageSkia* image = theme_service->GetImageSkiaNamed(
-          IDR_THEME_NTP_BACKGROUND);
-      DCHECK(image);
-      theme_info_.image_height = image->height();
-
-      theme_info_.has_attribution =
-          theme_service->HasCustomImage(IDR_THEME_NTP_ATTRIBUTION);
-    }
-
-    initialized_theme_info_ = true;
-  }
-
-  DCHECK(initialized_theme_info_);
-
-  if (browser_->search_model()->mode().is_ntp())
-    instant_.ThemeChanged(theme_info_);
+void BrowserInstantController::OnNetworkChanged(
+    net::NetworkChangeNotifier::ConnectionType type) {
+  instant_.OnNetworkChanged(type);
 }
 
 void BrowserInstantController::OnDefaultSearchProviderChanged(
diff --git a/chrome/browser/ui/browser_instant_controller.h b/chrome/browser/ui/browser_instant_controller.h
index defc8b6..0f9414f 100644
--- a/chrome/browser/ui/browser_instant_controller.h
+++ b/chrome/browser/ui/browser_instant_controller.h
@@ -13,14 +13,12 @@
 #include "chrome/browser/ui/search/instant_controller.h"
 #include "chrome/browser/ui/search/instant_unload_handler.h"
 #include "chrome/browser/ui/search/search_model_observer.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
+#include "net/base/network_change_notifier.h"
 #include "ui/base/window_open_disposition.h"
 
 class Browser;
 struct InstantSuggestion;
 class Profile;
-class ThemeService;
 
 namespace content {
 class WebContents;
@@ -30,8 +28,9 @@
 class Rect;
 }
 
-class BrowserInstantController : public content::NotificationObserver,
-                                 public SearchModelObserver {
+class BrowserInstantController
+    : public SearchModelObserver,
+      public net::NetworkChangeNotifier::NetworkChangeObserver {
  public:
   explicit BrowserInstantController(Browser* browser);
   virtual ~BrowserInstantController();
@@ -59,27 +58,11 @@
   // this BrowserInstantController.
   InstantController* instant() { return &instant_; }
 
-  // Invoked by |instant_| to commit the |overlay| by merging it into the active
-  // tab or adding it as a new tab.
-  void CommitInstant(scoped_ptr<content::WebContents> overlay, bool in_new_tab);
-
-  // Invoked by |instant_| to autocomplete the |suggestion| into the omnibox.
-  void SetInstantSuggestion(const InstantSuggestion& suggestion);
-
-  // Invoked by |instant_| to get the bounds that the overlay is placed at,
-  // in screen coordinates.
-  gfx::Rect GetInstantBounds();
-
-  // Invoked by |instant_| to notify that the overlay gained focus, usually due
-  // to the user clicking on it.
-  void InstantOverlayFocused();
-
   // Invoked by |instant_| to give the omnibox focus, with the option of making
   // the caret invisible.
   void FocusOmnibox(bool caret_visibility);
 
-  // Invoked by |instant_| to get the currently active tab, over which the
-  // overlay would be shown.
+  // Invoked by |instant_| to get the currently active tab.
   content::WebContents* GetActiveWebContents() const;
 
   // Invoked by |browser_| when the active tab changes.
@@ -88,9 +71,6 @@
   // Invoked by |browser_| when the active tab is about to be deactivated.
   void TabDeactivated(content::WebContents* contents);
 
-  // Invoked by |instant_| to update theme information for NTP.
-  void UpdateThemeInfo();
-
   // Invoked by the InstantController when it wants to open a URL.
   void OpenURL(const GURL& url,
                content::PageTransition transition,
@@ -99,6 +79,10 @@
   // Sets the stored omnibox bounds.
   void SetOmniboxBounds(const gfx::Rect& bounds);
 
+  // Updates the location bar to reflect the active page contents Instant
+  // support state.
+  void UpdateLocationBar();
+
   // Notifies |instant_| to toggle voice search.
   void ToggleVoiceSearch();
 
@@ -111,20 +95,16 @@
   virtual void ModelChanged(const SearchModel::State& old_state,
                             const SearchModel::State& new_state) OVERRIDE;
 
-  // content::NotificationObserver implementation.
-  virtual void Observe(int type,
-                       const content::NotificationSource& source,
-                       const content::NotificationDetails& details) OVERRIDE;
-
-  // Helper for handling theme change.
-  void OnThemeChanged(ThemeService* theme_service);
-
   // Called when the default search provider changes. Revokes the searchbox API
   // privileges for any existing WebContents (that belong to the erstwhile
   // default search provider) by simply reloading all such WebContents. This
   // ensures that they are reloaded in a non-privileged renderer process.
   void OnDefaultSearchProviderChanged(const std::string& pref_name);
 
+  // Overridden from net::NetworkChangeNotifier::NetworkChangeObserver:
+  virtual void OnNetworkChanged(net::NetworkChangeNotifier::ConnectionType type)
+      OVERRIDE;
+
   // Replaces the contents at tab |index| with |new_contents| and deletes the
   // existing contents.
   void ReplaceWebContentsAt(int index,
@@ -135,14 +115,8 @@
   InstantController instant_;
   InstantUnloadHandler instant_unload_handler_;
 
-  // Theme-related data for NTP overlay to adopt themes.
-  bool initialized_theme_info_;  // True if theme_info_ has been initialized.
-  ThemeBackgroundInfo theme_info_;
-
   PrefChangeRegistrar profile_pref_registrar_;
 
-  content::NotificationRegistrar registrar_;
-
   DISALLOW_COPY_AND_ASSIGN(BrowserInstantController);
 };
 
diff --git a/chrome/browser/ui/browser_mac.h b/chrome/browser/ui/browser_mac.h
index 2019b69..5031ac5 100644
--- a/chrome/browser/ui/browser_mac.h
+++ b/chrome/browser/ui/browser_mac.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_UI_BROWSER_MAC_H_
 
 #include "chrome/browser/ui/chrome_pages.h"
-#include "chrome/browser/ui/webui/sync_promo/sync_promo_ui.h"
+#include "chrome/browser/ui/sync/sync_promo_ui.h"
 
 class Profile;
 
diff --git a/chrome/browser/ui/browser_navigator.cc b/chrome/browser/ui/browser_navigator.cc
index 0b73f95..3942de5 100644
--- a/chrome/browser/ui/browser_navigator.cc
+++ b/chrome/browser/ui/browser_navigator.cc
@@ -364,6 +364,12 @@
       url, source_contents, &params->target_contents);
 }
 
+chrome::HostDesktopType GetHostDesktop(Browser* browser) {
+  if (browser)
+    return browser->host_desktop_type();
+  return chrome::GetActiveDesktop();
+}
+
 }  // namespace
 
 namespace chrome {
@@ -385,12 +391,9 @@
       ref_behavior(IGNORE_REF),
       browser(a_browser),
       initiating_profile(NULL),
+      host_desktop_type(GetHostDesktop(a_browser)),
       is_cross_site_redirect(false) {
-        if (a_browser)
-          host_desktop_type = a_browser->host_desktop_type();
-        else
-          host_desktop_type = chrome::HOST_DESKTOP_TYPE_NATIVE;
-      }
+}
 
 NavigateParams::NavigateParams(Browser* a_browser,
                                WebContents* a_target_contents)
@@ -407,12 +410,9 @@
       ref_behavior(IGNORE_REF),
       browser(a_browser),
       initiating_profile(NULL),
+      host_desktop_type(GetHostDesktop(a_browser)),
       is_cross_site_redirect(false) {
-        if (a_browser)
-          host_desktop_type = a_browser->host_desktop_type();
-        else
-          host_desktop_type = chrome::HOST_DESKTOP_TYPE_NATIVE;
-      }
+}
 
 NavigateParams::NavigateParams(Profile* a_profile,
                                const GURL& a_url,
@@ -431,8 +431,9 @@
       ref_behavior(IGNORE_REF),
       browser(NULL),
       initiating_profile(a_profile),
-      host_desktop_type(chrome::HOST_DESKTOP_TYPE_NATIVE),
-      is_cross_site_redirect(false) {}
+      host_desktop_type(chrome::GetActiveDesktop()),
+      is_cross_site_redirect(false) {
+}
 
 NavigateParams::~NavigateParams() {}
 
diff --git a/chrome/browser/ui/browser_navigator_browsertest.cc b/chrome/browser/ui/browser_navigator_browsertest.cc
index 5baf285..8cd9080 100644
--- a/chrome/browser/ui/browser_navigator_browsertest.cc
+++ b/chrome/browser/ui/browser_navigator_browsertest.cc
@@ -79,7 +79,7 @@
 Browser* BrowserNavigatorTest::CreateEmptyBrowserForType(Browser::Type type,
                                                          Profile* profile) {
   Browser* browser = new Browser(
-      Browser::CreateParams(type, profile, chrome::HOST_DESKTOP_TYPE_NATIVE));
+      Browser::CreateParams(type, profile, chrome::GetActiveDesktop()));
   chrome::AddBlankTabAt(browser, -1, true);
   return browser;
 }
@@ -89,7 +89,7 @@
   Browser* browser = new Browser(
       Browser::CreateParams::CreateForApp(
           Browser::TYPE_POPUP, "Test", gfx::Rect(), profile,
-          chrome::HOST_DESKTOP_TYPE_NATIVE));
+          chrome::GetActiveDesktop()));
   chrome::AddBlankTabAt(browser, -1, true);
   return browser;
 }
diff --git a/chrome/browser/ui/browser_tab_contents.cc b/chrome/browser/ui/browser_tab_contents.cc
index 56d3204..e10a5f2 100644
--- a/chrome/browser/ui/browser_tab_contents.cc
+++ b/chrome/browser/ui/browser_tab_contents.cc
@@ -42,8 +42,8 @@
 #include "chrome/browser/ui/tab_contents/core_tab_helper.h"
 #include "chrome/browser/ui/zoom/zoom_controller.h"
 #include "chrome/common/chrome_switches.h"
-#include "components/autofill/browser/autofill_manager.h"
 #include "components/autofill/content/browser/autofill_driver_impl.h"
+#include "components/autofill/core/browser/autofill_manager.h"
 #include "components/web_modal/web_contents_modal_dialog_manager.h"
 #include "content/public/browser/web_contents.h"
 #include "extensions/browser/view_type_utils.h"
@@ -109,15 +109,11 @@
 
   AlternateErrorPageTabObserver::CreateForWebContents(web_contents);
   TabAutofillManagerDelegate::CreateForWebContents(web_contents);
-  bool native_autofill_ui_enabled =
-      !CommandLine::ForCurrentProcess()->HasSwitch(
-           switches::kDisableNativeAutofillUi);
   AutofillDriverImpl::CreateForWebContentsAndDelegate(
       web_contents,
       TabAutofillManagerDelegate::FromWebContents(web_contents),
       g_browser_process->GetApplicationLocale(),
-      AutofillManager::ENABLE_AUTOFILL_DOWNLOAD_MANAGER,
-      native_autofill_ui_enabled);
+      AutofillManager::ENABLE_AUTOFILL_DOWNLOAD_MANAGER);
   BlockedContentTabHelper::CreateForWebContents(web_contents);
   BookmarkTabHelper::CreateForWebContents(web_contents);
   chrome_browser_net::LoadTimeStatsTabHelper::CreateForWebContents(
diff --git a/chrome/browser/ui/chrome_pages.h b/chrome/browser/ui/chrome_pages.h
index 9d943f7..3420c5d 100644
--- a/chrome/browser/ui/chrome_pages.h
+++ b/chrome/browser/ui/chrome_pages.h
@@ -7,7 +7,7 @@
 
 #include <string>
 
-#include "chrome/browser/ui/webui/sync_promo/sync_promo_ui.h"
+#include "chrome/browser/ui/sync/sync_promo_ui.h"
 #include "chrome/common/content_settings_types.h"
 
 class Browser;
diff --git a/chrome/browser/ui/chrome_web_modal_dialog_manager_delegate.cc b/chrome/browser/ui/chrome_web_modal_dialog_manager_delegate.cc
index 7155008..da6396e 100644
--- a/chrome/browser/ui/chrome_web_modal_dialog_manager_delegate.cc
+++ b/chrome/browser/ui/chrome_web_modal_dialog_manager_delegate.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/chrome/browser/ui/chrome_web_modal_dialog_manager_delegate.h b/chrome/browser/ui/chrome_web_modal_dialog_manager_delegate.h
index 2263d75..749debc 100644
--- a/chrome/browser/ui/chrome_web_modal_dialog_manager_delegate.h
+++ b/chrome/browser/ui/chrome_web_modal_dialog_manager_delegate.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/chrome/browser/ui/cocoa/about_ipc_controller.mm b/chrome/browser/ui/cocoa/about_ipc_controller.mm
index 33667ab..1aebf06 100644
--- a/chrome/browser/ui/cocoa/about_ipc_controller.mm
+++ b/chrome/browser/ui/cocoa/about_ipc_controller.mm
@@ -7,7 +7,7 @@
 #include "base/mac/mac_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/sys_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #import "chrome/browser/ui/cocoa/about_ipc_controller.h"
 #include "content/public/browser/browser_ipc_logging.h"
 
diff --git a/chrome/browser/ui/cocoa/about_ipc_controller_unittest.mm b/chrome/browser/ui/cocoa/about_ipc_controller_unittest.mm
index 3f4eee7..e4c7bc1 100644
--- a/chrome/browser/ui/cocoa/about_ipc_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/about_ipc_controller_unittest.mm
@@ -4,7 +4,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #include "base/message_loop.h"
 #import "chrome/browser/ui/cocoa/about_ipc_controller.h"
 #include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
@@ -46,15 +46,15 @@
                           "NPObjectHell" };
   for (size_t i = 0; i < arraysize(names); i++) {
     data.message_name = names[i];
-    scoped_nsobject<CocoaLogData> cdata([[CocoaLogData alloc]
-                                          initWithLogData:data]);
+    base::scoped_nsobject<CocoaLogData> cdata(
+        [[CocoaLogData alloc] initWithLogData:data]);
     EXPECT_FALSE([controller filterOut:cdata.get()]);
   }
 
   // Flip a checkbox, see it filtered, flip back, all is fine.
   data.message_name = "ViewMsgFoo";
-  scoped_nsobject<CocoaLogData> cdata([[CocoaLogData alloc]
-                                        initWithLogData:data]);
+  base::scoped_nsobject<CocoaLogData> cdata(
+      [[CocoaLogData alloc] initWithLogData:data]);
   [controller setDisplayViewMessages:NO];
   EXPECT_TRUE([controller filterOut:cdata.get()]);
   [controller setDisplayViewMessages:YES];
diff --git a/chrome/browser/ui/cocoa/animatable_image.h b/chrome/browser/ui/cocoa/animatable_image.h
index da1f297..102f337 100644
--- a/chrome/browser/ui/cocoa/animatable_image.h
+++ b/chrome/browser/ui/cocoa/animatable_image.h
@@ -8,7 +8,7 @@
 #import <Cocoa/Cocoa.h>
 #import <QuartzCore/QuartzCore.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 
 // This class helps animate an NSImage's frame and opacity. It works by creating
 // a blank NSWindow in the size specified and giving it a layer on which the
@@ -20,7 +20,7 @@
 @interface AnimatableImage : NSWindow {
  @private
   // The image to animate.
-  scoped_nsobject<NSImage> image_;
+  base::scoped_nsobject<NSImage> image_;
 
   // The frame of the image before and after the animation. This is in this
   // window's coordinate system.
diff --git a/chrome/browser/ui/cocoa/animatable_image.mm b/chrome/browser/ui/cocoa/animatable_image.mm
index 2d09bf0..d2fd2da 100644
--- a/chrome/browser/ui/cocoa/animatable_image.mm
+++ b/chrome/browser/ui/cocoa/animatable_image.mm
@@ -130,7 +130,7 @@
 // Sets the layer contents by converting the NSImage to a CGImageRef.  This will
 // rasterize PDF resources.
 - (void)setLayerContents:(CALayer*)layer {
-  base::mac::ScopedCFTypeRef<CGImageRef> image(
+  base::ScopedCFTypeRef<CGImageRef> image(
       base::mac::CopyNSImageToCGImage(image_.get()));
   // Create the layer that will be animated.
   [layer setContents:(id)image.get()];
diff --git a/chrome/browser/ui/cocoa/animatable_view.h b/chrome/browser/ui/cocoa/animatable_view.h
index 91cae44..f84c2a5 100644
--- a/chrome/browser/ui/cocoa/animatable_view.h
+++ b/chrome/browser/ui/cocoa/animatable_view.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/background_gradient_view.h"
 #import "chrome/browser/ui/cocoa/view_resizer.h"
 
@@ -24,7 +24,7 @@
   IBOutlet id delegate_;  // weak, used to send animation ended messages.
 
  @private
-  scoped_nsobject<NSAnimation> currentAnimation_;
+  base::scoped_nsobject<NSAnimation> currentAnimation_;
   id<ViewResizer> resizeDelegate_;  // weak, usually owns us
 }
 
diff --git a/chrome/browser/ui/cocoa/animatable_view_unittest.mm b/chrome/browser/ui/cocoa/animatable_view_unittest.mm
index e59eae9..1554ff5 100644
--- a/chrome/browser/ui/cocoa/animatable_view_unittest.mm
+++ b/chrome/browser/ui/cocoa/animatable_view_unittest.mm
@@ -4,7 +4,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/animatable_view.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #import "chrome/browser/ui/cocoa/view_resizer_pong.h"
@@ -24,8 +24,8 @@
     [view_ setResizeDelegate:resizeDelegate_.get()];
   }
 
-  scoped_nsobject<ViewResizerPong> resizeDelegate_;
-  scoped_nsobject<AnimatableView> view_;
+  base::scoped_nsobject<ViewResizerPong> resizeDelegate_;
+  base::scoped_nsobject<AnimatableView> view_;
 };
 
 // Basic view tests (AddRemove, Display).
diff --git a/chrome/browser/ui/cocoa/applescript/bookmark_applescript_utils_unittest.h b/chrome/browser/ui/cocoa/applescript/bookmark_applescript_utils_unittest.h
index 2de6a78..b1f6b07 100644
--- a/chrome/browser/ui/cocoa/applescript/bookmark_applescript_utils_unittest.h
+++ b/chrome/browser/ui/cocoa/applescript/bookmark_applescript_utils_unittest.h
@@ -5,10 +5,10 @@
 #ifndef CHROME_BROWSER_UI_COCOA_APPLESCRIPT_BOOKMARK_APPLESCRIPT_UTILS_UNITTEST_H_
 #define CHROME_BROWSER_UI_COCOA_APPLESCRIPT_BOOKMARK_APPLESCRIPT_UTILS_UNITTEST_H_
 
-#import <objc/objc-runtime.h>
 #import <Cocoa/Cocoa.h>
+#import <objc/objc-runtime.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/app_controller_mac.h"
 #import "chrome/browser/ui/cocoa/applescript/bookmark_folder_applescript.h"
 #include "chrome/browser/ui/cocoa/cocoa_profile_test.h"
@@ -42,9 +42,10 @@
   virtual ~BookmarkAppleScriptTest();
   virtual void SetUp() OVERRIDE;
  private:
-  scoped_nsobject<FakeAppDelegate> appDelegate_;
+  base::scoped_nsobject<FakeAppDelegate> appDelegate_;
+
  protected:
-  scoped_nsobject<BookmarkFolderAppleScript> bookmarkBar_;
+  base::scoped_nsobject<BookmarkFolderAppleScript> bookmarkBar_;
 };
 
 #endif  // CHROME_BROWSER_UI_COCOA_APPLESCRIPT_BOOKMARK_APPLESCRIPT_UTILS_UNITTEST_H_
diff --git a/chrome/browser/ui/cocoa/applescript/bookmark_applescript_utils_unittest.mm b/chrome/browser/ui/cocoa/applescript/bookmark_applescript_utils_unittest.mm
index 79c1233..fee143a 100644
--- a/chrome/browser/ui/cocoa/applescript/bookmark_applescript_utils_unittest.mm
+++ b/chrome/browser/ui/cocoa/applescript/bookmark_applescript_utils_unittest.mm
@@ -6,7 +6,7 @@
 
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
-#include "chrome/test/base/model_test_utils.h"
+#include "chrome/browser/bookmarks/bookmark_model_test_utils.h"
 
 @implementation FakeAppDelegate
 
@@ -66,7 +66,7 @@
   BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile());
   const BookmarkNode* root = model->bookmark_bar_node();
   const std::string modelString("a f1:[ b d c ] d f2:[ e f g ] h ");
-  model_test_utils::AddNodesFromModelString(model, root, modelString);
+  BookmarkModelTestUtils::AddNodesFromModelString(model, root, modelString);
   bookmarkBar_.reset([[BookmarkFolderAppleScript alloc]
       initWithBookmarkNode:model->bookmark_bar_node()]);
 }
diff --git a/chrome/browser/ui/cocoa/applescript/bookmark_folder_applescript.mm b/chrome/browser/ui/cocoa/applescript/bookmark_folder_applescript.mm
index cb978bf..a9ca820 100644
--- a/chrome/browser/ui/cocoa/applescript/bookmark_folder_applescript.mm
+++ b/chrome/browser/ui/cocoa/applescript/bookmark_folder_applescript.mm
@@ -4,7 +4,7 @@
 
 #import "chrome/browser/ui/cocoa/applescript/bookmark_folder_applescript.h"
 
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #import "base/strings/string16.h"
 #include "base/strings/sys_string_conversions.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
@@ -24,7 +24,7 @@
 
     if (!node->is_folder())
       continue;
-    scoped_nsobject<BookmarkFolderAppleScript> bookmarkFolder(
+    base::scoped_nsobject<BookmarkFolderAppleScript> bookmarkFolder(
         [[BookmarkFolderAppleScript alloc] initWithBookmarkNode:node]);
     [bookmarkFolder setContainer:self
                         property:AppleScript::kBookmarkFoldersProperty];
@@ -95,7 +95,7 @@
 
     if (!node->is_url())
       continue;
-    scoped_nsobject<BookmarkItemAppleScript> bookmarkItem(
+    base::scoped_nsobject<BookmarkItemAppleScript> bookmarkItem(
         [[BookmarkItemAppleScript alloc] initWithBookmarkNode:node]);
     [bookmarkItem setContainer:self
                       property:AppleScript::kBookmarkItemsProperty];
diff --git a/chrome/browser/ui/cocoa/applescript/bookmark_folder_applescript_unittest.mm b/chrome/browser/ui/cocoa/applescript/bookmark_folder_applescript_unittest.mm
index 0bbd0b4..04bac0e 100644
--- a/chrome/browser/ui/cocoa/applescript/bookmark_folder_applescript_unittest.mm
+++ b/chrome/browser/ui/cocoa/applescript/bookmark_folder_applescript_unittest.mm
@@ -4,7 +4,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/strings/sys_string_conversions.h"
 #import "chrome/browser/ui/cocoa/applescript/bookmark_applescript_utils_unittest.h"
 #import "chrome/browser/ui/cocoa/applescript/bookmark_folder_applescript.h"
@@ -45,9 +45,9 @@
   // Emulate what applescript would do when inserting a new bookmark folder.
   // Emulates a script like |set var to make new bookmark folder with
   // properties {title:"foo"}|.
-  scoped_nsobject<BookmarkFolderAppleScript> bookmarkFolder(
+  base::scoped_nsobject<BookmarkFolderAppleScript> bookmarkFolder(
       [[BookmarkFolderAppleScript alloc] init]);
-  scoped_nsobject<NSNumber> var([[bookmarkFolder.get() uniqueID] copy]);
+  base::scoped_nsobject<NSNumber> var([[bookmarkFolder.get() uniqueID] copy]);
   [bookmarkFolder.get() setTitle:@"foo"];
   [bookmarkBar_.get() insertInBookmarkFolders:bookmarkFolder.get()];
 
@@ -66,9 +66,9 @@
   // Emulate what applescript would do when inserting a new bookmark folder.
   // Emulates a script like |set var to make new bookmark folder with
   // properties {title:"foo"} at after bookmark folder 1|.
-  scoped_nsobject<BookmarkFolderAppleScript> bookmarkFolder(
+  base::scoped_nsobject<BookmarkFolderAppleScript> bookmarkFolder(
       [[BookmarkFolderAppleScript alloc] init]);
-  scoped_nsobject<NSNumber> var([[bookmarkFolder.get() uniqueID] copy]);
+  base::scoped_nsobject<NSNumber> var([[bookmarkFolder.get() uniqueID] copy]);
   [bookmarkFolder.get() setTitle:@"foo"];
   [bookmarkBar_.get() insertInBookmarkFolders:bookmarkFolder.get() atIndex:1];
 
@@ -119,9 +119,9 @@
   // Emulate what applescript would do when inserting a new bookmark folder.
   // Emulates a script like |set var to make new bookmark item with
   // properties {title:"Google", URL:"http://google.com"}|.
-  scoped_nsobject<BookmarkItemAppleScript> bookmarkItem(
+  base::scoped_nsobject<BookmarkItemAppleScript> bookmarkItem(
       [[BookmarkItemAppleScript alloc] init]);
-  scoped_nsobject<NSNumber> var([[bookmarkItem.get() uniqueID] copy]);
+  base::scoped_nsobject<NSNumber> var([[bookmarkItem.get() uniqueID] copy]);
   [bookmarkItem.get() setTitle:@"Google"];
   [bookmarkItem.get() setURL:@"http://google.com"];
   [bookmarkBar_.get() insertInBookmarkItems:bookmarkItem.get()];
@@ -137,7 +137,7 @@
   EXPECT_NSEQ(var.get(), [bi uniqueID]);
 
   // Test to see no bookmark item is created when no/invlid URL is entered.
-  scoped_nsobject<FakeScriptCommand> fakeScriptCommand(
+  base::scoped_nsobject<FakeScriptCommand> fakeScriptCommand(
       [[FakeScriptCommand alloc] init]);
   bookmarkItem.reset([[BookmarkItemAppleScript alloc] init]);
   [bookmarkBar_.get() insertInBookmarkItems:bookmarkItem.get()];
@@ -151,9 +151,9 @@
   // Emulates a script like |set var to make new bookmark item with
   // properties {title:"XKCD", URL:"http://xkcd.org}
   // at after bookmark item 1|.
-  scoped_nsobject<BookmarkItemAppleScript> bookmarkItem(
+  base::scoped_nsobject<BookmarkItemAppleScript> bookmarkItem(
       [[BookmarkItemAppleScript alloc] init]);
-  scoped_nsobject<NSNumber> var([[bookmarkItem.get() uniqueID] copy]);
+  base::scoped_nsobject<NSNumber> var([[bookmarkItem.get() uniqueID] copy]);
   [bookmarkItem.get() setTitle:@"XKCD"];
   [bookmarkItem.get() setURL:@"http://xkcd.org"];
 
@@ -171,7 +171,7 @@
   EXPECT_NSEQ(var.get(), [bi uniqueID]);
 
   // Test to see no bookmark item is created when no/invlid URL is entered.
-  scoped_nsobject<FakeScriptCommand> fakeScriptCommand(
+  base::scoped_nsobject<FakeScriptCommand> fakeScriptCommand(
       [[FakeScriptCommand alloc] init]);
   bookmarkItem.reset([[BookmarkItemAppleScript alloc] init]);
   [bookmarkBar_.get() insertInBookmarkItems:bookmarkItem.get() atIndex:1];
diff --git a/chrome/browser/ui/cocoa/applescript/bookmark_item_applescript_unittest.mm b/chrome/browser/ui/cocoa/applescript/bookmark_item_applescript_unittest.mm
index 44a309f..8e581f2 100644
--- a/chrome/browser/ui/cocoa/applescript/bookmark_item_applescript_unittest.mm
+++ b/chrome/browser/ui/cocoa/applescript/bookmark_item_applescript_unittest.mm
@@ -4,7 +4,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/strings/sys_string_conversions.h"
 #import "chrome/browser/ui/cocoa/applescript/bookmark_applescript_utils_unittest.h"
 #import "chrome/browser/ui/cocoa/applescript/bookmark_item_applescript.h"
@@ -35,7 +35,7 @@
             GURL(base::SysNSStringToUTF8([item1 URL])));
 
   // If scripter enters invalid URL.
-  scoped_nsobject<FakeScriptCommand> fakeScriptCommand(
+  base::scoped_nsobject<FakeScriptCommand> fakeScriptCommand(
       [[FakeScriptCommand alloc] init]);
   [item1 setURL:@"invalid-url.org"];
   EXPECT_EQ((int)AppleScript::errInvalidURL,
diff --git a/chrome/browser/ui/cocoa/applescript/bookmark_node_applescript.mm b/chrome/browser/ui/cocoa/applescript/bookmark_node_applescript.mm
index 49fcc06..5255cd6 100644
--- a/chrome/browser/ui/cocoa/applescript/bookmark_node_applescript.mm
+++ b/chrome/browser/ui/cocoa/applescript/bookmark_node_applescript.mm
@@ -5,7 +5,7 @@
 #import "chrome/browser/ui/cocoa/applescript/bookmark_node_applescript.h"
 
 #include "base/logging.h"
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #include "base/strings/sys_string_conversions.h"
 #import "chrome/browser/app_controller_mac.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
@@ -31,7 +31,7 @@
       return nil;
     }
 
-    scoped_nsobject<NSNumber> numID(
+    base::scoped_nsobject<NSNumber> numID(
         [[NSNumber alloc] initWithLongLong:model->next_node_id()]);
     [self setUniqueID:numID];
     [self setTempTitle:@""];
@@ -58,7 +58,7 @@
     // and this particular bookmark item/folder is never returned.
     bookmarkNode_ = aBookmarkNode;
 
-    scoped_nsobject<NSNumber>  numID(
+    base::scoped_nsobject<NSNumber> numID(
         [[NSNumber alloc] initWithLongLong:aBookmarkNode->id()]);
     [self setUniqueID:numID];
   }
@@ -73,7 +73,7 @@
   // and this particular bookmark item/folder is never returned.
   bookmarkNode_ = aBookmarkNode;
 
-  scoped_nsobject<NSNumber> numID(
+  base::scoped_nsobject<NSNumber> numID(
       [[NSNumber alloc] initWithLongLong:aBookmarkNode->id()]);
   [self setUniqueID:numID];
 
diff --git a/chrome/browser/ui/cocoa/applescript/browsercrapplication+applescript.mm b/chrome/browser/ui/cocoa/applescript/browsercrapplication+applescript.mm
index d6e3326..6cdd204 100644
--- a/chrome/browser/ui/cocoa/applescript/browsercrapplication+applescript.mm
+++ b/chrome/browser/ui/cocoa/applescript/browsercrapplication+applescript.mm
@@ -5,7 +5,7 @@
 #import "chrome/browser/ui/cocoa/applescript/browsercrapplication+applescript.h"
 
 #include "base/logging.h"
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #import "chrome/browser/app_controller_mac.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
@@ -30,7 +30,7 @@
     if ((*browserIterator)->IsAttemptingToCloseBrowser())
       continue;
 
-    scoped_nsobject<WindowAppleScript> window(
+    base::scoped_nsobject<WindowAppleScript> window(
         [[WindowAppleScript alloc] initWithBrowser:*browserIterator]);
     [window setContainer:NSApp
                 property:AppleScript::kWindowsProperty];
diff --git a/chrome/browser/ui/cocoa/applescript/browsercrapplication+applescript_test.mm b/chrome/browser/ui/cocoa/applescript/browsercrapplication+applescript_test.mm
index 0ac3eaa..12bdcb9 100644
--- a/chrome/browser/ui/cocoa/applescript/browsercrapplication+applescript_test.mm
+++ b/chrome/browser/ui/cocoa/applescript/browsercrapplication+applescript_test.mm
@@ -4,6 +4,7 @@
 
 #import <Cocoa/Cocoa.h>
 
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
@@ -47,8 +48,9 @@
   // Emulate what applescript would do when creating a new window.
   // Emulate a script like |set var to make new window with properties
   // {visible:false}|.
-  scoped_nsobject<WindowAppleScript> aWindow([[WindowAppleScript alloc] init]);
-  scoped_nsobject<NSNumber> var([[aWindow.get() uniqueID] copy]);
+  base::scoped_nsobject<WindowAppleScript> aWindow(
+      [[WindowAppleScript alloc] init]);
+  base::scoped_nsobject<NSNumber> var([[aWindow.get() uniqueID] copy]);
   [aWindow.get() setValue:[NSNumber numberWithBool:YES] forKey:@"isVisible"];
 
   [NSApp insertInAppleScriptWindows:aWindow.get()];
@@ -66,7 +68,7 @@
 // Inserting and deleting windows.
 IN_PROC_BROWSER_TEST_F(BrowserCrApplicationAppleScriptTest,
                        InsertAndDeleteWindows) {
-  scoped_nsobject<WindowAppleScript> aWindow;
+  base::scoped_nsobject<WindowAppleScript> aWindow;
   int count;
   // Create a bunch of windows.
   for (int i = 0; i < 5; ++i) {
diff --git a/chrome/browser/ui/cocoa/applescript/tab_applescript.mm b/chrome/browser/ui/cocoa/applescript/tab_applescript.mm
index 7fc426f..e2a3539 100644
--- a/chrome/browser/ui/cocoa/applescript/tab_applescript.mm
+++ b/chrome/browser/ui/cocoa/applescript/tab_applescript.mm
@@ -7,7 +7,7 @@
 #include "base/bind.h"
 #include "base/files/file_path.h"
 #include "base/logging.h"
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #include "base/strings/sys_string_conversions.h"
 #include "chrome/browser/printing/print_view_manager.h"
 #include "chrome/browser/sessions/session_id.h"
@@ -60,7 +60,7 @@
     SessionID session;
     SessionID::id_type futureSessionIDOfTab = session.id() + 1;
     // Holds the SessionID that the new tab is going to get.
-    scoped_nsobject<NSNumber> numID(
+    base::scoped_nsobject<NSNumber> numID(
         [[NSNumber alloc] initWithInt:futureSessionIDOfTab]);
     [self setUniqueID:numID];
   }
@@ -85,7 +85,7 @@
     webContents_ = webContents;
     SessionTabHelper* session_tab_helper =
         SessionTabHelper::FromWebContents(webContents);
-    scoped_nsobject<NSNumber> numID(
+    base::scoped_nsobject<NSNumber> numID(
         [[NSNumber alloc] initWithInt:session_tab_helper->session_id().id()]);
     [self setUniqueID:numID];
   }
@@ -100,7 +100,7 @@
   webContents_ = webContents;
   SessionTabHelper* session_tab_helper =
       SessionTabHelper::FromWebContents(webContents);
-  scoped_nsobject<NSNumber> numID(
+  base::scoped_nsobject<NSNumber> numID(
       [[NSNumber alloc] initWithInt:session_tab_helper->session_id().id()]);
   [self setUniqueID:numID];
 
diff --git a/chrome/browser/ui/cocoa/applescript/window_applescript.mm b/chrome/browser/ui/cocoa/applescript/window_applescript.mm
index fe6677f..ba93252 100644
--- a/chrome/browser/ui/cocoa/applescript/window_applescript.mm
+++ b/chrome/browser/ui/cocoa/applescript/window_applescript.mm
@@ -5,9 +5,9 @@
 #import "chrome/browser/ui/cocoa/applescript/window_applescript.h"
 
 #include "base/logging.h"
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #import "chrome/browser/app_controller_mac.h"
 #import "chrome/browser/chrome_browser_application_mac.h"
 #include "chrome/browser/profiles/profile.h"
@@ -75,7 +75,7 @@
         Browser::CreateParams(aProfile, chrome::HOST_DESKTOP_TYPE_NATIVE));
     chrome::NewTab(browser_);
     browser_->window()->Show();
-    scoped_nsobject<NSNumber> numID(
+    base::scoped_nsobject<NSNumber> numID(
         [[NSNumber alloc] initWithInt:browser_->session_id().id()]);
     [self setUniqueID:numID];
   }
@@ -93,7 +93,7 @@
     // the applescript runtime calls appleScriptWindows in
     // BrowserCrApplication and this particular window is never returned.
     browser_ = aBrowser;
-    scoped_nsobject<NSNumber> numID(
+    base::scoped_nsobject<NSNumber> numID(
         [[NSNumber alloc] initWithInt:browser_->session_id().id()]);
     [self setUniqueID:numID];
   }
@@ -159,7 +159,7 @@
       continue;
     }
 
-    scoped_nsobject<TabAppleScript> tab(
+    base::scoped_nsobject<TabAppleScript> tab(
         [[TabAppleScript alloc] initWithWebContents:webContents]);
     [tab setContainer:self
              property:AppleScript::kTabsProperty];
diff --git a/chrome/browser/ui/cocoa/applescript/window_applescript_test.mm b/chrome/browser/ui/cocoa/applescript/window_applescript_test.mm
index f13b03b..f627622 100644
--- a/chrome/browser/ui/cocoa/applescript/window_applescript_test.mm
+++ b/chrome/browser/ui/cocoa/applescript/window_applescript_test.mm
@@ -4,7 +4,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #include "base/strings/sys_string_conversions.h"
 #import "chrome/browser/app_controller_mac.h"
 #import "chrome/browser/chrome_browser_application_mac.h"
@@ -22,7 +22,7 @@
 
 // Create a window in default/normal mode.
 IN_PROC_BROWSER_TEST_F(WindowAppleScriptTest, DefaultCreation) {
-  scoped_nsobject<WindowAppleScript> aWindow(
+  base::scoped_nsobject<WindowAppleScript> aWindow(
       [[WindowAppleScript alloc] init]);
   EXPECT_TRUE(aWindow.get());
   NSString* mode = [aWindow.get() mode];
@@ -32,7 +32,7 @@
 
 // Create a window with a |NULL profile|.
 IN_PROC_BROWSER_TEST_F(WindowAppleScriptTest, CreationWithNoProfile) {
-  scoped_nsobject<WindowAppleScript> aWindow(
+  base::scoped_nsobject<WindowAppleScript> aWindow(
       [[WindowAppleScript alloc] initWithProfile:NULL]);
   EXPECT_FALSE(aWindow.get());
 }
@@ -40,7 +40,7 @@
 // Create a window with a particular profile.
 IN_PROC_BROWSER_TEST_F(WindowAppleScriptTest, CreationWithProfile) {
   Profile* lastProfile = [[NSApp delegate] lastProfile];
-  scoped_nsobject<WindowAppleScript> aWindow(
+  base::scoped_nsobject<WindowAppleScript> aWindow(
       [[WindowAppleScript alloc] initWithProfile:lastProfile]);
   EXPECT_TRUE(aWindow.get());
   EXPECT_TRUE([aWindow.get() uniqueID]);
@@ -48,14 +48,14 @@
 
 // Create a window with no |Browser*|.
 IN_PROC_BROWSER_TEST_F(WindowAppleScriptTest, CreationWithNoBrowser) {
-  scoped_nsobject<WindowAppleScript> aWindow(
+  base::scoped_nsobject<WindowAppleScript> aWindow(
       [[WindowAppleScript alloc] initWithBrowser:NULL]);
   EXPECT_FALSE(aWindow.get());
 }
 
 // Create a window with |Browser*| already present.
 IN_PROC_BROWSER_TEST_F(WindowAppleScriptTest, CreationWithBrowser) {
-  scoped_nsobject<WindowAppleScript> aWindow(
+  base::scoped_nsobject<WindowAppleScript> aWindow(
       [[WindowAppleScript alloc] initWithBrowser:browser()]);
   EXPECT_TRUE(aWindow.get());
   EXPECT_TRUE([aWindow.get() uniqueID]);
@@ -63,7 +63,7 @@
 
 // Tabs within the window.
 IN_PROC_BROWSER_TEST_F(WindowAppleScriptTest, Tabs) {
-  scoped_nsobject<WindowAppleScript> aWindow(
+  base::scoped_nsobject<WindowAppleScript> aWindow(
       [[WindowAppleScript alloc] initWithBrowser:browser()]);
   NSArray* tabs = [aWindow.get() tabs];
   EXPECT_EQ(1U, [tabs count]);
@@ -78,10 +78,10 @@
   // Emulate what applescript would do when creating a new tab.
   // Emulates a script like |set var to make new tab with
   // properties URL:"http://google.com"}|.
-  scoped_nsobject<TabAppleScript> aTab([[TabAppleScript alloc] init]);
-  scoped_nsobject<NSNumber> var([[aTab.get() uniqueID] copy]);
+  base::scoped_nsobject<TabAppleScript> aTab([[TabAppleScript alloc] init]);
+  base::scoped_nsobject<NSNumber> var([[aTab.get() uniqueID] copy]);
   [aTab.get() setURL:@"http://google.com"];
-  scoped_nsobject<WindowAppleScript> aWindow(
+  base::scoped_nsobject<WindowAppleScript> aWindow(
       [[WindowAppleScript alloc] initWithBrowser:browser()]);
   [aWindow.get() insertInTabs:aTab.get()];
 
@@ -100,10 +100,10 @@
   // Emulate what applescript would do when creating a new tab.
   // Emulates a script like |set var to make new tab with
   // properties URL:"http://google.com"} at before tab 1|.
-  scoped_nsobject<TabAppleScript> aTab([[TabAppleScript alloc] init]);
-  scoped_nsobject<NSNumber> var([[aTab.get() uniqueID] copy]);
+  base::scoped_nsobject<TabAppleScript> aTab([[TabAppleScript alloc] init]);
+  base::scoped_nsobject<NSNumber> var([[aTab.get() uniqueID] copy]);
   [aTab.get() setURL:@"http://google.com"];
-  scoped_nsobject<WindowAppleScript> aWindow(
+  base::scoped_nsobject<WindowAppleScript> aWindow(
       [[WindowAppleScript alloc] initWithBrowser:browser()]);
   [aWindow.get() insertInTabs:aTab.get() atIndex:0];
 
@@ -118,9 +118,9 @@
 
 // Inserting and deleting tabs.
 IN_PROC_BROWSER_TEST_F(WindowAppleScriptTest, InsertAndDeleteTabs) {
-  scoped_nsobject<WindowAppleScript> aWindow(
+  base::scoped_nsobject<WindowAppleScript> aWindow(
       [[WindowAppleScript alloc] initWithBrowser:browser()]);
-  scoped_nsobject<TabAppleScript> aTab;
+  base::scoped_nsobject<TabAppleScript> aTab;
   int count;
   for (int i = 0; i < 5; ++i) {
     for (int j = 0; j < 3; ++j) {
@@ -143,7 +143,7 @@
 
 // Getting and setting values from the NSWindow.
 IN_PROC_BROWSER_TEST_F(WindowAppleScriptTest, NSWindowTest) {
-  scoped_nsobject<WindowAppleScript> aWindow(
+  base::scoped_nsobject<WindowAppleScript> aWindow(
       [[WindowAppleScript alloc] initWithBrowser:browser()]);
   [aWindow.get() setValue:[NSNumber numberWithBool:YES]
                    forKey:@"isMiniaturized"];
@@ -155,9 +155,9 @@
 
 // Getting and setting the active tab.
 IN_PROC_BROWSER_TEST_F(WindowAppleScriptTest, ActiveTab) {
-  scoped_nsobject<WindowAppleScript> aWindow(
+  base::scoped_nsobject<WindowAppleScript> aWindow(
       [[WindowAppleScript alloc] initWithBrowser:browser()]);
-  scoped_nsobject<TabAppleScript> aTab([[TabAppleScript alloc] init]);
+  base::scoped_nsobject<TabAppleScript> aTab([[TabAppleScript alloc] init]);
   [aWindow.get() insertInTabs:aTab.get()];
   [aWindow.get() setActiveTabIndex:[NSNumber numberWithInt:2]];
   EXPECT_EQ(2, [[aWindow.get() activeTabIndex] intValue]);
@@ -168,9 +168,9 @@
 
 // Order of windows.
 IN_PROC_BROWSER_TEST_F(WindowAppleScriptTest, WindowOrder) {
-  scoped_nsobject<WindowAppleScript> window2(
+  base::scoped_nsobject<WindowAppleScript> window2(
       [[WindowAppleScript alloc] initWithBrowser:browser()]);
-  scoped_nsobject<WindowAppleScript> window1(
+  base::scoped_nsobject<WindowAppleScript> window1(
       [[WindowAppleScript alloc] init]);
   EXPECT_EQ([window1.get() windowComparator:window2.get()], NSOrderedAscending);
   EXPECT_EQ([window2.get() windowComparator:window1.get()],
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_account_chooser.h b/chrome/browser/ui/cocoa/autofill/autofill_account_chooser.h
index c1b1116..67d2bff 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_account_chooser.h
+++ b/chrome/browser/ui/cocoa/autofill/autofill_account_chooser.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 
 namespace autofill {
   class AutofillDialogController;
@@ -17,9 +17,9 @@
 
 @interface AutofillAccountChooser : NSView {
  @private
-  scoped_nsobject<NSButton> link_;
-  scoped_nsobject<MenuButton> popup_;
-  scoped_nsobject<NSImageView> icon_;
+  base::scoped_nsobject<NSButton> link_;
+  base::scoped_nsobject<MenuButton> popup_;
+  base::scoped_nsobject<NSImageView> icon_;
   autofill::AutofillDialogController* controller_;  // weak.
 }
 
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_account_chooser.mm b/chrome/browser/ui/cocoa/autofill/autofill_account_chooser.mm
index c3904ae..35111d2 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_account_chooser.mm
+++ b/chrome/browser/ui/cocoa/autofill/autofill_account_chooser.mm
@@ -26,10 +26,10 @@
     return;
   }
 
-  scoped_nsobject<NSMenuItem> item([[NSMenuItem alloc]
-    initWithTitle:title
-           action:selector
-    keyEquivalent:@""]);
+  base::scoped_nsobject<NSMenuItem> item(
+      [[NSMenuItem alloc] initWithTitle:title
+                                 action:selector
+                          keyEquivalent:@""]);
   [item setTag:tag];
   [menu addItem:item];
   [item setTarget:target];
@@ -63,7 +63,7 @@
         gfx::SkColorToCalibratedNSColor(chrome_style::GetLinkColor())];
 
     popup_.reset([[MenuButton alloc] initWithFrame:NSZeroRect]);
-    scoped_nsobject<DownArrowPopupMenuCell> popupCell(
+    base::scoped_nsobject<DownArrowPopupMenuCell> popupCell(
         [[DownArrowPopupMenuCell alloc] initTextCell:@""]);
     [popup_ setCell:popupCell];
 
@@ -75,7 +75,7 @@
     [popupCell setImage:popupImage
         forButtonState:image_button_cell::kDefaultState];
 
-    scoped_nsobject<NSMenu> menu([[NSMenu alloc] initWithTitle:@""]);
+    base::scoped_nsobject<NSMenu> menu([[NSMenu alloc] initWithTitle:@""]);
     [menu setAutoenablesItems:NO];
     [popup_ setAttachedMenu:menu];
 
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_account_chooser_unittest.mm b/chrome/browser/ui/cocoa/autofill/autofill_account_chooser_unittest.mm
index e6ce376..d4717cb 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_account_chooser_unittest.mm
+++ b/chrome/browser/ui/cocoa/autofill/autofill_account_chooser_unittest.mm
@@ -27,7 +27,7 @@
  }
 
  protected:
-  scoped_nsobject<AutofillAccountChooser> view_;
+  base::scoped_nsobject<AutofillAccountChooser> view_;
   testing::NiceMock<autofill::MockAutofillDialogController> controller_;
 
  private:
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_details_container.h b/chrome/browser/ui/cocoa/autofill/autofill_details_container.h
index 79c5804..aa99561 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_details_container.h
+++ b/chrome/browser/ui/cocoa/autofill/autofill_details_container.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/ui/autofill/autofill_dialog_types.h"
 #import "chrome/browser/ui/cocoa/autofill/autofill_layout.h"
 
@@ -20,7 +20,8 @@
 // UI controller for details for current payment instrument.
 @interface AutofillDetailsContainer : NSViewController<AutofillLayout> {
  @private
-  scoped_nsobject<NSMutableArray> details_;  // The individual detail sections.
+  base::scoped_nsobject<NSMutableArray> details_;   // The individual detail
+                                                    // sections.
   autofill::AutofillDialogController* controller_;  // Not owned.
 }
 
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_details_container.mm b/chrome/browser/ui/cocoa/autofill/autofill_details_container.mm
index 5a88597..0defb1f 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_details_container.mm
+++ b/chrome/browser/ui/cocoa/autofill/autofill_details_container.mm
@@ -19,7 +19,7 @@
 }
 
 - (void)addSection:(autofill::DialogSection)section {
-  scoped_nsobject<AutofillSectionContainer> sectionContainer(
+  base::scoped_nsobject<AutofillSectionContainer> sectionContainer(
       [[AutofillSectionContainer alloc] initWithController:controller_
                                                 forSection:section]);
   [details_ addObject:sectionContainer];
@@ -31,7 +31,7 @@
   [self addSection:autofill::SECTION_EMAIL];
   [self addSection:autofill::SECTION_CC];
   [self addSection:autofill::SECTION_BILLING];
-  // TODO(groby): Add SECTION_CC_BILLING once toggling is enabled.
+  [self addSection:autofill::SECTION_CC_BILLING];
   [self addSection:autofill::SECTION_SHIPPING];
 
   [self setView:[[NSView alloc] init]];
@@ -43,7 +43,6 @@
 
 - (NSSize)preferredSize {
   NSSize size = NSMakeSize(0, 0);
-
   for (AutofillSectionContainer* container in details_.get()) {
     NSSize containerSize = [container preferredSize];
     size.height += containerSize.height;
@@ -56,9 +55,11 @@
   NSRect rect = NSZeroRect;
   for (AutofillSectionContainer* container in
       [details_ reverseObjectEnumerator]) {
-    [container performLayout];
-    [[container view] setFrameOrigin:NSMakePoint(0, NSMaxY(rect))];
-    rect = NSUnionRect(rect, [[container view] frame]);
+    if (![[container view] isHidden]) {
+      [container performLayout];
+      [[container view] setFrameOrigin:NSMakePoint(0, NSMaxY(rect))];
+      rect = NSUnionRect(rect, [[container view] frame]);
+    }
   }
 
   [[self view] setFrameSize:[self preferredSize]];
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_details_container_unittest.mm b/chrome/browser/ui/cocoa/autofill/autofill_details_container_unittest.mm
index 4841710..7cbc178 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_details_container_unittest.mm
+++ b/chrome/browser/ui/cocoa/autofill/autofill_details_container_unittest.mm
@@ -4,7 +4,7 @@
 
 #import "chrome/browser/ui/cocoa/autofill/autofill_details_container.h"
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/ui/autofill/mock_autofill_dialog_controller.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
@@ -21,7 +21,7 @@
   }
 
  protected:
-  scoped_nsobject<AutofillDetailsContainer> container_;
+  base::scoped_nsobject<AutofillDetailsContainer> container_;
   testing::NiceMock<autofill::MockAutofillDialogController> controller_;
 };
 
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_dialog_cocoa.h b/chrome/browser/ui/cocoa/autofill/autofill_dialog_cocoa.h
index d86d6ca..73fc8bf 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_dialog_cocoa.h
+++ b/chrome/browser/ui/cocoa/autofill/autofill_dialog_cocoa.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_UI_COCOA_AUTOFILL_AUTOFILL_DIALOG_COCOA_H_
 #define CHROME_BROWSER_UI_COCOA_AUTOFILL_AUTOFILL_DIALOG_COCOA_H_
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #include "chrome/browser/ui/autofill/autofill_dialog_types.h"
 #include "chrome/browser/ui/autofill/autofill_dialog_view.h"
@@ -41,6 +41,7 @@
   virtual void UpdateDetailArea() OVERRIDE;
   virtual void UpdateForErrors() OVERRIDE;
   virtual void UpdateNotificationArea() OVERRIDE;
+  virtual void UpdateAutocheckoutStepsArea() OVERRIDE;
   virtual void UpdateSection(DialogSection section) OVERRIDE;
   virtual void FillSection(DialogSection section,
                            const DetailInput& originating_input) OVERRIDE;
@@ -65,7 +66,7 @@
  private:
 
   scoped_ptr<ConstrainedWindowMac> constrained_window_;
-  scoped_nsobject<AutofillDialogWindowController> sheet_controller_;
+  base::scoped_nsobject<AutofillDialogWindowController> sheet_controller_;
 
   // The controller |this| queries for logic and state.
   AutofillDialogController* controller_;
@@ -79,9 +80,9 @@
   content::WebContents* webContents_;  // weak.
   autofill::AutofillDialogCocoa* autofillDialog_;  // weak.
 
-  scoped_nsobject<AutofillMainContainer> mainContainer_;
-  scoped_nsobject<AutofillSignInContainer> signInContainer_;
-  scoped_nsobject<AutofillAccountChooser> accountChooser_;
+  base::scoped_nsobject<AutofillMainContainer> mainContainer_;
+  base::scoped_nsobject<AutofillSignInContainer> signInContainer_;
+  base::scoped_nsobject<AutofillAccountChooser> accountChooser_;
 }
 
 // Designated initializer. The WebContents cannot be NULL.
@@ -100,6 +101,7 @@
 
 // Forwarding AutofillDialogView calls.
 - (void)updateAccountChooser;
+- (void)updateNotificationArea;
 - (void)updateSection:(autofill::DialogSection)section;
 - (void)getInputs:(autofill::DetailOutputMap*)outputs
        forSection:(autofill::DialogSection)section;
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_dialog_cocoa.mm b/chrome/browser/ui/cocoa/autofill/autofill_dialog_cocoa.mm
index 30ecf35..7d8e3e2 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_dialog_cocoa.mm
+++ b/chrome/browser/ui/cocoa/autofill/autofill_dialog_cocoa.mm
@@ -5,10 +5,9 @@
 #include "chrome/browser/ui/cocoa/autofill/autofill_dialog_cocoa.h"
 
 #include "base/mac/bundle_locations.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/ui/autofill/autofill_dialog_controller.h"
 #include "chrome/browser/ui/chrome_style.h"
-#import "chrome/browser/ui/cocoa/constrained_window/constrained_window_button.h"
 #include "chrome/browser/ui/chrome_style.h"
 #include "chrome/browser/ui/chrome_style.h"
 #import "chrome/browser/ui/cocoa/autofill/autofill_account_chooser.h"
@@ -16,6 +15,7 @@
 #import "chrome/browser/ui/cocoa/autofill/autofill_main_container.h"
 #import "chrome/browser/ui/cocoa/autofill/autofill_section_container.h"
 #import "chrome/browser/ui/cocoa/autofill/autofill_sign_in_container.h"
+#import "chrome/browser/ui/cocoa/constrained_window/constrained_window_button.h"
 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_sheet.h"
 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_window.h"
 #import "ui/base/cocoa/flipped_view.h"
@@ -49,7 +49,7 @@
   sheet_controller_.reset([[AutofillDialogWindowController alloc]
        initWithWebContents:controller_->web_contents()
             autofillDialog:this]);
-  scoped_nsobject<CustomConstrainedWindowSheet> sheet(
+  base::scoped_nsobject<CustomConstrainedWindowSheet> sheet(
       [[CustomConstrainedWindowSheet alloc]
           initWithCustomWindow:[sheet_controller_ window]]);
   constrained_window_.reset(
@@ -75,6 +75,10 @@
 }
 
 void AutofillDialogCocoa::UpdateNotificationArea() {
+  [sheet_controller_ updateNotificationArea];
+}
+
+void AutofillDialogCocoa::UpdateAutocheckoutStepsArea() {
 }
 
 void AutofillDialogCocoa::UpdateSection(DialogSection section) {
@@ -133,7 +137,7 @@
       autofillDialog:(autofill::AutofillDialogCocoa*)autofillDialog {
   DCHECK(webContents);
 
-  scoped_nsobject<ConstrainedWindowCustomWindow> window(
+  base::scoped_nsobject<ConstrainedWindowCustomWindow> window(
       [[ConstrainedWindowCustomWindow alloc]
           initWithContentRect:ui::kWindowSizeDeterminedLater]);
 
@@ -166,13 +170,14 @@
     // This needs a flipped content view because otherwise the size
     // animation looks odd. However, replacing the contentView for constrained
     // windows does not work - it does custom rendering.
-    scoped_nsobject<NSView> flippedContentView(
+    base::scoped_nsobject<NSView> flippedContentView(
         [[FlippedView alloc] initWithFrame:NSZeroRect]);
     [flippedContentView setSubviews:
         @[accountChooser_, [mainContainer_ view], [signInContainer_ view]]];
     [flippedContentView setAutoresizingMask:
         (NSViewWidthSizable | NSViewHeightSizable)];
     [[[self window] contentView] addSubview:flippedContentView];
+    [mainContainer_ setAnchorView:[[accountChooser_ subviews] objectAtIndex:1]];
 
     NSRect contentRect = clientRect;
     contentRect.origin = NSMakePoint(0, 0);
@@ -206,10 +211,6 @@
 }
 
 - (void)performLayout {
-  // Don't animate when we first show the window.
-  BOOL shouldAnimate =
-      !NSEqualRects(ui::kWindowSizeDeterminedLater, [[self window] frame]);
-
   NSRect contentRect = NSZeroRect;
   contentRect.size = [self preferredSize];
   NSRect clientRect = NSInsetRect(
@@ -231,7 +232,7 @@
   }
 
   NSRect frameRect = [[self window] frameRectForContentRect:contentRect];
-  [[self window] setFrame:frameRect display:YES animate:shouldAnimate];
+  [[self window] setFrame:frameRect display:YES];
 }
 
 - (IBAction)accept:(id)sender {
@@ -247,6 +248,11 @@
 
 - (void)updateAccountChooser {
   [accountChooser_ update];
+  [mainContainer_ updateLegalDocuments];
+}
+
+- (void)updateNotificationArea {
+  [mainContainer_ updateNotificationArea];
 }
 
 - (void)updateSection:(autofill::DialogSection)section {
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_dialog_cocoa_browsertest.mm b/chrome/browser/ui/cocoa/autofill/autofill_dialog_cocoa_browsertest.mm
index f2394f1..c8c5429 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_dialog_cocoa_browsertest.mm
+++ b/chrome/browser/ui/cocoa/autofill/autofill_dialog_cocoa_browsertest.mm
@@ -10,7 +10,7 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/test/base/in_process_browser_test.h"
-#include "components/autofill/browser/autofill_common_test.h"
+#include "components/autofill/core/browser/autofill_common_test.h"
 #include "components/autofill/core/common/form_data.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_view.h"
@@ -44,7 +44,7 @@
   virtual ~TestAutofillDialogController() {}
 
   virtual void ViewClosed() OVERRIDE {
-    DCHECK(runner_);
+    DCHECK(runner_.get());
     runner_->Quit();
     AutofillDialogControllerImpl::ViewClosed();
   }
@@ -92,7 +92,7 @@
   TestAutofillDialogController* controller() { return controller_; }
 
   void RunMessageLoop() {
-    DCHECK(runner_);
+    DCHECK(runner_.get());
     runner_->Run();
   }
 
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_dialog_constants.h b/chrome/browser/ui/cocoa/autofill/autofill_dialog_constants.h
index d4e57ab..b5d1ba3 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_dialog_constants.h
+++ b/chrome/browser/ui/cocoa/autofill/autofill_dialog_constants.h
@@ -11,9 +11,20 @@
 // Horizontal padding between text and other elements (in pixels).
 const CGFloat kAroundTextPadding = 4;
 
+// Sizing of notification arrow.
+const int kArrowHeight = 7;
+const int kArrowWidth = 2 * kArrowHeight;
+
 // Spacing between buttons.
 const CGFloat kButtonGap = 6;
 
+// The space between the edges of a notification bar and the text within (in
+// pixels).
+const int kNotificationPadding = 14;
+
+// Vertical spacing between legal text and details section.
+const int kVerticalSpacing = 8;
+
 }  // namespace
 
 #endif  // CHROME_BROWSER_UI_COCOA_AUTOFILL_AUTOFILL_DIALOG_CONSTANTS__H_
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_input_field.h b/chrome/browser/ui/cocoa/autofill/autofill_input_field.h
new file mode 100644
index 0000000..ea1e43d
--- /dev/null
+++ b/chrome/browser/ui/cocoa/autofill/autofill_input_field.h
@@ -0,0 +1,17 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_COCOA_AUTOFILL_AUTOFILL_INPUT_FIELD_H_
+#define CHROME_BROWSER_UI_COCOA_AUTOFILL_AUTOFILL_INPUT_FIELD_H_
+
+// Protocol to allow access to any given input field in an Autofill dialog, no
+// matter what the underlying control is.
+@protocol AutofillInputField
+
+@property(nonatomic, assign) BOOL invalid;
+@property(nonatomic, copy) NSString* fieldValue;
+
+@end
+
+#endif  // CHROME_BROWSER_UI_COCOA_AUTOFILL_AUTOFILL_INPUT_FIELD_H_
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_main_container.h b/chrome/browser/ui/cocoa/autofill/autofill_main_container.h
index b05a713..7f6a92e 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_main_container.h
+++ b/chrome/browser/ui/cocoa/autofill/autofill_main_container.h
@@ -7,14 +7,16 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/ui/autofill/autofill_dialog_types.h"
 #import "chrome/browser/ui/cocoa/autofill/autofill_layout.h"
 
 @class AutofillDetailsContainer;
 @class AutofillDialogWindowController;
+@class AutofillNotificationContainer;
 @class AutofillSectionContainer;
 @class GTMWidthBasedTweaker;
+@class HyperlinkTextView;
 
 namespace autofill {
   class AutofillDialogController;
@@ -23,12 +25,23 @@
 // NSViewController for the main portion of the autofill dialog. Contains
 // account chooser, details for current payment instruments, OK/Cancel.
 // Might dynamically add and remove other elements.
-@interface AutofillMainContainer : NSViewController<AutofillLayout> {
+@interface AutofillMainContainer : NSViewController<AutofillLayout,
+                                                    NSTextViewDelegate> {
  @private
-  scoped_nsobject<GTMWidthBasedTweaker> buttonContainer_;
-  scoped_nsobject<AutofillDetailsContainer> detailsContainer_;
+  base::scoped_nsobject<GTMWidthBasedTweaker> buttonContainer_;
+  base::scoped_nsobject<AutofillDetailsContainer> detailsContainer_;
+  base::scoped_nsobject<HyperlinkTextView> legalDocumentsView_;
+  base::scoped_nsobject<AutofillNotificationContainer> notificationContainer_;
   AutofillDialogWindowController* target_;
-  autofill::AutofillDialogController* controller_;  // Not owned.
+
+  // Weak. Owns the dialog.
+  autofill::AutofillDialogController* controller_;
+
+  // Preferred size for legal documents.
+  NSSize legalDocumentsSize_;
+
+  // Dirty marker for preferred size.
+  BOOL legalDocumentsSizeDirty_;
 }
 
 @property(assign, nonatomic) AutofillDialogWindowController* target;
@@ -36,12 +49,21 @@
 // Designated initializer.
 - (id)initWithController:(autofill::AutofillDialogController*)controller;
 
+// Sets the anchor point for the notificationView_.
+- (void)setAnchorView:(NSView*)anchorView;
+
 // Returns the view controller responsible for |section|.
 - (AutofillSectionContainer*)sectionForId:(autofill::DialogSection)section;
 
 // Called when the controller-maintained suggestions model has changed.
 - (void)modelChanged;
 
+// Called when the legal documents text might need to be refreshed.
+- (void)updateLegalDocuments;
+
+// Called when there are changes to the notification area.
+- (void)updateNotificationArea;
+
 @end
 
 #endif  // CHROME_BROWSER_UI_COCOA_AUTOFILL_AUTOFILL_MAIN_CONTAINER_H_
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_main_container.mm b/chrome/browser/ui/cocoa/autofill/autofill_main_container.mm
index 80b050c..9d9449c 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_main_container.mm
+++ b/chrome/browser/ui/cocoa/autofill/autofill_main_container.mm
@@ -7,20 +7,28 @@
 #include <algorithm>
 #include <cmath>
 
+#include "base/mac/foundation_util.h"
+#include "base/strings/sys_string_conversions.h"
+#include "chrome/browser/ui/autofill/autofill_dialog_controller.h"
 #include "chrome/browser/ui/cocoa/autofill/autofill_dialog_constants.h"
 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_button.h"
 #import "chrome/browser/ui/cocoa/autofill/autofill_details_container.h"
+#import "chrome/browser/ui/cocoa/autofill/autofill_notification_container.h"
+#import "chrome/browser/ui/cocoa/hyperlink_text_view.h"
 #import "chrome/browser/ui/cocoa/key_equivalent_constants.h"
 #include "grit/generated_resources.h"
 #import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
 #include "ui/base/cocoa/window_size_constants.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/range/range.h"
 
 @interface AutofillMainContainer (Private)
 - (void)buildWindowButtonsForFrame:(NSRect)frame;
 - (void)layoutButtons;
+- (NSSize)preferredLegalDocumentSizeForWidth:(CGFloat)width;
 @end
 
+
 @implementation AutofillMainContainer
 
 @synthesize target = target_;
@@ -35,7 +43,7 @@
 - (void)loadView {
   [self buildWindowButtonsForFrame:NSZeroRect];
 
-  scoped_nsobject<NSView> view([[NSView alloc] initWithFrame:NSZeroRect]);
+  base::scoped_nsobject<NSView> view([[NSView alloc] initWithFrame:NSZeroRect]);
   [view setAutoresizesSubviews:YES];
   [view setSubviews:@[buttonContainer_]];
   [self setView:view];
@@ -50,22 +58,81 @@
   frameSize.height += NSHeight([buttonContainer_ frame]);
   [[self view] setFrameSize:frameSize];
   [[self view] addSubview:[detailsContainer_ view]];
+
+  legalDocumentsView_.reset(
+      [[HyperlinkTextView alloc] initWithFrame:NSZeroRect]);
+  [legalDocumentsView_ setEditable:NO];
+  [legalDocumentsView_ setBackgroundColor:
+      [NSColor colorWithCalibratedRed:0.96
+                                green:0.96
+                                 blue:0.96
+                                alpha:1.0]];
+  [legalDocumentsView_ setDrawsBackground:YES];
+  [legalDocumentsView_ setHidden:YES];
+  [legalDocumentsView_ setDelegate:self];
+  legalDocumentsSizeDirty_ = YES;
+  [[self view] addSubview:legalDocumentsView_];
+
+  notificationContainer_.reset(
+      [[AutofillNotificationContainer alloc] initWithController:controller_]);
+  [[self view] addSubview:[notificationContainer_ view]];
+}
+
+// Called when embedded links are clicked.
+- (BOOL)textView:(NSTextView*)textView
+    clickedOnLink:(id)link
+          atIndex:(NSUInteger)charIndex {
+  int index = [base::mac::ObjCCastStrict<NSNumber>(link) intValue];
+  controller_->LegalDocumentLinkClicked(
+      controller_->LegalDocumentLinks()[index]);
+  return YES;
 }
 
 - (NSSize)preferredSize {
-  // The buttons never change size, so rely on container.
+  // Overall width is determined by |detailsContainer_|.
   NSSize buttonSize = [buttonContainer_ frame].size;
   NSSize detailsSize = [detailsContainer_ preferredSize];
 
   NSSize size = NSMakeSize(std::max(buttonSize.width, detailsSize.width),
                            buttonSize.height + detailsSize.height);
 
+  if (![legalDocumentsView_ isHidden]) {
+    NSSize legalDocumentSize =
+        [self preferredLegalDocumentSizeForWidth:detailsSize.width];
+    size.height += legalDocumentSize.height + kVerticalSpacing;
+  }
+
+  NSSize notificationSize =
+      [notificationContainer_ preferredSizeForWidth:detailsSize.width];
+  size.height += notificationSize.height;
   return size;
 }
 
 - (void)performLayout {
-  // Assume that the frame for the container is set already.
+  NSSize preferredContainerSize = [self preferredSize];
+
+  CGFloat currentY = 0.0;
+  if (![legalDocumentsView_ isHidden]) {
+    [legalDocumentsView_ setFrameSize:
+        [self preferredLegalDocumentSizeForWidth:preferredContainerSize.width]];
+    currentY = NSMaxY([legalDocumentsView_ frame]) + kVerticalSpacing;
+  }
+
+  NSRect buttonFrame = [buttonContainer_ frame];
+  buttonFrame.origin.y = currentY;
+  [buttonContainer_ setFrameOrigin:buttonFrame.origin];
+
   [detailsContainer_ performLayout];
+  NSRect containerFrame = [[detailsContainer_ view] frame];
+  containerFrame.origin.y = NSMaxY(buttonFrame);
+  [[detailsContainer_ view] setFrameOrigin:containerFrame.origin];
+
+  NSRect notificationFrame;
+  notificationFrame.origin = NSMakePoint(0, NSMaxY(containerFrame));
+  notificationFrame.size = [notificationContainer_ preferredSizeForWidth:
+      preferredContainerSize.width];
+  [[notificationContainer_ view] setFrame:notificationFrame];
+  [notificationContainer_ performLayout];
 }
 
 - (void)buildWindowButtonsForFrame:(NSRect)frame {
@@ -77,7 +144,7 @@
   [buttonContainer_
       setAutoresizingMask:(NSViewMinXMargin | NSViewMaxYMargin)];
 
-  scoped_nsobject<NSButton> button(
+  base::scoped_nsobject<NSButton> button(
       [[ConstrainedWindowButton alloc] initWithFrame:NSZeroRect]);
   [button setTitle:l10n_util::GetNSStringWithFixup(IDS_CANCEL)];
   [button setKeyEquivalent:kKeyEquivalentEscape];
@@ -105,11 +172,37 @@
 }
 
 - (void)layoutButtons {
-  scoped_nsobject<GTMUILocalizerAndLayoutTweaker> layoutTweaker(
+  base::scoped_nsobject<GTMUILocalizerAndLayoutTweaker> layoutTweaker(
       [[GTMUILocalizerAndLayoutTweaker alloc] init]);
   [layoutTweaker tweakUI:buttonContainer_];
 }
 
+// Compute the preferred size for the legal documents text, given a width.
+- (NSSize)preferredLegalDocumentSizeForWidth:(CGFloat)width {
+  // Only recompute if necessary (On text or frame width change).
+  if (!legalDocumentsSizeDirty_ && abs(legalDocumentsSize_.width-width) < 1.0)
+    return legalDocumentsSize_;
+
+  // There's no direct API to compute desired sizes - use layouting instead.
+  // Layout in a rect with fixed width and "infinite" height.
+  NSRect currentFrame = [legalDocumentsView_ frame];
+  [legalDocumentsView_ setFrame:NSMakeRect(0, 0, width, CGFLOAT_MAX)];
+
+  // Now use the layout manager to compute layout.
+  NSLayoutManager* layoutManager = [legalDocumentsView_ layoutManager];
+  NSTextContainer* textContainer = [legalDocumentsView_ textContainer];
+  [layoutManager ensureLayoutForTextContainer:textContainer];
+  NSRect newFrame = [layoutManager usedRectForTextContainer:textContainer];
+
+  // And finally, restore old frame.
+  [legalDocumentsView_ setFrame:currentFrame];
+  newFrame.size.width = width;
+
+  legalDocumentsSizeDirty_ = NO;
+  legalDocumentsSize_ = newFrame.size;
+  return legalDocumentsSize_;
+}
+
 - (AutofillSectionContainer*)sectionForId:(autofill::DialogSection)section {
   return [detailsContainer_ sectionForId:section];
 }
@@ -118,4 +211,42 @@
   [detailsContainer_ modelChanged];
 }
 
+- (void)updateLegalDocuments {
+  NSString* text = base::SysUTF16ToNSString(controller_->LegalDocumentsText());
+
+  if ([text length]) {
+    NSFont* font = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]];
+    [legalDocumentsView_ setMessage:text
+                           withFont:font
+                       messageColor:[NSColor blackColor]];
+
+    const std::vector<ui::Range>& link_ranges =
+        controller_->LegalDocumentLinks();
+    for (size_t i = 0; i < link_ranges.size(); ++i) {
+      NSRange range = link_ranges[i].ToNSRange();
+      [legalDocumentsView_ addLinkRange:range
+                               withName:@(i)
+                              linkColor:[NSColor blueColor]];
+    }
+    legalDocumentsSizeDirty_ = YES;
+  }
+  [legalDocumentsView_ setHidden:[text length] == 0];
+
+  // Always request re-layout on state change.
+  id controller = [[[self view] window] windowController];
+  if ([controller respondsToSelector:@selector(requestRelayout)])
+    [controller performSelector:@selector(requestRelayout)];
+}
+
+- (void)updateNotificationArea {
+  [notificationContainer_ setNotifications:controller_->CurrentNotifications()];
+  id controller = [[[self view] window] windowController];
+  if ([controller respondsToSelector:@selector(requestRelayout)])
+    [controller performSelector:@selector(requestRelayout)];
+}
+
+- (void)setAnchorView:(NSView*)anchorView {
+  [notificationContainer_ setAnchorView:anchorView];
+}
+
 @end
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_main_container_unittest.mm b/chrome/browser/ui/cocoa/autofill/autofill_main_container_unittest.mm
index a52103d..5eeaf1d 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_main_container_unittest.mm
+++ b/chrome/browser/ui/cocoa/autofill/autofill_main_container_unittest.mm
@@ -4,9 +4,9 @@
 
 #import "chrome/browser/ui/cocoa/autofill/autofill_main_container.h"
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/ui/autofill/mock_autofill_dialog_controller.h"
-#import "chrome/browser/ui/cocoa/autofill/autofill_account_chooser.h"
+#import "chrome/browser/ui/cocoa/autofill/autofill_section_view.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
 #import "ui/base/test/ui_cocoa_test_helper.h"
@@ -23,7 +23,7 @@
   }
 
  protected:
-  scoped_nsobject<AutofillMainContainer> container_;
+  base::scoped_nsobject<AutofillMainContainer> container_;
   testing::NiceMock<autofill::MockAutofillDialogController> controller_;
 };
 
@@ -33,9 +33,12 @@
 
 TEST_F(AutofillMainContainerTest, SubViews) {
   bool hasButtons = false;
+  bool hasTextView = false;
+  bool hasDetailsContainer = false;
+  int hasNotificationContainer = false;
 
   // Should have account chooser, button strip, and details section.
-  EXPECT_EQ(2U, [[[container_ view] subviews] count]);
+  EXPECT_EQ(4U, [[[container_ view] subviews] count]);
   for (NSView* view in [[container_ view] subviews]) {
     NSArray* subviews = [view subviews];
     if ([subviews count] == 2) {
@@ -44,8 +47,21 @@
       EXPECT_TRUE(
           [[subviews objectAtIndex:1] isKindOfClass:[NSButton class]]);
       hasButtons = true;
+    } else if ([view isKindOfClass:[NSTextView class]]) {
+      hasTextView = true;
+    } else if ([subviews count] > 0 &&
+        [[subviews objectAtIndex:0] isKindOfClass:
+            [AutofillSectionView class]]) {
+      hasDetailsContainer = true;
+    } else {
+      // Assume by default this is the notification area view.
+      // There is no way to easily verify that with more detail.
+      hasNotificationContainer = true;
     }
   }
 
   EXPECT_TRUE(hasButtons);
-}
\ No newline at end of file
+  EXPECT_TRUE(hasTextView);
+  EXPECT_TRUE(hasDetailsContainer);
+  EXPECT_TRUE(hasNotificationContainer);
+}
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_notification_container.h b/chrome/browser/ui/cocoa/autofill/autofill_notification_container.h
new file mode 100644
index 0000000..7271f16
--- /dev/null
+++ b/chrome/browser/ui/cocoa/autofill/autofill_notification_container.h
@@ -0,0 +1,57 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_COCOA_AUTOFILL_AUTOFILL_NOTIFICATION_CONTAINER_H_
+#define CHROME_BROWSER_UI_COCOA_AUTOFILL_AUTOFILL_NOTIFICATION_CONTAINER_H_
+
+#import <Cocoa/Cocoa.h>
+
+#include <vector>
+
+#include "base/mac/scoped_nsobject.h"
+#include "base/memory/scoped_ptr.h"
+#import "chrome/browser/ui/cocoa/autofill/autofill_layout.h"
+
+@class AutofillArrowView;
+
+namespace autofill {
+  class DialogNotification;
+  typedef std::vector<DialogNotification> DialogNotifications;
+  class AutofillDialogController;
+}
+
+// Container for all notifications shown in requestAutocomplete dialog.
+@interface AutofillNotificationContainer : NSViewController<AutofillLayout> {
+ @private
+  // Array of all AutofillNotificationControllers.
+  base::scoped_nsobject<NSMutableArray> notificationControllers_;
+
+  // View that the arrow is anchored to. Weak.
+  NSView* anchorView_;
+
+  // The notification that the checkbox is associated with.
+  scoped_ptr<autofill::DialogNotification> checkboxNotification_;
+
+  // Main controller for the dialog. Weak, owns dialog.
+  autofill::AutofillDialogController* controller_;
+}
+
+// Designated initializer.
+- (id)initWithController:(autofill::AutofillDialogController*)controller;
+
+// Computes the views preferred size given a fixed width.
+- (NSSize)preferredSizeForWidth:(CGFloat)width;
+
+// Sets the notification contents.
+- (void)setNotifications:(const autofill::DialogNotifications&) notifications;
+
+// Sets a view that the arrow is anchored to - center of arrow will be aligned
+// with center of anchorView. (horizontally only).
+- (void)setAnchorView:(NSView*)anchorView;
+
+- (IBAction)checkboxClicked:(id)sender;
+
+@end
+
+#endif // CHROME_BROWSER_UI_COCOA_AUTOFILL_AUTOFILL_NOTIFICATION_CONTAINER_H_
\ No newline at end of file
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_notification_container.mm b/chrome/browser/ui/cocoa/autofill/autofill_notification_container.mm
new file mode 100644
index 0000000..7671ca7
--- /dev/null
+++ b/chrome/browser/ui/cocoa/autofill/autofill_notification_container.mm
@@ -0,0 +1,121 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/ui/cocoa/autofill/autofill_notification_container.h"
+
+#include "base/logging.h"
+#include "base/mac/scoped_nsobject.h"
+#include "base/strings/sys_string_conversions.h"
+#include "chrome/browser/ui/autofill/autofill_dialog_controller.h"
+#include "chrome/browser/ui/autofill/autofill_dialog_types.h"
+#include "chrome/browser/ui/cocoa/autofill/autofill_dialog_constants.h"
+#import "chrome/browser/ui/cocoa/autofill/autofill_notification_controller.h"
+#include "skia/ext/skia_utils_mac.h"
+
+@implementation AutofillNotificationContainer
+
+- (id)initWithController:(autofill::AutofillDialogController*)controller {
+  if (self = [super init]) {
+    controller_ = controller;
+    [self setView:[[[NSView alloc] initWithFrame:NSZeroRect] autorelease]];
+  }
+  return self;
+}
+
+// Just here to satisfy the protocol - not actually invoked.
+- (NSSize)preferredSize {
+  NOTREACHED();
+  return NSZeroSize;
+}
+
+- (NSSize)preferredSizeForWidth:(CGFloat)width {
+  NSSize preferredSize = NSMakeSize(width, 0);
+
+  if ([notificationControllers_ count] == 0)
+    return preferredSize;
+
+  // If the first notification doesn't have an arrow, reserve empty space.
+  if (![[notificationControllers_ objectAtIndex:0] hasArrow])
+    preferredSize.height += kArrowHeight;
+
+  for (AutofillNotificationController* controller in
+       notificationControllers_.get())
+    preferredSize.height += [controller preferredSizeForWidth:width].height;
+
+  return preferredSize;
+}
+
+- (void)performLayout {
+  if ([notificationControllers_ count] == 0)
+    return;
+
+  NSRect remaining = [[self view] bounds];
+
+  if (![[notificationControllers_ objectAtIndex:0] hasArrow])
+    remaining.size.height -= kArrowHeight;
+
+  for (AutofillNotificationController* controller in
+       notificationControllers_.get()) {
+    NSRect viewRect;
+    NSSize size = [controller preferredSizeForWidth:NSWidth(remaining)];
+    NSDivideRect(remaining, &viewRect, &remaining, size.height, NSMaxYEdge);
+    [[controller view ] setFrame:viewRect];
+    [controller performLayout];
+  }
+  DCHECK_EQ(0, NSHeight(remaining));
+}
+
+- (void)setNotifications:(const autofill::DialogNotifications&)notifications {
+  notificationControllers_.reset([[NSMutableArray alloc] init]);
+  checkboxNotification_.reset();
+  [[self view] setSubviews:@[]];
+
+  for (size_t i = 0; i < notifications.size(); ++i) {
+    // Create basic notification view.
+    const autofill::DialogNotification& notification = notifications[i];
+    base::scoped_nsobject<AutofillNotificationController>
+        notificationController([[AutofillNotificationController alloc] init]);
+    [notificationController setText:
+        base::SysUTF16ToNSString(notification.display_text())];
+    [notificationController setTextColor:
+        gfx::SkColorToCalibratedNSColor(notification.GetTextColor())];
+    [notificationController setBackgroundColor:
+        gfx::SkColorToCalibratedNSColor(notification.GetBackgroundColor())];
+
+    // Add optional checkbox.
+    if (notification.HasCheckbox()) {
+      DCHECK(checkboxNotification_);
+      checkboxNotification_.reset(
+          new autofill::DialogNotification(notification));
+      [notificationController setHasCheckbox:YES];
+      if (!notification.interactive())
+          [[notificationController checkbox] setEnabled:FALSE];
+      [[notificationController checkbox] setState:
+          (notification.checked() ? NSOnState : NSOffState)];
+      [[notificationController checkbox] setTarget:self];
+      [[notificationController checkbox] setAction:@selector(checkboxClicked:)];
+    }
+
+    if (i == 0) {
+      [notificationController setHasArrow:notification.HasArrow()
+                           withAnchorView:anchorView_];
+    }
+
+    [notificationControllers_ addObject:notificationController];
+    [[self view] addSubview:[notificationController view]];
+  }
+}
+
+- (void)setAnchorView:(NSView*)anchorView {
+  anchorView_ = anchorView;
+}
+
+- (IBAction)checkboxClicked:(id)sender {
+  DCHECK(checkboxNotification_);
+  BOOL isChecked = ([sender state] == NSOnState);
+  controller_->NotificationCheckboxStateChanged(checkboxNotification_->type(),
+                                                isChecked);
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_notification_container_unittest.mm b/chrome/browser/ui/cocoa/autofill/autofill_notification_container_unittest.mm
new file mode 100644
index 0000000..3d16429
--- /dev/null
+++ b/chrome/browser/ui/cocoa/autofill/autofill_notification_container_unittest.mm
@@ -0,0 +1,61 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/ui/cocoa/autofill/autofill_notification_container.h"
+
+#include "base/mac/scoped_nsobject.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/ui/autofill/autofill_dialog_types.h"
+#include "chrome/browser/ui/autofill/mock_autofill_dialog_controller.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#import "ui/base/test/ui_cocoa_test_helper.h"
+
+namespace {
+
+class AutofillNotificationContainerTest : public ui::CocoaTest {
+ public:
+  virtual void SetUp() {
+    CocoaTest::SetUp();
+    container_.reset([[AutofillNotificationContainer alloc] initWithController:
+                         &controller_]);
+    [[test_window() contentView] addSubview:[container_ view]];
+  }
+
+ protected:
+  base::scoped_nsobject<AutofillNotificationContainer> container_;
+  testing::NiceMock<autofill::MockAutofillDialogController> controller_;
+};
+
+}  // namespace
+
+TEST_VIEW(AutofillNotificationContainerTest, [container_ view])
+
+TEST_F(AutofillNotificationContainerTest, Subviews) {
+  // No subviews if there are no notifications.
+  EXPECT_EQ(0U, [[[container_ view] subviews] count]);
+
+  // Single notification adds one subview.
+  std::vector<autofill::DialogNotification> notifications;
+  notifications.push_back(
+      autofill::DialogNotification(
+          autofill::DialogNotification::REQUIRED_ACTION,
+          ASCIIToUTF16("test")));
+  ASSERT_FALSE(notifications[0].HasArrow());
+  [container_ setNotifications:notifications];
+
+  EXPECT_EQ(1U, [[[container_ view] subviews] count]);
+
+  // 2 notifications, one with arrow - 2 views.
+  notifications.push_back(
+      autofill::DialogNotification(
+          autofill::DialogNotification::REQUIRED_ACTION,
+          ASCIIToUTF16("test")));
+  ASSERT_FALSE(notifications[1].HasArrow());
+  [container_ setNotifications:notifications];
+
+  EXPECT_EQ(2U, [[[container_ view] subviews] count]);
+
+  // Just to exercise code path.
+  [container_ performLayout];
+}
\ No newline at end of file
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_notification_controller.h b/chrome/browser/ui/cocoa/autofill/autofill_notification_controller.h
new file mode 100644
index 0000000..deaff2a
--- /dev/null
+++ b/chrome/browser/ui/cocoa/autofill/autofill_notification_controller.h
@@ -0,0 +1,53 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_COCOA_AUTOFILL_AUTOFILL_NOTIFICATION_CONTROLLER_H_
+#define CHROME_BROWSER_UI_COCOA_AUTOFILL_AUTOFILL_NOTIFICATION_CONTROLLER_H_
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/mac/scoped_nsobject.h"
+#import "chrome/browser/ui/cocoa/autofill/autofill_layout.h"
+
+@class AutofillNotificationView;
+
+// Contains a single notification for requestAutocomplete dialog.
+@interface AutofillNotificationController : NSViewController<AutofillLayout> {
+ @private
+  // NSTextField for label.
+  base::scoped_nsobject<NSTextField> textfield_;
+
+  // Optional checkbox.
+  base::scoped_nsobject<NSButton> checkbox_;
+
+  // Size of a checkbox without title.
+  NSSize checkboxSizeWithoutTitle_;
+}
+
+@property(nonatomic, readonly) NSTextField* textfield;
+@property(nonatomic, readonly) NSButton* checkbox;
+@property(nonatomic, retain) NSColor* backgroundColor;
+@property(nonatomic, retain) NSColor* textColor;
+@property(nonatomic, copy) NSString* text;  // Label text.
+
+// Designated initializer.
+- (id)init;
+
+// Displays arrow on top of notification if set to YES. |anchorView| determines
+// the arrow position - the tip of the arrow is centered on the horizontal
+// midpoint of the anchorView.
+- (void)setHasArrow:(BOOL)hasArrow withAnchorView:(NSView*)anchorView;
+
+// Indicates if the controller draws an arrow.
+- (BOOL)hasArrow;
+
+// Enables the optional checkbox.
+- (void)setHasCheckbox:(BOOL)hasCheckbox;
+
+// Compute preferred size for given width.
+- (NSSize)preferredSizeForWidth:(CGFloat)width;
+
+@end
+
+#endif  // CHROME_BROWSER_UI_COCOA_AUTOFILL_AUTOFILL_NOTIFICATION_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_notification_controller.mm b/chrome/browser/ui/cocoa/autofill/autofill_notification_controller.mm
new file mode 100644
index 0000000..12606a2
--- /dev/null
+++ b/chrome/browser/ui/cocoa/autofill/autofill_notification_controller.mm
@@ -0,0 +1,183 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/ui/cocoa/autofill/autofill_notification_controller.h"
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "base/mac/foundation_util.h"
+#include "base/mac/scoped_nsobject.h"
+#include "chrome/browser/ui/cocoa/autofill/autofill_dialog_constants.h"
+
+@interface AutofillNotificationView : NSView {
+ @private
+  // Weak, determines anchor point for arrow.
+  NSView* arrowAnchorView_;
+  BOOL hasArrow_;
+  base::scoped_nsobject<NSColor> backgroundColor_;
+}
+
+@property (nonatomic, assign) NSView* anchorView;
+@property (nonatomic, assign) BOOL hasArrow;
+@property (nonatomic, retain) NSColor* backgroundColor;
+
+@end
+
+@implementation AutofillNotificationView
+
+@synthesize hasArrow = hasArrow_;
+@synthesize anchorView = arrowAnchorView_;
+
+- (void)drawRect:(NSRect)dirtyRect {
+  [super drawRect:dirtyRect];
+
+  NSRect backgroundRect = [self bounds];
+  if (hasArrow_) {
+    NSPoint anchorPoint = NSMakePoint(NSMidX([arrowAnchorView_ bounds]), 0);
+    anchorPoint = [self convertPoint:anchorPoint fromView:arrowAnchorView_];
+    anchorPoint.y = NSMaxY([self bounds]);
+
+    NSBezierPath* arrow = [NSBezierPath bezierPath];
+    [arrow moveToPoint:anchorPoint];
+    [arrow relativeLineToPoint:NSMakePoint(-kArrowWidth / 2.0, -kArrowHeight)];
+    [arrow relativeLineToPoint:NSMakePoint(kArrowWidth, 0)];
+    [arrow closePath];
+    [backgroundColor_ setFill];
+    [arrow fill];
+    backgroundRect.size.height -= kArrowHeight;
+  }
+
+  dirtyRect = NSIntersectionRect(backgroundRect, dirtyRect);
+  [backgroundColor_ setFill];
+  NSRectFill(dirtyRect);
+}
+
+- (NSColor*)backgroundColor {
+  return backgroundColor_;
+}
+
+- (void)setBackgroundColor:(NSColor*)backgroundColor {
+  backgroundColor_.reset([backgroundColor retain]);
+}
+
+@end
+
+@implementation AutofillNotificationController
+
+- (id)init {
+  if (self = [super init]) {
+    base::scoped_nsobject<AutofillNotificationView> view(
+        [[AutofillNotificationView alloc] initWithFrame:NSZeroRect]);
+    [self setView:view];
+
+    textfield_.reset([[NSTextField alloc] initWithFrame:NSZeroRect]);
+    [textfield_ setEditable:NO];
+    [textfield_ setBordered:NO];
+    [textfield_ setDrawsBackground:NO];
+
+    checkbox_.reset([[NSButton alloc] initWithFrame:NSZeroRect]);
+    [checkbox_ setButtonType:NSSwitchButton];
+    [checkbox_ setTitle:@""];
+    [checkbox_ sizeToFit];
+    checkboxSizeWithoutTitle_ = [checkbox_ frame].size;
+    [checkbox_ setHidden:YES];
+    [view setSubviews:@[textfield_, checkbox_]];
+  }
+  return self;
+}
+
+- (AutofillNotificationView*)notificationView {
+  return base::mac::ObjCCastStrict<AutofillNotificationView>([self view]);
+}
+
+- (void)setHasArrow:(BOOL)hasArrow withAnchorView:(NSView*)anchorView {
+  [[self notificationView] setAnchorView:anchorView];
+  [[self notificationView] setHasArrow:hasArrow];
+}
+
+- (BOOL)hasArrow {
+  return [[self notificationView] hasArrow];
+}
+
+- (void)setHasCheckbox:(BOOL)hasCheckbox {
+  [checkbox_ setHidden:!hasCheckbox];
+}
+
+- (NSString*)text {
+  return [textfield_ stringValue];
+}
+
+- (void)setText:(NSString*)string {
+  [textfield_ setStringValue:string];
+}
+
+- (NSTextField*)textfield {
+  return textfield_;
+}
+
+- (NSButton*)checkbox {
+  return checkbox_;
+}
+
+- (NSColor*)backgroundColor {
+  return [[self notificationView] backgroundColor];
+}
+
+- (void)setBackgroundColor:(NSColor*)backgroundColor {
+  [[self notificationView] setBackgroundColor:backgroundColor];
+}
+
+- (NSColor*)textColor {
+  return [textfield_ textColor];
+}
+
+- (void)setTextColor:(NSColor*)textColor {
+  [textfield_ setTextColor:textColor];
+}
+
+- (NSSize)preferredSizeForWidth:(CGFloat)width {
+  NSRect textRect = NSMakeRect(0, 0, width, CGFLOAT_MAX);
+  if (![checkbox_ isHidden])
+    textRect.size.width -= checkboxSizeWithoutTitle_.width;
+
+  NSSize preferredSize = [[textfield_ cell] cellSizeForBounds:textRect];
+  if (![checkbox_ isHidden]) {
+    preferredSize.height = std::max(preferredSize.height,
+                                    checkboxSizeWithoutTitle_.height);
+  }
+
+  if ([[self notificationView] hasArrow])
+      preferredSize.height += kArrowHeight;
+
+  preferredSize.height += 2 * kNotificationPadding;
+  return preferredSize;
+}
+
+- (NSSize)preferredSize {
+  NOTREACHED();
+  return NSZeroSize;
+}
+
+- (void)performLayout {
+  NSRect bounds = [[self view] bounds];
+  if ([[self notificationView] hasArrow])
+    bounds.size.height -= kArrowHeight;
+
+  NSRect textFrame = NSInsetRect(bounds, 0, kNotificationPadding);
+  if (![checkbox_ isHidden]) {
+    // Temporarily resize checkbox to just the box, no extra clickable area.
+    textFrame.origin.x += checkboxSizeWithoutTitle_.width;
+    textFrame.size.width -= checkboxSizeWithoutTitle_.width;
+    textFrame.size = [[textfield_ cell] cellSizeForBounds:textFrame];
+
+    NSRect checkboxFrame =
+        NSMakeRect(0, 0, NSMaxX(textFrame), NSHeight(textFrame));
+    [checkbox_ setFrame:checkboxFrame];
+  }
+  [textfield_ setFrame:textFrame];
+}
+
+@end
+
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_notification_controller_unittest.mm b/chrome/browser/ui/cocoa/autofill/autofill_notification_controller_unittest.mm
new file mode 100644
index 0000000..f353b03
--- /dev/null
+++ b/chrome/browser/ui/cocoa/autofill/autofill_notification_controller_unittest.mm
@@ -0,0 +1,43 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/ui/cocoa/autofill/autofill_notification_controller.h"
+
+#include "base/mac/scoped_nsobject.h"
+#include "testing/gtest_mac.h"
+#import "ui/base/test/ui_cocoa_test_helper.h"
+
+namespace {
+
+class AutofillNotificationControllerTest : public ui::CocoaTest {
+ public:
+  virtual void SetUp() {
+    CocoaTest::SetUp();
+    controller_.reset([[AutofillNotificationController alloc] init]);
+    [[test_window() contentView] addSubview:[controller_ view]];
+  }
+
+ protected:
+  base::scoped_nsobject<AutofillNotificationController> controller_;
+};
+
+}  // namespace
+
+TEST_VIEW(AutofillNotificationControllerTest, [controller_ view])
+
+TEST_F(AutofillNotificationControllerTest, Subviews) {
+  NSView* view = [controller_ view];
+  ASSERT_EQ(2U, [[view subviews] count]);
+  EXPECT_TRUE([[[view subviews] objectAtIndex:0] isKindOfClass:
+      [NSTextField class]]);
+  EXPECT_TRUE([[[view subviews] objectAtIndex:1] isKindOfClass:
+      [NSButton class]]);
+  EXPECT_NSEQ([controller_ textfield],
+              [[view subviews] objectAtIndex:0]);
+  EXPECT_NSEQ([controller_ checkbox],
+              [[view subviews] objectAtIndex:1]);
+
+  // Just to exercise the code path.
+  [controller_ performLayout];
+}
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_pop_up_button.h b/chrome/browser/ui/cocoa/autofill/autofill_pop_up_button.h
new file mode 100644
index 0000000..8068169
--- /dev/null
+++ b/chrome/browser/ui/cocoa/autofill/autofill_pop_up_button.h
@@ -0,0 +1,22 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_COCOA_AUTOFILL_AUTOFILL_POP_UP_BUTTON_H_
+#define CHROME_BROWSER_UI_COCOA_AUTOFILL_AUTOFILL_POP_UP_BUTTON_H_
+
+#import <Cocoa/Cocoa.h>
+
+#include "chrome/browser/ui/cocoa/autofill/autofill_input_field.h"
+
+@interface AutofillPopUpButton : NSPopUpButton<AutofillInputField>
+@end
+
+@interface AutofillPopUpCell : NSPopUpButtonCell<AutofillInputField> {
+ @private
+  BOOL invalid_;
+}
+
+@end
+
+#endif // CHROME_BROWSER_UI_COCOA_AUTOFILL_AUTOFILL_POP_UP_BUTTON_H_
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_pop_up_button.mm b/chrome/browser/ui/cocoa/autofill/autofill_pop_up_button.mm
new file mode 100644
index 0000000..b7d81a5
--- /dev/null
+++ b/chrome/browser/ui/cocoa/autofill/autofill_pop_up_button.mm
@@ -0,0 +1,73 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/ui/cocoa/autofill/autofill_pop_up_button.h"
+
+#include <ApplicationServices/ApplicationServices.h>
+
+#include "base/mac/scoped_nsobject.h"
+#include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
+
+@implementation AutofillPopUpButton
+
++ (Class)cellClass {
+  return [AutofillPopUpCell class];
+}
+
+- (BOOL)invalid {
+  return [[self cell] invalid];
+}
+
+- (void)setInvalid:(BOOL)invalid {
+  [[self cell] setInvalid:invalid];
+}
+
+- (NSString*)fieldValue {
+  return [[self cell] fieldValue];
+}
+
+- (void)setFieldValue:(NSString*)fieldValue {
+  [[self cell] setFieldValue:fieldValue];
+}
+
+@end
+
+
+@implementation AutofillPopUpCell
+
+@synthesize invalid = invalid_;
+
+// Draw a bezel that's highlighted.
+- (void)drawBezelWithFrame:(NSRect)frame inView:(NSView*)controlView {
+  if (invalid_) {
+    CGContextRef context = static_cast<CGContextRef>(
+        [[NSGraphicsContext currentContext] graphicsPort]);
+
+    // Create a highlight-shaded bezel in a transparency layer.
+    CGContextBeginTransparencyLayerWithRect(context, NSRectToCGRect(frame), 0);
+    // 1. Draw bezel.
+    [super drawBezelWithFrame:frame inView:controlView];
+
+    // 2. Use that as stencil against solid color rect.
+    [[NSColor redColor] set];
+    NSRectFillUsingOperation(frame, NSCompositeSourceAtop);
+
+    // 3. Composite the solid color bezel and the actual bezel.
+    CGContextSetBlendMode(context, kCGBlendModePlusDarker);
+    [super drawBezelWithFrame:frame inView:controlView];
+    CGContextEndTransparencyLayer(context);
+  } else {
+    [super drawBezelWithFrame:frame inView:controlView];
+  }
+}
+
+- (NSString*)fieldValue {
+  return [self titleOfSelectedItem];
+}
+
+- (void)setFieldValue:(NSString*)fieldValue {
+  [self selectItemWithTitle:fieldValue];
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_pop_up_button_unittest.mm b/chrome/browser/ui/cocoa/autofill/autofill_pop_up_button_unittest.mm
new file mode 100644
index 0000000..9310992
--- /dev/null
+++ b/chrome/browser/ui/cocoa/autofill/autofill_pop_up_button_unittest.mm
@@ -0,0 +1,35 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/ui/cocoa/autofill/autofill_pop_up_button.h"
+
+#import "base/mac/scoped_nsobject.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+class AutofillPopUpButtonTest : public CocoaTest {
+ public:
+  AutofillPopUpButtonTest() {
+    NSRect frame = NSMakeRect(0, 0, 50, 30);
+    button_.reset([[AutofillPopUpButton alloc] initWithFrame:frame]);
+    [button_ sizeToFit];
+    [[test_window() contentView] addSubview:button_];
+  }
+
+ protected:
+  base::scoped_nsobject<AutofillPopUpButton> button_;
+
+  DISALLOW_COPY_AND_ASSIGN(AutofillPopUpButtonTest);
+};
+
+TEST_VIEW(AutofillPopUpButtonTest, button_)
+
+// Test invalid, mostly to ensure nothing leaks or crashes.
+TEST_F(AutofillPopUpButtonTest, DisplayWithInvalid) {
+  [button_ setInvalid:YES];
+  [button_ display];
+  [button_ setInvalid:NO];
+  [button_ display];
+}
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_popup_view_bridge.h b/chrome/browser/ui/cocoa/autofill/autofill_popup_view_bridge.h
index 99a4095..09119f4 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_popup_view_bridge.h
+++ b/chrome/browser/ui/cocoa/autofill/autofill_popup_view_bridge.h
@@ -8,7 +8,7 @@
 #include <vector>
 
 #include "base/basictypes.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/compiler_specific.h"
 #include "chrome/browser/ui/autofill/autofill_popup_view.h"
 
 @class AutofillPopupViewCocoa;
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_popup_view_bridge.mm b/chrome/browser/ui/cocoa/autofill/autofill_popup_view_bridge.mm
index 18a4196..ee4313f 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_popup_view_bridge.mm
+++ b/chrome/browser/ui/cocoa/autofill/autofill_popup_view_bridge.mm
@@ -72,8 +72,6 @@
 }
 
 void AutofillPopupViewBridge::Hide() {
-  AutofillPopupView::Hide();
-
   delete this;
 }
 
@@ -92,11 +90,12 @@
 void AutofillPopupViewBridge::UpdateBoundsAndRedrawPopup() {
   NSRect frame = NSRectFromCGRect(controller_->popup_bounds().ToCGRect());
 
-  // Flip coordinates back into Cocoa-land.
-  // TODO(isherman): Does this agree with the controller's idea of handling
-  // multi-monitor setups correctly?
-  NSScreen* screen = [[controller_->container_view() window] screen];
-  frame.origin.y = NSHeight([screen frame]) - NSMaxY(frame);
+  // Flip coordinates back into Cocoa-land.  The controller's platform-neutral
+  // coordinate space places the origin at the top-left of the first screen,
+  // whereas Cocoa's coordinate space expects the origin to be at the
+  // bottom-left of this same screen.
+  NSScreen* screen = [[NSScreen screens] objectAtIndex:0];
+  frame.origin.y = NSMaxY([screen frame]) - NSMaxY(frame);
 
   // Leave room for the border.
   frame = NSInsetRect(frame, -kBorderWidth, -kBorderWidth);
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_section_container.h b/chrome/browser/ui/cocoa/autofill/autofill_section_container.h
index 1abaab0..62ff41b 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_section_container.h
+++ b/chrome/browser/ui/cocoa/autofill/autofill_section_container.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/ui/autofill/autofill_dialog_types.h"
 #import "chrome/browser/ui/cocoa/autofill/autofill_layout.h"
 
@@ -27,13 +27,14 @@
 @interface AutofillSectionContainer :
     NSViewController<AutofillLayout> {
  @private
-  scoped_nsobject<LayoutView> inputs_;
-  scoped_nsobject<MenuButton> suggestButton_;
-  scoped_nsobject<AutofillSuggestionContainer> suggestContainer_;
-  scoped_nsobject<NSTextField> label_;
-  scoped_nsobject<AutofillSectionView> view_;  // The view for the container.
+  base::scoped_nsobject<LayoutView> inputs_;
+  base::scoped_nsobject<MenuButton> suggestButton_;
+  base::scoped_nsobject<AutofillSuggestionContainer> suggestContainer_;
+  base::scoped_nsobject<NSTextField> label_;
+  base::scoped_nsobject<AutofillSectionView> view_;  // The view for the
+                                                     // container.
 
-  scoped_nsobject<MenuController> menuController_;
+  base::scoped_nsobject<MenuController> menuController_;
   autofill::DialogSection section_;
   autofill::AutofillDialogController* controller_;  // Not owned.
 }
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_section_container.mm b/chrome/browser/ui/cocoa/autofill/autofill_section_container.mm
index 73ef309..7c48db9 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_section_container.mm
+++ b/chrome/browser/ui/cocoa/autofill/autofill_section_container.mm
@@ -7,6 +7,7 @@
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/ui/autofill/autofill_dialog_controller.h"
+#import "chrome/browser/ui/cocoa/autofill/autofill_pop_up_button.h"
 #import "chrome/browser/ui/cocoa/autofill/autofill_section_view.h"
 #import "chrome/browser/ui/cocoa/autofill/autofill_suggestion_container.h"
 #import "chrome/browser/ui/cocoa/autofill/autofill_textfield.h"
@@ -91,12 +92,11 @@
 }
 
 - (void)getInputs:(autofill::DetailOutputMap*)output {
-  for (id input in [inputs_ subviews]) {
+  for (NSControl<AutofillInputField>* input in [inputs_ subviews]) {
     const autofill::DetailInput* detailInput =
         reinterpret_cast<autofill::DetailInput*>([input tag]);
     DCHECK(detailInput);
-    NSString* value = [input isKindOfClass:[NSPopUpButton class]] ?
-        [input titleOfSelectedItem] : [input stringValue];
+    NSString* value = [input fieldValue];
     output->insert(
         std::make_pair(detailInput,base::SysNSStringToUTF16(value)));
   }
@@ -126,7 +126,6 @@
 - (void)loadView {
   inputs_.reset([[self makeInputControls] retain]);
   string16 labelText = controller_->LabelForSection(section_);
-
   label_.reset([[self makeDetailSectionLabel:
                    base::SysUTF16ToNSString(labelText)] retain]);
 
@@ -141,6 +140,9 @@
 }
 
 - (NSSize)preferredSize {
+  if ([view_ isHidden])
+    return NSMakeSize(0, 0);
+
   NSSize labelSize = [label_ frame].size;  // Assumes sizeToFit was called.
   CGFloat controlHeight = [inputs_ preferredHeightForWidth:kDetailsWidth];
   if ([inputs_ isHidden])
@@ -154,6 +156,9 @@
 }
 
 - (void)performLayout {
+  if ([view_ isHidden])
+    return;
+
   NSSize buttonSize = [suggestButton_ frame].size;  // Assume sizeToFit.
   NSSize labelSize = [label_ frame].size;  // Assumes sizeToFit was called.
   CGFloat controlHeight = [inputs_ preferredHeightForWidth:kDetailsWidth];
@@ -198,12 +203,11 @@
 }
 
 - (NSTextField*)makeDetailSectionLabel:(NSString*)labelText {
-  scoped_nsobject<NSTextField> label([[NSTextField alloc] init]);
+  base::scoped_nsobject<NSTextField> label([[NSTextField alloc] init]);
   [label setFont:
       [[NSFontManager sharedFontManager] convertFont:[label font]
                                          toHaveTrait:NSBoldFontMask]];
   [label setStringValue:labelText];
-  [label sizeToFit];
   [label setEditable:NO];
   [label setBordered:NO];
   [label sizeToFit];
@@ -211,7 +215,7 @@
 }
 
 - (MenuButton*)makeSuggestionButton {
-  scoped_nsobject<MenuButton> button([[MenuButton alloc] init]);
+  base::scoped_nsobject<MenuButton> button([[MenuButton alloc] init]);
 
   [button setOpenMenuOnClick:YES];
   [button setBordered:NO];
@@ -245,7 +249,7 @@
   const autofill::DetailInputs& inputs =
       controller_->RequestedFieldsForSection(section_);
 
-  scoped_nsobject<LayoutView> view([[LayoutView alloc] init]);
+  base::scoped_nsobject<LayoutView> view([[LayoutView alloc] init]);
   [view setLayoutManager:
       scoped_ptr<SimpleGridLayout>(new SimpleGridLayout(view))];
   SimpleGridLayout* layout = [view layoutManager];
@@ -273,30 +277,30 @@
 
     ui::ComboboxModel* input_model =
         controller_->ComboboxModelForAutofillType(input.type);
+    base::scoped_nsprotocol<NSControl<AutofillInputField>*> control;
     if (input_model) {
-      scoped_nsobject<NSPopUpButton> popup(
-          [[NSPopUpButton alloc] initWithFrame:NSZeroRect pullsDown:YES]);
+      base::scoped_nsobject<AutofillPopUpButton> popup(
+          [[AutofillPopUpButton alloc] initWithFrame:NSZeroRect pullsDown:NO]);
       for (int i = 0; i < input_model->GetItemCount(); ++i) {
         [popup addItemWithTitle:
             base::SysUTF16ToNSString(input_model->GetItemAt(i))];
       }
-      [popup selectItemWithTitle:base::SysUTF16ToNSString(input.initial_value)];
-      [popup sizeToFit];
-      [popup setTag:reinterpret_cast<NSInteger>(&input)];
-      layout->AddView(popup);
+      control.reset(popup.release());
     } else {
-      scoped_nsobject<AutofillTextField> field(
+      base::scoped_nsobject<AutofillTextField> field(
           [[AutofillTextField alloc] init]);
       [[field cell] setPlaceholderString:
           l10n_util::GetNSStringWithFixup(input.placeholder_text_rid)];
       [[field cell] setIcon:
           controller_->IconForField(
               input.type, input.initial_value).AsNSImage()];
-      [[field cell] setInvalid:YES];
-      [field sizeToFit];
-      [field setTag:reinterpret_cast<NSInteger>(&input)];
-      layout->AddView(field);
+      control.reset(field.release());
     }
+    [control setFieldValue:base::SysUTF16ToNSString(input.initial_value)];
+    [control setInvalid:YES];
+    [control sizeToFit];
+    [control setTag:reinterpret_cast<NSInteger>(&input)];
+    layout->AddView(control);
   }
 
   return view.autorelease();
@@ -326,6 +330,7 @@
     [suggestContainer_ showTextfield:extraText withIcon:extraIcon];
   }
   [view_ setShouldHighlightOnHover:showSuggestions];
+  [view_ setHidden:!controller_->SectionIsActive(section_)];
 }
 
 - (void)update {
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_section_container_unittest.mm b/chrome/browser/ui/cocoa/autofill/autofill_section_container_unittest.mm
index 651d0c0..12c8199 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_section_container_unittest.mm
+++ b/chrome/browser/ui/cocoa/autofill/autofill_section_container_unittest.mm
@@ -5,15 +5,15 @@
 #import "chrome/browser/ui/cocoa/autofill/autofill_section_container.h"
 
 #include "base/mac/foundation_util.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/ui/autofill/autofill_dialog_models.h"
 #include "chrome/browser/ui/autofill/mock_autofill_dialog_controller.h"
 #import "chrome/browser/ui/cocoa/autofill/layout_view.h"
 #import "chrome/browser/ui/cocoa/menu_button.h"
 #include "grit/generated_resources.h"
-#include "testing/gtest_mac.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "testing/gtest_mac.h"
 #include "testing/platform_test.h"
 #include "ui/base/models/combobox_model.h"
 #include "ui/base/models/simple_menu_model.h"
@@ -41,7 +41,7 @@
   }
 
  protected:
-  scoped_nsobject<AutofillSectionContainer> container_;
+  base::scoped_nsobject<AutofillSectionContainer> container_;
   testing::NiceMock<autofill::MockAutofillDialogController> controller_;
 };
 
@@ -163,4 +163,4 @@
 
   EXPECT_NSEQ(@"a", [[menu itemAtIndex:1] title]);
   EXPECT_NSEQ(@"b", [[menu itemAtIndex:2] title]);
-}
\ No newline at end of file
+}
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_section_view_unittest.mm b/chrome/browser/ui/cocoa/autofill/autofill_section_view_unittest.mm
index 2515c71..8cad9d7 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_section_view_unittest.mm
+++ b/chrome/browser/ui/cocoa/autofill/autofill_section_view_unittest.mm
@@ -4,7 +4,7 @@
 
 #import "chrome/browser/ui/cocoa/autofill/autofill_section_view.h"
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/gtest_mac.h"
@@ -74,8 +74,8 @@
   }
 
  protected:
-  scoped_nsobject<AutofillSectionView> view_;
-  scoped_nsobject<NSBitmapImageRep> bitmap_;
+  base::scoped_nsobject<AutofillSectionView> view_;
+  base::scoped_nsobject<NSBitmapImageRep> bitmap_;
   scoped_ptr<gfx::ScopedNSGraphicsContextSaveGState> saved_context_;
   NSGraphicsContext* context_;
 };
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_sign_in_container_unittest.mm b/chrome/browser/ui/cocoa/autofill/autofill_sign_in_container_unittest.mm
index 83220df..77f8a4b 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_sign_in_container_unittest.mm
+++ b/chrome/browser/ui/cocoa/autofill/autofill_sign_in_container_unittest.mm
@@ -4,7 +4,7 @@
 
 #import "chrome/browser/ui/cocoa/autofill/autofill_sign_in_container.h"
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/ui/autofill/mock_autofill_dialog_controller.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
@@ -60,7 +60,7 @@
   }
 
  protected:
-  scoped_nsobject<AutofillSignInContainer> container_;
+  base::scoped_nsobject<AutofillSignInContainer> container_;
   testing::NiceMock<autofill::MockAutofillDialogController> controller_;
   CocoaTestHelperWindow* test_window_;
 };
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_suggestion_container.h b/chrome/browser/ui/cocoa/autofill/autofill_suggestion_container.h
index 6253a20..6fe11d7 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_suggestion_container.h
+++ b/chrome/browser/ui/cocoa/autofill/autofill_suggestion_container.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/autofill/autofill_layout.h"
 
 namespace autofill {
@@ -20,16 +20,16 @@
 @interface AutofillSuggestionContainer : NSViewController<AutofillLayout> {
  @private
   // The label that holds the suggestion description text.
-  scoped_nsobject<NSTextField> label_;
+  base::scoped_nsobject<NSTextField> label_;
 
   // The second (and longer) line of text that describes the suggestion.
-  scoped_nsobject<NSTextField> label2_;
+  base::scoped_nsobject<NSTextField> label2_;
 
   // The icon that comes just before |label_|.
-  scoped_nsobject<NSImageView> iconImageView_;
+  base::scoped_nsobject<NSImageView> iconImageView_;
 
   // The input set by ShowTextfield.
-  scoped_nsobject<AutofillTextField> inputField_;
+  base::scoped_nsobject<AutofillTextField> inputField_;
 
   autofill::AutofillDialogController* controller_;  // Not owned.
 }
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_suggestion_container.mm b/chrome/browser/ui/cocoa/autofill/autofill_suggestion_container.mm
index 6522e69..9989f83 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_suggestion_container.mm
+++ b/chrome/browser/ui/cocoa/autofill/autofill_suggestion_container.mm
@@ -8,7 +8,7 @@
 #include <cmath>
 
 #include "base/logging.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/strings/sys_string_conversions.h"
 #include "chrome/browser/ui/autofill/autofill_dialog_controller.h"
 #include "chrome/browser/ui/chrome_style.h"
@@ -38,7 +38,7 @@
 @implementation AutofillSuggestionContainer
 
 - (NSTextField*)makeDetailSectionLabel:(NSString*)labelText {
-  scoped_nsobject<NSTextField> label([[NSTextField alloc] init]);
+  base::scoped_nsobject<NSTextField> label([[NSTextField alloc] init]);
   [label setFont:
       [[NSFontManager sharedFontManager] convertFont:[label font]
                                          toHaveTrait:NSBoldFontMask]];
@@ -60,14 +60,14 @@
   inputField_.reset([[AutofillTextField alloc] initWithFrame:NSZeroRect]);
   [inputField_ setHidden:YES];
 
-  scoped_nsobject<NSView> view([[NSView alloc] initWithFrame:NSZeroRect]);
+  base::scoped_nsobject<NSView> view([[NSView alloc] initWithFrame:NSZeroRect]);
   [view setSubviews:
       @[iconImageView_, label_, inputField_, label2_ ]];
   [self setView:view];
 }
 
 - (NSTextField*)createLabelWithFrame:(NSRect)frame {
-  scoped_nsobject<NSTextField> label(
+  base::scoped_nsobject<NSTextField> label(
       [[NSTextField alloc] initWithFrame:frame]);
   [label setEditable:NO];
   [label setDrawsBackground:NO];
@@ -174,4 +174,4 @@
   [[self view] setFrameSize:preferredContainerSize];
 }
 
-@end
\ No newline at end of file
+@end
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_suggestion_container_unittest.mm b/chrome/browser/ui/cocoa/autofill/autofill_suggestion_container_unittest.mm
index 08b3848..e535d41 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_suggestion_container_unittest.mm
+++ b/chrome/browser/ui/cocoa/autofill/autofill_suggestion_container_unittest.mm
@@ -20,7 +20,7 @@
   }
 
  protected:
-  scoped_nsobject<AutofillSuggestionContainer> container_;
+  base::scoped_nsobject<AutofillSuggestionContainer> container_;
 };
 
 }  // namespace
@@ -47,4 +47,4 @@
   EXPECT_EQ(2, num_text_fields);
   EXPECT_TRUE(has_edit_field);
   EXPECT_TRUE(has_icon);
-}
\ No newline at end of file
+}
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_textfield.h b/chrome/browser/ui/cocoa/autofill/autofill_textfield.h
index 57fcea7..4a2d4d9 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_textfield.h
+++ b/chrome/browser/ui/cocoa/autofill/autofill_textfield.h
@@ -7,21 +7,21 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include <base/memory/scoped_nsobject.h>
+#include "base/mac/scoped_nsobject.h"
+#include "chrome/browser/ui/cocoa/autofill/autofill_input_field.h"
 
 // Text field used for text inputs inside Autofill.
 // Provide both dog ear and red outline when the contents are marked invalid.
-@interface AutofillTextField : NSTextField
+@interface AutofillTextField : NSTextField<AutofillInputField>
 @end
 
-@interface AutofillTextFieldCell : NSTextFieldCell {
+@interface AutofillTextFieldCell : NSTextFieldCell<AutofillInputField> {
  @private
   BOOL invalid_;
-  scoped_nsobject<NSImage> icon_;
+  base::scoped_nsobject<NSImage> icon_;
 }
 
-@property(assign, nonatomic) BOOL invalid;
-@property(nonatomic, retain, getter=icon, setter=setIcon:) NSImage* icon;
+@property(nonatomic, retain) NSImage* icon;
 
 @end
 
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_textfield.mm b/chrome/browser/ui/cocoa/autofill/autofill_textfield.mm
index 6be76c0..3daad77 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_textfield.mm
+++ b/chrome/browser/ui/cocoa/autofill/autofill_textfield.mm
@@ -27,6 +27,22 @@
   return [AutofillTextFieldCell class];
 }
 
+- (BOOL)invalid {
+  return [[self cell] invalid];
+}
+
+- (void)setInvalid:(BOOL)invalid {
+  [[self cell] setInvalid:invalid];
+}
+
+- (NSString*)fieldValue {
+  return [[self cell] fieldValue];
+}
+
+- (void)setFieldValue:(NSString*)fieldValue {
+  [[self cell] setFieldValue:fieldValue];
+}
+
 @end
 
 @implementation AutofillTextFieldCell
@@ -41,6 +57,14 @@
   icon_.reset([icon retain]);
 }
 
+- (NSString*)fieldValue {
+  return [self stringValue];
+}
+
+- (void)setFieldValue:(NSString*)fieldValue {
+  [self setStringValue:fieldValue];
+}
+
 - (NSRect)textFrameForFrame:(NSRect)frame {
   if (icon_) {
     NSRect textFrame, iconFrame;
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_textfield_unittest.mm b/chrome/browser/ui/cocoa/autofill/autofill_textfield_unittest.mm
index ed6fa79..f32e636 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_textfield_unittest.mm
+++ b/chrome/browser/ui/cocoa/autofill/autofill_textfield_unittest.mm
@@ -4,7 +4,7 @@
 
 #import "chrome/browser/ui/cocoa/autofill/autofill_textfield.h"
 
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
@@ -20,7 +20,7 @@
   }
 
  protected:
-  scoped_nsobject<AutofillTextField> textfield_;
+  base::scoped_nsobject<AutofillTextField> textfield_;
 
   DISALLOW_COPY_AND_ASSIGN(AutofillTextFieldTest);
 };
diff --git a/chrome/browser/ui/cocoa/autofill/down_arrow_popup_menu_cell_unittest.mm b/chrome/browser/ui/cocoa/autofill/down_arrow_popup_menu_cell_unittest.mm
index d41b496..4d878d6 100644
--- a/chrome/browser/ui/cocoa/autofill/down_arrow_popup_menu_cell_unittest.mm
+++ b/chrome/browser/ui/cocoa/autofill/down_arrow_popup_menu_cell_unittest.mm
@@ -6,7 +6,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/ui/cocoa/autofill/autofill_dialog_constants.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
@@ -19,13 +19,13 @@
   DownArrowPopupMenuCellTest() {
     NSRect frame = NSMakeRect(0, 0, 50, 30);
     view_.reset([[NSButton alloc] initWithFrame:frame]);
-    scoped_nsobject<DownArrowPopupMenuCell> cell(
+    base::scoped_nsobject<DownArrowPopupMenuCell> cell(
         [[DownArrowPopupMenuCell alloc] initTextCell:@"Testing"]);
     [view_ setCell:cell.get()];
     [[test_window() contentView] addSubview:view_];  }
 
  protected:
-  scoped_nsobject<NSButton> view_;
+  base::scoped_nsobject<NSButton> view_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(DownArrowPopupMenuCellTest);
@@ -50,7 +50,8 @@
   ASSERT_TRUE([cell isKindOfClass:[DownArrowPopupMenuCell class]]);
 
   NSRect rect = NSMakeRect(0, 0, 11, 17);
-  scoped_nsobject<NSImage> image([[NSImage alloc] initWithSize:rect.size]);
+  base::scoped_nsobject<NSImage> image(
+      [[NSImage alloc] initWithSize:rect.size]);
   [cell setImage:image forButtonState:image_button_cell::kDefaultState];
   [view_ setTitle:@"Testing"];
 
diff --git a/chrome/browser/ui/cocoa/autofill/layout_view_unittest.mm b/chrome/browser/ui/cocoa/autofill/layout_view_unittest.mm
index abfcd22..c56c9f8 100644
--- a/chrome/browser/ui/cocoa/autofill/layout_view_unittest.mm
+++ b/chrome/browser/ui/cocoa/autofill/layout_view_unittest.mm
@@ -4,7 +4,7 @@
 
 #import "chrome/browser/ui/cocoa/autofill/layout_view.h"
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/ui/cocoa/autofill/simple_grid_layout.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
@@ -24,7 +24,7 @@
   }
 
  protected:
-  scoped_nsobject<LayoutView> view_;
+  base::scoped_nsobject<LayoutView> view_;
   SimpleGridLayout* layout_;  // weak, owned by view_.
 };
 
@@ -40,9 +40,9 @@
   cs->AddColumn(0.4);
   cs->AddColumn(0.6);
   layout_->StartRow(0, 0);
-  scoped_nsobject<NSView> childView1(
+  base::scoped_nsobject<NSView> childView1(
       [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 0, 45)]);
-  scoped_nsobject<NSView> childView2(
+  base::scoped_nsobject<NSView> childView2(
       [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 20, 55)]);
   layout_->AddView(childView1);
   layout_->AddView(childView2);
@@ -62,4 +62,4 @@
   subview = [[view_ subviews] objectAtIndex:1];
   EXPECT_FLOAT_EQ(24, NSWidth([subview frame]));
   EXPECT_FLOAT_EQ(55, NSHeight([subview frame]));
-}
\ No newline at end of file
+}
diff --git a/chrome/browser/ui/cocoa/autofill/simple_grid_layout_unittest.mm b/chrome/browser/ui/cocoa/autofill/simple_grid_layout_unittest.mm
index d529211..da517c7 100644
--- a/chrome/browser/ui/cocoa/autofill/simple_grid_layout_unittest.mm
+++ b/chrome/browser/ui/cocoa/autofill/simple_grid_layout_unittest.mm
@@ -5,7 +5,7 @@
 #include "chrome/browser/ui/cocoa/autofill/simple_grid_layout.h"
 
 #include "base/logging.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
@@ -19,15 +19,15 @@
 
 class LayoutTest : public testing::Test {
  public:
-  scoped_nsobject<NSView> CreateViewWithWidth(float width) {
+  base::scoped_nsobject<NSView> CreateViewWithWidth(float width) {
     NSRect frame = NSMakeRect(0, 0, width, 0);
-    scoped_nsobject<NSView> view([[NSView alloc] initWithFrame:frame]);
+    base::scoped_nsobject<NSView> view([[NSView alloc] initWithFrame:frame]);
     return view;
   }
 
-  scoped_nsobject<NSView> CreateViewWithHeight(float height) {
+  base::scoped_nsobject<NSView> CreateViewWithHeight(float height) {
     NSRect frame = NSMakeRect(0, 0, 0, height);
-    scoped_nsobject<NSView> view([[NSView alloc] initWithFrame:frame]);
+    base::scoped_nsobject<NSView> view([[NSView alloc] initWithFrame:frame]);
     return view;
   }
 };
@@ -107,7 +107,7 @@
   ColumnSet* cs;
   cs = layout.AddRow();
   cs->AddColumn(1.0f);
-  scoped_nsobject<NSView> view1 = CreateViewWithHeight(30.0f);
+  base::scoped_nsobject<NSView> view1 = CreateViewWithHeight(30.0f);
   layout.AddView(view1);
 
   layout.AddPaddingRow(20);
@@ -115,7 +115,7 @@
   cs = layout.AddRow();
   cs->AddColumn(1.0f);
   EXPECT_EQ(3, layout.num_rows());
-  scoped_nsobject<NSView> view2 = CreateViewWithHeight(10.0f);
+  base::scoped_nsobject<NSView> view2 = CreateViewWithHeight(10.0f);
   layout.AddView(view2);
 
   layout.SizeRowsAndColumns(0.0f);
@@ -132,17 +132,17 @@
   layout.GetLastValidColumnSet()->AddColumn(0.6f);
   layout.GetLastValidColumnSet()->AddColumn(0.6f);
 
-  scoped_nsobject<NSView> view1 = CreateViewWithHeight(37.0f);
+  base::scoped_nsobject<NSView> view1 = CreateViewWithHeight(37.0f);
   layout.AddView(view1);
   layout.SizeRowsAndColumns(0.0f);
   EXPECT_FLOAT_EQ(37.0f, layout.GetRowHeight(0));
 
-  scoped_nsobject<NSView> view2 = CreateViewWithHeight(26.0f);
+  base::scoped_nsobject<NSView> view2 = CreateViewWithHeight(26.0f);
   layout.AddView(view2);
   layout.SizeRowsAndColumns(0.0f);
   EXPECT_FLOAT_EQ(37.0f, layout.GetRowHeight(0));
 
-  scoped_nsobject<NSView> view3 = CreateViewWithHeight(42.0f);
+  base::scoped_nsobject<NSView> view3 = CreateViewWithHeight(42.0f);
   layout.AddView(view3);
   layout.SizeRowsAndColumns(0.0f);
   EXPECT_FLOAT_EQ(42.0f, layout.GetRowHeight(0));
@@ -153,12 +153,12 @@
 
   layout.AddRow();
   layout.GetLastValidColumnSet()->AddColumn(0.6f);
-  scoped_nsobject<NSView> view1 = CreateViewWithHeight(30.0f);
+  base::scoped_nsobject<NSView> view1 = CreateViewWithHeight(30.0f);
   layout.AddView(view1);
 
   layout.AddRow();
   layout.GetLastValidColumnSet()->AddColumn(0.6f);
-  scoped_nsobject<NSView> view2 = CreateViewWithHeight(40.0f);
+  base::scoped_nsobject<NSView> view2 = CreateViewWithHeight(40.0f);
   layout.AddView(view2);
 
   layout.SizeRowsAndColumns(0.0f);
@@ -174,17 +174,17 @@
   layout.GetLastValidColumnSet()->AddPaddingColumn(30);
   layout.GetLastValidColumnSet()->AddColumn(0.4f);
 
-  scoped_nsobject<NSView> view1 = CreateViewWithHeight(22.0f);
-  scoped_nsobject<NSView> view2 = CreateViewWithHeight(20.0f);
+  base::scoped_nsobject<NSView> view1 = CreateViewWithHeight(22.0f);
+  base::scoped_nsobject<NSView> view2 = CreateViewWithHeight(20.0f);
   layout.AddView(view1);
   layout.AddView(view2);
 
   layout.AddRow();
   layout.GetLastValidColumnSet()->AddColumn(0.6f);
-  scoped_nsobject<NSView> view3 = CreateViewWithHeight(18.0f);
+  base::scoped_nsobject<NSView> view3 = CreateViewWithHeight(18.0f);
   layout.AddView(view3);
 
-  scoped_nsobject<NSView> host_view = CreateViewWithWidth(150.0f);
+  base::scoped_nsobject<NSView> host_view = CreateViewWithWidth(150.0f);
   layout.Layout(host_view);
 
   EXPECT_FLOAT_EQ(72.0f, NSWidth([view1 frame]));
@@ -214,7 +214,7 @@
   layout.AddRow();
   layout.GetLastValidColumnSet()->AddColumn(0.6f);
 
-  scoped_nsobject<NSView> view1 = CreateViewWithHeight(22.0f);
+  base::scoped_nsobject<NSView> view1 = CreateViewWithHeight(22.0f);
   layout.AddView(view1);
   EXPECT_FLOAT_EQ(22.0f, layout.GetPreferredHeightForWidth(100.0));
 
@@ -223,7 +223,7 @@
 
   layout.AddRow();
   layout.GetLastValidColumnSet()->AddColumn(0.6f);
-  scoped_nsobject<NSView> view2 = CreateViewWithHeight(13.0f);
+  base::scoped_nsobject<NSView> view2 = CreateViewWithHeight(13.0f);
   layout.AddView(view2);
   EXPECT_FLOAT_EQ(47.0f, layout.GetPreferredHeightForWidth(100.0));
 }
@@ -308,7 +308,7 @@
   layout.GetLastValidColumnSet()->AddColumn(0.4f);
 
   EXPECT_EQ(0, layout.next_column());
-  scoped_nsobject<NSView> view1 = CreateViewWithWidth(37.0f);
+  base::scoped_nsobject<NSView> view1 = CreateViewWithWidth(37.0f);
   layout.AddView(view1);
   EXPECT_EQ(2, layout.next_column());
 }
@@ -321,12 +321,12 @@
   layout.GetLastValidColumnSet()->AddPaddingColumn(30);
   layout.GetLastValidColumnSet()->AddColumn(0.4f);
 
-  scoped_nsobject<NSView> view1 = CreateViewWithWidth(37.0f);
-  scoped_nsobject<NSView> view2 = CreateViewWithWidth(42.0f);
+  base::scoped_nsobject<NSView> view1 = CreateViewWithWidth(37.0f);
+  base::scoped_nsobject<NSView> view2 = CreateViewWithWidth(42.0f);
   layout.AddView(view1);
   layout.AddView(view2);
 
-  scoped_nsobject<NSView> host_view = CreateViewWithWidth(150.0f);
+  base::scoped_nsobject<NSView> host_view = CreateViewWithWidth(150.0f);
   layout.Layout(host_view);
 
   EXPECT_FLOAT_EQ(72.0f, NSWidth([view1 frame]));
diff --git a/chrome/browser/ui/cocoa/background_gradient_view.h b/chrome/browser/ui/cocoa/background_gradient_view.h
index a156980..e8b6c2d 100644
--- a/chrome/browser/ui/cocoa/background_gradient_view.h
+++ b/chrome/browser/ui/cocoa/background_gradient_view.h
@@ -14,6 +14,9 @@
   BOOL showsDivider_;
 }
 
+// Controls whether the bar draws a dividing line at the bottom.
+@property(nonatomic, assign) BOOL showsDivider;
+
 // The color used for the bottom stroke. Public so subclasses can use.
 - (NSColor*)strokeColor;
 
@@ -26,8 +29,6 @@
 // example of this.
 - (void)drawBackgroundWithOpaque:(BOOL)opaque;
 
-// Controls whether the bar draws a dividing line at the bottom.
-@property(nonatomic, assign) BOOL showsDivider;
 @end
 
 #endif  // CHROME_BROWSER_UI_COCOA_BACKGROUND_GRADIENT_VIEW_H_
diff --git a/chrome/browser/ui/cocoa/background_gradient_view.mm b/chrome/browser/ui/cocoa/background_gradient_view.mm
index f16fd34..26a904f 100644
--- a/chrome/browser/ui/cocoa/background_gradient_view.mm
+++ b/chrome/browser/ui/cocoa/background_gradient_view.mm
@@ -16,6 +16,7 @@
 @end
 
 @implementation BackgroundGradientView
+
 @synthesize showsDivider = showsDivider_;
 
 - (id)initWithFrame:(NSRect)frameRect {
@@ -82,8 +83,12 @@
 }
 
 - (NSColor*)strokeColor {
-  BOOL isActive = [[self window] isMainWindow];
-  ui::ThemeProvider* themeProvider = [[self window] themeProvider];
+  NSWindow* window = [self window];
+  if ([window parentWindow])
+    window = [window parentWindow];
+
+  BOOL isActive = [window isMainWindow];
+  ui::ThemeProvider* themeProvider = [window themeProvider];
   if (!themeProvider)
     return [NSColor blackColor];
   return themeProvider->GetNSColor(
@@ -111,7 +116,7 @@
 
 - (void)windowFocusDidChange:(NSNotification*)notification {
   // The background color depends on the window's focus state.
-  [self setNeedsDisplay:YES];
+  [self cr_recursivelySetNeedsDisplay:YES];
 }
 
 - (void)viewWillMoveToWindow:(NSWindow*)window {
diff --git a/chrome/browser/ui/cocoa/background_gradient_view_unittest.mm b/chrome/browser/ui/cocoa/background_gradient_view_unittest.mm
index d1cda6c..b7e9697 100644
--- a/chrome/browser/ui/cocoa/background_gradient_view_unittest.mm
+++ b/chrome/browser/ui/cocoa/background_gradient_view_unittest.mm
@@ -4,7 +4,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/background_gradient_view.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -36,7 +36,7 @@
  public:
   BackgroundGradientViewTest() {
     NSRect frame = NSMakeRect(0, 0, 100, 30);
-    scoped_nsobject<BackgroundGradientSubClassTest> view;
+    base::scoped_nsobject<BackgroundGradientSubClassTest> view;
     view.reset([[BackgroundGradientSubClassTest alloc] initWithFrame:frame]);
     view_ = view.get();
     [[test_window() contentView] addSubview:view_];
diff --git a/chrome/browser/ui/cocoa/base_bubble_controller.mm b/chrome/browser/ui/cocoa/base_bubble_controller.mm
index 91eaa98..c7ef5b6 100644
--- a/chrome/browser/ui/cocoa/base_bubble_controller.mm
+++ b/chrome/browser/ui/cocoa/base_bubble_controller.mm
@@ -7,7 +7,7 @@
 #include "base/logging.h"
 #include "base/mac/bundle_locations.h"
 #include "base/mac/mac_util.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/strings/string_util.h"
 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
 #import "chrome/browser/ui/cocoa/info_bubble_view.h"
@@ -76,7 +76,7 @@
     DCHECK(![[self window] delegate]);
     [theWindow setDelegate:self];
 
-    scoped_nsobject<InfoBubbleView> contentView(
+    base::scoped_nsobject<InfoBubbleView> contentView(
         [[InfoBubbleView alloc] initWithFrame:NSMakeRect(0, 0, 0, 0)]);
     [theWindow setContentView:contentView.get()];
     bubble_ = contentView.get();
@@ -123,7 +123,7 @@
 
 - (NSBox*)separatorWithFrame:(NSRect)frame {
   frame.size.height = 1.0;
-  scoped_nsobject<NSBox> spacer([[NSBox alloc] initWithFrame:frame]);
+  base::scoped_nsobject<NSBox> spacer([[NSBox alloc] initWithFrame:frame]);
   [spacer setBoxType:NSBoxSeparator];
   [spacer setBorderType:NSLineBorder];
   [spacer setAlphaValue:0.2];
diff --git a/chrome/browser/ui/cocoa/base_bubble_controller_unittest.mm b/chrome/browser/ui/cocoa/base_bubble_controller_unittest.mm
index 307034c..feccd6f 100644
--- a/chrome/browser/ui/cocoa/base_bubble_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/base_bubble_controller_unittest.mm
@@ -5,7 +5,7 @@
 #import "chrome/browser/ui/cocoa/base_bubble_controller.h"
 
 #include "base/mac/mac_util.h"
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #import "chrome/browser/ui/cocoa/info_bubble_view.h"
 #import "chrome/browser/ui/cocoa/run_loop_testing.h"
@@ -44,7 +44,7 @@
   }
 
  public:
-  scoped_nsobject<NSWindow> bubbleWindow_;
+  base::scoped_nsobject<NSWindow> bubbleWindow_;
   BaseBubbleController* controller_;
 };
 
@@ -118,12 +118,12 @@
 // the key window changes.
 TEST_F(BaseBubbleControllerTest, ResignKeyCloses) {
   // Closing the bubble will autorelease the controller.
-  scoped_nsobject<BaseBubbleController> keep_alive([controller_ retain]);
+  base::scoped_nsobject<BaseBubbleController> keep_alive([controller_ retain]);
 
   NSWindow* bubble_window = [controller_ window];
   EXPECT_FALSE([bubble_window isVisible]);
 
-  scoped_nsobject<NSWindow> other_window(
+  base::scoped_nsobject<NSWindow> other_window(
       [[NSWindow alloc] initWithContentRect:NSMakeRect(500, 500, 500, 500)
                                   styleMask:NSTitledWindowMask
                                     backing:NSBackingStoreBuffered
@@ -163,7 +163,7 @@
     return;
 
   // Closing the bubble will autorelease the controller.
-  scoped_nsobject<BaseBubbleController> keep_alive([controller_ retain]);
+  base::scoped_nsobject<BaseBubbleController> keep_alive([controller_ retain]);
   NSWindow* window = [controller_ window];
 
   EXPECT_FALSE([window isVisible]);
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_all_tabs_controller_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_all_tabs_controller_unittest.mm
index 1e0a3ab..6e21dc2 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_all_tabs_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_all_tabs_controller_unittest.mm
@@ -4,7 +4,6 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_bridge_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_bridge_unittest.mm
index a0f2ef9..0a9650d 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_bridge_unittest.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_bridge_unittest.mm
@@ -26,7 +26,7 @@
 // Oddly, we are our own delegate.
 @interface FakeBookmarkBarController : BookmarkBarController {
  @public
-  scoped_nsobject<NSMutableArray> callbacks_;
+  base::scoped_nsobject<NSMutableArray> callbacks_;
   std::vector<OpenInfo> opens_;
 }
 @end
@@ -98,15 +98,15 @@
 TEST_F(BookmarkBarBridgeTest, TestRedirect) {
   BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile());
 
-  scoped_nsobject<NSView> parentView([[NSView alloc]
-                                       initWithFrame:NSMakeRect(0,0,100,100)]);
-  scoped_nsobject<NSView> webView([[NSView alloc]
-                                       initWithFrame:NSMakeRect(0,0,100,100)]);
-  scoped_nsobject<NSView> infoBarsView(
-      [[NSView alloc] initWithFrame:NSMakeRect(0,0,100,100)]);
+  base::scoped_nsobject<NSView> parentView(
+      [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)]);
+  base::scoped_nsobject<NSView> webView(
+      [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)]);
+  base::scoped_nsobject<NSView> infoBarsView(
+      [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)]);
 
-  scoped_nsobject<FakeBookmarkBarController>
-      controller([[FakeBookmarkBarController alloc] initWithBrowser:browser()]);
+  base::scoped_nsobject<FakeBookmarkBarController> controller(
+      [[FakeBookmarkBarController alloc] initWithBrowser:browser()]);
   EXPECT_TRUE(controller.get());
   scoped_ptr<BookmarkBarBridge> bridge(new BookmarkBarBridge(profile(),
                                                              controller.get(),
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_constants.h b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_constants.h
index 87fe929..9a2031b 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_constants.h
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_constants.h
@@ -23,21 +23,11 @@
 // |kVisualHeightOffset|.
 const int kBookmarkBarHeight = 26;
 
-// Height of the bookmark bar on the new tab page when instant extended is
-// enabled. TODO(sail): Remove this and update chrome::kNTPBookmarkBarHeight
-// instead.
-static const int kSearchNewTabBookmarkBarHeight = 40;
-
 // The amount of space between the inner bookmark bar and the outer toolbar on
 // new tab pages.
-const int kNTPBookmarkBarPadding = (chrome::kNTPBookmarkBarHeight -
-    (kBookmarkBarHeight + kVisualHeightOffset)) / 2;
-
-// Same as |kNTPBookmarkBarPadding| except for the instant extended UI.
-// TODO(sail): Remove this this and update |kNTPBookmarkBarPadding| instead.
-const int kSearchNTPBookmarkBarPadding =
-    (kSearchNewTabBookmarkBarHeight -
-     (kBookmarkBarHeight + kVisualHeightOffset)) / 2;
+const int kNTPBookmarkBarPadding =
+    (chrome::kNTPBookmarkBarHeight -
+        (kBookmarkBarHeight + kVisualHeightOffset)) / 2;
 
 // The height of buttons in the bookmark bar.
 const int kBookmarkButtonHeight = kBookmarkBarHeight + kVisualHeightOffset;
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h
index 234f663..baf11cd 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h
@@ -9,7 +9,7 @@
 #include <map>
 
 #import "base/mac/cocoa_protocols.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #include "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_bridge.h"
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_constants.h"
@@ -183,13 +183,13 @@
   std::map<int32,int64> menuTagMap_;
 
   // Our bookmark buttons, ordered from L-->R.
-  scoped_nsobject<NSMutableArray> buttons_;
+  base::scoped_nsobject<NSMutableArray> buttons_;
 
   // The folder image so we can use one copy for all buttons
-  scoped_nsobject<NSImage> folderImage_;
+  base::scoped_nsobject<NSImage> folderImage_;
 
   // The default image, so we can use one copy for all buttons.
-  scoped_nsobject<NSImage> defaultImage_;
+  base::scoped_nsobject<NSImage> defaultImage_;
 
   // If the bar is disabled, we hide it and ignore show/hide commands.
   // Set when using fullscreen mode.
@@ -206,7 +206,7 @@
   id<ViewResizer> resizeDelegate_;  // weak
 
   // Logic for dealing with a click on a bookmark folder button.
-  scoped_nsobject<BookmarkFolderTarget> folderTarget_;
+  base::scoped_nsobject<BookmarkFolderTarget> folderTarget_;
 
   // A controller for a pop-up bookmark folder window (custom menu).
   // This is not a scoped_nsobject because it owns itself (when its
@@ -224,17 +224,17 @@
   NSRect originalImportBookmarksRect_;  // Original, pre-resized field rect.
 
   // "Other bookmarks" button on the right side.
-  scoped_nsobject<BookmarkButton> otherBookmarksButton_;
+  base::scoped_nsobject<BookmarkButton> otherBookmarksButton_;
 
   // "Apps" button to the right of "Other bookmarks".
-  scoped_nsobject<BookmarkButton> appsPageShortcutButton_;
+  base::scoped_nsobject<BookmarkButton> appsPageShortcutButton_;
 
   // When doing a drag, this is folder button "hovered over" which we
   // may want to open after a short delay.  There are cases where a
   // mouse-enter can open a folder (e.g. if the menus are "active")
   // but that doesn't use this variable or need a delay so "hover" is
   // the wrong term.
-  scoped_nsobject<BookmarkButton> hoverButton_;
+  base::scoped_nsobject<BookmarkButton> hoverButton_;
 
   // We save the view width when we add bookmark buttons.  This lets
   // us avoid a rebuild until we've grown the window bigger than our
@@ -258,7 +258,7 @@
   BOOL showFolderMenus_;
 
   // If YES then state changes (for example, from hidden to shown) are animated.
-  // This is turned off for instant extended and for unit tests.
+  // This is turned off for unit tests.
   BOOL stateAnimationsEnabled_;
 
   // If YES then changes inside the bookmark bar (for example, removing a
@@ -273,7 +273,8 @@
   CGFloat insertionPos_;
 
   // Controller responsible for all bookmark context menus.
-  scoped_nsobject<BookmarkContextMenuCocoaController> contextMenuController_;
+  base::scoped_nsobject<BookmarkContextMenuCocoaController>
+      contextMenuController_;
 }
 
 @property(readonly, nonatomic) BookmarkBar::State currentState;
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.mm
index 3c43a37..baaf33a 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.mm
@@ -9,17 +9,16 @@
 #include "base/metrics/histogram.h"
 #include "base/prefs/pref_service.h"
 #include "base/strings/sys_string_conversions.h"
-#include "chrome/browser/bookmarks/bookmark_editor.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/browser/bookmarks/bookmark_utils.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/prefs/incognito_mode_prefs.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/search/search.h"
 #include "chrome/browser/themes/theme_properties.h"
 #include "chrome/browser/themes/theme_service.h"
 #import "chrome/browser/themes/theme_service_factory.h"
+#include "chrome/browser/ui/bookmarks/bookmark_editor.h"
 #include "chrome/browser/ui/bookmarks/bookmark_utils.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_list.h"
@@ -44,7 +43,6 @@
 #import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h"
 #import "chrome/browser/ui/cocoa/view_id_util.h"
 #import "chrome/browser/ui/cocoa/view_resizer.h"
-#include "chrome/browser/ui/search/search_ui.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/webui/ntp/app_launcher_handler.h"
 #include "chrome/common/extensions/extension_constants.h"
@@ -472,13 +470,17 @@
   // Add padding to the detached bookmark bar.
   // The state of our morph (if any); 1 is total bubble, 0 is the regular bar.
   CGFloat morph = [self detachedMorphProgress];
-  CGFloat padding = chrome::IsInstantExtendedAPIEnabled()
-                    ? bookmarks::kSearchNTPBookmarkBarPadding
-                    : bookmarks::kNTPBookmarkBarPadding;
+  CGFloat padding = bookmarks::kNTPBookmarkBarPadding;
   buttonViewFrame =
       NSInsetRect(buttonViewFrame, morph * padding, morph * padding);
 
   [buttonView_ setFrame:buttonViewFrame];
+
+  // Update bookmark button backgrounds.
+  if ([self isAnimationRunning]) {
+    for (NSButton* button in buttons_.get())
+      [button setNeedsDisplay:YES];
+  }
 }
 
 // We don't change a preference; we only change visibility. Preference changing
@@ -899,10 +901,7 @@
     [[self backgroundGradientView] setShowsDivider:YES];
     [[self view] setHidden:NO];
     AnimatableView* view = [self animatableView];
-    CGFloat newHeight = chrome::IsInstantExtendedAPIEnabled()
-                        ? bookmarks::kSearchNewTabBookmarkBarHeight
-                        : chrome::kNTPBookmarkBarHeight;
-    [view animateToNewHeight:newHeight
+    [view animateToNewHeight:chrome::kNTPBookmarkBarHeight
                     duration:kBookmarkBarAnimationDuration];
   } else if ([self isAnimatingFromState:BookmarkBar::DETACHED
                                 toState:BookmarkBar::SHOW]) {
@@ -946,8 +945,6 @@
     case BookmarkBar::SHOW:
       return bookmarks::kBookmarkBarHeight;
     case BookmarkBar::DETACHED:
-      if (chrome::IsInstantExtendedAPIEnabled())
-        return bookmarks::kSearchNewTabBookmarkBarHeight;
       return chrome::kNTPBookmarkBarHeight;
     case BookmarkBar::HIDDEN:
       return 0;
@@ -1073,8 +1070,8 @@
   BookmarkButtonCell* cell = [self cellForBookmarkNode:node];
   NSRect frame = [self frameForBookmarkButtonFromCell:cell xOffset:xOffset];
 
-  scoped_nsobject<BookmarkButton>
-      button([[BookmarkButton alloc] initWithFrame:frame]);
+  base::scoped_nsobject<BookmarkButton> button(
+      [[BookmarkButton alloc] initWithFrame:frame]);
   DCHECK(button.get());
 
   // [NSButton setCell:] warns to NOT use setCell: other than in the
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller_unittest.mm
index 7769928..b654f44 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller_unittest.mm
@@ -6,13 +6,14 @@
 
 #include "base/basictypes.h"
 #include "base/command_line.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/strings/string16.h"
 #include "base/strings/string_util.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
+#include "chrome/browser/bookmarks/bookmark_model_test_utils.h"
 #include "chrome/browser/bookmarks/bookmark_utils.h"
 #include "chrome/browser/extensions/test_extension_system.h"
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_constants.h"
@@ -26,12 +27,11 @@
 #import "chrome/browser/ui/cocoa/view_resizer_pong.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
-#include "chrome/test/base/model_test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #import "testing/gtest_mac.h"
 #include "testing/platform_test.h"
-#include "third_party/ocmock/gtest_support.h"
 #import "third_party/ocmock/OCMock/OCMock.h"
+#include "third_party/ocmock/gtest_support.h"
 #include "ui/base/cocoa/animation_utils.h"
 #include "ui/base/test/cocoa_test_event_utils.h"
 #include "ui/base/theme_provider.h"
@@ -204,7 +204,7 @@
 class FakeTheme : public ui::ThemeProvider {
  public:
   FakeTheme(NSColor* color) : color_(color) {}
-  scoped_nsobject<NSColor> color_;
+  base::scoped_nsobject<NSColor> color_;
 
   virtual gfx::ImageSkia* GetImageSkiaNamed(int id) const OVERRIDE {
     return NULL;
@@ -292,8 +292,8 @@
 
 class BookmarkBarControllerTestBase : public CocoaProfileTest {
  public:
-  scoped_nsobject<NSView> parent_view_;
-  scoped_nsobject<ViewResizerPong> resizeDelegate_;
+  base::scoped_nsobject<NSView> parent_view_;
+  base::scoped_nsobject<ViewResizerPong> resizeDelegate_;
 
   virtual void SetUp() {
     CocoaProfileTest::SetUp();
@@ -335,8 +335,8 @@
 
 class BookmarkBarControllerTest : public BookmarkBarControllerTestBase {
  public:
-  scoped_nsobject<NSButtonCell> cell_;
-  scoped_nsobject<BookmarkBarControllerNoOpen> bar_;
+  base::scoped_nsobject<NSButtonCell> cell_;
+  base::scoped_nsobject<BookmarkBarControllerNoOpen> bar_;
 
   virtual void SetUp() {
     BookmarkBarControllerTestBase::SetUp();
@@ -496,7 +496,7 @@
 
 // Make sure we're watching for frame change notifications.
 TEST_F(BookmarkBarControllerTest, FrameChangeNotification) {
-  scoped_nsobject<BookmarkBarControllerTogglePong> bar;
+  base::scoped_nsobject<BookmarkBarControllerTogglePong> bar;
   bar.reset(
     [[BookmarkBarControllerTogglePong alloc]
           initWithBrowser:browser()
@@ -731,9 +731,10 @@
   GURL gurl("http://walla.walla.ding.dong.com");
   scoped_ptr<BookmarkNode> node(new BookmarkNode(gurl));
 
-  scoped_nsobject<BookmarkButtonCell> cell([[BookmarkButtonCell alloc] init]);
+  base::scoped_nsobject<BookmarkButtonCell> cell(
+      [[BookmarkButtonCell alloc] init]);
   [cell setBookmarkNode:node.get()];
-  scoped_nsobject<BookmarkButton> button([[BookmarkButton alloc] init]);
+  base::scoped_nsobject<BookmarkButton> button([[BookmarkButton alloc] init]);
   [button setCell:cell.get()];
   [cell setRepresentedObject:[NSValue valueWithPointer:node.get()]];
 
@@ -830,7 +831,7 @@
 // Make sure that each button we add marches to the right and does not
 // overlap with the previous one.
 TEST_F(BookmarkBarControllerTest, TestButtonMarch) {
-  scoped_nsobject<NSMutableArray> cells([[NSMutableArray alloc] init]);
+  base::scoped_nsobject<NSMutableArray> cells([[NSMutableArray alloc] init]);
 
   CGFloat widths[] = { 10, 10, 100, 10, 500, 500, 80000, 60000, 1, 345 };
   for (unsigned int i = 0; i < arraysize(widths); i++) {
@@ -1168,7 +1169,7 @@
     bookmark_utils::AddIfNotBookmarked(model, gurls[i], titles[i]);
 
   // Get and retain the buttons so we can examine them after dealloc.
-  scoped_nsobject<NSArray> buttons([[bar_ buttons] retain]);
+  base::scoped_nsobject<NSArray> buttons([[bar_ buttons] retain]);
   EXPECT_EQ([buttons count], arraysize(titles));
 
   // Make sure that everything is set.
@@ -1238,10 +1239,11 @@
   BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile());
   const BookmarkNode* root = model->bookmark_bar_node();
   const std::string model_string("1b 2f:[ 2f1b 2f2b ] 3b 4f:[ 4f1b 4f2b ] ");
-  model_test_utils::AddNodesFromModelString(model, root, model_string);
+  BookmarkModelTestUtils::AddNodesFromModelString(model, root, model_string);
 
   // Validate initial model and that we do not have a folder controller.
-  std::string actualModelString = model_test_utils::ModelStringFromNode(root);
+  std::string actualModelString =
+      BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ(model_string, actualModelString);
   EXPECT_FALSE([bar_ folderController]);
 
@@ -1452,10 +1454,11 @@
   BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile());
   const BookmarkNode* root = model->bookmark_bar_node();
   const std::string model_string("1b 2f:[ 2f1b 2f2b ] 3b ");
-  model_test_utils::AddNodesFromModelString(model, root, model_string);
+  BookmarkModelTestUtils::AddNodesFromModelString(model, root, model_string);
 
   // Validate initial model.
-  std::string actualModelString = model_test_utils::ModelStringFromNode(root);
+  std::string actualModelString =
+      BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ(model_string, actualModelString);
 
   // Remember how many buttons are showing.
@@ -1525,7 +1528,7 @@
   BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile());
   const BookmarkNode* root = model->bookmark_bar_node();
   const std::string model_string("1b 2f:[ 2f1b 2f2b ] 3b ");
-  model_test_utils::AddNodesFromModelString(model, root, model_string);
+  BookmarkModelTestUtils::AddNodesFromModelString(model, root, model_string);
   [bar_ frameDidChange];
 
   CGFloat viewWidths[] = { 123.0, 124.0, 151.0, 152.0, 153.0, 154.0, 155.0,
@@ -1561,7 +1564,7 @@
   BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile());
   const BookmarkNode* root = model->bookmark_bar_node();
   const std::string model_string("1b 2f:[ 2f1b 2f2b ] 3b ");
-  model_test_utils::AddNodesFromModelString(model, root, model_string);
+  BookmarkModelTestUtils::AddNodesFromModelString(model, root, model_string);
   [bar_ frameDidChange];
 
   // Apps page shortcut button should be visible.
@@ -1702,9 +1705,9 @@
     // Do not add the bar to a window, yet.
   }
 
-  scoped_nsobject<NSView> parent_view_;
-  scoped_nsobject<ViewResizerPong> resizeDelegate_;
-  scoped_nsobject<BookmarkBarControllerNotificationPong> bar_;
+  base::scoped_nsobject<NSView> parent_view_;
+  base::scoped_nsobject<ViewResizerPong> resizeDelegate_;
+  base::scoped_nsobject<BookmarkBarControllerNotificationPong> bar_;
 };
 
 TEST_F(BookmarkBarControllerNotificationTest, DeregistersForNotifications) {
@@ -1740,7 +1743,7 @@
 
 class BookmarkBarControllerDragDropTest : public BookmarkBarControllerTestBase {
  public:
-  scoped_nsobject<BookmarkBarControllerDragData> bar_;
+  base::scoped_nsobject<BookmarkBarControllerDragData> bar_;
 
   virtual void SetUp() {
     BookmarkBarControllerTestBase::SetUp();
@@ -1765,10 +1768,11 @@
       "3bWithLongName 4bWithLongName 5bWithLongName 6bWithLongName "
       "7bWithLongName 8bWithLongName 9bWithLongName 10bWithLongName "
       "11bWithLongName 12bWithLongName 13b ");
-  model_test_utils::AddNodesFromModelString(model, root, model_string);
+  BookmarkModelTestUtils::AddNodesFromModelString(model, root, model_string);
 
   // Validate initial model.
-  std::string actualModelString = model_test_utils::ModelStringFromNode(root);
+  std::string actualModelString =
+      BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ(model_string, actualModelString);
 
   // Insure that the off-the-side is not showing.
@@ -1817,16 +1821,18 @@
       "11bWithLongName 12bWithLongName 13bWithLongName 14bWithLongName "
       "15bWithLongName 16bWithLongName 17bWithLongName 18bWithLongName "
       "19bWithLongName 20bWithLongName ");
-  model_test_utils::AddNodesFromModelString(model, root, model_string);
+  BookmarkModelTestUtils::AddNodesFromModelString(model, root, model_string);
 
   const BookmarkNode* other = model->other_node();
   const std::string other_string("1other 2other 3other ");
-  model_test_utils::AddNodesFromModelString(model, other, other_string);
+  BookmarkModelTestUtils::AddNodesFromModelString(model, other, other_string);
 
   // Validate initial model.
-  std::string actualModelString = model_test_utils::ModelStringFromNode(root);
+  std::string actualModelString =
+      BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ(model_string, actualModelString);
-  std::string actualOtherString = model_test_utils::ModelStringFromNode(other);
+  std::string actualOtherString =
+      BookmarkModelTestUtils::ModelStringFromNode(other);
   EXPECT_EQ(other_string, actualOtherString);
 
   // Insure that the off-the-side is showing.
@@ -1870,16 +1876,16 @@
   const BookmarkNode* root = model->bookmark_bar_node();
   const std::string model_string("1b 2f:[ 2f1b 2f2f:[ 2f2f1b 2f2f2b 2f2f3b ] "
                                   "2f3b ] 3b 4b ");
-  model_test_utils::AddNodesFromModelString(model, root, model_string);
+  BookmarkModelTestUtils::AddNodesFromModelString(model, root, model_string);
   const BookmarkNode* other = model->other_node();
   const std::string other_string("O1b O2b O3f:[ O3f1b O3f2f ] "
                                  "O4f:[ O4f1b O4f2f ] 05b ");
-  model_test_utils::AddNodesFromModelString(model, other, other_string);
+  BookmarkModelTestUtils::AddNodesFromModelString(model, other, other_string);
 
   // Validate initial model.
-  std::string actual = model_test_utils::ModelStringFromNode(root);
+  std::string actual = BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ(model_string, actual);
-  actual = model_test_utils::ModelStringFromNode(other);
+  actual = BookmarkModelTestUtils::ModelStringFromNode(other);
   EXPECT_EQ(other_string, actual);
 
   // Remember the little ones.
@@ -1891,7 +1897,7 @@
   // Gen up some dragging data.
   const BookmarkNode* newNode = other->GetChild(2);
   [bar_ setDragDataNode:newNode];
-  scoped_nsobject<FakeDragInfo> dragInfo([[FakeDragInfo alloc] init]);
+  base::scoped_nsobject<FakeDragInfo> dragInfo([[FakeDragInfo alloc] init]);
   [dragInfo setDropLocation:[targetButton center]];
   [bar_ dragBookmarkData:(id<NSDraggingInfo>)dragInfo.get()];
 
@@ -1901,7 +1907,7 @@
   // Verify the model.
   const std::string expected("1b 2f:[ 2f1b 2f2f:[ 2f2f1b 2f2f2b 2f2f3b ] "
                              "2f3b ] O3f:[ O3f1b O3f2f ] 3b 4b ");
-  actual = model_test_utils::ModelStringFromNode(root);
+  actual = BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ(expected, actual);
   oldChildCount = newChildCount;
 
@@ -1921,7 +1927,7 @@
   const std::string expected1("1b 2f:[ 2f1b 2f2f:[ 2f2f1b 2f2f2b 2f2f3b ] "
                               "2f3b O4f:[ O4f1b O4f2f ] ] O3f:[ O3f1b O3f2f ] "
                               "3b 4b ");
-  actual = model_test_utils::ModelStringFromNode(root);
+  actual = BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ(expected1, actual);
 }
 
@@ -1930,10 +1936,10 @@
   const BookmarkNode* root = model->bookmark_bar_node();
   const std::string model_string("1b 2f:[ 2f1b 2f2f:[ 2f2f1b 2f2f2b 2f2f3b ] "
                                  "2f3b ] 3b 4b ");
-  model_test_utils::AddNodesFromModelString(model, root, model_string);
+  BookmarkModelTestUtils::AddNodesFromModelString(model, root, model_string);
 
   // Validate initial model.
-  std::string actual = model_test_utils::ModelStringFromNode(root);
+  std::string actual = BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ(model_string, actual);
 
   // Remember the children.
@@ -1953,7 +1959,7 @@
   // Verify the model.
   const std::string expected("1b 2f:[ 2f1b 2f2f:[ 2f2f1b 2f2f2b 2f2f3b ] "
                              "2f3b ] SiteA SiteB 3b 4b ");
-  actual = model_test_utils::ModelStringFromNode(root);
+  actual = BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ(expected, actual);
 }
 
@@ -1961,10 +1967,11 @@
   BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile());
   const BookmarkNode* root = model->bookmark_bar_node();
   const std::string model_string("1b 2f:[ 2f1b 2f2b ] 3b ");
-  model_test_utils::AddNodesFromModelString(model, root, model_string);
+  BookmarkModelTestUtils::AddNodesFromModelString(model, root, model_string);
 
   // Validate initial model.
-  std::string actualModelString = model_test_utils::ModelStringFromNode(root);
+  std::string actualModelString =
+      BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ(model_string, actualModelString);
 
   // Find the main bar controller.
@@ -1977,10 +1984,10 @@
   BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile());
   const BookmarkNode* root = model->bookmark_bar_node();
   const std::string model_string("1b 2f:[ 2f1b 2f2b 2f3b ] 3b 4b ");
-  model_test_utils::AddNodesFromModelString(model, root, model_string);
+  BookmarkModelTestUtils::AddNodesFromModelString(model, root, model_string);
 
   // Validate initial model.
-  std::string actualModel = model_test_utils::ModelStringFromNode(root);
+  std::string actualModel = BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ(model_string, actualModel);
 
   // Test a series of points starting at the right edge of the bar.
@@ -2047,10 +2054,10 @@
   const BookmarkNode* root = model->bookmark_bar_node();
   const std::string model_string("1b 2f:[ 2f1b 2f2f:[ 2f2f1b 2f2f2b 2f2f3b ] "
                                   "2f3b ] 3b 4b ");
-  model_test_utils::AddNodesFromModelString(model, root, model_string);
+  BookmarkModelTestUtils::AddNodesFromModelString(model, root, model_string);
 
   // Validate initial model.
-  std::string actual = model_test_utils::ModelStringFromNode(root);
+  std::string actual = BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ(model_string, actual);
 
   int oldChildCount = root->child_count();
@@ -2067,7 +2074,7 @@
   // Verify the model.
   const std::string expected("1b 2f:[ 2f1b 2f2f:[ 2f2f1b 2f2f2b 2f2f3b ] "
                              "2f3b ] 4b ");
-  actual = model_test_utils::ModelStringFromNode(root);
+  actual = BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ(expected, actual);
 
   // Verify that the other bookmark folder can't be deleted.
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_button_cell_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_button_cell_unittest.mm
index 3b1eb0a..7418039 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_button_cell_unittest.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_button_cell_unittest.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_button_cell.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #include "grit/ui_resources.h"
@@ -15,7 +15,7 @@
 
 // Basic creation.
 TEST_F(BookmarkBarFolderButtonCellTest, Create) {
-  scoped_nsobject<BookmarkBarFolderButtonCell> cell;
+  base::scoped_nsobject<BookmarkBarFolderButtonCell> cell;
   cell.reset([[BookmarkBarFolderButtonCell buttonCellForNode:nil
                                                         text:nil
                                                        image:nil
@@ -25,21 +25,21 @@
 
 TEST_F(BookmarkBarFolderButtonCellTest, FaviconPositioning) {
   NSRect frame = NSMakeRect(0, 0, 50, 30);
-  scoped_nsobject<NSButton> view([[NSButton alloc] initWithFrame:frame]);
-  scoped_nsobject<NSButton> folder_view(
+  base::scoped_nsobject<NSButton> view([[NSButton alloc] initWithFrame:frame]);
+  base::scoped_nsobject<NSButton> folder_view(
       [[NSButton alloc] initWithFrame:frame]);
 
   ASSERT_TRUE(view.get());
   ASSERT_TRUE(folder_view.get());
 
   ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-  scoped_nsobject<NSImage> image(
+  base::scoped_nsobject<NSImage> image(
       rb.GetNativeImageNamed(IDR_DEFAULT_FAVICON).CopyNSImage());
   ASSERT_TRUE(image.get());
 
-  scoped_nsobject<BookmarkButtonCell> cell(
+  base::scoped_nsobject<BookmarkButtonCell> cell(
       [[BookmarkButtonCell alloc] initTextCell:@"Testing"]);
-  scoped_nsobject<BookmarkBarFolderButtonCell> folder_cell(
+  base::scoped_nsobject<BookmarkBarFolderButtonCell> folder_cell(
       [[BookmarkBarFolderButtonCell buttonCellForNode:nil
                                                  text:@"Testing"
                                                 image:image
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller.h b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller.h
index 746552c..ec27fea 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller.h
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_button.h"
 #import "ui/base/cocoa/tracking_area.h"
 
@@ -27,7 +27,7 @@
                        BookmarkButtonControllerProtocol> {
  @private
   // The button whose click opened us.
-  scoped_nsobject<BookmarkButton> parentButton_;
+  base::scoped_nsobject<BookmarkButton> parentButton_;
 
   // Bookmark bar folder controller chains are torn down in two ways:
   // 1. Clicking "outside" the folder (see use of the NSEvent local event
@@ -57,13 +57,13 @@
 
   // Our parent controller, if we are a nested folder, otherwise nil.
   // Strong to insure the object lives as long as we need it.
-  scoped_nsobject<BookmarkBarFolderController> parentController_;
+  base::scoped_nsobject<BookmarkBarFolderController> parentController_;
 
   // The main bar controller from whence we or a parent sprang.
   BookmarkBarController* barController_;  // WEAK: It owns us.
 
   // Our buttons.  We do not have buttons for nested folders.
-  scoped_nsobject<NSMutableArray> buttons_;
+  base::scoped_nsobject<NSMutableArray> buttons_;
 
   // The scroll view that contains our main button view (below).
   IBOutlet NSScrollView* scrollView_;
@@ -102,10 +102,10 @@
   // We model hover state as a state machine with specific allowable
   // transitions.  |hoverState_| is the state of this machine at any
   // given time.
-  scoped_nsobject<BookmarkBarFolderHoverState> hoverState_;
+  base::scoped_nsobject<BookmarkBarFolderHoverState> hoverState_;
 
   // Logic for dealing with a click on a bookmark folder button.
-  scoped_nsobject<BookmarkFolderTarget> folderTarget_;
+  base::scoped_nsobject<BookmarkFolderTarget> folderTarget_;
 
   // A controller for a pop-up bookmark folder window (custom menu).
   // We (self) are the parentController_ for our folderController_.
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller_unittest.mm
index 3999e7a..4ed276c 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller_unittest.mm
@@ -3,10 +3,11 @@
 // found in the LICENSE file.
 
 #include "base/basictypes.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
+#include "chrome/browser/bookmarks/bookmark_model_test_utils.h"
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_constants.h"
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h"
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_button_cell.h"
@@ -15,7 +16,6 @@
 #include "chrome/browser/ui/cocoa/cocoa_profile_test.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #import "chrome/browser/ui/cocoa/view_resizer_pong.h"
-#include "chrome/test/base/model_test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #import "testing/gtest_mac.h"
 #include "testing/platform_test.h"
@@ -129,7 +129,7 @@
 
 class BookmarkBarFolderControllerTest : public CocoaProfileTest {
  public:
-  scoped_nsobject<BookmarkBarControllerChildFolderRedirect> bar_;
+  base::scoped_nsobject<BookmarkBarControllerChildFolderRedirect> bar_;
   const BookmarkNode* folderA_;  // Owned by model.
   const BookmarkNode* longTitleNode_;  // Owned by model.
 
@@ -217,7 +217,7 @@
 };
 
 TEST_F(BookmarkBarFolderControllerTest, InitCreateAndDelete) {
-  scoped_nsobject<BookmarkBarFolderController> bbfc;
+  base::scoped_nsobject<BookmarkBarFolderController> bbfc;
   bbfc.reset(SimpleBookmarkBarFolderController());
 
   // Make sure none of the buttons overlap, that all are inside
@@ -251,7 +251,7 @@
 // Make sure closing of the window releases the controller.
 // (e.g. valgrind shouldn't complain if we do this).
 TEST_F(BookmarkBarFolderControllerTest, ReleaseOnClose) {
-  scoped_nsobject<BookmarkBarFolderController> bbfc;
+  base::scoped_nsobject<BookmarkBarFolderController> bbfc;
   bbfc.reset(SimpleBookmarkBarFolderController());
   EXPECT_TRUE(bbfc.get());
 
@@ -264,7 +264,7 @@
   EXPECT_TRUE(parentButton);
 
   // If parent is a BookmarkBarController, grow down.
-  scoped_nsobject<BookmarkBarFolderController> bbfc;
+  base::scoped_nsobject<BookmarkBarFolderController> bbfc;
   bbfc.reset([[BookmarkBarFolderController alloc]
                initWithParentButton:parentButton
                    parentController:nil
@@ -289,7 +289,7 @@
   EXPECT_LT(shifted.x, pt.x);
 
   // If parent is a BookmarkBarFolderController, grow right.
-  scoped_nsobject<BookmarkBarFolderController> bbfc2;
+  base::scoped_nsobject<BookmarkBarFolderController> bbfc2;
   bbfc2.reset([[BookmarkBarFolderController alloc]
                 initWithParentButton:[[bbfc buttons] objectAtIndex:0]
                     parentController:bbfc.get()
@@ -323,7 +323,7 @@
   EXPECT_TRUE(parentButton);
 
   // Open them all.
-  scoped_nsobject<NSMutableArray> folder_controller_array;
+  base::scoped_nsobject<NSMutableArray> folder_controller_array;
   folder_controller_array.reset([[NSMutableArray array] retain]);
   for (i=0; i<count; i++) {
     BookmarkBarFolderControllerNoLevel* bbfcl =
@@ -368,7 +368,7 @@
 }
 
 TEST_F(BookmarkBarFolderControllerTest, DropDestination) {
-  scoped_nsobject<BookmarkBarFolderController> bbfc;
+  base::scoped_nsobject<BookmarkBarFolderController> bbfc;
   bbfc.reset(SimpleBookmarkBarFolderController());
   EXPECT_TRUE(bbfc.get());
 
@@ -404,7 +404,7 @@
 }
 
 TEST_F(BookmarkBarFolderControllerTest, OpenFolder) {
-  scoped_nsobject<BookmarkBarFolderController> bbfc;
+  base::scoped_nsobject<BookmarkBarFolderController> bbfc;
   bbfc.reset(SimpleBookmarkBarFolderController());
   EXPECT_TRUE(bbfc.get());
 
@@ -430,7 +430,7 @@
 }
 
 TEST_F(BookmarkBarFolderControllerTest, DeleteOpenFolder) {
-  scoped_nsobject<BookmarkBarFolderController> parent_controller(
+  base::scoped_nsobject<BookmarkBarFolderController> parent_controller(
       SimpleBookmarkBarFolderController());
 
   // Open a folder.
@@ -445,7 +445,7 @@
 }
 
 TEST_F(BookmarkBarFolderControllerTest, ChildFolderCallbacks) {
-  scoped_nsobject<BookmarkBarFolderControllerPong> bbfc;
+  base::scoped_nsobject<BookmarkBarFolderControllerPong> bbfc;
   bbfc.reset(SimpleBookmarkBarFolderController());
   EXPECT_TRUE(bbfc.get());
   [bar_ setChildFolderDelegate:bbfc.get()];
@@ -463,7 +463,7 @@
 
 // Make sure bookmark folders have variable widths.
 TEST_F(BookmarkBarFolderControllerTest, ChildFolderWidth) {
-  scoped_nsobject<BookmarkBarFolderController> bbfc;
+  base::scoped_nsobject<BookmarkBarFolderController> bbfc;
 
   bbfc.reset(SimpleBookmarkBarFolderController());
   EXPECT_TRUE(bbfc.get());
@@ -482,7 +482,7 @@
 // Simple scrolling tests.
 // Currently flaky due to a changed definition of the correct menu boundaries.
 TEST_F(BookmarkBarFolderControllerTest, DISABLED_SimpleScroll) {
-  scoped_nsobject<BookmarkBarFolderController> bbfc;
+  base::scoped_nsobject<BookmarkBarFolderController> bbfc;
   NSRect screenFrame = [[NSScreen mainScreen] visibleFrame];
   CGFloat screenHeight = NSHeight(screenFrame);
   int nodecount = AddLotsOfNodes();
@@ -572,7 +572,7 @@
 // Folder menu sizing and placement while deleting bookmarks
 // and scrolling tests.
 TEST_F(BookmarkBarFolderControllerTest, MenuPlacementWhileScrollingDeleting) {
-  scoped_nsobject<BookmarkBarFolderController> bbfc;
+  base::scoped_nsobject<BookmarkBarFolderController> bbfc;
   AddLotsOfNodes();
   bbfc.reset(SimpleBookmarkBarFolderController());
   [bbfc showWindow:bbfc.get()];
@@ -625,7 +625,7 @@
 
 // Make sure that we return the correct browser window.
 TEST_F(BookmarkBarFolderControllerTest, BrowserWindow) {
-  scoped_nsobject<BookmarkBarFolderController> controller(
+  base::scoped_nsobject<BookmarkBarFolderController> controller(
       SimpleBookmarkBarFolderController());
   EXPECT_EQ([bar_ browserWindow], [controller browserWindow]);
 }
@@ -680,9 +680,9 @@
 
 class BookmarkBarFolderControllerMenuTest : public CocoaProfileTest {
  public:
-  scoped_nsobject<NSView> parent_view_;
-  scoped_nsobject<ViewResizerPong> resizeDelegate_;
-  scoped_nsobject<BookmarkBarController> bar_;
+  base::scoped_nsobject<NSView> parent_view_;
+  base::scoped_nsobject<ViewResizerPong> resizeDelegate_;
+  base::scoped_nsobject<BookmarkBarController> bar_;
 
   virtual void SetUp() {
     CocoaProfileTest::SetUp();
@@ -725,10 +725,11 @@
   const std::string model_string("1b 2f:[ 2f1b 2f2f:[ 2f2f1b 2f2f2b "
       "2f2f3b ] 2f3b ] 3b 4f:[ 4f1f:[ 4f1f1b 4f1f2b 4f1f3b ] 4f2f:[ 4f2f1b "
       "4f2f2b 4f2f3b ] 4f3f:[ 4f3f1b 4f3f2b 4f3f3b ] ] 5b ");
-  model_test_utils::AddNodesFromModelString(model, root, model_string);
+  BookmarkModelTestUtils::AddNodesFromModelString(model, root, model_string);
 
   // Validate initial model.
-  std::string actualModelString = model_test_utils::ModelStringFromNode(root);
+  std::string actualModelString =
+      BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ(model_string, actualModelString);
 
   // Pop up a folder menu and drag in a button from the bar.
@@ -757,7 +758,7 @@
   const std::string expected_string("2f:[ 2f1b 1b 2f2f:[ 2f2f1b "
       "2f2f2b 2f2f3b ] 2f3b ] 3b 4f:[ 4f1f:[ 4f1f1b 4f1f2b 4f1f3b ] 4f2f:[ "
       "4f2f1b 4f2f2b 4f2f3b ] 4f3f:[ 4f3f1b 4f3f2b 4f3f3b ] ] 5b ");
-  EXPECT_EQ(expected_string, model_test_utils::ModelStringFromNode(root));
+  EXPECT_EQ(expected_string, BookmarkModelTestUtils::ModelStringFromNode(root));
 
   // Verify the window still appears by looking for its controller.
   EXPECT_TRUE([bar_ folderController]);
@@ -788,7 +789,7 @@
   [bar_ dragButton:draggedButton
                 to:[targetButton left]
               copy:NO];
-  EXPECT_EQ(model_string, model_test_utils::ModelStringFromNode(root));
+  EXPECT_EQ(model_string, BookmarkModelTestUtils::ModelStringFromNode(root));
   // Don't check the folder window since it's not supposed to be showing.
 }
 
@@ -798,10 +799,11 @@
   const std::string model_string("1b 2f:[ 2f1b 2f2f:[ 2f2f1b 2f2f2b "
       "2f2f3b ] 2f3b ] 3b 4f:[ 4f1f:[ 4f1f1b 4f1f2b 4f1f3b ] 4f2f:[ 4f2f1b "
       "4f2f2b 4f2f3b ] 4f3f:[ 4f3f1b 4f3f2b 4f3f3b ] ] 5b ");
-  model_test_utils::AddNodesFromModelString(model, root, model_string);
+  BookmarkModelTestUtils::AddNodesFromModelString(model, root, model_string);
 
   // Validate initial model.
-  std::string actualModelString = model_test_utils::ModelStringFromNode(root);
+  std::string actualModelString =
+      BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ(model_string, actualModelString);
 
   // Pop up a folder menu and copy in a button from the bar.
@@ -829,7 +831,7 @@
   const std::string expected_1("1b 2f:[ 2f1b 1b 2f2f:[ 2f2f1b "
     "2f2f2b 2f2f3b ] 2f3b ] 3b 4f:[ 4f1f:[ 4f1f1b 4f1f2b 4f1f3b ] 4f2f:[ "
     "4f2f1b 4f2f2b 4f2f3b ] 4f3f:[ 4f3f1b 4f3f2b 4f3f3b ] ] 5b ");
-  EXPECT_EQ(expected_1, model_test_utils::ModelStringFromNode(root));
+  EXPECT_EQ(expected_1, BookmarkModelTestUtils::ModelStringFromNode(root));
 
   // Gather the new frames.
   NSRect newToFolderFrame = [toFolder frame];
@@ -853,7 +855,7 @@
   const std::string expected_2("1b 2f:[ 2f1b 1b 2f2f:[ 2f2f1b "
       "2f2f2b 2f2f3b ] 2f3b ] 3b 1b 4f:[ 4f1f:[ 4f1f1b 4f1f2b 4f1f3b ] 4f2f:[ "
       "4f2f1b 4f2f2b 4f2f3b ] 4f3f:[ 4f3f1b 4f3f2b 4f3f3b ] ] 5b ");
-  EXPECT_EQ(expected_2, model_test_utils::ModelStringFromNode(root));
+  EXPECT_EQ(expected_2, BookmarkModelTestUtils::ModelStringFromNode(root));
 }
 
 TEST_F(BookmarkBarFolderControllerMenuTest, DragMoveBarBookmarkToSubfolder) {
@@ -862,10 +864,11 @@
   const std::string model_string("1b 2f:[ 2f1b 2f2f:[ 2f2f1b 2f2f2b "
       "2f2f3b ] 2f3b ] 3b 4f:[ 4f1f:[ 4f1f1b 4f1f2b 4f1f3b ] 4f2f:[ 4f2f1b "
       "4f2f2b 4f2f3b ] 4f3f:[ 4f3f1b 4f3f2b 4f3f3b ] ] 5b ");
-  model_test_utils::AddNodesFromModelString(model, root, model_string);
+  BookmarkModelTestUtils::AddNodesFromModelString(model, root, model_string);
 
   // Validate initial model.
-  std::string actualModelString = model_test_utils::ModelStringFromNode(root);
+  std::string actualModelString =
+      BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ(model_string, actualModelString);
 
   // Pop up a folder menu and a subfolder menu.
@@ -903,7 +906,7 @@
   const std::string expected_string("1b 2f:[ 2f1b 2f2f:[ 2f2f1b "
       "2f2f2b 2f2f3b ] 2f3b ] 3b 4f:[ 4f1f:[ 4f1f1b 4f1f2b 4f1f3b ] 4f2f:[ "
       "4f2f1b 4f2f2b 4f2f3b 5b ] 4f3f:[ 4f3f1b 4f3f2b 4f3f3b ] ] ");
-  EXPECT_EQ(expected_string, model_test_utils::ModelStringFromNode(root));
+  EXPECT_EQ(expected_string, BookmarkModelTestUtils::ModelStringFromNode(root));
 
   // Check button spacing.
   [folderController validateMenuSpacing];
@@ -927,10 +930,11 @@
   const std::string model_string("1b 2f:[ 2f1b 2f2f:[ 2f2f1b 2f2f2b "
       "2f2f3b ] 2f3b ] 3b 4f:[ 4f1f:[ 4f1f1b 4f1f2b 4f1f3b ] 4f2f:[ 4f2f1b "
       "4f2f2b 4f2f3b ] 4f3f:[ 4f3f1b 4f3f2b 4f3f3b ] ] 5b ");
-  model_test_utils::AddNodesFromModelString(model, root, model_string);
+  BookmarkModelTestUtils::AddNodesFromModelString(model, root, model_string);
 
   // Validate initial model.
-  std::string actualModelString = model_test_utils::ModelStringFromNode(root);
+  std::string actualModelString =
+      BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ(model_string, actualModelString);
 
   // Pop up a folder menu.
@@ -957,7 +961,7 @@
   const std::string expected_string("1b 2f:[ 2f1b 2f2f:[ 2f2f1b "
       "2f2f2b 2f2f3b ] 2f3b ] 3b 4f:[ 4f2f:[ 4f2f1b 4f2f2b 4f2f3b ] "
       "4f1f:[ 4f1f1b 4f1f2b 4f1f3b ] 4f3f:[ 4f3f1b 4f3f2b 4f3f3b ] ] 5b ");
-  EXPECT_EQ(expected_string, model_test_utils::ModelStringFromNode(root));
+  EXPECT_EQ(expected_string, BookmarkModelTestUtils::ModelStringFromNode(root));
 
   // The window should not have gone away.
   EXPECT_TRUE([bar_ folderController]);
@@ -976,10 +980,11 @@
   const std::string model_string("1b 2f:[ 2f1b 2f2f:[ 2f2f1b 2f2f2b "
       "2f2f3b ] 2f3b ] 3b 4f:[ 4f1f:[ 4f1f1b 4f1f2b 4f1f3b ] 4f2f:[ 4f2f1b "
       "4f2f2b 4f2f3b ] 4f3f:[ 4f3f1b 4f3f2b 4f3f3b ] ] 5b ");
-  model_test_utils::AddNodesFromModelString(model, root, model_string);
+  BookmarkModelTestUtils::AddNodesFromModelString(model, root, model_string);
 
   // Validate initial model.
-  std::string actualModelString = model_test_utils::ModelStringFromNode(root);
+  std::string actualModelString =
+      BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ(model_string, actualModelString);
 
   // Pop up a folder menu.
@@ -1001,7 +1006,7 @@
                             to:[targetButton top]
                           copy:NO];
   // The model should not have changed.
-  EXPECT_EQ(model_string, model_test_utils::ModelStringFromNode(root));
+  EXPECT_EQ(model_string, BookmarkModelTestUtils::ModelStringFromNode(root));
 
   // Check button spacing.
   [folderController validateMenuSpacing];
@@ -1013,10 +1018,11 @@
   const std::string model_string("1b 2f:[ 2f1b 2f2f:[ 2f2f1b 2f2f2b "
       "2f2f3b ] 2f3b ] 3b 4f:[ 4f1f:[ 4f1f1b 4f1f2b 4f1f3b ] 4f2f:[ 4f2f1b "
       "4f2f2b 4f2f3b ] 4f3f:[ 4f3f1b 4f3f2b 4f3f3b ] ] 5b ");
-  model_test_utils::AddNodesFromModelString(model, root, model_string);
+  BookmarkModelTestUtils::AddNodesFromModelString(model, root, model_string);
 
   // Validate initial model.
-  std::string actualModelString = model_test_utils::ModelStringFromNode(root);
+  std::string actualModelString =
+      BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ(model_string, actualModelString);
 
   // Pop up a folder menu and a subfolder menu.
@@ -1049,7 +1055,7 @@
   const std::string expected_string("1b 2f:[ 2f1b 2f2f:[ 2f2f1b 2f2f2b "
       "2f2f3b ] 2f3b ] 3b 4f:[ 4f1f:[ 4f1f1b 4f1f2b 4f1f3b ] 4f2f3b 4f2f:[ "
       "4f2f1b 4f2f2b ] 4f3f:[ 4f3f1b 4f3f2b 4f3f3b ] ] 5b ");
-  EXPECT_EQ(expected_string, model_test_utils::ModelStringFromNode(root));
+  EXPECT_EQ(expected_string, BookmarkModelTestUtils::ModelStringFromNode(root));
 
   // Check button spacing.
   [folderController validateMenuSpacing];
@@ -1064,10 +1070,11 @@
   const BookmarkNode* root = model->bookmark_bar_node();
   const std::string
       model_string("a b:[ b1 b2 b3 ] reallyReallyLongBookmarkName c ");
-  model_test_utils::AddNodesFromModelString(model, root, model_string);
+  BookmarkModelTestUtils::AddNodesFromModelString(model, root, model_string);
 
   // Validate initial model.
-  std::string actualModelString = model_test_utils::ModelStringFromNode(root);
+  std::string actualModelString =
+      BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ(model_string, actualModelString);
 
   // Pop up a folder menu.
@@ -1093,7 +1100,7 @@
   // Verify the model change.
   const std::string
       expected_string("a b:[ b1 reallyReallyLongBookmarkName b2 b3 ] c ");
-  EXPECT_EQ(expected_string, model_test_utils::ModelStringFromNode(root));
+  EXPECT_EQ(expected_string, BookmarkModelTestUtils::ModelStringFromNode(root));
   // Verify the window grew. Just test a reasonable width gain.
   CGFloat newWidth = NSWidth([toWindow frame]);
   EXPECT_LT(oldWidth + 30.0, newWidth);
@@ -1103,10 +1110,11 @@
   BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile());
   const BookmarkNode* root = model->bookmark_bar_node();
   const std::string model_string("1b 2f:[ 2f1b 2f2b 2f3b ] 3b 4b ");
-  model_test_utils::AddNodesFromModelString(model, root, model_string);
+  BookmarkModelTestUtils::AddNodesFromModelString(model, root, model_string);
 
   // Validate initial model.
-  std::string actualModelString = model_test_utils::ModelStringFromNode(root);
+  std::string actualModelString =
+      BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ(model_string, actualModelString);
 
   // Pop up a folder menu.
@@ -1166,10 +1174,11 @@
   BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile());
   const BookmarkNode* root = model->bookmark_bar_node();
   const std::string model_string("1b 2f:[ 2f1b 2f2b ] 3b ");
-  model_test_utils::AddNodesFromModelString(model, root, model_string);
+  BookmarkModelTestUtils::AddNodesFromModelString(model, root, model_string);
 
   // Validate initial model.
-  std::string actualModelString = model_test_utils::ModelStringFromNode(root);
+  std::string actualModelString =
+      BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ(model_string, actualModelString);
 
   // Find the main bar controller.
@@ -1201,10 +1210,11 @@
   BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile());
   const BookmarkNode* root = model->bookmark_bar_node();
   const std::string model_string("1b 2b 3b ");
-  model_test_utils::AddNodesFromModelString(model, root, model_string);
+  BookmarkModelTestUtils::AddNodesFromModelString(model, root, model_string);
 
   // Validate initial model.
-  std::string actualModelString = model_test_utils::ModelStringFromNode(root);
+  std::string actualModelString =
+      BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ(model_string, actualModelString);
 
   const BookmarkNode* parent = model->bookmark_bar_node();
@@ -1365,21 +1375,21 @@
   const BookmarkNode* root = model->bookmark_bar_node();
   const std::string model_string("1b 2f:[ 2f1b 2f2f:[ 2f2f1b 2f2f2b 2f2f3b ] "
                                  "2f3b ] 3b 4b ");
-  model_test_utils::AddNodesFromModelString(model, root, model_string);
+  BookmarkModelTestUtils::AddNodesFromModelString(model, root, model_string);
   const BookmarkNode* other = model->other_node();
   const std::string other_string("O1b O2b O3f:[ O3f1b O3f2f ] "
                                  "O4f:[ O4f1b O4f2f ] 05b ");
-  model_test_utils::AddNodesFromModelString(model, other, other_string);
+  BookmarkModelTestUtils::AddNodesFromModelString(model, other, other_string);
 
   // Validate initial model.
-  std::string actual = model_test_utils::ModelStringFromNode(root);
+  std::string actual = BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ(model_string, actual);
-  actual = model_test_utils::ModelStringFromNode(other);
+  actual = BookmarkModelTestUtils::ModelStringFromNode(other);
   EXPECT_EQ(other_string, actual);
 
   // Pop open a folder.
   BookmarkButton* button = [bar_ buttonWithTitleEqualTo:@"2f"];
-  scoped_nsobject<BookmarkBarFolderControllerDragData> folderController;
+  base::scoped_nsobject<BookmarkBarFolderControllerDragData> folderController;
   folderController.reset([[BookmarkBarFolderControllerDragData alloc]
                           initWithParentButton:button
                               parentController:nil
@@ -1392,14 +1402,14 @@
   // Gen up some dragging data.
   const BookmarkNode* newNode = other->GetChild(2);
   [folderController setDragDataNode:newNode];
-  scoped_nsobject<FakedDragInfo> dragInfo([[FakedDragInfo alloc] init]);
+  base::scoped_nsobject<FakedDragInfo> dragInfo([[FakedDragInfo alloc] init]);
   [dragInfo setDropLocation:[targetButton top]];
   [folderController dragBookmarkData:(id<NSDraggingInfo>)dragInfo.get()];
 
   // Verify the model.
   const std::string expected("1b 2f:[ O3f:[ O3f1b O3f2f ] 2f1b 2f2f:[ 2f2f1b "
                              "2f2f2b 2f2f3b ] 2f3b ] 3b 4b ");
-  actual = model_test_utils::ModelStringFromNode(root);
+  actual = BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ(expected, actual);
 
   // Now drag over a folder button.
@@ -1415,7 +1425,7 @@
   const std::string expectedA("1b 2f:[ O3f:[ O3f1b O3f2f ] 2f1b 2f2f:[ "
                               "2f2f1b 2f2f2b 2f2f3b O4f:[ O4f1b O4f2f ] ] "
                               "2f3b ] 3b 4b ");
-  actual = model_test_utils::ModelStringFromNode(root);
+  actual = BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ(expectedA, actual);
 
   // Check button spacing.
@@ -1427,10 +1437,10 @@
   const BookmarkNode* root = model->bookmark_bar_node();
   const std::string model_string("1b 2f:[ 2f1b 2f2f:[ 2f2f1b 2f2f2b 2f2f3b ] "
                                  "2f3b ] 3b 4b ");
-  model_test_utils::AddNodesFromModelString(model, root, model_string);
+  BookmarkModelTestUtils::AddNodesFromModelString(model, root, model_string);
 
   // Validate initial model.
-  std::string actual = model_test_utils::ModelStringFromNode(root);
+  std::string actual = BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ(model_string, actual);
 
   const BookmarkNode* folderNode = root->GetChild(1);
@@ -1438,7 +1448,7 @@
 
   // Pop open a folder.
   BookmarkButton* button = [bar_ buttonWithTitleEqualTo:@"2f"];
-  scoped_nsobject<BookmarkBarFolderControllerDragData> folderController;
+  base::scoped_nsobject<BookmarkBarFolderControllerDragData> folderController;
   folderController.reset([[BookmarkBarFolderControllerDragData alloc]
                           initWithParentButton:button
                               parentController:nil
@@ -1458,7 +1468,7 @@
   // Verify the model.
   const std::string expected("1b 2f:[ 2f2f:[ 2f2f1b 2f2f2b 2f2f3b ] "
                              "2f3b ] 3b 4b ");
-  actual = model_test_utils::ModelStringFromNode(root);
+  actual = BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ(expected, actual);
 
   // Check button spacing.
@@ -1470,10 +1480,10 @@
   const BookmarkNode* root = model->bookmark_bar_node();
   const std::string model_string("1b 2f:[ 2f1b 2f2f:[ 2f2f1b 2f2f2b 2f2f3b ] "
                                  "2f3b ] 3b 4b ");
-  model_test_utils::AddNodesFromModelString(model, root, model_string);
+  BookmarkModelTestUtils::AddNodesFromModelString(model, root, model_string);
 
   // Validate initial model.
-  std::string actual = model_test_utils::ModelStringFromNode(root);
+  std::string actual = BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ(model_string, actual);
 
   // Pop open a folder.
@@ -1503,7 +1513,7 @@
   // Verify the model.
   const std::string expected("1b 2f:[ SiteA SiteB 2f1b 2f2f:[ 2f2f1b 2f2f2b "
                              "2f2f3b ] 2f3b ] 3b 4b ");
-  actual = model_test_utils::ModelStringFromNode(root);
+  actual = BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ(expected, actual);
 
   // Check button spacing.
@@ -1515,10 +1525,10 @@
   const BookmarkNode* root = model->bookmark_bar_node();
   const std::string model_string("1b 2f:[ 2f1b 2f2f:[ 2f2f1b 2f2f2b 2f2f3b ] "
                                  "2f3b ] 3b 4b ");
-  model_test_utils::AddNodesFromModelString(model, root, model_string);
+  BookmarkModelTestUtils::AddNodesFromModelString(model, root, model_string);
 
   // Validate initial model.
-  std::string actual = model_test_utils::ModelStringFromNode(root);
+  std::string actual = BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ(model_string, actual);
 
   // Pop open the folder.
@@ -1574,10 +1584,11 @@
   const BookmarkNode* root = model->bookmark_bar_node();
   const std::string model_string("1b 2f:[ 2f1b 2f2f:[ 2f2f1b 2f2f2b ] "
                                  "2f3b ] 3b ");
-  model_test_utils::AddNodesFromModelString(model, root, model_string);
+  BookmarkModelTestUtils::AddNodesFromModelString(model, root, model_string);
 
   // Validate initial model.
-  std::string actualModelString = model_test_utils::ModelStringFromNode(root);
+  std::string actualModelString =
+      BookmarkModelTestUtils::ModelStringFromNode(root);
   EXPECT_EQ(model_string, actualModelString);
 
   // Open the folder menu and submenu.
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_hover_state.h b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_hover_state.h
index 20ea39e..8d8dea7 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_hover_state.h
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_hover_state.h
@@ -4,7 +4,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_button.h"
 
 // Hover state machine.  Encapsulates the hover state for
@@ -39,7 +39,7 @@
   // Like normal menus, hovering over a folder button causes it to
   // open.  This variable is set when a hover is initiated (but has
   // not necessarily fired yet).
-  scoped_nsobject<BookmarkButton> hoverButton_;
+  base::scoped_nsobject<BookmarkButton> hoverButton_;
 
   // We model hover state as a state machine with specific allowable
   // transitions.  |hoverState_| is the state of this machine at any
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_hover_state_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_hover_state_unittest.mm
index bb39d7d..7c441be 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_hover_state_unittest.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_hover_state_unittest.mm
@@ -19,14 +19,14 @@
 // these specific state transitions.
 TEST_F(BookmarkBarFolderHoverStateTest, HoverState) {
   base::MessageLoopForUI message_loop;
-  scoped_nsobject<BookmarkBarFolderHoverState> bbfhs;
+  base::scoped_nsobject<BookmarkBarFolderHoverState> bbfhs;
   bbfhs.reset([[BookmarkBarFolderHoverState alloc] init]);
 
   // Initial state.
   EXPECT_FALSE([bbfhs hoverButton]);
   ASSERT_EQ(kHoverStateClosed, [bbfhs hoverState]);
 
-  scoped_nsobject<BookmarkButton> button;
+  base::scoped_nsobject<BookmarkButton> button;
   button.reset([[BookmarkButton alloc] initWithFrame:NSMakeRect(0, 0, 20, 20)]);
 
   // Test transition from closed to opening.
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_view_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_view_unittest.mm
index 0550eab..b48b86a 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_view_unittest.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_view_unittest.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
@@ -133,9 +133,9 @@
     return [mock_button retain];
   }
 
-  scoped_nsobject<id> mock_controller_;
-  scoped_nsobject<BookmarkBarFolderView> view_;
-  scoped_nsobject<id> mock_button_;
+  base::scoped_nsobject<id> mock_controller_;
+  base::scoped_nsobject<BookmarkBarFolderView> view_;
+  base::scoped_nsobject<id> mock_button_;
 };
 
 TEST_F(BookmarkBarFolderViewTest, BookmarkButtonDragAndDrop) {
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_window.h b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_window.h
index 21115db..513512f 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_window.h
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_window.h
@@ -6,8 +6,6 @@
 #define CHROME_BROWSER_UI_COCOA_BOOKMARKS_BOOKMARK_BAR_FOLDER_WINDOW_H_
 
 #import <Cocoa/Cocoa.h>
-#include "base/memory/scoped_nsobject.h"
-
 
 // Window for a bookmark folder "menu".  This menu pops up when you
 // click on a bookmark button that represents a folder of bookmarks.
@@ -27,5 +25,4 @@
 @interface BookmarkBarFolderWindowScrollView : NSScrollView
 @end
 
-
 #endif  // CHROME_BROWSER_UI_COCOA_BOOKMARKS_BOOKMARK_BAR_FOLDER_WINDOW_H_
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_window.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_window.mm
index 06a6112..3d6a25b 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_window.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_window.mm
@@ -5,11 +5,11 @@
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_window.h"
 
 #import "base/logging.h"
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_constants.h"
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller.h"
-#import "third_party/GTM/AppKit/GTMNSColor+Luminance.h"
 #import "third_party/GTM/AppKit/GTMNSBezierPath+RoundRect.h"
+#import "third_party/GTM/AppKit/GTMNSColor+Luminance.h"
 
 using bookmarks::kBookmarkBarMenuCornerRadius;
 
@@ -60,13 +60,13 @@
   NSColor* endColor =
       [startColor gtm_colorAdjustedFor:GTMColorationLightPenumbra faded:YES];
 
-  scoped_nsobject<NSGradient> gradient(
-    [[NSGradient alloc] initWithColorsAndLocations:startColor, 0.0,
-                        midColor, 0.25,
-                        endColor, 0.5,
-                        midColor, 0.75,
-                        startColor, 1.0,
-                        nil]);
+  base::scoped_nsobject<NSGradient> gradient(
+      [[NSGradient alloc] initWithColorsAndLocations:startColor, 0.0,
+                                                     midColor, 0.25,
+                                                     endColor, 0.5,
+                                                     midColor, 0.75,
+                                                     startColor, 1.0,
+                                                     nil]);
   [gradient drawInBezierPath:bezier angle:0.0];
 }
 
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_window_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_window_unittest.mm
index d1d1005..2701dd6 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_window_unittest.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_window_unittest.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/memory/scoped_ptr.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_window.h"
 #include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -12,7 +12,7 @@
 };
 
 TEST_F(BookmarkBarFolderWindowTest, Borderless) {
-  scoped_nsobject<BookmarkBarFolderWindow> window_;
+  base::scoped_nsobject<BookmarkBarFolderWindow> window_;
   window_.reset([[BookmarkBarFolderWindow alloc]
                   initWithContentRect:NSMakeRect(0,0,20,20)
                             styleMask:0
@@ -29,8 +29,8 @@
                   initWithFrame:NSMakeRect(0, 0, 100, 100)]);
     [[test_window() contentView] addSubview:view_.get()];
   }
-  scoped_nsobject<BookmarkBarFolderWindowContentView> view_;
-  scoped_nsobject<BookmarkBarFolderWindowScrollView> scroll_view_;
+  base::scoped_nsobject<BookmarkBarFolderWindowContentView> view_;
+  base::scoped_nsobject<BookmarkBarFolderWindowScrollView> scroll_view_;
 };
 
 TEST_VIEW(BookmarkBarFolderWindowContentViewTest, view_);
@@ -43,7 +43,7 @@
                   initWithFrame:NSMakeRect(0, 0, 100, 100)]);
     [[test_window() contentView] addSubview:scroll_view_.get()];
   }
-  scoped_nsobject<BookmarkBarFolderWindowScrollView> scroll_view_;
+  base::scoped_nsobject<BookmarkBarFolderWindowScrollView> scroll_view_;
 };
 
 TEST_VIEW(BookmarkBarFolderWindowScrollViewTest, scroll_view_);
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view.mm
index 7c58eaa..096e376 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view.mm
@@ -26,7 +26,6 @@
 
 @interface BookmarkBarToolbarView (Private)
 - (void)drawAsDetachedBubble;
-- (void)drawAsDetachedInstantExtendedUI;
 @end
 
 @implementation BookmarkBarToolbarView
@@ -45,10 +44,7 @@
   if ([controller_ isInState:BookmarkBar::DETACHED] ||
       [controller_ isAnimatingToState:BookmarkBar::DETACHED] ||
       [controller_ isAnimatingFromState:BookmarkBar::DETACHED]) {
-    if (chrome::IsInstantExtendedAPIEnabled())
-      [self drawAsDetachedInstantExtendedUI];
-    else
-      [self drawAsDetachedBubble];
+    [self drawAsDetachedBubble];
   } else {
     NSPoint phase = [[self window] themePatternPhase];
     [[NSGraphicsContext currentContext] cr_setPatternPhase:phase forView:self];
@@ -57,98 +53,6 @@
 }
 
 - (void)drawAsDetachedBubble {
-  // The state of our morph; 1 is total bubble, 0 is the regular bar. We use it
-  // to morph the bubble to a regular bar (shape and colour).
-  CGFloat morph = [controller_ detachedMorphProgress];
-
-  NSRect bounds = [self bounds];
-
-  ThemeService* themeService = [controller_ themeService];
-  if (!themeService)
-    return;
-
-  gfx::ScopedNSGraphicsContextSaveGState scopedGState;
-
-  // Draw the background.
-  {
-    // CanvasSkiaPaint draws to the NSGraphicsContext during its destructor, so
-    // explicitly scope this.
-    //
-    // Paint the entire bookmark bar, even if the damage rect is much smaller
-    // because PaintBackgroundDetachedMode() assumes that area's origin is
-    // (0, 0) and that its size is the size of the bookmark bar.
-    //
-    // In practice, this sounds worse than it is because redraw time is still
-    // minimal compared to the pause between frames of animations. We were
-    // already repainting the rest of the bookmark bar below without setting a
-    // clip area, anyway. Also, the only time we weren't asked to redraw the
-    // whole bookmark bar is when the find bar is drawn over it.
-    gfx::CanvasSkiaPaint canvas(bounds, true);
-    gfx::Rect area(0, 0, NSWidth(bounds), NSHeight(bounds));
-
-    NtpBackgroundUtil::PaintBackgroundDetachedMode(themeService, &canvas,
-        area, [controller_ currentTabContentsHeight]);
-  }
-
-  // Draw our bookmark bar border on top of the background.
-  NSRect frameRect =
-      NSMakeRect(
-          morph * bookmarks::kNTPBookmarkBarPadding,
-          morph * bookmarks::kNTPBookmarkBarPadding,
-          NSWidth(bounds) - 2 * morph * bookmarks::kNTPBookmarkBarPadding,
-          NSHeight(bounds) - 2 * morph * bookmarks::kNTPBookmarkBarPadding);
-  // Now draw a bezier path with rounded rectangles around the area.
-  frameRect = NSInsetRect(frameRect, morph * 0.5, morph * 0.5);
-  NSBezierPath* border =
-      [NSBezierPath bezierPathWithRoundedRect:frameRect
-                                      xRadius:(morph * kBorderRadius)
-                                      yRadius:(morph * kBorderRadius)];
-
-  // Draw the rounded rectangle.
-  NSColor* toolbarColor =
-      themeService->GetNSColor(ThemeProperties::COLOR_TOOLBAR, true);
-  CGFloat alpha = morph * [toolbarColor alphaComponent];
-  [[toolbarColor colorWithAlphaComponent:alpha] set];  // Set with opacity.
-  [border fill];
-
-  // Fade in/out the background.
-  {
-    gfx::ScopedNSGraphicsContextSaveGState bgScopedState;
-    [border setClip];
-    NSGraphicsContext* context = [NSGraphicsContext currentContext];
-    CGContextRef cgContext = static_cast<CGContextRef>([context graphicsPort]);
-    CGContextSetAlpha(cgContext, 1 - morph);
-    CGContextBeginTransparencyLayer(cgContext, NULL);
-    [context cr_setPatternPhase:[[self window] themePatternPhase] forView:self];
-    [self drawBackgroundWithOpaque:YES];
-    CGContextEndTransparencyLayer(cgContext);
-  }
-
-  // Draw the border of the rounded rectangle.
-  NSColor* borderColor = themeService->GetNSColor(
-      ThemeProperties::COLOR_TOOLBAR_BUTTON_STROKE, true);
-  alpha = morph * [borderColor alphaComponent];
-  [[borderColor colorWithAlphaComponent:alpha] set];  // Set with opacity.
-  [border stroke];
-
-  // Fade in/out the divider.
-  // TODO(viettrungluu): It's not obvious that this divider lines up exactly
-  // with |BackgroundGradientView|'s (in fact, it probably doesn't).
-  NSColor* strokeColor = [self strokeColor];
-  alpha = (1 - morph) * [strokeColor alphaComponent];
-  [[strokeColor colorWithAlphaComponent:alpha] set];
-  NSBezierPath* divider = [NSBezierPath bezierPath];
-  NSPoint dividerStart =
-      NSMakePoint(morph * bookmarks::kNTPBookmarkBarPadding + morph * 0.5,
-                  morph * bookmarks::kNTPBookmarkBarPadding + morph * 0.5);
-  CGFloat dividerWidth =
-      NSWidth(bounds) - 2 * morph * bookmarks::kNTPBookmarkBarPadding - 2 * 0.5;
-  [divider moveToPoint:dividerStart];
-  [divider relativeLineToPoint:NSMakePoint(dividerWidth, 0)];
-  [divider stroke];
-}
-
-- (void)drawAsDetachedInstantExtendedUI {
   CGFloat morph = [controller_ detachedMorphProgress];
   NSRect bounds = [self bounds];
   ThemeService* themeService = [controller_ themeService];
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view_unittest.mm
index e820897..f7a984b 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view_unittest.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view_unittest.mm
@@ -4,7 +4,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/themes/theme_properties.h"
 #include "chrome/browser/themes/theme_service.h"
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h"
@@ -94,14 +94,14 @@
   BookmarkBarToolbarViewTest() {
     controller_.reset([[DrawDetachedBarFakeController alloc] init]);
     NSRect frame = NSMakeRect(0, 0, 400, 40);
-    scoped_nsobject<BookmarkBarToolbarView> view(
+    base::scoped_nsobject<BookmarkBarToolbarView> view(
         [[BookmarkBarToolbarView alloc] initWithFrame:frame]);
     view_ = view.get();
     [[test_window() contentView] addSubview:view_];
     [view_ setController:controller_.get()];
   }
 
-  scoped_nsobject<DrawDetachedBarFakeController> controller_;
+  base::scoped_nsobject<DrawDetachedBarFakeController> controller_;
   BookmarkBarToolbarView* view_;
 };
 
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_view.h b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_view.h
index ef05ec6..f5083d0 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_view.h
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_view.h
@@ -10,14 +10,13 @@
 
 #import <Cocoa/Cocoa.h>
 
-#import "chrome/browser/ui/cocoa/background_gradient_view.h"
 #import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
 
 @class BookmarkBarController;
 @class BookmarkBarItemContainer;
 @class BookmarkBarTextField;
 
-@interface BookmarkBarView : BackgroundGradientView {
+@interface BookmarkBarView : NSView {
  @private
   BOOL dropIndicatorShown_;
   CGFloat dropIndicatorPosition_;  // x position
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_view.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_view.mm
index 1a50f7c..b468c6f 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_view.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_view.mm
@@ -121,10 +121,6 @@
     [controller_ clearDropInsertionPos];
 }
 
-- (void)drawRect:(NSRect)dirtyRect {
-  [super drawRect:dirtyRect];
-}
-
 // Shim function to assist in unit testing.
 - (BOOL)dragClipboardContainsBookmarks {
   return bookmark_pasteboard_helper_mac::PasteboardContainsBookmarks(
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_view_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_view_unittest.mm
index 902bb7f..8456dfa 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_view_unittest.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_view_unittest.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
@@ -201,7 +201,7 @@
     view_.reset([[BookmarkBarView alloc] init]);
   }
 
-  scoped_nsobject<BookmarkBarView> view_;
+  base::scoped_nsobject<BookmarkBarView> view_;
 };
 
 TEST_F(BookmarkBarViewTest, CanDragWindow) {
@@ -209,8 +209,8 @@
 }
 
 TEST_F(BookmarkBarViewTest, BookmarkButtonDragAndDrop) {
-  scoped_nsobject<FakeBookmarkDraggingInfo>
-      info([[FakeBookmarkDraggingInfo alloc] init]);
+  base::scoped_nsobject<FakeBookmarkDraggingInfo> info(
+      [[FakeBookmarkDraggingInfo alloc] init]);
   [view_ setController:info.get()];
   [info reset];
 
@@ -222,12 +222,13 @@
                              ASCIIToUTF16("Test Bookmark"),
                              GURL("http://www.exmaple.com"));
 
-  scoped_nsobject<BookmarkButtonCell> button_cell(
+  base::scoped_nsobject<BookmarkButtonCell> button_cell(
       [[BookmarkButtonCell buttonCellForNode:node
                                         text:nil
                                        image:nil
                               menuController:nil] retain]);
-  scoped_nsobject<BookmarkButton> dragged_button([[BookmarkButton alloc] init]);
+  base::scoped_nsobject<BookmarkButton> dragged_button(
+      [[BookmarkButton alloc] init]);
   [dragged_button setCell:button_cell];
   [info setDraggingSource:dragged_button.get()];
   [info setDragDataType:kBookmarkButtonDragType];
@@ -243,8 +244,8 @@
 
 // When dragging bookmarks across profiles, we should always copy, never move.
 TEST_F(BookmarkBarViewTest, BookmarkButtonDragAndDropAcrossProfiles) {
-  scoped_nsobject<FakeBookmarkDraggingInfo>
-  info([[FakeBookmarkDraggingInfo alloc] init]);
+  base::scoped_nsobject<FakeBookmarkDraggingInfo> info(
+      [[FakeBookmarkDraggingInfo alloc] init]);
   [view_ setController:info.get()];
   [info reset];
 
@@ -263,12 +264,13 @@
                              ASCIIToUTF16("Test Bookmark"),
                              GURL("http://www.exmaple.com"));
 
-  scoped_nsobject<BookmarkButtonCell> button_cell(
+  base::scoped_nsobject<BookmarkButtonCell> button_cell(
       [[BookmarkButtonCell buttonCellForNode:node
                                         text:nil
                                        image:nil
                               menuController:nil] retain]);
-  scoped_nsobject<BookmarkButton> dragged_button([[BookmarkButton alloc] init]);
+  base::scoped_nsobject<BookmarkButton> dragged_button(
+      [[BookmarkButton alloc] init]);
   [dragged_button setCell:button_cell];
   [info setDraggingSource:dragged_button.get()];
   [info setDragDataType:kBookmarkButtonDragType];
@@ -283,8 +285,8 @@
 }
 
 TEST_F(BookmarkBarViewTest, URLDragAndDrop) {
-  scoped_nsobject<FakeBookmarkDraggingInfo>
-      info([[FakeBookmarkDraggingInfo alloc] init]);
+  base::scoped_nsobject<FakeBookmarkDraggingInfo> info(
+      [[FakeBookmarkDraggingInfo alloc] init]);
   [view_ setController:info.get()];
   [info reset];
 
@@ -301,12 +303,13 @@
 }
 
 TEST_F(BookmarkBarViewTest, BookmarkButtonDropIndicator) {
-  scoped_nsobject<FakeBookmarkDraggingInfo>
-      info([[FakeBookmarkDraggingInfo alloc] init]);
+  base::scoped_nsobject<FakeBookmarkDraggingInfo> info(
+      [[FakeBookmarkDraggingInfo alloc] init]);
   [view_ setController:info.get()];
   [info reset];
 
-  scoped_nsobject<BookmarkButton> dragged_button([[BookmarkButton alloc] init]);
+  base::scoped_nsobject<BookmarkButton> dragged_button(
+      [[BookmarkButton alloc] init]);
   [info setDraggingSource:dragged_button.get()];
   [info setDragDataType:kBookmarkButtonDragType];
   EXPECT_FALSE([info draggingEnteredCalled]);
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bubble_controller_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bubble_controller_unittest.mm
index 5cad07e..1405f7c 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bubble_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bubble_controller_unittest.mm
@@ -5,7 +5,7 @@
 #import <Cocoa/Cocoa.h>
 
 #include "base/basictypes.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
@@ -252,8 +252,8 @@
         GURL("http://www.google.com"));
   EXPECT_EQ(edits_, 0);
 
-  scoped_nsobject<BookmarkPulseObserver> observer([[BookmarkPulseObserver alloc]
-                                                    init]);
+  base::scoped_nsobject<BookmarkPulseObserver> observer(
+      [[BookmarkPulseObserver alloc] init]);
   EXPECT_EQ([observer notifications], 0);
   BookmarkBubbleController* controller = ControllerForNode(node);
   EXPECT_TRUE(controller);
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_button.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_button.mm
index 876ac6d..43aff5d 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_button.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_button.mm
@@ -7,13 +7,15 @@
 #include <cmath>
 
 #include "base/logging.h"
-#import "base/memory/scoped_nsobject.h"
+#include "base/mac/foundation_util.h"
+#import "base/mac/scoped_nsobject.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_window.h"
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.h"
 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
 #import "chrome/browser/ui/cocoa/view_id_util.h"
 #include "content/public/browser/user_metrics.h"
+#include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
 
 using content::UserMetricsAction;
 
@@ -383,6 +385,29 @@
   return kDraggableButtonMixinDidWork;
 }
 
+- (BOOL)isOpaque {
+  // Make this control opaque so that sub pixel anti aliasing works when core
+  // animation is enabled.
+  return YES;
+}
+
+- (void)drawRect:(NSRect)rect {
+  // Draw the toolbar background.
+  {
+    gfx::ScopedNSGraphicsContextSaveGState scopedGSState;
+    NSView* toolbarView = [[self superview] superview];
+    NSRect frame = [self convertRect:[self bounds] toView:toolbarView];
+
+    NSAffineTransform* transform = [NSAffineTransform transform];
+    [transform translateXBy:-NSMinX(frame) yBy:-NSMinY(frame)];
+    [transform concat];
+
+    [toolbarView drawRect:[toolbarView bounds]];
+  }
+
+  [super drawRect:rect];
+}
+
 @end
 
 @implementation BookmarkButton(Private)
@@ -409,35 +434,24 @@
 
 - (NSImage*)dragImage {
   NSRect bounds = [self bounds];
+  base::scoped_nsobject<NSImage> image(
+      [[NSImage alloc] initWithSize:bounds.size]);
+  [image lockFocusFlipped:[self isFlipped]];
 
-  // Grab the image from the screen and put it in an |NSImage|. We can't use
-  // this directly since we need to clip it and set its opacity. This won't work
-  // if the source view is clipped. Fortunately, we don't display clipped
-  // bookmark buttons.
-  [self lockFocus];
-  scoped_nsobject<NSBitmapImageRep>
-      bitmap([[NSBitmapImageRep alloc] initWithFocusedViewRect:bounds]);
-  [self unlockFocus];
-  scoped_nsobject<NSImage> image([[NSImage alloc] initWithSize:[bitmap size]]);
-  [image addRepresentation:bitmap];
+  NSGraphicsContext* context = [NSGraphicsContext currentContext];
+  CGContextRef cgContext = static_cast<CGContextRef>([context graphicsPort]);
+  CGContextBeginTransparencyLayer(cgContext, 0);
+  CGContextSetAlpha(cgContext, kDragImageOpacity);
 
-  // Make an autoreleased |NSImage|, which will be returned, and draw into it.
-  // By default, the |NSImage| will be completely transparent.
-  NSImage* dragImage =
-      [[[NSImage alloc] initWithSize:[bitmap size]] autorelease];
-  [dragImage lockFocus];
-
-  // Draw the image with the appropriate opacity, clipping it tightly.
-  GradientButtonCell* cell = static_cast<GradientButtonCell*>([self cell]);
-  DCHECK([cell isKindOfClass:[GradientButtonCell class]]);
+  GradientButtonCell* cell =
+      base::mac::ObjCCastStrict<GradientButtonCell>([self cell]);
   [[cell clipPathForFrame:bounds inView:self] setClip];
-  [image drawAtPoint:NSMakePoint(0, 0)
-            fromRect:NSMakeRect(0, 0, NSWidth(bounds), NSHeight(bounds))
-           operation:NSCompositeSourceOver
-            fraction:kDragImageOpacity];
+  [cell drawWithFrame:bounds inView:self];
 
-  [dragImage unlockFocus];
-  return dragImage;
+  CGContextEndTransparencyLayer(cgContext);
+  [image unlockFocus];
+
+  return image.autorelease();
 }
 
 @end  // @implementation BookmarkButton(Private)
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.h b/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.h
index 32b13f4..0a4b7da 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.h
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.h
@@ -30,10 +30,10 @@
   BOOL drawFolderArrow_;
 
   // Arrow for folders
-  scoped_nsobject<NSImage> arrowImage_;
+  base::scoped_nsobject<NSImage> arrowImage_;
 
   // Text color for title.
-  scoped_nsobject<NSColor> textColor_;
+  base::scoped_nsobject<NSColor> textColor_;
 }
 
 @property(nonatomic, readwrite, assign) const BookmarkNode* bookmarkNode;
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.mm
index 6aaab33..a377295 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.mm
@@ -215,7 +215,8 @@
 
 // We must reapply the text color after any setTitle: call
 - (void)applyTextColor {
-  scoped_nsobject<NSMutableParagraphStyle> style([NSMutableParagraphStyle new]);
+  base::scoped_nsobject<NSMutableParagraphStyle> style(
+      [NSMutableParagraphStyle new]);
   [style setAlignment:NSLeftTextAlignment];
   NSDictionary* dict = [NSDictionary
                          dictionaryWithObjectsAndKeys:textColor_,
@@ -224,9 +225,8 @@
                          style.get(), NSParagraphStyleAttributeName,
                          [NSNumber numberWithFloat:0.2], NSKernAttributeName,
                          nil];
-  scoped_nsobject<NSAttributedString> ats([[NSAttributedString alloc]
-                                            initWithString:[self title]
-                                                attributes:dict]);
+  base::scoped_nsobject<NSAttributedString> ats(
+      [[NSAttributedString alloc] initWithString:[self title] attributes:dict]);
   [self setAttributedTitle:ats.get()];
 }
 
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell_unittest.mm
index baeccef..db26ae7 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell_unittest.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell_unittest.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
@@ -43,8 +43,8 @@
 // Make sure it's not totally bogus
 TEST_F(BookmarkButtonCellTest, SizeForBounds) {
   NSRect frame = NSMakeRect(0, 0, 50, 30);
-  scoped_nsobject<NSButton> view([[NSButton alloc] initWithFrame:frame]);
-  scoped_nsobject<BookmarkButtonCell> cell(
+  base::scoped_nsobject<NSButton> view([[NSButton alloc] initWithFrame:frame]);
+  base::scoped_nsobject<BookmarkButtonCell> cell(
       [[BookmarkButtonCell alloc] initTextCell:@"Testing"]);
   [view setCell:cell.get()];
   [[test_window() contentView] addSubview:view];
@@ -58,14 +58,14 @@
 // Make sure icon-only buttons are squeezed tightly.
 TEST_F(BookmarkButtonCellTest, IconOnlySqueeze) {
   NSRect frame = NSMakeRect(0, 0, 50, 30);
-  scoped_nsobject<NSButton> view([[NSButton alloc] initWithFrame:frame]);
-  scoped_nsobject<BookmarkButtonCell> cell(
+  base::scoped_nsobject<NSButton> view([[NSButton alloc] initWithFrame:frame]);
+  base::scoped_nsobject<BookmarkButtonCell> cell(
       [[BookmarkButtonCell alloc] initTextCell:@"Testing"]);
   [view setCell:cell.get()];
   [[test_window() contentView] addSubview:view];
 
   ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-  scoped_nsobject<NSImage> image(
+  base::scoped_nsobject<NSImage> image(
       rb.GetNativeImageNamed(IDR_DEFAULT_FAVICON).CopyNSImage());
   EXPECT_TRUE(image.get());
 
@@ -87,7 +87,7 @@
 
 // Make sure the default from the base class is overridden.
 TEST_F(BookmarkButtonCellTest, MouseEnterStuff) {
-  scoped_nsobject<BookmarkButtonCell> cell(
+  base::scoped_nsobject<BookmarkButtonCell> cell(
       [[BookmarkButtonCell alloc] initTextCell:@"Testing"]);
   // Setting the menu should have no affect since we either share or
   // dynamically compose the menu given a node.
@@ -106,7 +106,7 @@
 
 TEST_F(BookmarkButtonCellTest, BookmarkNode) {
   BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile());
-  scoped_nsobject<BookmarkButtonCell> cell(
+  base::scoped_nsobject<BookmarkButtonCell> cell(
       [[BookmarkButtonCell alloc] initTextCell:@"Testing"]);
 
   const BookmarkNode* node = model->bookmark_bar_node();
@@ -119,11 +119,11 @@
 }
 
 TEST_F(BookmarkButtonCellTest, BookmarkMouseForwarding) {
-  scoped_nsobject<BookmarkButtonCell> cell(
+  base::scoped_nsobject<BookmarkButtonCell> cell(
       [[BookmarkButtonCell alloc] initTextCell:@"Testing"]);
-  scoped_nsobject<ButtonRemembersMouseEnterExit>
-    button([[ButtonRemembersMouseEnterExit alloc]
-             initWithFrame:NSMakeRect(0,0,50,50)]);
+  base::scoped_nsobject<ButtonRemembersMouseEnterExit> button(
+      [[ButtonRemembersMouseEnterExit alloc]
+          initWithFrame:NSMakeRect(0, 0, 50, 50)]);
   [button setCell:cell.get()];
   EXPECT_EQ(0, button.get()->enters_);
   EXPECT_EQ(0, button.get()->exits_);
@@ -147,7 +147,8 @@
 
 // Confirms a cell created in a nib is initialized properly
 TEST_F(BookmarkButtonCellTest, Awake) {
-  scoped_nsobject<BookmarkButtonCell> cell([[BookmarkButtonCell alloc] init]);
+  base::scoped_nsobject<BookmarkButtonCell> cell(
+      [[BookmarkButtonCell alloc] init]);
   [cell awakeFromNib];
   EXPECT_EQ(NSLeftTextAlignment, [cell alignment]);
 }
@@ -159,11 +160,11 @@
   const BookmarkNode* node = model->AddURL(bar, bar->child_count(),
                                            ASCIIToUTF16("title"),
                                            GURL("http://www.google.com"));
-  scoped_nsobject<BookmarkButtonCell> cell(
-    [[BookmarkButtonCell alloc] initForNode:node
-                                       text:@"small"
-                                      image:nil
-                             menuController:nil]);
+  base::scoped_nsobject<BookmarkButtonCell> cell(
+      [[BookmarkButtonCell alloc] initForNode:node
+                                         text:@"small"
+                                        image:nil
+                               menuController:nil]);
   EXPECT_TRUE(cell.get());
 
   NSSize size = [cell cellSize];
@@ -184,9 +185,9 @@
                                            ASCIIToUTF16("title"),
                                            GURL("http://www.google.com"));
 
-  scoped_nsobject<GradientButtonCell> gradient_cell(
+  base::scoped_nsobject<GradientButtonCell> gradient_cell(
       [[GradientButtonCell alloc] initTextCell:@"Testing"]);
-  scoped_nsobject<BookmarkButtonCell> bookmark_cell(
+  base::scoped_nsobject<BookmarkButtonCell> bookmark_cell(
       [[BookmarkButtonCell alloc] initForNode:node
                                          text:@"small"
                                         image:nil
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_button_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_button_unittest.mm
index 6e0b5d3..a6cb9d2 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_button_unittest.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_button_unittest.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
@@ -65,14 +65,14 @@
 
 // Make sure nothing leaks
 TEST_F(BookmarkButtonTest, Create) {
-  scoped_nsobject<BookmarkButton> button;
+  base::scoped_nsobject<BookmarkButton> button;
   button.reset([[BookmarkButton alloc] initWithFrame:NSMakeRect(0,0,500,500)]);
 }
 
 // Test folder and empty node queries.
 TEST_F(BookmarkButtonTest, FolderAndEmptyOrNot) {
-  scoped_nsobject<BookmarkButton> button;
-  scoped_nsobject<BookmarkButtonCell> cell;
+  base::scoped_nsobject<BookmarkButton> button;
+  base::scoped_nsobject<BookmarkButtonCell> cell;
 
   button.reset([[BookmarkButton alloc] initWithFrame:NSMakeRect(0,0,500,500)]);
   cell.reset([[BookmarkButtonCell alloc] initTextCell:@"hi mom"]);
@@ -107,10 +107,10 @@
       cocoa_test_event_utils::MouseEventAtPoint(NSMakePoint(10,10),
                                                 NSMouseMoved,
                                                 0);
-  scoped_nsobject<BookmarkButton> button;
-  scoped_nsobject<BookmarkButtonCell> cell;
-  scoped_nsobject<FakeButtonDelegate>
-      delegate([[FakeButtonDelegate alloc] init]);
+  base::scoped_nsobject<BookmarkButton> button;
+  base::scoped_nsobject<BookmarkButtonCell> cell;
+  base::scoped_nsobject<FakeButtonDelegate> delegate(
+      [[FakeButtonDelegate alloc] init]);
   button.reset([[BookmarkButton alloc] initWithFrame:NSMakeRect(0,0,500,500)]);
   cell.reset([[BookmarkButtonCell alloc] initTextCell:@"hi mom"]);
   [button setCell:cell];
@@ -130,10 +130,10 @@
 }
 
 TEST_F(BookmarkButtonTest, DragToTrash) {
-  scoped_nsobject<BookmarkButton> button;
-  scoped_nsobject<BookmarkButtonCell> cell;
-  scoped_nsobject<FakeButtonDelegate>
-      delegate([[FakeButtonDelegate alloc] init]);
+  base::scoped_nsobject<BookmarkButton> button;
+  base::scoped_nsobject<BookmarkButtonCell> cell;
+  base::scoped_nsobject<FakeButtonDelegate> delegate(
+      [[FakeButtonDelegate alloc] init]);
   button.reset([[BookmarkButton alloc] initWithFrame:NSMakeRect(0,0,500,500)]);
   cell.reset([[BookmarkButtonCell alloc] initTextCell:@"hi mom"]);
   [button setCell:cell];
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_context_menu_cocoa_controller.h b/chrome/browser/ui/cocoa/bookmarks/bookmark_context_menu_cocoa_controller.h
index 7f4828c..61a49f0 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_context_menu_cocoa_controller.h
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_context_menu_cocoa_controller.h
@@ -8,7 +8,7 @@
 #import <Cocoa/Cocoa.h>
 
 #include "base/basictypes.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 
 @class BookmarkBarController;
@@ -41,7 +41,7 @@
 
   // Controller responsible for creating a Cocoa NSMenu from the cross-platform
   // SimpleMenuModel owned by the |bookmarkContextMenuController_|.
-  scoped_nsobject<MenuController> menuController_;
+  base::scoped_nsobject<MenuController> menuController_;
 }
 
 // Initializes the BookmarkContextMenuCocoaController for the given bookmark
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_drag_drop_cocoa.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_drag_drop_cocoa.mm
index 3c1889d..c69a17d 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_drag_drop_cocoa.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_drag_drop_cocoa.mm
@@ -9,7 +9,7 @@
 #include <cmath>
 
 #include "base/logging.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/message_loop.h"
 #include "base/strings/string16.h"
 #include "base/strings/sys_string_conversions.h"
@@ -69,9 +69,8 @@
 
   NSColor* color = [NSColor blackColor];
   NSColor* alpha_color = [color colorWithAlphaComponent:0.0];
-  scoped_nsobject<NSGradient> mask(
-      [[NSGradient alloc] initWithStartingColor:color
-                                    endingColor:alpha_color]);
+  base::scoped_nsobject<NSGradient> mask(
+      [[NSGradient alloc] initWithStartingColor:color endingColor:alpha_color]);
   // Draw the gradient mask.
   CGContextSetBlendMode(context, kCGBlendModeDestinationIn);
   [mask drawFromPoint:NSMakePoint(NSMaxX(frame) - gradient_width,
@@ -101,9 +100,8 @@
       [NSDictionary dictionaryWithObject:[NSFont systemFontOfSize:
                                            [NSFont smallSystemFontSize]]
                                   forKey:NSFontAttributeName];
-  scoped_nsobject<NSAttributedString> rich_title(
-      [[NSAttributedString alloc] initWithString:ns_title
-                                      attributes:attrs]);
+  base::scoped_nsobject<NSAttributedString> rich_title(
+      [[NSAttributedString alloc] initWithString:ns_title attributes:attrs]);
 
   // Set up sizes and locations for rendering.
   const CGFloat kIconMargin = 2.0;  // Gap between icon and text.
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_base_controller.h b/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_base_controller.h
index e8107ea..6e1162a 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_base_controller.h
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_base_controller.h
@@ -7,10 +7,10 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
-#include "chrome/browser/bookmarks/bookmark_editor.h"
 #include "chrome/browser/bookmarks/bookmark_expanded_state_tracker.h"
+#include "chrome/browser/ui/bookmarks/bookmark_editor.h"
 
 class BookmarkEditorBaseControllerBridge;
 class BookmarkModel;
@@ -41,10 +41,10 @@
   BOOL creatingNewFolders_;  // True while in createNewFolders.
   // An array of BookmarkFolderInfo where each item describes a folder in the
   // BookmarkNode structure.
-  scoped_nsobject<NSArray> folderTreeArray_;
+  base::scoped_nsobject<NSArray> folderTreeArray_;
   // Bound to the table view giving a path to the current selections, of which
   // there should only ever be one.
-  scoped_nsobject<NSArray> tableSelectionPaths_;
+  base::scoped_nsobject<NSArray> tableSelectionPaths_;
   // C++ bridge object that observes the BookmarkModel for me.
   scoped_ptr<BookmarkEditorBaseControllerBridge> observer_;
 }
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_base_controller_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_base_controller_unittest.mm
index c66f651..1efc1e7 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_base_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_base_controller_unittest.mm
@@ -4,7 +4,6 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
@@ -95,8 +94,7 @@
   }
 
   virtual Browser* CreateBrowser() OVERRIDE {
-    Browser::CreateParams native_params(profile(),
-                                        chrome::HOST_DESKTOP_TYPE_NATIVE);
+    Browser::CreateParams native_params(profile(), chrome::GetActiveDesktop());
     return chrome::CreateBrowserWithTestWindowForParams(&native_params);
   }
 };
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_controller.h b/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_controller.h
index da3ed89..abf67cb 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_controller.h
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_controller.h
@@ -13,7 +13,7 @@
 @interface BookmarkEditorController : BookmarkEditorBaseController {
  @private
   const BookmarkNode* node_;  // weak; owned by the model
-  scoped_nsobject<NSString> initialUrl_;
+  base::scoped_nsobject<NSString> initialUrl_;
   NSString* displayURL_;  // Bound to a text field in the dialog.
   IBOutlet NSTextField* urlField_;
   IBOutlet NSTextField* nameTextField_;
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_folder_target_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_folder_target_unittest.mm
index 2ca188d..c6019a9 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_folder_target_unittest.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_folder_target_unittest.mm
@@ -57,8 +57,8 @@
   // Make sure we get an addNew
   [[controller expect] addNewFolderControllerWithParentButton:sender];
 
-  scoped_nsobject<BookmarkFolderTarget> target(
-    [[BookmarkFolderTarget alloc] initWithController:controller]);
+  base::scoped_nsobject<BookmarkFolderTarget> target(
+      [[BookmarkFolderTarget alloc] initWithController:controller]);
 
   [target openBookmarkFolderFromButton:sender];
   EXPECT_OCMOCK_VERIFY(controller);
@@ -82,7 +82,7 @@
   // any subfolders).
   [[controller expect] closeBookmarkFolder:controller];
 
-  scoped_nsobject<BookmarkFolderTarget> target(
+  base::scoped_nsobject<BookmarkFolderTarget> target(
       [[BookmarkFolderTarget alloc] initWithController:controller]);
 
   [target openBookmarkFolderFromButton:sender];
@@ -111,8 +111,8 @@
   // close and open.
   [[controller expect] addNewFolderControllerWithParentButton:sender];
 
-  scoped_nsobject<BookmarkFolderTarget> target(
-    [[BookmarkFolderTarget alloc] initWithController:controller]);
+  base::scoped_nsobject<BookmarkFolderTarget> target(
+      [[BookmarkFolderTarget alloc] initWithController:controller]);
 
   [target openBookmarkFolderFromButton:sender];
   EXPECT_OCMOCK_VERIFY(controller);
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge.h b/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge.h
index 747a480..1d8fc04 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge.h
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge.h
@@ -22,7 +22,7 @@
 
 #include <map>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/bookmarks/bookmark_model_observer.h"
 #import "chrome/browser/ui/cocoa/main_menu_item.h"
 
@@ -139,7 +139,7 @@
   BookmarkMenuCocoaController* controller_;  // strong
 
   // The folder image so we can use one copy for all.
-  scoped_nsobject<NSImage> folder_image_;
+  base::scoped_nsobject<NSImage> folder_image_;
 
   // In order to appropriately update items in the bookmark menu, without
   // forcing a rebuild, map the model's nodes to menu items.
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge.mm
index 1c2f80b..566f88a 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge.mm
@@ -9,6 +9,7 @@
 #import "chrome/browser/app_controller_mac.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
+#include "chrome/browser/prefs/incognito_mode_prefs.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/browser_list.h"
@@ -256,6 +257,12 @@
     // Add menus for 'Open All Bookmarks'.
     [menu addItem:[NSMenuItem separatorItem]];
     bool enabled = child_count != 0;
+
+    IncognitoModePrefs::Availability incognito_availability =
+        IncognitoModePrefs::GetAvailability(profile_->GetPrefs());
+    bool incognito_enabled =
+        enabled && incognito_availability != IncognitoModePrefs::DISABLED;
+
     AddItemToMenu(IDC_BOOKMARK_BAR_OPEN_ALL,
                   IDS_BOOKMARK_BAR_OPEN_ALL,
                   node, menu, enabled);
@@ -264,7 +271,7 @@
                   node, menu, enabled);
     AddItemToMenu(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO,
                   IDS_BOOKMARK_BAR_OPEN_ALL_INCOGNITO,
-                  node, menu, enabled);
+                  node, menu, incognito_enabled);
   }
 }
 
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge_unittest.mm
index 73bc86d..e5eedd5 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge_unittest.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge_unittest.mm
@@ -4,7 +4,6 @@
 
 #import <AppKit/AppKit.h>
 
-#import "base/memory/scoped_nsobject.h"
 #include "base/strings/string16.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_cocoa_controller.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_cocoa_controller.mm
index 36b9705..93e7c64 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_cocoa_controller.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_cocoa_controller.mm
@@ -13,6 +13,7 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge.h"
+#import "chrome/browser/ui/cocoa/l10n_util.h"
 #include "chrome/browser/ui/host_desktop.h"
 #include "content/public/browser/user_metrics.h"
 #import "ui/base/cocoa/cocoa_event_utils.h"
@@ -40,14 +41,9 @@
 
 + (NSString*)tooltipForNode:(const BookmarkNode*)node {
   NSString* title = base::SysUTF16ToNSString(node->GetTitle());
-  std::string url_string = node->url().possibly_invalid_spec();
-  NSString* url = [NSString stringWithUTF8String:url_string.c_str()];
-  if ([title length] == 0)
-    return url;
-  else if ([url length] == 0 || [url isEqualToString:title])
-    return title;
-  else
-    return [NSString stringWithFormat:@"%@\n%@", title, url];
+  std::string urlString = node->url().possibly_invalid_spec();
+  NSString* url = base::SysUTF8ToNSString(urlString);
+  return cocoa_l10n_util::TooltipForURLAndTitle(url, title);
 }
 
 - (id)initWithBridge:(BookmarkMenuBridge*)bridge
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_cocoa_controller_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_cocoa_controller_unittest.mm
index fddc7fb..e4b7b4e 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_cocoa_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_cocoa_controller_unittest.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #include "base/strings/string16.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
@@ -76,7 +76,7 @@
   FakeBookmarkMenuController* controller() { return controller_.get(); }
 
  private:
-  scoped_nsobject<FakeBookmarkMenuController> controller_;
+  base::scoped_nsobject<FakeBookmarkMenuController> controller_;
 };
 
 TEST_F(BookmarkMenuCocoaControllerTest, TestOpenItem) {
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_model_observer_for_cocoa.h b/chrome/browser/ui/cocoa/bookmarks/bookmark_model_observer_for_cocoa.h
index e6bc619..f5246b6 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_model_observer_for_cocoa.h
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_model_observer_for_cocoa.h
@@ -25,7 +25,6 @@
 
 #include "base/basictypes.h"
 #include "base/mac/scoped_block.h"
-#include "base/memory/scoped_nsobject.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/bookmarks/bookmark_model_observer.h"
 
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_model_observer_for_cocoa_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_model_observer_for_cocoa_unittest.mm
index c781af2..83e8dae 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_model_observer_for_cocoa_unittest.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_model_observer_for_cocoa_unittest.mm
@@ -4,7 +4,6 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_name_folder_controller.h b/chrome/browser/ui/cocoa/bookmarks/bookmark_name_folder_controller.h
index d7009dd..e5a603e 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_name_folder_controller.h
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_name_folder_controller.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 
@@ -31,7 +31,7 @@
   const BookmarkNode* parent_;
   int newIndex_;
 
-  scoped_nsobject<NSString> initialName_;
+  base::scoped_nsobject<NSString> initialName_;
 
   // Ping me when things change out from under us.
   scoped_ptr<BookmarkModelObserverForCocoa> observer_;
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_name_folder_controller_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_name_folder_controller_unittest.mm
index eb78e7a..d8a023d 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_name_folder_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_name_folder_controller_unittest.mm
@@ -4,7 +4,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_name_folder_controller.h"
@@ -23,12 +23,11 @@
   const BookmarkNode* parent = model->bookmark_bar_node();
   EXPECT_EQ(0, parent->child_count());
 
-  scoped_nsobject<BookmarkNameFolderController>
-    controller([[BookmarkNameFolderController alloc]
-                 initWithParentWindow:test_window()
-                              profile:profile()
-                               parent:parent
-                             newIndex:0]);
+  base::scoped_nsobject<BookmarkNameFolderController> controller(
+      [[BookmarkNameFolderController alloc] initWithParentWindow:test_window()
+                                                         profile:profile()
+                                                          parent:parent
+                                                        newIndex:0]);
   [controller window];  // force nib load
 
   // Do nothing.
@@ -59,12 +58,11 @@
                 GURL("http://www.google.com"));
   EXPECT_EQ(2, parent->child_count());
 
-  scoped_nsobject<BookmarkNameFolderController>
-    controller([[BookmarkNameFolderController alloc]
-                 initWithParentWindow:test_window()
-                              profile:profile()
-                               parent:parent
-                             newIndex:1]);
+  base::scoped_nsobject<BookmarkNameFolderController> controller(
+      [[BookmarkNameFolderController alloc] initWithParentWindow:test_window()
+                                                         profile:profile()
+                                                          parent:parent
+                                                        newIndex:1]);
   [controller window];  // force nib load
 
   // Add a new folder.
@@ -83,12 +81,11 @@
   const BookmarkNode* parent = model->bookmark_bar_node();
   EXPECT_EQ(0, parent->child_count());
 
-  scoped_nsobject<BookmarkNameFolderController>
-    controller([[BookmarkNameFolderController alloc]
-                 initWithParentWindow:test_window()
-                              profile:profile()
-                               parent:parent
-                             newIndex:0]);
+  base::scoped_nsobject<BookmarkNameFolderController> controller(
+      [[BookmarkNameFolderController alloc] initWithParentWindow:test_window()
+                                                         profile:profile()
+                                                          parent:parent
+                                                        newIndex:0]);
 
   [controller window];  // force nib load
 
@@ -104,12 +101,11 @@
   const BookmarkNode* parent = model->bookmark_bar_node();
   EXPECT_EQ(0, parent->child_count());
 
-  scoped_nsobject<BookmarkNameFolderController>
-  controller([[BookmarkNameFolderController alloc]
-              initWithParentWindow:test_window()
-                           profile:profile()
-                            parent:parent
-                          newIndex:0]);
+  base::scoped_nsobject<BookmarkNameFolderController> controller(
+      [[BookmarkNameFolderController alloc] initWithParentWindow:test_window()
+                                                         profile:profile()
+                                                          parent:parent
+                                                        newIndex:0]);
   [controller window];  // force nib load
 
   // Change the name to blank, click OK.
@@ -128,11 +124,10 @@
 
   // Rename the folder by creating a controller that originates from
   // the node.
-  scoped_nsobject<BookmarkNameFolderController>
-    controller([[BookmarkNameFolderController alloc]
-                 initWithParentWindow:test_window()
-                              profile:profile()
-                                 node:folder]);
+  base::scoped_nsobject<BookmarkNameFolderController> controller(
+      [[BookmarkNameFolderController alloc] initWithParentWindow:test_window()
+                                                         profile:profile()
+                                                            node:folder]);
   [controller window];  // force nib load
 
   EXPECT_NSEQ(@"folder", [controller folderName]);
@@ -148,12 +143,11 @@
   const BookmarkNode* parent = model->bookmark_bar_node();
   EXPECT_EQ(0, parent->child_count());
 
-  scoped_nsobject<BookmarkNameFolderController>
-    controller([[BookmarkNameFolderController alloc]
-                 initWithParentWindow:test_window()
-                              profile:profile()
-                               parent:parent
-                             newIndex:0]);
+  base::scoped_nsobject<BookmarkNameFolderController> controller(
+      [[BookmarkNameFolderController alloc] initWithParentWindow:test_window()
+                                                         profile:profile()
+                                                          parent:parent
+                                                        newIndex:0]);
   [controller window];  // force nib load
 
   // We start enabled since the default "New Folder" is added for us.
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_tree_browser_cell_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_tree_browser_cell_unittest.mm
index 60f6deb..7450904 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_tree_browser_cell_unittest.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_tree_browser_cell_unittest.mm
@@ -4,7 +4,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_tree_browser_cell.h"
 #include "testing/platform_test.h"
@@ -20,8 +20,8 @@
   }
 
   scoped_ptr<BookmarkNode> bookmarkNodeMock_;
-  scoped_nsobject<NSMatrix> matrixMock_;
-  scoped_nsobject<NSObject> targetMock_;
+  base::scoped_nsobject<NSMatrix> matrixMock_;
+  base::scoped_nsobject<NSObject> targetMock_;
 };
 
 TEST_F(BookmarkTreeBrowserCellTest, BasicAllocDealloc) {
diff --git a/chrome/browser/ui/cocoa/browser/avatar_button_controller.h b/chrome/browser/ui/cocoa/browser/avatar_button_controller.h
index a72d6ee..f61ccad 100644
--- a/chrome/browser/ui/cocoa/browser/avatar_button_controller.h
+++ b/chrome/browser/ui/cocoa/browser/avatar_button_controller.h
@@ -7,7 +7,7 @@
 
 #import <AppKit/AppKit.h>
 
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 
 @class AvatarMenuBubbleController;
@@ -36,10 +36,10 @@
   __weak AvatarMenuBubbleController* menuController_;
 
   // The avatar button.
-  scoped_nsobject<NSButton> button_;
+  base::scoped_nsobject<NSButton> button_;
 
   // The managed user avatar label. Only used for managed user profiles.
-  scoped_nsobject<NSButton> labelButton_;
+  base::scoped_nsobject<NSButton> labelButton_;
 }
 
 // The avatar button view.
diff --git a/chrome/browser/ui/cocoa/browser/avatar_button_controller.mm b/chrome/browser/ui/cocoa/browser/avatar_button_controller.mm
index 52049b0..ab62229 100644
--- a/chrome/browser/ui/cocoa/browser/avatar_button_controller.mm
+++ b/chrome/browser/ui/cocoa/browser/avatar_button_controller.mm
@@ -98,8 +98,9 @@
   if ((self = [super init])) {
     browser_ = browser;
 
-    scoped_nsobject<NSView> container([[NSView alloc] initWithFrame:NSMakeRect(
-        0, 0, profiles::kAvatarIconWidth, profiles::kAvatarIconHeight)]);
+    base::scoped_nsobject<NSView> container(
+        [[NSView alloc] initWithFrame:NSMakeRect(
+            0, 0, profiles::kAvatarIconWidth, profiles::kAvatarIconHeight)]);
     [self setView:container];
     button_.reset([[NSButton alloc] initWithFrame:NSMakeRect(
         0, 0, profiles::kAvatarIconWidth, profiles::kAvatarIconHeight)]);
@@ -258,7 +259,7 @@
 - (NSImage*)compositeImageWithShadow:(NSImage*)image {
   gfx::ScopedNSGraphicsContextSaveGState scopedGState;
 
-  scoped_nsobject<NSImage> destination(
+  base::scoped_nsobject<NSImage> destination(
       [[NSImage alloc] initWithSize:[image size]]);
 
   NSRect destRect = NSZeroRect;
@@ -266,7 +267,7 @@
 
   [destination lockFocus];
 
-  scoped_nsobject<NSShadow> shadow([[NSShadow alloc] init]);
+  base::scoped_nsobject<NSShadow> shadow([[NSShadow alloc] init]);
   [shadow.get() setShadowColor:[NSColor colorWithCalibratedWhite:0.0
                                                            alpha:0.75]];
   [shadow.get() setShadowOffset:NSMakeSize(0, 0)];
diff --git a/chrome/browser/ui/cocoa/browser/avatar_button_controller_unittest.mm b/chrome/browser/ui/cocoa/browser/avatar_button_controller_unittest.mm
index 83001ee..43b7c3b 100644
--- a/chrome/browser/ui/cocoa/browser/avatar_button_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/browser/avatar_button_controller_unittest.mm
@@ -4,7 +4,7 @@
 
 #import "chrome/browser/ui/cocoa/browser/avatar_button_controller.h"
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_window.h"
 #import "chrome/browser/ui/cocoa/browser/avatar_menu_bubble_controller.h"
@@ -35,7 +35,7 @@
   AvatarButtonController* controller() { return controller_.get(); }
 
  private:
-  scoped_nsobject<AvatarButtonController> controller_;
+  base::scoped_nsobject<AvatarButtonController> controller_;
 };
 
 TEST_F(AvatarButtonControllerTest, AddRemoveProfiles) {
@@ -89,7 +89,7 @@
 
   // Build a new controller to check if it is initialized correctly for a
   // managed user profile.
-  scoped_nsobject<AvatarButtonController> controller(
+  base::scoped_nsobject<AvatarButtonController> controller(
       [[AvatarButtonController alloc] initWithBrowser:browser()]);
 
   EXPECT_TRUE([controller labelButtonView]);
diff --git a/chrome/browser/ui/cocoa/browser/avatar_menu_bubble_controller.h b/chrome/browser/ui/cocoa/browser/avatar_menu_bubble_controller.h
index f3f77f4..b0eb8f0 100644
--- a/chrome/browser/ui/cocoa/browser/avatar_menu_bubble_controller.h
+++ b/chrome/browser/ui/cocoa/browser/avatar_menu_bubble_controller.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #import "chrome/browser/ui/cocoa/base_bubble_controller.h"
 #import "ui/base/cocoa/tracking_area.h"
@@ -23,7 +23,7 @@
   scoped_ptr<AvatarMenuModel> model_;
 
   // Array of the below view controllers.
-  scoped_nsobject<NSMutableArray> items_;
+  base::scoped_nsobject<NSMutableArray> items_;
 
   // Is set to true if the managed user has clicked on Switch Users.
   BOOL expanded_;
@@ -65,7 +65,7 @@
 
   // The animation showing the edit link, which is run after the user has
   // dwelled over the item for a short delay.
-  scoped_nsobject<NSAnimation> linkAnimation_;
+  base::scoped_nsobject<NSAnimation> linkAnimation_;
 
   // Instance variables that back the outlets.
   __weak NSImageView* iconView_;
diff --git a/chrome/browser/ui/cocoa/browser/avatar_menu_bubble_controller.mm b/chrome/browser/ui/cocoa/browser/avatar_menu_bubble_controller.mm
index 65cff17..26e5ec9 100644
--- a/chrome/browser/ui/cocoa/browser/avatar_menu_bubble_controller.mm
+++ b/chrome/browser/ui/cocoa/browser/avatar_menu_bubble_controller.mm
@@ -110,7 +110,7 @@
   // Use an arbitrary height because it will reflect the size of the content.
   NSRect contentRect = NSMakeRect(0, 0, kBubbleMinWidth, 150);
   // Create an empty window into which content is placed.
-  scoped_nsobject<InfoBubbleWindow> window(
+  base::scoped_nsobject<InfoBubbleWindow> window(
       [[InfoBubbleWindow alloc] initWithContentRect:contentRect
                                           styleMask:NSBorderlessWindowMask
                                             backing:NSBackingStoreBuffered
@@ -183,11 +183,13 @@
   NSRect frame = [[self window] frame];
   // Adjust the origin after we have switched from the managed user menu to the
   // regular menu.
-  if (expanded_)
+  CGFloat newWidth = std::min(kBubbleMinWidth + width, kBubbleMaxWidth);
+  if (expanded_) {
+    frame.origin.x += frame.size.width - newWidth;
     frame.origin.y += frame.size.height - yOffset;
+  }
   frame.size.height = yOffset;
-  frame.size.width = kBubbleMinWidth + width;
-  frame.size.width = std::min(NSWidth(frame), kBubbleMaxWidth);
+  frame.size.width = newWidth;
   [[self window] setFrame:frame display:YES];
 }
 
@@ -302,10 +304,11 @@
 }
 
 - (NSView*)configureManagedUserInformation:(CGFloat)width {
-  scoped_nsobject<NSView> container([[NSView alloc] initWithFrame:NSZeroRect]);
+  base::scoped_nsobject<NSView> container(
+      [[NSView alloc] initWithFrame:NSZeroRect]);
 
   // Add the limited user icon on the left side of the information TextView.
-  scoped_nsobject<NSImageView> iconView(
+  base::scoped_nsobject<NSImageView> iconView(
       [[NSImageView alloc] initWithFrame:NSMakeRect(5, 0, 16, 16)]);
   [iconView setImage:model_->GetManagedUserIcon().ToNSImage()];
   [container addSubview:iconView];
@@ -314,9 +317,9 @@
       base::SysUTF16ToNSString(model_->GetManagedUserInformation());
   NSDictionary* attributes =
       @{ NSFontAttributeName : [NSFont labelFontOfSize:12] };
-  scoped_nsobject<NSAttributedString> attrString(
+  base::scoped_nsobject<NSAttributedString> attrString(
       [[NSAttributedString alloc] initWithString:info attributes:attributes]);
-  scoped_nsobject<NSTextView> label(
+  base::scoped_nsobject<NSTextView> label(
       [[NSTextView alloc] initWithFrame:NSMakeRect(
           kManagedUserSpacing, 0, width - kManagedUserSpacing - 5, 0)]);
   [[label textStorage] setAttributedString:attrString];
@@ -333,12 +336,11 @@
 
 - (NSButton*)configureNewUserButton:(CGFloat)yOffset
                   updateWidthAdjust:(CGFloat*)widthAdjust {
-  scoped_nsobject<NSButton> newButton(
-      [[NSButton alloc] initWithFrame:NSMakeRect(
-          kLabelInset, yOffset, kBubbleMinWidth - kLabelInset, 16)]);
-  scoped_nsobject<HyperlinkButtonCell> buttonCell(
+  base::scoped_nsobject<NSButton> newButton([[NSButton alloc] initWithFrame:
+          NSMakeRect(kLabelInset, yOffset, kBubbleMinWidth - kLabelInset, 16)]);
+  base::scoped_nsobject<HyperlinkButtonCell> buttonCell(
       [[HyperlinkButtonCell alloc] initTextCell:
-          l10n_util::GetNSString(IDS_PROFILES_CREATE_NEW_PROFILE_LINK)]);
+              l10n_util::GetNSString(IDS_PROFILES_CREATE_NEW_PROFILE_LINK)]);
   [newButton setCell:buttonCell.get()];
   [newButton setFont:[NSFont labelFontOfSize:12.0]];
   [newButton setBezelStyle:NSRegularSquareBezelStyle];
@@ -352,12 +354,12 @@
 
 - (NSButton*)configureSwitchUserButton:(CGFloat)yOffset
                      updateWidthAdjust:(CGFloat*)widthAdjust {
-  scoped_nsobject<NSButton> newButton(
+  base::scoped_nsobject<NSButton> newButton(
       [[NSButton alloc] initWithFrame:NSMakeRect(
           kManagedUserSpacing, yOffset, kBubbleMinWidth - kLabelInset, 16)]);
-  scoped_nsobject<HyperlinkButtonCell> buttonCell(
+  base::scoped_nsobject<HyperlinkButtonCell> buttonCell(
       [[HyperlinkButtonCell alloc] initTextCell:
-          l10n_util::GetNSString(IDS_PROFILES_SWITCH_PROFILE_LINK)]);
+              l10n_util::GetNSString(IDS_PROFILES_SWITCH_PROFILE_LINK)]);
   [newButton setCell:buttonCell.get()];
   [newButton setFont:[NSFont labelFontOfSize:12.0]];
   [newButton setBezelStyle:NSRegularSquareBezelStyle];
diff --git a/chrome/browser/ui/cocoa/browser/avatar_menu_bubble_controller_unittest.mm b/chrome/browser/ui/cocoa/browser/avatar_menu_bubble_controller_unittest.mm
index 2f5b3be..153efc4 100644
--- a/chrome/browser/ui/cocoa/browser/avatar_menu_bubble_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/browser/avatar_menu_bubble_controller_unittest.mm
@@ -4,9 +4,10 @@
 
 #import "chrome/browser/ui/cocoa/browser/avatar_menu_bubble_controller.h"
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/message_loop/message_pump_mac.h"
 #include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/prefs/pref_service_syncable.h"
 #include "chrome/browser/profiles/avatar_menu_model.h"
 #include "chrome/browser/profiles/avatar_menu_model_observer.h"
 #include "chrome/browser/profiles/profile_info_cache.h"
@@ -27,8 +28,10 @@
     CocoaTest::SetUp();
     ASSERT_TRUE(manager_.SetUp());
 
-    manager_.CreateTestingProfile("test1", ASCIIToUTF16("Test 1"), 1);
-    manager_.CreateTestingProfile("test2", ASCIIToUTF16("Test 2"), 0);
+    manager_.CreateTestingProfile("test1", scoped_ptr<PrefServiceSyncable>(),
+                                  ASCIIToUTF16("Test 1"), 1);
+    manager_.CreateTestingProfile("test2", scoped_ptr<PrefServiceSyncable>(),
+                                  ASCIIToUTF16("Test 2"), 0);
 
     model_ = new AvatarMenuModel(manager_.profile_info_cache(), NULL, NULL);
 
@@ -113,10 +116,11 @@
   NSView* contents = [[controller() window] contentView];
   EXPECT_EQ(4U, [[contents subviews] count]);
 
-  scoped_nsobject<NSMutableArray> oldItems([[controller() items] copy]);
+  base::scoped_nsobject<NSMutableArray> oldItems([[controller() items] copy]);
 
   // Now create a new profile and notify the delegate.
-  manager()->CreateTestingProfile("test3", ASCIIToUTF16("Test 3"), 0);
+  manager()->CreateTestingProfile("test3", scoped_ptr<PrefServiceSyncable>(),
+                                  ASCIIToUTF16("Test 3"), 0);
 
   // Testing the bridge is not worth the effort...
   [controller() performLayout];
@@ -176,7 +180,7 @@
 @end
 
 TEST_F(AvatarMenuBubbleControllerTest, HighlightForEventType) {
-  scoped_nsobject<TestingAvatarMenuItemController> item(
+  base::scoped_nsobject<TestingAvatarMenuItemController> item(
       [[TestingAvatarMenuItemController alloc] initWithModelIndex:0
                                                    menuController:nil]);
   // Test non-active states first.
diff --git a/chrome/browser/ui/cocoa/browser/edit_search_engine_cocoa_controller_unittest.mm b/chrome/browser/ui/cocoa/browser/edit_search_engine_cocoa_controller_unittest.mm
index 2315cfc..32f365f 100644
--- a/chrome/browser/ui/cocoa/browser/edit_search_engine_cocoa_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/browser/edit_search_engine_cocoa_controller_unittest.mm
@@ -4,7 +4,6 @@
 
 #import "chrome/browser/ui/cocoa/browser/edit_search_engine_cocoa_controller.h"
 
-#include "base/memory/scoped_nsobject.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/search_engines/template_url.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
diff --git a/chrome/browser/ui/cocoa/browser/password_generation_bubble_controller.mm b/chrome/browser/ui/cocoa/browser/password_generation_bubble_controller.mm
index 162b954..736ae92 100644
--- a/chrome/browser/ui/cocoa/browser/password_generation_bubble_controller.mm
+++ b/chrome/browser/ui/cocoa/browser/password_generation_bubble_controller.mm
@@ -13,7 +13,7 @@
 #import "chrome/browser/ui/cocoa/info_bubble_window.h"
 #include "chrome/browser/ui/cocoa/key_equivalent_constants.h"
 #import "chrome/browser/ui/cocoa/styled_text_field_cell.h"
-#include "components/autofill/browser/password_generator.h"
+#include "components/autofill/core/browser/password_generator.h"
 #include "components/autofill/core/common/autofill_messages.h"
 #include "components/autofill/core/common/password_generation_util.h"
 #include "content/public/browser/render_view_host.h"
@@ -69,8 +69,8 @@
  @private
   PasswordGenerationBubbleController* controller_;
   BOOL hovering_;
-  scoped_nsobject<NSImage> normalImage_;
-  scoped_nsobject<NSImage> hoverImage_;
+  base::scoped_nsobject<NSImage> normalImage_;
+  base::scoped_nsobject<NSImage> hoverImage_;
 }
 
 - (void)setUpWithController:(PasswordGenerationBubbleController*)controller
@@ -260,12 +260,10 @@
 - (void)setUpTrackingAreaInRect:(NSRect)frame
                          ofView:(PasswordGenerationTextField*)view {
   NSRect iconFrame = [self getIconFrame:frame];
-  scoped_nsobject<CrTrackingArea> area(
+  base::scoped_nsobject<CrTrackingArea> area(
       [[CrTrackingArea alloc] initWithRect:iconFrame
                                    options:NSTrackingMouseEnteredAndExited |
-                                           NSTrackingActiveAlways
-                                     owner:view
-                                  userInfo:nil]);
+          NSTrackingActiveAlways owner:view userInfo:nil]);
   [view addTrackingArea:area];
 }
 
@@ -308,7 +306,7 @@
                     kTopBorderOffset +
                     info_bubble::kBubbleArrowHeight);
   NSRect contentRect = NSMakeRect(0, 0, width, height);
-  scoped_nsobject<InfoBubbleWindow> window(
+  base::scoped_nsobject<InfoBubbleWindow> window(
       [[InfoBubbleWindow alloc] initWithContentRect:contentRect
                                           styleMask:NSBorderlessWindowMask
                                             backing:NSBackingStoreBuffered
@@ -364,12 +362,11 @@
   [button setAction:@selector(fillPassword:)];
   [contentView addSubview:button];
 
-  scoped_nsobject<NSTextField> title([[NSTextField alloc]
-                         initWithFrame:NSMakeRect(
-                             kBorderSize,
-                             kBorderSize + kTextFieldHeight + kVerticalSpacing,
-                             kTitleWidth,
-                             kTitleHeight)]);
+  base::scoped_nsobject<NSTextField> title([[NSTextField alloc] initWithFrame:
+          NSMakeRect(kBorderSize,
+                     kBorderSize + kTextFieldHeight + kVerticalSpacing,
+                     kTitleWidth,
+                     kTitleHeight)]);
   [title setEditable:NO];
   [title setBordered:NO];
   [title setStringValue:l10n_util::GetNSString(
diff --git a/chrome/browser/ui/cocoa/browser/password_generation_bubble_controller_unittest.mm b/chrome/browser/ui/cocoa/browser/password_generation_bubble_controller_unittest.mm
index 0e93aa6..f5c3db8 100644
--- a/chrome/browser/ui/cocoa/browser/password_generation_bubble_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/browser/password_generation_bubble_controller_unittest.mm
@@ -10,7 +10,7 @@
 #include "base/metrics/statistics_recorder.h"
 #include "base/strings/sys_string_conversions.h"
 #include "chrome/browser/ui/cocoa/cocoa_profile_test.h"
-#include "components/autofill/browser/password_generator.h"
+#include "components/autofill/core/browser/password_generator.h"
 #include "content/public/common/password_form.h"
 #include "testing/gtest_mac.h"
 
diff --git a/chrome/browser/ui/cocoa/browser/zoom_bubble_controller.h b/chrome/browser/ui/cocoa/browser/zoom_bubble_controller.h
index 8b909db..c92468e 100644
--- a/chrome/browser/ui/cocoa/browser/zoom_bubble_controller.h
+++ b/chrome/browser/ui/cocoa/browser/zoom_bubble_controller.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_UI_COCOA_BROWSER_ZOOM_BUBBLE_CONTROLLER_H_
 
 #include "base/mac/scoped_block.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/ui/cocoa/base_bubble_controller.h"
 #import "ui/base/cocoa/tracking_area.h"
 
@@ -31,7 +31,7 @@
   base::mac::ScopedBlock<void(^)(ZoomBubbleController*)> closeObserver_;
 
   // The text field that displays the current zoom percentage.
-  scoped_nsobject<NSTextField> zoomPercent_;
+  base::scoped_nsobject<NSTextField> zoomPercent_;
 
   // Whether or not the mouse is over the bubble.
   BOOL isMouseInside_;
diff --git a/chrome/browser/ui/cocoa/browser/zoom_bubble_controller.mm b/chrome/browser/ui/cocoa/browser/zoom_bubble_controller.mm
index a7c9b9e..0f2baa2 100644
--- a/chrome/browser/ui/cocoa/browser/zoom_bubble_controller.mm
+++ b/chrome/browser/ui/cocoa/browser/zoom_bubble_controller.mm
@@ -74,11 +74,11 @@
 
 - (id)initWithParentWindow:(NSWindow*)parentWindow
              closeObserver:(void(^)(ZoomBubbleController*))closeObserver {
-  scoped_nsobject<InfoBubbleWindow> window([[InfoBubbleWindow alloc]
-      initWithContentRect:NSMakeRect(0, 0, 200, 100)
-                styleMask:NSBorderlessWindowMask
-                  backing:NSBackingStoreBuffered
-                    defer:NO]);
+  base::scoped_nsobject<InfoBubbleWindow> window(
+      [[InfoBubbleWindow alloc] initWithContentRect:NSMakeRect(0, 0, 200, 100)
+                                          styleMask:NSBorderlessWindowMask
+                                            backing:NSBackingStoreBuffered
+                                              defer:NO]);
   if ((self = [super initWithWindow:window
                        parentWindow:parentWindow
                          anchoredAt:NSZeroPoint])) {
@@ -208,7 +208,8 @@
   // Separator view.
   rect.origin.x += NSWidth(rect);
   rect.size.width = 1;
-  scoped_nsobject<NSBox> separatorView([[NSBox alloc] initWithFrame:rect]);
+  base::scoped_nsobject<NSBox> separatorView(
+      [[NSBox alloc] initWithFrame:rect]);
   [separatorView setBoxType:NSBoxCustom];
   ui::NativeTheme* nativeTheme = ui::NativeTheme::instance();
   [separatorView setBorderColor:
@@ -241,7 +242,7 @@
 
 - (NSAttributedString*)attributedStringWithString:(NSString*)string
                                            fontSize:(CGFloat)fontSize {
-  scoped_nsobject<NSMutableParagraphStyle> paragraphStyle(
+  base::scoped_nsobject<NSMutableParagraphStyle> paragraphStyle(
       [[NSMutableParagraphStyle alloc] init]);
   [paragraphStyle setAlignment:NSCenterTextAlignment];
   NSDictionary* attributes = @{
@@ -260,7 +261,7 @@
 - (NSButton*)addButtonWithTitleID:(int)titleID
                          fontSize:(CGFloat)fontSize
                            action:(SEL)action {
-  scoped_nsobject<NSButton> button(
+  base::scoped_nsobject<NSButton> button(
       [[ZoomHoverButton alloc] initWithFrame:NSZeroRect]);
   NSString* title = l10n_util::GetNSStringWithFixup(titleID);
   [button setAttributedTitle:[self attributedStringWithString:title
@@ -273,7 +274,7 @@
 }
 
 - (NSTextField*)addZoomPercentTextField {
-  scoped_nsobject<NSTextField> textField(
+  base::scoped_nsobject<NSTextField> textField(
       [[NSTextField alloc] initWithFrame:NSZeroRect]);
   [textField setEditable:NO];
   [textField setBordered:NO];
diff --git a/chrome/browser/ui/cocoa/browser/zoom_bubble_controller_unittest.mm b/chrome/browser/ui/cocoa/browser/zoom_bubble_controller_unittest.mm
index 2d70b37..d5d4301 100644
--- a/chrome/browser/ui/cocoa/browser/zoom_bubble_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/browser/zoom_bubble_controller_unittest.mm
@@ -6,7 +6,7 @@
 
 #include "base/mac/bind_objc_block.h"
 #import "base/mac/mac_util.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #import "chrome/browser/ui/cocoa/info_bubble_window.h"
 #include "chrome/browser/ui/cocoa/run_loop_testing.h"
diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa.h b/chrome/browser/ui/cocoa/browser_window_cocoa.h
index 199e421..ea17ec7 100644
--- a/chrome/browser/ui/cocoa/browser_window_cocoa.h
+++ b/chrome/browser/ui/cocoa/browser_window_cocoa.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_UI_COCOA_BROWSER_WINDOW_COCOA_H_
 #define CHROME_BROWSER_UI_COCOA_BROWSER_WINDOW_COCOA_H_
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/extensions/extension_keybinding_registry.h"
@@ -169,7 +169,7 @@
   Browser* browser_;  // weak, owned by controller
   BrowserWindowController* controller_;  // weak, owns us
   base::WeakPtrFactory<Browser> confirm_close_factory_;
-  scoped_nsobject<NSString> pending_window_title_;
+  base::scoped_nsobject<NSString> pending_window_title_;
   ui::WindowShowState initial_show_state_;
   NSInteger attention_request_id_;  // identifier from requestUserAttention
 };
diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa.mm b/chrome/browser/ui/cocoa/browser_window_cocoa.mm
index 39813e2..5c7d583 100644
--- a/chrome/browser/ui/cocoa/browser_window_cocoa.mm
+++ b/chrome/browser/ui/cocoa/browser_window_cocoa.mm
@@ -6,10 +6,12 @@
 
 #include "base/bind.h"
 #include "base/command_line.h"
+#include "base/debug/crash_logging.h"
 #include "base/logging.h"
 #include "base/mac/mac_util.h"
 #include "base/message_loop.h"
 #include "base/prefs/pref_service.h"
+#include "base/strings/stringprintf.h"
 #include "base/strings/sys_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/download/download_shelf.h"
@@ -46,6 +48,7 @@
 #include "chrome/browser/ui/web_applications/web_app_ui.h"
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/common/chrome_notification_types.h"
+#include "chrome/common/crash_keys.h"
 #include "chrome/common/pref_names.h"
 #include "content/public/browser/native_web_keyboard_event.h"
 #include "content/public/browser/notification_details.h"
@@ -106,7 +109,8 @@
 void CreateShortcuts(const ShellIntegration::ShortcutInfo& shortcut_info) {
   // creation_locations will be ignored by CreatePlatformShortcuts on Mac.
   ShellIntegration::ShortcutLocations creation_locations;
-  web_app::CreateShortcuts(shortcut_info, creation_locations);
+  web_app::CreateShortcuts(shortcut_info, creation_locations,
+                           web_app::ALLOW_DUPLICATE_SHORTCUTS);
 }
 
 }  // namespace
@@ -304,6 +308,16 @@
 }
 
 void BrowserWindowCocoa::ZoomChangedForActiveTab(bool can_show_bubble) {
+  // Debug data for <http://crbug.com/254977>.
+  base::debug::ScopedCrashKey window_type(
+      crash_keys::mac::kZoomBubbleWindowType,
+      base::StringPrintf("type=%d,app_type=%d,app_name=%s",
+          browser_->type(), browser_->app_type(),
+          browser_->app_name().c_str()));
+  base::debug::ScopedCrashKey url(crash_keys::mac::kZoomBubbleURL,
+      browser_->tab_strip_model()->GetActiveWebContents()->GetActiveURL().
+          possibly_invalid_spec());
+
   [controller_ zoomChangedForActiveTab:can_show_bubble ? YES : NO];
 }
 
@@ -497,13 +511,12 @@
   WebContents* web_contents =
         browser_->tab_strip_model()->GetActiveWebContents();
   if (type == ONE_CLICK_SIGNIN_BUBBLE_TYPE_BUBBLE) {
-    scoped_nsobject<OneClickSigninBubbleController> bubble_controller(
-        [[OneClickSigninBubbleController alloc]
-            initWithBrowserWindowController:cocoa_controller()
-                                webContents:web_contents
-                               errorMessage:base::SysUTF16ToNSString(
-                                                error_message)
-                                   callback:start_sync_callback]);
+    base::scoped_nsobject<OneClickSigninBubbleController> bubble_controller([
+            [OneClickSigninBubbleController alloc]
+        initWithBrowserWindowController:cocoa_controller()
+                            webContents:web_contents
+                           errorMessage:base::SysUTF16ToNSString(error_message)
+                               callback:start_sync_callback]);
     [bubble_controller showWindow:nil];
   } else {
     // Deletes itself when the dialog closes.
@@ -673,7 +686,6 @@
 
 void BrowserWindowCocoa::ModelChanged(const SearchModel::State& old_state,
                                       const SearchModel::State& new_state) {
-  [controller_ updateBookmarkBarStateForInstantOverlay];
 }
 
 void BrowserWindowCocoa::DestroyBrowser() {
diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa_browsertest.mm b/chrome/browser/ui/cocoa/browser_window_cocoa_browsertest.mm
index 8577dfe..831f1d0 100644
--- a/chrome/browser/ui/cocoa/browser_window_cocoa_browsertest.mm
+++ b/chrome/browser/ui/cocoa/browser_window_cocoa_browsertest.mm
@@ -13,7 +13,7 @@
 #include "chrome/browser/ui/cocoa/browser_window_cocoa.h"
 #import "chrome/browser/ui/cocoa/info_bubble_window.h"
 #include "chrome/test/base/in_process_browser_test.h"
-#include "components/autofill/browser/password_generator.h"
+#include "components/autofill/core/browser/password_generator.h"
 #include "content/public/common/password_form.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/gfx/rect.h"
diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa_unittest.mm b/chrome/browser/ui/cocoa/browser_window_cocoa_unittest.mm
index 53835b3..8bb2f9e 100644
--- a/chrome/browser/ui/cocoa/browser_window_cocoa_unittest.mm
+++ b/chrome/browser/ui/cocoa/browser_window_cocoa_unittest.mm
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/mac/mac_util.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/string_util.h"
 #include "chrome/browser/ui/bookmarks/bookmark_utils.h"
@@ -14,8 +14,8 @@
 #include "chrome/common/pref_names.h"
 #include "content/public/browser/notification_details.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#import "third_party/ocmock/gtest_support.h"
 #import "third_party/ocmock/OCMock/OCMock.h"
+#import "third_party/ocmock/gtest_support.h"
 
 // Main test class.
 class BrowserWindowCocoaTest : public CocoaProfileTest {
@@ -79,7 +79,7 @@
   // Wrap the FakeController in a scoped_nsobject instead of autoreleasing in
   // windowWillClose: because we never actually open a window in this test (so
   // windowWillClose: never gets called).
-  scoped_nsobject<FakeController> fake_controller(
+  base::scoped_nsobject<FakeController> fake_controller(
       [[FakeController alloc] init]);
   scoped_ptr<BrowserWindowCocoa> bwc(new BrowserWindowCocoa(
       browser(), static_cast<BrowserWindowController*>(fake_controller.get())));
@@ -99,7 +99,7 @@
   // Wrap the FakeController in a scoped_nsobject instead of autoreleasing in
   // windowWillClose: because we never actually open a window in this test (so
   // windowWillClose: never gets called).
-  scoped_nsobject<FakeController> fake_controller(
+  base::scoped_nsobject<FakeController> fake_controller(
       [[FakeController alloc] init]);
   scoped_ptr<BrowserWindowCocoa> bwc(new BrowserWindowCocoa(
       browser(), static_cast<BrowserWindowController*>(fake_controller.get())));
diff --git a/chrome/browser/ui/cocoa/browser_window_controller.h b/chrome/browser/ui/cocoa/browser_window_controller.h
index 8ce1492..f50723c 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller.h
+++ b/chrome/browser/ui/cocoa/browser_window_controller.h
@@ -12,7 +12,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h"
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bubble_controller.h"
@@ -62,16 +62,17 @@
   scoped_ptr<Browser> browser_;
   NSWindow* savedRegularWindow_;
   scoped_ptr<BrowserWindowCocoa> windowShim_;
-  scoped_nsobject<ToolbarController> toolbarController_;
-  scoped_nsobject<TabStripController> tabStripController_;
-  scoped_nsobject<FindBarCocoaController> findBarCocoaController_;
-  scoped_nsobject<InfoBarContainerController> infoBarContainerController_;
-  scoped_nsobject<DownloadShelfController> downloadShelfController_;
-  scoped_nsobject<BookmarkBarController> bookmarkBarController_;
-  scoped_nsobject<DevToolsController> devToolsController_;
-  scoped_nsobject<OverlayableContentsController> overlayableContentsController_;
-  scoped_nsobject<PresentationModeController> presentationModeController_;
-  scoped_nsobject<FullscreenExitBubbleController>
+  base::scoped_nsobject<ToolbarController> toolbarController_;
+  base::scoped_nsobject<TabStripController> tabStripController_;
+  base::scoped_nsobject<FindBarCocoaController> findBarCocoaController_;
+  base::scoped_nsobject<InfoBarContainerController> infoBarContainerController_;
+  base::scoped_nsobject<DownloadShelfController> downloadShelfController_;
+  base::scoped_nsobject<BookmarkBarController> bookmarkBarController_;
+  base::scoped_nsobject<DevToolsController> devToolsController_;
+  base::scoped_nsobject<OverlayableContentsController>
+      overlayableContentsController_;
+  base::scoped_nsobject<PresentationModeController> presentationModeController_;
+  base::scoped_nsobject<FullscreenExitBubbleController>
       fullscreenExitBubbleController_;
 
   // Strong. StatusBubble is a special case of a strong reference that
@@ -106,16 +107,16 @@
   // The view controller that manages the incognito badge or the multi-profile
   // avatar icon. The view is always in the view hierarchy, but will be hidden
   // unless it's appropriate to show it.
-  scoped_nsobject<AvatarButtonController> avatarButtonController_;
+  base::scoped_nsobject<AvatarButtonController> avatarButtonController_;
 
   // Lazily created view which draws the background for the floating set of bars
   // in presentation mode (for window types having a floating bar; it remains
   // nil for those which don't).
-  scoped_nsobject<NSView> floatingBarBackingView_;
+  base::scoped_nsobject<NSView> floatingBarBackingView_;
 
   // The borderless window used in fullscreen mode.  Lion reuses the original
   // window in fullscreen mode, so this is always nil on Lion.
-  scoped_nsobject<NSWindow> fullscreenWindow_;
+  base::scoped_nsobject<NSWindow> fullscreenWindow_;
 
   // Tracks whether presentation mode was entered from fullscreen mode or
   // directly from normal windowed mode.  Used to determine what to do when
@@ -143,7 +144,7 @@
   // where keyboard focus is. Whenever an object requires bar visibility, it has
   // itself added to |barVisibilityLocks_|. When it no longer requires bar
   // visibility, it has itself removed.
-  scoped_nsobject<NSMutableSet> barVisibilityLocks_;
+  base::scoped_nsobject<NSMutableSet> barVisibilityLocks_;
 
   // Bar visibility locks and releases only result (when appropriate) in changes
   // in visible state when the following is |YES|.
@@ -159,10 +160,6 @@
   // handle.
   scoped_ptr<ExtensionKeybindingRegistryCocoa> extension_keybinding_registry_;
 
-  // The offset between the bottom of the toolbar and web contents. This is used
-  // to push the web contents below the bookmark bar.
-  CGFloat toolbarToWebContentsOffset_;
-
   // The number of history overlay views being shown.
   NSUInteger historyOverlayCount_;
 }
@@ -331,9 +328,6 @@
 // coordinates.
 - (NSPoint)bookmarkBubblePoint;
 
-// Shows or hides the Instant overlay contents.
-- (void)commitInstant;
-
 // Returns the frame, in Cocoa (unflipped) screen coordinates, of the area where
 // Instant results are.  If Instant is not showing, returns the frame of where
 // it would be.
@@ -344,9 +338,6 @@
          returnCode:(NSInteger)code
             context:(void*)context;
 
-// Updates the bookmark bar visibility based on the instant overlay state.
-- (void)updateBookmarkBarStateForInstantOverlay;
-
 // Called when the find bar visibility changes. This is used to update the
 // allowOverlappingViews state.
 - (void)onFindBarVisibilityChanged;
diff --git a/chrome/browser/ui/cocoa/browser_window_controller.mm b/chrome/browser/ui/cocoa/browser_window_controller.mm
index d200899..f9fb551 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller.mm
+++ b/chrome/browser/ui/cocoa/browser_window_controller.mm
@@ -10,11 +10,9 @@
 #include "base/command_line.h"
 #include "base/mac/bundle_locations.h"
 #include "base/mac/mac_util.h"
-#import "base/memory/scoped_nsobject.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"  // IDC_*
-#include "chrome/browser/bookmarks/bookmark_editor.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/devtools/devtools_window.h"
@@ -25,6 +23,7 @@
 #include "chrome/browser/signin/signin_ui_util.h"
 #include "chrome/browser/themes/theme_service.h"
 #include "chrome/browser/themes/theme_service_factory.h"
+#include "chrome/browser/ui/bookmarks/bookmark_editor.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_command_controller.h"
 #include "chrome/browser/ui/browser_commands.h"
@@ -49,6 +48,7 @@
 #import "chrome/browser/ui/cocoa/fullscreen_window.h"
 #import "chrome/browser/ui/cocoa/infobars/infobar_container_controller.h"
 #import "chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_editor.h"
+#import "chrome/browser/ui/cocoa/nsview_additions.h"
 #import "chrome/browser/ui/cocoa/presentation_mode_controller.h"
 #import "chrome/browser/ui/cocoa/status_bubble_mac.h"
 #import "chrome/browser/ui/cocoa/tab_contents/overlayable_contents_controller.h"
@@ -268,11 +268,10 @@
     windowShim_.reset(new BrowserWindowCocoa(browser, self));
 
     // Eagerly enable core animation if requested.
-    if (CommandLine::ForCurrentProcess()->HasSwitch(
-            switches::kUseCoreAnimation) &&
-        CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
-            switches::kUseCoreAnimation) != "lazy") {
+    if ([self coreAnimationStatus] ==
+            browser_window_controller::kCoreAnimationEnabledAlways) {
       [[[self window] contentView] setWantsLayer:YES];
+      [[self tabStripView] setWantsLayer:YES];
     }
 
     // Set different minimum sizes on tabbed windows vs non-tabbed, e.g. popups.
@@ -345,8 +344,7 @@
     // Create the overlayable contents controller.  This provides the switch
     // view that TabStripController needs.
     overlayableContentsController_.reset(
-        [[OverlayableContentsController alloc] initWithBrowser:browser
-                                              windowController:self]);
+        [[OverlayableContentsController alloc] initWithBrowser:browser]);
     [[overlayableContentsController_ view]
         setFrame:[[devToolsController_ view] bounds]];
     [[devToolsController_ view]
@@ -598,15 +596,20 @@
   // have to save the window position before we call orderOut:.
   [self saveWindowPositionIfNeeded];
 
+  bool fast_tab_closing_enabled =
+      CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableFastUnload);
+
   if (!browser_->tab_strip_model()->empty()) {
-    // Tab strip isn't empty.  Hide the window (so it appears to have closed
+    // Tab strip isn't empty.  Hide the frame (so it appears to have closed
     // immediately) and close all the tabs, allowing the renderers to shut
     // down. When the tab strip is empty we'll be called back again.
     [[self window] orderOut:self];
     browser_->OnWindowClosing();
-    browser_->tab_strip_model()->CloseAllTabs();
+    if (fast_tab_closing_enabled)
+      browser_->tab_strip_model()->CloseAllTabs();
     return NO;
-  } else if (!browser_->HasCompletedUnloadProcessing()) {
+  } else if (fast_tab_closing_enabled &&
+        !browser_->HasCompletedUnloadProcessing()) {
     // The browser needs to finish running unload handlers.
     // Hide the window (so it appears to have closed immediately), and
     // the browser will call us back again when it is ready to close.
@@ -1636,9 +1639,8 @@
 }
 
 - (void)userChangedTheme {
-  // TODO(dmaclach): Instead of redrawing the whole window, views that care
-  // about the active window state should be registering for notifications.
-  [[self window] setViewsNeedDisplay:YES];
+  NSView* contentView = [[self window] contentView];
+  [[contentView superview] cr_recursivelySetNeedsDisplay:YES];
 }
 
 - (ui::ThemeProvider*)themeProvider {
@@ -1955,19 +1957,15 @@
   NSView* toolbarView = [toolbarController_ view];
   NSRect anchorRect = [toolbarView frame];
 
-  // Adjust to account for height and possible bookmark bar.
+  // Adjust to account for height and possible bookmark bar. Compress by 1
+  // to account for the separator.
   anchorRect.origin.y =
-      NSMaxY(anchorRect) - [toolbarController_ desiredHeightForCompression:0];
+      NSMaxY(anchorRect) - [toolbarController_ desiredHeightForCompression:1];
 
   // Shift to window base coordinates.
   return [[toolbarView superview] convertRect:anchorRect toView:nil];
 }
 
-- (void)commitInstant {
-  if (BrowserInstantController* controller = browser_->instant_controller())
-    controller->instant()->CommitIfPossible(INSTANT_COMMIT_FOCUS_LOST);
-}
-
 - (NSRect)instantFrame {
   // The view's bounds are in its own coordinate system.  Convert that to the
   // window base coordinate system, then translate it into the screen's
@@ -1995,13 +1993,6 @@
   [sheet orderOut:self];
 }
 
-- (void)updateBookmarkBarStateForInstantOverlay {
-  [toolbarController_ setDividerOpacity:[self toolbarDividerOpacity]];
-  [self updateContentOffsets];
-  [self updateSubviewZOrder:[self inPresentationMode]];
-  [self updateInfoBarTipVisibility];
-}
-
 - (void)onFindBarVisibilityChanged {
   [self updateAllowOverlappingViews:[self inPresentationMode]];
 }
diff --git a/chrome/browser/ui/cocoa/browser_window_controller_browsertest.mm b/chrome/browser/ui/cocoa/browser_window_controller_browsertest.mm
index adb1817..8ec94d1 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller_browsertest.mm
+++ b/chrome/browser/ui/cocoa/browser_window_controller_browsertest.mm
@@ -12,7 +12,6 @@
 #include "chrome/browser/infobars/infobar_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/browser/search/search.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_list.h"
@@ -29,7 +28,6 @@
 #include "chrome/browser/ui/extensions/application_launch.h"
 #include "chrome/browser/ui/find_bar/find_bar_controller.h"
 #include "chrome/browser/ui/find_bar/find_bar.h"
-#include "chrome/browser/ui/search/search_model.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/testing_profile.h"
@@ -106,27 +104,6 @@
         browser()->window()->GetNativeWindow()];
   }
 
-  void ShowInstantResults() {
-    chrome::EnableInstantExtendedAPIForTesting();
-    SearchMode mode(SearchMode::MODE_SEARCH_SUGGESTIONS,
-                    SearchMode::ORIGIN_SEARCH);
-    browser()->search_model()->SetMode(mode);
-    browser()->search_model()->SetTopBarsVisible(false);
-    EXPECT_TRUE(browser()->search_model()->mode().is_search_suggestions());
-    EXPECT_EQ(browser_window_controller::kInstantUIFullPageResults,
-              [controller() currentInstantUIState]);
-  }
-
-  void ShowInstantNTP() {
-    chrome::EnableInstantExtendedAPIForTesting();
-    SearchMode mode(SearchMode::MODE_NTP, SearchMode::ORIGIN_NTP);
-    browser()->search_model()->SetMode(mode);
-    browser()->search_model()->SetTopBarsVisible(true);
-    EXPECT_TRUE(browser()->search_model()->mode().is_ntp());
-    EXPECT_EQ(browser_window_controller::kInstantUINone,
-              [controller() currentInstantUIState]);
-  }
-
   void ShowInfoBar() {
     content::WebContents* web_contents =
         browser()->tab_strip_model()->GetActiveWebContents();
@@ -138,15 +115,6 @@
            animate:NO];
   }
 
-  void HideInstant() {
-    SearchMode mode;
-    browser()->search_model()->SetMode(mode);
-    browser()->search_model()->SetTopBarsVisible(true);
-    EXPECT_TRUE(browser()->search_model()->mode().is_default());
-    EXPECT_EQ(browser_window_controller::kInstantUINone,
-              [controller() currentInstantUIState]);
-  }
-
   NSView* GetViewWithID(ViewID view_id) const {
     switch (view_id) {
       case VIEW_ID_FULLSCREEN_FLOATING_BAR:
@@ -296,68 +264,6 @@
   VerifyZOrder(view_list);
 }
 
-// Normal mode with Instant results showing. Should be same z-order as normal
-// mode except find bar is below content area.
-IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest, ZOrderNormalInstant) {
-  ShowInstantResults();
-  browser()->GetFindBarController();  // add find bar
-
-  std::vector<ViewID> view_list;
-  view_list.push_back(VIEW_ID_BOOKMARK_BAR);
-  view_list.push_back(VIEW_ID_TOOLBAR);
-  view_list.push_back(VIEW_ID_INFO_BAR);
-  view_list.push_back(VIEW_ID_TAB_CONTENT_AREA);
-  view_list.push_back(VIEW_ID_FIND_BAR);
-  view_list.push_back(VIEW_ID_DOWNLOAD_SHELF);
-  VerifyZOrder(view_list);
-}
-
-// Presentation mode with Instant results showing. Should be exact same as
-// non-Instant presentation mode.
-IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest,
-                       DISABLED_ZOrderInstantPresentationMode) {
-  // TODO(kbr): re-enable: http://crbug.com/222296
-  if (base::mac::IsOSMountainLionOrLater())
-    return;
-
-  chrome::ToggleFullscreenMode(browser());
-  ShowInstantResults();
-  browser()->GetFindBarController();  // add find bar
-
-  std::vector<ViewID> view_list;
-  view_list.push_back(VIEW_ID_INFO_BAR);
-  view_list.push_back(VIEW_ID_TAB_CONTENT_AREA);
-  view_list.push_back(VIEW_ID_FULLSCREEN_FLOATING_BAR);
-  view_list.push_back(VIEW_ID_BOOKMARK_BAR);
-  view_list.push_back(VIEW_ID_TOOLBAR);
-  view_list.push_back(VIEW_ID_FIND_BAR);
-  view_list.push_back(VIEW_ID_DOWNLOAD_SHELF);
-  VerifyZOrder(view_list);
-}
-
-// Verify that in presentation mode, Instant search results are below the
-// floating toolbar.
-IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest,
-                       DISABLED_OverlayOffsetInstantPresentationMode) {
-  chrome::ToggleFullscreenMode(browser());
-  ShowInstantResults();
-  [controller() setFloatingBarShownFraction:0.0];
-  EXPECT_EQ(
-      0, [[controller() overlayableContentsController] overlayContentsOffset]);
-  EXPECT_EQ(
-      0, [[controller() overlayableContentsController] activeContainerOffset]);
-  [controller() setFloatingBarShownFraction:1.0];
-
-  NSView* floating_bar = GetViewWithID(VIEW_ID_FULLSCREEN_FLOATING_BAR);
-  CGFloat floating_bar_height = NSHeight([floating_bar frame]);
-  EXPECT_EQ(
-      floating_bar_height,
-      [[controller() overlayableContentsController] overlayContentsOffset]);
-  EXPECT_EQ(
-      floating_bar_height,
-      [[controller() overlayableContentsController] activeContainerOffset]);
-}
-
 // Verify that if the fullscreen floating bar view is below the tab content area
 // then calling |updateSubviewZOrder:| will correctly move back above.
 IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest,
@@ -386,161 +292,6 @@
   VerifyZOrder(view_list);
 }
 
-// Verify that in non-Instant presentation mode the content area is beneath
-// the bookmark bar and info bar.
-IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest, ContentOffset) {
-  OverlayableContentsController* overlay =
-      [controller() overlayableContentsController];
-  // Just toolbar.
-  EXPECT_EQ(1, [overlay activeContainerOffset]);
-
-  // Plus bookmark bar.
-  browser()->window()->ToggleBookmarkBar();
-  CGFloat bookmark_bar_offset =
-      GetViewHeight(VIEW_ID_BOOKMARK_BAR) - bookmarks::kBookmarkBarOverlap + 1;
-  EXPECT_EQ(bookmark_bar_offset, [overlay activeContainerOffset]);
-
-  // Plus info bar.
-  ShowInfoBar();
-  EXPECT_EQ(bookmark_bar_offset + GetViewHeight(VIEW_ID_INFO_BAR),
-            [overlay activeContainerOffset]);
-
-  // Minus bookmark bar.
-  browser()->window()->ToggleBookmarkBar();
-  EXPECT_EQ(GetViewHeight(VIEW_ID_INFO_BAR) + 1,
-            [overlay activeContainerOffset]);
-}
-
-// Verify that in non-Instant presentation mode the content area is beneath
-// the info bar.
-IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest,
-                       DISABLED_ContentOffsetPresentationMode) {
-  // TODO(kbr): re-enable: http://crbug.com/222296
-  if (base::mac::IsOSMountainLionOrLater())
-    return;
-
-  chrome::ToggleFullscreenMode(browser());
-  OverlayableContentsController* overlay =
-      [controller() overlayableContentsController];
-
-  // Just toolbar.
-  EXPECT_EQ(0, [overlay activeContainerOffset]);
-
-  // Plus bookmark bar.
-  browser()->window()->ToggleBookmarkBar();
-  EXPECT_EQ(0, [overlay activeContainerOffset]);
-
-  // Plus info bar.
-  ShowInfoBar();
-  EXPECT_EQ(0, [overlay activeContainerOffset]);
-
-  // Minus bookmark bar.
-  browser()->window()->ToggleBookmarkBar();
-  EXPECT_EQ(0, [overlay activeContainerOffset]);
-}
-
-// Verify that when showing Instant results the content area overlaps the
-// bookmark bar and info bar.
-IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest, ContentOffsetInstant) {
-  OverlayableContentsController* overlay =
-      [controller() overlayableContentsController];
-  ShowInstantResults();
-
-  // Just toolbar.
-  EXPECT_EQ(0, [overlay activeContainerOffset]);
-
-  // Plus bookmark bar.
-  browser()->window()->ToggleBookmarkBar();
-  EXPECT_EQ(0, [overlay activeContainerOffset]);
-
-  // Plus info bar.
-  ShowInfoBar();
-  EXPECT_EQ(0, [overlay activeContainerOffset]);
-
-  // Minus bookmark bar.
-  browser()->window()->ToggleBookmarkBar();
-  EXPECT_EQ(0, [overlay activeContainerOffset]);
-}
-
-// The Instant NTP case is same as normal case except that the overlay is
-// also shifted down.
-IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest, ContentOffsetInstantNTP) {
-  ShowInstantNTP();
-  OverlayableContentsController* overlay =
-      [controller() overlayableContentsController];
-
-  // Just toolbar.
-  EXPECT_EQ(1, [overlay activeContainerOffset]);
-
-  // Plus bookmark bar.
-  browser()->window()->ToggleBookmarkBar();
-  CGFloat bookmark_bar_offset =
-      GetViewHeight(VIEW_ID_BOOKMARK_BAR) - bookmarks::kBookmarkBarOverlap + 1;
-  EXPECT_EQ(bookmark_bar_offset, [overlay activeContainerOffset]);
-
-  // Plus info bar.
-  ShowInfoBar();
-  EXPECT_EQ(bookmark_bar_offset + GetViewHeight(VIEW_ID_INFO_BAR),
-            [overlay activeContainerOffset]);
-
-  // Minus bookmark bar.
-  browser()->window()->ToggleBookmarkBar();
-  EXPECT_EQ(GetViewHeight(VIEW_ID_INFO_BAR) + 1,
-            [overlay activeContainerOffset]);
-}
-
-// Verify that the find bar is positioned corerctly when a full page instant
-// search result is displayed.
-IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest, FindBarOffsetInstant) {
-  // Add bookmark bar and find bar.
-  browser()->window()->ToggleBookmarkBar();
-  browser()->GetFindBarController();
-
-  CGFloat line_width = [GetViewWithID(VIEW_ID_FIND_BAR) cr_lineWidth];
-  NSRect bookmark_bar_frame = [GetViewWithID(VIEW_ID_BOOKMARK_BAR) frame];
-  NSRect find_bar_frame = [GetViewWithID(VIEW_ID_FIND_BAR) frame];
-  EXPECT_EQ(NSMinY(bookmark_bar_frame), NSMaxY(find_bar_frame) - line_width);
-
-  // Show instant and add a find bar to it.
-  ShowInstantResults();
-  browser()->GetFindBarController()->find_bar()->Show(false);;
-
-  NSRect toolbar_bar_frame = [GetViewWithID(VIEW_ID_TOOLBAR) frame];
-  find_bar_frame = [GetViewWithID(VIEW_ID_FIND_BAR) frame];
-  EXPECT_EQ(NSMinY(toolbar_bar_frame) - bookmarks::kBookmarkBarOverlap + 1 -
-            line_width,
-            NSMaxY(find_bar_frame));
-}
-
-// Verify that if bookmark bar is underneath Instant search results then
-// clicking on Instant search results still works.
-IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest,
-                       InstantSearchResultsHitTest) {
-  browser()->window()->ToggleBookmarkBar();
-  ShowInstantResults();
-
-  NSView* bookmarkView = [[controller() bookmarkBarController] view];
-  NSView* contentView = [[controller() window] contentView];
-  NSPoint point = [bookmarkView convertPoint:NSMakePoint(1, 1)
-                                      toView:[contentView superview]];
-
-  EXPECT_FALSE([[contentView hitTest:point] isDescendantOf:bookmarkView]);
-  EXPECT_TRUE([[contentView hitTest:point]
-      isDescendantOf:[controller() tabContentArea]]);
-}
-
-// Verify that |currentInstantUIState| returns the correct value for search
-// results mode.
-IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest, InstantSearchResultsMode) {
-  chrome::EnableInstantExtendedAPIForTesting();
-  SearchMode mode(SearchMode::MODE_SEARCH_RESULTS, SearchMode::ORIGIN_SEARCH);
-  browser()->search_model()->SetMode(mode);
-  browser()->search_model()->SetTopBarsVisible(false);
-  EXPECT_TRUE(browser()->search_model()->mode().is_search_results());
-  EXPECT_EQ(browser_window_controller::kInstantUIFullPageResults,
-            [controller() currentInstantUIState]);
-}
-
 IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest, SheetPosition) {
   ASSERT_TRUE([controller() isKindOfClass:[BrowserWindowController class]]);
   EXPECT_TRUE([controller() isTabbedWindow]);
@@ -574,7 +325,7 @@
   chrome::OpenAppShortcutWindow(
       browser()->profile(), GURL("about:blank"), initial_bounds);
   Browser* popup_browser = BrowserList::GetInstance(
-      chrome::HOST_DESKTOP_TYPE_NATIVE)->GetLastActive();
+      chrome::GetActiveDesktop())->GetLastActive();
   NSWindow* popupWindow = popup_browser->window()->GetNativeWindow();
   BrowserWindowController* popupController =
       [BrowserWindowController browserWindowControllerForWindow:popupWindow];
@@ -599,22 +350,6 @@
   [popupController close];
 }
 
-// Verify that the info bar tip is hidden when the instant overlay is visible.
-IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest,
-                       InfoBarTipHiddenForInstant) {
-  ShowInfoBar();
-  EXPECT_FALSE(
-      [[controller() infoBarContainerController] shouldSuppressTopInfoBarTip]);
-
-  ShowInstantResults();
-  EXPECT_TRUE(
-      [[controller() infoBarContainerController] shouldSuppressTopInfoBarTip]);
-
-  HideInstant();
-  EXPECT_FALSE(
-      [[controller() infoBarContainerController] shouldSuppressTopInfoBarTip]);
-}
-
 // Verify that the info bar tip is hidden when the toolbar is not visible.
 IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest,
                        InfoBarTipHiddenForWindowWithoutToolbar) {
@@ -654,7 +389,7 @@
       browser()->tab_strip_model()->GetActiveWebContents()->GetView();
   EXPECT_FALSE(web_contents_view->GetAllowOverlappingViews());
 
-  scoped_nsobject<HistoryOverlayController> overlay(
+  base::scoped_nsobject<HistoryOverlayController> overlay(
       [[HistoryOverlayController alloc] initForMode:kHistoryOverlayModeBack]);
   [overlay showPanelForView:web_contents_view->GetNativeView()];
   EXPECT_TRUE(web_contents_view->GetAllowOverlappingViews());
diff --git a/chrome/browser/ui/cocoa/browser_window_controller_private.h b/chrome/browser/ui/cocoa/browser_window_controller_private.h
index 6a70dc0..f3ba8dc 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller_private.h
+++ b/chrome/browser/ui/cocoa/browser_window_controller_private.h
@@ -9,13 +9,10 @@
 
 namespace browser_window_controller {
 
-enum InstantUIState {
-  kInstantUINone,
-  // Instant suggestions are displayed in a overlay overlapping the tab
-  // contents.
-  kInstantUIOverlay,
-  // Instant suggestions are displayed in the main tab contents.
-  kInstantUIFullPageResults,
+enum CoreAnimationStatus {
+  kCoreAnimationDisabled,
+  kCoreAnimationEnabledLazy,
+  kCoreAnimationEnabledAlways,
 };
 
 }  // namespace browser_window_controller
@@ -156,15 +153,6 @@
 // The opacity for the toolbar divider; 0 means that it shouldn't be shown.
 - (CGFloat)toolbarDividerOpacity;
 
-// This is used to check if either the instant overlay or full page instant
-// search results are currently being displayed.
-- (browser_window_controller::InstantUIState)currentInstantUIState;
-
-// Updates the content offets of the tab strip controller and the overlayable
-// contents controller. This is used to adjust the overlap between those views
-// and the bookmark bar.
-- (void)updateContentOffsets;
-
 // Ensures the z-order of subviews is correct.
 - (void)updateSubviewZOrder:(BOOL)inPresentationMode;
 
@@ -173,6 +161,9 @@
 // Update visibility of the infobar tip, depending on the state of the window.
 - (void)updateInfoBarTipVisibility;
 
+// Checks if core animation should be enabled or not.
+- (browser_window_controller::CoreAnimationStatus)coreAnimationStatus;
+
 @end  // @interface BrowserWindowController(Private)
 
 #endif  // CHROME_BROWSER_UI_COCOA_BROWSER_WINDOW_CONTROLLER_PRIVATE_H_
diff --git a/chrome/browser/ui/cocoa/browser_window_controller_private.mm b/chrome/browser/ui/cocoa/browser_window_controller_private.mm
index 39c04b0..43de7e5 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller_private.mm
+++ b/chrome/browser/ui/cocoa/browser_window_controller_private.mm
@@ -7,13 +7,12 @@
 #include <cmath>
 
 #include "base/command_line.h"
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #include "base/prefs/pref_service.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/prefs/scoped_user_pref_update.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_info_util.h"
-#include "chrome/browser/search/search.h"
 #include "chrome/browser/ui/bookmarks/bookmark_tab_helper.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_window_state.h"
@@ -34,8 +33,6 @@
 #import "chrome/browser/ui/cocoa/tabs/tab_strip_view.h"
 #import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h"
 #include "chrome/browser/ui/fullscreen/fullscreen_controller.h"
-#include "chrome/browser/ui/search/search_model.h"
-#include "chrome/browser/ui/search/search_ui.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
@@ -214,7 +211,6 @@
   DCHECK_LE(maxY, NSMaxY(contentBounds) + yOffset);
 
   // Place the toolbar at the top of the reserved area.
-  CGFloat toolbarTopY = maxY;
   maxY = [self layoutToolbarAtMinX:minX maxY:maxY width:width];
 
   // If we're not displaying the bookmark bar below the info bar, then it goes
@@ -222,7 +218,6 @@
   BOOL placeBookmarkBarBelowInfoBar = [self placeBookmarkBarBelowInfoBar];
   if (!placeBookmarkBarBelowInfoBar)
     maxY = [self layoutBookmarkBarAtMinX:minX maxY:maxY width:width];
-  CGFloat toolbarBottomY = maxY;
 
   // The floating bar backing view doesn't actually add any height.
   NSRect floatingBarBackingRect =
@@ -230,8 +225,11 @@
   [self layoutFloatingBarBackingView:floatingBarBackingRect
                     presentationMode:inPresentationMode];
 
-  [fullscreenExitBubbleController_ positionInWindowAtTop:toolbarBottomY
-                                                   width:width];
+  // Place the find bar immediately below the toolbar/attached bookmark bar. In
+  // presentation mode, it hangs off the top of the screen when the bar is
+  // hidden.
+  [findBarCocoaController_ positionFindBarViewAtMaxY:maxY maxWidth:width];
+  [fullscreenExitBubbleController_ positionInWindowAtTop:maxY width:width];
 
   // If in presentation mode, reset |maxY| to top of screen, so that the
   // floating bar slides over the things which appear to be in the content area.
@@ -242,55 +240,15 @@
   // presentation mode in which case it's at the top of the visual content area.
   maxY = [self layoutInfoBarAtMinX:minX maxY:maxY width:width];
 
-  // Place the download shelf, if any, at the bottom of the view.
-  minY = [self layoutDownloadShelfAtMinX:minX minY:minY width:width];
-
-  // Place the bookmark bar.
+  // If the bookmark bar is detached, place it next in the visual content area.
   if (placeBookmarkBarBelowInfoBar)
     maxY = [self layoutBookmarkBarAtMinX:minX maxY:maxY width:width];
 
-  // In presentation mode the content area takes up all the remaining space
-  // (from the bottom of the info bar down). In normal mode the content area
-  // takes up the space between the bottom of the toolbar down.
-  CGFloat contentAreaTop = 0;
-  if (inPresentationMode) {
-    // The tabContentaArea starts at the bottom of the info bar (or top of the
-    // screen if there's no info bar).
-    contentAreaTop = maxY;
-    CGFloat floatingBarHeight =
-        NSHeight(floatingBarBackingRect) * [self floatingBarShownFraction];
-    // When an instant overlay is shown this is the amount it needs to be pushed
-    // down so that it doesn't get covered by the floating toolbar.
-    toolbarToWebContentsOffset_ =
-        floatingBarHeight - (NSMaxY(contentBounds) - maxY);
-  } else {
-    // The tabContentArea view starts below the omnibox.
-    CGFloat minToolbarHeight = 0;
-    if ([self hasToolbar]) {
-      // 1 to account for the toolbar separator.
-      minToolbarHeight = [toolbarController_ desiredHeightForCompression:1];
-    }
-    contentAreaTop = toolbarTopY - minToolbarHeight;
-    // This is the space between the bottom of the omnibox and the bottom of the
-    // last bar (info bar or bookmark bar or toolbar). This is used to push the
-    // tab web content down when no instant overlay is shown.
-    toolbarToWebContentsOffset_ = contentAreaTop - maxY;
-  }
-  [self updateContentOffsets];
+  // Place the download shelf, if any, at the bottom of the view.
+  minY = [self layoutDownloadShelfAtMinX:minX minY:minY width:width];
 
-  // Place the find bar immediately below the toolbar/attached bookmark bar. In
-  // presentation mode, it hangs off the top of the screen when the bar is
-  // hidden.
-  if ([self currentInstantUIState] ==
-      browser_window_controller::kInstantUIFullPageResults) {
-    [findBarCocoaController_ positionFindBarViewAtMaxY:contentAreaTop - 1
-                                              maxWidth:width];
-  } else {
-    [findBarCocoaController_ positionFindBarViewAtMaxY:toolbarBottomY
-                                              maxWidth:width];
-  }
-
-  NSRect contentAreaRect = NSMakeRect(minX, minY, width, contentAreaTop - minY);
+  // Finally, the content area takes up all of the remaining space.
+  NSRect contentAreaRect = NSMakeRect(minX, minY, width, maxY - minY);
   [self layoutTabContentArea:contentAreaRect];
 
   // Normally, we don't need to tell the toolbar whether or not to show the
@@ -552,21 +510,22 @@
   [bookmarkBubbleController_ ok:self];
 
   // Save the current first responder so we can restore after views are moved.
-  scoped_nsobject<FocusTracker> focusTracker(
+  base::scoped_nsobject<FocusTracker> focusTracker(
       [[FocusTracker alloc] initWithWindow:sourceWindow]);
 
   // While we move views (and focus) around, disable any bar visibility changes.
   [self disableBarVisibilityUpdates];
 
   // Retain the tab strip view while we remove it from its superview.
-  scoped_nsobject<NSView> tabStripView;
+  base::scoped_nsobject<NSView> tabStripView;
   if ([self hasTabStrip]) {
     tabStripView.reset([[self tabStripView] retain]);
     [tabStripView removeFromSuperview];
   }
 
   // Ditto for the content view.
-  scoped_nsobject<NSView> contentView([[sourceWindow contentView] retain]);
+  base::scoped_nsobject<NSView> contentView(
+      [[sourceWindow contentView] retain]);
   // Disable autoresizing of subviews while we move views around. This prevents
   // spurious renderer resizes.
   [contentView setAutoresizesSubviews:NO];
@@ -883,71 +842,6 @@
   return [bookmarkBarController_ toolbarDividerOpacity];
 }
 
-- (browser_window_controller::InstantUIState)currentInstantUIState {
-  if (!browser_->search_model()->mode().is_search())
-    return browser_window_controller::kInstantUINone;
-
-  // If the search suggestions are already being displayed in the overlay
-  // contents then return kInstantUIOverlay.
-  if ([overlayableContentsController_ isShowingOverlay])
-    return browser_window_controller::kInstantUIOverlay;
-
-  if (browser_->search_model()->top_bars_visible())
-    return browser_window_controller::kInstantUINone;
-
-  return browser_window_controller::kInstantUIFullPageResults;
-}
-
-- (void)updateContentOffsets {
-  if ([self inPresentationMode]) {
-    // In presentation mode the tabContentArea starts at the bottom of the info
-    // bar (or top of the screen if there's no info bar).
-    if ([self currentInstantUIState] !=
-        browser_window_controller::kInstantUIFullPageResults) {
-      // Normal mode, keep the tab web contents at the top (below the info bar).
-      [overlayableContentsController_ setActiveContainerOffset:0];
-    } else {
-      // Instant suggestions are displayed in the main tab contents so push that
-      // down so that the floating toolbar doesn't obscure it.
-      [overlayableContentsController_
-          setActiveContainerOffset:toolbarToWebContentsOffset_];
-    }
-    // Floating overlay (if any) should also be below the floating toolbar.
-    [overlayableContentsController_
-        setOverlayContentsOffset:toolbarToWebContentsOffset_];
-
-    [[self tabContentArea] setContentOffset:0];
-    [devToolsController_ setTopContentOffset:0];
-  } else {
-    // In normal mode the tabContentArea starts just below the omnibox and the
-    // bookmark bar and info bar overlap it.
-    if ([self currentInstantUIState] !=
-        browser_window_controller::kInstantUIFullPageResults) {
-      // Normal mode, push the tab web contents down so that it doesn't obscure
-      // the bookmark bar and info bar.
-      [overlayableContentsController_
-          setActiveContainerOffset:toolbarToWebContentsOffset_];
-    } else {
-      // Instant suggestions are displayed in the main tab contents so don't
-      // push it down (keep it next to the omnibox).
-      [overlayableContentsController_ setActiveContainerOffset:0];
-    }
-    // Floating overlay (if any) should also be at the top (next to the
-    // omnibox).
-    [overlayableContentsController_ setOverlayContentsOffset:0];
-
-    // Prevent the fast resize view from drawing white over the bookmark bar.
-    [[self tabContentArea] setContentOffset:toolbarToWebContentsOffset_];
-    // Prevent the dev tools splitter from overlapping the bookmark bar.
-    if ([self currentInstantUIState] !=
-        browser_window_controller::kInstantUINone) {
-      [devToolsController_ setTopContentOffset:0];
-    } else {
-      [devToolsController_ setTopContentOffset:toolbarToWebContentsOffset_];
-    }
-  }
-}
-
 - (void)updateSubviewZOrder:(BOOL)inPresentationMode {
   NSView* contentView = [[self window] contentView];
   NSView* toolbarView = [toolbarController_ view];
@@ -959,17 +853,14 @@
                      isPositioned:NSWindowAbove
                        relativeTo:[self tabContentArea]];
   } else {
-    // Toolbar is below tab contents so that the infob ar arrow can appear above
-    // it.  Unlike other views the toolbar never overlaps the actual web
-    // content.
+    // Toolbar is below tab contents so that the info bar arrow can appear above
+    // it.
     [contentView cr_ensureSubview:toolbarView
                      isPositioned:NSWindowBelow
                        relativeTo:[self tabContentArea]];
   }
 
-  // The bookmark bar is always below the toolbar. In normal mode this means
-  // that it is below tab contents. This allows Instant results to be above
-  // the bookmark bar.
+  // The bookmark bar is always below the toolbar.
   [contentView cr_ensureSubview:[bookmarkBarController_ view]
                    isPositioned:NSWindowBelow
                      relativeTo:toolbarView];
@@ -987,17 +878,13 @@
                        relativeTo:toolbarView];
   }
 
-  // The find bar is above everything except Instant search results.
+  // The find bar is above everything.
   if (findBarCocoaController_) {
     NSView* relativeView = nil;
-    if (inPresentationMode) {
+    if (inPresentationMode)
       relativeView = toolbarView;
-    } else if ([self currentInstantUIState] ==
-               browser_window_controller::kInstantUIOverlay) {
-      relativeView = [infoBarContainerController_ view];
-    } else {
+    else
       relativeView = [self tabContentArea];
-    }
     [contentView cr_ensureSubview:[findBarCocoaController_ view]
                      isPositioned:NSWindowAbove
                        relativeTo:relativeView];
@@ -1040,6 +927,14 @@
 
   BOOL allowOverlappingViews =
       [self shouldAllowOverlappingViews:inPresentationMode];
+
+  if (allowOverlappingViews &&
+      [self coreAnimationStatus] ==
+          browser_window_controller::kCoreAnimationEnabledLazy) {
+    [[[self window] contentView] setWantsLayer:YES];
+    [[self tabStripView] setWantsLayer:YES];
+  }
+
   contents->GetView()->SetAllowOverlappingViews(allowOverlappingViews);
 
   DevToolsWindow* devToolsWindow =
@@ -1051,12 +946,26 @@
 }
 
 - (void)updateInfoBarTipVisibility {
-  // If the overlay is open or if there's no toolbar then hide the infobar tip.
-  BOOL suppressInfoBarTip =
-      [self currentInstantUIState] !=
-      browser_window_controller::kInstantUINone || ![self hasToolbar];
+  // If there's no toolbar then hide the infobar tip.
   [infoBarContainerController_
-      setShouldSuppressTopInfoBarTip:suppressInfoBarTip];
+      setShouldSuppressTopInfoBarTip:![self hasToolbar]];
+}
+
+- (browser_window_controller::CoreAnimationStatus)coreAnimationStatus {
+  // TODO(sail) Remove this.
+  if (!CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kUseCoreAnimation)) {
+    return browser_window_controller::kCoreAnimationDisabled;
+  }
+  if (CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+          switches::kUseCoreAnimation) == "lazy") {
+    return browser_window_controller::kCoreAnimationEnabledLazy;
+  }
+  if (CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+          switches::kUseCoreAnimation) == "disabled") {
+    return browser_window_controller::kCoreAnimationDisabled;
+  }
+  return browser_window_controller::kCoreAnimationEnabledAlways;
 }
 
 @end  // @implementation BrowserWindowController(Private)
diff --git a/chrome/browser/ui/cocoa/browser_window_controller_unittest.mm b/chrome/browser/ui/cocoa/browser_window_controller_unittest.mm
index ce77ea0..82032a1 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/browser_window_controller_unittest.mm
@@ -5,7 +5,7 @@
 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
 
 #include "base/mac/mac_util.h"
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/prefs/pref_service.h"
 #include "base/strings/utf_string_conversions.h"
@@ -140,7 +140,7 @@
   // popup_browser will be owned by its window.
   Browser* popup_browser(new Browser(
       Browser::CreateParams(Browser::TYPE_POPUP, profile(),
-                            chrome::HOST_DESKTOP_TYPE_NATIVE)));
+                            chrome::GetActiveDesktop())));
   NSWindow *cocoaWindow = popup_browser->window()->GetNativeWindow();
   BrowserWindowController* controller =
       static_cast<BrowserWindowController*>([cocoaWindow windowController]);
@@ -155,7 +155,7 @@
 TEST_F(BrowserWindowControllerTest, TestSetBounds) {
   // Create a normal browser with bounds smaller than the minimum.
   Browser::CreateParams params(Browser::TYPE_TABBED, profile(),
-                               chrome::HOST_DESKTOP_TYPE_NATIVE);
+                               chrome::GetActiveDesktop());
   params.initial_bounds = gfx::Rect(0, 0, 50, 50);
   Browser* browser = new Browser(params);
   NSWindow *cocoaWindow = browser->window()->GetNativeWindow();
@@ -181,7 +181,7 @@
 TEST_F(BrowserWindowControllerTest, TestSetBoundsPopup) {
   // Create a popup with bounds smaller than the minimum.
   Browser::CreateParams params(Browser::TYPE_POPUP, profile(),
-                               chrome::HOST_DESKTOP_TYPE_NATIVE);
+                               chrome::GetActiveDesktop());
   params.initial_bounds = gfx::Rect(0, 0, 50, 50);
   Browser* browser = new Browser(params);
   NSWindow *cocoaWindow = browser->window()->GetNativeWindow();
@@ -228,7 +228,7 @@
   incognito_profile->set_off_the_record(true);
   scoped_ptr<Browser> browser(
       new Browser(Browser::CreateParams(incognito_profile.get(),
-                                        chrome::HOST_DESKTOP_TYPE_NATIVE));
+                                        chrome::GetActiveDesktop()));
   controller_.reset([[BrowserWindowController alloc]
                               initWithBrowser:browser.get()
                                 takeOwnership:NO]);
@@ -243,6 +243,7 @@
 #endif
 
 namespace {
+
 // Verifies that the toolbar, infobar, tab content area, and download shelf
 // completely fill the area under the tabstrip.
 void CheckViewPositions(BrowserWindowController* controller) {
@@ -255,10 +256,7 @@
 
   EXPECT_EQ(NSMinY(contentView), NSMinY(download));
   EXPECT_EQ(NSMaxY(download), NSMinY(contentArea));
-
-  CGFloat min_toolbar_height = [[controller toolbarController]
-      desiredHeightForCompression:1];
-  EXPECT_EQ(NSMaxY(contentArea), NSMaxY(toolbar) - min_toolbar_height);
+  EXPECT_EQ(NSMaxY(contentArea), NSMinY(infobar));
 
   // Bookmark bar frame is random memory when hidden.
   if ([controller bookmarkBarVisible]) {
@@ -275,6 +273,7 @@
   // not necessarily fixed with respect to the content view.
   EXPECT_EQ(NSMinY(tabstrip), NSMaxY(toolbar));
 }
+
 }  // end namespace
 
 TEST_F(BrowserWindowControllerTest, TestAdjustWindowHeight) {
@@ -641,7 +640,7 @@
   NSPoint bubbleOrigin = [controller_ statusBubbleBaseFrame].origin;
 
   // Add a fake subview to devToolsView to emulate docked devTools.
-  scoped_nsobject<NSView> view(
+  base::scoped_nsobject<NSView> view(
       [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 10, 10)]);
   [[controller_ devToolsView] addSubview:view];
   [[controller_ devToolsView] adjustSubviews];
@@ -653,7 +652,7 @@
 }
 
 TEST_F(BrowserWindowControllerTest, TestSigninMenuItemNoErrors) {
-  scoped_nsobject<NSMenuItem> syncMenuItem(
+  base::scoped_nsobject<NSMenuItem> syncMenuItem(
       [[NSMenuItem alloc] initWithTitle:@""
                                  action:@selector(commandDispatch)
                           keyEquivalent:@""]);
@@ -697,7 +696,7 @@
 }
 
 TEST_F(BrowserWindowControllerTest, TestSigninMenuItemAuthError) {
-  scoped_nsobject<NSMenuItem> syncMenuItem(
+  base::scoped_nsobject<NSMenuItem> syncMenuItem(
       [[NSMenuItem alloc] initWithTitle:@""
                                  action:@selector(commandDispatch)
                           keyEquivalent:@""]);
@@ -728,7 +727,7 @@
 // If there's a separator after the signin menu item, make sure it is hidden/
 // shown when the signin menu item is.
 TEST_F(BrowserWindowControllerTest, TestSigninMenuItemWithSeparator) {
-  scoped_nsobject<NSMenu> menu([[NSMenu alloc] initWithTitle:@""]);
+  base::scoped_nsobject<NSMenu> menu([[NSMenu alloc] initWithTitle:@""]);
   NSMenuItem* signinMenuItem =
       [menu addItemWithTitle:@""
                       action:@selector(commandDispatch)
@@ -759,7 +758,7 @@
 // If there's a non-separator item after the signin menu item, it should not
 // change state when the signin menu item is hidden/shown.
 TEST_F(BrowserWindowControllerTest, TestSigninMenuItemWithNonSeparator) {
-  scoped_nsobject<NSMenu> menu([[NSMenu alloc] initWithTitle:@""]);
+  base::scoped_nsobject<NSMenu> menu([[NSMenu alloc] initWithTitle:@""]);
   NSMenuItem* signinMenuItem =
       [menu addItemWithTitle:@""
                       action:@selector(commandDispatch)
@@ -809,7 +808,7 @@
  @private
   // We release the window ourselves, so we don't have to rely on the unittest
   // doing it for us.
-  scoped_nsobject<NSWindow> testFullscreenWindow_;
+  base::scoped_nsobject<NSWindow> testFullscreenWindow_;
 }
 @end
 
diff --git a/chrome/browser/ui/cocoa/bubble_view.h b/chrome/browser/ui/cocoa/bubble_view.h
index 336f8cd..12c89f4 100644
--- a/chrome/browser/ui/cocoa/bubble_view.h
+++ b/chrome/browser/ui/cocoa/bubble_view.h
@@ -4,7 +4,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 
 // A view class that looks like a "bubble" with rounded corners and displays
 // text inside. Can be themed. To put flush against the sides of a window, the
@@ -33,7 +33,7 @@
 
 @interface BubbleView : NSView {
  @private
-  scoped_nsobject<NSString> content_;
+  base::scoped_nsobject<NSString> content_;
   unsigned long cornerFlags_;
   // The window from which we get the theme used to draw. In some cases,
   // it might not be the window we're in. As a result, this may or may not
diff --git a/chrome/browser/ui/cocoa/bubble_view.mm b/chrome/browser/ui/cocoa/bubble_view.mm
index 4c3d8e0..b9b8648 100644
--- a/chrome/browser/ui/cocoa/bubble_view.mm
+++ b/chrome/browser/ui/cocoa/bubble_view.mm
@@ -104,7 +104,7 @@
     textColor = themeProvider->GetNSColor(ThemeProperties::COLOR_TAB_TEXT,
                                           true);
   NSFont* textFont = [self font];
-  scoped_nsobject<NSShadow> textShadow([[NSShadow alloc] init]);
+  base::scoped_nsobject<NSShadow> textShadow([[NSShadow alloc] init]);
   [textShadow setShadowBlurRadius:0.0f];
   [textShadow.get() setShadowColor:[textColor gtm_legibleTextColor]];
   [textShadow.get() setShadowOffset:NSMakeSize(0.0f, -1.0f)];
diff --git a/chrome/browser/ui/cocoa/bubble_view_unittest.mm b/chrome/browser/ui/cocoa/bubble_view_unittest.mm
index 4b8850e..c1b5d9b 100644
--- a/chrome/browser/ui/cocoa/bubble_view_unittest.mm
+++ b/chrome/browser/ui/cocoa/bubble_view_unittest.mm
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/bubble_view.h"
 #include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #import "testing/gtest_mac.h"
@@ -12,7 +12,7 @@
  public:
   BubbleViewTest() {
     NSRect frame = NSMakeRect(0, 0, 50, 50);
-    scoped_nsobject<BubbleView> view(
+    base::scoped_nsobject<BubbleView> view(
         [[BubbleView alloc] initWithFrame:frame themeProvider:test_window()]);
     view_ = view.get();
     [[test_window() contentView] addSubview:view_];
@@ -27,7 +27,7 @@
 // Test a nil themeProvider in init.
 TEST_F(BubbleViewTest, NilThemeProvider) {
   NSRect frame = NSMakeRect(0, 0, 50, 50);
-  scoped_nsobject<BubbleView> view(
+  base::scoped_nsobject<BubbleView> view(
       [[BubbleView alloc] initWithFrame:frame themeProvider:nil]);
   [[test_window() contentView] addSubview:view.get()];
   [view display];
diff --git a/chrome/browser/ui/cocoa/certificate_viewer_mac.h b/chrome/browser/ui/cocoa/certificate_viewer_mac.h
index 737d40d..f33bef2 100644
--- a/chrome/browser/ui/cocoa/certificate_viewer_mac.h
+++ b/chrome/browser/ui/cocoa/certificate_viewer_mac.h
@@ -6,7 +6,7 @@
 
 #define CHROME_BROWSER_UI_COCOA_CERTIFICATE_VIEWER_MAC_H_
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_mac.h"
 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_sheet.h"
@@ -21,11 +21,11 @@
 @interface SSLCertificateViewerCocoa : NSObject<ConstrainedWindowSheet> {
  @private
   // The corresponding list of certificates.
-  scoped_nsobject<NSArray> certificates_;
+  base::scoped_nsobject<NSArray> certificates_;
   scoped_ptr<SSLCertificateViewerCocoaBridge> observer_;
-  scoped_nsobject<SFCertificatePanel> panel_;
+  base::scoped_nsobject<SFCertificatePanel> panel_;
   scoped_ptr<ConstrainedWindowMac> constrainedWindow_;
-  scoped_nsobject<NSWindow> overlayWindow_;
+  base::scoped_nsobject<NSWindow> overlayWindow_;
   BOOL closePending_;
   // A copy of the sheet's frame used to restore on show.
   NSRect oldSheetFrame_;
diff --git a/chrome/browser/ui/cocoa/certificate_viewer_mac.mm b/chrome/browser/ui/cocoa/certificate_viewer_mac.mm
index 5fc37c5..8e8ab9c 100644
--- a/chrome/browser/ui/cocoa/certificate_viewer_mac.mm
+++ b/chrome/browser/ui/cocoa/certificate_viewer_mac.mm
@@ -10,8 +10,6 @@
 
 #include "base/mac/foundation_util.h"
 #include "base/mac/scoped_cftyperef.h"
-#include "base/memory/scoped_nsobject.h"
-#include "base/memory/scoped_ptr.h"
 #include "chrome/browser/certificate_viewer.h"
 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_mac.h"
 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_sheet.h"
@@ -80,7 +78,7 @@
 
 - (id)initWithCertificate:(net::X509Certificate*)certificate {
   if ((self = [super init])) {
-    base::mac::ScopedCFTypeRef<CFArrayRef> cert_chain(
+    base::ScopedCFTypeRef<CFArrayRef> cert_chain(
         certificate->CreateOSCertChainForCert());
     NSArray* certificates = base::mac::CFToNSCast(cert_chain.get());
     certificates_.reset([certificates retain]);
@@ -110,7 +108,7 @@
   // the certificate viewer UI from displaying which certificate is revoked.
   // This is acceptable, as certificate revocation will still be shown in
   // the page info bubble if a certificate in the chain is actually revoked.
-  base::mac::ScopedCFTypeRef<CFMutableArrayRef> policies(
+  base::ScopedCFTypeRef<CFMutableArrayRef> policies(
       CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks));
   if (!policies.get()) {
     NOTREACHED();
diff --git a/chrome/browser/ui/cocoa/certificate_viewer_mac_browsertest.mm b/chrome/browser/ui/cocoa/certificate_viewer_mac_browsertest.mm
index 1c665f5..0840e8a 100644
--- a/chrome/browser/ui/cocoa/certificate_viewer_mac_browsertest.mm
+++ b/chrome/browser/ui/cocoa/certificate_viewer_mac_browsertest.mm
@@ -39,7 +39,7 @@
       WebContentsModalDialogManager::FromWebContents(web_contents);
   EXPECT_FALSE(web_contents_modal_dialog_manager->IsShowingDialog());
 
-  ShowCertificateViewer(web_contents, window, cert);
+  ShowCertificateViewer(web_contents, window, cert.get());
 
   content::RunAllPendingInMessageLoop();
   EXPECT_TRUE(web_contents_modal_dialog_manager->IsShowingDialog());
@@ -59,7 +59,7 @@
       browser()->tab_strip_model()->GetActiveWebContents();
 
   SSLCertificateViewerCocoa* viewer =
-      [[SSLCertificateViewerCocoa alloc] initWithCertificate:cert];
+      [[SSLCertificateViewerCocoa alloc] initWithCertificate:cert.get()];
   [viewer displayForWebContents:web_contents];
 
   content::RunAllPendingInMessageLoop();
diff --git a/chrome/browser/ui/cocoa/chrome_event_processing_window.h b/chrome/browser/ui/cocoa/chrome_event_processing_window.h
index cb69c52..b9a20e9 100644
--- a/chrome/browser/ui/cocoa/chrome_event_processing_window.h
+++ b/chrome/browser/ui/cocoa/chrome_event_processing_window.h
@@ -7,7 +7,6 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
 #import "ui/base/cocoa/underlay_opengl_hosting_window.h"
 
 // Override NSWindow to access unhandled keyboard events (for command
diff --git a/chrome/browser/ui/cocoa/chrome_event_processing_window_unittest.mm b/chrome/browser/ui/cocoa/chrome_event_processing_window_unittest.mm
index 823e7bd..3865b24 100644
--- a/chrome/browser/ui/cocoa/chrome_event_processing_window_unittest.mm
+++ b/chrome/browser/ui/cocoa/chrome_event_processing_window_unittest.mm
@@ -5,13 +5,12 @@
 #include <Carbon/Carbon.h>
 
 #include "base/debug/debugger.h"
-#include "base/memory/scoped_nsobject.h"
 #include "chrome/app/chrome_command_ids.h"
-#import "chrome/browser/ui/cocoa/chrome_event_processing_window.h"
 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
+#import "chrome/browser/ui/cocoa/chrome_event_processing_window.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#include "third_party/ocmock/gtest_support.h"
 #import "third_party/ocmock/OCMock/OCMock.h"
+#include "third_party/ocmock/gtest_support.h"
 #import "third_party/ocmock/ocmock_extensions.h"
 
 namespace {
diff --git a/chrome/browser/ui/cocoa/chrome_to_mobile_bubble_controller.h b/chrome/browser/ui/cocoa/chrome_to_mobile_bubble_controller.h
index a91db0d..74ca702 100644
--- a/chrome/browser/ui/cocoa/chrome_to_mobile_bubble_controller.h
+++ b/chrome/browser/ui/cocoa/chrome_to_mobile_bubble_controller.h
@@ -10,7 +10,7 @@
 #include <vector>
 
 #include "base/files/file_path.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #include "chrome/browser/chrome_to_mobile_service.h"
 #import "chrome/browser/ui/cocoa/base_bubble_controller.h"
@@ -97,7 +97,7 @@
   base::FilePath snapshotPath_;
 
   // An animation used to cycle through the "Sending..." status messages.
-  scoped_nsobject<NSAnimation> progressAnimation_;
+  base::scoped_nsobject<NSAnimation> progressAnimation_;
 }
 
 // The owner of this object is responsible for showing the bubble. It is not
diff --git a/chrome/browser/ui/cocoa/clickhold_button_cell.h b/chrome/browser/ui/cocoa/clickhold_button_cell.h
index 554e1f6..187eef0 100644
--- a/chrome/browser/ui/cocoa/clickhold_button_cell.h
+++ b/chrome/browser/ui/cocoa/clickhold_button_cell.h
@@ -7,7 +7,6 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/image_button_cell.h"
 
 // A button cell that implements "click hold" behavior after a specified delay
diff --git a/chrome/browser/ui/cocoa/clickhold_button_cell_unittest.mm b/chrome/browser/ui/cocoa/clickhold_button_cell_unittest.mm
index f76f805..0786271 100644
--- a/chrome/browser/ui/cocoa/clickhold_button_cell_unittest.mm
+++ b/chrome/browser/ui/cocoa/clickhold_button_cell_unittest.mm
@@ -4,7 +4,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/clickhold_button_cell.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -16,9 +16,10 @@
  public:
   ClickHoldButtonCellTest() {
     NSRect frame = NSMakeRect(0, 0, 50, 30);
-    scoped_nsobject<NSButton> view([[NSButton alloc] initWithFrame:frame]);
+    base::scoped_nsobject<NSButton> view(
+        [[NSButton alloc] initWithFrame:frame]);
     view_ = view.get();
-    scoped_nsobject<ClickHoldButtonCell> cell(
+    base::scoped_nsobject<ClickHoldButtonCell> cell(
         [[ClickHoldButtonCell alloc] initTextCell:@"Testing"]);
     [view_ setCell:cell.get()];
     [[test_window() contentView] addSubview:view_];
diff --git a/chrome/browser/ui/cocoa/cocoa_profile_test.mm b/chrome/browser/ui/cocoa/cocoa_profile_test.mm
index 4d56be3..5c3529c 100644
--- a/chrome/browser/ui/cocoa/cocoa_profile_test.mm
+++ b/chrome/browser/ui/cocoa/cocoa_profile_test.mm
@@ -96,5 +96,5 @@
 
 Browser* CocoaProfileTest::CreateBrowser() {
   return new Browser(Browser::CreateParams(profile(),
-                                           chrome::HOST_DESKTOP_TYPE_NATIVE));
+                                           chrome::GetActiveDesktop()));
 }
diff --git a/chrome/browser/ui/cocoa/color_chooser_mac.mm b/chrome/browser/ui/cocoa/color_chooser_mac.mm
index f5e8dda..2241818 100644
--- a/chrome/browser/ui/cocoa/color_chooser_mac.mm
+++ b/chrome/browser/ui/cocoa/color_chooser_mac.mm
@@ -5,7 +5,7 @@
 #import <Cocoa/Cocoa.h>
 
 #include "base/logging.h"
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #include "chrome/browser/ui/browser_dialogs.h"
 #include "content/public/browser/color_chooser.h"
 #include "content/public/browser/web_contents.h"
@@ -54,7 +54,7 @@
   // The web contents invoking the color chooser.  No ownership because it will
   // outlive this class.
   content::WebContents* web_contents_;
-  scoped_nsobject<ColorPanelCocoa> panel_;
+  base::scoped_nsobject<ColorPanelCocoa> panel_;
 };
 
 ColorChooserMac* ColorChooserMac::current_color_chooser_ = NULL;
diff --git a/chrome/browser/ui/cocoa/command_observer_bridge_unittest.mm b/chrome/browser/ui/cocoa/command_observer_bridge_unittest.mm
index ed973b1..eb65c2e 100644
--- a/chrome/browser/ui/cocoa/command_observer_bridge_unittest.mm
+++ b/chrome/browser/ui/cocoa/command_observer_bridge_unittest.mm
@@ -4,7 +4,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #include "chrome/browser/command_updater.h"
 #import "chrome/browser/ui/cocoa/command_observer_bridge.h"
@@ -45,7 +45,7 @@
         observer_([[CommandTestObserver alloc] init]) {
   }
   scoped_ptr<CommandUpdater> updater_;
-  scoped_nsobject<CommandTestObserver> observer_;
+  base::scoped_nsobject<CommandTestObserver> observer_;
 };
 
 // Tests creation and deletion. NULL arguments aren't allowed.
diff --git a/chrome/browser/ui/cocoa/confirm_bubble_cocoa.h b/chrome/browser/ui/cocoa/confirm_bubble_cocoa.h
index 8d2a3f3..c1971b0 100644
--- a/chrome/browser/ui/cocoa/confirm_bubble_cocoa.h
+++ b/chrome/browser/ui/cocoa/confirm_bubble_cocoa.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 
 @class ConfirmBubbleController;
 class ConfirmBubbleModel;
@@ -37,11 +37,11 @@
   ConfirmBubbleController* controller_;  // weak
 
   // Controls used in this bubble.
-  scoped_nsobject<NSImageView> icon_;
-  scoped_nsobject<NSTextView> titleLabel_;
-  scoped_nsobject<NSTextView> messageLabel_;
-  scoped_nsobject<NSButton> okButton_;
-  scoped_nsobject<NSButton> cancelButton_;
+  base::scoped_nsobject<NSImageView> icon_;
+  base::scoped_nsobject<NSTextView> titleLabel_;
+  base::scoped_nsobject<NSTextView> messageLabel_;
+  base::scoped_nsobject<NSButton> okButton_;
+  base::scoped_nsobject<NSButton> cancelButton_;
 }
 
 // Initializes a bubble view. Since this initializer programmatically creates a
diff --git a/chrome/browser/ui/cocoa/confirm_bubble_cocoa.mm b/chrome/browser/ui/cocoa/confirm_bubble_cocoa.mm
index b16acea..474bf21 100644
--- a/chrome/browser/ui/cocoa/confirm_bubble_cocoa.mm
+++ b/chrome/browser/ui/cocoa/confirm_bubble_cocoa.mm
@@ -215,17 +215,17 @@
       initWithFrame:NSMakeRect(left, bottom, kMaxMessageWidth, 0)]);
   NSString* messageText = [controller_ messageText];
   NSMutableDictionary* attributes = [NSMutableDictionary dictionary];
-  scoped_nsobject<NSMutableAttributedString> attributedMessage(
+  base::scoped_nsobject<NSMutableAttributedString> attributedMessage(
       [[NSMutableAttributedString alloc] initWithString:messageText
                                              attributes:attributes]);
   NSString* linkText = [controller_ linkText];
   if (linkText) {
-    scoped_nsobject<NSAttributedString> whiteSpace(
+    base::scoped_nsobject<NSAttributedString> whiteSpace(
         [[NSAttributedString alloc] initWithString:@" "]);
     [attributedMessage.get() appendAttributedString:whiteSpace.get()];
     [attributes setObject:[NSString string]
                    forKey:NSLinkAttributeName];
-    scoped_nsobject<NSAttributedString> attributedLink(
+    base::scoped_nsobject<NSAttributedString> attributedLink(
         [[NSAttributedString alloc] initWithString:linkText
                                         attributes:attributes]);
     [attributedMessage.get() appendAttributedString:attributedLink.get()];
diff --git a/chrome/browser/ui/cocoa/confirm_bubble_controller_unittest.mm b/chrome/browser/ui/cocoa/confirm_bubble_controller_unittest.mm
index 76d605b..f458e56 100644
--- a/chrome/browser/ui/cocoa/confirm_bubble_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/confirm_bubble_controller_unittest.mm
@@ -3,8 +3,6 @@
 // found in the LICENSE file.
 
 #include "base/compiler_specific.h"
-#include "base/memory/scoped_nsobject.h"
-#include "base/memory/scoped_ptr.h"
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
diff --git a/chrome/browser/ui/cocoa/confirm_quit_panel_controller.mm b/chrome/browser/ui/cocoa/confirm_quit_panel_controller.mm
index 659fff8..27813eb 100644
--- a/chrome/browser/ui/cocoa/confirm_quit_panel_controller.mm
+++ b/chrome/browser/ui/cocoa/confirm_quit_panel_controller.mm
@@ -8,7 +8,7 @@
 #import "chrome/browser/ui/cocoa/confirm_quit_panel_controller.h"
 
 #include "base/logging.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/metrics/histogram.h"
 #include "base/prefs/pref_registry_simple.h"
 #include "base/strings/sys_string_conversions.h"
@@ -65,7 +65,7 @@
 
 - (id)initWithFrame:(NSRect)frameRect {
   if ((self = [super initWithFrame:frameRect])) {
-    scoped_nsobject<NSTextField> message(
+    base::scoped_nsobject<NSTextField> message(
         // The frame will be fixed up when |-setMessageText:| is called.
         [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 0, 0)]);
     message_ = message.get();
@@ -95,9 +95,9 @@
   const CGFloat kHorizontalPadding = 30;  // In view coordinates.
 
   // Style the string.
-  scoped_nsobject<NSMutableAttributedString> attrString(
+  base::scoped_nsobject<NSMutableAttributedString> attrString(
       [[NSMutableAttributedString alloc] initWithString:text]);
-  scoped_nsobject<NSShadow> textShadow([[NSShadow alloc] init]);
+  base::scoped_nsobject<NSShadow> textShadow([[NSShadow alloc] init]);
   [textShadow.get() setShadowColor:[NSColor colorWithCalibratedWhite:0
                                                                alpha:0.6]];
   [textShadow.get() setShadowOffset:NSMakeSize(0, -1)];
@@ -192,7 +192,7 @@
 
 - (id)init {
   const NSRect kWindowFrame = NSMakeRect(0, 0, 350, 70);
-  scoped_nsobject<NSWindow> window(
+  base::scoped_nsobject<NSWindow> window(
       [[NSWindow alloc] initWithContentRect:kWindowFrame
                                   styleMask:NSBorderlessWindowMask
                                     backing:NSBackingStoreBuffered
@@ -205,7 +205,7 @@
 
     // Create the content view. Take the frame from the existing content view.
     NSRect frame = [[window contentView] frame];
-    scoped_nsobject<ConfirmQuitFrameView> frameView(
+    base::scoped_nsobject<ConfirmQuitFrameView> frameView(
         [[ConfirmQuitFrameView alloc] initWithFrame:frame]);
     contentView_ = frameView.get();
     [window setContentView:contentView_];
@@ -230,7 +230,7 @@
 }
 
 - (NSApplicationTerminateReply)runModalLoopForApplication:(NSApplication*)app {
-  scoped_nsobject<ConfirmQuitPanelController> keepAlive([self retain]);
+  base::scoped_nsobject<ConfirmQuitPanelController> keepAlive([self retain]);
 
   // If this is the second of two such attempts to quit within a certain time
   // interval, then just quit.
@@ -327,7 +327,7 @@
 - (void)showWindow:(id)sender {
   // If a panel that is fading out is going to be reused here, make sure it
   // does not get released when the animation finishes.
-  scoped_nsobject<ConfirmQuitPanelController> keepAlive([self retain]);
+  base::scoped_nsobject<ConfirmQuitPanelController> keepAlive([self retain]);
   [[self window] setAnimations:[NSDictionary dictionary]];
   [[self window] center];
   [[self window] setAlphaValue:1.0];
@@ -342,7 +342,7 @@
 
 - (void)animateFadeOut {
   NSWindow* window = [self window];
-  scoped_nsobject<CAAnimation> animation(
+  base::scoped_nsobject<CAAnimation> animation(
       [[window animationForKey:@"alphaValue"] copy]);
   [animation setDelegate:self];
   [animation setDuration:0.2];
diff --git a/chrome/browser/ui/cocoa/confirm_quit_panel_controller_unittest.mm b/chrome/browser/ui/cocoa/confirm_quit_panel_controller_unittest.mm
index 0348801..f191e0f 100644
--- a/chrome/browser/ui/cocoa/confirm_quit_panel_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/confirm_quit_panel_controller_unittest.mm
@@ -4,7 +4,6 @@
 
 #import "chrome/browser/ui/cocoa/confirm_quit_panel_controller.h"
 
-#include "base/memory/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #include "chrome/browser/ui/cocoa/confirm_quit.h"
 #include "testing/gtest_mac.h"
diff --git a/chrome/browser/ui/cocoa/constrained_web_dialog_delegate_mac.mm b/chrome/browser/ui/cocoa/constrained_web_dialog_delegate_mac.mm
index 3a718a4..36529a9 100644
--- a/chrome/browser/ui/cocoa/constrained_web_dialog_delegate_mac.mm
+++ b/chrome/browser/ui/cocoa/constrained_web_dialog_delegate_mac.mm
@@ -6,7 +6,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_sheet.h"
 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_window.h"
 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_mac.h"
@@ -95,7 +95,7 @@
  private:
   scoped_ptr<ConstrainedWebDialogDelegateMac> impl_;
   scoped_ptr<ConstrainedWindowMac> constrained_window_;
-  scoped_nsobject<NSWindow> window_;
+  base::scoped_nsobject<NSWindow> window_;
 
   DISALLOW_COPY_AND_ASSIGN(ConstrainedWebDialogDelegateViewMac);
 };
@@ -119,9 +119,8 @@
   [[window_ contentView]
       addSubview:GetWebContents()->GetView()->GetNativeView()];
 
-  scoped_nsobject<CustomConstrainedWindowSheet> sheet(
-      [[CustomConstrainedWindowSheet alloc]
-          initWithCustomWindow:window_]);
+  base::scoped_nsobject<CustomConstrainedWindowSheet> sheet(
+      [[CustomConstrainedWindowSheet alloc] initWithCustomWindow:window_]);
   constrained_window_.reset(new ConstrainedWindowMac(
       this, web_contents, sheet));
 
diff --git a/chrome/browser/ui/cocoa/constrained_window/constrained_window_alert.h b/chrome/browser/ui/cocoa/constrained_window/constrained_window_alert.h
index ac2f34c..389f6a8 100644
--- a/chrome/browser/ui/cocoa/constrained_window/constrained_window_alert.h
+++ b/chrome/browser/ui/cocoa/constrained_window/constrained_window_alert.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 
 // This class implements an alert that has a constrained window look and feel
 // (close button on top right, WebUI style buttons, etc...).  The alert can be
@@ -15,12 +15,12 @@
 // this would be done by ConstrainedWindowSheetController.
 @interface ConstrainedWindowAlert : NSObject {
  @private
-  scoped_nsobject<NSTextField> informativeTextField_;
-  scoped_nsobject<NSTextField> messageTextField_;
-  scoped_nsobject<NSView> accessoryView_;
-  scoped_nsobject<NSMutableArray> buttons_;
-  scoped_nsobject<NSButton> closeButton_;
-  scoped_nsobject<NSWindow> window_;
+  base::scoped_nsobject<NSTextField> informativeTextField_;
+  base::scoped_nsobject<NSTextField> messageTextField_;
+  base::scoped_nsobject<NSView> accessoryView_;
+  base::scoped_nsobject<NSMutableArray> buttons_;
+  base::scoped_nsobject<NSButton> closeButton_;
+  base::scoped_nsobject<NSWindow> window_;
 }
 
 @property(nonatomic, copy) NSString* informativeText;
diff --git a/chrome/browser/ui/cocoa/constrained_window/constrained_window_alert.mm b/chrome/browser/ui/cocoa/constrained_window/constrained_window_alert.mm
index 7fda80b..036c42a 100644
--- a/chrome/browser/ui/cocoa/constrained_window/constrained_window_alert.mm
+++ b/chrome/browser/ui/cocoa/constrained_window/constrained_window_alert.mm
@@ -110,7 +110,7 @@
                     action:(SEL)action {
   if (!buttons_.get())
     buttons_.reset([[NSMutableArray alloc] init]);
-  scoped_nsobject<NSButton> button(
+  base::scoped_nsobject<NSButton> button(
       [[ConstrainedWindowButton alloc] initWithFrame:NSZeroRect]);
   [button setTitle:title];
   [button setKeyEquivalent:keyEquivalent];
diff --git a/chrome/browser/ui/cocoa/constrained_window/constrained_window_alert_unittest.mm b/chrome/browser/ui/cocoa/constrained_window/constrained_window_alert_unittest.mm
index 52f6ca1..868f81d 100644
--- a/chrome/browser/ui/cocoa/constrained_window/constrained_window_alert_unittest.mm
+++ b/chrome/browser/ui/cocoa/constrained_window/constrained_window_alert_unittest.mm
@@ -11,7 +11,7 @@
 
 // Test showing the alert.
 TEST_F(ConstrainedWindowAlertTest, Show) {
-  scoped_nsobject<ConstrainedWindowAlert> alert(
+  base::scoped_nsobject<ConstrainedWindowAlert> alert(
       [[ConstrainedWindowAlert alloc] init]);
   EXPECT_TRUE([alert window]);
   EXPECT_TRUE([alert closeButton]);
@@ -27,7 +27,7 @@
 
 // Test showing the alert with no buttons.
 TEST_F(ConstrainedWindowAlertTest, NoButtons) {
-  scoped_nsobject<ConstrainedWindowAlert> alert(
+  base::scoped_nsobject<ConstrainedWindowAlert> alert(
       [[ConstrainedWindowAlert alloc] init]);
   [alert layout];
   [[alert window] makeKeyAndOrderFront:nil];
@@ -35,13 +35,13 @@
 
 // Test adding an accessory view to an alert.
 TEST_F(ConstrainedWindowAlertTest, AccessoryView) {
-  scoped_nsobject<ConstrainedWindowAlert> alert(
+  base::scoped_nsobject<ConstrainedWindowAlert> alert(
       [[ConstrainedWindowAlert alloc] init]);
   [alert addButtonWithTitle:@"OK" keyEquivalent:@"" target:nil action:NULL];
   [alert addButtonWithTitle:@"Cancel" keyEquivalent:@"" target:nil action:NULL];
 
   NSRect view_rect = NSMakeRect(0, 0, 700, 300);
-  scoped_nsobject<NSView> view([[NSView alloc] initWithFrame:view_rect]);
+  base::scoped_nsobject<NSView> view([[NSView alloc] initWithFrame:view_rect]);
   EXPECT_FALSE([alert accessoryView]);
   [alert setAccessoryView:view];
   EXPECT_NSEQ([alert accessoryView], view);
diff --git a/chrome/browser/ui/cocoa/constrained_window/constrained_window_animation.h b/chrome/browser/ui/cocoa/constrained_window/constrained_window_animation.h
index 3248411..635a6e6 100644
--- a/chrome/browser/ui/cocoa/constrained_window/constrained_window_animation.h
+++ b/chrome/browser/ui/cocoa/constrained_window/constrained_window_animation.h
@@ -7,12 +7,12 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 
 // Base class for all constrained window animation classes.
 @interface ConstrainedWindowAnimationBase : NSAnimation {
  @protected
-  scoped_nsobject<NSWindow> window_;
+  base::scoped_nsobject<NSWindow> window_;
 }
 
 - (id)initWithWindow:(NSWindow*)window;
diff --git a/chrome/browser/ui/cocoa/constrained_window/constrained_window_animation_unittest.mm b/chrome/browser/ui/cocoa/constrained_window/constrained_window_animation_unittest.mm
index 9c7c2bd..5ec022f 100644
--- a/chrome/browser/ui/cocoa/constrained_window/constrained_window_animation_unittest.mm
+++ b/chrome/browser/ui/cocoa/constrained_window/constrained_window_animation_unittest.mm
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/message_loop/message_pump_mac.h"
-#import "chrome/browser/ui/cocoa/constrained_window/constrained_window_animation.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#import "chrome/browser/ui/cocoa/constrained_window/constrained_window_animation.h"
 
 // This class runs an animation for exactly two frames then end it.
 @interface ConstrainedWindowAnimationTestDelegate : NSObject
@@ -57,26 +57,26 @@
     delegate_.reset([[ConstrainedWindowAnimationTestDelegate alloc] init]);
   }
 
-  scoped_nsobject<ConstrainedWindowAnimationTestDelegate> delegate_;
+  base::scoped_nsobject<ConstrainedWindowAnimationTestDelegate> delegate_;
 };
 
 // Test the show animation.
 TEST_F(ConstrainedWindowAnimationTest, Show) {
-  scoped_nsobject<NSAnimation> animation(
+  base::scoped_nsobject<NSAnimation> animation(
       [[ConstrainedWindowAnimationShow alloc] initWithWindow:test_window()]);
   [delegate_ runAnimation:animation];
 }
 
 // Test the hide animation.
 TEST_F(ConstrainedWindowAnimationTest, Hide) {
-  scoped_nsobject<NSAnimation> animation(
+  base::scoped_nsobject<NSAnimation> animation(
       [[ConstrainedWindowAnimationHide alloc] initWithWindow:test_window()]);
   [delegate_ runAnimation:animation];
 }
 
 // Test the pulse animation.
 TEST_F(ConstrainedWindowAnimationTest, Pulse) {
-  scoped_nsobject<NSAnimation> animation(
+  base::scoped_nsobject<NSAnimation> animation(
       [[ConstrainedWindowAnimationPulse alloc] initWithWindow:test_window()]);
   [delegate_ runAnimation:animation];
 }
diff --git a/chrome/browser/ui/cocoa/constrained_window/constrained_window_button.mm b/chrome/browser/ui/cocoa/constrained_window/constrained_window_button.mm
index fb07d84..39e4a3f 100644
--- a/chrome/browser/ui/cocoa/constrained_window/constrained_window_button.mm
+++ b/chrome/browser/ui/cocoa/constrained_window/constrained_window_button.mm
@@ -4,7 +4,7 @@
 
 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_button.h"
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/key_equivalent_constants.h"
 #include "skia/ext/skia_utils_mac.h"
 #import "third_party/molokocacao/NSBezierPath+MCAdditions.h"
@@ -88,13 +88,13 @@
   const SkColor shadow_color[] =
       {0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF};
 
-  scoped_nsobject<NSShadow> shadow([[NSShadow alloc] init]);
+  base::scoped_nsobject<NSShadow> shadow([[NSShadow alloc] init]);
   [shadow setShadowColor:
       gfx::SkColorToCalibratedNSColor(shadow_color[button_state])];
   [shadow setShadowOffset:NSMakeSize(0, -1)];
   [shadow setShadowBlurRadius:0];
 
-  scoped_nsobject<NSMutableParagraphStyle> paragraphStyle(
+  base::scoped_nsobject<NSMutableParagraphStyle> paragraphStyle(
       [[NSMutableParagraphStyle alloc] init]);
   [paragraphStyle setAlignment:NSCenterTextAlignment];
 
diff --git a/chrome/browser/ui/cocoa/constrained_window/constrained_window_button_unittest.mm b/chrome/browser/ui/cocoa/constrained_window/constrained_window_button_unittest.mm
index 3f0628b..ed9b40c 100644
--- a/chrome/browser/ui/cocoa/constrained_window/constrained_window_button_unittest.mm
+++ b/chrome/browser/ui/cocoa/constrained_window/constrained_window_button_unittest.mm
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "base/memory/scoped_nsobject.h"
-#import "chrome/browser/ui/cocoa/constrained_window/constrained_window_button.h"
+#import "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#import "chrome/browser/ui/cocoa/constrained_window/constrained_window_button.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
 
@@ -19,7 +19,7 @@
   }
 
  protected:
-  scoped_nsobject<ConstrainedWindowButton> button_;
+  base::scoped_nsobject<ConstrainedWindowButton> button_;
 };
 
 TEST_VIEW(ConstrainedWindowButtonTest, button_)
diff --git a/chrome/browser/ui/cocoa/constrained_window/constrained_window_control_utils.mm b/chrome/browser/ui/cocoa/constrained_window/constrained_window_control_utils.mm
index 5d73a8f..2be3ee7 100644
--- a/chrome/browser/ui/cocoa/constrained_window/constrained_window_control_utils.mm
+++ b/chrome/browser/ui/cocoa/constrained_window/constrained_window_control_utils.mm
@@ -4,7 +4,7 @@
 
 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_control_utils.h"
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "skia/ext/skia_utils_mac.h"
 
 namespace constrained_window {
@@ -29,7 +29,7 @@
 
   const gfx::Font& font =
       ui::ResourceBundle::GetSharedInstance().GetFont(fontStyle);
-  scoped_nsobject<NSMutableParagraphStyle> paragraphStyle(
+  base::scoped_nsobject<NSMutableParagraphStyle> paragraphStyle(
       [[NSMutableParagraphStyle alloc] init]);
   [paragraphStyle setAlignment:alignment];
   [paragraphStyle setLineBreakMode:lineBreakMode];
diff --git a/chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_sheet.h b/chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_sheet.h
index d1b6007..b36f07e 100644
--- a/chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_sheet.h
+++ b/chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_sheet.h
@@ -7,14 +7,14 @@
 
 #import <Cocoa/Cocoa.h>
 
+#import "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_sheet.h"
-#import "base/memory/scoped_nsobject.h"
 
 // Represents a custom sheet. The sheet's window is shown without using the
 // system |beginSheet:...| API.
 @interface CustomConstrainedWindowSheet : NSObject<ConstrainedWindowSheet> {
  @private
-  scoped_nsobject<NSWindow> customWindow_;
+  base::scoped_nsobject<NSWindow> customWindow_;
 }
 
 - (id)initWithCustomWindow:(NSWindow*)customWindow;
diff --git a/chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_sheet.mm b/chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_sheet.mm
index 28668aa..ab3d83e 100644
--- a/chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_sheet.mm
+++ b/chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_sheet.mm
@@ -17,7 +17,7 @@
 }
 
 - (void)showSheetForWindow:(NSWindow*)window {
-  scoped_nsobject<NSAnimation> animation(
+  base::scoped_nsobject<NSAnimation> animation(
       [[ConstrainedWindowAnimationShow alloc] initWithWindow:customWindow_]);
   [window addChildWindow:customWindow_
                  ordered:NSWindowAbove];
@@ -29,7 +29,7 @@
 
 - (void)closeSheetWithAnimation:(BOOL)withAnimation {
   if (withAnimation) {
-    scoped_nsobject<NSAnimation> animation(
+    base::scoped_nsobject<NSAnimation> animation(
         [[ConstrainedWindowAnimationHide alloc] initWithWindow:customWindow_]);
     [animation startAnimation];
   }
@@ -47,7 +47,7 @@
 }
 
 - (void)pulseSheet {
-  scoped_nsobject<NSAnimation> animation(
+  base::scoped_nsobject<NSAnimation> animation(
       [[ConstrainedWindowAnimationPulse alloc] initWithWindow:customWindow_]);
   [animation startAnimation];
 }
diff --git a/chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_window.mm b/chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_window.mm
index 984b176..cf972e0 100644
--- a/chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_window.mm
+++ b/chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_window.mm
@@ -4,7 +4,7 @@
 
 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_window.h"
 
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/chrome_style.h"
 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_sheet_controller.h"
 #include "skia/ext/skia_utils_mac.h"
@@ -17,7 +17,7 @@
                               styleMask:NSBorderlessWindowMask
                                 backing:NSBackingStoreBuffered
                                   defer:NO])) {
-    scoped_nsobject<NSView> contentView(
+    base::scoped_nsobject<NSView> contentView(
         [[ConstrainedWindowCustomWindowContentView alloc]
             initWithFrame:NSZeroRect]);
     [self setContentView:contentView];
diff --git a/chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_window_unittest.mm b/chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_window_unittest.mm
index f40ac1a..91dc464 100644
--- a/chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_window_unittest.mm
+++ b/chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_window_unittest.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_window.h"
 
@@ -11,7 +11,7 @@
 
 // Simply test creating and drawing the window.
 TEST_F(ConstrainedWindowCustomWindowTest, Basic) {
-  scoped_nsobject<ConstrainedWindowCustomWindow> window(
+  base::scoped_nsobject<ConstrainedWindowCustomWindow> window(
       [[ConstrainedWindowCustomWindow alloc]
           initWithContentRect:NSMakeRect(0, 0, 10, 10)]);
   EXPECT_TRUE([window canBecomeKeyWindow]);
diff --git a/chrome/browser/ui/cocoa/constrained_window/constrained_window_mac.h b/chrome/browser/ui/cocoa/constrained_window/constrained_window_mac.h
index 3707539..73202e8 100644
--- a/chrome/browser/ui/cocoa/constrained_window/constrained_window_mac.h
+++ b/chrome/browser/ui/cocoa/constrained_window/constrained_window_mac.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "components/web_modal/native_web_contents_modal_dialog.h"
 
 namespace content {
@@ -50,7 +50,7 @@
   // The WebContents that owns and constrains this ConstrainedWindowMac. Weak.
   content::WebContents* web_contents_;
 
-  scoped_nsprotocol<id<ConstrainedWindowSheet>> sheet_;
+  base::scoped_nsprotocol<id<ConstrainedWindowSheet>> sheet_;
 
   // This is true if the constrained window has been shown.
   bool shown_;
diff --git a/chrome/browser/ui/cocoa/constrained_window/constrained_window_mac_browsertest.mm b/chrome/browser/ui/cocoa/constrained_window/constrained_window_mac_browsertest.mm
index 6147583..04bc13a 100644
--- a/chrome/browser/ui/cocoa/constrained_window/constrained_window_mac_browsertest.mm
+++ b/chrome/browser/ui/cocoa/constrained_window/constrained_window_mac_browsertest.mm
@@ -66,8 +66,8 @@
   }
 
  protected:
-  scoped_nsobject<CustomConstrainedWindowSheet> sheet_;
-  scoped_nsobject<NSWindow> sheet_window_;
+  base::scoped_nsobject<CustomConstrainedWindowSheet> sheet_;
+  base::scoped_nsobject<NSWindow> sheet_window_;
   content::WebContents* tab0_;
   content::WebContents* tab1_;
   BrowserWindowController* controller_;
@@ -137,7 +137,7 @@
   EXPECT_EQ(1.0, [sheet_window_ alphaValue]);
 
   // Close the browser window.
-  scoped_nsobject<NSWindow> browser_window(
+  base::scoped_nsobject<NSWindow> browser_window(
       [browser()->window()->GetNativeWindow() retain]);
   EXPECT_TRUE([browser_window isVisible]);
   [browser()->window()->GetNativeWindow() performClose:nil];
diff --git a/chrome/browser/ui/cocoa/constrained_window/constrained_window_sheet_controller.h b/chrome/browser/ui/cocoa/constrained_window/constrained_window_sheet_controller.h
index 3223ac2..329594e 100644
--- a/chrome/browser/ui/cocoa/constrained_window/constrained_window_sheet_controller.h
+++ b/chrome/browser/ui/cocoa/constrained_window/constrained_window_sheet_controller.h
@@ -8,8 +8,8 @@
 #import <Cocoa/Cocoa.h>
 #include <vector>
 
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_vector.h"
-#include "base/memory/scoped_nsobject.h"
 
 @protocol ConstrainedWindowSheet;
 
@@ -18,9 +18,9 @@
 // A tab in this case is the |parentView| passed to |-showSheet:forParentView:|.
 @interface ConstrainedWindowSheetController : NSObject {
  @private
-  scoped_nsobject<NSMutableArray> sheets_;
-  scoped_nsobject<NSWindow> parentWindow_;
-  scoped_nsobject<NSView> activeView_;
+  base::scoped_nsobject<NSMutableArray> sheets_;
+  base::scoped_nsobject<NSWindow> parentWindow_;
+  base::scoped_nsobject<NSView> activeView_;
 }
 
 // Returns a sheet controller for |parentWindow|. If a sheet controller does not
diff --git a/chrome/browser/ui/cocoa/constrained_window/constrained_window_sheet_controller.mm b/chrome/browser/ui/cocoa/constrained_window/constrained_window_sheet_controller.mm
index c801d25..b4b4236 100644
--- a/chrome/browser/ui/cocoa/constrained_window/constrained_window_sheet_controller.mm
+++ b/chrome/browser/ui/cocoa/constrained_window/constrained_window_sheet_controller.mm
@@ -25,7 +25,7 @@
 // An invisible overlay window placed on top of the sheet's parent view.
 // This window blocks interaction with the underlying view.
 @interface CWSheetOverlayWindow : NSWindow {
-  scoped_nsobject<ConstrainedWindowSheetController> controller_;
+  base::scoped_nsobject<ConstrainedWindowSheetController> controller_;
 }
 @end
 
@@ -78,7 +78,7 @@
   if (controller)
     return controller;
 
-  scoped_nsobject<ConstrainedWindowSheetController> new_controller(
+  base::scoped_nsobject<ConstrainedWindowSheetController> new_controller(
       [[ConstrainedWindowSheetController alloc]
           initWithParentWindow:parentWindow]);
   if (!g_sheetControllers)
@@ -140,14 +140,13 @@
 
   // Create an invisible overlay window.
   NSRect rect = [self overlayWindowFrameForParentView:parentView];
-  scoped_nsobject<NSWindow> overlayWindow(
-      [[CWSheetOverlayWindow alloc] initWithContentRect:rect
-                                             controller:self]);
+  base::scoped_nsobject<NSWindow> overlayWindow(
+      [[CWSheetOverlayWindow alloc] initWithContentRect:rect controller:self]);
   [parentWindow_ addChildWindow:overlayWindow
                         ordered:NSWindowAbove];
 
   // Add an entry for the sheet.
-  scoped_nsobject<ConstrainedWindowSheetInfo> info(
+  base::scoped_nsobject<ConstrainedWindowSheetInfo> info(
       [[ConstrainedWindowSheetInfo alloc] initWithSheet:sheet
                                              parentView:parentView
                                           overlayWindow:overlayWindow]);
diff --git a/chrome/browser/ui/cocoa/constrained_window/constrained_window_sheet_controller_unittest.mm b/chrome/browser/ui/cocoa/constrained_window/constrained_window_sheet_controller_unittest.mm
index fdba717..562155a 100644
--- a/chrome/browser/ui/cocoa/constrained_window/constrained_window_sheet_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/constrained_window/constrained_window_sheet_controller_unittest.mm
@@ -79,7 +79,8 @@
     NSRect dummyRect = NSMakeRect(0, 0, 50, 50);
     tab_views_.reset([[NSMutableArray alloc] init]);
     for (int i = 0; i < 2; ++i) {
-      scoped_nsobject<NSView> view([[NSView alloc] initWithFrame:dummyRect]);
+      base::scoped_nsobject<NSView> view(
+          [[NSView alloc] initWithFrame:dummyRect]);
       [tab_views_ addObject:view];
     }
     tab0_.reset([[tab_views_ objectAtIndex:0] retain]);
@@ -135,13 +136,13 @@
     EXPECT_EQ(expected_x, NSMinX(sheet_frame));
   }
 
-  scoped_nsobject<NSWindow> sheet_window_;
-  scoped_nsobject<CustomConstrainedWindowSheet> sheet_;
-  scoped_nsobject<ConstrainedWindowSheetController> controller_;
-  scoped_nsobject<NSMutableArray> tab_views_;
-  scoped_nsobject<NSView> active_tab_view_;
-  scoped_nsobject<NSView> tab0_;
-  scoped_nsobject<NSView> tab1_;
+  base::scoped_nsobject<NSWindow> sheet_window_;
+  base::scoped_nsobject<CustomConstrainedWindowSheet> sheet_;
+  base::scoped_nsobject<ConstrainedWindowSheetController> controller_;
+  base::scoped_nsobject<NSMutableArray> tab_views_;
+  base::scoped_nsobject<NSView> active_tab_view_;
+  base::scoped_nsobject<NSView> tab0_;
+  base::scoped_nsobject<NSView> tab1_;
 };
 
 // Test showing then hiding the sheet.
@@ -183,11 +184,11 @@
 
 // Test that two parent windows with two sheet controllers don't conflict.
 TEST_F(ConstrainedWindowSheetControllerTest, TwoParentWindows) {
-  scoped_nsobject<NSWindow> parent_window2([[NSWindow alloc]
-      initWithContentRect:NSMakeRect(0, 0, 30, 30)
-                styleMask:NSTitledWindowMask
-                  backing:NSBackingStoreBuffered
-                    defer:NO]);
+  base::scoped_nsobject<NSWindow> parent_window2(
+      [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 30, 30)
+                                  styleMask:NSTitledWindowMask
+                                    backing:NSBackingStoreBuffered
+                                      defer:NO]);
   [parent_window2 setReleasedWhenClosed:NO];
 
   ConstrainedWindowSheetController* controller2 =
@@ -255,9 +256,9 @@
 
 // Test system sheets.
 TEST_F(ConstrainedWindowSheetControllerTest, SystemSheet) {
-  scoped_nsobject<ConstrainedWindowSystemSheetTest> system_sheet(
+  base::scoped_nsobject<ConstrainedWindowSystemSheetTest> system_sheet(
       [[ConstrainedWindowSystemSheetTest alloc] init]);
-  scoped_nsobject<NSAlert> alert([[NSAlert alloc] init]);
+  base::scoped_nsobject<NSAlert> alert([[NSAlert alloc] init]);
   [system_sheet setAlert:alert];
 
   EXPECT_FALSE([[alert window] isVisible]);
@@ -272,9 +273,9 @@
 
 // Test showing a system sheet on an inactive tab.
 TEST_F(ConstrainedWindowSheetControllerTest, SystemSheetAddToInactiveTab) {
-  scoped_nsobject<ConstrainedWindowSystemSheetTest> system_sheet(
+  base::scoped_nsobject<ConstrainedWindowSystemSheetTest> system_sheet(
       [[ConstrainedWindowSystemSheetTest alloc] init]);
-  scoped_nsobject<NSAlert> alert([[NSAlert alloc] init]);
+  base::scoped_nsobject<NSAlert> alert([[NSAlert alloc] init]);
   [system_sheet setAlert:alert];
 
   EXPECT_FALSE([[alert window] isVisible]);
diff --git a/chrome/browser/ui/cocoa/constrained_window/constrained_window_sheet_info.h b/chrome/browser/ui/cocoa/constrained_window/constrained_window_sheet_info.h
index 0c3c19b..b72e4f6 100644
--- a/chrome/browser/ui/cocoa/constrained_window/constrained_window_sheet_info.h
+++ b/chrome/browser/ui/cocoa/constrained_window/constrained_window_sheet_info.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 
 @protocol ConstrainedWindowSheet;
 
@@ -16,9 +16,9 @@
 // public use.
 @interface ConstrainedWindowSheetInfo : NSObject {
  @private
-  scoped_nsprotocol<id<ConstrainedWindowSheet>> sheet_;
-  scoped_nsobject<NSView> parentView_;
-  scoped_nsobject<NSWindow> overlayWindow_;
+  base::scoped_nsprotocol<id<ConstrainedWindowSheet>> sheet_;
+  base::scoped_nsobject<NSView> parentView_;
+  base::scoped_nsobject<NSWindow> overlayWindow_;
   BOOL sheetDidShow_;
 }
 
diff --git a/chrome/browser/ui/cocoa/content_settings/collected_cookies_mac.h b/chrome/browser/ui/cocoa/content_settings/collected_cookies_mac.h
index 2d0c06b..71d193f 100644
--- a/chrome/browser/ui/cocoa/content_settings/collected_cookies_mac.h
+++ b/chrome/browser/ui/cocoa/content_settings/collected_cookies_mac.h
@@ -4,7 +4,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #include "chrome/browser/browsing_data/cookies_tree_model.h"
 #include "chrome/browser/ui/cocoa/constrained_window/constrained_window_mac.h"
@@ -48,7 +48,7 @@
 
   scoped_ptr<ConstrainedWindowMac> window_;
 
-  scoped_nsobject<CollectedCookiesWindowController> sheet_controller_;
+  base::scoped_nsobject<CollectedCookiesWindowController> sheet_controller_;
 
   DISALLOW_COPY_AND_ASSIGN(CollectedCookiesMac);
 };
@@ -68,11 +68,11 @@
   scoped_ptr<CookiesTreeModel> blockedTreeModel_;
 
   // Cached array of icons.
-  scoped_nsobject<NSMutableArray> icons_;
+  base::scoped_nsobject<NSMutableArray> icons_;
 
   // Our Cocoa copy of the model.
-  scoped_nsobject<CocoaCookieTreeNode> cocoaAllowedTreeModel_;
-  scoped_nsobject<CocoaCookieTreeNode> cocoaBlockedTreeModel_;
+  base::scoped_nsobject<CocoaCookieTreeNode> cocoaAllowedTreeModel_;
+  base::scoped_nsobject<CocoaCookieTreeNode> cocoaBlockedTreeModel_;
 
   BOOL allowedCookiesButtonsEnabled_;
   BOOL blockedCookiesButtonsEnabled_;
@@ -89,9 +89,9 @@
   IBOutlet NSTextField* blockedCookiesText_;
   IBOutlet NSView* cookieDetailsViewPlaceholder_;
 
-  scoped_nsobject<NSViewAnimation> animation_;
+  base::scoped_nsobject<NSViewAnimation> animation_;
 
-  scoped_nsobject<CookieDetailsViewController> detailsViewController_;
+  base::scoped_nsobject<CookieDetailsViewController> detailsViewController_;
 
   content::WebContents* webContents_;  // weak
 
diff --git a/chrome/browser/ui/cocoa/content_settings/collected_cookies_mac.mm b/chrome/browser/ui/cocoa/content_settings/collected_cookies_mac.mm
index f1e44d9..424c512 100644
--- a/chrome/browser/ui/cocoa/content_settings/collected_cookies_mac.mm
+++ b/chrome/browser/ui/cocoa/content_settings/collected_cookies_mac.mm
@@ -82,7 +82,7 @@
       initWithWebContents:web_contents
       collectedCookiesMac:this]);
 
-  scoped_nsobject<CustomConstrainedWindowSheet> sheet(
+  base::scoped_nsobject<CustomConstrainedWindowSheet> sheet(
       [[CustomConstrainedWindowSheet alloc]
           initWithCustomWindow:[sheet_controller_ window]]);
   window_.reset(new ConstrainedWindowMac(
@@ -170,7 +170,7 @@
                                 green:kBannerGradientColorBottom[1]
                                  blue:kBannerGradientColorBottom[2]
                                 alpha:1.0];
-  scoped_nsobject<NSGradient> bannerGradient(
+  base::scoped_nsobject<NSGradient> bannerGradient(
       [[NSGradient alloc] initWithStartingColor:bannerStartingColor
                                     endingColor:bannerEndingColor]);
   [infoBar_ setGradient:bannerGradient];
@@ -243,7 +243,7 @@
     CookieTreeHostNode* host_node =
         static_cast<CookieTreeHostNode*>(cookie);
     host_node->CreateContentException(
-        CookieSettings::Factory::GetForProfile(profile), setting);
+        CookieSettings::Factory::GetForProfile(profile).get(), setting);
     if (!lastDomain.empty())
       multipleDomainsChanged = YES;
     lastDomain = host_node->GetTitle();
@@ -382,7 +382,7 @@
   // Create the Cocoa model.
   CookieTreeNode* root =
       static_cast<CookieTreeNode*>(allowedTreeModel_->GetRoot());
-  scoped_nsobject<CocoaCookieTreeNode> model(
+  base::scoped_nsobject<CocoaCookieTreeNode> model(
       [[CocoaCookieTreeNode alloc] initWithNode:root]);
   [self setCocoaAllowedTreeModel:model.get()];  // Takes ownership.
   root = static_cast<CookieTreeNode*>(blockedTreeModel_->GetRoot());
diff --git a/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa.h b/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa.h
index d6097dd..6781fd3 100644
--- a/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa.h
+++ b/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa.h
@@ -6,7 +6,6 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #import "chrome/browser/ui/cocoa/base_bubble_controller.h"
 #include "content/public/common/media_stream_request.h"
@@ -91,4 +90,4 @@
 // Returns the weak reference to the |mediaMenus_|.
 - (content_setting_bubble::MediaMenuPartsMap*)mediaMenus;
 
-@end
\ No newline at end of file
+@end
diff --git a/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa.mm b/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa.mm
index 7d1c13c..5040e5b 100644
--- a/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa.mm
+++ b/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa.mm
@@ -90,7 +90,7 @@
 
 // Sets the title for the popup button.
 void SetTitleForPopUpButton(NSPopUpButton* button, NSString* title) {
-  scoped_nsobject<NSMenuItem> titleItem([[NSMenuItem alloc] init]);
+  base::scoped_nsobject<NSMenuItem> titleItem([[NSMenuItem alloc] init]);
   [titleItem setTitle:title];
   [[button cell] setUsesItemFromMenu:NO];
   [[button cell] setMenuItem:titleItem.get()];
@@ -293,8 +293,8 @@
                                 title:(NSString*)title
                                  icon:(NSImage*)icon
                        referenceFrame:(NSRect)referenceFrame {
-  scoped_nsobject<HyperlinkButtonCell> cell([[HyperlinkButtonCell alloc]
-      initTextCell:title]);
+  base::scoped_nsobject<HyperlinkButtonCell> cell(
+      [[HyperlinkButtonCell alloc] initTextCell:title]);
   [cell.get() setAlignment:NSNaturalTextAlignment];
   if (icon) {
     [cell.get() setImagePosition:NSImageLeft];
@@ -410,7 +410,7 @@
 
   // "Clear" button / text field.
   if (!content.custom_link.empty()) {
-    scoped_nsobject<NSControl> control;
+    base::scoped_nsobject<NSControl> control;
     if(content.custom_link_enabled) {
       NSRect buttonFrame = NSMakeRect(0, 0,
                                       NSWidth(containerFrame),
@@ -512,7 +512,7 @@
 
     // |buttonFrame| will be resized and repositioned later on.
     NSRect buttonFrame = NSMakeRect(NSMinX(radioFrame), 0, 0, 0);
-    scoped_nsobject<NSPopUpButton> button(
+    base::scoped_nsobject<NSPopUpButton> button(
         [[NSPopUpButton alloc] initWithFrame:buttonFrame]);
     [button setTarget:self];
 
diff --git a/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa_unittest.mm b/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa_unittest.mm
index f7f1a43..fee3a79 100644
--- a/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa_unittest.mm
+++ b/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa_unittest.mm
@@ -7,7 +7,7 @@
 #import <Cocoa/Cocoa.h>
 
 #include "base/mac/scoped_nsautorelease_pool.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/media/media_capture_devices_dispatcher.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #include "chrome/browser/ui/content_settings/content_setting_bubble_model.h"
@@ -48,7 +48,7 @@
   ContentSettingBubbleController* CreateBubbleController(
       ContentSettingsType settingsType);
 
-  scoped_nsobject<NSWindow> parent_;
+  base::scoped_nsobject<NSWindow> parent_;
 
  private:
   base::mac::ScopedNSAutoreleasePool pool_;
diff --git a/chrome/browser/ui/cocoa/content_settings/cookie_details.h b/chrome/browser/ui/cocoa/content_settings/cookie_details.h
index ca439d8..c0c9c84 100644
--- a/chrome/browser/ui/cocoa/content_settings/cookie_details.h
+++ b/chrome/browser/ui/cocoa/content_settings/cookie_details.h
@@ -4,7 +4,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/browsing_data/browsing_data_database_helper.h"
 #include "chrome/browser/browsing_data/browsing_data_indexed_db_helper.h"
 #include "chrome/browser/browsing_data/browsing_data_local_storage_helper.h"
@@ -75,52 +75,52 @@
   BOOL hasExpiration_;
 
   // Only set for type kCocoaCookieDetailsTypeCookie.
-  scoped_nsobject<NSString> content_;
-  scoped_nsobject<NSString> path_;
-  scoped_nsobject<NSString> sendFor_;
+  base::scoped_nsobject<NSString> content_;
+  base::scoped_nsobject<NSString> path_;
+  base::scoped_nsobject<NSString> sendFor_;
   // Stringifed dates.
-  scoped_nsobject<NSString> expires_;
+  base::scoped_nsobject<NSString> expires_;
 
   // Only set for type kCocoaCookieDetailsTypeCookie and
   // kCocoaCookieDetailsTypeTreeAppCache nodes.
-  scoped_nsobject<NSString> created_;
+  base::scoped_nsobject<NSString> created_;
 
   // Only set for types kCocoaCookieDetailsTypeCookie, and
   // kCocoaCookieDetailsTypePromptDatabase nodes.
-  scoped_nsobject<NSString> name_;
+  base::scoped_nsobject<NSString> name_;
 
   // Only set for type kCocoaCookieDetailsTypeTreeLocalStorage,
   // kCocoaCookieDetailsTypeTreeDatabase,
   // kCocoaCookieDetailsTypePromptDatabase,
   // kCocoaCookieDetailsTypeTreeIndexedDB, and
   // kCocoaCookieDetailsTypeTreeAppCache nodes.
-  scoped_nsobject<NSString> fileSize_;
+  base::scoped_nsobject<NSString> fileSize_;
 
   // Only set for types kCocoaCookieDetailsTypeTreeLocalStorage,
   // kCocoaCookieDetailsTypeTreeDatabase, and
   // kCocoaCookieDetailsTypeTreeIndexedDB nodes.
-  scoped_nsobject<NSString> lastModified_;
+  base::scoped_nsobject<NSString> lastModified_;
 
   // Only set for type kCocoaCookieDetailsTypeTreeAppCache nodes.
-  scoped_nsobject<NSString> lastAccessed_;
+  base::scoped_nsobject<NSString> lastAccessed_;
 
   // Only set for type kCocoaCookieDetailsTypeCookie,
   // kCocoaCookieDetailsTypePromptDatabase,
   // kCocoaCookieDetailsTypePromptLocalStorage, and
   // kCocoaCookieDetailsTypeTreeIndexedDB nodes.
-  scoped_nsobject<NSString> domain_;
+  base::scoped_nsobject<NSString> domain_;
 
   // Only set for type kCocoaCookieTreeNodeTypeDatabaseStorage and
   // kCocoaCookieDetailsTypePromptDatabase nodes.
-  scoped_nsobject<NSString> databaseDescription_;
+  base::scoped_nsobject<NSString> databaseDescription_;
 
   // Only set for type kCocoaCookieDetailsTypePromptLocalStorage.
-  scoped_nsobject<NSString> localStorageKey_;
-  scoped_nsobject<NSString> localStorageValue_;
+  base::scoped_nsobject<NSString> localStorageKey_;
+  base::scoped_nsobject<NSString> localStorageValue_;
 
   // Only set for type kCocoaCookieDetailsTypeTreeAppCache and
   // kCocoaCookieDetailsTypePromptAppCache.
-  scoped_nsobject<NSString> manifestURL_;
+  base::scoped_nsobject<NSString> manifestURL_;
 }
 
 @property(nonatomic, readonly) BOOL canEditExpiration;
@@ -213,7 +213,7 @@
 // |CocoaCookieDetails| object for the cookie prompt.
 @interface CookiePromptContentDetailsAdapter : NSObject {
  @private
-  scoped_nsobject<CocoaCookieDetails> details_;
+  base::scoped_nsobject<CocoaCookieDetails> details_;
 }
 
 - (CocoaCookieDetails*)details;
diff --git a/chrome/browser/ui/cocoa/content_settings/cookie_details_unittest.mm b/chrome/browser/ui/cocoa/content_settings/cookie_details_unittest.mm
index 77cd6f7..fed777c 100644
--- a/chrome/browser/ui/cocoa/content_settings/cookie_details_unittest.mm
+++ b/chrome/browser/ui/cocoa/content_settings/cookie_details_unittest.mm
@@ -16,14 +16,14 @@
 };
 
 TEST_F(CookiesDetailsTest, CreateForFolder) {
-  scoped_nsobject<CocoaCookieDetails> details;
+  base::scoped_nsobject<CocoaCookieDetails> details;
   details.reset([[CocoaCookieDetails alloc] initAsFolder]);
 
   EXPECT_EQ([details.get() type], kCocoaCookieDetailsTypeFolder);
 }
 
 TEST_F(CookiesDetailsTest, CreateForCookie) {
-  scoped_nsobject<CocoaCookieDetails> details;
+  base::scoped_nsobject<CocoaCookieDetails> details;
   GURL url("http://chromium.org");
   std::string cookieLine(
       "PHPSESSID=0123456789abcdef0123456789abcdef; path=/");
@@ -53,15 +53,15 @@
 }
 
 TEST_F(CookiesDetailsTest, CreateForTreeDatabase) {
-  scoped_nsobject<CocoaCookieDetails> details;
-  std::string host("http://chromium.org");
+  base::scoped_nsobject<CocoaCookieDetails> details;
+  GURL origin("http://chromium.org");
   std::string database_name("sassolungo");
-  std::string origin_identifier("dolomites");
   std::string description("a great place to climb");
   int64 size = 1234;
   base::Time last_modified = base::Time::Now();
-  BrowsingDataDatabaseHelper::DatabaseInfo info(host, database_name,
-      origin_identifier, description, host, size, last_modified);
+  BrowsingDataDatabaseHelper::DatabaseInfo info(
+      webkit_database::DatabaseIdentifier::CreateFromOrigin(origin),
+      database_name, description, size, last_modified);
   details.reset([[CocoaCookieDetails alloc] initWithDatabase:&info]);
 
   EXPECT_EQ([details.get() type], kCocoaCookieDetailsTypeTreeDatabase);
@@ -80,7 +80,7 @@
 }
 
 TEST_F(CookiesDetailsTest, CreateForTreeLocalStorage) {
-  scoped_nsobject<CocoaCookieDetails> details;
+  base::scoped_nsobject<CocoaCookieDetails> details;
   const GURL kOrigin("http://chromium.org/");
   int64 size = 1234;
   base::Time last_modified = base::Time::Now();
@@ -104,7 +104,7 @@
 }
 
 TEST_F(CookiesDetailsTest, CreateForTreeAppCache) {
-  scoped_nsobject<CocoaCookieDetails> details;
+  base::scoped_nsobject<CocoaCookieDetails> details;
 
   GURL url("http://chromium.org/stuff.manifest");
   appcache::AppCacheInfo info;
@@ -133,7 +133,7 @@
 }
 
 TEST_F(CookiesDetailsTest, CreateForTreeIndexedDB) {
-  scoped_nsobject<CocoaCookieDetails> details;
+  base::scoped_nsobject<CocoaCookieDetails> details;
 
   GURL origin("http://moose.org/");
   int64 size = 1234;
@@ -162,7 +162,7 @@
 }
 
 TEST_F(CookiesDetailsTest, CreateForPromptDatabase) {
-  scoped_nsobject<CocoaCookieDetails> details;
+  base::scoped_nsobject<CocoaCookieDetails> details;
   std::string domain("chromium.org");
   string16 name(base::SysNSStringToUTF16(@"wicked_name"));
   string16 desc(base::SysNSStringToUTF16(@"desc"));
@@ -188,7 +188,7 @@
 }
 
 TEST_F(CookiesDetailsTest, CreateForPromptLocalStorage) {
-  scoped_nsobject<CocoaCookieDetails> details;
+  base::scoped_nsobject<CocoaCookieDetails> details;
   std::string domain("chromium.org");
   string16 key(base::SysNSStringToUTF16(@"testKey"));
   string16 value(base::SysNSStringToUTF16(@"testValue"));
@@ -212,7 +212,7 @@
 }
 
 TEST_F(CookiesDetailsTest, CreateForPromptAppCache) {
-  scoped_nsobject<CocoaCookieDetails> details;
+  base::scoped_nsobject<CocoaCookieDetails> details;
   std::string manifestURL("http://html5demos.com/html5demo.manifest");
   details.reset([[CocoaCookieDetails alloc]
       initWithAppCacheManifestURL:manifestURL.c_str()]);
diff --git a/chrome/browser/ui/cocoa/content_settings/cookie_details_view_controller_unittest.mm b/chrome/browser/ui/cocoa/content_settings/cookie_details_view_controller_unittest.mm
index 29a0806..c901c71 100644
--- a/chrome/browser/ui/cocoa/content_settings/cookie_details_view_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/content_settings/cookie_details_view_controller_unittest.mm
@@ -52,14 +52,14 @@
 }
 
 TEST_F(CookieDetailsViewControllerTest, Create) {
-  scoped_nsobject<CookieDetailsViewController> detailsViewController(
+  base::scoped_nsobject<CookieDetailsViewController> detailsViewController(
       [[CookieDetailsViewController alloc] init]);
 }
 
 TEST_F(CookieDetailsViewControllerTest, ShrinkToFit) {
-  scoped_nsobject<CookieDetailsViewController> detailsViewController(
+  base::scoped_nsobject<CookieDetailsViewController> detailsViewController(
       [[CookieDetailsViewController alloc] init]);
-  scoped_nsobject<CookiePromptContentDetailsAdapter> adapter(
+  base::scoped_nsobject<CookiePromptContentDetailsAdapter> adapter(
       [CreateDatabaseTestContent() retain]);
   [detailsViewController.get() setContentObject:adapter.get()];
   NSRect beforeFrame = [[detailsViewController.get() view] frame];
@@ -70,10 +70,10 @@
 }
 
 TEST_F(CookieDetailsViewControllerTest, ExpirationEditability) {
-  scoped_nsobject<CookieDetailsViewController> detailsViewController(
+  base::scoped_nsobject<CookieDetailsViewController> detailsViewController(
       [[CookieDetailsViewController alloc] init]);
   [detailsViewController view];
-  scoped_nsobject<CookiePromptContentDetailsAdapter> adapter(
+  base::scoped_nsobject<CookiePromptContentDetailsAdapter> adapter(
       [CreateCookieTestContent(YES) retain]);
   [detailsViewController.get() setContentObject:adapter.get()];
 
diff --git a/chrome/browser/ui/cocoa/content_settings/cookie_tree_node.h b/chrome/browser/ui/cocoa/content_settings/cookie_tree_node.h
index 2b95914..1af0a75 100644
--- a/chrome/browser/ui/cocoa/content_settings/cookie_tree_node.h
+++ b/chrome/browser/ui/cocoa/content_settings/cookie_tree_node.h
@@ -4,14 +4,14 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/browsing_data/cookies_tree_model.h"
 #include "chrome/browser/ui/cocoa/content_settings/cookie_details.h"
 
 @interface CocoaCookieTreeNode : NSObject {
-  scoped_nsobject<NSString> title_;
-  scoped_nsobject<NSMutableArray> children_;
-  scoped_nsobject<CocoaCookieDetails> details_;
+  base::scoped_nsobject<NSString> title_;
+  base::scoped_nsobject<NSMutableArray> children_;
+  base::scoped_nsobject<CocoaCookieDetails> details_;
   CookieTreeNode* treeNode_;  // weak
 }
 
diff --git a/chrome/browser/ui/cocoa/content_settings/cookie_tree_node.mm b/chrome/browser/ui/cocoa/content_settings/cookie_tree_node.mm
index a459194..44b97d0 100644
--- a/chrome/browser/ui/cocoa/content_settings/cookie_tree_node.mm
+++ b/chrome/browser/ui/cocoa/content_settings/cookie_tree_node.mm
@@ -43,7 +43,7 @@
     children_.reset([[NSMutableArray alloc] initWithCapacity:childCount]);
     for (int i = 0; i < childCount; ++i) {
       CookieTreeNode* child = treeNode_->GetChild(i);
-      scoped_nsobject<CocoaCookieTreeNode> childNode(
+      base::scoped_nsobject<CocoaCookieTreeNode> childNode(
           [[CocoaCookieTreeNode alloc] initWithNode:child]);
       [children_ addObject:childNode.get()];
     }
diff --git a/chrome/browser/ui/cocoa/custom_frame_view_unittest.mm b/chrome/browser/ui/cocoa/custom_frame_view_unittest.mm
index ee4a5f8..4f061cd 100644
--- a/chrome/browser/ui/cocoa/custom_frame_view_unittest.mm
+++ b/chrome/browser/ui/cocoa/custom_frame_view_unittest.mm
@@ -6,7 +6,7 @@
 #include <objc/runtime.h>
 
 #include "base/mac/mac_util.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/custom_frame_view.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
@@ -24,7 +24,7 @@
     view_.reset([[customFrameClass alloc] initWithFrame:frame]);
   }
 
-  scoped_nsobject<NSView> view_;
+  base::scoped_nsobject<NSView> view_;
 };
 
 //  Test to make sure our class modifications were successful.
diff --git a/chrome/browser/ui/cocoa/dev_tools_controller.h b/chrome/browser/ui/cocoa/dev_tools_controller.h
index 554b8ab..cfb12c6 100644
--- a/chrome/browser/ui/cocoa/dev_tools_controller.h
+++ b/chrome/browser/ui/cocoa/dev_tools_controller.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/devtools/devtools_window.h"
 
 @class GraySplitView;
@@ -23,7 +23,7 @@
 @interface DevToolsController : NSObject<NSSplitViewDelegate> {
  @private
   // A view hosting docked devTools contents.
-  scoped_nsobject<GraySplitView> splitView_;
+  base::scoped_nsobject<GraySplitView> splitView_;
 
   DevToolsDockSide dockSide_;
 
@@ -47,9 +47,6 @@
 - (void)updateDevToolsForWebContents:(content::WebContents*)contents
                          withProfile:(Profile*)profile;
 
-- (CGFloat)topContentOffset;
-- (void)setTopContentOffset:(CGFloat)offset;
-
 @end
 
 #endif  // CHROME_BROWSER_UI_COCOA_DEV_TOOLS_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/dev_tools_controller.mm b/chrome/browser/ui/cocoa/dev_tools_controller.mm
index c495d1f..d9e5b77 100644
--- a/chrome/browser/ui/cocoa/dev_tools_controller.mm
+++ b/chrome/browser/ui/cocoa/dev_tools_controller.mm
@@ -8,7 +8,6 @@
 
 #include <Cocoa/Cocoa.h>
 
-#import "base/mac/foundation_util.h"
 #include "base/prefs/pref_service.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/profile.h"
@@ -20,11 +19,9 @@
 using content::WebContents;
 
 @interface GraySplitView : NSSplitView {
-  CGFloat topContentOffset_;
   BOOL dividerHidden_;
 }
 
-@property(assign, nonatomic) CGFloat topContentOffset;
 @property(assign, nonatomic) BOOL dividerHidden;
 
 - (NSColor*)dividerColor;
@@ -35,7 +32,6 @@
 
 @implementation GraySplitView
 
-@synthesize topContentOffset = topContentOffset_;
 @synthesize dividerHidden = dividerHidden_;
 
 - (NSColor*)dividerColor {
@@ -46,29 +42,12 @@
   return dividerHidden_ ? 0 : [super dividerThickness];
 }
 
-- (void)drawDividerInRect:(NSRect)aRect {
-  NSRect dividerRect = aRect;
-  if ([self isVertical]) {
-    dividerRect.size.height -= topContentOffset_;
-    dividerRect.origin.y += topContentOffset_;
-  }
-  [super drawDividerInRect:dividerRect];
-}
-
-- (NSView*)hitTest:(NSPoint)point {
-  NSPoint viewPoint = [self convertPoint:point fromView:[self superview]];
-  if (viewPoint.y < topContentOffset_)
-    return nil;
-  return [super hitTest:point];
-}
-
 @end
 
 @interface DevToolsController (Private)
 - (void)showDevToolsContainer;
 - (void)hideDevToolsContainer;
 - (void)updateDevToolsSplitPosition;
-- (void)updateDevToolsViewFrame;
 @end
 
 
@@ -136,16 +115,6 @@
   }
 }
 
-- (CGFloat)topContentOffset {
-  return [splitView_ topContentOffset];
-}
-
-- (void)setTopContentOffset:(CGFloat)offset {
-  [splitView_ setTopContentOffset:offset];
-  if ([[splitView_ subviews] count] > 1)
-    [self updateDevToolsViewFrame];
-}
-
 - (void)showDevToolsContainer {
   NSArray* subviews = [splitView_ subviews];
   DCHECK_EQ([subviews count], 1u);
@@ -156,18 +125,11 @@
   // VIEW_ID_DEV_TOOLS_DOCKED here.
   NSView* devToolsView = devToolsContents->GetView()->GetNativeView();
   view_id_util::SetID(devToolsView, VIEW_ID_DEV_TOOLS_DOCKED);
-  [devToolsView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
-
-  NSRect containerRect = NSMakeRect(0, 0, 100, 100);
-  scoped_nsobject<NSView> devToolsContainerView(
-      [[NSView alloc] initWithFrame:containerRect]);
-  [devToolsContainerView addSubview:devToolsView];
-  [splitView_ addSubview:devToolsContainerView];
+  [splitView_ addSubview:devToolsView];
 
   BOOL isVertical = devToolsWindow_->dock_side() == DEVTOOLS_DOCK_SIDE_RIGHT;
   [splitView_ setVertical:isVertical];
   [self updateDevToolsSplitPosition];
-  [self updateDevToolsViewFrame];
 }
 
 - (void)hideDevToolsContainer {
@@ -215,15 +177,6 @@
   [splitView_ adjustSubviews];
 }
 
-- (void)updateDevToolsViewFrame {
-  NSView* devToolsView =
-      devToolsWindow_->web_contents()->GetView()->GetNativeView();
-  NSRect devToolsRect = [[devToolsView superview] bounds];
-  if (devToolsWindow_->dock_side() == DEVTOOLS_DOCK_SIDE_RIGHT)
-    devToolsRect.size.height -= [splitView_ topContentOffset];
-  [devToolsView setFrame:devToolsRect];
-}
-
 // NSSplitViewDelegate protocol.
 - (BOOL)splitView:(NSSplitView *)splitView
     shouldAdjustSizeOfSubview:(NSView *)subview {
@@ -236,16 +189,6 @@
   return YES;
 }
 
-- (CGFloat)splitView:(NSSplitView*)splitView
-    constrainSplitPosition:(CGFloat)proposedPosition
-               ofSubviewAt:(NSInteger)dividerIndex {
-  if (![splitView_ isVertical] &&
-      proposedPosition < [splitView_ topContentOffset]) {
-    return [splitView_ topContentOffset];
-  }
-  return proposedPosition;
-}
-
 - (NSRect)splitView:(NSSplitView*)splitView
       effectiveRect:(NSRect)proposedEffectiveRect
        forDrawnRect:(NSRect)drawnRect
diff --git a/chrome/browser/ui/cocoa/dev_tools_controller_browsertest.mm b/chrome/browser/ui/cocoa/dev_tools_controller_browsertest.mm
index 2c61e80..cffd2a7 100644
--- a/chrome/browser/ui/cocoa/dev_tools_controller_browsertest.mm
+++ b/chrome/browser/ui/cocoa/dev_tools_controller_browsertest.mm
@@ -26,115 +26,10 @@
                                          DEVTOOLS_TOGGLE_ACTION_SHOW);
   }
 
-  DevToolsController* controller() {
-    NSWindow* window = browser()->window()->GetNativeWindow();
-    BrowserWindowController* window_controller =
-        [BrowserWindowController browserWindowControllerForWindow:window];
-    return [window_controller devToolsController];
-  }
-
-  void SetDockSide(DevToolsDockSide side) {
-    content::WebContents* web_contents =
-        browser()->tab_strip_model()->GetActiveWebContents();
-    DevToolsWindow* dev_tools =
-        DevToolsWindow::GetDockedInstanceForInspectedTab(web_contents);
-    dev_tools->SetDockSide(dev_tools->SideToString(side));
-  }
-
  private:
   DISALLOW_COPY_AND_ASSIGN(DevToolsControllerTest);
 };
 
-// Verify that in horizontal mode the splitter is not allowed to go past the
-// bookmark bar.
-IN_PROC_BROWSER_TEST_F(DevToolsControllerTest, ConstrainSplitter) {
-  [controller() setTopContentOffset:0];
-  EXPECT_EQ(0, [controller() splitView:[controller() splitView]
-                constrainSplitPosition:0
-                           ofSubviewAt:0]);
-
-  CGFloat offset = 50;
-  [controller() setTopContentOffset:offset];
-  EXPECT_EQ(offset, [controller() splitView:[controller() splitView]
-                     constrainSplitPosition:0
-                                ofSubviewAt:0]);
-
-  // Should not be constrained in vertical mode.
-  [[controller() splitView] setVertical:YES];
-  EXPECT_EQ(0, [controller() splitView:[controller() splitView]
-                constrainSplitPosition:0
-                           ofSubviewAt:0]);
-}
-
-// When docked to the right the dev tools view should be shrunk so that it
-// doesn't overlap the bookmark bar.
-IN_PROC_BROWSER_TEST_F(DevToolsControllerTest, ViewSize) {
-  EXPECT_EQ(2u, [[[controller() splitView] subviews] count]);
-  NSView* container_view = [[[controller() splitView] subviews] lastObject];
-  EXPECT_EQ(1u, [[container_view subviews] count]);
-  NSView* dev_tools_view = [[container_view subviews] lastObject];
-  CGFloat width = NSWidth([[controller() splitView] bounds]);
-  CGFloat height = NSHeight([[controller() splitView] bounds]);
-  CGFloat offset = [controller() topContentOffset];
-
-  SetDockSide(DEVTOOLS_DOCK_SIDE_BOTTOM);
-  EXPECT_EQ(width, NSWidth([dev_tools_view bounds]));
-
-  SetDockSide(DEVTOOLS_DOCK_SIDE_RIGHT);
-  EXPECT_EQ(height - offset, NSHeight([dev_tools_view bounds]));
-
-  CGFloat new_offset = 50;
-  [controller() setTopContentOffset:new_offset];
-
-  SetDockSide(DEVTOOLS_DOCK_SIDE_BOTTOM);
-  EXPECT_EQ(width, NSWidth([dev_tools_view bounds]));
-
-  SetDockSide(DEVTOOLS_DOCK_SIDE_RIGHT);
-  EXPECT_EQ(height - new_offset, NSHeight([dev_tools_view bounds]));
-}
-
-// Verify that the dev tool's web view is layed out correctly when docked to the
-// right.
-IN_PROC_BROWSER_TEST_F(DevToolsControllerTest, WebViewLayout) {
-  CGFloat offset = 50;
-  [controller() setTopContentOffset:offset];
-
-  SetDockSide(DEVTOOLS_DOCK_SIDE_RIGHT);
-  AddTabAtIndex(
-      0, GURL(content::kAboutBlankURL), content::PAGE_TRANSITION_TYPED);
-  DevToolsWindow::ToggleDevToolsWindow(browser(), DEVTOOLS_TOGGLE_ACTION_SHOW);
-
-  NSView* container_view = [[[controller() splitView] subviews] lastObject];
-  NSView* dev_tools_view = [[container_view subviews] lastObject];
-  NSView* web_view = [[dev_tools_view subviews] lastObject];
-
-  CGFloat height = NSHeight([[controller() splitView] bounds]);
-
-  EXPECT_EQ(height - offset, NSHeight([web_view bounds]));
-  EXPECT_EQ(0, NSMinY([web_view bounds]));
-
-  // Update the offset and verify that the view is resized.
-  CGFloat new_offset = 25;
-  [controller() setTopContentOffset:new_offset];
-  EXPECT_EQ(height - new_offset, NSHeight([web_view bounds]));
-  EXPECT_EQ(0, NSMinY([web_view bounds]));
-}
-
-// Verify that the dev tools undocked window is layed out correctly.
-IN_PROC_BROWSER_TEST_F(DevToolsControllerTest, UndockedOffset) {
-  BrowserList* browser_list =
-      BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_NATIVE);
-  EXPECT_EQ(1u, browser_list->size());
-  SetDockSide(DEVTOOLS_DOCK_SIDE_UNDOCKED);
-  EXPECT_EQ(2u, browser_list->size());
-
-  Browser* dev_tools_browser = browser_list->get(1);
-  BrowserWindowController* window_controller =
-      [BrowserWindowController browserWindowControllerForWindow:
-              dev_tools_browser->window()->GetNativeWindow()];
-  EXPECT_EQ(0.0, [[window_controller devToolsController] topContentOffset]);
-}
-
 // Verify that AllowOverlappingViews is set while the find bar is visible.
 IN_PROC_BROWSER_TEST_F(DevToolsControllerTest, AllowOverlappingViews) {
   content::WebContents* web_contents =
diff --git a/chrome/browser/ui/cocoa/dock_icon.h b/chrome/browser/ui/cocoa/dock_icon.h
index ee1cd8c..259171a 100644
--- a/chrome/browser/ui/cocoa/dock_icon.h
+++ b/chrome/browser/ui/cocoa/dock_icon.h
@@ -4,7 +4,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/time.h"
+#include "base/time/time.h"
 
 // A class representing the dock icon of the Chromium app. It's its own class
 // since several parts of the app want to manipulate the display of the dock
diff --git a/chrome/browser/ui/cocoa/dock_icon.mm b/chrome/browser/ui/cocoa/dock_icon.mm
index d70618d..f6bf5ae 100644
--- a/chrome/browser/ui/cocoa/dock_icon.mm
+++ b/chrome/browser/ui/cocoa/dock_icon.mm
@@ -6,7 +6,7 @@
 
 #include "base/logging.h"
 #include "base/mac/bundle_locations.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "content/public/browser/browser_thread.h"
 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
 
@@ -85,7 +85,7 @@
   NSColor* backgroundHighlight =
       [backgroundColor blendedColorWithFraction:0.85
                                         ofColor:[NSColor whiteColor]];
-  scoped_nsobject<NSGradient> backgroundGradient(
+  base::scoped_nsobject<NSGradient> backgroundGradient(
       [[NSGradient alloc] initWithStartingColor:backgroundHighlight
                                     endingColor:backgroundColor]);
   NSBezierPath* badgeEdge = [NSBezierPath bezierPathWithOvalInRect:badgeRect];
@@ -108,7 +108,7 @@
     NSColor* sliceHighlight =
         [sliceColor blendedColorWithFraction:0.4
                                      ofColor:[NSColor whiteColor]];
-    scoped_nsobject<NSGradient> sliceGradient(
+    base::scoped_nsobject<NSGradient> sliceGradient(
         [[NSGradient alloc] initWithStartingColor:sliceHighlight
                                       endingColor:sliceColor]);
     NSBezierPath* progressSlice;
@@ -140,7 +140,7 @@
   {
     gfx::ScopedNSGraphicsContextSaveGState scopedGState;
     [[NSColor whiteColor] set];
-    scoped_nsobject<NSShadow> shadow([[NSShadow alloc] init]);
+    base::scoped_nsobject<NSShadow> shadow([[NSShadow alloc] init]);
     [shadow.get() setShadowOffset:NSMakeSize(0, -2)];
     [shadow setShadowBlurRadius:2];
     [shadow set];
@@ -149,12 +149,12 @@
   }
 
   // Download count
-  scoped_nsobject<NSNumberFormatter> formatter(
+  base::scoped_nsobject<NSNumberFormatter> formatter(
       [[NSNumberFormatter alloc] init]);
   NSString* countString =
       [formatter stringFromNumber:[NSNumber numberWithInt:downloads_]];
 
-  scoped_nsobject<NSShadow> countShadow([[NSShadow alloc] init]);
+  base::scoped_nsobject<NSShadow> countShadow([[NSShadow alloc] init]);
   [countShadow setShadowBlurRadius:3.0];
   [countShadow.get() setShadowColor:[NSColor whiteColor]];
   [countShadow.get() setShadowOffset:NSMakeSize(0.0, 0.0)];
@@ -165,7 +165,7 @@
           nil];
   CGFloat countFontSize = badgeRadius;
   NSSize countSize = NSZeroSize;
-  scoped_nsobject<NSAttributedString> countAttrString;
+  base::scoped_nsobject<NSAttributedString> countAttrString;
   while (1) {
     NSFont* countFont = [NSFont fontWithName:@"Helvetica-Bold"
                                         size:countFontSize];
@@ -207,7 +207,8 @@
   if (!icon) {
     NSDockTile* dockTile = [[NSApplication sharedApplication] dockTile];
 
-    scoped_nsobject<DockTileView> dockTileView([[DockTileView alloc] init]);
+    base::scoped_nsobject<DockTileView> dockTileView(
+        [[DockTileView alloc] init]);
     [dockTile setContentView:dockTileView];
 
     icon = [[DockIcon alloc] init];
diff --git a/chrome/browser/ui/cocoa/download/background_theme.h b/chrome/browser/ui/cocoa/download/background_theme.h
index 7751965..d044fe1 100644
--- a/chrome/browser/ui/cocoa/download/background_theme.h
+++ b/chrome/browser/ui/cocoa/download/background_theme.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "ui/base/theme_provider.h"
 
 class BackgroundTheme : public ui::ThemeProvider {
@@ -33,9 +33,9 @@
 
  private:
   ui::ThemeProvider* provider_;
-  scoped_nsobject<NSGradient> buttonGradient_;
-  scoped_nsobject<NSGradient> buttonPressedGradient_;
-  scoped_nsobject<NSColor> borderColor_;
+  base::scoped_nsobject<NSGradient> buttonGradient_;
+  base::scoped_nsobject<NSGradient> buttonPressedGradient_;
+  base::scoped_nsobject<NSColor> borderColor_;
 };
 
 #endif  // CHROME_BROWSER_UI_COCOA_DOWNLOAD_BACKGROUND_THEME_H_
diff --git a/chrome/browser/ui/cocoa/download/download_item_button.mm b/chrome/browser/ui/cocoa/download/download_item_button.mm
index 67920fe..4bfd70f 100644
--- a/chrome/browser/ui/cocoa/download/download_item_button.mm
+++ b/chrome/browser/ui/cocoa/download/download_item_button.mm
@@ -34,7 +34,7 @@
   } else {
     // Hold a reference to our controller in case the download completes and we
     // represent a file that's auto-removed (e.g. a theme).
-    scoped_nsobject<DownloadItemController> ref([controller_ retain]);
+    base::scoped_nsobject<DownloadItemController> ref([controller_ retain]);
     [cell setHighlighted:YES];
     [[self menu] setDelegate:self];
     [NSMenu popUpContextMenu:[self menu]
@@ -46,7 +46,7 @@
 // Override to retain the controller, in case a closure is pumped that deletes
 // the DownloadItemController while the menu is open <http://crbug.com/129826>.
 - (void)rightMouseDown:(NSEvent*)event {
-  scoped_nsobject<DownloadItemController> ref([controller_ retain]);
+  base::scoped_nsobject<DownloadItemController> ref([controller_ retain]);
   [super rightMouseDown:event];
 }
 
diff --git a/chrome/browser/ui/cocoa/download/download_item_button_unittest.mm b/chrome/browser/ui/cocoa/download/download_item_button_unittest.mm
index 6fc6b43..e6f07e9 100644
--- a/chrome/browser/ui/cocoa/download/download_item_button_unittest.mm
+++ b/chrome/browser/ui/cocoa/download/download_item_button_unittest.mm
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/memory/scoped_nsobject.h"
-#import "chrome/browser/ui/cocoa/download/download_item_button.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#import "chrome/browser/ui/cocoa/download/download_item_button.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
 
 // Make sure nothing leaks.
 TEST(DownloadItemButtonTest, Create) {
-  scoped_nsobject<DownloadItemButton> button;
+  base::scoped_nsobject<DownloadItemButton> button;
   button.reset([[DownloadItemButton alloc]
       initWithFrame:NSMakeRect(0,0,500,500)]);
 
diff --git a/chrome/browser/ui/cocoa/download/download_item_cell.h b/chrome/browser/ui/cocoa/download/download_item_cell.h
index c73f9c8..9e01975 100644
--- a/chrome/browser/ui/cocoa/download/download_item_cell.h
+++ b/chrome/browser/ui/cocoa/download/download_item_cell.h
@@ -30,23 +30,23 @@
   // Track which part of the button the mouse is over
   DownloadItemMousePosition mousePosition_;
   int mouseInsideCount_;
-  scoped_nsobject<NSTrackingArea> trackingAreaButton_;
-  scoped_nsobject<NSTrackingArea> trackingAreaDropdown_;
+  base::scoped_nsobject<NSTrackingArea> trackingAreaButton_;
+  base::scoped_nsobject<NSTrackingArea> trackingAreaDropdown_;
 
   base::FilePath downloadPath_;  // stored unelided
   NSString* secondaryTitle_;
   NSFont* secondaryFont_;
   int percentDone_;
-  scoped_nsobject<NSAnimation> completionAnimation_;
+  base::scoped_nsobject<NSAnimation> completionAnimation_;
 
   // In degrees, for downloads with no known total size.
   int indeterminateProgressAngle_;
-  scoped_nsobject<IndeterminateProgressTimer> indeterminateProgressTimer_;
+  base::scoped_nsobject<IndeterminateProgressTimer> indeterminateProgressTimer_;
 
   BOOL isStatusTextVisible_;
   CGFloat titleY_;
   CGFloat statusAlpha_;
-  scoped_nsobject<NSAnimation> toggleStatusVisibilityAnimation_;
+  base::scoped_nsobject<NSAnimation> toggleStatusVisibilityAnimation_;
 
   scoped_ptr<ui::ThemeProvider> themeProvider_;
 }
diff --git a/chrome/browser/ui/cocoa/download/download_item_cell.mm b/chrome/browser/ui/cocoa/download/download_item_cell.mm
index 2a47782..f6af374 100644
--- a/chrome/browser/ui/cocoa/download/download_item_cell.mm
+++ b/chrome/browser/ui/cocoa/download/download_item_cell.mm
@@ -96,7 +96,7 @@
 @interface IndeterminateProgressTimer : NSObject {
  @private
   DownloadItemCell* cell_;
-  scoped_nsobject<NSTimer> timer_;
+  base::scoped_nsobject<NSTimer> timer_;
 }
 
 - (id)initWithDownloadItemCell:(DownloadItemCell*)cell;
@@ -621,7 +621,7 @@
 
   gfx::ScopedNSGraphicsContextSaveGState scopedGState;
 
-  scoped_nsobject<NSShadow> shadow([[NSShadow alloc] init]);
+  base::scoped_nsobject<NSShadow> shadow([[NSShadow alloc] init]);
   [shadow.get() setShadowColor:[NSColor whiteColor]];
   [shadow.get() setShadowOffset:NSMakeSize(0, -1)];
   [shadow setShadowBlurRadius:0.0];
diff --git a/chrome/browser/ui/cocoa/download/download_item_cell_unittest.mm b/chrome/browser/ui/cocoa/download/download_item_cell_unittest.mm
index b68f36f..ef4aa54 100644
--- a/chrome/browser/ui/cocoa/download/download_item_cell_unittest.mm
+++ b/chrome/browser/ui/cocoa/download/download_item_cell_unittest.mm
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/download/download_item_model.h"
-#import "chrome/browser/ui/cocoa/download/download_item_cell.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#import "chrome/browser/ui/cocoa/download/download_item_cell.h"
 #include "content/public/test/mock_download_item.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
@@ -32,8 +32,8 @@
   }
 
  protected:
-  scoped_nsobject<DownloadItemCell> cell_;
-  scoped_nsobject<NSButton> button_;
+  base::scoped_nsobject<DownloadItemCell> cell_;
+  base::scoped_nsobject<NSButton> button_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(DownloadItemCellTest);
diff --git a/chrome/browser/ui/cocoa/download/download_item_controller.h b/chrome/browser/ui/cocoa/download/download_item_controller.h
index b7b25f5..b188a87 100644
--- a/chrome/browser/ui/cocoa/download/download_item_controller.h
+++ b/chrome/browser/ui/cocoa/download/download_item_controller.h
@@ -5,7 +5,7 @@
 #import <Cocoa/Cocoa.h>
 
 #include "base/memory/scoped_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
 
 @class ChromeUILocalizer;
 @class DownloadItemCell;
diff --git a/chrome/browser/ui/cocoa/download/download_item_mac.h b/chrome/browser/ui/cocoa/download/download_item_mac.h
index 363dd33..6d77801 100644
--- a/chrome/browser/ui/cocoa/download/download_item_mac.h
+++ b/chrome/browser/ui/cocoa/download/download_item_mac.h
@@ -7,8 +7,6 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
-#include "base/memory/scoped_ptr.h"
 #include "chrome/browser/download/download_item_model.h"
 #include "chrome/browser/icon_manager.h"
 #include "chrome/common/cancelable_task_tracker.h"
diff --git a/chrome/browser/ui/cocoa/download/download_shelf_controller.h b/chrome/browser/ui/cocoa/download/download_shelf_controller.h
index a71cf8e..c264571 100644
--- a/chrome/browser/ui/cocoa/download/download_shelf_controller.h
+++ b/chrome/browser/ui/cocoa/download/download_shelf_controller.h
@@ -4,10 +4,10 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
-#include "ui/base/cocoa/tracking_area.h"
 #import "chrome/browser/ui/cocoa/view_resizer.h"
+#include "ui/base/cocoa/tracking_area.h"
 
 @class AnimatableView;
 class Browser;
@@ -71,7 +71,7 @@
   ui::ScopedCrTrackingArea trackingArea_;
 
   // The download items we have added to our shelf.
-  scoped_nsobject<NSMutableArray> downloadItemControllers_;
+  base::scoped_nsobject<NSMutableArray> downloadItemControllers_;
 
   // The container that contains (and clamps) all the download items.
   IBOutlet NSView* itemContainerView_;
diff --git a/chrome/browser/ui/cocoa/download/download_shelf_controller.mm b/chrome/browser/ui/cocoa/download/download_shelf_controller.mm
index e0b8eae..be8355b 100644
--- a/chrome/browser/ui/cocoa/download/download_shelf_controller.mm
+++ b/chrome/browser/ui/cocoa/download/download_shelf_controller.mm
@@ -300,7 +300,7 @@
 
 - (void)addDownloadItem:(DownloadItem*)downloadItem {
   DCHECK([NSThread isMainThread]);
-  scoped_nsobject<DownloadItemController> controller(
+  base::scoped_nsobject<DownloadItemController> controller(
       [[DownloadItemController alloc] initWithDownload:downloadItem
                                                  shelf:self
                                              navigator:navigator_]);
diff --git a/chrome/browser/ui/cocoa/download/download_shelf_controller_unittest.mm b/chrome/browser/ui/cocoa/download/download_shelf_controller_unittest.mm
index ed952c3..8ce96ca 100644
--- a/chrome/browser/ui/cocoa/download/download_shelf_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/download/download_shelf_controller_unittest.mm
@@ -4,7 +4,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #include "chrome/browser/download/download_shelf.h"
 #include "chrome/browser/ui/cocoa/cocoa_profile_test.h"
@@ -110,8 +110,8 @@
  protected:
   id CreateItemController();
 
-  scoped_nsobject<CountingDownloadShelfController> shelf_;
-  scoped_nsobject<ViewResizerPong> resize_delegate_;
+  base::scoped_nsobject<CountingDownloadShelfController> shelf_;
+  base::scoped_nsobject<ViewResizerPong> resize_delegate_;
 };
 
 id DownloadShelfControllerTest::CreateItemController() {
@@ -122,12 +122,12 @@
   ON_CALL(*download.get(), GetState())
       .WillByDefault(Return(content::DownloadItem::IN_PROGRESS));
 
-  scoped_nsobject<WrappedMockDownloadItem> wrappedMockDownload(
+  base::scoped_nsobject<WrappedMockDownloadItem> wrappedMockDownload(
       [[WrappedMockDownloadItem alloc] initWithMockDownload:download.Pass()]);
 
   id item_controller =
       [OCMockObject mockForClass:[DownloadItemController class]];
-  scoped_nsobject<NSView> view([[NSView alloc] initWithFrame:NSZeroRect]);
+  base::scoped_nsobject<NSView> view([[NSView alloc] initWithFrame:NSZeroRect]);
   [[[item_controller stub] andCall:@selector(download)
                           onObject:wrappedMockDownload.get()] download];
   [[item_controller stub] updateVisibility:[OCMArg any]];
@@ -144,7 +144,7 @@
 // Removing the last download from the shelf should cause it to close
 // immediately.
 TEST_F(DownloadShelfControllerTest, AddAndRemoveDownload) {
-  scoped_nsobject<DownloadItemController> item(CreateItemController());
+  base::scoped_nsobject<DownloadItemController> item(CreateItemController());
   [shelf_ showDownloadShelf:YES
                isUserAction:NO];
   EXPECT_TRUE([shelf_ isVisible]);
@@ -160,8 +160,8 @@
 // Test that the shelf doesn't close automatically after a removal if there are
 // active download items still on the shelf.
 TEST_F(DownloadShelfControllerTest, AddAndRemoveWithActiveItem) {
-  scoped_nsobject<DownloadItemController> item1(CreateItemController());
-  scoped_nsobject<DownloadItemController> item2(CreateItemController());
+  base::scoped_nsobject<DownloadItemController> item1(CreateItemController());
+  base::scoped_nsobject<DownloadItemController> item2(CreateItemController());
   [shelf_ showDownloadShelf:YES
                isUserAction:NO];
   EXPECT_TRUE([shelf_ isVisible]);
@@ -177,7 +177,7 @@
 // DownloadShelf::Unhide() should cause the shelf to be displayed if there are
 // active downloads on it.
 TEST_F(DownloadShelfControllerTest, HideAndUnhide) {
-  scoped_nsobject<DownloadItemController> item(CreateItemController());
+  base::scoped_nsobject<DownloadItemController> item(CreateItemController());
   [shelf_ showDownloadShelf:YES
                isUserAction:NO];
   EXPECT_TRUE([shelf_ isVisible]);
@@ -193,7 +193,7 @@
 // DownloadShelf::Unhide() shouldn't cause the shelf to be displayed if all
 // active downloads are removed from the shelf while the shelf was hidden.
 TEST_F(DownloadShelfControllerTest, HideAutocloseUnhide) {
-  scoped_nsobject<DownloadItemController> item(CreateItemController());
+  base::scoped_nsobject<DownloadItemController> item(CreateItemController());
   [shelf_ showDownloadShelf:YES
                isUserAction:NO];
   EXPECT_TRUE([shelf_ isVisible]);
@@ -209,7 +209,7 @@
 // Test of autoclosing behavior after opening a download item. The mouse is on
 // the download shelf at the time the autoclose is scheduled.
 TEST_F(DownloadShelfControllerTest, AutoCloseAfterOpenWithMouseInShelf) {
-  scoped_nsobject<DownloadItemController> item(CreateItemController());
+  base::scoped_nsobject<DownloadItemController> item(CreateItemController());
   [shelf_ showDownloadShelf:YES
                isUserAction:NO];
   EXPECT_TRUE([shelf_ isVisible]);
@@ -246,7 +246,7 @@
 
 // Test of autoclosing behavior after opening a download item.
 TEST_F(DownloadShelfControllerTest, AutoCloseAfterOpenWithMouseOffShelf) {
-  scoped_nsobject<DownloadItemController> item(CreateItemController());
+  base::scoped_nsobject<DownloadItemController> item(CreateItemController());
   [shelf_ showDownloadShelf:YES
                isUserAction:NO];
   EXPECT_TRUE([shelf_ isVisible]);
@@ -265,7 +265,7 @@
 // Test that if the shelf is closed while an autoClose is pending, the pending
 // autoClose is cancelled.
 TEST_F(DownloadShelfControllerTest, CloseWithPendingAutoClose) {
-  scoped_nsobject<DownloadItemController> item(CreateItemController());
+  base::scoped_nsobject<DownloadItemController> item(CreateItemController());
   [shelf_ showDownloadShelf:YES
                isUserAction:NO];
   EXPECT_TRUE([shelf_ isVisible]);
@@ -306,7 +306,7 @@
 // That that the shelf cancels a pending autoClose if a new download item is
 // added to it.
 TEST_F(DownloadShelfControllerTest, AddItemWithPendingAutoClose) {
-  scoped_nsobject<DownloadItemController> item(CreateItemController());
+  base::scoped_nsobject<DownloadItemController> item(CreateItemController());
   [shelf_ showDownloadShelf:YES
                isUserAction:NO];
   EXPECT_TRUE([shelf_ isVisible]);
@@ -337,7 +337,7 @@
   EXPECT_EQ(0, shelf_.get()->cancelAutoCloseCount_);
 
   // Add a new download item. The pending autoClose should be cancelled.
-  scoped_nsobject<DownloadItemController> item2(CreateItemController());
+  base::scoped_nsobject<DownloadItemController> item2(CreateItemController());
   [shelf_ add:item.get()];
   EXPECT_EQ(1, shelf_.get()->scheduleAutoCloseCount_);
   EXPECT_EQ(1, shelf_.get()->cancelAutoCloseCount_);
@@ -346,7 +346,7 @@
 
 // Test that pending autoClose calls are cancelled when exiting.
 TEST_F(DownloadShelfControllerTest, CancelAutoCloseOnExit) {
-  scoped_nsobject<DownloadItemController> item(CreateItemController());
+  base::scoped_nsobject<DownloadItemController> item(CreateItemController());
   [shelf_ showDownloadShelf:YES
                isUserAction:NO];
   EXPECT_TRUE([shelf_ isVisible]);
diff --git a/chrome/browser/ui/cocoa/download/download_shelf_mac_unittest.mm b/chrome/browser/ui/cocoa/download/download_shelf_mac_unittest.mm
index 32354e2..c38dedf 100644
--- a/chrome/browser/ui/cocoa/download/download_shelf_mac_unittest.mm
+++ b/chrome/browser/ui/cocoa/download/download_shelf_mac_unittest.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #include "chrome/browser/ui/cocoa/cocoa_profile_test.h"
 #include "chrome/browser/ui/cocoa/download/download_shelf_mac.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -56,7 +56,7 @@
   }
 
  protected:
-  scoped_nsobject<FakeDownloadShelfController> shelf_controller_;
+  base::scoped_nsobject<FakeDownloadShelfController> shelf_controller_;
 };
 
 TEST_F(DownloadShelfMacTest, CreationDoesNotCallShow) {
diff --git a/chrome/browser/ui/cocoa/download/download_shelf_view.mm b/chrome/browser/ui/cocoa/download/download_shelf_view.mm
index d5a6743..a80420e 100644
--- a/chrome/browser/ui/cocoa/download/download_shelf_view.mm
+++ b/chrome/browser/ui/cocoa/download/download_shelf_view.mm
@@ -4,7 +4,6 @@
 
 #import "chrome/browser/ui/cocoa/download/download_shelf_view.h"
 
-#include "base/memory/scoped_nsobject.h"
 #include "chrome/browser/themes/theme_properties.h"
 #include "chrome/browser/themes/theme_service.h"
 #import "chrome/browser/ui/cocoa/nsview_additions.h"
diff --git a/chrome/browser/ui/cocoa/download/download_shelf_view_unittest.mm b/chrome/browser/ui/cocoa/download/download_shelf_view_unittest.mm
index b7263fc..cf22c69 100644
--- a/chrome/browser/ui/cocoa/download/download_shelf_view_unittest.mm
+++ b/chrome/browser/ui/cocoa/download/download_shelf_view_unittest.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #import "chrome/browser/ui/cocoa/download/download_shelf_view.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -16,7 +16,8 @@
 // This class only needs to do one thing: prevent mouse down events from moving
 // the parent window around.
 TEST_F(DownloadShelfViewTest, CanDragWindow) {
-  scoped_nsobject<DownloadShelfView> view([[DownloadShelfView alloc] init]);
+  base::scoped_nsobject<DownloadShelfView> view(
+      [[DownloadShelfView alloc] init]);
   EXPECT_FALSE([view mouseDownCanMoveWindow]);
 }
 
diff --git a/chrome/browser/ui/cocoa/draggable_button.h b/chrome/browser/ui/cocoa/draggable_button.h
index 5e126b2..0cd0d9b 100644
--- a/chrome/browser/ui/cocoa/draggable_button.h
+++ b/chrome/browser/ui/cocoa/draggable_button.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/draggable_button_mixin.h"
 
 // Class for buttons that can be drag sources. If the mouse is clicked and moved
@@ -15,7 +15,7 @@
 // |-performClick:|. Subclasses should override these two methods.
 @interface DraggableButton : NSButton<DraggableButtonMixin> {
  @private
-  scoped_nsobject<DraggableButtonImpl> draggableButtonImpl_;
+  base::scoped_nsobject<DraggableButtonImpl> draggableButtonImpl_;
 }
 
 @property(readonly, nonatomic) DraggableButtonImpl* draggableButton;
diff --git a/chrome/browser/ui/cocoa/draggable_button.mm b/chrome/browser/ui/cocoa/draggable_button.mm
index 1eb7d7d..0b3bcd8 100644
--- a/chrome/browser/ui/cocoa/draggable_button.mm
+++ b/chrome/browser/ui/cocoa/draggable_button.mm
@@ -39,7 +39,7 @@
   // The impl spins an event loop to distinguish clicks from drags,
   // which could result in our destruction.  Wire ourselves down for
   // the duration.
-  scoped_nsobject<DraggableButton> keepAlive([self retain]);
+  base::scoped_nsobject<DraggableButton> keepAlive([self retain]);
 
   if ([draggableButtonImpl_ mouseDownImpl:theEvent] ==
           kDraggableButtonMixinCallSuper) {
diff --git a/chrome/browser/ui/cocoa/draggable_button_mixin.mm b/chrome/browser/ui/cocoa/draggable_button_mixin.mm
index e28f674..986f5e9 100644
--- a/chrome/browser/ui/cocoa/draggable_button_mixin.mm
+++ b/chrome/browser/ui/cocoa/draggable_button_mixin.mm
@@ -7,9 +7,6 @@
 #include <cmath>
 
 #include "base/logging.h"
-#import "base/memory/scoped_nsobject.h"
-
-namespace {
 
 // Code taken from <http://codereview.chromium.org/180036/diff/3001/3004>.
 // TODO(viettrungluu): Do we want common, standard code for drag hysteresis?
@@ -17,8 +14,6 @@
 const CGFloat kWebDragStartHysteresisY = 5.0;
 const CGFloat kDragExpirationTimeout = 0.45;
 
-}
-
 // Private /////////////////////////////////////////////////////////////////////
 
 @interface DraggableButtonImpl (Private)
diff --git a/chrome/browser/ui/cocoa/draggable_button_unittest.mm b/chrome/browser/ui/cocoa/draggable_button_unittest.mm
index 6ee44a4..3cada7e 100644
--- a/chrome/browser/ui/cocoa/draggable_button_unittest.mm
+++ b/chrome/browser/ui/cocoa/draggable_button_unittest.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #import "chrome/browser/ui/cocoa/draggable_button.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -47,8 +47,9 @@
 
 // Make sure the basic case of "click" still works.
 TEST_F(DraggableButtonTest, DownUp) {
-  scoped_nsobject<TestableDraggableButton> button(
-      [[TestableDraggableButton alloc] initWithFrame:NSMakeRect(0,0,500,500)]);
+  base::scoped_nsobject<TestableDraggableButton> button(
+      [[TestableDraggableButton alloc]
+          initWithFrame:NSMakeRect(0, 0, 500, 500)]);
   [[test_window() contentView] addSubview:button.get()];
   [button setTarget:button];
   [button setAction:@selector(trigger:)];
@@ -67,8 +68,9 @@
 }
 
 TEST_F(DraggableButtonTest, DraggableHysteresis) {
-  scoped_nsobject<TestableDraggableButton> button(
-      [[TestableDraggableButton alloc] initWithFrame:NSMakeRect(0,0,500,500)]);
+  base::scoped_nsobject<TestableDraggableButton> button(
+      [[TestableDraggableButton alloc]
+          initWithFrame:NSMakeRect(0, 0, 500, 500)]);
   [[test_window() contentView] addSubview:button.get()];
   NSEvent* downEvent =
       cocoa_test_event_utils::MouseEventAtPoint(NSMakePoint(10,10),
@@ -106,8 +108,9 @@
 }
 
 TEST_F(DraggableButtonTest, ResetState) {
-  scoped_nsobject<TestableDraggableButton> button(
-      [[TestableDraggableButton alloc] initWithFrame:NSMakeRect(0,0,500,500)]);
+  base::scoped_nsobject<TestableDraggableButton> button(
+      [[TestableDraggableButton alloc]
+          initWithFrame:NSMakeRect(0, 0, 500, 500)]);
   [[test_window() contentView] addSubview:button.get()];
   NSEvent* downEvent =
       cocoa_test_event_utils::MouseEventAtPoint(NSMakePoint(10,10),
diff --git a/chrome/browser/ui/cocoa/extensions/browser_action_button.h b/chrome/browser/ui/cocoa/extensions/browser_action_button.h
index 7a083d3..fa5a46b 100644
--- a/chrome/browser/ui/cocoa/extensions/browser_action_button.h
+++ b/chrome/browser/ui/cocoa/extensions/browser_action_button.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #import "chrome/browser/ui/cocoa/image_button_cell.h"
 
@@ -31,7 +31,7 @@
   scoped_ptr<ExtensionActionIconFactoryBridge> iconFactoryBridge_;
 
   // Used to move the button and query whether a button is currently animating.
-  scoped_nsobject<NSViewAnimation> moveAnimation_;
+  base::scoped_nsobject<NSViewAnimation> moveAnimation_;
 
   // The extension for this button. Weak.
   const extensions::Extension* extension_;
diff --git a/chrome/browser/ui/cocoa/extensions/browser_actions_container_view.mm b/chrome/browser/ui/cocoa/extensions/browser_actions_container_view.mm
index c6b1fa6..2a0a0d3 100644
--- a/chrome/browser/ui/cocoa/extensions/browser_actions_container_view.mm
+++ b/chrome/browser/ui/cocoa/extensions/browser_actions_container_view.mm
@@ -7,7 +7,6 @@
 #include <algorithm>
 
 #include "base/basictypes.h"
-#import "base/memory/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/view_id_util.h"
 
 NSString* const kBrowserActionGrippyDragStartedNotification =
diff --git a/chrome/browser/ui/cocoa/extensions/browser_actions_container_view_unittest.mm b/chrome/browser/ui/cocoa/extensions/browser_actions_container_view_unittest.mm
index 14b5c1b..8e8d077 100644
--- a/chrome/browser/ui/cocoa/extensions/browser_actions_container_view_unittest.mm
+++ b/chrome/browser/ui/cocoa/extensions/browser_actions_container_view_unittest.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #import "chrome/browser/ui/cocoa/extensions/browser_actions_container_view.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -21,7 +21,7 @@
         initWithFrame:NSMakeRect(0, 0, 0, kContainerHeight)]);
   }
 
-  scoped_nsobject<BrowserActionsContainerView> view_;
+  base::scoped_nsobject<BrowserActionsContainerView> view_;
 };
 
 TEST_F(BrowserActionsContainerViewTest, BasicTests) {
diff --git a/chrome/browser/ui/cocoa/extensions/browser_actions_controller.h b/chrome/browser/ui/cocoa/extensions/browser_actions_controller.h
index f24a8d1..37cd3f0 100644
--- a/chrome/browser/ui/cocoa/extensions/browser_actions_controller.h
+++ b/chrome/browser/ui/cocoa/extensions/browser_actions_controller.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 
 class Browser;
@@ -52,19 +52,19 @@
   // A dictionary of Extension ID -> BrowserActionButton pairs representing the
   // buttons present in the container view. The ID is a string unique to each
   // extension.
-  scoped_nsobject<NSMutableDictionary> buttons_;
+  base::scoped_nsobject<NSMutableDictionary> buttons_;
 
   // Array of hidden buttons in the correct order in which the user specified.
-  scoped_nsobject<NSMutableArray> hiddenButtons_;
+  base::scoped_nsobject<NSMutableArray> hiddenButtons_;
 
   // The currently running chevron animation (fade in/out).
-  scoped_nsobject<NSViewAnimation> chevronAnimation_;
+  base::scoped_nsobject<NSViewAnimation> chevronAnimation_;
 
   // The chevron button used when Browser Actions are hidden.
-  scoped_nsobject<MenuButton> chevronMenuButton_;
+  base::scoped_nsobject<MenuButton> chevronMenuButton_;
 
   // The Browser Actions overflow menu.
-  scoped_nsobject<NSMenu> overflowMenu_;
+  base::scoped_nsobject<NSMenu> overflowMenu_;
 }
 
 @property(readonly, nonatomic) BrowserActionsContainerView* containerView;
diff --git a/chrome/browser/ui/cocoa/extensions/browser_actions_controller.mm b/chrome/browser/ui/cocoa/extensions/browser_actions_controller.mm
index 4f05f5a..e551c4b 100644
--- a/chrome/browser/ui/cocoa/extensions/browser_actions_controller.mm
+++ b/chrome/browser/ui/cocoa/extensions/browser_actions_controller.mm
@@ -487,10 +487,10 @@
   for (ExtensionList::const_iterator iter =
            toolbarModel_->toolbar_items().begin();
        iter != toolbarModel_->toolbar_items().end(); ++iter) {
-    if (![self shouldDisplayBrowserAction:*iter])
+    if (![self shouldDisplayBrowserAction:iter->get()])
       continue;
 
-    [self createActionButtonForExtension:*iter withIndex:i++];
+    [self createActionButtonForExtension:iter->get() withIndex:i++];
   }
 
   CGFloat width = [self savedWidth];
@@ -579,9 +579,9 @@
   for (ExtensionList::const_iterator iter =
            toolbarModel_->toolbar_items().begin();
        iter != toolbarModel_->toolbar_items().end(); ++iter) {
-    if (![self shouldDisplayBrowserAction:*iter])
+    if (![self shouldDisplayBrowserAction:iter->get()])
       continue;
-    BrowserActionButton* button = [self buttonForExtension:(*iter)];
+    BrowserActionButton* button = [self buttonForExtension:(iter->get())];
     if (!button)
       continue;
     if (![button isBeingDragged])
@@ -672,7 +672,7 @@
   for (ExtensionList::const_iterator iter =
            toolbarModel_->toolbar_items().begin();
        iter != toolbarModel_->toolbar_items().end(); ++iter) {
-    BrowserActionButton* button = [self buttonForExtension:(*iter)];
+    BrowserActionButton* button = [self buttonForExtension:(iter->get())];
     NSRect buttonFrame = [button frame];
     if (NSContainsRect([containerView_ bounds], buttonFrame))
       continue;
@@ -712,7 +712,7 @@
   for (ExtensionList::const_iterator iter =
            toolbarModel_->toolbar_items().begin();
        iter != toolbarModel_->toolbar_items().end(); ++iter) {
-    BrowserActionButton* button = [self buttonForExtension:(*iter)];
+    BrowserActionButton* button = [self buttonForExtension:(iter->get())];
     CGFloat intersectionWidth =
         NSWidth(NSIntersectionRect(draggedButtonFrame, [button frame]));
 
@@ -878,7 +878,7 @@
   const extensions::ExtensionList& toolbar_items =
       toolbarModel_->toolbar_items();
   if (index < toolbar_items.size()) {
-    const Extension* extension = toolbar_items[index];
+    const Extension* extension = toolbar_items[index].get();
     return [buttons_ objectForKey:base::SysUTF8ToNSString(extension->id())];
   }
   return nil;
diff --git a/chrome/browser/ui/cocoa/extensions/extension_action_context_menu.h b/chrome/browser/ui/cocoa/extensions/extension_action_context_menu.h
index b6b50f8..35d5ccf 100644
--- a/chrome/browser/ui/cocoa/extensions/extension_action_context_menu.h
+++ b/chrome/browser/ui/cocoa/extensions/extension_action_context_menu.h
@@ -7,7 +7,6 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 
 class AsyncUninstaller;
diff --git a/chrome/browser/ui/cocoa/extensions/extension_action_context_menu_browsertest.mm b/chrome/browser/ui/cocoa/extensions/extension_action_context_menu_browsertest.mm
index a92c9cc..7aee38c 100644
--- a/chrome/browser/ui/cocoa/extensions/extension_action_context_menu_browsertest.mm
+++ b/chrome/browser/ui/cocoa/extensions/extension_action_context_menu_browsertest.mm
@@ -64,7 +64,7 @@
 
 IN_PROC_BROWSER_TEST_F(ExtensionActionContextMenuTest, BasicTest) {
   SetupPageAction();
-  scoped_nsobject<ExtensionActionContextMenu> menu;
+  base::scoped_nsobject<ExtensionActionContextMenu> menu;
   menu.reset([[ExtensionActionContextMenu alloc] initWithExtension:extension_
                                                            browser:browser()
                                                    extensionAction:action_]);
@@ -103,7 +103,7 @@
        new Browser(Browser::CreateParams(browser()->profile(),
                                          browser()->host_desktop_type())));
 
-  scoped_nsobject<ExtensionActionContextMenu> menu;
+  base::scoped_nsobject<ExtensionActionContextMenu> menu;
   menu.reset([[ExtensionActionContextMenu alloc]
       initWithExtension:extension_
                 browser:empty_browser
@@ -158,7 +158,7 @@
 IN_PROC_BROWSER_TEST_F(
     ExtensionActionContextMenuTest, DISABLED_RunInspectPopup) {
   SetupPageAction();
-  scoped_nsobject<ExtensionActionContextMenu> menu;
+  base::scoped_nsobject<ExtensionActionContextMenu> menu;
   menu.reset([[ExtensionActionContextMenu alloc] initWithExtension:extension_
                                                            browser:browser()
                                                    extensionAction:action_]);
diff --git a/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.h b/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.h
index c9ada3a..18478ab 100644
--- a/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.h
+++ b/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/extensions/extension_install_prompt.h"
 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_mac.h"
 
@@ -46,7 +46,7 @@
 
  private:
   ExtensionInstallPrompt::Delegate* delegate_;
-  scoped_nsobject<ExtensionInstallViewController> view_controller_;
+  base::scoped_nsobject<ExtensionInstallViewController> view_controller_;
   scoped_ptr<ConstrainedWindowMac> constrained_window_;
 };
 
diff --git a/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.mm b/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.mm
index eb08510..066f3f4 100644
--- a/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.mm
+++ b/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.mm
@@ -42,13 +42,12 @@
                delegate:this
                  prompt:prompt]);
 
-  scoped_nsobject<NSWindow> window([[ConstrainedWindowCustomWindow alloc]
+  base::scoped_nsobject<NSWindow> window([[ConstrainedWindowCustomWindow alloc]
       initWithContentRect:[[view_controller_ view] bounds]]);
   [[window contentView] addSubview:[view_controller_ view]];
 
-  scoped_nsobject<CustomConstrainedWindowSheet> sheet(
-      [[CustomConstrainedWindowSheet alloc]
-          initWithCustomWindow:window]);
+  base::scoped_nsobject<CustomConstrainedWindowSheet> sheet(
+      [[CustomConstrainedWindowSheet alloc] initWithCustomWindow:window]);
   constrained_window_.reset(new ConstrainedWindowMac(
       this, show_params.parent_web_contents, sheet));
 }
diff --git a/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller_browsertest.mm b/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller_browsertest.mm
index 402dcfb..e3dbf83 100644
--- a/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller_browsertest.mm
+++ b/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller_browsertest.mm
@@ -30,14 +30,14 @@
 
   chrome::MockExtensionInstallPromptDelegate delegate;
   ExtensionInstallPrompt::Prompt prompt =
-      chrome::BuildExtensionInstallPrompt(extension_);
+      chrome::BuildExtensionInstallPrompt(extension_.get());
 
   ExtensionInstallDialogController* controller =
       new ExtensionInstallDialogController(show_params,
                                            &delegate,
                                            prompt);
 
-  scoped_nsobject<NSWindow> window(
+  base::scoped_nsobject<NSWindow> window(
       [[[controller->view_controller() view] window] retain]);
   EXPECT_TRUE([window isVisible]);
 
@@ -54,14 +54,14 @@
 
   chrome::MockExtensionInstallPromptDelegate delegate;
   ExtensionInstallPrompt::Prompt prompt =
-      chrome::BuildExtensionPostInstallPermissionsPrompt(extension_);
+      chrome::BuildExtensionPostInstallPermissionsPrompt(extension_.get());
 
   ExtensionInstallDialogController* controller =
       new ExtensionInstallDialogController(show_params,
                                            &delegate,
                                            prompt);
 
-  scoped_nsobject<NSWindow> window(
+  base::scoped_nsobject<NSWindow> window(
       [[[controller->view_controller() view] window] retain]);
   EXPECT_TRUE([window isVisible]);
 
diff --git a/chrome/browser/ui/cocoa/extensions/extension_install_view_controller.h b/chrome/browser/ui/cocoa/extensions/extension_install_view_controller.h
index ba3f192..3ba7292 100644
--- a/chrome/browser/ui/cocoa/extensions/extension_install_view_controller.h
+++ b/chrome/browser/ui/cocoa/extensions/extension_install_view_controller.h
@@ -9,7 +9,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/string16.h"
 #include "chrome/browser/extensions/extension_install_prompt.h"
@@ -45,7 +45,7 @@
   ExtensionInstallPrompt::Delegate* delegate_;  // weak
   scoped_ptr<ExtensionInstallPrompt::Prompt> prompt_;
 
-  scoped_nsobject<NSArray> warnings_;
+  base::scoped_nsobject<NSArray> warnings_;
   BOOL isComputingRowHeight_;
 }
 
diff --git a/chrome/browser/ui/cocoa/extensions/extension_install_view_controller.mm b/chrome/browser/ui/cocoa/extensions/extension_install_view_controller.mm
index 088f5ff..5e5af3c 100644
--- a/chrome/browser/ui/cocoa/extensions/extension_install_view_controller.mm
+++ b/chrome/browser/ui/cocoa/extensions/extension_install_view_controller.mm
@@ -149,7 +149,7 @@
     nibName = @"ExtensionInstallPromptBundle";
   } else if (prompt.type() == ExtensionInstallPrompt::INLINE_INSTALL_PROMPT) {
     nibName = @"ExtensionInstallPromptInline";
-  } else if (prompt.GetPermissionCount() == 0 &&
+  } else if (!prompt.ShouldShowPermissions() &&
              prompt.GetOAuthIssueCount() == 0 &&
              prompt.GetRetainedFileCount() == 0) {
     nibName = @"ExtensionInstallPromptNoWarnings";
@@ -270,7 +270,7 @@
 
   // If there are any warnings or OAuth issues, then we have to do some special
   // layout.
-  if (prompt_->GetPermissionCount() > 0 || prompt_->GetOAuthIssueCount() > 0 ||
+  if (prompt_->ShouldShowPermissions() || prompt_->GetOAuthIssueCount() > 0 ||
       prompt_->GetRetainedFileCount() > 0) {
     NSSize spacing = [outlineView_ intercellSpacing];
     spacing.width += 2;
@@ -314,7 +314,8 @@
   NSImage* image = gfx::NSImageFromImageSkiaWithColorSpace(
       *skiaImage, base::mac::GetSystemColorSpace());
   NSRect frame = NSMakeRect(0, 0, skiaImage->width(), skiaImage->height());
-  scoped_nsobject<NSImageView> view([[NSImageView alloc] initWithFrame:frame]);
+  base::scoped_nsobject<NSImageView> view(
+      [[NSImageView alloc] initWithFrame:frame]);
   [view setImage:image];
 
   // Add this star after all the other ones
@@ -489,17 +490,29 @@
 
 - (NSArray*)buildWarnings:(const ExtensionInstallPrompt::Prompt&)prompt {
   NSMutableArray* warnings = [NSMutableArray array];
+  NSString* heading = nil;
 
-  if (prompt.GetPermissionCount() > 0) {
+  if (prompt.ShouldShowPermissions()) {
     NSMutableArray* children = [NSMutableArray array];
-    for (size_t i = 0; i < prompt.GetPermissionCount(); ++i) {
+    if (prompt.GetPermissionCount() > 0) {
+      for (size_t i = 0; i < prompt.GetPermissionCount(); ++i) {
+        [children addObject:
+            [self buildItemWithTitle:SysUTF16ToNSString(prompt.GetPermission(i))
+                         isGroupItem:NO
+                            children:nil]];
+      }
+
+      heading = SysUTF16ToNSString(prompt.GetPermissionsHeading());
+    } else {
       [children addObject:
-          [self buildItemWithTitle:SysUTF16ToNSString(prompt.GetPermission(i))
+          [self buildItemWithTitle:
+              l10n_util::GetNSString(IDS_EXTENSION_NO_SPECIAL_PERMISSIONS)
                        isGroupItem:NO
                           children:nil]];
+      heading = @"";
     }
     [warnings addObject:[self
-        buildItemWithTitle:SysUTF16ToNSString(prompt.GetPermissionsHeading())
+        buildItemWithTitle:heading
                isGroupItem:YES
                   children:children]];
   }
diff --git a/chrome/browser/ui/cocoa/extensions/extension_install_view_controller_unittest.mm b/chrome/browser/ui/cocoa/extensions/extension_install_view_controller_unittest.mm
index ed72350..51e4bee 100644
--- a/chrome/browser/ui/cocoa/extensions/extension_install_view_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/extensions/extension_install_view_controller_unittest.mm
@@ -4,7 +4,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #import "chrome/browser/extensions/extension_install_prompt.h"
@@ -40,11 +40,10 @@
   permissions.push_back(UTF8ToUTF16("warning 1"));
   prompt.SetPermissions(permissions);
 
-  scoped_nsobject<ExtensionInstallViewController>
-    controller([[ExtensionInstallViewController alloc]
-                 initWithNavigator:browser()
-                          delegate:&delegate
-                            prompt:prompt]);
+  base::scoped_nsobject<ExtensionInstallViewController> controller(
+      [[ExtensionInstallViewController alloc] initWithNavigator:browser()
+                                                       delegate:&delegate
+                                                         prompt:prompt]);
 
   [controller view];  // Force nib load.
 
@@ -93,11 +92,10 @@
   permissions.push_back(UTF8ToUTF16("warning 1"));
   prompt.SetPermissions(permissions);
 
-  scoped_nsobject<ExtensionInstallViewController>
-  controller([[ExtensionInstallViewController alloc]
-               initWithNavigator:browser()
-                        delegate:&delegate
-                          prompt:prompt]);
+  base::scoped_nsobject<ExtensionInstallViewController> controller(
+      [[ExtensionInstallViewController alloc] initWithNavigator:browser()
+                                                       delegate:&delegate
+                                                         prompt:prompt]);
 
   [controller view];  // Force nib load.
   [controller ok:nil];
@@ -123,19 +121,19 @@
   permissions.push_back(UTF8ToUTF16("warning 2"));
   two_warnings_prompt.SetPermissions(permissions);
 
-  scoped_nsobject<ExtensionInstallViewController>
-  controller1([[ExtensionInstallViewController alloc]
-                initWithNavigator:browser()
-                         delegate:&delegate1
-                           prompt:one_warning_prompt]);
+  base::scoped_nsobject<ExtensionInstallViewController> controller1(
+      [[ExtensionInstallViewController alloc]
+          initWithNavigator:browser()
+                   delegate:&delegate1
+                     prompt:one_warning_prompt]);
 
   [controller1 view];  // Force nib load.
 
-  scoped_nsobject<ExtensionInstallViewController>
-  controller2([[ExtensionInstallViewController alloc]
-                initWithNavigator:browser()
-                         delegate:&delegate2
-                           prompt:two_warnings_prompt]);
+  base::scoped_nsobject<ExtensionInstallViewController> controller2(
+      [[ExtensionInstallViewController alloc]
+          initWithNavigator:browser()
+                   delegate:&delegate2
+                     prompt:two_warnings_prompt]);
 
   [controller2 view];  // Force nib load.
 
@@ -158,11 +156,11 @@
   ExtensionInstallPrompt::Prompt no_warnings_prompt =
       chrome::BuildExtensionInstallPrompt(extension_.get());
 
-  scoped_nsobject<ExtensionInstallViewController>
-  controller([[ExtensionInstallViewController alloc]
-               initWithNavigator:browser()
-                        delegate:&delegate
-                          prompt:no_warnings_prompt]);
+  base::scoped_nsobject<ExtensionInstallViewController> controller(
+      [[ExtensionInstallViewController alloc]
+          initWithNavigator:browser()
+                   delegate:&delegate
+                     prompt:no_warnings_prompt]);
 
   [controller view];  // Force nib load.
 
@@ -202,11 +200,10 @@
   inline_prompt.set_extension(extension_.get());
   inline_prompt.set_icon(chrome::LoadInstallPromptIcon());
 
-  scoped_nsobject<ExtensionInstallViewController>
-  controller([[ExtensionInstallViewController alloc]
-               initWithNavigator:browser()
-                        delegate:&delegate
-                          prompt:inline_prompt]);
+  base::scoped_nsobject<ExtensionInstallViewController> controller(
+      [[ExtensionInstallViewController alloc] initWithNavigator:browser()
+                                                       delegate:&delegate
+                                                         prompt:inline_prompt]);
 
   [controller view];  // Force nib load.
 
@@ -254,7 +251,7 @@
   chrome::MockExtensionInstallPromptDelegate delegate;
 
   ExtensionInstallPrompt::Prompt prompt =
-      chrome::BuildExtensionInstallPrompt(extension_);
+      chrome::BuildExtensionInstallPrompt(extension_.get());
   std::vector<string16> permissions;
   permissions.push_back(UTF8ToUTF16("warning 1"));
   prompt.SetPermissions(permissions);
@@ -265,11 +262,10 @@
   issues.push_back(issue);
   prompt.SetOAuthIssueAdvice(issues);
 
-  scoped_nsobject<ExtensionInstallViewController>
-  controller([[ExtensionInstallViewController alloc]
-               initWithNavigator:browser()
-                        delegate:&delegate
-                          prompt:prompt]);
+  base::scoped_nsobject<ExtensionInstallViewController> controller(
+      [[ExtensionInstallViewController alloc] initWithNavigator:browser()
+                                                       delegate:&delegate
+                                                         prompt:prompt]);
 
   [controller view];  // Force nib load.
   NSOutlineView* outlineView = [controller outlineView];
@@ -290,11 +286,10 @@
   permissions.push_back(UTF8ToUTF16("warning 1"));
   prompt.SetPermissions(permissions);
 
-  scoped_nsobject<ExtensionInstallViewController>
-  controller([[ExtensionInstallViewController alloc]
-               initWithNavigator:browser()
-                        delegate:&delegate
-                          prompt:prompt]);
+  base::scoped_nsobject<ExtensionInstallViewController> controller(
+      [[ExtensionInstallViewController alloc] initWithNavigator:browser()
+                                                       delegate:&delegate
+                                                         prompt:prompt]);
 
   [controller view];  // Force nib load.
 
diff --git a/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.h b/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.h
index 803a77d..aec6898 100644
--- a/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.h
+++ b/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.h
@@ -60,7 +60,7 @@
   const extensions::Extension* extension_;  // weak
   const extensions::BundleInstaller* bundle_;  // weak
   Browser* browser_;  // weak
-  scoped_nsobject<NSImage> icon_;
+  base::scoped_nsobject<NSImage> icon_;
 
   extension_installed_bubble::ExtensionType type_;
 
@@ -91,7 +91,7 @@
   // text views cannot conveniently be created in IB. The xib file contains
   // a text field |promoPlaceholder_| that's replaced by this text view |promo_|
   // in -awakeFromNib.
-  scoped_nsobject<HyperlinkTextView> promo_;
+  base::scoped_nsobject<HyperlinkTextView> promo_;
   // Only shown for bundle installs.
   IBOutlet NSTextField* installedHeadingMsg_;
   IBOutlet NSTextField* installedItemsMsg_;
diff --git a/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.mm b/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.mm
index 883ea76..4536b8d 100644
--- a/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.mm
+++ b/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.mm
@@ -29,7 +29,7 @@
 #include "chrome/browser/ui/cocoa/tabs/tab_strip_view.h"
 #include "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h"
 #include "chrome/browser/ui/singleton_tabs.h"
-#include "chrome/browser/ui/webui/sync_promo/sync_promo_ui.h"
+#include "chrome/browser/ui/sync/sync_promo_ui.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "chrome/common/extensions/api/commands/commands_handler.h"
 #include "chrome/common/extensions/api/extension_action/action_info.h"
diff --git a/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller_unittest.mm b/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller_unittest.mm
index 4781dd6..4016bbd 100644
--- a/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller_unittest.mm
@@ -111,7 +111,7 @@
     scoped_refptr<Extension> extension =
         Extension::Create(path, extensions::Manifest::INVALID_LOCATION,
                           extension_input_value, Extension::NO_FLAGS, &error);
-    extension_service_->AddExtension(extension);
+    extension_service_->AddExtension(extension.get());
     return extension;
   }
 
diff --git a/chrome/browser/ui/cocoa/extensions/extension_popup_controller.h b/chrome/browser/ui/cocoa/extensions/extension_popup_controller.h
index 782505d..7bd1f23 100644
--- a/chrome/browser/ui/cocoa/extensions/extension_popup_controller.h
+++ b/chrome/browser/ui/cocoa/extensions/extension_popup_controller.h
@@ -7,7 +7,6 @@
 
 #import <Cocoa/Cocoa.h>
 
-#import "base/memory/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #import "chrome/browser/ui/cocoa/base_bubble_controller.h"
 #import "chrome/browser/ui/cocoa/info_bubble_view.h"
diff --git a/chrome/browser/ui/cocoa/extensions/extension_popup_controller.mm b/chrome/browser/ui/cocoa/extensions/extension_popup_controller.mm
index b2af054..d5dc47a 100644
--- a/chrome/browser/ui/cocoa/extensions/extension_popup_controller.mm
+++ b/chrome/browser/ui/cocoa/extensions/extension_popup_controller.mm
@@ -149,12 +149,11 @@
         anchoredAt:(NSPoint)anchoredAt
      arrowLocation:(info_bubble::BubbleArrowLocation)arrowLocation
            devMode:(BOOL)devMode {
-  scoped_nsobject<InfoBubbleWindow> window(
-      [[InfoBubbleWindow alloc]
-          initWithContentRect:ui::kWindowSizeDeterminedLater
-                    styleMask:NSBorderlessWindowMask
-                      backing:NSBackingStoreBuffered
-                        defer:YES]);
+  base::scoped_nsobject<InfoBubbleWindow> window([[InfoBubbleWindow alloc]
+      initWithContentRect:ui::kWindowSizeDeterminedLater
+                styleMask:NSBorderlessWindowMask
+                  backing:NSBackingStoreBuffered
+                    defer:YES]);
   if (!window.get())
     return nil;
 
diff --git a/chrome/browser/ui/cocoa/extensions/media_galleries_dialog_cocoa.h b/chrome/browser/ui/cocoa/extensions/media_galleries_dialog_cocoa.h
index 74e39cb..54559af 100644
--- a/chrome/browser/ui/cocoa/extensions/media_galleries_dialog_cocoa.h
+++ b/chrome/browser/ui/cocoa/extensions/media_galleries_dialog_cocoa.h
@@ -74,22 +74,22 @@
   scoped_ptr<ConstrainedWindowMac> window_;
 
   // The alert that the dialog is being displayed as.
-  scoped_nsobject<ConstrainedWindowAlert> alert_;
+  base::scoped_nsobject<ConstrainedWindowAlert> alert_;
 
   // True if the user has pressed accept.
   bool accepted_;
 
   // List of checkboxes ordered from bottom to top.
-  scoped_nsobject<NSMutableArray> checkboxes_;
+  base::scoped_nsobject<NSMutableArray> checkboxes_;
 
   // Container view for checkboxes.
-  scoped_nsobject<NSView> checkbox_container_;
+  base::scoped_nsobject<NSView> checkbox_container_;
 
   // Container view for the main dialog contents.
-  scoped_nsobject<NSBox> accessory_;
+  base::scoped_nsobject<NSBox> accessory_;
 
   // An Objective-C class to route callbacks from Cocoa code.
-  scoped_nsobject<MediaGalleriesCocoaController> cocoa_controller_;
+  base::scoped_nsobject<MediaGalleriesCocoaController> cocoa_controller_;
 
   DISALLOW_COPY_AND_ASSIGN(MediaGalleriesDialogCocoa);
 };
diff --git a/chrome/browser/ui/cocoa/extensions/media_galleries_dialog_cocoa.mm b/chrome/browser/ui/cocoa/extensions/media_galleries_dialog_cocoa.mm
index e9776ee..5e9940c 100644
--- a/chrome/browser/ui/cocoa/extensions/media_galleries_dialog_cocoa.mm
+++ b/chrome/browser/ui/cocoa/extensions/media_galleries_dialog_cocoa.mm
@@ -98,7 +98,7 @@
 
   // May be NULL during tests.
   if (controller->web_contents()) {
-    scoped_nsobject<CustomConstrainedWindowSheet> sheet(
+    base::scoped_nsobject<CustomConstrainedWindowSheet> sheet(
         [[CustomConstrainedWindowSheet alloc]
             initWithCustomWindow:[alert_ window]]);
     window_.reset(new ConstrainedWindowMac(
@@ -121,9 +121,8 @@
                                                         blue:0.625
                                                        alpha:1.0]];
 
-  scoped_nsobject<NSScrollView> scroll_view(
-      [[NSScrollView alloc] initWithFrame:NSMakeRect(
-          0, 0, kCheckboxMaxWidth, kScrollAreaHeight)]);
+  base::scoped_nsobject<NSScrollView> scroll_view([[NSScrollView alloc]
+      initWithFrame:NSMakeRect(0, 0, kCheckboxMaxWidth, kScrollAreaHeight)]);
   [scroll_view setHasVerticalScroller:YES];
   [scroll_view setHasHorizontalScroller:NO];
   [scroll_view setBorderType:NSNoBorder];
@@ -203,7 +202,8 @@
 }
 
 CGFloat MediaGalleriesDialogCocoa::CreateCheckboxSeparator(CGFloat y_pos) {
-  scoped_nsobject<NSBox> separator([[NSBox alloc] initWithFrame:NSMakeRect(
+  base::scoped_nsobject<NSBox> separator(
+      [[NSBox alloc] initWithFrame:NSMakeRect(
           0, y_pos + kCheckboxMargin * 0.5, kCheckboxMaxWidth, 1.0)]);
   [separator setBoxType:NSBoxSeparator];
   [separator setBorderType:NSLineBorder];
@@ -211,7 +211,7 @@
   [checkbox_container_ addSubview:separator];
   y_pos += kCheckboxMargin * 0.5 + 4;
 
-  scoped_nsobject<NSTextField> unattached_label(
+  base::scoped_nsobject<NSTextField> unattached_label(
       [[NSTextField alloc] initWithFrame:NSZeroRect]);
   [unattached_label setEditable:NO];
   [unattached_label setSelectable:NO];
@@ -288,7 +288,7 @@
     const MediaGalleryPrefInfo& gallery,
     bool permitted,
     CGFloat y_pos) {
-  scoped_nsobject<NSButton> checkbox(
+  base::scoped_nsobject<NSButton> checkbox(
       [[NSButton alloc] initWithFrame:NSZeroRect]);
   NSString* unique_id = GetUniqueIDForGallery(gallery);
   [[checkbox cell] setRepresentedObject:unique_id];
@@ -299,10 +299,8 @@
   [checkboxes_ addObject:checkbox];
 
   [checkbox setTitle:base::SysUTF16ToNSString(
-      MediaGalleriesDialogController::GetGalleryDisplayNameNoAttachment(
-          gallery))];
-  [checkbox setToolTip:base::SysUTF16ToNSString(
-      MediaGalleriesDialogController::GetGalleryTooltip(gallery))];
+      gallery.GetGalleryDisplayName())];
+  [checkbox setToolTip:base::SysUTF16ToNSString(gallery.GetGalleryTooltip())];
   [checkbox setState:permitted ? NSOnState : NSOffState];
 
   [checkbox sizeToFit];
@@ -313,16 +311,14 @@
   [checkbox setFrame:rect];
   [checkbox_container_ addSubview:checkbox];
 
-  scoped_nsobject<NSTextField> details(
-    [[NSTextField alloc] initWithFrame:NSZeroRect]);
+  base::scoped_nsobject<NSTextField> details(
+      [[NSTextField alloc] initWithFrame:NSZeroRect]);
   [details setEditable:NO];
   [details setSelectable:NO];
   [details setBezeled:NO];
   [details setAttributedStringValue:
       constrained_window::GetAttributedLabelString(
-          base::SysUTF16ToNSString(
-              MediaGalleriesDialogController::GetGalleryAdditionalDetails(
-                  gallery)),
+          base::SysUTF16ToNSString(gallery.GetGalleryAdditionalDetails()),
           chrome_style::kTextFontStyle,
           NSNaturalTextAlignment,
           NSLineBreakByClipping
@@ -359,7 +355,7 @@
 // static
 MediaGalleriesDialog* MediaGalleriesDialog::Create(
     MediaGalleriesDialogController* controller) {
-  scoped_nsobject<MediaGalleriesCocoaController> cocoa_controller(
+  base::scoped_nsobject<MediaGalleriesCocoaController> cocoa_controller(
       [[MediaGalleriesCocoaController alloc] init]);
   return new MediaGalleriesDialogCocoa(controller, cocoa_controller);
 }
diff --git a/chrome/browser/ui/cocoa/extensions/media_galleries_dialog_cocoa_browsertest.mm b/chrome/browser/ui/cocoa/extensions/media_galleries_dialog_cocoa_browsertest.mm
index 19b09ab..81dca35 100644
--- a/chrome/browser/ui/cocoa/extensions/media_galleries_dialog_cocoa_browsertest.mm
+++ b/chrome/browser/ui/cocoa/extensions/media_galleries_dialog_cocoa_browsertest.mm
@@ -44,7 +44,7 @@
   scoped_ptr<MediaGalleriesDialogCocoa> dialog(
       static_cast<MediaGalleriesDialogCocoa*>(
           MediaGalleriesDialog::Create(&controller)));
-  scoped_nsobject<NSWindow> window([[dialog->alert_ window] retain]);
+  base::scoped_nsobject<NSWindow> window([[dialog->alert_ window] retain]);
   EXPECT_TRUE([window isVisible]);
 
   WebContentsModalDialogManager* web_contents_modal_dialog_manager =
diff --git a/chrome/browser/ui/cocoa/extensions/native_app_window_cocoa.h b/chrome/browser/ui/cocoa/extensions/native_app_window_cocoa.h
index f92d833..795dd6b 100644
--- a/chrome/browser/ui/cocoa/extensions/native_app_window_cocoa.h
+++ b/chrome/browser/ui/cocoa/extensions/native_app_window_cocoa.h
@@ -8,11 +8,11 @@
 #import <Cocoa/Cocoa.h>
 #include <vector>
 
-#include "base/memory/scoped_nsobject.h"
+#include "apps/shell_window.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #import "chrome/browser/ui/cocoa/browser_command_executor.h"
 #include "chrome/browser/ui/extensions/native_app_window.h"
-#include "chrome/browser/ui/extensions/shell_window.h"
 #include "content/public/browser/notification_registrar.h"
 #include "extensions/common/draggable_region.h"
 #include "ui/gfx/rect.h"
@@ -43,8 +43,8 @@
 // Cocoa bridge to AppWindow.
 class NativeAppWindowCocoa : public NativeAppWindow {
  public:
-  NativeAppWindowCocoa(ShellWindow* shell_window,
-                       const ShellWindow::CreateParams& params);
+  NativeAppWindowCocoa(apps::ShellWindow* shell_window,
+                       const apps::ShellWindow::CreateParams& params);
 
   // ui::BaseWindow implementation.
   virtual bool IsActive() const OVERRIDE;
@@ -147,7 +147,7 @@
   void UpdateDraggableRegionsForCustomDrag(
       const std::vector<extensions::DraggableRegion>& regions);
 
-  ShellWindow* shell_window_; // weak - ShellWindow owns NativeAppWindow.
+  apps::ShellWindow* shell_window_; // weak - ShellWindow owns NativeAppWindow.
 
   bool has_frame_;
 
@@ -159,7 +159,7 @@
   gfx::Size max_size_;
   bool resizable_;
 
-  scoped_nsobject<NativeAppWindowController> window_controller_;
+  base::scoped_nsobject<NativeAppWindowController> window_controller_;
   NSInteger attention_request_id_;  // identifier from requestUserAttention
 
   // Indicates whether system drag or custom drag should be used, depending on
diff --git a/chrome/browser/ui/cocoa/extensions/native_app_window_cocoa.mm b/chrome/browser/ui/cocoa/extensions/native_app_window_cocoa.mm
index 460ac10..d6ee237 100644
--- a/chrome/browser/ui/cocoa/extensions/native_app_window_cocoa.mm
+++ b/chrome/browser/ui/cocoa/extensions/native_app_window_cocoa.mm
@@ -20,6 +20,8 @@
 #include "content/public/browser/web_contents_view.h"
 #include "third_party/skia/include/core/SkRegion.h"
 
+using apps::ShellWindow;
+
 @interface NSWindow (NSPrivateApis)
 - (void)setBottomCornerRounded:(BOOL)rounded;
 @end
@@ -226,7 +228,7 @@
                           NSTexturedBackgroundWindowMask;
   if (resizable_)
     style_mask |= NSResizableWindowMask;
-  scoped_nsobject<NSWindow> window;
+  base::scoped_nsobject<NSWindow> window;
   if (has_frame_) {
     window.reset([[ShellNSWindow alloc]
         initWithContentRect:cocoa_bounds
@@ -656,7 +658,7 @@
   // Note that [webView subviews] returns the view's mutable internal array and
   // it should be copied to avoid mutating the original array while enumerating
   // it.
-  scoped_nsobject<NSArray> subviews([[webView subviews] copy]);
+  base::scoped_nsobject<NSArray> subviews([[webView subviews] copy]);
   for (NSView* subview in subviews.get())
     if ([subview isKindOfClass:[ControlRegionView class]])
       [subview removeFromSuperview];
@@ -667,7 +669,7 @@
            system_drag_exclude_areas_.begin();
        iter != system_drag_exclude_areas_.end();
        ++iter) {
-    scoped_nsobject<NSView> controlRegion(
+    base::scoped_nsobject<NSView> controlRegion(
         [[ControlRegionView alloc] initWithAppWindow:this]);
     [controlRegion setFrame:NSMakeRect(iter->x(),
                                        webViewHeight - iter->bottom(),
diff --git a/chrome/browser/ui/cocoa/external_protocol_dialog.h b/chrome/browser/ui/cocoa/external_protocol_dialog.h
index 224c280..e677c3e 100644
--- a/chrome/browser/ui/cocoa/external_protocol_dialog.h
+++ b/chrome/browser/ui/cocoa/external_protocol_dialog.h
@@ -4,7 +4,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/time.h"
+#include "base/time/time.h"
 #include "googleurl/src/gurl.h"
 
 @interface ExternalProtocolDialogController : NSObject {
diff --git a/chrome/browser/ui/cocoa/fast_resize_view.h b/chrome/browser/ui/cocoa/fast_resize_view.h
index cdc9c7f..fb68d95 100644
--- a/chrome/browser/ui/cocoa/fast_resize_view.h
+++ b/chrome/browser/ui/cocoa/fast_resize_view.h
@@ -16,19 +16,14 @@
 @interface FastResizeView : NSView {
  @private
   BOOL fastResizeMode_;
-
-  // Offset from the top of the view where the view's content starts. This is
-  // used to prevent this view from drawing white on non-content area.
-  CGFloat contentOffset_;
 }
 
-@property(assign, nonatomic) CGFloat contentOffset;
-
 // Turns fast resizing mode on or off, which determines how this view resizes
 // its subviews.  Turning fast resizing mode off has the effect of immediately
 // resizing subviews to fit; callers do not need to explictly call |setFrame:|
 // to trigger a resize.
 - (void)setFastResizeMode:(BOOL)fastResizeMode;
+
 @end
 
 #endif  // CHROME_BROWSER_UI_COCOA_FAST_RESIZE_VIEW_H_
diff --git a/chrome/browser/ui/cocoa/fast_resize_view.mm b/chrome/browser/ui/cocoa/fast_resize_view.mm
index e87a343..87f7787 100644
--- a/chrome/browser/ui/cocoa/fast_resize_view.mm
+++ b/chrome/browser/ui/cocoa/fast_resize_view.mm
@@ -16,14 +16,17 @@
 
 @implementation FastResizeView
 
-@synthesize contentOffset = contentOffset_;
-
 - (void)setFastResizeMode:(BOOL)fastResizeMode {
+  if (fastResizeMode_ == fastResizeMode)
+    return;
+
   fastResizeMode_ = fastResizeMode;
 
   // Force a relayout when coming out of fast resize mode.
   if (!fastResizeMode_)
     [self layoutSubviews];
+
+  [self setNeedsDisplay:YES];
 }
 
 - (void)resizeSubviewsWithOldSize:(NSSize)oldSize {
@@ -37,27 +40,14 @@
   if (!fastResizeMode_)
     return;
 
-  // Don't draw on the non-content area.
-  NSRect clipRect = [self bounds];
-  clipRect.size.height -= contentOffset_;
-  NSRectClip(clipRect);
-
   [[NSColor whiteColor] set];
   NSRectFill(dirtyRect);
 }
 
-- (NSView*)hitTest:(NSPoint)point {
-  NSView* result = [super hitTest:point];
-  // Never return this view during hit testing. This allows overlapping views to
-  // get events even when they are not topmost.
-  if ([result isEqual:self])
-    return nil;
-  return result;
-}
-
 @end
 
 @implementation FastResizeView (PrivateMethods)
+
 - (void)layoutSubviews {
   // There should never be more than one subview.  There can be zero, if we are
   // in the process of switching tabs or closing the window.  In those cases, no
@@ -79,4 +69,5 @@
     [subview setFrame:bounds];
   }
 }
+
 @end
diff --git a/chrome/browser/ui/cocoa/fast_resize_view_unittest.mm b/chrome/browser/ui/cocoa/fast_resize_view_unittest.mm
index 02ac295..edfea60 100644
--- a/chrome/browser/ui/cocoa/fast_resize_view_unittest.mm
+++ b/chrome/browser/ui/cocoa/fast_resize_view_unittest.mm
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/memory/scoped_nsobject.h"
-#import "chrome/browser/ui/cocoa/fast_resize_view.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#import "chrome/browser/ui/cocoa/fast_resize_view.h"
 
 namespace {
 
@@ -12,12 +12,13 @@
  public:
   FastResizeViewTest() {
     NSRect frame = NSMakeRect(0, 0, 100, 30);
-    scoped_nsobject<FastResizeView> view(
+    base::scoped_nsobject<FastResizeView> view(
         [[FastResizeView alloc] initWithFrame:frame]);
     view_ = view.get();
     [[test_window() contentView] addSubview:view_];
 
-    scoped_nsobject<NSView> childView([[NSView alloc] initWithFrame:frame]);
+    base::scoped_nsobject<NSView> childView(
+        [[NSView alloc] initWithFrame:frame]);
     childView_ = childView.get();
     [view_ addSubview:childView_];
   }
diff --git a/chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller.h b/chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller.h
index e5c482b..4c5a018 100644
--- a/chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller.h
+++ b/chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller.h
@@ -4,7 +4,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/strings/string16.h"
 #include "ui/gfx/point.h"
 
@@ -33,19 +33,19 @@
 
   Browser* browser_;
 
-  scoped_nsobject<FocusTracker> focusTracker_;
+  base::scoped_nsobject<FocusTracker> focusTracker_;
 
   // The show/hide animation. This is defined to be non-nil if the
   // animation is running, and is always nil otherwise.  The
   // FindBarCocoaController should not be deallocated while an animation is
   // running (stopAnimation is currently called before the last tab in a
   // window is removed).
-  scoped_nsobject<NSViewAnimation> showHideAnimation_;
+  base::scoped_nsobject<NSViewAnimation> showHideAnimation_;
 
   // The horizontal-moving animation, to avoid occluding find results. This
   // is nil when the animation is not running, and is also stopped by
   // stopAnimation.
-  scoped_nsobject<NSViewAnimation> moveAnimation_;
+  base::scoped_nsobject<NSViewAnimation> moveAnimation_;
 
   // If YES, do nothing as a result of find pasteboard update notifications.
   BOOL suppressPboardUpdateActions_;
diff --git a/chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller.mm b/chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller.mm
index cc3e356..6fcb98f 100644
--- a/chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller.mm
+++ b/chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller.mm
@@ -123,6 +123,11 @@
     findBarBridge_->GetFindBarController()->EndFindSession(
         FindBarController::kKeepSelectionOnPage,
         FindBarController::kKeepResultsInFindBox);
+
+  // Turn off hover state on close button else the button will remain
+  // hovered when we bring the find bar back up.
+  // crbug.com/227424
+  [[closeButton_ cell] setIsMouseInside:NO];
 }
 
 - (IBAction)previousResult:(id)sender {
diff --git a/chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller_unittest.mm b/chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller_unittest.mm
index 20aae91..9cd4db5 100644
--- a/chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller_unittest.mm
@@ -53,7 +53,7 @@
   }
 
  protected:
-  scoped_nsobject<FindBarCocoaController> controller_;
+  base::scoped_nsobject<FindBarCocoaController> controller_;
 };
 
 TEST_VIEW(FindBarCocoaControllerTest, [controller_ view])
@@ -110,7 +110,7 @@
 }
 
 TEST_F(FindBarCocoaControllerTest, FindTextIsGlobal) {
-  scoped_nsobject<FindBarCocoaController> otherController(
+  base::scoped_nsobject<FindBarCocoaController> otherController(
       [[FindBarCocoaController alloc] initWithBrowser:nil]);
   [[test_window() contentView] addSubview:[otherController view]];
 
diff --git a/chrome/browser/ui/cocoa/find_bar/find_bar_text_field_cell.h b/chrome/browser/ui/cocoa/find_bar/find_bar_text_field_cell.h
index ec61dc5..130009f 100644
--- a/chrome/browser/ui/cocoa/find_bar/find_bar_text_field_cell.h
+++ b/chrome/browser/ui/cocoa/find_bar/find_bar_text_field_cell.h
@@ -6,14 +6,14 @@
 
 #import "chrome/browser/ui/cocoa/styled_text_field_cell.h"
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 
 // FindBarTextFieldCell extends StyledTextFieldCell to provide support for a
 // results label rooted at the right edge of the cell.
 @interface FindBarTextFieldCell : StyledTextFieldCell {
  @private
   // Set if there is a results label to display on the right side of the cell.
-  scoped_nsobject<NSAttributedString> resultsString_;
+  base::scoped_nsobject<NSAttributedString> resultsString_;
 }
 
 // Sets the results label to the localized equivalent of "X of Y".
diff --git a/chrome/browser/ui/cocoa/find_bar/find_bar_text_field_cell.mm b/chrome/browser/ui/cocoa/find_bar/find_bar_text_field_cell.mm
index 3d2095c..82b0bf0 100644
--- a/chrome/browser/ui/cocoa/find_bar/find_bar_text_field_cell.mm
+++ b/chrome/browser/ui/cocoa/find_bar/find_bar_text_field_cell.mm
@@ -57,7 +57,7 @@
 // Convenience for the attributes used in the right-justified info
 // cells.  Sets the background color to red if |foundMatches| is YES.
 - (NSDictionary*)resultsAttributes:(BOOL)foundMatches {
-  scoped_nsobject<NSMutableParagraphStyle> style(
+  base::scoped_nsobject<NSMutableParagraphStyle> style(
       [[NSMutableParagraphStyle alloc] init]);
   [style setAlignment:NSRightTextAlignment];
 
diff --git a/chrome/browser/ui/cocoa/find_bar/find_bar_text_field_cell_unittest.mm b/chrome/browser/ui/cocoa/find_bar/find_bar_text_field_cell_unittest.mm
index 8b33d2a..249ff56 100644
--- a/chrome/browser/ui/cocoa/find_bar/find_bar_text_field_cell_unittest.mm
+++ b/chrome/browser/ui/cocoa/find_bar/find_bar_text_field_cell_unittest.mm
@@ -4,9 +4,9 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
-#import "chrome/browser/ui/cocoa/find_bar/find_bar_text_field_cell.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#import "chrome/browser/ui/cocoa/find_bar/find_bar_text_field_cell.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
 
@@ -36,13 +36,13 @@
     // decorations.
     const NSRect frame = NSMakeRect(0, 0, kWidth, 30);
 
-    scoped_nsobject<FindBarTextFieldCell> cell(
+    base::scoped_nsobject<FindBarTextFieldCell> cell(
         [[FindBarTextFieldCell alloc] initTextCell:@"Testing"]);
     cell_ = cell;
     [cell_ setEditable:YES];
     [cell_ setBordered:YES];
 
-    scoped_nsobject<NSTextField> view(
+    base::scoped_nsobject<NSTextField> view(
         [[NSTextField alloc] initWithFrame:frame]);
     view_ = view;
     [view_ setCell:cell_];
@@ -81,12 +81,12 @@
 // appropriately.
 TEST_F(FindBarTextFieldCellTest, SetAndClearFindResults) {
   [cell_ setActiveMatch:10 of:30];
-  scoped_nsobject<NSAttributedString> tenString(
+  base::scoped_nsobject<NSAttributedString> tenString(
       [[cell_ resultsAttributedString] copy]);
   EXPECT_GT([tenString length], 0U);
 
   [cell_ setActiveMatch:0 of:0];
-  scoped_nsobject<NSAttributedString> zeroString(
+  base::scoped_nsobject<NSAttributedString> zeroString(
       [[cell_ resultsAttributedString] copy]);
   EXPECT_GT([zeroString length], 0U);
   EXPECT_FALSE([tenString isEqualToAttributedString:zeroString]);
diff --git a/chrome/browser/ui/cocoa/find_bar/find_bar_text_field_unittest.mm b/chrome/browser/ui/cocoa/find_bar/find_bar_text_field_unittest.mm
index d205efb..30bc8d6 100644
--- a/chrome/browser/ui/cocoa/find_bar/find_bar_text_field_unittest.mm
+++ b/chrome/browser/ui/cocoa/find_bar/find_bar_text_field_unittest.mm
@@ -4,10 +4,10 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #import "chrome/browser/ui/cocoa/find_bar/find_bar_text_field.h"
 #import "chrome/browser/ui/cocoa/find_bar/find_bar_text_field_cell.h"
-#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
 
@@ -23,7 +23,7 @@
     // Make sure this is wide enough to play games with the cell
     // decorations.
     NSRect frame = NSMakeRect(0, 0, kWidth, 30);
-    scoped_nsobject<FindBarTextField> field(
+    base::scoped_nsobject<FindBarTextField> field(
         [[FindBarTextField alloc] initWithFrame:frame]);
     field_ = field.get();
 
diff --git a/chrome/browser/ui/cocoa/find_bar/find_bar_view_unittest.mm b/chrome/browser/ui/cocoa/find_bar/find_bar_view_unittest.mm
index 3714aa5..6f6ea80 100644
--- a/chrome/browser/ui/cocoa/find_bar/find_bar_view_unittest.mm
+++ b/chrome/browser/ui/cocoa/find_bar/find_bar_view_unittest.mm
@@ -4,7 +4,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #import "chrome/browser/ui/cocoa/find_bar/find_bar_view.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -31,7 +31,7 @@
  public:
   FindBarViewTest() {
     NSRect frame = NSMakeRect(0, 0, 100, 30);
-    scoped_nsobject<FindBarView> view(
+    base::scoped_nsobject<FindBarView> view(
         [[FindBarView alloc] initWithFrame:frame]);
     view_ = view.get();
     [[test_window() contentView] addSubview:view_];
@@ -43,7 +43,7 @@
 TEST_VIEW(FindBarViewTest, view_)
 
 TEST_F(FindBarViewTest, FindBarEatsMouseClicksInBackgroundArea) {
-  scoped_nsobject<MouseDownViewPong> pongView(
+  base::scoped_nsobject<MouseDownViewPong> pongView(
       [[MouseDownViewPong alloc] initWithFrame:NSMakeRect(0, 0, 200, 200)]);
 
   // Remove all of the subviews of the findbar, to make sure we don't
@@ -68,7 +68,7 @@
 }
 
 TEST_F(FindBarViewTest, FindBarPassesThroughClicksInTransparentArea) {
-  scoped_nsobject<MouseDownViewPong> pongView(
+  base::scoped_nsobject<MouseDownViewPong> pongView(
       [[MouseDownViewPong alloc] initWithFrame:NSMakeRect(0, 0, 200, 200)]);
   [view_ setFrame:NSMakeRect(0, 0, 200, 200)];
 
diff --git a/chrome/browser/ui/cocoa/find_pasteboard_unittest.mm b/chrome/browser/ui/cocoa/find_pasteboard_unittest.mm
index 049e152..374abc6 100644
--- a/chrome/browser/ui/cocoa/find_pasteboard_unittest.mm
+++ b/chrome/browser/ui/cocoa/find_pasteboard_unittest.mm
@@ -4,7 +4,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
@@ -68,7 +68,7 @@
     pboard_.reset([[FindPasteboardTesting alloc] init]);
   }
  protected:
-  scoped_nsobject<FindPasteboardTesting> pboard_;
+  base::scoped_nsobject<FindPasteboardTesting> pboard_;
 };
 
 TEST_F(FindPasteboardTest, SettingTextUpdatesPboard) {
diff --git a/chrome/browser/ui/cocoa/first_run_bubble_controller_unittest.mm b/chrome/browser/ui/cocoa/first_run_bubble_controller_unittest.mm
index 1d502f4..aee4d06 100644
--- a/chrome/browser/ui/cocoa/first_run_bubble_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/first_run_bubble_controller_unittest.mm
@@ -7,7 +7,7 @@
 #import <Cocoa/Cocoa.h>
 
 #include "base/debug/debugger.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/ui/cocoa/cocoa_profile_test.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -18,11 +18,11 @@
 
 // Check that the bubble doesn't crash or leak.
 TEST_F(FirstRunBubbleControllerTest, Init) {
-  scoped_nsobject<NSWindow> parent([[NSWindow alloc]
-      initWithContentRect:NSMakeRect(0, 0, 800, 600)
-                styleMask:NSBorderlessWindowMask
-                  backing:NSBackingStoreBuffered
-         defer:NO]);
+  base::scoped_nsobject<NSWindow> parent(
+      [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 800, 600)
+                                  styleMask:NSBorderlessWindowMask
+                                    backing:NSBackingStoreBuffered
+                                      defer:NO]);
   [parent setReleasedWhenClosed:NO];
   if (base::debug::BeingDebugged())
     [parent.get() orderFront:nil];
diff --git a/chrome/browser/ui/cocoa/first_run_dialog.mm b/chrome/browser/ui/cocoa/first_run_dialog.mm
index 658495e..29486ff 100644
--- a/chrome/browser/ui/cocoa/first_run_dialog.mm
+++ b/chrome/browser/ui/cocoa/first_run_dialog.mm
@@ -7,8 +7,8 @@
 #include "base/bind.h"
 #include "base/mac/bundle_locations.h"
 #include "base/mac/mac_util.h"
+#import "base/mac/scoped_nsobject.h"
 #include "base/memory/ref_counted.h"
-#import "base/memory/scoped_nsobject.h"
 #include "base/message_loop.h"
 #include "base/strings/sys_string_conversions.h"
 #include "chrome/browser/first_run/first_run.h"
@@ -91,7 +91,7 @@
       g_browser_process->local_state()->FindPreference(
           prefs::kMetricsReportingEnabled);
   if (!metrics_reporting_pref || !metrics_reporting_pref->IsManaged()) {
-    scoped_nsobject<FirstRunDialogController> dialog(
+    base::scoped_nsobject<FirstRunDialogController> dialog(
         [[FirstRunDialogController alloc] init]);
 
     [dialog.get() showWindow:nil];
diff --git a/chrome/browser/ui/cocoa/floating_bar_backing_view_unittest.mm b/chrome/browser/ui/cocoa/floating_bar_backing_view_unittest.mm
index bf94628..f4a3a59 100644
--- a/chrome/browser/ui/cocoa/floating_bar_backing_view_unittest.mm
+++ b/chrome/browser/ui/cocoa/floating_bar_backing_view_unittest.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #import "chrome/browser/ui/cocoa/floating_bar_backing_view.h"
 
@@ -12,7 +12,7 @@
  public:
   FloatingBarBackingViewTest() {
     NSRect content_frame = [[test_window() contentView] frame];
-    scoped_nsobject<FloatingBarBackingView> view(
+    base::scoped_nsobject<FloatingBarBackingView> view(
         [[FloatingBarBackingView alloc] initWithFrame:content_frame]);
     view_ = view.get();
     [[test_window() contentView] addSubview:view_];
diff --git a/chrome/browser/ui/cocoa/framed_browser_window.h b/chrome/browser/ui/cocoa/framed_browser_window.h
index ee70280..a5750bf 100644
--- a/chrome/browser/ui/cocoa/framed_browser_window.h
+++ b/chrome/browser/ui/cocoa/framed_browser_window.h
@@ -7,7 +7,6 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
 #include "chrome/browser/ui/cocoa/chrome_browser_window.h"
 
 // Offsets from the top/left of the window frame to the top of the window
diff --git a/chrome/browser/ui/cocoa/framed_browser_window_unittest.mm b/chrome/browser/ui/cocoa/framed_browser_window_unittest.mm
index 066576e..32322ee 100644
--- a/chrome/browser/ui/cocoa/framed_browser_window_unittest.mm
+++ b/chrome/browser/ui/cocoa/framed_browser_window_unittest.mm
@@ -5,7 +5,7 @@
 #import <Cocoa/Cocoa.h>
 
 #include "base/debug/debugger.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/app/chrome_command_ids.h"
 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
@@ -54,7 +54,7 @@
     bounds.origin.y += 40;
 
     [frameView lockFocus];
-    scoped_nsobject<NSBitmapImageRep> bitmap(
+    base::scoped_nsobject<NSBitmapImageRep> bitmap(
         [[NSBitmapImageRep alloc] initWithFocusedViewRect:bounds]);
     [frameView unlockFocus];
 
diff --git a/chrome/browser/ui/cocoa/fullscreen_exit_bubble_controller.h b/chrome/browser/ui/cocoa/fullscreen_exit_bubble_controller.h
index b48fc87..60b986d 100644
--- a/chrome/browser/ui/cocoa/fullscreen_exit_bubble_controller.h
+++ b/chrome/browser/ui/cocoa/fullscreen_exit_bubble_controller.h
@@ -4,7 +4,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/ui/fullscreen/fullscreen_exit_bubble_type.h"
 #include "googleurl/src/gurl.h"
 
@@ -34,10 +34,10 @@
   // text views cannot conveniently be created in IB. The xib file contains
   // a text field |exitLabelPlaceholder_| that's replaced by this text view
   // |exitLabel_| in -awakeFromNib.
-  scoped_nsobject<NSTextView> exitLabel_;
+  base::scoped_nsobject<NSTextView> exitLabel_;
 
-  scoped_nsobject<NSTimer> hideTimer_;
-  scoped_nsobject<NSAnimation> hideAnimation_;
+  base::scoped_nsobject<NSTimer> hideTimer_;
+  base::scoped_nsobject<NSAnimation> hideAnimation_;
 };
 
 // Initializes a new InfoBarController.
diff --git a/chrome/browser/ui/cocoa/fullscreen_exit_bubble_controller_unittest.mm b/chrome/browser/ui/cocoa/fullscreen_exit_bubble_controller_unittest.mm
index 520755e..fc169c1 100644
--- a/chrome/browser/ui/cocoa/fullscreen_exit_bubble_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/fullscreen_exit_bubble_controller_unittest.mm
@@ -66,13 +66,13 @@
 
   void AppendTabToStrip() {
     WebContents* web_contents = WebContents::Create(
-        content::WebContents::CreateParams(profile(), site_instance_));
+        content::WebContents::CreateParams(profile(), site_instance_.get()));
     browser()->tab_strip_model()->AppendWebContents(
         web_contents, /*foreground=*/true);
   }
 
   scoped_refptr<SiteInstance> site_instance_;
-  scoped_nsobject<FullscreenExitBubbleController> controller_;
+  base::scoped_nsobject<FullscreenExitBubbleController> controller_;
 };
 
 // http://crbug.com/103912
diff --git a/chrome/browser/ui/cocoa/fullscreen_exit_bubble_view.mm b/chrome/browser/ui/cocoa/fullscreen_exit_bubble_view.mm
index 6c491d6..8d79127 100644
--- a/chrome/browser/ui/cocoa/fullscreen_exit_bubble_view.mm
+++ b/chrome/browser/ui/cocoa/fullscreen_exit_bubble_view.mm
@@ -5,7 +5,7 @@
 #import "chrome/browser/ui/cocoa/fullscreen_exit_bubble_view.h"
 
 #include "base/mac/mac_util.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
 
 namespace {
@@ -43,7 +43,7 @@
   [bezier closePath];
   [[NSColor whiteColor] set];
   gfx::ScopedNSGraphicsContextSaveGState scoped_g_state;
-  scoped_nsobject<NSShadow> shadow([[NSShadow alloc] init]);
+  base::scoped_nsobject<NSShadow> shadow([[NSShadow alloc] init]);
   if (base::mac::IsOSLionOrLater()) {
     [shadow setShadowBlurRadius:kShadowBlurRadiusLion];
   } else {
diff --git a/chrome/browser/ui/cocoa/fullscreen_window_unittest.mm b/chrome/browser/ui/cocoa/fullscreen_window_unittest.mm
index 0ccf365..053a951 100644
--- a/chrome/browser/ui/cocoa/fullscreen_window_unittest.mm
+++ b/chrome/browser/ui/cocoa/fullscreen_window_unittest.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/memory/scoped_ptr.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #include "chrome/browser/ui/cocoa/fullscreen_window.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -25,7 +25,7 @@
 };
 
 TEST_F(FullscreenWindowTest, Basics) {
-  scoped_nsobject<FullscreenWindow> window;
+  base::scoped_nsobject<FullscreenWindow> window;
   window.reset([[FullscreenWindow alloc] init]);
 
   EXPECT_EQ([NSScreen mainScreen], [window screen]);
@@ -37,10 +37,10 @@
 }
 
 TEST_F(FullscreenWindowTest, CanPerformClose) {
-  scoped_nsobject<FullscreenWindow> window;
+  base::scoped_nsobject<FullscreenWindow> window;
   window.reset([[FullscreenWindow alloc] init]);
 
-  scoped_nsobject<PerformCloseUIItem> item;
+  base::scoped_nsobject<PerformCloseUIItem> item;
   item.reset([[PerformCloseUIItem alloc] init]);
 
   EXPECT_TRUE([window validateUserInterfaceItem:item.get()]);
diff --git a/chrome/browser/ui/cocoa/global_error_bubble_controller.mm b/chrome/browser/ui/cocoa/global_error_bubble_controller.mm
index bb3377a..4ccb41a 100644
--- a/chrome/browser/ui/cocoa/global_error_bubble_controller.mm
+++ b/chrome/browser/ui/cocoa/global_error_bubble_controller.mm
@@ -5,7 +5,7 @@
 #import "chrome/browser/ui/cocoa/global_error_bubble_controller.h"
 
 #include "base/logging.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/strings/string_util.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
@@ -90,10 +90,10 @@
   std::vector<string16> messages = error_->GetBubbleViewMessages();
   string16 message = JoinString(messages, '\n');
 
-  scoped_nsobject<NSMutableAttributedString> messageValue(
+  base::scoped_nsobject<NSMutableAttributedString> messageValue(
       [[NSMutableAttributedString alloc]
-        initWithString:SysUTF16ToNSString(message)]);
-  scoped_nsobject<NSMutableParagraphStyle> style(
+          initWithString:SysUTF16ToNSString(message)]);
+  base::scoped_nsobject<NSMutableParagraphStyle> style(
       [[NSMutableParagraphStyle alloc] init]);
   [style setParagraphSpacing:kParagraphSpacing];
   [messageValue addAttribute:NSParagraphStyleAttributeName
diff --git a/chrome/browser/ui/cocoa/gradient_button_cell.h b/chrome/browser/ui/cocoa/gradient_button_cell.h
index 515bc3a..7b03a28 100644
--- a/chrome/browser/ui/cocoa/gradient_button_cell.h
+++ b/chrome/browser/ui/cocoa/gradient_button_cell.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 
 namespace ui {
 class ThemeProvider;
@@ -55,15 +55,15 @@
   // Custom drawing means we need to perform our own mouse tracking if
   // the cell is setShowsBorderOnlyWhileMouseInside:YES.
   BOOL isMouseInside_;
-  scoped_nsobject<NSTrackingArea> trackingArea_;
+  base::scoped_nsobject<NSTrackingArea> trackingArea_;
   BOOL shouldTheme_;
   CGFloat hoverAlpha_;  // 0-1. Controls the alpha during mouse hover
   NSTimeInterval lastHoverUpdate_;
-  scoped_nsobject<NSGradient> gradient_;
+  base::scoped_nsobject<NSGradient> gradient_;
   gradient_button_cell::PulseState pulseState_;
   CGFloat pulseMultiplier_;  // for selecting pulse direction when continuous.
   CGFloat outerStrokeAlphaMult_;  // For pulsing.
-  scoped_nsobject<NSImage> overlayImage_;
+  base::scoped_nsobject<NSImage> overlayImage_;
 }
 
 // Turn off theming.  Temporary work-around.
diff --git a/chrome/browser/ui/cocoa/gradient_button_cell.mm b/chrome/browser/ui/cocoa/gradient_button_cell.mm
index b5b0d51..959e0d3 100644
--- a/chrome/browser/ui/cocoa/gradient_button_cell.mm
+++ b/chrome/browser/ui/cocoa/gradient_button_cell.mm
@@ -7,12 +7,12 @@
 #include <cmath>
 
 #include "base/logging.h"
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #import "chrome/browser/themes/theme_properties.h"
 #import "chrome/browser/themes/theme_service.h"
 #import "chrome/browser/ui/cocoa/nsview_additions.h"
-#import "chrome/browser/ui/cocoa/themed_window.h"
 #import "chrome/browser/ui/cocoa/rect_path_utils.h"
+#import "chrome/browser/ui/cocoa/themed_window.h"
 #include "grit/theme_resources.h"
 #import "third_party/GTM/AppKit/GTMNSColor+Luminance.h"
 #import "ui/base/cocoa/nsgraphics_context_additions.h"
@@ -422,7 +422,7 @@
     // Draw the top inner highlight.
     NSAffineTransform* highlightTransform = [NSAffineTransform transform];
     [highlightTransform translateXBy:1 yBy:1];
-    scoped_nsobject<NSBezierPath> highlightPath([innerPath copy]);
+    base::scoped_nsobject<NSBezierPath> highlightPath([innerPath copy]);
     [highlightPath transformUsingAffineTransform:highlightTransform];
     [[NSColor colorWithCalibratedWhite:1.0 alpha:0.2] setStroke];
     [highlightPath stroke];
@@ -604,7 +604,7 @@
         [NSColor blackColor];
 
     if (isTemplate && themeProvider && themeProvider->UsingDefaultTheme()) {
-      scoped_nsobject<NSShadow> shadow([[NSShadow alloc] init]);
+      base::scoped_nsobject<NSShadow> shadow([[NSShadow alloc] init]);
       [shadow.get() setShadowColor:themeProvider->GetNSColor(
           ThemeProperties::COLOR_TOOLBAR_BEZEL, true)];
       [shadow.get() setShadowOffset:NSMakeSize(0.0, -lineWidth)];
diff --git a/chrome/browser/ui/cocoa/gradient_button_cell_unittest.mm b/chrome/browser/ui/cocoa/gradient_button_cell_unittest.mm
index c174ae6..b9ea960 100644
--- a/chrome/browser/ui/cocoa/gradient_button_cell_unittest.mm
+++ b/chrome/browser/ui/cocoa/gradient_button_cell_unittest.mm
@@ -4,9 +4,9 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
-#import "chrome/browser/ui/cocoa/gradient_button_cell.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#import "chrome/browser/ui/cocoa/gradient_button_cell.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
 
@@ -20,10 +20,11 @@
  public:
   GradientButtonCellTest() {
     NSRect frame = NSMakeRect(0, 0, 50, 30);
-    scoped_nsobject<NSButton>view([[NSButton alloc] initWithFrame:frame]);
+    base::scoped_nsobject<NSButton> view(
+        [[NSButton alloc] initWithFrame:frame]);
     view_ = view.get();
-    scoped_nsobject<GradientButtonCell> cell([[GradientButtonCell alloc]
-                                              initTextCell:@"Testing"]);
+    base::scoped_nsobject<GradientButtonCell> cell(
+        [[GradientButtonCell alloc] initTextCell:@"Testing"]);
     [view_ setCell:cell.get()];
     [[test_window() contentView] addSubview:view_];
   }
diff --git a/chrome/browser/ui/cocoa/history_menu_bridge.h b/chrome/browser/ui/cocoa/history_menu_bridge.h
index 8f4582e..2ab76ed 100644
--- a/chrome/browser/ui/cocoa/history_menu_bridge.h
+++ b/chrome/browser/ui/cocoa/history_menu_bridge.h
@@ -9,8 +9,8 @@
 #include <map>
 #include <vector>
 
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/ref_counted.h"
-#include "base/memory/scoped_nsobject.h"
 #include "chrome/browser/common/cancelable_request.h"
 #import "chrome/browser/favicon/favicon_service.h"
 #include "chrome/browser/history/history_service.h"
@@ -75,7 +75,7 @@
     // The URL that will be navigated to if the user selects this item.
     GURL url;
     // Favicon for the URL.
-    scoped_nsobject<NSImage> icon;
+    base::scoped_nsobject<NSImage> icon;
 
     // If the icon is being requested from the FaviconService, |icon_requested|
     // will be true and |icon_task_id| will be valid. If this is false, then
@@ -89,7 +89,7 @@
     // quickly), the NSMenu can release the item before the HistoryItem has
     // been fully deleted. If this were a weak pointer, it would result in a
     // zombie.
-    scoped_nsobject<NSMenuItem> menu_item;
+    base::scoped_nsobject<NSMenuItem> menu_item;
 
     // This ID is unique for a browser session and can be passed to the
     // TabRestoreService to re-open the closed window or tab that this
@@ -204,7 +204,7 @@
   friend class ::HistoryMenuBridgeTest;
   friend class HistoryMenuCocoaControllerTest;
 
-  scoped_nsobject<HistoryMenuCocoaController> controller_;  // strong
+  base::scoped_nsobject<HistoryMenuCocoaController> controller_;  // strong
 
   Profile* profile_;  // weak
   HistoryService* history_service_;  // weak
@@ -229,7 +229,7 @@
   bool need_recreate_;
 
   // The default favicon if a HistoryItem does not have one.
-  scoped_nsobject<NSImage> default_favicon_;
+  base::scoped_nsobject<NSImage> default_favicon_;
 
   DISALLOW_COPY_AND_ASSIGN(HistoryMenuBridge);
 };
diff --git a/chrome/browser/ui/cocoa/history_menu_bridge.mm b/chrome/browser/ui/cocoa/history_menu_bridge.mm
index dcf7b8b..0fc7438 100644
--- a/chrome/browser/ui/cocoa/history_menu_bridge.mm
+++ b/chrome/browser/ui/cocoa/history_menu_bridge.mm
@@ -207,12 +207,12 @@
       item->session_id = entry_win->id;
 
       // Create the submenu.
-      scoped_nsobject<NSMenu> submenu([[NSMenu alloc] init]);
+      base::scoped_nsobject<NSMenu> submenu([[NSMenu alloc] init]);
 
       // Create standard items within the window submenu.
       NSString* restore_title = l10n_util::GetNSString(
           IDS_HISTORY_CLOSED_RESTORE_WINDOW_MAC);
-      scoped_nsobject<NSMenuItem> restore_item(
+      base::scoped_nsobject<NSMenuItem> restore_item(
           [[NSMenuItem alloc] initWithTitle:restore_title
                                      action:@selector(openHistoryMenuItem:)
                               keyEquivalent:@""]);
diff --git a/chrome/browser/ui/cocoa/history_menu_bridge_unittest.mm b/chrome/browser/ui/cocoa/history_menu_bridge_unittest.mm
index cccecdb..8ff1cf8 100644
--- a/chrome/browser/ui/cocoa/history_menu_bridge_unittest.mm
+++ b/chrome/browser/ui/cocoa/history_menu_bridge_unittest.mm
@@ -42,7 +42,7 @@
   }
 
  private:
-  scoped_nsobject<NSMenu> menu_;
+  base::scoped_nsobject<NSMenu> menu_;
 };
 
 class HistoryMenuBridgeTest : public CocoaProfileTest {
diff --git a/chrome/browser/ui/cocoa/history_menu_cocoa_controller_unittest.mm b/chrome/browser/ui/cocoa/history_menu_cocoa_controller_unittest.mm
index ddcfa9c..3870efb 100644
--- a/chrome/browser/ui/cocoa/history_menu_cocoa_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/history_menu_cocoa_controller_unittest.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/string_util.h"
 #include "base/strings/sys_string_conversions.h"
@@ -71,7 +71,7 @@
 };
 
 TEST_F(HistoryMenuCocoaControllerTest, OpenURLForItem) {
-  scoped_nsobject<NSMenu> menu([[NSMenu alloc] initWithTitle:@"History"]);
+  base::scoped_nsobject<NSMenu> menu([[NSMenu alloc] initWithTitle:@"History"]);
   CreateItems(menu.get());
 
   std::map<NSMenuItem*, HistoryMenuBridge::HistoryItem*>& items =
diff --git a/chrome/browser/ui/cocoa/history_overlay_controller.h b/chrome/browser/ui/cocoa/history_overlay_controller.h
index 3a83a26..541b2f2 100644
--- a/chrome/browser/ui/cocoa/history_overlay_controller.h
+++ b/chrome/browser/ui/cocoa/history_overlay_controller.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 
 @class HistoryOverlayView;
 
@@ -23,9 +23,9 @@
  @private
   HistoryOverlayMode mode_;
   // Strongly typed reference of self.view.
-  scoped_nsobject<HistoryOverlayView> contentView_;
+  base::scoped_nsobject<HistoryOverlayView> contentView_;
   // The view above which self.view is inserted as a subview.
-  scoped_nsobject<NSView> parent_;
+  base::scoped_nsobject<NSView> parent_;
 }
 
 // Designated initializer.
diff --git a/chrome/browser/ui/cocoa/history_overlay_controller.mm b/chrome/browser/ui/cocoa/history_overlay_controller.mm
index f211afc..593a942 100644
--- a/chrome/browser/ui/cocoa/history_overlay_controller.mm
+++ b/chrome/browser/ui/cocoa/history_overlay_controller.mm
@@ -62,7 +62,7 @@
     NSRect arrowRect = NSMakeRect(offset, 0, kShieldRadius, kShieldHeight);
     arrowRect = NSInsetRect(arrowRect, 10, 0);  // Give a little padding.
 
-    scoped_nsobject<NSImageView> imageView(
+    base::scoped_nsobject<NSImageView> imageView(
         [[NSImageView alloc] initWithFrame:arrowRect]);
     [imageView setImage:image];
     [imageView setAutoresizingMask:NSViewMinYMargin | NSViewMaxYMargin];
@@ -162,7 +162,7 @@
 
   NSView* overlay = self.view;
 
-  scoped_nsobject<CAAnimation> animation(
+  base::scoped_nsobject<CAAnimation> animation(
       [[overlay animationForKey:@"alphaValue"] copy]);
   [animation setDelegate:self];
   [animation setDuration:kFadeOutDurationSeconds];
diff --git a/chrome/browser/ui/cocoa/history_overlay_controller_unittest.mm b/chrome/browser/ui/cocoa/history_overlay_controller_unittest.mm
index 491bf24..96ab915 100644
--- a/chrome/browser/ui/cocoa/history_overlay_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/history_overlay_controller_unittest.mm
@@ -28,7 +28,7 @@
   }
 
  private:
-  scoped_nsobject<NSView> test_view_;
+  base::scoped_nsobject<NSView> test_view_;
 };
 
 // Tests that the controller's view gets removed from the hierarchy when the
@@ -37,7 +37,7 @@
   NSView* content_view = [test_window() contentView];
   EXPECT_EQ(1u, [[content_view subviews] count]);
 
-  scoped_nsobject<HistoryOverlayController> controller(
+  base::scoped_nsobject<HistoryOverlayController> controller(
       [[HistoryOverlayController alloc] initForMode:kHistoryOverlayModeBack]);
   [controller showPanelForView:test_view()];
   EXPECT_EQ(2u, [[content_view subviews] count]);
@@ -49,7 +49,7 @@
 // Tests that when the controller is |-dismiss|ed, the animation runs and then
 // is removed when the animation completes.
 TEST_F(HistoryOverlayControllerTest, DismissClearsAnimations) {
-  scoped_nsobject<HistoryOverlayController> controller(
+  base::scoped_nsobject<HistoryOverlayController> controller(
       [[HistoryOverlayController alloc] initForMode:kHistoryOverlayModeBack]);
   [controller showPanelForView:test_view()];
 
diff --git a/chrome/browser/ui/cocoa/hover_close_button.mm b/chrome/browser/ui/cocoa/hover_close_button.mm
index f01a172..7825cf7 100644
--- a/chrome/browser/ui/cocoa/hover_close_button.mm
+++ b/chrome/browser/ui/cocoa/hover_close_button.mm
@@ -4,8 +4,6 @@
 
 #import "chrome/browser/ui/cocoa/hover_close_button.h"
 
-#include "base/memory/scoped_nsobject.h"
-#include "base/memory/scoped_ptr.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "grit/ui_resources.h"
@@ -80,22 +78,6 @@
   [self animationDidStop:animation];
 }
 
-// Override to only accept clicks within the bounds of the defined path, not
-// the entire bounding box. |aPoint| is in the superview's coordinate system.
-- (NSView*)hitTest:(NSPoint)point {
-  NSPoint localPoint = [self convertPoint:point fromView:[self superview]];
-  NSRect pointRect = NSMakeRect(localPoint.x, localPoint.y, 1, 1);
-
-  NSImage* hoverImage = [self imageForHoverState:kHoverStateMouseOver];
-  if ([hoverImage hitTestRect:pointRect
-      withImageDestinationRect:[self bounds]
-                       context:nil
-                         hints:nil
-                       flipped:YES])
-    return [super hitTest:point];
-  return nil;
-}
-
 - (void)drawRect:(NSRect)dirtyRect {
   NSImage* image = [self imageForHoverState:[self hoverState]];
 
diff --git a/chrome/browser/ui/cocoa/hover_close_button_unittest.mm b/chrome/browser/ui/cocoa/hover_close_button_unittest.mm
index c978499..5d19c30 100644
--- a/chrome/browser/ui/cocoa/hover_close_button_unittest.mm
+++ b/chrome/browser/ui/cocoa/hover_close_button_unittest.mm
@@ -4,7 +4,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #import "chrome/browser/ui/cocoa/hover_close_button.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -18,7 +18,7 @@
   }
 
  protected:
-  scoped_nsobject<HoverCloseButton> button_;
+  base::scoped_nsobject<HoverCloseButton> button_;
 };
 
 class WebUIHoverCloseButtonTest : public CocoaTest {
@@ -30,7 +30,7 @@
   }
 
  protected:
-  scoped_nsobject<WebUIHoverCloseButton> button_;
+  base::scoped_nsobject<WebUIHoverCloseButton> button_;
 };
 
 TEST_VIEW(HoverCloseButtonTest, button_)
diff --git a/chrome/browser/ui/cocoa/hung_renderer_controller.h b/chrome/browser/ui/cocoa/hung_renderer_controller.h
index 1d55c8d..1725726 100644
--- a/chrome/browser/ui/cocoa/hung_renderer_controller.h
+++ b/chrome/browser/ui/cocoa/hung_renderer_controller.h
@@ -19,7 +19,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #import "base/memory/scoped_ptr.h"
 
 @class MultiKeyEquivalentButton;
@@ -46,11 +46,11 @@
 
   // Backing data for |tableView_|.  Titles of each WebContents that
   // shares a renderer process with |hungContents_|.
-  scoped_nsobject<NSArray> hungTitles_;
+  base::scoped_nsobject<NSArray> hungTitles_;
 
   // Favicons of each WebContents that shares a renderer process with
   // |hungContents_|.
-  scoped_nsobject<NSArray> hungFavicons_;
+  base::scoped_nsobject<NSArray> hungFavicons_;
 }
 
 // Kills the hung renderers.
diff --git a/chrome/browser/ui/cocoa/hung_renderer_controller.mm b/chrome/browser/ui/cocoa/hung_renderer_controller.mm
index 0837b8b..b75da41 100644
--- a/chrome/browser/ui/cocoa/hung_renderer_controller.mm
+++ b/chrome/browser/ui/cocoa/hung_renderer_controller.mm
@@ -176,8 +176,8 @@
   DCHECK(contents);
   hungContents_ = contents;
   hungContentsObserver_.reset(new WebContentsObserverBridge(contents, self));
-  scoped_nsobject<NSMutableArray> titles([[NSMutableArray alloc] init]);
-  scoped_nsobject<NSMutableArray> favicons([[NSMutableArray alloc] init]);
+  base::scoped_nsobject<NSMutableArray> titles([[NSMutableArray alloc] init]);
+  base::scoped_nsobject<NSMutableArray> favicons([[NSMutableArray alloc] init]);
   for (TabContentsIterator it; !it.done(); it.Next()) {
     if (it->GetRenderProcessHost() == hungContents_->GetRenderProcessHost()) {
       string16 title = it->GetTitle();
diff --git a/chrome/browser/ui/cocoa/hung_renderer_controller_unittest.mm b/chrome/browser/ui/cocoa/hung_renderer_controller_unittest.mm
index 4e71bd4..d7e1766 100644
--- a/chrome/browser/ui/cocoa/hung_renderer_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/hung_renderer_controller_unittest.mm
@@ -4,7 +4,6 @@
 
 #import <Cocoa/Cocoa.h>
 
-#import "base/memory/scoped_nsobject.h"
 #include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #import "chrome/browser/ui/cocoa/hung_renderer_controller.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ui/cocoa/hyperlink_button_cell.h b/chrome/browser/ui/cocoa/hyperlink_button_cell.h
index 2857275..1cdc263 100644
--- a/chrome/browser/ui/cocoa/hyperlink_button_cell.h
+++ b/chrome/browser/ui/cocoa/hyperlink_button_cell.h
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 #import <Cocoa/Cocoa.h>
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 
 // A HyperlinkButtonCell is used to create an NSButton that looks and acts
 // like a hyperlink. The default styling is to look like blue, underlined text
@@ -16,7 +16,7 @@
 //  4. In the Attributes panel, change the Bezel to Square.
 //  5. In the Size panel, set the Height to 16.
 @interface HyperlinkButtonCell : NSButtonCell {
-  scoped_nsobject<NSColor> textColor_;
+  base::scoped_nsobject<NSColor> textColor_;
   BOOL shouldUnderline_;
   BOOL underlineOnHover_;
   BOOL mouseIsInside_;
diff --git a/chrome/browser/ui/cocoa/hyperlink_button_cell.mm b/chrome/browser/ui/cocoa/hyperlink_button_cell.mm
index 4047101..49f316c 100644
--- a/chrome/browser/ui/cocoa/hyperlink_button_cell.mm
+++ b/chrome/browser/ui/cocoa/hyperlink_button_cell.mm
@@ -20,7 +20,7 @@
 
 + (NSButton*)buttonWithString:(NSString*)string {
   NSButton* button = [[[NSButton alloc] initWithFrame:NSZeroRect] autorelease];
-  scoped_nsobject<HyperlinkButtonCell> cell(
+  base::scoped_nsobject<HyperlinkButtonCell> cell(
       [[HyperlinkButtonCell alloc] initTextCell:string]);
   [cell setAlignment:NSLeftTextAlignment];
   [button setCell:cell.get()];
@@ -83,8 +83,8 @@
       (!underlineOnHover_ || (mouseIsInside_ && [self isEnabled])))
     underlineMask = NSUnderlinePatternSolid | NSUnderlineStyleSingle;
 
-  scoped_nsobject<NSMutableParagraphStyle> paragraphStyle(
-    [[NSParagraphStyle defaultParagraphStyle] mutableCopy]);
+  base::scoped_nsobject<NSMutableParagraphStyle> paragraphStyle(
+      [[NSParagraphStyle defaultParagraphStyle] mutableCopy]);
   [paragraphStyle setAlignment:[self alignment]];
   [paragraphStyle setLineBreakMode:[self lineBreakMode]];
 
diff --git a/chrome/browser/ui/cocoa/hyperlink_button_cell_unittest.mm b/chrome/browser/ui/cocoa/hyperlink_button_cell_unittest.mm
index fb59046..18abc03 100644
--- a/chrome/browser/ui/cocoa/hyperlink_button_cell_unittest.mm
+++ b/chrome/browser/ui/cocoa/hyperlink_button_cell_unittest.mm
@@ -5,9 +5,9 @@
 #import <Cocoa/Cocoa.h>
 
 #include "base/mac/foundation_util.h"
-#include "base/memory/scoped_nsobject.h"
-#import "chrome/browser/ui/cocoa/hyperlink_button_cell.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#import "chrome/browser/ui/cocoa/hyperlink_button_cell.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
 
@@ -15,9 +15,10 @@
  public:
   HyperlinkButtonCellTest() {
     NSRect frame = NSMakeRect(0, 0, 50, 30);
-    scoped_nsobject<NSButton> view([[NSButton alloc] initWithFrame:frame]);
+    base::scoped_nsobject<NSButton> view(
+        [[NSButton alloc] initWithFrame:frame]);
     view_ = view.get();
-    scoped_nsobject<HyperlinkButtonCell> cell(
+    base::scoped_nsobject<HyperlinkButtonCell> cell(
         [[HyperlinkButtonCell alloc] initTextCell:@"Testing"]);
     cell_ = cell.get();
     [view_ setCell:cell_];
@@ -47,7 +48,8 @@
 // Tests the three designated intializers.
 TEST_F(HyperlinkButtonCellTest, Initializers) {
   TestCellCustomization(cell_);  // |-initTextFrame:|
-  scoped_nsobject<HyperlinkButtonCell> cell([[HyperlinkButtonCell alloc] init]);
+  base::scoped_nsobject<HyperlinkButtonCell> cell(
+      [[HyperlinkButtonCell alloc] init]);
   TestCellCustomization(cell.get());
 
   // Need to create a dummy archiver to test |-initWithCoder:|.
diff --git a/chrome/browser/ui/cocoa/hyperlink_text_view.h b/chrome/browser/ui/cocoa/hyperlink_text_view.h
index a9ba8d3..adcfa4f 100644
--- a/chrome/browser/ui/cocoa/hyperlink_text_view.h
+++ b/chrome/browser/ui/cocoa/hyperlink_text_view.h
@@ -4,10 +4,13 @@
 
 #import <Cocoa/Cocoa.h>
 
+@class NSColor;
+
 // HyperlinkTextView is an NSTextView subclass for unselectable, linkable text.
 // This subclass doesn't show the text caret or IBeamCursor, whereas the base
 // class NSTextView displays both with full keyboard accessibility enabled.
 @interface HyperlinkTextView : NSTextView
+
 // Convenience function that sets the |HyperlinkTextView| contents to the
 // specified |message| with a hypertext style |link| inserted at |linkOffset|.
 // Uses the supplied |font|, |messageColor|, and |linkColor|.
@@ -17,4 +20,16 @@
                      font:(NSFont*)font
              messageColor:(NSColor*)messageColor
                 linkColor:(NSColor*)linkColor;
+
+// Set the |message| displayed by the HyperlinkTextView, using |font| and
+// |messageColor|.
+- (void)setMessage:(NSString*)message
+          withFont:(NSFont*)font
+      messageColor:(NSColor*)messageColor;
+
+// Marks a |range| within the given message as link, associating it with
+// a |name| that is passed to the delegate's textView:clickedOnLink:atIndex:.
+- (void)addLinkRange:(NSRange)range
+            withName:(id)name
+           linkColor:(NSColor*)linkColor;
 @end
diff --git a/chrome/browser/ui/cocoa/hyperlink_text_view.mm b/chrome/browser/ui/cocoa/hyperlink_text_view.mm
index ea92f4c..178d6a2 100644
--- a/chrome/browser/ui/cocoa/hyperlink_text_view.mm
+++ b/chrome/browser/ui/cocoa/hyperlink_text_view.mm
@@ -4,7 +4,7 @@
 
 #import "chrome/browser/ui/cocoa/hyperlink_text_view.h"
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 
 // The baseline shift for text in the NSTextView.
 const float kTextBaselineShift = -1.0;
@@ -71,6 +71,11 @@
   [self setDrawsBackground:NO];
   [self setHorizontallyResizable:NO];
   [self setVerticallyResizable:NO];
+
+  // When text is rendered, linkTextAttributes override anything set via
+  // addAttributes for text that has NSLinkAttributeName. Set to nil to allow
+  // custom attributes to take precendence.
+  [self setLinkTextAttributes:nil];
 }
 
 - (void)fixupCursor {
@@ -84,48 +89,48 @@
                      font:(NSFont*)font
              messageColor:(NSColor*)messageColor
                 linkColor:(NSColor*)linkColor {
+  NSMutableString* finalMessage = [NSMutableString stringWithString:message];
+  [finalMessage insertString:link atIndex:linkOffset];
+  [self setMessage:finalMessage withFont:font messageColor:messageColor];
+  if ([link length] != 0) {
+    [self addLinkRange:NSMakeRange(linkOffset, [link length])
+              withName:@""
+             linkColor:linkColor];
+  }
+}
+
+- (void)setMessage:(NSString*)message
+          withFont:(NSFont*)font
+      messageColor:(NSColor*)messageColor {
   // Create an attributes dictionary for the message and link.
-  NSMutableDictionary* attributes = [NSMutableDictionary dictionary];
-  [attributes setObject:messageColor
-                 forKey:NSForegroundColorAttributeName];
-  [attributes setObject:[NSCursor arrowCursor]
-                 forKey:NSCursorAttributeName];
-  [attributes setObject:font
-                 forKey:NSFontAttributeName];
-  [attributes setObject:[NSNumber numberWithFloat:kTextBaselineShift]
-                 forKey:NSBaselineOffsetAttributeName];
+  NSDictionary* attributes = @{
+    NSForegroundColorAttributeName : messageColor,
+    NSCursorAttributeName : [NSCursor arrowCursor],
+    NSFontAttributeName : font,
+    NSBaselineOffsetAttributeName : @(kTextBaselineShift)
+  };
 
   // Create the attributed string for the message.
-  scoped_nsobject<NSMutableAttributedString> attributedMessage(
+  base::scoped_nsobject<NSAttributedString> attributedMessage(
       [[NSMutableAttributedString alloc] initWithString:message
                                              attributes:attributes]);
 
-  if ([link length] != 0) {
-    // Add additional attributes to style the link text appropriately as
-    // well as linkify it.
-    [attributes setObject:linkColor
-                   forKey:NSForegroundColorAttributeName];
-    [attributes setObject:[NSNumber numberWithBool:YES]
-                   forKey:NSUnderlineStyleAttributeName];
-    [attributes setObject:[NSCursor pointingHandCursor]
-                   forKey:NSCursorAttributeName];
-    [attributes setObject:[NSNumber numberWithInt:NSSingleUnderlineStyle]
-                   forKey:NSUnderlineStyleAttributeName];
-    [attributes setObject:[NSString string]  // dummy value
-                   forKey:NSLinkAttributeName];
-
-    // Insert the link into the message at the appropriate offset.
-    scoped_nsobject<NSAttributedString> attributedLink(
-        [[NSAttributedString alloc] initWithString:link
-                                        attributes:attributes]);
-    [attributedMessage.get() insertAttributedString:attributedLink.get()
-                                            atIndex:linkOffset];
-    // Ensure the TextView doesn't override the link style.
-    [self setLinkTextAttributes:attributes];
-  }
-
   // Update the text view with the new text.
   [[self textStorage] setAttributedString:attributedMessage];
 }
 
+- (void)addLinkRange:(NSRange)range
+            withName:(id)name
+           linkColor:(NSColor*)linkColor {
+  NSDictionary* attributes = @{
+    NSForegroundColorAttributeName : linkColor,
+    NSUnderlineStyleAttributeName : @(YES),
+    NSCursorAttributeName : [NSCursor pointingHandCursor],
+    NSLinkAttributeName : name,
+    NSUnderlineStyleAttributeName : @(NSSingleUnderlineStyle)
+  };
+
+  [[self textStorage] addAttributes:attributes range:range];
+}
+
 @end
diff --git a/chrome/browser/ui/cocoa/hyperlink_text_view_unittest.mm b/chrome/browser/ui/cocoa/hyperlink_text_view_unittest.mm
index b5903b2..7b02530 100644
--- a/chrome/browser/ui/cocoa/hyperlink_text_view_unittest.mm
+++ b/chrome/browser/ui/cocoa/hyperlink_text_view_unittest.mm
@@ -2,9 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #import "chrome/browser/ui/cocoa/hyperlink_text_view.h"
+#include "testing/gtest_mac.h"
 
 namespace {
 
@@ -12,13 +13,46 @@
  public:
   HyperlinkTextViewTest() {
     NSRect frame = NSMakeRect(0, 0, 50, 50);
-    scoped_nsobject<HyperlinkTextView> view(
+    base::scoped_nsobject<HyperlinkTextView> view(
         [[HyperlinkTextView alloc] initWithFrame:frame]);
     view_ = view.get();
     [[test_window() contentView] addSubview:view_];
   }
 
+  NSFont* GetDefaultFont() {
+    return [NSFont labelFontOfSize:
+         [NSFont systemFontSizeForControlSize:NSRegularControlSize]];
+  }
+
+  NSDictionary* GetDefaultTextAttributes() {
+    const float kTextBaselineShift = -1.0;
+    return @{
+      NSForegroundColorAttributeName : [NSColor blackColor],
+      NSCursorAttributeName : [NSCursor arrowCursor],
+      NSFontAttributeName : GetDefaultFont(),
+      NSBaselineOffsetAttributeName : @(kTextBaselineShift)
+    };
+  }
+
+  NSMutableDictionary* GetDefaultLinkAttributes() {
+    if (!linkAttributes_.get()) {
+      linkAttributes_.reset(
+          [[NSMutableDictionary dictionaryWithDictionary:
+              GetDefaultTextAttributes()] retain]);
+      [linkAttributes_ addEntriesFromDictionary:@{
+          NSForegroundColorAttributeName : [NSColor blueColor],
+          NSUnderlineStyleAttributeName : @(YES),
+          NSCursorAttributeName : [NSCursor pointingHandCursor],
+          NSUnderlineStyleAttributeName : @(NSSingleUnderlineStyle),
+          NSLinkAttributeName : @""}];
+    }
+    return [NSMutableDictionary dictionaryWithDictionary:linkAttributes_];
+  }
+
   HyperlinkTextView* view_;
+
+ private:
+  base::scoped_nsobject<NSMutableDictionary> linkAttributes_;
 };
 
 TEST_VIEW(HyperlinkTextViewTest, view_);
@@ -30,4 +64,126 @@
   EXPECT_FALSE([view_ isVerticallyResizable]);
 }
 
+TEST_F(HyperlinkTextViewTest, LinkInsertion) {
+  // Test that setMessage:withLink:... inserts the link text.
+  [view_ setMessageAndLink:@"This is a short text message"
+                  withLink:@"alarmingly "
+                  atOffset:10
+                      font:GetDefaultFont()
+              messageColor:[NSColor blackColor]
+                 linkColor:[NSColor blueColor]];
+  EXPECT_NSEQ(@"This is a alarmingly short text message",
+              [[view_ textStorage] string]);
+
+  // Test insertion at end - most common use case.
+  NSString* message=@"This is another test message ";
+  [view_ setMessageAndLink:message
+                  withLink:@"with link"
+                  atOffset:[message length]
+                      font:GetDefaultFont()
+              messageColor:[NSColor blackColor]
+                 linkColor:[NSColor blueColor]];
+  EXPECT_NSEQ(@"This is another test message with link",
+              [[view_ textStorage] string]);
+}
+
+TEST_F(HyperlinkTextViewTest, AttributesForMessageWithLink) {
+  // Verifies text attributes are set as expected for setMessageWithLink:...
+  [view_ setMessageAndLink:@"aaabbbbb"
+                  withLink:@"xxxx"
+                  atOffset:3
+                      font:GetDefaultFont()
+              messageColor:[NSColor blackColor]
+                 linkColor:[NSColor blueColor]];
+
+  NSDictionary* attributes;
+  NSRange rangeLimit = NSMakeRange(0, 12);
+  NSRange range;
+  attributes = [[view_ textStorage] attributesAtIndex:0
+                                longestEffectiveRange:&range
+                                              inRange:rangeLimit];
+  EXPECT_EQ(0U, range.location);
+  EXPECT_EQ(3U, range.length);
+  EXPECT_NSEQ(GetDefaultTextAttributes(), attributes);
+
+  attributes = [[view_ textStorage] attributesAtIndex:3
+                                longestEffectiveRange:&range
+                                              inRange:rangeLimit];
+  EXPECT_EQ(3U, range.location);
+  EXPECT_EQ(4U, range.length);
+  EXPECT_NSEQ(GetDefaultLinkAttributes(), attributes);
+
+  attributes = [[view_ textStorage] attributesAtIndex:7
+                                longestEffectiveRange:&range
+                                              inRange:rangeLimit];
+  EXPECT_EQ(7U, range.location);
+  EXPECT_EQ(5U, range.length);
+  EXPECT_NSEQ(GetDefaultTextAttributes(), attributes);
+
+}
+
+TEST_F(HyperlinkTextViewTest, TestSetMessage) {
+  // Verifies setMessage sets text and attributes properly.
+  NSString* message = @"Test message";
+  [view_ setMessage:message
+           withFont:GetDefaultFont()
+       messageColor:[NSColor blackColor]];
+  EXPECT_NSEQ(@"Test message", [[view_ textStorage] string]);
+
+  NSDictionary* attributes;
+  NSRange rangeLimit = NSMakeRange(0, [message length]);
+  NSRange range;
+  attributes = [[view_ textStorage] attributesAtIndex:0
+                                longestEffectiveRange:&range
+                                              inRange:rangeLimit];
+  EXPECT_EQ(0U, range.location);
+  EXPECT_EQ([message length], range.length);
+  EXPECT_NSEQ(GetDefaultTextAttributes(), attributes);
+}
+
+TEST_F(HyperlinkTextViewTest, TestAddLinkRange) {
+  NSString* message = @"One Two Three Four";
+  [view_ setMessage:message
+           withFont:GetDefaultFont()
+       messageColor:[NSColor blackColor]];
+
+  NSColor* blue = [NSColor blueColor];
+  [view_ addLinkRange:NSMakeRange(4,3) withName:@"Name:Two" linkColor:blue];
+  [view_ addLinkRange:NSMakeRange(14,4) withName:@"Name:Four" linkColor:blue];
+
+  NSDictionary* attributes;
+  NSRange rangeLimit = NSMakeRange(0, [message length]);
+  NSRange range;
+  attributes = [[view_ textStorage] attributesAtIndex:0
+                                longestEffectiveRange:&range
+                                              inRange:rangeLimit];
+  EXPECT_EQ(0U, range.location);
+  EXPECT_EQ(4U, range.length);
+  EXPECT_NSEQ(GetDefaultTextAttributes(), attributes);
+
+  NSMutableDictionary* linkAttributes = GetDefaultLinkAttributes();
+  [linkAttributes setObject:@"Name:Two" forKey:NSLinkAttributeName];
+  attributes = [[view_ textStorage] attributesAtIndex:4
+                                longestEffectiveRange:&range
+                                              inRange:rangeLimit];
+  EXPECT_EQ(4U, range.location);
+  EXPECT_EQ(3U, range.length);
+  EXPECT_NSEQ(linkAttributes, attributes);
+
+  attributes = [[view_ textStorage] attributesAtIndex:7
+                                longestEffectiveRange:&range
+                                              inRange:rangeLimit];
+  EXPECT_EQ(7U, range.location);
+  EXPECT_EQ(7U, range.length);
+  EXPECT_NSEQ(GetDefaultTextAttributes(), attributes);
+
+  [linkAttributes setObject:@"Name:Four" forKey:NSLinkAttributeName];
+  attributes = [[view_ textStorage] attributesAtIndex:14
+                                longestEffectiveRange:&range
+                                              inRange:rangeLimit];
+  EXPECT_EQ(14U, range.location);
+  EXPECT_EQ(4U, range.length);
+  EXPECT_NSEQ(linkAttributes, attributes);
+}
+
 }  // namespace
diff --git a/chrome/browser/ui/cocoa/image_button_cell.h b/chrome/browser/ui/cocoa/image_button_cell.h
index 7f90195..4f4dc60 100644
--- a/chrome/browser/ui/cocoa/image_button_cell.h
+++ b/chrome/browser/ui/cocoa/image_button_cell.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 
 namespace image_button_cell {
 
@@ -39,7 +39,7 @@
   struct {
     // At most one of these two fields will be non-null.
     int imageId;
-    scoped_nsobject<NSImage> image;
+    base::scoped_nsobject<NSImage> image;
   } image_[image_button_cell::kButtonStateCount];
   BOOL isMouseInside_;
 }
diff --git a/chrome/browser/ui/cocoa/image_button_cell_unittest.mm b/chrome/browser/ui/cocoa/image_button_cell_unittest.mm
index bbe2921..84d1191 100644
--- a/chrome/browser/ui/cocoa/image_button_cell_unittest.mm
+++ b/chrome/browser/ui/cocoa/image_button_cell_unittest.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #import "chrome/browser/ui/cocoa/image_button_cell.h"
 #include "grit/theme_resources.h"
@@ -13,9 +13,10 @@
  public:
   ImageButtonCellTest() {
     NSRect frame = NSMakeRect(0, 0, 50, 30);
-    scoped_nsobject<NSButton>view([[NSButton alloc] initWithFrame:frame]);
+    base::scoped_nsobject<NSButton> view(
+        [[NSButton alloc] initWithFrame:frame]);
     view_ = view.get();
-    scoped_nsobject<ImageButtonCell> cell(
+    base::scoped_nsobject<ImageButtonCell> cell(
         [[ImageButtonCell alloc] initTextCell:@""]);
     [view_ setCell:cell.get()];
     [[test_window() contentView] addSubview:view_];
diff --git a/chrome/browser/ui/cocoa/importer/import_lock_dialog_cocoa.mm b/chrome/browser/ui/cocoa/importer/import_lock_dialog_cocoa.mm
index c3db086..e884072 100644
--- a/chrome/browser/ui/cocoa/importer/import_lock_dialog_cocoa.mm
+++ b/chrome/browser/ui/cocoa/importer/import_lock_dialog_cocoa.mm
@@ -6,7 +6,7 @@
 
 #include "base/bind.h"
 #include "base/callback.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/message_loop.h"
 #include "chrome/browser/importer/importer_lock_dialog.h"
 #include "content/public/browser/user_metrics.h"
@@ -20,7 +20,7 @@
 
 void ShowImportLockDialog(gfx::NativeWindow parent,
                           const base::Callback<void(bool)>& callback) {
-  scoped_nsobject<NSAlert> lock_alert([[NSAlert alloc] init]);
+  base::scoped_nsobject<NSAlert> lock_alert([[NSAlert alloc] init]);
   [lock_alert addButtonWithTitle:l10n_util::GetNSStringWithFixup(
       IDS_IMPORTER_LOCK_OK)];
   [lock_alert addButtonWithTitle:l10n_util::GetNSStringWithFixup(
diff --git a/chrome/browser/ui/cocoa/info_bubble_view.h b/chrome/browser/ui/cocoa/info_bubble_view.h
index b7c9a76..6987eb7 100644
--- a/chrome/browser/ui/cocoa/info_bubble_view.h
+++ b/chrome/browser/ui/cocoa/info_bubble_view.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 
 namespace info_bubble {
 
@@ -50,7 +50,7 @@
   info_bubble::BubbleArrowLocation arrowLocation_;
   info_bubble::BubbleAlignment alignment_;
   info_bubble::CornerFlags cornerFlags_;
-  scoped_nsobject<NSColor> backgroundColor_;
+  base::scoped_nsobject<NSColor> backgroundColor_;
 }
 
 @property(assign, nonatomic) info_bubble::BubbleArrowLocation arrowLocation;
diff --git a/chrome/browser/ui/cocoa/info_bubble_view.mm b/chrome/browser/ui/cocoa/info_bubble_view.mm
index e5be040..a25932a 100644
--- a/chrome/browser/ui/cocoa/info_bubble_view.mm
+++ b/chrome/browser/ui/cocoa/info_bubble_view.mm
@@ -5,7 +5,6 @@
 #import "chrome/browser/ui/cocoa/info_bubble_view.h"
 
 #include "base/logging.h"
-#include "base/memory/scoped_nsobject.h"
 #import "third_party/GTM/AppKit/GTMNSBezierPath+RoundRect.h"
 
 @implementation InfoBubbleView
diff --git a/chrome/browser/ui/cocoa/info_bubble_view_unittest.mm b/chrome/browser/ui/cocoa/info_bubble_view_unittest.mm
index ff60da5..82b135a 100644
--- a/chrome/browser/ui/cocoa/info_bubble_view_unittest.mm
+++ b/chrome/browser/ui/cocoa/info_bubble_view_unittest.mm
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/memory/scoped_nsobject.h"
-#import "chrome/browser/ui/cocoa/info_bubble_view.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#import "chrome/browser/ui/cocoa/info_bubble_view.h"
 
 namespace {
 
@@ -12,7 +12,7 @@
  public:
   InfoBubbleViewTest() {
     NSRect frame = NSMakeRect(0, 0, 100, 30);
-    scoped_nsobject<InfoBubbleView> view(
+    base::scoped_nsobject<InfoBubbleView> view(
         [[InfoBubbleView alloc] initWithFrame:frame]);
     view_ = view.get();
     [[test_window() contentView] addSubview:view_];
diff --git a/chrome/browser/ui/cocoa/info_bubble_window.mm b/chrome/browser/ui/cocoa/info_bubble_window.mm
index 4da277a..1cc17b8 100644
--- a/chrome/browser/ui/cocoa/info_bubble_window.mm
+++ b/chrome/browser/ui/cocoa/info_bubble_window.mm
@@ -6,7 +6,7 @@
 
 #include "base/basictypes.h"
 #include "base/logging.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
@@ -123,7 +123,7 @@
     // Notice that only the alphaValue Animation is replaced in case
     // superclasses set up animations.
     CAAnimation* alphaAnimation = [CABasicAnimation animation];
-    scoped_nsobject<InfoBubbleWindowCloser> delegate(
+    base::scoped_nsobject<InfoBubbleWindowCloser> delegate(
         [[InfoBubbleWindowCloser alloc] initWithWindow:self]);
     [alphaAnimation setDelegate:delegate];
     NSMutableDictionary* animations =
diff --git a/chrome/browser/ui/cocoa/infobars/before_translate_infobar_controller.h b/chrome/browser/ui/cocoa/infobars/before_translate_infobar_controller.h
index b2e10a0..df751e2 100644
--- a/chrome/browser/ui/cocoa/infobars/before_translate_infobar_controller.h
+++ b/chrome/browser/ui/cocoa/infobars/before_translate_infobar_controller.h
@@ -5,8 +5,8 @@
 #import "chrome/browser/ui/cocoa/infobars/translate_infobar_base.h"
 
 @interface BeforeTranslateInfobarController : TranslateInfoBarControllerBase {
-  scoped_nsobject<NSButton> alwaysTranslateButton_;
-  scoped_nsobject<NSButton> neverTranslateButton_;
+  base::scoped_nsobject<NSButton> alwaysTranslateButton_;
+  base::scoped_nsobject<NSButton> neverTranslateButton_;
 }
 
 // Creates and initializes the alwaysTranslate and neverTranslate buttons.
diff --git a/chrome/browser/ui/cocoa/infobars/confirm_infobar_controller_unittest.mm b/chrome/browser/ui/cocoa/infobars/confirm_infobar_controller_unittest.mm
index af29dee..2ef1404 100644
--- a/chrome/browser/ui/cocoa/infobars/confirm_infobar_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/infobars/confirm_infobar_controller_unittest.mm
@@ -4,7 +4,7 @@
 
 #import "chrome/browser/ui/cocoa/infobars/confirm_infobar_controller.h"
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/strings/string_util.h"
 #include "base/strings/sys_string_conversions.h"
 #include "chrome/browser/infobars/confirm_infobar_delegate.h"
@@ -110,8 +110,8 @@
   bool delegate_closed() const { return delegate_ == NULL; }
 
   MockConfirmInfoBarDelegate* delegate_;  // Owns itself.
-  scoped_nsobject<id> container_;
-  scoped_nsobject<ConfirmInfoBarController> controller_;
+  base::scoped_nsobject<id> container_;
+  base::scoped_nsobject<ConfirmInfoBarController> controller_;
   bool closed_delegate_ok_clicked_;
   bool closed_delegate_cancel_clicked_;
   bool closed_delegate_link_clicked_;
diff --git a/chrome/browser/ui/cocoa/infobars/extension_infobar_controller.h b/chrome/browser/ui/cocoa/infobars/extension_infobar_controller.h
index b028658..809aa31 100644
--- a/chrome/browser/ui/cocoa/infobars/extension_infobar_controller.h
+++ b/chrome/browser/ui/cocoa/infobars/extension_infobar_controller.h
@@ -9,7 +9,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 
 @class ExtensionActionContextMenu;
@@ -25,10 +25,10 @@
 
   // The InfoBar's button with the Extension's icon that launches the context
   // menu.
-  scoped_nsobject<MenuButton> dropdownButton_;
+  base::scoped_nsobject<MenuButton> dropdownButton_;
 
   // The context menu that pops up when the left button is clicked.
-  scoped_nsobject<ExtensionActionContextMenu> contextMenu_;
+  base::scoped_nsobject<ExtensionActionContextMenu> contextMenu_;
 
   // Helper class to bridge C++ and ObjC functionality together for the infobar.
   scoped_ptr<InfobarBridge> bridge_;
diff --git a/chrome/browser/ui/cocoa/infobars/infobar_container_controller.h b/chrome/browser/ui/cocoa/infobars/infobar_container_controller.h
index c08ea19..f645b79 100644
--- a/chrome/browser/ui/cocoa/infobars/infobar_container_controller.h
+++ b/chrome/browser/ui/cocoa/infobars/infobar_container_controller.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #import "chrome/browser/ui/cocoa/view_resizer.h"
 #include "content/public/browser/notification_registrar.h"
@@ -58,10 +58,10 @@
   content::WebContents* currentWebContents_;  // weak
 
   // Holds the InfoBarControllers currently owned by this container.
-  scoped_nsobject<NSMutableArray> infobarControllers_;
+  base::scoped_nsobject<NSMutableArray> infobarControllers_;
 
   // Holds InfoBarControllers when they are in the process of animating out.
-  scoped_nsobject<NSMutableSet> closingInfoBars_;
+  base::scoped_nsobject<NSMutableSet> closingInfoBars_;
 
   // Lets us registers for INFOBAR_ADDED/INFOBAR_REMOVED
   // notifications.  The actual notifications are sent to the
diff --git a/chrome/browser/ui/cocoa/infobars/infobar_container_controller_unittest.mm b/chrome/browser/ui/cocoa/infobars/infobar_container_controller_unittest.mm
index 5251de5..88d3152 100644
--- a/chrome/browser/ui/cocoa/infobars/infobar_container_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/infobars/infobar_container_controller_unittest.mm
@@ -4,7 +4,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #import "chrome/browser/ui/cocoa/infobars/infobar_container_controller.h"
 #include "chrome/browser/ui/cocoa/infobars/mock_confirm_infobar_delegate.h"
@@ -32,7 +32,7 @@
   }
 
  public:
-  scoped_nsobject<ViewResizerPong> resizeDelegate_;
+  base::scoped_nsobject<ViewResizerPong> resizeDelegate_;
   InfoBarContainerController* controller_;
 };
 
diff --git a/chrome/browser/ui/cocoa/infobars/infobar_controller.h b/chrome/browser/ui/cocoa/infobars/infobar_controller.h
index 2f8f26b..f96e7b1 100644
--- a/chrome/browser/ui/cocoa/infobars/infobar_controller.h
+++ b/chrome/browser/ui/cocoa/infobars/infobar_controller.h
@@ -4,7 +4,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 
 @class AnimatableView;
 @protocol InfoBarContainer;
@@ -39,7 +39,7 @@
   // text views cannot conveniently be created in IB. The xib file contains
   // a text field |labelPlaceholder_| that's replaced by this text view |label_|
   // in -awakeFromNib.
-  scoped_nsobject<NSTextView> label_;
+  base::scoped_nsobject<NSTextView> label_;
 };
 
 // Initializes a new InfoBarController.
diff --git a/chrome/browser/ui/cocoa/infobars/infobar_gradient_view.mm b/chrome/browser/ui/cocoa/infobars/infobar_gradient_view.mm
index 352d7ce..51fdb17 100644
--- a/chrome/browser/ui/cocoa/infobars/infobar_gradient_view.mm
+++ b/chrome/browser/ui/cocoa/infobars/infobar_gradient_view.mm
@@ -4,7 +4,7 @@
 
 #include "chrome/browser/ui/cocoa/infobars/infobar_gradient_view.h"
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/infobars/infobar.h"
 #import "chrome/browser/themes/theme_properties.h"
 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
@@ -42,7 +42,7 @@
 - (void)setInfobarType:(InfoBarDelegate::Type)infobarType {
   SkColor topColor = GetInfoBarTopColor(infobarType);
   SkColor bottomColor = GetInfoBarBottomColor(infobarType);
-  scoped_nsobject<NSGradient> gradient([[NSGradient alloc]
+  base::scoped_nsobject<NSGradient> gradient([[NSGradient alloc]
       initWithStartingColor:gfx::SkColorToCalibratedNSColor(topColor)
                 endingColor:gfx::SkColorToCalibratedNSColor(bottomColor)]);
   [self setGradient:gradient];
@@ -84,7 +84,7 @@
   [infoBarPath lineToPoint:NSMakePoint(NSMaxX(bounds), NSMaxY(bounds))];
 
   // Save off the top path of the infobar.
-  scoped_nsobject<NSBezierPath> topPath([infoBarPath copy]);
+  base::scoped_nsobject<NSBezierPath> topPath([infoBarPath copy]);
 
   [infoBarPath lineToPoint:NSMakePoint(NSMaxX(bounds), NSMinY(bounds))];
   [infoBarPath lineToPoint:NSMakePoint(NSMinX(bounds), NSMinY(bounds))];
diff --git a/chrome/browser/ui/cocoa/infobars/infobar_gradient_view_unittest.mm b/chrome/browser/ui/cocoa/infobars/infobar_gradient_view_unittest.mm
index da5b02b..5ef8e83 100644
--- a/chrome/browser/ui/cocoa/infobars/infobar_gradient_view_unittest.mm
+++ b/chrome/browser/ui/cocoa/infobars/infobar_gradient_view_unittest.mm
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/memory/scoped_nsobject.h"
-#import "chrome/browser/ui/cocoa/infobars/infobar_gradient_view.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#import "chrome/browser/ui/cocoa/infobars/infobar_gradient_view.h"
 
 namespace {
 
@@ -12,7 +12,7 @@
  public:
   InfoBarGradientViewTest() {
     NSRect frame = NSMakeRect(0, 0, 100, 30);
-    scoped_nsobject<InfoBarGradientView> view(
+    base::scoped_nsobject<InfoBarGradientView> view(
         [[InfoBarGradientView alloc] initWithFrame:frame]);
     view_ = view.get();
     [[test_window() contentView] addSubview:view_];
diff --git a/chrome/browser/ui/cocoa/infobars/infobar_utilities.mm b/chrome/browser/ui/cocoa/infobars/infobar_utilities.mm
index 13a09ff..c5e5e63 100644
--- a/chrome/browser/ui/cocoa/infobars/infobar_utilities.mm
+++ b/chrome/browser/ui/cocoa/infobars/infobar_utilities.mm
@@ -4,7 +4,7 @@
 
 #import "chrome/browser/ui/cocoa/infobars/infobar_utilities.h"
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/infobars/infobar_container_controller.h"
 #import "chrome/browser/ui/cocoa/infobars/infobar_gradient_view.h"
 
@@ -69,10 +69,10 @@
   if (tag == -1) {
     [menu addItem:[NSMenuItem separatorItem]];
   } else {
-    scoped_nsobject<NSMenuItem> item([[NSMenuItem alloc]
-      initWithTitle:title
-             action:selector
-      keyEquivalent:@""]);
+    base::scoped_nsobject<NSMenuItem> item(
+        [[NSMenuItem alloc] initWithTitle:title
+                                   action:selector
+                            keyEquivalent:@""]);
     [item setTag:tag];
     [menu addItem:item];
     [item setTarget:target];
diff --git a/chrome/browser/ui/cocoa/infobars/translate_infobar_base.h b/chrome/browser/ui/cocoa/infobars/translate_infobar_base.h
index 31df784..d1d96ae 100644
--- a/chrome/browser/ui/cocoa/infobars/translate_infobar_base.h
+++ b/chrome/browser/ui/cocoa/infobars/translate_infobar_base.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #include "chrome/browser/translate/options_menu_model.h"
 #include "chrome/browser/translate/translate_infobar_delegate.h"
@@ -23,17 +23,17 @@
 // - (bool)verifyLayout; // For testing.
 @interface TranslateInfoBarControllerBase : InfoBarController<NSMenuDelegate> {
  @protected
-  scoped_nsobject<NSTextField> label1_;
-  scoped_nsobject<NSTextField> label2_;
-  scoped_nsobject<NSTextField> label3_;
-  scoped_nsobject<NSPopUpButton> fromLanguagePopUp_;
-  scoped_nsobject<NSPopUpButton> toLanguagePopUp_;
-  scoped_nsobject<NSPopUpButton> optionsPopUp_;
-  scoped_nsobject<NSButton> showOriginalButton_;
+  base::scoped_nsobject<NSTextField> label1_;
+  base::scoped_nsobject<NSTextField> label2_;
+  base::scoped_nsobject<NSTextField> label3_;
+  base::scoped_nsobject<NSPopUpButton> fromLanguagePopUp_;
+  base::scoped_nsobject<NSPopUpButton> toLanguagePopUp_;
+  base::scoped_nsobject<NSPopUpButton> optionsPopUp_;
+  base::scoped_nsobject<NSButton> showOriginalButton_;
   // This is the button used in the translate message infobar.  It can either be
   // a "Try Again" button, or a "Show Original" button in the case that the
   // page was translated from an unknown language.
-  scoped_nsobject<NSButton> translateMessageButton_;
+  base::scoped_nsobject<NSButton> translateMessageButton_;
 
   // In the current locale, are the "from" and "to" language popup menu
   // flipped from what they'd appear in English.
diff --git a/chrome/browser/ui/cocoa/infobars/translate_infobar_unittest.mm b/chrome/browser/ui/cocoa/infobars/translate_infobar_unittest.mm
index fbbf9f3..e5ae2a0 100644
--- a/chrome/browser/ui/cocoa/infobars/translate_infobar_unittest.mm
+++ b/chrome/browser/ui/cocoa/infobars/translate_infobar_unittest.mm
@@ -4,12 +4,13 @@
 
 #import <Cocoa/Cocoa.h>
 
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #import "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #import "chrome/app/chrome_command_ids.h"  // For translate menu command ids.
 #include "chrome/browser/infobars/infobar_service.h"
 #import "chrome/browser/translate/translate_infobar_delegate.h"
+#include "chrome/browser/translate/translate_language_list.h"
 #include "chrome/browser/ui/cocoa/cocoa_profile_test.h"
 #import "chrome/browser/ui/cocoa/infobars/before_translate_infobar_controller.h"
 #import "chrome/browser/ui/cocoa/infobars/infobar.h"
@@ -61,6 +62,7 @@
   // Each test gets a single Mock translate delegate for the lifetime of
   // the test.
   virtual void SetUp() {
+    TranslateLanguageList::DisableUpdate();
     CocoaProfileTest::SetUp();
     web_contents_.reset(
         WebContents::Create(WebContents::CreateParams(profile())));
@@ -105,7 +107,7 @@
 
   scoped_ptr<WebContents> web_contents_;
   scoped_ptr<MockTranslateInfoBarDelegate> infobar_delegate_;
-  scoped_nsobject<TranslateInfoBarControllerBase> infobar_controller_;
+  base::scoped_nsobject<TranslateInfoBarControllerBase> infobar_controller_;
 };
 
 // Check that we can instantiate a Translate Infobar correctly.
diff --git a/chrome/browser/ui/cocoa/javascript_app_modal_dialog_cocoa.h b/chrome/browser/ui/cocoa/javascript_app_modal_dialog_cocoa.h
index 7aa97ff..aa7153c 100644
--- a/chrome/browser/ui/cocoa/javascript_app_modal_dialog_cocoa.h
+++ b/chrome/browser/ui/cocoa/javascript_app_modal_dialog_cocoa.h
@@ -8,7 +8,7 @@
 #include "chrome/browser/ui/app_modal_dialogs/native_app_modal_dialog.h"
 
 #include "base/logging.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 
 #if __OBJC__
@@ -37,7 +37,7 @@
  private:
   scoped_ptr<JavaScriptAppModalDialog> dialog_;
 
-  scoped_nsobject<JavaScriptAppModalDialogHelper> helper_;
+  base::scoped_nsobject<JavaScriptAppModalDialogHelper> helper_;
   NSAlert* alert_; // weak, owned by |helper_|.
 
   DISALLOW_COPY_AND_ASSIGN(JavaScriptAppModalDialogCocoa);
diff --git a/chrome/browser/ui/cocoa/javascript_app_modal_dialog_cocoa.mm b/chrome/browser/ui/cocoa/javascript_app_modal_dialog_cocoa.mm
index 5e8b6e3..a903723 100644
--- a/chrome/browser/ui/cocoa/javascript_app_modal_dialog_cocoa.mm
+++ b/chrome/browser/ui/cocoa/javascript_app_modal_dialog_cocoa.mm
@@ -21,7 +21,7 @@
 // going away. Is responsible for cleaning itself up.
 @interface JavaScriptAppModalDialogHelper : NSObject<NSAlertDelegate> {
  @private
-  scoped_nsobject<NSAlert> alert_;
+  base::scoped_nsobject<NSAlert> alert_;
   NSTextField* textField_;  // WEAK; owned by alert_
 }
 
@@ -208,13 +208,13 @@
   }
 
   if (message_has_rtl && message_text_field) {
-    scoped_nsobject<NSMutableParagraphStyle> alignment(
+    base::scoped_nsobject<NSMutableParagraphStyle> alignment(
         [[NSParagraphStyle defaultParagraphStyle] mutableCopy]);
     [alignment setAlignment:NSRightTextAlignment];
 
     NSDictionary* alignment_attributes =
         @{ NSParagraphStyleAttributeName : alignment };
-    scoped_nsobject<NSAttributedString> attr_string(
+    base::scoped_nsobject<NSAttributedString> attr_string(
         [[NSAttributedString alloc] initWithString:message_text
                                         attributes:alignment_attributes]);
 
@@ -225,7 +225,7 @@
   if (informative_has_rtl && informative_text_field) {
     base::i18n::TextDirection direction =
         base::i18n::GetFirstStrongCharacterDirection(dialog_->message_text());
-    scoped_nsobject<NSMutableParagraphStyle> alignment(
+    base::scoped_nsobject<NSMutableParagraphStyle> alignment(
         [[NSParagraphStyle defaultParagraphStyle] mutableCopy]);
     [alignment setAlignment:
         (direction == base::i18n::RIGHT_TO_LEFT) ? NSRightTextAlignment
@@ -233,7 +233,7 @@
 
     NSDictionary* alignment_attributes =
         @{ NSParagraphStyleAttributeName : alignment };
-    scoped_nsobject<NSAttributedString> attr_string(
+    base::scoped_nsobject<NSAttributedString> attr_string(
         [[NSAttributedString alloc] initWithString:informative_text
                                         attributes:alignment_attributes]);
 
diff --git a/chrome/browser/ui/cocoa/l10n_util.h b/chrome/browser/ui/cocoa/l10n_util.h
index 7f1be9e..17e8f22 100644
--- a/chrome/browser/ui/cocoa/l10n_util.h
+++ b/chrome/browser/ui/cocoa/l10n_util.h
@@ -29,4 +29,7 @@
                                       const string16& a,
                                       size_t* offset);
 
+// Generates a tooltip string for a given URL and title.
+NSString* TooltipForURLAndTitle(NSString* url, NSString* title);
+
 }  // namespace cocoa_l10n_util
diff --git a/chrome/browser/ui/cocoa/l10n_util.mm b/chrome/browser/ui/cocoa/l10n_util.mm
index 5b4dee4..61eb681 100644
--- a/chrome/browser/ui/cocoa/l10n_util.mm
+++ b/chrome/browser/ui/cocoa/l10n_util.mm
@@ -75,4 +75,13 @@
                                 offset));
 }
 
+NSString* TooltipForURLAndTitle(NSString* url, NSString* title) {
+  if ([title length] == 0)
+    return url;
+  else if ([url length] == 0 || [url isEqualToString:title])
+    return title;
+  else
+    return [NSString stringWithFormat:@"%@\n%@", title, url];
+}
+
 }  // namespace cocoa_l10n_util
diff --git a/chrome/browser/ui/cocoa/location_bar/action_box_menu_bubble_controller.h b/chrome/browser/ui/cocoa/location_bar/action_box_menu_bubble_controller.h
index c24c8de..f0a38ac 100644
--- a/chrome/browser/ui/cocoa/location_bar/action_box_menu_bubble_controller.h
+++ b/chrome/browser/ui/cocoa/location_bar/action_box_menu_bubble_controller.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #import "chrome/browser/ui/cocoa/base_bubble_controller.h"
 #import "ui/base/cocoa/tracking_area.h"
@@ -25,7 +25,7 @@
   scoped_ptr<ActionBoxMenuModel> model_;
 
   // Array of the below view controllers.
-  scoped_nsobject<NSMutableArray> items_;
+  base::scoped_nsobject<NSMutableArray> items_;
 }
 
 // Designated initializer. |point| must be in screen coordinates.
diff --git a/chrome/browser/ui/cocoa/location_bar/action_box_menu_bubble_controller.mm b/chrome/browser/ui/cocoa/location_bar/action_box_menu_bubble_controller.mm
index 5c0862e..d65dc50 100644
--- a/chrome/browser/ui/cocoa/location_bar/action_box_menu_bubble_controller.mm
+++ b/chrome/browser/ui/cocoa/location_bar/action_box_menu_bubble_controller.mm
@@ -100,7 +100,7 @@
   // Use an arbitrary height because it will reflect the size of the content.
   NSRect contentRect = NSMakeRect(0, 0, kBubbleMinWidth, 150);
   // Create an empty window into which content is placed.
-  scoped_nsobject<InfoBubbleWindow> window(
+  base::scoped_nsobject<InfoBubbleWindow> window(
       [[InfoBubbleWindow alloc] initWithContentRect:contentRect
                                           styleMask:NSBorderlessWindowMask
                                             backing:NSBackingStoreBuffered
@@ -160,7 +160,7 @@
   CGFloat yOffset = kVerticalPadding;
 
   // Keep track of a potential separator to resize it when we know the width.
-  scoped_nsobject<NSBox> separatorView;
+  base::scoped_nsobject<NSBox> separatorView;
 
   // Loop over the items in reverse, constructing the menu items.
   CGFloat width = kBubbleMinWidth;
@@ -183,11 +183,10 @@
     } else {
       // Create the item controller. Autorelease it because it will be owned
       // by the |items_| array.
-      scoped_nsobject<ActionBoxMenuItemController> itemController(
-          [[ActionBoxMenuItemController alloc]
-              initWithModelIndex:i
-                  menuController:self
-                         profile:profile_]);
+      base::scoped_nsobject<ActionBoxMenuItemController> itemController(
+          [[ActionBoxMenuItemController alloc] initWithModelIndex:i
+                                                   menuController:self
+                                                          profile:profile_]);
 
       // Adjust the name field to fit the string.
       [GTMUILocalizerAndLayoutTweaker sizeToFitView:[itemController nameField]];
diff --git a/chrome/browser/ui/cocoa/location_bar/action_box_menu_bubble_controller_unittest.mm b/chrome/browser/ui/cocoa/location_bar/action_box_menu_bubble_controller_unittest.mm
index 7139ed6..7399ac5 100644
--- a/chrome/browser/ui/cocoa/location_bar/action_box_menu_bubble_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/location_bar/action_box_menu_bubble_controller_unittest.mm
@@ -87,8 +87,8 @@
                          .Set("background", extensions::DictionaryBuilder()
                              .Set("page", ""))))
         .Build();
-    service_->AddExtension(extension);
-    model->AddExtension(*extension, command_id);
+    service_->AddExtension(extension.get());
+    model->AddExtension(*extension.get(), command_id);
     return extension;
   }
 
diff --git a/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.h b/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.h
index a54e788..eadb217 100644
--- a/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.h
+++ b/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/styled_text_field.h"
 #import "chrome/browser/ui/cocoa/url_drop_target.h"
 
@@ -113,18 +113,18 @@
  @private
   // Undo manager for this text field.  We use a specific instance rather than
   // the standard undo manager in order to let us clear the undo stack at will.
-  scoped_nsobject<NSUndoManager> undoManager_;
+  base::scoped_nsobject<NSUndoManager> undoManager_;
 
   AutocompleteTextFieldObserver* observer_;  // weak, owned by location bar.
 
   // Handles being a drag-and-drop target.
-  scoped_nsobject<URLDropTargetHandler> dropHandler_;
+  base::scoped_nsobject<URLDropTargetHandler> dropHandler_;
 
   // Holds current tooltip strings, to keep them from being dealloced.
-  scoped_nsobject<NSMutableArray> currentToolTips_;
+  base::scoped_nsobject<NSMutableArray> currentToolTips_;
 
-  scoped_nsobject<NSString> suggestText_;
-  scoped_nsobject<NSColor> suggestColor_;
+  base::scoped_nsobject<NSString> suggestText_;
+  base::scoped_nsobject<NSColor> suggestColor_;
 }
 
 @property(nonatomic) AutocompleteTextFieldObserver* observer;
diff --git a/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.mm b/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.mm
index fcdd149..addda9c 100644
--- a/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.mm
+++ b/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.mm
@@ -449,13 +449,13 @@
   if (![suggestText length])
     return;
 
-  scoped_nsobject<NSTextFieldCell> cell(
+  base::scoped_nsobject<NSTextFieldCell> cell(
       [[NSTextFieldCell alloc] initTextCell:@""]);
   [cell setBordered:NO];
   [cell setDrawsBackground:NO];
   [cell setEditable:NO];
 
-  scoped_nsobject<NSMutableAttributedString> combinedText(
+  base::scoped_nsobject<NSMutableAttributedString> combinedText(
       [[NSMutableAttributedString alloc] initWithAttributedString:mainText]);
   NSRange range = NSMakeRange([combinedText length], 0);
   [combinedText replaceCharactersInRange:range withString:suggestText];
diff --git a/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_cell.mm b/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_cell.mm
index 6277c90..ac53430 100644
--- a/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_cell.mm
+++ b/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_cell.mm
@@ -185,8 +185,6 @@
 @implementation AutocompleteTextFieldCell
 
 - (CGFloat)topTextFrameOffset {
-  if (chrome::IsInstantExtendedAPIEnabled())
-    return 2.0;
   return 3.0;
 }
 
@@ -208,9 +206,7 @@
 }
 
 - (CGFloat)lineHeight {
-  if (chrome::IsInstantExtendedAPIEnabled())
-    return 19;
-  return 16;
+  return 17;
 }
 
 - (void)clearDecorations {
@@ -551,7 +547,7 @@
       }
 
       NSDictionary* info = [self getDictionaryForButtonDecoration:button];
-      scoped_nsobject<CrTrackingArea> area(
+      base::scoped_nsobject<CrTrackingArea> area(
           [[CrTrackingArea alloc] initWithRect:decorationFrames[i]
                                        options:NSTrackingMouseEnteredAndExited |
                                                NSTrackingActiveAlways
diff --git a/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_cell_unittest.mm b/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_cell_unittest.mm
index 3af9e75..def7ede 100644
--- a/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_cell_unittest.mm
+++ b/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_cell_unittest.mm
@@ -4,7 +4,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/strings/utf_string_conversions.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #import "chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.h"
@@ -19,8 +19,8 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
-#include "third_party/ocmock/gtest_support.h"
 #import "third_party/ocmock/OCMock/OCMock.h"
+#include "third_party/ocmock/gtest_support.h"
 #include "ui/base/resource/resource_bundle.h"
 
 using ::testing::Return;
@@ -51,11 +51,11 @@
     // decorations.
     const NSRect frame = NSMakeRect(0, 0, kWidth, 30);
 
-    scoped_nsobject<NSTextField> view(
+    base::scoped_nsobject<NSTextField> view(
         [[NSTextField alloc] initWithFrame:frame]);
     view_ = view.get();
 
-    scoped_nsobject<AutocompleteTextFieldCell> cell(
+    base::scoped_nsobject<AutocompleteTextFieldCell> cell(
         [[AutocompleteTextFieldCell alloc] initTextCell:@"Testing"]);
     [cell setEditable:YES];
     [cell setBordered:YES];
diff --git a/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_editor.h b/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_editor.h
index 1943ae8..cf2c5b3 100644
--- a/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_editor.h
+++ b/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_editor.h
@@ -4,7 +4,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/url_drop_target.h"
 
 @class AutocompleteTextField;
@@ -23,9 +23,9 @@
   // allowing the |AutocompletTextField| to handle it (by making an empty
   // |-updateDragTypeRegistration|), since the latter results in a weird
   // start-up time regression.
-  scoped_nsobject<URLDropTargetHandler> dropHandler_;
+  base::scoped_nsobject<URLDropTargetHandler> dropHandler_;
 
-  scoped_nsobject<NSCharacterSet> forbiddenCharacters_;
+  base::scoped_nsobject<NSCharacterSet> forbiddenCharacters_;
 
   // Indicates if the field editor's interpretKeyEvents: method is being called.
   // If it's YES, then we should postpone the call to the observer's
diff --git a/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_editor_unittest.mm b/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_editor_unittest.mm
index 548f6e2..dac079a 100644
--- a/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_editor_unittest.mm
+++ b/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_editor_unittest.mm
@@ -4,7 +4,7 @@
 
 #import "chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_editor.h"
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/string_util.h"
 #include "chrome/app/chrome_command_ids.h"  // IDC_*
@@ -15,8 +15,8 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #import "testing/gtest_mac.h"
 #include "testing/platform_test.h"
-#include "third_party/ocmock/gtest_support.h"
 #import "third_party/ocmock/OCMock/OCMock.h"
+#include "third_party/ocmock/gtest_support.h"
 #import "third_party/ocmock/ocmock_extensions.h"
 #import "ui/base/test/cocoa_test_event_utils.h"
 
@@ -35,7 +35,7 @@
   virtual void SetUp() {
     CocoaTest::SetUp();
     NSRect frame = NSMakeRect(0, 0, 50, 30);
-    scoped_nsobject<AutocompleteTextField> field(
+    base::scoped_nsobject<AutocompleteTextField> field(
         [[AutocompleteTextField alloc] initWithFrame:frame]);
     field_ = field.get();
     [field_ setStringValue:@"Testing"];
@@ -56,7 +56,8 @@
 
   AutocompleteTextFieldEditor* editor_;
   AutocompleteTextField* field_;
-  scoped_nsobject<AutocompleteTextFieldWindowTestDelegate> window_delegate_;
+  base::scoped_nsobject<AutocompleteTextFieldWindowTestDelegate>
+      window_delegate_;
 };
 
 // Disabled because it crashes sometimes. http://crbug.com/49522
@@ -107,7 +108,7 @@
 
   // Trivial menu which we can recognize and which doesn't look like
   // the default editor context menu.
-  scoped_nsobject<id> menu([[NSMenu alloc] initWithTitle:@"Menu"]);
+  base::scoped_nsobject<id> menu([[NSMenu alloc] initWithTitle:@"Menu"]);
   [menu addItemWithTitle:@"Go Fish"
                   action:@selector(goFish:)
            keyEquivalent:@""];
diff --git a/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_unittest.mm b/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_unittest.mm
index 63a4d85..72ffc7a 100644
--- a/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_unittest.mm
+++ b/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_unittest.mm
@@ -5,13 +5,13 @@
 #import <Cocoa/Cocoa.h>
 
 #include "base/mac/foundation_util.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #import "chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.h"
 #import "chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_cell.h"
 #import "chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_editor.h"
 #import "chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_unittest_helper.h"
 #import "chrome/browser/ui/cocoa/location_bar/location_bar_decoration.h"
-#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #include "grit/theme_resources.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -75,7 +75,7 @@
     // Make sure this is wide enough to play games with the cell
     // decorations.
     NSRect frame = NSMakeRect(0, 0, kWidth, 30);
-    scoped_nsobject<AutocompleteTextField> field(
+    base::scoped_nsobject<AutocompleteTextField> field(
         [[AutocompleteTextField alloc] initWithFrame:frame]);
     field_ = field.get();
     [field_ setStringValue:@"Test test"];
@@ -129,7 +129,8 @@
   AutocompleteTextField* field_;
   MockDecoration mock_left_decoration_;
   MockDecoration mock_right_decoration_;
-  scoped_nsobject<AutocompleteTextFieldWindowTestDelegate> window_delegate_;
+  base::scoped_nsobject<AutocompleteTextFieldWindowTestDelegate>
+      window_delegate_;
 };
 
 TEST_VIEW(AutocompleteTextFieldTest, field_);
@@ -622,9 +623,9 @@
 
   const CGFloat edge = NSHeight(bounds) - 4.0;
   const NSSize size = NSMakeSize(edge, edge);
-  scoped_nsobject<NSImage> image([[NSImage alloc] initWithSize:size]);
+  base::scoped_nsobject<NSImage> image([[NSImage alloc] initWithSize:size]);
 
-  scoped_nsobject<NSMenu> menu([[NSMenu alloc] initWithTitle:@"Menu"]);
+  base::scoped_nsobject<NSMenu> menu([[NSMenu alloc] initWithTitle:@"Menu"]);
 
   mock_left_decoration_.SetVisible(true);
   mock_right_decoration_.SetVisible(true);
@@ -674,7 +675,7 @@
       [NSDictionary dictionaryWithObject:font
                                   forKey:NSFontAttributeName];
   NSString* const kString = @"This is a test";
-  scoped_nsobject<NSAttributedString> attributedString(
+  base::scoped_nsobject<NSAttributedString> attributedString(
       [[NSAttributedString alloc] initWithString:kString
                                       attributes:attributes]);
 
@@ -707,7 +708,7 @@
       [NSDictionary dictionaryWithObject:redColor
                                   forKey:NSForegroundColorAttributeName];
   NSString* const kString = @"This is a test";
-  scoped_nsobject<NSAttributedString> attributedString(
+  base::scoped_nsobject<NSAttributedString> attributedString(
       [[NSAttributedString alloc] initWithString:kString
                                       attributes:attributes]);
   [test_window() makePretendKeyWindowAndSetFirstResponder:field_];
@@ -816,7 +817,7 @@
   EXPECT_CALL(field_observer_, ClosePopup());
   [test_window() resignKeyWindow];
 
-  scoped_nsobject<AutocompleteTextField> pin([field_ retain]);
+  base::scoped_nsobject<AutocompleteTextField> pin([field_ retain]);
   [field_ removeFromSuperview];
   [test_window() resignKeyWindow];
 
diff --git a/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_unittest_helper.h b/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_unittest_helper.h
index cd8116a..3ba6511 100644
--- a/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_unittest_helper.h
+++ b/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_unittest_helper.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
@@ -17,7 +17,7 @@
 
 @interface AutocompleteTextFieldWindowTestDelegate :
     NSObject<NSWindowDelegate> {
-  scoped_nsobject<AutocompleteTextFieldEditor> editor_;
+  base::scoped_nsobject<AutocompleteTextFieldEditor> editor_;
 }
 - (id)windowWillReturnFieldEditor:(NSWindow *)sender toObject:(id)anObject;
 @end
diff --git a/chrome/browser/ui/cocoa/location_bar/bubble_decoration.h b/chrome/browser/ui/cocoa/location_bar/bubble_decoration.h
index a1e55f5..6a1d1cc 100644
--- a/chrome/browser/ui/cocoa/location_bar/bubble_decoration.h
+++ b/chrome/browser/ui/cocoa/location_bar/bubble_decoration.h
@@ -8,7 +8,7 @@
 #import <Cocoa/Cocoa.h>
 
 #include "base/gtest_prod_util.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/ui/cocoa/location_bar/location_bar_decoration.h"
 
 // Draws an outlined rounded rect, with an optional image to the left
@@ -46,18 +46,18 @@
                            UsesPartialKeywordIfNarrow);
 
   // Image drawn in the left side of the bubble.
-  scoped_nsobject<NSImage> image_;
+  base::scoped_nsobject<NSImage> image_;
 
   // Label to draw to right of image.  Can be |nil|.
-  scoped_nsobject<NSString> label_;
+  base::scoped_nsobject<NSString> label_;
 
   // Contains attribute for drawing |label_|.
-  scoped_nsobject<NSMutableDictionary> attributes_;
+  base::scoped_nsobject<NSMutableDictionary> attributes_;
 
   // Colors used to draw the bubble, should be set by the subclass
   // constructor.
-  scoped_nsobject<NSColor> background_color_;
-  scoped_nsobject<NSColor> border_color_;
+  base::scoped_nsobject<NSColor> background_color_;
+  base::scoped_nsobject<NSColor> border_color_;
 
   DISALLOW_COPY_AND_ASSIGN(BubbleDecoration);
 };
diff --git a/chrome/browser/ui/cocoa/location_bar/button_decoration.h b/chrome/browser/ui/cocoa/location_bar/button_decoration.h
index 70d4708..fde8f94 100644
--- a/chrome/browser/ui/cocoa/location_bar/button_decoration.h
+++ b/chrome/browser/ui/cocoa/location_bar/button_decoration.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_UI_COCOA_LOCATION_BAR_BUTTON_DECORATION_H_
 #define CHROME_BROWSER_UI_COCOA_LOCATION_BAR_BUTTON_DECORATION_H_
 
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #include "chrome/browser/ui/cocoa/location_bar/location_bar_decoration.h"
 
 // |LocationBarDecoration| which looks and acts like a button.
@@ -42,9 +42,9 @@
   void SetPressedImage(NSImage* pressed_image);
 
  private:
-  scoped_nsobject<NSImage> normal_image_;
-  scoped_nsobject<NSImage> hover_image_;
-  scoped_nsobject<NSImage> pressed_image_;
+  base::scoped_nsobject<NSImage> normal_image_;
+  base::scoped_nsobject<NSImage> hover_image_;
+  base::scoped_nsobject<NSImage> pressed_image_;
   ButtonState state_;
 
   NSImage* GetImage();
diff --git a/chrome/browser/ui/cocoa/location_bar/content_setting_decoration.h b/chrome/browser/ui/cocoa/location_bar/content_setting_decoration.h
index 219992e..dafcd11 100644
--- a/chrome/browser/ui/cocoa/location_bar/content_setting_decoration.h
+++ b/chrome/browser/ui/cocoa/location_bar/content_setting_decoration.h
@@ -52,7 +52,7 @@
   void SetToolTip(NSString* tooltip);
 
   // Returns an attributed string with the animated text.
-  scoped_nsobject<NSAttributedString> CreateAnimatedText();
+  base::scoped_nsobject<NSAttributedString> CreateAnimatedText();
 
   // Measure the width of the animated text.
   CGFloat MeasureTextWidth();
@@ -62,13 +62,13 @@
   LocationBarViewMac* owner_;  // weak
   Profile* profile_;  // weak
 
-  scoped_nsobject<NSString> tooltip_;
+  base::scoped_nsobject<NSString> tooltip_;
 
   // Used when the decoration has animated text.
-  scoped_nsobject<ContentSettingAnimationState> animation_;
+  base::scoped_nsobject<ContentSettingAnimationState> animation_;
   CGFloat text_width_;
-  scoped_nsobject<NSAttributedString> animated_text_;
-  scoped_nsobject<NSGradient> gradient_;
+  base::scoped_nsobject<NSAttributedString> animated_text_;
+  base::scoped_nsobject<NSGradient> gradient_;
 
   DISALLOW_COPY_AND_ASSIGN(ContentSettingDecoration);
 };
diff --git a/chrome/browser/ui/cocoa/location_bar/content_setting_decoration.mm b/chrome/browser/ui/cocoa/location_bar/content_setting_decoration.mm
index 79c33f1..174f5bf 100644
--- a/chrome/browser/ui/cocoa/location_bar/content_setting_decoration.mm
+++ b/chrome/browser/ui/cocoa/location_bar/content_setting_decoration.mm
@@ -228,19 +228,19 @@
   return [animated_text_ size].width;
 }
 
-scoped_nsobject<NSAttributedString>
+base::scoped_nsobject<NSAttributedString>
 ContentSettingDecoration::CreateAnimatedText() {
   NSString* text =
       l10n_util::GetNSString(
           content_setting_image_model_->explanatory_string_id());
-  scoped_nsobject<NSMutableParagraphStyle> style(
+  base::scoped_nsobject<NSMutableParagraphStyle> style(
       [[NSMutableParagraphStyle alloc] init]);
   // Set line break mode to clip the text, otherwise drawInRect: won't draw a
   // word if it doesn't fit in the bounding box.
   [style setLineBreakMode:NSLineBreakByClipping];
   NSDictionary* attributes = @{ NSFontAttributeName : GetFont(),
                                 NSParagraphStyleAttributeName : style };
-  return scoped_nsobject<NSAttributedString>(
+  return base::scoped_nsobject<NSAttributedString>(
       [[NSAttributedString alloc] initWithString:text attributes:attributes]);
 }
 
diff --git a/chrome/browser/ui/cocoa/location_bar/ev_bubble_decoration.h b/chrome/browser/ui/cocoa/location_bar/ev_bubble_decoration.h
index ee7d99f..b17e7d8 100644
--- a/chrome/browser/ui/cocoa/location_bar/ev_bubble_decoration.h
+++ b/chrome/browser/ui/cocoa/location_bar/ev_bubble_decoration.h
@@ -44,7 +44,7 @@
 
  private:
   // The real label.  BubbleDecoration's label may be elided.
-  scoped_nsobject<NSString> full_label_;
+  base::scoped_nsobject<NSString> full_label_;
 
   LocationIconDecoration* location_icon_;  // weak, owned by location bar.
 
diff --git a/chrome/browser/ui/cocoa/location_bar/ev_bubble_decoration_unittest.mm b/chrome/browser/ui/cocoa/location_bar/ev_bubble_decoration_unittest.mm
index f07cfb2..e898e20 100644
--- a/chrome/browser/ui/cocoa/location_bar/ev_bubble_decoration_unittest.mm
+++ b/chrome/browser/ui/cocoa/location_bar/ev_bubble_decoration_unittest.mm
@@ -28,7 +28,8 @@
   const CGFloat kMinimumWidth = 100.0;  // Never should get this small.
 
   const NSSize kImageSize = NSMakeSize(20.0, 20.0);
-  scoped_nsobject<NSImage> image([[NSImage alloc] initWithSize:kImageSize]);
+  base::scoped_nsobject<NSImage> image(
+      [[NSImage alloc] initWithSize:kImageSize]);
 
   decoration_.SetImage(image);
   decoration_.SetFullLabel(kLongString);
diff --git a/chrome/browser/ui/cocoa/location_bar/image_decoration.h b/chrome/browser/ui/cocoa/location_bar/image_decoration.h
index 6b105ab..0bb4193 100644
--- a/chrome/browser/ui/cocoa/location_bar/image_decoration.h
+++ b/chrome/browser/ui/cocoa/location_bar/image_decoration.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_UI_COCOA_LOCATION_BAR_IMAGE_DECORATION_H_
 #define CHROME_BROWSER_UI_COCOA_LOCATION_BAR_IMAGE_DECORATION_H_
 
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #include "chrome/browser/ui/cocoa/location_bar/location_bar_decoration.h"
 
 // |LocationBarDecoration| which sizes and draws itself according to
@@ -27,7 +27,7 @@
   virtual void DrawInFrame(NSRect frame, NSView* control_view) OVERRIDE;
 
  private:
-  scoped_nsobject<NSImage> image_;
+  base::scoped_nsobject<NSImage> image_;
 
   DISALLOW_COPY_AND_ASSIGN(ImageDecoration);
 };
diff --git a/chrome/browser/ui/cocoa/location_bar/image_decoration_unittest.mm b/chrome/browser/ui/cocoa/location_bar/image_decoration_unittest.mm
index db69b0d..2362f79 100644
--- a/chrome/browser/ui/cocoa/location_bar/image_decoration_unittest.mm
+++ b/chrome/browser/ui/cocoa/location_bar/image_decoration_unittest.mm
@@ -20,7 +20,8 @@
   EXPECT_FALSE(decoration_.GetImage());
 
   const NSSize kImageSize = NSMakeSize(20.0, 20.0);
-  scoped_nsobject<NSImage> image([[NSImage alloc] initWithSize:kImageSize]);
+  base::scoped_nsobject<NSImage> image(
+      [[NSImage alloc] initWithSize:kImageSize]);
 
   decoration_.SetImage(image);
   EXPECT_EQ(decoration_.GetImage(), image);
@@ -38,7 +39,8 @@
             LocationBarDecoration::kOmittedWidth);
 
   const NSSize kImageSize = NSMakeSize(20.0, 20.0);
-  scoped_nsobject<NSImage> image([[NSImage alloc] initWithSize:kImageSize]);
+  base::scoped_nsobject<NSImage> image(
+      [[NSImage alloc] initWithSize:kImageSize]);
 
   // Decoration takes up the space of the image.
   decoration_.SetImage(image);
diff --git a/chrome/browser/ui/cocoa/location_bar/keyword_hint_decoration.h b/chrome/browser/ui/cocoa/location_bar/keyword_hint_decoration.h
index 7a0e57e..cd218e8 100644
--- a/chrome/browser/ui/cocoa/location_bar/keyword_hint_decoration.h
+++ b/chrome/browser/ui/cocoa/location_bar/keyword_hint_decoration.h
@@ -9,7 +9,7 @@
 
 #import "chrome/browser/ui/cocoa/location_bar/location_bar_decoration.h"
 
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #include "base/strings/string16.h"
 
 // Draws the keyword hint, "Press [tab] to search <site>".
@@ -32,14 +32,14 @@
   NSImage* GetHintImage();
 
   // Attributes for drawing the hint string, such as font and color.
-  scoped_nsobject<NSDictionary> attributes_;
+  base::scoped_nsobject<NSDictionary> attributes_;
 
   // Cache for the [tab] image.
-  scoped_nsobject<NSImage> hint_image_;
+  base::scoped_nsobject<NSImage> hint_image_;
 
   // The text to display to the left and right of the hint image.
-  scoped_nsobject<NSString> hint_prefix_;
-  scoped_nsobject<NSString> hint_suffix_;
+  base::scoped_nsobject<NSString> hint_prefix_;
+  base::scoped_nsobject<NSString> hint_suffix_;
 
   DISALLOW_COPY_AND_ASSIGN(KeywordHintDecoration);
 };
diff --git a/chrome/browser/ui/cocoa/location_bar/location_bar_decoration.mm b/chrome/browser/ui/cocoa/location_bar/location_bar_decoration.mm
index a425bbb..13ff083 100644
--- a/chrome/browser/ui/cocoa/location_bar/location_bar_decoration.mm
+++ b/chrome/browser/ui/cocoa/location_bar/location_bar_decoration.mm
@@ -5,9 +5,8 @@
 #import "chrome/browser/ui/cocoa/location_bar/location_bar_decoration.h"
 
 #include "base/logging.h"
-#include "base/memory/scoped_nsobject.h"
-#include "chrome/browser/search/search.h"
-#include "ui/base/resource/resource_bundle.h"
+#include "base/mac/scoped_nsobject.h"
+#include "chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h"
 
 const CGFloat LocationBarDecoration::kOmittedWidth = 0.0;
 
@@ -69,17 +68,14 @@
 }
 
 NSFont* LocationBarDecoration::GetFont() const {
-  if (chrome::IsInstantExtendedAPIEnabled())
-    return [NSFont fontWithName:@"Helvetica Neue" size:15];
-  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-  return rb.GetFont(ResourceBundle::BaseFont).GetNativeFont();
+  return OmniboxViewMac::GetFieldFont();
 }
 
 // static
 void LocationBarDecoration::DrawLabel(NSString* label,
                                       NSDictionary* attributes,
                                       const NSRect& frame) {
-  scoped_nsobject<NSAttributedString> str(
+  base::scoped_nsobject<NSAttributedString> str(
       [[NSAttributedString alloc] initWithString:label attributes:attributes]);
   DrawAttributedString(str, frame);
 }
diff --git a/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h b/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h
index 7b07555..3948654 100644
--- a/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h
+++ b/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h
@@ -9,7 +9,6 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/scoped_vector.h"
 #include "base/memory/weak_ptr.h"
diff --git a/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.mm b/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.mm
index 71b11ff..8e871d2 100644
--- a/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.mm
+++ b/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.mm
@@ -94,7 +94,6 @@
       selected_keyword_decoration_(new SelectedKeywordDecoration()),
       ev_bubble_decoration_(
           new EVBubbleDecoration(location_icon_decoration_.get())),
-      plus_decoration_(NULL),
       star_decoration_(new StarDecoration(command_updater)),
       zoom_decoration_(new ZoomDecoration(this)),
       keyword_hint_decoration_(new KeywordHintDecoration()),
diff --git a/chrome/browser/ui/cocoa/location_bar/page_action_decoration.h b/chrome/browser/ui/cocoa/location_bar/page_action_decoration.h
index 99dfba9..74f56cc 100644
--- a/chrome/browser/ui/cocoa/location_bar/page_action_decoration.h
+++ b/chrome/browser/ui/cocoa/location_bar/page_action_decoration.h
@@ -104,10 +104,10 @@
   GURL current_url_;
 
   // The string to show for a tooltip.
-  scoped_nsobject<NSString> tooltip_;
+  base::scoped_nsobject<NSString> tooltip_;
 
   // The context menu for the Page Action.
-  scoped_nsobject<ExtensionActionContextMenu> menu_;
+  base::scoped_nsobject<ExtensionActionContextMenu> menu_;
 
   // This is used for post-install visual feedback. The page_action
   // icon is briefly shown even if it hasn't been enabled by its
diff --git a/chrome/browser/ui/cocoa/location_bar/plus_decoration.h b/chrome/browser/ui/cocoa/location_bar/plus_decoration.h
index e318c70..64bcf70 100644
--- a/chrome/browser/ui/cocoa/location_bar/plus_decoration.h
+++ b/chrome/browser/ui/cocoa/location_bar/plus_decoration.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/ui/cocoa/location_bar/button_decoration.h"
 #include "chrome/browser/ui/toolbar/action_box_button_controller.h"
 
@@ -54,7 +54,7 @@
 
   void SetIcons(int normal_id, int hover_id, int pressed_id);
 
-  scoped_nsobject<ActionBoxMenuBubbleController> menu_controller_;
+  base::scoped_nsobject<ActionBoxMenuBubbleController> menu_controller_;
 
   DISALLOW_COPY_AND_ASSIGN(PlusDecoration);
 };
diff --git a/chrome/browser/ui/cocoa/location_bar/selected_keyword_decoration.h b/chrome/browser/ui/cocoa/location_bar/selected_keyword_decoration.h
index bdd9e6f..000245c 100644
--- a/chrome/browser/ui/cocoa/location_bar/selected_keyword_decoration.h
+++ b/chrome/browser/ui/cocoa/location_bar/selected_keyword_decoration.h
@@ -33,9 +33,9 @@
   FRIEND_TEST_ALL_PREFIXES(SelectedKeywordDecorationTest,
                            UsesPartialKeywordIfNarrow);
 
-  scoped_nsobject<NSImage> search_image_;
-  scoped_nsobject<NSString> full_string_;
-  scoped_nsobject<NSString> partial_string_;
+  base::scoped_nsobject<NSImage> search_image_;
+  base::scoped_nsobject<NSString> full_string_;
+  base::scoped_nsobject<NSString> partial_string_;
 
   DISALLOW_COPY_AND_ASSIGN(SelectedKeywordDecoration);
 };
diff --git a/chrome/browser/ui/cocoa/location_bar/star_decoration.h b/chrome/browser/ui/cocoa/location_bar/star_decoration.h
index 6ec7d0d..691f52e 100644
--- a/chrome/browser/ui/cocoa/location_bar/star_decoration.h
+++ b/chrome/browser/ui/cocoa/location_bar/star_decoration.h
@@ -38,7 +38,7 @@
   CommandUpdater* command_updater_;  // Weak, owned by Browser.
 
   // The string to show for a tooltip.
-  scoped_nsobject<NSString> tooltip_;
+  base::scoped_nsobject<NSString> tooltip_;
 
   // Whether the star icon is lit.
   bool starred_;
diff --git a/chrome/browser/ui/cocoa/location_bar/zoom_decoration.h b/chrome/browser/ui/cocoa/location_bar/zoom_decoration.h
index 7819a18..ffc1994 100644
--- a/chrome/browser/ui/cocoa/location_bar/zoom_decoration.h
+++ b/chrome/browser/ui/cocoa/location_bar/zoom_decoration.h
@@ -50,7 +50,7 @@
   ZoomBubbleController* bubble_;
 
   // The string to show for a tooltip.
-  scoped_nsobject<NSString> tooltip_;
+  base::scoped_nsobject<NSString> tooltip_;
 
   DISALLOW_COPY_AND_ASSIGN(ZoomDecoration);
 };
diff --git a/chrome/browser/ui/cocoa/login_prompt_cocoa.mm b/chrome/browser/ui/cocoa/login_prompt_cocoa.mm
index fba3c01..dc3b678 100644
--- a/chrome/browser/ui/cocoa/login_prompt_cocoa.mm
+++ b/chrome/browser/ui/cocoa/login_prompt_cocoa.mm
@@ -6,7 +6,7 @@
 
 #include "base/mac/bundle_locations.h"
 #include "base/mac/mac_util.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/strings/string16.h"
 #include "base/strings/string_util.h"
 #include "base/strings/sys_string_conversions.h"
@@ -73,7 +73,7 @@
     WebContents* requesting_contents = GetWebContentsForLogin();
     DCHECK(requesting_contents);
 
-    scoped_nsobject<CustomConstrainedWindowSheet> sheet(
+    base::scoped_nsobject<CustomConstrainedWindowSheet> sheet(
         [[CustomConstrainedWindowSheet alloc]
             initWithCustomWindow:[sheet_controller_ window]]);
     constrained_window_.reset(new ConstrainedWindowMac(
@@ -121,7 +121,7 @@
   }
 
   // The Cocoa controller of the GUI.
-  scoped_nsobject<LoginHandlerSheet> sheet_controller_;
+  base::scoped_nsobject<LoginHandlerSheet> sheet_controller_;
 
   scoped_ptr<ConstrainedWindowMac> constrained_window_;
 
diff --git a/chrome/browser/ui/cocoa/menu_button.h b/chrome/browser/ui/cocoa/menu_button.h
index b2de8de..d0ffb58 100644
--- a/chrome/browser/ui/cocoa/menu_button.h
+++ b/chrome/browser/ui/cocoa/menu_button.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/toolbar/toolbar_button.h"
 
 // This a button which displays a user-provided menu "attached" below it upon
@@ -24,10 +24,10 @@
 // value is NO so that custom actions can be hooked up in Interface Builder.
 @interface MenuButton : ToolbarButton {
  @private
-  scoped_nsobject<NSMenu> attachedMenu_;
+  base::scoped_nsobject<NSMenu> attachedMenu_;
   BOOL openMenuOnClick_;
   BOOL openMenuOnRightClick_;
-  scoped_nsobject<NSPopUpButtonCell> popUpCell_;
+  base::scoped_nsobject<NSPopUpButtonCell> popUpCell_;
 }
 
 // The menu to display. Note that it should have no (i.e., a blank) title and
diff --git a/chrome/browser/ui/cocoa/menu_button.mm b/chrome/browser/ui/cocoa/menu_button.mm
index 8cc0812..4147a16 100644
--- a/chrome/browser/ui/cocoa/menu_button.mm
+++ b/chrome/browser/ui/cocoa/menu_button.mm
@@ -5,7 +5,6 @@
 #import "chrome/browser/ui/cocoa/menu_button.h"
 
 #include "base/logging.h"
-#include "base/memory/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/clickhold_button_cell.h"
 #import "chrome/browser/ui/cocoa/nsview_additions.h"
 
diff --git a/chrome/browser/ui/cocoa/menu_button_unittest.mm b/chrome/browser/ui/cocoa/menu_button_unittest.mm
index 543208f..95b00dc 100644
--- a/chrome/browser/ui/cocoa/menu_button_unittest.mm
+++ b/chrome/browser/ui/cocoa/menu_button_unittest.mm
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/clickhold_button_cell.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #import "chrome/browser/ui/cocoa/menu_button.h"
 
 @interface MenuButtonTestDelegate : NSObject<NSMenuDelegate> {
  @private
-  scoped_nsobject<NSMenu> menu_;
+  base::scoped_nsobject<NSMenu> menu_;
   BOOL open_;
   BOOL didOpen_;
 }
@@ -60,10 +60,10 @@
  public:
   MenuButtonTest() {
     NSRect frame = NSMakeRect(0, 0, 50, 30);
-    scoped_nsobject<MenuButton> button(
+    base::scoped_nsobject<MenuButton> button(
         [[MenuButton alloc] initWithFrame:frame]);
     button_ = button.get();
-    scoped_nsobject<ClickHoldButtonCell> cell(
+    base::scoped_nsobject<ClickHoldButtonCell> cell(
         [[ClickHoldButtonCell alloc] initTextCell:@"Testing"]);
     [button_ setCell:cell.get()];
     [[test_window() contentView] addSubview:button_];
@@ -102,7 +102,7 @@
 
 // Test assigning a menu, again mostly to ensure nothing leaks or crashes.
 TEST_F(MenuButtonTest, MenuAssign) {
-  scoped_nsobject<NSMenu> menu(CreateMenu());
+  base::scoped_nsobject<NSMenu> menu(CreateMenu());
   ASSERT_TRUE(menu.get());
 
   [button_ setAttachedMenu:menu];
@@ -110,10 +110,10 @@
 }
 
 TEST_F(MenuButtonTest, OpenOnClick) {
-  scoped_nsobject<NSMenu> menu(CreateMenu());
+  base::scoped_nsobject<NSMenu> menu(CreateMenu());
   ASSERT_TRUE(menu.get());
 
-  scoped_nsobject<MenuButtonTestDelegate> delegate(
+  base::scoped_nsobject<MenuButtonTestDelegate> delegate(
       [[MenuButtonTestDelegate alloc] initWithMenu:menu.get()]);
   ASSERT_TRUE(delegate.get());
 
@@ -132,10 +132,10 @@
 }
 
 TEST_F(MenuButtonTest, OpenOnRightClick) {
-  scoped_nsobject<NSMenu> menu(CreateMenu());
+  base::scoped_nsobject<NSMenu> menu(CreateMenu());
   ASSERT_TRUE(menu.get());
 
-  scoped_nsobject<MenuButtonTestDelegate> delegate(
+  base::scoped_nsobject<MenuButtonTestDelegate> delegate(
       [[MenuButtonTestDelegate alloc] initWithMenu:menu.get()]);
   ASSERT_TRUE(delegate.get());
 
@@ -157,10 +157,10 @@
 }
 
 TEST_F(MenuButtonTest, DontOpenOnRightClickWithoutSetRightClick) {
-  scoped_nsobject<NSMenu> menu(CreateMenu());
+  base::scoped_nsobject<NSMenu> menu(CreateMenu());
   ASSERT_TRUE(menu.get());
 
-  scoped_nsobject<MenuButtonTestDelegate> delegate(
+  base::scoped_nsobject<MenuButtonTestDelegate> delegate(
       [[MenuButtonTestDelegate alloc] initWithMenu:menu.get()]);
   ASSERT_TRUE(delegate.get());
 
diff --git a/chrome/browser/ui/cocoa/notifications/balloon_controller.h b/chrome/browser/ui/cocoa/notifications/balloon_controller.h
index c63caed..7c9c00a 100644
--- a/chrome/browser/ui/cocoa/notifications/balloon_controller.h
+++ b/chrome/browser/ui/cocoa/notifications/balloon_controller.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 
 class Balloon;
@@ -46,7 +46,7 @@
   // The options menu that appears when "options" is pressed.
   IBOutlet HoverImageButton* optionsButton_;
   scoped_ptr<NotificationOptionsMenuModel> menuModel_;
-  scoped_nsobject<MenuController> menuController_;
+  base::scoped_nsobject<MenuController> menuController_;
 
   // The host for the renderer of the HTML contents.
   scoped_ptr<BalloonViewHost> htmlContents_;
diff --git a/chrome/browser/ui/cocoa/notifications/balloon_controller.mm b/chrome/browser/ui/cocoa/notifications/balloon_controller.mm
index 4ee0669..fb481cd 100644
--- a/chrome/browser/ui/cocoa/notifications/balloon_controller.mm
+++ b/chrome/browser/ui/cocoa/notifications/balloon_controller.mm
@@ -6,7 +6,6 @@
 
 #include "base/mac/bundle_locations.h"
 #include "base/mac/mac_util.h"
-#import "base/memory/scoped_nsobject.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/notifications/balloon.h"
 #include "chrome/browser/notifications/desktop_notification_service.h"
diff --git a/chrome/browser/ui/cocoa/notifications/balloon_controller_unittest.mm b/chrome/browser/ui/cocoa/notifications/balloon_controller_unittest.mm
index 854e39a..8f4f659 100644
--- a/chrome/browser/ui/cocoa/notifications/balloon_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/notifications/balloon_controller_unittest.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/memory/scoped_ptr.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/notifications/balloon.h"
 #include "chrome/browser/notifications/balloon_collection.h"
@@ -59,8 +59,7 @@
     ChromeRenderViewHostTestHarness::SetUp();
     CocoaTest::BootstrapCocoa();
     profile()->CreateRequestContext();
-    Browser::CreateParams native_params(profile(),
-                                        chrome::HOST_DESKTOP_TYPE_NATIVE);
+    Browser::CreateParams native_params(profile(), chrome::GetActiveDesktop());
     browser_.reset(
         chrome::CreateBrowserWithTestWindowForParams(&native_params));
     collection_.reset(new MockBalloonCollection());
diff --git a/chrome/browser/ui/cocoa/notifications/balloon_view.mm b/chrome/browser/ui/cocoa/notifications/balloon_view.mm
index eeac6fa..b507eab 100644
--- a/chrome/browser/ui/cocoa/notifications/balloon_view.mm
+++ b/chrome/browser/ui/cocoa/notifications/balloon_view.mm
@@ -7,7 +7,6 @@
 #import <Cocoa/Cocoa.h>
 
 #include "base/basictypes.h"
-#include "base/memory/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/notifications/balloon_controller.h"
 #import "third_party/GTM/AppKit/GTMNSBezierPath+RoundRect.h"
 
diff --git a/chrome/browser/ui/cocoa/notifications/message_center_tray_bridge.h b/chrome/browser/ui/cocoa/notifications/message_center_tray_bridge.h
index 5a5fa79..d78a910 100644
--- a/chrome/browser/ui/cocoa/notifications/message_center_tray_bridge.h
+++ b/chrome/browser/ui/cocoa/notifications/message_center_tray_bridge.h
@@ -8,7 +8,7 @@
 #import <AppKit/AppKit.h>
 
 #include "base/basictypes.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "ui/message_center/message_center_tray_delegate.h"
@@ -39,6 +39,7 @@
   virtual void UpdatePopups() OVERRIDE;
   virtual bool ShowMessageCenter() OVERRIDE;
   virtual void HideMessageCenter() OVERRIDE;
+  virtual bool ShowNotifierSettings() OVERRIDE;
 
   message_center::MessageCenter* message_center() { return message_center_; }
 
@@ -58,13 +59,13 @@
   scoped_ptr<message_center::MessageCenterTray> tray_;
 
   // Obj-C window controller for the notification tray.
-  scoped_nsobject<MCTrayController> tray_controller_;
+  base::scoped_nsobject<MCTrayController> tray_controller_;
 
   // View that is displayed on the system menu bar item.
-  scoped_nsobject<MCStatusItemView> status_item_view_;
+  base::scoped_nsobject<MCStatusItemView> status_item_view_;
 
   // Obj-C controller for the on-screen popup notifications.
-  scoped_nsobject<MCPopupCollection> popup_collection_;
+  base::scoped_nsobject<MCPopupCollection> popup_collection_;
 
   // Weak pointer factory to posts tasks to self.
   base::WeakPtrFactory<MessageCenterTrayBridge> weak_ptr_factory_;
diff --git a/chrome/browser/ui/cocoa/notifications/message_center_tray_bridge.mm b/chrome/browser/ui/cocoa/notifications/message_center_tray_bridge.mm
index aced76a..adca08e 100644
--- a/chrome/browser/ui/cocoa/notifications/message_center_tray_bridge.mm
+++ b/chrome/browser/ui/cocoa/notifications/message_center_tray_bridge.mm
@@ -83,6 +83,12 @@
   tray_controller_.autorelease();
 }
 
+bool MessageCenterTrayBridge::ShowNotifierSettings() {
+  // This method needs to be implemented when the context menu of each
+  // notification is ready and it contains 'settings' menu item.
+  return false;
+}
+
 void MessageCenterTrayBridge::UpdateStatusItem() {
   // Only show the status item if there are notifications.
   if (message_center_->NotificationCount() == 0) {
diff --git a/chrome/browser/ui/cocoa/notifications/message_center_tray_bridge_unittest.mm b/chrome/browser/ui/cocoa/notifications/message_center_tray_bridge_unittest.mm
index 7fadb8a..24b6cb7 100644
--- a/chrome/browser/ui/cocoa/notifications/message_center_tray_bridge_unittest.mm
+++ b/chrome/browser/ui/cocoa/notifications/message_center_tray_bridge_unittest.mm
@@ -4,14 +4,14 @@
 
 #import "chrome/browser/ui/cocoa/notifications/message_center_tray_bridge.h"
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/memory/scoped_ptr.h"
 #include "base/message_loop.h"
 #include "base/run_loop.h"
-#include "base/utf_string_conversions.h"
+#include "base/strings/utf_string_conversions.h"
+#import "ui/base/test/ui_cocoa_test_helper.h"
 #import "ui/message_center/cocoa/status_item_view.h"
 #include "ui/message_center/message_center.h"
 #include "ui/message_center/notification.h"
-#import "ui/base/test/ui_cocoa_test_helper.h"
 
 class MessageCenterTrayBridgeTest : public ui::CocoaTest {
  public:
diff --git a/chrome/browser/ui/cocoa/nsmenuitem_additions_unittest.mm b/chrome/browser/ui/cocoa/nsmenuitem_additions_unittest.mm
index 90185bb..33ed98c 100644
--- a/chrome/browser/ui/cocoa/nsmenuitem_additions_unittest.mm
+++ b/chrome/browser/ui/cocoa/nsmenuitem_additions_unittest.mm
@@ -8,7 +8,7 @@
 
 #include <ostream>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/strings/sys_string_conversions.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -56,7 +56,7 @@
   // key equivalent, even though the original event would) and isn't a good
   // oracle function.
   if (compareCocoa) {
-    scoped_nsobject<NSMenu> menu([[NSMenu alloc] initWithTitle:@"Menu!"]);
+    base::scoped_nsobject<NSMenu> menu([[NSMenu alloc] initWithTitle:@"Menu!"]);
     [menu setAutoenablesItems:NO];
     EXPECT_FALSE([menu performKeyEquivalent:key]);
     [menu addItem:item];
diff --git a/chrome/browser/ui/cocoa/nsview_additions.h b/chrome/browser/ui/cocoa/nsview_additions.h
index ac52646..0ef8854 100644
--- a/chrome/browser/ui/cocoa/nsview_additions.h
+++ b/chrome/browser/ui/cocoa/nsview_additions.h
@@ -29,6 +29,9 @@
 // Return best color for keyboard focus ring.
 - (NSColor*)cr_keyboardFocusIndicatorColor;
 
+// Set needsDisplay for this view and all descendants.
+- (void)cr_recursivelySetNeedsDisplay:(BOOL)flag;
+
 @end
 
 #endif  // CHROME_BROWSER_UI_COCOA_NSVIEW_ADDITIONS_H_
diff --git a/chrome/browser/ui/cocoa/nsview_additions.mm b/chrome/browser/ui/cocoa/nsview_additions.mm
index 507f77b..00f36ab 100644
--- a/chrome/browser/ui/cocoa/nsview_additions.mm
+++ b/chrome/browser/ui/cocoa/nsview_additions.mm
@@ -67,4 +67,10 @@
       colorWithAlphaComponent:0.5 / [self cr_lineWidth]];
 }
 
+- (void)cr_recursivelySetNeedsDisplay:(BOOL)flag {
+  [self setNeedsDisplay:YES];
+  for (NSView* child in [self subviews])
+    [child cr_recursivelySetNeedsDisplay:flag];
+}
+
 @end
diff --git a/chrome/browser/ui/cocoa/nsview_additions_unittest.mm b/chrome/browser/ui/cocoa/nsview_additions_unittest.mm
index ffb7e0f..a9b7468 100644
--- a/chrome/browser/ui/cocoa/nsview_additions_unittest.mm
+++ b/chrome/browser/ui/cocoa/nsview_additions_unittest.mm
@@ -4,7 +4,7 @@
 
 #import "chrome/browser/ui/cocoa/nsview_additions.h"
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #import "testing/gtest_mac.h"
@@ -38,9 +38,12 @@
 @end
 
 TEST_F(NSViewChromeAdditionsTest, BelowAboveView) {
-  scoped_nsobject<NSView> parent([[NSView alloc] initWithFrame:NSZeroRect]);
-  scoped_nsobject<NSView> child1([[NSView alloc] initWithFrame:NSZeroRect]);
-  scoped_nsobject<NSView> child2([[NSView alloc] initWithFrame:NSZeroRect]);
+  base::scoped_nsobject<NSView> parent(
+      [[NSView alloc] initWithFrame:NSZeroRect]);
+  base::scoped_nsobject<NSView> child1(
+      [[NSView alloc] initWithFrame:NSZeroRect]);
+  base::scoped_nsobject<NSView> child2(
+      [[NSView alloc] initWithFrame:NSZeroRect]);
 
   [parent addSubview:child1];
   [parent addSubview:child2];
@@ -60,9 +63,12 @@
 }
 
 TEST_F(NSViewChromeAdditionsTest, EnsurePosition) {
-  scoped_nsobject<NSView> parent([[NSView alloc] initWithFrame:NSZeroRect]);
-  scoped_nsobject<NSView> child1([[NSView alloc] initWithFrame:NSZeroRect]);
-  scoped_nsobject<NSView> child2([[NSView alloc] initWithFrame:NSZeroRect]);
+  base::scoped_nsobject<NSView> parent(
+      [[NSView alloc] initWithFrame:NSZeroRect]);
+  base::scoped_nsobject<NSView> child1(
+      [[NSView alloc] initWithFrame:NSZeroRect]);
+  base::scoped_nsobject<NSView> child2(
+      [[NSView alloc] initWithFrame:NSZeroRect]);
 
   [parent addSubview:child1];
   [parent cr_ensureSubview:child2
@@ -81,10 +87,12 @@
 
 // Verify that no view is removed or added when no change is needed.
 TEST_F(NSViewChromeAdditionsTest, EnsurePositionNoChange) {
-  scoped_nsobject<ParentView> parent(
+  base::scoped_nsobject<ParentView> parent(
       [[ParentView alloc] initWithFrame:NSZeroRect]);
-  scoped_nsobject<NSView> child1([[NSView alloc] initWithFrame:NSZeroRect]);
-  scoped_nsobject<NSView> child2([[NSView alloc] initWithFrame:NSZeroRect]);
+  base::scoped_nsobject<NSView> child1(
+      [[NSView alloc] initWithFrame:NSZeroRect]);
+  base::scoped_nsobject<NSView> child2(
+      [[NSView alloc] initWithFrame:NSZeroRect]);
   [parent addSubview:child1];
   [parent addSubview:child2];
 
diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h
new file mode 100644
index 0000000..829441b
--- /dev/null
+++ b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h
@@ -0,0 +1,18 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_COCOA_OMNIBOX_OMNIBOX_POPUP_CELL_H_
+#define CHROME_BROWSER_UI_COCOA_OMNIBOX_OMNIBOX_POPUP_CELL_H_
+
+#import <Cocoa/Cocoa.h>
+
+// OmniboxPopupCell overrides how backgrounds are displayed to
+// handle hover versus selected.  So long as we're in there, it also
+// provides some default initialization.
+@interface OmniboxPopupCell : NSButtonCell {
+}
+
+@end
+
+#endif  // CHROME_BROWSER_UI_COCOA_OMNIBOX_OMNIBOX_POPUP_CELL_H_
diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm
new file mode 100644
index 0000000..db647f8
--- /dev/null
+++ b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm
@@ -0,0 +1,86 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h"
+
+#include <cmath>
+
+namespace {
+
+// How far to offset image column from the left.
+const CGFloat kImageXOffset = 5.0;
+
+// How far to offset the text column from the left.
+const CGFloat kTextXOffset = 28.0;
+
+// Rounding radius of selection and hover background on popup items.
+const CGFloat kCellRoundingRadius = 2.0;
+
+NSColor* SelectedBackgroundColor() {
+  return [NSColor selectedControlColor];
+}
+NSColor* HoveredBackgroundColor() {
+  return [NSColor controlHighlightColor];
+}
+
+}  // namespace
+
+@implementation OmniboxPopupCell
+
+- (id)init {
+  self = [super init];
+  if (self) {
+    [self setImagePosition:NSImageLeft];
+    [self setBordered:NO];
+    [self setButtonType:NSRadioButton];
+
+    // Without this highlighting messes up white areas of images.
+    [self setHighlightsBy:NSNoCellMask];
+  }
+  return self;
+}
+
+// The default NSButtonCell drawing leaves the image flush left and
+// the title next to the image.  This spaces things out to line up
+// with the star button and autocomplete field.
+- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView {
+  if ([self state] == NSOnState || [self isHighlighted]) {
+    if ([self state] == NSOnState)
+      [SelectedBackgroundColor() set];
+    else
+      [HoveredBackgroundColor() set];
+    NSBezierPath* path =
+        [NSBezierPath bezierPathWithRoundedRect:cellFrame
+                                        xRadius:kCellRoundingRadius
+                                        yRadius:kCellRoundingRadius];
+    [path fill];
+  }
+
+  // Put the image centered vertically but in a fixed column.
+  NSImage* image = [self image];
+  if (image) {
+    NSRect imageRect = cellFrame;
+    imageRect.size = [image size];
+    imageRect.origin.y +=
+        std::floor((NSHeight(cellFrame) - NSHeight(imageRect)) / 2.0);
+    imageRect.origin.x += kImageXOffset;
+    [image drawInRect:imageRect
+             fromRect:NSZeroRect  // Entire image
+            operation:NSCompositeSourceOver
+             fraction:1.0
+       respectFlipped:YES
+                hints:nil];
+  }
+
+  // Adjust the title position to be lined up under the field's text.
+  NSAttributedString* title = [self attributedTitle];
+  if (title && [title length]) {
+    NSRect titleRect = cellFrame;
+    titleRect.size.width -= kTextXOffset;
+    titleRect.origin.x += kTextXOffset;
+    [self drawTitle:title withFrame:titleRect inView:controlView];
+  }
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm
new file mode 100644
index 0000000..9b08280
--- /dev/null
+++ b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm
@@ -0,0 +1,47 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h"
+
+#include "base/mac/scoped_nsobject.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+
+namespace {
+
+class OmniboxPopupCellTest : public CocoaTest {
+ public:
+  OmniboxPopupCellTest() {
+  }
+
+  virtual void SetUp() OVERRIDE {
+    CocoaTest::SetUp();
+    cell_.reset([[OmniboxPopupCell alloc] initTextCell:@""]);
+    button_.reset([[NSButton alloc] initWithFrame:NSMakeRect(0, 0, 200, 20)]);
+    [button_ setCell:cell_];
+    [[test_window() contentView] addSubview:button_];
+  };
+
+ protected:
+  base::scoped_nsobject<OmniboxPopupCell> cell_;
+  base::scoped_nsobject<NSButton> button_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(OmniboxPopupCellTest);
+};
+
+TEST_VIEW(OmniboxPopupCellTest, button_);
+
+TEST_F(OmniboxPopupCellTest, Image) {
+  [cell_ setImage:[NSImage imageNamed:NSImageNameInfo]];
+  [button_ display];
+}
+
+TEST_F(OmniboxPopupCellTest, Title) {
+  base::scoped_nsobject<NSAttributedString> text([[NSAttributedString alloc]
+      initWithString:@"The quick brown fox jumps over the lazy dog."]);
+  [cell_ setAttributedTitle:text];
+  [button_ display];
+}
+
+}  // namespace
diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h
new file mode 100644
index 0000000..2ce6167
--- /dev/null
+++ b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h
@@ -0,0 +1,46 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_COCOA_OMNIBOX_OMNIBOX_POPUP_MATRIX_H_
+#define CHROME_BROWSER_UI_COCOA_OMNIBOX_OMNIBOX_POPUP_MATRIX_H_
+
+#import <Cocoa/Cocoa.h>
+
+#import "ui/base/cocoa/tracking_area.h"
+#include "ui/base/window_open_disposition.h"
+
+@class OmniboxPopupMatrix;
+
+class OmniboxPopupMatrixDelegate {
+ public:
+  // Called when the selection in the matrix changes.
+  virtual void OnMatrixRowSelected(OmniboxPopupMatrix* matrix, size_t row) = 0;
+
+  // Called when the user clicks on a row.
+  virtual void OnMatrixRowClicked(OmniboxPopupMatrix* matrix, size_t row) = 0;
+
+  // Called when the user middle clicks on a row.
+  virtual void OnMatrixRowMiddleClicked(OmniboxPopupMatrix* matrix,
+                                        size_t row) = 0;
+};
+
+// Sets up a tracking area to implement hover by highlighting the cell the mouse
+// is over.
+@interface OmniboxPopupMatrix : NSMatrix {
+  OmniboxPopupMatrixDelegate* delegate_;  // weak
+  ui::ScopedCrTrackingArea trackingArea_;
+}
+
+// Create a zero-size matrix.
+- (id)initWithDelegate:(OmniboxPopupMatrixDelegate*)delegate;
+
+// Sets the delegate.
+- (void)setDelegate:(OmniboxPopupMatrixDelegate*)delegate;
+
+// Return the currently highlighted row.  Returns -1 if no row is highlighted.
+- (NSInteger)highlightedRow;
+
+@end
+
+#endif  // CHROME_BROWSER_UI_COCOA_OMNIBOX_OMNIBOX_POPUP_MATRIX_H_
diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm
new file mode 100644
index 0000000..6bddf63
--- /dev/null
+++ b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm
@@ -0,0 +1,192 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h"
+
+#include "base/logging.h"
+#import "chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h"
+
+namespace {
+
+// NSEvent -buttonNumber for middle mouse button.
+const NSInteger kMiddleButtonNumber = 2;
+
+}  // namespace
+
+@interface OmniboxPopupMatrix()
+- (void)resetTrackingArea;
+- (void)highlightRowAt:(NSInteger)rowIndex;
+- (void)highlightRowUnder:(NSEvent*)theEvent;
+- (BOOL)selectCellForEvent:(NSEvent*)theEvent;
+@end
+
+@implementation OmniboxPopupMatrix
+
+- (id)initWithDelegate:(OmniboxPopupMatrixDelegate*)delegate {
+  if ((self = [super initWithFrame:NSZeroRect])) {
+    delegate_ = delegate;
+    [self setCellClass:[OmniboxPopupCell class]];
+
+    // Cells pack with no spacing.
+    [self setIntercellSpacing:NSMakeSize(0.0, 0.0)];
+
+    [self setDrawsBackground:YES];
+    [self setBackgroundColor:[NSColor controlBackgroundColor]];
+    [self renewRows:0 columns:1];
+    [self setAllowsEmptySelection:YES];
+    [self setMode:NSRadioModeMatrix];
+    [self deselectAllCells];
+
+    [self resetTrackingArea];
+  }
+  return self;
+}
+
+- (void)setDelegate:(OmniboxPopupMatrixDelegate*)delegate {
+  delegate_ = delegate;
+}
+
+- (NSInteger)highlightedRow {
+  NSArray* cells = [self cells];
+  const NSUInteger count = [cells count];
+  for(NSUInteger i = 0; i < count; ++i) {
+    if ([[cells objectAtIndex:i] isHighlighted]) {
+      return i;
+    }
+  }
+  return -1;
+}
+
+- (void)updateTrackingAreas {
+  [self resetTrackingArea];
+  [super updateTrackingAreas];
+}
+
+// Callbacks from tracking area.
+- (void)mouseEntered:(NSEvent*)theEvent {
+  [self highlightRowUnder:theEvent];
+}
+
+- (void)mouseMoved:(NSEvent*)theEvent {
+  [self highlightRowUnder:theEvent];
+}
+
+- (void)mouseExited:(NSEvent*)theEvent {
+  [self highlightRowAt:-1];
+}
+
+// The tracking area events aren't forwarded during a drag, so handle
+// highlighting manually for middle-click and middle-drag.
+- (void)otherMouseDown:(NSEvent*)theEvent {
+  if ([theEvent buttonNumber] == kMiddleButtonNumber) {
+    [self highlightRowUnder:theEvent];
+  }
+  [super otherMouseDown:theEvent];
+}
+
+- (void)otherMouseDragged:(NSEvent*)theEvent {
+  if ([theEvent buttonNumber] == kMiddleButtonNumber) {
+    [self highlightRowUnder:theEvent];
+  }
+  [super otherMouseDragged:theEvent];
+}
+
+- (void)otherMouseUp:(NSEvent*)theEvent {
+  // Only intercept middle button.
+  if ([theEvent buttonNumber] != kMiddleButtonNumber) {
+    [super otherMouseUp:theEvent];
+    return;
+  }
+
+  // -otherMouseDragged: should always have been called at this location, but
+  // make sure the user is getting the right feedback.
+  [self highlightRowUnder:theEvent];
+
+  const NSInteger highlightedRow = [self highlightedRow];
+  if (highlightedRow != -1) {
+    DCHECK(delegate_);
+    delegate_->OnMatrixRowMiddleClicked(self, highlightedRow);
+  }
+}
+
+// Track the mouse until released, keeping the cell under the mouse selected.
+// If the mouse wanders off-view, revert to the originally-selected cell. If
+// the mouse is released over a cell, call the delegate to open the row's URL.
+- (void)mouseDown:(NSEvent*)theEvent {
+  NSCell* selectedCell = [self selectedCell];
+
+  // Clear any existing highlight.
+  [self highlightRowAt:-1];
+
+  do {
+    if (![self selectCellForEvent:theEvent]) {
+      [self selectCell:selectedCell];
+    }
+
+    const NSUInteger mask = NSLeftMouseUpMask | NSLeftMouseDraggedMask;
+    theEvent = [[self window] nextEventMatchingMask:mask];
+  } while ([theEvent type] == NSLeftMouseDragged);
+
+  // Do not message the delegate if released outside view.
+  if (![self selectCellForEvent:theEvent]) {
+    [self selectCell:selectedCell];
+  } else {
+    const NSInteger selectedRow = [self selectedRow];
+    DCHECK_GE(selectedRow, 0);
+
+    DCHECK(delegate_);
+    delegate_->OnMatrixRowClicked(self, selectedRow);
+  }
+}
+
+- (void)resetTrackingArea {
+  if (trackingArea_.get())
+    [self removeTrackingArea:trackingArea_.get()];
+
+  trackingArea_.reset([[CrTrackingArea alloc]
+      initWithRect:[self frame]
+           options:NSTrackingMouseEnteredAndExited |
+                   NSTrackingMouseMoved |
+                   NSTrackingActiveInActiveApp |
+                   NSTrackingInVisibleRect
+             owner:self
+          userInfo:nil]);
+  [self addTrackingArea:trackingArea_.get()];
+}
+
+- (void)highlightRowAt:(NSInteger)rowIndex {
+  // highlightCell will be nil if rowIndex is out of range, so no cell will be
+  // highlighted.
+  NSCell* highlightCell = [self cellAtRow:rowIndex column:0];
+
+  for (NSCell* cell in [self cells]) {
+    [cell setHighlighted:(cell == highlightCell)];
+  }
+}
+
+- (void)highlightRowUnder:(NSEvent*)theEvent {
+  NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil];
+  NSInteger row, column;
+  if ([self getRow:&row column:&column forPoint:point]) {
+    [self highlightRowAt:row];
+  } else {
+    [self highlightRowAt:-1];
+  }
+}
+
+// Select cell under |theEvent|, returning YES if a selection is made.
+- (BOOL)selectCellForEvent:(NSEvent*)theEvent {
+  NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil];
+
+  NSInteger row, column;
+  if ([self getRow:&row column:&column forPoint:point]) {
+    DCHECK_EQ(column, 0);
+    DCHECK(delegate_);
+    delegate_->OnMatrixRowSelected(self, row);
+    return YES;
+  }
+  return NO;
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm
new file mode 100644
index 0000000..54d1e47
--- /dev/null
+++ b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm
@@ -0,0 +1,87 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h"
+
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#import "ui/base/test/cocoa_test_event_utils.h"
+
+namespace {
+
+NSEvent* MouseEventInRow(NSMatrix* matrix, NSEventType type, NSInteger row) {
+  NSRect cell_rect = [matrix cellFrameAtRow:row column:0];
+  NSPoint point_in_view = NSMakePoint(NSMidX(cell_rect), NSMidY(cell_rect));
+  NSPoint point_in_window = [matrix convertPoint:point_in_view toView:nil];
+  return cocoa_test_event_utils::MouseEventAtPoint(
+      point_in_window, type, 0);
+}
+
+class OmniboxPopupMatrixTest : public CocoaTest,
+                               public OmniboxPopupMatrixDelegate {
+ public:
+  OmniboxPopupMatrixTest()
+      : selected_row_(0),
+        clicked_row_(0),
+        middle_clicked_row_(0) {
+  }
+
+  virtual void SetUp() OVERRIDE {
+    CocoaTest::SetUp();
+    matrix_.reset([[OmniboxPopupMatrix alloc] initWithDelegate:this]);
+    [[test_window() contentView] addSubview:matrix_];
+  };
+
+  virtual void OnMatrixRowSelected(OmniboxPopupMatrix* matrix,
+                                   size_t row) OVERRIDE {
+    selected_row_ = row;
+    [matrix_ selectCellAtRow:row column:0];
+  }
+
+  virtual void OnMatrixRowClicked(OmniboxPopupMatrix* matrix,
+                                size_t row) OVERRIDE {
+    clicked_row_ = row;
+  }
+
+  virtual void OnMatrixRowMiddleClicked(OmniboxPopupMatrix* matrix,
+                                        size_t row) OVERRIDE {
+    middle_clicked_row_ = row;
+  }
+
+ protected:
+  base::scoped_nsobject<OmniboxPopupMatrix> matrix_;
+  size_t selected_row_;
+  size_t clicked_row_;
+  size_t middle_clicked_row_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(OmniboxPopupMatrixTest);
+};
+
+TEST_VIEW(OmniboxPopupMatrixTest, matrix_);
+
+TEST_F(OmniboxPopupMatrixTest, HighlightedRow) {
+  [matrix_ renewRows:3 columns:1];
+  EXPECT_EQ(-1, [matrix_ highlightedRow]);
+
+  [matrix_ mouseEntered:MouseEventInRow(matrix_, NSMouseMoved, 0)];
+  EXPECT_EQ(0, [matrix_ highlightedRow]);
+  [matrix_ mouseEntered:MouseEventInRow(matrix_, NSMouseMoved, 2)];
+  EXPECT_EQ(2, [matrix_ highlightedRow]);
+
+  [matrix_ mouseExited:MouseEventInRow(matrix_, NSMouseMoved, 2)];
+  EXPECT_EQ(-1, [matrix_ highlightedRow]);
+}
+
+TEST_F(OmniboxPopupMatrixTest, SelectedRow) {
+  [matrix_ renewRows:3 columns:1];
+
+  [NSApp postEvent:MouseEventInRow(matrix_, NSLeftMouseUp, 2) atStart:YES];
+  [matrix_ mouseDown:MouseEventInRow(matrix_, NSLeftMouseDown, 2)];
+
+  EXPECT_EQ(2u, selected_row_);
+  EXPECT_EQ(2u, clicked_row_);
+  EXPECT_EQ(0u, middle_clicked_row_);
+}
+
+}  // namespace
diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_separator_view.h b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_separator_view.h
new file mode 100644
index 0000000..ae2355a
--- /dev/null
+++ b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_separator_view.h
@@ -0,0 +1,28 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_COCOA_OMNIBOX_OMNIBOX_POPUP_SEPARATOR_VIEW_H_
+#define CHROME_BROWSER_UI_COCOA_OMNIBOX_OMNIBOX_POPUP_SEPARATOR_VIEW_H_
+
+#import <Cocoa/Cocoa.h>
+
+#include "chrome/browser/ui/cocoa/background_gradient_view.h"
+
+// A view used to draw a separator above omnibox popup.
+@interface OmniboxPopupTopSeparatorView : BackgroundGradientView {
+}
+
++ (CGFloat)preferredHeight;
+
+@end
+
+// A view used to draw a drop shadow beneath the omnibox popup.
+@interface OmniboxPopupBottomSeparatorView : NSView {
+}
+
++ (CGFloat)preferredHeight;
+
+@end
+
+#endif  // CHROME_BROWSER_UI_COCOA_OMNIBOX_OMNIBOX_POPUP_SEPARATOR_VIEW_H_
diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_separator_view.mm b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_separator_view.mm
new file mode 100644
index 0000000..1e43cea
--- /dev/null
+++ b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_separator_view.mm
@@ -0,0 +1,48 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/ui/cocoa/omnibox/omnibox_popup_separator_view.h"
+
+#import "chrome/browser/ui/cocoa/nsview_additions.h"
+#include "grit/theme_resources.h"
+#include "ui/base/resource/resource_bundle.h"
+
+@implementation OmniboxPopupTopSeparatorView
+
++ (CGFloat)preferredHeight {
+  return 1;
+}
+
+- (void)drawRect:(NSRect)rect {
+  NSRect separatorRect = [self bounds];
+  separatorRect.size.height = [self cr_lineWidth];
+  [[self strokeColor] set];
+  NSRectFillUsingOperation(separatorRect, NSCompositeSourceOver);
+}
+
+@end
+
+@implementation OmniboxPopupBottomSeparatorView
+
++ (CGFloat)preferredHeight {
+  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+  NSImage* shadowImage =
+      rb.GetNativeImageNamed(IDR_OVERLAY_DROP_SHADOW).ToNSImage();
+  return [shadowImage size].height;
+}
+
+- (void)drawRect:(NSRect)rect {
+  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+  NSRect bounds = [self bounds];
+
+  // Draw the shadow.
+  NSImage* shadowImage =
+      rb.GetNativeImageNamed(IDR_OVERLAY_DROP_SHADOW).ToNSImage();
+  [shadowImage drawInRect:bounds
+                 fromRect:NSZeroRect
+                operation:NSCompositeSourceOver
+                 fraction:1.0];
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_separator_view_unittest.mm b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_separator_view_unittest.mm
new file mode 100644
index 0000000..85149a3
--- /dev/null
+++ b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_separator_view_unittest.mm
@@ -0,0 +1,52 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/ui/cocoa/omnibox/omnibox_popup_separator_view.h"
+
+#include "base/mac/scoped_nsobject.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+
+class OmniboxPopupBottomSeparatorViewTest : public CocoaTest {
+ public:
+  OmniboxPopupBottomSeparatorViewTest() {
+    NSView* contentView = [test_window() contentView];
+    bottom_view_.reset([[OmniboxPopupBottomSeparatorView alloc]
+        initWithFrame:[contentView bounds]]);
+    [contentView addSubview:bottom_view_];
+  }
+
+ protected:
+  base::scoped_nsobject<OmniboxPopupBottomSeparatorView> bottom_view_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(OmniboxPopupBottomSeparatorViewTest);
+};
+
+TEST_VIEW(OmniboxPopupBottomSeparatorViewTest, bottom_view_);
+
+TEST_F(OmniboxPopupBottomSeparatorViewTest, PreferredHeight) {
+  EXPECT_LT(0, [OmniboxPopupBottomSeparatorView preferredHeight]);
+}
+
+class OmniboxPopupTopSeparatorViewTest : public CocoaTest {
+ public:
+  OmniboxPopupTopSeparatorViewTest() {
+    NSView* contentView = [test_window() contentView];
+    top_view_.reset([[OmniboxPopupTopSeparatorView alloc]
+        initWithFrame:[contentView bounds]]);
+    [contentView addSubview:top_view_];
+  }
+
+ protected:
+  base::scoped_nsobject<OmniboxPopupTopSeparatorView> top_view_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(OmniboxPopupTopSeparatorViewTest);
+};
+
+TEST_VIEW(OmniboxPopupTopSeparatorViewTest, top_view_);
+
+TEST_F(OmniboxPopupTopSeparatorViewTest, PreferredHeight) {
+  EXPECT_LT(0, [OmniboxPopupTopSeparatorView preferredHeight]);
+}
diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.h b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.h
index 629d572..da3b545 100644
--- a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.h
+++ b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.h
@@ -8,29 +8,23 @@
 #import <Cocoa/Cocoa.h>
 
 #include "base/basictypes.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #include "chrome/browser/autocomplete/autocomplete_match.h"
+#import "chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h"
 #include "chrome/browser/ui/omnibox/omnibox_popup_view.h"
 #include "ui/gfx/font.h"
 
-@class AutocompleteMatrix;
+class AutocompleteResult;
 class OmniboxEditModel;
 class OmniboxPopupModel;
 class OmniboxView;
 
 // Implements OmniboxPopupView using a raw NSWindow containing an
 // NSTableView.
-//
-// TODO(rohitrao): This class is set up in a way that makes testing hard.
-// Refactor and write unittests.  http://crbug.com/9977
-
-class OmniboxPopupViewMac : public OmniboxPopupView {
+class OmniboxPopupViewMac : public OmniboxPopupView,
+                            public OmniboxPopupMatrixDelegate {
  public:
-  static OmniboxPopupView* Create(OmniboxView* omnibox_view,
-                                  OmniboxEditModel* edit_model,
-                                  NSTextField* field);
-
   OmniboxPopupViewMac(OmniboxView* omnibox_view,
                       OmniboxEditModel* edit_model,
                       NSTextField* field);
@@ -38,71 +32,56 @@
 
   // Overridden from OmniboxPopupView:
   virtual bool IsOpen() const OVERRIDE;
-  virtual void InvalidateLine(size_t line) OVERRIDE {
-    // TODO(shess): Verify that there is no need to implement this.
-    // This is currently used in two places in the model:
-    //
-    // When setting the selected line, the selected line is
-    // invalidated, then the selected line is changed, then the new
-    // selected line is invalidated, then PaintUpdatesNow() is called.
-    // For us PaintUpdatesNow() should be sufficient.
-    //
-    // Same thing happens when changing the hovered line, except with
-    // no call to PaintUpdatesNow().  Since this code does not
-    // currently support special display of the hovered line, there's
-    // nothing to do here.
-    //
-    // deanm indicates that this is an anti-flicker optimization,
-    // which we probably cannot utilize (and may not need) so long as
-    // we're using NSTableView to implement the popup contents.  We
-    // may need to move away from NSTableView to implement hover,
-    // though.
-  }
+  virtual void InvalidateLine(size_t line) OVERRIDE {}
   virtual void UpdatePopupAppearance() OVERRIDE;
-
   virtual gfx::Rect GetTargetBounds() OVERRIDE;
-
-  // Set |line| to be selected.
-  void SetSelectedLine(size_t line);
-
   // This is only called by model in SetSelectedLine() after updating
   // everything.  Popup should already be visible.
   virtual void PaintUpdatesNow() OVERRIDE;
-
   virtual void OnDragCanceled() OVERRIDE {}
 
-  // Opens the URL corresponding to the given |row|.  If |force_background| is
-  // true, forces the URL to open in a background tab.  Otherwise, determines
-  // the proper window open disposition from the modifier flags on |[NSApp
-  // currentEvent]|.
-  void OpenURLForRow(int row, bool force_background);
+  // Overridden from OmniboxPopupMatrixDelegate:
+  virtual void OnMatrixRowSelected(OmniboxPopupMatrix* matrix,
+                                   size_t row) OVERRIDE;
+  virtual void OnMatrixRowClicked(OmniboxPopupMatrix* matrix,
+                                  size_t row) OVERRIDE;
+  virtual void OnMatrixRowMiddleClicked(OmniboxPopupMatrix* matrix,
+                                        size_t row) OVERRIDE;
+
+  OmniboxPopupMatrix* matrix() { return matrix_; }
 
   // Return the text to show for the match, based on the match's
   // contents and description.  Result will be in |font|, with the
   // boldfaced version used for matches.
   static NSAttributedString* MatchText(const AutocompleteMatch& match,
                                        gfx::Font& font,
-                                       float cellWidth);
+                                       float cell_width);
 
-  // Helper for MatchText() to allow sharing code between the contents
-  // and description cases.  Returns NSMutableAttributedString as a
-  // convenience for MatchText().
+  // Applies the given font and colors to the match string based on
+  // classifications.
   static NSMutableAttributedString* DecorateMatchedString(
-      const string16 &matchString,
-      const AutocompleteMatch::ACMatchClassifications &classifications,
-      NSColor* textColor, NSColor* dimTextColor, gfx::Font& font);
+      const string16& match_string,
+      const AutocompleteMatch::ACMatchClassifications& classifications,
+      NSColor* text_color,
+      NSColor* dim_text_color,
+      gfx::Font& font);
 
   // Helper for MatchText() to elide a marked-up string using
-  // gfx::ElideText() as a model.  Modifies |aString| in place.
+  // gfx::ElideText() as a model.  Modifies |a_string| in place.
   // TODO(shess): Consider breaking AutocompleteButtonCell out of this
   // code, and modifying it to have something like -setMatch:, so that
   // these convolutions to expose internals for testing can be
   // cleaner.
   static NSMutableAttributedString* ElideString(
-      NSMutableAttributedString* aString,
-      const string16 originalString,
+      NSMutableAttributedString* a_string,
+      const string16& original_string,
       const gfx::Font& font,
-      const float cellWidth);
+      const float cell_width);
+
+ protected:
+  // Gets the autocomplete results. This is virtual so that it can be overriden
+  // by tests.
+  virtual const AutocompleteResult& GetResult() const;
 
  private:
   // Create the popup_ instance if needed.
@@ -119,17 +98,21 @@
   // Returns the NSImage that should be used as an icon for the given match.
   NSImage* ImageForMatch(const AutocompleteMatch& match);
 
-  // TODO(shess): |omnibox_view_| should already be accessible via
-  // |field_|, or perhaps via |model_|.  Consider refactoring.
+  // Opens the URL at the given row.
+  void OpenURLForRow(size_t row, WindowOpenDisposition disposition);
+
   OmniboxView* omnibox_view_;
   scoped_ptr<OmniboxPopupModel> model_;
   NSTextField* field_;  // owned by tab controller
 
   // Child window containing a matrix which implements the popup.
-  scoped_nsobject<NSWindow> popup_;
-  NSRect targetPopupFrame_;
+  base::scoped_nsobject<NSWindow> popup_;
+  NSRect target_popup_frame_;
 
-  scoped_nsobject<AutocompleteMatrix> autocomplete_matrix_;
+  base::scoped_nsobject<OmniboxPopupMatrix> matrix_;
+  base::scoped_nsobject<NSView> top_separator_view_;
+  base::scoped_nsobject<NSView> bottom_separator_view_;
+  base::scoped_nsobject<NSBox> background_view_;
 
   DISALLOW_COPY_AND_ASSIGN(OmniboxPopupViewMac);
 };
diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm
index 9ba9aad..4d11860 100644
--- a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm
+++ b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm
@@ -11,6 +11,8 @@
 #include "chrome/browser/autocomplete/autocomplete_match.h"
 #include "chrome/browser/search/search.h"
 #include "chrome/browser/ui/cocoa/browser_window_controller.h"
+#import "chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h"
+#import "chrome/browser/ui/cocoa/omnibox/omnibox_popup_separator_view.h"
 #include "chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h"
 #include "chrome/browser/ui/omnibox/omnibox_edit_model.h"
 #include "chrome/browser/ui/omnibox/omnibox_popup_model.h"
@@ -35,9 +37,6 @@
 // Padding between matrix and the top and bottom of the popup window.
 const CGFloat kPopupPaddingVertical = 5.0;
 
-// How far to offset image column from the left.
-const CGFloat kImageXOffset = 5.0;
-
 // How far to offset the text column from the left.
 const CGFloat kTextXOffset = 28.0;
 
@@ -48,22 +47,10 @@
 // contents.
 const CGFloat kMaxContentsFraction = 0.7;
 
-// NSEvent -buttonNumber for middle mouse button.
-const NSInteger kMiddleButtonNumber = 2;
-
-// Rounding radius of selection and hover background on popup items.
-const CGFloat kCellRoundingRadius = 2.0;
-
 // Background colors for different states of the popup elements.
 NSColor* BackgroundColor() {
   return [NSColor controlBackgroundColor];
 }
-NSColor* SelectedBackgroundColor() {
-  return [NSColor selectedControlColor];
-}
-NSColor* HoveredBackgroundColor() {
-  return [NSColor controlHighlightColor];
-}
 
 NSColor* ContentTextColor() {
   return [NSColor blackColor];
@@ -77,111 +64,127 @@
 
 }  // namespace
 
-// Helper for MatchText() to allow sharing code between the contents
-// and description cases.  Returns NSMutableAttributedString as a
-// convenience for MatchText().
-NSMutableAttributedString* OmniboxPopupViewMac::DecorateMatchedString(
-    const string16 &matchString,
-    const AutocompleteMatch::ACMatchClassifications &classifications,
-    NSColor* textColor, NSColor* dimTextColor, gfx::Font& font) {
-  // Cache for on-demand computation of the bold version of |font|.
-  NSFont* boldFont = nil;
-
-  // Start out with a string using the default style info.
-  NSString* s = base::SysUTF16ToNSString(matchString);
-  NSDictionary* attributes = [NSDictionary dictionaryWithObjectsAndKeys:
-                                  font.GetNativeFont(), NSFontAttributeName,
-                                  textColor, NSForegroundColorAttributeName,
-                                  nil];
-  NSMutableAttributedString* as =
-      [[[NSMutableAttributedString alloc] initWithString:s
-                                              attributes:attributes]
-        autorelease];
-
-  // As a protective measure, bail if the length of the match string is not
-  // the same as the length of the converted NSString. http://crbug.com/121703
-  if ([s length] != matchString.size())
-    return as;
-
-  // Mark up the runs which differ from the default.
-  for (ACMatchClassifications::const_iterator i = classifications.begin();
-       i != classifications.end(); ++i) {
-    const BOOL isLast = (i+1) == classifications.end();
-    const NSInteger nextOffset =
-        (isLast ? [s length] : static_cast<NSInteger>((i + 1)->offset));
-    const NSInteger location = static_cast<NSInteger>(i->offset);
-    const NSInteger length = nextOffset - static_cast<NSInteger>(i->offset);
-    // Guard against bad, off-the-end classification ranges.
-    if (i->offset >= [s length] || length <= 0)
-      break;
-    const NSRange range = NSMakeRange(location,
-        MIN(length, static_cast<NSInteger>([s length]) - location));
-
-    if (0 != (i->style & ACMatchClassification::URL)) {
-      [as addAttribute:NSForegroundColorAttributeName
-                 value:URLTextColor() range:range];
-    }
-
-    if (0 != (i->style & ACMatchClassification::MATCH)) {
-      if (!boldFont) {
-        NSFontManager* fontManager = [NSFontManager sharedFontManager];
-        boldFont = [fontManager convertFont:font.GetNativeFont()
-                                toHaveTrait:NSBoldFontMask];
-      }
-      [as addAttribute:NSFontAttributeName value:boldFont range:range];
-    }
-
-    if (0 != (i->style & ACMatchClassification::DIM)) {
-      [as addAttribute:NSForegroundColorAttributeName
-                 value:dimTextColor
-                 range:range];
-    }
-  }
-
-  return as;
+OmniboxPopupViewMac::OmniboxPopupViewMac(OmniboxView* omnibox_view,
+                                         OmniboxEditModel* edit_model,
+                                         NSTextField* field)
+    : omnibox_view_(omnibox_view),
+      model_(new OmniboxPopupModel(this, edit_model)),
+      field_(field),
+      popup_(nil),
+      target_popup_frame_(NSZeroRect) {
+  DCHECK(omnibox_view);
+  DCHECK(edit_model);
 }
 
-NSMutableAttributedString* OmniboxPopupViewMac::ElideString(
-    NSMutableAttributedString* aString,
-    const string16 originalString,
-    const gfx::Font& font,
-    const float width) {
-  // If it already fits, nothing to be done.
-  if ([aString size].width <= width) {
-    return aString;
+OmniboxPopupViewMac::~OmniboxPopupViewMac() {
+  // Destroy the popup model before this object is destroyed, because
+  // it can call back to us in the destructor.
+  model_.reset();
+
+  // Break references to |this| because the popup may not be
+  // deallocated immediately.
+  [matrix_ setDelegate:NULL];
+}
+
+bool OmniboxPopupViewMac::IsOpen() const {
+  return popup_ != nil;
+}
+
+void OmniboxPopupViewMac::UpdatePopupAppearance() {
+  DCHECK([NSThread isMainThread]);
+  const AutocompleteResult& result = GetResult();
+  if (result.empty()) {
+    [[popup_ parentWindow] removeChildWindow:popup_];
+    [popup_ orderOut:nil];
+
+    // Break references to |this| because the popup may not be
+    // deallocated immediately.
+    [matrix_ setDelegate:nil];
+    matrix_.reset();
+
+    popup_.reset(nil);
+
+    target_popup_frame_ = NSZeroRect;
+
+    return;
   }
 
-  // If ElideText() decides to do nothing, nothing to be done.
-  const string16 elided =
-      ui::ElideText(originalString, font, width, ui::ELIDE_AT_END);
-  if (0 == elided.compare(originalString)) {
-    return aString;
+  CreatePopupIfNeeded();
+
+  gfx::Font result_font(OmniboxViewMac::GetFieldFont());
+
+  // Calculate the width of the matrix based on backing out the popup's border
+  // from the width of the field.
+  const CGFloat matrix_width = NSWidth([field_ bounds]);
+  DCHECK_GT(matrix_width, 0.0);
+
+  // Load the results into the popup's matrix.
+  const size_t rows = GetResult().size();
+  DCHECK_GT(rows, 0U);
+  [matrix_ renewRows:rows columns:1];
+  for (size_t ii = 0; ii < rows; ++ii) {
+    OmniboxPopupCell* cell = [matrix_ cellAtRow:ii column:0];
+    const AutocompleteMatch& match = GetResult().match_at(ii);
+    [cell setImage:ImageForMatch(match)];
+    [cell setAttributedTitle:MatchText(match, result_font, matrix_width)];
   }
 
-  // If everything was elided away, clear the string.
-  if (elided.empty()) {
-    [aString deleteCharactersInRange:NSMakeRange(0, [aString length])];
-    return aString;
-  }
+  // Set the cell size to fit a line of text in the cell's font.  All
+  // cells should use the same font and each should layout in one
+  // line, so they should all be about the same height.
+  const NSSize cell_size = [[matrix_ cellAtRow:0 column:0] cellSize];
+  DCHECK_GT(cell_size.height, 0.0);
+  const CGFloat cell_height = cell_size.height + kCellHeightAdjust;
+  [matrix_ setCellSize:NSMakeSize(matrix_width, cell_height)];
 
-  // The ellipses should be the last character, and everything before
-  // that should match the original string.
-  const size_t i(elided.length() - 1);
-  DCHECK_NE(0, elided.compare(0, i, originalString));
+  // Update the selection before placing (and displaying) the window.
+  PaintUpdatesNow();
 
-  // Replace the end of |aString| with the ellipses from |elided|.
-  NSString* s = base::SysUTF16ToNSString(elided.substr(i));
-  [aString replaceCharactersInRange:NSMakeRange(i, [aString length] - i)
-                         withString:s];
+  // Calculate the matrix size manually rather than using -sizeToCells
+  // because actually resizing the matrix messed up the popup size
+  // animation.
+  DCHECK_EQ([matrix_ intercellSpacing].height, 0.0);
+  PositionPopup(rows * cell_height);
+}
 
-  return aString;
+gfx::Rect OmniboxPopupViewMac::GetTargetBounds() {
+  // Flip the coordinate system before returning.
+  NSScreen* screen = [[NSScreen screens] objectAtIndex:0];
+  NSRect monitor_frame = [screen frame];
+  gfx::Rect bounds(NSRectToCGRect(target_popup_frame_));
+  bounds.set_y(monitor_frame.size.height - bounds.y() - bounds.height());
+  return bounds;
+}
+
+// This is only called by model in SetSelectedLine() after updating
+// everything.  Popup should already be visible.
+void OmniboxPopupViewMac::PaintUpdatesNow() {
+  [matrix_ selectCellAtRow:model_->selected_line() column:0];
+}
+
+void OmniboxPopupViewMac::OnMatrixRowSelected(OmniboxPopupMatrix* matrix,
+                                              size_t row) {
+  model_->SetSelectedLine(row, false, false);
+}
+
+void OmniboxPopupViewMac::OnMatrixRowClicked(OmniboxPopupMatrix* matrix,
+                                             size_t row) {
+  OpenURLForRow(row,
+                ui::WindowOpenDispositionFromNSEvent([NSApp currentEvent]));
+}
+
+void OmniboxPopupViewMac::OnMatrixRowMiddleClicked(OmniboxPopupMatrix* matrix,
+                                                   size_t row) {
+  OpenURLForRow(row, NEW_BACKGROUND_TAB);
 }
 
 // Return the text to show for the match, based on the match's
 // contents and description.  Result will be in |font|, with the
 // boldfaced version used for matches.
 NSAttributedString* OmniboxPopupViewMac::MatchText(
-    const AutocompleteMatch& match, gfx::Font& font, float cellWidth) {
+    const AutocompleteMatch& match,
+    gfx::Font& font,
+    float cell_width) {
   NSMutableAttributedString *as =
       DecorateMatchedString(match.contents,
                             match.contents_class,
@@ -197,18 +200,17 @@
     // partially visible.
     // TODO(shess): Consider revising our NSCell subclass to have two
     // bits and just draw them right, rather than truncating here.
-    const float textWidth = cellWidth - kTextXOffset;
+    const float text_width = cell_width - kTextXOffset;
     as = ElideString(as, match.contents, font,
-                     textWidth * kMaxContentsFraction);
+                     text_width * kMaxContentsFraction);
 
-    NSDictionary* attributes =
-        [NSDictionary dictionaryWithObjectsAndKeys:
-             font.GetNativeFont(), NSFontAttributeName,
-             ContentTextColor(), NSForegroundColorAttributeName,
-             nil];
-    NSString* rawEnDash = @" \u2013 ";
-    NSAttributedString* enDash =
-        [[[NSAttributedString alloc] initWithString:rawEnDash
+    NSDictionary* attributes = @{
+        NSFontAttributeName :  font.GetNativeFont(),
+        NSForegroundColorAttributeName : ContentTextColor()
+    };
+    NSString* raw_en_dash = @" \u2013 ";
+    NSAttributedString* en_dash =
+        [[[NSAttributedString alloc] initWithString:raw_en_dash
                                          attributes:attributes] autorelease];
 
     // In Windows, a boolean force_dim is passed as true for the
@@ -220,7 +222,7 @@
                               DimContentTextColor(),
                               font);
 
-    [as appendAttributedString:enDash];
+    [as appendAttributedString:en_dash];
     [as appendAttributedString:description];
   }
 
@@ -234,71 +236,109 @@
   return as;
 }
 
-// AutocompleteButtonCell overrides how backgrounds are displayed to
-// handle hover versus selected.  So long as we're in there, it also
-// provides some default initialization.
-
-@interface AutocompleteButtonCell : NSButtonCell {
-}
-@end
-
-// AutocompleteMatrix sets up a tracking area to implement hover by
-// highlighting the cell the mouse is over.
-
-@interface AutocompleteMatrix : NSMatrix {
- @private
-  // Target for click and middle-click.
-  OmniboxPopupViewMac* popupView_;  // weak, owns us.
-}
-
-// Create a zero-size matrix initializing |popupView_|.
-- (id)initWithPopupView:(OmniboxPopupViewMac*)popupView;
-
-// Set |popupView_|.
-- (void)setPopupView:(OmniboxPopupViewMac*)popupView;
-
-// Return the currently highlighted row.  Returns -1 if no row is
-// highlighted.
-- (NSInteger)highlightedRow;
-
-@end
-
 // static
-OmniboxPopupView* OmniboxPopupViewMac::Create(OmniboxView* omnibox_view,
-                                              OmniboxEditModel* edit_model,
-                                              NSTextField* field) {
-#if defined(HTML_INSTANT_EXTENDED_POPUP)
-  if (chrome::IsInstantExtendedAPIEnabled())
-    return new OmniboxPopupNonView(edit_model);
-#endif
-  return new OmniboxPopupViewMac(omnibox_view, edit_model, field);
+NSMutableAttributedString* OmniboxPopupViewMac::DecorateMatchedString(
+    const string16& match_string,
+    const AutocompleteMatch::ACMatchClassifications& classifications,
+    NSColor* text_color,
+    NSColor* dim_text_color,
+    gfx::Font& font) {
+  // Cache for on-demand computation of the bold version of |font|.
+  NSFont* bold_font = nil;
+
+  // Start out with a string using the default style info.
+  NSString* s = base::SysUTF16ToNSString(match_string);
+  NSDictionary* attributes = @{
+      NSFontAttributeName : font.GetNativeFont(),
+      NSForegroundColorAttributeName : text_color
+  };
+  NSMutableAttributedString* as =
+      [[[NSMutableAttributedString alloc] initWithString:s
+                                              attributes:attributes]
+        autorelease];
+
+  // As a protective measure, bail if the length of the match string is not
+  // the same as the length of the converted NSString. http://crbug.com/121703
+  if ([s length] != match_string.size())
+    return as;
+
+  // Mark up the runs which differ from the default.
+  for (ACMatchClassifications::const_iterator i = classifications.begin();
+       i != classifications.end(); ++i) {
+    const BOOL is_last = (i+1) == classifications.end();
+    const NSInteger next_offset =
+        (is_last ? [s length] : static_cast<NSInteger>((i + 1)->offset));
+    const NSInteger location = static_cast<NSInteger>(i->offset);
+    const NSInteger length = next_offset - static_cast<NSInteger>(i->offset);
+    // Guard against bad, off-the-end classification ranges.
+    if (i->offset >= [s length] || length <= 0)
+      break;
+    const NSRange range = NSMakeRange(location,
+        MIN(length, static_cast<NSInteger>([s length]) - location));
+
+    if (0 != (i->style & ACMatchClassification::URL)) {
+      [as addAttribute:NSForegroundColorAttributeName
+                 value:URLTextColor()
+                 range:range];
+    }
+
+    if (0 != (i->style & ACMatchClassification::MATCH)) {
+      if (!bold_font) {
+        NSFontManager* font_manager = [NSFontManager sharedFontManager];
+        bold_font = [font_manager convertFont:font.GetNativeFont()
+                                  toHaveTrait:NSBoldFontMask];
+      }
+      [as addAttribute:NSFontAttributeName value:bold_font range:range];
+    }
+
+    if (0 != (i->style & ACMatchClassification::DIM)) {
+      [as addAttribute:NSForegroundColorAttributeName
+                 value:dim_text_color
+                 range:range];
+    }
+  }
+
+  return as;
 }
 
+NSMutableAttributedString* OmniboxPopupViewMac::ElideString(
+    NSMutableAttributedString* a_string,
+    const string16& original_string,
+    const gfx::Font& font,
+    const float width) {
+  // If it already fits, nothing to be done.
+  if ([a_string size].width <= width) {
+    return a_string;
+  }
 
-OmniboxPopupViewMac::OmniboxPopupViewMac(OmniboxView* omnibox_view,
-                                         OmniboxEditModel* edit_model,
-                                         NSTextField* field)
-    : omnibox_view_(omnibox_view),
-      model_(new OmniboxPopupModel(this, edit_model)),
-      field_(field),
-      popup_(nil),
-      targetPopupFrame_(NSZeroRect) {
-  DCHECK(omnibox_view);
-  DCHECK(edit_model);
+  // If ElideText() decides to do nothing, nothing to be done.
+  const string16 elided =
+      ui::ElideText(original_string, font, width, ui::ELIDE_AT_END);
+  if (0 == elided.compare(original_string)) {
+    return a_string;
+  }
+
+  // If everything was elided away, clear the string.
+  if (elided.empty()) {
+    [a_string deleteCharactersInRange:NSMakeRange(0, [a_string length])];
+    return a_string;
+  }
+
+  // The ellipses should be the last character, and everything before
+  // that should match the original string.
+  const size_t i(elided.length() - 1);
+  DCHECK_NE(0, elided.compare(0, i, original_string));
+
+  // Replace the end of |aString| with the ellipses from |elided|.
+  NSString* s = base::SysUTF16ToNSString(elided.substr(i));
+  [a_string replaceCharactersInRange:NSMakeRange(i, [a_string length] - i)
+                          withString:s];
+
+  return a_string;
 }
 
-OmniboxPopupViewMac::~OmniboxPopupViewMac() {
-  // Destroy the popup model before this object is destroyed, because
-  // it can call back to us in the destructor.
-  model_.reset();
-
-  // Break references to |this| because the popup may not be
-  // deallocated immediately.
-  [autocomplete_matrix_ setPopupView:NULL];
-}
-
-bool OmniboxPopupViewMac::IsOpen() const {
-  return popup_ != nil;
+const AutocompleteResult& OmniboxPopupViewMac::GetResult() const {
+  return model_->result();
 }
 
 void OmniboxPopupViewMac::CreatePopupIfNeeded() {
@@ -308,65 +348,103 @@
                                     styleMask:NSBorderlessWindowMask
                                       backing:NSBackingStoreBuffered
                                         defer:YES]);
-    [popup_ setMovableByWindowBackground:NO];
-    // The window shape is determined by the content view.
-    [popup_ setAlphaValue:1.0];
-    [popup_ setOpaque:YES];
-    [popup_ setBackgroundColor:BackgroundColor()];
-    [popup_ setHasShadow:YES];
-    [popup_ setLevel:NSNormalWindowLevel];
+    [popup_ setBackgroundColor:[NSColor clearColor]];
+    [popup_ setOpaque:NO];
+
     // Use a flipped view to pin the matrix top the top left. This is needed
     // for animated resize.
-    scoped_nsobject<FlippedView> contentView(
+    base::scoped_nsobject<FlippedView> contentView(
         [[FlippedView alloc] initWithFrame:NSZeroRect]);
     [popup_ setContentView:contentView];
 
-    autocomplete_matrix_.reset(
-        [[AutocompleteMatrix alloc] initWithPopupView:this]);
-    [contentView addSubview:autocomplete_matrix_];
+    // View to draw a background beneath the matrix.
+    background_view_.reset([[NSBox alloc] initWithFrame:NSZeroRect]);
+    [background_view_ setBoxType:NSBoxCustom];
+    [background_view_ setBorderType:NSNoBorder];
+    [background_view_ setFillColor:BackgroundColor()];
+    [background_view_ setContentViewMargins:NSZeroSize];
+    [contentView addSubview:background_view_];
+
+    matrix_.reset([[OmniboxPopupMatrix alloc] initWithDelegate:this]);
+    [background_view_ addSubview:matrix_];
+
+    top_separator_view_.reset(
+        [[OmniboxPopupTopSeparatorView alloc] initWithFrame:NSZeroRect]);
+    [contentView addSubview:top_separator_view_];
+
+    bottom_separator_view_.reset(
+        [[OmniboxPopupBottomSeparatorView alloc] initWithFrame:NSZeroRect]);
+    [contentView addSubview:bottom_separator_view_];
 
     // TODO(dtseng): Ignore until we provide NSAccessibility support.
     [popup_ accessibilitySetOverrideValue:NSAccessibilityUnknownRole
-        forAttribute:NSAccessibilityRoleAttribute];
+                             forAttribute:NSAccessibilityRoleAttribute];
   }
 }
 
 void OmniboxPopupViewMac::PositionPopup(const CGFloat matrixHeight) {
   BrowserWindowController* controller =
       [BrowserWindowController browserWindowControllerForView:field_];
-  NSRect anchorRectBase = [controller omniboxPopupAnchorRect];
+  NSRect anchor_rect_base = [controller omniboxPopupAnchorRect];
 
   // Calculate the popup's position on the screen.
-  NSRect popupFrame = anchorRectBase;
+  NSRect popup_frame = anchor_rect_base;
   // Size to fit the matrix and shift down by the size.
-  popupFrame.size.height = matrixHeight + kPopupPaddingVertical * 2.0;
-  popupFrame.origin.y -= NSHeight(popupFrame);
+  popup_frame.size.height = matrixHeight + kPopupPaddingVertical * 2.0;
+  popup_frame.size.height += [OmniboxPopupTopSeparatorView preferredHeight];
+  popup_frame.size.height += [OmniboxPopupBottomSeparatorView preferredHeight];
+  popup_frame.origin.y -= NSHeight(popup_frame);
   // Shift to screen coordinates.
-  popupFrame.origin =
-      [[controller window] convertBaseToScreen:popupFrame.origin];
+  popup_frame.origin =
+      [[controller window] convertBaseToScreen:popup_frame.origin];
 
   // Do nothing if the popup is already animating to the given |frame|.
-  if (NSEqualRects(popupFrame, targetPopupFrame_))
+  if (NSEqualRects(popup_frame, target_popup_frame_))
     return;
 
-  NSPoint fieldOriginBase =
-      [field_ convertPoint:[field_ bounds].origin toView:nil];
-  NSRect matrixFrame = NSZeroRect;
-  matrixFrame.origin.x = fieldOriginBase.x - NSMinX(anchorRectBase);
-  matrixFrame.origin.y = kPopupPaddingVertical;
-  matrixFrame.size.width = [autocomplete_matrix_ cellSize].width;
-  matrixFrame.size.height = matrixHeight;
-  [autocomplete_matrix_ setFrame:matrixFrame];
+  // Top separator.
+  NSRect top_separator_frame = NSZeroRect;
+  top_separator_frame.size.width = NSWidth(popup_frame);
+  top_separator_frame.size.height =
+      [OmniboxPopupTopSeparatorView preferredHeight];
+  [top_separator_view_ setFrame:top_separator_frame];
 
-  NSRect currentPopupFrame = [popup_ frame];
-  targetPopupFrame_ = popupFrame;
+  // Bottom separator.
+  NSRect bottom_separator_frame = NSZeroRect;
+  bottom_separator_frame.size.width = NSWidth(popup_frame);
+  bottom_separator_frame.size.height =
+      [OmniboxPopupBottomSeparatorView preferredHeight];
+  bottom_separator_frame.origin.y =
+      NSHeight(popup_frame) - NSHeight(bottom_separator_frame);
+  [bottom_separator_view_ setFrame:bottom_separator_frame];
+
+  // Background view.
+  NSRect background_rect = NSZeroRect;
+  background_rect.size.width = NSWidth(popup_frame);
+  background_rect.size.height = NSHeight(popup_frame) -
+      NSHeight(top_separator_frame) - NSHeight(bottom_separator_frame);
+  background_rect.origin.y = NSMaxY(top_separator_frame);
+  [background_view_ setFrame:background_rect];
+
+  // Matrix.
+  NSPoint field_origin_base =
+      [field_ convertPoint:[field_ bounds].origin toView:nil];
+  NSRect matrix_frame = NSZeroRect;
+  matrix_frame.origin.x = field_origin_base.x - NSMinX(anchor_rect_base);
+  matrix_frame.origin.y = kPopupPaddingVertical;
+  matrix_frame.size.width = [matrix_ cellSize].width;
+  matrix_frame.size.height = matrixHeight;
+  [matrix_ setFrame:matrix_frame];
+
+  NSRect current_poup_frame = [popup_ frame];
+  target_popup_frame_ = popup_frame;
 
   // Animate the frame change if the only change is that the height got smaller.
   // Otherwise, resize immediately.
-  bool animate = (NSHeight(popupFrame) < NSHeight(currentPopupFrame) &&
-                  NSWidth(popupFrame) == NSWidth(currentPopupFrame));
+  bool animate = (NSHeight(popup_frame) < NSHeight(current_poup_frame) &&
+                  NSWidth(popup_frame) == NSWidth(current_poup_frame));
 
-  scoped_nsobject<NSDictionary> savedAnimations;
+  base::scoped_nsobject<NSDictionary> savedAnimations;
   if (!animate) {
     // In an ideal world, running a zero-length animation would cancel any
     // running animations and set the new frame value immediately.  In practice,
@@ -376,16 +454,14 @@
     // convinces AppKit to do the right thing.  Save off the current animations
     // dictionary so it can be restored later.
     savedAnimations.reset([[popup_ animations] copy]);
-    [popup_ setAnimations:
-              [NSDictionary dictionaryWithObjectsAndKeys:[NSNull null],
-                                                         @"frame", nil]];
+    [popup_ setAnimations:@{@"frame" : [NSNull null]}];
   }
 
   [NSAnimationContext beginGrouping];
   // Don't use the GTM additon for the "Steve" slowdown because this can happen
   // async from user actions and the effects could be a surprise.
   [[NSAnimationContext currentContext] setDuration:kShrinkAnimationDuration];
-  [[popup_ animator] setFrame:popupFrame display:YES];
+  [[popup_ animator] setFrame:popup_frame display:YES];
   [NSAnimationContext endGrouping];
 
   if (!animate) {
@@ -408,338 +484,13 @@
   return OmniboxViewMac::ImageForResource(resource_id);
 }
 
-void OmniboxPopupViewMac::UpdatePopupAppearance() {
-  DCHECK([NSThread isMainThread]);
-  const AutocompleteResult& result = model_->result();
-  if (result.empty()) {
-    [[popup_ parentWindow] removeChildWindow:popup_];
-    [popup_ orderOut:nil];
+void OmniboxPopupViewMac::OpenURLForRow(size_t row,
+                                        WindowOpenDisposition disposition) {
+  DCHECK_GE(row, 0u);
 
-    // Break references to |this| because the popup may not be
-    // deallocated immediately.
-    [autocomplete_matrix_ setPopupView:NULL];
-    autocomplete_matrix_.reset();
-
-    popup_.reset(nil);
-
-    targetPopupFrame_ = NSZeroRect;
-
-    return;
-  }
-
-  CreatePopupIfNeeded();
-
-  // The popup's font is a slightly smaller version of the field's.
-  NSFont* fieldFont = OmniboxViewMac::GetFieldFont();
-  const CGFloat resultFontSize = [fieldFont pointSize];
-  gfx::Font resultFont(base::SysNSStringToUTF8([fieldFont fontName]),
-                       static_cast<int>(resultFontSize));
-
-  // Calculate the width of the matrix based on backing out the
-  // popup's border from the width of the field.
-  const CGFloat matrixWidth = NSWidth([field_ bounds]);
-  DCHECK_GT(matrixWidth, 0.0);
-
-  // Load the results into the popup's matrix.
-  const size_t rows = model_->result().size();
-  DCHECK_GT(rows, 0U);
-  [autocomplete_matrix_ renewRows:rows columns:1];
-  for (size_t ii = 0; ii < rows; ++ii) {
-    AutocompleteButtonCell* cell = [autocomplete_matrix_ cellAtRow:ii column:0];
-    const AutocompleteMatch& match = model_->result().match_at(ii);
-    [cell setImage:ImageForMatch(match)];
-    [cell setAttributedTitle:MatchText(match, resultFont, matrixWidth)];
-  }
-
-  // Set the cell size to fit a line of text in the cell's font.  All
-  // cells should use the same font and each should layout in one
-  // line, so they should all be about the same height.
-  const NSSize cellSize =
-      [[autocomplete_matrix_ cellAtRow:0 column:0] cellSize];
-  DCHECK_GT(cellSize.height, 0.0);
-  const CGFloat cellHeight = cellSize.height + kCellHeightAdjust;
-  [autocomplete_matrix_ setCellSize:NSMakeSize(matrixWidth, cellHeight)];
-
-  // Update the selection before placing (and displaying) the window.
-  PaintUpdatesNow();
-
-  // Calculate the matrix size manually rather than using -sizeToCells
-  // because actually resizing the matrix messed up the popup size
-  // animation.
-  DCHECK_EQ([autocomplete_matrix_ intercellSpacing].height, 0.0);
-  PositionPopup(rows * cellHeight);
-}
-
-gfx::Rect OmniboxPopupViewMac::GetTargetBounds() {
-  // Flip the coordinate system before returning.
-  NSScreen* screen = [[NSScreen screens] objectAtIndex:0];
-  NSRect monitorFrame = [screen frame];
-  gfx::Rect bounds(NSRectToCGRect(targetPopupFrame_));
-  bounds.set_y(monitorFrame.size.height - bounds.y() - bounds.height());
-  return bounds;
-}
-
-void OmniboxPopupViewMac::SetSelectedLine(size_t line) {
-  model_->SetSelectedLine(line, false, false);
-}
-
-// This is only called by model in SetSelectedLine() after updating
-// everything.  Popup should already be visible.
-void OmniboxPopupViewMac::PaintUpdatesNow() {
-  [autocomplete_matrix_ selectCellAtRow:model_->selected_line() column:0];
-}
-
-void OmniboxPopupViewMac::OpenURLForRow(int row, bool force_background) {
-  DCHECK_GE(row, 0);
-
-  WindowOpenDisposition disposition = NEW_BACKGROUND_TAB;
-  if (!force_background) {
-    disposition = ui::WindowOpenDispositionFromNSEvent([NSApp currentEvent]);
-  }
-
-  // OpenMatch() may close the popup, which will clear the result set
-  // and, by extension, |match| and its contents.  So copy the
-  // relevant match out to make sure it stays alive until the call
-  // completes.
-  AutocompleteMatch match = model_->result().match_at(row);
+  // OpenMatch() may close the popup, which will clear the result set and, by
+  // extension, |match| and its contents.  So copy the relevant match out to
+  // make sure it stays alive until the call completes.
+  AutocompleteMatch match = GetResult().match_at(row);
   omnibox_view_->OpenMatch(match, disposition, GURL(), row);
 }
-
-@implementation AutocompleteButtonCell
-
-- (id)init {
-  self = [super init];
-  if (self) {
-    [self setImagePosition:NSImageLeft];
-    [self setBordered:NO];
-    [self setButtonType:NSRadioButton];
-
-    // Without this highlighting messes up white areas of images.
-    [self setHighlightsBy:NSNoCellMask];
-  }
-  return self;
-}
-
-// The default NSButtonCell drawing leaves the image flush left and
-// the title next to the image.  This spaces things out to line up
-// with the star button and autocomplete field.
-- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView {
-  [BackgroundColor() set];
-  NSRectFill(cellFrame);
-  if ([self state] == NSOnState || [self isHighlighted]) {
-    if ([self state] == NSOnState)
-      [SelectedBackgroundColor() set];
-    else
-      [HoveredBackgroundColor() set];
-    NSBezierPath* path =
-        [NSBezierPath bezierPathWithRoundedRect:cellFrame
-                                        xRadius:kCellRoundingRadius
-                                        yRadius:kCellRoundingRadius];
-    [path fill];
-  }
-
-  // Put the image centered vertically but in a fixed column.
-  NSImage* image = [self image];
-  if (image) {
-    NSRect imageRect = cellFrame;
-    imageRect.size = [image size];
-    imageRect.origin.y +=
-        std::floor((NSHeight(cellFrame) - NSHeight(imageRect)) / 2.0);
-    imageRect.origin.x += kImageXOffset;
-    [image drawInRect:imageRect
-             fromRect:NSZeroRect  // Entire image
-            operation:NSCompositeSourceOver
-             fraction:1.0
-       respectFlipped:YES
-                hints:nil];
-  }
-
-  // Adjust the title position to be lined up under the field's text.
-  NSAttributedString* title = [self attributedTitle];
-  if (title && [title length]) {
-    NSRect titleRect = cellFrame;
-    titleRect.size.width -= kTextXOffset;
-    titleRect.origin.x += kTextXOffset;
-    [self drawTitle:title withFrame:titleRect inView:controlView];
-  }
-}
-
-@end
-
-@implementation AutocompleteMatrix
-
-// Remove all tracking areas and initialize the one we want.  Removing
-// all might be overkill, but it's unclear why there would be others
-// for the popup window.
-- (void)resetTrackingArea {
-  for (NSTrackingArea* trackingArea in [self trackingAreas]) {
-    [self removeTrackingArea:trackingArea];
-  }
-
-  // TODO(shess): Consider overriding -acceptsFirstMouse: and changing
-  // NSTrackingActiveInActiveApp to NSTrackingActiveAlways.
-  NSTrackingAreaOptions options = NSTrackingMouseEnteredAndExited;
-  options |= NSTrackingMouseMoved;
-  options |= NSTrackingActiveInActiveApp;
-  options |= NSTrackingInVisibleRect;
-
-  scoped_nsobject<NSTrackingArea> trackingArea(
-      [[NSTrackingArea alloc] initWithRect:[self frame]
-                                   options:options
-                                     owner:self
-                                  userInfo:nil]);
-  [self addTrackingArea:trackingArea];
-}
-
-- (void)updateTrackingAreas {
-  [self resetTrackingArea];
-  [super updateTrackingAreas];
-}
-
-- (id)initWithPopupView:(OmniboxPopupViewMac*)popupView {
-  self = [super initWithFrame:NSZeroRect];
-  if (self) {
-    popupView_ = popupView;
-
-    [self setCellClass:[AutocompleteButtonCell class]];
-
-    // Cells pack with no spacing.
-    [self setIntercellSpacing:NSMakeSize(0.0, 0.0)];
-
-    [self setDrawsBackground:YES];
-    [self setBackgroundColor:BackgroundColor()];
-    [self renewRows:0 columns:1];
-    [self setAllowsEmptySelection:YES];
-    [self setMode:NSRadioModeMatrix];
-    [self deselectAllCells];
-
-    [self resetTrackingArea];
-  }
-  return self;
-}
-
-- (void)setPopupView:(OmniboxPopupViewMac*)popupView {
-  popupView_ = popupView;
-}
-
-- (void)highlightRowAt:(NSInteger)rowIndex {
-  // highlightCell will be nil if rowIndex is out of range, so no cell
-  // will be highlighted.
-  NSCell* highlightCell = [self cellAtRow:rowIndex column:0];
-
-  for (NSCell* cell in [self cells]) {
-    [cell setHighlighted:(cell == highlightCell)];
-  }
-}
-
-- (void)highlightRowUnder:(NSEvent*)theEvent {
-  NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil];
-  NSInteger row, column;
-  if ([self getRow:&row column:&column forPoint:point]) {
-    [self highlightRowAt:row];
-  } else {
-    [self highlightRowAt:-1];
-  }
-}
-
-// Callbacks from NSTrackingArea.
-- (void)mouseEntered:(NSEvent*)theEvent {
-  [self highlightRowUnder:theEvent];
-}
-- (void)mouseMoved:(NSEvent*)theEvent {
-  [self highlightRowUnder:theEvent];
-}
-- (void)mouseExited:(NSEvent*)theEvent {
-  [self highlightRowAt:-1];
-}
-
-// The tracking area events aren't forwarded during a drag, so handle
-// highlighting manually for middle-click and middle-drag.
-- (void)otherMouseDown:(NSEvent*)theEvent {
-  if ([theEvent buttonNumber] == kMiddleButtonNumber) {
-    [self highlightRowUnder:theEvent];
-  }
-  [super otherMouseDown:theEvent];
-}
-- (void)otherMouseDragged:(NSEvent*)theEvent {
-  if ([theEvent buttonNumber] == kMiddleButtonNumber) {
-    [self highlightRowUnder:theEvent];
-  }
-  [super otherMouseDragged:theEvent];
-}
-
-- (void)otherMouseUp:(NSEvent*)theEvent {
-  // Only intercept middle button.
-  if ([theEvent buttonNumber] != kMiddleButtonNumber) {
-    [super otherMouseUp:theEvent];
-    return;
-  }
-
-  // -otherMouseDragged: should always have been called at this
-  // location, but make sure the user is getting the right feedback.
-  [self highlightRowUnder:theEvent];
-
-  const NSInteger highlightedRow = [self highlightedRow];
-  if (highlightedRow != -1) {
-    DCHECK(popupView_);
-    popupView_->OpenURLForRow(highlightedRow, true);
-  }
-}
-
-// Select cell under |theEvent|, returning YES if a selection is made.
-- (BOOL)selectCellForEvent:(NSEvent*)theEvent {
-  NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil];
-
-  NSInteger row, column;
-  if ([self getRow:&row column:&column forPoint:point]) {
-    DCHECK_EQ(column, 0);
-    DCHECK(popupView_);
-    popupView_->SetSelectedLine(row);
-    return YES;
-  }
-  return NO;
-}
-
-// Track the mouse until released, keeping the cell under the mouse
-// selected.  If the mouse wanders off-view, revert to the
-// originally-selected cell.  If the mouse is released over a cell,
-// call |popupView_| to open the row's URL.
-- (void)mouseDown:(NSEvent*)theEvent {
-  NSCell* selectedCell = [self selectedCell];
-
-  // Clear any existing highlight.
-  [self highlightRowAt:-1];
-
-  do {
-    if (![self selectCellForEvent:theEvent]) {
-      [self selectCell:selectedCell];
-    }
-
-    const NSUInteger mask = NSLeftMouseUpMask | NSLeftMouseDraggedMask;
-    theEvent = [[self window] nextEventMatchingMask:mask];
-  } while ([theEvent type] == NSLeftMouseDragged);
-
-  // Do not message |popupView_| if released outside view.
-  if (![self selectCellForEvent:theEvent]) {
-    [self selectCell:selectedCell];
-  } else {
-    const NSInteger selectedRow = [self selectedRow];
-    DCHECK_GE(selectedRow, 0);
-
-    DCHECK(popupView_);
-    popupView_->OpenURLForRow(selectedRow, false);
-  }
-}
-
-- (NSInteger)highlightedRow {
-  NSArray* cells = [self cells];
-  const NSUInteger count = [cells count];
-  for(NSUInteger i = 0; i < count; ++i) {
-    if ([[cells objectAtIndex:i] isHighlighted]) {
-      return i;
-    }
-  }
-  return -1;
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac_unittest.mm b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac_unittest.mm
index de68daf..75f973a 100644
--- a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac_unittest.mm
+++ b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac_unittest.mm
@@ -7,101 +7,126 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
-#include "testing/platform_test.h"
+#include "chrome/browser/ui/cocoa/cocoa_profile_test.h"
+#import "chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h"
 #include "ui/base/text/text_elider.h"
 
 namespace {
 
 const float kLargeWidth = 10000;
 
-class OmniboxPopupViewMacTest : public PlatformTest {
+// Returns the length of the run starting at |location| for which
+// |attributeName| remains the same.
+NSUInteger RunLengthForAttribute(NSAttributedString* string,
+                                 NSUInteger location,
+                                 NSString* attributeName) {
+  const NSRange full_range = NSMakeRange(0, [string length]);
+  NSRange range;
+  [string attribute:attributeName
+            atIndex:location longestEffectiveRange:&range inRange:full_range];
+
+  // In order to signal when the run doesn't start exactly at location, return
+  // a weirdo length.  This causes the incorrect expectation to manifest at the
+  // calling location, which is more useful than an EXPECT_EQ() would be here.
+  if (range.location != location) {
+    return -1;
+  }
+
+  return range.length;
+}
+
+// Return true if the run starting at |location| has |color| for attribute
+// NSForegroundColorAttributeName.
+bool RunHasColor(NSAttributedString* string,
+                 NSUInteger location,
+                 NSColor* color) {
+  const NSRange full_range = NSMakeRange(0, [string length]);
+  NSRange range;
+  NSColor* run_color = [string attribute:NSForegroundColorAttributeName
+                                 atIndex:location
+                   longestEffectiveRange:&range
+                                 inRange:full_range];
+
+  // According to one "Ali Ozer", you can compare objects within the same color
+  // space using -isEqual:.  Converting color spaces seems too heavyweight for
+  // these tests.
+  // http://lists.apple.com/archives/cocoa-dev/2005/May/msg00186.html
+  return [run_color isEqual:color] ? true : false;
+}
+
+// Return true if the run starting at |location| has the font trait(s) in |mask|
+// font in NSFontAttributeName.
+bool RunHasFontTrait(NSAttributedString* string,
+                     NSUInteger location,
+                     NSFontTraitMask mask) {
+  const NSRange full_range = NSMakeRange(0, [string length]);
+  NSRange range;
+  NSFont* run_font = [string attribute:NSFontAttributeName
+                               atIndex:location
+                 longestEffectiveRange:&range
+                               inRange:full_range];
+  NSFontManager* fontManager = [NSFontManager sharedFontManager];
+  if (run_font && (mask == ([fontManager traitsOfFont:run_font] & mask))) {
+    return true;
+  }
+  return false;
+}
+
+// AutocompleteMatch doesn't really have the right constructor for our
+// needs.  Fake one for us to use.
+AutocompleteMatch MakeMatch(const string16& contents,
+                            const string16& description) {
+  AutocompleteMatch m(NULL, 1, true, AutocompleteMatchType::URL_WHAT_YOU_TYPED);
+  m.contents = contents;
+  m.description = description;
+  return m;
+}
+
+class MockOmniboxPopupViewMac : public OmniboxPopupViewMac {
  public:
-  OmniboxPopupViewMacTest() {}
+  MockOmniboxPopupViewMac(OmniboxView* omnibox_view,
+                          OmniboxEditModel* edit_model,
+                          NSTextField* field)
+      : OmniboxPopupViewMac(omnibox_view, edit_model, field) {
+  }
 
-  virtual void SetUp() {
-    PlatformTest::SetUp();
+  void SetResultCount(size_t count) {
+    ACMatches matches;
+    for (size_t i = 0; i < count; ++i)
+      matches.push_back(AutocompleteMatch());
+    result_.Reset();
+    result_.AppendMatches(matches);
+  }
 
-    // These are here because there is no autorelease pool for the
-    // constructor.
+ protected:
+  virtual const AutocompleteResult& GetResult() const OVERRIDE {
+    return result_;
+  }
+
+ private:
+  AutocompleteResult result_;
+};
+
+class OmniboxPopupViewMacTest : public CocoaProfileTest {
+ public:
+  OmniboxPopupViewMacTest() {
     color_ = [NSColor blackColor];
-    dimColor_ = [NSColor darkGrayColor];
+    dim_color_ = [NSColor darkGrayColor];
     font_ = gfx::Font(
         base::SysNSStringToUTF8([[NSFont userFontOfSize:12] fontName]), 12);
   }
 
-  // Returns the length of the run starting at |location| for which
-  // |attributeName| remains the same.
-  static NSUInteger RunLengthForAttribute(NSAttributedString* string,
-                                          NSUInteger location,
-                                          NSString* attributeName) {
-    const NSRange fullRange = NSMakeRange(0, [string length]);
-    NSRange range;
-    [string attribute:attributeName
-              atIndex:location longestEffectiveRange:&range inRange:fullRange];
-
-    // In order to signal when the run doesn't start exactly at
-    // location, return a weirdo length.  This causes the incorrect
-    // expectation to manifest at the calling location, which is more
-    // useful than an EXPECT_EQ() would be here.
-    if (range.location != location) {
-      return -1;
-    }
-
-    return range.length;
-  }
-
-  // Return true if the run starting at |location| has |color| for
-  // attribute NSForegroundColorAttributeName.
-  static bool RunHasColor(NSAttributedString* string,
-                          NSUInteger location, NSColor* color) {
-    const NSRange fullRange = NSMakeRange(0, [string length]);
-    NSRange range;
-    NSColor* runColor = [string attribute:NSForegroundColorAttributeName
-                                  atIndex:location
-                    longestEffectiveRange:&range inRange:fullRange];
-
-    // According to one "Ali Ozer", you can compare objects within the
-    // same color space using -isEqual:.  Converting color spaces
-    // seems too heavyweight for these tests.
-    // http://lists.apple.com/archives/cocoa-dev/2005/May/msg00186.html
-    return [runColor isEqual:color] ? true : false;
-  }
-
-  // Return true if the run starting at |location| has the font
-  // trait(s) in |mask| font in NSFontAttributeName.
-  static bool RunHasFontTrait(NSAttributedString* string, NSUInteger location,
-                              NSFontTraitMask mask) {
-    const NSRange fullRange = NSMakeRange(0, [string length]);
-    NSRange range;
-    NSFont* runFont = [string attribute:NSFontAttributeName
-                                atIndex:location
-                  longestEffectiveRange:&range inRange:fullRange];
-    NSFontManager* fontManager = [NSFontManager sharedFontManager];
-    if (runFont && (mask == ([fontManager traitsOfFont:runFont]&mask))) {
-      return true;
-    }
-    return false;
-  }
-
-  // AutocompleteMatch doesn't really have the right constructor for our
-  // needs.  Fake one for us to use.
-  static AutocompleteMatch MakeMatch(const string16 &contents,
-                                     const string16 &description) {
-    AutocompleteMatch m(NULL, 1, true,
-                        AutocompleteMatchType::URL_WHAT_YOU_TYPED);
-    m.contents = contents;
-    m.description = description;
-    return m;
-  }
-
+ protected:
   NSColor* color_;  // weak
-  NSColor* dimColor_;  // weak
+  NSColor* dim_color_;  // weak
   gfx::Font font_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(OmniboxPopupViewMacTest);
 };
 
-// Simple inputs with no matches should result in styled output who's
-// text matches the input string, with the passed-in color, and
-// nothing bolded.
+// Simple inputs with no matches should result in styled output who's text
+// matches the input string, with the passed-in color, and nothing bolded.
 TEST_F(OmniboxPopupViewMacTest, DecorateMatchedStringNoMatch) {
   NSString* const string = @"This is a test";
   AutocompleteMatch::ACMatchClassifications classifications;
@@ -109,7 +134,7 @@
   NSAttributedString* decorated =
       OmniboxPopupViewMac::DecorateMatchedString(
           base::SysNSStringToUTF16(string), classifications,
-          color_, dimColor_, font_);
+          color_, dim_color_, font_);
 
   // Result has same characters as the input.
   EXPECT_EQ([decorated length], [string length]);
@@ -122,13 +147,13 @@
   EXPECT_TRUE(RunHasColor(decorated, 0U, color_));
 
   // An unbolded font for the entire string.
-  EXPECT_EQ(RunLengthForAttribute(decorated, 0U,
-                                  NSFontAttributeName), [string length]);
+  EXPECT_EQ(RunLengthForAttribute(decorated, 0U, NSFontAttributeName),
+            [string length]);
   EXPECT_FALSE(RunHasFontTrait(decorated, 0U, NSBoldFontMask));
 }
 
-// Identical to DecorateMatchedStringNoMatch, except test that URL
-// style gets a different color than we passed in.
+// Identical to DecorateMatchedStringNoMatch, except test that URL style gets a
+// different color than we passed in.
 TEST_F(OmniboxPopupViewMacTest, DecorateMatchedStringURLNoMatch) {
   NSString* const string = @"This is a test";
   AutocompleteMatch::ACMatchClassifications classifications;
@@ -139,7 +164,7 @@
   NSAttributedString* decorated =
       OmniboxPopupViewMac::DecorateMatchedString(
           base::SysNSStringToUTF16(string), classifications,
-          color_, dimColor_, font_);
+          color_, dim_color_, font_);
 
   // Result has same characters as the input.
   EXPECT_EQ([decorated length], [string length]);
@@ -161,24 +186,24 @@
 TEST_F(OmniboxPopupViewMacTest, DecorateMatchedStringDimNoMatch) {
   NSString* const string = @"This is a test";
   // Dim "is".
-  const NSUInteger runLength1 = 5, runLength2 = 2, runLength3 = 7;
+  const NSUInteger run_length_1 = 5, run_length_2 = 2, run_length_3 = 7;
   // Make sure nobody messed up the inputs.
-  EXPECT_EQ(runLength1 + runLength2 + runLength3, [string length]);
+  EXPECT_EQ(run_length_1 + run_length_2 + run_length_3, [string length]);
 
   // Push each run onto classifications.
   AutocompleteMatch::ACMatchClassifications classifications;
   classifications.push_back(
       ACMatchClassification(0, ACMatchClassification::NONE));
   classifications.push_back(
-      ACMatchClassification(runLength1, ACMatchClassification::DIM));
+      ACMatchClassification(run_length_1, ACMatchClassification::DIM));
   classifications.push_back(
-      ACMatchClassification(runLength1 + runLength2,
+      ACMatchClassification(run_length_1 + run_length_2,
                             ACMatchClassification::NONE));
 
   NSAttributedString* decorated =
       OmniboxPopupViewMac::DecorateMatchedString(
           base::SysNSStringToUTF16(string), classifications,
-          color_, dimColor_, font_);
+          color_, dim_color_, font_);
 
   // Result has same characters as the input.
   EXPECT_EQ([decorated length], [string length]);
@@ -187,18 +212,18 @@
   // Should have three font runs, normal, dim, normal.
   EXPECT_EQ(RunLengthForAttribute(decorated, 0U,
                                   NSForegroundColorAttributeName),
-            runLength1);
+            run_length_1);
   EXPECT_TRUE(RunHasColor(decorated, 0U, color_));
 
-  EXPECT_EQ(RunLengthForAttribute(decorated, runLength1,
+  EXPECT_EQ(RunLengthForAttribute(decorated, run_length_1,
                                   NSForegroundColorAttributeName),
-            runLength2);
-  EXPECT_TRUE(RunHasColor(decorated, runLength1, dimColor_));
+            run_length_2);
+  EXPECT_TRUE(RunHasColor(decorated, run_length_1, dim_color_));
 
-  EXPECT_EQ(RunLengthForAttribute(decorated, runLength1 + runLength2,
+  EXPECT_EQ(RunLengthForAttribute(decorated, run_length_1 + run_length_2,
                                   NSForegroundColorAttributeName),
-            runLength3);
-  EXPECT_TRUE(RunHasColor(decorated, runLength1 + runLength2, color_));
+            run_length_3);
+  EXPECT_TRUE(RunHasColor(decorated, run_length_1 + run_length_2, color_));
 
   // An unbolded font for the entire string.
   EXPECT_EQ(RunLengthForAttribute(decorated, 0U,
@@ -206,29 +231,28 @@
   EXPECT_FALSE(RunHasFontTrait(decorated, 0U, NSBoldFontMask));
 }
 
-// Test that the matched run gets bold-faced, but keeps the same
-// color.
+// Test that the matched run gets bold-faced, but keeps the same color.
 TEST_F(OmniboxPopupViewMacTest, DecorateMatchedStringMatch) {
   NSString* const string = @"This is a test";
   // Match "is".
-  const NSUInteger runLength1 = 5, runLength2 = 2, runLength3 = 7;
+  const NSUInteger run_length_1 = 5, run_length_2 = 2, run_length_3 = 7;
   // Make sure nobody messed up the inputs.
-  EXPECT_EQ(runLength1 + runLength2 + runLength3, [string length]);
+  EXPECT_EQ(run_length_1 + run_length_2 + run_length_3, [string length]);
 
   // Push each run onto classifications.
   AutocompleteMatch::ACMatchClassifications classifications;
   classifications.push_back(
       ACMatchClassification(0, ACMatchClassification::NONE));
   classifications.push_back(
-      ACMatchClassification(runLength1, ACMatchClassification::MATCH));
+      ACMatchClassification(run_length_1, ACMatchClassification::MATCH));
   classifications.push_back(
-      ACMatchClassification(runLength1 + runLength2,
+      ACMatchClassification(run_length_1 + run_length_2,
                             ACMatchClassification::NONE));
 
   NSAttributedString* decorated =
       OmniboxPopupViewMac::DecorateMatchedString(
           base::SysNSStringToUTF16(string), classifications,
-          color_, dimColor_, font_);
+          color_, dim_color_, font_);
 
   // Result has same characters as the input.
   EXPECT_EQ([decorated length], [string length]);
@@ -242,16 +266,16 @@
 
   // Should have three font runs, not bold, bold, then not bold again.
   EXPECT_EQ(RunLengthForAttribute(decorated, 0U,
-                                  NSFontAttributeName), runLength1);
+                                  NSFontAttributeName), run_length_1);
   EXPECT_FALSE(RunHasFontTrait(decorated, 0U, NSBoldFontMask));
 
-  EXPECT_EQ(RunLengthForAttribute(decorated, runLength1,
-                                  NSFontAttributeName), runLength2);
-  EXPECT_TRUE(RunHasFontTrait(decorated, runLength1, NSBoldFontMask));
+  EXPECT_EQ(RunLengthForAttribute(decorated, run_length_1,
+                                  NSFontAttributeName), run_length_2);
+  EXPECT_TRUE(RunHasFontTrait(decorated, run_length_1, NSBoldFontMask));
 
-  EXPECT_EQ(RunLengthForAttribute(decorated, runLength1 + runLength2,
-                                  NSFontAttributeName), runLength3);
-  EXPECT_FALSE(RunHasFontTrait(decorated, runLength1 + runLength2,
+  EXPECT_EQ(RunLengthForAttribute(decorated, run_length_1 + run_length_2,
+                                  NSFontAttributeName), run_length_3);
+  EXPECT_FALSE(RunHasFontTrait(decorated, run_length_1 + run_length_2,
                                NSBoldFontMask));
 }
 
@@ -259,24 +283,24 @@
 TEST_F(OmniboxPopupViewMacTest, DecorateMatchedStringURLMatch) {
   NSString* const string = @"http://hello.world/";
   // Match "hello".
-  const NSUInteger runLength1 = 7, runLength2 = 5, runLength3 = 7;
+  const NSUInteger run_length_1 = 7, run_length_2 = 5, run_length_3 = 7;
   // Make sure nobody messed up the inputs.
-  EXPECT_EQ(runLength1 + runLength2 + runLength3, [string length]);
+  EXPECT_EQ(run_length_1 + run_length_2 + run_length_3, [string length]);
 
   // Push each run onto classifications.
   AutocompleteMatch::ACMatchClassifications classifications;
   classifications.push_back(
       ACMatchClassification(0, ACMatchClassification::URL));
   const int kURLMatch = ACMatchClassification::URL|ACMatchClassification::MATCH;
-  classifications.push_back(ACMatchClassification(runLength1, kURLMatch));
+  classifications.push_back(ACMatchClassification(run_length_1, kURLMatch));
   classifications.push_back(
-      ACMatchClassification(runLength1 + runLength2,
+      ACMatchClassification(run_length_1 + run_length_2,
                             ACMatchClassification::URL));
 
   NSAttributedString* decorated =
       OmniboxPopupViewMac::DecorateMatchedString(
           base::SysNSStringToUTF16(string), classifications,
-          color_, dimColor_, font_);
+          color_, dim_color_, font_);
 
   // Result has same characters as the input.
   EXPECT_EQ([decorated length], [string length]);
@@ -290,16 +314,16 @@
 
   // Should have three font runs, not bold, bold, then not bold again.
   EXPECT_EQ(RunLengthForAttribute(decorated, 0U,
-                                  NSFontAttributeName), runLength1);
+                                  NSFontAttributeName), run_length_1);
   EXPECT_FALSE(RunHasFontTrait(decorated, 0U, NSBoldFontMask));
 
-  EXPECT_EQ(RunLengthForAttribute(decorated, runLength1,
-                                  NSFontAttributeName), runLength2);
-  EXPECT_TRUE(RunHasFontTrait(decorated, runLength1, NSBoldFontMask));
+  EXPECT_EQ(RunLengthForAttribute(decorated, run_length_1,
+                                  NSFontAttributeName), run_length_2);
+  EXPECT_TRUE(RunHasFontTrait(decorated, run_length_1, NSBoldFontMask));
 
-  EXPECT_EQ(RunLengthForAttribute(decorated, runLength1 + runLength2,
-                                  NSFontAttributeName), runLength3);
-  EXPECT_FALSE(RunHasFontTrait(decorated, runLength1 + runLength2,
+  EXPECT_EQ(RunLengthForAttribute(decorated, run_length_1 + run_length_2,
+                                  NSFontAttributeName), run_length_3);
+  EXPECT_FALSE(RunHasFontTrait(decorated, run_length_1 + run_length_2,
                                NSBoldFontMask));
 }
 
@@ -342,9 +366,9 @@
 TEST_F(OmniboxPopupViewMacTest, MatchTextContentsMatch) {
   NSString* const contents = @"This is a test";
   // Match "is".
-  const NSUInteger runLength1 = 5, runLength2 = 2, runLength3 = 7;
+  const NSUInteger run_length_1 = 5, run_length_2 = 2, run_length_3 = 7;
   // Make sure nobody messed up the inputs.
-  EXPECT_EQ(runLength1 + runLength2 + runLength3, [contents length]);
+  EXPECT_EQ(run_length_1 + run_length_2 + run_length_3, [contents length]);
 
   AutocompleteMatch m = MakeMatch(base::SysNSStringToUTF16(contents),
                                   string16());
@@ -353,9 +377,9 @@
   m.contents_class.push_back(
       ACMatchClassification(0, ACMatchClassification::NONE));
   m.contents_class.push_back(
-      ACMatchClassification(runLength1, ACMatchClassification::MATCH));
+      ACMatchClassification(run_length_1, ACMatchClassification::MATCH));
   m.contents_class.push_back(
-      ACMatchClassification(runLength1 + runLength2,
+      ACMatchClassification(run_length_1 + run_length_2,
                             ACMatchClassification::NONE));
 
   NSAttributedString* decorated =
@@ -372,16 +396,16 @@
 
   // Should have three font runs, not bold, bold, then not bold again.
   EXPECT_EQ(RunLengthForAttribute(decorated, 0U,
-                                  NSFontAttributeName), runLength1);
+                                  NSFontAttributeName), run_length_1);
   EXPECT_FALSE(RunHasFontTrait(decorated, 0U, NSBoldFontMask));
 
-  EXPECT_EQ(RunLengthForAttribute(decorated, runLength1,
-                                  NSFontAttributeName), runLength2);
-  EXPECT_TRUE(RunHasFontTrait(decorated, runLength1, NSBoldFontMask));
+  EXPECT_EQ(RunLengthForAttribute(decorated, run_length_1,
+                                  NSFontAttributeName), run_length_2);
+  EXPECT_TRUE(RunHasFontTrait(decorated, run_length_1, NSBoldFontMask));
 
-  EXPECT_EQ(RunLengthForAttribute(decorated, runLength1 + runLength2,
-                                  NSFontAttributeName), runLength3);
-  EXPECT_FALSE(RunHasFontTrait(decorated, runLength1 + runLength2,
+  EXPECT_EQ(RunLengthForAttribute(decorated, run_length_1 + run_length_2,
+                                  NSFontAttributeName), run_length_3);
+  EXPECT_FALSE(RunHasFontTrait(decorated, run_length_1 + run_length_2,
                                NSBoldFontMask));
 }
 
@@ -390,9 +414,9 @@
   NSString* const contents = @"This is a test";
   NSString* const description = @"That was a test";
   // Match "That was".
-  const NSUInteger runLength1 = 8, runLength2 = 7;
+  const NSUInteger run_length_1 = 8, run_length_2 = 7;
   // Make sure nobody messed up the inputs.
-  EXPECT_EQ(runLength1 + runLength2, [description length]);
+  EXPECT_EQ(run_length_1 + run_length_2, [description length]);
 
   AutocompleteMatch m = MakeMatch(base::SysNSStringToUTF16(contents),
                                   base::SysNSStringToUTF16(description));
@@ -401,7 +425,7 @@
   m.description_class.push_back(
       ACMatchClassification(0, ACMatchClassification::MATCH));
   m.description_class.push_back(
-      ACMatchClassification(runLength1, ACMatchClassification::NONE));
+      ACMatchClassification(run_length_1, ACMatchClassification::NONE));
 
   NSAttributedString* decorated =
       OmniboxPopupViewMac::MatchText(m, font_, kLargeWidth);
@@ -430,12 +454,12 @@
   EXPECT_FALSE(RunHasFontTrait(decorated, 0U, NSBoldFontMask));
 
   EXPECT_EQ(RunLengthForAttribute(decorated, descriptionLocation,
-                                  NSFontAttributeName), runLength1);
+                                  NSFontAttributeName), run_length_1);
   EXPECT_TRUE(RunHasFontTrait(decorated, descriptionLocation, NSBoldFontMask));
 
-  EXPECT_EQ(RunLengthForAttribute(decorated, descriptionLocation + runLength1,
-                                  NSFontAttributeName), runLength2);
-  EXPECT_FALSE(RunHasFontTrait(decorated, descriptionLocation + runLength1,
+  EXPECT_EQ(RunLengthForAttribute(decorated, descriptionLocation + run_length_1,
+                                  NSFontAttributeName), run_length_2);
+  EXPECT_FALSE(RunHasFontTrait(decorated, descriptionLocation + run_length_1,
                                NSBoldFontMask));
 }
 
@@ -449,7 +473,7 @@
   NSDictionary* attributes =
       [NSDictionary dictionaryWithObject:font_.GetNativeFont()
                                   forKey:NSFontAttributeName];
-  scoped_nsobject<NSMutableAttributedString> as(
+  base::scoped_nsobject<NSMutableAttributedString> as(
       [[NSMutableAttributedString alloc] initWithString:contents
                                              attributes:attributes]);
 
@@ -478,9 +502,9 @@
   NSString* const contents = @"This is a test with long contents";
   NSString* const description = @"That was a test";
   // Match "long".
-  const NSUInteger runLength1 = 20, runLength2 = 4, runLength3 = 9;
+  const NSUInteger run_length_1 = 20, run_length_2 = 4, run_length_3 = 9;
   // Make sure nobody messed up the inputs.
-  EXPECT_EQ(runLength1 + runLength2 + runLength3, [contents length]);
+  EXPECT_EQ(run_length_1 + run_length_2 + run_length_3, [contents length]);
 
   AutocompleteMatch m = MakeMatch(base::SysNSStringToUTF16(contents),
                                   base::SysNSStringToUTF16(description));
@@ -489,9 +513,9 @@
   m.contents_class.push_back(
       ACMatchClassification(0, ACMatchClassification::NONE));
   m.contents_class.push_back(
-      ACMatchClassification(runLength1, ACMatchClassification::MATCH));
+      ACMatchClassification(run_length_1, ACMatchClassification::MATCH));
   m.contents_class.push_back(
-      ACMatchClassification(runLength1 + runLength2,
+      ACMatchClassification(run_length_1 + run_length_2,
                             ACMatchClassification::URL));
 
   // Figure out the width of the contents.
@@ -519,7 +543,7 @@
   // values being passed to NSAttributedString.  Push the ellipsis
   // through part of each run to verify that we don't continue to see
   // such things.
-  while([commonPrefix length] > runLength1 - 3) {
+  while([commonPrefix length] > run_length_1 - 3) {
     EXPECT_GT(cellWidth, 0.0);
     cellWidth -= 1.0;
     decorated = OmniboxPopupViewMac::MatchText(m, font_, cellWidth);
@@ -529,24 +553,33 @@
   }
 }
 
-// TODO(shess): Test that
-// OmniboxPopupViewMac::UpdatePopupAppearance() creates/destroys
-// the popup according to result contents.  Test that the matrix gets
-// the right number of results.  Test the contents of the cells for
-// the right strings.  Icons?  Maybe, that seems harder to test.
-// Styling seems almost impossible.
+TEST_F(OmniboxPopupViewMacTest, UpdatePopupAppearance) {
+  base::scoped_nsobject<NSTextField> field(
+      [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 100, 20)]);
+  [[test_window() contentView] addSubview:field];
 
-// TODO(shess): Test that OmniboxPopupViewMac::PaintUpdatesNow()
-// updates the matrix selection.
+  OmniboxViewMac view(NULL, NULL, profile(), NULL, NULL);
+  MockOmniboxPopupViewMac popup_view(&view, view.model(), field);
 
-// TODO(shess): Test that OmniboxPopupViewMac::AcceptInput()
-// updates the model's selection from the matrix before returning.
-// Could possibly test that via -select:.
+  popup_view.UpdatePopupAppearance();
+  EXPECT_FALSE(popup_view.IsOpen());
+  EXPECT_EQ(0, [popup_view.matrix() numberOfRows]);
 
-// TODO(shess): Test that AutocompleteButtonCell returns the right
-// background colors for on, highlighted, and neither.
+  popup_view.SetResultCount(3);
+  popup_view.UpdatePopupAppearance();
+  EXPECT_TRUE(popup_view.IsOpen());
+  EXPECT_EQ(3, [popup_view.matrix() numberOfRows]);
 
-// TODO(shess): Test that AutocompleteMatrixTarget can be initialized
-// and then sends -select: to the view.
+  int old_height = popup_view.GetTargetBounds().height();
+  popup_view.SetResultCount(5);
+  popup_view.UpdatePopupAppearance();
+  EXPECT_GT(popup_view.GetTargetBounds().height(), old_height);
+  EXPECT_EQ(5, [popup_view.matrix() numberOfRows]);
+
+  popup_view.SetResultCount(0);
+  popup_view.UpdatePopupAppearance();
+  EXPECT_FALSE(popup_view.IsOpen());
+  EXPECT_EQ(0, [popup_view.matrix() numberOfRows]);
+}
 
 }  // namespace
diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.mm b/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.mm
index 03a7df3..7a2ce85 100644
--- a/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.mm
+++ b/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.mm
@@ -13,7 +13,6 @@
 #include "chrome/browser/autocomplete/autocomplete_input.h"
 #include "chrome/browser/autocomplete/autocomplete_match.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/search/search.h"
 #include "chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_cell.h"
 #import "chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_editor.h"
 #include "chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.h"
@@ -139,8 +138,11 @@
                                CommandUpdater* command_updater,
                                AutocompleteTextField* field)
     : OmniboxView(profile, controller, toolbar_model, command_updater),
-      popup_view_(OmniboxPopupViewMac::Create(this, model(), field)),
+      popup_view_(new OmniboxPopupViewMac(this, model(), field)),
       field_(field),
+      saved_temporary_selection_(NSMakeRange(0, 0)),
+      selection_before_change_(NSMakeRange(0, 0)),
+      marked_range_before_change_(NSMakeRange(0, 0)),
       delete_was_pressed_(false),
       delete_at_end_pressed_(false) {
   [field_ setObserver:this];
@@ -149,8 +151,8 @@
   [field_ setAllowsEditingTextAttributes:YES];
 
   // Get the appropriate line height for the font that we use.
-  scoped_nsobject<NSLayoutManager>
-      layoutManager([[NSLayoutManager alloc] init]);
+  base::scoped_nsobject<NSLayoutManager> layoutManager(
+      [[NSLayoutManager alloc] init]);
   [layoutManager setUsesScreenFonts:YES];
 }
 
@@ -435,8 +437,8 @@
 
   // Make a paragraph style locking in the standard line height as the maximum,
   // otherwise the baseline may shift "downwards".
-  scoped_nsobject<NSMutableParagraphStyle>
-      paragraph_style([[NSMutableParagraphStyle alloc] init]);
+  base::scoped_nsobject<NSMutableParagraphStyle> paragraph_style(
+      [[NSMutableParagraphStyle alloc] init]);
   CGFloat line_height = [[field_ cell] lineHeight];
   [paragraph_style setMaximumLineHeight:line_height];
   [paragraph_style setMinimumLineHeight:line_height];
@@ -665,16 +667,12 @@
   }
 
   if (model()->popup_model()->IsOpen()) {
-    // If instant extended is enabled then allow users to press tab to select
-    // results from the omnibox popup.
-    BOOL enableTabAutocomplete = chrome::IsInstantExtendedAPIEnabled();
-
     if (cmd == @selector(insertBacktab:)) {
       if (model()->popup_model()->selected_line_state() ==
             OmniboxPopupModel::KEYWORD) {
         model()->ClearKeyword(GetText());
         return true;
-      } else if (enableTabAutocomplete) {
+      } else {
         model()->OnUpOrDownKeyPressed(-1);
         return true;
       }
@@ -682,7 +680,7 @@
 
     if ((cmd == @selector(insertTab:) ||
         cmd == @selector(insertTabIgnoringFieldEditor:)) &&
-        !model()->is_keyword_hint() && enableTabAutocomplete) {
+        !model()->is_keyword_hint()) {
       model()->OnUpOrDownKeyPressed(1);
       return true;
     }
@@ -902,7 +900,6 @@
   // things even cheaper by refactoring between the popup-placement
   // code and the matrix-population code.
   popup_view_->UpdatePopupAppearance();
-  model()->OnPopupBoundsChanged(popup_view_->GetTargetBounds());
 
   // Give controller a chance to rearrange decorations.
   model()->OnChanged();
@@ -953,11 +950,8 @@
 // static
 NSFont* OmniboxViewMac::GetFieldFont() {
   // This value should be kept in sync with InstantPage::InitializeFonts.
-  if (chrome::IsInstantExtendedAPIEnabled())
-    return [NSFont fontWithName:@"Helvetica Neue" size:16];
-
   ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-  return rb.GetFont(ResourceBundle::BaseFont).GetNativeFont();
+  return rb.GetFont(ResourceBundle::BaseFont).DeriveFont(1).GetNativeFont();
 }
 
 int OmniboxViewMac::GetOmniboxTextLength() const {
diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac_unittest.mm b/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac_unittest.mm
index 308d065..e9d77a3 100644
--- a/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac_unittest.mm
+++ b/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac_unittest.mm
@@ -146,7 +146,7 @@
 
 TEST_F(OmniboxViewMacTest, SetInstantSuggestion) {
   const NSRect frame = NSMakeRect(0, 0, 50, 30);
-  scoped_nsobject<AutocompleteTextField> field(
+  base::scoped_nsobject<AutocompleteTextField> field(
       [[AutocompleteTextField alloc] initWithFrame:frame]);
 
   TestingToolbarModelDelegate delegate;
diff --git a/chrome/browser/ui/cocoa/one_click_signin_bubble_controller.h b/chrome/browser/ui/cocoa/one_click_signin_bubble_controller.h
index 4676267..5298ef0 100644
--- a/chrome/browser/ui/cocoa/one_click_signin_bubble_controller.h
+++ b/chrome/browser/ui/cocoa/one_click_signin_bubble_controller.h
@@ -8,7 +8,7 @@
 #import <Cocoa/Cocoa.h>
 
 #include "base/callback.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/ui/browser_window.h"
 #import "chrome/browser/ui/cocoa/base_bubble_controller.h"
 
@@ -17,7 +17,7 @@
 
 // Displays the one-click signin confirmation bubble
 @interface OneClickSigninBubbleController : BaseBubbleController {
-  scoped_nsobject<OneClickSigninViewController> viewController_;
+  base::scoped_nsobject<OneClickSigninViewController> viewController_;
  @private
    IBOutlet NSTextField* messageTextField_;
 }
diff --git a/chrome/browser/ui/cocoa/one_click_signin_bubble_controller.mm b/chrome/browser/ui/cocoa/one_click_signin_bubble_controller.mm
index 6126103..a3d97fa 100644
--- a/chrome/browser/ui/cocoa/one_click_signin_bubble_controller.mm
+++ b/chrome/browser/ui/cocoa/one_click_signin_bubble_controller.mm
@@ -44,7 +44,7 @@
 
   // Create an empty window into which content is placed.
   NSRect viewBounds = [[viewController_ view] bounds];
-  scoped_nsobject<InfoBubbleWindow> window(
+  base::scoped_nsobject<InfoBubbleWindow> window(
       [[InfoBubbleWindow alloc] initWithContentRect:viewBounds
                                           styleMask:NSBorderlessWindowMask
                                             backing:NSBackingStoreBuffered
diff --git a/chrome/browser/ui/cocoa/one_click_signin_bubble_controller_browsertest.mm b/chrome/browser/ui/cocoa/one_click_signin_bubble_controller_browsertest.mm
index 1d4db26..0387770 100644
--- a/chrome/browser/ui/cocoa/one_click_signin_bubble_controller_browsertest.mm
+++ b/chrome/browser/ui/cocoa/one_click_signin_bubble_controller_browsertest.mm
@@ -39,7 +39,7 @@
                 [[controller_ viewController] nibName]);
   }
 
-  scoped_nsobject<OneClickSigninBubbleController> controller_;
+  base::scoped_nsobject<OneClickSigninBubbleController> controller_;
   int callback_count_;
 
  private:
diff --git a/chrome/browser/ui/cocoa/one_click_signin_bubble_controller_unittest.mm b/chrome/browser/ui/cocoa/one_click_signin_bubble_controller_unittest.mm
index 86ac826..a60e3a2 100644
--- a/chrome/browser/ui/cocoa/one_click_signin_bubble_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/one_click_signin_bubble_controller_unittest.mm
@@ -8,12 +8,12 @@
 
 #include "base/bind.h"
 #include "base/compiler_specific.h"
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #include "base/memory/weak_ptr.h"
 #import "chrome/browser/ui/cocoa/browser_window_cocoa.h"
 #include "chrome/browser/ui/cocoa/cocoa_profile_test.h"
-#include "chrome/browser/ui/sync/one_click_signin_sync_starter.h"
 #import "chrome/browser/ui/cocoa/one_click_signin_view_controller.h"
+#include "chrome/browser/ui/sync/one_click_signin_sync_starter.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #import "testing/gtest_mac.h"
@@ -54,7 +54,7 @@
  protected:
   base::WeakPtrFactory<OneClickSigninBubbleControllerTest> weak_ptr_factory_;
   BrowserWindow::StartSyncCallback start_sync_callback_;
-  scoped_nsobject<OneClickSigninBubbleController> controller_;
+  base::scoped_nsobject<OneClickSigninBubbleController> controller_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(OneClickSigninBubbleControllerTest);
diff --git a/chrome/browser/ui/cocoa/one_click_signin_dialog_controller.h b/chrome/browser/ui/cocoa/one_click_signin_dialog_controller.h
index 2cfa36b..4a7f082 100644
--- a/chrome/browser/ui/cocoa/one_click_signin_dialog_controller.h
+++ b/chrome/browser/ui/cocoa/one_click_signin_dialog_controller.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/cocoa/constrained_window/constrained_window_mac.h"
@@ -40,7 +40,7 @@
   void PerformClose();
 
   scoped_ptr<ConstrainedWindowMac> constrained_window_;
-  scoped_nsobject<OneClickSigninViewController> view_controller_;
+  base::scoped_nsobject<OneClickSigninViewController> view_controller_;
 };
 
 #endif  // CHROME_BROWSER_UI_COCOA_ONE_CLICK_SIGNIN_DIALOG_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/one_click_signin_dialog_controller.mm b/chrome/browser/ui/cocoa/one_click_signin_dialog_controller.mm
index 00b5a08..6078a50 100644
--- a/chrome/browser/ui/cocoa/one_click_signin_dialog_controller.mm
+++ b/chrome/browser/ui/cocoa/one_click_signin_dialog_controller.mm
@@ -22,13 +22,12 @@
         closeCallback:close_callback
          isSyncDialog:YES
          errorMessage:nil]);
-  scoped_nsobject<NSWindow> window([[ConstrainedWindowCustomWindow alloc]
+  base::scoped_nsobject<NSWindow> window([[ConstrainedWindowCustomWindow alloc]
       initWithContentRect:[[view_controller_ view] bounds]]);
   [[window contentView] addSubview:[view_controller_ view]];
 
-  scoped_nsobject<CustomConstrainedWindowSheet> sheet(
-      [[CustomConstrainedWindowSheet alloc]
-          initWithCustomWindow:window]);
+  base::scoped_nsobject<CustomConstrainedWindowSheet> sheet(
+      [[CustomConstrainedWindowSheet alloc] initWithCustomWindow:window]);
   constrained_window_.reset(new ConstrainedWindowMac(
       this, web_contents, sheet));
 }
diff --git a/chrome/browser/ui/cocoa/one_click_signin_view_controller.h b/chrome/browser/ui/cocoa/one_click_signin_view_controller.h
index 004ed34..02d71ae 100644
--- a/chrome/browser/ui/cocoa/one_click_signin_view_controller.h
+++ b/chrome/browser/ui/cocoa/one_click_signin_view_controller.h
@@ -8,7 +8,7 @@
 #import <Cocoa/Cocoa.h>
 
 #include "base/callback.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/ui/browser_window.h"
 
 @class BrowserWindowController;
@@ -31,13 +31,13 @@
   // This is YES if the user clicked the Learn More link before another action.
   BOOL clickedLearnMore_;
 
-  scoped_nsobject<NSString> errorMessage_;
+  base::scoped_nsobject<NSString> errorMessage_;
 
   // Text fields don't work as well with embedded links as text views, but
   // text views cannot conveniently be created in IB. The xib file contains
   // a text field |informativePlaceholderTextField_| that's replaced by this
   // text view |promo_| in -awakeFromNib.
-  scoped_nsobject<HyperlinkTextView> informativeTextView_;
+  base::scoped_nsobject<HyperlinkTextView> informativeTextView_;
   BrowserWindow::StartSyncCallback startSyncCallback_;
   base::Closure closeCallback_;
   content::WebContents* webContents_;
diff --git a/chrome/browser/ui/cocoa/panels/panel_cocoa_unittest.mm b/chrome/browser/ui/cocoa/panels/panel_cocoa_unittest.mm
index b0eda33..a817812 100644
--- a/chrome/browser/ui/cocoa/panels/panel_cocoa_unittest.mm
+++ b/chrome/browser/ui/cocoa/panels/panel_cocoa_unittest.mm
@@ -296,7 +296,7 @@
 TEST_F(PanelCocoaTest, MenuItems) {
   Panel* panel = CreateTestPanel("Test Panel");
 
-  scoped_nsobject<NSMenu> menu([[NSMenu alloc] initWithTitle:@""]);
+  base::scoped_nsobject<NSMenu> menu([[NSMenu alloc] initWithTitle:@""]);
   NSMenuItem* close_tab_menu_item = CreateMenuItem(menu, IDC_CLOSE_TAB);
   NSMenuItem* new_tab_menu_item = CreateMenuItem(menu, IDC_NEW_TAB);
   NSMenuItem* new_tab_window_item = CreateMenuItem(menu, IDC_NEW_WINDOW);
diff --git a/chrome/browser/ui/cocoa/panels/panel_stack_window_cocoa.h b/chrome/browser/ui/cocoa/panels/panel_stack_window_cocoa.h
index 35824de..442044c 100644
--- a/chrome/browser/ui/cocoa/panels/panel_stack_window_cocoa.h
+++ b/chrome/browser/ui/cocoa/panels/panel_stack_window_cocoa.h
@@ -11,7 +11,7 @@
 #include <map>
 
 #include "base/basictypes.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #include "chrome/browser/ui/panels/native_panel_stack_window.h"
 #include "ui/gfx/rect.h"
@@ -70,7 +70,7 @@
   NativePanelStackWindowDelegate* delegate_;
 
   // The underlying window.
-  scoped_nsobject<NSWindow> window_;
+  base::scoped_nsobject<NSWindow> window_;
 
   Panels panels_;
 
@@ -85,7 +85,8 @@
   // Used to animate the bounds changes at a synchronized pace.
   // Lifetime controlled manually, needs more than just |release| to terminate.
   NSViewAnimation* bounds_animation_;
-  scoped_nsobject<BatchBoundsAnimationDelegate> bounds_animation_delegate_;
+  base::scoped_nsobject<BatchBoundsAnimationDelegate>
+      bounds_animation_delegate_;
 
   DISALLOW_COPY_AND_ASSIGN(PanelStackWindowCocoa);
 };
diff --git a/chrome/browser/ui/cocoa/panels/panel_stack_window_cocoa.mm b/chrome/browser/ui/cocoa/panels/panel_stack_window_cocoa.mm
index ee2045d..90ba6e0 100644
--- a/chrome/browser/ui/cocoa/panels/panel_stack_window_cocoa.mm
+++ b/chrome/browser/ui/cocoa/panels/panel_stack_window_cocoa.mm
@@ -226,7 +226,7 @@
   int num_of_animations = 1;
   if (need_to_animate_individual_panels)
     num_of_animations += bounds_updates_.size();
-  scoped_nsobject<NSMutableArray> animations(
+  base::scoped_nsobject<NSMutableArray> animations(
       [[NSMutableArray alloc] initWithCapacity:num_of_animations]);
 
   // Add the animation for each panel in the update list.
diff --git a/chrome/browser/ui/cocoa/panels/panel_titlebar_view_cocoa.h b/chrome/browser/ui/cocoa/panels/panel_titlebar_view_cocoa.h
index e353fb4..dc139e5 100644
--- a/chrome/browser/ui/cocoa/panels/panel_titlebar_view_cocoa.h
+++ b/chrome/browser/ui/cocoa/panels/panel_titlebar_view_cocoa.h
@@ -61,12 +61,12 @@
   BOOL isDrawingAttention_;
 
   // "Glint" animation is used in "Draw Attention" mode.
-  scoped_nsobject<RepaintAnimation> glintAnimation_;
-  scoped_nsobject<NSTimer> glintAnimationTimer_;
+  base::scoped_nsobject<RepaintAnimation> glintAnimation_;
+  base::scoped_nsobject<NSTimer> glintAnimationTimer_;
   int glintCounter_;
 
   // Drag support.
-  scoped_nsobject<MouseDragController> dragController_;
+  base::scoped_nsobject<MouseDragController> dragController_;
 }
 
 // Callbacks from Close, Minimize, and Restore buttons.
diff --git a/chrome/browser/ui/cocoa/panels/panel_titlebar_view_cocoa.mm b/chrome/browser/ui/cocoa/panels/panel_titlebar_view_cocoa.mm
index 673e628..3a9dde6 100644
--- a/chrome/browser/ui/cocoa/panels/panel_titlebar_view_cocoa.mm
+++ b/chrome/browser/ui/cocoa/panels/panel_titlebar_view_cocoa.mm
@@ -146,7 +146,7 @@
     NSRectFillUsingOperation([self bounds], NSCompositeSourceOver);
 
     if ([glintAnimation_ isAnimating]) {
-      scoped_nsobject<NSGradient> glint([NSGradient alloc]);
+      base::scoped_nsobject<NSGradient> glint([NSGradient alloc]);
       float currentAlpha = 0.8 * [glintAnimation_ currentValue];
       NSColor* startColor = [NSColor colorWithCalibratedWhite:1.0
                                                         alpha:currentAlpha];
@@ -406,6 +406,8 @@
 
   if ([event clickCount] == 1)
     [controller_ onTitlebarMouseClicked:[event modifierFlags]];
+  else if ([event clickCount] == 2)
+    [controller_ minimizeButtonClicked:[event modifierFlags]];
 }
 
 - (void)mouseDragged:(NSEvent*)event {
diff --git a/chrome/browser/ui/cocoa/panels/panel_window_controller_cocoa.h b/chrome/browser/ui/cocoa/panels/panel_window_controller_cocoa.h
index 3e8bc57..6627170 100644
--- a/chrome/browser/ui/cocoa/panels/panel_window_controller_cocoa.h
+++ b/chrome/browser/ui/cocoa/panels/panel_window_controller_cocoa.h
@@ -11,7 +11,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #import "chrome/browser/ui/cocoa/chrome_browser_window.h"
 #include "chrome/browser/ui/panels/panel.h"
@@ -29,7 +29,7 @@
  @private
   IBOutlet PanelTitlebarViewCocoa* titlebar_view_;
   scoped_ptr<PanelCocoa> windowShim_;
-  scoped_nsobject<NSString> pendingWindowTitle_;
+  base::scoped_nsobject<NSString> pendingWindowTitle_;
   NSViewAnimation* boundsAnimation_;  // Lifetime controlled manually, needs
                                       // more then just |release| to terminate.
   BOOL animateOnBoundsChange_;
@@ -42,7 +42,7 @@
   // window over other application windows due to panels having a higher
   // priority NSWindowLevel, so we distinguish between the two scenarios.
   BOOL activationRequestedByPanel_;
-  scoped_nsobject<NSView> overlayView_;
+  base::scoped_nsobject<NSView> overlayView_;
 }
 
 // Load the window nib and do any Cocoa-specific initialization.
diff --git a/chrome/browser/ui/cocoa/panels/panel_window_controller_cocoa.mm b/chrome/browser/ui/cocoa/panels/panel_window_controller_cocoa.mm
index c335faa..3d3dbe8 100644
--- a/chrome/browser/ui/cocoa/panels/panel_window_controller_cocoa.mm
+++ b/chrome/browser/ui/cocoa/panels/panel_window_controller_cocoa.mm
@@ -94,6 +94,10 @@
       [[app windows] count] == static_cast<NSUInteger>([controller numPanels]);
 }
 
+- (void)performMiniaturize:(id)sender {
+  [[self windowController] minimizeButtonClicked:0];
+}
+
 // Ignore key events if window cannot become key window to fix problem
 // where keyboard input is still going into a minimized panel even though
 // the app has been deactivated in -[PanelWindowControllerCocoa deactivate:].
@@ -112,12 +116,12 @@
 @interface PanelResizeByMouseOverlay : NSView <MouseDragControllerClient> {
  @private
    Panel* panel_;
-   scoped_nsobject<MouseDragController> dragController_;
-   scoped_nsobject<NSCursor> dragCursor_;
-   scoped_nsobject<NSCursor> eastWestCursor_;
-   scoped_nsobject<NSCursor> northSouthCursor_;
-   scoped_nsobject<NSCursor> northEastSouthWestCursor_;
-   scoped_nsobject<NSCursor> northWestSouthEastCursor_;
+   base::scoped_nsobject<MouseDragController> dragController_;
+   base::scoped_nsobject<NSCursor> dragCursor_;
+   base::scoped_nsobject<NSCursor> eastWestCursor_;
+   base::scoped_nsobject<NSCursor> northSouthCursor_;
+   base::scoped_nsobject<NSCursor> northEastSouthWestCursor_;
+   base::scoped_nsobject<NSCursor> northWestSouthEastCursor_;
    NSRect leftCursorRect_;
    NSRect rightCursorRect_;
    NSRect topCursorRect_;
diff --git a/chrome/browser/ui/cocoa/presentation_mode_controller.h b/chrome/browser/ui/cocoa/presentation_mode_controller.h
index 728c2da..8af03b4 100644
--- a/chrome/browser/ui/cocoa/presentation_mode_controller.h
+++ b/chrome/browser/ui/cocoa/presentation_mode_controller.h
@@ -45,16 +45,16 @@
   // hidden, we still need to keep a 1px tall tracking area visible.  Attaching
   // to the content view allows us to do this.  |trackingArea_| can be nil if
   // not in presentation mode or during animations.
-  scoped_nsobject<NSTrackingArea> trackingArea_;
+  base::scoped_nsobject<NSTrackingArea> trackingArea_;
 
   // Pointer to the currently running animation.  Is nil if no animation is
   // running.
-  scoped_nsobject<DropdownAnimation> currentAnimation_;
+  base::scoped_nsobject<DropdownAnimation> currentAnimation_;
 
   // Timers for scheduled showing/hiding of the bar (which are always done with
   // animation).
-  scoped_nsobject<NSTimer> showTimer_;
-  scoped_nsobject<NSTimer> hideTimer_;
+  base::scoped_nsobject<NSTimer> showTimer_;
+  base::scoped_nsobject<NSTimer> hideTimer_;
 
   // Holds the current bounds of |trackingArea_|, even if |trackingArea_| is
   // currently nil.  Used to restore the tracking area when an animation
diff --git a/chrome/browser/ui/cocoa/presentation_mode_controller.mm b/chrome/browser/ui/cocoa/presentation_mode_controller.mm
index 8b11839..ccba724 100644
--- a/chrome/browser/ui/cocoa/presentation_mode_controller.mm
+++ b/chrome/browser/ui/cocoa/presentation_mode_controller.mm
@@ -53,7 +53,7 @@
 // duration may be less than |fullDuration|.
 - (id)initWithFraction:(CGFloat)fromFraction
           fullDuration:(CGFloat)fullDuration
-        animationCurve:(NSInteger)animationCurve
+        animationCurve:(NSAnimationCurve)animationCurve
             controller:(PresentationModeController*)controller;
 
 @end
@@ -65,7 +65,7 @@
 
 - (id)initWithFraction:(CGFloat)toFraction
           fullDuration:(CGFloat)fullDuration
-        animationCurve:(NSInteger)animationCurve
+        animationCurve:(NSAnimationCurve)animationCurve
             controller:(PresentationModeController*)controller {
   // Calculate the effective duration, based on the current shown fraction.
   DCHECK(controller);
diff --git a/chrome/browser/ui/cocoa/profile_menu_controller.h b/chrome/browser/ui/cocoa/profile_menu_controller.h
index 1610fa6..d7e552b 100644
--- a/chrome/browser/ui/cocoa/profile_menu_controller.h
+++ b/chrome/browser/ui/cocoa/profile_menu_controller.h
@@ -7,7 +7,6 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 
 class AvatarMenuModel;
diff --git a/chrome/browser/ui/cocoa/profile_menu_controller.mm b/chrome/browser/ui/cocoa/profile_menu_controller.mm
index 4f08ec4..f1ee54e 100644
--- a/chrome/browser/ui/cocoa/profile_menu_controller.mm
+++ b/chrome/browser/ui/cocoa/profile_menu_controller.mm
@@ -4,6 +4,7 @@
 
 #import "chrome/browser/ui/cocoa/profile_menu_controller.h"
 
+#include "base/mac/scoped_nsobject.h"
 #include "base/strings/sys_string_conversions.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/avatar_menu_model.h"
@@ -66,8 +67,7 @@
   if ((self = [super init])) {
     mainMenuItem_ = item;
 
-    scoped_nsobject<NSMenu> menu(
-        [[NSMenu alloc] initWithTitle:
+    base::scoped_nsobject<NSMenu> menu([[NSMenu alloc] initWithTitle:
             l10n_util::GetNSStringWithFixup(IDS_PROFILES_OPTIONS_GROUP_NAME)]);
     [mainMenuItem_ setSubmenu:menu];
 
@@ -110,7 +110,7 @@
   if (dock) {
     NSString* headerName =
         l10n_util::GetNSStringWithFixup(IDS_PROFILES_OPTIONS_GROUP_NAME);
-    scoped_nsobject<NSMenuItem> header(
+    base::scoped_nsobject<NSMenuItem> header(
         [[NSMenuItem alloc] initWithTitle:headerName
                                    action:NULL
                             keyEquivalent:@""]);
@@ -213,7 +213,7 @@
 }
 
 - (NSMenuItem*)createItemWithTitle:(NSString*)title action:(SEL)sel {
-  scoped_nsobject<NSMenuItem> item(
+  base::scoped_nsobject<NSMenuItem> item(
       [[NSMenuItem alloc] initWithTitle:title action:sel keyEquivalent:@""]);
   [item setTarget:self];
   return [item.release() autorelease];
diff --git a/chrome/browser/ui/cocoa/profile_menu_controller_unittest.mm b/chrome/browser/ui/cocoa/profile_menu_controller_unittest.mm
index 06f22b3..a0b001c 100644
--- a/chrome/browser/ui/cocoa/profile_menu_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/profile_menu_controller_unittest.mm
@@ -4,7 +4,7 @@
 
 #import "chrome/browser/ui/cocoa/profile_menu_controller.h"
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/threading/thread_restrictions.h"
 #include "chrome/browser/profiles/avatar_menu_model.h"
 #include "chrome/browser/profiles/profile_manager.h"
@@ -71,8 +71,8 @@
   NSMenuItem* menu_item() { return item_.get(); }
 
  private:
-  scoped_nsobject<NSMenuItem> item_;
-  scoped_nsobject<ProfileMenuController> controller_;
+  base::scoped_nsobject<NSMenuItem> item_;
+  base::scoped_nsobject<ProfileMenuController> controller_;
 };
 
 TEST_F(ProfileMenuControllerTest, InitializeMenu) {
@@ -124,7 +124,7 @@
 }
 
 TEST_F(ProfileMenuControllerTest, InsertItems) {
-  scoped_nsobject<NSMenu> menu([[NSMenu alloc] initWithTitle: @""]);
+  base::scoped_nsobject<NSMenu> menu([[NSMenu alloc] initWithTitle:@""]);
   ASSERT_EQ(0, [menu numberOfItems]);
 
   // With only one profile, insertItems should be a no-op.
@@ -197,8 +197,7 @@
   ASSERT_EQ(7, [menu numberOfItems]);
 
   // Create a browser and "show" it.
-  Browser::CreateParams profile2_params(profile2,
-                                        chrome::HOST_DESKTOP_TYPE_NATIVE);
+  Browser::CreateParams profile2_params(profile2, chrome::GetActiveDesktop());
   scoped_ptr<Browser> p2_browser(
       chrome::CreateBrowserWithTestWindowForParams(&profile2_params));
   BrowserList::SetLastActive(p2_browser.get());
@@ -209,8 +208,7 @@
   VerifyProfileNamedIsActive(@"Profile 2", __LINE__);
 
   // Open a new browser and make sure it takes effect.
-  Browser::CreateParams profile3_params(profile3,
-                                        chrome::HOST_DESKTOP_TYPE_NATIVE);
+  Browser::CreateParams profile3_params(profile3, chrome::GetActiveDesktop());
   scoped_ptr<Browser> p3_browser(
       chrome::CreateBrowserWithTestWindowForParams(&profile3_params));
   BrowserList::SetLastActive(p3_browser.get());
diff --git a/chrome/browser/ui/cocoa/profile_signin_confirmation_dialog_cocoa.h b/chrome/browser/ui/cocoa/profile_signin_confirmation_dialog_cocoa.h
index 561c0d6..227840e 100644
--- a/chrome/browser/ui/cocoa/profile_signin_confirmation_dialog_cocoa.h
+++ b/chrome/browser/ui/cocoa/profile_signin_confirmation_dialog_cocoa.h
@@ -11,7 +11,7 @@
 
 #include "base/callback.h"
 #include "base/compiler_specific.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/ui/cocoa/constrained_window/constrained_window_mac.h"
@@ -49,7 +49,7 @@
   virtual void OnConstrainedWindowClosed(ConstrainedWindowMac* window) OVERRIDE;
 
   // Controller for the dialog view.
-  scoped_nsobject<ProfileSigninConfirmationViewController> controller_;
+  base::scoped_nsobject<ProfileSigninConfirmationViewController> controller_;
 
   // The constrained window that contains the dialog view.
   scoped_ptr<ConstrainedWindowMac> window_;
diff --git a/chrome/browser/ui/cocoa/profile_signin_confirmation_dialog_cocoa.mm b/chrome/browser/ui/cocoa/profile_signin_confirmation_dialog_cocoa.mm
index 44fb43f..c1c8a49 100644
--- a/chrome/browser/ui/cocoa/profile_signin_confirmation_dialog_cocoa.mm
+++ b/chrome/browser/ui/cocoa/profile_signin_confirmation_dialog_cocoa.mm
@@ -72,13 +72,11 @@
      offerProfileCreation:offer_profile_creation]);
 
   // Setup the constrained window that will show the view.
-  scoped_nsobject<NSWindow> window(
-      [[ConstrainedWindowCustomWindow alloc]
-          initWithContentRect:[[controller_ view] bounds]]);
+  base::scoped_nsobject<NSWindow> window([[ConstrainedWindowCustomWindow alloc]
+      initWithContentRect:[[controller_ view] bounds]]);
   [[window contentView] addSubview:[controller_ view]];
-  scoped_nsobject<CustomConstrainedWindowSheet> sheet(
-      [[CustomConstrainedWindowSheet alloc]
-          initWithCustomWindow:window]);
+  base::scoped_nsobject<CustomConstrainedWindowSheet> sheet(
+      [[CustomConstrainedWindowSheet alloc] initWithCustomWindow:window]);
   window_.reset(new ConstrainedWindowMac(this, web_contents, sheet));
 }
 
diff --git a/chrome/browser/ui/cocoa/profile_signin_confirmation_view_controller.h b/chrome/browser/ui/cocoa/profile_signin_confirmation_view_controller.h
index 2b9f2d1..ffde5c4 100644
--- a/chrome/browser/ui/cocoa/profile_signin_confirmation_view_controller.h
+++ b/chrome/browser/ui/cocoa/profile_signin_confirmation_view_controller.h
@@ -9,7 +9,7 @@
 #include <string>
 
 #include "base/callback.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/ui/cocoa/constrained_window/constrained_window_button.h"
 
 @class HyperlinkTextView;
@@ -38,14 +38,14 @@
   base::Closure closeDialogCallback_;
 
   // UI elements.
-  scoped_nsobject<NSBox> promptBox_;
-  scoped_nsobject<NSButton> closeButton_;
-  scoped_nsobject<NSTextField> titleField_;
-  scoped_nsobject<NSTextField> promptField_;
-  scoped_nsobject<NSTextView> explanationField_;
-  scoped_nsobject<NSButton> createProfileLinkField_;
-  scoped_nsobject<ConstrainedWindowButton> cancelButton_;
-  scoped_nsobject<ConstrainedWindowButton> okButton_;
+  base::scoped_nsobject<NSBox> promptBox_;
+  base::scoped_nsobject<NSButton> closeButton_;
+  base::scoped_nsobject<NSTextField> titleField_;
+  base::scoped_nsobject<NSTextField> promptField_;
+  base::scoped_nsobject<NSTextView> explanationField_;
+  base::scoped_nsobject<ConstrainedWindowButton> createProfileButton_;
+  base::scoped_nsobject<ConstrainedWindowButton> cancelButton_;
+  base::scoped_nsobject<ConstrainedWindowButton> okButton_;
 }
 
 - (id)initWithBrowser:(Browser*)browser
@@ -63,7 +63,7 @@
 @interface ProfileSigninConfirmationViewController (TestingAPI)
 
 @property(readonly, nonatomic) ui::ProfileSigninConfirmationDelegate* delegate;
-@property(readonly, nonatomic) NSButton* createProfileLinkField;
+@property(readonly, nonatomic) NSButton* createProfileButton;
 @property(readonly, nonatomic) NSTextView* explanationField;
 
 @end
diff --git a/chrome/browser/ui/cocoa/profile_signin_confirmation_view_controller.mm b/chrome/browser/ui/cocoa/profile_signin_confirmation_view_controller.mm
index e6d6d77..367556b 100644
--- a/chrome/browser/ui/cocoa/profile_signin_confirmation_view_controller.mm
+++ b/chrome/browser/ui/cocoa/profile_signin_confirmation_view_controller.mm
@@ -59,7 +59,7 @@
 
 // Make the indicated range of characters in a text view bold.
 void MakeTextBold(NSTextField* textField, int offset, int length) {
-  scoped_nsobject<NSMutableAttributedString> text(
+  base::scoped_nsobject<NSMutableAttributedString> text(
       [[textField attributedStringValue] mutableCopy]);
   NSFont* currentFont =
       [text attribute:NSFontAttributeName
@@ -96,7 +96,7 @@
     const string16& link,
     int offset,
     const ui::ResourceBundle::FontStyle& font_style) {
-  scoped_nsobject<HyperlinkTextView> textView(
+  base::scoped_nsobject<HyperlinkTextView> textView(
       [[HyperlinkTextView alloc] initWithFrame:NSZeroRect]);
   NSFont* font = ui::ResourceBundle::GetSharedInstance().GetFont(
       font_style).GetNativeFont();
@@ -182,6 +182,10 @@
       [[ConstrainedWindowButton alloc] initWithFrame:NSZeroRect]);
   okButton_.reset(
       [[ConstrainedWindowButton alloc] initWithFrame:NSZeroRect]);
+  if (offerProfileCreation_) {
+    createProfileButton_.reset(
+        [[ConstrainedWindowButton alloc] initWithFrame:NSZeroRect]);
+  }
   promptBox_.reset(
       [[NSBox alloc] initWithFrame:NSZeroRect]);
   closeButton_.reset(
@@ -229,13 +233,11 @@
 
   // Create Profile link.
   if (offerProfileCreation_) {
-    createProfileLinkField_.reset(
-        [AddLinkButton([self view],
-                       l10n_util::GetStringUTF16(
-                           IDS_ENTERPRISE_SIGNIN_CREATE_NEW_PROFILE_NEW_STYLE),
-                       self,
-                       @selector(createProfile:)) retain]);
-    [createProfileLinkField_ sizeToFit];
+    [self addButton:createProfileButton_
+          withTitle:IDS_ENTERPRISE_SIGNIN_CREATE_NEW_PROFILE_NEW_STYLE
+             target:self
+             action:@selector(createProfile:)
+     shouldAutoSize:YES];
   }
 
   // Add the title label.
@@ -249,7 +251,7 @@
 
   // Compute the dialog width using the title and buttons.
   const CGFloat buttonsWidth =
-      (offerProfileCreation_ ? NSWidth([createProfileLinkField_ frame]) : 0) +
+      (offerProfileCreation_ ? NSWidth([createProfileButton_ frame]) : 0) +
       kButtonGap + NSWidth([cancelButton_ frame]) +
       kButtonGap + NSWidth([okButton_ frame]);
   const CGFloat titleWidth =
@@ -276,17 +278,17 @@
   [[self view] addSubview:promptBox_];
 
   // Prompt text.
-  std::vector<size_t> offsets;
+  size_t offset;
   const string16 domain = ASCIIToUTF16(gaia::ExtractDomainName(username_));
   const string16 username = ASCIIToUTF16(username_);
   const string16 prompt_text =
       l10n_util::GetStringFUTF16(
           IDS_ENTERPRISE_SIGNIN_ALERT_NEW_STYLE,
-          username, domain, &offsets);
+          domain, &offset);
   promptField_.reset(
       [AddTextField(promptBox_, prompt_text, chrome_style::kTextFontStyle)
           retain]);
-  MakeTextBold(promptField_, offsets[1], domain.size());
+  MakeTextBold(promptField_, offset, domain.size());
   [promptField_ setFrame:ComputeFrame(
         [promptField_ attributedStringValue], width, 0.0)];
 
@@ -300,7 +302,7 @@
   [promptBox_ setFrame:NSMakeRect(0, 0, dialogWidth, boxHeight)];
 
   // Explanation text.
-  offsets.clear();
+  std::vector<size_t> offsets;
   const string16 learn_more_text =
       l10n_util::GetStringUTF16(
           IDS_ENTERPRISE_SIGNIN_PROFILE_LINK_LEARN_MORE);
@@ -326,24 +328,21 @@
 
   // Layout the elements, starting at the bottom and moving up.
 
-  CGFloat curX = chrome_style::kHorizontalPadding;
+  CGFloat curX = dialogWidth - chrome_style::kHorizontalPadding;
   CGFloat curY = chrome_style::kClientBottomPadding;
 
-  // CreateProfile link sticks to the bottom-left, vertically centered with
-  // the other buttons.
+  // Buttons should go |Cancel|Continue|CreateProfile|, unless
+  // |CreateProfile| isn't shown.
   if (offerProfileCreation_) {
-    CGFloat linkHeight = NSHeight([createProfileLinkField_ frame]);
-    CGFloat buttonHeight = NSHeight([okButton_ frame]);
-    CGFloat dy = roundf((buttonHeight - linkHeight) / 2.0 + 1.0);
-    [createProfileLinkField_ setFrameOrigin:NSMakePoint(curX, curY + dy)];
+    curX -= NSWidth([createProfileButton_ frame]);
+    [createProfileButton_ setFrameOrigin:NSMakePoint(curX, curY)];
+    curX -= kButtonGap;
   }
-
-  // OK and Cancel buttons stick to the bottom-right.
-  curX = dialogWidth - chrome_style::kHorizontalPadding;
   curX -= NSWidth([okButton_ frame]);
   [okButton_ setFrameOrigin:NSMakePoint(curX, curY)];
   curX -= (kButtonGap + NSWidth([cancelButton_ frame]));
   [cancelButton_ setFrameOrigin:NSMakePoint(curX, curY)];
+
   curY += NSHeight([cancelButton_ frame]);
 
   // Explanation text.
@@ -463,8 +462,8 @@
   return delegate_;
 }
 
-- (NSButton*)createProfileLinkField {
-  return createProfileLinkField_.get();
+- (NSButton*)createProfileButton {
+  return createProfileButton_.get();
 }
 
 - (NSTextView*)explanationField {
diff --git a/chrome/browser/ui/cocoa/profile_signin_confirmation_view_controller_browsertest.mm b/chrome/browser/ui/cocoa/profile_signin_confirmation_view_controller_browsertest.mm
index 939875d..0d5a5c4 100644
--- a/chrome/browser/ui/cocoa/profile_signin_confirmation_view_controller_browsertest.mm
+++ b/chrome/browser/ui/cocoa/profile_signin_confirmation_view_controller_browsertest.mm
@@ -6,7 +6,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/ui/browser.h"
@@ -69,10 +69,10 @@
   void OnClose() { closed_ = true; }
 
   // The window containing the dialog.
-  scoped_nsobject<NSWindow> window_;
+  base::scoped_nsobject<NSWindow> window_;
 
   // Dialog under test.
-  scoped_nsobject<ProfileSigninConfirmationViewController> controller_;
+  base::scoped_nsobject<ProfileSigninConfirmationViewController> controller_;
 
   // Visible for testing UI interactions.
   bool continued_;
@@ -160,7 +160,7 @@
                        DoNotOfferNewProfile) {
   SetupDialog(/*offerProfileCreation = */ false);
   // Create Profile button shouldn't exist.
-  EXPECT_NSEQ(nil, [controller_ createProfileLinkField]);
+  EXPECT_NSEQ(nil, [controller_ createProfileButton]);
   // Explanation shouldn't mention creating a new profile.
   NSString* explanationWithoutCreateProfile = base::SysUTF16ToNSString(
       l10n_util::GetStringFUTF16(
@@ -174,9 +174,9 @@
                        OfferNewProfile) {
   SetupDialog(/*offerProfileCreation = */ true);
   // Create Profile button should exist and be visible.
-  EXPECT_NSNE(nil, [controller_ createProfileLinkField]);
+  EXPECT_NSNE(nil, [controller_ createProfileButton]);
   EXPECT_TRUE([[[controller_ view] subviews]
-                containsObject:[controller_ createProfileLinkField]]);
+                containsObject:[controller_ createProfileButton]]);
   NSString* explanationWithCreateProfile = base::SysUTF16ToNSString(
       l10n_util::GetStringFUTF16(
           IDS_ENTERPRISE_SIGNIN_EXPLANATION_WITH_PROFILE_CREATION_NEW_STYLE,
diff --git a/chrome/browser/ui/cocoa/run_loop_testing.mm b/chrome/browser/ui/cocoa/run_loop_testing.mm
index b85722a..f79aa53 100644
--- a/chrome/browser/ui/cocoa/run_loop_testing.mm
+++ b/chrome/browser/ui/cocoa/run_loop_testing.mm
@@ -6,7 +6,7 @@
 
 #import <Foundation/Foundation.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/message_loop/message_pump_mac.h"
 
 // This class is scheduled with a delayed selector to quit the message pump.
@@ -42,8 +42,8 @@
 
   // Put a delayed selector on the queue. All other pending delayed selectors
   // will run before this, after which the internal loop can end.
-  scoped_nsobject<CocoaQuitTask> quit_task(
-      [[CocoaQuitTask alloc] initWithMessagePump:message_pump]);
+  base::scoped_nsobject<CocoaQuitTask> quit_task(
+      [[CocoaQuitTask alloc] initWithMessagePump:message_pump.get()]);
 
   [quit_task performSelector:@selector(doQuit)
                   withObject:nil
diff --git a/chrome/browser/ui/cocoa/run_loop_testing_unittest.mm b/chrome/browser/ui/cocoa/run_loop_testing_unittest.mm
index d281c46..760f985 100644
--- a/chrome/browser/ui/cocoa/run_loop_testing_unittest.mm
+++ b/chrome/browser/ui/cocoa/run_loop_testing_unittest.mm
@@ -6,7 +6,7 @@
 
 #import <Foundation/Foundation.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 @interface TestDelayed : NSObject {
@@ -36,7 +36,7 @@
 @end
 
 TEST(RunLoopTesting, RunAllPending) {
-  scoped_nsobject<TestDelayed> tester([[TestDelayed alloc] init]);
+  base::scoped_nsobject<TestDelayed> tester([[TestDelayed alloc] init]);
   EXPECT_FALSE([tester didWork]);
 
   chrome::testing::NSRunLoopRunAllPending();
@@ -45,8 +45,8 @@
 }
 
 TEST(RunLoopTesting, NestedWork) {
-  scoped_nsobject<TestDelayed> tester([[TestDelayed alloc] init]);
-  scoped_nsobject<TestDelayed> nested([[TestDelayed alloc] init]);
+  base::scoped_nsobject<TestDelayed> tester([[TestDelayed alloc] init]);
+  base::scoped_nsobject<TestDelayed> nested([[TestDelayed alloc] init]);
   [tester setNext:nested];
 
   EXPECT_FALSE([tester didWork]);
diff --git a/chrome/browser/ui/cocoa/speech_recognition_bubble_cocoa.mm b/chrome/browser/ui/cocoa/speech_recognition_bubble_cocoa.mm
index eb48acb..c308f5a 100644
--- a/chrome/browser/ui/cocoa/speech_recognition_bubble_cocoa.mm
+++ b/chrome/browser/ui/cocoa/speech_recognition_bubble_cocoa.mm
@@ -6,7 +6,7 @@
 
 #include "chrome/browser/speech/speech_recognition_bubble.h"
 
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/cocoa/browser_window_cocoa.h"
 #include "chrome/browser/ui/cocoa/browser_window_controller.h"
@@ -35,7 +35,7 @@
   virtual void UpdateImage() OVERRIDE;
 
  private:
-  scoped_nsobject<SpeechRecognitionWindowController> window_;
+  base::scoped_nsobject<SpeechRecognitionWindowController> window_;
   Delegate* delegate_;
   gfx::Rect element_rect_;
 };
diff --git a/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa.h b/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa.h
index 88d9b79..ce94e3c 100644
--- a/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa.h
+++ b/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa.h
@@ -9,8 +9,8 @@
 #include <vector>
 
 #include "base/mac/scoped_cftyperef.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/ref_counted.h"
-#include "base/memory/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #include "chrome/browser/ssl/ssl_client_certificate_selector.h"
 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_sheet.h"
@@ -24,14 +24,14 @@
     : NSObject<ConstrainedWindowSheet> {
  @private
   // The list of identities offered to the user.
-  base::mac::ScopedCFTypeRef<CFMutableArrayRef> identities_;
+  base::ScopedCFTypeRef<CFMutableArrayRef> identities_;
   // The corresponding list of certificates.
   std::vector<scoped_refptr<net::X509Certificate> > certificates_;
   // A C++ object to bridge SSLClientAuthObserver notifications to us.
   scoped_ptr<SSLClientAuthObserverCocoaBridge> observer_;
-  scoped_nsobject<SFChooseIdentityPanel> panel_;
+  base::scoped_nsobject<SFChooseIdentityPanel> panel_;
   scoped_ptr<ConstrainedWindowMac> constrainedWindow_;
-  scoped_nsobject<NSWindow> overlayWindow_;
+  base::scoped_nsobject<NSWindow> overlayWindow_;
   BOOL closePending_;
   // A copy of the sheet's frame used to restore on show.
   NSRect oldSheetFrame_;
diff --git a/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa.mm b/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa.mm
index 232d55b..b3c9c05 100644
--- a/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa.mm
+++ b/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa.mm
@@ -111,7 +111,7 @@
     CFIndex index =
         CFArrayGetFirstIndexOfValue(identities_, range, [panel_ identity]);
     if (index != -1)
-      cert = certificates_[index];
+      cert = certificates_[index].get();
     else
       NOTREACHED();
   }
diff --git a/chrome/browser/ui/cocoa/status_bubble_mac.mm b/chrome/browser/ui/cocoa/status_bubble_mac.mm
index 99f8d98..e5e46e0 100644
--- a/chrome/browser/ui/cocoa/status_bubble_mac.mm
+++ b/chrome/browser/ui/cocoa/status_bubble_mac.mm
@@ -374,7 +374,7 @@
   // teardown sequence in BWC guarantees that |parent_| outlives the status
   // bubble and that the StatusBubble is torn down completely prior to the
   // window going away.
-  scoped_nsobject<BubbleView> view(
+  base::scoped_nsobject<BubbleView> view(
       [[BubbleView alloc] initWithFrame:NSZeroRect themeProvider:parent_]);
   [window_ setContentView:view];
 
diff --git a/chrome/browser/ui/cocoa/status_bubble_mac_unittest.mm b/chrome/browser/ui/cocoa/status_bubble_mac_unittest.mm
index b25225f..ffd903b 100644
--- a/chrome/browser/ui/cocoa/status_bubble_mac_unittest.mm
+++ b/chrome/browser/ui/cocoa/status_bubble_mac_unittest.mm
@@ -4,7 +4,7 @@
 
 #include <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/message_loop.h"
 #include "base/strings/utf_string_conversions.h"
@@ -175,7 +175,7 @@
   }
 
   base::MessageLoop message_loop_;
-  scoped_nsobject<StatusBubbleMacTestDelegate> delegate_;
+  base::scoped_nsobject<StatusBubbleMacTestDelegate> delegate_;
   StatusBubbleMac* bubble_;  // Strong.
 };
 
diff --git a/chrome/browser/ui/cocoa/status_icons/status_icon_mac.h b/chrome/browser/ui/cocoa/status_icons/status_icon_mac.h
index 51fa138..8b380c4 100644
--- a/chrome/browser/ui/cocoa/status_icons/status_icon_mac.h
+++ b/chrome/browser/ui/cocoa/status_icons/status_icon_mac.h
@@ -9,7 +9,7 @@
 
 #include "base/compiler_specific.h"
 #include "base/gtest_prod_util.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/strings/string16.h"
 #include "chrome/browser/status_icons/desktop_notification_balloon.h"
 #include "chrome/browser/status_icons/status_icon.h"
@@ -46,18 +46,18 @@
 
   // Getter for item_ that allows lazy initialization.
   NSStatusItem* item();
-  scoped_nsobject<NSStatusItem> item_;
+  base::scoped_nsobject<NSStatusItem> item_;
 
-  scoped_nsobject<StatusItemController> controller_;
+  base::scoped_nsobject<StatusItemController> controller_;
 
   // Notification balloon.
   DesktopNotificationBalloon notification_;
 
-  scoped_nsobject<NSString> toolTip_;
+  base::scoped_nsobject<NSString> toolTip_;
 
   // Status menu shown when right-clicking the system icon, if it has been
   // created by |UpdatePlatformContextMenu|.
-  scoped_nsobject<MenuController> menu_;
+  base::scoped_nsobject<MenuController> menu_;
 
   DISALLOW_COPY_AND_ASSIGN(StatusIconMac);
 };
diff --git a/chrome/browser/ui/cocoa/styled_text_field_cell_unittest.mm b/chrome/browser/ui/cocoa/styled_text_field_cell_unittest.mm
index 076583f..a01c2c4 100644
--- a/chrome/browser/ui/cocoa/styled_text_field_cell_unittest.mm
+++ b/chrome/browser/ui/cocoa/styled_text_field_cell_unittest.mm
@@ -4,10 +4,10 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #import "chrome/browser/ui/cocoa/styled_text_field_cell.h"
 #import "chrome/browser/ui/cocoa/styled_text_field_test_helper.h"
-#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
 
@@ -24,13 +24,13 @@
     // decorations.
     const NSRect frame = NSMakeRect(0, 0, kWidth, 30);
 
-    scoped_nsobject<StyledTextFieldTestCell> cell(
+    base::scoped_nsobject<StyledTextFieldTestCell> cell(
         [[StyledTextFieldTestCell alloc] initTextCell:@"Testing"]);
     cell_ = cell.get();
     [cell_ setEditable:YES];
     [cell_ setBordered:YES];
 
-    scoped_nsobject<NSTextField> view(
+    base::scoped_nsobject<NSTextField> view(
         [[NSTextField alloc] initWithFrame:frame]);
     view_ = view.get();
     [view_ setCell:cell_];
diff --git a/chrome/browser/ui/cocoa/styled_text_field_unittest.mm b/chrome/browser/ui/cocoa/styled_text_field_unittest.mm
index c4f066c..0a8ebe9 100644
--- a/chrome/browser/ui/cocoa/styled_text_field_unittest.mm
+++ b/chrome/browser/ui/cocoa/styled_text_field_unittest.mm
@@ -4,11 +4,11 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #import "chrome/browser/ui/cocoa/styled_text_field.h"
 #import "chrome/browser/ui/cocoa/styled_text_field_cell.h"
 #import "chrome/browser/ui/cocoa/styled_text_field_test_helper.h"
-#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
@@ -24,13 +24,13 @@
     // decorations.
     NSRect frame = NSMakeRect(0, 0, kWidth, 30);
 
-    scoped_nsobject<StyledTextFieldTestCell> cell(
+    base::scoped_nsobject<StyledTextFieldTestCell> cell(
         [[StyledTextFieldTestCell alloc] initTextCell:@"Testing"]);
     cell_ = cell.get();
     [cell_ setEditable:YES];
     [cell_ setBordered:YES];
 
-    scoped_nsobject<StyledTextField> field(
+    base::scoped_nsobject<StyledTextField> field(
         [[StyledTextField alloc] initWithFrame:frame]);
     field_ = field.get();
     [field_ setCell:cell_];
diff --git a/chrome/browser/ui/cocoa/tab_contents/instant_overlay_controller_mac.h b/chrome/browser/ui/cocoa/tab_contents/instant_overlay_controller_mac.h
index 2da31f7..836e225 100644
--- a/chrome/browser/ui/cocoa/tab_contents/instant_overlay_controller_mac.h
+++ b/chrome/browser/ui/cocoa/tab_contents/instant_overlay_controller_mac.h
@@ -10,13 +10,11 @@
 #include "chrome/browser/ui/search/instant_overlay_controller.h"
 
 class Browser;
-@class BrowserWindowController;
 @class OverlayableContentsController;
 
 class InstantOverlayControllerMac : public InstantOverlayController {
  public:
   InstantOverlayControllerMac(Browser* browser,
-                              BrowserWindowController* window,
                               OverlayableContentsController* overlay);
   virtual ~InstantOverlayControllerMac();
 
@@ -24,7 +22,6 @@
   // Overridden from InstantOverlayController:
   virtual void OverlayStateChanged(const InstantOverlayModel& model) OVERRIDE;
 
-  BrowserWindowController* const window_;
   OverlayableContentsController* const overlay_;
 
   DISALLOW_COPY_AND_ASSIGN(InstantOverlayControllerMac);
diff --git a/chrome/browser/ui/cocoa/tab_contents/instant_overlay_controller_mac.mm b/chrome/browser/ui/cocoa/tab_contents/instant_overlay_controller_mac.mm
index c5c819e..3510721 100644
--- a/chrome/browser/ui/cocoa/tab_contents/instant_overlay_controller_mac.mm
+++ b/chrome/browser/ui/cocoa/tab_contents/instant_overlay_controller_mac.mm
@@ -4,22 +4,13 @@
 
 #include "chrome/browser/ui/cocoa/tab_contents/instant_overlay_controller_mac.h"
 
-#include "chrome/browser/search/search.h"
-#include "chrome/browser/ui/browser.h"
-#import "chrome/browser/ui/cocoa/browser_window_controller.h"
-#include "chrome/browser/ui/cocoa/tab_contents/instant_overlay_controller_mac.h"
 #import "chrome/browser/ui/cocoa/tab_contents/overlayable_contents_controller.h"
 #include "chrome/browser/ui/search/instant_overlay_model.h"
-#include "chrome/browser/ui/search/search_model.h"
-#include "chrome/browser/ui/search/search_tab_helper.h"
-#include "chrome/browser/ui/tabs/tab_strip_model.h"
 
 InstantOverlayControllerMac::InstantOverlayControllerMac(
     Browser* browser,
-    BrowserWindowController* window,
     OverlayableContentsController* overlay)
     : InstantOverlayController(browser),
-      window_(window),
       overlay_(overlay) {
 }
 
@@ -28,8 +19,6 @@
 
 void InstantOverlayControllerMac::OverlayStateChanged(
     const InstantOverlayModel& model) {
-  bool set_top_bars_visibility = chrome::IsInstantExtendedAPIEnabled();
-
   if (model.mode().is_ntp() || model.mode().is_search_suggestions()) {
     // Drop shadow is only needed if search mode is not |NTP| and overlay does
     // not fill up the entire contents page.
@@ -45,25 +34,5 @@
                   height:0
              heightUnits:INSTANT_SIZE_PIXELS
           drawDropShadow:NO];
-  } else {
-    set_top_bars_visibility = false;
   }
-
-  if (set_top_bars_visibility) {
-    // Set top bars (bookmark and info bars) visibility for current tab via
-    // |SearchTabHelper| of current active web contents: top bars are hidden if
-    // there's overlay.
-    content::WebContents* active_web_contents =
-        browser_->tab_strip_model()->GetActiveWebContents();
-    if (active_web_contents) {
-      SearchTabHelper* search_tab_helper =
-          SearchTabHelper::FromWebContents(active_web_contents);
-      if (search_tab_helper) {
-        search_tab_helper->model()->SetTopBarsVisible(
-            ![overlay_ isShowingOverlay]);
-      }
-    }
-  }
-
-  [window_ updateBookmarkBarStateForInstantOverlay];
 }
diff --git a/chrome/browser/ui/cocoa/tab_contents/overlay_separator_view.h b/chrome/browser/ui/cocoa/tab_contents/overlay_separator_view.h
deleted file mode 100644
index 3ebd5da..0000000
--- a/chrome/browser/ui/cocoa/tab_contents/overlay_separator_view.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_TAB_CONTENTS_OVERLAY_SEPARATOR_VIEW_H_
-#define CHROME_BROWSER_UI_COCOA_TAB_CONTENTS_OVERLAY_SEPARATOR_VIEW_H_
-
-#import <Cocoa/Cocoa.h>
-
-#include "chrome/browser/ui/cocoa/background_gradient_view.h"
-
-// A view used to draw a separator above Instant overlay view.
-@interface OverlayTopSeparatorView : BackgroundGradientView {
-}
-
-+ (CGFloat)preferredHeight;
-
-@end
-
-// A view used to draw a drop shadow beneath the Instant overlay view.
-@interface OverlayBottomSeparatorView : NSView {
-}
-
-+ (CGFloat)preferredHeight;
-
-@end
-
-#endif  // CHROME_BROWSER_UI_COCOA_TAB_CONTENTS_OVERLAY_SEPARATOR_VIEW_H_
diff --git a/chrome/browser/ui/cocoa/tab_contents/overlay_separator_view.mm b/chrome/browser/ui/cocoa/tab_contents/overlay_separator_view.mm
deleted file mode 100644
index 35509b2..0000000
--- a/chrome/browser/ui/cocoa/tab_contents/overlay_separator_view.mm
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/tab_contents/overlay_separator_view.h"
-
-#import "chrome/browser/ui/cocoa/nsview_additions.h"
-#include "grit/theme_resources.h"
-#include "ui/base/resource/resource_bundle.h"
-
-@implementation OverlayTopSeparatorView
-
-+ (CGFloat)preferredHeight {
-  return 1;
-}
-
-- (void)drawRect:(NSRect)rect {
-  NSRect separatorRect = [self bounds];
-  separatorRect.size.height = [self cr_lineWidth];
-  [[self strokeColor] set];
-  NSRectFillUsingOperation(separatorRect, NSCompositeSourceOver);
-}
-
-@end
-
-@implementation OverlayBottomSeparatorView
-
-+ (CGFloat)preferredHeight {
-  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-  NSImage* shadowImage =
-      rb.GetNativeImageNamed(IDR_OVERLAY_DROP_SHADOW).ToNSImage();
-  return [shadowImage size].height;
-}
-
-- (void)drawRect:(NSRect)rect {
-  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-  NSRect bounds = [self bounds];
-
-  // Draw the shadow.
-  NSImage* shadowImage =
-      rb.GetNativeImageNamed(IDR_OVERLAY_DROP_SHADOW).ToNSImage();
-  [shadowImage drawInRect:bounds
-                 fromRect:NSZeroRect
-                operation:NSCompositeSourceOver
-                 fraction:1.0];
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/tab_contents/overlay_separator_view_unittest.mm b/chrome/browser/ui/cocoa/tab_contents/overlay_separator_view_unittest.mm
deleted file mode 100644
index 7254a31..0000000
--- a/chrome/browser/ui/cocoa/tab_contents/overlay_separator_view_unittest.mm
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/tab_contents/overlay_separator_view.h"
-
-#include "base/memory/scoped_nsobject.h"
-#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-
-class OverlayBottomSeparatorViewTest : public CocoaTest {
- public:
-  OverlayBottomSeparatorViewTest() {
-    NSView* contentView = [test_window() contentView];
-    bottom_view_.reset([[OverlayBottomSeparatorView alloc]
-        initWithFrame:[contentView bounds]]);
-    [contentView addSubview:bottom_view_];
-  }
-
- protected:
-  scoped_nsobject<OverlayBottomSeparatorView> bottom_view_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(OverlayBottomSeparatorViewTest);
-};
-
-TEST_VIEW(OverlayBottomSeparatorViewTest, bottom_view_);
-
-TEST_F(OverlayBottomSeparatorViewTest, PreferredHeight) {
-  EXPECT_LT(0, [OverlayBottomSeparatorView preferredHeight]);
-}
-
-class OverlayTopSeparatorViewTest : public CocoaTest {
- public:
-  OverlayTopSeparatorViewTest() {
-    NSView* contentView = [test_window() contentView];
-    top_view_.reset(
-        [[OverlayTopSeparatorView alloc] initWithFrame:[contentView bounds]]);
-    [contentView addSubview:top_view_];
-  }
-
- protected:
-  scoped_nsobject<OverlayTopSeparatorView> top_view_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(OverlayTopSeparatorViewTest);
-};
-
-TEST_VIEW(OverlayTopSeparatorViewTest, top_view_);
-
-TEST_F(OverlayTopSeparatorViewTest, PreferredHeight) {
-  EXPECT_LT(0, [OverlayTopSeparatorView preferredHeight]);
-}
diff --git a/chrome/browser/ui/cocoa/tab_contents/overlayable_contents_controller.h b/chrome/browser/ui/cocoa/tab_contents/overlayable_contents_controller.h
index 15ef7a6..6033cba 100644
--- a/chrome/browser/ui/cocoa/tab_contents/overlayable_contents_controller.h
+++ b/chrome/browser/ui/cocoa/tab_contents/overlayable_contents_controller.h
@@ -7,12 +7,11 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #include "chrome/common/instant_types.h"
 
 class Browser;
-@class BrowserWindowController;
 class InstantOverlayControllerMac;
 
 namespace content {
@@ -33,7 +32,7 @@
 @interface OverlayableContentsController : NSViewController {
  @private
   // Container view for the "active" contents.
-  scoped_nsobject<NSView> activeContainer_;
+  base::scoped_nsobject<NSView> activeContainer_;
 
   // The overlay WebContents. Will be NULL if no overlay is currently showing.
   content::WebContents* overlayContents_;  // weak
@@ -44,41 +43,12 @@
   // The desired height of the overlay and units.
   CGFloat overlayHeight_;
   InstantSizeUnits overlayHeightUnits_;
-
-  // If true then a shadow is drawn below the overlay. This is used to make the
-  // overlay "float" over the tab's web contents.
-  BOOL drawDropShadow_;
-
-  // View responsible for drawing a drop shadow.
-  scoped_nsobject<NSView> dropShadowView_;
-
-  // View responsible for drawing a separator at the top. The separator is
-  // only visible when the overlay is positioned right next to the omnibox.
-  scoped_nsobject<NSView> topSeparatorView_;
-
-  BrowserWindowController* windowController_;
-
-  // The vertical offset between the top of the view and the active container.
-  // This is used to push the active container below the bookmark bar. Normally
-  // this is set to the height of the bookmark bar so that the bookmark bar is
-  // not obscured.
-  CGFloat activeContainerOffset_;
-
-  // The vertical offset between the top of the view and the overlay. This is
-  // used in presentation mode to push the overlay below the floating toolbar
-  // view.
-  CGFloat overlayContentsOffset_;
 }
 
 @property(readonly, nonatomic) NSView* activeContainer;
-@property(readonly, nonatomic) NSView* dropShadowView;
-@property(readonly, nonatomic) BOOL drawDropShadow;
-@property(assign, nonatomic) CGFloat activeContainerOffset;
-@property(assign, nonatomic) CGFloat overlayContentsOffset;
 
 // Initialization.
-- (id)initWithBrowser:(Browser*)browser
-     windowController:(BrowserWindowController*)windowController;
+- (id)initWithBrowser:(Browser*)browser;
 
 // Sets the current overlay and installs its WebContentsView into the view
 // hierarchy. Hides the active view. If |overlay| is NULL then closes the
@@ -92,12 +62,9 @@
 // if it's the overlay being activated (and adjust internal state accordingly).
 - (void)onActivateTabWithContents:(content::WebContents*)contents;
 
-// Returns YES if the overlay contents is currently showing.
-- (BOOL)isShowingOverlay;
-
 - (InstantOverlayControllerMac*)instantOverlayController;
 
-- (void)activeContentsCompositingIOSurfaceCreated;
+- (BOOL)isShowingOverlay;
 
 @end
 
diff --git a/chrome/browser/ui/cocoa/tab_contents/overlayable_contents_controller.mm b/chrome/browser/ui/cocoa/tab_contents/overlayable_contents_controller.mm
index a7ec256..0b19677 100644
--- a/chrome/browser/ui/cocoa/tab_contents/overlayable_contents_controller.mm
+++ b/chrome/browser/ui/cocoa/tab_contents/overlayable_contents_controller.mm
@@ -4,10 +4,7 @@
 
 #import "chrome/browser/ui/cocoa/tab_contents/overlayable_contents_controller.h"
 
-#include "base/mac/bundle_locations.h"
-#include "chrome/browser/ui/cocoa/browser_window_controller.h"
 #include "chrome/browser/ui/cocoa/tab_contents/instant_overlay_controller_mac.h"
-#include "chrome/browser/ui/cocoa/tab_contents/overlay_separator_view.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_view.h"
 
@@ -15,22 +12,15 @@
 - (void)viewDidResize:(NSNotification*)note;
 - (void)layoutViews;
 - (CGFloat)overlayHeightInPixels;
-- (BOOL)shouldShowTopSeparator;
 @end
 
 @implementation OverlayableContentsController
 
-@synthesize drawDropShadow = drawDropShadow_;
-@synthesize activeContainerOffset = activeContainerOffset_;
-@synthesize overlayContentsOffset = overlayContentsOffset_;
-
-- (id)initWithBrowser:(Browser*)browser
-     windowController:(BrowserWindowController*)windowController {
+- (id)initWithBrowser:(Browser*)browser {
   if ((self = [super init])) {
-    windowController_ = windowController;
-    scoped_nsobject<NSView> view([[NSView alloc] initWithFrame:NSZeroRect]);
+    base::scoped_nsobject<NSView> view(
+        [[NSView alloc] initWithFrame:NSZeroRect]);
     [view setAutoresizingMask:NSViewHeightSizable | NSViewWidthSizable];
-    [view setAutoresizesSubviews:NO];
     [[NSNotificationCenter defaultCenter]
         addObserver:self
            selector:@selector(viewDidResize:)
@@ -39,13 +29,12 @@
     [self setView:view];
 
     activeContainer_.reset([[NSView alloc] initWithFrame:NSZeroRect]);
+    [activeContainer_ setAutoresizingMask:NSViewHeightSizable |
+                                          NSViewWidthSizable];
     [view addSubview:activeContainer_];
 
     instantOverlayController_.reset(
-        new InstantOverlayControllerMac(browser, windowController, self));
-    topSeparatorView_.reset(
-        [[OverlayTopSeparatorView alloc] initWithFrame:NSZeroRect]);
-    [[self view] addSubview:topSeparatorView_];
+        new InstantOverlayControllerMac(browser, self));
   }
   return self;
 }
@@ -59,17 +48,9 @@
             height:(CGFloat)height
        heightUnits:(InstantSizeUnits)heightUnits
     drawDropShadow:(BOOL)drawDropShadow {
-  // If drawing drop shadow, clip the bottom 1-px-thick separator out of
-  // overlay.
-  // TODO(sail): remove this when GWS gives chrome the height without the
-  // separator.
-  if (drawDropShadow && heightUnits != INSTANT_SIZE_PERCENT)
-    --height;
-
   if (overlayContents_ == overlay &&
       overlayHeight_ == height &&
-      overlayHeightUnits_ == heightUnits &&
-      drawDropShadow_ == drawDropShadow) {
+      overlayHeightUnits_ == heightUnits) {
     return;
   }
 
@@ -83,7 +64,6 @@
   overlayContents_ = overlay;
   overlayHeight_ = height;
   overlayHeightUnits_ = heightUnits;
-  drawDropShadow_ = drawDropShadow;
 
   // Add the overlay contents.
   if (overlayContents_) {
@@ -91,17 +71,6 @@
     [[self view] addSubview:overlayContents_->GetView()->GetNativeView()];
   }
 
-  if (drawDropShadow_) {
-    if (!dropShadowView_) {
-      dropShadowView_.reset(
-          [[OverlayBottomSeparatorView alloc] initWithFrame:NSZeroRect]);
-      [[self view] addSubview:dropShadowView_];
-    }
-  } else {
-    [dropShadowView_ removeFromSuperview];
-    dropShadowView_.reset();
-  }
-
   [self layoutViews];
 
   if (overlayContents_)
@@ -121,98 +90,36 @@
   }
 }
 
-- (BOOL)isShowingOverlay {
-  return overlayContents_ != nil;
-}
-
 - (InstantOverlayControllerMac*)instantOverlayController {
   return instantOverlayController_.get();
 }
 
-- (void)activeContentsCompositingIOSurfaceCreated {
-  if (!overlayContents_)
-    return;
-
-  // If the active tab becomes composited the the overlay will no longer be
-  // visible. Workaround this by re-adding the overlay to the view hierarchy.
-  // See http://crbug.com/222122
-  [overlayContents_->GetView()->GetNativeView() removeFromSuperview];
-  [[self view] addSubview:overlayContents_->GetView()->GetNativeView()];
+- (BOOL)isShowingOverlay {
+  return overlayContents_ != nil;
 }
 
 - (NSView*)activeContainer {
   return activeContainer_.get();
 }
 
-- (NSView*)dropShadowView {
-  return dropShadowView_.get();
-}
-
-- (void)setActiveContainerOffset:(CGFloat)activeContainerOffset {
-  if (activeContainerOffset_ == activeContainerOffset)
-    return;
-
-  activeContainerOffset_ = activeContainerOffset;
-  [self layoutViews];
-}
-
-- (void)setOverlayContentsOffset:(CGFloat)overlayContentsOffset {
-  if (overlayContentsOffset_ == overlayContentsOffset)
-    return;
-
-  overlayContentsOffset_ = overlayContentsOffset;
-  [self layoutViews];
-}
-
 - (void)viewDidResize:(NSNotification*)note {
   [self layoutViews];
 }
 
 - (void)layoutViews {
-  NSRect bounds = [[self view] bounds];
-
-  // Layout the separator at the top of the view.
-  NSRect separatorRect = bounds;
-  if ([self shouldShowTopSeparator])
-    separatorRect.size.height = [OverlayTopSeparatorView preferredHeight];
-  else
-    separatorRect.size.height = 0;
-  separatorRect.origin.y = NSMaxY(bounds) - NSHeight(separatorRect);
-  [topSeparatorView_ setFrame:separatorRect];
+  if (!overlayContents_)
+    return;
 
   // Layout the overlay.
-  if (overlayContents_) {
-    NSRect overlayFrame = bounds;
-    overlayFrame.size.height = [self overlayHeightInPixels];
-    overlayFrame.origin.y = NSMinY([topSeparatorView_ frame]) -
-                            NSHeight(overlayFrame) - overlayContentsOffset_;
-    [overlayContents_->GetView()->GetNativeView() setFrame:overlayFrame];
-
-    if (dropShadowView_) {
-      NSRect dropShadowFrame = bounds;
-      dropShadowFrame.size.height =
-          [OverlayBottomSeparatorView preferredHeight];
-      dropShadowFrame.origin.y =
-          NSMinY(overlayFrame) - NSHeight(dropShadowFrame);
-      [dropShadowView_ setFrame:dropShadowFrame];
-    }
-  }
-
-  // Layout the active tab contents.
-  NSRect activeFrame = bounds;
-  if (activeContainerOffset_)
-    activeFrame.size.height -= activeContainerOffset_;
-  else
-    activeFrame.size.height -= NSHeight([topSeparatorView_ frame]);
-  if (!NSEqualRects(activeFrame, [activeContainer_ frame])) {
-    [[activeContainer_ window] disableScreenUpdatesUntilFlush];
-    [activeContainer_ setFrame:activeFrame];
-  }
+  NSRect bounds = [[self view] bounds];
+  NSRect overlayFrame = bounds;
+  overlayFrame.size.height = [self overlayHeightInPixels];
+  overlayFrame.origin.y = NSMaxY(bounds) - NSHeight(overlayFrame);
+  [overlayContents_->GetView()->GetNativeView() setFrame:overlayFrame];
 }
 
 - (CGFloat)overlayHeightInPixels {
-  CGFloat height = NSHeight([[self view] bounds]) -
-                   NSHeight([topSeparatorView_ frame]) - overlayContentsOffset_;
+  CGFloat height = NSHeight([[self view] bounds]);
   switch (overlayHeightUnits_) {
     case INSTANT_SIZE_PERCENT:
       return std::min(height, (height * overlayHeight_) / 100);
@@ -221,18 +128,4 @@
   }
 }
 
-- (BOOL)shouldShowTopSeparator {
-  // In presentation mode tab contents are flush with the top of the screen
-  // so there's no need for a separator.
-  if ([windowController_ inPresentationMode])
-    return NO;
-
-  if (![windowController_ hasToolbar])
-    return NO;
-
-  // Show a separator is the overlay or the tab contents will be shown right
-  // next to the omnibox.
-  return activeContainerOffset_ == 0 || overlayContents_;
-}
-
 @end
diff --git a/chrome/browser/ui/cocoa/tab_contents/overlayable_contents_controller_browsertest.mm b/chrome/browser/ui/cocoa/tab_contents/overlayable_contents_controller_browsertest.mm
index d2e115d..075b981 100644
--- a/chrome/browser/ui/cocoa/tab_contents/overlayable_contents_controller_browsertest.mm
+++ b/chrome/browser/ui/cocoa/tab_contents/overlayable_contents_controller_browsertest.mm
@@ -7,9 +7,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/cocoa/browser_window_controller.h"
 #include "chrome/browser/ui/cocoa/tab_contents/instant_overlay_controller_mac.h"
-#include "chrome/browser/ui/cocoa/tab_contents/overlay_separator_view.h"
 #include "chrome/browser/ui/search/instant_overlay_model.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "content/public/browser/notification_source.h"
@@ -29,12 +27,8 @@
         content::WebContents::CreateParams(browser()->profile())));
     instant_overlay_model_.SetOverlayContents(web_contents_.get());
 
-    BrowserWindowController* window_controller =
-        [BrowserWindowController browserWindowControllerForWindow:
-                browser()->window()->GetNativeWindow()];
     controller_.reset([[OverlayableContentsController alloc]
-         initWithBrowser:browser()
-        windowController:window_controller]);
+         initWithBrowser:browser()]);
     [[controller_ view] setFrame:NSMakeRect(0, 0, 100, 200)];
     instant_overlay_model_.AddObserver([controller_ instantOverlayController]);
   }
@@ -50,7 +44,6 @@
   void VerifyOverlayFrame(CGFloat expected_height,
                           InstantSizeUnits units) {
     NSRect container_bounds = [[controller_ view] bounds];
-    container_bounds.size.height -= [OverlayTopSeparatorView preferredHeight];
     NSRect overlay_frame =
         [web_contents_->GetView()->GetNativeView() frame];
 
@@ -78,7 +71,7 @@
  protected:
   InstantOverlayModel instant_overlay_model_;
   scoped_ptr<content::WebContents> web_contents_;
-  scoped_nsobject<OverlayableContentsController> controller_;
+  base::scoped_nsobject<OverlayableContentsController> controller_;
   content::NotificationRegistrar registrar_;
   int visibility_changed_count_;
 };
@@ -117,48 +110,6 @@
   VerifyOverlayFrame(expected_height, units);
 }
 
-// Verify that a bottom border is not shown when the overlay covers the entire
-// page or when the overlay is in NTP mode.
-IN_PROC_BROWSER_TEST_F(OverlayableContentsControllerTest, NoShadowFullHeight) {
-  SearchMode mode;
-  mode.mode = SearchMode::MODE_SEARCH_SUGGESTIONS;
-  instant_overlay_model_.SetOverlayState(mode, 100, INSTANT_SIZE_PERCENT);
-  EXPECT_FALSE([controller_ dropShadowView]);
-  EXPECT_FALSE([controller_ drawDropShadow]);
-
-  mode.mode = SearchMode::MODE_NTP;
-  instant_overlay_model_.SetOverlayState(mode, 10, INSTANT_SIZE_PERCENT);
-  EXPECT_FALSE([controller_ dropShadowView]);
-  EXPECT_FALSE([controller_ drawDropShadow]);
-}
-
-// Verify that a shadow is shown when the overlay is in search mode.
-IN_PROC_BROWSER_TEST_F(OverlayableContentsControllerTest, NoShadowNTP) {
-  SearchMode mode;
-  mode.mode = SearchMode::MODE_SEARCH_SUGGESTIONS;
-  instant_overlay_model_.SetOverlayState(mode, 10, INSTANT_SIZE_PERCENT);
-  EXPECT_TRUE([controller_ dropShadowView]);
-  EXPECT_TRUE([controller_ drawDropShadow]);
-  EXPECT_NSEQ([controller_ view], [[controller_ dropShadowView] superview]);
-
-  NSRect dropShadowFrame = [[controller_ dropShadowView] frame];
-  NSRect controllerBounds = [[controller_ view] bounds];
-  EXPECT_EQ(NSWidth(controllerBounds), NSWidth(dropShadowFrame));
-  EXPECT_EQ([OverlayBottomSeparatorView preferredHeight],
-            NSHeight(dropShadowFrame));
-}
-
-// Verify that the shadow is hidden when hiding the overlay.
-IN_PROC_BROWSER_TEST_F(OverlayableContentsControllerTest, HideShadow) {
-  SearchMode mode;
-  mode.mode = SearchMode::MODE_SEARCH_SUGGESTIONS;
-  instant_overlay_model_.SetOverlayState(mode, 10, INSTANT_SIZE_PERCENT);
-  EXPECT_TRUE([controller_ dropShadowView]);
-
-  [controller_ onActivateTabWithContents:web_contents_.get()];
-  EXPECT_FALSE([controller_ dropShadowView]);
-}
-
 // Verify that the web contents is not hidden when just the height changes.
 IN_PROC_BROWSER_TEST_F(OverlayableContentsControllerTest, HeightChangeNoHide) {
   SearchMode mode;
@@ -172,23 +123,3 @@
   instant_overlay_model_.SetOverlayState(mode, 11, INSTANT_SIZE_PERCENT);
   EXPECT_EQ(1, visibility_changed_count_);
 }
-
-IN_PROC_BROWSER_TEST_F(OverlayableContentsControllerTest, OverlayOffset) {
-  SearchMode mode;
-  mode.mode = SearchMode::MODE_NTP;
-  CGFloat expected_height = 10;
-  InstantSizeUnits units = INSTANT_SIZE_PIXELS;
-  instant_overlay_model_.SetOverlayState(mode, expected_height, units);
-
-  CGFloat separator_height = [OverlayTopSeparatorView preferredHeight];
-  NSView* overlay_view = web_contents_->GetView()->GetNativeView();
-  EXPECT_EQ(separator_height,
-            NSMaxY([[overlay_view superview] frame]) -
-            NSMaxY([overlay_view frame]));
-
-  CGFloat offset = 30;
-  [controller_ setOverlayContentsOffset:offset];
-  EXPECT_EQ(separator_height + offset,
-            NSMaxY([[overlay_view superview] frame]) -
-            NSMaxY([overlay_view frame]));
-}
diff --git a/chrome/browser/ui/cocoa/tab_contents/render_view_context_menu_mac.h b/chrome/browser/ui/cocoa/tab_contents/render_view_context_menu_mac.h
index 35f8177..c43503a 100644
--- a/chrome/browser/ui/cocoa/tab_contents/render_view_context_menu_mac.h
+++ b/chrome/browser/ui/cocoa/tab_contents/render_view_context_menu_mac.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/tab_contents/render_view_context_menu.h"
 
 @class MenuController;
@@ -59,7 +59,7 @@
   void StopSpeaking();
 
   // The Cocoa menu controller for this menu.
-  scoped_nsobject<MenuController> menu_controller_;
+  base::scoped_nsobject<MenuController> menu_controller_;
 
   // Model for the "Speech" submenu.
   ui::SimpleMenuModel speech_submenu_model_;
diff --git a/chrome/browser/ui/cocoa/tab_contents/render_view_context_menu_mac.mm b/chrome/browser/ui/cocoa/tab_contents/render_view_context_menu_mac.mm
index 1581632..3ae3496 100644
--- a/chrome/browser/ui/cocoa/tab_contents/render_view_context_menu_mac.mm
+++ b/chrome/browser/ui/cocoa/tab_contents/render_view_context_menu_mac.mm
@@ -6,11 +6,9 @@
 
 #include "base/compiler_specific.h"
 #import "base/mac/scoped_sending_event.h"
-#include "base/memory/scoped_nsobject.h"
 #include "base/message_loop.h"
 #include "base/strings/sys_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
-#import "chrome/browser/ui/cocoa/browser_window_controller.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/render_widget_host_view.h"
 #include "grit/generated_resources.h"
@@ -110,13 +108,6 @@
 }
 
 void RenderViewContextMenuMac::ExecuteCommand(int command_id, int event_flags) {
-  // Auxiliary windows that do not have address bars (Panels for example)
-  // may not have Instant support.
-  NSWindow* parent_window = [parent_view_ window];
-  BrowserWindowController* controller =
-      [BrowserWindowController browserWindowControllerForWindow:parent_window];
-  [controller commitInstant];  // It's ok if controller is nil.
-
   switch (command_id) {
     case IDC_CONTENT_CONTEXT_LOOK_UP_IN_DICTIONARY:
       LookUpInDictionary();
diff --git a/chrome/browser/ui/cocoa/tab_contents/sad_tab_controller.h b/chrome/browser/ui/cocoa/tab_contents/sad_tab_controller.h
index 439e539..91fc745 100644
--- a/chrome/browser/ui/cocoa/tab_contents/sad_tab_controller.h
+++ b/chrome/browser/ui/cocoa/tab_contents/sad_tab_controller.h
@@ -7,7 +7,7 @@
 
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/ui/sad_tab.h"
 
 #import <Cocoa/Cocoa.h>
@@ -27,7 +27,7 @@
   virtual void Show() OVERRIDE;
   virtual void Close() OVERRIDE;
 
-  scoped_nsobject<SadTabController> sad_tab_controller_;
+  base::scoped_nsobject<SadTabController> sad_tab_controller_;
 
   content::WebContents* web_contents_;
 
diff --git a/chrome/browser/ui/cocoa/tab_contents/sad_tab_controller_unittest.mm b/chrome/browser/ui/cocoa/tab_contents/sad_tab_controller_unittest.mm
index 5c2e925..0067968 100644
--- a/chrome/browser/ui/cocoa/tab_contents/sad_tab_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/tab_contents/sad_tab_controller_unittest.mm
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/debug/debugger.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #import "chrome/browser/ui/cocoa/hyperlink_text_view.h"
 #import "chrome/browser/ui/cocoa/tab_contents/sad_tab_controller.h"
@@ -75,7 +75,7 @@
 bool SadTabControllerTest::link_clicked_;
 
 TEST_F(SadTabControllerTest, WithTabContents) {
-  scoped_nsobject<SadTabController> controller(CreateController());
+  base::scoped_nsobject<SadTabController> controller(CreateController());
   EXPECT_TRUE(controller);
   HyperlinkTextView* help = GetHelpTextView(controller);
   EXPECT_TRUE(help);
@@ -83,14 +83,14 @@
 
 TEST_F(SadTabControllerTest, WithoutTabContents) {
   DeleteContents();
-  scoped_nsobject<SadTabController> controller(CreateController());
+  base::scoped_nsobject<SadTabController> controller(CreateController());
   EXPECT_TRUE(controller);
   HyperlinkTextView* help = GetHelpTextView(controller);
   EXPECT_FALSE(help);
 }
 
 TEST_F(SadTabControllerTest, ClickOnLink) {
-  scoped_nsobject<SadTabController> controller(CreateController());
+  base::scoped_nsobject<SadTabController> controller(CreateController());
   HyperlinkTextView* help = GetHelpTextView(controller);
   EXPECT_TRUE(help);
   EXPECT_FALSE(link_clicked_);
diff --git a/chrome/browser/ui/cocoa/tab_contents/sad_tab_view.h b/chrome/browser/ui/cocoa/tab_contents/sad_tab_view.h
index b203cb2..45fdf7e 100644
--- a/chrome/browser/ui/cocoa/tab_contents/sad_tab_view.h
+++ b/chrome/browser/ui/cocoa/tab_contents/sad_tab_view.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_UI_COCOA_TAB_CONTENTS_SAD_TAB_VIEW_H_
 #define CHROME_BROWSER_UI_COCOA_TAB_CONTENTS_SAD_TAB_VIEW_H_
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "ui/base/cocoa/base_view.h"
 
 #import <Cocoa/Cocoa.h>
@@ -21,14 +21,14 @@
   IBOutlet NSTextField* message_;
   IBOutlet NSTextField* helpPlaceholder_;
 
-  scoped_nsobject<NSColor> backgroundColor_;
+  base::scoped_nsobject<NSColor> backgroundColor_;
   NSSize messageSize_;
 
   // Text fields don't work as well with embedded links as text views, but
   // text views cannot conveniently be created in IB. The xib file contains
   // a text field |helpPlaceholder_| that's replaced by this text view |help_|
   // in -awakeFromNib.
-  scoped_nsobject<HyperlinkTextView> help_;
+  base::scoped_nsobject<HyperlinkTextView> help_;
 
   // A weak reference to the parent controller.
   IBOutlet SadTabController* controller_;
diff --git a/chrome/browser/ui/cocoa/tab_contents/sad_tab_view_unittest.mm b/chrome/browser/ui/cocoa/tab_contents/sad_tab_view_unittest.mm
index 76808cf..82bf73a 100644
--- a/chrome/browser/ui/cocoa/tab_contents/sad_tab_view_unittest.mm
+++ b/chrome/browser/ui/cocoa/tab_contents/sad_tab_view_unittest.mm
@@ -11,8 +11,8 @@
  public:
   SadTabViewTest() {
     NSRect content_frame = [[test_window() contentView] frame];
-    scoped_nsobject<SadTabView> view([[SadTabView alloc]
-                                      initWithFrame:content_frame]);
+    base::scoped_nsobject<SadTabView> view(
+        [[SadTabView alloc] initWithFrame:content_frame]);
     view_ = view.get();
     [[test_window() contentView] addSubview:view_];
   }
diff --git a/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.mm b/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.mm
index 51d4c5b..5d54f76 100644
--- a/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.mm
+++ b/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.mm
@@ -6,7 +6,7 @@
 
 #include <utility>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/devtools/devtools_window.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/render_widget_host_view.h"
@@ -32,7 +32,7 @@
 }
 
 - (void)loadView {
-  scoped_nsobject<NSView> view([[NSView alloc] initWithFrame:NSZeroRect]);
+  base::scoped_nsobject<NSView> view([[NSView alloc] initWithFrame:NSZeroRect]);
   [view setAutoresizingMask:NSViewHeightSizable|NSViewWidthSizable];
   [self setView:view];
 }
diff --git a/chrome/browser/ui/cocoa/tab_modal_confirm_dialog_mac.h b/chrome/browser/ui/cocoa/tab_modal_confirm_dialog_mac.h
index 6a88203..0ead38a 100644
--- a/chrome/browser/ui/cocoa/tab_modal_confirm_dialog_mac.h
+++ b/chrome/browser/ui/cocoa/tab_modal_confirm_dialog_mac.h
@@ -47,8 +47,8 @@
 
   scoped_ptr<ConstrainedWindowMac> window_;
   scoped_ptr<TabModalConfirmDialogDelegate> delegate_;
-  scoped_nsobject<ConstrainedWindowAlert> alert_;
-  scoped_nsobject<TabModalConfirmDialogMacBridge> bridge_;
+  base::scoped_nsobject<ConstrainedWindowAlert> alert_;
+  base::scoped_nsobject<TabModalConfirmDialogMacBridge> bridge_;
 
   DISALLOW_COPY_AND_ASSIGN(TabModalConfirmDialogMac);
 };
diff --git a/chrome/browser/ui/cocoa/tab_modal_confirm_dialog_mac.mm b/chrome/browser/ui/cocoa/tab_modal_confirm_dialog_mac.mm
index ffc806f..e9b938e 100644
--- a/chrome/browser/ui/cocoa/tab_modal_confirm_dialog_mac.mm
+++ b/chrome/browser/ui/cocoa/tab_modal_confirm_dialog_mac.mm
@@ -4,7 +4,7 @@
 
 #include "chrome/browser/ui/cocoa/tab_modal_confirm_dialog_mac.h"
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/ui/browser_dialogs.h"
 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_alert.h"
 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_sheet.h"
@@ -73,7 +73,7 @@
   [[alert_ closeButton] setAction:@selector(onCancelButton:)];
   [alert_ layout];
 
-  scoped_nsobject<CustomConstrainedWindowSheet> sheet(
+  base::scoped_nsobject<CustomConstrainedWindowSheet> sheet(
       [[CustomConstrainedWindowSheet alloc]
           initWithCustomWindow:[alert_ window]]);
   window_.reset(new ConstrainedWindowMac(this, web_contents, sheet));
diff --git a/chrome/browser/ui/cocoa/table_row_nsimage_cache.h b/chrome/browser/ui/cocoa/table_row_nsimage_cache.h
index d0829fe..4932aa2 100644
--- a/chrome/browser/ui/cocoa/table_row_nsimage_cache.h
+++ b/chrome/browser/ui/cocoa/table_row_nsimage_cache.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 
 namespace gfx {
 class ImageSkia;
@@ -50,7 +50,7 @@
 
   // Stores strong NSImage refs for icons. If an entry is NULL, it will be
   // created in GetImageForRow().
-  scoped_nsobject<NSPointerArray> icon_images_;
+  base::scoped_nsobject<NSPointerArray> icon_images_;
 };
 
 #endif  // CHROME_BROWSER_UI_COCOA_TABLE_ROW_NSIMAGE_CACHE_H_
diff --git a/chrome/browser/ui/cocoa/tabpose_window.h b/chrome/browser/ui/cocoa/tabpose_window.h
index b2e0f28..7651812 100644
--- a/chrome/browser/ui/cocoa/tabpose_window.h
+++ b/chrome/browser/ui/cocoa/tabpose_window.h
@@ -9,7 +9,7 @@
 
 #include "base/mac/scoped_cftyperef.h"
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/scoped_vector.h"
 
@@ -54,17 +54,17 @@
   CALayer* selectionHighlight_;  // weak
 
   // Colors used by the layers.
-  base::mac::ScopedCFTypeRef<CGColorRef> gray_;
-  base::mac::ScopedCFTypeRef<CGColorRef> darkBlue_;
+  base::ScopedCFTypeRef<CGColorRef> gray_;
+  base::ScopedCFTypeRef<CGColorRef> darkBlue_;
 
   TabStripModel* tabStripModel_;  // weak
 
   // Stores all preview layers. The order in here matches the order in
   // the tabstrip model.
-  scoped_nsobject<NSMutableArray> allThumbnailLayers_;
+  base::scoped_nsobject<NSMutableArray> allThumbnailLayers_;
 
-  scoped_nsobject<NSMutableArray> allFaviconLayers_;
-  scoped_nsobject<NSMutableArray> allTitleLayers_;
+  base::scoped_nsobject<NSMutableArray> allFaviconLayers_;
+  base::scoped_nsobject<NSMutableArray> allTitleLayers_;
 
   // Manages the state of all layers.
   scoped_ptr<tabpose::TileSet> tileSet_;
@@ -77,7 +77,7 @@
   scoped_ptr<TabStripModelObserverBridge> tabStripModelObserverBridge_;
 
   // The icon used for the closebutton layers.
-  base::mac::ScopedCFTypeRef<CGImageRef> closeIcon_;
+  base::ScopedCFTypeRef<CGImageRef> closeIcon_;
 
   // True if all close layers should be shown (as opposed to just the close
   // layer of the currently selected thumbnail).
diff --git a/chrome/browser/ui/cocoa/tabpose_window.mm b/chrome/browser/ui/cocoa/tabpose_window.mm
index 339abd7..1921489 100644
--- a/chrome/browser/ui/cocoa/tabpose_window.mm
+++ b/chrome/browser/ui/cocoa/tabpose_window.mm
@@ -89,11 +89,11 @@
 }
 
 - (void)drawInContext:(CGContextRef)context {
-  base::mac::ScopedCFTypeRef<CGColorSpaceRef> grayColorSpace(
+  base::ScopedCFTypeRef<CGColorSpaceRef> grayColorSpace(
       CGColorSpaceCreateWithName(kCGColorSpaceGenericGray));
   CGFloat grays[] = { startGray_, 1.0, endGray_, 1.0 };
   CGFloat locations[] = { 0, 1 };
-  base::mac::ScopedCFTypeRef<CGGradientRef> gradient(
+  base::ScopedCFTypeRef<CGGradientRef> gradient(
       CGGradientCreateWithColorComponents(
           grayColorSpace.get(), grays, locations, arraysize(locations)));
   CGPoint topLeft = CGPointMake(0.0, self.bounds.size.height);
@@ -120,7 +120,7 @@
 
   // If the backing store couldn't be used and a thumbnail was returned from a
   // renderer process, it's stored in |thumbnail_|.
-  base::mac::ScopedCFTypeRef<CGImageRef> thumbnail_;
+  base::ScopedCFTypeRef<CGImageRef> thumbnail_;
 
   // True if the layer already sent a thumbnail request to a renderer.
   BOOL didSendLoad_;
@@ -976,10 +976,10 @@
                 showZoom:(BOOL)showZoom
                    slomo:(BOOL)slomo
        animationDelegate:(id)animationDelegate {
-  scoped_nsobject<CALayer> layer([[ThumbnailLayer alloc]
-      initWithWebContents:tile.web_contents()
-                 fullSize:tile.GetStartRectRelativeTo(
-                     tileSet_->selected_tile()).size]);
+  base::scoped_nsobject<CALayer> layer(
+      [[ThumbnailLayer alloc] initWithWebContents:tile.web_contents()
+                                         fullSize:tile.GetStartRectRelativeTo(
+                                             tileSet_->selected_tile()).size]);
   [layer setNeedsDisplay];
 
   NSTimeInterval interval =
@@ -1031,7 +1031,7 @@
   NSFont* font = [NSFont systemFontOfSize:tile.title_font_size()];
   tile.set_font_metrics([font ascender], -[font descender]);
 
-  base::mac::ScopedCFTypeRef<CGImageRef> favicon(
+  base::ScopedCFTypeRef<CGImageRef> favicon(
       base::mac::CopyNSImageToCGImage(tile.favicon()));
 
   CALayer* faviconLayer = [CALayer layer];
@@ -1611,15 +1611,15 @@
   tileSet_->MoveTileFromTo(from, to);
 
   // Move corresponding layers from |from| to |to|.
-  scoped_nsobject<CALayer> thumbLayer(
+  base::scoped_nsobject<CALayer> thumbLayer(
       [[allThumbnailLayers_ objectAtIndex:from] retain]);
   [allThumbnailLayers_ removeObjectAtIndex:from];
   [allThumbnailLayers_ insertObject:thumbLayer.get() atIndex:to];
-  scoped_nsobject<CALayer> faviconLayer(
+  base::scoped_nsobject<CALayer> faviconLayer(
       [[allFaviconLayers_ objectAtIndex:from] retain]);
   [allFaviconLayers_ removeObjectAtIndex:from];
   [allFaviconLayers_ insertObject:faviconLayer.get() atIndex:to];
-  scoped_nsobject<CALayer> titleLayer(
+  base::scoped_nsobject<CALayer> titleLayer(
       [[allTitleLayers_ objectAtIndex:from] retain]);
   [allTitleLayers_ removeObjectAtIndex:from];
   [allTitleLayers_ insertObject:titleLayer.get() atIndex:to];
diff --git a/chrome/browser/ui/cocoa/tabpose_window_unittest.mm b/chrome/browser/ui/cocoa/tabpose_window_unittest.mm
index bace43e..fdeba6c 100644
--- a/chrome/browser/ui/cocoa/tabpose_window_unittest.mm
+++ b/chrome/browser/ui/cocoa/tabpose_window_unittest.mm
@@ -25,7 +25,7 @@
 
   void AppendTabToStrip() {
     content::WebContents* web_contents = content::WebContents::Create(
-        content::WebContents::CreateParams(profile(), site_instance_));
+        content::WebContents::CreateParams(profile(), site_instance_.get()));
     browser()->tab_strip_model()->AppendWebContents(
         web_contents, /*foreground=*/true);
   }
diff --git a/chrome/browser/ui/cocoa/tabs/tab_audio_indicator_view_mac.h b/chrome/browser/ui/cocoa/tabs/tab_audio_indicator_view_mac.h
index 4150bef..4a21e7d 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_audio_indicator_view_mac.h
+++ b/chrome/browser/ui/cocoa/tabs/tab_audio_indicator_view_mac.h
@@ -7,7 +7,6 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 
 namespace content {
diff --git a/chrome/browser/ui/cocoa/tabs/tab_audio_indicator_view_mac_unittest.mm b/chrome/browser/ui/cocoa/tabs/tab_audio_indicator_view_mac_unittest.mm
index 478df04..b4b3620 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_audio_indicator_view_mac_unittest.mm
+++ b/chrome/browser/ui/cocoa/tabs/tab_audio_indicator_view_mac_unittest.mm
@@ -5,18 +5,19 @@
 #import "chrome/browser/ui/cocoa/tabs/tab_audio_indicator_view_mac.h"
 
 #include "base/message_loop.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 
 class TabAudioIndicatorViewMacTest : public CocoaTest {
  protected:
   TabAudioIndicatorViewMacTest() {
-    scoped_nsobject<TabAudioIndicatorViewMac> view(
+    base::scoped_nsobject<TabAudioIndicatorViewMac> view(
         [[TabAudioIndicatorViewMac alloc]
             initWithFrame:NSMakeRect(0, 0, 16, 16)]);
     view_ = view.get();
     [[test_window() contentView] addSubview:view_];
 
-    scoped_nsobject<NSImage> image(
+    base::scoped_nsobject<NSImage> image(
         [[NSImage alloc] initWithSize:NSMakeSize(16, 16)]);
     [image lockFocus];
     NSRectFill(NSMakeRect(0, 0, 16, 16));
diff --git a/chrome/browser/ui/cocoa/tabs/tab_controller.h b/chrome/browser/ui/cocoa/tabs/tab_controller.h
index d75d8d6..93cdbe4 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_controller.h
+++ b/chrome/browser/ui/cocoa/tabs/tab_controller.h
@@ -40,9 +40,9 @@
 
 @interface TabController : NSViewController<TabDraggingEventTarget> {
  @private
-  scoped_nsobject<NSView> iconView_;
-  scoped_nsobject<NSTextField> titleView_;
-  scoped_nsobject<HoverCloseButton> closeButton_;
+  base::scoped_nsobject<NSView> iconView_;
+  base::scoped_nsobject<NSTextField> titleView_;
+  base::scoped_nsobject<HoverCloseButton> closeButton_;
 
   NSRect originalIconFrame_;  // frame of iconView_ as loaded from nib
   BOOL isIconShowing_;  // last state of iconView_ in updateVisibility
@@ -60,7 +60,7 @@
   SEL action_;  // selector sent when tab is selected by clicking
   scoped_ptr<ui::SimpleMenuModel> contextMenuModel_;
   scoped_ptr<TabControllerInternal::MenuDelegate> contextMenuDelegate_;
-  scoped_nsobject<MenuController> contextMenuController_;
+  base::scoped_nsobject<MenuController> contextMenuController_;
 }
 
 @property(assign, nonatomic) TabLoadingState loadingState;
diff --git a/chrome/browser/ui/cocoa/tabs/tab_controller.mm b/chrome/browser/ui/cocoa/tabs/tab_controller.mm
index 3e7924c..1006ef0 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_controller.mm
+++ b/chrome/browser/ui/cocoa/tabs/tab_controller.mm
@@ -102,7 +102,7 @@
     // Label.
     titleView_.reset([[NSTextField alloc] initWithFrame:titleFrame]);
     [titleView_ setAutoresizingMask:NSViewWidthSizable];
-    scoped_nsobject<GTMFadeTruncatingTextFieldCell> labelCell(
+    base::scoped_nsobject<GTMFadeTruncatingTextFieldCell> labelCell(
         [[GTMFadeTruncatingTextFieldCell alloc] initTextCell:@"Label"]);
     [labelCell setControlSize:NSSmallControlSize];
     CGFloat fontSize = [NSFont systemFontSizeForControlSize:NSSmallControlSize];
@@ -118,8 +118,10 @@
     [closeButton_ setTarget:self];
     [closeButton_ setAction:@selector(closeTab:)];
 
-    scoped_nsobject<TabView> view([[TabView alloc] initWithFrame:
-        NSMakeRect(0, 0, 160, 25) controller:self closeButton:closeButton_]);
+    base::scoped_nsobject<TabView> view(
+        [[TabView alloc] initWithFrame:NSMakeRect(0, 0, 160, 25)
+                            controller:self
+                           closeButton:closeButton_]);
     [view setAutoresizingMask:NSViewMaxXMargin | NSViewMinYMargin];
     [view addSubview:iconView_];
     [view addSubview:titleView_];
diff --git a/chrome/browser/ui/cocoa/tabs/tab_controller_unittest.mm b/chrome/browser/ui/cocoa/tabs/tab_controller_unittest.mm
index f039c3b..ad24ca7 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/tabs/tab_controller_unittest.mm
@@ -4,7 +4,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #import "chrome/browser/ui/cocoa/tabs/tab_controller.h"
@@ -20,7 +20,7 @@
  @private
   bool selected_;
   bool closed_;
-  scoped_nsobject<TabStripDragController> dragController_;
+  base::scoped_nsobject<TabStripDragController> dragController_;
 }
 - (bool)selected;
 - (bool)closed;
@@ -101,7 +101,7 @@
 // Tests creating the controller, sticking it in a window, and removing it.
 TEST_F(TabControllerTest, Creation) {
   NSWindow* window = test_window();
-  scoped_nsobject<TabController> controller([[TabController alloc] init]);
+  base::scoped_nsobject<TabController> controller([[TabController alloc] init]);
   [[window contentView] addSubview:[controller view]];
   EXPECT_TRUE([controller tabView]);
   EXPECT_EQ([[controller view] window], window);
@@ -113,10 +113,10 @@
 // called. Mimics the user clicking on the close button in the tab.
 TEST_F(TabControllerTest, Close) {
   NSWindow* window = test_window();
-  scoped_nsobject<TabController> controller([[TabController alloc] init]);
+  base::scoped_nsobject<TabController> controller([[TabController alloc] init]);
   [[window contentView] addSubview:[controller view]];
 
-  scoped_nsobject<TabControllerTestTarget> target(
+  base::scoped_nsobject<TabControllerTestTarget> target(
       [[TabControllerTestTarget alloc] init]);
   EXPECT_FALSE([target closed]);
   [controller setTarget:target];
@@ -131,7 +131,7 @@
 // Tests setting the |selected| property via code.
 TEST_F(TabControllerTest, APISelection) {
   NSWindow* window = test_window();
-  scoped_nsobject<TabController> controller([[TabController alloc] init]);
+  base::scoped_nsobject<TabController> controller([[TabController alloc] init]);
   [[window contentView] addSubview:[controller view]];
 
   EXPECT_FALSE([controller selected]);
@@ -145,7 +145,7 @@
 TEST_F(TabControllerTest, ToolTip) {
   NSWindow* window = test_window();
 
-  scoped_nsobject<TabController> controller([[TabController alloc] init]);
+  base::scoped_nsobject<TabController> controller([[TabController alloc] init]);
   [[window contentView] addSubview:[controller view]];
 
   EXPECT_TRUE([[controller toolTip] length] == 0);
@@ -157,7 +157,7 @@
 // Tests setting the |loading| property via code.
 TEST_F(TabControllerTest, Loading) {
   NSWindow* window = test_window();
-  scoped_nsobject<TabController> controller([[TabController alloc] init]);
+  base::scoped_nsobject<TabController> controller([[TabController alloc] init]);
   [[window contentView] addSubview:[controller view]];
 
   EXPECT_EQ(kTabDone, [controller loadingState]);
@@ -178,7 +178,7 @@
 
   // Create a tab at a known location in the window that we can click on
   // to activate selection.
-  scoped_nsobject<TabController> controller([[TabController alloc] init]);
+  base::scoped_nsobject<TabController> controller([[TabController alloc] init]);
   [[window contentView] addSubview:[controller view]];
   NSRect frame = [[controller view] frame];
   frame.size.width = [TabController minTabWidth];
@@ -186,7 +186,7 @@
   [[controller view] setFrame:frame];
 
   // Set the target and action.
-  scoped_nsobject<TabControllerTestTarget> target(
+  base::scoped_nsobject<TabControllerTestTarget> target(
       [[TabControllerTestTarget alloc] init]);
   EXPECT_FALSE([target selected]);
   [controller setTarget:target];
@@ -224,7 +224,7 @@
 
 TEST_F(TabControllerTest, IconCapacity) {
   NSWindow* window = test_window();
-  scoped_nsobject<TabController> controller([[TabController alloc] init]);
+  base::scoped_nsobject<TabController> controller([[TabController alloc] init]);
   [[window contentView] addSubview:[controller view]];
   int cap = [controller iconCapacity];
   EXPECT_GE(cap, 1);
@@ -238,7 +238,7 @@
 
 TEST_F(TabControllerTest, ShouldShowIcon) {
   NSWindow* window = test_window();
-  scoped_nsobject<TabController> controller([[TabController alloc] init]);
+  base::scoped_nsobject<TabController> controller([[TabController alloc] init]);
   [[window contentView] addSubview:[controller view]];
   int cap = [controller iconCapacity];
   EXPECT_GT(cap, 0);
@@ -251,7 +251,7 @@
   EXPECT_FALSE([controller shouldShowCloseButton]);
 
   // Setting the icon when tab is at min width should not show icon (bug 18359).
-  scoped_nsobject<NSView> newIcon(
+  base::scoped_nsobject<NSView> newIcon(
       [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 16, 16)]);
   [controller setIconView:newIcon.get()];
   EXPECT_TRUE([newIcon isHidden]);
@@ -283,8 +283,8 @@
 
 TEST_F(TabControllerTest, Menu) {
   NSWindow* window = test_window();
-  scoped_nsobject<TabController> controller([[TabController alloc] init]);
-  scoped_nsobject<TabControllerTestTarget> target(
+  base::scoped_nsobject<TabController> controller([[TabController alloc] init]);
+  base::scoped_nsobject<TabControllerTestTarget> target(
       [[TabControllerTestTarget alloc] init]);
   [controller setTarget:target];
 
@@ -303,7 +303,7 @@
 TEST_F(TabControllerTest, TitleViewLayout) {
   NSWindow* window = test_window();
 
-  scoped_nsobject<TabController> controller([[TabController alloc] init]);
+  base::scoped_nsobject<TabController> controller([[TabController alloc] init]);
   [[window contentView] addSubview:[controller view]];
   NSRect tabFrame = [[controller view] frame];
   tabFrame.size.width = [TabController maxTabWidth];
diff --git a/chrome/browser/ui/cocoa/tabs/tab_projecting_image_view.h b/chrome/browser/ui/cocoa/tabs/tab_projecting_image_view.h
index 9b07b5b..7f74b16 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_projecting_image_view.h
+++ b/chrome/browser/ui/cocoa/tabs/tab_projecting_image_view.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #include "chrome/browser/ui/cocoa/tabs/throbbing_image_view.h"
 
@@ -16,7 +16,7 @@
 // animated glow. This view paints outside the favicon bounds due to the glow.
 @interface TabProjectingImageView : ThrobbingImageView {
  @private
-  scoped_nsobject<NSImage> projectorImage_;
+  base::scoped_nsobject<NSImage> projectorImage_;
 }
 
 - (id)initWithFrame:(NSRect)rect
diff --git a/chrome/browser/ui/cocoa/tabs/tab_projecting_image_view_unittest.mm b/chrome/browser/ui/cocoa/tabs/tab_projecting_image_view_unittest.mm
index 25bc7dd..ab10080 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_projecting_image_view_unittest.mm
+++ b/chrome/browser/ui/cocoa/tabs/tab_projecting_image_view_unittest.mm
@@ -14,31 +14,31 @@
 class TabProjectingImageViewTest : public CocoaTest {
  public:
   TabProjectingImageViewTest() {
-    scoped_nsobject<NSImage> backgroundImage(
+    base::scoped_nsobject<NSImage> backgroundImage(
         [[NSImage alloc] initWithSize:NSMakeSize(16, 16)]);
     [backgroundImage lockFocus];
     NSRectFill(NSMakeRect(0, 0, 16, 16));
     [backgroundImage unlockFocus];
 
-    scoped_nsobject<NSImage> projectorImage(
+    base::scoped_nsobject<NSImage> projectorImage(
         [[NSImage alloc] initWithSize:NSMakeSize(16, 16)]);
     [projectorImage lockFocus];
     NSRectFill(NSMakeRect(0, 0, 16, 16));
     [projectorImage unlockFocus];
 
-    scoped_nsobject<NSImage> throbImage(
+    base::scoped_nsobject<NSImage> throbImage(
         [[NSImage alloc] initWithSize:NSMakeSize(32, 32)]);
     [throbImage lockFocus];
     NSRectFill(NSMakeRect(0, 0, 32, 32));
     [throbImage unlockFocus];
 
-    scoped_nsobject<TabProjectingImageView> view([[TabProjectingImageView alloc]
-              initWithFrame:NSMakeRect(0, 0, 32, 32)
-            backgroundImage:backgroundImage
-             projectorImage:projectorImage
-                 throbImage:throbImage
-                 durationMS:20
-         animationContainer:NULL]);
+    base::scoped_nsobject<TabProjectingImageView> view(
+        [[TabProjectingImageView alloc] initWithFrame:NSMakeRect(0, 0, 32, 32)
+                                      backgroundImage:backgroundImage
+                                       projectorImage:projectorImage
+                                           throbImage:throbImage
+                                           durationMS:20
+                                   animationContainer:NULL]);
     view_ = view.get();
     [[test_window() contentView] addSubview:view_];
   }
diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.h b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.h
index dc5e357..216ff3b 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.h
+++ b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #import "chrome/browser/ui/cocoa/tabs/tab_controller_target.h"
 #import "chrome/browser/ui/cocoa/url_drop_target.h"
@@ -61,16 +61,17 @@
   NSObject<TabControllerTarget,
            URLDropTargetController> {
  @private
-  scoped_nsobject<TabStripView> tabStripView_;
+  base::scoped_nsobject<TabStripView> tabStripView_;
   NSView* switchView_;  // weak
-  scoped_nsobject<NSView> dragBlockingView_;  // avoid bad window server drags
+  base::scoped_nsobject<NSView> dragBlockingView_;  // avoid bad window server
+                                                    // drags
   NewTabButton* newTabButton_;  // weak, obtained from the nib.
 
   // The controller that manages all the interactions of dragging tabs.
-  scoped_nsobject<TabStripDragController> dragController_;
+  base::scoped_nsobject<TabStripDragController> dragController_;
 
   // Tracks the newTabButton_ for rollovers.
-  scoped_nsobject<CrTrackingArea> newTabTrackingArea_;
+  base::scoped_nsobject<CrTrackingArea> newTabTrackingArea_;
   scoped_ptr<TabStripModelObserverBridge> bridge_;
   Browser* browser_;  // weak
   TabStripModel* tabStripModel_;  // weak
@@ -89,14 +90,14 @@
   // tabs are animating closed (closed tabs are removed from |tabStripModel_|
   // immediately, but from |tabContentsArray_| only after their close animation
   // has completed).
-  scoped_nsobject<NSMutableArray> tabContentsArray_;
+  base::scoped_nsobject<NSMutableArray> tabContentsArray_;
   // An array of TabControllers which manage the actual tab views. See note
   // above |tabContentsArray_|. |tabContentsArray_| and |tabArray_| always
   // contain objects belonging to the same tabs at the same indices.
-  scoped_nsobject<NSMutableArray> tabArray_;
+  base::scoped_nsobject<NSMutableArray> tabArray_;
 
   // Set of TabControllers that are currently animating closed.
-  scoped_nsobject<NSMutableSet> closingControllers_;
+  base::scoped_nsobject<NSMutableSet> closingControllers_;
 
   // These values are only used during a drag, and override tab positioning.
   TabView* placeholderTab_;  // weak. Tab being dragged
@@ -105,7 +106,7 @@
   // Frame targets for all the current views.
   // target frames are used because repeated requests to [NSView animator].
   // aren't coalesced, so we store frames to avoid redundant calls.
-  scoped_nsobject<NSMutableDictionary> targetFrames_;
+  base::scoped_nsobject<NSMutableDictionary> targetFrames_;
   NSRect newTabTargetFrame_;
   // If YES, do not show the new tab button during layout.
   BOOL forceNewTabButtonHidden_;
@@ -121,15 +122,15 @@
   float availableResizeWidth_;
   // A tracking area that's the size of the tab strip used to be notified
   // when the mouse moves in the tab strip
-  scoped_nsobject<CrTrackingArea> trackingArea_;
+  base::scoped_nsobject<CrTrackingArea> trackingArea_;
   TabView* hoveredTab_;  // weak. Tab that the mouse is hovering over
 
   // Array of subviews which are permanent (and which should never be removed),
   // such as the new-tab button, but *not* the tabs themselves.
-  scoped_nsobject<NSMutableArray> permanentSubviews_;
+  base::scoped_nsobject<NSMutableArray> permanentSubviews_;
 
   // The default favicon, so we can use one copy for all buttons.
-  scoped_nsobject<NSImage> defaultFavicon_;
+  base::scoped_nsobject<NSImage> defaultFavicon_;
 
   // The amount by which to indent the tabs on the sides (to make room for the
   // red/yellow/green and incognito/fullscreen buttons).
diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
index de91256..b7f1c9d 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
+++ b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
@@ -162,7 +162,7 @@
 // 10.6 and 10.7.
 NSImage* CreateImageWithSize(NSSize size,
                              void (^drawingHandler)(NSSize)) {
-  scoped_nsobject<NSImage> result([[NSImage alloc] initWithSize:size]);
+  base::scoped_nsobject<NSImage> result([[NSImage alloc] initWithSize:size]);
   [NSGraphicsContext saveGraphicsState];
   for (ui::ScaleFactor scale_factor : ui::GetSupportedScaleFactors()) {
     float scale = GetScaleFactorScale(scale_factor);
@@ -1296,7 +1296,7 @@
 
   // Make a new tab. Load the contents of this tab from the nib and associate
   // the new controller with |contents| so it can be looked up later.
-  scoped_nsobject<TabContentsController> contentsController(
+  base::scoped_nsobject<TabContentsController> contentsController(
       [[TabContentsController alloc] initWithContents:contents]);
   [tabContentsArray_ insertObject:contentsController atIndex:index];
 
@@ -1410,7 +1410,7 @@
   // Simply create a new TabContentsController for |newContents| and place it
   // into the array, replacing |oldContents|.  An ActiveTabChanged notification
   // will follow, at which point we will install the new view.
-  scoped_nsobject<TabContentsController> newController(
+  base::scoped_nsobject<TabContentsController> newController(
       [[TabContentsController alloc] initWithContents:newContents]);
 
   // Bye bye, |oldController|.
@@ -1491,9 +1491,9 @@
   NSView* tabView = [closingTab view];
   CAAnimation* animation = [[tabView animationForKey:@"frameOrigin"] copy];
   [animation autorelease];
-  scoped_nsobject<TabCloseAnimationDelegate> delegate(
-    [[TabCloseAnimationDelegate alloc] initWithTabStrip:self
-                                          tabController:closingTab]);
+  base::scoped_nsobject<TabCloseAnimationDelegate> delegate(
+      [[TabCloseAnimationDelegate alloc] initWithTabStrip:self
+                                            tabController:closingTab]);
   [animation setDelegate:delegate.get()];  // Retains delegate.
   NSMutableDictionary* animationDictionary =
       [NSMutableDictionary dictionaryWithDictionary:[tabView animations]];
@@ -1636,7 +1636,7 @@
                  projectorImage:projector
                      throbImage:projectorGlow
                      durationMS:kRecordingDurationMs
-             animationContainer:animationContainer_] autorelease];
+             animationContainer:animationContainer_.get()] autorelease];
 
           iconView = projectingView;
         } else if (theme && chrome::ShouldShowRecordingIndicator(contents)) {
@@ -1655,7 +1655,7 @@
                      throbImage:recording
                      durationMS:kRecordingDurationMs
                   throbPosition:kThrobPositionBottomRight
-             animationContainer:animationContainer_] autorelease];
+             animationContainer:animationContainer_.get()] autorelease];
 
           iconView = recordingView;
         } else if (chrome::IsPlayingAudio(contents) ||
@@ -1666,7 +1666,7 @@
             tabAudioIndicatorViewMac = [[[TabAudioIndicatorViewMac alloc]
                 initWithFrame:frame] autorelease];
             [tabAudioIndicatorViewMac
-                setAnimationContainer:animationContainer_];
+                setAnimationContainer:animationContainer_.get()];
           }
           [tabAudioIndicatorViewMac
               setIsPlayingAudio:chrome::IsPlayingAudio(contents)];
@@ -1746,12 +1746,12 @@
   // Cancel any pending tab transition.
   hoverTabSelector_->CancelTabTransition();
 
-  scoped_nsobject<TabContentsController> movedTabContentsController(
+  base::scoped_nsobject<TabContentsController> movedTabContentsController(
       [[tabContentsArray_ objectAtIndex:from] retain]);
   [tabContentsArray_ removeObjectAtIndex:from];
   [tabContentsArray_ insertObject:movedTabContentsController.get()
                           atIndex:to];
-  scoped_nsobject<TabController> movedTabController(
+  base::scoped_nsobject<TabController> movedTabController(
       [[tabArray_ objectAtIndex:from] retain]);
   DCHECK([movedTabController isKindOfClass:[TabController class]]);
   [tabArray_ removeObjectAtIndex:from];
@@ -2044,6 +2044,7 @@
   if (activeTabView) {
     [subviews addObject:activeTabView];
   }
+  WithNoAnimation noAnimation;
   [tabStripView_ setSubviews:subviews];
   [self setTabTrackingAreasEnabled:mouseInside_];
 }
diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_controller_unittest.mm b/chrome/browser/ui/cocoa/tabs/tab_strip_controller_unittest.mm
index 025caae..cf230d1 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_strip_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/tabs/tab_strip_controller_unittest.mm
@@ -93,7 +93,7 @@
     // Create the "switch view" (view that gets changed out when a tab
     // switches).
     NSRect switch_frame = NSMakeRect(0, 0, content_frame.size.width, 500);
-    scoped_nsobject<NSView> switch_view(
+    base::scoped_nsobject<NSView> switch_view(
         [[NSView alloc] initWithFrame:switch_frame]);
     [parent addSubview:switch_view.get()];
 
@@ -105,7 +105,7 @@
         [[TabStripView alloc] initWithFrame:strip_frame]);
     [parent addSubview:tab_strip_.get()];
     NSRect button_frame = NSMakeRect(0, 0, 15, 15);
-    scoped_nsobject<NewTabButton> new_tab_button(
+    base::scoped_nsobject<NewTabButton> new_tab_button(
         [[NewTabButton alloc] initWithFrame:button_frame]);
     [tab_strip_ addSubview:new_tab_button.get()];
     [tab_strip_ setNewTabButton:new_tab_button.get()];
@@ -152,9 +152,9 @@
 
   scoped_ptr<TestTabStripModelDelegate> delegate_;
   TabStripModel* model_;
-  scoped_nsobject<TestTabStripControllerDelegate> controller_delegate_;
-  scoped_nsobject<TabStripController> controller_;
-  scoped_nsobject<TabStripView> tab_strip_;
+  base::scoped_nsobject<TestTabStripControllerDelegate> controller_delegate_;
+  base::scoped_nsobject<TabStripController> controller_;
+  base::scoped_nsobject<TabStripView> tab_strip_;
 };
 
 // Test adding and removing tabs and making sure that views get added to
@@ -240,10 +240,9 @@
   // Schedule a task to close all the tabs and stop the drag, before the call to
   // -maybeStartDrag:forTab:, which starts a nested event loop. This task will
   // run in that nested event loop, which shouldn't crash.
-  scoped_nsobject<TestClosureRunner> runner(
-      [[TestClosureRunner alloc] initWithClosure:
-          base::Bind(&TabStripControllerTest::CloseTabsAndEndDrag,
-                     base::Unretained(this))]);
+  base::scoped_nsobject<TestClosureRunner> runner([[TestClosureRunner alloc]
+      initWithClosure:base::Bind(&TabStripControllerTest::CloseTabsAndEndDrag,
+                                 base::Unretained(this))]);
   [runner scheduleDelayedRun];
 
   NSEvent* event =
diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_drag_controller.mm b/chrome/browser/ui/cocoa/tabs/tab_strip_drag_controller.mm
index 2a338bb..e24351a 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_strip_drag_controller.mm
+++ b/chrome/browser/ui/cocoa/tabs/tab_strip_drag_controller.mm
@@ -108,8 +108,8 @@
   // When spinning the event loop, a tab can get detached, which could lead to
   // our own destruction. Keep ourselves around while spinning the loop as well
   // as the tab controller being dragged.
-  scoped_nsobject<TabStripDragController> keepAlive([self retain]);
-  scoped_nsobject<TabController> keepAliveTab([tab retain]);
+  base::scoped_nsobject<TabStripDragController> keepAlive([self retain]);
+  base::scoped_nsobject<TabController> keepAliveTab([tab retain]);
 
   // Because we move views between windows, we need to handle the event loop
   // ourselves. Ideally we should use the standard event loop.
diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_view.h b/chrome/browser/ui/cocoa/tabs/tab_strip_view.h
index 1cb4ba2..c919671 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_strip_view.h
+++ b/chrome/browser/ui/cocoa/tabs/tab_strip_view.h
@@ -7,7 +7,8 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
+#import "chrome/browser/ui/cocoa/background_gradient_view.h"
 #import "chrome/browser/ui/cocoa/url_drop_target.h"
 
 @class NewTabButton;
@@ -16,16 +17,16 @@
 // A view class that handles rendering the tab strip and drops of URLS with
 // a positioning locator for drop feedback.
 
-@interface TabStripView : NSView<URLDropTarget> {
+@interface TabStripView : BackgroundGradientView<URLDropTarget> {
  @private
   TabStripController* controller_;  // Weak; owns us.
 
   NSTimeInterval lastMouseUp_;
 
   // Handles being a drag-and-drop target.
-  scoped_nsobject<URLDropTargetHandler> dropHandler_;
+  base::scoped_nsobject<URLDropTargetHandler> dropHandler_;
 
-  scoped_nsobject<NewTabButton> newTabButton_;
+  base::scoped_nsobject<NewTabButton> newTabButton_;
 
   // Whether the drop-indicator arrow is shown, and if it is, the coordinate of
   // its tip.
diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_view_unittest.mm b/chrome/browser/ui/cocoa/tabs/tab_strip_view_unittest.mm
index d7961aa..ed816bf 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_strip_view_unittest.mm
+++ b/chrome/browser/ui/cocoa/tabs/tab_strip_view_unittest.mm
@@ -4,7 +4,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #import "chrome/browser/ui/cocoa/tabs/tab_strip_view.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -16,7 +16,7 @@
  public:
   TabStripViewTest() {
     NSRect frame = NSMakeRect(0, 0, 100, 30);
-    scoped_nsobject<TabStripView> view(
+    base::scoped_nsobject<TabStripView> view(
         [[TabStripView alloc] initWithFrame:frame]);
     view_ = view.get();
     [[test_window() contentView] addSubview:view_];
diff --git a/chrome/browser/ui/cocoa/tabs/tab_view.h b/chrome/browser/ui/cocoa/tabs/tab_view.h
index 7f640d0..f5c3177 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_view.h
+++ b/chrome/browser/ui/cocoa/tabs/tab_view.h
@@ -5,11 +5,11 @@
 #ifndef CHROME_BROWSER_UI_COCOA_TABS_TAB_VIEW_H_
 #define CHROME_BROWSER_UI_COCOA_TABS_TAB_VIEW_H_
 
-#import <Cocoa/Cocoa.h>
 #include <ApplicationServices/ApplicationServices.h>
+#import <Cocoa/Cocoa.h>
 
 #include "base/mac/scoped_cftyperef.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/hover_close_button.h"
 
 namespace tabs {
@@ -70,11 +70,11 @@
   NSCellStateValue state_;
 
   // The tool tip text for this tab view.
-  scoped_nsobject<NSString> toolTipText_;
+  base::scoped_nsobject<NSString> toolTipText_;
 
   // A one-element mask image cache.  This cache makes drawing roughly 16%
   // faster.
-  base::mac::ScopedCFTypeRef<CGImageRef> maskCache_;
+  base::ScopedCFTypeRef<CGImageRef> maskCache_;
   CGFloat maskCacheWidth_;
   CGFloat maskCacheScale_;
 }
diff --git a/chrome/browser/ui/cocoa/tabs/tab_view.mm b/chrome/browser/ui/cocoa/tabs/tab_view.mm
index c312444..d7ff32f 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_view.mm
+++ b/chrome/browser/ui/cocoa/tabs/tab_view.mm
@@ -142,12 +142,8 @@
 // view or our child close button.
 - (NSView*)hitTest:(NSPoint)aPoint {
   NSPoint viewPoint = [self convertPoint:aPoint fromView:[self superview]];
-  if (![closeButton_ isHidden]) {
-    if (NSPointInRect(viewPoint,[closeButton_ frame]) &&
-        [closeButton_ hitTest:viewPoint]) {
-      return closeButton_;
-    }
-  }
+  if (![closeButton_ isHidden])
+    if (NSPointInRect(viewPoint, [closeButton_ frame])) return closeButton_;
 
   NSRect pointRect = NSMakeRect(viewPoint.x, viewPoint.y, 1, 1);
 
@@ -215,7 +211,7 @@
   // strip and then deallocated. This will also result in *us* being
   // deallocated. Both these are bad, so we prevent this by retaining the
   // controller.
-  scoped_nsobject<TabController> controller([controller_ retain]);
+  base::scoped_nsobject<TabController> controller([controller_ retain]);
 
   // Try to initiate a drag. This will spin a custom event loop and may
   // dispatch other mouse events.
@@ -383,7 +379,7 @@
     // Draw a mouse hover gradient for the default themes.
     if (!selected && hoverAlpha > 0) {
       if (themeProvider && !hasCustomTheme) {
-        scoped_nsobject<NSGradient> glow([NSGradient alloc]);
+        base::scoped_nsobject<NSGradient> glow([NSGradient alloc]);
         [glow initWithStartingColor:[NSColor colorWithCalibratedWhite:1.0
                                         alpha:1.0 * hoverAlpha]
                         endingColor:[NSColor colorWithCalibratedWhite:1.0
@@ -438,6 +434,13 @@
   [self drawStroke:dirtyRect];
 }
 
+- (void)setFrameOrigin:(NSPoint)origin {
+  // The background color depends on the view's vertical position.
+  if (NSMinY([self frame]) != origin.y)
+    [self setNeedsDisplay:YES];
+  [super setFrameOrigin:origin];
+}
+
 // Override this to catch the text so that we can choose when to display it.
 - (void)setToolTip:(NSString*)string {
   toolTipText_.reset([string retain]);
@@ -457,6 +460,13 @@
   }
 }
 
+- (void)setState:(NSCellStateValue)state {
+  if (state_ == state)
+    return;
+  state_ = state;
+  [self setNeedsDisplay:YES];
+}
+
 - (void)setClosing:(BOOL)closing {
   closing_ = closing;  // Safe because the property is nonatomic.
   // When closing, ensure clicks to the close button go nowhere.
@@ -671,7 +681,7 @@
 
   // Image masks must be in the DeviceGray colorspace. Create a context and
   // draw the mask into it.
-  base::mac::ScopedCFTypeRef<CGColorSpaceRef> colorspace(
+  base::ScopedCFTypeRef<CGColorSpaceRef> colorspace(
       CGColorSpaceCreateDeviceGray());
   CGContextRef maskContext =
       CGBitmapContextCreate(NULL, tabWidth * scale, kMaskHeight * scale,
diff --git a/chrome/browser/ui/cocoa/tabs/tab_view_unittest.mm b/chrome/browser/ui/cocoa/tabs/tab_view_unittest.mm
index e5f6c12..ccc1216 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_view_unittest.mm
+++ b/chrome/browser/ui/cocoa/tabs/tab_view_unittest.mm
@@ -4,7 +4,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #import "chrome/browser/ui/cocoa/tabs/tab_view.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -19,7 +19,7 @@
  public:
   TabViewTest() {
     NSRect frame = NSMakeRect(0, 0, kTabWidth, kTabHeight);
-    scoped_nsobject<TabView> view([[TabView alloc] initWithFrame:frame]);
+    base::scoped_nsobject<TabView> view([[TabView alloc] initWithFrame:frame]);
     view_ = view.get();
     [[test_window() contentView] addSubview:view_];
   }
diff --git a/chrome/browser/ui/cocoa/tabs/tab_window_controller.h b/chrome/browser/ui/cocoa/tabs/tab_window_controller.h
index 4242c2d..70693ff 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_window_controller.h
+++ b/chrome/browser/ui/cocoa/tabs/tab_window_controller.h
@@ -14,7 +14,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 
 @class FastResizeView;
 @class FocusTracker;
@@ -23,8 +23,8 @@
 
 @interface TabWindowController : NSWindowController<NSWindowDelegate> {
  @private
-  scoped_nsobject<FastResizeView> tabContentArea_;
-  scoped_nsobject<TabStripView> tabStripView_;
+  base::scoped_nsobject<FastResizeView> tabContentArea_;
+  base::scoped_nsobject<TabStripView> tabStripView_;
 
   // The child window used during dragging to achieve the opacity tricks.
   NSWindow* overlayWindow_;
@@ -33,7 +33,7 @@
   // of the drag) to the |overlayWindow_|.
   NSView* originalContentView_;  // weak
 
-  scoped_nsobject<FocusTracker> focusBeforeOverlay_;
+  base::scoped_nsobject<FocusTracker> focusBeforeOverlay_;
   BOOL closeDeferred_;  // If YES, call performClose: in removeOverlay:.
 }
 @property(readonly, nonatomic) TabStripView* tabStripView;
diff --git a/chrome/browser/ui/cocoa/tabs/tab_window_controller.mm b/chrome/browser/ui/cocoa/tabs/tab_window_controller.mm
index fa7a5e7..e49c875 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_window_controller.mm
+++ b/chrome/browser/ui/cocoa/tabs/tab_window_controller.mm
@@ -45,7 +45,7 @@
 
 - (id)initTabWindowControllerWithTabStrip:(BOOL)hasTabStrip {
   NSRect contentRect = NSMakeRect(60, 229, 750, 600);
-  scoped_nsobject<FramedBrowserWindow> window(
+  base::scoped_nsobject<FramedBrowserWindow> window(
       [[FramedBrowserWindow alloc] initWithContentRect:contentRect
                                            hasTabStrip:hasTabStrip]);
   [window setReleasedWhenClosed:YES];
diff --git a/chrome/browser/ui/cocoa/tabs/throbber_view.h b/chrome/browser/ui/cocoa/tabs/throbber_view.h
index 6e90ec0..ade4d7f 100644
--- a/chrome/browser/ui/cocoa/tabs/throbber_view.h
+++ b/chrome/browser/ui/cocoa/tabs/throbber_view.h
@@ -7,8 +7,6 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
-
 @protocol ThrobberDataDelegate;
 
 // A class that knows how to draw an animated state to indicate progress.
diff --git a/chrome/browser/ui/cocoa/tabs/throbber_view.mm b/chrome/browser/ui/cocoa/tabs/throbber_view.mm
index 29cc6df..0d838a3 100644
--- a/chrome/browser/ui/cocoa/tabs/throbber_view.mm
+++ b/chrome/browser/ui/cocoa/tabs/throbber_view.mm
@@ -7,6 +7,7 @@
 #include <set>
 
 #include "base/logging.h"
+#include "base/mac/scoped_nsobject.h"
 
 static const float kAnimationIntervalSeconds = 0.03;  // 30ms, same as windows
 
@@ -29,7 +30,7 @@
 
 @interface ThrobberFilmstripDelegate : NSObject
                                        <ThrobberDataDelegate> {
-  scoped_nsobject<NSImage> image_;
+  base::scoped_nsobject<NSImage> image_;
   unsigned int numFrames_;  // Number of frames in this animation.
   unsigned int animationFrame_;  // Current frame of the animation,
                                  // [0..numFrames_)
@@ -83,8 +84,8 @@
 
 @interface ThrobberToastDelegate : NSObject
                                    <ThrobberDataDelegate> {
-  scoped_nsobject<NSImage> image1_;
-  scoped_nsobject<NSImage> image2_;
+  base::scoped_nsobject<NSImage> image1_;
+  base::scoped_nsobject<NSImage> image2_;
   NSSize image1Size_;
   NSSize image2Size_;
   int animationFrame_;  // Current frame of the animation,
diff --git a/chrome/browser/ui/cocoa/tabs/throbber_view_unittest.mm b/chrome/browser/ui/cocoa/tabs/throbber_view_unittest.mm
index de7f295..22e72cc 100644
--- a/chrome/browser/ui/cocoa/tabs/throbber_view_unittest.mm
+++ b/chrome/browser/ui/cocoa/tabs/throbber_view_unittest.mm
@@ -4,7 +4,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #import "chrome/browser/ui/cocoa/tabs/throbber_view.h"
 #include "grit/ui_resources.h"
diff --git a/chrome/browser/ui/cocoa/tabs/throbbing_image_view.h b/chrome/browser/ui/cocoa/tabs/throbbing_image_view.h
index 1cd8d60..4cf9486 100644
--- a/chrome/browser/ui/cocoa/tabs/throbbing_image_view.h
+++ b/chrome/browser/ui/cocoa/tabs/throbbing_image_view.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #include "ui/base/animation/throb_animation.h"
 
@@ -23,8 +23,8 @@
 
 @interface ThrobbingImageView : NSView {
  @protected
-  scoped_nsobject<NSImage> backgroundImage_;
-  scoped_nsobject<NSImage> throbImage_;
+  base::scoped_nsobject<NSImage> backgroundImage_;
+  base::scoped_nsobject<NSImage> throbImage_;
   scoped_ptr<ui::ThrobAnimation> throbAnimation_;
 
  @private
diff --git a/chrome/browser/ui/cocoa/tabs/throbbing_image_view_unittest.mm b/chrome/browser/ui/cocoa/tabs/throbbing_image_view_unittest.mm
index 33f7f41..703d97b 100644
--- a/chrome/browser/ui/cocoa/tabs/throbbing_image_view_unittest.mm
+++ b/chrome/browser/ui/cocoa/tabs/throbbing_image_view_unittest.mm
@@ -14,19 +14,19 @@
 class ThrobbingImageViewTest : public CocoaTest {
  public:
   ThrobbingImageViewTest() {
-    scoped_nsobject<NSImage> image(
+    base::scoped_nsobject<NSImage> image(
         [[NSImage alloc] initWithSize:NSMakeSize(16, 16)]);
     [image lockFocus];
     NSRectFill(NSMakeRect(0, 0, 16, 16));
     [image unlockFocus];
 
-    scoped_nsobject<ThrobbingImageView> view([[ThrobbingImageView alloc]
-            initWithFrame:NSMakeRect(0, 0, 16, 16)
-          backgroundImage:image
-               throbImage:image
-               durationMS:20
-            throbPosition:kThrobPositionOverlay
-       animationContainer:NULL]);
+    base::scoped_nsobject<ThrobbingImageView> view(
+        [[ThrobbingImageView alloc] initWithFrame:NSMakeRect(0, 0, 16, 16)
+                                  backgroundImage:image
+                                       throbImage:image
+                                       durationMS:20
+                                    throbPosition:kThrobPositionOverlay
+                               animationContainer:NULL]);
     view_ = view.get();
     [[test_window() contentView] addSubview:view_];
   }
diff --git a/chrome/browser/ui/cocoa/task_manager_mac.h b/chrome/browser/ui/cocoa/task_manager_mac.h
index 7651e0d..093f9f4 100644
--- a/chrome/browser/ui/cocoa/task_manager_mac.h
+++ b/chrome/browser/ui/cocoa/task_manager_mac.h
@@ -8,7 +8,7 @@
 #import <Cocoa/Cocoa.h>
 #include <vector>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/task_manager/task_manager.h"
 #include "chrome/browser/ui/cocoa/table_row_nsimage_cache.h"
 
@@ -30,9 +30,8 @@
   TaskManagerMac* taskManagerObserver_;  // weak
   TaskManager* taskManager_;  // weak
   TaskManagerModel* model_;  // weak
-  bool highlightBackgroundResources_;
 
-  scoped_nsobject<WindowSizeAutosaver> size_saver_;
+  base::scoped_nsobject<WindowSizeAutosaver> size_saver_;
 
   // These contain a permutation of [0..|model_->ResourceCount() - 1|]. Used to
   // implement sorting.
@@ -40,15 +39,11 @@
   std::vector<int> modelToViewMap_;
 
   // Descriptor of the current sort column.
-  scoped_nsobject<NSSortDescriptor> currentSortDescriptor_;
-
-  // Color we use for background resources.
-  scoped_nsobject<NSColor> backgroundResourceColor_;
+  base::scoped_nsobject<NSSortDescriptor> currentSortDescriptor_;
 }
 
 // Creates and shows the task manager's window.
-- (id)initWithTaskManagerObserver:(TaskManagerMac*)taskManagerObserver
-     highlightBackgroundResources:(bool)highlightBackgroundResources;
+- (id)initWithTaskManagerObserver:(TaskManagerMac*)taskManagerObserver;
 
 // Refreshes all data in the task manager table.
 - (void)reloadData;
@@ -71,7 +66,7 @@
 class TaskManagerMac : public TaskManagerModelObserver,
                        public TableRowNSImageCache::Table {
  public:
-  TaskManagerMac(TaskManager* task_manager, bool highlight_background);
+  explicit TaskManagerMac(TaskManager* task_manager);
   virtual ~TaskManagerMac();
 
   // TaskManagerModelObserver
@@ -89,9 +84,8 @@
   virtual gfx::ImageSkia GetIcon(int r) const OVERRIDE;
 
   // Creates the task manager if it doesn't exist; otherwise, it activates the
-  // existing task manager window. Highlights background resources if
-  // |highlight_background_resources| is true.
-  static void Show(bool highlight_background_resources);
+  // existing task manager window.
+  static void Show();
 
   // Returns the TaskManager observed by |this|.
   TaskManager* task_manager() { return task_manager_; }
@@ -102,8 +96,6 @@
   // Returns the cocoa object. Used for testing.
   TaskManagerWindowController* cocoa_controller() { return window_controller_; }
 
-  // Returns true if the resource at this location is a background resource.
-  bool IsBackgroundRow(int row) const;
  private:
   // The task manager.
   TaskManager* const task_manager_;  // weak
@@ -118,9 +110,6 @@
   // Caches favicons for all rows. Needs to be initalized after |model_|.
   TableRowNSImageCache icon_cache_;
 
-  // If true, highlight background resources.
-  bool highlight_background_resources_;
-
   // An open task manager window. There can only be one open at a time. This
   // is reset to NULL when the window is closed.
   static TaskManagerMac* instance_;
diff --git a/chrome/browser/ui/cocoa/task_manager_mac.mm b/chrome/browser/ui/cocoa/task_manager_mac.mm
index bf8e04d..a75e706 100644
--- a/chrome/browser/ui/cocoa/task_manager_mac.mm
+++ b/chrome/browser/ui/cocoa/task_manager_mac.mm
@@ -113,8 +113,7 @@
 
 @implementation TaskManagerWindowController
 
-- (id)initWithTaskManagerObserver:(TaskManagerMac*)taskManagerObserver
-     highlightBackgroundResources:(bool)highlightBackgroundResources {
+- (id)initWithTaskManagerObserver:(TaskManagerMac*)taskManagerObserver {
   NSString* nibpath = [base::mac::FrameworkBundle()
                         pathForResource:@"TaskManager"
                                  ofType:@"nib"];
@@ -122,15 +121,6 @@
     taskManagerObserver_ = taskManagerObserver;
     taskManager_ = taskManagerObserver_->task_manager();
     model_ = taskManager_->model();
-    highlightBackgroundResources_ = highlightBackgroundResources;
-    if (highlightBackgroundResources_) {
-      // Highlight background resources with a yellow background.
-      backgroundResourceColor_.reset(
-          [[NSColor colorWithDeviceRed:0xff/255.0
-                                 green:0xfa/255.0
-                                  blue:0xcd/255.0
-                                 alpha:1.0] retain]);
-    }
 
     if (g_browser_process && g_browser_process->local_state()) {
       size_saver_.reset([[WindowSizeAutosaver alloc]
@@ -226,7 +216,7 @@
 // Adds a column which has the given string id as title. |isVisible| specifies
 // if the column is initially visible.
 - (NSTableColumn*)addColumnWithId:(int)columnId visible:(BOOL)isVisible {
-  scoped_nsobject<NSTableColumn> column([[NSTableColumn alloc]
+  base::scoped_nsobject<NSTableColumn> column([[NSTableColumn alloc]
       initWithIdentifier:[NSString stringWithFormat:@"%d", columnId]]);
 
   NSTextAlignment textAlignment =
@@ -248,9 +238,10 @@
   // The page column should by default be sorted ascending.
   BOOL ascending = columnId == IDS_TASK_MANAGER_TASK_COLUMN;
 
-  scoped_nsobject<NSSortDescriptor> sortDescriptor([[NSSortDescriptor alloc]
-      initWithKey:[NSString stringWithFormat:@"%d", columnId]
-        ascending:ascending]);
+  base::scoped_nsobject<NSSortDescriptor> sortDescriptor(
+      [[NSSortDescriptor alloc]
+          initWithKey:[NSString stringWithFormat:@"%d", columnId]
+            ascending:ascending]);
   [column.get() setSortDescriptorPrototype:sortDescriptor.get()];
 
   // Default values, only used in release builds if nobody notices the DCHECK
@@ -285,7 +276,7 @@
                                             visible:YES];
   // |nameColumn| displays an icon for every row -- this is done by an
   // NSButtonCell.
-  scoped_nsobject<NSButtonCell> nameCell(
+  base::scoped_nsobject<NSButtonCell> nameCell(
       [[NSButtonCell alloc] initTextCell:@""]);
   [nameCell.get() setImagePosition:NSImageLeft];
   [nameCell.get() setButtonType:NSSwitchButton];
@@ -320,7 +311,7 @@
 // which columns should be shown and which should be hidden (like e.g.
 // Task Manager.app's table header context menu).
 - (void)setUpTableHeaderContextMenu {
-  scoped_nsobject<NSMenu> contextMenu(
+  base::scoped_nsobject<NSMenu> contextMenu(
       [[NSMenu alloc] initWithTitle:@"Task Manager context menu"]);
   for (NSTableColumn* column in [tableView_ tableColumns]) {
     NSMenuItem* item = [contextMenu.get()
@@ -396,35 +387,6 @@
   [self autorelease];
 }
 
-// Delegate method invoked before each cell in the table is displayed. We
-// override this to provide highlighting of background resources.
-- (void)  tableView:(NSTableView*)tableView
-    willDisplayCell:(id)cell
-     forTableColumn:(NSTableColumn*)tableColumn
-                row:(NSInteger)row {
-  if (!highlightBackgroundResources_)
-    return;
-
-  DCHECK([cell respondsToSelector:@selector(setBackgroundColor:)]);
-  if ([cell respondsToSelector:@selector(setBackgroundColor:)]) {
-    NSColor* color = nil;
-    if (taskManagerObserver_->IsBackgroundRow(viewToModelMap_[row]) &&
-        ![tableView isRowSelected:row]) {
-      color = backgroundResourceColor_.get();
-      if ((row % 2) == 1 && [tableView usesAlternatingRowBackgroundColors]) {
-        color = [color blendedColorWithFraction:0.05
-                                        ofColor:[NSColor blackColor]];
-      }
-    }
-    [cell setBackgroundColor:color];
-
-    // The icon at the left is an |NSButtonCell|, which does not
-    // implement this method on 10.5.
-    if ([cell respondsToSelector:@selector(setDrawsBackground:)])
-      [cell setDrawsBackground:(color != nil)];
-  }
-}
-
 @end
 
 @implementation TaskManagerWindowController (NSTableDataSource)
@@ -489,16 +451,12 @@
 ////////////////////////////////////////////////////////////////////////////////
 // TaskManagerMac implementation:
 
-TaskManagerMac::TaskManagerMac(TaskManager* task_manager,
-                               bool highlight_background_resources)
+TaskManagerMac::TaskManagerMac(TaskManager* task_manager)
   : task_manager_(task_manager),
     model_(task_manager->model()),
-    icon_cache_(this),
-    highlight_background_resources_(highlight_background_resources) {
+    icon_cache_(this) {
   window_controller_ =
-      [[TaskManagerWindowController alloc]
-           initWithTaskManagerObserver:this
-          highlightBackgroundResources:highlight_background_resources];
+      [[TaskManagerWindowController alloc] initWithTaskManagerObserver:this];
   model_->AddObserver(this);
 }
 
@@ -560,37 +518,23 @@
   return model_->GetResourceIcon(r);
 }
 
-bool TaskManagerMac::IsBackgroundRow(int row) const {
-  return model_->IsBackgroundResource(row);
-}
-
 // static
-void TaskManagerMac::Show(bool highlight_background_resources) {
+void TaskManagerMac::Show() {
   if (instance_) {
-    if (instance_->highlight_background_resources_ ==
-        highlight_background_resources) {
-      // There's a Task manager window open already, so just activate it.
-      [[instance_->window_controller_ window]
-        makeKeyAndOrderFront:instance_->window_controller_];
-      return;
-    } else {
-      // The user is switching between "View Background Pages" and
-      // "Task Manager" so close the existing window and fall through to
-      // open a new one.
-      [[instance_->window_controller_ window] close];
-    }
+    [[instance_->window_controller_ window]
+      makeKeyAndOrderFront:instance_->window_controller_];
+    return;
   }
   // Create a new instance.
-  instance_ = new TaskManagerMac(TaskManager::GetInstance(),
-                                 highlight_background_resources);
+  instance_ = new TaskManagerMac(TaskManager::GetInstance());
   instance_->model_->StartUpdating();
 }
 
 namespace chrome {
 
 // Declared in browser_dialogs.h.
-void ShowTaskManager(Browser* browser, bool highlight_background_resources) {
-  TaskManagerMac::Show(highlight_background_resources);
+void ShowTaskManager(Browser* browser) {
+  TaskManagerMac::Show();
 }
 
 }  // namespace chrome
diff --git a/chrome/browser/ui/cocoa/task_manager_mac_unittest.mm b/chrome/browser/ui/cocoa/task_manager_mac_unittest.mm
index 6a548e4..9dff6b1 100644
--- a/chrome/browser/ui/cocoa/task_manager_mac_unittest.mm
+++ b/chrome/browser/ui/cocoa/task_manager_mac_unittest.mm
@@ -5,7 +5,6 @@
 #import <Cocoa/Cocoa.h>
 
 #include "base/compiler_specific.h"
-#include "base/memory/scoped_nsobject.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/task_manager/resource_provider.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
@@ -47,7 +46,7 @@
 // Test creation, to ensure nothing leaks or crashes.
 TEST_F(TaskManagerWindowControllerTest, Init) {
   TaskManager task_manager;
-  TaskManagerMac* bridge(new TaskManagerMac(&task_manager, false));
+  TaskManagerMac* bridge(new TaskManagerMac(&task_manager));
   TaskManagerWindowController* controller = bridge->cocoa_controller();
 
   // Releases the controller, which in turn deletes |bridge|.
@@ -65,7 +64,7 @@
   task_manager.AddResource(&resource2);
   task_manager.AddResource(&resource3);  // Will be in the same group as 2.
 
-  TaskManagerMac* bridge(new TaskManagerMac(&task_manager, false));
+  TaskManagerMac* bridge(new TaskManagerMac(&task_manager));
   TaskManagerWindowController* controller = bridge->cocoa_controller();
   NSTableView* table = [controller tableView];
   ASSERT_EQ(3, [controller numberOfRowsInTableView:table]);
@@ -98,7 +97,7 @@
   task_manager.AddResource(&resource1);
   task_manager.AddResource(&resource2);
 
-  TaskManagerMac* bridge(new TaskManagerMac(&task_manager, false));
+  TaskManagerMac* bridge(new TaskManagerMac(&task_manager));
   TaskManagerWindowController* controller = bridge->cocoa_controller();
   NSTableView* table = [controller tableView];
   ASSERT_EQ(2, [controller numberOfRowsInTableView:table]);
diff --git a/chrome/browser/ui/cocoa/toolbar/back_forward_menu_controller.h b/chrome/browser/ui/cocoa/toolbar/back_forward_menu_controller.h
index 282ff77..e186341 100644
--- a/chrome/browser/ui/cocoa/toolbar/back_forward_menu_controller.h
+++ b/chrome/browser/ui/cocoa/toolbar/back_forward_menu_controller.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #include "chrome/browser/ui/toolbar/back_forward_menu_model.h"
 
@@ -27,7 +27,7 @@
   BackForwardMenuType type_;
   MenuButton* button_;  // Weak; comes from nib.
   scoped_ptr<BackForwardMenuModel> model_;
-  scoped_nsobject<NSMenu> backForwardMenu_;
+  base::scoped_nsobject<NSMenu> backForwardMenu_;
 }
 
 // Type (back or forwards); can only be set on initialization.
diff --git a/chrome/browser/ui/cocoa/toolbar/reload_button_unittest.mm b/chrome/browser/ui/cocoa/toolbar/reload_button_unittest.mm
index c7eccd9..b8079c9 100644
--- a/chrome/browser/ui/cocoa/toolbar/reload_button_unittest.mm
+++ b/chrome/browser/ui/cocoa/toolbar/reload_button_unittest.mm
@@ -6,7 +6,7 @@
 
 #import "chrome/browser/ui/cocoa/toolbar/reload_button.h"
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/app/chrome_command_ids.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #import "chrome/browser/ui/cocoa/image_button_cell.h"
@@ -29,7 +29,7 @@
  public:
   ReloadButtonTest() {
     NSRect frame = NSMakeRect(0, 0, 20, 20);
-    scoped_nsobject<ReloadButton> button(
+    base::scoped_nsobject<ReloadButton> button(
         [[ReloadButton alloc] initWithFrame:frame]);
     button_ = button.get();
 
diff --git a/chrome/browser/ui/cocoa/toolbar/toolbar_button_unittest.mm b/chrome/browser/ui/cocoa/toolbar/toolbar_button_unittest.mm
index 3ebbefc..48a7dd3 100644
--- a/chrome/browser/ui/cocoa/toolbar/toolbar_button_unittest.mm
+++ b/chrome/browser/ui/cocoa/toolbar/toolbar_button_unittest.mm
@@ -4,7 +4,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #include "chrome/app/chrome_command_ids.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #import "chrome/browser/ui/cocoa/toolbar/toolbar_button.h"
@@ -54,7 +54,7 @@
  public:
   ToolbarButtonTest() {
     NSRect frame = NSMakeRect(0, 0, 20, 20);
-    scoped_nsobject<TestableToolbarButton> button(
+    base::scoped_nsobject<TestableToolbarButton> button(
         [[TestableToolbarButton alloc] initWithFrame:frame]);
     button_ = button.get();
 
diff --git a/chrome/browser/ui/cocoa/toolbar/toolbar_controller.h b/chrome/browser/ui/cocoa/toolbar/toolbar_controller.h
index 6fdbd58..07a0bf5 100644
--- a/chrome/browser/ui/cocoa/toolbar/toolbar_controller.h
+++ b/chrome/browser/ui/cocoa/toolbar/toolbar_controller.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/prefs/pref_member.h"
 #import "chrome/browser/ui/cocoa/command_observer_bridge.h"
@@ -64,14 +64,15 @@
   Browser* browser_;  // weak, one per window
   scoped_ptr<CommandObserverBridge> commandObserver_;
   scoped_ptr<LocationBarViewMac> locationBarView_;
-  scoped_nsobject<AutocompleteTextFieldEditor> autocompleteTextFieldEditor_;
+  base::scoped_nsobject<AutocompleteTextFieldEditor>
+      autocompleteTextFieldEditor_;
   id<ViewResizer> resizeDelegate_;  // weak
-  scoped_nsobject<BackForwardMenuController> backMenuController_;
-  scoped_nsobject<BackForwardMenuController> forwardMenuController_;
-  scoped_nsobject<BrowserActionsController> browserActionsController_;
+  base::scoped_nsobject<BackForwardMenuController> backMenuController_;
+  base::scoped_nsobject<BackForwardMenuController> forwardMenuController_;
+  base::scoped_nsobject<BrowserActionsController> browserActionsController_;
 
   // Lazily-instantiated menu controller.
-  scoped_nsobject<WrenchMenuController> wrenchMenuController_;
+  base::scoped_nsobject<WrenchMenuController> wrenchMenuController_;
 
   // Used for monitoring the optional toolbar button prefs.
   scoped_ptr<ToolbarControllerInternal::NotificationBridge> notificationBridge_;
@@ -82,7 +83,7 @@
 
   // We have an extra retain in the locationBar_.
   // See comments in awakeFromNib for more info.
-  scoped_nsobject<AutocompleteTextField> locationBarRetainer_;
+  base::scoped_nsobject<AutocompleteTextField> locationBarRetainer_;
 
   // Tracking area for mouse enter/exit/moved in the toolbar.
   ui::ScopedCrTrackingArea trackingArea_;
diff --git a/chrome/browser/ui/cocoa/toolbar/toolbar_controller.mm b/chrome/browser/ui/cocoa/toolbar/toolbar_controller.mm
index f037f1e..15cc8fb 100644
--- a/chrome/browser/ui/cocoa/toolbar/toolbar_controller.mm
+++ b/chrome/browser/ui/cocoa/toolbar/toolbar_controller.mm
@@ -72,11 +72,7 @@
 namespace {
 
 // Height of the toolbar in pixels when the bookmark bar is closed.
-const CGFloat kBaseToolbarHeightNormal = 34.0;
-
-// Height of the toolbar in pixels when the bookmark bar is if instant extended
-// is enabled.
-const CGFloat kBaseToolbarHeightInstantExtended = 35.0;
+const CGFloat kBaseToolbarHeightNormal = 35.0;
 
 // The minimum width of the location bar in pixels.
 const CGFloat kMinimumLocationBarWidth = 100.0;
@@ -221,16 +217,6 @@
 // Now we can hook up bridges that rely on UI objects such as the location
 // bar and button state.
 - (void)awakeFromNib {
-  // Make the location bar taller in instant extended mode. TODO(sail): Move
-  // this to the xib file once this switch is removed.
-  if (chrome::IsInstantExtendedAPIEnabled()) {
-    NSRect toolbarFrame = [[self view] frame];
-    toolbarFrame.size.height += 1;
-    [[self view] setFrame:toolbarFrame];
-    NSRect frame = NSInsetRect([locationBar_ frame], 0, -1);
-    [locationBar_ setFrame:frame];
-  }
-
   [[backButton_ cell] setImageID:IDR_BACK
                   forButtonState:image_button_cell::kDefaultState];
   [[backButton_ cell] setImageID:IDR_BACK_H
@@ -752,9 +738,6 @@
   if (!hasToolbar_)
     return NSHeight([locationBar_ frame]);
 
-  if (chrome::IsInstantExtendedAPIEnabled())
-    return kBaseToolbarHeightInstantExtended - compressByHeight;
-
   return kBaseToolbarHeightNormal - compressByHeight;
 }
 
@@ -768,6 +751,8 @@
     ToolbarView* toolbarView = (ToolbarView*)view;
     [toolbarView setDividerOpacity:opacity];
   }
+
+  [view setNeedsDisplay:YES];
 }
 
 - (BrowserActionsController*)browserActionsController {
diff --git a/chrome/browser/ui/cocoa/toolbar/toolbar_controller_unittest.mm b/chrome/browser/ui/cocoa/toolbar/toolbar_controller_unittest.mm
index 7491229..8fb005e 100644
--- a/chrome/browser/ui/cocoa/toolbar/toolbar_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/toolbar/toolbar_controller_unittest.mm
@@ -4,7 +4,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #include "base/prefs/pref_service.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/command_updater.h"
@@ -89,8 +89,8 @@
               [[views objectAtIndex:kHomeIndex] isEnabled] ? true : false);
   }
 
-  scoped_nsobject<ViewResizerPong> resizeDelegate_;
-  scoped_nsobject<ToolbarController> bar_;
+  base::scoped_nsobject<ViewResizerPong> resizeDelegate_;
+  base::scoped_nsobject<ToolbarController> bar_;
 };
 
 TEST_VIEW(ToolbarControllerTest, [bar_ view])
@@ -215,8 +215,8 @@
 }
 
 TEST_F(ToolbarControllerTest, HoverButtonForEvent) {
-  scoped_nsobject<HitView> view([[HitView alloc]
-                                  initWithFrame:NSMakeRect(0,0,100,100)]);
+  base::scoped_nsobject<HitView> view(
+      [[HitView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)]);
   [bar_ setView:view];
   NSEvent* event = [NSEvent mouseEventWithType:NSMouseMoved
                                       location:NSMakePoint(10,10)
@@ -233,12 +233,13 @@
   EXPECT_FALSE([bar_ hoverButtonForEvent:event]);
 
   // Not yet...
-  scoped_nsobject<NSButton> button([[NSButton alloc] init]);
+  base::scoped_nsobject<NSButton> button([[NSButton alloc] init]);
   [view setHitTestReturn:button];
   EXPECT_FALSE([bar_ hoverButtonForEvent:event]);
 
   // Now!
-  scoped_nsobject<GradientButtonCell> cell([[GradientButtonCell alloc] init]);
+  base::scoped_nsobject<GradientButtonCell> cell(
+      [[GradientButtonCell alloc] init]);
   [button setCell:cell.get()];
   EXPECT_TRUE([bar_ hoverButtonForEvent:nil]);
 }
diff --git a/chrome/browser/ui/cocoa/toolbar/toolbar_view_unittest.mm b/chrome/browser/ui/cocoa/toolbar/toolbar_view_unittest.mm
index f6bb035..4bdeb56 100644
--- a/chrome/browser/ui/cocoa/toolbar/toolbar_view_unittest.mm
+++ b/chrome/browser/ui/cocoa/toolbar/toolbar_view_unittest.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #import "chrome/browser/ui/cocoa/toolbar/toolbar_view.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -16,7 +16,7 @@
 // This class only needs to do one thing: prevent mouse down events from moving
 // the parent window around.
 TEST_F(ToolbarViewTest, CanDragWindow) {
-  scoped_nsobject<ToolbarView> view([[ToolbarView alloc] init]);
+  base::scoped_nsobject<ToolbarView> view([[ToolbarView alloc] init]);
   EXPECT_FALSE([view mouseDownCanMoveWindow]);
 }
 
diff --git a/chrome/browser/ui/cocoa/toolbar/wrench_toolbar_button_cell_unittest.mm b/chrome/browser/ui/cocoa/toolbar/wrench_toolbar_button_cell_unittest.mm
index 79ee865..416a500 100644
--- a/chrome/browser/ui/cocoa/toolbar/wrench_toolbar_button_cell_unittest.mm
+++ b/chrome/browser/ui/cocoa/toolbar/wrench_toolbar_button_cell_unittest.mm
@@ -21,14 +21,14 @@
 class WrenchToolbarButtonCellTest : public CocoaTest {
  protected:
   WrenchToolbarButtonCellTest() {
-    scoped_nsobject<NSButton> button([[TestWrenchToolbarButton alloc]
+    base::scoped_nsobject<NSButton> button([[TestWrenchToolbarButton alloc]
         initWithFrame:NSMakeRect(0, 0, 29, 29)]);
     button_ = button;
     [[test_window() contentView] addSubview:button_];
   }
 
   NSButton* button_;
-  scoped_nsobject<WrenchToolbarButtonCell> cell_;
+  base::scoped_nsobject<WrenchToolbarButtonCell> cell_;
   base::MessageLoopForUI message_loop_;  // Needed for ui::Animation.
 
  private:
diff --git a/chrome/browser/ui/cocoa/validation_message_bubble_cocoa.mm b/chrome/browser/ui/cocoa/validation_message_bubble_cocoa.mm
index 54cffda..362fd18 100644
--- a/chrome/browser/ui/cocoa/validation_message_bubble_cocoa.mm
+++ b/chrome/browser/ui/cocoa/validation_message_bubble_cocoa.mm
@@ -32,12 +32,12 @@
   mainText:(const string16&)mainText
    subText:(const string16&)subText {
 
-  scoped_nsobject<InfoBubbleWindow> window([[InfoBubbleWindow alloc]
-      initWithContentRect:
-          NSMakeRect(0, 0, kWindowInitialWidth, kWindowInitialHeight)
-                styleMask:NSBorderlessWindowMask
-                  backing:NSBackingStoreBuffered
-                    defer:NO]);
+  base::scoped_nsobject<InfoBubbleWindow> window(
+      [[InfoBubbleWindow alloc] initWithContentRect:
+              NSMakeRect(0, 0, kWindowInitialWidth, kWindowInitialHeight)
+                                          styleMask:NSBorderlessWindowMask
+                                            backing:NSBackingStoreBuffered
+                                              defer:NO]);
   if ((self = [super initWithWindow:window.get()
                        parentWindow:parentWindow
                          anchoredAt:anchorPoint])) {
@@ -66,7 +66,7 @@
 
   NSImage* image = ResourceBundle::GetSharedInstance()
       .GetNativeImageNamed(IDR_INPUT_ALERT).ToNSImage();
-  scoped_nsobject<NSImageView> imageView([[NSImageView alloc]
+  base::scoped_nsobject<NSImageView> imageView([[NSImageView alloc]
       initWithFrame:NSMakeRect(0, 0, image.size.width, image.size.height)]);
   [imageView setImageFrameStyle:NSImageFrameNone];
   [imageView setImage:image];
@@ -75,7 +75,7 @@
 
   const CGFloat textX = NSWidth([imageView frame]) + kIconTextMargin;
   NSRect textFrame = NSMakeRect(textX, 0, NSWidth(contentFrame) - textX, 0);
-  scoped_nsobject<NSTextField> text(
+  base::scoped_nsobject<NSTextField> text(
       [[NSTextField alloc] initWithFrame:textFrame]);
   [text setStringValue:base::SysUTF16ToNSString(mainText)];
   [text setFont:[NSFont systemFontOfSize:[NSFont systemFontSize]]];
@@ -104,7 +104,7 @@
     NSRect subTextFrame = NSMakeRect(
         textX, NSMaxY(textFrame) + kTextVerticalMargin,
         NSWidth(textFrame), 0);
-    scoped_nsobject<NSTextField> text2(
+    base::scoped_nsobject<NSTextField> text2(
         [[NSTextField alloc] initWithFrame:subTextFrame]);
     [text2 setStringValue:base::SysUTF16ToNSString(subText)];
     [text2 setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
@@ -174,7 +174,7 @@
   }
 
  private:
-  scoped_nsobject<ValidationMessageBubbleController> controller_;
+  base::scoped_nsobject<ValidationMessageBubbleController> controller_;
 };
 
 }
diff --git a/chrome/browser/ui/cocoa/validation_message_bubble_controller_unittest.mm b/chrome/browser/ui/cocoa/validation_message_bubble_controller_unittest.mm
index 207188b..c80c24d 100644
--- a/chrome/browser/ui/cocoa/validation_message_bubble_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/validation_message_bubble_controller_unittest.mm
@@ -4,7 +4,6 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
 #include "base/strings/utf_string_conversions.h"
 #import "chrome/browser/ui/cocoa/validation_message_bubble_controller.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ui/cocoa/vertical_gradient_view.h b/chrome/browser/ui/cocoa/vertical_gradient_view.h
index b42928d..c123017 100644
--- a/chrome/browser/ui/cocoa/vertical_gradient_view.h
+++ b/chrome/browser/ui/cocoa/vertical_gradient_view.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_UI_COCOA_VERTICAL_GRADIENT_VIEW_H_
 #define CHROME_BROWSER_UI_COCOA_VERTICAL_GRADIENT_VIEW_H_
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 
 #import <Cocoa/Cocoa.h>
 
@@ -17,9 +17,9 @@
 @interface VerticalGradientView : NSView {
  @private
   // The gradient to draw.
-  scoped_nsobject<NSGradient> gradient_;
+  base::scoped_nsobject<NSGradient> gradient_;
   // Color for bottom stroke.
-  scoped_nsobject<NSColor> strokeColor_;
+  base::scoped_nsobject<NSColor> strokeColor_;
 }
 
 // Gets and sets the gradient to paint as background.
diff --git a/chrome/browser/ui/cocoa/vertical_gradient_view_unittest.mm b/chrome/browser/ui/cocoa/vertical_gradient_view_unittest.mm
index ac046b0..fa550b3 100644
--- a/chrome/browser/ui/cocoa/vertical_gradient_view_unittest.mm
+++ b/chrome/browser/ui/cocoa/vertical_gradient_view_unittest.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #import "chrome/browser/ui/cocoa/vertical_gradient_view.h"
 
@@ -12,7 +12,7 @@
  public:
   VerticalGradientViewTest() {
     NSRect frame = NSMakeRect(0, 0, 50, 27);
-    scoped_nsobject<VerticalGradientView> view(
+    base::scoped_nsobject<VerticalGradientView> view(
         [[VerticalGradientView alloc] initWithFrame:frame]);
     view_ = view.get();
     [[test_window() contentView] addSubview:view_];
diff --git a/chrome/browser/ui/cocoa/web_dialog_window_controller.mm b/chrome/browser/ui/cocoa/web_dialog_window_controller.mm
index 9797deb..4460de9 100644
--- a/chrome/browser/ui/cocoa/web_dialog_window_controller.mm
+++ b/chrome/browser/ui/cocoa/web_dialog_window_controller.mm
@@ -5,7 +5,7 @@
 #import "chrome/browser/ui/cocoa/web_dialog_window_controller.h"
 
 #include "base/logging.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/strings/sys_string_conversions.h"
 #import "chrome/browser/ui/browser_dialogs.h"
 #import "chrome/browser/ui/cocoa/browser_command_executor.h"
@@ -317,12 +317,12 @@
   NSRect dialogRect = NSMakeRect(0, 0, dialogSize.width(), dialogSize.height());
   NSUInteger style = NSTitledWindowMask | NSClosableWindowMask |
       NSResizableWindowMask;
-  scoped_nsobject<ChromeEventProcessingWindow> window(
+  base::scoped_nsobject<ChromeEventProcessingWindow> window(
       [[ChromeEventProcessingWindow alloc]
-           initWithContentRect:dialogRect
-                     styleMask:style
-                       backing:NSBackingStoreBuffered
-                         defer:YES]);
+          initWithContentRect:dialogRect
+                    styleMask:style
+                      backing:NSBackingStoreBuffered
+                        defer:YES]);
   if (!window.get()) {
     return nil;
   }
diff --git a/chrome/browser/ui/cocoa/website_settings_bubble_controller.h b/chrome/browser/ui/cocoa/website_settings_bubble_controller.h
index 060496d..5f671e7 100644
--- a/chrome/browser/ui/cocoa/website_settings_bubble_controller.h
+++ b/chrome/browser/ui/cocoa/website_settings_bubble_controller.h
@@ -4,7 +4,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #import "chrome/browser/ui/cocoa/base_bubble_controller.h"
 #include "chrome/browser/ui/website_settings/website_settings_ui.h"
@@ -21,9 +21,9 @@
  @private
   content::WebContents* webContents_;
 
-  scoped_nsobject<NSView> contentView_;
-  scoped_nsobject<NSSegmentedControl> segmentedControl_;
-  scoped_nsobject<NSTabView> tabView_;
+  base::scoped_nsobject<NSView> contentView_;
+  base::scoped_nsobject<NSSegmentedControl> segmentedControl_;
+  base::scoped_nsobject<NSTabView> tabView_;
 
   // Displays the web site identity.
   NSTextField* identityField_;
diff --git a/chrome/browser/ui/cocoa/website_settings_bubble_controller.mm b/chrome/browser/ui/cocoa/website_settings_bubble_controller.mm
index 74e602c..b66584f 100644
--- a/chrome/browser/ui/cocoa/website_settings_bubble_controller.mm
+++ b/chrome/browser/ui/cocoa/website_settings_bubble_controller.mm
@@ -120,13 +120,13 @@
 
 @interface WebsiteSettingsTabSegmentedCell : NSSegmentedCell {
  @private
-  scoped_nsobject<NSImage> tabstripCenterImage_;
-  scoped_nsobject<NSImage> tabstripLeftImage_;
-  scoped_nsobject<NSImage> tabstripRightImage_;
+  base::scoped_nsobject<NSImage> tabstripCenterImage_;
+  base::scoped_nsobject<NSImage> tabstripLeftImage_;
+  base::scoped_nsobject<NSImage> tabstripRightImage_;
 
-  scoped_nsobject<NSImage> tabCenterImage_;
-  scoped_nsobject<NSImage> tabLeftImage_;
-  scoped_nsobject<NSImage> tabRightImage_;
+  base::scoped_nsobject<NSImage> tabCenterImage_;
+  base::scoped_nsobject<NSImage> tabLeftImage_;
+  base::scoped_nsobject<NSImage> tabRightImage_;
 
   // Key track of the index of segment which has keyboard focus. This is not
   // the same as the currently selected segment.
@@ -303,7 +303,7 @@
   // Use an arbitrary height; it will be changed in performLayout.
   NSRect contentRect = NSMakeRect(0, 0, [self defaultWindowWidth], 1);
   // Create an empty window into which content is placed.
-  scoped_nsobject<InfoBubbleWindow> window(
+  base::scoped_nsobject<InfoBubbleWindow> window(
       [[InfoBubbleWindow alloc] initWithContentRect:contentRect
                                           styleMask:NSBorderlessWindowMask
                                             backing:NSBackingStoreBuffered
@@ -403,7 +403,7 @@
 
   // Create the tab view and its two tabs.
 
-  scoped_nsobject<WebsiteSettingsTabSegmentedCell> cell(
+  base::scoped_nsobject<WebsiteSettingsTabSegmentedCell> cell(
       [[WebsiteSettingsTabSegmentedCell alloc] init]);
   CGFloat tabstripHeight = [cell cellSize].height;
   NSRect tabstripFrame = NSMakeRect(
@@ -470,11 +470,11 @@
 // Create the contents of the Permissions tab and add it to the given tab view.
 // Returns a weak reference to the tab view item's view.
 - (NSView*)addPermissionsTabToTabView:(NSTabView*)tabView {
-  scoped_nsobject<NSTabViewItem> item([[NSTabViewItem alloc] init]);
+  base::scoped_nsobject<NSTabViewItem> item([[NSTabViewItem alloc] init]);
   [tabView_ insertTabViewItem:item.get()
                       atIndex:WebsiteSettingsUI::TAB_ID_PERMISSIONS];
-  scoped_nsobject<NSView> contentView([[FlippedView alloc]
-      initWithFrame:[tabView_ contentRect]]);
+  base::scoped_nsobject<NSView> contentView(
+      [[FlippedView alloc] initWithFrame:[tabView_ contentRect]]);
   [contentView setAutoresizingMask:NSViewWidthSizable];
   [item setView:contentView.get()];
 
@@ -531,9 +531,9 @@
 // Create the contents of the Connection tab and add it to the given tab view.
 // Returns a weak reference to the tab view item's view.
 - (NSView*)addConnectionTabToTabView:(NSTabView*)tabView {
-  scoped_nsobject<NSTabViewItem> item([[NSTabViewItem alloc] init]);
-  scoped_nsobject<NSView> contentView([[FlippedView alloc]
-      initWithFrame:[tabView_ contentRect]]);
+  base::scoped_nsobject<NSTabViewItem> item([[NSTabViewItem alloc] init]);
+  base::scoped_nsobject<NSView> contentView(
+      [[FlippedView alloc] initWithFrame:[tabView_ contentRect]]);
   [contentView setAutoresizingMask:NSViewWidthSizable];
 
   // Place all the text and images at the same position. The positions will be
@@ -782,8 +782,8 @@
   // The height is arbitrary as it will be adjusted later.
   CGFloat width = NSWidth([view frame]) - point.x - kFramePadding;
   NSRect frame = NSMakeRect(point.x, point.y, width, 100);
-  scoped_nsobject<NSTextField> textField(
-     [[NSTextField alloc] initWithFrame:frame]);
+  base::scoped_nsobject<NSTextField> textField(
+      [[NSTextField alloc] initWithFrame:frame]);
   [self configureTextFieldAsLabel:textField.get()];
   [textField setStringValue:base::SysUTF16ToNSString(text)];
   NSFont* font = bold ? [NSFont boldSystemFontOfSize:fontSize]
@@ -801,7 +801,7 @@
                           toView:(NSView*)view
                          atPoint:(NSPoint)point {
   NSRect frame = NSMakeRect(point.x, point.y, size.width, size.height);
-  scoped_nsobject<NSImageView> imageView(
+  base::scoped_nsobject<NSImageView> imageView(
       [[NSImageView alloc] initWithFrame:frame]);
   [imageView setImageFrameStyle:NSImageFrameNone];
   [view addSubview:imageView.get()];
@@ -824,8 +824,9 @@
 - (NSButton*)addLinkButtonWithText:(NSString*)text toView:(NSView*)view {
   // Frame size is arbitrary; it will be adjusted by the layout tweaker.
   NSRect frame = NSMakeRect(kFramePadding, 0, 100, 10);
-  scoped_nsobject<NSButton> button([[NSButton alloc] initWithFrame:frame]);
-  scoped_nsobject<HyperlinkButtonCell> cell(
+  base::scoped_nsobject<NSButton> button(
+      [[NSButton alloc] initWithFrame:frame]);
+  base::scoped_nsobject<HyperlinkButtonCell> cell(
       [[HyperlinkButtonCell alloc] initTextCell:text]);
   [cell setControlSize:NSSmallControlSize];
   [button setCell:cell.get()];
@@ -860,7 +861,7 @@
                                       atPoint:(NSPoint)point {
   // Use an arbitrary width and height; it will be sized to fit.
   NSRect frame = NSMakeRect(point.x, point.y, 1, 1);
-  scoped_nsobject<NSPopUpButton> button(
+  base::scoped_nsobject<NSPopUpButton> button(
       [[NSPopUpButton alloc] initWithFrame:frame pullsDown:NO]);
   [button setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
   [button setBordered:NO];
@@ -896,7 +897,7 @@
   [button selectItemWithTag:permissionInfo.setting];
 
   // Set the button title.
-  scoped_nsobject<NSMenuItem> titleItem([[NSMenuItem alloc] init]);
+  base::scoped_nsobject<NSMenuItem> titleItem([[NSMenuItem alloc] init]);
   string16 buttonTitle = WebsiteSettingsUI::PermissionActionToUIString(
       permissionInfo.setting,
       permissionInfo.default_setting,
diff --git a/chrome/browser/ui/cocoa/window_size_autosaver.h b/chrome/browser/ui/cocoa/window_size_autosaver.h
index 8d136e3..e167125 100644
--- a/chrome/browser/ui/cocoa/window_size_autosaver.h
+++ b/chrome/browser/ui/cocoa/window_size_autosaver.h
@@ -10,7 +10,8 @@
 
 // WindowSizeAutosaver is a helper class that makes it easy to let windows
 // autoremember their position or position and size in a PrefService object.
-// To use this, add a |scoped_nsobject<WindowSizeAutosaver>| to your window
+// To use this, add a |base::scoped_nsobject<WindowSizeAutosaver>| to your
+// window
 // controller and initialize it in the window controller's init method, passing
 // a window and an autosave name. The autosaver will register for "window moved"
 // and "window resized" notifications and write the current window state to the
diff --git a/chrome/browser/ui/cocoa/window_size_autosaver_unittest.mm b/chrome/browser/ui/cocoa/window_size_autosaver_unittest.mm
index 93e28f9..b8d553c 100644
--- a/chrome/browser/ui/cocoa/window_size_autosaver_unittest.mm
+++ b/chrome/browser/ui/cocoa/window_size_autosaver_unittest.mm
@@ -6,7 +6,7 @@
 
 #import "chrome/browser/ui/cocoa/window_size_autosaver.h"
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/prefs/pref_service.h"
 #include "chrome/browser/prefs/scoped_user_pref_update.h"
 #include "chrome/browser/ui/cocoa/cocoa_profile_test.h"
@@ -69,10 +69,10 @@
   {
     NSRect frame = [window_ frame];
     // Empty state, shouldn't restore:
-    scoped_nsobject<WindowSizeAutosaver> sizeSaver([[WindowSizeAutosaver alloc]
-        initWithWindow:window_
-           prefService:pref
-                  path:path_]);
+    base::scoped_nsobject<WindowSizeAutosaver> sizeSaver(
+        [[WindowSizeAutosaver alloc] initWithWindow:window_
+                                        prefService:pref
+                                               path:path_]);
     EXPECT_EQ(NSMinX(frame), NSMinX([window_ frame]));
     EXPECT_EQ(NSMinY(frame), NSMinY([window_ frame]));
     EXPECT_EQ(NSWidth(frame), NSWidth([window_ frame]));
@@ -87,10 +87,10 @@
 
   {
     // Should restore last stored position, but not size.
-    scoped_nsobject<WindowSizeAutosaver> sizeSaver([[WindowSizeAutosaver alloc]
-        initWithWindow:window_
-           prefService:pref
-                  path:path_]);
+    base::scoped_nsobject<WindowSizeAutosaver> sizeSaver(
+        [[WindowSizeAutosaver alloc] initWithWindow:window_
+                                        prefService:pref
+                                               path:path_]);
     EXPECT_EQ(300, NSMinX([window_ frame]));
     EXPECT_EQ(310, NSMinY([window_ frame]));
     EXPECT_EQ(160, NSWidth([window_ frame]));
@@ -128,10 +128,10 @@
   {
     NSRect frame = [window_ frame];
     // Empty state, shouldn't restore:
-    scoped_nsobject<WindowSizeAutosaver> sizeSaver([[WindowSizeAutosaver alloc]
-        initWithWindow:window_
-           prefService:pref
-                  path:path_]);
+    base::scoped_nsobject<WindowSizeAutosaver> sizeSaver(
+        [[WindowSizeAutosaver alloc] initWithWindow:window_
+                                        prefService:pref
+                                               path:path_]);
     EXPECT_EQ(NSMinX(frame), NSMinX([window_ frame]));
     EXPECT_EQ(NSMinY(frame), NSMinY([window_ frame]));
     EXPECT_EQ(NSWidth(frame), NSWidth([window_ frame]));
@@ -146,10 +146,10 @@
 
   {
     // Should restore last stored size
-    scoped_nsobject<WindowSizeAutosaver> sizeSaver([[WindowSizeAutosaver alloc]
-        initWithWindow:window_
-           prefService:pref
-                  path:path_]);
+    base::scoped_nsobject<WindowSizeAutosaver> sizeSaver(
+        [[WindowSizeAutosaver alloc] initWithWindow:window_
+                                        prefService:pref
+                                               path:path_]);
     EXPECT_EQ(300, NSMinX([window_ frame]));
     EXPECT_EQ(310, NSMinY([window_ frame]));
     EXPECT_EQ(250, NSWidth([window_ frame]));
@@ -187,10 +187,10 @@
   {
     // Window rect shouldn't change...
     NSRect frame = [window_ frame];
-    scoped_nsobject<WindowSizeAutosaver> sizeSaver([[WindowSizeAutosaver alloc]
-        initWithWindow:window_
-           prefService:pref
-                  path:path_]);
+    base::scoped_nsobject<WindowSizeAutosaver> sizeSaver(
+        [[WindowSizeAutosaver alloc] initWithWindow:window_
+                                        prefService:pref
+                                               path:path_]);
     EXPECT_EQ(NSMinX(frame), NSMinX([window_ frame]));
     EXPECT_EQ(NSMinY(frame), NSMinY([window_ frame]));
     EXPECT_EQ(NSWidth(frame), NSWidth([window_ frame]));
diff --git a/chrome/browser/ui/cocoa/wrench_menu/menu_tracked_root_view_unittest.mm b/chrome/browser/ui/cocoa/wrench_menu/menu_tracked_root_view_unittest.mm
index 76da79c..14266b6 100644
--- a/chrome/browser/ui/cocoa/wrench_menu/menu_tracked_root_view_unittest.mm
+++ b/chrome/browser/ui/cocoa/wrench_menu/menu_tracked_root_view_unittest.mm
@@ -4,13 +4,13 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #import "chrome/browser/ui/cocoa/wrench_menu/menu_tracked_root_view.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
-#include "third_party/ocmock/gtest_support.h"
 #import "third_party/ocmock/OCMock/OCMock.h"
+#include "third_party/ocmock/gtest_support.h"
 
 class MenuTrackedRootViewTest : public CocoaTest {
  public:
@@ -19,7 +19,7 @@
     view_.reset([[MenuTrackedRootView alloc] init]);
   }
 
-  scoped_nsobject<MenuTrackedRootView> view_;
+  base::scoped_nsobject<MenuTrackedRootView> view_;
 };
 
 TEST_F(MenuTrackedRootViewTest, MouseUp) {
diff --git a/chrome/browser/ui/cocoa/wrench_menu/recent_tabs_menu_model_delegate.h b/chrome/browser/ui/cocoa/wrench_menu/recent_tabs_menu_model_delegate.h
index b1f2f42..d9cdd60 100644
--- a/chrome/browser/ui/cocoa/wrench_menu/recent_tabs_menu_model_delegate.h
+++ b/chrome/browser/ui/cocoa/wrench_menu/recent_tabs_menu_model_delegate.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "ui/base/models/menu_model_delegate.h"
 
 namespace ui {
@@ -26,7 +26,7 @@
 
  private:
   ui::MenuModel* model_;  // weak
-  scoped_nsobject<NSMenu> menu_;
+  base::scoped_nsobject<NSMenu> menu_;
 
   DISALLOW_COPY_AND_ASSIGN(RecentTabsMenuModelDelegate);
 };
diff --git a/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_button_cell.mm b/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_button_cell.mm
index 2e14478..bd334c2 100644
--- a/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_button_cell.mm
+++ b/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_button_cell.mm
@@ -4,7 +4,7 @@
 
 #import "chrome/browser/ui/cocoa/wrench_menu/wrench_menu_button_cell.h"
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
 
 @implementation WrenchMenuButtonCell
@@ -26,7 +26,7 @@
   // The default state should be a subtle gray gradient.
   if (![self isHighlighted]) {
     NSColor* end = [NSColor colorWithDeviceWhite:0.922 alpha:1.0];
-    scoped_nsobject<NSGradient> gradient(
+    base::scoped_nsobject<NSGradient> gradient(
         [[NSGradient alloc] initWithStartingColor:[NSColor whiteColor]
                                       endingColor:end]);
     [gradient drawInRect:frame angle:90.0];
diff --git a/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_button_cell_unittest.mm b/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_button_cell_unittest.mm
index 52791e2..2336393 100644
--- a/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_button_cell_unittest.mm
+++ b/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_button_cell_unittest.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/app/chrome_command_ids.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #import "chrome/browser/ui/cocoa/wrench_menu/wrench_menu_button_cell.h"
@@ -32,7 +32,7 @@
     [button_ setButtonType:NSMomentaryPushInButton];
   }
 
-  scoped_nsobject<NSButton> button_;
+  base::scoped_nsobject<NSButton> button_;
 };
 
 TEST_F(WrenchMenuButtonCellTest, Draw) {
diff --git a/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_controller.h b/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_controller.h
index fd6a283..fdbc62f 100644
--- a/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_controller.h
+++ b/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_controller.h
@@ -46,7 +46,7 @@
 
   // A shim NSViewController that loads the buttons from the NIB because ObjC
   // doesn't have multiple inheritance as this class is a MenuController.
-  scoped_nsobject<WrenchMenuButtonViewController> buttonViewController_;
+  base::scoped_nsobject<WrenchMenuButtonViewController> buttonViewController_;
 
   // The browser for which this controller exists.
   Browser* browser_;  // weak
diff --git a/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_controller.mm b/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_controller.mm
index 79fe776..172056d 100644
--- a/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_controller.mm
+++ b/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_controller.mm
@@ -16,7 +16,9 @@
 #include "chrome/browser/ui/browser_window.h"
 #import "chrome/browser/ui/cocoa/accelerators_cocoa.h"
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge.h"
+#import "chrome/browser/ui/cocoa/bookmarks/bookmark_menu_cocoa_controller.h"
 #import "chrome/browser/ui/cocoa/encoding_menu_controller_delegate_mac.h"
+#import "chrome/browser/ui/cocoa/l10n_util.h"
 #import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h"
 #import "chrome/browser/ui/cocoa/wrench_menu/menu_tracked_root_view.h"
 #import "chrome/browser/ui/cocoa/wrench_menu/recent_tabs_menu_model_delegate.h"
@@ -38,7 +40,7 @@
 - (NSButton*)zoomDisplay;
 - (void)removeAllItems:(NSMenu*)menu;
 - (NSMenu*)recentTabsSubmenu;
-- (ui::MenuModel*)recentTabsMenuModel;
+- (RecentTabsSubMenuModel*)recentTabsMenuModel;
 - (int)maxWidthForMenuModel:(ui::MenuModel*)model
                  modelIndex:(int)modelIndex;
 @end
@@ -122,10 +124,8 @@
 
   // Handle the special-cased menu items.
   int command_id = model->GetCommandIdAt(index);
-  scoped_nsobject<NSMenuItem> customItem(
-      [[NSMenuItem alloc] initWithTitle:@""
-                                 action:nil
-                          keyEquivalent:@""]);
+  base::scoped_nsobject<NSMenuItem> customItem(
+      [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]);
   MenuTrackedRootView* view;
   switch (command_id) {
     case IDC_EDIT_MENU:
@@ -148,6 +148,43 @@
   [menu insertItem:customItem.get() atIndex:index];
 }
 
+- (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item {
+  const BOOL enabled = [super validateUserInterfaceItem:item];
+
+  NSMenuItem* menuItem = (id)item;
+  ui::MenuModel* model =
+      static_cast<ui::MenuModel*>(
+          [[menuItem representedObject] pointerValue]);
+
+  // The section headers in the recent tabs submenu should be bold and black if
+  // a font is specified for the items (bold is already applied in the
+  // |MenuController| as the font returned by |GetLabelFontAt| is bold).
+  if (model && model == [self recentTabsMenuModel]) {
+    if (model->GetLabelFontAt([item tag])) {
+      DCHECK([menuItem attributedTitle]);
+      base::scoped_nsobject<NSMutableAttributedString> title(
+          [[NSMutableAttributedString alloc]
+              initWithAttributedString:[menuItem attributedTitle]]);
+      [title addAttribute:NSForegroundColorAttributeName
+                    value:[NSColor blackColor]
+                    range:NSMakeRange(0, [title length])];
+      [menuItem setAttributedTitle:title.get()];
+    } else {
+      // Not a section header. Add a tooltip with the title and the URL.
+      std::string url;
+      string16 title;
+      if ([self recentTabsMenuModel]->GetURLAndTitleForItemAtIndex(
+              [item tag], &url, &title)) {
+        [menuItem setToolTip:
+            cocoa_l10n_util::TooltipForURLAndTitle(
+                base::SysUTF8ToNSString(url), base::SysUTF16ToNSString(title))];
+       }
+    }
+  }
+
+  return enabled;
+}
+
 - (NSMenu*)bookmarkSubMenu {
   NSString* title = l10n_util::GetNSStringWithFixup(IDS_BOOKMARKS_MENU);
   return [[[self menu] itemWithTitle:title] submenu];
@@ -319,20 +356,20 @@
 
 // The recent tabs menu model is recognized by the existence of either the
 // kRecentlyClosedHeaderCommandId or the kDisabledRecentlyClosedHeaderCommandId.
-- (ui::MenuModel*)recentTabsMenuModel {
+- (RecentTabsSubMenuModel*)recentTabsMenuModel {
   int index = 0;
-  // Start searching at the wrnech menu model level, |model| will be updated
+  // Start searching at the wrench menu model level, |model| will be updated
   // only if the command we're looking for is found in one of the [sub]menus.
   ui::MenuModel* model = [self wrenchMenuModel];
   if (ui::MenuModel::GetModelAndIndexForCommandId(
           RecentTabsSubMenuModel::kRecentlyClosedHeaderCommandId, &model,
           &index)) {
-    return model;
+    return static_cast<RecentTabsSubMenuModel*>(model);
   }
   if (ui::MenuModel::GetModelAndIndexForCommandId(
           RecentTabsSubMenuModel::kDisabledRecentlyClosedHeaderCommandId,
           &model, &index)) {
-    return model;
+    return static_cast<RecentTabsSubMenuModel*>(model);
   }
   return NULL;
 }
@@ -341,10 +378,9 @@
 // menu.
 - (int)maxWidthForMenuModel:(ui::MenuModel*)model
                  modelIndex:(int)modelIndex {
-  ui::MenuModel* recentTabsMenuModel = [self recentTabsMenuModel];
+  RecentTabsSubMenuModel* recentTabsMenuModel = [self recentTabsMenuModel];
   if (recentTabsMenuModel && recentTabsMenuModel == model) {
-    return static_cast<RecentTabsSubMenuModel*>(
-        recentTabsMenuModel)->GetMaxWidthForItemAtIndex(modelIndex);
+    return recentTabsMenuModel->GetMaxWidthForItemAtIndex(modelIndex);
   }
   return -1;
 }
diff --git a/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_controller_unittest.mm b/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_controller_unittest.mm
index 0d08c3c..d681db0 100644
--- a/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_controller_unittest.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
@@ -62,7 +62,7 @@
     return controller_.get();
   }
 
-  scoped_nsobject<WrenchMenuController> controller_;
+  base::scoped_nsobject<WrenchMenuController> controller_;
 
   scoped_ptr<MockWrenchMenuModel> fake_model_;
 };
@@ -73,7 +73,7 @@
 }
 
 TEST_F(WrenchMenuControllerTest, DispatchSimple) {
-  scoped_nsobject<NSButton> button([[NSButton alloc] init]);
+  base::scoped_nsobject<NSButton> button([[NSButton alloc] init]);
   [button setTag:IDC_ZOOM_PLUS];
 
   // Set fake model to test dispatching.
diff --git a/chrome/browser/ui/extensions/OWNERS b/chrome/browser/ui/extensions/OWNERS
index 6ff02c4..565b21c 100644
--- a/chrome/browser/ui/extensions/OWNERS
+++ b/chrome/browser/ui/extensions/OWNERS
@@ -1,3 +1,2 @@
 benwells@chromium.org
-jeremya@chromium.org
 miket@chromium.org
diff --git a/chrome/browser/ui/extensions/apps_metro_handler_win.cc b/chrome/browser/ui/extensions/apps_metro_handler_win.cc
index 125c8bf..0f253b2 100644
--- a/chrome/browser/ui/extensions/apps_metro_handler_win.cc
+++ b/chrome/browser/ui/extensions/apps_metro_handler_win.cc
@@ -4,8 +4,8 @@
 
 #include "chrome/browser/ui/extensions/apps_metro_handler_win.h"
 
+#include "apps/shell_window.h"
 #include "chrome/browser/extensions/shell_window_registry.h"
-#include "chrome/browser/ui/extensions/shell_window.h"
 #include "chrome/browser/ui/simple_message_box.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
@@ -15,7 +15,7 @@
 
 bool VerifySwitchToMetroForApps(gfx::NativeWindow parent_window) {
   if (!extensions::ShellWindowRegistry::IsShellWindowRegisteredInAnyProfile(
-          ShellWindow::WINDOW_TYPE_DEFAULT)) {
+          apps::ShellWindow::WINDOW_TYPE_DEFAULT)) {
     return true;
   }
 
diff --git a/chrome/browser/ui/extensions/native_app_window.h b/chrome/browser/ui/extensions/native_app_window.h
index 868b906..3e030f2 100644
--- a/chrome/browser/ui/extensions/native_app_window.h
+++ b/chrome/browser/ui/extensions/native_app_window.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_UI_EXTENSIONS_NATIVE_APP_WINDOW_H_
 #define CHROME_BROWSER_UI_EXTENSIONS_NATIVE_APP_WINDOW_H_
 
-#include "chrome/browser/ui/extensions/shell_window.h"
+#include "apps/shell_window.h"
 #include "components/web_modal/web_contents_modal_dialog_host.h"
 #include "ui/base/base_window.h"
 #include "ui/gfx/insets.h"
@@ -16,9 +16,10 @@
 class NativeAppWindow : public ui::BaseWindow,
                         public web_modal::WebContentsModalDialogHost {
  public:
-  // Used by ShellWindow to instantiate the platform-specific ShellWindow code.
-  static NativeAppWindow* Create(ShellWindow* window,
-                                 const ShellWindow::CreateParams& params);
+  // Used by apps::ShellWindow to instantiate the platform-specific
+  // apps::ShellWindow code.
+  static NativeAppWindow* Create(apps::ShellWindow* window,
+                                 const apps::ShellWindow::CreateParams& params);
 
   // Called when the draggable regions are changed.
   virtual void UpdateDraggableRegions(
diff --git a/chrome/browser/ui/extensions/shell_window.cc b/chrome/browser/ui/extensions/shell_window.cc
deleted file mode 100644
index 5d3f4af..0000000
--- a/chrome/browser/ui/extensions/shell_window.cc
+++ /dev/null
@@ -1,646 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/extensions/shell_window.h"
-
-#include "apps/shell_window_geometry_cache.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/values.h"
-#include "chrome/browser/extensions/app_window_contents.h"
-#include "chrome/browser/extensions/extension_process_manager.h"
-#include "chrome/browser/extensions/extension_system.h"
-#include "chrome/browser/extensions/image_loader.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
-#include "chrome/browser/extensions/suggest_permission_util.h"
-#include "chrome/browser/favicon/favicon_tab_helper.h"
-#include "chrome/browser/file_select_helper.h"
-#include "chrome/browser/lifetime/application_lifetime.h"
-#include "chrome/browser/media/media_capture_devices_dispatcher.h"
-#include "chrome/browser/platform_util.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/sessions/session_id.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_dialogs.h"
-#include "chrome/browser/ui/browser_finder.h"
-#include "chrome/browser/ui/browser_tabstrip.h"
-#include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/extensions/native_app_window.h"
-#include "chrome/common/chrome_notification_types.h"
-#include "chrome/common/extensions/extension.h"
-#include "chrome/common/extensions/extension_constants.h"
-#include "chrome/common/extensions/extension_messages.h"
-#include "chrome/common/extensions/manifest_handlers/icons_handler.h"
-#include "components/web_modal/web_contents_modal_dialog_manager.h"
-#include "content/public/browser/invalidate_type.h"
-#include "content/public/browser/navigation_entry.h"
-#include "content/public/browser/notification_details.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_source.h"
-#include "content/public/browser/notification_types.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/resource_dispatcher_host.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/common/media_stream_request.h"
-#include "extensions/browser/view_type_utils.h"
-#include "skia/ext/image_operations.h"
-#include "third_party/skia/include/core/SkRegion.h"
-#include "ui/gfx/image/image_skia.h"
-
-#if defined(USE_ASH)
-#include "ash/launcher/launcher_types.h"
-#endif
-
-using content::ConsoleMessageLevel;
-using content::WebContents;
-using extensions::APIPermission;
-using web_modal::WebContentsModalDialogHost;
-using web_modal::WebContentsModalDialogManager;
-
-namespace {
-const int kDefaultWidth = 512;
-const int kDefaultHeight = 384;
-
-// The preferred icon size for displaying the app icon.
-#if defined(USE_ASH)
-const int kPreferredIconSize = ash::kLauncherPreferredSize;
-#else
-const int kPreferredIconSize = extension_misc::EXTENSION_ICON_SMALL;
-#endif
-
-static bool disable_external_open_for_testing_ = false;
-
-class ShellWindowLinkDelegate : public content::WebContentsDelegate {
- private:
-  virtual content::WebContents* OpenURLFromTab(
-      content::WebContents* source,
-      const content::OpenURLParams& params) OVERRIDE;
-};
-
-content::WebContents* ShellWindowLinkDelegate::OpenURLFromTab(
-    content::WebContents* source,
-    const content::OpenURLParams& params) {
-  platform_util::OpenExternal(params.url);
-  delete source;
-  return NULL;
-}
-
-}  // namespace
-
-ShellWindow::CreateParams::CreateParams()
-  : window_type(ShellWindow::WINDOW_TYPE_DEFAULT),
-    frame(ShellWindow::FRAME_CHROME),
-    transparent_background(false),
-    bounds(INT_MIN, INT_MIN, 0, 0),
-    creator_process_id(0),
-    state(ui::SHOW_STATE_DEFAULT),
-    hidden(false),
-    resizable(true),
-    focused(true) {
-}
-
-ShellWindow::CreateParams::~CreateParams() {
-}
-
-ShellWindow* ShellWindow::Create(Profile* profile,
-                                 const extensions::Extension* extension,
-                                 const GURL& url,
-                                 const CreateParams& params) {
-  // This object will delete itself when the window is closed.
-  ShellWindow* window = new ShellWindow(profile, extension);
-  window->Init(url, new AppWindowContents(window), params);
-  extensions::ShellWindowRegistry::Get(profile)->AddShellWindow(window);
-  return window;
-}
-
-ShellWindow::ShellWindow(Profile* profile,
-                         const extensions::Extension* extension)
-    : profile_(profile),
-      extension_(extension),
-      extension_id_(extension->id()),
-      window_type_(WINDOW_TYPE_DEFAULT),
-      image_loader_ptr_factory_(this),
-      fullscreen_for_window_api_(false),
-      fullscreen_for_tab_(false) {
-}
-
-void ShellWindow::Init(const GURL& url,
-                       ShellWindowContents* shell_window_contents,
-                       const CreateParams& params) {
-  // Initialize the render interface and web contents
-  shell_window_contents_.reset(shell_window_contents);
-  shell_window_contents_->Initialize(profile(), url);
-  WebContents* web_contents = shell_window_contents_->GetWebContents();
-  WebContentsModalDialogManager::CreateForWebContents(web_contents);
-  FaviconTabHelper::CreateForWebContents(web_contents);
-
-  web_contents->SetDelegate(this);
-  WebContentsModalDialogManager::FromWebContents(web_contents)->
-      set_delegate(this);
-  extensions::SetViewType(web_contents, extensions::VIEW_TYPE_APP_SHELL);
-
-  // Initialize the window
-  window_type_ = params.window_type;
-
-  gfx::Rect bounds = params.bounds;
-
-  if (bounds.width() == 0)
-    bounds.set_width(kDefaultWidth);
-  if (bounds.height() == 0)
-    bounds.set_height(kDefaultHeight);
-
-  // If left and top are left undefined, the native shell window will center
-  // the window on the main screen in a platform-defined manner.
-
-  ui::WindowShowState cached_state = ui::SHOW_STATE_DEFAULT;
-  if (!params.window_key.empty()) {
-    window_key_ = params.window_key;
-
-    apps::ShellWindowGeometryCache* cache =
-        apps::ShellWindowGeometryCache::Get(profile());
-
-    gfx::Rect cached_bounds;
-    if (cache->GetGeometry(extension()->id(), params.window_key,
-                           &cached_bounds, &cached_state)) {
-      bounds = cached_bounds;
-    }
-  }
-
-  CreateParams new_params = params;
-
-  gfx::Size& minimum_size = new_params.minimum_size;
-  gfx::Size& maximum_size = new_params.maximum_size;
-
-  // In the case that minimum size > maximum size, we consider the minimum
-  // size to be more important.
-  if (maximum_size.width() && maximum_size.width() < minimum_size.width())
-    maximum_size.set_width(minimum_size.width());
-  if (maximum_size.height() && maximum_size.height() < minimum_size.height())
-    maximum_size.set_height(minimum_size.height());
-
-  if (maximum_size.width() && bounds.width() > maximum_size.width())
-    bounds.set_width(maximum_size.width());
-  if (bounds.width() != INT_MIN && bounds.width() < minimum_size.width())
-    bounds.set_width(minimum_size.width());
-
-  if (maximum_size.height() && bounds.height() > maximum_size.height())
-    bounds.set_height(maximum_size.height());
-  if (bounds.height() != INT_MIN && bounds.height() < minimum_size.height())
-    bounds.set_height(minimum_size.height());
-
-  new_params.bounds = bounds;
-
-  if (cached_state != ui::SHOW_STATE_DEFAULT)
-    new_params.state = cached_state;
-
-  native_app_window_.reset(NativeAppWindow::Create(this, new_params));
-
-  if (!new_params.hidden) {
-    if (window_type_is_panel())
-      GetBaseWindow()->ShowInactive();  // Panels are not activated by default.
-    else
-      GetBaseWindow()->Show();
-  }
-
-  if (new_params.state == ui::SHOW_STATE_FULLSCREEN)
-    Fullscreen();
-  else if (new_params.state == ui::SHOW_STATE_MAXIMIZED)
-    Maximize();
-  else if (new_params.state == ui::SHOW_STATE_MINIMIZED)
-    Minimize();
-
-  OnNativeWindowChanged();
-
-  // When the render view host is changed, the native window needs to know
-  // about it in case it has any setup to do to make the renderer appear
-  // properly. In particular, on Windows, the view's clickthrough region needs
-  // to be set.
-  registrar_.Add(this, content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
-                 content::Source<content::NavigationController>(
-                    &web_contents->GetController()));
-  registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
-                 content::Source<Profile>(profile_));
-  // Close when the browser is exiting.
-  // TODO(mihaip): we probably don't want this in the long run (when platform
-  // apps are no longer tied to the browser process).
-  registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING,
-                 content::NotificationService::AllSources());
-
-  shell_window_contents_->LoadContents(params.creator_process_id);
-
-  // Prevent the browser process from shutting down while this window is open.
-  chrome::StartKeepAlive();
-
-  UpdateExtensionAppIcon();
-}
-
-ShellWindow::~ShellWindow() {
-  // Unregister now to prevent getting NOTIFICATION_APP_TERMINATING if we're the
-  // last window open.
-  registrar_.RemoveAll();
-
-  // Remove shutdown prevention.
-  chrome::EndKeepAlive();
-}
-
-void ShellWindow::RequestMediaAccessPermission(
-    content::WebContents* web_contents,
-    const content::MediaStreamRequest& request,
-    const content::MediaResponseCallback& callback) {
-  MediaCaptureDevicesDispatcher::GetInstance()->ProcessMediaAccessRequest(
-      web_contents, request, callback, extension());
-}
-
-WebContents* ShellWindow::OpenURLFromTab(WebContents* source,
-                                         const content::OpenURLParams& params) {
-  // Don't allow the current tab to be navigated. It would be nice to map all
-  // anchor tags (even those without target="_blank") to new tabs, but right
-  // now we can't distinguish between those and <meta> refreshes or window.href
-  // navigations, which we don't want to allow.
-  // TOOD(mihaip): Can we check for user gestures instead?
-  WindowOpenDisposition disposition = params.disposition;
-  if (disposition == CURRENT_TAB) {
-    AddMessageToDevToolsConsole(
-        content::CONSOLE_MESSAGE_LEVEL_ERROR,
-        base::StringPrintf(
-            "Can't open same-window link to \"%s\"; try target=\"_blank\".",
-            params.url.spec().c_str()));
-    return NULL;
-  }
-
-  // These dispositions aren't really navigations.
-  if (disposition == SUPPRESS_OPEN || disposition == SAVE_TO_DISK ||
-      disposition == IGNORE_ACTION) {
-    return NULL;
-  }
-
-  // Force all links to open in a new tab, even if they were trying to open a
-  // window.
-  chrome::NavigateParams new_tab_params(
-      static_cast<Browser*>(NULL), params.url, params.transition);
-  new_tab_params.disposition =
-      disposition == NEW_BACKGROUND_TAB ? disposition : NEW_FOREGROUND_TAB;
-  new_tab_params.initiating_profile = profile_;
-  chrome::Navigate(&new_tab_params);
-
-  if (!new_tab_params.target_contents) {
-    AddMessageToDevToolsConsole(
-        content::CONSOLE_MESSAGE_LEVEL_ERROR,
-        base::StringPrintf(
-            "Can't navigate to \"%s\"; apps do not support navigation.",
-            params.url.spec().c_str()));
-  }
-
-  return new_tab_params.target_contents;
-}
-
-void ShellWindow::AddNewContents(WebContents* source,
-                                 WebContents* new_contents,
-                                 WindowOpenDisposition disposition,
-                                 const gfx::Rect& initial_pos,
-                                 bool user_gesture,
-                                 bool* was_blocked) {
-  DCHECK(Profile::FromBrowserContext(new_contents->GetBrowserContext()) ==
-      profile_);
-#if defined(OS_MACOSX) || defined(OS_WIN) || \
-    (defined(OS_LINUX) && !defined(OS_CHROMEOS))
-  if (disable_external_open_for_testing_) {
-    Browser* browser =
-        chrome::FindOrCreateTabbedBrowser(profile_, chrome::GetActiveDesktop());
-    // Force all links to open in a new tab, even if they were trying to open a
-    // new window.
-    disposition =
-        disposition == NEW_BACKGROUND_TAB ? disposition : NEW_FOREGROUND_TAB;
-    chrome::AddWebContents(browser, NULL, new_contents, disposition,
-                           initial_pos, user_gesture, was_blocked);
-  } else {
-    new_contents->SetDelegate(new ShellWindowLinkDelegate());
-  }
-#else
-  Browser* browser =
-      chrome::FindOrCreateTabbedBrowser(profile_, chrome::GetActiveDesktop());
-  // Force all links to open in a new tab, even if they were trying to open a
-  // new window.
-  disposition =
-      disposition == NEW_BACKGROUND_TAB ? disposition : NEW_FOREGROUND_TAB;
-  chrome::AddWebContents(browser, NULL, new_contents, disposition, initial_pos,
-                         user_gesture, was_blocked);
-#endif
-}
-
-void ShellWindow::HandleKeyboardEvent(
-    WebContents* source,
-    const content::NativeWebKeyboardEvent& event) {
-  native_app_window_->HandleKeyboardEvent(event);
-}
-
-void ShellWindow::RequestToLockMouse(WebContents* web_contents,
-                                     bool user_gesture,
-                                     bool last_unlocked_by_target) {
-  bool has_permission = IsExtensionWithPermissionOrSuggestInConsole(
-      APIPermission::kPointerLock,
-      extension_,
-      web_contents->GetRenderViewHost());
-
-  web_contents->GotResponseToLockMouseRequest(has_permission);
-}
-
-void ShellWindow::OnNativeClose() {
-  extensions::ShellWindowRegistry::Get(profile_)->RemoveShellWindow(this);
-  if (shell_window_contents_)
-    shell_window_contents_->NativeWindowClosed();
-  delete this;
-}
-
-void ShellWindow::OnNativeWindowChanged() {
-  SaveWindowPosition();
-  if (shell_window_contents_ && native_app_window_)
-    shell_window_contents_->NativeWindowChanged(native_app_window_.get());
-}
-
-void ShellWindow::OnNativeWindowActivated() {
-  extensions::ShellWindowRegistry::Get(profile_)->ShellWindowActivated(this);
-}
-
-scoped_ptr<gfx::Image> ShellWindow::GetAppListIcon() {
-  // TODO(skuhne): We might want to use LoadImages in UpdateExtensionAppIcon
-  // instead to let the extension give us pre-defined icons in the launcher
-  // and the launcher list sizes. Since there is no mock yet, doing this now
-  // seems a bit premature and we scale for the time being.
-  if (app_icon_.IsEmpty())
-    return make_scoped_ptr(new gfx::Image());
-
-  SkBitmap bmp = skia::ImageOperations::Resize(
-        *app_icon_.ToSkBitmap(), skia::ImageOperations::RESIZE_BEST,
-        extension_misc::EXTENSION_ICON_SMALLISH,
-        extension_misc::EXTENSION_ICON_SMALLISH);
-  return make_scoped_ptr(
-      new gfx::Image(gfx::ImageSkia::CreateFrom1xBitmap(bmp)));
-}
-
-content::WebContents* ShellWindow::web_contents() const {
-  return shell_window_contents_->GetWebContents();
-}
-
-NativeAppWindow* ShellWindow::GetBaseWindow() {
-  return native_app_window_.get();
-}
-
-gfx::NativeWindow ShellWindow::GetNativeWindow() {
-  return GetBaseWindow()->GetNativeWindow();
-}
-
-gfx::Rect ShellWindow::GetClientBounds() const {
-  gfx::Rect bounds = native_app_window_->GetBounds();
-  bounds.Inset(native_app_window_->GetFrameInsets());
-  return bounds;
-}
-
-string16 ShellWindow::GetTitle() const {
-  // WebContents::GetTitle() will return the page's URL if there's no <title>
-  // specified. However, we'd prefer to show the name of the extension in that
-  // case, so we directly inspect the NavigationEntry's title.
-  if (!web_contents() ||
-      !web_contents()->GetController().GetActiveEntry() ||
-      web_contents()->GetController().GetActiveEntry()->GetTitle().empty())
-    return UTF8ToUTF16(extension()->name());
-  string16 title = web_contents()->GetTitle();
-  Browser::FormatTitleForDisplay(&title);
-  return title;
-}
-
-void ShellWindow::SetAppIconUrl(const GURL& url) {
-  // Avoid using any previous app icons were are being downloaded.
-  image_loader_ptr_factory_.InvalidateWeakPtrs();
-
-  app_icon_url_ = url;
-  web_contents()->DownloadImage(
-      url, true, kPreferredIconSize,
-      base::Bind(&ShellWindow::DidDownloadFavicon,
-                 image_loader_ptr_factory_.GetWeakPtr()));
-}
-
-void ShellWindow::UpdateDraggableRegions(
-    const std::vector<extensions::DraggableRegion>& regions) {
-  native_app_window_->UpdateDraggableRegions(regions);
-}
-
-void ShellWindow::UpdateAppIcon(const gfx::Image& image) {
-  if (image.IsEmpty())
-    return;
-  app_icon_ = image;
-  native_app_window_->UpdateWindowIcon();
-  extensions::ShellWindowRegistry::Get(profile_)->ShellWindowIconChanged(this);
-}
-
-void ShellWindow::Fullscreen() {
-  fullscreen_for_window_api_ = true;
-  GetBaseWindow()->SetFullscreen(true);
-}
-
-void ShellWindow::Maximize() {
-  GetBaseWindow()->Maximize();
-}
-
-void ShellWindow::Minimize() {
-  GetBaseWindow()->Minimize();
-}
-
-void ShellWindow::Restore() {
-  fullscreen_for_window_api_ = false;
-  fullscreen_for_tab_ = false;
-  if (GetBaseWindow()->IsFullscreenOrPending()) {
-    GetBaseWindow()->SetFullscreen(false);
-  } else {
-    GetBaseWindow()->Restore();
-  }
-}
-
-//------------------------------------------------------------------------------
-// Private methods
-
-void ShellWindow::OnImageLoaded(const gfx::Image& image) {
-  UpdateAppIcon(image);
-}
-
-void ShellWindow::DidDownloadFavicon(int id,
-                                     int http_status_code,
-                                     const GURL& image_url,
-                                     int requested_size,
-                                     const std::vector<SkBitmap>& bitmaps) {
-  if (image_url != app_icon_url_ || bitmaps.empty())
-    return;
-
-  // Bitmaps are ordered largest to smallest. Choose the smallest bitmap
-  // whose height >= the preferred size.
-  int largest_index = 0;
-  for (size_t i = 1; i < bitmaps.size(); ++i) {
-    if (bitmaps[i].height() < kPreferredIconSize)
-      break;
-    largest_index = i;
-  }
-  const SkBitmap& largest = bitmaps[largest_index];
-  UpdateAppIcon(gfx::Image::CreateFrom1xBitmap(largest));
-}
-
-void ShellWindow::UpdateExtensionAppIcon() {
-  // Avoid using any previous app icons were are being downloaded.
-  image_loader_ptr_factory_.InvalidateWeakPtrs();
-
-  // Enqueue OnImageLoaded callback.
-  extensions::ImageLoader* loader = extensions::ImageLoader::Get(profile());
-  loader->LoadImageAsync(
-      extension(),
-      extensions::IconsInfo::GetIconResource(extension(),
-                                             kPreferredIconSize,
-                                             ExtensionIconSet::MATCH_BIGGER),
-      gfx::Size(kPreferredIconSize, kPreferredIconSize),
-      base::Bind(&ShellWindow::OnImageLoaded,
-                 image_loader_ptr_factory_.GetWeakPtr()));
-}
-
-void ShellWindow::CloseContents(WebContents* contents) {
-  native_app_window_->Close();
-}
-
-bool ShellWindow::ShouldSuppressDialogs() {
-  return true;
-}
-
-content::ColorChooser* ShellWindow::OpenColorChooser(WebContents* web_contents,
-                                                     SkColor initial_color) {
-  return chrome::ShowColorChooser(web_contents, initial_color);
-}
-
-void ShellWindow::RunFileChooser(WebContents* tab,
-                                 const content::FileChooserParams& params) {
-  if (window_type_is_panel()) {
-    // Panels can't host a file dialog, abort. TODO(stevenjb): allow file
-    // dialogs to be unhosted but still close with the owning web contents.
-    // crbug.com/172502.
-    LOG(WARNING) << "File dialog opened by panel.";
-    return;
-  }
-  FileSelectHelper::RunFileChooser(tab, params);
-}
-
-bool ShellWindow::IsPopupOrPanel(const WebContents* source) const {
-  return true;
-}
-
-void ShellWindow::MoveContents(WebContents* source, const gfx::Rect& pos) {
-  native_app_window_->SetBounds(pos);
-}
-
-void ShellWindow::NavigationStateChanged(
-    const content::WebContents* source, unsigned changed_flags) {
-  if (changed_flags & content::INVALIDATE_TYPE_TITLE)
-    native_app_window_->UpdateWindowTitle();
-  else if (changed_flags & content::INVALIDATE_TYPE_TAB)
-    native_app_window_->UpdateWindowIcon();
-}
-
-void ShellWindow::ToggleFullscreenModeForTab(content::WebContents* source,
-                                             bool enter_fullscreen) {
-  if (!IsExtensionWithPermissionOrSuggestInConsole(
-      APIPermission::kFullscreen,
-      extension_,
-      source->GetRenderViewHost())) {
-    return;
-  }
-
-  fullscreen_for_tab_ = enter_fullscreen;
-
-  if (enter_fullscreen) {
-    native_app_window_->SetFullscreen(true);
-  } else if (!fullscreen_for_window_api_) {
-    native_app_window_->SetFullscreen(false);
-  }
-}
-
-bool ShellWindow::IsFullscreenForTabOrPending(
-    const content::WebContents* source) const {
-  return fullscreen_for_tab_;
-}
-
-void ShellWindow::Observe(int type,
-                          const content::NotificationSource& source,
-                          const content::NotificationDetails& details) {
-  switch (type) {
-    case content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED: {
-      // TODO(jianli): once http://crbug.com/123007 is fixed, we'll no longer
-      // need to make the native window (ShellWindowViews specially) update
-      // the clickthrough region for the new RVH.
-      native_app_window_->RenderViewHostChanged();
-      break;
-    }
-    case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
-      const extensions::Extension* unloaded_extension =
-          content::Details<extensions::UnloadedExtensionInfo>(
-              details)->extension;
-      if (extension_ == unloaded_extension)
-        native_app_window_->Close();
-      break;
-    }
-    case chrome::NOTIFICATION_APP_TERMINATING:
-      native_app_window_->Close();
-      break;
-    default:
-      NOTREACHED() << "Received unexpected notification";
-  }
-}
-
-extensions::ActiveTabPermissionGranter*
-    ShellWindow::GetActiveTabPermissionGranter() {
-  // Shell windows don't support the activeTab permission.
-  return NULL;
-}
-
-WebContentsModalDialogHost* ShellWindow::GetWebContentsModalDialogHost() {
-  return native_app_window_.get();
-}
-
-void ShellWindow::AddMessageToDevToolsConsole(ConsoleMessageLevel level,
-                                              const std::string& message) {
-  content::RenderViewHost* rvh = web_contents()->GetRenderViewHost();
-  rvh->Send(new ExtensionMsg_AddMessageToConsole(
-      rvh->GetRoutingID(), level, message));
-}
-
-void ShellWindow::SaveWindowPosition() {
-  if (window_key_.empty())
-    return;
-  if (!native_app_window_)
-    return;
-
-  apps::ShellWindowGeometryCache* cache =
-      apps::ShellWindowGeometryCache::Get(profile());
-
-  gfx::Rect bounds = native_app_window_->GetRestoredBounds();
-  bounds.Inset(native_app_window_->GetFrameInsets());
-  ui::WindowShowState window_state = native_app_window_->GetRestoredState();
-  cache->SaveGeometry(extension()->id(), window_key_, bounds, window_state);
-}
-
-// static
-SkRegion* ShellWindow::RawDraggableRegionsToSkRegion(
-      const std::vector<extensions::DraggableRegion>& regions) {
-  SkRegion* sk_region = new SkRegion;
-  for (std::vector<extensions::DraggableRegion>::const_iterator iter =
-           regions.begin();
-       iter != regions.end(); ++iter) {
-    const extensions::DraggableRegion& region = *iter;
-    sk_region->op(
-        region.bounds.x(),
-        region.bounds.y(),
-        region.bounds.right(),
-        region.bounds.bottom(),
-        region.draggable ? SkRegion::kUnion_Op : SkRegion::kDifference_Op);
-  }
-  return sk_region;
-}
-
-void ShellWindow::DisableExternalOpenForTesting() {
-  disable_external_open_for_testing_ = true;
-}
-
diff --git a/chrome/browser/ui/extensions/shell_window.h b/chrome/browser/ui/extensions/shell_window.h
deleted file mode 100644
index 64e66c7..0000000
--- a/chrome/browser/ui/extensions/shell_window.h
+++ /dev/null
@@ -1,319 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_EXTENSIONS_SHELL_WINDOW_H_
-#define CHROME_BROWSER_UI_EXTENSIONS_SHELL_WINDOW_H_
-
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "chrome/browser/extensions/extension_keybinding_registry.h"
-#include "chrome/browser/sessions/session_id.h"
-#include "chrome/browser/ui/chrome_web_modal_dialog_manager_delegate.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
-#include "content/public/browser/web_contents_delegate.h"
-#include "content/public/common/console_message_level.h"
-#include "ui/base/ui_base_types.h"  // WindowShowState
-#include "ui/gfx/image/image.h"
-#include "ui/gfx/rect.h"
-
-class GURL;
-class Profile;
-class NativeAppWindow;
-class SkRegion;
-
-namespace content {
-class WebContents;
-}
-
-namespace extensions {
-class Extension;
-class PlatformAppBrowserTest;
-class WindowController;
-
-struct DraggableRegion;
-}
-
-namespace ui {
-class BaseWindow;
-}
-
-// Manages the web contents for Shell Windows. The implementation for this
-// class should create and maintain the WebContents for the window, and handle
-// any message passing between the web contents and the extension system or
-// native window.
-class ShellWindowContents {
- public:
-  ShellWindowContents() {}
-  virtual ~ShellWindowContents() {}
-
-  // Called to initialize the WebContents, before the app window is created.
-  virtual void Initialize(Profile* profile, const GURL& url) = 0;
-
-  // Called to load the contents, after the app window is created.
-  virtual void LoadContents(int32 creator_process_id) = 0;
-
-  // Called when the native window changes.
-  virtual void NativeWindowChanged(NativeAppWindow* native_app_window) = 0;
-
-  // Called when the native window closes.
-  virtual void NativeWindowClosed() = 0;
-
-  virtual content::WebContents* GetWebContents() const = 0;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ShellWindowContents);
-};
-
-// ShellWindow is the type of window used by platform apps. Shell windows
-// have a WebContents but none of the chrome of normal browser windows.
-class ShellWindow : public content::NotificationObserver,
-                    public content::WebContentsDelegate,
-                    public extensions::ExtensionKeybindingRegistry::Delegate,
-                    public ChromeWebModalDialogManagerDelegate {
- public:
-  enum WindowType {
-    WINDOW_TYPE_DEFAULT  = 1 << 0,  // Default shell window.
-    WINDOW_TYPE_PANEL    = 1 << 1,  // OS controlled panel window (Ash only).
-    WINDOW_TYPE_V1_PANEL = 1 << 2,  // For apps v1 support in Ash; deprecate
-                                    // with v1 apps.
-  };
-
-  enum Frame {
-    FRAME_CHROME,  // Chrome-style window frame.
-    FRAME_NONE,  // Frameless window.
-  };
-
-  struct CreateParams {
-    CreateParams();
-    ~CreateParams();
-
-    WindowType window_type;
-    Frame frame;
-    bool transparent_background;  // Only supported on ash.
-
-    // Specify the initial content bounds of the window (excluding any window
-    // decorations). INT_MIN designates 'unspecified' for the position
-    // components, and 0 for the size components. When unspecified, they should
-    // be replaced with a default value.
-    gfx::Rect bounds;
-
-    gfx::Size minimum_size;
-    gfx::Size maximum_size;
-
-    std::string window_key;
-
-    // The process ID of the process that requested the create.
-    int32 creator_process_id;
-
-    // Initial state of the window.
-    ui::WindowShowState state;
-
-    // If true, don't show the window after creation.
-    bool hidden;
-
-    // If true, the window will be resizable by the user. Defaults to true.
-    bool resizable;
-
-    // If true, the window will be focused on creation. Defaults to true.
-    bool focused;
-  };
-
-  // Helper function for creating and intiailizing a v2 app window.
-  static ShellWindow* Create(Profile* profile,
-                             const extensions::Extension* extension,
-                             const GURL& url,
-                             const CreateParams& params);
-
-  // Convert draggable regions in raw format to SkRegion format. Caller is
-  // responsible for deleting the returned SkRegion instance.
-  static SkRegion* RawDraggableRegionsToSkRegion(
-      const std::vector<extensions::DraggableRegion>& regions);
-
-  // The constructor and Init methods are public for constructing a ShellWindow
-  // with a non-standard render interface (e.g. v1 apps using Ash Panels).
-  // Normally ShellWindow::Create should be used.
-  ShellWindow(Profile* profile, const extensions::Extension* extension);
-
-  // Initializes the render interface, web contents, and native window.
-  // |shell_window_contents| will become owned by ShellWindow.
-  void Init(const GURL& url,
-            ShellWindowContents* shell_window_contents,
-            const CreateParams& params);
-
-
-  const std::string& window_key() const { return window_key_; }
-  const SessionID& session_id() const { return session_id_; }
-  const extensions::Extension* extension() const { return extension_; }
-  const std::string& extension_id() const { return extension_id_; }
-  content::WebContents* web_contents() const;
-  WindowType window_type() const { return window_type_; }
-  bool window_type_is_panel() const {
-    return (window_type_ == WINDOW_TYPE_PANEL ||
-            window_type_ == WINDOW_TYPE_V1_PANEL);
-  }
-  Profile* profile() const { return profile_; }
-  const gfx::Image& app_icon() const { return app_icon_; }
-  const GURL& app_icon_url() { return app_icon_url_; }
-
-  NativeAppWindow* GetBaseWindow();
-  gfx::NativeWindow GetNativeWindow();
-
-  // Returns the bounds that should be reported to the renderer.
-  gfx::Rect GetClientBounds() const;
-
-  // This will return a slightly smaller icon then the app_icon to be used in
-  // application lists.
-  scoped_ptr<gfx::Image> GetAppListIcon();
-
-  // NativeAppWindows should call this to determine what the window's title
-  // is on startup and from within UpdateWindowTitle().
-  string16 GetTitle() const;
-
-  // Call to notify ShellRegistry and delete the window. Subclasses should
-  // invoke this method instead of using "delete this".
-  void OnNativeClose();
-
-  // Should be called by native implementations when the window size, position,
-  // or minimized/maximized state has changed.
-  void OnNativeWindowChanged();
-
-  // Should be called by native implementations when the window is activated.
-  void OnNativeWindowActivated();
-
-  // Specifies a url for the launcher icon.
-  void SetAppIconUrl(const GURL& icon_url);
-
-  // Called from the render interface to modify the draggable regions.
-  void UpdateDraggableRegions(
-      const std::vector<extensions::DraggableRegion>& regions);
-
-  // Updates the app image to |image|. Called internally from the image loader
-  // callback. Also called externally for v1 apps using Ash Panels.
-  void UpdateAppIcon(const gfx::Image& image);
-
-  // Transitions window into fullscreen, maximized, minimized or restores based
-  // on chrome.app.window API.
-  void Fullscreen();
-  void Maximize();
-  void Minimize();
-  void Restore();
-
-  ShellWindowContents* shell_window_contents_for_test() {
-    return shell_window_contents_.get();
-  }
-
-  static void DisableExternalOpenForTesting();
-
- protected:
-  virtual ~ShellWindow();
-
- private:
-  // PlatformAppBrowserTest needs access to web_contents()
-  friend class extensions::PlatformAppBrowserTest;
-
-  // content::WebContentsDelegate implementation.
-  virtual void CloseContents(content::WebContents* contents) OVERRIDE;
-  virtual bool ShouldSuppressDialogs() OVERRIDE;
-  virtual content::ColorChooser* OpenColorChooser(
-      content::WebContents* web_contents, SkColor color) OVERRIDE;
-  virtual void RunFileChooser(
-      content::WebContents* tab,
-      const content::FileChooserParams& params) OVERRIDE;
-  virtual bool IsPopupOrPanel(
-      const content::WebContents* source) const OVERRIDE;
-  virtual void MoveContents(
-      content::WebContents* source, const gfx::Rect& pos) OVERRIDE;
-  virtual void NavigationStateChanged(const content::WebContents* source,
-                                      unsigned changed_flags) OVERRIDE;
-  virtual void ToggleFullscreenModeForTab(content::WebContents* source,
-                                          bool enter_fullscreen) OVERRIDE;
-  virtual bool IsFullscreenForTabOrPending(
-      const content::WebContents* source) const OVERRIDE;
-  virtual void RequestMediaAccessPermission(
-      content::WebContents* web_contents,
-      const content::MediaStreamRequest& request,
-      const content::MediaResponseCallback& callback) OVERRIDE;
-  virtual content::WebContents* OpenURLFromTab(
-      content::WebContents* source,
-      const content::OpenURLParams& params) OVERRIDE;
-  virtual void AddNewContents(content::WebContents* source,
-                              content::WebContents* new_contents,
-                              WindowOpenDisposition disposition,
-                              const gfx::Rect& initial_pos,
-                              bool user_gesture,
-                              bool* was_blocked) OVERRIDE;
-  virtual void HandleKeyboardEvent(
-      content::WebContents* source,
-      const content::NativeWebKeyboardEvent& event) OVERRIDE;
-  virtual void RequestToLockMouse(content::WebContents* web_contents,
-                                  bool user_gesture,
-                                  bool last_unlocked_by_target) OVERRIDE;
-
-  // content::NotificationObserver implementation.
-  virtual void Observe(int type,
-                       const content::NotificationSource& source,
-                       const content::NotificationDetails& details) OVERRIDE;
-
-  // Helper method to add a message to the renderer's DevTools console.
-  void AddMessageToDevToolsConsole(content::ConsoleMessageLevel level,
-                                   const std::string& message);
-
-  // Saves the window geometry/position.
-  void SaveWindowPosition();
-
-  // Load the app's image, firing a load state change when loaded.
-  void UpdateExtensionAppIcon();
-
-  void OnImageLoaded(const gfx::Image& image);
-
-  // extensions::ExtensionKeybindingRegistry::Delegate implementation.
-  virtual extensions::ActiveTabPermissionGranter*
-      GetActiveTabPermissionGranter() OVERRIDE;
-
-  // web_modal::WebContentsModalDialogManagerDelegate implementation.
-  virtual web_modal::WebContentsModalDialogHost*
-      GetWebContentsModalDialogHost() OVERRIDE;
-
-  // Callback from web_contents()->DownloadFavicon.
-  void DidDownloadFavicon(int id,
-                          int http_status_code,
-                          const GURL& image_url,
-                          int requested_size,
-                          const std::vector<SkBitmap>& bitmaps);
-
-  Profile* profile_;  // weak pointer - owned by ProfileManager.
-  // weak pointer - owned by ExtensionService.
-  const extensions::Extension* extension_;
-  const std::string extension_id_;
-
-  // Identifier that is used when saving and restoring geometry for this
-  // window.
-  std::string window_key_;
-
-  const SessionID session_id_;
-  WindowType window_type_;
-  content::NotificationRegistrar registrar_;
-
-  // Icon shown in the task bar.
-  gfx::Image app_icon_;
-
-  // Icon URL to be used for setting the app icon. If not empty, app_icon_ will
-  // be fetched and set using this URL.
-  GURL app_icon_url_;
-
-  scoped_ptr<NativeAppWindow> native_app_window_;
-  scoped_ptr<ShellWindowContents> shell_window_contents_;
-
-  base::WeakPtrFactory<ShellWindow> image_loader_ptr_factory_;
-
-  // Fullscreen entered by app.window api.
-  bool fullscreen_for_window_api_;
-  // Fullscreen entered by HTML requestFullscreen.
-  bool fullscreen_for_tab_;
-
-  DISALLOW_COPY_AND_ASSIGN(ShellWindow);
-};
-
-#endif  // CHROME_BROWSER_UI_EXTENSIONS_SHELL_WINDOW_H_
diff --git a/chrome/browser/ui/external_protocol_dialog_delegate.h b/chrome/browser/ui/external_protocol_dialog_delegate.h
index 27647ca..8862e7e 100644
--- a/chrome/browser/ui/external_protocol_dialog_delegate.h
+++ b/chrome/browser/ui/external_protocol_dialog_delegate.h
@@ -7,7 +7,7 @@
 
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/ui/protocol_dialog_delegate.h"
 #include "googleurl/src/gurl.h"
 
diff --git a/chrome/browser/ui/fast_unload_controller.cc b/chrome/browser/ui/fast_unload_controller.cc
new file mode 100644
index 0000000..5a8373e
--- /dev/null
+++ b/chrome/browser/ui/fast_unload_controller.cc
@@ -0,0 +1,380 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/fast_unload_controller.h"
+
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_tabstrip.h"
+#include "chrome/browser/ui/tab_contents/core_tab_helper.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/browser/ui/tabs/tab_strip_model_delegate.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_source.h"
+#include "content/public/browser/notification_types.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_delegate.h"
+
+namespace chrome {
+
+
+////////////////////////////////////////////////////////////////////////////////
+// DetachedWebContentsDelegate will delete web contents when they close.
+class FastUnloadController::DetachedWebContentsDelegate
+    : public content::WebContentsDelegate {
+ public:
+  DetachedWebContentsDelegate() { }
+  virtual ~DetachedWebContentsDelegate() { }
+
+ private:
+  // WebContentsDelegate implementation.
+  virtual bool ShouldSuppressDialogs() OVERRIDE {
+    return true;  // Return true so dialogs are suppressed.
+  }
+
+  virtual void CloseContents(content::WebContents* source) OVERRIDE {
+    // Finished detached close.
+    // FastUnloadController will observe
+    // |NOTIFICATION_WEB_CONTENTS_DISCONNECTED|.
+    delete source;
+  }
+
+  DISALLOW_COPY_AND_ASSIGN(DetachedWebContentsDelegate);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// FastUnloadController, public:
+
+FastUnloadController::FastUnloadController(Browser* browser)
+    : browser_(browser),
+      tab_needing_before_unload_ack_(NULL),
+      is_attempting_to_close_browser_(false),
+      detached_delegate_(new DetachedWebContentsDelegate()),
+      weak_factory_(this) {
+  browser_->tab_strip_model()->AddObserver(this);
+}
+
+FastUnloadController::~FastUnloadController() {
+  browser_->tab_strip_model()->RemoveObserver(this);
+}
+
+bool FastUnloadController::CanCloseContents(content::WebContents* contents) {
+  // Don't try to close the tab when the whole browser is being closed, since
+  // that avoids the fast shutdown path where we just kill all the renderers.
+  return !is_attempting_to_close_browser_;
+}
+
+bool FastUnloadController::BeforeUnloadFired(content::WebContents* contents,
+                                             bool proceed) {
+  if (!is_attempting_to_close_browser_) {
+    if (!proceed) {
+      contents->SetClosedByUserGesture(false);
+    } else {
+      // No more dialogs are possible, so remove the tab and finish
+      // running unload listeners asynchrounously.
+      browser_->tab_strip_model()->delegate()->CreateHistoricalTab(contents);
+      DetachWebContents(contents);
+    }
+    return proceed;
+  }
+
+  if (!proceed) {
+    CancelWindowClose();
+    contents->SetClosedByUserGesture(false);
+    return false;
+  }
+
+  if (tab_needing_before_unload_ack_ == contents) {
+    // Now that beforeunload has fired, queue the tab to fire unload.
+    tab_needing_before_unload_ack_ = NULL;
+    tabs_needing_unload_.insert(contents);
+    ProcessPendingTabs();
+    // We want to handle firing the unload event ourselves since we want to
+    // fire all the beforeunload events before attempting to fire the unload
+    // events should the user cancel closing the browser.
+    return false;
+  }
+
+  return true;
+}
+
+bool FastUnloadController::ShouldCloseWindow() {
+  if (HasCompletedUnloadProcessing())
+    return true;
+
+  is_attempting_to_close_browser_ = true;
+
+  if (!TabsNeedBeforeUnloadFired())
+    return true;
+
+  ProcessPendingTabs();
+  return false;
+}
+
+bool FastUnloadController::TabsNeedBeforeUnloadFired() {
+  if (!tabs_needing_before_unload_.empty() ||
+      tab_needing_before_unload_ack_ != NULL)
+    return true;
+
+  if (!tabs_needing_unload_.empty())
+    return false;
+
+  for (int i = 0; i < browser_->tab_strip_model()->count(); ++i) {
+    content::WebContents* contents =
+        browser_->tab_strip_model()->GetWebContentsAt(i);
+    if (contents->NeedToFireBeforeUnload())
+      tabs_needing_before_unload_.insert(contents);
+  }
+  return !tabs_needing_before_unload_.empty();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// FastUnloadController, content::NotificationObserver implementation:
+
+void FastUnloadController::Observe(
+      int type,
+      const content::NotificationSource& source,
+      const content::NotificationDetails& details) {
+  switch (type) {
+    case content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED: {
+      registrar_.Remove(this,
+                        content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
+                        source);
+      content::WebContents* contents =
+          content::Source<content::WebContents>(source).ptr();
+      ClearUnloadState(contents);
+      break;
+    }
+    default:
+      NOTREACHED() << "Got a notification we didn't register for.";
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// FastUnloadController, TabStripModelObserver implementation:
+
+void FastUnloadController::TabInsertedAt(content::WebContents* contents,
+                                         int index,
+                                         bool foreground) {
+  TabAttachedImpl(contents);
+}
+
+void FastUnloadController::TabDetachedAt(content::WebContents* contents,
+                                         int index) {
+  TabDetachedImpl(contents);
+}
+
+void FastUnloadController::TabReplacedAt(TabStripModel* tab_strip_model,
+                                         content::WebContents* old_contents,
+                                         content::WebContents* new_contents,
+                                         int index) {
+  TabDetachedImpl(old_contents);
+  TabAttachedImpl(new_contents);
+}
+
+void FastUnloadController::TabStripEmpty() {
+  // Set is_attempting_to_close_browser_ here, so that extensions, etc, do not
+  // attempt to add tabs to the browser before it closes.
+  is_attempting_to_close_browser_ = true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// FastUnloadController, private:
+
+void FastUnloadController::TabAttachedImpl(content::WebContents* contents) {
+  // If the tab crashes in the beforeunload or unload handler, it won't be
+  // able to ack. But we know we can close it.
+  registrar_.Add(
+      this,
+      content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
+      content::Source<content::WebContents>(contents));
+}
+
+void FastUnloadController::TabDetachedImpl(content::WebContents* contents) {
+  if (tabs_needing_unload_ack_.find(contents) !=
+      tabs_needing_unload_ack_.end()) {
+    // Tab needs unload to complete.
+    // It will send |NOTIFICATION_WEB_CONTENTS_DISCONNECTED| when done.
+    return;
+  }
+
+  // If WEB_CONTENTS_DISCONNECTED was received then the notification may have
+  // already been unregistered.
+  const content::NotificationSource& source =
+      content::Source<content::WebContents>(contents);
+  if (registrar_.IsRegistered(this,
+                              content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
+                              source)) {
+    registrar_.Remove(this,
+                      content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
+                      source);
+  }
+
+  if (is_attempting_to_close_browser_)
+    ClearUnloadState(contents);
+}
+
+bool FastUnloadController::DetachWebContents(content::WebContents* contents) {
+  int index = browser_->tab_strip_model()->GetIndexOfWebContents(contents);
+  if (index != TabStripModel::kNoTab &&
+      contents->NeedToFireBeforeUnload()) {
+    tabs_needing_unload_ack_.insert(contents);
+    browser_->tab_strip_model()->DetachWebContentsAt(index);
+    contents->SetDelegate(detached_delegate_.get());
+    CoreTabHelper* core_tab_helper = CoreTabHelper::FromWebContents(contents);
+    core_tab_helper->OnUnloadDetachedStarted();
+    return true;
+  }
+  return false;
+}
+
+void FastUnloadController::ProcessPendingTabs() {
+  if (!is_attempting_to_close_browser_) {
+    // Because we might invoke this after a delay it's possible for the value of
+    // is_attempting_to_close_browser_ to have changed since we scheduled the
+    // task.
+    return;
+  }
+
+  if (tab_needing_before_unload_ack_ != NULL) {
+    // Wait for |BeforeUnloadFired| before proceeding.
+    return;
+  }
+
+  // Process a beforeunload handler.
+  if (!tabs_needing_before_unload_.empty()) {
+    WebContentsSet::iterator it = tabs_needing_before_unload_.begin();
+    content::WebContents* contents = *it;
+    tabs_needing_before_unload_.erase(it);
+    // Null check render_view_host here as this gets called on a PostTask and
+    // the tab's render_view_host may have been nulled out.
+    if (contents->GetRenderViewHost()) {
+      tab_needing_before_unload_ack_ = contents;
+
+      CoreTabHelper* core_tab_helper = CoreTabHelper::FromWebContents(contents);
+      core_tab_helper->OnCloseStarted();
+
+      contents->GetRenderViewHost()->FirePageBeforeUnload(false);
+    } else {
+      ProcessPendingTabs();
+    }
+    return;
+  }
+
+  // Process all the unload handlers. (The beforeunload handlers have finished.)
+  if (!tabs_needing_unload_.empty()) {
+    browser_->OnWindowClosing();
+
+    // Run unload handlers detached since no more interaction is possible.
+    WebContentsSet::iterator it = tabs_needing_unload_.begin();
+    while (it != tabs_needing_unload_.end()) {
+      WebContentsSet::iterator current = it++;
+      content::WebContents* contents = *current;
+      tabs_needing_unload_.erase(current);
+      // Null check render_view_host here as this gets called on a PostTask
+      // and the tab's render_view_host may have been nulled out.
+      if (contents->GetRenderViewHost()) {
+        CoreTabHelper* core_tab_helper =
+            CoreTabHelper::FromWebContents(contents);
+        core_tab_helper->OnUnloadStarted();
+        DetachWebContents(contents);
+        contents->GetRenderViewHost()->ClosePage();
+      }
+    }
+
+    // Get the browser hidden.
+    if (browser_->tab_strip_model()->empty()) {
+      browser_->TabStripEmpty();
+    } else {
+      browser_->tab_strip_model()->CloseAllTabs();  // tabs not needing unload
+    }
+    return;
+  }
+
+  if (HasCompletedUnloadProcessing()) {
+    browser_->OnWindowClosing();
+
+    // Get the browser closed.
+    if (browser_->tab_strip_model()->empty()) {
+      browser_->TabStripEmpty();
+    } else {
+      // There may be tabs if the last tab needing beforeunload crashed.
+      browser_->tab_strip_model()->CloseAllTabs();
+    }
+    return;
+  }
+}
+
+bool FastUnloadController::HasCompletedUnloadProcessing() const {
+  return is_attempting_to_close_browser_ &&
+      tabs_needing_before_unload_.empty() &&
+      tab_needing_before_unload_ack_ == NULL &&
+      tabs_needing_unload_.empty() &&
+      tabs_needing_unload_ack_.empty();
+}
+
+void FastUnloadController::CancelWindowClose() {
+  // Closing of window can be canceled from a beforeunload handler.
+  DCHECK(is_attempting_to_close_browser_);
+  tabs_needing_before_unload_.clear();
+  if (tab_needing_before_unload_ack_ != NULL) {
+
+    CoreTabHelper* core_tab_helper =
+        CoreTabHelper::FromWebContents(tab_needing_before_unload_ack_);
+    core_tab_helper->OnCloseCanceled();
+    tab_needing_before_unload_ack_ = NULL;
+  }
+  for (WebContentsSet::iterator it = tabs_needing_unload_.begin();
+       it != tabs_needing_unload_.end(); it++) {
+    content::WebContents* contents = *it;
+
+    CoreTabHelper* core_tab_helper = CoreTabHelper::FromWebContents(contents);
+    core_tab_helper->OnCloseCanceled();
+  }
+  tabs_needing_unload_.clear();
+
+  // No need to clear tabs_needing_unload_ack_. Those tabs are already detached.
+
+  is_attempting_to_close_browser_ = false;
+
+  content::NotificationService::current()->Notify(
+      chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED,
+      content::Source<Browser>(browser_),
+      content::NotificationService::NoDetails());
+}
+
+void FastUnloadController::ClearUnloadState(content::WebContents* contents) {
+  if (tabs_needing_unload_ack_.erase(contents) > 0) {
+    if (HasCompletedUnloadProcessing())
+      PostTaskForProcessPendingTabs();
+    return;
+  }
+
+  if (!is_attempting_to_close_browser_)
+    return;
+
+  if (tab_needing_before_unload_ack_ == contents) {
+    tab_needing_before_unload_ack_ = NULL;
+    PostTaskForProcessPendingTabs();
+    return;
+  }
+
+  if (tabs_needing_before_unload_.erase(contents) > 0 ||
+      tabs_needing_unload_.erase(contents) > 0) {
+    if (tab_needing_before_unload_ack_ == NULL)
+      PostTaskForProcessPendingTabs();
+  }
+}
+
+void FastUnloadController::PostTaskForProcessPendingTabs() {
+  base::MessageLoop::current()->PostTask(
+      FROM_HERE,
+      base::Bind(&FastUnloadController::ProcessPendingTabs,
+                 weak_factory_.GetWeakPtr()));
+}
+
+}  // namespace chrome
diff --git a/chrome/browser/ui/fast_unload_controller.h b/chrome/browser/ui/fast_unload_controller.h
new file mode 100644
index 0000000..945197d
--- /dev/null
+++ b/chrome/browser/ui/fast_unload_controller.h
@@ -0,0 +1,180 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_FAST_UNLOAD_CONTROLLER_H_
+#define CHROME_BROWSER_UI_FAST_UNLOAD_CONTROLLER_H_
+
+#include <set>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/strings/string_piece.h"
+#include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+
+class Browser;
+class TabStripModel;
+
+namespace content {
+class NotificationSource;
+class NotifictaionDetails;
+class WebContents;
+}
+
+namespace chrome {
+// FastUnloadController manages closing tabs and windows -- especially in
+// regards to beforeunload handlers (have proceed/cancel dialogs) and
+// unload handlers (have no user interaction).
+//
+// Typical flow of closing a tab:
+//  1. Browser calls CanCloseContents().
+//     If true, browser calls contents::CloseWebContents().
+//  2. WebContents notifies us via its delegate and BeforeUnloadFired()
+//     that the beforeunload handler was run. If the user allowed the
+//     close to continue, we detached the tab and hold onto it while the
+//     close finishes.
+//
+// Typical flow of closing a window:
+//  1. BrowserView::CanClose() calls TabsNeedBeforeUnloadFired().
+//     If beforeunload/unload handlers need to run, FastUnloadController returns
+//     true and calls ProcessPendingTabs() (private method).
+//  2. For each tab with a beforeunload/unload handler, ProcessPendingTabs()
+//        calls |CoreTabHelper::OnCloseStarted()|
+//        and   |web_contents->GetRenderViewHost()->FirePageBeforeUnload()|.
+//  3. If the user allowed the close to continue, we detach all the tabs with
+//     unload handlers, remove them from the tab strip, and finish closing
+//     the tabs in the background.
+//  4. The browser gets notified that the tab strip is empty and calls
+//     CloseFrame where the empty tab strip causes the window to hide.
+//     Once the detached tabs finish, the browser calls CloseFrame again and
+//     the window is finally closed.
+//
+class FastUnloadController : public content::NotificationObserver,
+                             public TabStripModelObserver {
+ public:
+  explicit FastUnloadController(Browser* browser);
+  virtual ~FastUnloadController();
+
+  // Returns true if |contents| can be cleanly closed. When |browser_| is being
+  // closed, this function will return false to indicate |contents| should not
+  // be cleanly closed, since the fast shutdown path will just kill its
+  // renderer.
+  bool CanCloseContents(content::WebContents* contents);
+
+  // Called when a BeforeUnload handler is fired for |contents|. |proceed|
+  // indicates the user's response to the Y/N BeforeUnload handler dialog. If
+  // this parameter is false, any pending attempt to close the whole browser
+  // will be canceled. Returns true if Unload handlers should be fired. When the
+  // |browser_| is being closed, Unload handlers for any particular WebContents
+  // will not be run until every WebContents being closed has a chance to run
+  // its BeforeUnloadHandler.
+  bool BeforeUnloadFired(content::WebContents* contents, bool proceed);
+
+  bool is_attempting_to_close_browser() const {
+    return is_attempting_to_close_browser_;
+  }
+
+  // Called in response to a request to close |browser_|'s window. Returns true
+  // when there are no remaining beforeunload handlers to be run.
+  bool ShouldCloseWindow();
+
+  // Returns true if |browser_| has any tabs that have BeforeUnload handlers
+  // that have not been fired. This method is non-const because it builds a list
+  // of tabs that need their BeforeUnloadHandlers fired.
+  // TODO(beng): This seems like it could be private but it is used by
+  //             AreAllBrowsersCloseable() in application_lifetime.cc. It seems
+  //             very similar to ShouldCloseWindow() and some consolidation
+  //             could be pursued.
+  bool TabsNeedBeforeUnloadFired();
+
+  // Returns true if all tabs' beforeunload/unload events have fired.
+  bool HasCompletedUnloadProcessing() const;
+
+ private:
+  // Overridden from content::NotificationObserver:
+  virtual void Observe(int type,
+                       const content::NotificationSource& source,
+                       const content::NotificationDetails& details) OVERRIDE;
+
+  // Overridden from TabStripModelObserver:
+  virtual void TabInsertedAt(content::WebContents* contents,
+                             int index,
+                             bool foreground) OVERRIDE;
+  virtual void TabDetachedAt(content::WebContents* contents,
+                             int index) OVERRIDE;
+  virtual void TabReplacedAt(TabStripModel* tab_strip_model,
+                             content::WebContents* old_contents,
+                             content::WebContents* new_contents,
+                             int index) OVERRIDE;
+  virtual void TabStripEmpty() OVERRIDE;
+
+  void TabAttachedImpl(content::WebContents* contents);
+  void TabDetachedImpl(content::WebContents* contents);
+
+  // Detach |contents| and wait for it to finish closing.
+  // The close must be inititiated outside of this method.
+  // Returns true if it succeeds.
+  bool DetachWebContents(content::WebContents* contents);
+
+  // Processes the next tab that needs it's beforeunload/unload event fired.
+  void ProcessPendingTabs();
+
+  // Clears all the state associated with processing tabs' beforeunload/unload
+  // events since the user cancelled closing the window.
+  void CancelWindowClose();
+
+  // Cleans up state appropriately when we are trying to close the
+  // browser or close a tab in the background. We also use this in the
+  // cases where a tab crashes or hangs even if the
+  // beforeunload/unload haven't successfully fired.
+  void ClearUnloadState(content::WebContents* contents);
+
+  // Helper for |ClearUnloadState| to unwind stack before proceeding.
+  void PostTaskForProcessPendingTabs();
+
+  // Log a step of the unload processing.
+  void LogUnloadStep(const base::StringPiece& step_name,
+                     content::WebContents* contents) const;
+
+  Browser* browser_;
+
+  content::NotificationRegistrar registrar_;
+
+  typedef std::set<content::WebContents*> WebContentsSet;
+
+  // Tracks tabs that need their beforeunload event started.
+  // Only gets populated when we try to close the browser.
+  WebContentsSet tabs_needing_before_unload_;
+
+  // Tracks the tab that needs its beforeunload event result.
+  // Only gets populated when we try to close the browser.
+  content::WebContents* tab_needing_before_unload_ack_;
+
+  // Tracks tabs that need their unload event started.
+  // Only gets populated when we try to close the browser.
+  WebContentsSet tabs_needing_unload_;
+
+  // Tracks tabs that need to finish running their unload event.
+  // Populated both when closing individual tabs and when closing the browser.
+  WebContentsSet tabs_needing_unload_ack_;
+
+  // Whether we are processing the beforeunload and unload events of each tab
+  // in preparation for closing the browser. FastUnloadController owns this
+  // state rather than Browser because unload handlers are the only reason that
+  // a Browser window isn't just immediately closed.
+  bool is_attempting_to_close_browser_;
+
+  // Manage tabs with beforeunload/unload handlers that close detached.
+  class DetachedWebContentsDelegate;
+  scoped_ptr<DetachedWebContentsDelegate> detached_delegate_;
+
+  base::WeakPtrFactory<FastUnloadController> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(FastUnloadController);
+};
+
+}  // namespace chrome
+
+#endif  // CHROME_BROWSER_UI_FAST_UNLOAD_CONTROLLER_H_
diff --git a/chrome/browser/ui/fullscreen/fullscreen_controller.cc b/chrome/browser/ui/fullscreen/fullscreen_controller.cc
index 6c9c340..935703d 100644
--- a/chrome/browser/ui/fullscreen/fullscreen_controller.cc
+++ b/chrome/browser/ui/fullscreen/fullscreen_controller.cc
@@ -79,8 +79,13 @@
 
 void FullscreenController::ToggleFullscreenModeForTab(WebContents* web_contents,
                                                       bool enter_fullscreen) {
-  if (web_contents != browser_->tab_strip_model()->GetActiveWebContents())
+  if (fullscreened_tab_) {
+    if (web_contents != fullscreened_tab_)
+      return;
+  } else if (
+      web_contents != browser_->tab_strip_model()->GetActiveWebContents()) {
     return;
+  }
   if (IsFullscreenForTabOrPending() == enter_fullscreen)
     return;
 
diff --git a/chrome/browser/ui/fullscreen/fullscreen_controller_state_unittest.cc b/chrome/browser/ui/fullscreen/fullscreen_controller_state_unittest.cc
index 24984be..885bb76 100644
--- a/chrome/browser/ui/fullscreen/fullscreen_controller_state_unittest.cc
+++ b/chrome/browser/ui/fullscreen/fullscreen_controller_state_unittest.cc
@@ -7,6 +7,7 @@
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/fullscreen/fullscreen_controller.h"
 #include "chrome/browser/ui/fullscreen/fullscreen_controller_state_test.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/test/base/browser_with_test_window_test.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/url_constants.h"
@@ -597,3 +598,50 @@
   EXPECT_EQ(FEB_TYPE_NONE,
             browser()->fullscreen_controller()->GetFullscreenExitBubbleType());
 }
+
+// Test that switching tabs takes the browser out of tab fullscreen.
+TEST_F(FullscreenControllerStateUnitTest, ExitTabFullscreenViaSwitchingTab) {
+  AddTab(browser(), GURL(content::kAboutBlankURL));
+  AddTab(browser(), GURL(content::kAboutBlankURL));
+  ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE));
+  ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE));
+  ASSERT_TRUE(browser()->window()->IsFullscreen());
+
+  browser()->tab_strip_model()->SelectNextTab();
+  ChangeWindowFullscreenState();
+  EXPECT_FALSE(browser()->window()->IsFullscreen());
+}
+
+// Test that switching tabs via detaching the active tab (which is in tab
+// fullscreen) takes the browser out of tab fullscreen. This case can
+// occur if the user is in both tab fullscreen and immersive browser fullscreen.
+TEST_F(FullscreenControllerStateUnitTest, ExitTabFullscreenViaDetachingTab) {
+  AddTab(browser(), GURL(content::kAboutBlankURL));
+  AddTab(browser(), GURL(content::kAboutBlankURL));
+  ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE));
+  ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE));
+  ASSERT_TRUE(browser()->window()->IsFullscreen());
+
+  scoped_ptr<content::WebContents> web_contents(
+      browser()->tab_strip_model()->DetachWebContentsAt(0));
+  ChangeWindowFullscreenState();
+  EXPECT_FALSE(browser()->window()->IsFullscreen());
+}
+
+// Test that replacing the web contents for a tab which is in tab fullscreen
+// takes the browser out of tab fullscreen. This can occur if the user
+// navigates to a prerendered page from a page which is tab fullscreen.
+TEST_F(FullscreenControllerStateUnitTest, ExitTabFullscreenViaReplacingTab) {
+  AddTab(browser(), GURL(content::kAboutBlankURL));
+  ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE));
+  ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE));
+  ASSERT_TRUE(browser()->window()->IsFullscreen());
+
+  content::WebContents* new_web_contents = content::WebContents::Create(
+      content::WebContents::CreateParams(profile()));
+  scoped_ptr<content::WebContents> old_web_contents(
+      browser()->tab_strip_model()->ReplaceWebContentsAt(
+          0, new_web_contents));
+  ChangeWindowFullscreenState();
+  EXPECT_FALSE(browser()->window()->IsFullscreen());
+}
diff --git a/chrome/browser/ui/fullscreen/fullscreen_exit_bubble.h b/chrome/browser/ui/fullscreen/fullscreen_exit_bubble.h
index da20148..d8d464d 100644
--- a/chrome/browser/ui/fullscreen/fullscreen_exit_bubble.h
+++ b/chrome/browser/ui/fullscreen/fullscreen_exit_bubble.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_EXIT_BUBBLE_H_
 #define CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_EXIT_BUBBLE_H_
 
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/ui/fullscreen/fullscreen_exit_bubble_type.h"
 #include "googleurl/src/gurl.h"
 #include "ui/base/animation/animation_delegate.h"
diff --git a/chrome/browser/ui/gesture_prefs_observer_factory_aura.cc b/chrome/browser/ui/gesture_prefs_observer_factory_aura.cc
index 288af95..c02c3e4 100644
--- a/chrome/browser/ui/gesture_prefs_observer_factory_aura.cc
+++ b/chrome/browser/ui/gesture_prefs_observer_factory_aura.cc
@@ -311,6 +311,8 @@
   GestureConfiguration::set_rail_start_proportion(
       prefs_->GetDouble(
           prefs::kRailStartProportion));
+  GestureConfiguration::set_scroll_prediction_seconds(
+      prefs_->GetDouble(prefs::kScrollPredictionSeconds));
 
   UpdateOverscrollPrefs();
   UpdateImmersiveModePrefs();
@@ -560,6 +562,10 @@
       prefs::kRailStartProportion,
       GestureConfiguration::rail_start_proportion(),
       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+  registry->RegisterDoublePref(
+      prefs::kScrollPredictionSeconds,
+      GestureConfiguration::scroll_prediction_seconds(),
+      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
 
   // Register for migration.
   registry->RegisterDoublePref(
diff --git a/chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.cc b/chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.cc
index 47782e4..114e8fa 100644
--- a/chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.cc
+++ b/chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.cc
@@ -72,8 +72,6 @@
 }
 
 void AutofillPopupViewGtk::Hide() {
-  AutofillPopupView::Hide();
-
   delete this;
 }
 
diff --git a/chrome/browser/ui/gtk/avatar_menu_bubble_gtk.cc b/chrome/browser/ui/gtk/avatar_menu_bubble_gtk.cc
index 8d81513..5488cf8 100644
--- a/chrome/browser/ui/gtk/avatar_menu_bubble_gtk.cc
+++ b/chrome/browser/ui/gtk/avatar_menu_bubble_gtk.cc
@@ -124,17 +124,6 @@
   OnAvatarMenuModelChanged(avatar_menu_model_.get());
 }
 
-void AvatarMenuBubbleGtk::OnRealize(GtkWidget* parent_widget) {
-  if (!managed_user_info_ || !theme_service_->UsingNativeTheme())
-    return;
-
-  // Use the same background color for the GtkTextView as the background color
-  // of the enclosing widget.
-  GtkStyle* style = gtk_widget_get_style(parent_widget);
-  GdkColor bg_color = style->bg[GTK_STATE_NORMAL];
-  gtk_widget_modify_base(managed_user_info_, GTK_STATE_NORMAL, &bg_color);
-}
-
 void AvatarMenuBubbleGtk::InitMenuContents() {
   size_t profile_count = avatar_menu_model_->GetNumberOfItems();
   GtkWidget* items_vbox = gtk_vbox_new(FALSE, ui::kContentAreaSpacing);
@@ -183,40 +172,29 @@
   gtk_box_pack_start(GTK_BOX(inner_contents_),
                      gtk_hseparator_new(), TRUE, TRUE, 0);
 
-  // Add information about managed users.
-  managed_user_info_ = gtk_text_view_new();
-  gtk_text_view_set_editable(GTK_TEXT_VIEW(managed_user_info_), FALSE);
-  gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(managed_user_info_), FALSE);
-  GtkTextBuffer* text_buffer =
-      gtk_text_view_get_buffer(GTK_TEXT_VIEW(managed_user_info_));
-  std::string info =
-      UTF16ToUTF8(avatar_menu_model_->GetManagedUserInformation());
-  gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(managed_user_info_), GTK_WRAP_WORD);
-
-  // Insert the managed user icon. Insert it inside a hbox in order to be able
-  // to define a padding around it.
-  GtkTextIter start_iter;
-  gtk_text_buffer_get_start_iter(text_buffer, &start_iter);
-  GtkWidget* icon_box = gtk_hbox_new(FALSE, 0);
+  // Add information about managed users within a hbox.
+  GtkWidget* managed_user_info = gtk_hbox_new(FALSE, 5);
   GdkPixbuf* limited_user_pixbuf =
       avatar_menu_model_->GetManagedUserIcon().ToGdkPixbuf();
   GtkWidget* limited_user_img = gtk_image_new_from_pixbuf(limited_user_pixbuf);
-  gtk_box_pack_start(GTK_BOX(icon_box), limited_user_img, FALSE, FALSE, 5);
-  GtkTextChildAnchor* anchor =
-      gtk_text_buffer_create_child_anchor(text_buffer, &start_iter);
-  gtk_text_view_add_child_at_anchor(
-      GTK_TEXT_VIEW(managed_user_info_), icon_box, anchor);
-
-  // Insert the information text.
-  GtkTextIter end_iter;
-  gtk_text_buffer_get_end_iter(text_buffer, &end_iter);
-  GtkTextTag* text_tag = gtk_text_buffer_create_tag(
-      text_buffer, NULL, "size-set", TRUE, "size", 10 * PANGO_SCALE, NULL);
-  gtk_text_buffer_insert_with_tags(
-      text_buffer, &end_iter, info.c_str(), info.size(), text_tag, NULL);
-
+  GtkWidget* icon_align = gtk_alignment_new(0, 0, 0, 0);
+  gtk_container_add(GTK_CONTAINER(icon_align), limited_user_img);
+  gtk_box_pack_start(GTK_BOX(managed_user_info), icon_align, FALSE, FALSE, 0);
+  GtkWidget* status_label =
+      theme_service_->BuildLabel(std::string(), ui::kGdkBlack);
+  char* markup = g_markup_printf_escaped(
+      "<span size='small'>%s</span>",
+      UTF16ToUTF8(avatar_menu_model_->GetManagedUserInformation()).c_str());
+  const int kLabelWidth = 150;
+  gtk_widget_set_size_request(status_label, kLabelWidth, -1);
+  gtk_label_set_markup(GTK_LABEL(status_label), markup);
+  gtk_label_set_line_wrap(GTK_LABEL(status_label), TRUE);
+  gtk_misc_set_alignment(GTK_MISC(status_label), 0, 0);
+  g_free(markup);
+  gtk_box_pack_start(GTK_BOX(managed_user_info), status_label, FALSE, FALSE, 0);
   gtk_box_pack_start(
-      GTK_BOX(inner_contents_), managed_user_info_, FALSE, FALSE, 0);
+      GTK_BOX(inner_contents_), managed_user_info, FALSE, FALSE, 0);
+
   gtk_box_pack_start(
       GTK_BOX(inner_contents_), gtk_hseparator_new(), TRUE, TRUE, 0);
 
@@ -226,14 +204,10 @@
   g_signal_connect(switch_profile_link, "clicked",
                    G_CALLBACK(OnSwitchProfileLinkClickedThunk), this);
 
-  GtkWidget* link_align = gtk_alignment_new(0, 0, 0, 0);
-  gtk_alignment_set_padding(GTK_ALIGNMENT(link_align),
-                            0, 0, kNewProfileLinkLeftPadding, 0);
+  GtkWidget* link_align = gtk_alignment_new(0.5, 0, 0, 0);
   gtk_container_add(GTK_CONTAINER(link_align), switch_profile_link);
 
   gtk_box_pack_start(GTK_BOX(inner_contents_), link_align, FALSE, FALSE, 0);
-  g_signal_connect(
-      inner_contents_, "realize", G_CALLBACK(OnRealizeThunk), this);
 }
 
 void AvatarMenuBubbleGtk::InitContents() {
diff --git a/chrome/browser/ui/gtk/avatar_menu_bubble_gtk.h b/chrome/browser/ui/gtk/avatar_menu_bubble_gtk.h
index 3c2136b..f611f68 100644
--- a/chrome/browser/ui/gtk/avatar_menu_bubble_gtk.h
+++ b/chrome/browser/ui/gtk/avatar_menu_bubble_gtk.h
@@ -51,7 +51,6 @@
                        GtkRequisition*);
   CHROMEGTK_CALLBACK_0(AvatarMenuBubbleGtk, void, OnNewProfileLinkClicked);
   CHROMEGTK_CALLBACK_0(AvatarMenuBubbleGtk, void, OnSwitchProfileLinkClicked);
-  CHROMEGTK_CALLBACK_0(AvatarMenuBubbleGtk, void, OnRealize);
 
   // Create all widgets in this bubble.
   void InitContents();
@@ -75,10 +74,6 @@
   // widgets in the bubble.
   GtkWidget* inner_contents_;
 
-  // A weak pointer to the GtkTextView which holds general information about
-  // managed users.
-  GtkWidget* managed_user_info_;
-
   // A weak pointer to the bubble window.
   BubbleGtk* bubble_;
 
diff --git a/chrome/browser/ui/gtk/bookmarks/bookmark_bar_gtk_interactive_uitest.cc b/chrome/browser/ui/gtk/bookmarks/bookmark_bar_gtk_interactive_uitest.cc
index fe0922d..cca8aa3 100644
--- a/chrome/browser/ui/gtk/bookmarks/bookmark_bar_gtk_interactive_uitest.cc
+++ b/chrome/browser/ui/gtk/bookmarks/bookmark_bar_gtk_interactive_uitest.cc
@@ -13,11 +13,11 @@
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/interactive_test_utils.h"
 #include "chrome/test/base/ui_test_utils.h"
-#include "net/test/spawned_test_server/spawned_test_server.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
 
 namespace {
 
-const char kSimplePage[] = "404_is_enough_for_us.html";
+const char kSimplePage[] = "/404_is_enough_for_us.html";
 
 void OnClicked(GtkWidget* widget, bool* clicked_bit) {
   *clicked_bit = true;
@@ -31,14 +31,14 @@
 // Makes sure that when you switch back to an NTP with an active findbar,
 // the findbar is above the floating bookmark bar.
 IN_PROC_BROWSER_TEST_F(BookmarkBarGtkInteractiveUITest, FindBarTest) {
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   // Create new tab; open findbar.
   chrome::NewTab(browser());
   chrome::Find(browser());
 
   // Create new tab with an arbitrary URL.
-  GURL url = test_server()->GetURL(kSimplePage);
+  GURL url = embedded_test_server()->GetURL(kSimplePage);
   chrome::AddSelectedTabWithURL(browser(), url, content::PAGE_TRANSITION_TYPED);
 
   // Switch back to the NTP with the active findbar.
@@ -58,7 +58,7 @@
 // Disabled due to http://crbug.com/88933.
 IN_PROC_BROWSER_TEST_F(
     BookmarkBarGtkInteractiveUITest, DISABLED_ClickOnFloatingTest) {
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   GtkWidget* other_bookmarks =
       ViewIDUtil::GetWidget(GTK_WIDGET(browser()->window()->GetNativeWindow()),
diff --git a/chrome/browser/ui/gtk/bookmarks/bookmark_bar_gtk_unittest.cc b/chrome/browser/ui/gtk/bookmarks/bookmark_bar_gtk_unittest.cc
index debbce8..c8330ba 100644
--- a/chrome/browser/ui/gtk/bookmarks/bookmark_bar_gtk_unittest.cc
+++ b/chrome/browser/ui/gtk/bookmarks/bookmark_bar_gtk_unittest.cc
@@ -42,7 +42,7 @@
     ui_test_utils::WaitForBookmarkModelToLoad(model_);
 
     Browser::CreateParams native_params(profile_.get(),
-                                        chrome::HOST_DESKTOP_TYPE_NATIVE);
+                                        chrome::GetActiveDesktop());
     browser_.reset(
         chrome::CreateBrowserWithTestWindowForParams(&native_params));
     origin_provider_.reset(new EmptyTabstripOriginProvider);
diff --git a/chrome/browser/ui/gtk/bookmarks/bookmark_bubble_gtk.cc b/chrome/browser/ui/gtk/bookmarks/bookmark_bubble_gtk.cc
index a5592d4..7125577 100644
--- a/chrome/browser/ui/gtk/bookmarks/bookmark_bubble_gtk.cc
+++ b/chrome/browser/ui/gtk/bookmarks/bookmark_bubble_gtk.cc
@@ -13,11 +13,11 @@
 #include "base/message_loop.h"
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/bookmarks/bookmark_editor.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/browser/bookmarks/bookmark_utils.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/bookmarks/bookmark_editor.h"
 #include "chrome/browser/ui/bookmarks/recently_used_folders_combo_model.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_list.h"
diff --git a/chrome/browser/ui/gtk/bookmarks/bookmark_editor_gtk.cc b/chrome/browser/ui/gtk/bookmarks/bookmark_editor_gtk.cc
index a4e2f14..aa6030b 100644
--- a/chrome/browser/ui/gtk/bookmarks/bookmark_editor_gtk.cc
+++ b/chrome/browser/ui/gtk/bookmarks/bookmark_editor_gtk.cc
@@ -549,7 +549,7 @@
   if (!show_tree_ || !selected_parent) {
     // TODO: this is wrong. Just because there is no selection doesn't mean new
     // folders weren't added.
-    bookmark_utils::ApplyEditsWithNoFolderChange(
+    BookmarkEditor::ApplyEditsWithNoFolderChange(
         bb_model_, parent_, details_, new_title, new_url);
     return;
   }
@@ -572,7 +572,7 @@
     return;
   }
 
-  bookmark_utils::ApplyEditsWithPossibleFolderChange(
+  BookmarkEditor::ApplyEditsWithPossibleFolderChange(
       bb_model_, new_parent, details_, new_title, new_url);
 
   // Remove the folders that were removed. This has to be done after all the
diff --git a/chrome/browser/ui/gtk/bookmarks/bookmark_editor_gtk.h b/chrome/browser/ui/gtk/bookmarks/bookmark_editor_gtk.h
index 798d6ed..59e3889 100644
--- a/chrome/browser/ui/gtk/bookmarks/bookmark_editor_gtk.h
+++ b/chrome/browser/ui/gtk/bookmarks/bookmark_editor_gtk.h
@@ -10,8 +10,8 @@
 #include "base/gtest_prod_util.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/string16.h"
-#include "chrome/browser/bookmarks/bookmark_editor.h"
 #include "chrome/browser/bookmarks/bookmark_model_observer.h"
+#include "chrome/browser/ui/bookmarks/bookmark_editor.h"
 #include "ui/base/glib/glib_integers.h"
 #include "ui/base/gtk/gtk_signal.h"
 
diff --git a/chrome/browser/ui/gtk/browser_titlebar.cc b/chrome/browser/ui/gtk/browser_titlebar.cc
index b81f6eb..0780f19 100644
--- a/chrome/browser/ui/gtk/browser_titlebar.cc
+++ b/chrome/browser/ui/gtk/browser_titlebar.cc
@@ -784,7 +784,7 @@
     gtk_widget_modify_bg(
         GTK_WIDGET(avatar_label_bg_), GTK_STATE_NORMAL, &label_background);
     char* markup = g_markup_printf_escaped(
-        "<span size='small' weight='bold'>%s</span>",
+        "<span size='small'>%s</span>",
         l10n_util::GetStringUTF8(IDS_MANAGED_USER_AVATAR_LABEL).c_str());
     gtk_label_set_markup(GTK_LABEL(avatar_label_), markup);
     g_free(markup);
@@ -820,7 +820,7 @@
   Profile* profile = browser_window_->browser()->profile();
   if (ManagedUserService::ProfileIsManaged(profile)) {
     avatar_label_ = gtk_label_new(NULL);
-    gtk_misc_set_padding(GTK_MISC(avatar_label_), 2, 2);
+    gtk_misc_set_padding(GTK_MISC(avatar_label_), 10, 2);
     avatar_label_bg_ = gtk_event_box_new();
     gtk_container_add(GTK_CONTAINER(avatar_label_bg_), avatar_label_);
     g_signal_connect(avatar_label_bg_, "button-press-event",
diff --git a/chrome/browser/ui/gtk/browser_window_gtk.cc b/chrome/browser/ui/gtk/browser_window_gtk.cc
index f343c44..d3ab2c8 100644
--- a/chrome/browser/ui/gtk/browser_window_gtk.cc
+++ b/chrome/browser/ui/gtk/browser_window_gtk.cc
@@ -24,7 +24,7 @@
 #include "base/prefs/pref_service.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/download/download_item_model.h"
@@ -1443,15 +1443,21 @@
   if (!browser_->ShouldCloseWindow())
     return false;
 
+  bool fast_tab_closing_enabled =
+      CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableFastUnload);
+
   if (!browser_->tab_strip_model()->empty()) {
     // Tab strip isn't empty.  Hide the window (so it appears to have closed
     // immediately) and close all the tabs, allowing the renderers to shut
     // down. When the tab strip is empty we'll be called back again.
     gtk_widget_hide(GTK_WIDGET(window_));
     browser_->OnWindowClosing();
-    browser_->tab_strip_model()->CloseAllTabs();
+
+    if (fast_tab_closing_enabled)
+      browser_->tab_strip_model()->CloseAllTabs();
     return false;
-  } else if (!browser_->HasCompletedUnloadProcessing()) {
+  } else if (fast_tab_closing_enabled &&
+      !browser_->HasCompletedUnloadProcessing()) {
     // The browser needs to finish running unload handlers.
     // Hide the window (so it appears to have closed immediately), and
     // the browser will call us back again when it is ready to close.
diff --git a/chrome/browser/ui/gtk/browser_window_gtk.h b/chrome/browser/ui/gtk/browser_window_gtk.h
index 4cd6ad6..40f763f 100644
--- a/chrome/browser/ui/gtk/browser_window_gtk.h
+++ b/chrome/browser/ui/gtk/browser_window_gtk.h
@@ -13,7 +13,7 @@
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/prefs/pref_member.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "build/build_config.h"
 #include "chrome/browser/devtools/devtools_window.h"
 #include "chrome/browser/extensions/extension_keybinding_registry.h"
diff --git a/chrome/browser/ui/gtk/bubble/bubble_gtk.cc b/chrome/browser/ui/gtk/bubble/bubble_gtk.cc
index f8c2064..0b023b0 100644
--- a/chrome/browser/ui/gtk/bubble/bubble_gtk.cc
+++ b/chrome/browser/ui/gtk/bubble/bubble_gtk.cc
@@ -539,6 +539,7 @@
 }
 
 void BubbleGtk::StopGrabbingInput() {
+  UngrabPointerAndKeyboard();
   if (!grab_input_)
     return;
   grab_input_ = false;
@@ -598,6 +599,12 @@
   }
 }
 
+void BubbleGtk::UngrabPointerAndKeyboard() {
+  gdk_pointer_ungrab(GDK_CURRENT_TIME);
+  if (grab_input_)
+    gdk_keyboard_ungrab(GDK_CURRENT_TIME);
+}
+
 gboolean BubbleGtk::OnGtkAccelerator(GtkAccelGroup* group,
                                      GObject* acceleratable,
                                      guint keyval,
diff --git a/chrome/browser/ui/gtk/bubble/bubble_gtk.h b/chrome/browser/ui/gtk/bubble/bubble_gtk.h
index 111654d..f800278 100644
--- a/chrome/browser/ui/gtk/bubble/bubble_gtk.h
+++ b/chrome/browser/ui/gtk/bubble/bubble_gtk.h
@@ -172,6 +172,11 @@
   // sure that we have the input focus.
   void GrabPointerAndKeyboard();
 
+  // Ungrab (in the X sense) the pointer and keyboard.  This is needed to make
+  // sure that we release the input focus, e.g. when an extension popup
+  // is inspected by the DevTools.
+  void UngrabPointerAndKeyboard();
+
   CHROMEG_CALLBACK_3(BubbleGtk, gboolean, OnGtkAccelerator, GtkAccelGroup*,
                      GObject*, guint, GdkModifierType);
 
diff --git a/chrome/browser/ui/gtk/certificate_viewer_gtk.cc b/chrome/browser/ui/gtk/certificate_viewer_gtk.cc
index b76b660..f0b8672 100644
--- a/chrome/browser/ui/gtk/certificate_viewer_gtk.cc
+++ b/chrome/browser/ui/gtk/certificate_viewer_gtk.cc
@@ -12,7 +12,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/certificate_viewer.h"
 #include "chrome/browser/ui/certificate_dialogs.h"
 #include "chrome/browser/ui/gtk/gtk_util.h"
diff --git a/chrome/browser/ui/gtk/create_application_shortcuts_dialog_gtk.cc b/chrome/browser/ui/gtk/create_application_shortcuts_dialog_gtk.cc
index d8fdd0f..48eb200 100644
--- a/chrome/browser/ui/gtk/create_application_shortcuts_dialog_gtk.cc
+++ b/chrome/browser/ui/gtk/create_application_shortcuts_dialog_gtk.cc
@@ -347,7 +347,9 @@
     const ShellIntegration::ShortcutLocations& creation_locations) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
 
-  if (web_app::CreateShortcutsOnFileThread(shortcut_info, creation_locations)) {
+  if (web_app::CreateShortcutsOnFileThread(
+          shortcut_info, creation_locations,
+          web_app::ALLOW_DUPLICATE_SHORTCUTS)) {
     Release();
   } else {
     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
diff --git a/chrome/browser/ui/gtk/download/download_item_gtk.cc b/chrome/browser/ui/gtk/download/download_item_gtk.cc
index 7577367..860f011 100644
--- a/chrome/browser/ui/gtk/download/download_item_gtk.cc
+++ b/chrome/browser/ui/gtk/download/download_item_gtk.cc
@@ -10,7 +10,7 @@
 #include "base/metrics/histogram.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/download/chrome_download_manager_delegate.h"
 #include "chrome/browser/download/download_item_model.h"
diff --git a/chrome/browser/ui/gtk/download/download_item_gtk.h b/chrome/browser/ui/gtk/download/download_item_gtk.h
index c71905d..e71d325 100644
--- a/chrome/browser/ui/gtk/download/download_item_gtk.h
+++ b/chrome/browser/ui/gtk/download/download_item_gtk.h
@@ -12,8 +12,8 @@
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/download/download_item_model.h"
 #include "chrome/browser/icon_manager.h"
 #include "chrome/common/cancelable_task_tracker.h"
diff --git a/chrome/browser/ui/gtk/extensions/media_galleries_dialog_gtk.cc b/chrome/browser/ui/gtk/extensions/media_galleries_dialog_gtk.cc
index ef81871..aaf3130 100644
--- a/chrome/browser/ui/gtk/extensions/media_galleries_dialog_gtk.cc
+++ b/chrome/browser/ui/gtk/extensions/media_galleries_dialog_gtk.cc
@@ -127,19 +127,15 @@
                              checkbox_container);
   }
 
-  // Holds the "add gallery" and cancel/confirm buttons.
-  GtkWidget* add_folder_area = gtk_hbox_new(FALSE, ui::kControlSpacing);
-  gtk_box_pack_start(GTK_BOX(contents_.get()), add_folder_area,
-                     FALSE, FALSE, 0);
+  GtkWidget* bottom_area = gtk_hbox_new(FALSE, ui::kControlSpacing);
 
   // Add gallery button.
   GtkWidget* add_folder = gtk_button_new_with_label(
       l10n_util::GetStringUTF8(IDS_MEDIA_GALLERIES_DIALOG_ADD_GALLERY).c_str());
   g_signal_connect(add_folder, "clicked", G_CALLBACK(OnAddFolderThunk), this);
-  gtk_box_pack_start(GTK_BOX(add_folder_area), add_folder, FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(bottom_area), add_folder, FALSE, FALSE, 0);
 
   // Confirm/cancel button.
-  GtkWidget* bottom_area = gtk_hbox_new(FALSE, ui::kControlSpacing);
   confirm_ = gtk_button_new_with_label(l10n_util::GetStringUTF8(
       IDS_MEDIA_GALLERIES_DIALOG_CONFIRM).c_str());
   gtk_button_set_image(
@@ -180,8 +176,7 @@
   g_signal_connect(widget, "toggled", G_CALLBACK(OnToggledThunk), this);
   gtk_box_pack_start(GTK_BOX(checkbox_container), hbox, FALSE, FALSE, 0);
   gtk_box_pack_start(GTK_BOX(hbox), widget, FALSE, FALSE, 0);
-  std::string details = UTF16ToUTF8(
-      MediaGalleriesDialogController::GetGalleryAdditionalDetails(gallery));
+  std::string details = UTF16ToUTF8(gallery.GetGalleryAdditionalDetails());
   GtkWidget* details_label = gtk_label_new(details.c_str());
   gtk_label_set_line_wrap(GTK_LABEL(details_label), FALSE);
   gtk_util::SetLabelColor(details_label, &kDeemphasizedTextColor);
@@ -190,14 +185,11 @@
   gtk_widget_show(hbox);
   checkbox_map_[gallery.pref_id] = widget;
 
-  std::string tooltip_text = UTF16ToUTF8(
-      MediaGalleriesDialogController::GetGalleryTooltip(gallery));
+  std::string tooltip_text = UTF16ToUTF8(gallery.GetGalleryTooltip());
   gtk_widget_set_tooltip_text(widget, tooltip_text.c_str());
 
   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), permitted);
-  std::string label = UTF16ToUTF8(
-      MediaGalleriesDialogController::GetGalleryDisplayNameNoAttachment(
-          gallery));
+  std::string label = UTF16ToUTF8(gallery.GetGalleryDisplayName());
   gtk_button_set_label(GTK_BUTTON(widget), label.c_str());
 }
 
diff --git a/chrome/browser/ui/gtk/extensions/native_app_window_gtk.cc b/chrome/browser/ui/gtk/extensions/native_app_window_gtk.cc
index b715652..76e5b04 100644
--- a/chrome/browser/ui/gtk/extensions/native_app_window_gtk.cc
+++ b/chrome/browser/ui/gtk/extensions/native_app_window_gtk.cc
@@ -20,6 +20,8 @@
 #include "ui/gfx/image/image.h"
 #include "ui/gfx/rect.h"
 
+using apps::ShellWindow;
+
 namespace {
 
 // The timeout in milliseconds before we'll get the true window position with
diff --git a/chrome/browser/ui/gtk/extensions/native_app_window_gtk.h b/chrome/browser/ui/gtk/extensions/native_app_window_gtk.h
index e01f9bd..c1c018e 100644
--- a/chrome/browser/ui/gtk/extensions/native_app_window_gtk.h
+++ b/chrome/browser/ui/gtk/extensions/native_app_window_gtk.h
@@ -7,10 +7,10 @@
 
 #include <gtk/gtk.h>
 
+#include "apps/shell_window.h"
 #include "base/observer_list.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/ui/extensions/native_app_window.h"
-#include "chrome/browser/ui/extensions/shell_window.h"
 #include "chrome/browser/ui/gtk/extensions/extension_view_gtk.h"
 #include "third_party/skia/include/core/SkRegion.h"
 #include "ui/base/gtk/gtk_signal.h"
@@ -28,8 +28,8 @@
                            public ExtensionViewGtk::Container,
                            public ui::ActiveWindowWatcherXObserver {
  public:
-  NativeAppWindowGtk(ShellWindow* shell_window,
-                     const ShellWindow::CreateParams& params);
+  NativeAppWindowGtk(apps::ShellWindow* shell_window,
+                     const apps::ShellWindow::CreateParams& params);
 
   // ui::BaseWindow implementation.
   virtual bool IsActive() const OVERRIDE;
@@ -105,7 +105,7 @@
 
   void OnDebouncedBoundsChanged();
 
-  ShellWindow* shell_window_;  // weak - ShellWindow owns NativeAppWindow.
+  apps::ShellWindow* shell_window_;  // weak - ShellWindow owns NativeAppWindow.
 
   GtkWindow* window_;
   GdkWindowState state_;
diff --git a/chrome/browser/ui/gtk/gtk_theme_service.cc b/chrome/browser/ui/gtk/gtk_theme_service.cc
index 5ab6203..143ddcb 100644
--- a/chrome/browser/ui/gtk/gtk_theme_service.cc
+++ b/chrome/browser/ui/gtk/gtk_theme_service.cc
@@ -15,6 +15,7 @@
 #include "base/nix/xdg_util.h"
 #include "base/prefs/pref_service.h"
 #include "base/stl_util.h"
+#include "chrome/browser/managed_mode/managed_user_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/themes/theme_properties.h"
 #include "chrome/browser/themes/theme_service_factory.h"
@@ -308,6 +309,14 @@
 }
 
 gfx::Image GtkThemeService::GetImageNamed(int id) const {
+  // TODO(akuegel): Remove this once we have the default managed user theme.
+  if (ManagedUserService::ProfileIsManaged(profile())) {
+    if (id == IDR_THEME_FRAME)
+      id = IDR_MANAGED_USER_THEME_FRAME;
+    else if (id == IDR_THEME_FRAME_INACTIVE)
+      id = IDR_MANAGED_USER_THEME_FRAME_INACTIVE;
+  }
+
   // Try to get our cached version:
   ImageCache::const_iterator it = gtk_images_.find(id);
   if (it != gtk_images_.end())
@@ -324,6 +333,14 @@
 }
 
 SkColor GtkThemeService::GetColor(int id) const {
+  // TODO(akuegel): Remove this once we have the default managed user theme.
+  if (ManagedUserService::ProfileIsManaged(profile())) {
+    if (id == ThemeProperties::COLOR_FRAME)
+      id = ThemeProperties::COLOR_FRAME_MANAGED_USER;
+    else if (id == ThemeProperties::COLOR_FRAME_INACTIVE)
+      id = ThemeProperties::COLOR_FRAME_MANAGED_USER_INACTIVE;
+  }
+
   if (use_gtk_) {
     ColorMap::const_iterator it = colors_.find(id);
     if (it != colors_.end())
diff --git a/chrome/browser/ui/gtk/gtk_util.cc b/chrome/browser/ui/gtk/gtk_util.cc
index 0e5a902..df8a277 100644
--- a/chrome/browser/ui/gtk/gtk_util.cc
+++ b/chrome/browser/ui/gtk/gtk_util.cc
@@ -804,18 +804,18 @@
     return false;
 
   GdkWindow* gdk_window = gtk_widget_get_window(widget);
-  if (!gdk_pointer_grab(gdk_window,
-                        TRUE,
-                        GdkEventMask(GDK_BUTTON_PRESS_MASK |
-                                     GDK_BUTTON_RELEASE_MASK |
-                                     GDK_ENTER_NOTIFY_MASK |
-                                     GDK_LEAVE_NOTIFY_MASK |
-                                     GDK_POINTER_MOTION_MASK),
-                        NULL, NULL, time) == 0) {
+  if (gdk_pointer_grab(gdk_window,
+                       TRUE,
+                       GdkEventMask(GDK_BUTTON_PRESS_MASK |
+                                    GDK_BUTTON_RELEASE_MASK |
+                                    GDK_ENTER_NOTIFY_MASK |
+                                    GDK_LEAVE_NOTIFY_MASK |
+                                    GDK_POINTER_MOTION_MASK),
+                       NULL, NULL, time) != 0) {
     return false;
   }
 
-  if (!gdk_keyboard_grab(gdk_window, TRUE, time) == 0) {
+  if (gdk_keyboard_grab(gdk_window, TRUE, time) != 0) {
     gdk_display_pointer_ungrab(gdk_drawable_get_display(gdk_window), time);
     return false;
   }
diff --git a/chrome/browser/ui/gtk/omnibox/omnibox_view_gtk.cc b/chrome/browser/ui/gtk/omnibox/omnibox_view_gtk.cc
index 9e99690..a824049 100644
--- a/chrome/browser/ui/gtk/omnibox/omnibox_view_gtk.cc
+++ b/chrome/browser/ui/gtk/omnibox/omnibox_view_gtk.cc
@@ -1238,7 +1238,7 @@
   g_free(text);
 
   // Copy URL menu item.
-  if (chrome::IsQueryExtractionEnabled(browser_->profile())) {
+  if (chrome::IsQueryExtractionEnabled()) {
     GtkWidget* copy_url_menuitem = gtk_menu_item_new_with_mnemonic(
         ui::ConvertAcceleratorsFromWindowsStyle(
             l10n_util::GetStringUTF8(IDS_COPY_URL)).c_str());
diff --git a/chrome/browser/ui/gtk/panels/panel_gtk.cc b/chrome/browser/ui/gtk/panels/panel_gtk.cc
index 4361cf9..26ae46d 100644
--- a/chrome/browser/ui/gtk/panels/panel_gtk.cc
+++ b/chrome/browser/ui/gtk/panels/panel_gtk.cc
@@ -195,7 +195,7 @@
   frame_size.SetSize(new_size.width(), new_size.height());
 }
 
-}
+}  // namespace
 
 // static
 NativePanel* Panel::CreateNativePanel(Panel* panel,
@@ -608,7 +608,30 @@
   if (event->type != GDK_BUTTON_PRESS)
     return TRUE;
 
-  gdk_window_raise(gtk_widget_get_window(GTK_WIDGET(window_)));
+  // If the panel is in a stack, bring all other panels in the stack to the
+  // top.
+  StackedPanelCollection* stack = panel_->stack();
+  if (stack) {
+    for (StackedPanelCollection::Panels::const_iterator iter =
+             stack->panels().begin();
+         iter != stack->panels().end(); ++iter) {
+      Panel* panel = *iter;
+      GtkWindow* gtk_window = panel->GetNativeWindow();
+      // If a panel is collapsed, we make it not to take focus. For such window,
+      // it cannot be brought to the top by calling gdk_window_raise. To work
+      // around this issue, we make it always-on-top first and then put it back
+      // to normal. Note that this trick has been done for all panels in the
+      // stack, regardless of whether it is collapsed or not.
+      // There is one side-effect to this approach: if the panel being pressed
+      // on is collapsed, clicking on the client area of the last active
+      // window will not raise it above these panels.
+      gtk_window_set_keep_above(gtk_window, true);
+      gtk_window_set_keep_above(gtk_window, false);
+    }
+  } else {
+    gdk_window_raise(gtk_widget_get_window(GTK_WIDGET(window_)));
+  }
+
   EnsureDragHelperCreated();
   drag_helper_->InitialTitlebarMousePress(event, titlebar_->widget());
   return TRUE;
diff --git a/chrome/browser/ui/gtk/panels/panel_gtk.h b/chrome/browser/ui/gtk/panels/panel_gtk.h
index 8b76023..e3b35e6 100644
--- a/chrome/browser/ui/gtk/panels/panel_gtk.h
+++ b/chrome/browser/ui/gtk/panels/panel_gtk.h
@@ -10,7 +10,7 @@
 
 #include "base/basictypes.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/ui/panels/native_panel.h"
 #include "chrome/browser/ui/panels/panel_constants.h"
 #include "ui/base/gtk/gtk_signal.h"
diff --git a/chrome/browser/ui/gtk/panels/panel_stack_window_gtk.cc b/chrome/browser/ui/gtk/panels/panel_stack_window_gtk.cc
index 395a9af..dfdde74 100644
--- a/chrome/browser/ui/gtk/panels/panel_stack_window_gtk.cc
+++ b/chrome/browser/ui/gtk/panels/panel_stack_window_gtk.cc
@@ -220,6 +220,7 @@
   window_ = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
   gtk_window_set_decorated(window_, false);
   gtk_window_set_resizable(window_, false);
+  gtk_window_set_focus_on_map(window_, false);
   gtk_widget_show(GTK_WIDGET(window_));
   gdk_window_move_resize(gtk_widget_get_window(GTK_WIDGET(window_)),
       panel->GetBounds().x(), panel->GetBounds().y(), 1, 1);
diff --git a/chrome/browser/ui/gtk/password_generation_bubble_gtk.cc b/chrome/browser/ui/gtk/password_generation_bubble_gtk.cc
index 70be410..5086b87 100644
--- a/chrome/browser/ui/gtk/password_generation_bubble_gtk.cc
+++ b/chrome/browser/ui/gtk/password_generation_bubble_gtk.cc
@@ -14,7 +14,7 @@
 #include "chrome/browser/ui/gtk/gtk_theme_service.h"
 #include "chrome/browser/ui/gtk/gtk_util.h"
 #include "chrome/common/url_constants.h"
-#include "components/autofill/browser/password_generator.h"
+#include "components/autofill/core/browser/password_generator.h"
 #include "components/autofill/core/common/autofill_messages.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
diff --git a/chrome/browser/ui/gtk/protocol_dialog_gtk.h b/chrome/browser/ui/gtk/protocol_dialog_gtk.h
index 9ee746f..0685b3e 100644
--- a/chrome/browser/ui/gtk/protocol_dialog_gtk.h
+++ b/chrome/browser/ui/gtk/protocol_dialog_gtk.h
@@ -7,7 +7,7 @@
 
 #include "base/basictypes.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/ui/protocol_dialog_delegate.h"
 #include "googleurl/src/gurl.h"
 #include "ui/base/gtk/gtk_signal.h"
diff --git a/chrome/browser/ui/gtk/reload_button_gtk.h b/chrome/browser/ui/gtk/reload_button_gtk.h
index 7527c37..8d30745 100644
--- a/chrome/browser/ui/gtk/reload_button_gtk.h
+++ b/chrome/browser/ui/gtk/reload_button_gtk.h
@@ -9,14 +9,14 @@
 
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/ui/gtk/custom_button.h"
 #include "chrome/browser/ui/gtk/menu_gtk.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
-#include "ui/base/models/simple_menu_model.h"
 #include "ui/base/gtk/gtk_signal.h"
 #include "ui/base/gtk/owned_widget_gtk.h"
+#include "ui/base/models/simple_menu_model.h"
 
 class Browser;
 class GtkThemeService;
diff --git a/chrome/browser/ui/gtk/status_bubble_gtk.h b/chrome/browser/ui/gtk/status_bubble_gtk.h
index 8cc71a6..dbc2b5b 100644
--- a/chrome/browser/ui/gtk/status_bubble_gtk.h
+++ b/chrome/browser/ui/gtk/status_bubble_gtk.h
@@ -11,7 +11,7 @@
 
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/ui/status_bubble.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
diff --git a/chrome/browser/ui/gtk/tab_contents/chrome_web_contents_view_delegate_gtk.cc b/chrome/browser/ui/gtk/tab_contents/chrome_web_contents_view_delegate_gtk.cc
index 26d5f50..45a32e0 100644
--- a/chrome/browser/ui/gtk/tab_contents/chrome_web_contents_view_delegate_gtk.cc
+++ b/chrome/browser/ui/gtk/tab_contents/chrome_web_contents_view_delegate_gtk.cc
@@ -136,9 +136,9 @@
   content::RenderWidgetHostView* view = NULL;
   if (params.custom_context.render_widget_id !=
       content::CustomContextMenuContext::kCurrentRenderWidget) {
-    content::RenderWidgetHost* host =
-        web_contents_->GetRenderProcessHost()->GetRenderWidgetHostByID(
-            params.custom_context.render_widget_id);
+    content::RenderWidgetHost* host = content::RenderWidgetHost::FromID(
+        web_contents_->GetRenderProcessHost()->GetID(),
+        params.custom_context.render_widget_id);
     if (!host) {
       NOTREACHED();
       return;
diff --git a/chrome/browser/ui/gtk/tab_modal_confirm_dialog_gtk.cc b/chrome/browser/ui/gtk/tab_modal_confirm_dialog_gtk.cc
index ff4b261..f96d8a6 100644
--- a/chrome/browser/ui/gtk/tab_modal_confirm_dialog_gtk.cc
+++ b/chrome/browser/ui/gtk/tab_modal_confirm_dialog_gtk.cc
@@ -6,7 +6,12 @@
 
 #include "base/message_loop.h"
 #include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_dialogs.h"
+#include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/gtk/event_utils.h"
+#include "chrome/browser/ui/gtk/gtk_theme_service.h"
 #include "chrome/browser/ui/tab_modal_confirm_dialog_delegate.h"
 #include "components/web_modal/web_contents_modal_dialog_manager.h"
 #include "content/public/browser/notification_types.h"
@@ -37,6 +42,7 @@
                                                      GTK_ICON_SIZE_DIALOG);
   gtk_misc_set_alignment(GTK_MISC(image), 0.5, 0.0);
 
+  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
   gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
   gtk_label_set_selectable(GTK_LABEL(label), TRUE);
 
@@ -44,8 +50,26 @@
 
   gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0);
 
-  gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
+  GtkWidget* vbox = gtk_vbox_new(FALSE, ui::kContentAreaSpacing);
 
+  gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
+
+  string16 link_text = delegate->GetLinkText();
+  if (!link_text.empty()) {
+    Browser* browser = chrome::FindBrowserWithWebContents(web_contents);
+    GtkThemeService* theme_service = GtkThemeService::GetFrom(
+        browser->profile());
+
+    GtkWidget* link = theme_service->BuildChromeLinkButton(UTF16ToUTF8(
+        link_text.c_str()));
+    g_signal_connect(link, "clicked", G_CALLBACK(OnLinkClickedThunk), this);
+    GtkWidget* link_align = gtk_alignment_new(0, 0, 0, 0);
+    gtk_container_add(GTK_CONTAINER(link_align), link);
+
+    gtk_box_pack_end(GTK_BOX(vbox), link_align, FALSE, FALSE, 0);
+  }
+
+  gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
   gtk_box_pack_start(GTK_BOX(dialog_), hbox, FALSE, FALSE, 0);
 
   GtkWidget* buttonBox = gtk_hbutton_box_new();
@@ -107,6 +131,10 @@
   delegate_->Cancel();
 }
 
+void TabModalConfirmDialogGtk::OnLinkClicked(GtkWidget* widget) {
+  delegate_->LinkClicked(event_utils::DispositionForCurrentButtonPressEvent());
+}
+
 void TabModalConfirmDialogGtk::OnDestroy(GtkWidget* widget) {
   delete this;
 }
diff --git a/chrome/browser/ui/gtk/tab_modal_confirm_dialog_gtk.h b/chrome/browser/ui/gtk/tab_modal_confirm_dialog_gtk.h
index 543d148..8c7104a 100644
--- a/chrome/browser/ui/gtk/tab_modal_confirm_dialog_gtk.h
+++ b/chrome/browser/ui/gtk/tab_modal_confirm_dialog_gtk.h
@@ -45,6 +45,7 @@
   CHROMEGTK_CALLBACK_0(TabModalConfirmDialogGtk, void, OnAccept);
   CHROMEGTK_CALLBACK_0(TabModalConfirmDialogGtk, void, OnCancel);
   CHROMEGTK_CALLBACK_0(TabModalConfirmDialogGtk, void, OnDestroy);
+  CHROMEGTK_CALLBACK_0(TabModalConfirmDialogGtk, void, OnLinkClicked);
 
   scoped_ptr<TabModalConfirmDialogDelegate> delegate_;
 
diff --git a/chrome/browser/ui/gtk/tabs/dragged_tab_controller_gtk.h b/chrome/browser/ui/gtk/tabs/dragged_tab_controller_gtk.h
index 4e757c6..ad780c3 100644
--- a/chrome/browser/ui/gtk/tabs/dragged_tab_controller_gtk.h
+++ b/chrome/browser/ui/gtk/tabs/dragged_tab_controller_gtk.h
@@ -13,7 +13,7 @@
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/ui/gtk/tabs/drag_data.h"
 #include "chrome/browser/ui/tabs/dock_info.h"
 #include "content/public/browser/notification_observer.h"
diff --git a/chrome/browser/ui/gtk/task_manager_gtk.cc b/chrome/browser/ui/gtk/task_manager_gtk.cc
index c765e3e..32cb85c 100644
--- a/chrome/browser/ui/gtk/task_manager_gtk.cc
+++ b/chrome/browser/ui/gtk/task_manager_gtk.cc
@@ -71,16 +71,12 @@
   kTaskManagerFPS,
   kTaskManagerSqliteMemoryUsed,
   kTaskManagerGoatsTeleported,
-  // Columns below this point are not visible in the task manager.
-  kTaskManagerBackgroundColor,
   kTaskManagerColumnCount,
 };
 
 const TaskManagerColumn kTaskManagerLastVisibleColumn =
     kTaskManagerGoatsTeleported;
 
-static const GdkColor kHighlightColor = GDK_COLOR_RGB(0xff, 0xfa, 0xcd);
-
 TaskManagerColumn TaskManagerResourceIDToColumnID(int id) {
   switch (id) {
     case IDS_TASK_MANAGER_TASK_COLUMN:
@@ -194,15 +190,9 @@
   gtk_tree_view_column_pack_start(column, image_renderer, FALSE);
   gtk_tree_view_column_add_attribute(column, image_renderer,
                                      "pixbuf", kTaskManagerIcon);
-  gtk_tree_view_column_add_attribute(column, image_renderer,
-                                     "cell-background-gdk",
-                                     kTaskManagerBackgroundColor);
   GtkCellRenderer* text_renderer = gtk_cell_renderer_text_new();
   gtk_tree_view_column_pack_start(column, text_renderer, TRUE);
   gtk_tree_view_column_add_attribute(column, text_renderer, "markup", colid);
-  gtk_tree_view_column_add_attribute(column, text_renderer,
-                                     "cell-background-gdk",
-                                     kTaskManagerBackgroundColor);
   gtk_tree_view_column_set_resizable(column, TRUE);
   // This is temporary: we'll turn expanding off after getting the size.
   gtk_tree_view_column_set_expand(column, TRUE);
@@ -218,7 +208,6 @@
       GTK_TREE_VIEW(treeview), -1,
       name, renderer,
       "text", colid,
-      "cell-background-gdk", kTaskManagerBackgroundColor,
       NULL);
   GtkTreeViewColumn* column = gtk_tree_view_get_column(
       GTK_TREE_VIEW(treeview), TreeViewColumnIndexFromID(colid));
@@ -315,15 +304,14 @@
   DISALLOW_COPY_AND_ASSIGN(ContextMenuController);
 };
 
-TaskManagerGtk::TaskManagerGtk(bool highlight_background_resources)
+TaskManagerGtk::TaskManagerGtk()
   : task_manager_(TaskManager::GetInstance()),
     model_(TaskManager::GetInstance()->model()),
     dialog_(NULL),
     treeview_(NULL),
     process_list_(NULL),
     process_count_(0),
-    ignore_selection_changed_(false),
-    highlight_background_resources_(highlight_background_resources) {
+    ignore_selection_changed_(false) {
   Init();
 }
 
@@ -427,19 +415,12 @@
 }
 
 // static
-void TaskManagerGtk::Show(bool highlight_background_resources) {
-  if (instance_ &&
-      instance_->highlight_background_resources_ !=
-          highlight_background_resources) {
-    instance_->Close();
-    DCHECK(!instance_);
-  }
-
+void TaskManagerGtk::Show() {
   if (instance_) {
     // If there's a Task manager window open already, just activate it.
     gtk_util::PresentWindow(instance_->dialog_, 0);
   } else {
-    instance_ = new TaskManagerGtk(highlight_background_resources);
+    instance_ = new TaskManagerGtk();
     instance_->model_->StartUpdating();
   }
 }
@@ -584,7 +565,7 @@
       GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
       G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
       G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
-      G_TYPE_STRING, G_TYPE_STRING, GDK_TYPE_COLOR);
+      G_TYPE_STRING, G_TYPE_STRING);
 
   // Support sorting on all columns.
   process_list_sort_ = gtk_tree_model_sort_new_with_model(
@@ -736,8 +717,6 @@
   std::string goats =
       GetModelText(row, IDS_TASK_MANAGER_GOATS_TELEPORTED_COLUMN);
 
-  bool is_background = model_->IsBackgroundResource(row) &&
-      highlight_background_resources_;
   gtk_list_store_set(process_list_, iter,
                      kTaskManagerIcon, icon,
                      kTaskManagerTask, task_markup,
@@ -755,8 +734,6 @@
                      kTaskManagerFPS, fps.c_str(),
                      kTaskManagerSqliteMemoryUsed, sqlite_memory.c_str(),
                      kTaskManagerGoatsTeleported, goats.c_str(),
-                     kTaskManagerBackgroundColor,
-                     is_background ? &kHighlightColor : NULL,
                      -1);
   g_object_unref(icon);
   g_free(task_markup);
@@ -969,8 +946,8 @@
 namespace chrome {
 
 // Declared in browser_dialogs.h.
-void ShowTaskManager(Browser* browser, bool highlight_background_resources) {
-  TaskManagerGtk::Show(highlight_background_resources);
+void ShowTaskManager(Browser* browser) {
+  TaskManagerGtk::Show();
 }
 
 }  // namespace chrome
diff --git a/chrome/browser/ui/gtk/task_manager_gtk.h b/chrome/browser/ui/gtk/task_manager_gtk.h
index 7df063d..cce76f9 100644
--- a/chrome/browser/ui/gtk/task_manager_gtk.h
+++ b/chrome/browser/ui/gtk/task_manager_gtk.h
@@ -21,7 +21,7 @@
 
 class TaskManagerGtk : public TaskManagerModelObserver {
  public:
-  explicit TaskManagerGtk(bool highlight_background_resources);
+  TaskManagerGtk();
   virtual ~TaskManagerGtk();
 
   // TaskManagerModelObserver
@@ -34,10 +34,8 @@
   void Close();
 
   // Creates the task manager if it doesn't exist; otherwise, it activates the
-  // existing task manager window. If |highlight_background_resources| is true,
-  // background resources are rendered with a yellow highlight (for the
-  // "View Background Pages" menu item).
-  static void Show(bool highlight_background_resources);
+  // existing task manager window.
+  static void Show();
 
  private:
   class ContextMenuController;
@@ -249,9 +247,6 @@
   // ourselves caused.
   bool ignore_selection_changed_;
 
-  // If true, background resources are rendered with a yellow highlight.
-  bool highlight_background_resources_;
-
   DISALLOW_COPY_AND_ASSIGN(TaskManagerGtk);
 };
 
diff --git a/chrome/browser/ui/gtk/zoom_bubble_gtk.h b/chrome/browser/ui/gtk/zoom_bubble_gtk.h
index 4a6b470..355109f 100644
--- a/chrome/browser/ui/gtk/zoom_bubble_gtk.h
+++ b/chrome/browser/ui/gtk/zoom_bubble_gtk.h
@@ -8,7 +8,7 @@
 #include <gtk/gtk.h>
 
 #include "base/basictypes.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/ui/gtk/bubble/bubble_gtk.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
diff --git a/chrome/browser/ui/host_desktop.h b/chrome/browser/ui/host_desktop.h
index 1349da5..9728454 100644
--- a/chrome/browser/ui/host_desktop.h
+++ b/chrome/browser/ui/host_desktop.h
@@ -12,8 +12,9 @@
 namespace chrome {
 
 // A value that specifies what desktop environment hosts a particular piece of
-// UI. Please take a look at the following document for details on choosing the
-// right HostDesktopType:
+// UI. You should almost never manually hardcode one of these enums manually,
+// please refer to the following document for details on getting the right
+// HostDesktopType:
 // http://sites.google.com/a/chromium.org/dev/developers/design-documents/aura/multi-desktop
 enum HostDesktopType {
   HOST_DESKTOP_TYPE_FIRST = 0,
@@ -37,6 +38,9 @@
 
 // Returns the type of host desktop most likely to be in use.  This is the one
 // most recently activated by the user.
+// You should almost never use this outside of tests, please refer to the
+// following document for details on getting the right HostDesktopType:
+// http://sites.google.com/a/chromium.org/dev/developers/design-documents/aura/multi-desktop
 HostDesktopType GetActiveDesktop();
 
 }  // namespace chrome
diff --git a/chrome/browser/ui/hung_plugin_tab_helper.h b/chrome/browser/ui/hung_plugin_tab_helper.h
index 52dbfc2..4457797 100644
--- a/chrome/browser/ui/hung_plugin_tab_helper.h
+++ b/chrome/browser/ui/hung_plugin_tab_helper.h
@@ -9,8 +9,8 @@
 
 #include "base/memory/linked_ptr.h"
 #include "base/strings/string16.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "content/public/browser/web_contents_observer.h"
diff --git a/chrome/browser/ui/libgtk2ui/gtk2_ui.cc b/chrome/browser/ui/libgtk2ui/gtk2_ui.cc
index 195460a..c249cc6 100644
--- a/chrome/browser/ui/libgtk2ui/gtk2_ui.cc
+++ b/chrome/browser/ui/libgtk2ui/gtk2_ui.cc
@@ -7,6 +7,7 @@
 #include <set>
 
 #include "base/command_line.h"
+#include "base/environment.h"
 #include "base/i18n/rtl.h"
 #include "base/logging.h"
 #include "base/nix/mime_util_xdg.h"
@@ -17,6 +18,7 @@
 #include "chrome/browser/ui/libgtk2ui/native_theme_gtk2.h"
 #include "chrome/browser/ui/libgtk2ui/select_file_dialog_impl.h"
 #include "chrome/browser/ui/libgtk2ui/skia_utils_gtk2.h"
+#include "chrome/browser/ui/libgtk2ui/unity_service.h"
 #include "grit/theme_resources.h"
 #include "grit/ui_resources.h"
 #include "third_party/skia/include/core/SkBitmap.h"
@@ -342,10 +344,42 @@
   return false;
 }
 
+bool Gtk2UI::HasCustomImage(int id) const {
+  return IsOverridableImage(id);
+}
+
 ui::NativeTheme* Gtk2UI::GetNativeTheme() const {
   return NativeThemeGtk2::instance();
 }
 
+bool Gtk2UI::GetDefaultUsesSystemTheme() const {
+  scoped_ptr<base::Environment> env(base::Environment::Create());
+
+  switch (base::nix::GetDesktopEnvironment(env.get())) {
+    case base::nix::DESKTOP_ENVIRONMENT_GNOME:
+    case base::nix::DESKTOP_ENVIRONMENT_UNITY:
+    case base::nix::DESKTOP_ENVIRONMENT_XFCE:
+      return true;
+    case base::nix::DESKTOP_ENVIRONMENT_KDE3:
+    case base::nix::DESKTOP_ENVIRONMENT_KDE4:
+    case base::nix::DESKTOP_ENVIRONMENT_OTHER:
+      return false;
+  }
+  // Unless GetDesktopEnvironment() badly misbehaves, this should never happen.
+  NOTREACHED();
+  return false;
+}
+
+void Gtk2UI::SetDownloadCount(int count) const {
+  if (unity::IsRunning())
+    unity::SetDownloadCount(count);
+}
+
+void Gtk2UI::SetProgressFraction(float percentage) const {
+  if (unity::IsRunning())
+    unity::SetProgressFraction(percentage);
+}
+
 ui::SelectFileDialog* Gtk2UI::CreateSelectFileDialog(
     ui::SelectFileDialog::Listener* listener,
     ui::SelectFilePolicy* policy) const {
diff --git a/chrome/browser/ui/libgtk2ui/gtk2_ui.h b/chrome/browser/ui/libgtk2ui/gtk2_ui.h
index 5d1d681..e53ff6b 100644
--- a/chrome/browser/ui/libgtk2ui/gtk2_ui.h
+++ b/chrome/browser/ui/libgtk2ui/gtk2_ui.h
@@ -42,7 +42,11 @@
   virtual bool UseNativeTheme() const OVERRIDE;
   virtual gfx::Image GetThemeImageNamed(int id) const OVERRIDE;
   virtual bool GetColor(int id, SkColor* color) const OVERRIDE;
+  virtual bool HasCustomImage(int id) const OVERRIDE;
   virtual ui::NativeTheme* GetNativeTheme() const OVERRIDE;
+  virtual bool GetDefaultUsesSystemTheme() const OVERRIDE;
+  virtual void SetDownloadCount(int count) const OVERRIDE;
+  virtual void SetProgressFraction(float percentage) const OVERRIDE;
 
  private:
   typedef std::map<int, SkColor> ColorMap;
diff --git a/chrome/browser/ui/libgtk2ui/gtk2_util.cc b/chrome/browser/ui/libgtk2ui/gtk2_util.cc
index ce542f6..eec6b1a 100644
--- a/chrome/browser/ui/libgtk2ui/gtk2_util.cc
+++ b/chrome/browser/ui/libgtk2ui/gtk2_util.cc
@@ -7,6 +7,7 @@
 #include <gtk/gtk.h>
 
 #include "base/command_line.h"
+#include "base/environment.h"
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
 #include "skia/ext/platform_canvas.h"
@@ -43,6 +44,23 @@
   CommonInitFromCommandLine(command_line, gtk_init);
 }
 
+// TODO(erg): This method was copied out of shell_integration_linux.cc. Because
+// of how this library is structured as a stand alone .so, we can't call code
+// from browser and above.
+std::string GetDesktopName(base::Environment* env) {
+#if defined(GOOGLE_CHROME_BUILD)
+  return "google-chrome.desktop";
+#else  // CHROMIUM_BUILD
+  // Allow $CHROME_DESKTOP to override the built-in value, so that development
+  // versions can set themselves as the default without interfering with
+  // non-official, packaged versions using the built-in value.
+  std::string name;
+  if (env->GetVar("CHROME_DESKTOP", &name) && !name.empty())
+    return name;
+  return "chromium-browser.desktop";
+#endif
+}
+
 const SkBitmap GdkPixbufToImageSkia(GdkPixbuf* pixbuf) {
   // TODO(erg): What do we do in the case where the pixbuf fails these dchecks?
   // I would prefer to use our gtk based canvas, but that would require
diff --git a/chrome/browser/ui/libgtk2ui/gtk2_util.h b/chrome/browser/ui/libgtk2ui/gtk2_util.h
index b1673df..77a1cbf 100644
--- a/chrome/browser/ui/libgtk2ui/gtk2_util.h
+++ b/chrome/browser/ui/libgtk2ui/gtk2_util.h
@@ -5,15 +5,24 @@
 #ifndef CHROME_BROWSER_UI_LIBGTK2UI_GTK2_UTIL_H_
 #define CHROME_BROWSER_UI_LIBGTK2UI_GTK2_UTIL_H_
 
+#include <string>
+
 typedef struct _GdkPixbuf GdkPixbuf;
 
 class CommandLine;
 class SkBitmap;
 
+namespace base {
+class Environment;
+}
+
 namespace libgtk2ui {
 
 void GtkInitFromCommandLine(const CommandLine& command_line);
 
+// Returns the name of the ".desktop" file associated with our running process.
+std::string GetDesktopName(base::Environment* env);
+
 const SkBitmap GdkPixbufToImageSkia(GdkPixbuf* pixbuf);
 
 }  // namespace libgtk2ui
diff --git a/chrome/browser/ui/libgtk2ui/libgtk2ui.gyp b/chrome/browser/ui/libgtk2ui/libgtk2ui.gyp
index 3e91f6d..efa61e9 100644
--- a/chrome/browser/ui/libgtk2ui/libgtk2ui.gyp
+++ b/chrome/browser/ui/libgtk2ui/libgtk2ui.gyp
@@ -50,6 +50,8 @@
         'select_file_dialog_impl_kde.cc',
         'skia_utils_gtk2.cc',
         'skia_utils_gtk2.h',
+        'unity_service.cc',
+        'unity_service.h',
       ],
     },
   ],
diff --git a/chrome/browser/ui/libgtk2ui/native_theme_gtk2.cc b/chrome/browser/ui/libgtk2ui/native_theme_gtk2.cc
index 680e39c..18b0f4b 100644
--- a/chrome/browser/ui/libgtk2ui/native_theme_gtk2.cc
+++ b/chrome/browser/ui/libgtk2ui/native_theme_gtk2.cc
@@ -218,8 +218,6 @@
       return GetEntryStyle()->text[GTK_STATE_SELECTED];
     case kColorId_TextfieldSelectionBackgroundFocused:
       return GetEntryStyle()->base[GTK_STATE_SELECTED];
-    case kColorId_TextfieldSelectionBackgroundUnfocused:
-      return GetEntryStyle()->base[GTK_STATE_ACTIVE];
 
     // Tree
     // Table
diff --git a/chrome/browser/ui/libgtk2ui/unity_service.cc b/chrome/browser/ui/libgtk2ui/unity_service.cc
new file mode 100644
index 0000000..10085fc
--- /dev/null
+++ b/chrome/browser/ui/libgtk2ui/unity_service.cc
@@ -0,0 +1,141 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/libgtk2ui/unity_service.h"
+
+#include <dlfcn.h>
+#include <string>
+
+#include <gtk/gtk.h>
+
+#include "base/environment.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/nix/xdg_util.h"
+#include "chrome/browser/shell_integration_linux.h"
+#include "chrome/browser/ui/libgtk2ui/gtk2_util.h"
+
+// Unity data typedefs.
+typedef struct _UnityInspector UnityInspector;
+typedef UnityInspector* (*unity_inspector_get_default_func)(void);
+typedef gboolean (*unity_inspector_get_unity_running_func)
+    (UnityInspector* self);
+
+typedef struct _UnityLauncherEntry UnityLauncherEntry;
+typedef UnityLauncherEntry* (*unity_launcher_entry_get_for_desktop_id_func)
+    (const gchar* desktop_id);
+typedef void (*unity_launcher_entry_set_count_func)(UnityLauncherEntry* self,
+                                               gint64 value);
+typedef void (*unity_launcher_entry_set_count_visible_func)
+    (UnityLauncherEntry* self, gboolean value);
+typedef void (*unity_launcher_entry_set_progress_func)(UnityLauncherEntry* self,
+                                                       gdouble value);
+typedef void (*unity_launcher_entry_set_progress_visible_func)
+    (UnityLauncherEntry* self, gboolean value);
+
+
+namespace {
+
+bool attempted_load = false;
+
+// Unity has a singleton object that we can ask whether the unity is running.
+UnityInspector* inspector = NULL;
+
+// A link to the desktop entry in the panel.
+UnityLauncherEntry* chrome_entry = NULL;
+
+// Retrieved functions from libunity.
+unity_inspector_get_unity_running_func get_unity_running = NULL;
+unity_launcher_entry_set_count_func entry_set_count = NULL;
+unity_launcher_entry_set_count_visible_func entry_set_count_visible = NULL;
+unity_launcher_entry_set_progress_func entry_set_progress = NULL;
+unity_launcher_entry_set_progress_visible_func entry_set_progress_visible =
+    NULL;
+
+void EnsureMethodsLoaded() {
+  using base::nix::GetDesktopEnvironment;
+
+  if (attempted_load)
+    return;
+  attempted_load = true;
+
+  scoped_ptr<base::Environment> env(base::Environment::Create());
+  if (GetDesktopEnvironment(env.get()) != base::nix::DESKTOP_ENVIRONMENT_UNITY)
+    return;
+
+  // Ubuntu still hasn't given us a nice libunity.so symlink.
+  void* unity_lib = dlopen("libunity.so.4", RTLD_LAZY);
+  if (!unity_lib)
+    unity_lib = dlopen("libunity.so.6", RTLD_LAZY);
+  if (!unity_lib)
+    unity_lib = dlopen("libunity.so.9", RTLD_LAZY);
+  if (!unity_lib)
+    return;
+
+  unity_inspector_get_default_func inspector_get_default =
+      reinterpret_cast<unity_inspector_get_default_func>(
+          dlsym(unity_lib, "unity_inspector_get_default"));
+  if (inspector_get_default) {
+    inspector = inspector_get_default();
+
+    get_unity_running =
+        reinterpret_cast<unity_inspector_get_unity_running_func>(
+            dlsym(unity_lib, "unity_inspector_get_unity_running"));
+  }
+
+  unity_launcher_entry_get_for_desktop_id_func entry_get_for_desktop_id =
+      reinterpret_cast<unity_launcher_entry_get_for_desktop_id_func>(
+          dlsym(unity_lib, "unity_launcher_entry_get_for_desktop_id"));
+  if (entry_get_for_desktop_id) {
+    std::string desktop_id = libgtk2ui::GetDesktopName(env.get());
+    chrome_entry = entry_get_for_desktop_id(desktop_id.c_str());
+
+    entry_set_count =
+        reinterpret_cast<unity_launcher_entry_set_count_func>(
+            dlsym(unity_lib, "unity_launcher_entry_set_count"));
+
+    entry_set_count_visible =
+        reinterpret_cast<unity_launcher_entry_set_count_visible_func>(
+            dlsym(unity_lib, "unity_launcher_entry_set_count_visible"));
+
+    entry_set_progress =
+        reinterpret_cast<unity_launcher_entry_set_progress_func>(
+            dlsym(unity_lib, "unity_launcher_entry_set_progress"));
+
+    entry_set_progress_visible =
+        reinterpret_cast<unity_launcher_entry_set_progress_visible_func>(
+            dlsym(unity_lib, "unity_launcher_entry_set_progress_visible"));
+  }
+}
+
+}  // namespace
+
+
+namespace unity {
+
+bool IsRunning() {
+  EnsureMethodsLoaded();
+  if (inspector && get_unity_running)
+    return get_unity_running(inspector);
+
+  return false;
+}
+
+void SetDownloadCount(int count) {
+  EnsureMethodsLoaded();
+  if (chrome_entry && entry_set_count && entry_set_count_visible) {
+    entry_set_count(chrome_entry, count);
+    entry_set_count_visible(chrome_entry, count != 0);
+  }
+}
+
+void SetProgressFraction(float percentage) {
+  EnsureMethodsLoaded();
+  if (chrome_entry && entry_set_progress && entry_set_progress_visible) {
+    entry_set_progress(chrome_entry, percentage);
+    entry_set_progress_visible(chrome_entry,
+                               percentage > 0.0 && percentage < 1.0);
+  }
+}
+
+}  // namespace unity
diff --git a/chrome/browser/ui/libgtk2ui/unity_service.h b/chrome/browser/ui/libgtk2ui/unity_service.h
new file mode 100644
index 0000000..53c9007
--- /dev/null
+++ b/chrome/browser/ui/libgtk2ui/unity_service.h
@@ -0,0 +1,23 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_LIBGTK2UI_UNITY_SERVICE_H_
+#define CHROME_BROWSER_UI_LIBGTK2UI_UNITY_SERVICE_H_
+
+namespace unity {
+
+// Returns whether unity is currently running.
+bool IsRunning();
+
+// If unity is running, sets the download counter in the dock icon. Any value
+// other than 0 displays the badge.
+void SetDownloadCount(int count);
+
+// If unity is running, sets the download progress bar in the dock icon. Any
+// value between 0.0 and 1.0 (exclusive) shows the progress bar.
+void SetProgressFraction(float percentage);
+
+}  // namespace unity
+
+#endif  // CHROME_BROWSER_UI_LIBGTK2UI_UNITY_SERVICE_H_
diff --git a/chrome/browser/ui/login/login_prompt_browsertest.cc b/chrome/browser/ui/login/login_prompt_browsertest.cc
index eca933d..5220c8b 100644
--- a/chrome/browser/ui/login/login_prompt_browsertest.cc
+++ b/chrome/browser/ui/login/login_prompt_browsertest.cc
@@ -753,10 +753,9 @@
   EXPECT_TRUE(test_server()->Stop());
 }
 
-// Block crossdomain subresource login prompting as a phishing defense.
-// Disabled per http://crbug.com/174179.
+// Block crossdomain image login prompting as a phishing defense.
 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
-                       DISABLED_BlockCrossdomainPrompt) {
+                       BlockCrossdomainPrompt) {
   const char* kTestPage = "files/login/load_img_from_b.html";
 
   host_resolver()->AddRule("www.a.com", "127.0.0.1");
@@ -825,6 +824,54 @@
   EXPECT_TRUE(test_server()->Stop());
 }
 
+// Allow crossdomain iframe login prompting despite the above.
+IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
+                       AllowCrossdomainPrompt) {
+  const char* kTestPage = "files/login/load_iframe_from_b.html";
+
+  host_resolver()->AddRule("www.a.com", "127.0.0.1");
+  host_resolver()->AddRule("www.b.com", "127.0.0.1");
+  ASSERT_TRUE(test_server()->Start());
+
+  content::WebContents* contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  NavigationController* controller = &contents->GetController();
+  LoginPromptBrowserTestObserver observer;
+  observer.Register(content::Source<NavigationController>(controller));
+
+  // Load a page that has a cross-domain iframe authentication.
+  {
+    GURL test_page = test_server()->GetURL(kTestPage);
+    ASSERT_EQ("127.0.0.1", test_page.host());
+
+    // Change the host from 127.0.0.1 to www.a.com so that when the
+    // page tries to load from b, it will be cross-origin.
+    std::string new_host("www.a.com");
+    GURL::Replacements replacements;
+    replacements.SetHostStr(new_host);
+    test_page = test_page.ReplaceComponents(replacements);
+
+    WindowedAuthNeededObserver auth_needed_waiter(controller);
+    browser()->OpenURL(OpenURLParams(
+        test_page, Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_TYPED,
+        false));
+    auth_needed_waiter.Wait();
+    ASSERT_EQ(1u, observer.handlers_.size());
+
+    while (!observer.handlers_.empty()) {
+      WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
+      LoginHandler* handler = *observer.handlers_.begin();
+
+      ASSERT_TRUE(handler);
+      handler->CancelAuth();
+      auth_cancelled_waiter.Wait();
+    }
+  }
+
+  EXPECT_EQ(1, observer.auth_needed_count_);
+  EXPECT_TRUE(test_server()->Stop());
+}
+
 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, SupplyRedundantAuths) {
   ASSERT_TRUE(test_server()->Start());
 
diff --git a/chrome/browser/ui/metro_pin_tab_helper_win.cc b/chrome/browser/ui/metro_pin_tab_helper_win.cc
index a05c564..a11664e 100644
--- a/chrome/browser/ui/metro_pin_tab_helper_win.cc
+++ b/chrome/browser/ui/metro_pin_tab_helper_win.cc
@@ -394,7 +394,8 @@
   }
 
   // Request all the candidates.
-  int image_size = 0; // Request the full sized image.
+  int preferred_image_size = 0;  // Request the first image.
+  int max_image_size = 0;  // Do not resize images.
   for (std::vector<content::FaviconURL>::const_iterator iter =
            favicon_url_candidates_.begin();
        iter != favicon_url_candidates_.end();
@@ -402,7 +403,8 @@
     favicon_chooser_->AddPendingRequest(
         web_contents()->DownloadImage(iter->icon_url,
             true,
-            image_size,
+            preferred_image_size,
+            max_image_size,
             base::Bind(&MetroPinTabHelper::DidDownloadFavicon,
                        base::Unretained(this))));
   }
diff --git a/chrome/browser/ui/network_profile_bubble.cc b/chrome/browser/ui/network_profile_bubble.cc
index fa8cfe8..9152e84 100644
--- a/chrome/browser/ui/network_profile_bubble.cc
+++ b/chrome/browser/ui/network_profile_bubble.cc
@@ -17,7 +17,7 @@
 #include "base/logging.h"
 #include "base/metrics/histogram.h"
 #include "base/prefs/pref_service.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser_finder.h"
@@ -135,7 +135,7 @@
       } else {
         RecordUmaEvent(METRIC_CHECK_IO_FAILED);
       }
-      file_util::Delete(temp_file, false);
+      base::Delete(temp_file, false);
     }
     if (profile_on_network) {
       RecordUmaEvent(METRIC_PROFILE_ON_NETWORK);
diff --git a/chrome/browser/ui/omnibox/alternate_nav_url_fetcher.cc b/chrome/browser/ui/omnibox/alternate_nav_url_fetcher.cc
index c6e6d63..2b302c0 100644
--- a/chrome/browser/ui/omnibox/alternate_nav_url_fetcher.cc
+++ b/chrome/browser/ui/omnibox/alternate_nav_url_fetcher.cc
@@ -29,8 +29,6 @@
       navigated_to_entry_(false) {
   registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_PENDING,
                  content::NotificationService::AllSources());
-  registrar_.Add(this, chrome::NOTIFICATION_INSTANT_COMMITTED,
-                 content::NotificationService::AllSources());
 }
 
 AlternateNavURLFetcher::~AlternateNavURLFetcher() {
@@ -60,19 +58,6 @@
       break;
     }
 
-    case chrome::NOTIFICATION_INSTANT_COMMITTED: {
-      // See above.
-      NavigationController* controller =
-          &content::Source<content::WebContents>(source)->GetController();
-      if (controller_ == controller) {
-        delete this;
-      } else if (!controller_) {
-        navigated_to_entry_ = true;
-        StartFetch(controller);
-      }
-      break;
-    }
-
     case content::NOTIFICATION_NAV_ENTRY_COMMITTED:
       // The page was navigated, we can show the infobar now if necessary.
       registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
diff --git a/chrome/browser/ui/omnibox/omnibox_controller.cc b/chrome/browser/ui/omnibox/omnibox_controller.cc
index c99baa2..cd75dda 100644
--- a/chrome/browser/ui/omnibox/omnibox_controller.cc
+++ b/chrome/browser/ui/omnibox/omnibox_controller.cc
@@ -25,23 +25,6 @@
 #include "extensions/common/constants.h"
 #include "ui/gfx/rect.h"
 
-using predictors::AutocompleteActionPredictor;
-
-namespace {
-
-string16 GetDefaultSearchProviderKeyword(Profile* profile) {
-  TemplateURLService* template_url_service =
-      TemplateURLServiceFactory::GetForProfile(profile);
-  if (template_url_service) {
-    TemplateURL* template_url =
-        template_url_service->GetDefaultSearchProvider();
-    if (template_url)
-      return template_url->keyword();
-  }
-  return string16();
-}
-
-}  // namespace
 
 OmniboxController::OmniboxController(OmniboxEditModel* omnibox_edit_model,
                                      Profile* profile)
@@ -59,6 +42,7 @@
 void OmniboxController::StartAutocomplete(
     string16 user_text,
     size_t cursor_position,
+    const GURL& current_url,
     bool prevent_inline_autocomplete,
     bool prefer_keyword,
     bool allow_exact_keyword_match,
@@ -66,20 +50,6 @@
   ClearPopupKeywordMode();
   popup_->SetHoveredLine(OmniboxPopupModel::kNoMatch);
 
-#if defined(HTML_INSTANT_EXTENDED_POPUP)
-  InstantController* instant_controller = GetInstantController();
-  if (instant_controller) {
-    instant_controller->OnAutocompleteStart();
-    // If the embedded page for InstantExtended is fetching its own suggestions,
-    // suppress search suggestions from SearchProvider. We still need
-    // SearchProvider to run for FinalizeInstantQuery.
-    // TODO(dcblack): Once we are done refactoring the omnibox so we don't need
-    // to use FinalizeInstantQuery anymore, we can take out this check and
-    // remove this provider from kInstantExtendedOmniboxProviders.
-    if (instant_controller->WillFetchCompletions())
-      autocomplete_controller_->search_provider()->SuppressSearchSuggestions();
-  }
-#endif
   if (chrome::IsInstantExtendedAPIEnabled()) {
     autocomplete_controller_->search_provider()->
         SetOmniboxStartMargin(omnibox_start_margin);
@@ -88,7 +58,7 @@
   // We don't explicitly clear OmniboxPopupModel::manually_selected_match, as
   // Start ends up invoking OmniboxPopupModel::OnResultChanged which clears it.
   autocomplete_controller_->Start(AutocompleteInput(
-      user_text, cursor_position, string16(), GURL(),
+      user_text, cursor_position, string16(), current_url,
       prevent_inline_autocomplete, prefer_keyword, allow_exact_keyword_match,
       AutocompleteInput::ALL_MATCHES));
 }
@@ -121,7 +91,7 @@
 
       if (!prerender::IsOmniboxEnabled(profile_))
         DoPreconnect(*match);
-      omnibox_edit_model_->OnCurrentMatchChanged(false);
+      omnibox_edit_model_->OnCurrentMatchChanged();
     } else {
       InvalidateCurrentMatch();
       popup_->OnResultChanged();
@@ -132,138 +102,22 @@
     popup_->OnResultChanged();
   }
 
-  // TODO(beaudoin): This may no longer be needed now that instant classic is
-  // gone.
-  if (popup_->IsOpen()) {
-    // The popup size may have changed, let instant know.
-    OnPopupBoundsChanged(popup_->view()->GetTargetBounds());
-
-#if defined(HTML_INSTANT_EXTENDED_POPUP)
-    InstantController* instant_controller = GetInstantController();
-    if (instant_controller && !omnibox_edit_model_->in_revert()) {
-      instant_controller->HandleAutocompleteResults(
-          *autocomplete_controller_->providers(),
-          autocomplete_controller_->result());
-    }
-#endif
-  } else if (was_open) {
+  if (!popup_->IsOpen() && was_open) {
     // Accept the temporary text as the user text, because it makes little sense
     // to have temporary text when the popup is closed.
     omnibox_edit_model_->AcceptTemporaryTextAsUserText();
-    // The popup has been closed, let instant know.
-    OnPopupBoundsChanged(gfx::Rect());
   }
 }
 
-bool OmniboxController::DoInstant(const AutocompleteMatch& match,
-                                  string16 user_text,
-                                  string16 full_text,
-                                  size_t selection_start,
-                                  size_t selection_end,
-                                  bool user_input_in_progress,
-                                  bool in_escape_handler,
-                                  bool just_deleted_text,
-                                  bool keyword_is_selected) {
-#if defined(HTML_INSTANT_EXTENDED_POPUP)
-  InstantController* instant_controller = GetInstantController();
-  if (!instant_controller)
-    return false;
-
-  // Remove "?" if we're in forced query mode.
-  AutocompleteInput::RemoveForcedQueryStringIfNecessary(
-      autocomplete_controller_->input().type(), &user_text);
-  AutocompleteInput::RemoveForcedQueryStringIfNecessary(
-      autocomplete_controller_->input().type(), &full_text);
-  return instant_controller->Update(
-      match, user_text, full_text, selection_start, selection_end,
-      UseVerbatimInstant(just_deleted_text), user_input_in_progress,
-      popup_->IsOpen(), in_escape_handler, keyword_is_selected);
-#else
-  return false;
-#endif
-}
-
-void OmniboxController::FinalizeInstantQuery(
-    const string16& input_text,
-    const InstantSuggestion& suggestion) {
-// Should only get called for the HTML popup.
-#if defined(HTML_INSTANT_EXTENDED_POPUP)
-  if (!popup_model()->result().empty()) {
-    // We need to finalize the instant query in all cases where the
-    // |popup_model| holds some result. It is not enough to check whether the
-    // popup is open, since when an IME is active the popup may be closed while
-    // |popup_model| contains a non-empty result.
-    SearchProvider* search_provider =
-        autocomplete_controller_->search_provider();
-    // There may be no providers during testing; guard against that.
-    if (search_provider)
-      search_provider->FinalizeInstantQuery(input_text, suggestion);
-  }
-#endif
-}
-
 void OmniboxController::SetInstantSuggestion(
     const InstantSuggestion& suggestion) {
-// Should only get called for the HTML popup.
-#if defined(HTML_INSTANT_EXTENDED_POPUP)
-  switch (suggestion.behavior) {
-    case INSTANT_COMPLETE_NOW:
-      // Set blue suggestion text.
-      // TODO(beaudoin): This currently goes to the SearchProvider. Instead we
-      // should just create a valid current_match_ and call
-      // omnibox_edit_model_->OnCurrentMatchChanged. This way we can get rid of
-      // FinalizeInstantQuery entirely.
-      if (!suggestion.text.empty())
-        FinalizeInstantQuery(omnibox_edit_model_->GetViewText(), suggestion);
-      return;
-
-    case INSTANT_COMPLETE_NEVER: {
-      DCHECK_EQ(INSTANT_SUGGESTION_SEARCH, suggestion.type);
-
-      // Set gray suggestion text.
-      // Remove "?" if we're in forced query mode.
-      gray_suggestion_ = suggestion.text;
-
-      // TODO(beaudoin): The following should no longer be needed once the
-      // instant suggestion no longer goes through the search provider.
-      SearchProvider* search_provider =
-          autocomplete_controller_->search_provider();
-      if (search_provider)
-        search_provider->ClearInstantSuggestion();
-
-      omnibox_edit_model_->OnGrayTextChanged();
-      return;
-    }
-
-    case INSTANT_COMPLETE_REPLACE:
-      // Replace the entire omnibox text by the suggestion the user just arrowed
-      // to.
-      CreateAndSetInstantMatch(suggestion.text, suggestion.text,
-                               suggestion.type == INSTANT_SUGGESTION_SEARCH ?
-                                   AutocompleteMatchType::SEARCH_SUGGEST :
-                                   AutocompleteMatchType::URL_WHAT_YOU_TYPED);
-
-      omnibox_edit_model_->OnCurrentMatchChanged(true);
-      return;
-  }
-#endif
+  // TODO(jered): Delete this.
 }
 
 void OmniboxController::InvalidateCurrentMatch() {
   current_match_ = AutocompleteMatch();
 }
 
-const AutocompleteMatch& OmniboxController::CurrentMatch(
-    GURL* alternate_nav_url) const {
-  if (alternate_nav_url && current_match_.destination_url.is_valid()) {
-    *alternate_nav_url = AutocompleteResult::ComputeAlternateNavUrl(
-        autocomplete_controller_->input(), current_match_);
-  }
-
-  return current_match_;
-}
-
-
 void OmniboxController::ClearPopupKeywordMode() const {
   if (popup_->IsOpen() &&
       popup_->selected_line_state() == OmniboxPopupModel::KEYWORD)
@@ -278,7 +132,7 @@
     if (profile_->GetNetworkPredictor()) {
       profile_->GetNetworkPredictor()->AnticipateOmniboxUrl(
           match.destination_url,
-          AutocompleteActionPredictor::IsPreconnectable(match));
+          predictors::AutocompleteActionPredictor::IsPreconnectable(match));
     }
     // We could prefetch the alternate nav URL, if any, but because there
     // can be many of these as a user types an initial series of characters,
@@ -286,12 +140,6 @@
   }
 }
 
-void OmniboxController::OnPopupBoundsChanged(const gfx::Rect& bounds) {
-  InstantController* instant_controller = GetInstantController();
-  if (instant_controller)
-    instant_controller->SetPopupBounds(bounds);
-}
-
 bool OmniboxController::UseVerbatimInstant(bool just_deleted_text) const {
 #if defined(OS_MACOSX)
   // TODO(suzhe): Fix Mac port to display Instant suggest in a separated NSView,
@@ -320,11 +168,17 @@
     string16 query_string,
     string16 input_text,
     AutocompleteMatchType::Type match_type) {
-  string16 keyword = GetDefaultSearchProviderKeyword(profile_);
-  if (keyword.empty())
-    return;  // CreateSearchSuggestion needs a keyword.
+  TemplateURLService* template_url_service =
+      TemplateURLServiceFactory::GetForProfile(profile_);
+  if (!template_url_service)
+    return;
+
+  TemplateURL* template_url =
+      template_url_service->GetDefaultSearchProvider();
+  if (!template_url)
+    return;
 
   current_match_ = SearchProvider::CreateSearchSuggestion(
-      profile_, NULL, AutocompleteInput(), query_string, input_text, 0,
-      match_type, 0, false, keyword, -1);
+      NULL, 0, match_type, template_url, query_string, input_text,
+      AutocompleteInput(), false, 0, -1, true);
 }
diff --git a/chrome/browser/ui/omnibox/omnibox_controller.h b/chrome/browser/ui/omnibox/omnibox_controller.h
index 75bc5a8..2259ae7 100644
--- a/chrome/browser/ui/omnibox/omnibox_controller.h
+++ b/chrome/browser/ui/omnibox/omnibox_controller.h
@@ -41,8 +41,10 @@
                     Profile* profile);
   virtual ~OmniboxController();
 
+  // |current_url| is only set for mobile ports.
   void StartAutocomplete(string16 user_text,
                          size_t cursor_position,
+                         const GURL& current_url,
                          bool prevent_inline_autocomplete,
                          bool prefer_keyword,
                          bool allow_exact_keyword_match,
@@ -55,20 +57,6 @@
     return autocomplete_controller_.get();
   }
 
-  bool DoInstant(const AutocompleteMatch& match,
-                 string16 user_text,
-                 string16 full_text,
-                 size_t selection_start,
-                 size_t selection_end,
-                 bool user_input_in_progress,
-                 bool in_escape_handler,
-                 bool just_deleted_text,
-                 bool keyword_is_selected);
-
-  // Calls through to SearchProvider::FinalizeInstantQuery.
-  void FinalizeInstantQuery(const string16& input_text,
-                            const InstantSuggestion& suggestion);
-
   // Sets the suggestion text.
   void SetInstantSuggestion(const InstantSuggestion& suggestion);
 
@@ -84,9 +72,7 @@
   // LocationBarView, making this accessor unnecessary.
   OmniboxPopupModel* popup_model() const { return popup_; }
 
-  const string16& gray_suggestion() const { return gray_suggestion_; }
-
-  const AutocompleteMatch& CurrentMatch(GURL* alternate_nav_url) const;
+  const AutocompleteMatch& current_match() const { return current_match_; }
 
   // Turns off keyword mode for the current match.
   void ClearPopupKeywordMode() const;
@@ -98,11 +84,6 @@
   // TODO(beaudoin): Make private once OmniboxEditModel no longer refers to it.
   void DoPreconnect(const AutocompleteMatch& match);
 
-  // TODO(beaudoin): Make private once OmniboxEditModel no longer refers to it.
-  // Invoked when the popup has changed its bounds to |bounds|. |bounds| here
-  // is in screen coordinates.
-  void OnPopupBoundsChanged(const gfx::Rect& bounds);
-
  private:
 
   // Returns true if a verbatim query should be used for Instant. A verbatim
@@ -138,10 +119,6 @@
   // some time to extract these fields and use a tighter structure here.
   AutocompleteMatch current_match_;
 
-  // The completion suggested by instant, displayed in gray text besides
-  // |fill_into_edit|.
-  string16 gray_suggestion_;
-
   DISALLOW_COPY_AND_ASSIGN(OmniboxController);
 };
 
diff --git a/chrome/browser/ui/omnibox/omnibox_controller_unittest.cc b/chrome/browser/ui/omnibox/omnibox_controller_unittest.cc
index ad9d9c6..4c855c3 100644
--- a/chrome/browser/ui/omnibox/omnibox_controller_unittest.cc
+++ b/chrome/browser/ui/omnibox/omnibox_controller_unittest.cc
@@ -69,11 +69,8 @@
   // Ensure we have at least one provider.
   ASSERT_NE(0, observed_providers);
 
-  // Ensure instant extended includes all the basic ones save for those that are
-  // not expected to run in instant extended.
-  int providers_with_instant_extended =
-      observed_providers &
-      ~AutocompleteProvider::TYPE_SHORTCUTS;
+  // Ensure instant extended includes all the provides in classic Chrome.
+  int providers_with_instant_extended = observed_providers;
   // TODO(beaudoin): remove TYPE_SEARCH once it's no longer needed to pass
   // the Instant suggestion through via FinalizeInstantQuery.
   chrome::EnableInstantExtendedAPIForTesting();
diff --git a/chrome/browser/ui/omnibox/omnibox_edit_model.cc b/chrome/browser/ui/omnibox/omnibox_edit_model.cc
index 99d6680..405e407 100644
--- a/chrome/browser/ui/omnibox/omnibox_edit_model.cc
+++ b/chrome/browser/ui/omnibox/omnibox_edit_model.cc
@@ -127,15 +127,11 @@
       user_input_in_progress_(false),
       just_deleted_text_(false),
       has_temporary_text_(false),
-      is_temporary_text_set_by_instant_(false),
-      selected_instant_autocomplete_match_index_(OmniboxPopupModel::kNoMatch),
-      is_instant_temporary_text_a_search_query_(false),
       paste_state_(NONE),
       control_key_state_(UP),
       is_keyword_hint_(false),
       profile_(profile),
       in_revert_(false),
-      in_escape_handler_(false),
       allow_exact_keyword_match_(false) {
   omnibox_controller_.reset(new OmniboxController(this, profile));
   delegate_.reset(new OmniboxCurrentPageDelegateImpl(controller, profile));
@@ -187,10 +183,14 @@
 AutocompleteMatch OmniboxEditModel::CurrentMatch(
     GURL* alternate_nav_url) const {
   // If we have a valid match use it. Otherwise get one for the current text.
-  AutocompleteMatch match =
-      omnibox_controller_->CurrentMatch(alternate_nav_url);
-  if (!match.destination_url.is_valid())
+  AutocompleteMatch match = omnibox_controller_->current_match();
+
+  if (!match.destination_url.is_valid()) {
     GetInfoForCurrentText(&match, alternate_nav_url);
+  } else if (alternate_nav_url) {
+    *alternate_nav_url = AutocompleteResult::ComputeAlternateNavUrl(
+        autocomplete_controller()->input(), match);
+  }
   return match;
 }
 
@@ -209,7 +209,8 @@
   string16 instant_suggestion = view_->GetInstantSuggestion();
   const bool visibly_changed_permanent_text =
       (permanent_text_ != new_permanent_text) &&
-      (!user_input_in_progress_ || !has_focus()) &&
+      (!has_focus() ||
+       (!user_input_in_progress_ && !popup_model()->IsOpen())) &&
       (instant_suggestion.empty() ||
        new_permanent_text != user_text_ + instant_suggestion);
 
@@ -227,17 +228,10 @@
   omnibox_controller_->InvalidateCurrentMatch();
   paste_state_ = NONE;
   has_temporary_text_ = false;
-  is_temporary_text_set_by_instant_ = false;
-  selected_instant_autocomplete_match_index_ = OmniboxPopupModel::kNoMatch;
-  is_instant_temporary_text_a_search_query_ = false;
 }
 
 void OmniboxEditModel::SetInstantSuggestion(
     const InstantSuggestion& suggestion) {
-// Should only get called for the HTML popup.
-#if defined(HTML_INSTANT_EXTENDED_POPUP)
-  omnibox_controller_->SetInstantSuggestion(suggestion);
-#endif
 }
 
 bool OmniboxEditModel::CommitSuggestedText() {
@@ -282,27 +276,8 @@
                             recommended_action,
                             AutocompleteActionPredictor::LAST_PREDICT_ACTION);
 
-  // Do not perform instant if we're currently reverting or the change is the
-  // result of an INSTANT_COMPLETE_REPLACE instant suggestion.
-  bool performed_instant = false;
-  if (!in_revert_ && !is_temporary_text_set_by_instant_) {
-    size_t start, end;
-    view_->GetSelectionBounds(&start, &end);
-    string16 user_text = DisplayTextFromUserText(user_text_);
-    performed_instant = omnibox_controller_->DoInstant(
-        current_match, user_text, view_->GetText(), start, end,
-        user_input_in_progress_, in_escape_handler_,
-        view_->DeleteAtEndPressed() || just_deleted_text_,
-        KeywordIsSelected());
-  }
-
-  if (!performed_instant) {
-    // Hide any suggestions we might be showing.
-    view_->SetInstantSuggestion(string16());
-
-    // No need to wait any longer for Instant.
-    omnibox_controller_->FinalizeInstantQuery(string16(), InstantSuggestion());
-  }
+  // Hide any suggestions we might be showing.
+  view_->SetInstantSuggestion(string16());
 
   switch (recommended_action) {
     case AutocompleteActionPredictor::ACTION_PRERENDER:
@@ -427,9 +402,6 @@
   keyword_.clear();
   is_keyword_hint_ = false;
   has_temporary_text_ = false;
-  is_temporary_text_set_by_instant_ = false;
-  selected_instant_autocomplete_match_index_ = OmniboxPopupModel::kNoMatch;
-  is_instant_temporary_text_a_search_query_ = false;
   view_->SetWindowTextAndCaretPos(permanent_text_,
                                   has_focus() ? permanent_text_.length() : 0,
                                   false, true);
@@ -467,10 +439,14 @@
     cursor_position = user_text_.length();
   }
 
+  GURL current_url =
+      (delegate_->CurrentPageExists() && view_->IsIndicatingQueryRefinement()) ?
+      delegate_->GetURL() : GURL();
   bool keyword_is_selected = KeywordIsSelected();
   omnibox_controller_->StartAutocomplete(
       user_text_,
       cursor_position,
+      current_url,
       prevent_inline_autocomplete || just_deleted_text_ ||
       (has_selected_text && inline_autocomplete_text_.empty()) ||
       (paste_state_ != NONE),
@@ -599,7 +575,6 @@
       elapsed_time_since_last_change_to_default_match =
           base::TimeDelta::FromMilliseconds(-1);
     }
-    // TODO(sreeram): Handle is_temporary_text_set_by_instant_ correctly.
     OmniboxLog log(
         autocomplete_controller()->input().text(),
         just_deleted_text_,
@@ -696,19 +671,14 @@
     const GURL destination_url = autocomplete_controller()->
         GetDestinationURL(match, query_formulation_time);
 
-#if defined(HTML_INSTANT_EXTENDED_POPUP)
-    // If running with instant, notify the instant controller that a navigation
-    // is about to take place if we are navigating to a URL. This can be
-    // determined by inspecting the transition type. To ensure that this is only
-    // done on Enter key press, check that the disposition is CURRENT_TAB. This
-    // is the same heuristic used by BrowserInstantController::OpenInstant
-    if (match.transition == content::PAGE_TRANSITION_TYPED &&
-        disposition == CURRENT_TAB) {
-      InstantController* instant = GetInstantController();
-      if (instant)
-        instant->OmniboxNavigateToURL();
-    }
-#endif
+    // Track whether the destination URL sends us to a search results page
+    // using the default search provider.
+    TemplateURL* default_provider =
+        TemplateURLServiceFactory::GetForProfile(profile_)->
+            GetDefaultSearchProvider();
+    if (default_provider && default_provider->IsSearchURL(destination_url))
+      content::RecordAction(UserMetricsAction(
+          "OmniboxDestinationURLMatchesDefaultSearchProvider"));
 
     // This calls RevertAll again.
     base::AutoReset<bool> tmp(&in_revert_, true);
@@ -736,9 +706,6 @@
   // the current state properly.
   bool save_original_selection = !has_temporary_text_;
   has_temporary_text_ = true;
-  is_temporary_text_set_by_instant_ = false;
-  selected_instant_autocomplete_match_index_ = OmniboxPopupModel::kNoMatch;
-  is_instant_temporary_text_a_search_query_ = false;
   view_->OnTemporaryTextMaybeChanged(
       DisplayTextFromUserText(CurrentMatch(NULL).fill_into_edit),
       save_original_selection, true);
@@ -753,10 +720,6 @@
 void OmniboxEditModel::AcceptTemporaryTextAsUserText() {
   InternalSetUserText(UserTextFromDisplayText(view_->GetText()));
   has_temporary_text_ = false;
-  is_temporary_text_set_by_instant_ = false;
-  selected_instant_autocomplete_match_index_ = OmniboxPopupModel::kNoMatch;
-  is_instant_temporary_text_a_search_query_ = false;
-  OnPopupBoundsChanged(gfx::Rect());
   delegate_->NotifySearchTabHelper(user_input_in_progress_, !in_revert_,
                                    popup_model()->IsOpen(), user_text_.empty());
 }
@@ -801,7 +764,6 @@
     // the actual underlying current URL, e.g. if we're on the NTP and the
     // |permanent_text_| is empty.
     autocomplete_controller()->StartZeroSuggest(delegate_->GetURL(),
-                                                user_text_,
                                                 permanent_text_);
   }
 
@@ -863,77 +825,47 @@
   if (!user_input_in_progress_ && view_->IsSelectAll())
     return false;
 
-  in_escape_handler_ = true;
   if (!user_text_.empty()) {
     UMA_HISTOGRAM_ENUMERATION(kOmniboxUserTextClearedHistogram,
                               OMNIBOX_USER_TEXT_CLEARED_WITH_ESCAPE,
                               OMNIBOX_USER_TEXT_CLEARED_NUM_OF_ITEMS);
   }
   view_->RevertAll();
-  in_escape_handler_ = false;
   view_->SelectAll(true);
   return true;
 }
 
 void OmniboxEditModel::OnControlKeyChanged(bool pressed) {
-  // Don't change anything unless the key state is actually toggling.
-  if (pressed == (control_key_state_ == UP)) {
-    ControlKeyState old_state = control_key_state_;
+  if (pressed == (control_key_state_ == UP))
     control_key_state_ = pressed ? DOWN_WITHOUT_CHANGE : UP;
-    if ((control_key_state_ == DOWN_WITHOUT_CHANGE) && has_temporary_text_) {
-      // Arrowing down and then hitting control accepts the temporary text as
-      // the input text.
-      InternalSetUserText(UserTextFromDisplayText(view_->GetText()));
-      has_temporary_text_ = false;
-      is_temporary_text_set_by_instant_ = false;
-      selected_instant_autocomplete_match_index_ = OmniboxPopupModel::kNoMatch;
-      is_instant_temporary_text_a_search_query_ = false;
-    }
-    if ((old_state != DOWN_WITH_CHANGE) && popup_model()->IsOpen()) {
-      // Autocomplete history provider results may change, so refresh the
-      // popup.  This will force user_input_in_progress_ to true, but if the
-      // popup is open, that should have already been the case.
-      view_->UpdatePopup();
-    }
-  }
 }
 
 void OmniboxEditModel::OnUpOrDownKeyPressed(int count) {
   // NOTE: This purposefully doesn't trigger any code that resets paste_state_.
-  if (!popup_model()->IsOpen()) {
-    if (!query_in_progress()) {
-      // The popup is neither open nor working on a query already.  So, start an
-      // autocomplete query for the current text.  This also sets
-      // user_input_in_progress_ to true, which we want: if the user has started
-      // to interact with the popup, changing the permanent_text_ shouldn't
-      // change the displayed text.
-      // Note: This does not force the popup to open immediately.
-      // TODO(pkasting): We should, in fact, force this particular query to open
-      // the popup immediately.
-      if (!user_input_in_progress_)
-        InternalSetUserText(permanent_text_);
-      view_->UpdatePopup();
-    } else {
-      // TODO(pkasting): The popup is working on a query but is not open.  We
-      // should force it to open immediately.
-    }
-  } else {
-#if defined(HTML_INSTANT_EXTENDED_POPUP)
-    InstantController* instant = GetInstantController();
-    if (instant && instant->OnUpOrDownKeyPressed(count)) {
-      // If Instant handles the key press, it's showing a list of suggestions
-      // that it's stepping through. In that case, our popup model is
-      // irrelevant, so don't process the key press ourselves. However, do stop
-      // the autocomplete system from changing the results.
-      autocomplete_controller()->Stop(false);
-    } else
-#endif
-    {
-      // The popup is open, so the user should be able to interact with it
-      // normally.
-      popup_model()->Move(count);
-    }
+  if (popup_model()->IsOpen()) {
+    // The popup is open, so the user should be able to interact with it
+    // normally.
+    popup_model()->Move(count);
+    return;
   }
+
+  if (!query_in_progress()) {
+    // The popup is neither open nor working on a query already.  So, start an
+    // autocomplete query for the current text.  This also sets
+    // user_input_in_progress_ to true, which we want: if the user has started
+    // to interact with the popup, changing the permanent_text_ shouldn't change
+    // the displayed text.
+    // Note: This does not force the popup to open immediately.
+    // TODO(pkasting): We should, in fact, force this particular query to open
+    // the popup immediately.
+    if (!user_input_in_progress_)
+      InternalSetUserText(permanent_text_);
+    view_->UpdatePopup();
+    return;
+  }
+
+  // TODO(pkasting): The popup is working on a query but is not open.  We should
+  // force it to open immediately.
 }
 
 void OmniboxEditModel::OnPopupDataChanged(
@@ -961,9 +893,6 @@
     if (save_original_selection) {
       // Save the original selection and URL so it can be reverted later.
       has_temporary_text_ = true;
-      is_temporary_text_set_by_instant_ = false;
-      selected_instant_autocomplete_match_index_ = OmniboxPopupModel::kNoMatch;
-      is_instant_temporary_text_a_search_query_ = false;
       original_url_ = *destination_for_temporary_text_change;
       inline_autocomplete_text_.clear();
     }
@@ -985,6 +914,7 @@
   bool call_controller_onchanged = true;
   inline_autocomplete_text_ = text;
 
+  string16 user_text = user_input_in_progress_ ? user_text_ : permanent_text_;
   if (keyword_state_changed && KeywordIsSelected()) {
     // If we reach here, the user most likely entered keyword mode by inserting
     // a space between a keyword name and a search string (as pressing space or
@@ -1001,11 +931,11 @@
     // temporary text back to a default match that's a keyword search, but in
     // that case the RevertTemporaryText() call below will reset the caret or
     // selection correctly so the caret positioning we do here won't matter.
-    view_->SetWindowTextAndCaretPos(DisplayTextFromUserText(user_text_), 0,
+    view_->SetWindowTextAndCaretPos(DisplayTextFromUserText(user_text), 0,
                                                             false, false);
   } else if (view_->OnInlineAutocompleteTextMaybeChanged(
-             DisplayTextFromUserText(user_text_ + inline_autocomplete_text_),
-             DisplayTextFromUserText(user_text_).length())) {
+             DisplayTextFromUserText(user_text + inline_autocomplete_text_),
+             DisplayTextFromUserText(user_text).length())) {
     call_controller_onchanged = false;
   }
 
@@ -1068,9 +998,6 @@
   if (user_text_changed) {
     InternalSetUserText(UserTextFromDisplayText(new_text));
     has_temporary_text_ = false;
-    is_temporary_text_set_by_instant_ = false;
-    selected_instant_autocomplete_match_index_ = OmniboxPopupModel::kNoMatch;
-    is_instant_temporary_text_a_search_query_ = false;
 
     // Track when the user has deleted text so we won't allow inline
     // autocomplete.
@@ -1122,38 +1049,27 @@
            MaybeAcceptKeywordBySpace(user_text_));
 }
 
-void OmniboxEditModel::OnCurrentMatchChanged(bool is_temporary_set_by_instant) {
-  has_temporary_text_ = is_temporary_set_by_instant;
-  is_temporary_text_set_by_instant_ = is_temporary_set_by_instant;
+void OmniboxEditModel::OnCurrentMatchChanged() {
+  has_temporary_text_ = false;
 
-  const AutocompleteMatch& match = omnibox_controller_->CurrentMatch(NULL);
+  const AutocompleteMatch& match = omnibox_controller_->current_match();
 
-  if (is_temporary_set_by_instant) {
-    view_->OnTemporaryTextMaybeChanged(
-        DisplayTextFromUserText(match.fill_into_edit), !has_temporary_text_,
-        false);
-  } else {
-    // We store |keyword| and |is_keyword_hint| in temporary variables since
-    // OnPopupDataChanged use their previous state to detect changes.
-    string16 keyword;
-    bool is_keyword_hint;
-    match.GetKeywordUIState(profile_, &keyword, &is_keyword_hint);
-    string16 inline_autocomplete_text;
-    if (match.inline_autocomplete_offset < match.fill_into_edit.length()) {
-      // We have blue text, go through OnPopupDataChanged.
-      // TODO(beaudoin): Merge OnPopupDataChanged with this method once the
-      // popup handling has completely migrated to omnibox_controller.
-      inline_autocomplete_text =
-          match.fill_into_edit.substr(match.inline_autocomplete_offset);
-    }
-    popup_model()->OnResultChanged();
-    OnPopupDataChanged(inline_autocomplete_text, NULL, keyword,
-                       is_keyword_hint);
+  // We store |keyword| and |is_keyword_hint| in temporary variables since
+  // OnPopupDataChanged use their previous state to detect changes.
+  string16 keyword;
+  bool is_keyword_hint;
+  match.GetKeywordUIState(profile_, &keyword, &is_keyword_hint);
+  string16 inline_autocomplete_text;
+  if (match.inline_autocomplete_offset < match.fill_into_edit.length()) {
+    // We have blue text, go through OnPopupDataChanged.
+    // TODO(beaudoin): Merge OnPopupDataChanged with this method once the
+    // popup handling has completely migrated to omnibox_controller.
+    inline_autocomplete_text =
+        match.fill_into_edit.substr(match.inline_autocomplete_offset);
   }
-}
-
-void OmniboxEditModel::OnGrayTextChanged() {
-  view_->SetInstantSuggestion(omnibox_controller_->gray_suggestion());
+  popup_model()->OnResultChanged();
+  OnPopupDataChanged(inline_autocomplete_text, NULL, keyword,
+                     is_keyword_hint);
 }
 
 string16 OmniboxEditModel::GetViewText() const {
@@ -1211,56 +1127,6 @@
     match->destination_url =
         delegate_->GetNavigationController().GetVisibleEntry()->GetURL();
     match->transition = content::PAGE_TRANSITION_RELOAD;
-#if defined(HTML_INSTANT_EXTENDED_POPUP)
-  } else if (is_temporary_text_set_by_instant_) {
-    // If there's temporary text and it has been set by Instant, we won't find
-    // it in the popup model, so create the match based on the type Instant told
-    // us (SWYT for queries and UWYT for URLs). We do this instead of
-    // classifying the text ourselves because the text may look like a URL, but
-    // Instant may expect it to be a search (e.g.: a query for "amazon.com").
-    if (selected_instant_autocomplete_match_index_ !=
-            OmniboxPopupModel::kNoMatch) {
-      // Great, we know the exact match struct. Just use that.
-      const AutocompleteResult& result = this->result();
-      *match = result.match_at(selected_instant_autocomplete_match_index_);
-    } else {
-      const string16& text = view_->GetText();
-      AutocompleteInput input(text, string16::npos, string16(), GURL(), false,
-                              false, false, AutocompleteInput::BEST_MATCH);
-      // Only the destination_url and the transition of the match will be be
-      // used (to either navigate to the URL or let Instant commit its preview).
-      // The match won't be used for logging, displaying in the dropdown, etc.
-      // So, it's okay to pass in mostly bogus params (such as relevance = 0).
-      // TODO(sreeram): Always using NO_SUGGESTIONS_AVAILABLE is wrong when
-      // Instant is using the local fallback overlay. Fix.
-      if (is_instant_temporary_text_a_search_query_) {
-        const TemplateURL* default_provider =
-            TemplateURLServiceFactory::GetForProfile(profile_)->
-                GetDefaultSearchProvider();
-        if (default_provider && default_provider->SupportsReplacement()) {
-          *match = SearchProvider::CreateSearchSuggestion(profile_,
-              autocomplete_controller()->search_provider(), input, text, text,
-              0, AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,
-              TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, false,
-              default_provider->keyword(),
-              controller_->GetOmniboxBounds().x());
-        } else {
-          // Can't create a new search match. Leave |match| as is, with an
-          // invalid destination_url. This shouldn't ever happen. For example,
-          // even if a group policy update in the midst of interacting with
-          // Instant leaves us without a valid search provider, Instant
-          // should've observed the update and reset
-          // |is_temporary_text_set_by_instant_|, so we still shouldn't get
-          // here. However, as protection against the unknowns and Instant
-          // regressions, we simply return an invalid match instead of crashing
-          // (hence no DCHECK).
-        }
-      } else {
-        *match = HistoryURLProvider::SuggestExactInput(
-            autocomplete_controller()->history_url_provider(), input, false);
-      }
-    }
-#endif
   } else if (popup_model()->IsOpen() || query_in_progress()) {
     if (query_in_progress()) {
       // It's technically possible for |result| to be empty if no provider
@@ -1291,36 +1157,9 @@
   // The user typed something, then selected a different item.  Restore the
   // text they typed and change back to the default item.
   // NOTE: This purposefully does not reset paste_state_.
-#if defined(HTML_INSTANT_EXTENDED_POPUP)
-  bool notify_instant = is_temporary_text_set_by_instant_;
-#endif
   just_deleted_text_ = false;
   has_temporary_text_ = false;
-  is_temporary_text_set_by_instant_ = false;
-  selected_instant_autocomplete_match_index_ = OmniboxPopupModel::kNoMatch;
-  is_instant_temporary_text_a_search_query_ = false;
 
-#if defined(HTML_INSTANT_EXTENDED_POPUP)
-  InstantController* instant = GetInstantController();
-  if (instant && notify_instant) {
-    // Normally, popup_model()->ResetToDefaultMatch() will cause the view text
-    // to be updated. In Instant Extended mode however, the popup_model() is
-    // not used, so it won't do anything. So, update the view ourselves. Even
-    // if Instant is not in extended mode (i.e., it's enabled in non-extended
-    // mode, or disabled altogether), this is okay to do, since the call to
-    // popup_model()->ResetToDefaultMatch() will just override whatever we do
-    // here.
-    //
-    // The two "false" arguments make sure that our shenanigans don't cause any
-    // previously saved selection to be erased nor OnChanged() to be called.
-    view_->OnTemporaryTextMaybeChanged(user_text_ + inline_autocomplete_text_,
-        false, false);
-    AutocompleteResult::const_iterator match(result().default_match());
-    instant->OnCancel(match != result().end() ? *match : AutocompleteMatch(),
-                      user_text_,
-                      user_text_ + inline_autocomplete_text_);
-  }
-#endif
   if (revert_popup)
     popup_model()->ResetToDefaultMatch();
   view_->OnRevertTemporaryText();
diff --git a/chrome/browser/ui/omnibox/omnibox_edit_model.h b/chrome/browser/ui/omnibox/omnibox_edit_model.h
index dcf6ccc..d9f40c8 100644
--- a/chrome/browser/ui/omnibox/omnibox_edit_model.h
+++ b/chrome/browser/ui/omnibox/omnibox_edit_model.h
@@ -9,7 +9,7 @@
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/string16.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/autocomplete/autocomplete_controller_delegate.h"
 #include "chrome/browser/autocomplete/autocomplete_match.h"
 #include "chrome/browser/ui/omnibox/omnibox_controller.h"
@@ -297,19 +297,8 @@
                              bool just_deleted_text,
                              bool allow_keyword_ui_change);
 
-  // TODO(beaudoin): Mac code still calls this here. We should try to untangle
-  // this.
-  // Invoked when the popup has changed its bounds to |bounds|. |bounds| here
-  // is in screen coordinates.
-  void OnPopupBoundsChanged(const gfx::Rect& bounds) {
-    omnibox_controller_->OnPopupBoundsChanged(bounds);
-  }
-
   // Called when the current match has changed in the OmniboxController.
-  void OnCurrentMatchChanged(bool is_temporary_set_by_instant);
-
-  // Callend when the gray text suggestion has changed in the OmniboxController.
-  void OnGrayTextChanged();
+  void OnCurrentMatchChanged();
 
   // Access the current view text.
   string16 GetViewText() const;
@@ -492,26 +481,6 @@
   bool has_temporary_text_;
   GURL original_url_;
 
-  // True if Instant set the current temporary text, as opposed to it being set
-  // due to the user arrowing up/down through the popup. This can only be true
-  // if |has_temporary_text_| is true.
-  // TODO(sreeram): This is a temporary hack. Remove it once the omnibox edit
-  // model/view code is decoupled from Instant (among other things).
-  bool is_temporary_text_set_by_instant_;
-
-  // The index of the selected AutocompleteMatch in AutocompleteResult. This is
-  // needed to get the metadata details of the temporary text set by instant on
-  // the Local NTP. If the Instant extended is disabled or an Instant NTP is
-  // used, this is set to OmniboxPopupModel::kNoMatch.
-  size_t selected_instant_autocomplete_match_index_;
-
-  // True if the current temporary text set by Instant is a search query; false
-  // if it is a URL that can be directly navigated to. This is only valid if
-  // |is_temporary_text_set_by_instant_| is true. This field is needed because
-  // Instant's temporary text doesn't come from the popup model, so we can't
-  // lookup its type from the current match.
-  bool is_instant_temporary_text_a_search_query_;
-
   // When the user's last action was to paste, we disallow inline autocomplete
   // (on the theory that the user is trying to paste in a new URL or part of
   // one, and in either case inline autocomplete would get in the way).
@@ -552,11 +521,6 @@
   // "foo", which is wrong.
   bool in_revert_;
 
-  // InstantController needs this in extended mode to distinguish the case in
-  // which it should instruct a committed search results page to revert to
-  // showing results for the original query.
-  bool in_escape_handler_;
-
   // Indicates if the upcoming autocomplete search is allowed to be treated as
   // an exact keyword match.  If this is true then keyword mode will be
   // triggered automatically if the input is "<keyword> <search string>".  We
diff --git a/chrome/browser/ui/omnibox/omnibox_view.cc b/chrome/browser/ui/omnibox/omnibox_view.cc
index 86b5bdd..50cc536 100644
--- a/chrome/browser/ui/omnibox/omnibox_view.cc
+++ b/chrome/browser/ui/omnibox/omnibox_view.cc
@@ -128,9 +128,16 @@
 }
 
 bool OmniboxView::IsImeShowingPopup() const {
-  // Since not all the IMEs/platforms support the detection of a IME's popup
-  // window, falls back to IsImeComposing().
-  return IsImeComposing();
+  // Default to claiming that the IME is not showing a popup, since hiding the
+  // omnibox dropdown is a bad user experience when we don't know for sure that
+  // we have to.
+  return false;
+}
+
+bool OmniboxView::IsIndicatingQueryRefinement() const {
+  // The default implementation always returns false.  Mobile ports can override
+  // this method and implement as needed.
+  return false;
 }
 
 OmniboxView::OmniboxView(Profile* profile,
diff --git a/chrome/browser/ui/omnibox/omnibox_view.h b/chrome/browser/ui/omnibox/omnibox_view.h
index 32e7810..972cac8 100644
--- a/chrome/browser/ui/omnibox/omnibox_view.h
+++ b/chrome/browser/ui/omnibox/omnibox_view.h
@@ -209,10 +209,17 @@
   // Returns true if the user is composing something in an IME.
   virtual bool IsImeComposing() const = 0;
 
-  // Returns true if an IME is showing a popup window, which may overlap
-  // the omnibox's popup window.
+  // Returns true if we know for sure that an IME is showing a popup window,
+  // which may overlap the omnibox's popup window.
   virtual bool IsImeShowingPopup() const;
 
+  // Returns true if the view is displaying UI that indicates that query
+  // refinement will take place when the user selects the current match.  For
+  // search matches, this will cause the omnibox to search over the existing
+  // corpus (e.g. Images) rather than start a new Web search.  This method will
+  // only ever return true on mobile ports.
+  virtual bool IsIndicatingQueryRefinement() const;
+
 #if defined(TOOLKIT_VIEWS)
   virtual int GetMaxEditWidth(int entry_width) const = 0;
 
diff --git a/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc b/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc
index 7e7ab10..0cda639 100644
--- a/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc
+++ b/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc
@@ -8,7 +8,7 @@
 #include "base/strings/string16.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/autocomplete/autocomplete_input.h"
 #include "chrome/browser/autocomplete/autocomplete_match.h"
@@ -580,7 +580,8 @@
                 GetController())));
 
     GURL url = browser()->tab_strip_model()->GetActiveWebContents()->GetURL();
-    EXPECT_STREQ(kDesiredTLDHostname, url.host().c_str());
+    EXPECT_EQ(kDesiredTLDHostname, url.host());
+    EXPECT_EQ("/", url.path());
   }
 
   void AltEnterTest() {
@@ -616,7 +617,7 @@
             &browser()->tab_strip_model()->GetActiveWebContents()->
                 GetController())));
     GURL url = browser()->tab_strip_model()->GetActiveWebContents()->GetURL();
-    EXPECT_STREQ(kSearchTextURL, url.spec().c_str());
+    EXPECT_EQ(kSearchTextURL, url.spec());
 
     // Test that entering a single character then Enter performs a search.
     chrome::FocusLocationBar(browser());
@@ -637,7 +638,7 @@
             &browser()->tab_strip_model()->GetActiveWebContents()->
                 GetController())));
     url = browser()->tab_strip_model()->GetActiveWebContents()->GetURL();
-    EXPECT_STREQ(kSearchSingleCharURL, url.spec().c_str());
+    EXPECT_EQ(kSearchSingleCharURL, url.spec());
   }
 
   void EscapeToDefaultMatchTest() {
@@ -1336,14 +1337,7 @@
 }
 #undef MAYBE_ESCAPE
 
-// http://crbug.com/131179
-#if defined(OS_LINUX)
-#define MAYBE_DesiredTLD DISABLED_DesiredTLD
-#else
-#define MAYBE_DesiredTLD DesiredTLD
-#endif
-
-IN_PROC_BROWSER_TEST_F(OmniboxViewTest, MAYBE_DesiredTLD) {
+IN_PROC_BROWSER_TEST_F(OmniboxViewTest, DesiredTLD) {
   DesiredTLDTest();
 }
 
diff --git a/chrome/browser/ui/panels/base_panel_browser_test.cc b/chrome/browser/ui/panels/base_panel_browser_test.cc
index 4cce306..8277ce2 100644
--- a/chrome/browser/ui/panels/base_panel_browser_test.cc
+++ b/chrome/browser/ui/panels/base_panel_browser_test.cc
@@ -14,6 +14,7 @@
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/panels/detached_panel_collection.h"
 #include "chrome/browser/ui/panels/native_panel.h"
 #include "chrome/browser/ui/panels/panel_collection.h"
@@ -447,6 +448,48 @@
   return panel;
 }
 
+Panel* BasePanelBrowserTest::CreateInactivePanel(const std::string& name) {
+  // Create an active panel first, instead of inactive panel. This is because
+  // certain window managers on Linux, like icewm, will always activate the
+  // new window.
+  Panel* panel = CreatePanel(name);
+
+  DeactivatePanel(panel);
+  WaitForPanelActiveState(panel, SHOW_AS_INACTIVE);
+
+  return panel;
+}
+
+Panel* BasePanelBrowserTest::CreateInactiveDetachedPanel(
+    const std::string& name, const gfx::Rect& bounds) {
+  // Create an active panel first, instead of inactive panel. This is because
+  // certain window managers on Linux, like icewm, will always activate the
+  // new window.
+  Panel* panel = CreateDetachedPanel(name, bounds);
+
+  DeactivatePanel(panel);
+  WaitForPanelActiveState(panel, SHOW_AS_INACTIVE);
+
+  return panel;
+}
+
+void BasePanelBrowserTest::DeactivatePanel(Panel* panel) {
+#if defined(OS_LINUX)
+  // For certain window managers on Linux, like icewm, panel activation and
+  // deactivation notification might not get tiggered when non-panel window is
+  // activated or deactivated. So we deactivate the panel directly.
+  panel->Deactivate();
+#else
+  // Make the panel lose focus by activating the browser window. This is
+  // because:
+  // 1) On Windows, deactivating the panel window might cause the application
+  //    to lose the foreground status. When this occurs, trying to activate
+  //    the panel window again will not be allowed by the system.
+  // 2) On MacOS, deactivating a window is not supported by Cocoa.
+  browser()->window()->Activate();
+#endif
+}
+
 // static
 NativePanelTesting* BasePanelBrowserTest::CreateNativePanelTesting(
     Panel* panel) {
diff --git a/chrome/browser/ui/panels/base_panel_browser_test.h b/chrome/browser/ui/panels/base_panel_browser_test.h
index 83b4820..c5e21b2 100644
--- a/chrome/browser/ui/panels/base_panel_browser_test.h
+++ b/chrome/browser/ui/panels/base_panel_browser_test.h
@@ -86,6 +86,12 @@
                             const gfx::Rect& bounds,
                             StackedPanelCollection* stack);
 
+  Panel* CreateInactivePanel(const std::string& name);
+  Panel* CreateInactiveDetachedPanel(const std::string& name,
+                                     const gfx::Rect& bounds);
+
+  void DeactivatePanel(Panel* panel);
+
   static NativePanelTesting* CreateNativePanelTesting(Panel* panel);
 
   void WaitForPanelActiveState(Panel* panel, ActiveState state);
diff --git a/chrome/browser/ui/panels/detached_panel_browsertest.cc b/chrome/browser/ui/panels/detached_panel_browsertest.cc
index e20501f..4b744dc 100644
--- a/chrome/browser/ui/panels/detached_panel_browsertest.cc
+++ b/chrome/browser/ui/panels/detached_panel_browsertest.cc
@@ -12,14 +12,7 @@
 class DetachedPanelBrowserTest : public BasePanelBrowserTest {
 };
 
-// http://crbug.com/143247
-#if !defined(OS_WIN)
-#define MAYBE_CheckDetachedPanelProperties DISABLED_CheckDetachedPanelProperties
-#else
-#define MAYBE_CheckDetachedPanelProperties CheckDetachedPanelProperties
-#endif
-IN_PROC_BROWSER_TEST_F(DetachedPanelBrowserTest,
-                       MAYBE_CheckDetachedPanelProperties) {
+IN_PROC_BROWSER_TEST_F(DetachedPanelBrowserTest, CheckDetachedPanelProperties) {
   PanelManager* panel_manager = PanelManager::GetInstance();
   DetachedPanelCollection* detached_collection =
       panel_manager->detached_collection();
@@ -46,7 +39,12 @@
   EXPECT_FALSE(panel->IsAlwaysOnTop());
 
   EXPECT_TRUE(panel_testing->IsButtonVisible(panel::CLOSE_BUTTON));
-  EXPECT_TRUE(panel_testing->IsButtonVisible(panel::MINIMIZE_BUTTON));
+  // The minimize button will not be shown on some Linux desktop environment
+  // that does not support system minimize.
+  if (PanelManager::CanUseSystemMinimize())
+    EXPECT_TRUE(panel_testing->IsButtonVisible(panel::MINIMIZE_BUTTON));
+  else
+    EXPECT_FALSE(panel_testing->IsButtonVisible(panel::MINIMIZE_BUTTON));
   EXPECT_FALSE(panel_testing->IsButtonVisible(panel::RESTORE_BUTTON));
 
   EXPECT_EQ(panel::RESIZABLE_ALL, panel->CanResizeByMouse());
@@ -61,13 +59,7 @@
   panel_manager->CloseAll();
 }
 
-// http://crbug.com/143247
-#if !defined(OS_WIN)
-#define MAYBE_DrawAttentionOnActive DISABLED_DrawAttentionOnActive
-#else
-#define MAYBE_DrawAttentionOnActive DrawAttentionOnActive
-#endif
-IN_PROC_BROWSER_TEST_F(DetachedPanelBrowserTest, MAYBE_DrawAttentionOnActive) {
+IN_PROC_BROWSER_TEST_F(DetachedPanelBrowserTest, DrawAttentionOnActive) {
   // Create a detached panel that is initially active.
   Panel* panel = CreateDetachedPanel("1", gfx::Rect(300, 200, 250, 200));
   scoped_ptr<NativePanelTesting> native_panel_testing(
@@ -75,7 +67,6 @@
 
   // Test that the attention should not be drawn if the detached panel is in
   // focus.
-  WaitForPanelActiveState(panel, SHOW_AS_ACTIVE);  // doublecheck active state
   EXPECT_FALSE(panel->IsDrawingAttention());
   panel->FlashFrame(true);
   EXPECT_FALSE(panel->IsDrawingAttention());
@@ -84,19 +75,10 @@
   panel->Close();
 }
 
-// http://crbug.com/143247
-#if !defined(OS_WIN)
-#define MAYBE_DrawAttentionOnInactive DISABLED_DrawAttentionOnInactive
-#else
-#define MAYBE_DrawAttentionOnInactive DrawAttentionOnInactive
-#endif
-IN_PROC_BROWSER_TEST_F(DetachedPanelBrowserTest,
-                       MAYBE_DrawAttentionOnInactive) {
-  // Create two panels so that first panel becomes inactive.
-  Panel* panel = CreateDetachedPanel("1", gfx::Rect(300, 200, 250, 200));
-  CreateDetachedPanel("2", gfx::Rect(100, 100, 250, 200));
-  WaitForPanelActiveState(panel, SHOW_AS_INACTIVE);
-
+IN_PROC_BROWSER_TEST_F(DetachedPanelBrowserTest, DrawAttentionOnInactive) {
+  // Create an inactive detached panel.
+  Panel* panel =
+      CreateInactiveDetachedPanel("1", gfx::Rect(300, 200, 250, 200));
   scoped_ptr<NativePanelTesting> native_panel_testing(
       CreateNativePanelTesting(panel));
 
@@ -115,55 +97,33 @@
   PanelManager::GetInstance()->CloseAll();
 }
 
-// http://crbug.com/143247
-#if !defined(OS_WIN)
-#define MAYBE_DrawAttentionResetOnActivate DISABLED_DrawAttentionResetOnActivate
-#else
-#define MAYBE_DrawAttentionResetOnActivate DrawAttentionResetOnActivate
-#endif
-IN_PROC_BROWSER_TEST_F(DetachedPanelBrowserTest,
-                       MAYBE_DrawAttentionResetOnActivate) {
-  // Create 2 panels so we end up with an inactive panel that can
-  // be made to draw attention.
-  Panel* panel1 = CreateDetachedPanel("test panel1",
-                                      gfx::Rect(300, 200, 250, 200));
-  Panel* panel2 = CreateDetachedPanel("test panel2",
-                                      gfx::Rect(100, 100, 250, 200));
-  WaitForPanelActiveState(panel1, SHOW_AS_INACTIVE);
-
+IN_PROC_BROWSER_TEST_F(DetachedPanelBrowserTest, DrawAttentionResetOnActivate) {
+  // Create an inactive detached panel.
+  Panel* panel =
+      CreateInactiveDetachedPanel("1", gfx::Rect(300, 200, 250, 200));
   scoped_ptr<NativePanelTesting> native_panel_testing(
-      CreateNativePanelTesting(panel1));
+      CreateNativePanelTesting(panel));
 
   // Test that the attention is drawn when the detached panel is not in focus.
-  panel1->FlashFrame(true);
-  EXPECT_TRUE(panel1->IsDrawingAttention());
+  panel->FlashFrame(true);
+  EXPECT_TRUE(panel->IsDrawingAttention());
   EXPECT_TRUE(native_panel_testing->VerifyDrawingAttention());
 
   // Test that the attention is cleared when panel gets focus.
-  panel1->Activate();
-  WaitForPanelActiveState(panel1, SHOW_AS_ACTIVE);
-  EXPECT_FALSE(panel1->IsDrawingAttention());
+  panel->Activate();
+  WaitForPanelActiveState(panel, SHOW_AS_ACTIVE);
+  EXPECT_FALSE(panel->IsDrawingAttention());
   EXPECT_FALSE(native_panel_testing->VerifyDrawingAttention());
 
-  panel1->Close();
-  panel2->Close();
+  PanelManager::GetInstance()->CloseAll();
 }
 
-// http://crbug.com/143247
-#if !defined(OS_WIN)
-#define MAYBE_ClickTitlebar DISABLED_ClickTitlebar
-#else
-#define MAYBE_ClickTitlebar ClickTitlebar
-#endif
-IN_PROC_BROWSER_TEST_F(DetachedPanelBrowserTest, MAYBE_ClickTitlebar) {
-  PanelManager* panel_manager = PanelManager::GetInstance();
-
+IN_PROC_BROWSER_TEST_F(DetachedPanelBrowserTest, ClickTitlebar) {
   Panel* panel = CreateDetachedPanel("1", gfx::Rect(300, 200, 250, 200));
   EXPECT_FALSE(panel->IsMinimized());
 
   // Clicking on an active detached panel's titlebar has no effect, regardless
   // of modifier.
-  WaitForPanelActiveState(panel, SHOW_AS_ACTIVE);  // doublecheck active state
   scoped_ptr<NativePanelTesting> test_panel(
       CreateNativePanelTesting(panel));
   test_panel->PressLeftMouseButtonTitlebar(panel->GetBounds().origin());
@@ -177,17 +137,14 @@
   EXPECT_TRUE(panel->IsActive());
   EXPECT_FALSE(panel->IsMinimized());
 
-  // Create a second panel to cause the first to become inactive.
-  CreateDetachedPanel("2", gfx::Rect(100, 200, 230, 345));
-  WaitForPanelActiveState(panel, SHOW_AS_INACTIVE);
-
   // Clicking on an inactive detached panel's titlebar activates it.
+  DeactivatePanel(panel);
   test_panel->PressLeftMouseButtonTitlebar(panel->GetBounds().origin());
   test_panel->ReleaseMouseButtonTitlebar();
   WaitForPanelActiveState(panel, SHOW_AS_ACTIVE);
   EXPECT_FALSE(panel->IsMinimized());
 
-  panel_manager->CloseAll();
+  PanelManager::GetInstance()->CloseAll();
 }
 
 IN_PROC_BROWSER_TEST_F(DetachedPanelBrowserTest,
diff --git a/chrome/browser/ui/panels/display_settings_provider.h b/chrome/browser/ui/panels/display_settings_provider.h
index 5dc527d..da3df1d 100644
--- a/chrome/browser/ui/panels/display_settings_provider.h
+++ b/chrome/browser/ui/panels/display_settings_provider.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_UI_PANELS_DISPLAY_SETTINGS_PROVIDER_H_
 
 #include "base/observer_list.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "ui/gfx/rect.h"
 
 // Encapsulates the logic to provide display settings support, including the
diff --git a/chrome/browser/ui/panels/display_settings_provider_win.h b/chrome/browser/ui/panels/display_settings_provider_win.h
index 50343ba..75b0674 100644
--- a/chrome/browser/ui/panels/display_settings_provider_win.h
+++ b/chrome/browser/ui/panels/display_settings_provider_win.h
@@ -9,7 +9,7 @@
 
 #include <windows.h>
 #include "base/compiler_specific.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 
 class DisplaySettingsProviderWin : public DisplaySettingsProvider {
  public:
diff --git a/chrome/browser/ui/panels/panel_browsertest.cc b/chrome/browser/ui/panels/panel_browsertest.cc
index 7148c24..6b5dccf 100644
--- a/chrome/browser/ui/panels/panel_browsertest.cc
+++ b/chrome/browser/ui/panels/panel_browsertest.cc
@@ -503,16 +503,10 @@
   panel->Close();
 }
 
-#if defined(OS_LINUX) || defined(OS_WIN)
-// There is no animations on Linux, by design (http://crbug.com/144074).
-// And there are intermittent/flaky failures on windows try bots
-// (http://crbug.com/179069).
-#define MAYBE_AnimateBounds DISABLED_AnimateBounds
-#else
-#define MAYBE_AnimateBounds AnimateBounds
-#endif
-IN_PROC_BROWSER_TEST_F(PanelBrowserTest, MAYBE_AnimateBounds) {
-  Panel* panel = CreatePanelWithBounds("PanelTest", gfx::Rect(0, 0, 100, 100));
+IN_PROC_BROWSER_TEST_F(PanelBrowserTest, AnimateBounds) {
+  // Create a detached panel, instead of docked panel because it cannot be
+  // moved to any location.
+  Panel* panel = CreateDetachedPanel("1", gfx::Rect(200, 100, 100, 100));
   scoped_ptr<NativePanelTesting> panel_testing(
       CreateNativePanelTesting(panel));
 
@@ -527,8 +521,11 @@
   // Set bounds with animation.
   gfx::Rect bounds = gfx::Rect(10, 20, 150, 160);
   panel->SetPanelBounds(bounds);
+  // There is no animation on Linux, by design.
+#if !defined(OS_LINUX)
   EXPECT_TRUE(panel_testing->IsAnimatingBounds());
   WaitForBoundsAnimationFinished(panel);
+#endif
   EXPECT_FALSE(panel_testing->IsAnimatingBounds());
   EXPECT_EQ(bounds, panel->GetBounds());
 
@@ -1046,15 +1043,8 @@
   EXPECT_FALSE(tabbed_window->IsActive());
 }
 
-// http://crbug.com/143247
-#if !defined(OS_WIN)
-#define MAYBE_DrawAttentionBasic DISABLED_DrawAttentionBasic
-#else
-#define MAYBE_DrawAttentionBasic DrawAttentionBasic
-#endif
-IN_PROC_BROWSER_TEST_F(PanelBrowserTest, MAYBE_DrawAttentionBasic) {
-  CreatePanelParams params("Initially Inactive", gfx::Rect(), SHOW_AS_INACTIVE);
-  Panel* panel = CreatePanelWithParams(params);
+IN_PROC_BROWSER_TEST_F(PanelBrowserTest, DrawAttentionBasic) {
+  Panel* panel = CreateInactivePanel("P1");
   scoped_ptr<NativePanelTesting> native_panel_testing(
       CreateNativePanelTesting(panel));
 
@@ -1087,70 +1077,50 @@
   panel->Close();
 }
 
-// http://crbug.com/143247
-#if !defined(OS_WIN)
-#define MAYBE_DrawAttentionWhileMinimized DISABLED_DrawAttentionWhileMinimized
-#else
-#define MAYBE_DrawAttentionWhileMinimized DrawAttentionWhileMinimized
-#endif
-IN_PROC_BROWSER_TEST_F(PanelBrowserTest, MAYBE_DrawAttentionWhileMinimized) {
-  // Create 3 panels so we end up with an inactive panel that can
-  // be made to draw attention.
-  Panel* panel = CreatePanel("test panel1");
-  Panel* panel2 = CreatePanel("test panel2");
-  Panel* panel3 = CreatePanel("test panel3");
+IN_PROC_BROWSER_TEST_F(PanelBrowserTest, DrawAttentionWhileMinimized) {
+  Panel* panel1 = CreateInactivePanel("P1");
+  Panel* panel2 = CreateInactivePanel("P2");
 
-  scoped_ptr<NativePanelTesting> native_panel_testing(
-      CreateNativePanelTesting(panel));
+  scoped_ptr<NativePanelTesting> native_panel1_testing(
+      CreateNativePanelTesting(panel1));
 
   // Test that the attention is drawn and the title-bar is brought up when the
   // minimized panel is drawing attention.
-  panel->Minimize();
-  EXPECT_EQ(Panel::MINIMIZED, panel->expansion_state());
-  panel->FlashFrame(true);
-  EXPECT_TRUE(panel->IsDrawingAttention());
-  EXPECT_EQ(Panel::TITLE_ONLY, panel->expansion_state());
-  EXPECT_TRUE(native_panel_testing->VerifyDrawingAttention());
+  panel1->Minimize();
+  EXPECT_EQ(Panel::MINIMIZED, panel1->expansion_state());
+  panel1->FlashFrame(true);
+  EXPECT_TRUE(panel1->IsDrawingAttention());
+  EXPECT_EQ(Panel::TITLE_ONLY, panel1->expansion_state());
+  EXPECT_TRUE(native_panel1_testing->VerifyDrawingAttention());
 
   // Test that we cannot bring up other minimized panel if the mouse is over
   // the panel that draws attension.
   panel2->Minimize();
-  gfx::Point hover_point(panel->GetBounds().origin());
+  gfx::Point hover_point(panel1->GetBounds().origin());
   MoveMouse(hover_point);
-  EXPECT_EQ(Panel::TITLE_ONLY, panel->expansion_state());
+  EXPECT_EQ(Panel::TITLE_ONLY, panel1->expansion_state());
   EXPECT_EQ(Panel::MINIMIZED, panel2->expansion_state());
 
   // Test that we cannot bring down the panel that is drawing the attention.
   hover_point.set_y(hover_point.y() - 200);
   MoveMouse(hover_point);
-  EXPECT_EQ(Panel::TITLE_ONLY, panel->expansion_state());
+  EXPECT_EQ(Panel::TITLE_ONLY, panel1->expansion_state());
 
   // Test that the attention is cleared when activated.
-  panel->Activate();
-  WaitForPanelActiveState(panel, SHOW_AS_ACTIVE);
-  EXPECT_FALSE(panel->IsDrawingAttention());
-  EXPECT_EQ(Panel::EXPANDED, panel->expansion_state());
-  EXPECT_FALSE(native_panel_testing->VerifyDrawingAttention());
+  panel1->Activate();
+  WaitForPanelActiveState(panel1, SHOW_AS_ACTIVE);
+  EXPECT_FALSE(panel1->IsDrawingAttention());
+  EXPECT_EQ(Panel::EXPANDED, panel1->expansion_state());
+  EXPECT_FALSE(native_panel1_testing->VerifyDrawingAttention());
 
-  panel->Close();
-  panel2->Close();
-  panel3->Close();
+  PanelManager::GetInstance()->CloseAll();
 }
 
-// http://crbug.com/175760; several panel tests failing regularly on mac.
-#if defined(OS_MACOSX) || defined(OS_LINUX)
-#define MAYBE_StopDrawingAttentionWhileMinimized \
-  DISABLED_StopDrawingAttentionWhileMinimized
-#else
-#define MAYBE_StopDrawingAttentionWhileMinimized \
-  StopDrawingAttentionWhileMinimized
-#endif
 // Verify that minimized state of a panel is correct after draw attention
 // is stopped when there are other minimized panels.
-IN_PROC_BROWSER_TEST_F(PanelBrowserTest,
-                       MAYBE_StopDrawingAttentionWhileMinimized) {
-  Panel* panel1 = CreatePanel("panel1");
-  Panel* panel2 = CreatePanel("panel2");
+IN_PROC_BROWSER_TEST_F(PanelBrowserTest, StopDrawingAttentionWhileMinimized) {
+  Panel* panel1 = CreateInactivePanel("P1");
+  Panel* panel2 = CreateInactivePanel("P2");
 
   panel1->Minimize();
   EXPECT_EQ(Panel::MINIMIZED, panel1->expansion_state());
@@ -1214,21 +1184,17 @@
   EXPECT_EQ(Panel::MINIMIZED, panel1->expansion_state());
   EXPECT_EQ(Panel::MINIMIZED, panel2->expansion_state());
 
-  panel1->Close();
-  panel2->Close();
+  PanelManager::GetInstance()->CloseAll();
 }
 
 IN_PROC_BROWSER_TEST_F(PanelBrowserTest, DrawAttentionWhenActive) {
-  CreatePanelParams params("Initially Active", gfx::Rect(), SHOW_AS_ACTIVE);
-  Panel* panel = CreatePanelWithParams(params);
+  // Create an active panel.
+  Panel* panel = CreatePanel("P1");
   scoped_ptr<NativePanelTesting> native_panel_testing(
       CreateNativePanelTesting(panel));
 
   // Test that the attention should not be drawn if the expanded panel is in
   // focus.
-  EXPECT_EQ(Panel::EXPANDED, panel->expansion_state());
-  WaitForPanelActiveState(panel, SHOW_AS_ACTIVE);  // doublecheck active state
-  EXPECT_FALSE(panel->IsDrawingAttention());
   panel->FlashFrame(true);
   EXPECT_FALSE(panel->IsDrawingAttention());
   EXPECT_FALSE(native_panel_testing->VerifyDrawingAttention());
@@ -1236,19 +1202,8 @@
   panel->Close();
 }
 
-// http://crbug.com/143247
-#if !defined(OS_WIN)
-#define MAYBE_DrawAttentionResetOnActivate DISABLED_DrawAttentionResetOnActivate
-#else
-#define MAYBE_DrawAttentionResetOnActivate DrawAttentionResetOnActivate
-#endif
-IN_PROC_BROWSER_TEST_F(PanelBrowserTest, MAYBE_DrawAttentionResetOnActivate) {
-  // Create 2 panels so we end up with an inactive panel that can
-  // be made to draw attention.
-  Panel* panel = CreatePanel("test panel1");
-  Panel* panel2 = CreatePanel("test panel2");
-  WaitForPanelActiveState(panel, SHOW_AS_INACTIVE);
-
+IN_PROC_BROWSER_TEST_F(PanelBrowserTest, DrawAttentionResetOnActivate) {
+  Panel* panel = CreateInactivePanel("P1");
   scoped_ptr<NativePanelTesting> native_panel_testing(
       CreateNativePanelTesting(panel));
 
@@ -1263,59 +1218,36 @@
   EXPECT_FALSE(native_panel_testing->VerifyDrawingAttention());
 
   panel->Close();
-  panel2->Close();
 }
 
-// http://crbug.com/143247
-#if !defined(OS_WIN)
-#define MAYBE_DrawAttentionMinimizedNotResetOnActivate DISABLED_DrawAttentionMinimizedNotResetOnActivate
-#else
-#define MAYBE_DrawAttentionMinimizedNotResetOnActivate DrawAttentionMinimizedNotResetOnActivate
-#endif
 IN_PROC_BROWSER_TEST_F(PanelBrowserTest,
-                       MAYBE_DrawAttentionMinimizedNotResetOnActivate) {
-  // Create 2 panels so we end up with an inactive panel that can
-  // be made to draw attention.
-  Panel* panel1 = CreatePanel("test panel1");
-  Panel* panel2 = CreatePanel("test panel2");
-  WaitForPanelActiveState(panel1, SHOW_AS_INACTIVE);
+                       DrawAttentionMinimizedNotResetOnActivate) {
+  Panel* panel = CreateInactivePanel("P1");
 
-  panel1->Minimize();
-  EXPECT_TRUE(panel1->IsMinimized());
-  panel1->FlashFrame(true);
-  EXPECT_TRUE(panel1->IsDrawingAttention());
+  panel->Minimize();
+  EXPECT_TRUE(panel->IsMinimized());
+  panel->FlashFrame(true);
+  EXPECT_TRUE(panel->IsDrawingAttention());
 
   // Simulate panel being activated while minimized. Cannot call
   // Activate() as that expands the panel.
-  panel1->OnActiveStateChanged(true);
-  EXPECT_TRUE(panel1->IsDrawingAttention());  // Unchanged.
+  panel->OnActiveStateChanged(true);
+  EXPECT_TRUE(panel->IsDrawingAttention());  // Unchanged.
 
   // Unminimize panel to show that attention would have been cleared
   // if panel had not been minimized.
-  panel1->Restore();
-  EXPECT_FALSE(panel1->IsMinimized());
-  EXPECT_TRUE(panel1->IsDrawingAttention());  // Unchanged.
+  panel->Restore();
+  EXPECT_FALSE(panel->IsMinimized());
+  EXPECT_TRUE(panel->IsDrawingAttention());  // Unchanged.
 
-  panel1->OnActiveStateChanged(true);
-  EXPECT_FALSE(panel1->IsDrawingAttention());  // Attention cleared.
+  panel->OnActiveStateChanged(true);
+  EXPECT_FALSE(panel->IsDrawingAttention());  // Attention cleared.
 
-  panel1->Close();
-  panel2->Close();
+  panel->Close();
 }
 
-// http://crbug.com/143247
-#if !defined(OS_WIN)
-#define MAYBE_DrawAttentionResetOnClick DISABLED_DrawAttentionResetOnClick
-#else
-#define MAYBE_DrawAttentionResetOnClick DrawAttentionResetOnClick
-#endif
-IN_PROC_BROWSER_TEST_F(PanelBrowserTest, MAYBE_DrawAttentionResetOnClick) {
-  // Create 2 panels so we end up with an inactive panel that can
-  // be made to draw attention.
-  Panel* panel = CreatePanel("test panel1");
-  Panel* panel2 = CreatePanel("test panel2");
-  WaitForPanelActiveState(panel, SHOW_AS_INACTIVE);
-
+IN_PROC_BROWSER_TEST_F(PanelBrowserTest, DrawAttentionResetOnClick) {
+  Panel* panel = CreateInactivePanel("P1");
   scoped_ptr<NativePanelTesting> native_panel_testing(
       CreateNativePanelTesting(panel));
 
@@ -1333,7 +1265,6 @@
   EXPECT_FALSE(native_panel_testing->VerifyDrawingAttention());
 
   panel->Close();
-  panel2->Close();
 }
 
 // http://crbug.com/175760; several panel tests failing regularly on mac.
@@ -1448,14 +1379,8 @@
   panel2->Close();
 }
 
-// http://crbug.com/143247
-#if !defined(OS_WIN)
-#define MAYBE_NonExtensionDomainPanelsCloseOnUninstall DISABLED_NonExtensionDomainPanelsCloseOnUninstall
-#else
-#define MAYBE_NonExtensionDomainPanelsCloseOnUninstall NonExtensionDomainPanelsCloseOnUninstall
-#endif
 IN_PROC_BROWSER_TEST_F(PanelBrowserTest,
-                       MAYBE_NonExtensionDomainPanelsCloseOnUninstall) {
+                       NonExtensionDomainPanelsCloseOnUninstall) {
   // Create a test extension.
   DictionaryValue empty_value;
   scoped_refptr<extensions::Extension> extension =
@@ -1468,7 +1393,7 @@
   EXPECT_EQ(0, panel_manager->num_panels());
 
   // Create a panel with the extension as host.
-  CreatePanelParams params(extension_app_name, gfx::Rect(), SHOW_AS_INACTIVE);
+  CreatePanelParams params(extension_app_name, gfx::Rect(), SHOW_AS_ACTIVE);
   std::string extension_domain_url(extensions::kExtensionScheme);
   extension_domain_url += "://";
   extension_domain_url += extension->id();
@@ -1478,7 +1403,7 @@
   EXPECT_EQ(1, panel_manager->num_panels());
 
   // Create a panel with a non-extension host.
-  CreatePanelParams params1(extension_app_name, gfx::Rect(), SHOW_AS_INACTIVE);
+  CreatePanelParams params1(extension_app_name, gfx::Rect(), SHOW_AS_ACTIVE);
   params1.url = GURL(content::kAboutBlankURL);
   Panel* panel1 = CreatePanelWithParams(params1);
   EXPECT_EQ(2, panel_manager->num_panels());
@@ -1685,12 +1610,6 @@
   panel->Close();
 }
 
-// http://crbug.com/175760; several panel tests failing regularly on mac.
-#if defined(OS_MACOSX)
-#define MAYBE_DevTools DISABLED_DevTools
-#else
-#define MAYBE_DevTools DevTools
-#endif
 IN_PROC_BROWSER_TEST_F(PanelBrowserTest, DevTools) {
   // Create a test panel with web contents loaded.
   CreatePanelParams params("1", gfx::Rect(0, 0, 200, 220), SHOW_AS_ACTIVE);
@@ -1725,12 +1644,6 @@
   panel->Close();
 }
 
-// http://crbug.com/175760; several panel tests failing regularly on mac.
-#if defined(OS_MACOSX)
-#define MAYBE_DevToolsConsole DISABLED_DevToolsConsole
-#else
-#define MAYBE_DevToolsConsole DevToolsConsole
-#endif
 IN_PROC_BROWSER_TEST_F(PanelBrowserTest, DevToolsConsole) {
   // Create a test panel with web contents loaded.
   CreatePanelParams params("1", gfx::Rect(0, 0, 200, 220), SHOW_AS_ACTIVE);
diff --git a/chrome/browser/ui/panels/panel_drag_browsertest.cc b/chrome/browser/ui/panels/panel_drag_browsertest.cc
index 1cd2603..f88a649 100644
--- a/chrome/browser/ui/panels/panel_drag_browsertest.cc
+++ b/chrome/browser/ui/panels/panel_drag_browsertest.cc
@@ -820,47 +820,37 @@
   PanelManager::GetInstance()->CloseAll();
 }
 
-IN_PROC_BROWSER_TEST_F(PanelDragBrowserTest,
-                       DISABLED_CloseDetachedPanelOnDrag) {
+IN_PROC_BROWSER_TEST_F(PanelDragBrowserTest, CloseDetachedPanelOnDrag) {
   PanelManager* panel_manager = PanelManager::GetInstance();
   PanelDragController* drag_controller = panel_manager->drag_controller();
   DetachedPanelCollection* detached_collection =
       panel_manager->detached_collection();
 
-  // Create 4 detached panels.
+  // Create 1 detached panel.
   Panel* panel1 = CreateDetachedPanel("1", gfx::Rect(100, 200, 100, 100));
-  Panel* panel2 = CreateDetachedPanel("2", gfx::Rect(200, 210, 110, 110));
-  Panel* panel3 = CreateDetachedPanel("3", gfx::Rect(300, 220, 120, 120));
-  Panel* panel4 = CreateDetachedPanel("4", gfx::Rect(400, 230, 130, 130));
-  ASSERT_EQ(4, detached_collection->num_panels());
+  ASSERT_EQ(1, detached_collection->num_panels());
 
   scoped_ptr<NativePanelTesting> panel1_testing(
       CreateNativePanelTesting(panel1));
   gfx::Point panel1_old_position = panel1->GetBounds().origin();
-  gfx::Point panel2_position = panel2->GetBounds().origin();
-  gfx::Point panel3_position = panel3->GetBounds().origin();
-  gfx::Point panel4_position = panel4->GetBounds().origin();
 
   // Test the scenario: drag a panel, close another panel, cancel the drag.
   {
-    gfx::Point panel1_new_position = panel1_old_position;
-    panel1_new_position.Offset(-51, -102);
+    // Create a panel to be closed.
+    Panel* panel2 = CreateDetachedPanel("2", gfx::Rect(300, 210, 110, 110));
 
     // Start dragging a panel.
     panel1_testing->PressLeftMouseButtonTitlebar(panel1->GetBounds().origin());
+    gfx::Point panel1_new_position = panel1_old_position;
+    panel1_new_position.Offset(-51, -102);
     panel1_testing->DragTitlebar(panel1_new_position);
     EXPECT_TRUE(drag_controller->is_dragging());
     EXPECT_EQ(panel1, drag_controller->dragging_panel());
 
-    ASSERT_EQ(4, detached_collection->num_panels());
+    ASSERT_EQ(2, detached_collection->num_panels());
     EXPECT_TRUE(detached_collection->HasPanel(panel1));
     EXPECT_TRUE(detached_collection->HasPanel(panel2));
-    EXPECT_TRUE(detached_collection->HasPanel(panel3));
-    EXPECT_TRUE(detached_collection->HasPanel(panel4));
     EXPECT_EQ(panel1_new_position, panel1->GetBounds().origin());
-    EXPECT_EQ(panel2_position, panel2->GetBounds().origin());
-    EXPECT_EQ(panel3_position, panel3->GetBounds().origin());
-    EXPECT_EQ(panel4_position, panel4->GetBounds().origin());
 
     // Closing another panel while dragging in progress will keep the dragging
     // panel intact.
@@ -868,86 +858,64 @@
     EXPECT_TRUE(drag_controller->is_dragging());
     EXPECT_EQ(panel1, drag_controller->dragging_panel());
 
-    ASSERT_EQ(3, detached_collection->num_panels());
+    ASSERT_EQ(1, detached_collection->num_panels());
     EXPECT_TRUE(detached_collection->HasPanel(panel1));
-    EXPECT_TRUE(detached_collection->HasPanel(panel3));
-    EXPECT_TRUE(detached_collection->HasPanel(panel4));
     EXPECT_EQ(panel1_new_position, panel1->GetBounds().origin());
-    EXPECT_EQ(panel3_position, panel3->GetBounds().origin());
-    EXPECT_EQ(panel4_position, panel4->GetBounds().origin());
 
     // Cancel the drag.
     panel1_testing->CancelDragTitlebar();
     WaitForBoundsAnimationFinished(panel1);
     EXPECT_FALSE(drag_controller->is_dragging());
-
-    ASSERT_EQ(3, detached_collection->num_panels());
-    EXPECT_TRUE(detached_collection->HasPanel(panel1));
-    EXPECT_TRUE(detached_collection->HasPanel(panel3));
-    EXPECT_TRUE(detached_collection->HasPanel(panel4));
     EXPECT_EQ(panel1_old_position, panel1->GetBounds().origin());
-    EXPECT_EQ(panel3_position, panel3->GetBounds().origin());
-    EXPECT_EQ(panel4_position, panel4->GetBounds().origin());
   }
 
   // Test the scenario: drag a panel, close another panel, end the drag.
   {
-    gfx::Point panel1_new_position = panel1_old_position;
-    panel1_new_position.Offset(-51, -102);
+    // Create a panel to be closed.
+    Panel* panel2 = CreateDetachedPanel("2", gfx::Rect(300, 210, 110, 110));
 
     // Start dragging a panel.
     panel1_testing->PressLeftMouseButtonTitlebar(panel1->GetBounds().origin());
+    gfx::Point panel1_new_position = panel1_old_position;
+    panel1_new_position.Offset(-51, -102);
     panel1_testing->DragTitlebar(panel1_new_position);
     EXPECT_TRUE(drag_controller->is_dragging());
     EXPECT_EQ(panel1, drag_controller->dragging_panel());
 
-    ASSERT_EQ(3, detached_collection->num_panels());
-    EXPECT_TRUE(detached_collection->HasPanel(panel1));
-    EXPECT_TRUE(detached_collection->HasPanel(panel3));
-    EXPECT_TRUE(detached_collection->HasPanel(panel4));
-    EXPECT_EQ(panel1_new_position, panel1->GetBounds().origin());
-    EXPECT_EQ(panel3_position, panel3->GetBounds().origin());
-    EXPECT_EQ(panel4_position, panel4->GetBounds().origin());
-
-    // Closing another panel while dragging in progress will keep the dragging
-    // panel intact.
-    CloseWindowAndWait(panel3);
-    EXPECT_TRUE(drag_controller->is_dragging());
-    EXPECT_EQ(panel1, drag_controller->dragging_panel());
-
     ASSERT_EQ(2, detached_collection->num_panels());
     EXPECT_TRUE(detached_collection->HasPanel(panel1));
-    EXPECT_TRUE(detached_collection->HasPanel(panel4));
+    EXPECT_TRUE(detached_collection->HasPanel(panel2));
     EXPECT_EQ(panel1_new_position, panel1->GetBounds().origin());
-    EXPECT_EQ(panel4_position, panel4->GetBounds().origin());
+
+    // Closing another panel while dragging in progress will keep the dragging
+    // panel intact.
+    CloseWindowAndWait(panel2);
+    EXPECT_TRUE(drag_controller->is_dragging());
+    EXPECT_EQ(panel1, drag_controller->dragging_panel());
+
+    ASSERT_EQ(1, detached_collection->num_panels());
+    EXPECT_TRUE(detached_collection->HasPanel(panel1));
+    EXPECT_EQ(panel1_new_position, panel1->GetBounds().origin());
 
     // Finish the drag.
     panel1_testing->FinishDragTitlebar();
     EXPECT_FALSE(drag_controller->is_dragging());
-
-    ASSERT_EQ(2, detached_collection->num_panels());
-    EXPECT_TRUE(detached_collection->HasPanel(panel1));
-    EXPECT_TRUE(detached_collection->HasPanel(panel4));
     EXPECT_EQ(panel1_new_position, panel1->GetBounds().origin());
-    EXPECT_EQ(panel4_position, panel4->GetBounds().origin());
   }
 
   // Test the scenario: drag a panel and close the dragging panel.
   {
-    gfx::Point panel1_new_position = panel1->GetBounds().origin();
-    panel1_new_position.Offset(-51, -102);
-
     // Start dragging a panel again.
     panel1_testing->PressLeftMouseButtonTitlebar(panel1->GetBounds().origin());
+    gfx::Point panel1_new_position = panel1->GetBounds().origin();
+    panel1_new_position.Offset(45, 67);
     panel1_testing->DragTitlebar(panel1_new_position);
     EXPECT_TRUE(drag_controller->is_dragging());
     EXPECT_EQ(panel1, drag_controller->dragging_panel());
 
-    ASSERT_EQ(2, detached_collection->num_panels());
+    ASSERT_EQ(1, detached_collection->num_panels());
     EXPECT_TRUE(detached_collection->HasPanel(panel1));
-    EXPECT_TRUE(detached_collection->HasPanel(panel4));
     EXPECT_EQ(panel1_new_position, panel1->GetBounds().origin());
-    EXPECT_EQ(panel4_position, panel4->GetBounds().origin());
 
     // Closing the dragging panel should make the drag controller abort.
     content::WindowedNotificationObserver signal(
@@ -962,12 +930,8 @@
 
     // Wait till the panel is fully closed.
     signal.Wait();
-    ASSERT_EQ(1, detached_collection->num_panels());
-    EXPECT_TRUE(detached_collection->HasPanel(panel4));
-    EXPECT_EQ(panel4_position, panel4->GetBounds().origin());
+    ASSERT_EQ(0, detached_collection->num_panels());
   }
-
-  panel_manager->CloseAll();
 }
 
 IN_PROC_BROWSER_TEST_F(PanelDragBrowserTest, Detach) {
@@ -1278,21 +1242,12 @@
   panel_manager->CloseAll();
 }
 
-// http://crbug.com/175760; several panel tests failing regularly on mac.
-// http://crbug.com/240459 some panel tests are flaky on Linux/GTK.
-#if defined(OS_MACOSX) || defined(TOOLKIT_GTK)
-#define MAYBE_DetachWithSqueeze DISABLED_DetachWithSqueeze
-#else
-#define MAYBE_DetachWithSqueeze DetachWithSqueeze
-#endif
-IN_PROC_BROWSER_TEST_F(PanelDragBrowserTest, MAYBE_DetachWithSqueeze) {
+IN_PROC_BROWSER_TEST_F(PanelDragBrowserTest, DetachWithSqueeze) {
   PanelManager* panel_manager = PanelManager::GetInstance();
   DockedPanelCollection* docked_collection = panel_manager->docked_collection();
   DetachedPanelCollection* detached_collection =
       panel_manager->detached_collection();
 
-  gfx::Vector2d drag_delta_to_detach = GetDragDeltaToDetach();
-
   // Create some docked panels.
   //   docked:    P1  P2  P3  P4  P5
   Panel* panel1 = CreateDockedPanel("1", gfx::Rect(0, 0, 200, 100));
@@ -1308,7 +1263,8 @@
   //   detached:  P2
   //   docked:    P1  P3  P4 P5
   gfx::Point panel2_docked_position = panel2->GetBounds().origin();
-  DragPanelByDelta(panel2, drag_delta_to_detach);
+  gfx::Vector2d drag_delta_to_detach_panel2(-20, -100);
+  DragPanelByDelta(panel2, drag_delta_to_detach_panel2);
   ASSERT_EQ(1, detached_collection->num_panels());
   ASSERT_EQ(4, docked_collection->num_panels());
   EXPECT_EQ(PanelCollection::DOCKED, panel1->collection()->type());
@@ -1317,7 +1273,7 @@
   EXPECT_EQ(PanelCollection::DOCKED, panel4->collection()->type());
   EXPECT_EQ(PanelCollection::DOCKED, panel5->collection()->type());
   gfx::Point panel2_new_position =
-      panel2_docked_position + drag_delta_to_detach;
+      panel2_docked_position + drag_delta_to_detach_panel2;
   EXPECT_EQ(panel2_new_position, panel2->GetBounds().origin());
 
   // Drag to detach the left-most docked panel.
@@ -1325,7 +1281,8 @@
   //   detached:  P2  P4
   //   docked:    P1  P3  P5
   gfx::Point panel4_docked_position = panel4->GetBounds().origin();
-  DragPanelByDelta(panel4, drag_delta_to_detach);
+  gfx::Vector2d drag_delta_to_detach_panel4(-40, -250);
+  DragPanelByDelta(panel4, drag_delta_to_detach_panel4);
   ASSERT_EQ(2, detached_collection->num_panels());
   ASSERT_EQ(3, docked_collection->num_panels());
   EXPECT_EQ(PanelCollection::DOCKED, panel1->collection()->type());
@@ -1335,7 +1292,7 @@
   EXPECT_EQ(PanelCollection::DOCKED, panel5->collection()->type());
   EXPECT_EQ(panel2_new_position, panel2->GetBounds().origin());
   gfx::Point panel4_new_position =
-      panel4_docked_position + drag_delta_to_detach;
+      panel4_docked_position + drag_delta_to_detach_panel4;
   EXPECT_EQ(panel4_new_position, panel4->GetBounds().origin());
 
   // Drag to detach the right-most docked panel.
@@ -1344,8 +1301,8 @@
   //   docked:    P3  P5
   gfx::Point docked_position1 = panel1->GetBounds().origin();
   gfx::Point docked_position2 = panel3->GetBounds().origin();
-
-  DragPanelByDelta(panel1, drag_delta_to_detach);
+  gfx::Vector2d drag_delta_to_detach_panel1(-60, -400);
+  DragPanelByDelta(panel1, drag_delta_to_detach_panel1);
   ASSERT_EQ(3, detached_collection->num_panels());
   ASSERT_EQ(2, docked_collection->num_panels());
   EXPECT_EQ(PanelCollection::DETACHED, panel1->collection()->type());
@@ -1353,7 +1310,8 @@
   EXPECT_EQ(PanelCollection::DOCKED, panel3->collection()->type());
   EXPECT_EQ(PanelCollection::DETACHED, panel4->collection()->type());
   EXPECT_EQ(PanelCollection::DOCKED, panel5->collection()->type());
-  gfx::Point panel1_new_position = docked_position1 + drag_delta_to_detach;
+  gfx::Point panel1_new_position =
+      docked_position1 + drag_delta_to_detach_panel1;
   EXPECT_EQ(panel1_new_position, panel1->GetBounds().origin());
   EXPECT_EQ(panel2_new_position, panel2->GetBounds().origin());
   EXPECT_EQ(panel4_new_position, panel4->GetBounds().origin());
diff --git a/chrome/browser/ui/panels/panel_mouse_watcher_timer.cc b/chrome/browser/ui/panels/panel_mouse_watcher_timer.cc
index 029a835..0572eda 100644
--- a/chrome/browser/ui/panels/panel_mouse_watcher_timer.cc
+++ b/chrome/browser/ui/panels/panel_mouse_watcher_timer.cc
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/ui/panels/panel_mouse_watcher.h"
 #include "ui/gfx/screen.h"
 
diff --git a/chrome/browser/ui/panels/stacked_panel_browsertest.cc b/chrome/browser/ui/panels/stacked_panel_browsertest.cc
index e019ee2..dbc55e4 100644
--- a/chrome/browser/ui/panels/stacked_panel_browsertest.cc
+++ b/chrome/browser/ui/panels/stacked_panel_browsertest.cc
@@ -907,22 +907,15 @@
   panel_manager->CloseAll();
 }
 
-// http://crbug.com/240459 some panel tests are flaky on Linux/GTK.
-#if defined(TOOLKIT_GTK)
-#define MAYBE_AddNewPanelToGroupWithDetachedPanelWithCollapseToFit \
-    DISABLED_AddNewPanelToGroupWithDetachedPanelWithCollapseToFit
-#else
-#define MAYBE_AddNewPanelToGroupWithDetachedPanelWithCollapseToFit \
-    AddNewPanelToGroupWithDetachedPanelWithCollapseToFit
-#endif
 IN_PROC_BROWSER_TEST_F(StackedPanelBrowserTest,
-    MAYBE_AddNewPanelToGroupWithDetachedPanelWithCollapseToFit) {
+                       AddNewPanelToGroupWithDetachedPanelWithCollapseToFit) {
   PanelManager* panel_manager = PanelManager::GetInstance();
 
   // Create 2 detached panels.
   // Since P2 is active, it will not get collapsed when the new panel to stack
   // with needs the space.
-  Panel* panel1 = CreateDetachedPanel("1", gfx::Rect(100, 310, 200, 200));
+  Panel* panel1 =
+      CreateInactiveDetachedPanel("1", gfx::Rect(100, 310, 200, 200));
   Panel* panel2 = CreateDetachedPanel("2", gfx::Rect(300, 300, 150, 200));
   ASSERT_EQ(2, panel_manager->num_panels());
   ASSERT_EQ(0, panel_manager->num_stacks());
diff --git a/chrome/browser/ui/pdf/pdf_browsertest.cc b/chrome/browser/ui/pdf/pdf_browsertest.cc
index 1917021..e7b0c14 100644
--- a/chrome/browser/ui/pdf/pdf_browsertest.cc
+++ b/chrome/browser/ui/pdf/pdf_browsertest.cc
@@ -21,7 +21,7 @@
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test_utils.h"
-#include "net/test/spawned_test_server/spawned_test_server.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/base/clipboard/clipboard.h"
 #include "ui/gfx/codec/png_codec.h"
@@ -44,16 +44,19 @@
   PDFBrowserTest()
       : snapshot_different_(true),
         next_dummy_search_value_(0),
-        load_stop_notification_count_(0) {
-    pdf_test_server_.reset(new net::SpawnedTestServer(
-        net::SpawnedTestServer::TYPE_HTTP,
-        net::SpawnedTestServer::kLocalhost,
-        base::FilePath(FILE_PATH_LITERAL("pdf/test"))));
+        load_stop_notification_count_(0),
+        pdf_test_server_(
+            content::BrowserThread::GetMessageLoopProxyForThread(
+                content::BrowserThread::IO)) {
+    pdf_test_server_.ServeFilesFromDirectory(
+        base::FilePath(FILE_PATH_LITERAL("pdf/test")));
   }
 
  protected:
   // Use our own TestServer so that we can serve files from the pdf directory.
-  net::SpawnedTestServer* pdf_test_server() { return pdf_test_server_.get(); }
+  net::test_server::EmbeddedTestServer* pdf_test_server() {
+    return &pdf_test_server_;
+  }
 
   int load_stop_notification_count() const {
     return load_stop_notification_count_;
@@ -207,7 +210,7 @@
   // How many times we've seen chrome::LOAD_STOP.
   int load_stop_notification_count_;
 
-  scoped_ptr<net::SpawnedTestServer> pdf_test_server_;
+  net::test_server::EmbeddedTestServer pdf_test_server_;
 };
 
 #if defined(OS_CHROMEOS)
@@ -303,7 +306,7 @@
 // regressions.
 // If it flakes, reopen http://crbug.com/74548.
 IN_PROC_BROWSER_TEST_P(PDFBrowserTest, Loading) {
-  ASSERT_TRUE(pdf_test_server()->Start());
+  ASSERT_TRUE(pdf_test_server()->InitializeAndWaitUntilReady());
 
   NavigationController* controller =
       &(browser()->tab_strip_model()->GetActiveWebContents()->GetController());
@@ -311,7 +314,7 @@
   registrar.Add(this,
                 content::NOTIFICATION_LOAD_STOP,
                 content::Source<NavigationController>(controller));
-  std::string base_url = std::string("files/");
+  std::string base_url = std::string("/");
 
   base::FileEnumerator file_enumerator(
       ui_test_utils::GetTestFilePath(GetPDFTestDir(), base::FilePath()),
@@ -396,9 +399,9 @@
 
 // Flaky as per http://crbug.com/74549.
 IN_PROC_BROWSER_TEST_F(PDFBrowserTest, DISABLED_OnLoadAndReload) {
-  ASSERT_TRUE(pdf_test_server()->Start());
+  ASSERT_TRUE(pdf_test_server()->InitializeAndWaitUntilReady());
 
-  GURL url = pdf_test_server()->GetURL("files/onload_reload.html");
+  GURL url = pdf_test_server()->GetURL("/onload_reload.html");
   ui_test_utils::NavigateToURL(browser(), url);
 
   content::WindowedNotificationObserver observer(
diff --git a/chrome/browser/ui/screen_capture_notification_ui_win.cc b/chrome/browser/ui/screen_capture_notification_ui_win.cc
deleted file mode 100644
index 3841601..0000000
--- a/chrome/browser/ui/screen_capture_notification_ui_win.cc
+++ /dev/null
@@ -1,366 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/screen_capture_notification_ui.h"
-
-#include <windows.h>
-
-#include "base/compiler_specific.h"
-#include "base/i18n/rtl.h"
-#include "base/logging.h"
-#include "base/process_util.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/win/scoped_gdi_object.h"
-#include "base/win/scoped_hdc.h"
-#include "base/win/scoped_select_object.h"
-#include "chrome/app/chrome_dll_resource.h"
-#include "grit/generated_resources.h"
-#include "ui/base/l10n/l10n_util.h"
-
-namespace {
-
-// Maximum length of "Your desktop is shared with ..." message in UTF-16
-// characters.
-const size_t kMaxSharingWithTextLength = 100;
-
-const wchar_t kShellTrayWindowName[] = L"Shell_TrayWnd";
-const int kWindowBorderRadius = 14;
-
-} // namespace anonymous
-
-class ScreenCaptureNotificationUIWin : public ScreenCaptureNotificationUI {
- public:
-  ScreenCaptureNotificationUIWin();
-  virtual ~ScreenCaptureNotificationUIWin();
-
-  // ScreenCaptureNotificationUI interface.
-  virtual bool Show(const base::Closure& stop_callback,
-                    const string16& title) OVERRIDE;
-
- private:
-  static INT_PTR CALLBACK DialogProc(HWND hwnd, UINT message, WPARAM wparam,
-                                     LPARAM lparam);
-
-  BOOL OnDialogMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
-
-  // Creates the dialog window.
-  bool BeginDialog(const string16& title);
-
-  // Closes the dialog and invokes the disconnect callback, if set.
-  void EndDialog();
-
-  // Trys to position the dialog window above the taskbar.
-  void SetDialogPosition();
-
-  // Applies localization string and resizes the dialog.
-  bool UpdateStrings(const string16& title);
-
-  base::Closure stop_callback_;
-  HWND hwnd_;
-  base::win::ScopedGDIObject<HPEN> border_pen_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScreenCaptureNotificationUIWin);
-};
-
-static int GetControlTextWidth(HWND control) {
-  RECT rect = {0, 0, 0, 0};
-  WCHAR text[256];
-  int result = GetWindowText(control, text, arraysize(text));
-  if (result) {
-    base::win::ScopedGetDC dc(control);
-    base::win::ScopedSelectObject font(
-        dc, (HFONT)SendMessage(control, WM_GETFONT, 0, 0));
-    DrawText(dc, text, -1, &rect, DT_CALCRECT | DT_SINGLELINE);
-  }
-  return rect.right;
-}
-
-ScreenCaptureNotificationUIWin::ScreenCaptureNotificationUIWin()
-    : hwnd_(NULL),
-      border_pen_(CreatePen(PS_SOLID, 5,
-                            RGB(0.13 * 255, 0.69 * 255, 0.11 * 255))) {
-}
-
-ScreenCaptureNotificationUIWin::~ScreenCaptureNotificationUIWin() {
-  stop_callback_.Reset();
-  EndDialog();
-}
-
-bool ScreenCaptureNotificationUIWin::Show(
-    const base::Closure& stop_callback,
-    const string16& title) {
-  DCHECK(stop_callback_.is_null());
-  DCHECK(!stop_callback.is_null());
-
-  stop_callback_ = stop_callback;
-
-  if (BeginDialog(title)) {
-    return true;
-  } else {
-    stop_callback_ = stop_callback;
-    EndDialog();
-    return false;
-  }
-}
-
-INT_PTR CALLBACK ScreenCaptureNotificationUIWin::DialogProc(
-    HWND hwnd, UINT message,
-    WPARAM wparam, LPARAM lparam) {
-  LONG_PTR self = NULL;
-  if (message == WM_INITDIALOG) {
-    self = lparam;
-
-    // Store |this| to the window's user data.
-    SetLastError(ERROR_SUCCESS);
-    LONG_PTR result = SetWindowLongPtr(hwnd, DWLP_USER, self);
-    if (result == 0 && GetLastError() != ERROR_SUCCESS)
-      reinterpret_cast<ScreenCaptureNotificationUIWin*>(self)->EndDialog();
-  } else {
-    self = GetWindowLongPtr(hwnd, DWLP_USER);
-  }
-
-  if (self) {
-    return reinterpret_cast<ScreenCaptureNotificationUIWin*>(self)->
-        OnDialogMessage(hwnd, message, wparam, lparam);
-  }
-  return FALSE;
-}
-
-BOOL ScreenCaptureNotificationUIWin::OnDialogMessage(HWND hwnd, UINT message,
-                                          WPARAM wparam, LPARAM lparam) {
-  switch (message) {
-    // Ignore close messages.
-    case WM_CLOSE:
-      return TRUE;
-
-    // Handle the Stop button.
-    case WM_COMMAND:
-      switch (LOWORD(wparam)) {
-        case IDC_SCREEN_CAPTURE_STOP:
-          EndDialog();
-          return TRUE;
-      }
-      return FALSE;
-
-    // Ensure we don't try to use the HWND anymore.
-    case WM_DESTROY:
-      hwnd_ = NULL;
-
-      // Ensure that the stop callback is invoked even if somehow our window
-      // gets destroyed.
-      EndDialog();
-
-      return TRUE;
-
-    // Ensure the dialog stays visible if the work area dimensions change.
-    case WM_SETTINGCHANGE:
-      if (wparam == SPI_SETWORKAREA)
-        SetDialogPosition();
-      return TRUE;
-
-    // Ensure the dialog stays visible if the display dimensions change.
-    case WM_DISPLAYCHANGE:
-      SetDialogPosition();
-      return TRUE;
-
-    // Let the window be draggable by its client area by responding
-    // that the entire window is the title bar.
-    case WM_NCHITTEST:
-      SetWindowLongPtr(hwnd, DWLP_MSGRESULT, HTCAPTION);
-      return TRUE;
-
-    case WM_PAINT: {
-      PAINTSTRUCT ps;
-      HDC hdc = BeginPaint(hwnd_, &ps);
-      RECT rect;
-      GetClientRect(hwnd_, &rect);
-      {
-        base::win::ScopedSelectObject border(hdc, border_pen_);
-        base::win::ScopedSelectObject brush(hdc, GetStockObject(NULL_BRUSH));
-        RoundRect(hdc, rect.left, rect.top, rect.right - 1, rect.bottom - 1,
-                  kWindowBorderRadius, kWindowBorderRadius);
-      }
-      EndPaint(hwnd_, &ps);
-      return TRUE;
-    }
-  }
-  return FALSE;
-}
-
-bool ScreenCaptureNotificationUIWin::BeginDialog(const string16& title) {
-  DCHECK(!hwnd_);
-
-  // TODO(sergeyu): Currently this code relies on resources for the dialog. Fix
-  // it to work without resources.
-
-  // Load the dialog resource so that we can modify the RTL flags if necessary.
-  HMODULE module = base::GetModuleFromAddress(&DialogProc);
-  HRSRC dialog_resource = FindResource(
-      module, MAKEINTRESOURCE(IDD_SCREEN_CAPTURE_NOTIFICATION), RT_DIALOG);
-  if (!dialog_resource)
-    return false;
-
-  HGLOBAL dialog_template = LoadResource(module, dialog_resource);
-  if (!dialog_template)
-    return false;
-
-  DLGTEMPLATE* dialog_pointer =
-      reinterpret_cast<DLGTEMPLATE*>(LockResource(dialog_template));
-  if (!dialog_pointer)
-    return false;
-
-  // The actual resource type is DLGTEMPLATEEX, but this is not defined in any
-  // standard headers, so we treat it as a generic pointer and manipulate the
-  // correct offsets explicitly.
-  scoped_ptr<unsigned char[]> rtl_dialog_template;
-  if (base::i18n::IsRTL()) {
-    unsigned long dialog_template_size =
-        SizeofResource(module, dialog_resource);
-    rtl_dialog_template.reset(new unsigned char[dialog_template_size]);
-    memcpy(rtl_dialog_template.get(), dialog_pointer, dialog_template_size);
-    DWORD* rtl_dwords = reinterpret_cast<DWORD*>(rtl_dialog_template.get());
-    rtl_dwords[2] |= (WS_EX_LAYOUTRTL | WS_EX_RTLREADING);
-    dialog_pointer = reinterpret_cast<DLGTEMPLATE*>(rtl_dwords);
-  }
-
-  hwnd_ = CreateDialogIndirectParam(module, dialog_pointer, NULL,
-                                    DialogProc, reinterpret_cast<LPARAM>(this));
-  if (!hwnd_)
-    return false;
-
-  if (!UpdateStrings(title))
-    return false;
-
-  SetDialogPosition();
-  ShowWindow(hwnd_, SW_SHOW);
-  return IsWindowVisible(hwnd_) != FALSE;
-}
-
-void ScreenCaptureNotificationUIWin::EndDialog() {
-  if (hwnd_) {
-    DestroyWindow(hwnd_);
-    hwnd_ = NULL;
-  }
-
-  if (!stop_callback_.is_null()) {
-    stop_callback_.Run();
-    stop_callback_.Reset();
-  }
-}
-
-void ScreenCaptureNotificationUIWin::SetDialogPosition() {
-  // Try to center the window above the task-bar. If that fails, use the
-  // primary monitor. If that fails (very unlikely), use the default position.
-  HWND taskbar = FindWindow(kShellTrayWindowName, NULL);
-  HMONITOR monitor = MonitorFromWindow(taskbar, MONITOR_DEFAULTTOPRIMARY);
-  MONITORINFO monitor_info = {sizeof(monitor_info)};
-  RECT window_rect;
-  if (GetMonitorInfo(monitor, &monitor_info) &&
-      GetWindowRect(hwnd_, &window_rect)) {
-    int window_width = window_rect.right - window_rect.left;
-    int window_height = window_rect.bottom - window_rect.top;
-    int top = monitor_info.rcWork.bottom - window_height;
-    int left = (monitor_info.rcWork.right + monitor_info.rcWork.left -
-        window_width) / 2;
-    SetWindowPos(hwnd_, NULL, left, top, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
-  }
-}
-
-bool ScreenCaptureNotificationUIWin::UpdateStrings(const string16& title) {
-  string16 window_title =
-      l10n_util::GetStringFUTF16(IDS_MEDIA_SCREEN_CAPTURE_NOTIFICATION_TITLE,
-                                 title);
-  if (!SetWindowText(hwnd_, window_title.c_str()))
-    return false;
-
-  // Localize the disconnect button text and measure length of the old and new
-  // labels.
-  HWND stop_button = GetDlgItem(hwnd_, IDC_SCREEN_CAPTURE_STOP);
-  if (!stop_button)
-    return false;
-  int button_old_required_width = GetControlTextWidth(stop_button);
-  string16 button_label =
-      l10n_util::GetStringUTF16(IDS_MEDIA_SCREEN_CAPTURE_NOTIFICATION_STOP);
-  if (!SetWindowText(stop_button, button_label.c_str()))
-    return false;
-  int button_new_required_width = GetControlTextWidth(stop_button);
-  int button_width_delta =
-      button_new_required_width - button_old_required_width;
-
-  // Format and truncate "Your desktop is shared with ..." message.
-
-  string16 text = l10n_util::GetStringFUTF16(
-      IDS_MEDIA_SCREEN_CAPTURE_NOTIFICATION_TEXT, title);
-  if (text.length() > kMaxSharingWithTextLength)
-    text.erase(kMaxSharingWithTextLength);
-
-  // Set localized and truncated "Your desktop is shared with ..." message and
-  // measure length of the old and new text.
-  HWND sharing_with_label = GetDlgItem(hwnd_, IDC_SCREEN_CAPTURE_TEXT);
-  if (!sharing_with_label)
-    return false;
-  int label_old_required_width = GetControlTextWidth(sharing_with_label);
-  if (!SetWindowText(sharing_with_label, text.c_str()))
-    return false;
-  int label_new_required_width = GetControlTextWidth(sharing_with_label);
-  int label_width_delta = label_new_required_width - label_old_required_width;
-
-  // Reposition the controls such that the label lies to the left of the
-  // disconnect button (assuming LTR layout). The dialog template determines
-  // the controls' spacing; update their size to fit the localized content.
-  RECT label_rect;
-  if (!GetClientRect(sharing_with_label, &label_rect))
-    return false;
-  if (!SetWindowPos(sharing_with_label, NULL, 0, 0,
-                    label_rect.right + label_width_delta, label_rect.bottom,
-                    SWP_NOMOVE | SWP_NOZORDER)) {
-    return false;
-  }
-
-  // Reposition the disconnect button as well.
-  RECT button_rect;
-  if (!GetWindowRect(stop_button, &button_rect))
-    return false;
-  int button_width = button_rect.right - button_rect.left;
-  int button_height = button_rect.bottom - button_rect.top;
-  SetLastError(ERROR_SUCCESS);
-  int result = MapWindowPoints(HWND_DESKTOP, hwnd_,
-                               reinterpret_cast<LPPOINT>(&button_rect), 2);
-  if (!result && GetLastError() != ERROR_SUCCESS)
-    return false;
-  if (!SetWindowPos(stop_button, NULL,
-                    button_rect.left + label_width_delta, button_rect.top,
-                    button_width + button_width_delta, button_height,
-                    SWP_NOZORDER)) {
-    return false;
-  }
-
-  // Resize the whole window to fit the resized controls.
-  RECT window_rect;
-  if (!GetWindowRect(hwnd_, &window_rect))
-    return false;
-  int width = (window_rect.right - window_rect.left) +
-      button_width_delta + label_width_delta;
-  int height = window_rect.bottom - window_rect.top;
-  if (!SetWindowPos(hwnd_, NULL, 0, 0, width, height,
-                    SWP_NOMOVE | SWP_NOZORDER)) {
-    return false;
-  }
-
-  // Make the corners of the disconnect window rounded.
-  HRGN rgn = CreateRoundRectRgn(0, 0, width, height, kWindowBorderRadius,
-                                kWindowBorderRadius);
-  if (!rgn)
-    return false;
-  if (!SetWindowRgn(hwnd_, rgn, TRUE))
-    return false;
-
-  return true;
-}
-
-scoped_ptr<ScreenCaptureNotificationUI> ScreenCaptureNotificationUI::Create() {
-  return scoped_ptr<ScreenCaptureNotificationUI>(
-      new ScreenCaptureNotificationUIWin());
-}
diff --git a/chrome/browser/ui/search/instant_commit_type.h b/chrome/browser/ui/search/instant_commit_type.h
deleted file mode 100644
index 3ead857..0000000
--- a/chrome/browser/ui/search/instant_commit_type.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_SEARCH_INSTANT_COMMIT_TYPE_H_
-#define CHROME_BROWSER_UI_SEARCH_INSTANT_COMMIT_TYPE_H_
-
-// Reason why the Instant overlay is committed (merged into a tab).
-enum InstantCommitType {
-  // The commit is due to the user pressing Enter from the omnibox.
-  INSTANT_COMMIT_PRESSED_ENTER,
-
-  // The commit is due to the user pressing Alt-Enter from the omnibox (which
-  // causes the overlay to be committed onto a new tab).
-  INSTANT_COMMIT_PRESSED_ALT_ENTER,
-
-  // The commit is due to the omnibox losing focus, usually due to the user
-  // clicking on the overlay.
-  INSTANT_COMMIT_FOCUS_LOST,
-
-  // The commit is due to the Instant overlay navigating to a non-Instant URL.
-  INSTANT_COMMIT_NAVIGATED,
-};
-
-#endif  // CHROME_BROWSER_UI_SEARCH_INSTANT_COMMIT_TYPE_H_
diff --git a/chrome/browser/ui/search/instant_controller.cc b/chrome/browser/ui/search/instant_controller.cc
index c861a1c..a3f465b 100644
--- a/chrome/browser/ui/search/instant_controller.cc
+++ b/chrome/browser/ui/search/instant_controller.cc
@@ -4,22 +4,13 @@
 
 #include "chrome/browser/ui/search/instant_controller.h"
 
-#include <iterator>
-
 #include "base/metrics/histogram.h"
 #include "base/prefs/pref_service.h"
-#include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/autocomplete/autocomplete_provider.h"
-#include "chrome/browser/autocomplete/autocomplete_result.h"
-#include "chrome/browser/autocomplete/search_provider.h"
 #include "chrome/browser/content_settings/content_settings_provider.h"
 #include "chrome/browser/content_settings/host_content_settings_map.h"
-#include "chrome/browser/history/history_service.h"
-#include "chrome/browser/history/history_service_factory.h"
-#include "chrome/browser/history/history_tab_helper.h"
 #include "chrome/browser/platform_util.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search/instant_service.h"
 #include "chrome/browser/search/instant_service_factory.h"
 #include "chrome/browser/search/search.h"
@@ -28,7 +19,6 @@
 #include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/browser/ui/browser_instant_controller.h"
 #include "chrome/browser/ui/search/instant_ntp.h"
-#include "chrome/browser/ui/search/instant_overlay.h"
 #include "chrome/browser/ui/search/instant_tab.h"
 #include "chrome/browser/ui/search/search_tab_helper.h"
 #include "chrome/common/chrome_notification_types.h"
@@ -46,7 +36,6 @@
 #include "content/public/browser/web_contents_view.h"
 #include "net/base/escape.h"
 #include "net/base/network_change_notifier.h"
-#include "third_party/icu/public/common/unicode/normalizer2.h"
 
 #if defined(TOOLKIT_VIEWS)
 #include "ui/views/widget/widget.h"
@@ -54,11 +43,6 @@
 
 namespace {
 
-// An artificial delay (in milliseconds) we introduce before telling the Instant
-// page about the new omnibox bounds, in cases where the bounds shrink. This is
-// to avoid the page jumping up/down very fast in response to bounds changes.
-const int kUpdateBoundsDelayMS = 1000;
-
 // For reporting Instant navigations.
 enum InstantNavigation {
   INSTANT_NAVIGATION_LOCAL_CLICK = 0,
@@ -85,128 +69,6 @@
                             INSTANT_NAVIGATION_MAX);
 }
 
-void RecordFallbackReasonHistogram(
-    const InstantController::InstantFallbackReason fallback_reason) {
-  UMA_HISTOGRAM_ENUMERATION("InstantExtended.FallbackToLocalOverlay",
-                            fallback_reason,
-                            InstantController::INSTANT_FALLBACK_MAX);
-}
-
-InstantController::InstantFallbackReason DetermineFallbackReason(
-    const InstantPage* page, std::string instant_url) {
-  InstantController::InstantFallbackReason fallback_reason;
-  if (!page) {
-    fallback_reason = InstantController::INSTANT_FALLBACK_NO_OVERLAY;
-  } else if (instant_url.empty()) {
-    fallback_reason = InstantController::INSTANT_FALLBACK_INSTANT_URL_EMPTY;
-  } else if (!chrome::MatchesOriginAndPath(GURL(page->instant_url()),
-                                           GURL(instant_url))) {
-    fallback_reason = InstantController::INSTANT_FALLBACK_ORIGIN_PATH_MISMATCH;
-  } else if (!page->supports_instant()) {
-    fallback_reason = InstantController::INSTANT_FALLBACK_INSTANT_NOT_SUPPORTED;
-  } else {
-    fallback_reason = InstantController::INSTANT_FALLBACK_UNKNOWN;
-  }
-  return fallback_reason;
-}
-
-void AddSessionStorageHistogram(bool extended_enabled,
-                                const content::WebContents* tab1,
-                                const content::WebContents* tab2) {
-  base::HistogramBase* histogram = base::BooleanHistogram::FactoryGet(
-      std::string("Instant.SessionStorageNamespace") +
-          (extended_enabled ? "_Extended" : "_Instant"),
-      base::HistogramBase::kUmaTargetedHistogramFlag);
-  const content::SessionStorageNamespaceMap& session_storage_map1 =
-      tab1->GetController().GetSessionStorageNamespaceMap();
-  const content::SessionStorageNamespaceMap& session_storage_map2 =
-      tab2->GetController().GetSessionStorageNamespaceMap();
-  bool is_session_storage_the_same =
-      session_storage_map1.size() == session_storage_map2.size();
-  if (is_session_storage_the_same) {
-    // The size is the same, so let's check that all entries match.
-    for (content::SessionStorageNamespaceMap::const_iterator
-             it1 = session_storage_map1.begin(),
-             it2 = session_storage_map2.begin();
-         it1 != session_storage_map1.end() && it2 != session_storage_map2.end();
-         ++it1, ++it2) {
-      if (it1->first != it2->first || it1->second.get() != it2->second.get()) {
-        is_session_storage_the_same = false;
-        break;
-      }
-    }
-  }
-  histogram->AddBoolean(is_session_storage_the_same);
-}
-
-string16 Normalize(const string16& str) {
-  UErrorCode status = U_ZERO_ERROR;
-  const icu::Normalizer2* normalizer =
-      icu::Normalizer2::getInstance(NULL, "nfkc_cf", UNORM2_COMPOSE, status);
-  if (normalizer == NULL || U_FAILURE(status))
-    return str;
-  icu::UnicodeString norm_str(normalizer->normalize(
-      icu::UnicodeString(FALSE, str.c_str(), str.size()), status));
-  if (U_FAILURE(status))
-    return str;
-  return string16(norm_str.getBuffer(), norm_str.length());
-}
-
-bool NormalizeAndStripPrefix(string16* text, const string16& prefix) {
-  string16 norm_prefix = Normalize(prefix);
-  string16 norm_text = Normalize(*text);
-  if (norm_prefix.size() <= norm_text.size() &&
-      norm_text.compare(0, norm_prefix.size(), norm_prefix) == 0) {
-    *text = norm_text.erase(0, norm_prefix.size());
-    return true;
-  }
-  return false;
-}
-
-// For TOOLKIT_VIEWS, the top level widget is always focused. If the focus
-// change originated in views determine the child Widget from the view that is
-// being focused.
-gfx::NativeView GetViewGainingFocus(gfx::NativeView view_gaining_focus) {
-#if defined(TOOLKIT_VIEWS)
-  views::Widget* widget = view_gaining_focus ?
-      views::Widget::GetWidgetForNativeView(view_gaining_focus) : NULL;
-  if (widget) {
-    views::FocusManager* focus_manager = widget->GetFocusManager();
-    if (focus_manager && focus_manager->is_changing_focus() &&
-        focus_manager->GetFocusedView() &&
-        focus_manager->GetFocusedView()->GetWidget())
-      return focus_manager->GetFocusedView()->GetWidget()->GetNativeView();
-  }
-#endif
-  return view_gaining_focus;
-}
-
-// Returns true if |view| is the top-level contents view or a child view in the
-// view hierarchy of |contents|.
-bool IsViewInContents(gfx::NativeView view, content::WebContents* contents) {
-  content::RenderWidgetHostView* rwhv = contents->GetRenderWidgetHostView();
-  if (!view || !rwhv)
-    return false;
-
-  gfx::NativeView tab_view = contents->GetView()->GetNativeView();
-  if (view == rwhv->GetNativeView() || view == tab_view)
-    return true;
-
-  // Walk up the view hierarchy to determine if the view is a subview of the
-  // WebContents view (such as a windowed plugin or http auth dialog).
-  while (view) {
-    view = platform_util::GetParent(view);
-    if (view == tab_view)
-      return true;
-  }
-
-  return false;
-}
-
-bool IsFullHeight(const InstantOverlayModel& model) {
-  return model.height() == 100 && model.height_units() == INSTANT_SIZE_PERCENT;
-}
-
 bool IsContentsFrom(const InstantPage* page,
                     const content::WebContents* contents) {
   return page && (page->contents() == contents);
@@ -256,300 +118,31 @@
                                      bool extended_enabled)
     : browser_(browser),
       extended_enabled_(extended_enabled),
-      instant_enabled_(false),
-      use_local_page_only_(true),
-      preload_ntp_(true),
-      model_(this),
-      use_tab_for_suggestions_(false),
-      last_omnibox_text_has_inline_autocompletion_(false),
-      last_verbatim_(false),
-      last_transition_type_(content::PAGE_TRANSITION_LINK),
-      last_match_was_search_(false),
       omnibox_focus_state_(OMNIBOX_FOCUS_NONE),
       omnibox_focus_change_reason_(OMNIBOX_FOCUS_CHANGE_EXPLICIT),
-      omnibox_bounds_(-1, -1, 0, 0),
-      allow_overlay_to_show_search_suggestions_(false) {
+      omnibox_bounds_(-1, -1, 0, 0) {
 
   // When the InstantController lives, the InstantService should live.
   // InstantService sets up profile-level facilities such as the ThemeSource for
   // the NTP.
   // However, in some tests, browser_ may be null.
-  if (browser_)
-    InstantServiceFactory::GetForProfile(browser_->profile());
+  if (browser_) {
+    InstantService* instant_service = GetInstantService();
+    instant_service->AddObserver(this);
+  }
 }
 
 InstantController::~InstantController() {
-}
-
-void InstantController::OnAutocompleteStart() {
-  if (UseTabForSuggestions() && instant_tab_->supports_instant()) {
-    LOG_INSTANT_DEBUG_EVENT(
-        this, "OnAutocompleteStart: using InstantTab");
-    return;
+  if (browser_) {
+    InstantService* instant_service = GetInstantService();
+    instant_service->RemoveObserver(this);
   }
-
-  // Not using |instant_tab_|. Check if overlay is OK to use.
-  InstantFallbackReason fallback_reason = ShouldSwitchToLocalOverlay();
-  if (fallback_reason != INSTANT_FALLBACK_NONE) {
-    ResetOverlay(GetLocalInstantURL());
-    RecordFallbackReasonHistogram(fallback_reason);
-    LOG_INSTANT_DEBUG_EVENT(
-        this, "OnAutocompleteStart: switching to local overlay");
-  } else {
-    LOG_INSTANT_DEBUG_EVENT(
-        this, "OnAutocompleteStart: using existing overlay");
-  }
-  use_tab_for_suggestions_ = false;
-}
-
-bool InstantController::Update(const AutocompleteMatch& match,
-                               const string16& user_text,
-                               const string16& full_text,
-                               size_t selection_start,
-                               size_t selection_end,
-                               bool verbatim,
-                               bool user_input_in_progress,
-                               bool omnibox_popup_is_open,
-                               bool escape_pressed,
-                               bool is_keyword_search) {
-  if (!extended_enabled() && !instant_enabled_)
-    return false;
-
-  LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf(
-      "Update: %s user_text='%s' full_text='%s' selection_start=%d "
-      "selection_end=%d verbatim=%d typing=%d popup=%d escape_pressed=%d "
-      "is_keyword_search=%d",
-      AutocompleteMatchType::ToString(match.type).c_str(),
-      UTF16ToUTF8(user_text).c_str(), UTF16ToUTF8(full_text).c_str(),
-      static_cast<int>(selection_start), static_cast<int>(selection_end),
-      verbatim, user_input_in_progress, omnibox_popup_is_open, escape_pressed,
-      is_keyword_search));
-
-  // Store the current |last_omnibox_text_| and update |last_omnibox_text_|
-  // upfront with the contents of |full_text|. Even if we do an early return,
-  // |last_omnibox_text_| will be updated.
-  string16 previous_omnibox_text = last_omnibox_text_;
-  last_omnibox_text_ = full_text;
-  last_match_was_search_ = AutocompleteMatch::IsSearchType(match.type) &&
-                           !user_text.empty();
-
-  // TODO(dhollowa): Complete keyword match UI.  For now just hide suggestions.
-  // http://crbug.com/153932.  Note, this early escape is happens prior to the
-  // DCHECKs below because |user_text| and |full_text| have different semantics
-  // when keyword search is in effect.
-  if (is_keyword_search) {
-    if (UseTabForSuggestions())
-      instant_tab_->Update(string16(), 0, 0, true);
-    else
-      HideOverlay();
-    last_match_was_search_ = false;
-    last_suggestion_ = InstantSuggestion();
-    return false;
-  }
-
-  // Ignore spurious updates when the omnibox is blurred; otherwise click
-  // targets on the page may vanish before a click event arrives.
-  if (omnibox_focus_state_ == OMNIBOX_FOCUS_NONE)
-    return false;
-
-  // If the popup is open, the user has to be typing.
-  DCHECK(!omnibox_popup_is_open || user_input_in_progress);
-
-  // If the popup is closed, there should be no inline autocompletion.
-  DCHECK(omnibox_popup_is_open || user_text.empty() || user_text == full_text)
-      << user_text << "|" << full_text;
-
-  // If there's no text in the omnibox, the user can't have typed any.
-  DCHECK(!full_text.empty() || user_text.empty()) << user_text;
-
-  // If the user isn't typing, and the popup is closed, there can't be any
-  // user-typed text.
-  DCHECK(user_input_in_progress || omnibox_popup_is_open || user_text.empty())
-      << user_text;
-
-  // The overlay is being clicked and will commit soon. Don't change anything.
-  // TODO(sreeram): Add a browser test for this.
-  if (overlay_ && overlay_->is_pointer_down_from_activate())
-    return false;
-
-  // In non-extended mode, SearchModeChanged() is never called, so fake it. The
-  // mode is set to "disallow suggestions" here, so that if one of the early
-  // "return false" conditions is hit, suggestions will be disallowed. If the
-  // query is sent to the overlay, the mode is set to "allow" further below.
-  if (!extended_enabled())
-    search_mode_.mode = SearchMode::MODE_DEFAULT;
-
-  // In non extended mode, Instant is disabled for URLs and keyword mode.
-  if (!extended_enabled() &&
-      (!last_match_was_search_ ||
-       match.type == AutocompleteMatchType::SEARCH_OTHER_ENGINE)) {
-    HideOverlay();
-    return false;
-  }
-
-  if (!UseTabForSuggestions() && !overlay_) {
-    HideOverlay();
-    return false;
-  }
-
-  if (extended_enabled()) {
-    if (!omnibox_popup_is_open) {
-      if (!user_input_in_progress) {
-        // If the user isn't typing and the omnibox popup is closed, it means a
-        // regular navigation, tab-switch or the user hitting Escape.
-        if (UseTabForSuggestions()) {
-          // The user is on a search results page. It may be showing results for
-          // a partial query the user typed before they hit Escape. Send the
-          // omnibox text to the page to restore the original results.
-          //
-          // In a tab switch, |instant_tab_| won't have updated yet, so it may
-          // be pointing to the previous tab (which was a search results page).
-          // Ensure we don't send the omnibox text to a random webpage (the new
-          // tab), by comparing the old and new WebContents.
-          if (escape_pressed &&
-              instant_tab_->contents() == browser_->GetActiveWebContents()) {
-            // TODO(kmadhusu): If the |full_text| is not empty, send an
-            // onkeypress(esc) to the Instant page. Do not call
-            // onsubmit(full_text). Fix.
-            if (full_text.empty()) {
-              // Call onchange("") to clear the query for the page.
-              instant_tab_->Update(string16(), 0, 0, true);
-              instant_tab_->EscKeyPressed();
-             } else {
-              instant_tab_->Submit(full_text);
-            }
-          }
-        } else if (!full_text.empty()) {
-          // If |full_text| is empty, the user is on the NTP. The overlay may
-          // be showing custom NTP content; hide only if that's not the case.
-          HideOverlay();
-        }
-      } else if (full_text.empty()) {
-        // The user is typing, and backspaced away all omnibox text. Clear
-        // |last_omnibox_text_| so that we don't attempt to set suggestions.
-        last_omnibox_text_.clear();
-        last_user_text_.clear();
-        last_suggestion_ = InstantSuggestion();
-        if (UseTabForSuggestions()) {
-          // On a search results page, tell it to clear old results.
-          instant_tab_->Update(string16(), 0, 0, true);
-        } else if (search_mode_.is_origin_ntp()) {
-          // On the NTP, tell the overlay to clear old results. Don't hide the
-          // overlay so it can show a blank page or logo if it wants.
-          overlay_->Update(string16(), 0, 0, true);
-        } else {
-          HideOverlay();
-        }
-      } else {
-        // The user switched to a tab with partial text already in the omnibox.
-        HideOverlay();
-
-        // The new tab may or may not be a search results page; we don't know
-        // since SearchModeChanged() hasn't been called yet. If it later turns
-        // out to be, we should store |full_text| now, so that if the user hits
-        // Enter, we'll send the correct query to instant_tab_->Submit(). If the
-        // partial text is not a query (|last_match_was_search_| is false), we
-        // won't Submit(), so no need to worry about that.
-        last_user_text_ = user_text;
-        last_suggestion_ = InstantSuggestion();
-      }
-      return false;
-    } else if (full_text.empty()) {
-      // The user typed a solitary "?". Same as the backspace case above.
-      last_omnibox_text_.clear();
-      last_user_text_.clear();
-      last_suggestion_ = InstantSuggestion();
-      if (UseTabForSuggestions())
-        instant_tab_->Update(string16(), 0, 0, true);
-      else if (search_mode_.is_origin_ntp())
-        overlay_->Update(string16(), 0, 0, true);
-      else
-        HideOverlay();
-      return false;
-    }
-  } else if (!omnibox_popup_is_open || full_text.empty()) {
-    // In the non-extended case, hide the overlay as long as the user isn't
-    // actively typing a non-empty query.
-    HideOverlay();
-    return false;
-  }
-
-  last_omnibox_text_has_inline_autocompletion_ = user_text != full_text;
-
-  // If the user continues typing the same query as the suggested text is
-  // showing, reuse the suggestion (but only for INSTANT_COMPLETE_NEVER).
-  bool reused_suggestion = false;
-  if (last_suggestion_.behavior == INSTANT_COMPLETE_NEVER &&
-      !last_omnibox_text_has_inline_autocompletion_) {
-    if (StartsWith(previous_omnibox_text, full_text, false))  {
-      // The user is backspacing away characters.
-      last_suggestion_.text.insert(0, previous_omnibox_text, full_text.size(),
-          previous_omnibox_text.size() - full_text.size());
-      reused_suggestion = true;
-    } else if (StartsWith(full_text, previous_omnibox_text, false)) {
-      // The user is typing forward. Normalize any added characters.
-      reused_suggestion = NormalizeAndStripPrefix(&last_suggestion_.text,
-          string16(full_text, previous_omnibox_text.size()));
-    }
-  }
-  if (!reused_suggestion)
-    last_suggestion_ = InstantSuggestion();
-
-  // TODO(kmadhusu): Investigate whether it's possible to update
-  // |last_user_text_| at the beginning of this function.
-  last_user_text_ = user_text;
-
-  if (!extended_enabled()) {
-    // In non-extended mode, the query is verbatim if there's any selection
-    // (including inline autocompletion) or if the cursor is not at the end.
-    verbatim = verbatim || selection_start != selection_end ||
-                           selection_start != full_text.size();
-  }
-  last_verbatim_ = verbatim;
-
-  last_transition_type_ = match.transition;
-  url_for_history_ = match.destination_url;
-
-  // Allow search suggestions. In extended mode, SearchModeChanged() will set
-  // this, but it's not called in non-extended mode, so fake it.
-  if (!extended_enabled())
-    search_mode_.mode = SearchMode::MODE_SEARCH_SUGGESTIONS;
-
-  if (UseTabForSuggestions()) {
-    instant_tab_->Update(user_text, selection_start, selection_end, verbatim);
-  } else {
-    allow_overlay_to_show_search_suggestions_ = true;
-
-    overlay_->Update(extended_enabled() ? user_text : full_text,
-                     selection_start, selection_end, verbatim);
-  }
-
-  content::NotificationService::current()->Notify(
-      chrome::NOTIFICATION_INSTANT_CONTROLLER_UPDATED,
-      content::Source<InstantController>(this),
-      content::NotificationService::NoDetails());
-
-  // We don't have new suggestions yet, but we can either reuse the existing
-  // suggestion or reset the existing "gray text".
-  browser_->SetInstantSuggestion(last_suggestion_);
-
-  // Record the time of the first keypress for logging histograms.
-  if (!first_interaction_time_recorded_ && first_interaction_time_.is_null())
-    first_interaction_time_ = base::Time::Now();
-
-  return true;
-}
-
-bool InstantController::WillFetchCompletions() const {
-  if (!extended_enabled())
-    return false;
-
-  return !UsingLocalPage();
 }
 
 scoped_ptr<content::WebContents> InstantController::ReleaseNTPContents() {
   if (!extended_enabled() || !browser_->profile() ||
-      browser_->profile()->IsOffTheRecord())
+      browser_->profile()->IsOffTheRecord() ||
+      !chrome::ShouldShowInstantNTP())
     return scoped_ptr<content::WebContents>();
 
   LOG_INSTANT_DEBUG_EVENT(this, "ReleaseNTPContents");
@@ -560,199 +153,32 @@
   scoped_ptr<content::WebContents> ntp_contents = ntp_->ReleaseContents();
 
   // Preload a new Instant NTP.
-  if (preload_ntp_)
-    ResetNTP(GetInstantURL());
-  else
-    ntp_.reset();
+  ResetNTP(GetInstantURL());
 
   return ntp_contents.Pass();
 }
 
-// TODO(tonyg): This method only fires when the omnibox bounds change. It also
-// needs to fire when the overlay bounds change (e.g.: open/close info bar).
-void InstantController::SetPopupBounds(const gfx::Rect& bounds) {
-  if (!extended_enabled() && !instant_enabled_)
-    return;
-
-  if (popup_bounds_ == bounds)
-    return;
-
-  popup_bounds_ = bounds;
-  if (popup_bounds_.height() > last_popup_bounds_.height()) {
-    update_bounds_timer_.Stop();
-    SendPopupBoundsToPage();
-  } else if (!update_bounds_timer_.IsRunning()) {
-    update_bounds_timer_.Start(FROM_HERE,
-        base::TimeDelta::FromMilliseconds(kUpdateBoundsDelayMS), this,
-        &InstantController::SendPopupBoundsToPage);
-  }
-}
-
 void InstantController::SetOmniboxBounds(const gfx::Rect& bounds) {
   if (!extended_enabled() || omnibox_bounds_ == bounds)
     return;
 
   omnibox_bounds_ = bounds;
-  if (overlay_)
-    overlay_->SetOmniboxBounds(omnibox_bounds_);
   if (ntp_)
-    ntp_->SetOmniboxBounds(omnibox_bounds_);
+    ntp_->sender()->SetOmniboxBounds(omnibox_bounds_);
   if (instant_tab_)
-    instant_tab_->SetOmniboxBounds(omnibox_bounds_);
-}
-
-void InstantController::HandleAutocompleteResults(
-    const std::vector<AutocompleteProvider*>& providers,
-    const AutocompleteResult& autocomplete_result) {
-  if (!extended_enabled())
-    return;
-
-  if (!UseTabForSuggestions() && !overlay_)
-    return;
-
-  // The omnibox sends suggestions when its possibly imaginary popup closes
-  // as it stops autocomplete. Ignore these.
-  if (omnibox_focus_state_ == OMNIBOX_FOCUS_NONE)
-    return;
-
-  for (ACProviders::const_iterator provider = providers.begin();
-       provider != providers.end(); ++provider) {
-    const bool from_search_provider =
-        (*provider)->type() == AutocompleteProvider::TYPE_SEARCH;
-
-    // TODO(jeremycho): Pass search_provider() as a parameter to this function
-    // and remove the static cast.
-    const bool provider_done = from_search_provider ?
-        static_cast<SearchProvider*>(*provider)->IsNonInstantSearchDone() :
-        (*provider)->done();
-    if (!provider_done) {
-      DVLOG(1) << "Waiting for " << (*provider)->GetName();
-      return;
-    }
-  }
-
-  DVLOG(1) << "AutocompleteResults:";
-  std::vector<InstantAutocompleteResult> results;
-  if (UsingLocalPage()) {
-    for (AutocompleteResult::const_iterator match(autocomplete_result.begin());
-         match != autocomplete_result.end(); ++match) {
-      InstantAutocompleteResult result;
-      PopulateInstantAutocompleteResultFromMatch(
-          *match, std::distance(autocomplete_result.begin(), match), &result);
-      results.push_back(result);
-    }
-  } else {
-    for (ACProviders::const_iterator provider = providers.begin();
-         provider != providers.end(); ++provider) {
-      for (ACMatches::const_iterator match = (*provider)->matches().begin();
-           match != (*provider)->matches().end(); ++match) {
-        // When the top match is an inline history URL, the page calls
-        // SetSuggestions(url) which calls FinalizeInstantQuery() in
-        // SearchProvider creating a NAVSUGGEST match for the URL. If we sent
-        // this NAVSUGGEST match back to the page, it would be deduped against
-        // the original history match and replace it. But since the page ignores
-        // SearchProvider suggestions, the match would then disappear. Yuck.
-        // TODO(jered): Remove this when FinalizeInstantQuery() is ripped out.
-        if ((*provider)->type() == AutocompleteProvider::TYPE_SEARCH &&
-            match->type == AutocompleteMatchType::NAVSUGGEST) {
-          continue;
-        }
-        InstantAutocompleteResult result;
-        PopulateInstantAutocompleteResultFromMatch(*match, kNoMatchIndex,
-                                                   &result);
-        results.push_back(result);
-      }
-    }
-  }
-  LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf(
-      "HandleAutocompleteResults: total_results=%d",
-      static_cast<int>(results.size())));
-
-  if (UseTabForSuggestions())
-    instant_tab_->SendAutocompleteResults(results);
-  else
-    overlay_->SendAutocompleteResults(results);
-
-  content::NotificationService::current()->Notify(
-      chrome::NOTIFICATION_INSTANT_SENT_AUTOCOMPLETE_RESULTS,
-      content::Source<InstantController>(this),
-      content::NotificationService::NoDetails());
+    instant_tab_->sender()->SetOmniboxBounds(omnibox_bounds_);
 }
 
 void InstantController::OnDefaultSearchProviderChanged() {
   if (ntp_ && extended_enabled()) {
     ntp_.reset();
-    if (preload_ntp_)
-      ResetNTP(GetInstantURL());
+    ResetNTP(GetInstantURL());
   }
-
-  // Do not reload the overlay if it's actually the local overlay.
-  if (overlay_ && !overlay_->IsLocal()) {
-    overlay_.reset();
-    if (extended_enabled() || instant_enabled_) {
-      // Try to create another overlay immediately so that it is ready for the
-      // next user interaction.
-      ResetOverlay(GetInstantURL());
-    }
-  }
-}
-
-bool InstantController::OnUpOrDownKeyPressed(int count) {
-  if (!extended_enabled())
-    return false;
-
-  if (!UseTabForSuggestions() && !overlay_)
-    return false;
-
-  if (UseTabForSuggestions())
-    instant_tab_->UpOrDownKeyPressed(count);
-  else
-    overlay_->UpOrDownKeyPressed(count);
-
-  return true;
-}
-
-void InstantController::OnCancel(const AutocompleteMatch& match,
-                                 const string16& user_text,
-                                 const string16& full_text) {
-  if (!extended_enabled())
-    return;
-
-  if (!UseTabForSuggestions() && !overlay_)
-    return;
-
-  // We manually reset the state here since the JS is not expected to do it.
-  // TODO(sreeram): Handle the case where user_text is now a URL
-  last_match_was_search_ = AutocompleteMatch::IsSearchType(match.type) &&
-                           !full_text.empty();
-  last_omnibox_text_ = full_text;
-  last_user_text_ = user_text;
-  last_suggestion_ = InstantSuggestion();
-
-  // Say |full_text| is "amazon.com" and |user_text| is "ama". This means the
-  // inline autocompletion is "zon.com"; so the selection should span from
-  // user_text.size() to full_text.size(). The selection bounds are inverted
-  // because the caret is at the end of |user_text|, not |full_text|.
-  if (UseTabForSuggestions()) {
-    instant_tab_->CancelSelection(user_text, full_text.size(), user_text.size(),
-                                  last_verbatim_);
-  } else {
-    overlay_->CancelSelection(user_text, full_text.size(), user_text.size(),
-                              last_verbatim_);
-  }
-}
-
-void InstantController::OmniboxNavigateToURL() {
-  RecordNavigationHistogram(UsingLocalPage(), false, extended_enabled());
-  if (!extended_enabled())
-    return;
-  if (UseTabForSuggestions())
-    instant_tab_->Submit(string16());
 }
 
 void InstantController::ToggleVoiceSearch() {
   if (instant_tab_)
-    instant_tab_->ToggleVoiceSearch();
+    instant_tab_->sender()->ToggleVoiceSearch();
 }
 
 void InstantController::InstantPageLoadFailed(content::WebContents* contents) {
@@ -787,35 +213,21 @@
     DeletePageSoon(ntp_.Pass());
     if (!is_local)
       ResetNTP(GetLocalInstantURL());
-  } else if (IsContentsFrom(overlay(), contents)) {
-    LOG_INSTANT_DEBUG_EVENT(this, "InstantPageLoadFailed: overlay");
-    bool is_local = overlay_->IsLocal();
-    DeletePageSoon(overlay_.Pass());
-    if (!is_local)
-      ResetOverlay(GetLocalInstantURL());
+  } else {
+    NOTREACHED();
   }
 }
 
-content::WebContents* InstantController::GetOverlayContents() const {
-  return overlay_ ? overlay_->contents() : NULL;
-}
-
 content::WebContents* InstantController::GetNTPContents() const {
   return ntp_ ? ntp_->contents() : NULL;
 }
 
-bool InstantController::IsOverlayingSearchResults() const {
-  return model_.mode().is_search_suggestions() && IsFullHeight(model_) &&
-         (last_match_was_search_ ||
-          last_suggestion_.behavior == INSTANT_COMPLETE_NEVER);
-}
-
 bool InstantController::SubmitQuery(const string16& search_terms) {
   if (extended_enabled() && instant_tab_ && instant_tab_->supports_instant() &&
       search_mode_.is_origin_search()) {
     // Use |instant_tab_| to run the query if we're already on a search results
     // page. (NOTE: in particular, we do not send the query to NTPs.)
-    instant_tab_->Submit(search_terms);
+    instant_tab_->sender()->Submit(search_terms);
     instant_tab_->contents()->GetView()->Focus();
     EnsureSearchTermsAreSet(instant_tab_->contents(), search_terms);
     return true;
@@ -823,153 +235,6 @@
   return false;
 }
 
-bool InstantController::CommitIfPossible(InstantCommitType type) {
-  if (!extended_enabled() && !instant_enabled_)
-    return false;
-
-  LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf(
-      "CommitIfPossible: type=%d last_omnibox_text_='%s' "
-      "last_match_was_search_=%d use_tab_for_suggestions=%d", type,
-      UTF16ToUTF8(last_omnibox_text_).c_str(), last_match_was_search_,
-      UseTabForSuggestions()));
-
-  // If we are on an already committed search results page, send a submit event
-  // to the page, but otherwise, nothing else to do.
-  if (UseTabForSuggestions()) {
-    if (type == INSTANT_COMMIT_PRESSED_ENTER &&
-        !instant_tab_->IsLocal() &&
-        (last_match_was_search_ ||
-         last_suggestion_.behavior == INSTANT_COMPLETE_NEVER)) {
-      last_suggestion_.text.clear();
-      instant_tab_->Submit(last_omnibox_text_);
-      instant_tab_->contents()->GetView()->Focus();
-      EnsureSearchTermsAreSet(instant_tab_->contents(), last_omnibox_text_);
-      return true;
-    }
-    return false;
-  }
-
-  // If the overlay is not showing at all, don't commit it.
-  if (!model_.mode().is_search_suggestions())
-    return false;
-
-  // If the overlay is showing at full height (with results), commit it.
-  // If it's showing at parial height, commit if it's navigating.
-  if (!IsOverlayingSearchResults() && type != INSTANT_COMMIT_NAVIGATED)
-    return false;
-
-  // There may re-entrance here, from the call to browser_->CommitInstant below,
-  // which can cause a TabDeactivated notification which gets back here.
-  // In this case, overlay_->ReleaseContents() was called already.
-  if (!GetOverlayContents())
-    return false;
-
-  // Never commit the local overlay.
-  if (overlay_->IsLocal())
-    return false;
-
-  if (type == INSTANT_COMMIT_FOCUS_LOST) {
-    // Extended mode doesn't need or use the Cancel message.
-    if (!extended_enabled())
-      overlay_->Cancel(last_omnibox_text_);
-  } else if (type != INSTANT_COMMIT_NAVIGATED) {
-    overlay_->Submit(last_omnibox_text_);
-  }
-
-  // We expect the WebContents to be in a valid state (i.e., has a last
-  // committed entry, no transient entry, and no existing pending entry).
-  scoped_ptr<content::WebContents> overlay = overlay_->ReleaseContents();
-  CHECK(overlay->GetController().CanPruneAllButVisible());
-
-  // If the overlay page has navigated since the last Update(), we need to add
-  // the navigation to history ourselves. Else, the page will navigate after
-  // commit, and it will be added to history in the usual manner.
-  const history::HistoryAddPageArgs& last_navigation =
-      overlay_->last_navigation();
-  if (!last_navigation.url.is_empty()) {
-    content::NavigationEntry* entry = overlay->GetController().GetActiveEntry();
-
-    // The last navigation should be the same as the active entry if the overlay
-    // is in search mode. During navigation, the active entry could have
-    // changed since DidCommitProvisionalLoadForFrame is called after the entry
-    // is changed.
-    // TODO(shishir): Should we commit the last navigation for
-    // INSTANT_COMMIT_NAVIGATED.
-    DCHECK(type == INSTANT_COMMIT_NAVIGATED ||
-           last_navigation.url == entry->GetURL());
-
-    // Add the page to history.
-    HistoryTabHelper* history_tab_helper =
-        HistoryTabHelper::FromWebContents(overlay.get());
-    history_tab_helper->UpdateHistoryForNavigation(last_navigation);
-
-    // Update the page title.
-    history_tab_helper->UpdateHistoryPageTitle(*entry);
-  }
-
-  // Add a fake history entry with a non-Instant search URL, so that search
-  // terms extraction (for autocomplete history matches) works.
-  HistoryService* history = HistoryServiceFactory::GetForProfile(
-      Profile::FromBrowserContext(overlay->GetBrowserContext()),
-      Profile::EXPLICIT_ACCESS);
-  if (history) {
-    history->AddPage(url_for_history_, base::Time::Now(), NULL, 0, GURL(),
-                     history::RedirectList(), last_transition_type_,
-                     history::SOURCE_BROWSED, false);
-  }
-
-  if (type == INSTANT_COMMIT_PRESSED_ALT_ENTER) {
-    overlay->GetController().PruneAllButVisible();
-  } else {
-    content::WebContents* active_tab = browser_->GetActiveWebContents();
-    AddSessionStorageHistogram(extended_enabled(), active_tab, overlay.get());
-    overlay->GetController().CopyStateFromAndPrune(
-        &active_tab->GetController());
-  }
-
-  if (extended_enabled()) {
-    // Adjust the search terms shown in the omnibox for this query. Hitting
-    // ENTER searches for what the user typed, so use last_omnibox_text_.
-    // Clicking on the overlay commits what is currently showing, so add in the
-    // gray text in that case.
-    if (type == INSTANT_COMMIT_FOCUS_LOST &&
-        last_suggestion_.behavior == INSTANT_COMPLETE_NEVER) {
-      // Update |last_omnibox_text_| so that the controller commits the proper
-      // query if the user focuses the omnibox and presses Enter.
-      last_omnibox_text_ += last_suggestion_.text;
-    }
-
-    EnsureSearchTermsAreSet(overlay.get(), last_omnibox_text_);
-  }
-
-  // Save notification source before we release the overlay.
-  content::Source<content::WebContents> notification_source(overlay.get());
-
-  browser_->CommitInstant(overlay.Pass(),
-                          type == INSTANT_COMMIT_PRESSED_ALT_ENTER);
-
-  content::NotificationService::current()->Notify(
-      chrome::NOTIFICATION_INSTANT_COMMITTED,
-      notification_source,
-      content::NotificationService::NoDetails());
-
-  // Hide explicitly. See comments in HideOverlay() for why.
-  model_.SetOverlayState(SearchMode(), 0, INSTANT_SIZE_PERCENT);
-
-  // Delay deletion as we could've gotten here from an InstantOverlay method.
-  DeletePageSoon(overlay_.Pass());
-
-  // Try to create another overlay immediately so that it is ready for the next
-  // user interaction.
-  ResetOverlay(GetInstantURL());
-
-  if (instant_tab_)
-    use_tab_for_suggestions_ = true;
-
-  LOG_INSTANT_DEBUG_EVENT(this, "Committed");
-  return true;
-}
-
 void InstantController::OmniboxFocusChanged(
     OmniboxFocusState state,
     OmniboxFocusChangeReason reason,
@@ -978,37 +243,21 @@
       "OmniboxFocusChanged: %d to %d for reason %d", omnibox_focus_state_,
       state, reason));
 
-  OmniboxFocusState old_focus_state = omnibox_focus_state_;
   omnibox_focus_state_ = state;
-  if (!extended_enabled() && !instant_enabled_)
+  if (!extended_enabled() || !instant_tab_)
     return;
 
-  if (extended_enabled()) {
-    if (overlay_)
-      overlay_->FocusChanged(omnibox_focus_state_, reason);
+  content::NotificationService::current()->Notify(
+      chrome::NOTIFICATION_OMNIBOX_FOCUS_CHANGED,
+      content::Source<InstantController>(this),
+      content::NotificationService::NoDetails());
 
-    if (instant_tab_) {
-      instant_tab_->FocusChanged(omnibox_focus_state_, reason);
-      // Don't send oninputstart/oninputend updates in response to focus changes
-      // if there's a navigation in progress. This prevents Chrome from sending
-      // a spurious oninputend when the user accepts a match in the omnibox.
-      if (instant_tab_->contents()->GetController().GetPendingEntry() == NULL)
-        instant_tab_->SetInputInProgress(IsInputInProgress());
-    }
-  }
-
-  if (state == OMNIBOX_FOCUS_VISIBLE && old_focus_state == OMNIBOX_FOCUS_NONE) {
-    // If the user explicitly focused the omnibox, then create the overlay if
-    // it doesn't exist. If we're using a fallback overlay, try loading the
-    // remote overlay again.
-    if (!overlay_ || (overlay_->IsLocal() && !use_local_page_only_))
-      ResetOverlay(GetInstantURL());
-  } else if (state == OMNIBOX_FOCUS_NONE &&
-             old_focus_state != OMNIBOX_FOCUS_NONE) {
-    // If the focus went from the omnibox to outside the omnibox, commit or
-    // discard the overlay.
-    OmniboxLostFocus(view_gaining_focus);
-  }
+  instant_tab_->sender()->FocusChanged(omnibox_focus_state_, reason);
+  // Don't send oninputstart/oninputend updates in response to focus changes
+  // if there's a navigation in progress. This prevents Chrome from sending
+  // a spurious oninputend when the user accepts a match in the omnibox.
+  if (instant_tab_->contents()->GetController().GetPendingEntry() == NULL)
+    instant_tab_->sender()->SetInputInProgress(IsInputInProgress());
 }
 
 void InstantController::SearchModeChanged(const SearchMode& old_mode,
@@ -1021,118 +270,32 @@
       old_mode.mode, new_mode.origin, new_mode.mode));
 
   search_mode_ = new_mode;
-  if (!new_mode.is_search_suggestions())
-    HideOverlay();
-
   ResetInstantTab();
 
   if (instant_tab_ && old_mode.is_ntp() != new_mode.is_ntp())
-    instant_tab_->SetInputInProgress(IsInputInProgress());
+    instant_tab_->sender()->SetInputInProgress(IsInputInProgress());
 }
 
 void InstantController::ActiveTabChanged() {
-  if (!extended_enabled() && !instant_enabled_)
-    return;
-
-  LOG_INSTANT_DEBUG_EVENT(this, "ActiveTabChanged");
-
-  // When switching tabs, always hide the overlay.
-  HideOverlay();
-
-  if (extended_enabled())
-    ResetInstantTab();
-}
-
-void InstantController::TabDeactivated(content::WebContents* contents) {
-  LOG_INSTANT_DEBUG_EVENT(this, "TabDeactivated");
-  if (extended_enabled() && !contents->IsBeingDestroyed())
-    CommitIfPossible(INSTANT_COMMIT_FOCUS_LOST);
-
-  if (GetOverlayContents())
-    HideOverlay();
-}
-
-void InstantController::SetInstantEnabled(bool instant_enabled,
-                                          bool use_local_page_only) {
-  LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf(
-      "SetInstantEnabled: instant_enabled=%d, use_local_page_only=%d",
-      instant_enabled, use_local_page_only));
-
-  // Non extended mode does not care about |use_local_page_only|.
-  if (instant_enabled == instant_enabled_ &&
-      (!extended_enabled() ||
-       use_local_page_only == use_local_page_only_)) {
-    return;
-  }
-
-  instant_enabled_ = instant_enabled;
-  use_local_page_only_ = use_local_page_only;
-  preload_ntp_ = !use_local_page_only_ || chrome::ShouldPreloadLocalOnlyNTP();
-
-  // Preload the overlay.
-  HideInternal();
-  overlay_.reset();
-  if (extended_enabled() || instant_enabled_)
-    ResetOverlay(GetInstantURL());
-
-  // Preload the Instant NTP.
-  ntp_.reset();
-  if (extended_enabled() && preload_ntp_)
-    ResetNTP(GetInstantURL());
-
-  if (instant_tab_)
-    instant_tab_->SetDisplayInstantResults(instant_enabled_);
-}
-
-void InstantController::ThemeChanged(const ThemeBackgroundInfo& theme_info) {
   if (!extended_enabled())
     return;
 
-  if (overlay_)
-    overlay_->SendThemeBackgroundInfo(theme_info);
+  LOG_INSTANT_DEBUG_EVENT(this, "ActiveTabChanged");
+  ResetInstantTab();
+}
+
+void InstantController::TabDeactivated(content::WebContents* contents) {
+}
+
+void InstantController::ThemeInfoChanged(
+    const ThemeBackgroundInfo& theme_info) {
+  if (!extended_enabled())
+    return;
+
   if (ntp_)
-    ntp_->SendThemeBackgroundInfo(theme_info);
+    ntp_->sender()->SendThemeBackgroundInfo(theme_info);
   if (instant_tab_)
-    instant_tab_->SendThemeBackgroundInfo(theme_info);
-}
-
-void InstantController::SwappedOverlayContents() {
-  model_.SetOverlayContents(GetOverlayContents());
-}
-
-void InstantController::FocusedOverlayContents() {
-#if defined(USE_AURA)
-  // On aura the omnibox only receives a focus lost if we initiate the focus
-  // change. This does that.
-  if (!model_.mode().is_default())
-    browser_->InstantOverlayFocused();
-#endif
-}
-
-void InstantController::ReloadOverlayIfStale() {
-  // The local overlay is never stale.
-  if (overlay_ && (overlay_->IsLocal() || !overlay_->is_stale()))
-    return;
-
-  // If the overlay is showing or the omnibox has focus, don't refresh the
-  // overlay. It will get refreshed the next time the overlay is hidden or the
-  // omnibox loses focus.
-  if (omnibox_focus_state_ == OMNIBOX_FOCUS_NONE && model_.mode().is_default())
-    ResetOverlay(GetInstantURL());
-}
-
-void InstantController::OverlayLoadCompletedMainFrame() {
-  if (overlay_->supports_instant())
-    return;
-  InstantService* instant_service =
-      InstantServiceFactory::GetForProfile(browser_->profile());
-  content::WebContents* contents = overlay_->contents();
-  DCHECK(contents);
-  if (instant_service->IsInstantProcess(
-      contents->GetRenderProcessHost()->GetID())) {
-    return;
-  }
-  InstantSupportDetermined(contents, false);
+    instant_tab_->sender()->SendThemeBackgroundInfo(theme_info);
 }
 
 void InstantController::LogDebugEvent(const std::string& info) const {
@@ -1149,32 +312,12 @@
   debug_events_.clear();
 }
 
-void InstantController::UpdateMostVisitedItems() {
-  InstantService* instant_service =
-      InstantServiceFactory::GetForProfile(profile());
-  if (!instant_service)
-    return;
-
-  std::vector<InstantMostVisitedItem> items;
-  instant_service->GetCurrentMostVisitedItems(&items);
-
-  if (overlay_ && GetOverlayContents() &&
-      SearchTabHelper::FromWebContents(overlay_->contents())->
-          UpdateLastKnownMostVisitedItems(items)) {
-    overlay_->SendMostVisitedItems(items);
-  }
-
-  if (ntp_ && ntp_->contents() &&
-      SearchTabHelper::FromWebContents(ntp_->contents())->
-          UpdateLastKnownMostVisitedItems(items)) {
-    ntp_->SendMostVisitedItems(items);
-  }
-
-  if (instant_tab_ && instant_tab_->contents() &&
-      SearchTabHelper::FromWebContents(instant_tab_->contents())->
-          UpdateLastKnownMostVisitedItems(items)) {
-    instant_tab_->SendMostVisitedItems(items);
-  }
+void InstantController::MostVisitedItemsChanged(
+    const std::vector<InstantMostVisitedItem>& items) {
+  if (ntp_)
+    ntp_->sender()->SendMostVisitedItems(items);
+  if (instant_tab_)
+    instant_tab_->sender()->SendMostVisitedItems(items);
 
   content::NotificationService::current()->Notify(
       chrome::NOTIFICATION_INSTANT_SENT_MOST_VISITED_ITEMS,
@@ -1184,8 +327,7 @@
 
 void InstantController::DeleteMostVisitedItem(const GURL& url) {
   DCHECK(!url.is_empty());
-  InstantService* instant_service =
-      InstantServiceFactory::GetForProfile(profile());
+  InstantService* instant_service = GetInstantService();
   if (!instant_service)
     return;
 
@@ -1194,8 +336,7 @@
 
 void InstantController::UndoMostVisitedDeletion(const GURL& url) {
   DCHECK(!url.is_empty());
-  InstantService* instant_service =
-      InstantServiceFactory::GetForProfile(profile());
+  InstantService* instant_service = GetInstantService();
   if (!instant_service)
     return;
 
@@ -1203,8 +344,7 @@
 }
 
 void InstantController::UndoAllMostVisitedDeletions() {
-  InstantService* instant_service =
-      InstantServiceFactory::GetForProfile(profile());
+  InstantService* instant_service = GetInstantService();
   if (!instant_service)
     return;
 
@@ -1215,10 +355,6 @@
   return browser_->profile();
 }
 
-InstantOverlay* InstantController::overlay() const {
-  return overlay_.get();
-}
-
 InstantTab* InstantController::instant_tab() const {
   return instant_tab_.get();
 }
@@ -1227,6 +363,17 @@
   return ntp_.get();
 }
 
+void InstantController::OnNetworkChanged(
+    net::NetworkChangeNotifier::ConnectionType type) {
+  // Not interested in events conveying change to offline
+  if (type == net::NetworkChangeNotifier::CONNECTION_NONE)
+    return;
+  if (!extended_enabled_)
+    return;
+  if (!ntp_ || ntp_->IsLocal())
+    ResetNTP(GetInstantURL());
+}
+
 // TODO(shishir): We assume that the WebContent's current RenderViewHost is the
 // RenderViewHost being created which is not always true. Fix this.
 void InstantController::InstantPageRenderViewCreated(
@@ -1235,22 +382,36 @@
     return;
 
   // Update theme info so that the page picks it up.
-  browser_->UpdateThemeInfo();
+  InstantService* instant_service = GetInstantService();
+  if (instant_service) {
+    instant_service->UpdateThemeInfo();
+    instant_service->UpdateMostVisitedItemsInfo();
+  }
 
   // Ensure the searchbox API has the correct initial state.
-  if (IsContentsFrom(overlay(), contents)) {
-    overlay_->SetDisplayInstantResults(instant_enabled_);
-    overlay_->FocusChanged(omnibox_focus_state_, omnibox_focus_change_reason_);
-    overlay_->SetOmniboxBounds(omnibox_bounds_);
-    overlay_->InitializeFonts();
-  } else if (IsContentsFrom(ntp(), contents)) {
-    ntp_->SetDisplayInstantResults(instant_enabled_);
-    ntp_->SetOmniboxBounds(omnibox_bounds_);
+  if (IsContentsFrom(ntp(), contents)) {
+    ntp_->sender()->SetOmniboxBounds(omnibox_bounds_);
     ntp_->InitializeFonts();
+    ntp_->InitializePromos();
   } else {
     NOTREACHED();
   }
-  UpdateMostVisitedItems();
+}
+
+void InstantController::InstantSupportChanged(
+    InstantSupportState instant_support) {
+  // Instant support determined. Update location bar contents to reflect the
+  // page Instant support state.
+  if (instant_support != INSTANT_SUPPORT_UNKNOWN)
+    browser_->UpdateLocationBar();
+
+  // Handle INSTANT_SUPPORT_YES here because InstantPage is not hooked up to the
+  // active tab. Search model changed listener in InstantPage will handle other
+  // cases.
+  if (instant_support != INSTANT_SUPPORT_YES)
+    return;
+
+  ResetInstantTab();
 }
 
 void InstantController::InstantSupportDetermined(
@@ -1279,29 +440,14 @@
         content::Source<InstantController>(this),
         content::NotificationService::NoDetails());
 
-  } else if (IsContentsFrom(overlay(), contents)) {
-    if (!supports_instant) {
-      HideInternal();
-      bool is_local = overlay_->IsLocal();
-      DeletePageSoon(overlay_.Pass());
-      // Preload a local overlay in place of the broken online one.
-      if (!is_local && extended_enabled())
-        ResetOverlay(GetLocalInstantURL());
-    }
-
-    content::NotificationService::current()->Notify(
-        chrome::NOTIFICATION_INSTANT_OVERLAY_SUPPORT_DETERMINED,
-        content::Source<InstantController>(this),
-        content::NotificationService::NoDetails());
+  } else {
+    NOTREACHED();
   }
 }
 
 void InstantController::InstantPageRenderViewGone(
     const content::WebContents* contents) {
-  if (IsContentsFrom(overlay(), contents)) {
-    HideInternal();
-    DeletePageSoon(overlay_.Pass());
-  } else if (IsContentsFrom(ntp(), contents)) {
+  if (IsContentsFrom(ntp(), contents)) {
     DeletePageSoon(ntp_.Pass());
   } else {
     NOTREACHED();
@@ -1311,31 +457,7 @@
 void InstantController::InstantPageAboutToNavigateMainFrame(
     const content::WebContents* contents,
     const GURL& url) {
-  if (IsContentsFrom(overlay(), contents)) {
-    // If the page does not yet support Instant, we allow redirects and other
-    // navigations to go through since the Instant URL can redirect - e.g. to
-    // country specific pages.
-    if (!overlay_->supports_instant())
-      return;
-
-    GURL instant_url(overlay_->instant_url());
-
-    // If we are navigating to the Instant URL, do nothing.
-    if (url == instant_url)
-      return;
-
-    // Commit the navigation if either:
-    //  - The page is in NTP mode (so it could only navigate on a user click) or
-    //  - The page is not in NTP mode and we are navigating to a URL with a
-    //    different host or path than the Instant URL. This enables the instant
-    //    page when it is showing search results to change the query parameters
-    //    and fragments of the URL without it navigating.
-    if (model_.mode().is_ntp() ||
-        (url.host() != instant_url.host() ||
-         url.path() != instant_url.path())) {
-      CommitIfPossible(INSTANT_COMMIT_NAVIGATED);
-    }
-  } else if (IsContentsFrom(instant_tab(), contents)) {
+  if (IsContentsFrom(instant_tab(), contents)) {
     // The Instant tab navigated.  Send it the data it needs to display
     // properly.
     UpdateInfoForInstantTab();
@@ -1344,118 +466,6 @@
   }
 }
 
-void InstantController::SetSuggestions(
-    const content::WebContents* contents,
-    const std::vector<InstantSuggestion>& suggestions) {
-  LOG_INSTANT_DEBUG_EVENT(this, "SetSuggestions");
-
-  // Ignore if the message is from an unexpected source.
-  if (IsContentsFrom(ntp(), contents))
-    return;
-  if (UseTabForSuggestions() && !IsContentsFrom(instant_tab(), contents))
-    return;
-  if (IsContentsFrom(overlay(), contents) &&
-      !allow_overlay_to_show_search_suggestions_)
-    return;
-
-  InstantSuggestion suggestion;
-  if (!suggestions.empty())
-    suggestion = suggestions[0];
-
-  // TODO(samarth): allow InstantTabs to call SetSuggestions() from the NTP once
-  // that is better supported.
-  bool can_use_instant_tab = UseTabForSuggestions() &&
-      search_mode_.is_search();
-  bool can_use_overlay = search_mode_.is_search_suggestions() &&
-      !last_omnibox_text_.empty();
-  if (!can_use_instant_tab && !can_use_overlay)
-    return;
-
-  if (suggestion.behavior == INSTANT_COMPLETE_REPLACE) {
-    if (omnibox_focus_state_ == OMNIBOX_FOCUS_NONE) {
-      // TODO(samarth,skanuj): setValue() needs to be handled differently when
-      // the omnibox doesn't have focus. Instead of setting temporary text, we
-      // should be setting search terms on the appropriate NavigationEntry.
-      // (Among other things, this ensures that URL-shaped values will get the
-      // additional security token.)
-      //
-      // Note that this also breaks clicking on a suggestion corresponding to
-      // gray-text completion: we can't distinguish between the user
-      // clicking on white space (where we don't accept the gray text) and the
-      // user clicking on the suggestion (when we do accept the gray text).
-      // This needs to be fixed before we can turn on Instant again.
-      return;
-    }
-
-    // We don't get an Update() when changing the omnibox due to a REPLACE
-    // suggestion (so that we don't inadvertently cause the overlay to change
-    // what it's showing, as the user arrows up/down through the page-provided
-    // suggestions). So, update these state variables here.
-    last_omnibox_text_ = suggestion.text;
-    last_user_text_.clear();
-    last_suggestion_ = InstantSuggestion();
-    last_match_was_search_ = suggestion.type == INSTANT_SUGGESTION_SEARCH;
-    LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf(
-        "ReplaceSuggestion text='%s' type=%d",
-        UTF16ToUTF8(suggestion.text).c_str(), suggestion.type));
-    browser_->SetInstantSuggestion(suggestion);
-  } else {
-    if (FixSuggestion(&suggestion)) {
-      last_suggestion_ = suggestion;
-      if (suggestion.type == INSTANT_SUGGESTION_SEARCH &&
-          suggestion.behavior == INSTANT_COMPLETE_NEVER)
-        last_omnibox_text_ = last_user_text_;
-      LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf(
-          "SetInstantSuggestion: text='%s' behavior=%d",
-          UTF16ToUTF8(suggestion.text).c_str(),
-          suggestion.behavior));
-      browser_->SetInstantSuggestion(suggestion);
-      content::NotificationService::current()->Notify(
-          chrome::NOTIFICATION_INSTANT_SET_SUGGESTION,
-          content::Source<InstantController>(this),
-          content::NotificationService::NoDetails());
-    } else {
-      last_suggestion_ = InstantSuggestion();
-    }
-  }
-
-  // Extended mode pages will call ShowOverlay() when they are ready.
-  if (!extended_enabled())
-    ShowOverlay(100, INSTANT_SIZE_PERCENT);
-}
-
-void InstantController::ShowInstantOverlay(const content::WebContents* contents,
-                                           int height,
-                                           InstantSizeUnits units) {
-  if (extended_enabled() && IsContentsFrom(overlay(), contents))
-    ShowOverlay(height, units);
-}
-
-void InstantController::LogDropdownShown() {
-  // If suggestions are being shown for the first time since the user started
-  // typing, record a histogram value.
-  if (!first_interaction_time_.is_null() && !first_interaction_time_recorded_) {
-    base::TimeDelta delta = base::Time::Now() - first_interaction_time_;
-    first_interaction_time_recorded_ = true;
-    if (search_mode_.is_origin_ntp()) {
-      UMA_HISTOGRAM_TIMES("Instant.TimeToFirstShowFromNTP", delta);
-      LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf(
-          "LogShowInstantOverlay: TimeToFirstShowFromNTP=%d",
-          static_cast<int>(delta.InMilliseconds())));
-    } else if (search_mode_.is_origin_search()) {
-      UMA_HISTOGRAM_TIMES("Instant.TimeToFirstShowFromSERP", delta);
-      LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf(
-          "LogShowInstantOverlay: TimeToFirstShowFromSERP=%d",
-          static_cast<int>(delta.InMilliseconds())));
-    } else {
-      UMA_HISTOGRAM_TIMES("Instant.TimeToFirstShowFromWeb", delta);
-      LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf(
-          "LogShowInstantOverlay: TimeToFirstShowFromWeb=%d",
-          static_cast<int>(delta.InMilliseconds())));
-    }
-  }
-}
-
 void InstantController::FocusOmnibox(const content::WebContents* contents,
                                      OmniboxFocusState state) {
   if (!extended_enabled())
@@ -1498,9 +508,6 @@
   // has switched tabs).
   if (!extended_enabled())
     return;
-  if (overlay_) {
-    HideOverlay();
-  }
 
   if (transition == content::PAGE_TRANSITION_AUTO_BOOKMARK) {
     content::RecordAction(
@@ -1513,43 +520,12 @@
   browser_->OpenURL(url, transition, disposition);
 }
 
-void InstantController::OmniboxLostFocus(gfx::NativeView view_gaining_focus) {
-  // If the overlay is showing custom NTP content, don't hide it, commit it
-  // (no matter where the user clicked) or try to recreate it.
-  if (model_.mode().is_ntp())
-    return;
-
-  if (model_.mode().is_default()) {
-    // If the overlay is not showing at all, recreate it if it's stale.
-    ReloadOverlayIfStale();
-    return;
-  }
-
-  // The overlay is showing search suggestions. If GetOverlayContents() is NULL,
-  // we are in the commit path. Don't do anything.
-  if (!GetOverlayContents())
-    return;
-
-#if defined(OS_MACOSX)
-  // TODO(sreeram): See if Mac really needs this special treatment.
-  if (!overlay_->is_pointer_down_from_activate())
-    HideOverlay();
-#else
-  if (IsFullHeight(model_))
-    CommitIfPossible(INSTANT_COMMIT_FOCUS_LOST);
-  else if (!IsViewInContents(GetViewGainingFocus(view_gaining_focus),
-                             overlay_->contents()))
-    HideOverlay();
-#endif
-}
-
 std::string InstantController::GetLocalInstantURL() const {
   return chrome::GetLocalInstantURL(profile()).spec();
 }
 
 std::string InstantController::GetInstantURL() const {
-  if (extended_enabled() &&
-      (use_local_page_only_ || net::NetworkChangeNotifier::IsOffline()))
+  if (extended_enabled() && net::NetworkChangeNotifier::IsOffline())
     return GetLocalInstantURL();
 
   const GURL instant_url = chrome::GetInstantURL(profile(),
@@ -1577,10 +553,15 @@
 }
 
 void InstantController::ResetNTP(const std::string& instant_url) {
+  // Never load the Instant NTP if it is disabled.
+  if (!chrome::ShouldShowInstantNTP())
+    return;
+
   // Instant NTP is only used in extended mode so we should always have a
   // non-empty URL to use.
   DCHECK(!instant_url.empty());
-  ntp_.reset(new InstantNTP(this, instant_url));
+  ntp_.reset(new InstantNTP(this, instant_url,
+                            browser_->profile()->IsOffTheRecord()));
   ntp_->InitContents(profile(), browser_->GetActiveWebContents(),
                      base::Bind(&InstantController::ReloadStaleNTP,
                                 base::Unretained(this)));
@@ -1589,7 +570,8 @@
 }
 
 void InstantController::ReloadStaleNTP() {
-  ResetNTP(GetInstantURL());
+  if (extended_enabled())
+    ResetNTP(GetInstantURL());
 }
 
 bool InstantController::ShouldSwitchToLocalNTP() const {
@@ -1614,57 +596,15 @@
   return !(InStartup() && chrome::ShouldPreferRemoteNTPOnStartup());
 }
 
-void InstantController::ResetOverlay(const std::string& instant_url) {
-  HideInternal();
-  // If there's no active tab, the browser is opening or closing.
-  const content::WebContents* active_tab = browser_->GetActiveWebContents();
-  if (!active_tab || instant_url.empty()) {
-    overlay_.reset();
-  } else {
-    overlay_.reset(new InstantOverlay(this, instant_url));
-    overlay_->InitContents(browser_->profile(), active_tab);
-  }
-  LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf(
-      "ResetOverlay: instant_url='%s'", instant_url.c_str()));
-}
-
-InstantController::InstantFallbackReason
-InstantController::ShouldSwitchToLocalOverlay() const {
-  if (!extended_enabled())
-    return INSTANT_FALLBACK_NONE;
-
-  if (!overlay())
-    return DetermineFallbackReason(NULL, std::string());
-
-  // Assume users with Javascript disabled do not want the online experience.
-  if (!IsJavascriptEnabled())
-    return INSTANT_FALLBACK_JAVASCRIPT_DISABLED;
-
-  if (overlay()->IsLocal())
-    return INSTANT_FALLBACK_NONE;
-
-  bool page_is_current = PageIsCurrent(overlay());
-  if (!page_is_current)
-    return DetermineFallbackReason(overlay(), GetInstantURL());
-
-  return INSTANT_FALLBACK_NONE;
-}
-
 void InstantController::ResetInstantTab() {
-  // Do not wire up the InstantTab in Incognito, to prevent it from sending data
-  // to the page.
-  if (!search_mode_.is_origin_default() &&
-      !browser_->profile()->IsOffTheRecord()) {
+  if (!search_mode_.is_origin_default()) {
     content::WebContents* active_tab = browser_->GetActiveWebContents();
     if (!instant_tab_ || active_tab != instant_tab_->contents()) {
-      instant_tab_.reset(new InstantTab(this));
+      instant_tab_.reset(
+          new InstantTab(this, browser_->profile()->IsOffTheRecord()));
       instant_tab_->Init(active_tab);
       UpdateInfoForInstantTab();
-      use_tab_for_suggestions_ = true;
     }
-
-    // Hide the |overlay_| since we are now using |instant_tab_| instead.
-    HideOverlay();
   } else {
     instant_tab_.reset();
   }
@@ -1672,14 +612,20 @@
 
 void InstantController::UpdateInfoForInstantTab() {
   if (instant_tab_) {
-    browser_->UpdateThemeInfo();
-    instant_tab_->SetDisplayInstantResults(instant_enabled_);
-    instant_tab_->SetOmniboxBounds(omnibox_bounds_);
+    instant_tab_->sender()->SetOmniboxBounds(omnibox_bounds_);
+
+    // Update theme details.
+    InstantService* instant_service = GetInstantService();
+    if (instant_service) {
+      instant_service->UpdateThemeInfo();
+      instant_service->UpdateMostVisitedItemsInfo();
+    }
+
     instant_tab_->InitializeFonts();
-    UpdateMostVisitedItems();
-    instant_tab_->FocusChanged(omnibox_focus_state_,
-                               omnibox_focus_change_reason_);
-    instant_tab_->SetInputInProgress(IsInputInProgress());
+    instant_tab_->InitializePromos();
+    instant_tab_->sender()->FocusChanged(omnibox_focus_state_,
+                                         omnibox_focus_change_reason_);
+    instant_tab_->sender()->SetInputInProgress(IsInputInProgress());
   }
 }
 
@@ -1688,164 +634,8 @@
       omnibox_focus_state_ == OMNIBOX_FOCUS_VISIBLE;
 }
 
-void InstantController::HideOverlay() {
-  HideInternal();
-  ReloadOverlayIfStale();
-}
-
-void InstantController::HideInternal() {
-  LOG_INSTANT_DEBUG_EVENT(this, "Hide");
-
-  // If GetOverlayContents() returns NULL, either we're already in the desired
-  // MODE_DEFAULT state, or we're in the commit path. For the latter, don't
-  // change the state just yet; else we may hide the overlay unnecessarily.
-  // Instead, the state will be set correctly after the commit is done.
-  if (GetOverlayContents()) {
-    model_.SetOverlayState(SearchMode(), 0, INSTANT_SIZE_PERCENT);
-    allow_overlay_to_show_search_suggestions_ = false;
-
-    // Send a message asking the overlay to clear out old results.
-    overlay_->Update(string16(), 0, 0, true);
-  }
-
-  // Clear the first interaction timestamp for later use.
-  first_interaction_time_ = base::Time();
-  first_interaction_time_recorded_ = false;
-
-  if (instant_tab_)
-    use_tab_for_suggestions_ = true;
-}
-
-void InstantController::ShowOverlay(int height, InstantSizeUnits units) {
-  // If we are on a committed search results page, the |overlay_| is not in use.
-  if (UseTabForSuggestions())
-    return;
-
-  LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf(
-      "Show: height=%d units=%d", height, units));
-
-  // Must have updated omnibox after the last HideOverlay() to show suggestions.
-  if (!allow_overlay_to_show_search_suggestions_)
-    return;
-
-  // The page is trying to hide itself. Hide explicitly (i.e., don't use
-  // HideOverlay()) so that it can change its mind.
-  if (height == 0) {
-    model_.SetOverlayState(SearchMode(), 0, INSTANT_SIZE_PERCENT);
-    if (instant_tab_)
-      use_tab_for_suggestions_ = true;
-    return;
-  }
-
-  // Show at 100% height except in the following cases:
-  // - The local overlay (omnibox popup) is being loaded.
-  // - Instant is disabled. The page needs to be able to show only a dropdown.
-  // - The page is over a website other than search or an NTP, and is not
-  //   already showing at 100% height.
-  if (overlay_->IsLocal() || !instant_enabled_ ||
-      (search_mode_.is_origin_default() && !IsFullHeight(model_)))
-    model_.SetOverlayState(search_mode_, height, units);
-  else
-    model_.SetOverlayState(search_mode_, 100, INSTANT_SIZE_PERCENT);
-
-  // If the overlay is being shown at full height and the omnibox is not
-  // focused, commit right away.
-  if (IsFullHeight(model_) && omnibox_focus_state_ == OMNIBOX_FOCUS_NONE)
-    CommitIfPossible(INSTANT_COMMIT_FOCUS_LOST);
-}
-
-void InstantController::SendPopupBoundsToPage() {
-  if (last_popup_bounds_ == popup_bounds_ || !overlay_ ||
-      overlay_->is_pointer_down_from_activate())
-    return;
-
-  last_popup_bounds_ = popup_bounds_;
-  gfx::Rect overlay_bounds = browser_->GetInstantBounds();
-  gfx::Rect intersection = gfx::IntersectRects(popup_bounds_, overlay_bounds);
-
-  // Translate into window coordinates.
-  if (!intersection.IsEmpty()) {
-    intersection.Offset(-overlay_bounds.origin().x(),
-                        -overlay_bounds.origin().y());
-  }
-
-  // In the current Chrome UI, these must always be true so they sanity check
-  // the above operations. In a future UI, these may be removed or adjusted.
-  // There is no point in sanity-checking |intersection.y()| because the omnibox
-  // can be placed anywhere vertically relative to the overlay (for example, in
-  // Mac fullscreen mode, the omnibox is fully enclosed by the overlay bounds).
-  DCHECK_LE(0, intersection.x());
-  DCHECK_LE(0, intersection.width());
-  DCHECK_LE(0, intersection.height());
-
-  overlay_->SetPopupBounds(intersection);
-}
-
-
-
-bool InstantController::FixSuggestion(InstantSuggestion* suggestion) const {
-  // We only accept suggestions if the user has typed text. If the user is
-  // arrowing up/down (|last_user_text_| is empty), we reject suggestions.
-  if (last_user_text_.empty())
-    return false;
-
-  // If the page is trying to set inline autocompletion in verbatim mode,
-  // instead try suggesting the exact omnibox text. This makes the omnibox
-  // interpret user text as an URL if possible while preventing unwanted
-  // autocompletion during backspacing.
-  if (suggestion->behavior == INSTANT_COMPLETE_NOW && last_verbatim_)
-    suggestion->text = last_omnibox_text_;
-
-  // Suggestion text should be a full URL for URL suggestions, or the
-  // completion of a query for query suggestions.
-  if (suggestion->type == INSTANT_SUGGESTION_URL) {
-    // If the suggestion is not a valid URL, perhaps it's something like
-    // "foo.com". Try prefixing "http://". If it still isn't valid, drop it.
-    if (!GURL(suggestion->text).is_valid()) {
-      suggestion->text.insert(0, ASCIIToUTF16("http://"));
-      if (!GURL(suggestion->text).is_valid())
-        return false;
-    }
-
-    // URL suggestions are only accepted if the query for which the suggestion
-    // was generated is the same as |last_user_text_|.
-    //
-    // Any other URL suggestions--in particular suggestions for old user_text
-    // lagging behind a slow IPC--are ignored. See crbug.com/181589.
-    //
-    // TODO(samarth): Accept stale suggestions if they would be accepted by
-    // SearchProvider as an inlinable suggestion. http://crbug.com/191656.
-    return suggestion->query == last_user_text_;
-  }
-
-  // We use |last_user_text_| because |last_omnibox_text| may contain text from
-  // a previous URL suggestion at this point.
-  if (suggestion->type == INSTANT_SUGGESTION_SEARCH) {
-    if (StartsWith(suggestion->text, last_user_text_, true)) {
-      // The user typed an exact prefix of the suggestion.
-      suggestion->text.erase(0, last_user_text_.size());
-      return true;
-    } else if (NormalizeAndStripPrefix(&suggestion->text, last_user_text_)) {
-      // Unicode normalize and case-fold the user text and suggestion. If the
-      // user text is a prefix, suggest the normalized, case-folded completion
-      // for instance, if the user types 'i' and the suggestion is 'INSTANT',
-      // suggest 'nstant'. Otherwise, the user text really isn't a prefix, so
-      // suggest nothing.
-      // TODO(samarth|jered): revisit this logic. http://crbug.com/196572.
-      return true;
-    }
-  }
-
-  return false;
-}
-
 bool InstantController::UsingLocalPage() const {
-  return (UseTabForSuggestions() && instant_tab_->IsLocal()) ||
-      (!UseTabForSuggestions() && overlay_ && overlay_->IsLocal());
-}
-
-bool InstantController::UseTabForSuggestions() const {
-  return instant_tab_ && use_tab_for_suggestions_;
+  return instant_tab_ && instant_tab_->IsLocal();
 }
 
 void InstantController::RedirectToLocalNTP(content::WebContents* contents) {
@@ -1859,31 +649,6 @@
   // entry.
 }
 
-void InstantController::PopulateInstantAutocompleteResultFromMatch(
-    const AutocompleteMatch& match, size_t autocomplete_match_index,
-    InstantAutocompleteResult* result) {
-  DCHECK(result);
-  result->provider = UTF8ToUTF16(match.provider->GetName());
-  result->type = match.type;
-  result->description = match.description;
-  result->destination_url = UTF8ToUTF16(match.destination_url.spec());
-
-  // Setting the search_query field tells the Instant page to treat the
-  // suggestion as a query.
-  if (AutocompleteMatch::IsSearchType(match.type))
-    result->search_query = match.contents;
-
-  result->transition = match.transition;
-  result->relevance = match.relevance;
-  result->autocomplete_match_index = autocomplete_match_index;
-
-  DVLOG(1) << "    " << result->relevance << " "
-      << UTF8ToUTF16(AutocompleteMatchType::ToString(result->type)) << " "
-      << result->provider << " " << result->destination_url << " '"
-      << result->description << "' '" << result->search_query << "' "
-      << result->transition <<  " " << result->autocomplete_match_index;
-}
-
 bool InstantController::IsJavascriptEnabled() const {
   GURL instant_url(GetInstantURL());
   GURL origin(instant_url.GetOrigin());
@@ -1907,3 +672,7 @@
   // startup time.
   return !browser_->GetActiveWebContents();
 }
+
+InstantService* InstantController::GetInstantService() const {
+  return InstantServiceFactory::GetForProfile(profile());
+}
diff --git a/chrome/browser/ui/search/instant_controller.h b/chrome/browser/ui/search/instant_controller.h
index 0a3d42e..8dd8bb9 100644
--- a/chrome/browser/ui/search/instant_controller.h
+++ b/chrome/browser/ui/search/instant_controller.h
@@ -14,31 +14,22 @@
 #include "base/gtest_prod_util.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/string16.h"
-#include "base/time.h"
-#include "base/timer.h"
-#include "chrome/browser/ui/omnibox/omnibox_edit_model.h"
-#include "chrome/browser/ui/search/instant_commit_type.h"
-#include "chrome/browser/ui/search/instant_overlay_model.h"
+#include "chrome/browser/search/instant_service_observer.h"
 #include "chrome/browser/ui/search/instant_page.h"
 #include "chrome/common/instant_types.h"
 #include "chrome/common/omnibox_focus_state.h"
 #include "chrome/common/search_types.h"
-#include "content/public/common/page_transition_types.h"
 #include "googleurl/src/gurl.h"
+#include "net/base/network_change_notifier.h"
 #include "ui/base/window_open_disposition.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/gfx/rect.h"
 
-struct AutocompleteMatch;
-struct InstantAutocompleteResult;
-
-class AutocompleteProvider;
-class AutocompleteResult;
 class BrowserInstantController;
 class InstantNTP;
-class InstantOverlay;
+class InstantService;
 class InstantTab;
-class TemplateURL;
+class Profile;
 
 namespace content {
 class WebContents;
@@ -51,123 +42,48 @@
 // InstantController drives Chrome Instant, i.e., the browser implementation of
 // the Embedded Search API (see http://dev.chromium.org/embeddedsearch).
 //
-// In extended mode, InstantController maintains and coordinates three
+// In extended mode, InstantController maintains and coordinates two
 // instances of InstantPage:
-//  (1) An InstantOverlay instance that is used to show search suggestions and
-//      results in an overlay over a non-search page.
-//  (2) An InstantNTP instance which is a preloaded search page that will be
+//  (1) An InstantNTP instance which is a preloaded search page that will be
 //      swapped-in the next time the user navigates to the New Tab Page. It is
 //      never shown to the user in an uncommitted state.
-//  (3) An InstantTab instance which points to the currently active tab, if it
+//  (2) An InstantTab instance which points to the currently active tab, if it
 //      supports the Embedded Search API.
 //
-// All three are backed by a WebContents. InstantOverlay and InstantNTP own
-// their corresponding WebContents; InstantTab does not. In non-extended mode,
-// only an InstantOverlay instance is kept.
+// Both are backed by a WebContents. InstantNTP owns its WebContents and
+// InstantTab does not.
 //
 // InstantController is owned by Browser via BrowserInstantController.
-class InstantController : public InstantPage::Delegate {
+class InstantController : public InstantPage::Delegate,
+                          public InstantServiceObserver {
  public:
-  // For reporting fallbacks to local overlay.
-  enum InstantFallbackReason {
-    INSTANT_FALLBACK_NONE = 0,
-    INSTANT_FALLBACK_UNKNOWN = 1,
-    INSTANT_FALLBACK_INSTANT_URL_EMPTY = 2,
-    INSTANT_FALLBACK_ORIGIN_PATH_MISMATCH = 3,
-    INSTANT_FALLBACK_INSTANT_NOT_SUPPORTED = 4,
-    INSTANT_FALLBACK_NO_OVERLAY = 5,
-    INSTANT_FALLBACK_JAVASCRIPT_DISABLED = 6,
-    INSTANT_FALLBACK_MAX = 7,
-  };
-
   InstantController(BrowserInstantController* browser,
                     bool extended_enabled);
   virtual ~InstantController();
 
-  // Called when the Autocomplete flow is about to start. Sets up the
-  // appropriate page to send user updates to.  May reset |instant_tab_| or
-  // switch to a local fallback |overlay_| as necessary.
-  void OnAutocompleteStart();
-
-  // Invoked as the user types into the omnibox. |user_text| is what the user
-  // has typed. |full_text| is what the omnibox is showing. These may differ if
-  // the user typed only some text, and the rest was inline autocompleted. If
-  // |verbatim| is true, search results are shown for the exact omnibox text,
-  // rather than the best guess as to what the user means. Returns true if the
-  // update is accepted (i.e., if |match| is a search rather than a URL).
-  // |is_keyword_search| is true if keyword searching is in effect.
-  bool Update(const AutocompleteMatch& match,
-              const string16& user_text,
-              const string16& full_text,
-              size_t selection_start,
-              size_t selection_end,
-              bool verbatim,
-              bool user_input_in_progress,
-              bool omnibox_popup_is_open,
-              bool escape_pressed,
-              bool is_keyword_search);
-
-  // Returns whether the Instant page currently being used will fetch its own
-  // completions. True for extended mode, unless using a local Instant page.
-  bool WillFetchCompletions() const;
-
   // Releases and returns the NTP WebContents. May be NULL. Loads a new
   // WebContents for the NTP.
   scoped_ptr<content::WebContents> ReleaseNTPContents() WARN_UNUSED_RESULT;
 
-  // Sets the bounds of the omnibox popup, in screen coordinates.
-  void SetPopupBounds(const gfx::Rect& bounds);
-
   // Sets the stored start-edge margin and width of the omnibox.
   void SetOmniboxBounds(const gfx::Rect& bounds);
 
-  // Send autocomplete results from |providers| to the overlay page.
-  void HandleAutocompleteResults(
-      const std::vector<AutocompleteProvider*>& providers,
-      const AutocompleteResult& result);
-
-  // Called when the default search provider changes. Resets InstantNTP and
-  // InstantOverlay.
+  // Called when the default search provider changes. Resets InstantNTP.
   void OnDefaultSearchProviderChanged();
 
-  // Called when the user presses up or down. |count| is a repeat count,
-  // negative for moving up, positive for moving down. Returns true if Instant
-  // handled the key press.
-  bool OnUpOrDownKeyPressed(int count);
-
-  // Called when the user has arrowed into the suggestions but wants to cancel,
-  // typically by pressing ESC. The omnibox text is expected to have been
-  // reverted to |full_text| by the OmniboxEditModel prior to calling this.
-  // |match| is the match reverted to.
-  void OnCancel(const AutocompleteMatch& match,
-                const string16& user_text,
-                const string16& full_text);
-
-  // Called when the user navigates to a URL from the omnibox. This will send
-  // an onsubmit notification to the instant page.
-  void OmniboxNavigateToURL();
-
   // Notifies |instant_Tab_| to toggle voice search.
   void ToggleVoiceSearch();
 
-  // The overlay WebContents. May be NULL. InstantController retains ownership.
-  content::WebContents* GetOverlayContents() const;
-
   // The ntp WebContents. May be NULL. InstantController retains ownership.
   content::WebContents* GetNTPContents() const;
 
-  // Returns true if Instant is showing a search results overlay. Returns false
-  // if the overlay is not showing, or if it's showing only suggestions.
-  bool IsOverlayingSearchResults() const;
-
   // Called if the browser is navigating to a search URL for |search_terms| with
   // search-term-replacement enabled. If |instant_tab_| can be used to process
   // the search, this does so and returns true. Else, returns false.
   bool SubmitQuery(const string16& search_terms);
 
-  // If the overlay is showing search results, commits the overlay, calling
-  // CommitInstant() on the browser, and returns true. Else, returns false.
-  bool CommitIfPossible(InstantCommitType type);
+  // If the network status changes, try to reset NTP and Overlay.
+  void OnNetworkChanged(net::NetworkChangeNotifier::ConnectionType type);
 
   // Called to indicate that the omnibox focus state changed with the given
   // |reason|. If |focus_state| is FOCUS_NONE, |view_gaining_focus| is set to
@@ -176,41 +92,18 @@
                            OmniboxFocusChangeReason reason,
                            gfx::NativeView view_gaining_focus);
 
-  // The search mode in the active tab has changed. Pass the message down to
-  // the overlay which will notify the renderer. Create |instant_tab_| if the
+  // The search mode in the active tab has changed. Bind |instant_tab_| if the
   // |new_mode| reflects an Instant search results page.
   void SearchModeChanged(const SearchMode& old_mode,
                          const SearchMode& new_mode);
 
-  // The user switched tabs. Hide the overlay. Create |instant_tab_| if the
-  // newly active tab is an Instant search results page.
+  // The user switched tabs. Bind |instant_tab_| if the newly active tab is an
+  // Instant search results page.
   void ActiveTabChanged();
 
-  // The user is about to switch tabs. Commit the overlay if needed.
+  // The user is about to switch tabs.
   void TabDeactivated(content::WebContents* contents);
 
-  // Sets whether Instant should show result overlays. |use_local_page_only|
-  // will force the use of baked-in page as the Instant URL and is only
-  // applicable if |extended_enabled_| is true.
-  void SetInstantEnabled(bool instant_enabled, bool use_local_page_only);
-
-  // The theme has changed. Pass the message to the overlay page.
-  void ThemeChanged(const ThemeBackgroundInfo& theme_info);
-
-  // Called when someone else swapped in a different contents in the |overlay_|.
-  void SwappedOverlayContents();
-
-  // Called when contents for |overlay_| received focus.
-  void FocusedOverlayContents();
-
-  // Called when the |overlay_| might be stale. If it's actually stale, and the
-  // omnibox doesn't have focus, and the overlay isn't showing, the |overlay_|
-  // is deleted and recreated. Else the refresh is skipped.
-  void ReloadOverlayIfStale();
-
-  // Called when the |overlay_|'s main frame has finished loading.
-  void OverlayLoadCompletedMainFrame();
-
   // Adds a new event to |debug_events_| and also DVLOG's it. Ensures that
   // |debug_events_| doesn't get too large.
   void LogDebugEvent(const std::string& info) const;
@@ -218,13 +111,11 @@
   // Resets list of debug events.
   void ClearDebugEvents();
 
-  // Gets the Most Visited items info from InstantService and forwards them to
-  // the Instant page renderer via the appropriate InstantPage subclass.
-  void UpdateMostVisitedItems();
+  // Loads a new NTP to replace |ntp_|.
+  void ReloadStaleNTP();
 
   // Returns the correct Instant URL to use from the following possibilities:
   //   o The default search engine's Instant URL
-  //   o The --instant-url command line switch
   //   o The local page (see GetLocalInstantURL())
   // Returns empty string if no valid Instant URL is available (this is only
   // possible in non-extended mode where we don't have a local page fall-back).
@@ -235,20 +126,14 @@
     return debug_events_;
   }
 
-  // Returns the transition type of the last AutocompleteMatch passed to Update.
-  content::PageTransition last_transition_type() const {
-    return last_transition_type_;
-  }
-
-  // Non-const for Add/RemoveObserver only.  Other model changes should only
-  // happen through the InstantController interface.
-  InstantOverlayModel* model() { return &model_; }
+  // Used by BrowserInstantController to notify InstantController about the
+  // instant support change event for the active web contents.
+  void InstantSupportChanged(InstantSupportState instant_support);
 
  protected:
   // Accessors are made protected for testing purposes.
   virtual bool extended_enabled() const;
 
-  virtual InstantOverlay* overlay() const;
   virtual InstantTab* instant_tab() const;
   virtual InstantNTP* ntp() const;
 
@@ -270,34 +155,13 @@
   UNIT_F(IsJavascriptEnabledChecksContentSettings);
   UNIT_F(IsJavascriptEnabledChecksPrefs);
   UNIT_F(PrefersRemoteNTPOnStartup);
-  UNIT_F(ShouldSwitchToLocalOverlay);
   UNIT_F(SwitchesToLocalNTPIfJSDisabled);
   UNIT_F(SwitchesToLocalNTPIfNoInstantSupport);
   UNIT_F(SwitchesToLocalNTPIfNoNTPReady);
   UNIT_F(SwitchesToLocalNTPIfPathBad);
 #undef UNIT_F
-  FRIEND_TEST_ALL_PREFIXES(InstantTest, OmniboxFocusLoadsInstant);
-  FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, UsesOverlayIfTabNotReady);
-  FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest,
-                           SearchQueryNotDisplayedForNavsuggest);
-  FRIEND_TEST_ALL_PREFIXES(InstantTest, SetWithTemplateURL);
-  FRIEND_TEST_ALL_PREFIXES(InstantTest, NonInstantSearchProvider);
-  FRIEND_TEST_ALL_PREFIXES(InstantTest, InstantOverlayRefresh);
-  FRIEND_TEST_ALL_PREFIXES(InstantTest, InstantOverlayRefreshDifferentOrder);
-  FRIEND_TEST_ALL_PREFIXES(InstantTest, InstantRenderViewGone);
   FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, ExtendedModeIsOn);
   FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, MostVisited);
-  FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, RestrictedItemReadback);
-  FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, OmniboxFocusLoadsInstant);
-  FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest,
-                           OmniboxTextUponFocusedCommittedSERP);
-  FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest,
-                           NavigationSuggestionIsDiscardedUponSearchSuggestion);
-  FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest,
-                           NavigateToURLSuggestionHitEnterAndLookForSubmit);
-  FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest,
-                           MiddleClickOnSuggestionOpensInNewTab);
-  FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, SearchProviderRunsForFallback);
   FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, NTPIsPreloaded);
   FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, PreloadedNTPIsUsedInNewTab);
   FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, PreloadedNTPIsUsedInSameTab);
@@ -307,37 +171,25 @@
                            PreloadedNTPDoesntSupportInstant);
   FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, ProcessIsolation);
   FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, UnrelatedSiteInstance);
-  FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, ValidatesSuggestions);
-  FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest,
-                           OmniboxCommitsWhenShownFullHeight);
-  FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, LocalOnlyNTPIsPreloaded);
-  FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, LocalOnlyNTPIsNotPreloaded);
-  FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, OverlayRenderViewGone);
-  FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, OverlayDoesntSupportInstant);
-  FRIEND_TEST_ALL_PREFIXES(InstantExtendedManualTest,
-                           MANUAL_OmniboxFocusLoadsInstant);
-  FRIEND_TEST_ALL_PREFIXES(InstantExtendedManualTest,
-                           MANUAL_BackspaceFromQueryToSelectedUrlAndNavigate);
   FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, OnDefaultSearchProviderChanged);
-  FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, SearchProviderForLocalNTP);
+  FRIEND_TEST_ALL_PREFIXES(InstantExtendedNetworkTest,
+                           NTPReactsToNetworkChanges);
   FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest,
                            AcceptingURLSearchDoesNotNavigate);
   FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, AcceptingJSSearchDoesNotRunJS);
   FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest,
                            ReloadSearchAfterBackReloadsCorrectQuery);
-  FRIEND_TEST_ALL_PREFIXES(
-      InstantExtendedFirstTabTest, RedirectToLocalOnLoadFailure);
-  FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, LogDropdownShown);
-  FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest,
-                           OverlayDoesNotEchoSearchProviderNavsuggest);
+  FRIEND_TEST_ALL_PREFIXES(InstantExtendedFirstTabTest,
+                           RedirectToLocalOnLoadFailure);
   FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, KeyboardTogglesVoiceSearch);
-#if !defined(HTML_INSTANT_EXTENDED_POPUP)
+  FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, HomeButtonAffectsMargin);
   FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, SearchReusesInstantTab);
   FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest,
                            SearchDoesntReuseInstantTabWithoutSupport);
   FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest,
                            TypedSearchURLDoesntReuseInstantTab);
-#endif
+  FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest,
+                           DispatchMVChangeEventWhileNavigatingBackToNTP);
 
   // Overridden from InstantPage::Delegate:
   // TODO(shishir): We assume that the WebContent's current RenderViewHost is
@@ -352,14 +204,6 @@
   virtual void InstantPageAboutToNavigateMainFrame(
       const content::WebContents* contents,
       const GURL& url) OVERRIDE;
-  virtual void SetSuggestions(
-      const content::WebContents* contents,
-      const std::vector<InstantSuggestion>& suggestions) OVERRIDE;
-  virtual void ShowInstantOverlay(
-      const content::WebContents* contents,
-      int height,
-      InstantSizeUnits units) OVERRIDE;
-  virtual void LogDropdownShown() OVERRIDE;
   virtual void FocusOmnibox(const content::WebContents* contents,
                             OmniboxFocusState state) OVERRIDE;
   virtual void NavigateToURL(
@@ -370,6 +214,11 @@
       bool is_search_type) OVERRIDE;
   virtual void InstantPageLoadFailed(content::WebContents* contents) OVERRIDE;
 
+  // Overridden from InstantServiceObserver:
+  virtual void ThemeInfoChanged(const ThemeBackgroundInfo& theme_info) OVERRIDE;
+  virtual void MostVisitedItemsChanged(
+      const std::vector<InstantMostVisitedItem>& items) OVERRIDE;
+
   // Invoked by the InstantLoader when the Instant page wants to delete a
   // Most Visited item.
   virtual void DeleteMostVisitedItem(const GURL& url) OVERRIDE;
@@ -400,19 +249,9 @@
   // Recreates |ntp_| using |instant_url|.
   void ResetNTP(const std::string& instant_url);
 
-  // Reloads a new InstantNTP.  Called when |ntp_| is stale.
-  void ReloadStaleNTP();
-
   // Returns true if we should switch to using the local NTP.
   bool ShouldSwitchToLocalNTP() const;
 
-  // Recreates |overlay_| using |instant_url|. |overlay_| will be NULL if
-  // |instant_url| is empty or if there is no active tab.
-  void ResetOverlay(const std::string& instant_url);
-
-  // Returns an enum value indicating the reason to fallback.
-  InstantFallbackReason ShouldSwitchToLocalOverlay() const;
-
   // If the active tab is an Instant search results page, sets |instant_tab_| to
   // point to it. Else, deletes any existing |instant_tab_|.
   void ResetInstantTab();
@@ -424,102 +263,22 @@
   // active tab is in mode SEARCH_SUGGESTIONS.
   bool IsInputInProgress() const;
 
-  // Hide the overlay. Also sends an onchange event (with blank query) to the
-  // overlay, telling it to clear out results for any old queries.
-  void HideOverlay();
-
-  // Like HideOverlay(), but doesn't call OnStaleOverlay(). Use HideOverlay()
-  // unless you are going to call overlay_.reset() yourself subsequently.
-  void HideInternal();
-
-  // Counterpart to HideOverlay(). Asks the |browser_| to display the overlay
-  // with the given |height| in |units|.
-  void ShowOverlay(int height, InstantSizeUnits units);
-
-  // Send the omnibox popup bounds to the page.
-  void SendPopupBoundsToPage();
-
-  // If possible, tries to mutate |suggestion| to a valid suggestion. Returns
-  // true if successful. (Note that |suggestion| may be modified even if this
-  // returns false.)
-  bool FixSuggestion(InstantSuggestion* suggestion) const;
-
   // Returns true if the local page is being used.
   bool UsingLocalPage() const;
 
-  // Returns true iff |use_tab_for_suggestions_| is true and |instant_tab_|
-  // exists.
-  bool UseTabForSuggestions() const;
-
-  // Populates InstantAutocompleteResult with AutocompleteMatch details.
-  // |autocomplete_match_index| specifies the index of |match| in the
-  // AutocompleteResult. If the |match| is obtained from auto complete
-  // providers, then the |autocomplete_match_index| is set to kNoMatchIndex.
-  void PopulateInstantAutocompleteResultFromMatch(
-      const AutocompleteMatch& match,
-      size_t autocomplete_match_index,
-      InstantAutocompleteResult* result);
+  // Returns the InstantService for the browser profile.
+  InstantService* GetInstantService() const;
 
   BrowserInstantController* const browser_;
 
   // Whether the extended API and regular API are enabled. If both are false,
   // Instant is effectively disabled.
   const bool extended_enabled_;
-  bool instant_enabled_;
 
-  // If true, the Instant URL is set to kChromeSearchLocalNtpUrl.
-  bool use_local_page_only_;
-
-  // If true, preload an NTP into |ntp_|.
-  bool preload_ntp_;
-
-  // The state of the overlay page, i.e., the page owned by |overlay_|. Ignored
-  // if |instant_tab_| is in use.
-  InstantOverlayModel model_;
-
-  // The three instances of InstantPage maintained by InstantController as
-  // described above. All three may be non-NULL in extended mode.  If
-  // |instant_tab_| is not NULL, then |overlay_| is guaranteed to be hidden and
-  // messages will be sent to |instant_tab_| instead.
-  //
-  // In non-extended mode, only |overlay_| is ever non-NULL.
-  scoped_ptr<InstantOverlay> overlay_;
+  // The instances of InstantPage maintained by InstantController.
   scoped_ptr<InstantNTP> ntp_;
   scoped_ptr<InstantTab> instant_tab_;
 
-  // If true, send suggestion-related events (such as user key strokes, auto
-  // complete results, etc.) to |instant_tab_| instead of |overlay_|. Once set
-  // to false, will stay false until the overlay is hidden or committed.
-  bool use_tab_for_suggestions_;
-
-  // The most recent full_text passed to Update(). If empty, we'll not accept
-  // search suggestions from |overlay_| or |instant_tab_|.
-  string16 last_omnibox_text_;
-
-  // The most recent user_text passed to Update(). Used to filter out-of-date
-  // URL suggestions from the Instant page. Set in Update() and cleared when
-  // the page sets temporary text (SetSuggestions() with REPLACE behavior).
-  string16 last_user_text_;
-
-  // True if the last Update() had an inline autocompletion. Used only to make
-  // sure that we don't accidentally suggest gray text suggestion in that case.
-  bool last_omnibox_text_has_inline_autocompletion_;
-
-  // The most recent verbatim passed to Update(). Used only to ensure that we
-  // don't accidentally suggest an inline autocompletion.
-  bool last_verbatim_;
-
-  // The most recent suggestion received from the page, minus any prefix that
-  // the user has typed.
-  InstantSuggestion last_suggestion_;
-
-  // See comments on the getter above.
-  content::PageTransition last_transition_type_;
-
-  // True if the last match passed to Update() was a search (versus a URL).
-  // Used to ensure that the overlay page is committable.
-  bool last_match_was_search_;
-
   // Omnibox focus state.
   OmniboxFocusState omnibox_focus_state_;
 
@@ -529,38 +288,10 @@
   // The search model mode for the active tab.
   SearchMode search_mode_;
 
-  // Current omnibox popup bounds.
-  gfx::Rect popup_bounds_;
-
-  // Last popup bounds passed to the page.
-  gfx::Rect last_popup_bounds_;
-
   // The start-edge margin and width of the omnibox, used by the page to align
   // its suggestions with the omnibox.
   gfx::Rect omnibox_bounds_;
 
-  // Timer used to update the bounds of the omnibox popup.
-  base::OneShotTimer<InstantController> update_bounds_timer_;
-
-  // Search terms extraction (for autocomplete history matches) doesn't work
-  // on Instant URLs. So, whenever the user commits an Instant search, we add
-  // an equivalent non-Instant search URL to history, so that the search shows
-  // up in autocomplete history matches.
-  // TODO(sreeram): Remove when http://crbug.com/155373 is fixed.
-  GURL url_for_history_;
-
-  // The timestamp at which query editing began. This value is used when the
-  // overlay is showed and cleared when the overlay is hidden.
-  base::Time first_interaction_time_;
-
-  // Indicates that the first interaction time has already been logged.
-  bool first_interaction_time_recorded_;
-
-  // Whether to allow the overlay to show search suggestions. In general, the
-  // overlay is allowed to show search suggestions whenever |search_mode_| is
-  // MODE_SEARCH_SUGGESTIONS, except in those cases where this is false.
-  bool allow_overlay_to_show_search_suggestions_;
-
   // List of events and their timestamps, useful in debugging Instant behaviour.
   mutable std::list<std::pair<int64, std::string> > debug_events_;
 
diff --git a/chrome/browser/ui/search/instant_controller_unittest.cc b/chrome/browser/ui/search/instant_controller_unittest.cc
index 3ed131e..b96540b 100644
--- a/chrome/browser/ui/search/instant_controller_unittest.cc
+++ b/chrome/browser/ui/search/instant_controller_unittest.cc
@@ -11,7 +11,6 @@
 #include "chrome/browser/search/search.h"
 #include "chrome/browser/ui/search/instant_controller.h"
 #include "chrome/browser/ui/search/instant_ntp.h"
-#include "chrome/browser/ui/search/instant_overlay.h"
 #include "chrome/common/content_settings.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_profile.h"
@@ -22,41 +21,11 @@
 using base::HistogramSamples;
 using base::StatisticsRecorder;
 
-class TestableInstantOverlay : public InstantOverlay {
- public:
-  TestableInstantOverlay(InstantController* controller,
-                         const std::string& instant_url)
-      : InstantOverlay(controller, instant_url) {
-  }
-
-  // Overrides from InstantPage
-  virtual bool supports_instant() const OVERRIDE {
-    return test_supports_instant_;
-  }
-
-  virtual bool IsLocal() const OVERRIDE {
-    return test_is_local_;
-  };
-
-  void set_supports_instant(bool supports_instant) {
-    test_supports_instant_ = supports_instant;
-  }
-
-  void set_is_local(bool is_local) {
-    test_is_local_ = is_local;
-  }
-
- private:
-  std::string test_instant_url_;
-  bool test_supports_instant_;
-  bool test_is_local_;
-};
-
 class TestableInstantNTP : public InstantNTP {
  public:
   TestableInstantNTP(InstantController* controller,
                      const std::string& instant_url)
-      : InstantNTP(controller, instant_url) {
+      : InstantNTP(controller, instant_url, false) {
   }
 
   // Overrides from InstantPage
@@ -99,7 +68,6 @@
         override_javascript_enabled_(true),
         test_javascript_enabled_(true),
         test_in_startup_(false),
-        test_overlay_(NULL),
         test_ntp_(NULL) {}
 
   // Overrides from InstantController
@@ -115,10 +83,6 @@
     return test_extended_enabled_;
   }
 
-  virtual InstantOverlay* overlay() const OVERRIDE {
-    return test_overlay_;
-  }
-
   virtual InstantNTP* ntp() const OVERRIDE {
     return test_ntp_;
   }
@@ -131,10 +95,6 @@
     test_extended_enabled_ = extended_enabled;
   }
 
-  void set_overlay(InstantOverlay* overlay) {
-    test_overlay_ = overlay;
-  }
-
   void set_ntp(InstantNTP* ntp) {
     test_ntp_ = ntp;
   }
@@ -173,7 +133,6 @@
   bool override_javascript_enabled_;
   bool test_javascript_enabled_;
   bool test_in_startup_;
-  InstantOverlay* test_overlay_;
   InstantNTP* test_ntp_;
   mutable TestingProfile profile_;
 };
@@ -198,53 +157,6 @@
   scoped_ptr<TestableInstantController> instant_controller_;
 };
 
-TEST_F(InstantControllerTest, ShouldSwitchToLocalOverlay) {
-  InstantController::InstantFallbackReason fallback_reason;
-
-  instant_controller()->set_extended_enabled(false);
-  fallback_reason = instant_controller()->ShouldSwitchToLocalOverlay();
-  ASSERT_EQ(fallback_reason, InstantController::INSTANT_FALLBACK_NONE);
-
-  instant_controller()->set_extended_enabled(true);
-  fallback_reason = instant_controller()->ShouldSwitchToLocalOverlay();
-  ASSERT_EQ(fallback_reason, InstantController::INSTANT_FALLBACK_NO_OVERLAY);
-
-  std::string instant_url("http://test_url");
-  scoped_ptr<TestableInstantOverlay> test_overlay(
-      new TestableInstantOverlay(instant_controller(), instant_url));
-  test_overlay->set_is_local(true);
-  instant_controller()->set_overlay(test_overlay.get());
-  fallback_reason = instant_controller()->ShouldSwitchToLocalOverlay();
-  ASSERT_EQ(fallback_reason, InstantController::INSTANT_FALLBACK_NONE);
-
-  instant_controller()->set_javascript_enabled(false);
-  fallback_reason = instant_controller()->ShouldSwitchToLocalOverlay();
-  ASSERT_EQ(fallback_reason,
-            InstantController::INSTANT_FALLBACK_JAVASCRIPT_DISABLED);
-  instant_controller()->set_javascript_enabled(true);
-
-  test_overlay->set_is_local(false);
-  instant_controller()->set_instant_url("");
-  fallback_reason = instant_controller()->ShouldSwitchToLocalOverlay();
-  ASSERT_EQ(fallback_reason,
-            InstantController::INSTANT_FALLBACK_INSTANT_URL_EMPTY);
-
-  instant_controller()->set_instant_url("http://instant_url");
-  fallback_reason = instant_controller()->ShouldSwitchToLocalOverlay();
-  ASSERT_EQ(fallback_reason,
-            InstantController::INSTANT_FALLBACK_ORIGIN_PATH_MISMATCH);
-
-  instant_controller()->set_instant_url(instant_url);
-  test_overlay->set_supports_instant(false);
-  fallback_reason = instant_controller()->ShouldSwitchToLocalOverlay();
-  ASSERT_EQ(fallback_reason,
-            InstantController::INSTANT_FALLBACK_INSTANT_NOT_SUPPORTED);
-
-  test_overlay->set_supports_instant(true);
-  fallback_reason = instant_controller()->ShouldSwitchToLocalOverlay();
-  ASSERT_EQ(fallback_reason, InstantController::INSTANT_FALLBACK_NONE);
-}
-
 TEST_F(InstantControllerTest, PrefersRemoteNTPOnStartup) {
   std::string instant_url("http://instant_url");
   scoped_ptr<TestableInstantNTP> ntp(new TestableInstantNTP(
diff --git a/chrome/browser/ui/search/instant_extended_interactive_uitest.cc b/chrome/browser/ui/search/instant_extended_interactive_uitest.cc
index c9a6666..344b7e4 100644
--- a/chrome/browser/ui/search/instant_extended_interactive_uitest.cc
+++ b/chrome/browser/ui/search/instant_extended_interactive_uitest.cc
@@ -5,16 +5,16 @@
 #include <sstream>
 
 #include "base/command_line.h"
-#include "base/metrics/field_trial.h"
 #include "base/metrics/histogram_base.h"
 #include "base/metrics/histogram_samples.h"
 #include "base/metrics/statistics_recorder.h"
 #include "base/prefs/pref_service.h"
+#include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/autocomplete/autocomplete_controller.h"
 #include "chrome/browser/autocomplete/autocomplete_match.h"
 #include "chrome/browser/autocomplete/autocomplete_provider.h"
@@ -43,9 +43,7 @@
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/omnibox/omnibox_view.h"
-#include "chrome/browser/ui/search/instant_commit_type.h"
 #include "chrome/browser/ui/search/instant_ntp.h"
-#include "chrome/browser/ui/search/instant_overlay.h"
 #include "chrome/browser/ui/search/instant_tab.h"
 #include "chrome/browser/ui/search/instant_test_utils.h"
 #include "chrome/browser/ui/search/search_tab_helper.h"
@@ -75,6 +73,7 @@
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_utils.h"
 #include "grit/generated_resources.h"
+#include "net/base/network_change_notifier.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -113,6 +112,26 @@
   DISALLOW_COPY_AND_ASSIGN(QuittingHistoryDBTask);
 };
 
+class FakeNetworkChangeNotifier : public net::NetworkChangeNotifier {
+ public:
+  FakeNetworkChangeNotifier() : connection_type_(CONNECTION_NONE) {}
+
+  virtual ConnectionType GetCurrentConnectionType() const OVERRIDE {
+    return connection_type_;
+  }
+
+  void SetConnectionType(ConnectionType type) {
+    connection_type_ = type;
+    NotifyObserversOfNetworkChange(type);
+    base::RunLoop().RunUntilIdle();
+  }
+
+  virtual ~FakeNetworkChangeNotifier() {}
+
+ private:
+  ConnectionType connection_type_;
+  DISALLOW_COPY_AND_ASSIGN(FakeNetworkChangeNotifier);
+};
 }  // namespace
 
 class InstantExtendedTest : public InProcessBrowserTest,
@@ -150,10 +169,6 @@
     return histogram->SnapshotSamples()->TotalCount();
   }
 
-  std::string GetOmniboxText() {
-    return UTF16ToUTF8(omnibox()->GetText());
-  }
-
   void SendDownArrow() {
     omnibox()->model()->OnUpOrDownKeyPressed(1);
     // Wait for JavaScript to run the key handler by executing a blank script.
@@ -251,6 +266,29 @@
   int on_toggle_voice_search_calls_;
 };
 
+class InstantExtendedNetworkTest : public InstantExtendedTest {
+ protected:
+  virtual void SetUpOnMainThread() OVERRIDE {
+    disable_for_test_.reset(new net::NetworkChangeNotifier::DisableForTest);
+    fake_network_change_notifier_.reset(new FakeNetworkChangeNotifier);
+    InstantExtendedTest::SetUpOnMainThread();
+  }
+
+  virtual void CleanUpOnMainThread() OVERRIDE {
+    InstantExtendedTest::CleanUpOnMainThread();
+    fake_network_change_notifier_.reset();
+    disable_for_test_.reset();
+  }
+
+  void SetConnectionType(net::NetworkChangeNotifier::ConnectionType type) {
+    fake_network_change_notifier_->SetConnectionType(type);
+  }
+
+ private:
+  scoped_ptr<net::NetworkChangeNotifier::DisableForTest> disable_for_test_;
+  scoped_ptr<FakeNetworkChangeNotifier> fake_network_change_notifier_;
+};
+
 // Test class used to verify chrome-search: scheme and access policy from the
 // Instant overlay.  This is a subclass of |ExtensionBrowserTest| because it
 // loads a theme that provides a background image.
@@ -295,538 +333,45 @@
   EXPECT_TRUE(instant()->extended_enabled_);
 }
 
-// Test that Instant is preloaded when the omnibox is focused.
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, OmniboxFocusLoadsInstant) {
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-
-  // Explicitly unfocus the omnibox.
-  EXPECT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-  ui_test_utils::ClickOnView(browser(), VIEW_ID_TAB_CONTAINER);
-
-  EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_TAB_CONTAINER));
-  EXPECT_FALSE(omnibox()->model()->has_focus());
-
-  // Delete any existing overlay.
-  instant()->overlay_.reset();
-  EXPECT_FALSE(instant()->GetOverlayContents());
-
-  // Refocus the omnibox. The InstantController should've preloaded Instant.
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-
-  EXPECT_FALSE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_TAB_CONTAINER));
-  EXPECT_TRUE(omnibox()->model()->has_focus());
-
-  content::WebContents* overlay = instant()->GetOverlayContents();
-  EXPECT_TRUE(overlay);
-
-  // Check that the page supports Instant, but it isn't showing.
-  EXPECT_TRUE(instant()->overlay_->supports_instant());
-  EXPECT_FALSE(instant()->IsOverlayingSearchResults());
-  EXPECT_TRUE(instant()->model()->mode().is_default());
-
-  // Adding a new tab shouldn't delete or recreate the overlay; otherwise,
-  // what's the point of preloading?
-  AddBlankTabAndShow(browser());
-  EXPECT_EQ(overlay, instant()->GetOverlayContents());
-
-  // Unfocusing and refocusing the omnibox should also preserve the overlay.
-  ui_test_utils::ClickOnView(browser(), VIEW_ID_TAB_CONTAINER);
-  EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_TAB_CONTAINER));
-
-  FocusOmnibox();
-  EXPECT_FALSE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_TAB_CONTAINER));
-  EXPECT_EQ(overlay, instant()->GetOverlayContents());
-}
-
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, InputShowsOverlay) {
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-
-  // Focus omnibox and confirm overlay isn't shown.
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-  content::WebContents* overlay = instant()->GetOverlayContents();
-  EXPECT_TRUE(overlay);
-  EXPECT_FALSE(instant()->IsOverlayingSearchResults());
-  EXPECT_TRUE(instant()->model()->mode().is_default());
-
-  // Typing in the omnibox should show the overlay.
-  ASSERT_TRUE(SetOmniboxTextAndWaitForOverlayToShow("query"));
-  EXPECT_TRUE(instant()->model()->mode().is_search_suggestions());
-  EXPECT_EQ(overlay, instant()->GetOverlayContents());
-}
-
-// Flaky on Linux Tests bot.
-#if defined(OS_LINUX)
-#define MAYBE_UsesOverlayIfTabNotReady DISABLED_UsesOverlayIfTabNotReady
-#else
-#define MAYBE_UsesOverlayIfTabNotReady UsesOverlayIfTabNotReady
-#endif
-
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, MAYBE_UsesOverlayIfTabNotReady) {
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-
-  // Open a new tab and start typing before InstantTab is properly hooked up.
-  // Should use the overlay.
-  ui_test_utils::NavigateToURLWithDisposition(
-      browser(),
-      GURL(chrome::kChromeUINewTabURL),
-      NEW_FOREGROUND_TAB,
-      ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
-  ASSERT_TRUE(SetOmniboxTextAndWaitForOverlayToShow("query"));
-
-  // But Instant tab should still exist.
-  ASSERT_NE(static_cast<InstantTab*>(NULL), instant()->instant_tab());
-  EXPECT_FALSE(instant()->UseTabForSuggestions());
-
-  // Wait for Instant Tab support if it still hasn't finished loading.
-  if (!instant()->instant_tab()->supports_instant()) {
-    content::WindowedNotificationObserver instant_tab_observer(
-        chrome::NOTIFICATION_INSTANT_TAB_SUPPORT_DETERMINED,
-        content::NotificationService::AllSources());
-    instant_tab_observer.Wait();
-  }
-
-  // Hide the overlay. Now, we should be using Instant tab for suggestions.
-  instant()->HideOverlay();
-  EXPECT_TRUE(instant()->UseTabForSuggestions());
-}
-
-// Flaky on Mac Tests bot. crbug.com/242415
-#if defined(OS_MACOSX)
-#define MAYBE_MiddleClickOnSuggestionOpensInNewTab DISABLED_MiddleClickOnSuggestionOpensInNewTab
-#else
-#define MAYBE_MiddleClickOnSuggestionOpensInNewTab MiddleClickOnSuggestionOpensInNewTab
-#endif
-
-// Test that middle clicking on a suggestion opens the result in a new tab.
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest,
-                       MAYBE_MiddleClickOnSuggestionOpensInNewTab) {
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-  EXPECT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-
-  EXPECT_EQ(1, browser()->tab_strip_model()->count());
-
-  // Typing in the omnibox should show the overlay.
-  ASSERT_TRUE(SetOmniboxTextAndWaitForOverlayToShow("http://www.example.com/"));
-
-  // Create an event listener that opens the top suggestion in a new tab.
-  EXPECT_TRUE(ExecuteScript(
-      "var rid = getApiHandle().nativeSuggestions[0].rid;"
-      "document.body.addEventListener('click', function() {"
-        "chrome.embeddedSearch.navigateContentWindow(rid, 2);"
-      "});"
-      ));
-
-  content::WindowedNotificationObserver observer(
-        chrome::NOTIFICATION_TAB_ADDED,
-        content::NotificationService::AllSources());
-
-  // Click to trigger the event listener.
-  ui_test_utils::ClickOnView(browser(), VIEW_ID_TAB_CONTAINER);
-
-  // Wait for the new tab to be added.
-  observer.Wait();
-
-  // Check that the new tab URL is as expected.
-  content::WebContents* new_tab_contents =
-      browser()->tab_strip_model()->GetWebContentsAt(1);
-  EXPECT_EQ("http://www.example.com/", new_tab_contents->GetURL().spec());
-
-  // Check that there are now two tabs.
-  EXPECT_EQ(2, browser()->tab_strip_model()->count());
-}
-
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest,
-                       UnfocusingOmniboxDoesNotChangeSuggestions) {
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-  EXPECT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-
-  // Get a committed tab to work with.
-  content::WebContents* instant_tab = instant()->GetOverlayContents();
-  ASSERT_TRUE(SetOmniboxTextAndWaitForOverlayToShow("committed"));
-  browser()->window()->GetLocationBar()->AcceptInput();
-
-  // Put focus back into the omnibox, type, and wait for some gray text.
-  EXPECT_TRUE(content::ExecuteScript(instant_tab,
-                                     "suggestion = 'santa claus';"));
-  SetOmniboxTextAndWaitForSuggestion("santa ");
-  EXPECT_EQ(ASCIIToUTF16("claus"), GetGrayText());
-  EXPECT_TRUE(content::ExecuteScript(instant_tab,
-      "onChangeCalls = onNativeSuggestionsCalls = 0;"));
-
-  // Now unfocus the omnibox.
-  ui_test_utils::ClickOnView(browser(), VIEW_ID_TAB_CONTAINER);
-  EXPECT_TRUE(UpdateSearchState(instant_tab));
-  EXPECT_EQ(0, on_change_calls_);
-  EXPECT_EQ(0, on_native_suggestions_calls_);
-}
-
-// Test that omnibox text is correctly set when overlay is committed with Enter.
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, OmniboxTextUponEnterCommit) {
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-
-  // The page will autocomplete once we set the omnibox value.
-  EXPECT_TRUE(ExecuteScript("suggestion = 'santa claus';"));
-
-  // Set the text, and wait for suggestions to show up.
-  ASSERT_TRUE(SetOmniboxTextAndWaitForOverlayToShow("santa"));
-  EXPECT_EQ(ASCIIToUTF16("santa"), omnibox()->GetText());
-
-  // Test that the current suggestion is correctly set.
-  EXPECT_EQ(ASCIIToUTF16(" claus"), GetGrayText());
-
-  // Commit the search by pressing Enter.
-  browser()->window()->GetLocationBar()->AcceptInput();
-
-  // 'Enter' commits the query as it was typed.
-  EXPECT_EQ(ASCIIToUTF16("santa"), omnibox()->GetText());
-
-  // Suggestion should be cleared at this point.
-  EXPECT_EQ(ASCIIToUTF16(""), GetGrayText());
-}
-
-// Test that omnibox text is correctly set when committed with focus lost.
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, OmniboxTextUponFocusLostCommit) {
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-
-  // Set autocomplete text (grey text).
-  EXPECT_TRUE(ExecuteScript("suggestion = 'johnny depp';"));
-
-  // Set the text, and wait for suggestions to show up.
-  ASSERT_TRUE(SetOmniboxTextAndWaitForOverlayToShow("johnny"));
-  EXPECT_EQ(ASCIIToUTF16("johnny"), omnibox()->GetText());
-
-  // Test that the current suggestion is correctly set.
-  EXPECT_EQ(ASCIIToUTF16(" depp"), GetGrayText());
-
-  // Commit the overlay by lost focus (e.g. clicking on the page).
-  instant()->CommitIfPossible(INSTANT_COMMIT_FOCUS_LOST);
-
-  // Omnibox text and suggestion should not be changed.
-  EXPECT_EQ(ASCIIToUTF16("johnny"), omnibox()->GetText());
-  EXPECT_EQ(ASCIIToUTF16(" depp"), GetGrayText());
-}
-
-// Test that omnibox text is correctly set when clicking on committed SERP.
-// Disabled on Mac because omnibox focus loss is not working correctly.
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest,
-                       OmniboxTextUponFocusedCommittedSERP) {
-  // Setup Instant.
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-
-  // Create an observer to wait for the instant tab to support Instant.
-  content::WindowedNotificationObserver observer(
-      chrome::NOTIFICATION_INSTANT_TAB_SUPPORT_DETERMINED,
-      content::NotificationService::AllSources());
-
-  // Do a search and commit it.
-  ASSERT_TRUE(SetOmniboxTextAndWaitForOverlayToShow("hello k"));
-  EXPECT_EQ(ASCIIToUTF16("hello k"), omnibox()->GetText());
-  browser()->window()->GetLocationBar()->AcceptInput();
-  observer.Wait();
-
-  // With a committed results page, do a search by unfocusing the omnibox and
-  // focusing the contents.
-  SetOmniboxText("hello");
-  // Calling handleOnChange manually to make sure it is called before the
-  // Focus() call below.
-  EXPECT_TRUE(content::ExecuteScript(instant()->instant_tab()->contents(),
-                                     "suggestion = 'hello kitty';"
-                                     "handleOnChange();"));
-  instant()->instant_tab()->contents()->GetView()->Focus();
-
-  // Omnibox text and suggestion should not be changed.
-  EXPECT_EQ(ASCIIToUTF16("hello"), omnibox()->GetText());
-  EXPECT_EQ(ASCIIToUTF16(" kitty"), GetGrayText());
-}
-
-// Checks that a previous Navigation suggestion is not re-used when a search
-// suggestion comes in.
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest,
-                       NavigationSuggestionIsDiscardedUponSearchSuggestion) {
-  // Setup Instant.
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-
-  // Tell the page to send a URL suggestion.
-  EXPECT_TRUE(ExecuteScript("suggestion = 'http://www.example.com';"
-                            "behavior = 1;"));
-  ASSERT_TRUE(SetOmniboxTextAndWaitForOverlayToShow("exa"));
-  EXPECT_EQ(ASCIIToUTF16("example.com"), omnibox()->GetText());
-
-  // Now send a search suggestion and see that Navigation suggestion is no
-  // longer kept.
-  EXPECT_TRUE(ExecuteScript("suggestion = 'exams are great';"
-                            "behavior = 2;"));
-  SetOmniboxText("exam");
-  // Wait for JavaScript to run handleOnChange by executing a blank script.
-  EXPECT_TRUE(ExecuteScript(std::string()));
-
-  instant()->overlay()->contents()->GetView()->Focus();
-  EXPECT_EQ(ASCIIToUTF16("exam"), omnibox()->GetText());
-  EXPECT_EQ(ASCIIToUTF16("s are great"), GetGrayText());
-
-  // TODO(jered): Remove this after fixing OnBlur().
-  omnibox()->RevertAll();
-}
-
-// This test simulates a search provider using the InstantExtended API to
-// navigate through the suggested results and back to the original user query.
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, NavigateSuggestionsWithArrowKeys) {
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-
-  ASSERT_TRUE(SetOmniboxTextAndWaitForOverlayToShow("hello"));
-  EXPECT_EQ("hello", GetOmniboxText());
-
-  SendDownArrow();
-  EXPECT_EQ("result 1", GetOmniboxText());
-  SendDownArrow();
-  EXPECT_EQ("result 2", GetOmniboxText());
-  SendUpArrow();
-  EXPECT_EQ("result 1", GetOmniboxText());
-  SendUpArrow();
-  EXPECT_EQ("hello", GetOmniboxText());
-
-  // Ensure that the API's value is set correctly.
-  std::string result;
-  EXPECT_TRUE(GetStringFromJS(instant()->GetOverlayContents(),
-                              "window.chrome.searchBox.value",
-                              &result));
-  EXPECT_EQ("hello", result);
-
-  EXPECT_TRUE(HasUserInputInProgress());
-  // TODO(beaudoin): Figure out why this fails.
-  // EXPECT_FALSE(HasTemporaryText());
-
-  // Commit the search by pressing Enter.
-  browser()->window()->GetLocationBar()->AcceptInput();
-  EXPECT_EQ("hello", GetOmniboxText());
-}
-
-// Flaky on Linux Tests bot.  See http://crbug.com/233090.
-#if defined(OS_LINUX)
-#define MAYBE_NavigateToURLSuggestionHitEnterAndLookForSubmit DISABLED_NavigateToURLSuggestionHitEnterAndLookForSubmit
-#else
-#define MAYBE_NavigateToURLSuggestionHitEnterAndLookForSubmit NavigateToURLSuggestionHitEnterAndLookForSubmit
-#endif
-
-// This test simulates a search provider using the InstantExtended API to
-// navigate through the suggested results and back to the original user query.
-// If this test starts to flake, it may be that the second call to AcceptInput
-// below causes instant()->instant_tab() to no longer be valid due to e.g. a
-// navigation. In that case, see https://codereview.chromium.org/12895007/#msg28
-// and onwards for possible alternatives.
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest,
-                       MAYBE_NavigateToURLSuggestionHitEnterAndLookForSubmit) {
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-
-  // Create an observer to wait for the instant tab to support Instant.
-  content::WindowedNotificationObserver observer(
-      chrome::NOTIFICATION_INSTANT_TAB_SUPPORT_DETERMINED,
-      content::NotificationService::AllSources());
-
-  // Do a search and commit it.
-  ASSERT_TRUE(SetOmniboxTextAndWaitForOverlayToShow("hello k"));
-  EXPECT_EQ(ASCIIToUTF16("hello k"), omnibox()->GetText());
-  browser()->window()->GetLocationBar()->AcceptInput();
-  observer.Wait();
-
-  SetOmniboxText("http");
-  EXPECT_EQ("http", GetOmniboxText());
-
-  SendDownArrow();
-  EXPECT_EQ("result 1", GetOmniboxText());
-  SendDownArrow();
-  EXPECT_EQ("result 2", GetOmniboxText());
-
-  // Set the next suggestion to be of type INSTANT_SUGGESTION_URL.
-  EXPECT_TRUE(content::ExecuteScript(instant()->instant_tab()->contents(),
-                                     "suggestionType = 1;"));
-  SendDownArrow();
-  EXPECT_EQ("http://www.google.com", GetOmniboxText());
-
-  EXPECT_TRUE(HasUserInputInProgress());
-
-  EXPECT_TRUE(UpdateSearchState(instant()->instant_tab()->contents()));
-  // Note the commit count is initially 1 due to the AcceptInput() call above.
-  EXPECT_EQ(1, submit_count_);
-
-  std::string old_query_value(query_value_);
-
-  // Commit the search by pressing Enter.
-  browser()->window()->GetLocationBar()->AcceptInput();
-
-  // Make sure a submit message got sent.
-  EXPECT_TRUE(UpdateSearchState(instant()->instant_tab()->contents()));
-  EXPECT_EQ(2, submit_count_);
-  EXPECT_EQ(old_query_value, query_value_);
-}
-
-// This test simulates a search provider using the InstantExtended API to
-// navigate through the suggested results and hitting escape to get back to the
-// original user query.
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, NavigateSuggestionsAndHitEscape) {
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-
-  ASSERT_TRUE(SetOmniboxTextAndWaitForOverlayToShow("hello"));
-  EXPECT_EQ("hello", GetOmniboxText());
-
-  SendDownArrow();
-  EXPECT_EQ("result 1", GetOmniboxText());
-  SendDownArrow();
-  EXPECT_EQ("result 2", GetOmniboxText());
-  SendEscape();
-  EXPECT_EQ("hello", GetOmniboxText());
-
-  // Ensure that the API's value is set correctly.
-  std::string result;
-  EXPECT_TRUE(GetStringFromJS(instant()->GetOverlayContents(),
-                              "window.chrome.searchBox.value",
-                              &result));
-  EXPECT_EQ("hello", result);
-
-  EXPECT_TRUE(HasUserInputInProgress());
-  EXPECT_FALSE(HasTemporaryText());
-
-  // Commit the search by pressing Enter.
-  browser()->window()->GetLocationBar()->AcceptInput();
-  EXPECT_EQ("hello", GetOmniboxText());
-}
-
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, PressEscapeWithBlueText) {
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-
-  // Set blue text completion.
-  EXPECT_TRUE(ExecuteScript("suggestion = 'chimichanga.com';"
-                            "behavior = 1;"));
-
-  ASSERT_TRUE(SetOmniboxTextAndWaitForOverlayToShow("chimi"));
-
-  EXPECT_EQ(ASCIIToUTF16("chimichanga.com"), omnibox()->GetText());
-  EXPECT_EQ(ASCIIToUTF16("changa.com"), GetBlueText());
-  EXPECT_EQ(ASCIIToUTF16(""), GetGrayText());
-
-  EXPECT_TRUE(ExecuteScript("onChangeCalls = onNativeSuggestionsCalls = 0;"));
-
-  SendDownArrow();
-
-  EXPECT_EQ(ASCIIToUTF16("result 1"), omnibox()->GetText());
-  EXPECT_EQ(ASCIIToUTF16(""), GetBlueText());
-  EXPECT_EQ(ASCIIToUTF16(""), GetGrayText());
-
-  content::WindowedNotificationObserver observer(
-      chrome::NOTIFICATION_INSTANT_SET_SUGGESTION,
-      content::NotificationService::AllSources());
-  SendEscape();
-  observer.Wait();
-
-  EXPECT_EQ(ASCIIToUTF16("chimichanga.com"), omnibox()->GetText());
-  EXPECT_EQ(ASCIIToUTF16("changa.com"), GetBlueText());
-  EXPECT_EQ(ASCIIToUTF16(""), GetGrayText());
-
-  EXPECT_TRUE(UpdateSearchState(instant()->GetOverlayContents()));
-  EXPECT_EQ(0, on_native_suggestions_calls_);
-  EXPECT_EQ(0, on_change_calls_);
-}
-
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, PressEscapeWithGrayText) {
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-
-  // Set gray text completion.
-  EXPECT_TRUE(ExecuteScript("suggestion = 'cowabunga';"
-                            "behavior = 2;"));
-
-  ASSERT_TRUE(SetOmniboxTextAndWaitForOverlayToShow("cowa"));
-
-  EXPECT_EQ(ASCIIToUTF16("cowa"), omnibox()->GetText());
-  EXPECT_EQ(ASCIIToUTF16(""), GetBlueText());
-  EXPECT_EQ(ASCIIToUTF16("bunga"), GetGrayText());
-
-  EXPECT_TRUE(ExecuteScript("onChangeCalls = onNativeSuggestionsCalls = 0;"));
-
-  SendDownArrow();
-
-  EXPECT_EQ(ASCIIToUTF16("result 1"), omnibox()->GetText());
-  EXPECT_EQ(ASCIIToUTF16(""), GetBlueText());
-  EXPECT_EQ(ASCIIToUTF16(""), GetGrayText());
-
-  content::WindowedNotificationObserver observer(
-      chrome::NOTIFICATION_INSTANT_SET_SUGGESTION,
-      content::NotificationService::AllSources());
-  SendEscape();
-  observer.Wait();
-
-  EXPECT_EQ(ASCIIToUTF16("cowa"), omnibox()->GetText());
-  EXPECT_EQ(ASCIIToUTF16(""), GetBlueText());
-  EXPECT_EQ(ASCIIToUTF16("bunga"), GetGrayText());
-
-  EXPECT_TRUE(UpdateSearchState(instant()->GetOverlayContents()));
-  EXPECT_EQ(0, on_native_suggestions_calls_);
-  EXPECT_EQ(0, on_change_calls_);
-}
-
 IN_PROC_BROWSER_TEST_F(InstantExtendedTest, NTPIsPreloaded) {
   // Setup Instant.
   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
+  FocusOmniboxAndWaitForInstantNTPSupport();
 
   // NTP contents should be preloaded.
   ASSERT_NE(static_cast<InstantNTP*>(NULL), instant()->ntp());
   content::WebContents* ntp_contents = instant()->ntp_->contents();
   EXPECT_TRUE(ntp_contents);
 }
+#endif  // HTML_INSTANT_EXTENDED_POPUP
 
-// Test that the local NTP is preloaded.
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, LocalOnlyNTPIsPreloaded) {
+IN_PROC_BROWSER_TEST_F(InstantExtendedNetworkTest, NTPReactsToNetworkChanges) {
   // Setup Instant.
   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
+  FocusOmniboxAndWaitForInstantNTPSupport();
 
-  // The second argument says to use only the local overlay and NTP.
-  instant()->SetInstantEnabled(false, true);
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
+  // The setup first initializes the platform specific NetworkChangeNotifier.
+  // The InstantExtendedNetworkTest replaces it with a fake, but by the time,
+  // instant controller has already registered itself. So the instant controller
+  // needs to register itself as NetworkChangeObserver again.
+  net::NetworkChangeNotifier::AddNetworkChangeObserver(browser_instant());
 
-  // NTP contents should be preloaded.
+  // The fake network change notifier will provide the network state to be
+  // offline, so the ntp will be local.
   ASSERT_NE(static_cast<InstantNTP*>(NULL), instant()->ntp());
-  content::WebContents* ntp_contents = instant()->ntp_->contents();
-  EXPECT_NE(static_cast<content::WebContents*>(NULL), ntp_contents);
   EXPECT_TRUE(instant()->ntp()->IsLocal());
-}
 
-// Test that the local NTP is not preloaded.
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, LocalOnlyNTPIsNotPreloaded) {
-  // Setup Instant.
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  ASSERT_TRUE(base::FieldTrialList::CreateTrialsFromString(
-      "InstantExtended/Group1 local_only:1 preload_local_only_ntp:0/"));
+  // Change the connect state, and wait for the notifications to be run, and NTP
+  // support to be determined.
+  SetConnectionType(net::NetworkChangeNotifier::CONNECTION_ETHERNET);
+  FocusOmniboxAndWaitForInstantNTPSupport();
 
-  // The second argument says to use only the local overlay and NTP.
-  instant()->SetInstantEnabled(false, true);
+  // Verify the network state is fine, and instant controller doesn't want to
+  // switch to local NTP anymore.
+  EXPECT_FALSE(net::NetworkChangeNotifier::IsOffline());
+  EXPECT_FALSE(instant()->ShouldSwitchToLocalNTP());
 
-  // NTP contents should not be preloaded.
-  EXPECT_EQ(NULL, instant()->ntp());
-}
-
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, PreloadedNTPIsUsedInNewTab) {
-  // Setup Instant.
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-
-  // NTP contents should be preloaded.
-  ASSERT_NE(static_cast<InstantNTP*>(NULL), instant()->ntp());
-  content::WebContents* ntp_contents = instant()->ntp_->contents();
-  EXPECT_TRUE(ntp_contents);
-
-  // Open new tab. Preloaded NTP contents should have been used.
+  // Open new tab.
   ui_test_utils::NavigateToURLWithDisposition(
       browser(),
       GURL(chrome::kChromeUINewTabURL),
@@ -834,14 +379,41 @@
       ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
   content::WebContents* active_tab =
       browser()->tab_strip_model()->GetActiveWebContents();
-  EXPECT_EQ(ntp_contents, active_tab);
+
+  // Verify new NTP is not local.
   EXPECT_TRUE(chrome::IsInstantNTP(active_tab));
+  EXPECT_NE(instant()->GetLocalInstantURL(), active_tab->GetURL().spec());
+  ASSERT_NE(static_cast<InstantNTP*>(NULL), instant()->ntp());
+  EXPECT_FALSE(instant()->ntp()->IsLocal());
+
+  SetConnectionType(net::NetworkChangeNotifier::CONNECTION_NONE);
+  FocusOmniboxAndWaitForInstantNTPSupport();
+
+  // Verify the network state is fine, and instant controller doesn't want to
+  // switch to local NTP anymore.
+  EXPECT_TRUE(net::NetworkChangeNotifier::IsOffline());
+  EXPECT_TRUE(instant()->ShouldSwitchToLocalNTP());
+
+  // Open new tab. Preloaded NTP contents should have been used.
+  ui_test_utils::NavigateToURLWithDisposition(
+      browser(),
+      GURL(chrome::kChromeUINewTabURL),
+      NEW_FOREGROUND_TAB,
+      ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
+  active_tab = browser()->tab_strip_model()->GetActiveWebContents();
+
+  // Verify new NTP is not local.
+  EXPECT_TRUE(chrome::IsInstantNTP(active_tab));
+  EXPECT_EQ(instant()->GetLocalInstantURL(), active_tab->GetURL().spec());
+  ASSERT_NE(static_cast<InstantNTP*>(NULL), instant()->ntp());
+  EXPECT_TRUE(instant()->ntp()->IsLocal());
 }
 
+#if defined(HTML_INSTANT_EXTENDED_POPUP)
 IN_PROC_BROWSER_TEST_F(InstantExtendedTest, PreloadedNTPIsUsedInSameTab) {
   // Setup Instant.
   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
+  FocusOmniboxAndWaitForInstantNTPSupport();
 
   // NTP contents should be preloaded.
   ASSERT_NE(static_cast<InstantNTP*>(NULL), instant()->ntp());
@@ -863,7 +435,7 @@
 IN_PROC_BROWSER_TEST_F(InstantExtendedTest, PreloadedNTPForWrongProvider) {
   // Setup Instant.
   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
+  FocusOmniboxAndWaitForInstantNTPSupport();
 
   // NTP contents should be preloaded.
   ASSERT_NE(static_cast<InstantNTP*>(NULL), instant()->ntp());
@@ -888,7 +460,7 @@
 IN_PROC_BROWSER_TEST_F(InstantExtendedTest, PreloadedNTPRenderViewGone) {
   // Setup Instant.
   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
+  FocusOmniboxAndWaitForInstantNTPSupport();
 
   // NTP contents should be preloaded.
   ASSERT_NE(static_cast<InstantNTP*>(NULL), instant()->ntp());
@@ -914,7 +486,7 @@
   GURL instant_url = test_server()->GetURL("files/empty.html?strk=1");
   InstantTestBase::Init(instant_url);
   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
+  FocusOmniboxAndWaitForInstantNTPSupport();
 
   // NTP contents should have fallen back to the local page.
   ASSERT_NE(static_cast<InstantNTP*>(NULL), instant()->ntp());
@@ -935,7 +507,7 @@
 IN_PROC_BROWSER_TEST_F(InstantExtendedTest, DISABLED_OmniboxHasFocusOnNewTab) {
   // Setup Instant.
   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
+  FocusOmniboxAndWaitForInstantNTPSupport();
 
   // Explicitly unfocus the omnibox.
   EXPECT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
@@ -956,7 +528,7 @@
 IN_PROC_BROWSER_TEST_F(InstantExtendedTest, OmniboxEmptyOnNewTabPage) {
   // Setup Instant.
   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
+  FocusOmniboxAndWaitForInstantNTPSupport();
 
   // Open new tab. Preloaded NTP contents should have been used.
   ui_test_utils::NavigateToURLWithDisposition(
@@ -972,7 +544,7 @@
 IN_PROC_BROWSER_TEST_F(InstantExtendedTest, NoFaviconOnNewTabPage) {
   // Setup Instant.
   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
+  FocusOmniboxAndWaitForInstantNTPSupport();
 
   // Open new tab. Preloaded NTP contents should have been used.
   ui_test_utils::NavigateToURLWithDisposition(
@@ -995,31 +567,8 @@
   EXPECT_TRUE(favicon_tab_helper->ShouldDisplayFavicon());
 }
 
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, InputOnNTPDoesntShowOverlay) {
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-
-  // Focus omnibox and confirm overlay isn't shown.
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-  content::WebContents* overlay = instant()->GetOverlayContents();
-  EXPECT_TRUE(overlay);
-  EXPECT_FALSE(instant()->IsOverlayingSearchResults());
-  EXPECT_TRUE(instant()->model()->mode().is_default());
-
-  // Navigate to the NTP. Should use preloaded contents.
-  ui_test_utils::NavigateToURLWithDisposition(
-      browser(),
-      GURL(chrome::kChromeUINewTabURL),
-      CURRENT_TAB,
-      ui_test_utils::BROWSER_TEST_NONE);
-
-  // Typing in the omnibox should not show the overlay.
-  SetOmniboxText("query");
-  EXPECT_FALSE(instant()->IsOverlayingSearchResults());
-  EXPECT_TRUE(instant()->model()->mode().is_default());
-}
-
 IN_PROC_BROWSER_TEST_F(InstantExtendedTest, ProcessIsolation) {
-  // Prior to setup, Instant has an overlay with a failed "google.com" load in
+  // Prior to setup, Instant has an ntp with a failed "google.com" load in
   // it, which is rendered in the dedicated Instant renderer process.
   //
   // TODO(sreeram): Fix this up when we stop doing crazy things on init.
@@ -1034,15 +583,11 @@
 
   // Setup Instant.
   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
+  FocusOmniboxAndWaitForInstantNTPSupport();
 
   // The registered Instant render process should still exist.
   EXPECT_EQ(1, instant_service->GetInstantProcessCount());
-
-  // And the Instant overlay and ntp should live inside it.
-  content::WebContents* overlay = instant()->GetOverlayContents();
-  EXPECT_TRUE(instant_service->IsInstantProcess(
-      overlay->GetRenderProcessHost()->GetID()));
+  // And the Instant ntp should live inside it.
   content::WebContents* ntp_contents = instant()->ntp_->contents();
   EXPECT_TRUE(instant_service->IsInstantProcess(
       ntp_contents->GetRenderProcessHost()->GetID()));
@@ -1064,235 +609,24 @@
       active_tab->GetRenderProcessHost()->GetID()));
 }
 
-// Test that a search query will not be displayed for navsuggest queries.
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest,
-                       SearchQueryNotDisplayedForNavsuggest) {
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-
-  // The second argument indicates to use only the local overlay and NTP.
-  instant()->SetInstantEnabled(true, true);
-
-  // Focus omnibox and confirm overlay isn't shown.
-  FocusOmniboxAndWaitForInstantOverlaySupport();
-
-  // Typing in the omnibox should show the overlay.
-  SetOmniboxText("face");
-
-  content::WebContents* overlay = instant()->GetOverlayContents();
-
-  // Add a navsuggest suggestion.
-  instant()->SetSuggestions(
-      overlay,
-      std::vector<InstantSuggestion>(
-          1,
-          InstantSuggestion(ASCIIToUTF16("http://facemash.com/"),
-                            INSTANT_COMPLETE_NOW,
-                            INSTANT_SUGGESTION_URL,
-                            ASCIIToUTF16("face"),
-                            kNoMatchIndex)));
-
-  while (!omnibox()->model()->autocomplete_controller()->done()) {
-    content::WindowedNotificationObserver autocomplete_observer(
-        chrome::NOTIFICATION_AUTOCOMPLETE_CONTROLLER_RESULT_READY,
-        content::NotificationService::AllSources());
-    autocomplete_observer.Wait();
-  }
-
-  EXPECT_TRUE(ExecuteScript(
-      "var sorted = chrome.embeddedSearch.searchBox.nativeSuggestions.sort("
-          "function (a,b) {"
-            "return b.rankingData.relevance - a.rankingData.relevance;"
-          "});"));
-
-  int suggestions_count = -1;
-  EXPECT_TRUE(GetIntFromJS(
-      overlay, "sorted.length", &suggestions_count));
-  ASSERT_GT(suggestions_count, 0);
-
-  std::string type;
-  EXPECT_TRUE(
-      GetStringFromJS(overlay, "sorted[0].type", &type));
-  ASSERT_EQ("navsuggest", type);
-
-  bool is_search;
-  EXPECT_TRUE(GetBoolFromJS(
-      overlay, "!!sorted[0].is_search", &is_search));
-  EXPECT_FALSE(is_search);
-}
-
-// Verification of fix for BUG=176365.  Ensure that each Instant WebContents in
-// a tab uses a new BrowsingInstance, to avoid conflicts in the
-// NavigationController.
-// Flaky: http://crbug.com/177516
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, DISABLED_UnrelatedSiteInstance) {
-  // Setup Instant.
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-
-  // Check that the uncommited ntp page and uncommited overlay have unrelated
-  // site instances.
-  // TODO(sreeram): |ntp_| is going away, so this check can be removed in the
-  // future.
-  content::WebContents* overlay = instant()->GetOverlayContents();
-  content::WebContents* ntp_contents = instant()->ntp_->contents();
-  EXPECT_FALSE(overlay->GetSiteInstance()->IsRelatedSiteInstance(
-      ntp_contents->GetSiteInstance()));
-
-  // Type a query and hit enter to get a results page.  The overlay becomes the
-  // active tab.
-  ASSERT_TRUE(SetOmniboxTextAndWaitForOverlayToShow("hello"));
-  EXPECT_EQ("hello", GetOmniboxText());
-  browser()->window()->GetLocationBar()->AcceptInput();
-  content::WebContents* first_active_tab =
-      browser()->tab_strip_model()->GetActiveWebContents();
-  EXPECT_EQ(first_active_tab, overlay);
-  scoped_refptr<content::SiteInstance> first_site_instance =
-      first_active_tab->GetSiteInstance();
-  EXPECT_FALSE(first_site_instance->IsRelatedSiteInstance(
-      ntp_contents->GetSiteInstance()));
-
-  // Navigating elsewhere gets us off of the commited page.  The next
-  // query will give us a new |overlay| which we will then commit.
-  ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIAboutURL));
-
-  // Show and commit the new overlay.
-  ASSERT_TRUE(SetOmniboxTextAndWaitForOverlayToShow("hello again"));
-  EXPECT_EQ("hello again", GetOmniboxText());
-  browser()->window()->GetLocationBar()->AcceptInput();
-  content::WebContents* second_active_tab =
-      browser()->tab_strip_model()->GetActiveWebContents();
-  EXPECT_NE(first_active_tab, second_active_tab);
-  scoped_refptr<content::SiteInstance> second_site_instance =
-      second_active_tab->GetSiteInstance();
-  EXPECT_NE(first_site_instance, second_site_instance);
-  EXPECT_FALSE(
-      first_site_instance->IsRelatedSiteInstance(second_site_instance.get()));
-}
-
-// Tests that suggestions are sanity checked.
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, ValidatesSuggestions) {
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-
-  // Do not set gray text that is not a suffix of the query.
-  EXPECT_TRUE(ExecuteScript("suggestion = 'potato';"
-                            "behavior = 2;"));
-  ASSERT_TRUE(SetOmniboxTextAndWaitForOverlayToShow("query"));
-  EXPECT_EQ(ASCIIToUTF16("query"), omnibox()->GetText());
-  EXPECT_EQ(ASCIIToUTF16(""), GetGrayText());
-
-  omnibox()->RevertAll();
-
-  // Do not set blue text that is not a valid URL completion.
-  EXPECT_TRUE(ExecuteScript("suggestion = 'this is not a url!';"
-                            "behavior = 1;"));
-  ASSERT_TRUE(SetOmniboxTextAndWaitForOverlayToShow("this is"));
-  EXPECT_EQ(ASCIIToUTF16("this is"), omnibox()->GetText());
-  EXPECT_EQ(ASCIIToUTF16(""), GetGrayText());
-
-  omnibox()->RevertAll();
-
-  // Do not set gray text when blue text is already set.
-  // First set up some blue text completion.
-  EXPECT_TRUE(ExecuteScript("suggestion = 'www.example.com';"
-                            "behavior = 1;"));
-  ASSERT_TRUE(SetOmniboxTextAndWaitForOverlayToShow("http://www.ex"));
-  EXPECT_EQ(ASCIIToUTF16("http://www.example.com"), omnibox()->GetText());
-  EXPECT_EQ(ASCIIToUTF16("ample.com"), GetBlueText());
-
-  // Now try to set gray text for the same query.
-  EXPECT_TRUE(ExecuteScript("suggestion = 'www.example.com rocks';"
-                            "behavior = 2;"));
-  SetOmniboxText("http://www.ex");
-  EXPECT_EQ(ASCIIToUTF16("http://www.example.com"), omnibox()->GetText());
-  EXPECT_EQ(ASCIIToUTF16(""), GetGrayText());
-
-  omnibox()->RevertAll();
-
-  // Ignore an out-of-date blue text suggestion. (Simulates a laggy
-  // SetSuggestion IPC by directly calling into InstantController.)
-  ASSERT_TRUE(SetOmniboxTextAndWaitForOverlayToShow("http://www.example.com/"));
-  instant()->SetSuggestions(
-      instant()->overlay()->contents(),
-      std::vector<InstantSuggestion>(
-          1,
-          InstantSuggestion(ASCIIToUTF16("www.exa"),
-                            INSTANT_COMPLETE_NOW,
-                            INSTANT_SUGGESTION_URL,
-                            ASCIIToUTF16("www.exa"),
-                            kNoMatchIndex)));
-  EXPECT_EQ(
-      "http://www.example.com/",
-      omnibox()->model()->result().default_match()->destination_url.spec());
-
-  omnibox()->RevertAll();
-
-  // TODO(samarth): uncomment after fixing crbug.com/191656.
-  // Use an out-of-date blue text suggestion, if the text typed by the user is
-  // contained in the suggestion.
-  // ASSERT_TRUE(SetOmniboxTextAndWaitForOverlayToShow("ex"));
-  // instant()->SetSuggestions(
-  //     instant()->overlay()->contents(),
-  //     std::vector<InstantSuggestion>(
-  //         1,
-  //         InstantSuggestion(ASCIIToUTF16("www.example.com"),
-  //                           INSTANT_COMPLETE_NOW,
-  //                           INSTANT_SUGGESTION_URL,
-  //                           ASCIIToUTF16("e"))));
-  // EXPECT_EQ(
-  //     "http://www.example.com/",
-  //     omnibox()->model()->result().default_match()->destination_url.spec());
-
-  // omnibox()->RevertAll();
-
-  // When asked to suggest blue text in verbatim mode, suggest the exact
-  // omnibox text rather than using the supplied suggestion text.
-  EXPECT_TRUE(ExecuteScript("suggestion = 'www.example.com/q';"
-                            "behavior = 1;"));
-  SetOmniboxText("www.example.com/q");
-  omnibox()->OnBeforePossibleChange();
-  SetOmniboxText("www.example.com/");
-  omnibox()->OnAfterPossibleChange();
-  EXPECT_EQ(ASCIIToUTF16("www.example.com/"), omnibox()->GetText());
-}
-
-// Tests that a previous navigation suggestion is not discarded if it's not
-// stale.
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest,
-                       NavigationSuggestionIsNotDiscarded) {
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-
-  // Tell the page to send a URL suggestion.
-  EXPECT_TRUE(ExecuteScript("suggestion = 'http://www.example.com';"
-                            "behavior = 1;"));
-  ASSERT_TRUE(SetOmniboxTextAndWaitForOverlayToShow("exa"));
-  EXPECT_EQ(ASCIIToUTF16("example.com"), omnibox()->GetText());
-  SetOmniboxText("exam");
-  EXPECT_EQ(ASCIIToUTF16("example.com"), omnibox()->GetText());
-
-  // TODO(jered): Remove this after fixing OnBlur().
-  omnibox()->RevertAll();
-}
-
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, MostVisited) {
+IN_PROC_BROWSER_TEST_F(InstantExtendedTest, DISABLED_MostVisited) {
   content::WindowedNotificationObserver observer(
       chrome::NOTIFICATION_INSTANT_SENT_MOST_VISITED_ITEMS,
       content::NotificationService::AllSources());
   // Initialize Instant.
   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
+  FocusOmniboxAndWaitForInstantNTPSupport();
 
   // Get a handle to the NTP and the current state of the JS.
   ASSERT_NE(static_cast<InstantNTP*>(NULL), instant()->ntp());
-  content::WebContents* overlay = instant()->ntp_->contents();
-  EXPECT_TRUE(overlay);
-  EXPECT_TRUE(UpdateSearchState(overlay));
+  content::WebContents* ntp = instant()->ntp_->contents();
+  EXPECT_TRUE(ntp);
+  EXPECT_TRUE(UpdateSearchState(ntp));
 
   // Wait for most visited data to be ready, if necessary.
   if (on_most_visited_change_calls_ == 0) {
     observer.Wait();
-    EXPECT_TRUE(UpdateSearchState(overlay));
+    EXPECT_TRUE(UpdateSearchState(ntp));
   }
 
   EXPECT_EQ(1, on_most_visited_change_calls_);
@@ -1308,11 +642,11 @@
   int rid = first_most_visited_item_id_;
   std::ostringstream stream;
   stream << "newTabPageHandle.deleteMostVisitedItem(" << rid << ");";
-  EXPECT_TRUE(ExecuteScript(stream.str()));
+  EXPECT_TRUE(content::ExecuteScript(ntp, stream.str()));
   observer.Wait();
 
   // Update Most Visited state.
-  EXPECT_TRUE(UpdateSearchState(overlay));
+  EXPECT_TRUE(UpdateSearchState(ntp));
 
   // Make sure we have one less item in there.
   EXPECT_EQ(most_visited_items_count_, old_most_visited_items_count - 1);
@@ -1320,11 +654,11 @@
   // Undo the deletion of the fist Most Visited Item.
   stream.str(std::string());
   stream << "newTabPageHandle.undoMostVisitedDeletion(" << rid << ");";
-  EXPECT_TRUE(ExecuteScript(stream.str()));
+  EXPECT_TRUE(content::ExecuteScript(ntp, stream.str()));
   observer.Wait();
 
   // Update Most Visited state.
-  EXPECT_TRUE(UpdateSearchState(overlay));
+  EXPECT_TRUE(UpdateSearchState(ntp));
 
   // Make sure we have the same number of items as before.
   EXPECT_EQ(most_visited_items_count_, old_most_visited_items_count);
@@ -1333,21 +667,21 @@
   rid = first_most_visited_item_id_;
   stream.str(std::string());
   stream << "newTabPageHandle.deleteMostVisitedItem(" << rid << ");";
-  EXPECT_TRUE(ExecuteScript(stream.str()));
+  EXPECT_TRUE(content::ExecuteScript(ntp, stream.str()));
   observer.Wait();
 
   // Update Most Visited state.
-  EXPECT_TRUE(UpdateSearchState(overlay));
+  EXPECT_TRUE(UpdateSearchState(ntp));
 
   // Delete the second Most Visited Item.
   rid = first_most_visited_item_id_;
   stream.str(std::string());
   stream << "newTabPageHandle.deleteMostVisitedItem(" << rid << ");";
-  EXPECT_TRUE(ExecuteScript(stream.str()));
+  EXPECT_TRUE(content::ExecuteScript(ntp, stream.str()));
   observer.Wait();
 
   // Update Most Visited state.
-  EXPECT_TRUE(UpdateSearchState(overlay));
+  EXPECT_TRUE(UpdateSearchState(ntp));
 
   // Make sure we have two less items in there.
   EXPECT_EQ(most_visited_items_count_, old_most_visited_items_count - 2);
@@ -1355,43 +689,16 @@
   // Delete the second Most Visited Item.
   stream.str(std::string());
   stream << "newTabPageHandle.undoAllMostVisitedDeletions();";
-  EXPECT_TRUE(ExecuteScript(stream.str()));
+  EXPECT_TRUE(content::ExecuteScript(ntp, stream.str()));
   observer.Wait();
 
   // Update Most Visited state.
-  EXPECT_TRUE(UpdateSearchState(overlay));
+  EXPECT_TRUE(UpdateSearchState(ntp));
 
   // Make sure we have the same number of items as before.
   EXPECT_EQ(most_visited_items_count_, old_most_visited_items_count);
 }
 
-IN_PROC_BROWSER_TEST_F(InstantPolicyTest, ThemeBackgroundAccess) {
-  InstallThemeSource();
-  ASSERT_NO_FATAL_FAILURE(InstallThemeAndVerify("theme", "camo theme"));
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-
-  // The "Instant" New Tab should have access to chrome-search: scheme but not
-  // chrome: scheme.
-  ui_test_utils::NavigateToURLWithDisposition(
-      browser(),
-      GURL(chrome::kChromeUINewTabURL),
-      NEW_FOREGROUND_TAB,
-      ui_test_utils::BROWSER_TEST_NONE);
-
-  content::RenderViewHost* rvh =
-      browser()->tab_strip_model()->GetActiveWebContents()->GetRenderViewHost();
-
-  const std::string chrome_url("chrome://theme/IDR_THEME_NTP_BACKGROUND");
-  const std::string search_url(
-      "chrome-search://theme/IDR_THEME_NTP_BACKGROUND");
-  bool loaded = false;
-  ASSERT_TRUE(LoadImage(rvh, chrome_url, &loaded));
-  EXPECT_FALSE(loaded) << chrome_url;
-  ASSERT_TRUE(LoadImage(rvh, search_url, &loaded));
-  EXPECT_TRUE(loaded) << search_url;
-}
-
 // TODO(dhollowa): Fix flakes.  http://crbug.com/179930.
 IN_PROC_BROWSER_TEST_F(InstantExtendedTest, DISABLED_FaviconAccess) {
   // Create a favicon.
@@ -1402,7 +709,7 @@
   EXPECT_TRUE(top_sites->SetPageThumbnail(url, thumbnail, high_score));
 
   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
+  FocusOmniboxAndWaitForInstantNTPSupport();
 
   // The "Instant" New Tab should have access to chrome-search: scheme but not
   // chrome: scheme.
@@ -1427,10 +734,46 @@
   EXPECT_TRUE(loaded) << search_favicon_url;
 }
 
+// Only implemented in Views and Mac currently: http://crbug.com/164723
+#if defined(OS_WIN) || defined(OS_CHROMEOS) || defined(OS_MACOSX)
+#define MAYBE_HomeButtonAffectsMargin HomeButtonAffectsMargin
+#else
+#define MAYBE_HomeButtonAffectsMargin DISABLED_HomeButtonAffectsMargin
+#endif
+
+// Check that toggling the state of the home button changes the start-edge
+// margin and width.
+IN_PROC_BROWSER_TEST_F(InstantExtendedTest, MAYBE_HomeButtonAffectsMargin) {
+  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
+  FocusOmniboxAndWaitForInstantNTPSupport();
+
+  // Get the current value of the start-edge margin and width.
+  int start_margin;
+  int width;
+  content::WebContents* ntp = instant()->ntp_->contents();
+  EXPECT_TRUE(GetIntFromJS(ntp, "chrome.searchBox.startMargin", &start_margin));
+  EXPECT_TRUE(GetIntFromJS(ntp, "chrome.searchBox.width", &width));
+
+  // Toggle the home button visibility pref.
+  PrefService* profile_prefs = browser()->profile()->GetPrefs();
+  bool show_home = profile_prefs->GetBoolean(prefs::kShowHomeButton);
+  profile_prefs->SetBoolean(prefs::kShowHomeButton, !show_home);
+
+  // Make sure the margin and width changed.
+  int new_start_margin;
+  int new_width;
+  EXPECT_TRUE(GetIntFromJS(ntp, "chrome.searchBox.startMargin",
+      &new_start_margin));
+  EXPECT_TRUE(GetIntFromJS(ntp, "chrome.searchBox.width", &new_width));
+  EXPECT_NE(start_margin, new_start_margin);
+  EXPECT_NE(width, new_width);
+  EXPECT_EQ(new_width - width, start_margin - new_start_margin);
+}
+
 // WebUIBindings should never be enabled on ANY Instant web contents.
 IN_PROC_BROWSER_TEST_F(InstantExtendedTest, NoWebUIBindingsOnNTP) {
   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
+  FocusOmniboxAndWaitForInstantNTPSupport();
 
   ui_test_utils::NavigateToURLWithDisposition(
       browser(),
@@ -1445,369 +788,22 @@
 }
 
 // WebUIBindings should never be enabled on ANY Instant web contents.
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, NoWebUIBindingsOnPreview) {
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-
-  // Typing in the omnibox shows the overlay.
-  ASSERT_TRUE(SetOmniboxTextAndWaitForOverlayToShow("query"));
-  EXPECT_TRUE(instant()->model()->mode().is_search_suggestions());
-  content::WebContents* preview = instant()->GetOverlayContents();
-  ASSERT_NE(static_cast<content::WebContents*>(NULL), preview);
-
-  // Instant preview should not have any bindings enabled.
-  EXPECT_EQ(0, preview->GetRenderViewHost()->GetEnabledBindings());
-}
-
-// WebUIBindings should never be enabled on ANY Instant web contents.
 IN_PROC_BROWSER_TEST_F(InstantExtendedTest, NoWebUIBindingsOnResults) {
   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
+  FocusOmniboxAndWaitForInstantNTPSupport();
 
-  // Typing in the omnibox shows the overlay.
-  ASSERT_TRUE(SetOmniboxTextAndWaitForOverlayToShow("query"));
-  content::WebContents* preview = instant()->GetOverlayContents();
-  EXPECT_TRUE(instant()->model()->mode().is_search_suggestions());
+  // Type a query and press enter to get results.
+  SetOmniboxText("query");
   // Commit the search by pressing Enter.
   browser()->window()->GetLocationBar()->AcceptInput();
   EXPECT_TRUE(instant()->model()->mode().is_default());
   const content::WebContents* tab =
       browser()->tab_strip_model()->GetActiveWebContents();
-  EXPECT_EQ(preview, tab);
 
   // The commited Instant page should not have any bindings enabled.
   EXPECT_EQ(0, tab->GetRenderViewHost()->GetEnabledBindings());
 }
 
-// Only implemented in Views and Mac currently: http://crbug.com/164723
-#if defined(OS_WIN) || defined(OS_CHROMEOS) || defined(OS_MACOSX)
-#define MAYBE_HomeButtonAffectsMargin HomeButtonAffectsMargin
-#else
-#define MAYBE_HomeButtonAffectsMargin DISABLED_HomeButtonAffectsMargin
-#endif
-// Check that toggling the state of the home button changes the start-edge
-// margin and width.
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, MAYBE_HomeButtonAffectsMargin) {
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlaySupport();
-
-  // Get the current value of the start-edge margin and width.
-  int start_margin;
-  int width;
-  content::WebContents* overlay = instant()->GetOverlayContents();
-  EXPECT_TRUE(GetIntFromJS(overlay, "chrome.searchBox.startMargin",
-      &start_margin));
-  EXPECT_TRUE(GetIntFromJS(overlay, "chrome.searchBox.width", &width));
-
-  // Toggle the home button visibility pref.
-  PrefService* profile_prefs = browser()->profile()->GetPrefs();
-  bool show_home = profile_prefs->GetBoolean(prefs::kShowHomeButton);
-  profile_prefs->SetBoolean(prefs::kShowHomeButton, !show_home);
-
-  // Make sure the margin and width changed.
-  int new_start_margin;
-  int new_width;
-  EXPECT_TRUE(GetIntFromJS(overlay, "chrome.searchBox.startMargin",
-      &new_start_margin));
-  EXPECT_TRUE(GetIntFromJS(overlay, "chrome.searchBox.width", &new_width));
-  EXPECT_NE(start_margin, new_start_margin);
-  EXPECT_NE(width, new_width);
-  EXPECT_EQ(new_width - width, start_margin - new_start_margin);
-}
-
-// Commit does not happen on Mac: http://crbug.com/178520
-#if defined(OS_MACOSX)
-#define MAYBE_CommitWhenFocusLostInFullHeight \
-        DISABLED_CommitWhenFocusLostInFullHeight
-#else
-#define MAYBE_CommitWhenFocusLostInFullHeight CommitWhenFocusLostInFullHeight
-#endif
-// Test that the overlay is committed when the omnibox loses focus when it is
-// shown at 100% height.
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest,
-                       MAYBE_CommitWhenFocusLostInFullHeight) {
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-
-  // Focus omnibox and confirm overlay isn't shown.
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-  content::WebContents* overlay = instant()->GetOverlayContents();
-  EXPECT_TRUE(overlay);
-  EXPECT_TRUE(instant()->model()->mode().is_default());
-  EXPECT_FALSE(instant()->IsOverlayingSearchResults());
-
-  // Typing in the omnibox should show the overlay.
-  ASSERT_TRUE(SetOmniboxTextAndWaitForOverlayToShow("query"));
-  EXPECT_TRUE(instant()->IsOverlayingSearchResults());
-  EXPECT_EQ(overlay, instant()->GetOverlayContents());
-
-  // Explicitly unfocus the omnibox without triggering a click. Note that this
-  // doesn't actually change the focus state of the omnibox, only what the
-  // Instant controller sees it as.
-  omnibox()->model()->OnWillKillFocus(NULL);
-  omnibox()->model()->OnKillFocus();
-
-  // Confirm that the overlay has been committed.
-  content::WebContents* active_tab =
-      browser()->tab_strip_model()->GetActiveWebContents();
-  EXPECT_EQ(overlay, active_tab);
-}
-
-#if defined(OS_MACOSX)
-// http://crbug.com/227076
-#define MAYBE_CommitWhenShownInFullHeightWithoutFocus \
-        DISABLED_CommitWhenShownInFullHeightWithoutFocus
-#else
-#define MAYBE_CommitWhenShownInFullHeightWithoutFocus \
-        CommitWhenShownInFullHeightWithoutFocus
-#endif
-
-// Test that the overlay is committed when shown at 100% height without focus
-// in the omnibox.
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest,
-                       MAYBE_CommitWhenShownInFullHeightWithoutFocus) {
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-
-  // Focus omnibox and confirm overlay isn't shown.
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-  content::WebContents* overlay = instant()->GetOverlayContents();
-  EXPECT_TRUE(overlay);
-  EXPECT_TRUE(instant()->model()->mode().is_default());
-  EXPECT_FALSE(instant()->IsOverlayingSearchResults());
-
-  // Create an observer to wait for the commit.
-  content::WindowedNotificationObserver commit_observer(
-      chrome::NOTIFICATION_INSTANT_COMMITTED,
-      content::NotificationService::AllSources());
-
-  // Create an observer to wait for the autocomplete.
-  content::WindowedNotificationObserver autocomplete_observer(
-      chrome::NOTIFICATION_INSTANT_SENT_AUTOCOMPLETE_RESULTS,
-      content::NotificationService::AllSources());
-
-  // Typing in the omnibox should show the overlay. Don't wait for the overlay
-  // to show however.
-  SetOmniboxText("query");
-
-  autocomplete_observer.Wait();
-
-  // Explicitly unfocus the omnibox without triggering a click. Note that this
-  // doesn't actually change the focus state of the omnibox, only what the
-  // Instant controller sees it as.
-  omnibox()->model()->OnWillKillFocus(NULL);
-  omnibox()->model()->OnKillFocus();
-
-  // Wait for the overlay to show.
-  commit_observer.Wait();
-
-  // Confirm that the overlay has been committed.
-  content::WebContents* active_tab =
-      browser()->tab_strip_model()->GetActiveWebContents();
-  EXPECT_EQ(overlay, active_tab);
-}
-
-// Test that a transient entry is set properly when the overlay is committed
-// without a navigation.
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, TransientEntrySet) {
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-
-  // Focus omnibox and confirm overlay isn't shown.
-  FocusOmniboxAndWaitForInstantOverlaySupport();
-  content::WebContents* overlay = instant()->GetOverlayContents();
-  EXPECT_TRUE(overlay);
-  EXPECT_TRUE(instant()->model()->mode().is_default());
-  EXPECT_FALSE(instant()->IsOverlayingSearchResults());
-
-  // Commit the overlay without triggering a navigation.
-  content::WindowedNotificationObserver observer(
-      chrome::NOTIFICATION_INSTANT_COMMITTED,
-      content::NotificationService::AllSources());
-  ASSERT_TRUE(SetOmniboxTextAndWaitForOverlayToShow("query"));
-  browser()->window()->GetLocationBar()->AcceptInput();
-  observer.Wait();
-
-  // Confirm that the overlay has been committed.
-  content::WebContents* active_tab =
-      browser()->tab_strip_model()->GetActiveWebContents();
-  EXPECT_EQ(overlay, active_tab);
-
-  // The page hasn't navigated so there should be a transient entry with the
-  // same URL but different page ID as the last committed entry.
-  const content::NavigationEntry* transient_entry =
-      active_tab->GetController().GetTransientEntry();
-  const content::NavigationEntry* committed_entry =
-      active_tab->GetController().GetLastCommittedEntry();
-  EXPECT_EQ(transient_entry->GetURL(), committed_entry->GetURL());
-  EXPECT_NE(transient_entry->GetPageID(), committed_entry->GetPageID());
-}
-
-// Test that the a transient entry is cleared when the overlay is committed
-// with a navigation.
-// TODO(samarth) : this test fails, http://crbug.com/181070.
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, DISABLED_TransientEntryRemoved) {
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-
-  // Focus omnibox and confirm overlay isn't shown.
-  FocusOmniboxAndWaitForInstantOverlaySupport();
-  content::WebContents* overlay = instant()->GetOverlayContents();
-  EXPECT_TRUE(overlay);
-  EXPECT_TRUE(instant()->model()->mode().is_default());
-  EXPECT_FALSE(instant()->IsOverlayingSearchResults());
-
-  // Create an observer to wait for the commit.
-  content::WindowedNotificationObserver observer(
-      chrome::NOTIFICATION_INSTANT_COMMITTED,
-      content::NotificationService::AllSources());
-
-  // Trigger a navigation on commit.
-  EXPECT_TRUE(ExecuteScript(
-      "getApiHandle().oncancel = function() {"
-      "  location.replace(location.href + '#q=query');"
-      "};"
-      ));
-
-  // Commit the overlay.
-  ASSERT_TRUE(SetOmniboxTextAndWaitForOverlayToShow("query"));
-  browser()->window()->GetLocationBar()->AcceptInput();
-  observer.Wait();
-
-  // Confirm that the overlay has been committed.
-  content::WebContents* active_tab =
-      browser()->tab_strip_model()->GetActiveWebContents();
-  EXPECT_EQ(overlay, active_tab);
-
-  // The page has navigated so there should be no transient entry.
-  const content::NavigationEntry* transient_entry =
-      active_tab->GetController().GetTransientEntry();
-  EXPECT_EQ(NULL, transient_entry);
-
-  // The last committed entry should be the URL the page navigated to.
-  const content::NavigationEntry* committed_entry =
-      active_tab->GetController().GetLastCommittedEntry();
-  EXPECT_TRUE(EndsWith(committed_entry->GetURL().spec(), "#q=query", true));
-}
-
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, RestrictedURLReading) {
-  std::string search_query;
-  bool is_undefined;
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlaySupport();
-
-  // Verify we can read out something ok.
-  const char kOKQuery[] = "santa";
-  SetOmniboxText(kOKQuery);
-  EXPECT_EQ(ASCIIToUTF16(kOKQuery), omnibox()->GetText());
-  // Must always assert the value is defined before trying to read it, as trying
-  // to read undefined values causes the test to hang.
-  EXPECT_TRUE(GetBoolFromJS(instant()->GetOverlayContents(),
-                            "apiHandle.value === undefined",
-                            &is_undefined));
-  ASSERT_FALSE(is_undefined);
-  EXPECT_TRUE(GetStringFromJS(instant()->GetOverlayContents(),
-                              "apiHandle.value",
-                              &search_query));
-  EXPECT_EQ(kOKQuery, search_query);
-
-  // Verify we can't read out something that should be restricted, like a https
-  // url with a path.
-  const char kHTTPSUrlWithPath[] = "https://www.example.com/foobar";
-  SetOmniboxText(kHTTPSUrlWithPath);
-  EXPECT_EQ(ASCIIToUTF16(kHTTPSUrlWithPath), omnibox()->GetText());
-  EXPECT_TRUE(GetBoolFromJS(instant()->GetOverlayContents(),
-                            "apiHandle.value === undefined",
-                            &is_undefined));
-  EXPECT_TRUE(is_undefined);
-}
-
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, RestrictedItemReadback) {
-  // Initialize Instant.
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlaySupport();
-
-  // Get a handle to the NTP and the current state of the JS.
-  ASSERT_NE(static_cast<InstantNTP*>(NULL), instant()->ntp());
-  content::WebContents* preview_tab = instant()->ntp()->contents();
-  EXPECT_TRUE(preview_tab);
-
-  // Manufacture a few autocomplete results and get them down to the page.
-  std::vector<InstantAutocompleteResult> autocomplete_results;
-  for (int i = 0; i < 3; ++i) {
-    std::string description(base::StringPrintf("Test Description %d", i));
-    std::string url(base::StringPrintf("http://www.testurl%d.com", i));
-
-    InstantAutocompleteResult res;
-    res.provider = ASCIIToUTF16(AutocompleteProvider::TypeToString(
-        AutocompleteProvider::TYPE_BUILTIN));
-    res.type = AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,
-    res.description = ASCIIToUTF16(description);
-    res.destination_url = ASCIIToUTF16(url);
-    res.transition = content::PAGE_TRANSITION_TYPED;
-    res.relevance = 42 + i;
-
-    autocomplete_results.push_back(res);
-  }
-  instant()->overlay()->SendAutocompleteResults(autocomplete_results);
-
-  // Apparently, one needs to access nativeSuggestions before
-  // apiHandle.setRestrictedValue can work.
-  EXPECT_TRUE(ExecuteScript("var foo = apiHandle.nativeSuggestions;"));
-
-  const char kQueryString[] = "Hippos go berzerk!";
-
-  // First set the query text to a non restricted value and ensure it can be
-  // read back.
-  std::ostringstream stream;
-  stream << "apiHandle.setValue('" << kQueryString << "');";
-  EXPECT_TRUE(ExecuteScript(stream.str()));
-
-  std::string query_string;
-  bool is_undefined;
-  EXPECT_TRUE(GetStringFromJS(instant()->GetOverlayContents(),
-                              "apiHandle.value",
-                              &query_string));
-  EXPECT_EQ(kQueryString, query_string);
-
-  // Set the query text to the first restricted autocomplete item.
-  int rid = 1;
-  stream.str(std::string());
-  stream << "apiHandle.setRestrictedValue(" << rid << ");";
-  EXPECT_TRUE(ExecuteScript(stream.str()));
-
-  // Expect that we now receive undefined when reading the value back.
-  EXPECT_TRUE(GetBoolFromJS(
-      instant()->GetOverlayContents(),
-      "apiHandle.value === undefined",
-      &is_undefined));
-  EXPECT_TRUE(is_undefined);
-
-  // Now set the query text to a non restricted value and ensure that the
-  // visibility has been reset and the string can again be read back.
-  stream.str(std::string());
-  stream << "apiHandle.setValue('" << kQueryString << "');";
-  EXPECT_TRUE(ExecuteScript(stream.str()));
-
-  EXPECT_TRUE(GetStringFromJS(instant()->GetOverlayContents(),
-                              "apiHandle.value",
-                              &query_string));
-  EXPECT_EQ(kQueryString, query_string);
-}
-
-// Test that autocomplete results are sent to the page only when all the
-// providers are done.
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, AutocompleteProvidersDone) {
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-
-  content::WebContents* overlay = instant()->GetOverlayContents();
-  EXPECT_TRUE(UpdateSearchState(overlay));
-  EXPECT_EQ(0, on_native_suggestions_calls_);
-
-  ASSERT_TRUE(SetOmniboxTextAndWaitForOverlayToShow("railroad"));
-
-  EXPECT_EQ(overlay, instant()->GetOverlayContents());
-  EXPECT_TRUE(UpdateSearchState(overlay));
-  EXPECT_EQ(1, on_native_suggestions_calls_);
-}
-
 // Test that the Bookmark provider is enabled, and returns results.
 // TODO(sreeram): Convert this to a unit test.
 IN_PROC_BROWSER_TEST_F(InstantExtendedTest, DISABLED_HasBookmarkProvider) {
@@ -1834,119 +830,10 @@
   EXPECT_TRUE(found_bookmark_match);
 }
 
-// Test that the omnibox's temporary text is reset when the popup is closed.
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, TemporaryTextResetWhenPopupClosed) {
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-  EXPECT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-
-  // Show the overlay and arrow-down to a suggestion (this sets temporary text).
-  ASSERT_TRUE(SetOmniboxTextAndWaitForOverlayToShow("juju"));
-  SendDownArrow();
-
-  EXPECT_TRUE(HasTemporaryText());
-  EXPECT_EQ("result 1", GetOmniboxText());
-
-  // Click outside the omnibox (but not on the overlay), to make the omnibox
-  // lose focus. Close the popup explicitly, to workaround test/toolkit issues.
-  ui_test_utils::ClickOnView(browser(), VIEW_ID_TOOLBAR);
-  omnibox()->CloseOmniboxPopup();
-
-  // The temporary text should've been accepted as the user text.
-  EXPECT_FALSE(HasTemporaryText());
-  EXPECT_EQ("result 1", GetOmniboxText());
-
-  // Now refocus the omnibox and hit Escape. This shouldn't crash.
-  FocusOmnibox();
-  SendEscape();
-
-  // The omnibox should've reverted to the underlying permanent URL.
-  EXPECT_FALSE(HasTemporaryText());
-  EXPECT_EQ(std::string(content::kAboutBlankURL), GetOmniboxText());
-}
-
-// Test that autocomplete results aren't sent when the popup is closed.
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest,
-                       NoAutocompleteResultsWhenPopupClosed) {
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-  EXPECT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-
-  // Show the overlay and arrow-down to a suggestion (this sets temporary text).
-  ASSERT_TRUE(SetOmniboxTextAndWaitForOverlayToShow("thangam"));
-  SendDownArrow();
-  EXPECT_TRUE(HasTemporaryText());
-
-  EXPECT_TRUE(ExecuteScript("onChangeCalls = onNativeSuggestionsCalls = 0;"));
-
-  content::WebContents* overlay = instant()->GetOverlayContents();
-  EXPECT_TRUE(UpdateSearchState(overlay));
-  EXPECT_EQ(0, on_change_calls_);
-  EXPECT_EQ(0, on_native_suggestions_calls_);
-
-  // Click outside the omnibox (but not on the overlay), to make the omnibox
-  // lose focus. Close the popup explicitly, to workaround test/toolkit issues.
-  ui_test_utils::ClickOnView(browser(), VIEW_ID_TOOLBAR);
-  omnibox()->CloseOmniboxPopup();
-  EXPECT_FALSE(HasTemporaryText());
-
-  EXPECT_EQ(overlay, instant()->GetOverlayContents());
-  EXPECT_TRUE(UpdateSearchState(overlay));
-  EXPECT_EQ(0, on_change_calls_);
-  EXPECT_EQ(0, on_native_suggestions_calls_);
-}
-
-// Test that suggestions are not accepted when unexpected.
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, DeniesUnexpectedSuggestions) {
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-  ASSERT_TRUE(SetOmniboxTextAndWaitForOverlayToShow("chip"));
-  SendDownArrow();
-
-  EXPECT_EQ("result 1", GetOmniboxText());
-  EXPECT_EQ(ASCIIToUTF16(""), GetGrayText());
-
-  // Make the page send an unexpected suggestion.
-  EXPECT_TRUE(ExecuteScript("suggestion = 'chippies';"
-                            "handleOnChange();"));
-
-  // Verify that the suggestion is ignored.
-  EXPECT_EQ("result 1", GetOmniboxText());
-  EXPECT_EQ(ASCIIToUTF16(""), GetGrayText());
-}
-
-// Test that autocomplete results are cleared when the query is cleared.
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, EmptyAutocompleteResults) {
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-
-  // Type a URL, so that there's at least one autocomplete result (a "URL what
-  // you typed" match).
-  ASSERT_TRUE(SetOmniboxTextAndWaitForOverlayToShow("http://upsamina/"));
-
-  content::WebContents* overlay = instant()->GetOverlayContents();
-
-  int num_autocomplete_results = 0;
-  EXPECT_TRUE(GetIntFromJS(
-      overlay,
-      "chrome.embeddedSearch.searchBox.nativeSuggestions.length",
-      &num_autocomplete_results));
-  EXPECT_LT(0, num_autocomplete_results);
-
-  // Erase the query in the omnibox.
-  SetOmniboxText("");
-
-  EXPECT_TRUE(GetIntFromJS(
-      overlay,
-      "chrome.embeddedSearch.searchBox.nativeSuggestions.length",
-      &num_autocomplete_results));
-  EXPECT_EQ(0, num_autocomplete_results);
-}
-
 // Test that hitting Esc to clear the omnibox works. http://crbug.com/231744.
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, EscapeClearsOmnibox) {
+IN_PROC_BROWSER_TEST_F(InstantExtendedTest, DISABLED_EscapeClearsOmnibox) {
   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
+  FocusOmniboxAndWaitForInstantNTPSupport();
 
   // Navigate to the Instant NTP, and wait for it to be recognized.
   content::WindowedNotificationObserver instant_tab_observer(
@@ -1985,63 +872,6 @@
   EXPECT_LT(0, on_esc_key_press_event_calls_);
 }
 
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, FocusApiRespondsToFocusChange) {
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-  EXPECT_FALSE(is_focused_);
-  EXPECT_EQ(0, on_focus_changed_calls_);
-
-  // Focus the omnibox.
-  FocusOmniboxAndWaitForInstantOverlaySupport();
-  ASSERT_TRUE(UpdateSearchState(instant()->GetOverlayContents()));
-  EXPECT_TRUE(is_focused_);
-  EXPECT_EQ(1, on_focus_changed_calls_);
-
-  // Now unfocus the omnibox.
-  ui_test_utils::ClickOnView(browser(), VIEW_ID_TAB_CONTAINER);
-  ASSERT_TRUE(UpdateSearchState(instant()->GetOverlayContents()));
-  EXPECT_FALSE(is_focused_);
-  EXPECT_EQ(2, on_focus_changed_calls_);
-
-  // Focus the omnibox again.
-  // The first focus may have worked only due to initial-state anomalies.
-  FocusOmnibox();
-  ASSERT_TRUE(UpdateSearchState(instant()->GetOverlayContents()));
-  EXPECT_TRUE(is_focused_);
-  EXPECT_EQ(3, on_focus_changed_calls_);
-}
-
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, FocusApiIgnoresRedundantFocus) {
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-  EXPECT_FALSE(is_focused_);
-  EXPECT_EQ(0, on_focus_changed_calls_);
-
-  // Focus the Omnibox.
-  FocusOmniboxAndWaitForInstantOverlaySupport();
-  ASSERT_TRUE(UpdateSearchState(instant()->GetOverlayContents()));
-  EXPECT_TRUE(is_focused_);
-  EXPECT_EQ(1, on_focus_changed_calls_);
-
-  // When we focus the omnibox again, nothing should change.
-  FocusOmnibox();
-  ASSERT_TRUE(UpdateSearchState(instant()->GetOverlayContents()));
-  EXPECT_TRUE(is_focused_);
-  EXPECT_EQ(1, on_focus_changed_calls_);
-
-  // Now unfocus the omnibox.
-  ui_test_utils::ClickOnView(browser(), VIEW_ID_TAB_CONTAINER);
-  ASSERT_TRUE(UpdateSearchState(instant()->GetOverlayContents()));
-  EXPECT_FALSE(is_focused_);
-  EXPECT_EQ(2, on_focus_changed_calls_);
-
-  // When we unfocus again, nothing should change.
-  ui_test_utils::ClickOnView(browser(), VIEW_ID_TAB_CONTAINER);
-  ASSERT_TRUE(UpdateSearchState(instant()->GetOverlayContents()));
-  EXPECT_FALSE(is_focused_);
-  EXPECT_EQ(2, on_focus_changed_calls_);
-}
-
 IN_PROC_BROWSER_TEST_F(InstantExtendedTest, OnDefaultSearchProviderChanged) {
   InstantService* instant_service =
       InstantServiceFactory::GetForProfile(browser()->profile());
@@ -2049,7 +879,7 @@
 
   // Setup Instant.
   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
+  FocusOmniboxAndWaitForInstantNTPSupport();
   EXPECT_EQ(1, instant_service->GetInstantProcessCount());
 
   // Navigating to the NTP should use the Instant render process.
@@ -2102,109 +932,19 @@
   EXPECT_EQ(ntp_url, ntp_contents->GetURL());
 }
 
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, OverlayRenderViewGone) {
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-  EXPECT_NE(static_cast<content::WebContents*>(NULL),
-            instant()->GetOverlayContents());
-
-  // Overlay is not reloaded after being killed.
-  EXPECT_FALSE(instant()->overlay()->IsLocal());
-  instant()->InstantPageRenderViewGone(instant()->GetOverlayContents());
-  EXPECT_EQ(NULL, instant()->GetOverlayContents());
-
-  // The local overlay is used on the next Update().
-  SetOmniboxText("query");
-  EXPECT_TRUE(instant()->overlay()->IsLocal());
-
-  // Switched back to the remote overlay when omnibox loses and regains focus.
-  instant()->HideOverlay();
-  browser()->tab_strip_model()->GetActiveWebContents()->GetView()->Focus();
-  FocusOmnibox();
-  EXPECT_FALSE(instant()->overlay()->IsLocal());
-}
-
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, OverlayDoesntSupportInstant) {
-  GURL instant_url = test_server()->GetURL("files/empty.html?strk=1");
-  InstantTestBase::Init(instant_url);
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-
-  // Focus the omnibox. When the support determination response comes back,
-  // Instant will destroy the non-Instant page and fall back to the local page.
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-  ASSERT_NE(static_cast<InstantOverlay*>(NULL), instant()->overlay());
-  EXPECT_TRUE(instant()->overlay()->IsLocal());
-
-  // The local overlay is used on the next Update().
-  SetOmniboxText("query");
-  EXPECT_TRUE(instant()->overlay()->IsLocal());
-
-  // Switched back to the remote overlay when omnibox loses and regains focus.
-  instant()->HideOverlay();
-  browser()->tab_strip_model()->GetActiveWebContents()->GetView()->Focus();
-  FocusOmnibox();
-  EXPECT_FALSE(instant()->overlay()->IsLocal());
-
-  // Overlay falls back to local again after determining support.
-  FocusOmniboxAndWaitForInstantOverlaySupport();
-  ASSERT_NE(static_cast<InstantOverlay*>(NULL), instant()->overlay());
-  EXPECT_TRUE(instant()->overlay()->IsLocal());
-}
-
-// Test that if Instant alters the input from URL to search, it's respected.
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, InputChangedFromURLToSearch) {
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-
-  content::WebContents* overlay = instant()->GetOverlayContents();
-  EXPECT_TRUE(ExecuteScript("suggestions = ['mcqueen.com'];"));
-
-  SetOmniboxTextAndWaitForOverlayToShow("lightning");
-  EXPECT_EQ("lightning", GetOmniboxText());
-
-  SendDownArrow();
-  EXPECT_EQ("mcqueen.com", GetOmniboxText());
-
-  // Press Enter.
-  browser()->window()->GetLocationBar()->AcceptInput();
-
-  // Confirm that the Instant overlay was committed.
-  EXPECT_EQ(overlay, browser()->tab_strip_model()->GetActiveWebContents());
-}
-
-// Test that if Instant alters the input from search to URL, it's respected.
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, InputChangedFromSearchToURL) {
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-
-  content::WebContents* overlay = instant()->GetOverlayContents();
-  EXPECT_TRUE(ExecuteScript("suggestionType = 1;"));  // INSTANT_SUGGESTION_URL
-
-  SetOmniboxTextAndWaitForOverlayToShow("mack.com");
-  EXPECT_EQ("mack.com", GetOmniboxText());
-
-  SendDownArrow();
-  EXPECT_EQ("result 1", GetOmniboxText());
-
-  // Press Enter.
-  browser()->window()->GetLocationBar()->AcceptInput();
-
-  // Confirm that the Instant overlay was NOT committed.
-  EXPECT_NE(overlay, browser()->tab_strip_model()->GetActiveWebContents());
-}
-
 // Test that renderer initiated navigations to an instant URL from a non
 // Instant page do not end up in an Instant process if they are bounced to the
 // browser.
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest,
-                       RendererInitiatedNavigationNotInInstantProcess) {
+IN_PROC_BROWSER_TEST_F(
+    InstantExtendedTest,
+    DISABLED_RendererInitiatedNavigationNotInInstantProcess) {
   InstantService* instant_service =
       InstantServiceFactory::GetForProfile(browser()->profile());
   ASSERT_NE(static_cast<InstantService*>(NULL), instant_service);
 
   // Setup Instant.
   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
+  FocusOmniboxAndWaitForInstantNTPSupport();
 
   EXPECT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
   EXPECT_EQ(1, browser()->tab_strip_model()->count());
@@ -2269,7 +1009,7 @@
 
   // Setup Instant.
   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
+  FocusOmniboxAndWaitForInstantNTPSupport();
 
   EXPECT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
   EXPECT_EQ(1, browser()->tab_strip_model()->count());
@@ -2307,159 +1047,11 @@
   EXPECT_EQ(GURL(instant_url_with_query), contents->GetURL());
 }
 
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, SearchProviderDoesntRun) {
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlaySupport();
-
-  // Add "query" to history.
-  ASSERT_TRUE(AddSearchToHistory(ASCIIToUTF16("query"), 10000));
-  BlockUntilHistoryProcessesPendingRequests();
-
-  SetOmniboxText("quer");
-
-  // Should get only SWYT from SearchProvider.
-  EXPECT_EQ(1, CountSearchProviderSuggestions());
-}
-
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, SearchProviderRunsForLocalOnly) {
-  // Force local-only Instant.
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  instant()->SetInstantEnabled(true, true);
-  FocusOmniboxAndWaitForInstantOverlaySupport();
-
-  // Add "query" to history.
-  ASSERT_TRUE(AddSearchToHistory(ASCIIToUTF16("query"), 10000));
-  BlockUntilHistoryProcessesPendingRequests();
-
-  SetOmniboxText("quer");
-
-  // Should get 2 suggestions from SearchProvider:
-  //   - SWYT for "quer"
-  //   - Search history suggestion for "query"
-  EXPECT_EQ(2, CountSearchProviderSuggestions());
-}
-
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, SearchProviderRunsForFallback) {
-  // Use an Instant URL that won't support Instant.
-  GURL instant_url = test_server()->GetURL("files/empty.html?strk=1");
-  InstantTestBase::Init(instant_url);
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlaySupport();
-  // Should fallback to the local overlay.
-  ASSERT_NE(static_cast<InstantOverlay*>(NULL), instant()->overlay());
-  EXPECT_TRUE(instant()->overlay()->IsLocal());
-
-  // Add "query" to history and wait for Instant support.
-  ASSERT_TRUE(AddSearchToHistory(ASCIIToUTF16("query"), 10000));
-  BlockUntilHistoryProcessesPendingRequests();
-
-  SetOmniboxText("quer");
-
-  // Should get 2 suggestions from SearchProvider:
-  //   - SWYT for "quer"
-  //   - Search history suggestion for "query"
-  EXPECT_EQ(2, CountSearchProviderSuggestions());
-}
-
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, SearchProviderForLocalNTP) {
-  // Force local-only Instant.
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-  instant()->SetInstantEnabled(true, true);
-
-  // Add "google" to history.
-  ASSERT_TRUE(AddSearchToHistory(ASCIIToUTF16("google"), 10000));
-  BlockUntilHistoryProcessesPendingRequests();
-
-  // Create an observer to wait for the autocomplete.
-  content::WindowedNotificationObserver autocomplete_observer(
-      chrome::NOTIFICATION_INSTANT_SENT_AUTOCOMPLETE_RESULTS,
-      content::NotificationService::AllSources());
-
-  SetOmniboxText("http://www.example.com");
-
-  autocomplete_observer.Wait();
-  ASSERT_TRUE(omnibox()->model()->autocomplete_controller()->
-              search_provider()->IsNonInstantSearchDone());
-}
-
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, OverlaySendsSearchWhatYouTyped) {
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-
-  // This input could be interpreted either as an URL or a query based on the
-  // relative ranking of search-what-you-typed or url-what-you-typed.
-  content::WindowedNotificationObserver autocomplete_observer(
-      chrome::NOTIFICATION_INSTANT_SENT_AUTOCOMPLETE_RESULTS,
-      content::NotificationService::AllSources());
-  SetOmniboxText("define:foo");
-  autocomplete_observer.Wait();
-
-  // In this case, we should treat [define:foo] as a query, so
-  // search-what-you-typed should be the top suggestion.
-  EXPECT_TRUE(ExecuteScript(
-      "var sorted = chrome.embeddedSearch.searchBox.nativeSuggestions.sort("
-          "function (a,b) {"
-            "return b.rankingData.relevance - a.rankingData.relevance;"
-          "});"));
-  std::string type;
-  EXPECT_TRUE(GetStringFromJS(instant()->GetOverlayContents(),
-                              "sorted[0].type", &type));
-  ASSERT_EQ("search-what-you-typed", type);
-}
-
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest,
-                       OverlayDoesNotEchoSearchProviderNavsuggest) {
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-
-  // Show the overlay so suggestions are allowed.
-  SetOmniboxTextAndWaitForOverlayToShow("www.");
-  content::WebContents* overlay = instant()->GetOverlayContents();
-
-  // Set a URL suggestion and wait for SearchProvider to echo it.
-  content::WindowedNotificationObserver autocomplete_observer(
-      chrome::NOTIFICATION_INSTANT_SENT_AUTOCOMPLETE_RESULTS,
-      content::NotificationService::AllSources());
-  instant()->SetSuggestions(
-      overlay,
-      std::vector<InstantSuggestion>(
-          1,
-          InstantSuggestion(ASCIIToUTF16("http://www.example.com/"),
-                            INSTANT_COMPLETE_NOW,
-                            INSTANT_SUGGESTION_URL,
-                            ASCIIToUTF16("www."),
-                            kNoMatchIndex)));
-  autocomplete_observer.Wait();
-
-  // Check that SearchProvider set a NAVSUGGEST match.
-  bool have_navsuggest_match = false;
-  SearchProvider* search_provider =
-      omnibox()->model()->autocomplete_controller()->search_provider();
-  for (ACMatches::const_iterator match = search_provider->matches().begin();
-       match != search_provider->matches().end(); ++match) {
-    if (match->type == AutocompleteMatchType::NAVSUGGEST) {
-      have_navsuggest_match = true;
-      break;
-    }
-  }
-  ASSERT_TRUE(have_navsuggest_match);
-
-  // Check that InstantController did not send the NAVSUGGEST match.
-  bool sent_navsuggest_match = true;
-  EXPECT_TRUE(GetBoolFromJS(overlay,
-      "chrome.embeddedSearch.searchBox.nativeSuggestions.some("
-          "function (s) {"
-            "return s.type == 'navsuggest';"
-          "})", &sent_navsuggest_match));
-  EXPECT_FALSE(sent_navsuggest_match);
-}
-
 IN_PROC_BROWSER_TEST_F(InstantExtendedTest, AcceptingURLSearchDoesNotNavigate) {
   // Get a committed Instant tab, which will be in the Instant process and thus
   // support chrome::GetSearchTerms().
   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlaySupport();
+  FocusOmnibox();
 
   // Create an observer to wait for the instant tab to support Instant.
   content::WindowedNotificationObserver observer(
@@ -2467,7 +1059,7 @@
       content::NotificationService::AllSources());
 
   // Do a search and commit it.
-  ASSERT_TRUE(SetOmniboxTextAndWaitForOverlayToShow("foo"));
+  SetOmniboxText("foo");
   EXPECT_EQ(ASCIIToUTF16("foo"), omnibox()->GetText());
   browser()->window()->GetLocationBar()->AcceptInput();
   observer.Wait();
@@ -2491,11 +1083,13 @@
   EXPECT_EQ(instant_tab_url, instant_tab->GetURL());
 }
 
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, AcceptingJSSearchDoesNotRunJS) {
+// TODO(jered): Figure out why this test flakes and fix it.
+IN_PROC_BROWSER_TEST_F(InstantExtendedTest,
+                       DISABLED_AcceptingJSSearchDoesNotRunJS) {
   // Get a committed Instant tab, which will be in the Instant process and thus
   // support chrome::GetSearchTerms().
   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlaySupport();
+  FocusOmnibox();
 
   // Create an observer to wait for the instant tab to support Instant.
   content::WindowedNotificationObserver observer(
@@ -2503,7 +1097,7 @@
       content::NotificationService::AllSources());
 
   // Do a search and commit it.
-  ASSERT_TRUE(SetOmniboxTextAndWaitForOverlayToShow("foo"));
+  SetOmniboxText("foo");
   EXPECT_EQ(ASCIIToUTF16("foo"), omnibox()->GetText());
   browser()->window()->GetLocationBar()->AcceptInput();
   observer.Wait();
@@ -2529,17 +1123,11 @@
   EXPECT_NE(ASCIIToUTF16("evil"), instant_tab->GetTitle());
 }
 
-// Flaky on mac: http://crbug.com/242164
-#if defined(OS_MACOSX)
-#define MAYBE_ReloadSearchAfterBackReloadsCorrectQuery DISABLED_ReloadSearchAfterBackReloadsCorrectQuery
-#else
-#define MAYBE_ReloadSearchAfterBackReloadsCorrectQuery ReloadSearchAfterBackReloadsCorrectQuery
-#endif
-
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest,
-                       MAYBE_ReloadSearchAfterBackReloadsCorrectQuery) {
+IN_PROC_BROWSER_TEST_F(
+    InstantExtendedTest,
+    DISABLED_ReloadSearchAfterBackReloadsCorrectQuery) {
   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlaySupport();
+  FocusOmnibox();
 
   // Create an observer to wait for the instant tab to support Instant.
   content::WindowedNotificationObserver observer(
@@ -2547,7 +1135,7 @@
       content::NotificationService::AllSources());
 
   // Search for [foo].
-  ASSERT_TRUE(SetOmniboxTextAndWaitForOverlayToShow("foo"));
+  SetOmniboxText("foo");
   EXPECT_EQ(ASCIIToUTF16("foo"), omnibox()->GetText());
   browser()->window()->GetLocationBar()->AcceptInput();
   observer.Wait();
@@ -2557,7 +1145,6 @@
   EXPECT_TRUE(content::ExecuteScript(instant_tab,
                                      "suggestion = 'bart';"));
   SetOmniboxTextAndWaitForSuggestion("bar");
-  EXPECT_EQ(ASCIIToUTF16("t"), GetGrayText());
 
   // Accept the new query and wait for the page to navigate.
   content::WindowedNotificationObserver nav_observer(
@@ -2604,12 +1191,12 @@
       NEW_WINDOW,
       ui_test_utils::BROWSER_TEST_WAIT_FOR_BROWSER);
 
-  const BrowserList* native_browser_list = BrowserList::GetInstance(
-      chrome::HOST_DESKTOP_TYPE_NATIVE);
-  ASSERT_EQ(2u, native_browser_list->size());
-  set_browser(native_browser_list->get(1));
+  const BrowserList* browser_list = BrowserList::GetInstance(
+      chrome::GetActiveDesktop());
+  ASSERT_EQ(2u, browser_list->size());
+  set_browser(browser_list->get(1));
 
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
+  FocusOmniboxAndWaitForInstantNTPSupport();
 
   // Also make sure our instant_tab_ is loaded.
   if (!instant()->instant_tab_) {
@@ -2623,69 +1210,11 @@
   ASSERT_NE(static_cast<InstantNTP*>(NULL), instant()->ntp());
   EXPECT_TRUE(instant()->ntp()->IsLocal());
 
-  // Overlay contents should be preloaded.
-  ASSERT_NE(static_cast<InstantOverlay*>(NULL), instant()->overlay());
-  EXPECT_TRUE(instant()->overlay()->IsLocal());
-
   // Instant tab contents should be preloaded.
   ASSERT_NE(static_cast<InstantTab*>(NULL), instant()->instant_tab());
   EXPECT_TRUE(instant()->instant_tab()->IsLocal());
 }
 
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest,
-                       PageVisibilityEventOnCommit) {
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-
-  // Set the text, and wait for suggestions to show up.
-  ASSERT_TRUE(SetOmniboxTextAndWaitForOverlayToShow("search"));
-
-  content::WebContents* overlay = instant()->GetOverlayContents();
-
-  // Before commiting, verify visibility calls.
-  int on_visibility_calls = -1;
-  EXPECT_TRUE(GetIntFromJS(overlay, "onvisibilitycalls", &on_visibility_calls));
-  EXPECT_EQ(1, on_visibility_calls);
-
-  // Commit the search by pressing Enter.
-  browser()->window()->GetLocationBar()->AcceptInput();
-
-  // After commiting, verify visibility calls.
-  on_visibility_calls = -1;
-  EXPECT_TRUE(GetIntFromJS(overlay, "onvisibilitycalls", &on_visibility_calls));
-  EXPECT_EQ(1, on_visibility_calls);
-}
-
-// Test that if the LogDropdownShown() call records a histogram value.
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, LogDropdownShown) {
-  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-  int64 histogramValue = GetHistogramCount("Instant.TimeToFirstShowFromWeb");
-  ASSERT_TRUE(SetOmniboxTextAndWaitForOverlayToShow("a"));
-  EXPECT_EQ(histogramValue + 1,
-            GetHistogramCount("Instant.TimeToFirstShowFromWeb"));
-}
-
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, TaskManagerPrefix) {
-  TaskManagerModel* task_manager = TaskManager::GetInstance()->model();
-  task_manager->StartUpdating();
-
-  // There should be three renderers, the second being the Instant overlay,
-  // and the third being the preloaded NTP.
-  TaskManagerBrowserTestUtil::WaitForWebResourceChange(3);
-
-  string16 prefix = l10n_util::GetStringFUTF16(
-      IDS_TASK_MANAGER_INSTANT_OVERLAY_PREFIX, string16());
-
-  int instant_overlays = 0;
-  for (int i = 0; i < task_manager->ResourceCount(); ++i) {
-    string16 title = task_manager->GetResourceTitle(i);
-    if (StartsWith(title, prefix, true))
-      ++instant_overlays;
-  }
-  EXPECT_EQ(2, instant_overlays);
-}
-
 // Broken on mac: http://crbug.com/247448
 #if defined(OS_MACOSX)
 #define MAYBE_KeyboardTogglesVoiceSearch DISABLED_KeyboardTogglesVoiceSearch
@@ -2694,23 +1223,19 @@
 #endif
 IN_PROC_BROWSER_TEST_F(InstantExtendedTest, MAYBE_KeyboardTogglesVoiceSearch) {
   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-
-  // Test that toggle is not fired when no tab is open.
-  ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), ui::VKEY_OEM_PERIOD,
-                                              true, true, false, false));
-  EXPECT_TRUE(UpdateSearchState(instant()->GetOverlayContents()));
-  EXPECT_EQ(0, on_toggle_voice_search_calls_);
+  FocusOmniboxAndWaitForInstantNTPSupport();
 
   // Open new tab and test that toggle is fired.
   ui_test_utils::NavigateToURLWithDisposition(
       browser(),
       GURL(chrome::kChromeUINewTabURL),
-      NEW_FOREGROUND_TAB,
-      ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
+      CURRENT_TAB,
+      ui_test_utils::BROWSER_TEST_NONE);
+  content::WebContents* active_tab =
+      browser()->tab_strip_model()->GetActiveWebContents();
   ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), ui::VKEY_OEM_PERIOD,
                                               true, true, false, false));
-  EXPECT_TRUE(UpdateSearchState(instant()->instant_tab()->contents()));
+  EXPECT_TRUE(UpdateSearchState(active_tab));
   EXPECT_EQ(1, on_toggle_voice_search_calls_);
 }
 
@@ -2719,17 +1244,9 @@
 IN_PROC_BROWSER_TEST_F(InstantExtendedTest, UpdateSearchQueryOnNavigation) {
   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
 
-  // Focus omnibox and confirm overlay isn't shown.
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-  content::WebContents* overlay = instant()->GetOverlayContents();
-  EXPECT_TRUE(overlay);
-  EXPECT_TRUE(instant()->model()->mode().is_default());
-  EXPECT_FALSE(instant()->IsOverlayingSearchResults());
-
-  // Typing in the omnibox should show the overlay.
-  SetOmniboxTextAndWaitForOverlayToShow("flowers");
-  EXPECT_TRUE(instant()->IsOverlayingSearchResults());
-  EXPECT_EQ(overlay, instant()->GetOverlayContents());
+  // Focus omnibox.
+  FocusOmniboxAndWaitForInstantNTPSupport();
+  SetOmniboxText("flowers");
 
   // Commit the search by pressing 'Enter'.
   PressEnterAndWaitForNavigation();
@@ -2765,39 +1282,43 @@
 #if !defined(HTML_INSTANT_EXTENDED_POPUP)
 IN_PROC_BROWSER_TEST_F(InstantExtendedTest, SearchReusesInstantTab) {
   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
+  FocusOmniboxAndWaitForInstantNTPSupport();
 
-  // Create an observer to wait for the instant tab to support Instant.
+  // Open new tab. Preloaded NTP contents should have been used.
+  ui_test_utils::NavigateToURLWithDisposition(
+      browser(),
+      GURL(chrome::kChromeUINewTabURL),
+      NEW_FOREGROUND_TAB,
+      ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
+
   content::WindowedNotificationObserver observer(
       chrome::NOTIFICATION_INSTANT_TAB_SUPPORT_DETERMINED,
       content::NotificationService::AllSources());
-
   SetOmniboxText("flowers");
-  browser()->window()->GetLocationBar()->AcceptInput();
+  PressEnterAndWaitForNavigation();
   observer.Wait();
 
   // Just did a regular search.
-  ASSERT_THAT(
-      browser()->tab_strip_model()->GetActiveWebContents()->GetURL().spec(),
-      HasSubstr("q=flowers"));
-  ASSERT_TRUE(UpdateSearchState(instant()->instant_tab()->contents()));
+  content::WebContents* active_tab =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  ASSERT_THAT(active_tab->GetURL().spec(), HasSubstr("q=flowers"));
+  ASSERT_TRUE(UpdateSearchState(active_tab));
   ASSERT_EQ(0, submit_count_);
 
   SetOmniboxText("puppies");
-  browser()->window()->GetLocationBar()->AcceptInput();
+  PressEnterAndWaitForNavigation();
 
   // Should have reused the tab and sent an onsubmit message.
-  ASSERT_THAT(
-      browser()->tab_strip_model()->GetActiveWebContents()->GetURL().spec(),
-      HasSubstr("q=flowers"));
-  ASSERT_TRUE(UpdateSearchState(instant()->instant_tab()->contents()));
+  active_tab = browser()->tab_strip_model()->GetActiveWebContents();
+  ASSERT_THAT(active_tab->GetURL().spec(), HasSubstr("q=puppies"));
+  ASSERT_TRUE(UpdateSearchState(active_tab));
   EXPECT_EQ(1, submit_count_);
 }
 
 IN_PROC_BROWSER_TEST_F(InstantExtendedTest,
                        SearchDoesntReuseInstantTabWithoutSupport) {
   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
+  FocusOmniboxAndWaitForInstantNTPSupport();
 
   // Don't wait for the navigation to complete.
   SetOmniboxText("flowers");
@@ -2815,37 +1336,53 @@
 IN_PROC_BROWSER_TEST_F(InstantExtendedTest,
                        TypedSearchURLDoesntReuseInstantTab) {
   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
+  FocusOmniboxAndWaitForInstantNTPSupport();
+
+  // Open new tab. Preloaded NTP contents should have been used.
+  ui_test_utils::NavigateToURLWithDisposition(
+      browser(),
+      GURL(chrome::kChromeUINewTabURL),
+      NEW_FOREGROUND_TAB,
+      ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
 
   // Create an observer to wait for the instant tab to support Instant.
-  content::WindowedNotificationObserver observer(
+  content::WindowedNotificationObserver observer_1(
       chrome::NOTIFICATION_INSTANT_TAB_SUPPORT_DETERMINED,
       content::NotificationService::AllSources());
-
   SetOmniboxText("flowers");
-  browser()->window()->GetLocationBar()->AcceptInput();
-  observer.Wait();
+  PressEnterAndWaitForNavigation();
+  observer_1.Wait();
 
   // Just did a regular search.
-  ASSERT_THAT(
-      browser()->tab_strip_model()->GetActiveWebContents()->GetURL().spec(),
-      HasSubstr("q=flowers"));
-  ASSERT_TRUE(UpdateSearchState(instant()->instant_tab()->contents()));
+  content::WebContents* active_tab =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  ASSERT_THAT(active_tab->GetURL().spec(), HasSubstr("q=flowers"));
+  ASSERT_TRUE(UpdateSearchState(active_tab));
   ASSERT_EQ(0, submit_count_);
 
   // Typed in a search URL "by hand".
+  content::WindowedNotificationObserver observer_2(
+      chrome::NOTIFICATION_INSTANT_TAB_SUPPORT_DETERMINED,
+      content::NotificationService::AllSources());
   SetOmniboxText(instant_url().spec() + "#q=puppies");
-  browser()->window()->GetLocationBar()->AcceptInput();
+  PressEnterAndWaitForNavigation();
+  observer_2.Wait();
 
   // Should not have reused the tab.
-  ASSERT_THAT(
-      browser()->tab_strip_model()->GetActiveWebContents()->GetURL().spec(),
-      HasSubstr("q=puppies"));
+  active_tab = browser()->tab_strip_model()->GetActiveWebContents();
+  ASSERT_THAT(active_tab->GetURL().spec(), HasSubstr("q=puppies"));
 }
 
 IN_PROC_BROWSER_TEST_F(InstantExtendedTest, OmniboxMarginSetForSearchURLs) {
   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
+  FocusOmniboxAndWaitForInstantNTPSupport();
+
+  // Open new tab. Preloaded NTP contents should have been used.
+  ui_test_utils::NavigateToURLWithDisposition(
+      browser(),
+      GURL(chrome::kChromeUINewTabURL),
+      NEW_FOREGROUND_TAB,
+      ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
 
   // Create an observer to wait for the instant tab to support Instant.
   content::WindowedNotificationObserver observer(
@@ -2870,7 +1407,7 @@
 IN_PROC_BROWSER_TEST_F(InstantExtendedTest, NoMostVisitedChangedOnTabSwitch) {
   // Initialize Instant.
   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
+  FocusOmniboxAndWaitForInstantNTPSupport();
 
   // Open new tab. Preloaded NTP contents should have been used.
   ui_test_utils::NavigateToURLWithDisposition(
@@ -2884,7 +1421,7 @@
   content::WebContents* active_tab =
       browser()->tab_strip_model()->GetActiveWebContents();
   EXPECT_TRUE(UpdateSearchState(active_tab));
-  EXPECT_EQ(2, on_most_visited_change_calls_);
+  EXPECT_EQ(1, on_most_visited_change_calls_);
 
   // Activate the previous tab.
   browser()->tab_strip_model()->ActivateTabAt(0, false);
@@ -2895,5 +1432,346 @@
   // Confirm that new tab got no onmostvisitedchanged event.
   active_tab = browser()->tab_strip_model()->GetActiveWebContents();
   EXPECT_TRUE(UpdateSearchState(active_tab));
-  EXPECT_EQ(2, on_most_visited_change_calls_);
+  EXPECT_EQ(1, on_most_visited_change_calls_);
+}
+
+IN_PROC_BROWSER_TEST_F(InstantPolicyTest, ThemeBackgroundAccess) {
+  InstallThemeSource();
+  ASSERT_NO_FATAL_FAILURE(InstallThemeAndVerify("theme", "camo theme"));
+  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
+  FocusOmniboxAndWaitForInstantNTPSupport();
+
+  // The "Instant" New Tab should have access to chrome-search: scheme but not
+  // chrome: scheme.
+  ui_test_utils::NavigateToURLWithDisposition(
+      browser(),
+      GURL(chrome::kChromeUINewTabURL),
+      NEW_FOREGROUND_TAB,
+      ui_test_utils::BROWSER_TEST_NONE);
+
+  content::RenderViewHost* rvh =
+      browser()->tab_strip_model()->GetActiveWebContents()->GetRenderViewHost();
+
+  const std::string chrome_url("chrome://theme/IDR_THEME_NTP_BACKGROUND");
+  const std::string search_url(
+      "chrome-search://theme/IDR_THEME_NTP_BACKGROUND");
+  bool loaded = false;
+  ASSERT_TRUE(LoadImage(rvh, chrome_url, &loaded));
+  EXPECT_FALSE(loaded) << chrome_url;
+  ASSERT_TRUE(LoadImage(rvh, search_url, &loaded));
+  EXPECT_TRUE(loaded) << search_url;
+}
+
+IN_PROC_BROWSER_TEST_F(InstantPolicyTest,
+                       NoThemeBackgroundChangeEventOnTabSwitch) {
+  InstallThemeSource();
+  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
+  FocusOmniboxAndWaitForInstantNTPSupport();
+
+  // Install a theme.
+  ASSERT_NO_FATAL_FAILURE(InstallThemeAndVerify("theme", "camo theme"));
+  EXPECT_EQ(1, browser()->tab_strip_model()->count());
+
+  // Open new tab. Preloaded NTP contents should have been used.
+  ui_test_utils::NavigateToURLWithDisposition(
+      browser(),
+      GURL(chrome::kChromeUINewTabURL),
+      NEW_FOREGROUND_TAB,
+      ui_test_utils::BROWSER_TEST_NONE);
+  EXPECT_EQ(2, browser()->tab_strip_model()->count());
+
+  content::WebContents* active_tab =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  ASSERT_EQ(1, browser()->tab_strip_model()->active_index());
+  int on_theme_changed_calls = 0;
+  EXPECT_TRUE(GetIntFromJS(active_tab, "onThemeChangedCalls",
+                           &on_theme_changed_calls));
+  EXPECT_EQ(1, on_theme_changed_calls);
+
+  // Activate the previous tab.
+  browser()->tab_strip_model()->ActivateTabAt(0, false);
+  ASSERT_EQ(0, browser()->tab_strip_model()->active_index());
+
+  // Switch back to new tab.
+  browser()->tab_strip_model()->ActivateTabAt(1, false);
+  ASSERT_EQ(1, browser()->tab_strip_model()->active_index());
+
+  // Confirm that new tab got no onthemechanged event while switching tabs.
+  active_tab = browser()->tab_strip_model()->GetActiveWebContents();
+  on_theme_changed_calls = 0;
+  EXPECT_TRUE(GetIntFromJS(active_tab, "onThemeChangedCalls",
+                           &on_theme_changed_calls));
+  EXPECT_EQ(1, on_theme_changed_calls);
+}
+
+IN_PROC_BROWSER_TEST_F(InstantPolicyTest,
+                       SendThemeBackgroundChangedEvent) {
+  InstallThemeSource();
+  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
+  FocusOmniboxAndWaitForInstantNTPSupport();
+
+  // Install a theme.
+  ASSERT_NO_FATAL_FAILURE(InstallThemeAndVerify("theme", "camo theme"));
+
+  // Open new tab. Preloaded NTP contents should have been used.
+  ui_test_utils::NavigateToURLWithDisposition(
+      browser(),
+      GURL(chrome::kChromeUINewTabURL),
+      NEW_FOREGROUND_TAB,
+      ui_test_utils::BROWSER_TEST_NONE);
+  EXPECT_EQ(2, browser()->tab_strip_model()->count());
+
+  // Make sure new tab received an onthemechanged event.
+  content::WebContents* active_tab =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  ASSERT_EQ(1, browser()->tab_strip_model()->active_index());
+  int on_theme_changed_calls = 0;
+  EXPECT_TRUE(GetIntFromJS(active_tab, "onThemeChangedCalls",
+                           &on_theme_changed_calls));
+  EXPECT_EQ(1, on_theme_changed_calls);
+
+  // Install a new theme.
+  ASSERT_NO_FATAL_FAILURE(InstallThemeAndVerify("theme2", "snowflake theme"));
+
+  // Confirm that new tab is notified about the theme changed event.
+  on_theme_changed_calls = 0;
+  EXPECT_TRUE(GetIntFromJS(active_tab, "onThemeChangedCalls",
+                           &on_theme_changed_calls));
+  EXPECT_EQ(2, on_theme_changed_calls);
+}
+
+// Flaky on Mac and Linux Tests bots.
+#if defined(OS_MACOSX) || defined(OS_LINUX)
+#define MAYBE_UpdateSearchQueryOnBackNavigation DISABLED_UpdateSearchQueryOnBackNavigation
+#else
+#define MAYBE_UpdateSearchQueryOnBackNavigation UpdateSearchQueryOnBackNavigation
+#endif
+// Test to verify that the omnibox search query is updated on browser
+// back button press event.
+IN_PROC_BROWSER_TEST_F(InstantExtendedTest,
+                       MAYBE_UpdateSearchQueryOnBackNavigation) {
+  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
+
+  // Focus omnibox and confirm overlay isn't shown.
+  FocusOmniboxAndWaitForInstantNTPSupport();
+
+  // Open new tab. Preloaded NTP contents should have been used.
+  ui_test_utils::NavigateToURLWithDisposition(
+      browser(),
+      GURL(chrome::kChromeUINewTabURL),
+      NEW_FOREGROUND_TAB,
+      ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
+
+  // Create an observer to wait for the instant tab to support Instant.
+  content::WindowedNotificationObserver observer(
+      chrome::NOTIFICATION_INSTANT_TAB_SUPPORT_DETERMINED,
+      content::NotificationService::AllSources());
+
+  SetOmniboxText("flowers");
+  // Commit the search by pressing 'Enter'.
+  PressEnterAndWaitForNavigation();
+  observer.Wait();
+
+  EXPECT_EQ(ASCIIToUTF16("flowers"), omnibox()->GetText());
+
+  // Typing in the new search query in omnibox.
+  SetOmniboxText("cattles");
+  // Commit the search by pressing 'Enter'.
+  PressEnterAndWaitForNavigation();
+  // 'Enter' commits the query as it was typed. This creates a navigation entry
+  // in the history.
+  EXPECT_EQ(ASCIIToUTF16("cattles"), omnibox()->GetText());
+
+  content::WebContents* active_tab =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  EXPECT_TRUE(active_tab->GetController().CanGoBack());
+  content::WindowedNotificationObserver load_stop_observer(
+      content::NOTIFICATION_LOAD_STOP,
+      content::Source<content::NavigationController>(
+          &active_tab->GetController()));
+  active_tab->GetController().GoBack();
+  load_stop_observer.Wait();
+
+  EXPECT_EQ(ASCIIToUTF16("flowers"), omnibox()->GetText());
+  // Commit the search by pressing 'Enter'.
+  FocusOmnibox();
+  PressEnterAndWaitForNavigation();
+  EXPECT_EQ(ASCIIToUTF16("flowers"), omnibox()->GetText());
+}
+
+// Flaky on Mac and Linux Tests bots.
+#if defined(OS_MACOSX) || defined(OS_LINUX)
+#define MAYBE_UpdateSearchQueryOnForwardNavigation DISABLED_UpdateSearchQueryOnForwardNavigation
+#else
+#define MAYBE_UpdateSearchQueryOnForwardNavigation UpdateSearchQueryOnForwardNavigation
+#endif
+// Test to verify that the omnibox search query is updated on browser
+// forward button press events.
+IN_PROC_BROWSER_TEST_F(InstantExtendedTest,
+                       MAYBE_UpdateSearchQueryOnForwardNavigation) {
+  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
+
+  // Focus omnibox and confirm overlay isn't shown.
+  FocusOmniboxAndWaitForInstantNTPSupport();
+
+  // Open new tab. Preloaded NTP contents should have been used.
+  ui_test_utils::NavigateToURLWithDisposition(
+      browser(),
+      GURL(chrome::kChromeUINewTabURL),
+      NEW_FOREGROUND_TAB,
+      ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
+
+  // Create an observer to wait for the instant tab to support Instant.
+  content::WindowedNotificationObserver observer(
+      chrome::NOTIFICATION_INSTANT_TAB_SUPPORT_DETERMINED,
+      content::NotificationService::AllSources());
+
+  SetOmniboxText("flowers");
+  // Commit the search by pressing 'Enter'.
+  PressEnterAndWaitForNavigation();
+  observer.Wait();
+
+  EXPECT_EQ(ASCIIToUTF16("flowers"), omnibox()->GetText());
+
+  // Typing in the new search query in omnibox.
+  SetOmniboxText("cattles");
+  // Commit the search by pressing 'Enter'.
+  PressEnterAndWaitForNavigation();
+  // 'Enter' commits the query as it was typed. This creates a navigation entry
+  // in the history.
+  EXPECT_EQ(ASCIIToUTF16("cattles"), omnibox()->GetText());
+
+  content::WebContents* active_tab =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  EXPECT_TRUE(active_tab->GetController().CanGoBack());
+  content::WindowedNotificationObserver load_stop_observer(
+      content::NOTIFICATION_LOAD_STOP,
+      content::Source<content::NavigationController>(
+          &active_tab->GetController()));
+  active_tab->GetController().GoBack();
+  load_stop_observer.Wait();
+
+  EXPECT_EQ(ASCIIToUTF16("flowers"), omnibox()->GetText());
+
+  active_tab = browser()->tab_strip_model()->GetActiveWebContents();
+  EXPECT_TRUE(active_tab->GetController().CanGoForward());
+  content::WindowedNotificationObserver load_stop_observer_2(
+      content::NOTIFICATION_LOAD_STOP,
+      content::Source<content::NavigationController>(
+          &active_tab->GetController()));
+  active_tab->GetController().GoForward();
+  load_stop_observer_2.Wait();
+
+  // Commit the search by pressing 'Enter'.
+  FocusOmnibox();
+  EXPECT_EQ(ASCIIToUTF16("cattles"), omnibox()->GetText());
+  PressEnterAndWaitForNavigation();
+  EXPECT_EQ(ASCIIToUTF16("cattles"), omnibox()->GetText());
+}
+
+// Flaky on all bots since re-enabled in r208032, crbug.com/253092
+IN_PROC_BROWSER_TEST_F(InstantExtendedTest, DISABLED_NavigateBackToNTP) {
+  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
+  FocusOmniboxAndWaitForInstantNTPSupport();
+
+  // Open a new tab page.
+  ui_test_utils::NavigateToURLWithDisposition(
+      browser(),
+      GURL(chrome::kChromeUINewTabURL),
+      NEW_FOREGROUND_TAB,
+      ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
+  EXPECT_EQ(2, browser()->tab_strip_model()->count());
+
+  content::WindowedNotificationObserver observer(
+      chrome::NOTIFICATION_INSTANT_TAB_SUPPORT_DETERMINED,
+      content::NotificationService::AllSources());
+  SetOmniboxText("flowers");
+  PressEnterAndWaitForNavigation();
+  observer.Wait();
+
+  EXPECT_EQ(ASCIIToUTF16("flowers"), omnibox()->GetText());
+
+  // Typing in the new search query in omnibox.
+  // Commit the search by pressing 'Enter'.
+  SetOmniboxText("cattles");
+  PressEnterAndWaitForNavigation();
+
+  // 'Enter' commits the query as it was typed. This creates a navigation entry
+  // in the history.
+  EXPECT_EQ(ASCIIToUTF16("cattles"), omnibox()->GetText());
+
+  // Navigate back to "flowers" search result page.
+  content::WebContents* active_tab =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  EXPECT_TRUE(active_tab->GetController().CanGoBack());
+  content::WindowedNotificationObserver load_stop_observer(
+      content::NOTIFICATION_LOAD_STOP,
+      content::Source<content::NavigationController>(
+          &active_tab->GetController()));
+  active_tab->GetController().GoBack();
+  load_stop_observer.Wait();
+
+  EXPECT_EQ(ASCIIToUTF16("flowers"), omnibox()->GetText());
+
+  // Navigate back to NTP.
+  active_tab = browser()->tab_strip_model()->GetActiveWebContents();
+  EXPECT_TRUE(active_tab->GetController().CanGoBack());
+  content::WindowedNotificationObserver load_stop_observer_2(
+      content::NOTIFICATION_LOAD_STOP,
+      content::Source<content::NavigationController>(
+          &active_tab->GetController()));
+  active_tab->GetController().GoBack();
+  load_stop_observer_2.Wait();
+
+  active_tab = browser()->tab_strip_model()->GetActiveWebContents();
+  EXPECT_TRUE(chrome::IsInstantNTP(active_tab));
+}
+
+// Flaky on Windows and Mac try bots.
+#if defined(OS_CHROMEOS)
+#define MAYBE_DispatchMVChangeEventWhileNavigatingBackToNTP DispatchMVChangeEventWhileNavigatingBackToNTP
+#else
+#define MAYBE_DispatchMVChangeEventWhileNavigatingBackToNTP DISABLED_DispatchMVChangeEventWhileNavigatingBackToNTP
+#endif
+IN_PROC_BROWSER_TEST_F(InstantExtendedTest,
+                       MAYBE_DispatchMVChangeEventWhileNavigatingBackToNTP) {
+  // Setup Instant.
+  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
+  FocusOmniboxAndWaitForInstantNTPSupport();
+
+  // Open new tab. Preloaded NTP contents should have been used.
+  ui_test_utils::NavigateToURLWithDisposition(
+      browser(),
+      GURL(chrome::kChromeUINewTabURL),
+      NEW_FOREGROUND_TAB,
+      ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
+
+  content::WebContents* active_tab =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  EXPECT_TRUE(UpdateSearchState(active_tab));
+  EXPECT_EQ(1, on_most_visited_change_calls_);
+
+  content::WindowedNotificationObserver observer(
+      content::NOTIFICATION_LOAD_STOP,
+      content::NotificationService::AllSources());
+  // Set the text and press enter to navigate from NTP.
+  SetOmniboxText("Pen");
+  PressEnterAndWaitForNavigation();
+  EXPECT_EQ(ASCIIToUTF16("Pen"), omnibox()->GetText());
+  observer.Wait();
+
+  // Navigate back to NTP.
+  content::WindowedNotificationObserver back_observer(
+      content::NOTIFICATION_LOAD_STOP,
+      content::NotificationService::AllSources());
+  active_tab = browser()->tab_strip_model()->GetActiveWebContents();
+  EXPECT_TRUE(active_tab->GetController().CanGoBack());
+  active_tab->GetController().GoBack();
+  back_observer.Wait();
+
+  // Verify that onmostvisitedchange event is dispatched when we navigate from
+  // SRP to NTP.
+  active_tab = browser()->tab_strip_model()->GetActiveWebContents();
+  EXPECT_TRUE(UpdateSearchState(active_tab));
+  EXPECT_EQ(1, on_most_visited_change_calls_);
 }
diff --git a/chrome/browser/ui/search/instant_extended_manual_interactive_uitest.cc b/chrome/browser/ui/search/instant_extended_manual_interactive_uitest.cc
index ff81870..6ee7e94 100644
--- a/chrome/browser/ui/search/instant_extended_manual_interactive_uitest.cc
+++ b/chrome/browser/ui/search/instant_extended_manual_interactive_uitest.cc
@@ -11,10 +11,10 @@
 #include "chrome/browser/ui/host_desktop.h"
 #include "chrome/browser/ui/omnibox/omnibox_view.h"
 #include "chrome/browser/ui/search/instant_ntp.h"
-#include "chrome/browser/ui/search/instant_overlay.h"
 #include "chrome/browser/ui/search/instant_test_utils.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/chrome_notification_types.h"
+#include "chrome/common/omnibox_focus_state.h"
 #include "chrome/common/search_types.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/base/in_process_browser_test.h"
@@ -59,7 +59,7 @@
         testing::UnitTest::GetInstance()->current_test_info();
     ASSERT_TRUE(StartsWithASCII(test_info->name(), "MANUAL_", true) ||
                 StartsWithASCII(test_info->name(), "DISABLED_", true));
-    // Make IsOffline() return false so we don't try to use the local overlay.
+    // Make IsOffline() return false so we don't try to use the local NTP.
     disable_network_change_notifier_.reset(
         new net::NetworkChangeNotifier::DisableForTest());
   }
@@ -68,16 +68,6 @@
     disable_network_change_notifier_.reset();
   }
 
-  void ResetInstant() {
-    set_browser(browser());
-    instant()->SetInstantEnabled(false, true);
-    instant()->SetInstantEnabled(true, false);
-
-    FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-    ASSERT_TRUE(IsGoogleOverlay());
-    ASSERT_TRUE(IsGoogleNTP());
-  }
-
  protected:
   virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
     chrome::EnableInstantExtendedAPIForTesting();
@@ -87,47 +77,6 @@
     return browser()->tab_strip_model()->GetActiveWebContents();
   }
 
-  bool PressBackspace() {
-    return ui_test_utils::SendKeyPressSync(browser(), ui::VKEY_BACK,
-                                           false, false, false, false);
-  }
-
-  bool PressBackspaceAndWaitForSuggestions() {
-    content::WindowedNotificationObserver observer(
-        chrome::NOTIFICATION_INSTANT_SET_SUGGESTION,
-        content::NotificationService::AllSources());
-    bool result = PressBackspace();
-    observer.Wait();
-    return result;
-  }
-
-  bool PressBackspaceAndWaitForOverlayToShow() {
-    InstantTestModelObserver observer(
-        instant()->model(), SearchMode::MODE_SEARCH_SUGGESTIONS);
-    return PressBackspace() && observer.WaitForExpectedOverlayState() ==
-        SearchMode::MODE_SEARCH_SUGGESTIONS;
-  }
-
-  bool PressEnterAndWaitForNavigationWithTitle(content::WebContents* contents,
-                                               const string16& title) {
-    content::TitleWatcher title_watcher(contents, title);
-    content::WindowedNotificationObserver nav_observer(
-        content::NOTIFICATION_NAV_ENTRY_COMMITTED,
-        content::NotificationService::AllSources());
-    browser()->window()->GetLocationBar()->AcceptInput();
-    nav_observer.Wait();
-    return title_watcher.WaitAndGetTitle() == title;
-  }
-
-  GURL GetActiveTabURL() {
-    return active_tab()->GetController().GetActiveEntry()->GetURL();
-  }
-
-  bool GetSelectionState(bool* selected) {
-    return GetBoolFromJS(instant()->GetOverlayContents(),
-                         "google.ac.gs().api.i()", selected);
-  }
-
   bool IsGooglePage(content::WebContents* contents) {
     bool is_google = false;
     if (!GetBoolFromJS(contents, "!!window.google", &is_google))
@@ -135,14 +84,6 @@
     return is_google;
   }
 
-  bool IsGoogleOverlay() {
-    return IsGooglePage(instant()->overlay()->contents());
-  }
-
-  bool IsGoogleNTP() {
-    return IsGooglePage(instant()->ntp()->contents());
-  }
-
  private:
   scoped_refptr<net::RuleBasedHostResolverProc> host_resolver_proc_;
   scoped_ptr<net::ScopedDefaultHostResolverProc> scoped_host_resolver_proc_;
@@ -150,31 +91,75 @@
       disable_network_change_notifier_;
 };
 
-IN_PROC_BROWSER_TEST_F(InstantExtendedManualTest,
-                       MANUAL_OmniboxFocusLoadsInstant) {
+IN_PROC_BROWSER_TEST_F(InstantExtendedManualTest, MANUAL_ShowsGoogleNTP) {
   set_browser(browser());
+  instant()->ReloadStaleNTP();
+  FocusOmniboxAndWaitForInstantNTPSupport();
 
-  // Explicitly unfocus the omnibox.
-  EXPECT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
+  content::WindowedNotificationObserver observer(
+      content::NOTIFICATION_NAV_ENTRY_COMMITTED,
+      content::NotificationService::AllSources());
+  ui_test_utils::NavigateToURLWithDisposition(
+      browser(),
+      GURL(chrome::kChromeUINewTabURL),
+      CURRENT_TAB,
+      ui_test_utils::BROWSER_TEST_NONE);
+  observer.Wait();
+  content::WebContents* active_tab =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  EXPECT_TRUE(IsGooglePage(active_tab));
+}
+
+IN_PROC_BROWSER_TEST_F(InstantExtendedManualTest, MANUAL_SearchesFromFakebox) {
+  set_browser(browser());
+  instant()->ReloadStaleNTP();
+  FocusOmniboxAndWaitForInstantNTPSupport();
+
+  // Open a new tab page.
+  content::WindowedNotificationObserver observer(
+      content::NOTIFICATION_NAV_ENTRY_COMMITTED,
+      content::NotificationService::AllSources());
+  ui_test_utils::NavigateToURLWithDisposition(
+      browser(),
+      GURL(chrome::kChromeUINewTabURL),
+      CURRENT_TAB,
+      ui_test_utils::BROWSER_TEST_NONE);
+  observer.Wait();
+  content::WebContents* active_tab =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  ASSERT_TRUE(IsGooglePage(active_tab));
+
+  // Click in the fakebox and expect invisible focus.
   ui_test_utils::ClickOnView(browser(), VIEW_ID_TAB_CONTAINER);
+  bool fakebox_is_present = false;
+  content::WindowedNotificationObserver focus_observer(
+      chrome::NOTIFICATION_OMNIBOX_FOCUS_CHANGED,
+      content::NotificationService::AllSources());
+  ASSERT_TRUE(GetBoolFromJS(active_tab, "!!document.querySelector('#fkbx')",
+                            &fakebox_is_present));
+  ASSERT_TRUE(fakebox_is_present);
+  ASSERT_TRUE(content::ExecuteScript(
+      active_tab, "document.querySelector('#fkbx').click()"));
+  focus_observer.Wait();
+  EXPECT_EQ(OMNIBOX_FOCUS_INVISIBLE, omnibox()->model()->focus_state());
 
-  EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_TAB_CONTAINER));
-  EXPECT_FALSE(omnibox()->model()->has_focus());
+  // Type "test".
+  const ui::KeyboardCode query[] = {
+    ui::VKEY_T, ui::VKEY_E, ui::VKEY_S, ui::VKEY_T,
+    ui::VKEY_UNKNOWN
+  };
+  for (size_t i = 0; query[i] != ui::VKEY_UNKNOWN; i++) {
+    ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), query[i],
+                                                false, false, false, false));
+  }
 
-  // Delete any existing overlay.
-  instant()->overlay_.reset();
-  EXPECT_FALSE(instant()->GetOverlayContents());
+  // The omnibox should say "test" and have visible focus.
+  EXPECT_EQ("test", GetOmniboxText());
+  EXPECT_EQ(OMNIBOX_FOCUS_VISIBLE, omnibox()->model()->focus_state());
 
-  // Refocus the omnibox. The InstantController should've preloaded Instant.
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
-  ASSERT_TRUE(IsGoogleOverlay());
-
-  EXPECT_FALSE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_TAB_CONTAINER));
-  EXPECT_TRUE(omnibox()->model()->has_focus());
-
-  // Check that the page supports Instant, but it isn't showing.
-  ASSERT_TRUE(instant()->overlay());
-  EXPECT_TRUE(instant()->overlay()->supports_instant());
-  EXPECT_FALSE(instant()->IsOverlayingSearchResults());
-  EXPECT_TRUE(instant()->model()->mode().is_default());
+  // Pressing enter should search for [test].
+  const string16& search_title = ASCIIToUTF16("test - Google Search");
+  content::TitleWatcher title_watcher(active_tab, search_title);
+  PressEnterAndWaitForNavigation();
+  EXPECT_EQ(search_title, title_watcher.WaitAndGetTitle());
 }
diff --git a/chrome/browser/ui/search/instant_ipc_sender.cc b/chrome/browser/ui/search/instant_ipc_sender.cc
new file mode 100644
index 0000000..a457534
--- /dev/null
+++ b/chrome/browser/ui/search/instant_ipc_sender.cc
@@ -0,0 +1,98 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/search/instant_ipc_sender.h"
+
+#include "chrome/common/render_messages.h"
+
+namespace {
+
+// Implementation for regular profiles.
+class InstantIPCSenderImpl : public InstantIPCSender {
+ public:
+  InstantIPCSenderImpl() {}
+  virtual ~InstantIPCSenderImpl() {}
+
+ private:
+  virtual void Submit(const string16& text) OVERRIDE {
+    Send(new ChromeViewMsg_SearchBoxSubmit(routing_id(), text));
+  }
+
+  virtual void SetOmniboxBounds(const gfx::Rect& bounds) OVERRIDE {
+    Send(new ChromeViewMsg_SearchBoxMarginChange(
+        routing_id(), bounds.x(), bounds.width()));
+  }
+
+  virtual void SetFontInformation(const string16& omnibox_font_name,
+                          size_t omnibox_font_size) OVERRIDE {
+    Send(new ChromeViewMsg_SearchBoxFontInformation(
+        routing_id(), omnibox_font_name, omnibox_font_size));
+  }
+
+  virtual void SetPromoInformation(bool is_app_launcher_enabled) OVERRIDE {
+    Send(new ChromeViewMsg_SearchBoxPromoInformation(
+        routing_id(), is_app_launcher_enabled));
+  }
+
+  virtual void SendThemeBackgroundInfo(
+      const ThemeBackgroundInfo& theme_info) OVERRIDE {
+    Send(new ChromeViewMsg_SearchBoxThemeChanged(routing_id(), theme_info));
+  }
+
+  virtual void FocusChanged(OmniboxFocusState state,
+                    OmniboxFocusChangeReason reason) OVERRIDE {
+    Send(new ChromeViewMsg_SearchBoxFocusChanged(routing_id(), state, reason));
+  }
+
+  virtual void SetInputInProgress(bool input_in_progress) OVERRIDE {
+    Send(new ChromeViewMsg_SearchBoxSetInputInProgress(
+        routing_id(), input_in_progress));
+  }
+
+  virtual void SendMostVisitedItems(
+      const std::vector<InstantMostVisitedItem>& items) OVERRIDE {
+    Send(new ChromeViewMsg_SearchBoxMostVisitedItemsChanged(
+        routing_id(), items));
+  }
+
+  virtual void ToggleVoiceSearch() OVERRIDE {
+    Send(new ChromeViewMsg_SearchBoxToggleVoiceSearch(routing_id()));
+  }
+
+  DISALLOW_COPY_AND_ASSIGN(InstantIPCSenderImpl);
+};
+
+// Implementation for incognito profiles.
+class IncognitoInstantIPCSenderImpl : public InstantIPCSender {
+ public:
+  IncognitoInstantIPCSenderImpl() {}
+  virtual ~IncognitoInstantIPCSenderImpl() {}
+
+ private:
+  virtual void Submit(const string16& text) OVERRIDE {
+    Send(new ChromeViewMsg_SearchBoxSubmit(routing_id(), text));
+  }
+
+  virtual void SetOmniboxBounds(const gfx::Rect& bounds) OVERRIDE {
+    Send(new ChromeViewMsg_SearchBoxMarginChange(
+        routing_id(), bounds.x(), bounds.width()));
+  }
+
+  DISALLOW_COPY_AND_ASSIGN(IncognitoInstantIPCSenderImpl);
+};
+
+}  // anonymous namespace
+
+// static
+scoped_ptr<InstantIPCSender> InstantIPCSender::Create(bool is_incognito) {
+  scoped_ptr<InstantIPCSender> sender(
+      is_incognito ?
+      static_cast<InstantIPCSender*>(new IncognitoInstantIPCSenderImpl()) :
+      static_cast<InstantIPCSender*>(new InstantIPCSenderImpl()));
+  return sender.Pass();
+}
+
+void InstantIPCSender::SetContents(content::WebContents* web_contents) {
+  Observe(web_contents);
+}
diff --git a/chrome/browser/ui/search/instant_ipc_sender.h b/chrome/browser/ui/search/instant_ipc_sender.h
new file mode 100644
index 0000000..8319f2c
--- /dev/null
+++ b/chrome/browser/ui/search/instant_ipc_sender.h
@@ -0,0 +1,73 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_SEARCH_INSTANT_IPC_SENDER_H_
+#define CHROME_BROWSER_UI_SEARCH_INSTANT_IPC_SENDER_H_
+
+#include <vector>
+
+#include "base/memory/scoped_ptr.h"
+#include "chrome/common/instant_types.h"
+#include "chrome/common/omnibox_focus_state.h"
+#include "content/public/browser/web_contents_observer.h"
+
+namespace gfx {
+class Rect;
+}
+
+namespace IPC {
+class Sender;
+}
+
+class InstantIPCSender : public content::WebContentsObserver {
+ public:
+  // Creates a new instance of InstantIPCSender. If |is_incognito| is true,
+  // the instance will only send appropriate IPCs for incognito profiles.
+  static scoped_ptr<InstantIPCSender> Create(bool is_incognito);
+
+  virtual ~InstantIPCSender() {}
+
+  // Sets |web_contents| as the receiver of IPCs.
+  void SetContents(content::WebContents* web_contents);
+
+  // Tells the page that the user pressed Enter in the omnibox.
+  virtual void Submit(const string16& text) {}
+
+  // Tells the page the bounds of the omnibox (in screen coordinates). This is
+  // used by the page to align text or assets properly with the omnibox.
+  virtual void SetOmniboxBounds(const gfx::Rect& bounds) {}
+
+  // Tells the page about the font information.
+  virtual void SetFontInformation(const string16& omnibox_font_name,
+                                  size_t omnibox_font_size) {}
+
+  // Tells the page information it needs to display promos.
+  virtual void SetPromoInformation(bool is_app_launcher_enabled) {}
+
+  // Tells the page about the current theme background.
+  virtual void SendThemeBackgroundInfo(
+      const ThemeBackgroundInfo& theme_info) {}
+
+  // Tells the page that the omnibox focus has changed.
+  virtual void FocusChanged(OmniboxFocusState state,
+                            OmniboxFocusChangeReason reason) {}
+
+  // Tells the page that user input started or stopped.
+  virtual void SetInputInProgress(bool input_in_progress) {}
+
+  // Tells the page about new Most Visited data.
+  virtual void SendMostVisitedItems(
+      const std::vector<InstantMostVisitedItem>& items) {}
+
+  // Tells the page to toggle voice search.
+  virtual void ToggleVoiceSearch() {}
+
+ protected:
+  InstantIPCSender() {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(InstantIPCSender);
+};
+
+#endif  // CHROME_BROWSER_UI_SEARCH_INSTANT_IPC_SENDER_H_
diff --git a/chrome/browser/ui/search/instant_loader.cc b/chrome/browser/ui/search/instant_loader.cc
index 79d0031..c50b7fb 100644
--- a/chrome/browser/ui/search/instant_loader.cc
+++ b/chrome/browser/ui/search/instant_loader.cc
@@ -21,6 +21,8 @@
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/site_instance.h"
 #include "content/public/browser/web_contents_view.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace {
 
@@ -56,6 +58,17 @@
   contents_->GetController().LoadURL(
       instant_url_, content::Referrer(),
       content::PAGE_TRANSITION_GENERATED, kInstantHeader);
+
+  // Explicitly set the new tab title and virtual URL.
+  //
+  // This ensures that the title is set even before we get a title from the
+  // page, preventing a potential flicker of the URL, and also ensures that
+  // (unless overridden by the page) the new tab title matches the browser UI
+  // locale.
+  content::NavigationEntry* entry = contents_->GetController().GetActiveEntry();
+  if (entry)
+    entry->SetTitle(l10n_util::GetStringUTF16(IDS_NEW_TAB_TITLE));
+
   contents_->WasHidden();
 
   int staleness_timeout_ms = chrome::GetInstantLoaderStalenessTimeoutSec() *
diff --git a/chrome/browser/ui/search/instant_loader.h b/chrome/browser/ui/search/instant_loader.h
index 6071cbd..e0ec012 100644
--- a/chrome/browser/ui/search/instant_loader.h
+++ b/chrome/browser/ui/search/instant_loader.h
@@ -9,7 +9,7 @@
 #include "base/callback.h"
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/ui/tab_contents/core_tab_helper_delegate.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
diff --git a/chrome/browser/ui/search/instant_ntp.cc b/chrome/browser/ui/search/instant_ntp.cc
index bda523e..5813ae0 100644
--- a/chrome/browser/ui/search/instant_ntp.cc
+++ b/chrome/browser/ui/search/instant_ntp.cc
@@ -4,13 +4,16 @@
 
 #include "chrome/browser/ui/search/instant_ntp.h"
 
+#include "chrome/browser/ui/search/search_tab_helper.h"
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/web_contents.h"
 
 InstantNTP::InstantNTP(InstantPage::Delegate* delegate,
-                       const std::string& instant_url)
-    : InstantPage(delegate, instant_url),
+                       const std::string& instant_url,
+                       bool is_incognito)
+    : InstantPage(delegate, instant_url, is_incognito),
       loader_(this) {
+  DCHECK(delegate);
 }
 
 InstantNTP::~InstantNTP() {
@@ -21,6 +24,7 @@
                               const base::Closure& on_stale_callback) {
   loader_.Init(GURL(instant_url()), profile, active_tab, on_stale_callback);
   SetContents(loader_.contents());
+  SearchTabHelper::FromWebContents(contents())->InitForPreloadedNTP();
   loader_.Load();
 }
 
@@ -29,6 +33,14 @@
   return loader_.ReleaseContents();
 }
 
+void InstantNTP::RenderViewCreated(content::RenderViewHost* render_view_host) {
+  delegate()->InstantPageRenderViewCreated(contents());
+}
+
+void InstantNTP::RenderViewGone(base::TerminationStatus /* status */) {
+  delegate()->InstantPageRenderViewGone(contents());
+}
+
 void InstantNTP::OnSwappedContents() {
   SetContents(loader_.contents());
 }
@@ -53,11 +65,3 @@
 
 void InstantNTP::LoadCompletedMainFrame() {
 }
-
-bool InstantNTP::ShouldProcessRenderViewCreated() {
-  return true;
-}
-
-bool InstantNTP::ShouldProcessRenderViewGone() {
-  return true;
-}
diff --git a/chrome/browser/ui/search/instant_ntp.h b/chrome/browser/ui/search/instant_ntp.h
index eedc6e1..3000ee5 100644
--- a/chrome/browser/ui/search/instant_ntp.h
+++ b/chrome/browser/ui/search/instant_ntp.h
@@ -10,18 +10,24 @@
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/process_util.h"
 #include "chrome/browser/ui/search/instant_loader.h"
 #include "chrome/browser/ui/search/instant_page.h"
 
 class Profile;
 
+namespace content {
+class RenderViewHost;
+}
+
 // InstantNTP is used to preload an Instant page that will be swapped in when a
 // user navigates to a New Tab Page (NTP). The InstantNTP contents are never
 // shown in an un-committed state.
 class InstantNTP : public InstantPage,
                    public InstantLoader::Delegate {
  public:
-  InstantNTP(InstantPage::Delegate* delegate, const std::string& instant_url);
+  InstantNTP(InstantPage::Delegate* delegate, const std::string& instant_url,
+             bool is_incognito);
   virtual ~InstantNTP();
 
   // Creates a new WebContents and loads |instant_url_| into it. Uses
@@ -37,6 +43,12 @@
   scoped_ptr<content::WebContents> ReleaseContents();
 
  private:
+  // Overridden from content::WebContentsObserver:
+  virtual void RenderViewCreated(
+      content::RenderViewHost* render_view_host) OVERRIDE;
+  virtual void RenderViewGone(
+      base::TerminationStatus status) OVERRIDE;
+
   // Overriden from InstantLoader::Delegate:
   virtual void OnSwappedContents() OVERRIDE;
   virtual void OnFocus() OVERRIDE;
@@ -47,10 +59,6 @@
       const content::OpenURLParams& params) OVERRIDE;
   virtual void LoadCompletedMainFrame() OVERRIDE;
 
-  // Overridden from InstantPage:
-  virtual bool ShouldProcessRenderViewCreated() OVERRIDE;
-  virtual bool ShouldProcessRenderViewGone() OVERRIDE;
-
   InstantLoader loader_;
 
   DISALLOW_COPY_AND_ASSIGN(InstantNTP);
diff --git a/chrome/browser/ui/search/instant_overlay.cc b/chrome/browser/ui/search/instant_overlay.cc
deleted file mode 100644
index 6656964..0000000
--- a/chrome/browser/ui/search/instant_overlay.cc
+++ /dev/null
@@ -1,171 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/search/instant_overlay.h"
-
-#include "base/auto_reset.h"
-#include "base/supports_user_data.h"
-#include "chrome/browser/search/search.h"
-#include "chrome/common/url_constants.h"
-#include "content/public/browser/web_contents.h"
-
-namespace {
-
-int kUserDataKey;
-
-class InstantOverlayUserData : public base::SupportsUserData::Data {
- public:
-  explicit InstantOverlayUserData(InstantOverlay* overlay)
-      : overlay_(overlay) {}
-
-  virtual InstantOverlay* overlay() const { return overlay_; }
-
- private:
-  virtual ~InstantOverlayUserData() {}
-
-  InstantOverlay* const overlay_;
-
-  DISALLOW_COPY_AND_ASSIGN(InstantOverlayUserData);
-};
-
-}  // namespace
-
-// static
-InstantOverlay* InstantOverlay::FromWebContents(
-    const content::WebContents* web_contents) {
-  InstantOverlayUserData* data = static_cast<InstantOverlayUserData*>(
-      web_contents->GetUserData(&kUserDataKey));
-  return data ? data->overlay() : NULL;
-}
-
-InstantOverlay::InstantOverlay(InstantController* controller,
-                               const std::string& instant_url)
-    : InstantPage(controller, instant_url),
-      loader_(this),
-      is_stale_(false),
-      is_pointer_down_from_activate_(false) {
-}
-
-InstantOverlay::~InstantOverlay() {
-}
-
-void InstantOverlay::InitContents(Profile* profile,
-                                  const content::WebContents* active_tab) {
-  loader_.Init(GURL(instant_url()), profile, active_tab,
-               base::Bind(&InstantOverlay::HandleStalePage,
-                           base::Unretained(this)));
-  SetContents(loader_.contents());
-  contents()->SetUserData(&kUserDataKey, new InstantOverlayUserData(this));
-  loader_.Load();
-}
-
-scoped_ptr<content::WebContents> InstantOverlay::ReleaseContents() {
-  contents()->RemoveUserData(&kUserDataKey);
-  SetContents(NULL);
-  return loader_.ReleaseContents();
-}
-
-void InstantOverlay::DidNavigate(
-    const history::HistoryAddPageArgs& add_page_args) {
-  last_navigation_ = add_page_args;
-}
-
-void InstantOverlay::Update(const string16& text,
-                            size_t selection_start,
-                            size_t selection_end,
-                            bool verbatim) {
-  last_navigation_ = history::HistoryAddPageArgs();
-  InstantPage::Update(text, selection_start, selection_end, verbatim);
-}
-
-bool InstantOverlay::ShouldProcessRenderViewCreated() {
-  return true;
-}
-
-bool InstantOverlay::ShouldProcessRenderViewGone() {
-  return true;
-}
-
-bool InstantOverlay::ShouldProcessAboutToNavigateMainFrame() {
-  return true;
-}
-
-bool InstantOverlay::ShouldProcessSetSuggestions() {
-  return true;
-}
-
-bool InstantOverlay::ShouldProcessShowInstantOverlay() {
-  return true;
-}
-
-bool InstantOverlay::ShouldProcessNavigateToURL() {
-  return true;
-}
-
-void InstantOverlay::OnSwappedContents() {
-  contents()->RemoveUserData(&kUserDataKey);
-  SetContents(loader_.contents());
-  contents()->SetUserData(&kUserDataKey, new InstantOverlayUserData(this));
-  instant_controller()->SwappedOverlayContents();
-}
-
-void InstantOverlay::OnFocus() {
-  // The overlay is getting focus. Equivalent to it being clicked.
-  base::AutoReset<bool> reset(&is_pointer_down_from_activate_, true);
-  instant_controller()->FocusedOverlayContents();
-}
-
-void InstantOverlay::OnMouseDown() {
-  is_pointer_down_from_activate_ = true;
-}
-
-void InstantOverlay::OnMouseUp() {
-  if (is_pointer_down_from_activate_) {
-    is_pointer_down_from_activate_ = false;
-    instant_controller()->CommitIfPossible(INSTANT_COMMIT_FOCUS_LOST);
-  }
-}
-
-content::WebContents* InstantOverlay::OpenURLFromTab(
-    content::WebContents* source,
-    const content::OpenURLParams& params) {
-  if (!supports_instant()) {
-    // If the page doesn't yet support Instant, it hasn't fully loaded.
-    // This is a redirect that we should allow. http://crbug.com/177948
-    content::NavigationController::LoadURLParams load_params(params.url);
-    load_params.transition_type = params.transition;
-    load_params.referrer = params.referrer;
-    load_params.extra_headers = params.extra_headers;
-    load_params.is_renderer_initiated = params.is_renderer_initiated;
-    load_params.transferred_global_request_id =
-        params.transferred_global_request_id;
-    load_params.is_cross_site_redirect = params.is_cross_site_redirect;
-
-    contents()->GetController().LoadURLWithParams(load_params);
-    return contents();
-  }
-
-  // We will allow the navigate to continue if we are able to commit the
-  // overlay.
-  //
-  // First, cache the overlay contents since committing it will cause the
-  // contents to be released (and be set to NULL).
-  content::WebContents* overlay = contents();
-  if (instant_controller()->CommitIfPossible(INSTANT_COMMIT_NAVIGATED)) {
-    // If the commit was successful, the overlay's delegate should be the tab
-    // strip, which will be able to handle the navigation.
-    DCHECK_NE(&loader_, overlay->GetDelegate());
-    return overlay->GetDelegate()->OpenURLFromTab(source, params);
-  }
-  return NULL;
-}
-
-void InstantOverlay::LoadCompletedMainFrame() {
-  instant_controller()->OverlayLoadCompletedMainFrame();
-}
-
-void InstantOverlay::HandleStalePage() {
-  is_stale_ = true;
-  instant_controller()->ReloadOverlayIfStale();
-}
diff --git a/chrome/browser/ui/search/instant_overlay.h b/chrome/browser/ui/search/instant_overlay.h
deleted file mode 100644
index beea995..0000000
--- a/chrome/browser/ui/search/instant_overlay.h
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_SEARCH_INSTANT_OVERLAY_H_
-#define CHROME_BROWSER_UI_SEARCH_INSTANT_OVERLAY_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/gtest_prod_util.h"
-#include "base/memory/scoped_ptr.h"
-#include "chrome/browser/history/history_types.h"
-#include "chrome/browser/ui/search/instant_controller.h"
-#include "chrome/browser/ui/search/instant_loader.h"
-#include "chrome/browser/ui/search/instant_page.h"
-
-class Profile;
-
-namespace content {
-class WebContents;
-}
-
-// InstantOverlay is used to communicate with an overlay WebContents that it
-// owns and loads the "Instant URL" into. This overlay can appear and disappear
-// at will as the user types in the omnibox.
-class InstantOverlay : public InstantPage,
-                       public InstantLoader::Delegate {
- public:
-  // Returns the InstantOverlay for |contents| if it's used for Instant.
-  static InstantOverlay* FromWebContents(const content::WebContents* contents);
-
-  InstantOverlay(InstantController* controller,
-                 const std::string& instant_url);
-  virtual ~InstantOverlay();
-
-  // Creates a new WebContents and loads |instant_url_| into it. Uses
-  // |active_tab|, if non-NULL, to initialize the size of the WebContents.
-  void InitContents(Profile* profile,
-                    const content::WebContents* active_tab);
-
-  // Releases the overlay WebContents. This should be called when the overlay
-  // is committed.
-  scoped_ptr<content::WebContents> ReleaseContents();
-
-  // Returns whether the underlying contents is stale (i.e. was loaded too long
-  // ago).
-  bool is_stale() const { return is_stale_; }
-
-  // Returns true if the mouse or a touch pointer is down due to activating the
-  // overlay contents.
-  bool is_pointer_down_from_activate() const {
-    return is_pointer_down_from_activate_;
-  }
-
-  // Returns info about the last navigation by the Instant page. If the page
-  // hasn't navigated since the last Update(), the URL is empty.
-  const history::HistoryAddPageArgs& last_navigation() const {
-    return last_navigation_;
-  }
-
-  // Called by the history tab helper with information that it would have added
-  // to the history service had this WebContents not been used for Instant.
-  void DidNavigate(const history::HistoryAddPageArgs& add_page_args);
-
-  // Overridden from InstantPage:
-  virtual void Update(const string16& text,
-                      size_t selection_start,
-                      size_t selection_end,
-                      bool verbatim) OVERRIDE;
-
- private:
-  FRIEND_TEST_ALL_PREFIXES(InstantTest, InstantOverlayRefresh);
-  FRIEND_TEST_ALL_PREFIXES(InstantTest, InstantOverlayRefreshDifferentOrder);
-
-  // Helper to access delegate() as an InstantController object.
-  InstantController* instant_controller() const {
-    return static_cast<InstantController*>(delegate());
-  }
-
-  // Overridden from InstantPage:
-  virtual bool ShouldProcessRenderViewCreated() OVERRIDE;
-  virtual bool ShouldProcessRenderViewGone() OVERRIDE;
-  virtual bool ShouldProcessAboutToNavigateMainFrame() OVERRIDE;
-  virtual bool ShouldProcessSetSuggestions() OVERRIDE;
-  virtual bool ShouldProcessShowInstantOverlay() OVERRIDE;
-  virtual bool ShouldProcessNavigateToURL() OVERRIDE;
-
-  // Overriden from InstantLoader::Delegate:
-  virtual void OnSwappedContents() OVERRIDE;
-  virtual void OnFocus() OVERRIDE;
-  virtual void OnMouseDown() OVERRIDE;
-  virtual void OnMouseUp() OVERRIDE;
-  virtual content::WebContents* OpenURLFromTab(
-      content::WebContents* source,
-      const content::OpenURLParams& params) OVERRIDE;
-  virtual void LoadCompletedMainFrame() OVERRIDE;
-
-  // Called when the underlying page becomes stale.
-  void HandleStalePage();
-
-  InstantLoader loader_;
-  bool is_stale_;
-  bool is_pointer_down_from_activate_;
-  history::HistoryAddPageArgs last_navigation_;
-
-  DISALLOW_COPY_AND_ASSIGN(InstantOverlay);
-};
-
-#endif  // CHROME_BROWSER_UI_SEARCH_INSTANT_OVERLAY_H_
diff --git a/chrome/browser/ui/search/instant_overlay_controller.cc b/chrome/browser/ui/search/instant_overlay_controller.cc
index 547ccab..64fda78 100644
--- a/chrome/browser/ui/search/instant_overlay_controller.cc
+++ b/chrome/browser/ui/search/instant_overlay_controller.cc
@@ -9,11 +9,7 @@
 
 InstantOverlayController::InstantOverlayController(Browser* browser)
     : browser_(browser) {
-  if (browser_->instant_controller())
-    browser_->instant_controller()->instant()->model()->AddObserver(this);
 }
 
 InstantOverlayController::~InstantOverlayController() {
-  if (browser_->instant_controller())
-    browser_->instant_controller()->instant()->model()->RemoveObserver(this);
 }
diff --git a/chrome/browser/ui/search/instant_overlay_model.cc b/chrome/browser/ui/search/instant_overlay_model.cc
index 09a668b..bc6213b 100644
--- a/chrome/browser/ui/search/instant_overlay_model.cc
+++ b/chrome/browser/ui/search/instant_overlay_model.cc
@@ -50,9 +50,6 @@
 }
 
 content::WebContents* InstantOverlayModel::GetOverlayContents() const {
-  // |controller_| maybe NULL durning tests.
-  if (controller_)
-    return controller_->GetOverlayContents();
   return overlay_contents_;
 }
 
diff --git a/chrome/browser/ui/search/instant_page.cc b/chrome/browser/ui/search/instant_page.cc
index 356ecd0..121300a 100644
--- a/chrome/browser/ui/search/instant_page.cc
+++ b/chrome/browser/ui/search/instant_page.cc
@@ -4,7 +4,11 @@
 
 #include "chrome/browser/ui/search/instant_page.h"
 
+#include "apps/app_launcher.h"
 #include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/search/search.h"
+#include "chrome/browser/ui/search/search_model.h"
+#include "chrome/browser/ui/search/search_tab_helper.h"
 #include "chrome/common/render_messages.h"
 #include "chrome/common/url_constants.h"
 #include "content/public/browser/navigation_controller.h"
@@ -19,10 +23,13 @@
 }
 
 InstantPage::~InstantPage() {
+  if (contents())
+    SearchTabHelper::FromWebContents(contents())->model()->RemoveObserver(this);
 }
 
 bool InstantPage::supports_instant() const {
-  return supports_instant_;
+  return contents() ?
+      SearchTabHelper::FromWebContents(contents())->SupportsInstant() : false;
 }
 
 const std::string& InstantPage::instant_url() const {
@@ -35,137 +42,53 @@
        contents()->GetURL() == GURL(chrome::kChromeSearchLocalGoogleNtpUrl));
 }
 
-void InstantPage::Update(const string16& text,
-                         size_t selection_start,
-                         size_t selection_end,
-                         bool verbatim) {
-  Send(new ChromeViewMsg_SearchBoxChange(routing_id(), text, verbatim,
-                                         selection_start, selection_end));
-}
-
-void InstantPage::Submit(const string16& text) {
-  Send(new ChromeViewMsg_SearchBoxSubmit(routing_id(), text));
-}
-
-void InstantPage::Cancel(const string16& text) {
-  Send(new ChromeViewMsg_SearchBoxCancel(routing_id(), text));
-}
-
-void InstantPage::SetPopupBounds(const gfx::Rect& bounds) {
-  Send(new ChromeViewMsg_SearchBoxPopupResize(routing_id(), bounds));
-}
-
-void InstantPage::SetOmniboxBounds(const gfx::Rect& bounds) {
-  Send(new ChromeViewMsg_SearchBoxMarginChange(
-      routing_id(), bounds.x(), bounds.width()));
-}
-
 void InstantPage::InitializeFonts() {
 #if defined(OS_MACOSX)
   // This value should be kept in sync with OmniboxViewMac::GetFieldFont.
-  const gfx::Font omnibox_font("Helvetica Neue", 16);
+  const gfx::Font& omnibox_font =
+      ui::ResourceBundle::GetSharedInstance().GetFont(
+          ui::ResourceBundle::MediumFont).DeriveFont(1);
 #else
   const gfx::Font& omnibox_font =
       ui::ResourceBundle::GetSharedInstance().GetFont(
           ui::ResourceBundle::MediumFont);
 #endif
-  string16 omnibox_font_name = UTF8ToUTF16(omnibox_font.GetFontName());
-  size_t omnibox_font_size = omnibox_font.GetFontSize();
-  Send(new ChromeViewMsg_SearchBoxFontInformation(
-      routing_id(), omnibox_font_name, omnibox_font_size));
+  sender()->SetFontInformation(UTF8ToUTF16(omnibox_font.GetFontName()),
+                               omnibox_font.GetFontSize());
 }
 
-void InstantPage::DetermineIfPageSupportsInstant() {
-  if (IsLocal()) {
-    // Local pages always support Instant. That's why we keep them around.
-    int page_id = contents()->GetController().GetActiveEntry()->GetPageID();
-    OnInstantSupportDetermined(page_id, true);
-  } else {
-    Send(new ChromeViewMsg_DetermineIfPageSupportsInstant(routing_id()));
-  }
+void InstantPage::InitializePromos() {
+  sender()->SetPromoInformation(apps::IsAppLauncherEnabled());
 }
 
-void InstantPage::SendAutocompleteResults(
-    const std::vector<InstantAutocompleteResult>& results) {
-  Send(new ChromeViewMsg_SearchBoxAutocompleteResults(routing_id(), results));
-}
-
-void InstantPage::UpOrDownKeyPressed(int count) {
-  Send(new ChromeViewMsg_SearchBoxUpOrDownKeyPressed(routing_id(), count));
-}
-
-void InstantPage::EscKeyPressed() {
-  Send(new ChromeViewMsg_SearchBoxEscKeyPressed(routing_id()));
-}
-
-void InstantPage::CancelSelection(const string16& user_text,
-                                  size_t selection_start,
-                                  size_t selection_end,
-                                  bool verbatim) {
-  Send(new ChromeViewMsg_SearchBoxCancelSelection(
-      routing_id(), user_text, verbatim, selection_start, selection_end));
-}
-
-void InstantPage::SendThemeBackgroundInfo(
-    const ThemeBackgroundInfo& theme_info) {
-  Send(new ChromeViewMsg_SearchBoxThemeChanged(routing_id(), theme_info));
-}
-
-void InstantPage::SetDisplayInstantResults(bool display_instant_results) {
-  Send(new ChromeViewMsg_SearchBoxSetDisplayInstantResults(
-      routing_id(), display_instant_results));
-}
-
-void InstantPage::FocusChanged(OmniboxFocusState state,
-                               OmniboxFocusChangeReason reason) {
-  Send(new ChromeViewMsg_SearchBoxFocusChanged(routing_id(), state, reason));
-}
-
-void InstantPage::SetInputInProgress(bool input_in_progress) {
-  Send(new ChromeViewMsg_SearchBoxSetInputInProgress(
-      routing_id(), input_in_progress));
-}
-
-void InstantPage::SendMostVisitedItems(
-    const std::vector<InstantMostVisitedItem>& items) {
-  Send(new ChromeViewMsg_SearchBoxMostVisitedItemsChanged(routing_id(), items));
-}
-
-void InstantPage::ToggleVoiceSearch() {
-  Send(new ChromeViewMsg_SearchBoxToggleVoiceSearch(routing_id()));
-}
-
-InstantPage::InstantPage(Delegate* delegate, const std::string& instant_url)
+InstantPage::InstantPage(Delegate* delegate, const std::string& instant_url,
+                         bool is_incognito)
     : delegate_(delegate),
+      ipc_sender_(InstantIPCSender::Create(is_incognito)),
       instant_url_(instant_url),
-      supports_instant_(false),
-      instant_support_determined_(false) {
+      is_incognito_(is_incognito) {
 }
 
-void InstantPage::SetContents(content::WebContents* contents) {
-  Observe(contents);
-}
+void InstantPage::SetContents(content::WebContents* web_contents) {
+  ClearContents();
 
-bool InstantPage::ShouldProcessRenderViewCreated() {
-  return false;
-}
+  if (!web_contents)
+    return;
 
-bool InstantPage::ShouldProcessRenderViewGone() {
-  return false;
+  sender()->SetContents(web_contents);
+  Observe(web_contents);
+  SearchModel* model = SearchTabHelper::FromWebContents(contents())->model();
+  model->AddObserver(this);
+
+  // Already know whether the page supports instant.
+  if (model->instant_support() != INSTANT_SUPPORT_UNKNOWN)
+    InstantSupportDetermined(model->instant_support() == INSTANT_SUPPORT_YES);
 }
 
 bool InstantPage::ShouldProcessAboutToNavigateMainFrame() {
   return false;
 }
 
-bool InstantPage::ShouldProcessSetSuggestions() {
-  return false;
-}
-
-bool InstantPage::ShouldProcessShowInstantOverlay() {
-  return false;
-}
-
 bool InstantPage::ShouldProcessFocusOmnibox() {
   return false;
 }
@@ -186,28 +109,12 @@
   return false;
 }
 
-void InstantPage::RenderViewCreated(content::RenderViewHost* render_view_host) {
-  if (ShouldProcessRenderViewCreated())
-    delegate_->InstantPageRenderViewCreated(contents());
-}
-
-void InstantPage::DidFinishLoad(
-    int64 /* frame_id */,
-    const GURL& /* validated_url */,
-    bool is_main_frame,
-    content::RenderViewHost* /* render_view_host */) {
-  if (is_main_frame && !supports_instant_)
-    DetermineIfPageSupportsInstant();
-}
-
 bool InstantPage::OnMessageReceived(const IPC::Message& message) {
+  if (is_incognito_)
+    return false;
+
   bool handled = true;
   IPC_BEGIN_MESSAGE_MAP(InstantPage, message)
-    IPC_MESSAGE_HANDLER(ChromeViewHostMsg_SetSuggestions, OnSetSuggestions)
-    IPC_MESSAGE_HANDLER(ChromeViewHostMsg_InstantSupportDetermined,
-                        OnInstantSupportDetermined)
-    IPC_MESSAGE_HANDLER(ChromeViewHostMsg_ShowInstantOverlay,
-                        OnShowInstantOverlay)
     IPC_MESSAGE_HANDLER(ChromeViewHostMsg_FocusOmnibox, OnFocusOmnibox)
     IPC_MESSAGE_HANDLER(ChromeViewHostMsg_SearchBoxNavigate,
                         OnSearchBoxNavigate);
@@ -222,11 +129,6 @@
   return handled;
 }
 
-void InstantPage::RenderViewGone(base::TerminationStatus /* status */) {
-  if (ShouldProcessRenderViewGone())
-    delegate_->InstantPageRenderViewGone(contents());
-}
-
 void InstantPage::DidCommitProvisionalLoadForFrame(
     int64 /* frame_id */,
     bool is_main_frame,
@@ -258,54 +160,25 @@
     delegate_->InstantPageLoadFailed(contents());
 }
 
-void InstantPage::OnSetSuggestions(
-    int page_id,
-    const std::vector<InstantSuggestion>& suggestions) {
-  if (!contents()->IsActiveEntry(page_id))
-    return;
-
-  OnInstantSupportDetermined(page_id, true);
-  if (!ShouldProcessSetSuggestions())
-    return;
-
-  delegate_->SetSuggestions(contents(), suggestions);
+void InstantPage::ModelChanged(const SearchModel::State& old_state,
+                               const SearchModel::State& new_state) {
+  if (old_state.instant_support != new_state.instant_support)
+    InstantSupportDetermined(new_state.instant_support == INSTANT_SUPPORT_YES);
 }
 
-void InstantPage::OnInstantSupportDetermined(int page_id,
-                                             bool supports_instant) {
-  if (!contents()->IsActiveEntry(page_id) || supports_instant_) {
-    // Nothing to do if the page already supports Instant.
-    return;
-  }
-
-  instant_support_determined_ = true;
-  supports_instant_ = supports_instant;
+void InstantPage::InstantSupportDetermined(bool supports_instant) {
   delegate_->InstantSupportDetermined(contents(), supports_instant);
 
   // If the page doesn't support Instant, stop listening to it.
   if (!supports_instant)
-    Observe(NULL);
-}
-
-void InstantPage::OnShowInstantOverlay(int page_id,
-                                       int height,
-                                       InstantSizeUnits units) {
-  if (!contents()->IsActiveEntry(page_id))
-    return;
-
-  OnInstantSupportDetermined(page_id, true);
-  delegate_->LogDropdownShown();
-  if (!ShouldProcessShowInstantOverlay())
-    return;
-
-  delegate_->ShowInstantOverlay(contents(), height, units);
+    ClearContents();
 }
 
 void InstantPage::OnFocusOmnibox(int page_id, OmniboxFocusState state) {
   if (!contents()->IsActiveEntry(page_id))
     return;
 
-  OnInstantSupportDetermined(page_id, true);
+  SearchTabHelper::FromWebContents(contents())->InstantSupportChanged(true);
   if (!ShouldProcessFocusOmnibox())
     return;
 
@@ -320,7 +193,7 @@
   if (!contents()->IsActiveEntry(page_id))
     return;
 
-  OnInstantSupportDetermined(page_id, true);
+  SearchTabHelper::FromWebContents(contents())->InstantSupportChanged(true);
   if (!ShouldProcessNavigateToURL())
     return;
 
@@ -332,7 +205,7 @@
   if (!contents()->IsActiveEntry(page_id))
     return;
 
-  OnInstantSupportDetermined(page_id, true);
+  SearchTabHelper::FromWebContents(contents())->InstantSupportChanged(true);
   if (!ShouldProcessDeleteMostVisitedItem())
     return;
 
@@ -343,7 +216,7 @@
   if (!contents()->IsActiveEntry(page_id))
     return;
 
-  OnInstantSupportDetermined(page_id, true);
+  SearchTabHelper::FromWebContents(contents())->InstantSupportChanged(true);
   if (!ShouldProcessUndoMostVisitedDeletion())
     return;
 
@@ -354,9 +227,17 @@
   if (!contents()->IsActiveEntry(page_id))
     return;
 
-  OnInstantSupportDetermined(page_id, true);
+  SearchTabHelper::FromWebContents(contents())->InstantSupportChanged(true);
   if (!ShouldProcessUndoAllMostVisitedDeletions())
     return;
 
   delegate_->UndoAllMostVisitedDeletions();
 }
+
+void InstantPage::ClearContents() {
+  if (contents())
+    SearchTabHelper::FromWebContents(contents())->model()->RemoveObserver(this);
+
+  sender()->SetContents(NULL);
+  Observe(NULL);
+}
diff --git a/chrome/browser/ui/search/instant_page.h b/chrome/browser/ui/search/instant_page.h
index 341defc..bf60ccb 100644
--- a/chrome/browser/ui/search/instant_page.h
+++ b/chrome/browser/ui/search/instant_page.h
@@ -10,7 +10,10 @@
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "base/gtest_prod_util.h"
+#include "base/memory/scoped_ptr.h"
 #include "base/strings/string16.h"
+#include "chrome/browser/ui/search/instant_ipc_sender.h"
+#include "chrome/browser/ui/search/search_model_observer.h"
 #include "chrome/common/instant_types.h"
 #include "chrome/common/omnibox_focus_state.h"
 #include "content/public/browser/web_contents_observer.h"
@@ -30,9 +33,10 @@
 
 // InstantPage is used to exchange messages with a page that implements the
 // Instant/Embedded Search API (http://dev.chromium.org/embeddedsearch).
-// InstantPage is not used directly but via one of its derived classes:
-// InstantOverlay, InstantNTP and InstantTab.
-class InstantPage : public content::WebContentsObserver {
+// InstantPage is not used directly but via one of its derived classes,
+// InstantNTP and InstantTab.
+class InstantPage : public content::WebContentsObserver,
+                    public SearchModelObserver {
  public:
   // InstantPage calls its delegate in response to messages received from the
   // page. Each method is called with the |contents| corresponding to the page
@@ -57,22 +61,6 @@
         const content::WebContents* contents,
         const GURL& url) = 0;
 
-    // Called when the page has suggestions. Usually in response to Update(),
-    // SendAutocompleteResults() or UpOrDownKeyPressed().
-    virtual void SetSuggestions(
-        const content::WebContents* contents,
-        const std::vector<InstantSuggestion>& suggestions) = 0;
-
-    // Called when the page wants to be shown. Usually in response to Update()
-    // or SendAutocompleteResults().
-    virtual void ShowInstantOverlay(const content::WebContents* contents,
-                                    int height,
-                                    InstantSizeUnits units) = 0;
-
-    // Called when the page shows suggestions for logging purposes, regardless
-    // of whether the page is processing the call.
-    virtual void LogDropdownShown() = 0;
-
     // Called when the page wants the omnibox to be focused. |state| specifies
     // the omnibox focus state.
     virtual void FocusOmnibox(const content::WebContents* contents,
@@ -109,6 +97,9 @@
   // The WebContents corresponding to the page we're talking to. May be NULL.
   content::WebContents* contents() const { return web_contents(); }
 
+  // Used to send IPC messages to the page.
+  InstantIPCSender* sender() const { return ipc_sender_.get(); }
+
   // Returns the Instant URL that was loaded for this page. Returns the empty
   // string if no URL was explicitly loaded as is the case for InstantTab.
   virtual const std::string& instant_url() const;
@@ -119,94 +110,21 @@
   // support suddenly).
   virtual bool supports_instant() const;
 
-  // True if Instant support has been tested and determined for this page at
-  // least once. Note that Instant support may change in the future.
-  bool instant_support_determined() const {
-    return instant_support_determined_;
-  }
-
   // Returns true if the page is the local NTP (i.e. its URL is
   // chrome::kChromeSearchLocalNTPURL).
   virtual bool IsLocal() const;
 
-  // Tells the page that the user typed |text| into the omnibox. If |verbatim|
-  // is false, the page predicts the query the user means to type and fetches
-  // results for the prediction. If |verbatim| is true, |text| is taken as the
-  // exact query (no prediction is made). |selection_start| and |selection_end|
-  // mark the inline autocompleted portion (i.e., blue highlighted text). The
-  // omnibox caret (cursor) is at |selection_end|.
-  virtual void Update(const string16& text,
-                      size_t selection_start,
-                      size_t selection_end,
-                      bool verbatim);
-
-  // Tells the page that the user pressed Enter in the omnibox.
-  void Submit(const string16& text);
-
-  // Tells the page that the user clicked on it. Nothing is being cancelled; the
-  // poor choice of name merely reflects the IPC of the same (poor) name.
-  void Cancel(const string16& text);
-
-  // Tells the page the bounds of the omnibox dropdown (in screen coordinates).
-  // This is used by the page to offset the results to avoid them being covered
-  // by the omnibox dropdown.
-  void SetPopupBounds(const gfx::Rect& bounds);
-
-  // Tells the page the bounds of the omnibox (in screen coordinates). This is
-  // used by the page to align text or assets properly with the omnibox.
-  void SetOmniboxBounds(const gfx::Rect& bounds);
-
-  // Tells the page about the font information.
   void InitializeFonts();
 
-  // Tells the renderer to determine if the page supports the Instant API, which
-  // results in a call to InstantSupportDetermined() when the reply is received.
-  void DetermineIfPageSupportsInstant();
-
-  // Tells the page about the available autocomplete results.
-  void SendAutocompleteResults(
-      const std::vector<InstantAutocompleteResult>& results);
-
-  // Tells the page that the user pressed Up or Down in the omnibox. |count| is
-  // a repeat count, negative for moving up, positive for moving down.
-  void UpOrDownKeyPressed(int count);
-
-  // Tells the page that the user pressed Esc key in the omnibox.
-  void EscKeyPressed();
-
-  // Tells the page that the user pressed Esc in the omnibox after having
-  // arrowed down in the suggestions. The page should reset the selection to
-  // the first suggestion. Arguments are the same as those for Update().
-  void CancelSelection(const string16& user_text,
-                       size_t selection_start,
-                       size_t selection_end,
-                       bool verbatim);
-
-  // Tells the page about the current theme background.
-  void SendThemeBackgroundInfo(const ThemeBackgroundInfo& theme_info);
-
-  // Tells the page whether it is allowed to display Instant results.
-  void SetDisplayInstantResults(bool display_instant_results);
-
-  // Tells the page that the omnibox focus has changed.
-  void FocusChanged(OmniboxFocusState state, OmniboxFocusChangeReason reason);
-
-  // Tells the page that user input started or stopped.
-  void SetInputInProgress(bool input_in_progress);
-
-  // Tells the page about new Most Visited data.
-  void SendMostVisitedItems(
-      const std::vector<InstantMostVisitedItem>& items);
-
-  // Tells the page to toggle voice search.
-  void ToggleVoiceSearch();
+  void InitializePromos();
 
  protected:
-  InstantPage(Delegate* delegate, const std::string& instant_url);
+  InstantPage(Delegate* delegate, const std::string& instant_url,
+              bool is_incognito);
 
-  // Sets |contents| as the page to communicate with. |contents| may be NULL,
-  // which effectively stops all communication.
-  void SetContents(content::WebContents* contents);
+  // Sets |web_contents| as the page to communicate with. |web_contents| may be
+  // NULL, which effectively stops all communication.
+  void SetContents(content::WebContents* web_contents);
 
   Delegate* delegate() const { return delegate_; }
 
@@ -214,11 +132,7 @@
   // page. By default, all messages are handled, but any derived classes may
   // choose to ignore some or all of the received messages by overriding these
   // methods.
-  virtual bool ShouldProcessRenderViewCreated();
-  virtual bool ShouldProcessRenderViewGone();
   virtual bool ShouldProcessAboutToNavigateMainFrame();
-  virtual bool ShouldProcessSetSuggestions();
-  virtual bool ShouldProcessShowInstantOverlay();
   virtual bool ShouldProcessFocusOmnibox();
   virtual bool ShouldProcessNavigateToURL();
   virtual bool ShouldProcessDeleteMostVisitedItem();
@@ -236,17 +150,11 @@
                            IgnoreMessageIfThePageIsNotActive);
   FRIEND_TEST_ALL_PREFIXES(InstantPageTest,
                            IgnoreMessageReceivedFromThePage);
+  FRIEND_TEST_ALL_PREFIXES(InstantPageTest,
+                           IgnoreMessageReceivedFromIncognitoPage);
 
   // Overridden from content::WebContentsObserver:
-  virtual void RenderViewCreated(
-      content::RenderViewHost* render_view_host) OVERRIDE;
-  virtual void DidFinishLoad(
-      int64 frame_id,
-      const GURL& validated_url,
-      bool is_main_frame,
-      content::RenderViewHost* render_view_host) OVERRIDE;
   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
-  virtual void RenderViewGone(base::TerminationStatus status) OVERRIDE;
   virtual void DidCommitProvisionalLoadForFrame(
       int64 frame_id,
       bool is_main_frame,
@@ -264,12 +172,13 @@
       const string16& error_description,
       content::RenderViewHost* render_view_host) OVERRIDE;
 
-  void OnSetSuggestions(int page_id,
-                        const std::vector<InstantSuggestion>& suggestions);
-  void OnInstantSupportDetermined(int page_id, bool supports_instant);
-  void OnShowInstantOverlay(int page_id,
-                            int height,
-                            InstantSizeUnits units);
+  // Overridden from SearchModelObserver:
+  virtual void ModelChanged(const SearchModel::State& old_state,
+                            const SearchModel::State& new_state) OVERRIDE;
+
+  // Update the status of Instant support.
+  void InstantSupportDetermined(bool supports_instant);
+
   void OnFocusOmnibox(int page_id, OmniboxFocusState state);
   void OnSearchBoxNavigate(int page_id,
                            const GURL& url,
@@ -280,10 +189,12 @@
   void OnUndoMostVisitedDeletion(int page_id, const GURL& url);
   void OnUndoAllMostVisitedDeletions(int page_id);
 
+  void ClearContents();
+
   Delegate* const delegate_;
+  scoped_ptr<InstantIPCSender> ipc_sender_;
   const std::string instant_url_;
-  bool supports_instant_;
-  bool instant_support_determined_;
+  const bool is_incognito_;
 
   DISALLOW_COPY_AND_ASSIGN(InstantPage);
 };
diff --git a/chrome/browser/ui/search/instant_page_unittest.cc b/chrome/browser/ui/search/instant_page_unittest.cc
index c9830ee..a73ffc9 100644
--- a/chrome/browser/ui/search/instant_page_unittest.cc
+++ b/chrome/browser/ui/search/instant_page_unittest.cc
@@ -4,7 +4,10 @@
 
 #include "chrome/browser/ui/search/instant_page.h"
 
+#include "base/command_line.h"
 #include "base/memory/scoped_ptr.h"
+#include "chrome/browser/ui/search/search_tab_helper.h"
+#include "chrome/common/chrome_switches.h"
 #include "chrome/common/render_messages.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
@@ -34,14 +37,6 @@
   MOCK_METHOD2(InstantPageAboutToNavigateMainFrame,
                void(const content::WebContents* contents,
                     const GURL& url));
-  MOCK_METHOD2(SetSuggestions,
-               void(const content::WebContents* contents,
-                    const std::vector<InstantSuggestion>& suggestions));
-  MOCK_METHOD3(ShowInstantOverlay,
-               void(const content::WebContents* contents,
-                    int height,
-                    InstantSizeUnits units));
-  MOCK_METHOD0(LogDropdownShown, void());
   MOCK_METHOD2(FocusOmnibox,
                void(const content::WebContents* contents,
                     OmniboxFocusState state));
@@ -59,7 +54,8 @@
 
 class FakePage : public InstantPage {
  public:
-  FakePage(Delegate* delegate, const std::string& instant_url);
+  FakePage(Delegate* delegate, const std::string& instant_url,
+           bool is_incognito);
   virtual ~FakePage();
 
   // InstantPage overrride.
@@ -78,8 +74,9 @@
   DISALLOW_COPY_AND_ASSIGN(FakePage);
 };
 
-FakePage::FakePage(Delegate* delegate, const std::string& instant_url)
-    : InstantPage(delegate, instant_url),
+FakePage::FakePage(Delegate* delegate, const std::string& instant_url,
+                   bool is_incognito)
+    : InstantPage(delegate, instant_url, is_incognito),
       should_handle_messages_(true) {
 }
 
@@ -106,12 +103,26 @@
 
 class InstantPageTest : public ChromeRenderViewHostTestHarness {
  public:
+  virtual void SetUp() OVERRIDE;
+
+  bool MessageWasSent(uint32 id) {
+    return process()->sink().GetFirstMessageMatching(id) != NULL;
+  }
+
   scoped_ptr<FakePage> page;
   FakePageDelegate delegate;
 };
 
+void InstantPageTest::SetUp() {
+  CommandLine::ForCurrentProcess()->AppendSwitch(
+      switches::kEnableInstantExtendedAPI);
+  ChromeRenderViewHostTestHarness::SetUp();
+  SearchTabHelper::CreateForWebContents(web_contents());
+}
+
 TEST_F(InstantPageTest, IsLocal) {
-  page.reset(new FakePage(&delegate, ""));
+  page.reset(new FakePage(&delegate, "", false));
+  EXPECT_FALSE(page->supports_instant());
   EXPECT_FALSE(page->IsLocal());
   page->SetContents(web_contents());
   NavigateAndCommit(GURL(chrome::kChromeSearchLocalNtpUrl));
@@ -123,25 +134,27 @@
 }
 
 TEST_F(InstantPageTest, DetermineIfPageSupportsInstant_Local) {
-  page.reset(new FakePage(&delegate, ""));
+  page.reset(new FakePage(&delegate, "", false));
   EXPECT_FALSE(page->supports_instant());
   page->SetContents(web_contents());
   NavigateAndCommit(GURL(chrome::kChromeSearchLocalNtpUrl));
   EXPECT_TRUE(page->IsLocal());
   EXPECT_CALL(delegate, InstantSupportDetermined(web_contents(), true))
       .Times(1);
-  page->DetermineIfPageSupportsInstant();
+  SearchTabHelper::FromWebContents(web_contents())->
+      DetermineIfPageSupportsInstant();
   EXPECT_TRUE(page->supports_instant());
 }
 
 TEST_F(InstantPageTest, DetermineIfPageSupportsInstant_NonLocal) {
-  page.reset(new FakePage(&delegate, ""));
+  page.reset(new FakePage(&delegate, "", false));
   EXPECT_FALSE(page->supports_instant());
   page->SetContents(web_contents());
-  NavigateAndCommit(GURL("http://example.com/"));
+  NavigateAndCommit(GURL("chrome-search://foo/bar"));
   EXPECT_FALSE(page->IsLocal());
   process()->sink().ClearMessages();
-  page->DetermineIfPageSupportsInstant();
+  SearchTabHelper::FromWebContents(web_contents())->
+      DetermineIfPageSupportsInstant();
   const IPC::Message* message = process()->sink().GetFirstMessageMatching(
       ChromeViewMsg_DetermineIfPageSupportsInstant::ID);
   ASSERT_TRUE(message != NULL);
@@ -149,7 +162,7 @@
 }
 
 TEST_F(InstantPageTest, DispatchRequestToDeleteMostVisitedItem) {
-  page.reset(new FakePage(&delegate, ""));
+  page.reset(new FakePage(&delegate, "", false));
   page->SetContents(web_contents());
   NavigateAndCommit(GURL(chrome::kChromeSearchLocalNtpUrl));
   GURL item_url("www.foo.com");
@@ -161,7 +174,7 @@
 }
 
 TEST_F(InstantPageTest, DispatchRequestToUndoMostVisitedDeletion) {
-  page.reset(new FakePage(&delegate, ""));
+  page.reset(new FakePage(&delegate, "", false));
   page->SetContents(web_contents());
   NavigateAndCommit(GURL(chrome::kChromeSearchLocalNtpUrl));
   GURL item_url("www.foo.com");
@@ -173,7 +186,7 @@
 }
 
 TEST_F(InstantPageTest, DispatchRequestToUndoAllMostVisitedDeletions) {
-  page.reset(new FakePage(&delegate, ""));
+  page.reset(new FakePage(&delegate, "", false));
   page->SetContents(web_contents());
   NavigateAndCommit(GURL(chrome::kChromeSearchLocalNtpUrl));
   int page_id = web_contents()->GetController().GetActiveEntry()->GetPageID();
@@ -183,8 +196,33 @@
           rvh()->GetRoutingID(), page_id)));
 }
 
+TEST_F(InstantPageTest, IgnoreMessageReceivedFromIncognitoPage) {
+  page.reset(new FakePage(&delegate, "", true));
+  page->SetContents(web_contents());
+  NavigateAndCommit(GURL(chrome::kChromeSearchLocalNtpUrl));
+  GURL item_url("www.foo.com");
+  int page_id = web_contents()->GetController().GetActiveEntry()->GetPageID();
+
+  EXPECT_CALL(delegate, DeleteMostVisitedItem(item_url)).Times(0);
+  EXPECT_FALSE(page->OnMessageReceived(
+      ChromeViewHostMsg_SearchBoxDeleteMostVisitedItem(rvh()->GetRoutingID(),
+                                                       page_id,
+                                                       item_url)));
+
+  EXPECT_CALL(delegate, UndoMostVisitedDeletion(item_url)).Times(0);
+  EXPECT_FALSE(page->OnMessageReceived(
+      ChromeViewHostMsg_SearchBoxUndoMostVisitedDeletion(rvh()->GetRoutingID(),
+                                                         page_id,
+                                                         item_url)));
+
+  EXPECT_CALL(delegate, UndoAllMostVisitedDeletions()).Times(0);
+  EXPECT_FALSE(page->OnMessageReceived(
+      ChromeViewHostMsg_SearchBoxUndoAllMostVisitedDeletions(
+          rvh()->GetRoutingID(), page_id)));
+}
+
 TEST_F(InstantPageTest, IgnoreMessageIfThePageIsNotActive) {
-  page.reset(new FakePage(&delegate, ""));
+  page.reset(new FakePage(&delegate, "", false));
   page->SetContents(web_contents());
   NavigateAndCommit(GURL(chrome::kChromeSearchLocalNtpUrl));
   GURL item_url("www.foo.com");
@@ -209,7 +247,7 @@
 }
 
 TEST_F(InstantPageTest, IgnoreMessageReceivedFromThePage) {
-  page.reset(new FakePage(&delegate, ""));
+  page.reset(new FakePage(&delegate, "", false));
   page->SetContents(web_contents());
 
   // Ignore the messages received from the page.
@@ -233,3 +271,88 @@
       ChromeViewHostMsg_SearchBoxUndoAllMostVisitedDeletions(
           rvh()->GetRoutingID(), page_id)));
 }
+
+TEST_F(InstantPageTest, PageURLDoesntBelongToInstantRenderer) {
+  page.reset(new FakePage(&delegate, "", false));
+  EXPECT_FALSE(page->supports_instant());
+  NavigateAndCommit(GURL(chrome::kChromeSearchLocalNtpUrl));
+  page->SetContents(web_contents());
+
+  // Navigate to a page URL that doesn't belong to Instant renderer.
+  // SearchTabHelper::DeterminerIfPageSupportsInstant() should return
+  // immediately without dispatching any message to the renderer.
+  NavigateAndCommit(GURL("http://www.example.com"));
+  EXPECT_FALSE(page->IsLocal());
+  process()->sink().ClearMessages();
+  EXPECT_CALL(delegate, InstantSupportDetermined(web_contents(), false))
+      .Times(1);
+
+  SearchTabHelper::FromWebContents(web_contents())->
+      DetermineIfPageSupportsInstant();
+  const IPC::Message* message = process()->sink().GetFirstMessageMatching(
+      ChromeViewMsg_DetermineIfPageSupportsInstant::ID);
+  ASSERT_TRUE(message == NULL);
+  EXPECT_FALSE(page->supports_instant());
+}
+
+// Test to verify that ChromeViewMsg_DetermineIfPageSupportsInstant message
+// reply handler updates the instant support state in InstantPage.
+TEST_F(InstantPageTest, PageSupportsInstant) {
+  page.reset(new FakePage(&delegate, "", false));
+  EXPECT_FALSE(page->supports_instant());
+  page->SetContents(web_contents());
+  NavigateAndCommit(GURL("chrome-search://foo/bar"));
+  process()->sink().ClearMessages();
+  SearchTabHelper::FromWebContents(web_contents())->
+      DetermineIfPageSupportsInstant();
+  const IPC::Message* message = process()->sink().GetFirstMessageMatching(
+      ChromeViewMsg_DetermineIfPageSupportsInstant::ID);
+  ASSERT_TRUE(message != NULL);
+  EXPECT_EQ(web_contents()->GetRoutingID(), message->routing_id());
+
+  EXPECT_CALL(delegate, InstantSupportDetermined(web_contents(), true))
+      .Times(1);
+
+  // Assume the page supports instant. Invoke the message reply handler to make
+  // sure the InstantPage is notified about the instant support state.
+  const content::NavigationEntry* entry =
+      web_contents()->GetController().GetActiveEntry();
+  EXPECT_TRUE(entry);
+  SearchTabHelper::FromWebContents(web_contents())->
+      OnInstantSupportDetermined(entry->GetPageID(), true);
+  EXPECT_TRUE(page->supports_instant());
+}
+
+TEST_F(InstantPageTest, AppropriateMessagesSentToIncognitoPages) {
+  page.reset(new FakePage(&delegate, "", true));
+  page->SetContents(web_contents());
+  NavigateAndCommit(GURL(chrome::kChromeSearchLocalNtpUrl));
+  process()->sink().ClearMessages();
+
+  // Incognito pages should get these messages.
+  page->sender()->Submit(string16());
+  EXPECT_TRUE(MessageWasSent(ChromeViewMsg_SearchBoxSubmit::ID));
+  page->sender()->SetOmniboxBounds(gfx::Rect());
+  EXPECT_TRUE(MessageWasSent(ChromeViewMsg_SearchBoxMarginChange::ID));
+
+  // Incognito pages should not get any others.
+  page->sender()->SetFontInformation(string16(), 0);
+  EXPECT_FALSE(MessageWasSent(ChromeViewMsg_SearchBoxFontInformation::ID));
+
+  page->sender()->SendThemeBackgroundInfo(ThemeBackgroundInfo());
+  EXPECT_FALSE(MessageWasSent(ChromeViewMsg_SearchBoxThemeChanged::ID));
+
+  page->sender()->FocusChanged(
+      OMNIBOX_FOCUS_NONE, OMNIBOX_FOCUS_CHANGE_EXPLICIT);
+  EXPECT_FALSE(MessageWasSent(ChromeViewMsg_SearchBoxFocusChanged::ID));
+
+  page->sender()->SetInputInProgress(false);
+  EXPECT_FALSE(MessageWasSent(ChromeViewMsg_SearchBoxSetInputInProgress::ID));
+
+  page->sender()->SendMostVisitedItems(std::vector<InstantMostVisitedItem>());
+  EXPECT_FALSE(MessageWasSent(
+      ChromeViewMsg_SearchBoxMostVisitedItemsChanged::ID));
+
+  page->sender()->ToggleVoiceSearch();
+  EXPECT_FALSE(MessageWasSent(ChromeViewMsg_SearchBoxToggleVoiceSearch::ID));
+}
diff --git a/chrome/browser/ui/search/instant_tab.cc b/chrome/browser/ui/search/instant_tab.cc
index e1c5b2a..fcda092 100644
--- a/chrome/browser/ui/search/instant_tab.cc
+++ b/chrome/browser/ui/search/instant_tab.cc
@@ -5,8 +5,9 @@
 #include "chrome/browser/ui/search/instant_tab.h"
 #include "content/public/browser/web_contents.h"
 
-InstantTab::InstantTab(InstantPage::Delegate* delegate)
-    : InstantPage(delegate, "") {
+InstantTab::InstantTab(InstantPage::Delegate* delegate,
+                       bool is_incognito)
+    : InstantPage(delegate, "", is_incognito) {
 }
 
 InstantTab::~InstantTab() {
@@ -14,18 +15,12 @@
 
 void InstantTab::Init(content::WebContents* contents) {
   SetContents(contents);
-  if (!contents->IsWaitingForResponse())
-    DetermineIfPageSupportsInstant();
 }
 
 bool InstantTab::ShouldProcessAboutToNavigateMainFrame() {
   return true;
 }
 
-bool InstantTab::ShouldProcessSetSuggestions() {
-  return true;
-}
-
 bool InstantTab::ShouldProcessFocusOmnibox() {
   return true;
 }
diff --git a/chrome/browser/ui/search/instant_tab.h b/chrome/browser/ui/search/instant_tab.h
index 6951c58..d1cdb67 100644
--- a/chrome/browser/ui/search/instant_tab.h
+++ b/chrome/browser/ui/search/instant_tab.h
@@ -13,7 +13,7 @@
 // that supports the Instant API.
 class InstantTab : public InstantPage {
  public:
-  explicit InstantTab(InstantPage::Delegate* delegate);
+  InstantTab(InstantPage::Delegate* delegate, bool is_incognito);
   virtual ~InstantTab();
 
   // Start observing |contents| for messages. Sends a message to determine if
@@ -23,7 +23,6 @@
  private:
   // Overridden from InstantPage:
   virtual bool ShouldProcessAboutToNavigateMainFrame() OVERRIDE;
-  virtual bool ShouldProcessSetSuggestions() OVERRIDE;
   virtual bool ShouldProcessFocusOmnibox() OVERRIDE;
   virtual bool ShouldProcessNavigateToURL() OVERRIDE;
   virtual bool ShouldProcessDeleteMostVisitedItem() OVERRIDE;
diff --git a/chrome/browser/ui/search/instant_test_utils.cc b/chrome/browser/ui/search/instant_test_utils.cc
index 29b460a..1ccbd03 100644
--- a/chrome/browser/ui/search/instant_test_utils.cc
+++ b/chrome/browser/ui/search/instant_test_utils.cc
@@ -6,12 +6,12 @@
 
 #include "base/command_line.h"
 #include "base/prefs/pref_service.h"
+#include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search_engines/template_url_service.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/browser/ui/omnibox/omnibox_view.h"
 #include "chrome/browser/ui/search/instant_ntp.h"
-#include "chrome/browser/ui/search/instant_overlay.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
@@ -31,32 +31,6 @@
 
 }  // namespace
 
-// InstantTestModelObserver --------------------------------------------------
-
-InstantTestModelObserver::InstantTestModelObserver(
-    InstantOverlayModel* model,
-    SearchMode::Type expected_mode_type)
-    : model_(model),
-      expected_mode_type_(expected_mode_type),
-      observed_mode_type_(static_cast<SearchMode::Type>(-1)) {
-  model_->AddObserver(this);
-}
-
-InstantTestModelObserver::~InstantTestModelObserver() {
-  model_->RemoveObserver(this);
-}
-
-SearchMode::Type InstantTestModelObserver::WaitForExpectedOverlayState() {
-  run_loop_.Run();
-  return observed_mode_type_;
-}
-
-void InstantTestModelObserver::OverlayStateChanged(
-    const InstantOverlayModel& model) {
-  observed_mode_type_ = model.mode().mode;
-  run_loop_.Quit();
-}
-
 // InstantTestBase -----------------------------------------------------------
 
 void InstantTestBase::SetupInstant(Browser* browser) {
@@ -78,9 +52,7 @@
   service->Add(template_url);  // Takes ownership of |template_url|.
   service->SetDefaultSearchProvider(template_url);
 
-  // TODO(shishir): Fix this ugly hack.
-  instant()->SetInstantEnabled(false, true);
-  instant()->SetInstantEnabled(true, false);
+  instant()->ReloadStaleNTP();
 }
 
 void InstantTestBase::SetInstantURL(const std::string& url) {
@@ -101,13 +73,6 @@
   instant_url_ = instant_url;
 }
 
-void InstantTestBase::KillInstantRenderView() {
-  base::KillProcess(
-      instant()->GetOverlayContents()->GetRenderProcessHost()->GetHandle(),
-      content::RESULT_CODE_KILLED,
-      false);
-}
-
 void InstantTestBase::FocusOmnibox() {
   // If the omnibox already has focus, just notify Instant.
   if (omnibox()->model()->has_focus()) {
@@ -118,33 +83,13 @@
   }
 }
 
-void InstantTestBase::FocusOmniboxAndWaitForInstantOverlaySupport() {
-  content::WindowedNotificationObserver observer(
-      chrome::NOTIFICATION_INSTANT_OVERLAY_SUPPORT_DETERMINED,
-      content::NotificationService::AllSources());
-  FocusOmnibox();
-  if (!instant()->overlay() ||
-      !instant()->overlay()->instant_support_determined()) {
-    observer.Wait();
-  }
-}
-
-void InstantTestBase::FocusOmniboxAndWaitForInstantOverlayAndNTPSupport() {
+void InstantTestBase::FocusOmniboxAndWaitForInstantNTPSupport() {
   content::WindowedNotificationObserver ntp_observer(
       chrome::NOTIFICATION_INSTANT_NTP_SUPPORT_DETERMINED,
       content::NotificationService::AllSources());
-  content::WindowedNotificationObserver overlay_observer(
-      chrome::NOTIFICATION_INSTANT_OVERLAY_SUPPORT_DETERMINED,
-      content::NotificationService::AllSources());
   FocusOmnibox();
-  if (!instant()->ntp() ||
-      !instant()->ntp()->instant_support_determined()) {
+  if (!instant()->ntp() || !instant()->ntp()->supports_instant())
     ntp_observer.Wait();
-  }
-  if (!instant()->overlay() ||
-      !instant()->overlay()->instant_support_determined()) {
-    overlay_observer.Wait();
-  }
 }
 
 void InstantTestBase::SetOmniboxText(const std::string& text) {
@@ -152,36 +97,6 @@
   omnibox()->SetUserText(UTF8ToUTF16(text));
 }
 
-bool InstantTestBase::SetOmniboxTextAndWaitForOverlayToShow(
-    const std::string& text) {
-  // The order of events may be:
-  //   { hide, show } or just { show } depending on the order things
-  // flow in from GWS and Chrome's response to hiding the infobar and/or
-  // bookmark bar.  Note, the GWS response is relevant because of the
-  // Instant "MANUAL_*" tests.
-  InstantTestModelObserver first_observer(
-      instant()->model(), SearchMode::MODE_DEFAULT);
-  SetOmniboxText(text);
-
-  SearchMode::Type observed = first_observer.WaitForExpectedOverlayState();
-  if (observed == SearchMode::MODE_DEFAULT) {
-    InstantTestModelObserver second_observer(
-        instant()->model(), SearchMode::MODE_SEARCH_SUGGESTIONS);
-    observed = second_observer.WaitForExpectedOverlayState();
-  }
-  EXPECT_EQ(SearchMode::MODE_SEARCH_SUGGESTIONS, observed);
-  return observed == SearchMode::MODE_SEARCH_SUGGESTIONS;
-}
-
-void InstantTestBase::SetOmniboxTextAndWaitForSuggestion(
-    const std::string& text) {
-  content::WindowedNotificationObserver observer(
-      chrome::NOTIFICATION_INSTANT_SET_SUGGESTION,
-      content::NotificationService::AllSources());
-  SetOmniboxText(text);
-  observer.Wait();
-}
-
 void InstantTestBase::PressEnterAndWaitForNavigation() {
   content::WindowedNotificationObserver nav_observer(
       content::NOTIFICATION_NAV_ENTRY_COMMITTED,
@@ -212,7 +127,7 @@
 }
 
 bool InstantTestBase::ExecuteScript(const std::string& script) {
-  return content::ExecuteScript(instant()->GetOverlayContents(), script);
+  return content::ExecuteScript(instant()->GetNTPContents(), script);
 }
 
 bool InstantTestBase::CheckVisibilityIs(content::WebContents* contents,
@@ -232,6 +147,10 @@
   return omnibox()->model()->has_temporary_text_;
 }
 
+std::string InstantTestBase::GetOmniboxText() {
+  return UTF16ToUTF8(omnibox()->GetText());
+}
+
 bool InstantTestBase::LoadImage(content::RenderViewHost* rvh,
                                 const std::string& image,
                                 bool* loaded) {
diff --git a/chrome/browser/ui/search/instant_test_utils.h b/chrome/browser/ui/search/instant_test_utils.h
index 647b8cd..5072443 100644
--- a/chrome/browser/ui/search/instant_test_utils.h
+++ b/chrome/browser/ui/search/instant_test_utils.h
@@ -16,11 +16,11 @@
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/omnibox/location_bar.h"
 #include "chrome/browser/ui/search/instant_controller.h"
-#include "chrome/browser/ui/search/instant_overlay_model_observer.h"
 #include "chrome/common/search_types.h"
 #include "googleurl/src/gurl.h"
 #include "net/test/spawned_test_server/spawned_test_server.h"
 
+class BrowserInstantController;
 class InstantController;
 class InstantModel;
 class OmniboxView;
@@ -29,28 +29,6 @@
 class WebContents;
 };
 
-class InstantTestModelObserver : public InstantOverlayModelObserver {
- public:
-  InstantTestModelObserver(InstantOverlayModel* model,
-                           SearchMode::Type expected_mode_type);
-  virtual ~InstantTestModelObserver();
-
-  // Returns the observed mode type, may be different than the
-  // |expected_mode_type_| that was observed in OverlayStateChanged.
-  SearchMode::Type WaitForExpectedOverlayState();
-
-  // Overridden from InstantOverlayModelObserver:
-  virtual void OverlayStateChanged(const InstantOverlayModel& model) OVERRIDE;
-
- private:
-  InstantOverlayModel* const model_;
-  const SearchMode::Type expected_mode_type_;
-  SearchMode::Type observed_mode_type_;
-  base::RunLoop run_loop_;
-
-  DISALLOW_COPY_AND_ASSIGN(InstantTestModelObserver);
-};
-
 // This utility class is meant to be used in a "mix-in" fashion, giving the
 // derived test class additional Instant-related functionality.
 class InstantTestBase {
@@ -73,6 +51,10 @@
     browser_ = browser;
   }
 
+  BrowserInstantController* browser_instant() {
+    return browser_->instant_controller();
+  }
+
   InstantController* instant() {
     return browser_->instant_controller()->instant();
   }
@@ -88,12 +70,9 @@
   void KillInstantRenderView();
 
   void FocusOmnibox();
-  void FocusOmniboxAndWaitForInstantOverlaySupport();
-  void FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
+  void FocusOmniboxAndWaitForInstantNTPSupport();
 
   void SetOmniboxText(const std::string& text);
-  bool SetOmniboxTextAndWaitForOverlayToShow(const std::string& text);
-  void SetOmniboxTextAndWaitForSuggestion(const std::string& text);
 
   void PressEnterAndWaitForNavigation();
 
@@ -112,6 +91,8 @@
   bool HasUserInputInProgress();
   bool HasTemporaryText();
 
+  std::string GetOmniboxText();
+
   // Loads a named image from url |image| from the given |rvh| host.  |loaded|
   // returns whether the image was able to load without error.
   // The method returns true if the JavaScript executed cleanly.
diff --git a/chrome/browser/ui/search/local_ntp_browsertest.cc b/chrome/browser/ui/search/local_ntp_browsertest.cc
index 8c2b63a..84decce 100644
--- a/chrome/browser/ui/search/local_ntp_browsertest.cc
+++ b/chrome/browser/ui/search/local_ntp_browsertest.cc
@@ -2,12 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/prefs/pref_service.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/browser_process.h"
 #include "chrome/browser/search/search.h"
 #include "chrome/browser/ui/search/instant_test_utils.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/url_constants.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/web_contents.h"
+#include "ui/base/resource/resource_bundle.h"
 
 class LocalNTPTest : public InProcessBrowserTest,
                      public InstantTestBase {
@@ -26,7 +32,7 @@
 
 IN_PROC_BROWSER_TEST_F(LocalNTPTest, LocalNTPJavascriptTest) {
   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-  FocusOmniboxAndWaitForInstantOverlayAndNTPSupport();
+  FocusOmniboxAndWaitForInstantNTPSupport();
 
   ui_test_utils::NavigateToURLWithDisposition(
       browser(),
@@ -36,8 +42,46 @@
       ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
   content::WebContents* active_tab =
       browser()->tab_strip_model()->GetActiveWebContents();
-  ASSERT_TRUE(chrome::IsInstantNTP(active_tab));
+  EXPECT_TRUE(chrome::ShouldAssignURLToInstantRenderer(active_tab->GetURL(),
+                                                       browser()->profile()));
   bool success = false;
   ASSERT_TRUE(GetBoolFromJS(active_tab, "!!runTests()", &success));
   EXPECT_TRUE(success);
 }
+
+// Flaky on Linux Tests bot.
+#if defined(OS_LINUX)
+#define MAYBE_NTPRespectsBrowserLanguageSetting DISABLED_NTPRespectsBrowserLanguageSetting
+#else
+#define MAYBE_NTPRespectsBrowserLanguageSetting NTPRespectsBrowserLanguageSetting
+#endif
+IN_PROC_BROWSER_TEST_F(LocalNTPTest, MAYBE_NTPRespectsBrowserLanguageSetting) {
+  // Make sure the default language is not French.
+  std::string default_locale = g_browser_process->GetApplicationLocale();
+  EXPECT_NE("fr", default_locale);
+
+  // Switch browser language to French.
+  std::string loaded_locale =
+      ui::ResourceBundle::GetSharedInstance().ReloadLocaleResources("fr");
+  EXPECT_EQ("fr", loaded_locale);
+  g_browser_process->SetApplicationLocale(loaded_locale);
+  PrefService* prefs = g_browser_process->local_state();
+  prefs->SetString(prefs::kApplicationLocale, loaded_locale);
+
+  // Setup Instant.
+  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
+  FocusOmniboxAndWaitForInstantNTPSupport();
+
+  // Open a new tab.
+  ui_test_utils::NavigateToURLWithDisposition(
+      browser(),
+      GURL(chrome::kChromeUINewTabURL),
+      NEW_FOREGROUND_TAB,
+      ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB |
+      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+
+  // Verify that the NTP is in French.
+  content::WebContents* active_tab =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  EXPECT_EQ(ASCIIToUTF16("Nouvel onglet"), active_tab->GetTitle());
+}
diff --git a/chrome/browser/ui/search/search_model.cc b/chrome/browser/ui/search/search_model.cc
index 53d0fcc..840fbfa 100644
--- a/chrome/browser/ui/search/search_model.cc
+++ b/chrome/browser/ui/search/search_model.cc
@@ -7,6 +7,28 @@
 #include "chrome/browser/search/search.h"
 #include "chrome/browser/ui/search/search_model_observer.h"
 
+SearchModel::State::State()
+    : top_bars_visible(true),
+      instant_support(INSTANT_SUPPORT_UNKNOWN),
+      voice_search_supported(false) {
+}
+
+SearchModel::State::State(const SearchMode& mode,
+                          bool top_bars_visible,
+                          InstantSupportState instant_support,
+                          bool voice_search_supported)
+    : mode(mode),
+      top_bars_visible(top_bars_visible),
+      instant_support(instant_support),
+      voice_search_supported(voice_search_supported) {
+}
+
+bool SearchModel::State::operator==(const State& rhs) const {
+  return mode == rhs.mode && top_bars_visible == rhs.top_bars_visible &&
+      instant_support == rhs.instant_support &&
+      voice_search_supported == rhs.voice_search_supported;
+}
+
 SearchModel::SearchModel() {
 }
 
@@ -64,7 +86,7 @@
 
 void SearchModel::SetTopBarsVisible(bool visible) {
   DCHECK(chrome::IsInstantExtendedAPIEnabled())
-      << "Please do not try to set the SearchModel mode without first "
+      << "Please do not try to set the SearchModel state without first "
       << "checking if Search is enabled.";
 
   if (state_.top_bars_visible == visible)
@@ -77,6 +99,35 @@
                     ModelChanged(old_state, state_));
 }
 
+void SearchModel::SetInstantSupportState(InstantSupportState instant_support) {
+  DCHECK(chrome::IsInstantExtendedAPIEnabled())
+      << "Please do not try to set the SearchModel state without first "
+      << "checking if Search is enabled.";
+
+  if (state_.instant_support == instant_support)
+    return;
+
+  const State old_state = state_;
+  state_.instant_support = instant_support;
+  FOR_EACH_OBSERVER(SearchModelObserver, observers_,
+                    ModelChanged(old_state, state_));
+}
+
+void SearchModel::SetVoiceSearchSupported(bool supported) {
+  DCHECK(chrome::IsInstantExtendedAPIEnabled())
+      << "Please do not try to set the SearchModel state without first "
+      << "checking if Search is enabled.";
+
+  if (state_.voice_search_supported == supported)
+    return;
+
+  const State old_state = state_;
+  state_.voice_search_supported = supported;
+
+  FOR_EACH_OBSERVER(SearchModelObserver, observers_,
+                    ModelChanged(old_state, state_));
+}
+
 void SearchModel::AddObserver(SearchModelObserver* observer) {
   observers_.AddObserver(observer);
 }
diff --git a/chrome/browser/ui/search/search_model.h b/chrome/browser/ui/search/search_model.h
index 3f77b87..b9a62fb 100644
--- a/chrome/browser/ui/search/search_model.h
+++ b/chrome/browser/ui/search/search_model.h
@@ -11,25 +11,37 @@
 
 class SearchModelObserver;
 
+// Represents whether a page supports Instant.
+enum InstantSupportState {
+  INSTANT_SUPPORT_NO,
+  INSTANT_SUPPORT_YES,
+  INSTANT_SUPPORT_UNKNOWN,
+};
+
 // An observable model for UI components that care about search model state
 // changes.
 class SearchModel {
  public:
   struct State {
-    State() : top_bars_visible(true) {}
-    State(const SearchMode& mode, bool top_bars_visible)
-        : mode(mode),
-          top_bars_visible(top_bars_visible) {}
+    State();
+    State(const SearchMode& mode,
+          bool top_bars_visible,
+          InstantSupportState instant_support,
+          bool voice_search_supported);
 
-    bool operator==(const State& rhs) const {
-      return mode == rhs.mode && top_bars_visible == rhs.top_bars_visible;
-    }
+    bool operator==(const State& rhs) const;
 
     // The display mode of UI elements such as the toolbar, the tab strip, etc.
     SearchMode mode;
 
     // The visibility of top bars such as bookmark and info bars.
     bool top_bars_visible;
+
+    // Does the current page support Instant?
+    InstantSupportState instant_support;
+
+    // Does the current page support voice search?
+    bool voice_search_supported;
   };
 
   SearchModel();
@@ -58,6 +70,22 @@
   // Get the visibility of top bars.
   bool top_bars_visible() const { return state_.top_bars_visible; }
 
+  // Sets the page instant support state. Change notifications are sent to
+  // observers.
+  void SetInstantSupportState(InstantSupportState instant_support);
+
+  // Gets the instant support state of the page.
+  InstantSupportState instant_support() const {
+    return state_.instant_support;
+  }
+
+  // Sets the page voice search support state.  Change notifications are sent to
+  // observers.
+  void SetVoiceSearchSupported(bool supported);
+
+  // Gets the voice search support state of the page.
+  bool voice_search_supported() const { return state_.voice_search_supported; }
+
   // Add and remove observers.
   void AddObserver(SearchModelObserver* observer);
   void RemoveObserver(SearchModelObserver* observer);
diff --git a/chrome/browser/ui/search/search_model_unittest.cc b/chrome/browser/ui/search/search_model_unittest.cc
new file mode 100644
index 0000000..762256b
--- /dev/null
+++ b/chrome/browser/ui/search/search_model_unittest.cc
@@ -0,0 +1,174 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/search/search_model.h"
+
+#include "base/command_line.h"
+#include "chrome/browser/ui/search/search_model_observer.h"
+#include "chrome/browser/ui/search/search_tab_helper.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/search_types.h"
+#include "chrome/test/base/chrome_render_view_host_test_harness.h"
+
+namespace {
+
+class MockSearchModelObserver : public SearchModelObserver {
+ public:
+  MockSearchModelObserver();
+  virtual ~MockSearchModelObserver();
+
+  virtual void ModelChanged(const SearchModel::State& old_state,
+                            const SearchModel::State& new_state) OVERRIDE;
+
+  void VerifySearchModelStates(const SearchModel::State& expected_old_state,
+                               const SearchModel::State& expected_new_state);
+
+  void VerifyNotificationCount(int expected_count);
+
+ private:
+  // How many times we've seen search model changed notifications.
+  int modelchanged_notification_count_;
+
+  SearchModel::State actual_old_state_;
+  SearchModel::State actual_new_state_;
+
+  DISALLOW_COPY_AND_ASSIGN(MockSearchModelObserver);
+};
+
+MockSearchModelObserver::MockSearchModelObserver()
+    : modelchanged_notification_count_(0) {
+}
+
+MockSearchModelObserver::~MockSearchModelObserver() {
+}
+
+void MockSearchModelObserver::ModelChanged(
+    const SearchModel::State& old_state,
+    const SearchModel::State& new_state) {
+  actual_old_state_ = old_state;
+  actual_new_state_ = new_state;
+  modelchanged_notification_count_++;
+}
+
+void MockSearchModelObserver::VerifySearchModelStates(
+    const SearchModel::State& expected_old_state,
+    const SearchModel::State& expected_new_state) {
+  EXPECT_TRUE(actual_old_state_ == expected_old_state);
+  EXPECT_TRUE(actual_new_state_ == expected_new_state);
+}
+
+void MockSearchModelObserver::VerifyNotificationCount(int expected_count) {
+  EXPECT_EQ(modelchanged_notification_count_, expected_count);
+}
+
+}  // namespace
+
+class SearchModelTest : public ChromeRenderViewHostTestHarness {
+ public:
+  virtual void SetUp() OVERRIDE;
+  virtual void TearDown() OVERRIDE;
+
+  MockSearchModelObserver mock_observer;
+  SearchModel* model;
+};
+
+void SearchModelTest::SetUp() {
+  CommandLine::ForCurrentProcess()->AppendSwitch(
+      switches::kEnableInstantExtendedAPI);
+  ChromeRenderViewHostTestHarness::SetUp();
+  SearchTabHelper::CreateForWebContents(web_contents());
+  SearchTabHelper* search_tab_helper =
+      SearchTabHelper::FromWebContents(web_contents());
+  ASSERT_TRUE(search_tab_helper != NULL);
+  model = search_tab_helper->model();
+  model->AddObserver(&mock_observer);
+}
+
+void SearchModelTest::TearDown() {
+  model->RemoveObserver(&mock_observer);
+  ChromeRenderViewHostTestHarness::TearDown();
+}
+
+TEST_F(SearchModelTest, UpdateSearchModelInstantSupport) {
+  mock_observer.VerifyNotificationCount(0);
+  EXPECT_TRUE(model->instant_support() == INSTANT_SUPPORT_UNKNOWN);
+  SearchModel::State expected_old_state = model->state();
+  SearchModel::State expected_new_state(model->state());
+  expected_new_state.instant_support = INSTANT_SUPPORT_YES;
+
+  model->SetInstantSupportState(INSTANT_SUPPORT_YES);
+  mock_observer.VerifySearchModelStates(expected_old_state, expected_new_state);
+  mock_observer.VerifyNotificationCount(1);
+  EXPECT_TRUE(model->instant_support() == INSTANT_SUPPORT_YES);
+
+  expected_old_state = expected_new_state;
+  expected_new_state.instant_support = INSTANT_SUPPORT_NO;
+  model->SetInstantSupportState(INSTANT_SUPPORT_NO);
+  mock_observer.VerifySearchModelStates(expected_old_state, expected_new_state);
+  mock_observer.VerifyNotificationCount(2);
+
+  // Notify the observer only if the search model state is changed.
+  model->SetInstantSupportState(INSTANT_SUPPORT_NO);
+  EXPECT_TRUE(model->state() == expected_new_state);
+  EXPECT_TRUE(model->instant_support() == INSTANT_SUPPORT_NO);
+  mock_observer.VerifyNotificationCount(2);
+}
+
+TEST_F(SearchModelTest, UpdateSearchModelMode) {
+  mock_observer.VerifyNotificationCount(0);
+  SearchMode search_mode(SearchMode::MODE_NTP, SearchMode::ORIGIN_NTP);
+  SearchModel::State expected_old_state = model->state();
+  SearchModel::State expected_new_state(model->state());
+  expected_new_state.mode = search_mode;
+
+  model->SetMode(search_mode);
+  mock_observer.VerifySearchModelStates(expected_old_state, expected_new_state);
+  mock_observer.VerifyNotificationCount(1);
+
+  search_mode.mode = SearchMode::MODE_SEARCH_RESULTS;
+  expected_old_state = expected_new_state;
+  expected_new_state.mode = search_mode;
+  model->SetMode(search_mode);
+  mock_observer.VerifySearchModelStates(expected_old_state, expected_new_state);
+  mock_observer.VerifyNotificationCount(2);
+  EXPECT_TRUE(model->state() == expected_new_state);
+}
+
+TEST_F(SearchModelTest, UpdateTopBarVisibility) {
+  mock_observer.VerifyNotificationCount(0);
+  EXPECT_TRUE(model->top_bars_visible());
+
+  SearchModel::State expected_old_state = model->state();
+  SearchModel::State expected_new_state(model->state());
+  expected_new_state.top_bars_visible = false;
+
+  model->SetTopBarsVisible(false);
+  mock_observer.VerifySearchModelStates(expected_old_state, expected_new_state);
+  mock_observer.VerifyNotificationCount(1);
+  EXPECT_FALSE(model->top_bars_visible());
+}
+
+TEST_F(SearchModelTest, UpdateSearchModelState) {
+  SearchModel::State expected_new_state(model->state());
+  expected_new_state.top_bars_visible = false;
+  expected_new_state.instant_support = INSTANT_SUPPORT_NO;
+  EXPECT_FALSE(model->state() == expected_new_state);
+  model->SetState(expected_new_state);
+  mock_observer.VerifyNotificationCount(1);
+  EXPECT_TRUE(model->state() == expected_new_state);
+}
+
+TEST_F(SearchModelTest, UpdateVoiceSearchSupported) {
+  mock_observer.VerifyNotificationCount(0);
+  EXPECT_FALSE(model->voice_search_supported());
+
+  SearchModel::State expected_old_state = model->state();
+  SearchModel::State expected_new_state(model->state());
+  expected_new_state.voice_search_supported = true;
+
+  model->SetVoiceSearchSupported(true);
+  mock_observer.VerifySearchModelStates(expected_old_state, expected_new_state);
+  mock_observer.VerifyNotificationCount(1);
+  EXPECT_TRUE(model->voice_search_supported());
+}
diff --git a/chrome/browser/ui/search/search_tab_helper.cc b/chrome/browser/ui/search/search_tab_helper.cc
index 4cbbd8a..881b22e 100644
--- a/chrome/browser/ui/search/search_tab_helper.cc
+++ b/chrome/browser/ui/search/search_tab_helper.cc
@@ -4,12 +4,18 @@
 
 #include "chrome/browser/ui/search/search_tab_helper.h"
 
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search/search.h"
 #include "chrome/common/render_messages.h"
 #include "chrome/common/url_constants.h"
+#include "content/public/browser/navigation_controller.h"
+#include "content/public/browser/navigation_details.h"
 #include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/navigation_type.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_types.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 DEFINE_WEB_CONTENTS_USER_DATA_KEY(SearchTabHelper);
 
@@ -30,6 +36,14 @@
   return !chrome::GetSearchTerms(contents).empty();
 }
 
+// TODO(kmadhusu): Move this helper from anonymous namespace to chrome
+// namespace and remove InstantPage::IsLocal().
+bool IsLocal(const content::WebContents* contents) {
+  return contents &&
+      (contents->GetURL() == GURL(chrome::kChromeSearchLocalNtpUrl) ||
+       contents->GetURL() == GURL(chrome::kChromeSearchLocalGoogleNtpUrl));
+}
+
 }  // namespace
 
 SearchTabHelper::SearchTabHelper(content::WebContents* web_contents)
@@ -42,6 +56,9 @@
   if (!is_search_enabled_)
     return;
 
+  // Observe NOTIFICATION_NAV_ENTRY_COMMITTED events so we can reset state
+  // associated with the WebContents  (such as mode, last known most visited
+  // items, instant support state etc).
   registrar_.Add(
       this,
       content::NOTIFICATION_NAV_ENTRY_COMMITTED,
@@ -52,6 +69,10 @@
 SearchTabHelper::~SearchTabHelper() {
 }
 
+void SearchTabHelper::InitForPreloadedNTP() {
+  UpdateMode(true, true);
+}
+
 void SearchTabHelper::OmniboxEditModelChanged(bool user_input_in_progress,
                                               bool cancelling,
                                               bool popup_is_open,
@@ -65,23 +86,26 @@
   if (!user_input_in_progress && !cancelling)
     return;
 
-  UpdateMode();
+  UpdateMode(false, false);
 }
 
 void SearchTabHelper::NavigationEntryUpdated() {
   if (!is_search_enabled_)
     return;
 
-  UpdateMode();
+  UpdateMode(false, false);
 }
 
-bool SearchTabHelper::UpdateLastKnownMostVisitedItems(
-    const std::vector<InstantMostVisitedItem>& items) {
-  if (chrome::AreMostVisitedItemsEqual(items, last_known_most_visited_items_))
-    return false;
+void SearchTabHelper::InstantSupportChanged(bool instant_support) {
+  if (!is_search_enabled_)
+    return;
 
-  last_known_most_visited_items_ = items;
-  return true;
+  model_.SetInstantSupportState(instant_support ? INSTANT_SUPPORT_YES :
+                                                  INSTANT_SUPPORT_NO);
+}
+
+bool SearchTabHelper::SupportsInstant() const {
+  return model_.instant_support() == INSTANT_SUPPORT_YES;
 }
 
 void SearchTabHelper::Observe(
@@ -89,8 +113,52 @@
     const content::NotificationSource& source,
     const content::NotificationDetails& details) {
   DCHECK_EQ(content::NOTIFICATION_NAV_ENTRY_COMMITTED, type);
-  UpdateMode();
-  last_known_most_visited_items_.clear();
+  content::LoadCommittedDetails* load_details =
+      content::Details<content::LoadCommittedDetails>(details).ptr();
+  if (!load_details->is_main_frame)
+    return;
+
+  UpdateMode(true, false);
+
+  // Already determined the instant support state for this page, do not reset
+  // the instant support state.
+  //
+  // When we get a navigation entry committed event, there seem to be two ways
+  // to tell whether the navigation was "in-page". Ideally, when
+  // LoadCommittedDetails::is_in_page is true, we should have
+  // LoadCommittedDetails::type to be NAVIGATION_TYPE_IN_PAGE. Unfortunately,
+  // they are different in some cases. To workaround this bug, we are checking
+  // (is_in_page || type == NAVIGATION_TYPE_IN_PAGE). Please refer to
+  // crbug.com/251330 for more details.
+  if (load_details->is_in_page ||
+      load_details->type == content::NAVIGATION_TYPE_IN_PAGE) {
+    return;
+  }
+
+  model_.SetInstantSupportState(INSTANT_SUPPORT_UNKNOWN);
+  model_.SetVoiceSearchSupported(false);
+}
+
+void SearchTabHelper::DidNavigateMainFrame(
+    const content::LoadCommittedDetails& details,
+    const content::FrameNavigateParams& params) {
+  // Always set the title on the new tab page to be the one from our UI
+  // resources.  Normally, we set the title when we begin a NTP load, but it
+  // can get reset in several places (like when you press Reload). This check
+  // ensures that the title is properly set to the string defined by the Chrome
+  // UI language (rather than the server language) in all cases.
+  //
+  // We only override the title when it's nonempty to allow the page to set the
+  // title if it really wants. An empty title means to use the default. There's
+  // also a race condition between this code and the page's SetTitle call which
+  // this rule avoids.
+  content::NavigationEntry* entry =
+      web_contents_->GetController().GetActiveEntry();
+  if (entry && entry->GetTitle().empty() &&
+      (entry->GetVirtualURL() == GURL(chrome::kChromeUINewTabURL) ||
+       chrome::NavEntryIsInstantNTP(web_contents_, entry))) {
+    entry->SetTitle(l10n_util::GetStringUTF16(IDS_NEW_TAB_TITLE));
+  }
 }
 
 bool SearchTabHelper::OnMessageReceived(const IPC::Message& message) {
@@ -100,21 +168,36 @@
                         OnSearchBoxShowBars)
     IPC_MESSAGE_HANDLER(ChromeViewHostMsg_SearchBoxHideBars,
                         OnSearchBoxHideBars)
+    IPC_MESSAGE_HANDLER(ChromeViewHostMsg_InstantSupportDetermined,
+                        OnInstantSupportDetermined)
+    IPC_MESSAGE_HANDLER(ChromeViewHostMsg_SetVoiceSearchSupported,
+                        OnSetVoiceSearchSupported)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
   return handled;
 }
 
-void SearchTabHelper::UpdateMode() {
+void SearchTabHelper::DidFinishLoad(
+    int64 /* frame_id */,
+    const GURL&  /* validated_url */,
+    bool is_main_frame,
+    content::RenderViewHost* /* render_view_host */) {
+  if (is_main_frame)
+    DetermineIfPageSupportsInstant();
+}
+
+void SearchTabHelper::UpdateMode(bool update_origin, bool is_preloaded_ntp) {
   SearchMode::Type type = SearchMode::MODE_DEFAULT;
   SearchMode::Origin origin = SearchMode::ORIGIN_DEFAULT;
-  if (IsNTP(web_contents_)) {
+  if (IsNTP(web_contents_) || is_preloaded_ntp) {
     type = SearchMode::MODE_NTP;
     origin = SearchMode::ORIGIN_NTP;
   } else if (IsSearchResults(web_contents_)) {
     type = SearchMode::MODE_SEARCH_RESULTS;
     origin = SearchMode::ORIGIN_SEARCH;
   }
+  if (!update_origin)
+    origin = model_.mode().origin;
   if (user_input_in_progress_)
     type = SearchMode::MODE_SEARCH_SUGGESTIONS;
 
@@ -122,17 +205,45 @@
       !popup_is_open_ && !user_text_is_empty_) {
     // We're switching back (|popup_is_open_| is false) to an NTP (type and
     // mode are |NTP|) with suggestions (|user_text_is_empty_| is false), don't
-    // modify visibility of top bars.  This specific omnibox state is set when
-    // OmniboxEditModelChanged() is called from
+    // modify visibility of top bars or voice search support.  This specific
+    // omnibox state is set when OmniboxEditModelChanged() is called from
     // OmniboxEditModel::SetInputInProgress() which is called from
     // OmniboxEditModel::Revert().
     model_.SetState(SearchModel::State(SearchMode(type, origin),
-                                       model_.state().top_bars_visible));
+                                       model_.state().top_bars_visible,
+                                       model_.instant_support(),
+                                       model_.state().voice_search_supported));
   } else {
     model_.SetMode(SearchMode(type, origin));
   }
 }
 
+void SearchTabHelper::DetermineIfPageSupportsInstant() {
+  Profile* profile =
+      Profile::FromBrowserContext(web_contents_->GetBrowserContext());
+  if (!chrome::ShouldAssignURLToInstantRenderer(web_contents_->GetURL(),
+                                                profile)) {
+    // The page is not in the Instant process. This page does not support
+    // instant. If we send an IPC message to a page that is not in the Instant
+    // process, it will never receive it and will never respond. Therefore,
+    // return immediately.
+    InstantSupportChanged(false);
+  } else if (IsLocal(web_contents_)) {
+    // Local pages always support Instant.
+    InstantSupportChanged(true);
+  } else {
+    Send(new ChromeViewMsg_DetermineIfPageSupportsInstant(routing_id()));
+  }
+}
+
+void SearchTabHelper::OnInstantSupportDetermined(int page_id,
+                                                 bool instant_support) {
+  if (!web_contents()->IsActiveEntry(page_id))
+    return;
+
+  InstantSupportChanged(instant_support);
+}
+
 void SearchTabHelper::OnSearchBoxShowBars(int page_id) {
   if (web_contents()->IsActiveEntry(page_id))
     model_.SetTopBarsVisible(true);
@@ -144,3 +255,8 @@
     Send(new ChromeViewMsg_SearchBoxBarsHidden(routing_id()));
   }
 }
+
+void SearchTabHelper::OnSetVoiceSearchSupported(int page_id, bool supported) {
+  if (web_contents()->IsActiveEntry(page_id))
+    model_.SetVoiceSearchSupported(supported);
+}
diff --git a/chrome/browser/ui/search/search_tab_helper.h b/chrome/browser/ui/search/search_tab_helper.h
index 8dd7711..8d3ae48 100644
--- a/chrome/browser/ui/search/search_tab_helper.h
+++ b/chrome/browser/ui/search/search_tab_helper.h
@@ -5,12 +5,10 @@
 #ifndef CHROME_BROWSER_UI_SEARCH_SEARCH_TAB_HELPER_H_
 #define CHROME_BROWSER_UI_SEARCH_SEARCH_TAB_HELPER_H_
 
-#include <vector>
-
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
+#include "base/gtest_prod_util.h"
 #include "chrome/browser/ui/search/search_model.h"
-#include "chrome/common/instant_types.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "content/public/browser/web_contents_observer.h"
@@ -20,8 +18,15 @@
 class WebContents;
 }
 
+class InstantPageTest;
+
 // Per-tab search "helper".  Acts as the owner and controller of the tab's
 // search UI model.
+//
+// When the page is finished loading, SearchTabHelper determines the instant
+// support for the page. When a navigation entry is committed (except for
+// in-page navigations), SearchTabHelper resets the instant support state to
+// INSTANT_SUPPORT_UNKNOWN and cause support to be determined again.
 class SearchTabHelper : public content::NotificationObserver,
                         public content::WebContentsObserver,
                         public content::WebContentsUserData<SearchTabHelper> {
@@ -32,6 +37,13 @@
     return &model_;
   }
 
+  const SearchModel* model() const {
+    return &model_;
+  }
+
+  // Sets up the initial state correctly for a preloaded NTP.
+  void InitForPreloadedNTP();
+
   // Invoked when the OmniboxEditModel changes state in some way that might
   // affect the search mode.
   void OmniboxEditModelChanged(bool user_input_in_progress,
@@ -45,13 +57,23 @@
   // the notification system and shouldn't call this method.
   void NavigationEntryUpdated();
 
-  // Updates |last_known_most_visited_items_| with |items|.
-  // Returns false if |items| matches the |last_known_most_visited_items_|.
-  bool UpdateLastKnownMostVisitedItems(
-      const std::vector<InstantMostVisitedItem>& items);
+  // Invoked to update the instant support state.
+  void InstantSupportChanged(bool supports_instant);
+
+  // Returns true if the page supports instant. If the instant support state is
+  // not determined or if the page does not support instant returns false.
+  bool SupportsInstant() const;
 
  private:
   friend class content::WebContentsUserData<SearchTabHelper>;
+  friend class InstantPageTest;
+  FRIEND_TEST_ALL_PREFIXES(InstantPageTest,
+                           DetermineIfPageSupportsInstant_Local);
+  FRIEND_TEST_ALL_PREFIXES(InstantPageTest,
+                           DetermineIfPageSupportsInstant_NonLocal);
+  FRIEND_TEST_ALL_PREFIXES(InstantPageTest,
+                           PageURLDoesntBelongToInstantRenderer);
+  FRIEND_TEST_ALL_PREFIXES(InstantPageTest, PageSupportsInstant);
 
   explicit SearchTabHelper(content::WebContents* web_contents);
 
@@ -61,16 +83,39 @@
                        const content::NotificationDetails& details) OVERRIDE;
 
   // Overridden from contents::WebContentsObserver:
+  virtual void DidNavigateMainFrame(
+      const content::LoadCommittedDetails& details,
+      const content::FrameNavigateParams& params) OVERRIDE;
   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+  virtual void DidFinishLoad(
+      int64 frame_id,
+      const GURL& validated_url,
+      bool is_main_frame,
+      content::RenderViewHost* render_view_host) OVERRIDE;
 
   // Sets the mode of the model based on the current URL of web_contents().
-  void UpdateMode();
+  // Only updates the origin part of the mode if |update_origin| is true,
+  // otherwise keeps the current origin. If |is_preloaded_ntp| is true, the mode
+  // is set to NTP regardless of the current URL; this is used to ensure that
+  // InstantController can bind InstantTab to new tab pages immediately.
+  void UpdateMode(bool update_origin, bool is_preloaded_ntp);
+
+  // Tells the renderer to determine if the page supports the Instant API, which
+  // results in a call to OnInstantSupportDetermined() when the reply
+  // is received.
+  void DetermineIfPageSupportsInstant();
+
+  // Handler for when Instant support has been determined.
+  void OnInstantSupportDetermined(int page_id, bool supports_instant);
 
   // Handlers for SearchBox API to show and hide top bars (bookmark and info
   // bars).
   void OnSearchBoxShowBars(int page_id);
   void OnSearchBoxHideBars(int page_id);
 
+  // Sets whether the page supports voice search on the model.
+  void OnSetVoiceSearchSupported(int page_id, bool supported);
+
   const bool is_search_enabled_;
 
   // Tracks the last value passed to OmniboxEditModelChanged().
@@ -85,10 +130,6 @@
 
   content::WebContents* web_contents_;
 
-  // Tracks the last set of most visited items sent to the InstantPage renderer.
-  // Used to prevent sending duplicate IPC messages to the renderer.
-  std::vector<InstantMostVisitedItem> last_known_most_visited_items_;
-
   DISALLOW_COPY_AND_ASSIGN(SearchTabHelper);
 };
 
diff --git a/chrome/browser/ui/startup/startup_browser_creator.cc b/chrome/browser/ui/startup/startup_browser_creator.cc
index e64f900..f90004a 100644
--- a/chrome/browser/ui/startup/startup_browser_creator.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator.cc
@@ -45,9 +45,7 @@
 #include "chrome/browser/printing/print_dialog_cloud.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/browser/search_engines/template_url.h"
-#include "chrome/browser/search_engines/template_url_service.h"
-#include "chrome/browser/search_engines/template_url_service_factory.h"
+#include "chrome/browser/search_engines/util.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_window.h"
@@ -384,22 +382,17 @@
     const base::FilePath& cur_dir,
     Profile* profile) {
   std::vector<GURL> urls;
-  const CommandLine::StringVector& params = command_line.GetArgs();
 
+  const CommandLine::StringVector& params = command_line.GetArgs();
   for (size_t i = 0; i < params.size(); ++i) {
     base::FilePath param = base::FilePath(params[i]);
     // Handle Vista way of searching - "? <search-term>"
-    if (param.value().size() > 2 &&
-        param.value()[0] == '?' && param.value()[1] == ' ') {
-      const TemplateURL* default_provider =
-          TemplateURLServiceFactory::GetForProfile(profile)->
-          GetDefaultSearchProvider();
-      if (default_provider) {
-        const TemplateURLRef& search_url = default_provider->url_ref();
-        DCHECK(search_url.SupportsReplacement());
-        string16 search_term = param.LossyDisplayName().substr(2);
-        urls.push_back(GURL(search_url.ReplaceSearchTerms(
-            TemplateURLRef::SearchTermsArgs(search_term))));
+    if ((param.value().size() > 2) && (param.value()[0] == '?') &&
+        (param.value()[1] == ' ')) {
+      GURL url(GetDefaultSearchURLForSearchTerms(
+          profile, param.LossyDisplayName().substr(2)));
+      if (url.is_valid()) {
+        urls.push_back(url);
         continue;
       }
     }
@@ -436,9 +429,9 @@
     // If we are in Windows 8 metro mode and were launched as a result of the
     // search charm or via a url navigation in metro, then fetch the
     // corresponding url.
-    GURL url = chrome::GetURLToOpen(profile);
+    GURL url(chrome::GetURLToOpen(profile));
     if (url.is_valid())
-      urls.push_back(GURL(url));
+      urls.push_back(url);
   }
 #endif  // OS_WIN
   return urls;
diff --git a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
index 1af06b1..f761bf8 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
@@ -29,8 +29,8 @@
 #include "chrome/browser/ui/host_desktop.h"
 #include "chrome/browser/ui/startup/startup_browser_creator.h"
 #include "chrome/browser/ui/startup/startup_browser_creator_impl.h"
+#include "chrome/browser/ui/sync/sync_promo_ui.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/browser/ui/webui/sync_promo/sync_promo_ui.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
diff --git a/chrome/browser/ui/startup/startup_browser_creator_impl.cc b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
index 2f29df6..fb78c6a 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_impl.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
@@ -65,11 +65,11 @@
 #include "chrome/browser/ui/startup/obsolete_os_infobar_delegate.h"
 #include "chrome/browser/ui/startup/session_crashed_prompt.h"
 #include "chrome/browser/ui/startup/startup_browser_creator.h"
+#include "chrome/browser/ui/sync/sync_promo_ui.h"
 #include "chrome/browser/ui/tabs/pinned_tab_codec.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/webui/ntp/app_launcher_handler.h"
 #include "chrome/browser/ui/webui/sync_promo/sync_promo_trial.h"
-#include "chrome/browser/ui/webui/sync_promo/sync_promo_ui.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "chrome/common/chrome_paths.h"
@@ -830,8 +830,7 @@
     params.extension_app_id = tabs[i].app_id;
 
 #if defined(ENABLE_RLZ)
-    if (process_startup &&
-        google_util::IsGoogleHomePageUrl(tabs[i].url.spec())) {
+    if (process_startup && google_util::IsGoogleHomePageUrl(tabs[i].url)) {
       params.extra_headers = RLZTracker::GetAccessPointHttpHeader(
           RLZTracker::CHROME_HOME_PAGE);
     }
diff --git a/chrome/browser/ui/startup/startup_browser_creator_win.cc b/chrome/browser/ui/startup/startup_browser_creator_win.cc
index 0544d90..a53e900 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_win.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_win.cc
@@ -6,9 +6,7 @@
 
 #include "base/logging.h"
 #include "base/win/metro.h"
-#include "chrome/browser/search_engines/template_url.h"
-#include "chrome/browser/search_engines/template_url_service.h"
-#include "chrome/browser/search_engines/template_url_service_factory.h"
+#include "chrome/browser/search_engines/util.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/startup/startup_browser_creator_impl.h"
@@ -21,22 +19,11 @@
   string16 params;
   base::win::MetroLaunchType launch_type =
       base::win::GetMetroLaunchParams(&params);
-
   if ((launch_type == base::win::METRO_PROTOCOL) ||
-      (launch_type == base::win::METRO_LAUNCH)) {
+      (launch_type == base::win::METRO_LAUNCH))
     return GURL(params);
-  } else if (launch_type == base::win::METRO_SEARCH) {
-    const TemplateURL* default_provider =
-        TemplateURLServiceFactory::GetForProfile(profile)->
-        GetDefaultSearchProvider();
-    if (default_provider) {
-      const TemplateURLRef& search_url = default_provider->url_ref();
-      DCHECK(search_url.SupportsReplacement());
-      return GURL(search_url.ReplaceSearchTerms(
-          TemplateURLRef::SearchTermsArgs(params)));
-    }
-  }
-  return GURL();
+  return (launch_type == base::win::METRO_SEARCH) ?
+      GetDefaultSearchURLForSearchTerms(profile, params) : GURL();
 }
 
 }  // namespace chrome
diff --git a/chrome/browser/ui/sync/one_click_signin_helper.cc b/chrome/browser/ui/sync/one_click_signin_helper.cc
index 8502d52..b614c93 100644
--- a/chrome/browser/ui/sync/one_click_signin_helper.cc
+++ b/chrome/browser/ui/sync/one_click_signin_helper.cc
@@ -229,20 +229,12 @@
     return;
   }
 
-  // If we are giving the user the option to configure sync, then that will
-  // suffice as a confirmation.
-  OneClickSigninSyncStarter::ConfirmationRequired confirmation =
-      args.confirmation_required;
-  if (start_mode == OneClickSigninSyncStarter::CONFIGURE_SYNC_FIRST &&
-      confirmation == OneClickSigninSyncStarter::CONFIRM_UNTRUSTED_SIGNIN) {
-    confirmation = OneClickSigninSyncStarter::CONFIRM_AFTER_SIGNIN;
-  }
-
   // The starter deletes itself once its done.
   new OneClickSigninSyncStarter(args.profile, args.browser, args.session_index,
                                 args.email, args.password, start_mode,
                                 args.force_same_tab_navigation,
-                                confirmation);
+                                args.confirmation_required,
+                                args.source);
 
   int action = one_click_signin::HISTOGRAM_MAX;
   switch (args.auto_accept) {
@@ -999,6 +991,22 @@
   }
 }
 
+void OneClickSigninHelper::DidNavigateMainFrame(
+    const content::LoadCommittedDetails& details,
+    const content::FrameNavigateParams& params) {
+  // If we navigate to a non-sign-in URL, make sure that the renderer process
+  // is no longer considered the trusted sign-in process.
+  if (!SigninManager::IsWebBasedSigninFlowURL(params.url)) {
+    Profile* profile =
+        Profile::FromBrowserContext(web_contents()->GetBrowserContext());
+    SigninManager* manager = profile ?
+        SigninManagerFactory::GetForProfile(profile) : NULL;
+    int process_id = web_contents()->GetRenderProcessHost()->GetID();
+    if (manager && manager->IsSigninProcess(process_id))
+      manager->ClearSigninProcess();
+  }
+}
+
 void OneClickSigninHelper::DidStopLoading(
     content::RenderViewHost* render_view_host) {
   // If the user left the sign in process, clear all members.
@@ -1150,12 +1158,12 @@
       LogOneClickHistogramValue(one_click_signin::HISTOGRAM_ACCEPTED);
       LogOneClickHistogramValue(one_click_signin::HISTOGRAM_WITH_ADVANCED);
       SigninManager::DisableOneClickSignIn(profile);
-      // Don't bother displaying an extra confirmation (even in the SAML case)
-      // since the user will get prompted to setup sync anyway.
+      // Display the extra confirmation (even in the SAML case) in case this
+      // was an untrusted renderer.
       StartSync(
           StartSyncArgs(profile, browser, auto_accept_, session_index_, email_,
                         password_, false /* force_same_tab_navigation */,
-                        false /* confirmation_required */, source_),
+                        true /* confirmation_required */, source_),
           OneClickSigninSyncStarter::CONFIGURE_SYNC_FIRST);
       break;
     case AUTO_ACCEPT_EXPLICIT: {
diff --git a/chrome/browser/ui/sync/one_click_signin_helper.h b/chrome/browser/ui/sync/one_click_signin_helper.h
index 1d17870..20c9954 100644
--- a/chrome/browser/ui/sync/one_click_signin_helper.h
+++ b/chrome/browser/ui/sync/one_click_signin_helper.h
@@ -9,7 +9,7 @@
 
 #include "base/gtest_prod_util.h"
 #include "chrome/browser/sync/profile_sync_service_observer.h"
-#include "chrome/browser/ui/webui/sync_promo/sync_promo_ui.h"
+#include "chrome/browser/ui/sync/sync_promo_ui.h"
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/browser/web_contents_user_data.h"
@@ -21,6 +21,8 @@
 
 namespace content {
 class WebContents;
+struct FrameNavigateParams;
+struct LoadCommittedDetails;
 struct PasswordForm;
 }
 
@@ -209,6 +211,9 @@
   virtual void NavigateToPendingEntry(
       const GURL& url,
       content::NavigationController::ReloadType reload_type) OVERRIDE;
+  virtual void DidNavigateMainFrame(
+      const content::LoadCommittedDetails& details,
+      const content::FrameNavigateParams& params) OVERRIDE;
   virtual void DidStopLoading(
       content::RenderViewHost* render_view_host) OVERRIDE;
 
diff --git a/chrome/browser/ui/sync/one_click_signin_sync_starter.cc b/chrome/browser/ui/sync/one_click_signin_sync_starter.cc
index b05a727..37001a4 100644
--- a/chrome/browser/ui/sync/one_click_signin_sync_starter.cc
+++ b/chrome/browser/ui/sync/one_click_signin_sync_starter.cc
@@ -48,10 +48,12 @@
     const std::string& password,
     StartSyncMode start_mode,
     bool force_same_tab_navigation,
-    ConfirmationRequired confirmation_required)
+    ConfirmationRequired confirmation_required,
+    SyncPromoUI::Source source)
     : start_mode_(start_mode),
       force_same_tab_navigation_(force_same_tab_navigation),
       confirmation_required_(confirmation_required),
+      source_(source),
       weak_pointer_factory_(this) {
   DCHECK(profile);
   BrowserList::AddObserver(this);
@@ -312,6 +314,16 @@
     StartSyncMode response) {
   if (response == UNDO_SYNC) {
     CancelSigninAndDelete();
+    // If this was not an interstitial signin, (i.e. it was a SAML signin)
+    // then the browser page is now blank and should redirect to the NTP.
+    if (source_ != SyncPromoUI::SOURCE_UNKNOWN) {
+      EnsureBrowser();
+      chrome::NavigateParams params(browser_, GURL(chrome::kChromeUINewTabURL),
+                                    content::PAGE_TRANSITION_AUTO_TOPLEVEL);
+      params.disposition = CURRENT_TAB;
+      params.window_action = chrome::NavigateParams::SHOW_WINDOW;
+      chrome::Navigate(&params);
+    }
   } else {
     // If the user clicked the "Advanced" link in the confirmation dialog, then
     // override the current start_mode_ to bring up the advanced sync settings.
diff --git a/chrome/browser/ui/sync/one_click_signin_sync_starter.h b/chrome/browser/ui/sync/one_click_signin_sync_starter.h
index 628d4f5..ce4ccda 100644
--- a/chrome/browser/ui/sync/one_click_signin_sync_starter.h
+++ b/chrome/browser/ui/sync/one_click_signin_sync_starter.h
@@ -13,6 +13,7 @@
 #include "chrome/browser/ui/browser_list_observer.h"
 #include "chrome/browser/ui/host_desktop.h"
 #include "chrome/browser/ui/sync/profile_signin_confirmation_helper.h"
+#include "chrome/browser/ui/sync/sync_promo_ui.h"
 
 class Browser;
 class ProfileSyncService;
@@ -65,7 +66,8 @@
                             const std::string& password,
                             StartSyncMode start_mode,
                             bool force_same_tab_navigation,
-                            ConfirmationRequired display_confirmation);
+                            ConfirmationRequired display_confirmation,
+                            SyncPromoUI::Source source);
 
   // chrome::BrowserListObserver override.
   virtual void OnBrowserRemoved(Browser* browser) OVERRIDE;
@@ -165,6 +167,7 @@
   chrome::HostDesktopType desktop_type_;
   bool force_same_tab_navigation_;
   ConfirmationRequired confirmation_required_;
+  SyncPromoUI::Source source_;
   base::WeakPtrFactory<OneClickSigninSyncStarter> weak_pointer_factory_;
 
 #if defined(ENABLE_CONFIGURATION_POLICY)
diff --git a/chrome/browser/ui/sync/profile_signin_confirmation_helper.cc b/chrome/browser/ui/sync/profile_signin_confirmation_helper.cc
index 38bc300..4d5dcda 100644
--- a/chrome/browser/ui/sync/profile_signin_confirmation_helper.cc
+++ b/chrome/browser/ui/sync/profile_signin_confirmation_helper.cc
@@ -68,27 +68,6 @@
   return has_bookmarks;
 }
 
-bool HasSyncedExtensions(Profile* profile) {
-  extensions::ExtensionSystem* system =
-      extensions::ExtensionSystem::Get(profile);
-  if (system && system->extension_service()) {
-    const ExtensionSet* extensions = system->extension_service()->extensions();
-    for (ExtensionSet::const_iterator iter = extensions->begin();
-         iter != extensions->end(); ++iter) {
-      // The webstore is synced so that it stays put on the new tab
-      // page, but since it's installed by default we don't want to
-      // consider it when determining if the profile is dirty.
-      if (extensions::sync_helper::IsSyncable(iter->get()) &&
-          (*iter)->id() != extension_misc::kWebStoreAppId) {
-        VLOG(1) << "ProfileSigninConfirmationHelper: "
-                << "profile contains a synced extension: " << (*iter)->id();
-        return true;
-      }
-    }
-  }
-  return false;
-}
-
 // Helper functions for Chrome profile signin.
 class ProfileSigninConfirmationHelper
     : public base::RefCounted<ProfileSigninConfirmationHelper> {
@@ -217,6 +196,28 @@
   return has_been_shutdown;
 }
 
+bool HasSyncedExtensions(Profile* profile) {
+  extensions::ExtensionSystem* system =
+      extensions::ExtensionSystem::Get(profile);
+  if (system && system->extension_service()) {
+    const ExtensionSet* extensions = system->extension_service()->extensions();
+    for (ExtensionSet::const_iterator iter = extensions->begin();
+         iter != extensions->end(); ++iter) {
+      // The webstore is synced so that it stays put on the new tab
+      // page, but since it's installed by default we don't want to
+      // consider it when determining if the profile is dirty.
+      if (extensions::sync_helper::IsSyncable(iter->get()) &&
+          (*iter)->id() != extension_misc::kWebStoreAppId &&
+          (*iter)->id() != extension_misc::kChromeAppId) {
+        VLOG(1) << "ProfileSigninConfirmationHelper: "
+                << "profile contains a synced extension: " << (*iter)->id();
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
 void CheckShouldPromptForNewProfile(
     Profile* profile,
     const base::Callback<void(bool)>& return_result) {
diff --git a/chrome/browser/ui/sync/profile_signin_confirmation_helper.h b/chrome/browser/ui/sync/profile_signin_confirmation_helper.h
index 073a579..d0d0c21 100644
--- a/chrome/browser/ui/sync/profile_signin_confirmation_helper.h
+++ b/chrome/browser/ui/sync/profile_signin_confirmation_helper.h
@@ -23,6 +23,10 @@
 // profile was created.
 bool HasBeenShutdown(Profile* profile);
 
+// Determines whether there are any synced extensions installed (that
+// shouldn't be ignored).
+bool HasSyncedExtensions(Profile* profile);
+
 // Determines whether the user should be prompted to create a new
 // profile before signin.
 void CheckShouldPromptForNewProfile(
diff --git a/chrome/browser/ui/sync/profile_signin_confirmation_helper_browsertest.cc b/chrome/browser/ui/sync/profile_signin_confirmation_helper_browsertest.cc
index c250511..41a9416 100644
--- a/chrome/browser/ui/sync/profile_signin_confirmation_helper_browsertest.cc
+++ b/chrome/browser/ui/sync/profile_signin_confirmation_helper_browsertest.cc
@@ -35,3 +35,8 @@
 #endif
   EXPECT_FALSE(ui::HasBeenShutdown(browser()->profile()));
 }
+
+IN_PROC_BROWSER_TEST_F(ProfileSigninConfirmationHelperBrowserTest,
+                       HasNoSyncedExtensions) {
+  EXPECT_FALSE(ui::HasSyncedExtensions(browser()->profile()));
+}
diff --git a/chrome/browser/ui/sync/sync_promo_ui.cc b/chrome/browser/ui/sync/sync_promo_ui.cc
new file mode 100644
index 0000000..83585b6
--- /dev/null
+++ b/chrome/browser/ui/sync/sync_promo_ui.cc
@@ -0,0 +1,275 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/sync/sync_promo_ui.h"
+
+#include "base/command_line.h"
+#include "base/prefs/pref_service.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/first_run/first_run.h"
+#include "chrome/browser/google/google_util.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_info_cache.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/signin/signin_manager.h"
+#include "chrome/browser/signin/signin_manager_factory.h"
+#include "chrome/browser/sync/profile_sync_service.h"
+#include "chrome/browser/sync/profile_sync_service_factory.h"
+#include "chrome/browser/ui/webui/options/core_options_handler.h"
+#include "chrome/browser/ui/webui/sync_promo/sync_promo_trial.h"
+#include "chrome/browser/ui/webui/theme_source.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/net/url_util.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/url_constants.h"
+#include "components/user_prefs/pref_registry_syncable.h"
+#include "content/public/browser/url_data_source.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_ui.h"
+#include "content/public/browser/web_ui_data_source.h"
+#include "google_apis/gaia/gaia_urls.h"
+#include "grit/browser_resources.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "net/base/escape.h"
+#include "net/base/network_change_notifier.h"
+#include "net/base/url_util.h"
+#include "ui/base/l10n/l10n_util.h"
+
+using content::WebContents;
+
+namespace {
+
+const char kStringsJsFile[] = "strings.js";
+const char kSyncPromoJsFile[] = "sync_promo.js";
+
+const char kSyncPromoQueryKeyAutoClose[] = "auto_close";
+const char kSyncPromoQueryKeyContinue[] = "continue";
+const char kSyncPromoQueryKeySource[] = "source";
+
+// Gaia cannot support about:blank as a continue URL, so using a hosted blank
+// page instead.
+const char kSyncLandingUrlPrefix[] =
+    "https://www.google.com/intl/%s/chrome/blank.html";
+
+// The maximum number of times we want to show the sync promo at startup.
+const int kSyncPromoShowAtStartupMaximum = 10;
+
+// Forces the web based signin flow when set.
+bool g_force_web_based_signin_flow = false;
+
+// Checks we want to show the sync promo for the given brand.
+bool AllowPromoAtStartupForCurrentBrand() {
+  std::string brand;
+  google_util::GetBrand(&brand);
+
+  if (brand.empty())
+    return true;
+
+  if (google_util::IsInternetCafeBrandCode(brand))
+    return false;
+
+  // Enable for both organic and distribution.
+  return true;
+}
+
+}  // namespace
+
+// static
+bool SyncPromoUI::HasShownPromoAtStartup(Profile* profile) {
+  return profile->GetPrefs()->HasPrefPath(prefs::kSyncPromoStartupCount);
+}
+
+// static
+bool SyncPromoUI::ShouldShowSyncPromo(Profile* profile) {
+#if defined(OS_CHROMEOS)
+  // There's no need to show the sync promo on cros since cros users are logged
+  // into sync already.
+  return false;
+#else
+
+  // Don't bother if we don't have any kind of network connection.
+  if (net::NetworkChangeNotifier::IsOffline())
+    return false;
+
+  // Don't show if the profile is an incognito.
+  if (profile->IsOffTheRecord())
+    return false;
+
+  // Don't show for managed profiles.
+  if (profile->GetPrefs()->GetBoolean(prefs::kProfileIsManaged))
+    return false;
+
+  // Display the signin promo if the user is not signed in.
+  SigninManager* signin = SigninManagerFactory::GetForProfile(
+      profile->GetOriginalProfile());
+  return !signin->AuthInProgress() && signin->IsSigninAllowed() &&
+      signin->GetAuthenticatedUsername().empty();
+#endif
+}
+
+// static
+void SyncPromoUI::RegisterUserPrefs(
+    user_prefs::PrefRegistrySyncable* registry) {
+  registry->RegisterIntegerPref(
+      prefs::kSyncPromoStartupCount,
+      0,
+      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+  registry->RegisterBooleanPref(
+      prefs::kSyncPromoUserSkipped,
+      false,
+      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+  registry->RegisterBooleanPref(
+      prefs::kSyncPromoShowOnFirstRunAllowed,
+      true,
+      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+  registry->RegisterBooleanPref(
+      prefs::kSyncPromoShowNTPBubble,
+      false,
+      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+  registry->RegisterStringPref(
+      prefs::kSyncPromoErrorMessage,
+      std::string(),
+      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+}
+
+// static
+bool SyncPromoUI::ShouldShowSyncPromoAtStartup(Profile* profile,
+                                               bool is_new_profile) {
+  DCHECK(profile);
+
+  if (!ShouldShowSyncPromo(profile))
+    return false;
+
+  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+  if (command_line.HasSwitch(switches::kNoFirstRun))
+    is_new_profile = false;
+
+  if (!is_new_profile) {
+    if (!HasShownPromoAtStartup(profile))
+      return false;
+  }
+
+  if (HasUserSkippedSyncPromo(profile))
+    return false;
+
+  // For Chinese users skip the sync promo.
+  if (g_browser_process->GetApplicationLocale() == "zh-CN")
+    return false;
+
+  PrefService* prefs = profile->GetPrefs();
+  int show_count = prefs->GetInteger(prefs::kSyncPromoStartupCount);
+  if (show_count >= kSyncPromoShowAtStartupMaximum)
+    return false;
+
+  // This pref can be set in the master preferences file to allow or disallow
+  // showing the sync promo at startup.
+  if (prefs->HasPrefPath(prefs::kSyncPromoShowOnFirstRunAllowed))
+    return prefs->GetBoolean(prefs::kSyncPromoShowOnFirstRunAllowed);
+
+  // For now don't show the promo for some brands.
+  if (!AllowPromoAtStartupForCurrentBrand())
+    return false;
+
+  // Default to show the promo for Google Chrome builds.
+#if defined(GOOGLE_CHROME_BUILD)
+  return true;
+#else
+  return false;
+#endif
+}
+
+void SyncPromoUI::DidShowSyncPromoAtStartup(Profile* profile) {
+  int show_count = profile->GetPrefs()->GetInteger(
+      prefs::kSyncPromoStartupCount);
+  show_count++;
+  profile->GetPrefs()->SetInteger(prefs::kSyncPromoStartupCount, show_count);
+}
+
+bool SyncPromoUI::HasUserSkippedSyncPromo(Profile* profile) {
+  return profile->GetPrefs()->GetBoolean(prefs::kSyncPromoUserSkipped);
+}
+
+void SyncPromoUI::SetUserSkippedSyncPromo(Profile* profile) {
+  profile->GetPrefs()->SetBoolean(prefs::kSyncPromoUserSkipped, true);
+}
+
+// static
+std::string SyncPromoUI::GetSyncLandingURL(const char* option, int value) {
+  const std::string& locale = g_browser_process->GetApplicationLocale();
+  std::string url = base::StringPrintf(kSyncLandingUrlPrefix, locale.c_str());
+  base::StringAppendF(&url, "?%s=%d", option, value);
+  return url;
+}
+
+// static
+GURL SyncPromoUI::GetSyncPromoURL(Source source, bool auto_close) {
+  DCHECK_NE(SOURCE_UNKNOWN, source);
+
+  std::string url_string;
+
+  // Build a Gaia-based URL that can be used to sign the user into chrome.
+  // There are required request parameters:
+  //
+  //  - tell Gaia which service the user is signing into.  In this case,
+  //    a chrome sign in uses the service "chromiumsync"
+  //  - provide a continue URL.  This is the URL that Gaia will redirect to
+  //    once the sign is complete.
+  //
+  // The continue URL includes a source parameter that can be extracted using
+  // the function GetSourceForSyncPromoURL() below.  This is used to know
+  // which of the chrome sign in access points was used to sign the user in.
+  // See OneClickSigninHelper for details.
+  url_string = GaiaUrls::GetInstance()->service_login_url();
+  url_string.append("?service=chromiumsync&sarp=1");
+
+  std::string continue_url = GetSyncLandingURL(
+      kSyncPromoQueryKeySource, static_cast<int>(source));
+
+  base::StringAppendF(&url_string, "&%s=%s", kSyncPromoQueryKeyContinue,
+                      net::EscapeQueryParamValue(
+                          continue_url, false).c_str());
+
+  return GURL(url_string);
+}
+
+// static
+GURL SyncPromoUI::GetNextPageURLForSyncPromoURL(const GURL& url) {
+  std::string value;
+  if (net::GetValueForKeyInQuery(url, kSyncPromoQueryKeyContinue, &value))
+    return GURL(value);
+
+  return GURL();
+}
+
+// static
+SyncPromoUI::Source SyncPromoUI::GetSourceForSyncPromoURL(const GURL& url) {
+  std::string value;
+  if (net::GetValueForKeyInQuery(url, kSyncPromoQueryKeySource, &value)) {
+    int source = 0;
+    if (base::StringToInt(value, &source) && source >= SOURCE_START_PAGE &&
+        source < SOURCE_UNKNOWN) {
+      return static_cast<Source>(source);
+    }
+  }
+  return SOURCE_UNKNOWN;
+}
+
+// static
+bool SyncPromoUI::IsContinueUrlForWebBasedSigninFlow(const GURL& url) {
+  GURL::Replacements replacements;
+  replacements.ClearQuery();
+  const std::string& locale = g_browser_process->GetApplicationLocale();
+  return url.ReplaceComponents(replacements) ==
+      GURL(base::StringPrintf(kSyncLandingUrlPrefix, locale.c_str()));
+}
+
+// static
+void SyncPromoUI::ForceWebBasedSigninFlowForTesting(bool force) {
+  g_force_web_based_signin_flow = force;
+}
diff --git a/chrome/browser/ui/sync/sync_promo_ui.h b/chrome/browser/ui/sync/sync_promo_ui.h
new file mode 100644
index 0000000..48d2f1b
--- /dev/null
+++ b/chrome/browser/ui/sync/sync_promo_ui.h
@@ -0,0 +1,87 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_SYNC_SYNC_PROMO_UI_H_
+#define CHROME_BROWSER_UI_SYNC_SYNC_PROMO_UI_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+
+class GURL;
+class Profile;
+
+namespace user_prefs {
+class PrefRegistrySyncable;
+}
+
+// Static helper functions useful for chrome sign in.
+class SyncPromoUI {
+ public:
+  // Please keep this in sync with enums in sync_promo_trial.cc.
+  enum Source {
+    SOURCE_START_PAGE = 0, // This must be first.
+    SOURCE_NTP_LINK,
+    SOURCE_MENU,
+    SOURCE_SETTINGS,
+    SOURCE_EXTENSION_INSTALL_BUBBLE,
+    SOURCE_WEBSTORE_INSTALL,
+    SOURCE_APP_LAUNCHER,
+    SOURCE_APPS_PAGE_LINK,
+    SOURCE_UNKNOWN, // This must be last.
+  };
+
+  // Returns true if the sync promo should be visible.
+  // |profile| is the profile of the tab the promo would be shown on.
+  static bool ShouldShowSyncPromo(Profile* profile);
+
+  // Returns true if we should show the sync promo at startup.
+  static bool ShouldShowSyncPromoAtStartup(Profile* profile,
+                                           bool is_new_profile);
+
+  // Called when the sync promo has been shown so that we can keep track
+  // of the number of times we've displayed it.
+  static void DidShowSyncPromoAtStartup(Profile* profile);
+
+  // Returns true if a user has seen the sync promo at startup previously.
+  static bool HasShownPromoAtStartup(Profile* profile);
+
+  // Returns true if the user has previously skipped the sync promo.
+  static bool HasUserSkippedSyncPromo(Profile* profile);
+
+  // Registers the fact that the user has skipped the sync promo.
+  static void SetUserSkippedSyncPromo(Profile* profile);
+
+  // Registers the preferences the Sync Promo UI needs.
+  static void RegisterUserPrefs(user_prefs::PrefRegistrySyncable* registry);
+
+  // Gets the sync landing page URL.
+  static std::string GetSyncLandingURL(const char* option, int value);
+
+  // Returns the sync promo URL wth the given arguments in the query.
+  // |source| identifies from where the sync promo is being called, and is used
+  // to record sync promo UMA stats in the context of the source.
+  // |auto_close| whether to close the sync promo automatically when done.
+  static GURL GetSyncPromoURL(Source source, bool auto_close);
+
+  // Gets the next page URL from the query portion of the sync promo URL.
+  static GURL GetNextPageURLForSyncPromoURL(const GURL& url);
+
+  // Gets the source from the query portion of the sync promo URL.
+  // The source identifies from where the sync promo was opened.
+  static Source GetSourceForSyncPromoURL(const GURL& url);
+
+  // Returns true if the given URL is the standard continue URL used with the
+  // sync promo when the web-based flow is enabled.  The query parameters
+  // of the URL are ignored for this comparison.
+  static bool IsContinueUrlForWebBasedSigninFlow(const GURL& url);
+
+  // Forces UseWebBasedSigninFlow() to return true when set; used in tests only.
+  static void ForceWebBasedSigninFlowForTesting(bool force);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(SyncPromoUI);
+};
+
+#endif  // CHROME_BROWSER_UI_SYNC_SYNC_PROMO_UI_H_
diff --git a/chrome/browser/ui/tab_contents/core_tab_helper.cc b/chrome/browser/ui/tab_contents/core_tab_helper.cc
index f8dc42e..52106b8 100644
--- a/chrome/browser/ui/tab_contents/core_tab_helper.cc
+++ b/chrome/browser/ui/tab_contents/core_tab_helper.cc
@@ -4,8 +4,10 @@
 
 #include "chrome/browser/ui/tab_contents/core_tab_helper.h"
 
+#include "base/command_line.h"
 #include "base/metrics/histogram.h"
 #include "chrome/browser/renderer_host/web_cache_manager.h"
+#include "chrome/common/chrome_switches.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
@@ -116,20 +118,32 @@
 void CoreTabHelper::WebContentsDestroyed(WebContents* web_contents) {
   // OnCloseStarted isn't called in unit tests.
   if (!close_start_time_.is_null()) {
-    base::TimeTicks now = base::TimeTicks::Now();
-    base::TimeDelta close_time = now - close_start_time_;
-    UMA_HISTOGRAM_TIMES("Tab.Close", close_time);
+    bool fast_tab_close_enabled = CommandLine::ForCurrentProcess()->HasSwitch(
+        switches::kEnableFastUnload);
 
-    base::TimeTicks unload_start_time = close_start_time_;
-    base::TimeTicks unload_end_time = now;
-    if (!before_unload_end_time_.is_null())
-      unload_start_time = before_unload_end_time_;
-    if (!unload_detached_start_time_.is_null())
-      unload_end_time = unload_detached_start_time_;
-    base::TimeDelta unload_time = unload_end_time - unload_start_time;
-    UMA_HISTOGRAM_TIMES("Tab.Close.UnloadTime", unload_time);
+    if (fast_tab_close_enabled) {
+      base::TimeTicks now = base::TimeTicks::Now();
+      base::TimeDelta close_time = now - close_start_time_;
+      UMA_HISTOGRAM_TIMES("Tab.Close", close_time);
 
+      base::TimeTicks unload_start_time = close_start_time_;
+      base::TimeTicks unload_end_time = now;
+      if (!before_unload_end_time_.is_null())
+        unload_start_time = before_unload_end_time_;
+      if (!unload_detached_start_time_.is_null())
+        unload_end_time = unload_detached_start_time_;
+      base::TimeDelta unload_time = unload_end_time - unload_start_time;
+      UMA_HISTOGRAM_TIMES("Tab.Close.UnloadTime", unload_time);
+    } else {
+      base::TimeTicks now = base::TimeTicks::Now();
+      base::TimeTicks unload_start_time = close_start_time_;
+      if (!before_unload_end_time_.is_null())
+        unload_start_time = before_unload_end_time_;
+      UMA_HISTOGRAM_TIMES("Tab.Close", now - close_start_time_);
+      UMA_HISTOGRAM_TIMES("Tab.Close.UnloadTime", now - unload_start_time);
+    }
   }
+
 }
 
 void CoreTabHelper::BeforeUnloadFired(const base::TimeTicks& proceed_time) {
diff --git a/chrome/browser/ui/tab_contents/core_tab_helper.h b/chrome/browser/ui/tab_contents/core_tab_helper.h
index e5a37dd..c8e6782 100644
--- a/chrome/browser/ui/tab_contents/core_tab_helper.h
+++ b/chrome/browser/ui/tab_contents/core_tab_helper.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_UI_TAB_CONTENTS_CORE_TAB_HELPER_H_
 #define CHROME_BROWSER_UI_TAB_CONTENTS_CORE_TAB_HELPER_H_
 
-#include "base/time.h"
+#include "base/time/time.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/browser/web_contents_user_data.h"
 
diff --git a/chrome/browser/ui/tests/ui_gfx_image_unittest.mm b/chrome/browser/ui/tests/ui_gfx_image_unittest.mm
index e025ccc..4e45cf2 100644
--- a/chrome/browser/ui/tests/ui_gfx_image_unittest.mm
+++ b/chrome/browser/ui/tests/ui_gfx_image_unittest.mm
@@ -5,7 +5,7 @@
 #import <AppKit/AppKit.h>
 
 #import "base/mac/mac_util.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkBitmap.h"
@@ -45,7 +45,7 @@
 }
 
 TEST_F(UiGfxImageTest, ImageView) {
-  scoped_nsobject<NSImageView> image_view(
+  base::scoped_nsobject<NSImageView> image_view(
       [[NSImageView alloc] initWithFrame:NSMakeRect(10, 10, 25, 25)]);
   [[test_window() contentView] addSubview:image_view];
   [test_window() orderFront:nil];
diff --git a/chrome/browser/ui/toolbar/back_forward_menu_model_unittest.cc b/chrome/browser/ui/toolbar/back_forward_menu_model_unittest.cc
index dee248b..4f2af32 100644
--- a/chrome/browser/ui/toolbar/back_forward_menu_model_unittest.cc
+++ b/chrome/browser/ui/toolbar/back_forward_menu_model_unittest.cc
@@ -8,7 +8,7 @@
 #include "base/strings/string16.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/favicon/favicon_service_factory.h"
 #include "chrome/browser/history/history_service.h"
 #include "chrome/browser/history/history_service_factory.h"
@@ -499,8 +499,7 @@
 TEST_F(BackFwdMenuModelTest, FaviconLoadTest) {
   profile()->CreateHistoryService(true, false);
   profile()->CreateFaviconService();
-  Browser::CreateParams native_params(profile(),
-                                      chrome::HOST_DESKTOP_TYPE_NATIVE);
+  Browser::CreateParams native_params(profile(), chrome::GetActiveDesktop());
   scoped_ptr<Browser> browser(
       chrome::CreateBrowserWithTestWindowForParams(&native_params));
   FaviconDelegate favicon_delegate;
diff --git a/chrome/browser/ui/toolbar/recent_tabs_builder_test_helper.h b/chrome/browser/ui/toolbar/recent_tabs_builder_test_helper.h
index 862f4b7..63f4761 100644
--- a/chrome/browser/ui/toolbar/recent_tabs_builder_test_helper.h
+++ b/chrome/browser/ui/toolbar/recent_tabs_builder_test_helper.h
@@ -8,7 +8,7 @@
 #include <vector>
 
 #include "base/strings/string16.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/sessions/session_id.h"
 
 namespace browser_sync {
diff --git a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
index aed88a7..d32cb3c 100644
--- a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
+++ b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h"
 
 #include "base/bind.h"
+#include "base/metrics/histogram.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
@@ -112,6 +113,14 @@
 
 }  // namespace
 
+enum RecentTabAction {
+  LOCAL_SESSION_TAB = 0,
+  OTHER_DEVICE_TAB,
+  RESTORE_WINDOW,
+  SHOW_MORE,
+  LIMIT_RECENT_TAB_ACTION
+};
+
 // An element in |RecentTabsSubMenuModel::tab_navigation_items_| that stores
 // the navigation information of a local or foreign tab required to restore the
 // tab.
@@ -120,9 +129,11 @@
 
   TabNavigationItem(const std::string& session_tag,
                     const SessionID::id_type& tab_id,
+                    const string16& title,
                     const GURL& url)
       : session_tag(session_tag),
         tab_id(tab_id),
+        title(title),
         url(url) {}
 
   // For use by std::set for sorting.
@@ -132,6 +143,7 @@
 
   std::string session_tag;  // Empty for local tabs, non-empty for foreign tabs.
   SessionID::id_type tab_id;  // -1 for invalid, >= 0 otherwise.
+  string16 title;
   GURL url;
 };
 
@@ -205,6 +217,8 @@
 
 void RecentTabsSubMenuModel::ExecuteCommand(int command_id, int event_flags) {
   if (command_id == IDC_SHOW_HISTORY) {
+    UMA_HISTOGRAM_ENUMERATION("WrenchMenu.RecentTabsSubMenu", SHOW_MORE,
+                              LIMIT_RECENT_TAB_ACTION);
     // We show all "other devices" on the history page.
     chrome::ExecuteCommandWithDisposition(browser_, IDC_SHOW_HISTORY,
         ui::DispositionFromEventFlags(event_flags));
@@ -233,6 +247,8 @@
 
     if (item.session_tag.empty()) {  // Restore tab of local session.
       if (service && delegate) {
+        UMA_HISTOGRAM_ENUMERATION("WrenchMenu.RecentTabsSubMenu",
+                                  LOCAL_SESSION_TAB, LIMIT_RECENT_TAB_ACTION);
         service->RestoreEntryById(delegate, item.tab_id,
                                   browser_->host_desktop_type(), disposition);
       }
@@ -245,6 +261,8 @@
         return;
       if (tab->navigations.empty())
         return;
+      UMA_HISTOGRAM_ENUMERATION("WrenchMenu.RecentTabsSubMenu",
+                                OTHER_DEVICE_TAB, LIMIT_RECENT_TAB_ACTION);
       SessionRestore::RestoreForeignSessionTab(
           browser_->tab_strip_model()->GetActiveWebContents(),
           *tab, disposition);
@@ -255,6 +273,8 @@
       int model_idx = CommandIdToWindowModelIndex(command_id);
       DCHECK(model_idx >= 0 &&
              model_idx < static_cast<int>(window_items_.size()));
+      UMA_HISTOGRAM_ENUMERATION("WrenchMenu.RecentTabsSubMenu", RESTORE_WINDOW,
+                                LIMIT_RECENT_TAB_ACTION);
       service->RestoreEntryById(delegate, window_items_[model_idx],
                                 browser_->host_desktop_type(), disposition);
     }
@@ -281,6 +301,22 @@
   return 320;
 }
 
+bool RecentTabsSubMenuModel::GetURLAndTitleForItemAtIndex(
+    int index,
+    std::string* url,
+    string16* title) const {
+  int command_id = GetCommandIdAt(index);
+  if (IsTabModelCommandId(command_id)) {
+    int model_idx = CommandIdToTabModelIndex(command_id);
+    DCHECK(model_idx >= 0 &&
+           model_idx < static_cast<int>(tab_navigation_items_.size()));
+    *url = tab_navigation_items_[model_idx].url.possibly_invalid_spec();
+    *title = tab_navigation_items_[model_idx].title;
+    return true;
+  }
+  return false;
+}
+
 void RecentTabsSubMenuModel::Build() {
   // The menu contains:
   // - Recently closed tabs header, then list of tabs, then separator
@@ -299,6 +335,12 @@
   ListValue recently_closed_list;
   TabRestoreService* service =
       TabRestoreServiceFactory::GetForProfile(browser_->profile());
+  if (service) {
+    // This does nothing if the tabs have already been loaded or they
+    // shouldn't be loaded.
+    service->LoadTabsFromLastSession();
+  }
+
   if (!service || service->entries().size() == 0) {
     // This is to show a disabled restore tab entry with the accelerator to
     // teach users about this command.
@@ -414,7 +456,7 @@
     int session_id,
     const string16& title,
     const GURL& url) {
-  TabNavigationItem item("", session_id, url);
+  TabNavigationItem item("", session_id, title, url);
   int command_id = TabModelIndexToCommandId(tab_navigation_items_.size());
   // There may be no tab title, in which case, use the url as tab title.
   AddItem(command_id, title.empty() ? UTF8ToUTF16(item.url.spec()) : title);
@@ -428,6 +470,7 @@
   const sessions::SerializedNavigationEntry& current_navigation =
       tab.navigations.at(tab.normalized_navigation_index());
   TabNavigationItem item(session_tag, tab.tab_id.id(),
+                         current_navigation.title(),
                          current_navigation.virtual_url());
   int command_id = TabModelIndexToCommandId(tab_navigation_items_.size());
   // There may be no tab title, in which case, use the url as tab title.
diff --git a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h
index 2a455f0..62d9a07 100644
--- a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h
+++ b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h
@@ -56,6 +56,9 @@
   virtual const gfx::Font* GetLabelFontAt(int index) const OVERRIDE;
 
   int GetMaxWidthForItemAtIndex(int item_index) const;
+  bool GetURLAndTitleForItemAtIndex(int index,
+                                    std::string* url,
+                                    string16* title) const;
 
   // Command Id for recently closed items header or disabled item to which the
   // accelerator string will be appended.
diff --git a/chrome/browser/ui/toolbar/toolbar_model_impl.cc b/chrome/browser/ui/toolbar/toolbar_model_impl.cc
index 5c6d8bc..8ecf05c 100644
--- a/chrome/browser/ui/toolbar/toolbar_model_impl.cc
+++ b/chrome/browser/ui/toolbar/toolbar_model_impl.cc
@@ -270,6 +270,12 @@
       (entry->GetSSL().security_style == content::SECURITY_STYLE_UNKNOWN))
     return search_terms;
 
+  // If the URL is using a Google base URL specified via the command line, skip
+  // the security check below.
+  if (entry &&
+      google_util::StartsWithCommandLineGoogleBaseURL(entry->GetVirtualURL()))
+    return search_terms;
+
   // Otherwise, extract search terms for HTTPS pages that do not have a security
   // error.
   ToolbarModel::SecurityLevel security_level = GetSecurityLevel();
diff --git a/chrome/browser/ui/toolbar/toolbar_model_unittest.cc b/chrome/browser/ui/toolbar/toolbar_model_unittest.cc
index f8f8226..c3da77c 100644
--- a/chrome/browser/ui/toolbar/toolbar_model_unittest.cc
+++ b/chrome/browser/ui/toolbar/toolbar_model_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/autocomplete/autocomplete_classifier_factory.h"
 #include "chrome/browser/search/search.h"
+#include "chrome/browser/search_engines/search_terms_data.h"
 #include "chrome/browser/search_engines/template_url.h"
 #include "chrome/browser/search_engines/template_url_service.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
@@ -182,6 +183,7 @@
       profile(), &TemplateURLServiceFactory::BuildInstanceFor);
   AutocompleteClassifierFactory::GetInstance()->SetTestingFactoryAndUse(
       profile(), &AutocompleteClassifierFactory::BuildInstanceFor);
+  UIThreadSearchTermsData::SetGoogleBaseURL("http://google.com/");
 }
 
 void ToolbarModelTest::ResetDefaultTemplateURL() {
@@ -203,7 +205,7 @@
 void ToolbarModelTest::ResetTemplateURLForInstant(const GURL& instant_url) {
   TemplateURLData data;
   data.short_name = ASCIIToUTF16("Google");
-  data.SetURL("http://google.com/search?q={searchTerms}");
+  data.SetURL("{google:baseURL}search?q={searchTerms}");
   data.instant_url = instant_url.spec();
   data.search_terms_replacement_key = "{google:instantExtendedEnabledKey}";
   TemplateURL* search_template_url = new TemplateURL(profile(), data);
@@ -254,16 +256,13 @@
 
 // Test that we don't replace any URLs when the query extraction is disabled.
 TEST_F(ToolbarModelTest, ShouldDisplayURLQueryExtractionDisabled) {
-  ASSERT_FALSE(chrome::IsQueryExtractionEnabled(profile()))
+  ASSERT_FALSE(chrome::IsQueryExtractionEnabled())
       << "This test expects query extraction to be disabled.";
-  ResetDefaultTemplateURL();
   AddTab(browser(), GURL(content::kAboutBlankURL));
   for (size_t i = 0; i < arraysize(test_items); ++i) {
     const TestItem& test_item = test_items[i];
-    NavigateAndCheckText(test_item.url,
-                         test_item.expected_text,
-                         test_item.expected_replace_text_inactive,
-                         false,
+    NavigateAndCheckText(test_item.url, test_item.expected_text,
+                         test_item.expected_replace_text_inactive, false,
                          test_item.should_display);
   }
 }
@@ -271,15 +270,12 @@
 // Test that we replace URLs when the query extraction API is enabled.
 TEST_F(ToolbarModelTest, ShouldDisplayURLQueryExtractionEnabled) {
   chrome::EnableInstantExtendedAPIForTesting();
-  ResetDefaultTemplateURL();
   AddTab(browser(), GURL(content::kAboutBlankURL));
   for (size_t i = 0; i < arraysize(test_items); ++i) {
     const TestItem& test_item = test_items[i];
-    NavigateAndCheckText(test_item.url,
-                         test_item.expected_text,
+    NavigateAndCheckText(test_item.url, test_item.expected_text,
                          test_item.expected_replace_text_active,
-                         test_item.would_replace,
-                         test_item.should_display);
+                         test_item.would_replace, test_item.should_display);
   }
 }
 
@@ -307,3 +303,30 @@
       content::SECURITY_STYLE_UNKNOWN;
   EXPECT_FALSE(toolbar_model->WouldReplaceSearchURLWithSearchTerms());
 }
+
+// When the Google base URL is overridden on the command line, we should extract
+// search terms from URLs that start with that base URL even when they're not
+// secure.
+TEST_F(ToolbarModelTest, GoogleBaseURL) {
+  chrome::EnableInstantExtendedAPIForTesting();
+  AddTab(browser(), GURL(content::kAboutBlankURL));
+
+  // If the Google base URL wasn't specified on the command line, then if it's
+  // HTTP, we should not extract search terms.
+  UIThreadSearchTermsData::SetGoogleBaseURL("http://www.foo.com/");
+  NavigateAndCheckText(
+      GURL("http://www.foo.com/search?q=tractor+supply&espv=1"),
+      ASCIIToUTF16("www.foo.com/search?q=tractor+supply&espv=1"),
+      ASCIIToUTF16("www.foo.com/search?q=tractor+supply&espv=1"), false,
+      true);
+
+  // The same URL, when specified on the command line, should allow search term
+  // extraction.
+  UIThreadSearchTermsData::SetGoogleBaseURL(std::string());
+  CommandLine::ForCurrentProcess()->AppendSwitchASCII(switches::kGoogleBaseURL,
+                                                      "http://www.foo.com/");
+  NavigateAndCheckText(
+      GURL("http://www.foo.com/search?q=tractor+supply&espv=1"),
+      ASCIIToUTF16("www.foo.com/search?q=tractor+supply&espv=1"),
+      ASCIIToUTF16("tractor supply"), true, true);
+}
diff --git a/chrome/browser/ui/toolbar/wrench_menu_model.cc b/chrome/browser/ui/toolbar/wrench_menu_model.cc
index f742d75..ab5998f 100644
--- a/chrome/browser/ui/toolbar/wrench_menu_model.cc
+++ b/chrome/browser/ui/toolbar/wrench_menu_model.cc
@@ -8,7 +8,6 @@
 #include <cmath>
 
 #include "base/command_line.h"
-#include "base/i18n/number_formatting.h"
 #include "base/prefs/pref_service.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
@@ -278,7 +277,6 @@
 #elif defined(OS_WIN)
          command_id == IDC_PIN_TO_START_SCREEN ||
 #endif
-         command_id == IDC_VIEW_BACKGROUND_PAGES ||
          command_id == IDC_UPGRADE_DIALOG ||
          command_id == IDC_SHOW_SIGNIN;
 }
@@ -308,12 +306,6 @@
       return l10n_util::GetStringUTF16(string_id);
     }
 #endif
-    case IDC_VIEW_BACKGROUND_PAGES: {
-      string16 num_background_pages = base::FormatNumber(
-          TaskManager::GetBackgroundPageCount());
-      return l10n_util::GetStringFUTF16(IDS_VIEW_BACKGROUND_PAGES,
-                                        num_background_pages);
-    }
     case IDC_UPGRADE_DIALOG:
       return GetUpgradeDialogMenuItemName();
     case IDC_SHOW_SIGNIN:
@@ -428,8 +420,6 @@
 #endif
   } else if (command_id == IDC_UPGRADE_DIALOG) {
     return UpgradeDetector::GetInstance()->notify_upgrade();
-  } else if (command_id == IDC_VIEW_BACKGROUND_PAGES) {
-    return TaskManager::GetBackgroundPageCount() > 0;
   }
   return true;
 }
@@ -601,19 +591,12 @@
                              IDS_TOGGLE_REQUEST_TABLET_SITE);
 #endif
 
-// On ChromeOS-Touch, we don't want the about/background pages menu options.
+// On ChromeOS-Touch, we don't want the about menu option.
 #if defined(OS_CHROMEOS)
   if (!is_new_menu)
 #endif
   {
     AddItem(IDC_ABOUT, l10n_util::GetStringUTF16(IDS_ABOUT));
-    // We use the task manager to show background pages.
-    if (chrome::CanOpenTaskManager()) {
-      string16 num_background_pages = base::FormatNumber(
-          TaskManager::GetBackgroundPageCount());
-      AddItem(IDC_VIEW_BACKGROUND_PAGES, l10n_util::GetStringFUTF16(
-          IDS_VIEW_BACKGROUND_PAGES, num_background_pages));
-    }
   }
 
   if (browser_defaults::kShowUpgradeMenuItem)
@@ -681,8 +664,10 @@
     if (error->HasMenuItem()) {
       // Don't add a signin error if it's already being displayed elsewhere.
 #if !defined(OS_CHROMEOS)
-      if (error == signin_ui_util::GetSignedInServiceError(
-                       browser_->profile()->GetOriginalProfile())) {
+      std::vector<GlobalError*> errors =
+          signin_ui_util::GetSignedInServiceErrors(
+              browser_->profile()->GetOriginalProfile());
+      if (std::find(errors.begin(), errors.end(), error) != errors.end()) {
         MenuModel* model = this;
         int index = 0;
         if (MenuModel::GetModelAndIndexForCommandId(
diff --git a/chrome/browser/ui/unload_controller.cc b/chrome/browser/ui/unload_controller.cc
index 19d6154..da61646 100644
--- a/chrome/browser/ui/unload_controller.cc
+++ b/chrome/browser/ui/unload_controller.cc
@@ -4,55 +4,25 @@
 
 #include "chrome/browser/ui/unload_controller.h"
 
-#include "base/logging.h"
 #include "base/message_loop.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
-#include "chrome/browser/ui/tab_contents/core_tab_helper.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/browser/ui/tabs/tab_strip_model_delegate.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_source.h"
 #include "content/public/browser/notification_types.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_delegate.h"
 
 namespace chrome {
 
-
-////////////////////////////////////////////////////////////////////////////////
-// DetachedWebContentsDelegate will delete web contents when they close.
-class UnloadController::DetachedWebContentsDelegate
-    : public content::WebContentsDelegate {
- public:
-  DetachedWebContentsDelegate() { }
-  virtual ~DetachedWebContentsDelegate() { }
-
- private:
-  // WebContentsDelegate implementation.
-  virtual bool ShouldSuppressDialogs() OVERRIDE {
-    return true;  // Return true so dialogs are suppressed.
-  }
-
-  virtual void CloseContents(content::WebContents* source) OVERRIDE {
-    // Finished detached close.
-    // UnloadController will observe |NOTIFICATION_WEB_CONTENTS_DISCONNECTED|.
-    delete source;
-  }
-
-  DISALLOW_COPY_AND_ASSIGN(DetachedWebContentsDelegate);
-};
-
 ////////////////////////////////////////////////////////////////////////////////
 // UnloadController, public:
 
 UnloadController::UnloadController(Browser* browser)
     : browser_(browser),
-      tab_needing_before_unload_ack_(NULL),
       is_attempting_to_close_browser_(false),
-      detached_delegate_(new DetachedWebContentsDelegate()),
       weak_factory_(this) {
   browser_->tab_strip_model()->AddObserver(this);
 }
@@ -64,20 +34,16 @@
 bool UnloadController::CanCloseContents(content::WebContents* contents) {
   // Don't try to close the tab when the whole browser is being closed, since
   // that avoids the fast shutdown path where we just kill all the renderers.
+  if (is_attempting_to_close_browser_)
+    ClearUnloadState(contents, true);
   return !is_attempting_to_close_browser_;
 }
 
 bool UnloadController::BeforeUnloadFired(content::WebContents* contents,
                                          bool proceed) {
   if (!is_attempting_to_close_browser_) {
-    if (!proceed) {
+    if (!proceed)
       contents->SetClosedByUserGesture(false);
-    } else {
-      // No more dialogs are possible, so remove the tab and finish
-      // running unload listeners asynchrounously.
-      browser_->tab_strip_model()->delegate()->CreateHistoricalTab(contents);
-      DetachWebContents(contents);
-    }
     return proceed;
   }
 
@@ -87,10 +53,10 @@
     return false;
   }
 
-  if (tab_needing_before_unload_ack_ == contents) {
-    // Now that beforeunload has fired, queue the tab to fire unload.
-    tab_needing_before_unload_ack_ = NULL;
-    tabs_needing_unload_.insert(contents);
+  if (RemoveFromSet(&tabs_needing_before_unload_fired_, contents)) {
+    // Now that beforeunload has fired, put the tab on the queue to fire
+    // unload.
+    tabs_needing_unload_fired_.insert(contents);
     ProcessPendingTabs();
     // We want to handle firing the unload event ourselves since we want to
     // fire all the beforeunload events before attempting to fire the unload
@@ -115,20 +81,15 @@
 }
 
 bool UnloadController::TabsNeedBeforeUnloadFired() {
-  if (!tabs_needing_before_unload_.empty() ||
-      tab_needing_before_unload_ack_ != NULL)
-    return true;
-
-  if (!tabs_needing_unload_.empty())
-    return false;
-
-  for (int i = 0; i < browser_->tab_strip_model()->count(); ++i) {
-    content::WebContents* contents =
-        browser_->tab_strip_model()->GetWebContentsAt(i);
-    if (contents->NeedToFireBeforeUnload())
-      tabs_needing_before_unload_.insert(contents);
+  if (tabs_needing_before_unload_fired_.empty()) {
+    for (int i = 0; i < browser_->tab_strip_model()->count(); ++i) {
+      content::WebContents* contents =
+          browser_->tab_strip_model()->GetWebContentsAt(i);
+      if (contents->NeedToFireBeforeUnload())
+        tabs_needing_before_unload_fired_.insert(contents);
+    }
   }
-  return !tabs_needing_before_unload_.empty();
+  return !tabs_needing_before_unload_fired_.empty();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -138,15 +99,12 @@
                                const content::NotificationSource& source,
                                const content::NotificationDetails& details) {
   switch (type) {
-    case content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED: {
-      registrar_.Remove(this,
-                        content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
-                        source);
-      content::WebContents* contents =
-          content::Source<content::WebContents>(source).ptr();
-      ClearUnloadState(contents);
+    case content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED:
+      if (is_attempting_to_close_browser_) {
+        ClearUnloadState(content::Source<content::WebContents>(source).ptr(),
+                         false);  // See comment for ClearUnloadState().
+      }
       break;
-    }
     default:
       NOTREACHED() << "Got a notification we didn't register for.";
   }
@@ -193,41 +151,11 @@
 }
 
 void UnloadController::TabDetachedImpl(content::WebContents* contents) {
-  if (tabs_needing_unload_ack_.find(contents) !=
-      tabs_needing_unload_ack_.end()) {
-    // Tab needs unload to complete.
-    // It will send |NOTIFICATION_WEB_CONTENTS_DISCONNECTED| when done.
-    return;
-  }
-
-  // If WEB_CONTENTS_DISCONNECTED was received then the notification may have
-  // already been unregistered.
-  const content::NotificationSource& source =
-      content::Source<content::WebContents>(contents);
-  if (registrar_.IsRegistered(this,
-                              content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
-                              source)) {
-    registrar_.Remove(this,
-                      content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
-                      source);
-  }
-
   if (is_attempting_to_close_browser_)
-    ClearUnloadState(contents);
-}
-
-bool UnloadController::DetachWebContents(content::WebContents* contents) {
-  int index = browser_->tab_strip_model()->GetIndexOfWebContents(contents);
-  if (index != TabStripModel::kNoTab &&
-      contents->NeedToFireBeforeUnload()) {
-    tabs_needing_unload_ack_.insert(contents);
-    browser_->tab_strip_model()->DetachWebContentsAt(index);
-    contents->SetDelegate(detached_delegate_.get());
-    CoreTabHelper* core_tab_helper = CoreTabHelper::FromWebContents(contents);
-    core_tab_helper->OnUnloadDetachedStarted();
-    return true;
-  }
-  return false;
+    ClearUnloadState(contents, false);
+  registrar_.Remove(this,
+                    content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
+                    content::Source<content::WebContents>(contents));
 }
 
 void UnloadController::ProcessPendingTabs() {
@@ -238,105 +166,58 @@
     return;
   }
 
-  if (tab_needing_before_unload_ack_ != NULL) {
-    // Wait for |BeforeUnloadFired| before proceeding.
+  if (HasCompletedUnloadProcessing()) {
+    // We've finished all the unload events and can proceed to close the
+    // browser.
+    browser_->OnWindowClosing();
     return;
   }
 
-  // Process a beforeunload handler.
-  if (!tabs_needing_before_unload_.empty()) {
-    WebContentsSet::iterator it = tabs_needing_before_unload_.begin();
-    content::WebContents* contents = *it;
-    tabs_needing_before_unload_.erase(it);
+  // Process beforeunload tabs first. When that queue is empty, process
+  // unload tabs.
+  if (!tabs_needing_before_unload_fired_.empty()) {
+    content::WebContents* web_contents =
+        *(tabs_needing_before_unload_fired_.begin());
     // Null check render_view_host here as this gets called on a PostTask and
     // the tab's render_view_host may have been nulled out.
-    if (contents->GetRenderViewHost()) {
-      tab_needing_before_unload_ack_ = contents;
-
-      CoreTabHelper* core_tab_helper = CoreTabHelper::FromWebContents(contents);
-      core_tab_helper->OnCloseStarted();
-
-      contents->GetRenderViewHost()->FirePageBeforeUnload(false);
+    if (web_contents->GetRenderViewHost()) {
+      web_contents->GetRenderViewHost()->FirePageBeforeUnload(false);
     } else {
-      ProcessPendingTabs();
+      ClearUnloadState(web_contents, true);
     }
-    return;
-  }
-
-  // Process all the unload handlers. (The beforeunload handlers have finished.)
-  if (!tabs_needing_unload_.empty()) {
-    browser_->OnWindowClosing();
-
-    // Run unload handlers detached since no more interaction is possible.
-    WebContentsSet::iterator it = tabs_needing_unload_.begin();
-    while (it != tabs_needing_unload_.end()) {
-      WebContentsSet::iterator current = it++;
-      content::WebContents* contents = *current;
-      tabs_needing_unload_.erase(current);
-      // Null check render_view_host here as this gets called on a PostTask
-      // and the tab's render_view_host may have been nulled out.
-      if (contents->GetRenderViewHost()) {
-        CoreTabHelper* core_tab_helper =
-            CoreTabHelper::FromWebContents(contents);
-        core_tab_helper->OnUnloadStarted();
-        DetachWebContents(contents);
-        contents->GetRenderViewHost()->ClosePage();
-      }
-    }
-
-    // Get the browser hidden.
-    if (browser_->tab_strip_model()->empty()) {
-      browser_->TabStripEmpty();
+  } else if (!tabs_needing_unload_fired_.empty()) {
+    // We've finished firing all beforeunload events and can proceed with unload
+    // events.
+    // TODO(ojan): We should add a call to browser_shutdown::OnShutdownStarting
+    // somewhere around here so that we have accurate measurements of shutdown
+    // time.
+    // TODO(ojan): We can probably fire all the unload events in parallel and
+    // get a perf benefit from that in the cases where the tab hangs in it's
+    // unload handler or takes a long time to page in.
+    content::WebContents* web_contents = *(tabs_needing_unload_fired_.begin());
+    // Null check render_view_host here as this gets called on a PostTask and
+    // the tab's render_view_host may have been nulled out.
+    if (web_contents->GetRenderViewHost()) {
+      web_contents->GetRenderViewHost()->ClosePage();
     } else {
-      browser_->tab_strip_model()->CloseAllTabs();  // tabs not needing unload
+      ClearUnloadState(web_contents, true);
     }
-    return;
-  }
-
-  if (HasCompletedUnloadProcessing()) {
-    browser_->OnWindowClosing();
-
-    // Get the browser closed.
-    if (browser_->tab_strip_model()->empty()) {
-      browser_->TabStripEmpty();
-    } else {
-      // There may be tabs if the last tab needing beforeunload crashed.
-      browser_->tab_strip_model()->CloseAllTabs();
-    }
-    return;
+  } else {
+    NOTREACHED();
   }
 }
 
 bool UnloadController::HasCompletedUnloadProcessing() const {
   return is_attempting_to_close_browser_ &&
-      tabs_needing_before_unload_.empty() &&
-      tab_needing_before_unload_ack_ == NULL &&
-      tabs_needing_unload_.empty() &&
-      tabs_needing_unload_ack_.empty();
+      tabs_needing_before_unload_fired_.empty() &&
+      tabs_needing_unload_fired_.empty();
 }
 
 void UnloadController::CancelWindowClose() {
   // Closing of window can be canceled from a beforeunload handler.
   DCHECK(is_attempting_to_close_browser_);
-  tabs_needing_before_unload_.clear();
-  if (tab_needing_before_unload_ack_ != NULL) {
-
-    CoreTabHelper* core_tab_helper =
-        CoreTabHelper::FromWebContents(tab_needing_before_unload_ack_);
-    core_tab_helper->OnCloseCanceled();
-    tab_needing_before_unload_ack_ = NULL;
-  }
-  for (WebContentsSet::iterator it = tabs_needing_unload_.begin();
-       it != tabs_needing_unload_.end(); it++) {
-    content::WebContents* contents = *it;
-
-    CoreTabHelper* core_tab_helper = CoreTabHelper::FromWebContents(contents);
-    core_tab_helper->OnCloseCanceled();
-  }
-  tabs_needing_unload_.clear();
-
-  // No need to clear tabs_needing_unload_ack_. Those tabs are already detached.
-
+  tabs_needing_before_unload_fired_.clear();
+  tabs_needing_unload_fired_.clear();
   is_attempting_to_close_browser_ = false;
 
   content::NotificationService::current()->Notify(
@@ -345,34 +226,33 @@
       content::NotificationService::NoDetails());
 }
 
-void UnloadController::ClearUnloadState(content::WebContents* contents) {
-  if (tabs_needing_unload_ack_.erase(contents) > 0) {
-    if (HasCompletedUnloadProcessing())
-      PostTaskForProcessPendingTabs();
-    return;
-  }
+bool UnloadController::RemoveFromSet(UnloadListenerSet* set,
+                                     content::WebContents* web_contents) {
+  DCHECK(is_attempting_to_close_browser_);
 
-  if (!is_attempting_to_close_browser_)
-    return;
-
-  if (tab_needing_before_unload_ack_ == contents) {
-    tab_needing_before_unload_ack_ = NULL;
-    PostTaskForProcessPendingTabs();
-    return;
+  UnloadListenerSet::iterator iter =
+      std::find(set->begin(), set->end(), web_contents);
+  if (iter != set->end()) {
+    set->erase(iter);
+    return true;
   }
-
-  if (tabs_needing_before_unload_.erase(contents) > 0 ||
-      tabs_needing_unload_.erase(contents) > 0) {
-    if (tab_needing_before_unload_ack_ == NULL)
-      PostTaskForProcessPendingTabs();
-  }
+  return false;
 }
 
-void UnloadController::PostTaskForProcessPendingTabs() {
-  base::MessageLoop::current()->PostTask(
-      FROM_HERE,
-      base::Bind(&UnloadController::ProcessPendingTabs,
-                 weak_factory_.GetWeakPtr()));
+void UnloadController::ClearUnloadState(content::WebContents* web_contents,
+                                        bool process_now) {
+  if (is_attempting_to_close_browser_) {
+    RemoveFromSet(&tabs_needing_before_unload_fired_, web_contents);
+    RemoveFromSet(&tabs_needing_unload_fired_, web_contents);
+    if (process_now) {
+      ProcessPendingTabs();
+    } else {
+      base::MessageLoop::current()->PostTask(
+          FROM_HERE,
+          base::Bind(&UnloadController::ProcessPendingTabs,
+                     weak_factory_.GetWeakPtr()));
+    }
+  }
 }
 
 }  // namespace chrome
diff --git a/chrome/browser/ui/unload_controller.h b/chrome/browser/ui/unload_controller.h
index 47e50b0..4c13c67 100644
--- a/chrome/browser/ui/unload_controller.h
+++ b/chrome/browser/ui/unload_controller.h
@@ -7,9 +7,7 @@
 
 #include <set>
 
-#include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
-#include "base/strings/string_piece.h"
 #include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
@@ -24,33 +22,7 @@
 }
 
 namespace chrome {
-// UnloadController manages closing tabs and windows -- especially in
-// regards to beforeunload handlers (have proceed/cancel dialogs) and
-// unload handlers (have no user interaction).
-//
-// Typical flow of closing a tab:
-//  1. Browser calls CanCloseContents().
-//     If true, browser calls contents::CloseWebContents().
-//  2. WebContents notifies us via its delegate and BeforeUnloadFired()
-//     that the beforeunload handler was run. If the user allowed the
-//     close to continue, we detached the tab and hold onto it while the
-//     close finishes.
-//
-// Typical flow of closing a window:
-//  1. BrowserView::CanClose() calls TabsNeedBeforeUnloadFired().
-//     If beforeunload/unload handlers need to run, UnloadController returns
-//     true and calls ProcessPendingTabs() (private method).
-//  2. For each tab with a beforeunload/unload handler, ProcessPendingTabs()
-//        calls |CoreTabHelper::OnCloseStarted()|
-//        and   |web_contents->GetRenderViewHost()->FirePageBeforeUnload()|.
-//  3. If the user allowed the close to continue, we detach all the tabs with
-//     unload handlers, remove them from the tab strip, and finish closing
-//     the tabs in the background.
-//  4. The browser gets notified that the tab strip is empty and calls
-//     CloseFrame where the empty tab strip causes the window to hide.
-//     Once the detached tabs finish, the browser calls CloseFrame again and
-//     the window is finally closed.
-//
+
 class UnloadController : public content::NotificationObserver,
                          public TabStripModelObserver {
  public:
@@ -77,7 +49,7 @@
   }
 
   // Called in response to a request to close |browser_|'s window. Returns true
-  // when there are no remaining beforeunload handlers to be run.
+  // when there are no remaining unload handlers to be run.
   bool ShouldCloseWindow();
 
   // Returns true if |browser_| has any tabs that have BeforeUnload handlers
@@ -89,10 +61,9 @@
   //             could be pursued.
   bool TabsNeedBeforeUnloadFired();
 
-  // Returns true if all tabs' beforeunload/unload events have fired.
-  bool HasCompletedUnloadProcessing() const;
-
  private:
+  typedef std::set<content::WebContents*> UnloadListenerSet;
+
   // Overridden from content::NotificationObserver:
   virtual void Observe(int type,
                        const content::NotificationSource& source,
@@ -113,52 +84,43 @@
   void TabAttachedImpl(content::WebContents* contents);
   void TabDetachedImpl(content::WebContents* contents);
 
-  // Detach |contents| and wait for it to finish closing.
-  // The close must be inititiated outside of this method.
-  // Returns true if it succeeds.
-  bool DetachWebContents(content::WebContents* contents);
-
   // Processes the next tab that needs it's beforeunload/unload event fired.
   void ProcessPendingTabs();
 
+  // Whether we've completed firing all the tabs' beforeunload/unload events.
+  bool HasCompletedUnloadProcessing() const;
+
   // Clears all the state associated with processing tabs' beforeunload/unload
   // events since the user cancelled closing the window.
   void CancelWindowClose();
 
-  // Cleans up state appropriately when we are trying to close the
-  // browser or close a tab in the background. We also use this in the
-  // cases where a tab crashes or hangs even if the
-  // beforeunload/unload haven't successfully fired.
-  void ClearUnloadState(content::WebContents* contents);
+  // Removes |web_contents| from the passed |set|.
+  // Returns whether the tab was in the set in the first place.
+  bool RemoveFromSet(UnloadListenerSet* set,
+                     content::WebContents* web_contents);
 
-  // Helper for |ClearUnloadState| to unwind stack before proceeding.
-  void PostTaskForProcessPendingTabs();
-
-  // Log a step of the unload processing.
-  void LogUnloadStep(const base::StringPiece& step_name,
-                     content::WebContents* contents) const;
+  // Cleans up state appropriately when we are trying to close the browser and
+  // the tab has finished firing its unload handler. We also use this in the
+  // cases where a tab crashes or hangs even if the beforeunload/unload haven't
+  // successfully fired. If |process_now| is true |ProcessPendingTabs| is
+  // invoked immediately, otherwise it is invoked after a delay (PostTask).
+  //
+  // Typically you'll want to pass in true for |process_now|. Passing in true
+  // may result in deleting |tab|. If you know that shouldn't happen (because of
+  // the state of the stack), pass in false.
+  void ClearUnloadState(content::WebContents* web_contents, bool process_now);
 
   Browser* browser_;
 
   content::NotificationRegistrar registrar_;
 
-  typedef std::set<content::WebContents*> WebContentsSet;
+  // Tracks tabs that need there beforeunload event fired before we can
+  // close the browser. Only gets populated when we try to close the browser.
+  UnloadListenerSet tabs_needing_before_unload_fired_;
 
-  // Tracks tabs that need their beforeunload event started.
-  // Only gets populated when we try to close the browser.
-  WebContentsSet tabs_needing_before_unload_;
-
-  // Tracks the tab that needs its beforeunload event result.
-  // Only gets populated when we try to close the browser.
-  content::WebContents* tab_needing_before_unload_ack_;
-
-  // Tracks tabs that need their unload event started.
-  // Only gets populated when we try to close the browser.
-  WebContentsSet tabs_needing_unload_;
-
-  // Tracks tabs that need to finish running their unload event.
-  // Populated both when closing individual tabs and when closing the browser.
-  WebContentsSet tabs_needing_unload_ack_;
+  // Tracks tabs that need there unload event fired before we can
+  // close the browser. Only gets populated when we try to close the browser.
+  UnloadListenerSet tabs_needing_unload_fired_;
 
   // Whether we are processing the beforeunload and unload events of each tab
   // in preparation for closing the browser. UnloadController owns this state
@@ -166,10 +128,6 @@
   // Browser window isn't just immediately closed.
   bool is_attempting_to_close_browser_;
 
-  // Manage tabs with beforeunload/unload handlers that close detached.
-  class DetachedWebContentsDelegate;
-  scoped_ptr<DetachedWebContentsDelegate> detached_delegate_;
-
   base::WeakPtrFactory<UnloadController> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(UnloadController);
diff --git a/chrome/browser/ui/views/about_ipc_dialog.cc b/chrome/browser/ui/views/about_ipc_dialog.cc
index cb09301..23c5821 100644
--- a/chrome/browser/ui/views/about_ipc_dialog.cc
+++ b/chrome/browser/ui/views/about_ipc_dialog.cc
@@ -26,7 +26,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/app/chrome_dll_resource.h"
 #include "chrome/browser/ui/browser_dialogs.h"
diff --git a/chrome/browser/ui/views/app_list/app_list_controller_win.cc b/chrome/browser/ui/views/app_list/app_list_controller_win.cc
index 20ff1b4..d459a01 100644
--- a/chrome/browser/ui/views/app_list/app_list_controller_win.cc
+++ b/chrome/browser/ui/views/app_list/app_list_controller_win.cc
@@ -15,13 +15,14 @@
 #include "base/prefs/pref_service.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/sequenced_worker_pool.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "base/win/shortcut.h"
 #include "base/win/windows_version.h"
 #include "chrome/app/chrome_dll_resource.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/extension_system.h"
 #include "chrome/browser/lifetime/application_lifetime.h"
 #include "chrome/browser/platform_util.h"
 #include "chrome/browser/profiles/profile.h"
@@ -257,10 +258,9 @@
   virtual bool CanPin() OVERRIDE;
   virtual void OnShowExtensionPrompt() OVERRIDE;
   virtual void OnCloseExtensionPrompt() OVERRIDE;
-  virtual bool CanShowCreateShortcutsDialog() OVERRIDE;
-  virtual void ShowCreateShortcutsDialog(
-      Profile* profile,
-      const std::string& extension_id) OVERRIDE;
+  virtual bool CanDoCreateShortcutsFlow(bool is_platform_app) OVERRIDE;
+  virtual void DoCreateShortcutsFlow(Profile* profile,
+                                     const std::string& extension_id) OVERRIDE;
   virtual void CreateNewWindow(Profile* profile, bool incognito) OVERRIDE;
   virtual void ActivateApp(Profile* profile,
                            const extensions::Extension* extension,
@@ -431,14 +431,16 @@
   AppListController::GetInstance()->set_can_close(true);
 }
 
-bool AppListControllerDelegateWin::CanShowCreateShortcutsDialog() {
+bool AppListControllerDelegateWin::CanDoCreateShortcutsFlow(
+    bool is_platform_app) {
   return true;
 }
 
-void AppListControllerDelegateWin::ShowCreateShortcutsDialog(
+void AppListControllerDelegateWin::DoCreateShortcutsFlow(
     Profile* profile,
     const std::string& extension_id) {
-  ExtensionService* service = profile->GetExtensionService();
+  ExtensionService* service =
+      extensions::ExtensionSystem::Get(profile)->extension_service();
   DCHECK(service);
   const extensions::Extension* extension = service->GetInstalledExtension(
       extension_id);
@@ -863,6 +865,28 @@
         ShowAppListDuringModeSwitch(initial_profile);
   }
 
+  // Migrate from legacy app launcher if we are on a non-canary and non-chromium
+  // build.
+#if defined(GOOGLE_CHROME_BUILD)
+  if (!InstallUtil::IsChromeSxSProcess() &&
+      !chrome_launcher_support::GetAnyAppHostPath().empty()) {
+    chrome_launcher_support::InstallationState state =
+        chrome_launcher_support::GetAppLauncherInstallationState();
+    if (state == chrome_launcher_support::NOT_INSTALLED) {
+      // If app_host.exe is found but can't be located in the registry,
+      // skip the migration as this is likely a developer build.
+      return;
+    } else if (state == chrome_launcher_support::INSTALLED_AT_SYSTEM_LEVEL) {
+      chrome_launcher_support::UninstallLegacyAppLauncher(
+          chrome_launcher_support::SYSTEM_LEVEL_INSTALLATION);
+    } else if (state == chrome_launcher_support::INSTALLED_AT_USER_LEVEL) {
+      chrome_launcher_support::UninstallLegacyAppLauncher(
+          chrome_launcher_support::USER_LEVEL_INSTALLATION);
+    }
+    EnableAppList();
+  }
+#endif
+
   // Instantiate AppListController so it listens for profile deletions.
   AppListController::GetInstance();
 
@@ -887,25 +911,21 @@
   // shortcut, they can restore it by pinning the start menu or desktop
   // shortcut.
   PrefService* local_state = g_browser_process->local_state();
-  bool has_been_enabled = local_state->GetBoolean(
-      apps::prefs::kAppLauncherHasBeenEnabled);
-  if (!has_been_enabled) {
-    local_state->SetBoolean(apps::prefs::kAppLauncherHasBeenEnabled, true);
-    ShellIntegration::ShortcutLocations shortcut_locations;
-    shortcut_locations.on_desktop = true;
-    shortcut_locations.in_quick_launch_bar = true;
-    shortcut_locations.in_applications_menu = true;
-    BrowserDistribution* dist = BrowserDistribution::GetDistribution();
-    shortcut_locations.applications_menu_subdir = dist->GetAppShortCutName();
-    base::FilePath user_data_dir(
-        g_browser_process->profile_manager()->user_data_dir());
+  local_state->SetBoolean(apps::prefs::kAppLauncherHasBeenEnabled, true);
+  ShellIntegration::ShortcutLocations shortcut_locations;
+  shortcut_locations.on_desktop = true;
+  shortcut_locations.in_quick_launch_bar = true;
+  shortcut_locations.in_applications_menu = true;
+  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
+  shortcut_locations.applications_menu_subdir = dist->GetAppShortCutName();
+  base::FilePath user_data_dir(
+      g_browser_process->profile_manager()->user_data_dir());
 
-    content::BrowserThread::PostTask(
-        content::BrowserThread::FILE,
-        FROM_HERE,
-        base::Bind(&CreateAppListShortcuts,
-                   user_data_dir, GetAppModelId(), shortcut_locations));
-  }
+  content::BrowserThread::PostTask(
+      content::BrowserThread::FILE,
+      FROM_HERE,
+      base::Bind(&CreateAppListShortcuts,
+                  user_data_dir, GetAppModelId(), shortcut_locations));
 }
 
 void AppListController::DisableAppList() {
@@ -937,7 +957,7 @@
 
   // We only need to initialize the view if there's no view already created and
   // there's no profile loading to be shown.
-  return !current_view_ && !profile_loader().AnyProfilesLoading();
+  return !current_view_ && !profile_loader().IsAnyProfileLoading();
 }
 
 void AppListController::LoadProfileForWarmup() {
diff --git a/chrome/browser/ui/views/ash/tab_scrubber.h b/chrome/browser/ui/views/ash/tab_scrubber.h
index f22fbe5..d0511ad 100644
--- a/chrome/browser/ui/views/ash/tab_scrubber.h
+++ b/chrome/browser/ui/views/ash/tab_scrubber.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_ASH_TAB_SCRUBBER_H_
 #define CHROME_BROWSER_UI_VIEWS_ASH_TAB_SCRUBBER_H_
 
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/ui/views/frame/immersive_mode_controller.h"
 #include "chrome/browser/ui/views/tabs/tab_strip_observer.h"
 #include "content/public/browser/notification_observer.h"
diff --git a/chrome/browser/ui/views/autofill/autofill_dialog_views.cc b/chrome/browser/ui/views/autofill/autofill_dialog_views.cc
index 32dff53..0bd2fd0 100644
--- a/chrome/browser/ui/views/autofill/autofill_dialog_views.cc
+++ b/chrome/browser/ui/views/autofill/autofill_dialog_views.cc
@@ -12,8 +12,8 @@
 #include "chrome/browser/ui/autofill/autofill_dialog_controller.h"
 #include "chrome/browser/ui/autofill/autofill_dialog_sign_in_delegate.h"
 #include "chrome/browser/ui/views/constrained_window_views.h"
-#include "components/autofill/browser/autofill_type.h"
 #include "components/autofill/content/browser/wallet/wallet_service_url.h"
+#include "components/autofill/core/browser/autofill_type.h"
 #include "components/web_modal/web_contents_modal_dialog_manager.h"
 #include "components/web_modal/web_contents_modal_dialog_manager_delegate.h"
 #include "content/public/browser/native_web_keyboard_event.h"
@@ -39,6 +39,7 @@
 #include "ui/views/controls/button/label_button.h"
 #include "ui/views/controls/button/label_button_border.h"
 #include "ui/views/controls/combobox/combobox.h"
+#include "ui/views/controls/focusable_border.h"
 #include "ui/views/controls/image_view.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/controls/link.h"
@@ -66,6 +67,9 @@
 // Horizontal padding between text and other elements (in pixels).
 const int kAroundTextPadding = 4;
 
+// Padding around icons inside DecoratedTextfields.
+const size_t kTextfieldIconPadding = 3;
+
 // Size of the triangular mark that indicates an invalid textfield (in pixels).
 const size_t kDogEarSize = 10;
 
@@ -76,8 +80,11 @@
 // Vertical padding above and below each detail section (in pixels).
 const size_t kDetailSectionInset = 10;
 
-const size_t kAutocheckoutProgressBarWidth = 300;
-const size_t kAutocheckoutProgressBarHeight = 11;
+const size_t kAutocheckoutStepsAreaPadding = 28;
+const size_t kAutocheckoutStepInset = 20;
+
+const size_t kAutocheckoutProgressBarWidth = 375;
+const size_t kAutocheckoutProgressBarHeight = 15;
 
 const size_t kArrowHeight = 7;
 const size_t kArrowWidth = 2 * kArrowHeight;
@@ -311,57 +318,74 @@
   DISALLOW_COPY_AND_ASSIGN(DetailsContainerView);
 };
 
-// ButtonStripView wraps the Autocheckout progress bar and the "[X] Save details
-// in Chrome" checkbox and listens for visibility changes.
-class ButtonStripView : public views::View {
+// A view that propagates visibility and preferred size changes.
+class LayoutPropagationView : public views::View {
  public:
-  ButtonStripView() {}
-  virtual ~ButtonStripView() {}
+  LayoutPropagationView() {}
+  virtual ~LayoutPropagationView() {}
 
  protected:
   virtual void ChildVisibilityChanged(views::View* child) OVERRIDE {
     PreferredSizeChanged();
   }
+  virtual void ChildPreferredSizeChanged(views::View* child) OVERRIDE {
+    PreferredSizeChanged();
+  }
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(ButtonStripView);
+  DISALLOW_COPY_AND_ASSIGN(LayoutPropagationView);
+};
+
+// A class which displays the status of an individual step in an
+// Autocheckout flow.
+class AutocheckoutStepProgressView : public views::View {
+ public:
+  AutocheckoutStepProgressView(const string16& description,
+                               const gfx::Font& font,
+                               const SkColor color,
+                               const bool is_icon_visible) {
+    views::GridLayout* layout = new views::GridLayout(this);
+    SetLayoutManager(layout);
+    const int kColumnSetId = 0;
+    views::ColumnSet* columns = layout->AddColumnSet(kColumnSetId);
+    columns->AddColumn(views::GridLayout::LEADING,
+                       views::GridLayout::LEADING,
+                       0,
+                       views::GridLayout::USE_PREF,
+                       0,
+                       0);
+    columns->AddPaddingColumn(0, 8);
+    columns->AddColumn(views::GridLayout::LEADING,
+                       views::GridLayout::LEADING,
+                       0,
+                       views::GridLayout::USE_PREF,
+                       0,
+                       0);
+    layout->StartRow(0, kColumnSetId);
+    views::Label* label = new views::Label();
+    label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+    label->set_border(views::Border::CreateEmptyBorder(0, 0, 0, 0));
+    label->SetText(description);
+    label->SetFont(font);
+    label->SetEnabledColor(color);
+
+    views::ImageView* icon = new views::ImageView();
+    icon->SetVisible(is_icon_visible);
+    icon->SetImage(ui::ResourceBundle::GetSharedInstance().GetImageNamed(
+        IDR_WALLET_STEP_CHECK).ToImageSkia());
+
+    layout->AddView(icon);
+    layout->AddView(label);
+  }
+
+  virtual ~AutocheckoutStepProgressView() {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(AutocheckoutStepProgressView);
 };
 
 }  // namespace
 
-// AutofillDialogViews::SizeLimitedScrollView ----------------------------------
-
-AutofillDialogViews::SizeLimitedScrollView::SizeLimitedScrollView(
-    views::View* scroll_contents)
-    : max_height_(-1) {
-  set_hide_horizontal_scrollbar(true);
-  SetContents(scroll_contents);
-}
-
-AutofillDialogViews::SizeLimitedScrollView::~SizeLimitedScrollView() {}
-
-void AutofillDialogViews::SizeLimitedScrollView::Layout() {
-  contents()->SizeToPreferredSize();
-  ScrollView::Layout();
-}
-
-gfx::Size AutofillDialogViews::SizeLimitedScrollView::GetPreferredSize() {
-  gfx::Size size = contents()->GetPreferredSize();
-  if (max_height_ >= 0 && max_height_ < size.height())
-    size.set_height(max_height_);
-
-  return size;
-}
-
-void AutofillDialogViews::SizeLimitedScrollView::SetMaximumHeight(
-    int max_height) {
-  int old_max = max_height_;
-  max_height_ = max_height;
-
-  if (max_height_ < height() || old_max <= height())
-    PreferredSizeChanged();
-}
-
 // AutofillDialogViews::ErrorBubble --------------------------------------------
 
 AutofillDialogViews::ErrorBubble::ErrorBubble(views::View* anchor,
@@ -371,7 +395,7 @@
       observer_(this) {
   widget_ = new views::Widget;
   views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
-  params.transparent = true;
+  params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
   views::Widget* anchor_widget = anchor->GetWidget();
   DCHECK(anchor_widget);
   params.parent = anchor_widget->GetNativeView();
@@ -429,13 +453,19 @@
     const string16& default_value,
     const string16& placeholder,
     views::TextfieldController* controller)
-    : textfield_(new views::Textfield()),
+    : border_(new views::FocusableBorder()),
       invalid_(false) {
-  textfield_->set_placeholder_text(placeholder);
-  textfield_->SetText(default_value);
-  textfield_->SetController(controller);
-  SetLayoutManager(new views::FillLayout());
-  AddChildView(textfield_);
+  set_background(
+      views::Background::CreateSolidBackground(GetBackgroundColor()));
+
+  set_border(border_);
+  // Removes the border from |native_wrapper_|.
+  RemoveBorder();
+
+  set_placeholder_text(placeholder);
+  SetText(default_value);
+  SetController(controller);
+  SetHorizontalMargins(0, 0);
 }
 
 AutofillDialogViews::DecoratedTextfield::~DecoratedTextfield() {}
@@ -443,9 +473,21 @@
 void AutofillDialogViews::DecoratedTextfield::SetInvalid(bool invalid) {
   invalid_ = invalid;
   if (invalid)
-    textfield_->SetBorderColor(kWarningColor);
+    border_->SetColor(kWarningColor);
   else
-    textfield_->UseDefaultBorderColor();
+    border_->UseDefaultColor();
+  SchedulePaint();
+}
+
+void AutofillDialogViews::DecoratedTextfield::SetIcon(const gfx::Image& icon) {
+  int icon_space = icon.IsEmpty() ? 0 :
+                                    icon.Width() + 2 * kTextfieldIconPadding;
+  int left = base::i18n::IsRTL() ? icon_space : 0;
+  int right = base::i18n::IsRTL() ? 0 : icon_space;
+  SetHorizontalMargins(left, right);
+  icon_ = icon;
+
+  PreferredSizeChanged();
   SchedulePaint();
 }
 
@@ -457,17 +499,30 @@
     gfx::Canvas* canvas) {}
 
 void AutofillDialogViews::DecoratedTextfield::OnPaint(gfx::Canvas* canvas) {
-  // Draw the textfield first.
-  canvas->Save();
-  if (FlipCanvasOnPaintForRTLUI()) {
-    canvas->Translate(gfx::Vector2d(width(), 0));
-    canvas->Scale(-1, 1);
-  }
-  views::View::PaintChildren(canvas);
-  canvas->Restore();
+  // Draw the border and background.
+  border_->set_has_focus(HasFocus());
+  views::View::OnPaint(canvas);
 
-  // Then draw extra stuff on top.
+  // Then the textfield.
+  views::View::PaintChildren(canvas);
+
+  // Then the icon.
+  if (!icon_.IsEmpty()) {
+    gfx::Rect bounds = GetContentsBounds();
+    int x = base::i18n::IsRTL() ?
+        kTextfieldIconPadding :
+        bounds.right() - icon_.Width() - kTextfieldIconPadding;
+    canvas->DrawImageInt(icon_.AsImageSkia(), x,
+                         bounds.y() + (bounds.height() - icon_.Height()) / 2);
+  }
+
+  // Then the invalid indicator.
   if (invalid_) {
+    if (base::i18n::IsRTL()) {
+      canvas->Translate(gfx::Vector2d(width(), 0));
+      canvas->Scale(-1, 1);
+    }
+
     SkPath dog_ear;
     dog_ear.moveTo(width() - kDogEarSize, 0);
     dog_ear.lineTo(width(), 0);
@@ -478,10 +533,6 @@
   }
 }
 
-void AutofillDialogViews::DecoratedTextfield::RequestFocus() {
-  textfield()->RequestFocus();
-}
-
 // AutofillDialogViews::AccountChooser -----------------------------------------
 
 AutofillDialogViews::AccountChooser::AccountChooser(
@@ -508,6 +559,8 @@
 AutofillDialogViews::AccountChooser::~AccountChooser() {}
 
 void AutofillDialogViews::AccountChooser::Update() {
+  SetVisible(!controller_->ShouldShowSpinner());
+
   gfx::Image icon = controller_->AccountChooserImage();
   image_->SetImage(icon.AsImageSkia());
   label_->SetText(controller_->AccountChooserText());
@@ -656,13 +709,6 @@
 
 void AutofillDialogViews::OnWidgetBoundsChanged(views::Widget* widget,
                                                 const gfx::Rect& new_bounds) {
-  int non_scrollable_height = window_->GetContentsView()->bounds().height() -
-      scrollable_area_->bounds().height();
-  int browser_window_height = widget->GetContentsView()->bounds().height();
-
-  scrollable_area_->SetMaximumHeight(
-      std::max(kMinimumContentsHeight,
-               (browser_window_height - non_scrollable_height) * 8 / 10));
   ContentsPreferredSizeChanged();
 }
 
@@ -806,11 +852,12 @@
   label_container_->AddChildView(decorated_);
   decorated_->SetVisible(false);
   // TODO(estade): get the sizing and spacing right on this textfield.
-  decorated_->textfield()->set_default_width_in_chars(10);
+  decorated_->set_default_width_in_chars(10);
   AddChildView(label_container_);
 
   label_line_2_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
   label_line_2_->SetVisible(false);
+  label_line_2_->SetMultiLine(true);
   AddChildView(label_line_2_);
 
   SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0));
@@ -845,16 +892,42 @@
 
 void AutofillDialogViews::SuggestionView::ShowTextfield(
     const string16& placeholder_text,
-    const gfx::ImageSkia& icon) {
-  decorated_->textfield()->set_placeholder_text(placeholder_text);
-  decorated_->textfield()->SetIcon(icon);
+    const gfx::Image& icon) {
+  decorated_->set_placeholder_text(placeholder_text);
+  decorated_->SetIcon(icon);
   decorated_->SetVisible(true);
   // The textfield will increase the height of the first row and cause the
   // label to be aligned properly, so the border is not necessary.
   label_->set_border(NULL);
 }
 
-// AutofilDialogViews::AutocheckoutProgressBar ---------------------------------
+// AutofillDialogViews::AutocheckoutStepsArea ---------------------------------
+
+AutofillDialogViews::AutocheckoutStepsArea::AutocheckoutStepsArea() {
+  SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical,
+                                        kAutocheckoutStepsAreaPadding,
+                                        0,
+                                        kAutocheckoutStepInset));
+}
+
+void AutofillDialogViews::AutocheckoutStepsArea::SetSteps(
+    const std::vector<DialogAutocheckoutStep>& steps) {
+  RemoveAllChildViews(true);
+  for (size_t i = 0; i < steps.size(); ++i) {
+    const DialogAutocheckoutStep& step = steps[i];
+    AutocheckoutStepProgressView* progressView =
+        new AutocheckoutStepProgressView(step.GetDisplayText(),
+                                         step.GetTextFont(),
+                                         step.GetTextColor(),
+                                         step.IsIconVisible());
+
+    AddChildView(progressView);
+  }
+
+  PreferredSizeChanged();
+}
+
+// AutofillDialogViews::AutocheckoutProgressBar
 
 AutofillDialogViews::AutocheckoutProgressBar::AutocheckoutProgressBar() {}
 AutofillDialogViews::AutocheckoutProgressBar::~AutocheckoutProgressBar() {}
@@ -877,16 +950,16 @@
 AutofillDialogViews::AutofillDialogViews(AutofillDialogController* controller)
     : controller_(controller),
       window_(NULL),
-      contents_(NULL),
       notification_area_(NULL),
       account_chooser_(NULL),
       sign_in_webview_(NULL),
-      main_container_(NULL),
       scrollable_area_(NULL),
       details_container_(NULL),
+      loading_shield_(NULL),
       overlay_view_(NULL),
       button_strip_extra_view_(NULL),
       save_in_chrome_checkbox_(NULL),
+      autocheckout_steps_area_(NULL),
       autocheckout_progress_bar_view_(NULL),
       autocheckout_progress_bar_(NULL),
       footnote_view_(NULL),
@@ -945,7 +1018,6 @@
       views::Widget::GetTopLevelWidgetForNativeView(
           controller_->web_contents()->GetView()->GetNativeView());
   observer_.Add(browser_widget);
-  OnWidgetBoundsChanged(browser_widget, gfx::Rect());
 }
 
 void AutofillDialogViews::Hide() {
@@ -955,6 +1027,15 @@
 
 void AutofillDialogViews::UpdateAccountChooser() {
   account_chooser_->Update();
+  // TODO(estade): replace this with a better loading image/animation.
+  // See http://crbug.com/230932
+  string16 new_loading_message = (controller_->ShouldShowSpinner() ?
+      ASCIIToUTF16("Loading...") : base::string16());
+  if (new_loading_message != loading_shield_->text()) {
+    loading_shield_->SetText(new_loading_message);
+    loading_shield_->SetVisible(!new_loading_message.empty());
+    Layout();
+  }
 
   // Update legal documents for the account.
   if (footnote_view_) {
@@ -976,6 +1057,11 @@
   }
 }
 
+void AutofillDialogViews::UpdateAutocheckoutStepsArea() {
+  autocheckout_steps_area_->SetSteps(controller_->CurrentAutocheckoutSteps());
+  ContentsPreferredSizeChanged();
+}
+
 void AutofillDialogViews::UpdateButtonStrip() {
   button_strip_extra_view_->SetVisible(
       GetDialogButtons() != ui::DIALOG_BUTTON_NONE);
@@ -987,7 +1073,7 @@
 }
 
 void AutofillDialogViews::UpdateDetailArea() {
-  details_container_->SetVisible(controller_->ShouldShowDetailArea());
+  scrollable_area_->SetVisible(controller_->ShouldShowDetailArea());
   ContentsPreferredSizeChanged();
 }
 
@@ -1012,7 +1098,7 @@
   TextfieldMap::iterator text_mapping =
       group->textfields.find(&originating_input);
   if (text_mapping != group->textfields.end())
-    text_mapping->second->textfield()->SetText(string16());
+    text_mapping->second->SetText(string16());
 
   // If the Autofill data comes from a credit card, make sure to overwrite the
   // CC comboboxes (even if they already have something in them). If the
@@ -1035,7 +1121,7 @@
   DetailsGroup* group = GroupForSection(section);
   for (TextfieldMap::const_iterator it = group->textfields.begin();
        it != group->textfields.end(); ++it) {
-    output->insert(std::make_pair(it->first, it->second->textfield()->text()));
+    output->insert(std::make_pair(it->first, it->second->text()));
   }
   for (ComboboxMap::const_iterator it = group->comboboxes.begin();
        it != group->comboboxes.end(); ++it) {
@@ -1048,7 +1134,7 @@
   DialogSection billing_section = controller_->SectionIsActive(SECTION_CC) ?
       SECTION_CC : SECTION_CC_BILLING;
   return GroupForSection(billing_section)->suggested_info->
-      decorated_textfield()->textfield()->text();
+      decorated_textfield()->text();
 }
 
 bool AutofillDialogViews::SaveDetailsLocally() {
@@ -1062,7 +1148,6 @@
 
   sign_in_webview_->LoadInitialURL(wallet::GetSignInUrl());
 
-  main_container_->SetVisible(false);
   sign_in_webview_->SetVisible(true);
   UpdateButtonStrip();
   ContentsPreferredSizeChanged();
@@ -1071,7 +1156,6 @@
 
 void AutofillDialogViews::HideSignIn() {
   sign_in_webview_->SetVisible(false);
-  main_container_->SetVisible(true);
   UpdateButtonStrip();
   ContentsPreferredSizeChanged();
 }
@@ -1144,6 +1228,13 @@
   NOTREACHED();
 }
 
+void AutofillDialogViews::SetTextContentsOfSuggestionInput(
+    DialogSection section,
+    const base::string16& text) {
+  GroupForSection(section)->suggested_info->decorated_textfield()->
+      SetText(text);
+}
+
 void AutofillDialogViews::ActivateInput(const DetailInput& input) {
   TextfieldEditedOrActivated(TextfieldForInput(input), false);
 }
@@ -1164,6 +1255,93 @@
   return true;
 }
 
+gfx::Size AutofillDialogViews::GetPreferredSize() {
+  gfx::Insets insets = GetInsets();
+  gfx::Size scroll_size = scrollable_area_->contents()->GetPreferredSize();
+  int width = scroll_size.width() + insets.width();
+
+  if (sign_in_webview_->visible()) {
+    gfx::Size size = static_cast<views::View*>(sign_in_webview_)->
+        GetPreferredSize();
+    return gfx::Size(width, size.height() + insets.height());
+  }
+
+  int base_height = insets.height();
+  int notification_height = notification_area_->
+      GetHeightForWidth(scroll_size.width());
+  if (notification_height > 0)
+    base_height += notification_height + views::kRelatedControlVerticalSpacing;
+
+  int steps_height = autocheckout_steps_area_->
+      GetHeightForWidth(scroll_size.width());
+  if (steps_height > 0)
+    base_height += steps_height + views::kRelatedControlVerticalSpacing;
+
+  // When the scroll area isn't visible, it still sets the width but doesn't
+  // factor into height.
+  if (!scrollable_area_->visible())
+    return gfx::Size(width, base_height);
+
+  // Show as much of the scroll view as is possible without going past the
+  // bottom of the browser window.
+  views::Widget* widget =
+      views::Widget::GetTopLevelWidgetForNativeView(
+          controller_->web_contents()->GetView()->GetNativeView());
+  int browser_window_height =
+      widget ? widget->GetContentsView()->bounds().height() : INT_MAX;
+  const int kWindowDecorationHeight = 200;
+  int height = base_height + std::min(
+      scroll_size.height(),
+      std::max(kMinimumContentsHeight,
+               browser_window_height - base_height - kWindowDecorationHeight));
+
+  return gfx::Size(width, height);
+}
+
+void AutofillDialogViews::Layout() {
+  gfx::Rect content_bounds = GetContentsBounds();
+  if (sign_in_webview_->visible()) {
+    sign_in_webview_->SetBoundsRect(content_bounds);
+    return;
+  }
+
+  const int x = content_bounds.x();
+  const int y = content_bounds.y();
+  const int w = content_bounds.width();
+  // Layout notification area at top of dialog.
+  int notification_height = notification_area_->GetHeightForWidth(w);
+  notification_area_->SetBounds(x, y, w, notification_height);
+
+  // Layout Autocheckout steps at bottom of dialog.
+  int steps_height = autocheckout_steps_area_->GetHeightForWidth(w);
+  autocheckout_steps_area_->SetBounds(x, content_bounds.bottom() - steps_height,
+                                      w, steps_height);
+
+  // The rest (the |scrollable_area_|) takes up whatever's left.
+  if (scrollable_area_->visible()) {
+    int scroll_y = y;
+    if (notification_height > 0)
+      scroll_y += notification_height + views::kRelatedControlVerticalSpacing;
+
+    int scroll_bottom = content_bounds.bottom();
+    if (steps_height > 0)
+      scroll_bottom -= steps_height + views::kRelatedControlVerticalSpacing;
+
+    scrollable_area_->contents()->SizeToPreferredSize();
+    scrollable_area_->SetBounds(x, scroll_y, w, scroll_bottom - scroll_y);
+  }
+
+  if (loading_shield_->visible())
+    loading_shield_->SetBoundsRect(bounds());
+
+  if (error_bubble_)
+    error_bubble_->UpdatePosition();
+}
+
+void AutofillDialogViews::OnBoundsChanged(const gfx::Rect& previous_bounds) {
+  sign_in_delegate_->SetMinWidth(GetContentsBounds().width());
+}
+
 string16 AutofillDialogViews::GetWindowTitle() const {
   return controller_->DialogTitle();
 }
@@ -1178,18 +1356,6 @@
   controller_->ViewClosed();
 }
 
-views::Widget* AutofillDialogViews::GetWidget() {
-  return contents_->GetWidget();
-}
-
-const views::Widget* AutofillDialogViews::GetWidget() const {
-  return contents_->GetWidget();
-}
-
-views::View* AutofillDialogViews::GetContentsView() {
-  return contents_;
-}
-
 int AutofillDialogViews::GetDialogButtons() const {
   if (sign_in_webview_->visible())
     return ui::DIALOG_BUTTON_NONE;
@@ -1216,7 +1382,7 @@
 }
 
 views::View* AutofillDialogViews::CreateFootnoteView() {
-  footnote_view_ = new views::View();
+  footnote_view_ = new LayoutPropagationView();
   footnote_view_->SetLayoutManager(
       new views::BoxLayout(views::BoxLayout::kVertical,
                            kLegalDocPadding,
@@ -1368,7 +1534,7 @@
 }
 
 void AutofillDialogViews::InitChildViews() {
-  button_strip_extra_view_ = new ButtonStripView();
+  button_strip_extra_view_ = new LayoutPropagationView();
   button_strip_extra_view_->SetLayoutManager(
       new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0));
 
@@ -1379,12 +1545,7 @@
 
   autocheckout_progress_bar_view_ = new views::View();
   autocheckout_progress_bar_view_->SetLayoutManager(
-      new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0));
-
-  views::Label* progress_bar_label = new views::Label();
-  progress_bar_label->SetText(controller_->ProgressBarText());
-  progress_bar_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-  autocheckout_progress_bar_view_->AddChildView(progress_bar_label);
+      new views::BoxLayout(views::BoxLayout::kVertical, 0, 15, 0));
 
   autocheckout_progress_bar_ = new AutocheckoutProgressBar();
   autocheckout_progress_bar_view_->AddChildView(autocheckout_progress_bar_);
@@ -1392,37 +1553,36 @@
   button_strip_extra_view_->AddChildView(autocheckout_progress_bar_view_);
   autocheckout_progress_bar_view_->SetVisible(false);
 
-  contents_ = new views::View();
-  contents_->SetLayoutManager(
-      new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0));
-  contents_->AddChildView(CreateMainContainer());
+  account_chooser_ = new AccountChooser(controller_);
+  notification_area_ = new NotificationArea(controller_);
+  notification_area_->set_arrow_centering_anchor(account_chooser_->AsWeakPtr());
+  AddChildView(notification_area_);
+
+  scrollable_area_ = new views::ScrollView();
+  scrollable_area_->set_hide_horizontal_scrollbar(true);
+  scrollable_area_->SetContents(CreateDetailsContainer());
+  AddChildView(scrollable_area_);
+
+  autocheckout_steps_area_ = new AutocheckoutStepsArea();
+  AddChildView(autocheckout_steps_area_);
+
+  loading_shield_ = new views::Label();
+  loading_shield_->SetVisible(false);
+  loading_shield_->set_background(views::Background::CreateSolidBackground(
+      GetNativeTheme()->GetSystemColor(
+          ui::NativeTheme::kColorId_DialogBackground)));
+  loading_shield_->SetFont(ui::ResourceBundle::GetSharedInstance().GetFont(
+      ui::ResourceBundle::BaseFont).DeriveFont(15));
+  AddChildView(loading_shield_);
+
   sign_in_webview_ = new views::WebView(controller_->profile());
   sign_in_webview_->SetVisible(false);
-  contents_->AddChildView(sign_in_webview_);
+  AddChildView(sign_in_webview_);
   sign_in_delegate_.reset(
       new AutofillDialogSignInDelegate(this,
                                        sign_in_webview_->GetWebContents()));
 }
 
-views::View* AutofillDialogViews::CreateMainContainer() {
-  main_container_ = new views::View();
-  main_container_->SetLayoutManager(
-      new views::BoxLayout(views::BoxLayout::kVertical, 0, 0,
-                           views::kRelatedControlVerticalSpacing));
-
-  account_chooser_ = new AccountChooser(controller_);
-  if (!views::DialogDelegate::UseNewStyle())
-    main_container_->AddChildView(account_chooser_);
-
-  notification_area_ = new NotificationArea(controller_);
-  notification_area_->set_arrow_centering_anchor(account_chooser_->AsWeakPtr());
-  main_container_->AddChildView(notification_area_);
-
-  scrollable_area_ = new SizeLimitedScrollView(CreateDetailsContainer());
-  main_container_->AddChildView(scrollable_area_);
-  return main_container_;
-}
-
 views::View* AutofillDialogViews::CreateDetailsContainer() {
   details_container_ = new DetailsContainerView(
       base::Bind(&AutofillDialogViews::DetailsContainerBoundsChanged,
@@ -1572,7 +1732,7 @@
 
       gfx::Image icon =
           controller_->IconForField(input.type, input.initial_value);
-      field->textfield()->SetIcon(icon.AsImageSkia());
+      field->SetIcon(icon);
 
       textfields->insert(std::make_pair(&input, field));
       view_to_add = field;
@@ -1602,12 +1762,12 @@
     TextfieldMap::iterator text_mapping = group->textfields.find(&input);
 
     if (text_mapping != group->textfields.end()) {
-      views::Textfield* textfield = text_mapping->second->textfield();
-      textfield->SetEnabled(input.editable);
-      if (textfield->text().empty() || clobber_inputs) {
-        textfield->SetText(iter->initial_value);
-        textfield->SetIcon(controller_->IconForField(
-            input.type, textfield->text()).AsImageSkia());
+      DecoratedTextfield* decorated = text_mapping->second;
+      decorated->SetEnabled(input.editable);
+      if (decorated->text().empty() || clobber_inputs) {
+        decorated->SetText(iter->initial_value);
+        decorated->SetIcon(
+            controller_->IconForField(input.type, decorated->text()));
       }
     }
 
@@ -1642,7 +1802,7 @@
   if (!suggestion_state.extra_text.empty()) {
     group.suggested_info->ShowTextfield(
         suggestion_state.extra_text,
-        suggestion_state.extra_icon.AsImageSkia());
+        suggestion_state.extra_icon);
   }
 
   group.manual_input->SetVisible(!show_suggestions);
@@ -1689,44 +1849,57 @@
   if (!view->GetWidget())
     return;
 
-  views::View* input =
-      view->GetAncestorWithClassName(kDecoratedTextfieldClassName);
-  if (!input)
-    input = view;
-
-  if (error_bubble_ && error_bubble_->anchor() == input)
+  if (error_bubble_ && error_bubble_->anchor() == view)
     return;
 
   std::map<views::View*, string16>::iterator error_message =
-      validity_map_.find(input);
+      validity_map_.find(view);
   if (error_message != validity_map_.end())
-    error_bubble_.reset(new ErrorBubble(input, error_message->second));
+    error_bubble_.reset(new ErrorBubble(view, error_message->second));
 }
 
 void AutofillDialogViews::MarkInputsInvalid(DialogSection section,
                                             const ValidityData& validity_data) {
-  DetailsGroup group = *GroupForSection(section);
-  DCHECK(group.container->visible());
+  DetailsGroup* group = GroupForSection(section);
+  DCHECK(group->container->visible());
 
   typedef std::map<AutofillFieldType,
       base::Callback<void(const base::string16&)> > FieldMap;
   FieldMap field_map;
 
-  if (group.manual_input->visible()) {
-    for (TextfieldMap::const_iterator iter = group.textfields.begin();
-         iter != group.textfields.end(); ++iter) {
+  if (group->manual_input->visible()) {
+    for (TextfieldMap::const_iterator iter = group->textfields.begin();
+         iter != group->textfields.end(); ++iter) {
       field_map[iter->first->type] = base::Bind(
           &AutofillDialogViews::SetValidityForInput<DecoratedTextfield>,
           base::Unretained(this),
           iter->second);
     }
-    for (ComboboxMap::const_iterator iter = group.comboboxes.begin();
-         iter != group.comboboxes.end(); ++iter) {
+    for (ComboboxMap::const_iterator iter = group->comboboxes.begin();
+         iter != group->comboboxes.end(); ++iter) {
       field_map[iter->first->type] = base::Bind(
           &AutofillDialogViews::SetValidityForInput<views::Combobox>,
           base::Unretained(this),
           iter->second);
     }
+  } else {
+    // Purge invisible views from |validity_map_|.
+    std::map<views::View*, base::string16>::iterator it;
+    for (it = validity_map_.begin(); it != validity_map_.end();) {
+      DCHECK(GroupForView(it->first));
+      if (GroupForView(it->first) == group)
+        validity_map_.erase(it++);
+      else
+        ++it;
+    }
+
+    if (section == SECTION_CC) {
+      // Special case CVC as it's not part of |group->manual_input|.
+      field_map[CREDIT_CARD_VERIFICATION_CODE] = base::Bind(
+          &AutofillDialogViews::SetValidityForInput<DecoratedTextfield>,
+          base::Unretained(this),
+          group->suggested_info->decorated_textfield());
+    }
   }
 
   // Flag invalid fields, removing them from |field_map|.
@@ -1757,7 +1930,7 @@
       if (!iter->first->editable)
         continue;
 
-      detail_outputs[iter->first] = iter->second->textfield()->text();
+      detail_outputs[iter->first] = iter->second->text();
     }
     for (ComboboxMap::const_iterator iter = group.comboboxes.begin();
          iter != group.comboboxes.end(); ++iter) {
@@ -1774,7 +1947,7 @@
         group.suggested_info->decorated_textfield();
     cvc_input.reset(new DetailInput);
     cvc_input->type = CREDIT_CARD_VERIFICATION_CODE;
-    detail_outputs[cvc_input.get()] = decorated_cvc->textfield()->text();
+    detail_outputs[cvc_input.get()] = decorated_cvc->text();
   }
 
   ValidityData invalid_inputs = controller_->InputsAreValid(
@@ -1786,6 +1959,8 @@
 
 bool AutofillDialogViews::ValidateForm() {
   bool all_valid = true;
+  validity_map_.clear();
+
   for (DetailGroupMap::iterator iter = detail_groups_.begin();
        iter != detail_groups_.end(); ++iter) {
     const DetailsGroup& group = iter->second;
@@ -1810,13 +1985,11 @@
   DecoratedTextfield* decorated = NULL;
 
   // Look for the input in the manual inputs.
-  views::View* ancestor =
-      textfield->GetAncestorWithClassName(kDecoratedTextfieldClassName);
   for (TextfieldMap::const_iterator iter = group->textfields.begin();
        iter != group->textfields.end();
        ++iter) {
     decorated = iter->second;
-    if (decorated == ancestor) {
+    if (decorated == textfield) {
       controller_->UserEditedOrActivatedInput(group->section,
                                               iter->first,
                                               GetWidget()->GetNativeView(),
@@ -1828,7 +2001,7 @@
     }
   }
 
-  if (ancestor == group->suggested_info->decorated_textfield()) {
+  if (textfield == group->suggested_info->decorated_textfield()) {
     decorated = group->suggested_info->decorated_textfield();
     type = CREDIT_CARD_VERIFICATION_CODE;
   }
@@ -1852,7 +2025,7 @@
   }
 
   gfx::Image icon = controller_->IconForField(type, textfield->text());
-  textfield->SetIcon(icon.AsImageSkia());
+  decorated->SetIcon(icon);
 }
 
 void AutofillDialogViews::UpdateSaveInChromeCheckbox() {
@@ -1865,10 +2038,7 @@
     GetWidget()->SetSize(GetWidget()->non_client_view()->GetPreferredSize());
     // If the above line does not cause the dialog's size to change, |contents_|
     // may not be laid out. This will trigger a layout only if it's needed.
-    contents_->SetBoundsRect(contents_->bounds());
-
-    if (error_bubble_)
-      error_bubble_->UpdatePosition();
+    SetBoundsRect(bounds());
   }
 }
 
@@ -1878,25 +2048,23 @@
 }
 
 AutofillDialogViews::DetailsGroup* AutofillDialogViews::GroupForView(
-  views::View* view) {
+    views::View* view) {
   DCHECK(view);
-  // Textfields are treated slightly differently. For them, inspect
-  // the DecoratedTextfield ancestor, not the actual control.
-  views::View* ancestor =
-      view->GetAncestorWithClassName(kDecoratedTextfieldClassName);
 
-  views::View* control = ancestor ? ancestor : view;
   for (DetailGroupMap::iterator iter = detail_groups_.begin();
        iter != detail_groups_.end(); ++iter) {
     DetailsGroup* group = &iter->second;
-    if (control->parent() == group->manual_input)
+    if (view->parent() == group->manual_input)
       return group;
 
+    views::View* decorated =
+        view->GetAncestorWithClassName(kDecoratedTextfieldClassName);
+
     // Textfields need to check a second case, since they can be
     // suggested inputs instead of directly editable inputs. Those are
     // accessed via |suggested_info|.
-    if (ancestor &&
-        ancestor == group->suggested_info->decorated_textfield()) {
+    if (decorated &&
+        decorated == group->suggested_info->decorated_textfield()) {
       return group;
     }
   }
@@ -1910,7 +2078,7 @@
     const DetailsGroup& group = iter->second;
     TextfieldMap::const_iterator text_mapping = group.textfields.find(&input);
     if (text_mapping != group.textfields.end())
-      return text_mapping->second->textfield();
+      return text_mapping->second;
   }
 
   return NULL;
diff --git a/chrome/browser/ui/views/autofill/autofill_dialog_views.h b/chrome/browser/ui/views/autofill/autofill_dialog_views.h
index cff27ea..ef7d115 100644
--- a/chrome/browser/ui/views/autofill/autofill_dialog_views.h
+++ b/chrome/browser/ui/views/autofill/autofill_dialog_views.h
@@ -20,6 +20,7 @@
 #include "ui/views/controls/progress_bar.h"
 #include "ui/views/controls/scroll_view.h"
 #include "ui/views/controls/styled_label_listener.h"
+#include "ui/views/controls/textfield/textfield.h"
 #include "ui/views/controls/textfield/textfield_controller.h"
 #include "ui/views/focus/focus_manager.h"
 #include "ui/views/widget/widget_observer.h"
@@ -36,6 +37,7 @@
 namespace views {
 class Checkbox;
 class Combobox;
+class FocusableBorder;
 class FocusManager;
 class ImageButton;
 class ImageView;
@@ -43,7 +45,6 @@
 class Link;
 class MenuRunner;
 class StyledLabel;
-class Textfield;
 class WebView;
 class Widget;
 }  // namespace views
@@ -62,14 +63,13 @@
 // imperative autocomplete API call.
 class AutofillDialogViews : public AutofillDialogView,
                             public TestableAutofillDialogView,
-                            public views::DialogDelegate,
+                            public views::DialogDelegateView,
                             public views::WidgetObserver,
                             public views::ButtonListener,
                             public views::TextfieldController,
                             public views::FocusChangeListener,
                             public views::ComboboxListener,
-                            public views::StyledLabelListener,
-                            public ui::AcceleratorTarget {
+                            public views::StyledLabelListener {
  public:
   explicit AutofillDialogViews(AutofillDialogController* controller);
   virtual ~AutofillDialogViews();
@@ -78,6 +78,7 @@
   virtual void Show() OVERRIDE;
   virtual void Hide() OVERRIDE;
   virtual void UpdateAccountChooser() OVERRIDE;
+  virtual void UpdateAutocheckoutStepsArea() OVERRIDE;
   virtual void UpdateButtonStrip() OVERRIDE;
   virtual void UpdateDetailArea() OVERRIDE;
   virtual void UpdateForErrors() OVERRIDE;
@@ -102,6 +103,9 @@
   virtual string16 GetTextContentsOfInput(const DetailInput& input) OVERRIDE;
   virtual void SetTextContentsOfInput(const DetailInput& input,
                                       const string16& contents) OVERRIDE;
+  virtual void SetTextContentsOfSuggestionInput(
+      DialogSection section,
+      const base::string16& text) OVERRIDE;
   virtual void ActivateInput(const DetailInput& input) OVERRIDE;
   virtual gfx::Size GetSize() const OVERRIDE;
 
@@ -109,13 +113,15 @@
   virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE;
   virtual bool CanHandleAccelerators() const OVERRIDE;
 
+  // views::View implementation.
+  virtual gfx::Size GetPreferredSize() OVERRIDE;
+  virtual void Layout() OVERRIDE;
+  virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE;
+
   // views::DialogDelegate implementation:
   virtual string16 GetWindowTitle() const OVERRIDE;
   virtual void WindowClosing() OVERRIDE;
   virtual void DeleteDelegate() OVERRIDE;
-  virtual views::Widget* GetWidget() OVERRIDE;
-  virtual const views::Widget* GetWidget() const OVERRIDE;
-  virtual views::View* GetContentsView() OVERRIDE;
   virtual views::View* CreateOverlayView() OVERRIDE;
   virtual int GetDialogButtons() const OVERRIDE;
   virtual string16 GetDialogButtonLabel(ui::DialogButton button) const OVERRIDE;
@@ -159,26 +165,6 @@
       OVERRIDE;
 
  private:
-  // A view that contains a single child view, and adds a vertical scrollbar
-  // after a certain maximum height is reached.
-  class SizeLimitedScrollView : public views::ScrollView {
-   public:
-    explicit SizeLimitedScrollView(views::View* scroll_contents);
-    virtual ~SizeLimitedScrollView();
-
-    // views::View implementation.
-    virtual void Layout() OVERRIDE;
-    virtual gfx::Size GetPreferredSize() OVERRIDE;
-
-    // Sets the maximum height for the viewport.
-    void SetMaximumHeight(int max_height);
-
-   private:
-    int max_height_;
-
-    DISALLOW_COPY_AND_ASSIGN(SizeLimitedScrollView);
-  };
-
   // A class that creates and manages a widget for error messages.
   class ErrorBubble : public views::WidgetObserver {
    public:
@@ -211,28 +197,35 @@
 
   // A class which holds a textfield and draws extra stuff on top, like
   // invalid content indications.
-  class DecoratedTextfield : public views::View {
+  class DecoratedTextfield : public views::Textfield {
    public:
     DecoratedTextfield(const string16& default_value,
                        const string16& placeholder,
                        views::TextfieldController* controller);
     virtual ~DecoratedTextfield();
 
-    // The wrapped text field.
-    views::Textfield* textfield() { return textfield_; }
-
     // Sets whether to indicate the textfield has invalid content.
     void SetInvalid(bool invalid);
     bool invalid() const { return invalid_; }
 
+    // Sets the icon to be displayed inside the textfield at the end of the
+    // text.
+    void SetIcon(const gfx::Image& icon);
+
     // views::View implementation.
     virtual const char* GetClassName() const OVERRIDE;
     virtual void PaintChildren(gfx::Canvas* canvas) OVERRIDE;
     virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
-    virtual void RequestFocus() OVERRIDE;
 
    private:
-    views::Textfield* textfield_;
+    // We draw the border.
+    views::FocusableBorder* border_;  // Weak.
+
+    // The icon that goes at the right side of the textfield.
+    gfx::Image icon_;
+
+    // Whether the text contents are "invalid" (i.e. should special markers be
+    // shown to indicate invalidness).
     bool invalid_;
 
     DISALLOW_COPY_AND_ASSIGN(DecoratedTextfield);
@@ -379,7 +372,7 @@
     // Shows an auxiliary textfield to the right of the suggestion icon and
     // text. This is currently only used to show a CVC field for the CC section.
     void ShowTextfield(const string16& placeholder_text,
-                       const gfx::ImageSkia& icon);
+                       const gfx::Image& icon);
 
     DecoratedTextfield* decorated_textfield() { return decorated_; }
 
@@ -423,13 +416,26 @@
     views::ImageButton* suggested_button;
   };
 
+  // Area for displaying that status of various steps in an Autocheckout flow.
+  class AutocheckoutStepsArea : public views::View {
+   public:
+    AutocheckoutStepsArea();
+    virtual ~AutocheckoutStepsArea() {}
+
+    // Display the given steps.
+    void SetSteps(const std::vector<DialogAutocheckoutStep>& steps);
+
+   private:
+    DISALLOW_COPY_AND_ASSIGN(AutocheckoutStepsArea);
+  };
+
   class AutocheckoutProgressBar : public views::ProgressBar {
    public:
     AutocheckoutProgressBar();
     virtual ~AutocheckoutProgressBar();
 
    private:
-    // Overidden from View:
+    // Overriden from View
     virtual gfx::Size GetPreferredSize() OVERRIDE;
 
     DISALLOW_COPY_AND_ASSIGN(AutocheckoutProgressBar);
@@ -533,9 +539,6 @@
   // dialog is closing.
   views::Widget* window_;
 
-  // The top-level View for the dialog. Owned by the constrained window.
-  views::View* contents_;
-
   // A DialogSection-keyed map of the DetailGroup structs.
   DetailGroupMap detail_groups_;
 
@@ -552,15 +555,15 @@
   // sign-in.
   views::WebView* sign_in_webview_;
 
-  // View to host everything that isn't related to sign-in.
-  views::View* main_container_;
-
   // View that wraps |details_container_| and makes it scroll vertically.
-  SizeLimitedScrollView* scrollable_area_;
+  views::ScrollView* scrollable_area_;
 
   // View to host details sections.
   views::View* details_container_;
 
+  // A view that overlays |this| (for "loading..." messages).
+  views::Label* loading_shield_;
+
   // The view that completely overlays the dialog (used for the splash page).
   views::View* overlay_view_;
 
@@ -571,6 +574,9 @@
   // database. It lives in |extra_view_|.
   views::Checkbox* save_in_chrome_checkbox_;
 
+  // View to host Autocheckout steps.
+  AutocheckoutStepsArea* autocheckout_steps_area_;
+
   // View to host |autocheckout_progress_bar_| and its label.
   views::View* autocheckout_progress_bar_view_;
 
diff --git a/chrome/browser/ui/views/autofill/autofill_popup_view_views.cc b/chrome/browser/ui/views/autofill/autofill_popup_view_views.cc
index 2b0723a..661ef09 100644
--- a/chrome/browser/ui/views/autofill/autofill_popup_view_views.cc
+++ b/chrome/browser/ui/views/autofill/autofill_popup_view_views.cc
@@ -164,8 +164,6 @@
 }
 
 void AutofillPopupViewViews::HideInternal() {
-  AutofillPopupView::Hide();
-
   observing_widget_->RemoveObserver(this);
 }
 
diff --git a/chrome/browser/ui/views/avatar_label.cc b/chrome/browser/ui/views/avatar_label.cc
new file mode 100644
index 0000000..11a7056
--- /dev/null
+++ b/chrome/browser/ui/views/avatar_label.cc
@@ -0,0 +1,91 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/avatar_label.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "chrome/browser/themes/theme_properties.h"
+#include "chrome/browser/ui/views/avatar_menu_bubble_view.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "grit/generated_resources.h"
+#include "ui/base/events/event.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/theme_provider.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/color_utils.h"
+#include "ui/views/painter.h"
+
+namespace {
+
+// A special text button border for the managed user avatar label.
+class AvatarLabelBorder: public views::TextButtonBorder {
+ public:
+  explicit AvatarLabelBorder(ui::ThemeProvider* theme_provider);
+
+  virtual void Paint(const views::View& view, gfx::Canvas* canvas) OVERRIDE;
+
+ private:
+  scoped_ptr<views::Painter> hot_painter_;
+  scoped_ptr<views::Painter> painter_;
+
+  DISALLOW_COPY_AND_ASSIGN(AvatarLabelBorder);
+};
+
+AvatarLabelBorder::AvatarLabelBorder(ui::ThemeProvider* theme_provider) {
+  const int kHorizontalInset = 10;
+  const int kVerticalInset = 2;
+  SetInsets(gfx::Insets(
+      kVerticalInset, kHorizontalInset, kVerticalInset, kHorizontalInset));
+  SkColor color = theme_provider->GetColor(
+      ThemeProperties::COLOR_MANAGED_USER_LABEL_BACKGROUND);
+  SkColor color2 = color_utils::BlendTowardOppositeLuminance(color, 0x20);
+  painter_.reset(views::Painter::CreateVerticalGradient(color, color2));
+  hot_painter_.reset(views::Painter::CreateVerticalGradient(color2, color));
+}
+
+void AvatarLabelBorder::Paint(const views::View& view, gfx::Canvas* canvas) {
+  const views::TextButton* button =
+      static_cast<const views::TextButton*>(&view);
+  if (button->state() == views::TextButton::STATE_HOVERED ||
+      button->state() == views::TextButton::STATE_PRESSED)
+    hot_painter_->Paint(canvas, view.size());
+  else
+    painter_->Paint(canvas, view.size());
+}
+
+}  // namespace
+
+AvatarLabel::AvatarLabel(BrowserView* browser_view,
+                         ui::ThemeProvider* theme_provider)
+    : TextButton(NULL,
+                 l10n_util::GetStringUTF16(IDS_MANAGED_USER_AVATAR_LABEL)),
+      browser_view_(browser_view),
+      theme_provider_(theme_provider) {
+  SetFont(ui::ResourceBundle::GetSharedInstance().GetFont(
+      ui::ResourceBundle::SmallFont));
+  ClearMaxTextSize();
+  set_border(new AvatarLabelBorder(theme_provider));
+  UpdateLabelStyle();
+}
+
+AvatarLabel::~AvatarLabel() {}
+
+bool AvatarLabel::OnMousePressed(const ui::MouseEvent& event) {
+  if (!TextButton::OnMousePressed(event))
+    return false;
+
+  browser_view_->ShowAvatarBubbleFromAvatarButton();
+  return true;
+}
+
+void AvatarLabel::UpdateLabelStyle() {
+  SkColor color_label =
+      theme_provider_->GetColor(ThemeProperties::COLOR_MANAGED_USER_LABEL);
+  SetEnabledColor(color_label);
+  SetHighlightColor(color_label);
+  SetHoverColor(color_label);
+  SetDisabledColor(color_label);
+  SchedulePaint();
+}
diff --git a/chrome/browser/ui/views/avatar_label.h b/chrome/browser/ui/views/avatar_label.h
new file mode 100644
index 0000000..d2ad823
--- /dev/null
+++ b/chrome/browser/ui/views/avatar_label.h
@@ -0,0 +1,40 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_AVATAR_LABEL_H_
+#define CHROME_BROWSER_UI_VIEWS_AVATAR_LABEL_H_
+
+#include "base/compiler_specific.h"
+#include "ui/views/controls/button/text_button.h"
+
+class BrowserView;
+
+namespace ui {
+class MouseEvent;
+class ThemeProvider;
+}
+
+// AvatarLabel
+//
+// A label used to display a string indicating that the current profile belongs
+// to a managed user.
+class AvatarLabel : public views::TextButton {
+ public:
+  AvatarLabel(BrowserView* browser_view, ui::ThemeProvider* theme_provider);
+  virtual ~AvatarLabel();
+
+  // views::TextButton:
+  virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
+
+  // Update the style of the label according to the provided theme.
+  void UpdateLabelStyle();
+
+ private:
+  BrowserView* browser_view_;
+  ui::ThemeProvider* theme_provider_;
+
+  DISALLOW_COPY_AND_ASSIGN(AvatarLabel);
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_AVATAR_LABEL_H_
diff --git a/chrome/browser/ui/views/avatar_menu_bubble_view.cc b/chrome/browser/ui/views/avatar_menu_bubble_view.cc
index 1049861..6119289 100644
--- a/chrome/browser/ui/views/avatar_menu_bubble_view.cc
+++ b/chrome/browser/ui/views/avatar_menu_bubble_view.cc
@@ -41,6 +41,7 @@
 #include "ui/views/controls/link.h"
 #include "ui/views/controls/separator.h"
 #include "ui/views/layout/grid_layout.h"
+#include "ui/views/layout/layout_constants.h"
 #include "ui/views/widget/widget.h"
 
 namespace {
@@ -553,7 +554,6 @@
     preferred_size.Enlarge(
         0,
         kSeparatorPaddingY * 4 + separator_->GetPreferredSize().height() * 2);
-
   }
 
   const int kBubbleViewMaxWidth = 800;
@@ -563,10 +563,12 @@
   // We have to do this after the final width is calculated, since the label
   // will wrap based on the width.
   if (managed_user_info_) {
+    int remaining_width =
+        preferred_size.width() - icon_view_->GetPreferredSize().width() -
+        views::kRelatedControlSmallHorizontalSpacing;
     preferred_size.Enlarge(
         0,
-        managed_user_info_->GetHeightForWidth(preferred_size.width()) +
-            kItemMarginY);
+        managed_user_info_->GetHeightForWidth(remaining_width) + kItemMarginY);
   }
 
   return preferred_size;
@@ -594,9 +596,15 @@
     buttons_view_->SetBounds(0, y,
         width(), buttons_view_->GetPreferredSize().height());
   } else if (managed_user_info_) {
-    managed_user_info_->SizeToFit(width());
-    int height = managed_user_info_->GetPreferredSize().height();
-    managed_user_info_->SetBounds(0, y, width(), height);
+    gfx::Size icon_size = icon_view_->GetPreferredSize();
+    gfx::Rect icon_bounds(0, y, icon_size.width(), icon_size.height());
+    icon_view_->SetBoundsRect(icon_bounds);
+    int info_width = width() - icon_bounds.right() -
+                     views::kRelatedControlSmallHorizontalSpacing;
+    int height = managed_user_info_->GetHeightForWidth(info_width);
+    managed_user_info_->SetBounds(
+        icon_bounds.right() + views::kRelatedControlSmallHorizontalSpacing,
+        y, info_width, height);
     y += height + kItemMarginY + kSeparatorPaddingY;
     separator_switch_users_->SetBounds(0, y, width(), separator_height);
     y += separator_height + kSeparatorPaddingY;
@@ -749,6 +757,11 @@
   managed_user_info_->SetBackgroundColor(color());
   AddChildView(managed_user_info_);
 
+  // Add the managed user icon.
+  icon_view_ = new views::ImageView();
+  icon_view_->SetImage(avatar_menu_model_->GetManagedUserIcon().ToImageSkia());
+  AddChildView(icon_view_);
+
   // Add a link for switching profiles.
   separator_switch_users_ = new views::Separator(views::Separator::HORIZONTAL);
   AddChildView(separator_switch_users_);
diff --git a/chrome/browser/ui/views/avatar_menu_bubble_view.h b/chrome/browser/ui/views/avatar_menu_bubble_view.h
index 63d9263..29597b1 100644
--- a/chrome/browser/ui/views/avatar_menu_bubble_view.h
+++ b/chrome/browser/ui/views/avatar_menu_bubble_view.h
@@ -25,6 +25,7 @@
 
 namespace views {
 class CustomButton;
+class ImageView;
 class Label;
 class Link;
 class Separator;
@@ -112,6 +113,7 @@
   // avatar_menu_model_->GetManagedUserInformation() returns a non-empty string.
   // See OnAvatarMenuModelChanged().
   views::Label* managed_user_info_;
+  views::ImageView* icon_view_;
   views::Separator* separator_switch_users_;
   views::Link* switch_profile_link_;
 
diff --git a/chrome/browser/ui/views/avatar_menu_button_browsertest.cc b/chrome/browser/ui/views/avatar_menu_button_browsertest.cc
index bd294f8..611995e 100644
--- a/chrome/browser/ui/views/avatar_menu_button_browsertest.cc
+++ b/chrome/browser/ui/views/avatar_menu_button_browsertest.cc
@@ -6,7 +6,7 @@
 
 #include "base/command_line.h"
 #include "base/path_service.h"
-#include "base/utf_string_conversions.h"
+#include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/profiles/avatar_menu_model.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/browser_list.h"
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
index fce68ef..81b4a3b 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
@@ -78,6 +78,7 @@
 #include "ui/views/view_constants.h"
 #include "ui/views/widget/tooltip_manager.h"
 #include "ui/views/widget/widget.h"
+#include "ui/views/window/non_client_view.h"
 
 using content::OpenURLParams;
 using content::PageNavigator;
@@ -134,18 +135,6 @@
 // Tag for the 'Other bookmarks' button.
 static const int kOtherFolderButtonTag = 1;
 
-// TODO(kuan): change chrome::kNTPBookmarkBarHeight to this new height when
-// search_ntp replaces ntp4; for now, while both versions exist, this new height
-// is only needed locally.
-static const int kSearchNewTabBookmarkBarHeight = 40;
-
-// TODO(kuan): change BookmarkBarView::kNewtabHorizontalPadding and
-// BookmarkBarView::kNewtabVerticalPadding to these new values when search_ntp
-// replaces ntp4; for now, while both versions exist, these new values are only
-// needed locally.
-static const int kSearchNewTabHorizontalPadding = 2;
-static const int kSearchNewTabVerticalPadding = 5;
-
 // Tag for the 'Apps Shortcut' button.
 static const int kAppsShortcutButtonTag = 2;
 
@@ -336,18 +325,6 @@
       extension->GetType());
 }
 
-int GetNewtabHorizontalPadding() {
-  return chrome::IsInstantExtendedAPIEnabled()
-         ? kSearchNewTabHorizontalPadding
-         : BookmarkBarView::kNewtabHorizontalPadding;
-}
-
-int GetNewtabVerticalPadding() {
-  return chrome::IsInstantExtendedAPIEnabled()
-         ? kSearchNewTabVerticalPadding
-         : BookmarkBarView::kNewtabVerticalPadding;
-}
-
 }  // namespace
 
 // DropLocation ---------------------------------------------------------------
@@ -440,8 +417,7 @@
 
 // static
 const int BookmarkBarView::kMaxButtonWidth = 150;
-const int BookmarkBarView::kNewtabHorizontalPadding = 8;
-const int BookmarkBarView::kNewtabVerticalPadding = 12;
+const int BookmarkBarView::kNewtabHorizontalPadding = 2;
 const int BookmarkBarView::kToolbarAttachedBookmarkBarOverlap = 3;
 
 static const gfx::ImageSkia& GetDefaultFavicon() {
@@ -529,19 +505,13 @@
   bookmark_bar_state_ = state;
 }
 
-int BookmarkBarView::GetToolbarOverlap(bool return_max) const {
-  // When not detached, always overlap by the full amount.
-  if (return_max || bookmark_bar_state_ != BookmarkBar::DETACHED)
-    return kToolbarAttachedBookmarkBarOverlap;
-  // When detached with an infobar, overlap by 0 whenever the infobar
-  // is above us (i.e. when we're detached), since drawing over the infobar
-  // looks weird.
-  if (IsDetached() && infobar_visible_)
+int BookmarkBarView::GetFullyDetachedToolbarOverlap() const {
+  if (!infobar_visible_ && browser_->window()->IsFullscreen()) {
+    // There is no client edge to overlap when detached in fullscreen with no
+    // infobars visible.
     return 0;
-  // When detached with no infobar, animate the overlap between the attached and
-  // detached states.
-  return static_cast<int>(
-      kToolbarAttachedBookmarkBarOverlap * size_animation_->GetCurrentValue());
+  }
+  return views::NonClientFrameView::kClientEdgeThickness;
 }
 
 bool BookmarkBarView::is_animating() {
@@ -676,7 +646,23 @@
 }
 
 int BookmarkBarView::GetToolbarOverlap() const {
-  return GetToolbarOverlap(false);
+  int attached_overlap = kToolbarAttachedBookmarkBarOverlap +
+      views::NonClientFrameView::kClientEdgeThickness;
+  if (!IsDetached())
+    return attached_overlap;
+
+  int detached_overlap = GetFullyDetachedToolbarOverlap();
+
+  // Do not animate the overlap when the infobar is above us (i.e. when we're
+  // detached), since drawing over the infobar looks weird.
+  if (infobar_visible_)
+    return detached_overlap;
+
+  // When detached with no infobar, animate the overlap between the attached and
+  // detached states.
+  return detached_overlap + static_cast<int>(
+      (attached_overlap - detached_overlap) *
+          size_animation_->GetCurrentValue());
 }
 
 gfx::Size BookmarkBarView::GetPreferredSize() {
@@ -689,9 +675,13 @@
   // Bookmarks" folder, along with appropriate margins and button padding.
   int width = kLeftMargin;
 
-  if (bookmark_bar_state_ == BookmarkBar::DETACHED) {
+  int height = browser_defaults::kBookmarkBarHeight;
+  if (IsDetached()) {
     double current_state = 1 - size_animation_->GetCurrentValue();
-    width += 2 * static_cast<int>(GetNewtabHorizontalPadding() * current_state);
+    width += 2 * static_cast<int>(kNewtabHorizontalPadding * current_state);
+    height += static_cast<int>(
+        (chrome::kNTPBookmarkBarHeight - browser_defaults::kBookmarkBarHeight) *
+            current_state);
   }
 
   gfx::Size other_bookmarked_pref;
@@ -712,7 +702,7 @@
       overflow_pref.width() + kButtonPadding +
       bookmarks_separator_pref.width();
 
-  return gfx::Size(width, browser_defaults::kBookmarkBarHeight);
+  return gfx::Size(width, height);
 }
 
 void BookmarkBarView::Layout() {
@@ -946,10 +936,10 @@
   int64 install_time =
       g_browser_process->local_state()->GetInt64(prefs::kInstallDate);
   int64 time_from_install = base::Time::Now().ToTimeT() - install_time;
-  if (bookmark_bar_state_ == BookmarkBar::SHOW)
+  if (bookmark_bar_state_ == BookmarkBar::SHOW) {
     UMA_HISTOGRAM_COUNTS("Import.ShowDialog.FromBookmarkBarView",
                          time_from_install);
-  else if (bookmark_bar_state_ == BookmarkBar::DETACHED) {
+  } else if (bookmark_bar_state_ == BookmarkBar::DETACHED) {
     UMA_HISTOGRAM_COUNTS("Import.ShowDialog.FromFloatingBookmarkBarView",
                          time_from_install);
   }
@@ -1724,9 +1714,9 @@
 
   if (IsDetached()) {
     double current_state = 1 - size_animation_->GetCurrentValue();
-    x += static_cast<int>(GetNewtabHorizontalPadding() * current_state);
+    x += static_cast<int>(kNewtabHorizontalPadding * current_state);
     y += (View::height() - browser_defaults::kBookmarkBarHeight) / 2;
-    width -= static_cast<int>(GetNewtabHorizontalPadding() * current_state);
+    width -= static_cast<int>(kNewtabHorizontalPadding * current_state);
     separator_margin -= static_cast<int>(kSeparatorMargin * current_state);
   } else {
     // For the attached appearance, pin the content to the bottom of the bar
@@ -1747,8 +1737,6 @@
       bookmarks_separator_pref.width();
   if (other_bookmarked_button_->visible())
     max_x -= other_bookmarked_pref.width() + kButtonPadding;
-  if (apps_page_shortcut_->visible())
-    max_x -= apps_page_shortcut_pref.width() + kButtonPadding;
 
   // Next, layout out the buttons. Any buttons that are placed beyond the
   // visible region and made invisible.
@@ -1833,15 +1821,12 @@
     x += kRightMargin;
     prefsize.set_width(x);
     if (IsDetached()) {
-      x += static_cast<int>(GetNewtabHorizontalPadding() *
+      x += static_cast<int>(kNewtabHorizontalPadding *
           (1 - size_animation_->GetCurrentValue()));
-      int ntp_bookmark_bar_height =
-          chrome::IsInstantExtendedAPIEnabled()
-          ? kSearchNewTabBookmarkBarHeight : chrome::kNTPBookmarkBarHeight;
       prefsize.set_height(
           browser_defaults::kBookmarkBarHeight +
           static_cast<int>(
-              (ntp_bookmark_bar_height -
+              (chrome::kNTPBookmarkBarHeight -
                browser_defaults::kBookmarkBarHeight) *
               (1 - size_animation_->GetCurrentValue())));
     } else {
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.h b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.h
index 5768fc0..72b0e2c 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.h
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.h
@@ -67,10 +67,9 @@
   // The internal view class name.
   static const char kViewClassName[];
 
-  // Constants used in Browser View, as well as here.
+  // Constant used in Browser View, as well as here.
   // How inset the bookmarks bar is when displayed on the new tab page.
   static const int kNewtabHorizontalPadding;
-  static const int kNewtabVerticalPadding;
 
   // Maximum size of buttons on the bookmark bar.
   static const int kMaxButtonWidth;
@@ -101,9 +100,8 @@
   void SetBookmarkBarState(BookmarkBar::State state,
                            BookmarkBar::AnimateChangeType animate_type);
 
-  // How much we want the bookmark bar to overlap the toolbar.  If |return_max|
-  // is true, we return the maximum overlap rather than the current overlap.
-  int GetToolbarOverlap(bool return_max) const;
+  // Returns the toolbar overlap when fully detached.
+  int GetFullyDetachedToolbarOverlap() const;
 
   // Whether or not we are animating.
   bool is_animating();
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc
index dbeebea..d0b2ba8 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc
@@ -127,7 +127,7 @@
     profile_->GetPrefs()->SetBoolean(prefs::kShowBookmarkBar, true);
 
     Browser::CreateParams native_params(profile_.get(),
-                                        chrome::HOST_DESKTOP_TYPE_NATIVE);
+                                        chrome::GetActiveDesktop());
     browser_.reset(
         chrome::CreateBrowserWithTestWindowForParams(&native_params));
 
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc
index 3c2a170..ca52a45 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc
@@ -8,11 +8,11 @@
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
-#include "chrome/browser/bookmarks/bookmark_editor.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/browser/bookmarks/bookmark_utils.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/bookmarks/bookmark_editor.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/views/bookmarks/bookmark_bubble_view_observer.h"
@@ -22,6 +22,7 @@
 #include "ui/base/keycodes/keyboard_codes.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
+#include "ui/views/bubble/bubble_frame_view.h"
 #include "ui/views/controls/button/label_button.h"
 #include "ui/views/controls/combobox/combobox.h"
 #include "ui/views/controls/label.h"
@@ -37,14 +38,8 @@
 
 namespace {
 
-// Padding between "Title:" and the actual title.
-const int kTitlePadding = 4;
-
-// Minimum width for the fields - they will push out the size of the bubble if
-// necessary. This should be big enough so that the field pushes the right side
-// of the bubble far enough so that the edit button's left edge is to the right
-// of the field's left edge.
-const int kMinimumFieldSize = 180;
+// Minimum width of the the bubble.
+const int kMinBubbleWidth = 350;
 
 }  // namespace
 
@@ -89,6 +84,7 @@
   views::BubbleDelegateView::CreateBubble(bookmark_bubble_)->Show();
   // Select the entire title textfield contents when the bubble is first shown.
   bookmark_bubble_->title_tf_->SelectAll(true);
+  bookmark_bubble_->SetArrowPaintType(views::BubbleBorder::PAINT_NONE);
 
   if (bookmark_bubble_->observer_)
     bookmark_bubble_->observer_->OnBookmarkBubbleShown(url);
@@ -146,9 +142,16 @@
 }
 
 void BookmarkBubbleView::Init() {
-  remove_link_ = new views::Link(l10n_util::GetStringUTF16(
+  views::Label* title_label = new views::Label(
+      l10n_util::GetStringUTF16(
+          newly_bookmarked_ ? IDS_BOOKMARK_BUBBLE_PAGE_BOOKMARKED :
+                              IDS_BOOKMARK_BUBBLE_PAGE_BOOKMARK));
+  ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
+  title_label->SetFont(rb.GetFont(ui::ResourceBundle::MediumFont));
+
+  remove_button_ = new views::LabelButton(this, l10n_util::GetStringUTF16(
       IDS_BOOKMARK_BUBBLE_REMOVE_BOOKMARK));
-  remove_link_->set_listener(this);
+  remove_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
 
   edit_button_ = new views::LabelButton(
       this, l10n_util::GetStringUTF16(IDS_BOOKMARK_BUBBLE_OPTIONS));
@@ -166,66 +169,54 @@
   parent_combobox_->set_listener(this);
   parent_combobox_->SetAccessibleName(combobox_label->text());
 
-  views::Label* title_label = new views::Label(
-      l10n_util::GetStringUTF16(
-          newly_bookmarked_ ? IDS_BOOKMARK_BUBBLE_PAGE_BOOKMARKED :
-                              IDS_BOOKMARK_BUBBLE_PAGE_BOOKMARK));
-  ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
-  title_label->SetFont(rb.GetFont(ui::ResourceBundle::MediumFont));
-
   GridLayout* layout = new GridLayout(this);
   SetLayoutManager(layout);
 
-  ColumnSet* cs = layout->AddColumnSet(0);
-
-  // Top (title) row.
-  cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0, GridLayout::USE_PREF,
-                0, 0);
-  cs->AddPaddingColumn(1, views::kUnrelatedControlHorizontalSpacing);
+  const int kTitleColumnSetID = 0;
+  ColumnSet* cs = layout->AddColumnSet(kTitleColumnSetID);
   cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0, GridLayout::USE_PREF,
                 0, 0);
 
-  // Middle (input field) rows.
-  cs = layout->AddColumnSet(2);
+  // The column layout used for middle and bottom rows.
+  const int kFirstColumnSetID = 1;
+  cs = layout->AddColumnSet(kFirstColumnSetID);
   cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
                 GridLayout::USE_PREF, 0, 0);
-  cs->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
-  cs->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
-                GridLayout::USE_PREF, 0, kMinimumFieldSize);
+  cs->AddPaddingColumn(0, views::kUnrelatedControlHorizontalSpacing);
 
-  // Bottom (buttons) row.
-  cs = layout->AddColumnSet(3);
-  cs->AddPaddingColumn(1, views::kRelatedControlHorizontalSpacing);
+  cs->AddColumn(GridLayout::FILL, GridLayout::CENTER, 0,
+                GridLayout::USE_PREF, 0, 0);
+  cs->AddPaddingColumn(1, views::kUnrelatedControlLargeHorizontalSpacing);
+
   cs->AddColumn(GridLayout::LEADING, GridLayout::TRAILING, 0,
                 GridLayout::USE_PREF, 0, 0);
-  // We subtract 2 to account for the natural button padding, and
-  // to bring the separation visually in line with the row separation
-  // height.
-  cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing - 2);
+  cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
   cs->AddColumn(GridLayout::LEADING, GridLayout::TRAILING, 0,
                 GridLayout::USE_PREF, 0, 0);
 
-  layout->StartRow(0, 0);
+  layout->StartRow(0, kTitleColumnSetID);
   layout->AddView(title_label);
-  layout->AddView(remove_link_);
+  layout->AddPaddingRow(0, views::kUnrelatedControlHorizontalSpacing);
 
-  layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing);
-  layout->StartRow(0, 2);
+  layout->StartRow(0, kFirstColumnSetID);
   views::Label* label = new views::Label(
       l10n_util::GetStringUTF16(IDS_BOOKMARK_BUBBLE_TITLE_TEXT));
   layout->AddView(label);
   title_tf_ = new views::Textfield();
   title_tf_->SetText(GetTitle());
-  layout->AddView(title_tf_);
+  layout->AddView(title_tf_, 5, 1);
 
-  layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing);
+  layout->AddPaddingRow(0, views::kUnrelatedControlHorizontalSpacing);
 
-  layout->StartRow(0, 2);
+  layout->StartRow(0, kFirstColumnSetID);
   layout->AddView(combobox_label);
-  layout->AddView(parent_combobox_);
-  layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing);
+  layout->AddView(parent_combobox_, 5, 1);
 
-  layout->StartRow(0, 3);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
+
+  layout->StartRow(0, kFirstColumnSetID);
+  layout->SkipColumns(2);
+  layout->AddView(remove_button_);
   layout->AddView(edit_button_);
   layout->AddView(close_button_);
 
@@ -246,15 +237,20 @@
           BookmarkModelFactory::GetForProfile(profile_),
           BookmarkModelFactory::GetForProfile(profile_)->
               GetMostRecentlyAddedNodeForURL(url)),
-      remove_link_(NULL),
+      remove_button_(NULL),
       edit_button_(NULL),
       close_button_(NULL),
       title_tf_(NULL),
       parent_combobox_(NULL),
       remove_bookmark_(false),
       apply_edits_(true) {
+  const SkColor background_color = GetNativeTheme()->GetSystemColor(
+      ui::NativeTheme::kColorId_DialogBackground);
+  set_color(background_color);
+  set_background(views::Background::CreateSolidBackground(background_color));
+  set_margins(gfx::Insets(12, 19, 18, 18));
   // Compensate for built-in vertical padding in the anchor view's image.
-  set_anchor_view_insets(gfx::Insets(5, 0, 5, 0));
+  set_anchor_view_insets(gfx::Insets(7, 0, 7, 0));
 }
 
 string16 BookmarkBubbleView::GetTitle() {
@@ -269,21 +265,17 @@
   return string16();
 }
 
+gfx::Size BookmarkBubbleView::GetMinimumSize() {
+  gfx::Size size(views::BubbleDelegateView::GetPreferredSize());
+  size.SetToMax(gfx::Size(kMinBubbleWidth, 0));
+  return size;
+}
+
 void BookmarkBubbleView::ButtonPressed(views::Button* sender,
                                        const ui::Event& event) {
   HandleButtonPressed(sender);
 }
 
-void BookmarkBubbleView::LinkClicked(views::Link* source, int event_flags) {
-  DCHECK_EQ(remove_link_, source);
-  content::RecordAction(UserMetricsAction("BookmarkBubble_Unstar"));
-
-  // Set this so we remove the bookmark after the window closes.
-  remove_bookmark_ = true;
-  apply_edits_ = false;
-  StartFade(false);
-}
-
 void BookmarkBubbleView::OnSelectedIndexChanged(views::Combobox* combobox) {
   if (combobox->selected_index() + 1 == parent_model_.GetItemCount()) {
     content::RecordAction(UserMetricsAction("BookmarkBubble_EditFromCombobox"));
@@ -292,7 +284,13 @@
 }
 
 void BookmarkBubbleView::HandleButtonPressed(views::Button* sender) {
-  if (sender == edit_button_) {
+  if (sender == remove_button_) {
+    content::RecordAction(UserMetricsAction("BookmarkBubble_Unstar"));
+    // Set this so we remove the bookmark after the window closes.
+    remove_bookmark_ = true;
+    apply_edits_ = false;
+    StartFade(false);
+  } else if (sender == edit_button_) {
     content::RecordAction(UserMetricsAction("BookmarkBubble_Edit"));
     ShowEditor();
   } else {
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.h b/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.h
index 5f4e739..83923ec 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.h
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.h
@@ -13,7 +13,6 @@
 #include "ui/views/bubble/bubble_delegate.h"
 #include "ui/views/controls/button/button.h"
 #include "ui/views/controls/combobox/combobox_listener.h"
-#include "ui/views/controls/link_listener.h"
 
 class BookmarkBubbleViewObserver;
 class Profile;
@@ -28,7 +27,6 @@
 // bookmark it is created with. Don't create a BookmarkBubbleView directly,
 // instead use the static Show method.
 class BookmarkBubbleView : public views::BubbleDelegateView,
-                           public views::LinkListener,
                            public views::ButtonListener,
                            public views::ComboboxListener {
  public:
@@ -68,10 +66,8 @@
   // Returns the title to display.
   string16 GetTitle();
 
-  // Overridden from views::LinkListener:
-  // Either unstars the item or shows the bookmark editor (depending upon which
-  // link was clicked).
-  virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE;
+  // Overridden from views::View:
+  virtual gfx::Size GetMinimumSize() OVERRIDE;
 
   // Overridden from views::ButtonListener:
   // Closes the bubble or opens the edit dialog.
@@ -107,8 +103,8 @@
 
   RecentlyUsedFoldersComboModel parent_model_;
 
-  // Link for removing/unstarring the bookmark.
-  views::Link* remove_link_;
+  // Button for removing the bookmark.
+  views::LabelButton* remove_button_;
 
   // Button to bring up the editor.
   views::LabelButton* edit_button_;
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc
index 56be739..42c7d12 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc
@@ -547,7 +547,7 @@
   string16 new_title(title_tf_->text());
 
   if (!show_tree_) {
-    bookmark_utils::ApplyEditsWithNoFolderChange(
+    BookmarkEditor::ApplyEditsWithNoFolderChange(
         bb_model_, parent_, details_, new_title, new_url);
     return;
   }
@@ -557,7 +557,7 @@
   ApplyNameChangesAndCreateNewFolders(
       bb_model_->root_node(), tree_model_->GetRoot(), parent, &new_parent);
 
-  bookmark_utils::ApplyEditsWithPossibleFolderChange(
+  BookmarkEditor::ApplyEditsWithPossibleFolderChange(
       bb_model_, new_parent, details_, new_title, new_url);
 
   BookmarkExpandedStateTracker::Nodes expanded_nodes;
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_editor_view.h b/chrome/browser/ui/views/bookmarks/bookmark_editor_view.h
index b11f00d..21f553d 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_editor_view.h
+++ b/chrome/browser/ui/views/bookmarks/bookmark_editor_view.h
@@ -10,9 +10,9 @@
 #include "base/compiler_specific.h"
 #include "base/gtest_prod_util.h"
 #include "base/strings/string16.h"
-#include "chrome/browser/bookmarks/bookmark_editor.h"
 #include "chrome/browser/bookmarks/bookmark_expanded_state_tracker.h"
 #include "chrome/browser/bookmarks/bookmark_model_observer.h"
+#include "chrome/browser/ui/bookmarks/bookmark_editor.h"
 #include "ui/base/models/simple_menu_model.h"
 #include "ui/base/models/tree_node_model.h"
 #include "ui/views/context_menu_controller.h"
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.cc b/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.cc
index afd0b9f..5965de1 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.cc
@@ -9,7 +9,6 @@
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/browser/bookmarks/bookmark_node_data.h"
-#include "chrome/browser/bookmarks/bookmark_utils.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/bookmarks/bookmark_drag_drop.h"
 #include "chrome/browser/ui/bookmarks/bookmark_utils.h"
@@ -106,7 +105,12 @@
     int id,
     const gfx::Point& screen_loc) const {
   MenuIDToNodeMap::const_iterator i = menu_id_to_node_map_.find(id);
-  DCHECK(i != menu_id_to_node_map_.end());
+  // When removing bookmarks it may be possible to end up here without a node.
+  if (i == menu_id_to_node_map_.end()) {
+    DCHECK(is_mutating_model_);
+    return string16();
+  }
+
   const BookmarkNode* node = i->second;
   if (node->is_url()) {
     return BookmarkBarView::CreateToolTipForURLAndTitle(
@@ -369,10 +373,6 @@
   // is the DCHECK.
   DCHECK(changed_parent_menus.size() <= 1);
 
-  for (std::set<MenuItemView*>::const_iterator i(changed_parent_menus.begin());
-       i != changed_parent_menus.end(); ++i)
-    (*i)->ChildrenChanged();
-
   // Remove any descendants of the removed nodes in |node_to_menu_map_|.
   for (NodeToMenuMap::iterator i(node_to_menu_map_.begin());
        i != node_to_menu_map_.end(); ) {
@@ -391,6 +391,10 @@
       ++i;
     }
   }
+
+  for (std::set<MenuItemView*>::const_iterator i(changed_parent_menus.begin());
+       i != changed_parent_menus.end(); ++i)
+    (*i)->ChildrenChanged();
 }
 
 void BookmarkMenuDelegate::DidRemoveBookmarks() {
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.h b/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.h
index 6e36d04..7a8a2cb 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.h
+++ b/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.h
@@ -62,7 +62,7 @@
             const BookmarkNode* node,
             int start_child_index,
             ShowOptions show_options,
-            bookmark_utils::BookmarkLaunchLocation);
+            bookmark_utils::BookmarkLaunchLocation location);
 
   // Sets the PageNavigator.
   void SetPageNavigator(content::PageNavigator* navigator);
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate_unittest.cc b/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate_unittest.cc
new file mode 100644
index 0000000..5564601
--- /dev/null
+++ b/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate_unittest.cc
@@ -0,0 +1,97 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/bookmarks/bookmark_model.h"
+#include "chrome/browser/bookmarks/bookmark_model_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/test/base/browser_with_test_window_test.h"
+#include "chrome/test/base/testing_profile.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "ui/views/controls/menu/menu_runner.h"
+
+class BookmarkMenuDelegateTest : public BrowserWithTestWindowTest {
+ public:
+  BookmarkMenuDelegateTest() : model_(NULL) {
+  }
+
+  virtual void SetUp() OVERRIDE {
+    BrowserWithTestWindowTest::SetUp();
+
+    profile()->CreateBookmarkModel(true);
+
+    model_ = BookmarkModelFactory::GetForProfile(profile());
+    ui_test_utils::WaitForBookmarkModelToLoad(model_);
+
+    AddTestData();
+
+    bookmark_menu_delegate_.reset(
+        new BookmarkMenuDelegate(browser(), NULL, NULL, 0));
+  }
+
+  virtual void TearDown() OVERRIDE {
+    // Since we never show the menu we need to pass the MenuItemView to
+    // MenuRunner so that the MenuItemView is destroyed.
+    views::MenuRunner menu_runner(bookmark_menu_delegate_->menu());
+    bookmark_menu_delegate_.reset();
+    BrowserWithTestWindowTest::TearDown();
+  }
+
+ protected:
+  BookmarkModel* model_;
+
+  scoped_ptr<BookmarkMenuDelegate> bookmark_menu_delegate_;
+
+ private:
+  std::string base_path() const { return "file:///c:/tmp/"; }
+
+  // Creates the following structure:
+  // bookmark bar node
+  //   a
+  //   F1
+  //    f1a
+  //    F11
+  //     f11a
+  //   F2
+  // other node
+  //   oa
+  //   OF1
+  //     of1a
+  void AddTestData() {
+    const BookmarkNode* bb_node = model_->bookmark_bar_node();
+    std::string test_base = base_path();
+    model_->AddURL(bb_node, 0, ASCIIToUTF16("a"), GURL(test_base + "a"));
+    const BookmarkNode* f1 = model_->AddFolder(bb_node, 1, ASCIIToUTF16("F1"));
+    model_->AddURL(f1, 0, ASCIIToUTF16("f1a"), GURL(test_base + "f1a"));
+    const BookmarkNode* f11 = model_->AddFolder(f1, 1, ASCIIToUTF16("F11"));
+    model_->AddURL(f11, 0, ASCIIToUTF16("f11a"), GURL(test_base + "f11a"));
+    model_->AddFolder(bb_node, 2, ASCIIToUTF16("F2"));
+
+    // Children of the other node.
+    model_->AddURL(model_->other_node(), 0, ASCIIToUTF16("oa"),
+                   GURL(test_base + "oa"));
+    const BookmarkNode* of1 =
+        model_->AddFolder(model_->other_node(), 1, ASCIIToUTF16("OF1"));
+    model_->AddURL(of1, 0, ASCIIToUTF16("of1a"), GURL(test_base + "of1a"));
+  }
+
+  DISALLOW_COPY_AND_ASSIGN(BookmarkMenuDelegateTest);
+};
+
+// Verifies WillRemoveBookmarks() doesn't attempt to access MenuItemViews that
+// have since been deleted.
+TEST_F(BookmarkMenuDelegateTest, RemoveBookmarks) {
+  views::MenuDelegate test_delegate;
+  const BookmarkNode* node = model_->bookmark_bar_node()->GetChild(1);
+  bookmark_menu_delegate_->Init(&test_delegate, NULL, node, 0,
+                                BookmarkMenuDelegate::HIDE_PERMANENT_FOLDERS,
+                                bookmark_utils::LAUNCH_NONE);
+  std::vector<const BookmarkNode*> nodes_to_remove;
+  nodes_to_remove.push_back(node->GetChild(1));
+  bookmark_menu_delegate_->WillRemoveBookmarks(nodes_to_remove);
+  nodes_to_remove.clear();
+  bookmark_menu_delegate_->DidRemoveBookmarks();
+}
diff --git a/chrome/browser/ui/views/chrome_views_delegate.cc b/chrome/browser/ui/views/chrome_views_delegate.cc
index a84c8f5..f25f15a 100644
--- a/chrome/browser/ui/views/chrome_views_delegate.cc
+++ b/chrome/browser/ui/views/chrome_views_delegate.cc
@@ -4,12 +4,11 @@
 
 #include "chrome/browser/ui/views/chrome_views_delegate.h"
 
-#include "base/command_line.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/prefs/pref_service.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/prefs/scoped_user_pref_update.h"
 #include "chrome/browser/profiles/profile_manager.h"
@@ -25,6 +24,7 @@
 #include <dwmapi.h>
 #include "base/win/windows_version.h"
 #include "chrome/browser/app_icon_win.h"
+#include "ui/base/win/shell.h"
 #endif
 
 #if defined(USE_AURA)
@@ -204,28 +204,27 @@
       (!params->top_level ||
        chrome::GetHostDesktopTypeForNativeView(params->parent) !=
           chrome::HOST_DESKTOP_TYPE_NATIVE);
-#endif  // defined(OS_WIN)
 
-#if defined(OS_WIN)
-  // If we're on Vista+ with composition enabled, then we can use toplevel
-  // windows for most things (they get blended via WS_EX_COMPOSITED, which
-  // allows for animation effects, but also exceeding the bounds of the parent
-  // window).
-  if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
-    BOOL composition_enabled = FALSE;
-    HRESULT hr = DwmIsCompositionEnabled(&composition_enabled);
-    if (CommandLine::ForCurrentProcess()->HasSwitch(
-            switches::kDisableDwmComposition))
-      composition_enabled = FALSE;
-    if (SUCCEEDED(hr) && composition_enabled) {
-      if (chrome::GetActiveDesktop() != chrome::HOST_DESKTOP_TYPE_ASH &&
-          params->parent &&
-          params->type != views::Widget::InitParams::TYPE_CONTROL &&
-          params->type != views::Widget::InitParams::TYPE_WINDOW) {
-        // When we set this to false, we get a DesktopNativeWidgetAura from the
-        // default case (not handled in this function).
-        use_non_toplevel_window = false;
-      }
+  if (!ui::win::IsAeroGlassEnabled()) {
+    // If we don't have composition (either because Glass is not enabled or
+    // because it was disabled at the command line), anything that requires
+    // transparency will be broken with a toplevel window, so force the use of
+    // a non toplevel window.
+    if (params->opacity == views::Widget::InitParams::TRANSLUCENT_WINDOW &&
+        params->type != views::Widget::InitParams::TYPE_MENU)
+      use_non_toplevel_window = true;
+  } else {
+    // If we're on Vista+ with composition enabled, then we can use toplevel
+    // windows for most things (they get blended via WS_EX_COMPOSITED, which
+    // allows for animation effects, but also exceeding the bounds of the parent
+    // window).
+    if (chrome::GetActiveDesktop() != chrome::HOST_DESKTOP_TYPE_ASH &&
+        params->parent &&
+        params->type != views::Widget::InitParams::TYPE_CONTROL &&
+        params->type != views::Widget::InitParams::TYPE_WINDOW) {
+      // When we set this to false, we get a DesktopNativeWidgetAura from the
+      // default case (not handled in this function).
+      use_non_toplevel_window = false;
     }
   }
 #endif  // OS_WIN
diff --git a/chrome/browser/ui/views/chrome_views_delegate_chromeos.cc b/chrome/browser/ui/views/chrome_views_delegate_chromeos.cc
index f387f08..e1bcf4a 100644
--- a/chrome/browser/ui/views/chrome_views_delegate_chromeos.cc
+++ b/chrome/browser/ui/views/chrome_views_delegate_chromeos.cc
@@ -4,21 +4,19 @@
 
 #include "chrome/browser/ui/views/chrome_views_delegate.h"
 
-#include "base/time.h"
-#include "chrome/browser/chromeos/login/startup_utils.h"
+#include "base/time/time.h"
 #include "chrome/browser/chromeos/login/user_manager.h"
 #include "chrome/browser/chromeos/system/statistics_provider.h"
 #include "chromeos/chromeos_constants.h"
 
 base::TimeDelta
 ChromeViewsDelegate::GetDefaultTextfieldObscuredRevealDuration() {
-  // Enable password echo during OOBE when keyboard driven flag is set.
+  // Enable password echo on login screen when the keyboard driven flag is set.
   if (chromeos::UserManager::IsInitialized() &&
-      !chromeos::UserManager::Get()->IsUserLoggedIn() &&
-      !chromeos::StartupUtils::IsOobeCompleted()) {
+      !chromeos::UserManager::Get()->IsUserLoggedIn()) {
     bool keyboard_driven_oobe = false;
     chromeos::system::StatisticsProvider::GetInstance()->GetMachineFlag(
-        chromeos::kOemKeyboardDrivenOobeKey, &keyboard_driven_oobe);
+        chromeos::system::kOemKeyboardDrivenOobeKey, &keyboard_driven_oobe);
     if (keyboard_driven_oobe)
       return base::TimeDelta::FromSeconds(1);
   }
diff --git a/chrome/browser/ui/views/collected_cookies_views.cc b/chrome/browser/ui/views/collected_cookies_views.cc
index c91af18..4f26860 100644
--- a/chrome/browser/ui/views/collected_cookies_views.cc
+++ b/chrome/browser/ui/views/collected_cookies_views.cc
@@ -45,6 +45,7 @@
 #include "ui/views/layout/grid_layout.h"
 #include "ui/views/layout/layout_constants.h"
 #include "ui/views/widget/widget.h"
+#include "ui/views/window/dialog_delegate.h"
 
 using web_modal::WebContentsModalDialogManager;
 
@@ -310,11 +311,13 @@
                         GridLayout::USE_PREF, 0, 0);
 
   layout->StartRow(0, single_column_layout_id);
-  views::TabbedPane* tabbed_pane = new views::TabbedPane();
-  // This color matches tabbed_pane.cc's kTabBorderColor.
-  const SkColor border_color = SkColorSetRGB(0xCC, 0xCC, 0xCC);
-  // TODO(msw): Remove border and expand bounds in new dialog style.
-  tabbed_pane->set_border(views::Border::CreateSolidBorder(1, border_color));
+  views::TabbedPane* tabbed_pane = NULL;
+  if (DialogDelegate::UseNewStyle()) {
+    tabbed_pane = new views::TabbedPane(false);
+    layout->SetInsets(gfx::Insets());
+  } else {
+    tabbed_pane = new views::TabbedPane(true);
+  }
 
   layout->AddView(tabbed_pane);
   // NOTE: Panes must be added after |tabbed_pane| has been added to its parent.
diff --git a/chrome/browser/ui/views/constrained_window_views.cc b/chrome/browser/ui/views/constrained_window_views.cc
index ffba423..bc7bb68 100644
--- a/chrome/browser/ui/views/constrained_window_views.cc
+++ b/chrome/browser/ui/views/constrained_window_views.cc
@@ -661,7 +661,7 @@
             dialog,
             kWebContentsModalDialogHostObserverViewsKey);
 #if defined(USE_AURA)
-    params.transparent = true;
+    params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
 #endif
   } else {
     params.parent = parent;
diff --git a/chrome/browser/ui/views/cookie_info_view.cc b/chrome/browser/ui/views/cookie_info_view.cc
index 6747cd5..d7e1657 100644
--- a/chrome/browser/ui/views/cookie_info_view.cc
+++ b/chrome/browser/ui/views/cookie_info_view.cc
@@ -25,6 +25,7 @@
 #include "ui/views/controls/textfield/textfield.h"
 #include "ui/views/layout/grid_layout.h"
 #include "ui/views/layout/layout_constants.h"
+#include "ui/views/window/dialog_delegate.h"
 
 namespace {
 
@@ -184,9 +185,6 @@
 #else
   SkColor border_color = color_utils::GetSysSkColor(COLOR_3DSHADOW);
 #endif
-  views::Border* border = views::Border::CreateSolidBorder(
-      kCookieInfoViewBorderSize, border_color);
-  set_border(border);
 
   name_label_ = new views::Label(
       l10n_util::GetStringUTF16(IDS_COOKIES_COOKIE_NAME_LABEL));
@@ -217,10 +215,17 @@
   using views::ColumnSet;
 
   GridLayout* layout = new GridLayout(this);
-  layout->SetInsets(kCookieInfoViewInsetSize,
-                    kCookieInfoViewInsetSize,
-                    kCookieInfoViewInsetSize,
-                    kCookieInfoViewInsetSize);
+  if (views::DialogDelegate::UseNewStyle()) {
+    layout->SetInsets(
+        0, views::kButtonHEdgeMarginNew, 0, views::kButtonHEdgeMarginNew);
+  } else {
+    set_border(views::Border::CreateSolidBorder(kCookieInfoViewBorderSize,
+                                                border_color));
+    layout->SetInsets(kCookieInfoViewInsetSize,
+                      kCookieInfoViewInsetSize,
+                      kCookieInfoViewInsetSize,
+                      kCookieInfoViewInsetSize);
+  }
   SetLayoutManager(layout);
 
   int three_column_layout_id = 0;
diff --git a/chrome/browser/ui/views/create_application_shortcut_view.cc b/chrome/browser/ui/views/create_application_shortcut_view.cc
index 8fd8b73..80e346f 100644
--- a/chrome/browser/ui/views/create_application_shortcut_view.cc
+++ b/chrome/browser/ui/views/create_application_shortcut_view.cc
@@ -382,7 +382,8 @@
   creation_locations.in_quick_launch_bar = false;
 #endif
 
-  web_app::CreateShortcuts(shortcut_info_, creation_locations);
+  web_app::CreateShortcuts(shortcut_info_, creation_locations,
+                           web_app::ALLOW_DUPLICATE_SHORTCUTS);
   return true;
 }
 
@@ -456,11 +457,13 @@
   if (unprocessed_icons_.empty())  // No icons to fetch.
     return;
 
+  int preferred_size = std::max(unprocessed_icons_.back().width,
+                                unprocessed_icons_.back().height);
   pending_download_id_ = web_contents_->DownloadImage(
       unprocessed_icons_.back().url,
-      true,
-      std::max(unprocessed_icons_.back().width,
-               unprocessed_icons_.back().height),
+      true,  // is a favicon
+      preferred_size,
+      0,  // no maximum size
       base::Bind(&CreateUrlApplicationShortcutView::DidDownloadFavicon,
                  base::Unretained(this)));
 
diff --git a/chrome/browser/ui/views/critical_notification_bubble_view.h b/chrome/browser/ui/views/critical_notification_bubble_view.h
index d4facfc..f387c29 100644
--- a/chrome/browser/ui/views/critical_notification_bubble_view.h
+++ b/chrome/browser/ui/views/critical_notification_bubble_view.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_CRITICAL_NOTIFICATION_BUBBLE_VIEW_H_
 #define CHROME_BROWSER_UI_VIEWS_CRITICAL_NOTIFICATION_BUBBLE_VIEW_H_
 
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "ui/views/bubble/bubble_delegate.h"
 #include "ui/views/controls/button/button.h"
 
diff --git a/chrome/browser/ui/views/detachable_toolbar_view.cc b/chrome/browser/ui/views/detachable_toolbar_view.cc
index 4975158..b57e104 100644
--- a/chrome/browser/ui/views/detachable_toolbar_view.cc
+++ b/chrome/browser/ui/views/detachable_toolbar_view.cc
@@ -66,16 +66,6 @@
 }
 
 // static
-void DetachableToolbarView::PaintHorizontalBorderForState(
-    gfx::Canvas* canvas,
-    DetachableToolbarView* view) {
-  // Border can be at the top or at the bottom of the view depending on whether
-  // the view (bar/shelf) is attached or detached.
-  PaintHorizontalBorder(canvas, view, view->IsDetached(),
-                        ThemeProperties::GetDefaultColor(
-                            ThemeProperties::COLOR_TOOLBAR_SEPARATOR));
-}
-
 void DetachableToolbarView::PaintHorizontalBorder(
     gfx::Canvas* canvas,
     DetachableToolbarView* view,
diff --git a/chrome/browser/ui/views/detachable_toolbar_view.h b/chrome/browser/ui/views/detachable_toolbar_view.h
index 0fc784d..1148312 100644
--- a/chrome/browser/ui/views/detachable_toolbar_view.h
+++ b/chrome/browser/ui/views/detachable_toolbar_view.h
@@ -55,11 +55,6 @@
                                    views::View* view);
 
   // Paint the horizontal border separating the shelf/bar from the toolbar or
-  // page content according to view's detached/attached state.
-  static void PaintHorizontalBorderForState(gfx::Canvas* canvas,
-                                            DetachableToolbarView* view);
-
-  // Paint the horizontal border separating the shelf/bar from the toolbar or
   // page content according to |at_top| with |color|.
   static void PaintHorizontalBorder(gfx::Canvas* canvas,
                                     DetachableToolbarView* view,
diff --git a/chrome/browser/ui/views/download/download_item_view.h b/chrome/browser/ui/views/download/download_item_view.h
index ac672a5..61e7327 100644
--- a/chrome/browser/ui/views/download/download_item_view.h
+++ b/chrome/browser/ui/views/download/download_item_view.h
@@ -22,8 +22,8 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/strings/string_util.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/download/download_item_model.h"
 #include "chrome/browser/icon_manager.h"
 #include "chrome/common/cancelable_task_tracker.h"
diff --git a/chrome/browser/ui/views/download/download_started_animation_views.cc b/chrome/browser/ui/views/download/download_started_animation_views.cc
index 5b67f38..80252bd 100644
--- a/chrome/browser/ui/views/download/download_started_animation_views.cc
+++ b/chrome/browser/ui/views/download/download_started_animation_views.cc
@@ -109,7 +109,7 @@
   popup_ = new views::Widget;
 
   views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
-  params.transparent = true;
+  params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
   params.accept_events = false;
   params.parent = web_contents_->GetView()->GetNativeView();
   popup_->Init(params);
diff --git a/chrome/browser/ui/views/dropdown_bar_host.cc b/chrome/browser/ui/views/dropdown_bar_host.cc
index fb16b7c..1d150c8 100644
--- a/chrome/browser/ui/views/dropdown_bar_host.cc
+++ b/chrome/browser/ui/views/dropdown_bar_host.cc
@@ -67,7 +67,7 @@
   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
   params.parent = browser_view_->GetWidget()->GetNativeView();
 #if defined(USE_AURA)
-  params.transparent = true;
+  params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
 #endif
   host_->Init(params);
   host_->SetContentsView(view_);
diff --git a/chrome/browser/ui/views/extensions/extension_installed_bubble.cc b/chrome/browser/ui/views/extensions/extension_installed_bubble.cc
index caa0369..7d43187 100644
--- a/chrome/browser/ui/views/extensions/extension_installed_bubble.cc
+++ b/chrome/browser/ui/views/extensions/extension_installed_bubble.cc
@@ -19,13 +19,14 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/singleton_tabs.h"
+#include "chrome/browser/ui/sync/sync_promo_ui.h"
 #include "chrome/browser/ui/views/browser_action_view.h"
 #include "chrome/browser/ui/views/browser_actions_container.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/frame/immersive_mode_controller.h"
 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "chrome/browser/ui/views/tabs/tab_strip.h"
 #include "chrome/browser/ui/views/toolbar_view.h"
-#include "chrome/browser/ui/webui/sync_promo/sync_promo_ui.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "chrome/common/extensions/api/extension_action/action_info.h"
 #include "chrome/common/extensions/api/omnibox/omnibox_handler.h"
@@ -653,6 +654,15 @@
   SetLayoutManager(new views::FillLayout());
   AddChildView(
       new InstalledBubbleContent(browser_, extension_, type_, &icon_, this));
+
+  // If we are in immersive fullscreen, reveal the top-of-window views
+  // (omnibox, toolbar) so that the view the bubble is anchored to is visible.
+  // We do not need to hold onto the lock because ImmersiveModeController will
+  // keep the top-of-window views revealed as long as the popup is active.
+  // TODO(pkotwicz): Move logic to ImmersiveModeController.
+  scoped_ptr<ImmersiveRevealedLock> immersive_reveal_lock(
+      browser_view->immersive_mode_controller()->GetRevealedLock(
+          ImmersiveModeController::ANIMATE_REVEAL_NO));
   views::BubbleDelegateView::CreateBubble(this);
 
   // The bubble widget is now the parent and owner of |this| and takes care of
diff --git a/chrome/browser/ui/views/extensions/extension_popup.cc b/chrome/browser/ui/views/extensions/extension_popup.cc
index d02e840..0c36f22 100644
--- a/chrome/browser/ui/views/extensions/extension_popup.cc
+++ b/chrome/browser/ui/views/extensions/extension_popup.cc
@@ -13,6 +13,9 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/frame/immersive_mode_controller.h"
+#include "chrome/browser/ui/views/frame/top_container_view.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "content/public/browser/devtools_agent_host.h"
 #include "content/public/browser/devtools_manager.h"
@@ -67,6 +70,7 @@
                                views::BubbleBorder::Arrow arrow,
                                ShowAction show_action)
     : BubbleDelegateView(anchor_view, arrow),
+      browser_(browser),
       extension_host_(host),
       devtools_callback_(base::Bind(
           &ExtensionPopup::OnDevToolsStateChanged, base::Unretained(this))) {
@@ -193,6 +197,21 @@
 }
 
 void ExtensionPopup::ShowBubble() {
+  BrowserView* browser_view = browser_ ?
+      BrowserView::GetBrowserViewForBrowser(browser_) : NULL;
+  scoped_ptr<ImmersiveRevealedLock> immersive_reveal_lock;
+  if (browser_view &&
+      browser_view->top_container()->Contains(anchor_view())) {
+    // If we are in immersive fullscreen and we are anchored to a view in the
+    // top-of-window views (eg omnibox, toolbar), trigger an immersive reveal.
+    // We do not need to hold onto the lock because ImmersiveModeController will
+    // keep the top-of-window views revealed as long as the popup is active.
+    // TODO(pkotwicz): Move logic to ImmersiveModeController.
+    immersive_reveal_lock.reset(
+        browser_view->immersive_mode_controller()->GetRevealedLock(
+            ImmersiveModeController::ANIMATE_REVEAL_NO));
+    SizeToContents();
+  }
   GetWidget()->Show();
 
   // Focus on the host contents when the bubble is first shown.
diff --git a/chrome/browser/ui/views/extensions/extension_popup.h b/chrome/browser/ui/views/extensions/extension_popup.h
index f8b3237..b3b031a 100644
--- a/chrome/browser/ui/views/extensions/extension_popup.h
+++ b/chrome/browser/ui/views/extensions/extension_popup.h
@@ -84,6 +84,9 @@
 
   void OnDevToolsStateChanged(content::DevToolsAgentHost*, bool attached);
 
+  // The browser to which the popup is anchored. Not owned.
+  Browser* browser_;
+
   // The contained host for the view.
   scoped_ptr<extensions::ExtensionHost> extension_host_;
 
diff --git a/chrome/browser/ui/views/extensions/media_galleries_dialog_views.cc b/chrome/browser/ui/views/extensions/media_galleries_dialog_views.cc
index 7e80dd0..409b889 100644
--- a/chrome/browser/ui/views/extensions/media_galleries_dialog_views.cc
+++ b/chrome/browser/ui/views/extensions/media_galleries_dialog_views.cc
@@ -192,24 +192,6 @@
   layout->AddView(scroll_view, 1, 1,
                   views::GridLayout::FILL, views::GridLayout::FILL,
                   dialog_content_width, kScrollAreaHeight);
-
-  // Add location button.
-  add_gallery_button_ = new views::LabelButton(this,
-      l10n_util::GetStringUTF16(IDS_MEDIA_GALLERIES_DIALOG_ADD_GALLERY));
-  add_gallery_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
-  views::View* add_gallery_container = new views::View();
-  add_gallery_container->SetLayoutManager(
-      new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0));
-  add_gallery_container->set_border(views::Border::CreateEmptyBorder(
-      views::kRelatedControlVerticalSpacing,
-      0,
-      views::kRelatedControlVerticalSpacing,
-      0));
-  add_gallery_container->AddChildView(add_gallery_button_);
-
-  layout->StartRowWithPadding(0, column_set_id,
-                              0, views::kRelatedControlVerticalSpacing);
-  layout->AddView(add_gallery_container);
 }
 
 void MediaGalleriesDialogViews::UpdateGallery(
@@ -229,13 +211,9 @@
     bool permitted,
     views::View* container,
     int trailing_vertical_space) {
-  string16 label =
-      MediaGalleriesDialogController::GetGalleryDisplayNameNoAttachment(
-          gallery);
-  string16 tooltip_text =
-      MediaGalleriesDialogController::GetGalleryTooltip(gallery);
-  string16 details =
-      MediaGalleriesDialogController::GetGalleryAdditionalDetails(gallery);
+  string16 label = gallery.GetGalleryDisplayName();
+  string16 tooltip_text = gallery.GetGalleryTooltip();
+  string16 details = gallery.GetGalleryAdditionalDetails();
 
   CheckboxMap::iterator iter = checkbox_map_.find(gallery.pref_id);
   if (iter != checkbox_map_.end()) {
@@ -330,6 +308,14 @@
 #endif
 }
 
+views::View* MediaGalleriesDialogViews::CreateExtraView() {
+  DCHECK(!add_gallery_button_);
+  add_gallery_button_ = new views::LabelButton(this,
+      l10n_util::GetStringUTF16(IDS_MEDIA_GALLERIES_DIALOG_ADD_GALLERY));
+  add_gallery_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
+  return add_gallery_button_;
+}
+
 bool MediaGalleriesDialogViews::Cancel() {
   return true;
 }
diff --git a/chrome/browser/ui/views/extensions/media_galleries_dialog_views.h b/chrome/browser/ui/views/extensions/media_galleries_dialog_views.h
index cd043b9..a6944be 100644
--- a/chrome/browser/ui/views/extensions/media_galleries_dialog_views.h
+++ b/chrome/browser/ui/views/extensions/media_galleries_dialog_views.h
@@ -45,6 +45,7 @@
   virtual string16 GetDialogButtonLabel(ui::DialogButton button) const OVERRIDE;
   virtual bool IsDialogButtonEnabled(ui::DialogButton button) const OVERRIDE;
   virtual ui::ModalType GetModalType() const OVERRIDE;
+  virtual views::View* CreateExtraView() OVERRIDE;
   virtual bool Cancel() OVERRIDE;
   virtual bool Accept() OVERRIDE;
   virtual views::NonClientFrameView* CreateNonClientFrameView(
diff --git a/chrome/browser/ui/views/extensions/native_app_window_views.cc b/chrome/browser/ui/views/extensions/native_app_window_views.cc
index a030010..8d5433a 100644
--- a/chrome/browser/ui/views/extensions/native_app_window_views.cc
+++ b/chrome/browser/ui/views/extensions/native_app_window_views.cc
@@ -30,6 +30,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/ui/web_applications/web_app_ui.h"
 #include "chrome/browser/web_applications/web_app.h"
+#include "chrome/browser/web_applications/web_app_win.h"
 #include "ui/base/win/shell.h"
 #include "ui/views/win/hwnd_util.h"
 #endif
@@ -46,6 +47,8 @@
 #include "ui/aura/window.h"
 #endif
 
+using apps::ShellWindow;
+
 namespace {
 
 const int kMinPanelWidth = 100;
diff --git a/chrome/browser/ui/views/extensions/native_app_window_views.h b/chrome/browser/ui/views/extensions/native_app_window_views.h
index 0b66b57..138a9e0 100644
--- a/chrome/browser/ui/views/extensions/native_app_window_views.h
+++ b/chrome/browser/ui/views/extensions/native_app_window_views.h
@@ -5,9 +5,9 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_EXTENSIONS_NATIVE_APP_WINDOW_VIEWS_H_
 #define CHROME_BROWSER_UI_VIEWS_EXTENSIONS_NATIVE_APP_WINDOW_VIEWS_H_
 
+#include "apps/shell_window.h"
 #include "base/observer_list.h"
 #include "chrome/browser/ui/extensions/native_app_window.h"
-#include "chrome/browser/ui/extensions/shell_window.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "third_party/skia/include/core/SkRegion.h"
 #include "ui/gfx/image/image_skia.h"
@@ -41,16 +41,18 @@
                              public views::WidgetObserver,
                              public content::WebContentsObserver {
  public:
-  NativeAppWindowViews(ShellWindow* shell_window,
-                       const ShellWindow::CreateParams& params);
+  NativeAppWindowViews(apps::ShellWindow* shell_window,
+                       const apps::ShellWindow::CreateParams& params);
   virtual ~NativeAppWindowViews();
 
   bool frameless() const { return frameless_; }
   SkRegion* draggable_region() { return draggable_region_.get(); }
 
  private:
-  void InitializeDefaultWindow(const ShellWindow::CreateParams& create_params);
-  void InitializePanelWindow(const ShellWindow::CreateParams& create_params);
+  void InitializeDefaultWindow(
+      const apps::ShellWindow::CreateParams& create_params);
+  void InitializePanelWindow(
+      const apps::ShellWindow::CreateParams& create_params);
   void OnViewWasResized();
 
   bool ShouldUseChromeStyleFrame() const;
@@ -154,7 +156,7 @@
     return shell_window_->extension();
   }
 
-  ShellWindow* shell_window_; // weak - ShellWindow owns NativeAppWindow.
+  apps::ShellWindow* shell_window_; // weak - ShellWindow owns NativeAppWindow.
   views::WebView* web_view_;
   views::Widget* window_;
   bool is_fullscreen_;
diff --git a/chrome/browser/ui/views/external_protocol_dialog.h b/chrome/browser/ui/views/external_protocol_dialog.h
index e16ec67..2f79103 100644
--- a/chrome/browser/ui/views/external_protocol_dialog.h
+++ b/chrome/browser/ui/views/external_protocol_dialog.h
@@ -7,7 +7,7 @@
 
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "googleurl/src/gurl.h"
 #include "ui/views/window/dialog_delegate.h"
 
diff --git a/chrome/browser/ui/views/external_tab_container_win.cc b/chrome/browser/ui/views/external_tab_container_win.cc
index 4970de9..92c5834 100644
--- a/chrome/browser/ui/views/external_tab_container_win.cc
+++ b/chrome/browser/ui/views/external_tab_container_win.cc
@@ -19,7 +19,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/win/win_util.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/app/chrome_dll_resource.h"
@@ -342,6 +342,7 @@
   params.desktop_root_window_host =
       new ExternalTabRootWindowHost(widget_, native_widget, params.bounds);
   params.type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS;
+  params.opacity = views::Widget::InitParams::OPAQUE_WINDOW;
 #endif
   widget_->Init(params);
 
@@ -831,7 +832,12 @@
 void ExternalTabContainerWin::RegisterRenderViewHostForAutomation(
     bool pending_view,
     RenderViewHost* render_view_host) {
-  if (render_view_host) {
+  if (!GetTabHandle()) {
+    // This method is being called when it shouldn't be on the win_rel trybot;
+    // see http://crbug.com/250965. Don't crash release builds in that case
+    // until the root cause can be diagnosed and fixed. TODO(grt): fix this.
+    DLOG(FATAL) << "tab_handle_ unset";
+  } else if (render_view_host) {
     AutomationResourceMessageFilter::RegisterRenderView(
         render_view_host->GetProcess()->GetID(),
         render_view_host->GetRoutingID(),
diff --git a/chrome/browser/ui/views/frame/app_non_client_frame_view_ash.cc b/chrome/browser/ui/views/frame/app_non_client_frame_view_ash.cc
index c604457..fbdb190 100644
--- a/chrome/browser/ui/views/frame/app_non_client_frame_view_ash.cc
+++ b/chrome/browser/ui/views/frame/app_non_client_frame_view_ash.cc
@@ -214,7 +214,7 @@
   control_widget_ = new views::Widget;
   views::Widget::InitParams params(views::Widget::InitParams::TYPE_CONTROL);
   params.parent = browser_view->GetNativeWindow();
-  params.transparent = true;
+  params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
   control_widget_->Init(params);
   control_widget_->SetContentsView(control_view_);
   aura::Window* window = control_widget_->GetNativeView();
diff --git a/chrome/browser/ui/views/frame/browser_desktop_root_window_host_win.cc b/chrome/browser/ui/views/frame/browser_desktop_root_window_host_win.cc
index 07f888d..3e8e4d7 100644
--- a/chrome/browser/ui/views/frame/browser_desktop_root_window_host_win.cc
+++ b/chrome/browser/ui/views/frame/browser_desktop_root_window_host_win.cc
@@ -151,6 +151,10 @@
 }
 
 void BrowserDesktopRootWindowHostWin::HandleFrameChanged() {
+  // Reinitialize the status bubble, since it needs to be initialized
+  // differently depending on whether or not DWM composition is enabled
+  browser_view_->InitStatusBubble();
+
   // We need to update the glass region on or off before the base class adjusts
   // the window region.
   UpdateDWMFrame();
diff --git a/chrome/browser/ui/views/frame/browser_frame_win.cc b/chrome/browser/ui/views/frame/browser_frame_win.cc
index cc0f756..7234942 100644
--- a/chrome/browser/ui/views/frame/browser_frame_win.cc
+++ b/chrome/browser/ui/views/frame/browser_frame_win.cc
@@ -14,9 +14,7 @@
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/lifetime/application_lifetime.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/search_engines/template_url.h"
-#include "chrome/browser/search_engines/template_url_service.h"
-#include "chrome/browser/search_engines/template_url_service_factory.h"
+#include "chrome/browser/search_engines/util.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
@@ -466,22 +464,11 @@
   DCHECK(browser);
 
   GURL request_url;
-
   if (w_param) {
-    const wchar_t* url = reinterpret_cast<const wchar_t*>(w_param);
-    request_url = GURL(url);
+    request_url = GURL(reinterpret_cast<const wchar_t*>(w_param));
   } else if (l_param) {
-    const wchar_t* search_string =
-        reinterpret_cast<const wchar_t*>(l_param);
-    const TemplateURL* default_provider =
-        TemplateURLServiceFactory::GetForProfile(browser->profile())->
-        GetDefaultSearchProvider();
-    if (default_provider) {
-      const TemplateURLRef& search_url = default_provider->url_ref();
-      DCHECK(search_url.SupportsReplacement());
-      request_url = GURL(search_url.ReplaceSearchTerms(
-          TemplateURLRef::SearchTermsArgs(search_string)));
-    }
+    request_url = GetDefaultSearchURLForSearchTerms(
+        browser->profile(), reinterpret_cast<const wchar_t*>(l_param));
   }
   if (request_url.is_valid()) {
     browser->OpenURL(OpenURLParams(request_url, Referrer(), NEW_FOREGROUND_TAB,
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc
index 049e266..d7e2f76 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc
@@ -9,7 +9,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_info_cache.h"
 #include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/browser/themes/theme_properties.h"
+#include "chrome/browser/ui/views/avatar_label.h"
 #include "chrome/browser/ui/views/avatar_menu_button.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/frame/taskbar_decorator.h"
@@ -21,7 +21,6 @@
 #include "ui/base/theme_provider.h"
 #include "ui/gfx/image/image.h"
 #include "ui/views/background.h"
-#include "ui/views/controls/label.h"
 
 #if defined(ENABLE_MANAGED_USERS)
 #include "chrome/browser/managed_mode/managed_user_service.h"
@@ -31,7 +30,9 @@
 BrowserNonClientFrameView::BrowserNonClientFrameView(BrowserFrame* frame,
                                                      BrowserView* browser_view)
     : frame_(frame),
-      browser_view_(browser_view) {
+      browser_view_(browser_view),
+      avatar_button_(NULL),
+      avatar_label_(NULL) {
 }
 
 BrowserNonClientFrameView::~BrowserNonClientFrameView() {
@@ -48,54 +49,38 @@
 }
 
 void BrowserNonClientFrameView::OnThemeChanged() {
-  UpdateAvatarLabelStyle();
-}
-
-void BrowserNonClientFrameView::UpdateAvatarLabelStyle() {
-  if (!avatar_label_.get())
-    return;
-
-  ui::ThemeProvider* tp = frame_->GetThemeProvider();
-  SkColor color_background = tp->GetColor(
-      ThemeProperties::COLOR_MANAGED_USER_LABEL_BACKGROUND);
-  avatar_label_->set_background(
-      views::Background::CreateSolidBackground(color_background));
-  avatar_label_->SetBackgroundColor(color_background);
-  SkColor color_label = tp->GetColor(
-      ThemeProperties::COLOR_MANAGED_USER_LABEL);
-  avatar_label_->SetEnabledColor(color_label);
+  if (avatar_label_)
+    avatar_label_->UpdateLabelStyle();
 }
 
 void BrowserNonClientFrameView::UpdateAvatarInfo() {
   if (browser_view_->ShouldShowAvatar()) {
-    if (!avatar_button_.get()) {
-      avatar_button_.reset(
-          new AvatarMenuButton(browser_view_->browser(),
-                               browser_view_->IsOffTheRecord()));
-      AddChildView(avatar_button_.get());
+    if (!avatar_button_) {
+      avatar_button_ = new AvatarMenuButton(browser_view_->browser(),
+                                            browser_view_->IsOffTheRecord());
+      AddChildView(avatar_button_);
 #if defined(ENABLE_MANAGED_USERS)
       Profile* profile = browser_view_->browser()->profile();
       ManagedUserService* service =
           ManagedUserServiceFactory::GetForProfile(profile);
-      if (service->ProfileIsManaged() && !avatar_label_.get()) {
-        ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
-        avatar_label_.reset(new views::Label(
-            l10n_util::GetStringUTF16(IDS_MANAGED_USER_AVATAR_LABEL),
-            rb.GetFont(ui::ResourceBundle::BoldFont)));
-        UpdateAvatarLabelStyle();
-        AddChildView(avatar_label_.get());
+      if (service->ProfileIsManaged() && !avatar_label_) {
+        avatar_label_ =
+            new AvatarLabel(browser_view_, frame_->GetThemeProvider());
+        AddChildView(avatar_label_);
       }
 #endif
       frame_->GetRootView()->Layout();
     }
-  } else if (avatar_button_.get()) {
+  } else if (avatar_button_) {
     // The avatar label can just be there if there is also an avatar button.
-    if (avatar_label_.get()) {
-      RemoveChildView(avatar_label_.get());
-      avatar_label_.reset();
+    if (avatar_label_) {
+      RemoveChildView(avatar_label_);
+      delete avatar_label_;
+      avatar_label_ = NULL;
     }
-    RemoveChildView(avatar_button_.get());
-    avatar_button_.reset();
+    RemoveChildView(avatar_button_);
+    delete avatar_button_;
+    avatar_button_ = NULL;
     frame_->GetRootView()->Layout();
   }
 
@@ -118,7 +103,7 @@
     avatar = cache.GetAvatarIconOfProfileAtIndex(index);
     text = cache.GetNameOfProfileAtIndex(index);
   }
-  if (avatar_button_.get()) {
+  if (avatar_button_) {
     avatar_button_->SetAvatarIcon(avatar, is_gaia_picture);
     if (!text.empty())
       avatar_button_->SetText(text);
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
index 8f319a8..91a9b0d 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
@@ -5,17 +5,13 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_NON_CLIENT_FRAME_VIEW_H_
 #define CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_NON_CLIENT_FRAME_VIEW_H_
 
-#include "base/memory/scoped_ptr.h"
 #include "ui/views/window/non_client_view.h"
 
+class AvatarLabel;
 class AvatarMenuButton;
 class BrowserFrame;
 class BrowserView;
 
-namespace views {
-class Label;
-}
-
 // A specialization of the NonClientFrameView object that provides additional
 // Browser-specific methods.
 class BrowserNonClientFrameView : public views::NonClientFrameView {
@@ -36,9 +32,9 @@
   BrowserNonClientFrameView(BrowserFrame* frame, BrowserView* browser_view);
   virtual ~BrowserNonClientFrameView();
 
-  AvatarMenuButton* avatar_button() const { return avatar_button_.get(); }
+  AvatarMenuButton* avatar_button() const { return avatar_button_; }
 
-  views::Label* avatar_label() const { return avatar_label_.get(); }
+  AvatarLabel* avatar_label() const { return avatar_label_; }
 
   // Returns the bounds within which the TabStrip should be laid out.
   virtual gfx::Rect GetBoundsForTabStrip(views::View* tabstrip) const = 0;
@@ -63,9 +59,6 @@
   BrowserView* browser_view() const { return browser_view_; }
   BrowserFrame* frame() const { return frame_; }
 
-  // Determine the color of the label text and the label background.
-  void UpdateAvatarLabelStyle();
-
   // Updates the title and icon of the avatar button.
   void UpdateAvatarInfo();
 
@@ -78,10 +71,10 @@
 
   // Menu button that displays that either the incognito icon or the profile
   // icon.  May be NULL for some frame styles.
-  scoped_ptr<AvatarMenuButton> avatar_button_;
+  AvatarMenuButton* avatar_button_;
 
   // Avatar label that is used for a managed user.
-  scoped_ptr<views::Label> avatar_label_;
+  AvatarLabel* avatar_label_;
 };
 
 namespace chrome {
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
index 28b2be3..523a456 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
@@ -11,6 +11,7 @@
 #include "chrome/browser/ui/ash/chrome_shell_delegate.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/immersive_fullscreen_configuration.h"
+#include "chrome/browser/ui/views/avatar_label.h"
 #include "chrome/browser/ui/views/avatar_menu_button.h"
 #include "chrome/browser/ui/views/frame/browser_frame.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
diff --git a/chrome/browser/ui/views/frame/browser_root_view.cc b/chrome/browser/ui/views/frame/browser_root_view.cc
index 44cd1dc..88aea53 100644
--- a/chrome/browser/ui/views/frame/browser_root_view.cc
+++ b/chrome/browser/ui/views/frame/browser_root_view.cc
@@ -14,6 +14,7 @@
 #include "chrome/browser/ui/views/frame/browser_frame.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/tabs/tab_strip.h"
+#include "chrome/browser/ui/views/touch_uma/touch_uma.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "grit/chromium_strings.h"
 #include "ui/base/accessibility/accessible_view_state.h"
@@ -119,6 +120,16 @@
   return kViewClassName;
 }
 
+void BrowserRootView::DispatchGestureEvent(ui::GestureEvent* event) {
+  if (event->type() == ui::ET_GESTURE_TAP &&
+      event->location().y() <= 0 &&
+      event->location().x() <= browser_view_->GetBounds().width()) {
+    TouchUMA::RecordGestureAction(TouchUMA::GESTURE_ROOTVIEWTOP_TAP);
+  }
+
+  RootView::DispatchGestureEvent(event);
+}
+
 bool BrowserRootView::ShouldForwardToTabStrip(
     const ui::DropTargetEvent& event) {
   if (!tabstrip()->visible())
diff --git a/chrome/browser/ui/views/frame/browser_root_view.h b/chrome/browser/ui/views/frame/browser_root_view.h
index 594b70c..6200f8b 100644
--- a/chrome/browser/ui/views/frame/browser_root_view.h
+++ b/chrome/browser/ui/views/frame/browser_root_view.h
@@ -39,6 +39,9 @@
   virtual int OnPerformDrop(const ui::DropTargetEvent& event) OVERRIDE;
   virtual const char* GetClassName() const OVERRIDE;
 
+  // Overridden from internal::RootView:
+  virtual void DispatchGestureEvent(ui::GestureEvent* event) OVERRIDE;
+
  private:
   // Returns true if the event should be forwarded to the tabstrip.
   bool ShouldForwardToTabStrip(const ui::DropTargetEvent& event);
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index df661dc..e6fbbda 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -248,15 +248,6 @@
   return true;
 }
 
-// Returns whether immersive mode should replace fullscreen, which should only
-// occur for "browser-fullscreen" and not for "tab-fullscreen" (which has a URL
-// for the tab entering fullscreen).
-bool UseImmersiveFullscreenForUrl(const GURL& url) {
-  bool is_browser_fullscreen = url.is_empty();
-  return is_browser_fullscreen &&
-         ImmersiveFullscreenConfiguration::UseImmersiveFullscreen();
-}
-
 }  // namespace
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -341,97 +332,50 @@
 void BookmarkExtensionBackground::Paint(gfx::Canvas* canvas,
                                         views::View* view) const {
   int toolbar_overlap = host_view_->GetToolbarOverlap();
-  // The client edge is drawn below the toolbar bounds.
-  if (toolbar_overlap)
-    toolbar_overlap += views::NonClientFrameView::kClientEdgeThickness;
-  if (host_view_->IsDetached()) {
-    // As 'hidden' according to the animation is the full in-tab state,
-    // we invert the value - when current_state is at '0', we expect the
-    // bar to be docked.
-    double current_state = 1 - host_view_->GetAnimationValue();
-
-    // In Search NTP, the detached bookmark bar is different from regular NTP:
-    // - there's no padding around the bar
-    // - there's a separator below the bar
-    // - if animating between pinned and unpinned states:
-    //   - cross-fade the bar backgrounds
-    //   - fade in/out the separator between toolbar and bookmark bar.
-    if (chrome::IsInstantExtendedAPIEnabled()) {
-      ThemeService* ts =
-          ThemeServiceFactory::GetForProfile(browser_->profile());
-      if (current_state == 0.0 || current_state == 1.0) {
-        PaintDetachedBookmarkBar(canvas, host_view_, ts);
-        return;
-      }
-      // While animating, set opacity to cross-fade between attached and
-      // detached backgrounds including their respective separators.
-      int detached_alpha = static_cast<uint8>(current_state * 255);
-      int attached_alpha = 255 - detached_alpha;
-      if (browser_->bookmark_bar_state() == BookmarkBar::DETACHED) {
-        // To animate from attached to detached state:
-        // - fade out attached background
-        // - fade in detached background.
-        canvas->SaveLayerAlpha(attached_alpha);
-        PaintAttachedBookmarkBar(canvas, host_view_, browser_view_,
-                                 browser_->host_desktop_type(),
-                                 toolbar_overlap);
-        canvas->Restore();
-        canvas->SaveLayerAlpha(detached_alpha);
-        PaintDetachedBookmarkBar(canvas, host_view_, ts);
-      } else {
-        // To animate from detached to attached state:
-        // - fade out detached background
-        // - fade in attached background.
-        canvas->SaveLayerAlpha(detached_alpha);
-        PaintDetachedBookmarkBar(canvas, host_view_, ts);
-        canvas->Restore();
-        canvas->SaveLayerAlpha(attached_alpha);
-        PaintAttachedBookmarkBar(canvas, host_view_, browser_view_,
-                                 browser_->host_desktop_type(),
-                                 toolbar_overlap);
-      }
-      canvas->Restore();
-      return;
-    }
-
-    // Draw the background to match the new tab page.
-    ui::ThemeProvider* tp = host_view_->GetThemeProvider();
-    int height = 0;
-    WebContents* contents = browser_->tab_strip_model()->GetActiveWebContents();
-    if (contents && contents->GetView())
-      height = contents->GetView()->GetContainerSize().height();
-    NtpBackgroundUtil::PaintBackgroundDetachedMode(
-        tp, canvas,
-        gfx::Rect(0, toolbar_overlap, host_view_->width(),
-                  host_view_->height() - toolbar_overlap),
-        height);
-
-    double h_padding =
-        static_cast<double>(BookmarkBarView::kNewtabHorizontalPadding) *
-        current_state;
-    double v_padding =
-        static_cast<double>(BookmarkBarView::kNewtabVerticalPadding) *
-        current_state;
-
-    SkRect rect;
-    double roundness = 0;
-    DetachableToolbarView::CalculateContentArea(current_state, h_padding,
-        v_padding, &rect, &roundness, host_view_);
-    DetachableToolbarView::PaintContentAreaBackground(canvas, tp, rect,
-                                                      roundness);
-    DetachableToolbarView::PaintContentAreaBorder(canvas, tp, rect, roundness);
-    if (!toolbar_overlap)
-      DetachableToolbarView::PaintHorizontalBorderForState(canvas, host_view_);
-  } else {
-    gfx::Point background_image_offset =
-        browser_view_->OffsetPointForToolbarBackgroundImage(
-            gfx::Point(host_view_->GetMirroredX(), host_view_->y()));
-    DetachableToolbarView::PaintBackgroundAttachedMode(canvas,
-        host_view_->GetThemeProvider(), host_view_->GetLocalBounds(),
-        background_image_offset, browser_->host_desktop_type());
-    if (host_view_->height() >= toolbar_overlap)
-      DetachableToolbarView::PaintHorizontalBorderForState(canvas, host_view_);
+  if (!host_view_->IsDetached()) {
+    PaintAttachedBookmarkBar(canvas, host_view_, browser_view_,
+                             browser_->host_desktop_type(), toolbar_overlap);
+    return;
   }
+
+  // As 'hidden' according to the animation is the full in-tab state, we invert
+  // the value - when current_state is at '0', we expect the bar to be docked.
+  double current_state = 1 - host_view_->GetAnimationValue();
+
+  ThemeService* ts =
+      ThemeServiceFactory::GetForProfile(browser_->profile());
+  if (current_state == 0.0 || current_state == 1.0) {
+    PaintDetachedBookmarkBar(canvas, host_view_, ts);
+    return;
+  }
+  // While animating, set opacity to cross-fade between attached and detached
+  // backgrounds including their respective separators.
+  int detached_alpha = static_cast<uint8>(current_state * 255);
+  int attached_alpha = 255 - detached_alpha;
+  if (browser_->bookmark_bar_state() == BookmarkBar::DETACHED) {
+    // To animate from attached to detached state:
+    // - fade out attached background
+    // - fade in detached background.
+    canvas->SaveLayerAlpha(attached_alpha);
+    PaintAttachedBookmarkBar(canvas, host_view_, browser_view_,
+                             browser_->host_desktop_type(),
+                             toolbar_overlap);
+    canvas->Restore();
+    canvas->SaveLayerAlpha(detached_alpha);
+    PaintDetachedBookmarkBar(canvas, host_view_, ts);
+  } else {
+    // To animate from detached to attached state:
+    // - fade out detached background
+    // - fade in attached background.
+    canvas->SaveLayerAlpha(detached_alpha);
+    PaintDetachedBookmarkBar(canvas, host_view_, ts);
+    canvas->Restore();
+    canvas->SaveLayerAlpha(attached_alpha);
+    PaintAttachedBookmarkBar(canvas, host_view_, browser_view_,
+                             browser_->host_desktop_type(),
+                             toolbar_overlap);
+  }
+  canvas->Restore();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -543,6 +487,10 @@
   return static_cast<BrowserView*>(browser->window());
 }
 
+void BrowserView::InitStatusBubble() {
+  status_bubble_.reset(new StatusBubbleViews(contents_container_));
+}
+
 gfx::Rect BrowserView::GetToolbarBounds() const {
   gfx::Rect toolbar_bounds(toolbar_->bounds());
   if (toolbar_bounds.IsEmpty())
@@ -886,7 +834,7 @@
   // Immersive mode has no exit bubble because it has a visible strip at the
   // top that gives the user a hover target.
   // TODO(jamescook): Figure out what to do with mouse-lock.
-  if (bubble_type == FEB_TYPE_NONE || UseImmersiveFullscreenForUrl(url)) {
+  if (bubble_type == FEB_TYPE_NONE || ShouldUseImmersiveFullscreenForUrl(url)) {
     fullscreen_bubble_.reset();
   } else if (fullscreen_bubble_.get()) {
     fullscreen_bubble_->UpdateContent(url, bubble_type);
@@ -1824,15 +1772,20 @@
   if (!browser_->ShouldCloseWindow())
     return false;
 
+  bool fast_tab_closing_enabled =
+    CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableFastUnload);
+
   if (!browser_->tab_strip_model()->empty()) {
     // Tab strip isn't empty.  Hide the frame (so it appears to have closed
     // immediately) and close all the tabs, allowing the renderers to shut
     // down. When the tab strip is empty we'll be called back again.
     frame_->Hide();
     browser_->OnWindowClosing();
-    browser_->tab_strip_model()->CloseAllTabs();
+    if (fast_tab_closing_enabled)
+      browser_->tab_strip_model()->CloseAllTabs();
     return false;
-  } else if (!browser_->HasCompletedUnloadProcessing()) {
+  } else if (fast_tab_closing_enabled &&
+        !browser_->HasCompletedUnloadProcessing()) {
     // The browser needs to finish running unload handlers.
     // Hide the frame (so it appears to have closed immediately), and
     // the browser will call us back again when it is ready to close.
@@ -2048,7 +2001,7 @@
   AddChildView(contents_split_);
   set_contents_view(contents_split_);
 
-  status_bubble_.reset(new StatusBubbleViews(contents_container_));
+  InitStatusBubble();
 
   // Top container holds tab strip and toolbar and lives at the front of the
   // view hierarchy.
@@ -2396,7 +2349,7 @@
   }
 
   // Enable immersive before the browser refreshes its list of enabled commands.
-  if (UseImmersiveFullscreenForUrl(url))
+  if (ShouldUseImmersiveFullscreenForUrl(url))
     immersive_mode_controller_->SetEnabled(fullscreen);
 
   browser_->WindowFullscreenStateChanged();
@@ -2404,7 +2357,7 @@
   if (fullscreen) {
     if (!chrome::IsRunningInAppMode() &&
         type != FOR_METRO &&
-        !UseImmersiveFullscreenForUrl(url)) {
+        !ShouldUseImmersiveFullscreenForUrl(url)) {
       fullscreen_bubble_.reset(new FullscreenExitBubbleViews(
           this, url, bubble_type));
     }
@@ -2427,6 +2380,12 @@
   ToolbarSizeChanged(false);
 }
 
+bool BrowserView::ShouldUseImmersiveFullscreenForUrl(const GURL& url) const {
+  bool is_browser_fullscreen = url.is_empty();
+  return ImmersiveFullscreenConfiguration::UseImmersiveFullscreen() &&
+      is_browser_fullscreen && IsBrowserTypeNormal();
+}
+
 void BrowserView::LoadAccelerators() {
 #if defined(OS_WIN) && !defined(USE_AURA)
   HACCEL accelerator_table = AtlLoadAccelerators(IDR_MAINFRAME);
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h
index bac93d8..6141f1a 100644
--- a/chrome/browser/ui/views/frame/browser_view.h
+++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -11,7 +11,7 @@
 
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "build/build_config.h"
 #include "chrome/browser/devtools/devtools_window.h"
 #include "chrome/browser/infobars/infobar_container.h"
@@ -128,6 +128,12 @@
   // Returns a Browser instance of this view.
   Browser* browser() { return browser_.get(); }
 
+  // Initializes (or re-initializes) the status bubble.  We try to only create
+  // the bubble once and re-use it for the life of the browser, but certain
+  // events (such as changing enabling/disabling Aero on Win) can force a need
+  // to change some of the bubble's creation parameters.
+  void InitStatusBubble();
+
   // Returns the apparent bounds of the toolbar, in BrowserView coordinates.
   // These differ from |toolbar_.bounds()| in that they match where the toolbar
   // background image is drawn -- slightly outside the "true" bounds
@@ -551,6 +557,11 @@
                          const GURL& url,
                          FullscreenExitBubbleType bubble_type);
 
+  // Returns whether immmersive fullscreen should replace fullscreen. This
+  // should only occur for "browser-fullscreen" for tabbed-typed windows (not
+  // for tab-fullscreen and not for app/popup type windows).
+  bool ShouldUseImmersiveFullscreenForUrl(const GURL& url) const;
+
   // Copy the accelerator table from the app resources into something we can
   // use.
   void LoadAccelerators();
diff --git a/chrome/browser/ui/views/frame/browser_view_layout.cc b/chrome/browser/ui/views/frame/browser_view_layout.cc
index 8efb7e7..1262a3d 100644
--- a/chrome/browser/ui/views/frame/browser_view_layout.cc
+++ b/chrome/browser/ui/views/frame/browser_view_layout.cc
@@ -182,9 +182,7 @@
       bookmark_bar_->visible() &&
       browser()->SupportsWindowFeature(Browser::FEATURE_BOOKMARKBAR)) {
     bookmark_bar_size = bookmark_bar_->GetMinimumSize();
-    bookmark_bar_size.Enlarge(0,
-        -(views::NonClientFrameView::kClientEdgeThickness +
-            bookmark_bar_->GetToolbarOverlap(true)));
+    bookmark_bar_size.Enlarge(0, -bookmark_bar_->GetToolbarOverlap());
   }
   // TODO: Adjust the minimum height for the find bar.
 
@@ -485,8 +483,7 @@
 
   bookmark_bar_->set_infobar_visible(InfobarVisible());
   int bookmark_bar_height = bookmark_bar_->GetPreferredSize().height();
-  y -= views::NonClientFrameView::kClientEdgeThickness +
-      bookmark_bar_->GetToolbarOverlap(false);
+  y -= bookmark_bar_->GetToolbarOverlap();
   bookmark_bar_->SetBounds(vertical_layout_rect_.x(),
                            y,
                            vertical_layout_rect_.width(),
@@ -575,7 +572,7 @@
 
   // Offset for the detached bookmark bar.
   return bookmark_bar_->height() -
-      views::NonClientFrameView::kClientEdgeThickness;
+      bookmark_bar_->GetFullyDetachedToolbarOverlap();
 }
 
 int BrowserViewLayout::GetTopMarginForActiveContent() {
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
index a744bc0..f1d8ba5 100644
--- a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
+++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
@@ -11,6 +11,7 @@
 #include "chrome/app/chrome_dll_resource.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/themes/theme_properties.h"
+#include "chrome/browser/ui/views/avatar_label.h"
 #include "chrome/browser/ui/views/avatar_menu_button.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/tabs/tab.h"
@@ -71,7 +72,7 @@
 // is no avatar icon.
 const int kTabStripIndent = -6;
 
-}
+}  // namespace
 
 ///////////////////////////////////////////////////////////////////////////////
 // GlassBrowserFrameView, public:
@@ -206,9 +207,11 @@
   if (!browser_view()->IsBrowserTypeNormal() || !bounds().Contains(point))
     return HTNOWHERE;
 
-  // See if the point is within the avatar menu button.
-  if (avatar_button() &&
-      avatar_button()->GetMirroredBounds().Contains(point))
+  // See if the point is within the avatar menu button or within the avatar
+  // label.
+  if ((avatar_button() &&
+       avatar_button()->GetMirroredBounds().Contains(point)) ||
+      (avatar_label() && avatar_label()->GetMirroredBounds().Contains(point)))
     return HTCLIENT;
 
   int frame_component = frame()->client_view()->NonClientHitTest(point);
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller.cc b/chrome/browser/ui/views/frame/immersive_mode_controller.cc
new file mode 100644
index 0000000..cebf6cb
--- /dev/null
+++ b/chrome/browser/ui/views/frame/immersive_mode_controller.cc
@@ -0,0 +1,20 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/frame/immersive_mode_controller.h"
+
+ImmersiveModeController::ImmersiveModeController() {
+}
+
+ImmersiveModeController::~ImmersiveModeController() {
+  FOR_EACH_OBSERVER(Observer, observers_, OnImmersiveModeControllerDestroyed());
+}
+
+void ImmersiveModeController::AddObserver(Observer* observer) {
+  observers_.AddObserver(observer);
+}
+
+void ImmersiveModeController::RemoveObserver(Observer* observer) {
+  observers_.RemoveObserver(observer);
+}
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller.h b/chrome/browser/ui/views/frame/immersive_mode_controller.h
index ae8a0eb..81da8d8 100644
--- a/chrome/browser/ui/views/frame/immersive_mode_controller.h
+++ b/chrome/browser/ui/views/frame/immersive_mode_controller.h
@@ -6,6 +6,7 @@
 #define CHROME_BROWSER_UI_VIEWS_FRAME_IMMERSIVE_MODE_CONTROLLER_H_
 
 #include "base/compiler_specific.h"
+#include "base/observer_list.h"
 
 class BookmarkBarView;
 class FullscreenController;
@@ -40,6 +41,18 @@
     ANIMATE_REVEAL_NO
   };
 
+  class Observer {
+   public:
+    // Called when a reveal of the top-of-window views has been initiated.
+    virtual void OnImmersiveRevealStarted() {}
+
+    // Called when the immersive mode controller has been destroyed.
+    virtual void OnImmersiveModeControllerDestroyed() {}
+
+   protected:
+    virtual ~Observer() {}
+  };
+
   class Delegate {
    public:
     // Returns the bookmark bar, or NULL if the window does not support one.
@@ -58,7 +71,8 @@
     virtual ~Delegate() {}
   };
 
-  virtual ~ImmersiveModeController() {}
+  ImmersiveModeController();
+  virtual ~ImmersiveModeController();
 
   // Must initialize after browser view has a Widget and native window.
   virtual void Init(Delegate* delegate,
@@ -127,6 +141,15 @@
   // visible.
   virtual void OnFindBarVisibleBoundsChanged(
       const gfx::Rect& new_visible_bounds_in_screen) = 0;
+
+  virtual void AddObserver(Observer* observer);
+  virtual void RemoveObserver(Observer* observer);
+
+ protected:
+  ObserverList<Observer> observers_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ImmersiveModeController);
 };
 
 namespace chrome {
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc b/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc
index 9b21a6f..a931f44 100644
--- a/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc
+++ b/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc
@@ -86,6 +86,16 @@
   return false;
 }
 
+// Returns the location of |event| in screen coordinates.
+gfx::Point GetEventLocationInScreen(const ui::LocatedEvent& event) {
+  gfx::Point location_in_screen = event.location();
+  aura::Window* target = static_cast<aura::Window*>(event.target());
+  aura::client::ScreenPositionClient* screen_position_client =
+      aura::client::GetScreenPositionClient(target->GetRootWindow());
+  screen_position_client->ConvertPointToScreen(target, &location_in_screen);
+  return location_in_screen;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 
 class RevealedLockAsh : public ImmersiveRevealedLock {
@@ -288,11 +298,11 @@
       revealed_lock_count_(0),
       tab_indicator_visibility_(TAB_INDICATORS_HIDE),
       mouse_x_when_hit_top_(-1),
+      gesture_begun_(false),
       native_window_(NULL),
       animation_(new ui::SlideAnimation(this)),
       animations_disabled_for_test_(false),
-      weak_ptr_factory_(this),
-      gesture_begun_(false) {
+      weak_ptr_factory_(this) {
 }
 
 ImmersiveModeControllerAsh::~ImmersiveModeControllerAsh() {
@@ -350,10 +360,7 @@
     return;
   enabled_ = enabled;
 
-  // Delay the initialization of the window observers till the first call to
-  // SetEnabled(true) because FullscreenController is not yet initialized when
-  // Init() is called.
-  EnableWindowObservers(true);
+  EnableWindowObservers(enabled_);
 
   UpdateUseMinimalChrome(LAYOUT_NO);
 
@@ -505,7 +512,7 @@
 
   switch (event->type()) {
     case ui::ET_GESTURE_SCROLL_BEGIN:
-      if (ShouldHandleEvent(event->location())) {
+      if (ShouldHandleGestureEvent(GetEventLocationInScreen(*event))) {
         gesture_begun_ = true;
         event->SetHandled();
       }
@@ -585,6 +592,9 @@
 void ImmersiveModeControllerAsh::OnWindowPropertyChanged(aura::Window* window,
                                                          const void* key,
                                                          intptr_t old) {
+  if (!enabled_)
+    return;
+
   if (key == aura::client::kShowStateKey) {
     // Disable immersive mode when the user exits fullscreen without going
     // through FullscreenController::ToggleFullscreenMode(). This is the case
@@ -598,21 +608,18 @@
           base::Bind(&ImmersiveModeControllerAsh::MaybeExitImmersiveFullscreen,
                      weak_ptr_factory_.GetWeakPtr()));
     }
+
+    ui::WindowShowState show_state = native_window_->GetProperty(
+        aura::client::kShowStateKey);
+    if (show_state == ui::SHOW_STATE_FULLSCREEN &&
+        old == ui::SHOW_STATE_MINIMIZED) {
+      // Relayout in case there was a layout while the window show state was
+      // ui::SHOW_STATE_MINIMIZED.
+      LayoutBrowserRootView();
+    }
   }
 }
 
-void ImmersiveModeControllerAsh::OnWindowAddedToRootWindow(
-    aura::Window* window) {
-  DCHECK_EQ(window, native_window_);
-  UpdatePreTargetHandler();
-}
-
-void ImmersiveModeControllerAsh::OnWindowRemovingFromRootWindow(
-    aura::Window* window) {
-  DCHECK_EQ(window, native_window_);
-  UpdatePreTargetHandler();
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // Testing interface:
 
@@ -663,7 +670,10 @@
     focus_manager->RemoveFocusChangeListener(this);
   }
 
-  UpdatePreTargetHandler();
+  if (enable)
+    ash::Shell::GetInstance()->AddPreTargetHandler(this);
+  else
+    ash::Shell::GetInstance()->RemovePreTargetHandler(this);
 
   if (enable) {
     native_window_->AddObserver(this);
@@ -692,18 +702,29 @@
 void ImmersiveModeControllerAsh::UpdateTopEdgeHoverTimer(
     ui::MouseEvent* event) {
   DCHECK(enabled_);
-  // If the top-of-window views are already revealed or the cursor left the
-  // top edge we don't need to trigger based on a timer anymore.
-  if (reveal_state_ == SLIDING_OPEN ||
-      reveal_state_ == REVEALED ||
-      event->root_location().y() != 0) {
+  // Stop the timer if the top-of-window views are already revealed.
+  if (reveal_state_ == SLIDING_OPEN || reveal_state_ == REVEALED) {
     top_edge_hover_timer_.Stop();
     return;
   }
+
+  gfx::Point location_in_screen = GetEventLocationInScreen(*event);
+  gfx::Rect top_container_bounds_in_screen =
+      top_container_->GetBoundsInScreen();
+
+  // Stop the timer if the cursor left the top edge or is on a different
+  // display.
+  if (location_in_screen.y() != top_container_bounds_in_screen.y() ||
+      location_in_screen.x() < top_container_bounds_in_screen.x() ||
+      location_in_screen.x() >= top_container_bounds_in_screen.right()) {
+    top_edge_hover_timer_.Stop();
+    return;
+  }
+
   // The cursor is now at the top of the screen. Consider the cursor "not
   // moving" even if it moves a little bit in x, because users don't have
   // perfect pointing precision.
-  int mouse_x = event->root_location().x();
+  int mouse_x = location_in_screen.x() - top_container_bounds_in_screen.x();
   if (top_edge_hover_timer_.IsRunning() &&
       abs(mouse_x - mouse_x_when_hit_top_) <=
           ImmersiveFullscreenConfiguration::
@@ -749,11 +770,7 @@
 
   gfx::Point location_in_screen;
   if (event && event->type() != ui::ET_MOUSE_CAPTURE_CHANGED) {
-    location_in_screen = event->location();
-    aura::Window* target = static_cast<aura::Window*>(event->target());
-    aura::client::ScreenPositionClient* screen_position_client =
-        aura::client::GetScreenPositionClient(target->GetRootWindow());
-    screen_position_client->ConvertPointToScreen(target, &location_in_screen);
+    location_in_screen = GetEventLocationInScreen(*event);
   } else {
     aura::client::CursorClient* cursor_client = aura::client::GetCursorClient(
         native_window_->GetRootWindow());
@@ -932,8 +949,11 @@
 
     // Do not do any more processing if LayoutBrowserView() changed
     // |reveal_state_|.
-    if (reveal_state_ != SLIDING_OPEN)
+    if (reveal_state_ != SLIDING_OPEN) {
+      if (reveal_state_ == REVEALED)
+        FOR_EACH_OBSERVER(Observer, observers_, OnImmersiveRevealStarted());
       return;
+    }
   }
   // Slide in the reveal view.
   if (animate == ANIMATE_NO) {
@@ -943,6 +963,9 @@
     animation_->SetSlideDuration(GetAnimationDuration(animate));
     animation_->Show();
   }
+
+   if (previous_reveal_state == CLOSED)
+     FOR_EACH_OBSERVER(Observer, observers_, OnImmersiveRevealStarted());
 }
 
 void ImmersiveModeControllerAsh::EnablePaintToLayer(bool enable) {
@@ -1048,7 +1071,7 @@
   return SWIPE_NONE;
 }
 
-bool ImmersiveModeControllerAsh::ShouldHandleEvent(
+bool ImmersiveModeControllerAsh::ShouldHandleGestureEvent(
     const gfx::Point& location) const {
   // All of the gestures that are of interest start in a region with left &
   // right edges agreeing with |top_container_|. When CLOSED it is difficult to
@@ -1062,17 +1085,5 @@
   return near_bounds.Contains(location) ||
       ((location.y() < near_bounds.y()) &&
        (location.x() >= near_bounds.x()) &&
-       (location.x() <= near_bounds.right()));
-}
-
-void ImmersiveModeControllerAsh::UpdatePreTargetHandler() {
-  if (!native_window_)
-    return;
-  aura::RootWindow* root_window = native_window_->GetRootWindow();
-  if (!root_window)
-    return;
-  if (observers_enabled_)
-    root_window->AddPreTargetHandler(this);
-  else
-    root_window->RemovePreTargetHandler(this);
+       (location.x() < near_bounds.right()));
 }
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_ash.h b/chrome/browser/ui/views/frame/immersive_mode_controller_ash.h
index c72c17d..ae7417a 100644
--- a/chrome/browser/ui/views/frame/immersive_mode_controller_ash.h
+++ b/chrome/browser/ui/views/frame/immersive_mode_controller_ash.h
@@ -7,7 +7,7 @@
 
 #include "chrome/browser/ui/views/frame/immersive_mode_controller.h"
 
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "ui/aura/window_observer.h"
@@ -108,8 +108,6 @@
   virtual void OnWindowPropertyChanged(aura::Window* window,
                                        const void* key,
                                        intptr_t old) OVERRIDE;
-  virtual void OnWindowAddedToRootWindow(aura::Window* window) OVERRIDE;
-  virtual void OnWindowRemovingFromRootWindow(aura::Window* window) OVERRIDE;
 
   // Testing interface.
   void SetForceHideTabIndicatorsForTest(bool force);
@@ -219,11 +217,7 @@
   // bounds, above it, or within a few pixels below it. This allow the container
   // to steal enough pixels to detect a swipe in and handles the case that there
   // is a bezel sensor above the top container.
-  bool ShouldHandleEvent(const gfx::Point& location) const;
-
-  // Call Add/RemovePreTargerHandler since either the RootWindow has changed or
-  // the enabled state of observing has changed.
-  void UpdatePreTargetHandler();
+  bool ShouldHandleGestureEvent(const gfx::Point& location) const;
 
   // Injected dependencies. Not owned.
   Delegate* delegate_;
@@ -252,6 +246,10 @@
   // the top edge of the screen.
   int mouse_x_when_hit_top_;
 
+  // Tracks if the controller has seen a ET_GESTURE_SCROLL_BEGIN, without the
+  // following events.
+  bool gesture_begun_;
+
   // The current visible bounds of the find bar, in screen coordinates. This is
   // an empty rect if the find bar is not visible.
   gfx::Rect find_bar_visible_bounds_in_screen_;
@@ -284,10 +282,6 @@
 
   base::WeakPtrFactory<ImmersiveModeControllerAsh> weak_ptr_factory_;
 
-  // Tracks if the controller has seen a ET_GESTURE_SCROLL_BEGIN, without the
-  // following events.
-  bool gesture_begun_;
-
   DISALLOW_COPY_AND_ASSIGN(ImmersiveModeControllerAsh);
 };
 
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_ash_unittest.cc b/chrome/browser/ui/views/frame/immersive_mode_controller_ash_unittest.cc
index 81192ff..f3125d7 100644
--- a/chrome/browser/ui/views/frame/immersive_mode_controller_ash_unittest.cc
+++ b/chrome/browser/ui/views/frame/immersive_mode_controller_ash_unittest.cc
@@ -230,12 +230,14 @@
 
   // Large move right restarts the timer (so it is still running) and considers
   // this a new hit at the top.
-  event_generator()->MoveMouseTo(150, 0);
+  event_generator()->MoveMouseTo(499, 0);
   EXPECT_TRUE(top_edge_hover_timer_running());
-  EXPECT_EQ(150, mouse_x_when_hit_top());
+  EXPECT_EQ(499, mouse_x_when_hit_top());
 
-  // Moving off the top edge stops the timer.
-  event_generator()->MoveMouseTo(150, 1);
+  // Moving off the top edge horizontally stops the timer.
+  EXPECT_GT(CurrentContext()->bounds().width(), top_container()->width());
+  EXPECT_EQ(500, top_container()->width());
+  event_generator()->MoveMouseTo(500, 0);
   EXPECT_FALSE(top_edge_hover_timer_running());
 
   // Once revealed, a move just a little below the top container doesn't end a
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
index d77399c..c4bbf28 100644
--- a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
+++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
@@ -12,6 +12,7 @@
 #include "base/prefs/pref_service.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/themes/theme_properties.h"
+#include "chrome/browser/ui/views/avatar_label.h"
 #include "chrome/browser/ui/views/avatar_menu_button.h"
 #include "chrome/browser/ui/views/frame/browser_frame.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
@@ -321,9 +322,11 @@
   if (!bounds().Contains(point))
     return HTNOWHERE;
 
-  // See if the point is within the avatar menu button.
-  if (avatar_button() &&
-      avatar_button()->GetMirroredBounds().Contains(point))
+  // See if the point is within the avatar menu button or within the avatar
+  // label.
+  if ((avatar_button() &&
+       avatar_button()->GetMirroredBounds().Contains(point)) ||
+      (avatar_label() && avatar_label()->GetMirroredBounds().Contains(point)))
     return HTCLIENT;
 
   int frame_component = frame()->client_view()->NonClientHitTest(point);
diff --git a/chrome/browser/ui/views/fullscreen_exit_bubble_views.cc b/chrome/browser/ui/views/fullscreen_exit_bubble_views.cc
index cdd69ca..87bb1a3 100644
--- a/chrome/browser/ui/views/fullscreen_exit_bubble_views.cc
+++ b/chrome/browser/ui/views/fullscreen_exit_bubble_views.cc
@@ -277,7 +277,7 @@
   // Initialize the popup.
   popup_ = new views::Widget;
   views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
-  params.transparent = true;
+  params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
   params.can_activate = false;
   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
   params.parent = browser_view_->GetWidget()->GetNativeView();
diff --git a/chrome/browser/ui/views/keyboard_access_browsertest.cc b/chrome/browser/ui/views/keyboard_access_browsertest.cc
index 2d78b89..3e69624 100644
--- a/chrome/browser/ui/views/keyboard_access_browsertest.cc
+++ b/chrome/browser/ui/views/keyboard_access_browsertest.cc
@@ -9,7 +9,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/message_loop.h"
 #include "base/strings/string_util.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
diff --git a/chrome/browser/ui/views/location_bar/content_setting_image_view.cc b/chrome/browser/ui/views/location_bar/content_setting_image_view.cc
index 38edd16..014c3da 100644
--- a/chrome/browser/ui/views/location_bar/content_setting_image_view.cc
+++ b/chrome/browser/ui/views/location_bar/content_setting_image_view.cc
@@ -99,8 +99,9 @@
 }
 
 void ContentSettingImageView::Update(content::WebContents* web_contents) {
-  if (web_contents)
-    content_setting_image_model_->UpdateFromWebContents(web_contents);
+  // Note: We explicitly want to call this even if |web_contents| is NULL, so we
+  // get hidden properly while the user is editing the omnibox.
+  content_setting_image_model_->UpdateFromWebContents(web_contents);
 
   if (!content_setting_image_model_->is_visible()) {
     SetVisible(false);
diff --git a/chrome/browser/ui/views/location_bar/zoom_bubble_view.cc b/chrome/browser/ui/views/location_bar/zoom_bubble_view.cc
index 7301f6d..76f1c7a 100644
--- a/chrome/browser/ui/views/location_bar/zoom_bubble_view.cc
+++ b/chrome/browser/ui/views/location_bar/zoom_bubble_view.cc
@@ -46,9 +46,11 @@
   DCHECK(browser && browser->window() && browser->fullscreen_controller());
 
   BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser);
-  bool is_fullscreen = browser->window()->IsFullscreen();
-  views::View* anchor_view = is_fullscreen ?
-      NULL : browser_view->GetLocationBarView()->zoom_view();
+  bool is_fullscreen = browser_view->IsFullscreen();
+  bool anchor_to_view = !is_fullscreen ||
+      browser_view->immersive_mode_controller()->IsRevealed();
+  views::View* anchor_view = anchor_to_view ?
+      browser_view->GetLocationBarView()->zoom_view() : NULL;
 
   // If the bubble is already showing in this window and its |auto_close_| value
   // is equal to |auto_close|, the bubble can be reused and only the label text
@@ -66,11 +68,11 @@
     zoom_bubble_ = new ZoomBubbleView(anchor_view,
                                       web_contents,
                                       auto_close,
+                                      browser_view->immersive_mode_controller(),
                                       browser->fullscreen_controller());
 
-    // If we're fullscreen, there is no anchor view, so parent the bubble to
-    // the content area.
-    if (is_fullscreen) {
+    // If we do not have an anchor view, parent the bubble to the content area.
+    if (!anchor_to_view) {
       zoom_bubble_->set_parent_window(
           web_contents->GetView()->GetTopLevelNativeWindow());
     }
@@ -93,33 +95,58 @@
 
 // static
 bool ZoomBubbleView::IsShowing() {
-  return zoom_bubble_ != NULL;
+  // The bubble may be in the process of closing.
+  return zoom_bubble_ != NULL && zoom_bubble_->GetWidget()->IsVisible();
 }
 
-ZoomBubbleView::ZoomBubbleView(views::View* anchor_view,
-                               content::WebContents* web_contents,
-                               bool auto_close,
-                               FullscreenController* fullscreen_controller)
+// static
+const ZoomBubbleView* ZoomBubbleView::GetZoomBubbleForTest() {
+  return zoom_bubble_;
+}
+
+ZoomBubbleView::ZoomBubbleView(
+    views::View* anchor_view,
+    content::WebContents* web_contents,
+    bool auto_close,
+    ImmersiveModeController* immersive_mode_controller,
+    FullscreenController* fullscreen_controller)
     : BubbleDelegateView(anchor_view, anchor_view ?
           views::BubbleBorder::TOP_RIGHT : views::BubbleBorder::NONE),
       label_(NULL),
       web_contents_(web_contents),
-      auto_close_(auto_close) {
+      auto_close_(auto_close),
+      immersive_mode_controller_(immersive_mode_controller) {
   // Compensate for built-in vertical padding in the anchor view's image.
   set_anchor_view_insets(gfx::Insets(5, 0, 5, 0));
   set_use_focusless(auto_close);
   set_notify_enter_exit_on_child(true);
 
+  if (anchor_view) {
+    // If we are in immersive fullscreen and the top-of-window views are
+    // already revealed, lock the top-of-window views in the revealed state
+    // as long as the zoom bubble is visible. ImmersiveModeController does
+    // not do this for us automatically because the zoom bubble is not
+    // activatable.
+    immersive_reveal_lock_.reset(immersive_mode_controller_->GetRevealedLock(
+        ImmersiveModeController::ANIMATE_REVEAL_NO));
+  }
+
+  // Add observers to close the bubble if the fullscreen state or immersive
+  // fullscreen revealed state changes.
   registrar_.Add(this,
                  chrome::NOTIFICATION_FULLSCREEN_CHANGED,
                  content::Source<FullscreenController>(fullscreen_controller));
+  immersive_mode_controller_->AddObserver(this);
 }
 
 ZoomBubbleView::~ZoomBubbleView() {
+  if (immersive_mode_controller_)
+    immersive_mode_controller_->RemoveObserver(this);
 }
 
 void ZoomBubbleView::AdjustForFullscreen(const gfx::Rect& screen_bounds) {
-  DCHECK(!anchor_view());
+  if (anchor_view())
+    return;
 
   // TODO(dbeam): should RTL logic be done in views::BubbleDelegateView?
   const size_t bubble_half_width = width() / 2;
@@ -218,6 +245,14 @@
   CloseBubble();
 }
 
+void ZoomBubbleView::OnImmersiveRevealStarted() {
+  CloseBubble();
+}
+
+void ZoomBubbleView::OnImmersiveModeControllerDestroyed() {
+  immersive_mode_controller_ = NULL;
+}
+
 void ZoomBubbleView::WindowClosing() {
   // |zoom_bubble_| can be a new bubble by this point (as Close(); doesn't
   // call this right away). Only set to NULL when it's this bubble.
diff --git a/chrome/browser/ui/views/location_bar/zoom_bubble_view.h b/chrome/browser/ui/views/location_bar/zoom_bubble_view.h
index 1bf4c8d..1b05401 100644
--- a/chrome/browser/ui/views/location_bar/zoom_bubble_view.h
+++ b/chrome/browser/ui/views/location_bar/zoom_bubble_view.h
@@ -6,7 +6,8 @@
 #define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_ZOOM_BUBBLE_VIEW_H_
 
 #include "base/basictypes.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
+#include "chrome/browser/ui/views/frame/immersive_mode_controller.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "ui/views/bubble/bubble_delegate.h"
@@ -24,7 +25,8 @@
 // View used to display the zoom percentage when it has changed.
 class ZoomBubbleView : public views::BubbleDelegateView,
                        public views::ButtonListener,
-                       public content::NotificationObserver {
+                       public content::NotificationObserver,
+                       public ImmersiveModeController::Observer {
  public:
   // Shows the bubble and automatically closes it after a short time period if
   // |auto_close| is true.
@@ -37,16 +39,22 @@
   // Whether the zoom bubble is currently showing.
   static bool IsShowing();
 
+  // Returns the zoom bubble if the zoom bubble is showing. Returns NULL
+  // otherwise.
+  static const ZoomBubbleView* GetZoomBubbleForTest();
+
  private:
   ZoomBubbleView(views::View* anchor_view,
                  content::WebContents* web_contents,
                  bool auto_close,
+                 ImmersiveModeController* immersive_mode_controller,
                  FullscreenController* fullscreen_controller);
   virtual ~ZoomBubbleView();
 
-  // Place the bubble in the top right (left in RTL) of the |screen_bounds| that
-  // contain |web_contents_|'s browser window. Because the positioning is based
-  // on the size of the bubble, this must be called after the bubble is created.
+  // If the bubble is not anchored to a view, places the bubble in the top
+  // right (left in RTL) of the |screen_bounds| that contain |web_contents_|'s
+  // browser window. Because the positioning is based on the size of the
+  // bubble, this must be called after the bubble is created.
   void AdjustForFullscreen(const gfx::Rect& screen_bounds);
 
   // Refreshes the bubble by changing the zoom percentage appropriately and
@@ -81,6 +89,10 @@
                        const content::NotificationSource& source,
                        const content::NotificationDetails& details) OVERRIDE;
 
+  // ImmersiveModeController::Observer methods.
+  virtual void OnImmersiveRevealStarted() OVERRIDE;
+  virtual void OnImmersiveModeControllerDestroyed() OVERRIDE;
+
   // Singleton instance of the zoom bubble. The zoom bubble can only be shown on
   // the active browser window, so there is no case in which it will be shown
   // twice at the same time.
@@ -98,6 +110,15 @@
   // Whether the currently displayed bubble will automatically close.
   bool auto_close_;
 
+  // The immersive mode controller for the BrowserView containing
+  // |web_contents_|.
+  // Not owned.
+  ImmersiveModeController* immersive_mode_controller_;
+
+  // Keeps the top-of-window views revealed (but does not initiate a reveal)
+  // when the bubble is visible in immersive fullscreen.
+  scoped_ptr<ImmersiveRevealedLock> immersive_reveal_lock_;
+
   // Used to register for fullscreen change notifications.
   content::NotificationRegistrar registrar_;
 
diff --git a/chrome/browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc b/chrome/browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc
new file mode 100644
index 0000000..d075227
--- /dev/null
+++ b/chrome/browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc
@@ -0,0 +1,149 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/location_bar/zoom_bubble_view.h"
+
+#include "chrome/browser/ui/browser_commands.h"
+#include "chrome/browser/ui/fullscreen/fullscreen_controller.h"
+#include "chrome/browser/ui/fullscreen/fullscreen_controller_test.h"
+#include "chrome/browser/ui/immersive_fullscreen_configuration.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/frame/immersive_mode_controller.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
+
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/ui/views/frame/immersive_mode_controller_ash.h"
+#endif
+
+class ZoomBubbleBrowserTest : public InProcessBrowserTest {
+ public:
+  ZoomBubbleBrowserTest() {}
+  virtual ~ZoomBubbleBrowserTest() {}
+
+  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+    ImmersiveFullscreenConfiguration::EnableImmersiveFullscreenForTest();
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ZoomBubbleBrowserTest);
+};
+
+// TODO(linux_aura) http://crbug.com/163931
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA)
+#define MAYBE_NonImmersiveFullscreen DISABLED_NonImmersiveFullscreen
+#else
+#define MAYBE_NonImmersiveFullscreen NonImmersiveFullscreen
+#endif
+// Test whether the zoom bubble is anchored and whether it is visible when in
+// non-immersive fullscreen.
+IN_PROC_BROWSER_TEST_F(ZoomBubbleBrowserTest, MAYBE_NonImmersiveFullscreen) {
+  BrowserView* browser_view = static_cast<BrowserView*>(browser()->window());
+  content::WebContents* web_contents = browser_view->GetActiveWebContents();
+
+  // The zoom bubble should be anchored when not in fullscreen.
+  ZoomBubbleView::ShowBubble(web_contents, true);
+  ASSERT_TRUE(ZoomBubbleView::IsShowing());
+  const ZoomBubbleView* zoom_bubble = ZoomBubbleView::GetZoomBubbleForTest();
+  EXPECT_TRUE(zoom_bubble->anchor_view());
+
+  // Entering fullscreen should close the bubble. (We enter into tab fullscreen
+  // here because tab fullscreen is non-immersive even when
+  // ImmersiveFullscreenConfiguration::UseImmersiveFullscreen()) returns
+  // true.
+  {
+    // NOTIFICATION_FULLSCREEN_CHANGED is sent asynchronously. Wait for the
+    // notification before testing the zoom bubble visibility.
+    scoped_ptr<FullscreenNotificationObserver> waiter(
+        new FullscreenNotificationObserver());
+    browser()->fullscreen_controller()->ToggleFullscreenModeForTab(
+        web_contents, true);
+    waiter->Wait();
+  }
+  ASSERT_FALSE(browser_view->immersive_mode_controller()->IsEnabled());
+  EXPECT_FALSE(ZoomBubbleView::IsShowing());
+
+  // The bubble should not be anchored when it is shown in non-immersive
+  // fullscreen.
+  ZoomBubbleView::ShowBubble(web_contents, true);
+  ASSERT_TRUE(ZoomBubbleView::IsShowing());
+  zoom_bubble = ZoomBubbleView::GetZoomBubbleForTest();
+  EXPECT_FALSE(zoom_bubble->anchor_view());
+
+  // Exit fullscreen before ending the test for the sake of sanity.
+  {
+    scoped_ptr<FullscreenNotificationObserver> waiter(
+        new FullscreenNotificationObserver());
+    chrome::ToggleFullscreenMode(browser());
+    waiter->Wait();
+  }
+}
+
+// Immersive fullscreen is CrOS only for now.
+#if defined(OS_CHROMEOS)
+// Test whether the zoom bubble is anchored and whether it is visible when in
+// immersive fullscreen.
+IN_PROC_BROWSER_TEST_F(ZoomBubbleBrowserTest, ImmersiveFullscreen) {
+  BrowserView* browser_view = static_cast<BrowserView*>(browser()->window());
+  content::WebContents* web_contents = browser_view->GetActiveWebContents();
+
+  ASSERT_TRUE(ImmersiveFullscreenConfiguration::UseImmersiveFullscreen());
+  ImmersiveModeControllerAsh* immersive_controller =
+      static_cast<ImmersiveModeControllerAsh*>(
+          browser_view->immersive_mode_controller());
+  immersive_controller->DisableAnimationsForTest();
+
+  // Move the mouse out of the way.
+  immersive_controller->SetMouseHoveredForTest(false);
+
+  // Enter immersive fullscreen.
+  {
+    scoped_ptr<FullscreenNotificationObserver> waiter(
+        new FullscreenNotificationObserver());
+    chrome::ToggleFullscreenMode(browser());
+    waiter->Wait();
+  }
+  ASSERT_TRUE(immersive_controller->IsEnabled());
+  ASSERT_FALSE(immersive_controller->IsRevealed());
+
+  // The zoom bubble should not be anchored when it is shown in immersive
+  // fullscreen and the top-of-window views are not revealed.
+  ZoomBubbleView::ShowBubble(web_contents, false);
+  ASSERT_TRUE(ZoomBubbleView::IsShowing());
+  const ZoomBubbleView* zoom_bubble = ZoomBubbleView::GetZoomBubbleForTest();
+  EXPECT_FALSE(zoom_bubble->anchor_view());
+
+  // An immersive reveal should hide the zoom bubble.
+  scoped_ptr<ImmersiveRevealedLock> immersive_reveal_lock(
+      immersive_controller->GetRevealedLock(
+          ImmersiveModeController::ANIMATE_REVEAL_NO));
+  ASSERT_TRUE(immersive_controller->IsRevealed());
+  EXPECT_FALSE(ZoomBubbleView::IsShowing());
+
+  // The zoom bubble should be anchored when it is shown in immersive fullscreen
+  // and the top-of-window views are revealed.
+  ZoomBubbleView::ShowBubble(web_contents, true);
+  ASSERT_TRUE(ZoomBubbleView::IsShowing());
+  zoom_bubble = ZoomBubbleView::GetZoomBubbleForTest();
+  EXPECT_TRUE(zoom_bubble->anchor_view());
+
+  // The top-of-window views should not hide till the zoom bubble hides. (It
+  // would be weird if the view to which the zoom bubble is anchored hid while
+  // the zoom bubble was still visible.)
+  immersive_reveal_lock.reset();
+  EXPECT_TRUE(immersive_controller->IsRevealed());
+  ZoomBubbleView::CloseBubble();
+  // The zoom bubble is deleted on a task.
+  content::RunAllPendingInMessageLoop();
+  EXPECT_FALSE(immersive_controller->IsRevealed());
+
+  // Exit fullscreen before ending the test for the sake of sanity.
+  {
+    scoped_ptr<FullscreenNotificationObserver> waiter(
+        new FullscreenNotificationObserver());
+    chrome::ToggleFullscreenMode(browser());
+    waiter->Wait();
+  }
+}
+#endif  // OS_CHROMEOS
diff --git a/chrome/browser/ui/views/message_center/web_notification_tray.cc b/chrome/browser/ui/views/message_center/web_notification_tray.cc
index 77a79db..d8ae595 100644
--- a/chrome/browser/ui/views/message_center/web_notification_tray.cc
+++ b/chrome/browser/ui/views/message_center/web_notification_tray.cc
@@ -30,10 +30,6 @@
 #include "ui/message_center/views/message_popup_collection.h"
 #include "ui/views/widget/widget.h"
 
-#if defined(OS_WIN)
-#include "ui/base/win/hwnd_util.h"
-#endif
-
 namespace {
 
 // Tray constants
@@ -145,20 +141,21 @@
 }
 
 bool WebNotificationTray::ShowPopups() {
-  popup_collection_.reset(
-      new message_center::MessagePopupCollection(NULL, message_center()));
+  popup_collection_.reset(new message_center::MessagePopupCollection(
+      NULL, message_center(), message_center_tray_.get()));
   return true;
 }
 
 void WebNotificationTray::HidePopups() { popup_collection_.reset(); }
 
-bool WebNotificationTray::ShowMessageCenter() {
+bool WebNotificationTray::ShowMessageCenterInternal(bool show_settings) {
   content::RecordAction(UserMetricsAction("Notifications.ShowMessageCenter"));
 
   // Using MessageBubbleBase instead of MessageCenterBubble to
   // remove dependence on implicit type conversion
-  scoped_ptr<message_center::MessageBubbleBase> bubble(
-      new message_center::MessageCenterBubble(message_center()));
+  scoped_ptr<message_center::MessageCenterBubble> bubble(
+      new message_center::MessageCenterBubble(message_center(),
+                                              message_center_tray_.get()));
 
   gfx::Screen* screen = gfx::Screen::GetNativeScreen();
   gfx::Rect work_area = screen->GetPrimaryDisplay().work_area();
@@ -183,14 +180,20 @@
     }
   }
   bubble->SetMaxHeight(max_height);
+  if (show_settings)
+    bubble->SetSettingsVisible();
 
   message_center_bubble_.reset(new internal::NotificationBubbleWrapper(
       this,
-      bubble.Pass(),
+      bubble.PassAs<message_center::MessageBubbleBase>(),
       internal::NotificationBubbleWrapper::BUBBLE_TYPE_MESSAGE_CENTER));
   return true;
 }
 
+bool WebNotificationTray::ShowMessageCenter() {
+  return ShowMessageCenterInternal(false /* show_settings */);
+}
+
 void WebNotificationTray::HideMessageCenter() {
   message_center_bubble_.reset();
 }
@@ -202,6 +205,15 @@
   // non-rich-notifications in ChromeOS).
 };
 
+bool WebNotificationTray::ShowNotifierSettings() {
+  if (message_center_bubble_) {
+    static_cast<MessageCenterBubble*>(
+        message_center_bubble_->bubble())->SetSettingsVisible();
+    return true;
+  }
+  return ShowMessageCenterInternal(true /* show_settings */);
+}
+
 void WebNotificationTray::OnMessageCenterTrayChanged() {
   // See the comments in ash/system/web_notification/web_notification_tray.cc
   // for why PostTask.
diff --git a/chrome/browser/ui/views/message_center/web_notification_tray.h b/chrome/browser/ui/views/message_center/web_notification_tray.h
index 86b867e..67e2d4f 100644
--- a/chrome/browser/ui/views/message_center/web_notification_tray.h
+++ b/chrome/browser/ui/views/message_center/web_notification_tray.h
@@ -50,6 +50,7 @@
   virtual void HideMessageCenter() OVERRIDE;
   virtual void UpdatePopups() OVERRIDE;
   virtual void OnMessageCenterTrayChanged() OVERRIDE;
+  virtual bool ShowNotifierSettings() OVERRIDE;
 
   // These are forwarded to WebNotificationTray by
   // NotificationBubbleWrapper classes since they don't have enough
@@ -61,6 +62,13 @@
 
   // StatusIconObserver implementation.
   virtual void OnStatusIconClicked() OVERRIDE;
+#if defined(OS_WIN)
+  virtual void OnBalloonClicked() OVERRIDE;
+
+  // This shows a platform-specific balloon informing the user of the existence
+  // of the message center in the status tray area.
+  void DisplayFirstRunBalloon();
+#endif
 
   // Changes the icon and hovertext based on number of unread notifications.
   void UpdateStatusIcon();
@@ -73,6 +81,10 @@
                            ManyMessageCenterNotifications);
   FRIEND_TEST_ALL_PREFIXES(WebNotificationTrayTest, ManyPopupNotifications);
 
+  // The actual process to show the message center. Set |show_settings| to true
+  // if the message center should be initialized with the settings visible.
+  // Returns true if the center is successfully created.
+  bool ShowMessageCenterInternal(bool show_settings);
   StatusIcon* GetStatusIcon();
   void DestroyStatusIcon();
   void AddQuietModeMenu(StatusIcon* status_icon);
diff --git a/chrome/browser/ui/views/message_center/web_notification_tray_win.cc b/chrome/browser/ui/views/message_center/web_notification_tray_win.cc
new file mode 100644
index 0000000..dcc6e25
--- /dev/null
+++ b/chrome/browser/ui/views/message_center/web_notification_tray_win.cc
@@ -0,0 +1,61 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/message_center/web_notification_tray.h"
+
+#include <windows.h>
+
+#include "base/win/windows_version.h"
+#include "chrome/browser/app_icon_win.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/status_icons/status_icon.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/host_desktop.h"
+#include "chrome/browser/ui/singleton_tabs.h"
+#include "chrome/common/url_constants.h"
+#include "grit/chromium_strings.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/image/image_skia.h"
+
+namespace message_center {
+void WebNotificationTray::OnBalloonClicked() {
+  Browser* browser = chrome::FindOrCreateTabbedBrowser(
+      ProfileManager::GetLastUsedProfileAllowedByPolicy(),
+      chrome::GetActiveDesktop());
+  chrome::ShowSingletonTab(browser, GURL(chrome::kNotificationsHelpURL));
+}
+
+void WebNotificationTray::DisplayFirstRunBalloon() {
+  StatusIcon* status_icon = GetStatusIcon();
+  if (!status_icon)
+    return;
+
+  base::win::Version win_version = base::win::GetVersion();
+  if (win_version == base::win::VERSION_PRE_XP)
+    return;
+
+  ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
+
+  // StatusIconWin uses NIIF_LARGE_ICON if the version is >= vista.  According
+  // to http://msdn.microsoft.com/en-us/library/windows/desktop/bb773352.aspx:
+  // This corresponds to the icon with dimensions SM_CXICON x SM_CYICON. If
+  // this flag is not set, the icon with dimensions SM_CXSMICON x SM_CYSMICON
+  // is used.
+  int icon_size = GetSystemMetrics(SM_CXICON);
+  if (win_version < base::win::VERSION_VISTA)
+    icon_size = GetSystemMetrics(SM_CXSMICON);
+
+  scoped_ptr<SkBitmap> sized_app_icon_bitmap = GetAppIconForSize(icon_size);
+  gfx::ImageSkia sized_app_icon_skia =
+      gfx::ImageSkia::CreateFrom1xBitmap(*sized_app_icon_bitmap);
+  string16 product_name(l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME));
+  GetStatusIcon()->DisplayBalloon(
+      sized_app_icon_skia,
+      l10n_util::GetStringUTF16(IDS_MESSAGE_CENTER_BALLOON_TITLE),
+      l10n_util::GetStringUTF16(IDS_MESSAGE_CENTER_BALLOON_TEXT));
+}
+}  // namespace message_center
diff --git a/chrome/browser/ui/views/notifications/balloon_view_views.cc b/chrome/browser/ui/views/notifications/balloon_view_views.cc
index d6dc956..83884c7 100644
--- a/chrome/browser/ui/views/notifications/balloon_view_views.cc
+++ b/chrome/browser/ui/views/notifications/balloon_view_views.cc
@@ -336,7 +336,7 @@
 
   frame_container_ = new views::Widget;
   params.delegate = this;
-  params.transparent = true;
+  params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
   params.bounds = GetBoundsForFrameContainer();
   frame_container_->Init(params);
   frame_container_->SetContentsView(this);
diff --git a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
index 7fa6764..ec579dc 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
@@ -216,7 +216,7 @@
     popup_ = (new AutocompletePopupWidget)->AsWeakPtr();
     views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
     params.can_activate = false;
-    params.transparent = true;
+    params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
     params.parent = popup_parent;
     params.bounds = GetPopupBounds();
     params.context = popup_parent;
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
index 4abb228..3c39284 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
@@ -364,7 +364,6 @@
   bool changed_security_level = (security_level != security_level_);
   security_level_ = security_level;
 
-  // TODO(msw|oshima): Copied from GTK, determine correct Win/CrOS behavior.
   if (contents) {
     RevertAll();
     const OmniboxState* state = static_cast<OmniboxState*>(
@@ -377,7 +376,30 @@
       ClearEditHistory();
     }
   } else if (visibly_changed_permanent_text) {
+    // Not switching tabs, just updating the permanent text.  (In the case where
+    // we _were_ switching tabs, the RevertAll() above already drew the new
+    // permanent text.)
+
+    // Tweak: if the user had all the text selected, select all the new text.
+    // This makes one particular case better: the user clicks in the box to
+    // change it right before the permanent URL is changed.  Since the new URL
+    // is still fully selected, the user's typing will replace the edit contents
+    // as they'd intended.
+    const ui::Range range(GetSelectedRange());
+    const bool was_select_all = (range.length() == text().length());
+
     RevertAll();
+
+    // Only select all when we have focus.  If we don't have focus, selecting
+    // all is unnecessary since the selection will change on regaining focus,
+    // and can in fact cause artifacts, e.g. if the user is on the NTP and
+    // clicks a link to navigate, causing |was_select_all| to be vacuously true
+    // for the empty omnibox, and we then select all here, leading to the
+    // trailing portion of a long URL being scrolled into view.  We could try
+    // and address cases like this, but it seems better to just not muck with
+    // things when the omnibox isn't focused to begin with.
+    if (was_select_all && model()->has_focus())
+      SelectAll(range.is_reversed());
   } else if (changed_security_level) {
     EmphasizeURLComponents();
   }
@@ -585,10 +607,16 @@
 #if defined(OS_CHROMEOS)
   return ime_candidate_window_open_;
 #else
-  // TODO(yukishiino): Implement detection of candidate windows on Windows.
-  // We can detect whether any candidate window is open or not on Windows.
-  // Currently we simply fall back to IsImeComposing() as a second best way.
-  return IsImeComposing();
+  // We need const_cast here because there is no const version of
+  // View::GetInputMethod().  It's because Widget::GetInputMethod(), called from
+  // View::GetInputMethod(), creates a new views::InputMethod at the first-time
+  // call.  Except for this point, none of this method, View::GetInputMethod()
+  // or Widget::GetInputMethod() modifies the state of their instances.
+  // TODO(yukishiino): Make {View,Widget}::GetInputMethod() const and make the
+  // underlying input method object mutable.
+  const views::InputMethod* input_method =
+      const_cast<OmniboxViewViews*>(this)->GetInputMethod();
+  return input_method && input_method->IsCandidatePopupOpen();
 #endif
 }
 
@@ -741,7 +769,7 @@
   menu_contents->AddItemWithStringId(IDC_EDIT_SEARCH_ENGINES,
       IDS_EDIT_SEARCH_ENGINES);
 
-  if (chrome::IsQueryExtractionEnabled(model()->profile())) {
+  if (chrome::IsQueryExtractionEnabled()) {
     int copy_position = menu_contents->GetIndexOfCommandId(IDS_APP_COPY);
     DCHECK(copy_position >= 0);
     menu_contents->InsertItemWithStringIdAt(
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_win.cc b/chrome/browser/ui/views/omnibox/omnibox_view_win.cc
index 3548e7f..db535a3 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_view_win.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_view_win.cc
@@ -639,26 +639,27 @@
     // we _were_ switching tabs, the RevertAll() above already drew the new
     // permanent text.)
 
-    // Tweak: if the edit was previously nonempty and had all the text selected,
-    // select all the new text.  This makes one particular case better: the
-    // user clicks in the box to change it right before the permanent URL is
-    // changed.  Since the new URL is still fully selected, the user's typing
-    // will replace the edit contents as they'd intended.
-    //
-    // NOTE: The selection can be longer than the text length if the edit is in
-    // in rich text mode and the user has selected the "phantom newline" at the
-    // end, so use ">=" instead of "==" to see if all the text is selected.  In
-    // theory we prevent this case from ever occurring, but this is still safe.
+    // Tweak: if the user had all the text selected, select all the new text.
+    // This makes one particular case better: the user clicks in the box to
+    // change it right before the permanent URL is changed.  Since the new URL
+    // is still fully selected, the user's typing will replace the edit contents
+    // as they'd intended.
     CHARRANGE sel;
     GetSelection(sel);
-    const bool was_reversed = (sel.cpMin > sel.cpMax);
-    const bool was_sel_all = (sel.cpMin != sel.cpMax) &&
-      IsSelectAllForRange(sel);
+    const bool was_select_all = IsSelectAllForRange(sel);
 
     RevertAll();
 
-    if (was_sel_all)
-      SelectAll(was_reversed);
+    // Only select all when we have focus.  If we don't have focus, selecting
+    // all is unnecessary since the selection will change on regaining focus,
+    // and can in fact cause artifacts, e.g. if the user is on the NTP and
+    // clicks a link to navigate, causing |was_select_all| to be vacuously true
+    // for the empty omnibox, and we then select all here, leading to the
+    // trailing portion of a long URL being scrolled into view.  We could try
+    // and address cases like this, but it seems better to just not muck with
+    // things when the omnibox isn't focused to begin with.
+    if (was_select_all && model()->has_focus())
+      SelectAll(sel.cpMin > sel.cpMax);
   } else if (changed_security_level) {
     // Only the security style changed, nothing else.  Redraw our text using it.
     EmphasizeURLComponents();
@@ -2784,7 +2785,7 @@
     context_menu_contents_->AddSeparator(ui::NORMAL_SEPARATOR);
     context_menu_contents_->AddItemWithStringId(IDC_CUT, IDS_CUT);
     context_menu_contents_->AddItemWithStringId(IDC_COPY, IDS_COPY);
-    if (chrome::IsQueryExtractionEnabled(model()->profile()))
+    if (chrome::IsQueryExtractionEnabled())
       context_menu_contents_->AddItemWithStringId(IDC_COPY_URL, IDS_COPY_URL);
     context_menu_contents_->AddItemWithStringId(IDC_PASTE, IDS_PASTE);
     // GetContextualLabel() will override this next label with the
diff --git a/chrome/browser/ui/views/panels/panel_stack_view.cc b/chrome/browser/ui/views/panels/panel_stack_view.cc
index b4c7df3..25843ed 100644
--- a/chrome/browser/ui/views/panels/panel_stack_view.cc
+++ b/chrome/browser/ui/views/panels/panel_stack_view.cc
@@ -218,6 +218,11 @@
     // To work around this problem, we recreate the underlying window.
     views::Widget* old_window = window_;
     window_ = CreateWindowWithBounds(GetStackWindowBounds());
+
+    // New background window should also be minimized if the old one is.
+    if (old_window->IsMinimized())
+      window_->Minimize();
+
     // Make sure the new background window stays at the same z-order as the old
     // one.
     ::SetWindowPos(views::HWNDForWidget(window_),
@@ -228,6 +233,11 @@
          iter != panels_.end(); ++iter) {
       MakeStackWindowOwnPanelWindow(*iter, this);
     }
+
+    // Serve the snapshot to the new backgroud window.
+    if (thumbnailer_.get())
+      thumbnailer_->ReplaceWindow(views::HWNDForWidget(window_));
+
     window_->UpdateWindowTitle();
     window_->UpdateWindowIcon();
     old_window->Close();
@@ -450,12 +460,6 @@
       ShellIntegration::GetAppModelIdForProfile(UTF8ToWide(panel->app_name()),
                                                 panel->profile()->GetPath()),
       views::HWNDForWidget(window));
-
-  if (base::win::GetVersion() >= base::win::VERSION_WIN7) {
-    HWND native_window = views::HWNDForWidget(window);
-    thumbnailer_.reset(new TaskbarWindowThumbnailerWin(native_window, this));
-    thumbnailer_->Start();
-  }
 #endif
 
   return window;
@@ -468,6 +472,14 @@
   // Empty size is not allowed so a temporary small size is passed. SetBounds
   // will be called later to update the bounds.
   window_ = CreateWindowWithBounds(gfx::Rect(0, 0, 1, 1));
+
+#if defined(OS_WIN)
+  if (base::win::GetVersion() >= base::win::VERSION_WIN7) {
+    HWND native_window = views::HWNDForWidget(window_);
+    thumbnailer_.reset(new TaskbarWindowThumbnailerWin(native_window, this));
+    thumbnailer_->Start();
+  }
+#endif
 }
 
 #if defined(OS_WIN)
@@ -484,7 +496,9 @@
 }
 
 void PanelStackView::RefreshLivePreviewThumbnail() {
-  if (!thumbnailer_.get())
+  // Don't refresh the thumbnail when the stack window is system minimized
+  // because the snapshot could not be retrieved.
+  if (!thumbnailer_.get() || IsMinimized())
     return;
   thumbnailer_->InvalidateSnapshot();
 }
diff --git a/chrome/browser/ui/views/panels/panel_view.cc b/chrome/browser/ui/views/panels/panel_view.cc
index a253fa4..bf81562 100644
--- a/chrome/browser/ui/views/panels/panel_view.cc
+++ b/chrome/browser/ui/views/panels/panel_view.cc
@@ -568,6 +568,16 @@
       window_->Hide();
   } else {
     ShowPanelInactive();
+
+#if defined(OS_WIN)
+    // When hiding and showing again a top-most window that belongs to a
+    // background application (i.e. the application is not a foreground one),
+    // the window may loose top-most placement even though its WS_EX_TOPMOST
+    // bit is still set. Re-issuing SetWindowsPos() returns the window to its
+    // top-most placement.
+    if (always_on_top_)
+      window_->SetAlwaysOnTop(true);
+#endif
   }
 }
 
diff --git a/chrome/browser/ui/views/panels/taskbar_window_thumbnailer_win.cc b/chrome/browser/ui/views/panels/taskbar_window_thumbnailer_win.cc
index 9a47e96..e6946bb 100644
--- a/chrome/browser/ui/views/panels/taskbar_window_thumbnailer_win.cc
+++ b/chrome/browser/ui/views/panels/taskbar_window_thumbnailer_win.cc
@@ -82,6 +82,18 @@
   ::DwmInvalidateIconicBitmaps(hwnd_);
 }
 
+void TaskbarWindowThumbnailerWin::ReplaceWindow(HWND new_hwnd) {
+  // Stop serving the custom thumbnail for the old window.
+  EnableCustomThumbnail(hwnd_, false);
+  ui::HWNDSubclass::RemoveFilterFromAllTargets(this);
+
+  hwnd_ = new_hwnd;
+
+  // Start serving the custom thumbnail to the new window.
+  ui::HWNDSubclass::AddFilterToTarget(hwnd_, this);
+  EnableCustomThumbnail(hwnd_, true);
+}
+
 bool TaskbarWindowThumbnailerWin::FilterMessage(HWND hwnd,
                                                 UINT message,
                                                 WPARAM w_param,
diff --git a/chrome/browser/ui/views/panels/taskbar_window_thumbnailer_win.h b/chrome/browser/ui/views/panels/taskbar_window_thumbnailer_win.h
index 6d13b00..8031599 100644
--- a/chrome/browser/ui/views/panels/taskbar_window_thumbnailer_win.h
+++ b/chrome/browser/ui/views/panels/taskbar_window_thumbnailer_win.h
@@ -42,6 +42,10 @@
   // when the system requests it.
   void InvalidateSnapshot();
 
+  // Provide the snapshot to the new window. If the snapshot is captured for the
+  // old window, it will also be used for the new window.
+  void ReplaceWindow(HWND new_hwnd);
+
  private:
   // Overridden from ui::HWNDMessageFilter:
   virtual bool FilterMessage(HWND hwnd,
diff --git a/chrome/browser/ui/views/password_generation_bubble_view.cc b/chrome/browser/ui/views/password_generation_bubble_view.cc
index 0c45d3f..cab4c79 100644
--- a/chrome/browser/ui/views/password_generation_bubble_view.cc
+++ b/chrome/browser/ui/views/password_generation_bubble_view.cc
@@ -9,7 +9,7 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/common/url_constants.h"
-#include "components/autofill/browser/password_generator.h"
+#include "components/autofill/core/browser/password_generator.h"
 #include "components/autofill/core/common/autofill_messages.h"
 #include "components/autofill/core/common/password_generation_util.h"
 #include "content/public/browser/page_navigator.h"
diff --git a/chrome/browser/ui/views/reload_button.h b/chrome/browser/ui/views/reload_button.h
index 31ebdc9..2611aef 100644
--- a/chrome/browser/ui/views/reload_button.h
+++ b/chrome/browser/ui/views/reload_button.h
@@ -7,7 +7,7 @@
 
 #include "base/basictypes.h"
 #include "base/gtest_prod_util.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "ui/base/models/simple_menu_model.h"
 #include "ui/views/controls/button/button_dropdown.h"
 
diff --git a/chrome/browser/ui/views/screen_capture_notification_ui_views.cc b/chrome/browser/ui/views/screen_capture_notification_ui_views.cc
new file mode 100644
index 0000000..227ef1c
--- /dev/null
+++ b/chrome/browser/ui/views/screen_capture_notification_ui_views.cc
@@ -0,0 +1,286 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/screen_capture_notification_ui.h"
+
+#include "ash/shell.h"
+#include "chrome/app/chrome_dll_resource.h"
+#include "chrome/browser/ui/views/chrome_views_export.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "ui/aura/root_window.h"
+#include "ui/base/hit_test.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/views/bubble/bubble_border.h"
+#include "ui/views/bubble/bubble_frame_view.h"
+#include "ui/views/controls/button/blue_button.h"
+#include "ui/views/controls/image_view.h"
+#include "ui/views/corewm/shadow_types.h"
+#include "ui/views/layout/box_layout.h"
+#include "ui/views/view.h"
+#include "ui/views/widget/widget.h"
+#include "ui/views/widget/widget_delegate.h"
+
+namespace {
+
+const int kMinimumWidth = 460;
+const int kMaximumWidth = 1000;
+const int kHorizontalMargin = 10;
+const int kPadding = 5;
+const int kPaddingLeft = 10;
+
+namespace {
+
+// A ClientView that overrides NonClientHitTest() so that the whole window area
+// acts as a window caption, except a rect specified using SetClientRect().
+// ScreenCaptureNotificationUIViews uses this class to make the notification bar
+// draggable.
+class NotificationBarClientView : public views::ClientView {
+ public:
+  NotificationBarClientView(views::Widget* widget, views::View* view)
+      : views::ClientView(widget, view) {
+  }
+  virtual ~NotificationBarClientView() {}
+
+  void SetClientRect(const gfx::Rect& rect) {
+    rect_ = rect;
+  }
+
+  // views::ClientView overrides.
+  virtual int NonClientHitTest(const gfx::Point& point) OVERRIDE  {
+    if (!bounds().Contains(point))
+      return HTNOWHERE;
+    // The whole window is HTCAPTION, except the |rect_|.
+    if (rect_.Contains(gfx::PointAtOffsetFromOrigin(point - bounds().origin())))
+      return HTCLIENT;
+
+    return HTCAPTION;
+  }
+
+ private:
+  gfx::Rect rect_;
+
+  DISALLOW_COPY_AND_ASSIGN(NotificationBarClientView);
+};
+
+}  // namespace
+
+// ScreenCaptureNotificationUI implementation using Views.
+class ScreenCaptureNotificationUIViews
+    : public ScreenCaptureNotificationUI,
+      public views::WidgetDelegateView,
+      public views::ButtonListener {
+ public:
+  ScreenCaptureNotificationUIViews();
+  virtual ~ScreenCaptureNotificationUIViews();
+
+  // ScreenCaptureNotificationUI interface.
+  virtual bool Show(const base::Closure& stop_callback,
+                    const string16& title) OVERRIDE;
+
+  // views::View overrides.
+  virtual gfx::Size GetPreferredSize() OVERRIDE;
+  virtual void Layout() OVERRIDE;
+
+  // views::WidgetDelegateView overrides.
+  virtual void DeleteDelegate() OVERRIDE;
+  virtual views::View* GetContentsView() OVERRIDE;
+  virtual views::ClientView* CreateClientView(views::Widget* widget) OVERRIDE;
+  virtual views::NonClientFrameView* CreateNonClientFrameView(
+      views::Widget* widget) OVERRIDE;
+  virtual string16 GetWindowTitle() const OVERRIDE;
+  virtual bool ShouldShowWindowTitle() const OVERRIDE;
+  virtual bool ShouldShowCloseButton() const OVERRIDE;
+
+  // views::ButtonListener interface.
+  virtual void ButtonPressed(views::Button* sender,
+                             const ui::Event& event) OVERRIDE;
+
+ private:
+  // Helper to call |stop_callback_|.
+  void NotifyStopped();
+
+  base::Closure stop_callback_;
+  string16 window_title_;
+  NotificationBarClientView* client_view_;
+  views::ImageView* gripper_;
+  views::Label* label_;
+  views::BlueButton* stop_button_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScreenCaptureNotificationUIViews);
+};
+
+ScreenCaptureNotificationUIViews::ScreenCaptureNotificationUIViews()
+    : client_view_(NULL),
+      gripper_(NULL),
+      label_(NULL),
+      stop_button_(NULL) {
+  set_owned_by_client();
+
+  set_background(views::Background::CreateSolidBackground(GetNativeTheme()->
+      GetSystemColor(ui::NativeTheme::kColorId_DialogBackground)));
+
+  gripper_ = new views::ImageView();
+  gripper_->SetImage(
+      ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
+          IDR_SCREEN_CAPTURE_NOTIFICATION_GRIP));
+  AddChildView(gripper_);
+
+  label_ = new views::Label();
+  AddChildView(label_);
+
+  string16 stop_text =
+      l10n_util::GetStringUTF16(IDS_MEDIA_SCREEN_CAPTURE_NOTIFICATION_STOP);
+  stop_button_ = new views::BlueButton(this, stop_text);
+  AddChildView(stop_button_);
+}
+
+ScreenCaptureNotificationUIViews::~ScreenCaptureNotificationUIViews() {
+  stop_callback_.Reset();
+  delete GetWidget();
+}
+
+bool ScreenCaptureNotificationUIViews::Show(
+    const base::Closure& stop_callback,
+    const string16& title) {
+  stop_callback_ = stop_callback;
+
+  label_->SetElideBehavior(views::Label::ELIDE_IN_MIDDLE);
+  label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+  string16 text = l10n_util::GetStringFUTF16(
+      IDS_MEDIA_SCREEN_CAPTURE_NOTIFICATION_TEXT, title);
+  label_->SetText(text);
+  window_title_ = l10n_util::GetStringFUTF16(
+      IDS_MEDIA_SCREEN_CAPTURE_NOTIFICATION_TITLE, title);
+
+  views::Widget* widget = new views::Widget;
+
+  views::Widget::InitParams params;
+  params.delegate = this;
+  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+  params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
+  params.remove_standard_frame = true;
+  params.keep_on_top = true;
+  params.top_level = true;
+  params.can_activate = false;
+
+#if defined(USE_ASH)
+  // TODO(sergeyu): The notification bar must be shown on the monitor that's
+  // being captured. Make sure it's always the case. Currently we always capture
+  // the primary monitor.
+  if (ash::Shell::HasInstance())
+    params.context = ash::Shell::GetPrimaryRootWindow();
+#endif
+
+  widget->set_frame_type(views::Widget::FRAME_TYPE_FORCE_CUSTOM);
+  widget->Init(params);
+  widget->SetAlwaysOnTop(true);
+
+  gfx::Screen* screen = gfx::Screen::GetNativeScreen();
+  // TODO(sergeyu): Move the notification to the display being captured when
+  // per-display screen capture is supported.
+  gfx::Rect work_area = screen->GetPrimaryDisplay().work_area();
+
+  // Place the bar in the center of the bottom of the display.
+  gfx::Size size = widget->non_client_view()->GetPreferredSize();
+  gfx::Rect bounds(
+      work_area.x() + work_area.width() / 2 - size.width() / 2,
+      work_area.y() + work_area.height() - size.height(),
+      size.width(), size.height());
+  widget->SetBounds(bounds);
+
+  widget->Show();
+
+  return true;
+}
+
+gfx::Size ScreenCaptureNotificationUIViews::GetPreferredSize() {
+  gfx::Size grip_size = gripper_->GetPreferredSize();
+  gfx::Size label_size = child_at(1)->GetPreferredSize();
+  gfx::Size button_size = child_at(2)->GetPreferredSize();
+  int width = kHorizontalMargin * 2 + grip_size.width() + label_size.width() +
+      button_size.width();
+  width = std::max(width, kMinimumWidth);
+  width = std::min(width, kMaximumWidth);
+  return gfx::Size(width, std::max(label_size.height(), button_size.height()));
+}
+
+void ScreenCaptureNotificationUIViews::Layout() {
+  gfx::Rect grip_rect(gripper_->GetPreferredSize());
+  grip_rect.set_y(bounds().height() / 2 - grip_rect.height() / 2);
+  gripper_->SetBoundsRect(grip_rect);
+
+  gfx::Rect button_rect(stop_button_->GetPreferredSize());
+  button_rect.set_x(bounds().width() - button_rect.width());
+  stop_button_->SetBoundsRect(button_rect);
+
+  gfx::Rect label_rect;
+  label_rect.set_x(grip_rect.right() + kHorizontalMargin);
+  label_rect.set_width(button_rect.x() - kHorizontalMargin - label_rect.x());
+  label_rect.set_height(bounds().height());
+  label_->SetBoundsRect(label_rect);
+
+  client_view_->SetClientRect(button_rect);
+}
+
+void ScreenCaptureNotificationUIViews::DeleteDelegate() {
+  NotifyStopped();
+}
+
+views::View* ScreenCaptureNotificationUIViews::GetContentsView() {
+  return this;
+}
+
+views::ClientView* ScreenCaptureNotificationUIViews::CreateClientView(
+    views::Widget* widget) {
+  DCHECK(!client_view_);
+  client_view_ = new NotificationBarClientView(widget, this);
+  return client_view_;
+}
+
+views::NonClientFrameView*
+ScreenCaptureNotificationUIViews::CreateNonClientFrameView(
+    views::Widget* widget) {
+  views::BubbleFrameView* frame = new views::BubbleFrameView(
+      gfx::Insets(kPadding, kPaddingLeft, kPadding, kPadding));
+  SkColor color = widget->GetNativeTheme()->GetSystemColor(
+      ui::NativeTheme::kColorId_DialogBackground);
+  views::BubbleBorder* border = new views::BubbleBorder(
+      views::BubbleBorder::NONE, views::BubbleBorder::SMALL_SHADOW, color);
+  frame->SetBubbleBorder(border);
+  return frame;
+}
+
+string16 ScreenCaptureNotificationUIViews::GetWindowTitle() const {
+  return window_title_;
+}
+
+bool ScreenCaptureNotificationUIViews::ShouldShowWindowTitle() const {
+  return false;
+}
+
+bool ScreenCaptureNotificationUIViews::ShouldShowCloseButton() const {
+  return false;
+}
+
+void ScreenCaptureNotificationUIViews::ButtonPressed(views::Button* sender,
+                                                     const ui::Event& event) {
+  NotifyStopped();
+}
+
+void ScreenCaptureNotificationUIViews::NotifyStopped() {
+  if (!stop_callback_.is_null()) {
+    base::Closure callback = stop_callback_;
+    stop_callback_.Reset();
+    callback.Run();
+  }
+}
+
+}  // namespace
+
+scoped_ptr<ScreenCaptureNotificationUI> ScreenCaptureNotificationUI::Create() {
+  return scoped_ptr<ScreenCaptureNotificationUI>(
+      new ScreenCaptureNotificationUIViews());
+}
diff --git a/chrome/browser/ui/views/select_file_dialog_extension.cc b/chrome/browser/ui/views/select_file_dialog_extension.cc
index 3efc148..09e9ee5 100644
--- a/chrome/browser/ui/views/select_file_dialog_extension.cc
+++ b/chrome/browser/ui/views/select_file_dialog_extension.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/ui/views/select_file_dialog_extension.h"
 
+#include "apps/shell_window.h"
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/logging.h"
@@ -24,7 +25,6 @@
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/chrome_select_file_policy.h"
 #include "chrome/browser/ui/extensions/native_app_window.h"
-#include "chrome/browser/ui/extensions/shell_window.h"
 #include "chrome/browser/ui/host_desktop.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/views/extensions/extension_dialog.h"
@@ -33,16 +33,14 @@
 #include "ui/base/base_window.h"
 #include "ui/shell_dialogs/selected_file_info.h"
 
+using apps::ShellWindow;
 using content::BrowserThread;
 
 namespace {
 
-const int kFileManagerWidth = 954;  // pixels
+const int kFileManagerWidth = 972;  // pixels
 const int kFileManagerHeight = 640;  // pixels
 
-const int kFileManagerMinimumWidth = kFileManagerWidth * 2 / 3;  // pixels
-const int kFileManagerMinimumHeight = kFileManagerHeight * 2 / 3;  // pixels
-
 // Holds references to file manager dialogs that have callbacks pending
 // to their listeners.
 class PendingDialog {
@@ -354,8 +352,8 @@
   ExtensionDialog* dialog = ExtensionDialog::Show(file_browser_url,
       base_window, profile_, web_contents,
       kFileManagerWidth, kFileManagerHeight,
-      kFileManagerMinimumWidth,
-      kFileManagerMinimumHeight,
+      kFileManagerWidth,
+      kFileManagerHeight,
 #if defined(USE_AURA)
       file_manager_util::GetTitleFromType(type),
 #else
diff --git a/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc b/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc
index 92cf6eb..b77b366 100644
--- a/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc
+++ b/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc
@@ -200,7 +200,8 @@
     content::RenderViewHost* host = dialog_->GetRenderViewHost();
     string16 main_frame;
     std::string button_class =
-        (button_type == DIALOG_BTN_OK) ? ".ok" : ".cancel";
+        (button_type == DIALOG_BTN_OK) ? ".button-panel .ok" :
+                                         ".button-panel .cancel";
     string16 script = ASCIIToUTF16(
         "console.log(\'Test JavaScript injected.\');"
         "document.querySelector(\'" + button_class + "\').click();");
diff --git a/chrome/browser/ui/views/status_bubble_views.cc b/chrome/browser/ui/views/status_bubble_views.cc
index 3fbb520..48ed6eb 100644
--- a/chrome/browser/ui/views/status_bubble_views.cc
+++ b/chrome/browser/ui/views/status_bubble_views.cc
@@ -572,7 +572,7 @@
     if (!expand_view_.get())
       expand_view_.reset(new StatusViewExpander(this, view_));
     views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
-    params.transparent = true;
+    params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
     params.accept_events = false;
     params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
     params.parent = frame->GetNativeView();
diff --git a/chrome/browser/ui/views/status_icons/status_icon_win.cc b/chrome/browser/ui/views/status_icons/status_icon_win.cc
index ee23a68..a5af417 100644
--- a/chrome/browser/ui/views/status_icons/status_icon_win.cc
+++ b/chrome/browser/ui/views/status_icons/status_icon_win.cc
@@ -63,6 +63,11 @@
       ui::MENU_SOURCE_MOUSE, views::MenuRunner::HAS_MNEMONICS));
 }
 
+void StatusIconWin::HandleBalloonClickEvent() {
+  if (HasObservers())
+    DispatchBalloonClickEvent();
+}
+
 void StatusIconWin::ResetIcon() {
   NOTIFYICONDATA icon_data;
   InitIconData(&icon_data);
@@ -143,6 +148,9 @@
 // StatusIconWin, private:
 
 void StatusIconWin::UpdatePlatformContextMenu(ui::MenuModel* menu) {
+  // |menu_model_| is about to be destroyed. Destroy the menu (which closes it)
+  // so that it doesn't attempt to continue using |menu_model_|.
+  menu_runner_.reset();
   DCHECK(menu);
   menu_model_ = menu;
 }
diff --git a/chrome/browser/ui/views/status_icons/status_icon_win.h b/chrome/browser/ui/views/status_icons/status_icon_win.h
index b15a5e1..8f4cf1b 100644
--- a/chrome/browser/ui/views/status_icons/status_icon_win.h
+++ b/chrome/browser/ui/views/status_icons/status_icon_win.h
@@ -33,6 +33,9 @@
   // otherwise displays the context menu if there is one.
   void HandleClickEvent(const gfx::Point& cursor_pos, bool left_button_click);
 
+  // Handles a click on the balloon from the user.
+  void HandleBalloonClickEvent();
+
   // Re-creates the status tray icon now after the taskbar has been created.
   void ResetIcon();
 
diff --git a/chrome/browser/ui/views/status_icons/status_tray_win.cc b/chrome/browser/ui/views/status_icons/status_tray_win.cc
index 03797c0..97792f7 100644
--- a/chrome/browser/ui/views/status_icons/status_tray_win.cc
+++ b/chrome/browser/ui/views/status_icons/status_tray_win.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/ui/views/status_icons/status_tray_win.h"
 
+#include <commctrl.h>
+
 #include "base/win/wrapped_window_proc.h"
 #include "chrome/browser/ui/views/status_icons/status_icon_win.h"
 #include "chrome/common/chrome_constants.h"
@@ -68,22 +70,32 @@
     }
     return TRUE;
   } else if (message == kStatusIconMessage) {
+    StatusIconWin* win_icon = NULL;
+
+    // Find the selected status icon.
+    for (StatusIcons::const_iterator i(status_icons().begin());
+         i != status_icons().end();
+         ++i) {
+      StatusIconWin* current_win_icon = static_cast<StatusIconWin*>(*i);
+      if (current_win_icon->icon_id() == wparam) {
+        win_icon = current_win_icon;
+        break;
+      }
+    }
+
     switch (lparam) {
+      case TB_INDETERMINATE:
+        win_icon->HandleBalloonClickEvent();
+        return TRUE;
+
       case WM_LBUTTONDOWN:
       case WM_RBUTTONDOWN:
       case WM_CONTEXTMENU:
         // Walk our icons, find which one was clicked on, and invoke its
         // HandleClickEvent() method.
-        for (StatusIcons::const_iterator i(status_icons().begin());
-             i != status_icons().end(); ++i) {
-          StatusIconWin* win_icon = static_cast<StatusIconWin*>(*i);
-          if (win_icon->icon_id() == wparam) {
-            gfx::Point cursor_pos(
-                gfx::Screen::GetNativeScreen()->GetCursorScreenPoint());
-            win_icon->HandleClickEvent(cursor_pos, lparam == WM_LBUTTONDOWN);
-            break;
-          }
-        }
+        gfx::Point cursor_pos(
+            gfx::Screen::GetNativeScreen()->GetCursorScreenPoint());
+        win_icon->HandleClickEvent(cursor_pos, lparam == WM_LBUTTONDOWN);
         return TRUE;
     }
   }
diff --git a/chrome/browser/ui/views/status_icons/status_tray_win_unittest.cc b/chrome/browser/ui/views/status_icons/status_tray_win_unittest.cc
index 7ff8309..3968cdc 100644
--- a/chrome/browser/ui/views/status_icons/status_tray_win_unittest.cc
+++ b/chrome/browser/ui/views/status_icons/status_tray_win_unittest.cc
@@ -4,21 +4,34 @@
 
 #include "chrome/browser/ui/views/status_icons/status_tray_win.h"
 
+#include <commctrl.h>
+
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/status_icons/status_icon_observer.h"
 #include "chrome/browser/ui/views/status_icons/status_icon_win.h"
 #include "grit/chrome_unscaled_resources.h"
-#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/models/simple_menu_model.h"
 #include "ui/base/resource/resource_bundle.h"
 
-class SkBitmap;
-
-class MockStatusIconObserver : public StatusIconObserver {
+class FakeStatusIconObserver : public StatusIconObserver {
  public:
-  MOCK_METHOD0(OnStatusIconClicked, void());
+  FakeStatusIconObserver()
+      : balloon_clicked_(false),
+        status_icon_click_count_(0) {}
+  virtual void OnStatusIconClicked() {
+    ++status_icon_click_count_;
+  }
+  virtual void OnBalloonClicked() { balloon_clicked_ = true; }
+  bool balloon_clicked() const { return balloon_clicked_; }
+  size_t status_icon_click_count() const {
+    return status_icon_click_count_;
+  }
+
+ private:
+  size_t status_icon_click_count_;
+  bool balloon_clicked_;
 };
 
 TEST(StatusTrayWinTest, CreateTray) {
@@ -46,13 +59,26 @@
   // Create an icon, send a fake click event, make sure observer is called.
   StatusTrayWin tray;
   StatusIconWin* icon = static_cast<StatusIconWin*>(tray.CreateStatusIcon());
-  MockStatusIconObserver observer;
+  FakeStatusIconObserver observer;
   icon->AddObserver(&observer);
-  EXPECT_CALL(observer, OnStatusIconClicked());
   // Mimic a click.
   tray.WndProc(NULL, icon->message_id(), icon->icon_id(), WM_LBUTTONDOWN);
   // Mimic a right-click - observer should not be called.
   tray.WndProc(NULL, icon->message_id(), icon->icon_id(), WM_RBUTTONDOWN);
+  EXPECT_EQ(1, observer.status_icon_click_count());
+  icon->RemoveObserver(&observer);
+}
+
+TEST(StatusTrayWinTest, ClickOnBalloon) {
+  // Create an icon, send a fake click event, make sure observer is called.
+  StatusTrayWin tray;
+  StatusIconWin* icon = static_cast<StatusIconWin*>(tray.CreateStatusIcon());
+  FakeStatusIconObserver observer;
+  icon->AddObserver(&observer);
+  // Mimic a click.
+  tray.WndProc(
+      NULL, icon->message_id(), icon->icon_id(), TB_INDETERMINATE);
+  EXPECT_TRUE(observer.balloon_clicked());
   icon->RemoveObserver(&observer);
 }
 #endif  // !defined(USE_AURA)
diff --git a/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc b/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc
index fff9132..a585367 100644
--- a/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc
+++ b/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.h"
 
+#include <algorithm>
+
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_dialogs.h"
@@ -25,29 +27,12 @@
 #include "ui/gfx/native_widget_types.h"
 #include "ui/views/background.h"
 #include "ui/views/controls/label.h"
-#include "ui/views/controls/link.h"
 #include "ui/views/controls/styled_label.h"
 #include "ui/views/layout/box_layout.h"
 #include "ui/views/layout/grid_layout.h"
 #include "ui/views/layout/layout_constants.h"
 #include "ui/views/widget/widget.h"
-
-namespace {
-
-// Wrap a view in a fixed-width container.
-views::View* MakeFixedWidth(views::View* view, int width) {
-  views::View* container = new views::View;
-  views::GridLayout* layout = views::GridLayout::CreatePanel(container);
-  container->SetLayoutManager(layout);
-  layout->AddColumnSet(0)->AddColumn(
-      views::GridLayout::LEADING, views::GridLayout::CENTER, 0,
-      views::GridLayout::FIXED, width, false);
-  layout->StartRow(0, 0);
-  layout->AddView(view, 1, 1, views::GridLayout::FILL, views::GridLayout::FILL);
-  return container;
-}
-
-}  // namespace
+#include "ui/views/window/dialog_client_view.h"
 
 namespace chrome {
 // Declared in browser_dialogs.h
@@ -74,7 +59,7 @@
     username_(username),
     delegate_(delegate),
     prompt_for_new_profile_(true),
-    link_(NULL) {
+    continue_signin_button_(NULL) {
 }
 
 ProfileSigninConfirmationDialogViews::~ProfileSigninConfirmationDialogViews() {}
@@ -109,9 +94,15 @@
 
 string16 ProfileSigninConfirmationDialogViews::GetDialogButtonLabel(
     ui::DialogButton button) const {
-  return l10n_util::GetStringUTF16((button == ui::DIALOG_BUTTON_OK) ?
-      IDS_ENTERPRISE_SIGNIN_CONTINUE_NEW_STYLE :
-      IDS_ENTERPRISE_SIGNIN_CANCEL);
+  if (button == ui::DIALOG_BUTTON_OK) {
+    // If we're giving the option to create a new profile, then OK is
+    // "Create new profile".  Otherwise it is "Continue signin".
+    return l10n_util::GetStringUTF16(
+        prompt_for_new_profile_ ?
+            IDS_ENTERPRISE_SIGNIN_CREATE_NEW_PROFILE_NEW_STYLE :
+            IDS_ENTERPRISE_SIGNIN_CONTINUE_NEW_STYLE);
+  }
+  return l10n_util::GetStringUTF16(IDS_ENTERPRISE_SIGNIN_CANCEL);
 }
 
 int ProfileSigninConfirmationDialogViews::GetDefaultDialogButton() const {
@@ -120,20 +111,22 @@
 
 views::View* ProfileSigninConfirmationDialogViews::CreateExtraView() {
   if (prompt_for_new_profile_) {
-    const string16 create_profile_text =
-        l10n_util::GetStringUTF16(
-            IDS_ENTERPRISE_SIGNIN_CREATE_NEW_PROFILE_NEW_STYLE);
-    link_ = new views::Link(create_profile_text);
-    link_->SetUnderline(false);
-    link_->set_listener(this);
-    link_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+    const string16 continue_signin_text =
+        l10n_util::GetStringUTF16(IDS_ENTERPRISE_SIGNIN_CONTINUE_NEW_STYLE);
+    continue_signin_button_ =
+        new views::LabelButton(this, continue_signin_text);
+    continue_signin_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
+    continue_signin_button_->set_focusable(true);
   }
-  return link_;
+  return continue_signin_button_;
 }
 
 bool ProfileSigninConfirmationDialogViews::Accept() {
   if (delegate_) {
-    delegate_->OnContinueSignin();
+    if (prompt_for_new_profile_)
+      delegate_->OnSigninWithNewProfile();
+    else
+      delegate_->OnContinueSignin();
     delegate_ = NULL;
   }
   return true;
@@ -160,39 +153,35 @@
   if (!details.is_add || details.child != this)
     return;
 
-  // Layout the labels in a single fixed-width column.
-  SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0));
-
   // Create the prompt label.
-  std::vector<size_t> offsets;
+  size_t offset;
   const string16 domain = ASCIIToUTF16(gaia::ExtractDomainName(username_));
   const string16 username = ASCIIToUTF16(username_);
   const string16 prompt_text =
       l10n_util::GetStringFUTF16(
           IDS_ENTERPRISE_SIGNIN_ALERT_NEW_STYLE,
-          username, domain, &offsets);
+          domain, &offset);
   views::StyledLabel* prompt_label = new views::StyledLabel(prompt_text, this);
   views::StyledLabel::RangeStyleInfo bold_style;
   bold_style.font_style = gfx::Font::BOLD;
   prompt_label->AddStyleRange(
-      ui::Range(offsets[1], offsets[1] + domain.size()), bold_style);
+      ui::Range(offset, offset + domain.size()), bold_style);
 
-  // Add the prompt label with a darker background and border.
-  const int kDialogWidth = 440;
-  views::View* prompt_container = MakeFixedWidth(prompt_label, kDialogWidth);
-  prompt_container->set_border(
+  // Create the prompt bar.
+  views::View* prompt_bar = new views::View;
+  prompt_bar->set_border(
       views::Border::CreateSolidSidedBorder(
           1, 0, 1, 0,
           ui::GetSigninConfirmationPromptBarColor(
               ui::kSigninConfirmationPromptBarBorderAlpha)));
-  prompt_container->set_background(
+  // TODO(dconnelly): set the background color on the label (crbug.com/244630)
+  prompt_bar->set_background(
       views::Background::CreateSolidBackground(
           ui::GetSigninConfirmationPromptBarColor(
               ui::kSigninConfirmationPromptBarBackgroundAlpha)));
-  AddChildView(prompt_container);
 
-  // Create and add the explanation label.
-  offsets.clear();
+  // Create the explanation label.
+  std::vector<size_t> offsets;
   const string16 learn_more_text =
       l10n_util::GetStringUTF16(
           IDS_ENTERPRISE_SIGNIN_PROFILE_LINK_LEARN_MORE);
@@ -208,17 +197,42 @@
   explanation_label_->AddStyleRange(
       ui::Range(offsets[1], offsets[1] + learn_more_text.size()),
       link_style);
-  // TODO(dconnelly): set the background color on the label (crbug.com/244630)
-  AddChildView(MakeFixedWidth(explanation_label_, kDialogWidth));
-}
 
-void ProfileSigninConfirmationDialogViews::LinkClicked(views::Link* source,
-                                                       int event_flags) {
-  if (delegate_) {
-    delegate_->OnSigninWithNewProfile();
-    delegate_ = NULL;
-  }
-  GetWidget()->Close();
+  // Layout the components.
+  views::GridLayout* dialog_layout = new views::GridLayout(this);
+  SetLayoutManager(dialog_layout);
+
+  // Use GridLayout inside the prompt bar because StyledLabel requires it.
+  views::GridLayout* prompt_layout = views::GridLayout::CreatePanel(prompt_bar);
+  prompt_bar->SetLayoutManager(prompt_layout);
+  prompt_layout->AddColumnSet(0)->AddColumn(
+      views::GridLayout::FILL, views::GridLayout::CENTER, 100,
+      views::GridLayout::USE_PREF, 0, 0);
+  prompt_layout->StartRow(0, 0);
+  prompt_layout->AddView(prompt_label);
+  // Use a column set with no padding.
+  dialog_layout->AddColumnSet(0)->AddColumn(
+      views::GridLayout::FILL, views::GridLayout::FILL, 100,
+      views::GridLayout::USE_PREF, 0, 0);
+  dialog_layout->StartRow(0, 0);
+  dialog_layout->AddView(
+      prompt_bar, 1, 1,
+      views::GridLayout::FILL, views::GridLayout::FILL, 0, 0);
+
+  // Use a new column set for the explanation label so we can add padding.
+  dialog_layout->AddPaddingRow(0.0, views::kPanelVertMargin);
+  views::ColumnSet* explanation_columns = dialog_layout->AddColumnSet(1);
+  explanation_columns->AddPaddingColumn(0.0, views::kButtonHEdgeMarginNew);
+  explanation_columns->AddColumn(
+      views::GridLayout::FILL, views::GridLayout::FILL, 100,
+      views::GridLayout::USE_PREF, 0, 0);
+  explanation_columns->AddPaddingColumn(0.0, views::kButtonHEdgeMarginNew);
+  dialog_layout->StartRow(0, 1);
+  const int kPreferredWidth = 440;
+  dialog_layout->AddView(
+      explanation_label_, 1, 1,
+      views::GridLayout::FILL, views::GridLayout::FILL,
+      kPreferredWidth, explanation_label_->GetHeightForWidth(kPreferredWidth));
 }
 
 void ProfileSigninConfirmationDialogViews::StyledLabelLinkClicked(
@@ -232,3 +246,15 @@
   params.window_action = chrome::NavigateParams::SHOW_WINDOW;
   chrome::Navigate(&params);
 }
+
+void ProfileSigninConfirmationDialogViews::ButtonPressed(
+    views::Button* sender,
+    const ui::Event& event) {
+  DCHECK(prompt_for_new_profile_);
+  DCHECK_EQ(continue_signin_button_, sender);
+  if (delegate_) {
+    delegate_->OnContinueSignin();
+    delegate_ = NULL;
+  }
+  GetWidget()->Close();
+}
diff --git a/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.h b/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.h
index 69193c0..3499cf1 100644
--- a/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.h
+++ b/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.h
@@ -7,6 +7,8 @@
 
 #include "base/compiler_specific.h"
 #include "chrome/browser/ui/sync/profile_signin_confirmation_helper.h"
+#include "ui/views/controls/button/button.h"
+#include "ui/views/controls/button/label_button.h"
 #include "ui/views/controls/link_listener.h"
 #include "ui/views/controls/styled_label_listener.h"
 #include "ui/views/window/dialog_delegate.h"
@@ -25,8 +27,8 @@
 // A tab-modal dialog to allow a user signing in with a managed account
 // to create a new Chrome profile.
 class ProfileSigninConfirmationDialogViews : public views::DialogDelegateView,
-                                             public views::LinkListener,
-                                             public views::StyledLabelListener {
+                                             public views::StyledLabelListener,
+                                             public views::ButtonListener {
  public:
   // Create and show the dialog, which owns itself.
   static void ShowDialog(Browser* browser,
@@ -54,13 +56,13 @@
   virtual void ViewHierarchyChanged(
       const ViewHierarchyChangedDetails& details) OVERRIDE;
 
-  // views::LinkListener:
-  virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE;
-
   // views::StyledLabelListener:
   virtual void StyledLabelLinkClicked(const ui::Range& range,
                                       int event_flags) OVERRIDE;
 
+  // views::ButtonListener:
+  virtual void ButtonPressed(views::Button*, const ui::Event& event) OVERRIDE;
+
   // Shows the dialog and releases ownership of this object. It will
   // delete itself when the dialog is closed. If |prompt_for_new_profile|
   // is true, the dialog will offer to create a new profile before signin.
@@ -84,8 +86,8 @@
   // Whether the user should be prompted to create a new profile.
   bool prompt_for_new_profile_;
 
-  // The link to create a new profile.
-  views::Link* link_;
+  // The button to continue with signin, if an extra button is required.
+  views::LabelButton* continue_signin_button_;
 
   DISALLOW_COPY_AND_ASSIGN(ProfileSigninConfirmationDialogViews);
 };
diff --git a/chrome/browser/ui/views/tab_contents/render_view_context_menu_views.cc b/chrome/browser/ui/views/tab_contents/render_view_context_menu_views.cc
index 70d6c7b..3349064 100644
--- a/chrome/browser/ui/views/tab_contents/render_view_context_menu_views.cc
+++ b/chrome/browser/ui/views/tab_contents/render_view_context_menu_views.cc
@@ -40,33 +40,16 @@
 }
 #endif  // OS_WIN
 
-void RenderViewContextMenuViews::RunMenuAt(
-    views::Widget* parent,
-    const gfx::Point& point,
-    content::ContextMenuSourceType type) {
+void RenderViewContextMenuViews::RunMenuAt(views::Widget* parent,
+                                           const gfx::Point& point,
+                                           ui::MenuSourceType type) {
   views::MenuItemView::AnchorPosition anchor_position =
-      (type == content::CONTEXT_MENU_SOURCE_TOUCH ||
-          type == content::CONTEXT_MENU_SOURCE_TOUCH_EDIT_MENU) ?
+      (type == ui::MENU_SOURCE_TOUCH ||
+          type == ui::MENU_SOURCE_TOUCH_EDIT_MENU) ?
           views::MenuItemView::BOTTOMCENTER : views::MenuItemView::TOPLEFT;
 
-  // TODO(varunjain): remove this by consolidating ui::MenuSourceType and
-  // content::ContextMenuSourceType.
-  ui::MenuSourceType source_type = ui::MENU_SOURCE_NONE;
-  switch (type) {
-    case content::CONTEXT_MENU_SOURCE_MOUSE:
-      source_type = ui::MENU_SOURCE_MOUSE;
-      break;
-    case content::CONTEXT_MENU_SOURCE_KEYBOARD:
-      source_type = ui::MENU_SOURCE_KEYBOARD;
-      break;
-    case content::CONTEXT_MENU_SOURCE_TOUCH:
-      source_type = ui::MENU_SOURCE_TOUCH;
-      break;
-    default:
-      break;
-  }
   if (menu_runner_->RunMenuAt(parent, NULL, gfx::Rect(point, gfx::Size()),
-      anchor_position, source_type, views::MenuRunner::HAS_MNEMONICS |
+      anchor_position, type, views::MenuRunner::HAS_MNEMONICS |
           views::MenuRunner::CONTEXT_MENU) ==
       views::MenuRunner::MENU_DELETED)
     return;
diff --git a/chrome/browser/ui/views/tab_contents/render_view_context_menu_views.h b/chrome/browser/ui/views/tab_contents/render_view_context_menu_views.h
index 05b81e8..0b58ee1 100644
--- a/chrome/browser/ui/views/tab_contents/render_view_context_menu_views.h
+++ b/chrome/browser/ui/views/tab_contents/render_view_context_menu_views.h
@@ -9,7 +9,7 @@
 #include "base/memory/scoped_vector.h"
 #include "base/strings/string16.h"
 #include "chrome/browser/tab_contents/render_view_context_menu.h"
-#include "content/public/common/context_menu_source_type.h"
+#include "ui/base/ui_base_types.h"
 
 namespace gfx {
 class Point;
@@ -31,7 +31,7 @@
 
   void RunMenuAt(views::Widget* parent,
                  const gfx::Point& point,
-                 content::ContextMenuSourceType type);
+                 ui::MenuSourceType type);
 
   // RenderViewContextMenuDelegate implementation.
   virtual void UpdateMenuItem(int command_id,
diff --git a/chrome/browser/ui/views/tab_contents/web_drag_bookmark_handler_win.cc b/chrome/browser/ui/views/tab_contents/web_drag_bookmark_handler_win.cc
index d63d1b5..474235b 100644
--- a/chrome/browser/ui/views/tab_contents/web_drag_bookmark_handler_win.cc
+++ b/chrome/browser/ui/views/tab_contents/web_drag_bookmark_handler_win.cc
@@ -12,9 +12,9 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/url_constants.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/common/drop_data.h"
 #include "ui/base/dragdrop/os_exchange_data.h"
 #include "ui/base/dragdrop/os_exchange_data_provider_win.h"
-#include "webkit/common/webdropdata.h"
 
 using content::WebContents;
 
@@ -92,7 +92,7 @@
   }
 }
 
-bool WebDragBookmarkHandlerWin::AddDragData(const WebDropData& drop_data,
+bool WebDragBookmarkHandlerWin::AddDragData(const content::DropData& drop_data,
                                             ui::OSExchangeData* data) {
   if (!drop_data.url.SchemeIs(chrome::kJavaScriptScheme))
     return false;
diff --git a/chrome/browser/ui/views/tab_contents/web_drag_bookmark_handler_win.h b/chrome/browser/ui/views/tab_contents/web_drag_bookmark_handler_win.h
index 06460fd..404044a 100644
--- a/chrome/browser/ui/views/tab_contents/web_drag_bookmark_handler_win.h
+++ b/chrome/browser/ui/views/tab_contents/web_drag_bookmark_handler_win.h
@@ -28,7 +28,7 @@
   virtual void OnDragEnter(IDataObject* data_object) OVERRIDE;
   virtual void OnDrop(IDataObject* data_object) OVERRIDE;
   virtual void OnDragLeave(IDataObject* data_object) OVERRIDE;
-  virtual bool AddDragData(const WebDropData& drop_data,
+  virtual bool AddDragData(const content::DropData& drop_data,
                            ui::OSExchangeData* data) OVERRIDE;
 
  private:
diff --git a/chrome/browser/ui/views/tabs/dragged_tab_view.cc b/chrome/browser/ui/views/tabs/dragged_tab_view.cc
index d95d9da..9c5e19f 100644
--- a/chrome/browser/ui/views/tabs/dragged_tab_view.cc
+++ b/chrome/browser/ui/views/tabs/dragged_tab_view.cc
@@ -42,7 +42,7 @@
 
   container_.reset(new views::Widget);
   views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
-  params.transparent = true;
+  params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
   params.keep_on_top = true;
   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
   params.bounds = gfx::Rect(PreferredContainerSize());
diff --git a/chrome/browser/ui/views/tabs/native_view_photobooth_win.cc b/chrome/browser/ui/views/tabs/native_view_photobooth_win.cc
index c9f8f77..132b895 100644
--- a/chrome/browser/ui/views/tabs/native_view_photobooth_win.cc
+++ b/chrome/browser/ui/views/tabs/native_view_photobooth_win.cc
@@ -36,7 +36,7 @@
   return gfx::Point(point.x() - 1, point.y() - 1);
 }
 
-}
+}  // namespace
 
 ///////////////////////////////////////////////////////////////////////////////
 // NativeViewPhotoboothWin, public:
@@ -152,7 +152,7 @@
                            contents_rect.bottom - contents_rect.top);
   capture_window_ = new views::Widget;
   views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
-  params.transparent = true;
+  params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
   params.bounds = capture_bounds;
   capture_window_->Init(params);
   // If the capture window isn't visible, blitting from the WebContents's
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc
index acfb5c5..3100357 100644
--- a/chrome/browser/ui/views/tabs/tab.cc
+++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -17,6 +17,7 @@
 #include "chrome/browser/ui/view_ids.h"
 #include "chrome/browser/ui/views/tabs/tab_controller.h"
 #include "chrome/browser/ui/views/theme_image_mapper.h"
+#include "chrome/browser/ui/views/touch_uma/touch_uma.h"
 #include "chrome/common/chrome_switches.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
@@ -457,6 +458,7 @@
       immersive_loading_step_(0),
       should_display_crashed_favicon_(false),
       theme_provider_(NULL),
+      tab_activated_with_last_gesture_begin_(false),
       hover_controller_(this),
       showing_icon_(false),
       showing_close_button_(false),
@@ -711,6 +713,8 @@
       CLOSE_TAB_FROM_TOUCH;
   DCHECK_EQ(close_button_, sender);
   controller()->CloseTab(this, source);
+  if (event.type() == ui::ET_GESTURE_TAP)
+    TouchUMA::RecordGestureAction(TouchUMA::GESTURE_TABCLOSE_TAP);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -1028,6 +1032,7 @@
                                        parent());
       ui::ListSelectionModel original_selection;
       original_selection.Copy(controller()->GetSelectionModel());
+      tab_activated_with_last_gesture_begin_ = !IsActive();
       if (!IsSelected())
         controller()->SelectTab(this);
       gfx::Point loc(event->location());
diff --git a/chrome/browser/ui/views/tabs/tab.h b/chrome/browser/ui/views/tabs/tab.h
index 91ddca8..534091f 100644
--- a/chrome/browser/ui/views/tabs/tab.h
+++ b/chrome/browser/ui/views/tabs/tab.h
@@ -100,6 +100,14 @@
     background_offset_ = offset;
   }
 
+  // Returns true if this tab became the active tab selected in
+  // response to the last ui::ET_GESTURE_BEGIN gesture dispatched to
+  // this tab. Only used for collecting UMA metrics.
+  // See ash/touch/touch_uma.cc.
+  bool tab_activated_with_last_gesture_begin() const {
+    return tab_activated_with_last_gesture_begin_;
+  }
+
   views::GlowHoverController* hover_controller() {
     return &hover_controller_;
   }
@@ -320,6 +328,8 @@
 
   ui::ThemeProvider* theme_provider_;
 
+  bool tab_activated_with_last_gesture_begin_;
+
   views::GlowHoverController hover_controller_;
 
   // The bounds of various sections of the display.
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller.cc b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
index f36b867..3b432ce 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller.cc
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
@@ -254,7 +254,7 @@
         in_enable_area_(info.in_enable_area()) {
     popup_ = new views::Widget;
     views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
-    params.transparent = true;
+    params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
     params.keep_on_top = true;
     params.bounds = info.GetPopupRect();
     popup_->Init(params);
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller.h b/chrome/browser/ui/views/tabs/tab_drag_controller.h
index 7b6fbbc..7323976 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller.h
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller.h
@@ -9,7 +9,7 @@
 
 #include "base/memory/scoped_ptr.h"
 #include "base/message_loop.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/ui/tabs/dock_info.h"
 #include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
 #include "chrome/browser/ui/views/tabs/tab_strip_types.h"
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
index da53034..f1e896a 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
@@ -1323,7 +1323,7 @@
       second_root).work_area();
   work_area.Inset(20,20,20,60);
   Browser::CreateParams params(browser()->profile(),
-                               chrome::HOST_DESKTOP_TYPE_NATIVE);
+                               browser()->host_desktop_type());
   params.initial_show_state = ui::SHOW_STATE_NORMAL;
   params.initial_bounds = work_area;
   Browser* browser2 = new Browser(params);
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc
index 68fede9..e0356c8 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.cc
+++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -25,6 +25,7 @@
 #include "chrome/browser/ui/views/tabs/tab_drag_controller.h"
 #include "chrome/browser/ui/views/tabs/tab_strip_controller.h"
 #include "chrome/browser/ui/views/tabs/tab_strip_observer.h"
+#include "chrome/browser/ui/views/touch_uma/touch_uma.h"
 #include "content/public/browser/user_metrics.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
@@ -1495,6 +1496,8 @@
     UMA_HISTOGRAM_ENUMERATION("Tab.NewTab", TabStripModel::NEW_TAB_BUTTON,
                               TabStripModel::NEW_TAB_ENUM_COUNT);
     controller()->CreateNewTab();
+    if (event.type() == ui::ET_GESTURE_TAP)
+      TouchUMA::RecordGestureAction(TouchUMA::GESTURE_NEWTAB_TAP);
   }
 }
 
@@ -1583,6 +1586,17 @@
       EndDrag(END_DRAG_CANCEL);
       break;
 
+    case ui::ET_GESTURE_TAP: {
+      const int active_index = controller_->GetActiveIndex();
+      DCHECK_NE(-1, active_index);
+      Tab* active_tab = tab_at(active_index);
+      TouchUMA::GestureActionType action = TouchUMA::GESTURE_TABNOSWITCH_TAP;
+      if (active_tab->tab_activated_with_last_gesture_begin())
+        action = TouchUMA::GESTURE_TABSWITCH_TAP;
+      TouchUMA::RecordGestureAction(action);
+      break;
+    }
+
     default:
       break;
   }
@@ -2401,7 +2415,7 @@
   arrow_window = new views::Widget;
   views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
   params.keep_on_top = true;
-  params.transparent = true;
+  params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
   params.accept_events = false;
   params.can_activate = false;
   params.bounds = gfx::Rect(drop_indicator_width, drop_indicator_height);
diff --git a/chrome/browser/ui/views/tabs/tab_strip.h b/chrome/browser/ui/views/tabs/tab_strip.h
index 8f44c6f..a78cff7 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.h
+++ b/chrome/browser/ui/views/tabs/tab_strip.h
@@ -9,7 +9,7 @@
 
 #include "base/compiler_specific.h"
 #include "base/memory/ref_counted.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/ui/tabs/tab_strip_layout_type.h"
 #include "chrome/browser/ui/views/tabs/tab.h"
 #include "chrome/browser/ui/views/tabs/tab_controller.h"
diff --git a/chrome/browser/ui/views/task_manager_view.cc b/chrome/browser/ui/views/task_manager_view.cc
index 183a2b4..65195cd 100644
--- a/chrome/browser/ui/views/task_manager_view.cc
+++ b/chrome/browser/ui/views/task_manager_view.cc
@@ -29,7 +29,6 @@
 #include "ui/base/models/table_model.h"
 #include "ui/base/models/table_model_observer.h"
 #include "ui/gfx/canvas.h"
-#include "ui/views/background.h"
 #include "ui/views/context_menu_controller.h"
 #include "ui/views/controls/button/label_button.h"
 #include "ui/views/controls/link.h"
@@ -38,7 +37,6 @@
 #include "ui/views/controls/table/table_grouper.h"
 #include "ui/views/controls/table/table_view.h"
 #include "ui/views/controls/table/table_view_observer.h"
-#include "ui/views/controls/table/table_view_row_background_painter.h"
 #include "ui/views/layout/layout_constants.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/window/dialog_delegate.h"
@@ -51,10 +49,6 @@
 #include "win8/util/win8_util.h"
 #endif
 
-// Yellow highlight used when highlighting background resources.
-static const SkColor kBackgroundResourceHighlight =
-    SkColorSetRGB(0xff, 0xf1, 0xcd);
-
 namespace {
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -93,9 +87,6 @@
   virtual void OnItemsAdded(int start, int length) OVERRIDE;
   virtual void OnItemsRemoved(int start, int length) OVERRIDE;
 
-  // Returns true if resource corresponding to |row| is a background resource.
-  bool IsBackgroundResource(int row);
-
  private:
   TaskManagerModel* model_;
   ui::TableModelObserver* observer_;
@@ -170,28 +161,6 @@
   OnModelChanged();
 }
 
-bool TaskManagerTableModel::IsBackgroundResource(int row) {
-  return model_->IsBackgroundResource(row);
-}
-
-class BackgroundPainter : public views::TableViewRowBackgroundPainter {
- public:
-  explicit BackgroundPainter(TaskManagerTableModel* model) : model_(model) {}
-  virtual ~BackgroundPainter() {}
-
-  virtual void PaintRowBackground(int model_index,
-                                  const gfx::Rect& row_bounds,
-                                  gfx::Canvas* canvas) OVERRIDE {
-    if (model_->IsBackgroundResource(model_index))
-      canvas->FillRect(row_bounds, kBackgroundResourceHighlight);
-  }
-
- private:
-  TaskManagerTableModel* model_;
-
-  DISALLOW_COPY_AND_ASSIGN(BackgroundPainter);
-};
-
 // The Task manager UI container.
 class TaskManagerView : public views::ButtonListener,
                         public views::DialogDelegateView,
@@ -200,14 +169,11 @@
                         public views::ContextMenuController,
                         public ui::SimpleMenuModel::Delegate {
  public:
-  TaskManagerView(bool highlight_background_resources,
-                  chrome::HostDesktopType desktop_type);
+  explicit TaskManagerView(chrome::HostDesktopType desktop_type);
   virtual ~TaskManagerView();
 
-  // Shows the Task manager window, or re-activates an existing one. If
-  // |highlight_background_resources| is true, highlights the background
-  // resources in the resource display.
-  static void Show(bool highlight_background_resources, Browser* browser);
+  // Shows the Task manager window, or re-activates an existing one.
+  static void Show(Browser* browser);
 
   // views::View:
   virtual void Layout() OVERRIDE;
@@ -288,9 +254,6 @@
   // True when the Task Manager window should be shown on top of other windows.
   bool is_always_on_top_;
 
-  // True when the Task Manager should highlight background resources.
-  const bool highlight_background_resources_;
-
   // The host desktop type this task manager belongs to.
   const chrome::HostDesktopType desktop_type_;
 
@@ -310,8 +273,7 @@
 TaskManagerView* TaskManagerView::instance_ = NULL;
 
 
-TaskManagerView::TaskManagerView(bool highlight_background_resources,
-                                 chrome::HostDesktopType desktop_type)
+TaskManagerView::TaskManagerView(chrome::HostDesktopType desktop_type)
     : purge_memory_button_(NULL),
       kill_button_(NULL),
       about_memory_link_(NULL),
@@ -320,7 +282,6 @@
       task_manager_(TaskManager::GetInstance()),
       model_(TaskManager::GetInstance()->model()),
       is_always_on_top_(false),
-      highlight_background_resources_(highlight_background_resources),
       desktop_type_(desktop_type) {
   Init();
 }
@@ -394,12 +355,6 @@
   tab_table_ = new views::TableView(
       table_model_.get(), columns_, views::ICON_AND_TEXT, false);
   tab_table_->SetGrouper(table_model_.get());
-  if (highlight_background_resources_) {
-    scoped_ptr<BackgroundPainter> painter(
-        new BackgroundPainter(table_model_.get()));
-    tab_table_->SetRowBackgroundPainter(
-        painter.PassAs<views::TableViewRowBackgroundPainter>());
-  }
 
   // Hide some columns by default
   tab_table_->SetColumnVisibility(IDS_TASK_MANAGER_PROFILE_NAME_COLUMN, false);
@@ -529,8 +484,7 @@
 }
 
 // static
-void TaskManagerView::Show(bool highlight_background_resources,
-                           Browser* browser) {
+void TaskManagerView::Show(Browser* browser) {
 #if defined(OS_WIN)
   // In Windows Metro it's not good to open this native window.
   DCHECK(!win8::IsSingleWindowMetroMode());
@@ -541,17 +495,11 @@
       browser ? browser->host_desktop_type() : chrome::HOST_DESKTOP_TYPE_ASH;
 
   if (instance_) {
-    if (instance_->highlight_background_resources_ !=
-        highlight_background_resources ||
-        instance_->desktop_type_ != desktop_type) {
-      instance_->GetWidget()->Close();
-    } else {
-      // If there's a Task manager window open already, just activate it.
-      instance_->GetWidget()->Activate();
-      return;
-    }
+    // If there's a Task manager window open already, just activate it.
+    instance_->GetWidget()->Activate();
+    return;
   }
-  instance_ = new TaskManagerView(highlight_background_resources, desktop_type);
+  instance_ = new TaskManagerView(desktop_type);
   gfx::NativeWindow window =
       browser ? browser->window()->GetNativeWindow() : NULL;
 #if defined(USE_ASH)
@@ -779,8 +727,8 @@
 namespace chrome {
 
 // Declared in browser_dialogs.h so others don't need to depend on our header.
-void ShowTaskManager(Browser* browser, bool highlight_background_resources) {
-  TaskManagerView::Show(highlight_background_resources, browser);
+void ShowTaskManager(Browser* browser) {
+  TaskManagerView::Show(browser);
 }
 
 }  // namespace chrome
diff --git a/chrome/browser/ui/views/touch_uma/touch_uma.cc b/chrome/browser/ui/views/touch_uma/touch_uma.cc
new file mode 100644
index 0000000..d6dc3f8
--- /dev/null
+++ b/chrome/browser/ui/views/touch_uma/touch_uma.cc
@@ -0,0 +1,9 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/touch_uma/touch_uma.h"
+
+// static
+void TouchUMA::RecordGestureAction(GestureActionType action) {
+}
diff --git a/chrome/browser/ui/views/touch_uma/touch_uma.h b/chrome/browser/ui/views/touch_uma/touch_uma.h
new file mode 100644
index 0000000..34e950b
--- /dev/null
+++ b/chrome/browser/ui/views/touch_uma/touch_uma.h
@@ -0,0 +1,26 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_TOUCH_UMA_TOUCH_UMA_H_
+#define CHROME_BROWSER_UI_VIEWS_TOUCH_UMA_TOUCH_UMA_H_
+
+#include "base/basictypes.h"
+
+class TouchUMA {
+ public:
+  enum GestureActionType {
+    GESTURE_TABSWITCH_TAP,
+    GESTURE_TABNOSWITCH_TAP,
+    GESTURE_TABCLOSE_TAP,
+    GESTURE_NEWTAB_TAP,
+    GESTURE_ROOTVIEWTOP_TAP,
+  };
+
+  static void RecordGestureAction(GestureActionType action);
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(TouchUMA);
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_TOUCH_UMA_TOUCH_UMA_H_
diff --git a/chrome/browser/ui/views/touch_uma/touch_uma_ash.cc b/chrome/browser/ui/views/touch_uma/touch_uma_ash.cc
new file mode 100644
index 0000000..14fc5d3
--- /dev/null
+++ b/chrome/browser/ui/views/touch_uma/touch_uma_ash.cc
@@ -0,0 +1,30 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/touch_uma/touch_uma.h"
+
+#include "ash/touch/touch_uma.h"
+
+// static
+void TouchUMA::RecordGestureAction(GestureActionType action) {
+  ash::TouchUMA::GestureActionType type = ash::TouchUMA::GESTURE_UNKNOWN;
+  switch (action) {
+    case GESTURE_TABSWITCH_TAP:
+      type = ash::TouchUMA::GESTURE_TABSWITCH_TAP;
+      break;
+    case GESTURE_TABNOSWITCH_TAP:
+      type = ash::TouchUMA::GESTURE_TABNOSWITCH_TAP;
+      break;
+    case GESTURE_TABCLOSE_TAP:
+      type = ash::TouchUMA::GESTURE_TABCLOSE_TAP;
+      break;
+    case GESTURE_NEWTAB_TAP:
+      type = ash::TouchUMA::GESTURE_NEWTAB_TAP;
+      break;
+    case GESTURE_ROOTVIEWTOP_TAP:
+      type = ash::TouchUMA::GESTURE_ROOTVIEWTOP_TAP;
+      break;
+  }
+  ash::TouchUMA::GetInstance()->RecordGestureAction(type);
+}
diff --git a/chrome/browser/ui/views/website_settings/website_settings_popup_view.cc b/chrome/browser/ui/views/website_settings/website_settings_popup_view.cc
index c17ed02..b2cc59f 100644
--- a/chrome/browser/ui/views/website_settings/website_settings_popup_view.cc
+++ b/chrome/browser/ui/views/website_settings/website_settings_popup_view.cc
@@ -310,7 +310,7 @@
   layout->AddView(header_);
 
   layout->AddPaddingRow(1, kHeaderMarginBottom);
-  tabbed_pane_ = new views::TabbedPane();
+  tabbed_pane_ = new views::TabbedPane(false);
   layout->StartRow(1, content_column);
   layout->AddView(tabbed_pane_);
   // Tabs must be added after the tabbed_pane_ was added to the views
diff --git a/chrome/browser/ui/web_applications/web_app_ui.cc b/chrome/browser/ui/web_applications/web_app_ui.cc
index edd4570..b83cbd5 100644
--- a/chrome/browser/ui/web_applications/web_app_ui.cc
+++ b/chrome/browser/ui/web_applications/web_app_ui.cc
@@ -43,6 +43,7 @@
 #if defined(OS_WIN)
 #include "base/win/shortcut.h"
 #include "base/win/windows_version.h"
+#include "chrome/browser/web_applications/web_app_win.h"
 #include "ui/gfx/icon_util.h"
 #endif
 
@@ -184,11 +185,13 @@
     return;
   }
 
+  int preferred_size = std::max(unprocessed_icons_.back().width,
+                                unprocessed_icons_.back().height);
   web_contents_->DownloadImage(
       unprocessed_icons_.back().url,
       true,  // favicon
-      std::max(unprocessed_icons_.back().width,
-               unprocessed_icons_.back().height),
+      preferred_size,
+      0,  // no maximum size
       base::Bind(&UpdateShortcutWorker::DidDownloadFavicon,
                  base::Unretained(this)));
   unprocessed_icons_.pop_back();
diff --git a/chrome/browser/ui/website_settings/website_settings.h b/chrome/browser/ui/website_settings/website_settings.h
index bb423dd..89712b4 100644
--- a/chrome/browser/ui/website_settings/website_settings.h
+++ b/chrome/browser/ui/website_settings/website_settings.h
@@ -7,7 +7,7 @@
 
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/string16.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/common/cancelable_request.h"
 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
 #include "chrome/browser/history/history_service.h"
diff --git a/chrome/browser/ui/webui/app_launcher_page_ui.cc b/chrome/browser/ui/webui/app_launcher_page_ui.cc
index f8cc98e..1a2b32e 100644
--- a/chrome/browser/ui/webui/app_launcher_page_ui.cc
+++ b/chrome/browser/ui/webui/app_launcher_page_ui.cc
@@ -4,7 +4,9 @@
 
 #include "chrome/browser/ui/webui/app_launcher_page_ui.h"
 
+#include "apps/app_launcher.h"
 #include "base/memory/ref_counted_memory.h"
+#include "base/metrics/histogram.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/webui/ntp/app_launcher_handler.h"
 #include "chrome/browser/ui/webui/ntp/app_resource_cache_factory.h"
@@ -109,6 +111,16 @@
   scoped_refptr<base::RefCountedMemory> html_bytes(
       resource->GetNewTabHTML(is_incognito));
 
+  if (!is_incognito) {
+    if (apps::IsAppLauncherEnabled()) {
+      AppLauncherHandler::RecordAppLauncherPromoHistogram(
+          apps::APP_LAUNCHER_PROMO_ALREADY_INSTALLED);
+    } else if (apps::ShouldShowAppLauncherPromo()){
+      AppLauncherHandler::RecordAppLauncherPromoHistogram(
+          apps::APP_LAUNCHER_PROMO_SHOWN);
+    }
+  }
+
   callback.Run(html_bytes.get());
 }
 
diff --git a/chrome/browser/ui/webui/bidi_checker_web_ui_test.cc b/chrome/browser/ui/webui/bidi_checker_web_ui_test.cc
index 09d7e16..18b2888 100644
--- a/chrome/browser/ui/webui/bidi_checker_web_ui_test.cc
+++ b/chrome/browser/ui/webui/bidi_checker_web_ui_test.cc
@@ -12,7 +12,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/threading/platform_thread.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/autofill/personal_data_manager_factory.h"
 #include "chrome/browser/history/history_service.h"
@@ -22,9 +22,9 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/base/ui_test_utils.h"
-#include "components/autofill/browser/autofill_common_test.h"
-#include "components/autofill/browser/autofill_profile.h"
-#include "components/autofill/browser/personal_data_manager.h"
+#include "components/autofill/core/browser/autofill_common_test.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/personal_data_manager.h"
 #include "content/public/browser/browser_thread.h"
 #include "ui/base/resource/resource_bundle.h"
 
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
index 68d4fcc..4bcecf7 100644
--- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
+++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -72,6 +72,10 @@
 #include "chrome/browser/ui/webui/policy_ui.h"
 #endif
 
+#if defined(ENABLE_WEBRTC)
+#include "chrome/browser/ui/webui/media/webrtc_logs_ui.h"
+#endif
+
 #if defined(OS_ANDROID)
 #include "chrome/browser/ui/webui/welcome_ui_android.h"
 #else
@@ -96,6 +100,7 @@
 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
 #include "chrome/browser/ui/webui/chromeos/mobile_setup_ui.h"
 #include "chrome/browser/ui/webui/chromeos/proxy_settings_ui.h"
+#include "chrome/browser/ui/webui/chromeos/salsa_ui.h"
 #include "chrome/browser/ui/webui/chromeos/sim_unlock_ui.h"
 #include "chrome/browser/ui/webui/chromeos/system_info_ui.h"
 #endif
@@ -107,7 +112,7 @@
 #endif
 
 #if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
-#include "chrome/browser/ui/webui/sync_promo/sync_promo_ui.h"
+#include "chrome/browser/ui/sync/sync_promo_ui.h"
 #endif
 
 #if defined(OS_WIN)
@@ -250,6 +255,10 @@
     return &NewWebUI<UserActionsUI>;
   if (url.host() == chrome::kChromeUIVersionHost)
     return &NewWebUI<VersionUI>;
+#if defined(ENABLE_WEBRTC)
+  if (url.host() == chrome::kChromeUIWebRtcLogsHost)
+    return &NewWebUI<WebRtcLogsUI>;
+#endif
 
   /****************************************************************************
    * OS Specific #defines
@@ -341,6 +350,8 @@
     return &NewWebUI<chromeos::OobeUI>;
   if (url.host() == chrome::kChromeUIProxySettingsHost)
     return &NewWebUI<chromeos::ProxySettingsUI>;
+  if (url.host() == chrome::kChromeUISalsaHost)
+    return &NewWebUI<SalsaUI>;
   if (url.host() == chrome::kChromeUISimUnlockHost)
     return &NewWebUI<chromeos::SimUnlockUI>;
   if (url.host() == chrome::kChromeUISystemInfoHost)
diff --git a/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc b/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc
index 0ef48ea..498ecf7 100644
--- a/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc
@@ -22,14 +22,14 @@
 #include "chrome/browser/chromeos/drive/file_system_util.h"
 #include "chrome/browser/chromeos/drive/job_list.h"
 #include "chrome/browser/chromeos/drive/logging.h"
+#include "chrome/browser/drive/drive_api_util.h"
 #include "chrome/browser/drive/drive_notification_manager.h"
 #include "chrome/browser/drive/drive_notification_manager_factory.h"
 #include "chrome/browser/drive/drive_service_interface.h"
+#include "chrome/browser/drive/drive_switches.h"
+#include "chrome/browser/drive/event_logger.h"
 #include "chrome/browser/google_apis/auth_service.h"
 #include "chrome/browser/google_apis/drive_api_parser.h"
-#include "chrome/browser/google_apis/drive_api_util.h"
-#include "chrome/browser/google_apis/drive_switches.h"
-#include "chrome/browser/google_apis/event_logger.h"
 #include "chrome/browser/google_apis/gdata_errorcode.h"
 #include "chrome/browser/google_apis/gdata_wapi_parser.h"
 #include "chrome/browser/google_apis/time_util.h"
@@ -209,11 +209,11 @@
   void UpdateDriveRelatedFlagsSection();
   void UpdateDriveRelatedPreferencesSection();
   void UpdateAuthStatusSection(
-      google_apis::DriveServiceInterface* drive_service);
+      drive::DriveServiceInterface* drive_service);
   void UpdateAboutResourceSection(
-      google_apis::DriveServiceInterface* drive_service);
+      drive::DriveServiceInterface* drive_service);
   void UpdateAppListSection(
-      google_apis::DriveServiceInterface* drive_service);
+      drive::DriveServiceInterface* drive_service);
   void UpdateLocalMetadataSection(
       drive::DebugInfoCollector* debug_info_collector);
   void UpdateDeltaUpdateStatusSection(
@@ -238,7 +238,6 @@
   // Called when ReadDirectoryByPath() is complete.
   void OnReadDirectoryByPath(const base::FilePath& parent_path,
                              drive::FileError error,
-                             bool hide_hosted_documents,
                              scoped_ptr<drive::ResourceEntryVector> entries);
 
   // Called as the iterator for DebugInfoCollector::IterateFileCache().
@@ -375,7 +374,7 @@
   if (!integration_service)
     return;
 
-  google_apis::DriveServiceInterface* drive_service =
+  drive::DriveServiceInterface* drive_service =
       integration_service->drive_service();
   DCHECK(drive_service);
   drive::DebugInfoCollector* debug_info_collector =
@@ -406,7 +405,7 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   const char* kDriveRelatedFlags[] = {
-    google_apis::switches::kEnableDriveV2Api,
+    drive::switches::kEnableDriveV2Api,
     chromeos::switches::kDisableDrive,
   };
 
@@ -454,7 +453,7 @@
 }
 
 void DriveInternalsWebUIHandler::UpdateAuthStatusSection(
-    google_apis::DriveServiceInterface* drive_service) {
+    drive::DriveServiceInterface* drive_service) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(drive_service);
 
@@ -467,7 +466,7 @@
 }
 
 void DriveInternalsWebUIHandler::UpdateAboutResourceSection(
-    google_apis::DriveServiceInterface* drive_service) {
+    drive::DriveServiceInterface* drive_service) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(drive_service);
 
@@ -477,7 +476,7 @@
 }
 
 void DriveInternalsWebUIHandler::UpdateAppListSection(
-    google_apis::DriveServiceInterface* drive_service) {
+    drive::DriveServiceInterface* drive_service) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(drive_service);
 
@@ -550,8 +549,8 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   Profile* profile = Profile::FromWebUI(web_ui());
-  google_apis::DriveNotificationManager* drive_notification_manager =
-      google_apis::DriveNotificationManagerFactory::GetForProfile(profile);
+  drive::DriveNotificationManager* drive_notification_manager =
+      drive::DriveNotificationManagerFactory::GetForProfile(profile);
   if (!drive_notification_manager)
     return;
 
@@ -674,7 +673,7 @@
 void DriveInternalsWebUIHandler::UpdateEventLogSection() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-  const std::vector<google_apis::EventLogger::Event> log =
+  const std::vector<drive::EventLogger::Event> log =
       drive::util::GetLogHistory();
 
   base::ListValue list;
@@ -722,7 +721,6 @@
 void DriveInternalsWebUIHandler::OnReadDirectoryByPath(
     const base::FilePath& parent_path,
     drive::FileError error,
-    bool hide_hosted_documents,
     scoped_ptr<drive::ResourceEntryVector> entries) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
diff --git a/chrome/browser/ui/webui/chromeos/keyboard_overlay_ui.cc b/chrome/browser/ui/webui/chromeos/keyboard_overlay_ui.cc
index 64cba4f..a768034 100644
--- a/chrome/browser/ui/webui/chromeos/keyboard_overlay_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/keyboard_overlay_ui.cc
@@ -62,19 +62,6 @@
 } kI18nContentToMessage[] = {
   { "keyboardOverlayLearnMore", IDS_KEYBOARD_OVERLAY_LEARN_MORE },
   { "keyboardOverlayTitle", IDS_KEYBOARD_OVERLAY_TITLE },
-  { "keyboardOverlayF1", IDS_KEYBOARD_OVERLAY_F1 },
-  { "keyboardOverlayF2", IDS_KEYBOARD_OVERLAY_F2 },
-  { "keyboardOverlayF3", IDS_KEYBOARD_OVERLAY_F3 },
-  { "keyboardOverlayF4", IDS_KEYBOARD_OVERLAY_F4 },
-  { "keyboardOverlayF5", IDS_KEYBOARD_OVERLAY_F5 },
-  { "keyboardOverlayF6", IDS_KEYBOARD_OVERLAY_F6 },
-  { "keyboardOverlayF7", IDS_KEYBOARD_OVERLAY_F7 },
-  { "keyboardOverlayF8", IDS_KEYBOARD_OVERLAY_F8 },
-  { "keyboardOverlayF9", IDS_KEYBOARD_OVERLAY_F9 },
-  { "keyboardOverlayF10", IDS_KEYBOARD_OVERLAY_F10 },
-  { "keyboardOverlayF11", IDS_KEYBOARD_OVERLAY_F11 },
-  { "keyboardOverlayF12", IDS_KEYBOARD_OVERLAY_F12 },
-  { "keyboardOverlayInsert", IDS_KEYBOARD_OVERLAY_INSERT },
   { "keyboardOverlayInstructions", IDS_KEYBOARD_OVERLAY_INSTRUCTIONS },
   { "keyboardOverlayInstructionsHide", IDS_KEYBOARD_OVERLAY_INSTRUCTIONS_HIDE },
   { "keyboardOverlayActivateLastLauncherItem",
@@ -132,6 +119,18 @@
   { "keyboardOverlayDomInspector", IDS_KEYBOARD_OVERLAY_DOM_INSPECTOR },
   { "keyboardOverlayDownloads", IDS_KEYBOARD_OVERLAY_DOWNLOADS },
   { "keyboardOverlayEnd", IDS_KEYBOARD_OVERLAY_END },
+  { "keyboardOverlayF1", IDS_KEYBOARD_OVERLAY_F1 },
+  { "keyboardOverlayF10", IDS_KEYBOARD_OVERLAY_F10 },
+  { "keyboardOverlayF11", IDS_KEYBOARD_OVERLAY_F11 },
+  { "keyboardOverlayF12", IDS_KEYBOARD_OVERLAY_F12 },
+  { "keyboardOverlayF2", IDS_KEYBOARD_OVERLAY_F2 },
+  { "keyboardOverlayF3", IDS_KEYBOARD_OVERLAY_F3 },
+  { "keyboardOverlayF4", IDS_KEYBOARD_OVERLAY_F4 },
+  { "keyboardOverlayF5", IDS_KEYBOARD_OVERLAY_F5 },
+  { "keyboardOverlayF6", IDS_KEYBOARD_OVERLAY_F6 },
+  { "keyboardOverlayF7", IDS_KEYBOARD_OVERLAY_F7 },
+  { "keyboardOverlayF8", IDS_KEYBOARD_OVERLAY_F8 },
+  { "keyboardOverlayF9", IDS_KEYBOARD_OVERLAY_F9 },
   { "keyboardOverlayFindPreviousText",
     IDS_KEYBOARD_OVERLAY_FIND_PREVIOUS_TEXT },
   { "keyboardOverlayFindText", IDS_KEYBOARD_OVERLAY_FIND_TEXT },
@@ -155,6 +154,7 @@
     IDS_KEYBOARD_OVERLAY_INCREASE_KEY_BRIGHTNESS },
   { "keyboardOverlayInputUnicodeCharacters",
     IDS_KEYBOARD_OVERLAY_INPUT_UNICODE_CHARACTERS },
+  { "keyboardOverlayInsert", IDS_KEYBOARD_OVERLAY_INSERT },
   { "keyboardOverlayJavascriptConsole",
     IDS_KEYBOARD_OVERLAY_JAVASCRIPT_CONSOLE },
   { "keyboardOverlayLockScreen", IDS_KEYBOARD_OVERLAY_LOCK_SCREEN },
diff --git a/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc b/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc
index 185d124..259cdf6 100644
--- a/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc
@@ -200,7 +200,7 @@
   bool enable_keyboard_flow = false;
   chromeos::system::StatisticsProvider* provider =
       chromeos::system::StatisticsProvider::GetInstance();
-  provider->GetMachineFlag(chromeos::kOemKeyboardDrivenOobeKey,
+  provider->GetMachineFlag(chromeos::system::kOemKeyboardDrivenOobeKey,
                            &enable_keyboard_flow);
   if (enable_keyboard_flow)
     CallJS("cr.ui.Oobe.enableKeyboardFlow", enable_keyboard_flow);
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 847a807..e533193 100644
--- a/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc
@@ -182,6 +182,8 @@
     case GoogleServiceAuthError::HOSTED_NOT_ALLOWED:
     case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS:
     case GoogleServiceAuthError::REQUEST_CANCELED:
+    case GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE:
+    case GoogleServiceAuthError::SERVICE_ERROR:
       ShowError(IDS_ENTERPRISE_ENROLLMENT_AUTH_FATAL_ERROR, false);
       return;
     case GoogleServiceAuthError::USER_NOT_SIGNED_UP:
@@ -275,14 +277,6 @@
   NOTREACHED();
 }
 
-void EnrollmentScreenHandler::SubmitTestCredentials(
-    const std::string& email,
-    const std::string& password) {
-  test_email_ = email;
-  test_password_ = password;
-  DoShow();
-}
-
 // EnrollmentScreenHandler BaseScreenHandler implementation -----
 
 void EnrollmentScreenHandler::Initialize() {
@@ -465,10 +459,6 @@
   screen_data.SetString("gaiaUrl", GaiaUrls::GetInstance()->gaia_url().spec());
   screen_data.SetBoolean("is_auto_enrollment", is_auto_enrollment_);
   screen_data.SetBoolean("prevent_cancellation", !can_exit_enrollment_);
-  if (!test_email_.empty()) {
-    screen_data.SetString("test_email", test_email_);
-    screen_data.SetString("test_password", test_password_);
-  }
 
   ShowScreen(OobeUI::kScreenOobeEnrollment, &screen_data);
 }
diff --git a/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.h
index 42e8f63..5183066 100644
--- a/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.h
@@ -51,8 +51,6 @@
   virtual void ShowAuthError(const GoogleServiceAuthError& error) OVERRIDE;
   virtual void ShowEnrollmentStatus(policy::EnrollmentStatus status) OVERRIDE;
   virtual void ShowUIError(UIError error_code) OVERRIDE;
-  virtual void SubmitTestCredentials(const std::string& email,
-                                     const std::string& password) OVERRIDE;
 
   // Implements BaseScreenHandler:
   virtual void Initialize() OVERRIDE;
@@ -123,10 +121,6 @@
   // Username of the user signing in.
   std::string user_;
 
-  // Credentials used for tests.
-  std::string test_email_;
-  std::string test_password_;
-
   // This intentionally lives here and not in the controller, since it needs to
   // execute requests in the context of the profile that displays the webui.
   scoped_ptr<GaiaOAuthFetcher> oauth_fetcher_;
diff --git a/chrome/browser/ui/webui/chromeos/login/error_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/error_screen_handler.cc
index f296b0c..cee9ea1 100644
--- a/chrome/browser/ui/webui/chromeos/login/error_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/error_screen_handler.cc
@@ -6,7 +6,7 @@
 
 #include "base/logging.h"
 #include "base/message_loop.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/chromeos/login/captive_portal_window_proxy.h"
 #include "chrome/browser/chromeos/net/network_portal_detector.h"
 #include "chrome/browser/ui/webui/chromeos/login/native_window_delegate.h"
diff --git a/chrome/browser/ui/webui/chromeos/login/kiosk_app_menu_handler.cc b/chrome/browser/ui/webui/chromeos/login/kiosk_app_menu_handler.cc
index fa23a06..1fdc155 100644
--- a/chrome/browser/ui/webui/chromeos/login/kiosk_app_menu_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/kiosk_app_menu_handler.cc
@@ -7,9 +7,11 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/values.h"
+#include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/app_mode/kiosk_app_launch_error.h"
 #include "chrome/browser/chromeos/app_mode/kiosk_app_launcher.h"
 #include "chrome/browser/chromeos/login/existing_user_controller.h"
+#include "chrome/browser/policy/browser_policy_connector.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "chromeos/chromeos_switches.h"
 #include "content/public/browser/notification_details.h"
@@ -87,6 +89,12 @@
 
 void KioskAppMenuHandler::HandleInitializeKioskApps(
     const base::ListValue* args) {
+  if (g_browser_process->browser_policy_connector()->IsEnterpriseManaged()) {
+    initialized_ = true;
+    SendKioskApps();
+    return;
+  }
+
   KioskAppManager::Get()->GetConsumerKioskModeStatus(
       base::Bind(&KioskAppMenuHandler::OnGetConsumerKioskModeStatus,
                  weak_ptr_factory_.GetWeakPtr()));
diff --git a/chrome/browser/ui/webui/chromeos/login/locally_managed_user_creation_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/locally_managed_user_creation_screen_handler.cc
index e83226c..c2a594b 100644
--- a/chrome/browser/ui/webui/chromeos/login/locally_managed_user_creation_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/locally_managed_user_creation_screen_handler.cc
@@ -12,8 +12,10 @@
 #include "chrome/browser/chromeos/settings/cros_settings.h"
 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
 #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
+#include "chrome/common/url_constants.h"
 #include "google_apis/gaia/gaia_auth_util.h"
 #include "grit/generated_resources.h"
+#include "net/base/data_url.h"
 #include "ui/base/l10n/l10n_util.h"
 
 namespace {
@@ -22,15 +24,13 @@
 const char kLocallyManagedUserCreationScreen[] =
     "locally-managed-user-creation";
 
-const char kLocallyManagedWebURL[] =
-    "www.chrome.com/SomeTBDURL";
-
 }  // namespace
 
 namespace chromeos {
 
 LocallyManagedUserCreationScreenHandler::
-    LocallyManagedUserCreationScreenHandler() {}
+LocallyManagedUserCreationScreenHandler() : delegate_(NULL) {
+}
 
 LocallyManagedUserCreationScreenHandler::
     ~LocallyManagedUserCreationScreenHandler() {}
@@ -59,13 +59,13 @@
                IDS_CREATE_LOCALLY_MANAGED_INTRO_TEXT_2);
   builder->AddF("createManagedUserIntroText3",
                IDS_CREATE_LOCALLY_MANAGED_INTRO_TEXT_3,
-               UTF8ToUTF16(kLocallyManagedWebURL));
+               UTF8ToUTF16(chrome::kSupervisedUserManagementDisplayURL));
 
   builder->Add("createManagedUserPickManagerTitle",
                IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_PICK_MANAGER_TITLE);
   builder->AddF("createManagedUserPickManagerTitleExplanation",
                IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_PICK_MANAGER_EXPLANATION,
-               UTF8ToUTF16(kLocallyManagedWebURL));
+               UTF8ToUTF16(chrome::kSupervisedUserManagementDisplayURL));
   builder->Add("createManagedUserManagerPasswordHint",
                IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_MANAGER_PASSWORD_HINT);
   builder->Add("createManagedUserWrongManagerPasswordText",
@@ -101,21 +101,15 @@
   builder->Add("createManagedUserCreated1Text2",
                IDS_CREATE_LOCALLY_MANAGED_USER_CREATED_1_TEXT_2);
   builder->Add("createManagedUserCreated1Text3",
-               IDS_CREATE_LOCALLY_MANAGED_USER_CREATED_3_TEXT_3);
+               IDS_CREATE_LOCALLY_MANAGED_USER_CREATED_1_TEXT_3);
 
-  builder->Add("createManagedUserCreated2Text1",
-               IDS_CREATE_LOCALLY_MANAGED_USER_CREATED_2_TEXT_1);
-  builder->Add("createManagedUserCreated2Text2",
-               IDS_CREATE_LOCALLY_MANAGED_USER_CREATED_2_TEXT_2);
+  builder->Add("managementURL", chrome::kSupervisedUserManagementDisplayURL);
 
-  builder->Add("createManagedUserCreated3Text1",
-               IDS_CREATE_LOCALLY_MANAGED_USER_CREATED_3_TEXT_1);
-  builder->Add("createManagedUserCreated3Text2",
-               IDS_CREATE_LOCALLY_MANAGED_USER_CREATED_3_TEXT_2);
-  builder->Add("createManagedUserCreated3Text3",
-               IDS_CREATE_LOCALLY_MANAGED_USER_CREATED_3_TEXT_3);
-
-  builder->Add("managementURL", kLocallyManagedWebURL);
+  // TODO(antrim) : this is an explicit code duplications with UserImageScreen.
+  // It should be removed by issue 251179.
+  builder->Add("takePhoto", IDS_OPTIONS_CHANGE_PICTURE_TAKE_PHOTO);
+  builder->Add("discardPhoto", IDS_OPTIONS_CHANGE_PICTURE_DISCARD_PHOTO);
+  builder->Add("flipPhoto", IDS_OPTIONS_CHANGE_PICTURE_FLIP_PHOTO);
 }
 
 void LocallyManagedUserCreationScreenHandler::Initialize() {}
@@ -139,6 +133,20 @@
   AddCallback("managerSelectedOnLocallyManagedUserCreationFlow",
               &LocallyManagedUserCreationScreenHandler::
                   HandleManagerSelected);
+
+  // TODO(antrim) : this is an explicit code duplications with UserImageScreen.
+  // It should be removed by issue 251179.
+  AddCallback("supervisedUserGetImages",
+              &LocallyManagedUserCreationScreenHandler::
+                  HandleGetImages);
+
+  AddCallback("supervisedUserPhotoTaken",
+              &LocallyManagedUserCreationScreenHandler::HandlePhotoTaken);
+  AddCallback("supervisedUserSelectImage",
+              &LocallyManagedUserCreationScreenHandler::HandleSelectImage);
+  AddCallback("supervisedUserCheckCameraPresence",
+              &LocallyManagedUserCreationScreenHandler::
+                  HandleCheckCameraPresence);
 }
 
 void LocallyManagedUserCreationScreenHandler::PrepareToShow() {}
@@ -160,6 +168,10 @@
   }
   data->Set("managers", users_list.release());
   ShowScreen(OobeUI::kScreenManagedUserCreationFlow, data.get());
+
+  if (!delegate_)
+    return;
+  delegate_->CheckCameraPresence();
 }
 
 void LocallyManagedUserCreationScreenHandler::Hide() {}
@@ -270,4 +282,49 @@
   delegate_->AuthenticateManager(manager_username, manager_password);
 }
 
+// TODO(antrim) : this is an explicit code duplications with UserImageScreen.
+// It should be removed by issue 251179.
+void LocallyManagedUserCreationScreenHandler::HandleGetImages() {
+  base::ListValue image_urls;
+  for (int i = kFirstDefaultImageIndex; i < kDefaultImagesCount; ++i) {
+    scoped_ptr<base::DictionaryValue> image_data(new base::DictionaryValue);
+    image_data->SetString("url", GetDefaultImageUrl(i));
+    image_data->SetString(
+        "author", l10n_util::GetStringUTF16(kDefaultImageAuthorIDs[i]));
+    image_data->SetString(
+        "website", l10n_util::GetStringUTF16(kDefaultImageWebsiteIDs[i]));
+    image_data->SetString("title", GetDefaultImageDescription(i));
+    image_urls.Append(image_data.release());
+  }
+  CallJS("login.LocallyManagedUserCreationScreen.setDefaultImages", image_urls);
+}
+
+void LocallyManagedUserCreationScreenHandler::HandlePhotoTaken
+    (const std::string& image_url) {
+  std::string mime_type, charset, raw_data;
+  if (!net::DataURL::Parse(GURL(image_url), &mime_type, &charset, &raw_data))
+    NOTREACHED();
+  DCHECK_EQ("image/png", mime_type);
+
+  if (delegate_)
+    delegate_->OnPhotoTaken(raw_data);
+}
+
+void LocallyManagedUserCreationScreenHandler::HandleCheckCameraPresence() {
+  if (!delegate_)
+    return;
+  delegate_->CheckCameraPresence();
+}
+
+void LocallyManagedUserCreationScreenHandler::HandleSelectImage(
+    const std::string& image_url,
+    const std::string& image_type) {
+  if (delegate_)
+    delegate_->OnImageSelected(image_type, image_url);
+}
+
+void LocallyManagedUserCreationScreenHandler::SetCameraPresent(bool present) {
+  CallJS("login.LocallyManagedUserCreationScreen.setCameraPresent", present);
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/login/locally_managed_user_creation_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/locally_managed_user_creation_screen_handler.h
index d88faa3..1ec027a 100644
--- a/chrome/browser/ui/webui/chromeos/login/locally_managed_user_creation_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/locally_managed_user_creation_screen_handler.h
@@ -9,6 +9,7 @@
 
 #include "base/compiler_specific.h"
 #include "base/strings/string16.h"
+#include "chrome/browser/chromeos/login/default_user_images.h"
 #include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h"
 #include "content/public/browser/web_ui.h"
 
@@ -44,11 +45,14 @@
         const string16& display_name,
         const std::string& managed_user_password) = 0;
 
-    // Starts picture selection for created managed user.
-    virtual void SelectPicture() = 0;
-
     virtual void AbortFlow() = 0;
     virtual void FinishFlow() = 0;
+
+    virtual void CheckCameraPresence() = 0;
+    virtual void OnPhotoTaken(const std::string& raw_data) = 0;
+    virtual void OnImageSelected(const std::string& image_url,
+                                 const std::string& image_type) = 0;
+    virtual void OnImageAccepted() = 0;
   };
 
   LocallyManagedUserCreationScreenHandler();
@@ -74,6 +78,8 @@
                      const string16& message,
                      const string16& button_text);
 
+  void SetCameraPresent(bool enabled);
+
   // BaseScreenHandler implementation:
   virtual void DeclareLocalizedValues(LocalizedValuesBuilder* builder) OVERRIDE;
   virtual void Initialize() OVERRIDE;
@@ -96,6 +102,12 @@
   void HandleCreateManagedUser(const string16& new_raw_user_name,
                                const std::string& new_user_password);
 
+  void HandleGetImages();
+  void HandlePhotoTaken(const std::string& image_url);
+  void HandleCheckCameraPresence();
+  void HandleSelectImage(const std::string& image_url,
+                         const std::string& image_type);
+
   void UpdateText(const std::string& element_id, const string16& text);
 
   Delegate* delegate_;
diff --git a/chrome/browser/ui/webui/chromeos/login/network_dropdown.cc b/chrome/browser/ui/webui/chromeos/login/network_dropdown.cc
index c4b6a83..139092e 100644
--- a/chrome/browser/ui/webui/chromeos/login/network_dropdown.cc
+++ b/chrome/browser/ui/webui/chromeos/login/network_dropdown.cc
@@ -8,7 +8,7 @@
 
 #include "ash/system/chromeos/network/network_icon.h"
 #include "ash/system/chromeos/network/network_icon_animation.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/chromeos/login/login_display_host.h"
 #include "chrome/browser/chromeos/login/login_display_host_impl.h"
diff --git a/chrome/browser/ui/webui/chromeos/login/network_dropdown.h b/chrome/browser/ui/webui/chromeos/login/network_dropdown.h
index 6cf0fca..c92654b 100644
--- a/chrome/browser/ui/webui/chromeos/login/network_dropdown.h
+++ b/chrome/browser/ui/webui/chromeos/login/network_dropdown.h
@@ -7,7 +7,7 @@
 
 #include "ash/system/chromeos/network/network_icon_animation_observer.h"
 #include "base/basictypes.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/chromeos/status/network_menu.h"
 #include "chromeos/network/network_state_handler_observer.h"
 #include "ui/gfx/native_widget_types.h"
diff --git a/chrome/browser/ui/webui/chromeos/login/network_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/network_screen_handler.cc
index 4044379..8d96641 100644
--- a/chrome/browser/ui/webui/chromeos/login/network_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/network_screen_handler.cc
@@ -89,7 +89,7 @@
 void NetworkScreenHandler::EnableContinue(bool enabled) {
   is_continue_enabled_ = enabled;
   if (page_is_ready())
-    CallJS("cr.ui.Oobe.enableContinueButton", enabled);
+    CallJS("login.NetworkScreen.enableContinueButton", enabled);
 }
 
 // NetworkScreenHandler, BaseScreenHandler implementation: --------------------
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
index 81f0336..ef64deb 100644
--- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
@@ -57,9 +57,6 @@
 // Path for a stripped down login page that does not have OOBE elements.
 const char kLoginPath[] = "login#login";
 
-// Path for the enterprise enrollment gaia page hosting.
-const char kEnterpriseEnrollmentGaiaLoginPath[] = "gaialogin";
-
 const char kStringsJSPath[] = "strings.js";
 const char kLoginJSPath[] = "login.js";
 const char kOobeJSPath[] = "oobe.js";
@@ -110,8 +107,6 @@
                           IDR_LOGIN_HTML);
   source->AddResourcePath(kLoginJSPath,
                           IDR_LOGIN_JS);
-  source->AddResourcePath(kEnterpriseEnrollmentGaiaLoginPath,
-                          IDR_GAIA_LOGIN_HTML);
   source->AddResourcePath(kKeyboardUtilsJSPath,
                           IDR_KEYBOARD_UTILS_JS);
   source->OverrideContentSecurityPolicyFrameSrc(
@@ -354,7 +349,7 @@
 
   bool keyboard_driven_oobe = false;
   system::StatisticsProvider::GetInstance()->GetMachineFlag(
-      chromeos::kOemKeyboardDrivenOobeKey, &keyboard_driven_oobe);
+      chromeos::system::kOemKeyboardDrivenOobeKey, &keyboard_driven_oobe);
   localized_strings->SetString("highlightStrength",
                                keyboard_driven_oobe ? "strong" : "normal");
 }
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
index e8cdd21..2388a61 100644
--- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
@@ -29,7 +29,6 @@
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
 #include "chrome/browser/io_thread.h"
-#include "chrome/browser/managed_mode/managed_user_service.h"
 #include "chrome/browser/policy/browser_policy_connector.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/webui/chromeos/login/error_screen_handler.h"
@@ -329,6 +328,7 @@
       dns_clear_task_running_(false),
       cookies_cleared_(false),
       network_state_informer_(network_state_informer),
+      test_expects_complete_login_(false),
       weak_factory_(this),
       webui_visible_(false),
       preferences_changed_delayed_(false),
@@ -434,8 +434,9 @@
   builder->Add("publicAccountEnter", IDS_LOGIN_PUBLIC_ACCOUNT_ENTER);
   builder->Add("publicAccountEnterAccessibleName",
                IDS_LOGIN_PUBLIC_ACCOUNT_ENTER_ACCESSIBLE_NAME);
-  builder->Add("removeManagedUserWarningText",
-               IDS_USER_IS_LOCALLY_MANAGED_REMOVE_WARNING);
+  builder->AddF("removeManagedUserWarningText",
+               IDS_USER_IS_LOCALLY_MANAGED_REMOVE_WARNING,
+               UTF8ToUTF16(chrome::kSupervisedUserManagementDisplayURL));
   builder->Add("removeManagedUserWarningButtonTitle",
                IDS_USER_IS_LOCALLY_MANAGED_REMOVE_WARNING_BUTTON);
 
@@ -897,11 +898,20 @@
 void SigninScreenHandler::ShowSigninScreenForCreds(
     const std::string& username,
     const std::string& password) {
-  VLOG(2) << "ShowSigninScreenForCreds " << username << " " << password;
+  VLOG(2) << "ShowSigninScreenForCreds  for user " << username
+          << ", frame_state=" << frame_state_;
 
   test_user_ = username;
   test_pass_ = password;
-  HandleShowAddUser(NULL);
+  test_expects_complete_login_ = true;
+
+  // Submit login form for test if gaia is ready. If gaia is loading, login
+  // will be attempted in HandleLoginWebuiReady after gaia is ready. Otherwise,
+  // reload gaia then follow the loading case.
+  if (frame_state_ == FRAME_STATE_LOADED)
+    SubmitLoginFormForTest();
+  else if (frame_state_ != FRAME_STATE_LOADING)
+    HandleShowAddUser(NULL);
 }
 
 void SigninScreenHandler::OnCookiesCleared(base::Closure on_clear_callback) {
@@ -994,21 +1004,20 @@
 
 
 void SigninScreenHandler::UpdateAuthParams(DictionaryValue* params) {
+  if (!delegate_)
+    return;
+
   UpdateAuthParamsFromSettings(params, CrosSettings::Get());
 
-  // TODO(nkostylev): Allow locally managed user creation only if:
+  // Allow locally managed user creation only if:
   // 1. Enterprise managed device > is allowed by policy.
   // 2. Consumer device > owner exists.
-  // g_browser_process->browser_policy_connector()->IsEnterpriseManaged()
-  // const UserList& users = delegate_->GetUsers();
-  // bool single_user = users.size() == 1;
-  // chromeos::CrosSettings::Get()->GetString(chromeos::kDeviceOwner, &owner);
-
-  bool managed_users_enabled = ManagedUserService::AreManagedUsersEnabled();
+  bool managed_users_allowed =
+      UserManager::Get()->AreLocallyManagedUsersAllowed();
   bool managed_users_can_create = false;
-  if (managed_users_enabled)
+  if (managed_users_allowed)
     managed_users_can_create = delegate_->GetUsers().size() > 0;
-  params->SetBoolean("managedUsersEnabled", managed_users_enabled);
+  params->SetBoolean("managedUsersEnabled", managed_users_allowed);
   params->SetBoolean("managedUsersCanCreate", managed_users_can_create);
 }
 
@@ -1057,18 +1066,6 @@
           GaiaUrls::GetInstance()->gaia_url();
   params.SetString("gaiaUrl", gaia_url.spec());
 
-  // Test automation data:
-  const CommandLine* command_line = CommandLine::ForCurrentProcess();
-  if (command_line->HasSwitch(switches::kAuthExtensionPath)) {
-    if (!test_user_.empty()) {
-      params.SetString("test_email", test_user_);
-      test_user_.clear();
-    }
-    if (!test_pass_.empty()) {
-      params.SetString("test_password", test_pass_);
-      test_pass_.clear();
-    }
-  }
   frame_state_ = FRAME_STATE_LOADING;
   ignore_next_user_abort_frame_error_ = true;
   CallJS("login.GaiaSigninScreen.loadAuthExtension", params);
@@ -1094,6 +1091,15 @@
   delegate_->CompleteLogin(UserContext(sanitized_email,
                                        password,
                                        std::string()));  // auth_code
+
+  if (test_expects_complete_login_) {
+    VLOG(2) << "Complete test login for " << typed_email
+            << ", requested=" << test_user_;
+
+    test_expects_complete_login_ = false;
+    test_user_.clear();
+    test_pass_.clear();
+  }
 }
 
 void SigninScreenHandler::HandleCompleteAuthentication(
@@ -1127,9 +1133,10 @@
 }
 
 void SigninScreenHandler::HandleShowLocallyManagedUserCreationScreen() {
-  const CommandLine* command_line = CommandLine::ForCurrentProcess();
-  if (!command_line->HasSwitch(::switches::kEnableManagedUsers))
+  if (!UserManager::Get()->AreLocallyManagedUsersAllowed()) {
+    LOG(ERROR) << "Managed users not allowed.";
     return;
+  }
   scoped_ptr<DictionaryValue> params(new DictionaryValue());
   LoginDisplayHostImpl::default_host()->
       StartWizard(WizardController::kLocallyManagedUserCreationScreenName,
@@ -1386,6 +1393,9 @@
     RefocusCurrentPod();
   }
   HandleFrameLoadingCompleted(0);
+
+  if (test_expects_complete_login_)
+    SubmitLoginFormForTest();
 }
 
 void SigninScreenHandler::HandleDemoWebuiReady() {
@@ -1649,4 +1659,22 @@
   return !show_pods;
 }
 
+void SigninScreenHandler::SubmitLoginFormForTest() {
+  VLOG(2) << "Submit login form for test, user=" << test_user_;
+
+  std::string code;
+  code += "document.getElementById('Email').value = '" + test_user_ + "';";
+  code += "document.getElementById('Passwd').value = '" + test_pass_ + "';";
+  code += "document.getElementById('signIn').click();";
+
+  RenderViewHost* rvh = web_ui()->GetWebContents()->GetRenderViewHost();
+  rvh->ExecuteJavascriptInWebFrame(
+      ASCIIToUTF16("//iframe[@id='signin-frame']\n//iframe"),
+      ASCIIToUTF16(code));
+
+  // Test properties are cleared in HandleCompleteLogin because the form
+  // submission might fail and login will not be attempted after reloading
+  // if they are cleared here.
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
index fe5e98a..1c17b8c 100644
--- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
@@ -376,6 +376,9 @@
   // Returns true if offline login is allowed.
   bool IsOfflineLoginAllowed() const;
 
+  // Attempts login for test.
+  void SubmitLoginFormForTest();
+
   // Current UI state of the signin screen.
   UIState ui_state_;
 
@@ -432,6 +435,7 @@
   // Test credentials.
   std::string test_user_;
   std::string test_pass_;
+  bool test_expects_complete_login_;
 
   base::WeakPtrFactory<SigninScreenHandler> weak_factory_;
 
diff --git a/chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.h
index 9602558..9ac7c64 100644
--- a/chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.h
@@ -8,7 +8,7 @@
 #include <string>
 
 #include "base/memory/weak_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/chromeos/login/screens/user_image_screen_actor.h"
 #include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h"
 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
diff --git a/chrome/browser/ui/webui/chromeos/proxy_settings_ui.cc b/chrome/browser/ui/webui/chromeos/proxy_settings_ui.cc
index 672bc83..c136db5 100644
--- a/chrome/browser/ui/webui/chromeos/proxy_settings_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/proxy_settings_ui.cc
@@ -101,7 +101,7 @@
 
   bool keyboard_driven_oobe = false;
   system::StatisticsProvider::GetInstance()->GetMachineFlag(
-      chromeos::kOemKeyboardDrivenOobeKey, &keyboard_driven_oobe);
+      chromeos::system::kOemKeyboardDrivenOobeKey, &keyboard_driven_oobe);
   localized_strings->SetString("highlightStrength",
                                keyboard_driven_oobe ? "strong" : "normal");
 
diff --git a/chrome/browser/ui/webui/chromeos/salsa_ui.cc b/chrome/browser/ui/webui/chromeos/salsa_ui.cc
new file mode 100644
index 0000000..62ed671
--- /dev/null
+++ b/chrome/browser/ui/webui/chromeos/salsa_ui.cc
@@ -0,0 +1,193 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/chromeos/salsa_ui.h"
+
+#include "base/bind.h"
+#include "base/prefs/pref_service.h"
+#include "base/values.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/url_constants.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/web_ui.h"
+#include "content/public/browser/web_ui_data_source.h"
+#include "grit/browser_resources.h"
+
+// Whitelist of which preferences are possible targets for Salsa treatments.
+// If new preferences are added and they are to be used in an experiment, then
+// they must be added to this list as well to keep chrome://salsa from
+// changing arbitrary values.
+
+namespace {
+
+const char* kWhitelist[] = {
+  prefs::kFlingMaxCancelToDownTimeInMs,
+  prefs::kFlingMaxTapGapTimeInMs,
+  prefs::kLongPressTimeInSeconds,
+  prefs::kLongPressTimeInSeconds,
+  prefs::kMaxSecondsBetweenDoubleClick,
+  prefs::kMaxSeparationForGestureTouchesInPixels,
+  prefs::kMaxSwipeDeviationRatio,
+  prefs::kMaxTouchDownDurationInSecondsForClick,
+  prefs::kMaxTouchMoveInPixelsForClick,
+  prefs::kMaxDistanceBetweenTapsForDoubleTap,
+  prefs::kMaxDistanceForTwoFingerTapInPixels,
+  prefs::kMinDistanceForPinchScrollInPixels,
+  prefs::kMinFlickSpeedSquared,
+  prefs::kMinPinchUpdateDistanceInPixels,
+  prefs::kMinRailBreakVelocity,
+  prefs::kMinScrollDeltaSquared,
+  prefs::kMinSwipeSpeed,
+  prefs::kMinTouchDownDurationInSecondsForClick,
+  prefs::kPointsBufferedForVelocity,
+  prefs::kRailBreakProportion,
+  prefs::kRailStartProportion,
+  prefs::kFlingAccelerationCurveCoefficient0,
+  prefs::kFlingAccelerationCurveCoefficient1,
+  prefs::kFlingAccelerationCurveCoefficient2,
+  prefs::kFlingAccelerationCurveCoefficient3,
+  prefs::kFlingVelocityCap,
+  prefs::kTabScrubActivationDelayInMS,
+  prefs::kOverscrollHorizontalThresholdComplete,
+  prefs::kOverscrollVerticalThresholdComplete,
+  prefs::kOverscrollMinimumThresholdStart,
+  prefs::kOverscrollHorizontalResistThreshold,
+  prefs::kOverscrollVerticalResistThreshold,
+  prefs::kImmersiveModeRevealDelayMs,
+  prefs::kImmersiveModeRevealXThresholdPixels,
+  prefs::kWorkspaceCyclerSelectedScale,
+  prefs::kWorkspaceCyclerMinScale,
+  prefs::kWorkspaceCyclerMaxScale,
+  prefs::kWorkspaceCyclerMinBrightness,
+  prefs::kWorkspaceCyclerBackgroundOpacity,
+  prefs::kWorkspaceCyclerDesktopWorkspaceBrightness,
+  prefs::kWorkspaceCyclerDistanceToInitiateCycling,
+  prefs::kWorkspaceCyclerScrollDistanceToCycleToNextWorkspace,
+  prefs::kWorkspaceCyclerCyclerStepAnimationDurationRatio,
+  prefs::kWorkspaceCyclerStartCyclerAnimationDuration,
+  prefs::kWorkspaceCyclerStopCyclerAnimationDuration,
+  prefs::kFlingCurveTouchscreenAlpha,
+  prefs::kFlingCurveTouchscreenBeta,
+  prefs::kFlingCurveTouchscreenGamma,
+  prefs::kFlingCurveTouchpadAlpha,
+  prefs::kFlingCurveTouchpadBeta,
+  prefs::kFlingCurveTouchpadGamma,
+};
+
+void RevertPreferences(PrefService* prefs,
+                       std::map<int, const base::Value*>* vals) {
+  std::map<int, const base::Value*>::const_iterator it;
+  for (it = vals->begin(); it != vals->end(); ++it) {
+    if (!prefs->FindPreference(kWhitelist[it->first]))
+      continue;
+
+    if (!it->second) {
+      prefs->ClearPref(kWhitelist[it->first]);
+    } else {
+      prefs->Set(kWhitelist[it->first], *it->second);
+      delete it->second;
+    }
+  }
+}
+
+} // namespace
+
+SalsaUI::SalsaUI(content::WebUI* web_ui)
+    : content::WebUIController(web_ui) {
+  // Set up the chrome://salsa source.
+  content::WebUIDataSource* html_source =
+      content::WebUIDataSource::Create(chrome::kChromeUISalsaHost);
+
+  // Register callback handlers.
+  web_ui->RegisterMessageCallback(
+      "salsaSetPreferenceValue",
+      base::Bind(&SalsaUI::SetPreferenceValue,
+                 base::Unretained(this)));
+  web_ui->RegisterMessageCallback(
+      "salsaBackupPreferenceValue",
+      base::Bind(&SalsaUI::BackupPreferenceValue,
+                 base::Unretained(this)));
+
+  // Add required resources.
+  html_source->AddResourcePath("salsa.css", IDR_SALSA_CSS);
+  html_source->AddResourcePath("salsa.js", IDR_SALSA_JS);
+  html_source->SetDefaultResource(IDR_SALSA_HTML);
+
+  Profile* profile = Profile::FromWebUI(web_ui);
+  content::WebUIDataSource::Add(profile, html_source);
+}
+
+SalsaUI::~SalsaUI() {
+  std::map<int, const base::Value*>* values_to_revert =
+      new std::map<int, const base::Value*>;
+  values_to_revert->swap(orig_values_);
+
+  Profile* profile = Profile::FromWebUI(web_ui());
+  PrefService* prefs = profile->GetPrefs();
+
+  content::BrowserThread::PostTask(
+      content::BrowserThread::UI,
+      FROM_HERE,
+      base::Bind(&RevertPreferences, prefs, base::Owned(values_to_revert))
+    );
+}
+
+int SalsaUI::WhitelistIndex(const char* key) const {
+  if (!key)
+    return -1;
+
+  int len = arraysize(kWhitelist);
+  for (int i = 0; i < len; ++i) {
+    if (!strcmp(key, kWhitelist[i]))
+      return i;
+  }
+  return -1;
+}
+
+void SalsaUI::SetPreferenceValue(const base::ListValue* args) {
+  std::string pref_name;
+  const base::Value* value;
+  if (!args->GetString(0, &pref_name) || !args->Get(1, &value))
+    return;
+
+  int index = WhitelistIndex(pref_name.c_str());
+  if (index < 0)
+    return;
+
+  Profile* profile = Profile::FromWebUI(web_ui());
+  PrefService* prefs = profile->GetPrefs();
+  const PrefService::Preference* pref =
+      prefs->FindPreference(kWhitelist[index]);
+
+  if (pref->GetType() != value->GetType())
+    return;
+
+  prefs->Set(kWhitelist[index], *value);
+}
+
+void SalsaUI::BackupPreferenceValue(const base::ListValue* args) {
+  std::string pref_name;
+  if (!args->GetString(0, &pref_name))
+    return;
+
+  int index = WhitelistIndex(pref_name.c_str());
+  if (index < 0)
+    return;
+
+  Profile* profile = Profile::FromWebUI(web_ui());
+  PrefService* prefs = profile->GetPrefs();
+  const PrefService::Preference* pref =
+      prefs->FindPreference(kWhitelist[index]);
+
+  if (!pref)
+    return;
+
+  // Get our own copy of the user defined value or NULL if they are using the
+  // default. You have to make a copy since they'll be used in the destructor
+  // to restore the values and we need to make sure they're still around.
+  orig_values_[index] =
+      pref->IsDefaultValue() ? NULL : pref->GetValue()->DeepCopy();
+}
diff --git a/chrome/browser/ui/webui/chromeos/salsa_ui.h b/chrome/browser/ui/webui/chromeos/salsa_ui.h
new file mode 100644
index 0000000..130dd4b
--- /dev/null
+++ b/chrome/browser/ui/webui/chromeos/salsa_ui.h
@@ -0,0 +1,49 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_SALSA_UI_H_
+#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_SALSA_UI_H_
+
+#include <map>
+
+#include "base/values.h"
+#include "chrome/browser/profiles/profile.h"
+#include "content/public/browser/web_ui_controller.h"
+
+namespace base {
+class ListValue;
+class Value;
+}  // namespace base
+
+// The WebUI for 'chrome://salsa' -- a user front end for the touch UI
+// blind user studies.  I does this by setting gesture preference values
+// without the user knowing which ones and having them try out various
+// settings to see which results in a better experience for them.
+class SalsaUI : public content::WebUIController {
+ public:
+  // Constructs a new GestureConfig for the specified |web_ui|.
+  explicit SalsaUI(content::WebUI* web_ui);
+  virtual ~SalsaUI();
+
+ private:
+  // Set a preference setting's value.
+  // Two parameters are provided in a JS list: prefName and value, the
+  // key of the preference value to be set, and the value it's to be set to.
+  void SetPreferenceValue(const base::ListValue* args);
+
+  // Record the current value for a preference key and store the key/value pair
+  // in the member variable orig_values_.
+  void BackupPreferenceValue(const base::ListValue* args);
+
+  // Check and see if a key is on the whitelist.  Returns the index into
+  // the whitelist on success and -1 on failure.
+  int WhitelistIndex(const char* key) const;
+
+  std::map<int, const base::Value*> orig_values_;
+
+  DISALLOW_COPY_AND_ASSIGN(SalsaUI);
+};
+
+#endif  // CHROME_BROWSER_UI_WEBUI_CHROMEOS_SALSA_UI_H_
+
diff --git a/chrome/browser/ui/webui/chromeos/system_info_ui.cc b/chrome/browser/ui/webui/chromeos/system_info_ui.cc
index c3d62e8..e60ca63 100644
--- a/chrome/browser/ui/webui/chromeos/system_info_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/system_info_ui.cc
@@ -16,7 +16,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/threading/thread.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/chromeos/cros/cros_library.h"
 #include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
diff --git a/chrome/browser/ui/webui/chromeos/ui_account_tweaks.cc b/chrome/browser/ui/webui/chromeos/ui_account_tweaks.cc
index 3d5a909..51d9540 100644
--- a/chrome/browser/ui/webui/chromeos/ui_account_tweaks.cc
+++ b/chrome/browser/ui/webui/chromeos/ui_account_tweaks.cc
@@ -29,6 +29,9 @@
 
   localized_strings->SetBoolean("loggedInAsGuest",
       UserManager::Get()->IsLoggedInAsGuest());
+
+  localized_strings->SetBoolean("loggedInAsLocallyManagedUser",
+      UserManager::Get()->IsLoggedInAsLocallyManagedUser());
 }
 
 void AddAccountUITweaksLocalizedValues(
diff --git a/chrome/browser/ui/webui/cookies_tree_model_util.cc b/chrome/browser/ui/webui/cookies_tree_model_util.cc
index eeb5eb2..109f0c7 100644
--- a/chrome/browser/ui/webui/cookies_tree_model_util.cc
+++ b/chrome/browser/ui/webui/cookies_tree_model_util.cc
@@ -8,6 +8,7 @@
 
 #include "base/i18n/time_formatting.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
@@ -18,6 +19,7 @@
 #include "net/cookies/canonical_cookie.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/text/bytes_formatting.h"
+#include "webkit/common/fileapi/file_system_types.h"
 
 namespace {
 
@@ -197,18 +199,20 @@
 
       const BrowsingDataFileSystemHelper::FileSystemInfo& file_system_info =
           *node.GetDetailedInfo().file_system_info;
+      const fileapi::FileSystemType kPerm = fileapi::kFileSystemTypePersistent;
+      const fileapi::FileSystemType kTemp = fileapi::kFileSystemTypeTemporary;
 
       dict->SetString(kKeyOrigin, file_system_info.origin.spec());
       dict->SetString(kKeyPersistent,
-                      file_system_info.has_persistent ?
+                      ContainsKey(file_system_info.usage_map, kPerm) ?
                           UTF16ToUTF8(ui::FormatBytes(
-                              file_system_info.usage_persistent)) :
+                              file_system_info.usage_map.find(kPerm)->second)) :
                           l10n_util::GetStringUTF8(
                               IDS_COOKIES_FILE_SYSTEM_USAGE_NONE));
       dict->SetString(kKeyTemporary,
-                      file_system_info.has_temporary ?
+                      ContainsKey(file_system_info.usage_map, kTemp) ?
                           UTF16ToUTF8(ui::FormatBytes(
-                              file_system_info.usage_temporary)) :
+                              file_system_info.usage_map.find(kTemp)->second)) :
                           l10n_util::GetStringUTF8(
                               IDS_COOKIES_FILE_SYSTEM_USAGE_NONE));
       break;
diff --git a/chrome/browser/ui/webui/crashes_ui.cc b/chrome/browser/ui/webui/crashes_ui.cc
index 85743ba..b885b01 100644
--- a/chrome/browser/ui/webui/crashes_ui.cc
+++ b/chrome/browser/ui/webui/crashes_ui.cc
@@ -78,7 +78,7 @@
   virtual void RegisterMessages() OVERRIDE;
 
   // CrashUploadList::Delegate implemenation.
-  virtual void OnCrashListAvailable() OVERRIDE;
+  virtual void OnUploadListAvailable() OVERRIDE;
 
  private:
   // Asynchronously fetches the list of crashes. Called from JS.
@@ -104,7 +104,7 @@
 }
 
 void CrashesDOMHandler::RegisterMessages() {
-  upload_list_->LoadCrashListAsynchronously();
+  upload_list_->LoadUploadListAsynchronously();
 
   web_ui()->RegisterMessageCallback("requestCrashList",
       base::Bind(&CrashesDOMHandler::HandleRequestCrashes,
@@ -118,7 +118,7 @@
     js_request_pending_ = true;
 }
 
-void CrashesDOMHandler::OnCrashListAvailable() {
+void CrashesDOMHandler::OnUploadListAvailable() {
   list_available_ = true;
   if (js_request_pending_)
     UpdateUI();
@@ -129,15 +129,14 @@
   ListValue crash_list;
 
   if (crash_reporting_enabled) {
-    std::vector<CrashUploadList::CrashInfo> crashes;
-    upload_list_->GetUploadedCrashes(50, &crashes);
+    std::vector<CrashUploadList::UploadInfo> crashes;
+    upload_list_->GetUploads(50, &crashes);
 
-    for (std::vector<CrashUploadList::CrashInfo>::iterator i = crashes.begin();
+    for (std::vector<CrashUploadList::UploadInfo>::iterator i = crashes.begin();
          i != crashes.end(); ++i) {
       DictionaryValue* crash = new DictionaryValue();
-      crash->SetString("id", i->crash_id);
-      crash->SetString("time",
-                       base::TimeFormatFriendlyDateAndTime(i->crash_time));
+      crash->SetString("id", i->id);
+      crash->SetString("time", base::TimeFormatFriendlyDateAndTime(i->time));
       crash_list.Append(crash);
     }
   }
diff --git a/chrome/browser/ui/webui/devtools_ui.cc b/chrome/browser/ui/webui/devtools_ui.cc
index 34dbfb0..0d70e13 100644
--- a/chrome/browser/ui/webui/devtools_ui.cc
+++ b/chrome/browser/ui/webui/devtools_ui.cc
@@ -41,10 +41,6 @@
 #if defined(DEBUG_DEVTOOLS)
 // Local frontend url provided by InspectUI.
 const char kLocalFrontendURLPrefix[] = "https://localhost:9222/";
-// URL local frontend should be served from.
-const char kLocalFrontendBase[] = "http://localhost:9222/";
-// Local frontend path in DevToolsDataSource.
-const char kLocalFrontendDataSourcePath[] = "localhost";
 #endif  // defined(DEBUG_DEVTOOLS)
 
 class FetchRequest : public net::URLFetcherDelegate {
@@ -140,17 +136,6 @@
                               callback);
       return;
     }
-#if defined(DEBUG_DEVTOOLS)
-    std::string local_path_prefix(kLocalFrontendDataSourcePath);
-    local_path_prefix += "/";
-    if (StartsWithASCII(path, local_path_prefix, false)) {
-      StartLocalDataRequest(path.substr(local_path_prefix.length()),
-                              render_process_id,
-                              render_view_id,
-                              callback);
-      return;
-    }
-#endif  // defined(DEBUG_DEVTOOLS)
   }
 
   // Serves bundled DevTools frontend from ResourceBundle.
@@ -184,18 +169,6 @@
     new FetchRequest(request_context_.get(), url, callback);
   }
 
-  // Serves debug DevTools frontend from localhost:9222.
-#if defined(DEBUG_DEVTOOLS)
-  void StartLocalDataRequest(
-      const std::string& path,
-      int render_process_id,
-      int render_view_id,
-      const content::URLDataSource::GotDataCallback& callback) {
-    GURL url = GURL(kLocalFrontendBase + path);
-    new FetchRequest(request_context_.get(), url, callback);
-  }
-#endif  // defined(DEBUG_DEVTOOLS)
-
   virtual std::string GetMimeType(const std::string& path) const OVERRIDE {
     return GetMimeTypeForPath(path);
   }
@@ -219,12 +192,17 @@
 #if defined(DEBUG_DEVTOOLS)
   if (frontend_url.find(kLocalFrontendURLPrefix) == 0) {
     std::string path = url.path();
-    CHECK(path.find(chrome::kChromeUIDevToolsHost) == 1);
-    return GURL(base::StringPrintf("%s://%s/%s/%s",
-                                   chrome::kChromeDevToolsScheme,
-                                   chrome::kChromeUIDevToolsHost,
-                                   kLocalFrontendDataSourcePath,
-                                   path.substr(1).c_str()));
+    std::string local_path_prefix = "/";
+    local_path_prefix += chrome::kChromeUIDevToolsHost;
+    local_path_prefix += "/";
+    if (StartsWithASCII(path, local_path_prefix, false)) {
+      std::string local_path = path.substr(local_path_prefix.length());
+      return GURL(base::StringPrintf("%s://%s/%s/%s",
+                                     chrome::kChromeDevToolsScheme,
+                                     chrome::kChromeUIDevToolsHost,
+                                     chrome::kChromeUIDevToolsBundledPath,
+                                     local_path.c_str()));
+    }
   }
 #endif  // defined(DEBUG_DEVTOOLS)
   CHECK(url.is_valid());
diff --git a/chrome/browser/ui/webui/extensions/extension_icon_source.cc b/chrome/browser/ui/webui/extensions/extension_icon_source.cc
index edb0dbb..c9de20f 100644
--- a/chrome/browser/ui/webui/extensions/extension_icon_source.cc
+++ b/chrome/browser/ui/webui/extensions/extension_icon_source.cc
@@ -24,6 +24,7 @@
 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
 #include "chrome/common/extensions/manifest_handlers/icons_handler.h"
 #include "chrome/common/url_constants.h"
+#include "content/public/child/image_decoder_utils.h"
 #include "extensions/common/extension_resource.h"
 #include "googleurl/src/gurl.h"
 #include "grit/component_extension_resources_map.h"
@@ -34,8 +35,8 @@
 #include "ui/gfx/codec/png_codec.h"
 #include "ui/gfx/color_utils.h"
 #include "ui/gfx/favicon_size.h"
+#include "ui/gfx/size.h"
 #include "ui/gfx/skbitmap_operations.h"
-#include "webkit/glue/image_decoder.h"
 
 namespace {
 
@@ -51,9 +52,8 @@
 }
 
 SkBitmap* ToBitmap(const unsigned char* data, size_t size) {
-  webkit_glue::ImageDecoder decoder;
   SkBitmap* decoded = new SkBitmap();
-  *decoded = decoder.Decode(data, size);
+  *decoded = content::DecodeImage(data, gfx::Size(), size);
   return decoded;
 }
 
diff --git a/chrome/browser/ui/webui/extensions/extension_info_ui.cc b/chrome/browser/ui/webui/extensions/extension_info_ui.cc
index e364066..456cc78 100644
--- a/chrome/browser/ui/webui/extensions/extension_info_ui.cc
+++ b/chrome/browser/ui/webui/extensions/extension_info_ui.cc
@@ -7,7 +7,7 @@
 #include "base/i18n/time_formatting.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/extensions/extension_prefs.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_system.h"
diff --git a/chrome/browser/ui/webui/extensions/extension_settings_browsertest.js b/chrome/browser/ui/webui/extensions/extension_settings_browsertest.js
index 966a833..ed1f622 100644
--- a/chrome/browser/ui/webui/extensions/extension_settings_browsertest.js
+++ b/chrome/browser/ui/webui/extensions/extension_settings_browsertest.js
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// TODO(dbeam): test for loading upacked extensions?
+
 /**
  * TestFixture for extension settings WebUI testing.
  * @extends {testing.Test}
@@ -12,10 +14,46 @@
 ExtensionSettingsWebUITest.prototype = {
   __proto__: testing.Test.prototype,
 
+  /**
+   * A URL to load before starting each test.
+   * @type {string}
+   * @const
+   */
   browsePreload: 'chrome://extensions-frame/',
 };
 
-// Test opening extension settings has correct location.
-TEST_F('ExtensionSettingsWebUITest', 'testOpenExtensionSettings', function() {
+TEST_F('ExtensionSettingsWebUITest', 'testChromeSendHandled', function() {
   assertEquals(this.browsePreload, document.location.href);
+
+  // This dialog should be hidden at first.
+  assertFalse($('packExtensionOverlay').classList.contains('showing'));
+
+  // Show the dialog, which triggers a chrome.send() for metrics purposes.
+  cr.dispatchSimpleEvent($('pack-extension'), 'click');
+  assertTrue($('packExtensionOverlay').classList.contains('showing'));
+});
+
+/**
+ * TestFixture for extension settings WebUI testing (commands config edition).
+ * @extends {testing.Test}
+ * @constructor
+ */
+function ExtensionSettingsCommandsConfigWebUITest() {}
+
+ExtensionSettingsCommandsConfigWebUITest.prototype = {
+  __proto__: testing.Test.prototype,
+
+  /**
+   * A URL to load before starting each test.
+   * @type {string}
+   * @const
+   */
+  browsePreload: 'chrome://extensions-frame/configureCommands',
+};
+
+TEST_F('ExtensionSettingsCommandsConfigWebUITest', 'testChromeSendHandler',
+    function() {
+  // Just navigating to the page should trigger the chrome.send().
+  assertEquals(this.browsePreload, document.location.href);
+  assertTrue($('extensionCommandsOverlay').classList.contains('showing'));
 });
diff --git a/chrome/browser/ui/webui/extensions/extension_settings_handler.cc b/chrome/browser/ui/webui/extensions/extension_settings_handler.cc
index 770d234..240cbca 100644
--- a/chrome/browser/ui/webui/extensions/extension_settings_handler.cc
+++ b/chrome/browser/ui/webui/extensions/extension_settings_handler.cc
@@ -7,6 +7,7 @@
 #include "apps/app_load_service.h"
 #include "apps/app_restore_service.h"
 #include "apps/saved_files_service.h"
+#include "apps/shell_window.h"
 #include "base/auto_reset.h"
 #include "base/base64.h"
 #include "base/bind.h"
@@ -43,7 +44,6 @@
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/chrome_select_file_policy.h"
 #include "chrome/browser/ui/extensions/application_launch.h"
-#include "chrome/browser/ui/extensions/shell_window.h"
 #include "chrome/browser/ui/webui/extensions/extension_basic_info.h"
 #include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
 #include "chrome/common/chrome_notification_types.h"
@@ -65,6 +65,7 @@
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/site_instance.h"
+#include "content/public/browser/user_metrics.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_view.h"
 #include "content/public/browser/web_ui.h"
@@ -319,7 +320,7 @@
   source->AddString("extensionSettingsPolicyControlled",
      l10n_util::GetStringUTF16(IDS_EXTENSIONS_POLICY_CONTROLLED));
   source->AddString("extensionSettingsManagedMode",
-     l10n_util::GetStringUTF16(IDS_EXTENSIONS_LOCKED_MANAGED_MODE));
+     l10n_util::GetStringUTF16(IDS_EXTENSIONS_LOCKED_MANAGED_USER));
   source->AddString("sideloadWipeoutUrl",
       chrome::kSideloadWipeoutHelpURL);
   source->AddString("sideloadWipoutLearnMore",
@@ -885,6 +886,8 @@
       base::FilePath::StringType(),
       web_ui()->GetWebContents()->GetView()->GetTopLevelNativeWindow(),
       NULL);
+
+  content::RecordComputedAction("Options_LoadUnpackedExtension");
 }
 
 void ExtensionSettingsHandler::ShowAlert(const std::string& message) {
diff --git a/chrome/browser/ui/webui/extensions/extensions_ui.cc b/chrome/browser/ui/webui/extensions/extensions_ui.cc
index 7d1b9de..25ab454 100644
--- a/chrome/browser/ui/webui/extensions/extensions_ui.cc
+++ b/chrome/browser/ui/webui/extensions/extensions_ui.cc
@@ -9,6 +9,7 @@
 #include "chrome/browser/ui/webui/extensions/extension_settings_handler.h"
 #include "chrome/browser/ui/webui/extensions/install_extension_handler.h"
 #include "chrome/browser/ui/webui/extensions/pack_extension_handler.h"
+#include "chrome/browser/ui/webui/metrics_handler.h"
 #include "chrome/common/url_constants.h"
 #include "content/public/browser/web_ui.h"
 #include "content/public/browser/web_ui_data_source.h"
@@ -66,6 +67,8 @@
   web_ui->AddMessageHandler(kiosk_app_handler);
 #endif
 
+  web_ui->AddMessageHandler(new MetricsHandler());
+
   content::WebUIDataSource::Add(profile, source);
 }
 
diff --git a/chrome/browser/ui/webui/extensions/install_extension_handler.cc b/chrome/browser/ui/webui/extensions/install_extension_handler.cc
index cb640b9..6ccf455 100644
--- a/chrome/browser/ui/webui/extensions/install_extension_handler.cc
+++ b/chrome/browser/ui/webui/extensions/install_extension_handler.cc
@@ -17,10 +17,10 @@
 #include "content/public/browser/web_contents_view.h"
 #include "content/public/browser/web_ui.h"
 #include "content/public/browser/web_ui_data_source.h"
+#include "content/public/common/drop_data.h"
 #include "grit/generated_resources.h"
 #include "net/base/net_util.h"
 #include "ui/base/l10n/l10n_util.h"
-#include "webkit/common/webdropdata.h"
 
 InstallExtensionHandler::InstallExtensionHandler() {
 }
@@ -54,7 +54,8 @@
 }
 
 void InstallExtensionHandler::HandleStartDragMessage(const ListValue* args) {
-  WebDropData* drop_data = web_ui()->GetWebContents()->GetView()->GetDropData();
+  content::DropData* drop_data =
+      web_ui()->GetWebContents()->GetView()->GetDropData();
   if (!drop_data) {
     DLOG(ERROR) << "No current drop data.";
     return;
@@ -65,7 +66,7 @@
     return;
   }
 
-  const WebDropData::FileInfo& file_info = drop_data->filenames.front();
+  const content::DropData::FileInfo& file_info = drop_data->filenames.front();
 
   file_to_install_ = base::FilePath::FromWStringHack(
       UTF16ToWide(file_info.path));
diff --git a/chrome/browser/ui/webui/feedback_ui.cc b/chrome/browser/ui/webui/feedback_ui.cc
index 042b6fc..3da8d3a 100644
--- a/chrome/browser/ui/webui/feedback_ui.cc
+++ b/chrome/browser/ui/webui/feedback_ui.cc
@@ -18,7 +18,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/download/download_prefs.h"
@@ -117,7 +117,6 @@
                            std::vector<std::string>* saved_screenshots,
                            base::Closure callback,
                            drive::FileError error,
-                           bool hide_hosted_documents,
                            scoped_ptr<drive::ResourceEntryVector> entries) {
   if (error != drive::FILE_ERROR_OK) {
     callback.Run();
diff --git a/chrome/browser/ui/webui/flags_ui.cc b/chrome/browser/ui/webui/flags_ui.cc
index 6a31619..b02441ee 100644
--- a/chrome/browser/ui/webui/flags_ui.cc
+++ b/chrome/browser/ui/webui/flags_ui.cc
@@ -36,6 +36,7 @@
 #include "base/chromeos/chromeos_version.h"
 #include "chrome/browser/chromeos/login/user_manager.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
+#include "chrome/browser/chromeos/settings/owner_flags_storage.h"
 #include "components/user_prefs/pref_registry_syncable.h"
 #endif
 
@@ -98,8 +99,9 @@
 // The handler for Javascript messages for the about:flags page.
 class FlagsDOMHandler : public WebUIMessageHandler {
  public:
-  explicit FlagsDOMHandler(PrefService* prefs, about_flags::FlagAccess access)
-      : flags_storage_(prefs), access_(access) {}
+  FlagsDOMHandler(about_flags::FlagsStorage* flags_storage,
+                  about_flags::FlagAccess access)
+      : flags_storage_(flags_storage), access_(access) {}
   virtual ~FlagsDOMHandler() {}
 
   // WebUIMessageHandler implementation.
@@ -118,7 +120,7 @@
   void HandleResetAllFlags(const ListValue* args);
 
  private:
-  about_flags::PrefServiceFlagsStorage flags_storage_;
+  scoped_ptr<about_flags::FlagsStorage> flags_storage_;
   about_flags::FlagAccess access_;
 
   DISALLOW_COPY_AND_ASSIGN(FlagsDOMHandler);
@@ -142,7 +144,7 @@
 void FlagsDOMHandler::HandleRequestFlagsExperiments(const ListValue* args) {
   scoped_ptr<ListValue> supported_experiments(new ListValue);
   scoped_ptr<ListValue> unsupported_experiments(new ListValue);
-  about_flags::GetFlagsExperimentsData(&flags_storage_,
+  about_flags::GetFlagsExperimentsData(flags_storage_.get(),
                                        access_,
                                        supported_experiments.get(),
                                        unsupported_experiments.get());
@@ -177,7 +179,7 @@
     return;
 
   about_flags::SetExperimentEnabled(
-      &flags_storage_,
+      flags_storage_.get(),
       experiment_internal_name,
       enable_str == "true");
 }
@@ -187,7 +189,7 @@
 }
 
 void FlagsDOMHandler::HandleResetAllFlags(const ListValue* args) {
-  about_flags::ResetAllFlags(&flags_storage_);
+  about_flags::ResetAllFlags(flags_storage_.get());
 }
 
 }  // namespace
@@ -209,7 +211,8 @@
                  weak_factory_.GetWeakPtr(), profile));
 #else
   web_ui->AddMessageHandler(
-      new FlagsDOMHandler(g_browser_process->local_state(),
+      new FlagsDOMHandler(new about_flags::PrefServiceFlagsStorage(
+                              g_browser_process->local_state()),
                           about_flags::kOwnerAccessToFlags));
 
   // Set up the about:flags source.
@@ -245,18 +248,17 @@
     bool current_user_is_owner) {
   // On Chrome OS the owner can set system wide flags and other users can only
   // set flags for their own session.
-  if (!current_user_is_owner) {
+  if (current_user_is_owner) {
     web_ui()->AddMessageHandler(
-        new FlagsDOMHandler(profile->GetPrefs(),
-                            about_flags::kGeneralAccessFlagsOnly));
+        new FlagsDOMHandler(new chromeos::about_flags::OwnerFlagsStorage(
+                                profile->GetPrefs(),
+                                chromeos::CrosSettings::Get()),
+                            about_flags::kOwnerAccessToFlags));
   } else {
     web_ui()->AddMessageHandler(
-        new FlagsDOMHandler(g_browser_process->local_state(),
-                            about_flags::kOwnerAccessToFlags));
-    // If the owner managed to set the flags pref on his own profile clear it
-    // because it will never be accessible anymore.
-    if (profile->GetPrefs()->HasPrefPath(prefs::kEnabledLabsExperiments))
-      profile->GetPrefs()->ClearPref(prefs::kEnabledLabsExperiments);
+        new FlagsDOMHandler(new about_flags::PrefServiceFlagsStorage(
+                                profile->GetPrefs()),
+                            about_flags::kGeneralAccessFlagsOnly));
   }
 
   // Set up the about:flags source.
diff --git a/chrome/browser/ui/webui/flash_ui.cc b/chrome/browser/ui/webui/flash_ui.cc
index 1ef49ac..84a5eba 100644
--- a/chrome/browser/ui/webui/flash_ui.cc
+++ b/chrome/browser/ui/webui/flash_ui.cc
@@ -17,7 +17,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_restrictions.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "base/values.h"
 #include "chrome/browser/crash_upload_list.h"
 #include "chrome/browser/plugins/plugin_prefs.h"
@@ -90,7 +90,7 @@
   virtual void RegisterMessages() OVERRIDE;
 
   // CrashUploadList::Delegate implementation.
-  virtual void OnCrashListAvailable() OVERRIDE;
+  virtual void OnUploadListAvailable() OVERRIDE;
 
   // GpuDataManager::Observer implementation.
   virtual void OnGpuInfoUpdate() OVERRIDE;
@@ -142,7 +142,7 @@
       has_plugin_info_(false) {
   // Request Crash data asynchronously.
   upload_list_ = CrashUploadList::Create(this);
-  upload_list_->LoadCrashListAsynchronously();
+  upload_list_->LoadUploadListAsynchronously();
 
   // Watch for changes in GPUInfo.
   GpuDataManager::GetInstance()->AddObserver(this);
@@ -167,6 +167,7 @@
 
 FlashDOMHandler::~FlashDOMHandler() {
   GpuDataManager::GetInstance()->RemoveObserver(this);
+  upload_list_->ClearDelegate();
 }
 
 void FlashDOMHandler::RegisterMessages() {
@@ -175,7 +176,7 @@
                  base::Unretained(this)));
 }
 
-void FlashDOMHandler::OnCrashListAvailable() {
+void FlashDOMHandler::OnUploadListAvailable() {
   crash_list_available_ = true;
   MaybeRespondToPage();
 }
@@ -295,14 +296,14 @@
   AddPair(list, string16(), "--- Crash data ---");
   bool crash_reporting_enabled = CrashesUI::CrashReportingUIEnabled();
   if (crash_reporting_enabled) {
-    std::vector<CrashUploadList::CrashInfo> crashes;
-    upload_list_->GetUploadedCrashes(10, &crashes);
+    std::vector<CrashUploadList::UploadInfo> crashes;
+    upload_list_->GetUploads(10, &crashes);
 
-    for (std::vector<CrashUploadList::CrashInfo>::iterator i = crashes.begin();
+    for (std::vector<CrashUploadList::UploadInfo>::iterator i = crashes.begin();
          i != crashes.end(); ++i) {
-      string16 crash_string(ASCIIToUTF16(i->crash_id));
+      string16 crash_string(ASCIIToUTF16(i->id));
       crash_string += ASCIIToUTF16(" ");
-      crash_string += base::TimeFormatFriendlyDateAndTime(i->crash_time);
+      crash_string += base::TimeFormatFriendlyDateAndTime(i->time);
       AddPair(list, ASCIIToUTF16("crash id"), crash_string);
     }
   } else {
diff --git a/chrome/browser/ui/webui/help/help_handler.cc b/chrome/browser/ui/webui/help/help_handler.cc
index 3da02fd..3ca356a 100644
--- a/chrome/browser/ui/webui/help/help_handler.cc
+++ b/chrome/browser/ui/webui/help/help_handler.cc
@@ -23,6 +23,7 @@
 #include "chrome/browser/ui/send_feedback_experiment.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "chrome/common/chrome_version_info.h"
+#include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_service.h"
@@ -46,6 +47,9 @@
 #include "chrome/browser/chromeos/settings/cros_settings.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/webui/help/help_utils_chromeos.h"
+#include "chromeos/chromeos_switches.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/power_manager_client.h"
 #include "content/public/browser/browser_thread.h"
 #endif
 
@@ -89,17 +93,21 @@
   }
 }
 
-bool CanChangeReleaseChannel() {
-  // On non managed machines we have local owner who is the only one to change
-  // anything.
-  if (chromeos::UserManager::Get()->IsCurrentUserOwner())
-    return true;
+// Returns true if the device is enterprise managed, false otherwise.
+bool IsEnterpriseManaged() {
+  return g_browser_process->browser_policy_connector()->IsEnterpriseManaged();
+}
+
+// Returns true if current user can change channel, false otherwise.
+bool CanChangeChannel() {
+  bool value = false;
+  chromeos::CrosSettings::Get()->GetBoolean(chromeos::kReleaseChannelDelegated,
+                                            &value);
+
   // On a managed machine we delegate this setting to the users of the same
   // domain only if the policy value is "domain".
-  if (g_browser_process->browser_policy_connector()->IsEnterpriseManaged()) {
-    bool value = false;
-    if (!chromeos::CrosSettings::Get()->GetBoolean(
-            chromeos::kReleaseChannelDelegated, &value) || !value)
+  if (IsEnterpriseManaged()) {
+    if (!value)
       return false;
     // Get the currently logged in user and strip the domain part only.
     std::string domain = "";
@@ -109,6 +117,10 @@
       domain = user.substr(user.find('@') + 1);
     return domain == g_browser_process->browser_policy_connector()->
         GetEnterpriseDomain();
+  } else if (chromeos::UserManager::Get()->IsCurrentUserOwner()) {
+    // On non managed machines we have local owner who is the only one to change
+    // anything. Ensure that ReleaseChannelDelegated is false.
+    return !value;
   }
   return false;
 }
@@ -146,12 +158,22 @@
 #endif
     { "aboutProductDescription", IDS_ABOUT_PRODUCT_DESCRIPTION },
     { "relaunch", IDS_RELAUNCH_BUTTON },
+    { "relaunch", IDS_RELAUNCH_BUTTON },
+#if defined(OS_CHROMEOS)
+    { "relaunchAndPowerwash", IDS_RELAUNCH_AND_POWERWASH_BUTTON },
+#endif
     { "productName", IDS_PRODUCT_NAME },
     { "productCopyright", IDS_ABOUT_VERSION_COPYRIGHT },
     { "updateCheckStarted", IDS_UPGRADE_CHECK_STARTED },
     { "upToDate", IDS_UPGRADE_UP_TO_DATE },
     { "updating", IDS_UPGRADE_UPDATING },
+#if defined(OS_CHROMEOS)
+    { "updatingChannelSwitch", IDS_UPGRADE_UPDATING_CHANNEL_SWITCH },
+#endif
     { "updateAlmostDone", IDS_UPGRADE_SUCCESSFUL_RELAUNCH },
+#if defined(OS_CHROMEOS)
+    { "successfulChannelSwitch", IDS_UPGRADE_SUCCESSFUL_CHANNEL_SWITCH },
+#endif
     { "getHelpWithChrome", IDS_GET_HELP_USING_CHROME },
     { kResourceReportIssue, IDS_REPORT_AN_ISSUE },
 #if defined(OS_CHROMEOS)
@@ -164,6 +186,28 @@
     { "beta", IDS_ABOUT_PAGE_CHANNEL_BETA },
     { "dev", IDS_ABOUT_PAGE_CHANNEL_DEVELOPMENT },
     { "channel-changed", IDS_ABOUT_PAGE_CHANNEL_CHANGED },
+    { "currentChannelStable", IDS_ABOUT_PAGE_CURRENT_CHANNEL_STABLE },
+    { "currentChannelBeta", IDS_ABOUT_PAGE_CURRENT_CHANNEL_BETA },
+    { "currentChannelDev", IDS_ABOUT_PAGE_CURRENT_CHANNEL_DEV },
+    { "currentChannel", IDS_ABOUT_PAGE_CURRENT_CHANNEL },
+    { "channelChangeButton", IDS_ABOUT_PAGE_CHANNEL_CHANGE_BUTTON },
+    { "channelChangeDisallowedMessage",
+      IDS_ABOUT_PAGE_CHANNEL_CHANGE_DISALLOWED_MESSAGE },
+    { "channelChangePageTitle", IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_TITLE },
+    { "channelChangePagePowerwashTitle",
+      IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_POWERWASH_TITLE },
+    { "channelChangePagePowerwashMessage",
+      IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_POWERWASH_MESSAGE },
+    { "channelChangePageDelayedChangeTitle",
+      IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_DELAYED_CHANGE_TITLE },
+    { "channelChangePageUnstableTitle",
+      IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_UNSTABLE_TITLE },
+    { "channelChangePagePowerwashButton",
+      IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_POWERWASH_BUTTON },
+    { "channelChangePageChangeButton",
+      IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_CHANGE_BUTTON },
+    { "channelChangePageCancelButton",
+      IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_CANCEL_BUTTON },
     { "webkit", IDS_WEBKIT },
     { "userAgent", IDS_ABOUT_VERSION_USER_AGENT },
     { "commandLine", IDS_ABOUT_VERSION_COMMAND_LINE },
@@ -206,6 +250,23 @@
       IDS_ABOUT_CROS_VERSION_LICENSE,
       ASCIIToUTF16(chrome::kChromeUIOSCreditsURL));
   source->AddString("productOsLicense", os_license);
+
+  string16 product_name = l10n_util::GetStringUTF16(IDS_PRODUCT_OS_NAME);
+  source->AddString(
+      "channelChangePageDelayedChangeMessage",
+      l10n_util::GetStringFUTF16(
+          IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_DELAYED_CHANGE_MESSAGE,
+          product_name));
+  source->AddString(
+      "channelChangePageUnstableMessage",
+      l10n_util::GetStringFUTF16(
+          IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_UNSTABLE_MESSAGE,
+          product_name));
+
+  if (CommandLine::ForCurrentProcess()->
+      HasSwitch(chromeos::switches::kDisableNewChannelSwitcherUI)) {
+    source->AddBoolean("disableNewChannelSwitcherUI", true);
+  }
 #endif
 
   string16 tos = l10n_util::GetStringFUTF16(
@@ -237,8 +298,10 @@
   web_ui()->RegisterMessageCallback("openHelpPage",
       base::Bind(&HelpHandler::OpenHelpPage, base::Unretained(this)));
 #if defined(OS_CHROMEOS)
-  web_ui()->RegisterMessageCallback("setReleaseTrack",
-      base::Bind(&HelpHandler::SetReleaseTrack, base::Unretained(this)));
+  web_ui()->RegisterMessageCallback("setChannel",
+      base::Bind(&HelpHandler::SetChannel, base::Unretained(this)));
+  web_ui()->RegisterMessageCallback("relaunchAndPowerwash",
+      base::Bind(&HelpHandler::RelaunchAndPowerwash, base::Unretained(this)));
 #endif
 #if defined(OS_MACOSX)
   web_ui()->RegisterMessageCallback("promoteUpdater",
@@ -278,7 +341,7 @@
 
   web_ui()->CallJavascriptFunction(
       "help.HelpPage.updateEnableReleaseChannel",
-      base::FundamentalValue(CanChangeReleaseChannel()));
+      base::FundamentalValue(CanChangeChannel()));
 
   if (g_build_date_string == NULL) {
     // If |g_build_date_string| is |NULL|, the date has not yet been assigned.
@@ -302,8 +365,16 @@
       );
 
 #if defined(OS_CHROMEOS)
-  version_updater_->GetReleaseChannel(
-      base::Bind(&HelpHandler::OnReleaseChannel, base::Unretained(this)));
+  web_ui()->CallJavascriptFunction(
+      "help.HelpPage.updateIsEnterpriseManaged",
+      base::FundamentalValue(IsEnterpriseManaged()));
+  // First argument to GetChannel() is a flag that indicates whether
+  // current channel should be returned (if true) or target channel
+  // (otherwise).
+  version_updater_->GetChannel(true,
+      base::Bind(&HelpHandler::OnCurrentChannel, weak_factory_.GetWeakPtr()));
+  version_updater_->GetChannel(false,
+      base::Bind(&HelpHandler::OnTargetChannel, weak_factory_.GetWeakPtr()));
 #endif
 }
 
@@ -334,27 +405,45 @@
 
 #if defined(OS_CHROMEOS)
 
-void HelpHandler::SetReleaseTrack(const ListValue* args) {
-  if (!CanChangeReleaseChannel()) {
+void HelpHandler::SetChannel(const ListValue* args) {
+  DCHECK(args->GetSize() == 2);
+
+  if (!CanChangeChannel()) {
     LOG(WARNING) << "Non-owner tried to change release track.";
     return;
   }
 
-  const std::string channel = UTF16ToUTF8(ExtractStringValue(args));
-  version_updater_->SetReleaseChannel(channel);
-  // On enterprise machines we can only use SetReleaseChannel to store the
-  // user choice in the lsb-release file but we can not modify the policy blob.
-  // Therefore we only call SetString if the device is locally owned and the
-  // currently logged in user is the owner.
+  base::string16 channel;
+  bool is_powerwash_allowed;
+  if (!args->GetString(0, &channel) ||
+      !args->GetBoolean(1, &is_powerwash_allowed)) {
+    LOG(ERROR) << "Can't parse SetReleaseTrack() args";
+    return;
+  }
+
+  version_updater_->SetChannel(UTF16ToUTF8(channel), is_powerwash_allowed);
   if (chromeos::UserManager::Get()->IsCurrentUserOwner()) {
-    chromeos::CrosSettings::Get()->SetString(chromeos::kReleaseChannel,
-                                             channel);
     // Check for update after switching release channel.
     version_updater_->CheckForUpdate(base::Bind(&HelpHandler::SetUpdateStatus,
                                                 base::Unretained(this)));
   }
 }
 
+void HelpHandler::RelaunchAndPowerwash(const ListValue* args) {
+  DCHECK(args->empty());
+
+  if (IsEnterpriseManaged())
+    return;
+
+  PrefService* prefs = g_browser_process->local_state();
+  prefs->SetBoolean(prefs::kFactoryResetRequested, true);
+  prefs->CommitPendingWrite();
+
+  // Perform sign out. Current chrome process will then terminate, new one will
+  // be launched (as if it was a restart).
+  chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart();
+}
+
 #endif  // defined(OS_CHROMEOS)
 
 void HelpHandler::SetUpdateStatus(VersionUpdater::Status status,
@@ -447,9 +536,14 @@
                                    base::StringValue(firmware));
 }
 
-void HelpHandler::OnReleaseChannel(const std::string& channel) {
+void HelpHandler::OnCurrentChannel(const std::string& channel) {
   web_ui()->CallJavascriptFunction(
-      "help.HelpPage.updateSelectedChannel", base::StringValue(channel));
+      "help.HelpPage.updateCurrentChannel", base::StringValue(channel));
+}
+
+void HelpHandler::OnTargetChannel(const std::string& channel) {
+  web_ui()->CallJavascriptFunction(
+      "help.HelpPage.updateTargetChannel", base::StringValue(channel));
 }
 
 void HelpHandler::ProcessLsbFileInfo(
diff --git a/chrome/browser/ui/webui/help/help_handler.h b/chrome/browser/ui/webui/help/help_handler.h
index 397c023..0f25dab 100644
--- a/chrome/browser/ui/webui/help/help_handler.h
+++ b/chrome/browser/ui/webui/help/help_handler.h
@@ -60,7 +60,10 @@
 
 #if defined(OS_CHROMEOS)
   // Sets the release track version.
-  void SetReleaseTrack(const base::ListValue* args);
+  void SetChannel(const base::ListValue* args);
+
+  // Performs relaunch and powerwash.
+  void RelaunchAndPowerwash(const base::ListValue* args);
 #endif
 
   // Callback method which forwards status updates to the page.
@@ -76,7 +79,8 @@
   // Callbacks from VersionLoader.
   void OnOSVersion(const std::string& version);
   void OnOSFirmware(const std::string& firmware);
-  void OnReleaseChannel(const std::string& channel);
+  void OnCurrentChannel(const std::string& channel);
+  void OnTargetChannel(const std::string& channel);
 
   void ProcessLsbFileInfo(
       base::PlatformFileError rv, const base::PlatformFileInfo& file_info);
diff --git a/chrome/browser/ui/webui/help/help_ui.cc b/chrome/browser/ui/webui/help/help_ui.cc
index f7694ba..0d48728 100644
--- a/chrome/browser/ui/webui/help/help_ui.cc
+++ b/chrome/browser/ui/webui/help/help_ui.cc
@@ -21,6 +21,7 @@
   source->SetJsonPath("strings.js");
   source->SetUseJsonJSFormatV2();
   source->AddResourcePath("help.js", IDR_HELP_JS);
+  source->AddResourcePath("channel_change_page.js", IDR_CHANNEL_CHANGE_PAGE_JS);
   source->SetDefaultResource(IDR_HELP_HTML);
   source->DisableDenyXFrameOptions();
   return source;
diff --git a/chrome/browser/ui/webui/help/version_updater.h b/chrome/browser/ui/webui/help/version_updater.h
index 76e381f..a78444d 100644
--- a/chrome/browser/ui/webui/help/version_updater.h
+++ b/chrome/browser/ui/webui/help/version_updater.h
@@ -75,8 +75,10 @@
   virtual void RelaunchBrowser() const = 0;
 
 #if defined(OS_CHROMEOS)
-  virtual void SetReleaseChannel(const std::string& channel) = 0;
-  virtual void GetReleaseChannel(const ChannelCallback& callback) = 0;
+  virtual void SetChannel(const std::string& channel,
+                          bool is_powerwash_allowed) = 0;
+  virtual void GetChannel(bool get_current_channel,
+                          const ChannelCallback& callback) = 0;
 #endif
 };
 
diff --git a/chrome/browser/ui/webui/help/version_updater_chromeos.cc b/chrome/browser/ui/webui/help/version_updater_chromeos.cc
index 1ea7be5..9532bc4 100644
--- a/chrome/browser/ui/webui/help/version_updater_chromeos.cc
+++ b/chrome/browser/ui/webui/help/version_updater_chromeos.cc
@@ -8,11 +8,13 @@
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
+#include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/login/startup_utils.h"
 #include "chrome/browser/chromeos/login/user_manager.h"
 #include "chrome/browser/chromeos/login/wizard_controller.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
 #include "chrome/browser/chromeos/settings/cros_settings_names.h"
+#include "chrome/browser/policy/browser_policy_connector.h"
 #include "chrome/browser/ui/webui/help/help_utils_chromeos.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/power_manager_client.h"
@@ -125,25 +127,28 @@
   DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart();
 }
 
-void VersionUpdaterCros::SetReleaseChannel(const std::string& channel) {
-  DBusThreadManager::Get()->GetUpdateEngineClient()->SetReleaseTrack(channel);
-  // For local owner set the field in the policy blob too.
-  if (UserManager::Get()->IsCurrentUserOwner())
+void VersionUpdaterCros::SetChannel(const std::string& channel,
+                                    bool is_powerwash_allowed) {
+  // On enterprise machines we can only use SetChannel to store the
+  // user choice in the lsb-release file but we can not modify the
+  // policy blob.  Therefore we only call SetString if the device is
+  // locally owned and the currently logged in user is the owner.
+  if (g_browser_process->browser_policy_connector()->IsEnterpriseManaged()) {
+    DBusThreadManager::Get()->GetUpdateEngineClient()->
+        SetChannel(channel, is_powerwash_allowed);
+  } else if (UserManager::Get()->IsCurrentUserOwner()) {
+    // For local owner set the field in the policy blob.
     CrosSettings::Get()->SetString(chromeos::kReleaseChannel, channel);
+  }
 }
 
-void VersionUpdaterCros::GetReleaseChannel(const ChannelCallback& cb) {
-  channel_callback_ = cb;
-
-  // TODO(jhawkins): Store on this object.
+void VersionUpdaterCros::GetChannel(bool get_current_channel,
+                                    const ChannelCallback& cb) {
   UpdateEngineClient* update_engine_client =
       DBusThreadManager::Get()->GetUpdateEngineClient();
 
-  // Request the channel information. Use the observer to track the help page
-  // handler and ensure it does not get deleted before the callback.
-  update_engine_client->GetReleaseTrack(
-      base::Bind(&VersionUpdaterCros::UpdateSelectedChannel,
-                 weak_ptr_factory_.GetWeakPtr()));
+  // Request the channel information.
+  update_engine_client->GetChannel(get_current_channel, cb);
 }
 
 VersionUpdaterCros::VersionUpdaterCros()
@@ -215,7 +220,3 @@
   if (result == UpdateEngineClient::UPDATE_RESULT_NOTIMPLEMENTED)
     callback_.Run(UPDATED, 0, string16());
 }
-
-void VersionUpdaterCros::UpdateSelectedChannel(const std::string& channel) {
-  channel_callback_.Run(channel);
-}
diff --git a/chrome/browser/ui/webui/help/version_updater_chromeos.h b/chrome/browser/ui/webui/help/version_updater_chromeos.h
index ffd4782..59bbecd 100644
--- a/chrome/browser/ui/webui/help/version_updater_chromeos.h
+++ b/chrome/browser/ui/webui/help/version_updater_chromeos.h
@@ -16,8 +16,10 @@
   // VersionUpdater implementation.
   virtual void CheckForUpdate(const StatusCallback& callback) OVERRIDE;
   virtual void RelaunchBrowser() const OVERRIDE;
-  virtual void SetReleaseChannel(const std::string& channel) OVERRIDE;
-  virtual void GetReleaseChannel(const ChannelCallback& callback) OVERRIDE;
+  virtual void SetChannel(const std::string& channel,
+                          bool is_powerwash_allowed) OVERRIDE;
+  virtual void GetChannel(bool get_current_channel,
+                          const ChannelCallback& callback) OVERRIDE;
 
  protected:
   friend class VersionUpdater;
@@ -34,15 +36,9 @@
   // Callback from UpdateEngineClient::RequestUpdateCheck().
   void OnUpdateCheck(chromeos::UpdateEngineClient::UpdateCheckResult result);
 
-  // Callback from UpdateEngineClient::GetReleaseTrack().
-  void UpdateSelectedChannel(const std::string& channel);
-
   // Callback used to communicate update status to the client.
   StatusCallback callback_;
 
-  // Callback used to communicate current channel to the client.
-  ChannelCallback channel_callback_;
-
   // Last state received via UpdateStatusChanged().
   chromeos::UpdateEngineClient::UpdateStatusOperation last_operation_;
 
diff --git a/chrome/browser/ui/webui/help/version_updater_mac.h b/chrome/browser/ui/webui/help/version_updater_mac.h
index 2b705d7..f2a82bc 100644
--- a/chrome/browser/ui/webui/help/version_updater_mac.h
+++ b/chrome/browser/ui/webui/help/version_updater_mac.h
@@ -8,7 +8,7 @@
 #import <AppKit/AppKit.h>
 
 #include "base/compiler_specific.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/ui/webui/help/version_updater.h"
 
 @class KeystoneObserver;
@@ -50,7 +50,7 @@
   bool show_promote_button_;
 
   // The observer that will receive keystone status updates.
-  scoped_nsobject<KeystoneObserver> keystone_observer_;
+  base::scoped_nsobject<KeystoneObserver> keystone_observer_;
 
   DISALLOW_COPY_AND_ASSIGN(VersionUpdaterMac);
 };
diff --git a/chrome/browser/ui/webui/help/version_updater_win.cc b/chrome/browser/ui/webui/help/version_updater_win.cc
index 59482d2..3d1a7ad 100644
--- a/chrome/browser/ui/webui/help/version_updater_win.cc
+++ b/chrome/browser/ui/webui/help/version_updater_win.cc
@@ -214,13 +214,17 @@
     case UPGRADE_ERROR: {
       content::RecordAction(UserMetricsAction("UpgradeCheck_Error"));
       status = FAILED;
-      if (error_code != GOOGLE_UPDATE_DISABLED_BY_POLICY) {
-        message =
-            l10n_util::GetStringFUTF16Int(IDS_UPGRADE_ERROR, error_code);
-      } else {
+      if (error_code == GOOGLE_UPDATE_DISABLED_BY_POLICY) {
         message =
             l10n_util::GetStringUTF16(IDS_UPGRADE_DISABLED_BY_POLICY);
+      } else if (error_code == GOOGLE_UPDATE_DISABLED_BY_POLICY_AUTO_ONLY) {
+        message =
+            l10n_util::GetStringUTF16(IDS_UPGRADE_DISABLED_BY_POLICY_MANUAL);
+      } else {
+        message =
+            l10n_util::GetStringFUTF16Int(IDS_UPGRADE_ERROR, error_code);
       }
+
       if (!error_message.empty()) {
         message +=
             l10n_util::GetStringFUTF16(IDS_ABOUT_BOX_ERROR_DURING_UPDATE_CHECK,
diff --git a/chrome/browser/ui/webui/history_ui.cc b/chrome/browser/ui/webui/history_ui.cc
index 0b93651..ddcc5bb 100644
--- a/chrome/browser/ui/webui/history_ui.cc
+++ b/chrome/browser/ui/webui/history_ui.cc
@@ -18,7 +18,7 @@
 #include "base/strings/string16.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
@@ -40,6 +40,7 @@
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/webui/favicon_source.h"
+#include "chrome/browser/ui/webui/metrics_handler.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
@@ -962,6 +963,7 @@
 
 HistoryUI::HistoryUI(content::WebUI* web_ui) : WebUIController(web_ui) {
   web_ui->AddMessageHandler(new BrowsingHistoryHandler());
+  web_ui->AddMessageHandler(new MetricsHandler());
 
 // On mobile we deal with foreign sessions differently.
 #if !defined(OS_ANDROID) && !defined(OS_IOS)
diff --git a/chrome/browser/ui/webui/history_ui.h b/chrome/browser/ui/webui/history_ui.h
index 2d67292..318db25 100644
--- a/chrome/browser/ui/webui/history_ui.h
+++ b/chrome/browser/ui/webui/history_ui.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_UI_WEBUI_HISTORY_UI_H_
 
 #include "base/strings/string16.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "base/values.h"
 #include "chrome/browser/common/cancelable_request.h"
 #include "chrome/browser/history/history_service.h"
diff --git a/chrome/browser/ui/webui/identity_internals_ui.cc b/chrome/browser/ui/webui/identity_internals_ui.cc
index 00e03df..e575e49 100644
--- a/chrome/browser/ui/webui/identity_internals_ui.cc
+++ b/chrome/browser/ui/webui/identity_internals_ui.cc
@@ -32,7 +32,7 @@
 const char kScopes[] = "scopes";
 const char kStatus[] = "status";
 const char kTokenExpirationTime[] = "expirationTime";
-const char kTokenId[] = "tokenId";
+const char kAccessToken[] = "accessToken";
 
 // RevokeToken message parameter offsets.
 const int kRevokeTokenExtensionOffset = 0;
@@ -40,6 +40,7 @@
 
 class IdentityInternalsTokenRevoker;
 
+// Class acting as a controller of the chrome://identity-internals WebUI.
 class IdentityInternalsUIMessageHandler : public content::WebUIMessageHandler {
  public:
   IdentityInternalsUIMessageHandler();
@@ -54,26 +55,41 @@
   virtual void RegisterMessages() OVERRIDE;
 
  private:
+  // Gets the name of an extension referred to by |token_cache_key| as a string.
   const std::string GetExtensionName(
       const extensions::IdentityAPI::TokenCacheKey& token_cache_key);
 
+  // Gets a list of scopes specified in |token_cache_key| and returns a pointer
+  // to a ListValue containing the scopes. The caller gets ownership of the
+  // returned object.
   ListValue* GetScopes(
       const extensions::IdentityAPI::TokenCacheKey& token_cache_key);
 
+  // Gets a localized status of the access token in |token_cache_value|.
   const base::string16 GetStatus(
       const extensions::IdentityTokenCacheValue& token_cache_value);
 
+  // Gets a string representation of an expiration time of the access token in
+  // |token_cache_value|.
   const std::string GetExpirationTime(
       const extensions::IdentityTokenCacheValue& token_cache_value);
 
+  // Converts a pair of |token_cache_key| and |token_cache_value| to a
+  // DictionaryValue object with corresponding information in a localized and
+  // readable form and returns a pointer to created object. Caller gets the
+  // ownership of the returned object.
   DictionaryValue* GetInfoForToken(
       const extensions::IdentityAPI::TokenCacheKey& token_cache_key,
       const extensions::IdentityTokenCacheValue& token_cache_value);
 
+  // Gets all of the tokens stored in IdentityAPI token cache and returns them
+  // to the caller using Javascript callback function
+  // |identity_internals.returnTokens()|.
   void GetInfoForAllTokens(const ListValue* args);
 
   // Initiates revoking of the token, based on the extension ID and token
-  // passed as entries in the args list.
+  // passed as entries in the |args| list. Updates the caller of completion
+  // using Javascript callback function |identity_internals.tokenRevokeDone()|.
   void RevokeToken(const ListValue* args);
 
   // A vector of token revokers that are currently revoking tokens.
@@ -192,7 +208,7 @@
   token_data->SetString(kExtensionName, GetExtensionName(token_cache_key));
   token_data->Set(kScopes, GetScopes(token_cache_key));
   token_data->SetString(kStatus, GetStatus(token_cache_value));
-  token_data->SetString(kTokenId, token_cache_value.token());
+  token_data->SetString(kAccessToken, token_cache_value.token());
   token_data->SetString(kTokenExpirationTime,
                         GetExpirationTime(token_cache_value));
   return token_data;
@@ -262,8 +278,8 @@
   // Localized strings
   html_source->AddLocalizedString("tokenCacheHeader",
       IDS_IDENTITY_INTERNALS_TOKEN_CACHE_TEXT);
-  html_source->AddLocalizedString("tokenId",
-      IDS_IDENTITY_INTERNALS_TOKEN_ID);
+  html_source->AddLocalizedString("accessToken",
+      IDS_IDENTITY_INTERNALS_ACCESS_TOKEN);
   html_source->AddLocalizedString("extensionName",
       IDS_IDENTITY_INTERNALS_EXTENSION_NAME);
   html_source->AddLocalizedString("extensionId",
diff --git a/chrome/browser/ui/webui/identity_internals_ui_browsertest.cc b/chrome/browser/ui/webui/identity_internals_ui_browsertest.cc
index ec45499..aba132d 100644
--- a/chrome/browser/ui/webui/identity_internals_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/identity_internals_ui_browsertest.cc
@@ -5,7 +5,7 @@
 #include "chrome/browser/ui/webui/identity_internals_ui_browsertest.h"
 
 #include "base/strings/string_number_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/extensions/api/identity/identity_api.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
diff --git a/chrome/browser/ui/webui/identity_internals_ui_browsertest.js b/chrome/browser/ui/webui/identity_internals_ui_browsertest.js
index 09163b3..67a6cb6 100644
--- a/chrome/browser/ui/webui/identity_internals_ui_browsertest.js
+++ b/chrome/browser/ui/webui/identity_internals_ui_browsertest.js
@@ -79,8 +79,8 @@
    * @param {Element} tokenEntry Display element holding token information.
    * @return {string} Token ID of the token.
    */
-  getTokenId: function(tokenEntry) {
-    return tokenEntry.querySelector('.token-id').innerText;
+  getAccessToken: function(tokenEntry) {
+    return tokenEntry.querySelector('.access-token').innerText;
   },
 
   /**
@@ -135,7 +135,7 @@
   expectEquals('Store', this.getExtensionName(tokenListEntries[0]));
   expectEquals('ahfgeienlihckogmohjhadlkjgocpleb',
                this.getExtensionId(tokenListEntries[0]));
-  expectEquals('store_token', this.getTokenId(tokenListEntries[0]));
+  expectEquals('store_token', this.getAccessToken(tokenListEntries[0]));
   expectEquals('Token Present', this.getTokenStatus(tokenListEntries[0]));
   expectLT(this.getExpirationTime(tokenListEntries[0]) - new Date(),
            3600 * 1000);
@@ -158,8 +158,8 @@
       tokenListEntries[0].querySelector('.extension-name').innerText);
   expectEquals(this.getExtensionId(tokenListEntries[0]),
       tokenListEntries[0].querySelector('.extension-id').innerText);
-  expectEquals(this.getTokenId(tokenListEntries[0]),
-      tokenListEntries[0].querySelector('.token-id').innerText);
+  expectEquals(this.getAccessToken(tokenListEntries[0]),
+      tokenListEntries[0].querySelector('.access-token').innerText);
   expectEquals(this.getTokenStatus(tokenListEntries[0]),
       tokenListEntries[0].querySelector('.token-status').innerText);
   expectEquals(this.getExpirationTime(tokenListEntries[0]),
@@ -200,7 +200,7 @@
   expectEquals('', this.getExtensionName(tokenListEntries[0]));
   expectEquals('extension0',
                this.getExtensionId(tokenListEntries[0]));
-  expectEquals('token0', this.getTokenId(tokenListEntries[0]));
+  expectEquals('token0', this.getAccessToken(tokenListEntries[0]));
   expectEquals('Token Present', this.getTokenStatus(tokenListEntries[0]));
   expectLT(this.getExpirationTime(tokenListEntries[0]) - new Date(),
            3600 * 1000);
@@ -212,7 +212,7 @@
   expectEquals('', this.getExtensionName(tokenListEntries[1]));
   expectEquals('extension1',
                this.getExtensionId(tokenListEntries[1]));
-  expectEquals('token1', this.getTokenId(tokenListEntries[1]));
+  expectEquals('token1', this.getAccessToken(tokenListEntries[1]));
   expectEquals('Token Present', this.getTokenStatus(tokenListEntries[1]));
   expectLT(this.getExpirationTime(tokenListEntries[1]) - new Date(),
            3600 * 1000);
@@ -243,13 +243,13 @@
   expectEquals(2, tokenListBefore.length);
   var tokenRevokeDone = identity_internals.tokenRevokeDone;
   identity_internals.tokenRevokeDone = this.continueTest(
-      WhenTestDone.ALWAYS, function (tokenIds) {
-        tokenRevokeDone.call(identity_internals, tokenIds);
+      WhenTestDone.ALWAYS, function (accessTokens) {
+        tokenRevokeDone.call(identity_internals, accessTokens);
         identity_internals.tokenRevokeDone = tokenRevokeDone;
         var tokenListAfter = this.getTokens();
         expectEquals(1, tokenListAfter.length);
-        expectEquals(this.getTokenId(tokenListBefore[0]),
-                     this.getTokenId(tokenListAfter[0]));
+        expectEquals(this.getAccessToken(tokenListBefore[0]),
+                     this.getAccessToken(tokenListAfter[0]));
       }.bind(this));
   this.getRevokeButton(tokenListBefore[1]).click();
 });
diff --git a/chrome/browser/ui/webui/inline_login_ui.cc b/chrome/browser/ui/webui/inline_login_ui.cc
index 55f3a1b..8683184 100644
--- a/chrome/browser/ui/webui/inline_login_ui.cc
+++ b/chrome/browser/ui/webui/inline_login_ui.cc
@@ -13,6 +13,7 @@
 #include "chrome/browser/signin/token_service.h"
 #include "chrome/browser/signin/token_service_factory.h"
 #include "chrome/browser/ui/sync/one_click_signin_sync_starter.h"
+#include "chrome/browser/ui/sync/sync_promo_ui.h"
 #include "chrome/common/url_constants.h"
 #include "content/public/browser/web_ui.h"
 #include "content/public/browser/web_ui_data_source.h"
@@ -131,7 +132,8 @@
         UTF16ToASCII(email), UTF16ToASCII(password),
         OneClickSigninSyncStarter::SYNC_WITH_DEFAULT_SETTINGS,
         true /* force_same_tab_navigation */,
-        OneClickSigninSyncStarter::NO_CONFIRMATION);
+        OneClickSigninSyncStarter::NO_CONFIRMATION,
+        SyncPromoUI::SOURCE_UNKNOWN);
     web_ui()->CallJavascriptFunction("inline.login.closeDialog");
 #endif
   }
diff --git a/chrome/browser/ui/webui/instant_ui.cc b/chrome/browser/ui/webui/instant_ui.cc
index 289e83d..d399753 100644
--- a/chrome/browser/ui/webui/instant_ui.cc
+++ b/chrome/browser/ui/webui/instant_ui.cc
@@ -7,7 +7,7 @@
 #include "base/bind.h"
 #include "base/prefs/pref_service.h"
 #include "base/strings/stringprintf.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
diff --git a/chrome/browser/ui/webui/media/webrtc_logs_ui.cc b/chrome/browser/ui/webui/media/webrtc_logs_ui.cc
new file mode 100644
index 0000000..54de606
--- /dev/null
+++ b/chrome/browser/ui/webui/media/webrtc_logs_ui.cc
@@ -0,0 +1,196 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/media/webrtc_logs_ui.h"
+
+#include <vector>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/i18n/time_formatting.h"
+#include "base/memory/ref_counted_memory.h"
+#include "base/prefs/pref_service.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/media/webrtc_log_upload_list.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/chrome_version_info.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/url_constants.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_ui.h"
+#include "content/public/browser/web_ui_data_source.h"
+#include "content/public/browser/web_ui_message_handler.h"
+#include "grit/browser_resources.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/settings/cros_settings.h"
+#endif
+
+using content::WebContents;
+using content::WebUIMessageHandler;
+
+namespace {
+
+content::WebUIDataSource* CreateWebRtcLogsUIHTMLSource() {
+  content::WebUIDataSource* source =
+      content::WebUIDataSource::Create(chrome::kChromeUIWebRtcLogsHost);
+  source->SetUseJsonJSFormatV2();
+
+  source->AddLocalizedString("webrtcLogsTitle", IDS_WEBRTC_LOGS_TITLE);
+  source->AddLocalizedString("webrtcLogCountFormat",
+                             IDS_WEBRTC_LOGS_LOG_COUNT_BANNER_FORMAT);
+  source->AddLocalizedString("webrtcLogHeaderFormat",
+                             IDS_WEBRTC_LOGS_LOG_HEADER_FORMAT);
+  source->AddLocalizedString("webrtcLogTimeFormat",
+                             IDS_WEBRTC_LOGS_LOG_TIME_FORMAT);
+  source->AddLocalizedString("bugLinkText", IDS_WEBRTC_LOGS_BUG_LINK_LABEL);
+  source->AddLocalizedString("noLogsMessage",
+                             IDS_WEBRTC_LOGS_NO_LOGS_MESSAGE);
+  source->AddLocalizedString("disabledHeader", IDS_WEBRTC_LOGS_DISABLED_HEADER);
+  source->AddLocalizedString("disabledMessage",
+                             IDS_WEBRTC_LOGS_DISABLED_MESSAGE);
+  source->SetJsonPath("strings.js");
+  source->AddResourcePath("webrtc_logs.js", IDR_WEBRTC_LOGS_JS);
+  source->SetDefaultResource(IDR_WEBRTC_LOGS_HTML);
+  return source;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// WebRtcLogsDOMHandler
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// The handler for Javascript messages for the chrome://webrtc-logs/ page.
+class WebRtcLogsDOMHandler : public WebUIMessageHandler,
+                             public WebRtcLogUploadList::Delegate {
+ public:
+  explicit WebRtcLogsDOMHandler();
+  virtual ~WebRtcLogsDOMHandler();
+
+  // WebUIMessageHandler implementation.
+  virtual void RegisterMessages() OVERRIDE;
+
+  // WebRtcLogUploadList::Delegate implemenation.
+  virtual void OnUploadListAvailable() OVERRIDE;
+
+ private:
+  // Asynchronously fetches the list of upload WebRTC logs. Called from JS.
+  void HandleRequestWebRtcLogs(const ListValue* args);
+
+  // Sends the recently uploaded logs list JS.
+  void UpdateUI();
+
+  // Loads, parses and stores the list of uploaded WebRTC logs.
+  scoped_refptr<WebRtcLogUploadList> upload_list_;
+
+  // Set when |upload_list_| has finished populating the list of logs.
+  bool list_available_;
+
+  // Set when the webpage wants to update the list (on the webpage) but
+  // |upload_list_| hasn't finished populating the list of logs yet.
+  bool js_request_pending_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebRtcLogsDOMHandler);
+};
+
+WebRtcLogsDOMHandler::WebRtcLogsDOMHandler()
+    : list_available_(false), js_request_pending_(false) {
+  upload_list_ = WebRtcLogUploadList::Create(this);
+}
+
+WebRtcLogsDOMHandler::~WebRtcLogsDOMHandler() {
+  upload_list_->ClearDelegate();
+}
+
+void WebRtcLogsDOMHandler::RegisterMessages() {
+  upload_list_->LoadUploadListAsynchronously();
+
+  web_ui()->RegisterMessageCallback("requestWebRtcLogsList",
+      base::Bind(&WebRtcLogsDOMHandler::HandleRequestWebRtcLogs,
+                 base::Unretained(this)));
+}
+
+void WebRtcLogsDOMHandler::HandleRequestWebRtcLogs(const ListValue* args) {
+  if (!WebRtcLogsUI::WebRtcLogsUIEnabled() || list_available_)
+    UpdateUI();
+  else
+    js_request_pending_ = true;
+}
+
+void WebRtcLogsDOMHandler::OnUploadListAvailable() {
+  list_available_ = true;
+  if (js_request_pending_)
+    UpdateUI();
+}
+
+void WebRtcLogsDOMHandler::UpdateUI() {
+  bool webrtc_logs_enabled = WebRtcLogsUI::WebRtcLogsUIEnabled();
+  ListValue upload_list;
+
+  if (webrtc_logs_enabled) {
+    std::vector<WebRtcLogUploadList::UploadInfo> uploads;
+    upload_list_->GetUploads(50, &uploads);
+
+    for (std::vector<WebRtcLogUploadList::UploadInfo>::iterator i =
+         uploads.begin(); i != uploads.end(); ++i) {
+      DictionaryValue* upload = new DictionaryValue();
+      upload->SetString("id", i->id);
+      upload->SetString("time", base::TimeFormatFriendlyDateAndTime(i->time));
+      upload_list.Append(upload);
+    }
+  }
+
+  base::FundamentalValue enabled(webrtc_logs_enabled);
+
+  const chrome::VersionInfo version_info;
+  base::StringValue version(version_info.Version());
+
+  web_ui()->CallJavascriptFunction("updateWebRtcLogsList", enabled, upload_list,
+                                   version);
+}
+
+}  // namespace
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// WebRtcLogsUI
+//
+///////////////////////////////////////////////////////////////////////////////
+
+WebRtcLogsUI::WebRtcLogsUI(content::WebUI* web_ui) : WebUIController(web_ui) {
+  web_ui->AddMessageHandler(new WebRtcLogsDOMHandler());
+
+  // Set up the chrome://webrtc-logs/ source.
+  Profile* profile = Profile::FromWebUI(web_ui);
+  content::WebUIDataSource::Add(profile, CreateWebRtcLogsUIHTMLSource());
+}
+
+// static
+bool WebRtcLogsUI::WebRtcLogsUIEnabled() {
+#if defined(GOOGLE_CHROME_BUILD)
+#if defined(OS_CHROMEOS)
+  bool reporting_enabled = false;
+  chromeos::CrosSettings::Get()->GetBoolean(chromeos::kStatsReportingPref,
+                                            &reporting_enabled);
+  return reporting_enabled;
+#elif defined(OS_ANDROID)
+  // Android has it's own setings for metrics / crash uploading.
+  PrefService* prefs = g_browser_process->local_state();
+  return prefs->GetBoolean(prefs::kCrashReportingEnabled);
+#else
+  PrefService* prefs = g_browser_process->local_state();
+  return prefs->GetBoolean(prefs::kMetricsReportingEnabled);
+#endif
+#else
+  return false;
+#endif
+}
diff --git a/chrome/browser/ui/webui/media/webrtc_logs_ui.h b/chrome/browser/ui/webui/media/webrtc_logs_ui.h
new file mode 100644
index 0000000..3c37548
--- /dev/null
+++ b/chrome/browser/ui/webui/media/webrtc_logs_ui.h
@@ -0,0 +1,27 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_MEDIA_WEBRTC_LOGS_UI_H_
+#define CHROME_BROWSER_UI_WEBUI_MEDIA_WEBRTC_LOGS_UI_H_
+
+#include "content/public/browser/web_ui_controller.h"
+#include "ui/base/layout.h"
+
+namespace base {
+class RefCountedMemory;
+}
+
+// The WebUI handler for chrome://webrtc-logs.
+class WebRtcLogsUI : public content::WebUIController {
+ public:
+  explicit WebRtcLogsUI(content::WebUI* web_ui);
+
+  // Whether WebRTC logs UI has been enabled.
+  static bool WebRtcLogsUIEnabled();
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(WebRtcLogsUI);
+};
+
+#endif  // CHROME_BROWSER_UI_WEBUI_MEDIA_WEBRTC_LOGS_UI_H_
diff --git a/chrome/browser/ui/webui/memory_internals/memory_internals_proxy.cc b/chrome/browser/ui/webui/memory_internals/memory_internals_proxy.cc
index 3c0e244..accb3a5 100644
--- a/chrome/browser/ui/webui/memory_internals/memory_internals_proxy.cc
+++ b/chrome/browser/ui/webui/memory_internals/memory_internals_proxy.cc
@@ -4,42 +4,38 @@
 
 #include "chrome/browser/ui/webui/memory_internals/memory_internals_proxy.h"
 
+#include <set>
 #include <string>
 #include <vector>
 
 #include "base/bind.h"
 #include "base/strings/string16.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
 #include "base/sys_info.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/defaults.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/extensions/extension_system.h"
 #include "chrome/browser/memory_details.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/renderer_host/chrome_render_message_filter.h"
+#include "chrome/browser/ui/tab_contents/tab_contents_iterator.h"
 #include "chrome/browser/ui/webui/memory_internals/memory_internals_handler.h"
-#include "chrome/common/extensions/extension.h"
-#include "chrome/common/extensions/extension_set.h"
-#include "content/public/browser/url_data_source.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "chrome/common/render_messages.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
-#include "grit/chromium_strings.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/webui/jstemplate_builder.h"
-#include "ui/webui/web_ui_util.h"
 
 using content::BrowserThread;
 
 namespace {
 
-class BrowserProcessDetails : public MemoryDetails {
+class ProcessDetails : public MemoryDetails {
  public:
   typedef base::Callback<void(const ProcessData&)> DataCallback;
-  explicit BrowserProcessDetails(const DataCallback& callback)
+  explicit ProcessDetails(const DataCallback& callback)
       : callback_(callback) {}
+  // MemoryDetails:
   virtual void OnDetailsAvailable() OVERRIDE {
     const std::vector<ProcessData>& browser_processes = processes();
     // [0] means Chrome.
@@ -47,16 +43,75 @@
   }
 
  private:
-  virtual ~BrowserProcessDetails() {}
+  virtual ~ProcessDetails() {}
 
   DataCallback callback_;
 
-  DISALLOW_COPY_AND_ASSIGN(BrowserProcessDetails);
+  DISALLOW_COPY_AND_ASSIGN(ProcessDetails);
 };
 
 }  // namespace
 
-MemoryInternalsProxy::MemoryInternalsProxy() {}
+class RendererDetails : public content::NotificationObserver {
+ public:
+  typedef base::Callback<void(const base::ProcessId pid,
+                              const size_t v8_allocated,
+                              const size_t v8_used)> V8DataCallback;
+
+  explicit RendererDetails(const V8DataCallback& callback)
+      : callback_(callback) {
+    registrar_.Add(this, chrome::NOTIFICATION_RENDERER_V8_HEAP_STATS_COMPUTED,
+                   content::NotificationService::AllSources());
+  }
+  virtual ~RendererDetails() {}
+
+  void Request() {
+    for (std::set<content::WebContents*>::iterator iter = web_contents_.begin();
+         iter != web_contents_.end(); ++iter)
+      (*iter)->GetRenderViewHost()->Send(new ChromeViewMsg_GetV8HeapStats);
+  }
+  void AddWebContents(content::WebContents* content) {
+    web_contents_.insert(content);
+  }
+  void Clear() {
+    web_contents_.clear();
+  }
+  void RemoveWebContents() {
+    // We don't have to detect which content is the caller of this method.
+    if (!web_contents_.empty())
+      web_contents_.erase(web_contents_.begin());
+  }
+  int IsClean() {
+    return web_contents_.empty();
+  }
+
+ private:
+  // NotificationObserver:
+  virtual void Observe(int type,
+                       const content::NotificationSource& source,
+                       const content::NotificationDetails& details) OVERRIDE {
+    const base::ProcessId* pid =
+        content::Source<const base::ProcessId>(source).ptr();
+    const ChromeRenderMessageFilter::V8HeapStatsDetails* v8_heap =
+        content::Details<const ChromeRenderMessageFilter::V8HeapStatsDetails>(
+            details).ptr();
+    callback_.Run(*pid,
+                  v8_heap->v8_memory_allocated(),
+                  v8_heap->v8_memory_used());
+  }
+
+  V8DataCallback callback_;
+  content::NotificationRegistrar registrar_;
+  std::set<content::WebContents*> web_contents_;  // This class does not own
+
+  DISALLOW_COPY_AND_ASSIGN(RendererDetails);
+};
+
+MemoryInternalsProxy::MemoryInternalsProxy()
+    : information_(new base::DictionaryValue()),
+      renderer_details_(new RendererDetails(
+          base::Bind(&MemoryInternalsProxy::OnV8MemoryUpdate, this))) {
+}
 
 void MemoryInternalsProxy::Attach(MemoryInternalsHandler* handler) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -71,7 +126,7 @@
 void MemoryInternalsProxy::GetInfo(const base::ListValue* list) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-  scoped_refptr<BrowserProcessDetails> browsers(new BrowserProcessDetails(
+  scoped_refptr<ProcessDetails> browsers(new ProcessDetails(
       base::Bind(&MemoryInternalsProxy::OnDetailsAvailable, this)));
   browsers->StartFetch(MemoryDetails::SKIP_USER_METRICS);
 }
@@ -86,43 +141,80 @@
     handler_->OnUpdate(update);
 }
 
+void MemoryInternalsProxy::OnV8MemoryUpdate(const base::ProcessId pid,
+                                            const size_t v8_allocated,
+                                            const size_t v8_used) {
+  base::ListValue* processes;
+  if (!information_->GetList("processes", &processes))
+    return;
+
+  const size_t size = processes->GetSize();
+  for (size_t i = 0; i < size; ++i) {
+    base::DictionaryValue* process;
+    processes->GetDictionary(i, &process);
+    int id;
+    if (!process->GetInteger("pid", &id) || id != static_cast<int>(pid))
+      continue;
+    process->SetInteger("v8_alloc", v8_allocated);
+    process->SetInteger("v8_used", v8_used);
+    break;
+  }
+
+  renderer_details_->RemoveWebContents();
+  if (renderer_details_->IsClean())
+    CallJavaScriptFunctionOnUIThread("g_main_view.onSetSnapshot", information_);
+}
+
+void MemoryInternalsProxy::RequestV8MemoryUpdate() {
+  renderer_details_->Clear();
+#if !defined(OS_ANDROID)
+  for (TabContentsIterator iter; !iter.done(); iter.Next())
+    renderer_details_->AddWebContents(*iter);
+#endif
+
+  // if no contents are shown, update UI.
+  if (renderer_details_->IsClean())
+    CallJavaScriptFunctionOnUIThread("g_main_view.onSetSnapshot", information_);
+
+  renderer_details_->Request();
+}
+
 void MemoryInternalsProxy::OnDetailsAvailable(const ProcessData& browser) {
-  base::DictionaryValue details;
+  information_->Clear();
 
   // System information, which is independent from processes.
-  details.SetInteger("uptime", base::SysInfo::Uptime());
-  details.SetString("os", base::SysInfo::OperatingSystemName());
-  details.SetString("os_version", base::SysInfo::OperatingSystemVersion());
+  information_->SetInteger("uptime", base::SysInfo::Uptime());
+  information_->SetString("os", base::SysInfo::OperatingSystemName());
+  information_->SetString("os_version",
+                          base::SysInfo::OperatingSystemVersion());
 
   base::ListValue* processes = new ListValue();
   base::ListValue* extensions = new ListValue();
-  details.Set("processes", processes);
-  details.Set("extensions", extensions);
+  information_->Set("processes", processes);
+  information_->Set("extensions", extensions);
   for (ProcessMemoryInformationList::const_iterator
            iter = browser.processes.begin();
        iter != browser.processes.end(); ++iter) {
-    base::DictionaryValue* info = new DictionaryValue();
-
-    // Information from MemoryDetails.
-    info->SetInteger("pid", iter->pid);
-    info->SetString("type",
-                    ProcessMemoryInformation::GetFullTypeNameInEnglish(
-                        iter->process_type, iter->renderer_type));
-    info->SetInteger("memory_private",
-                     iter->working_set.priv + iter->committed.priv);
-    base::ListValue* titles = new ListValue();
-    info->Set("titles", titles);
-    for (size_t i = 0; i < iter->titles.size(); ++i)
-      titles->AppendString(iter->titles[i]);
-
+    base::DictionaryValue* process = new DictionaryValue();
     if (iter->process_type == content::PROCESS_TYPE_RENDERER &&
         iter->renderer_type == ProcessMemoryInformation::RENDERER_EXTENSION)
-      extensions->Append(info);
+      extensions->Append(process);
     else
-      processes->Append(info);
+      processes->Append(process);
+
+    // Information from MemoryDetails.
+    process->SetInteger("pid", iter->pid);
+    process->SetString("type",
+                    ProcessMemoryInformation::GetFullTypeNameInEnglish(
+                        iter->process_type, iter->renderer_type));
+    process->SetInteger("memory_private", iter->working_set.priv);
+    base::ListValue* titles = new ListValue();
+    process->Set("titles", titles);
+    for (size_t i = 0; i < iter->titles.size(); ++i)
+      titles->AppendString(iter->titles[i]);
   }
 
-  CallJavaScriptFunctionOnUIThread("g_main_view.onSetSnapshot", &details);
+  RequestV8MemoryUpdate();
 }
 
 void MemoryInternalsProxy::CallJavaScriptFunctionOnUIThread(
diff --git a/chrome/browser/ui/webui/memory_internals/memory_internals_proxy.h b/chrome/browser/ui/webui/memory_internals/memory_internals_proxy.h
index f3e4b84..5c5ee78 100644
--- a/chrome/browser/ui/webui/memory_internals/memory_internals_proxy.h
+++ b/chrome/browser/ui/webui/memory_internals/memory_internals_proxy.h
@@ -9,10 +9,12 @@
 
 #include "base/memory/ref_counted.h"
 #include "base/strings/string16.h"
+#include "base/values.h"
 #include "chrome/browser/memory_details.h"
 #include "content/public/browser/browser_thread.h"
 
 class MemoryInternalsHandler;
+class RendererDetails;
 
 namespace base {
 class ListValue;
@@ -21,7 +23,7 @@
 
 class MemoryInternalsProxy
     : public base::RefCountedThreadSafe<
-        MemoryInternalsProxy, content::BrowserThread::DeleteOnUIThread> {
+          MemoryInternalsProxy, content::BrowserThread::DeleteOnUIThread> {
  public:
   MemoryInternalsProxy();
 
@@ -43,6 +45,12 @@
   // Sends a message from IO thread to update UI on UI thread.
   void UpdateUIOnUIThread(const string16& update);
 
+  // Measure memory usage of V8.
+  void OnV8MemoryUpdate(const base::ProcessId pid,
+                        const size_t v8_allocated,
+                        const size_t v8_used);
+  void RequestV8MemoryUpdate();
+
   // Convert memory information into DictionaryValue format.
   void OnDetailsAvailable(const ProcessData& browser);
 
@@ -51,6 +59,8 @@
                                         base::Value* args);
 
   MemoryInternalsHandler* handler_;
+  base::DictionaryValue* information_;
+  RendererDetails* renderer_details_;
 
   DISALLOW_COPY_AND_ASSIGN(MemoryInternalsProxy);
 };
diff --git a/chrome/browser/ui/webui/net_internals/net_internals_ui.cc b/chrome/browser/ui/webui/net_internals/net_internals_ui.cc
index 96b3f22..7b65a8e 100644
--- a/chrome/browser/ui/webui/net_internals/net_internals_ui.cc
+++ b/chrome/browser/ui/webui/net_internals/net_internals_ui.cc
@@ -61,6 +61,7 @@
 #include "grit/generated_resources.h"
 #include "grit/net_internals_resources.h"
 #include "net/base/net_errors.h"
+#include "net/base/net_log_logger.h"
 #include "net/base/net_util.h"
 #include "net/disk_cache/disk_cache.h"
 #include "net/dns/host_cache.h"
@@ -104,11 +105,6 @@
 // sent to the page at once, which reduces context switching and CPU usage.
 const int kNetLogEventDelayMilliseconds = 100;
 
-// about:net-internals will not even attempt to load a log dump when it
-// encounters a new version.  This should be incremented when significant
-// changes are made that will invalidate the old loading code.
-const int kLogFormatVersion = 1;
-
 // Returns the HostCache for |context|'s primary HostResolver, or NULL if
 // there is none.
 net::HostCache* GetHostResolverCache(net::URLRequestContext* context) {
@@ -327,7 +323,7 @@
 void CloseAndDeleteDebugLogFile(PassPlatformFile pass_platform_file,
                                 const base::FilePath& file_path) {
   CloseDebugLogFile(pass_platform_file);
-  file_util::Delete(file_path, false);
+  base::Delete(file_path, false);
 }
 
 // Called upon completion of |WriteDebugLogToFile|. Closes file
@@ -1572,23 +1568,32 @@
   std::string error;
   if (!chromeos::onc::ParseAndValidateOncForImport(
           onc_blob, onc_source, passcode, &network_configs, &certificates)) {
-    error = "Errors occurred during the ONC parsing.";
+    error = "Errors occurred during the ONC parsing. ";
+    LOG(ERROR) << error;
+  }
+
+  chromeos::CertificateHandler::CertsByGUID imported_server_and_ca_certs;
+  chromeos::CertificateHandler certificate_handler;
+  if (!certificate_handler.ImportCertificates(certificates, onc_source, NULL,
+                                              &imported_server_and_ca_certs)) {
+    error += "Some certificates couldn't be imported. ";
+    LOG(ERROR) << error;
+  }
+
+  if (!chromeos::onc::ResolveServerCertRefsInNetworks(
+          imported_server_and_ca_certs, &network_configs)) {
+    error += "Some certificate references could not be resolved. ";
     LOG(ERROR) << error;
   }
 
   chromeos::NetworkLibrary* network_library =
       chromeos::CrosLibrary::Get()->GetNetworkLibrary();
   network_library->LoadOncNetworks(network_configs, onc_source);
+
   // Now that we've added the networks, we need to rescan them so they'll be
   // available from the menu more immediately.
   network_library->RequestNetworkScan();
 
-  chromeos::CertificateHandler certificate_handler;
-  if (!certificate_handler.ImportCertificates(certificates, onc_source, NULL)) {
-    error += "Some certificates couldn't be imported.";
-    LOG(ERROR) << error;
-  }
-
   SendJavascriptCommand("receivedONCFileParse",
                         Value::CreateStringValue(error));
 }
@@ -1854,14 +1859,8 @@
 
 // static
 Value* NetInternalsUI::GetConstants() {
-  DictionaryValue* constants_dict = new DictionaryValue();
-
-  // Version of the file format.
-  constants_dict->SetInteger("logFormatVersion", kLogFormatVersion);
-
-  // Add a dictionary with information on the relationship between event type
-  // enums and their symbolic names.
-  constants_dict->Set("logEventTypes", net::NetLog::GetEventTypesAsValue());
+  DictionaryValue* constants_dict = net::NetLogLogger::GetConstants();
+  DCHECK(constants_dict);
 
   // Add a dictionary with the version of the client and its command line
   // arguments.
@@ -1890,111 +1889,6 @@
     constants_dict->Set("clientInfo", dict);
   }
 
-  // Add a dictionary with information about the relationship between load flag
-  // enums and their symbolic names.
-  {
-    DictionaryValue* dict = new DictionaryValue();
-
-#define LOAD_FLAG(label, value) \
-    dict->SetInteger(# label, static_cast<int>(value));
-#include "net/base/load_flags_list.h"
-#undef LOAD_FLAG
-
-    constants_dict->Set("loadFlag", dict);
-  }
-
-  // Add a dictionary with information about the relationship between load state
-  // enums and their symbolic names.
-  {
-    DictionaryValue* dict = new DictionaryValue();
-
-#define LOAD_STATE(label) \
-    dict->SetInteger(# label, net::LOAD_STATE_ ## label);
-#include "net/base/load_states_list.h"
-#undef LOAD_STATE
-
-    constants_dict->Set("loadState", dict);
-  }
-
-  // Add information on the relationship between net error codes and their
-  // symbolic names.
-  {
-    DictionaryValue* dict = new DictionaryValue();
-
-#define NET_ERROR(label, value) \
-    dict->SetInteger(# label, static_cast<int>(value));
-#include "net/base/net_error_list.h"
-#undef NET_ERROR
-
-    constants_dict->Set("netError", dict);
-  }
-
-  // Information about the relationship between event phase enums and their
-  // symbolic names.
-  {
-    DictionaryValue* dict = new DictionaryValue();
-
-    dict->SetInteger("PHASE_BEGIN", net::NetLog::PHASE_BEGIN);
-    dict->SetInteger("PHASE_END", net::NetLog::PHASE_END);
-    dict->SetInteger("PHASE_NONE", net::NetLog::PHASE_NONE);
-
-    constants_dict->Set("logEventPhase", dict);
-  }
-
-  // Information about the relationship between source type enums and
-  // their symbolic names.
-  constants_dict->Set("logSourceType", net::NetLog::GetSourceTypesAsValue());
-
-  // Information about the relationship between LogLevel enums and their
-  // symbolic names.
-  {
-    DictionaryValue* dict = new DictionaryValue();
-
-    dict->SetInteger("LOG_ALL", net::NetLog::LOG_ALL);
-    dict->SetInteger("LOG_ALL_BUT_BYTES", net::NetLog::LOG_ALL_BUT_BYTES);
-    dict->SetInteger("LOG_BASIC", net::NetLog::LOG_BASIC);
-
-    constants_dict->Set("logLevelType", dict);
-  }
-
-  // Information about the relationship between address family enums and
-  // their symbolic names.
-  {
-    DictionaryValue* dict = new DictionaryValue();
-
-    dict->SetInteger("ADDRESS_FAMILY_UNSPECIFIED",
-                     net::ADDRESS_FAMILY_UNSPECIFIED);
-    dict->SetInteger("ADDRESS_FAMILY_IPV4",
-                     net::ADDRESS_FAMILY_IPV4);
-    dict->SetInteger("ADDRESS_FAMILY_IPV6",
-                     net::ADDRESS_FAMILY_IPV6);
-
-    constants_dict->Set("addressFamily", dict);
-  }
-
-  // Information about how the "time ticks" values we have given it relate to
-  // actual system times. (We used time ticks throughout since they are stable
-  // across system clock changes).
-  {
-    int64 cur_time_ms = (base::Time::Now() - base::Time()).InMilliseconds();
-
-    int64 cur_time_ticks_ms =
-        (base::TimeTicks::Now() - base::TimeTicks()).InMilliseconds();
-
-    // If we add this number to a time tick value, it gives the timestamp.
-    int64 tick_to_time_ms = cur_time_ms - cur_time_ticks_ms;
-
-    // Chrome on all platforms stores times using the Windows epoch
-    // (Jan 1 1601), but the javascript wants a unix epoch.
-    // TODO(eroman): Getting the timestamp relative to the unix epoch should
-    //               be part of the time library.
-    const int64 kUnixEpochMs = 11644473600000LL;
-    int64 tick_to_unix_time_ms = tick_to_time_ms - kUnixEpochMs;
-
-    // Pass it as a string, since it may be too large to fit in an integer.
-    constants_dict->SetString("timeTickOffset",
-                              base::Int64ToString(tick_to_unix_time_ms));
-  }
   return constants_dict;
 }
 
diff --git a/chrome/browser/ui/webui/net_internals/net_internals_ui_browsertest.cc b/chrome/browser/ui/webui/net_internals/net_internals_ui_browsertest.cc
index 06f809a..486e28e 100644
--- a/chrome/browser/ui/webui/net_internals/net_internals_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/net_internals/net_internals_ui_browsertest.cc
@@ -14,12 +14,12 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/io_thread.h"
 #include "chrome/browser/net/chrome_net_log.h"
-#include "chrome/browser/net/net_log_logger.h"
 #include "chrome/browser/prerender/prerender_manager.h"
 #include "chrome/browser/prerender/prerender_manager_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/browser/ui/webui/net_internals/net_internals_ui.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/render_view_host.h"
@@ -29,6 +29,7 @@
 #include "net/base/address_list.h"
 #include "net/base/net_errors.h"
 #include "net/base/net_log.h"
+#include "net/base/net_log_logger.h"
 #include "net/dns/host_cache.h"
 #include "net/dns/host_resolver.h"
 #include "net/dns/mock_host_resolver.h"
@@ -344,7 +345,9 @@
   FILE* temp_file_handle = file_util::OpenFile(temp_file, "w");
   ASSERT_TRUE(temp_file_handle);
 
-  scoped_ptr<NetLogLogger> net_log_logger(new NetLogLogger(temp_file_handle));
+  scoped_ptr<base::Value> constants(NetInternalsUI::GetConstants());
+  scoped_ptr<net::NetLogLogger> net_log_logger(new net::NetLogLogger(
+      temp_file_handle, *constants));
   net_log_logger->StartObserving(g_browser_process->net_log());
   g_browser_process->net_log()->AddGlobalEntry(
       net::NetLog::TYPE_NETWORK_IP_ADDRESSES_CHANGED);
diff --git a/chrome/browser/ui/webui/ntp/android/OWNERS b/chrome/browser/ui/webui/ntp/android/OWNERS
index 9549e8c..0d259ac 100644
--- a/chrome/browser/ui/webui/ntp/android/OWNERS
+++ b/chrome/browser/ui/webui/ntp/android/OWNERS
@@ -1,4 +1,3 @@
-jcivelli@chromium.org
 newt@chromium.org
 tedchoc@chromium.org
 yfriedman@chromium.org
diff --git a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
index 88bff10..82c0078 100644
--- a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
+++ b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
@@ -6,6 +6,7 @@
 
 #include <vector>
 
+#include "apps/metrics_names.h"
 #include "apps/pref_names.h"
 #include "base/auto_reset.h"
 #include "base/bind.h"
@@ -212,6 +213,9 @@
   web_ui()->RegisterMessageCallback("stopShowingAppLauncherPromo",
       base::Bind(&AppLauncherHandler::StopShowingAppLauncherPromo,
                  base::Unretained(this)));
+  web_ui()->RegisterMessageCallback("onLearnMore",
+      base::Bind(&AppLauncherHandler::OnLearnMore,
+                 base::Unretained(this)));
 }
 
 void AppLauncherHandler::Observe(int type,
@@ -694,6 +698,11 @@
     const base::ListValue* args) {
   g_browser_process->local_state()->SetBoolean(
       apps::prefs::kShowAppLauncherPromo, false);
+  RecordAppLauncherPromoHistogram(apps::APP_LAUNCHER_PROMO_DISMISSED);
+}
+
+void AppLauncherHandler::OnLearnMore(const base::ListValue* args) {
+  RecordAppLauncherPromoHistogram(apps::APP_LAUNCHER_PROMO_LEARN_MORE);
 }
 
 void AppLauncherHandler::OnFaviconForApp(
@@ -758,6 +767,7 @@
 void AppLauncherHandler::RecordAppLaunchType(
     extension_misc::AppLaunchBucket bucket,
     extensions::Manifest::Type app_type) {
+  DCHECK_LT(bucket, extension_misc::APP_LAUNCH_BUCKET_BOUNDARY);
   if (app_type == extensions::Manifest::TYPE_PLATFORM_APP) {
     UMA_HISTOGRAM_ENUMERATION(extension_misc::kPlatformAppLaunchHistogram,
         bucket, extension_misc::APP_LAUNCH_BUCKET_BOUNDARY);
@@ -790,6 +800,14 @@
 }
 
 // static
+void AppLauncherHandler::RecordAppLauncherPromoHistogram(
+      apps::AppLauncherPromoHistogramValues value) {
+  DCHECK_LT(value, apps::APP_LAUNCHER_PROMO_MAX);
+  UMA_HISTOGRAM_ENUMERATION(
+      "Apps.AppLauncherPromo", value, apps::APP_LAUNCHER_PROMO_MAX);
+}
+
+// static
 void AppLauncherHandler::RecordWebStoreLaunch() {
   RecordAppLaunchType(extension_misc::APP_LAUNCH_NTP_WEBSTORE,
       extensions::Manifest::TYPE_HOSTED_APP);
diff --git a/chrome/browser/ui/webui/ntp/app_launcher_handler.h b/chrome/browser/ui/webui/ntp/app_launcher_handler.h
index 986d055..7a5dc0f 100644
--- a/chrome/browser/ui/webui/ntp/app_launcher_handler.h
+++ b/chrome/browser/ui/webui/ntp/app_launcher_handler.h
@@ -8,6 +8,7 @@
 #include <set>
 #include <string>
 
+#include "apps/metrics_names.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/prefs/pref_change_registrar.h"
 #include "chrome/browser/extensions/extension_uninstall_dialog.h"
@@ -68,31 +69,41 @@
   // Populate the given dictionary with the web store promo content.
   void FillPromoDictionary(base::DictionaryValue* value);
 
-  // Callback for the "getApps" message.
+  // Handles the "launchApp" message with unused |args|.
   void HandleGetApps(const base::ListValue* args);
 
-  // Callback for the "launchApp" message.
+  // Handles the "launchApp" message with |args| containing [extension_id,
+  // source] with optional [url, disposition], |disposition| defaulting to
+  // CURRENT_TAB.
   void HandleLaunchApp(const base::ListValue* args);
 
-  // Callback for the "setLaunchType" message.
+  // Handles the "setLaunchType" message with args containing [extension_id,
+  // launch_type].
   void HandleSetLaunchType(const base::ListValue* args);
 
-  // Callback for the "uninstallApp" message.
+  // Handles the "uninstallApp" message with |args| containing [extension_id]
+  // and an optional bool to not confirm the uninstall when true, defaults to
+  // false.
   void HandleUninstallApp(const base::ListValue* args);
 
-  // Callback for the "createAppShortcut" message.
+  // Handles the "createAppShortcut" message with |args| containing
+  // [extension_id].
   void HandleCreateAppShortcut(const base::ListValue* args);
 
-  // Callback for the "reorderApps" message.
+  // Handles the "reorderApps" message with |args| containing [dragged_app_id,
+  // app_order].
   void HandleReorderApps(const base::ListValue* args);
 
-  // Callback for the "setPageIndex" message.
+  // Handles the "setPageIndex" message with |args| containing [extension_id,
+  // page_index].
   void HandleSetPageIndex(const base::ListValue* args);
 
-  // Callback for the "saveAppPageName" message.
+  // Handles "saveAppPageName" message with |args| containing [name,
+  // page_index].
   void HandleSaveAppPageName(const base::ListValue* args);
 
-  // Callback for the "generateAppForLink" message.
+  // Handles "generateAppForLink" message with |args| containing [url, title,
+  // page_index].
   void HandleGenerateAppForLink(const base::ListValue* args);
 
   // Callback for the "recordAppLaunchByURL" message. Takes an escaped URL and a
@@ -100,14 +111,9 @@
   // action for UMA.
   void HandleRecordAppLaunchByUrl(const base::ListValue* args);
 
-  // Callback for "stopShowingAppLauncherPromo" message.
+  // Other registered message callbacks with unused |args|.
   void StopShowingAppLauncherPromo(const base::ListValue* args);
-
-  // Callback for "closeNotification" message.
-  void HandleNotificationClose(const base::ListValue* args);
-
-  // Callback for "setNotificationsDisabled" message.
-  void HandleSetNotificationsDisabled(const base::ListValue* args);
+  void OnLearnMore(const base::ListValue* args);
 
   // Register app launcher preferences.
   static void RegisterUserPrefs(user_prefs::PrefRegistrySyncable* registry);
@@ -122,6 +128,10 @@
   // Records an app launch from the main view of the app list.
   static void RecordAppListMainLaunch(const extensions::Extension* extension);
 
+  // Records the given |value| in the apps::kAppLauncherPromoHistogram.
+  static void RecordAppLauncherPromoHistogram(
+      apps::AppLauncherPromoHistogramValues value);
+
  private:
   struct AppInstallInfo {
     AppInstallInfo();
diff --git a/chrome/browser/ui/webui/ntp/foreign_session_handler.h b/chrome/browser/ui/webui/ntp/foreign_session_handler.h
index 4e466f0..fd470ca 100644
--- a/chrome/browser/ui/webui/ntp/foreign_session_handler.h
+++ b/chrome/browser/ui/webui/ntp/foreign_session_handler.h
@@ -7,7 +7,7 @@
 
 #include <vector>
 
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/sessions/session_service.h"
 #include "chrome/browser/sync/glue/session_model_associator.h"
 #include "content/public/browser/notification_observer.h"
diff --git a/chrome/browser/ui/webui/ntp/new_tab_ui.h b/chrome/browser/ui/webui/ntp/new_tab_ui.h
index 644430a..bbc4ff8 100644
--- a/chrome/browser/ui/webui/ntp/new_tab_ui.h
+++ b/chrome/browser/ui/webui/ntp/new_tab_ui.h
@@ -9,8 +9,8 @@
 
 #include "base/gtest_prod_util.h"
 #include "base/prefs/pref_change_registrar.h"
-#include "base/time.h"
-#include "base/timer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "content/public/browser/url_data_source.h"
diff --git a/chrome/browser/ui/webui/ntp/ntp_login_handler.cc b/chrome/browser/ui/webui/ntp/ntp_login_handler.cc
index 7be787e..cfafc72 100644
--- a/chrome/browser/ui/webui/ntp/ntp_login_handler.cc
+++ b/chrome/browser/ui/webui/ntp/ntp_login_handler.cc
@@ -28,8 +28,8 @@
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/chrome_pages.h"
+#include "chrome/browser/ui/sync/sync_promo_ui.h"
 #include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
-#include "chrome/browser/ui/webui/sync_promo/sync_promo_ui.h"
 #include "chrome/browser/web_resource/promo_resource_service.h"
 #include "chrome/common/chrome_notification_types.h"
 #include "chrome/common/pref_names.h"
diff --git a/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc b/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc
index e19ad8a..15d0f19 100644
--- a/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc
+++ b/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc
@@ -8,11 +8,9 @@
 #include <vector>
 
 #include "apps/app_launcher.h"
-#include "apps/field_trial_names.h"
 #include "apps/pref_names.h"
 #include "base/command_line.h"
 #include "base/memory/ref_counted_memory.h"
-#include "base/metrics/field_trial.h"
 #include "base/prefs/pref_service.h"
 #include "base/strings/string16.h"
 #include "base/strings/string_number_conversions.h"
@@ -31,10 +29,10 @@
 #include "chrome/browser/themes/theme_service.h"
 #include "chrome/browser/themes/theme_service_factory.h"
 #include "chrome/browser/ui/bookmarks/bookmark_bar_constants.h"
+#include "chrome/browser/ui/sync/sync_promo_ui.h"
 #include "chrome/browser/ui/webui/ntp/new_tab_page_handler.h"
 #include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
 #include "chrome/browser/ui/webui/ntp/ntp_login_handler.h"
-#include "chrome/browser/ui/webui/sync_promo/sync_promo_ui.h"
 #include "chrome/browser/ui/webui/sync_setup_handler.h"
 #include "chrome/browser/web_resource/notification_promo.h"
 #include "chrome/common/chrome_notification_types.h"
@@ -338,7 +336,6 @@
   // Show the profile name in the title and most visited labels if the current
   // profile is not the default.
   PrefService* prefs = profile_->GetPrefs();
-  PrefService* local_state = g_browser_process->local_state();
   DictionaryValue load_time_data;
   load_time_data.SetBoolean("bookmarkbarattached",
       prefs->GetBoolean(prefs::kShowBookmarkBar));
@@ -346,15 +343,8 @@
       ThemeServiceFactory::GetForProfile(profile_)->HasCustomImage(
           IDR_THEME_NTP_ATTRIBUTION));
   load_time_data.SetBoolean("showMostvisited", should_show_most_visited_page_);
-  std::string app_launcher_promo_group_name =
-      base::FieldTrialList::FindFullName(apps::kLauncherPromoTrialName);
-  bool show_app_launcher_promo =
-      !apps::IsAppLauncherEnabled() &&
-      local_state->GetBoolean(apps::prefs::kShowAppLauncherPromo) &&
-      (app_launcher_promo_group_name == apps::kShowLauncherPromoOnceGroupName ||
-       app_launcher_promo_group_name ==
-          apps::kResetShowLauncherPromoPrefGroupName);
-  load_time_data.SetBoolean("showAppLauncherPromo", show_app_launcher_promo);
+  load_time_data.SetBoolean("showAppLauncherPromo",
+      apps::ShouldShowAppLauncherPromo());
   load_time_data.SetBoolean("showRecentlyClosed",
       should_show_recently_closed_menu_);
   load_time_data.SetString("title",
@@ -405,6 +395,8 @@
       l10n_util::GetStringUTF16(IDS_SYNC_START_SYNC_BUTTON_LABEL));
   load_time_data.SetString("syncLinkText",
       l10n_util::GetStringUTF16(IDS_SYNC_ADVANCED_OPTIONS));
+  load_time_data.SetBoolean("shouldShowSyncLogin",
+                            NTPLoginHandler::ShouldShow(profile_));
   load_time_data.SetString("otherSessions",
       l10n_util::GetStringUTF16(IDS_NEW_TAB_OTHER_SESSIONS_LABEL));
   load_time_data.SetString("otherSessionsEmpty",
diff --git a/chrome/browser/ui/webui/omnibox/omnibox_ui_handler.cc b/chrome/browser/ui/webui/omnibox/omnibox_ui_handler.cc
index 3856684..3b62f03 100644
--- a/chrome/browser/ui/webui/omnibox/omnibox_ui_handler.cc
+++ b/chrome/browser/ui/webui/omnibox/omnibox_ui_handler.cc
@@ -11,7 +11,7 @@
 #include "base/strings/string16.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/autocomplete/autocomplete_classifier.h"
 #include "chrome/browser/autocomplete/autocomplete_controller.h"
diff --git a/chrome/browser/ui/webui/omnibox/omnibox_ui_handler.h b/chrome/browser/ui/webui/omnibox/omnibox_ui_handler.h
index 292d4de..8c18792 100644
--- a/chrome/browser/ui/webui/omnibox/omnibox_ui_handler.h
+++ b/chrome/browser/ui/webui/omnibox/omnibox_ui_handler.h
@@ -8,7 +8,7 @@
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/autocomplete/autocomplete_controller_delegate.h"
 #include "chrome/browser/autocomplete/autocomplete_match.h"
 #include "content/public/browser/web_ui_message_handler.h"
diff --git a/chrome/browser/ui/webui/options/autofill_options_handler.cc b/chrome/browser/ui/webui/options/autofill_options_handler.cc
index 4fcbb41..e00af5c 100644
--- a/chrome/browser/ui/webui/options/autofill_options_handler.cc
+++ b/chrome/browser/ui/webui/options/autofill_options_handler.cc
@@ -19,11 +19,11 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/autofill/country_combobox_model.h"
 #include "chrome/common/url_constants.h"
-#include "components/autofill/browser/autofill_country.h"
-#include "components/autofill/browser/autofill_profile.h"
-#include "components/autofill/browser/credit_card.h"
-#include "components/autofill/browser/personal_data_manager.h"
-#include "components/autofill/browser/phone_number_i18n.h"
+#include "components/autofill/core/browser/autofill_country.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/credit_card.h"
+#include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/autofill/core/browser/phone_number_i18n.h"
 #include "components/autofill/core/common/autofill_constants.h"
 #include "content/public/browser/web_ui.h"
 #include "grit/component_strings.h"
diff --git a/chrome/browser/ui/webui/options/autofill_options_handler.h b/chrome/browser/ui/webui/options/autofill_options_handler.h
index a9b90a8..5d58d21 100644
--- a/chrome/browser/ui/webui/options/autofill_options_handler.h
+++ b/chrome/browser/ui/webui/options/autofill_options_handler.h
@@ -9,7 +9,7 @@
 
 #include "base/compiler_specific.h"
 #include "chrome/browser/ui/webui/options/options_ui.h"
-#include "components/autofill/browser/personal_data_manager_observer.h"
+#include "components/autofill/core/browser/personal_data_manager_observer.h"
 
 namespace autofill {
 class PersonalDataManager;
diff --git a/chrome/browser/ui/webui/options/browser_options_handler.cc b/chrome/browser/ui/webui/options/browser_options_handler.cc
index da0e12d..04f7ceb 100644
--- a/chrome/browser/ui/webui/options/browser_options_handler.cc
+++ b/chrome/browser/ui/webui/options/browser_options_handler.cc
@@ -31,7 +31,6 @@
 #include "chrome/browser/prefs/session_startup_pref.h"
 #include "chrome/browser/printing/cloud_print/cloud_print_proxy_service.h"
 #include "chrome/browser/printing/cloud_print/cloud_print_proxy_service_factory.h"
-#include "chrome/browser/printing/cloud_print/cloud_print_setup_flow.h"
 #include "chrome/browser/printing/cloud_print/cloud_print_url.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_info_cache.h"
@@ -92,7 +91,6 @@
 #endif
 
 #if !defined(OS_CHROMEOS)
-#include "chrome/browser/printing/cloud_print/cloud_print_setup_handler.h"
 #include "chrome/browser/ui/webui/options/advanced_options_utils.h"
 #include "chromeos/chromeos_switches.h"
 #endif
@@ -116,10 +114,6 @@
 #include "chrome/installer/util/auto_launch_util.h"
 #endif  // defined(OS_WIN)
 
-#if defined(TOOLKIT_GTK)
-#include "chrome/browser/ui/gtk/gtk_theme_service.h"
-#endif  // defined(TOOLKIT_GTK)
-
 using content::BrowserContext;
 using content::BrowserThread;
 using content::DownloadManager;
@@ -131,11 +125,13 @@
 
 namespace {
 
-bool ShouldShowMultiProfilesUserList() {
+bool ShouldShowMultiProfilesUserList(chrome::HostDesktopType desktop_type) {
 #if defined(OS_CHROMEOS)
   // On Chrome OS we use different UI for multi-profiles.
   return false;
 #else
+  if (desktop_type != chrome::HOST_DESKTOP_TYPE_NATIVE)
+    return false;
   return ProfileManager::IsMultipleProfilesEnabled();
 #endif
 }
@@ -338,9 +334,9 @@
     { "toolbarShowHomeButton", IDS_OPTIONS_TOOLBAR_SHOW_HOME_BUTTON },
     { "translateEnableTranslate",
       IDS_OPTIONS_TRANSLATE_ENABLE_TRANSLATE },
-#if defined(TOOLKIT_GTK)
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
     { "showWindowDecorations", IDS_SHOW_WINDOW_DECORATIONS },
-    { "themesGTKButton", IDS_THEMES_GTK_BUTTON },
+    { "themesNativeButton", IDS_THEMES_GTK_BUTTON },
     { "themesSetClassic", IDS_THEMES_SET_CLASSIC },
 #else
     { "themes", IDS_THEMES_GROUP_NAME },
@@ -512,7 +508,7 @@
       g_browser_process->profile_manager()->GetNumberOfProfiles() > 1);
 #endif
 
-  if (ShouldShowMultiProfilesUserList())
+  if (ShouldShowMultiProfilesUserList(GetDesktopType()))
     values->Set("profilesInfo", GetProfilesInfoList().release());
 
 #if defined(ENABLE_MANAGED_USERS)
@@ -580,10 +576,10 @@
       "themesReset",
       base::Bind(&BrowserOptionsHandler::ThemesReset,
                  base::Unretained(this)));
-#if defined(TOOLKIT_GTK)
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
   web_ui()->RegisterMessageCallback(
-      "themesSetGTK",
-      base::Bind(&BrowserOptionsHandler::ThemesSetGTK,
+      "themesSetNative",
+      base::Bind(&BrowserOptionsHandler::ThemesSetNative,
                  base::Unretained(this)));
 #endif
   web_ui()->RegisterMessageCallback(
@@ -1091,7 +1087,7 @@
 }
 
 void BrowserOptionsHandler::SendProfilesInfo() {
-  if (!ShouldShowMultiProfilesUserList())
+  if (!ShouldShowMultiProfilesUserList(GetDesktopType()))
     return;
   web_ui()->CallJavascriptFunction("BrowserOptions.setProfilesInfo",
                                    *GetProfilesInfoList());
@@ -1320,31 +1316,35 @@
 
 void BrowserOptionsHandler::ObserveThemeChanged() {
   Profile* profile = Profile::FromWebUI(web_ui());
-#if defined(TOOLKIT_GTK)
-  GtkThemeService* theme_service = GtkThemeService::GetFrom(profile);
-  bool is_gtk_theme = theme_service->UsingNativeTheme();
-  base::FundamentalValue gtk_enabled(!is_gtk_theme);
-  web_ui()->CallJavascriptFunction("BrowserOptions.setGtkThemeButtonEnabled",
-                                   gtk_enabled);
-#else
+  bool profile_is_managed = ManagedUserService::ProfileIsManaged(profile);
   ThemeService* theme_service = ThemeServiceFactory::GetForProfile(profile);
-  bool is_gtk_theme = false;
+  bool is_native_theme = false;
+
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+  is_native_theme = theme_service->UsingNativeTheme();
+  base::FundamentalValue native_theme_enabled(!is_native_theme &&
+                                              !profile_is_managed);
+  web_ui()->CallJavascriptFunction("BrowserOptions.setNativeThemeButtonEnabled",
+                                   native_theme_enabled);
 #endif
 
-  bool is_classic_theme = !is_gtk_theme && theme_service->UsingDefaultTheme();
-  base::FundamentalValue enabled(!is_classic_theme);
+  bool is_classic_theme = !is_native_theme &&
+                          theme_service->UsingDefaultTheme();
+  base::FundamentalValue enabled(!is_classic_theme && !profile_is_managed);
   web_ui()->CallJavascriptFunction("BrowserOptions.setThemesResetButtonEnabled",
                                    enabled);
 }
 
 void BrowserOptionsHandler::ThemesReset(const ListValue* args) {
-  content::RecordAction(UserMetricsAction("Options_ThemesReset"));
   Profile* profile = Profile::FromWebUI(web_ui());
+  if (ManagedUserService::ProfileIsManaged(profile))
+    return;
+  content::RecordAction(UserMetricsAction("Options_ThemesReset"));
   ThemeServiceFactory::GetForProfile(profile)->UseDefaultTheme();
 }
 
-#if defined(TOOLKIT_GTK)
-void BrowserOptionsHandler::ThemesSetGTK(const ListValue* args) {
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+void BrowserOptionsHandler::ThemesSetNative(const ListValue* args) {
   content::RecordAction(UserMetricsAction("Options_GtkThemeSet"));
   Profile* profile = Profile::FromWebUI(web_ui());
   ThemeServiceFactory::GetForProfile(profile)->SetNativeTheme();
@@ -1441,13 +1441,6 @@
   pref_service->SetFilePath(prefs::kSaveFileDefaultDirectory, path);
 }
 
-void BrowserOptionsHandler::OnCloudPrintSetupClosed() {
-#if !defined(OS_CHROMEOS)
-  if (cloud_print_connector_ui_enabled_)
-    SetupCloudPrintConnectorSection();
-#endif
-}
-
 #if defined(OS_CHROMEOS)
 void BrowserOptionsHandler::TouchpadExists(bool exists) {
   base::FundamentalValue val(exists);
@@ -1737,8 +1730,8 @@
   bool is_extension_controlled = (proxy_config &&
                                   proxy_config->IsExtensionControlled());
 
-  base::FundamentalValue disabled(profile_pref_registrar_.IsManaged() ||
-                                  is_extension_controlled);
+  base::FundamentalValue disabled(proxy_config &&
+                                  !proxy_config->IsUserModifiable());
   base::FundamentalValue extension_controlled(is_extension_controlled);
   web_ui()->CallJavascriptFunction("BrowserOptions.setupProxySettingsSection",
                                    disabled, extension_controlled);
diff --git a/chrome/browser/ui/webui/options/browser_options_handler.h b/chrome/browser/ui/webui/options/browser_options_handler.h
index acc81cf..6acf28f 100644
--- a/chrome/browser/ui/webui/options/browser_options_handler.h
+++ b/chrome/browser/ui/webui/options/browser_options_handler.h
@@ -11,8 +11,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/prefs/pref_member.h"
-#include "base/time.h"
-#include "chrome/browser/printing/cloud_print/cloud_print_setup_handler.h"
+#include "base/time/time.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/search_engines/template_url_service_observer.h"
@@ -38,7 +37,6 @@
 // Chrome browser options page UI handler.
 class BrowserOptionsHandler
     : public OptionsPageUIHandler,
-      public CloudPrintSetupHandlerDelegate,
       public ProfileSyncServiceObserver,
       public ui::SelectFileDialog::Listener,
       public ShellIntegration::DefaultWebClientObserver,
@@ -88,9 +86,6 @@
                             int index,
                             void* params) OVERRIDE;
 
-  // CloudPrintSetupHandler::Delegate implementation.
-  virtual void OnCloudPrintSetupClosed() OVERRIDE;
-
 #if defined(OS_CHROMEOS)
   // PointerDeviceObserver::Observer implementation.
   virtual void TouchpadExists(bool exists) OVERRIDE;
@@ -199,8 +194,8 @@
 
   void ObserveThemeChanged();
   void ThemesReset(const base::ListValue* args);
-#if defined(TOOLKIT_GTK)
-  void ThemesSetGTK(const base::ListValue* args);
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+  void ThemesSetNative(const base::ListValue* args);
 #endif
 
 #if defined(OS_CHROMEOS)
@@ -343,7 +338,6 @@
   StringPrefMember cloud_print_connector_email_;
   BooleanPrefMember cloud_print_connector_enabled_;
   bool cloud_print_connector_ui_enabled_;
-  scoped_ptr<CloudPrintSetupHandler> cloud_print_setup_handler_;
 #endif
 
   StringPrefMember auto_open_files_;
diff --git a/chrome/browser/ui/webui/options/certificate_manager_browsertest.cc b/chrome/browser/ui/webui/options/certificate_manager_browsertest.cc
index f45624c..d18f733 100644
--- a/chrome/browser/ui/webui/options/certificate_manager_browsertest.cc
+++ b/chrome/browser/ui/webui/options/certificate_manager_browsertest.cc
@@ -51,10 +51,9 @@
 
     // Enable web trust certs from policy.
     g_browser_process->browser_policy_connector()->
-        GetNetworkConfigurationUpdater()->SetUserPolicyService(
+        network_configuration_updater()->SetUserPolicyService(
             true, "", connector->policy_service());
 #endif
-    content::RunAllPendingInMessageLoop();
   }
 
 #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/ui/webui/options/certificate_manager_handler.cc b/chrome/browser/ui/webui/options/certificate_manager_handler.cc
index 6a97f84..f77cc8b 100644
--- a/chrome/browser/ui/webui/options/certificate_manager_handler.cc
+++ b/chrome/browser/ui/webui/options/certificate_manager_handler.cc
@@ -114,8 +114,8 @@
 // Struct to bind the Equals member function to an object for use in find_if.
 struct CertEquals {
   explicit CertEquals(const net::X509Certificate* cert) : cert_(cert) {}
-  bool operator()(const net::X509Certificate* cert) const {
-    return cert_->Equals(cert);
+  bool operator()(const scoped_refptr<net::X509Certificate> cert) const {
+    return cert_->Equals(cert.get());
   }
   const net::X509Certificate* cert_;
 };
diff --git a/chrome/browser/ui/webui/options/chromeos/accounts_options_browsertest.js b/chrome/browser/ui/webui/options/chromeos/accounts_options_browsertest.js
new file mode 100644
index 0000000..4dd58bd
--- /dev/null
+++ b/chrome/browser/ui/webui/options/chromeos/accounts_options_browsertest.js
@@ -0,0 +1,40 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function AccountsOptionsWebUITest() {}
+
+AccountsOptionsWebUITest.prototype = {
+  __proto__: testing.Test.prototype,
+
+  /**
+   * Browse to accounts options.
+   **/
+  browsePreload: 'chrome://settings-frame/accounts',
+};
+
+function createEnterKeyboardEvent(type) {
+  return new KeyboardEvent(type, {
+    'bubbles': true,
+    'cancelable': true,
+    'keyIdentifier': 'Enter'
+  });
+}
+
+TEST_F('AccountsOptionsWebUITest', 'testNoCloseOnEnter', function() {
+  assertEquals(this.browsePreload, document.location.href);
+
+  var inputField = $('userNameEdit');
+  var overlay = $('accountsPage').parentNode;
+
+  // Overlay is visible.
+  assertFalse(overlay.classList.contains('transparent'));
+
+  // Simulate pressing the enter key in the edit field.
+  inputField.dispatchEvent(createEnterKeyboardEvent('keydown'));
+  inputField.dispatchEvent(createEnterKeyboardEvent('keypress'));
+  inputField.dispatchEvent(createEnterKeyboardEvent('keyup'));
+
+  // Verify the overlay is still visible.
+  assertFalse(overlay.classList.contains('transparent'));
+});
diff --git a/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc b/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc
index 1b9c086..9d1f9e1 100644
--- a/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc
+++ b/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc
@@ -227,7 +227,7 @@
 
 void DisplayOptionsHandler::OnFadeOutForDisplayLayoutFinished(
     int position, int offset) {
-  SetCurrentAndDefaultDisplayLayout(
+  SetCurrentDisplayLayout(
       ash::DisplayLayout::FromInts(position, offset));
   ash::Shell::GetInstance()->output_configurator_animation()->
       StartFadeInAnimation();
diff --git a/chrome/browser/ui/webui/options/chromeos/internet_options_handler.cc b/chrome/browser/ui/webui/options/chromeos/internet_options_handler.cc
index d39d0af..a49dd5c 100644
--- a/chrome/browser/ui/webui/options/chromeos/internet_options_handler.cc
+++ b/chrome/browser/ui/webui/options/chromeos/internet_options_handler.cc
@@ -23,7 +23,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/choose_mobile_network_dialog.h"
@@ -1194,21 +1194,29 @@
   chromeos::Network* network = cros_->FindNetworkByPath(service_path);
   if (!network)
     return;
-  // Have to copy the properties because the object will go out of scope when
-  // this function call completes (it's owned by the calling function).
-  base::DictionaryValue* shill_props_copy = shill_properties->DeepCopy();
-  cros_->GetIPConfigs(
-      network->device_path(),
-      chromeos::NetworkLibrary::FORMAT_COLON_SEPARATED_HEX,
-      base::Bind(&InternetOptionsHandler::PopulateIPConfigsCallback,
-                 weak_factory_.GetWeakPtr(),
-                 service_path,
-                 base::Owned(shill_props_copy)));
+
+  if (network->device_path().empty()) {
+    PopulateIPConfigsCallback(service_path,
+                              shill_properties,
+                              chromeos::NetworkIPConfigVector(),
+                              std::string());
+  } else {
+    // Have to copy the properties because the object will go out of scope when
+    // this function call completes (it's owned by the calling function).
+    base::DictionaryValue* shill_props_copy = shill_properties->DeepCopy();
+    cros_->GetIPConfigs(
+        network->device_path(),
+        chromeos::NetworkLibrary::FORMAT_COLON_SEPARATED_HEX,
+        base::Bind(&InternetOptionsHandler::PopulateIPConfigsCallback,
+                   weak_factory_.GetWeakPtr(),
+                   service_path,
+                   base::Owned(shill_props_copy)));
+  }
 }
 
 void InternetOptionsHandler::PopulateIPConfigsCallback(
     const std::string& service_path,
-    base::DictionaryValue* shill_properties,
+    const base::DictionaryValue* shill_properties,
     const chromeos::NetworkIPConfigVector& ipconfigs,
     const std::string& hardware_address) {
   if (!shill_properties)
diff --git a/chrome/browser/ui/webui/options/chromeos/internet_options_handler.h b/chrome/browser/ui/webui/options/chromeos/internet_options_handler.h
index 9d19ad3..59ef335 100644
--- a/chrome/browser/ui/webui/options/chromeos/internet_options_handler.h
+++ b/chrome/browser/ui/webui/options/chromeos/internet_options_handler.h
@@ -109,7 +109,7 @@
       const base::DictionaryValue* shill_properties);
   void PopulateIPConfigsCallback(
       const std::string& service_path,
-      base::DictionaryValue* shill_properties,
+      const base::DictionaryValue* shill_properties,
       const chromeos::NetworkIPConfigVector& ipconfigs,
       const std::string& hardware_address);
   void PopulateConnectionDetails(const chromeos::Network* network,
diff --git a/chrome/browser/ui/webui/options/chromeos/proxy_handler.cc b/chrome/browser/ui/webui/options/chromeos/proxy_handler.cc
index 92bab43..4ed2345 100644
--- a/chrome/browser/ui/webui/options/chromeos/proxy_handler.cc
+++ b/chrome/browser/ui/webui/options/chromeos/proxy_handler.cc
@@ -8,7 +8,7 @@
 #include "base/callback.h"
 #include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/chromeos/system/statistics_provider.h"
 #include "chrome/common/chrome_constants.h"
@@ -70,7 +70,7 @@
 
   bool keyboard_driven_oobe = false;
   system::StatisticsProvider::GetInstance()->GetMachineFlag(
-      chromeos::kOemKeyboardDrivenOobeKey, &keyboard_driven_oobe);
+      chromeos::system::kOemKeyboardDrivenOobeKey, &keyboard_driven_oobe);
   if (keyboard_driven_oobe) {
     web_ui()->CallJavascriptFunction(
         "DetailsInternetPage.initializeKeyboardFlow");
diff --git a/chrome/browser/ui/webui/options/core_options_handler.cc b/chrome/browser/ui/webui/options/core_options_handler.cc
index 4241edb..e063533 100644
--- a/chrome/browser/ui/webui/options/core_options_handler.cc
+++ b/chrome/browser/ui/webui/options/core_options_handler.cc
@@ -472,26 +472,41 @@
 
   switch (type) {
     case TYPE_BOOLEAN:
-      CHECK_EQ(base::Value::TYPE_BOOLEAN, value->GetType());
+      if (!value->IsType(base::Value::TYPE_BOOLEAN)) {
+        NOTREACHED();
+        return;
+      }
       break;
     case TYPE_INTEGER: {
       // In JS all numbers are doubles.
       double double_value;
-      CHECK(value->GetAsDouble(&double_value));
+      if (!value->GetAsDouble(&double_value)) {
+        NOTREACHED();
+        return;
+      }
       int int_value = static_cast<int>(double_value);
       temp_value.reset(new base::FundamentalValue(int_value));
       value = temp_value.get();
       break;
     }
     case TYPE_DOUBLE:
-      CHECK_EQ(base::Value::TYPE_DOUBLE, value->GetType());
+      if (!value->IsType(base::Value::TYPE_DOUBLE)) {
+        NOTREACHED();
+        return;
+      }
       break;
     case TYPE_STRING:
-      CHECK_EQ(base::Value::TYPE_STRING, value->GetType());
+      if (!value->IsType(base::Value::TYPE_STRING)) {
+        NOTREACHED();
+        return;
+      }
       break;
     case TYPE_URL: {
       std::string original;
-      CHECK(value->GetAsString(&original));
+      if (!value->GetAsString(&original)) {
+        NOTREACHED();
+        return;
+      }
       GURL fixed = URLFixerUpper::FixupURL(original, std::string());
       temp_value.reset(new base::StringValue(fixed.spec()));
       value = temp_value.get();
@@ -500,11 +515,17 @@
     case TYPE_LIST: {
       // In case we have a List pref we got a JSON string.
       std::string json_string;
-      CHECK(value->GetAsString(&json_string));
+      if (!value->GetAsString(&json_string)) {
+        NOTREACHED();
+        return;
+      }
       temp_value.reset(
           base::JSONReader::Read(json_string));
       value = temp_value.get();
-      CHECK_EQ(base::Value::TYPE_LIST, value->GetType());
+      if (!value->IsType(base::Value::TYPE_LIST)) {
+        NOTREACHED();
+        return;
+      }
       break;
     }
     default:
diff --git a/chrome/browser/ui/webui/options/import_data_handler.cc b/chrome/browser/ui/webui/options/import_data_handler.cc
index 2bb576b..ccb0165 100644
--- a/chrome/browser/ui/webui/options/import_data_handler.cc
+++ b/chrome/browser/ui/webui/options/import_data_handler.cc
@@ -16,10 +16,10 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/values.h"
+#include "chrome/browser/browser_process.h"
 #include "chrome/browser/importer/external_process_importer_host.h"
-#include "chrome/browser/importer/importer_host.h"
+#include "chrome/browser/importer/importer_creator.h"
 #include "chrome/browser/importer/importer_list.h"
-#include "chrome/browser/importer/importer_type.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "content/public/browser/web_ui.h"
@@ -35,10 +35,10 @@
 
 ImportDataHandler::~ImportDataHandler() {
   if (importer_list_.get())
-    importer_list_->SetObserver(NULL);
+    importer_list_->set_observer(NULL);
 
   if (importer_host_)
-    importer_host_->SetObserver(NULL);
+    importer_host_->set_observer(NULL);
 }
 
 void ImportDataHandler::GetLocalizedValues(DictionaryValue* localized_strings) {
@@ -64,9 +64,9 @@
 }
 
 void ImportDataHandler::InitializeHandler() {
-  Profile* profile = Profile::FromWebUI(web_ui());
-  importer_list_ = new ImporterList(profile->GetRequestContext());
-  importer_list_->DetectSourceProfiles(this);
+  importer_list_ = new ImporterList();
+  importer_list_->DetectSourceProfiles(
+      g_browser_process->GetApplicationLocale(), this);
 }
 
 void ImportDataHandler::RegisterMessages() {
@@ -109,22 +109,8 @@
                                      state);
     import_did_succeed_ = false;
 
-    // TODO(gab): Make Linux use OOP import as well (http://crbug.com/56816) and
-    // get rid of these ugly ifdefs.
-#if defined(OS_MACOSX) || defined(OS_WIN)
-    // The Google Toolbar importer doesn't work for the out-of-process import.
-    // This is the only entry point for this importer (it is never used on first
-    // run). See discussion on http://crbug.com/219419 for details.
-    if (source_profile.importer_type == importer::TYPE_GOOGLE_TOOLBAR5)
-      importer_host_ = new ImporterHost;
-    else
-      importer_host_ = new ExternalProcessImporterHost;
-#else
-    importer_host_ = new ImporterHost;
-#endif
-    importer_host_->SetObserver(this);
-    importer_host_->set_browser(
-        chrome::FindBrowserWithWebContents(web_ui()->GetWebContents()));
+    importer_host_ = new ExternalProcessImporterHost();
+    importer_host_->set_observer(this);
     Profile* profile = Profile::FromWebUI(web_ui());
     importer_host_->StartImportSettings(source_profile, profile,
                                         import_services,
@@ -184,7 +170,7 @@
 }
 
 void ImportDataHandler::ImportEnded() {
-  importer_host_->SetObserver(NULL);
+  importer_host_->set_observer(NULL);
   importer_host_ = NULL;
 
   if (import_did_succeed_) {
diff --git a/chrome/browser/ui/webui/options/import_data_handler.h b/chrome/browser/ui/webui/options/import_data_handler.h
index d22ff82..79bd035 100644
--- a/chrome/browser/ui/webui/options/import_data_handler.h
+++ b/chrome/browser/ui/webui/options/import_data_handler.h
@@ -8,12 +8,12 @@
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "base/memory/ref_counted.h"
-#include "chrome/browser/importer/importer_data_types.h"
 #include "chrome/browser/importer/importer_list_observer.h"
 #include "chrome/browser/importer/importer_progress_observer.h"
 #include "chrome/browser/ui/webui/options/options_ui.h"
+#include "chrome/common/importer/importer_data_types.h"
 
-class ImporterHost;
+class ExternalProcessImporterHost;
 class ImporterList;
 
 namespace options {
@@ -51,7 +51,7 @@
 
   // If non-null it means importing is in progress. ImporterHost takes care
   // of deleting itself when import is complete.
-  ImporterHost* importer_host_;  // weak
+  ExternalProcessImporterHost* importer_host_;  // weak
 
   bool import_did_succeed_;
 
diff --git a/chrome/browser/ui/webui/options/language_options_handler_common.cc b/chrome/browser/ui/webui/options/language_options_handler_common.cc
index 5517541..9493a06 100644
--- a/chrome/browser/ui/webui/options/language_options_handler_common.cc
+++ b/chrome/browser/ui/webui/options/language_options_handler_common.cc
@@ -13,7 +13,7 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/prefs/pref_service.h"
-#include "base/string_util.h"
+#include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
@@ -125,6 +125,13 @@
   localized_strings->SetBoolean("enableTranslateSettings",
                                 enable_translate_settings);
 
+  Profile* profile = Profile::FromWebUI(web_ui());
+  PrefService* prefs = profile->GetPrefs();
+  std::string default_target_language =
+      TranslateManager::GetTargetLanguage(prefs);
+  localized_strings->SetString("defaultTargetLanguage",
+                               default_target_language);
+
   std::vector<std::string> languages;
   TranslateManager::GetSupportedLanguages(&languages);
 
diff --git a/chrome/browser/ui/webui/options/manage_profile_handler.cc b/chrome/browser/ui/webui/options/manage_profile_handler.cc
index ad252ff..94a0929 100644
--- a/chrome/browser/ui/webui/options/manage_profile_handler.cc
+++ b/chrome/browser/ui/webui/options/manage_profile_handler.cc
@@ -92,13 +92,16 @@
     { "manageProfilesDuplicateNameError",
         IDS_PROFILES_MANAGE_DUPLICATE_NAME_ERROR },
     { "manageProfilesIconLabel", IDS_PROFILES_MANAGE_ICON_LABEL },
-    { "manageProfilesLimitedNotSignedInLabel",
-        IDS_PROFILES_CREATE_LIMITED_NOT_SIGNED_IN_LABEL },
-    { "manageProfilesLimitedNotSignedInLink",
-        IDS_PROFILES_CREATE_LIMITED_NOT_SIGNED_IN_LINK },
+    { "manageProfilesManagedSignedInLabel",
+    IDS_PROFILES_CREATE_MANAGED_SIGNED_IN_LABEL },
+    { "manageProfilesManagedNotSignedInLabel",
+        IDS_PROFILES_CREATE_MANAGED_NOT_SIGNED_IN_LABEL },
+    { "manageProfilesManagedNotSignedInLink",
+        IDS_PROFILES_CREATE_MANAGED_NOT_SIGNED_IN_LINK },
     { "deleteProfileTitle", IDS_PROFILES_DELETE_TITLE },
     { "deleteProfileOK", IDS_PROFILES_DELETE_OK_BUTTON_LABEL },
     { "deleteProfileMessage", IDS_PROFILES_DELETE_MESSAGE },
+    { "deleteManagedProfileAddendum", IDS_PROFILES_DELETE_MANAGED_ADDENDUM },
     { "createProfileTitle", IDS_PROFILES_CREATE_TITLE },
     { "createProfileInstructions", IDS_PROFILES_CREATE_INSTRUCTIONS },
     { "createProfileConfirm", IDS_PROFILES_CREATE_CONFIRM },
@@ -124,10 +127,17 @@
 void ManageProfileHandler::InitializeHandler() {
   registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
                  content::NotificationService::AllSources());
+
+  pref_change_registrar_.Init(Profile::FromWebUI(web_ui())->GetPrefs());
+  pref_change_registrar_.Add(
+      prefs::kManagedUserCreationAllowed,
+      base::Bind(&ManageProfileHandler::OnCreateManagedUserPrefChange,
+                 base::Unretained(this)));
 }
 
 void ManageProfileHandler::InitializePage() {
   SendProfileNames();
+  OnCreateManagedUserPrefChange();
 }
 
 void ManageProfileHandler::RegisterMessages() {
@@ -143,8 +153,8 @@
   web_ui()->RegisterMessageCallback("requestHasProfileShortcuts",
       base::Bind(&ManageProfileHandler::RequestHasProfileShortcuts,
                  base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("requestSignedInText",
-      base::Bind(&ManageProfileHandler::RequestSignedInText,
+  web_ui()->RegisterMessageCallback("requestCreateProfileUpdate",
+      base::Bind(&ManageProfileHandler::RequestCreateProfileUpdate,
                  base::Unretained(this)));
   web_ui()->RegisterMessageCallback("profileIconSelectionChanged",
       base::Bind(&ManageProfileHandler::ProfileIconSelectionChanged,
@@ -389,18 +399,24 @@
                                weak_factory_.GetWeakPtr()));
 }
 
-void ManageProfileHandler::RequestSignedInText(const base::ListValue* args) {
+void ManageProfileHandler::RequestCreateProfileUpdate(
+    const base::ListValue* args) {
   SigninManagerBase* manager =
       SigninManagerFactory::GetForProfile(Profile::FromWebUI(web_ui()));
   string16 username = UTF8ToUTF16(manager->GetAuthenticatedUsername());
-  string16 text = string16();
-  if (!username.empty()) {
-     text = l10n_util::GetStringFUTF16(
-         IDS_PROFILES_CREATE_LIMITED_SIGNED_IN_LABEL, username);
-  }
-  StringValue text_value(text);
+  StringValue username_value(username);
   web_ui()->CallJavascriptFunction("CreateProfileOverlay.updateSignedInStatus",
-                                   text_value);
+                                   username_value);
+
+  OnCreateManagedUserPrefChange();
+}
+
+void ManageProfileHandler::OnCreateManagedUserPrefChange() {
+  PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs();
+  base::FundamentalValue allowed(
+      prefs->GetBoolean(prefs::kManagedUserCreationAllowed));
+  web_ui()->CallJavascriptFunction(
+      "CreateProfileOverlay.updateManagedUsersAllowed", allowed);
 }
 
 void ManageProfileHandler::OnHasProfileShortcuts(bool has_shortcuts) {
diff --git a/chrome/browser/ui/webui/options/manage_profile_handler.h b/chrome/browser/ui/webui/options/manage_profile_handler.h
index 6872cf5..4723b67 100644
--- a/chrome/browser/ui/webui/options/manage_profile_handler.h
+++ b/chrome/browser/ui/webui/options/manage_profile_handler.h
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "base/memory/weak_ptr.h"
+#include "base/prefs/pref_change_registrar.h"
 #include "chrome/browser/ui/webui/options/options_ui.h"
 
 namespace base {
@@ -87,10 +88,15 @@
   // |args| is of the form: [ {string} profileFilePath ]
   void RequestHasProfileShortcuts(const base::ListValue* args);
 
-  // Callback for the "requestSignedInText" message.
-  // Sends the text to be shown if the user is signed in, or an empty string
-  // if not. |args| is not used.
-  void RequestSignedInText(const base::ListValue* args);
+  // Callback for the "RequestCreateProfileUpdate" message.
+  // Sends the email address of the signed-in user, or an empty string if the
+  // user is not signed in. Also sends information about whether managed users
+  // may be created.
+  void RequestCreateProfileUpdate(const base::ListValue* args);
+
+  // When the pref allowing managed-user creation changes, sends the new value
+  // to the UI.
+  void OnCreateManagedUserPrefChange();
 
   // Callback invoked from the profile manager indicating whether the profile
   // being edited has any desktop shortcuts.
@@ -112,6 +118,10 @@
   // For generating weak pointers to itself for callbacks.
   base::WeakPtrFactory<ManageProfileHandler> weak_factory_;
 
+  // Used to observe the preference that allows creating managed users, which
+  // can be changed by policy.
+  PrefChangeRegistrar pref_change_registrar_;
+
   DISALLOW_COPY_AND_ASSIGN(ManageProfileHandler);
 };
 
diff --git a/chrome/browser/ui/webui/options/managed_user_create_confirm_handler.cc b/chrome/browser/ui/webui/options/managed_user_create_confirm_handler.cc
index 04ad4cd..92d6524 100644
--- a/chrome/browser/ui/webui/options/managed_user_create_confirm_handler.cc
+++ b/chrome/browser/ui/webui/options/managed_user_create_confirm_handler.cc
@@ -11,6 +11,9 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/signin/signin_manager.h"
+#include "chrome/browser/signin/signin_manager_base.h"
+#include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/host_desktop.h"
 #include "chrome/browser/ui/startup/startup_types.h"
@@ -31,18 +34,21 @@
   DCHECK(localized_strings);
 
   static OptionsStringResource resources[] = {
-    {"managedUserCreateConfirmTitle", IDS_NEW_LIMITED_USER_SUCCESS_TITLE},
-    {"managedUserCreateConfirmTextSlide1",
-     IDS_NEW_LIMITED_USER_SUCCESS_TEXT_SLIDE_1},
-    {"managedUserCreateConfirmTextSlide2",
-     IDS_NEW_LIMITED_USER_SUCCESS_TEXT_SLIDE_2},
-    {"managedUserCreateConfirmTextSlide3",
-     IDS_NEW_LIMITED_USER_SUCCESS_TEXT_SLIDE_3},
-    {"managedUserCreateConfirmDone", IDS_NEW_LIMITED_USER_SUCCESS_DONE_BUTTON},
-    {"managedUserCreateConfirmSwitch",
-     IDS_NEW_LIMITED_USER_SUCCESS_SWITCH_BUTTON},
+    { "managedUserCreatedTitle", IDS_NEW_MANAGED_USER_CREATED_TITLE },
+    { "managedUserCreatedText", IDS_NEW_MANAGED_USER_CREATED_TEXT },
+    { "managedUserCreatedDone", IDS_NEW_MANAGED_USER_CREATED_DONE_BUTTON },
+    { "managedUserCreatedSwitch", IDS_NEW_MANAGED_USER_CREATED_SWITCH_BUTTON },
   };
 
+  SigninManagerBase* signin =
+      SigninManagerFactory::GetForProfile(Profile::FromWebUI(web_ui()));
+  if (signin) {
+    localized_strings->SetString("custodianEmail",
+                                 signin->GetAuthenticatedUsername());
+  } else {
+    localized_strings->SetString("custodianEmail", std::string());
+  }
+
   RegisterStrings(localized_strings, resources, arraysize(resources));
 }
 
diff --git a/chrome/browser/ui/webui/options/managed_user_learn_more_handler.cc b/chrome/browser/ui/webui/options/managed_user_learn_more_handler.cc
index a1a77fd..177def7 100644
--- a/chrome/browser/ui/webui/options/managed_user_learn_more_handler.cc
+++ b/chrome/browser/ui/webui/options/managed_user_learn_more_handler.cc
@@ -20,9 +20,9 @@
   DCHECK(localized_strings);
 
   static OptionsStringResource resources[] = {
-    { "managedUserLearnMoreTitle", IDS_NEW_LIMITED_USER_LEARN_MORE_TITLE },
-    { "managedUserLearnMoreText", IDS_NEW_LIMITED_USER_LEARN_MORE_TEXT },
-    { "managedUserLearnMoreDone", IDS_NEW_LIMITED_USER_LEARN_MORE_DONE_BUTTON },
+    { "managedUserLearnMoreTitle", IDS_NEW_MANAGED_USER_LEARN_MORE_TITLE },
+    { "managedUserLearnMoreText", IDS_NEW_MANAGED_USER_LEARN_MORE_TEXT },
+    { "managedUserLearnMoreDone", IDS_NEW_MANAGED_USER_LEARN_MORE_DONE_BUTTON },
   };
 
   RegisterStrings(localized_strings, resources, arraysize(resources));
diff --git a/chrome/browser/ui/webui/options/media_galleries_handler.cc b/chrome/browser/ui/webui/options/media_galleries_handler.cc
index 90a9362..c157a1b 100644
--- a/chrome/browser/ui/webui/options/media_galleries_handler.cc
+++ b/chrome/browser/ui/webui/options/media_galleries_handler.cc
@@ -9,7 +9,6 @@
 #include "base/strings/string_number_conversions.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/media_galleries/media_file_system_registry.h"
-#include "chrome/browser/media_galleries/media_galleries_dialog_controller.h"
 #include "chrome/browser/media_galleries/media_galleries_preferences.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/storage_monitor/storage_monitor.h"
@@ -24,7 +23,6 @@
 
 namespace options {
 
-using chrome::MediaGalleriesDialogController;
 using chrome::MediaGalleriesPreferences;
 using chrome::MediaGalleriesPrefInfoMap;
 using chrome::MediaGalleryPrefInfo;
@@ -53,7 +51,7 @@
 }
 
 void MediaGalleriesHandler::InitializePage() {
-  chrome::StorageMonitor::GetInstance()->Initialize(
+  chrome::StorageMonitor::GetInstance()->EnsureInitialized(
       base::Bind(&MediaGalleriesHandler::InitializeOnStorageMonitorInit,
                  weak_ptr_factory_.GetWeakPtr()));
 }
@@ -75,7 +73,7 @@
 }
 
 void MediaGalleriesHandler::RegisterMessages() {
-  chrome::StorageMonitor::GetInstance()->Initialize(
+  chrome::StorageMonitor::GetInstance()->EnsureInitialized(
       base::Bind(&MediaGalleriesHandler::RegisterOnStorageMonitorInit,
                  weak_ptr_factory_.GetWeakPtr()));
 }
@@ -106,9 +104,7 @@
       continue;
 
     DictionaryValue* dict = new DictionaryValue();
-    dict->SetString("displayName",
-        MediaGalleriesDialogController::GetGalleryDisplayNameNoAttachment(
-            gallery));
+    dict->SetString("displayName", gallery.GetGalleryDisplayName());
     dict->SetString("path", gallery.AbsolutePath().LossyDisplayName());
     dict->SetString("id", base::Uint64ToString(gallery.pref_id));
     list.Append(dict);
diff --git a/chrome/browser/ui/webui/options/options_ui.cc b/chrome/browser/ui/webui/options/options_ui.cc
index f4567d9..11a58b1 100644
--- a/chrome/browser/ui/webui/options/options_ui.cc
+++ b/chrome/browser/ui/webui/options/options_ui.cc
@@ -15,7 +15,7 @@
 #include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
 #include "base/threading/thread.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/autocomplete/autocomplete_match.h"
 #include "chrome/browser/autocomplete/autocomplete_result.h"
@@ -59,6 +59,7 @@
 #include "grit/options_resources.h"
 #include "grit/theme_resources.h"
 #include "net/base/escape.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/webui/jstemplate_builder.h"
 #include "ui/webui/web_ui_util.h"
diff --git a/chrome/browser/ui/webui/options/preferences_browsertest.cc b/chrome/browser/ui/webui/options/preferences_browsertest.cc
index dab5306..da6b08d 100644
--- a/chrome/browser/ui/webui/options/preferences_browsertest.cc
+++ b/chrome/browser/ui/webui/options/preferences_browsertest.cc
@@ -33,7 +33,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 #if defined(OS_CHROMEOS)
-#include "base/stringprintf.h"
+#include "base/strings/stringprintf.h"
 #include "chrome/browser/chromeos/net/proxy_config_handler.h"
 #include "chrome/browser/chromeos/proxy_cros_settings_parser.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
diff --git a/chrome/browser/ui/webui/options/settings_app_browsertest.js b/chrome/browser/ui/webui/options/settings_app_browsertest.js
new file mode 100644
index 0000000..7de3546
--- /dev/null
+++ b/chrome/browser/ui/webui/options/settings_app_browsertest.js
@@ -0,0 +1,57 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * TestFixture for App Launcher's Settings App testing.
+ * @extends {testing.Test}
+ * @constructor
+ */
+function SettingsAppWebUITest() {}
+
+SettingsAppWebUITest.prototype = {
+  __proto__: testing.Test.prototype,
+
+  /**
+   * Browse to Settings App page, in a browser.
+   */
+  browsePreload: 'chrome://settings-frame/options_settings_app.html',
+};
+
+GEN('#if defined(ENABLE_SETTINGS_APP)');
+
+// Test opening Settings App, and do some checks on section visibility.
+TEST_F('SettingsAppWebUITest', 'testOpenSettingsApp', function() {
+  // Note there is no location bar in the Settings App.
+
+  // Some things are hidden via a parent, so make a helper function.
+  function isVisible(elementId) {
+    var elem = $(elementId);
+    return elem.offsetWidth > 0 || elem.offsetHeight > 0;
+  }
+  assertTrue(OptionsPage.isSettingsApp());
+  assertTrue(isVisible('sync-users-section'));
+  assertTrue(isVisible('sync-section'));
+
+  // Spot-check some regular settings items that should be hidden.
+  assertFalse(isVisible('change-home-page-section'));
+  assertFalse(isVisible('default-search-engine'));
+  assertFalse(isVisible('privacy-section'));
+  assertFalse(isVisible('startup-section'));
+});
+
+// Check functionality of LoadTimeData.overrideValues(), which the Settings App
+// uses. Do spot checks, so the test is not too fragile. Some of the content
+// strings rely on waiting for sync sign-in status, or platform-specifics.
+TEST_F('SettingsAppWebUITest', 'testStrings', function() {
+  // Ensure we check against the override values.
+  assertTrue(!!loadTimeData.getValue('settingsApp'));
+
+  // Check a product-specific label, to ensure it uses "App Launcher", and not
+  // Chrome / Chromium.
+  var languagesLabelElement =
+      document.querySelector('[i18n-content="languageSectionLabel"]');
+  assertNotEquals(-1, languagesLabelElement.innerHTML.indexOf('App Launcher'));
+});
+
+GEN('#endif  // defined(ENABLE_SETTINGS_APP)');
diff --git a/chrome/browser/ui/webui/performance_monitor/performance_monitor_handler.cc b/chrome/browser/ui/webui/performance_monitor/performance_monitor_handler.cc
index af7fbce..118452f 100644
--- a/chrome/browser/ui/webui/performance_monitor/performance_monitor_handler.cc
+++ b/chrome/browser/ui/webui/performance_monitor/performance_monitor_handler.cc
@@ -7,7 +7,7 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/command_line.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/performance_monitor/database.h"
 #include "chrome/browser/performance_monitor/event.h"
diff --git a/chrome/browser/ui/webui/performance_monitor/performance_monitor_ui_constants.cc b/chrome/browser/ui/webui/performance_monitor/performance_monitor_ui_constants.cc
index 07ffb35..a510e24 100644
--- a/chrome/browser/ui/webui/performance_monitor/performance_monitor_ui_constants.cc
+++ b/chrome/browser/ui/webui/performance_monitor/performance_monitor_ui_constants.cc
@@ -5,7 +5,7 @@
 #include "chrome/browser/ui/webui/performance_monitor/performance_monitor_ui_constants.h"
 
 #include "base/logging.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/performance_monitor/constants.h"
 
 namespace performance_monitor {
diff --git a/chrome/browser/ui/webui/performance_monitor/performance_monitor_ui_util.cc b/chrome/browser/ui/webui/performance_monitor/performance_monitor_ui_util.cc
index 2e8a9c1..5bf736b 100644
--- a/chrome/browser/ui/webui/performance_monitor/performance_monitor_ui_util.cc
+++ b/chrome/browser/ui/webui/performance_monitor/performance_monitor_ui_util.cc
@@ -6,7 +6,7 @@
 
 #include <algorithm>
 
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/performance_monitor/metric.h"
 
 namespace performance_monitor {
diff --git a/chrome/browser/ui/webui/performance_monitor/performance_monitor_ui_util_unittest.cc b/chrome/browser/ui/webui/performance_monitor/performance_monitor_ui_util_unittest.cc
index d120f38..6841ea8 100644
--- a/chrome/browser/ui/webui/performance_monitor/performance_monitor_ui_util_unittest.cc
+++ b/chrome/browser/ui/webui/performance_monitor/performance_monitor_ui_util_unittest.cc
@@ -5,7 +5,7 @@
 #include <string>
 
 #include "base/strings/string_number_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/performance_monitor/metric.h"
 #include "chrome/browser/ui/webui/performance_monitor/performance_monitor_ui_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ui/webui/policy_ui.cc b/chrome/browser/ui/webui/policy_ui.cc
index 2ee0e85..3b3f1ea 100644
--- a/chrome/browser/ui/webui/policy_ui.cc
+++ b/chrome/browser/ui/webui/policy_ui.cc
@@ -12,7 +12,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/strings/string16.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/policy/browser_policy_connector.h"
@@ -32,8 +32,12 @@
 #include "chrome/browser/policy/profile_policy_connector_factory.h"
 #include "chrome/browser/policy/proto/cloud/device_management_backend.pb.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/common/chrome_notification_types.h"
 #include "chrome/common/time_format.h"
 #include "chrome/common/url_constants.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+#include "content/public/browser/notification_service.h"
 #include "content/public/browser/web_ui.h"
 #include "content/public/browser/web_ui_data_source.h"
 #include "content/public/browser/web_ui_message_handler.h"
@@ -54,6 +58,17 @@
 #include "chrome/browser/policy/cloud/user_cloud_policy_manager_factory.h"
 #endif
 
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/extension_system.h"
+#include "chrome/browser/policy/policy_domain_descriptor.h"
+#include "chrome/browser/policy/policy_schema.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/extension_manifest_constants.h"
+#include "chrome/common/extensions/extension_set.h"
+#include "chrome/common/extensions/manifest.h"
+#endif
+
 namespace em = enterprise_management;
 
 namespace {
@@ -258,12 +273,18 @@
 #endif
 
 // The JavaScript message handler for the chrome://policy page.
-class PolicyUIHandler : public content::WebUIMessageHandler,
+class PolicyUIHandler : public content::NotificationObserver,
+                        public content::WebUIMessageHandler,
                         public policy::PolicyService::Observer {
  public:
   PolicyUIHandler();
   virtual ~PolicyUIHandler();
 
+  // content::NotificationObserver implementation.
+  virtual void Observe(int type,
+                       const content::NotificationSource& source,
+                       const content::NotificationDetails& details) OVERRIDE;
+
   // content::WebUIMessageHandler implementation.
   virtual void RegisterMessages() OVERRIDE;
 
@@ -286,6 +307,14 @@
   // information is sent.
   void SendStatus() const;
 
+  // Inserts a description of each policy in |policy_map| into |values|, using
+  // the optional errors in |errors| to determine the status of each policy.
+  void GetPolicyValues(const policy::PolicyMap& policy_map,
+                       policy::PolicyErrorMap* errors,
+                       base::DictionaryValue* values) const;
+
+  void GetChromePolicyValues(base::DictionaryValue* values) const;
+
   void HandleInitialized(const base::ListValue* args);
   void HandleReloadPolicies(const base::ListValue* args);
 
@@ -303,6 +332,8 @@
   scoped_ptr<CloudPolicyStatusProvider> user_status_provider_;
   scoped_ptr<CloudPolicyStatusProvider> device_status_provider_;
 
+  content::NotificationRegistrar registrar_;
+
   DISALLOW_COPY_AND_ASSIGN(PolicyUIHandler);
 };
 
@@ -425,6 +456,7 @@
 
 PolicyUIHandler::~PolicyUIHandler() {
   GetPolicyService()->RemoveObserver(policy::POLICY_DOMAIN_CHROME, this);
+  GetPolicyService()->RemoveObserver(policy::POLICY_DOMAIN_EXTENSIONS, this);
 }
 
 void PolicyUIHandler::RegisterMessages() {
@@ -472,6 +504,14 @@
   user_status_provider_->SetStatusChangeCallback(update_callback);
   device_status_provider_->SetStatusChangeCallback(update_callback);
   GetPolicyService()->AddObserver(policy::POLICY_DOMAIN_CHROME, this);
+  GetPolicyService()->AddObserver(policy::POLICY_DOMAIN_EXTENSIONS, this);
+
+  registrar_.Add(this,
+                 chrome::NOTIFICATION_EXTENSION_LOADED,
+                 content::NotificationService::AllSources());
+  registrar_.Add(this,
+                 chrome::NOTIFICATION_EXTENSION_UNLOADED,
+                 content::NotificationService::AllSources());
 
   web_ui()->RegisterMessageCallback(
       "initialized",
@@ -482,44 +522,119 @@
                  base::Unretained(this)));
 }
 
+void PolicyUIHandler::Observe(int type,
+                              const content::NotificationSource& source,
+                              const content::NotificationDetails& details) {
+  DCHECK(type == chrome::NOTIFICATION_EXTENSION_LOADED ||
+         type == chrome::NOTIFICATION_EXTENSION_UNLOADED);
+  SendPolicyNames();
+  SendPolicyValues();
+}
+
 void PolicyUIHandler::OnPolicyUpdated(const policy::PolicyNamespace& ns,
                                       const policy::PolicyMap& previous,
                                       const policy::PolicyMap& current) {
-  DCHECK_EQ(policy::POLICY_DOMAIN_CHROME, ns.domain);
-  DCHECK(ns.component_id.empty());
   SendPolicyValues();
 }
 
 void PolicyUIHandler::SendPolicyNames() const {
   base::DictionaryValue names;
+
+  // Add Chrome policy names.
+  base::DictionaryValue* chrome_policy_names = new base::DictionaryValue;
   const policy::PolicyDefinitionList* list =
       policy::GetChromePolicyDefinitionList();
   for (const policy::PolicyDefinitionList::Entry* entry = list->begin;
        entry != list->end; ++entry) {
-    names.SetBoolean(entry->name, true);
+    chrome_policy_names->SetBoolean(entry->name, true);
   }
+  names.Set("chromePolicyNames", chrome_policy_names);
+
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+  // Add extension policy names.
+  base::DictionaryValue* extension_policy_names = new base::DictionaryValue;
+  extensions::ExtensionSystem* extension_system =
+      extensions::ExtensionSystem::Get(Profile::FromWebUI(web_ui()));
+  const ExtensionSet* extensions =
+      extension_system->extension_service()->extensions();
+  scoped_refptr<const policy::PolicyDomainDescriptor> policy_domain_descriptor;
+  policy_domain_descriptor = GetPolicyService()->
+      GetPolicyDomainDescriptor(policy::POLICY_DOMAIN_EXTENSIONS);
+  const policy::PolicyDomainDescriptor::SchemaMap& schema_map =
+      policy_domain_descriptor->components();
+
+  for (ExtensionSet::const_iterator it = extensions->begin();
+       it != extensions->end(); ++it) {
+    const extensions::Extension* extension = it->get();
+    // Skip this extension if it's not an enterprise extension.
+    if (!extension->manifest()->HasPath(
+        extension_manifest_keys::kStorageManagedSchema))
+      continue;
+    base::DictionaryValue* extension_value = new base::DictionaryValue;
+    extension_value->SetString("name", extension->name());
+    policy::PolicyDomainDescriptor::SchemaMap::const_iterator schema =
+        schema_map.find(extension->id());
+    base::DictionaryValue* policy_names = new base::DictionaryValue;
+    if (schema != schema_map.end()) {
+      // Get policy names from the extension's policy schema.
+      // Store in a map, not an array, for faster lookup on JS side.
+      const policy::PolicySchemaMap* policies = schema->second->GetProperties();
+      policy::PolicySchemaMap::const_iterator it_policies;
+      for (it_policies = policies->begin(); it_policies != policies->end();
+           it_policies++) {
+        policy_names->SetBoolean(it_policies->first, true);
+      }
+    }
+    extension_value->Set("policyNames", policy_names);
+    extension_policy_names->Set(extension->id(), extension_value);
+  }
+  names.Set("extensionPolicyNames", extension_policy_names);
+#endif
+
   web_ui()->CallJavascriptFunction("policy.Page.setPolicyNames", names);
 }
 
 void PolicyUIHandler::SendPolicyValues() const {
-  // Make a copy that can be modified, since some policy values are modified
-  // before being displayed.
-  policy::PolicyMap map;
-  map.CopyFrom(GetPolicyService()->GetPolicies(policy::PolicyNamespace(
-      policy::POLICY_DOMAIN_CHROME, std::string())));
+  base::DictionaryValue all_policies;
 
-  // Get a list of all the errors in the policy values.
-  const policy::ConfigurationPolicyHandlerList* handler_list =
-      g_browser_process->browser_policy_connector()->GetHandlerList();
-  policy::PolicyErrorMap errors;
-  handler_list->ApplyPolicySettings(map, NULL, &errors);
+  // Add Chrome policy values.
+  base::DictionaryValue* chrome_policies = new base::DictionaryValue;
+  GetChromePolicyValues(chrome_policies);
+  all_policies.Set("chromePolicies", chrome_policies);
 
-  // Convert dictionary values to strings for display.
-  handler_list->PrepareForDisplaying(&map);
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+  // Add extension policy values.
+  extensions::ExtensionSystem* extension_system =
+      extensions::ExtensionSystem::Get(Profile::FromWebUI(web_ui()));
+  const ExtensionSet* extensions =
+      extension_system->extension_service()->extensions();
+  base::DictionaryValue* extension_values = new base::DictionaryValue;
 
-  base::DictionaryValue values;
+  for (ExtensionSet::const_iterator it = extensions->begin();
+       it != extensions->end(); ++it) {
+    const extensions::Extension* extension = it->get();
+    // Skip this extension if it's not an enterprise extension.
+    if (!extension->manifest()->HasPath(
+        extension_manifest_keys::kStorageManagedSchema))
+      continue;
+    base::DictionaryValue* extension_policies = new base::DictionaryValue;
+    policy::PolicyNamespace policy_namespace = policy::PolicyNamespace(
+        policy::POLICY_DOMAIN_EXTENSIONS, extension->id());
+    policy::PolicyErrorMap empty_error_map;
+    GetPolicyValues(GetPolicyService()->GetPolicies(policy_namespace),
+                    &empty_error_map, extension_policies);
+    extension_values->Set(extension->id(), extension_policies);
+  }
+  all_policies.Set("extensionPolicies", extension_values);
+#endif
+  web_ui()->CallJavascriptFunction("policy.Page.setPolicyValues", all_policies);
+}
+
+void PolicyUIHandler::GetPolicyValues(const policy::PolicyMap& map,
+                                      policy::PolicyErrorMap* errors,
+                                      base::DictionaryValue* values) const {
   for (policy::PolicyMap::const_iterator entry = map.begin();
-      entry != map.end(); ++entry) {
+       entry != map.end(); ++entry) {
     base::DictionaryValue* value = new base::DictionaryValue;
     value->Set("value", entry->second.value->DeepCopy());
     if (entry->second.scope == policy::POLICY_SCOPE_USER)
@@ -530,13 +645,33 @@
       value->SetString("level", "recommended");
     else
       value->SetString("level", "mandatory");
-    string16 error = errors.GetErrors(entry->first);
+    string16 error = errors->GetErrors(entry->first);
     if (!error.empty())
       value->SetString("error", error);
-    values.Set(entry->first, value);
+    values->Set(entry->first, value);
   }
+}
 
-  web_ui()->CallJavascriptFunction("policy.Page.setPolicyValues", values);
+void PolicyUIHandler::GetChromePolicyValues(
+    base::DictionaryValue* values) const {
+  policy::PolicyService* policy_service = GetPolicyService();
+  policy::PolicyMap map;
+
+  // Make a copy that can be modified, since some policy values are modified
+  // before being displayed.
+  map.CopyFrom(policy_service->GetPolicies(
+      policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME, std::string())));
+
+  // Get a list of all the errors in the policy values.
+  const policy::ConfigurationPolicyHandlerList* handler_list =
+      g_browser_process->browser_policy_connector()->GetHandlerList();
+  policy::PolicyErrorMap errors;
+  handler_list->ApplyPolicySettings(map, NULL, &errors);
+
+  // Convert dictionary values to strings for display.
+  handler_list->PrepareForDisplaying(&map);
+
+  GetPolicyValues(map, &errors, values);
 }
 
 void PolicyUIHandler::SendStatus() const {
diff --git a/chrome/browser/ui/webui/policy_ui_browsertest.cc b/chrome/browser/ui/webui/policy_ui_browsertest.cc
index 13fc4ff..2d8193f 100644
--- a/chrome/browser/ui/webui/policy_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/policy_ui_browsertest.cc
@@ -122,7 +122,7 @@
   // Retrieve the text contents of the policy table cells for all policies.
   const std::string javascript =
       "var entries = document.querySelectorAll("
-      "    'table#policy-table > tbody');"
+      "    'section.policy-table-section > * > tbody');"
       "var policies = [];"
       "for (var i = 0; i < entries.length; ++i) {"
       "  var items = entries[i].querySelectorAll('tr > td');"
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_ui.h b/chrome/browser/ui/webui/print_preview/print_preview_ui.h
index 4cfd242..51fdd02 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_ui.h
+++ b/chrome/browser/ui/webui/print_preview/print_preview_ui.h
@@ -9,7 +9,7 @@
 
 #include "base/gtest_prod_util.h"
 #include "base/memory/ref_counted.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/ui/webui/constrained_web_dialog_ui.h"
 
 class PrintPreviewDataService;
diff --git a/chrome/browser/ui/webui/quota_internals/quota_internals_types.h b/chrome/browser/ui/webui/quota_internals/quota_internals_types.h
index 0291567..a559782 100644
--- a/chrome/browser/ui/webui/quota_internals/quota_internals_types.h
+++ b/chrome/browser/ui/webui/quota_internals/quota_internals_types.h
@@ -8,7 +8,7 @@
 #include <map>
 #include <string>
 
-#include "base/time.h"
+#include "base/time/time.h"
 #include "googleurl/src/gurl.h"
 #include "webkit/common/quota/quota_types.h"
 
diff --git a/chrome/browser/ui/webui/set_as_default_browser_ui.cc b/chrome/browser/ui/webui/set_as_default_browser_ui.cc
index d939033..89184e2 100644
--- a/chrome/browser/ui/webui/set_as_default_browser_ui.cc
+++ b/chrome/browser/ui/webui/set_as_default_browser_ui.cc
@@ -23,8 +23,8 @@
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/singleton_tabs.h"
+#include "chrome/browser/ui/sync/sync_promo_ui.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/browser/ui/webui/sync_promo/sync_promo_ui.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/installer/util/install_util.h"
diff --git a/chrome/browser/ui/webui/signin/login_ui_service.cc b/chrome/browser/ui/webui/signin/login_ui_service.cc
index baa07f7..cae530f 100644
--- a/chrome/browser/ui/webui/signin/login_ui_service.cc
+++ b/chrome/browser/ui/webui/signin/login_ui_service.cc
@@ -11,8 +11,8 @@
 #include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/host_desktop.h"
 #include "chrome/browser/ui/sync/inline_login_dialog.h"
+#include "chrome/browser/ui/sync/sync_promo_ui.h"
 #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
-#include "chrome/browser/ui/webui/sync_promo/sync_promo_ui.h"
 #include "chrome/common/url_constants.h"
 
 #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/ui/webui/sync_file_system_internals/extension_statuses_handler.cc b/chrome/browser/ui/webui/sync_file_system_internals/extension_statuses_handler.cc
index 15aa2f4..9e35e1e 100644
--- a/chrome/browser/ui/webui/sync_file_system_internals/extension_statuses_handler.cc
+++ b/chrome/browser/ui/webui/sync_file_system_internals/extension_statuses_handler.cc
@@ -9,9 +9,12 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/values.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/extension_system.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sync_file_system/sync_file_system_service.h"
 #include "chrome/browser/sync_file_system/sync_file_system_service_factory.h"
+#include "chrome/common/extensions/extension.h"
 #include "content/public/browser/web_ui.h"
 #include "content/public/browser/web_ui_data_source.h"
 #include "grit/sync_file_system_internals_resources.h"
@@ -33,23 +36,42 @@
                  base::Unretained(this)));
 }
 
-void ExtensionStatusesHandler::GetExtensionStatuses(
-    const base::ListValue* args) {
-  DCHECK(args);
+//static
+void ExtensionStatusesHandler::GetExtensionStatusesAsDictionary(
+    Profile* profile,
+    base::ListValue* values) {
+  DCHECK(profile);
+  DCHECK(values);
   std::map<GURL, std::string> status_map;
-  SyncFileSystemServiceFactory::GetForProfile(profile_)->GetExtensionStatusMap(
+  SyncFileSystemServiceFactory::GetForProfile(profile)->GetExtensionStatusMap(
       &status_map);
 
-  base::ListValue list;
+  ExtensionService* extension_service =
+      extensions::ExtensionSystem::Get(profile)->extension_service();
+  DCHECK(extension_service);
   for (std::map<GURL, std::string>::const_iterator itr = status_map.begin();
        itr != status_map.end();
        ++itr) {
-    base::DictionaryValue* dict = new DictionaryValue;
-    dict->SetString("extensionID", itr->first.spec());
-    dict->SetString("status", itr->second);
-    list.Append(dict);
-  }
+    std::string extension_id = itr->first.HostNoBrackets();
 
+    // Join with human readable extension name.
+    const extensions::Extension* extension =
+        extension_service->GetExtensionById(extension_id, true);
+    DCHECK(extension);
+
+    base::DictionaryValue* dict = new DictionaryValue;
+    dict->SetString("extensionID", extension_id);
+    dict->SetString("extensionName", extension->name());
+    dict->SetString("status", itr->second);
+    values->Append(dict);
+  }
+}
+
+void ExtensionStatusesHandler::GetExtensionStatuses(
+    const base::ListValue* args) {
+  DCHECK(args);
+  base::ListValue list;
+  GetExtensionStatusesAsDictionary(profile_, &list);
   web_ui()->CallJavascriptFunction("ExtensionStatuses.onGetExtensionStatuses",
                                    list);
 }
diff --git a/chrome/browser/ui/webui/sync_file_system_internals/extension_statuses_handler.h b/chrome/browser/ui/webui/sync_file_system_internals/extension_statuses_handler.h
index 74b1cbb..94e9442 100644
--- a/chrome/browser/ui/webui/sync_file_system_internals/extension_statuses_handler.h
+++ b/chrome/browser/ui/webui/sync_file_system_internals/extension_statuses_handler.h
@@ -21,6 +21,11 @@
   explicit ExtensionStatusesHandler(Profile* profile);
   virtual ~ExtensionStatusesHandler();
 
+  // Shared by Extension Statuses Tab and also File Metadata Tab to generate the
+  // extension drop down.
+  static void GetExtensionStatusesAsDictionary(Profile* profile,
+                                               base::ListValue* values);
+
   // WebUIMessageHandler implementation.
   virtual void RegisterMessages() OVERRIDE;
 
diff --git a/chrome/browser/ui/webui/sync_file_system_internals/file_metadata_handler.cc b/chrome/browser/ui/webui/sync_file_system_internals/file_metadata_handler.cc
index 6b508ad..42025bf 100644
--- a/chrome/browser/ui/webui/sync_file_system_internals/file_metadata_handler.cc
+++ b/chrome/browser/ui/webui/sync_file_system_internals/file_metadata_handler.cc
@@ -14,6 +14,8 @@
 #include "chrome/browser/sync_file_system/file_metadata.h"
 #include "chrome/browser/sync_file_system/sync_file_system_service.h"
 #include "chrome/browser/sync_file_system/sync_file_system_service_factory.h"
+#include "chrome/browser/ui/webui/sync_file_system_internals/extension_statuses_handler.h"
+#include "chrome/common/extensions/extension.h"
 #include "content/public/browser/web_ui.h"
 #include "content/public/browser/web_ui_data_source.h"
 #include "grit/sync_file_system_internals_resources.h"
@@ -49,6 +51,10 @@
 
 void FileMetadataHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
+      "getExtensions",
+      base::Bind(&FileMetadataHandler::GetExtensions,
+                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
       "getFileMetadata",
       base::Bind(&FileMetadataHandler::GetFileMetadata,
                  base::Unretained(this)));
@@ -56,9 +62,22 @@
 
 void FileMetadataHandler::GetFileMetadata(
     const base::ListValue* args) {
-  OriginFileMetadataMap* metadata_map = new OriginFileMetadataMap;
+  std::string extension_id;
+  if (!args->GetString(0, &extension_id) || extension_id.empty()) {
+    LOG(WARNING) << "GetFileMetadata() Extension ID wasn't given";
+    return;
+  }
+
+  // Extension ID from JS is just the host. Need to reformat it to chrome
+  // extension type GURL.
+  const GURL origin = extensions::Extension::GetBaseURLFromExtensionId(
+      extension_id);
+
+  // Get all metadata for the one specific origin.
+  FileMetadataMap* metadata_map = new FileMetadataMap;
   size_t* num_results = new size_t(0);
   SyncFileSystemServiceFactory::GetForProfile(profile_)->GetFileMetadataMap(
+      origin,
       metadata_map,
       num_results,
       base::Bind(&FileMetadataHandler::DidGetFileMetadata,
@@ -67,11 +86,18 @@
                  base::Owned(num_results)));
 }
 
+void FileMetadataHandler::GetExtensions(const base::ListValue* args) {
+  DCHECK(args);
+  base::ListValue list;
+  ExtensionStatusesHandler::GetExtensionStatusesAsDictionary(profile_, &list);
+  web_ui()->CallJavascriptFunction("FileMetadata.onGetExtensions", list);
+}
+
 // TODO(calvinlo): This would probably be better if there was a drop down UI
 // box to pick one origin at a time. Then this function would only print
 // files for one origin.
 void FileMetadataHandler::DidGetFileMetadata(
-    OriginFileMetadataMap* metadata_map,
+    FileMetadataMap* metadata_map,
     size_t* num_results,
     sync_file_system::SyncStatusCode status) {
   DCHECK(metadata_map);
@@ -79,30 +105,24 @@
 
   // Flatten map hierarchy in initial version.
   base::ListValue list;
-  RemoteFileSyncService::OriginFileMetadataMap::const_iterator origin_itr;
-  for (origin_itr = metadata_map->begin();
-       origin_itr != metadata_map->end();
-       ++origin_itr) {
-    RemoteFileSyncService::FileMetadataMap::const_iterator file_path_itr;
-    for (file_path_itr = origin_itr->second.begin();
-         file_path_itr != origin_itr->second.end();
-         ++file_path_itr) {
-      const GURL& origin = origin_itr->first;
-      const FileMetadata& metadata_object = file_path_itr->second;
-      std::string status_string = extensions::api::sync_file_system::ToString(
-            extensions::SyncFileStatusToExtensionEnum(
-                metadata_object.sync_status));
+  RemoteFileSyncService::FileMetadataMap::const_iterator file_path_itr;
+  for (file_path_itr = metadata_map->begin();
+       file_path_itr != metadata_map->end();
+       ++file_path_itr) {
+    const FileMetadata& metadata_object = file_path_itr->second;
+    std::string status_string = extensions::api::sync_file_system::ToString(
+          extensions::SyncFileStatusToExtensionEnum(
+              metadata_object.sync_status));
 
-      // Convert each file metadata object into primitives for rendering.
-      base::DictionaryValue* dict = new DictionaryValue;
-      dict->SetString("origin", origin.spec());
-      dict->SetString("status", status_string);
-      dict->SetString("type", FileTypeToString(metadata_object.type));
-      dict->SetString("title", metadata_object.title);
-      dict->SetString("details", metadata_object.service_specific_metadata);
-      list.Append(dict);
-    }
+    // Convert each file metadata object into primitives for rendering.
+    base::DictionaryValue* dict = new DictionaryValue;
+    dict->SetString("status", status_string);
+    dict->SetString("type", FileTypeToString(metadata_object.type));
+    dict->SetString("title", metadata_object.title);
+    dict->SetString("details", metadata_object.service_specific_metadata);
+    list.Append(dict);
   }
+
   web_ui()->CallJavascriptFunction("FileMetadata.onGetFileMetadata", list);
 }
 
diff --git a/chrome/browser/ui/webui/sync_file_system_internals/file_metadata_handler.h b/chrome/browser/ui/webui/sync_file_system_internals/file_metadata_handler.h
index b7e2e22..64a8152 100644
--- a/chrome/browser/ui/webui/sync_file_system_internals/file_metadata_handler.h
+++ b/chrome/browser/ui/webui/sync_file_system_internals/file_metadata_handler.h
@@ -29,11 +29,13 @@
   virtual void RegisterMessages() OVERRIDE;
 
  private:
-  typedef sync_file_system::RemoteFileSyncService::OriginFileMetadataMap
-      OriginFileMetadataMap;
+  void GetExtensions(const base::ListValue* args);
+
+  typedef sync_file_system::RemoteFileSyncService::FileMetadataMap
+      FileMetadataMap;
   void GetFileMetadata(const base::ListValue* args);
   void DidGetFileMetadata(
-      OriginFileMetadataMap* metadata_map,
+      FileMetadataMap* metadata_map,
       size_t* num_results,
       sync_file_system::SyncStatusCode status);
 
diff --git a/chrome/browser/ui/webui/sync_file_system_internals/sync_file_system_internals_handler.cc b/chrome/browser/ui/webui/sync_file_system_internals/sync_file_system_internals_handler.cc
index 200d88c..1890731 100644
--- a/chrome/browser/ui/webui/sync_file_system_internals/sync_file_system_internals_handler.cc
+++ b/chrome/browser/ui/webui/sync_file_system_internals/sync_file_system_internals_handler.cc
@@ -20,7 +20,7 @@
 #include "content/public/browser/storage_partition.h"
 #include "content/public/browser/web_ui.h"
 
-using google_apis::EventLogger;
+using drive::EventLogger;
 using sync_file_system::SyncFileSystemServiceFactory;
 using sync_file_system::SyncServiceState;
 
@@ -90,8 +90,8 @@
 
 void SyncFileSystemInternalsHandler::GetNotificationSource(
     const base::ListValue* args) {
-  google_apis::DriveNotificationManager* drive_notification_manager =
-      google_apis::DriveNotificationManagerFactory::GetForProfile(profile_);
+  drive::DriveNotificationManager* drive_notification_manager =
+      drive::DriveNotificationManagerFactory::GetForProfile(profile_);
   bool xmpp_enabled = drive_notification_manager->push_notification_enabled();
   std::string notification_source = xmpp_enabled ? "XMPP" : "Polling";
   web_ui()->CallJavascriptFunction("SyncService.onGetNotificationSource",
diff --git a/chrome/browser/ui/webui/sync_promo/sync_promo_trial.cc b/chrome/browser/ui/webui/sync_promo/sync_promo_trial.cc
index 14517a7..a410d2b 100644
--- a/chrome/browser/ui/webui/sync_promo/sync_promo_trial.cc
+++ b/chrome/browser/ui/webui/sync_promo/sync_promo_trial.cc
@@ -6,7 +6,7 @@
 
 #include "base/logging.h"
 #include "chrome/browser/metrics/metrics_service.h"
-#include "chrome/browser/ui/webui/sync_promo/sync_promo_ui.h"
+#include "chrome/browser/ui/sync/sync_promo_ui.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
 
diff --git a/chrome/browser/ui/webui/sync_promo/sync_promo_trial.h b/chrome/browser/ui/webui/sync_promo/sync_promo_trial.h
index c4510ea..f522ba9 100644
--- a/chrome/browser/ui/webui/sync_promo/sync_promo_trial.h
+++ b/chrome/browser/ui/webui/sync_promo/sync_promo_trial.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_UI_WEBUI_SYNC_PROMO_SYNC_PROMO_TRIAL_H_
 
 #include "base/basictypes.h"
-#include "chrome/browser/ui/webui/sync_promo/sync_promo_ui.h"
+#include "chrome/browser/ui/sync/sync_promo_ui.h"
 
 class Profile;
 namespace content {
diff --git a/chrome/browser/ui/webui/sync_promo/sync_promo_ui.cc b/chrome/browser/ui/webui/sync_promo/sync_promo_ui.cc
deleted file mode 100644
index b63325d..0000000
--- a/chrome/browser/ui/webui/sync_promo/sync_promo_ui.cc
+++ /dev/null
@@ -1,275 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/webui/sync_promo/sync_promo_ui.h"
-
-#include "base/command_line.h"
-#include "base/prefs/pref_service.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/first_run/first_run.h"
-#include "chrome/browser/google/google_util.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/profiles/profile_info_cache.h"
-#include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/browser/signin/signin_manager.h"
-#include "chrome/browser/signin/signin_manager_factory.h"
-#include "chrome/browser/sync/profile_sync_service.h"
-#include "chrome/browser/sync/profile_sync_service_factory.h"
-#include "chrome/browser/ui/webui/options/core_options_handler.h"
-#include "chrome/browser/ui/webui/sync_promo/sync_promo_trial.h"
-#include "chrome/browser/ui/webui/theme_source.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/net/url_util.h"
-#include "chrome/common/pref_names.h"
-#include "chrome/common/url_constants.h"
-#include "components/user_prefs/pref_registry_syncable.h"
-#include "content/public/browser/url_data_source.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_ui.h"
-#include "content/public/browser/web_ui_data_source.h"
-#include "google_apis/gaia/gaia_urls.h"
-#include "grit/browser_resources.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-#include "net/base/escape.h"
-#include "net/base/network_change_notifier.h"
-#include "net/base/url_util.h"
-#include "ui/base/l10n/l10n_util.h"
-
-using content::WebContents;
-
-namespace {
-
-const char kStringsJsFile[] = "strings.js";
-const char kSyncPromoJsFile[] = "sync_promo.js";
-
-const char kSyncPromoQueryKeyAutoClose[] = "auto_close";
-const char kSyncPromoQueryKeyContinue[] = "continue";
-const char kSyncPromoQueryKeySource[] = "source";
-
-// Gaia cannot support about:blank as a continue URL, so using a hosted blank
-// page instead.
-const char kSyncLandingUrlPrefix[] =
-    "https://www.google.com/intl/%s/chrome/blank.html";
-
-// The maximum number of times we want to show the sync promo at startup.
-const int kSyncPromoShowAtStartupMaximum = 10;
-
-// Forces the web based signin flow when set.
-bool g_force_web_based_signin_flow = false;
-
-// Checks we want to show the sync promo for the given brand.
-bool AllowPromoAtStartupForCurrentBrand() {
-  std::string brand;
-  google_util::GetBrand(&brand);
-
-  if (brand.empty())
-    return true;
-
-  if (google_util::IsInternetCafeBrandCode(brand))
-    return false;
-
-  // Enable for both organic and distribution.
-  return true;
-}
-
-}  // namespace
-
-// static
-bool SyncPromoUI::HasShownPromoAtStartup(Profile* profile) {
-  return profile->GetPrefs()->HasPrefPath(prefs::kSyncPromoStartupCount);
-}
-
-// static
-bool SyncPromoUI::ShouldShowSyncPromo(Profile* profile) {
-#if defined(OS_CHROMEOS)
-  // There's no need to show the sync promo on cros since cros users are logged
-  // into sync already.
-  return false;
-#else
-
-  // Don't bother if we don't have any kind of network connection.
-  if (net::NetworkChangeNotifier::IsOffline())
-    return false;
-
-  // Don't show if the profile is an incognito.
-  if (profile->IsOffTheRecord())
-    return false;
-
-  // Don't show for managed profiles.
-  if (profile->GetPrefs()->GetBoolean(prefs::kProfileIsManaged))
-    return false;
-
-  // Display the signin promo if the user is not signed in.
-  SigninManager* signin = SigninManagerFactory::GetForProfile(
-      profile->GetOriginalProfile());
-  return !signin->AuthInProgress() && signin->IsSigninAllowed() &&
-      signin->GetAuthenticatedUsername().empty();
-#endif
-}
-
-// static
-void SyncPromoUI::RegisterUserPrefs(
-    user_prefs::PrefRegistrySyncable* registry) {
-  registry->RegisterIntegerPref(
-      prefs::kSyncPromoStartupCount,
-      0,
-      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
-  registry->RegisterBooleanPref(
-      prefs::kSyncPromoUserSkipped,
-      false,
-      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
-  registry->RegisterBooleanPref(
-      prefs::kSyncPromoShowOnFirstRunAllowed,
-      true,
-      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
-  registry->RegisterBooleanPref(
-      prefs::kSyncPromoShowNTPBubble,
-      false,
-      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
-  registry->RegisterStringPref(
-      prefs::kSyncPromoErrorMessage,
-      std::string(),
-      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
-}
-
-// static
-bool SyncPromoUI::ShouldShowSyncPromoAtStartup(Profile* profile,
-                                               bool is_new_profile) {
-  DCHECK(profile);
-
-  if (!ShouldShowSyncPromo(profile))
-    return false;
-
-  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
-  if (command_line.HasSwitch(switches::kNoFirstRun))
-    is_new_profile = false;
-
-  if (!is_new_profile) {
-    if (!HasShownPromoAtStartup(profile))
-      return false;
-  }
-
-  if (HasUserSkippedSyncPromo(profile))
-    return false;
-
-  // For Chinese users skip the sync promo.
-  if (g_browser_process->GetApplicationLocale() == "zh-CN")
-    return false;
-
-  PrefService* prefs = profile->GetPrefs();
-  int show_count = prefs->GetInteger(prefs::kSyncPromoStartupCount);
-  if (show_count >= kSyncPromoShowAtStartupMaximum)
-    return false;
-
-  // This pref can be set in the master preferences file to allow or disallow
-  // showing the sync promo at startup.
-  if (prefs->HasPrefPath(prefs::kSyncPromoShowOnFirstRunAllowed))
-    return prefs->GetBoolean(prefs::kSyncPromoShowOnFirstRunAllowed);
-
-  // For now don't show the promo for some brands.
-  if (!AllowPromoAtStartupForCurrentBrand())
-    return false;
-
-  // Default to show the promo for Google Chrome builds.
-#if defined(GOOGLE_CHROME_BUILD)
-  return true;
-#else
-  return false;
-#endif
-}
-
-void SyncPromoUI::DidShowSyncPromoAtStartup(Profile* profile) {
-  int show_count = profile->GetPrefs()->GetInteger(
-      prefs::kSyncPromoStartupCount);
-  show_count++;
-  profile->GetPrefs()->SetInteger(prefs::kSyncPromoStartupCount, show_count);
-}
-
-bool SyncPromoUI::HasUserSkippedSyncPromo(Profile* profile) {
-  return profile->GetPrefs()->GetBoolean(prefs::kSyncPromoUserSkipped);
-}
-
-void SyncPromoUI::SetUserSkippedSyncPromo(Profile* profile) {
-  profile->GetPrefs()->SetBoolean(prefs::kSyncPromoUserSkipped, true);
-}
-
-// static
-std::string SyncPromoUI::GetSyncLandingURL(const char* option, int value) {
-  const std::string& locale = g_browser_process->GetApplicationLocale();
-  std::string url = base::StringPrintf(kSyncLandingUrlPrefix, locale.c_str());
-  base::StringAppendF(&url, "?%s=%d", option, value);
-  return url;
-}
-
-// static
-GURL SyncPromoUI::GetSyncPromoURL(Source source, bool auto_close) {
-  DCHECK_NE(SOURCE_UNKNOWN, source);
-
-  std::string url_string;
-
-  // Build a Gaia-based URL that can be used to sign the user into chrome.
-  // There are required request parameters:
-  //
-  //  - tell Gaia which service the user is signing into.  In this case,
-  //    a chrome sign in uses the service "chromiumsync"
-  //  - provide a continue URL.  This is the URL that Gaia will redirect to
-  //    once the sign is complete.
-  //
-  // The continue URL includes a source parameter that can be extracted using
-  // the function GetSourceForSyncPromoURL() below.  This is used to know
-  // which of the chrome sign in access points was used to sign the user in.
-  // See OneClickSigninHelper for details.
-  url_string = GaiaUrls::GetInstance()->service_login_url();
-  url_string.append("?service=chromiumsync&sarp=1");
-
-  std::string continue_url = GetSyncLandingURL(
-      kSyncPromoQueryKeySource, static_cast<int>(source));
-
-  base::StringAppendF(&url_string, "&%s=%s", kSyncPromoQueryKeyContinue,
-                      net::EscapeQueryParamValue(
-                          continue_url, false).c_str());
-
-  return GURL(url_string);
-}
-
-// static
-GURL SyncPromoUI::GetNextPageURLForSyncPromoURL(const GURL& url) {
-  std::string value;
-  if (net::GetValueForKeyInQuery(url, kSyncPromoQueryKeyContinue, &value))
-    return GURL(value);
-
-  return GURL();
-}
-
-// static
-SyncPromoUI::Source SyncPromoUI::GetSourceForSyncPromoURL(const GURL& url) {
-  std::string value;
-  if (net::GetValueForKeyInQuery(url, kSyncPromoQueryKeySource, &value)) {
-    int source = 0;
-    if (base::StringToInt(value, &source) && source >= SOURCE_START_PAGE &&
-        source < SOURCE_UNKNOWN) {
-      return static_cast<Source>(source);
-    }
-  }
-  return SOURCE_UNKNOWN;
-}
-
-// static
-bool SyncPromoUI::IsContinueUrlForWebBasedSigninFlow(const GURL& url) {
-  GURL::Replacements replacements;
-  replacements.ClearQuery();
-  const std::string& locale = g_browser_process->GetApplicationLocale();
-  return url.ReplaceComponents(replacements) ==
-      GURL(base::StringPrintf(kSyncLandingUrlPrefix, locale.c_str()));
-}
-
-// static
-void SyncPromoUI::ForceWebBasedSigninFlowForTesting(bool force) {
-  g_force_web_based_signin_flow = force;
-}
diff --git a/chrome/browser/ui/webui/sync_promo/sync_promo_ui.h b/chrome/browser/ui/webui/sync_promo/sync_promo_ui.h
deleted file mode 100644
index ae67031..0000000
--- a/chrome/browser/ui/webui/sync_promo/sync_promo_ui.h
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_WEBUI_SYNC_PROMO_SYNC_PROMO_UI_H_
-#define CHROME_BROWSER_UI_WEBUI_SYNC_PROMO_SYNC_PROMO_UI_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-
-class GURL;
-class Profile;
-
-namespace user_prefs {
-class PrefRegistrySyncable;
-}
-
-// Static helper functions useful for chrome sign in.
-class SyncPromoUI {
- public:
-  // Please keep this in sync with enums in sync_promo_trial.cc.
-  enum Source {
-    SOURCE_START_PAGE = 0, // This must be first.
-    SOURCE_NTP_LINK,
-    SOURCE_MENU,
-    SOURCE_SETTINGS,
-    SOURCE_EXTENSION_INSTALL_BUBBLE,
-    SOURCE_WEBSTORE_INSTALL,
-    SOURCE_APP_LAUNCHER,
-    SOURCE_APPS_PAGE_LINK,
-    SOURCE_UNKNOWN, // This must be last.
-  };
-
-  // Returns true if the sync promo should be visible.
-  // |profile| is the profile of the tab the promo would be shown on.
-  static bool ShouldShowSyncPromo(Profile* profile);
-
-  // Returns true if we should show the sync promo at startup.
-  static bool ShouldShowSyncPromoAtStartup(Profile* profile,
-                                           bool is_new_profile);
-
-  // Called when the sync promo has been shown so that we can keep track
-  // of the number of times we've displayed it.
-  static void DidShowSyncPromoAtStartup(Profile* profile);
-
-  // Returns true if a user has seen the sync promo at startup previously.
-  static bool HasShownPromoAtStartup(Profile* profile);
-
-  // Returns true if the user has previously skipped the sync promo.
-  static bool HasUserSkippedSyncPromo(Profile* profile);
-
-  // Registers the fact that the user has skipped the sync promo.
-  static void SetUserSkippedSyncPromo(Profile* profile);
-
-  // Registers the preferences the Sync Promo UI needs.
-  static void RegisterUserPrefs(user_prefs::PrefRegistrySyncable* registry);
-
-  // Gets the sync landing page URL.
-  static std::string GetSyncLandingURL(const char* option, int value);
-
-  // Returns the sync promo URL wth the given arguments in the query.
-  // |source| identifies from where the sync promo is being called, and is used
-  // to record sync promo UMA stats in the context of the source.
-  // |auto_close| whether to close the sync promo automatically when done.
-  static GURL GetSyncPromoURL(Source source, bool auto_close);
-
-  // Gets the next page URL from the query portion of the sync promo URL.
-  static GURL GetNextPageURLForSyncPromoURL(const GURL& url);
-
-  // Gets the source from the query portion of the sync promo URL.
-  // The source identifies from where the sync promo was opened.
-  static Source GetSourceForSyncPromoURL(const GURL& url);
-
-  // Returns true if the given URL is the standard continue URL used with the
-  // sync promo when the web-based flow is enabled.  The query parameters
-  // of the URL are ignored for this comparison.
-  static bool IsContinueUrlForWebBasedSigninFlow(const GURL& url);
-
-  // Forces UseWebBasedSigninFlow() to return true when set; used in tests only.
-  static void ForceWebBasedSigninFlowForTesting(bool force);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(SyncPromoUI);
-};
-
-#endif  // CHROME_BROWSER_UI_WEBUI_SYNC_PROMO_SYNC_PROMO_UI_H_
diff --git a/chrome/browser/ui/webui/sync_setup_handler.cc b/chrome/browser/ui/webui/sync_setup_handler.cc
index 03a82fe..11085ea 100644
--- a/chrome/browser/ui/webui/sync_setup_handler.cc
+++ b/chrome/browser/ui/webui/sync_setup_handler.cc
@@ -29,10 +29,10 @@
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/browser/ui/sync/signin_histogram.h"
+#include "chrome/browser/ui/sync/sync_promo_ui.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/webui/signin/login_ui_service.h"
 #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
-#include "chrome/browser/ui/webui/sync_promo/sync_promo_ui.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
@@ -652,7 +652,7 @@
 }
 
 void SyncSetupHandler::OnDidClosePage(const ListValue* args) {
-  CloseSyncSetup();
+  CloseOverlay();
 }
 
 void SyncSetupHandler::SyncStartupFailed() {
@@ -932,6 +932,13 @@
       if (sync_service) {
         DVLOG(1) << "Sync setup aborted by user action";
         sync_service->OnStopSyncingPermanently();
+#if !defined(OS_CHROMEOS)
+        // Sign out the user on desktop Chrome if they click cancel during
+        // initial setup.
+        // TODO(rsimha): Revisit this for M30. See http://crbug.com/252049.
+        if (sync_service->FirstSetupInProgress())
+          SigninManagerFactory::GetForProfile(GetProfile())->SignOut();
+#endif
       }
     }
 
@@ -1094,9 +1101,6 @@
 }
 
 void SyncSetupHandler::CloseOverlay() {
-  // Stop a timer to handle timeout in waiting for sync setup.
-  backend_start_timer_.reset();
-
   CloseSyncSetup();
   web_ui()->CallJavascriptFunction("OptionsPage.closeOverlay");
 }
diff --git a/chrome/browser/ui/webui/sync_setup_handler.h b/chrome/browser/ui/webui/sync_setup_handler.h
index 9dedce6..4285beb 100644
--- a/chrome/browser/ui/webui/sync_setup_handler.h
+++ b/chrome/browser/ui/webui/sync_setup_handler.h
@@ -7,7 +7,7 @@
 
 #include "base/gtest_prod_util.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/signin/signin_tracker.h"
 #include "chrome/browser/sync/sync_startup_tracker.h"
 #include "chrome/browser/ui/webui/options/options_ui.h"
diff --git a/chrome/browser/ui/webui/task_manager/task_manager_handler.cc b/chrome/browser/ui/webui/task_manager/task_manager_handler.cc
index afb3960..42a74a4 100644
--- a/chrome/browser/ui/webui/task_manager/task_manager_handler.cc
+++ b/chrome/browser/ui/webui/task_manager/task_manager_handler.cc
@@ -264,10 +264,8 @@
   int index = model_->GetResourceIndexForGroup(group_index, 0);
   int length = model_->GetGroupRangeForResource(index).second;
 
-  // Forces to set following 3 columns regardless of |enable_columns|.
+  // Forces to set following column regardless of |enable_columns|.
   val->SetInteger("index", index);
-  val->SetBoolean("isBackgroundResource",
-                  model_->IsBackgroundResource(index));
   CreateGroupColumnList("processId", index, 1, val);
   CreateGroupColumnList("type", index, length, val);
   CreateGroupColumnList("uniqueId", index, length, val);
diff --git a/chrome/browser/ui/webui/translate_internals/translate_internals_handler.cc b/chrome/browser/ui/webui/translate_internals/translate_internals_handler.cc
index 09d7ede..9b44249 100644
--- a/chrome/browser/ui/webui/translate_internals/translate_internals_handler.cc
+++ b/chrome/browser/ui/webui/translate_internals/translate_internals_handler.cc
@@ -9,12 +9,14 @@
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
+#include "base/command_line.h"
 #include "base/prefs/pref_service.h"
 #include "base/values.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/translate/translate_error_details.h"
 #include "chrome/browser/translate/translate_event_details.h"
 #include "chrome/browser/translate/translate_prefs.h"
+#include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/translate/language_detection_details.h"
 #include "content/public/browser/web_contents.h"
@@ -89,11 +91,16 @@
   if (!args->GetString(0, &pref_name))
     return;
 
-  if (pref_name == "language_blacklist") {
+  if (pref_name == "blocked_languages") {
     std::string language;
     if (!args->GetString(1, &language))
       return;
-    translate_prefs.RemoveLanguageFromBlacklist(language);
+    translate_prefs.UnblockLanguage(language);
+  } else if (pref_name == "language_blacklist") {
+    std::string language;
+    if (!args->GetString(1, &language))
+      return;
+    translate_prefs.RemoveLanguageFromLegacyBlacklist(language);
   } else if (pref_name == "site_blacklist") {
     std::string site;
     if (!args->GetString(1, &site))
@@ -133,18 +140,25 @@
 
   base::DictionaryValue dict;
 
-  static const char* keys[] = {
-    prefs::kEnableTranslate,
-    TranslatePrefs::kPrefTranslateLanguageBlacklist,
-    TranslatePrefs::kPrefTranslateSiteBlacklist,
-    TranslatePrefs::kPrefTranslateWhitelists,
-    TranslatePrefs::kPrefTranslateDeniedCount,
-    TranslatePrefs::kPrefTranslateAcceptedCount,
-  };
+  std::vector<std::string> keys;
+  keys.push_back(prefs::kEnableTranslate);
 
-  for (size_t i = 0; i < arraysize(keys); ++i) {
-    const char* key = keys[i];
-    const PrefService::Preference* pref = prefs->FindPreference(key);
+  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+  bool enable_translate_settings =
+      command_line.HasSwitch(switches::kEnableTranslateSettings);
+  if (enable_translate_settings)
+    keys.push_back(TranslatePrefs::kPrefTranslateBlockedLanguages);
+
+  keys.push_back(TranslatePrefs::kPrefTranslateLanguageBlacklist);
+  keys.push_back(TranslatePrefs::kPrefTranslateSiteBlacklist);
+  keys.push_back(TranslatePrefs::kPrefTranslateWhitelists);
+  keys.push_back(TranslatePrefs::kPrefTranslateDeniedCount);
+  keys.push_back(TranslatePrefs::kPrefTranslateAcceptedCount);
+
+  for (std::vector<std::string>::const_iterator it = keys.begin();
+       it != keys.end(); ++it) {
+    const std::string& key = *it;
+    const PrefService::Preference* pref = prefs->FindPreference(key.c_str());
     if (pref)
       dict.Set(key, pref->GetValue()->DeepCopy());
   }
diff --git a/chrome/browser/ui/webui/translate_internals/translate_internals_ui.cc b/chrome/browser/ui/webui/translate_internals/translate_internals_ui.cc
index 0c7570c..6f5b606 100644
--- a/chrome/browser/ui/webui/translate_internals/translate_internals_ui.cc
+++ b/chrome/browser/ui/webui/translate_internals/translate_internals_ui.cc
@@ -7,11 +7,13 @@
 #include <string>
 #include <vector>
 
+#include "base/command_line.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/webui/translate_internals/translate_internals_handler.h"
+#include "chrome/common/chrome_switches.h"
 #include "chrome/common/url_constants.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
@@ -58,6 +60,11 @@
     source->AddString(key, value);
   }
 
+  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+  bool enable_translate_settings =
+      command_line.HasSwitch(switches::kEnableTranslateSettings);
+  source->AddBoolean("enable-translate-settings", enable_translate_settings);
+
   return source;
 }
 
diff --git a/chrome/browser/unload_browsertest.cc b/chrome/browser/unload_browsertest.cc
index 331b23c..b39cb8e 100644
--- a/chrome/browser/unload_browsertest.cc
+++ b/chrome/browser/unload_browsertest.cc
@@ -411,9 +411,13 @@
   CheckTitle("only_one_unload");
 }
 
-
 class FastUnloadTest : public UnloadTest {
  public:
+  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+    UnloadTest::SetUpCommandLine(command_line);
+    command_line->AppendSwitch(switches::kEnableFastUnload);
+  }
+
   virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
     ASSERT_TRUE(test_server()->Start());
   }
diff --git a/chrome/browser/upgrade_detector.h b/chrome/browser/upgrade_detector.h
index 86f2c44..9c1826e 100644
--- a/chrome/browser/upgrade_detector.h
+++ b/chrome/browser/upgrade_detector.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_UPGRADE_DETECTOR_H_
 #define CHROME_BROWSER_UPGRADE_DETECTOR_H_
 
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/idle.h"
 #include "ui/gfx/image/image.h"
 
diff --git a/chrome/browser/upgrade_detector_impl.cc b/chrome/browser/upgrade_detector_impl.cc
index d56f33f..436d05e 100644
--- a/chrome/browser/upgrade_detector_impl.cc
+++ b/chrome/browser/upgrade_detector_impl.cc
@@ -17,7 +17,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/version.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/google/google_util.h"
diff --git a/chrome/browser/upgrade_detector_impl.h b/chrome/browser/upgrade_detector_impl.h
index 95597cd..e8a1d82 100644
--- a/chrome/browser/upgrade_detector_impl.h
+++ b/chrome/browser/upgrade_detector_impl.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_UPGRADE_DETECTOR_IMPL_H_
 
 #include "base/memory/weak_ptr.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/net/network_time_tracker.h"
 #include "chrome/browser/upgrade_detector.h"
 
diff --git a/chrome/browser/upload_list.cc b/chrome/browser/upload_list.cc
new file mode 100644
index 0000000..52c42a7
--- /dev/null
+++ b/chrome/browser/upload_list.cc
@@ -0,0 +1,95 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/upload_list.h"
+
+#include <algorithm>
+#include <iterator>
+
+#include "base/bind.h"
+#include "base/file_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
+#include "content/public/browser/browser_thread.h"
+
+using content::BrowserThread;
+
+UploadList::UploadInfo::UploadInfo(const std::string& c, const base::Time& t)
+    : id(c), time(t) {}
+
+UploadList::UploadInfo::~UploadInfo() {}
+
+UploadList::UploadList(Delegate* delegate,
+                       const base::FilePath& upload_log_path)
+    : delegate_(delegate),
+      upload_log_path_(upload_log_path) {}
+
+UploadList::~UploadList() {}
+
+void UploadList::LoadUploadListAsynchronously() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  BrowserThread::PostBlockingPoolTask(
+      FROM_HERE,
+      base::Bind(&UploadList::LoadUploadListAndInformDelegateOfCompletion,
+                 this));
+}
+
+void UploadList::ClearDelegate() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  delegate_ = NULL;
+}
+
+void UploadList::LoadUploadListAndInformDelegateOfCompletion() {
+  LoadUploadList();
+  BrowserThread::PostTask(
+      BrowserThread::UI,
+      FROM_HERE,
+      base::Bind(&UploadList::InformDelegateOfCompletion, this));
+}
+
+void UploadList::LoadUploadList() {
+  if (file_util::PathExists(upload_log_path_)) {
+    std::string contents;
+    file_util::ReadFileToString(upload_log_path_, &contents);
+    std::vector<std::string> log_entries;
+    base::SplitStringAlongWhitespace(contents, &log_entries);
+    ParseLogEntries(log_entries);
+  }
+}
+
+void UploadList::AppendUploadInfo(const UploadInfo& info) {
+  uploads_.push_back(info);
+}
+
+void UploadList::ParseLogEntries(
+    const std::vector<std::string>& log_entries) {
+  std::vector<std::string>::const_reverse_iterator i;
+  for (i = log_entries.rbegin(); i != log_entries.rend(); ++i) {
+    std::vector<std::string> components;
+    base::SplitString(*i, ',', &components);
+    // Skip any blank (or corrupted) lines.
+    if (components.size() != 2)
+      continue;
+    double seconds_since_epoch;
+    if (!base::StringToDouble(components[0], &seconds_since_epoch))
+      continue;
+    UploadInfo info(components[1],
+                    base::Time::FromDoubleT(seconds_since_epoch));
+    uploads_.push_back(info);
+  }
+}
+
+void UploadList::InformDelegateOfCompletion() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  if (delegate_)
+    delegate_->OnUploadListAvailable();
+}
+
+void UploadList::GetUploads(unsigned int max_count,
+                            std::vector<UploadInfo>* uploads) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  std::copy(uploads_.begin(),
+            uploads_.begin() + std::min<size_t>(uploads_.size(), max_count),
+            std::back_inserter(*uploads));
+}
diff --git a/chrome/browser/upload_list.h b/chrome/browser/upload_list.h
new file mode 100644
index 0000000..23c4ff5
--- /dev/null
+++ b/chrome/browser/upload_list.h
@@ -0,0 +1,88 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UPLOAD_LIST_H_
+#define CHROME_BROWSER_UPLOAD_LIST_H_
+
+#include <string>
+#include <vector>
+
+#include "base/files/file_path.h"
+#include "base/gtest_prod_util.h"
+#include "base/memory/ref_counted.h"
+#include "base/time/time.h"
+
+// Loads and parses an upload list text file of the format
+// time,id
+// time,id
+// etc.
+// where each line represents an upload and "time" is Unix time. Must be used
+// from the UI thread. The loading and parsing is done on a blocking pool task
+// runner.
+class UploadList : public base::RefCountedThreadSafe<UploadList> {
+ public:
+  struct UploadInfo {
+    UploadInfo(const std::string& c, const base::Time& t);
+    ~UploadInfo();
+
+    std::string id;
+    base::Time time;
+  };
+
+  class Delegate {
+   public:
+    // Invoked when the upload list has been loaded. Will be called on the
+    // UI thread.
+    virtual void OnUploadListAvailable() = 0;
+
+   protected:
+    virtual ~Delegate() {}
+  };
+
+  // Creates a new upload list with the given callback delegate.
+  UploadList(Delegate* delegate, const base::FilePath& upload_log_path);
+
+  // Starts loading the upload list. OnUploadListAvailable will be called when
+  // loading is complete.
+  void LoadUploadListAsynchronously();
+
+  // Clears the delegate, so that any outstanding asynchronous load will not
+  // call the delegate on completion.
+  void ClearDelegate();
+
+  // Populates |uploads| with the |max_count| most recent uploads,
+  // in reverse chronological order.
+  // Must be called only after OnUploadListAvailable has been called.
+  void GetUploads(unsigned int max_count, std::vector<UploadInfo>* uploads);
+
+ protected:
+  virtual ~UploadList();
+
+  // Reads the upload log and stores the entries in |uploads_|.
+  virtual void LoadUploadList();
+
+  // Adds |info| to |uploads_|.
+  void AppendUploadInfo(const UploadInfo& info);
+
+ private:
+  friend class base::RefCountedThreadSafe<UploadList>;
+  FRIEND_TEST_ALL_PREFIXES(UploadListTest, ParseLogEntries);
+
+  // Manages the background thread work for LoadUploadListAsynchronously().
+  void LoadUploadListAndInformDelegateOfCompletion();
+
+  // Calls the delegate's callback method, if there is a delegate.
+  void InformDelegateOfCompletion();
+
+  // Parses upload log lines, converting them to UploadInfo entries.
+  void ParseLogEntries(const std::vector<std::string>& log_entries);
+
+  std::vector<UploadInfo> uploads_;
+  Delegate* delegate_;
+  const base::FilePath upload_log_path_;
+
+  DISALLOW_COPY_AND_ASSIGN(UploadList);
+};
+
+#endif  // CHROME_BROWSER_UPLOAD_LIST_H_
diff --git a/chrome/browser/upload_list_unittest.cc b/chrome/browser/upload_list_unittest.cc
new file mode 100644
index 0000000..153f9db
--- /dev/null
+++ b/chrome/browser/upload_list_unittest.cc
@@ -0,0 +1,44 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+
+#include "base/files/file_path.h"
+#include "base/memory/ref_counted.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/time/time.h"
+#include "chrome/browser/upload_list.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+// Test that UploadList can parse a vector of log entry strings to a vector of
+// UploadInfo objects. See the UploadList declaration for a description of the
+// log entry string format.
+TEST(UploadListTest, ParseLogEntries) {
+  const char kTestTime[] = "1234567890";
+  const char kTestID[] = "0123456789abcdef";
+  std::string test_entry = kTestTime;
+  test_entry += ",";
+  test_entry.append(kTestID, sizeof(kTestID));
+
+  scoped_refptr<UploadList> upload_list =
+      new UploadList(NULL, base::FilePath());
+
+  // 1 entry.
+  std::vector<std::string> log_entries;
+  log_entries.push_back(test_entry);
+  upload_list->ParseLogEntries(log_entries);
+  EXPECT_EQ(1u, upload_list->uploads_.size());
+  double time_double = upload_list->uploads_[0].time.ToDoubleT();
+  EXPECT_STREQ(kTestTime, base::DoubleToString(time_double).c_str());
+  EXPECT_STREQ(kTestID, upload_list->uploads_[0].id.c_str());
+
+  // Add 3 more entries.
+  log_entries.push_back(test_entry);
+  log_entries.push_back(test_entry);
+  upload_list->ParseLogEntries(log_entries);
+  EXPECT_EQ(4u, upload_list->uploads_.size());
+  time_double = upload_list->uploads_[3].time.ToDoubleT();
+  EXPECT_STREQ(kTestTime, base::DoubleToString(time_double).c_str());
+  EXPECT_STREQ(kTestID, upload_list->uploads_[3].id.c_str());
+}
diff --git a/chrome/browser/usb/usb_service.cc b/chrome/browser/usb/usb_service.cc
index 038786d..e44c8aa 100644
--- a/chrome/browser/usb/usb_service.cc
+++ b/chrome/browser/usb/usb_service.cc
@@ -104,6 +104,22 @@
 #endif  // defined(OS_CHROMEOS)
 }
 
+void UsbService::EnumerateDevices(
+    std::vector<scoped_refptr<UsbDevice> >* devices) {
+  devices->clear();
+
+  DeviceVector enumerated_devices;
+  EnumerateDevicesImpl(&enumerated_devices);
+
+  for (DeviceVector::iterator it = enumerated_devices.begin();
+       it != enumerated_devices.end(); ++it) {
+    PlatformUsbDevice device = it->device();
+    UsbDevice* const wrapper = LookupOrCreateDevice(device);
+    if (wrapper)
+      devices->push_back(wrapper);
+  }
+}
+
 void UsbService::FindDevicesImpl(const uint16 vendor_id,
                                  const uint16 product_id,
                                  vector<scoped_refptr<UsbDevice> >* devices,
@@ -120,12 +136,11 @@
     return;
 
   DeviceVector enumerated_devices;
-  EnumerateDevices(&enumerated_devices);
-  if (enumerated_devices.empty())
-    return;
+  EnumerateDevicesImpl(&enumerated_devices);
 
-  for (unsigned int i = 0; i < enumerated_devices.size(); ++i) {
-    PlatformUsbDevice device = enumerated_devices[i].device();
+  for (DeviceVector::iterator it = enumerated_devices.begin();
+       it != enumerated_devices.end(); ++it) {
+    PlatformUsbDevice device = it->device();
     if (DeviceMatches(device, vendor_id, product_id)) {
       UsbDevice* const wrapper = LookupOrCreateDevice(device);
       if (wrapper)
@@ -165,7 +180,7 @@
   return device_;
 }
 
-void UsbService::EnumerateDevices(DeviceVector* output) {
+void UsbService::EnumerateDevicesImpl(DeviceVector* output) {
   STLClearObject(output);
 
   libusb_device** devices = NULL;
diff --git a/chrome/browser/usb/usb_service.h b/chrome/browser/usb/usb_service.h
index 8e04ce2..f2cfd3c 100644
--- a/chrome/browser/usb/usb_service.h
+++ b/chrome/browser/usb/usb_service.h
@@ -40,6 +40,10 @@
                    std::vector<scoped_refptr<UsbDevice> >* devices,
                    const base::Callback<void()>& callback);
 
+  // Find all of the devices attached to the system, inserting them into
+  // |devices|. Clears |devices| before use.
+  void EnumerateDevices(std::vector<scoped_refptr<UsbDevice> >* devices);
+
   // This function should not be called by normal code. It is invoked by a
   // UsbDevice's Close function and disposes of the associated platform handle.
   void CloseDevice(scoped_refptr<UsbDevice> device);
@@ -79,7 +83,7 @@
                        bool success);
 
   // Populates |output| with the result of enumerating all attached USB devices.
-  void EnumerateDevices(DeviceVector* output);
+  void EnumerateDevicesImpl(DeviceVector* output);
 
   // If a UsbDevice wrapper corresponding to |device| has already been created,
   // returns it. Otherwise, opens the device, creates a wrapper, and associates
diff --git a/chrome/browser/user_style_sheet_watcher.h b/chrome/browser/user_style_sheet_watcher.h
index 72b002c..9ab8482 100644
--- a/chrome/browser/user_style_sheet_watcher.h
+++ b/chrome/browser/user_style_sheet_watcher.h
@@ -13,7 +13,7 @@
 #include "components/browser_context_keyed_service/refcounted_browser_context_keyed_service.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 class Profile;
 class UserStyleSheetLoader;
diff --git a/chrome/browser/validation_message_message_filter.cc b/chrome/browser/validation_message_message_filter.cc
index 1d48232..ef2366b 100644
--- a/chrome/browser/validation_message_message_filter.cc
+++ b/chrome/browser/validation_message_message_filter.cc
@@ -62,8 +62,8 @@
 void ValidationMessageMessageFilter::OnShowValidationMessage(
     int route_id, const gfx::Rect& anchor_in_root_view,
     const string16& main_text, const string16& sub_text) {
-  RenderProcessHost* process = RenderProcessHost::FromID(renderer_id_);
-  RenderWidgetHost* widget_host = process->GetRenderWidgetHostByID(route_id);
+  RenderWidgetHost* widget_host =
+      RenderWidgetHost::FromID(renderer_id_, route_id);
   validation_message_bubble_ = chrome::ValidationMessageBubble::CreateAndShow(
       widget_host, anchor_in_root_view, main_text, sub_text);
 }
@@ -76,8 +76,8 @@
     int route_id, const gfx::Rect& anchor_in_root_view) {
   if (!validation_message_bubble_)
       return;
-  RenderProcessHost* process = RenderProcessHost::FromID(renderer_id_);
-  RenderWidgetHost* widget_host = process->GetRenderWidgetHostByID(route_id);
+  RenderWidgetHost* widget_host =
+      RenderWidgetHost::FromID(renderer_id_, route_id);
   validation_message_bubble_->SetPositionRelativeToAnchor(
       widget_host, anchor_in_root_view);
 }
diff --git a/chrome/browser/value_store/leveldb_value_store.cc b/chrome/browser/value_store/leveldb_value_store.cc
index 54fc3c2..d192399 100644
--- a/chrome/browser/value_store/leveldb_value_store.cc
+++ b/chrome/browser/value_store/leveldb_value_store.cc
@@ -94,7 +94,7 @@
   if (db_ && IsEmpty()) {
     // Close |db_| now to release any lock on the directory.
     db_.reset();
-    if (!file_util::Delete(db_path_, true)) {
+    if (!base::Delete(db_path_, true)) {
       LOG(WARNING) << "Failed to delete LeveldbValueStore database " <<
           db_path_.value();
     }
diff --git a/chrome/browser/value_store/value_store.h b/chrome/browser/value_store/value_store.h
index c57140f..4a25786 100644
--- a/chrome/browser/value_store/value_store.h
+++ b/chrome/browser/value_store/value_store.h
@@ -19,7 +19,7 @@
   class ReadResultType {
    public:
     // Ownership of |settings| taken.
-    explicit ReadResultType(DictionaryValue* settings);
+    explicit ReadResultType(base::DictionaryValue* settings);
     explicit ReadResultType(const std::string& error);
     ~ReadResultType();
 
@@ -27,7 +27,7 @@
     // the root object. If you request the value for key "foo", that value will
     // be in |settings.foo|.
     // Must only be called if HasError() is false.
-    scoped_ptr<DictionaryValue>& settings();
+    scoped_ptr<base::DictionaryValue>& settings();
 
     // Gets whether the operation failed.
     bool HasError() const;
@@ -37,7 +37,7 @@
     const std::string& error() const;
 
    private:
-    scoped_ptr<DictionaryValue> settings_;
+    scoped_ptr<base::DictionaryValue> settings_;
     const std::string error_;
 
     DISALLOW_COPY_AND_ASSIGN(ReadResultType);
@@ -124,12 +124,13 @@
   virtual ReadResult Get() = 0;
 
   // Sets a single key to a new value.
-  virtual WriteResult Set(
-      WriteOptions options, const std::string& key, const Value& value) = 0;
+  virtual WriteResult Set(WriteOptions options,
+                          const std::string& key,
+                          const base::Value& value) = 0;
 
   // Sets multiple keys to new values.
   virtual WriteResult Set(
-      WriteOptions options, const DictionaryValue& values) = 0;
+      WriteOptions options, const base::DictionaryValue& values) = 0;
 
   // Removes a key from the storage.
   virtual WriteResult Remove(const std::string& key) = 0;
diff --git a/chrome/browser/web_applications/web_app.cc b/chrome/browser/web_applications/web_app.cc
index de8e048..06a12f7 100644
--- a/chrome/browser/web_applications/web_app.cc
+++ b/chrome/browser/web_applications/web_app.cc
@@ -149,14 +149,15 @@
 
 void CreateShortcuts(
     const ShellIntegration::ShortcutInfo& shortcut_info,
-    const ShellIntegration::ShortcutLocations& creation_locations) {
+    const ShellIntegration::ShortcutLocations& creation_locations,
+    ShortcutCreationPolicy creation_policy) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   BrowserThread::PostTask(
       BrowserThread::FILE,
       FROM_HERE,
       base::Bind(base::IgnoreResult(&CreateShortcutsOnFileThread),
-                 shortcut_info, creation_locations));
+                 shortcut_info, creation_locations, creation_policy));
 }
 
 void DeleteAllShortcuts(const ShellIntegration::ShortcutInfo& shortcut_info) {
@@ -180,14 +181,16 @@
 
 bool CreateShortcutsOnFileThread(
     const ShellIntegration::ShortcutInfo& shortcut_info,
-    const ShellIntegration::ShortcutLocations& creation_locations) {
+    const ShellIntegration::ShortcutLocations& creation_locations,
+    ShortcutCreationPolicy creation_policy) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
 
   base::FilePath shortcut_data_dir = GetWebAppDataDirectory(
       shortcut_info.profile_path, shortcut_info.extension_id,
       shortcut_info.url);
   return internals::CreatePlatformShortcuts(shortcut_data_dir, shortcut_info,
-                                            creation_locations);
+                                            creation_locations,
+                                            creation_policy);
 }
 
 bool IsValidUrl(const GURL& url) {
diff --git a/chrome/browser/web_applications/web_app.h b/chrome/browser/web_applications/web_app.h
index f4c647c..1fc5a5a 100644
--- a/chrome/browser/web_applications/web_app.h
+++ b/chrome/browser/web_applications/web_app.h
@@ -24,6 +24,14 @@
 
 namespace web_app {
 
+// Policy on whether to create duplicate shortcuts.
+enum ShortcutCreationPolicy {
+  // Duplicate shortcuts may be created, at the discretion of the
+  // implementation.
+  ALLOW_DUPLICATE_SHORTCUTS,
+  DONT_CREATE_DUPLICATE_SHORTCUTS
+};
+
 // Gets the user data directory for given web app. The path for the directory is
 // based on |extension_id|. If |extension_id| is empty then |url| is used
 // to construct a unique ID.
@@ -56,7 +64,8 @@
 // |creation_locations| contains information about where to create them.
 void CreateShortcuts(
     const ShellIntegration::ShortcutInfo& shortcut_info,
-    const ShellIntegration::ShortcutLocations& creation_locations);
+    const ShellIntegration::ShortcutLocations& creation_locations,
+    ShortcutCreationPolicy creation_policy);
 
 // Delete all the shortcuts that have been created for the given
 // |shortcut_data| in the profile with |profile_path|.
@@ -75,7 +84,8 @@
 // |creation_locations| contains information about where to create them.
 bool CreateShortcutsOnFileThread(
     const ShellIntegration::ShortcutInfo& shortcut_info,
-    const ShellIntegration::ShortcutLocations& creation_locations);
+    const ShellIntegration::ShortcutLocations& creation_locations,
+    ShortcutCreationPolicy creation_policy);
 
 // Returns true if given url is a valid web app url.
 bool IsValidUrl(const GURL& url);
@@ -101,9 +111,6 @@
 namespace internals {
 
 #if defined(OS_WIN)
-bool CheckAndSaveIcon(const base::FilePath& icon_file,
-                      const gfx::ImageFamily& image);
-
 std::vector<base::FilePath> GetShortcutPaths(
     const ShellIntegration::ShortcutLocations& creation_locations);
 #endif
@@ -117,7 +124,8 @@
 bool CreatePlatformShortcuts(
     const base::FilePath& shortcut_data_path,
     const ShellIntegration::ShortcutInfo& shortcut_info,
-    const ShellIntegration::ShortcutLocations& creation_locations);
+    const ShellIntegration::ShortcutLocations& creation_locations,
+    ShortcutCreationPolicy creation_policy);
 
 // Delete all the shortcuts we have added for this extension. This is the
 // platform specific implementation of the DeleteAllShortcuts function, and
@@ -134,6 +142,10 @@
     const string16& old_app_title,
     const ShellIntegration::ShortcutInfo& shortcut_info);
 
+// Delete all the shortcuts for an entire profile.
+// This is executed on the FILE thread.
+void DeleteAllShortcutsForProfile(const base::FilePath& profile_path);
+
 // Sanitizes |name| and returns a version of it that is safe to use as an
 // on-disk file name .
 base::FilePath GetSanitizedFileName(const string16& name);
diff --git a/chrome/browser/web_applications/web_app_android.cc b/chrome/browser/web_applications/web_app_android.cc
index ece27a1..bce8a52 100644
--- a/chrome/browser/web_applications/web_app_android.cc
+++ b/chrome/browser/web_applications/web_app_android.cc
@@ -10,7 +10,8 @@
 bool CreatePlatformShortcuts(
     const base::FilePath& web_app_path,
     const ShellIntegration::ShortcutInfo& shortcut_info,
-    const ShellIntegration::ShortcutLocations& creation_locations) {
+    const ShellIntegration::ShortcutLocations& creation_locations,
+    ShortcutCreationPolicy creation_policy) {
   return true;
 }
 
@@ -23,5 +24,7 @@
     const string16& old_app_title,
     const ShellIntegration::ShortcutInfo& shortcut_info) {}
 
+void DeleteAllShortcutsForProfile(const base::FilePath& profile_path) {}
+
 }  // namespace internals
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/web_app_linux.cc b/chrome/browser/web_applications/web_app_linux.cc
index f3139ba..09aaf91 100644
--- a/chrome/browser/web_applications/web_app_linux.cc
+++ b/chrome/browser/web_applications/web_app_linux.cc
@@ -16,7 +16,8 @@
 bool CreatePlatformShortcuts(
     const base::FilePath& web_app_path,
     const ShellIntegration::ShortcutInfo& shortcut_info,
-    const ShellIntegration::ShortcutLocations& creation_locations) {
+    const ShellIntegration::ShortcutLocations& creation_locations,
+    ShortcutCreationPolicy /*creation_policy*/) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
   return ShellIntegrationLinux::CreateDesktopShortcut(
       shortcut_info, creation_locations);
@@ -50,7 +51,12 @@
   // currently in a different location).
   creation_locations.applications_menu_subdir = GetAppShortcutsSubdirName();
 
-  CreatePlatformShortcuts(web_app_path, shortcut_info, creation_locations);
+  CreatePlatformShortcuts(web_app_path, shortcut_info, creation_locations,
+                          ALLOW_DUPLICATE_SHORTCUTS);
+}
+
+void DeleteAllShortcutsForProfile(const base::FilePath& profile_path) {
+  // TODO(mgiuca): Implement this on Linux.
 }
 
 }  // namespace internals
diff --git a/chrome/browser/web_applications/web_app_mac.h b/chrome/browser/web_applications/web_app_mac.h
index e0ba9ab..fed1b1e 100644
--- a/chrome/browser/web_applications/web_app_mac.h
+++ b/chrome/browser/web_applications/web_app_mac.h
@@ -5,6 +5,8 @@
 #ifndef CHROME_BROWSER_WEB_APPLICATIONS_WEB_APP_MAC_H_
 #define CHROME_BROWSER_WEB_APPLICATIONS_WEB_APP_MAC_H_
 
+#include <vector>
+
 #include "base/files/file_path.h"
 #include "base/gtest_prod_util.h"
 #include "base/strings/string16.h"
@@ -38,45 +40,63 @@
   WebAppShortcutCreator(
       const base::FilePath& app_data_path,
       const ShellIntegration::ShortcutInfo& shortcut_info,
-      const string16& chrome_bundle_id);
+      const std::string& chrome_bundle_id);
 
   virtual ~WebAppShortcutCreator();
 
-  // Returns a path to the destination where the app should be written to.
-  base::FilePath GetShortcutPath() const;
+  // Returns the base name for the shortcut.
+  base::FilePath GetShortcutName() const;
 
-  // Copies the app launcher template into place and fills in all relevant
-  // information.
-  bool CreateShortcut();
+  // Returns a path to the Chrome Apps folder in the relevant applications
+  // folder. E.g. ~/Applications or /Applications.
+  virtual base::FilePath GetDestinationPath() const;
+
+  bool CreateShortcuts();
+  void DeleteShortcuts();
+  bool UpdateShortcuts();
 
  protected:
   // Returns a path to the app loader.
   base::FilePath GetAppLoaderPath() const;
 
-  // Returns a path to the destination where the app should be written to.
-  virtual base::FilePath GetDestinationPath() const;
-
   // Updates the plist inside |app_path| with information about the app.
   bool UpdatePlist(const base::FilePath& app_path) const;
 
   // Updates the icon for the shortcut.
   bool UpdateIcon(const base::FilePath& app_path) const;
 
+  // Returns a path to an app bundle with the given id. Or an empty path if no
+  // matching bundle was found.
+  // Protected and virtual so it can be mocked out for testing.
+  virtual base::FilePath GetAppBundleById(const std::string& bundle_id) const;
+
  private:
   FRIEND_TEST_ALL_PREFIXES(WebAppShortcutCreatorTest, UpdateIcon);
+  FRIEND_TEST_ALL_PREFIXES(WebAppShortcutCreatorTest, UpdateShortcuts);
+
+  // Copies the app loader template into a temporary directory and fills in all
+  // relevant information.
+  bool BuildShortcut(const base::FilePath& staging_path) const;
+
+  // Builds a shortcut and copies it into the given destination folders.
+  // Returns with the number of successful copies. Returns on the first failure.
+  size_t CreateShortcutsIn(const std::vector<base::FilePath>& folders) const;
 
   // Updates the InfoPlist.string inside |app_path| with the display name for
   // the app.
   bool UpdateDisplayName(const base::FilePath& app_path) const;
 
+  // Updates the bundle id of the internal copy of the app shim bundle.
+  bool UpdateInternalBundleIdentifier() const;
+
   // Returns the bundle identifier to use for this app bundle.
-  // |plist| is a dictionary containg a copy of the template plist file to
-  // be used for creating the app bundle.
-  NSString* GetBundleIdentifier(NSDictionary* plist) const;
+  std::string GetBundleIdentifier() const;
+
+  // Returns the bundle identifier for the internal copy of the bundle.
+  std::string GetInternalBundleIdentifier() const;
 
   // Show the bundle we just generated in the Finder.
-  virtual void RevealGeneratedBundleInFinder(
-      const base::FilePath& generated_bundle) const;
+  virtual void RevealAppShimInFinder() const;
 
   // Path to the data directory for this app. For example:
   // ~/Library/Application Support/Chromium/Default/Web Applications/_crx_abc/
@@ -86,7 +106,7 @@
   ShellIntegration::ShortcutInfo info_;
 
   // The CFBundleIdentifier of the Chrome browser bundle.
-  string16 chrome_bundle_id_;
+  std::string chrome_bundle_id_;
 };
 
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/web_app_mac.mm b/chrome/browser/web_applications/web_app_mac.mm
index 224c798..2743f32 100644
--- a/chrome/browser/web_applications/web_app_mac.mm
+++ b/chrome/browser/web_applications/web_app_mac.mm
@@ -17,7 +17,6 @@
 #include "base/mac/mac_logging.h"
 #include "base/mac/mac_util.h"
 #include "base/mac/scoped_cftyperef.h"
-#include "base/memory/scoped_nsobject.h"
 #include "base/strings/string_util.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
@@ -166,7 +165,16 @@
     const ShellIntegration::ShortcutInfo& shortcut_info) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
   base::FilePath shim_path = web_app::GetAppInstallPath(shortcut_info);
-  if (shim_path.empty())
+
+  if (shim_path.empty() || !file_util::PathExists(shim_path)) {
+    // The user may have deleted the copy in the Applications folder, use the
+    // one in the web app's app_data_path.
+    base::FilePath app_data_path = web_app::GetWebAppDataDirectory(
+        shortcut_info.profile_path, shortcut_info.extension_id, GURL());
+    shim_path = app_data_path.Append(shim_path.BaseName());
+  }
+
+  if (!file_util::PathExists(shim_path))
     return;
 
   CommandLine command_line(CommandLine::NO_PROGRAM);
@@ -219,6 +227,14 @@
                  atomically:YES];
 }
 
+void DeletePathAndParentIfEmpty(const base::FilePath& app_path) {
+  DCHECK(!app_path.empty());
+  base::Delete(app_path, true);
+  base::FilePath apps_folder = app_path.DirName();
+  if (file_util::IsDirectoryEmpty(apps_folder))
+    base::Delete(apps_folder, false);
+}
+
 }  // namespace
 
 namespace web_app {
@@ -227,7 +243,7 @@
 WebAppShortcutCreator::WebAppShortcutCreator(
     const base::FilePath& app_data_path,
     const ShellIntegration::ShortcutInfo& shortcut_info,
-    const string16& chrome_bundle_id)
+    const std::string& chrome_bundle_id)
     : app_data_path_(app_data_path),
       info_(shortcut_info),
       chrome_bundle_id_(chrome_bundle_id) {
@@ -236,40 +252,21 @@
 WebAppShortcutCreator::~WebAppShortcutCreator() {
 }
 
-base::FilePath WebAppShortcutCreator::GetShortcutPath() const {
-  base::FilePath dst_path = GetDestinationPath();
-  if (dst_path.empty())
-    return dst_path;
-
-  base::FilePath app_name = internals::GetSanitizedFileName(UTF8ToUTF16(
-      info_.profile_path.BaseName().value() + " " + info_.extension_id));
-  return dst_path.Append(app_name.ReplaceExtension("app"));
+base::FilePath WebAppShortcutCreator::GetShortcutName() const {
+  std::string app_name;
+  // Check if there should be a separate shortcut made for different profiles.
+  // Such shortcuts will have a |profile_name| set on the ShortcutInfo,
+  // otherwise it will be empty.
+  if (!info_.profile_name.empty()) {
+    app_name += info_.profile_path.BaseName().value();
+    app_name += ' ';
+  }
+  app_name += info_.extension_id;
+  return base::FilePath(app_name).ReplaceExtension("app");
 }
 
-bool WebAppShortcutCreator::CreateShortcut() {
-  base::FilePath app_path = GetShortcutPath();
-  base::FilePath app_name = app_path.BaseName();
-  base::FilePath dst_path = app_path.DirName();
-  if (app_path.empty() || !file_util::DirectoryExists(dst_path.DirName())) {
-    LOG(ERROR) << "Couldn't find an Applications directory to copy app to.";
-    return false;
-  }
-  if (!file_util::CreateDirectory(app_data_path_)) {
-    LOG(ERROR) << "Creating app_data_path " << app_data_path_.value()
-               << " failed.";
-    return false;
-  }
-  if (!file_util::CreateDirectory(dst_path)) {
-    LOG(ERROR) << "Creating directory " << dst_path.value() << " failed.";
-    return false;
-  }
-  UpdateAppShortcutsSubdirLocalizedName(dst_path);
-
-  base::ScopedTempDir scoped_temp_dir;
-  if (!scoped_temp_dir.CreateUniqueTempDir())
-    return false;
-  base::FilePath staging_path = scoped_temp_dir.path().Append(app_name);
-
+bool WebAppShortcutCreator::BuildShortcut(
+    const base::FilePath& staging_path) const {
   // Update the app's plist and icon in a temp directory. This works around
   // a Finder bug where the app's icon doesn't properly update.
   if (!file_util::CopyDirectory(GetAppLoaderPath(), staging_path, true)) {
@@ -287,23 +284,115 @@
   if (!UpdateIcon(staging_path))
     return false;
 
-  // Put one copy in the app's app_data_path so we can still run it if the user
-  // deletes the one in the applications folder.
-  if (!file_util::CopyDirectory(staging_path, app_data_path_, true)) {
-    NOTREACHED();
+  return true;
+}
+
+size_t WebAppShortcutCreator::CreateShortcutsIn(
+    const std::vector<base::FilePath>& folders) const {
+  size_t succeeded = 0;
+
+  base::ScopedTempDir scoped_temp_dir;
+  if (!scoped_temp_dir.CreateUniqueTempDir())
+    return 0;
+
+  base::FilePath app_name = GetShortcutName();
+  base::FilePath staging_path =
+      scoped_temp_dir.path().Append(app_name);
+  if (!BuildShortcut(staging_path))
+    return 0;
+
+  for (std::vector<base::FilePath>::const_iterator it = folders.begin();
+       it != folders.end(); ++it) {
+    const base::FilePath& dst_path = *it;
+    if (!file_util::CopyDirectory(staging_path, dst_path, true)) {
+      LOG(ERROR) << "Copying app to dst path: " << dst_path.value()
+                 << " failed";
+      return succeeded;
+    }
+
+    base::mac::RemoveQuarantineAttribute(dst_path.Append(app_name));
+    ++succeeded;
+  }
+
+  return succeeded;
+}
+
+bool WebAppShortcutCreator::CreateShortcuts() {
+  base::FilePath dst_path = GetDestinationPath();
+  if (dst_path.empty() || !file_util::DirectoryExists(dst_path.DirName())) {
+    LOG(ERROR) << "Couldn't find an Applications directory to copy app to.";
     return false;
   }
-  base::mac::RemoveQuarantineAttribute(app_data_path_.Append(app_name));
 
-  if (!file_util::CopyDirectory(staging_path, dst_path, true))
+  if (!file_util::CreateDirectory(app_data_path_)) {
+    LOG(ERROR) << "Creating app_data_path " << app_data_path_.value()
+               << " failed.";
+    return false;
+  }
+
+  if (!file_util::CreateDirectory(dst_path)) {
+    LOG(ERROR) << "Creating directory " << dst_path.value() << " failed.";
+    return false;
+  }
+
+  UpdateAppShortcutsSubdirLocalizedName(dst_path);
+
+  std::vector<base::FilePath> paths;
+  paths.push_back(app_data_path_);
+  paths.push_back(dst_path);
+  size_t success_count = CreateShortcutsIn(paths);
+  if (success_count == 0)
     return false;
 
-  base::mac::RemoveQuarantineAttribute(app_path);
-  RevealGeneratedBundleInFinder(app_path);
+  UpdateInternalBundleIdentifier();
 
+  if (success_count != paths.size())
+    return false;
+
+  RevealAppShimInFinder();
   return true;
 }
 
+void WebAppShortcutCreator::DeleteShortcuts() {
+  base::FilePath dst_path = GetDestinationPath();
+  if (!dst_path.empty())
+    DeletePathAndParentIfEmpty(dst_path.Append(GetShortcutName()));
+
+  // In case the user has moved/renamed/copied the app bundle.
+  base::FilePath bundle_path = GetAppBundleById(GetBundleIdentifier());
+  if (!bundle_path.empty())
+    base::Delete(bundle_path, true);
+
+  // Delete the internal one.
+  DeletePathAndParentIfEmpty(app_data_path_.Append(GetShortcutName()));
+}
+
+bool WebAppShortcutCreator::UpdateShortcuts() {
+  std::vector<base::FilePath> paths;
+  base::Delete(app_data_path_.Append(GetShortcutName()), true);
+  paths.push_back(app_data_path_);
+
+  base::FilePath dst_path = GetDestinationPath();
+  base::FilePath app_path = dst_path.Append(GetShortcutName());
+
+  // If the path does not exist, check if a matching bundle can be found
+  // elsewhere.
+  if (dst_path.empty() || !file_util::PathExists(app_path))
+    app_path = GetAppBundleById(GetBundleIdentifier());
+
+  if (!app_path.empty()) {
+    base::Delete(app_path, true);
+    paths.push_back(app_path.DirName());
+  }
+
+  size_t success_count = CreateShortcutsIn(paths);
+  if (success_count == 0)
+    return false;
+
+  UpdateInternalBundleIdentifier();
+  return success_count == paths.size() && !app_path.empty();
+}
+
 base::FilePath WebAppShortcutCreator::GetAppLoaderPath() const {
   return base::mac::PathForFrameworkBundleResource(
       base::mac::NSToCFCast(@"app_mode_loader.app"));
@@ -320,7 +409,7 @@
   NSString* extension_id = base::SysUTF8ToNSString(info_.extension_id);
   NSString* extension_title = base::SysUTF16ToNSString(info_.title);
   NSString* extension_url = base::SysUTF8ToNSString(info_.url.spec());
-  NSString* chrome_bundle_id = base::SysUTF16ToNSString(chrome_bundle_id_);
+  NSString* chrome_bundle_id = base::SysUTF8ToNSString(chrome_bundle_id_);
   NSDictionary* replacement_dict =
       [NSDictionary dictionaryWithObjectsAndKeys:
           extension_id, app_mode::kShortcutIdPlaceholder,
@@ -351,7 +440,7 @@
   }
 
   // 2. Fill in other values.
-  [plist setObject:GetBundleIdentifier(plist)
+  [plist setObject:base::SysUTF8ToNSString(GetBundleIdentifier())
             forKey:base::mac::CFToNSCast(kCFBundleIdentifierKey)];
   [plist setObject:base::mac::FilePathToNSString(app_data_path_)
             forKey:app_mode::kCrAppModeUserDataDirKey];
@@ -366,7 +455,8 @@
   [plist setObject:base::mac::FilePathToNSString(app_name)
             forKey:base::mac::CFToNSCast(kCFBundleNameKey)];
 
-  return [plist writeToFile:plist_path atomically:YES];
+  return [plist writeToFile:plist_path
+                 atomically:YES];
 }
 
 bool WebAppShortcutCreator::UpdateDisplayName(
@@ -427,25 +517,60 @@
   return icon_family.WriteDataToFile(resources_path.Append("app.icns"));
 }
 
-NSString* WebAppShortcutCreator::GetBundleIdentifier(NSDictionary* plist) const
-{
-  NSString* bundle_id_template =
-    base::mac::ObjCCast<NSString>(
-        [plist objectForKey:base::mac::CFToNSCast(kCFBundleIdentifierKey)]);
-  NSString* extension_id = base::SysUTF8ToNSString(info_.extension_id);
-  NSString* placeholder =
-      [NSString stringWithFormat:@"@%@@", app_mode::kShortcutIdPlaceholder];
-  NSString* bundle_id =
-      [bundle_id_template
-          stringByReplacingOccurrencesOfString:placeholder
-                                    withString:extension_id];
+bool WebAppShortcutCreator::UpdateInternalBundleIdentifier() const {
+  NSString* plist_path = base::mac::FilePathToNSString(
+      app_data_path_.Append(GetShortcutName())
+          .Append("Contents").Append("Info.plist"));
+  NSMutableDictionary* plist =
+      [NSMutableDictionary dictionaryWithContentsOfFile:plist_path];
+
+  [plist setObject:base::SysUTF8ToNSString(GetInternalBundleIdentifier())
+            forKey:base::mac::CFToNSCast(kCFBundleIdentifierKey)];
+  return [plist writeToFile:plist_path
+                 atomically:YES];
+}
+
+base::FilePath WebAppShortcutCreator::GetAppBundleById(
+    const std::string& bundle_id) const {
+  base::ScopedCFTypeRef<CFStringRef> bundle_id_cf(
+      base::SysUTF8ToCFStringRef(bundle_id));
+  CFURLRef url_ref = NULL;
+  OSStatus status = LSFindApplicationForInfo(
+      kLSUnknownCreator, bundle_id_cf.get(), NULL, NULL, &url_ref);
+  if (status != noErr)
+    return base::FilePath();
+
+  base::ScopedCFTypeRef<CFURLRef> url(url_ref);
+  NSString* path_string = [base::mac::CFToNSCast(url.get()) path];
+  return base::FilePath([path_string fileSystemRepresentation]);
+}
+
+std::string WebAppShortcutCreator::GetBundleIdentifier() const {
+  // Replace spaces in the profile path with hyphen.
+  std::string normalized_profile_path;
+  ReplaceChars(info_.profile_path.BaseName().value(),
+               " ", "-", &normalized_profile_path);
+
+  // This matches APP_MODE_APP_BUNDLE_ID in chrome/chrome.gyp.
+  std::string bundle_id =
+      chrome_bundle_id_ + std::string(".app.") +
+      normalized_profile_path + "-" + info_.extension_id;
+
   return bundle_id;
 }
 
-void WebAppShortcutCreator::RevealGeneratedBundleInFinder(
-    const base::FilePath& generated_bundle) const {
+std::string WebAppShortcutCreator::GetInternalBundleIdentifier() const {
+  return GetBundleIdentifier() + "-internal";
+}
+
+void WebAppShortcutCreator::RevealAppShimInFinder() const {
+  base::FilePath dst_path = GetDestinationPath();
+  if (dst_path.empty())
+    return;
+
+  base::FilePath app_path = dst_path.Append(GetShortcutName());
   [[NSWorkspace sharedWorkspace]
-                    selectFile:base::mac::FilePathToNSString(generated_bundle)
+                    selectFile:base::mac::FilePathToNSString(app_path)
       inFileViewerRootedAtPath:nil];
 }
 
@@ -453,8 +578,10 @@
     const ShellIntegration::ShortcutInfo& shortcut_info) {
   WebAppShortcutCreator shortcut_creator(base::FilePath(),
                                          shortcut_info,
-                                         string16());
-  return shortcut_creator.GetShortcutPath();
+                                         std::string());
+  base::FilePath dst_path = shortcut_creator.GetDestinationPath();
+  return dst_path.empty() ?
+      base::FilePath() : dst_path.Append(shortcut_creator.GetShortcutName());
 }
 
 void MaybeLaunchShortcut(const ShellIntegration::ShortcutInfo& shortcut_info) {
@@ -468,51 +595,38 @@
 
 namespace internals {
 
-base::FilePath GetAppBundleByExtensionId(std::string extension_id) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
-  // This matches APP_MODE_APP_BUNDLE_ID in chrome/chrome.gyp.
-  std::string bundle_id =
-      base::mac::BaseBundleID() + std::string(".app.") + extension_id;
-  base::mac::ScopedCFTypeRef<CFStringRef> bundle_id_cf(
-      base::SysUTF8ToCFStringRef(bundle_id));
-  CFURLRef url_ref = NULL;
-  OSStatus status = LSFindApplicationForInfo(
-      kLSUnknownCreator, bundle_id_cf.get(), NULL, NULL, &url_ref);
-  base::mac::ScopedCFTypeRef<CFURLRef> url(url_ref);
-
-  if (status != noErr)
-    return base::FilePath();
-
-  NSString* path_string = [base::mac::CFToNSCast(url.get()) path];
-  return base::FilePath([path_string fileSystemRepresentation]);
-}
-
 bool CreatePlatformShortcuts(
     const base::FilePath& app_data_path,
     const ShellIntegration::ShortcutInfo& shortcut_info,
-    const ShellIntegration::ShortcutLocations& creation_locations) {
+    const ShellIntegration::ShortcutLocations& creation_locations,
+    ShortcutCreationPolicy /*creation_policy*/) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
-  string16 bundle_id = UTF8ToUTF16(base::mac::BaseBundleID());
-  WebAppShortcutCreator shortcut_creator(app_data_path, shortcut_info,
-                            bundle_id);
-  return shortcut_creator.CreateShortcut();
+  WebAppShortcutCreator shortcut_creator(
+      app_data_path, shortcut_info, base::mac::BaseBundleID());
+  return shortcut_creator.CreateShortcuts();
 }
 
 void DeletePlatformShortcuts(
     const base::FilePath& app_data_path,
-    const ShellIntegration::ShortcutInfo& info) {
+    const ShellIntegration::ShortcutInfo& shortcut_info) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
-
-  base::FilePath bundle_path = GetAppBundleByExtensionId(info.extension_id);
-  file_util::Delete(bundle_path, true);
+  WebAppShortcutCreator shortcut_creator(
+      app_data_path, shortcut_info, base::mac::BaseBundleID());
+  shortcut_creator.DeleteShortcuts();
 }
 
 void UpdatePlatformShortcuts(
     const base::FilePath& app_data_path,
     const string16& old_app_title,
     const ShellIntegration::ShortcutInfo& shortcut_info) {
-  // TODO(benwells): Implement this when shortcuts / weblings are enabled on
-  // mac.
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
+  WebAppShortcutCreator shortcut_creator(
+      app_data_path, shortcut_info, base::mac::BaseBundleID());
+  shortcut_creator.UpdateShortcuts();
+}
+
+void DeleteAllShortcutsForProfile(const base::FilePath& profile_path) {
+  // TODO(mgiuca): Implement this on Mac.
 }
 
 }  // namespace internals
diff --git a/chrome/browser/web_applications/web_app_mac_unittest.mm b/chrome/browser/web_applications/web_app_mac_unittest.mm
index b82a0d5..a96ff4c 100644
--- a/chrome/browser/web_applications/web_app_mac_unittest.mm
+++ b/chrome/browser/web_applications/web_app_mac_unittest.mm
@@ -6,13 +6,13 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include <sys/xattr.h>
 #include <errno.h>
+#include <sys/xattr.h>
 
 #include "base/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/mac/foundation_util.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/common/mac/app_mode_common.h"
@@ -30,27 +30,31 @@
 
 namespace {
 
+const char kFakeChromeBundleId[] = "fake.cfbundleidentifier";
+
 class WebAppShortcutCreatorMock : public web_app::WebAppShortcutCreator {
  public:
   explicit WebAppShortcutCreatorMock(
       const base::FilePath& app_data_path,
       const ShellIntegration::ShortcutInfo& shortcut_info)
-      : WebAppShortcutCreator(app_data_path, shortcut_info,
-            UTF8ToUTF16("fake.cfbundleidentifier")) {
+      : WebAppShortcutCreator(app_data_path,
+                              shortcut_info,
+                              kFakeChromeBundleId) {
   }
 
   MOCK_CONST_METHOD0(GetDestinationPath, base::FilePath());
-  MOCK_CONST_METHOD1(RevealGeneratedBundleInFinder,
-                     void (const base::FilePath&));
+  MOCK_CONST_METHOD1(GetAppBundleById,
+                     base::FilePath(const std::string& bundle_id));
+  MOCK_CONST_METHOD0(RevealAppShimInFinder, void());
 };
 
 ShellIntegration::ShortcutInfo GetShortcutInfo() {
   ShellIntegration::ShortcutInfo info;
-  info.extension_id = "extension_id";
+  info.extension_id = "extensionid";
   info.extension_path = base::FilePath("/fake/extension/path");
   info.title = ASCIIToUTF16("Shortcut Title");
   info.url = GURL("http://example.com/");
-  info.profile_path = base::FilePath("Default");
+  info.profile_path = base::FilePath("Profile 1");
   info.profile_name = "profile name";
   return info;
 }
@@ -59,7 +63,7 @@
 
 namespace web_app {
 
-TEST(WebAppShortcutCreatorTest, CreateShortcut) {
+TEST(WebAppShortcutCreatorTest, CreateShortcuts) {
   base::ScopedTempDir temp_app_data_path;
   EXPECT_TRUE(temp_app_data_path.CreateUniqueTempDir());
   base::ScopedTempDir temp_dst_dir;
@@ -67,7 +71,6 @@
 
   ShellIntegration::ShortcutInfo info = GetShortcutInfo();
 
-
   base::FilePath app_name(
       info.profile_path.value() + " " + info.extension_id + ".app");
   base::FilePath app_in_app_data_path_path =
@@ -79,12 +82,12 @@
       temp_app_data_path.path(), info);
   EXPECT_CALL(shortcut_creator, GetDestinationPath())
       .WillRepeatedly(Return(dst_folder));
-  EXPECT_CALL(shortcut_creator, RevealGeneratedBundleInFinder(dst_path));
+  EXPECT_CALL(shortcut_creator, RevealAppShimInFinder());
 
-  EXPECT_TRUE(shortcut_creator.CreateShortcut());
+  EXPECT_TRUE(shortcut_creator.CreateShortcuts());
   EXPECT_TRUE(file_util::PathExists(app_in_app_data_path_path));
   EXPECT_TRUE(file_util::PathExists(dst_path));
-  EXPECT_EQ(dst_path.value(), shortcut_creator.GetShortcutPath().value());
+  EXPECT_EQ(dst_path.BaseName(), shortcut_creator.GetShortcutName());
 
   base::FilePath plist_path = dst_path.Append("Contents").Append("Info.plist");
   NSDictionary* plist = [NSDictionary dictionaryWithContentsOfFile:
@@ -107,6 +110,77 @@
   }
 }
 
+TEST(WebAppShortcutCreatorTest, UpdateShortcuts) {
+  base::ScopedTempDir temp_app_data_path;
+  EXPECT_TRUE(temp_app_data_path.CreateUniqueTempDir());
+  base::ScopedTempDir temp_dst_dir;
+  EXPECT_TRUE(temp_dst_dir.CreateUniqueTempDir());
+  base::ScopedTempDir temp_dst_dir_other;
+  EXPECT_TRUE(temp_dst_dir_other.CreateUniqueTempDir());
+
+  ShellIntegration::ShortcutInfo info = GetShortcutInfo();
+
+  base::FilePath app_name(
+      info.profile_path.value() + " " + info.extension_id + ".app");
+  base::FilePath app_in_app_data_path_path =
+      temp_app_data_path.path().Append(app_name);
+  base::FilePath dst_folder = temp_dst_dir.path();
+  base::FilePath other_folder = temp_dst_dir_other.path();
+
+  NiceMock<WebAppShortcutCreatorMock> shortcut_creator(
+      temp_app_data_path.path(), info);
+  EXPECT_CALL(shortcut_creator, GetDestinationPath())
+      .WillRepeatedly(Return(dst_folder));
+
+  std::string expected_bundle_id = kFakeChromeBundleId;
+  expected_bundle_id += ".app.Profile-1-" + info.extension_id;
+  EXPECT_CALL(shortcut_creator, GetAppBundleById(expected_bundle_id))
+      .WillOnce(Return(other_folder.Append(app_name)));
+
+  shortcut_creator.BuildShortcut(other_folder.Append(app_name));
+
+  EXPECT_TRUE(base::Delete(
+      other_folder.Append(app_name).Append("Contents"), true));
+
+  EXPECT_TRUE(shortcut_creator.UpdateShortcuts());
+  EXPECT_FALSE(file_util::PathExists(dst_folder.Append(app_name)));
+  EXPECT_TRUE(file_util::PathExists(
+      other_folder.Append(app_name).Append("Contents")));
+
+  // Also test case where GetAppBundleById fails.
+  EXPECT_CALL(shortcut_creator, GetAppBundleById(expected_bundle_id))
+      .WillOnce(Return(base::FilePath()));
+
+  shortcut_creator.BuildShortcut(other_folder.Append(app_name));
+
+  EXPECT_TRUE(base::Delete(
+      other_folder.Append(app_name).Append("Contents"), true));
+
+  EXPECT_FALSE(shortcut_creator.UpdateShortcuts());
+  EXPECT_FALSE(file_util::PathExists(dst_folder.Append(app_name)));
+  EXPECT_FALSE(file_util::PathExists(
+      other_folder.Append(app_name).Append("Contents")));
+}
+
+TEST(WebAppShortcutCreatorTest, CreateAppListShortcut) {
+  base::ScopedTempDir temp_dst_dir;
+  EXPECT_TRUE(temp_dst_dir.CreateUniqueTempDir());
+
+  ShellIntegration::ShortcutInfo info = GetShortcutInfo();
+
+  base::FilePath dst_folder = temp_dst_dir.path();
+
+  // With an empty |profile_name|, the shortcut path should not have the profile
+  // directory prepended to the extension id on the app bundle name.
+  info.profile_name.clear();
+  base::FilePath dst_path = dst_folder.Append(info.extension_id + ".app");
+
+  NiceMock<WebAppShortcutCreatorMock> shortcut_creator(base::FilePath(), info);
+  EXPECT_CALL(shortcut_creator, GetDestinationPath())
+      .WillRepeatedly(Return(dst_folder));
+  EXPECT_EQ(dst_path.BaseName(), shortcut_creator.GetShortcutName());
+}
+
 TEST(WebAppShortcutCreatorTest, RunShortcut) {
   base::ScopedTempDir temp_app_data_path;
   EXPECT_TRUE(temp_app_data_path.CreateUniqueTempDir());
@@ -123,9 +197,9 @@
       temp_app_data_path.path(), info);
   EXPECT_CALL(shortcut_creator, GetDestinationPath())
       .WillRepeatedly(Return(dst_folder));
-  EXPECT_CALL(shortcut_creator, RevealGeneratedBundleInFinder(dst_path));
+  EXPECT_CALL(shortcut_creator, RevealAppShimInFinder());
 
-  EXPECT_TRUE(shortcut_creator.CreateShortcut());
+  EXPECT_TRUE(shortcut_creator.CreateShortcuts());
   EXPECT_TRUE(file_util::PathExists(dst_path));
 
   ssize_t status = getxattr(
@@ -147,7 +221,7 @@
       temp_app_data_path.path(), GetShortcutInfo());
   EXPECT_CALL(shortcut_creator, GetDestinationPath())
       .WillRepeatedly(Return(non_existent_path));
-  EXPECT_FALSE(shortcut_creator.CreateShortcut());
+  EXPECT_FALSE(shortcut_creator.CreateShortcuts());
 }
 
 TEST(WebAppShortcutCreatorTest, UpdateIcon) {
@@ -168,8 +242,8 @@
   base::FilePath icon_path =
       dst_path.Append("Contents").Append("Resources").Append("app.icns");
 
-  scoped_nsobject<NSImage> image([[NSImage alloc] initWithContentsOfFile:
-      base::mac::FilePathToNSString(icon_path)]);
+  base::scoped_nsobject<NSImage> image([[NSImage alloc]
+      initWithContentsOfFile:base::mac::FilePathToNSString(icon_path)]);
   EXPECT_TRUE(image);
   EXPECT_EQ(product_logo.Width(), [image size].width);
   EXPECT_EQ(product_logo.Height(), [image size].height);
diff --git a/chrome/browser/web_applications/web_app_win.cc b/chrome/browser/web_applications/web_app_win.cc
index 9e3c5ee..6e19753 100644
--- a/chrome/browser/web_applications/web_app_win.cc
+++ b/chrome/browser/web_applications/web_app_win.cc
@@ -2,12 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/web_applications/web_app.h"
+#include "chrome/browser/web_applications/web_app_win.h"
 
 #include <shlobj.h>
 
 #include "base/command_line.h"
 #include "base/file_util.h"
+#include "base/files/file_enumerator.h"
 #include "base/logging.h"
 #include "base/md5.h"
 #include "base/path_service.h"
@@ -16,6 +17,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/win/shortcut.h"
 #include "base/win/windows_version.h"
+#include "chrome/browser/web_applications/web_app.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/installer/launcher_support/chrome_launcher_support.h"
 #include "chrome/installer/util/util_constants.h"
@@ -91,53 +93,78 @@
                 sizeof(base::MD5Digest)) != 0;
 }
 
-bool ShortcutIsForProfile(const base::FilePath& shortcut_file_name,
-                          const base::FilePath& profile_path) {
+// Returns true if |shortcut_file_name| matches profile |profile_path|, and has
+// an --app-id flag.
+bool IsAppShortcutForProfile(const base::FilePath& shortcut_file_name,
+                             const base::FilePath& profile_path) {
   string16 cmd_line_string;
   if (base::win::ResolveShortcut(shortcut_file_name, NULL, &cmd_line_string)) {
     cmd_line_string = L"program " + cmd_line_string;
     CommandLine shortcut_cmd_line = CommandLine::FromString(cmd_line_string);
     return shortcut_cmd_line.HasSwitch(switches::kProfileDirectory) &&
            shortcut_cmd_line.GetSwitchValuePath(switches::kProfileDirectory) ==
-               profile_path.BaseName();
+               profile_path.BaseName() &&
+           shortcut_cmd_line.HasSwitch(switches::kAppId);
   }
 
   return false;
 }
 
-std::vector<base::FilePath> MatchingShortcutsForProfileAndExtension(
+// Finds shortcuts in |shortcut_path| that match profile for |profile_path| and
+// extension with title |shortcut_name|.
+// If |shortcut_name| is empty, finds all shortcuts matching |profile_path|.
+std::vector<base::FilePath> FindAppShortcutsByProfileAndTitle(
     const base::FilePath& shortcut_path,
     const base::FilePath& profile_path,
     const string16& shortcut_name) {
   std::vector<base::FilePath> shortcut_paths;
-  base::FilePath base_path = shortcut_path.
-      Append(web_app::internals::GetSanitizedFileName(shortcut_name)).
-      AddExtension(FILE_PATH_LITERAL(".lnk"));
 
-  const int fileNamesToCheck = 10;
-  for (int i = 0; i < fileNamesToCheck; ++i) {
-    base::FilePath shortcut_file = base_path;
-    if (i) {
-      shortcut_file = shortcut_file.InsertBeforeExtensionASCII(
-          base::StringPrintf(" (%d)", i));
+  if (shortcut_name.empty()) {
+    // Find all shortcuts for this profile.
+    base::FileEnumerator files(shortcut_path, false,
+                               base::FileEnumerator::FILES,
+                               FILE_PATH_LITERAL("*.lnk"));
+    base::FilePath shortcut_file = files.Next();
+    while (!shortcut_file.empty()) {
+      if (IsAppShortcutForProfile(shortcut_file, profile_path))
+        shortcut_paths.push_back(shortcut_file);
+      shortcut_file = files.Next();
     }
-    if (file_util::PathExists(shortcut_file) &&
-        ShortcutIsForProfile(shortcut_file, profile_path)) {
-      shortcut_paths.push_back(shortcut_file);
+  } else {
+    // Find all shortcuts matching |shortcut_name|.
+    base::FilePath base_path = shortcut_path.
+        Append(web_app::internals::GetSanitizedFileName(shortcut_name)).
+        AddExtension(FILE_PATH_LITERAL(".lnk"));
+
+    const int fileNamesToCheck = 10;
+    for (int i = 0; i < fileNamesToCheck; ++i) {
+      base::FilePath shortcut_file = base_path;
+      if (i > 0) {
+        shortcut_file = shortcut_file.InsertBeforeExtensionASCII(
+            base::StringPrintf(" (%d)", i));
+      }
+      if (file_util::PathExists(shortcut_file) &&
+          IsAppShortcutForProfile(shortcut_file, profile_path)) {
+        shortcut_paths.push_back(shortcut_file);
+      }
     }
   }
+
   return shortcut_paths;
 }
 
 // Creates application shortcuts in a given set of paths.
 // |shortcut_paths| is a list of directories in which shortcuts should be
-// created.
+// created. If |creation_policy| is DONT_CREATE_DUPLICATE_SHORTCUTS and there is
+// an existing shortcut to this app for this profile, does nothing (succeeding).
 // Returns true on success, false on failure.
 // Must be called on the FILE thread.
 bool CreateShortcutsInPaths(
     const base::FilePath& web_app_path,
     const ShellIntegration::ShortcutInfo& shortcut_info,
-    const std::vector<base::FilePath>& shortcut_paths) {
+    const std::vector<base::FilePath>& shortcut_paths,
+    web_app::ShortcutCreationPolicy creation_policy,
+    std::vector<base::FilePath>* out_filenames) {
   // Ensure web_app_path exists.
   if (!file_util::PathExists(web_app_path) &&
       !file_util::CreateDirectory(web_app_path)) {
@@ -188,6 +215,15 @@
   for (size_t i = 0; i < shortcut_paths.size(); ++i) {
     base::FilePath shortcut_file = shortcut_paths[i].Append(file_name).
         AddExtension(installer::kLnkExt);
+    if (creation_policy == web_app::DONT_CREATE_DUPLICATE_SHORTCUTS) {
+      // Check whether there is an existing shortcut to this app.
+      std::vector<base::FilePath> shortcut_files =
+          FindAppShortcutsByProfileAndTitle(shortcut_paths[i],
+                                            shortcut_info.profile_path,
+                                            shortcut_info.title);
+      if (!shortcut_files.empty())
+        continue;
+    }
     if (shortcut_paths[i] != web_app_path) {
       int unique_number =
           file_util::GetUniquePathNumber(shortcut_file, FILE_PATH_LITERAL(""));
@@ -215,6 +251,8 @@
     success = base::win::CreateOrUpdateShortcutLink(
         shortcut_file, shortcut_properties,
         base::win::SHORTCUT_CREATE_ALWAYS) && success;
+    if (out_filenames)
+      out_filenames->push_back(shortcut_file);
   }
 
   return success;
@@ -225,6 +263,9 @@
 // in the profile with |profile_path|.
 // |was_pinned_to_taskbar| will be set to true if there was previously a
 // shortcut pinned to the taskbar for this app; false otherwise.
+// If |web_app_path| is empty, this will not delete shortcuts from the web app
+// directory. If |title| is empty, all shortcuts for this profile will be
+// deleted.
 // |shortcut_paths| will be populated with a list of directories where shortcuts
 // for this app were found (and deleted). This will delete duplicate shortcuts,
 // but only return each path once, even if it contained multiple deleted
@@ -249,16 +290,18 @@
       web_app::GetAppShortcutsSubdirName();
   std::vector<base::FilePath> all_paths = web_app::internals::GetShortcutPaths(
       all_shortcut_locations);
-  if (base::win::GetVersion() >= base::win::VERSION_WIN7)
+  if (base::win::GetVersion() >= base::win::VERSION_WIN7 &&
+      !web_app_path.empty()) {
     all_paths.push_back(web_app_path);
+  }
 
   if (was_pinned_to_taskbar) {
     // Determine if there is a link to this app in the TaskBar pin directory.
     base::FilePath taskbar_pin_path;
     if (PathService::Get(base::DIR_TASKBAR_PINS, &taskbar_pin_path)) {
       std::vector<base::FilePath> taskbar_pin_files =
-          MatchingShortcutsForProfileAndExtension(taskbar_pin_path,
-                                                  profile_path, title);
+          FindAppShortcutsByProfileAndTitle(taskbar_pin_path, profile_path,
+                                            title);
       *was_pinned_to_taskbar = !taskbar_pin_files.empty();
     } else {
       *was_pinned_to_taskbar = false;
@@ -268,7 +311,7 @@
   for (std::vector<base::FilePath>::const_iterator i = all_paths.begin();
        i != all_paths.end(); ++i) {
     std::vector<base::FilePath> shortcut_files =
-        MatchingShortcutsForProfileAndExtension(*i, profile_path, title);
+        FindAppShortcutsByProfileAndTitle(*i, profile_path, title);
     if (shortcut_paths && !shortcut_files.empty()) {
       shortcut_paths->push_back(*i);
     }
@@ -277,7 +320,7 @@
       // Any shortcut could have been pinned, either by chrome or the user, so
       // they are all unpinned.
       base::win::TaskbarUnpinShortcutLink(j->value().c_str());
-      file_util::Delete(*j, false);
+      base::Delete(*j, false);
     }
   }
 }
@@ -286,6 +329,18 @@
 
 namespace web_app {
 
+base::FilePath CreateShortcutInWebAppDir(
+    const base::FilePath& web_app_dir,
+    const ShellIntegration::ShortcutInfo& shortcut_info) {
+  std::vector<base::FilePath> paths;
+  paths.push_back(web_app_dir);
+  std::vector<base::FilePath> out_filenames;
+  CreateShortcutsInPaths(web_app_dir, shortcut_info, paths,
+                         ALLOW_DUPLICATE_SHORTCUTS, &out_filenames);
+  DCHECK_EQ(out_filenames.size(), 1u);
+  return out_filenames[0];
+}
+
 namespace internals {
 
 // Saves |image| to |icon_file| if the file is outdated and refresh shell's
@@ -311,7 +366,8 @@
 bool CreatePlatformShortcuts(
     const base::FilePath& web_app_path,
     const ShellIntegration::ShortcutInfo& shortcut_info,
-    const ShellIntegration::ShortcutLocations& creation_locations) {
+    const ShellIntegration::ShortcutLocations& creation_locations,
+    ShortcutCreationPolicy creation_policy) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
 
   // Shortcut paths under which to create shortcuts.
@@ -331,7 +387,8 @@
   if (shortcut_paths.empty())
     return false;
 
-  if (!CreateShortcutsInPaths(web_app_path, shortcut_info, shortcut_paths))
+  if (!CreateShortcutsInPaths(web_app_path, shortcut_info, shortcut_paths,
+                              creation_policy, NULL))
     return false;
 
   if (pin_to_taskbar) {
@@ -367,7 +424,8 @@
     GetShortcutLocationsAndDeleteShortcuts(
         web_app_path, shortcut_info.profile_path, old_app_title,
         &was_pinned_to_taskbar, &shortcut_paths);
-    CreateShortcutsInPaths(web_app_path, shortcut_info, shortcut_paths);
+    CreateShortcutsInPaths(web_app_path, shortcut_info, shortcut_paths,
+                           ALLOW_DUPLICATE_SHORTCUTS, NULL);
     // If the shortcut was pinned to the taskbar,
     // GetShortcutLocationsAndDeleteShortcuts will have deleted it. In that
     // case, re-pin it.
@@ -403,7 +461,20 @@
   if (PathService::Get(base::DIR_START_MENU, &chrome_apps_dir)) {
     chrome_apps_dir = chrome_apps_dir.Append(GetAppShortcutsSubdirName());
     if (file_util::IsDirectoryEmpty(chrome_apps_dir))
-      file_util::Delete(chrome_apps_dir, false);
+      base::Delete(chrome_apps_dir, false);
+  }
+}
+
+void DeleteAllShortcutsForProfile(const base::FilePath& profile_path) {
+  GetShortcutLocationsAndDeleteShortcuts(base::FilePath(), profile_path, L"",
+                                         NULL, NULL);
+
+  // If there are no more shortcuts in the Chrome Apps subdirectory, remove it.
+  base::FilePath chrome_apps_dir;
+  if (PathService::Get(base::DIR_START_MENU, &chrome_apps_dir)) {
+    chrome_apps_dir = chrome_apps_dir.Append(GetAppShortcutsSubdirName());
+    if (file_util::IsDirectoryEmpty(chrome_apps_dir))
+      base::Delete(chrome_apps_dir, false);
   }
 }
 
diff --git a/chrome/browser/web_applications/web_app_win.h b/chrome/browser/web_applications/web_app_win.h
new file mode 100644
index 0000000..6b2cf5b
--- /dev/null
+++ b/chrome/browser/web_applications/web_app_win.h
@@ -0,0 +1,32 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_WEB_APPLICATIONS_WEB_APP_WIN_H_
+#define CHROME_BROWSER_WEB_APPLICATIONS_WEB_APP_WIN_H_
+
+#include "base/files/file_path.h"
+#include "chrome/browser/shell_integration.h"
+
+namespace gfx {
+class ImageFamily;
+}
+
+namespace web_app {
+
+// Create a shortcut in the given web app data dir, returning the name of the
+// created shortcut.
+base::FilePath CreateShortcutInWebAppDir(
+    const base::FilePath& web_app_path,
+    const ShellIntegration::ShortcutInfo& shortcut_info);
+
+namespace internals {
+
+bool CheckAndSaveIcon(const base::FilePath& icon_file,
+                      const gfx::ImageFamily& image);
+
+}  // namespace internals
+
+}  // namespace web_app
+
+#endif  // CHROME_BROWSER_WEB_APPLICATIONS_WEB_APP_WIN_H_
diff --git a/chrome/browser/web_resource/notification_promo.cc b/chrome/browser/web_resource/notification_promo.cc
index f0869e4..222f4f5 100644
--- a/chrome/browser/web_resource/notification_promo.cc
+++ b/chrome/browser/web_resource/notification_promo.cc
@@ -16,7 +16,7 @@
 #include "base/strings/string_util.h"
 #include "base/sys_info.h"
 #include "base/threading/thread_restrictions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/web_resource/promo_resource_service.h"
@@ -24,8 +24,8 @@
 #include "chrome/common/pref_names.h"
 #include "components/user_prefs/pref_registry_syncable.h"
 #include "content/public/browser/user_metrics.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/url_util.h"
+#include "url/gurl.h"
 
 #if defined(OS_ANDROID)
 #include "base/command_line.h"
diff --git a/chrome/browser/web_resource/notification_promo.h b/chrome/browser/web_resource/notification_promo.h
index bde22d6..0cc8ace 100644
--- a/chrome/browser/web_resource/notification_promo.h
+++ b/chrome/browser/web_resource/notification_promo.h
@@ -11,7 +11,7 @@
 #include "base/gtest_prod_util.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 class PrefRegistrySimple;
 class PrefService;
diff --git a/chrome/browser/web_resource/promo_resource_service.cc b/chrome/browser/web_resource/promo_resource_service.cc
index 02c1655..2c02f63 100644
--- a/chrome/browser/web_resource/promo_resource_service.cc
+++ b/chrome/browser/web_resource/promo_resource_service.cc
@@ -18,7 +18,7 @@
 #include "chrome/common/pref_names.h"
 #include "components/user_prefs/pref_registry_syncable.h"
 #include "content/public/browser/notification_service.h"
-#include "googleurl/src/gurl.h"
+#include "url/gurl.h"
 
 namespace {
 
diff --git a/chrome/browser/web_resource/promo_resource_service_mobile_ntp_unittest.cc b/chrome/browser/web_resource/promo_resource_service_mobile_ntp_unittest.cc
index 389ebe0..fd98b20 100644
--- a/chrome/browser/web_resource/promo_resource_service_mobile_ntp_unittest.cc
+++ b/chrome/browser/web_resource/promo_resource_service_mobile_ntp_unittest.cc
@@ -8,7 +8,7 @@
 #include "base/message_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/web_resource/notification_promo.h"
diff --git a/chrome/browser/web_resource/promo_resource_service_unittest.cc b/chrome/browser/web_resource/promo_resource_service_unittest.cc
index 8c7c98f..bea1751 100644
--- a/chrome/browser/web_resource/promo_resource_service_unittest.cc
+++ b/chrome/browser/web_resource/promo_resource_service_unittest.cc
@@ -12,7 +12,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/prefs/browser_prefs.h"
diff --git a/chrome/browser/web_resource/web_resource_service.cc b/chrome/browser/web_resource/web_resource_service.cc
index 94f00b3..b483a6e 100644
--- a/chrome/browser/web_resource/web_resource_service.cc
+++ b/chrome/browser/web_resource/web_resource_service.cc
@@ -10,14 +10,14 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/google/google_util.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/load_flags.h"
 #include "net/url_request/url_fetcher.h"
 #include "net/url_request/url_request_status.h"
+#include "url/gurl.h"
 
 WebResourceService::WebResourceService(
     PrefService* prefs,
diff --git a/chrome/browser/web_resource/web_resource_service.h b/chrome/browser/web_resource/web_resource_service.h
index 9cc4d3c..7acc63a 100644
--- a/chrome/browser/web_resource/web_resource_service.h
+++ b/chrome/browser/web_resource/web_resource_service.h
@@ -12,8 +12,8 @@
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/web_resource/json_asynchronous_unpacker.h"
 #include "chrome/browser/web_resource/resource_request_allowed_notifier.h"
-#include "googleurl/src/gurl.h"
 #include "net/url_request/url_fetcher_delegate.h"
+#include "url/gurl.h"
 
 class PrefService;
 
diff --git a/chrome/browser/webdata/autocomplete_syncable_service.cc b/chrome/browser/webdata/autocomplete_syncable_service.cc
index 2a95887..a57994a 100644
--- a/chrome/browser/webdata/autocomplete_syncable_service.cc
+++ b/chrome/browser/webdata/autocomplete_syncable_service.cc
@@ -7,8 +7,8 @@
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/strings/utf_string_conversions.h"
-#include "components/autofill/browser/webdata/autofill_table.h"
-#include "components/autofill/browser/webdata/autofill_webdata_service.h"
+#include "components/autofill/core/browser/webdata/autofill_table.h"
+#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
 #include "components/webdata/common/web_database.h"
 #include "content/public/browser/browser_thread.h"
 #include "net/base/escape.h"
@@ -238,8 +238,10 @@
   DCHECK(sync_processor_.get());
 
   if (!sync_processor_.get()) {
-    syncer::SyncError error(FROM_HERE, "Models not yet associated.",
-                    syncer::AUTOFILL);
+    syncer::SyncError error(FROM_HERE,
+                            syncer::SyncError::DATATYPE_ERROR,
+                            "Models not yet associated.",
+                            syncer::AUTOFILL);
     return error;
   }
 
diff --git a/chrome/browser/webdata/autocomplete_syncable_service.h b/chrome/browser/webdata/autocomplete_syncable_service.h
index 3deb86b..fb254dc 100644
--- a/chrome/browser/webdata/autocomplete_syncable_service.h
+++ b/chrome/browser/webdata/autocomplete_syncable_service.h
@@ -15,11 +15,11 @@
 #include "base/scoped_observer.h"
 #include "base/supports_user_data.h"
 #include "base/threading/non_thread_safe.h"
-#include "components/autofill/browser/webdata/autofill_change.h"
-#include "components/autofill/browser/webdata/autofill_entry.h"
-#include "components/autofill/browser/webdata/autofill_webdata_backend.h"
-#include "components/autofill/browser/webdata/autofill_webdata_service.h"
-#include "components/autofill/browser/webdata/autofill_webdata_service_observer.h"
+#include "components/autofill/core/browser/webdata/autofill_change.h"
+#include "components/autofill/core/browser/webdata/autofill_entry.h"
+#include "components/autofill/core/browser/webdata/autofill_webdata_backend.h"
+#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
+#include "components/autofill/core/browser/webdata/autofill_webdata_service_observer.h"
 #include "sync/api/sync_change.h"
 #include "sync/api/sync_data.h"
 #include "sync/api/sync_error.h"
diff --git a/chrome/browser/webdata/autofill_profile_syncable_service.cc b/chrome/browser/webdata/autofill_profile_syncable_service.cc
index 60b73b5..530f390 100644
--- a/chrome/browser/webdata/autofill_profile_syncable_service.cc
+++ b/chrome/browser/webdata/autofill_profile_syncable_service.cc
@@ -8,11 +8,11 @@
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/strings/utf_string_conversions.h"
-#include "components/autofill/browser/autofill_country.h"
-#include "components/autofill/browser/autofill_profile.h"
-#include "components/autofill/browser/form_group.h"
-#include "components/autofill/browser/webdata/autofill_table.h"
-#include "components/autofill/browser/webdata/autofill_webdata_service.h"
+#include "components/autofill/core/browser/autofill_country.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/form_group.h"
+#include "components/autofill/core/browser/webdata/autofill_table.h"
+#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
 #include "components/webdata/common/web_database.h"
 #include "content/public/browser/browser_thread.h"
 #include "sync/api/sync_error.h"
@@ -228,8 +228,10 @@
     const syncer::SyncChangeList& change_list) {
   DCHECK(CalledOnValidThread());
   if (!sync_processor_.get()) {
-    syncer::SyncError error(FROM_HERE, "Models not yet associated.",
-                    syncer::AUTOFILL_PROFILE);
+    syncer::SyncError error(FROM_HERE,
+                            syncer::SyncError::DATATYPE_ERROR,
+                            "Models not yet associated.",
+                            syncer::AUTOFILL_PROFILE);
     return error;
   }
 
@@ -319,6 +321,15 @@
     AutofillProfile* profile,
     const std::string& app_locale) {
   bool diff = false;
+  if (profile->origin() != specifics.origin()) {
+    bool was_verified = profile->IsVerified();
+    profile->set_origin(specifics.origin());
+    diff = true;
+
+    // Verified profiles should never be overwritten by unverified ones.
+    DCHECK(!was_verified || profile->IsVerified());
+  }
+
   diff = UpdateMultivaluedField(autofill::NAME_FIRST,
                                 specifics.name_first(), profile) || diff;
   diff = UpdateMultivaluedField(autofill::NAME_MIDDLE,
@@ -368,6 +379,8 @@
   specifics->clear_phone_home_whole_number();
 
   specifics->set_guid(profile.guid());
+  specifics->set_origin(profile.origin());
+
   std::vector<string16> values;
   profile.GetRawMultiInfo(autofill::NAME_FIRST, &values);
   for (size_t i = 0; i < values.size(); ++i) {
@@ -435,49 +448,59 @@
   const sync_pb::AutofillProfileSpecifics& autofill_specifics(
       specifics.autofill_profile());
 
-  GUIDToProfileMap::iterator it = profile_map->find(
+  GUIDToProfileMap::iterator existing_profile = profile_map->find(
         autofill_specifics.guid());
-  if (it != profile_map->end()) {
-    // Some profile that already present is synced.
+  if (existing_profile != profile_map->end()) {
+    // The synced profile already exists locally.  It might need to be updated.
     if (OverwriteProfileWithServerData(
-            autofill_specifics, it->second, app_locale_)) {
-      bundle->profiles_to_update.push_back(it->second);
+            autofill_specifics, existing_profile->second, app_locale_)) {
+      bundle->profiles_to_update.push_back(existing_profile->second);
     }
-  } else {
-    // New profile synced.
-    // TODO(isherman): Read the origin from |autofill_specifics|.
-    AutofillProfile* new_profile(
-        new AutofillProfile(autofill_specifics.guid(), std::string()));
-    OverwriteProfileWithServerData(
-        autofill_specifics, new_profile, app_locale_);
-
-    // Check if profile appears under a different guid.
-    for (GUIDToProfileMap::iterator i = profile_map->begin();
-         i != profile_map->end(); ++i) {
-      if (i->second->Compare(*new_profile) == 0) {
-        bundle->profiles_to_delete.push_back(i->second->guid());
-        DVLOG(2) << "[AUTOFILL SYNC]"
-                 << "Found in sync db but with a different guid: "
-                 << UTF16ToUTF8(i->second->GetRawInfo(autofill::NAME_FIRST))
-                 << UTF16ToUTF8(i->second->GetRawInfo(autofill::NAME_LAST))
-                 << "New guid " << new_profile->guid()
-                 << ". Profile to be deleted " << i->second->guid();
-        profile_map->erase(i);
-        break;
-      } else if (!i->second->PrimaryValue().empty() &&
-                 i->second->PrimaryValue() == new_profile->PrimaryValue()) {
-        // Add it to candidates for merge - if there is no profile with this
-        // guid we will merge them.
-        bundle->candidates_to_merge.insert(std::make_pair(i->second->guid(),
-                                                          new_profile));
-      }
-    }
-    profiles_.push_back(new_profile);
-    it = profile_map->insert(std::make_pair(new_profile->guid(),
-                                            new_profile)).first;
-    bundle->profiles_to_add.push_back(new_profile);
+    return existing_profile;
   }
-  return it;
+
+
+  // New profile synced.
+  AutofillProfile* new_profile = new AutofillProfile(
+      autofill_specifics.guid(), autofill_specifics.origin());
+  OverwriteProfileWithServerData(autofill_specifics, new_profile, app_locale_);
+
+  // Check if profile appears under a different guid.
+  // Unverified profiles should never overwrite verified ones.
+  for (GUIDToProfileMap::iterator it = profile_map->begin();
+       it != profile_map->end(); ++it) {
+    AutofillProfile* local_profile = it->second;
+    if (local_profile->Compare(*new_profile) == 0) {
+      // Ensure that a verified profile can never revert back to an unverified
+      // one.
+      if (local_profile->IsVerified() && !new_profile->IsVerified()) {
+        new_profile->set_origin(local_profile->origin());
+        bundle->profiles_to_sync_back.push_back(new_profile);
+      }
+
+      bundle->profiles_to_delete.push_back(local_profile->guid());
+      DVLOG(2) << "[AUTOFILL SYNC]"
+               << "Found in sync db but with a different guid: "
+               << UTF16ToUTF8(local_profile->GetRawInfo(autofill::NAME_FIRST))
+               << UTF16ToUTF8(local_profile->GetRawInfo(autofill::NAME_LAST))
+               << "New guid " << new_profile->guid()
+               << ". Profile to be deleted " << local_profile->guid();
+      profile_map->erase(it);
+      break;
+    } else if (!local_profile->IsVerified() &&
+               !new_profile->IsVerified() &&
+               !local_profile->PrimaryValue().empty() &&
+               local_profile->PrimaryValue() == new_profile->PrimaryValue()) {
+      // Add it to candidates for merge - if there is no profile with this
+      // guid we will merge them.
+      bundle->candidates_to_merge.insert(
+          std::make_pair(local_profile->guid(), new_profile));
+    }
+  }
+  profiles_.push_back(new_profile);
+  bundle->profiles_to_add.push_back(new_profile);
+  return profile_map->insert(std::make_pair(new_profile->guid(),
+                                            new_profile)).first;
 }
 
 void AutofillProfileSyncableService::ActOnChange(
@@ -582,7 +605,8 @@
     AutofillProfile* merge_into,
     const std::string& app_locale) {
   merge_into->OverwriteWithOrAddTo(merge_from, app_locale);
-  return (merge_into->Compare(merge_from) != 0);
+  return (merge_into->Compare(merge_from) != 0 ||
+          merge_into->origin() != merge_from.origin());
 }
 
 AutofillTable* AutofillProfileSyncableService::GetAutofillTable() const {
diff --git a/chrome/browser/webdata/autofill_profile_syncable_service.h b/chrome/browser/webdata/autofill_profile_syncable_service.h
index 6f0a831..498d3aa 100644
--- a/chrome/browser/webdata/autofill_profile_syncable_service.h
+++ b/chrome/browser/webdata/autofill_profile_syncable_service.h
@@ -14,11 +14,11 @@
 #include "base/supports_user_data.h"
 #include "base/synchronization/lock.h"
 #include "base/threading/non_thread_safe.h"
-#include "components/autofill/browser/autofill_type.h"
-#include "components/autofill/browser/webdata/autofill_change.h"
-#include "components/autofill/browser/webdata/autofill_entry.h"
-#include "components/autofill/browser/webdata/autofill_webdata_backend.h"
-#include "components/autofill/browser/webdata/autofill_webdata_service_observer.h"
+#include "components/autofill/core/browser/autofill_type.h"
+#include "components/autofill/core/browser/webdata/autofill_change.h"
+#include "components/autofill/core/browser/webdata/autofill_entry.h"
+#include "components/autofill/core/browser/webdata/autofill_webdata_backend.h"
+#include "components/autofill/core/browser/webdata/autofill_webdata_service_observer.h"
 #include "sync/api/sync_change.h"
 #include "sync/api/sync_data.h"
 #include "sync/api/sync_error.h"
@@ -96,26 +96,28 @@
   struct DataBundle;
 
   // Helper to query WebDatabase for the current autofill state.
-  // Made virtual for ease of mocking in the unit-test.
+  // Made virtual for ease of mocking in unit tests.
   // Caller owns returned |profiles|.
   virtual bool LoadAutofillData(
       std::vector<autofill::AutofillProfile*>* profiles);
 
   // Helper to persist any changes that occured during model association to
   // the WebDatabase.
-  // Made virtual for ease of mocking in the unit-test.
+  // Made virtual for ease of mocking in unit tests.
   virtual bool SaveChangesToWebData(const DataBundle& bundle);
 
+  // For unit tests.
+  AutofillProfileSyncableService();
+  void set_sync_processor(syncer::SyncChangeProcessor* sync_processor) {
+    sync_processor_.reset(sync_processor);
+  }
+
+  // Creates syncer::SyncData based on supplied |profile|.
+  // Exposed for unit tests.
+  static syncer::SyncData CreateData(const autofill::AutofillProfile& profile);
+
  private:
   friend class ProfileSyncServiceAutofillTest;
-  friend class MockAutofillProfileSyncableService;
-  FRIEND_TEST_ALL_PREFIXES(AutofillProfileSyncableServiceTest,
-                           MergeDataAndStartSyncing);
-  FRIEND_TEST_ALL_PREFIXES(AutofillProfileSyncableServiceTest, GetAllSyncData);
-  FRIEND_TEST_ALL_PREFIXES(AutofillProfileSyncableServiceTest,
-                           ProcessSyncChanges);
-  FRIEND_TEST_ALL_PREFIXES(AutofillProfileSyncableServiceTest,
-                           ActOnChange);
   FRIEND_TEST_ALL_PREFIXES(AutofillProfileSyncableServiceTest,
                            UpdateField);
   FRIEND_TEST_ALL_PREFIXES(AutofillProfileSyncableServiceTest,
@@ -156,9 +158,6 @@
   // Syncs |change| to the cloud.
   void ActOnChange(const autofill::AutofillProfileChange& change);
 
-  // Creates syncer::SyncData based on supplied |profile|.
-  static syncer::SyncData CreateData(const autofill::AutofillProfile& profile);
-
   autofill::AutofillTable* GetAutofillTable() const;
 
   // Helper to compare the local value and cloud value of a field, copy into
@@ -174,17 +173,14 @@
 
   // Calls merge_into->OverwriteWithOrAddTo() and then checks if the
   // |merge_into| has extra data. Returns |true| if |merge_into| posseses some
-  // multi-valued field values that are not in |merge_from|, false otherwise.
+  // multi-valued field values that are not in |merge_from| or if the origins
+  // of the two profiles differ, false otherwise.
+  // TODO(isherman): Seems like this should return |true| if |merge_into| was
+  // modified at all: http://crbug.com/248440
   static bool MergeProfile(const autofill::AutofillProfile& merge_from,
                            autofill::AutofillProfile* merge_into,
                            const std::string& app_locale);
 
-  // For unit-tests.
-  AutofillProfileSyncableService();
-  void set_sync_processor(syncer::SyncChangeProcessor* sync_processor) {
-    sync_processor_.reset(sync_processor);
-  }
-
   autofill::AutofillWebDataBackend* webdata_backend_;  // WEAK
   std::string app_locale_;
   ScopedObserver<autofill::AutofillWebDataBackend,
@@ -204,7 +200,7 @@
   DISALLOW_COPY_AND_ASSIGN(AutofillProfileSyncableService);
 };
 
-// This object is used in unit-tests as well, so it defined here.
+// This object is used in unit tests as well, so it defined here.
 struct AutofillProfileSyncableService::DataBundle {
   DataBundle();
   ~DataBundle();
diff --git a/chrome/browser/webdata/autofill_profile_syncable_service_unittest.cc b/chrome/browser/webdata/autofill_profile_syncable_service_unittest.cc
index bc51614..f5265a2 100644
--- a/chrome/browser/webdata/autofill_profile_syncable_service_unittest.cc
+++ b/chrome/browser/webdata/autofill_profile_syncable_service_unittest.cc
@@ -6,8 +6,8 @@
 #include "base/message_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/webdata/autofill_profile_syncable_service.h"
-#include "components/autofill/browser/autofill_profile.h"
-#include "components/autofill/browser/webdata/autofill_change.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/webdata/autofill_change.h"
 #include "content/public/test/test_browser_thread.h"
 #include "sync/api/sync_error_factory.h"
 #include "sync/api/sync_error_factory_mock.h"
@@ -36,10 +36,13 @@
 class MockAutofillProfileSyncableService
     : public AutofillProfileSyncableService {
  public:
-  MockAutofillProfileSyncableService() {
-  }
+  MockAutofillProfileSyncableService() {}
   virtual ~MockAutofillProfileSyncableService() {}
 
+  using AutofillProfileSyncableService::DataBundle;
+  using AutofillProfileSyncableService::set_sync_processor;
+  using AutofillProfileSyncableService::CreateData;
+
   MOCK_METHOD1(LoadAutofillData, bool(std::vector<AutofillProfile*>*));
   MOCK_METHOD1(SaveChangesToWebData,
                bool(const AutofillProfileSyncableService::DataBundle&));
@@ -71,21 +74,18 @@
 MATCHER_P(DataBundleCheck, n_bundle, "") {
   if ((arg.profiles_to_delete.size() != n_bundle.profiles_to_delete.size()) ||
       (arg.profiles_to_update.size() != n_bundle.profiles_to_update.size()) ||
-      (arg.profiles_to_add.size() != n_bundle.profiles_to_add.size())) {
+      (arg.profiles_to_add.size() != n_bundle.profiles_to_add.size()))
     return false;
-  }
   for (size_t i = 0; i < arg.profiles_to_delete.size(); ++i) {
     if (arg.profiles_to_delete[i] != n_bundle.profiles_to_delete[i])
       return false;
   }
   for (size_t i = 0; i < arg.profiles_to_update.size(); ++i) {
-    if (arg.profiles_to_update[i]->guid() !=
-        n_bundle.profiles_to_update[i]->guid()) {
+    if (*arg.profiles_to_update[i] != *n_bundle.profiles_to_update[i])
       return false;
-    }
   }
   for (size_t i = 0; i < arg.profiles_to_add.size(); ++i) {
-    if (arg.profiles_to_add[i]->Compare(*n_bundle.profiles_to_add[i]))
+    if (*arg.profiles_to_add[i] != *n_bundle.profiles_to_add[i])
       return false;
   }
   return true;
@@ -98,7 +98,25 @@
 
   MOCK_METHOD2(ProcessSyncChanges,
                syncer::SyncError(const tracked_objects::Location&,
-                         const syncer::SyncChangeList&));
+                                 const syncer::SyncChangeList&));
+};
+
+class TestSyncChangeProcessor : public syncer::SyncChangeProcessor {
+ public:
+  TestSyncChangeProcessor() {}
+  virtual ~TestSyncChangeProcessor() {}
+
+  virtual syncer::SyncError ProcessSyncChanges(
+      const tracked_objects::Location& location,
+      const syncer::SyncChangeList& changes) OVERRIDE {
+    changes_ = changes;
+    return syncer::SyncError();
+  }
+
+  const syncer::SyncChangeList& changes() { return changes_; }
+
+ private:
+  syncer::SyncChangeList changes_;
 };
 
 class AutofillProfileSyncableServiceTest : public testing::Test {
@@ -111,6 +129,35 @@
     sync_processor_.reset(new MockSyncChangeProcessor);
   }
 
+  // Wrapper around AutofillProfileSyncableService::MergeDataAndStartSyncing()
+  // that also verifies expectations.
+  void MergeDataAndStartSyncing(
+      const std::vector<AutofillProfile*>& profiles_from_web_db,
+      const syncer::SyncDataList& data_list,
+      const MockAutofillProfileSyncableService::DataBundle& expected_bundle,
+      const syncer::SyncChangeList& expected_change_list) {
+    EXPECT_CALL(autofill_syncable_service_, LoadAutofillData(_))
+        .Times(1)
+        .WillOnce(DoAll(CopyData(&profiles_from_web_db), Return(true)));
+    EXPECT_CALL(autofill_syncable_service_,
+                SaveChangesToWebData(DataBundleCheck(expected_bundle)))
+        .Times(1)
+        .WillOnce(Return(true));
+    ON_CALL(*sync_processor_, ProcessSyncChanges(_, _))
+        .WillByDefault(Return(syncer::SyncError()));
+    EXPECT_CALL(*sync_processor_,
+                ProcessSyncChanges(_, CheckSyncChanges(expected_change_list)))
+        .Times(1)
+        .WillOnce(Return(syncer::SyncError()));
+
+    // Takes ownership of sync_processor_.
+    autofill_syncable_service_.MergeDataAndStartSyncing(
+        syncer::AUTOFILL_PROFILE, data_list,
+        sync_processor_.PassAs<syncer::SyncChangeProcessor>(),
+        scoped_ptr<syncer::SyncErrorFactory>(
+            new syncer::SyncErrorFactoryMock()));
+  }
+
  protected:
   base::MessageLoop message_loop_;
   content::TestBrowserThread ui_thread_;
@@ -120,7 +167,7 @@
 };
 
 TEST_F(AutofillProfileSyncableServiceTest, MergeDataAndStartSyncing) {
-  std::vector<AutofillProfile *> profiles_from_web_db;
+  std::vector<AutofillProfile*> profiles_from_web_db;
   std::string guid_present1 = kGuid1;
   std::string guid_present2 = kGuid2;
   std::string guid_synced1 = kGuid3;
@@ -150,7 +197,7 @@
   AutofillProfile profile2(guid_synced2, origin_synced2);
   profile2.SetRawInfo(autofill::NAME_FIRST, UTF8ToUTF16("Harry"));
   data_list.push_back(autofill_syncable_service_.CreateData(profile2));
-  // This one will have the name updated.
+  // This one will have the name and origin updated.
   AutofillProfile profile3(guid_present2, origin_synced2);
   profile3.SetRawInfo(autofill::NAME_FIRST, UTF8ToUTF16("Tom Doe"));
   data_list.push_back(autofill_syncable_service_.CreateData(profile3));
@@ -159,14 +206,172 @@
   expected_change_list.push_back(
       syncer::SyncChange(FROM_HERE,
                          syncer::SyncChange::ACTION_ADD,
-                         AutofillProfileSyncableService::CreateData(
-                             (*profiles_from_web_db.front()))));
+                         MockAutofillProfileSyncableService::CreateData(
+                             *profiles_from_web_db.front())));
 
-  AutofillProfileSyncableService::DataBundle expected_bundle;
+  MockAutofillProfileSyncableService::DataBundle expected_bundle;
   expected_bundle.profiles_to_add.push_back(&profile1);
   expected_bundle.profiles_to_add.push_back(&profile2);
   expected_bundle.profiles_to_update.push_back(&profile3);
 
+  MergeDataAndStartSyncing(
+      profiles_from_web_db, data_list, expected_bundle, expected_change_list);
+  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
+}
+
+TEST_F(AutofillProfileSyncableServiceTest, MergeIdenticalProfiles) {
+  std::vector<AutofillProfile*> profiles_from_web_db;
+  std::string guid_present1 = kGuid1;
+  std::string guid_present2 = kGuid2;
+  std::string guid_synced1 = kGuid3;
+  std::string guid_synced2 = kGuid4;
+  std::string origin_present1 = kHttpOrigin;
+  std::string origin_present2 = kSettingsOrigin;
+  std::string origin_synced1 = kHttpsOrigin;
+  std::string origin_synced2 = kHttpsOrigin;
+
+  profiles_from_web_db.push_back(
+      new AutofillProfile(guid_present1, origin_present1));
+  profiles_from_web_db.back()->SetRawInfo(
+      autofill::NAME_FIRST, UTF8ToUTF16("John"));
+  profiles_from_web_db.back()->SetRawInfo(
+      autofill::ADDRESS_HOME_LINE1, UTF8ToUTF16("1 1st st"));
+  profiles_from_web_db.push_back(
+      new AutofillProfile(guid_present2, origin_present2));
+  profiles_from_web_db.back()->SetRawInfo(
+      autofill::NAME_FIRST, UTF8ToUTF16("Tom"));
+  profiles_from_web_db.back()->SetRawInfo(
+      autofill::ADDRESS_HOME_LINE1, UTF8ToUTF16("2 2nd st"));
+
+  // The synced profiles are identical to the local ones, except that the guids
+  // are different.
+  syncer::SyncDataList data_list;
+  AutofillProfile profile1(guid_synced1, origin_synced1);
+  profile1.SetRawInfo(autofill::NAME_FIRST, UTF8ToUTF16("John"));
+  profile1.SetRawInfo(autofill::ADDRESS_HOME_LINE1, UTF8ToUTF16("1 1st st"));
+  data_list.push_back(autofill_syncable_service_.CreateData(profile1));
+  AutofillProfile profile2(guid_synced2, origin_synced2);
+  profile2.SetRawInfo(autofill::NAME_FIRST, UTF8ToUTF16("Tom"));
+  profile2.SetRawInfo(autofill::ADDRESS_HOME_LINE1, UTF8ToUTF16("2 2nd st"));
+  data_list.push_back(autofill_syncable_service_.CreateData(profile2));
+
+  AutofillProfile expected_profile(profile2);
+  expected_profile.set_origin(kSettingsOrigin);
+  syncer::SyncChangeList expected_change_list;
+  expected_change_list.push_back(
+      syncer::SyncChange(FROM_HERE,
+                         syncer::SyncChange::ACTION_UPDATE,
+                         MockAutofillProfileSyncableService::CreateData(
+                             expected_profile)));
+
+  MockAutofillProfileSyncableService::DataBundle expected_bundle;
+  expected_bundle.profiles_to_delete.push_back(guid_present1);
+  expected_bundle.profiles_to_delete.push_back(guid_present2);
+  expected_bundle.profiles_to_add.push_back(&profile1);
+  expected_bundle.profiles_to_add.push_back(&expected_profile);
+
+  MergeDataAndStartSyncing(
+      profiles_from_web_db, data_list, expected_bundle, expected_change_list);
+  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
+}
+
+TEST_F(AutofillProfileSyncableServiceTest, MergeSimilarProfiles) {
+  std::vector<AutofillProfile*> profiles_from_web_db;
+  std::string guid_present1 = kGuid1;
+  std::string guid_present2 = kGuid2;
+  std::string guid_synced1 = kGuid3;
+  std::string guid_synced2 = kGuid4;
+  std::string origin_present1 = kHttpOrigin;
+  std::string origin_present2 = kSettingsOrigin;
+  std::string origin_synced1 = kHttpsOrigin;
+  std::string origin_synced2 = kHttpsOrigin;
+
+  profiles_from_web_db.push_back(
+      new AutofillProfile(guid_present1, origin_present1));
+  profiles_from_web_db.back()->SetRawInfo(
+      autofill::NAME_FIRST, UTF8ToUTF16("John"));
+  profiles_from_web_db.back()->SetRawInfo(
+      autofill::ADDRESS_HOME_LINE1, UTF8ToUTF16("1 1st st"));
+  profiles_from_web_db.push_back(
+      new AutofillProfile(guid_present2, origin_present2));
+  profiles_from_web_db.back()->SetRawInfo(
+      autofill::NAME_FIRST, UTF8ToUTF16("Tom"));
+  profiles_from_web_db.back()->SetRawInfo(
+      autofill::ADDRESS_HOME_LINE1, UTF8ToUTF16("2 2nd st"));
+
+  // The synced profiles are identical to the local ones, except that the guids
+  // are different.
+  syncer::SyncDataList data_list;
+  AutofillProfile profile1(guid_synced1, origin_synced1);
+  profile1.SetRawInfo(autofill::NAME_FIRST, UTF8ToUTF16("John"));
+  profile1.SetRawInfo(autofill::ADDRESS_HOME_LINE1, UTF8ToUTF16("1 1st st"));
+  profile1.SetRawInfo(autofill::COMPANY_NAME, UTF8ToUTF16("Frobbers, Inc."));
+  data_list.push_back(autofill_syncable_service_.CreateData(profile1));
+  AutofillProfile profile2(guid_synced2, origin_synced2);
+  profile2.SetRawInfo(autofill::NAME_FIRST, UTF8ToUTF16("Tom"));
+  profile2.SetRawInfo(autofill::ADDRESS_HOME_LINE1, UTF8ToUTF16("2 2nd st"));
+  profile2.SetRawInfo(autofill::COMPANY_NAME, UTF8ToUTF16("Fizzbang, LLC."));
+  data_list.push_back(autofill_syncable_service_.CreateData(profile2));
+
+  // The first profile should have its origin updated.
+  // The second profile should remain as-is, because an unverified profile
+  // should never overwrite a verified one.
+  AutofillProfile expected_profile(profile1);
+  expected_profile.set_origin(origin_present1);
+  syncer::SyncChangeList expected_change_list;
+  expected_change_list.push_back(
+      syncer::SyncChange(FROM_HERE,
+                         syncer::SyncChange::ACTION_ADD,
+                         MockAutofillProfileSyncableService::CreateData(
+                             *profiles_from_web_db.back())));
+  expected_change_list.push_back(
+      syncer::SyncChange(FROM_HERE,
+                         syncer::SyncChange::ACTION_UPDATE,
+                         MockAutofillProfileSyncableService::CreateData(
+                             expected_profile)));
+
+  MockAutofillProfileSyncableService::DataBundle expected_bundle;
+  expected_bundle.profiles_to_delete.push_back(guid_present1);
+  expected_bundle.profiles_to_add.push_back(&expected_profile);
+  expected_bundle.profiles_to_add.push_back(&profile2);
+
+  MergeDataAndStartSyncing(
+      profiles_from_web_db, data_list, expected_bundle, expected_change_list);
+  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
+}
+
+// Ensure that no Sync events are generated to fill in missing origins from Sync
+// with explicitly present empty ones.  This ensures that the migration to add
+// origins to profiles does not generate lots of needless Sync updates.
+TEST_F(AutofillProfileSyncableServiceTest, MergeDataEmptyOrigins) {
+  std::vector<AutofillProfile*> profiles_from_web_db;
+
+  // Create a profile with an empty origin.
+  AutofillProfile profile(kGuid1, std::string());
+  profile.SetRawInfo(autofill::NAME_FIRST, UTF8ToUTF16("John"));
+  profile.SetRawInfo(autofill::ADDRESS_HOME_LINE1, UTF8ToUTF16("1 1st st"));
+
+  profiles_from_web_db.push_back(new AutofillProfile(profile));
+
+  // Create a Sync profile identical to |profile|, except with no origin set.
+  sync_pb::EntitySpecifics specifics;
+  sync_pb::AutofillProfileSpecifics* autofill_specifics =
+      specifics.mutable_autofill_profile();
+  autofill_specifics->set_guid(profile.guid());
+  autofill_specifics->add_name_first("John");
+  autofill_specifics->add_name_middle(std::string());
+  autofill_specifics->add_name_last(std::string());
+  autofill_specifics->add_email_address(std::string());
+  autofill_specifics->add_phone_home_whole_number(std::string());
+  autofill_specifics->set_address_home_line1("1 1st st");
+  EXPECT_FALSE(autofill_specifics->has_origin());
+
+  syncer::SyncDataList data_list;
+  data_list.push_back(
+      syncer::SyncData::CreateLocalData(
+          profile.guid(), profile.guid(), specifics));
+
+  MockAutofillProfileSyncableService::DataBundle expected_bundle;
   EXPECT_CALL(autofill_syncable_service_, LoadAutofillData(_))
       .Times(1)
       .WillOnce(DoAll(CopyData(&profiles_from_web_db), Return(true)));
@@ -174,23 +379,19 @@
               SaveChangesToWebData(DataBundleCheck(expected_bundle)))
       .Times(1)
       .WillOnce(Return(true));
-  ON_CALL(*sync_processor_, ProcessSyncChanges(_, _))
-      .WillByDefault(Return(syncer::SyncError()));
-  EXPECT_CALL(*sync_processor_,
-              ProcessSyncChanges(_, CheckSyncChanges(expected_change_list)))
-      .Times(1)
-      .WillOnce(Return(syncer::SyncError()));
+  EXPECT_CALL(*sync_processor_, ProcessSyncChanges(_, _)).Times(0);
 
   // Takes ownership of sync_processor_.
   autofill_syncable_service_.MergeDataAndStartSyncing(
       syncer::AUTOFILL_PROFILE, data_list,
       sync_processor_.PassAs<syncer::SyncChangeProcessor>(),
       scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
+
   autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
 }
 
 TEST_F(AutofillProfileSyncableServiceTest, GetAllSyncData) {
-  std::vector<AutofillProfile *> profiles_from_web_db;
+  std::vector<AutofillProfile*> profiles_from_web_db;
   std::string guid_present1 = kGuid1;
   std::string guid_present2 = kGuid2;
 
@@ -203,27 +404,22 @@
   profiles_from_web_db.back()->SetRawInfo(
       autofill::NAME_FIRST, UTF8ToUTF16("Jane"));
 
-  EXPECT_CALL(autofill_syncable_service_, LoadAutofillData(_))
-      .Times(1)
-      .WillOnce(DoAll(CopyData(&profiles_from_web_db), Return(true)));
-  EXPECT_CALL(autofill_syncable_service_, SaveChangesToWebData(_))
-      .Times(1)
-      .WillOnce(Return(true));
-  ON_CALL(*sync_processor_, ProcessSyncChanges(_, _))
-      .WillByDefault(Return(syncer::SyncError()));
-  EXPECT_CALL(*sync_processor_,
-              ProcessSyncChanges(
-                  _,
-                  Property(&syncer::SyncChangeList::size, Eq(2U))))
-      .Times(1)
-      .WillOnce(Return(syncer::SyncError()));
+  syncer::SyncChangeList expected_change_list;
+  expected_change_list.push_back(
+      syncer::SyncChange(FROM_HERE,
+                         syncer::SyncChange::ACTION_ADD,
+                         MockAutofillProfileSyncableService::CreateData(
+                             *profiles_from_web_db.front())));
+  expected_change_list.push_back(
+      syncer::SyncChange(FROM_HERE,
+                         syncer::SyncChange::ACTION_ADD,
+                         MockAutofillProfileSyncableService::CreateData(
+                             *profiles_from_web_db.back())));
 
+  MockAutofillProfileSyncableService::DataBundle expected_bundle;
   syncer::SyncDataList data_list;
-  // Takes ownership of sync_processor_.
-  autofill_syncable_service_.MergeDataAndStartSyncing(
-      syncer::AUTOFILL_PROFILE, data_list,
-      sync_processor_.PassAs<syncer::SyncChangeProcessor>(),
-      scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
+  MergeDataAndStartSyncing(
+      profiles_from_web_db, data_list, expected_bundle, expected_change_list);
 
   syncer::SyncDataList data =
       autofill_syncable_service_.GetAllSyncData(syncer::AUTOFILL_PROFILE);
@@ -231,12 +427,10 @@
   ASSERT_EQ(2U, data.size());
   EXPECT_EQ(guid_present1, data[0].GetSpecifics().autofill_profile().guid());
   EXPECT_EQ(guid_present2, data[1].GetSpecifics().autofill_profile().guid());
-  // TODO(isherman): Verify that the origins match once they are saved and read
-  // from the database and included in the Sync protocol buffers.
-  // http://crbug.com/170401
-  // EXPECT_EQ(kHttpOrigin, data[0].GetSpecifics().autofill_profile().origin());
-  // EXPECT_EQ(kHttpsOrigin,
-  //           data[1].GetSpecifics().autofill_profile().origin());
+  EXPECT_EQ(kHttpOrigin, data[0].GetSpecifics().autofill_profile().origin());
+  EXPECT_EQ(kHttpsOrigin, data[1].GetSpecifics().autofill_profile().origin());
+
+  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
 }
 
 TEST_F(AutofillProfileSyncableServiceTest, ProcessSyncChanges) {
@@ -248,17 +442,18 @@
   AutofillProfile profile(guid_synced, kHttpOrigin);
   profile.SetRawInfo(autofill::NAME_FIRST, UTF8ToUTF16("Jane"));
   change_list.push_back(
-      syncer::SyncChange(FROM_HERE,
-                         syncer::SyncChange::ACTION_ADD,
-                         AutofillProfileSyncableService::CreateData(profile)));
+      syncer::SyncChange(
+          FROM_HERE,
+          syncer::SyncChange::ACTION_ADD,
+          MockAutofillProfileSyncableService::CreateData(profile)));
   AutofillProfile empty_profile(guid_present, kHttpsOrigin);
   change_list.push_back(
       syncer::SyncChange(
           FROM_HERE,
           syncer::SyncChange::ACTION_DELETE,
-          AutofillProfileSyncableService::CreateData(empty_profile)));
+          MockAutofillProfileSyncableService::CreateData(empty_profile)));
 
-  AutofillProfileSyncableService::DataBundle expected_bundle;
+  MockAutofillProfileSyncableService::DataBundle expected_bundle;
   expected_bundle.profiles_to_delete.push_back(guid_present);
   expected_bundle.profiles_to_add.push_back(&profile);
 
@@ -274,20 +469,43 @@
   EXPECT_FALSE(error.IsSet());
 }
 
-TEST_F(AutofillProfileSyncableServiceTest, ActOnChange) {
-  AutofillProfile profile(kGuid1, std::string());
-  profile.SetRawInfo(autofill::NAME_FIRST, UTF8ToUTF16("Jane"));
-  AutofillProfileChange change1(AutofillProfileChange::ADD, kGuid1, &profile);
-  AutofillProfileChange change2(AutofillProfileChange::REMOVE, kGuid2, NULL);
-  ON_CALL(*sync_processor_, ProcessSyncChanges(_, _))
-      .WillByDefault(
-          Return(syncer::SyncError(FROM_HERE, std::string("an error"),
-                                   syncer::AUTOFILL_PROFILE)));
-  EXPECT_CALL(*sync_processor_, ProcessSyncChanges(_, _)).Times(2);
+TEST_F(AutofillProfileSyncableServiceTest, AutofillProfileAdded) {
+  // Will be owned by the syncable service.  Keep a reference available here for
+  // verifying test expectations.
+  TestSyncChangeProcessor* sync_change_processor = new TestSyncChangeProcessor;
+  autofill_syncable_service_.set_sync_processor(sync_change_processor);
 
-  autofill_syncable_service_.set_sync_processor(sync_processor_.release());
-  autofill_syncable_service_.ActOnChange(change1);
-  autofill_syncable_service_.ActOnChange(change2);
+  AutofillProfile profile(kGuid1, kHttpsOrigin);
+  profile.SetRawInfo(autofill::NAME_FIRST, UTF8ToUTF16("Jane"));
+  AutofillProfileChange change(AutofillProfileChange::ADD, kGuid1, &profile);
+  autofill_syncable_service_.AutofillProfileChanged(change);
+
+  ASSERT_EQ(1U, sync_change_processor->changes().size());
+  syncer::SyncChange result = sync_change_processor->changes()[0];
+  EXPECT_EQ(syncer::SyncChange::ACTION_ADD, result.change_type());
+
+  sync_pb::AutofillProfileSpecifics specifics =
+      result.sync_data().GetSpecifics().autofill_profile();
+  EXPECT_EQ(kGuid1, specifics.guid());
+  EXPECT_EQ(kHttpsOrigin, specifics.origin());
+  EXPECT_THAT(specifics.name_first(), testing::ElementsAre("Jane"));
+}
+
+TEST_F(AutofillProfileSyncableServiceTest, AutofillProfileDeleted) {
+  // Will be owned by the syncable service.  Keep a reference available here for
+  // verifying test expectations.
+  TestSyncChangeProcessor* sync_change_processor = new TestSyncChangeProcessor;
+  autofill_syncable_service_.set_sync_processor(sync_change_processor);
+
+  AutofillProfileChange change(AutofillProfileChange::REMOVE, kGuid2, NULL);
+  autofill_syncable_service_.AutofillProfileChanged(change);
+
+  ASSERT_EQ(1U, sync_change_processor->changes().size());
+  syncer::SyncChange result = sync_change_processor->changes()[0];
+  EXPECT_EQ(syncer::SyncChange::ACTION_DELETE, result.change_type());
+  sync_pb::AutofillProfileSpecifics specifics =
+      result.sync_data().GetSpecifics().autofill_profile();
+  EXPECT_EQ(kGuid2, specifics.guid());
 }
 
 TEST_F(AutofillProfileSyncableServiceTest, UpdateField) {
@@ -350,7 +568,7 @@
   values.push_back(UTF8ToUTF16("2@1.com"));
   profile1.SetRawMultiInfo(autofill::EMAIL_ADDRESS, values);
 
-  AutofillProfile profile2(kGuid2, std::string());
+  AutofillProfile profile2(kGuid2, kHttpsOrigin);
   profile2.SetRawInfo(
       autofill::ADDRESS_HOME_LINE1, UTF8ToUTF16("111 First St."));
 
@@ -398,6 +616,8 @@
   ASSERT_EQ(values.size(), 1U);
   EXPECT_EQ(values[0], UTF8ToUTF16("650234567"));
 
+  EXPECT_EQ(profile2.origin(), profile1.origin());
+
   AutofillProfile profile3(kGuid3, kHttpOrigin);
   profile3.SetRawInfo(
       autofill::ADDRESS_HOME_LINE1, UTF8ToUTF16("111 First St."));
diff --git a/chrome/browser/webdata/keyword_table.cc b/chrome/browser/webdata/keyword_table.cc
index 3560bb3..640985e 100644
--- a/chrome/browser/webdata/keyword_table.cc
+++ b/chrome/browser/webdata/keyword_table.cc
@@ -20,9 +20,9 @@
 #include "chrome/browser/search_engines/template_url.h"
 #include "chrome/browser/search_engines/template_url_service.h"
 #include "components/webdata/common/web_database.h"
-#include "googleurl/src/gurl.h"
 #include "sql/statement.h"
 #include "sql/transaction.h"
+#include "url/gurl.h"
 
 using base::Time;
 
diff --git a/chrome/browser/webdata/keyword_table_unittest.cc b/chrome/browser/webdata/keyword_table_unittest.cc
index 48fe297..7f15aa1 100644
--- a/chrome/browser/webdata/keyword_table_unittest.cc
+++ b/chrome/browser/webdata/keyword_table_unittest.cc
@@ -10,7 +10,7 @@
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/search_engines/template_url.h"
 #include "chrome/browser/webdata/keyword_table.h"
 #include "components/webdata/common/web_database.h"
diff --git a/chrome/browser/webdata/logins_table_win.cc b/chrome/browser/webdata/logins_table_win.cc
index 0e3ae5a..2a959e9 100644
--- a/chrome/browser/webdata/logins_table_win.cc
+++ b/chrome/browser/webdata/logins_table_win.cc
@@ -6,7 +6,7 @@
 
 #include "base/logging.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "components/webdata/encryptor/ie7_password.h"
 #include "sql/statement.h"
 
diff --git a/chrome/browser/webdata/token_service_table_unittest.cc b/chrome/browser/webdata/token_service_table_unittest.cc
index 20c1827..d291a5a 100644
--- a/chrome/browser/webdata/token_service_table_unittest.cc
+++ b/chrome/browser/webdata/token_service_table_unittest.cc
@@ -5,7 +5,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/path_service.h"
 #include "base/strings/string_number_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/webdata/token_service_table.h"
 #include "components/webdata/common/web_database.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/webdata/web_apps_table.cc b/chrome/browser/webdata/web_apps_table.cc
index ac1e305..16d498b 100644
--- a/chrome/browser/webdata/web_apps_table.cc
+++ b/chrome/browser/webdata/web_apps_table.cc
@@ -7,10 +7,10 @@
 #include "base/logging.h"
 #include "chrome/browser/history/history_database.h"
 #include "components/webdata/common/web_database.h"
-#include "googleurl/src/gurl.h"
 #include "sql/statement.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/gfx/codec/png_codec.h"
+#include "url/gurl.h"
 
 namespace {
 
diff --git a/chrome/browser/webdata/web_apps_table_unittest.cc b/chrome/browser/webdata/web_apps_table_unittest.cc
index 86fbade..3ca084a 100644
--- a/chrome/browser/webdata/web_apps_table_unittest.cc
+++ b/chrome/browser/webdata/web_apps_table_unittest.cc
@@ -5,12 +5,12 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/path_service.h"
 #include "base/strings/string_number_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/webdata/web_apps_table.h"
 #include "components/webdata/common/web_database.h"
-#include "googleurl/src/gurl.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "url/gurl.h"
 
 using base::Time;
 
diff --git a/chrome/browser/webdata/web_data_service_factory.cc b/chrome/browser/webdata/web_data_service_factory.cc
index e63220b..1838713 100644
--- a/chrome/browser/webdata/web_data_service_factory.cc
+++ b/chrome/browser/webdata/web_data_service_factory.cc
@@ -19,9 +19,9 @@
 #include "chrome/browser/webdata/web_apps_table.h"
 #include "chrome/browser/webdata/web_data_service.h"
 #include "chrome/browser/webdata/web_intents_table.h"
-#include "components/autofill/browser/autofill_country.h"
-#include "components/autofill/browser/webdata/autofill_table.h"
-#include "components/autofill/browser/webdata/autofill_webdata_service.h"
+#include "components/autofill/core/browser/autofill_country.h"
+#include "components/autofill/core/browser/webdata/autofill_table.h"
+#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
 #include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
 #include "components/webdata/common/webdata_constants.h"
 #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/webdata/web_intents_table.cc b/chrome/browser/webdata/web_intents_table.cc
index cdd9472..bb57097 100644
--- a/chrome/browser/webdata/web_intents_table.cc
+++ b/chrome/browser/webdata/web_intents_table.cc
@@ -11,10 +11,10 @@
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/webdata/common/web_database.h"
-#include "googleurl/src/gurl.h"
 #include "net/base/mime_util.h"
 #include "sql/statement.h"
 #include "third_party/sqlite/sqlite3.h"
+#include "url/gurl.h"
 
 namespace {
 
diff --git a/chrome/browser/webview/webview_guest.cc b/chrome/browser/webview/webview_guest.cc
deleted file mode 100644
index 958b0e2..0000000
--- a/chrome/browser/webview/webview_guest.cc
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/webview/webview_guest.h"
-
-#include "base/lazy_instance.h"
-#include "chrome/browser/extensions/api/web_request/web_request_api.h"
-#include "chrome/browser/extensions/extension_renderer_state.h"
-#include "chrome/browser/extensions/script_executor.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/site_instance.h"
-#include "content/public/browser/web_contents.h"
-
-using content::WebContents;
-
-namespace chrome {
-
-namespace {
-
-typedef std::map<std::pair<int, int>, WebViewGuest*> WebViewGuestMap;
-static base::LazyInstance<WebViewGuestMap> webview_guest_map =
-    LAZY_INSTANCE_INITIALIZER;
-
-void RemoveWebViewEventListenersOnIOThread(
-    void* profile,
-    const std::string& extension_id,
-    int embedder_process_id,
-    int guest_instance_id) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
-  ExtensionWebRequestEventRouter::GetInstance()->RemoveWebViewEventListeners(
-      profile, extension_id, embedder_process_id, guest_instance_id);
-}
-
-}  // namespace
-
-WebViewGuest::WebViewGuest(WebContents* guest_web_contents,
-                           WebContents* embedder_web_contents,
-                           const std::string& extension_id,
-                           int webview_instance_id)
-    : WebContentsObserver(guest_web_contents),
-      embedder_web_contents_(embedder_web_contents),
-      extension_id_(extension_id),
-      embedder_render_process_id_(
-          embedder_web_contents->GetRenderProcessHost()->GetID()),
-      profile_(guest_web_contents->GetBrowserContext()),
-      guest_instance_id_(guest_web_contents->GetEmbeddedInstanceID()),
-      webview_instance_id_(webview_instance_id),
-      script_executor_(new extensions::ScriptExecutor(guest_web_contents,
-                                                      &script_observers_)) {
-  std::pair<int, int> key(embedder_render_process_id_, guest_instance_id_);
-  webview_guest_map.Get().insert(std::make_pair(key, this));
-
-  AddWebViewToExtensionRendererState();
-}
-
-// static
-WebViewGuest* WebViewGuest::From(int embedder_process_id,
-                                 int guest_instance_id) {
-  WebViewGuestMap* guest_map = webview_guest_map.Pointer();
-  WebViewGuestMap::iterator it = guest_map->find(
-      std::make_pair(embedder_process_id, guest_instance_id));
-  return it == guest_map->end() ? NULL : it->second;
-}
-
-WebViewGuest::~WebViewGuest() {
-  std::pair<int, int> key(embedder_render_process_id_, guest_instance_id_);
-  webview_guest_map.Get().erase(key);
-}
-
-void WebViewGuest::WebContentsDestroyed(WebContents* web_contents) {
-  RemoveWebViewFromExtensionRendererState(web_contents);
-  content::BrowserThread::PostTask(
-      content::BrowserThread::IO,
-      FROM_HERE,
-      base::Bind(
-          &RemoveWebViewEventListenersOnIOThread,
-          profile_, extension_id_,
-          embedder_render_process_id_,
-          webview_instance_id_));
-  delete this;
-}
-
-void WebViewGuest::AddWebViewToExtensionRendererState() {
-  ExtensionRendererState::WebViewInfo webview_info;
-  webview_info.embedder_process_id =
-      embedder_web_contents()->GetRenderProcessHost()->GetID();
-  webview_info.embedder_routing_id = embedder_web_contents()->GetRoutingID();
-  webview_info.guest_instance_id = guest_instance_id_;
-  webview_info.instance_id = webview_instance_id_;
-
-  content::BrowserThread::PostTask(
-      content::BrowserThread::IO, FROM_HERE,
-      base::Bind(
-          &ExtensionRendererState::AddWebView,
-          base::Unretained(ExtensionRendererState::GetInstance()),
-          web_contents()->GetRenderProcessHost()->GetID(),
-          web_contents()->GetRoutingID(),
-          webview_info));
-}
-
-// static
-void WebViewGuest::RemoveWebViewFromExtensionRendererState(
-    WebContents* web_contents) {
-  content::BrowserThread::PostTask(
-      content::BrowserThread::IO, FROM_HERE,
-      base::Bind(
-          &ExtensionRendererState::RemoveWebView,
-          base::Unretained(ExtensionRendererState::GetInstance()),
-          web_contents->GetRenderProcessHost()->GetID(),
-          web_contents->GetRoutingID()));
-}
-
-}  // namespace chrome
diff --git a/chrome/browser/webview/webview_guest.h b/chrome/browser/webview/webview_guest.h
deleted file mode 100644
index ff68d60..0000000
--- a/chrome/browser/webview/webview_guest.h
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_WEBVIEW_WEBVIEW_GUEST_H_
-#define CHROME_BROWSER_WEBVIEW_WEBVIEW_GUEST_H_
-
-#include "base/observer_list.h"
-#include "chrome/browser/extensions/tab_helper.h"
-#include "content/public/browser/web_contents_observer.h"
-
-namespace extensions {
-class ScriptExecutor;
-}  // namespace extensions
-
-namespace chrome {
-
-// A WebViewGuest is a WebContentsObserver on the guest WebContents of a
-// <webview> tag. It provides the browser-side implementation of the <webview>
-// API and manages the lifetime of <webview> extension events. WebViewGuest is
-// created on attachment. That is, when a guest WebContents is associated with
-// a particular embedder WebContents. This happens on either initial navigation
-// or through the use of the New Window API, when a new window is attached to
-// a particular <webview>.
-class WebViewGuest : public content::WebContentsObserver {
- public:
-  WebViewGuest(content::WebContents* guest_web_contents,
-               content::WebContents* embedder_web_contents,
-               const std::string& extension_id,
-               int webview_instance_id);
-
-  static WebViewGuest* From(int embedder_process_id, int instance_id);
-
-  content::WebContents* embedder_web_contents() const {
-    return embedder_web_contents_;
-  }
-
-  content::WebContents* web_contents() const {
-    return WebContentsObserver::web_contents();
-  }
-
-  int instance_id() const { return webview_instance_id_; }
-
-  extensions::ScriptExecutor* script_executor() {
-    return script_executor_.get();
-  }
-
- private:
-  virtual ~WebViewGuest();
-  virtual void WebContentsDestroyed(
-      content::WebContents* web_contents) OVERRIDE;
-
-  void AddWebViewToExtensionRendererState();
-  static void RemoveWebViewFromExtensionRendererState(
-      content::WebContents* web_contents);
-
-  content::WebContents* embedder_web_contents_;
-  const std::string extension_id_;
-  const int embedder_render_process_id_;
-  // Profile and instance ID are cached here because |web_contents()| is
-  // null on destruction.
-  void* profile_;
-  // |guest_instance_id_| is a profile-wide unique identifier for a guest
-  // WebContents.
-  const int guest_instance_id_;
-  // |webview_instance_id_| is an identifier that's unique within a particular
-  // embedder RenderView for a particular <webview> instance.
-  const int webview_instance_id_;
-
-  ObserverList<extensions::TabHelper::ScriptExecutionObserver>
-      script_observers_;
-  scoped_ptr<extensions::ScriptExecutor> script_executor_;
-
-
-  DISALLOW_COPY_AND_ASSIGN(WebViewGuest);
-};
-
-}  // namespace chrome
-
-#endif  // CHROME_BROWSER_WEBVIEW_WEBVIEW_GUEST_H_
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index db90ea1..8b13695 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -221,6 +221,10 @@
             '..',
           ],
           'sources': [
+            'browser/devtools/adb/android_usb_device.cc',
+            'browser/devtools/adb/android_usb_device.h',
+            'browser/devtools/adb/android_usb_socket.cc',
+            'browser/devtools/adb/android_usb_socket.h',
             'browser/devtools/adb_client_socket.cc',
             'browser/devtools/adb_client_socket.h',
             'browser/devtools/browser_list_tabcontents_provider.cc',
@@ -285,10 +289,13 @@
             '../base/base.gyp:base',
             '../content/content.gyp:content_utility',
             '../skia/skia.gyp:skia',
+            '../third_party/libxml/libxml.gyp:libxml',
           ],
           'sources': [
             'utility/chrome_content_utility_client.cc',
             'utility/chrome_content_utility_client.h',
+            'utility/itunes_pref_parser_win.cc',
+            'utility/itunes_pref_parser_win.h',
             'utility/profile_import_handler.cc',
             'utility/profile_import_handler.h',
           ],
@@ -301,6 +308,18 @@
                 '../build/linux/system.gyp:gtk',
               ],
             }],
+            ['OS=="win" or OS=="mac"', {
+              'sources': [
+                'utility/itunes_library_parser.cc',
+                'utility/itunes_library_parser.h',
+                'utility/media_galleries/picasa_album_table_reader.cc',
+                'utility/media_galleries/picasa_album_table_reader.h',
+                'utility/media_galleries/picasa_albums_indexer.cc',
+                'utility/media_galleries/picasa_albums_indexer.h',
+                'utility/media_galleries/pmp_column_reader.cc',
+                'utility/media_galleries/pmp_column_reader.h',
+              ],
+            }],
             ['OS=="android"', {
               'sources!': [
                 'utility/profile_import_handler.cc',
@@ -365,8 +384,6 @@
             'service/cloud_print/printer_job_handler.h',
             'service/cloud_print/printer_job_queue_handler.cc',
             'service/cloud_print/printer_job_queue_handler.h',
-            'service/gaia/service_gaia_authenticator.cc',
-            'service/gaia/service_gaia_authenticator.h',
             'service/net/service_url_request_context.cc',
             'service/net/service_url_request_context.h',
           ],
diff --git a/chrome/chrome_android.gypi b/chrome/chrome_android.gypi
index 078c23b..8237fac 100644
--- a/chrome/chrome_android.gypi
+++ b/chrome/chrome_android.gypi
@@ -68,7 +68,6 @@
         'native_lib_target': 'libchromiumtestshell',
         'additional_input_paths': [
           '<@(chrome_android_pak_output_resources)',
-          '<(chrome_android_pak_output_folder)/devtools_resources.pak',
         ],
       },
       'includes': [ '../build/java_apk.gypi', ],
@@ -155,7 +154,6 @@
           'destination': '<(chrome_android_pak_output_folder)',
           'files': [
             '<@(chrome_android_pak_input_resources)',
-            '<(SHARED_INTERMEDIATE_DIR)/webkit/devtools_resources.pak',
           ],
         }
       ],
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index ccee18c..eccd7f7 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -96,12 +96,15 @@
         'browser/android/crash_dump_manager.h',
         'browser/android/dev_tools_server.cc',
         'browser/android/dev_tools_server.h',
+        'browser/android/favicon_helper.cc',
+        'browser/android/favicon_helper.h',
         'browser/android/google_location_settings_helper.h',
-        'browser/android/infobar_stubs.cc',
         'browser/android/intent_helper.cc',
         'browser/android/intent_helper.h',
         'browser/android/intercept_download_resource_throttle.cc',
         'browser/android/intercept_download_resource_throttle.h',
+        'browser/android/most_visited_sites.cc',
+        'browser/android/most_visited_sites.h',
         'browser/android/provider/blocking_ui_thread_async_request.cc',
         'browser/android/provider/blocking_ui_thread_async_request.h',
         'browser/android/provider/bookmark_model_observer_task.cc',
@@ -233,12 +236,10 @@
         'browser/bookmarks/base_bookmark_model_observer.h',
         'browser/bookmarks/bookmark_codec.cc',
         'browser/bookmarks/bookmark_codec.h',
-        'browser/bookmarks/bookmark_editor.cc',
-        'browser/bookmarks/bookmark_editor.h',
         'browser/bookmarks/bookmark_expanded_state_tracker.cc',
         'browser/bookmarks/bookmark_expanded_state_tracker.h',
-        'browser/bookmarks/bookmark_html_reader.cc',
-        'browser/bookmarks/bookmark_html_reader.h',
+        'browser/importer/bookmark_html_reader.cc',
+        'browser/importer/bookmark_html_reader.h',
         'browser/bookmarks/bookmark_html_writer.cc',
         'browser/bookmarks/bookmark_html_writer.h',
         'browser/bookmarks/bookmark_index.cc',
@@ -264,8 +265,6 @@
         'browser/bookmarks/bookmark_title_match.h',
         'browser/bookmarks/bookmark_utils.cc',
         'browser/bookmarks/bookmark_utils.h',
-        'browser/bookmarks/imported_bookmark_entry.cc',
-        'browser/bookmarks/imported_bookmark_entry.h',
         'browser/browser_about_handler.cc',
         'browser/browser_about_handler.h',
         'browser/browser_process.cc',
@@ -382,6 +381,12 @@
         'browser/command_updater_delegate.h',
         'browser/common/cancelable_request.cc',
         'browser/common/cancelable_request.h',
+        'browser/component_updater/component_patcher.cc',
+        'browser/component_updater/component_patcher.h',
+        'browser/component_updater/component_patcher_operation.cc',
+        'browser/component_updater/component_patcher_operation.h',
+        'browser/component_updater/component_patcher_win.cc',
+        'browser/component_updater/component_patcher_win.h',
         'browser/component_updater/component_updater_configurator.cc',
         'browser/component_updater/component_updater_configurator.h',
         'browser/component_updater/component_unpacker.cc',
@@ -394,6 +399,8 @@
         'browser/component_updater/pnacl/pnacl_component_installer.h',
         'browser/component_updater/pnacl/pnacl_profile_observer.cc',
         'browser/component_updater/pnacl/pnacl_profile_observer.h',
+        'browser/component_updater/pnacl/pnacl_updater_observer.cc',
+        'browser/component_updater/pnacl/pnacl_updater_observer.h',
         'browser/component_updater/recovery_component_installer.cc',
         'browser/component_updater/recovery_component_installer.h',
         'browser/component_updater/swiftshader_component_installer.cc',
@@ -510,13 +517,20 @@
         'browser/download/save_package_file_picker.h',
         'browser/drive/drive_api_service.cc',
         'browser/drive/drive_api_service.h',
+        'browser/drive/drive_api_util.cc',
+        'browser/drive/drive_api_util.h',
         'browser/drive/drive_notification_manager.cc',
         'browser/drive/drive_notification_manager.h',
         'browser/drive/drive_notification_manager_factory.cc',
         'browser/drive/drive_notification_manager_factory.h',
+        'browser/drive/drive_notification_observer.h',
+        'browser/drive/drive_service_interface.h',
+        'browser/drive/drive_switches.cc',
+        'browser/drive/drive_switches.h',
         'browser/drive/drive_uploader.cc',
         'browser/drive/drive_uploader.h',
-        'browser/drive/drive_service_interface.h',
+        'browser/drive/event_logger.cc',
+        'browser/drive/event_logger.h',
         'browser/drive/gdata_wapi_service.cc',
         'browser/drive/gdata_wapi_service.h',
         'browser/enumerate_modules_model_win.cc',
@@ -547,18 +561,16 @@
         'browser/favicon/favicon_types.h',
         'browser/favicon/favicon_util.cc',
         'browser/favicon/favicon_util.h',
-        'browser/favicon/imported_favicon_usage.cc',
-        'browser/favicon/imported_favicon_usage.h',
         'browser/file_select_helper.cc',
         'browser/file_select_helper.h',
         'browser/first_run/first_run.cc',
         'browser/first_run/first_run.h',
         'browser/first_run/first_run_dialog.h',
         'browser/first_run/first_run_internal.h',
-        'browser/first_run/first_run_linux.cc',
-        'browser/first_run/first_run_mac.mm',
-        'browser/first_run/first_run_posix.cc',
-        'browser/first_run/first_run_win.cc',
+        'browser/first_run/first_run_internal_linux.cc',
+        'browser/first_run/first_run_internal_mac.mm',
+        'browser/first_run/first_run_internal_posix.cc',
+        'browser/first_run/first_run_internal_win.cc',
         'browser/first_run/try_chrome_dialog_view.cc',
         'browser/first_run/try_chrome_dialog_view.h',
         'browser/first_run/upgrade_util.cc',
@@ -631,15 +643,8 @@
         'browser/google_apis/drive_api_requests.h',
         'browser/google_apis/drive_api_url_generator.cc',
         'browser/google_apis/drive_api_url_generator.h',
-        'browser/google_apis/drive_api_util.cc',
-        'browser/google_apis/drive_api_util.h',
         'browser/google_apis/drive_common_callbacks.h',
         'browser/google_apis/drive_entry_kinds.h',
-        'browser/google_apis/drive_notification_observer.h',
-        'browser/google_apis/drive_switches.cc',
-        'browser/google_apis/drive_switches.h',
-        'browser/google_apis/event_logger.cc',
-        'browser/google_apis/event_logger.h',
         'browser/google_apis/gdata_contacts_requests.cc',
         'browser/google_apis/gdata_contacts_requests.h',
         'browser/google_apis/gdata_errorcode.cc',
@@ -650,8 +655,6 @@
         'browser/google_apis/gdata_wapi_parser.h',
         'browser/google_apis/gdata_wapi_url_generator.cc',
         'browser/google_apis/gdata_wapi_url_generator.h',
-        'browser/google_apis/request_registry.cc',
-        'browser/google_apis/request_registry.h',
         'browser/google_apis/request_sender.cc',
         'browser/google_apis/request_sender.h',
         'browser/google_apis/request_util.cc',
@@ -668,6 +671,18 @@
         'browser/gpu/gpu_feature_checker.h',
         'browser/gpu/gpu_mode_manager.cc',
         'browser/gpu/gpu_mode_manager.h',
+        'browser/guestview/adview/adview_constants.cc',
+        'browser/guestview/adview/adview_constants.h',
+        'browser/guestview/adview/adview_guest.cc',
+        'browser/guestview/adview/adview_guest.h',
+        'browser/guestview/guestview_constants.cc',
+        'browser/guestview/guestview_constants.h',
+        'browser/guestview/guestview.cc',
+        'browser/guestview/guestview.h',
+        'browser/guestview/webview/webview_constants.cc',
+        'browser/guestview/webview/webview_constants.h',
+        'browser/guestview/webview/webview_guest.cc',
+        'browser/guestview/webview/webview_guest.h',
         'browser/hang_monitor/hang_crash_dump_win.cc',
         'browser/hang_monitor/hang_crash_dump_win.h',
         'browser/hang_monitor/hung_plugin_action.cc',
@@ -843,17 +858,13 @@
         'browser/importer/importer.h',
         'browser/importer/importer_bridge.cc',
         'browser/importer/importer_bridge.h',
-        'browser/importer/importer_data_types.cc',
-        'browser/importer/importer_data_types.h',
-        'browser/importer/importer_host.cc',
-        'browser/importer/importer_host.h',
+        'browser/importer/importer_creator.cc',
+        'browser/importer/importer_creator.h',
         'browser/importer/importer_list.cc',
         'browser/importer/importer_list.h',
         'browser/importer/importer_list_observer.h',
         'browser/importer/importer_lock_dialog.h',
         'browser/importer/importer_progress_observer.h',
-        'browser/importer/importer_type.cc',
-        'browser/importer/importer_type.h',
         'browser/importer/in_process_importer_bridge.cc',
         'browser/importer/in_process_importer_bridge.h',
         'browser/importer/nss_decryptor.cc',
@@ -864,16 +875,10 @@
         'browser/importer/nss_decryptor_system_nss.h',
         'browser/importer/nss_decryptor_win.cc',
         'browser/importer/nss_decryptor_win.h',
-        'browser/importer/profile_import_process_messages.cc',
-        'browser/importer/profile_import_process_messages.h',
         'browser/importer/profile_writer.cc',
         'browser/importer/profile_writer.h',
         'browser/importer/safari_importer.h',
         'browser/importer/safari_importer.mm',
-        'browser/importer/toolbar_importer.cc',
-        'browser/importer/toolbar_importer.h',
-        'browser/importer/toolbar_importer_utils.cc',
-        'browser/importer/toolbar_importer_utils.h',
         'browser/infobars/confirm_infobar_delegate.cc',
         'browser/infobars/confirm_infobar_delegate.h',
         'browser/infobars/infobar.cc',
@@ -892,7 +897,9 @@
         'browser/internal_auth.h',
         'browser/intranet_redirect_detector.cc',
         'browser/intranet_redirect_detector.h',
-        'browser/invalidation/invalidation_frontend.h',
+        'browser/invalidation/fake_invalidation_service.cc',
+        'browser/invalidation/fake_invalidation_service.h',
+        'browser/invalidation/invalidation_service.h',
         'browser/invalidation/invalidation_service_android.cc',
         'browser/invalidation/invalidation_service_android.h',
         'browser/invalidation/invalidation_service_factory.cc',
@@ -972,24 +979,18 @@
         'browser/media/media_stream_devices_controller.h',
         'browser/media/media_stream_infobar_delegate.cc',
         'browser/media/media_stream_infobar_delegate.h',
+        'browser/media/webrtc_log_upload_list.cc',
+        'browser/media/webrtc_log_upload_list.h',
         'browser/media/webrtc_log_uploader.cc',
         'browser/media/webrtc_log_uploader.h',
         'browser/media/webrtc_logging_handler_host.cc',
         'browser/media/webrtc_logging_handler_host.h',
-        'browser/media_galleries/fileapi/itunes_data_provider.cc',
-        'browser/media_galleries/fileapi/itunes_data_provider.h',
-        'browser/media_galleries/fileapi/itunes_file_util.cc',
-        'browser/media_galleries/fileapi/itunes_file_util.h',
         'browser/media_galleries/fileapi/itunes_finder.cc',
         'browser/media_galleries/fileapi/itunes_finder.h',
         'browser/media_galleries/fileapi/itunes_finder_mac.h',
         'browser/media_galleries/fileapi/itunes_finder_mac.mm',
         'browser/media_galleries/fileapi/itunes_finder_win.cc',
         'browser/media_galleries/fileapi/itunes_finder_win.h',
-        'browser/media_galleries/fileapi/itunes_library_parser.cc',
-        'browser/media_galleries/fileapi/itunes_library_parser.h',
-        'browser/media_galleries/fileapi/itunes_xml_utils.cc',
-        'browser/media_galleries/fileapi/itunes_xml_utils.h',
         'browser/media_galleries/fileapi/media_file_system_mount_point_provider.cc',
         'browser/media_galleries/fileapi/media_file_system_mount_point_provider.h',
         'browser/media_galleries/fileapi/media_file_validator_factory.h',
@@ -998,23 +999,12 @@
         'browser/media_galleries/fileapi/media_path_filter.h',
         'browser/media_galleries/fileapi/native_media_file_util.cc',
         'browser/media_galleries/fileapi/native_media_file_util.h',
-        'browser/media_galleries/fileapi/picasa/picasa_album_table_reader.cc',
-        'browser/media_galleries/fileapi/picasa/picasa_album_table_reader.h',
-        'browser/media_galleries/fileapi/picasa/picasa_data_provider.cc',
-        'browser/media_galleries/fileapi/picasa/picasa_data_provider.h',
-        'browser/media_galleries/fileapi/picasa/picasa_file_util.cc',
-        'browser/media_galleries/fileapi/picasa/picasa_file_util.h',
         'browser/media_galleries/fileapi/picasa/picasa_finder.cc',
         'browser/media_galleries/fileapi/picasa/picasa_finder.h',
-        'browser/media_galleries/fileapi/picasa/pmp_column_reader.cc',
-        'browser/media_galleries/fileapi/picasa/pmp_column_reader.cc',
-        'browser/media_galleries/fileapi/picasa/pmp_column_reader.cc',
-        'browser/media_galleries/fileapi/picasa/pmp_column_reader.h',
-        'browser/media_galleries/fileapi/picasa/pmp_constants.h',
-        'browser/media_galleries/fileapi/picasa/pmp_table_reader.cc',
-        'browser/media_galleries/fileapi/picasa/pmp_table_reader.h',
-        'browser/media_galleries/fileapi/supported_image_type_validator.h',
+        'browser/media_galleries/fileapi/safe_itunes_pref_parser_win.cc',
+        'browser/media_galleries/fileapi/safe_itunes_pref_parser_win.h',
         'browser/media_galleries/fileapi/supported_image_type_validator.cc',
+        'browser/media_galleries/fileapi/supported_image_type_validator.h',
         'browser/media_galleries/imported_media_gallery_registry.cc',
         'browser/media_galleries/imported_media_gallery_registry.h',
         'browser/media_galleries/linux/mtp_device_delegate_impl_linux.cc',
@@ -1139,8 +1129,6 @@
         'browser/net/load_time_stats.h',
         'browser/net/net_error_tab_helper.cc',
         'browser/net/net_error_tab_helper.h',
-        'browser/net/net_log_logger.cc',
-        'browser/net/net_log_logger.h',
         'browser/net/net_log_temp_file.cc',
         'browser/net/net_log_temp_file.h',
         'browser/net/net_pref_observer.cc',
@@ -1201,6 +1189,7 @@
         'browser/notifications/fake_balloon_view.h',
         'browser/notifications/message_center_notification_manager.cc',
         'browser/notifications/message_center_notification_manager.h',
+        'browser/notifications/message_center_notification_manager_win.cc',
         'browser/notifications/message_center_settings_controller.cc',
         'browser/notifications/message_center_settings_controller.h',
         'browser/notifications/notification.cc',
@@ -1343,6 +1332,8 @@
         'browser/policy/browser_policy_connector.h',
         'browser/policy/cloud/cloud_policy_client.cc',
         'browser/policy/cloud/cloud_policy_client.h',
+        'browser/policy/cloud/cloud_policy_client_registration_helper.cc',
+        'browser/policy/cloud/cloud_policy_client_registration_helper.h',
         'browser/policy/cloud/cloud_policy_constants.cc',
         'browser/policy/cloud/cloud_policy_constants.h',
         'browser/policy/cloud/cloud_policy_core.cc',
@@ -1387,6 +1378,10 @@
         'browser/policy/cloud/user_info_fetcher.h',
         'browser/policy/cloud/user_policy_signin_service.cc',
         'browser/policy/cloud/user_policy_signin_service.h',
+        'browser/policy/cloud/user_policy_signin_service_android.cc',
+        'browser/policy/cloud/user_policy_signin_service_android.h',
+        'browser/policy/cloud/user_policy_signin_service_base.cc',
+        'browser/policy/cloud/user_policy_signin_service_base.h',
         'browser/policy/cloud/user_policy_signin_service_factory.cc',
         'browser/policy/cloud/user_policy_signin_service_factory.h',
         'browser/policy/config_dir_policy_loader.cc',
@@ -1531,14 +1526,6 @@
         'browser/printing/cloud_print/cloud_print_proxy_service.h',
         'browser/printing/cloud_print/cloud_print_proxy_service_factory.cc',
         'browser/printing/cloud_print/cloud_print_proxy_service_factory.h',
-        'browser/printing/cloud_print/cloud_print_setup_flow.cc',
-        'browser/printing/cloud_print/cloud_print_setup_flow.h',
-        'browser/printing/cloud_print/cloud_print_setup_handler.cc',
-        'browser/printing/cloud_print/cloud_print_setup_handler.h',
-        'browser/printing/cloud_print/cloud_print_setup_message_handler.cc',
-        'browser/printing/cloud_print/cloud_print_setup_message_handler.h',
-        'browser/printing/cloud_print/cloud_print_setup_source.cc',
-        'browser/printing/cloud_print/cloud_print_setup_source.h',
         'browser/printing/cloud_print/cloud_print_url.cc',
         'browser/printing/cloud_print/cloud_print_url.h',
         'browser/printing/print_dialog_cloud.cc',
@@ -1627,6 +1614,8 @@
         'browser/profiles/profile_info_util.h',
         'browser/profiles/profile_io_data.cc',
         'browser/profiles/profile_io_data.h',
+        'browser/profiles/profile_loader.cc',
+        'browser/profiles/profile_loader.h',
         'browser/profiles/profile_manager.cc',
         'browser/profiles/profile_manager.h',
         'browser/profiles/profile_metrics.cc',
@@ -1749,14 +1738,13 @@
         'browser/screensaver_window_finder_x11.h',
         'browser/search/iframe_source.cc',
         'browser/search/iframe_source.h',
-        'browser/search/instant_extended_context_menu_observer.cc',
-        'browser/search/instant_extended_context_menu_observer.h',
         'browser/search/instant_io_context.cc',
         'browser/search/instant_io_context.h',
         'browser/search/instant_service.cc',
         'browser/search/instant_service.h',
         'browser/search/instant_service_factory.cc',
         'browser/search/instant_service_factory.h',
+        'browser/search/instant_service_observer.h',
         'browser/search/local_ntp_source.cc',
         'browser/search/local_ntp_source.h',
         'browser/search/most_visited_iframe_source.cc',
@@ -1800,6 +1788,12 @@
         'browser/service/service_process_control.cc',
         'browser/service/service_process_control_mac.mm',
         'browser/service/service_process_control.h',
+        'browser/local_discovery/local_domain_resolver.cc',
+        'browser/local_discovery/local_domain_resolver.h',
+        'browser/local_discovery/service_discovery_client.cc',
+        'browser/local_discovery/service_discovery_client.h',
+        'browser/local_discovery/service_discovery_client_impl.cc',
+        'browser/local_discovery/service_discovery_client_impl.h',
         'browser/sessions/base_session_service.cc',
         'browser/sessions/base_session_service.h',
         'browser/sessions/persistent_tab_restore_service.cc',
@@ -1991,10 +1985,6 @@
         'browser/sync/backend_migrator.h',
         'browser/sync/backend_unrecoverable_error_handler.cc',
         'browser/sync/backend_unrecoverable_error_handler.h',
-        'browser/sync/glue/android_invalidator_bridge.cc',
-        'browser/sync/glue/android_invalidator_bridge.h',
-        'browser/sync/glue/android_invalidator_bridge_proxy.cc',
-        'browser/sync/glue/android_invalidator_bridge_proxy.h',
         'browser/sync/glue/autofill_data_type_controller.cc',
         'browser/sync/glue/autofill_data_type_controller.h',
         'browser/sync/glue/autofill_profile_data_type_controller.cc',
@@ -2118,6 +2108,7 @@
         'browser/sync/profile_sync_service_harness.cc',
         'browser/sync/profile_sync_service_harness.h',
         'browser/sync/profile_sync_service_model_type_selection_android.h',
+        'browser/sync/profile_sync_service_observer.cc',
         'browser/sync/profile_sync_service_observer.h',
         'browser/sync/retry_verifier.cc',
         'browser/sync/retry_verifier.h',
@@ -2131,13 +2122,19 @@
         'browser/sync/sync_ui_util.h',
         'browser/sync/user_selectable_sync_type.h',
         'browser/sync_file_system/conflict_resolution_policy.h',
-        'browser/sync_file_system/drive/api_util.cc',
-        'browser/sync_file_system/drive/api_util.h',
-        'browser/sync_file_system/drive/api_util_interface.h',
-        'browser/sync_file_system/drive/local_change_processor_delegate.cc',
-        'browser/sync_file_system/drive/local_change_processor_delegate.h',
-        'browser/sync_file_system/drive/metadata_db_migration_util.cc',
-        'browser/sync_file_system/drive/metadata_db_migration_util.h',
+        'browser/sync_file_system/conflict_resolution_resolver.cc',
+        'browser/sync_file_system/conflict_resolution_resolver.h',
+        'browser/sync_file_system/drive_backend/api_util.cc',
+        'browser/sync_file_system/drive_backend/api_util.h',
+        'browser/sync_file_system/drive_backend/api_util_interface.h',
+        'browser/sync_file_system/drive_backend/local_sync_delegate.cc',
+        'browser/sync_file_system/drive_backend/local_sync_delegate.h',
+        'browser/sync_file_system/drive_backend/metadata_database.cc',
+        'browser/sync_file_system/drive_backend/metadata_database.h',
+        'browser/sync_file_system/drive_backend/metadata_db_migration_util.cc',
+        'browser/sync_file_system/drive_backend/metadata_db_migration_util.h',
+        'browser/sync_file_system/drive_backend/remote_sync_delegate.cc',
+        'browser/sync_file_system/drive_backend/remote_sync_delegate.h',
         'browser/sync_file_system/drive_file_sync_service.cc',
         'browser/sync_file_system/drive_file_sync_service.h',
         'browser/sync_file_system/drive_file_sync_util.cc',
@@ -2159,6 +2156,8 @@
         'browser/sync_file_system/remote_file_sync_service.h',
         'browser/sync_file_system/remote_sync_operation_resolver.cc',
         'browser/sync_file_system/remote_sync_operation_resolver.h',
+        'browser/sync_file_system/sync_action.h',
+        'browser/sync_file_system/sync_direction.h',
         'browser/sync_file_system/sync_event_observer.h',
         'browser/sync_file_system/sync_file_system_service.cc',
         'browser/sync_file_system/sync_file_system_service.h',
@@ -2227,6 +2226,8 @@
         'browser/themes/theme_service_factory.cc',
         'browser/themes/theme_service_factory.h',
         'browser/themes/theme_service.h',
+        'browser/themes/theme_service_aurax11.cc',
+        'browser/themes/theme_service_aurax11.h',
         'browser/themes/theme_service_gtk.cc',
         'browser/themes/theme_service_mac.mm',
         'browser/themes/theme_syncable_service.cc',
@@ -2270,8 +2271,12 @@
         'browser/translate/translate_manager.h',
         'browser/translate/translate_prefs.cc',
         'browser/translate/translate_prefs.h',
+        'browser/translate/translate_script.cc',
+        'browser/translate/translate_script.h',
         'browser/translate/translate_tab_helper.cc',
         'browser/translate/translate_tab_helper.h',
+        'browser/translate/translate_url_fetcher.cc',
+        'browser/translate/translate_url_fetcher.h',
         'browser/translate/translate_url_util.cc',
         'browser/translate/translate_url_util.h',
         'browser/undo/undo_service.cc',
@@ -2282,6 +2287,8 @@
         'browser/upgrade_detector.h',
         'browser/upgrade_detector_impl.cc',
         'browser/upgrade_detector_impl.h',
+        'browser/upload_list.cc',
+        'browser/upload_list.h',
         'browser/usb/usb_device.cc',
         'browser/usb/usb_device.h',
         'browser/usb/usb_interface.cc',
@@ -2316,6 +2323,7 @@
         'browser/web_applications/web_app_linux.cc',
         'browser/web_applications/web_app_mac.h',
         'browser/web_applications/web_app_mac.mm',
+        'browser/web_applications/web_app_win.h',
         'browser/web_applications/web_app_win.cc',
         'browser/web_resource/eula_accepted_notifier.cc',
         'browser/web_resource/eula_accepted_notifier.h',
@@ -2351,8 +2359,6 @@
         'browser/webdata/web_data_service_win.cc',
         'browser/webdata/web_intents_table.cc',
         'browser/webdata/web_intents_table.h',
-        'browser/webview/webview_guest.cc',
-        'browser/webview/webview_guest.h',
         # These files are needed by page_cycler.cc
         'test/base/test_switches.cc',
         'test/base/test_switches.h',
@@ -2377,9 +2383,9 @@
             'common/extensions/api/api.gyp:api',
             'debugger',
             'installer_util',
+            'sync_file_system_drive_proto',
             'sync_file_system_proto',
             '../cc/cc.gyp:cc',
-            '../components/components.gyp:autofill_browser',
             '../components/components.gyp:autofill_content_browser',
             '../components/components.gyp:navigation_interception',
             '../net/net.gyp:net_with_v8',
@@ -2434,7 +2440,7 @@
             'xcode_settings': {'OTHER_LDFLAGS': ['-weak_framework CoreImage']},
           },
         }],
-        ['OS=="mac" or OS=="win" or OS=="linux" or chromeos==1', {
+        ['OS=="win" or OS=="mac" or OS=="linux" or chromeos==1', {
           'sources': [
             'browser/media_galleries/fileapi/device_media_async_file_util.cc',
             'browser/media_galleries/fileapi/device_media_async_file_util.h',
@@ -2443,6 +2449,22 @@
             'browser/media_galleries/fileapi/mtp_device_map_service.h',
           ],
         }],
+        ['OS=="win" or OS=="mac"', {
+          'sources': [
+            'browser/media_galleries/fileapi/itunes_data_provider.cc',
+            'browser/media_galleries/fileapi/itunes_data_provider.h',
+            'browser/media_galleries/fileapi/itunes_file_util.cc',
+            'browser/media_galleries/fileapi/itunes_file_util.h',
+            'browser/media_galleries/fileapi/picasa/picasa_data_provider.cc',
+            'browser/media_galleries/fileapi/picasa/picasa_data_provider.h',
+            'browser/media_galleries/fileapi/picasa/picasa_file_util.cc',
+            'browser/media_galleries/fileapi/picasa/picasa_file_util.h',
+            'browser/media_galleries/fileapi/safe_itunes_library_parser.cc',
+            'browser/media_galleries/fileapi/safe_itunes_library_parser.h',
+            'browser/media_galleries/fileapi/safe_itunes_pref_parser_win.cc',
+            'browser/media_galleries/fileapi/safe_itunes_pref_parser_win.h',
+          ],
+        }],
         ['enable_extensions==1', {
           'sources': [
             # Only extension API implementations should go here.
@@ -2655,6 +2677,8 @@
             'browser/password_manager/native_backend_kwallet_x.cc',
             'browser/password_manager/native_backend_kwallet_x.h',
             'browser/platform_util_linux.cc',
+            'browser/policy/cloud/cloud_policy_client_registration_helper.cc',
+            'browser/policy/cloud/cloud_policy_client_registration_helper.h',
             'browser/policy/cloud/user_cloud_policy_manager.cc',
             'browser/policy/cloud/user_cloud_policy_manager.h',
             'browser/policy/cloud/user_cloud_policy_manager_factory.cc',
@@ -2663,6 +2687,8 @@
             'browser/policy/cloud/user_cloud_policy_store.h',
             'browser/policy/cloud/user_policy_signin_service.cc',
             'browser/policy/cloud/user_policy_signin_service.h',
+            'browser/policy/cloud/user_policy_signin_service_base.cc',
+            'browser/policy/cloud/user_policy_signin_service_base.h',
             'browser/policy/cloud/user_policy_signin_service_factory.cc',
             'browser/policy/cloud/user_policy_signin_service_factory.h',
             'browser/screensaver_window_finder_x11.cc',
@@ -2673,6 +2699,8 @@
             'browser/storage_monitor/mtab_watcher_linux.h',
             'browser/storage_monitor/storage_monitor_linux.cc',
             'browser/storage_monitor/storage_monitor_linux.h',
+            'browser/themes/theme_service_aurax11.cc',
+            'browser/themes/theme_service_aurax11.h',
             'browser/ui/webui/help/version_updater_basic.cc',
             'browser/ui/webui/help/version_updater_basic.h',
             'browser/upgrade_detector_impl.cc',
@@ -2889,7 +2917,7 @@
           'sources!': [
             # Bookmark export/import are handled via the BookmarkColumns
             # ContentProvider.
-            'browser/bookmarks/bookmark_html_reader.cc',
+            'browser/importer/bookmark_html_reader.cc',
             'browser/bookmarks/bookmark_html_writer.cc',
             'browser/ssl/ssl_add_certificate.cc',
 
@@ -2915,10 +2943,14 @@
             'browser/policy/cloud/external_policy_data_updater.h',
             'browser/policy/cloud/resource_cache.cc',
             'browser/policy/cloud/resource_cache.h',
+            'browser/policy/cloud/user_policy_signin_service.cc',
+            'browser/policy/cloud/user_policy_signin_service.h',
             'browser/policy/config_dir_policy_loader.cc',
             'browser/policy/config_dir_policy_loader.h',
             'browser/policy/managed_mode_policy_provider.cc',
             'browser/policy/managed_mode_policy_provider.h',
+            'browser/profiles/profile_loader.cc',
+            'browser/profiles/profile_loader.h',
             'browser/sessions/persistent_tab_restore_service.cc',
             'browser/sessions/persistent_tab_restore_service.h',
             'browser/sessions/session_backend.cc',
@@ -3063,7 +3095,7 @@
             ['exclude', '^browser/hang_monitor/'],
           ],
           'conditions': [
-            ['use_aura==1',{
+            ['use_aura==1', {
               'dependencies': [
                 '../build/linux/system.gyp:dbus',
                 '../build/linux/system.gyp:fontconfig',
@@ -3128,12 +3160,24 @@
         }],
         ['enable_webrtc==0', {
           'sources!': [
+            'browser/media/webrtc_log_upload_list.cc',
+            'browser/media/webrtc_log_upload_list.h',
             'browser/media/webrtc_log_uploader.cc',
             'browser/media/webrtc_log_uploader.h',
             'browser/media/webrtc_logging_handler_host.cc',
             'browser/media/webrtc_logging_handler_host.h',
           ]
         }],
+        ['enable_mdns != 1', {
+            'sources!': [
+              'browser/local_discovery/local_domain_resolver.cc',
+              'browser/local_discovery/local_domain_resolver.h',
+              'browser/local_discovery/service_discovery_client.cc',
+              'browser/local_discovery/service_discovery_client.h',
+              'browser/local_discovery/service_discovery_client_impl.cc',
+              'browser/local_discovery/service_discovery_client_impl.h',
+            ]
+        }],
       ],
       'target_conditions': [
         # Need 'target_conditions' to override default filename_rules to include
@@ -3230,6 +3274,19 @@
       'includes': [ '../build/protoc.gypi' ]
     },
     {
+      # Protobuf compiler / generator for Sync FileSystem protocol buffer.
+      'target_name': 'sync_file_system_drive_proto',
+      'type': 'static_library',
+      'sources': [
+        'browser/sync_file_system/drive_backend/metadata_database.proto',
+      ],
+      'variables': {
+        'proto_in_dir': 'browser/sync_file_system/drive_backend',
+        'proto_out_dir': 'chrome/browser/sync_file_system/drive_backend',
+      },
+      'includes': [ '../build/protoc.gypi' ]
+    },
+    {
       # Protobuf compiler / generator for cloud policy protocol buffers.
       'target_name': 'cloud_policy_proto',
       'type': 'static_library',
@@ -3263,9 +3320,11 @@
             'android/java/src/org/chromium/chrome/browser/ContentViewUtil.java',
             'android/java/src/org/chromium/chrome/browser/DevToolsServer.java',
             'android/java/src/org/chromium/chrome/browser/database/SQLiteCursor.java',
+            'android/java/src/org/chromium/chrome/browser/favicon/FaviconHelper.java',
             'android/java/src/org/chromium/chrome/browser/IntentHelper.java',
             'android/java/src/org/chromium/chrome/browser/JavascriptAppModalDialog.java',
             'android/java/src/org/chromium/chrome/browser/NavigationPopup.java',
+            'android/java/src/org/chromium/chrome/browser/profiles/MostVisitedSites.java',
             'android/java/src/org/chromium/chrome/browser/profiles/Profile.java',
             'android/java/src/org/chromium/chrome/browser/SSLClientCertificateRequest.java',
             'android/java/src/org/chromium/chrome/browser/search_engines/TemplateUrlService.java',
diff --git a/chrome/chrome_browser_chromeos.gypi b/chrome/chrome_browser_chromeos.gypi
index 6872360..bbd6291 100644
--- a/chrome/chrome_browser_chromeos.gypi
+++ b/chrome/chrome_browser_chromeos.gypi
@@ -22,7 +22,7 @@
       },
       'dependencies': [
         # TODO(tbarzic): Cleanup this list.
-	'attestation_proto',
+        'attestation_proto',
         'app/policy/cloud_policy_codegen.gyp:policy',
         'browser/performance_monitor/performance_monitor.gyp:performance_monitor',
         'browser_extensions',
@@ -47,6 +47,8 @@
         '../build/linux/system.gyp:dbus',
         '../chromeos/chromeos.gyp:chromeos',
         '../chromeos/chromeos.gyp:chromeos_memory',
+        # browser_chromeos #includes power_supply_properties.pb.h directly.
+        '../chromeos/chromeos.gyp:power_manager_proto',
         '../chromeos/ime/input_method.gyp:gencode',
         '../content/content.gyp:content_browser',
         '../content/content.gyp:content_common',
@@ -211,6 +213,8 @@
         'browser/chromeos/dbus/proxy_resolution_service_provider.cc',
         'browser/chromeos/dbus/proxy_resolution_service_provider.h',
         'browser/chromeos/device_hierarchy_observer.h',
+        'browser/chromeos/device_uma.cc',
+        'browser/chromeos/device_uma.h',
         'browser/chromeos/drive/change_list_loader.cc',
         'browser/chromeos/drive/change_list_loader.h',
         'browser/chromeos/drive/change_list_loader_observer.h',
@@ -257,6 +261,8 @@
         'browser/chromeos/drive/file_system/search_operation.h',
         'browser/chromeos/drive/file_system/touch_operation.cc',
         'browser/chromeos/drive/file_system/touch_operation.h',
+        'browser/chromeos/drive/file_system/truncate_operation.cc',
+        'browser/chromeos/drive/file_system/truncate_operation.h',
         'browser/chromeos/drive/file_system/update_operation.cc',
         'browser/chromeos/drive/file_system/update_operation.h',
         'browser/chromeos/drive/file_system_interface.h',
@@ -271,6 +277,8 @@
         'browser/chromeos/drive/file_task_executor.h',
         'browser/chromeos/drive/file_write_helper.cc',
         'browser/chromeos/drive/file_write_helper.h',
+        'browser/chromeos/drive/fileapi_worker.cc',
+        'browser/chromeos/drive/fileapi_worker.h',
         'browser/chromeos/drive/job_list.cc',
         'browser/chromeos/drive/job_list.h',
         'browser/chromeos/drive/job_queue.cc',
@@ -325,6 +333,14 @@
         'browser/chromeos/external_metrics.h',
         'browser/chromeos/external_protocol_dialog.cc',
         'browser/chromeos/external_protocol_dialog.h',
+        'browser/chromeos/fileapi/cros_mount_point_provider.cc',
+        'browser/chromeos/fileapi/cros_mount_point_provider.h',
+        'browser/chromeos/fileapi/file_access_permissions.cc',
+        'browser/chromeos/fileapi/file_access_permissions.h',
+        'browser/chromeos/fileapi/remote_file_system_operation.cc',
+        'browser/chromeos/fileapi/remote_file_system_operation.h',
+        'browser/chromeos/fileapi/remote_file_stream_writer.cc',
+        'browser/chromeos/fileapi/remote_file_stream_writer.h',
         'browser/chromeos/imageburner/burn_controller.cc',
         'browser/chromeos/imageburner/burn_controller.h',
         'browser/chromeos/imageburner/burn_device_handler.cc',
@@ -369,6 +385,8 @@
         'browser/chromeos/input_method/component_extension_ime_manager_impl.h',
         'browser/chromeos/input_method/mock_ibus_controller.cc',
         'browser/chromeos/input_method/mock_ibus_controller.h',
+        'browser/chromeos/keyboard_driven_event_rewriter.cc',
+        'browser/chromeos/keyboard_driven_event_rewriter.h',
         'browser/chromeos/kiosk_mode/kiosk_mode_idle_logout.cc',
         'browser/chromeos/kiosk_mode/kiosk_mode_idle_logout.h',
         'browser/chromeos/kiosk_mode/kiosk_mode_screensaver.cc',
@@ -627,6 +645,8 @@
         'browser/chromeos/policy/enrollment_status_chromeos.h',
         'browser/chromeos/policy/enterprise_install_attributes.cc',
         'browser/chromeos/policy/enterprise_install_attributes.h',
+        'browser/chromeos/policy/login_profile_policy_provider.cc',
+        'browser/chromeos/policy/login_profile_policy_provider.h',
         'browser/chromeos/policy/network_configuration_updater.cc',
         'browser/chromeos/policy/network_configuration_updater.h',
         'browser/chromeos/policy/network_configuration_updater_impl.cc',
@@ -639,6 +659,10 @@
         'browser/chromeos/policy/policy_oauth2_token_fetcher.h',
         'browser/chromeos/policy/proxy_policy_provider.cc',
         'browser/chromeos/policy/proxy_policy_provider.h',
+        'browser/chromeos/policy/recommendation_restorer.cc',
+        'browser/chromeos/policy/recommendation_restorer.h',
+        'browser/chromeos/policy/recommendation_restorer_factory.cc',
+        'browser/chromeos/policy/recommendation_restorer_factory.h',
         'browser/chromeos/policy/user_cloud_policy_manager_chromeos.cc',
         'browser/chromeos/policy/user_cloud_policy_manager_chromeos.h',
         'browser/chromeos/policy/user_cloud_policy_manager_factory_chromeos.cc',
@@ -705,6 +729,8 @@
         'browser/chromeos/settings/device_settings_provider.h',
         'browser/chromeos/settings/device_settings_service.cc',
         'browser/chromeos/settings/device_settings_service.h',
+        'browser/chromeos/settings/owner_flags_storage.cc',
+        'browser/chromeos/settings/owner_flags_storage.h',
         'browser/chromeos/settings/owner_key_util.cc',
         'browser/chromeos/settings/owner_key_util.h',
         'browser/chromeos/settings/session_manager_operation.cc',
@@ -723,10 +749,13 @@
         'browser/chromeos/status/network_menu.h',
         'browser/chromeos/status/network_menu_icon.cc',
         'browser/chromeos/status/network_menu_icon.h',
+        'browser/chromeos/swap_metrics.cc',
+        'browser/chromeos/swap_metrics.h',
         'browser/chromeos/system/ash_system_tray_delegate.cc',
         'browser/chromeos/system/ash_system_tray_delegate.h',
         'browser/chromeos/system/automatic_reboot_manager.cc',
         'browser/chromeos/system/automatic_reboot_manager.h',
+        'browser/chromeos/system/automatic_reboot_manager_observer.h',
         'browser/chromeos/system/device_change_handler.cc',
         'browser/chromeos/system/device_change_handler.h',
         'browser/chromeos/system/input_device_settings.cc',
@@ -823,6 +852,12 @@
             'browser/chromeos/extensions/wallpaper_private_api.h',
           ],
         }],
+        ['use_x11==0', {
+          'sources!': [
+            'browser/chromeos/device_uma.cc',
+            'browser/chromeos/device_uma.h',
+          ],
+        }],
         ['use_cras==1', {
           'cflags': [
             '<!@(<(pkg-config) --cflags libcras)',
diff --git a/chrome/chrome_browser_extensions.gypi b/chrome/chrome_browser_extensions.gypi
index d2c4f7c..16a03f3 100644
--- a/chrome/chrome_browser_extensions.gypi
+++ b/chrome/chrome_browser_extensions.gypi
@@ -336,6 +336,10 @@
         'browser/extensions/api/permissions/permissions_api.h',
         'browser/extensions/api/permissions/permissions_api_helpers.cc',
         'browser/extensions/api/permissions/permissions_api_helpers.h',
+        'browser/extensions/api/diagnostics/diagnostics_api.cc',
+        'browser/extensions/api/diagnostics/diagnostics_api.h',
+        'browser/extensions/api/diagnostics/diagnostics_api_nonchromeos.cc',
+        'browser/extensions/api/diagnostics/diagnostics_api_chromeos.cc',
         'browser/extensions/api/power/power_api.cc',
         'browser/extensions/api/power/power_api.h',
         'browser/extensions/api/power/power_api_manager.cc',
@@ -794,6 +798,7 @@
           'sources!': [
             'browser/extensions/api/audio/audio_service.cc',
             'browser/extensions/api/feedback_private/feedback_service_nonchromeos.cc',
+            'browser/extensions/api/diagnostics/diagnostics_api_nonchromeos.cc',
             'browser/extensions/default_apps.cc',
             'browser/extensions/default_apps.h',
           ],
diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi
index 6111be5..90049a9 100644
--- a/chrome/chrome_browser_ui.gypi
+++ b/chrome/chrome_browser_ui.gypi
@@ -129,8 +129,6 @@
         'browser/ui/app_list/chrome_signin_delegate.h',
         'browser/ui/app_list/extension_app_item.cc',
         'browser/ui/app_list/extension_app_item.h',
-        'browser/ui/app_list/profile_loader.cc',
-        'browser/ui/app_list/profile_loader.h',
         'browser/ui/app_list/search/app_result.cc',
         'browser/ui/app_list/search/app_result.h',
         'browser/ui/app_list/search/app_search_provider.cc',
@@ -163,6 +161,8 @@
         'browser/ui/app_list/search/tokenized_string_char_iterator.h',
         'browser/ui/app_list/search/tokenized_string_match.cc',
         'browser/ui/app_list/search/tokenized_string_match.h',
+        'browser/ui/app_list/search/webstore_installer.cc',
+        'browser/ui/app_list/search/webstore_installer.h',
         'browser/ui/app_list/search/webstore_provider.cc',
         'browser/ui/app_list/search/webstore_provider.h',
         'browser/ui/app_list/search/webstore_result.cc',
@@ -180,6 +180,8 @@
         'browser/ui/app_modal_dialogs/javascript_dialog_manager.cc',
         'browser/ui/app_modal_dialogs/javascript_dialog_manager.h',
         'browser/ui/app_modal_dialogs/native_app_modal_dialog.h',
+        'browser/ui/apps/chrome_shell_window_delegate.cc',
+        'browser/ui/apps/chrome_shell_window_delegate.h',
         'browser/ui/ash/ash_keyboard_controller_proxy.cc',
         'browser/ui/ash/ash_keyboard_controller_proxy.h',
         'browser/ui/ash/app_list/app_list_controller_ash.h',
@@ -290,7 +292,6 @@
         'browser/ui/autofill/autofill_popup_controller.h',
         'browser/ui/autofill/autofill_popup_controller_impl.cc',
         'browser/ui/autofill/autofill_popup_controller_impl.h',
-        'browser/ui/autofill/autofill_popup_view.cc',
         'browser/ui/autofill/autofill_popup_view.h',
         'browser/ui/autofill/country_combobox_model.cc',
         'browser/ui/autofill/country_combobox_model.h',
@@ -300,6 +301,7 @@
         'browser/ui/autofill/tab_autofill_manager_delegate.h',
         'browser/ui/auto_login_infobar_delegate.cc',
         'browser/ui/auto_login_infobar_delegate.h',
+        'browser/ui/auto_login_infobar_delegate_android.h',
         'browser/ui/auto_login_prompter.cc',
         'browser/ui/auto_login_prompter.h',
         'browser/ui/blocked_content/blocked_content_container.cc',
@@ -315,6 +317,8 @@
         'browser/ui/bookmarks/bookmark_context_menu_controller.h',
         'browser/ui/bookmarks/bookmark_drag_drop.cc',
         'browser/ui/bookmarks/bookmark_drag_drop.h',
+        'browser/ui/bookmarks/bookmark_editor.cc',
+        'browser/ui/bookmarks/bookmark_editor.h',
         'browser/ui/bookmarks/bookmark_prompt_controller.cc',
         'browser/ui/bookmarks/bookmark_prompt_controller.h',
         'browser/ui/bookmarks/bookmark_tab_helper.cc',
@@ -420,6 +424,10 @@
         'browser/ui/cocoa/autofill/autofill_dialog_cocoa.mm',
         'browser/ui/cocoa/autofill/autofill_dialog_constants.h',
         'browser/ui/cocoa/autofill/autofill_layout.h',
+        'browser/ui/cocoa/autofill/autofill_notification_container.h',
+        'browser/ui/cocoa/autofill/autofill_notification_container.mm',
+        'browser/ui/cocoa/autofill/autofill_notification_controller.h',
+        'browser/ui/cocoa/autofill/autofill_notification_controller.mm',
         'browser/ui/cocoa/autofill/autofill_main_container.h',
         'browser/ui/cocoa/autofill/autofill_main_container.mm',
         'browser/ui/cocoa/autofill/autofill_popup_view_bridge.h',
@@ -440,6 +448,8 @@
         'browser/ui/cocoa/autofill/down_arrow_popup_menu_cell.mm',
         'browser/ui/cocoa/autofill/layout_view.h',
         'browser/ui/cocoa/autofill/layout_view.mm',
+        'browser/ui/cocoa/autofill/autofill_pop_up_button.h',
+        'browser/ui/cocoa/autofill/autofill_pop_up_button.mm',
         'browser/ui/cocoa/autofill/simple_grid_layout.h',
         'browser/ui/cocoa/autofill/simple_grid_layout.mm',
         'browser/ui/cocoa/background_gradient_view.h',
@@ -778,6 +788,12 @@
         'browser/ui/cocoa/nsmenuitem_additions.mm',
         'browser/ui/cocoa/nsview_additions.h',
         'browser/ui/cocoa/nsview_additions.mm',
+        'browser/ui/cocoa/omnibox/omnibox_popup_cell.h',
+        'browser/ui/cocoa/omnibox/omnibox_popup_cell.mm',
+        'browser/ui/cocoa/omnibox/omnibox_popup_matrix.h',
+        'browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm',
+        'browser/ui/cocoa/omnibox/omnibox_popup_separator_view.h',
+        'browser/ui/cocoa/omnibox/omnibox_popup_separator_view.mm',
         'browser/ui/cocoa/omnibox/omnibox_popup_view_mac.h',
         'browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm',
         'browser/ui/cocoa/omnibox/omnibox_view_mac.h',
@@ -837,8 +853,6 @@
         'browser/ui/cocoa/tab_contents/favicon_util_mac.mm',
         'browser/ui/cocoa/tab_contents/instant_overlay_controller_mac.h',
         'browser/ui/cocoa/tab_contents/instant_overlay_controller_mac.mm',
-        'browser/ui/cocoa/tab_contents/overlay_separator_view.h',
-        'browser/ui/cocoa/tab_contents/overlay_separator_view.mm',
         'browser/ui/cocoa/tab_contents/overlayable_contents_controller.h',
         'browser/ui/cocoa/tab_contents/overlayable_contents_controller.mm',
         'browser/ui/cocoa/tab_contents/render_view_context_menu_mac.h',
@@ -956,10 +970,10 @@
         'browser/ui/extensions/extension_enable_flow.h',
         'browser/ui/extensions/extension_enable_flow_delegate.h',
         'browser/ui/extensions/native_app_window.h',
-        'browser/ui/extensions/shell_window.cc',
-        'browser/ui/extensions/shell_window.h',
         'browser/ui/external_protocol_dialog_delegate.cc',
         'browser/ui/external_protocol_dialog_delegate.h',
+        'browser/ui/fast_unload_controller.cc',
+        'browser/ui/fast_unload_controller.h',
         'browser/ui/find_bar/find_bar.h',
         'browser/ui/find_bar/find_bar_controller.cc',
         'browser/ui/find_bar/find_bar_controller.h',
@@ -1346,16 +1360,14 @@
         'browser/ui/sad_tab_types.h',
         'browser/ui/screen_capture_notification_ui.h',
         'browser/ui/screen_capture_notification_ui_stub.cc',
-        'browser/ui/screen_capture_notification_ui_win.cc',
-        'browser/ui/search/instant_commit_type.h',
         'browser/ui/search/instant_controller.cc',
         'browser/ui/search/instant_controller.h',
+        'browser/ui/search/instant_ipc_sender.cc',
+        'browser/ui/search/instant_ipc_sender.h',
         'browser/ui/search/instant_loader.cc',
         'browser/ui/search/instant_loader.h',
         'browser/ui/search/instant_ntp.cc',
         'browser/ui/search/instant_ntp.h',
-        'browser/ui/search/instant_overlay.cc',
-        'browser/ui/search/instant_overlay.h',
         'browser/ui/search/instant_overlay_controller.cc',
         'browser/ui/search/instant_overlay_controller.h',
         'browser/ui/search/instant_overlay_model.cc',
@@ -1429,6 +1441,8 @@
         'browser/ui/sync/profile_signin_confirmation_helper.cc',
         'browser/ui/sync/profile_signin_confirmation_helper.h',
         'browser/ui/sync/signin_histogram.h',
+        'browser/ui/sync/sync_promo_ui.cc',
+        'browser/ui/sync/sync_promo_ui.h',
         'browser/ui/sync/tab_contents_synced_tab_delegate.cc',
         'browser/ui/sync/tab_contents_synced_tab_delegate.h',
         'browser/ui/tab_contents/chrome_web_contents_view_delegate.h',
@@ -1532,6 +1546,8 @@
         'browser/ui/views/avatar_menu_bubble_view.h',
         'browser/ui/views/avatar_menu_button.cc',
         'browser/ui/views/avatar_menu_button.h',
+        'browser/ui/views/avatar_label.cc',
+        'browser/ui/views/avatar_label.cc',
         'browser/ui/views/bookmarks/bookmark_bar_instructions_view.cc',
         'browser/ui/views/bookmarks/bookmark_bar_instructions_view.h',
         'browser/ui/views/bookmarks/bookmark_bar_view.cc',
@@ -1574,8 +1590,8 @@
         'browser/ui/views/color_chooser_win.cc',
         'browser/ui/views/confirm_bubble_views.cc',
         'browser/ui/views/confirm_bubble_views.h',
-        'browser/ui/views/conflicting_module_view_win.cc',  
-        'browser/ui/views/conflicting_module_view_win.h',  
+        'browser/ui/views/conflicting_module_view_win.cc',
+        'browser/ui/views/conflicting_module_view_win.h',
         'browser/ui/views/constrained_web_dialog_delegate_views.cc',
         'browser/ui/views/constrained_window_views.cc',
         'browser/ui/views/constrained_window_views.h',
@@ -1685,6 +1701,7 @@
         'browser/ui/views/frame/browser_desktop_root_window_host_x11.h',
         'browser/ui/views/frame/glass_browser_frame_view.cc',
         'browser/ui/views/frame/glass_browser_frame_view.h',
+        'browser/ui/views/frame/immersive_mode_controller.cc',
         'browser/ui/views/frame/immersive_mode_controller.h',
         'browser/ui/views/frame/immersive_mode_controller_ash.cc',
         'browser/ui/views/frame/immersive_mode_controller_ash.h',
@@ -1798,6 +1815,7 @@
         'browser/ui/views/message_center/notification_bubble_wrapper.cc',
         'browser/ui/views/message_center/web_notification_tray.h',
         'browser/ui/views/message_center/web_notification_tray.cc',
+        'browser/ui/views/message_center/web_notification_tray_win.cc',
         'browser/ui/views/native_focus_tracker_views.cc',
         'browser/ui/views/native_focus_tracker_views.h',
         'browser/ui/views/native_focus_tracker_views_aura.cc',
@@ -1838,6 +1856,7 @@
         'browser/ui/views/reload_button.h',
         'browser/ui/views/sad_tab_view.cc',
         'browser/ui/views/sad_tab_view.h',
+        'browser/ui/views/screen_capture_notification_ui_views.cc',
         'browser/ui/views/script_bubble_view.cc',
         'browser/ui/views/script_bubble_view.h',
         'browser/ui/views/select_file_dialog_extension.cc',
@@ -1899,6 +1918,7 @@
         'browser/ui/views/toolbar_view.cc',
         'browser/ui/views/toolbar_view.h',
         'browser/ui/views/top_level_widget_views.cc',
+        'browser/ui/views/touch_uma/touch_uma.h',
         'browser/ui/views/uninstall_view.cc',
         'browser/ui/views/uninstall_view.h',
         'browser/ui/views/update_recommended_message_box.cc',
@@ -2065,6 +2085,8 @@
         'browser/ui/webui/flash_ui.h',
         'browser/ui/webui/gesture_config_ui.cc',
         'browser/ui/webui/gesture_config_ui.h',
+        'browser/ui/webui/chromeos/salsa_ui.cc',
+        'browser/ui/webui/chromeos/salsa_ui.h',
         'browser/ui/webui/help/help_handler.cc',
         'browser/ui/webui/help/help_handler.h',
         'browser/ui/webui/help/help_ui.cc',
@@ -2089,6 +2111,8 @@
         'browser/ui/webui/inspect_ui.h',
         'browser/ui/webui/instant_ui.cc',
         'browser/ui/webui/instant_ui.h',
+        'browser/ui/webui/media/webrtc_logs_ui.cc',
+        'browser/ui/webui/media/webrtc_logs_ui.h',
         'browser/ui/webui/memory_internals/memory_internals_handler.cc',
         'browser/ui/webui/memory_internals/memory_internals_handler.h',
         'browser/ui/webui/memory_internals/memory_internals_proxy.cc',
@@ -2307,8 +2331,6 @@
         'browser/ui/webui/sync_internals_ui.h',
         'browser/ui/webui/sync_promo/sync_promo_trial.cc',
         'browser/ui/webui/sync_promo/sync_promo_trial.h',
-        'browser/ui/webui/sync_promo/sync_promo_ui.cc',
-        'browser/ui/webui/sync_promo/sync_promo_ui.h',
         'browser/ui/webui/sync_setup_handler.cc',
         'browser/ui/webui/sync_setup_handler.h',
         'browser/ui/webui/tab_modal_confirm_dialog_webui.cc',
@@ -2535,6 +2557,7 @@
             ['exclude', 'browser/ui/views/frame/desktop_user_action_handler_aura.h'],
             ['exclude', 'browser/ui/views/frame/browser_desktop_root_window_host_x11.cc'],
             ['exclude', 'browser/ui/views/frame/browser_desktop_root_window_host_x11.h'],
+            ['exclude', 'browser/ui/views/screen_capture_notification_ui_views.cc'],
             ['exclude', 'browser/ui/webui/help/version_updater_basic.cc'],
             ['exclude', 'browser/ui/webui/help/version_updater_basic.h'],
             ['exclude', 'browser/upgrade_detector_impl.cc'],
@@ -2553,10 +2576,17 @@
           ],
         }],
         ['use_ash==1', {
+          'sources': [
+            'browser/ui/views/touch_uma/touch_uma_ash.cc',
+          ],
           'dependencies': [
             '../ash/ash.gyp:ash',
             '../ash/ash_strings.gyp:ash_strings',
           ],
+        }, { # use_ash==0
+          'sources': [
+            'browser/ui/views/touch_uma/touch_uma.cc',
+          ],
         }],
         ['toolkit_views==0 or chromeos==1', {
           'sources!': [
@@ -2647,6 +2677,8 @@
             ['exclude', '^browser/ui/views/theme_image_mapper_aura_win.cc'],
             ['exclude', '^browser/ui/webui/gesture_config_ui.cc'],
             ['exclude', '^browser/ui/webui/gesture_config_ui.h'],
+            ['exclude', '^browser/ui/webui/salsa_ui.cc'],
+            ['exclude', '^browser/ui/webui/salsa_ui.h'],
             ['exclude', '^browser/ui/webui/task_manager/'],
           ],
         }],
@@ -3006,6 +3038,12 @@
             'browser/ui/webui/options/geolocation_options_handler.h',
           ],
         }],
+        ['enable_webrtc==0', {
+          'sources!': [
+            'browser/ui/webui/media/webrtc_logs_ui.cc',
+            'browser/ui/webui/media/webrtc_logs_ui.h',
+          ],
+        }],
       ],
     },
   ],
diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi
index 7856327..2082620 100644
--- a/chrome/chrome_common.gypi
+++ b/chrome/chrome_common.gypi
@@ -36,7 +36,6 @@
         '<(DEPTH)/chrome/chrome_resources.gyp:chrome_strings',
         '<(DEPTH)/chrome/chrome_resources.gyp:theme_resources',
         '<(DEPTH)/chrome/common_constants.gyp:common_constants',
-        '<(DEPTH)/components/components.gyp:breakpad_common',
         '<(DEPTH)/components/components.gyp:visitedlink_common',
         '<(DEPTH)/content/content.gyp:content_common',
         '<(DEPTH)/net/net.gyp:net',
@@ -220,8 +219,6 @@
         'common/extensions/extension_icon_set.h',
         'common/extensions/extension_l10n_util.cc',
         'common/extensions/extension_l10n_util.h',
-        'common/extensions/extension_localization_peer.cc',
-        'common/extensions/extension_localization_peer.h',
         'common/extensions/extension_manifest_constants.cc',
         'common/extensions/extension_manifest_constants.h',
         'common/extensions/extension_messages.cc',
@@ -289,10 +286,10 @@
         'common/extensions/permissions/api_permission.h',
         'common/extensions/permissions/api_permission_set.cc',
         'common/extensions/permissions/api_permission_set.h',
-        'common/extensions/permissions/bluetooth_device_permission.cc',
-        'common/extensions/permissions/bluetooth_device_permission.h',
-        'common/extensions/permissions/bluetooth_device_permission_data.cc',
-        'common/extensions/permissions/bluetooth_device_permission_data.h',
+        'common/extensions/permissions/bluetooth_permission.cc',
+        'common/extensions/permissions/bluetooth_permission.h',
+        'common/extensions/permissions/bluetooth_permission_data.cc',
+        'common/extensions/permissions/bluetooth_permission_data.h',
         'common/extensions/permissions/chrome_api_permissions.cc',
         'common/extensions/permissions/chrome_api_permissions.h',
         'common/extensions/permissions/media_galleries_permission.cc',
@@ -328,10 +325,21 @@
         'common/extensions/value_counter.h',
         'common/extensions/web_accessible_resources_handler.cc',
         'common/extensions/web_accessible_resources_handler.h',
-        'common/external_ipc_fuzzer.h',
         'common/external_ipc_fuzzer.cc',
+        'common/external_ipc_fuzzer.h',
         'common/icon_with_badge_image_source.cc',
         'common/icon_with_badge_image_source.h',
+        'common/importer/imported_bookmark_entry.cc',
+        'common/importer/imported_bookmark_entry.h',
+        'common/importer/imported_favicon_usage.cc',
+        'common/importer/imported_favicon_usage.h',
+        'common/importer/importer_data_types.cc',
+        'common/importer/importer_data_types.h',
+        'common/importer/importer_type.h',
+        'common/importer/importer_url_row.cc',
+        'common/importer/importer_url_row.h',
+        'common/importer/profile_import_process_messages.cc',
+        'common/importer/profile_import_process_messages.h',
         'common/instant_restricted_id_cache.h',
         'common/instant_types.cc',
         'common/instant_types.h',
@@ -476,6 +484,17 @@
             ['include', 'common/extensions/api/managed_mode_private/managed_mode_handler.h'],
           ],
         }],
+        ['OS=="win" or OS=="mac"', {
+          'sources': [
+            'common/itunes_library.cc',
+            'common/itunes_library.h',
+            'common/itunes_xml_utils.cc',
+            'common/itunes_xml_utils.h',
+            'common/media_galleries/picasa_types.cc',
+            'common/media_galleries/picasa_types.h',
+            'common/media_galleries/pmp_constants.h',
+          ],
+        }],
         ['OS != "ios"', {
           'dependencies': [
             '<(DEPTH)/chrome/app/policy/cloud_policy_codegen.gyp:policy',
diff --git a/chrome/chrome_dll.gypi b/chrome/chrome_dll.gypi
index 9ed89d6..420948b 100644
--- a/chrome/chrome_dll.gypi
+++ b/chrome/chrome_dll.gypi
@@ -146,6 +146,7 @@
                 '<(SHARED_INTERMEDIATE_DIR)/chrome/common_resources.rc',
                 '<(SHARED_INTERMEDIATE_DIR)/chrome/extensions_api_resources.rc',
                 '<(SHARED_INTERMEDIATE_DIR)/content/content_resources.rc',
+                '<(SHARED_INTERMEDIATE_DIR)/content/browser/tracing/tracing_resources.rc',
                 '<(SHARED_INTERMEDIATE_DIR)/net/net_resources.rc',
                 '<(SHARED_INTERMEDIATE_DIR)/ui/ui_resources/ui_unscaled_resources.rc',
                 '<(SHARED_INTERMEDIATE_DIR)/webkit/webkit_chromium_resources.rc',
diff --git a/chrome/chrome_installer.gypi b/chrome/chrome_installer.gypi
index e748fbd..1553f06 100644
--- a/chrome/chrome_installer.gypi
+++ b/chrome/chrome_installer.gypi
@@ -528,8 +528,7 @@
           'installer/linux/debian/changelog.template',
           'installer/linux/debian/control.template',
           'installer/linux/debian/debian.menu',
-          'installer/linux/debian/expected_deps_ia32',
-          'installer/linux/debian/expected_deps_x64',
+          'installer/linux/debian/expected_deps',
           'installer/linux/debian/postinst',
           'installer/linux/debian/postrm',
           'installer/linux/debian/prerm',
@@ -782,7 +781,7 @@
                 '<@(packaging_files_deb)',
               ],
               'outputs': [
-                '<(PRODUCT_DIR)/google-chrome-<(channel)_<(version)-r<(revision)_<(deb_arch).deb',
+                '<(PRODUCT_DIR)/google-chrome-<(channel)_<(version)-1_<(deb_arch).deb',
               ],
               'action': [ '<@(deb_cmd)', '-c', '<(channel)', ],
             },
@@ -810,7 +809,7 @@
                 '<@(packaging_files_deb)',
               ],
               'outputs': [
-                '<(PRODUCT_DIR)/google-chrome-<(channel)_<(version)-r<(revision)_<(deb_arch).deb',
+                '<(PRODUCT_DIR)/google-chrome-<(channel)_<(version)-1_<(deb_arch).deb',
               ],
               'action': [ '<@(deb_cmd)', '-c', '<(channel)', ],
             },
@@ -838,7 +837,7 @@
                 '<@(packaging_files_deb)',
               ],
               'outputs': [
-                '<(PRODUCT_DIR)/google-chrome-<(channel)_<(version)-r<(revision)_<(deb_arch).deb',
+                '<(PRODUCT_DIR)/google-chrome-<(channel)_<(version)-1_<(deb_arch).deb',
               ],
               'action': [ '<@(deb_cmd)', '-c', '<(channel)', ],
             },
@@ -866,7 +865,7 @@
                 '<@(packaging_files_deb)',
               ],
               'outputs': [
-                '<(PRODUCT_DIR)/google-chrome-<(channel)_<(version)-r<(revision)_<(deb_arch).deb',
+                '<(PRODUCT_DIR)/google-chrome-<(channel)_<(version)-1_<(deb_arch).deb',
               ],
               'action': [ '<@(deb_cmd)', '-c', '<(channel)', ],
             },
@@ -894,7 +893,7 @@
                 '<@(packaging_files_deb)',
               ],
               'outputs': [
-                '<(PRODUCT_DIR)/google-chrome-<(channel)_<(version)-r<(revision)_<(deb_arch).deb',
+                '<(PRODUCT_DIR)/google-chrome-<(channel)_<(version)-1_<(deb_arch).deb',
               ],
               'action': [ '<@(deb_cmd)', '-c', '<(channel)', ],
             },
@@ -923,7 +922,7 @@
                 '<@(packaging_files_rpm)',
               ],
               'outputs': [
-                '<(PRODUCT_DIR)/google-chrome-<(channel)-<(version)-<(revision).<(rpm_arch).rpm',
+                '<(PRODUCT_DIR)/google-chrome-<(channel)-<(version)-1.<(rpm_arch).rpm',
               ],
               'action': [ '<@(rpm_cmd)', '-c', '<(channel)', ],
             },
@@ -952,7 +951,7 @@
                 '<@(packaging_files_rpm)',
               ],
               'outputs': [
-                '<(PRODUCT_DIR)/google-chrome-<(channel)-<(version)-<(revision).<(rpm_arch).rpm',
+                '<(PRODUCT_DIR)/google-chrome-<(channel)-<(version)-1.<(rpm_arch).rpm',
               ],
               'action': [ '<@(rpm_cmd)', '-c', '<(channel)', ],
             },
@@ -981,7 +980,7 @@
                 '<@(packaging_files_rpm)',
               ],
               'outputs': [
-                '<(PRODUCT_DIR)/google-chrome-<(channel)-<(version)-<(revision).<(rpm_arch).rpm',
+                '<(PRODUCT_DIR)/google-chrome-<(channel)-<(version)-1.<(rpm_arch).rpm',
               ],
               'action': [ '<@(rpm_cmd)', '-c', '<(channel)', ],
             },
@@ -1010,7 +1009,7 @@
                 '<@(packaging_files_rpm)',
               ],
               'outputs': [
-                '<(PRODUCT_DIR)/google-chrome-<(channel)-<(version)-<(revision).<(rpm_arch).rpm',
+                '<(PRODUCT_DIR)/google-chrome-<(channel)-<(version)-1.<(rpm_arch).rpm',
               ],
               'action': [ '<@(rpm_cmd)', '-c', '<(channel)', ],
             },
@@ -1039,7 +1038,7 @@
                 '<@(packaging_files_rpm)',
               ],
               'outputs': [
-                '<(PRODUCT_DIR)/google-chrome-<(channel)-<(version)-<(revision).<(rpm_arch).rpm',
+                '<(PRODUCT_DIR)/google-chrome-<(channel)-<(version)-1.<(rpm_arch).rpm',
               ],
               'action': [ '<@(rpm_cmd)', '-c', '<(channel)', ],
             },
diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi
index cff83a7..270e5b6 100644
--- a/chrome/chrome_renderer.gypi
+++ b/chrome/chrome_renderer.gypi
@@ -87,6 +87,8 @@
         'renderer/extensions/extension_groups.h',
         'renderer/extensions/extension_helper.cc',
         'renderer/extensions/extension_helper.h',
+        'renderer/extensions/extension_localization_peer.cc',
+        'renderer/extensions/extension_localization_peer.h',
         'renderer/extensions/feedback_private_custom_bindings.cc',
         'renderer/extensions/feedback_private_custom_bindings.h',
         'renderer/extensions/file_browser_handler_custom_bindings.cc',
@@ -115,6 +117,8 @@
         'renderer/extensions/page_capture_custom_bindings.h',
         'renderer/extensions/renderer_permissions_policy_delegate.cc',
         'renderer/extensions/renderer_permissions_policy_delegate.h',
+        'renderer/extensions/render_view_observer_natives.cc',
+        'renderer/extensions/render_view_observer_natives.h',
         'renderer/extensions/request_sender.cc',
         'renderer/extensions/request_sender.h',
         'renderer/extensions/resource_request_policy.cc',
@@ -152,16 +156,16 @@
         'renderer/isolated_world_ids.h',
         'renderer/loadtimes_extension_bindings.cc',
         'renderer/loadtimes_extension_bindings.h',
-        'renderer/media/webrtc_logging_handler_impl.cc',
-        'renderer/media/webrtc_logging_handler_impl.h',
+        'renderer/media/chrome_webrtc_log_message_delegate.cc',
+        'renderer/media/chrome_webrtc_log_message_delegate.h',
         'renderer/media/webrtc_logging_message_filter.cc',
         'renderer/media/webrtc_logging_message_filter.h',
         'renderer/net/net_error_helper.cc',
         'renderer/net/net_error_helper.h',
         'renderer/net/predictor_queue.cc',
         'renderer/net/predictor_queue.h',
-	'renderer/net/prescient_networking_dispatcher.cc',
-	'renderer/net/prescient_networking_dispatcher.h',
+        'renderer/net/prescient_networking_dispatcher.cc',
+        'renderer/net/prescient_networking_dispatcher.h',
         'renderer/net/renderer_net_predictor.cc',
         'renderer/net/renderer_net_predictor.h',
         'renderer/net_benchmarking_extension.cc',
@@ -364,8 +368,8 @@
         }],
         ['enable_webrtc==0', {
           'sources!': [
-            'renderer/media/webrtc_logging_handler_impl.cc',
-            'renderer/media/webrtc_logging_handler_impl.h',
+            'renderer/media/chrome_webrtc_log_message_delegate.cc',
+            'renderer/media/chrome_webrtc_log_message_delegate.h',
             'renderer/media/webrtc_logging_message_filter.cc',
             'renderer/media/webrtc_logging_message_filter.h',
           ],
diff --git a/chrome/chrome_repack_chrome.gypi b/chrome/chrome_repack_chrome.gypi
index 7d65d1a..58cab20 100644
--- a/chrome/chrome_repack_chrome.gypi
+++ b/chrome/chrome_repack_chrome.gypi
@@ -14,6 +14,7 @@
       ['OS != "ios"', {
         'pak_inputs': [
           '<(SHARED_INTERMEDIATE_DIR)/content/content_resources.pak',
+          '<(SHARED_INTERMEDIATE_DIR)/content/browser/tracing/tracing_resources.pak',
           '<(SHARED_INTERMEDIATE_DIR)/webkit/webkit_chromium_resources.pak',
         ],
       }],
diff --git a/chrome/chrome_resources.gyp b/chrome/chrome_resources.gyp
index 3793742..b00c7ac 100644
--- a/chrome/chrome_resources.gyp
+++ b/chrome/chrome_resources.gyp
@@ -56,6 +56,7 @@
         ['OS != "ios"', {
           'dependencies': [
             '../content/browser/devtools/devtools_resources.gyp:devtools_resources',
+            '../content/browser/tracing/tracing_resources.gyp:tracing_resources',
           ],
           'actions': [
             {
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index ca8aa6d..80b28d2 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -929,6 +929,7 @@
       # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
       'msvs_disabled_warnings': [ 4267, ],
     },
+    # This is the new ChromeDriver based on DevTools.
     {
       'target_name': 'chromedriver2_lib',
       'type': 'static_library',
@@ -953,14 +954,7 @@
         'test/chromedriver/capabilities.h',
         'test/chromedriver/chrome_launcher.cc',
         'test/chromedriver/chrome_launcher.h',
-        'test/chromedriver/chromedriver.cc',
-        'test/chromedriver/chromedriver.h',
         'test/chromedriver/command.h',
-        'test/chromedriver/command_executor.h',
-        'test/chromedriver/command_executor_impl.cc',
-        'test/chromedriver/command_executor_impl.h',
-        'test/chromedriver/command_names.cc',
-        'test/chromedriver/command_names.h',
         'test/chromedriver/commands.cc',
         'test/chromedriver/commands.h',
         'test/chromedriver/element_commands.cc',
@@ -989,23 +983,6 @@
       # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
       'msvs_disabled_warnings': [ 4267, ],
     },
-    # This is the new ChromeDriver based on DevTools.
-    {
-      'target_name': 'chromedriver2',
-      'type': 'loadable_module',
-      'dependencies': [
-        'chromedriver2_lib',
-        '../base/base.gyp:base',
-      ],
-      'include_dirs': [
-        '..',
-      ],
-      'sources': [
-        'test/chromedriver/chromedriver_shared_library.cc',
-      ],
-      # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
-      'msvs_disabled_warnings': [ 4267, ],
-    },
     {
       'target_name': 'chromedriver2_server_lib',
       'type': 'static_library',
@@ -1076,8 +1053,6 @@
         'test/chromedriver/chrome/stub_web_view.h',
         'test/chromedriver/chrome/web_view_impl_unittest.cc',
         'test/chromedriver/chrome_launcher_unittest.cc',
-        'test/chromedriver/chromedriver_unittest.cc',
-        'test/chromedriver/command_executor_impl_unittest.cc',
         'test/chromedriver/commands_unittest.cc',
         'test/chromedriver/fake_session_accessor.cc',
         'test/chromedriver/fake_session_accessor.h',
@@ -1165,6 +1140,7 @@
         '../third_party/leveldatabase/leveldatabase.gyp:leveldatabase',
         '../third_party/safe_browsing/safe_browsing.gyp:safe_browsing',
         '../ui/web_dialogs/web_dialogs.gyp:web_dialogs_test_support',
+        '../ui/ui.gyp:webui_test_support',
         '../v8/tools/gyp/v8.gyp:v8',
         '../webkit/plugins/webkit_plugins.gyp:test_mock_plugin_list',
         # Runtime dependencies
@@ -1190,7 +1166,7 @@
         'browser/app_controller_mac_browsertest.mm',
         'browser/autocomplete/autocomplete_browsertest.cc',
         'browser/autofill/autofill_browsertest.cc',
-        'browser/autofill/autofill_external_delegate_browsertest.cc',
+        'browser/autofill/autofill_driver_impl_browsertest.cc',
         'browser/autofill/form_structure_browsertest.cc',
         'browser/autofill/risk/fingerprint_browsertest.cc',
         'browser/browser_encoding_browsertest.cc',
@@ -1208,6 +1184,7 @@
         'browser/chromeos/accessibility/accessibility_manager_browsertest.cc',
         'browser/chromeos/accessibility/magnification_manager_browsertest.cc',
         'browser/chromeos/app_mode/kiosk_app_manager_browsertest.cc',
+        'browser/chromeos/app_mode/kiosk_app_update_service_browsertest.cc',
         'browser/chromeos/cros/cros_in_process_browser_test.cc',
         'browser/chromeos/cros/cros_in_process_browser_test.h',
         'browser/chromeos/cros/cros_mock.cc',
@@ -1267,6 +1244,7 @@
         'browser/chromeos/policy/device_policy_cros_browser_test.cc',
         'browser/chromeos/policy/device_policy_cros_browser_test.h',
         'browser/chromeos/policy/device_status_collector_browsertest.cc',
+        'browser/chromeos/policy/login_screen_default_policy_browsertest.cc',
         'browser/chromeos/policy/policy_cert_verifier_browsertest.cc',
         'browser/chromeos/policy/power_policy_browsertest.cc',
         'browser/chromeos/policy/variations_service_policy_browsertest.cc',
@@ -1328,7 +1306,6 @@
         'browser/extensions/api/identity/identity_apitest.cc',
         'browser/extensions/api/idle/idle_apitest.cc',
         'browser/extensions/api/idltest/idltest_apitest.cc',
-        'browser/extensions/api/input/input_apitest.cc',
         'browser/extensions/api/input_ime/input_ime_apitest_chromeos.cc',
         'browser/extensions/api/management/management_api_browsertest.cc',
         'browser/extensions/api/management/management_apitest.cc',
@@ -1378,6 +1355,7 @@
         'browser/extensions/api/webstore_private/webstore_private_apitest.cc',
         'browser/extensions/app_background_page_apitest.cc',
         'browser/extensions/app_process_apitest.cc',
+        'browser/extensions/background_app_browsertest.cc',
         'browser/extensions/background_page_apitest.cc',
         'browser/extensions/background_scripts_apitest.cc',
         'browser/extensions/chrome_app_api_browsertest.cc',
@@ -1440,6 +1418,7 @@
         'browser/extensions/stubs_apitest.cc',
         'browser/extensions/subscribe_page_action_browsertest.cc',
         'browser/extensions/api/system_private/system_private_apitest.cc',
+        'browser/extensions/window_controls_browsertest.cc',
         'browser/extensions/web_contents_browsertest.cc',
         'browser/extensions/web_view_browsertest.cc',
         'browser/extensions/webstore_startup_installer_browsertest.cc',
@@ -1458,7 +1437,6 @@
         'browser/importer/ie_importer_browsertest_win.cc',
         'browser/importer/importer_unittest_utils.cc',
         'browser/importer/importer_unittest_utils.h',
-        'browser/importer/toolbar_importer_utils_browsertest.cc',
         'browser/infobars/infobar_extension_apitest.cc',
         'browser/infobars/infobars_browsertest.cc',
         'browser/loadtimes_extension_bindings_browsertest.cc',
@@ -1467,7 +1445,10 @@
         'browser/managed_mode/managed_mode_browsertest.cc',
         'browser/managed_mode/managed_mode_resource_throttle_browsertest.cc',
         'browser/managed_mode/managed_user_service_browsertest.cc',
+        'browser/media/chrome_media_stream_infobar_browsertest.cc',
         'browser/media/chrome_webrtc_browsertest.cc',
+        'browser/media/chrome_webrtc_video_quality_browsertest.cc',
+        'browser/media_galleries/fileapi/itunes_finder_win_browsertest.cc',
         'browser/media_galleries/fileapi/media_file_validator_unittest.cc',
         'browser/media_galleries/media_galleries_dialog_controller_mock.cc',
         'browser/media_galleries/media_galleries_dialog_controller_mock.h',
@@ -1505,6 +1486,7 @@
         'browser/profiles/avatar_menu_model_browsertest.cc',
         'browser/profiles/profile_browsertest.cc',
         'browser/profiles/profile_manager_browsertest.cc',
+        'browser/profile_resetter/profile_resetter_browsertest.cc',
         'browser/referrer_policy_browsertest.cc',
         'browser/renderer_host/render_process_host_chrome_browsertest.cc',
         'browser/renderer_host/web_cache_manager_browsertest.cc',
@@ -1611,6 +1593,7 @@
         'browser/ui/views/frame/app_non_client_frame_view_ash_browsertest.cc',
         'browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc',
         'browser/ui/views/frame/immersive_mode_controller_ash_browsertest.cc',
+        'browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc',
         'browser/ui/views/select_file_dialog_extension_browsertest.cc',
         'browser/ui/views/sync/one_click_signin_bubble_view_browsertest.cc',
         'browser/ui/views/toolbar_view_browsertest.cc',
@@ -1637,6 +1620,7 @@
         'browser/ui/webui/options/browser_options_browsertest.js',
         'browser/ui/webui/options/certificate_manager_browsertest.cc',
         'browser/ui/webui/options/certificate_manager_browsertest.js',
+        'browser/ui/webui/options/chromeos/accounts_options_browsertest.js',
         'browser/ui/webui/options/chromeos/bluetooth_options_browsertest.js',
         'browser/ui/webui/options/chromeos/guest_mode_options_ui_browsertest.cc',
         'browser/ui/webui/options/content_options_browsertest.js',
@@ -1654,6 +1638,7 @@
         'browser/ui/webui/options/preferences_browsertest.cc',
         'browser/ui/webui/options/preferences_browsertest.h',
         'browser/ui/webui/options/search_engine_manager_browsertest.js',
+        'browser/ui/webui/options/settings_app_browsertest.js',
         'browser/ui/webui/options/settings_format_browsertest.js',
         'browser/ui/webui/policy_ui_browsertest.cc',
         'browser/ui/webui/print_preview/print_preview_ui_browsertest.cc',
@@ -1681,7 +1666,6 @@
         'test/base/chrome_render_view_test.cc',
         'test/base/chrome_render_view_test.h',
         'test/base/chrome_test_launcher.cc',
-        'test/base/empty_browser_test.cc',
         'test/base/web_ui_browsertest.cc',
         'test/base/web_ui_browsertest.h',
         'test/data/chromeos/oobe_webui_browsertest.js',
@@ -1723,6 +1707,7 @@
         'test/data/webui/print_preview.h',
         'test/data/webui/print_preview.js',
         'test/data/webui/sandboxstatus_browsertest.js',
+        'test/data/webui/webui_resource_browsertest.cc',
         'test/gpu/gpu_feature_browsertest.cc',
         'test/gpu/webgl_infobar_browsertest.cc',
         'test/ppapi/ppapi_browsertest.cc',
@@ -2048,7 +2033,6 @@
         }, { # else: toolkit_views == 0
           'sources/': [
             ['exclude', '^../ui/views/'],
-            ['exclude', '^browser/extensions/api/input/input_apitest.cc'],
             ['exclude', '^browser/ui/views/'],
           ],
         }],
@@ -2122,7 +2106,6 @@
         'test/base/chrome_test_launcher.cc',
         'test/perf/browser_perf_test.cc',
         'test/perf/browser_perf_test.h',
-        'test/perf/rendering/latency_tests.cc',
         'test/perf/rendering/throughput_tests.cc',
       ],
       'rules': [
@@ -3160,7 +3143,7 @@
                 '../crypto/crypto.gyp:crypto_unittests',
                 '../jingle/jingle.gyp:jingle_unittests',
                 '../net/net.gyp:net_perftests',
-                '../third_party/WebKit/Source/WebKit/chromium/WebKitUnitTests.gyp:webkit_unit_tests',
+                '../third_party/WebKit/public/all.gyp:all_blink',
                 '../url/url.gyp:googleurl_unittests',
                 'browser_tests',
                 'chromedriver_unittests',
@@ -3396,5 +3379,21 @@
         },
       ],
     }],
+    [ 'enable_mdns == 1', {
+      'targets': [{
+          'target_name': 'service_discovery_sniffer',
+          'type': 'executable',
+          'dependencies': [
+            '../net/net.gyp:net',
+            'browser',
+            '../base/base.gyp:base',
+            '../base/base.gyp:test_support_base',
+          ],
+          'sources': [
+            'tools/service_discovery_sniffer/service_discovery_sniffer.h',
+            'tools/service_discovery_sniffer/service_discovery_sniffer.cc',
+          ],
+        }]
+    }],
   ],  # 'conditions'
 }
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi
index f2ebd30..692254d 100644
--- a/chrome/chrome_tests_unit.gypi
+++ b/chrome/chrome_tests_unit.gypi
@@ -108,8 +108,6 @@
         'browser/download/test_download_shelf.h',
         'browser/drive/dummy_drive_service.cc',
         'browser/drive/dummy_drive_service.h',
-        'browser/drive/mock_drive_service.cc',
-        'browser/drive/mock_drive_service.h',
         'browser/drive/fake_drive_service.cc',
         'browser/drive/fake_drive_service.h',
         'browser/extensions/api/messaging/native_messaging_test_util.cc',
@@ -132,8 +130,6 @@
         'browser/extensions/test_management_policy.h',
         'browser/google_apis/test_util.cc',
         'browser/google_apis/test_util.h',
-        'browser/media_galleries/fileapi/picasa/pmp_test_helper.cc',
-        'browser/media_galleries/fileapi/picasa/pmp_test_helper.h',
         'browser/media_galleries/media_galleries_test_util.cc',
         'browser/media_galleries/media_galleries_test_util.h',
         'browser/net/url_request_mock_util.cc',
@@ -158,6 +154,8 @@
         'browser/policy/test/local_policy_test_server.h',
         'browser/prefs/pref_service_mock_builder.cc',
         'browser/prefs/pref_service_mock_builder.h',
+        'browser/profile_resetter/profile_resetter_test_base.cc',
+        'browser/profile_resetter/profile_resetter_test_base.h',
         'browser/search_engines/template_url_service_test_util.cc',
         'browser/search_engines/template_url_service_test_util.h',
         'browser/sessions/session_service_test_helper.cc',
@@ -226,8 +224,6 @@
         'test/base/in_process_browser_test.h',
         'test/base/javascript_test_observer.cc',
         'test/base/javascript_test_observer.h',
-        'test/base/model_test_utils.cc',
-        'test/base/model_test_utils.h',
         'test/base/module_system_test.cc',
         'test/base/module_system_test.h',
         'test/base/profile_mock.cc',
@@ -273,20 +269,20 @@
 
         # TODO(joi): Move to //components/components.gypi once
         # remaining dependencies back to //chrome are eliminated.
-        '../components/autofill/browser/android/test_auxiliary_profile_loader_android.cc',
-        '../components/autofill/browser/android/test_auxiliary_profile_loader_android.h',
-        '../components/autofill/browser/autofill_common_test.cc',
-        '../components/autofill/browser/autofill_common_test.h',
-        '../components/autofill/browser/data_driven_test.cc',
-        '../components/autofill/browser/data_driven_test.h',
-        '../components/autofill/browser/test_autofill_driver.cc',
-        '../components/autofill/browser/test_autofill_driver.h',
-        '../components/autofill/browser/test_autofill_external_delegate.cc',
-        '../components/autofill/browser/test_autofill_external_delegate.h',
-        '../components/autofill/browser/test_autofill_manager_delegate.cc',
-        '../components/autofill/browser/test_autofill_manager_delegate.h',
-        '../components/autofill/browser/test_personal_data_manager.cc',
-        '../components/autofill/browser/test_personal_data_manager.h',
+        '../components/autofill/core/browser/android/test_auxiliary_profile_loader_android.cc',
+        '../components/autofill/core/browser/android/test_auxiliary_profile_loader_android.h',
+        '../components/autofill/core/browser/autofill_common_test.cc',
+        '../components/autofill/core/browser/autofill_common_test.h',
+        '../components/autofill/core/browser/data_driven_test.cc',
+        '../components/autofill/core/browser/data_driven_test.h',
+        '../components/autofill/core/browser/test_autofill_driver.cc',
+        '../components/autofill/core/browser/test_autofill_driver.h',
+        '../components/autofill/core/browser/test_autofill_external_delegate.cc',
+        '../components/autofill/core/browser/test_autofill_external_delegate.h',
+        '../components/autofill/core/browser/test_autofill_manager_delegate.cc',
+        '../components/autofill/core/browser/test_autofill_manager_delegate.h',
+        '../components/autofill/core/browser/test_personal_data_manager.cc',
+        '../components/autofill/core/browser/test_personal_data_manager.h',
 
         '../ui/gfx/image/image_unittest_util.h',
         '../ui/gfx/image/image_unittest_util.cc',
@@ -375,6 +371,20 @@
           'include_dirs': [
             '<(DEPTH)/third_party/wtl/include',
           ],
+          'conditions': [
+            ['use_aura==1', {
+              'dependencies': [
+                '../win8/win8.gyp:test_registrar_constants',
+                '../win8/win8.gyp:test_support_win8',
+              ],
+            }],
+          ],
+        }],
+        ['OS=="win" or OS=="mac"', {
+          'sources': [
+            'utility/media_galleries/pmp_test_helper.cc',
+            'utility/media_galleries/pmp_test_helper.h',
+          ],
         }],
       ],
     },
@@ -437,6 +447,7 @@
         'test_support_common',
         'test_support_unit',
         # 3) anything tests directly depend on
+        '../courgette/courgette.gyp:courgette_lib',
         '../google_apis/google_apis.gyp:google_apis',
         '../skia/skia.gyp:skia',
         '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation',
@@ -515,8 +526,6 @@
         'browser/background/background_mode_manager_unittest.cc',
         'browser/bookmarks/bookmark_codec_unittest.cc',
         'browser/bookmarks/bookmark_expanded_state_tracker_unittest.cc',
-        'browser/bookmarks/bookmark_html_reader_unittest.cc',
-        'browser/bookmarks/bookmark_html_writer_unittest.cc',
         'browser/bookmarks/bookmark_index_unittest.cc',
         'browser/bookmarks/bookmark_model_test_utils.cc',
         'browser/bookmarks/bookmark_model_test_utils.h',
@@ -604,14 +613,13 @@
         'browser/chromeos/drive/file_system/remove_operation_unittest.cc',
         'browser/chromeos/drive/file_system/search_operation_unittest.cc',
         'browser/chromeos/drive/file_system/touch_operation_unittest.cc',
+        'browser/chromeos/drive/file_system/truncate_operation_unittest.cc',
         'browser/chromeos/drive/file_system/update_operation_unittest.cc',
         'browser/chromeos/drive/file_system_util_unittest.cc',
         'browser/chromeos/drive/file_write_helper_unittest.cc',
         'browser/chromeos/drive/job_queue_unittest.cc',
         'browser/chromeos/drive/job_scheduler_unittest.cc',
         'browser/chromeos/drive/local_file_reader_unittest.cc',
-        'browser/chromeos/drive/mock_directory_change_observer.cc',
-        'browser/chromeos/drive/mock_directory_change_observer.h',
         'browser/chromeos/drive/remove_stale_cache_files_unittest.cc',
         'browser/chromeos/drive/resource_entry_conversion_unittest.cc',
         'browser/chromeos/drive/resource_metadata_storage_unittest.cc',
@@ -626,6 +634,8 @@
         'browser/chromeos/extensions/file_manager/file_manager_notifications_unittest.cc',
         'browser/chromeos/extensions/wallpaper_private_api_unittest.cc',
         'browser/chromeos/external_metrics_unittest.cc',
+        'browser/chromeos/fileapi/cros_mount_point_provider_unittest.cc',
+        'browser/chromeos/fileapi/file_access_permissions_unittest.cc',
         'browser/chromeos/imageburner/burn_device_handler_unittest.cc',
         'browser/chromeos/imageburner/burn_manager_unittest.cc',
         'browser/chromeos/input_method/browser_state_monitor_unittest.cc',
@@ -638,6 +648,7 @@
         'browser/chromeos/input_method/input_method_manager_impl_unittest.cc',
         'browser/chromeos/input_method/input_method_persistence_unittest.cc',
         'browser/chromeos/input_method/input_method_util_unittest.cc',
+        'browser/chromeos/keyboard_driven_event_rewriter_unittest.cc',
         'browser/chromeos/kiosk_mode/kiosk_mode_idle_logout_unittest.cc',
         'browser/chromeos/kiosk_mode/kiosk_mode_settings_unittest.cc',
         'browser/chromeos/language_preferences_unittest.cc',
@@ -665,6 +676,7 @@
         'browser/chromeos/policy/enterprise_install_attributes_unittest.cc',
         'browser/chromeos/policy/network_configuration_updater_impl_cros_unittest.cc',
         'browser/chromeos/policy/proxy_policy_provider_unittest.cc',
+        'browser/chromeos/policy/recommendation_restorer_unittest.cc',
         'browser/chromeos/policy/user_cloud_policy_manager_chromeos_unittest.cc',
         'browser/chromeos/policy/user_cloud_policy_store_chromeos_unittest.cc',
         'browser/chromeos/preferences_unittest.cc',
@@ -685,7 +697,12 @@
         'browser/chromeos/web_socket_proxy_helper_unittest.cc',
         'browser/command_updater_unittest.cc',
         'browser/component_updater/test/component_installers_unittest.cc',
+        'browser/component_updater/test/component_patcher_mock.h',
+        'browser/component_updater/test/component_patcher_unittest.cc',
+        'browser/component_updater/test/component_patcher_unittest_win.cc',
         'browser/component_updater/test/component_updater_service_unittest.cc',
+        'browser/component_updater/test/component_updater_service_unittest_win.cc',
+        'browser/component_updater/test/test_installer.cc',
         'browser/content_settings/content_settings_default_provider_unittest.cc',
         'browser/content_settings/content_settings_mock_observer.cc',
         'browser/content_settings/content_settings_mock_observer.h',
@@ -716,7 +733,9 @@
         'browser/download/download_status_updater_unittest.cc',
         'browser/download/download_target_determiner_unittest.cc',
         'browser/download/download_ui_controller_unittest.cc',
+        'browser/drive/drive_api_util_unittest.cc',
         'browser/drive/drive_uploader_unittest.cc',
+        'browser/drive/event_logger_unittest.cc',
         'browser/drive/fake_drive_service_unittest.cc',
         'browser/enumerate_modules_model_unittest_win.cc',
         'browser/extensions/active_tab_unittest.cc',
@@ -858,8 +877,6 @@
         'browser/google_apis/drive_api_requests_unittest.cc',
         'browser/google_apis/drive_api_parser_unittest.cc',
         'browser/google_apis/drive_api_url_generator_unittest.cc',
-        'browser/google_apis/drive_api_util_unittest.cc',
-        'browser/google_apis/event_logger_unittest.cc',
         'browser/google_apis/gdata_wapi_parser_unittest.cc',
         'browser/google_apis/gdata_wapi_requests_unittest.cc',
         'browser/google_apis/gdata_wapi_url_generator_unittest.cc',
@@ -901,6 +918,8 @@
         'browser/history/visit_database_unittest.cc',
         'browser/history/visit_filter_unittest.cc',
         'browser/history/visit_tracker_unittest.cc',
+        'browser/importer/bookmark_html_reader_unittest.cc',
+        'browser/importer/bookmark_html_writer_unittest.cc',
         'browser/importer/firefox_importer_unittest.cc',
         'browser/importer/firefox_importer_unittest_messages_internal.h',
         'browser/importer/firefox_importer_unittest_utils.h',
@@ -911,11 +930,10 @@
         'browser/importer/ie_importer_unittest_win.cc',
         'browser/importer/profile_writer_unittest.cc',
         'browser/importer/safari_importer_unittest.mm',
-        'browser/importer/toolbar_importer_unittest.cc',
         'browser/internal_auth_unittest.cc',
-        'browser/invalidation/invalidation_frontend_test_template.cc',
-        'browser/invalidation/invalidation_frontend_test_template.h',
         'browser/invalidation/invalidation_service_android_unittest.cc',
+        'browser/invalidation/invalidation_service_test_template.cc',
+        'browser/invalidation/invalidation_service_test_template.h',
         'browser/invalidation/invalidator_storage_unittest.cc',
         'browser/invalidation/ticl_invalidation_service_unittest.cc',
         'browser/language_usage_metrics_unittest.cc',
@@ -925,15 +943,10 @@
         'browser/managed_mode/managed_user_registration_service_unittest.cc',
         'browser/managed_mode/managed_user_service_unittest.cc',
         'browser/managed_mode/managed_user_refresh_token_fetcher_unittest.cc',
-        'browser/media_galleries/fileapi/itunes_finder_win_unittest.cc',
-        'browser/media_galleries/fileapi/itunes_library_parser_unittest.cc',
         'browser/media_galleries/fileapi/native_media_file_util_unittest.cc',
-        'browser/media_galleries/fileapi/picasa/picasa_album_table_reader_unittest.cc',
-        'browser/media_galleries/fileapi/picasa/picasa_file_util_unittest.cc',
-        'browser/media_galleries/fileapi/picasa/pmp_column_reader_unittest.cc',
-        'browser/media_galleries/fileapi/picasa/pmp_table_reader_unittest.cc',
         'browser/media_galleries/linux/mtp_device_object_enumerator_unittest.cc',
         'browser/media_galleries/mac/mtp_device_delegate_impl_mac_unittest.mm',
+        'browser/media_galleries/win/mtp_device_delegate_impl_win_unittest.cc',
         'browser/media_galleries/media_file_system_registry_unittest.cc',
         'browser/media_galleries/media_galleries_dialog_controller_mock.cc',
         'browser/media_galleries/media_galleries_dialog_controller_mock.h',
@@ -947,6 +960,7 @@
         'browser/metrics/thread_watcher_unittest.cc',
         'browser/metrics/time_ticks_experiment_unittest.cc',
         'browser/metrics/variations/variations_service_unittest.cc',
+        'browser/metrics/variations/variations_request_scheduler_unittest.cc',
         'browser/nacl_host/nacl_file_host_unittest.cc',
         'browser/nacl_host/nacl_validation_cache_unittest.cc',
         'browser/nacl_host/pnacl_translation_cache_unittest.cc',
@@ -959,7 +973,6 @@
         'browser/net/gaia/gaia_oauth_fetcher_unittest.cc',
         'browser/net/http_pipelining_compatibility_client_unittest.cc',
         'browser/net/http_server_properties_manager_unittest.cc',
-        'browser/net/net_log_logger_unittest.cc',
         'browser/net/net_log_temp_file_unittest.cc',
         'browser/net/network_stats_unittest.cc',
         'browser/net/network_time_tracker_unittest.cc',
@@ -972,6 +985,7 @@
         'browser/net/url_fixer_upper_unittest.cc',
         'browser/net/url_info_unittest.cc',
         'browser/notifications/desktop_notification_service_unittest.cc',
+        'browser/notifications/message_center_notifications_unittest_win.cc',
         'browser/notifications/notification_audio_controller_unittest.cc',
         'browser/notifications/sync_notifier/chrome_notifier_service_unittest.cc',
         'browser/notifications/sync_notifier/synced_notification_unittest.cc',
@@ -1057,7 +1071,6 @@
         'browser/prerender/prerender_unittest.cc',
         'browser/prerender/prerender_util_unittest.cc',
         'browser/printing/cloud_print/cloud_print_proxy_service_unittest.cc',
-        'browser/printing/cloud_print/cloud_print_setup_source_unittest.cc',
         'browser/printing/print_dialog_cloud_unittest.cc',
         'browser/printing/print_job_unittest.cc',
         'browser/printing/print_preview_dialog_controller_unittest.cc',
@@ -1074,10 +1087,14 @@
         'browser/profiles/profile_info_cache_unittest.cc',
         'browser/profiles/profile_info_cache_unittest.h',
         'browser/profiles/profile_info_util_unittest.cc',
+        'browser/profiles/profile_loader_unittest.cc',
         'browser/profiles/profile_manager_unittest.cc',
         'browser/profiles/profile_shortcut_manager_unittest_win.cc',
         'browser/renderer_host/plugin_info_message_filter_unittest.cc',
         'browser/renderer_host/web_cache_manager_unittest.cc',
+        'browser/resources/google_now/background.js',
+        'browser/resources/google_now/background_test_util.js',
+        'browser/resources/google_now/background_unittest.gtestjs',
         'browser/resources/print_preview/data/measurement_system.js',
         'browser/resources/print_preview/data/measurement_system_unittest.gtestjs',
         'browser/resources/print_preview/print_preview_utils.js',
@@ -1121,6 +1138,8 @@
         'browser/sessions/session_backend_unittest.cc',
         'browser/sessions/session_service_unittest.cc',
         'browser/sessions/session_types_unittest.cc',
+        'browser/local_discovery/local_domain_resolver_unittest.cc',
+        'browser/local_discovery/service_discovery_client_unittest.cc',
         'browser/shell_integration_unittest.cc',
         'browser/shell_integration_win_unittest.cc',
         'browser/signin/fake_auth_status_provider.cc',
@@ -1175,8 +1194,6 @@
         'browser/sync/abstract_profile_sync_service_test.cc',
         'browser/sync/abstract_profile_sync_service_test.h',
         'browser/sync/backend_migrator_unittest.cc',
-        'browser/sync/glue/android_invalidator_bridge_proxy_unittest.cc',
-        'browser/sync/glue/android_invalidator_bridge_unittest.cc',
         'browser/sync/glue/autofill_data_type_controller_unittest.cc',
         'browser/sync/glue/bookmark_data_type_controller_unittest.cc',
         'browser/sync/glue/browser_thread_model_worker_unittest.cc',
@@ -1243,12 +1260,14 @@
         'browser/sync/test/test_http_bridge_factory.h',
         'browser/sync/test_profile_sync_service.cc',
         'browser/sync/test_profile_sync_service.h',
-        'browser/sync_file_system/drive/api_util_unittest.cc',
-        'browser/sync_file_system/drive/fake_api_util.cc',
-        'browser/sync_file_system/drive/fake_api_util.h',
-        'browser/sync_file_system/drive/fake_api_util_unittest.cc',
-        'browser/sync_file_system/drive/metadata_db_migration_util_unittest.cc',
-        'browser/sync_file_system/drive_file_sync_service_mock_unittest.cc',
+        'browser/sync_file_system/drive_backend/api_util_unittest.cc',
+        'browser/sync_file_system/drive_backend/fake_api_util.cc',
+        'browser/sync_file_system/drive_backend/fake_api_util.h',
+        'browser/sync_file_system/drive_backend/fake_api_util_unittest.cc',
+        'browser/sync_file_system/drive_backend/fake_drive_service_helper.cc',
+        'browser/sync_file_system/drive_backend/fake_drive_service_helper.h',
+        'browser/sync_file_system/drive_backend/metadata_db_migration_util_unittest.cc',
+        'browser/sync_file_system/drive_file_sync_service_fake_unittest.cc',
         'browser/sync_file_system/drive_file_sync_service_sync_unittest.cc',
         'browser/sync_file_system/drive_file_sync_service_unittest.cc',
         'browser/sync_file_system/drive_metadata_store_unittest.cc',
@@ -1284,6 +1303,7 @@
         'browser/thumbnails/thumbnail_service_unittest.cc',
         'browser/translate/translate_browser_metrics_unittest.cc',
         'browser/translate/translate_manager_unittest.cc',
+        'browser/translate/translate_prefs_unittest.cc',
         'browser/ui/android/tab_model/tab_model_unittest.cc',
         'browser/ui/ash/event_rewriter_unittest.cc',
         'browser/ui/ash/ime_controller_chromeos_unittest.cc',
@@ -1303,6 +1323,7 @@
         'browser/ui/autofill/mock_autofill_dialog_controller.cc',
         'browser/ui/autofill/mock_autofill_dialog_controller.h',
         'browser/ui/bookmarks/bookmark_context_menu_controller_unittest.cc',
+        'browser/ui/bookmarks/bookmark_editor_unittest.cc',
         'browser/ui/bookmarks/bookmark_prompt_controller_unittest.cc',
         'browser/ui/bookmarks/bookmark_ui_utils_unittest.cc',
         'browser/ui/bookmarks/bookmark_unittest.cc',
@@ -1326,6 +1347,9 @@
         'browser/ui/cocoa/autofill/autofill_account_chooser_unittest.mm',
         'browser/ui/cocoa/autofill/autofill_details_container_unittest.mm',
         'browser/ui/cocoa/autofill/autofill_main_container_unittest.mm',
+        'browser/ui/cocoa/autofill/autofill_notification_container_unittest.mm',
+        'browser/ui/cocoa/autofill/autofill_notification_controller_unittest.mm',
+        'browser/ui/cocoa/autofill/autofill_pop_up_button_unittest.mm',
         'browser/ui/cocoa/autofill/autofill_textfield_unittest.mm',
         'browser/ui/cocoa/autofill/autofill_section_container_unittest.mm',
         'browser/ui/cocoa/autofill/autofill_section_view_unittest.mm',
@@ -1440,6 +1464,9 @@
         'browser/ui/cocoa/notifications/message_center_tray_bridge_unittest.mm',
         'browser/ui/cocoa/nsmenuitem_additions_unittest.mm',
         'browser/ui/cocoa/nsview_additions_unittest.mm',
+        'browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm',
+        'browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm',
+        'browser/ui/cocoa/omnibox/omnibox_popup_separator_view_unittest.mm',
         'browser/ui/cocoa/omnibox/omnibox_popup_view_mac_unittest.mm',
         'browser/ui/cocoa/omnibox/omnibox_view_mac_unittest.mm',
         'browser/ui/cocoa/one_click_signin_bubble_controller_unittest.mm',
@@ -1452,7 +1479,6 @@
         'browser/ui/cocoa/styled_text_field_test_helper.h',
         'browser/ui/cocoa/styled_text_field_test_helper.mm',
         'browser/ui/cocoa/styled_text_field_unittest.mm',
-        'browser/ui/cocoa/tab_contents/overlay_separator_view_unittest.mm',
         'browser/ui/cocoa/tab_contents/sad_tab_controller_unittest.mm',
         'browser/ui/cocoa/tab_contents/sad_tab_view_unittest.mm',
         'browser/ui/cocoa/table_row_nsimage_cache_unittest.mm',
@@ -1510,6 +1536,7 @@
         'browser/ui/search/instant_controller_unittest.cc',
         'browser/ui/search/instant_page_unittest.cc',
         'browser/ui/search/search_delegate_unittest.cc',
+        'browser/ui/search/search_model_unittest.cc',
         'browser/ui/startup/session_crashed_infobar_delegate_unittest.cc',
         'browser/ui/sync/one_click_signin_helper_unittest.cc',
         'browser/ui/sync/profile_signin_confirmation_helper_unittest.cc',
@@ -1541,6 +1568,7 @@
         'browser/ui/views/bookmarks/bookmark_bar_view_unittest.cc',
         'browser/ui/views/bookmarks/bookmark_context_menu_test.cc',
         'browser/ui/views/bookmarks/bookmark_editor_view_unittest.cc',
+        'browser/ui/views/bookmarks/bookmark_menu_delegate_unittest.cc',
         'browser/ui/views/confirm_bubble_views_unittest.cc',
         'browser/ui/views/crypto_module_password_dialog_view_unittest.cc',
         'browser/ui/views/extensions/browser_action_drag_data_unittest.cc',
@@ -1577,6 +1605,7 @@
         'browser/ui/window_sizer/window_sizer_common_unittest.cc',
         'browser/ui/window_sizer/window_sizer_unittest.cc',
         'browser/ui/zoom/zoom_controller_unittest.cc',
+        'browser/upload_list_unittest.cc',
         'browser/chrome_to_mobile_service_unittest.cc',
         'browser/user_style_sheet_watcher_unittest.cc',
         'browser/value_store/leveldb_value_store_unittest.cc',
@@ -1617,7 +1646,6 @@
         'common/extensions/extension_file_util_unittest.cc',
         'common/extensions/extension_icon_set_unittest.cc',
         'common/extensions/extension_l10n_util_unittest.cc',
-        'common/extensions/extension_localization_peer_unittest.cc',
         'common/extensions/extension_set_unittest.cc',
         'common/extensions/extension_unittest.cc',
         'common/extensions/feature_switch_unittest.cc',
@@ -1634,6 +1662,7 @@
         'common/extensions/manifest_tests/extension_manifests_contentsecuritypolicy_unittest.cc',
         'common/extensions/manifest_tests/extension_manifests_default_extent_path_unittest.cc',
         'common/extensions/manifest_tests/extension_manifests_devtools_unittest.cc',
+        'common/extensions/manifest_tests/extension_manifests_dummy_unittest.cc',
         'common/extensions/manifest_tests/extension_manifests_experimental_unittest.cc',
         'common/extensions/manifest_tests/extension_manifests_homepage_unittest.cc',
         'common/extensions/manifest_tests/extension_manifests_icons_unittest.cc',
@@ -1703,10 +1732,12 @@
         'renderer/content_settings_observer_unittest.cc',
         'renderer/extensions/chrome_v8_context_set_unittest.cc',
         'renderer/extensions/event_unittest.cc',
+        'renderer/extensions/extension_localization_peer_unittest.cc',
         'renderer/extensions/json_schema_unittest.cc',
         'renderer/extensions/module_system_unittest.cc',
         'renderer/extensions/renderer_permissions_policy_delegate_unittest.cc',
-        'renderer/media/webrtc_logging_handler_impl_unittest.cc',
+        'renderer/extensions/safe_builtins_unittest.cc',
+        'renderer/media/chrome_webrtc_log_message_delegate_unittest.cc',
         'renderer/net/predictor_queue_unittest.cc',
         'renderer/net/renderer_predictor_unittest.cc',
         'renderer/plugins/plugin_uma_unittest.cc',
@@ -1753,42 +1784,12 @@
         # unit_tests than in base_unittests.
         '../base/path_service_unittest.cc',
 
-        # TODO(joi): Move to //components/components.gypi once
+        # TODO(joi): Move to //components/components_tests.gypi once
         # remaining dependencies back to //chrome are eliminated.
-        '../components/autofill/browser/address_field_unittest.cc',
-        '../components/autofill/browser/address_unittest.cc',
-        '../components/autofill/browser/android/auxiliary_profile_unittest_android.cc',
-        '../components/autofill/browser/autocomplete_history_manager_unittest.cc',
-        '../components/autofill/browser/autofill_country_unittest.cc',
-        '../components/autofill/browser/autofill_data_model_unittest.cc',
-        '../components/autofill/browser/autofill_download_unittest.cc',
-        '../components/autofill/browser/autofill_download_url_unittest.cc',
-        '../components/autofill/browser/autofill_external_delegate_unittest.cc',
-        '../components/autofill/browser/autofill_field_unittest.cc',
-        '../components/autofill/browser/autofill_ie_toolbar_import_win_unittest.cc',
-        '../components/autofill/browser/autofill_manager_unittest.cc',
-        '../components/autofill/browser/autofill_merge_unittest.cc',
-        '../components/autofill/browser/autofill_metrics_unittest.cc',
-        '../components/autofill/browser/autofill_profile_unittest.cc',
-        '../components/autofill/browser/autofill_regexes_unittest.cc',
-        '../components/autofill/browser/autofill_type_unittest.cc',
-        '../components/autofill/browser/autofill_xml_parser_unittest.cc',
-        '../components/autofill/browser/contact_info_unittest.cc',
-        '../components/autofill/browser/credit_card_field_unittest.cc',
-        '../components/autofill/browser/credit_card_unittest.cc',
-        '../components/autofill/browser/form_field_unittest.cc',
-        '../components/autofill/browser/form_structure_unittest.cc',
-        '../components/autofill/browser/name_field_unittest.cc',
-        '../components/autofill/browser/password_autofill_manager_unittest.cc',
-        '../components/autofill/browser/password_generator_unittest.cc',
-        '../components/autofill/browser/personal_data_manager_unittest.cc',
-        '../components/autofill/browser/phone_field_unittest.cc',
-        '../components/autofill/browser/phone_number_unittest.cc',
-        '../components/autofill/browser/phone_number_i18n_unittest.cc',
-        '../components/autofill/browser/validation_unittest.cc',
         '../components/autofill/content/browser/autocheckout/whitelist_manager_unittest.cc',
         '../components/autofill/content/browser/autocheckout_manager_unittest.cc',
         '../components/autofill/content/browser/autocheckout_page_meta_data_unittest.cc',
+        '../components/autofill/content/browser/autofill_driver_impl_unittest.cc',
         '../components/autofill/content/browser/wallet/encryption_escrow_client_unittest.cc',
         '../components/autofill/content/browser/wallet/full_wallet_unittest.cc',
         '../components/autofill/content/browser/wallet/instrument_unittest.cc',
@@ -1797,12 +1798,44 @@
         '../components/autofill/content/browser/wallet/wallet_items_unittest.cc',
         '../components/autofill/content/browser/wallet/wallet_service_url_unittest.cc',
         '../components/autofill/content/browser/wallet/wallet_signin_helper_unittest.cc',
+        '../components/autofill/core/browser/address_field_unittest.cc',
+        '../components/autofill/core/browser/address_unittest.cc',
+        '../components/autofill/core/browser/android/auxiliary_profile_unittest_android.cc',
+        '../components/autofill/core/browser/autocomplete_history_manager_unittest.cc',
+        '../components/autofill/core/browser/autofill_country_unittest.cc',
+        '../components/autofill/core/browser/autofill_data_model_unittest.cc',
+        '../components/autofill/core/browser/autofill_download_unittest.cc',
+        '../components/autofill/core/browser/autofill_download_url_unittest.cc',
+        '../components/autofill/core/browser/autofill_external_delegate_unittest.cc',
+        '../components/autofill/core/browser/autofill_field_unittest.cc',
+        '../components/autofill/core/browser/autofill_ie_toolbar_import_win_unittest.cc',
+        '../components/autofill/core/browser/autofill_manager_unittest.cc',
+        '../components/autofill/core/browser/autofill_merge_unittest.cc',
+        '../components/autofill/core/browser/autofill_metrics_unittest.cc',
+        '../components/autofill/core/browser/autofill_profile_unittest.cc',
+        '../components/autofill/core/browser/autofill_regexes_unittest.cc',
+        '../components/autofill/core/browser/autofill_type_unittest.cc',
+        '../components/autofill/core/browser/autofill_xml_parser_unittest.cc',
+        '../components/autofill/core/browser/contact_info_unittest.cc',
+        '../components/autofill/core/browser/credit_card_field_unittest.cc',
+        '../components/autofill/core/browser/credit_card_unittest.cc',
+        '../components/autofill/core/browser/form_field_unittest.cc',
+        '../components/autofill/core/browser/form_structure_unittest.cc',
+        '../components/autofill/core/browser/name_field_unittest.cc',
+        '../components/autofill/core/browser/password_autofill_manager_unittest.cc',
+        '../components/autofill/core/browser/password_generator_unittest.cc',
+        '../components/autofill/core/browser/personal_data_manager_unittest.cc',
+        '../components/autofill/core/browser/phone_field_unittest.cc',
+        '../components/autofill/core/browser/phone_number_unittest.cc',
+        '../components/autofill/core/browser/phone_number_i18n_unittest.cc',
+        '../components/autofill/core/browser/validation_unittest.cc',
 
-        # TODO(caitkp): Move to //components/components.gypi once
+        # TODO(caitkp): Move to //components/components_tests.gypi once
         # remaining dependencies back to //chrome are eliminated.
-        '../components/autofill/browser/webdata/autofill_entry_unittest.cc',
-        '../components/autofill/browser/webdata/autofill_table_unittest.cc',
-        '../components/autofill/browser/webdata/web_data_service_unittest.cc',
+        '../components/autofill/core/browser/webdata/autofill_entry_unittest.cc',
+        '../components/autofill/core/browser/webdata/autofill_table_unittest.cc',
+        '../components/autofill/core/browser/webdata/web_data_service_unittest.cc',
+        '../components/autofill/core/common/password_form_fill_data_unittest.cc',
         '../components/webdata/common/web_database_migration_unittest.cc',
         '../components/webdata/common/web_data_service_test_util.cc',
         '../components/webdata/common/web_data_service_test_util.h',
@@ -1814,7 +1847,6 @@
         '../google_apis/gaia/mock_url_fetcher_factory.h',
         '../google_apis/gaia/gaia_auth_fetcher_unittest.cc',
         '../google_apis/gaia/gaia_auth_util_unittest.cc',
-        '../google_apis/gaia/gaia_authenticator_unittest.cc',
         '../google_apis/gaia/gaia_oauth_client_unittest.cc',
         '../google_apis/gaia/google_service_auth_error_unittest.cc',
         '../google_apis/gaia/oauth_request_signer_unittest.cc',
@@ -2077,7 +2109,7 @@
         }],
         ['enable_webrtc==0', {
           'sources!': [
-            'renderer/media/webrtc_logging_handler_impl_unittest.cc',
+            'renderer/media/chrome_webrtc_log_message_delegate_unittest.cc',
           ],
         }],
         ['chromeos==1', {
@@ -2140,6 +2172,15 @@
                 }],
               ],
             }],
+            ['OS=="win" or OS=="mac"', {
+              'sources': [
+                'browser/media_galleries/fileapi/picasa/picasa_file_util_unittest.cc',
+                'utility/itunes_library_parser_unittest.cc',
+                'utility/media_galleries/picasa_album_table_reader_unittest.cc',
+                'utility/media_galleries/picasa_albums_indexer_unittest.cc',
+                'utility/media_galleries/pmp_column_reader_unittest.cc',
+              ],
+            }],
           ],
           'dependencies': [
             '../build/linux/system.gyp:dbus',
@@ -2310,8 +2351,8 @@
           'sources!': [
             # Bookmark export/import are handled via the BookmarkColumns
             # ContentProvider.
-            'browser/bookmarks/bookmark_html_reader_unittest.cc',
-            'browser/bookmarks/bookmark_html_writer_unittest.cc',
+            'browser/importer/bookmark_html_reader_unittest.cc',
+            'browser/importer/bookmark_html_writer_unittest.cc',
 
             'browser/shell_integration_unittest.cc',
 
@@ -2335,6 +2376,7 @@
             'browser/policy/managed_mode_policy_provider_unittest.cc',
             'browser/policy/policy_path_parser_unittest.cc',
             'browser/profiles/off_the_record_profile_impl_unittest.cc',
+            'browser/profiles/profile_loader_unittest.cc',
             'browser/search/search_unittest.cc',
             'browser/signin/profile_oauth2_token_service_unittest.cc',
             'browser/sync/profile_sync_service_session_unittest.cc',
@@ -2348,7 +2390,9 @@
             'browser/ui/fullscreen/fullscreen_controller_state_unittest.cc',
             'browser/ui/fullscreen/fullscreen_controller_unittest.cc',
             'browser/ui/search/instant_controller_unittest.cc',
+            'browser/ui/search/instant_page_unittest.cc',
             'browser/ui/search/search_delegate_unittest.cc',
+            'browser/ui/search/search_model_unittest.cc',
             'browser/ui/tab_contents/tab_contents_iterator_unittest.cc',
             'browser/ui/toolbar/recent_tabs_sub_menu_model_unittest.cc',
             'browser/ui/toolbar/toolbar_model_unittest.cc',
@@ -2370,6 +2414,7 @@
             'browser/google_apis/drive_api_requests_unittest.cc',
             'browser/google_apis/gdata_wapi_requests_unittest.cc',
             'browser/google_apis/gdata_wapi_parser_unittest.cc',
+            'browser/sync_file_system/drive_file_sync_service_sync_unittest.cc',
 
             'browser/user_style_sheet_watcher_unittest.cc',
 
@@ -2467,6 +2512,12 @@
             ['exclude', '^browser/extensions/blacklist_unittest.cc'],
           ],
         }],
+        ['enable_mdns != 1', {
+            'sources!' : [
+              'browser/local_discovery/local_domain_resolver_unittest.cc',
+              'browser/local_discovery/service_discovery_client_unittest.cc',
+            ],
+        }],
       ],
       'target_conditions': [
         ['OS == "ios"', {
diff --git a/chrome/common/DEPS b/chrome/common/DEPS
index 70cdc98..a066e70 100644
--- a/chrome/common/DEPS
+++ b/chrome/common/DEPS
@@ -3,8 +3,8 @@
   "+breakpad",  # For Breakpad constants.
   "+chromeos",  # For chromeos_switches.h
   "+components/autofill/core/common",
-  "+components/breakpad/common",
-  "+device/bluetooth",  # For BluetoothDevicePermission
+  "+components/nacl/common",
+  "+device/bluetooth",  # For BluetoothPermission
   "+device/media_transfer_protocol",  # For MediaTransferProtocolManager
   "+device/usb",  # For UsbDevicePermission
   "+extensions/common",
@@ -23,6 +23,10 @@
   # TODO(jam): remove me once chrome_notifcation_types.h moves to browser
   "+content/public/browser/notification_types.h",
 
+  # TODO(ananta): remove me when
+  # bug https://code.google.com/p/chromium/issues/detail?id=237249 is fixed.
+  "!content/public/child/image_decoder_utils.h",
+
   # Other libraries.
   "+chrome/third_party/xdg_user_dirs",
   "+third_party/bzip2",
diff --git a/chrome/common/all_messages.h b/chrome/common/all_messages.h
index 6e3eb1e..fb1438e 100644
--- a/chrome/common/all_messages.h
+++ b/chrome/common/all_messages.h
@@ -10,7 +10,7 @@
 // should not be listed here and instead get an exemption in
 // chrome/tools/ipclist/ipclist.cc.
 #if !defined(OS_ANDROID)
-#include "chrome/browser/importer/profile_import_process_messages.h"
+#include "chrome/common/importer/profile_import_process_messages.h"
 #endif
 
 #if defined(ENABLE_AUTOMATION)
diff --git a/chrome/common/auto_start_linux.cc b/chrome/common/auto_start_linux.cc
index bc8b666..0033aae 100644
--- a/chrome/common/auto_start_linux.cc
+++ b/chrome/common/auto_start_linux.cc
@@ -50,7 +50,7 @@
   if (file_util::WriteFile(autostart_file, autostart_file_contents.c_str(),
                            content_length) !=
       static_cast<int>(content_length)) {
-    file_util::Delete(autostart_file, false);
+    base::Delete(autostart_file, false);
     return false;
   }
   return true;
@@ -61,7 +61,7 @@
   base::FilePath autostart_directory = GetAutostartDirectory(environment.get());
   base::FilePath autostart_file =
       autostart_directory.Append(autostart_filename);
-  return file_util::Delete(autostart_file, false);
+  return base::Delete(autostart_file, false);
 }
 
 bool AutoStart::GetAutostartFileContents(
diff --git a/chrome/common/chrome_constants.cc b/chrome/common/chrome_constants.cc
index 14b8338..66482f1 100644
--- a/chrome/common/chrome_constants.cc
+++ b/chrome/common/chrome_constants.cc
@@ -133,8 +133,6 @@
 };
 #endif  // OS_MACOSX
 
-const wchar_t kNaClAppName[] = L"nacl64";
-
 #if defined(OS_WIN)
 const base::FilePath::CharType kMetroDriverDll[] = FPL("metro_driver.dll");
 const wchar_t kStatusTrayWindowClass[] = L"Chrome_StatusTrayWindow";
diff --git a/chrome/common/chrome_constants.h b/chrome/common/chrome_constants.h
index 7446209..1457939 100644
--- a/chrome/common/chrome_constants.h
+++ b/chrome/common/chrome_constants.h
@@ -46,7 +46,6 @@
 extern const char    kInitialProfile[];
 extern const char    kMultiProfileDirPrefix[];
 extern const wchar_t kBrowserResourcesDll[];
-extern const wchar_t kNaClAppName[];
 extern const base::FilePath::CharType kExtensionFileExtension[];
 extern const base::FilePath::CharType kExtensionKeyFileExtension[];
 
diff --git a/chrome/common/chrome_content_client.cc b/chrome/common/chrome_content_client.cc
index e60f06d..d0d178f 100644
--- a/chrome/common/chrome_content_client.cc
+++ b/chrome/common/chrome_content_client.cc
@@ -387,13 +387,6 @@
 
 namespace chrome {
 
-std::string ChromeContentClient::GetProductImpl() {
-  chrome::VersionInfo version_info;
-  std::string product("Chrome/");
-  product += version_info.is_valid() ? version_info.Version() : "0.0.0.0";
-  return product;
-}
-
 void ChromeContentClient::SetActiveURL(const GURL& url) {
   child_process_logging::SetActiveURL(url);
 }
@@ -439,7 +432,9 @@
 }
 
 std::string ChromeContentClient::GetProduct() const {
-  return GetProductImpl();
+  chrome::VersionInfo version_info;
+  return version_info.is_valid() ?
+      version_info.ProductNameAndVersionForUserAgent() : std::string();
 }
 
 std::string ChromeContentClient::GetUserAgent() const {
@@ -474,8 +469,6 @@
 
 std::string ChromeContentClient::GetProcessTypeNameInEnglish(int type) {
   switch (type) {
-    case PROCESS_TYPE_PROFILE_IMPORT:
-      return "Profile Import helper";
     case PROCESS_TYPE_NACL_LOADER:
       return "Native Client module";
     case PROCESS_TYPE_NACL_BROKER:
diff --git a/chrome/common/chrome_content_client.h b/chrome/common/chrome_content_client.h
index 699b0a1..f65e287 100644
--- a/chrome/common/chrome_content_client.h
+++ b/chrome/common/chrome_content_client.h
@@ -19,9 +19,6 @@
   static const char* const kNaClPluginName;
   static const char* const kNaClOldPluginName;
 
-  // This is what the ContentClient::GetProduct implementation calls.
-  static std::string GetProductImpl();
-
   virtual void SetActiveURL(const GURL& url) OVERRIDE;
   virtual void SetGpuInfo(const gpu::GPUInfo& gpu_info) OVERRIDE;
   virtual void AddPepperPlugins(
diff --git a/chrome/common/chrome_notification_types.h b/chrome/common/chrome_notification_types.h
index a851d68..3000dea 100644
--- a/chrome/common/chrome_notification_types.h
+++ b/chrome/common/chrome_notification_types.h
@@ -415,6 +415,9 @@
   // is the profile.
   NOTIFICATION_OMNIBOX_OPENED_URL,
 
+  // This is sent from Instant when the omnibox focus state changes.
+  NOTIFICATION_OMNIBOX_FOCUS_CHANGED,
+
   // Sent when the Google URL for a profile has been updated.  Some services
   // cache this value and need to update themselves when it changes.  See
   // google_util::GetGoogleURLAndUpdateIfNecessary().  The source is the
@@ -1079,17 +1082,6 @@
   // Send when a context menu is closed.
   NOTIFICATION_RENDER_VIEW_CONTEXT_MENU_CLOSED,
 
-  // Sent each time the InstantController is updated.
-  NOTIFICATION_INSTANT_CONTROLLER_UPDATED,
-
-  // Sent when an Instant overlay is committed. The Source is the WebContents
-  // containing the committed overlay.
-  NOTIFICATION_INSTANT_COMMITTED,
-
-  // Sent when the Instant Controller determines whether the overlay supports
-  // the Instant API or not.
-  NOTIFICATION_INSTANT_OVERLAY_SUPPORT_DETERMINED,
-
   // Sent when the Instant Controller determines whether an Instant tab supports
   // the Instant API or not.
   NOTIFICATION_INSTANT_TAB_SUPPORT_DETERMINED,
@@ -1102,12 +1094,6 @@
   // renderer.
   NOTIFICATION_INSTANT_SENT_MOST_VISITED_ITEMS,
 
-  // Sent when the Instant Controller sets an omnibox suggestion.
-  NOTIFICATION_INSTANT_SET_SUGGESTION,
-
-  // Sent when the Instant Controller has sent autocomplete results.
-  NOTIFICATION_INSTANT_SENT_AUTOCOMPLETE_RESULTS,
-
   // Sent when the CaptivePortalService checks if we're behind a captive portal.
   // The Source is the Profile the CaptivePortalService belongs to, and the
   // Details are a Details<CaptivePortalService::CheckResults>.
diff --git a/chrome/common/chrome_paths.cc b/chrome/common/chrome_paths.cc
index 647763a..9c20980 100644
--- a/chrome/common/chrome_paths.cc
+++ b/chrome/common/chrome_paths.cc
@@ -14,7 +14,6 @@
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_paths_internal.h"
 #include "chrome/common/widevine_cdm_constants.h"
-#include "components/breakpad/common/breakpad_paths.h"
 #include "ui/base/ui_base_paths.h"
 
 #if defined(OS_ANDROID)
@@ -65,15 +64,6 @@
 #endif
 
 #if defined(OS_POSIX) && !defined(OS_MACOSX)
-// File name of the nacl_helper and nacl_helper_bootstrap, Linux only.
-const base::FilePath::CharType kInternalNaClHelperFileName[] =
-    FILE_PATH_LITERAL("nacl_helper");
-const base::FilePath::CharType kInternalNaClHelperBootstrapFileName[] =
-    FILE_PATH_LITERAL("nacl_helper_bootstrap");
-#endif
-
-
-#if defined(OS_POSIX) && !defined(OS_MACOSX)
 
 const base::FilePath::CharType kO3DPluginFileName[] =
     FILE_PATH_LITERAL("pepper/libppo3dautoplugin.so");
@@ -200,6 +190,24 @@
       // and annoyed a lot of users.
 #endif
       break;
+    case chrome::DIR_CRASH_DUMPS:
+#if defined(OS_CHROMEOS)
+      // ChromeOS uses a separate directory. See http://crosbug.com/25089
+      cur = base::FilePath("/var/log/chrome");
+#elif defined(OS_ANDROID)
+      if (!base::android::GetCacheDirectory(&cur))
+        return false;
+#else
+      // The crash reports are always stored relative to the default user data
+      // directory.  This avoids the problem of having to re-initialize the
+      // exception handler after parsing command line options, which may
+      // override the location of the app's profile directory.
+      if (!GetDefaultUserDataDirectory(&cur))
+        return false;
+#endif
+      cur = cur.Append(FILE_PATH_LITERAL("Crash Reports"));
+      create_dir = true;
+      break;
     case chrome::DIR_RESOURCES:
 #if defined(OS_MACOSX)
       cur = base::mac::FrameworkBundlePath();
@@ -311,16 +319,6 @@
       cur = cur.Append(FILE_PATH_LITERAL("pnacl"));
       break;
 #if defined(OS_POSIX) && !defined(OS_MACOSX)
-    case chrome::FILE_NACL_HELPER:
-      if (!PathService::Get(base::DIR_MODULE, &cur))
-        return false;
-      cur = cur.Append(kInternalNaClHelperFileName);
-      break;
-    case chrome::FILE_NACL_HELPER_BOOTSTRAP:
-      if (!PathService::Get(base::DIR_MODULE, &cur))
-        return false;
-      cur = cur.Append(kInternalNaClHelperBootstrapFileName);
-      break;
     case chrome::FILE_O3D_PLUGIN:
       if (!PathService::Get(base::DIR_MODULE, &cur))
         return false;
@@ -498,25 +496,6 @@
 #endif
       break;
 
-    case breakpad::DIR_CRASH_DUMPS:
-#if defined(OS_CHROMEOS)
-      // ChromeOS uses a separate directory. See http://crosbug.com/25089
-      cur = base::FilePath("/var/log/chrome");
-#elif defined(OS_ANDROID)
-      if (!base::android::GetCacheDirectory(&cur))
-        return false;
-#else
-      // The crash reports are always stored relative to the default user data
-      // directory.  This avoids the problem of having to re-initialize the
-      // exception handler after parsing command line options, which may
-      // override the location of the app's profile directory.
-      if (!GetDefaultUserDataDirectory(&cur))
-        return false;
-#endif
-      cur = cur.Append(FILE_PATH_LITERAL("Crash Reports"));
-      create_dir = true;
-      break;
-
     default:
       return false;
   }
@@ -533,8 +512,6 @@
 // eliminate this object file if there is no direct entry point into it.
 void RegisterPathProvider() {
   PathService::RegisterProvider(PathProvider, PATH_START, PATH_END);
-  PathService::RegisterProvider(
-      PathProvider, breakpad::PATH_START, breakpad::PATH_END);
 }
 
 }  // namespace chrome
diff --git a/chrome/common/chrome_paths.h b/chrome/common/chrome_paths.h
index 99c44d0..a3b4dab 100644
--- a/chrome/common/chrome_paths.h
+++ b/chrome/common/chrome_paths.h
@@ -18,6 +18,7 @@
   DIR_APP = PATH_START,         // Directory where dlls and data reside.
   DIR_LOGS,                     // Directory where logs should be written.
   DIR_USER_DATA,                // Directory where user data can be written.
+  DIR_CRASH_DUMPS,              // Directory where crash dumps are written.
   DIR_RESOURCES,                // Directory containing separate file resources
                                 // used by Chrome at runtime.
   DIR_INSPECTOR,                // Directory where web inspector is located.
@@ -78,10 +79,6 @@
                                 // file.
   FILE_PDF_PLUGIN,              // Full path to the internal PDF plugin file.
 
-#if defined(OS_POSIX) && !defined(OS_MACOSX)
-  FILE_NACL_HELPER,             // Full path to Linux nacl_helper executable.
-  FILE_NACL_HELPER_BOOTSTRAP,   // ... and nacl_helper_bootstrap executable.
-#endif
   FILE_NACL_PLUGIN,             // Full path to the internal NaCl plugin file.
   DIR_PNACL_BASE,               // Full path to the base dir for PNaCl.
   DIR_PNACL_COMPONENT,          // Full path to the latest PNaCl version
diff --git a/chrome/common/chrome_paths_win.cc b/chrome/common/chrome_paths_win.cc
index 5eb6591..337f9b9 100644
--- a/chrome/common/chrome_paths_win.cc
+++ b/chrome/common/chrome_paths_win.cc
@@ -17,6 +17,7 @@
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/installer/util/browser_distribution.h"
+#include "components/nacl/common/nacl_switches.h"
 
 namespace chrome {
 
diff --git a/chrome/common/chrome_process_type.h b/chrome/common/chrome_process_type.h
index ba6ca10..b4d28a2 100644
--- a/chrome/common/chrome_process_type.h
+++ b/chrome/common/chrome_process_type.h
@@ -10,8 +10,9 @@
 // Defines the process types that are custom to chrome (i.e. as opposed to the
 // ones that content knows about).
 enum ChromeProcessType {
-  PROCESS_TYPE_PROFILE_IMPORT = content::PROCESS_TYPE_CONTENT_END,
-  PROCESS_TYPE_NACL_LOADER,
+  // Start at +1 because we removed an unused value and didn't want to change
+  // the IDs as they're used in UMA (see the comment for ProcessType).
+  PROCESS_TYPE_NACL_LOADER = content::PROCESS_TYPE_CONTENT_END + 1,
   PROCESS_TYPE_NACL_BROKER,
 };
 
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index 706c1e7..ca3dd1b 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -208,7 +208,7 @@
 
 // Comma-separated options to troubleshoot the component updater. Only valid
 // for the browser process.
-const char kComponentUpdaterDebug[]         = "component-updater-debug";
+const char kComponentUpdater[]              = "component-updater";
 
 // Causes the browser process to inspect loaded and registered DLLs for known
 // conflicts and warn the user.
@@ -352,19 +352,11 @@
 // Disable always using the local NTP for the first NTP load of a new window.
 const char kDisableLocalFirstLoadNTP[] = "disable-local-first-load-ntp";
 
-// Disable local-only Instant extended API.
-const char kDisableLocalOnlyInstantExtendedAPI[] =
-    "disable-local-only-instant-extended-api";
-
 // Disable the behavior that the second click on a launcher item (the click when
 // the item is already active) minimizes the item.
 const char kDisableMinimizeOnSecondLauncherItemClick[] =
     "disable-minimize-on-second-launcher-item-click";
 
-// Disables the native Autofill UI, which is part of the browser process rather
-// than part of the renderer process.  http://crbug.com/51644
-const char kDisableNativeAutofillUi[]       = "disable-new-autofill-ui";
-
 // Disables the menu on the NTP for accessing sessions from other devices.
 const char kDisableNTPOtherSessionsMenu[]   = "disable-ntp-other-sessions-menu";
 
@@ -490,6 +482,9 @@
 // (for testing purposes, to skip the whitelist).
 const char kEnableAdviewSrcAttribute[]      = "enable-adview-src-attribute";
 
+// Enables the <window-controls> tag in platform apps.
+const char kEnableAppWindowControls[]       = "enable-app-window-controls";
+
 // Enables the experimental asynchronous DNS client.
 const char kEnableAsyncDns[]                = "enable-async-dns";
 
@@ -498,6 +493,10 @@
 // HttpAuthHandlerNegotiate::CreateSPN for more background.
 const char kEnableAuthNegotiatePort[]       = "enable-auth-negotiate-port";
 
+// Enable using a public suffix based domain matching for autofill of passwords.
+const char kEnablePasswordAutofillPublicSuffixDomainMatching[] =
+    "enable-password-autofill-public-suffix-domain-matching";
+
 // Enables the pre- and auto-login features. When a user signs in to sync, the
 // browser's cookie jar is pre-filled with GAIA cookies. When the user visits a
 // GAIA login page, an info bar can help the user login.
@@ -521,15 +520,9 @@
 // Enables desktop guest mode.
 const char kEnableDesktopGuestMode[]        = "enable-desktop-guest-mode";
 
-// Enables device discovery.
-const char kEnableDeviceDiscovery[]        = "enable-device-discovery";
-
 // If true devtools experimental settings are enabled.
 const char kEnableDevToolsExperiments[]     = "enable-devtools-experiments";
 
-// Enable draggable menu button.
-const char kEnableDraggableMenuButton[]     = "enable-draggable-menu-button";
-
 // Enables extensions to be easily installed from sites other than the web
 // store. Without this flag, they can still be installed, but must be manually
 // dragged onto chrome://extensions/.
@@ -555,6 +548,11 @@
 // manifest.
 const char kExtensionsOnChromeURLs[]        = "extensions-on-chrome-urls";
 
+// Enable the fast unload controller, which speeds up tab/window close by
+// running a tab's onunload js handler independently of the GUI -
+// crbug.com/142458 .
+const char kEnableFastUnload[]         = "enable-fast-unload";
+
 // By default, cookies are not allowed on file://. They are needed for testing,
 // for example page cycler and layout tests. See bug 1157243.
 const char kEnableFileCookies[]             = "enable-file-cookies";
@@ -583,10 +581,6 @@
 // Enable always using the local NTP for the first NTP load of a new window.
 const char kEnableLocalFirstLoadNTP[] = "enable-local-first-load-ntp";
 
-// Enable Instant extended API, but use only the local omnibox popup and NTP.
-const char kEnableLocalOnlyInstantExtendedAPI[] =
-    "enable-local-only-instant-extended-api";
-
 // Enables support for user profiles that are managed by another user and can
 // have restrictions applied.
 const char kEnableManagedUsers[]            = "enable-managed-users";
@@ -631,9 +625,12 @@
 // account creation.
 const char kEnablePasswordGeneration[]      = "enable-password-generation";
 
-// Enables the installation and usage of Portable Native Client.
+// Enables the usage of Portable Native Client.
 const char kEnablePnacl[]                   = "enable-pnacl";
 
+// Disables the installation of Portable Native Client.
+const char kDisablePnaclInstall[]           = "disable-pnacl-install";
+
 // Enables tracking of tasks in profiler for viewing via about:profiler.
 // To predominantly disable tracking (profiling), use the command line switch:
 // --enable-profiling=0
@@ -665,6 +662,9 @@
 // Disable SPDY/3.1. This is a temporary testing flag.
 const char kDisableSpdy31[]                 = "disable-spdy31";
 
+// Enable SPDY/4 alpha 2. This is a temporary testing flag.
+const char kEnableSpdy4a2[]                 = "enable-spdy4a2";
+
 // Enable SPDY CREDENTIAL frame support.  This is a temporary testing flag.
 const char kEnableSpdyCredentialFrames[]    = "enable-spdy-credential-frames";
 
@@ -740,12 +740,21 @@
 // Frequency in seconds for Extensions auto-update.
 const char kExtensionsUpdateFrequency[]     = "extensions-update-frequency";
 
+// Additional query params to insert in the search and instant URLs.  Useful for
+// testing.
+const char kExtraSearchQueryParams[]        = "extra-search-query-params";
+
 // Fakes the channel of the browser for purposes of Variations filtering. This
 // is to be used for testing only. Possible values are "stable", "beta", "dev"
 // and "canary". Note that this only applies if the browser's reported channel
 // is UNKNOWN.
 const char kFakeVariationsChannel[]         = "fake-variations-channel";
 
+// If this flag is present then this command line is being delegated to an
+// already running chrome process via the fast path, ie: before chrome.dll is
+// loaded. It is useful to tell the difference for tracking purposes.
+const char kFastStart[]            = "fast-start";
+
 // These two flags are added around the switches about:flags adds to the
 // command line. This is useful to see which switches were added by about:flags
 // on about:version. They don't have any effect.
@@ -776,9 +785,8 @@
 // Enables using GAIA information to populate profile name and icon.
 const char kGaiaProfileInfo[]               = "gaia-profile-info";
 
-// Specifies an alternate URL to use for retrieving suggestions. Useful for
-// testing.
-const char kGoogleBaseSuggestURL[]    = "google-base-suggest-url";
+// Specifies an alternate URL to use for speaking to Google. Useful for testing.
+const char kGoogleBaseURL[]                 = "google-base-url";
 
 // Specifies an alternate URL to use for retrieving the search domain for
 // Google. Useful for testing.
@@ -837,8 +845,8 @@
 
 // Causes net::URLFetchers to ignore requests for SSL client certificates,
 // causing them to attempt an unauthenticated SSL/TLS session. This is intended
-// for use when testing various service URLs (eg: kPromoServerURL, kInstantURL,
-// kSbURLPrefix, kSyncServiceURL, etc)
+// for use when testing various service URLs (eg: kPromoServerURL, kSbURLPrefix,
+// kSyncServiceURL, etc)
 const char kIgnoreUrlFetcherCertRequests[]  =
     "ignore-urlfetcher-cert-requests";
 
@@ -852,10 +860,6 @@
 // Marks a renderer as an Instant process.
 const char kInstantProcess[]                = "instant-process";
 
-// URL to use for instant. If specified this overrides the url from the
-// TemplateURL.
-const char kInstantURL[]                    = "instant-url";
-
 // Used for testing - keeps browser alive after last browser window closes.
 const char kKeepAliveForTest[]              = "keep-alive-for-test";
 
@@ -880,10 +884,6 @@
 // Loads an extension from the specified directory.
 const char kLoadExtension[]                 = "load-extension";
 
-// Enables displaying net log events on the command line, or writing the events
-// to a separate file if a file name is given.
-const char kLogNetLog[]                     = "log-net-log";
-
 // Makes Chrome default browser
 const char kMakeDefaultBrowser[]            = "make-default-browser";
 
@@ -916,33 +916,6 @@
 // Enables multiprofile Chrome.
 const char kMultiProfiles[]                 = "multi-profiles";
 
-// Causes the process to run as a NativeClient broker
-// (used for launching NaCl loader processes on 64-bit Windows).
-const char kNaClBrokerProcess[]             = "nacl-broker";
-
-// Uses NaCl manifest URL to choose whether NaCl program will be debugged by
-// debug stub.
-// Switch value format: [!]pattern1,pattern2,...,patternN. Each pattern uses
-// the same syntax as patterns in Chrome extension manifest. The only difference
-// is that * scheme matches all schemes instead of matching only http and https.
-// If the value doesn't start with !, a program will be debugged if manifest URL
-// matches any pattern. If the value starts with !, a program will be debugged
-// if manifest URL does not match any pattern.
-const char kNaClDebugMask[]                 = "nacl-debug-mask";
-
-// Native Client GDB debugger that will be launched automatically when needed.
-const char kNaClGdb[]                       = "nacl-gdb";
-
-// GDB script to pass to the nacl-gdb debugger at startup.
-const char kNaClGdbScript[]                 = "nacl-gdb-script";
-
-// Causes the process to run as a NativeClient loader.
-const char kNaClLoaderProcess[]             = "nacl-loader";
-
-// On POSIX only: the contents of this flag are prepended to the nacl-loader
-// command line. Useful values might be "valgrind" or "xterm -e gdb --args".
-const char kNaClLoaderCmdPrefix[]           = "nacl-loader-cmd-prefix";
-
 // List of native messaging hosts outside of the default location. Used for
 // tests. The value must be comma-separate lists of key-value pairs separated
 // equal sign. E.g. "host1=/path/to/host1/manifest.json,host2=/path/host2.json".
@@ -1374,9 +1347,6 @@
 const char kSyncShortInitialRetryOverride[] =
     "sync-short-initial-retry-override";
 
-// Overrides the default notification method for sync.
-const char kSyncNotificationMethod[]        = "sync-notification-method";
-
 // Overrides the default host:port used for sync notifications.
 const char kSyncNotificationHostPort[]      = "sync-notification-host-port";
 
@@ -1415,9 +1385,6 @@
 // Passes the name of the current running automated test to Chrome.
 const char kTestName[]                      = "test-name";
 
-// Runs the security test for the NaCl loader sandbox.
-const char kTestNaClSandbox[]               = "test-nacl-sandbox";
-
 // Type of the current test harness ("browser" or "ui").
 const char kTestType[]                      = "test-type";
 
@@ -1481,10 +1448,6 @@
 // Prints version information and quits.
 const char kVersion[]                       = "version";
 
-// Requests that Chrome connect to a remote viewer process using an IPC
-// channel of the given name.
-const char kViewerConnection[]              = "viewer-connection";
-
 // Cycle through a series of URLs listed in the specified file.
 const char kVisitURLs[]                     = "visit-urls";
 
@@ -1605,6 +1568,16 @@
 
 #endif
 
+#if defined(OS_WIN) && defined(USE_AURA)
+// Requests that Chrome connect to the running Metro viewer process.
+const char kViewerConnect[]                 = "viewer-connect";
+
+// Requests that Chrome launch the Metro viewer process via the given appid
+// (which is assumed to be registered as default browser) and synchronously
+// connect to it.
+const char kViewerLaunchViaAppId[]          = "viewer-launch-via-appid";
+#endif
+
 #ifndef NDEBUG
 // Enables overriding the path of file manager extension.
 const char kFileManagerExtensionPath[]      = "filemgr-ext-path";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index 7cc7ba1..504576c 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -71,7 +71,7 @@
 extern const char kCloudPrintPrintTicket[];
 extern const char kCloudPrintSetupProxy[];
 extern const char kCloudPrintServiceURL[];
-extern const char kComponentUpdaterDebug[];
+extern const char kComponentUpdater[];
 extern const char kConflictingModulesCheck[];
 extern const char kContentSettings2[];
 extern const char kCountry[];
@@ -105,9 +105,7 @@
 extern const char kDisableIPv6[];
 extern const char kDisableIPPooling[];
 extern const char kDisableLocalFirstLoadNTP[];
-extern const char kDisableLocalOnlyInstantExtendedAPI[];
 extern const char kDisableMinimizeOnSecondLauncherItemClick[];
-extern const char kDisableNativeAutofillUi[];
 extern const char kDisableNTPOtherSessionsMenu[];
 extern const char kDisablePopupBlocking[];
 extern const char kDisablePreconnect[];
@@ -145,6 +143,7 @@
 extern const char kEasyOffStoreExtensionInstall[];
 extern const char kEnableAdview[];
 extern const char kEnableAdviewSrcAttribute[];
+extern const char kEnableAppWindowControls[];
 extern const char kEnableAsyncDns[];
 extern const char kEnableAuthNegotiatePort[];
 extern const char kEnableAutologin[];
@@ -153,12 +152,11 @@
 extern const char kEnableComponentCloudPolicy[];
 extern const char kEnableContacts[];
 extern const char kEnableDesktopGuestMode[];
-extern const char kEnableDeviceDiscovery[];
 extern const char kEnableDevToolsExperiments[];
-extern const char kEnableDraggableMenuButton[];
 extern const char kEnableExperimentalExtensionApis[];
 extern const char kEnableExtensionActivityLogging[];
 extern const char kEnableExtensionActivityLogTesting[];
+extern const char kEnableFastUnload[];
 extern const char kEnableFileCookies[];
 extern const char kEnableGoogleNowIntegration[];
 extern const char kEnableInstantExtendedAPI[];
@@ -166,7 +164,6 @@
 extern const char kEnableIPPooling[];
 extern const char kEnableIPv6[];
 extern const char kEnableLocalFirstLoadNTP[];
-extern const char kEnableLocalOnlyInstantExtendedAPI[];
 extern const char kEnableManagedStorage[];
 extern const char kEnableManagedUsers[];
 extern const char kEnableMemoryInfo[];
@@ -178,8 +175,10 @@
 extern const char kEnableNpnHttpOnly[];
 extern const char kEnableOmniboxAutoCompletionForIme[];
 extern const char kEnablePanels[];
+extern const char kEnablePasswordAutofillPublicSuffixDomainMatching[];
 extern const char kEnablePasswordGeneration[];
 extern const char kEnablePnacl[];
+extern const char kDisablePnaclInstall[];
 extern const char kEnableProfiling[];
 extern const char kEnableQuic[];
 extern const char kEnableQuickofficeEdit[];
@@ -187,6 +186,7 @@
 extern const char kEnableResourceContentSettings[];
 extern const char kEnableSdch[];
 extern const char kDisableSpdy31[];
+extern const char kEnableSpdy4a2[];
 extern const char kEnableSpdyCredentialFrames[];
 extern const char kEnableSpellingAutoCorrect[];
 extern const char kEnableSpellingServiceFeedback[];
@@ -208,7 +208,9 @@
 extern const char kExplicitlyAllowedPorts[];
 extern const char kExtensionProcess[];
 extern const char kExtensionsUpdateFrequency[];
+extern const char kExtraSearchQueryParams[];
 extern const char kFakeVariationsChannel[];
+extern const char kFastStart[];
 extern const char kFlagSwitchesBegin[];
 extern const char kFlagSwitchesEnd[];
 extern const char kFeedbackServer[];
@@ -217,7 +219,7 @@
 extern const char kForceFirstRun[];
 extern const char kForceLoadCloudPolicy[];
 extern const char kGaiaProfileInfo[];
-extern const char kGoogleBaseSuggestURL[];
+extern const char kGoogleBaseURL[];
 extern const char kGoogleSearchDomainCheckURL[];
 extern const char kGSSAPILibraryName[];
 extern const char kHelp[];
@@ -234,14 +236,12 @@
 extern const char kIncognito[];
 extern const char kInstallFromWebstore[];
 extern const char kInstantProcess[];
-extern const char kInstantURL[];
 extern const char kKeepAliveForTest[];
 extern const char kKioskMode[];
 extern const char kKioskModePrinting[];
 extern const char kLimitedInstallFromWebstore[];
 extern const char kLoadComponentExtension[];
 extern const char kLoadExtension[];
-extern const char kLogNetLog[];
 extern const char kMakeDefaultBrowser[];
 extern const char kManagedUserSyncToken[];
 extern const char kManaged[];
@@ -250,12 +250,6 @@
 extern const char kMessageLoopHistogrammer[];
 extern const char kMetricsRecordingOnly[];
 extern const char kMultiProfiles[];
-extern const char kNaClBrokerProcess[];
-extern const char kNaClDebugMask[];
-extern const char kNaClGdb[];
-extern const char kNaClGdbScript[];
-extern const char kNaClLoaderCmdPrefix[];
-extern const char kNaClLoaderProcess[];
 extern const char kNativeMessagingHosts[];
 extern const char kNetLogLevel[];
 extern const char kNewProfileManagement[];
@@ -362,7 +356,6 @@
 extern const char kSyncInvalidateXmppLogin[];
 extern const char kSyncKeystoreEncryption[];
 extern const char kSyncShortInitialRetryOverride[];
-extern const char kSyncNotificationMethod[];
 extern const char kSyncNotificationHostPort[];
 extern const char kSyncServiceURL[];
 extern const char kSyncTabFavicons[];
@@ -373,7 +366,6 @@
 extern const char kSyncfsEnableDirectoryOperation[];
 extern const char kTabBrowserDragging[];
 extern const char kTabCapture[];
-extern const char kTestNaClSandbox[];
 extern const char kTestName[];
 extern const char kTestType[];
 extern const char kTestingChannelID[];
@@ -393,7 +385,6 @@
 extern const char kValidateCrx[];
 extern const char kVariationsServerURL[];
 extern const char kVersion[];
-extern const char kViewerConnection[];
 extern const char kVisitURLs[];
 extern const char kWhitelistedExtensionID[];
 extern const char kWindowPosition[];
@@ -448,6 +439,11 @@
 extern const char kWindows8Search[];
 #endif
 
+#if defined(OS_WIN) && defined(USE_AURA)
+extern const char kViewerConnect[];
+extern const char kViewerLaunchViaAppId[];
+#endif
+
 #ifndef NDEBUG
 extern const char kFileManagerExtensionPath[];
 extern const char kImageLoaderExtensionPath[];
diff --git a/chrome/common/chrome_utility_messages.h b/chrome/common/chrome_utility_messages.h
index 1bf01b6..efe2c03 100644
--- a/chrome/common/chrome_utility_messages.h
+++ b/chrome/common/chrome_utility_messages.h
@@ -13,6 +13,7 @@
 #include "base/strings/string16.h"
 #include "base/values.h"
 #include "chrome/common/extensions/update_manifest.h"
+#include "chrome/common/itunes_library.h"
 #include "chrome/common/safe_browsing/zip_analyzer.h"
 #include "ipc/ipc_message_macros.h"
 #include "ipc/ipc_platform_file.h"
@@ -54,9 +55,15 @@
   IPC_STRUCT_TRAITS_MEMBER(has_archive)
 IPC_STRUCT_TRAITS_END()
 
+IPC_STRUCT_TRAITS_BEGIN(itunes::parser::Track)
+  IPC_STRUCT_TRAITS_MEMBER(id)
+  IPC_STRUCT_TRAITS_MEMBER(location)
+IPC_STRUCT_TRAITS_END()
+
 //------------------------------------------------------------------------------
 // Utility process messages:
 // These are messages from the browser to the utility process.
+
 // Tell the utility process to unpack the given extension file in its
 // directory and verify that it is valid.
 IPC_MESSAGE_CONTROL4(ChromeUtilityMsg_UnpackExtension,
@@ -124,9 +131,24 @@
 IPC_MESSAGE_CONTROL1(ChromeUtilityMsg_AnalyzeZipFileForDownloadProtection,
                      IPC::PlatformFileForTransit /* zip_file */)
 
+#if defined(OS_WIN)
+// Tell the utility process to parse the iTunes preference XML file contents
+// and return the path to the iTunes directory.
+IPC_MESSAGE_CONTROL1(ChromeUtilityMsg_ParseITunesPrefXml,
+                     std::string /* XML to parse */)
+#endif  // defined(OS_WIN)
+
+#if defined(OS_WIN) || defined(OS_MACOSX)
+// Tell the utility process to parse the iTunes library XML file and
+// return the parse result as well as the iTunes library as an itunes::Library.
+IPC_MESSAGE_CONTROL1(ChromeUtilityMsg_ParseITunesLibraryXmlFile,
+                     IPC::PlatformFileForTransit /* XML file to parse */)
+#endif  // defined(OS_WIN) || defined(OS_MACOSX)
+
 //------------------------------------------------------------------------------
 // Utility process host messages:
 // These are messages from the utility process to the browser.
+
 // Reply when the utility process is done unpacking an extension.  |manifest|
 // is the parsed manifest.json file.
 // The unpacker should also have written out files containing the decoded
@@ -217,3 +239,18 @@
 IPC_MESSAGE_CONTROL1(
     ChromeUtilityHostMsg_AnalyzeZipFileForDownloadProtection_Finished,
     safe_browsing::zip_analyzer::Results)
+
+#if defined(OS_WIN)
+// Reply after parsing the iTunes preferences XML file contents with either the
+// path to the iTunes directory or an empty FilePath.
+IPC_MESSAGE_CONTROL1(ChromeUtilityHostMsg_GotITunesDirectory,
+                     base::FilePath /* Path to iTunes library */)
+#endif  // defined(OS_WIN)
+
+#if defined(OS_WIN) || defined(OS_MACOSX)
+// Reply after parsing the iTunes library XML file with the parser result and
+// an itunes::Library data structure.
+IPC_MESSAGE_CONTROL2(ChromeUtilityHostMsg_GotITunesLibrary,
+                     bool /* Parser result */,
+                     itunes::parser::Library /* iTunes library */)
+#endif  // defined(OS_WIN) || defined(OS_MACOSX)
diff --git a/chrome/common/chrome_version_info.cc b/chrome/common/chrome_version_info.cc
index 89f6ede..7671a3d 100644
--- a/chrome/common/chrome_version_info.cc
+++ b/chrome/common/chrome_version_info.cc
@@ -16,6 +16,12 @@
 
 namespace chrome {
 
+std::string VersionInfo::ProductNameAndVersionForUserAgent() const {
+  if (!is_valid())
+    return std::string();
+  return "Chrome/" + Version();
+}
+
 #if defined(OS_WIN) || defined(OS_MACOSX)
 // On Windows and Mac, we get the Chrome version info by querying
 // FileVersionInfo for the current module.
diff --git a/chrome/common/chrome_version_info.h b/chrome/common/chrome_version_info.h
index 41cee4b..3ebe6fc 100644
--- a/chrome/common/chrome_version_info.h
+++ b/chrome/common/chrome_version_info.h
@@ -36,6 +36,9 @@
   // check is_valid().
   bool is_valid() const;
 
+  // E.g. "Chrome/a.b.c.d"
+  std::string ProductNameAndVersionForUserAgent() const;
+
   // E.g. "Chromium" or "Google Chrome".
   std::string Name() const;
 
diff --git a/chrome/common/cloud_print/cloud_print_constants.cc b/chrome/common/cloud_print/cloud_print_constants.cc
index 6787279..b25773b 100644
--- a/chrome/common/cloud_print/cloud_print_constants.cc
+++ b/chrome/common/cloud_print/cloud_print_constants.cc
@@ -8,8 +8,6 @@
 
 const char kCloudPrintUserAgent[] = "GoogleCloudPrintProxy";
 const char kChromeCloudPrintProxyHeader[] = "X-CloudPrint-Proxy: Chrome";
-const char kCloudPrintGaiaServiceId[] = "cloudprint";
-const char kProxyAuthUserAgent[] = "ChromiumBrowser";
 const char kCloudPrintPushNotificationsSource[] = "cloudprint.google.com";
 
 const char kProxyIdValue[] = "proxy";
diff --git a/chrome/common/cloud_print/cloud_print_constants.h b/chrome/common/cloud_print/cloud_print_constants.h
index d846ae0..c9933cd 100644
--- a/chrome/common/cloud_print/cloud_print_constants.h
+++ b/chrome/common/cloud_print/cloud_print_constants.h
@@ -13,10 +13,6 @@
 extern const char kCloudPrintUserAgent[];
 // The proxy header required by cloud print server.
 extern const char kChromeCloudPrintProxyHeader[];
-// The service id of cloud print used in gaia authentication.
-extern const char kCloudPrintGaiaServiceId[];
-// The user agent string used in gaia authentication.
-extern const char kProxyAuthUserAgent[];
 // The source of cloud print notifications.
 extern const char kCloudPrintPushNotificationsSource[];
 
diff --git a/chrome/common/crash_keys.cc b/chrome/common/crash_keys.cc
index 691e877..8ecf1c9 100644
--- a/chrome/common/crash_keys.cc
+++ b/chrome/common/crash_keys.cc
@@ -60,6 +60,8 @@
     { mac::kSendAction, kMediumSize },
     { mac::kZombie, kMediumSize },
     { mac::kZombieTrace, kMediumSize },
+    { mac::kZoomBubbleWindowType, kSmallSize },
+    { mac::kZoomBubbleURL, kLargeSize },
     // content/:
     { "channel_error_bt", kMediumSize },
     { "remove_route_bt", kMediumSize },
@@ -89,6 +91,9 @@
 const char kZombie[] = "zombie";
 const char kZombieTrace[] = "zombie_dealloc_bt";
 
+const char kZoomBubbleWindowType[] = "zoom_bubble_window_type";
+const char kZoomBubbleURL[] = "zoom_bubble_url";
+
 }  // namespace mac
 #endif
 
diff --git a/chrome/common/crash_keys.h b/chrome/common/crash_keys.h
index 4111eb6..abfefc7 100644
--- a/chrome/common/crash_keys.h
+++ b/chrome/common/crash_keys.h
@@ -39,6 +39,10 @@
 extern const char kZombie[];
 extern const char kZombieTrace[];
 
+// For http://crbug.com/254977.
+extern const char kZoomBubbleWindowType[];
+extern const char kZoomBubbleURL[];
+
 }  // namespace mac
 #endif
 
diff --git a/chrome/common/extensions/OWNERS b/chrome/common/extensions/OWNERS
index cab97ff..8e1a98e 100644
--- a/chrome/common/extensions/OWNERS
+++ b/chrome/common/extensions/OWNERS
@@ -3,7 +3,6 @@
 benwells@chromium.org
 erikkay@chromium.org
 finnur@chromium.org
-jeremya@chromium.org
 jyasskin@chromium.org
 kalman@chromium.org
 koz@chromium.org
diff --git a/chrome/common/extensions/api/_api_features.json b/chrome/common/extensions/api/_api_features.json
index ba89362..38a6fa6 100644
--- a/chrome/common/extensions/api/_api_features.json
+++ b/chrome/common/extensions/api/_api_features.json
@@ -10,6 +10,10 @@
     "dependencies": ["permission:activityLogPrivate"],
     "contexts": ["blessed_extension"]
   },
+  "adview": {
+    "dependencies": ["permission:adview"],
+    "contexts": ["blessed_extension"]
+  },
   "alarms": {
     "dependencies": ["permission:alarms"],
     "contexts": ["blessed_extension"]
@@ -121,6 +125,11 @@
     "dependencies": ["permission:developerPrivate"],
     "contexts": ["blessed_extension"]
   },
+  "diagnostics": {
+    "dependencies": ["permission:diagnostics"],
+    "extension_types": ["platform_app"],
+    "contexts": ["blessed_extension"]
+  },
   "dial": {
     "dependencies": ["permission:dial"],
     "contexts": ["blessed_extension"]
diff --git a/chrome/common/extensions/api/_manifest_features.json b/chrome/common/extensions/api/_manifest_features.json
index 53503b6..0aed543 100644
--- a/chrome/common/extensions/api/_manifest_features.json
+++ b/chrome/common/extensions/api/_manifest_features.json
@@ -245,7 +245,10 @@
       "extension", "platform_app"
     ],
     "whitelist": [
-      "mdbihdcgjmagbcapkhhkjbbdlkflmbfo"  // Placeholder to activate whitelist.
+      "mdbihdcgjmagbcapkhhkjbbdlkflmbfo",  // unit_tests
+      "pmofbkohncoogjjhahejjfbppikbjigm",  // Google Now
+      "hkhhlkdconhgemhegnplaldnmnmkaemd",  // Get Started App
+      "nmmhkkegccagdldgiimedpiccmgmieda"  // In-app payments support app.
     ]
   },
   "offline_enabled": {
@@ -289,6 +292,10 @@
       "extension", "packaged_app", "hosted_app", "platform_app"
     ]
   },
+  "platforms": {
+    "channel": "stable",
+    "extension_types": "all"
+  },
   "plugins": {
     "channel": "stable",
     "extension_types": ["extension", "packaged_app", "hosted_app"]
diff --git a/chrome/common/extensions/api/_permission_features.json b/chrome/common/extensions/api/_permission_features.json
index 578dedf..2b1d627 100644
--- a/chrome/common/extensions/api/_permission_features.json
+++ b/chrome/common/extensions/api/_permission_features.json
@@ -98,7 +98,10 @@
   "chromeosInfoPrivate": {
     "channel": "stable",
     "extension_types": ["extension", "packaged_app"],
-    "location": "component"
+    "whitelist": [
+      "8C3741E3AF0B93B6E8E0DDD499BB0B74839EA578",  // http://crbug.com/234235
+      "E703483CEF33DEC18B4B6DD84B5C776FB9182BDB"   // http://crbug.com/234235
+    ]
   },
   "clipboardRead": {
     "channel": "stable",
@@ -135,6 +138,21 @@
     "channel": "stable",
     "extension_types": ["extension", "packaged_app"]
   },
+  "diagnostics": [
+    {
+      "channel": "dev",
+      "extension_types": ["platform_app"]
+    },
+    {
+      "channel": "stable",
+      "extension_types": ["platform_app"],
+      "whitelist": [
+        "mlocfejafidcakdddnndjdngfmncfbeg",  // CCD Development
+        "ganomidahfnpdchomfgdoppjmmedlhia",  // CCD Testing
+        "eemlkeanncmjljgehlbplemhmdmalhdc"   // CCD Release
+      ]
+    }
+  ],
   "debugger": {
     "channel": "stable",
     "extension_types": ["extension", "packaged_app"]
@@ -186,10 +204,6 @@
       "16CA7A47AAE4BE49B1E75A6B960C3875E945B264"   // Release
     ]
   },
-  "identity": {
-    "channel": "dev",
-    "extension_types": ["extension", "platform_app"]
-  },
   "enterprise.platformKeysPrivate": {
     "channel": "stable",
     "extension_types": ["extension", "packaged_app"],
@@ -208,7 +222,9 @@
     "channel": "stable",
     "extension_types": ["extension", "platform_app"],
     "whitelist": [
-      "7910EAFDAF64B947E1CB31B333A9BD14CA556B6C" // Feedback UI.
+      "7910EAFDAF64B947E1CB31B333A9BD14CA556B6C",  // Feedback UI.
+      "8C3741E3AF0B93B6E8E0DDD499BB0B74839EA578",  // http://crbug.com/234235
+      "E703483CEF33DEC18B4B6DD84B5C776FB9182BDB"   // http://crbug.com/234235
     ]
   },
   "fileBrowserHandler": {
@@ -229,7 +245,7 @@
     "whitelist": [ "2FC374607C2DF285634B67C64A2E356C607091C3" ]
   }],
   "fileSystem.retainFiles": [{
-    "channel": "trunk",
+    "channel": "dev",
     "extension_types": ["platform_app"]
   }],
   "fileSystem.write": [{
@@ -258,6 +274,10 @@
     "channel": "stable",
     "extension_types": ["extension", "packaged_app"]
   },
+  "identity": {
+    "channel": "stable",
+    "extension_types": ["extension", "platform_app"]
+  },
   "identityPrivate": {
     "channel": "stable",
     "extension_types": [
@@ -366,7 +386,10 @@
       "bpmcpldpdmajfigpchkicefoigmkfalc",  // Quickoffice component extension
       "ehibbfinohgbchlgdbfpikodjaojhccn",  // Editor
       "pmofbkohncoogjjhahejjfbppikbjigm",  // Google Now
-      "iejldcgjigodajhjecapkeiggcncflph"   // Google Now dev
+      "khopmbdjffemhegeeobelklnbglcdgfh",  // RU-NTP
+      "mlocfejafidcakdddnndjdngfmncfbeg",  // CCD Development
+      "ganomidahfnpdchomfgdoppjmmedlhia",  // CCD Testing
+      "eemlkeanncmjljgehlbplemhmdmalhdc"   // CCD Release
     ]
   },
   "musicManagerPrivate": {
@@ -377,35 +400,24 @@
       "B8F61FD1B25DE03706DBB8906A73261E4DBB992A"  // Test
     ]
   },
-  "nativeMessaging": [
-    {
-      "channel": "beta",
-      "extension_types": [
-        "extension", "packaged_app", "platform_app"
-      ]
-    },
-    {
-      "channel": "stable",
-      "extension_types": [
-        "extension", "packaged_app", "platform_app"
-      ],
-      "whitelist": [
-        "gbchcmhmhahfdphkhkmpfmihenigjmpp",  // Chrome Remote Desktop
-        "kgngmbheleoaphbjbaiobfdepmghbfah",  // Dogfood Chrome Remote Desktop
-        "odkaodonbgfohohmklejpjiejmcipmib",  // QA Chrome Remote Desktop
-        "ojoimpklfciegopdfgeenehpalipignm"   // Chromoting canary
-      ]
-    }
-  ],
+  "nativeMessaging": {
+    "channel": "stable",
+    "extension_types": [
+      "extension", "packaged_app", "platform_app"
+    ]
+  },
   "networkingPrivate": {
     "channel": "stable",
-    "extension_types": ["extension", "packaged_app"],
+    "extension_types": ["extension", "packaged_app", "platform_app"],
     "whitelist": [
       "pkedcjkdefgpdelpbcmbmeomcjbeemfm",  // Trusted Tester
       "fmfcbgogabcbclcofgocippekhfcmgfj",  // Staging
       "hfaagokkkhdbgiakmmlclaapfelnkoah",  // Canary
       "F155646B5D1CA545F7E1E4E20D573DFDD44C2540",  // Trusted Tester (public)
-      "16CA7A47AAE4BE49B1E75A6B960C3875E945B264"   // Release
+      "16CA7A47AAE4BE49B1E75A6B960C3875E945B264",  // Release
+      "mlocfejafidcakdddnndjdngfmncfbeg",  // CCD Development
+      "ganomidahfnpdchomfgdoppjmmedlhia",  // CCD Testing
+      "eemlkeanncmjljgehlbplemhmdmalhdc"   // CCD Release
     ]
   },
   "notifications": {
diff --git a/chrome/common/extensions/api/activity_log_private.json b/chrome/common/extensions/api/activity_log_private.json
index 6336de2..72dbc46 100644
--- a/chrome/common/extensions/api/activity_log_private.json
+++ b/chrome/common/extensions/api/activity_log_private.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "activityLogPrivate",
+    "description": "none",
     "types": [
       {
         "id": "DomActivityDetail",
diff --git a/chrome/common/extensions/api/adview.json b/chrome/common/extensions/api/adview.json
new file mode 100644
index 0000000..68d8802
--- /dev/null
+++ b/chrome/common/extensions/api/adview.json
@@ -0,0 +1,12 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+[
+  {
+    "namespace": "adview",
+    "description": "none",
+    "nodoc": true
+  }
+]
+
diff --git a/chrome/common/extensions/api/alarms.idl b/chrome/common/extensions/api/alarms.idl
index 9e610ad..3b218e0 100644
--- a/chrome/common/extensions/api/alarms.idl
+++ b/chrome/common/extensions/api/alarms.idl
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// TODO(mpcomplete): We need documentation before we can release this.
-
+// Use the <code>chrome.alarms</code> API to schedule code to run
+// periodically or at a specified time in the future.
 namespace alarms {
   dictionary Alarm {
     // Name of this alarm.
diff --git a/chrome/common/extensions/api/api.gyp b/chrome/common/extensions/api/api.gyp
index 184f3e6..d09c800 100644
--- a/chrome/common/extensions/api/api.gyp
+++ b/chrome/common/extensions/api/api.gyp
@@ -21,6 +21,7 @@
         'schema_files': [
           'alarms.idl',
           'activity_log_private.json',
+          'adview.json',
           'app_current_window_internal.idl',
           'app_runtime.idl',
           'app_window.idl',
@@ -37,6 +38,7 @@
           'cookies.json',
           'debugger.json',
           'developer_private.idl',
+          'diagnostics.idl',
           'dial.idl',
           'downloads.idl',
           'echo_private.json',
diff --git a/chrome/common/extensions/api/app.json b/chrome/common/extensions/api/app.json
index 7735f63..d9bffa7 100644
--- a/chrome/common/extensions/api/app.json
+++ b/chrome/common/extensions/api/app.json
@@ -5,7 +5,7 @@
 [
   {
     "namespace": "app",
-    "nodoc": true,
+    "description": "none",
     "types": [
       {
         "id": "Details",
diff --git a/chrome/common/extensions/api/app_runtime.idl b/chrome/common/extensions/api/app_runtime.idl
index 391adaa..da8ddb8 100644
--- a/chrome/common/extensions/api/app_runtime.idl
+++ b/chrome/common/extensions/api/app_runtime.idl
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// Use the <code>chrome.app.runtime</code> API to manage the app lifecycle.
+// The app runtime manages app installation, controls the event page, and can
+// shut down the app at anytime.
 namespace app.runtime {
 
   [inline_doc] dictionary LaunchItem {
diff --git a/chrome/common/extensions/api/app_window.idl b/chrome/common/extensions/api/app_window.idl
index c4a258b..d4e1b40 100644
--- a/chrome/common/extensions/api/app_window.idl
+++ b/chrome/common/extensions/api/app_window.idl
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// Use the <code>chrome.app.window</code> API to create windows. Windows
+// have an optional frame with title bar and size controls. They are not
+// associated with any Chrome browser windows.
 namespace app.window {
   dictionary Bounds {
     long? left;
diff --git a/chrome/common/extensions/api/audio.idl b/chrome/common/extensions/api/audio.idl
index 081889c..15efd77 100644
--- a/chrome/common/extensions/api/audio.idl
+++ b/chrome/common/extensions/api/audio.idl
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// Use the <code>chrome.audio</code> API to query audio device configuration and
+// be notified when it changes.
 namespace audio {
 
   dictionary OutputDeviceInfo {
diff --git a/chrome/common/extensions/api/bluetooth.idl b/chrome/common/extensions/api/bluetooth.idl
index 0fd8be6..d1774b7 100644
--- a/chrome/common/extensions/api/bluetooth.idl
+++ b/chrome/common/extensions/api/bluetooth.idl
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Bluetooth API.
-
+// Use the <code>chrome.bluetooth</code> API to connect to a Bluetooth
+// device.
 namespace bluetooth {
   dictionary AdapterState {
     // The address of the adapter, in the format 'XX:XX:XX:XX:XX:XX'.
diff --git a/chrome/common/extensions/api/bookmark_manager_private.json b/chrome/common/extensions/api/bookmark_manager_private.json
index 8f573a3..192973a 100644
--- a/chrome/common/extensions/api/bookmark_manager_private.json
+++ b/chrome/common/extensions/api/bookmark_manager_private.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "bookmarkManagerPrivate",
+    "description": "none",
     "nodoc": true,
     "types": [
       {
diff --git a/chrome/common/extensions/api/bookmarks.json b/chrome/common/extensions/api/bookmarks.json
index 61ce218..e168362 100644
--- a/chrome/common/extensions/api/bookmarks.json
+++ b/chrome/common/extensions/api/bookmarks.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "bookmarks",
+    "description": "Use the <code>chrome.bookmarks</code> API to create, organize, and otherwise manipulate bookmarks. Also see <a href='override.html'>Override Pages</a>, which you can use to create a custom Bookmark Manager page.",
     "properties": {
       "MAX_WRITE_OPERATIONS_PER_HOUR": {
         "value": 100,
diff --git a/chrome/common/extensions/api/browser_action.json b/chrome/common/extensions/api/browser_action.json
index f734c4b..85dd9bb 100644
--- a/chrome/common/extensions/api/browser_action.json
+++ b/chrome/common/extensions/api/browser_action.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "browserAction",
+    "description": "Use browser actions to put icons in the main Google Chrome toolbar, to the right of the address bar. In addition to its <a href='#icon'>icon</a>, a browser action can also have a <a href='#tooltip'>tooltip</a>, a <a href='#badge'>badge</a>, and a <a href = '#popups'>popup</a>.",
     "types": [
       {
         "id": "ColorArray",
diff --git a/chrome/common/extensions/api/browsing_data.json b/chrome/common/extensions/api/browsing_data.json
index 9d9824a..332186d 100644
--- a/chrome/common/extensions/api/browsing_data.json
+++ b/chrome/common/extensions/api/browsing_data.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "browsingData",
+    "description": "Use the <code>chrome.browsingData</code> API to remove browsing data from a user's local profile.",
     "types": [
       {
         "id": "RemovalOptions",
diff --git a/chrome/common/extensions/api/chromeos_info_private.json b/chrome/common/extensions/api/chromeos_info_private.json
index 4518da0..095edee 100644
--- a/chrome/common/extensions/api/chromeos_info_private.json
+++ b/chrome/common/extensions/api/chromeos_info_private.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "chromeosInfoPrivate",
+    "description": "none",
     "compiler_options": {
       "implemented_in": "chrome/browser/chromeos/extensions/info_private_api.h"
     },
diff --git a/chrome/common/extensions/api/cloud_print_private.json b/chrome/common/extensions/api/cloud_print_private.json
index c79a430..edd3e02 100644
--- a/chrome/common/extensions/api/cloud_print_private.json
+++ b/chrome/common/extensions/api/cloud_print_private.json
@@ -5,7 +5,7 @@
 [
   {
     "namespace": "cloudPrintPrivate",
-    "nodoc": "true",
+    "description": "none",
     "types": [
       {
         "id": "PrinterSettings",
diff --git a/chrome/common/extensions/api/command_line_private.json b/chrome/common/extensions/api/command_line_private.json
index 2504376..90c052d 100644
--- a/chrome/common/extensions/api/command_line_private.json
+++ b/chrome/common/extensions/api/command_line_private.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "commandLinePrivate",
+    "description": "none",
     "functions": [
       {
         "name": "hasSwitch",
diff --git a/chrome/common/extensions/api/commands.json b/chrome/common/extensions/api/commands.json
index b064c9a..c02008e 100644
--- a/chrome/common/extensions/api/commands.json
+++ b/chrome/common/extensions/api/commands.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "commands",
+    "description": "Use the commands API to add keyboard shortcuts that trigger actions in your extension, for example, an action to open the browser action or send a command to the extension.",
     "types": [
       {
         "id": "Command",
diff --git a/chrome/common/extensions/api/content_settings.json b/chrome/common/extensions/api/content_settings.json
index f9542d7..2a0b86a 100644
--- a/chrome/common/extensions/api/content_settings.json
+++ b/chrome/common/extensions/api/content_settings.json
@@ -5,6 +5,10 @@
 [
   {
     "namespace": "contentSettings",
+    "description": "Use the <code>chrome.contentSettings</code> API to change settings that control whether websites can use features such as cookies, JavaScript, and plug-ins. More generally speaking, content settings allow you to customize Chrome's behavior on a per-site basis instead of globally.",
+    "compiler_options": {
+      "generate_type_functions": true
+    },
     "types": [
       {
         "id": "ResourceIdentifier",
diff --git a/chrome/common/extensions/api/context_menus.json b/chrome/common/extensions/api/context_menus.json
index e44322f..a96bbae 100644
--- a/chrome/common/extensions/api/context_menus.json
+++ b/chrome/common/extensions/api/context_menus.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "contextMenus",
+    "description": "Use the <code>chrome.contextMenus</code> API to add items to Google Chrome's context menu. You can choose what types of objects your context menu additions apply to, such as images, hyperlinks, and pages.",
     "types": [
       {
         "id": "OnClickData",
diff --git a/chrome/common/extensions/api/cookies.json b/chrome/common/extensions/api/cookies.json
index fc3e53f..8c083ac 100644
--- a/chrome/common/extensions/api/cookies.json
+++ b/chrome/common/extensions/api/cookies.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "cookies",
+    "description": "Use the <code>chrome.cookies</code> API to query and modify cookies, and to be notified when they change.",
     "types": [
       {
         "id": "Cookie",
diff --git a/chrome/common/extensions/api/debugger.json b/chrome/common/extensions/api/debugger.json
index fe2e08a..1150895 100644
--- a/chrome/common/extensions/api/debugger.json
+++ b/chrome/common/extensions/api/debugger.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "debugger",
+    "description": "The <code>chrome.debugger</code> API serves as an alternate transport for Chrome's <a href='http://code.google.com/chrome/devtools/docs/remote-debugging.html'>remote debugging protocol</a>. Use <code>chrome.debugger</code> to attach to one or more tabs to instrument network interaction, debug JavaScript, mutate the DOM and CSS, etc. Use the Debuggee <code>tabId</code> to target tabs with sendCommand and route events by <code>tabId</code> from onEvent callbacks.",
     "types": [
       {
         "id": "Debuggee",
diff --git a/chrome/common/extensions/api/declarative_content.json b/chrome/common/extensions/api/declarative_content.json
index f2e2ae2..bed20fc 100644
--- a/chrome/common/extensions/api/declarative_content.json
+++ b/chrome/common/extensions/api/declarative_content.json
@@ -5,6 +5,8 @@
 [
   {
     "namespace": "declarativeContent",
+    "description": "Use the <code>chrome.declarativeContent</code> API to take actions depending on the content of a page, without requiring permission to read the page's content.",
+    "documentation_permissions_required": ["declarative", "declarativeContent"],
     "types": [
       {
         "id": "PageStateMatcher",
diff --git a/chrome/common/extensions/api/declarative_web_request.json b/chrome/common/extensions/api/declarative_web_request.json
index 4a99fbc..fdca489 100644
--- a/chrome/common/extensions/api/declarative_web_request.json
+++ b/chrome/common/extensions/api/declarative_web_request.json
@@ -5,6 +5,8 @@
 [
   {
     "namespace": "declarativeWebRequest",
+    "description": "Use the <code>chrome.declarativeWebRequest</code> API to intercept, block, or modify requests in-flight. It is significantly faster than the <a href='webRequest.html'><code>chrome.webRequest</code> API</a> because you can register rules that are evaluated in the browser rather than the JavaScript engine with reduces roundtrip latencies and allows higher efficiency.",
+    "documentation_permissions_required": ["declarative", "declarativeWebRequest"],
     "types": [
       {
         "id": "HeaderFilter",
diff --git a/chrome/common/extensions/api/developer_private.idl b/chrome/common/extensions/api/developer_private.idl
index 740390c..df4b1cc 100644
--- a/chrome/common/extensions/api/developer_private.idl
+++ b/chrome/common/extensions/api/developer_private.idl
@@ -5,7 +5,6 @@
 // developerPrivate API.
 // This is a private API exposing developing and debugging functionalities for
 // apps and extensions.
-
 namespace developerPrivate {
 
   enum ItemType {
@@ -84,6 +83,17 @@
     FOLDER
   };
 
+  enum EventType {
+    INSTALLED,
+    UNINSTALLED,
+    LOADED,
+    UNLOADED,
+    // New window / view opened.
+    VIEW_REGISTERED,
+    // window / view closed.
+    VIEW_UNREGISTERED
+  };
+
   dictionary PackDirectoryResponse {
     // The response message of success or error.
     DOMString message;
@@ -102,6 +112,11 @@
     DOMString name;
   };
 
+  dictionary EventData {
+    EventType event_type;
+    DOMString item_id;
+  };
+
   callback VoidCallback = void ();
   callback BooleanCallback = void (boolean result);
   callback ItemsInfoCallback = void (ItemInfo[] result);
@@ -188,4 +203,9 @@
     static void getStrings(GetStringsCallback callback);
   };
 
+  interface Events {
+    // Fired when a item state is changed.
+    static void onItemStateChanged(EventData response);
+  };
+
 };
diff --git a/chrome/common/extensions/api/devtools/experimental_audits.json b/chrome/common/extensions/api/devtools/experimental_audits.json
index b9107bc..d359496 100644
--- a/chrome/common/extensions/api/devtools/experimental_audits.json
+++ b/chrome/common/extensions/api/devtools/experimental_audits.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "experimental.devtools.audits",
+    "description": "Use the <code>chrome.experimental.devtools.audits</code> API to add new audit categories to the Developer Tools' Audit panel.",
     "nocompile": true,
     "functions": [
       {
diff --git a/chrome/common/extensions/api/devtools/experimental_console.json b/chrome/common/extensions/api/devtools/experimental_console.json
index 35ea7f0..42fe4c7 100644
--- a/chrome/common/extensions/api/devtools/experimental_console.json
+++ b/chrome/common/extensions/api/devtools/experimental_console.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "experimental.devtools.console",
+    "description": "Use the <code>chrome.experimental.devtools.console</code> API to retrieve messages from the inspected page console and post messages there.",
     "nocompile": true,
     "functions": [
       {
diff --git a/chrome/common/extensions/api/devtools/inspected_window.json b/chrome/common/extensions/api/devtools/inspected_window.json
index 48346f8..bd5b764 100644
--- a/chrome/common/extensions/api/devtools/inspected_window.json
+++ b/chrome/common/extensions/api/devtools/inspected_window.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "devtools.inspectedWindow",
+    "description": "Use the <code>chrome.devtools.inspectedWindow</code> API to interact with the inspected window: obtain the tab ID for the inspected page, evaluate the code in the context of the inspected window, reload the page, or obtain the list of resources within the page.",
     "nocompile": true,
     "types": [
       {
diff --git a/chrome/common/extensions/api/devtools/network.json b/chrome/common/extensions/api/devtools/network.json
index c7dc56e..3bb6e0b 100644
--- a/chrome/common/extensions/api/devtools/network.json
+++ b/chrome/common/extensions/api/devtools/network.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "devtools.network",
+    "description": "Use the <code>chrome.devtools.network</code> API to retrieve the information about network requests displayed by the Developer Tools in the Network panel.",
     "nocompile": true,
     "types": [
       {
diff --git a/chrome/common/extensions/api/devtools/panels.json b/chrome/common/extensions/api/devtools/panels.json
index de0635f..31ee936 100644
--- a/chrome/common/extensions/api/devtools/panels.json
+++ b/chrome/common/extensions/api/devtools/panels.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "devtools.panels",
+    "description": "Use the <code>chrome.devtools.panels</code> API to integrate your extension into Developer Tools window UI: create your own panels, access existing panels, and add sidebars.",
     "nocompile": true,
     "types": [
       {
diff --git a/chrome/common/extensions/api/diagnostics.idl b/chrome/common/extensions/api/diagnostics.idl
new file mode 100644
index 0000000..b498dbb
--- /dev/null
+++ b/chrome/common/extensions/api/diagnostics.idl
@@ -0,0 +1,37 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Use the <code>chrome.diagnostics</code> API to query various properties of
+// the environment that may be useful for diagnostics.
+namespace diagnostics {
+  dictionary SendPacketOptions {
+    // Target IP address.
+    DOMString ip;
+    // Packet time to live value. If omitted, the system default value will be
+    // used.
+    long? ttl;
+    // Packet timeout in seconds. If omitted, the system default value will be
+    // used.
+    long? timeout;
+    // Size of the payload. If omitted, the system default value will be used.
+    long? size;
+  };
+
+  dictionary SendPacketResult {
+    // The IP of the host which we recieves the ICMP reply from.
+    // The IP may differs from our target IP if the packet's ttl is used up.
+    DOMString ip;
+
+    // Latency in millisenconds.
+    double latency;
+  };
+
+  callback SendPacketCallback = void(SendPacketResult result);
+
+  interface Functions {
+    // Send a packet of the given type with the given parameters.
+    static void sendPacket(SendPacketOptions options,
+                           SendPacketCallback callback);
+  };
+};
diff --git a/chrome/common/extensions/api/dial.idl b/chrome/common/extensions/api/dial.idl
index 42263b3..d16fdfd 100644
--- a/chrome/common/extensions/api/dial.idl
+++ b/chrome/common/extensions/api/dial.idl
@@ -2,34 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// An API for discovery of devices that support DIAL.
+// Use the <code>chrome.dial</code> API to discover devices that support DIAL.
 // Protocol specification: http://www.dial-multiscreen.org/
-//
-// The API is backed by a service that multicasts discovery requests on the
-// local network to discover DIAL-capable devices and maintains a list of
-// devices that have responded.  Adding an onDeviceList listener causes the
-// service to periodically issue discovery requests to maintain the device list.
-// (No polling is done when there are no onDeviceList listeners.)
-//
-// The onDeviceList event is fired when discovery respnses are received and in
-// other circumstances; see the documentation for onDeviceList.
-//
-// The client can request that network discovery can be done immediately by
-// invoking discoverNow() which is useful for presenting the user with an
-// updated list of devices.
-//
-// On-demand use (updates when discoverNow() is called):
-// chrome.dial.onDeviceList.addListener(function (list) { updateMenu(list); });
-// chrome.dial.discoverNow();
-// (Remember to remove the listener when the menu closes.)
-//
-// Background use (updates only when periodic polling happens):
-// var myList;
-// chrome.dial.onDeviceList.addListener(function (list) { myList = list; });
-//
-// These can be combined to poll for devices to prime the device menu, then
-// refresh the menu when it is displayed.
-
 namespace dial {
 
   // Represents a unique device that responded to a DIAL discovery request.
diff --git a/chrome/common/extensions/api/downloads.idl b/chrome/common/extensions/api/downloads.idl
index f306f08..af6eac1 100644
--- a/chrome/common/extensions/api/downloads.idl
+++ b/chrome/common/extensions/api/downloads.idl
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// Use the <code>chrome.downloads</code> API to programmatically initiate,
+// monitor, manipulate, and search for downloads.
+[permissions=downloads]
 namespace downloads {
   [inline_doc] dictionary HeaderNameValuePair {
     // Name of the HTTP header.
diff --git a/chrome/common/extensions/api/downloads_internal.idl b/chrome/common/extensions/api/downloads_internal.idl
index 1e5b910..bbbfbcd 100644
--- a/chrome/common/extensions/api/downloads_internal.idl
+++ b/chrome/common/extensions/api/downloads_internal.idl
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// downloadsInternal
 [nodoc=true]
 namespace downloadsInternal {
   interface Functions {
@@ -10,7 +11,4 @@
                                   DOMString filename,
                                   DOMString conflict_action);
   };
-
-  interface Events {
-  };
 };
diff --git a/chrome/common/extensions/api/echo_private.json b/chrome/common/extensions/api/echo_private.json
index c5b9371..2d1a40f 100644
--- a/chrome/common/extensions/api/echo_private.json
+++ b/chrome/common/extensions/api/echo_private.json
@@ -8,9 +8,8 @@
     "compiler_options": {
       "implemented_in": "chrome/browser/chromeos/extensions/echo_private_api.h"
     },
-    "nodoc": true,
+    "description": "none",
     "platforms": ["chromeos"],
-    "types": [],
     "functions": [
       {
         "name": "getRegistrationCode",
diff --git a/chrome/common/extensions/api/enterprise_platform_keys_private.json b/chrome/common/extensions/api/enterprise_platform_keys_private.json
index 483586c..8c66814 100644
--- a/chrome/common/extensions/api/enterprise_platform_keys_private.json
+++ b/chrome/common/extensions/api/enterprise_platform_keys_private.json
@@ -5,9 +5,8 @@
 [
   {
     "namespace": "enterprise.platformKeysPrivate",
-    "nodoc": true,
+    "description": "none",
     "platforms": ["chromeos"],
-    "types": [],
     "functions": [
       {
         "name": "challengeMachineKey",
diff --git a/chrome/common/extensions/api/events.json b/chrome/common/extensions/api/events.json
index 66fdf3d..b67b8b0 100644
--- a/chrome/common/extensions/api/events.json
+++ b/chrome/common/extensions/api/events.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "events",
+    "description": "Use the <code>chrome.events</code> API to notify you when something interesting happens.",
     "compiler_options": {
       "implemented_in": "chrome/browser/extensions/api/declarative/declarative_api.h"
     },
diff --git a/chrome/common/extensions/api/experimental_accessibility.json b/chrome/common/extensions/api/experimental_accessibility.json
index 5a733dc..da3536e 100644
--- a/chrome/common/extensions/api/experimental_accessibility.json
+++ b/chrome/common/extensions/api/experimental_accessibility.json
@@ -8,7 +8,7 @@
     "compiler_options": {
       "implemented_in": "chrome/browser/accessibility/accessibility_extension_api.h"
     },
-    "nodoc": true,
+    "description": "none",
     "types": [
       {
         "id": "CheckboxDetails",
diff --git a/chrome/common/extensions/api/experimental_discovery.idl b/chrome/common/extensions/api/experimental_discovery.idl
index d8b4e5e..4f631c3 100644
--- a/chrome/common/extensions/api/experimental_discovery.idl
+++ b/chrome/common/extensions/api/experimental_discovery.idl
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// An experimental API that allows extensions to inject suggest links in the recommended pane of the New Tab Page.
 namespace experimental.discovery {
 
   dictionary SuggestDetails {
diff --git a/chrome/common/extensions/api/experimental_dns.idl b/chrome/common/extensions/api/experimental_dns.idl
index 23c5c4b..04de6ad 100644
--- a/chrome/common/extensions/api/experimental_dns.idl
+++ b/chrome/common/extensions/api/experimental_dns.idl
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-[nodoc] namespace experimental.dns {
+// Experimental.dns.
+namespace experimental.dns {
 
   dictionary ResolveCallbackResolveInfo {
     // The result code. Zero indicates success.
diff --git a/chrome/common/extensions/api/experimental_history.json b/chrome/common/extensions/api/experimental_history.json
index 09a6f8e..f7f2290 100644
--- a/chrome/common/extensions/api/experimental_history.json
+++ b/chrome/common/extensions/api/experimental_history.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "experimental.history",
+    "description": "Use the <code>chrome.experimental.history</code> API to interact with the browser's record of most visited pages.",
     "types": [
       {
         "id": "MostVisitedItem",
diff --git a/chrome/common/extensions/api/experimental_identity.idl b/chrome/common/extensions/api/experimental_identity.idl
index 1f2bf1f..9bcee6b 100644
--- a/chrome/common/extensions/api/experimental_identity.idl
+++ b/chrome/common/extensions/api/experimental_identity.idl
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// The <code>chrome.experimental.identity</code> API.
 namespace experimental.identity {
 
   [inline_doc] dictionary ExperimentalTokenDetails {
diff --git a/chrome/common/extensions/api/experimental_idltest.idl b/chrome/common/extensions/api/experimental_idltest.idl
index 4ee9ff7..5e85ce7 100644
--- a/chrome/common/extensions/api/experimental_idltest.idl
+++ b/chrome/common/extensions/api/experimental_idltest.idl
@@ -3,8 +3,7 @@
 // found in the LICENSE file.
 
 // An API to test IDL schema specifications.
-
-[nodoc] namespace experimental.idltest {
+namespace experimental.idltest {
 
   callback LongArrayCallback = void(long[] array);
   callback ArrayBufferCallback = void(ArrayBuffer buffer);
diff --git a/chrome/common/extensions/api/experimental_infobars.json b/chrome/common/extensions/api/experimental_infobars.json
index 220f679..ec3cfdd 100644
--- a/chrome/common/extensions/api/experimental_infobars.json
+++ b/chrome/common/extensions/api/experimental_infobars.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "experimental.infobars",
+    "description": "Use the <code>chrome.infobars</code> API to add a horizontal panel just above a tab's contents. See the screenshot below.",
     "compiler_options": {
       "implemented_in": "chrome/browser/infobars/infobar_extension_api.h"
     },
diff --git a/chrome/common/extensions/api/experimental_input_virtual_keyboard.json b/chrome/common/extensions/api/experimental_input_virtual_keyboard.json
index 2aea6ca..4bd2c81 100644
--- a/chrome/common/extensions/api/experimental_input_virtual_keyboard.json
+++ b/chrome/common/extensions/api/experimental_input_virtual_keyboard.json
@@ -5,52 +5,21 @@
 [
   {
     "namespace": "experimental.input.virtualKeyboard",
-    "nodoc": true,
-    "types": [],
+    "description": "none",
     "functions": [
       {
-        "name": "sendKeyboardEvent",
+        "name": "insertText",
         "type": "function",
-        "description": "Sends a keyboard event to Chrome.",
+        "description": "Inserts text into the currently focused text field.",
         "parameters": [
-          { "type": "object",
-            "name": "event",
-            "properties": {
-              "type": {
-                "type": "string",
-                "description": "One of 'keyup' or 'keydown'."
-              },
-              "keyIdentifier": {
-                "type": "string",
-                "description": "See http://www.w3.org/TR/2003/NOTE-DOM-Level-3-Events-20031107/keyset.html#KeySet-Set"
-              },
-              "altKey": {
-                "type": "boolean",
-                "optional": true,
-                "description": "Whether or not the ALT key is pressed."
-              },
-              "ctrlKey": {
-                "type": "boolean",
-                "optional": true,
-                "description": "Whether or not the CTRL key is pressed."
-              },
-              "metaKey": {
-                "type": "boolean",
-                "optional": true,
-                "description": "Whether or not the META key is pressed."
-              },
-              "shiftKey": {
-                "type": "boolean",
-                "optional": true,
-                "description": "Whether or not the SHIFT key is pressed."
-              }
-            },
-            "description": "The keyboard event to be sent."
+          { "name": "text",
+            "type": "string",
+            "description": "The text that will be inserted."
           },
           { "type": "function",
             "name": "callback",
             "optional": true,
-            "description": "This function is called when the event processing is completed.",
+            "description": "Called when the insertion is completed.",
             "parameters": []
           }
         ]
diff --git a/chrome/common/extensions/api/experimental_media_galleries.idl b/chrome/common/extensions/api/experimental_media_galleries.idl
index 0ada32e..649bd95 100644
--- a/chrome/common/extensions/api/experimental_media_galleries.idl
+++ b/chrome/common/extensions/api/experimental_media_galleries.idl
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// An experimental API that expands upon the <code>chrome.mediaGalleries</code>
+// API's functionality.
 namespace experimental.mediaGalleries {
 
   callback AssembleMediaFileCallback =
diff --git a/chrome/common/extensions/api/experimental_processes.json b/chrome/common/extensions/api/experimental_processes.json
index 5fdeebc..9bb7633 100644
--- a/chrome/common/extensions/api/experimental_processes.json
+++ b/chrome/common/extensions/api/experimental_processes.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "experimental.processes",
+    "description": "Use the <code>chrome.experimental.processes</code> API to interact with the browser's processes.",
     "types": [
       {
         "id": "Process",
@@ -13,7 +14,7 @@
         "properties": {
           "id": {
             "type": "integer",
-            "description": "Unique ID of the process provided by the browser." 
+            "description": "Unique ID of the process provided by the browser."
           },
           "osProcessId": {
             "type": "integer",
diff --git a/chrome/common/extensions/api/experimental_record.json b/chrome/common/extensions/api/experimental_record.json
index ce55501..cf95448 100644
--- a/chrome/common/extensions/api/experimental_record.json
+++ b/chrome/common/extensions/api/experimental_record.json
@@ -1,6 +1,7 @@
 [
   {
     "namespace": "experimental.record",
+    "description": "The <code>chrome.experimental.record</code> API.",
     "types": [
       {
         "id": "SessionDetails",
@@ -10,7 +11,7 @@
           "extensionPath": {
             "type": "string",
             "optional": true,
-            "description": 
+            "description":
                 "Absolute path to an unpacked extension to run in the subbrowser session."
           }
         }
@@ -80,7 +81,7 @@
             "description": "Unique name of capture.  Use to determine cache."
           },
           {
-            "type": "integer", 
+            "type": "integer",
             "name": "repeatCount",
             "minimum": 0,
             "maximum": 100
diff --git a/chrome/common/extensions/api/experimental_rlz.json b/chrome/common/extensions/api/experimental_rlz.json
index b954a4e..f97f925 100644
--- a/chrome/common/extensions/api/experimental_rlz.json
+++ b/chrome/common/extensions/api/experimental_rlz.json
@@ -5,8 +5,7 @@
 [
   {
     "namespace": "experimental.rlz",
-    "nodoc": true,
-    "types": [],
+    "description": "none",
     "functions": [
       {
         "name": "recordProductEvent",
diff --git a/chrome/common/extensions/api/experimental_system_info_storage.idl b/chrome/common/extensions/api/experimental_system_info_storage.idl
index d6d5002..85ad898 100644
--- a/chrome/common/extensions/api/experimental_system_info_storage.idl
+++ b/chrome/common/extensions/api/experimental_system_info_storage.idl
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// Use the <code>chrome.experimental.systemInfo.storage</code> API to query
+// storage device information and be notified when it changes.
 namespace experimental.systemInfo.storage {
 
   enum StorageUnitType {
@@ -73,6 +75,6 @@
     // Fired when a removable storage is detached from the system.
     static void onDetached(DOMString id);
   };
- 
+
 };
 
diff --git a/chrome/common/extensions/api/extension.json b/chrome/common/extensions/api/extension.json
index 17cdc32..cd53553 100644
--- a/chrome/common/extensions/api/extension.json
+++ b/chrome/common/extensions/api/extension.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "extension",
+    "description": "The <code>chrome.extension</code> API has utilities that can be used by any extension page. It includes support for exchanging messages between an extension and its content scripts or between extensions, as described in detail in <a href='messaging.html'>Message Passing</a>.",
     "compiler_options": {
       "implemented_in": "chrome/browser/extensions/api/module/module.h"
     },
diff --git a/chrome/common/extensions/api/feedback_private.idl b/chrome/common/extensions/api/feedback_private.idl
index faa579d..97ce494 100644
--- a/chrome/common/extensions/api/feedback_private.idl
+++ b/chrome/common/extensions/api/feedback_private.idl
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// A private API for accessing feedback reports sent by a user.
 namespace feedbackPrivate {
 
   dictionary AttachedFile {
diff --git a/chrome/common/extensions/api/file_browser_handler.json b/chrome/common/extensions/api/file_browser_handler.json
index 2eb694c..ed05911 100644
--- a/chrome/common/extensions/api/file_browser_handler.json
+++ b/chrome/common/extensions/api/file_browser_handler.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace":"fileBrowserHandler",
+    "description": "Use the <code>chrome.fileBrowserHandler</code> API to extend the Chrome OS file browser. For example, you can use this API to enable users to upload files to your website.",
     "platforms": ["chromeos"],
     "types": [
       {
diff --git a/chrome/common/extensions/api/file_browser_handler_internal.json b/chrome/common/extensions/api/file_browser_handler_internal.json
index c4461ed..af42611 100644
--- a/chrome/common/extensions/api/file_browser_handler_internal.json
+++ b/chrome/common/extensions/api/file_browser_handler_internal.json
@@ -8,7 +8,7 @@
     "compiler_options": {
       "implemented_in": "chrome/browser/chromeos/extensions/file_manager/file_browser_handler_api.h"
     },
-    "nodoc": true,
+    "description": "none",
     "platforms": ["chromeos"],
     "types": [
       {
diff --git a/chrome/common/extensions/api/file_browser_private.json b/chrome/common/extensions/api/file_browser_private.json
index 8e44a6a..1939d74 100644
--- a/chrome/common/extensions/api/file_browser_private.json
+++ b/chrome/common/extensions/api/file_browser_private.json
@@ -5,7 +5,7 @@
 [
   {
     "namespace":"fileBrowserPrivate",
-    "nodoc": "true",
+    "description": "none",
     "types": [
       {
         "id": "FileBrowserTask",
@@ -99,6 +99,11 @@
             "optional": true,
             "description": "URL to the Drive thumbnail image for this file."
           },
+          "shareUrl": {
+            "type": "string",
+            "optional": true,
+            "description": "Drive share URL for this file."
+          },
           "isPinned": {
             "type": "boolean",
             "optional": true,
@@ -450,7 +455,7 @@
             "optional": true,
             "parameters": []
           }
-        ]        
+        ]
       },
       {
         "name": "getFileTasks",
@@ -1136,7 +1141,7 @@
           {
             "name": "callback",
             "type": "function",
-            "description": "Called back when the check is finished.", 
+            "description": "Called back when the check is finished.",
             "parameters": [
               {
                 "name": "result",
@@ -1148,13 +1153,13 @@
         ]
       },
       {
-        "name": "openNewWindow",
-        "description": "Opens a new window of the Files.app.",
+        "name": "zoom",
+        "description": "Changes the zoom factor of the Files.app.",
         "parameters": [
           {
-            "name": "url",
+            "name": "operation",
             "type": "string",
-            "description": "Internal url to be opened."
+            "enum": ["in", "out", "reset"]
           }
         ]
       }
diff --git a/chrome/common/extensions/api/file_system.idl b/chrome/common/extensions/api/file_system.idl
index 89db7df..e2bd173 100644
--- a/chrome/common/extensions/api/file_system.idl
+++ b/chrome/common/extensions/api/file_system.idl
@@ -2,6 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// Use the <code>chrome.fileSystem</code> API to create, read, navigate,
+// and write to a sandboxed section of the user's local file system. With this
+// API, packaged apps can read and write to a user-seleced location. For
+// example, a text editor app can use the API to read and write local documents.
 namespace fileSystem {
   dictionary AcceptOption {
     // This is the optional text description for this option. If not present,
diff --git a/chrome/common/extensions/api/font_settings.json b/chrome/common/extensions/api/font_settings.json
index 0719147..1999fcf 100644
--- a/chrome/common/extensions/api/font_settings.json
+++ b/chrome/common/extensions/api/font_settings.json
@@ -5,6 +5,8 @@
 [
   {
     "namespace": "fontSettings",
+    "description": "Use the <code>chrome.fontSettings</code> API to manage Chrome's font settings.",
+    "documentation_permissions_required": ["fontSettings"],
     "types": [
       {
         "id": "FontName",
diff --git a/chrome/common/extensions/api/history.json b/chrome/common/extensions/api/history.json
index c72caee..b73e3e3 100644
--- a/chrome/common/extensions/api/history.json
+++ b/chrome/common/extensions/api/history.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "history",
+    "description": "Use the <code>chrome.history</code> API to interact with the browser's record of visited pages. You can add, remove, and query for URLs in the browser's history. To override the history page with your own version, see <a href='override.html'>Override Pages</a>.",
     "types": [
       {
         "id": "HistoryItem",
diff --git a/chrome/common/extensions/api/i18n.json b/chrome/common/extensions/api/i18n.json
index e568913..510256c 100644
--- a/chrome/common/extensions/api/i18n.json
+++ b/chrome/common/extensions/api/i18n.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "i18n",
+    "description": "Use the <code>chrome.i18n</code> infrastructure to implement internationalization across your whole app or extension.",
     "types": [],
     "functions": [
       {
diff --git a/chrome/common/extensions/api/identity.idl b/chrome/common/extensions/api/identity.idl
index aacdd84..b4ec9fc 100644
--- a/chrome/common/extensions/api/identity.idl
+++ b/chrome/common/extensions/api/identity.idl
@@ -2,56 +2,89 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// TODO(courage): documentation.
 namespace identity {
 
-  [nodoc] dictionary TokenDetails {
-    // Whether to prompt the user to log in or grant scope permissions (if they
-    // have not already done so). Default is false.
+  dictionary TokenDetails {
+    // Fetching a token may require the user to sign-in to Chrome, or
+    // approve the application's requested scopes. If the interactive
+    // flag is <code>true</code>, <code>getAuthToken</code> will
+    // prompt the user as necessary. When the flag is
+    // <code>false</code> or ommitted, <code>getAuthToken</code> will
+    // return failure any time a prompt would be required.
     boolean? interactive;
   };
 
-  [nodoc] dictionary InvalidTokenDetails {
+  dictionary InvalidTokenDetails {
     // The specific token that should be removed from the cache.
     DOMString token;
   };
 
-  [nodoc] dictionary WebAuthFlowDetails {
+  dictionary WebAuthFlowDetails {
     // The URL that initiates the auth flow.
     DOMString url;
 
-    // Whether to launch auth flow in interactive mode. Default is false.
+    // Whether to launch auth flow in interactive mode.
+    //
+    // Since some auth flows may immediately redirect to a result URL,
+    // <code>launchWebAuthFlow</code> hides its web view until the
+    // first navigation either redirects to the final URL, or finishes
+    // loading a page meant to be displayed.
+    //
+    // If the interactive flag is <code>true</code>, the window will
+    // be displayed when a page load completes. If the flag is
+    // <code>false</code> or ommitted, <code>launchWebAuthFlow</code>
+    // will return with an error if the initial navigation does not
+    // complete the flow.
     boolean? interactive;
   };
 
-  [nodoc] callback GetAuthTokenCallback = void (optional DOMString token);
-  [nodoc] callback InvalidateAuthTokenCallback = void ();
-  [nodoc] callback LaunchWebAuthFlowCallback = void (optional DOMString responseUrl);
+  callback GetAuthTokenCallback = void (optional DOMString token);
+  callback InvalidateAuthTokenCallback = void ();
+  callback LaunchWebAuthFlowCallback = void (optional DOMString responseUrl);
 
   interface Functions {
-    // Gets an OAuth2 access token as specified by the manifest.
+    // Gets an OAuth2 access token using the client ID and scopes
+    // specified in the <a
+    // href="app_identity.html#update_manifest"><code>oauth2</code>
+    // section of manifest.json</a>.
+    //
+    // The Identity API caches access tokens in memory, so it's ok to
+    // call <code>getAuthToken</code> any time a token is
+    // required. The token cache automatically handles expiration.
     //
     // |details| : Token options.
     // |callback| : Called with an OAuth2 access token as specified by the
     // manifest, or undefined if there was an error.
-    [nodoc] static void getAuthToken(optional TokenDetails details,
-                                     GetAuthTokenCallback callback);
+    static void getAuthToken(optional TokenDetails details,
+                             GetAuthTokenCallback callback);
 
     // Removes an OAuth2 access token from the Identity API's token cache.
-    // When an access token is discovered to be invalid, it should be
-    // passed to removeCachedAuthToken to remove it from the cache. The
-    // app may then retrieve a fresh token with getAuthToken.
+    //
+    // If an access token is discovered to be invalid, it should be
+    // passed to removeCachedAuthToken to remove it from the
+    // cache. The app may then retrieve a fresh token with
+    // <code>getAuthToken</code>.
     //
     // |details| : Token information.
     // |callback| : Called when the token has been removed from the cache.
-    [nodoc] static void removeCachedAuthToken(
+    static void removeCachedAuthToken(
         InvalidTokenDetails details, InvalidateAuthTokenCallback callback);
 
     // Starts an auth flow at the specified URL.
     //
+    // This method enables auth flows with non-Google identity
+    // providers by launching a web view and navigating it to the
+    // first URL in the provider's auth flow. When the provider
+    // redirects to a URL matching the pattern
+    // <code>https://&lt;app-id&gt;.chromiumapp.org/*</code>, the
+    // window will close, and the final redirect URL will be passed to
+    // the <var>callback</var> function.
+    //
     // |details| : WebAuth flow options.
     // |callback| : Called with the URL redirected back to your application.
-    [nodoc] static void launchWebAuthFlow(WebAuthFlowDetails details,
-                                          LaunchWebAuthFlowCallback callback);
+    static void launchWebAuthFlow(WebAuthFlowDetails details,
+                                  LaunchWebAuthFlowCallback callback);
   }
   ;
 };
diff --git a/chrome/common/extensions/api/identity/extension_manifests_auth_unittest.cc b/chrome/common/extensions/api/identity/extension_manifests_auth_unittest.cc
index 82f719a..e4403b0 100644
--- a/chrome/common/extensions/api/identity/extension_manifests_auth_unittest.cc
+++ b/chrome/common/extensions/api/identity/extension_manifests_auth_unittest.cc
@@ -9,6 +9,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace keys = extension_manifest_keys;
+namespace errors = extension_manifest_errors;
 
 namespace {
 
@@ -33,16 +34,22 @@
     AUTO_APPROVE_INVALID
   };
 
+  enum ClientIdValue {
+    CLIENT_ID_DEFAULT,
+    CLIENT_ID_NOT_SET,
+    CLIENT_ID_EMPTY
+  };
+
   base::DictionaryValue* CreateManifest(
       AutoApproveValue auto_approve,
-      bool extension_id_whitelisted) {
+      bool extension_id_whitelisted,
+      ClientIdValue client_id) {
     parsed_manifest_.reset(base::test::ParseJson(
         "{ \n"
         "  \"name\": \"test\", \n"
         "  \"version\": \"0.1\", \n"
         "  \"manifest_version\": 2, \n"
         "  \"oauth2\": { \n"
-        "    \"client_id\": \"client1\", \n"
         "    \"scopes\": [ \"scope1\" ], \n"
         "  }, \n"
         "} \n").release());
@@ -61,6 +68,15 @@
         ext_manifest->SetString(keys::kOAuth2AutoApprove, "incorrect value");
         break;
     }
+    switch (client_id) {
+      case CLIENT_ID_DEFAULT:
+        ext_manifest->SetString(keys::kOAuth2ClientId, "client1");
+        break;
+      case CLIENT_ID_NOT_SET:
+        break;
+      case CLIENT_ID_EMPTY:
+        ext_manifest->SetString(keys::kOAuth2ClientId, "");
+    }
     if (extension_id_whitelisted)
       ext_manifest->SetString(keys::kKey, kExtensionKey);
     return ext_manifest;
@@ -142,7 +158,7 @@
 
 TEST_F(OAuth2ManifestTest, AutoApproveNotSetExtensionNotOnWhitelist) {
   base::DictionaryValue* ext_manifest =
-      CreateManifest(AUTO_APPROVE_NOT_SET, false);
+      CreateManifest(AUTO_APPROVE_NOT_SET, false, CLIENT_ID_DEFAULT);
   Manifest manifest(ext_manifest, "test");
   scoped_refptr<extensions::Extension> extension =
       LoadAndExpectSuccess(manifest);
@@ -152,7 +168,7 @@
 
 TEST_F(OAuth2ManifestTest, AutoApproveFalseExtensionNotOnWhitelist) {
   base::DictionaryValue* ext_manifest =
-      CreateManifest(AUTO_APPROVE_FALSE, false);
+      CreateManifest(AUTO_APPROVE_FALSE, false, CLIENT_ID_DEFAULT);
   Manifest manifest(ext_manifest, "test");
   scoped_refptr<extensions::Extension> extension =
       LoadAndExpectSuccess(manifest);
@@ -165,7 +181,7 @@
 
 TEST_F(OAuth2ManifestTest, AutoApproveTrueExtensionNotOnWhitelist) {
   base::DictionaryValue* ext_manifest =
-      CreateManifest(AUTO_APPROVE_TRUE, false);
+      CreateManifest(AUTO_APPROVE_TRUE, false, CLIENT_ID_DEFAULT);
   Manifest manifest(ext_manifest, "test");
   scoped_refptr<extensions::Extension> extension =
       LoadAndExpectSuccess(manifest);
@@ -178,7 +194,7 @@
 
 TEST_F(OAuth2ManifestTest, AutoApproveInvalidExtensionNotOnWhitelist) {
   base::DictionaryValue* ext_manifest =
-      CreateManifest(AUTO_APPROVE_INVALID, false);
+      CreateManifest(AUTO_APPROVE_INVALID, false, CLIENT_ID_DEFAULT);
   Manifest manifest(ext_manifest, "test");
   scoped_refptr<extensions::Extension> extension =
       LoadAndExpectSuccess(manifest);
@@ -191,7 +207,7 @@
 
 TEST_F(OAuth2ManifestTest, AutoApproveNotSetExtensionOnWhitelist) {
   base::DictionaryValue* ext_manifest =
-      CreateManifest(AUTO_APPROVE_NOT_SET, true);
+      CreateManifest(AUTO_APPROVE_NOT_SET, true, CLIENT_ID_DEFAULT);
   Manifest manifest(ext_manifest, "test");
   scoped_refptr<extensions::Extension> extension =
       LoadAndExpectSuccess(manifest);
@@ -201,7 +217,7 @@
 
 TEST_F(OAuth2ManifestTest, AutoApproveFalseExtensionOnWhitelist) {
   base::DictionaryValue* ext_manifest =
-      CreateManifest(AUTO_APPROVE_FALSE, true);
+      CreateManifest(AUTO_APPROVE_FALSE, true, CLIENT_ID_DEFAULT);
   Manifest manifest(ext_manifest, "test");
   scoped_refptr<extensions::Extension> extension =
       LoadAndExpectSuccess(manifest);
@@ -211,7 +227,7 @@
 
 TEST_F(OAuth2ManifestTest, AutoApproveTrueExtensionOnWhitelist) {
   base::DictionaryValue* ext_manifest =
-      CreateManifest(AUTO_APPROVE_TRUE, true);
+      CreateManifest(AUTO_APPROVE_TRUE, true, CLIENT_ID_DEFAULT);
   Manifest manifest(ext_manifest, "test");
   scoped_refptr<extensions::Extension> extension =
       LoadAndExpectSuccess(manifest);
@@ -221,7 +237,7 @@
 
 TEST_F(OAuth2ManifestTest, AutoApproveInvalidExtensionOnWhitelist) {
   base::DictionaryValue* ext_manifest =
-      CreateManifest(AUTO_APPROVE_INVALID, true);
+      CreateManifest(AUTO_APPROVE_INVALID, true, CLIENT_ID_DEFAULT);
   Manifest manifest(ext_manifest, "test");
   std::string error;
   scoped_refptr<extensions::Extension> extension =
@@ -231,4 +247,76 @@
       error);
 }
 
+TEST_F(OAuth2ManifestTest, InvalidClientId) {
+  {
+    base::DictionaryValue* ext_manifest =
+        CreateManifest(AUTO_APPROVE_NOT_SET, false, CLIENT_ID_NOT_SET);
+    Manifest manifest(ext_manifest, "test");
+    std::string error;
+    LoadAndExpectError(manifest, errors::kInvalidOAuth2ClientId);
+  }
+
+  {
+    base::DictionaryValue* ext_manifest =
+        CreateManifest(AUTO_APPROVE_NOT_SET, false, CLIENT_ID_EMPTY);
+    Manifest manifest(ext_manifest, "test");
+    std::string error;
+    LoadAndExpectError(manifest, errors::kInvalidOAuth2ClientId);
+  }
+}
+
+TEST_F(OAuth2ManifestTest, ComponentInvalidClientId) {
+  // Component Apps without auto_approve must include a client ID.
+  {
+    base::DictionaryValue* ext_manifest =
+        CreateManifest(AUTO_APPROVE_NOT_SET, false, CLIENT_ID_NOT_SET);
+    Manifest manifest(ext_manifest, "test");
+    std::string error;
+    LoadAndExpectError(manifest,
+                       errors::kInvalidOAuth2ClientId,
+                       extensions::Manifest::COMPONENT);
+  }
+
+  {
+    base::DictionaryValue* ext_manifest =
+        CreateManifest(AUTO_APPROVE_NOT_SET, false, CLIENT_ID_EMPTY);
+    Manifest manifest(ext_manifest, "test");
+    std::string error;
+    LoadAndExpectError(manifest,
+                       errors::kInvalidOAuth2ClientId,
+                       extensions::Manifest::COMPONENT);
+  }
+}
+
+TEST_F(OAuth2ManifestTest, ComponentWithChromeClientId) {
+  {
+    base::DictionaryValue* ext_manifest =
+        CreateManifest(AUTO_APPROVE_TRUE, true, CLIENT_ID_NOT_SET);
+    Manifest manifest(ext_manifest, "test");
+    scoped_refptr<extensions::Extension> extension =
+        LoadAndExpectSuccess(manifest, extensions::Manifest::COMPONENT);
+    EXPECT_TRUE(OAuth2Info::GetOAuth2Info(extension.get()).client_id.empty());
+
+  }
+
+  {
+    base::DictionaryValue* ext_manifest =
+        CreateManifest(AUTO_APPROVE_TRUE, true, CLIENT_ID_EMPTY);
+    Manifest manifest(ext_manifest, "test");
+    scoped_refptr<extensions::Extension> extension =
+        LoadAndExpectSuccess(manifest, extensions::Manifest::COMPONENT);
+    EXPECT_TRUE(OAuth2Info::GetOAuth2Info(extension.get()).client_id.empty());
+
+  }
+}
+
+TEST_F(OAuth2ManifestTest, ComponentWithStandardClientId) {
+  base::DictionaryValue* ext_manifest =
+      CreateManifest(AUTO_APPROVE_TRUE, true, CLIENT_ID_DEFAULT);
+  Manifest manifest(ext_manifest, "test");
+  scoped_refptr<extensions::Extension> extension =
+      LoadAndExpectSuccess(manifest, extensions::Manifest::COMPONENT);
+  EXPECT_EQ("client1", OAuth2Info::GetOAuth2Info(extension.get()).client_id);
+}
+
 }  // namespace extensions
diff --git a/chrome/common/extensions/api/identity/oauth2_manifest_handler.cc b/chrome/common/extensions/api/identity/oauth2_manifest_handler.cc
index 5bb617d..67df919 100644
--- a/chrome/common/extensions/api/identity/oauth2_manifest_handler.cc
+++ b/chrome/common/extensions/api/identity/oauth2_manifest_handler.cc
@@ -48,9 +48,26 @@
                                   string16* error) {
   scoped_ptr<OAuth2Info> info(new OAuth2Info);
   const base::DictionaryValue* dict = NULL;
-  if (!extension->manifest()->GetDictionary(keys::kOAuth2, &dict) ||
-      !dict->GetString(kClientId, &info->client_id) ||
-      info->client_id.empty()) {
+  if (!extension->manifest()->GetDictionary(keys::kOAuth2, &dict)) {
+    *error = ASCIIToUTF16(errors::kInvalidOAuth2ClientId);
+    return false;
+  }
+
+  // HasPath checks for whether the manifest is allowed to have
+  // oauth2.auto_approve based on whitelist, and if it is present.
+  // GetBoolean reads the value of auto_approve directly from dict to prevent
+  // duplicate checking.
+  if (extension->manifest()->HasPath(keys::kOAuth2AutoApprove) &&
+      !dict->GetBoolean(kAutoApprove, &info->auto_approve)) {
+    *error = ASCIIToUTF16(errors::kInvalidOAuth2AutoApprove);
+    return false;
+  }
+
+  // Component apps using auto_approve may use Chrome's client ID by
+  // omitting the field.
+  if ((!dict->GetString(kClientId, &info->client_id) ||
+       info->client_id.empty()) &&
+      (extension->location() != Manifest::COMPONENT || !info->auto_approve)) {
     *error = ASCIIToUTF16(errors::kInvalidOAuth2ClientId);
     return false;
   }
@@ -70,16 +87,6 @@
     info->scopes.push_back(scope);
   }
 
-  // HasPath checks for whether the manifest is allowed to have
-  // oauth2.auto_approve based on whitelist, and if it is present.
-  // GetBoolean reads the value of auto_approve directly from dict to prevent
-  // duplicate checking.
-  if (extension->manifest()->HasPath(keys::kOAuth2AutoApprove) &&
-      !dict->GetBoolean(kAutoApprove, &info->auto_approve)) {
-    *error = ASCIIToUTF16(errors::kInvalidOAuth2AutoApprove);
-    return false;
-  }
-
   extension->SetManifestData(keys::kOAuth2, info.release());
   return true;
 }
diff --git a/chrome/common/extensions/api/identity_private.idl b/chrome/common/extensions/api/identity_private.idl
index 2f44ffe..201d4b6 100644
--- a/chrome/common/extensions/api/identity_private.idl
+++ b/chrome/common/extensions/api/identity_private.idl
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// identityPrivate.
 namespace identityPrivate {
 
   callback GetResourcesCallback = void (object result);
diff --git a/chrome/common/extensions/api/idle.json b/chrome/common/extensions/api/idle.json
index 3672056..153e931 100644
--- a/chrome/common/extensions/api/idle.json
+++ b/chrome/common/extensions/api/idle.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "idle",
+    "description": "Use the <code>chrome.idle</code> API to detect when the machine's idle state changes.",
     "types": [],
     "functions": [
       {
diff --git a/chrome/common/extensions/api/input_ime.json b/chrome/common/extensions/api/input_ime.json
index ce2cfc9..9a7b170 100644
--- a/chrome/common/extensions/api/input_ime.json
+++ b/chrome/common/extensions/api/input_ime.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "input.ime",
+    "description": "Use the <code>chrome.input.ime</code> API to implement a custom IME for Chrome OS. This allows your extension to handle keystrokes, set the composition, and manage the candidate window.",
     "platforms": ["chromeos"],
     "types": [
       {
diff --git a/chrome/common/extensions/api/input_method_private.json b/chrome/common/extensions/api/input_method_private.json
index d49c099..9b40b62 100644
--- a/chrome/common/extensions/api/input_method_private.json
+++ b/chrome/common/extensions/api/input_method_private.json
@@ -5,9 +5,8 @@
 [
   {
     "namespace": "inputMethodPrivate",
-    "nodoc": true,
     "platforms": ["chromeos"],
-    "types": [],
+    "description": "none",
     "functions": [
       {
         "name": "get",
diff --git a/chrome/common/extensions/api/location.idl b/chrome/common/extensions/api/location.idl
index 9a33ee0..0900c8f 100644
--- a/chrome/common/extensions/api/location.idl
+++ b/chrome/common/extensions/api/location.idl
@@ -1,8 +1,11 @@
 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
-
 // TODO(vadimt): Consider reusing WebKit/Blink types, if this is possible.
+
+// The <code>chrome.location</code> API augments the events from the
+// <a href="http://dev.w3.org/geo/api/spec-source.html">HTML Geolocation API</a>
+// to be event page compatible.
 namespace location {
   // Coordinates part of the Location object.
   dictionary Coordinates {
diff --git a/chrome/common/extensions/api/management.json b/chrome/common/extensions/api/management.json
index c4890f1..8ac1f07 100644
--- a/chrome/common/extensions/api/management.json
+++ b/chrome/common/extensions/api/management.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace":"management",
+    "description": "The <code>chrome.management</code> API provides ways to manage the list of extensions/apps that are installed and running. It is particularly useful for extensions that <a href='override.html'>override</a> the built-in New Tab page.",
     "types": [
       {
         "id": "IconInfo",
diff --git a/chrome/common/extensions/api/manifest_types.json b/chrome/common/extensions/api/manifest_types.json
index 4f9588a..4fc77ed 100644
--- a/chrome/common/extensions/api/manifest_types.json
+++ b/chrome/common/extensions/api/manifest_types.json
@@ -8,6 +8,7 @@
 [
   {
     "namespace": "manifestTypes",
+    "description": "Schemas for structured manfiest entries",
     "types": [
       {
         "id": "ExternallyConnectable",
diff --git a/chrome/common/extensions/api/media_galleries.idl b/chrome/common/extensions/api/media_galleries.idl
index f1a92a4..0cd469b 100644
--- a/chrome/common/extensions/api/media_galleries.idl
+++ b/chrome/common/extensions/api/media_galleries.idl
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// Use the <code>chrome.mediaGalleries</code> API to access media files (images,
+// video, audio) from the user's local disks (with the user's consent).
 namespace mediaGalleries {
 
   [inline_doc] enum GetMediaFileSystemsInteractivity {
@@ -19,7 +21,9 @@
     // before returning the permitted set. Default is silent.  If the value
     // 'yes' is passed, or if the application has not been granted access to
     // any media galleries and the value 'if_needed' is passed, then the
-    // media gallery configuration dialog will be displayed.
+    // media gallery configuration dialog will be displayed. A user
+    // gesture is required for the display of the dialog. (i.e. making the call
+    // in the context of a button press)
     GetMediaFileSystemsInteractivity? interactive;
   };
 
diff --git a/chrome/common/extensions/api/media_galleries_private.idl b/chrome/common/extensions/api/media_galleries_private.idl
index 80acb0f..6ecb4e3 100644
--- a/chrome/common/extensions/api/media_galleries_private.idl
+++ b/chrome/common/extensions/api/media_galleries_private.idl
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// This is a private API for M23. This will be superceded by the
-// systeminfo.storage API in M24.
-
+// This is a private API since M23. This will be superceded by the
+// systeminfo.storage API in the future.
+// See http://crbug.com/166950 and http://crbug.com/177605.
 namespace mediaGalleriesPrivate {
   // A dictionary that describes an attached device.
   [inline_doc] dictionary DeviceAttachmentDetails {
diff --git a/chrome/common/extensions/api/media_player_private.json b/chrome/common/extensions/api/media_player_private.json
index 60f394c..da31398 100644
--- a/chrome/common/extensions/api/media_player_private.json
+++ b/chrome/common/extensions/api/media_player_private.json
@@ -5,10 +5,10 @@
 [
   {
     "namespace": "mediaPlayerPrivate",
-    "nodoc": "true",
     "compiler_options": {
       "implemented_in": "chrome/browser/chromeos/extensions/media_player_api.h"
     },
+    "description": "none",
     "platforms": ["chromeos"],
     "types": [
       {
diff --git a/chrome/common/extensions/api/metrics_private.json b/chrome/common/extensions/api/metrics_private.json
index 2e86f88..627687c 100644
--- a/chrome/common/extensions/api/metrics_private.json
+++ b/chrome/common/extensions/api/metrics_private.json
@@ -5,7 +5,7 @@
 [
   {
     "namespace": "metricsPrivate",
-    "nodoc": true,
+    "description": "none",
     "types": [
       {
         "id": "MetricType",
@@ -41,6 +41,22 @@
         ]
       },
       {
+        "name": "getFieldTrial",
+        "description": "Returns the group name chosen for the named trial, or the empty string if the trial does not exist or is not enabled.",
+        "type": "function",
+        "parameters": [
+          {"name": "name", "type": "string"},
+          {
+            "name": "callback",
+            "type": "function",
+            "optional": "false",
+            "parameters": [
+              { "name": "group", "type": "string" }
+            ]
+          }
+        ]
+      },
+      {
         "name": "recordUserAction",
         "type": "function",
         "description": "Records an action performed by the user.",
diff --git a/chrome/common/extensions/api/music_manager_private.idl b/chrome/common/extensions/api/music_manager_private.idl
index 5997d70..d1dbfae 100644
--- a/chrome/common/extensions/api/music_manager_private.idl
+++ b/chrome/common/extensions/api/music_manager_private.idl
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// musicManagerPrivate.
 [nodoc] namespace musicManagerPrivate {
 
   callback GetDeviceIdCallback = void (DOMString device_id);
diff --git a/chrome/common/extensions/api/networking_private.json b/chrome/common/extensions/api/networking_private.json
index b0901c5..14640ef 100644
--- a/chrome/common/extensions/api/networking_private.json
+++ b/chrome/common/extensions/api/networking_private.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace":"networkingPrivate",
+    "description": "none",
     "compiler_options": {
       "implemented_in": "chrome/browser/chromeos/extensions/networking_private_api.h"
     },
diff --git a/chrome/common/extensions/api/notifications.idl b/chrome/common/extensions/api/notifications.idl
index cba11d4..321cd5c 100644
--- a/chrome/common/extensions/api/notifications.idl
+++ b/chrome/common/extensions/api/notifications.idl
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// Use the <code>chrome.notifications</code> API to create rich notifications
+// using templates and show these notifications to users in the system tray.
 namespace notifications {
   [noinline_doc] enum TemplateType {
     // icon, title, message, expandedMessage, up to two buttons
diff --git a/chrome/common/extensions/api/omnibox.json b/chrome/common/extensions/api/omnibox.json
index a9e51e5..9d43836 100644
--- a/chrome/common/extensions/api/omnibox.json
+++ b/chrome/common/extensions/api/omnibox.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "omnibox",
+    "description": "The omnibox API allows you to register a keyword with Google Chrome's address bar, which is also known as the omnibox.",
     "types": [
       {
         "id": "SuggestResult",
diff --git a/chrome/common/extensions/api/page_action.json b/chrome/common/extensions/api/page_action.json
index 5214283..09c4964 100644
--- a/chrome/common/extensions/api/page_action.json
+++ b/chrome/common/extensions/api/page_action.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "pageAction",
+    "description": "Use the <code>chrome.pageAction</code> API to put icons inside the address bar. Page actions represent actions that can be taken on the current page, but that aren't applicable to all pages.",
     "types": [
       {
         "id": "ImageDataType",
diff --git a/chrome/common/extensions/api/page_actions.json b/chrome/common/extensions/api/page_actions.json
index 7283439..d991860 100644
--- a/chrome/common/extensions/api/page_actions.json
+++ b/chrome/common/extensions/api/page_actions.json
@@ -5,9 +5,8 @@
 [
   {
     "namespace": "pageActions",
-    "nodoc": true,
+    "description": "none",
     "maximumManifestVersion": 1,
-    "types": [],
     "functions": [
       {
         "name": "enableForTab",
diff --git a/chrome/common/extensions/api/page_capture.json b/chrome/common/extensions/api/page_capture.json
index 5c97410..f796d69 100644
--- a/chrome/common/extensions/api/page_capture.json
+++ b/chrome/common/extensions/api/page_capture.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "pageCapture",
+    "description": "Use the <code>chrome.pageCapture</code> API to save a tab as MHTML.",
     "functions": [
       {
         "name": "saveAsMHTML",
diff --git a/chrome/common/extensions/api/page_launcher.idl b/chrome/common/extensions/api/page_launcher.idl
index deef68a..fceab2b 100644
--- a/chrome/common/extensions/api/page_launcher.idl
+++ b/chrome/common/extensions/api/page_launcher.idl
@@ -2,9 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// This module allows platform apps an additional way of launching themselves
-// from the browser. To use this api, an app needs to specify the page_launcher
-// manifest property, then register to listen to pageLauncher.onClicked events.
+// Use the <code>chrome.pageLauncher</code> API to provide platform apps with
+// an additional way of launching themselves from the browser. To use this api,
+// an app needs to specify the page_launcher manifest property, then register to
+// listen to pageLauncher.onClicked events.
 namespace pageLauncher {
   // Information about the page the user was on when the event was fired.
   dictionary PageData {
diff --git a/chrome/common/extensions/api/permissions.json b/chrome/common/extensions/api/permissions.json
index d4a8689..f6a03b7 100644
--- a/chrome/common/extensions/api/permissions.json
+++ b/chrome/common/extensions/api/permissions.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "permissions",
+    "description": "Use the <code>chrome.permissions</code> API to implement optional permissions. As of Chrome 16, you can request optional permissions during your extension's regular application flow rather than at install time, so users understand why the permissions are needed and use only those that are necessary.",
     "types": [
       {
         "id": "Permissions",
diff --git a/chrome/common/extensions/api/preferences_private.json b/chrome/common/extensions/api/preferences_private.json
index ea64053..c68b08d 100644
--- a/chrome/common/extensions/api/preferences_private.json
+++ b/chrome/common/extensions/api/preferences_private.json
@@ -5,7 +5,7 @@
 [
   {
     "namespace": "preferencesPrivate",
-    "nodoc": true,
+    "description": "none",
     "properties": {
       "googleGeolocationAccessEnabled": {
         "$ref": "types.ChromeSetting",
diff --git a/chrome/common/extensions/api/privacy.json b/chrome/common/extensions/api/privacy.json
index abf4073..03845c9 100644
--- a/chrome/common/extensions/api/privacy.json
+++ b/chrome/common/extensions/api/privacy.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "privacy",
+    "description": "Use the <code>chrome.privacy</code> API to control usage of the features in Chrome that can affect a user's privacy. This API relies on the <a href='types.html#ChromeSetting'>ChromeSetting prototype of the type API</a> for getting and setting Chrome's configuration.",
     "properties": {
       "network": {
         "type": "object",
diff --git a/chrome/common/extensions/api/proxy.json b/chrome/common/extensions/api/proxy.json
index 9eabd8c..2d28bb6 100644
--- a/chrome/common/extensions/api/proxy.json
+++ b/chrome/common/extensions/api/proxy.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "proxy",
+    "description": "Use the <code>chrome.proxy</code> API to manage Chrome's proxy settings. This API relies on the <a href='types.html#ChromeSetting'>ChromeSetting prototype of the type API</a> for getting and setting the proxy configuration.",
     "types": [
       {
         "id": "ProxyServer",
diff --git a/chrome/common/extensions/api/push_messaging.idl b/chrome/common/extensions/api/push_messaging.idl
index 9cdf753..7d3f417 100644
--- a/chrome/common/extensions/api/push_messaging.idl
+++ b/chrome/common/extensions/api/push_messaging.idl
@@ -2,7 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-namespace pushMessaging{
+// Use <code>chrome.pushMessaging</code> to enable apps and extensions to
+// receive message data sent through
+// <a href="cloudMessaging">Google Cloud Messaging</a>.
+namespace pushMessaging {
 
   dictionary Message {
     // The subchannel the message was sent on;
diff --git a/chrome/common/extensions/api/rtc_private.idl b/chrome/common/extensions/api/rtc_private.idl
index 88e775f..73e26af 100644
--- a/chrome/common/extensions/api/rtc_private.idl
+++ b/chrome/common/extensions/api/rtc_private.idl
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// rtcPrivate.
 namespace rtcPrivate {
   // Launch action type.
   enum ActionType {chat, voice, video};
diff --git a/chrome/common/extensions/api/runtime.json b/chrome/common/extensions/api/runtime.json
index d3bef58..4be0200 100644
--- a/chrome/common/extensions/api/runtime.json
+++ b/chrome/common/extensions/api/runtime.json
@@ -5,6 +5,8 @@
 [
   {
     "namespace": "runtime",
+    "description": "Use the <code>chrome.runtime</code> API to retrieve the background page, return details about the manifest, and listen for and respond to events in the app or extension lifecycle. You can also use this API to convert the relative path of URLs to fully-qualified URLs.",
+    "documentation_permissions_required": ["runtime"],
     "types": [
       {
         "id": "Port",
@@ -370,9 +372,12 @@
         ]
       },
       {
+        // TODO(xiyuan): onBrowserUpdateAvailable is deprecated in favor of
+        // onRestartRequired. We should remove it when we are sure it is unused.
         "name": "onBrowserUpdateAvailable",
         "type": "function",
         "description": "Fired when a Chrome update is available, but isn't installed immediately because a browser restart is required.",
+        "nodoc": true,
         "parameters": []
       },
       {
@@ -426,10 +431,20 @@
           "optional": "true",
           "description": "Return true from the event listener if you wish to call <code>sendResponse</code> after the event listener returns."
         }
+      },
+      {
+        "name": "onRestartRequired",
+        "type": "function",
+        "description": "Fired when an app or the device that it runs on needs to be restarted. The app should close all its windows at its earliest convenient time to let the restart to happen. If the app does nothing, a restart will be enforced after a 24-hour grace period has passed. Currently, this event is only fired for Chrome OS kiosk apps.",
+        "parameters": [
+          {
+            "type": "string",
+            "name": "reason",
+            "description": "The reason that the event is being dispatched. 'app_update' is used when the restart is needed because the application is updated to a newer version. 'os_update' is used when the restart is needed because the browser/OS is updated to a newer version. 'periodic' is used when the system runs for more than the permitted uptime set in the enterprise policy.",
+            "enum": ["app_update", "os_update", "periodic"]
+          }
+        ]
       }
-
-
-
     ]
   }
 ]
diff --git a/chrome/common/extensions/api/script_badge.json b/chrome/common/extensions/api/script_badge.json
index 43df1e0..e9051c2 100644
--- a/chrome/common/extensions/api/script_badge.json
+++ b/chrome/common/extensions/api/script_badge.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "scriptBadge",
+    "description": "Use the <code>chrome.scriptBadge</code> API to control the behaviour of the script badge.",
     "functions": [
       {
         "name": "setPopup",
diff --git a/chrome/common/extensions/api/serial.idl b/chrome/common/extensions/api/serial.idl
index 6aad781..1df7550 100644
--- a/chrome/common/extensions/api/serial.idl
+++ b/chrome/common/extensions/api/serial.idl
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// Use the <code>chrome.serial</code> API to read from and write to a device
+// connected to a serial port.
 namespace serial {
 
   callback GetPortsCallback = void (DOMString[] ports);
diff --git a/chrome/common/extensions/api/session_restore.json b/chrome/common/extensions/api/session_restore.json
index 6071194..e44a59c 100644
--- a/chrome/common/extensions/api/session_restore.json
+++ b/chrome/common/extensions/api/session_restore.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "sessionRestore",
+    "description": "Use the <code>chrome.sessionRestore</code> API to query and restore tabs and windows from a browsing session.",
     "types": [
       {
         "id": "ClosedEntry",
@@ -26,7 +27,7 @@
           {
             "type": "object",
             "name": "options",
-            "optional": true, 
+            "optional": true,
             "properties": {
               "maxResults": {
                 "type": "integer",
diff --git a/chrome/common/extensions/api/socket.idl b/chrome/common/extensions/api/socket.idl
index 4bc6068..e727d84 100644
--- a/chrome/common/extensions/api/socket.idl
+++ b/chrome/common/extensions/api/socket.idl
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// Use the <code>chrome.socket</code> API to send and receive data over the
+// network using TCP and UDP connections.
 namespace socket {
   enum SocketType {
     tcp,
@@ -267,18 +269,18 @@
     // before calling this method.
     // |socketId| : The socketId.
     // |address| : The group address to join. Domain names are not supported.
-    // |callback| : Called when the join group operation is done with an 
+    // |callback| : Called when the join group operation is done with an
     // integer parameter indicating the platform-independent error code.
     static void joinGroup(long socketId,
                           DOMString address,
                           JoinGroupCallback callback);
 
     // Leave the multicast group previously joined using <code>joinGroup</code>.
-    // It's not necessary to leave the multicast group before destroying the 
+    // It's not necessary to leave the multicast group before destroying the
     // socket or exiting. This is automatically called by the OS.
     //
-    // Leaving the group will prevent the router from sending multicast 
-    // datagrams to the local host, presuming no other process on the host is 
+    // Leaving the group will prevent the router from sending multicast
+    // datagrams to the local host, presuming no other process on the host is
     // still joined to the group.
     //
     // |socketId| : The socketId.
@@ -300,7 +302,7 @@
         long ttl,
         SetMulticastTimeToLiveCallback callback);
 
-    // Set whether multicast packets sent from the host to the multicast 
+    // Set whether multicast packets sent from the host to the multicast
     // group will be looped back to the host.
     //
     // Note: the behavior of <code>setMulticastLoopbackMode</code> is slightly
diff --git a/chrome/common/extensions/api/storage.json b/chrome/common/extensions/api/storage.json
index db7d7fa..e1bcf98 100644
--- a/chrome/common/extensions/api/storage.json
+++ b/chrome/common/extensions/api/storage.json
@@ -5,6 +5,8 @@
 [
   {
     "namespace": "storage",
+    "description": "Use the <code>chrome.storage</code> API to store, retrieve, and track changes to user data.",
+    "unprivileged": true,
     "types": [
       {
         "id": "StorageChange",
diff --git a/chrome/common/extensions/api/streams_private.json b/chrome/common/extensions/api/streams_private.json
index f6134e0..f248345 100644
--- a/chrome/common/extensions/api/streams_private.json
+++ b/chrome/common/extensions/api/streams_private.json
@@ -5,9 +5,7 @@
 [
   {
     "namespace":"streamsPrivate",
-    "types": [
-    ],
-
+    "description": "none",
     "events": [
       {
         "name": "onExecuteMimeTypeHandler",
diff --git a/chrome/common/extensions/api/sync_file_system.idl b/chrome/common/extensions/api/sync_file_system.idl
index c772c70..3c7afb1 100644
--- a/chrome/common/extensions/api/sync_file_system.idl
+++ b/chrome/common/extensions/api/sync_file_system.idl
@@ -2,6 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// Use the <code>chrome.syncFileSystem</code> API to save and synchronize data
+// on Google Drive. This API is NOT for accessing arbitrary user docs stored in
+// Google Drive. It provides app-specific syncable storage for offline and
+// caching usage so that the same data can be available across different
+// clients. Read
+// <a href="http://developer.chrome.com/trunk/apps/app_storage.html">Manage
+// Data</a> for more on using this API.
 namespace syncFileSystem {
   enum SyncAction {
     added, updated, deleted
diff --git a/chrome/common/extensions/api/system_info_cpu.idl b/chrome/common/extensions/api/system_info_cpu.idl
index ee61007..cb54340 100644
--- a/chrome/common/extensions/api/system_info_cpu.idl
+++ b/chrome/common/extensions/api/system_info_cpu.idl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// File-level comment to appease parser. Eventually this will not be necessary.
+// Use the <code>systemInfo.cpu</code> API to query CPU metadata.
 namespace systemInfo.cpu {
 
   dictionary CpuInfo {
@@ -15,7 +15,7 @@
   };
 
   callback CpuInfoCallback = void (CpuInfo info);
-  
+
   interface Functions {
     // Queries basic CPU information of the system.
     static void get(CpuInfoCallback callback);
diff --git a/chrome/common/extensions/api/system_info_display.idl b/chrome/common/extensions/api/system_info_display.idl
index cf225e3..71c4a8b 100644
--- a/chrome/common/extensions/api/system_info_display.idl
+++ b/chrome/common/extensions/api/system_info_display.idl
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// Use the <code>systemInfo.display</code> API to query display metadata.
 namespace systemInfo.display {
 
   dictionary Bounds {
@@ -35,16 +36,16 @@
   dictionary DisplayUnitInfo {
     // The unique identifier of the display.
     DOMString id;
-    
+
     // The user-friendly name (e.g. "HP LCD monitor").
     DOMString name;
-  
+
     // Identifier of the display that is being mirrored on the display unit.
     // If mirroring is not in progress, set to an empty string.
     // Currently exposed only on ChromeOS. Will be empty string on other
     // platforms.
     DOMString mirroringSourceId;
-  
+
     // True if this is the primary display.
     boolean isPrimary;
 
@@ -87,22 +88,22 @@
     // the specified id (if mirroring is in progress).
     // If set, no other parameter may be set.
     DOMString? mirroringSourceId;
-  
+
     // If set to true, makes the display primary. No-op if set to false.
     boolean? isPrimary;
- 
+
     // If set, sets the display's overscan insets to the provided values. Note
     // that overscan values may not be negative or larger than a half of the
     // screen's size. Overscan cannot be changed on the internal monitor.
     // It's applied after <code>isPrimary</code> parameter.
     Insets? overscan;
- 
+
     // If set, updates the display's rotation.
     // Legal values are [0, 90, 180, 270]. The rotation is set clockwise,
     // relative to the display's vertical position.
     // It's applied after <code>overscan</code> paramter.
     long? rotation;
- 
+
     // If set, updates the display's logical bounds origin along x-axis. Applied
     // together with <code>boundsOriginY</code>, if <code>boundsOriginY</code>
     // is set. Note that, when updating the display origin, some constraints
@@ -113,12 +114,12 @@
     // also invalid to set bounds origin values if <code>isPrimary</code> is
     // also set (as <code>isPrimary</code> parameter is applied first).
     long? boundsOriginX;
- 
+
     // If set, updates the display's logical bounds origin along y-axis.
     // See documentation for <code>boundsOriginX</code> parameter.
     long? boundsOriginY;
   };
-  
+
   callback DisplayInfoCallback = void (DisplayUnitInfo[] displayInfo);
   callback SetDisplayUnitInfoCallback = void();
 
@@ -135,13 +136,13 @@
     //     |info|.
     // |callback|: Empty function called when the function finishes. To find out
     //     whether the function succeeded, $ref:runtime.lastError should be
-    //     queried. 
+    //     queried.
     static void setDisplayProperties(
         DOMString id,
         DisplayProperties info,
         optional SetDisplayUnitInfoCallback callback);
   };
-  
+
   interface Events {
     // Fired when anything changes to the display configuration.
     static void onDisplayChanged();
diff --git a/chrome/common/extensions/api/system_private.json b/chrome/common/extensions/api/system_private.json
index ec6cc53..7d95450 100644
--- a/chrome/common/extensions/api/system_private.json
+++ b/chrome/common/extensions/api/system_private.json
@@ -5,7 +5,7 @@
 [
   {
     "namespace": "systemPrivate",
-    "nodoc": true,
+    "description": "none",
     "types": [
       {
         "id": "UpdateStatus",
diff --git a/chrome/common/extensions/api/tab_capture.idl b/chrome/common/extensions/api/tab_capture.idl
index dbd1d67..7e1d5c3 100644
--- a/chrome/common/extensions/api/tab_capture.idl
+++ b/chrome/common/extensions/api/tab_capture.idl
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// An API for tab media streams.
-
+// Use the <code>chrome.tabCapture</code> API to interact with tab media
+// streams.
 namespace tabCapture {
 
   enum TabCaptureState {
diff --git a/chrome/common/extensions/api/tabs.json b/chrome/common/extensions/api/tabs.json
index f3fb008..f3b37a6 100644
--- a/chrome/common/extensions/api/tabs.json
+++ b/chrome/common/extensions/api/tabs.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "tabs",
+    "description": "Use the <code>chrome.tabs</code> API to interact with the browser's tab system. You can use this API to create, modify, and rearrange tabs in the browser.",
     "types": [
       {
         "id": "Tab",
@@ -16,7 +17,7 @@
           "openerTabId": {"type": "integer", "minimum": 0, "optional": true, "description": "The ID of the tab that opened this tab, if any. This will only be present if the opener tab still exists."},
           "selected": {"type": "boolean", "description": "Whether the tab is selected.", "nodoc": true},
           "highlighted": {"type": "boolean", "description": "Whether the tab is highlighted."},
-          "active": {"type": "boolean", "description": "Whether the tab is active in its window."},
+          "active": {"type": "boolean", "description": "Whether the tab is active in its window. (Does not necessarily mean the window is focused.)"},
           "pinned": {"type": "boolean", "description": "Whether the tab is pinned."},
           "url": {"type": "string", "optional": true, "description": "The URL the tab is displaying. This will only be present if the extension has the 'tabs' or 'webNavigation' permission."},
           "title": {"type": "string", "optional": true, "optional": true, "description": "The title of the tab. This will only be present if the extension has the 'tabs' or 'webNavigation' permission. It may also be an empty string if the tab is loading."},
@@ -84,7 +85,7 @@
         "name": "connect",
         "nocompile": true,
         "type": "function",
-        "description": "Connects to the content script(s) in the specified tab. The $ref:runtime.onConnect event is fired in each content script running in the specified tab for the current extension. For more details, see <a href='content_scripts.html#messaging'>Content Script Messaging</a>.",
+        "description": "Connects to the content script(s) in the specified tab. The $ref:runtime.onConnect event is fired in each content script running in the specified tab for the current extension. For more details, see <a href='messaging.html'>Content Script Messaging</a>.",
         "parameters": [
           {
             "type": "integer",
@@ -237,7 +238,7 @@
               "active": {
                 "type": "boolean",
                 "optional": true,
-                "description": "Whether the tab should become the active tab in the window. Defaults to <var>true</var>"
+                "description": "Whether the tab should become the active tab in the window. Does not affect whether the window is focused (see $ref:windows.update). Defaults to <var>true</var>."
               },
               "selected": {
                 "nodoc": true,
@@ -444,7 +445,7 @@
               "active": {
                 "type": "boolean",
                 "optional": true,
-                "description": "Whether the tab should be active."
+                "description": "Whether the tab should be active. Does not affect whether the window is focused (see $ref:windows.update)."
               },
               "highlighted": {
                 "type": "boolean",
diff --git a/chrome/common/extensions/api/terminal_private.json b/chrome/common/extensions/api/terminal_private.json
index 79817cc..07bbe2d 100644
--- a/chrome/common/extensions/api/terminal_private.json
+++ b/chrome/common/extensions/api/terminal_private.json
@@ -8,9 +8,8 @@
     "compiler_options": {
       "implemented_in": "chrome/browser/extensions/api/terminal/terminal_private_api.h"
     },
-    "nodoc": true,
     "platforms": ["chromeos"],
-    "types": [],
+    "description": "none",
     "functions": [
       {
         "name": "openTerminalProcess",
diff --git a/chrome/common/extensions/api/test.json b/chrome/common/extensions/api/test.json
index e9a43d5..a06052d 100644
--- a/chrome/common/extensions/api/test.json
+++ b/chrome/common/extensions/api/test.json
@@ -5,8 +5,7 @@
 [
   {
     "namespace": "test",
-    "nodoc": true,
-    "types": [],
+    "description": "none",
     "functions": [
       {
         "name": "getConfig",
diff --git a/chrome/common/extensions/api/top_sites.json b/chrome/common/extensions/api/top_sites.json
index e220447..3a8ece8 100644
--- a/chrome/common/extensions/api/top_sites.json
+++ b/chrome/common/extensions/api/top_sites.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "topSites",
+    "description": "Use the <code>chrome.topSites</code> API to access the top sites that are displayed on the new tab page.",
     "types": [
       {
         "id": "MostVisitedURL",
diff --git a/chrome/common/extensions/api/tts.json b/chrome/common/extensions/api/tts.json
index 49bd4b2..ae8771e 100644
--- a/chrome/common/extensions/api/tts.json
+++ b/chrome/common/extensions/api/tts.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "tts",
+    "description": "Use the <code>chrome.tts</code> API to play synthesized text-to-speech (TTS). See also the related <a href='http://developer.chrome.com/extensions/ttsEngine.html'>ttsEngine</a> API, which allows an extension to implement a speech engine.",
     "types": [
       {
         "id": "TtsEvent",
diff --git a/chrome/common/extensions/api/tts_engine.json b/chrome/common/extensions/api/tts_engine.json
index 4c6bb26..8dd72b1 100644
--- a/chrome/common/extensions/api/tts_engine.json
+++ b/chrome/common/extensions/api/tts_engine.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "ttsEngine",
+    "description": "Use the <code>chrome.ttsEngine</code> API to implement a text-to-speech(TTS) engine using an extension. If your extension registers using this API, it will receive events containing an utterance to be spoken and other parameters when any extension or packaged app uses the <a href='tts.html'>tts</a> API to generate speech. Your extension can then use any available web technology to synthesize and output the speech, and send events back to the calling function to report the status.",
     "functions": [
       {
         "name": "sendTtsEvent",
diff --git a/chrome/common/extensions/api/types.json b/chrome/common/extensions/api/types.json
index 7b80460..0ed8428 100644
--- a/chrome/common/extensions/api/types.json
+++ b/chrome/common/extensions/api/types.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "types",
+    "description": "The <code>chrome.types</code> API contains type declarations for Chrome. Currently, this comprises only a prototype for giving other APIs access to manage Chrome browser settings. This prototype is used, for example, for $ref:proxy.settings.",
     "types": [
       {
         "id": "ChromeSetting",
diff --git a/chrome/common/extensions/api/usb.idl b/chrome/common/extensions/api/usb.idl
index 068f34b..1b757b0 100644
--- a/chrome/common/extensions/api/usb.idl
+++ b/chrome/common/extensions/api/usb.idl
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// Use the <code>chrome.usb</code> API to interact with connected USB
+// devices. This API provides access to USB operations from within the context
+// of an app. Using this API, apps can function as drivers for hardware devices.
 namespace usb {
 
   // Direction, Recipient, RequestType, and TransferType all map to their
diff --git a/chrome/common/extensions/api/wallpaper_private.json b/chrome/common/extensions/api/wallpaper_private.json
index bb8ca78..40b870a 100644
--- a/chrome/common/extensions/api/wallpaper_private.json
+++ b/chrome/common/extensions/api/wallpaper_private.json
@@ -9,7 +9,7 @@
       "implemented_in": "chrome/browser/chromeos/extensions/wallpaper_private_api.h"
     },
     "platforms": ["chromeos"],
-    "nodoc": "true",
+    "description": "none",
     "functions": [
       {
         "name": "getStrings",
diff --git a/chrome/common/extensions/api/web_navigation.json b/chrome/common/extensions/api/web_navigation.json
index 9fa1759..783ecdd 100644
--- a/chrome/common/extensions/api/web_navigation.json
+++ b/chrome/common/extensions/api/web_navigation.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "webNavigation",
+    "description": "Use the <code>chrome.webNavigation</code> API to receive notifications about the status of navigation requests in-flight.",
     "types": [],
     "functions": [
       {
diff --git a/chrome/common/extensions/api/web_request.json b/chrome/common/extensions/api/web_request.json
index 5a96a8c..6fd2b14 100644
--- a/chrome/common/extensions/api/web_request.json
+++ b/chrome/common/extensions/api/web_request.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "webRequest",
+    "description": "Use the <code>chrome.webRequest</code> API to observe and analyze traffic and to intercept, block, or modify requests in-flight.",
     "properties": {
       "MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES": {
         "value": 20,
diff --git a/chrome/common/extensions/api/web_request_internal.json b/chrome/common/extensions/api/web_request_internal.json
index fbdc7fa..4c56b5d 100644
--- a/chrome/common/extensions/api/web_request_internal.json
+++ b/chrome/common/extensions/api/web_request_internal.json
@@ -5,7 +5,7 @@
 [
   {
     "namespace": "webRequestInternal",
-    "nodoc": true,
+    "description": "none",
     "functions": [
       {
         "name": "addEventListener",
diff --git a/chrome/common/extensions/api/web_socket_proxy_private.json b/chrome/common/extensions/api/web_socket_proxy_private.json
index 4afa792..3666079 100644
--- a/chrome/common/extensions/api/web_socket_proxy_private.json
+++ b/chrome/common/extensions/api/web_socket_proxy_private.json
@@ -5,8 +5,7 @@
 [
   {
     "namespace": "webSocketProxyPrivate",
-    "nodoc": true,
-    "types": [],
+    "description": "none",
     "functions": [
       {
         "name": "getPassportForTCP",
diff --git a/chrome/common/extensions/api/webstore.json b/chrome/common/extensions/api/webstore.json
index 2b72c0c..31cbd2d 100644
--- a/chrome/common/extensions/api/webstore.json
+++ b/chrome/common/extensions/api/webstore.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "webstore",
+    "description": "Use the <code>chrome.webstore</code> API to initiate app and extension installations \"inline\" from your site.",
     "functions": [
       {
         "name": "install",
diff --git a/chrome/common/extensions/api/webstore_private.json b/chrome/common/extensions/api/webstore_private.json
index 83fb48d..f80ff33 100644
--- a/chrome/common/extensions/api/webstore_private.json
+++ b/chrome/common/extensions/api/webstore_private.json
@@ -5,7 +5,7 @@
 [
   {
     "namespace":"webstorePrivate",
-    "nodoc": "true",
+    "description": "none",
     "functions": [
       {
         "name": "install",
@@ -238,6 +238,20 @@
             ]
           }
         ]
+      },
+      {
+        "name": "isInIncognitoMode",
+        "description": "Returns whether the browser is in incognito mode or not.",
+        "parameters": [
+          {
+            "name": "callback",
+            "type": "function",
+            "optional": "false",
+            "parameters": [
+              { "name": "is_incognito", "type": "boolean" }
+            ]
+          }
+        ]
       }
     ]
   }
diff --git a/chrome/common/extensions/api/webview.json b/chrome/common/extensions/api/webview.json
index 0fe91eb..bdfd844 100644
--- a/chrome/common/extensions/api/webview.json
+++ b/chrome/common/extensions/api/webview.json
@@ -5,7 +5,7 @@
 [
   {
     "namespace": "webview",
-    "nodoc": true,
+    "description": "none",
     "functions": [
       {
         "name": "executeScript",
@@ -70,6 +70,20 @@
             ]
           }
         ]
+      },
+      {
+        "name": "go",
+        "type": "function",
+        "parameters": [
+          {
+            "type": "integer",
+            "name": "instanceId"
+          },
+          {
+            "type": "integer",
+            "name": "relativeIndex"
+          }
+        ]
       }
     ]
   }
diff --git a/chrome/common/extensions/api/windows.json b/chrome/common/extensions/api/windows.json
index f59ce95..eaa6760 100644
--- a/chrome/common/extensions/api/windows.json
+++ b/chrome/common/extensions/api/windows.json
@@ -5,6 +5,7 @@
 [
   {
     "namespace": "windows",
+    "description": "Use the <code>chrome.windows</code> API to interact with browser windows. You can use this API to create, modify, and rearrange windows in the browser.",
     "compiler_options": {
       "implemented_in": "chrome/browser/extensions/api/tabs/tabs_api.h"
     },
diff --git a/chrome/common/extensions/docs/examples/api/nativeMessaging/host/native-messaging-example-host.bat b/chrome/common/extensions/docs/examples/api/nativeMessaging/host/native-messaging-example-host.bat
index 7793ee7..430179e 100755
--- a/chrome/common/extensions/docs/examples/api/nativeMessaging/host/native-messaging-example-host.bat
+++ b/chrome/common/extensions/docs/examples/api/nativeMessaging/host/native-messaging-example-host.bat
@@ -3,4 +3,4 @@
 :: Use of this source code is governed by a BSD-style license that can be
 :: found in the LICENSE file.
 
-python "%~dp0/native-messaging-example-host.py" %*
+python "%~dp0/native-messaging-example-host" %*
diff --git a/chrome/common/extensions/docs/examples/api/tabs/screenshot/background.js b/chrome/common/extensions/docs/examples/api/tabs/screenshot/background.js
index 3670b02..4124857 100644
--- a/chrome/common/extensions/docs/examples/api/tabs/screenshot/background.js
+++ b/chrome/common/extensions/docs/examples/api/tabs/screenshot/background.js
@@ -49,7 +49,7 @@
 
 // Listen for a click on the camera icon.  On that click, take a screenshot.
 chrome.browserAction.onClicked.addListener(function(tab) {
-  if (tab.url.match(/code.google.com/)) {
+  if (tab.url.match("^https?://code.google.com")) {
     takeScreenshot();
   } else {
     alert('This sample can only take screenshots of code.google.com pages');
diff --git a/chrome/common/extensions/docs/examples/api/tabs/screenshot/manifest.json b/chrome/common/extensions/docs/examples/api/tabs/screenshot/manifest.json
index 4376aa0..f7392b0 100644
--- a/chrome/common/extensions/docs/examples/api/tabs/screenshot/manifest.json
+++ b/chrome/common/extensions/docs/examples/api/tabs/screenshot/manifest.json
@@ -7,9 +7,11 @@
     "scripts": ["background.js"]
   },
   "browser_action": {
-     "default_icon": "camera.png",
-     "default_title": "Take a screen shot!"
+    "default_icon": "camera.png",
+    "default_title": "Take a screen shot!"
   },
-  "permissions": ["tabs", "http://code.google.com/"],
+  "permissions": [
+    "tabs", "*://code.google.com/"
+  ],
   "manifest_version": 2
 }
diff --git a/chrome/common/extensions/docs/examples/extensions/imageinfo/info.html b/chrome/common/extensions/docs/examples/extensions/imageinfo/info.html
index 5757f7d..4ca3a2e 100644
--- a/chrome/common/extensions/docs/examples/extensions/imageinfo/info.html
+++ b/chrome/common/extensions/docs/examples/extensions/imageinfo/info.html
@@ -4,7 +4,7 @@
  * source code is governed by a BSD-style license that can be found in the
  * LICENSE file.
 -->
-<html
+<html>
   <head>
     <script src="imageinfo/binaryajax.js"></script>
     <script src="imageinfo/imageinfo.js" ></script>
diff --git a/chrome/common/extensions/docs/server2/api_data_source.py b/chrome/common/extensions/docs/server2/api_data_source.py
index 7f3d32c..3fdd375 100644
--- a/chrome/common/extensions/docs/server2/api_data_source.py
+++ b/chrome/common/extensions/docs/server2/api_data_source.py
@@ -132,6 +132,7 @@
       return {}
     return {
       'name': self._namespace.name,
+      'description': self._namespace.description,
       'types': self._GenerateTypes(self._namespace.types.values()),
       'functions': self._GenerateFunctions(self._namespace.functions),
       'events': self._GenerateEvents(self._namespace.events),
diff --git a/chrome/common/extensions/docs/server2/app.yaml b/chrome/common/extensions/docs/server2/app.yaml
index 35c406b..b271d55 100644
--- a/chrome/common/extensions/docs/server2/app.yaml
+++ b/chrome/common/extensions/docs/server2/app.yaml
@@ -1,5 +1,5 @@
 application: chrome-apps-doc
-version: 2-7-1
+version: 2-8-1
 runtime: python27
 api_version: 1
 threadsafe: false
diff --git a/chrome/common/extensions/docs/server2/availability_finder.py b/chrome/common/extensions/docs/server2/availability_finder.py
new file mode 100644
index 0000000..4105703
--- /dev/null
+++ b/chrome/common/extensions/docs/server2/availability_finder.py
@@ -0,0 +1,247 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import collections
+import os
+
+from branch_utility import BranchUtility
+from compiled_file_system import CompiledFileSystem
+from file_system import FileNotFoundError
+import svn_constants
+from third_party.json_schema_compiler import json_parse, model
+from third_party.json_schema_compiler.memoize import memoize
+
+_API_AVAILABILITIES = svn_constants.JSON_PATH + '/api_availabilities.json'
+_API_FEATURES = svn_constants.API_PATH + '/_api_features.json'
+_EXTENSION_API = svn_constants.API_PATH + '/extension_api.json'
+_MANIFEST_FEATURES = svn_constants.API_PATH + '/_manifest_features.json'
+_PERMISSION_FEATURES = svn_constants.API_PATH + '/_permission_features.json'
+_STABLE = 'stable'
+
+class AvailabilityInfo(object):
+  def __init__(self, channel, version):
+    self.channel = channel
+    self.version = version
+
+def _GetChannelFromFeatures(api_name, file_system, path):
+  '''Finds API channel information within _features.json files at the given
+  |path| for the given |file_system|. Returns None if channel information for
+  the API cannot be located.
+  '''
+  feature = file_system.GetFromFile(path).get(api_name)
+
+  if feature is None:
+    return None
+  if isinstance(feature, collections.Mapping):
+    # The channel information dict is nested within a list for whitelisting
+    # purposes.
+    return feature.get('channel')
+  # Features can contain a list of entries. Take the newest branch.
+  return BranchUtility.NewestChannel(entry.get('channel')
+                                     for entry in feature)
+
+def _GetChannelFromApiFeatures(api_name, file_system):
+  try:
+    return _GetChannelFromFeatures(api_name, file_system, _API_FEATURES)
+  except FileNotFoundError as e:
+    # TODO(epeterson) Remove except block once _api_features is in all channels.
+    return None
+
+def _GetChannelFromPermissionFeatures(api_name, file_system):
+  return _GetChannelFromFeatures(api_name, file_system, _PERMISSION_FEATURES)
+
+def _GetChannelFromManifestFeatures(api_name, file_system):
+  return _GetChannelFromFeatures(#_manifest_features uses unix_style API names
+                                 model.UnixName(api_name),
+                                 file_system,
+                                 _MANIFEST_FEATURES)
+
+def _ExistsInFileSystem(api_name, file_system):
+  '''Checks for existence of |api_name| within the list of files in the api/
+  directory found using the given file system.
+  '''
+  file_names = file_system.GetFromFileListing(svn_constants.API_PATH)
+  # File names switch from unix_hacker_style to camelCase at versions <= 20.
+  return model.UnixName(api_name) in file_names or api_name in file_names
+
+def _ExistsInExtensionApi(api_name, file_system):
+  '''Parses the api/extension_api.json file (available in Chrome versions
+  before 18) for an API namespace. If this is successfully found, then the API
+  is considered to have been 'stable' for the given version.
+  '''
+  try:
+    extension_api_json = file_system.GetFromFile(_EXTENSION_API)
+    api_rows = [row.get('namespace') for row in extension_api_json
+                if 'namespace' in row]
+    return True if api_name in api_rows else False
+  except FileNotFoundError as e:
+    # This should only happen on preview.py since extension_api.json is no
+    # longer present in trunk.
+    return False
+
+class AvailabilityFinder(object):
+  '''Uses API data sources generated by a ChromeVersionDataSource in order to
+  search the filesystem for the earliest existence of a specified API throughout
+  the different versions of Chrome; this constitutes an API's availability.
+  '''
+  class Factory(object):
+    def __init__(self,
+                 object_store_creator,
+                 compiled_host_fs_factory,
+                 branch_utility,
+                 # Takes a |version|, and returns a caching offline or online
+                 # subversion file system for that version.
+                 create_file_system_at_version):
+      self._object_store_creator = object_store_creator
+      self._compiled_host_fs_factory = compiled_host_fs_factory
+      self._branch_utility = branch_utility
+      self._create_file_system_at_version = create_file_system_at_version
+
+    def Create(self):
+      return AvailabilityFinder(self._object_store_creator,
+                                self._compiled_host_fs_factory,
+                                self._branch_utility,
+                                self._create_file_system_at_version)
+
+  def __init__(self,
+               object_store_creator,
+               compiled_host_fs_factory,
+               branch_utility,
+               create_file_system_at_version):
+    self._object_store_creator = object_store_creator
+    self._json_cache = compiled_host_fs_factory.Create(
+        lambda _, json: json_parse.Parse(json),
+        AvailabilityFinder,
+        'json-cache')
+    self._branch_utility = branch_utility
+    self._create_file_system_at_version = create_file_system_at_version
+    self._object_store = object_store_creator.Create(AvailabilityFinder)
+
+  @memoize
+  def _CreateFeaturesAndNamesFileSystems(self, version):
+    '''The 'features' compiled file system's populate function parses and
+    returns the contents of a _features.json file. The 'names' compiled file
+    system's populate function creates a list of file names with .json or .idl
+    extensions.
+    '''
+    fs_factory = CompiledFileSystem.Factory(
+        self._create_file_system_at_version(version),
+        self._object_store_creator)
+    features_fs = fs_factory.Create(lambda _, json: json_parse.Parse(json),
+                                    AvailabilityFinder,
+                                    category='features')
+    names_fs = fs_factory.Create(self._GetExtNames,
+                                 AvailabilityFinder,
+                                 category='names')
+    return (features_fs, names_fs)
+
+  def _GetExtNames(self, base_path, apis):
+    return [os.path.splitext(api)[0] for api in apis
+            if os.path.splitext(api)[1][1:] in ['json', 'idl']]
+
+  def _FindEarliestStableAvailability(self, api_name, version):
+    '''Searches in descending order through filesystem caches tied to specific
+    chrome version numbers and looks for the availability of an API, |api_name|,
+    on the stable channel. When a version is found where the API is no longer
+    available on stable, returns the previous version number (the last known
+    version where the API was stable).
+    '''
+    available = True
+    while available:
+      if version < 5:
+        # SVN data isn't available below version 5.
+        return version + 1
+      available = False
+      features_fs, names_fs = self._CreateFeaturesAndNamesFileSystems(version)
+      if version >= 28:
+        # The _api_features.json file first appears in version 28 and should be
+        # the most reliable for finding API availabilities, so it gets checked
+        # first. The _permission_features.json and _manifest_features.json files
+        # are present in Chrome 20 and onwards. Fall back to a check for file
+        # system existence if the API is not stable in any of the _features.json
+        # files.
+        available = _GetChannelFromApiFeatures(api_name, features_fs) == _STABLE
+      if version >= 20:
+        # Check other _features.json files/file existence if the API wasn't
+        # found in _api_features.json, or if _api_features.json wasn't present.
+        available = available or (
+            _GetChannelFromPermissionFeatures(api_name, features_fs) == _STABLE
+            or _GetChannelFromManifestFeatures(api_name, features_fs) == _STABLE
+            or _ExistsInFileSystem(api_name, names_fs))
+      elif version >= 18:
+        # These versions are a little troublesome. Version 19 has
+        # _permission_features.json, but it lacks 'channel' information.
+        # Version 18 lacks all of the _features.json files. For now, we're using
+        # a simple check for filesystem existence here.
+        available = _ExistsInFileSystem(api_name, names_fs)
+      elif version >= 5:
+        # Versions 17 and down to 5 have an extension_api.json file which
+        # contains namespaces for each API that was available at the time. We
+        # can use this file to check for API existence.
+        available = _ExistsInExtensionApi(api_name, features_fs)
+
+      if not available:
+        return version + 1
+      version -= 1
+
+  def _GetAvailableChannelForVersion(self, api_name, version):
+    '''Searches through the _features files for a given |version| and returns
+    the channel that the given API is determined to be available on.
+    '''
+    features_fs, names_fs = self._CreateFeaturesAndNamesFileSystems(version)
+    channel = (_GetChannelFromApiFeatures(api_name, features_fs)
+               or _GetChannelFromPermissionFeatures(api_name, features_fs)
+               or _GetChannelFromManifestFeatures(api_name, features_fs))
+    if channel is None and _ExistsInFileSystem(api_name, names_fs):
+      # If an API is not represented in any of the _features files, but exists
+      # in the filesystem, then assume it is available in this version.
+      # The windows API is an example of this.
+      return self._branch_utility.GetChannelForVersion(version)
+
+    return channel
+
+  def GetApiAvailability(self, api_name):
+    '''Determines the availability for an API by testing several scenarios.
+    (i.e. Is the API experimental? Only available on certain development
+    channels? If it's stable, when did it first become stable? etc.)
+    '''
+    availability = self._object_store.Get(api_name).Get()
+    if availability is not None:
+      return availability
+
+    # Check for a predetermined availability for this API.
+    api_info = self._json_cache.GetFromFile(_API_AVAILABILITIES).get(api_name)
+    if api_info is not None:
+      channel = api_info.get('channel')
+      return AvailabilityInfo(
+          channel,
+          api_info.get('version') if channel == _STABLE else None)
+
+    # Check for the API in the development channels.
+    availability = None
+    for channel_info in self._branch_utility.GetAllChannelInfo():
+      available_channel = self._GetAvailableChannelForVersion(
+          api_name,
+          channel_info.version)
+      # If the |available_channel| for the API is the same as, or older than,
+      # the channel we're checking, then the API is available on this channel.
+      if (available_channel is not None and
+          BranchUtility.NewestChannel((available_channel, channel_info.channel))
+              == channel_info.channel):
+        availability = AvailabilityInfo(channel_info.channel,
+                                        channel_info.version)
+        break
+
+    # The API should at least be available on trunk. It's a bug otherwise.
+    assert availability, 'No availability found for %s' % api_name
+
+    # If the API is in stable, find the chrome version in which it became
+    # stable.
+    if availability.channel == _STABLE:
+      availability.version = self._FindEarliestStableAvailability(
+          api_name,
+          availability.version)
+
+    self._object_store.Set(api_name, availability)
+    return availability
diff --git a/chrome/common/extensions/docs/server2/availability_finder_test.py b/chrome/common/extensions/docs/server2/availability_finder_test.py
new file mode 100755
index 0000000..6577ee5
--- /dev/null
+++ b/chrome/common/extensions/docs/server2/availability_finder_test.py
@@ -0,0 +1,181 @@
+#!/usr/bin/env python
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import sys
+import unittest
+
+from availability_finder import AvailabilityFinder
+from branch_utility import BranchUtility
+from compiled_file_system import CompiledFileSystem
+from fake_url_fetcher import FakeUrlFetcher
+from object_store_creator import ObjectStoreCreator
+from test_file_system import TestFileSystem
+from test_data.canned_data import (CANNED_API_FILE_SYSTEM_DATA, CANNED_BRANCHES)
+
+def _CreateCannedFileSystem(version):
+  branch = CANNED_BRANCHES[version]
+  return TestFileSystem(CANNED_API_FILE_SYSTEM_DATA[str(branch)])
+
+class AvailabilityFinderTest(unittest.TestCase):
+  def setUp(self):
+    self._avail_ds_factory = AvailabilityFinder.Factory(
+        ObjectStoreCreator.ForTest(),
+        CompiledFileSystem.Factory(
+            TestFileSystem(CANNED_API_FILE_SYSTEM_DATA['trunk']),
+            ObjectStoreCreator.ForTest()),
+        BranchUtility(
+            os.path.join('branch_utility', 'first.json'),
+            os.path.join('branch_utility', 'second.json'),
+            FakeUrlFetcher(os.path.join(sys.path[0], 'test_data')),
+            ObjectStoreCreator.ForTest()),
+        _CreateCannedFileSystem)
+    self._avail_ds = self._avail_ds_factory.Create()
+
+  def testGetApiAvailability(self):
+    # Key: Using 'channel' (i.e. 'beta') to represent an availability listing
+    # for an API in a _features.json file, and using |channel| (i.e. |dev|) to
+    # represent the development channel, or phase of development, where an API's
+    # availability is being checked.
+
+    # Testing the predetermined APIs found in
+    # templates/json/api_availabilities.json.
+    self.assertEqual('stable',
+        self._avail_ds.GetApiAvailability('jsonAPI1').channel)
+    self.assertEqual(10,
+        self._avail_ds.GetApiAvailability('jsonAPI1').version)
+    self.assertEqual('trunk',
+        self._avail_ds.GetApiAvailability('jsonAPI2').channel)
+    self.assertEqual(None,
+        self._avail_ds.GetApiAvailability('jsonAPI2').version)
+    self.assertEqual('dev',
+        self._avail_ds.GetApiAvailability('jsonAPI3').channel)
+    self.assertEqual(None,
+        self._avail_ds.GetApiAvailability('jsonAPI3').version)
+
+    # Testing APIs found only by checking file system existence.
+    self.assertEquals('stable',
+        self._avail_ds.GetApiAvailability('windows').channel)
+    self.assertEquals(23,
+        self._avail_ds.GetApiAvailability('windows').version)
+    self.assertEquals('stable',
+        self._avail_ds.GetApiAvailability('tabs').channel)
+    self.assertEquals(18,
+        self._avail_ds.GetApiAvailability('tabs').version)
+    self.assertEquals('stable',
+        self._avail_ds.GetApiAvailability('input.ime').channel)
+    self.assertEquals(18,
+        self._avail_ds.GetApiAvailability('input.ime').version)
+
+    # Testing API channel existence for _api_features.json.
+    # Listed as 'dev' on |beta|, 'dev' on |dev|.
+    self.assertEquals('dev',
+        self._avail_ds.GetApiAvailability('systemInfo.stuff').channel)
+    self.assertEquals(28,
+        self._avail_ds.GetApiAvailability('systemInfo.stuff').version)
+    # Listed as 'stable' on |beta|.
+    self.assertEquals('beta',
+        self._avail_ds.GetApiAvailability('systemInfo.cpu').channel)
+    self.assertEquals(27,
+        self._avail_ds.GetApiAvailability('systemInfo.cpu').version)
+
+    # Testing API channel existence for _manifest_features.json.
+    # Listed as 'trunk' on all channels.
+    self.assertEquals('trunk',
+        self._avail_ds.GetApiAvailability('sync').channel)
+    self.assertEquals('trunk',
+        self._avail_ds.GetApiAvailability('sync').version)
+    # No records of API until |trunk|.
+    self.assertEquals('trunk',
+        self._avail_ds.GetApiAvailability('history').channel)
+    self.assertEquals('trunk',
+        self._avail_ds.GetApiAvailability('history').version)
+    # Listed as 'dev' on |dev|.
+    self.assertEquals('dev',
+        self._avail_ds.GetApiAvailability('storage').channel)
+    self.assertEquals(28,
+        self._avail_ds.GetApiAvailability('storage').version)
+    # Stable in _manifest_features and into pre-18 versions.
+    self.assertEquals('stable',
+        self._avail_ds.GetApiAvailability('pageAction').channel)
+    self.assertEquals(8,
+        self._avail_ds.GetApiAvailability('pageAction').version)
+
+    # Testing API channel existence for _permission_features.json.
+    # Listed as 'beta' on |trunk|.
+    self.assertEquals('trunk',
+        self._avail_ds.GetApiAvailability('falseBetaAPI').version)
+    self.assertEquals('trunk',
+        self._avail_ds.GetApiAvailability('falseBetaAPI').version)
+    # Listed as 'trunk' on |trunk|.
+    self.assertEquals('trunk',
+        self._avail_ds.GetApiAvailability('trunkAPI').channel)
+    self.assertEquals('trunk',
+        self._avail_ds.GetApiAvailability('trunkAPI').version)
+    # Listed as 'trunk' on all development channels.
+    self.assertEquals('trunk',
+        self._avail_ds.GetApiAvailability('declarativeContent').channel)
+    self.assertEquals('trunk',
+        self._avail_ds.GetApiAvailability('declarativeContent').version)
+    # Listed as 'dev' on all development channels.
+    self.assertEquals('dev',
+        self._avail_ds.GetApiAvailability('bluetooth').channel)
+    self.assertEquals(28,
+        self._avail_ds.GetApiAvailability('bluetooth').version)
+    # Listed as 'dev' on |dev|.
+    self.assertEquals('dev',
+        self._avail_ds.GetApiAvailability('cookies').channel)
+    self.assertEquals(28,
+        self._avail_ds.GetApiAvailability('cookies').version)
+    # Treated as 'stable' APIs.
+    self.assertEquals('stable',
+        self._avail_ds.GetApiAvailability('alarms').channel)
+    self.assertEquals(24,
+        self._avail_ds.GetApiAvailability('alarms').version)
+    self.assertEquals('stable',
+        self._avail_ds.GetApiAvailability('bookmarks').channel)
+    self.assertEquals(21,
+        self._avail_ds.GetApiAvailability('bookmarks').version)
+
+    # Testing older API existence using extension_api.json.
+    self.assertEquals('stable',
+        self._avail_ds.GetApiAvailability('menus').channel)
+    self.assertEquals(6,
+        self._avail_ds.GetApiAvailability('menus').version)
+    self.assertEquals('stable',
+        self._avail_ds.GetApiAvailability('idle').channel)
+    self.assertEquals(5,
+        self._avail_ds.GetApiAvailability('idle').version)
+
+    # Switches between _features.json files across branches.
+    # Listed as 'trunk' on all channels, in _api, _permission, or _manifest.
+    self.assertEquals('trunk',
+        self._avail_ds.GetApiAvailability('contextMenus').channel)
+    self.assertEquals('trunk',
+        self._avail_ds.GetApiAvailability('contextMenus').version)
+    # Moves between _permission and _manifest as file system is traversed.
+    self.assertEquals('stable',
+        self._avail_ds.GetApiAvailability('systemInfo.display').channel)
+    self.assertEquals(23,
+        self._avail_ds.GetApiAvailability('systemInfo.display').version)
+    self.assertEquals('stable',
+        self._avail_ds.GetApiAvailability('webRequest').channel)
+    self.assertEquals(17,
+        self._avail_ds.GetApiAvailability('webRequest').version)
+
+    # Mid-upgrade cases:
+    # Listed as 'dev' on |beta| and 'beta' on |dev|.
+    self.assertEquals('dev',
+        self._avail_ds.GetApiAvailability('notifications').channel)
+    self.assertEquals(28,
+        self._avail_ds.GetApiAvailability('notifications').version)
+    # Listed as 'beta' on |stable|, 'dev' on |beta| ... until |stable| on trunk.
+    self.assertEquals('trunk',
+        self._avail_ds.GetApiAvailability('events').channel)
+    self.assertEquals('trunk',
+        self._avail_ds.GetApiAvailability('events').version)
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/chrome/common/extensions/docs/server2/branch_utility.py b/chrome/common/extensions/docs/server2/branch_utility.py
index 1c683c6..4f49113 100644
--- a/chrome/common/extensions/docs/server2/branch_utility.py
+++ b/chrome/common/extensions/docs/server2/branch_utility.py
@@ -137,14 +137,23 @@
 
     version_json = json.loads(self._history_result.Get().content)
     for entry in version_json['events']:
-      # Here, entry['title'] looks like: 'title - version#.#.branch#.#'
+      # Here, entry['title'] looks like: '<title> - <version>.##.<branch>.##'
       version_title = entry['title'].split(' - ')[1].split('.')
       if version_title[0] == str(version):
         self._branch_object_store.Set(str(version), version_title[2])
         return int(version_title[2])
 
-    raise ValueError(
-        'The branch for %s could not be found.' % version)
+    raise ValueError('The branch for %s could not be found.' % version)
+
+  def GetChannelForVersion(self, version):
+    '''Returns the name of the development channel corresponding to a given
+    version number.
+    '''
+    for channel_info in self.GetAllChannelInfo():
+      if channel_info.channel == 'stable' and version <= channel_info.version:
+        return channel_info.channel
+      if version == channel_info.version:
+        return channel_info.channel
 
   def GetLatestVersionNumber(self):
     '''Returns the most recent version number found using data stored on
diff --git a/chrome/common/extensions/docs/server2/branch_utility_test.py b/chrome/common/extensions/docs/server2/branch_utility_test.py
index c6a5034..ea9198e 100755
--- a/chrome/common/extensions/docs/server2/branch_utility_test.py
+++ b/chrome/common/extensions/docs/server2/branch_utility_test.py
@@ -120,5 +120,26 @@
     self.assertEquals(396,
         self._branch_util.GetBranchForVersion(5))
 
+  def testGetChannelForVersion(self):
+    self.assertEquals('trunk',
+        self._branch_util.GetChannelForVersion('trunk'))
+    self.assertEquals('dev',
+        self._branch_util.GetChannelForVersion(28))
+    self.assertEquals('beta',
+        self._branch_util.GetChannelForVersion(27))
+    self.assertEquals('stable',
+        self._branch_util.GetChannelForVersion(26))
+    self.assertEquals('stable',
+        self._branch_util.GetChannelForVersion(22))
+    self.assertEquals('stable',
+        self._branch_util.GetChannelForVersion(18))
+    self.assertEquals('stable',
+        self._branch_util.GetChannelForVersion(14))
+    self.assertEquals(None,
+        self._branch_util.GetChannelForVersion(30))
+    self.assertEquals(None,
+        self._branch_util.GetChannelForVersion(42))
+
+
 if __name__ == '__main__':
   unittest.main()
diff --git a/chrome/common/extensions/docs/server2/cron.yaml b/chrome/common/extensions/docs/server2/cron.yaml
index 3c6f142..8313de6 100644
--- a/chrome/common/extensions/docs/server2/cron.yaml
+++ b/chrome/common/extensions/docs/server2/cron.yaml
@@ -2,19 +2,19 @@
 - description: Load everything for trunk.
   url: /_cron/trunk
   schedule: every 5 minutes
-  target: 2-7-1
+  target: 2-8-1
 
 - description: Load everything for dev.
   url: /_cron/dev
   schedule: every 5 minutes
-  target: 2-7-1
+  target: 2-8-1
 
 - description: Load everything for beta.
   url: /_cron/beta
   schedule: every 5 minutes
-  target: 2-7-1
+  target: 2-8-1
 
 - description: Load everything for stable.
   url: /_cron/stable
   schedule: every 5 minutes
-  target: 2-7-1
+  target: 2-8-1
diff --git a/chrome/common/extensions/docs/server2/cron_servlet.py b/chrome/common/extensions/docs/server2/cron_servlet.py
index b3d4953..2e7c620 100644
--- a/chrome/common/extensions/docs/server2/cron_servlet.py
+++ b/chrome/common/extensions/docs/server2/cron_servlet.py
@@ -79,15 +79,17 @@
     server_instance = self._GetSafeServerInstance()
 
     def get_via_render_servlet(path):
-      return RenderServlet(
-          Request(path, self._request.host, self._request.headers),
-          _SingletonRenderServletDelegate(server_instance)).Get()
+      request = Request(path, self._request.host, self._request.headers)
+      delegate = _SingletonRenderServletDelegate(server_instance)
+      return RenderServlet(request, delegate).Get()
 
     def run_cron_for_dir(d, path_prefix=''):
       success = True
       start_time = time.time()
+      # TODO(jshumway): use server_instance.host_file_system.Walk.
+      # TODO(kalman): delete me where it's set.
       files = [f for f in server_instance.content_cache.GetFromFileListing(d)
-               if not f.endswith('/')]
+               if not f.endswith('/') and f != 'redirects.json']
       logging.info('cron/%s: rendering %s files from %s...' % (
           channel, len(files), d))
       try:
@@ -160,14 +162,12 @@
           logging.info('cron/%s: rendering %s example zips took %s seconds' % (
               channel, len(example_zips), time.time() - start_time))
 
-      # Also trigger a redirect so that PathCanonicalizer has an opportunity to
-      # cache file listings.
-      logging.info('cron/%s: triggering a redirect...' % channel)
-      redirect_response = get_via_render_servlet('storage.html')
-      success = success and redirect_response.status == 302
     except DeadlineExceededError:
       success = False
 
+    logging.info("cron/%s: running Redirector cron..." % channel)
+    server_instance.redirector.Cron()
+
     logging.info('cron/%s: finished' % channel)
 
     return (Response.Ok('Success') if success else
diff --git a/chrome/common/extensions/docs/server2/cron_servlet_test.py b/chrome/common/extensions/docs/server2/cron_servlet_test.py
index 0ee14a3..c0655a2 100755
--- a/chrome/common/extensions/docs/server2/cron_servlet_test.py
+++ b/chrome/common/extensions/docs/server2/cron_servlet_test.py
@@ -27,7 +27,7 @@
     self._app_version = GetAppVersion()
 
   def CreateBranchUtility(self, object_store_creator):
-    return TestBranchUtility()
+    return TestBranchUtility.CreateWithCannedData()
 
   def CreateHostFileSystemForBranchAndRevision(self, branch, revision):
     file_system = self._create_file_system(revision)
diff --git a/chrome/common/extensions/docs/server2/file_system.py b/chrome/common/extensions/docs/server2/file_system.py
index 72bb599..d899826 100644
--- a/chrome/common/extensions/docs/server2/file_system.py
+++ b/chrome/common/extensions/docs/server2/file_system.py
@@ -74,3 +74,24 @@
     different to a LocalFileSystem with a base path of /usr.
     '''
     raise NotImplementedError()
+
+  def Walk(self, root):
+    '''Recursively walk the directories in a file system, starting with root.
+    Emulates os.walk from the standard os module.
+    '''
+    if not root.endswith('/'):
+      root += '/'
+
+    dirs, files = [], []
+
+    for f in self.ReadSingle(root):
+      if f.endswith('/'):
+        dirs.append(f)
+      else:
+        files.append(f)
+
+    yield (root.rstrip('/'), dirs, files)
+
+    for d in dirs:
+      for walkinfo in self.Walk(root + d):
+        yield walkinfo
diff --git a/chrome/common/extensions/docs/server2/handler.py b/chrome/common/extensions/docs/server2/handler.py
index 2156c16..7254611 100644
--- a/chrome/common/extensions/docs/server2/handler.py
+++ b/chrome/common/extensions/docs/server2/handler.py
@@ -2,31 +2,24 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-from branch_utility import BranchUtility
 from cron_servlet import CronServlet
 from patch_servlet import PatchServlet
 from instance_servlet import InstanceServlet
 from servlet import Servlet, Request, Response
 
+_DEFAULT_SERVLET = InstanceServlet.GetConstructor()
 _SERVLETS = {
   'cron': CronServlet,
   'patch': PatchServlet,
 }
-_DEFAULT_SERVLET = InstanceServlet.GetConstructor()
 
 class Handler(Servlet):
   def Get(self):
     path = self._request.path
 
-    redirect = self._RedirectSpecialCases()
-    if redirect is None:
-      redirect = self._RedirectFromCodeDotGoogleDotCom()
-    if redirect is not None:
-      return redirect
-
     if path.startswith('_'):
       servlet_path = path[1:]
-      if servlet_path.find('/') == -1:
+      if not '/' in servlet_path:
         servlet_path += '/'
       servlet_name, servlet_path = servlet_path.split('/', 1)
       servlet = _SERVLETS.get(servlet_name)
@@ -36,36 +29,5 @@
       servlet_path = path
       servlet = _DEFAULT_SERVLET
 
-    return servlet(Request(servlet_path,
-                           self._request.host,
-                           self._request.headers)).Get()
-
-  def _RedirectSpecialCases(self):
-    path = self._request.path
-    if not path or path == 'index.html':
-      return Response.Redirect('http://developer.google.com/chrome')
-    if path == 'apps.html':
-      return Response.Redirect('/apps/about_apps.html')
-    return None
-
-  def _RedirectFromCodeDotGoogleDotCom(self):
-    host, path = (self._request.host, self._request.path)
-
-    if not host in ('http://code.google.com', 'https://code.google.com'):
-      return None
-
-    new_host = 'http://developer.chrome.com'
-
-    # switch to https if necessary
-    if host.startswith('https'):
-      new_host = new_host.replace('http', 'https', 1)
-
-    new_path = path.split('/')
-    if len(new_path) > 0 and new_path[0] == 'chrome':
-      new_path.pop(0)
-    for channel in BranchUtility.GetAllChannelNames():
-      if channel in new_path:
-        position = new_path.index(channel)
-        new_path.pop(position)
-        new_path.insert(0, channel)
-    return Response.Redirect('/'.join([new_host] + new_path))
+    return servlet(
+      Request(servlet_path, self._request.host, self._request.headers)).Get()
diff --git a/chrome/common/extensions/docs/server2/handler_test.py b/chrome/common/extensions/docs/server2/handler_test.py
index 085412f..605d260 100755
--- a/chrome/common/extensions/docs/server2/handler_test.py
+++ b/chrome/common/extensions/docs/server2/handler_test.py
@@ -5,6 +5,7 @@
 
 import unittest
 
+from cron_servlet import CronServlet
 from fake_fetchers import ConfigureFakeFetchers
 from handler import Handler
 from servlet import Request
@@ -13,24 +14,10 @@
   def setUp(self):
     ConfigureFakeFetchers()
 
-  def testCodeGoogleRedirect(self):
-    response = Handler(Request('chrome/extensions/storage.html',
-                               'http://code.google.com',
-                               {})).Get()
-    self.assertEqual(302, response.status)
-    self.assertEqual('http://developer.chrome.com/extensions/storage.html',
-                     response.headers.get('Location'))
+  def testInvalid(self):
+    handler = Handler(Request.ForTest('_notreal'))
 
-  def testDeveloperGoogleRedirect(self):
-    response = Handler(Request.ForTest('')).Get()
-    self.assertEqual(302, response.status)
-    self.assertEqual('http://developer.google.com/chrome',
-                     response.headers.get('Location'))
-
-  def testAppRedirect(self):
-    response = Handler(Request.ForTest('apps.html')).Get()
-    self.assertEqual(302, response.status)
-    self.assertEqual('/apps/about_apps.html', response.headers.get('Location'))
+    self.assertEqual(404, handler.Get().status)
 
 if __name__ == '__main__':
   unittest.main()
diff --git a/chrome/common/extensions/docs/server2/instance_servlet_test.py b/chrome/common/extensions/docs/server2/instance_servlet_test.py
index fb92fe1..0ac7a4a 100755
--- a/chrome/common/extensions/docs/server2/instance_servlet_test.py
+++ b/chrome/common/extensions/docs/server2/instance_servlet_test.py
@@ -19,7 +19,7 @@
     self._file_system_type = file_system_type
 
   def CreateBranchUtility(self, object_store_creator):
-    return TestBranchUtility()
+    return TestBranchUtility.CreateWithCannedData()
 
   def CreateHostFileSystemForBranch(self, branch):
     return self._file_system_type()
diff --git a/chrome/common/extensions/docs/server2/integration_test.py b/chrome/common/extensions/docs/server2/integration_test.py
index 2ed80f3..acd4d44 100755
--- a/chrome/common/extensions/docs/server2/integration_test.py
+++ b/chrome/common/extensions/docs/server2/integration_test.py
@@ -67,6 +67,8 @@
     start_time = time.time()
     try:
       for path, content in public_files.iteritems():
+        if path.endswith('redirects.json'):
+          continue
         def check_result(response):
           self.assertEqual(200, response.status,
               'Got %s when rendering %s' % (response.status, path))
diff --git a/chrome/common/extensions/docs/server2/patch_servlet_test.py b/chrome/common/extensions/docs/server2/patch_servlet_test.py
index e62b95a..df2c748 100755
--- a/chrome/common/extensions/docs/server2/patch_servlet_test.py
+++ b/chrome/common/extensions/docs/server2/patch_servlet_test.py
@@ -95,11 +95,6 @@
     # Invalid issue number results in a 404.
     self._AssertNotFound('extensions/index.html', '11111')
 
-    # Test redirect.
-    self.assertEqual(self._RenderWithPatch('extensions/',
-                                          issue).headers['Location'],
-                     '/_patch/%s/extensions/index.html' % issue)
-
   def testXssRedirect(self):
     def is_redirect(from_host, from_path, to_url):
       response = PatchServlet(Request.ForTest(from_path, host=from_host),
diff --git a/chrome/common/extensions/docs/server2/redirector.py b/chrome/common/extensions/docs/server2/redirector.py
new file mode 100644
index 0000000..8c1d890
--- /dev/null
+++ b/chrome/common/extensions/docs/server2/redirector.py
@@ -0,0 +1,75 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import posixpath
+from urlparse import urlsplit
+
+from branch_utility import BranchUtility
+from file_system import FileNotFoundError
+from third_party.json_schema_compiler.json_parse import Parse
+
+class Redirector(object):
+  def __init__(self, compiled_fs_factory, file_system, root_path):
+    self._root_path = root_path
+    self._file_system = file_system
+    self._cache = compiled_fs_factory.Create(
+      lambda _, rules: Parse(rules), Redirector)
+
+  def Redirect(self, host, path):
+    ''' Check if a path should be redirected, first according to host
+    redirection rules, then from rules in redirects.json files.
+
+    Returns the path that should be redirected to, or None if no redirection
+    should occur.
+    '''
+    return self._RedirectOldHosts(host, path) or self._RedirectFromConfig(path)
+
+  def _RedirectFromConfig(self, url):
+    ''' Lookup the redirects configuration file in the directory that contains
+    the requested resource. If no redirection rule is matched, or no
+    configuration file exists, returns None.
+    '''
+    dirname, filename = posixpath.split(url)
+
+    try:
+      rules = self._cache.GetFromFile(
+          posixpath.join(self._root_path, dirname, 'redirects.json'))
+    except FileNotFoundError:
+      return None
+
+    redirect = rules.get(filename)
+    if redirect is None:
+      return None
+    if (redirect.startswith('/') or
+        urlsplit(redirect).scheme in ('http', 'https')):
+      return redirect
+
+    return posixpath.normpath('/' + posixpath.join(dirname, redirect))
+
+  def _RedirectOldHosts(self, host, path):
+    ''' Redirect paths from the old code.google.com to the new
+    developer.chrome.com, retaining elements like the channel and https, if
+    used.
+    '''
+    if urlsplit(host).hostname != 'code.google.com':
+      return None
+
+    path = path.split('/')
+    if path and path[0] == 'chrome':
+      path.pop(0)
+
+    for channel in BranchUtility.GetAllChannelNames():
+      if channel in path:
+        path.remove(channel)
+        path.insert(0, channel)
+        break
+
+    return 'https://developer.chrome.com/' + posixpath.join(*path)
+
+  def Cron(self):
+    ''' Load files during a cron run.
+    '''
+    for root, dirs, files in self._file_system.Walk(self._root_path + '/'):
+      if 'redirects.json' in files:
+        self._cache.GetFromFile('%s/redirects.json' % root)
diff --git a/chrome/common/extensions/docs/server2/redirector_test.py b/chrome/common/extensions/docs/server2/redirector_test.py
new file mode 100755
index 0000000..713d6e4
--- /dev/null
+++ b/chrome/common/extensions/docs/server2/redirector_test.py
@@ -0,0 +1,88 @@
+#!/usr/bin/env python
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import json
+import unittest
+
+from compiled_file_system import CompiledFileSystem
+from object_store_creator import ObjectStoreCreator
+from redirector import Redirector
+from test_file_system import TestFileSystem
+
+HOST = 'http://localhost/'
+
+file_system = TestFileSystem({
+  'public': {
+    'redirects.json': json.dumps({
+      '': '/index.html',
+      'home': 'index.html',
+      'index.html': 'http://something.absolute.com/'
+    }),
+    'apps': {
+      'redirects.json': json.dumps({
+        '': '../index.html',
+        'index.html': 'about_apps.html'
+      })
+    },
+    'extensions': {
+      'redirects.json': json.dumps({
+        'manifest': 'manifest.html'
+      }),
+      'manifest': {
+        'redirects.json': json.dumps({
+          '': '../manifest.html',
+          'more-info': 'http://lmgtfy.com'
+        })
+      }
+    }
+  }
+})
+
+redirector = Redirector(
+    CompiledFileSystem.Factory(file_system, ObjectStoreCreator.ForTest()),
+    None,
+    'public')
+
+class RedirectorTest(unittest.TestCase):
+  def testExternalRedirection(self):
+    self.assertEqual(
+        'http://something.absolute.com/',
+        redirector.Redirect(HOST, 'index.html'))
+    self.assertEqual(
+        'http://lmgtfy.com',
+        redirector.Redirect(HOST, 'extensions/manifest/more-info'))
+
+  def testAbsoluteRedirection(self):
+    self.assertEqual(
+        '/apps/about_apps.html', redirector.Redirect(HOST, 'apps/index.html'))
+    self.assertEqual(
+      '/index.html', redirector.Redirect(HOST, ''))
+    self.assertEqual(
+      '/index.html', redirector.Redirect(HOST, 'home'))
+
+  def testRelativeRedirection(self):
+    self.assertEqual(
+        '/extensions/manifest.html',
+        redirector.Redirect(HOST, 'extensions/manifest/'))
+    self.assertEqual(
+        '/extensions/manifest.html',
+        redirector.Redirect(HOST, 'extensions/manifest'))
+    self.assertEqual(
+        '/index.html', redirector.Redirect(HOST, 'apps/'))
+
+  def testNotFound(self):
+    self.assertIsNone(redirector.Redirect(HOST, 'not/a/real/path'))
+    self.assertIsNone(redirector.Redirect(HOST, 'public/apps/okay.html'))
+
+  def testOldHosts(self):
+    self.assertEqual(
+        'https://developer.chrome.com/',
+        redirector.Redirect('http://code.google.com', ''))
+    self.assertEqual(
+        'https://developer.chrome.com/',
+        redirector.Redirect('https://code.google.com', ''))
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/chrome/common/extensions/docs/server2/render_servlet.py b/chrome/common/extensions/docs/server2/render_servlet.py
index 84479d7..a14e3a3 100644
--- a/chrome/common/extensions/docs/server2/render_servlet.py
+++ b/chrome/common/extensions/docs/server2/render_servlet.py
@@ -5,19 +5,17 @@
 from fnmatch import fnmatch
 import logging
 import mimetypes
-import os
 import traceback
+from urlparse import urlsplit
 
-from appengine_wrappers import IsDevServer
 from branch_utility import BranchUtility
 from file_system import FileNotFoundError
-from server_instance import ServerInstance
 from servlet import Servlet, Response
 import svn_constants
 
 def _IsBinaryMimetype(mimetype):
-  return any(mimetype.startswith(prefix)
-             for prefix in ['audio', 'image', 'video'])
+  return any(
+    mimetype.startswith(prefix) for prefix in ['audio', 'image', 'video'])
 
 class RenderServlet(Servlet):
   '''Servlet which renders templates.
@@ -32,31 +30,34 @@
     self._default_channel = default_channel
 
   def Get(self):
-    path_with_channel, headers = (self._request.path, self._request.headers)
+    ''' Render the page for a request.
+    '''
+    headers = self._request.headers
+    channel, path = BranchUtility.SplitChannelNameFromPath(self._request.path)
 
-    # Redirect "extensions" and "extensions/" to "extensions/index.html", etc.
-    if (os.path.splitext(path_with_channel)[1] == '' and
-        path_with_channel.find('/') == -1):
-      path_with_channel += '/'
-    if path_with_channel.endswith('/'):
-      return Response.Redirect('/%sindex.html' % path_with_channel)
-
-    channel, path = BranchUtility.SplitChannelNameFromPath(path_with_channel)
+    if path.split('/')[-1] == 'redirects.json':
+      return Response.Ok('')
 
     if channel == self._default_channel:
-      return Response.Redirect('/%s' % path)
-
+      return Response.Redirect('/' + path)
     if channel is None:
       channel = self._default_channel
 
     server_instance = self._delegate.CreateServerInstanceForChannel(channel)
 
-    canonical_path = (
-        server_instance.path_canonicalizer.Canonicalize(path).lstrip('/'))
-    if path != canonical_path:
-      redirect_path = (canonical_path if channel is None else
-                       '%s/%s' % (channel, canonical_path))
-      return Response.Redirect('/%s' % redirect_path)
+    redirect = server_instance.redirector.Redirect(self._request.host, path)
+    if redirect is not None:
+      if (channel != self._default_channel and
+          not urlsplit(redirect).scheme in ('http', 'https')):
+        redirect = '/%s%s' % (channel, redirect)
+      return Response.Redirect(redirect)
+
+    canonical_path = server_instance.path_canonicalizer.Canonicalize(path)
+    redirect = canonical_path.lstrip('/')
+    if path != redirect:
+      if channel is not None:
+        redirect = '%s/%s' % (channel, canonical_path)
+      return Response.Redirect('/' + redirect)
 
     templates = server_instance.template_data_source_factory.Create(
         self._request, path)
@@ -84,7 +85,7 @@
       elif path.endswith('.html'):
         content = templates.Render(path)
         content_type = 'text/html'
-    except FileNotFoundError as e:
+    except FileNotFoundError:
       logging.warning(traceback.format_exc())
       content = None
 
diff --git a/chrome/common/extensions/docs/server2/server_instance.py b/chrome/common/extensions/docs/server2/server_instance.py
index 1456a45..88f3d8b 100644
--- a/chrome/common/extensions/docs/server2/server_instance.py
+++ b/chrome/common/extensions/docs/server2/server_instance.py
@@ -24,6 +24,7 @@
 from object_store_creator import ObjectStoreCreator
 from offline_file_system import OfflineFileSystem
 from path_canonicalizer import PathCanonicalizer
+from redirector import Redirector
 from reference_resolver import ReferenceResolver
 from samples_data_source import SamplesDataSource
 from sidenav_data_source import SidenavDataSource
@@ -122,6 +123,11 @@
     self.content_cache = self.compiled_host_fs_factory.CreateIdentity(
         ServerInstance)
 
+    self.redirector = Redirector(
+        self.compiled_host_fs_factory,
+        self.host_file_system,
+        svn_constants.PUBLIC_TEMPLATE_PATH)
+
   @staticmethod
   def ForTest(file_system):
     object_store_creator = ObjectStoreCreator.ForTest()
diff --git a/chrome/common/extensions/docs/server2/test_branch_utility.py b/chrome/common/extensions/docs/server2/test_branch_utility.py
index aaabdca..5dec476 100644
--- a/chrome/common/extensions/docs/server2/test_branch_utility.py
+++ b/chrome/common/extensions/docs/server2/test_branch_utility.py
@@ -3,19 +3,38 @@
 # found in the LICENSE file.
 
 from branch_utility import BranchUtility, ChannelInfo
+from test_data.canned_data import (CANNED_BRANCHES, CANNED_CHANNELS)
 
 class TestBranchUtility(object):
   '''Mimics BranchUtility to return valid-ish data without needing omahaproxy
   data.
   '''
+  def __init__(self, branches, channels):
+    ''' Parameters: |branches| is a mapping of versions to branches, and
+    |channels| is a mapping of channels to versions.
+    '''
+    self._branches = branches
+    self._channels = channels
+
+  @staticmethod
+  def CreateWithCannedData():
+    '''Returns a TestBranchUtility that uses 'canned' test data pulled from
+    older branches of SVN data.
+    '''
+    return TestBranchUtility(CANNED_BRANCHES, CANNED_CHANNELS)
+
   def GetAllChannelInfo(self):
     return [self.GetChannelInfo(channel)
             for channel in BranchUtility.GetAllChannelNames()]
 
   def GetChannelInfo(self, channel):
-    return ChannelInfo(channel,
-                       'fakebranch-%s' % channel,
-                       'fakeversion-%s' % channel)
+    version = self._channels[channel]
+    return ChannelInfo(channel, self.GetBranchForVersion(version), version)
 
   def GetBranchForVersion(self, version):
-    return 'fakebranch-%s' % version
+    return self._branches[version]
+
+  def GetChannelForVersion(self, version):
+    for channel in self._channels.iterkeys():
+      if self._channels[channel] == version:
+        return channel
diff --git a/chrome/common/extensions/docs/server2/test_data/__init__.py b/chrome/common/extensions/docs/server2/test_data/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/chrome/common/extensions/docs/server2/test_data/__init__.py
diff --git a/chrome/common/extensions/docs/server2/test_data/canned_data.py b/chrome/common/extensions/docs/server2/test_data/canned_data.py
new file mode 100644
index 0000000..a28707e
--- /dev/null
+++ b/chrome/common/extensions/docs/server2/test_data/canned_data.py
@@ -0,0 +1,703 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import json
+
+CANNED_CHANNELS = {
+  'trunk': 'trunk',
+  'dev': 28,
+  'beta': 27,
+  'stable': 26
+}
+
+CANNED_BRANCHES = {
+  'trunk': 'trunk',
+  28: 1500,
+  27: 1453,
+  26: 1410,
+  25: 1364,
+  24: 1312,
+  23: 1271,
+  22: 1229,
+  21: 1180,
+  20: 1132,
+  19: 1084,
+  18: 1025,
+  17: 963,
+  16: 912,
+  15: 874,
+  14: 835,
+  13: 782,
+  12: 742,
+  11: 696,
+  10: 648,
+   9: 597,
+   8: 552,
+   7: 544,
+   6: 495,
+   5: 396
+}
+
+CANNED_TEST_FILE_SYSTEM_DATA = {
+  'api': {
+    '_manifest_features.json': json.dumps({
+      'manifest': 'features'
+    }),
+    '_permission_features.json': json.dumps({
+      'permission': 'features'
+    })
+  },
+  'docs': {
+    'templates': {
+      'intros': {
+        'test.html': '<h1>hi</h1>you<h2>first</h2><h3>inner</h3><h2>second</h2>'
+      },
+      'json': {
+        'api_availabilities.json': json.dumps({
+          'tester': {
+              'channel': 'stable',
+              'version': 42
+            }
+          }),
+        'intro_tables.json': json.dumps({
+          'tester': {
+            'Permissions': [
+              {
+                'permission': 'tester'
+              },
+              {
+                'extra': 'is an API.'
+              }
+            ],
+            'LearnMore': [
+              {
+                'href': 'https://tester.test.com/welcome.html',
+                'content': 'Welcome!'
+              }
+            ]
+          }
+        })
+      }
+    }
+  }
+}
+
+CANNED_API_FILE_SYSTEM_DATA = {
+  'trunk': {
+    'api': {
+      '_api_features.json': json.dumps({
+        'contextMenus': {
+          'channel': 'stable'
+        },
+        'events': {
+          'channel': 'stable'
+        },
+        'extension': {
+          'channel': 'stable'
+        }
+      }),
+      '_manifest_features.json': json.dumps({
+        'history': {
+          'channel': 'beta'
+        },
+        'runtime': {
+          'channel': 'stable'
+        },
+        'storage': {
+          'channel': 'beta'
+        },
+        'sync': {
+          'channel': 'trunk'
+        }
+      }),
+      '_permission_features.json': json.dumps({
+        'alarms': {
+          'channel': 'stable'
+        },
+        'bluetooth': {
+          'channel': 'dev'
+        },
+        'bookmarks': {
+          'channel': 'stable'
+        },
+        'cookies': {
+          'channel': 'dev'
+        },
+        'declarativeContent': {
+          'channel': 'trunk'
+        },
+        'falseBetaAPI': {
+          'channel': 'beta'
+        },
+        'trunkAPI': {
+          'channel': 'trunk'
+        }
+      }),
+      'idle.json': 'idle contents',
+      'input_ime.json': 'input.ime contents',
+      'menus.json': 'menus contents',
+      'tabs.json': 'tabs contents',
+      'windows.json': 'windows contents'
+    },
+    'docs': {
+      'templates': {
+        'json': {
+          'api_availabilities.json': json.dumps({
+            'jsonAPI1': {
+              'channel': 'stable',
+              'version': 10
+            },
+            'jsonAPI2': {
+              'channel': 'trunk'
+            },
+            'jsonAPI3': {
+              'channel': 'dev'
+            }
+          }),
+          'intro_tables.json': json.dumps({
+            'test': [
+              {
+                'Permissions': 'probably none'
+              }
+            ]
+          })
+        }
+      }
+    }
+  },
+  '1500': {
+    'api': {
+      '_api_features.json': json.dumps({
+        'events': {
+          'channel': 'trunk'
+        },
+        'extension': {
+          'channel': 'stable'
+        },
+        'systemInfo.stuff': {
+          'channel': 'dev'
+        }
+      }),
+      '_manifest_features.json': json.dumps({
+        'contextMenus': {
+          'channel': 'trunk'
+        },
+        'notifications': {
+          'channel': 'beta'
+        },
+        'runtime': {
+          'channel': 'stable'
+        },
+        'storage': {
+          'channel': 'dev'
+        },
+        'sync': {
+          'channel': 'trunk'
+        }
+      }),
+      '_permission_features.json': json.dumps({
+        'alarms': {
+          'channel': 'stable'
+        },
+        'bluetooth': {
+          'channel': 'dev'
+        },
+        'bookmarks': {
+          'channel': 'stable'
+        },
+        'cookies': {
+          'channel': 'dev'
+        },
+        'declarativeContent': {
+          'channel': 'trunk'
+        },
+        'downloads': {
+          'channel': 'beta'
+        }
+      }),
+      'idle.json': 'idle contents',
+      'input_ime.json': 'input.ime contents',
+      'menus.json': 'menus contents',
+      'tabs.json': 'tabs contents',
+      'windows.json': 'windows contents'
+    }
+  },
+  '1453': {
+    'api': {
+      '_api_features.json': json.dumps({
+        'events': {
+          'channel': 'dev'
+        },
+        'extension': {
+          'channel': 'stable'
+        },
+        'systemInfo.cpu': {
+          'channel': 'stable'
+        },
+        'systemInfo.stuff': {
+          'channel': 'dev'
+        }
+      }),
+      '_manifest_features.json': json.dumps({
+        'notifications': {
+          'channel': 'dev'
+        },
+        'runtime': {
+          'channel': 'stable'
+        },
+        'storage': {
+          'channel': 'dev'
+        }
+      }),
+      '_permission_features.json': json.dumps({
+        'alarms': {
+          'channel': 'stable'
+        },
+        'bluetooth': {
+          'channel': 'dev'
+        },
+        'bookmarks': {
+          'channel': 'stable'
+        },
+        'context_menus': {
+          'channel': 'trunk'
+        },
+        'declarativeContent': {
+          'channel': 'trunk'
+        },
+        'downloads': {
+          'channel': 'dev'
+        }
+      }),
+      'idle.json': 'idle contents',
+      'input_ime.json': 'input.ime contents',
+      'menus.json': 'menus contents',
+      'tabs.json': 'tabs contents',
+      'windows.json': 'windows contents'
+    }
+  },
+  '1410': {
+    'api': {
+      '_manifest_features.json': json.dumps({
+        'events': {
+          'channel': 'beta'
+        },
+        'notifications': {
+          'channel': 'dev'
+        },
+        'page_action': {
+          'channel': 'stable'
+        },
+        'runtime': {
+          'channel': 'stable'
+        },
+        'web_request': {
+          'channel': 'stable'
+        }
+      }),
+      '_permission_features.json': json.dumps({
+        'alarms': {
+          'channel': 'stable'
+        },
+        'bluetooth': {
+          'channel': 'dev'
+        },
+        'bookmarks': {
+          'channel': 'stable'
+        },
+        'context_menus': {
+          'channel': 'trunk'
+        },
+        'declarativeContent': {
+          'channel': 'trunk'
+        },
+        'systemInfo.display': {
+          'channel': 'stable'
+        }
+      }),
+      'idle.json': 'idle contents',
+      'input_ime.json': 'input.ime contents',
+      'menus.json': 'menus contents',
+      'tabs.json': 'tabs contents',
+      'windows.json': 'windows contents'
+    }
+  },
+  '1364': {
+    'api': {
+      '_manifest_features.json': json.dumps({
+        'page_action': {
+          'channel': 'stable'
+        },
+        'runtime': {
+          'channel': 'stable'
+        }
+      }),
+      '_permission_features.json': json.dumps({
+        'alarms': {
+          'channel': 'stable'
+        },
+        'bookmarks': {
+          'channel': 'stable'
+        },
+        'systemInfo.display': {
+          'channel': 'stable'
+        },
+        'webRequest': {
+          'channel': 'stable'
+        }
+      }),
+      'idle.json': 'idle contents',
+      'input_ime.json': 'input.ime contents',
+      'menus.json': 'menus contents',
+      'tabs.json': 'tabs contents',
+      'windows.json': 'windows contents'
+    }
+  },
+  '1312': {
+    'api': {
+      '_manifest_features.json': json.dumps({
+        'page_action': {
+          'channel': 'stable'
+        },
+        'runtime': {
+          'channel': 'stable'
+        },
+        'web_request': {
+          'channel': 'stable'
+        }
+      }),
+      '_permission_features.json': json.dumps({
+        'alarms': {
+          'channel': 'stable'
+        },
+        'bookmarks': {
+          'channel': 'stable'
+        },
+        'systemInfo.display': {
+          'channel': 'stable'
+        }
+      }),
+      'idle.json': 'idle contents',
+      'input_ime.json': 'input.ime contents',
+      'menus.json': 'menus contents',
+      'tabs.json': 'tabs contents',
+      'windows.json': 'windows contents'
+    }
+  },
+  '1271': {
+    'api': {
+      '_manifest_features.json': json.dumps({
+        'page_action': {
+          'channel': 'stable'
+        },
+        'runtime': {
+          'channel': 'stable'
+        },
+        'system_info_display': {
+          'channel': 'stable'
+        }
+      }),
+      '_permission_features.json': json.dumps({
+        'alarms': {
+          'channel': 'beta'
+        },
+        'bookmarks': {
+          'channel': 'stable'
+        },
+        'webRequest': {
+          'channel': 'stable'
+        }
+      }),
+      'idle.json': 'idle contents',
+      'input_ime.json': 'input.ime contents',
+      'menus.json': 'menus contents',
+      'tabs.json': 'tabs contents',
+      'windows.json': 'windows contents'
+    }
+  },
+  '1229': {
+    'api': {
+      '_manifest_features.json': json.dumps({
+        'page_action': {
+          'channel': 'stable'
+        },
+        'runtime': {
+          'channel': 'stable'
+        },
+        'web_request': {
+          'channel': 'stable'
+        }
+      }),
+      '_permission_features.json': json.dumps({
+        'bookmarks': {
+          'channel': 'stable'
+        },
+        'systemInfo.display': {
+          'channel': 'beta'
+        }
+      }),
+      'idle.json': 'idle contents',
+      'input_ime.json': 'input.ime contents',
+      'menus.json': 'menus contents',
+      'tabs.json': 'tabs contents'
+    }
+  },
+  '1180': {
+    'api': {
+      '_manifest_features.json': json.dumps({
+        'page_action': {
+          'channel': 'stable'
+        },
+        'runtime': {
+          'channel': 'stable'
+        }
+      }),
+      '_permission_features.json': json.dumps({
+        'bookmarks': {
+          'channel': 'stable'
+        },
+        'webRequest': {
+          'channel': 'stable'
+        }
+      }),
+      'idle.json': 'idle contents',
+      'input_ime.json': 'input.ime contents',
+      'menus.json': 'menus contents',
+      'tabs.json': 'tabs contents'
+    }
+  },
+  '1132': {
+    'api': {
+      '_manifest_features.json': json.dumps({
+        'page_action': {
+          'channel': 'stable'
+        }
+      }),
+      '_permission_features.json': json.dumps({
+        'webRequest': {
+          'channel': 'stable'
+        }
+      }),
+      'idle.json': 'idle contents',
+      'input.ime.json': 'input.ime contents',
+      'menus.json': 'menus contents',
+      'tabs.json': 'tabs contents'
+    }
+  },
+  '1084': {
+    'api': {
+      '_manifest_features.json': json.dumps({
+        'contents': 'nothing of interest here,really'
+      }),
+      'idle.json': 'idle contents',
+      'input.ime.json': 'input.ime contents',
+      'menus.json': 'menus contents',
+      'pageAction.json': 'pageAction contents',
+      'tabs.json': 'tabs contents',
+      'webRequest.json': 'webRequest contents'
+    }
+  },
+  '1025': {
+    'api': {
+      'idle.json': 'idle contents',
+      'input.ime.json': 'input.ime contents',
+      'menus.json': 'menus contents',
+      'pageAction.json': 'pageAction contents',
+      'tabs.json': 'tabs contents',
+      'webRequest.json': 'webRequest contents'
+    }
+  },
+  '963': {
+    'api': {
+      'extension_api.json': json.dumps([
+        {
+          'namespace': 'idle'
+        },
+        {
+          'namespace': 'menus'
+        },
+        {
+          'namespace': 'pageAction'
+        },
+        {
+          'namespace': 'webRequest'
+        }
+      ])
+    }
+  },
+  '912': {
+    'api': {
+      'extension_api.json': json.dumps([
+        {
+          'namespace': 'idle'
+        },
+        {
+          'namespace': 'menus'
+        },
+        {
+          'namespace': 'pageAction'
+        },
+        {
+          'namespace': 'experimental.webRequest'
+        }
+      ])
+    }
+  },
+  '874': {
+    'api': {
+      'extension_api.json': json.dumps([
+        {
+          'namespace': 'idle'
+        },
+        {
+          'namespace': 'menus'
+        },
+        {
+          'namespace': 'pageAction'
+        }
+      ])
+    }
+  },
+  '835': {
+    'api': {
+      'extension_api.json': json.dumps([
+        {
+          'namespace': 'idle'
+        },
+        {
+          'namespace': 'menus'
+        },
+        {
+          'namespace': 'pageAction'
+        }
+      ])
+    }
+  },
+  '782': {
+    'api': {
+      'extension_api.json': json.dumps([
+        {
+          'namespace': 'idle'
+        },
+        {
+          'namespace': 'menus'
+        },
+        {
+          'namespace': 'pageAction'
+        }
+      ])
+    }
+  },
+  '742': {
+    'api': {
+      'extension_api.json': json.dumps([
+        {
+          'namespace': 'idle'
+        },
+        {
+          'namespace': 'menus'
+        },
+        {
+          'namespace': 'pageAction'
+        }
+      ])
+    }
+  },
+  '696': {
+    'api': {
+      'extension_api.json': json.dumps([
+        {
+          'namespace': 'idle'
+        },
+        {
+          'namespace': 'menus'
+        },
+        {
+          'namespace': 'pageAction'
+        }
+      ])
+    }
+  },
+  '648': {
+    'api': {
+      'extension_api.json': json.dumps([
+        {
+          'namespace': 'idle'
+        },
+        {
+          'namespace': 'menus'
+        },
+        {
+          'namespace': 'pageAction'
+        }
+      ])
+    }
+  },
+  '597': {
+    'api': {
+      'extension_api.json': json.dumps([
+        {
+          'namespace': 'idle'
+        },
+        {
+          'namespace': 'menus'
+        },
+        {
+          'namespace': 'pageAction'
+        }
+      ])
+    }
+  },
+  '552': {
+    'api': {
+      'extension_api.json': json.dumps([
+        {
+          'namespace': 'idle'
+        },
+        {
+          'namespace': 'menus'
+        },
+        {
+          'namespace': 'pageAction'
+        }
+      ])
+    }
+  },
+  '544': {
+    'api': {
+      'extension_api.json': json.dumps([
+        {
+          'namespace': 'idle'
+        },
+        {
+          'namespace': 'menus'
+        }
+      ])
+    }
+  },
+  '495': {
+    'api': {
+      'extension_api.json': json.dumps([
+        {
+          'namespace': 'idle'
+        },
+        {
+          'namespace': 'menus'
+        }
+      ])
+    }
+  },
+  '396': {
+    'api': {
+      'extension_api.json': json.dumps([
+        {
+          'namespace': 'idle'
+        },
+        {
+          'namespace': 'experimental.menus'
+        }
+      ])
+    }
+  }
+}
diff --git a/chrome/common/extensions/docs/server2/test_data/test_json/expected_test_file.json b/chrome/common/extensions/docs/server2/test_data/test_json/expected_test_file.json
index b9dfa6b..9d5993a 100644
--- a/chrome/common/extensions/docs/server2/test_data/test_json/expected_test_file.json
+++ b/chrome/common/extensions/docs/server2/test_data/test_json/expected_test_file.json
@@ -94,6 +94,7 @@
   ],
   "properties": [],
   "name": "tester",
+  "description": "a test api",
   "types": [
     {
       "properties": [
diff --git a/chrome/common/extensions/docs/server2/test_data/test_json/ref_test.json b/chrome/common/extensions/docs/server2/test_data/test_json/ref_test.json
index 6e07fe1..d9fffae 100644
--- a/chrome/common/extensions/docs/server2/test_data/test_json/ref_test.json
+++ b/chrome/common/extensions/docs/server2/test_data/test_json/ref_test.json
@@ -1,6 +1,7 @@
 [
   {
     "namespace": "ref_test",
+    "description": "An API for testing ref's",
     "types": [
       {
         "id": "type1",
diff --git a/chrome/common/extensions/docs/server2/test_data/test_json/test_file.json b/chrome/common/extensions/docs/server2/test_data/test_json/test_file.json
index ea39b62..5f4fbf5 100644
--- a/chrome/common/extensions/docs/server2/test_data/test_json/test_file.json
+++ b/chrome/common/extensions/docs/server2/test_data/test_json/test_file.json
@@ -1,6 +1,7 @@
 [
   {
     "namespace": "tester",
+    "description": "a test api",
     "types": [
       {
         "id": "TypeA",
diff --git a/chrome/common/extensions/docs/templates/articles/a11y.html b/chrome/common/extensions/docs/templates/articles/a11y.html
index 1a6036c..87c604e 100644
--- a/chrome/common/extensions/docs/templates/articles/a11y.html
+++ b/chrome/common/extensions/docs/templates/articles/a11y.html
@@ -299,8 +299,12 @@
 <p>
 A good way to ensure discoverability of keyboard shortcuts
 is to list them somewhere.
-Your extension’s
-<a href="options.html">Options page</a>
+{{?is_apps}}
+  Your application's options page
+{{:is_apps}}
+  Your extension's
+  <a href="options.html">Options page</a>
+{{/is_apps}}
 might be a good place to do this.
 </p>
 
diff --git a/chrome/common/extensions/docs/templates/articles/app_identity.html b/chrome/common/extensions/docs/templates/articles/app_identity.html
index 04d8525..4239289 100644
--- a/chrome/common/extensions/docs/templates/articles/app_identity.html
+++ b/chrome/common/extensions/docs/templates/articles/app_identity.html
@@ -1,6 +1,5 @@
 <h1>Identify User</h1>
 
-
 <p>
 Web authentication protocols utilize HTTP features,
 but packaged apps run inside the app container;
@@ -8,7 +7,7 @@
 </p>
 
 <p>
-Use the <a href="experimental.identity.html">Chrome Identity API</a>
+Use the <a href="identity.html">Chrome Identity API</a>
 to authenticate users:
 the <code>getAuthToken</code> for users logged into their Google Account and
 the <code>launchWebAuthFlow</code> for users logged into a non-Google account.
@@ -19,28 +18,22 @@
 <b>API Samples: </b>
 Want to play with the code?
 Check out the
-<a href="https://github.com/GoogleChrome/chrome-app-samples/tree/master/identity">identity</a> sample.
+<a href="https://github.com/GoogleChrome/chrome-app-samples#authentication-and-user-identification">identity</a> samples.
 </p>
 
 <h2 id="how">How it works</h2>
 
 <p>
-Apps that use Google accounts
-need to specify the OAuth2 client ID
-and scopes in their manifest.
-When users install the apps,
-the OAuth2 permissions are displayed along with the Chrome permissions.
-Once a user accepts the permissions,
-the apps can get the access token
-using <code>getAuthToken</code>.
+Chrome Apps users have a Google account associated with their
+profile. Apps can get OAuth2 tokens for these users using
+the <code>getAuthToken</code> API.
 </p>
 
 <p>
-Apps that want to perform authentication
-with any provider must call <code>launchAuthFlow</code>.
-This method uses a browser pop-up to show the provider pages
-and captures redirects to the specific URL patterns.
-The redirect URLs are passed to the app
+Apps that want to perform authentication with non-Google identity
+providers must call <code>launchWebAuthFlow</code>.  This method uses a
+browser pop-up to show the provider pages and captures redirects to
+the specific URL patterns.  The redirect URLs are passed to the app
 and the app extracts the token from the URL.
 </p>
 
@@ -51,37 +44,42 @@
 </p>
 
 <ol>
-	<li>Add permissions to your manifest and upload your app.</li>
-	<li>Copy key in the installed <code>manifest.json</code> to your source manifest.</li>
-	<li>Get your client ID.</li>
-	<li>Update your manifest to include the client ID and scopes.</li>
-	<li>Get the authentication token.</li>
+  <li>Add permissions to your manifest and upload your app.</li>
+  <li>Copy key in the installed <code>manifest.json</code> to
+    your source manifest, so that your application ID will stay
+    constant during development.</li>
+  <li>Get an OAuth2 client ID for your Chrome App.</li>
+  <li>Update your manifest to include the client ID and scopes.</li>
+  <li>Get the authentication token.</li>
 </ol>
 
 <h3 id="add_permissions">Add permissions and upload app</h3>
 
 <p>
-The identity API is still experimental.
-You need to make sure the experimental
-and identity permissions are in your manifest.
-You can then upload your app to the apps and extensions management page
-(see <a href="publish_app.html">Publish</a>).
+You need to make sure the identity permission is in your manifest.
+You can then upload your app to the apps and extensions management
+page (see <a href="publish_app.html">Publish</a>).
 </p>
 
 <pre>
 "permissions": [
-  "experimental",
   "identity"
- ]
+]
 </pre>
 
 <h3 id="copy_key">Copy key to your manifest</h3>
 
 <p>
-You need to copy the key in the installed
+When you register your application in the Google OAuth console, you'll
+provide your application's ID, which will be checked during token
+requests. Therefore it's important to have a consistent application ID
+during development.
+</p>
+
+<p>
+To keep your application ID constant, you need to copy the key in the
+installed
 <code>manifest.json</code> to your source manifest.
-This ensures that the key isn't overridden anytime your reload your app
-or share the app with other users.
 It's not the most graceful task, but here's how it goes:
 </p>
 
@@ -97,14 +95,14 @@
   source manifest file.</li>
 </ol>
 
-<h3 id="client_id">Get your client ID</h3>
+<h3 id="client_id">Get your OAuth2 client ID</h3>
 
 <p>
 You need to register your app
 in the Google APIs Console
 to get the client ID:
 </p>
- 
+
 <ol>
   <li>Login to the <a href="https://code.google.com/apis/console/">Google APIs Console</a>
   using the same Google account used to upload your app to the Chrome Web Store. </li>
@@ -126,7 +124,7 @@
 an error will occur when your app calls <a href="#token">getAuthToken()</a>.
 </p>
 
-<h3 id="update_manifest">Update your manifest</h3>
+<h3 id="update_manifest">Update your manifest with OAuth2 client ID and scopes</h3>
 
 <p>
 You need to update your manifest to include
@@ -147,14 +145,103 @@
   }
 </pre>
 
-<h3 id="token">Get the token</h3>
+<h3 id="token">Get access tokens</h3>
 
 <p>
-You are now ready to get the auth token:
+You are now ready to get the auth token by calling
+$ref:identity.getAuthToken.
 </p>
 
 <pre>
-chrome.experimental.identity.getAuthToken(function(token) { })
+chrome.identity.getAuthToken({ interactive: true }, function(token) {
+  // Use the token.
+});
+</pre>
+
+<h4 id="getAuthToken-prompts">User interaction</h4>
+
+<p>
+When calling <code>getAuthToken</code>, you can pass a flag
+(<code>interactive: true</code> in the example above) indicating
+whether you want the API to be called in interactive mode or silent
+mode.  If you invoke the API in interactive mode, the user is shown
+sign in and/or approval UI when necessary.
+</p>
+
+<p>
+If you invoke the API in silent mode, the API will only return a token
+if it's possible to produce one without showing any UI.  This is
+useful in cases when an app is doing the flow at app startup, for
+example, or in general in cases where there is no user gesture
+involved.
+</p>
+
+<p>
+The best practice we suggest is to use silent mode when there is no
+user gesture involved and use interactive mode if there is a user
+gesture (for example, the user clicked the Sign In button in your
+app). Note that we do not enforce any gesture requirement.
+</p>
+
+<h4 id="getAuthToken-caching">Caching</h4>
+
+<p>
+Chrome has an in-memory cache of access tokens, so you can call
+<code>getAuthToken</code> any time you need to use a token. Token
+expiration is handled automatically by the cache.
+</p>
+
+<p>
+You can see the current state of the token cache
+on <code>chrome://identity-internals</code>.
+</p>
+
+<p>
+There are some cases, such as when the user changes their password,
+when non-expired access tokens will stop working. API calls using the
+token will start returning with an HTTP status code 401. If you detect
+that this has happened, you can remove the invalid token from Chrome's
+cache by calling $ref:identity.removeCachedAuthToken.
+</p>
+
+<p>
+Example of <code>removeCachedAuthToken</code> usage:
+</p>
+
+<pre>
+// callback = function (error, httpStatus, responseText);
+function authenticatedXhr(method, url, callback) {
+  var retry = true;
+  function getTokenAndXhr() {
+    chrome.identity.getAuthToken({/* details */},
+                                 function (access_token) {
+      if (chrome.runtime.lastError) {
+        callback(chrome.runtime.lastError);
+        return;
+      }
+
+      var xhr = new XMLHttpRequest();
+      xhr.open(method, url);
+      xhr.setRequestHeader('Authorization',
+                           'Bearer ' + access_token);
+
+      xhr.onload = function () {
+        if (this.status === 401 && retry) {
+          // This status may indicate that the cached
+          // access token was invalid. Retry once with
+          // a fresh token.
+          retry = false;
+          chrome.identity.removeCachedAuthToken(
+              { token: access_token },
+              getTokenAndXhr);
+          return;
+        }
+
+        callback(null, this.status, this.responseText);
+      }
+    });
+  }
+}
 </pre>
 
 <h2 id="non">Non-Google account authentication</h2>
@@ -164,9 +251,9 @@
 </p>
 
 <ol>
-	<li>Register with the provider.</li>
-	<li>Add permissions for provider resources that your app will access.</li>
-	<li>Get the authentication token.</li>
+  <li>Register with the provider.</li>
+  <li>Add permissions for provider resources that your app will access.</li>
+  <li>Get the authentication token.</li>
 </ol>
 
 <h3 id="register_provider">Register with the provider</h3>
@@ -180,10 +267,10 @@
 </p>
 
 <p>
-For example, if you app ID is abcdefghijklmnopqrstuvwxyzabcdef and
-you want provider_cb to be the path,
-to distinguish it with redirect URIs from other providers,
-you should use:
+For example, if you app ID
+is <code>abcdefghijklmnopqrstuvwxyzabcdef</code> and you want
+<code>provider_cb</code> to be the path, to distinguish it with
+redirect URIs from other providers, you should use:
 <code>https://abcdefghijklmnopqrstuvwxyzabcdef.chromiumapp.org/provider_cb</code>
 </p>
 
@@ -210,7 +297,7 @@
 </p>
 
 <pre>
-chrome.experimental.identity.launchWebAuthFlow(
+chrome.identity.launchWebAuthFlow(
   {‘url’: ‘&lt;url-to-do-auth>’, ‘interactive’: true},
   function(redirect_url) { // Extract token from redirect_url });
 </pre>
@@ -236,7 +323,7 @@
 The app should extract the token out of the URL.
 </p>
 
-<h3 id="interactive">Interactive versus silent mode</h3>
+<h3 id="launchWebAuthFlow-interactive">Interactive versus silent mode</h3>
 
 <p>
 When calling <code>launchWebAuthFlow</code>,
diff --git a/chrome/common/extensions/docs/templates/articles/declare_permissions.html b/chrome/common/extensions/docs/templates/articles/declare_permissions.html
index 92454c3..5da54d0 100644
--- a/chrome/common/extensions/docs/templates/articles/declare_permissions.html
+++ b/chrome/common/extensions/docs/templates/articles/declare_permissions.html
@@ -340,6 +340,11 @@
        <a href="windows.html">chrome.windows</a> module. </td>
 </tr>
 <tr>
+  <td> "tabCapture" </td>
+  <td> Required if the extension uses the
+       <a href="tabCapture.html">chrome.tabCapture</a> module. </td>
+</tr>
+<tr>
   <td> "topSites" </td>
   <td> Required if the extension uses the
        <a href="topSites.html">chrome.topSites</a> module. </td>
diff --git a/chrome/common/extensions/docs/templates/articles/event_pages.html b/chrome/common/extensions/docs/templates/articles/event_pages.html
index 36285f2..7c6c422 100644
--- a/chrome/common/extensions/docs/templates/articles/event_pages.html
+++ b/chrome/common/extensions/docs/templates/articles/event_pages.html
@@ -90,8 +90,7 @@
 <p>
 Make sure your event page closes as soon as the event that
 opened it is processed.
-You can observe the lifetime of your event page by clicking
-on "View Background Pages" in the Chrome menu, or by
+You can observe the lifetime of your event page by
 opening Chrome's task manager. You can see when your event
 page loads and unloads by observing when an entry for your
 extension appears in the list of processes.
diff --git a/chrome/common/extensions/docs/templates/articles/experimental_identity.html b/chrome/common/extensions/docs/templates/articles/experimental_identity.html
new file mode 100644
index 0000000..e48b374
--- /dev/null
+++ b/chrome/common/extensions/docs/templates/articles/experimental_identity.html
@@ -0,0 +1,11 @@
+<h1>experimental.identity</h1>
+
+<p>
+The <code>experimental.identity</code> API has moved
+to <a href="identity.html"><code>identity</code></a>.  You can read
+all about it at its new home:
+</p>
+
+<blockquote>
+<a href="identity.html">chrome.identity</a>
+</blockquote>
diff --git a/chrome/common/extensions/docs/templates/articles/faq.html b/chrome/common/extensions/docs/templates/articles/faq.html
index c90fa91..52fc275 100644
--- a/chrome/common/extensions/docs/templates/articles/faq.html
+++ b/chrome/common/extensions/docs/templates/articles/faq.html
@@ -16,7 +16,9 @@
   <h4 id="general">General</h4>
   <ul>
     <li><a href="#faq-gen-01">What are Google Chrome Extensions?</a></li>
+{{^is_apps}}
     <li><a href="#faq-dev-01">How can I set up Chrome for extension development?</a></li>
+{{/is_apps}}
     <li><a href="#faq-gen-02">What technologies are used to write extensions for Chrome?</a></li>
     <li><a href="#faq-gen-03">Are extensions fetched from the web every time the browser is loaded?</a></li>
     <li><a href="#faq-dev-14">How do I determine which version of Chrome is deployed to which channel?</a></li>
@@ -34,8 +36,8 @@
     <li><a href="#faq-dev-11">Can two extensions communicate with each other?</a></li>
 {{^is_apps}}
     <li><a href="#faq-dev-13">Can extensions use Google Analytics?</a></li>
-{{/is_apps}}
     <li><a href="#faq-dev-15">Can extensions modify chrome:// URLs?</a></li>
+{{/is_apps}}
     <li><a href="#faq-open-popups">Can extensions open browser/page action popups without user interaction?</a></li>
     <li><a href="#faq-persist-popups">Can extensions keep popups open after the user clicks away from them?</a></li>
     <li><a href="#faq-lifecycle-events">Can extensions be notified when they are installed/uninstalled?</a></li>
@@ -44,7 +46,9 @@
   <ul>
     <li><a href="#faq-building-ui">How do I build a UI for my extension?</a>
     <li><a href="#faq-dev-09">How much data can I store in localStorage?</a></li>
+{{^is_apps}}
     <li><a href="#faq-dev-10">How do I create an options menu for my application?</a></li>
+{{/is_apps}}
     <li><a href="#faq-dev-12">What debugging tools are available to extension developers?</a></li>
     <li><a href="#faq-dev-16">Why do wildcard matches not work for top level domains (TLDs)?</a></li>
     <li><a href="#faq-management">Why does the management API not fire events when my extension is installed/uninstalled?</a></li>
@@ -66,6 +70,7 @@
   party websites or services, and customized browsing experiences.
 </p>
 
+{{^is_apps}}
 <h3 id="faq-dev-01">How can I set up Chrome for extension development?</h3>
 <p>
   As long as you are using a version of Chrome that supports
@@ -86,6 +91,7 @@
   and more. For a complete tutorial, see
   <a href="http://code.google.com/chrome/extensions/getstarted.html">Getting Started</a>.
 </p>
+{{/is_apps}}
 
 <h3 id="faq-gen-02">What technologies are used to write extensions for Chrome?</h3>
 <p>
@@ -240,6 +246,7 @@
 </p>
 {{/is_apps}}
 
+{{^is_apps}}
 <h3 id="faq-dev-15">Can extensions modify chrome:// URLs?</h3>
 <p>
   No. The extensions APIs have been designed to minimize backwards
@@ -260,6 +267,7 @@
   functionality they want without depending on the browser's internal implementation
   to stay the same.
 </p>
+{{/is_apps}}
 
 <h3 id="faq-open-popups">Can extensions open browser/page action popups without
   user interaction?</h3>
@@ -303,6 +311,7 @@
   Extensions can store up to 5MB of data in localStorage.
 </p>
 
+{{^is_apps}}
 <h3 id="faq-dev-10">How do I create an options menu for my application?</h3>
 <p>
   You can let users set options for your extension by creating an
@@ -312,6 +321,7 @@
   to localStorage, or even send options to a web server so that they can be
   persisted across browsers.
 </p>
+{{/is_apps}}
 
 <h3 id="faq-dev-12">What debugging tools are available to extension developers?</h3>
 <p>
diff --git a/chrome/common/extensions/docs/templates/articles/manifest.html b/chrome/common/extensions/docs/templates/articles/manifest.html
index 97ecf4e..418708a 100644
--- a/chrome/common/extensions/docs/templates/articles/manifest.html
+++ b/chrome/common/extensions/docs/templates/articles/manifest.html
@@ -23,28 +23,31 @@
   "<a href="#name">name</a>": "<em>My Extension</em>",
   "<a href="#version">version</a>": "<em>versionString</em>",
   "<a href="#manifest_version">manifest_version</a>": 2,
+{{?is_apps}}
+  "<a href="#app">app</a>": {...},
+{{/is_apps}}
 
   <em>// Recommended</em>
   "<a href="#description">description</a>": "<em>A plain text description</em>",
   "<a href="#icons">icons</a>": { ... },
   "<a href="#default_locale">default_locale</a>": "<em>en</em>",
+{{^is_apps}}
 
   <em>// Pick one (or none)</em>
   "<a href="browserAction.html">browser_action</a>": {...},
   "<a href="pageAction.html">page_action</a>": {...},
   "<a href="themes.html">theme</a>": {...},
   "<a href="#app">app</a>": {...},
+{{/is_apps}}
 
   <em>// Add any of these that you need</em>
   "<a href="event_pages.html">background</a>": {"persistent": false, ...},
   "<a href="background_pages.html">background</a>": {"persistent": true, ...},
+{{^is_apps}}
   "<a href="override.html">chrome_url_overrides</a>": {...},
-  "<a href="content_scripts.html">content_scripts</a>": [...],
-{{?is_apps}}
-  "<a href="app_csp.html">content_security_policy</a>": "<em>policyString</em>",
-{{:is_apps}}
-  "<a href="contentSecurityPolicy.html">content_security_policy</a>": "<em>policyString</em>",
 {{/is_apps}}
+  "<a href="content_scripts.html">content_scripts</a>": [...],
+  "<a href="contentSecurityPolicy.html">content_security_policy</a>": "<em>policyString</em>",
   "<a href="fileBrowserHandler.html">file_browser_handlers</a>": [...],
   "<a href="#file_handlers">file_handlers</a>": {...},
   "<a href="#homepage_url">homepage_url</a>": "http://<em>path/to/homepage</em>",
@@ -56,7 +59,9 @@
   "<a href="#kiosk_enabled">kiosk_enabled</a>": true,
   "<a href="#offline_enabled">offline_enabled</a>": true,
   "<a href="omnibox.html">omnibox</a>": { "keyword": "<em>aString</em>" },
+{{^is_apps}}
   "<a href="options.html">options_page</a>": "<em>aFile</em>.html",
+{{/is_apps}}
   "<a href="declare_permissions.html">permissions</a>": [...],
   "<a href="npapi.html">plugins</a>": [...],
   "<a href="#requirements">requirements</a>": {...},
@@ -266,7 +271,7 @@
 <b>Note:</b> You don't usually need to
 use this value. Instead, write your
 code so that the key value doesn't matter
-by using <a href="overview.html#relative-urls">relative paths</a>
+by using <a href="../extensions/overview.html#relative-urls">relative paths</a>
 and $ref:runtime.getURL.
 </p>
 
@@ -422,7 +427,7 @@
 if an app or extension requires NPAPI to run.
 This requirement is enabled by default
 when the manifest includes the
-<a href="http://developer.chrome.com/extensions/npapi.html">"plugins" field</a>. 
+<a href="http://developer.chrome.com/extensions/npapi.html">"plugins" field</a>.
 For apps and extensions that still work when plugins aren't available,
 you can disable this requirement
 by setting NPAPI to false.
diff --git a/chrome/common/extensions/docs/templates/articles/match_patterns.html b/chrome/common/extensions/docs/templates/articles/match_patterns.html
index 204f878..d3a098d 100644
--- a/chrome/common/extensions/docs/templates/articles/match_patterns.html
+++ b/chrome/common/extensions/docs/templates/articles/match_patterns.html
@@ -61,7 +61,9 @@
 The meaning of '<code>*</code>' depends on whether
 it's in the <em>scheme</em>, <em>host</em>, or <em>path</em> part.
 If the <em>scheme</em> is <code>*</code>,
-then it matches either <code>http</code> or <code>https</code>.
+then it matches either <code>http</code> or <code>https</code>,
+and <strong>not</strong> <code>file</code>, <code>ftp</code>,
+or <code>chrome-extension</code>.
 If the <em>host</em> is just <code>*</code>,
 then it matches any host.
 If the <em>host</em> is <code>*.<em>hostname</em></code>,
diff --git a/chrome/common/extensions/docs/templates/articles/messaging.html b/chrome/common/extensions/docs/templates/articles/messaging.html
index 3bd19da..82e9091 100644
--- a/chrome/common/extensions/docs/templates/articles/messaging.html
+++ b/chrome/common/extensions/docs/templates/articles/messaging.html
@@ -217,6 +217,65 @@
 port.postMessage(...);
 </pre>
 
+
+<h2 id="external-webpage">Sending messages from web pages</h2>
+<p>
+Similar to <a href="#external">cross-extension messaging</a>,
+your app or extension can receive and
+respond to messages from regular web pages.
+To use this feature, you must first
+specify in your manifest.json which web sites you want to communicate with. For
+example:
+
+<pre>
+"externally_connectable": {
+  "matches": ["*://*.example.com/*"]
+}
+</pre>
+
+<p>
+This will expose the messaging API to any page which matches the URL patterns
+you specify. The URL pattern must contain at least a
+<a href="http://en.wikipedia.org/wiki/Second-level_domain">second-level domain</a>
+- that is, hostname
+patterns like "*", "*.com", "*.co.uk", and "*.appspot.com" are prohibited.
+From the web page, use the
+$ref:runtime.sendMessage
+or
+$ref:runtime.connect
+APIs to send a message to a specific app or extension. For example:
+<pre>
+// The ID of the extension we want to talk to.
+var editorExtensionId = "abcdefghijklmnoabcdefhijklmnoabc";
+
+// Make a simple request:
+chrome.runtime.sendMessage(editorExtensionId, {openUrlInEditor: url},
+  function(response) {
+    if (!response.success)
+      handleError(url);
+  });
+</pre>
+
+<p>
+From your app or extension, you may listen to messages from web pages via the
+$ref:runtime.onMessageExternal
+or
+$ref:runtime.onConnectExternal
+APIs, similar to <a href="#external">cross-extension messaging</a>.
+Only the web page can initiate a connection.
+Here is an example:
+
+<pre>
+chrome.runtime.onMessageExternal.addListener(
+  function(request, sender, sendResponse) {
+    if (sender.url == blacklistedWebsite)
+      return;  // don't allow this web page access
+    if (request.openUrlInEditor)
+      openUrl(request.openUrlInEditor);
+  });
+</pre>
+
+
 <h2 id="native-messaging">Native messaging</h2>
 <p>
 Extensions can exchange messages with native applications. Native
@@ -278,9 +337,8 @@
   <dt>Windows:</dt>
     <dd>The manifest file can be located anywhere in the file system.
      The application installer must create registry key
-     <code>HKEY_LOCAL_MACHINE\SOFTWARE\Google\Chrome\NativeMessagingHosts</code>
-     (if it didn't exist), and then create string value with the same name as
-     the name of the host and set it to the full path to the host manifest file.
+     <code>HKEY_LOCAL_MACHINE\SOFTWARE\Google\Chrome\NativeMessagingHosts\<em>host_name</em></code>
+     and set default value of that key to the full path to the manifest file.
     </dd>
 
   <dt>OSX:</dt>
diff --git a/chrome/common/extensions/docs/templates/articles/npapi.html b/chrome/common/extensions/docs/templates/articles/npapi.html
index a47d75e..fa95439 100644
--- a/chrome/common/extensions/docs/templates/articles/npapi.html
+++ b/chrome/common/extensions/docs/templates/articles/npapi.html
@@ -41,7 +41,6 @@
   "name": "My extension",
   ...
   <b>"plugins": [
-    { "path": "content_plugin.dll", "public": true },
     { "path": "extension_plugin.dll" }
   ]</b>,
   ...
@@ -53,7 +52,11 @@
     The "public" property specifies whether
     your plugin can be accessed by regular web pages;
     the default is false,
-    meaning only your extension can load the plugin.
+    meaning only your extension can load the plugin. Add
+    <code>"public": true</code> to make your plugin accessible on
+    regular web pages and content scripts. But
+    <a href="#security-considerations">be careful</a> - any
+    web page will then be able to call into your plugin.
     </p>
    </li>
 
diff --git a/chrome/common/extensions/docs/templates/intros/dial.html b/chrome/common/extensions/docs/templates/intros/dial.html
new file mode 100644
index 0000000..9d84882
--- /dev/null
+++ b/chrome/common/extensions/docs/templates/intros/dial.html
@@ -0,0 +1,30 @@
+<p>The <code>chrome.dial</code> API is backed by a service that multicasts
+discovery requests on the local network to discover DIAL-capable devices and
+maintains a list of devices that have responded.  Adding an onDeviceList
+listener causes the service to periodically issue discovery requests to maintain
+the device list. (No polling is done when there are no onDeviceList listeners.)
+</p>
+
+<p>The onDeviceList event is fired when discovery respnses are received and in
+other circumstances; see the documentation for onDeviceList.</p>
+
+<p>The client can request that network discovery can be done immediately by
+invoking discoverNow() which is useful for presenting the user with an
+updated list of devices.</p>
+
+<p>On-demand use (updates when discoverNow() is called):
+<pre>
+chrome.dial.onDeviceList.addListener(function (list) { updateMenu(list); });
+chrome.dial.discoverNow();
+</pre>
+(Remember to remove the listener when the menu closes.)</p>
+
+<p>Background use (updates only when periodic polling happens):</p>
+
+<pre>
+var myList;
+chrome.dial.onDeviceList.addListener(function (list) { myList = list; });
+</pre>
+
+<p>These can be combined to poll for devices to prime the device menu, then
+refresh the menu when it is displayed.</p>
diff --git a/chrome/common/extensions/docs/templates/intros/identity.html b/chrome/common/extensions/docs/templates/intros/identity.html
new file mode 100644
index 0000000..e2c36b9
--- /dev/null
+++ b/chrome/common/extensions/docs/templates/intros/identity.html
@@ -0,0 +1,23 @@
+<table class="intro">
+  <tr>
+    <th scope="col"></th>
+    <th scope="col"></th>
+  </tr>
+  <tr>
+    <td><strong>Description:</strong></td>
+    <td>Use the <code>chrome.identity</code> module
+    to get OAuth2 access tokens.</td>
+  </tr>
+  <tr>
+    <td><strong>Availability:</strong></td>
+    <td>Google Chrome 29</td>
+  </tr>
+  <tr>
+    <td><strong>Permissions:</strong></td>
+    <td><code>"identity"</code></td>
+  </tr>
+  <tr>
+    <td><strong>Learn more:</strong></td>
+    <td><a href="app_identity.html">Identify User</a></td>
+  </tr>
+</table>
diff --git a/chrome/common/extensions/docs/templates/json/api_availabilities.json b/chrome/common/extensions/docs/templates/json/api_availabilities.json
new file mode 100644
index 0000000..a81f194
--- /dev/null
+++ b/chrome/common/extensions/docs/templates/json/api_availabilities.json
@@ -0,0 +1,18 @@
+{
+  "devtools.inspectedWindow": {
+    "channel": "stable",
+    "version": 18
+  },
+  "devtools.network": {
+    "channel": "stable",
+    "version": 18
+  },
+  "devtools.panels": {
+    "channel": "stable",
+    "version": 18
+  },
+  "webstore": {
+    "channel": "stable",
+    "version": 15
+  }
+}
diff --git a/chrome/common/extensions/docs/templates/private/table_of_contents.html b/chrome/common/extensions/docs/templates/private/table_of_contents.html
index 76a5d67..d7c918e 100644
--- a/chrome/common/extensions/docs/templates/private/table_of_contents.html
+++ b/chrome/common/extensions/docs/templates/private/table_of_contents.html
@@ -3,10 +3,10 @@
     {{?has_toc}}
     {{#toc_items}}
     <li>
-      <a href=#{{link}}>{{{title}}}</a>
+      <a href="#{{link}}">{{{title}}}</a>
       {{?subheadings}}
       <ol>
-        {{#subheadings}}<li><a href=#{{link}}>{{{title}}}</a></li>{{/}}
+        {{#subheadings}}<li><a href="#{{link}}">{{{title}}}</a></li>{{/}}
       </ol>
       {{/}}
     </li>
diff --git a/chrome/common/extensions/docs/templates/public/apps/commands.html b/chrome/common/extensions/docs/templates/public/apps/commands.html
deleted file mode 100644
index a4393d5..0000000
--- a/chrome/common/extensions/docs/templates/public/apps/commands.html
+++ /dev/null
@@ -1 +0,0 @@
-{{+partials.standard_apps_api api:apis.commands intro:intros.commands}}
diff --git a/chrome/common/extensions/docs/templates/public/apps/app_csp.html b/chrome/common/extensions/docs/templates/public/apps/contentSecurityPolicy.html
similarity index 100%
rename from chrome/common/extensions/docs/templates/public/apps/app_csp.html
rename to chrome/common/extensions/docs/templates/public/apps/contentSecurityPolicy.html
diff --git a/chrome/common/extensions/docs/templates/public/apps/devguide.html b/chrome/common/extensions/docs/templates/public/apps/devguide.html
deleted file mode 100644
index 7be8259..0000000
--- a/chrome/common/extensions/docs/templates/public/apps/devguide.html
+++ /dev/null
@@ -1 +0,0 @@
-{{+partials.standard_apps_article article:intros.devguide}}
diff --git a/chrome/common/extensions/docs/templates/public/apps/experimental_identity.html b/chrome/common/extensions/docs/templates/public/apps/experimental_identity.html
index 39ee7cb..cad7b5d 100644
--- a/chrome/common/extensions/docs/templates/public/apps/experimental_identity.html
+++ b/chrome/common/extensions/docs/templates/public/apps/experimental_identity.html
@@ -1 +1 @@
-{{+partials.standard_apps_api api:apis.experimental_identity}}
+{{+partials.standard_apps_article article:intros.experimental_identity}}
diff --git a/chrome/common/extensions/docs/templates/public/apps/getstarted.html b/chrome/common/extensions/docs/templates/public/apps/getstarted.html
deleted file mode 100644
index 612efb3..0000000
--- a/chrome/common/extensions/docs/templates/public/apps/getstarted.html
+++ /dev/null
@@ -1 +0,0 @@
-{{+partials.standard_apps_article article:intros.getstarted}}
diff --git a/chrome/common/extensions/docs/templates/public/apps/identity.html b/chrome/common/extensions/docs/templates/public/apps/identity.html
new file mode 100644
index 0000000..727cff8
--- /dev/null
+++ b/chrome/common/extensions/docs/templates/public/apps/identity.html
@@ -0,0 +1 @@
+{{+partials.standard_apps_api api:apis.identity intro:intros.identity}}
diff --git a/chrome/common/extensions/docs/templates/public/apps/index.html b/chrome/common/extensions/docs/templates/public/apps/index.html
deleted file mode 100644
index a25d506..0000000
--- a/chrome/common/extensions/docs/templates/public/apps/index.html
+++ /dev/null
@@ -1 +0,0 @@
-<html><head><meta http-equiv="refresh" content="0;URL='about_apps.html'"></head></html>
diff --git a/chrome/common/extensions/docs/templates/public/apps/options.html b/chrome/common/extensions/docs/templates/public/apps/options.html
deleted file mode 100644
index 267e080..0000000
--- a/chrome/common/extensions/docs/templates/public/apps/options.html
+++ /dev/null
@@ -1 +0,0 @@
-{{+partials.standard_apps_article article:intros.options}}
diff --git a/chrome/common/extensions/docs/templates/public/apps/override.html b/chrome/common/extensions/docs/templates/public/apps/override.html
deleted file mode 100644
index 6dbb5d6..0000000
--- a/chrome/common/extensions/docs/templates/public/apps/override.html
+++ /dev/null
@@ -1 +0,0 @@
-{{+partials.standard_apps_article article:intros.override}}
diff --git a/chrome/common/extensions/docs/templates/public/apps/overview.html b/chrome/common/extensions/docs/templates/public/apps/overview.html
deleted file mode 100644
index 8504647..0000000
--- a/chrome/common/extensions/docs/templates/public/apps/overview.html
+++ /dev/null
@@ -1 +0,0 @@
-{{+partials.standard_apps_article article:intros.overview}}
diff --git a/chrome/common/extensions/docs/templates/public/apps/redirects.json b/chrome/common/extensions/docs/templates/public/apps/redirects.json
new file mode 100644
index 0000000..fea5a4c
--- /dev/null
+++ b/chrome/common/extensions/docs/templates/public/apps/redirects.json
@@ -0,0 +1,5 @@
+{
+  "": "about_apps.html",
+  "index.html": "about_apps.html",
+  "app_csp.html": "contentSecurityPolicy.html"
+}
diff --git a/chrome/common/extensions/docs/templates/public/apps/tutorials.html b/chrome/common/extensions/docs/templates/public/apps/tutorials.html
deleted file mode 100644
index 8f2389b..0000000
--- a/chrome/common/extensions/docs/templates/public/apps/tutorials.html
+++ /dev/null
@@ -1 +0,0 @@
-{{+partials.standard_apps_article article:intros.tutorials}}
diff --git a/chrome/common/extensions/docs/templates/public/extensions/app_identity.html b/chrome/common/extensions/docs/templates/public/extensions/app_identity.html
new file mode 100644
index 0000000..ee3c4e5
--- /dev/null
+++ b/chrome/common/extensions/docs/templates/public/extensions/app_identity.html
@@ -0,0 +1 @@
+{{+partials.standard_extensions_article article:intros.app_identity}}
diff --git a/chrome/common/extensions/docs/templates/public/extensions/experimental_identity.html b/chrome/common/extensions/docs/templates/public/extensions/experimental_identity.html
index 9c9b563..5ec4d2f 100644
--- a/chrome/common/extensions/docs/templates/public/extensions/experimental_identity.html
+++ b/chrome/common/extensions/docs/templates/public/extensions/experimental_identity.html
@@ -1 +1 @@
-{{+partials.standard_extensions_api api:apis.experimental_identity}}
+{{+partials.standard_extensions_article article:intros.experimental_identity}}
diff --git a/chrome/common/extensions/docs/templates/public/extensions/identity.html b/chrome/common/extensions/docs/templates/public/extensions/identity.html
new file mode 100644
index 0000000..8671acc
--- /dev/null
+++ b/chrome/common/extensions/docs/templates/public/extensions/identity.html
@@ -0,0 +1 @@
+{{+partials.standard_extensions_api api:apis.identity intro:intros.identity}}
diff --git a/chrome/common/extensions/docs/templates/public/extensions/redirects.json b/chrome/common/extensions/docs/templates/public/extensions/redirects.json
new file mode 100644
index 0000000..38431d7
--- /dev/null
+++ b/chrome/common/extensions/docs/templates/public/extensions/redirects.json
@@ -0,0 +1,3 @@
+{
+  "": "index.html"
+}
diff --git a/chrome/common/extensions/docs/templates/public/redirects.json b/chrome/common/extensions/docs/templates/public/redirects.json
new file mode 100644
index 0000000..53f47a8
--- /dev/null
+++ b/chrome/common/extensions/docs/templates/public/redirects.json
@@ -0,0 +1,7 @@
+{
+  "": "http://developer.google.com/chrome",
+  "apps.html": "/apps/about_apps.html",
+  "apps": "/apps/about_apps.html",
+  "extensions": "/extensions/index.html",
+  "index.html": "http://developer.google.com/chrome"
+}
diff --git a/chrome/common/extensions/extension_file_util.cc b/chrome/common/extensions/extension_file_util.cc
index ce529b5..188abc4 100644
--- a/chrome/common/extensions/extension_file_util.cc
+++ b/chrome/common/extensions/extension_file_util.cc
@@ -87,7 +87,7 @@
   }
   base::FilePath crx_temp_source =
       extension_temp_dir.path().Append(unpacked_source_dir.BaseName());
-  if (!file_util::Move(unpacked_source_dir, crx_temp_source)) {
+  if (!base::Move(unpacked_source_dir, crx_temp_source)) {
     LOG(ERROR) << "Moving extension from : " << unpacked_source_dir.value()
                << " to : " << crx_temp_source.value() << " failed.";
     return base::FilePath();
@@ -111,7 +111,7 @@
     return base::FilePath();
   }
 
-  if (!file_util::Move(crx_temp_source, version_dir)) {
+  if (!base::Move(crx_temp_source, version_dir)) {
     LOG(ERROR) << "Installing extension from : " << crx_temp_source.value()
                << " into : " << version_dir.value() << " failed.";
     return base::FilePath();
@@ -125,7 +125,7 @@
   // We don't care about the return value. If this fails (and it can, due to
   // plugins that aren't unloaded yet), it will get cleaned up by
   // ExtensionService::GarbageCollectExtensions.
-  file_util::Delete(extensions_dir.AppendASCII(id), true);  // recursive.
+  base::Delete(extensions_dir.AppendASCII(id), true);  // recursive.
 }
 
 scoped_refptr<Extension> LoadExtension(const base::FilePath& extension_path,
@@ -345,7 +345,7 @@
     // Clean up temporary files left if Chrome crashed or quit in the middle
     // of an extension install.
     if (basename.value() == kTempDirectoryName) {
-      file_util::Delete(extension_path, true);  // Recursive
+      base::Delete(extension_path, true);  // Recursive
       continue;
     }
 
@@ -362,7 +362,7 @@
                        "directory: " << basename.value();
       DVLOG(1) << "Deleting invalid extension directory "
                << extension_path.value() << ".";
-      file_util::Delete(extension_path, true);  // Recursive.
+      base::Delete(extension_path, true);  // Recursive.
       continue;
     }
 
@@ -375,7 +375,7 @@
     if (iter_pair.first == iter_pair.second) {
       DVLOG(1) << "Deleting unreferenced install for directory "
                << extension_path.LossyDisplayName() << ".";
-      file_util::Delete(extension_path, true);  // Recursive.
+      base::Delete(extension_path, true);  // Recursive.
       continue;
     }
 
@@ -396,7 +396,7 @@
       if (!knownVersion) {
         DVLOG(1) << "Deleting old version for directory "
                  << version_dir.LossyDisplayName() << ".";
-        file_util::Delete(version_dir, true);  // Recursive.
+        base::Delete(version_dir, true);  // Recursive.
       }
     }
   }
@@ -570,7 +570,7 @@
 }
 
 void DeleteFile(const base::FilePath& path, bool recursive) {
-  file_util::Delete(path, recursive);
+  base::Delete(path, recursive);
 }
 
 }  // namespace extension_file_util
diff --git a/chrome/common/extensions/extension_file_util.h b/chrome/common/extensions/extension_file_util.h
index b7ae262..6335355 100644
--- a/chrome/common/extensions/extension_file_util.h
+++ b/chrome/common/extensions/extension_file_util.h
@@ -143,7 +143,7 @@
 base::FilePath GetInstallTempDir(const base::FilePath& extensions_dir);
 
 // Helper function to delete files. This is used to avoid ugly casts which
-// would be necessary with PostMessage since file_util::Delete is overloaded.
+// would be necessary with PostMessage since base::Delete is overloaded.
 // TODO(skerner): Make a version of Delete that is not overloaded in file_util.
 void DeleteFile(const base::FilePath& path, bool recursive);
 
diff --git a/chrome/common/extensions/extension_file_util_unittest.cc b/chrome/common/extensions/extension_file_util_unittest.cc
index b9d567d..ff90cf9 100644
--- a/chrome/common/extensions/extension_file_util_unittest.cc
+++ b/chrome/common/extensions/extension_file_util_unittest.cc
@@ -339,7 +339,7 @@
       " For the path " << url;
   }
   // Remove temp files.
-  ASSERT_TRUE(file_util::Delete(root_path, true));
+  ASSERT_TRUE(base::Delete(root_path, true));
 }
 
 static scoped_refptr<Extension> LoadExtensionManifest(
diff --git a/chrome/common/extensions/extension_localization_peer.cc b/chrome/common/extensions/extension_localization_peer.cc
deleted file mode 100644
index 9e7129c..0000000
--- a/chrome/common/extensions/extension_localization_peer.cc
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/common/extensions/extension_localization_peer.h"
-
-#include "base/memory/scoped_ptr.h"
-#include "base/strings/string_util.h"
-#include "chrome/common/extensions/extension_messages.h"
-#include "chrome/common/extensions/message_bundle.h"
-#include "chrome/common/url_constants.h"
-#include "extensions/common/constants.h"
-#include "grit/generated_resources.h"
-#include "net/base/net_errors.h"
-#include "net/http/http_response_headers.h"
-#include "webkit/glue/webkit_glue.h"
-
-ExtensionLocalizationPeer::ExtensionLocalizationPeer(
-    webkit_glue::ResourceLoaderBridge::Peer* peer,
-    IPC::Sender* message_sender,
-    const GURL& request_url)
-    : original_peer_(peer),
-      message_sender_(message_sender),
-      request_url_(request_url) {
-}
-
-ExtensionLocalizationPeer::~ExtensionLocalizationPeer() {
-}
-
-// static
-ExtensionLocalizationPeer*
-ExtensionLocalizationPeer::CreateExtensionLocalizationPeer(
-    webkit_glue::ResourceLoaderBridge::Peer* peer,
-    IPC::Sender* message_sender,
-    const std::string& mime_type,
-    const GURL& request_url) {
-  // Return NULL if content is not text/css or it doesn't belong to extension
-  // scheme.
-  return (request_url.SchemeIs(extensions::kExtensionScheme) &&
-          StartsWithASCII(mime_type, "text/css", false)) ?
-      new ExtensionLocalizationPeer(peer, message_sender, request_url) : NULL;
-}
-
-void ExtensionLocalizationPeer::OnUploadProgress(
-    uint64 position, uint64 size) {
-  NOTREACHED();
-}
-
-bool ExtensionLocalizationPeer::OnReceivedRedirect(
-    const GURL& new_url,
-    const webkit_glue::ResourceResponseInfo& info,
-    bool* has_new_first_party_for_cookies,
-    GURL* new_first_party_for_cookies) {
-  NOTREACHED();
-  return false;
-}
-
-void ExtensionLocalizationPeer::OnReceivedResponse(
-    const webkit_glue::ResourceResponseInfo& info) {
-  response_info_ = info;
-}
-
-void ExtensionLocalizationPeer::OnReceivedData(const char* data,
-                                               int data_length,
-                                               int encoded_data_length) {
-  data_.append(data, data_length);
-}
-
-void ExtensionLocalizationPeer::OnCompletedRequest(
-    int error_code,
-    bool was_ignored_by_handler,
-    const std::string& security_info,
-    const base::TimeTicks& completion_time) {
-  // Make sure we delete ourselves at the end of this call.
-  scoped_ptr<ExtensionLocalizationPeer> this_deleter(this);
-
-  // Give sub-classes a chance at altering the data.
-  if (error_code != net::OK) {
-    // We failed to load the resource.
-    original_peer_->OnReceivedResponse(response_info_);
-    original_peer_->OnCompletedRequest(net::ERR_ABORTED, false, security_info,
-                                       completion_time);
-    return;
-  }
-
-  ReplaceMessages();
-
-  original_peer_->OnReceivedResponse(response_info_);
-  if (!data_.empty())
-    original_peer_->OnReceivedData(data_.data(),
-                                   static_cast<int>(data_.size()),
-                                   -1);
-  original_peer_->OnCompletedRequest(error_code, was_ignored_by_handler,
-                                     security_info, completion_time);
-}
-
-void ExtensionLocalizationPeer::ReplaceMessages() {
-  if (!message_sender_ || data_.empty())
-    return;
-
-  if (!request_url_.is_valid())
-    return;
-
-  std::string extension_id = request_url_.host();
-  extensions::L10nMessagesMap* l10n_messages =
-      extensions::GetL10nMessagesMap(extension_id);
-  if (!l10n_messages) {
-    extensions::L10nMessagesMap messages;
-    message_sender_->Send(new ExtensionHostMsg_GetMessageBundle(
-        extension_id, &messages));
-
-    // Save messages we got, so we don't have to ask again.
-    // Messages map is never empty, it contains at least @@extension_id value.
-    extensions::ExtensionToL10nMessagesMap& l10n_messages_map =
-        *extensions::GetExtensionToL10nMessagesMap();
-    l10n_messages_map[extension_id] = messages;
-
-    l10n_messages = extensions::GetL10nMessagesMap(extension_id);
-  }
-
-  std::string error;
-  if (extensions::MessageBundle::ReplaceMessagesWithExternalDictionary(
-          *l10n_messages, &data_, &error)) {
-    data_.resize(data_.size());
-  }
-}
diff --git a/chrome/common/extensions/extension_localization_peer.h b/chrome/common/extensions/extension_localization_peer.h
deleted file mode 100644
index fd69f41..0000000
--- a/chrome/common/extensions/extension_localization_peer.h
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_COMMON_EXTENSIONS_EXTENSION_LOCALIZATION_PEER_H_
-#define CHROME_COMMON_EXTENSIONS_EXTENSION_LOCALIZATION_PEER_H_
-
-#include <string>
-
-#include "ipc/ipc_sender.h"
-#include "webkit/glue/resource_loader_bridge.h"
-
-// The ExtensionLocalizationPeer is a proxy to a
-// webkit_glue::ResourceLoaderBridge::Peer instance.  It is used to pre-process
-// CSS files requested by extensions to replace localization templates with the
-// appropriate localized strings.
-//
-// Call the factory method CreateExtensionLocalizationPeer() to obtain an
-// instance of ExtensionLocalizationPeer based on the original Peer.
-class ExtensionLocalizationPeer
-    : public webkit_glue::ResourceLoaderBridge::Peer {
- public:
-  virtual ~ExtensionLocalizationPeer();
-
-  static ExtensionLocalizationPeer* CreateExtensionLocalizationPeer(
-      webkit_glue::ResourceLoaderBridge::Peer* peer,
-      IPC::Sender* message_sender,
-      const std::string& mime_type,
-      const GURL& request_url);
-
-  // ResourceLoaderBridge::Peer methods.
-  virtual void OnUploadProgress(uint64 position, uint64 size) OVERRIDE;
-  virtual bool OnReceivedRedirect(
-      const GURL& new_url,
-      const webkit_glue::ResourceResponseInfo& info,
-      bool* has_new_first_party_for_cookies,
-      GURL* new_first_party_for_cookies) OVERRIDE;
-  virtual void OnReceivedResponse(
-      const webkit_glue::ResourceResponseInfo& info) OVERRIDE;
-  virtual void OnDownloadedData(int len) OVERRIDE {}
-  virtual void OnReceivedData(const char* data,
-                              int data_length,
-                              int encoded_data_length) OVERRIDE;
-  virtual void OnCompletedRequest(
-      int error_code,
-      bool was_ignored_by_handler,
-      const std::string& security_info,
-      const base::TimeTicks& completion_time) OVERRIDE;
-
- private:
-  friend class ExtensionLocalizationPeerTest;
-
-  // Use CreateExtensionLocalizationPeer to create an instance.
-  ExtensionLocalizationPeer(
-      webkit_glue::ResourceLoaderBridge::Peer* peer,
-      IPC::Sender* message_sender,
-      const GURL& request_url);
-
-  // Loads message catalogs, and replaces all __MSG_some_name__ templates within
-  // loaded file.
-  void ReplaceMessages();
-
-  // Original peer that handles the request once we are done processing data_.
-  webkit_glue::ResourceLoaderBridge::Peer* original_peer_;
-
-  // We just pass though the response info. This holds the copy of the original.
-  webkit_glue::ResourceResponseInfo response_info_;
-
-  // Sends ExtensionHostMsg_GetMessageBundle message to the browser to fetch
-  // message catalog.
-  IPC::Sender* message_sender_;
-
-  // Buffer for incoming data. We wait until OnCompletedRequest before using it.
-  std::string data_;
-
-  // Original request URL.
-  GURL request_url_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ExtensionLocalizationPeer);
-};
-
-#endif  // CHROME_COMMON_EXTENSIONS_EXTENSION_LOCALIZATION_PEER_H_
diff --git a/chrome/common/extensions/extension_localization_peer_unittest.cc b/chrome/common/extensions/extension_localization_peer_unittest.cc
deleted file mode 100644
index df74791..0000000
--- a/chrome/common/extensions/extension_localization_peer_unittest.cc
+++ /dev/null
@@ -1,250 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <map>
-#include <string>
-
-#include "base/memory/scoped_ptr.h"
-#include "chrome/common/extensions/extension_localization_peer.h"
-#include "chrome/common/extensions/message_bundle.h"
-#include "ipc/ipc_sender.h"
-#include "ipc/ipc_sync_message.h"
-#include "net/base/net_errors.h"
-#include "net/url_request/url_request_status.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/glue/resource_loader_bridge.h"
-
-using testing::_;
-using testing::DoAll;
-using testing::Invoke;
-using testing::StrEq;
-using testing::Return;
-
-static const char* const kExtensionUrl_1 =
-    "chrome-extension://some_id/popup.css";
-
-static const char* const kExtensionUrl_2 =
-    "chrome-extension://some_id2/popup.css";
-
-static const char* const kExtensionUrl_3 =
-    "chrome-extension://some_id3/popup.css";
-
-void MessageDeleter(IPC::Message* message) {
-  delete message;
-}
-
-class MockIpcMessageSender : public IPC::Sender {
- public:
-  MockIpcMessageSender() {
-    ON_CALL(*this, Send(_))
-        .WillByDefault(DoAll(Invoke(MessageDeleter), Return(true)));
-  }
-
-  virtual ~MockIpcMessageSender() {}
-
-  MOCK_METHOD1(Send, bool(IPC::Message* message));
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockIpcMessageSender);
-};
-
-class MockResourceLoaderBridgePeer
-    : public webkit_glue::ResourceLoaderBridge::Peer {
- public:
-  MockResourceLoaderBridgePeer() {}
-  virtual ~MockResourceLoaderBridgePeer() {}
-
-  MOCK_METHOD2(OnUploadProgress, void(uint64 position, uint64 size));
-  MOCK_METHOD4(OnReceivedRedirect, bool(
-      const GURL& new_url,
-      const webkit_glue::ResourceResponseInfo& info,
-      bool* has_new_first_party_for_cookies,
-      GURL* new_first_party_for_cookies));
-  MOCK_METHOD1(OnReceivedResponse, void(
-      const webkit_glue::ResourceResponseInfo& info));
-  MOCK_METHOD1(OnDownloadedData, void(int len));
-  MOCK_METHOD3(OnReceivedData, void(const char* data,
-                                    int data_length,
-                                    int encoded_data_length));
-  MOCK_METHOD4(OnCompletedRequest, void(
-      int error_code,
-      bool was_ignored_by_handler,
-      const std::string& security_info,
-      const base::TimeTicks& completion_time));
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockResourceLoaderBridgePeer);
-};
-
-class ExtensionLocalizationPeerTest : public testing::Test {
- protected:
-  virtual void SetUp() {
-    sender_.reset(new MockIpcMessageSender());
-    original_peer_.reset(new MockResourceLoaderBridgePeer());
-    filter_peer_.reset(
-        ExtensionLocalizationPeer::CreateExtensionLocalizationPeer(
-            original_peer_.get(), sender_.get(), "text/css",
-            GURL(kExtensionUrl_1)));
-  }
-
-  ExtensionLocalizationPeer* CreateExtensionLocalizationPeer(
-      const std::string& mime_type,
-      const GURL& request_url) {
-    return ExtensionLocalizationPeer::CreateExtensionLocalizationPeer(
-        original_peer_.get(), sender_.get(), mime_type, request_url);
-  }
-
-  std::string GetData(ExtensionLocalizationPeer* filter_peer) {
-    EXPECT_TRUE(NULL != filter_peer);
-    return filter_peer->data_;
-  }
-
-  void SetData(ExtensionLocalizationPeer* filter_peer,
-               const std::string& data) {
-    EXPECT_TRUE(NULL != filter_peer);
-    filter_peer->data_ = data;
-  }
-
-  scoped_ptr<MockIpcMessageSender> sender_;
-  scoped_ptr<MockResourceLoaderBridgePeer> original_peer_;
-  scoped_ptr<ExtensionLocalizationPeer> filter_peer_;
-};
-
-TEST_F(ExtensionLocalizationPeerTest, CreateWithWrongMimeType) {
-  filter_peer_.reset(
-      CreateExtensionLocalizationPeer("text/html", GURL(kExtensionUrl_1)));
-  EXPECT_TRUE(NULL == filter_peer_.get());
-}
-
-TEST_F(ExtensionLocalizationPeerTest, CreateWithValidInput) {
-  EXPECT_TRUE(NULL != filter_peer_.get());
-}
-
-TEST_F(ExtensionLocalizationPeerTest, OnReceivedData) {
-  EXPECT_TRUE(GetData(filter_peer_.get()).empty());
-
-  const std::string data_chunk("12345");
-  filter_peer_->OnReceivedData(data_chunk.c_str(), data_chunk.length(), -1);
-
-  EXPECT_EQ(data_chunk, GetData(filter_peer_.get()));
-
-  filter_peer_->OnReceivedData(data_chunk.c_str(), data_chunk.length(), -1);
-  EXPECT_EQ(data_chunk + data_chunk, GetData(filter_peer_.get()));
-}
-
-MATCHER_P(IsURLRequestEqual, status, "") { return arg.status() == status; }
-
-TEST_F(ExtensionLocalizationPeerTest, OnCompletedRequestBadURLRequestStatus) {
-  // It will self-delete once it exits OnCompletedRequest.
-  ExtensionLocalizationPeer* filter_peer = filter_peer_.release();
-
-  EXPECT_CALL(*original_peer_, OnReceivedResponse(_));
-  EXPECT_CALL(*original_peer_, OnCompletedRequest(
-    net::ERR_ABORTED, false, "", base::TimeTicks()));
-
-  filter_peer->OnCompletedRequest(
-      net::ERR_FAILED, false, std::string(), base::TimeTicks());
-}
-
-TEST_F(ExtensionLocalizationPeerTest, OnCompletedRequestEmptyData) {
-  // It will self-delete once it exits OnCompletedRequest.
-  ExtensionLocalizationPeer* filter_peer = filter_peer_.release();
-
-  EXPECT_CALL(*original_peer_, OnReceivedData(_, _, _)).Times(0);
-  EXPECT_CALL(*sender_, Send(_)).Times(0);
-
-  EXPECT_CALL(*original_peer_, OnReceivedResponse(_));
-  EXPECT_CALL(*original_peer_, OnCompletedRequest(
-      net::OK, false, "", base::TimeTicks()));
-
-  filter_peer->OnCompletedRequest(
-      net::OK, false, std::string(), base::TimeTicks());
-}
-
-TEST_F(ExtensionLocalizationPeerTest, OnCompletedRequestNoCatalogs) {
-  // It will self-delete once it exits OnCompletedRequest.
-  ExtensionLocalizationPeer* filter_peer = filter_peer_.release();
-
-  SetData(filter_peer, "some text");
-
-  EXPECT_CALL(*sender_, Send(_));
-
-  std::string data = GetData(filter_peer);
-  EXPECT_CALL(*original_peer_,
-              OnReceivedData(StrEq(data.data()), data.length(), -1)).Times(2);
-
-  EXPECT_CALL(*original_peer_, OnReceivedResponse(_)).Times(2);
-  EXPECT_CALL(*original_peer_, OnCompletedRequest(
-          net::OK, false, "", base::TimeTicks())).Times(2);
-
-  filter_peer->OnCompletedRequest(
-      net::OK, false, std::string(), base::TimeTicks());
-
-  // Test if Send gets called again (it shouldn't be) when first call returned
-  // an empty dictionary.
-  filter_peer =
-      CreateExtensionLocalizationPeer("text/css", GURL(kExtensionUrl_1));
-  SetData(filter_peer, "some text");
-  filter_peer->OnCompletedRequest(
-      net::OK, false, std::string(), base::TimeTicks());
-}
-
-TEST_F(ExtensionLocalizationPeerTest, OnCompletedRequestWithCatalogs) {
-  // It will self-delete once it exits OnCompletedRequest.
-  ExtensionLocalizationPeer* filter_peer =
-      CreateExtensionLocalizationPeer("text/css", GURL(kExtensionUrl_2));
-
-  extensions::L10nMessagesMap messages;
-  messages.insert(std::make_pair("text", "new text"));
-  extensions::ExtensionToL10nMessagesMap& l10n_messages_map =
-      *extensions::GetExtensionToL10nMessagesMap();
-  l10n_messages_map["some_id2"] = messages;
-
-  SetData(filter_peer, "some __MSG_text__");
-
-  // We already have messages in memory, Send will be skipped.
-  EXPECT_CALL(*sender_, Send(_)).Times(0);
-
-  // __MSG_text__ gets replaced with "new text".
-  std::string data("some new text");
-  EXPECT_CALL(*original_peer_,
-              OnReceivedData(StrEq(data.data()), data.length(), -1));
-
-  EXPECT_CALL(*original_peer_, OnReceivedResponse(_));
-  EXPECT_CALL(*original_peer_, OnCompletedRequest(
-      net::OK, false, "", base::TimeTicks()));
-
-  filter_peer->OnCompletedRequest(
-      net::OK, false, std::string(), base::TimeTicks());
-}
-
-TEST_F(ExtensionLocalizationPeerTest, OnCompletedRequestReplaceMessagesFails) {
-  // It will self-delete once it exits OnCompletedRequest.
-  ExtensionLocalizationPeer* filter_peer =
-      CreateExtensionLocalizationPeer("text/css", GURL(kExtensionUrl_3));
-
-  extensions::L10nMessagesMap messages;
-  messages.insert(std::make_pair("text", "new text"));
-  extensions::ExtensionToL10nMessagesMap& l10n_messages_map =
-      *extensions::GetExtensionToL10nMessagesMap();
-  l10n_messages_map["some_id3"] = messages;
-
-  std::string message("some __MSG_missing_message__");
-  SetData(filter_peer, message);
-
-  // We already have messages in memory, Send will be skipped.
-  EXPECT_CALL(*sender_, Send(_)).Times(0);
-
-  // __MSG_missing_message__ is missing, so message stays the same.
-  EXPECT_CALL(*original_peer_,
-              OnReceivedData(StrEq(message.data()), message.length(), -1));
-
-  EXPECT_CALL(*original_peer_, OnReceivedResponse(_));
-  EXPECT_CALL(*original_peer_, OnCompletedRequest(
-      net::OK, false, "", base::TimeTicks()));
-
-  filter_peer->OnCompletedRequest(
-      net::OK, false, std::string(), base::TimeTicks());
-}
diff --git a/chrome/common/extensions/extension_messages.h b/chrome/common/extensions/extension_messages.h
index 708f0f6..303237c 100644
--- a/chrome/common/extensions/extension_messages.h
+++ b/chrome/common/extensions/extension_messages.h
@@ -11,7 +11,7 @@
 #include "base/shared_memory.h"
 #include "base/values.h"
 #include "chrome/common/extensions/extension.h"
-#include "chrome/common/extensions/permissions/bluetooth_device_permission_data.h"
+#include "chrome/common/extensions/permissions/bluetooth_permission_data.h"
 #include "chrome/common/extensions/permissions/media_galleries_permission_data.h"
 #include "chrome/common/extensions/permissions/permission_set.h"
 #include "chrome/common/extensions/permissions/socket_permission_data.h"
@@ -171,10 +171,6 @@
   IPC_STRUCT_TRAITS_MEMBER(match_subdomains())
 IPC_STRUCT_TRAITS_END()
 
-IPC_STRUCT_TRAITS_BEGIN(extensions::BluetoothDevicePermissionData)
-  IPC_STRUCT_TRAITS_MEMBER(device_address())
-IPC_STRUCT_TRAITS_END()
-
 IPC_STRUCT_TRAITS_BEGIN(extensions::UsbDevicePermissionData)
   IPC_STRUCT_TRAITS_MEMBER(vendor_id())
   IPC_STRUCT_TRAITS_MEMBER(product_id())
@@ -184,6 +180,10 @@
   IPC_STRUCT_TRAITS_MEMBER(permission())
 IPC_STRUCT_TRAITS_END()
 
+IPC_STRUCT_TRAITS_BEGIN(extensions::BluetoothPermissionData)
+  IPC_STRUCT_TRAITS_MEMBER(uuid())
+IPC_STRUCT_TRAITS_END()
+
 // Singly-included section for custom IPC traits.
 #ifndef CHROME_COMMON_EXTENSIONS_EXTENSION_MESSAGES_H_
 #define CHROME_COMMON_EXTENSIONS_EXTENSION_MESSAGES_H_
@@ -426,7 +426,7 @@
 // Deliver a message sent with ExtensionHostMsg_PostMessage.
 IPC_MESSAGE_ROUTED2(ExtensionMsg_DeliverMessage,
                     int /* target_port_id */,
-                    base::ListValue /* message args, a 0-or-1 length list */)
+                    std::string /* message */)
 
 // Dispatch the Port.onDisconnect event for message channels.
 IPC_MESSAGE_ROUTED2(ExtensionMsg_DispatchOnDisconnect,
@@ -536,7 +536,7 @@
 // by ViewHostMsg_OpenChannelTo*.
 IPC_MESSAGE_ROUTED2(ExtensionHostMsg_PostMessage,
                     int /* port_id */,
-                    base::ListValue /* message args, a 0-or-1 length list */)
+                    std::string /* message */)
 
 // Send a message to an extension process.  The handle is the value returned
 // by ViewHostMsg_OpenChannelTo*.
diff --git a/chrome/common/extensions/manifest_handlers/icons_handler.cc b/chrome/common/extensions/manifest_handlers/icons_handler.cc
index c068a5c..2d107df 100644
--- a/chrome/common/extensions/manifest_handlers/icons_handler.cc
+++ b/chrome/common/extensions/manifest_handlers/icons_handler.cc
@@ -14,11 +14,12 @@
 #include "chrome/common/extensions/extension_file_util.h"
 #include "chrome/common/extensions/extension_manifest_constants.h"
 #include "chrome/common/extensions/manifest_handler_helpers.h"
+#include "content/public/child/image_decoder_utils.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/base/resource/resource_bundle.h"
-#include "webkit/glue/image_decoder.h"
+#include "ui/gfx/size.h"
 
 namespace keys = extension_manifest_keys;
 
@@ -71,9 +72,8 @@
   // Decode the image using WebKit's image decoder.
   const unsigned char* data =
     reinterpret_cast<const unsigned char*>(file_contents.data());
-  webkit_glue::ImageDecoder decoder;
   scoped_ptr<SkBitmap> decoded(new SkBitmap());
-  *decoded = decoder.Decode(data, file_contents.length());
+  *decoded = content::DecodeImage(data, gfx::Size(), file_contents.length());
   if (decoded->empty()) {
     DLOG(ERROR) << "Could not decode icon file: "
                 << icon_path.LossyDisplayName();
diff --git a/chrome/common/extensions/manifest_tests/extension_manifests_dummy_unittest.cc b/chrome/common/extensions/manifest_tests/extension_manifests_dummy_unittest.cc
new file mode 100644
index 0000000..73c1350
--- /dev/null
+++ b/chrome/common/extensions/manifest_tests/extension_manifests_dummy_unittest.cc
@@ -0,0 +1,21 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/common/extensions/manifest_tests/extension_manifest_test.h"
+
+namespace extensions {
+
+TEST_F(ExtensionManifestTest, PlatformsKey) {
+  scoped_refptr<Extension> extension =
+      LoadAndExpectSuccess("platforms_key.json");
+  EXPECT_EQ(0u, extension->install_warnings().size());
+}
+
+TEST_F(ExtensionManifestTest, UnrecognizedKeyWarning) {
+  scoped_refptr<Extension> extension =
+      LoadAndExpectWarning("unrecognized_key.json",
+                           "Unrecognized manifest key 'unrecognized_key_1'.");
+}
+
+}  // namespace extensions
diff --git a/chrome/common/extensions/permissions/api_permission.h b/chrome/common/extensions/permissions/api_permission.h
index 5c60fb5..ca9e7b1 100644
--- a/chrome/common/extensions/permissions/api_permission.h
+++ b/chrome/common/extensions/permissions/api_permission.h
@@ -47,7 +47,6 @@
     kAutoTestPrivate,
     kBackground,
     kBluetooth,
-    kBluetoothDevice,
     kBookmark,
     kBookmarkManagerPrivate,
     kBrowsingData,
@@ -59,6 +58,7 @@
     kContentSettings,
     kContextMenus,
     kCookie,
+    kDiagnostics,
     kDial,
     kDebugger,
     kDeclarative,
diff --git a/chrome/common/extensions/permissions/bluetooth_device_permission.cc b/chrome/common/extensions/permissions/bluetooth_device_permission.cc
deleted file mode 100644
index cea2f06..0000000
--- a/chrome/common/extensions/permissions/bluetooth_device_permission.cc
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/common/extensions/permissions/bluetooth_device_permission.h"
-
-#include <string>
-#include <vector>
-
-#include "base/logging.h"
-#include "base/strings/string16.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/common/extensions/permissions/bluetooth_device_permission_data.h"
-#include "chrome/common/extensions/permissions/permissions_info.h"
-#include "device/bluetooth/bluetooth_adapter.h"
-#include "device/bluetooth/bluetooth_adapter_factory.h"
-#include "device/bluetooth/bluetooth_device.h"
-#include "grit/generated_resources.h"
-#include "ui/base/l10n/l10n_util.h"
-
-namespace extensions {
-
-BluetoothDevicePermission::BluetoothDevicePermission(
-    const APIPermissionInfo* info)
-  : SetDisjunctionPermission<BluetoothDevicePermissionData,
-                             BluetoothDevicePermission>(info) {
-}
-
-BluetoothDevicePermission::~BluetoothDevicePermission() {
-}
-
-bool BluetoothDevicePermission::ManifestEntryForbidden() const {
-  return true;
-}
-
-PermissionMessages BluetoothDevicePermission::GetMessages() const {
-  DCHECK(HasMessages());
-  PermissionMessages result;
-
-  scoped_refptr<device::BluetoothAdapter> bluetooth_adapter =
-      device::BluetoothAdapterFactory::MaybeGetAdapter();
-
-  for (std::set<BluetoothDevicePermissionData>::const_iterator i =
-      data_set_.begin(); i != data_set_.end(); ++i) {
-
-    const std::string& device_address = i->device_address();
-    string16 device_identifier;
-    if (bluetooth_adapter.get()) {
-      device::BluetoothDevice* device =
-          bluetooth_adapter->GetDevice(device_address);
-      if (device)
-        device_identifier = device->GetName();
-    }
-
-    if (device_identifier.length() == 0) {
-      UTF8ToUTF16(device_address.c_str(), device_address.length(),
-          &device_identifier);
-    }
-
-    result.push_back(PermissionMessage(
-          PermissionMessage::kBluetoothDevice,
-          l10n_util::GetStringFUTF16(
-              IDS_EXTENSION_PROMPT_WARNING_BLUETOOTH_DEVICE,
-              device_identifier)));
-  }
-
-  return result;
-}
-
-}  // namespace extensions
diff --git a/chrome/common/extensions/permissions/bluetooth_device_permission.h b/chrome/common/extensions/permissions/bluetooth_device_permission.h
deleted file mode 100644
index e818224..0000000
--- a/chrome/common/extensions/permissions/bluetooth_device_permission.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_COMMON_EXTENSIONS_PERMISSIONS_BLUETOOTH_DEVICE_PERMISSION_H_
-#define CHROME_COMMON_EXTENSIONS_PERMISSIONS_BLUETOOTH_DEVICE_PERMISSION_H_
-
-#include <string>
-
-#include "chrome/common/extensions/permissions/api_permission.h"
-#include "chrome/common/extensions/permissions/bluetooth_device_permission_data.h"
-#include "chrome/common/extensions/permissions/set_disjunction_permission.h"
-
-namespace extensions {
-
-// BluetoothDevicePermission represents the permission to access a specific
-// Bluetooth Device.
-class BluetoothDevicePermission
-  : public SetDisjunctionPermission<BluetoothDevicePermissionData,
-                                    BluetoothDevicePermission> {
- public:
-  // A Bluetooth device address that should be check for permission to access.
-  struct CheckParam : APIPermission::CheckParam {
-    explicit CheckParam(std::string device_address)
-      : device_address(device_address) {}
-    const std::string device_address;
-  };
-
-  explicit BluetoothDevicePermission(const APIPermissionInfo* info);
-  virtual ~BluetoothDevicePermission();
-
-  // APIPermission overrides
-  virtual bool ManifestEntryForbidden() const OVERRIDE;
-  virtual PermissionMessages GetMessages() const OVERRIDE;
-};
-
-}  // namespace extensions
-
-#endif  // CHROME_COMMON_EXTENSIONS_PERMISSIONS_BLUETOOTH_DEVICE_PERMISSION_H_
diff --git a/chrome/common/extensions/permissions/bluetooth_device_permission_data.cc b/chrome/common/extensions/permissions/bluetooth_device_permission_data.cc
deleted file mode 100644
index 82c5acd..0000000
--- a/chrome/common/extensions/permissions/bluetooth_device_permission_data.cc
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/common/extensions/permissions/bluetooth_device_permission_data.h"
-
-#include <string>
-
-#include "base/memory/scoped_ptr.h"
-#include "base/values.h"
-#include "chrome/common/extensions/permissions/bluetooth_device_permission.h"
-
-namespace {
-
-const char* kDeviceAddressKey = "deviceAddress";
-
-}  // namespace
-
-namespace extensions {
-
-BluetoothDevicePermissionData::BluetoothDevicePermissionData() {}
-
-BluetoothDevicePermissionData::BluetoothDevicePermissionData(
-    const std::string& device_address) : device_address_(device_address) {
-}
-
-bool BluetoothDevicePermissionData::Check(
-    const APIPermission::CheckParam* param) const {
-  if (!param)
-    return false;
-  const BluetoothDevicePermission::CheckParam& specific_param =
-      *static_cast<const BluetoothDevicePermission::CheckParam*>(param);
-  return device_address_ == specific_param.device_address;
-}
-
-scoped_ptr<base::Value> BluetoothDevicePermissionData::ToValue() const {
-  base::DictionaryValue* result = new base::DictionaryValue();
-  result->SetString(kDeviceAddressKey, device_address_);
-  return scoped_ptr<base::Value>(result);
-}
-
-bool BluetoothDevicePermissionData::FromValue(const base::Value* value) {
-  if (!value)
-    return false;
-
-  const base::DictionaryValue* dict_value;
-  if (!value->GetAsDictionary(&dict_value))
-    return false;
-
-  if (!dict_value->GetString(kDeviceAddressKey, &device_address_)) {
-    device_address_.clear();
-    return false;
-  }
-
-  return true;
-}
-
-bool BluetoothDevicePermissionData::operator<(
-    const BluetoothDevicePermissionData& rhs) const {
-  return device_address_ < rhs.device_address_;
-}
-
-bool BluetoothDevicePermissionData::operator==(
-    const BluetoothDevicePermissionData& rhs) const {
-  return device_address_ == rhs.device_address_;
-}
-
-}  // namespace extensions
diff --git a/chrome/common/extensions/permissions/bluetooth_device_permission_data.h b/chrome/common/extensions/permissions/bluetooth_device_permission_data.h
deleted file mode 100644
index ede285d..0000000
--- a/chrome/common/extensions/permissions/bluetooth_device_permission_data.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_COMMON_EXTENSIONS_PERMISSIONS_BLUETOOTH_DEVICE_PERMISSION_DATA_H_
-#define CHROME_COMMON_EXTENSIONS_PERMISSIONS_BLUETOOTH_DEVICE_PERMISSION_DATA_H_
-
-#include <string>
-
-#include "base/memory/scoped_ptr.h"
-#include "chrome/common/extensions/permissions/api_permission.h"
-
-namespace base {
-
-class Value;
-
-}  // namespace base
-
-namespace extensions {
-
-// A pattern that can be used to match a Bluetooth device permission.
-// Must be of the format: "XX:XX:XX:XX:XX:XX", where XX are hexadecimal digits.
-class BluetoothDevicePermissionData {
- public:
-  BluetoothDevicePermissionData();
-  explicit BluetoothDevicePermissionData(const std::string& device_address);
-
-  // Check if |param| (which must be a BluetoothDevicePermission::CheckParam)
-  // matches the address of this object..
-  bool Check(const APIPermission::CheckParam* param) const;
-
-  // Convert |this| into a base::Value.
-  scoped_ptr<base::Value> ToValue() const;
-
-  // Populate |this| from a base::Value.
-  bool FromValue(const base::Value* value);
-
-  bool operator<(const BluetoothDevicePermissionData& rhs) const;
-  bool operator==(const BluetoothDevicePermissionData& rhs) const;
-
-  // The address |this| matches against.
-  const std::string& device_address() const { return device_address_; }
-
-  // This accessor is provided for IPC_STRUCT_TRAITS_MEMBER.  Please
-  // think twice before using it for anything else.
-  std::string& device_address() { return device_address_; }
-
- private:
-  std::string device_address_;
-};
-
-}  // namespace extensions
-
-#endif  // CHROME_COMMON_EXTENSIONS_PERMISSIONS_BLUETOOTH_DEVICE_PERMISSION_DATA_H_
diff --git a/chrome/common/extensions/permissions/bluetooth_permission.cc b/chrome/common/extensions/permissions/bluetooth_permission.cc
new file mode 100644
index 0000000..984c4a0
--- /dev/null
+++ b/chrome/common/extensions/permissions/bluetooth_permission.cc
@@ -0,0 +1,65 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/common/extensions/permissions/bluetooth_permission.h"
+
+#include <string>
+
+#include "base/logging.h"
+#include "base/strings/string16.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/common/extensions/permissions/bluetooth_permission_data.h"
+#include "chrome/common/extensions/permissions/permissions_info.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace extensions {
+
+BluetoothPermission::BluetoothPermission(const APIPermissionInfo* info)
+  : SetDisjunctionPermission<BluetoothPermissionData,
+                             BluetoothPermission>(info) {
+}
+
+BluetoothPermission::~BluetoothPermission() {
+}
+
+bool BluetoothPermission::FromValue(const base::Value* value) {
+  // Value may be omitted to gain access to non-profile functions.
+  if (!value)
+    return true;
+
+  // Value may be an empty list for the same reason.
+  const base::ListValue* list = NULL;
+  if (value->GetAsList(&list) && list->GetSize() == 0)
+    return true;
+
+  if (!SetDisjunctionPermission<BluetoothPermissionData,
+                                BluetoothPermission>::FromValue(value)) {
+    return false;
+  }
+
+  return true;
+}
+
+PermissionMessages BluetoothPermission::GetMessages() const {
+  DCHECK(HasMessages());
+  PermissionMessages result;
+
+  result.push_back(PermissionMessage(
+        PermissionMessage::kBluetooth,
+        l10n_util::GetStringUTF16(
+            IDS_EXTENSION_PROMPT_WARNING_BLUETOOTH)));
+
+  if (!data_set_.empty()) {
+    result.push_back(PermissionMessage(
+          PermissionMessage::kBluetoothDevices,
+          l10n_util::GetStringUTF16(
+              IDS_EXTENSION_PROMPT_WARNING_BLUETOOTH_DEVICES)));
+  }
+
+  return result;
+}
+
+}  // namespace extensions
diff --git a/chrome/common/extensions/permissions/bluetooth_permission.h b/chrome/common/extensions/permissions/bluetooth_permission.h
new file mode 100644
index 0000000..7ca8445
--- /dev/null
+++ b/chrome/common/extensions/permissions/bluetooth_permission.h
@@ -0,0 +1,43 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_COMMON_EXTENSIONS_PERMISSIONS_BLUETOOTH_PERMISSION_H_
+#define CHROME_COMMON_EXTENSIONS_PERMISSIONS_BLUETOOTH_PERMISSION_H_
+
+#include <string>
+
+#include "chrome/common/extensions/permissions/api_permission.h"
+#include "chrome/common/extensions/permissions/bluetooth_permission_data.h"
+#include "chrome/common/extensions/permissions/set_disjunction_permission.h"
+
+namespace extensions {
+
+// BluetoothPermission represents the permission to implement a specific
+// Bluetooth Profile.
+class BluetoothPermission
+  : public SetDisjunctionPermission<BluetoothPermissionData,
+                                    BluetoothPermission> {
+ public:
+  // A Bluetooth profile uuid that should be checked for permission to access.
+  struct CheckParam : APIPermission::CheckParam {
+    explicit CheckParam(std::string uuid)
+      : uuid(uuid) {}
+    const std::string uuid;
+  };
+
+  explicit BluetoothPermission(const APIPermissionInfo* info);
+  virtual ~BluetoothPermission();
+
+  // SetDisjunctionPermission overrides.
+  // BluetoothPermission permits an empty list for gaining permission to the
+  // Bluetooth APIs without implementing a profile.
+  virtual bool FromValue(const base::Value* value) OVERRIDE;
+
+  // APIPermission overrides
+  virtual PermissionMessages GetMessages() const OVERRIDE;
+};
+
+}  // namespace extensions
+
+#endif  // CHROME_COMMON_EXTENSIONS_PERMISSIONS_BLUETOOTH_PERMISSION_H_
diff --git a/chrome/common/extensions/permissions/bluetooth_permission_data.cc b/chrome/common/extensions/permissions/bluetooth_permission_data.cc
new file mode 100644
index 0000000..70eb747
--- /dev/null
+++ b/chrome/common/extensions/permissions/bluetooth_permission_data.cc
@@ -0,0 +1,73 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/common/extensions/permissions/bluetooth_permission_data.h"
+
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/values.h"
+#include "chrome/common/extensions/permissions/bluetooth_permission.h"
+#include "device/bluetooth/bluetooth_utils.h"
+
+namespace {
+
+const char* kUuidKey = "uuid";
+
+}  // namespace
+
+namespace extensions {
+
+BluetoothPermissionData::BluetoothPermissionData() {}
+
+BluetoothPermissionData::BluetoothPermissionData(
+    const std::string& uuid) : uuid_(uuid) {
+}
+
+bool BluetoothPermissionData::Check(
+    const APIPermission::CheckParam* param) const {
+  if (!param)
+    return false;
+  const BluetoothPermission::CheckParam& specific_param =
+      *static_cast<const BluetoothPermission::CheckParam*>(param);
+
+  std::string canonical_uuid = device::bluetooth_utils::CanonicalUuid(uuid_);
+  std::string canonical_param_uuid = device::bluetooth_utils::CanonicalUuid(
+      specific_param.uuid);
+  return canonical_uuid == canonical_param_uuid;
+}
+
+scoped_ptr<base::Value> BluetoothPermissionData::ToValue() const {
+  base::DictionaryValue* result = new base::DictionaryValue();
+  result->SetString(kUuidKey, uuid_);
+  return scoped_ptr<base::Value>(result);
+}
+
+bool BluetoothPermissionData::FromValue(const base::Value* value) {
+  if (!value)
+    return false;
+
+  const base::DictionaryValue* dict_value;
+  if (!value->GetAsDictionary(&dict_value))
+    return false;
+
+  if (!dict_value->GetString(kUuidKey, &uuid_)) {
+    uuid_.clear();
+    return false;
+  }
+
+  return true;
+}
+
+bool BluetoothPermissionData::operator<(
+    const BluetoothPermissionData& rhs) const {
+  return uuid_ < rhs.uuid_;
+}
+
+bool BluetoothPermissionData::operator==(
+    const BluetoothPermissionData& rhs) const {
+  return uuid_ == rhs.uuid_;
+}
+
+}  // namespace extensions
diff --git a/chrome/common/extensions/permissions/bluetooth_permission_data.h b/chrome/common/extensions/permissions/bluetooth_permission_data.h
new file mode 100644
index 0000000..9ae5dd4
--- /dev/null
+++ b/chrome/common/extensions/permissions/bluetooth_permission_data.h
@@ -0,0 +1,54 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_COMMON_EXTENSIONS_PERMISSIONS_BLUETOOTH_PERMISSION_DATA_H_
+#define CHROME_COMMON_EXTENSIONS_PERMISSIONS_BLUETOOTH_PERMISSION_DATA_H_
+
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+#include "chrome/common/extensions/permissions/api_permission.h"
+
+namespace base {
+
+class Value;
+
+}  // namespace base
+
+namespace extensions {
+
+// A pattern that can be used to match a Bluetooth profile permission, must be
+// of a format that can be passed to device::bluetooth_utils::CanonoicalUuid().
+class BluetoothPermissionData {
+ public:
+  BluetoothPermissionData();
+  explicit BluetoothPermissionData(const std::string& uuid);
+
+  // Check if |param| (which must be a BluetoothPermission::CheckParam)
+  // matches the uuid of this object.
+  bool Check(const APIPermission::CheckParam* param) const;
+
+  // Convert |this| into a base::Value.
+  scoped_ptr<base::Value> ToValue() const;
+
+  // Populate |this| from a base::Value.
+  bool FromValue(const base::Value* value);
+
+  bool operator<(const BluetoothPermissionData& rhs) const;
+  bool operator==(const BluetoothPermissionData& rhs) const;
+
+  // The uuid |this| matches against.
+  const std::string& uuid() const { return uuid_; }
+
+  // This accessor is provided for IPC_STRUCT_TRAITS_MEMBER.  Please
+  // think twice before using it for anything else.
+  std::string& uuid() { return uuid_; }
+
+ private:
+  std::string uuid_;
+};
+
+}  // namespace extensions
+
+#endif  // CHROME_COMMON_EXTENSIONS_PERMISSIONS_BLUETOOTH_PERMISSION_DATA_H_
diff --git a/chrome/common/extensions/permissions/chrome_api_permissions.cc b/chrome/common/extensions/permissions/chrome_api_permissions.cc
index 95aca85b..7e9269a 100644
--- a/chrome/common/extensions/permissions/chrome_api_permissions.cc
+++ b/chrome/common/extensions/permissions/chrome_api_permissions.cc
@@ -6,7 +6,7 @@
 
 #include "chrome/common/extensions/permissions/api_permission.h"
 #include "chrome/common/extensions/permissions/api_permission_set.h"
-#include "chrome/common/extensions/permissions/bluetooth_device_permission.h"
+#include "chrome/common/extensions/permissions/bluetooth_permission.h"
 #include "chrome/common/extensions/permissions/media_galleries_permission.h"
 #include "chrome/common/extensions/permissions/permission_message.h"
 #include "chrome/common/extensions/permissions/permissions_info.h"
@@ -149,6 +149,8 @@
       APIPermissionInfo::kFlagCannotBeOptional },
     { APIPermission::kDeveloperPrivate, "developerPrivate",
       APIPermissionInfo::kFlagCannotBeOptional },
+    { APIPermission::kDiagnostics, "diagnostics",
+      APIPermissionInfo::kFlagCannotBeOptional },
     { APIPermission::kDial, "dial", APIPermissionInfo::kFlagCannotBeOptional },
     { APIPermission::kDownloadsInternal, "downloadsInternal" },
     { APIPermission::kFileBrowserHandlerInternal, "fileBrowserHandlerInternal",
@@ -266,12 +268,13 @@
       &CreateAPIPermission<MediaGalleriesPermission> },
     { APIPermission::kPushMessaging, "pushMessaging",
       APIPermissionInfo::kFlagCannotBeOptional },
+    // Because warning messages for the "bluetooth" permission vary based on
+    // the permissions parameters, no message ID or message text is specified
+    // here. The message ID and text used will be determined at run-time in the
+    // |BluetoothPermission| class.
     { APIPermission::kBluetooth, "bluetooth", APIPermissionInfo::kFlagNone,
-      IDS_EXTENSION_PROMPT_WARNING_BLUETOOTH,
-      PermissionMessage::kBluetooth },
-    { APIPermission::kBluetoothDevice, "bluetoothDevices",
-      APIPermissionInfo::kFlagNone, 0, PermissionMessage::kNone,
-      &CreateAPIPermission<BluetoothDevicePermission> },
+      0, PermissionMessage::kNone,
+      &CreateAPIPermission<BluetoothPermission> },
     { APIPermission::kUsb, "usb", APIPermissionInfo::kFlagNone,
       IDS_EXTENSION_PROMPT_WARNING_USB,
       PermissionMessage::kUsb },
diff --git a/chrome/common/extensions/permissions/permission_message.h b/chrome/common/extensions/permissions/permission_message.h
index 8ff7bcd..ad814ae 100644
--- a/chrome/common/extensions/permissions/permission_message.h
+++ b/chrome/common/extensions/permissions/permission_message.h
@@ -54,7 +54,6 @@
     kBluetooth,
     kUsb,
     kSystemIndicator,
-    kBluetoothDevice,
     kUsbDevice,
     kMediaGalleriesAllGalleriesWrite,
     kSystemInfoDisplay,
@@ -65,6 +64,7 @@
     kMusicManagerPrivate,
     kWebConnectable,
     kActivityLogPrivate,
+    kBluetoothDevices,
     kEnumBoundary,
   };
 
diff --git a/chrome/common/extensions/permissions/permission_set_unittest.cc b/chrome/common/extensions/permissions/permission_set_unittest.cc
index 232afc6..e5d6e4e 100644
--- a/chrome/common/extensions/permissions/permission_set_unittest.cc
+++ b/chrome/common/extensions/permissions/permission_set_unittest.cc
@@ -632,6 +632,7 @@
   skip.insert(APIPermission::kAudio);
   skip.insert(APIPermission::kBrowsingData);
   skip.insert(APIPermission::kContextMenus);
+  skip.insert(APIPermission::kDiagnostics);
   skip.insert(APIPermission::kFontSettings);
   skip.insert(APIPermission::kFullscreen);
   skip.insert(APIPermission::kIdle);
@@ -717,6 +718,7 @@
   skip.insert(APIPermission::kDevtools);
 
   // Platform apps.
+  skip.insert(APIPermission::kBluetooth);
   skip.insert(APIPermission::kFileSystem);
   skip.insert(APIPermission::kFileSystemRetainFiles);
   skip.insert(APIPermission::kSocket);
diff --git a/chrome/common/extensions/permissions/socket_permission_data.cc b/chrome/common/extensions/permissions/socket_permission_data.cc
index 24e6277..d5ad9ae 100644
--- a/chrome/common/extensions/permissions/socket_permission_data.cc
+++ b/chrome/common/extensions/permissions/socket_permission_data.cc
@@ -31,6 +31,8 @@
 const char kUDPBind[] = "udp-bind";
 const char kUDPSendTo[] = "udp-send-to";
 const char kUDPMulticastMembership[] = "udp-multicast-membership";
+const char kResolveHost[] = "resolve-host";
+const char kResolveProxy[] = "resolve-proxy";
 const int kWildcardPortNumber = 0;
 const int kInvalidPort = -1;
 
@@ -45,6 +47,10 @@
     return SocketPermissionRequest::UDP_SEND_TO;
   if (s == kUDPMulticastMembership)
     return SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP;
+  if (s == kResolveHost)
+    return SocketPermissionRequest::RESOLVE_HOST;
+  if (s == kResolveProxy)
+    return SocketPermissionRequest::RESOLVE_PROXY;
   return SocketPermissionRequest::NONE;
 }
 
@@ -60,6 +66,10 @@
       return kUDPSendTo;
     case SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP:
       return kUDPMulticastMembership;
+    case SocketPermissionRequest::RESOLVE_HOST:
+      return kResolveHost;
+    case SocketPermissionRequest::RESOLVE_PROXY:
+      return kResolveProxy;
     default:
       return kInvalid;
   }
@@ -192,6 +202,7 @@
   return match_subdomains_;
 }
 
+// TODO(ikarienator): Rewrite this method to support IPv6.
 bool SocketPermissionData::Parse(const std::string& permission) {
   do {
     pattern_.host.clear();
@@ -212,9 +223,12 @@
     if (tokens.size() == 1)
       return true;
 
-    // Multicast membership permission string does not include an address.
-    if (pattern_.type == SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP)
-      return false;
+    // Multicast membership, resolve proxy and resolve host permission strings
+    // do not carry an address.
+    if (pattern_.type == SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP ||
+        pattern_.type == SocketPermissionRequest::RESOLVE_PROXY ||
+        pattern_.type == SocketPermissionRequest::RESOLVE_HOST)
+      break;
 
     pattern_.host = tokens[1];
     if (!pattern_.host.empty()) {
@@ -259,7 +273,9 @@
   spec_.reserve(64);
   spec_.append(TypeToString(pattern_.type));
 
-  if (pattern_.type == SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP)
+  if (pattern_.type == SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP ||
+      pattern_.type == SocketPermissionRequest::RESOLVE_PROXY ||
+      pattern_.type == SocketPermissionRequest::RESOLVE_HOST)
     return spec_;
 
   if (match_subdomains_) {
diff --git a/chrome/common/extensions/permissions/socket_permission_unittest.cc b/chrome/common/extensions/permissions/socket_permission_unittest.cc
index 1fe5635..51a36c8 100644
--- a/chrome/common/extensions/permissions/socket_permission_unittest.cc
+++ b/chrome/common/extensions/permissions/socket_permission_unittest.cc
@@ -59,11 +59,18 @@
   EXPECT_FALSE(data.ParseForTest("tcp-connect:*.exmaple.com:99 "));
   EXPECT_FALSE(data.ParseForTest("tcp-connect:\t*.exmaple.com:99"));
   EXPECT_FALSE(data.ParseForTest("tcp-connect:\n*.exmaple.com:99"));
+  EXPECT_FALSE(data.ParseForTest("resolve-host:exmaple.com:99"));
+  EXPECT_FALSE(data.ParseForTest("resolve-host:127.0.0.1"));
+  EXPECT_FALSE(data.ParseForTest("resolve-host:"));
+  EXPECT_FALSE(data.ParseForTest("resolve-proxy:exmaple.com:99"));
+  EXPECT_FALSE(data.ParseForTest("resolve-proxy:exmaple.com"));
 
   ParseTest("tcp-connect", "tcp-connect:*:*");
   ParseTest("tcp-listen", "tcp-listen:*:*");
   ParseTest("udp-bind", "udp-bind:*:*");
   ParseTest("udp-send-to", "udp-send-to:*:*");
+  ParseTest("resolve-host", "resolve-host");
+  ParseTest("resolve-proxy", "resolve-proxy");
 
   ParseTest("tcp-connect:", "tcp-connect:*:*");
   ParseTest("tcp-listen:", "tcp-listen:*:*");
@@ -122,98 +129,126 @@
 
   CHECK(data.ParseForTest("tcp-connect"));
   param.reset(new SocketPermission::CheckParam(
-        SocketPermissionRequest::TCP_CONNECT, "www.example.com", 80));
+      SocketPermissionRequest::TCP_CONNECT, "www.example.com", 80));
   EXPECT_TRUE(data.Check(param.get()));
   param.reset(new SocketPermission::CheckParam(
-        SocketPermissionRequest::UDP_SEND_TO, "www.example.com", 80));
+      SocketPermissionRequest::UDP_SEND_TO, "www.example.com", 80));
   EXPECT_FALSE(data.Check(param.get()));
 
   CHECK(data.ParseForTest("udp-send-to::8800"));
   param.reset(new SocketPermission::CheckParam(
-        SocketPermissionRequest::UDP_SEND_TO, "www.example.com", 8800));
+      SocketPermissionRequest::UDP_SEND_TO, "www.example.com", 8800));
   EXPECT_TRUE(data.Check(param.get()));
   param.reset(new SocketPermission::CheckParam(
-        SocketPermissionRequest::UDP_SEND_TO, "smtp.example.com", 8800));
+      SocketPermissionRequest::UDP_SEND_TO, "smtp.example.com", 8800));
   EXPECT_TRUE(data.Check(param.get()));
   param.reset(new SocketPermission::CheckParam(
-        SocketPermissionRequest::TCP_CONNECT, "www.example.com", 80));
+      SocketPermissionRequest::TCP_CONNECT, "www.example.com", 80));
   EXPECT_FALSE(data.Check(param.get()));
 
   CHECK(data.ParseForTest("udp-send-to:*.example.com:8800"));
   param.reset(new SocketPermission::CheckParam(
-        SocketPermissionRequest::UDP_SEND_TO, "www.example.com", 8800));
+      SocketPermissionRequest::UDP_SEND_TO, "www.example.com", 8800));
   EXPECT_TRUE(data.Check(param.get()));
   param.reset(new SocketPermission::CheckParam(
-        SocketPermissionRequest::UDP_SEND_TO, "smtp.example.com", 8800));
+      SocketPermissionRequest::UDP_SEND_TO, "smtp.example.com", 8800));
   EXPECT_TRUE(data.Check(param.get()));
   param.reset(new SocketPermission::CheckParam(
-        SocketPermissionRequest::UDP_SEND_TO, "SMTP.example.com", 8800));
+      SocketPermissionRequest::UDP_SEND_TO, "SMTP.example.com", 8800));
   EXPECT_TRUE(data.Check(param.get()));
   param.reset(new SocketPermission::CheckParam(
-        SocketPermissionRequest::TCP_CONNECT, "www.example.com", 80));
+      SocketPermissionRequest::TCP_CONNECT, "www.example.com", 80));
   EXPECT_FALSE(data.Check(param.get()));
   param.reset(new SocketPermission::CheckParam(
-        SocketPermissionRequest::UDP_SEND_TO, "www.google.com", 8800));
+      SocketPermissionRequest::UDP_SEND_TO, "www.google.com", 8800));
   EXPECT_FALSE(data.Check(param.get()));
   param.reset(new SocketPermission::CheckParam(
-        SocketPermissionRequest::UDP_SEND_TO, "wwwexample.com", 8800));
+      SocketPermissionRequest::UDP_SEND_TO, "wwwexample.com", 8800));
   EXPECT_FALSE(data.Check(param.get()));
 
   CHECK(data.ParseForTest("udp-send-to:*.ExAmPlE.cOm:8800"));
   param.reset(new SocketPermission::CheckParam(
-        SocketPermissionRequest::UDP_SEND_TO, "www.example.com", 8800));
+      SocketPermissionRequest::UDP_SEND_TO, "www.example.com", 8800));
   EXPECT_TRUE(data.Check(param.get()));
   param.reset(new SocketPermission::CheckParam(
-        SocketPermissionRequest::UDP_SEND_TO, "smtp.example.com", 8800));
+      SocketPermissionRequest::UDP_SEND_TO, "smtp.example.com", 8800));
   EXPECT_TRUE(data.Check(param.get()));
   param.reset(new SocketPermission::CheckParam(
-        SocketPermissionRequest::UDP_SEND_TO, "SMTP.example.com", 8800));
+      SocketPermissionRequest::UDP_SEND_TO, "SMTP.example.com", 8800));
   EXPECT_TRUE(data.Check(param.get()));
   param.reset(new SocketPermission::CheckParam(
-        SocketPermissionRequest::TCP_CONNECT, "www.example.com", 80));
+      SocketPermissionRequest::TCP_CONNECT, "www.example.com", 80));
   EXPECT_FALSE(data.Check(param.get()));
   param.reset(new SocketPermission::CheckParam(
-        SocketPermissionRequest::UDP_SEND_TO, "www.google.com", 8800));
+      SocketPermissionRequest::UDP_SEND_TO, "www.google.com", 8800));
   EXPECT_FALSE(data.Check(param.get()));
 
   ASSERT_TRUE(data.ParseForTest("udp-bind::8800"));
   param.reset(new SocketPermission::CheckParam(
-        SocketPermissionRequest::UDP_BIND, "127.0.0.1", 8800));
+      SocketPermissionRequest::UDP_BIND, "127.0.0.1", 8800));
   EXPECT_TRUE(data.Check(param.get()));
   param.reset(new SocketPermission::CheckParam(
-        SocketPermissionRequest::UDP_BIND, "127.0.0.1", 8888));
+      SocketPermissionRequest::UDP_BIND, "127.0.0.1", 8888));
   EXPECT_FALSE(data.Check(param.get()));
   param.reset(new SocketPermission::CheckParam(
-        SocketPermissionRequest::TCP_CONNECT, "www.example.com", 80));
+      SocketPermissionRequest::TCP_CONNECT, "www.example.com", 80));
   EXPECT_FALSE(data.Check(param.get()));
   param.reset(new SocketPermission::CheckParam(
-        SocketPermissionRequest::UDP_SEND_TO, "www.google.com", 8800));
+      SocketPermissionRequest::UDP_SEND_TO, "www.google.com", 8800));
   EXPECT_FALSE(data.Check(param.get()));
 
   // Do not wildcard part of ip address.
   ASSERT_TRUE(data.ParseForTest("tcp-connect:*.168.0.1:8800"));
   param.reset(new SocketPermission::CheckParam(
-        SocketPermissionRequest::TCP_CONNECT, "192.168.0.1", 8800));
+      SocketPermissionRequest::TCP_CONNECT, "192.168.0.1", 8800));
   EXPECT_FALSE(data.Check(param.get()));
 
   ASSERT_FALSE(data.ParseForTest("udp-multicast-membership:*"));
   ASSERT_FALSE(data.ParseForTest("udp-multicast-membership:*:*"));
   ASSERT_TRUE(data.ParseForTest("udp-multicast-membership"));
   param.reset(new SocketPermission::CheckParam(
-        SocketPermissionRequest::UDP_BIND, "127.0.0.1", 8800));
+      SocketPermissionRequest::UDP_BIND, "127.0.0.1", 8800));
   EXPECT_FALSE(data.Check(param.get()));
   param.reset(new SocketPermission::CheckParam(
-        SocketPermissionRequest::UDP_BIND, "127.0.0.1", 8888));
+      SocketPermissionRequest::UDP_BIND, "127.0.0.1", 8888));
   EXPECT_FALSE(data.Check(param.get()));
   param.reset(new SocketPermission::CheckParam(
-        SocketPermissionRequest::TCP_CONNECT, "www.example.com", 80));
+      SocketPermissionRequest::TCP_CONNECT, "www.example.com", 80));
   EXPECT_FALSE(data.Check(param.get()));
   param.reset(new SocketPermission::CheckParam(
-        SocketPermissionRequest::UDP_SEND_TO, "www.google.com", 8800));
+      SocketPermissionRequest::UDP_SEND_TO, "www.google.com", 8800));
   EXPECT_FALSE(data.Check(param.get()));
   param.reset(new SocketPermission::CheckParam(
-        SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP, "127.0.0.1", 35));
+      SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP, "127.0.0.1", 35));
   EXPECT_TRUE(data.Check(param.get()));
+
+  ASSERT_TRUE(data.ParseForTest("resolve-host"));
+  param.reset(new SocketPermission::CheckParam(
+      SocketPermissionRequest::RESOLVE_HOST, "www.example.com", 80));
+  EXPECT_TRUE(data.Check(param.get()));
+  param.reset(new SocketPermission::CheckParam(
+      SocketPermissionRequest::RESOLVE_HOST, "www.example.com", 8080));
+  EXPECT_TRUE(data.Check(param.get()));
+  param.reset(new SocketPermission::CheckParam(
+      SocketPermissionRequest::UDP_BIND, "127.0.0.1", 8800));
+  EXPECT_FALSE(data.Check(param.get()));
+  param.reset(new SocketPermission::CheckParam(
+      SocketPermissionRequest::TCP_CONNECT, "127.0.0.1", 8800));
+  EXPECT_FALSE(data.Check(param.get()));
+
+  ASSERT_TRUE(data.ParseForTest("resolve-proxy"));
+  param.reset(new SocketPermission::CheckParam(
+      SocketPermissionRequest::RESOLVE_PROXY, "www.example.com", 80));
+  EXPECT_TRUE(data.Check(param.get()));
+  param.reset(new SocketPermission::CheckParam(
+      SocketPermissionRequest::RESOLVE_PROXY, "www.example.com", 8080));
+  EXPECT_TRUE(data.Check(param.get()));
+  param.reset(new SocketPermission::CheckParam(
+      SocketPermissionRequest::UDP_BIND, "127.0.0.1", 8800));
+  EXPECT_FALSE(data.Check(param.get()));
+  param.reset(new SocketPermission::CheckParam(
+      SocketPermissionRequest::TCP_CONNECT, "127.0.0.1", 8800));
+  EXPECT_FALSE(data.Check(param.get()));
 }
 
 TEST(SocketPermissionTest, IPC) {
@@ -284,3 +319,4 @@
 }  // namespace
 
 }  // namespace extensions
+
diff --git a/chrome/common/extensions/sync_helper.cc b/chrome/common/extensions/sync_helper.cc
index 3cffcca..c8b8dc4 100644
--- a/chrome/common/extensions/sync_helper.cc
+++ b/chrome/common/extensions/sync_helper.cc
@@ -41,8 +41,10 @@
   //
   // TODO(akalin): Relax this restriction once we've put in UI to
   // approve synced extensions.
-  if (PluginInfo::HasPlugins(extension))
+  if (PluginInfo::HasPlugins(extension) ||
+      extension->HasAPIPermission(APIPermission::kPlugin)) {
     return SYNC_TYPE_NONE;
+  }
 
   switch (extension->GetType()) {
     case Manifest::TYPE_EXTENSION:
@@ -83,6 +85,8 @@
                       !extension->was_installed_by_default());
   // Sync the chrome web store to maintain its position on the new tab page.
   is_syncable |= (extension->id() == extension_misc::kWebStoreAppId);
+  // Sync the chrome component app to maintain its position on the app list.
+  is_syncable |= (extension->id() == extension_misc::kChromeAppId);
   return is_syncable;
 }
 
diff --git a/chrome/common/extensions/sync_type_unittest.cc b/chrome/common/extensions/sync_type_unittest.cc
index 73d33d1..c6f5958 100644
--- a/chrome/common/extensions/sync_type_unittest.cc
+++ b/chrome/common/extensions/sync_type_unittest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/files/file_path.h"
+#include "chrome/common/extensions/api/plugins/plugins_handler.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_manifest_constants.h"
 #include "chrome/common/extensions/manifest.h"
@@ -24,14 +25,15 @@
     THEME
   };
 
-  static scoped_refptr<Extension> MakeSyncTestExtension(
+  static scoped_refptr<Extension> MakeSyncTestExtensionWithPluginPermission(
       SyncTestExtensionType type,
       const GURL& update_url,
       const GURL& launch_url,
       Manifest::Location location,
       int num_plugins,
       const base::FilePath& extension_path,
-      int creation_flags) {
+      int creation_flags,
+      bool has_plugin_permission) {
     base::DictionaryValue source;
     source.SetString(keys::kName, "PossiblySyncableExtension");
     source.SetString(keys::kVersion, "0.0.0.0");
@@ -55,6 +57,11 @@
       }
       source.Set(keys::kPlugins, plugins);
     }
+    if (has_plugin_permission) {
+      ListValue* plugins = new ListValue();
+      plugins->Set(0, new StringValue("plugin"));
+      source.Set(keys::kPermissions, plugins);
+    }
 
     std::string error;
     scoped_refptr<Extension> extension = Extension::Create(
@@ -64,6 +71,19 @@
     return extension;
   }
 
+  static scoped_refptr<Extension> MakeSyncTestExtension(
+      SyncTestExtensionType type,
+      const GURL& update_url,
+      const GURL& launch_url,
+      Manifest::Location location,
+      int num_plugins,
+      const base::FilePath& extension_path,
+      int creation_flags) {
+    return MakeSyncTestExtensionWithPluginPermission(
+        type, update_url, launch_url, location, num_plugins, extension_path,
+        creation_flags, false);
+  }
+
   static const char kValidUpdateUrl1[];
   static const char kValidUpdateUrl2[];
 };
@@ -238,6 +258,16 @@
   if (extension.get())
     EXPECT_FALSE(sync_helper::IsSyncableExtension(extension.get()));
 }
+
+TEST_F(ExtensionSyncTypeTest, ExtensionWithPluginPermission) {
+  scoped_refptr<Extension> extension(
+      MakeSyncTestExtensionWithPluginPermission(EXTENSION, GURL(), GURL(),
+                                                Manifest::INTERNAL,
+                                                0, base::FilePath(),
+                                                Extension::NO_FLAGS, true));
+  if (extension.get())
+    EXPECT_FALSE(sync_helper::IsSyncableExtension(extension.get()));
+}
 #endif // !defined(OS_CHROMEOS)
 
 }  // namespace extensions
diff --git a/chrome/common/extensions/unpacker.cc b/chrome/common/extensions/unpacker.cc
index 7a958df..336a7d5 100644
--- a/chrome/common/extensions/unpacker.cc
+++ b/chrome/common/extensions/unpacker.cc
@@ -23,6 +23,7 @@
 #include "chrome/common/extensions/extension_manifest_constants.h"
 #include "chrome/common/extensions/manifest.h"
 #include "chrome/common/url_constants.h"
+#include "content/public/child/image_decoder_utils.h"
 #include "content/public/common/common_param_traits.h"
 #include "extensions/common/constants.h"
 #include "grit/generated_resources.h"
@@ -31,7 +32,7 @@
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/zlib/google/zip.h"
 #include "ui/base/l10n/l10n_util.h"
-#include "webkit/glue/image_decoder.h"
+#include "ui/gfx/size.h"
 
 namespace errors = extension_manifest_errors;
 namespace keys = extension_manifest_keys;
@@ -53,8 +54,9 @@
   // Decode the image using WebKit's image decoder.
   const unsigned char* data =
       reinterpret_cast<const unsigned char*>(file_contents.data());
-  webkit_glue::ImageDecoder decoder;
-  SkBitmap bitmap = decoder.Decode(data, file_contents.length());
+  SkBitmap bitmap = content::DecodeImage(data,
+                                         gfx::Size(),
+                                         file_contents.length());
   Sk64 bitmap_size = bitmap.getSize64();
   if (!bitmap_size.is32() || bitmap_size.get32() > kMaxImageCanvas)
     return SkBitmap();
diff --git a/chrome/common/extensions/update_manifest.cc b/chrome/common/extensions/update_manifest.cc
index feb6f70..0ed653f 100644
--- a/chrome/common/extensions/update_manifest.cc
+++ b/chrome/common/extensions/update_manifest.cc
@@ -19,7 +19,9 @@
 static const char* kExpectedGupdateXmlns =
     "http://www.google.com/update2/response";
 
-UpdateManifest::Result::Result() {}
+UpdateManifest::Result::Result()
+    : size(0),
+      diff_size(0) {}
 
 UpdateManifest::Result::~Result() {}
 
@@ -154,7 +156,7 @@
   result->crx_url = GURL(GetAttribute(updatecheck, "codebase"));
   if (!result->crx_url.is_valid()) {
     *error_detail = "Invalid codebase url: '";
-    *error_detail += GetAttribute(updatecheck, "codebase");
+    *error_detail += result->crx_url.possibly_invalid_spec();
     *error_detail += "'.";
     return false;
   }
@@ -189,6 +191,23 @@
   // sha256 hash of the package in hex format.
   result->package_hash = GetAttribute(updatecheck, "hash");
 
+  int size = 0;
+  if (base::StringToInt(GetAttribute(updatecheck, "size"), &size)) {
+    result->size = size;
+  }
+
+  // package_fingerprint is optional. It identifies the package, preferably
+  // with a modified sha256 hash of the package in hex format.
+  result->package_fingerprint = GetAttribute(updatecheck, "fp");
+
+  // Differential update information is optional.
+  result->diff_crx_url = GURL(GetAttribute(updatecheck, "codebasediff"));
+  result->diff_package_hash = GetAttribute(updatecheck, "hashdiff");
+  int sizediff = 0;
+  if (base::StringToInt(GetAttribute(updatecheck, "sizediff"), &sizediff)) {
+    result->diff_size = sizediff;
+  }
+
   return true;
 }
 
diff --git a/chrome/common/extensions/update_manifest.h b/chrome/common/extensions/update_manifest.h
index d847743..bff70b4 100644
--- a/chrome/common/extensions/update_manifest.h
+++ b/chrome/common/extensions/update_manifest.h
@@ -15,13 +15,16 @@
 
   // An update manifest looks like this:
   //
-  // <?xml version='1.0' encoding='UTF-8'?>
-  // <gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>
-  //  <daystart elapsed_seconds='300' />
-  //  <app appid='12345'>
-  //   <updatecheck codebase='http://example.com/extension_1.2.3.4.crx'
-  //                version='1.2.3.4' prodversionmin='2.0.143.0'
-  //                hash="12345"/>
+  // <?xml version="1.0" encoding="UTF-8"?>
+  // <gupdate xmlns="http://www.google.com/update2/response" protocol="2.0">
+  //  <daystart elapsed_seconds="300" />
+  //  <app appid="12345" status="ok">
+  //   <updatecheck codebase="http://example.com/extension_1.2.3.4.crx"
+  //                hash="12345" size="9854" status="ok" version="1.2.3.4"
+  //                prodversionmin="2.0.143.0"
+  //                codebasediff="http://example.com/diff_1.2.3.4.crx"
+  //                hashdiff="123" sizediff="101"
+  //                fp="1.123" />
   //  </app>
   // </gupdate>
   //
@@ -33,6 +36,9 @@
   // fetch the updated crx file, and the "prodversionmin" attribute refers to
   // the minimum version of the chrome browser that the update applies to.
 
+  // The diff data members correspond to the differential update package, if
+  // a differential update is specified in the response.
+
   // The result of parsing one <app> tag in an xml update check manifest.
   struct Result {
     Result();
@@ -41,8 +47,17 @@
     std::string extension_id;
     std::string version;
     std::string browser_min_version;
-    std::string package_hash;
+
+    // Attributes for the full update.
     GURL crx_url;
+    std::string package_hash;
+    int size;
+    std::string package_fingerprint;
+
+    // Attributes for the differential update.
+    GURL diff_crx_url;
+    std::string diff_package_hash;
+    int diff_size;
   };
 
   static const int kNoDaystart = -1;
diff --git a/chrome/common/extensions/user_script.h b/chrome/common/extensions/user_script.h
index 1b1947b..07f28a0 100644
--- a/chrome/common/extensions/user_script.h
+++ b/chrome/common/extensions/user_script.h
@@ -37,7 +37,7 @@
   // Locations that user scripts can be run inside the document.
   enum RunLocation {
     UNDEFINED,
-    DOCUMENT_START,  // After the documentElemnet is created, but before
+    DOCUMENT_START,  // After the documentElement is created, but before
                      // anything else happens.
     DOCUMENT_END,  // After the entire document is parsed. Same as
                    // DOMContentLoaded.
diff --git a/chrome/common/importer/imported_bookmark_entry.cc b/chrome/common/importer/imported_bookmark_entry.cc
new file mode 100644
index 0000000..faa932c
--- /dev/null
+++ b/chrome/common/importer/imported_bookmark_entry.cc
@@ -0,0 +1,21 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/common/importer/imported_bookmark_entry.h"
+
+ImportedBookmarkEntry::ImportedBookmarkEntry()
+    : in_toolbar(false),
+      is_folder(false) {}
+
+ImportedBookmarkEntry::~ImportedBookmarkEntry() {}
+
+bool ImportedBookmarkEntry::operator==(
+    const ImportedBookmarkEntry& other) const {
+  return (in_toolbar == other.in_toolbar &&
+          is_folder == other.is_folder &&
+          url == other.url &&
+          path == other.path &&
+          title == other.title &&
+          creation_time == other.creation_time);
+}
diff --git a/chrome/common/importer/imported_bookmark_entry.h b/chrome/common/importer/imported_bookmark_entry.h
new file mode 100644
index 0000000..8f6f1ca
--- /dev/null
+++ b/chrome/common/importer/imported_bookmark_entry.h
@@ -0,0 +1,28 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_COMMON_IMPORTER_IMPORTED_BOOKMARK_ENTRY_H_
+#define CHROME_COMMON_IMPORTER_IMPORTED_BOOKMARK_ENTRY_H_
+
+#include <vector>
+
+#include "base/strings/string16.h"
+#include "base/time/time.h"
+#include "url/gurl.h"
+
+struct ImportedBookmarkEntry {
+  ImportedBookmarkEntry();
+  ~ImportedBookmarkEntry();
+
+  bool operator==(const ImportedBookmarkEntry& other) const;
+
+  bool in_toolbar;
+  bool is_folder;
+  GURL url;
+  std::vector<base::string16> path;
+  base::string16 title;
+  base::Time creation_time;
+};
+
+#endif  // CHROME_COMMON_IMPORTER_IMPORTED_BOOKMARK_ENTRY_H_
diff --git a/chrome/common/importer/imported_favicon_usage.cc b/chrome/common/importer/imported_favicon_usage.cc
new file mode 100644
index 0000000..96306c3
--- /dev/null
+++ b/chrome/common/importer/imported_favicon_usage.cc
@@ -0,0 +1,11 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/common/importer/imported_favicon_usage.h"
+
+ImportedFaviconUsage::ImportedFaviconUsage() {
+}
+
+ImportedFaviconUsage::~ImportedFaviconUsage() {
+}
diff --git a/chrome/common/importer/imported_favicon_usage.h b/chrome/common/importer/imported_favicon_usage.h
new file mode 100644
index 0000000..8dc9389
--- /dev/null
+++ b/chrome/common/importer/imported_favicon_usage.h
@@ -0,0 +1,28 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_COMMON_IMPORTER_IMPORTED_FAVICON_USAGE_H_
+#define CHROME_COMMON_IMPORTER_IMPORTED_FAVICON_USAGE_H_
+
+#include <set>
+#include <vector>
+
+#include "url/gurl.h"
+
+// Used to correlate favicons to imported bookmarks.
+struct ImportedFaviconUsage {
+  ImportedFaviconUsage();
+  ~ImportedFaviconUsage();
+
+  // The URL of the favicon.
+  GURL favicon_url;
+
+  // The raw png-encoded data.
+  std::vector<unsigned char> png_data;
+
+  // The list of URLs using this favicon.
+  std::set<GURL> urls;
+};
+
+#endif  // CHROME_COMMON_IMPORTER_IMPORTED_FAVICON_USAGE_H_
diff --git a/chrome/common/importer/importer_data_types.cc b/chrome/common/importer/importer_data_types.cc
new file mode 100644
index 0000000..392b13d
--- /dev/null
+++ b/chrome/common/importer/importer_data_types.cc
@@ -0,0 +1,17 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/common/importer/importer_data_types.h"
+
+namespace importer {
+
+SourceProfile::SourceProfile()
+    : importer_type(TYPE_UNKNOWN),
+      services_supported(0) {
+}
+
+SourceProfile::~SourceProfile() {
+}
+
+}  // namespace importer
diff --git a/chrome/common/importer/importer_data_types.h b/chrome/common/importer/importer_data_types.h
new file mode 100644
index 0000000..e4c027e
--- /dev/null
+++ b/chrome/common/importer/importer_data_types.h
@@ -0,0 +1,56 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_COMMON_IMPORTER_IMPORTER_DATA_TYPES_H_
+#define CHROME_COMMON_IMPORTER_IMPORTER_DATA_TYPES_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/files/file_path.h"
+#include "base/memory/ref_counted.h"
+#include "base/strings/string16.h"
+#include "chrome/common/importer/importer_type.h"
+#include "url/gurl.h"
+
+// Types needed for importing data from other browsers and the Google Toolbar.
+namespace importer {
+
+// An enumeration of the type of data that can be imported.
+enum ImportItem {
+  NONE           = 0,
+  HISTORY        = 1 << 0,
+  FAVORITES      = 1 << 1,
+  COOKIES        = 1 << 2,  // Not supported yet.
+  PASSWORDS      = 1 << 3,
+  SEARCH_ENGINES = 1 << 4,
+  HOME_PAGE      = 1 << 5,
+  ALL            = (1 << 6) - 1  // All the bits should be 1, hence the -1.
+};
+
+// Information about a profile needed by an importer to do import work.
+struct SourceProfile {
+  SourceProfile();
+  ~SourceProfile();
+
+  string16 importer_name;
+  ImporterType importer_type;
+  base::FilePath source_path;
+  base::FilePath app_path;
+  uint16 services_supported;  // Bitmask of ImportItem.
+  // The application locale. Stored because we can only access it from the UI
+  // thread on the browser process. This is only used by the Firefox importer.
+  std::string locale;
+};
+
+// Contains information needed for importing bookmarks/search engine urls, etc.
+struct URLKeywordInfo {
+  GURL url;
+  string16 keyword;
+  string16 display_name;
+};
+
+}  // namespace importer
+
+#endif  // CHROME_COMMON_IMPORTER_IMPORTER_DATA_TYPES_H_
diff --git a/chrome/common/importer/importer_type.h b/chrome/common/importer/importer_type.h
new file mode 100644
index 0000000..7b301af
--- /dev/null
+++ b/chrome/common/importer/importer_type.h
@@ -0,0 +1,33 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_COMMON_IMPORTER_IMPORTER_TYPE_H_
+#define CHROME_COMMON_IMPORTER_IMPORTER_TYPE_H_
+
+#include "build/build_config.h"
+
+namespace importer {
+
+// An enumeration of the type of importers that we support to import
+// settings and data from (browsers, google toolbar and a bookmarks html file).
+// NOTE: Numbers added so that data can be reliably cast to ints and passed
+// across IPC.
+enum ImporterType {
+  TYPE_UNKNOWN         = -1,
+#if defined(OS_WIN)
+  TYPE_IE              = 0,
+#endif
+  // Value 1 was the (now deleted) Firefox 2 profile importer.
+  TYPE_FIREFOX3        = 2,
+#if defined(OS_MACOSX)
+  TYPE_SAFARI          = 3,
+#endif
+  // Value 4 was the (now deleted) Google Toolbar importer.
+  TYPE_BOOKMARKS_FILE  = 5  // Identifies a 'bookmarks.html' file.
+};
+
+}  // namespace importer
+
+
+#endif  // CHROME_COMMON_IMPORTER_IMPORTER_TYPE_H_
diff --git a/chrome/common/importer/importer_url_row.cc b/chrome/common/importer/importer_url_row.cc
new file mode 100644
index 0000000..429bfc1
--- /dev/null
+++ b/chrome/common/importer/importer_url_row.cc
@@ -0,0 +1,18 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/common/importer/importer_url_row.h"
+
+ImporterURLRow::ImporterURLRow()
+    : visit_count(0),
+      typed_count(0),
+      hidden(false) {
+}
+
+ImporterURLRow::ImporterURLRow(const GURL& url)
+    : url(url),
+      visit_count(0),
+      typed_count(0),
+      hidden(false) {
+}
diff --git a/chrome/common/importer/importer_url_row.h b/chrome/common/importer/importer_url_row.h
new file mode 100644
index 0000000..857644a
--- /dev/null
+++ b/chrome/common/importer/importer_url_row.h
@@ -0,0 +1,38 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_COMMON_IMPORTER_IMPORTER_URL_ROW_H_
+#define CHROME_COMMON_IMPORTER_IMPORTER_URL_ROW_H_
+
+#include "base/strings/string16.h"
+#include "base/time/time.h"
+#include "url/gurl.h"
+
+// Used as the target for importing history URLs from other browser's profiles
+// in the utility process. Converted to history::URLRow after being passed via
+// IPC to the browser.
+struct ImporterURLRow {
+ public:
+  ImporterURLRow();
+  explicit ImporterURLRow(const GURL& url);
+
+  GURL url;
+  base::string16 title;
+
+  // Total number of times this URL has been visited.
+  int visit_count;
+
+  // Number of times this URL has been manually entered in the URL bar.
+  int typed_count;
+
+  // The date of the last visit of this URL, which saves us from having to
+  // loop up in the visit table for things like autocomplete and expiration.
+  base::Time last_visit;
+
+  // Indicates this entry should now be shown in typical UI or queries, this
+  // is usually for subframes.
+  bool hidden;
+};
+
+#endif  // CHROME_COMMON_IMPORTER_IMPORTER_URL_ROW_H_
diff --git a/chrome/common/importer/profile_import_process_messages.cc b/chrome/common/importer/profile_import_process_messages.cc
new file mode 100644
index 0000000..4a0b9a4
--- /dev/null
+++ b/chrome/common/importer/profile_import_process_messages.cc
@@ -0,0 +1,33 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Get basic type definitions.
+#define IPC_MESSAGE_IMPL
+#include "chrome/common/importer/profile_import_process_messages.h"
+
+// Generate constructors.
+#include "ipc/struct_constructor_macros.h"
+#include "chrome/common/importer/profile_import_process_messages.h"
+
+// Generate destructors.
+#include "ipc/struct_destructor_macros.h"
+#include "chrome/common/importer/profile_import_process_messages.h"
+
+// Generate param traits write methods.
+#include "ipc/param_traits_write_macros.h"
+namespace IPC {
+#include "chrome/common/importer/profile_import_process_messages.h"
+}  // namespace IPC
+
+// Generate param traits read methods.
+#include "ipc/param_traits_read_macros.h"
+namespace IPC {
+#include "chrome/common/importer/profile_import_process_messages.h"
+}  // namespace IPC
+
+// Generate param traits log methods.
+#include "ipc/param_traits_log_macros.h"
+namespace IPC {
+#include "chrome/common/importer/profile_import_process_messages.h"
+}  // namespace IPC
diff --git a/chrome/common/importer/profile_import_process_messages.h b/chrome/common/importer/profile_import_process_messages.h
new file mode 100644
index 0000000..8641f7c
--- /dev/null
+++ b/chrome/common/importer/profile_import_process_messages.h
@@ -0,0 +1,293 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Multiply-included message file, no traditonal include guard.
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/strings/string16.h"
+#include "base/values.h"
+#include "chrome/common/common_param_traits_macros.h"
+#include "chrome/common/importer/imported_bookmark_entry.h"
+#include "chrome/common/importer/imported_favicon_usage.h"
+#include "chrome/common/importer/importer_data_types.h"
+#include "chrome/common/importer/importer_url_row.h"
+#include "content/public/common/common_param_traits.h"
+#include "content/public/common/password_form.h"
+#include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_message_utils.h"
+
+#ifndef CHROME_COMMON_IMPORTER_PROFILE_IMPORT_PROCESS_MESSAGES_H_
+#define CHROME_COMMON_IMPORTER_PROFILE_IMPORT_PROCESS_MESSAGES_H_
+
+namespace IPC {
+
+// Traits for importer::SourceProfile struct to pack/unpack.
+template <>
+struct ParamTraits<importer::SourceProfile> {
+  typedef importer::SourceProfile param_type;
+  static void Write(Message* m, const param_type& p) {
+    WriteParam(m, p.importer_name);
+    WriteParam(m, static_cast<int>(p.importer_type));
+    WriteParam(m, p.source_path);
+    WriteParam(m, p.app_path);
+    WriteParam(m, static_cast<int>(p.services_supported));
+    WriteParam(m, p.locale);
+  }
+  static bool Read(const Message* m, PickleIterator* iter, param_type* p) {
+    if (!ReadParam(m, iter, &p->importer_name))
+      return false;
+
+    int importer_type = 0;
+    if (!ReadParam(m, iter, &importer_type))
+      return false;
+    p->importer_type = static_cast<importer::ImporterType>(importer_type);
+
+    if (!ReadParam(m, iter, &p->source_path) ||
+        !ReadParam(m, iter, &p->app_path)) {
+        return false;
+    }
+
+    int services_supported = 0;
+    if (!ReadParam(m, iter, &services_supported))
+      return false;
+    p->services_supported = static_cast<uint16>(services_supported);
+
+    if (!ReadParam(m, iter, &p->locale))
+      return false;
+
+    return true;
+  }
+  static void Log(const param_type& p, std::string* l) {
+    l->append("(");
+    LogParam(p.importer_name, l);
+    l->append(", ");
+    LogParam(static_cast<int>(p.importer_type), l);
+    l->append(", ");
+    LogParam(p.source_path, l);
+    l->append(", ");
+    LogParam(p.app_path, l);
+    l->append(", ");
+    LogParam(static_cast<int>(p.services_supported), l);
+    l->append(", ");
+    LogParam(p.locale, l);
+    l->append(")");
+  }
+};  // ParamTraits<importer::SourceProfile>
+
+// Traits for ImporterURLRow to pack/unpack.
+template <>
+struct ParamTraits<ImporterURLRow> {
+  typedef ImporterURLRow param_type;
+  static void Write(Message* m, const param_type& p) {
+    WriteParam(m, p.url);
+    WriteParam(m, p.title);
+    WriteParam(m, p.visit_count);
+    WriteParam(m, p.typed_count);
+    WriteParam(m, p.last_visit);
+    WriteParam(m, p.hidden);
+  }
+  static bool Read(const Message* m, PickleIterator* iter, param_type* p) {
+    GURL url;
+    string16 title;
+    int visit_count, typed_count;
+    base::Time last_visit;
+    bool hidden;
+    if (!ReadParam(m, iter, &url) ||
+        !ReadParam(m, iter, &title) ||
+        !ReadParam(m, iter, &visit_count) ||
+        !ReadParam(m, iter, &typed_count) ||
+        !ReadParam(m, iter, &last_visit) ||
+        !ReadParam(m, iter, &hidden))
+      return false;
+    *p = ImporterURLRow(url);
+    p->title = title;
+    p->visit_count = visit_count;
+    p->typed_count = typed_count;
+    p->last_visit = last_visit;
+    p->hidden = hidden;
+    return true;
+  }
+  static void Log(const param_type& p, std::string* l) {
+    l->append("(");
+    LogParam(p.url, l);
+    l->append(", ");
+    LogParam(p.title, l);
+    l->append(", ");
+    LogParam(p.visit_count, l);
+    l->append(", ");
+    LogParam(p.typed_count, l);
+    l->append(", ");
+    LogParam(p.last_visit, l);
+    l->append(", ");
+    LogParam(p.hidden, l);
+    l->append(")");
+  }
+};  // ParamTraits<ImporterURLRow>
+
+// Traits for ImportedBookmarkEntry to pack/unpack.
+template <>
+struct ParamTraits<ImportedBookmarkEntry> {
+  typedef ImportedBookmarkEntry param_type;
+  static void Write(Message* m, const param_type& p) {
+    WriteParam(m, p.in_toolbar);
+    WriteParam(m, p.is_folder);
+    WriteParam(m, p.url);
+    WriteParam(m, p.path);
+    WriteParam(m, p.title);
+    WriteParam(m, p.creation_time);
+  }
+  static bool Read(const Message* m, PickleIterator* iter, param_type* p) {
+    return
+        (ReadParam(m, iter, &p->in_toolbar)) &&
+        (ReadParam(m, iter, &p->is_folder)) &&
+        (ReadParam(m, iter, &p->url)) &&
+        (ReadParam(m, iter, &p->path)) &&
+        (ReadParam(m, iter, &p->title)) &&
+        (ReadParam(m, iter, &p->creation_time));
+  }
+  static void Log(const param_type& p, std::string* l) {
+    l->append("(");
+    LogParam(p.in_toolbar, l);
+    l->append(", ");
+    LogParam(p.is_folder, l);
+    l->append(", ");
+    LogParam(p.url, l);
+    l->append(", ");
+    LogParam(p.path, l);
+    l->append(", ");
+    LogParam(p.title, l);
+    l->append(", ");
+    LogParam(p.creation_time, l);
+    l->append(")");
+  }
+};  // ParamTraits<ImportedBookmarkEntry>
+
+// Traits for ImportedFaviconUsage.
+template <>
+struct ParamTraits<ImportedFaviconUsage> {
+  typedef ImportedFaviconUsage param_type;
+  static void Write(Message* m, const param_type& p) {
+    WriteParam(m, p.favicon_url);
+    WriteParam(m, p.png_data);
+    WriteParam(m, p.urls);
+  }
+  static bool Read(const Message* m, PickleIterator* iter, param_type* p) {
+    return
+        ReadParam(m, iter, &p->favicon_url) &&
+        ReadParam(m, iter, &p->png_data) &&
+        ReadParam(m, iter, &p->urls);
+  }
+  static void Log(const param_type& p, std::string* l) {
+    l->append("(");
+    LogParam(p.favicon_url, l);
+    l->append(", ");
+    LogParam(p.png_data, l);
+    l->append(", ");
+    LogParam(p.urls, l);
+    l->append(")");
+  }
+};  // ParamTraits<ImportedFaviconUsage>
+
+// Traits for importer::URLKeywordInfo
+template <>
+struct ParamTraits<importer::URLKeywordInfo> {
+  typedef importer::URLKeywordInfo param_type;
+  static void Write(Message* m, const param_type& p) {
+    WriteParam(m, p.url);
+    WriteParam(m, p.keyword);
+    WriteParam(m, p.display_name);
+  }
+
+  static bool Read(const Message* m, PickleIterator* iter, param_type* p) {
+    return
+        ReadParam(m, iter, &p->url) &&
+        ReadParam(m, iter, &p->keyword) &&
+        ReadParam(m, iter, &p->display_name);
+  }
+
+  static void Log(const param_type& p, std::string* l) {
+    l->append("(");
+    LogParam(p.url, l);
+    l->append(", ");
+    LogParam(p.keyword, l);
+    l->append(", ");
+    LogParam(p.display_name, l);
+    l->append(")");
+  }
+};  // ParamTraits<importer::URLKeywordInfo>
+
+}  // namespace IPC
+
+#endif  // CHROME_COMMON_IMPORTER_PROFILE_IMPORT_PROCESS_MESSAGES_H_
+
+#define IPC_MESSAGE_START ProfileImportMsgStart
+
+//-----------------------------------------------------------------------------
+// ProfileImportProcess messages
+// These are messages sent from the browser to the profile import process.
+IPC_MESSAGE_CONTROL3(ProfileImportProcessMsg_StartImport,
+                     importer::SourceProfile,
+                     int                     /* Bitmask of items to import. */,
+                     DictionaryValue         /* Localized strings. */)
+
+IPC_MESSAGE_CONTROL0(ProfileImportProcessMsg_CancelImport)
+
+IPC_MESSAGE_CONTROL1(ProfileImportProcessMsg_ReportImportItemFinished,
+                     int  /* ImportItem */)
+
+//---------------------------------------------------------------------------
+// ProfileImportProcessHost messages
+// These are messages sent from the profile import process to the browser.
+// These messages send information about the status of the import and
+// individual import tasks.
+IPC_MESSAGE_CONTROL0(ProfileImportProcessHostMsg_Import_Started)
+
+IPC_MESSAGE_CONTROL2(ProfileImportProcessHostMsg_Import_Finished,
+                     bool         /* was import successful? */,
+                     std::string  /* error message, if any */)
+
+IPC_MESSAGE_CONTROL1(ProfileImportProcessHostMsg_ImportItem_Started,
+                     int  /* ImportItem */)
+
+IPC_MESSAGE_CONTROL1(ProfileImportProcessHostMsg_ImportItem_Finished,
+                     int  /* ImportItem */)
+
+// These messages send data from the external importer process back to
+// the process host so it can be written to the profile.
+IPC_MESSAGE_CONTROL1(ProfileImportProcessHostMsg_NotifyHistoryImportStart,
+                     int  /* total number of ImporterURLRow items */)
+
+IPC_MESSAGE_CONTROL2(ProfileImportProcessHostMsg_NotifyHistoryImportGroup,
+                     std::vector<ImporterURLRow>,
+                     int  /* the source of URLs as in history::VisitSource.*/
+                          /* To simplify IPC call, pass as an integer */)
+
+IPC_MESSAGE_CONTROL1(ProfileImportProcessHostMsg_NotifyHomePageImportReady,
+                     GURL  /* GURL of home page */)
+
+IPC_MESSAGE_CONTROL2(ProfileImportProcessHostMsg_NotifyBookmarksImportStart,
+                     string16  /* first folder name */,
+                     int       /* total number of bookmarks */)
+
+IPC_MESSAGE_CONTROL1(ProfileImportProcessHostMsg_NotifyBookmarksImportGroup,
+                     std::vector<ImportedBookmarkEntry>)
+
+IPC_MESSAGE_CONTROL1(ProfileImportProcessHostMsg_NotifyFaviconsImportStart,
+                     int  /* total number of favicons */)
+
+IPC_MESSAGE_CONTROL1(ProfileImportProcessHostMsg_NotifyFaviconsImportGroup,
+                     std::vector<ImportedFaviconUsage>)
+
+IPC_MESSAGE_CONTROL1(ProfileImportProcessHostMsg_NotifyPasswordFormReady,
+                     content::PasswordForm)
+
+IPC_MESSAGE_CONTROL2(ProfileImportProcessHostMsg_NotifyKeywordsReady,
+                     std::vector<importer::URLKeywordInfo>, // url_keywords
+                     bool  /* unique on host and path */)
+
+IPC_MESSAGE_CONTROL1(ProfileImportProcessHostMsg_NotifyFirefoxSearchEngData,
+                     std::vector<std::string>) // search_engine_data
+
diff --git a/chrome/common/instant_types.cc b/chrome/common/instant_types.cc
index 1817faa..c8673ac 100644
--- a/chrome/common/instant_types.cc
+++ b/chrome/common/instant_types.cc
@@ -47,3 +47,16 @@
 
 ThemeBackgroundInfo::~ThemeBackgroundInfo() {
 }
+
+bool ThemeBackgroundInfo::operator==(const ThemeBackgroundInfo& rhs) const {
+  return color_r == rhs.color_r &&
+      color_g == rhs.color_g &&
+      color_b == rhs.color_b &&
+      color_a == rhs.color_a &&
+      theme_id == rhs.theme_id &&
+      image_horizontal_alignment == rhs.image_horizontal_alignment &&
+      image_vertical_alignment == rhs.image_vertical_alignment &&
+      image_tiling == rhs.image_tiling &&
+      image_height == rhs.image_height &&
+      has_attribution == rhs.has_attribution;
+}
diff --git a/chrome/common/instant_types.h b/chrome/common/instant_types.h
index 3826075..ed8b2f8 100644
--- a/chrome/common/instant_types.h
+++ b/chrome/common/instant_types.h
@@ -144,6 +144,8 @@
   ThemeBackgroundInfo();
   ~ThemeBackgroundInfo();
 
+  bool operator==(const ThemeBackgroundInfo& rhs) const;
+
   // The theme background color in RGBA format where the R, G, B and A values
   // are between 0 and 255 inclusive and always valid.
   int color_r;
diff --git a/chrome/common/itunes_library.cc b/chrome/common/itunes_library.cc
new file mode 100644
index 0000000..9d7d4df
--- /dev/null
+++ b/chrome/common/itunes_library.cc
@@ -0,0 +1,24 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/common/itunes_library.h"
+
+namespace itunes {
+namespace parser {
+
+Track::Track()
+    : id(0) {
+}
+
+Track::Track(uint64 id, const base::FilePath& location)
+    : id(id),
+      location(location) {
+}
+
+bool Track::operator<(const Track& other) const {
+  return id < other.id;
+}
+
+}  // namespace parser
+}  // namespace itunes
diff --git a/chrome/common/itunes_library.h b/chrome/common/itunes_library.h
new file mode 100644
index 0000000..6173d6b
--- /dev/null
+++ b/chrome/common/itunes_library.h
@@ -0,0 +1,36 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// These data structures can be used to describe the contents of an iTunes
+// library.
+
+#ifndef CHROME_COMMON_ITUNES_LIBRARY_H_
+#define CHROME_COMMON_ITUNES_LIBRARY_H_
+
+#include <map>
+#include <set>
+
+#include "base/files/file_path.h"
+
+namespace itunes {
+namespace parser {
+
+struct Track {
+  Track();
+  Track(uint64 id, const base::FilePath& location);
+  bool operator<(const Track& other) const;
+
+  uint64 id;
+  base::FilePath location;
+};
+
+typedef std::set<Track> Album;
+typedef std::map<std::string /*album name*/, Album> Albums;
+typedef std::map<std::string /*artist name*/, Albums> Library;
+
+}  // namespace parser
+}  // namespace itunes
+
+#endif  // CHROME_COMMON_ITUNES_LIBRARY_H_
+
diff --git a/chrome/common/itunes_xml_utils.cc b/chrome/common/itunes_xml_utils.cc
new file mode 100644
index 0000000..9d555b1
--- /dev/null
+++ b/chrome/common/itunes_xml_utils.cc
@@ -0,0 +1,58 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/common/itunes_xml_utils.h"
+
+#include <string>
+
+#include "base/logging.h"
+#include "third_party/libxml/chromium/libxml_utils.h"
+
+namespace itunes {
+
+bool SkipToNextElement(XmlReader* reader) {
+  if (!reader->SkipToElement()) {
+    // SkipToElement returns false if the current node is an end element,
+    // try to advance to the next element and then try again.
+    if (!reader->Read() || !reader->SkipToElement())
+      return false;
+  }
+  return true;
+}
+
+bool SeekToNodeAtCurrentDepth(XmlReader* reader, const std::string& name) {
+  int depth = reader->Depth();
+  do {
+    if (!SkipToNextElement(reader))
+      return false;
+    DCHECK_EQ(depth, reader->Depth());
+    if (reader->NodeName() == name)
+      return true;
+  } while (reader->Next());
+
+  return false;
+}
+
+bool SeekInDict(XmlReader* reader, const std::string& key) {
+  DCHECK_EQ("dict", reader->NodeName());
+
+  int dict_content_depth = reader->Depth() + 1;
+  // Advance past the dict node and into the body of the dictionary.
+  if (!reader->Read())
+    return false;
+
+  while (reader->Depth() >= dict_content_depth) {
+    if (!SeekToNodeAtCurrentDepth(reader, "key"))
+      return false;
+    std::string found_key;
+    if (!reader->ReadElementContent(&found_key))
+      return false;
+    DCHECK_EQ(dict_content_depth, reader->Depth());
+    if (found_key == key)
+      return true;
+  }
+  return false;
+}
+
+}  // namespace itunes
diff --git a/chrome/common/itunes_xml_utils.h b/chrome/common/itunes_xml_utils.h
new file mode 100644
index 0000000..8bfef57
--- /dev/null
+++ b/chrome/common/itunes_xml_utils.h
@@ -0,0 +1,28 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_COMMON_ITUNES_XML_UTILS_H_
+#define CHROME_COMMON_ITUNES_XML_UTILS_H_
+
+#include <string>
+
+class XmlReader;
+
+namespace itunes {
+
+// Like XmlReader::SkipToElement, but will advance to the next open tag if the
+// cursor is on a close tag.
+bool SkipToNextElement(XmlReader* reader);
+
+// Traverse |reader| looking for a node named |name| at the current depth
+// of |reader|.
+bool SeekToNodeAtCurrentDepth(XmlReader* reader, const std::string& name);
+
+// Search within a "dict" node for |key|. The cursor must be on the starting
+// "dict" node when entering this function.
+bool SeekInDict(XmlReader* reader, const std::string& key);
+
+}  // namespace itunes
+
+#endif  // CHROME_COMMON_ITUNES_XML_UTILS_H_
diff --git a/chrome/common/localized_error.cc b/chrome/common/localized_error.cc
index 07e223c..c2f48b3 100644
--- a/chrome/common/localized_error.cc
+++ b/chrome/common/localized_error.cc
@@ -546,7 +546,7 @@
       base::DictionaryValue* reload_button = new base::DictionaryValue;
       reload_button->SetString("msg",
           l10n_util::GetStringUTF16(IDS_ERRORPAGES_BUTTON_RELOAD));
-      reload_button->SetString("reloadUrl", failed_url_string);
+      reload_button->SetString("reloadUrl", failed_url.spec());
       error_strings->Set("reload", reload_button);
     } else {
       // If the page was created by a post, it can't be reloaded in the same
diff --git a/chrome/common/logging_chrome.cc b/chrome/common/logging_chrome.cc
index cada54f..e588ccc 100644
--- a/chrome/common/logging_chrome.cc
+++ b/chrome/common/logging_chrome.cc
@@ -43,7 +43,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_restrictions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
@@ -132,13 +132,11 @@
 #ifdef NDEBUG
   bool enable_logging = false;
   const char *kInvertLoggingSwitch = switches::kEnableLogging;
-  const logging::LoggingDestination kDefaultLoggingMode =
-      logging::LOG_ONLY_TO_FILE;
+  const logging::LoggingDestination kDefaultLoggingMode = logging::LOG_TO_FILE;
 #else
   bool enable_logging = true;
   const char *kInvertLoggingSwitch = switches::kDisableLogging;
-  const logging::LoggingDestination kDefaultLoggingMode =
-      logging::LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG;
+  const logging::LoggingDestination kDefaultLoggingMode = logging::LOG_TO_ALL;
 #endif
 
   if (command_line.HasSwitch(kInvertLoggingSwitch))
@@ -149,7 +147,7 @@
     // Let --enable-logging=stderr force only stderr, particularly useful for
     // non-debug builds where otherwise you can't get logs to stderr at all.
     if (command_line.GetSwitchValueASCII(switches::kEnableLogging) == "stderr")
-      log_mode = logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG;
+      log_mode = logging::LOG_TO_SYSTEM_DEBUG_LOG;
     else
       log_mode = kDefaultLoggingMode;
   } else {
@@ -252,11 +250,11 @@
 
   // ChromeOS always logs through the symlink, so it shouldn't be
   // deleted if it already exists.
-  if (!InitLogging(log_path.value().c_str(),
-                   DetermineLogMode(command_line),
-                   logging::LOCK_LOG_FILE,
-                   logging::APPEND_TO_OLD_LOG_FILE,
-                   dcheck_state)) {
+  logging::LoggingSettings settings;
+  settings.logging_dest = DetermineLogMode(command_line);
+  settings.log_file = log_path.value().c_str();
+  settings.dcheck_state = dcheck_state;
+  if (!logging::InitLogging(settings)) {
     DLOG(ERROR) << "Unable to initialize logging to " << log_path.value();
     RemoveSymlinkAndLog(log_path, target_path);
   } else {
@@ -280,8 +278,7 @@
 
   // Don't resolve the log path unless we need to. Otherwise we leave an open
   // ALPC handle after sandbox lockdown on Windows.
-  if (logging_dest == LOG_ONLY_TO_FILE ||
-      logging_dest == LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG) {
+  if ((logging_dest & LOG_TO_FILE) != 0) {
     log_path = GetLogFileName();
 
 #if defined(OS_CHROMEOS)
@@ -311,11 +308,13 @@
       logging::ENABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS :
       logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS;
 
-  bool success = InitLogging(log_path.value().c_str(),
-                             logging_dest,
-                             log_locking_state,
-                             delete_old_log_file,
-                             dcheck_state);
+  logging::LoggingSettings settings;
+  settings.logging_dest = logging_dest;
+  settings.log_file = log_path.value().c_str();
+  settings.lock_log = log_locking_state;
+  settings.delete_old = delete_old_log_file;
+  settings.dcheck_state = dcheck_state;
+  bool success = logging::InitLogging(settings);
 
 #if defined(OS_CHROMEOS)
   if (!success) {
diff --git a/chrome/common/logging_chrome.h b/chrome/common/logging_chrome.h
index bde1793..91cd276 100644
--- a/chrome/common/logging_chrome.h
+++ b/chrome/common/logging_chrome.h
@@ -9,7 +9,7 @@
 #include <vector>
 
 #include "base/logging.h"
-#include "base/time.h"
+#include "base/time/time.h"
 
 class CommandLine;
 
diff --git a/chrome/common/mac/cfbundle_blocker.mm b/chrome/common/mac/cfbundle_blocker.mm
index a6cb6fe..41d3320 100644
--- a/chrome/common/mac/cfbundle_blocker.mm
+++ b/chrome/common/mac/cfbundle_blocker.mm
@@ -11,7 +11,7 @@
 #include "base/mac/mac_util.h"
 #include "base/mac/scoped_cftyperef.h"
 #include "base/mac/scoped_nsautorelease_pool.h"
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #include "base/strings/sys_string_conversions.h"
 #include "third_party/mach_override/mach_override.h"
 
@@ -156,8 +156,8 @@
 
   DCHECK(g_original_underscore_cfbundle_load_executable_and_return_error);
 
-  base::mac::ScopedCFTypeRef<CFURLRef> url_cf(CFBundleCopyBundleURL(bundle));
-  scoped_nsobject<NSString> path(base::mac::CFToNSCast(
+  base::ScopedCFTypeRef<CFURLRef> url_cf(CFBundleCopyBundleURL(bundle));
+  base::scoped_nsobject<NSString> path(base::mac::CFToNSCast(
       CFURLCopyFileSystemPath(url_cf, kCFURLPOSIXPathStyle)));
 
   NSString* bundle_id = base::mac::CFToNSCast(CFBundleGetIdentifier(bundle));
@@ -185,7 +185,7 @@
               << [path fileSystemRepresentation];
 
     if (error) {
-      base::mac::ScopedCFTypeRef<CFStringRef> app_bundle_id(
+      base::ScopedCFTypeRef<CFStringRef> app_bundle_id(
           base::SysUTF8ToCFStringRef(base::mac::BaseBundleID()));
 
       // 0xb10c10ad = "block load"
diff --git a/chrome/common/mac/mock_launchd.cc b/chrome/common/mac/mock_launchd.cc
index bc08bf8..6a39540 100644
--- a/chrome/common/mac/mock_launchd.cc
+++ b/chrome/common/mac/mock_launchd.cc
@@ -83,12 +83,12 @@
   }
   const UInt8* bundle_root_path =
       reinterpret_cast<const UInt8*>(bundle_root->value().c_str());
-  base::mac::ScopedCFTypeRef<CFURLRef> url(
+  base::ScopedCFTypeRef<CFURLRef> url(
       CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault,
                                               bundle_root_path,
                                               bundle_root->value().length(),
                                               true));
-  base::mac::ScopedCFTypeRef<CFBundleRef> bundle(
+  base::ScopedCFTypeRef<CFBundleRef> bundle(
       CFBundleCreate(kCFAllocatorDefault, url));
   return bundle.get();
 }
@@ -126,9 +126,8 @@
 
   CFStringRef env_var =
       base::mac::NSToCFCast(GetServiceProcessLaunchDSocketEnvVar());
-  base::mac::ScopedCFTypeRef<CFStringRef> socket_path(
-      CFStringCreateWithCString(kCFAllocatorDefault, pipe_name_.c_str(),
-                                kCFStringEncodingUTF8));
+  base::ScopedCFTypeRef<CFStringRef> socket_path(CFStringCreateWithCString(
+      kCFAllocatorDefault, pipe_name_.c_str(), kCFStringEncodingUTF8));
   const void *keys[] = { env_var };
   const void *values[] = { socket_path };
   COMPILE_ASSERT(arraysize(keys) == arraysize(values), array_sizes_must_match);
@@ -151,10 +150,10 @@
   CFStringRef program = CFSTR(LAUNCH_JOBKEY_PROGRAM);
   CFStringRef program_pid = CFSTR(LAUNCH_JOBKEY_PID);
   const void *keys[] = { program, program_pid };
-  base::mac::ScopedCFTypeRef<CFStringRef> path(
+  base::ScopedCFTypeRef<CFStringRef> path(
       base::SysUTF8ToCFStringRef(file_.value()));
   int process_id = base::GetCurrentProcId();
-  base::mac::ScopedCFTypeRef<CFNumberRef> pid(
+  base::ScopedCFTypeRef<CFNumberRef> pid(
       CFNumberCreate(NULL, kCFNumberIntType, &process_id));
   const void *values[] = { path, pid };
   COMPILE_ASSERT(arraysize(keys) == arraysize(values), array_sizes_must_match);
@@ -170,14 +169,11 @@
   checkin_called_ = true;
   CFStringRef program = CFSTR(LAUNCH_JOBKEY_PROGRAM);
   CFStringRef program_args = CFSTR(LAUNCH_JOBKEY_PROGRAMARGUMENTS);
-  base::mac::ScopedCFTypeRef<CFStringRef> path(
+  base::ScopedCFTypeRef<CFStringRef> path(
       base::SysUTF8ToCFStringRef(file_.value()));
   const void *array_values[] = { path.get() };
-  base::mac::ScopedCFTypeRef<CFArrayRef> args(
-      CFArrayCreate(kCFAllocatorDefault,
-                    array_values,
-                    1,
-                    &kCFTypeArrayCallBacks));
+  base::ScopedCFTypeRef<CFArrayRef> args(CFArrayCreate(
+      kCFAllocatorDefault, array_values, 1, &kCFTypeArrayCallBacks));
 
   if (!create_socket_) {
     const void *keys[] = { program, program_args };
@@ -210,7 +206,7 @@
   signature.protocol = 0;
   size_t unix_addr_len = offsetof(struct sockaddr_un,
                                   sun_path) + path_len + 1;
-  base::mac::ScopedCFTypeRef<CFDataRef> address(
+  base::ScopedCFTypeRef<CFDataRef> address(
       CFDataCreate(NULL, reinterpret_cast<UInt8*>(&unix_addr), unix_addr_len));
   signature.address = address;
 
@@ -227,20 +223,17 @@
     return NULL;
   }
 
-  base::mac::ScopedCFTypeRef<CFNumberRef> socket_fd(
+  base::ScopedCFTypeRef<CFNumberRef> socket_fd(
       CFNumberCreate(NULL, kCFNumberIntType, &local_pipe));
   const void *socket_array_values[] = { socket_fd };
-  base::mac::ScopedCFTypeRef<CFArrayRef> sockets(
-      CFArrayCreate(kCFAllocatorDefault,
-                    socket_array_values,
-                    1,
-                    &kCFTypeArrayCallBacks));
+  base::ScopedCFTypeRef<CFArrayRef> sockets(CFArrayCreate(
+      kCFAllocatorDefault, socket_array_values, 1, &kCFTypeArrayCallBacks));
   CFStringRef socket_dict_key = CFSTR("ServiceProcessSocket");
   const void *socket_keys[] = { socket_dict_key };
   const void *socket_values[] = { sockets };
   COMPILE_ASSERT(arraysize(socket_keys) == arraysize(socket_values),
                  socket_array_sizes_must_match);
-  base::mac::ScopedCFTypeRef<CFDictionaryRef> socket_dict(
+  base::ScopedCFTypeRef<CFDictionaryRef> socket_dict(
       CFDictionaryCreate(kCFAllocatorDefault,
                          socket_keys,
                          socket_values,
@@ -277,8 +270,7 @@
     Domain domain,
     Type type,
     CFStringRef name)  {
-  base::mac::ScopedCFTypeRef<CFDictionaryRef> dict(
-      CopyDictionaryByCheckingIn(NULL));
+  base::ScopedCFTypeRef<CFDictionaryRef> dict(CopyDictionaryByCheckingIn(NULL));
   return CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, dict);
 }
 
diff --git a/chrome/common/mac/nscoder_util_unittest.mm b/chrome/common/mac/nscoder_util_unittest.mm
index 204ebd7..ed84a94 100644
--- a/chrome/common/mac/nscoder_util_unittest.mm
+++ b/chrome/common/mac/nscoder_util_unittest.mm
@@ -5,7 +5,7 @@
 #import <Foundation/Foundation.h>
 
 #include "base/basictypes.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "chrome/common/mac/nscoder_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
@@ -27,12 +27,12 @@
   for (size_t i = 0; i < arraysize(testStrings); ++i) {
     NSMutableData *data = [NSMutableData data];
 
-    scoped_nsobject<NSKeyedArchiver> archiver(
+    base::scoped_nsobject<NSKeyedArchiver> archiver(
         [[NSKeyedArchiver alloc] initForWritingWithMutableData:data]);
     nscoder_util::EncodeString(archiver, @"test", testStrings[i]);
     [archiver finishEncoding];
 
-    scoped_nsobject<NSKeyedUnarchiver> unarchiver(
+    base::scoped_nsobject<NSKeyedUnarchiver> unarchiver(
         [[NSKeyedUnarchiver alloc] initForReadingWithData:data]);
     const std::string decoded = nscoder_util::DecodeString(unarchiver, @"test");
 
@@ -43,11 +43,11 @@
 TEST_F(NSCoderStdStringTest, decodeEmpty) {
   NSMutableData *data = [NSMutableData data];
 
-  scoped_nsobject<NSKeyedArchiver> archiver(
+  base::scoped_nsobject<NSKeyedArchiver> archiver(
       [[NSKeyedArchiver alloc] initForWritingWithMutableData:data]);
   [archiver finishEncoding];
 
-  scoped_nsobject<NSKeyedUnarchiver> unarchiver(
+  base::scoped_nsobject<NSKeyedUnarchiver> unarchiver(
       [[NSKeyedUnarchiver alloc] initForReadingWithData:data]);
   const std::string decoded = nscoder_util::DecodeString(unarchiver, @"test");
 
diff --git a/chrome/common/mac/objc_method_swizzle.mm b/chrome/common/mac/objc_method_swizzle.mm
index 4ed4df8..62b630a 100644
--- a/chrome/common/mac/objc_method_swizzle.mm
+++ b/chrome/common/mac/objc_method_swizzle.mm
@@ -5,7 +5,6 @@
 #import "chrome/common/mac/objc_method_swizzle.h"
 
 #import "base/logging.h"
-#import "base/memory/scoped_nsobject.h"
 
 namespace ObjcEvilDoers {
 
diff --git a/chrome/common/mac/objc_method_swizzle_unittest.mm b/chrome/common/mac/objc_method_swizzle_unittest.mm
index 261e24d..3053f3b 100644
--- a/chrome/common/mac/objc_method_swizzle_unittest.mm
+++ b/chrome/common/mac/objc_method_swizzle_unittest.mm
@@ -4,7 +4,7 @@
 
 #import "chrome/common/mac/objc_method_swizzle.h"
 
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 @interface ObjcMethodSwizzleTest : NSObject
@@ -58,7 +58,7 @@
 }
 
 TEST(ObjcMethodSwizzleTest, SwizzleImplementedInstanceMethods) {
-  scoped_nsobject<ObjcMethodSwizzleTest> object(
+  base::scoped_nsobject<ObjcMethodSwizzleTest> object(
       [[ObjcMethodSwizzleTest alloc] init]);
   EXPECT_EQ([object one], 1);
   EXPECT_EQ([object two], 2);
diff --git a/chrome/common/mac/objc_zombie_unittest.mm b/chrome/common/mac/objc_zombie_unittest.mm
index bb11cf0..9e438d2 100644
--- a/chrome/common/mac/objc_zombie_unittest.mm
+++ b/chrome/common/mac/objc_zombie_unittest.mm
@@ -6,14 +6,14 @@
 #include <objc/runtime.h>
 
 #include "base/logging.h"
-#import "base/memory/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #import "chrome/common/mac/objc_zombie.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
 
 @interface ZombieCxxDestructTest : NSObject
 {
-  scoped_nsobject<id> aRef_;
+  base::scoped_nsobject<id> aRef_;
 }
 - (id)initWith:(id)anObject;
 @end
@@ -54,12 +54,12 @@
 // NOTE(shess): To test the negative, comment out the |g_objectDestruct()|
 // call in |ZombieDealloc()|.
 TEST(ObjcZombieTest, CxxDestructors) {
-  scoped_nsobject<id> anObject([[NSObject alloc] init]);
+  base::scoped_nsobject<id> anObject([[NSObject alloc] init]);
   EXPECT_EQ(1u, [anObject retainCount]);
 
   ASSERT_TRUE(ObjcEvilDoers::ZombieEnable(YES, 100));
 
-  scoped_nsobject<ZombieCxxDestructTest> soonInfected(
+  base::scoped_nsobject<ZombieCxxDestructTest> soonInfected(
       [[ZombieCxxDestructTest alloc] initWith:anObject]);
   EXPECT_EQ(2u, [anObject retainCount]);
 
@@ -76,12 +76,12 @@
 // Verify that the associated objects are released when the object is
 // released.
 TEST(ObjcZombieTest, AssociatedObjectsReleased) {
-  scoped_nsobject<id> anObject([[NSObject alloc] init]);
+  base::scoped_nsobject<id> anObject([[NSObject alloc] init]);
   EXPECT_EQ(1u, [anObject retainCount]);
 
   ASSERT_TRUE(ObjcEvilDoers::ZombieEnable(YES, 100));
 
-  scoped_nsobject<ZombieAssociatedObjectTest> soonInfected(
+  base::scoped_nsobject<ZombieAssociatedObjectTest> soonInfected(
       [[ZombieAssociatedObjectTest alloc] initWithAssociatedObject:anObject]);
   EXPECT_EQ(2u, [anObject retainCount]);
 
diff --git a/chrome/common/media_galleries/OWNERS b/chrome/common/media_galleries/OWNERS
new file mode 100644
index 0000000..f441493
--- /dev/null
+++ b/chrome/common/media_galleries/OWNERS
@@ -0,0 +1,4 @@
+estade@chromium.org
+gbillock@chromium.org
+thestig@chromium.org
+vandebo@chromium.org
diff --git a/chrome/common/media_galleries/picasa_types.cc b/chrome/common/media_galleries/picasa_types.cc
new file mode 100644
index 0000000..1bcc398
--- /dev/null
+++ b/chrome/common/media_galleries/picasa_types.cc
@@ -0,0 +1,54 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/common/media_galleries/picasa_types.h"
+
+#include "base/logging.h"
+#include "chrome/common/media_galleries/pmp_constants.h"
+
+namespace picasa {
+
+namespace {
+
+void ClosePlatformFile(base::PlatformFile* platform_file) {
+  DCHECK(platform_file);
+  if (base::ClosePlatformFile(*platform_file))
+    *platform_file = base::kInvalidPlatformFileValue;
+}
+
+}  // namespace
+
+AlbumInfo::AlbumInfo() {}
+
+AlbumInfo::AlbumInfo(const std::string& name, const base::Time& timestamp,
+                     const std::string& uid, const base::FilePath& path)
+    : name(name),
+      timestamp(timestamp),
+      uid(uid),
+      path(path) {
+}
+
+AlbumInfo::~AlbumInfo() {}
+
+AlbumTableFiles::AlbumTableFiles()
+    : indicator_file(base::kInvalidPlatformFileValue),
+      category_file(base::kInvalidPlatformFileValue),
+      date_file(base::kInvalidPlatformFileValue),
+      filename_file(base::kInvalidPlatformFileValue),
+      name_file(base::kInvalidPlatformFileValue),
+      token_file(base::kInvalidPlatformFileValue),
+      uid_file(base::kInvalidPlatformFileValue) {
+}
+
+void CloseAlbumTableFiles(AlbumTableFiles* table_files) {
+  ClosePlatformFile(&(table_files->indicator_file));
+  ClosePlatformFile(&(table_files->category_file));
+  ClosePlatformFile(&(table_files->date_file));
+  ClosePlatformFile(&(table_files->filename_file));
+  ClosePlatformFile(&(table_files->name_file));
+  ClosePlatformFile(&(table_files->token_file));
+  ClosePlatformFile(&(table_files->uid_file));
+}
+
+}  // namespace picasa
diff --git a/chrome/common/media_galleries/picasa_types.h b/chrome/common/media_galleries/picasa_types.h
new file mode 100644
index 0000000..7e6bc67
--- /dev/null
+++ b/chrome/common/media_galleries/picasa_types.h
@@ -0,0 +1,48 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_COMMON_MEDIA_GALLERIES_PICASA_TYPES_H_
+#define CHROME_COMMON_MEDIA_GALLERIES_PICASA_TYPES_H_
+
+#include <string>
+
+#include "base/files/file_path.h"
+#include "base/platform_file.h"
+
+namespace picasa {
+
+const char kPicasaAlbumTableName[] = "albumdata";
+
+struct AlbumInfo {
+  AlbumInfo();
+  AlbumInfo(const std::string& name, const base::Time& timestamp,
+            const std::string& uid, const base::FilePath& path);
+
+  ~AlbumInfo();
+
+  std::string name;
+  base::Time timestamp;
+  std::string uid;
+  base::FilePath path;
+};
+
+struct AlbumTableFiles {
+  AlbumTableFiles();
+
+  // Special empty file used to confirm existence of table.
+  base::PlatformFile indicator_file;
+
+  base::PlatformFile category_file;
+  base::PlatformFile date_file;
+  base::PlatformFile filename_file;
+  base::PlatformFile name_file;
+  base::PlatformFile token_file;
+  base::PlatformFile uid_file;
+};
+
+void CloseAlbumTableFiles(AlbumTableFiles* table_files);
+
+}  // namespace picasa
+
+#endif  // CHROME_COMMON_MEDIA_GALLERIES_PICASA_TYPES_H_
diff --git a/chrome/common/media_galleries/pmp_constants.h b/chrome/common/media_galleries/pmp_constants.h
new file mode 100644
index 0000000..385af9c
--- /dev/null
+++ b/chrome/common/media_galleries/pmp_constants.h
@@ -0,0 +1,52 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_COMMON_MEDIA_GALLERIES_PMP_CONSTANTS_H_
+#define CHROME_COMMON_MEDIA_GALLERIES_PMP_CONSTANTS_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/time/time.h"
+
+namespace picasa {
+
+// PMP file format.
+// Info derived from: http://sbktech.blogspot.com/2011/12/picasa-pmp-format.html
+
+const char kPmpExtension[] = "pmp";
+
+const base::Time::Exploded kPmpVariantTimeEpoch = {
+  1899, 12, 7, 30,  // Dec 30, 1899 (Saturday)
+  0, 0, 0, 0        // 00:00:00.000
+};
+
+const int64 kPmpHeaderSize = 20;
+
+const int kPmpMagic1Offset = 0;
+const int kPmpMagic2Offset = 6;
+const int kPmpMagic3Offset = 8;
+const int kPmpMagic4Offset = 14;
+
+const uint32 kPmpMagic1 = 0x3fcccccd;
+const uint16 kPmpMagic2 = 0x1332;
+const uint32 kPmpMagic3 = 0x00000002;
+const uint16 kPmpMagic4 = 0x1332;
+
+const int kPmpFieldType1Offset = 4;
+const int kPmpFieldType2Offset = 12;
+const int kPmpRowCountOffset   = 16;
+
+enum PmpFieldType {
+  PMP_TYPE_STRING   = 0x00,
+  PMP_TYPE_UINT32   = 0x01,
+  PMP_TYPE_DOUBLE64 = 0x02,
+  PMP_TYPE_UINT8    = 0x03,
+  PMP_TYPE_UINT64   = 0x04,
+  PMP_TYPE_INVALID  = 0xff
+};
+
+}  // namespace picasa
+
+#endif  // CHROME_COMMON_MEDIA_GALLERIES_PMP_CONSTANTS_H_
diff --git a/chrome/common/metrics/entropy_provider_unittest.cc b/chrome/common/metrics/entropy_provider_unittest.cc
index f76d153..e64a8eb 100644
--- a/chrome/common/metrics/entropy_provider_unittest.cc
+++ b/chrome/common/metrics/entropy_provider_unittest.cc
@@ -22,7 +22,7 @@
 
 // Size of the low entropy source to use for the permuted entropy provider
 // in tests.
-const size_t kMaxLowEntropySize = (1 << 13);
+const size_t kMaxLowEntropySize = 8000;
 
 // Field trial names used in unit tests.
 const std::string kTestTrialNames[] = { "TestTrial", "AnotherTestTrial",
diff --git a/chrome/common/metrics/metrics_log_base.h b/chrome/common/metrics/metrics_log_base.h
index 5b87f07..8f9c753 100644
--- a/chrome/common/metrics/metrics_log_base.h
+++ b/chrome/common/metrics/metrics_log_base.h
@@ -12,7 +12,7 @@
 
 #include "base/basictypes.h"
 #include "base/metrics/histogram.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/common/metrics/proto/chrome_user_metrics_extension.pb.h"
 #include "content/public/common/page_transition_types.h"
 
diff --git a/chrome/common/metrics/metrics_log_base_unittest.cc b/chrome/common/metrics/metrics_log_base_unittest.cc
index cd6b3bf..cde676a 100644
--- a/chrome/common/metrics/metrics_log_base_unittest.cc
+++ b/chrome/common/metrics/metrics_log_base_unittest.cc
@@ -8,7 +8,7 @@
 #include "base/format_macros.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/common/metrics/metrics_log_base.h"
 #include "googleurl/src/gurl.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/common/metrics/variations/uniformity_field_trials.cc b/chrome/common/metrics/variations/uniformity_field_trials.cc
index 3032e17..0ae53a5 100644
--- a/chrome/common/metrics/variations/uniformity_field_trials.cc
+++ b/chrome/common/metrics/variations/uniformity_field_trials.cc
@@ -6,7 +6,7 @@
 
 #include "base/metrics/field_trial.h"
 #include "base/strings/stringprintf.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/common/metrics/variations/variations_util.h"
 
 namespace {
diff --git a/chrome/common/metrics/variations/variations_util_unittest.cc b/chrome/common/metrics/variations/variations_util_unittest.cc
index b4c150f..edc0bf4 100644
--- a/chrome/common/metrics/variations/variations_util_unittest.cc
+++ b/chrome/common/metrics/variations/variations_util_unittest.cc
@@ -11,7 +11,7 @@
 #include "base/metrics/field_trial.h"
 #include "base/strings/string_split.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/common/metrics/metrics_util.h"
 #include "chrome/common/metrics/variations/variations_util.h"
 #include "content/public/test/test_browser_thread.h"
diff --git a/chrome/common/multi_process_lock_mac.cc b/chrome/common/multi_process_lock_mac.cc
index 35fc576..176ae4c 100644
--- a/chrome/common/multi_process_lock_mac.cc
+++ b/chrome/common/multi_process_lock_mac.cc
@@ -33,7 +33,7 @@
     }
 
     CFStringRef cf_name(base::SysUTF8ToCFStringRef(name_));
-    base::mac::ScopedCFTypeRef<CFStringRef> scoped_cf_name(cf_name);
+    base::ScopedCFTypeRef<CFStringRef> scoped_cf_name(cf_name);
     port_.reset(CFMessagePortCreateLocal(NULL, cf_name, NULL, NULL, NULL));
     return port_ != NULL;
   }
@@ -48,7 +48,7 @@
 
  private:
   std::string name_;
-  base::mac::ScopedCFTypeRef<CFMessagePortRef> port_;
+  base::ScopedCFTypeRef<CFMessagePortRef> port_;
   DISALLOW_COPY_AND_ASSIGN(MultiProcessLockMac);
 };
 
diff --git a/chrome/common/multi_process_lock_unittest.cc b/chrome/common/multi_process_lock_unittest.cc
index 250e065..1059448 100644
--- a/chrome/common/multi_process_lock_unittest.cc
+++ b/chrome/common/multi_process_lock_unittest.cc
@@ -9,7 +9,7 @@
 #include "base/rand_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/test/multiprocess_test.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/common/multi_process_lock.h"
 #include "testing/multiprocess_func_list.h"
 
diff --git a/chrome/common/nacl_cmd_line.cc b/chrome/common/nacl_cmd_line.cc
index 2c2fde6..9fb1a0e 100644
--- a/chrome/common/nacl_cmd_line.cc
+++ b/chrome/common/nacl_cmd_line.cc
@@ -5,6 +5,8 @@
 #include "base/basictypes.h"
 #include "base/command_line.h"
 #include "chrome/common/chrome_switches.h"
+#include "components/nacl/common/nacl_switches.h"
+#include "content/public/common/content_switches.h"
 
 namespace nacl {
 
@@ -23,8 +25,6 @@
     switches::kDisableLogging,
     switches::kLoggingLevel,
     switches::kEnableDCHECK,
-    switches::kSilentDumpOnDCHECK,
-    switches::kMemoryProfiling,
     switches::kNoErrorDialogs,
 #if defined(OS_MACOSX)
     switches::kEnableSandboxLogging,
diff --git a/chrome/common/nacl_paths.cc b/chrome/common/nacl_paths.cc
new file mode 100644
index 0000000..22f9c22
--- /dev/null
+++ b/chrome/common/nacl_paths.cc
@@ -0,0 +1,53 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/common/nacl_paths.h"
+
+#include "base/file_util.h"
+#include "base/path_service.h"
+
+namespace {
+
+#if defined(OS_POSIX) && !defined(OS_MACOSX)
+// File name of the nacl_helper and nacl_helper_bootstrap, Linux only.
+const base::FilePath::CharType kInternalNaClHelperFileName[] =
+    FILE_PATH_LITERAL("nacl_helper");
+const base::FilePath::CharType kInternalNaClHelperBootstrapFileName[] =
+    FILE_PATH_LITERAL("nacl_helper_bootstrap");
+#endif
+
+}  // namespace
+
+namespace nacl {
+
+bool PathProvider(int key, base::FilePath* result) {
+  base::FilePath cur;
+  switch (key) {
+#if defined(OS_LINUX)
+    case FILE_NACL_HELPER:
+      if (!PathService::Get(base::DIR_MODULE, &cur))
+        return false;
+      cur = cur.Append(kInternalNaClHelperFileName);
+      break;
+    case FILE_NACL_HELPER_BOOTSTRAP:
+      if (!PathService::Get(base::DIR_MODULE, &cur))
+        return false;
+      cur = cur.Append(kInternalNaClHelperBootstrapFileName);
+      break;
+#endif
+    default:
+      return false;
+  }
+
+  *result = cur;
+  return true;
+}
+
+// This cannot be done as a static initializer sadly since Visual Studio will
+// eliminate this object file if there is no direct entry point into it.
+void RegisterPathProvider() {
+  PathService::RegisterProvider(PathProvider, PATH_START, PATH_END);
+}
+
+}  // namespace nacl
diff --git a/chrome/common/nacl_paths.h b/chrome/common/nacl_paths.h
new file mode 100644
index 0000000..1ae755f
--- /dev/null
+++ b/chrome/common/nacl_paths.h
@@ -0,0 +1,31 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_COMMON_NACL_PATHS_H_
+#define CHROME_COMMON_NACL_PATHS_H_
+
+#include "build/build_config.h"
+
+// This file declares path keys for the chrome module.  These can be used with
+// the PathService to access various special directories and files.
+
+namespace nacl {
+
+enum {
+  PATH_START = 9000,
+
+#if defined(OS_LINUX)
+  FILE_NACL_HELPER = PATH_START, // Full path to Linux nacl_helper executable.
+  FILE_NACL_HELPER_BOOTSTRAP,    // ... and nacl_helper_bootstrap executable.
+#endif
+
+  PATH_END
+};
+
+// Call once to register the provider for the path keys defined above.
+void RegisterPathProvider();
+
+}  // namespace nacl
+
+#endif  // CHROME_COMMON_NACL_PATHS_H_
diff --git a/chrome/common/net/x509_certificate_model_unittest.cc b/chrome/common/net/x509_certificate_model_unittest.cc
index 40e2834..62bffa7 100644
--- a/chrome/common/net/x509_certificate_model_unittest.cc
+++ b/chrome/common/net/x509_certificate_model_unittest.cc
@@ -14,7 +14,7 @@
 TEST(X509CertificateModelTest, GetTypeCA) {
   scoped_refptr<net::X509Certificate> cert(
       net::ImportCertFromFile(net::GetTestCertsDirectory(),
-                              "root_ca_cert.crt"));
+                              "root_ca_cert.pem"));
   ASSERT_TRUE(cert.get());
 
 #if defined(USE_OPENSSL)
diff --git a/chrome/common/omaha_query_params/omaha_query_params.cc b/chrome/common/omaha_query_params/omaha_query_params.cc
index 6db55d9..04fb7ab 100644
--- a/chrome/common/omaha_query_params/omaha_query_params.cc
+++ b/chrome/common/omaha_query_params/omaha_query_params.cc
@@ -49,22 +49,6 @@
 const char kChromeCrx[] = "chromecrx";
 const char kChromiumCrx[] = "chromiumcrx";
 
-const char* GetProdIdString(chrome::OmahaQueryParams::ProdId prod) {
-  switch (prod) {
-    case chrome::OmahaQueryParams::CHROME:
-      return kChrome;
-      break;
-    case chrome::OmahaQueryParams::CRX:
-#if defined(GOOGLE_CHROME_BUILD)
-      return kChromeCrx;
-#else
-      return kChromiumCrx;
-#endif
-      break;
-  }
-  return kUnknown;
-}
-
 const char kStable[] = "stable";
 const char kBeta[] = "beta";
 const char kDev[] = "dev";
@@ -95,6 +79,7 @@
 
 namespace chrome {
 
+// static
 std::string OmahaQueryParams::Get(ProdId prod) {
   return base::StringPrintf(
       "os=%s&arch=%s&nacl_arch=%s&prod=%s&prodchannel=%s&prodversion=%s",
@@ -107,6 +92,24 @@
 }
 
 // static
+const char* OmahaQueryParams::GetProdIdString(
+    chrome::OmahaQueryParams::ProdId prod) {
+  switch (prod) {
+    case chrome::OmahaQueryParams::CHROME:
+      return kChrome;
+      break;
+    case chrome::OmahaQueryParams::CRX:
+#if defined(GOOGLE_CHROME_BUILD)
+      return kChromeCrx;
+#else
+      return kChromiumCrx;
+#endif
+      break;
+  }
+  return kUnknown;
+}
+
+// static
 const char* OmahaQueryParams::getOS() {
   return kOs;
 }
diff --git a/chrome/common/omaha_query_params/omaha_query_params.h b/chrome/common/omaha_query_params/omaha_query_params.h
index 7f74be1..91f6f18 100644
--- a/chrome/common/omaha_query_params/omaha_query_params.h
+++ b/chrome/common/omaha_query_params/omaha_query_params.h
@@ -23,6 +23,10 @@
   // prod, prodchannel, prodversion.
   static std::string Get(ProdId prod);
 
+  // Returns the value we use for the "prod=" parameter. Possible return values
+  // include "chrome", "chromecrx", "chromiumcrx", and "unknown".
+  static const char* GetProdIdString(chrome::OmahaQueryParams::ProdId prod);
+
   // Returns the value we use for the "os=" parameter. Possible return values
   // include: "mac", "win", "android", "cros", "linux", and "openbsd".
   static const char* getOS();
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index 0f110a9..55c07ca 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -39,8 +39,13 @@
 const char kManagedModeManualURLs[] = "profile.managed.manual_urls";
 
 // Stores the email address associated with the google account of the custodian
-// of the managed user.
-const char kManagedUserCustodian[] = "profile.managed.custodian_email";
+// of the managed user, set when the managed user is created.
+const char kManagedUserCustodianEmail[] = "profile.managed.custodian_email";
+
+// Stores the display name associated with the google account of the custodian
+// of the managed user, updated (if possible) each time the managed user
+// starts a session.
+const char kManagedUserCustodianName[] = "profile.managed.custodian_name";
 
 // Used to determine if the last session exited cleanly. Set to false when
 // first opened, and to true when closing. On startup if the value is false,
@@ -796,21 +801,6 @@
 // A dictionary pref that stores per display preferences.
 const char kDisplayProperties[] = "settings.display.properties";
 
-// A 64bit integer pref that specifies the name of the primary display device.
-const char kPrimaryDisplayID[] = "settings.display.primary_id";
-
-// An enumeration that specifies the layout of the secondary display.
-//  0 - The secondary display is at the top of the primary display.
-//  1 - The secondary display is at the right of the primary display.
-//  2 - The secondary display is at the bottom of the primary display.
-//  3 - The secondary display is at the left of the primary display.
-// TODO(mukai,oshima): update the format of the multi-display settings.
-const char kSecondaryDisplayLayout[] = "settings.display.secondary_layout";
-
-// An integer pref that specifies how far the secondary display is positioned
-// from the edge of the primary display.
-const char kSecondaryDisplayOffset[] = "settings.display.secondary_offset";
-
 // A dictionary pref that specifies per-display layout/offset information.
 // Its key is the ID of the display and its value is a dictionary for the
 // layout/offset information.
@@ -831,7 +821,7 @@
 // Inactivity time in milliseconds while the system is on AC power before
 // the screen should be dimmed, turned off, or locked, before an
 // IdleActionImminent D-Bus signal should be sent, or before
-// kPowerIdleAction should be performed.  0 disables the delay (N/A for
+// kPowerAcIdleAction should be performed.  0 disables the delay (N/A for
 // kPowerAcIdleDelayMs).
 const char kPowerAcScreenDimDelayMs[] = "power.ac_screen_dim_delay_ms";
 const char kPowerAcScreenOffDelayMs[] = "power.ac_screen_off_delay_ms";
@@ -851,9 +841,11 @@
 const char kPowerBatteryIdleDelayMs[] =
     "power.battery_idle_delay_ms";
 
-// Action that should be performed when the idle delay is reached.
+// Action that should be performed when the idle delay is reached while the
+// system is on AC power or battery power.
 // Values are from the chromeos::PowerPolicyController::Action enum.
-const char kPowerIdleAction[] = "power.idle_action";
+const char kPowerAcIdleAction[] = "power.ac_idle_action";
+const char kPowerBatteryIdleAction[] = "power.battery_idle_action";
 
 // Action that should be performed when the lid is closed.
 // Values are from the chromeos::PowerPolicyController::Action enum.
@@ -867,11 +859,6 @@
 // screen-related power management (including locking)?
 const char kPowerAllowScreenWakeLocks[] = "power.allow_screen_wake_locks";
 
-// DEPRECATED: This is replaced by kPowerPresentationScreenDimDelayFactor
-// and has no effect.
-const char kPowerPresentationIdleDelayFactor[] =
-    "power.presentation_idle_delay_factor";
-
 // Amount by which the screen-dim delay should be scaled while the system
 // is in presentation mode. Values are limited to a minimum of 1.0.
 const char kPowerPresentationScreenDimDelayFactor[] =
@@ -955,8 +942,8 @@
 // Boolean controlling whether SafeSearch is mandatory for Google Web Searches.
 const char kForceSafeSearch[] = "settings.force_safesearch";
 
-#if defined(TOOLKIT_GTK)
-// GTK specific preference on whether we should match the system GTK theme.
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+// Linux specific preference on whether we should match the system theme.
 const char kUsesSystemTheme[] = "extensions.theme.use_system";
 #endif
 const char kCurrentThemePackFilename[] = "extensions.theme.pack";
@@ -1237,6 +1224,10 @@
 const char kDefaultManagedModeFilteringBehavior[] =
     "profile.managed.default_filtering_behavior";
 
+// Whether this user is permitted to create managed users.
+const char kManagedUserCreationAllowed[] =
+    "profile.managed_user_creation_allowed";
+
 // List pref containing the users managed by this user.
 const char kManagedUsers[] = "profile.managed_users";
 
@@ -1250,6 +1241,11 @@
 const char kMessageCenterDisabledSystemComponentIds[] =
     "message_center.disabled_system_component_ids";
 
+// List pref containing the system component ids which are allowed to send
+// notifications to the message center.
+extern const char kMessageCenterEnabledSyncNotifierIds[] =
+    "message_center.enabled_sync_notifier_ids";
+
 // *************** LOCAL STATE ***************
 // These are attached to the machine/installation
 
@@ -1852,6 +1848,9 @@
 // passphrase.
 const char kSyncUsingSecondaryPassphrase[] = "sync.using_secondary_passphrase";
 
+// Preferences that follow the status of sync server triggered experiments.
+const char kSyncFaviconsEnabled[] ="sync.favicons_syncing_enabled";
+
 // String the identifies the last user that logged into sync and other
 // google services. As opposed to kGoogleServicesUsername, this value is not
 // cleared on signout, but while the user is signed in the two values will
@@ -2156,6 +2155,11 @@
 // Indicates that factory reset was requested from options page.
 const char kFactoryResetRequested[] = "FactoryResetRequested";
 
+// Boolean recording whether we have showed a balloon that calls out the message
+// center for desktop notifications.
+const char kMessageCenterShowedFirstRunBalloon[] =
+    "message_center.showed_first_run_balloon";
+
 // *************** SERVICE PREFS ***************
 // These are attached to the service process.
 
@@ -2416,6 +2420,8 @@
     "gesture.rail_break_proportion";
 const char kRailStartProportion[] =
     "gesture.rail_start_proportion";
+const char kScrollPredictionSeconds[] =
+    "gesture.scroll_prediction_seconds";
 const char kSemiLongPressTimeInSeconds[] =
     "gesture.semi_long_press_time_in_seconds";
 const char kTabScrubActivationDelayInMS[] =
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index 0335acd..6a9a357 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -23,7 +23,8 @@
 extern const char kHomePage[];
 extern const char kManagedModeManualHosts[];
 extern const char kManagedModeManualURLs[];
-extern const char kManagedUserCustodian[];
+extern const char kManagedUserCustodianEmail[];
+extern const char kManagedUserCustodianName[];
 extern const char kSessionExitedCleanly[];
 extern const char kSessionExitType[];
 extern const char kRestoreOnStartup[];
@@ -291,9 +292,6 @@
 extern const char kUseSharedProxies[];
 extern const char kDisplayPowerState[];
 extern const char kDisplayProperties[];
-extern const char kPrimaryDisplayID[];
-extern const char kSecondaryDisplayLayout[];
-extern const char kSecondaryDisplayOffset[];
 extern const char kSecondaryDisplays[];
 extern const char kSessionStartTime[];
 extern const char kSessionLengthLimit[];
@@ -307,12 +305,12 @@
 extern const char kPowerBatteryScreenLockDelayMs[];
 extern const char kPowerBatteryIdleWarningDelayMs[];
 extern const char kPowerBatteryIdleDelayMs[];
-extern const char kPowerIdleAction[];
+extern const char kPowerAcIdleAction[];
+extern const char kPowerBatteryIdleAction[];
 extern const char kPowerLidClosedAction[];
 extern const char kPowerUseAudioActivity[];
 extern const char kPowerUseVideoActivity[];
 extern const char kPowerAllowScreenWakeLocks[];
-extern const char kPowerPresentationIdleDelayFactor[];
 extern const char kPowerPresentationScreenDimDelayFactor[];
 extern const char kPowerUserActivityScreenDimDelayFactor[];
 extern const char kTermsOfServiceURL[];
@@ -341,7 +339,7 @@
 extern const char kForceSafeSearch[];
 extern const char kDeleteTimePeriod[];
 extern const char kLastClearBrowsingDataTime[];
-#if defined(TOOLKIT_GTK)
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
 extern const char kUsesSystemTheme[];
 #endif
 extern const char kCurrentThemePackFilename[];
@@ -426,10 +424,12 @@
 
 extern const char kDefaultManagedModeFilteringBehavior[];
 
+extern const char kManagedUserCreationAllowed[];
 extern const char kManagedUsers[];
 
 extern const char kMessageCenterDisabledExtensionIds[];
 extern const char kMessageCenterDisabledSystemComponentIds[];
+extern const char kMessageCenterEnabledSyncNotifierIds[];
 
 // Local state prefs. Please add Profile prefs above instead.
 extern const char kCertRevocationCheckingEnabled[];
@@ -670,6 +670,8 @@
 extern const char kSyncPromoShowNTPBubble[];
 extern const char kSyncPromoErrorMessage[];
 
+extern const char kSyncFaviconsEnabled[];
+
 extern const char kProfileGAIAInfoUpdateTime[];
 extern const char kProfileGAIAInfoPictureURL[];
 
@@ -830,6 +832,8 @@
 
 extern const char kFactoryResetRequested[];
 
+extern const char kMessageCenterShowedFirstRunBalloon[];
+
 extern const char kRecoveryComponentVersion[];
 extern const char kComponentUpdaterState[];
 
@@ -885,6 +889,7 @@
 extern const char kPointsBufferedForVelocity[];
 extern const char kRailBreakProportion[];
 extern const char kRailStartProportion[];
+extern const char kScrollPredictionSeconds[];
 extern const char kSemiLongPressTimeInSeconds[];
 extern const char kTabScrubActivationDelayInMS[];
 extern const char kFlingAccelerationCurveCoefficient0[];
diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h
index 15dd718..16df123 100644
--- a/chrome/common/render_messages.h
+++ b/chrome/common/render_messages.h
@@ -355,6 +355,9 @@
                     string16 /* omnibox_font */,
                     size_t /* omnibox_font_size */)
 
+IPC_MESSAGE_ROUTED1(ChromeViewMsg_SearchBoxPromoInformation,
+                    bool /* is_app_launcher_enabled */)
+
 IPC_MESSAGE_ROUTED2(ChromeViewMsg_SearchBoxFocusChanged,
                     OmniboxFocusState /* new_focus_state */,
                     OmniboxFocusChangeReason /* reason */)
@@ -712,6 +715,11 @@
 IPC_MESSAGE_ROUTED1(ChromeViewHostMsg_SearchBoxHideBars,
                     int /* page_id */)
 
+// Sent by Instant to indicate whether the page supports voice search.
+IPC_MESSAGE_ROUTED2(ChromeViewHostMsg_SetVoiceSearchSupported,
+                    int /* page_id */,
+                    bool /* supported */)
+
 // The currently displayed PDF has an unsupported feature.
 IPC_MESSAGE_ROUTED0(ChromeViewHostMsg_PDFHasUnsupportedFeature)
 
diff --git a/chrome/common/service_messages.h b/chrome/common/service_messages.h
index 829b9f7..e868b63 100644
--- a/chrome/common/service_messages.h
+++ b/chrome/common/service_messages.h
@@ -19,14 +19,6 @@
   IPC_STRUCT_TRAITS_MEMBER(proxy_id)
 IPC_STRUCT_TRAITS_END()
 
-//-----------------------------------------------------------------------------
-// Service process messages:
-// These are messages from the browser to the service process.
-// Tell the service process to enable the cloud proxy passing in the lsid
-// of the account to be used.
-IPC_MESSAGE_CONTROL1(ServiceMsg_EnableCloudPrintProxy,
-                     std::string /* lsid */)
-
 // Tell the service process to enable the cloud proxy passing in the OAuth2
 // auth code of a robot account.
 IPC_MESSAGE_CONTROL4(ServiceMsg_EnableCloudPrintProxyWithRobot,
diff --git a/chrome/common/service_process_util_mac.mm b/chrome/common/service_process_util_mac.mm
index 4848b80..0222710 100644
--- a/chrome/common/service_process_util_mac.mm
+++ b/chrome/common/service_process_util_mac.mm
@@ -16,7 +16,7 @@
 #include "base/mac/foundation_util.h"
 #include "base/mac/mac_util.h"
 #include "base/mac/scoped_nsautorelease_pool.h"
-#include "base/memory/scoped_nsobject.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/path_service.h"
 #include "base/process_util.h"
 #include "base/strings/string_util.h"
@@ -43,7 +43,7 @@
 }
 
 NSString* GetServiceProcessLaunchDLabel() {
-  scoped_nsobject<NSString> name(
+  base::scoped_nsobject<NSString> name(
       base::mac::CFToNSCast(CopyServiceProcessLaunchDName()));
   NSString *label = [name stringByAppendingString:@".service_process"];
   base::FilePath user_data_dir;
@@ -67,7 +67,7 @@
 bool RemoveFromLaunchd() {
   // We're killing a file.
   base::ThreadRestrictions::AssertIOAllowed();
-  base::mac::ScopedCFTypeRef<CFStringRef> name(CopyServiceProcessLaunchDName());
+  base::ScopedCFTypeRef<CFStringRef> name(CopyServiceProcessLaunchDName());
   return Launchd::GetInstance()->DeletePlist(Launchd::User,
                                              Launchd::Agent,
                                              name);
@@ -100,7 +100,7 @@
 IPC::ChannelHandle GetServiceProcessChannel() {
   base::mac::ScopedNSAutoreleasePool pool;
   std::string socket_path;
-  scoped_nsobject<NSDictionary> dictionary(
+  base::scoped_nsobject<NSDictionary> dictionary(
       base::mac::CFToNSCast(Launchd::GetInstance()->CopyExports()));
   NSString *ns_socket_path =
       [dictionary objectForKey:GetServiceProcessLaunchDSocketEnvVar()];
@@ -127,8 +127,8 @@
 bool GetServiceProcessData(std::string* version, base::ProcessId* pid) {
   base::mac::ScopedNSAutoreleasePool pool;
   CFStringRef label = base::mac::NSToCFCast(GetServiceProcessLaunchDLabel());
-  scoped_nsobject<NSDictionary> launchd_conf(base::mac::CFToNSCast(
-      Launchd::GetInstance()->CopyJobDictionary(label)));
+  base::scoped_nsobject<NSDictionary> launchd_conf(
+      base::mac::CFToNSCast(Launchd::GetInstance()->CopyJobDictionary(label)));
   if (!launchd_conf.get()) {
     return false;
   }
@@ -295,8 +295,8 @@
   // We're creating directories and writing a file.
   base::ThreadRestrictions::AssertIOAllowed();
   DCHECK(autorun_command_line_.get());
-  base::mac::ScopedCFTypeRef<CFStringRef> name(CopyServiceProcessLaunchDName());
-  base::mac::ScopedCFTypeRef<CFDictionaryRef> plist(
+  base::ScopedCFTypeRef<CFStringRef> name(CopyServiceProcessLaunchDName());
+  base::ScopedCFTypeRef<CFDictionaryRef> plist(
       CreateServiceProcessLaunchdPlist(autorun_command_line_.get(), true));
   return Launchd::GetInstance()->WritePlistToFile(Launchd::User,
                                                   Launchd::Agent,
@@ -358,10 +358,10 @@
     if (GetParentFSRef(macos_fsref, &contents_fsref)) {
       FSRef bundle_fsref;
       if (GetParentFSRef(contents_fsref, &bundle_fsref)) {
-        base::mac::ScopedCFTypeRef<CFURLRef> bundle_url(
+        base::ScopedCFTypeRef<CFURLRef> bundle_url(
             CFURLCreateFromFSRef(kCFAllocatorDefault, &bundle_fsref));
         if (bundle_url.get()) {
-          base::mac::ScopedCFTypeRef<CFBundleRef> bundle(
+          base::ScopedCFTypeRef<CFBundleRef> bundle(
               CFBundleCreate(kCFAllocatorDefault, bundle_url));
           // Check to see if the bundle still has a minimal structure.
           good_bundle = CFBundleGetIdentifier(bundle) != NULL;
@@ -394,21 +394,18 @@
   }
   if (needs_shutdown || needs_restart) {
     // First deal with the plist.
-    base::mac::ScopedCFTypeRef<CFStringRef> name(
-        CopyServiceProcessLaunchDName());
+    base::ScopedCFTypeRef<CFStringRef> name(CopyServiceProcessLaunchDName());
     if (needs_restart) {
-      base::mac::ScopedCFTypeRef<CFMutableDictionaryRef> plist(
-         Launchd::GetInstance()->CreatePlistFromFile(Launchd::User,
-                                                     Launchd::Agent,
-                                                     name));
+      base::ScopedCFTypeRef<CFMutableDictionaryRef> plist(
+          Launchd::GetInstance()->CreatePlistFromFile(
+              Launchd::User, Launchd::Agent, name));
       if (plist.get()) {
         NSMutableDictionary* ns_plist = base::mac::CFToNSCast(plist);
         std::string new_path = base::mac::PathFromFSRef(executable_fsref_);
         NSString* ns_new_path = base::SysUTF8ToNSString(new_path);
         [ns_plist setObject:ns_new_path forKey:@ LAUNCH_JOBKEY_PROGRAM];
-        scoped_nsobject<NSMutableArray> args(
-            [[ns_plist objectForKey:@ LAUNCH_JOBKEY_PROGRAMARGUMENTS]
-             mutableCopy]);
+        base::scoped_nsobject<NSMutableArray> args([[ns_plist
+            objectForKey:@LAUNCH_JOBKEY_PROGRAMARGUMENTS] mutableCopy]);
         [args replaceObjectAtIndex:0 withObject:ns_new_path];
         [ns_plist setObject:args forKey:@ LAUNCH_JOBKEY_PROGRAMARGUMENTS];
         if (!Launchd::GetInstance()->WritePlistToFile(Launchd::User,
@@ -445,7 +442,7 @@
           base::mac::NSToCFCast(GetServiceProcessLaunchDLabel());
       CFErrorRef err = NULL;
       if (!Launchd::GetInstance()->RemoveJob(label, &err)) {
-        base::mac::ScopedCFTypeRef<CFErrorRef> scoped_err(err);
+        base::ScopedCFTypeRef<CFErrorRef> scoped_err(err);
         DLOG(ERROR) << "RemoveJob " << err;
         // Exiting with zero, so launchd doesn't restart the process.
         exit(0);
diff --git a/chrome/common/service_process_util_posix.h b/chrome/common/service_process_util_posix.h
index 3d3533c..2f841bb 100644
--- a/chrome/common/service_process_util_posix.h
+++ b/chrome/common/service_process_util_posix.h
@@ -68,7 +68,7 @@
 #if defined(OS_MACOSX)
   bool WatchExecutable();
 
-  base::mac::ScopedCFTypeRef<CFDictionaryRef> launchd_conf_;
+  base::ScopedCFTypeRef<CFDictionaryRef> launchd_conf_;
   base::FilePathWatcher executable_watcher_;
 #endif  // OS_MACOSX
 #if defined(OS_POSIX) && !defined(OS_MACOSX)
diff --git a/chrome/common/service_process_util_unittest.cc b/chrome/common/service_process_util_unittest.cc
index c436cde..92c5340 100644
--- a/chrome/common/service_process_util_unittest.cc
+++ b/chrome/common/service_process_util_unittest.cc
@@ -298,11 +298,11 @@
 };
 
 void DeleteFunc(const base::FilePath& file) {
-  EXPECT_TRUE(file_util::Delete(file, true));
+  EXPECT_TRUE(base::Delete(file, true));
 }
 
 void MoveFunc(const base::FilePath& from, const base::FilePath& to) {
-  EXPECT_TRUE(file_util::Move(from, to));
+  EXPECT_TRUE(base::Move(from, to));
 }
 
 void ChangeAttr(const base::FilePath& from, int mode) {
@@ -401,7 +401,7 @@
   ASSERT_TRUE(mock_launchd()->delete_called());
   std::string path(base::mac::PathFromFSRef(bundle_ref));
   base::FilePath file_path(path);
-  ASSERT_TRUE(file_util::Delete(file_path, true));
+  ASSERT_TRUE(base::Delete(file_path, true));
 }
 
 TEST_F(ServiceProcessStateFileManipulationTest, ChangeAttr) {
diff --git a/chrome/common/startup_metric_utils.cc b/chrome/common/startup_metric_utils.cc
index f73eaed..3d576e9 100644
--- a/chrome/common/startup_metric_utils.cc
+++ b/chrome/common/startup_metric_utils.cc
@@ -11,7 +11,7 @@
 #include "base/metrics/statistics_recorder.h"
 #include "base/synchronization/lock.h"
 #include "base/sys_info.h"
-#include "base/time.h"
+#include "base/time/time.h"
 
 namespace {
 
diff --git a/chrome/common/startup_metric_utils.h b/chrome/common/startup_metric_utils.h
index 3c6ea96..e82578b 100644
--- a/chrome/common/startup_metric_utils.h
+++ b/chrome/common/startup_metric_utils.h
@@ -7,7 +7,7 @@
 
 #include <string>
 
-#include "base/time.h"
+#include "base/time/time.h"
 
 // Utility functions to support metric collection for browser startup.
 
diff --git a/chrome/common/thumbnail_score.h b/chrome/common/thumbnail_score.h
index b5e2df3..486a4bc 100644
--- a/chrome/common/thumbnail_score.h
+++ b/chrome/common/thumbnail_score.h
@@ -6,7 +6,7 @@
 #define CHROME_COMMON_THUMBNAIL_SCORE_H_
 
 #include <string>
-#include "base/time.h"
+#include "base/time/time.h"
 
 // A set of metadata about a Thumbnail.
 struct ThumbnailScore {
diff --git a/chrome/common/time_format.cc b/chrome/common/time_format.cc
index 402e3b9..adc246a 100644
--- a/chrome/common/time_format.cc
+++ b/chrome/common/time_format.cc
@@ -13,7 +13,7 @@
 #include "base/stl_util.h"
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "grit/generated_resources.h"
 #include "third_party/icu/public/common/unicode/locid.h"
 #include "third_party/icu/public/i18n/unicode/datefmt.h"
diff --git a/chrome/common/time_format_unittest.cc b/chrome/common/time_format_unittest.cc
index 8d21f3c..60c84e7 100644
--- a/chrome/common/time_format_unittest.cc
+++ b/chrome/common/time_format_unittest.cc
@@ -6,7 +6,7 @@
 
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
diff --git a/chrome/common/translate/language_detection_details.h b/chrome/common/translate/language_detection_details.h
index e93504d..bb5ab56 100644
--- a/chrome/common/translate/language_detection_details.h
+++ b/chrome/common/translate/language_detection_details.h
@@ -8,7 +8,7 @@
 #include <string>
 
 #include "base/strings/string16.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "googleurl/src/gurl.h"
 #include "ipc/ipc_message_macros.h"
 
diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc
index c357943..b6d5553 100644
--- a/chrome/common/url_constants.cc
+++ b/chrome/common/url_constants.cc
@@ -65,6 +65,7 @@
 const char kChromeUIProfileSigninConfirmationURL[] =
     "chrome://profile-signin-confirmation/";
 const char kChromeUIPrintURL[] = "chrome://print/";
+const char kChromeUIRestartURL[] = "chrome://restart/";
 const char kChromeUISessionFaviconURL[] = "chrome://session-favicon/";
 const char kChromeUISettingsURL[] = "chrome://settings/";
 const char kChromeUISettingsFrameURL[] = "chrome://settings-frame/";
@@ -119,6 +120,8 @@
 #if defined(USE_AURA)
 const char kChromeUIGestureConfigURL[] = "chrome://gesture/";
 const char kChromeUIGestureConfigHost[] = "gesture";
+const char kChromeUISalsaURL[] = "chrome://salsa/";
+const char kChromeUISalsaHost[] = "salsa";
 #endif
 
 #if (defined(OS_LINUX) && defined(TOOLKIT_VIEWS)) || defined(USE_AURA)
@@ -126,6 +129,10 @@
     "chrome://tab-modal-confirm-dialog/";
 #endif
 
+#if defined(ENABLE_WEBRTC)
+const char kChromeUIWebRtcLogsURL[] = "chrome://webrtc-logs/";
+#endif
+
 // Add Chrome UI hosts here, in alphabetical order.
 // Add hosts to kChromePaths in browser_about_handler.cc to be listed by
 // chrome://chrome-urls (about:about) and the built-in AutocompleteProvider.
@@ -189,6 +196,7 @@
 const char kChromeUIPrintHost[] = "print";
 const char kChromeUIProfilerHost[] = "profiler";
 const char kChromeUIQuotaInternalsHost[] = "quota-internals";
+const char kChromeUIRestartHost[] = "restart";
 const char kChromeUISessionFaviconHost[] = "session-favicon";
 const char kChromeUISettingsHost[] = "settings";
 const char kChromeUISettingsFrameHost[] = "settings-frame";
@@ -273,6 +281,10 @@
 const char kChromeUITabModalConfirmDialogHost[] = "tab-modal-confirm-dialog";
 #endif
 
+#if defined(ENABLE_WEBRTC)
+const char kChromeUIWebRtcLogsHost[] = "webrtc-logs";
+#endif
+
 // Option sub pages.
 // Add sub page paths to kChromeSettingsSubPages in builtin_provider.cc to be
 // listed by the built-in AutocompleteProvider.
@@ -367,6 +379,10 @@
 const char kChromeEnterpriseSignInLearnMoreURL[] =
   "http://support.google.com/chromeos/bin/answer.py?hl=en&answer=1331549";
 
+const char kSupervisedUserManagementURL[] = "https://www.chrome.com/manage";
+
+const char kSupervisedUserManagementDisplayURL[] = "www.chrome.com/manage";
+
 const char kSettingsSearchHelpURL[] =
 #if defined(OS_CHROMEOS)
     "https://support.google.com/chromeos/?p=settings_search_help";
@@ -488,6 +504,9 @@
     "https://support.google.com/chromeos/bin/answer.py?answer=2535613";
 #endif
 
+const char kNotificationsHelpURL[] =
+    "https://support.google.com/chrome/?p=ui_notifications";
+
 const char* const kChromeDebugURLs[] = {
   content::kChromeUICrashURL,
   content::kChromeUIKillURL,
@@ -497,7 +516,8 @@
   content::kChromeUIGpuCrashURL,
   content::kChromeUIGpuHangURL,
   content::kChromeUIPpapiFlashCrashURL,
-  content::kChromeUIPpapiFlashHangURL
+  content::kChromeUIPpapiFlashHangURL,
+  chrome::kChromeUIRestartURL
 };
 const int kNumberOfChromeDebugURLs =
     static_cast<int>(arraysize(kChromeDebugURLs));
diff --git a/chrome/common/url_constants.h b/chrome/common/url_constants.h
index 46790fb..7b686f1 100644
--- a/chrome/common/url_constants.h
+++ b/chrome/common/url_constants.h
@@ -61,6 +61,7 @@
 extern const char kChromeUIPolicyURL[];
 extern const char kChromeUIProfileSigninConfirmationURL[];
 extern const char kChromeUIPrintURL[];
+extern const char kChromeUIRestartURL[];
 extern const char kChromeUISessionFaviconURL[];
 extern const char kChromeUISettingsURL[];
 extern const char kChromeUISettingsFrameURL[];
@@ -113,12 +114,18 @@
 #if defined(USE_AURA)
 extern const char kChromeUIGestureConfigURL[];
 extern const char kChromeUIGestureConfigHost[];
+extern const char kChromeUISalsaURL[];
+extern const char kChromeUISalsaHost[];
 #endif
 
 #if (defined(OS_LINUX) && defined(TOOLKIT_VIEWS)) || defined(USE_AURA)
 extern const char kChromeUITabModalConfirmDialogURL[];
 #endif
 
+#if defined(ENABLE_WEBRTC)
+extern const char kChromeUIWebRtcLogsURL[];
+#endif
+
 // chrome components of URLs. Should be kept in sync with the full URLs above.
 extern const char kChromeUIAboutHost[];
 extern const char kChromeUIAboutPageFrameHost[];
@@ -180,6 +187,7 @@
 extern const char kChromeUIPrintHost[];
 extern const char kChromeUIProfilerHost[];
 extern const char kChromeUIQuotaInternalsHost[];
+extern const char kChromeUIRestartHost[];
 extern const char kChromeUISessionFaviconHost[];
 extern const char kChromeUISettingsHost[];
 extern const char kChromeUISettingsFrameHost[];
@@ -263,6 +271,10 @@
 extern const char kChromeUITabModalConfirmDialogHost[];
 #endif
 
+#if defined(ENABLE_WEBRTC)
+extern const char kChromeUIWebRtcLogsHost[];
+#endif
+
 // Options sub-pages.
 extern const char kAutofillSubPage[];
 extern const char kClearBrowserDataSubPage[];
@@ -317,6 +329,13 @@
 // "Learn more" URL for the enterprise sign-in confirmation dialog.
 extern const char kChromeEnterpriseSignInLearnMoreURL[];
 
+// Management URL for the supervised users.
+extern const char kSupervisedUserManagementURL[];
+
+// Management URL for the supervised users - version without scheme, used
+// for display.
+extern const char kSupervisedUserManagementDisplayURL[];
+
 // Help URL for the settings page's search feature.
 extern const char kSettingsSearchHelpURL[];
 
@@ -396,6 +415,8 @@
 extern const char kLearnMoreEnterpriseURL[];
 #endif
 
+extern const char kNotificationsHelpURL[];
+
 // "Debug" pages which are dangerous and not for general consumption.
 extern const char* const kChromeDebugURLs[];
 extern const int kNumberOfChromeDebugURLs;
diff --git a/chrome/common_constants.gyp b/chrome/common_constants.gyp
index 7020f80..b0ee2cd 100644
--- a/chrome/common_constants.gyp
+++ b/chrome/common_constants.gyp
@@ -67,6 +67,7 @@
       ],
       'dependencies': [
         '../base/base.gyp:base',
+        '../components/nacl_common.gyp:nacl_switches',
         '../third_party/widevine/cdm/widevine_cdm.gyp:widevine_cdm_version_h',
       ],
       'target_conditions': [
@@ -96,6 +97,7 @@
           ],
           'dependencies': [
             '../base/base.gyp:base_nacl_win64',
+            '../components/nacl_common.gyp:nacl_switches_win64',
             '../third_party/widevine/cdm/widevine_cdm.gyp:widevine_cdm_version_h',
           ],
           'defines': [
diff --git a/chrome/installer/gcapi/gcapi.cc b/chrome/installer/gcapi/gcapi.cc
index 23dbd9c..002e370 100644
--- a/chrome/installer/gcapi/gcapi.cc
+++ b/chrome/installer/gcapi/gcapi.cc
@@ -29,7 +29,7 @@
 #include "base/strings/string16.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/win/registry.h"
 #include "base/win/scoped_com_initializer.h"
 #include "base/win/scoped_comptr.h"
diff --git a/chrome/installer/gcapi/gcapi_dll.cc b/chrome/installer/gcapi/gcapi_dll.cc
index 744321a..cb512e4 100644
--- a/chrome/installer/gcapi/gcapi_dll.cc
+++ b/chrome/installer/gcapi/gcapi_dll.cc
@@ -22,12 +22,9 @@
   if (reason == DLL_PROCESS_ATTACH) {
     g_exit_manager = new base::AtExitManager();
     CommandLine::Init(0, NULL);
-    logging::InitLogging(
-        NULL,
-        logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG,
-        logging::LOCK_LOG_FILE,
-        logging::DELETE_OLD_LOG_FILE,
-        logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS);
+    logging::LoggingSettings settings;
+    settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
+    logging::InitLogging(settings);
   } else if (reason == DLL_PROCESS_DETACH) {
     CommandLine::Reset();
     delete g_exit_manager;
diff --git a/chrome/installer/gcapi/gcapi_last_run_test.cc b/chrome/installer/gcapi/gcapi_last_run_test.cc
index 58ff0b0..ba57e59 100644
--- a/chrome/installer/gcapi/gcapi_last_run_test.cc
+++ b/chrome/installer/gcapi/gcapi_last_run_test.cc
@@ -11,7 +11,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/test_reg_util_win.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/win/registry.h"
 #include "chrome/installer/gcapi/gcapi.h"
 #include "chrome/installer/util/google_update_constants.h"
diff --git a/chrome/installer/gcapi/gcapi_omaha_experiment.cc b/chrome/installer/gcapi/gcapi_omaha_experiment.cc
index c30bdee..5314922 100644
--- a/chrome/installer/gcapi/gcapi_omaha_experiment.cc
+++ b/chrome/installer/gcapi/gcapi_omaha_experiment.cc
@@ -6,7 +6,7 @@
 
 #include "base/strings/string16.h"
 #include "base/strings/stringprintf.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/installer/gcapi/gcapi.h"
 #include "chrome/installer/util/google_update_experiment_util.h"
 #include "chrome/installer/util/google_update_settings.h"
diff --git a/chrome/installer/gcapi/gcapi_reactivation.cc b/chrome/installer/gcapi/gcapi_reactivation.cc
index 8609090..3d576c7 100644
--- a/chrome/installer/gcapi/gcapi_reactivation.cc
+++ b/chrome/installer/gcapi/gcapi_reactivation.cc
@@ -4,10 +4,10 @@
 
 #include "chrome/installer/gcapi/gcapi_reactivation.h"
 
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/win/registry.h"
-#include "chrome/installer/util/google_update_constants.h"
 #include "chrome/installer/gcapi/gcapi.h"
+#include "chrome/installer/util/google_update_constants.h"
 
 using base::Time;
 using base::win::RegKey;
diff --git a/chrome/installer/gcapi/gcapi_reactivation_test.cc b/chrome/installer/gcapi/gcapi_reactivation_test.cc
index e9b57a3..cc552df 100644
--- a/chrome/installer/gcapi/gcapi_reactivation_test.cc
+++ b/chrome/installer/gcapi/gcapi_reactivation_test.cc
@@ -10,7 +10,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/test_reg_util_win.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/win/registry.h"
 #include "chrome/installer/gcapi/gcapi.h"
 #include "chrome/installer/gcapi/gcapi_omaha_experiment.h"
diff --git a/chrome/installer/launcher_support/chrome_launcher_support.cc b/chrome/installer/launcher_support/chrome_launcher_support.cc
index 14321cc..181007d 100644
--- a/chrome/installer/launcher_support/chrome_launcher_support.cc
+++ b/chrome/installer/launcher_support/chrome_launcher_support.cc
@@ -11,6 +11,7 @@
 #include "base/file_util.h"
 #include "base/files/file_path.h"
 #include "base/logging.h"
+#include "base/process_util.h"
 #include "base/strings/string16.h"
 #include "base/win/registry.h"
 
@@ -142,6 +143,24 @@
 
 }  // namespace
 
+void UninstallLegacyAppLauncher(InstallationLevel level) {
+  base::FilePath setup_exe(GetSetupExeFromRegistry(level, kAppHostAppId));
+  if (setup_exe.empty())
+    return;
+  string16 uninstall_arguments;
+  if (GetClientStateValue(level,
+                          kAppHostAppId,
+                          kUninstallArgumentsField,
+                          &uninstall_arguments)) {
+    CommandLine uninstall_cmd = CommandLine::FromString(
+        L"\"" + setup_exe.value() + L"\" " + uninstall_arguments);
+
+    VLOG(1) << "Uninstalling legacy app launcher with command line: "
+            << uninstall_cmd.GetCommandLineString();
+    base::LaunchProcess(uninstall_cmd, base::LaunchOptions(), NULL);
+  }
+}
+
 base::FilePath GetSetupExeForInstallationLevel(InstallationLevel level) {
   // Look in the registry for Chrome Binaries first.
   base::FilePath setup_exe_path(
diff --git a/chrome/installer/launcher_support/chrome_launcher_support.h b/chrome/installer/launcher_support/chrome_launcher_support.h
index 7c5bc68..5a948db 100644
--- a/chrome/installer/launcher_support/chrome_launcher_support.h
+++ b/chrome/installer/launcher_support/chrome_launcher_support.h
@@ -52,6 +52,11 @@
 // The file path returned (if any) is guaranteed to exist.
 base::FilePath GetAnyAppHostPath();
 
+// Uninstalls the legacy app launcher by launching setup.exe with the uninstall
+// arguments from the App Launcher ClientState registry key. The uninstall will
+// run asynchronously.
+void UninstallLegacyAppLauncher(InstallationLevel level);
+
 // Returns true if App Host is installed (system-level or user-level),
 // or in the same directory as the current executable.
 bool IsAppHostPresent();
diff --git a/chrome/installer/linux/common/installer.include b/chrome/installer/linux/common/installer.include
index ef2914f..c5ec0f6 100644
--- a/chrome/installer/linux/common/installer.include
+++ b/chrome/installer/linux/common/installer.include
@@ -56,7 +56,7 @@
     -e "s#@@CHANNEL@@#${CHANNEL}#g" \
     -e "s#@@COMPANY_FULLNAME@@#${COMPANY_FULLNAME}#g" \
     -e "s#@@VERSION@@#${VERSION}#g" \
-    -e "s#@@REVISION@@#${REVISION}#g" \
+    -e "s#@@PACKAGE_RELEASE@@#${PACKAGE_RELEASE}#g" \
     -e "s#@@VERSIONFULL@@#${VERSIONFULL}#g" \
     -e "s#@@INSTALLDIR@@#${INSTALLDIR}#g" \
     -e "s#@@BUILDDIR@@#${BUILDDIR}#g" \
@@ -89,24 +89,16 @@
 }
 
 get_version_info() {
-  # Default to a bogus low version, so if somebody creates and installs
-  # a package with no version info, it won't prevent upgrading when
-  # trying to install a properly versioned package (i.e. a proper
-  # package will always be "newer").
-  VERSION="0.0.0.0"
-  # Use epoch timestamp so packages with bogus versions still increment
-  # and will upgrade older bogus-versioned packages.
-  REVISION=$(date +"%s")
-  # Default to non-official build since official builds set this
-  # properly.
-  OFFICIAL_BUILD=0
-
-  VERSIONFILE="${BUILDDIR}/installer/version.txt"
-  if [ -f "${VERSIONFILE}" ]; then
-    source "${VERSIONFILE}"
-    VERSION="${MAJOR}.${MINOR}.${BUILD}.${PATCH}"
-    REVISION="${LASTCHANGE}"
-  fi
+  source "${BUILDDIR}/installer/version.txt"
+  VERSION="${MAJOR}.${MINOR}.${BUILD}.${PATCH}"
+  # TODO(phajdan.jr): Provide a mechanism to pass a different package
+  # release number if needed. The meaning of it is to bump it for
+  # packaging-only changes while the underlying software has the same version.
+  # This corresponds to the Release field in RPM spec files and debian_revision
+  # component of the Version field for DEB control file.
+  # Generally with Chrome's fast release cycle it'd be more hassle to try
+  # to bump this number between releases.
+  PACKAGE_RELEASE="1"
 }
 
 stage_install_common() {
diff --git a/chrome/installer/linux/debian/build.sh b/chrome/installer/linux/debian/build.sh
index d35f6e2..d9d98a1 100755
--- a/chrome/installer/linux/debian/build.sh
+++ b/chrome/installer/linux/debian/build.sh
@@ -224,7 +224,7 @@
 source ${BUILDDIR}/installer/common/installer.include
 
 get_version_info
-VERSIONFULL="${VERSION}-r${REVISION}"
+VERSIONFULL="${VERSION}-${PACKAGE_RELEASE}"
 
 if [ "$CHROMIUM_BUILD" = "_google_chrome" ]; then
   source "${BUILDDIR}/installer/common/google-chrome.info"
@@ -276,13 +276,12 @@
 
 # Compare the expected dependency list to the generate list.
 BAD_DIFF=0
-diff "$SCRIPTDIR/expected_deps_$TARGETARCH" actual || BAD_DIFF=1
+diff "$SCRIPTDIR/expected_deps" actual || BAD_DIFF=1
 if [ $BAD_DIFF -ne 0 ] && [ -z "${IGNORE_DEPS_CHANGES:-}" ]; then
   echo
   echo "ERROR: Shared library dependencies changed!"
   echo "If this is intentional, please update:"
-  echo "chrome/installer/linux/debian/expected_deps_ia32"
-  echo "chrome/installer/linux/debian/expected_deps_x64"
+  echo "chrome/installer/linux/debian/expected_deps"
   echo
   exit $BAD_DIFF
 fi
diff --git a/chrome/installer/linux/debian/expected_deps_x64 b/chrome/installer/linux/debian/expected_deps
similarity index 100%
rename from chrome/installer/linux/debian/expected_deps_x64
rename to chrome/installer/linux/debian/expected_deps
diff --git a/chrome/installer/linux/debian/expected_deps_ia32 b/chrome/installer/linux/debian/expected_deps_ia32
deleted file mode 100644
index ed34748..0000000
--- a/chrome/installer/linux/debian/expected_deps_ia32
+++ /dev/null
@@ -1,29 +0,0 @@
-gconf-service
-lib32gcc1 (>= 1:4.1.1)
-lib32stdc++6 (>= 4.6)
-libasound2 (>= 1.0.23)
-libatk1.0-0 (>= 1.12.4)
-libc6 (>= 2.3)
-libc6-i386 (>= 2.11)
-libcairo2 (>= 1.6.0)
-libcups2 (>= 1.4.0)
-libdbus-1-3 (>= 1.2.14)
-libexpat1 (>= 1.95.8)
-libfontconfig1 (>= 2.8.0)
-libfreetype6 (>= 2.3.9)
-libgconf-2-4 (>= 2.31.1)
-libgcrypt11 (>= 1.4.5)
-libgdk-pixbuf2.0-0 (>= 2.22.0)
-libglib2.0-0 (>= 2.18.0)
-libgtk2.0-0 (>= 2.24.0)
-libnspr4 (>= 1.8.0.10)
-libnss3 (>= 3.12.6)
-libpango1.0-0 (>= 1.22.0)
-libudev0 (>= 147)
-libx11-6 (>= 2:1.4.99.1)
-libxcomposite1 (>= 1:0.3-1)
-libxdamage1 (>= 1:1.1)
-libxext6
-libxfixes3
-libxrender1
-libxss1
diff --git a/chrome/installer/linux/rpm/build.sh b/chrome/installer/linux/rpm/build.sh
index 68a5f41..544a46a 100755
--- a/chrome/installer/linux/rpm/build.sh
+++ b/chrome/installer/linux/rpm/build.sh
@@ -145,7 +145,7 @@
     --define "_binary_payload w9.bzdio" \
     --define "__os_install_post  %{nil}" \
     "${SPEC}"
-  PKGNAME="${PACKAGE}-${CHANNEL}-${VERSION}-${REVISION}"
+  PKGNAME="${PACKAGE}-${CHANNEL}-${VERSION}-${PACKAGE_RELEASE}"
   mv "$RPMBUILD_DIR/RPMS/$ARCHITECTURE/${PKGNAME}.${ARCHITECTURE}.rpm" \
      "${OUTPUTDIR}"
   # Make sure the package is world-readable, otherwise it causes problems when
diff --git a/chrome/installer/linux/rpm/chrome.spec.template b/chrome/installer/linux/rpm/chrome.spec.template
index 3ec7362..c4fc91c 100644
--- a/chrome/installer/linux/rpm/chrome.spec.template
+++ b/chrome/installer/linux/rpm/chrome.spec.template
@@ -9,7 +9,7 @@
 License         : Multiple, see @@PRODUCTURL@@
 Name            : @@PACKAGE@@-@@CHANNEL@@
 Version         : @@VERSION@@
-Release         : @@REVISION@@
+Release         : @@PACKAGE_RELEASE@@
 Group           : Applications/Internet
 Vendor          : @@COMPANY_FULLNAME@@
 Url             : @@PRODUCTURL@@
diff --git a/chrome/installer/setup/chrome_frame_ready_mode.cc b/chrome/installer/setup/chrome_frame_ready_mode.cc
index e7f14da..74f5f7c 100644
--- a/chrome/installer/setup/chrome_frame_ready_mode.cc
+++ b/chrome/installer/setup/chrome_frame_ready_mode.cc
@@ -10,7 +10,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/win/registry.h"
 #include "chrome/installer/setup/install.h"
 #include "chrome/installer/setup/install_worker.h"
diff --git a/chrome/installer/setup/install.cc b/chrome/installer/setup/install.cc
index 5c70174..163c6ea 100644
--- a/chrome/installer/setup/install.cc
+++ b/chrome/installer/setup/install.cc
@@ -257,7 +257,7 @@
                              shortcut_level, &uninstall_shortcut_path);
   uninstall_shortcut_path = uninstall_shortcut_path.Append(
       dist->GetUninstallLinkName() + installer::kLnkExt);
-  file_util::Delete(uninstall_shortcut_path, false);
+  base::Delete(uninstall_shortcut_path, false);
 
   if (installer_state.system_install()) {
     ShellUtil::RemoveShortcuts(
diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc
index 735be3f..7259c4d 100644
--- a/chrome/installer/setup/setup_main.cc
+++ b/chrome/installer/setup/setup_main.cc
@@ -14,6 +14,7 @@
 #include "base/command_line.h"
 #include "base/file_util.h"
 #include "base/file_version_info.h"
+#include "base/files/file_path.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/path_service.h"
 #include "base/process_util.h"
@@ -491,7 +492,6 @@
                                InstallerState* installer_state,
                                installer::InstallStatus* status) {
   if (installer_state->FindProduct(BrowserDistribution::CHROME_APP_HOST)) {
-
     if (!installer_state->is_multi_install()) {
       LOG(DFATAL) << "App Launcher requires multi install";
       *status = installer::APP_HOST_REQUIRES_MULTI_INSTALL;
@@ -507,7 +507,6 @@
       installer_state->WriteInstallerResult(*status, 0, NULL);
       return false;
     }
-
   }
 
   return true;
@@ -941,7 +940,7 @@
   if (cmd_line.HasSwitch(installer::switches::kInstallerData)) {
     base::FilePath prefs_path(cmd_line.GetSwitchValuePath(
         installer::switches::kInstallerData));
-    if (!file_util::Delete(prefs_path, true)) {
+    if (!base::Delete(prefs_path, true)) {
       LOG(ERROR) << "Failed deleting master preferences file "
                  << prefs_path.value()
                  << ", scheduling for deletion after reboot.";
@@ -1477,6 +1476,27 @@
   } else if (cmd_line.HasSwitch(installer::switches::kChromeFrameQuickEnable)) {
     *exit_code = installer::ChromeFrameQuickEnable(original_state,
                                                    installer_state);
+  } else if (cmd_line.HasSwitch(installer::switches::kPatch)) {
+    const std::string patch_type_str(
+        cmd_line.GetSwitchValueASCII(installer::switches::kPatch));
+    const base::FilePath input_file(
+        cmd_line.GetSwitchValuePath(installer::switches::kInputFile));
+    const base::FilePath patch_file(
+        cmd_line.GetSwitchValuePath(installer::switches::kPatchFile));
+    const base::FilePath output_file(
+        cmd_line.GetSwitchValuePath(installer::switches::kOutputFile));
+
+    if (patch_type_str == installer::kCourgette) {
+      *exit_code = installer::CourgettePatchFiles(input_file,
+                                                  patch_file,
+                                                  output_file);
+    } else if (patch_type_str == installer::kBsdiff) {
+      *exit_code = installer::BsdiffPatchFiles(input_file,
+                                               patch_file,
+                                               output_file);
+    } else {
+      *exit_code = installer::PATCH_INVALID_ARGUMENTS;
+    }
   } else {
     handled = false;
   }
diff --git a/chrome/installer/setup/setup_util.cc b/chrome/installer/setup/setup_util.cc
index ef0f836..d679274 100644
--- a/chrome/installer/setup/setup_util.cc
+++ b/chrome/installer/setup/setup_util.cc
@@ -24,6 +24,7 @@
 #include "chrome/installer/util/util_constants.h"
 #include "chrome/installer/util/work_item.h"
 #include "courgette/courgette.h"
+#include "courgette/third_party/bsdiff.h"
 #include "third_party/bspatch/mbspatch.h"
 
 namespace installer {
@@ -86,12 +87,59 @@
 
 }  // namespace
 
+int CourgettePatchFiles(const base::FilePath& src,
+                        const base::FilePath& patch,
+                        const base::FilePath& dest) {
+  VLOG(1) << "Applying Courgette patch " << patch.value()
+          << " to file " << src.value()
+          << " and generating file " << dest.value();
+
+  if (src.empty() || patch.empty() || dest.empty())
+    return installer::PATCH_INVALID_ARGUMENTS;
+
+  const courgette::Status patch_status =
+      courgette::ApplyEnsemblePatch(src.value().c_str(),
+                                    patch.value().c_str(),
+                                    dest.value().c_str());
+  const int exit_code = (patch_status != courgette::C_OK) ?
+      static_cast<int>(patch_status) + kCourgetteErrorOffset : 0;
+
+  LOG_IF(ERROR, exit_code)
+      << "Failed to apply Courgette patch " << patch.value()
+      << " to file " << src.value() << " and generating file " << dest.value()
+      << ". err=" << exit_code;
+
+  return exit_code;
+}
+
+int BsdiffPatchFiles(const base::FilePath& src,
+                     const base::FilePath& patch,
+                     const base::FilePath& dest) {
+  VLOG(1) << "Applying bsdiff patch " << patch.value()
+          << " to file " << src.value()
+          << " and generating file " << dest.value();
+
+  if (src.empty() || patch.empty() || dest.empty())
+    return installer::PATCH_INVALID_ARGUMENTS;
+
+  const int patch_status = courgette::ApplyBinaryPatch(src, patch, dest);
+  const int exit_code = patch_status != OK ?
+                        patch_status + kBsdiffErrorOffset : 0;
+
+  LOG_IF(ERROR, exit_code)
+      << "Failed to apply bsdiff patch " << patch.value()
+      << " to file " << src.value() << " and generating file " << dest.value()
+      << ". err=" << exit_code;
+
+  return exit_code;
+}
+
 int ApplyDiffPatch(const base::FilePath& src,
                    const base::FilePath& patch,
                    const base::FilePath& dest,
                    const InstallerState* installer_state) {
-  VLOG(1) << "Applying patch " << patch.value() << " to file " << src.value()
-          << " and generating file " << dest.value();
+  VLOG(1) << "Applying patch " << patch.value() << " to file "
+          << src.value() << " and generating file " << dest.value();
 
   if (installer_state != NULL)
     installer_state->UpdateStage(installer::ENSEMBLE_PATCHING);
@@ -105,8 +153,10 @@
   if (patch_status == courgette::C_OK)
     return 0;
 
-  VLOG(1) << "Failed to apply patch " << patch.value()
-          << " using courgette. err=" << patch_status;
+  LOG(ERROR)
+        << "Failed to apply patch " << patch.value()
+        << " to file " << src.value() << " and generating file " << dest.value()
+        << " using courgette. err=" << patch_status;
 
   // If we ran out of memory or disk space, then these are likely the errors
   // we will see.  If we run into them, return an error and stay on the
@@ -119,8 +169,16 @@
   if (installer_state != NULL)
     installer_state->UpdateStage(installer::BINARY_PATCHING);
 
-  return ApplyBinaryPatch(src.value().c_str(), patch.value().c_str(),
-                          dest.value().c_str());
+  int binary_patch_status = ApplyBinaryPatch(src.value().c_str(),
+                                             patch.value().c_str(),
+                                             dest.value().c_str());
+
+  LOG_IF(ERROR, binary_patch_status != OK)
+      << "Failed to apply patch " << patch.value()
+      << " to file " << src.value() << " and generating file " << dest.value()
+      << " using bsdiff. err=" << binary_patch_status;
+
+  return binary_patch_status;
 }
 
 Version* GetMaxVersionFromArchiveDir(const base::FilePath& chrome_path) {
diff --git a/chrome/installer/setup/setup_util.h b/chrome/installer/setup/setup_util.h
index 2a7530a..97bf4d4 100644
--- a/chrome/installer/setup/setup_util.h
+++ b/chrome/installer/setup/setup_util.h
@@ -2,7 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
-// This file declares util functions for setup project.
+// This file declares util functions for setup project. It also declares a
+// few functions that the Chrome component updater uses for patching binary
+// deltas.
 
 #ifndef CHROME_INSTALLER_SETUP_SETUP_UTIL_H_
 #define CHROME_INSTALLER_SETUP_SETUP_UTIL_H_
@@ -28,15 +30,32 @@
 class InstallerState;
 class ProductState;
 
-// Apply a diff patch to source file. First tries to apply it using courgette
-// since it checks for courgette header and fails quickly. If that fails
-// tries to apply the patch using regular bsdiff. Returns status code.
+// Apply a diff patch to source file. First tries to apply it using Courgette
+// since it checks for Courgette header and fails quickly. If that fails
+// tries to apply the patch using regular bsdiff. Returns status code as
+// defined by the bsdiff code (see third_party/bspatch/mbspatch.h for the
+// definitions of the codes).
 // The installer stage is updated if |installer_state| is non-NULL.
 int ApplyDiffPatch(const base::FilePath& src,
                    const base::FilePath& patch,
                    const base::FilePath& dest,
                    const InstallerState* installer_state);
 
+// Applies a patch file to source file using Courgette. Returns 0 in case of
+// success. In case of errors, it returns kCourgetteErrorOffset + a Courgette
+// status code, as defined in courgette/courgette.h
+int CourgettePatchFiles(const base::FilePath& src,
+                        const base::FilePath& patch,
+                        const base::FilePath& dest);
+
+// Applies a patch file to source file using bsdiff. This function uses
+// Courgette's flavor of bsdiff. Returns 0 in case of success, or
+// kBsdiffErrorOffset + a bsdiff status code in case of errors.
+// See courgette/third_party/bsdiff.h for details.
+int BsdiffPatchFiles(const base::FilePath& src,
+                     const base::FilePath& patch,
+                     const base::FilePath& dest);
+
 // Find the version of Chrome from an install source directory.
 // Chrome_path should contain at least one version folder.
 // Returns the maximum version found or NULL if no version is found.
diff --git a/chrome/installer/setup/setup_util_unittest.cc b/chrome/installer/setup/setup_util_unittest.cc
index c699b1b..ce3e13c 100644
--- a/chrome/installer/setup/setup_util_unittest.cc
+++ b/chrome/installer/setup/setup_util_unittest.cc
@@ -15,7 +15,7 @@
 #include "base/path_service.h"
 #include "base/process_util.h"
 #include "base/threading/platform_thread.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/win/scoped_handle.h"
 #include "base/win/windows_version.h"
 #include "chrome/common/chrome_paths.h"
@@ -124,7 +124,7 @@
       installer::GetMaxVersionFromArchiveDir(test_dir_.path()));
   ASSERT_EQ(version->GetString(), "1.0.0.0");
 
-  file_util::Delete(chrome_dir, true);
+  base::Delete(chrome_dir, true);
   ASSERT_FALSE(file_util::PathExists(chrome_dir));
   ASSERT_TRUE(installer::GetMaxVersionFromArchiveDir(test_dir_.path()) == NULL);
 
diff --git a/chrome/installer/setup/uninstall.cc b/chrome/installer/setup/uninstall.cc
index 1232f19..a39f153 100644
--- a/chrome/installer/setup/uninstall.cc
+++ b/chrome/installer/setup/uninstall.cc
@@ -270,7 +270,7 @@
       continue;
 
     VLOG(1) << "Deleting installer path " << to_delete.value();
-    if (!file_util::Delete(to_delete, true)) {
+    if (!base::Delete(to_delete, true)) {
       LOG(ERROR) << "Failed to delete path: " << to_delete.value();
       success = false;
     }
@@ -402,7 +402,7 @@
   if (!file_util::IsDirectoryEmpty(path))
     return DELETE_NOT_EMPTY;
 
-  if (file_util::Delete(path, true))
+  if (base::Delete(path, true))
     return DELETE_SUCCEEDED;
 
   LOG(ERROR) << "Failed to delete folder: " << path.value();
@@ -449,7 +449,7 @@
   for (size_t i = 0; i < local_state_folders.size(); ++i) {
     const base::FilePath& user_local_state = local_state_folders[i];
     VLOG(1) << "Deleting user profile " << user_local_state.value();
-    if (!file_util::Delete(user_local_state, true)) {
+    if (!base::Delete(user_local_state, true)) {
       LOG(ERROR) << "Failed to delete user profile dir: "
                  << user_local_state.value();
       if (schedule_on_failure) {
@@ -495,12 +495,12 @@
       PLOG(ERROR) << "Failed to change the current directory.";
 
     VLOG(1) << "Attempting to move setup to: " << temp_file.value();
-    ret = file_util::Move(setup_exe, temp_file);
+    ret = base::Move(setup_exe, temp_file);
     PLOG_IF(ERROR, !ret) << "Failed to move setup to " << temp_file.value();
 
     // We cannot delete the file right away, but try to delete it some other
     // way. Either with the help of a different process or the system.
-    if (ret && !file_util::DeleteAfterReboot(temp_file)) {
+    if (ret && !base::DeleteAfterReboot(temp_file)) {
       static const uint32 kDeleteAfterMs = 10 * 1000;
       installer::DeleteFileFromTempProcess(temp_file, kDeleteAfterMs);
     }
@@ -543,7 +543,7 @@
   DeleteResult result = DELETE_SUCCEEDED;
 
   base::FilePath app_host_exe(target_path.Append(installer::kChromeAppHostExe));
-  if (!file_util::Delete(app_host_exe, false)) {
+  if (!base::Delete(app_host_exe, false)) {
     result = DELETE_FAILED;
     LOG(ERROR) << "Failed to delete path: " << app_host_exe.value();
   }
@@ -589,7 +589,7 @@
     }
 
     VLOG(1) << "Deleting install path " << to_delete.value();
-    if (!file_util::Delete(to_delete, true)) {
+    if (!base::Delete(to_delete, true)) {
       LOG(ERROR) << "Failed to delete path (1st try): " << to_delete.value();
       if (installer_state.FindProduct(BrowserDistribution::CHROME_FRAME)) {
         // We don't try killing Chrome processes for Chrome Frame builds since
@@ -605,7 +605,7 @@
         // Try closing any running Chrome processes and deleting files once
         // again.
         CloseAllChromeProcesses();
-        if (!file_util::Delete(to_delete, true)) {
+        if (!base::Delete(to_delete, true)) {
           LOG(ERROR) << "Failed to delete path (2nd try): "
                      << to_delete.value();
           result = DELETE_FAILED;
@@ -1351,7 +1351,7 @@
   // Try and delete the preserved local state once the post-install
   // operations are complete.
   if (!backup_state_file.empty())
-    file_util::Delete(backup_state_file, false);
+    base::Delete(backup_state_file, false);
 
   return ret;
 }
diff --git a/chrome/installer/test/alternate_version_generator.cc b/chrome/installer/test/alternate_version_generator.cc
index 54458fd..3cd067a 100644
--- a/chrome/installer/test/alternate_version_generator.cc
+++ b/chrome/installer/test/alternate_version_generator.cc
@@ -75,7 +75,7 @@
  public:
   ScopedTempDirectory() { }
   ~ScopedTempDirectory() {
-    if (!directory_.empty() && !file_util::Delete(directory_, true)) {
+    if (!directory_.empty() && !base::Delete(directory_, true)) {
       LOG(DFATAL) << "Failed deleting temporary directory \""
                   << directory_.value() << "\"";
     }
@@ -447,8 +447,8 @@
 
   // Change the versioned directory.
   base::FilePath chrome_bin = work_dir.Append(&kChromeBin[0]);
-  doing_great = file_util::Move(chrome_bin.Append(ctx.current_version_str),
-                                chrome_bin.Append(ctx.new_version_str));
+  doing_great = base::Move(chrome_bin.Append(ctx.current_version_str),
+                           chrome_bin.Append(ctx.new_version_str));
 
   if (doing_great) {
     // Report the version numbers if requested.
@@ -602,9 +602,9 @@
 
   // Get rid of intermediate files
   base::FilePath chrome_7z(chrome_7z_name);
-  if (!file_util::Delete(chrome_7z, false) ||
-      !file_util::Delete(chrome_packed_7z, false) ||
-      !file_util::Delete(setup_ex_, false)) {
+  if (!base::Delete(chrome_7z, false) ||
+      !base::Delete(chrome_packed_7z, false) ||
+      !base::Delete(setup_ex_, false)) {
     LOG(DFATAL) << "Failed deleting intermediate files";
     return false;
   }
@@ -649,7 +649,7 @@
   }
 
   // Finally, move the updated mini_installer into place.
-  return file_util::Move(mini_installer, target_path);
+  return base::Move(mini_installer, target_path);
 }
 
 bool GenerateAlternatePEFileVersion(const base::FilePath& original_file,
diff --git a/chrome/installer/test/upgrade_test.cc b/chrome/installer/test/upgrade_test.cc
index ee02414..7c9f9bd 100644
--- a/chrome/installer/test/upgrade_test.cc
+++ b/chrome/installer/test/upgrade_test.cc
@@ -32,7 +32,7 @@
 
   // Clean up by deleting the created newer version of mini_installer.exe.
   static void TearDownTestCase() {
-    EXPECT_TRUE(file_util::Delete(next_mini_installer_path_, false));
+    EXPECT_TRUE(base::Delete(next_mini_installer_path_, false));
   }
  private:
   static base::FilePath next_mini_installer_path_;
diff --git a/chrome/installer/tools/validate_installation_main.cc b/chrome/installer/tools/validate_installation_main.cc
index 7cc1161..1fd86de 100644
--- a/chrome/installer/tools/validate_installation_main.cc
+++ b/chrome/installer/tools/validate_installation_main.cc
@@ -61,12 +61,12 @@
 
 ConsoleLogHelper::ConsoleLogHelper() : log_file_path_(GetLogFilePath()) {
   LOG_ASSERT(old_message_handler_ == NULL);
-  logging::InitLogging(
-      log_file_path_.value().c_str(),
-      logging::LOG_ONLY_TO_FILE,
-      logging::DONT_LOCK_LOG_FILE,
-      logging::DELETE_OLD_LOG_FILE,
-      logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS);
+  logging::LoggingSettings settings;
+  settings.logging_dest = logging::LOG_TO_FILE;
+  settings.log_file = log_file_path_.value().c_str();
+  settings.lock_log = logging::DONT_LOCK_LOG_FILE;
+  settings.delete_old = logging::DELETE_OLD_LOG_FILE;
+  logging::InitLogging(settings);
 
   old_message_handler_ = logging::GetLogMessageHandler();
   logging::SetLogMessageHandler(&DumpLogMessage);
@@ -81,7 +81,7 @@
   // Delete the log file if it wasn't written to (this is expected).
   int64 file_size = 0;
   if (file_util::GetFileSize(log_file_path_, &file_size) && file_size == 0)
-    file_util::Delete(log_file_path_, false);
+    base::Delete(log_file_path_, false);
 }
 
 // Returns the path to the log file to create.  The file should be empty at
diff --git a/chrome/installer/util/copy_tree_work_item.cc b/chrome/installer/util/copy_tree_work_item.cc
index 7f82e6a..118a217 100644
--- a/chrome/installer/util/copy_tree_work_item.cc
+++ b/chrome/installer/util/copy_tree_work_item.cc
@@ -78,7 +78,7 @@
     }
 
     base::FilePath backup = backup_path_.path().Append(dest_path_.BaseName());
-    if (file_util::Move(dest_path_, backup)) {
+    if (base::Move(dest_path_, backup)) {
       moved_to_backup_ = true;
       VLOG(1) << "Moved destination " << dest_path_.value() <<
                  " to backup path " << backup.value();
@@ -109,18 +109,18 @@
   // If this does happen sometimes, we may consider using Move instead of
   // Delete here. For now we just log the error and continue with the
   // rest of rollback operation.
-  if (copied_to_dest_path_ && !file_util::Delete(dest_path_, true)) {
+  if (copied_to_dest_path_ && !base::Delete(dest_path_, true)) {
     LOG(ERROR) << "Can not delete " << dest_path_.value();
   }
   if (moved_to_backup_) {
     base::FilePath backup(backup_path_.path().Append(dest_path_.BaseName()));
-    if (!file_util::Move(backup, dest_path_)) {
+    if (!base::Move(backup, dest_path_)) {
       LOG(ERROR) << "failed move " << backup.value()
                  << " to " << dest_path_.value();
     }
   }
   if (copied_to_alternate_path_ &&
-      !file_util::Delete(alternative_path_, true)) {
+      !base::Delete(alternative_path_, true)) {
     LOG(ERROR) << "Can not delete " << alternative_path_.value();
   }
 }
diff --git a/chrome/installer/util/copy_tree_work_item_unittest.cc b/chrome/installer/util/copy_tree_work_item_unittest.cc
index cd51925..23cc5b3 100644
--- a/chrome/installer/util/copy_tree_work_item_unittest.cc
+++ b/chrome/installer/util/copy_tree_work_item_unittest.cc
@@ -562,7 +562,7 @@
   EXPECT_FALSE(file_util::PathExists(backup_file));
 
   // Now delete the destination and try copying the file again.
-  file_util::Delete(file_name_to, true);
+  base::Delete(file_name_to, true);
   work_item.reset(WorkItem::CreateCopyTreeWorkItem(
       file_name_from, file_name_to,
       temp_dir_.path(), WorkItem::IF_NOT_PRESENT,
diff --git a/chrome/installer/util/delete_after_reboot_helper_unittest.cc b/chrome/installer/util/delete_after_reboot_helper_unittest.cc
index 02adf5e..02b52a7 100644
--- a/chrome/installer/util/delete_after_reboot_helper_unittest.cc
+++ b/chrome/installer/util/delete_after_reboot_helper_unittest.cc
@@ -39,7 +39,7 @@
   }
   virtual void TearDown() {
     // Delete the temporary directory if it's still there.
-    file_util::Delete(temp_dir_, true);
+    base::Delete(temp_dir_, true);
 
     // Try and restore the pending moves value, if we have one.
     if (IsUserAnAdmin() && original_pending_moves_.size() > 1) {
@@ -228,7 +228,7 @@
   }
 
   // Delete the temporary directory.
-  file_util::Delete(temp_dir_, true);
+  base::Delete(temp_dir_, true);
 
   // Test that we can remove the pending deletes.
   EXPECT_TRUE(RemoveFromMovesPendingReboot(temp_dir_.value().c_str()));
diff --git a/chrome/installer/util/delete_tree_work_item.cc b/chrome/installer/util/delete_tree_work_item.cc
index 0299a83..a5ccf4d 100644
--- a/chrome/installer/util/delete_tree_work_item.cc
+++ b/chrome/installer/util/delete_tree_work_item.cc
@@ -91,7 +91,7 @@
     // We can safely delete the key files now.
     for (ptrdiff_t i = 0; !abort && i != num_key_files_; ++i) {
       base::FilePath& key_file = key_paths_[i];
-      if (!file_util::Delete(key_file, true)) {
+      if (!base::Delete(key_file, true)) {
         // This should not really be possible because of the above.
         PLOG(DFATAL) << "Unexpectedly could not delete " << key_file.value();
         abort = true;
@@ -126,7 +126,7 @@
         }
       }
     }
-    if (!file_util::Delete(root_path_, true)) {
+    if (!base::Delete(root_path_, true)) {
       LOG(ERROR) << "can not delete " << root_path_.value();
       return ignore_failure_;
     }
@@ -144,7 +144,7 @@
     DCHECK(!backup_path_.path().empty());
     base::FilePath backup = backup_path_.path().Append(root_path_.BaseName());
     if (file_util::PathExists(backup))
-      file_util::Move(backup, root_path_);
+      base::Move(backup, root_path_);
   }
 
   for (ptrdiff_t i = 0; i != num_key_files_; ++i) {
@@ -154,7 +154,7 @@
       base::FilePath backup_file =
           backup_dir.path().Append(key_file.BaseName());
       if (file_util::PathExists(backup_file) &&
-          !file_util::Move(backup_file, key_file)) {
+          !base::Move(backup_file, key_file)) {
         // This could happen if we could not delete the key file to begin with.
         PLOG(WARNING) << "Rollback: Failed to move backup file back in place: "
                       << backup_file.value() << " to " << key_file.value();
diff --git a/chrome/installer/util/google_update_experiment_util.cc b/chrome/installer/util/google_update_experiment_util.cc
index 101dd39..0baca39 100644
--- a/chrome/installer/util/google_update_experiment_util.cc
+++ b/chrome/installer/util/google_update_experiment_util.cc
@@ -9,7 +9,7 @@
 #include "base/logging.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 
 namespace installer {
 
diff --git a/chrome/installer/util/google_update_settings.cc b/chrome/installer/util/google_update_settings.cc
index 3b985b2..6e41637 100644
--- a/chrome/installer/util/google_update_settings.cc
+++ b/chrome/installer/util/google_update_settings.cc
@@ -12,7 +12,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_restrictions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/win/registry.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/installer/util/browser_distribution.h"
@@ -39,9 +39,6 @@
 #endif
 
 bool ReadGoogleUpdateStrKey(const wchar_t* const name, std::wstring* value) {
-  // The registry functions below will end up going to disk.  Do this on another
-  // thread to avoid slowing the IO thread.  http://crbug.com/62121
-  base::ThreadRestrictions::ScopedAllowIO allow_io;
   BrowserDistribution* dist = BrowserDistribution::GetDistribution();
   std::wstring reg_path = dist->GetStateKey();
   RegKey key(HKEY_CURRENT_USER, reg_path.c_str(), KEY_READ);
@@ -108,10 +105,6 @@
     return true;
   }
 
-  // The registry functions below will end up going to disk.  Do this on another
-  // thread to avoid slowing the IO thread.  http://crbug.com/62121
-  base::ThreadRestrictions::ScopedAllowIO allow_io;
-
   HKEY root_key = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
   string16 reg_path = dist->GetStateKey();
   RegKey key(root_key, reg_path.c_str(), KEY_READ);
@@ -147,6 +140,7 @@
     case GoogleUpdateSettings::UPDATES_DISABLED:
     case GoogleUpdateSettings::AUTOMATIC_UPDATES:
     case GoogleUpdateSettings::MANUAL_UPDATES_ONLY:
+    case GoogleUpdateSettings::AUTO_UPDATES_ONLY:
       *update_policy = static_cast<GoogleUpdateSettings::UpdatePolicy>(value);
       return true;
     default:
diff --git a/chrome/installer/util/google_update_settings.h b/chrome/installer/util/google_update_settings.h
index 7ca9f7c..b1fa5b7 100644
--- a/chrome/installer/util/google_update_settings.h
+++ b/chrome/installer/util/google_update_settings.h
@@ -9,7 +9,7 @@
 
 #include "base/basictypes.h"
 #include "base/strings/string16.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/version.h"
 #include "chrome/installer/util/util_constants.h"
 
@@ -30,6 +30,7 @@
     UPDATES_DISABLED    = 0,
     AUTOMATIC_UPDATES   = 1,
     MANUAL_UPDATES_ONLY = 2,
+    AUTO_UPDATES_ONLY   = 3,
   };
 
   // Defines product data that is tracked/used by Google Update.
diff --git a/chrome/installer/util/google_update_settings_unittest.cc b/chrome/installer/util/google_update_settings_unittest.cc
index 4b665b4..17d64a6 100644
--- a/chrome/installer/util/google_update_settings_unittest.cc
+++ b/chrome/installer/util/google_update_settings_unittest.cc
@@ -544,12 +544,22 @@
                                                      &is_overridden));
   EXPECT_FALSE(is_overridden);
 
-  // The default policy should be in force for bogus values.
   EXPECT_EQ(ERROR_SUCCESS,
             RegKey(HKEY_LOCAL_MACHINE, kGoogleUpdatePoliciesKey,
                    KEY_SET_VALUE).WriteValue(kGoogleUpdateUpdateDefault,
                                              static_cast<DWORD>(3)));
   is_overridden = true;
+  EXPECT_EQ(GoogleUpdateSettings::AUTO_UPDATES_ONLY,
+            GoogleUpdateSettings::GetAppUpdatePolicy(kTestProductGuid,
+                                                     &is_overridden));
+  EXPECT_FALSE(is_overridden);
+
+  // The default policy should be in force for bogus values.
+  EXPECT_EQ(ERROR_SUCCESS,
+            RegKey(HKEY_LOCAL_MACHINE, kGoogleUpdatePoliciesKey,
+                   KEY_SET_VALUE).WriteValue(kGoogleUpdateUpdateDefault,
+                                             static_cast<DWORD>(4)));
+  is_overridden = true;
   EXPECT_EQ(kDefaultUpdatePolicy,
             GoogleUpdateSettings::GetAppUpdatePolicy(kTestProductGuid,
                                                      &is_overridden));
@@ -599,11 +609,21 @@
                                                      &is_overridden));
   EXPECT_TRUE(is_overridden);
 
-  // The default policy should be in force for bogus values.
   EXPECT_EQ(ERROR_SUCCESS,
             RegKey(HKEY_LOCAL_MACHINE, kGoogleUpdatePoliciesKey,
                    KEY_SET_VALUE).WriteValue(app_policy_value.c_str(),
                                              static_cast<DWORD>(3)));
+  is_overridden = false;
+  EXPECT_EQ(GoogleUpdateSettings::AUTO_UPDATES_ONLY,
+            GoogleUpdateSettings::GetAppUpdatePolicy(kTestProductGuid,
+                                                     &is_overridden));
+  EXPECT_TRUE(is_overridden);
+
+  // The default policy should be in force for bogus values.
+  EXPECT_EQ(ERROR_SUCCESS,
+            RegKey(HKEY_LOCAL_MACHINE, kGoogleUpdatePoliciesKey,
+                   KEY_SET_VALUE).WriteValue(app_policy_value.c_str(),
+                                             static_cast<DWORD>(4)));
   is_overridden = true;
   EXPECT_EQ(GoogleUpdateSettings::UPDATES_DISABLED,
             GoogleUpdateSettings::GetAppUpdatePolicy(kTestProductGuid,
diff --git a/chrome/installer/util/google_update_util.cc b/chrome/installer/util/google_update_util.cc
index 8434ab9..b002356 100644
--- a/chrome/installer/util/google_update_util.cc
+++ b/chrome/installer/util/google_update_util.cc
@@ -17,7 +17,7 @@
 #include "base/process_util.h"
 #include "base/strings/string16.h"
 #include "base/strings/string_split.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/win/registry.h"
 #include "base/win/scoped_handle.h"
 #include "chrome/installer/launcher_support/chrome_launcher_support.h"
diff --git a/chrome/installer/util/installer_state.cc b/chrome/installer/util/installer_state.cc
index f69d5cd..5fd81bc 100644
--- a/chrome/installer/util/installer_state.cc
+++ b/chrome/installer/util/installer_state.cc
@@ -665,7 +665,7 @@
       LOG(ERROR) << "Deleting old version directory: " << next_version.value();
 
       // Attempt to recursively delete the old version dir.
-      bool delete_succeeded = file_util::Delete(next_version, true);
+      bool delete_succeeded = base::Delete(next_version, true);
 
       // Note: temporarily log old version deletion at ERROR level to make it
       // more likely we see this in the installer log.
diff --git a/chrome/installer/util/logging_installer.cc b/chrome/installer/util/logging_installer.cc
index 2e47269..adb0172 100644
--- a/chrome/installer/util/logging_installer.cc
+++ b/chrome/installer/util/logging_installer.cc
@@ -47,8 +47,8 @@
     if (old_log_file.IsValid()) {
       result = LOGFILE_DELETED;
       base::FilePath tmp_log(log_file.value() + FILE_PATH_LITERAL(".tmp"));
-      // Note that file_util::Move will attempt to replace existing files.
-      if (file_util::Move(log_file, tmp_log)) {
+      // Note that base::Move will attempt to replace existing files.
+      if (base::Move(log_file, tmp_log)) {
         int64 offset = log_size - kTruncatedInstallerLogFileSize;
         std::string old_log_data(kTruncatedInstallerLogFileSize, 0);
         int bytes_read = base::ReadPlatformFile(old_log_file,
@@ -63,7 +63,7 @@
           result = LOGFILE_TRUNCATED;
         }
       }
-    } else if (file_util::Delete(log_file, false)) {
+    } else if (base::Delete(log_file, false)) {
       // Couldn't get sufficient access to the log file, optimistically try to
       // delete it.
       result = LOGFILE_DELETED;
@@ -89,12 +89,10 @@
   base::FilePath log_file_path(GetLogFilePath(prefs));
   TruncateLogFileIfNeeded(log_file_path);
 
-  logging::InitLogging(
-      log_file_path.value().c_str(),
-      logging::LOG_ONLY_TO_FILE,
-      logging::LOCK_LOG_FILE,
-      logging::APPEND_TO_OLD_LOG_FILE,
-      logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS);
+  logging::LoggingSettings settings;
+  settings.logging_dest = logging::LOG_TO_FILE;
+  settings.log_file = log_file_path.value().c_str();
+  logging::InitLogging(settings);
 
   if (prefs.GetBool(installer::master_preferences::kVerboseLogging,
                     &value) && value) {
diff --git a/chrome/installer/util/master_preferences.cc b/chrome/installer/util/master_preferences.cc
index 25df264..6e8a94f 100644
--- a/chrome/installer/util/master_preferences.cc
+++ b/chrome/installer/util/master_preferences.cc
@@ -23,23 +23,23 @@
 base::LazyInstance<installer::MasterPreferences> g_master_preferences =
     LAZY_INSTANCE_INITIALIZER;
 
-bool GetURLFromValue(const Value* in_value, std::string* out_value) {
+bool GetURLFromValue(const base::Value* in_value, std::string* out_value) {
   return in_value && out_value && in_value->GetAsString(out_value);
 }
 
 std::vector<std::string> GetNamedList(const char* name,
-                                      const DictionaryValue* prefs) {
+                                      const base::DictionaryValue* prefs) {
   std::vector<std::string> list;
   if (!prefs)
     return list;
 
-  const ListValue* value_list = NULL;
+  const base::ListValue* value_list = NULL;
   if (!prefs->GetList(name, &value_list))
     return list;
 
   list.reserve(value_list->GetSize());
   for (size_t i = 0; i < value_list->GetSize(); ++i) {
-    const Value* entry;
+    const base::Value* entry;
     std::string url_entry;
     if (!value_list->Get(i, &entry) || !GetURLFromValue(entry, &url_entry)) {
       NOTREACHED();
@@ -50,20 +50,21 @@
   return list;
 }
 
-DictionaryValue* ParseDistributionPreferences(const std::string& json_data) {
+base::DictionaryValue* ParseDistributionPreferences(
+    const std::string& json_data) {
   JSONStringValueSerializer json(json_data);
   std::string error;
-  scoped_ptr<Value> root(json.Deserialize(NULL, &error));
+  scoped_ptr<base::Value> root(json.Deserialize(NULL, &error));
   if (!root.get()) {
     LOG(WARNING) << "Failed to parse master prefs file: " << error;
     return NULL;
   }
-  if (!root->IsType(Value::TYPE_DICTIONARY)) {
+  if (!root->IsType(base::Value::TYPE_DICTIONARY)) {
     LOG(WARNING) << "Failed to parse master prefs file: "
                  << "Root item must be a dictionary.";
     return NULL;
   }
-  return static_cast<DictionaryValue*>(root.release());
+  return static_cast<base::DictionaryValue*>(root.release());
 }
 
 }  // namespace
@@ -128,7 +129,7 @@
         installer::switches::kInstallerData));
     this->MasterPreferences::MasterPreferences(prefs_path);
   } else {
-    master_dictionary_.reset(new DictionaryValue());
+    master_dictionary_.reset(new base::DictionaryValue());
   }
 
   DCHECK(master_dictionary_.get());
@@ -216,7 +217,7 @@
 
   bool data_is_valid = true;
   if (!master_dictionary_.get()) {
-    master_dictionary_.reset(new DictionaryValue());
+    master_dictionary_.reset(new base::DictionaryValue());
     data_is_valid = false;
   } else {
     // Cache a pointer to the distribution dictionary.
@@ -305,7 +306,8 @@
   return GetNamedList(kFirstRunTabs, master_dictionary_.get());
 }
 
-bool MasterPreferences::GetExtensionsBlock(DictionaryValue** extensions) const {
+bool MasterPreferences::GetExtensionsBlock(
+    base::DictionaryValue** extensions) const {
   return master_dictionary_->GetDictionary(
       master_preferences::kExtensionsBlock, extensions);
 }
diff --git a/chrome/installer/util/master_preferences_unittest.cc b/chrome/installer/util/master_preferences_unittest.cc
index c2cabae..ec6e1cb 100644
--- a/chrome/installer/util/master_preferences_unittest.cc
+++ b/chrome/installer/util/master_preferences_unittest.cc
@@ -23,7 +23,7 @@
   }
 
   virtual void TearDown() {
-    EXPECT_TRUE(file_util::Delete(prefs_file_, false));
+    EXPECT_TRUE(base::Delete(prefs_file_, false));
   }
 
   const base::FilePath& prefs_file() const { return prefs_file_; }
@@ -41,7 +41,7 @@
 }  // namespace
 
 TEST_F(MasterPreferencesTest, NoFileToParse) {
-  EXPECT_TRUE(file_util::Delete(prefs_file(), false));
+  EXPECT_TRUE(base::Delete(prefs_file(), false));
   installer::MasterPreferences prefs(prefs_file());
   EXPECT_FALSE(prefs.read_from_file());
 }
@@ -275,7 +275,7 @@
   }
 
   // Delete temporary prefs file.
-  EXPECT_TRUE(file_util::Delete(prefs_file, false));
+  EXPECT_TRUE(base::Delete(prefs_file, false));
 
   // Check that if master prefs doesn't exist, we can still parse the common
   // prefs.
diff --git a/chrome/installer/util/move_tree_work_item.cc b/chrome/installer/util/move_tree_work_item.cc
index 7190222..ccbbf64 100644
--- a/chrome/installer/util/move_tree_work_item.cc
+++ b/chrome/installer/util/move_tree_work_item.cc
@@ -55,7 +55,7 @@
         // The files we are moving are already present in the destination path.
         // We most likely don't need to do anything. As such, just move the
         // source files to the temp folder as backup.
-        if (file_util::Move(source_path_, backup)) {
+        if (base::Move(source_path_, backup)) {
           source_moved_to_backup_ = true;
           VLOG(1) << "Moved source " << source_path_.value()
                   << " to backup path " << backup.value();
@@ -74,7 +74,7 @@
       }
     }
 
-    if (file_util::Move(dest_path_, backup)) {
+    if (base::Move(dest_path_, backup)) {
       moved_to_backup_ = true;
       VLOG(1) << "Moved destination " << dest_path_.value()
               << " to backup path " << backup.value();
@@ -86,7 +86,7 @@
   }
 
   // Now move source to destination.
-  if (file_util::Move(source_path_, dest_path_)) {
+  if (base::Move(source_path_, dest_path_)) {
     moved_to_dest_path_ = true;
     VLOG(1) << "Moved source " << source_path_.value()
             << " to destination " << dest_path_.value();
@@ -100,17 +100,17 @@
 }
 
 void MoveTreeWorkItem::Rollback() {
-  if (moved_to_dest_path_ && !file_util::Move(dest_path_, source_path_))
+  if (moved_to_dest_path_ && !base::Move(dest_path_, source_path_))
     LOG(ERROR) << "Can not move " << dest_path_.value()
                << " to " << source_path_.value();
 
   base::FilePath backup = backup_path_.path().Append(dest_path_.BaseName());
-  if (moved_to_backup_ && !file_util::Move(backup, dest_path_)) {
+  if (moved_to_backup_ && !base::Move(backup, dest_path_)) {
     LOG(ERROR) << "failed move " << backup.value()
                << " to " << dest_path_.value();
   }
 
-  if (source_moved_to_backup_ && !file_util::Move(backup, source_path_)) {
+  if (source_moved_to_backup_ && !base::Move(backup, source_path_)) {
     LOG(ERROR) << "Can not restore " << backup.value()
                << " to " << source_path_.value();
   }
diff --git a/chrome/installer/util/self_cleaning_temp_dir.cc b/chrome/installer/util/self_cleaning_temp_dir.cc
index cdb61e8..bb2fd6c 100644
--- a/chrome/installer/util/self_cleaning_temp_dir.cc
+++ b/chrome/installer/util/self_cleaning_temp_dir.cc
@@ -78,7 +78,7 @@
 
   // First try to recursively delete the leaf directory managed by our
   // base::ScopedTempDir.
-  if (!file_util::Delete(path(), true)) {
+  if (!base::Delete(path(), true)) {
     // That failed, so schedule the temp dir and its contents for deletion after
     // reboot.
     LOG(WARNING) << "Failed to delete temporary directory " << path().value()
diff --git a/chrome/installer/util/shell_util.cc b/chrome/installer/util/shell_util.cc
index 19958c6..4a196ea 100644
--- a/chrome/installer/util/shell_util.cc
+++ b/chrome/installer/util/shell_util.cc
@@ -1200,7 +1200,7 @@
 }
 
 bool ShortcutOpDelete(const base::FilePath& shortcut_path) {
-  bool ret = file_util::Delete(shortcut_path, false);
+  bool ret = base::Delete(shortcut_path, false);
   LOG_IF(ERROR, !ret) << "Failed to remove " << shortcut_path.value();
   return ret;
 }
@@ -1269,7 +1269,7 @@
     LOG(WARNING) << "Cannot find path at location " << location;
     return false;
   }
-  if (!file_util::Delete(shortcut_folder, true)) {
+  if (!base::Delete(shortcut_folder, true)) {
     LOG(ERROR) << "Cannot remove folder " << shortcut_folder.value();
     return false;
   }
diff --git a/chrome/installer/util/util_constants.cc b/chrome/installer/util/util_constants.cc
index c380a5f..e293e76 100644
--- a/chrome/installer/util/util_constants.cc
+++ b/chrome/installer/util/util_constants.cc
@@ -196,6 +196,15 @@
 // to. See DuplicateGoogleUpdateSystemClientKey for details.
 const char kToastResultsKey[] = "toast-results-key";
 
+// Applies a binary patch to a file. The input, patch, and the output file are
+// specified as command line arguments following the --patch switch.
+// Ex: --patch=courgette --input_file='input' --patch_file='patch'
+//        --output_file='output'
+const char kPatch[] = "patch";
+const char kInputFile[] = "input-file";
+const char kPatchFile[] = "patch-file";
+const char kOutputFile[] = "output-file";
+
 }  // namespace switches
 
 // The Active Setup executable will be an identical copy of setup.exe; this is
@@ -261,4 +270,7 @@
 
 const size_t kMaxAppModelIdLength = 64U;
 
+const char kCourgette[] = "courgette";
+const char kBsdiff[] = "bsdiff";
+
 }  // namespace installer
diff --git a/chrome/installer/util/util_constants.h b/chrome/installer/util/util_constants.h
index bb7b693..3f9a496 100644
--- a/chrome/installer/util/util_constants.h
+++ b/chrome/installer/util/util_constants.h
@@ -80,12 +80,14 @@
   INVALID_STATE_FOR_OPTION,    // 47. A non-install option was called with an
                                // invalid installer state.
   WAIT_FOR_EXISTING_FAILED,    // 48. OS error waiting for existing setup.exe.
+  PATCH_INVALID_ARGUMENTS,     // 49. The arguments of --patch were missing or
+                               // they were invalid for any reason.
   // Friendly reminder: note the COMPILE_ASSERT below.
 };
 
 
 // Existing InstallStatus values must not change.  Always add to the end.
-COMPILE_ASSERT(installer::WAIT_FOR_EXISTING_FAILED == 48,
+COMPILE_ASSERT(installer::PATCH_INVALID_ARGUMENTS == 49,
                dont_change_enum);
 
 // The type of an update archive.
@@ -128,6 +130,7 @@
                never_ever_ever_change_InstallerStage_values_bang);
 
 namespace switches {
+
 extern const char kAutoLaunchChrome[];
 extern const char kChrome[];
 extern const char kChromeAppHostDeprecated[];  // TODO(huangs): Remove by M27.
@@ -177,6 +180,11 @@
 extern const char kSystemLevelToast[];
 extern const char kExperimentGroup[];
 extern const char kToastResultsKey[];
+extern const char kPatch[];
+extern const char kInputFile[];
+extern const char kPatchFile[];
+extern const char kOutputFile[];
+
 }  // namespace switches
 
 extern const wchar_t kActiveSetupExe[];
@@ -237,6 +245,16 @@
 
 extern const size_t kMaxAppModelIdLength;
 
+// The range of error values for the installer, Courgette, and bsdiff is
+// overlapping. These offset values disambiguate between different sets
+// of errors by shifting the values up with the specified offset.
+const int kCourgetteErrorOffset = 300;
+const int kBsdiffErrorOffset = 600;
+
+// Arguments to --patch switch
+extern const char kCourgette[];
+extern const char kBsdiff[];
+
 }  // namespace installer
 
 #endif  // CHROME_INSTALLER_UTIL_UTIL_CONSTANTS_H_
diff --git a/chrome/interactive_ui_tests.isolate b/chrome/interactive_ui_tests.isolate
index ca57765..d75c040 100644
--- a/chrome/interactive_ui_tests.isolate
+++ b/chrome/interactive_ui_tests.isolate
@@ -26,7 +26,7 @@
       'variables': {
         'isolate_dependency_tracked': [
           '../net/data/ssl/certificates/ok_cert.pem',
-          '../net/data/ssl/certificates/root_ca_cert.crt',
+          '../net/data/ssl/certificates/root_ca_cert.pem',
           '../net/tools/testserver/asn1.py',
           '../net/tools/testserver/echo_message.py',
           '../net/tools/testserver/minica.py',
diff --git a/chrome/nacl.gypi b/chrome/nacl.gypi
index 0607ef5..d9d4ec1 100644
--- a/chrome/nacl.gypi
+++ b/chrome/nacl.gypi
@@ -54,6 +54,8 @@
             'sources': [
               'app/nacl_fork_delegate_linux.cc',
               'app/nacl_fork_delegate_linux.h',
+              'common/nacl_paths.cc',
+              'common/nacl_paths.h',
             ],
           },],
         ],
@@ -149,14 +151,19 @@
               'dependencies': [
                 '../crypto/crypto.gyp:crypto',
                 '../sandbox/sandbox.gyp:libc_urandom_override',
+                '../sandbox/sandbox.gyp:sandbox',
                 'nacl',
               ],
               'sources': [
                 'nacl/nacl_helper_linux.cc',
+                'nacl/nacl_sandbox_linux.cc',
                 '../base/posix/unix_domain_socket_linux.cc',
                 '../chrome/common/nacl_messages.cc',
                 '../chrome/common/nacl_types.cc',
                 '../content/common/child_process_sandbox_support_impl_shm_linux.cc',
+                '../content/common/sandbox_init_linux.cc',
+                '../content/common/sandbox_seccomp_bpf_linux.cc',
+                '../content/public/common/content_switches.cc',
               ],
               'conditions': [
                 ['toolkit_uses_gtk == 1', {
diff --git a/chrome/nacl/DEPS b/chrome/nacl/DEPS
index 4ab0571..c5a003d 100644
--- a/chrome/nacl/DEPS
+++ b/chrome/nacl/DEPS
@@ -1,6 +1,8 @@
 include_rules = [
   "+chrome/app/breakpad_win.h",
+  "+components/nacl",
   "+content/public/app/startup_helper_win.h",
+  "+sandbox/linux/seccomp-bpf",
   "+sandbox/linux/services",
   "+sandbox/win/src",
   "+native_client/src",
diff --git a/chrome/nacl/nacl_broker_listener.cc b/chrome/nacl/nacl_broker_listener.cc
index e310dfe..1a49a1f 100644
--- a/chrome/nacl/nacl_broker_listener.cc
+++ b/chrome/nacl/nacl_broker_listener.cc
@@ -15,6 +15,8 @@
 #include "chrome/common/nacl_cmd_line.h"
 #include "chrome/common/nacl_debug_exception_handler_win.h"
 #include "chrome/common/nacl_messages.h"
+#include "components/nacl/common/nacl_switches.h"
+#include "content/public/common/content_switches.h"
 #include "content/public/common/sandbox_init.h"
 #include "ipc/ipc_channel.h"
 #include "ipc/ipc_switches.h"
diff --git a/chrome/nacl/nacl_exe_win_64.cc b/chrome/nacl/nacl_exe_win_64.cc
index 7ba3c40..951d128 100644
--- a/chrome/nacl/nacl_exe_win_64.cc
+++ b/chrome/nacl/nacl_exe_win_64.cc
@@ -4,20 +4,21 @@
 
 #include "base/at_exit.h"
 #include "base/command_line.h"
-#include "base/hi_res_timer_manager.h"
 #include "base/logging.h"
 #include "base/message_loop.h"
 #include "base/power_monitor/power_monitor.h"
 #include "base/process_util.h"
 #include "base/strings/string_util.h"
+#include "base/timer/hi_res_timer_manager.h"
 #include "chrome/app/breakpad_win.h"
 #include "chrome/common/chrome_result_codes.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/logging_chrome.h"
 #include "chrome/nacl/nacl_broker_listener.h"
 #include "chrome/nacl/nacl_listener.h"
 #include "chrome/nacl/nacl_main_platform_delegate.h"
+#include "components/nacl/common/nacl_switches.h"
 #include "content/public/app/startup_helper_win.h"
+#include "content/public/common/content_switches.h"
 #include "content/public/common/main_function_params.h"
 #include "content/public/common/sandbox_init.h"
 #include "sandbox/win/src/sandbox_types.h"
@@ -33,7 +34,7 @@
   base::PlatformThread::SetName("CrNaClBrokerMain");
 
   base::PowerMonitor power_monitor;
-  HighResolutionTimerManager hi_res_timer_manager;
+  base::HighResolutionTimerManager hi_res_timer_manager;
 
   NaClBrokerListener listener;
   listener.Listen();
diff --git a/chrome/nacl/nacl_helper_linux.cc b/chrome/nacl/nacl_helper_linux.cc
index f8f32c4..7134457 100644
--- a/chrome/nacl/nacl_helper_linux.cc
+++ b/chrome/nacl/nacl_helper_linux.cc
@@ -28,6 +28,7 @@
 #include "base/posix/unix_domain_socket_linux.h"
 #include "base/rand_util.h"
 #include "chrome/nacl/nacl_listener.h"
+#include "chrome/nacl/nacl_sandbox_linux.h"
 #include "crypto/nss_util.h"
 #include "ipc/ipc_descriptors.h"
 #include "ipc/ipc_switches.h"
@@ -38,19 +39,25 @@
 // The child must mimic the behavior of zygote_main_linux.cc on the child
 // side of the fork. See zygote_main_linux.cc:HandleForkRequest from
 //   if (!child) {
-// Note: this code doesn't attempt to support the SECCOMP sandbox.
 void BecomeNaClLoader(const std::vector<int>& child_fds,
-                      size_t prereserved_sandbox_size) {
+                      size_t prereserved_sandbox_size,
+                      int number_of_cores) {
   VLOG(1) << "NaCl loader: setting up IPC descriptor";
   // don't need zygote FD any more
   if (HANDLE_EINTR(close(kNaClZygoteDescriptor)) != 0)
     LOG(ERROR) << "close(kNaClZygoteDescriptor) failed.";
+  bool sandbox_initialized = InitializeBpfSandbox();
+  if (!sandbox_initialized) {
+    LOG(ERROR) << "Could not initialize NaCl's second "
+      << "layer sandbox (seccomp-bpf).";
+  }
   base::GlobalDescriptors::GetInstance()->Set(kPrimaryIPCChannel,
                                               child_fds[kNaClBrowserFDIndex]);
 
   base::MessageLoopForIO main_message_loop;
   NaClListener listener;
   listener.set_prereserved_sandbox_size(prereserved_sandbox_size);
+  listener.set_number_of_cores(number_of_cores);
   listener.Listen();
   _exit(0);
 }
@@ -58,7 +65,8 @@
 // Some of this code was lifted from
 // content/browser/zygote_main_linux.cc:ForkWithRealPid()
 void HandleForkRequest(const std::vector<int>& child_fds,
-                       size_t prereserved_sandbox_size) {
+                       size_t prereserved_sandbox_size,
+                       int number_of_cores) {
   VLOG(1) << "nacl_helper: forking";
   pid_t childpid = fork();
   if (childpid < 0) {
@@ -96,7 +104,7 @@
     if (HANDLE_EINTR(close(child_fds[kNaClParentFDIndex])) != 0)
       LOG(ERROR) << "close(child_fds[kNaClParentFDIndex]) failed";
     if (validack) {
-      BecomeNaClLoader(child_fds, prereserved_sandbox_size);
+      BecomeNaClLoader(child_fds, prereserved_sandbox_size, number_of_cores);
     } else {
       LOG(ERROR) << "Failed to synch with zygote";
     }
@@ -234,6 +242,7 @@
 #endif
   std::vector<int> empty; // for SendMsg() calls
   size_t prereserved_sandbox_size = CheckReservedAtZero();
+  int number_of_cores = sysconf(_SC_NPROCESSORS_ONLN);
 
   CheckRDebug(argv[0]);
 
@@ -270,7 +279,7 @@
     } else if (msglen == sizeof(kNaClForkRequest) - 1 &&
                memcmp(buf, kNaClForkRequest, msglen) == 0) {
       if (kNaClParentFDIndex + 1 == fds.size()) {
-        HandleForkRequest(fds, prereserved_sandbox_size);
+        HandleForkRequest(fds, prereserved_sandbox_size, number_of_cores);
         continue;  // fork succeeded. Note: child does not return
       } else {
         LOG(ERROR) << "nacl_helper: unexpected number of fds, got "
diff --git a/chrome/nacl/nacl_listener.cc b/chrome/nacl/nacl_listener.cc
index 8d91a8b..568a107 100644
--- a/chrome/nacl/nacl_listener.cc
+++ b/chrome/nacl/nacl_listener.cc
@@ -7,6 +7,10 @@
 #include <errno.h>
 #include <stdlib.h>
 
+#if defined(OS_POSIX)
+#include <unistd.h>
+#endif
+
 #include "base/command_line.h"
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
@@ -174,6 +178,9 @@
 #if defined(OS_LINUX)
                                prereserved_sandbox_size_(0),
 #endif
+#if defined(OS_POSIX)
+                               number_of_cores_(-1),  // unknown/error
+#endif
                                main_loop_(NULL) {
   io_thread_.StartWithOptions(
       base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
@@ -260,6 +267,7 @@
     LOG(ERROR) << "Failed to dup() the urandom FD";
     return;
   }
+  args->number_of_cores = number_of_cores_;
   args->create_memory_object_func = CreateMemoryObject;
 # if defined(OS_MACOSX)
   CHECK(handles.size() >= 1);
diff --git a/chrome/nacl/nacl_listener.h b/chrome/nacl/nacl_listener.h
index 2936eee..a6cec25 100644
--- a/chrome/nacl/nacl_listener.h
+++ b/chrome/nacl/nacl_listener.h
@@ -34,6 +34,11 @@
     prereserved_sandbox_size_ = prereserved_sandbox_size;
   }
 #endif
+#if defined(OS_POSIX)
+  void set_number_of_cores(int number_of_cores) {
+    number_of_cores_ = number_of_cores;
+  }
+#endif
 
  private:
   void OnStart(const nacl::NaClStartParams& params);
@@ -51,6 +56,14 @@
 #if defined(OS_LINUX)
   size_t prereserved_sandbox_size_;
 #endif
+#if defined(OS_POSIX)
+  // The outer sandbox on Linux and OSX prevents
+  // sysconf(_SC_NPROCESSORS) from working; in Windows, there are no
+  // problems with invoking GetSystemInfo.  Therefore, only in
+  // OS_POSIX do we need to supply the number of cores into the
+  // NaClChromeMainArgs object.
+  int number_of_cores_;
+#endif
 
   // Used to identify what thread we're on.
   base::MessageLoop* main_loop_;
diff --git a/chrome/nacl/nacl_main.cc b/chrome/nacl/nacl_main.cc
index fa4835e..0deea3e 100644
--- a/chrome/nacl/nacl_main.cc
+++ b/chrome/nacl/nacl_main.cc
@@ -5,14 +5,15 @@
 #include "build/build_config.h"
 
 #include "base/command_line.h"
-#include "base/hi_res_timer_manager.h"
 #include "base/message_loop.h"
 #include "base/power_monitor/power_monitor.h"
+#include "base/timer/hi_res_timer_manager.h"
 #include "chrome/common/chrome_result_codes.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/logging_chrome.h"
 #include "chrome/nacl/nacl_listener.h"
 #include "chrome/nacl/nacl_main_platform_delegate.h"
+#include "content/public/common/content_switches.h"
 #include "content/public/common/main_function_params.h"
 
 // main() routine for the NaCl loader process.
@@ -24,7 +25,7 @@
   base::PlatformThread::SetName("CrNaClMain");
 
   base::PowerMonitor power_monitor;
-  HighResolutionTimerManager hi_res_timer_manager;
+  base::HighResolutionTimerManager hi_res_timer_manager;
 
 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
   NaClMainPlatformDelegate platform(parameters);
@@ -33,6 +34,12 @@
   bool no_sandbox = parsed_command_line.HasSwitch(switches::kNoSandbox);
   platform.InitSandboxTests(no_sandbox);
 
+#if defined(OS_POSIX)
+  // The number of cores must be obtained before the invocation of
+  // platform.EnableSandbox(), so cannot simply be inlined below.
+  int number_of_cores = sysconf(_SC_NPROCESSORS_ONLN);
+#endif
+
   if (!no_sandbox) {
     platform.EnableSandbox();
   }
@@ -40,6 +47,9 @@
 
   if (sandbox_test_result) {
     NaClListener listener;
+#if defined(OS_POSIX)
+    listener.set_number_of_cores(number_of_cores);
+#endif
     listener.Listen();
   } else {
     // This indirectly prevents the test-harness-success-cookie from being set,
diff --git a/chrome/nacl/nacl_main_platform_delegate_mac.mm b/chrome/nacl/nacl_main_platform_delegate_mac.mm
index e304ea7..2b094b1 100644
--- a/chrome/nacl/nacl_main_platform_delegate_mac.mm
+++ b/chrome/nacl/nacl_main_platform_delegate_mac.mm
@@ -10,7 +10,7 @@
 #include "base/logging.h"
 #include "base/native_library.h"
 #include "chrome/common/chrome_sandbox_type_mac.h"
-#include "chrome/common/chrome_switches.h"
+#include "components/nacl/common/nacl_switches.h"
 #include "content/public/common/sandbox_init.h"
 
 NaClMainPlatformDelegate::NaClMainPlatformDelegate(
diff --git a/chrome/nacl/nacl_main_platform_delegate_win.cc b/chrome/nacl/nacl_main_platform_delegate_win.cc
index abd9b3e..be37857 100644
--- a/chrome/nacl/nacl_main_platform_delegate_win.cc
+++ b/chrome/nacl/nacl_main_platform_delegate_win.cc
@@ -8,7 +8,7 @@
 #include "base/files/file_path.h"
 #include "base/logging.h"
 #include "base/native_library.h"
-#include "chrome/common/chrome_switches.h"
+#include "components/nacl/common/nacl_switches.h"
 #include "sandbox/win/src/sandbox.h"
 
 NaClMainPlatformDelegate::NaClMainPlatformDelegate(
diff --git a/chrome/nacl/nacl_sandbox_linux.cc b/chrome/nacl/nacl_sandbox_linux.cc
new file mode 100644
index 0000000..19585ea
--- /dev/null
+++ b/chrome/nacl/nacl_sandbox_linux.cc
@@ -0,0 +1,72 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/nacl/nacl_sandbox_linux.h"
+
+#include <signal.h>
+#include <sys/ptrace.h>
+
+#include "base/callback.h"
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "content/public/common/sandbox_init.h"
+#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
+#include "sandbox/linux/services/linux_syscalls.h"
+
+using playground2::ErrorCode;
+using playground2::Sandbox;
+
+namespace {
+
+// This policy does very little:
+// - Any invalid system call for the current architecture is handled by
+//   the baseline policy.
+// - ptrace() is denied.
+// - Anything else is allowed.
+// Note that the seccomp-bpf sandbox always prevents cross-architecture
+// system calls (on x86, long/compatibility/x32).
+// So even this trivial policy has a security benefit.
+ErrorCode NaClBpfSandboxPolicy(
+    playground2::Sandbox* sb, int sysnum, void* aux) {
+  const playground2::BpfSandboxPolicyCallback baseline_policy =
+      content::GetBpfSandboxBaselinePolicy();
+  if (!playground2::Sandbox::IsValidSyscallNumber(sysnum)) {
+    return baseline_policy.Run(sb, sysnum, aux);
+  }
+  switch (sysnum) {
+    case __NR_ptrace:
+      return ErrorCode(EPERM);
+    default:
+      return ErrorCode(ErrorCode::ERR_ALLOWED);
+  }
+  NOTREACHED();
+  // GCC wants this.
+  return ErrorCode(EPERM);
+}
+
+void RunSandboxSanityChecks() {
+  errno = 0;
+  // Make a ptrace request with an invalid PID.
+  long ptrace_ret = ptrace(PTRACE_PEEKUSER, -1 /* pid */, NULL, NULL);
+  CHECK_EQ(-1, ptrace_ret);
+  // Without the sandbox on, this ptrace call would ESRCH instead.
+  CHECK_EQ(EPERM, errno);
+}
+
+}  // namespace
+
+bool InitializeBpfSandbox() {
+  bool sandbox_is_initialized =
+      content::InitializeSandbox(NaClBpfSandboxPolicy);
+  if (sandbox_is_initialized) {
+    RunSandboxSanityChecks();
+    // TODO(jln): Find a way to fix this.
+    // The sandbox' SIGSYS handler trips NaCl, so we disable it.
+    // If SIGSYS is triggered it'll now execute the default action
+    // (CORE). This will make it hard to track down bugs and sandbox violations.
+    CHECK(signal(SIGSYS, SIG_DFL) != SIG_ERR);
+    return true;
+  }
+  return false;
+}
diff --git a/chrome/nacl/nacl_sandbox_linux.h b/chrome/nacl/nacl_sandbox_linux.h
new file mode 100644
index 0000000..6c1662f
--- /dev/null
+++ b/chrome/nacl/nacl_sandbox_linux.h
@@ -0,0 +1,10 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_NACL_NACL_SANDBOX_LINUX_H_
+#define CHROME_NACL_NACL_SANDBOX_LINUX_H_
+
+bool InitializeBpfSandbox();
+
+#endif  // CHROME_NACL_NACL_SANDBOX_LINUX_H_
diff --git a/chrome/plugin/chrome_content_plugin_client.cc b/chrome/plugin/chrome_content_plugin_client.cc
index c6712ab..f9f8f0c 100644
--- a/chrome/plugin/chrome_content_plugin_client.cc
+++ b/chrome/plugin/chrome_content_plugin_client.cc
@@ -55,14 +55,16 @@
 void ChromeContentPluginClient::PluginProcessStarted(
     const string16& plugin_name) {
 #if defined(OS_MACOSX)
-  base::mac::ScopedCFTypeRef<CFStringRef> cf_plugin_name(
+  base::ScopedCFTypeRef<CFStringRef> cf_plugin_name(
       base::SysUTF16ToCFStringRef(plugin_name));
-  base::mac::ScopedCFTypeRef<CFStringRef> app_name(
-      base::SysUTF16ToCFStringRef(
-          l10n_util::GetStringUTF16(IDS_SHORT_PLUGIN_APP_NAME)));
-  base::mac::ScopedCFTypeRef<CFStringRef> process_name(
-      CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ (%@)"),
-                               cf_plugin_name.get(), app_name.get()));
+  base::ScopedCFTypeRef<CFStringRef> app_name(base::SysUTF16ToCFStringRef(
+      l10n_util::GetStringUTF16(IDS_SHORT_PLUGIN_APP_NAME)));
+  base::ScopedCFTypeRef<CFStringRef> process_name(
+      CFStringCreateWithFormat(kCFAllocatorDefault,
+                               NULL,
+                               CFSTR("%@ (%@)"),
+                               cf_plugin_name.get(),
+                               app_name.get()));
   base::mac::SetProcessName(process_name);
 #endif
 }
diff --git a/chrome/renderer/autofill/OWNERS b/chrome/renderer/autofill/OWNERS
index 8af2222..3883338 100644
--- a/chrome/renderer/autofill/OWNERS
+++ b/chrome/renderer/autofill/OWNERS
@@ -1,2 +1,5 @@
 estade@chromium.org
 isherman@chromium.org
+
+# Owner for password autofill/generation only.
+gcasto@chromium.org
diff --git a/chrome/renderer/autofill/form_autocomplete_browsertest.cc b/chrome/renderer/autofill/form_autocomplete_browsertest.cc
index d6a6dea..abd6507 100644
--- a/chrome/renderer/autofill/form_autocomplete_browsertest.cc
+++ b/chrome/renderer/autofill/form_autocomplete_browsertest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/test/base/chrome_render_view_test.h"
 #include "components/autofill/core/common/autofill_messages.h"
 #include "components/autofill/core/common/form_data.h"
diff --git a/chrome/renderer/autofill/password_autofill_agent_browsertest.cc b/chrome/renderer/autofill/password_autofill_agent_browsertest.cc
index 9813cad..dcc3574 100644
--- a/chrome/renderer/autofill/password_autofill_agent_browsertest.cc
+++ b/chrome/renderer/autofill/password_autofill_agent_browsertest.cc
@@ -65,7 +65,7 @@
   // protected.
   void SimulateOnFillPasswordForm(
       const PasswordFormFillData& fill_data) {
-    AutofillMsg_FillPasswordForm msg(0, fill_data, false);
+    AutofillMsg_FillPasswordForm msg(0, fill_data);
     password_autofill_->OnMessageReceived(msg);
   }
 
@@ -92,8 +92,12 @@
     password_field.form_control_type = "password";
     fill_data_.basic_data.fields.push_back(password_field);
 
-    fill_data_.additional_logins[username2_] = password2_;
-    fill_data_.additional_logins[username3_] = password3_;
+    PasswordAndRealm password2;
+    password2.password = password2_;
+    fill_data_.additional_logins[username2_] = password2;
+    PasswordAndRealm password3;
+    password3.password = password3_;
+    fill_data_.additional_logins[username3_] = password3;
 
     UsernamesCollectionKey key;
     key.username = username3_;
@@ -281,6 +285,21 @@
   CheckTextFieldsState("bogus", false, std::string(), false);
 }
 
+// Tests that changing the username does not fill a field specifying
+// autocomplete="off".
+TEST_F(PasswordAutofillAgentTest, NoInitialAutocompleteForAutocompleteOff) {
+  password_element_.setAttribute(WebString::fromUTF8("autocomplete"),
+                                 WebString::fromUTF8("off"));
+
+  // Simulate the browser sending back the login info, it triggers the
+  // autocomplete.
+  SimulateOnFillPasswordForm(fill_data_);
+
+  // Only the username should have been autocompleted.
+  // TODO(jcivelli): may be we should not event fill the username?
+  CheckTextFieldsState(kAliceUsername, true, std::string(), false);
+}
+
 TEST_F(PasswordAutofillAgentTest, NoAutocompleteForTextFieldPasswords) {
   const char kTextFieldPasswordFormHTML[] =
       "<FORM name='LoginTestForm' action='http://www.bidule.com'>"
diff --git a/chrome/renderer/benchmarking_extension.cc b/chrome/renderer/benchmarking_extension.cc
index ace6d08..b04a306 100644
--- a/chrome/renderer/benchmarking_extension.cc
+++ b/chrome/renderer/benchmarking_extension.cc
@@ -6,7 +6,7 @@
 
 #include "base/command_line.h"
 #include "base/metrics/stats_table.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/renderer/render_thread.h"
 #include "v8/include/v8.h"
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc
index 43c83f8..7959ea0 100644
--- a/chrome/renderer/chrome_content_renderer_client.cc
+++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -193,13 +193,13 @@
   if (plugin.name == ASCIIToUTF16(chrome::ChromeContentClient::kNaClPluginName))
     return true;
 
-#if defined(WIDEVINE_CDM_AVAILABLE)
+#if defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
   // Treat CDM invocations like JavaScript.
   if (plugin.name == ASCIIToUTF16(kWidevineCdmDisplayName)) {
     DCHECK(plugin.type == WebPluginInfo::PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS);
     return true;
   }
-#endif  // WIDEVINE_CDM_AVAILABLE
+#endif  // defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
 
   return false;
 }
@@ -463,22 +463,21 @@
   return placeholder->plugin();
 }
 
-webkit_media::WebMediaPlayerImpl*
-ChromeContentRendererClient::OverrideCreateWebMediaPlayer(
+void ChromeContentRendererClient::DeferMediaLoad(
     content::RenderView* render_view,
-    WebKit::WebFrame* frame,
-    WebKit::WebMediaPlayerClient* client,
-    base::WeakPtr<webkit_media::WebMediaPlayerDelegate> delegate,
-    const webkit_media::WebMediaPlayerParams& params) {
+    const base::Closure& closure) {
 #if defined(OS_ANDROID)
   // Chromium for Android doesn't support prerender yet.
-  return NULL;
+  closure.Run();
+  return;
 #else
-  if (!prerender::PrerenderHelper::IsPrerendering(render_view))
-    return NULL;
+  if (!prerender::PrerenderHelper::IsPrerendering(render_view)) {
+    closure.Run();
+    return;
+  }
 
-  return new prerender::PrerenderWebMediaPlayer(
-      render_view, frame, client, delegate, params);
+  // Lifetime is tied to |render_view| via content::RenderViewObserver.
+  new prerender::PrerenderWebMediaPlayer(render_view, closure);
 #endif
 }
 
@@ -768,12 +767,15 @@
     bool is_nacl_unrestricted,
     const Extension* extension,
     WebPluginParams* params) {
-  // Temporarily allow these URLs to run NaCl apps. We should remove this
-  // code when PNaCl ships.
+  // Temporarily allow these URLs to run NaCl apps, as long as the manifest is
+  // also whitelisted. We should remove this code when PNaCl ships.
   bool is_whitelisted_url =
       app_url.SchemeIs("https") &&
       (app_url.host() == "plus.google.com" ||
-       app_url.host() == "plus.sandbox.google.com");
+       app_url.host() == "plus.sandbox.google.com") &&
+      manifest_url.SchemeIs("https") &&
+      manifest_url.host() == "ssl.gstatic.com" &&
+      (manifest_url.path().find("s2/oz/nacl/") == 1);
 
   bool is_extension_from_webstore =
       extension && extension->from_webstore();
diff --git a/chrome/renderer/chrome_content_renderer_client.h b/chrome/renderer/chrome_content_renderer_client.h
index be628b2..7d8b225 100644
--- a/chrome/renderer/chrome_content_renderer_client.h
+++ b/chrome/renderer/chrome_content_renderer_client.h
@@ -85,12 +85,8 @@
       const WebKit::WebURLError& error,
       std::string* error_html,
       string16* error_description) OVERRIDE;
-  virtual webkit_media::WebMediaPlayerImpl* OverrideCreateWebMediaPlayer(
-      content::RenderView* render_view,
-      WebKit::WebFrame* frame,
-      WebKit::WebMediaPlayerClient* client,
-      base::WeakPtr<webkit_media::WebMediaPlayerDelegate> delegate,
-      const webkit_media::WebMediaPlayerParams& params) OVERRIDE;
+  virtual void DeferMediaLoad(content::RenderView* render_view,
+                              const base::Closure& closure) OVERRIDE;
   virtual bool RunIdleHandlerWhenWidgetsHidden() OVERRIDE;
   virtual bool AllowPopup() OVERRIDE;
   virtual bool ShouldFork(WebKit::WebFrame* frame,
diff --git a/chrome/renderer/chrome_content_renderer_client_unittest.cc b/chrome/renderer/chrome_content_renderer_client_unittest.cc
index 80a6383..aef8e61 100644
--- a/chrome/renderer/chrome_content_renderer_client_unittest.cc
+++ b/chrome/renderer/chrome_content_renderer_client_unittest.cc
@@ -37,6 +37,10 @@
 const char kNaClMimeType[] = "application/x-nacl";
 const char kExtensionUrl[] = "chrome-extension://extension_id/background.html";
 
+const char kAllowedNaClAppURL1[] = "https://plus.google.com";
+const char kAllowedNaClAppURL2[] = "https://plus.sandbox.google.com";
+const char kAllowedNaClManifestURL[] = "https://ssl.gstatic.com/s2/oz/nacl/foo";
+
 bool AllowsDevInterfaces(const WebPluginParams& params) {
   for (size_t i = 0; i < params.attributeNames.size(); ++i) {
     if (params.attributeNames[i] == WebString::fromUTF8("@dev"))
@@ -195,58 +199,71 @@
     EXPECT_TRUE(AllowsDevInterfaces(params));
   }
   // Whitelisted URLs are allowed without --enable-nacl, without 'dev'
-  // interfaces.
+  // interfaces. There is a whitelist for the app URL and the manifest URL.
   {
     WebPluginParams params;
+    // Whitelisted manifest URL, whitelisted app URL root #1 is allowed.
+    EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
+        GURL(kAllowedNaClManifestURL),
+        GURL(kAllowedNaClAppURL1),
+        kNaClRestricted,
+        CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
+        &params));
+    EXPECT_FALSE(AllowsDevInterfaces(params));
+    // Whitelisted manifest URL, whitelisted app URL root #2 is allowed.
+    EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
+        GURL(kAllowedNaClManifestURL),
+        GURL(kAllowedNaClAppURL2),
+        kNaClRestricted,
+        CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
+        &params));
+    EXPECT_FALSE(AllowsDevInterfaces(params));
+
+    // Whitelisted manifest URL, bad app URLs, NOT allowed.
     EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
-        GURL(),
-        GURL("http://plus.google.com/foo"),
+        GURL(kAllowedNaClManifestURL),
+        GURL("http://plus.google.com/foo"),  // http scheme
         kNaClRestricted,
         CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
         &params));
-    EXPECT_FALSE(AllowsDevInterfaces(params));
-    EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
-        GURL(),
-        GURL("https://plus.google.com/foo"),
-        kNaClRestricted,
-        CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
-        &params));
-    EXPECT_FALSE(AllowsDevInterfaces(params));
-    EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
-        GURL(),
-        GURL("https://plus.google.com/209089085730"),
-        kNaClRestricted,
-        CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
-        &params));
-    EXPECT_FALSE(AllowsDevInterfaces(params));
     EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
-        GURL(),
-        GURL("http://plus.sandbox.google.com/foo"),
+        GURL(kAllowedNaClManifestURL),
+        GURL("http://plus.sandbox.google.com/foo"),  // http scheme
         kNaClRestricted,
         CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
         &params));
-    EXPECT_FALSE(AllowsDevInterfaces(params));
-    EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
-        GURL(),
-        GURL("https://plus.sandbox.google.com/foo"),
+    EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
+        GURL(kAllowedNaClManifestURL),
+        GURL("https://plus.google.evil.com/foo"),  // bad host
         kNaClRestricted,
         CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
         &params));
-    EXPECT_FALSE(AllowsDevInterfaces(params));
-    EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
-        GURL(),
-        GURL("https://plus.google.com/209089085730"),
+    // Whitelisted app URL, bad manifest URL, NOT allowed.
+    EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
+        GURL("http://ssl.gstatic.com/s2/oz/nacl/foo"),  // http scheme
+        GURL(kAllowedNaClAppURL1),
         kNaClRestricted,
         CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
         &params));
-    EXPECT_FALSE(AllowsDevInterfaces(params));
+    EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
+        GURL("https://ssl.gstatic.evil.com/s2/oz/nacl/foo"),  // bad host
+        GURL(kAllowedNaClAppURL1),
+        kNaClRestricted,
+        CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
+        &params));
+    EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
+        GURL("https://ssl.gstatic.com/wrong/s2/oz/nacl/foo"),  // bad path
+        GURL(kAllowedNaClAppURL1),
+        kNaClRestricted,
+        CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
+        &params));
   }
   // Whitelisted URLs can't get 'dev' interfaces with --enable-nacl.
   {
     WebPluginParams params;
     EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
-        GURL(),
-        GURL("https://plus.google.com/209089085730"),
+        GURL(kAllowedNaClManifestURL),
+        GURL(kAllowedNaClAppURL1),
         kNaClUnrestricted,
         CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
         &params));
@@ -258,8 +275,8 @@
     WebPluginParams params;
     AddFakeDevAttribute(&params);
     EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
-        GURL(),
-        GURL("https://plus.google.com/209089085730"),
+        GURL(kAllowedNaClManifestURL),
+        GURL(kAllowedNaClAppURL1),
         kNaClRestricted,
         CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
         &params));
diff --git a/chrome/renderer/chrome_render_process_observer.cc b/chrome/renderer/chrome_render_process_observer.cc
index 53fd038..e55baee 100644
--- a/chrome/renderer/chrome_render_process_observer.cc
+++ b/chrome/renderer/chrome_render_process_observer.cc
@@ -24,12 +24,12 @@
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/chrome_version_info.h"
-#include "chrome/common/extensions/extension_localization_peer.h"
 #include "chrome/common/metrics/variations/variations_util.h"
 #include "chrome/common/net/net_resource_provider.h"
 #include "chrome/common/render_messages.h"
 #include "chrome/renderer/chrome_content_renderer_client.h"
 #include "chrome/renderer/content_settings_observer.h"
+#include "chrome/renderer/extensions/extension_localization_peer.h"
 #include "chrome/renderer/security_filter_peer.h"
 #include "content/public/common/resource_dispatcher_delegate.h"
 #include "content/public/renderer/render_thread.h"
diff --git a/chrome/renderer/chrome_render_view_observer.cc b/chrome/renderer/chrome_render_view_observer.cc
index 9f24a89..857604f 100644
--- a/chrome/renderer/chrome_render_view_observer.cc
+++ b/chrome/renderer/chrome_render_view_observer.cc
@@ -51,7 +51,6 @@
 #include "ui/gfx/size.h"
 #include "ui/gfx/skbitmap_operations.h"
 #include "v8/include/v8-testing.h"
-#include "webkit/glue/image_decoder.h"
 #include "webkit/glue/webkit_glue.h"
 
 using WebKit::WebAccessibilityObject;
@@ -666,7 +665,7 @@
     return;
 
   WebKit::WebTextInputType text_input_type =
-      render_view()->GetWebView()->textInputType();
+      render_view()->GetWebView()->textInputInfo().type;
 
   render_view()->Send(new ChromeViewHostMsg_FocusedNodeTouched(
       routing_id(),
diff --git a/chrome/renderer/chrome_render_view_observer.h b/chrome/renderer/chrome_render_view_observer.h
index b72e507..ddaba27 100644
--- a/chrome/renderer/chrome_render_view_observer.h
+++ b/chrome/renderer/chrome_render_view_observer.h
@@ -11,7 +11,7 @@
 
 #include "base/memory/linked_ptr.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/timer.h"
+#include "base/timer/timer.h"
 #include "chrome/common/extensions/permissions/api_permission.h"
 #include "content/public/common/top_controls_state.h"
 #include "content/public/renderer/render_view_observer.h"
diff --git a/chrome/renderer/extensions/OWNERS b/chrome/renderer/extensions/OWNERS
index 199c3a7..33d8609 100644
--- a/chrome/renderer/extensions/OWNERS
+++ b/chrome/renderer/extensions/OWNERS
@@ -3,7 +3,6 @@
 benwells@chromium.org
 erikkay@chromium.org
 finnur@chromium.org
-jeremya@chromium.org
 jyasskin@chromium.org
 kalman@chromium.org
 koz@chromium.org
diff --git a/chrome/renderer/extensions/app_window_custom_bindings.cc b/chrome/renderer/extensions/app_window_custom_bindings.cc
index 3e9f4e6..3c94d57 100644
--- a/chrome/renderer/extensions/app_window_custom_bindings.cc
+++ b/chrome/renderer/extensions/app_window_custom_bindings.cc
@@ -6,6 +6,8 @@
 
 #include <string>
 
+#include "base/command_line.h"
+#include "chrome/common/chrome_switches.h"
 #include "chrome/common/extensions/extension_messages.h"
 #include "chrome/renderer/extensions/chrome_v8_context.h"
 #include "chrome/renderer/extensions/dispatcher.h"
@@ -14,9 +16,11 @@
 #include "content/public/renderer/render_view.h"
 #include "content/public/renderer/render_view_observer.h"
 #include "content/public/renderer/render_view_visitor.h"
+#include "content/public/renderer/v8_value_converter.h"
+#include "grit/renderer_resources.h"
 #include "third_party/WebKit/public/web/WebFrame.h"
 #include "third_party/WebKit/public/web/WebView.h"
-#include "third_party/WebKit/public/web/WebScopedMicrotaskSuppression.h"
+#include "ui/base/resource/resource_bundle.h"
 #include "v8/include/v8.h"
 
 namespace extensions {
@@ -56,73 +60,12 @@
   RouteFunction("GetView",
       base::Bind(&AppWindowCustomBindings::GetView,
                  base::Unretained(this)));
-  RouteFunction("OnContextReady",
-      base::Bind(&AppWindowCustomBindings::OnContextReady,
+
+  RouteFunction("GetWindowControlsHtmlTemplate",
+      base::Bind(&AppWindowCustomBindings::GetWindowControlsHtmlTemplate,
                  base::Unretained(this)));
 }
 
-namespace {
-class LoadWatcher : public content::RenderViewObserver {
- public:
-  LoadWatcher(v8::Isolate* isolate,
-              content::RenderView* view,
-              v8::Handle<v8::Function> cb)
-      : content::RenderViewObserver(view),
-        callback_(cb) {
-  }
-
-  virtual void DidCreateDocumentElement(WebKit::WebFrame* frame) OVERRIDE {
-    CallbackAndDie(frame, true);
-  }
-
-  virtual void DidFailProvisionalLoad(
-      WebKit::WebFrame* frame,
-      const WebKit::WebURLError& error) OVERRIDE {
-    CallbackAndDie(frame, false);
-  }
-
- private:
-  ScopedPersistent<v8::Function> callback_;
-
-  void CallbackAndDie(WebKit::WebFrame* frame, bool succeeded) {
-    v8::HandleScope handle_scope;
-    v8::Local<v8::Context> context = frame->mainWorldScriptContext();
-    v8::Context::Scope scope(context);
-    v8::Local<v8::Object> global = context->Global();
-    {
-      WebKit::WebScopedMicrotaskSuppression suppression;
-      v8::Handle<v8::Value> args[] = {
-        succeeded ? v8::True() : v8::False()
-      };
-      callback_->Call(global, 1, args);
-    }
-    delete this;
-  }
-};
-}  // namespace
-
-void AppWindowCustomBindings::OnContextReady(
-    const v8::FunctionCallbackInfo<v8::Value>& args) {
-  if (args.Length() != 2)
-    return;
-
-  if (!args[0]->IsInt32())
-    return;
-  if (!args[1]->IsFunction())
-    return;
-
-  int view_id = args[0]->Int32Value();
-
-  content::RenderView* view = content::RenderView::FromRoutingID(view_id);
-  if (!view)
-    return;
-
-  v8::Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(args[1]);
-  new LoadWatcher(args.GetIsolate(), view, func);
-
-  args.GetReturnValue().Set(true);
-}
-
 void AppWindowCustomBindings::GetView(
     const v8::FunctionCallbackInfo<v8::Value>& args) {
   // TODO(jeremya): convert this to IDL nocompile to get validation, and turn
@@ -167,4 +110,21 @@
   args.GetReturnValue().Set(window);
 }
 
+void AppWindowCustomBindings::GetWindowControlsHtmlTemplate(
+    const v8::FunctionCallbackInfo<v8::Value>& args) {
+  CHECK_EQ(args.Length(), 0);
+
+  v8::Handle<v8::Value> result = v8::String::Empty();
+  if (CommandLine::ForCurrentProcess()->HasSwitch(
+      switches::kEnableAppWindowControls)) {
+    base::Value* value = base::Value::CreateStringValue(
+        ResourceBundle::GetSharedInstance().GetRawDataResource(
+            IDR_WINDOW_CONTROLS_TEMPLATE_HTML).as_string());
+    scoped_ptr<content::V8ValueConverter> converter(
+        content::V8ValueConverter::create());
+    result = converter->ToV8Value(value, context()->v8_context());
+  }
+  args.GetReturnValue().Set(result);
+}
+
 }  // namespace extensions
diff --git a/chrome/renderer/extensions/app_window_custom_bindings.h b/chrome/renderer/extensions/app_window_custom_bindings.h
index 1c27e10..48635ca 100644
--- a/chrome/renderer/extensions/app_window_custom_bindings.h
+++ b/chrome/renderer/extensions/app_window_custom_bindings.h
@@ -17,7 +17,11 @@
 
  private:
   void GetView(const v8::FunctionCallbackInfo<v8::Value>& args);
-  void OnContextReady(const v8::FunctionCallbackInfo<v8::Value>& args);
+
+  // Return string containing the HTML <template> for the <window-controls>
+  // custom element.
+  void GetWindowControlsHtmlTemplate(
+      const v8::FunctionCallbackInfo<v8::Value>& args);
 
   DISALLOW_COPY_AND_ASSIGN(AppWindowCustomBindings);
 };
diff --git a/chrome/renderer/extensions/chrome_v8_context.cc b/chrome/renderer/extensions/chrome_v8_context.cc
index 79a03dc..e8e18ec 100644
--- a/chrome/renderer/extensions/chrome_v8_context.cc
+++ b/chrome/renderer/extensions/chrome_v8_context.cc
@@ -77,6 +77,8 @@
     int argc,
     v8::Handle<v8::Value> argv[]) const {
   v8::HandleScope handle_scope;
+  v8::Context::Scope scope(v8_context());
+
   WebKit::WebScopedMicrotaskSuppression suppression;
   if (!is_valid())
     return handle_scope.Close(v8::Undefined());
diff --git a/chrome/renderer/extensions/chrome_v8_context_set.cc b/chrome/renderer/extensions/chrome_v8_context_set.cc
index fa7d34b..b9eb580 100644
--- a/chrome/renderer/extensions/chrome_v8_context_set.cc
+++ b/chrome/renderer/extensions/chrome_v8_context_set.cc
@@ -60,10 +60,13 @@
 }
 
 ChromeV8Context* ChromeV8ContextSet::GetCurrent() const {
-  if (!v8::Context::InContext())
-    return NULL;
-  else
-    return GetByV8Context(v8::Context::GetCurrent());
+  return v8::Context::InContext() ?
+      GetByV8Context(v8::Context::GetCurrent()) : NULL;
+}
+
+ChromeV8Context* ChromeV8ContextSet::GetCalling() const {
+  v8::Local<v8::Context> calling = v8::Context::GetCalling();
+  return calling.IsEmpty() ? NULL : GetByV8Context(calling);
 }
 
 ChromeV8Context* ChromeV8ContextSet::GetByV8Context(
diff --git a/chrome/renderer/extensions/chrome_v8_context_set.h b/chrome/renderer/extensions/chrome_v8_context_set.h
index 4781fb1..f47a61f 100644
--- a/chrome/renderer/extensions/chrome_v8_context_set.h
+++ b/chrome/renderer/extensions/chrome_v8_context_set.h
@@ -51,10 +51,14 @@
   typedef std::set<ChromeV8Context*> ContextSet;
   ContextSet GetAll() const;
 
-  // Gets the ChromeV8Context corresponding to the v8::Context that is
-  // on the top of the stack, or NULL if no such context exists.
+  // Gets the ChromeV8Context corresponding to v8::Context::GetCurrent(), or
+  // NULL if no such context exists.
   ChromeV8Context* GetCurrent() const;
 
+  // Gets the ChromeV8Context corresponding to v8::Context::GetCalling(), or
+  // NULL if no such context exists.
+  ChromeV8Context* GetCalling() const;
+
   // Gets the ChromeV8Context corresponding to the specified
   // v8::Context or NULL if no such context exists.
   ChromeV8Context* GetByV8Context(v8::Handle<v8::Context> context) const;
diff --git a/chrome/renderer/extensions/dispatcher.cc b/chrome/renderer/extensions/dispatcher.cc
index 25d32f1..44e3e41 100644
--- a/chrome/renderer/extensions/dispatcher.cc
+++ b/chrome/renderer/extensions/dispatcher.cc
@@ -56,6 +56,7 @@
 #include "chrome/renderer/extensions/object_backed_native_handler.h"
 #include "chrome/renderer/extensions/page_actions_custom_bindings.h"
 #include "chrome/renderer/extensions/page_capture_custom_bindings.h"
+#include "chrome/renderer/extensions/render_view_observer_natives.h"
 #include "chrome/renderer/extensions/request_sender.h"
 #include "chrome/renderer/extensions/runtime_custom_bindings.h"
 #include "chrome/renderer/extensions/safe_builtins.h"
@@ -304,8 +305,12 @@
     RouteFunction("IsSendRequestDisabled",
         base::Bind(&ProcessInfoNativeHandler::IsSendRequestDisabled,
                    base::Unretained(this)));
+    RouteFunction("HasSwitch",
+        base::Bind(&ProcessInfoNativeHandler::HasSwitch,
+                   base::Unretained(this)));
   }
 
+ private:
   void GetExtensionId(const v8::FunctionCallbackInfo<v8::Value>& args) {
     args.GetReturnValue().Set(v8::String::New(extension_id_.c_str()));
   }
@@ -330,7 +335,13 @@
     }
   }
 
- private:
+  void HasSwitch(const v8::FunctionCallbackInfo<v8::Value>& args) {
+    CHECK(args.Length() == 1 && args[0]->IsString());
+    bool has_switch = CommandLine::ForCurrentProcess()->HasSwitch(
+        *v8::String::AsciiValue(args[0]));
+    args.GetReturnValue().Set(v8::Boolean::New(has_switch));
+  }
+
   std::string extension_id_;
   std::string context_type_;
   bool is_incognito_context_;
@@ -510,7 +521,7 @@
 }
 
 void Dispatcher::OnDeliverMessage(int target_port_id,
-                                  const base::ListValue& message) {
+                                  const std::string& message) {
   MiscellaneousBindings::DeliverMessage(
       v8_context_set_.GetAll(),
       target_port_id,
@@ -826,6 +837,8 @@
       content_watcher_->MakeNatives(context));
   module_system->RegisterNativeHandler("activityLogger",
       scoped_ptr<NativeHandler>(new APIActivityLogger(this, context)));
+  module_system->RegisterNativeHandler("renderViewObserverNatives",
+      scoped_ptr<NativeHandler>(new RenderViewObserverNatives(this, context)));
 
   // Natives used by multiple APIs.
   module_system->RegisterNativeHandler("file_system_natives",
@@ -955,6 +968,7 @@
   source_map_.RegisterSource("webRequestInternal",
                              IDR_WEB_REQUEST_INTERNAL_CUSTOM_BINDINGS_JS);
   source_map_.RegisterSource("webstore", IDR_WEBSTORE_CUSTOM_BINDINGS_JS);
+  source_map_.RegisterSource("windowControls", IDR_WINDOW_CONTROLS_JS);
   source_map_.RegisterSource("binding", IDR_BINDING_JS);
 
   // Custom types sources.
@@ -971,10 +985,6 @@
                              IDR_WEB_VIEW_EXPERIMENTAL_JS);
   source_map_.RegisterSource("denyWebView", IDR_WEB_VIEW_DENY_JS);
   source_map_.RegisterSource("adView", IDR_AD_VIEW_JS);
-  if (CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableAdviewSrcAttribute)) {
-    source_map_.RegisterSource("adViewCustom", IDR_AD_VIEW_CUSTOM_JS);
-  }
   source_map_.RegisterSource("denyAdView", IDR_AD_VIEW_DENY_JS);
   source_map_.RegisterSource("platformApp", IDR_PLATFORM_APP_JS);
   source_map_.RegisterSource("injectAppTitlebar", IDR_INJECT_APP_TITLEBAR_JS);
@@ -1077,19 +1087,30 @@
           ChromeRenderProcessObserver::is_incognito_process(),
           manifest_version, send_request_disabled)));
 
-
   // chrome.Event is part of the public API (although undocumented). Make it
-  // lazily evalulate to Event from event_bindings.js.
-  v8::Handle<v8::Object> chrome = AsObjectOrEmpty(GetOrCreateChrome(context));
-  if (!chrome.IsEmpty())
-    module_system->SetLazyField(chrome, "Event", kEventModule, "Event");
+  // lazily evalulate to Event from event_bindings.js. For extensions only
+  // though, not all webpages!
+  if (context->extension()) {
+    v8::Handle<v8::Object> chrome = AsObjectOrEmpty(GetOrCreateChrome(context));
+    if (!chrome.IsEmpty())
+      module_system->SetLazyField(chrome, "Event", kEventModule, "Event");
+  }
 
   AddOrRemoveBindingsForContext(context);
 
   bool is_within_platform_app = IsWithinPlatformApp(frame);
   // Inject custom JS into the platform app context.
-  if (is_within_platform_app)
+  if (is_within_platform_app) {
     module_system->Require("platformApp");
+  }
+
+  if (context_type == Feature::BLESSED_EXTENSION_CONTEXT &&
+      is_within_platform_app &&
+      Feature::GetCurrentChannel() <= chrome::VersionInfo::CHANNEL_DEV &&
+      CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kEnableAppWindowControls)) {
+    module_system->Require("windowControls");
+  }
 
   // Only platform apps support the <webview> tag, because the "webView" and
   // "denyWebView" modules will affect the performance of DOM modifications
@@ -1112,10 +1133,6 @@
       is_within_platform_app) {
     if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableAdview)) {
       if (extension->HasAPIPermission(APIPermission::kAdView)) {
-        if (CommandLine::ForCurrentProcess()->HasSwitch(
-                switches::kEnableAdviewSrcAttribute)) {
-          module_system->Require("adViewCustom");
-        }
         module_system->Require("adView");
       } else {
         module_system->Require("denyAdView");
diff --git a/chrome/renderer/extensions/dispatcher.h b/chrome/renderer/extensions/dispatcher.h
index 2d81dff..8d7a8fd 100644
--- a/chrome/renderer/extensions/dispatcher.h
+++ b/chrome/renderer/extensions/dispatcher.h
@@ -11,14 +11,14 @@
 #include <vector>
 
 #include "base/shared_memory.h"
-#include "base/timer.h"
-#include "content/public/renderer/render_process_observer.h"
+#include "base/timer/timer.h"
 #include "chrome/common/extensions/extension_set.h"
 #include "chrome/common/extensions/features/feature.h"
 #include "chrome/renderer/extensions/chrome_v8_context.h"
 #include "chrome/renderer/extensions/chrome_v8_context_set.h"
 #include "chrome/renderer/extensions/v8_schema_registry.h"
 #include "chrome/renderer/resource_bundle_source_map.h"
+#include "content/public/renderer/render_process_observer.h"
 #include "extensions/common/event_filter.h"
 #include "v8/include/v8.h"
 
@@ -164,7 +164,7 @@
                            const std::string& channel_name,
                            const base::DictionaryValue& source_tab,
                            const ExtensionMsg_ExternalConnectionInfo& info);
-  void OnDeliverMessage(int target_port_id, const base::ListValue& message);
+  void OnDeliverMessage(int target_port_id, const std::string& message);
   void OnDispatchOnDisconnect(int port_id, const std::string& error_message);
   void OnSetFunctionNames(const std::vector<std::string>& names);
   void OnSetSystemFont(const std::string& font_family,
diff --git a/chrome/renderer/extensions/event_bindings.cc b/chrome/renderer/extensions/event_bindings.cc
index 823b85d..1c4e761 100644
--- a/chrome/renderer/extensions/event_bindings.cc
+++ b/chrome/renderer/extensions/event_bindings.cc
@@ -302,6 +302,11 @@
       v8::Handle<v8::Value> url_value(object->Get(url));
       info.SetURL(GURL(*v8::String::AsciiValue(url_value)));
     }
+    v8::Handle<v8::String> instance_id(v8::String::New("instanceId"));
+    if (object->Has(instance_id)) {
+      v8::Handle<v8::Value> instance_id_value(object->Get(instance_id));
+      info.SetInstanceID(instance_id_value->IntegerValue());
+    }
     return info;
   }
 
diff --git a/chrome/renderer/extensions/extension_helper.cc b/chrome/renderer/extensions/extension_helper.cc
index a0b651a..2dc8dc6 100644
--- a/chrome/renderer/extensions/extension_helper.cc
+++ b/chrome/renderer/extensions/extension_helper.cc
@@ -271,9 +271,8 @@
       render_view());
 }
 
-void ExtensionHelper::OnExtensionDeliverMessage(
-    int target_id,
-    const base::ListValue& message) {
+void ExtensionHelper::OnExtensionDeliverMessage(int target_id,
+                                                const std::string& message) {
   MiscellaneousBindings::DeliverMessage(dispatcher_->v8_context_set().GetAll(),
                                         target_id,
                                         message,
diff --git a/chrome/renderer/extensions/extension_helper.h b/chrome/renderer/extensions/extension_helper.h
index 0d4f8b5..07a9b59 100644
--- a/chrome/renderer/extensions/extension_helper.h
+++ b/chrome/renderer/extensions/extension_helper.h
@@ -81,7 +81,7 @@
       const base::DictionaryValue& source_tab,
       const ExtensionMsg_ExternalConnectionInfo& info);
   void OnExtensionDeliverMessage(int target_port_id,
-                                 const base::ListValue& message);
+                                 const std::string& message);
   void OnExtensionDispatchOnDisconnect(int port_id,
                                        const std::string& error_message);
   void OnExecuteCode(const ExtensionMsg_ExecuteCode_Params& params);
diff --git a/chrome/renderer/extensions/extension_localization_peer.cc b/chrome/renderer/extensions/extension_localization_peer.cc
new file mode 100644
index 0000000..03973e6
--- /dev/null
+++ b/chrome/renderer/extensions/extension_localization_peer.cc
@@ -0,0 +1,125 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/renderer/extensions/extension_localization_peer.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_util.h"
+#include "chrome/common/extensions/extension_messages.h"
+#include "chrome/common/extensions/message_bundle.h"
+#include "chrome/common/url_constants.h"
+#include "extensions/common/constants.h"
+#include "grit/generated_resources.h"
+#include "net/base/net_errors.h"
+#include "net/http/http_response_headers.h"
+
+ExtensionLocalizationPeer::ExtensionLocalizationPeer(
+    webkit_glue::ResourceLoaderBridge::Peer* peer,
+    IPC::Sender* message_sender,
+    const GURL& request_url)
+    : original_peer_(peer),
+      message_sender_(message_sender),
+      request_url_(request_url) {
+}
+
+ExtensionLocalizationPeer::~ExtensionLocalizationPeer() {
+}
+
+// static
+ExtensionLocalizationPeer*
+ExtensionLocalizationPeer::CreateExtensionLocalizationPeer(
+    webkit_glue::ResourceLoaderBridge::Peer* peer,
+    IPC::Sender* message_sender,
+    const std::string& mime_type,
+    const GURL& request_url) {
+  // Return NULL if content is not text/css or it doesn't belong to extension
+  // scheme.
+  return (request_url.SchemeIs(extensions::kExtensionScheme) &&
+          StartsWithASCII(mime_type, "text/css", false)) ?
+      new ExtensionLocalizationPeer(peer, message_sender, request_url) : NULL;
+}
+
+void ExtensionLocalizationPeer::OnUploadProgress(
+    uint64 position, uint64 size) {
+  NOTREACHED();
+}
+
+bool ExtensionLocalizationPeer::OnReceivedRedirect(
+    const GURL& new_url,
+    const webkit_glue::ResourceResponseInfo& info,
+    bool* has_new_first_party_for_cookies,
+    GURL* new_first_party_for_cookies) {
+  NOTREACHED();
+  return false;
+}
+
+void ExtensionLocalizationPeer::OnReceivedResponse(
+    const webkit_glue::ResourceResponseInfo& info) {
+  response_info_ = info;
+}
+
+void ExtensionLocalizationPeer::OnReceivedData(const char* data,
+                                               int data_length,
+                                               int encoded_data_length) {
+  data_.append(data, data_length);
+}
+
+void ExtensionLocalizationPeer::OnCompletedRequest(
+    int error_code,
+    bool was_ignored_by_handler,
+    const std::string& security_info,
+    const base::TimeTicks& completion_time) {
+  // Make sure we delete ourselves at the end of this call.
+  scoped_ptr<ExtensionLocalizationPeer> this_deleter(this);
+
+  // Give sub-classes a chance at altering the data.
+  if (error_code != net::OK) {
+    // We failed to load the resource.
+    original_peer_->OnReceivedResponse(response_info_);
+    original_peer_->OnCompletedRequest(net::ERR_ABORTED, false, security_info,
+                                       completion_time);
+    return;
+  }
+
+  ReplaceMessages();
+
+  original_peer_->OnReceivedResponse(response_info_);
+  if (!data_.empty())
+    original_peer_->OnReceivedData(data_.data(),
+                                   static_cast<int>(data_.size()),
+                                   -1);
+  original_peer_->OnCompletedRequest(error_code, was_ignored_by_handler,
+                                     security_info, completion_time);
+}
+
+void ExtensionLocalizationPeer::ReplaceMessages() {
+  if (!message_sender_ || data_.empty())
+    return;
+
+  if (!request_url_.is_valid())
+    return;
+
+  std::string extension_id = request_url_.host();
+  extensions::L10nMessagesMap* l10n_messages =
+      extensions::GetL10nMessagesMap(extension_id);
+  if (!l10n_messages) {
+    extensions::L10nMessagesMap messages;
+    message_sender_->Send(new ExtensionHostMsg_GetMessageBundle(
+        extension_id, &messages));
+
+    // Save messages we got, so we don't have to ask again.
+    // Messages map is never empty, it contains at least @@extension_id value.
+    extensions::ExtensionToL10nMessagesMap& l10n_messages_map =
+        *extensions::GetExtensionToL10nMessagesMap();
+    l10n_messages_map[extension_id] = messages;
+
+    l10n_messages = extensions::GetL10nMessagesMap(extension_id);
+  }
+
+  std::string error;
+  if (extensions::MessageBundle::ReplaceMessagesWithExternalDictionary(
+          *l10n_messages, &data_, &error)) {
+    data_.resize(data_.size());
+  }
+}
diff --git a/chrome/renderer/extensions/extension_localization_peer.h b/chrome/renderer/extensions/extension_localization_peer.h
new file mode 100644
index 0000000..531fd6b
--- /dev/null
+++ b/chrome/renderer/extensions/extension_localization_peer.h
@@ -0,0 +1,83 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_RENDERER_EXTENSIONS_EXTENSION_LOCALIZATION_PEER_H_
+#define CHROME_RENDERER_EXTENSIONS_EXTENSION_LOCALIZATION_PEER_H_
+
+#include <string>
+
+#include "ipc/ipc_sender.h"
+#include "webkit/glue/resource_loader_bridge.h"
+
+// The ExtensionLocalizationPeer is a proxy to a
+// webkit_glue::ResourceLoaderBridge::Peer instance.  It is used to pre-process
+// CSS files requested by extensions to replace localization templates with the
+// appropriate localized strings.
+//
+// Call the factory method CreateExtensionLocalizationPeer() to obtain an
+// instance of ExtensionLocalizationPeer based on the original Peer.
+class ExtensionLocalizationPeer
+    : public webkit_glue::ResourceLoaderBridge::Peer {
+ public:
+  virtual ~ExtensionLocalizationPeer();
+
+  static ExtensionLocalizationPeer* CreateExtensionLocalizationPeer(
+      webkit_glue::ResourceLoaderBridge::Peer* peer,
+      IPC::Sender* message_sender,
+      const std::string& mime_type,
+      const GURL& request_url);
+
+  // ResourceLoaderBridge::Peer methods.
+  virtual void OnUploadProgress(uint64 position, uint64 size) OVERRIDE;
+  virtual bool OnReceivedRedirect(
+      const GURL& new_url,
+      const webkit_glue::ResourceResponseInfo& info,
+      bool* has_new_first_party_for_cookies,
+      GURL* new_first_party_for_cookies) OVERRIDE;
+  virtual void OnReceivedResponse(
+      const webkit_glue::ResourceResponseInfo& info) OVERRIDE;
+  virtual void OnDownloadedData(int len) OVERRIDE {}
+  virtual void OnReceivedData(const char* data,
+                              int data_length,
+                              int encoded_data_length) OVERRIDE;
+  virtual void OnCompletedRequest(
+      int error_code,
+      bool was_ignored_by_handler,
+      const std::string& security_info,
+      const base::TimeTicks& completion_time) OVERRIDE;
+
+ private:
+  friend class ExtensionLocalizationPeerTest;
+
+  // Use CreateExtensionLocalizationPeer to create an instance.
+  ExtensionLocalizationPeer(
+      webkit_glue::ResourceLoaderBridge::Peer* peer,
+      IPC::Sender* message_sender,
+      const GURL& request_url);
+
+  // Loads message catalogs, and replaces all __MSG_some_name__ templates within
+  // loaded file.
+  void ReplaceMessages();
+
+  // Original peer that handles the request once we are done processing data_.
+  webkit_glue::ResourceLoaderBridge::Peer* original_peer_;
+
+  // We just pass though the response info. This holds the copy of the original.
+  webkit_glue::ResourceResponseInfo response_info_;
+
+  // Sends ExtensionHostMsg_GetMessageBundle message to the browser to fetch
+  // message catalog.
+  IPC::Sender* message_sender_;
+
+  // Buffer for incoming data. We wait until OnCompletedRequest before using it.
+  std::string data_;
+
+  // Original request URL.
+  GURL request_url_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ExtensionLocalizationPeer);
+};
+
+#endif  // CHROME_RENDERER_EXTENSIONS_EXTENSION_LOCALIZATION_PEER_H_
diff --git a/chrome/renderer/extensions/extension_localization_peer_unittest.cc b/chrome/renderer/extensions/extension_localization_peer_unittest.cc
new file mode 100644
index 0000000..dd16705
--- /dev/null
+++ b/chrome/renderer/extensions/extension_localization_peer_unittest.cc
@@ -0,0 +1,250 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <map>
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+#include "chrome/common/extensions/message_bundle.h"
+#include "chrome/renderer/extensions/extension_localization_peer.h"
+#include "ipc/ipc_sender.h"
+#include "ipc/ipc_sync_message.h"
+#include "net/base/net_errors.h"
+#include "net/url_request/url_request_status.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/glue/resource_loader_bridge.h"
+
+using testing::_;
+using testing::DoAll;
+using testing::Invoke;
+using testing::StrEq;
+using testing::Return;
+
+static const char* const kExtensionUrl_1 =
+    "chrome-extension://some_id/popup.css";
+
+static const char* const kExtensionUrl_2 =
+    "chrome-extension://some_id2/popup.css";
+
+static const char* const kExtensionUrl_3 =
+    "chrome-extension://some_id3/popup.css";
+
+void MessageDeleter(IPC::Message* message) {
+  delete message;
+}
+
+class MockIpcMessageSender : public IPC::Sender {
+ public:
+  MockIpcMessageSender() {
+    ON_CALL(*this, Send(_))
+        .WillByDefault(DoAll(Invoke(MessageDeleter), Return(true)));
+  }
+
+  virtual ~MockIpcMessageSender() {}
+
+  MOCK_METHOD1(Send, bool(IPC::Message* message));
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockIpcMessageSender);
+};
+
+class MockResourceLoaderBridgePeer
+    : public webkit_glue::ResourceLoaderBridge::Peer {
+ public:
+  MockResourceLoaderBridgePeer() {}
+  virtual ~MockResourceLoaderBridgePeer() {}
+
+  MOCK_METHOD2(OnUploadProgress, void(uint64 position, uint64 size));
+  MOCK_METHOD4(OnReceivedRedirect, bool(
+      const GURL& new_url,
+      const webkit_glue::ResourceResponseInfo& info,
+      bool* has_new_first_party_for_cookies,
+      GURL* new_first_party_for_cookies));
+  MOCK_METHOD1(OnReceivedResponse, void(
+      const webkit_glue::ResourceResponseInfo& info));
+  MOCK_METHOD1(OnDownloadedData, void(int len));
+  MOCK_METHOD3(OnReceivedData, void(const char* data,
+                                    int data_length,
+                                    int encoded_data_length));
+  MOCK_METHOD4(OnCompletedRequest, void(
+      int error_code,
+      bool was_ignored_by_handler,
+      const std::string& security_info,
+      const base::TimeTicks& completion_time));
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockResourceLoaderBridgePeer);
+};
+
+class ExtensionLocalizationPeerTest : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    sender_.reset(new MockIpcMessageSender());
+    original_peer_.reset(new MockResourceLoaderBridgePeer());
+    filter_peer_.reset(
+        ExtensionLocalizationPeer::CreateExtensionLocalizationPeer(
+            original_peer_.get(), sender_.get(), "text/css",
+            GURL(kExtensionUrl_1)));
+  }
+
+  ExtensionLocalizationPeer* CreateExtensionLocalizationPeer(
+      const std::string& mime_type,
+      const GURL& request_url) {
+    return ExtensionLocalizationPeer::CreateExtensionLocalizationPeer(
+        original_peer_.get(), sender_.get(), mime_type, request_url);
+  }
+
+  std::string GetData(ExtensionLocalizationPeer* filter_peer) {
+    EXPECT_TRUE(NULL != filter_peer);
+    return filter_peer->data_;
+  }
+
+  void SetData(ExtensionLocalizationPeer* filter_peer,
+               const std::string& data) {
+    EXPECT_TRUE(NULL != filter_peer);
+    filter_peer->data_ = data;
+  }
+
+  scoped_ptr<MockIpcMessageSender> sender_;
+  scoped_ptr<MockResourceLoaderBridgePeer> original_peer_;
+  scoped_ptr<ExtensionLocalizationPeer> filter_peer_;
+};
+
+TEST_F(ExtensionLocalizationPeerTest, CreateWithWrongMimeType) {
+  filter_peer_.reset(
+      CreateExtensionLocalizationPeer("text/html", GURL(kExtensionUrl_1)));
+  EXPECT_TRUE(NULL == filter_peer_.get());
+}
+
+TEST_F(ExtensionLocalizationPeerTest, CreateWithValidInput) {
+  EXPECT_TRUE(NULL != filter_peer_.get());
+}
+
+TEST_F(ExtensionLocalizationPeerTest, OnReceivedData) {
+  EXPECT_TRUE(GetData(filter_peer_.get()).empty());
+
+  const std::string data_chunk("12345");
+  filter_peer_->OnReceivedData(data_chunk.c_str(), data_chunk.length(), -1);
+
+  EXPECT_EQ(data_chunk, GetData(filter_peer_.get()));
+
+  filter_peer_->OnReceivedData(data_chunk.c_str(), data_chunk.length(), -1);
+  EXPECT_EQ(data_chunk + data_chunk, GetData(filter_peer_.get()));
+}
+
+MATCHER_P(IsURLRequestEqual, status, "") { return arg.status() == status; }
+
+TEST_F(ExtensionLocalizationPeerTest, OnCompletedRequestBadURLRequestStatus) {
+  // It will self-delete once it exits OnCompletedRequest.
+  ExtensionLocalizationPeer* filter_peer = filter_peer_.release();
+
+  EXPECT_CALL(*original_peer_, OnReceivedResponse(_));
+  EXPECT_CALL(*original_peer_, OnCompletedRequest(
+    net::ERR_ABORTED, false, "", base::TimeTicks()));
+
+  filter_peer->OnCompletedRequest(
+      net::ERR_FAILED, false, std::string(), base::TimeTicks());
+}
+
+TEST_F(ExtensionLocalizationPeerTest, OnCompletedRequestEmptyData) {
+  // It will self-delete once it exits OnCompletedRequest.
+  ExtensionLocalizationPeer* filter_peer = filter_peer_.release();
+
+  EXPECT_CALL(*original_peer_, OnReceivedData(_, _, _)).Times(0);
+  EXPECT_CALL(*sender_, Send(_)).Times(0);
+
+  EXPECT_CALL(*original_peer_, OnReceivedResponse(_));
+  EXPECT_CALL(*original_peer_, OnCompletedRequest(
+      net::OK, false, "", base::TimeTicks()));
+
+  filter_peer->OnCompletedRequest(
+      net::OK, false, std::string(), base::TimeTicks());
+}
+
+TEST_F(ExtensionLocalizationPeerTest, OnCompletedRequestNoCatalogs) {
+  // It will self-delete once it exits OnCompletedRequest.
+  ExtensionLocalizationPeer* filter_peer = filter_peer_.release();
+
+  SetData(filter_peer, "some text");
+
+  EXPECT_CALL(*sender_, Send(_));
+
+  std::string data = GetData(filter_peer);
+  EXPECT_CALL(*original_peer_,
+              OnReceivedData(StrEq(data.data()), data.length(), -1)).Times(2);
+
+  EXPECT_CALL(*original_peer_, OnReceivedResponse(_)).Times(2);
+  EXPECT_CALL(*original_peer_, OnCompletedRequest(
+          net::OK, false, "", base::TimeTicks())).Times(2);
+
+  filter_peer->OnCompletedRequest(
+      net::OK, false, std::string(), base::TimeTicks());
+
+  // Test if Send gets called again (it shouldn't be) when first call returned
+  // an empty dictionary.
+  filter_peer =
+      CreateExtensionLocalizationPeer("text/css", GURL(kExtensionUrl_1));
+  SetData(filter_peer, "some text");
+  filter_peer->OnCompletedRequest(
+      net::OK, false, std::string(), base::TimeTicks());
+}
+
+TEST_F(ExtensionLocalizationPeerTest, OnCompletedRequestWithCatalogs) {
+  // It will self-delete once it exits OnCompletedRequest.
+  ExtensionLocalizationPeer* filter_peer =
+      CreateExtensionLocalizationPeer("text/css", GURL(kExtensionUrl_2));
+
+  extensions::L10nMessagesMap messages;
+  messages.insert(std::make_pair("text", "new text"));
+  extensions::ExtensionToL10nMessagesMap& l10n_messages_map =
+      *extensions::GetExtensionToL10nMessagesMap();
+  l10n_messages_map["some_id2"] = messages;
+
+  SetData(filter_peer, "some __MSG_text__");
+
+  // We already have messages in memory, Send will be skipped.
+  EXPECT_CALL(*sender_, Send(_)).Times(0);
+
+  // __MSG_text__ gets replaced with "new text".
+  std::string data("some new text");
+  EXPECT_CALL(*original_peer_,
+              OnReceivedData(StrEq(data.data()), data.length(), -1));
+
+  EXPECT_CALL(*original_peer_, OnReceivedResponse(_));
+  EXPECT_CALL(*original_peer_, OnCompletedRequest(
+      net::OK, false, "", base::TimeTicks()));
+
+  filter_peer->OnCompletedRequest(
+      net::OK, false, std::string(), base::TimeTicks());
+}
+
+TEST_F(ExtensionLocalizationPeerTest, OnCompletedRequestReplaceMessagesFails) {
+  // It will self-delete once it exits OnCompletedRequest.
+  ExtensionLocalizationPeer* filter_peer =
+      CreateExtensionLocalizationPeer("text/css", GURL(kExtensionUrl_3));
+
+  extensions::L10nMessagesMap messages;
+  messages.insert(std::make_pair("text", "new text"));
+  extensions::ExtensionToL10nMessagesMap& l10n_messages_map =
+      *extensions::GetExtensionToL10nMessagesMap();
+  l10n_messages_map["some_id3"] = messages;
+
+  std::string message("some __MSG_missing_message__");
+  SetData(filter_peer, message);
+
+  // We already have messages in memory, Send will be skipped.
+  EXPECT_CALL(*sender_, Send(_)).Times(0);
+
+  // __MSG_missing_message__ is missing, so message stays the same.
+  EXPECT_CALL(*original_peer_,
+              OnReceivedData(StrEq(message.data()), message.length(), -1));
+
+  EXPECT_CALL(*original_peer_, OnReceivedResponse(_));
+  EXPECT_CALL(*original_peer_, OnCompletedRequest(
+      net::OK, false, "", base::TimeTicks()));
+
+  filter_peer->OnCompletedRequest(
+      net::OK, false, std::string(), base::TimeTicks());
+}
diff --git a/chrome/renderer/extensions/miscellaneous_bindings.cc b/chrome/renderer/extensions/miscellaneous_bindings.cc
index 753c9bb..8921d77 100644
--- a/chrome/renderer/extensions/miscellaneous_bindings.cc
+++ b/chrome/renderer/extensions/miscellaneous_bindings.cc
@@ -95,9 +95,10 @@
     if (!renderview)
       return;
 
-    // Arguments are (int32 port_id, object message).
-    CHECK_EQ(2, args.Length());
-    CHECK(args[0]->IsInt32());
+    // Arguments are (int32 port_id, string message).
+    CHECK(args.Length() == 2 &&
+          args[0]->IsInt32() &&
+          args[1]->IsString());
 
     int port_id = args[0]->Int32Value();
     if (!HasPortData(port_id)) {
@@ -106,18 +107,8 @@
       return;
     }
 
-    // The message can be any base::Value but IPC can't serialize that, so we
-    // give it a singleton base::ListValue instead, or an empty list if the
-    // argument was undefined (v8 value converter will return NULL for this).
-    scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
-    scoped_ptr<base::Value> message(
-        converter->FromV8Value(args[1], context()->v8_context()));
-    ListValue message_as_list;
-    if (message)
-      message_as_list.Append(message.release());
-
     renderview->Send(new ExtensionHostMsg_PostMessage(
-        renderview->GetRoutingID(), port_id, message_as_list));
+        renderview->GetRoutingID(), port_id, *v8::String::AsciiValue(args[1])));
   }
 
   // Forcefully disconnects a port.
@@ -284,7 +275,7 @@
 void MiscellaneousBindings::DeliverMessage(
     const ChromeV8ContextSet::ContextSet& contexts,
     int target_port_id,
-    const base::ListValue& message,
+    const std::string& message,
     content::RenderView* restrict_to_render_view) {
   v8::HandleScope handle_scope;
 
@@ -300,9 +291,6 @@
     if ((*it)->v8_context().IsEmpty())
       continue;
 
-    v8::Handle<v8::Context> context = (*it)->v8_context();
-    v8::Context::Scope context_scope(context);
-
     // Check to see whether the context has this port before bothering to create
     // the message.
     v8::Handle<v8::Value> port_id_handle = v8::Integer::New(target_port_id);
@@ -316,19 +304,7 @@
       continue;
 
     std::vector<v8::Handle<v8::Value> > arguments;
-
-    // Convert the message to a v8 object; either a value or undefined.
-    // See PostMessage for more details.
-    if (message.empty()) {
-      arguments.push_back(v8::Undefined());
-    } else {
-      CHECK_EQ(1u, message.GetSize());
-      const base::Value* message_value = NULL;
-      message.Get(0, &message_value);
-      scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
-      arguments.push_back(converter->ToV8Value(message_value, context));
-    }
-
+    arguments.push_back(v8::String::New(message.c_str(), message.size()));
     arguments.push_back(port_id_handle);
     (*it)->module_system()->CallModuleMethod("miscellaneous_bindings",
                                              "dispatchOnMessage",
diff --git a/chrome/renderer/extensions/miscellaneous_bindings.h b/chrome/renderer/extensions/miscellaneous_bindings.h
index 95d0733..79dfeb7 100644
--- a/chrome/renderer/extensions/miscellaneous_bindings.h
+++ b/chrome/renderer/extensions/miscellaneous_bindings.h
@@ -11,7 +11,6 @@
 
 namespace base {
 class DictionaryValue;
-class ListValue;
 }
 
 namespace content {
@@ -56,7 +55,7 @@
   static void DeliverMessage(
       const ChromeV8ContextSet::ContextSet& context_set,
       int target_port_id,
-      const base::ListValue& message,
+      const std::string& message,
       content::RenderView* restrict_to_render_view);
 
   // Dispatches the onDisconnect event in response to the channel being closed.
@@ -67,6 +66,6 @@
       content::RenderView* restrict_to_render_view);
 };
 
-}  // namespace
+}  // namespace extensions
 
 #endif  // CHROME_RENDERER_EXTENSIONS_MISCELLANEOUS_BINDINGS_H_
diff --git a/chrome/renderer/extensions/module_system.cc b/chrome/renderer/extensions/module_system.cc
index c29b440..bcb229e 100644
--- a/chrome/renderer/extensions/module_system.cc
+++ b/chrome/renderer/extensions/module_system.cc
@@ -5,10 +5,12 @@
 #include "chrome/renderer/extensions/module_system.h"
 
 #include "base/bind.h"
+#include "base/command_line.h"
 #include "base/debug/trace_event.h"
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
+#include "chrome/common/chrome_switches.h"
 #include "chrome/common/extensions/extension_messages.h"
 #include "chrome/renderer/extensions/chrome_v8_context.h"
 #include "chrome/renderer/extensions/console.h"
@@ -26,9 +28,50 @@
 const char* kModuleField = "module_field";
 const char* kModulesField = "modules";
 
+// Prepends |extension_id| if it's non-empty to |message|.
+std::string PrependExtensionID(const std::string& extension_id,
+                               const std::string& message) {
+  std::string with_extension_id;
+  if (!extension_id.empty()) {
+    with_extension_id += "(";
+    with_extension_id += extension_id;
+    with_extension_id += ") ";
+  }
+  with_extension_id += message;
+  return with_extension_id;
+}
+
+void Fatal(const std::string& extension_id, const std::string& message) {
+  // Only crash web pages in dev channel.
+  // Always crash extension processes, or when in single process mode (since
+  // typically it's used to debug renderer crashes).
+  bool is_fatal = false;
+  const CommandLine* command_line = CommandLine::ForCurrentProcess();
+  if (command_line->HasSwitch(switches::kExtensionProcess) ||
+      command_line->HasSwitch(switches::kSingleProcess)) {
+    is_fatal = true;
+  } else {
+    // <= dev means dev, canary, and trunk.
+    is_fatal = Feature::GetCurrentChannel() <= chrome::VersionInfo::CHANNEL_DEV;
+  }
+  std::string with_extension_id = PrependExtensionID(extension_id, message);
+  if (is_fatal)
+    console::Fatal(v8::Context::GetCalling(), with_extension_id);
+  else
+    console::Error(v8::Context::GetCalling(), with_extension_id);
+}
+
+void Warn(const std::string& extension_id, const std::string& message) {
+  console::Warn(v8::Context::GetCalling(),
+                PrependExtensionID(extension_id, message));
+}
+
 // Default exception handler which logs the exception.
 class DefaultExceptionHandler : public ModuleSystem::ExceptionHandler {
  public:
+  explicit DefaultExceptionHandler(const std::string& extension_id)
+      : extension_id_(extension_id) {}
+
   // Fatally dumps the debug info from |try_catch| to the console.
   // Make sure this is never used for exceptions that originate in external
   // code!
@@ -42,9 +85,12 @@
       else
         stack_trace = "<could not convert stack trace to string>";
     }
-    console::Fatal(v8::Context::GetCalling(),
-                   CreateExceptionString(try_catch) + "{" + stack_trace + "}");
+    Fatal(extension_id_,
+          CreateExceptionString(try_catch) + "{" + stack_trace + "}");
   }
+
+ private:
+  std::string extension_id_;
 };
 
 } // namespace
@@ -81,7 +127,8 @@
       context_(context),
       source_map_(source_map),
       natives_enabled_(0),
-      exception_handler_(new DefaultExceptionHandler()) {
+      exception_handler_(
+          new DefaultExceptionHandler(context->GetExtensionID())) {
   RouteFunction("require",
       base::Bind(&ModuleSystem::RequireForJs, base::Unretained(this)));
   RouteFunction("requireNative",
@@ -159,7 +206,7 @@
   v8::Handle<v8::Value> modules_value =
       global->GetHiddenValue(v8::String::New(kModulesField));
   if (modules_value.IsEmpty() || modules_value->IsUndefined()) {
-    console::Warn(v8::Context::GetCalling(), "Extension view no longer exists");
+    Warn(context_->GetExtensionID(), "Extension view no longer exists");
     return v8::Undefined();
   }
 
@@ -171,8 +218,8 @@
   std::string module_name_str = *v8::String::AsciiValue(module_name);
   v8::Handle<v8::Value> source(GetSource(module_name_str));
   if (source.IsEmpty() || source->IsUndefined()) {
-    console::Error(v8::Context::GetCalling(),
-                   "No source for require(" + module_name_str + ")");
+    Fatal(context_->GetExtensionID(),
+          "No source for require(" + module_name_str + ")");
     return v8::Undefined();
   }
   v8::Handle<v8::String> wrapped_source(WrapSource(
@@ -180,8 +227,8 @@
   // Modules are wrapped in (function(){...}) so they always return functions.
   v8::Handle<v8::Value> func_as_value = RunString(wrapped_source, module_name);
   if (func_as_value.IsEmpty() || func_as_value->IsUndefined()) {
-    console::Error(v8::Context::GetCalling(),
-                   "Bad source for require(" + module_name_str + ")");
+    Fatal(context_->GetExtensionID(),
+          "Bad source for require(" + module_name_str + ")");
     return v8::Undefined();
   }
 
@@ -189,6 +236,8 @@
 
   exports = v8::Object::New();
   v8::Handle<v8::Object> natives(NewInstance());
+  CHECK(!natives.IsEmpty());  // this can happen if v8 has issues
+
   // These must match the argument order in WrapSource.
   v8::Handle<v8::Value> args[] = {
     // CommonJS.
@@ -198,7 +247,10 @@
     // Each safe builtin. Keep in order with the arguments in WrapSource.
     context_->safe_builtins()->GetArray(),
     context_->safe_builtins()->GetFunction(),
+    context_->safe_builtins()->GetJSON(),
     context_->safe_builtins()->GetObjekt(),
+    context_->safe_builtins()->GetRegExp(),
+    context_->safe_builtins()->GetString(),
   };
   {
     v8::TryCatch try_catch;
@@ -249,9 +301,8 @@
   }
 
   if (module.IsEmpty() || !module->IsObject()) {
-    console::Error(
-        v8::Context::GetCalling(),
-        "Failed to get module " + module_name + " to call " + method_name);
+    Fatal(context_->GetExtensionID(),
+          "Failed to get module " + module_name + " to call " + method_name);
     return handle_scope.Close(v8::Undefined());
   }
 
@@ -259,8 +310,8 @@
       v8::Handle<v8::Object>::Cast(module)->Get(
           v8::String::New(method_name.c_str()));
   if (value.IsEmpty() || !value->IsFunction()) {
-    console::Error(v8::Context::GetCalling(),
-                   module_name + "." + method_name + " is not a function");
+    Fatal(context_->GetExtensionID(),
+          module_name + "." + method_name + " is not a function");
     return handle_scope.Close(v8::Undefined());
   }
 
@@ -324,8 +375,7 @@
   if (module_system_value.IsEmpty() || !module_system_value->IsExternal()) {
     // ModuleSystem has been deleted.
     // TODO(kalman): See comment in header file.
-    console::Warn(v8::Context::GetCalling(),
-                  "Module system has been deleted, does extension view exist?");
+    Warn("", "Module system has been deleted, does extension view exist?");
     return;
   }
 
@@ -357,9 +407,9 @@
 
   if (!module->Has(field)) {
     std::string field_str = *v8::String::AsciiValue(field);
-    console::Fatal(v8::Context::GetCalling(),
-                   "Lazy require of " + name + "." + field_str + " did not " +
-                   "set the " + field_str + " field");
+    Fatal(module_system->context_->GetExtensionID(),
+          "Lazy require of " + name + "." + field_str + " did not " +
+              "set the " + field_str + " field");
     return;
   }
 
@@ -459,8 +509,8 @@
     // we could crash.
     if (exception_handler_)
       return v8::ThrowException(v8::String::New("Natives disabled"));
-    console::Fatal(v8::Context::GetCalling(),
-                   "Natives disabled for requireNative(" + native_name + ")");
+    Fatal(context_->GetExtensionID(),
+          "Natives disabled for requireNative(" + native_name + ")");
     return v8::Undefined();
   }
 
@@ -469,9 +519,8 @@
 
   NativeHandlerMap::iterator i = native_handler_map_.find(native_name);
   if (i == native_handler_map_.end()) {
-    console::Fatal(
-        v8::Context::GetCalling(),
-        "Couldn't find native for requireNative(" + native_name + ")");
+    Fatal(context_->GetExtensionID(),
+          "Couldn't find native for requireNative(" + native_name + ")");
     return v8::Undefined();
   }
   return i->second->NewInstance();
@@ -482,7 +531,7 @@
   // Keep in order with the arguments in RequireForJsInner.
   v8::Handle<v8::String> left = v8::String::New(
       "(function(require, requireNative, exports,"
-                "$Array, $Function, $Object) {"
+                "$Array, $Function, $JSON, $Object, $RegExp, $String) {"
        "'use strict';");
   v8::Handle<v8::String> right = v8::String::New("\n})");
   return handle_scope.Close(
diff --git a/chrome/renderer/extensions/render_view_observer_natives.cc b/chrome/renderer/extensions/render_view_observer_natives.cc
new file mode 100644
index 0000000..32a351d
--- /dev/null
+++ b/chrome/renderer/extensions/render_view_observer_natives.cc
@@ -0,0 +1,81 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/renderer/extensions/render_view_observer_natives.h"
+
+#include "chrome/common/extensions/api/extension_api.h"
+#include "chrome/renderer/extensions/dispatcher.h"
+#include "content/public/renderer/render_view.h"
+#include "content/public/renderer/render_view_observer.h"
+#include "third_party/WebKit/public/web/WebFrame.h"
+#include "third_party/WebKit/public/web/WebScopedMicrotaskSuppression.h"
+
+namespace extensions {
+
+namespace {
+
+// Deletes itself when done.
+class LoadWatcher : public content::RenderViewObserver {
+ public:
+  LoadWatcher(ChromeV8Context* context,
+              content::RenderView* view,
+              v8::Handle<v8::Function> cb)
+      : content::RenderViewObserver(view),
+        context_(context),
+        callback_(cb) {
+  }
+
+  virtual void DidCreateDocumentElement(WebKit::WebFrame* frame) OVERRIDE {
+    CallbackAndDie(true);
+  }
+
+  virtual void DidFailProvisionalLoad(
+      WebKit::WebFrame* frame,
+      const WebKit::WebURLError& error) OVERRIDE {
+    CallbackAndDie(false);
+  }
+
+ private:
+  void CallbackAndDie(bool succeeded) {
+    v8::HandleScope handle_scope;
+    v8::Handle<v8::Value> args[] = { v8::Boolean::New(succeeded) };
+    context_->CallFunction(callback_.get(), 1, args);
+    delete this;
+  }
+
+  ChromeV8Context* context_;
+  ScopedPersistent<v8::Function> callback_;
+  DISALLOW_COPY_AND_ASSIGN(LoadWatcher);
+};
+}  // namespace
+
+
+RenderViewObserverNatives::RenderViewObserverNatives(Dispatcher* dispatcher,
+                                                     ChromeV8Context* context)
+    : ChromeV8Extension(dispatcher, context) {
+  RouteFunction("OnDocumentElementCreated",
+                base::Bind(&RenderViewObserverNatives::OnDocumentElementCreated,
+                           base::Unretained(this)));
+}
+
+void RenderViewObserverNatives::OnDocumentElementCreated(
+    const v8::FunctionCallbackInfo<v8::Value>& args) {
+  CHECK(args.Length() == 2);
+  CHECK(args[0]->IsInt32());
+  CHECK(args[1]->IsFunction());
+
+  int view_id = args[0]->Int32Value();
+
+  content::RenderView* view = content::RenderView::FromRoutingID(view_id);
+  if (!view) {
+    LOG(WARNING) << "No render view found to register LoadWatcher.";
+    return;
+  }
+
+  new LoadWatcher(context(), view, args[1].As<v8::Function>());
+
+  args.GetReturnValue().Set(true);
+}
+
+}  // namespace extensions
diff --git a/chrome/renderer/extensions/render_view_observer_natives.h b/chrome/renderer/extensions/render_view_observer_natives.h
new file mode 100644
index 0000000..cb2390a
--- /dev/null
+++ b/chrome/renderer/extensions/render_view_observer_natives.h
@@ -0,0 +1,32 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_RENDERER_EXTENSIONS_RENDER_VIEW_OBSERVER_NATIVES_H_
+#define CHROME_RENDERER_EXTENSIONS_RENDER_VIEW_OBSERVER_NATIVES_H_
+
+#include "chrome/renderer/extensions/chrome_v8_extension.h"
+#include "v8/include/v8.h"
+
+class ChromeV8Context;
+
+namespace extensions {
+
+class Dispatcher;
+
+// Native functions for JS to run callbacks upon RenderView events.
+class RenderViewObserverNatives : public ChromeV8Extension {
+ public:
+  RenderViewObserverNatives(Dispatcher* dispatcher, ChromeV8Context* context);
+
+ private:
+  // Runs a callback upon creation of new document element inside a render view
+  // (document.documentElement).
+  void OnDocumentElementCreated(
+      const v8::FunctionCallbackInfo<v8::Value>& args);
+  DISALLOW_COPY_AND_ASSIGN(RenderViewObserverNatives);
+};
+
+}  // namespace extensions
+
+#endif  // CHROME_RENDERER_EXTENSIONS_RENDER_VIEW_OBSERVER_NATIVES_H_
diff --git a/chrome/renderer/extensions/safe_builtins.cc b/chrome/renderer/extensions/safe_builtins.cc
index c28b077..dbb85b7 100644
--- a/chrome/renderer/extensions/safe_builtins.cc
+++ b/chrome/renderer/extensions/safe_builtins.cc
@@ -28,6 +28,7 @@
 // This is a convenient way to save functions that user scripts may clobber.\n"
 const char kScript[] =
     "(function() {\n"
+    "'use strict';\n"
     "native function Apply();\n"
     "native function Save();\n"
     "\n"
@@ -52,16 +53,69 @@
     "  });\n"
     "}\n"
     "\n"
-    "function getSafeBuiltin(builtin) {\n"
-    "  var safe = {};\n"
+    "function getSafeBuiltin(builtin, includePrototype) {\n"
+    "  var safe = function() {\n"
+    "    throw 'Safe objects cannot be called nor constructed. ' +\n"
+    "          'Use $Foo.self() or new $Foo.self() instead.';\n"
+    "  };\n"
+    "  safe.self = builtin;\n"
     "  makeCallable(builtin, safe, true);\n"
-    "  makeCallable(builtin.prototype, safe, false);\n"
+    "  if (includePrototype)\n"
+    "    makeCallable(builtin.prototype, safe, false);\n"
     "  return safe;\n"
     "}\n"
     "\n"
-    "[Array, Function, Object].forEach(function(builtin) {\n"
-    "  Save(builtin.name, getSafeBuiltin(builtin));\n"
+    "// Built-in types taken from the ECMAScript spec. The spec may change,\n"
+    "// though. It would be nice to generate this somehow.\n"
+    "// Note: no JSON, it needs to handle toJSON being overriden so is\n"
+    "//       implemented by hand.\n"
+    "// Note: no Math, it's static (we also don't need it yet).\n"
+    "// Note: the other things that are commented out are ones that aren't\n"
+    "//       needed to make the clobber tests pass, because running this\n"
+    "//       file is a bit slow.\n"
+    "var builtinTypes = [\n"
+    "    Object, Function, Array, String, /*Boolean, Number,*/\n"
+    "    /*Math, Date,*/ RegExp, /*JSON, Error, EvalError,\n"
+    "    ReferenceError, SyntaxError, TypeError, URIError*/];\n"
+    "builtinTypes.forEach(function(builtin) {\n"
+    "  Save(builtin.name, getSafeBuiltin(builtin, true));\n"
     "});\n"
+    "//Save('Math', getSafeBuiltin(Math, false));\n"
+    "// Save JSON. This is trickier because extensions can override toJSON in\n"
+    "// incompatible ways, and we need to prevent that.\n"
+    "var builtinToJSONs = builtinTypes.map(function(t) {\n"
+    "  return t.toJSON;\n"
+    "});\n"
+    "var builtinArray = Array;\n"
+    "var builtinJSONStringify = JSON.stringify;\n"
+    "Save('JSON', {\n"
+    "  parse: JSON.parse,\n"
+    "  stringify: function(obj) {\n"
+    "    var savedToJSONs = new builtinArray(builtinTypes.length);\n"
+    "    try {\n"
+    "      for (var i = 0; i < builtinTypes.length; ++i) {\n"
+    "        try {\n"
+    "          if (builtinTypes[i].prototype.toJSON !==\n"
+    "              builtinToJSONs[i]) {\n"
+    "            savedToJSONs[i] = builtinTypes[i].prototype.toJSON;\n"
+    "            builtinTypes[i].prototype.toJSON = builtinToJSONs[i];\n"
+    "          }\n"
+    "        } catch (e) {}\n"
+    "      }\n"
+    "    } catch (e) {}\n"
+    "    try {\n"
+    "      return builtinJSONStringify(obj);\n"
+    "    } finally {\n"
+    "      for (var i = 0; i < builtinTypes.length; ++i) {\n"
+    "        try {\n"
+    "          if (i in savedToJSONs)\n"
+    "            builtinTypes[i].prototype.toJSON = savedToJSONs[i];\n"
+    "        } catch (e) {}\n"
+    "      }\n"
+    "    }\n"
+    "  }\n"
+    "});\n"
+    "\n"
     "}());\n";
 
 v8::Local<v8::String> MakeKey(const char* name) {
@@ -101,17 +155,21 @@
   static void Apply(const v8::FunctionCallbackInfo<v8::Value>& info) {
     CHECK(info.Length() == 5 &&
           info[0]->IsFunction() &&  // function
-          // info[1]->Object()      // recv (will throw error not check)
+          // info[1] could be an object or a string
           info[2]->IsObject() &&    // args
           info[3]->IsInt32() &&     // first_arg_index
           info[4]->IsInt32());      // args_length
-    if (!info[1]->IsObject()) {
+    v8::Local<v8::Function> function = info[0].As<v8::Function>();
+    v8::Local<v8::Object> recv;
+    if (info[1]->IsObject()) {
+      recv = info[1]->ToObject();
+    } else if (info[1]->IsString()) {
+      recv = v8::StringObject::New(info[1]->ToString())->ToObject();
+    } else {
       v8::ThrowException(v8::Exception::TypeError(v8::String::New(
           "The first argument is the receiver and must be an object")));
       return;
     }
-    v8::Local<v8::Function> function = info[0].As<v8::Function>();
-    v8::Local<v8::Object> recv = info[1]->ToObject();
     v8::Local<v8::Object> args = info[2]->ToObject();
     int first_arg_index = static_cast<int>(info[3]->ToInt32()->Value());
     int args_length = static_cast<int>(info[4]->ToInt32()->Value());
@@ -157,8 +215,20 @@
   return Load("Function", context_->v8_context());
 }
 
+v8::Local<v8::Object> SafeBuiltins::GetJSON() const {
+  return Load("JSON", context_->v8_context());
+}
+
 v8::Local<v8::Object> SafeBuiltins::GetObjekt() const {
   return Load("Object", context_->v8_context());
 }
 
+v8::Local<v8::Object> SafeBuiltins::GetRegExp() const {
+  return Load("RegExp", context_->v8_context());
+}
+
+v8::Local<v8::Object> SafeBuiltins::GetString() const {
+  return Load("String", context_->v8_context());
+}
+
 } //  namespace extensions
diff --git a/chrome/renderer/extensions/safe_builtins.h b/chrome/renderer/extensions/safe_builtins.h
index c2dcb4d..f34a949 100644
--- a/chrome/renderer/extensions/safe_builtins.h
+++ b/chrome/renderer/extensions/safe_builtins.h
@@ -30,9 +30,12 @@
   //   Object.keys.call(...) becomes Object.keys(...)
   v8::Local<v8::Object> GetArray() const;
   v8::Local<v8::Object> GetFunction() const;
+  v8::Local<v8::Object> GetJSON() const;
   // NOTE(kalman): VS2010 won't compile "GetObject", it mysteriously renames it
   // to "GetObjectW" - hence GetObjekt. Sorry.
   v8::Local<v8::Object> GetObjekt() const;
+  v8::Local<v8::Object> GetRegExp() const;
+  v8::Local<v8::Object> GetString() const;
 
  private:
   ChromeV8Context* context_;
diff --git a/chrome/renderer/extensions/safe_builtins_unittest.cc b/chrome/renderer/extensions/safe_builtins_unittest.cc
new file mode 100644
index 0000000..effc087
--- /dev/null
+++ b/chrome/renderer/extensions/safe_builtins_unittest.cc
@@ -0,0 +1,68 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/test/base/module_system_test.h"
+
+#include "grit/renderer_resources.h"
+
+namespace extensions {
+namespace {
+
+class SafeBuiltinsUnittest : public ModuleSystemTest {
+};
+
+TEST_F(SafeBuiltinsUnittest, TestNotOriginalObject) {
+  ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
+  RegisterModule("test",
+      "var assert = requireNative('assert');\n"
+      "Array.foo = 10;\n"
+      "assert.AssertTrue(!$Array.hasOwnProperty('foo'));\n"
+  );
+  module_system_->Require("test");
+}
+
+TEST_F(SafeBuiltinsUnittest, TestSelf) {
+  ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
+  RegisterModule("test",
+      "var assert = requireNative('assert');\n"
+      "Array.foo = 10;\n"
+      "assert.AssertTrue($Array.self.foo == 10);\n"
+      "var arr = $Array.self(1);\n"
+      "assert.AssertTrue(arr.length == 1);\n"
+      "assert.AssertTrue(arr[0] === undefined);\n"
+  );
+  module_system_->Require("test");
+}
+
+TEST_F(SafeBuiltinsUnittest, TestStaticFunction) {
+  ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
+  RegisterModule("test",
+      "var assert = requireNative('assert');\n"
+      "Object.getOwnPropertyNames = function() {throw new Error()};\n"
+      "var obj = {a: 10};\n"
+      "var propertyNames = $Object.getOwnPropertyNames(obj);\n"
+      "assert.AssertTrue(propertyNames.length == 1);\n"
+      "assert.AssertTrue(propertyNames[0] == 'a');\n"
+  );
+  module_system_->Require("test");
+}
+
+TEST_F(SafeBuiltinsUnittest, TestInstanceMethod) {
+  ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
+  RegisterModule("test",
+      "var assert = requireNative('assert');\n"
+      "Array.prototype.push = function() {throw new Error();}\n"
+      "var arr = []\n"
+      "$Array.push(arr, 1);\n"
+      "assert.AssertTrue(arr.length == 1);\n"
+      "assert.AssertTrue(arr[0] == 1);\n"
+  );
+  module_system_->Require("test");
+}
+
+// NOTE: JSON is already tested in ExtensionApiTest.Messaging, via
+// chrome/test/data/extensions/api_test/messaging/connect/page.js.
+
+}  // namespace
+}  // namespace extensions
diff --git a/chrome/renderer/loadtimes_extension_bindings.cc b/chrome/renderer/loadtimes_extension_bindings.cc
index d49c473..9d32397 100644
--- a/chrome/renderer/loadtimes_extension_bindings.cc
+++ b/chrome/renderer/loadtimes_extension_bindings.cc
@@ -6,7 +6,7 @@
 
 #include <math.h>
 
-#include "base/time.h"
+#include "base/time/time.h"
 #include "content/public/renderer/document_state.h"
 #include "net/http/http_response_info.h"
 #include "third_party/WebKit/public/web/WebFrame.h"
diff --git a/chrome/renderer/media/chrome_webrtc_log_message_delegate.cc b/chrome/renderer/media/chrome_webrtc_log_message_delegate.cc
new file mode 100644
index 0000000..67e6882
--- /dev/null
+++ b/chrome/renderer/media/chrome_webrtc_log_message_delegate.cc
@@ -0,0 +1,77 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/renderer/media/chrome_webrtc_log_message_delegate.h"
+
+#include "base/logging.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "chrome/common/partial_circular_buffer.h"
+#include "chrome/renderer/media/webrtc_logging_message_filter.h"
+
+ChromeWebRtcLogMessageDelegate::ChromeWebRtcLogMessageDelegate(
+    const scoped_refptr<base::MessageLoopProxy>& io_message_loop,
+    WebRtcLoggingMessageFilter* message_filter)
+    : io_message_loop_(io_message_loop),
+      message_filter_(message_filter),
+      log_initialized_(false) {
+  content::InitWebRtcLoggingDelegate(this);
+}
+
+ChromeWebRtcLogMessageDelegate::~ChromeWebRtcLogMessageDelegate() {
+  DCHECK(CalledOnValidThread());
+}
+
+void ChromeWebRtcLogMessageDelegate::InitLogging(
+    const std::string& app_session_id,
+    const std::string& app_url) {
+  DCHECK(CalledOnValidThread());
+
+  if (!log_initialized_) {
+    log_initialized_ = true;
+    message_filter_->InitLogging(app_session_id, app_url);
+  }
+}
+
+void ChromeWebRtcLogMessageDelegate::LogMessage(const std::string& message) {
+  if (!CalledOnValidThread()) {
+    io_message_loop_->PostTask(
+        FROM_HERE, base::Bind(
+            &ChromeWebRtcLogMessageDelegate::LogMessage,
+            base::Unretained(this),
+            message));
+    return;
+  }
+
+  if (circular_buffer_) {
+    circular_buffer_->Write(message.c_str(), message.length());
+    const char eol = '\n';
+    circular_buffer_->Write(&eol, 1);
+  }
+}
+
+void ChromeWebRtcLogMessageDelegate::OnFilterRemoved() {
+  DCHECK(CalledOnValidThread());
+  message_filter_ = NULL;
+}
+
+void ChromeWebRtcLogMessageDelegate::OnLogOpened(
+    base::SharedMemoryHandle handle,
+    uint32 length) {
+  DCHECK(CalledOnValidThread());
+
+  shared_memory_.reset(new base::SharedMemory(handle, false));
+  CHECK(shared_memory_->Map(length));
+  circular_buffer_.reset(
+      new PartialCircularBuffer(shared_memory_->memory(),
+                                length,
+                                length / 2,
+                                true));
+}
+
+void ChromeWebRtcLogMessageDelegate::OnOpenLogFailed() {
+  DCHECK(CalledOnValidThread());
+  DLOG(ERROR) << "Could not open log.";
+  // TODO(grunell): Implement.
+  NOTIMPLEMENTED();
+}
diff --git a/chrome/renderer/media/chrome_webrtc_log_message_delegate.h b/chrome/renderer/media/chrome_webrtc_log_message_delegate.h
new file mode 100644
index 0000000..0ce6e4d
--- /dev/null
+++ b/chrome/renderer/media/chrome_webrtc_log_message_delegate.h
@@ -0,0 +1,56 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_RENDERER_MEDIA_CHROME_WEBRTC_LOG_MESSAGE_DELEGATE_H_
+#define CHROME_RENDERER_MEDIA_CHROME_WEBRTC_LOG_MESSAGE_DELEGATE_H_
+
+#include <string>
+
+#include "base/shared_memory.h"
+#include "content/public/renderer/webrtc_log_message_delegate.h"
+#include "ipc/ipc_channel_proxy.h"
+
+namespace base {
+class MessageLoopProxy;
+}
+
+class PartialCircularBuffer;
+class WebRtcLoggingMessageFilter;
+
+// ChromeWebRtcLogMessageDelegate handles WebRTC logging. There is one object
+// per render process, owned by WebRtcLoggingMessageFilter. It communicates with
+// WebRtcLoggingHandlerHost and receives logging messages from libjingle and
+// writes them to a shared memory buffer.
+class ChromeWebRtcLogMessageDelegate
+    : public content::WebRtcLogMessageDelegate,
+      public base::NonThreadSafe {
+ public:
+  ChromeWebRtcLogMessageDelegate(
+      const scoped_refptr<base::MessageLoopProxy>& io_message_loop,
+      WebRtcLoggingMessageFilter* message_filter);
+
+  virtual ~ChromeWebRtcLogMessageDelegate();
+
+  // content::WebRtcLogMessageDelegate implementation.
+  virtual void InitLogging(const std::string& app_session_id,
+                           const std::string& app_url) OVERRIDE;
+  virtual void LogMessage(const std::string& message) OVERRIDE;
+
+  void OnFilterRemoved();
+
+  void OnLogOpened(base::SharedMemoryHandle handle, uint32 length);
+  void OnOpenLogFailed();
+
+ private:
+  scoped_refptr<base::MessageLoopProxy> io_message_loop_;
+  scoped_ptr<base::SharedMemory> shared_memory_;
+  scoped_ptr<PartialCircularBuffer> circular_buffer_;
+
+  WebRtcLoggingMessageFilter* message_filter_;
+  bool log_initialized_;
+
+  DISALLOW_COPY_AND_ASSIGN(ChromeWebRtcLogMessageDelegate);
+};
+
+#endif  // CHROME_RENDERER_MEDIA_CHROME_WEBRTC_LOG_MESSAGE_DELEGATE_H_
diff --git a/chrome/renderer/media/chrome_webrtc_log_message_delegate_unittest.cc b/chrome/renderer/media/chrome_webrtc_log_message_delegate_unittest.cc
new file mode 100644
index 0000000..90fca67
--- /dev/null
+++ b/chrome/renderer/media/chrome_webrtc_log_message_delegate_unittest.cc
@@ -0,0 +1,47 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+
+#include "base/process_util.h"
+#include "chrome/common/partial_circular_buffer.h"
+#include "chrome/renderer/media/chrome_webrtc_log_message_delegate.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+TEST(ChromeWebRtcLogMessageDelegateTest, Basic) {
+  const uint32 kTestLogSize = 1024;  // 1 KB
+  const char kTestString[] = "abcdefghijklmnopqrstuvwxyz";
+
+  base::MessageLoop message_loop(base::MessageLoop::TYPE_IO);
+
+  scoped_ptr<ChromeWebRtcLogMessageDelegate> log_message_delegate(
+      new ChromeWebRtcLogMessageDelegate(message_loop.message_loop_proxy(),
+                                         NULL));
+
+  base::SharedMemory shared_memory;
+  ASSERT_TRUE(shared_memory.CreateAndMapAnonymous(kTestLogSize));
+  base::SharedMemoryHandle new_handle;
+  ASSERT_TRUE(shared_memory.ShareToProcess(base::GetCurrentProcessHandle(),
+                                           &new_handle));
+  log_message_delegate->OnLogOpened(new_handle, kTestLogSize);
+
+  log_message_delegate->LogMessage(kTestString);
+  log_message_delegate->LogMessage(kTestString);
+
+  PartialCircularBuffer read_pcb(
+      reinterpret_cast<uint8*>(shared_memory.memory()), kTestLogSize);
+
+  // Size is calculated as (sizeof(kTestString) - 1 for terminating null
+  // + 1 for eol added for each log message in LogMessage) * 2 + 1 for
+  // terminating null.
+  char read_buffer[sizeof(kTestString) * 2 + 1] = {0};
+
+  uint32 read = read_pcb.Read(read_buffer, sizeof(read_buffer));
+  EXPECT_EQ(sizeof(read_buffer) - 1, read);
+  std::string ref_output = kTestString;
+  ref_output.append("\n");
+  ref_output.append(kTestString);
+  ref_output.append("\n");
+  EXPECT_STREQ(ref_output.c_str(), read_buffer);
+}
diff --git a/chrome/renderer/media/webrtc_logging_handler_impl.cc b/chrome/renderer/media/webrtc_logging_handler_impl.cc
deleted file mode 100644
index ec2ace4..0000000
--- a/chrome/renderer/media/webrtc_logging_handler_impl.cc
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/renderer/media/webrtc_logging_handler_impl.h"
-
-#include "base/logging.h"
-#include "base/message_loop/message_loop_proxy.h"
-#include "chrome/common/partial_circular_buffer.h"
-#include "chrome/renderer/media/webrtc_logging_message_filter.h"
-
-WebRtcLoggingHandlerImpl::WebRtcLoggingHandlerImpl(
-    const scoped_refptr<base::MessageLoopProxy>& io_message_loop,
-    WebRtcLoggingMessageFilter* message_filter)
-    : io_message_loop_(io_message_loop),
-      message_filter_(message_filter),
-      log_initialized_(false) {
-  content::InitWebRtcLoggingDelegate(this);
-}
-
-WebRtcLoggingHandlerImpl::~WebRtcLoggingHandlerImpl() {
-  DCHECK(CalledOnValidThread());
-}
-
-void WebRtcLoggingHandlerImpl::InitLogging(const std::string& app_session_id,
-                                           const std::string& app_url) {
-  DCHECK(CalledOnValidThread());
-
-  if (!log_initialized_) {
-    log_initialized_ = true;
-    message_filter_->InitLogging(app_session_id, app_url);
-  }
-}
-
-void WebRtcLoggingHandlerImpl::LogMessage(const std::string& message) {
-  if (!CalledOnValidThread()) {
-    io_message_loop_->PostTask(
-        FROM_HERE, base::Bind(
-            &WebRtcLoggingHandlerImpl::LogMessage,
-            base::Unretained(this),
-            message));
-    return;
-  }
-
-  if (circular_buffer_) {
-    circular_buffer_->Write(message.c_str(), message.length());
-    const char eol = '\n';
-    circular_buffer_->Write(&eol, 1);
-  }
-}
-
-void WebRtcLoggingHandlerImpl::OnFilterRemoved() {
-  DCHECK(CalledOnValidThread());
-  message_filter_ = NULL;
-}
-
-void WebRtcLoggingHandlerImpl::OnLogOpened(
-    base::SharedMemoryHandle handle,
-    uint32 length) {
-  DCHECK(CalledOnValidThread());
-
-  shared_memory_.reset(new base::SharedMemory(handle, false));
-  CHECK(shared_memory_->Map(length));
-  circular_buffer_.reset(
-      new PartialCircularBuffer(shared_memory_->memory(),
-                                length,
-                                length / 2,
-                                true));
-}
-
-void WebRtcLoggingHandlerImpl::OnOpenLogFailed() {
-  DCHECK(CalledOnValidThread());
-  DLOG(ERROR) << "Could not open log.";
-  // TODO(grunell): Implement.
-  NOTIMPLEMENTED();
-}
diff --git a/chrome/renderer/media/webrtc_logging_handler_impl.h b/chrome/renderer/media/webrtc_logging_handler_impl.h
deleted file mode 100644
index 5a98143..0000000
--- a/chrome/renderer/media/webrtc_logging_handler_impl.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_RENDERER_MEDIA_WEBRTC_LOGGING_HANDLER_IMPL_H_
-#define CHROME_RENDERER_MEDIA_WEBRTC_LOGGING_HANDLER_IMPL_H_
-
-#include <string>
-
-#include "base/shared_memory.h"
-#include "content/public/renderer/webrtc_log_message_delegate.h"
-#include "ipc/ipc_channel_proxy.h"
-
-namespace base {
-class MessageLoopProxy;
-}
-
-class PartialCircularBuffer;
-class WebRtcLoggingMessageFilter;
-
-// WebRtcLoggingHandlerImpl handles WebRTC logging. There is one object per
-// render process, owned by WebRtcLoggingMessageFilter. It communicates with
-// WebRtcLoggingHandlerHost and receives logging messages from libjingle and
-// writes them to a shared memory buffer.
-class WebRtcLoggingHandlerImpl
-    : public content::WebRtcLogMessageDelegate,
-      public base::NonThreadSafe {
- public:
-  WebRtcLoggingHandlerImpl(
-      const scoped_refptr<base::MessageLoopProxy>& io_message_loop,
-      WebRtcLoggingMessageFilter* message_filter);
-
-  virtual ~WebRtcLoggingHandlerImpl();
-
-  // content::WebRtcLogMessageDelegate implementation.
-  virtual void InitLogging(const std::string& app_session_id,
-                           const std::string& app_url) OVERRIDE;
-  virtual void LogMessage(const std::string& message) OVERRIDE;
-
-  void OnFilterRemoved();
-
-  void OnLogOpened(base::SharedMemoryHandle handle, uint32 length);
-  void OnOpenLogFailed();
-
- private:
-  scoped_refptr<base::MessageLoopProxy> io_message_loop_;
-  scoped_ptr<base::SharedMemory> shared_memory_;
-  scoped_ptr<PartialCircularBuffer> circular_buffer_;
-
-  WebRtcLoggingMessageFilter* message_filter_;
-  bool log_initialized_;
-
-  DISALLOW_COPY_AND_ASSIGN(WebRtcLoggingHandlerImpl);
-};
-
-#endif  // CHROME_RENDERER_MEDIA_WEBRTC_LOGGING_HANDLER_IMPL_H_
diff --git a/chrome/renderer/media/webrtc_logging_handler_impl_unittest.cc b/chrome/renderer/media/webrtc_logging_handler_impl_unittest.cc
deleted file mode 100644
index b12f622..0000000
--- a/chrome/renderer/media/webrtc_logging_handler_impl_unittest.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <string>
-
-#include "base/process_util.h"
-#include "chrome/common/partial_circular_buffer.h"
-#include "chrome/renderer/media/webrtc_logging_handler_impl.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-TEST(WebRtcLoggingHandlerImplTest, Basic) {
-  const uint32 kTestLogSize = 1024;  // 1 KB
-  const char kTestString[] = "abcdefghijklmnopqrstuvwxyz";
-
-  base::MessageLoop message_loop(base::MessageLoop::TYPE_IO);
-
-  scoped_ptr<WebRtcLoggingHandlerImpl> logging_handler(
-      new WebRtcLoggingHandlerImpl(message_loop.message_loop_proxy(), NULL));
-
-  base::SharedMemory shared_memory;
-  ASSERT_TRUE(shared_memory.CreateAndMapAnonymous(kTestLogSize));
-  base::SharedMemoryHandle new_handle;
-  ASSERT_TRUE(shared_memory.ShareToProcess(base::GetCurrentProcessHandle(),
-                                           &new_handle));
-  logging_handler->OnLogOpened(new_handle, kTestLogSize);
-
-  logging_handler->LogMessage(kTestString);
-  logging_handler->LogMessage(kTestString);
-
-  PartialCircularBuffer read_pcb(
-      reinterpret_cast<uint8*>(shared_memory.memory()), kTestLogSize);
-
-  // Size is calculated as (sizeof(kTestString) - 1 for terminating null
-  // + 1 for eol added for each log message in LogMessage) * 2 + 1 for
-  // terminating null.
-  char read_buffer[sizeof(kTestString) * 2 + 1] = {0};
-
-  uint32 read = read_pcb.Read(read_buffer, sizeof(read_buffer));
-  EXPECT_EQ(sizeof(read_buffer) - 1, read);
-  std::string ref_output = kTestString;
-  ref_output.append("\n");
-  ref_output.append(kTestString);
-  ref_output.append("\n");
-  EXPECT_STREQ(ref_output.c_str(), read_buffer);
-}
diff --git a/chrome/renderer/media/webrtc_logging_message_filter.cc b/chrome/renderer/media/webrtc_logging_message_filter.cc
index 9a6fcfb..be4f665 100644
--- a/chrome/renderer/media/webrtc_logging_message_filter.cc
+++ b/chrome/renderer/media/webrtc_logging_message_filter.cc
@@ -7,12 +7,12 @@
 #include "base/logging.h"
 #include "base/message_loop/message_loop_proxy.h"
 #include "chrome/common/media/webrtc_logging_messages.h"
-#include "chrome/renderer/media/webrtc_logging_handler_impl.h"
+#include "chrome/renderer/media/chrome_webrtc_log_message_delegate.h"
 #include "ipc/ipc_logging.h"
 
 WebRtcLoggingMessageFilter::WebRtcLoggingMessageFilter(
     const scoped_refptr<base::MessageLoopProxy>& io_message_loop)
-    : logging_handler_(NULL),
+    : log_message_delegate_(NULL),
       io_message_loop_(io_message_loop),
       channel_(NULL) {
   io_message_loop_->PostTask(
@@ -44,13 +44,13 @@
 void WebRtcLoggingMessageFilter::OnFilterRemoved() {
   DCHECK(io_message_loop_->BelongsToCurrentThread());
   channel_ = NULL;
-  logging_handler_->OnFilterRemoved();
+  log_message_delegate_->OnFilterRemoved();
 }
 
 void WebRtcLoggingMessageFilter::OnChannelClosing() {
   DCHECK(io_message_loop_->BelongsToCurrentThread());
   channel_ = NULL;
-  logging_handler_->OnFilterRemoved();
+  log_message_delegate_->OnFilterRemoved();
 }
 
 void WebRtcLoggingMessageFilter::InitLogging(
@@ -62,19 +62,20 @@
 
 void WebRtcLoggingMessageFilter::CreateLoggingHandler() {
   DCHECK(io_message_loop_->BelongsToCurrentThread());
-  logging_handler_ = new WebRtcLoggingHandlerImpl(io_message_loop_, this);
+  log_message_delegate_ =
+      new ChromeWebRtcLogMessageDelegate(io_message_loop_, this);
 }
 
 void WebRtcLoggingMessageFilter::OnLogOpened(
     base::SharedMemoryHandle handle,
     uint32 length) {
   DCHECK(io_message_loop_->BelongsToCurrentThread());
-  logging_handler_->OnLogOpened(handle, length);
+  log_message_delegate_->OnLogOpened(handle, length);
 }
 
 void WebRtcLoggingMessageFilter::OnOpenLogFailed() {
   DCHECK(io_message_loop_->BelongsToCurrentThread());
-  logging_handler_->OnOpenLogFailed();
+  log_message_delegate_->OnOpenLogFailed();
 }
 
 void WebRtcLoggingMessageFilter::Send(IPC::Message* message) {
diff --git a/chrome/renderer/media/webrtc_logging_message_filter.h b/chrome/renderer/media/webrtc_logging_message_filter.h
index 4466a1c..e6c38de 100644
--- a/chrome/renderer/media/webrtc_logging_message_filter.h
+++ b/chrome/renderer/media/webrtc_logging_message_filter.h
@@ -12,11 +12,11 @@
 class MessageLoopProxy;
 }
 
-class WebRtcLoggingHandlerImpl;
+class ChromeWebRtcLogMessageDelegate;
 
-// Filter for WebRTC logging messages. Sits between WebRtcLoggingHandlerImpl
-// (renderer process) and WebRtcLoggingHandlerHost (browser process). Must be
-// called on the IO thread.
+// Filter for WebRTC logging messages. Sits between
+// ChromeWebRtcLogMessageDelegate (renderer process) and
+// WebRtcLoggingHandlerHost (browser process). Must be called on the IO thread.
 class WebRtcLoggingMessageFilter
     : public IPC::ChannelProxy::MessageFilter {
  public:
@@ -51,7 +51,7 @@
   // file. That's a global pointer used on different threads, so we will leak
   // this object when we go away to ensure that it outlives any log messages
   // coming from libjingle.
-  WebRtcLoggingHandlerImpl* logging_handler_;
+  ChromeWebRtcLogMessageDelegate* log_message_delegate_;
 
   scoped_refptr<base::MessageLoopProxy> io_message_loop_;
 
diff --git a/chrome/renderer/page_load_histograms.cc b/chrome/renderer/page_load_histograms.cc
index 32ab044..cc9eab2 100644
--- a/chrome/renderer/page_load_histograms.cc
+++ b/chrome/renderer/page_load_histograms.cc
@@ -11,7 +11,7 @@
 #include "base/metrics/field_trial.h"
 #include "base/metrics/histogram.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/renderer/chrome_content_renderer_client.h"
 #include "content/public/common/content_constants.h"
diff --git a/chrome/renderer/pepper/ppb_nacl_private_impl.cc b/chrome/renderer/pepper/ppb_nacl_private_impl.cc
index 54ba85e..94e9e35 100644
--- a/chrome/renderer/pepper/ppb_nacl_private_impl.cc
+++ b/chrome/renderer/pepper/ppb_nacl_private_impl.cc
@@ -25,6 +25,7 @@
 #include "ppapi/native_client/src/trusted/plugin/nacl_entry_points.h"
 #include "ppapi/shared_impl/ppapi_preferences.h"
 #include "ppapi/shared_impl/var.h"
+#include "ppapi/thunk/enter.h"
 #include "third_party/WebKit/public/web/WebDocument.h"
 #include "third_party/WebKit/public/web/WebElement.h"
 #include "third_party/WebKit/public/web/WebFrame.h"
@@ -248,6 +249,30 @@
   return handle;
 }
 
+int32_t GetNexeFd(PP_Instance instance,
+                  const char* cache_key,
+                  PP_Bool* is_hit,
+                  PP_FileHandle* handle,
+                  struct PP_CompletionCallback callback) {
+  // Check the instance. Once the call into the browser is hooked up, will need
+  // to do it again before calling the callback in case the plugin goes away.
+  ppapi::thunk::EnterInstance enter(instance, callback);
+  if (enter.failed())
+    return enter.retval();
+  // stubbed out implementation for testing.
+  *is_hit = PP_FALSE;
+  *handle = CreateTemporaryFile(instance);
+  enter.callback()->PostRun(PP_OK);
+  enter.SetResult(PP_OK_COMPLETIONPENDING);
+  return enter.retval();
+}
+
+void ReportTranslationFinished(PP_Instance instance) {
+  // Do nothing for now. Once the IPC plumbing is in place, this function will
+  // send the routing id to the browser process, which will cache the contents
+  // of the temp file it sent.
+}
+
 PP_Bool IsOffTheRecord() {
   return PP_FromBool(ChromeRenderProcessObserver::is_incognito_process());
 }
@@ -311,6 +336,8 @@
   &BrokerDuplicateHandle,
   &GetReadonlyPnaclFD,
   &CreateTemporaryFile,
+  &GetNexeFd,
+  &ReportTranslationFinished,
   &IsOffTheRecord,
   &IsPnaclEnabled,
   &ReportNaClError,
diff --git a/chrome/renderer/prerender/prerender_helper.h b/chrome/renderer/prerender/prerender_helper.h
index a9879c1..e0a2d3f 100644
--- a/chrome/renderer/prerender/prerender_helper.h
+++ b/chrome/renderer/prerender/prerender_helper.h
@@ -6,7 +6,7 @@
 #define CHROME_RENDERER_PRERENDER_PRERENDER_HELPER_H_
 
 #include "base/compiler_specific.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "content/public/renderer/render_view_observer.h"
 #include "content/public/renderer/render_view_observer_tracker.h"
 
diff --git a/chrome/renderer/prerender/prerender_webmediaplayer.cc b/chrome/renderer/prerender/prerender_webmediaplayer.cc
index dd7be9a..c81402c 100644
--- a/chrome/renderer/prerender/prerender_webmediaplayer.cc
+++ b/chrome/renderer/prerender/prerender_webmediaplayer.cc
@@ -4,57 +4,23 @@
 
 #include "chrome/renderer/prerender/prerender_webmediaplayer.h"
 
+#include "base/callback_helpers.h"
 #include "chrome/common/prerender_messages.h"
 #include "content/public/renderer/render_view.h"
-#include "third_party/WebKit/public/platform/WebURL.h"
-#include "third_party/WebKit/public/web/WebMediaSource.h"
-#include "webkit/renderer/media/webmediaplayer_delegate.h"
 
 namespace prerender {
 
 PrerenderWebMediaPlayer::PrerenderWebMediaPlayer(
     content::RenderView* render_view,
-    WebKit::WebFrame* frame,
-    WebKit::WebMediaPlayerClient* client,
-    base::WeakPtr<webkit_media::WebMediaPlayerDelegate> delegate,
-    const webkit_media::WebMediaPlayerParams& params)
+    const base::Closure& closure)
     : RenderViewObserver(render_view),
-      WebMediaPlayerImpl(frame, client, delegate, params),
       is_prerendering_(true),
-      url_loaded_(false),
-      cors_mode_(CORSModeUnspecified) {
+      continue_loading_cb_(closure) {
+  DCHECK(!continue_loading_cb_.is_null());
 }
 
 PrerenderWebMediaPlayer::~PrerenderWebMediaPlayer() {}
 
-void PrerenderWebMediaPlayer::load(const WebKit::WebURL& url,
-                                   CORSMode cors_mode) {
-  DCHECK(!url_loaded_);
-  if (is_prerendering_) {
-    url_to_load_.reset(new WebKit::WebURL(url));
-    media_source_to_load_.reset();
-    cors_mode_ = cors_mode;
-    return;
-  }
-  url_loaded_ = true;
-  WebMediaPlayerImpl::load(url, cors_mode);
-}
-
-void PrerenderWebMediaPlayer::load(const WebKit::WebURL& url,
-                                   WebKit::WebMediaSource* media_source,
-                                   CORSMode cors_mode) {
-  DCHECK(!url_loaded_);
-  if (is_prerendering_) {
-    url_to_load_.reset(new WebKit::WebURL(url));
-    media_source_to_load_.reset(media_source);
-    cors_mode_ = cors_mode;
-    return;
-  }
-
-  url_loaded_ = true;
-  WebMediaPlayerImpl::load(url, media_source, cors_mode);
-}
-
 bool PrerenderWebMediaPlayer::OnMessageReceived(const IPC::Message& message) {
   IPC_BEGIN_MESSAGE_MAP(PrerenderWebMediaPlayer, message)
     IPC_MESSAGE_HANDLER(PrerenderMsg_SetIsPrerendering, OnSetIsPrerendering)
@@ -72,13 +38,7 @@
     return;
 
   is_prerendering_ = false;
-  if (!url_to_load_)
-    return;
-
-  if (media_source_to_load_)
-    load(*url_to_load_, media_source_to_load_.release(), cors_mode_);
-  else
-    load(*url_to_load_, cors_mode_);
+  base::ResetAndReturn(&continue_loading_cb_).Run();
 }
 
 }  // namespace prerender
diff --git a/chrome/renderer/prerender/prerender_webmediaplayer.h b/chrome/renderer/prerender/prerender_webmediaplayer.h
index da0b4d3..60f9403 100644
--- a/chrome/renderer/prerender/prerender_webmediaplayer.h
+++ b/chrome/renderer/prerender/prerender_webmediaplayer.h
@@ -5,33 +5,23 @@
 #ifndef CHROME_RENDERER_PRERENDER_PRERENDER_WEBMEDIAPLAYER_H_
 #define CHROME_RENDERER_PRERENDER_PRERENDER_WEBMEDIAPLAYER_H_
 
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
+#include "base/callback.h"
 #include "content/public/renderer/render_view_observer.h"
-#include "webkit/renderer/media/webmediaplayer_impl.h"
 
 namespace prerender {
 
-// Substitute for WebMediaPlayerImpl to be used in prerendered pages. Defers
-// the loading of the media till the prerendered page is swapped in.
-class PrerenderWebMediaPlayer
-    : public content::RenderViewObserver,
-      public webkit_media::WebMediaPlayerImpl {
+// Defers media player loading in prerendered pages until the prerendered page
+// is swapped in.
+//
+// TODO(scherkus): Rename as this class no longer inherits WebMediaPlayer.
+class PrerenderWebMediaPlayer : public content::RenderViewObserver {
  public:
-  PrerenderWebMediaPlayer(
-      content::RenderView* render_view,
-      WebKit::WebFrame* frame,
-      WebKit::WebMediaPlayerClient* client,
-      base::WeakPtr<webkit_media::WebMediaPlayerDelegate> delegate,
-      const webkit_media::WebMediaPlayerParams& params);
+  // Will run |closure| to continue loading the media resource once the page is
+  // swapped in.
+  PrerenderWebMediaPlayer(content::RenderView* render_view,
+                          const base::Closure& closure);
   virtual ~PrerenderWebMediaPlayer();
 
-  // WebMediaPlayerImpl methods:
-  virtual void load(const WebKit::WebURL& url, CORSMode cors_mode) OVERRIDE;
-  virtual void load(const WebKit::WebURL& url,
-                    WebKit::WebMediaSource* media_source,
-                    CORSMode cors_mode) OVERRIDE;
-
  private:
   // RenderViewObserver method:
   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
@@ -39,10 +29,7 @@
   void OnSetIsPrerendering(bool is_prerendering);
 
   bool is_prerendering_;
-  bool url_loaded_;
-  scoped_ptr<WebKit::WebURL> url_to_load_;
-  scoped_ptr<WebKit::WebMediaSource> media_source_to_load_;
-  CORSMode cors_mode_;
+  base::Closure continue_loading_cb_;
 
   DISALLOW_COPY_AND_ASSIGN(PrerenderWebMediaPlayer);
 };
diff --git a/chrome/renderer/printing/print_web_view_helper.cc b/chrome/renderer/printing/print_web_view_helper.cc
index 3966b36..5ea7340 100644
--- a/chrome/renderer/printing/print_web_view_helper.cc
+++ b/chrome/renderer/printing/print_web_view_helper.cc
@@ -858,15 +858,15 @@
 
 bool PrintWebViewHelper::GetPrintFrame(WebKit::WebFrame** frame) {
   DCHECK(frame);
-  DCHECK(render_view()->GetWebView());
-  if (!render_view()->GetWebView())
+  WebKit::WebView* webView = render_view()->GetWebView();
+  DCHECK(webView);
+  if (!webView)
     return false;
 
   // If the user has selected text in the currently focused frame we print
   // only that frame (this makes print selection work for multiple frames).
-  *frame = render_view()->GetWebView()->focusedFrame()->hasSelection() ?
-      render_view()->GetWebView()->focusedFrame() :
-      render_view()->GetWebView()->mainFrame();
+  WebKit::WebFrame* focusedFrame = webView->focusedFrame();
+  *frame = focusedFrame->hasSelection() ? focusedFrame : webView->mainFrame();
   return true;
 }
 
diff --git a/chrome/renderer/printing/print_web_view_helper.h b/chrome/renderer/printing/print_web_view_helper.h
index 4e84173..e1f9499 100644
--- a/chrome/renderer/printing/print_web_view_helper.h
+++ b/chrome/renderer/printing/print_web_view_helper.h
@@ -10,7 +10,7 @@
 #include "base/gtest_prod_util.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/shared_memory.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "content/public/renderer/render_view_observer.h"
 #include "content/public/renderer/render_view_observer_tracker.h"
 #include "printing/metafile_impl.h"
diff --git a/chrome/renderer/resources/default_100_percent/common/sadplugin.png b/chrome/renderer/resources/default_100_percent/common/sadplugin.png
index 2054430..9ad1225 100644
--- a/chrome/renderer/resources/default_100_percent/common/sadplugin.png
+++ b/chrome/renderer/resources/default_100_percent/common/sadplugin.png
Binary files differ
diff --git a/chrome/renderer/resources/default_100_percent/common/webview-crash.png b/chrome/renderer/resources/default_100_percent/common/webview-crash.png
index b983f04..0ce1db1 100644
--- a/chrome/renderer/resources/default_100_percent/common/webview-crash.png
+++ b/chrome/renderer/resources/default_100_percent/common/webview-crash.png
Binary files differ
diff --git a/chrome/renderer/resources/default_200_percent/common/sadplugin.png b/chrome/renderer/resources/default_200_percent/common/sadplugin.png
index 8e74b77..7828679 100644
--- a/chrome/renderer/resources/default_200_percent/common/sadplugin.png
+++ b/chrome/renderer/resources/default_200_percent/common/sadplugin.png
Binary files differ
diff --git a/chrome/renderer/resources/default_200_percent/common/webview-crash.png b/chrome/renderer/resources/default_200_percent/common/webview-crash.png
index 6db078c..eeb34b2 100644
--- a/chrome/renderer/resources/default_200_percent/common/webview-crash.png
+++ b/chrome/renderer/resources/default_200_percent/common/webview-crash.png
Binary files differ
diff --git a/chrome/renderer/resources/extensions/OWNERS b/chrome/renderer/resources/extensions/OWNERS
index 1294f7e..db39821 100644
--- a/chrome/renderer/resources/extensions/OWNERS
+++ b/chrome/renderer/resources/extensions/OWNERS
@@ -3,7 +3,6 @@
 benwells@chromium.org
 erikkay@chromium.org
 finnur@chromium.org
-jeremya@chromium.org
 jyasskin@chromium.org
 kalman@chromium.org
 koz@chromium.org
diff --git a/chrome/renderer/resources/extensions/ad_view.js b/chrome/renderer/resources/extensions/ad_view.js
index 8c3b27b..d5105ac 100644
--- a/chrome/renderer/resources/extensions/ad_view.js
+++ b/chrome/renderer/resources/extensions/ad_view.js
@@ -10,17 +10,17 @@
 // TODO(rpaquay): This file is currently very similar to "web_view.js". Do we
 //                want to refactor to extract common pieces?
 
-var adViewCustom = require('adViewCustom');
+var eventBindings = require('event_bindings');
+var process = requireNative('process');
 var watchForTag = require('tagWatcher').watchForTag;
 
 /**
- * Define "allowCustomAdNetworks" function such that it returns "true" if the
- * "adViewCustom" module was injected. This is so that the
+ * Define "allowCustomAdNetworks" function such that the
  * "kEnableAdviewSrcAttribute" flag is respected.
  */
-var allowCustomAdNetworks = (function(allow){
-  return function() { return Boolean(allow); }
-})(adViewCustom ? adViewCustom.enabled : false);
+function allowCustomAdNetworks() {
+  return process.HasSwitch('enable-adview-src-attribute');
+}
 
 /**
  * List of attribute names to "blindly" sync between <adview> tag and internal
@@ -74,6 +74,13 @@
   'sizechanged': ['oldHeight', 'oldWidth', 'newHeight', 'newWidth'],
 };
 
+var createEvent = function(name) {
+  var eventOpts = {supportsListeners: true, supportsFilters: true};
+  return new eventBindings.Event(name, undefined, eventOpts);
+};
+
+var AdviewLoadCommitEvent = createEvent('adview.onLoadCommit');
+
 /**
  * List of supported ad-networks.
  *
@@ -125,6 +132,7 @@
 AdView.prototype.createBrowserPluginNode_ = function() {
   var browserPluginNode = document.createElement('object');
   browserPluginNode.type = 'application/browser-plugin';
+  browserPluginNode.setAttribute('api', 'adview');
   // The <object> node fills in the <adview> container.
   browserPluginNode.style.width = '100%';
   browserPluginNode.style.height = '100%';
@@ -160,7 +168,7 @@
   var self = this;
   $Array.forEach(AD_VIEW_API_METHODS, function(apiMethod) {
     self.adviewNode_[apiMethod] = function(var_args) {
-      return self.browserPluginNode_[apiMethod].apply(
+      return $Function.apply(self.browserPluginNode_[apiMethod],
         self.browserPluginNode_, arguments);
     };
   }, this);
@@ -175,7 +183,7 @@
   var handleMutation = $Function.bind(function(mutation) {
     this.handleAdviewAttributeMutation_(mutation);
   }, this);
-  var observer = new WebKitMutationObserver(function(mutations) {
+  var observer = new MutationObserver(function(mutations) {
     $Array.forEach(mutations, handleMutation);
   });
   observer.observe(
@@ -192,7 +200,7 @@
   var handleMutation = $Function.bind(function(mutation) {
     this.handleAdviewCustomAttributeMutation_(mutation);
   }, this);
-  var observer = new WebKitMutationObserver(function(mutations) {
+  var observer = new MutationObserver(function(mutations) {
     $Array.forEach(mutations, handleMutation);
   });
   var customAttributeNames =
@@ -209,7 +217,7 @@
   var handleMutation = $Function.bind(function(mutation) {
     this.handleBrowserPluginAttributeMutation_(mutation);
   }, this);
-  var objectObserver = new WebKitMutationObserver(function(mutations) {
+  var objectObserver = new MutationObserver(function(mutations) {
     $Array.forEach(mutations, handleMutation);
   });
   objectObserver.observe(
@@ -431,6 +439,21 @@
  * @private
  */
 AdView.prototype.setupAdviewNodeEvents_ = function() {
+  var adviewNode = this.adviewNode_;
+  // TODO(fsamuel): Generalize this further as we add more events.
+  var onAttached = function(e) {
+    var detail = e.detail ? JSON.parse(e.detail) : {};
+    AdviewLoadCommitEvent.addListener(function(event) {
+      var adviewEvent = new Event('loadcommit', {bubbles: true});
+      var attribs = AD_VIEW_EVENTS['loadcommit'];
+      $Array.forEach(attribs, function(attribName) {
+        adviewEvent[attribName] = event[attribName];
+      });
+      adviewNode.dispatchEvent(adviewEvent);
+    }, {instanceId: detail.windowId});
+  };
+  this.browserPluginNode_.addEventListener('-internal-attached', onAttached);
+
   for (var eventName in AD_VIEW_EVENTS) {
     this.setupEvent_(eventName, AD_VIEW_EVENTS[eventName]);
   }
diff --git a/chrome/renderer/resources/extensions/ad_view_custom.js b/chrome/renderer/resources/extensions/ad_view_custom.js
deleted file mode 100644
index 118e447..0000000
--- a/chrome/renderer/resources/extensions/ad_view_custom.js
+++ /dev/null
@@ -1,5 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-exports.enabled = true;
diff --git a/chrome/renderer/resources/extensions/app_custom_bindings.js b/chrome/renderer/resources/extensions/app_custom_bindings.js
index 2bc8690..733395d 100644
--- a/chrome/renderer/resources/extensions/app_custom_bindings.js
+++ b/chrome/renderer/resources/extensions/app_custom_bindings.js
@@ -22,8 +22,8 @@
     // TODO(ataly): We need to make sure we use the right prototype for
     // fun.apply. Array slice can either be rewritten or similarly defined.
     logActivity.LogAPICall(id, "app." + fun.name,
-        Array.prototype.slice.call(arguments));
-    return fun.apply(this, arguments);
+        $Array.slice(arguments));
+    return $Function.apply(fun, this, arguments);
   });
 }
 
diff --git a/chrome/renderer/resources/extensions/app_runtime_custom_bindings.js b/chrome/renderer/resources/extensions/app_runtime_custom_bindings.js
index 431633f..0411d32 100644
--- a/chrome/renderer/resources/extensions/app_runtime_custom_bindings.js
+++ b/chrome/renderer/resources/extensions/app_runtime_custom_bindings.js
@@ -27,7 +27,7 @@
       if (err) {
         console.error('Error getting fileEntry, code: ' + err.code);
       } else {
-        items.push(item);
+        $Array.push(items, item);
       }
       if (--numItems === 0) {
         if (items.length === 0) {
diff --git a/chrome/renderer/resources/extensions/app_window_custom_bindings.js b/chrome/renderer/resources/extensions/app_window_custom_bindings.js
index 2bd570d..944189a 100644
--- a/chrome/renderer/resources/extensions/app_window_custom_bindings.js
+++ b/chrome/renderer/resources/extensions/app_window_custom_bindings.js
@@ -8,6 +8,7 @@
 var Binding = require('binding').Binding;
 var Event = require('event_bindings').Event;
 var forEach = require('utils').forEach;
+var renderViewObserverNatives = requireNative('renderViewObserverNatives');
 var sendRequest = require('sendRequest').sendRequest;
 
 var appWindowData = null;
@@ -56,14 +57,16 @@
         return;
       }
 
-      var willCallback = appWindowNatives.OnContextReady(windowParams.viewId,
-                                                         function(success) {
-        if (success) {
-          callback(view.chrome.app.window.current());
-        } else {
-          callback(undefined);
-        }
-      });
+      var willCallback =
+          renderViewObserverNatives.OnDocumentElementCreated(
+              windowParams.viewId,
+              function(success) {
+                if (success) {
+                  callback(view.chrome.app.window.current());
+                } else {
+                  callback(undefined);
+                }
+              });
       if (!willCallback) {
         callback(undefined);
       }
diff --git a/chrome/renderer/resources/extensions/binding.js b/chrome/renderer/resources/extensions/binding.js
index 55f6eda..a53737c 100644
--- a/chrome/renderer/resources/extensions/binding.js
+++ b/chrome/renderer/resources/extensions/binding.js
@@ -40,9 +40,9 @@
 
 APIFunctions.prototype.setHook_ =
     function(apiName, propertyName, customizedFunction) {
-  if (this.unavailableApiFunctions_.hasOwnProperty(apiName))
+  if ($Object.hasOwnProperty(this.unavailableApiFunctions_, apiName))
     return;
-  if (!this.apiFunctions_.hasOwnProperty(apiName))
+  if (!$Object.hasOwnProperty(this.apiFunctions_, apiName))
     throw new Error('Tried to set hook for unknown API "' + apiName + '"');
   this.apiFunctions_[apiName][propertyName] = customizedFunction;
 };
@@ -50,15 +50,14 @@
 APIFunctions.prototype.setHandleRequest =
     function(apiName, customizedFunction) {
   var prefix = this.namespace;
-  // TODO(ataly): Need to replace/redefine apply and slice.
   return this.setHook_(apiName, 'handleRequest',
     function() {
-      var ret = customizedFunction.apply(this, arguments);
+      var ret = $Function.apply(customizedFunction, this, arguments);
       // Logs API calls to the Activity Log if it doesn't go through an
       // ExtensionFunction.
       if (!sendRequestHandler.getCalledSendRequest())
         logActivity.LogAPICall(extensionId, prefix + "." + apiName,
-            Array.prototype.slice.call(arguments));
+            $Array.slice(arguments));
       return ret;
     });
 };
@@ -107,7 +106,7 @@
   ];
 
   for (var i = 0; i < platforms.length; i++) {
-    if (platforms[i][0].test(navigator.appVersion)) {
+    if ($RegExp.test(platforms[i][0], navigator.appVersion)) {
       return platforms[i][1];
     }
   }
@@ -176,7 +175,7 @@
   // interact with, and second the current extension ID. See where
   // |customHooks| is used.
   registerCustomHook: function(fn) {
-    this.customHooks_.push(fn);
+    $Array.push(this.customHooks_, fn);
   },
 
   // TODO(kalman/cduvall): Refactor this so |runHooks_| is not needed.
@@ -207,7 +206,7 @@
         return shouldCheck;
 
       $Array.forEach(['functions', 'events'], function(type) {
-        if (schema.hasOwnProperty(type)) {
+        if ($Object.hasOwnProperty(schema, type)) {
           $Array.forEach(schema[type], function(node) {
             if ('unprivileged' in node)
               shouldCheck = true;
@@ -218,7 +217,7 @@
         return shouldCheck;
 
       for (var property in schema.properties) {
-        if (schema.hasOwnProperty(property) &&
+        if ($Object.hasOwnProperty(schema, property) &&
             'unprivileged' in schema.properties[property]) {
           shouldCheck = true;
           break;
@@ -238,7 +237,7 @@
 
     var mod = {};
 
-    var namespaces = schema.namespace.split('.');
+    var namespaces = $String.split(schema.namespace, '.');
     for (var index = 0, name; name = namespaces[index]; index++) {
       mod[name] = mod[name] || {};
       mod = mod[name];
@@ -301,19 +300,22 @@
         this.apiFunctions_.register(functionDef.name, apiFunction);
 
         mod[functionDef.name] = $Function.bind(function() {
-          var args = Array.prototype.slice.call(arguments);
+          var args = $Array.slice(arguments);
           if (this.updateArgumentsPreValidate)
-            args = this.updateArgumentsPreValidate.apply(this, args);
+            args = $Function.apply(this.updateArgumentsPreValidate, this, args);
 
           args = schemaUtils.normalizeArgumentsAndValidate(args, this);
-          if (this.updateArgumentsPostValidate)
-            args = this.updateArgumentsPostValidate.apply(this, args);
+          if (this.updateArgumentsPostValidate) {
+            args = $Function.apply(this.updateArgumentsPostValidate,
+                                   this,
+                                   args);
+          }
 
           sendRequestHandler.clearCalledSendRequest();
 
           var retval;
           if (this.handleRequest) {
-            retval = this.handleRequest.apply(this, args);
+            retval = $Function.apply(this.handleRequest, this, args);
           } else {
             var optArgs = {
               customCallback: this.customCallback
@@ -403,7 +405,7 @@
             // not as an array), so we have to fake calling |new| on the
             // constructor.
             value = { __proto__: constructor.prototype };
-            constructor.apply(value, args);
+            $Function.apply(constructor, value, args);
             // Recursively add properties.
             addProperties(value, propertyDef);
           } else if (type === 'object') {
@@ -421,7 +423,7 @@
     addProperties(mod, schema);
 
     var availability = GetAvailability(schema.namespace);
-    if (!availability.is_available && Object.keys(mod).length == 0) {
+    if (!availability.is_available && $Object.keys(mod).length == 0) {
       console.error('chrome.' + schema.namespace + ' is not available: ' +
                         availability.message);
       return;
diff --git a/chrome/renderer/resources/extensions/bluetooth_custom_bindings.js b/chrome/renderer/resources/extensions/bluetooth_custom_bindings.js
index 07697d4..a125877 100644
--- a/chrome/renderer/resources/extensions/bluetooth_custom_bindings.js
+++ b/chrome/renderer/resources/extensions/bluetooth_custom_bindings.js
@@ -121,7 +121,7 @@
 
   apiFunctions.setUpdateArgumentsPostValidate('getDevices',
       function() {
-        var args = Array.prototype.slice.call(arguments);
+        var args = $Array.slice(arguments);
 
         if (bluetooth.getDevicesState != null) {
           throw new Error('Concurrent calls to getDevices are not allowed.');
@@ -131,7 +131,7 @@
 
         if (typeof(args[args.length - 1]) == 'function') {
           state.finalCallback = args.pop();
-          args.push(
+          $Array.push(args,
               function() {
                 if (chrome.runtime.lastError) {
                   finishDeviceSearch();
diff --git a/chrome/renderer/resources/extensions/chrome_setting.js b/chrome/renderer/resources/extensions/chrome_setting.js
index b2194b1..8d6f29e 100644
--- a/chrome/renderer/resources/extensions/chrome_setting.js
+++ b/chrome/renderer/resources/extensions/chrome_setting.js
@@ -7,7 +7,7 @@
 var validate = require('schemaUtils').validate;
 
 function extendSchema(schema) {
-  var extendedSchema = schema.slice();
+  var extendedSchema = $Array.slice(schema);
   extendedSchema.unshift({'type': 'string'});
   return extendedSchema;
 }
@@ -21,7 +21,8 @@
                        extendSchema(getSchema));
   };
   this.set = function(details, callback) {
-    var setSchema = this.functionSchemas.set.definition.parameters.slice();
+    var setSchema = $Array.slice(
+        this.functionSchemas.set.definition.parameters);
     setSchema[0].properties.value = valueSchema;
     validate([details, callback], setSchema);
     return sendRequest('types.ChromeSetting.set',
diff --git a/chrome/renderer/resources/extensions/content_setting.js b/chrome/renderer/resources/extensions/content_setting.js
index 990d269..c76b74b 100644
--- a/chrome/renderer/resources/extensions/content_setting.js
+++ b/chrome/renderer/resources/extensions/content_setting.js
@@ -8,7 +8,7 @@
 var validate = require('schemaUtils').validate;
 
 function extendSchema(schema) {
-  var extendedSchema = schema.slice();
+  var extendedSchema = $Array.slice(schema);
   extendedSchema.unshift({'type': 'string'});
   return extendedSchema;
 }
@@ -22,7 +22,8 @@
                        extendSchema(getSchema));
   };
   this.set = function(details, callback) {
-    var setSchema = this.functionSchemas.set.definition.parameters.slice();
+    var setSchema = $Array.slice(
+        this.functionSchemas.set.definition.parameters);
     setSchema[0].properties.setting = settingSchema;
     validate([details, callback], setSchema);
     return sendRequest('contentSettings.set',
diff --git a/chrome/renderer/resources/extensions/content_watcher.js b/chrome/renderer/resources/extensions/content_watcher.js
index c060276..9c118ed 100644
--- a/chrome/renderer/resources/extensions/content_watcher.js
+++ b/chrome/renderer/resources/extensions/content_watcher.js
@@ -10,7 +10,7 @@
   $Array.forEach(cssSelectors, function(selector, index) {
     try {
       if (document.querySelector(selector) != null)
-        result.push(index);
+        $Array.push(result, index);
     } catch (exception) {
       throw new Error("query Selector failed on '" + selector + "': " +
                       exception.stack);
@@ -21,8 +21,7 @@
 
 // Watches the page for all changes and calls FrameMutated (a C++ callback) in
 // response.
-var mutation_observer = new WebKitMutationObserver(
-  contentWatcherNative.FrameMutated);
+var mutation_observer = new MutationObserver(contentWatcherNative.FrameMutated);
 
 // This runs once per frame, when the module is 'require'd.
 mutation_observer.observe(document, {
diff --git a/chrome/renderer/resources/extensions/context_menus_custom_bindings.js b/chrome/renderer/resources/extensions/context_menus_custom_bindings.js
index f143ee6..5323f73 100644
--- a/chrome/renderer/resources/extensions/context_menus_custom_bindings.js
+++ b/chrome/renderer/resources/extensions/context_menus_custom_bindings.js
@@ -39,7 +39,7 @@
       var id = arguments[0].menuItemId;
       var onclick = contextMenus.handlersForId(id)[id];
       if (onclick) {
-        onclick.apply(null, arguments);
+        $Function.apply(onclick, null, arguments);
       }
     });
   };
diff --git a/chrome/renderer/resources/extensions/declarative_content_custom_bindings.js b/chrome/renderer/resources/extensions/declarative_content_custom_bindings.js
index 066413e..beb5409 100644
--- a/chrome/renderer/resources/extensions/declarative_content_custom_bindings.js
+++ b/chrome/renderer/resources/extensions/declarative_content_custom_bindings.js
@@ -26,7 +26,7 @@
   // generated union dictionary against the schema for |typeId|.
   function setupInstance(instance, parameters, typeId) {
     for (var key in parameters) {
-      if (parameters.hasOwnProperty(key)) {
+      if ($Object.hasOwnProperty(parameters, key)) {
         instance[key] = parameters[key];
       }
     }
diff --git a/chrome/renderer/resources/extensions/declarative_webrequest_custom_bindings.js b/chrome/renderer/resources/extensions/declarative_webrequest_custom_bindings.js
index 2034cc8..641b782 100644
--- a/chrome/renderer/resources/extensions/declarative_webrequest_custom_bindings.js
+++ b/chrome/renderer/resources/extensions/declarative_webrequest_custom_bindings.js
@@ -26,7 +26,7 @@
   // generated union dictionary against the schema for |typeId|.
   function setupInstance(instance, parameters, typeId) {
     for (var key in parameters) {
-      if (parameters.hasOwnProperty(key)) {
+      if ($Object.hasOwnProperty(parameters, key)) {
         instance[key] = parameters[key];
       }
     }
diff --git a/chrome/renderer/resources/extensions/entry_id_manager.js b/chrome/renderer/resources/extensions/entry_id_manager.js
index 8933239..669e7bf 100644
--- a/chrome/renderer/resources/extensions/entry_id_manager.js
+++ b/chrome/renderer/resources/extensions/entry_id_manager.js
@@ -17,7 +17,7 @@
   if (!fileSystemId)
     return null;
   // Strip the leading '/' from the path.
-  return fileSystemId + ':' + entry.fullPath.slice(1);
+  return fileSystemId + ':' + $String.slice(entry.fullPath, 1);
 }
 
 function registerEntry(id, entry) {
diff --git a/chrome/renderer/resources/extensions/event.js b/chrome/renderer/resources/extensions/event.js
index 8c352d3..9e7f0b1 100644
--- a/chrome/renderer/resources/extensions/event.js
+++ b/chrome/renderer/resources/extensions/event.js
@@ -109,14 +109,14 @@
   FilteredAttachmentStrategy.prototype.getListenersByIDs = function(ids) {
     var result = [];
     for (var i = 0; i < ids.length; i++)
-      result.push(this.listenerMap_[ids[i]]);
+      $Array.push(result, this.listenerMap_[ids[i]]);
     return result;
   };
 
   function parseEventOptions(opt_eventOptions) {
     function merge(dest, src) {
       for (var k in src) {
-        if (!dest.hasOwnProperty(k)) {
+        if (!$Object.hasOwnProperty(dest, k)) {
           dest[k] = src[k];
         }
       }
@@ -224,7 +224,7 @@
     }
     var listener = {callback: cb, filters: filters};
     this.attach_(listener);
-    this.listeners_.push(listener);
+    $Array.push(this.listeners_, listener);
   };
 
   Event.prototype.attach_ = function(listener) {
@@ -249,7 +249,7 @@
     if (idx == -1)
       return;
 
-    var removedListener = this.listeners_.splice(idx, 1)[0];
+    var removedListener = $Array.splice(this.listeners_, idx, 1)[0];
     this.attachmentStrategy_.onRemovedListener(removedListener);
 
     if (this.listeners_.length == 0) {
@@ -308,15 +308,15 @@
 
     // Make a copy of the listeners in case the listener list is modified
     // while dispatching the event.
-    var listeners =
-        this.attachmentStrategy_.getListenersByIDs(listenerIDs).slice();
+    var listeners = $Array.slice(
+        this.attachmentStrategy_.getListenersByIDs(listenerIDs));
 
     var results = [];
     for (var i = 0; i < listeners.length; i++) {
       try {
         var result = this.dispatchToListener(listeners[i].callback, args);
         if (result !== undefined)
-          results.push(result);
+          $Array.push(results, result);
       } catch (e) {
         var errorMessage = "Error in event handler";
         if (this.eventName_)
@@ -331,13 +331,13 @@
 
   // Can be overridden to support custom dispatching.
   Event.prototype.dispatchToListener = function(callback, args) {
-    return callback.apply(null, args);
+    return $Function.apply(callback, null, args);
   }
 
   // Dispatches this event object to all listeners, passing all supplied
   // arguments to this function each listener.
   Event.prototype.dispatch = function(varargs) {
-    return this.dispatch_(Array.prototype.slice.call(arguments), undefined);
+    return this.dispatch_($Array.slice(arguments), undefined);
   };
 
   // Detaches this event object from its name.
@@ -396,7 +396,8 @@
     // We remove the first parameter from the validation to give the user more
     // meaningful error messages.
     validate([rules, opt_cb],
-             ruleFunctionSchemas.addRules.parameters.slice().splice(1));
+             $Array.splice(
+                 $Array.slice(ruleFunctionSchemas.addRules.parameters), 1));
     sendRequest("events.addRules", [this.eventName_, rules, opt_cb],
                 ruleFunctionSchemas.addRules.parameters);
   }
@@ -408,7 +409,8 @@
     // We remove the first parameter from the validation to give the user more
     // meaningful error messages.
     validate([ruleIdentifiers, opt_cb],
-             ruleFunctionSchemas.removeRules.parameters.slice().splice(1));
+             $Array.splice(
+                 $Array.slice(ruleFunctionSchemas.removeRules.parameters), 1));
     sendRequest("events.removeRules",
                 [this.eventName_, ruleIdentifiers, opt_cb],
                 ruleFunctionSchemas.removeRules.parameters);
@@ -421,7 +423,8 @@
     // We remove the first parameter from the validation to give the user more
     // meaningful error messages.
     validate([ruleIdentifiers, cb],
-             ruleFunctionSchemas.getRules.parameters.slice().splice(1));
+             $Array.splice(
+                 $Array.slice(ruleFunctionSchemas.getRules.parameters), 1));
 
     sendRequest("events.getRules",
                 [this.eventName_, ruleIdentifiers, cb],
diff --git a/chrome/renderer/resources/extensions/experimental.offscreenTabs_custom_bindings.js b/chrome/renderer/resources/extensions/experimental.offscreenTabs_custom_bindings.js
index 7903a3d..394f191 100644
--- a/chrome/renderer/resources/extensions/experimental.offscreenTabs_custom_bindings.js
+++ b/chrome/renderer/resources/extensions/experimental.offscreenTabs_custom_bindings.js
@@ -45,8 +45,10 @@
   // We are making a copy of |arr|, but applying |func| to index 1.
   function validate(arr, func) {
     var newArr = [];
-    for (var i = 0; i < arr.length; i++)
-      newArr.push(i == 1 && typeof(arr) == 'object' ? func(arr[i]) : arr[i]);
+    for (var i = 0; i < arr.length; i++) {
+      $Array.push(newArr,
+                  i == 1 && typeof(arr) == 'object' ? func(arr[i]) : arr[i]);
+    }
     return newArr;
   }
 
diff --git a/chrome/renderer/resources/extensions/extension_custom_bindings.js b/chrome/renderer/resources/extensions/extension_custom_bindings.js
index e1c03dc..3326e9b 100644
--- a/chrome/renderer/resources/extensions/extension_custom_bindings.js
+++ b/chrome/renderer/resources/extensions/extension_custom_bindings.js
@@ -80,7 +80,7 @@
     // Checking existence isn't enough since some functions are disabled via
     // getters that throw exceptions. Assume that any getter is such a function.
     if (chrome.runtime &&
-        chrome.runtime.hasOwnProperty(alias) &&
+        $Object.hasOwnProperty(chrome.runtime, alias) &&
         chrome.runtime.__lookupGetter__(alias) === undefined) {
       extension[alias] = chrome.runtime[alias];
     }
diff --git a/chrome/renderer/resources/extensions/file_system_custom_bindings.js b/chrome/renderer/resources/extensions/file_system_custom_bindings.js
index 50055b8..f66c20d 100644
--- a/chrome/renderer/resources/extensions/file_system_custom_bindings.js
+++ b/chrome/renderer/resources/extensions/file_system_custom_bindings.js
@@ -76,7 +76,7 @@
     apiFunctions.setUpdateArgumentsPostValidate(
         functionName, function(fileEntry, callback) {
       var fileSystemName = fileEntry.filesystem.name;
-      var relativePath = fileEntry.fullPath.slice(1);
+      var relativePath = $String.slice(fileEntry.fullPath, 1);
       return [fileSystemName, relativePath, callback];
     });
   }
@@ -93,7 +93,7 @@
     if (!id)
       return '';
     var fileSystemName = fileEntry.filesystem.name;
-    var relativePath = fileEntry.fullPath.slice(1);
+    var relativePath = $String.slice(fileEntry.fullPath, 1);
 
     sendRequest(this.name, [id, fileSystemName, relativePath],
       this.definition.parameters, {});
@@ -129,19 +129,19 @@
   fileSystem.getWritableFileEntry = function() {
     console.log("chrome.fileSystem.getWritableFileEntry is deprecated");
     console.log("Please use chrome.fileSystem.getWritableEntry instead");
-    fileSystem.getWritableEntry.apply(this, arguments);
+    $Function.apply(fileSystem.getWritableEntry, this, arguments);
   };
 
   fileSystem.isWritableFileEntry = function() {
     console.log("chrome.fileSystem.isWritableFileEntry is deprecated");
     console.log("Please use chrome.fileSystem.isWritableEntry instead");
-    fileSystem.isWritableEntry.apply(this, arguments);
+    $Function.apply(fileSystem.isWritableEntry, this, arguments);
   };
 
   fileSystem.chooseFile = function() {
     console.log("chrome.fileSystem.chooseFile is deprecated");
     console.log("Please use chrome.fileSystem.chooseEntry instead");
-    fileSystem.chooseEntry.apply(this, arguments);
+    $Function.apply(fileSystem.chooseEntry, this, arguments);
   };
 });
 
diff --git a/chrome/renderer/resources/extensions/i18n_custom_bindings.js b/chrome/renderer/resources/extensions/i18n_custom_bindings.js
index a2f5869..ae8395b 100644
--- a/chrome/renderer/resources/extensions/i18n_custom_bindings.js
+++ b/chrome/renderer/resources/extensions/i18n_custom_bindings.js
@@ -13,7 +13,7 @@
   var apiFunctions = bindingsAPI.apiFunctions;
 
   apiFunctions.setUpdateArgumentsPreValidate('getMessage', function() {
-    var args = Array.prototype.slice.call(arguments);
+    var args = $Array.slice(arguments);
 
     // The first argument is the message, and should be a string.
     var message = args[0];
diff --git a/chrome/renderer/resources/extensions/image_util.js b/chrome/renderer/resources/extensions/image_util.js
index 7075c94..7986740 100644
--- a/chrome/renderer/resources/extensions/image_util.js
+++ b/chrome/renderer/resources/extensions/image_util.js
@@ -60,7 +60,7 @@
     finished[index] = { width: width, height: height, data: imageData };
     if (err)
       callbacks.onerror(index);
-    if (Object.keys(loading).length == 0)
+    if ($Object.keys(loading).length == 0)
       callbacks.oncomplete(finished);
   }
 }
diff --git a/chrome/renderer/resources/extensions/json_schema.js b/chrome/renderer/resources/extensions/json_schema.js
index 19d3634..c894ef2 100644
--- a/chrome/renderer/resources/extensions/json_schema.js
+++ b/chrome/renderer/resources/extensions/json_schema.js
@@ -167,18 +167,18 @@
 JSONSchemaValidator.prototype.getAllTypesForSchema = function(schema) {
   var schemaTypes = [];
   if (schema.type)
-    schemaTypes.push(schema.type);
+    $Array.push(schemaTypes, schema.type);
   if (schema.choices) {
     for (var i = 0; i < schema.choices.length; i++) {
       var choiceTypes = this.getAllTypesForSchema(schema.choices[i]);
-      schemaTypes = schemaTypes.concat(choiceTypes);
+      schemaTypes = $Array.concat(schemaTypes, choiceTypes);
     }
   }
   var ref = schema['$ref'];
   if (ref) {
     var type = this.getOrAddType(ref);
     CHECK(type, 'Could not find type ' + ref);
-    schemaTypes = schemaTypes.concat(this.getAllTypesForSchema(type));
+    schemaTypes = $Array.concat(schemaTypes, this.getAllTypesForSchema(type));
   }
   return schemaTypes;
 };
@@ -341,7 +341,7 @@
       // TODO(aa): If it ever turns out that we actually want this to work,
       // there are other checks we could put here, like requiring that schema
       // properties be objects that have a 'type' property.
-      if (!schema.properties.hasOwnProperty(prop))
+      if (!$Object.hasOwnProperty(schema.properties, prop))
         continue;
 
       var propPath = path ? path + "." + prop : prop;
@@ -377,7 +377,7 @@
       continue;
 
     // Any properties inherited through the prototype are ignored.
-    if (!instance.hasOwnProperty(prop))
+    if (!$Object.hasOwnProperty(instance, prop))
       continue;
 
     var propPath = path ? path + "." + prop : prop;
@@ -502,7 +502,7 @@
  * message.
  */
 JSONSchemaValidator.prototype.addError = function(path, key, replacements) {
-  this.errors.push({
+  $Array.push(this.errors, {
     path: path,
     message: JSONSchemaValidator.formatError(key, replacements)
   });
diff --git a/chrome/renderer/resources/extensions/last_error.js b/chrome/renderer/resources/extensions/last_error.js
index 42e5dd8..7252a2e 100644
--- a/chrome/renderer/resources/extensions/last_error.js
+++ b/chrome/renderer/resources/extensions/last_error.js
@@ -54,7 +54,7 @@
   var targetChrome = GetGlobal(callback).chrome;
   set(name, message, stack, targetChrome);
   try {
-    callback.apply(undefined, args);
+    $Function.apply(callback, undefined, args);
   } finally {
     clear(targetChrome);
   }
diff --git a/chrome/renderer/resources/extensions/media_galleries_custom_bindings.js b/chrome/renderer/resources/extensions/media_galleries_custom_bindings.js
index 93e0a34..e741fea 100644
--- a/chrome/renderer/resources/extensions/media_galleries_custom_bindings.js
+++ b/chrome/renderer/resources/extensions/media_galleries_custom_bindings.js
@@ -24,7 +24,7 @@
       for (var i = 0; i < response.length; i++) {
         var filesystem = mediaGalleriesNatives.GetMediaFileSystemObject(
             response[i].fsid);
-        result.push(filesystem);
+        $Array.push(result, filesystem);
         var metadata = response[i];
         delete metadata.fsid;
         mediaGalleriesMetadata[filesystem.name] = metadata;
diff --git a/chrome/renderer/resources/extensions/miscellaneous_bindings.js b/chrome/renderer/resources/extensions/miscellaneous_bindings.js
index 32f4c85..14b83ba 100644
--- a/chrome/renderer/resources/extensions/miscellaneous_bindings.js
+++ b/chrome/renderer/resources/extensions/miscellaneous_bindings.js
@@ -45,7 +45,10 @@
   // Sends a message asynchronously to the context on the other end of this
   // port.
   Port.prototype.postMessage = function(msg) {
-    miscNatives.PostMessage(this.portId_, msg);
+    // JSON.stringify doesn't support a root object which is undefined.
+    if (msg === undefined)
+      msg = null;
+    miscNatives.PostMessage(this.portId_, $JSON.stringify(msg));
   };
 
   // Disconnects the port from the other end.
@@ -98,19 +101,19 @@
     var errorMsg = [];
     var eventName = isSendMessage ? "runtime.onMessage" : "extension.onRequest";
     if (isSendMessage && !responseCallbackPreserved) {
-      errorMsg.push(
+      $Array.push(errorMsg,
           "The chrome." + eventName + " listener must return true if you " +
           "want to send a response after the listener returns");
     } else {
-      errorMsg.push(
+      $Array.push(errorMsg,
           "Cannot send a response more than once per chrome." + eventName +
           " listener per document");
     }
-    errorMsg.push("(message was sent by extension" + sourceExtensionId);
+    $Array.push(errorMsg, "(message was sent by extension" + sourceExtensionId);
     if (sourceExtensionId != "" && sourceExtensionId != targetExtensionId)
-      errorMsg.push("for extension " + targetExtensionId);
+      $Array.push(errorMsg, "for extension " + targetExtensionId);
     if (sourceUrl != "")
-      errorMsg.push("for URL " + sourceUrl);
+      $Array.push(errorMsg, "for URL " + sourceUrl);
     lastError.set(eventName, errorMsg.join(" ") + ").", null, chrome);
   }
 
@@ -266,8 +269,11 @@
   // Called by native code when a message has been sent to the given port.
   function dispatchOnMessage(msg, portId) {
     var port = ports[portId];
-    if (port)
+    if (port) {
+      if (msg)
+        msg = $JSON.parse(msg);
       port.onMessage.dispatch(msg, port);
+    }
   };
 
   // Shared implementation used by tabs.sendMessage and runtime.sendMessage.
@@ -312,7 +318,7 @@
     // schema validation is expecting, e.g.
     //   extension.sendRequest(req)     -> extension.sendRequest(null, req)
     //   extension.sendRequest(req, cb) -> extension.sendRequest(null, req, cb)
-    var args = Array.prototype.splice.call(arguments, 1);  // skip functionName
+    var args = $Array.splice(arguments, 1);  // skip functionName
     var lastArg = args.length - 1;
 
     // responseCallback (last argument) is optional.
diff --git a/chrome/renderer/resources/extensions/notifications_custom_bindings.js b/chrome/renderer/resources/extensions/notifications_custom_bindings.js
index fb19ac4..5150a4f 100644
--- a/chrome/renderer/resources/extensions/notifications_custom_bindings.js
+++ b/chrome/renderer/resources/extensions/notifications_custom_bindings.js
@@ -36,7 +36,7 @@
 
   // |imageUrl| is optional.
   if (notification_details.imageUrl) {
-    url_specs.push({
+    $Array.push(url_specs, {
       path: notification_details.imageUrl,
       width: 360,
       height: 540,
@@ -50,7 +50,7 @@
     var num_buttons = button_list.length;
     for (var i = 0; i < num_buttons; i++) {
       if (button_list[i].iconUrl) {
-        url_specs.push({
+        $Array.push(url_specs, {
           path: button_list[i].iconUrl,
           width: 16,
           height: 16,
diff --git a/chrome/renderer/resources/extensions/omnibox_custom_bindings.js b/chrome/renderer/resources/extensions/omnibox_custom_bindings.js
index 2fd7a6c..6e753a9 100644
--- a/chrome/renderer/resources/extensions/omnibox_custom_bindings.js
+++ b/chrome/renderer/resources/extensions/omnibox_custom_bindings.js
@@ -65,7 +65,7 @@
           'type': child.nodeName,
           'offset': result.description.length
         };
-        result.descriptionStyles.push(style);
+        $Array.push(result.descriptionStyles, style);
         walk(child);
         style.length = result.description.length - style.offset;
         continue;
@@ -105,7 +105,7 @@
       var parseResult = parseOmniboxDescription(
           userSuggestions[i].description);
       parseResult.content = userSuggestions[i].content;
-      suggestions.push(parseResult);
+      $Array.push(suggestions, parseResult);
     }
     return [requestId, suggestions];
   });
diff --git a/chrome/renderer/resources/extensions/permissions_custom_bindings.js b/chrome/renderer/resources/extensions/permissions_custom_bindings.js
index 7ff85f5..244fd95 100644
--- a/chrome/renderer/resources/extensions/permissions_custom_bindings.js
+++ b/chrome/renderer/resources/extensions/permissions_custom_bindings.js
@@ -21,7 +21,7 @@
   var permissions = api.compiledApi;
 
   function maybeConvertToObject(str) {
-    var parts = str.split('|');
+    var parts = $String.split(str, '|');
     if (parts.length != 2)
       return str;
 
@@ -41,7 +41,7 @@
     for (var i = 0; i < args.length; i += 1) {
       if (typeof(args[i]) == 'object') {
         var a = args[i];
-        var keys = Object.keys(a);
+        var keys = $Object.keys(a);
         if (keys.length != 1) {
           throw new Error("Too many keys in object-style permission.");
         }
@@ -75,7 +75,7 @@
         // that handleResponse doesn't call it again.
         try {
           if (request.callback)
-            request.callback.apply(request, [response]);
+            $Function.apply(request.callback, request, [response]);
         } finally {
           delete request.callback;
         }
diff --git a/chrome/renderer/resources/extensions/platform_app.js b/chrome/renderer/resources/extensions/platform_app.js
index 607ea8b..78a13ff 100644
--- a/chrome/renderer/resources/extensions/platform_app.js
+++ b/chrome/renderer/resources/extensions/platform_app.js
@@ -134,5 +134,5 @@
   if (type === 'unload' || type === 'beforeunload')
     generateDisabledMethodStub(type)();
   else
-    return windowAddEventListener.apply(window, arguments);
+    return $Function.apply(windowAddEventListener, window, arguments);
 };
diff --git a/chrome/renderer/resources/extensions/schema_utils.js b/chrome/renderer/resources/extensions/schema_utils.js
index 5ec93fc..d54fbe2 100644
--- a/chrome/renderer/resources/extensions/schema_utils.js
+++ b/chrome/renderer/resources/extensions/schema_utils.js
@@ -44,11 +44,11 @@
   if (parameterSchemas.length === 0)
     return [[]];
   var signatures = [];
-  var remaining = getSignatures(parameterSchemas.slice(1));
+  var remaining = getSignatures($Array.slice(parameterSchemas, 1));
   for (var i = 0; i < remaining.length; i++)
-    signatures.push([parameterSchemas[0]].concat(remaining[i]))
+    $Array.push(signatures, $Array.concat([parameterSchemas[0]], remaining[i]))
   if (parameterSchemas[0].optional)
-    return signatures.concat(remaining);
+    return $Array.concat(signatures, remaining);
   return signatures;
 };
 
@@ -119,9 +119,9 @@
   var ai = 0;
   for (var si = 0; si < definedSignature.length; si++) {
     if (definedSignature[si] === resolvedSignature[ai])
-      normalizedArgs.push(args[ai++]);
+      $Array.push(normalizedArgs, args[ai++]);
     else
-      normalizedArgs.push(null);
+      $Array.push(normalizedArgs, null);
   }
   return normalizedArgs;
 };
diff --git a/chrome/renderer/resources/extensions/searchbox_api.js b/chrome/renderer/resources/extensions/searchbox_api.js
index 8a21d03..7d2daa5 100644
--- a/chrome/renderer/resources/extensions/searchbox_api.js
+++ b/chrome/renderer/resources/extensions/searchbox_api.js
@@ -55,6 +55,7 @@
       native function SetSuggestion();
       native function SetSuggestionFromAutocompleteResult();
       native function SetSuggestions();
+      native function SetVoiceSearchSupported();
       native function ShowOverlay();
       native function FocusOmnibox();
       native function StartCapturingKeyStrokes();
@@ -99,7 +100,7 @@
         }
         var dedupedResults = [];
         for (url in urlToResultMap) {
-          dedupedResults.push(urlToResultMap[url]);
+          $Array.push(dedupedResults, urlToResultMap[url]);
         }
         return dedupedResults;
       }
@@ -181,6 +182,9 @@
       this.setSuggestions = function(text) {
         SetSuggestions(text);
       };
+      this.setVoiceSearchSupported = function(supported) {
+        SetVoiceSearchSupported(supported);
+      };
       this.setAutocompleteText = function(text, behavior) {
         SetSuggestion(text, behavior);
       };
@@ -254,6 +258,7 @@
       native function UndoMostVisitedDeletion();
       native function NavigateNewTabPage();
       native function IsInputInProgress();
+      native function GetAppLauncherEnabled();
 
       function GetMostVisitedItemsWrapper() {
         var mostVisitedItems = GetMostVisitedItems();
@@ -274,6 +279,7 @@
       this.__defineGetter__('mostVisited', GetMostVisitedItemsWrapper);
       this.__defineGetter__('themeBackgroundInfo', GetThemeBackgroundInfo);
       this.__defineGetter__('isInputInProgress', IsInputInProgress);
+      this.__defineGetter__('appLauncherEnabled', GetAppLauncherEnabled);
 
       this.deleteMostVisitedItem = function(restrictedId) {
         DeleteMostVisitedItem(restrictedId);
diff --git a/chrome/renderer/resources/extensions/send_request.js b/chrome/renderer/resources/extensions/send_request.js
index 1e203ca..28798ba 100644
--- a/chrome/renderer/resources/extensions/send_request.js
+++ b/chrome/renderer/resources/extensions/send_request.js
@@ -18,7 +18,7 @@
 // Runs a user-supplied callback safely.
 function safeCallbackApply(name, request, callback, args) {
   try {
-    callback.apply(request, args);
+    $Function.apply(callback, request, args);
   } catch (e) {
     var errorMessage = "Error in response to " + name + ": " + e;
     if (request.stack && request.stack != '')
@@ -44,7 +44,7 @@
     if (request.callback) {
       var chromeForCallback = natives.GetGlobal(request.callback).chrome;
       if (chromeForCallback != chrome)
-        chromesForLastError.push(chromeForCallback);
+        $Array.push(chromesForLastError, chromeForCallback);
     }
 
     $Array.forEach(chromesForLastError, function(c) {lastError.clear(c)});
@@ -60,7 +60,7 @@
       safeCallbackApply(name,
                         request,
                         request.customCallback,
-                        [name, request].concat(responseList));
+                        $Array.concat([name, request], responseList));
     }
 
     if (request.callback) {
@@ -82,7 +82,7 @@
 };
 
 function getExtensionStackTrace(call_name) {
-  var stack = new Error().stack.split('\n');
+  var stack = $String.split(new Error().stack, '\n');
 
   // Remove stack frames before and after that weren't associated with the
   // extension.
diff --git a/chrome/renderer/resources/extensions/storage_area.js b/chrome/renderer/resources/extensions/storage_area.js
index 0749602..66d57d4 100644
--- a/chrome/renderer/resources/extensions/storage_area.js
+++ b/chrome/renderer/resources/extensions/storage_area.js
@@ -7,7 +7,7 @@
 var sendRequest = require('sendRequest').sendRequest;
 
 function extendSchema(schema) {
-  var extendedSchema = schema.slice();
+  var extendedSchema = $Array.slice(schema);
   extendedSchema.unshift({'type': 'string'});
   return extendedSchema;
 }
@@ -24,11 +24,11 @@
   function bindApiFunction(functionName) {
     self[functionName] = function() {
       var funSchema = this.functionSchemas[functionName];
-      var args = Array.prototype.slice.call(arguments);
+      var args = $Array.slice(arguments);
       args = normalizeArgumentsAndValidate(args, funSchema);
       return sendRequest(
           'storage.' + functionName,
-          [namespace].concat(args),
+          $Array.concat([namespace], args),
           extendSchema(funSchema.definition.parameters),
           {preserveNullInObjects: true});
     };
diff --git a/chrome/renderer/resources/extensions/sync_file_system_custom_bindings.js b/chrome/renderer/resources/extensions/sync_file_system_custom_bindings.js
index 6ada6a7..c2df0b0 100644
--- a/chrome/renderer/resources/extensions/sync_file_system_custom_bindings.js
+++ b/chrome/renderer/resources/extensions/sync_file_system_custom_bindings.js
@@ -29,7 +29,7 @@
         functionName, function(entries, callback) {
       var fileSystemUrlArray = [];
       for (var i=0; i < entries.length; i++) {
-        fileSystemUrlArray.push(entries[i].toURL());
+        $Array.push(fileSystemUrlArray, entries[i].toURL());
       }
       return [fileSystemUrlArray, callback];
     });
@@ -76,7 +76,7 @@
             entry.isDirectory);
         result.status = response[i].status;
         result.error = response[i].error;
-        results.push(result);
+        $Array.push(results, result);
       }
     }
     if (request.callback)
diff --git a/chrome/renderer/resources/extensions/tag_watcher.js b/chrome/renderer/resources/extensions/tag_watcher.js
index e970b96..c956c37 100644
--- a/chrome/renderer/resources/extensions/tag_watcher.js
+++ b/chrome/renderer/resources/extensions/tag_watcher.js
@@ -16,7 +16,7 @@
   findChildTags(document.body);
 
   // Observe the tags added later.
-  var documentObserver = new WebKitMutationObserver(function(mutations) {
+  var documentObserver = new MutationObserver(function(mutations) {
     $Array.forEach(mutations, function(mutation) {
       $Array.forEach(mutation.addedNodes, function(addedNode) {
         if (addedNode.nodeType == Node.ELEMENT_NODE) {
diff --git a/chrome/renderer/resources/extensions/test_custom_bindings.js b/chrome/renderer/resources/extensions/test_custom_bindings.js
index ad0bd25..231e339 100644
--- a/chrome/renderer/resources/extensions/test_custom_bindings.js
+++ b/chrome/renderer/resources/extensions/test_custom_bindings.js
@@ -61,8 +61,10 @@
         var redundantPrefix = 'Error\n';
         chrome.test.fail(
           'Callback has already been run. ' +
-          'First call:\n' + called.slice(redundantPrefix.length) + '\n' +
-          'Second call:\n' + new Error().stack.slice(redundantPrefix.length));
+          'First call:\n' +
+          $String.slice(called, redundantPrefix.length) + '\n' +
+          'Second call:\n' +
+          $String.slice(new Error().stack, redundantPrefix.length));
       }
       called = new Error().stack;
 
@@ -151,12 +153,16 @@
       return false;
 
     for (var p in actual) {
-      if (actual.hasOwnProperty(p) && !expected.hasOwnProperty(p))
+      if ($Object.hasOwnProperty(actual, p) &&
+          !$Object.hasOwnProperty(expected, p)) {
         return false;
+      }
     }
     for (var p in expected) {
-      if (expected.hasOwnProperty(p) && !actual.hasOwnProperty(p))
+      if ($Object.hasOwnProperty(expected, p) &&
+          !$Object.hasOwnProperty(actual, p)) {
         return false;
+      }
     }
 
     for (var p in expected) {
@@ -225,7 +231,7 @@
   function safeFunctionApply(func, args) {
     try {
       if (func)
-        func.apply(null, args);
+        $Function.apply(func, null, args);
     } catch (e) {
       var msg = "uncaught exception " + e;
       chromeTest.fail(msg);
diff --git a/chrome/renderer/resources/extensions/unload_event.js b/chrome/renderer/resources/extensions/unload_event.js
index 85a5465..52cf889 100644
--- a/chrome/renderer/resources/extensions/unload_event.js
+++ b/chrome/renderer/resources/extensions/unload_event.js
@@ -11,13 +11,13 @@
 var listeners = [];
 
 exports.addListener = function(listener) {
-  listeners.push(listener);
+  $Array.push(listeners, listener);
 };
 
 exports.removeListener = function(listener) {
   for (var i = 0; i < listeners.length; ++i) {
     if (listeners[i] == listener) {
-      listeners.splice(i, 1);
+      $Array.splice(listeners, i, 1);
       return;
     }
   }
diff --git a/chrome/renderer/resources/extensions/utils.js b/chrome/renderer/resources/extensions/utils.js
index 45d9295..80b5f1b 100644
--- a/chrome/renderer/resources/extensions/utils.js
+++ b/chrome/renderer/resources/extensions/utils.js
@@ -32,7 +32,7 @@
 }
 
 function loadTypeSchema(typeName, defaultSchema) {
-  var parts = typeName.split('.');
+  var parts = $String.split(typeName, '.');
   if (parts.length == 1) {
     if (defaultSchema == null) {
       WARNING('Trying to reference "' + typeName + '" ' +
@@ -41,7 +41,7 @@
     }
     var types = defaultSchema.types;
   } else {
-    var schemaName = parts.slice(0, parts.length - 1).join('.')
+    var schemaName = $Array.join($Array.slice(parts, 0, parts.length - 1), '.');
     var types = schemaRegistry.GetSchema(schemaName).types;
   }
   for (var i = 0; i < types.length; ++i) {
diff --git a/chrome/renderer/resources/extensions/web_request_custom_bindings.js b/chrome/renderer/resources/extensions/web_request_custom_bindings.js
index 6e2bac0..045fe96 100644
--- a/chrome/renderer/resources/extensions/web_request_custom_bindings.js
+++ b/chrome/renderer/resources/extensions/web_request_custom_bindings.js
@@ -12,7 +12,7 @@
   var apiFunctions = api.apiFunctions;
 
   apiFunctions.setHandleRequest('handlerBehaviorChanged', function() {
-    var args = Array.prototype.slice.call(arguments);
+    var args = $Array.slice(arguments);
     sendRequest(this.name, args, this.definition.parameters,
                 {forIOThread: true});
   });
diff --git a/chrome/renderer/resources/extensions/web_request_internal_custom_bindings.js b/chrome/renderer/resources/extensions/web_request_internal_custom_bindings.js
index 45ebec2..7d16805 100644
--- a/chrome/renderer/resources/extensions/web_request_internal_custom_bindings.js
+++ b/chrome/renderer/resources/extensions/web_request_internal_custom_bindings.js
@@ -67,7 +67,7 @@
   var subEventName = webRequestNatives.GetUniqueSubEventName(this.eventName_);
   // Note: this could fail to validate, in which case we would not add the
   // subEvent listener.
-  validate(Array.prototype.slice.call(arguments, 1), this.extraArgSchemas_);
+  validate($Array.slice(arguments, 1), this.extraArgSchemas_);
   webRequestInternal.addEventListener(
       cb, opt_filter, opt_extraInfo, this.eventName_, subEventName,
       this.webViewInstanceId_);
@@ -79,7 +79,7 @@
     subEventCallback = function() {
       var requestId = arguments[0].requestId;
       try {
-        var result = cb.apply(null, arguments);
+        var result = $Function.apply(cb, null, arguments);
         webRequestInternal.eventHandled(
             eventName, subEventName, requestId, result);
       } catch (e) {
@@ -97,10 +97,10 @@
         webRequestInternal.eventHandled(
             eventName, subEventName, requestId, response);
       };
-      cb.apply(null, [details, handledCallback]);
+      $Function.apply(cb, null, [details, handledCallback]);
     };
   }
-  this.subEvents_.push(
+  $Array.push(this.subEvents_,
       {subEvent: subEvent, callback: cb, subEventCallback: subEventCallback});
   subEvent.addListener(subEventCallback);
 };
@@ -117,7 +117,7 @@
       console.error(
           'Internal error: webRequest subEvent has orphaned listeners.');
     }
-    this.subEvents_.splice(idx, 1);
+    $Array.splice(this.subEvents_, idx, 1);
   }
 };
 
@@ -156,13 +156,13 @@
   var apiFunctions = api.apiFunctions;
 
   apiFunctions.setHandleRequest('addEventListener', function() {
-    var args = Array.prototype.slice.call(arguments);
+    var args = $Array.slice(arguments);
     sendRequest(this.name, args, this.definition.parameters,
                 {forIOThread: true});
   });
 
   apiFunctions.setHandleRequest('eventHandled', function() {
-    var args = Array.prototype.slice.call(arguments);
+    var args = $Array.slice(arguments);
     sendRequest(this.name, args, this.definition.parameters,
                 {forIOThread: true});
   });
diff --git a/chrome/renderer/resources/extensions/web_view.js b/chrome/renderer/resources/extensions/web_view.js
index 8337782..ee95690 100644
--- a/chrome/renderer/resources/extensions/web_view.js
+++ b/chrome/renderer/resources/extensions/web_view.js
@@ -8,6 +8,7 @@
 // are hidden via Shadow DOM.
 
 var watchForTag = require('tagWatcher').watchForTag;
+var eventBindings = require('event_bindings');
 
 /** @type {Array.<string>} */
 var WEB_VIEW_ATTRIBUTES = ['name', 'src', 'partition', 'autosize', 'minheight',
@@ -17,12 +18,6 @@
 // All exposed api methods for <webview>, these are forwarded to the browser
 // plugin.
 var WEB_VIEW_API_METHODS = [
-  'back',
-  'canGoBack',
-  'canGoForward',
-  'forward',
-  'getProcessId',
-  'go',
   'reload',
   'stop',
   'terminate'
@@ -31,21 +26,79 @@
 var WEB_VIEW_EVENTS = {
   'close': [],
   'consolemessage': ['level', 'message', 'line', 'sourceId'],
-  'contentload' : [],
   'exit' : ['processId', 'reason'],
   'loadabort' : ['url', 'isTopLevel', 'reason'],
-  'loadcommit' : ['url', 'isTopLevel'],
-  'loadredirect' : ['oldUrl', 'newUrl', 'isTopLevel'],
-  'loadstart' : ['url', 'isTopLevel'],
-  'loadstop' : [],
   'responsive' : ['processId'],
   'sizechanged': ['oldHeight', 'oldWidth', 'newHeight', 'newWidth'],
   'unresponsive' : ['processId']
 };
 
-window.addEventListener('DOMContentLoaded', function() {
-  watchForTag('WEBVIEW', function(addedNode) { new WebView(addedNode); });
-});
+var createEvent = function(name) {
+  var eventOpts = {supportsListeners: true, supportsFilters: true};
+  return new eventBindings.Event(name, undefined, eventOpts);
+};
+
+var contentLoadEvent = createEvent('webview.onContentLoad');
+var loadCommitEvent = createEvent('webview.onLoadCommit');
+var loadRedirectEvent = createEvent('webview.onLoadRedirect');
+var loadStartEvent = createEvent('webview.onLoadStart');
+var loadStopEvent = createEvent('webview.onLoadStop');
+
+var WEB_VIEW_EXT_EVENTS = {
+  'contentload': {
+    evt: contentLoadEvent,
+    fields: []
+  },
+  'loadcommit': {
+    customHandler: function(webview, event) {
+      webview.currentEntryIndex_ = event.currentEntryIndex;
+      webview.entryCount_ = event.entryCount;
+      webview.processId_ = event.processId;
+    },
+    evt: loadCommitEvent,
+    fields: ['url', 'isTopLevel']
+  },
+  'loadredirect': {
+    evt: loadRedirectEvent,
+    fields: ['isTopLevel', 'oldUrl', 'newUrl']
+  },
+  'loadstart': {
+    evt: loadStartEvent,
+    fields: ['url', 'isTopLevel']
+  },
+  'loadstop': {
+    evt: loadStopEvent,
+    fields: []
+  }
+};
+
+
+// The <webview> tags we wish to watch for (watchForTag) does not belong to the
+// current scope's "document" reference. We need to wait until the document
+// begins loading, since only then will the "document" reference
+// point to the page's document (it will be reset between now and then).
+// We can't listen for the "readystatechange" event on the document (because
+// the object that it's dispatched on doesn't exist yet), but we can instead
+// do it at the window level in the capturing phase.
+window.addEventListener('readystatechange', function(e) {
+  if (document.readyState != 'loading') {
+    return;
+  }
+
+  document.addEventListener('DOMContentLoaded', function(e) {
+    watchForTag('WEBVIEW', function(addedNode) { new WebView(addedNode); });
+  });
+}, true /* useCapture */);
+
+
+/** @type {number} */
+WebView.prototype.entryCount_;
+
+/** @type {number} */
+WebView.prototype.currentEntryIndex_;
+
+/** @type {number} */
+WebView.prototype.processId_;
 
 /**
  * @constructor
@@ -72,6 +125,7 @@
 WebView.prototype.createBrowserPluginNode_ = function() {
   var browserPluginNode = document.createElement('object');
   browserPluginNode.type = 'application/browser-plugin';
+  browserPluginNode.setAttribute('api', 'webview');
   // The <object> node fills in the <webview> container.
   browserPluginNode.style.width = '100%';
   browserPluginNode.style.height = '100%';
@@ -122,11 +176,42 @@
 WebView.prototype.setupWebviewNodeMethods_ = function() {
   // this.browserPluginNode_[apiMethod] are not necessarily defined immediately
   // after the shadow object is appended to the shadow root.
+  var webviewNode = this.webviewNode_;
+  var browserPluginNode = this.browserPluginNode_;
   var self = this;
+
+  webviewNode['canGoBack'] = function() {
+    return self.entryCount_ > 1 && self.currentEntryIndex_ > 0;
+  };
+
+  webviewNode['canGoForward'] = function() {
+    return self.currentEntryIndex_ >=0 &&
+        self.currentEntryIndex_ < (self.entryCount_ - 1);
+  };
+
+  webviewNode['back'] = function() {
+    webviewNode.go(-1);
+  };
+
+  webviewNode['forward'] = function() {
+    webviewNode.go(1);
+  };
+
+  webviewNode['getProcessId'] = function() {
+    return self.processId_;
+  };
+
+  webviewNode['go'] = function(relativeIndex) {
+    var instanceId = browserPluginNode.getGuestInstanceId();
+    if (!instanceId)
+      return;
+    chrome.webview.go(instanceId, relativeIndex);
+  };
+
   $Array.forEach(WEB_VIEW_API_METHODS, function(apiMethod) {
-    self.webviewNode_[apiMethod] = function(var_args) {
-      return self.browserPluginNode_[apiMethod].apply(
-          self.browserPluginNode_, arguments);
+    webviewNode[apiMethod] = function(var_args) {
+      return $Function.apply(browserPluginNode[apiMethod],
+          browserPluginNode, arguments);
     };
   }, this);
   this.setupExecuteCodeAPI_();
@@ -158,10 +243,8 @@
   // getter value.
   Object.defineProperty(this.webviewNode_, 'contentWindow', {
     get: function() {
-      // TODO(fsamuel): This is a workaround to enable
-      // contentWindow.postMessage until http://crbug.com/152006 is fixed.
       if (browserPluginNode.contentWindow)
-        return browserPluginNode.contentWindow.self;
+        return browserPluginNode.contentWindow;
       console.error(ERROR_MSG_CONTENTWINDOW_NOT_AVAILABLE);
     },
     // No setter.
@@ -186,7 +269,7 @@
   var handleMutation = $Function.bind(function(mutation) {
     this.handleWebviewAttributeMutation_(mutation);
   }, this);
-  var observer = new WebKitMutationObserver(function(mutations) {
+  var observer = new MutationObserver(function(mutations) {
     $Array.forEach(mutations, handleMutation);
   });
   observer.observe(
@@ -201,7 +284,7 @@
   var handleMutation = $Function.bind(function(mutation) {
     this.handleBrowserPluginAttributeMutation_(mutation);
   }, this);
-  var objectObserver = new WebKitMutationObserver(function(mutations) {
+  var objectObserver = new MutationObserver(function(mutations) {
     $Array.forEach(mutations, handleMutation);
   });
   objectObserver.observe(
@@ -252,6 +335,16 @@
  * @private
  */
 WebView.prototype.setupWebviewNodeEvents_ = function() {
+  var self = this;
+  var webviewNode = this.webviewNode_;
+  this.browserPluginNode_.addEventListener('-internal-attached', function(e) {
+    var detail = e.detail ? JSON.parse(e.detail) : {};
+    self.instanceId_ = detail.windowId;
+    for (var eventName in WEB_VIEW_EXT_EVENTS) {
+      self.setupExtEvent_(eventName, WEB_VIEW_EXT_EVENTS[eventName]);
+    }
+  });
+
   for (var eventName in WEB_VIEW_EVENTS) {
     this.setupEvent_(eventName, WEB_VIEW_EVENTS[eventName]);
   }
@@ -262,11 +355,29 @@
 /**
  * @private
  */
-WebView.prototype.setupEvent_ = function(eventname, attribs) {
+WebView.prototype.setupExtEvent_ = function(eventName, eventInfo) {
+  var self = this;
   var webviewNode = this.webviewNode_;
-  var internalname = '-internal-' + eventname;
+  eventInfo.evt.addListener(function(event) {
+    var webviewEvent = new Event(eventName, {bubbles: true});
+    $Array.forEach(eventInfo.fields, function(field) {
+      webviewEvent[field] = event[field];
+    });
+    if (eventInfo.customHandler) {
+      eventInfo.customHandler(self, event);
+    }
+    webviewNode.dispatchEvent(webviewEvent);
+  }, {instanceId: self.instanceId_});
+};
+
+/**
+ * @private
+ */
+WebView.prototype.setupEvent_ = function(eventName, attribs) {
+  var webviewNode = this.webviewNode_;
+  var internalname = '-internal-' + eventName;
   this.browserPluginNode_.addEventListener(internalname, function(e) {
-    var evt = new Event(eventname, { bubbles: true });
+    var evt = new Event(eventName, { bubbles: true });
     var detail = e.detail ? JSON.parse(e.detail) : {};
     $Array.forEach(attribs, function(attribName) {
       evt[attribName] = detail[attribName];
@@ -303,7 +414,7 @@
     var evt = new Event('newwindow', { bubbles: true, cancelable: true });
     var detail = e.detail ? JSON.parse(e.detail) : {};
 
-    NEW_WINDOW_EVENT_ATTRIBUTES.forEach(function(attribName) {
+    $Array.forEach(NEW_WINDOW_EVENT_ATTRIBUTES, function(attribName) {
       evt[attribName] = detail[attribName];
     });
     var requestId = detail.requestId;
@@ -375,15 +486,15 @@
 
   this.webviewNode_['executeScript'] = function(var_args) {
     validateCall();
-    var args = [self.browserPluginNode_.getGuestInstanceId()].concat(
-        Array.prototype.slice.call(arguments));
-    chrome.webview.executeScript.apply(null, args);
+    var args = $Array.concat([self.browserPluginNode_.getGuestInstanceId()],
+                             $Array.slice(arguments));
+    $Function.apply(chrome.webview.executeScript, null, args);
   }
   this.webviewNode_['insertCSS'] = function(var_args) {
     validateCall();
-    var args = [self.browserPluginNode_.getGuestInstanceId()].concat(
-        Array.prototype.slice.call(arguments));
-    chrome.webview.insertCSS.apply(null, args);
+    var args = $Array.concat([self.browserPluginNode_.getGuestInstanceId()],
+                             $Array.slice(arguments));
+    $Function.apply(chrome.webview.insertCSS, null, args);
   }
 };
 
diff --git a/chrome/renderer/resources/extensions/window_controls.js b/chrome/renderer/resources/extensions/window_controls.js
new file mode 100644
index 0000000..1e69695
--- /dev/null
+++ b/chrome/renderer/resources/extensions/window_controls.js
@@ -0,0 +1,84 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+//
+// <window-controls> shadow element implementation.
+//
+
+var chrome = requireNative('chrome').GetChrome();
+var forEach = require('utils').forEach;
+var watchForTag = require('tagWatcher').watchForTag;
+var appWindow = require('app.window');
+var getHtmlTemplate =
+  requireNative('app_window_natives').GetWindowControlsHtmlTemplate;
+
+/**
+ * @constructor
+ */
+function WindowControls(document, node) {
+  this.node_ = node;
+  this.shadowRoot_ = this.createShadowRoot_(node);
+  this.setupWindowControls_();
+}
+
+/**
+ * @private
+ */
+WindowControls.prototype.template_element = null;
+
+/**
+ * @private
+ */
+WindowControls.prototype.createShadowRoot_ = function(node) {
+  // Initialize |template| from HTML template resource and cache result.
+  var template = WindowControls.prototype.template_element;
+  if (!template) {
+    var element = document.createElement('div');
+    element.innerHTML = getHtmlTemplate();
+    WindowControls.prototype.template_element = element.firstChild;
+    template = WindowControls.prototype.template_element;
+  }
+  // Create shadow root element with template clone as first child.
+  var shadowRoot = node.webkitCreateShadowRoot();
+  shadowRoot.appendChild(template.content.cloneNode(true));
+  return shadowRoot;
+}
+
+/**
+ * @private
+ */
+WindowControls.prototype.setupWindowControls_ = function() {
+  var self = this;
+  this.shadowRoot_.querySelector("#close-control").addEventListener('click',
+      function(e) {
+        chrome.app.window.current().close();
+      });
+
+  this.shadowRoot_.querySelector("#maximize-control").addEventListener('click',
+      function(e) {
+        self.maxRestore_();
+      });
+}
+
+/**
+ * @private
+ * Restore or maximize depending on current state
+ */
+WindowControls.prototype.maxRestore_ = function() {
+  if (chrome.app.window.current().isMaximized()) {
+    chrome.app.window.current().restore();
+  } else {
+    chrome.app.window.current().maximize();
+  }
+}
+
+//
+//Hook up <window-controls> tag creation in DOM.
+//
+window.addEventListener('DOMContentLoaded', function() {
+  var doc = window.document;
+  watchForTag('WINDOW-CONTROLS', function(addedNode) {
+    new WindowControls(doc, addedNode);
+    });
+});
diff --git a/chrome/renderer/resources/extensions/window_controls_template.html b/chrome/renderer/resources/extensions/window_controls_template.html
new file mode 100644
index 0000000..6f468bc
--- /dev/null
+++ b/chrome/renderer/resources/extensions/window_controls_template.html
@@ -0,0 +1,52 @@
+<template id="window-controls-template">
+  <style>
+    .controls {
+      width:32px;
+      height:32px;
+      position:absolute;
+      z-index:200;
+    }
+    #close-control {
+      top:8px;
+      right:10px;
+    }
+    #maximize-control {
+      top:8px;
+      right:52px;
+    }
+    #close {
+      top:0;
+      right:0;
+      -webkit-mask-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAALNJREFUeNrsllEOwyAIhmVXwIu487dXKEdy2PBgWuxwm/VhkPwvSuALAhFyzmGmPcJkcwAHcAAHMAMAQGItLGSFhlB8kpmgrGKL2NbiziIWKqHK2SY+qzluBwBKcg2iTr7fjQBoQZySd1W2E0CD2LSqjAQ4Qqh9YY37zRj+5iPx4RPUZac7n6DVhHRHE74bQxo9hvUiio1FRCMXURKIeNFSKD5Pa1zwX7EDOIAD/D3AS4ABAKWdkCCeGGsrAAAAAElFTkSuQmCC');
+    }
+    .windowbutton {
+      width:32px;
+      height:32px;
+      position:absolute;
+      background-color:rgba(0, 0, 0, 0.49);
+    }
+    .windowbuttonbackground {
+      width:32px;
+      height:32px;
+      position:absolute;
+    }
+    .windowbuttonbackground:hover {
+      background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAEBJREFUeNrszrENAEAIw8A8EvU32X9RGsQUaewFfM/2l9TKNBWcX10KBwAAAAAAAAAAAAAAAAAAABxggv9ZAQYAhakDi3I15kgAAAAASUVORK5CYII=');
+
+    }
+    .windowbuttonbackground:active {
+      background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAFtJREFUeNrs1zESgCAMRNEAkSZD5VW8/1k8hFaCCqfY5u9M6v/apIh2mH1hkqXba92uUvxU5Mfoe57xx0Rb7WziAQAAAAAAAAAAAAAAAAAAOcDXkzqvifrvL8AAWBcLpapo5CcAAAAASUVORK5CYII=');
+    }
+    #maximize {
+      -webkit-mask-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAFFJREFUeNrs1jsOACAIREHWeP8royWdnwaDj9pi2OhGubtlTrPkAQAAAIC+e1DSUWXOhlWtBGIYq+W5hAAA1GzC23f+fALiVwwAAIDvAUOAAQAv/Aw+jTHzugAAAABJRU5ErkJggg==');
+    }
+  </style>
+  <div id="close-control" class="controls">
+    <div id="close" class="windowbutton"> </div>
+    <div id="close-background" class="windowbuttonbackground"> </div>
+  </div>
+  <div id="maximize-control" class="controls">
+    <div id="maximize" class="windowbutton"></div>
+    <div id="maximize-background" class="windowbuttonbackground"></div>
+  </div>
+</template>
diff --git a/chrome/renderer/resources/neterror.html b/chrome/renderer/resources/neterror.html
index 365d128..bb301f2 100644
--- a/chrome/renderer/resources/neterror.html
+++ b/chrome/renderer/resources/neterror.html
@@ -337,6 +337,7 @@
    </div>
   </div>
  </div>
+</div>
 <div id="sub-frame-error">
   <!-- Show details when hovering over the icon, in case the details are
        hidden because they're too large. -->
diff --git a/chrome/renderer/resources/play.png b/chrome/renderer/resources/play.png
index 947cafe..fa19179 100644
--- a/chrome/renderer/resources/play.png
+++ b/chrome/renderer/resources/play.png
Binary files differ
diff --git a/chrome/renderer/resources/plugin_blocked.png b/chrome/renderer/resources/plugin_blocked.png
index 7ce78ab..07a516a 100644
--- a/chrome/renderer/resources/plugin_blocked.png
+++ b/chrome/renderer/resources/plugin_blocked.png
Binary files differ
diff --git a/chrome/renderer/resources/plugin_blocked_android.png b/chrome/renderer/resources/plugin_blocked_android.png
index 24e484e..fbf6b41 100644
--- a/chrome/renderer/resources/plugin_blocked_android.png
+++ b/chrome/renderer/resources/plugin_blocked_android.png
Binary files differ
diff --git a/chrome/renderer/resources/renderer_resources.grd b/chrome/renderer/resources/renderer_resources.grd
index 88d317e..93e82f7 100644
--- a/chrome/renderer/resources/renderer_resources.grd
+++ b/chrome/renderer/resources/renderer_resources.grd
@@ -47,7 +47,6 @@
         <!-- Custom bindings for extension APIs. -->
         <include name="IDR_AD_VIEW_DENY_JS" file="extensions\ad_view_deny.js" type="BINDATA" />
         <include name="IDR_AD_VIEW_JS" file="extensions\ad_view.js" type="BINDATA" />
-        <include name="IDR_AD_VIEW_CUSTOM_JS" file="extensions\ad_view_custom.js" type="BINDATA" />
         <include name="IDR_APP_CUSTOM_BINDINGS_JS" file="extensions\app_custom_bindings.js" type="BINDATA" />
         <include name="IDR_APP_RUNTIME_CUSTOM_BINDINGS_JS" file="extensions\app_runtime_custom_bindings.js" type="BINDATA" />
         <include name="IDR_APP_WINDOW_CUSTOM_BINDINGS_JS" file="extensions\app_window_custom_bindings.js" type="BINDATA" />
@@ -85,6 +84,8 @@
         <include name="IDR_TEST_CUSTOM_BINDINGS_JS" file="extensions\test_custom_bindings.js" type="BINDATA" />
         <include name="IDR_TTS_CUSTOM_BINDINGS_JS" file="extensions\tts_custom_bindings.js" type="BINDATA" />
         <include name="IDR_TTS_ENGINE_CUSTOM_BINDINGS_JS" file="extensions\tts_engine_custom_bindings.js" type="BINDATA" />
+        <include name="IDR_WINDOW_CONTROLS_JS" file="extensions\window_controls.js" type="BINDATA" />
+        <include name="IDR_WINDOW_CONTROLS_TEMPLATE_HTML" file="extensions\window_controls_template.html" type="BINDATA" />
         <include name="IDR_WEB_REQUEST_CUSTOM_BINDINGS_JS" file="extensions\web_request_custom_bindings.js" type="BINDATA" />
         <include name="IDR_WEB_REQUEST_INTERNAL_CUSTOM_BINDINGS_JS" file="extensions\web_request_internal_custom_bindings.js" type="BINDATA" />
         <include name="IDR_WEBSTORE_CUSTOM_BINDINGS_JS" file="extensions\webstore_custom_bindings.js" type="BINDATA" />
diff --git a/chrome/renderer/resources/youtube.png b/chrome/renderer/resources/youtube.png
index 65873fd..f2c28eb 100644
--- a/chrome/renderer/resources/youtube.png
+++ b/chrome/renderer/resources/youtube.png
Binary files differ
diff --git a/chrome/renderer/safe_browsing/feature_extractor_clock.h b/chrome/renderer/safe_browsing/feature_extractor_clock.h
index 54bff06..f14fc24 100644
--- a/chrome/renderer/safe_browsing/feature_extractor_clock.h
+++ b/chrome/renderer/safe_browsing/feature_extractor_clock.h
@@ -8,7 +8,7 @@
 #ifndef CHROME_RENDERER_SAFE_BROWSING_FEATURE_EXTRACTOR_CLOCK_H_
 #define CHROME_RENDERER_SAFE_BROWSING_FEATURE_EXTRACTOR_CLOCK_H_
 
-#include "base/time.h"
+#include "base/time/time.h"
 
 namespace safe_browsing {
 
diff --git a/chrome/renderer/safe_browsing/phishing_dom_feature_extractor.cc b/chrome/renderer/safe_browsing/phishing_dom_feature_extractor.cc
index bff86e6..86faa69 100644
--- a/chrome/renderer/safe_browsing/phishing_dom_feature_extractor.cc
+++ b/chrome/renderer/safe_browsing/phishing_dom_feature_extractor.cc
@@ -11,16 +11,16 @@
 #include "base/message_loop.h"
 #include "base/metrics/histogram.h"
 #include "base/strings/string_util.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/renderer/safe_browsing/feature_extractor_clock.h"
 #include "chrome/renderer/safe_browsing/features.h"
 #include "content/public/renderer/render_view.h"
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+#include "third_party/WebKit/public/platform/WebString.h"
 #include "third_party/WebKit/public/web/WebElement.h"
 #include "third_party/WebKit/public/web/WebFrame.h"
 #include "third_party/WebKit/public/web/WebNodeCollection.h"
 #include "third_party/WebKit/public/web/WebView.h"
-#include "third_party/WebKit/public/platform/WebString.h"
 
 namespace safe_browsing {
 
diff --git a/chrome/renderer/safe_browsing/phishing_dom_feature_extractor_browsertest.cc b/chrome/renderer/safe_browsing/phishing_dom_feature_extractor_browsertest.cc
index 60cfc0c..e98919f 100644
--- a/chrome/renderer/safe_browsing/phishing_dom_feature_extractor_browsertest.cc
+++ b/chrome/renderer/safe_browsing/phishing_dom_feature_extractor_browsertest.cc
@@ -14,7 +14,7 @@
 #include "base/compiler_specific.h"
 #include "base/memory/weak_ptr.h"
 #include "base/message_loop.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/renderer/safe_browsing/features.h"
 #include "chrome/renderer/safe_browsing/mock_feature_extractor_clock.h"
 #include "chrome/renderer/safe_browsing/test_utils.h"
@@ -223,8 +223,7 @@
   ExpectFeatureMapsAreEqual(features, expected_features);
 }
 
-// TODO(kbr): http://crbug.com/251376
-TEST_F(PhishingDOMFeatureExtractorTest, DISABLED_SubFrames) {
+TEST_F(PhishingDOMFeatureExtractorTest, SubFrames) {
   // This test doesn't exercise the extraction timing.
   EXPECT_CALL(clock_, Now()).WillRepeatedly(Return(base::TimeTicks::Now()));
 
diff --git a/chrome/renderer/safe_browsing/phishing_term_feature_extractor.cc b/chrome/renderer/safe_browsing/phishing_term_feature_extractor.cc
index 31e075d..b2a3aef 100644
--- a/chrome/renderer/safe_browsing/phishing_term_feature_extractor.cc
+++ b/chrome/renderer/safe_browsing/phishing_term_feature_extractor.cc
@@ -14,7 +14,7 @@
 #include "base/message_loop.h"
 #include "base/metrics/histogram.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/renderer/safe_browsing/feature_extractor_clock.h"
 #include "chrome/renderer/safe_browsing/features.h"
 #include "chrome/renderer/safe_browsing/murmurhash3_util.h"
diff --git a/chrome/renderer/safe_browsing/phishing_term_feature_extractor_unittest.cc b/chrome/renderer/safe_browsing/phishing_term_feature_extractor_unittest.cc
index b348d29..7aa8a23 100644
--- a/chrome/renderer/safe_browsing/phishing_term_feature_extractor_unittest.cc
+++ b/chrome/renderer/safe_browsing/phishing_term_feature_extractor_unittest.cc
@@ -14,7 +14,7 @@
 #include "base/strings/string16.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/renderer/safe_browsing/features.h"
 #include "chrome/renderer/safe_browsing/mock_feature_extractor_clock.h"
 #include "chrome/renderer/safe_browsing/murmurhash3_util.h"
diff --git a/chrome/renderer/searchbox/searchbox.cc b/chrome/renderer/searchbox/searchbox.cc
index 1d87397..c098637 100644
--- a/chrome/renderer/searchbox/searchbox.cc
+++ b/chrome/renderer/searchbox/searchbox.cc
@@ -28,6 +28,23 @@
 // Size of the results cache.
 const size_t kMaxInstantAutocompleteResultItemCacheSize = 100;
 
+// Returns true if items stored in |old_item_id_pairs| and |new_items| are
+// equal.
+bool AreMostVisitedItemsEqual(
+    const std::vector<InstantMostVisitedItemIDPair>& old_item_id_pairs,
+    const std::vector<InstantMostVisitedItem>& new_items) {
+  if (old_item_id_pairs.size() != new_items.size())
+    return false;
+
+  for (size_t i = 0; i < new_items.size(); ++i) {
+    if (new_items[i].url != old_item_id_pairs[i].second.url ||
+        new_items[i].title != old_item_id_pairs[i].second.title) {
+      return false;
+    }
+  }
+  return true;
+}
+
 }  // namespace
 
 namespace internal {  // for testing
@@ -73,6 +90,7 @@
       is_input_in_progress_(false),
       display_instant_results_(false),
       omnibox_font_size_(0),
+      app_launcher_enabled_(false),
       autocomplete_results_cache_(kMaxInstantAutocompleteResultItemCacheSize),
       most_visited_items_cache_(kMaxInstantMostVisitedItemCacheSize) {
 }
@@ -92,6 +110,11 @@
       render_view()->GetRoutingID(), render_view()->GetPageId(), suggestions));
 }
 
+void SearchBox::SetVoiceSearchSupported(bool supported) {
+  render_view()->Send(new ChromeViewHostMsg_SetVoiceSearchSupported(
+      render_view()->GetRoutingID(), render_view()->GetPageId(), supported));
+}
+
 void SearchBox::MarkQueryAsRestricted() {
   query_is_restricted_ = true;
   query_.clear();
@@ -249,6 +272,8 @@
                         OnThemeChanged)
     IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxFontInformation,
                         OnFontInformationReceived)
+    IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxPromoInformation,
+                        OnPromoInformationReceived)
     IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxMostVisitedItemsChanged,
                         OnMostVisitedChanged)
     IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxToggleVoiceSearch,
@@ -448,6 +473,10 @@
 }
 
 void SearchBox::OnThemeChanged(const ThemeBackgroundInfo& theme_info) {
+  // Do not send duplicate notifications.
+  if (theme_info_ == theme_info)
+    return;
+
   theme_info_ = theme_info;
   if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) {
     extensions_v8::SearchBoxExtension::DispatchThemeChange(
@@ -461,6 +490,10 @@
   omnibox_font_size_ = omnibox_font_size;
 }
 
+void SearchBox::OnPromoInformationReceived(bool is_app_launcher_enabled) {
+  app_launcher_enabled_ = is_app_launcher_enabled;
+}
+
 double SearchBox::GetZoom() const {
   WebKit::WebView* web_view = render_view()->GetWebView();
   if (web_view) {
@@ -497,6 +530,12 @@
 
 void SearchBox::OnMostVisitedChanged(
     const std::vector<InstantMostVisitedItem>& items) {
+  std::vector<InstantMostVisitedItemIDPair> last_known_items;
+  GetMostVisitedItems(&last_known_items);
+
+  if (AreMostVisitedItemsEqual(last_known_items, items))
+    return;  // Do not send duplicate onmostvisitedchange events.
+
   most_visited_items_cache_.AddItems(items);
   if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) {
     extensions_v8::SearchBoxExtension::DispatchMostVisitedChanged(
diff --git a/chrome/renderer/searchbox/searchbox.h b/chrome/renderer/searchbox/searchbox.h
index 0a45a05..38a766e 100644
--- a/chrome/renderer/searchbox/searchbox.h
+++ b/chrome/renderer/searchbox/searchbox.h
@@ -32,6 +32,9 @@
   // Sends ChromeViewHostMsg_SetSuggestion to the browser.
   void SetSuggestions(const std::vector<InstantSuggestion>& suggestions);
 
+  // Sends ChromeViewHostMsg_SetVoiceSearchSupported to the browser.
+  void SetVoiceSearchSupported(bool supported);
+
   // Marks the current query text as restricted, to make sure that it does
   // not get communicated to the page.  The restricted status lasts until the
   // query is next changed or cleared.
@@ -73,6 +76,7 @@
   bool display_instant_results() const { return display_instant_results_; }
   const string16& omnibox_font() const { return omnibox_font_; }
   size_t omnibox_font_size() const { return omnibox_font_size_; }
+  bool app_launcher_enabled() const { return app_launcher_enabled_; }
 
   // In extended Instant, returns the start-edge margin of the location bar in
   // screen pixels.
@@ -165,6 +169,7 @@
   void OnThemeAreaHeightChanged(int height);
   void OnFontInformationReceived(const string16& omnibox_font,
                                  size_t omnibox_font_size);
+  void OnPromoInformationReceived(bool is_app_launcher_enabled);
   void OnMostVisitedChanged(
       const std::vector<InstantMostVisitedItem>& items);
   void OnToggleVoiceSearch();
@@ -195,6 +200,7 @@
   bool display_instant_results_;
   string16 omnibox_font_;
   size_t omnibox_font_size_;
+  bool app_launcher_enabled_;
   InstantRestrictedIDCache<InstantAutocompleteResult>
       autocomplete_results_cache_;
   InstantRestrictedIDCache<InstantMostVisitedItem> most_visited_items_cache_;
diff --git a/chrome/renderer/searchbox/searchbox_extension.cc b/chrome/renderer/searchbox/searchbox_extension.cc
index 7c19aed..e2779ee 100644
--- a/chrome/renderer/searchbox/searchbox_extension.cc
+++ b/chrome/renderer/searchbox/searchbox_extension.cc
@@ -572,6 +572,10 @@
   // Gets the font size of the text in the omnibox.
   static void GetFontSize(const v8::FunctionCallbackInfo<v8::Value>& args);
 
+  // Gets whether or not the app launcher is enabled.
+  static void GetAppLauncherEnabled(
+      const v8::FunctionCallbackInfo<v8::Value>& args);
+
   // Navigates the window to a URL represented by either a URL string or a
   // restricted ID. The two variants handle restricted IDs in their
   // respective namespaces.
@@ -602,6 +606,10 @@
   static void SetQueryFromAutocompleteResult(
       const v8::FunctionCallbackInfo<v8::Value>& args);
 
+  // Indicates whether the page supports voice search.
+  static void SetVoiceSearchSupported(
+      const v8::FunctionCallbackInfo<v8::Value>& args);
+
   // Requests the overlay be shown with the specified contents and height.
   static void ShowOverlay(const v8::FunctionCallbackInfo<v8::Value>& args);
 
@@ -697,6 +705,8 @@
     return v8::FunctionTemplate::New(GetFont);
   if (name->Equals(v8::String::New("GetFontSize")))
     return v8::FunctionTemplate::New(GetFontSize);
+  if (name->Equals(v8::String::New("GetAppLauncherEnabled")))
+    return v8::FunctionTemplate::New(GetAppLauncherEnabled);
   if (name->Equals(v8::String::New("NavigateSearchBox")))
     return v8::FunctionTemplate::New(NavigateSearchBox);
   if (name->Equals(v8::String::New("NavigateNewTabPage")))
@@ -713,6 +723,8 @@
     return v8::FunctionTemplate::New(SetQuery);
   if (name->Equals(v8::String::New("SetQueryFromAutocompleteResult")))
     return v8::FunctionTemplate::New(SetQueryFromAutocompleteResult);
+  if (name->Equals(v8::String::New("SetVoiceSearchSupported")))
+    return v8::FunctionTemplate::New(SetVoiceSearchSupported);
   if (name->Equals(v8::String::New("ShowOverlay")))
     return v8::FunctionTemplate::New(ShowOverlay);
   if (name->Equals(v8::String::New("FocusOmnibox")))
@@ -1025,6 +1037,16 @@
 }
 
 // static
+void SearchBoxExtensionWrapper::GetAppLauncherEnabled(
+    const v8::FunctionCallbackInfo<v8::Value>& args) {
+  content::RenderView* render_view = GetRenderView();
+  if (!render_view) return;
+
+  args.GetReturnValue().Set(
+      SearchBox::Get(render_view)->app_launcher_enabled());
+}
+
+// static
 void SearchBoxExtensionWrapper::NavigateSearchBox(
     const v8::FunctionCallbackInfo<v8::Value>& args) {
   content::RenderView* render_view = GetRenderView();
@@ -1264,6 +1286,16 @@
 }
 
 // static
+void SearchBoxExtensionWrapper::SetVoiceSearchSupported(
+    const v8::FunctionCallbackInfo<v8::Value>& args) {
+  content::RenderView* render_view = GetRenderView();
+  if (!render_view || args.Length() < 1) return;
+
+  DVLOG(1) << render_view << " SetVoiceSearchSupported";
+  SearchBox::Get(render_view)->SetVoiceSearchSupported(args[0]->BooleanValue());
+}
+
+// static
 void SearchBoxExtensionWrapper::ShowOverlay(
     const v8::FunctionCallbackInfo<v8::Value>& args) {
   content::RenderView* render_view = GetRenderView();
diff --git a/chrome/renderer/spellchecker/hunspell_engine.cc b/chrome/renderer/spellchecker/hunspell_engine.cc
index 23706fa..3b79c10 100644
--- a/chrome/renderer/spellchecker/hunspell_engine.cc
+++ b/chrome/renderer/spellchecker/hunspell_engine.cc
@@ -9,7 +9,7 @@
 
 #include "base/files/memory_mapped_file.h"
 #include "base/metrics/histogram.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/common/spellcheck_common.h"
 #include "chrome/common/spellcheck_messages.h"
 #include "content/public/renderer/render_thread.h"
diff --git a/chrome/renderer/translate/translate_helper.cc b/chrome/renderer/translate/translate_helper.cc
index 4428b53..fbc4d06 100644
--- a/chrome/renderer/translate/translate_helper.cc
+++ b/chrome/renderer/translate/translate_helper.cc
@@ -9,6 +9,7 @@
 #include "base/logging.h"
 #include "base/message_loop.h"
 #include "base/strings/string16.h"
+#include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/common/chrome_constants.h"
@@ -327,14 +328,41 @@
 }
 
 // static
-void TranslateHelper::ResetInvalidLanguageCode(std::string* code) {
-  // Roughly check if the language code follows [a-z][a-z](-[A-Z][A-Z]).
-  size_t dash_index = code->find('-');
-  if (!(dash_index == 2 && code->size() == 5) &&
-      !(dash_index == std::string::npos && code->size() == 2)) {
-    // Reset |language| to ignore the invalid code.
-    *code = std::string();
+bool TranslateHelper::IsValidLanguageCode(const std::string& code) {
+  // Roughly check if the language code follows /[a-zA-Z]{2,3}(-[a-zA-Z]{2})?/.
+  // TODO(hajimehoshi): How about es-419, which is used as an Accept language?
+  std::vector<std::string> chunks;
+  base::SplitString(code, '-', &chunks);
+
+  if (chunks.size() < 1 || 2 < chunks.size())
+    return false;
+
+  const std::string& main_code = chunks[0];
+
+  if (main_code.size() < 1 || 3 < main_code.size())
+    return false;
+
+  for (std::string::const_iterator it = main_code.begin();
+       it != main_code.end(); ++it) {
+    if (!IsAsciiAlpha(*it))
+      return false;
   }
+
+  if (chunks.size() == 1)
+    return true;
+
+  const std::string& sub_code = chunks[1];
+
+  if (sub_code.size() != 2)
+    return false;
+
+  for (std::string::const_iterator it = sub_code.begin();
+       it != sub_code.end(); ++it) {
+    if (!IsAsciiAlpha(*it))
+      return false;
+  }
+
+  return true;
 }
 
 // static
@@ -342,11 +370,12 @@
   // Correct well-known format errors.
   CorrectLanguageCodeTypo(code);
 
-  // Convert language code synonym firstly because sometime synonym code is in
-  // invalid format, e.g. 'fil'. After validation, such a 3 characters language
-  // gets converted to an empty string.
+  if (!IsValidLanguageCode(*code)) {
+    *code = std::string();
+    return;
+  }
+
   TranslateUtil::ToTranslateLanguageSynonym(code);
-  ResetInvalidLanguageCode(code);
 }
 
 // static
@@ -392,6 +421,16 @@
 }
 
 // static
+bool TranslateHelper::CanCLDComplementSubCode(
+    const std::string& page_language, const std::string& cld_language) {
+  // Translate server cannot treat general Chinese. If Content-Language and
+  // CLD agree that the language is Chinese and Content-Language doesn't know
+  // which dialect is used, CLD language has priority.
+  // TODO(hajimehoshi): How about the other dialects like zh-MO?
+  return page_language == "zh" && StartsWithASCII(cld_language, "zh-", false);
+}
+
+// static
 std::string TranslateHelper::DeterminePageLanguage(const std::string& code,
                                                    const std::string& html_lang,
                                                    const string16& contents,
@@ -445,13 +484,19 @@
   if (cld_language == chrome::kUnknownLanguageCode) {
     TranslateHelperMetrics::ReportLanguageVerification(
         TranslateHelperMetrics::LANGUAGE_VERIFICATION_UNKNOWN);
+    return language;
   } else if (IsSameOrSimilarLanguages(language, cld_language)) {
     TranslateHelperMetrics::ReportLanguageVerification(
         TranslateHelperMetrics::LANGUAGE_VERIFICATION_CLD_AGREE);
+    return language;
   } else if (MaybeServerWrongConfiguration(language, cld_language)) {
-    language = cld_language;
     TranslateHelperMetrics::ReportLanguageVerification(
         TranslateHelperMetrics::LANGUAGE_VERIFICATION_TRUST_CLD);
+    return cld_language;
+  } else if (CanCLDComplementSubCode(language, cld_language)) {
+    TranslateHelperMetrics::ReportLanguageVerification(
+        TranslateHelperMetrics::LANGUAGE_VERIFICATION_CLD_COMPLEMENT_SUB_CODE);
+    return cld_language;
   } else {
     TranslateHelperMetrics::ReportLanguageVerification(
         TranslateHelperMetrics::LANGUAGE_VERIFICATION_CLD_DISAGREE);
diff --git a/chrome/renderer/translate/translate_helper.h b/chrome/renderer/translate/translate_helper.h
index fa2b0b0..21fbcaa 100644
--- a/chrome/renderer/translate/translate_helper.h
+++ b/chrome/renderer/translate/translate_helper.h
@@ -9,7 +9,7 @@
 
 #include "base/gtest_prod_util.h"
 #include "base/memory/weak_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/common/translate/translate_errors.h"
 #include "content/public/renderer/render_view_observer.h"
 
@@ -87,6 +87,7 @@
   virtual double ExecuteScriptAndGetDoubleResult(const std::string& script);
 
  private:
+  FRIEND_TEST_ALL_PREFIXES(TranslateHelperTest, IsValidLanguageCode);
   FRIEND_TEST_ALL_PREFIXES(TranslateHelperTest, AdoptHtmlLang);
   FRIEND_TEST_ALL_PREFIXES(TranslateHelperTest,
                            CLDAgreeWithLanguageCodeHavingCountryCode);
@@ -106,8 +107,8 @@
   // Converts language code to the one used in server supporting list.
   static void ConvertLanguageCodeSynonym(std::string* code);
 
-  // Resets language code if the specified string is apparently invalid.
-  static void ResetInvalidLanguageCode(std::string* code);
+  // Checks if the language code's format is valid.
+  static bool IsValidLanguageCode(const std::string& code);
 
   // Applies a series of language code modification in proper order.
   static void ApplyLanguageCodeCorrection(std::string* code);
@@ -123,6 +124,11 @@
   static bool MaybeServerWrongConfiguration(const std::string& page_language,
                                             const std::string& cld_language);
 
+  // Checks if CLD can complement a sub code when the page language doesn't
+  // know the sub code.
+  static bool CanCLDComplementSubCode(const std::string& page_language,
+                                      const std::string& cld_language);
+
   // Determines content page language from Content-Language code and contents.
   static std::string DeterminePageLanguage(const std::string& code,
                                            const std::string& html_lang,
diff --git a/chrome/renderer/translate/translate_helper_browsertest.cc b/chrome/renderer/translate/translate_helper_browsertest.cc
index cfb2f20..aba7610 100644
--- a/chrome/renderer/translate/translate_helper_browsertest.cc
+++ b/chrome/renderer/translate/translate_helper_browsertest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/render_messages.h"
 #include "chrome/renderer/translate/translate_helper.h"
diff --git a/chrome/renderer/translate/translate_helper_metrics.h b/chrome/renderer/translate/translate_helper_metrics.h
index 89d4de5..cd0050f 100644
--- a/chrome/renderer/translate/translate_helper_metrics.h
+++ b/chrome/renderer/translate/translate_helper_metrics.h
@@ -7,7 +7,7 @@
 
 #include <string>
 
-#include "base/time.h"
+#include "base/time/time.h"
 
 namespace TranslateHelperMetrics {
 
@@ -45,6 +45,7 @@
   LANGUAGE_VERIFICATION_CLD_AGREE,
   LANGUAGE_VERIFICATION_CLD_DISAGREE,
   LANGUAGE_VERIFICATION_TRUST_CLD,
+  LANGUAGE_VERIFICATION_CLD_COMPLEMENT_SUB_CODE,
   LANGUAGE_VERIFICATION_MAX,
 };
 
diff --git a/chrome/renderer/translate/translate_helper_metrics_unittest.cc b/chrome/renderer/translate/translate_helper_metrics_unittest.cc
index 0851528..b0d4585 100644
--- a/chrome/renderer/translate/translate_helper_metrics_unittest.cc
+++ b/chrome/renderer/translate/translate_helper_metrics_unittest.cc
@@ -57,7 +57,8 @@
                                  int expected_unknown,
                                  int expected_cld_agree,
                                  int expected_cld_disagree,
-                                 int expected_trust_cld) {
+                                 int expected_trust_cld,
+                                 int expected_cld_complement_sub_code) {
     ASSERT_EQ(TranslateHelperMetrics::GetMetricsName(
         TranslateHelperMetrics::UMA_LANGUAGE_VERIFICATION), key_);
 
@@ -87,6 +88,11 @@
         expected_trust_cld,
         GetCountWithoutSnapshot(
             TranslateHelperMetrics::LANGUAGE_VERIFICATION_TRUST_CLD));
+    EXPECT_EQ(
+        expected_cld_complement_sub_code,
+        GetCountWithoutSnapshot(
+            TranslateHelperMetrics::
+            LANGUAGE_VERIFICATION_CLD_COMPLEMENT_SUB_CODE));
   }
 
   void CheckScheme(int expected_http, int expected_https, int expected_others) {
@@ -194,25 +200,28 @@
   MetricsRecorder recorder(TranslateHelperMetrics::GetMetricsName(
       TranslateHelperMetrics::UMA_LANGUAGE_VERIFICATION));
 
-  recorder.CheckLanguageVerification(0, 0, 0, 0, 0, 0);
+  recorder.CheckLanguageVerification(0, 0, 0, 0, 0, 0, 0);
   TranslateHelperMetrics::ReportLanguageVerification(
       TranslateHelperMetrics::LANGUAGE_VERIFICATION_CLD_DISABLED);
-  recorder.CheckLanguageVerification(1, 0, 0, 0, 0, 0);
+  recorder.CheckLanguageVerification(1, 0, 0, 0, 0, 0, 0);
   TranslateHelperMetrics::ReportLanguageVerification(
       TranslateHelperMetrics::LANGUAGE_VERIFICATION_CLD_ONLY);
-  recorder.CheckLanguageVerification(1, 1, 0, 0, 0, 0);
+  recorder.CheckLanguageVerification(1, 1, 0, 0, 0, 0, 0);
   TranslateHelperMetrics::ReportLanguageVerification(
       TranslateHelperMetrics::LANGUAGE_VERIFICATION_UNKNOWN);
-  recorder.CheckLanguageVerification(1, 1, 1, 0, 0, 0);
+  recorder.CheckLanguageVerification(1, 1, 1, 0, 0, 0, 0);
   TranslateHelperMetrics::ReportLanguageVerification(
       TranslateHelperMetrics::LANGUAGE_VERIFICATION_CLD_AGREE);
-  recorder.CheckLanguageVerification(1, 1, 1, 1, 0, 0);
+  recorder.CheckLanguageVerification(1, 1, 1, 1, 0, 0, 0);
   TranslateHelperMetrics::ReportLanguageVerification(
       TranslateHelperMetrics::LANGUAGE_VERIFICATION_CLD_DISAGREE);
-  recorder.CheckLanguageVerification(1, 1, 1, 1, 1, 0);
+  recorder.CheckLanguageVerification(1, 1, 1, 1, 1, 0, 0);
   TranslateHelperMetrics::ReportLanguageVerification(
       TranslateHelperMetrics::LANGUAGE_VERIFICATION_TRUST_CLD);
-  recorder.CheckLanguageVerification(1, 1, 1, 1, 1, 1);
+  recorder.CheckLanguageVerification(1, 1, 1, 1, 1, 1, 0);
+  TranslateHelperMetrics::ReportLanguageVerification(
+      TranslateHelperMetrics::LANGUAGE_VERIFICATION_CLD_COMPLEMENT_SUB_CODE);
+  recorder.CheckLanguageVerification(1, 1, 1, 1, 1, 1, 1);
 }
 
 TEST(TranslateHelperMetricsTest, ReportTimeToBeReady) {
diff --git a/chrome/renderer/translate/translate_helper_unittest.cc b/chrome/renderer/translate/translate_helper_unittest.cc
index e1024ee..88f3b1f 100644
--- a/chrome/renderer/translate/translate_helper_unittest.cc
+++ b/chrome/renderer/translate/translate_helper_unittest.cc
@@ -30,32 +30,33 @@
   EXPECT_EQ("ja-JP", language);
 }
 
-// Tests that invalid language code is reset to empty string.
-TEST_F(TranslateHelperTest, ResetInvalidLanguageCode) {
+// Tests if the language codes' format is invalid.
+TEST_F(TranslateHelperTest, IsValidLanguageCode) {
   std::string language;
 
   language = std::string("ja");
-  TranslateHelper::ResetInvalidLanguageCode(&language);
-  EXPECT_EQ("ja", language);
+  EXPECT_TRUE(TranslateHelper::IsValidLanguageCode(language));
 
   language = std::string("ja-JP");
-  TranslateHelper::ResetInvalidLanguageCode(&language);
-  EXPECT_EQ("ja-JP", language);
+  EXPECT_TRUE(TranslateHelper::IsValidLanguageCode(language));
 
-  // Invalid because of three characters before hyphen.
+  language = std::string("ceb");
+  EXPECT_TRUE(TranslateHelper::IsValidLanguageCode(language));
+
+  language = std::string("ceb-XX");
+  EXPECT_TRUE(TranslateHelper::IsValidLanguageCode(language));
+
+  // Invalid because the sub code consists of a number.
   language = std::string("utf-8");
-  TranslateHelper::ResetInvalidLanguageCode(&language);
-  EXPECT_TRUE(language.empty());
+  EXPECT_FALSE(TranslateHelper::IsValidLanguageCode(language));
 
   // Invalid because of six characters after hyphen.
   language = std::string("ja-YUKARI");
-  TranslateHelper::ResetInvalidLanguageCode(&language);
-  EXPECT_TRUE(language.empty());
+  EXPECT_FALSE(TranslateHelper::IsValidLanguageCode(language));
 
-  // Invalid because of three characters.
-  language = std::string("YMO");
-  TranslateHelper::ResetInvalidLanguageCode(&language);
-  EXPECT_TRUE(language.empty());
+  // Invalid because of four characters.
+  language = std::string("DHMO");
+  EXPECT_FALSE(TranslateHelper::IsValidLanguageCode(language));
 }
 
 // Tests that similar language table works.
diff --git a/chrome/service/chrome_service_application_mac.mm b/chrome/service/chrome_service_application_mac.mm
index c60fa06..3b78059 100644
--- a/chrome/service/chrome_service_application_mac.mm
+++ b/chrome/service/chrome_service_application_mac.mm
@@ -21,16 +21,16 @@
 + (void)submitPrint:(NSAppleEventDescriptor*)event {
   std::string silent = std::string("--") + switches::kNoStartupWindow;
   // Set up flag so that it can be passed along with the Apple Event.
-  base::mac::ScopedCFTypeRef<CFStringRef> silentLaunchFlag(
+  base::ScopedCFTypeRef<CFStringRef> silentLaunchFlag(
       base::SysUTF8ToCFStringRef(silent));
   CFStringRef flags[] = { silentLaunchFlag };
   // Argv array that will be passed.
-  base::mac::ScopedCFTypeRef<CFArrayRef> passArgv(
-      CFArrayCreate(NULL, (const void**) flags, 1, &kCFTypeArrayCallBacks));
+  base::ScopedCFTypeRef<CFArrayRef> passArgv(
+      CFArrayCreate(NULL, (const void**)flags, 1, &kCFTypeArrayCallBacks));
   FSRef ref;
   // Get Chrome's bundle ID.
   std::string bundleID = base::mac::BaseBundleID();
-  base::mac::ScopedCFTypeRef<CFStringRef> bundleIDCF(
+  base::ScopedCFTypeRef<CFStringRef> bundleIDCF(
       base::SysUTF8ToCFStringRef(bundleID));
   // Use Launch Services to locate Chrome using its bundleID.
   OSStatus status = LSFindApplicationForInfo(kLSUnknownCreator, bundleIDCF,
diff --git a/chrome/service/cloud_print/cloud_print_auth.cc b/chrome/service/cloud_print/cloud_print_auth.cc
index 3505a91..5abfb99 100644
--- a/chrome/service/cloud_print/cloud_print_auth.cc
+++ b/chrome/service/cloud_print/cloud_print_auth.cc
@@ -9,7 +9,6 @@
 #include "chrome/common/cloud_print/cloud_print_constants.h"
 #include "chrome/common/cloud_print/cloud_print_helpers.h"
 #include "chrome/service/cloud_print/cloud_print_token_store.h"
-#include "chrome/service/gaia/service_gaia_authenticator.h"
 #include "chrome/service/net/service_url_request_context.h"
 #include "chrome/service/service_process.h"
 #include "google_apis/gaia/gaia_urls.h"
@@ -28,39 +27,6 @@
   DCHECK(client);
 }
 
-void CloudPrintAuth::AuthenticateWithLsid(
-    const std::string& lsid,
-    const std::string& last_robot_refresh_token,
-    const std::string& last_robot_email,
-    const std::string& last_user_email) {
-  // Keeping VLOGs for Cloud Print proxy logging. It is convinient for finding
-  // issues with GCP in the field, where only release version is avaialble.
-  VLOG(1) << "CP_AUTH: Authenticating with LSID";
-  scoped_refptr<ServiceGaiaAuthenticator> gaia_auth_for_print(
-      new ServiceGaiaAuthenticator(
-          kProxyAuthUserAgent,
-          kCloudPrintGaiaServiceId,
-          GaiaUrls::GetInstance()->client_login_url(),
-          g_service_process->io_thread()->message_loop_proxy().get()));
-  gaia_auth_for_print->set_message_loop(base::MessageLoop::current());
-  if (gaia_auth_for_print->AuthenticateWithLsid(lsid)) {
-    // Stash away the user email so we can save it in prefs.
-    user_email_ = gaia_auth_for_print->email();
-    // If the same user is re-enabling Cloud Print and we have stashed robot
-    // credentials, we will use those.
-    if ((0 == base::strcasecmp(user_email_.c_str(), last_user_email.c_str())) &&
-        !last_robot_refresh_token.empty() &&
-        !last_robot_email.empty()) {
-      AuthenticateWithRobotToken(last_robot_refresh_token,
-                                 last_robot_email);
-    }
-    AuthenticateWithToken(gaia_auth_for_print->auth_token());
-  } else {
-    // Notify client about authentication error.
-    client_->OnInvalidCredentials();
-  }
-}
-
 void CloudPrintAuth::AuthenticateWithToken(
     const std::string& cloud_print_token) {
   VLOG(1) << "CP_AUTH: Authenticating with token";
@@ -96,7 +62,6 @@
   robot_email_ = robot_email;
   // Now that we have an auth code we need to get the refresh and access tokens.
   oauth_client_.reset(new gaia::GaiaOAuthClient(
-      GaiaUrls::GetInstance()->oauth2_token_url(),
       g_service_process->GetServiceURLRequestContextGetter()));
   oauth_client_->GetTokensFromAuthCode(oauth_client_info_,
                                        robot_oauth_auth_code,
@@ -106,10 +71,11 @@
 
 void CloudPrintAuth::RefreshAccessToken() {
   oauth_client_.reset(new gaia::GaiaOAuthClient(
-      GaiaUrls::GetInstance()->oauth2_token_url(),
       g_service_process->GetServiceURLRequestContextGetter()));
+  std::vector<std::string> empty_scope_list;  // (Use scope from refresh token.)
   oauth_client_->RefreshToken(oauth_client_info_,
                               refresh_token_,
+                              empty_scope_list,
                               kCloudPrintAuthMaxRetryCount,
                               this);
 }
@@ -173,7 +139,6 @@
   json_data->GetString(kXMPPJidValue, &robot_email_);
   // Now that we have an auth code we need to get the refresh and access tokens.
   oauth_client_.reset(new gaia::GaiaOAuthClient(
-      GaiaUrls::GetInstance()->oauth2_token_url(),
       g_service_process->GetServiceURLRequestContextGetter()));
   oauth_client_->GetTokensFromAuthCode(oauth_client_info_,
                                        auth_code,
diff --git a/chrome/service/cloud_print/cloud_print_auth.h b/chrome/service/cloud_print/cloud_print_auth.h
index 1107694..d4c4755 100644
--- a/chrome/service/cloud_print/cloud_print_auth.h
+++ b/chrome/service/cloud_print/cloud_print_auth.h
@@ -47,14 +47,6 @@
   // The Authenticate* methods are the various entry points from
   // CloudPrintProxyBackend::Core. It calls us on a dedicated thread to
   // actually perform synchronous (and potentially blocking) operations.
-  //
-  // When we are passed in an LSID we authenticate using that
-  // and retrieve new auth tokens.
-  void AuthenticateWithLsid(const std::string& lsid,
-                            const std::string& last_robot_refresh_token,
-                            const std::string& last_robot_email,
-                            const std::string& last_user_email);
-
   void AuthenticateWithToken(const std::string& cloud_print_token);
   void AuthenticateWithRobotToken(const std::string& robot_oauth_refresh_token,
                                   const std::string& robot_email);
diff --git a/chrome/service/cloud_print/cloud_print_proxy.cc b/chrome/service/cloud_print/cloud_print_proxy.cc
index c3df3c1..c460a1a 100644
--- a/chrome/service/cloud_print/cloud_print_proxy.cc
+++ b/chrome/service/cloud_print/cloud_print_proxy.cc
@@ -78,7 +78,7 @@
   client_ = client;
 }
 
-void CloudPrintProxy::EnableForUser(const std::string& lsid) {
+void CloudPrintProxy::EnableForUser() {
   DCHECK(CalledOnValidThread());
   if (!CreateBackend())
     return;
@@ -91,23 +91,16 @@
       service_prefs_->GetString(prefs::kCloudPrintRobotEmail, std::string());
   user_email_ = service_prefs_->GetString(prefs::kCloudPrintEmail, user_email_);
 
-  // If we have been passed in an LSID, we want to use this to authenticate.
-  // Else we will try and retrieve the last used auth tokens from prefs.
-  if (!lsid.empty()) {
-    backend_->InitializeWithLsid(lsid, robot_refresh_token, robot_email,
-                                 user_email_);
+  // See if we have persisted robot credentials.
+  if (!robot_refresh_token.empty()) {
+    DCHECK(!robot_email.empty());
+    backend_->InitializeWithRobotToken(robot_refresh_token, robot_email);
   } else {
-    // See if we have persisted robot credentials.
-    if (!robot_refresh_token.empty()) {
-      DCHECK(!robot_email.empty());
-      backend_->InitializeWithRobotToken(robot_refresh_token, robot_email);
-    } else {
-      // Finally see if we have persisted user credentials (legacy case).
-      std::string cloud_print_token =
-          service_prefs_->GetString(prefs::kCloudPrintAuthToken, std::string());
-      DCHECK(!cloud_print_token.empty());
-      backend_->InitializeWithToken(cloud_print_token);
-    }
+    // Finally see if we have persisted user credentials (legacy case).
+    std::string cloud_print_token =
+        service_prefs_->GetString(prefs::kCloudPrintAuthToken, std::string());
+    DCHECK(!cloud_print_token.empty());
+    backend_->InitializeWithToken(cloud_print_token);
   }
   if (client_) {
     client_->OnCloudPrintProxyEnabled(true);
diff --git a/chrome/service/cloud_print/cloud_print_proxy.h b/chrome/service/cloud_print/cloud_print_proxy.h
index 9765add..507eb9e 100644
--- a/chrome/service/cloud_print/cloud_print_proxy.h
+++ b/chrome/service/cloud_print/cloud_print_proxy.h
@@ -41,7 +41,7 @@
   void Initialize(ServiceProcessPrefs* service_prefs, Client* client);
 
   // Enables/disables cloud printing for the user
-  void EnableForUser(const std::string& lsid);
+  void EnableForUser();
   void EnableForUserWithRobot(
       const std::string& robot_auth_code,
       const std::string& robot_email,
diff --git a/chrome/service/cloud_print/cloud_print_proxy_backend.cc b/chrome/service/cloud_print/cloud_print_proxy_backend.cc
index 84084f4..d8eb42e 100644
--- a/chrome/service/cloud_print/cloud_print_proxy_backend.cc
+++ b/chrome/service/cloud_print/cloud_print_proxy_backend.cc
@@ -19,7 +19,6 @@
 #include "chrome/service/cloud_print/cloud_print_helpers.h"
 #include "chrome/service/cloud_print/cloud_print_token_store.h"
 #include "chrome/service/cloud_print/connector_settings.h"
-#include "chrome/service/gaia/service_gaia_authenticator.h"
 #include "chrome/service/net/service_url_request_context.h"
 #include "chrome/service/service_process.h"
 #include "google_apis/gaia/gaia_oauth_client.h"
@@ -52,15 +51,6 @@
   // The Do* methods are the various entry points from CloudPrintProxyBackend
   // It calls us on a dedicated thread to actually perform synchronous
   // (and potentially blocking) operations.
-  //
-  // Called on the CloudPrintProxyBackend core_thread_ to perform
-  // initialization. When we are passed in an LSID we authenticate using that
-  // and retrieve new auth tokens.
-  void DoInitializeWithLsid(const std::string& lsid,
-                            const std::string& last_robot_refresh_token,
-                            const std::string& last_robot_email,
-                            const std::string& last_user_email);
-
   void DoInitializeWithToken(const std::string& cloud_print_token);
   void DoInitializeWithRobotToken(const std::string& robot_oauth_refresh_token,
                                   const std::string& robot_email);
@@ -177,21 +167,6 @@
 
 CloudPrintProxyBackend::~CloudPrintProxyBackend() { DCHECK(!core_.get()); }
 
-bool CloudPrintProxyBackend::InitializeWithLsid(
-    const std::string& lsid,
-    const std::string& last_robot_refresh_token,
-    const std::string& last_robot_email,
-    const std::string& last_user_email) {
-  if (!core_thread_.Start())
-    return false;
-  core_thread_.message_loop()->PostTask(
-      FROM_HERE,
-      base::Bind(&CloudPrintProxyBackend::Core::DoInitializeWithLsid,
-                 core_.get(), lsid, last_robot_refresh_token, last_robot_email,
-                 last_user_email));
-  return true;
-}
-
 bool CloudPrintProxyBackend::InitializeWithToken(
     const std::string& cloud_print_token) {
   if (!core_thread_.Start())
@@ -273,20 +248,6 @@
   connector_ = NULL;
 }
 
-void CloudPrintProxyBackend::Core::DoInitializeWithLsid(
-    const std::string& lsid,
-    const std::string& last_robot_refresh_token,
-    const std::string& last_robot_email,
-    const std::string& last_user_email) {
-  DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop());
-  CreateAuthAndConnector();
-  // Note: The GAIA login is synchronous but that should be OK because we are in
-  // the CloudPrintProxyCoreThread and we cannot really do anything else until
-  // the GAIA signin is successful.
-  auth_->AuthenticateWithLsid(lsid, last_robot_refresh_token,
-                              last_robot_email, last_user_email);
-}
-
 void CloudPrintProxyBackend::Core::DoInitializeWithToken(
     const std::string& cloud_print_token) {
   DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop());
diff --git a/chrome/service/cloud_print/cloud_print_proxy_backend.h b/chrome/service/cloud_print/cloud_print_proxy_backend.h
index 9c7e715..403ea18 100644
--- a/chrome/service/cloud_print/cloud_print_proxy_backend.h
+++ b/chrome/service/cloud_print/cloud_print_proxy_backend.h
@@ -63,14 +63,6 @@
                          bool enable_job_poll);
   ~CloudPrintProxyBackend();
 
-  // Called when the user enables Google Cloud Print.
-  // |last_robot_refresh_token|, |last_robot_email| and |last_user_email| are
-  // the previously persisted credentials if any. We will use this is the passed
-  // in LSID belongs to the same user as |last_user_email|.
-  bool InitializeWithLsid(const std::string& lsid,
-                          const std::string& last_robot_refresh_token,
-                          const std::string& last_robot_email,
-                          const std::string& last_user_email);
   // Legacy mechanism when we have saved user credentials but no saved robot
   // credentials.
   bool InitializeWithToken(const std::string& cloud_print_token);
diff --git a/chrome/service/cloud_print/connector_settings_unittest.cc b/chrome/service/cloud_print/connector_settings_unittest.cc
index 7616e63..8dcf59b 100644
--- a/chrome/service/cloud_print/connector_settings_unittest.cc
+++ b/chrome/service/cloud_print/connector_settings_unittest.cc
@@ -56,7 +56,7 @@
 
   ServiceProcessPrefs* CreateTestFile(const char* json) {
     base::FilePath file_name = temp_dir_.path().AppendASCII("file.txt");
-    file_util::Delete(file_name, false);
+    base::Delete(file_name, false);
     if (json) {
       std::string content = json;
       std::replace(content.begin(), content.end(), '\'', '"');
diff --git a/chrome/service/cloud_print/printer_job_handler.h b/chrome/service/cloud_print/printer_job_handler.h
index 6326615..3b96507 100644
--- a/chrome/service/cloud_print/printer_job_handler.h
+++ b/chrome/service/cloud_print/printer_job_handler.h
@@ -14,7 +14,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/message_loop/message_loop_proxy.h"
 #include "base/threading/thread.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/service/cloud_print/cloud_print_url_fetcher.h"
 #include "chrome/service/cloud_print/job_status_updater.h"
 #include "chrome/service/cloud_print/printer_job_queue_handler.h"
diff --git a/chrome/service/cloud_print/printer_job_handler_unittest.cc b/chrome/service/cloud_print/printer_job_handler_unittest.cc
index 854e7aa..3efe21c 100644
--- a/chrome/service/cloud_print/printer_job_handler_unittest.cc
+++ b/chrome/service/cloud_print/printer_job_handler_unittest.cc
@@ -635,14 +635,13 @@
     : job_spooler_(new NiceMock<MockJobSpooler>()),
       printer_watcher_(new NiceMock<MockPrinterWatcher>()),
       print_server_watcher_(new NiceMock<MockPrintServerWatcher>()) {
-  ON_CALL(*this, CreateJobSpooler())
-      .WillByDefault(Return(job_spooler_));
+  ON_CALL(*this, CreateJobSpooler()).WillByDefault(Return(job_spooler_.get()));
 
   ON_CALL(*this, CreatePrinterWatcher(_))
-      .WillByDefault(Return(printer_watcher_));
+      .WillByDefault(Return(printer_watcher_.get()));
 
   ON_CALL(*this, CreatePrintServerWatcher())
-      .WillByDefault(Return(print_server_watcher_));
+      .WillByDefault(Return(print_server_watcher_.get()));
 
   ON_CALL(*this, IsValidPrinter(_)).
       WillByDefault(Return(true));
diff --git a/chrome/service/cloud_print/printer_job_queue_handler.h b/chrome/service/cloud_print/printer_job_queue_handler.h
index 0351d2a..27d2764 100644
--- a/chrome/service/cloud_print/printer_job_queue_handler.h
+++ b/chrome/service/cloud_print/printer_job_queue_handler.h
@@ -14,7 +14,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/common/cloud_print/cloud_print_constants.h"
 
 namespace base {
diff --git a/chrome/service/gaia/service_gaia_authenticator.cc b/chrome/service/gaia/service_gaia_authenticator.cc
deleted file mode 100644
index e46cbc7..0000000
--- a/chrome/service/gaia/service_gaia_authenticator.cc
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/service/gaia/service_gaia_authenticator.h"
-
-#include "base/bind.h"
-#include "base/message_loop/message_loop_proxy.h"
-#include "chrome/service/net/service_url_request_context.h"
-#include "chrome/service/service_process.h"
-#include "googleurl/src/gurl.h"
-#include "net/url_request/url_fetcher.h"
-
-ServiceGaiaAuthenticator::ServiceGaiaAuthenticator(
-    const std::string& user_agent, const std::string& service_id,
-    const std::string& gaia_url,
-    base::MessageLoopProxy* io_message_loop_proxy)
-        : gaia::GaiaAuthenticator(user_agent, service_id, gaia_url),
-          http_post_completed_(false, false),
-          io_message_loop_proxy_(io_message_loop_proxy),
-          http_response_code_(0) {
-}
-
-// net::URLFetcherDelegate implementation
-void ServiceGaiaAuthenticator::OnURLFetchComplete(
-    const net::URLFetcher* source) {
-  DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
-  http_response_code_ = source->GetResponseCode();
-  source->GetResponseAsString(&response_data_);
-  delete source;
-  // Add an extra reference because we want http_post_completed_ to remain
-  // valid until after Signal() returns.
-  scoped_refptr<ServiceGaiaAuthenticator> keep_alive(this);
-  // Wake the blocked thread in Post.
-  http_post_completed_.Signal();
-  // WARNING: DONT DO ANYTHING AFTER THIS CALL! |this| may be deleted!
-}
-
-bool ServiceGaiaAuthenticator::Post(const GURL& url,
-                                    const std::string& post_body,
-                                    unsigned long* response_code,
-                                    std::string* response_body) {
-  DCHECK(url.SchemeIsSecure());
-  DCHECK(io_message_loop_proxy_.get());
-  io_message_loop_proxy_->PostTask(
-      FROM_HERE,
-      base::Bind(&ServiceGaiaAuthenticator::DoPost, this, url, post_body));
-  // TODO(sanjeevr): Waiting here until the network request completes is not
-  // desirable. We need to change Post to be asynchronous.
-  // Block until network request completes. See OnURLFetchComplete.
-  http_post_completed_.Wait();
-
-  *response_code = static_cast<int>(http_response_code_);
-  *response_body = response_data_;
-  return true;
-}
-
-// TODO(sanjeevr): This is a placeholder implementation. Need to move this logic
-// to a common location within the service process so that it can be resued by
-// other classes needing a backoff delay calculation.
-int ServiceGaiaAuthenticator::GetBackoffDelaySeconds(
-    int current_backoff_delay) {
-  const int kMaxBackoffDelaySeconds = 60 * 60;  // (1 hour)
-  int ret = 0;
-  if (0 == current_backoff_delay) {
-    ret = 1;
-  } else {
-    ret = current_backoff_delay * 2;
-  }
-  if (ret > kMaxBackoffDelaySeconds) {
-    ret = kMaxBackoffDelaySeconds;
-  }
-  return ret;
-}
-
-ServiceGaiaAuthenticator::~ServiceGaiaAuthenticator() {}
-
-void ServiceGaiaAuthenticator::DoPost(const GURL& post_url,
-                                      const std::string& post_body) {
-  DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
-  net::URLFetcher* request = net::URLFetcher::Create(
-      post_url, net::URLFetcher::POST, this);
-  request->SetRequestContext(
-      g_service_process->GetServiceURLRequestContextGetter());
-  request->SetUploadData("application/x-www-form-urlencoded", post_body);
-  request->Start();
-}
diff --git a/chrome/service/gaia/service_gaia_authenticator.h b/chrome/service/gaia/service_gaia_authenticator.h
deleted file mode 100644
index ffde6d3..0000000
--- a/chrome/service/gaia/service_gaia_authenticator.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_SERVICE_GAIA_SERVICE_GAIA_AUTHENTICATOR_H_
-#define CHROME_SERVICE_GAIA_SERVICE_GAIA_AUTHENTICATOR_H_
-
-#include <string>
-
-#include "base/compiler_specific.h"
-#include "base/memory/ref_counted.h"
-#include "base/synchronization/waitable_event.h"
-#include "google_apis/gaia/gaia_authenticator.h"
-#include "net/url_request/url_fetcher_delegate.h"
-
-namespace base {
-class MessageLoopProxy;
-}
-
-// A GaiaAuthenticator implementation to be used in the service process (where
-// we cannot rely on the existence of a Profile)
-class ServiceGaiaAuthenticator
-    : public base::RefCountedThreadSafe<ServiceGaiaAuthenticator>,
-      public net::URLFetcherDelegate,
-      public gaia::GaiaAuthenticator {
- public:
-  ServiceGaiaAuthenticator(const std::string& user_agent,
-                           const std::string& service_id,
-                           const std::string& gaia_url,
-                           base::MessageLoopProxy* io_message_loop_proxy);
-
-  // net::URLFetcherDelegate implementation.
-  virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
-
- protected:
-  // GaiaAuthenticator overrides.
-  virtual bool Post(const GURL& url,
-                    const std::string& post_body,
-                    unsigned long* response_code,
-                    std::string* response_body) OVERRIDE;
-  virtual int GetBackoffDelaySeconds(int current_backoff_delay) OVERRIDE;
-
- private:
-  friend class base::RefCountedThreadSafe<ServiceGaiaAuthenticator>;
-  virtual ~ServiceGaiaAuthenticator();
-
-  void DoPost(const GURL& post_url, const std::string& post_body);
-
-  base::WaitableEvent http_post_completed_;
-  scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_;
-  int http_response_code_;
-  std::string response_data_;
-
-  DISALLOW_COPY_AND_ASSIGN(ServiceGaiaAuthenticator);
-};
-
-#endif  // CHROME_SERVICE_GAIA_SERVICE_GAIA_AUTHENTICATOR_H_
diff --git a/chrome/service/service_ipc_server.cc b/chrome/service/service_ipc_server.cc
index c1f7e21..f05bf4b 100644
--- a/chrome/service/service_ipc_server.cc
+++ b/chrome/service/service_ipc_server.cc
@@ -92,8 +92,6 @@
   // again on subsequent connections.
   client_connected_ = true;
   IPC_BEGIN_MESSAGE_MAP(ServiceIPCServer, msg)
-    IPC_MESSAGE_HANDLER(ServiceMsg_EnableCloudPrintProxy,
-                        OnEnableCloudPrintProxy)
     IPC_MESSAGE_HANDLER(ServiceMsg_EnableCloudPrintProxyWithRobot,
                         OnEnableCloudPrintProxyWithRobot)
     IPC_MESSAGE_HANDLER(ServiceMsg_DisableCloudPrintProxy,
@@ -107,10 +105,6 @@
   return handled;
 }
 
-void ServiceIPCServer::OnEnableCloudPrintProxy(const std::string& lsid) {
-  g_service_process->GetCloudPrintProxy()->EnableForUser(lsid);
-}
-
 void ServiceIPCServer::OnEnableCloudPrintProxyWithRobot(
     const std::string& robot_auth_code,
     const std::string& robot_email,
diff --git a/chrome/service/service_ipc_server.h b/chrome/service/service_ipc_server.h
index 52a6432..28fe4b4 100644
--- a/chrome/service/service_ipc_server.h
+++ b/chrome/service/service_ipc_server.h
@@ -52,7 +52,6 @@
   virtual void OnChannelError() OVERRIDE;
 
   // IPC message handlers.
-  void OnEnableCloudPrintProxy(const std::string& lsid);
   void OnEnableCloudPrintProxyWithRobot(
       const std::string& robot_auth_code,
       const std::string& robot_email,
diff --git a/chrome/service/service_process.cc b/chrome/service/service_process.cc
index af04fbd..5e7acb1 100644
--- a/chrome/service/service_process.cc
+++ b/chrome/service/service_process.cc
@@ -193,7 +193,7 @@
   // Then check if the cloud print proxy was previously enabled.
   if (command_line.HasSwitch(switches::kEnableCloudPrintProxy) ||
       service_prefs_->GetBoolean(prefs::kCloudPrintProxyEnabled, false)) {
-    GetCloudPrintProxy()->EnableForUser(std::string());
+    GetCloudPrintProxy()->EnableForUser();
   }
 
   VLOG(1) << "Starting Service Process IPC Server";
diff --git a/chrome/test/DEPS b/chrome/test/DEPS
index d0c3c0f..8c88f2b 100644
--- a/chrome/test/DEPS
+++ b/chrome/test/DEPS
@@ -20,4 +20,5 @@
   "+sandbox/win/tests",
   "+webkit/glue",
   "+webkit/plugins",
+  "+win8/test",
 ]
diff --git a/chrome/test/automation/automation_json_requests.cc b/chrome/test/automation/automation_json_requests.cc
index 1bc7106..28d24af 100644
--- a/chrome/test/automation/automation_json_requests.cc
+++ b/chrome/test/automation/automation_json_requests.cc
@@ -13,7 +13,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/stringprintf.h"
 #include "base/test/test_timeouts.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/common/automation_messages.h"
 #include "chrome/test/automation/automation_proxy.h"
diff --git a/chrome/test/automation/automation_proxy.h b/chrome/test/automation/automation_proxy.h
index 3dfb7f1..8abfbfd 100644
--- a/chrome/test/automation/automation_proxy.h
+++ b/chrome/test/automation/automation_proxy.h
@@ -15,7 +15,7 @@
 #include "base/synchronization/waitable_event.h"
 #include "base/threading/platform_thread.h"
 #include "base/threading/thread.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/common/automation_constants.h"
 #include "chrome/test/automation/automation_handle_tracker.h"
diff --git a/chrome/test/automation/browser_proxy.cc b/chrome/test/automation/browser_proxy.cc
index eade432..bf1ad34 100644
--- a/chrome/test/automation/browser_proxy.cc
+++ b/chrome/test/automation/browser_proxy.cc
@@ -9,7 +9,7 @@
 #include "base/json/json_reader.h"
 #include "base/logging.h"
 #include "base/threading/platform_thread.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/common/automation_constants.h"
 #include "chrome/common/automation_messages.h"
 #include "chrome/test/automation/automation_proxy.h"
diff --git a/chrome/test/automation/proxy_launcher.cc b/chrome/test/automation/proxy_launcher.cc
index 2a81cef..4b40cc1 100644
--- a/chrome/test/automation/proxy_launcher.cc
+++ b/chrome/test/automation/proxy_launcher.cc
@@ -559,7 +559,7 @@
 #if defined(OS_POSIX)
     // Because we are waiting on the existence of the testing file below,
     // make sure there isn't one already there before browser launch.
-    if (!file_util::Delete(base::FilePath(channel_id_), false)) {
+    if (!base::Delete(base::FilePath(channel_id_), false)) {
       LOG(ERROR) << "Failed to delete " << channel_id_;
       return false;
     }
diff --git a/chrome/test/automation/proxy_launcher.h b/chrome/test/automation/proxy_launcher.h
index 9ad091f..d638461 100644
--- a/chrome/test/automation/proxy_launcher.h
+++ b/chrome/test/automation/proxy_launcher.h
@@ -14,7 +14,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/process.h"
-#include "base/time.h"
+#include "base/time/time.h"
 
 class AutomationProxy;
 
diff --git a/chrome/test/base/chrome_process_util.cc b/chrome/test/base/chrome_process_util.cc
index 09ab2c8..26097a6 100644
--- a/chrome/test/base/chrome_process_util.cc
+++ b/chrome/test/base/chrome_process_util.cc
@@ -10,7 +10,7 @@
 
 #include "base/command_line.h"
 #include "base/process_util.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/test/base/test_switches.h"
 #include "content/public/common/result_codes.h"
@@ -18,6 +18,47 @@
 using base::TimeDelta;
 using base::TimeTicks;
 
+namespace {
+
+// Returns the executable name of the current Chrome browser process.
+const base::FilePath::CharType* GetRunningBrowserExecutableName() {
+  const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
+  if (cmd_line->HasSwitch(switches::kEnableChromiumBranding))
+    return chrome::kBrowserProcessExecutableNameChromium;
+  return chrome::kBrowserProcessExecutableName;
+}
+
+// Returns the executable name of the current Chrome helper process.
+std::vector<base::FilePath::StringType> GetRunningHelperExecutableNames() {
+  base::FilePath::StringType name;
+  const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
+  if (cmd_line->HasSwitch(switches::kEnableChromiumBranding)) {
+    name = chrome::kHelperProcessExecutableNameChromium;
+  } else {
+    name = chrome::kHelperProcessExecutableName;
+  }
+
+  std::vector<base::FilePath::StringType> names;
+  names.push_back(name);
+
+#if defined(OS_MACOSX)
+  // The helper might show up as these different flavors depending on the
+  // executable flags required.
+  for (const char* const* suffix = chrome::kHelperFlavorSuffixes;
+       *suffix;
+       ++suffix) {
+    std::string flavor_name(name);
+    flavor_name.append(1, ' ');
+    flavor_name.append(*suffix);
+    names.push_back(flavor_name);
+  }
+#endif
+
+  return names;
+}
+
+}  // namespace
+
 void TerminateAllChromeProcesses(const ChromeProcessList& process_pids) {
   ChromeProcessList::const_iterator it;
   for (it = process_pids.begin(); it != process_pids.end(); ++it) {
@@ -51,41 +92,6 @@
   DISALLOW_COPY_AND_ASSIGN(ChildProcessFilter);
 };
 
-const base::FilePath::CharType* GetRunningBrowserExecutableName() {
-  const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
-  if (cmd_line->HasSwitch(switches::kEnableChromiumBranding))
-    return chrome::kBrowserProcessExecutableNameChromium;
-  return chrome::kBrowserProcessExecutableName;
-}
-
-std::vector<base::FilePath::StringType> GetRunningHelperExecutableNames() {
-  base::FilePath::StringType name;
-  const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
-  if (cmd_line->HasSwitch(switches::kEnableChromiumBranding)) {
-    name = chrome::kHelperProcessExecutableNameChromium;
-  } else {
-    name = chrome::kHelperProcessExecutableName;
-  }
-
-  std::vector<base::FilePath::StringType> names;
-  names.push_back(name);
-
-#if defined(OS_MACOSX)
-  // The helper might show up as these different flavors depending on the
-  // executable flags required.
-  for (const char* const* suffix = chrome::kHelperFlavorSuffixes;
-       *suffix;
-       ++suffix) {
-    std::string flavor_name(name);
-    flavor_name.append(1, ' ');
-    flavor_name.append(*suffix);
-    names.push_back(flavor_name);
-  }
-#endif
-
-  return names;
-}
-
 ChromeProcessList GetRunningChromeProcesses(base::ProcessId browser_pid) {
   const base::FilePath::CharType* executable_name =
       GetRunningBrowserExecutableName();
diff --git a/chrome/test/base/chrome_process_util.h b/chrome/test/base/chrome_process_util.h
index aaad5c1..a3f558a 100644
--- a/chrome/test/base/chrome_process_util.h
+++ b/chrome/test/base/chrome_process_util.h
@@ -12,12 +12,6 @@
 
 typedef std::vector<base::ProcessId> ChromeProcessList;
 
-// Returns the executable name of the current Chrome browser process.
-const base::FilePath::CharType* GetRunningBrowserExecutableName();
-
-// Returns the executable name of the current Chrome helper process.
-const base::FilePath::CharType* GetRunningHelperExecutableName();
-
 // Returns a vector of PIDs of all chrome processes (main and renderers etc)
 // based on |browser_pid|, the PID of the main browser process.
 ChromeProcessList GetRunningChromeProcesses(base::ProcessId browser_pid);
diff --git a/chrome/test/base/chrome_test_launcher.cc b/chrome/test/base/chrome_test_launcher.cc
index d1a25e0..deae8ba 100644
--- a/chrome/test/base/chrome_test_launcher.cc
+++ b/chrome/test/base/chrome_test_launcher.cc
@@ -47,17 +47,11 @@
 #include "ash/test/ui_controls_factory_ash.h"
 #endif
 
-const char kEmptyTestName[] = "InProcessBrowserTest.Empty";
-
 class ChromeTestLauncherDelegate : public content::TestLauncherDelegate {
  public:
   ChromeTestLauncherDelegate() {}
   virtual ~ChromeTestLauncherDelegate() {}
 
-  virtual std::string GetEmptyTestName() OVERRIDE {
-    return kEmptyTestName;
-  }
-
   virtual int RunTestSuite(int argc, char** argv) OVERRIDE {
     return ChromeTestSuite(argc, argv).Run();
   }
diff --git a/chrome/test/base/chrome_test_suite.cc b/chrome/test/base/chrome_test_suite.cc
index d9fac00..bb25ee3 100644
--- a/chrome/test/base/chrome_test_suite.cc
+++ b/chrome/test/base/chrome_test_suite.cc
@@ -152,8 +152,10 @@
 
   virtual void OnTestEnd(const testing::TestInfo& test_info) OVERRIDE {
     if (g_browser_process) {
-      delete g_browser_process;
+      BrowserProcess* browser_process = g_browser_process;
+      // g_browser_process must be NULL during its own destruction.
       g_browser_process = NULL;
+      delete browser_process;
     }
 
     // TODO(ios): Bring this back once ChromeContentBrowserClient is building.
diff --git a/chrome/test/base/empty_browser_test.cc b/chrome/test/base/empty_browser_test.cc
deleted file mode 100644
index 15ab7d4..0000000
--- a/chrome/test/base/empty_browser_test.cc
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/test/base/in_process_browser_test.h"
-
-// An empty test (it starts up and shuts down the browser as part of its
-// setup and teardown) used to prefetch all of the browser code into memory.
-IN_PROC_BROWSER_TEST_F(InProcessBrowserTest, Empty) {
-}
diff --git a/chrome/test/base/in_process_browser_test.cc b/chrome/test/base/in_process_browser_test.cc
index 5cdbf8f..46cd611 100644
--- a/chrome/test/base/in_process_browser_test.cc
+++ b/chrome/test/base/in_process_browser_test.cc
@@ -5,6 +5,7 @@
 #include "chrome/test/base/in_process_browser_test.h"
 
 #include "base/auto_reset.h"
+#include "base/basictypes.h"
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/file_util.h"
@@ -13,6 +14,7 @@
 #include "base/path_service.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/test/test_file_util.h"
+#include "base/threading/non_thread_safe.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/google/google_util.h"
 #include "chrome/browser/io_thread.h"
@@ -23,6 +25,7 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/browser_list_observer.h"
 #include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/browser_window.h"
@@ -36,6 +39,7 @@
 #include "chrome/renderer/chrome_content_renderer_client.h"
 #include "chrome/test/base/chrome_test_suite.h"
 #include "chrome/test/base/test_launcher_utils.h"
+#include "chrome/test/base/test_switches.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/notification_service.h"
@@ -45,6 +49,7 @@
 #include "content/public/test/test_launcher.h"
 #include "content/public/test/test_navigation_observer.h"
 #include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
 #include "net/test/spawned_test_server/spawned_test_server.h"
 #include "ui/compositor/compositor_switches.h"
 
@@ -54,6 +59,15 @@
 #include "base/mac/scoped_nsautorelease_pool.h"
 #endif
 
+#if defined(OS_WIN) && defined(USE_AURA)
+#include "base/win/scoped_com_initializer.h"
+#include "base/win/windows_version.h"
+#include "ui/base/win/atl_module.h"
+#include "ui/compositor/compositor_setup.h"
+#include "win8/test/metro_registration_helper.h"
+#include "win8/test/test_registrar_constants.h"
+#endif
+
 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
 #include "chrome/browser/captive_portal/captive_portal_service.h"
 #endif
@@ -67,11 +81,44 @@
 base::LazyInstance<chrome::ChromeContentRendererClient>::Leaky
     g_chrome_content_renderer_client = LAZY_INSTANCE_INITIALIZER;
 
+// A BrowserListObserver that makes sure that all browsers created are on the
+// |allowed_desktop_|.
+class SingleDesktopTestObserver : public chrome::BrowserListObserver,
+                                  public base::NonThreadSafe {
+ public:
+  explicit SingleDesktopTestObserver(chrome::HostDesktopType allowed_desktop);
+  virtual ~SingleDesktopTestObserver();
+
+  // chrome::BrowserListObserver:
+  virtual void OnBrowserAdded(Browser* browser) OVERRIDE;
+
+ private:
+  chrome::HostDesktopType allowed_desktop_;
+
+  DISALLOW_COPY_AND_ASSIGN(SingleDesktopTestObserver);
+};
+
+SingleDesktopTestObserver::SingleDesktopTestObserver(
+    chrome::HostDesktopType allowed_desktop)
+        : allowed_desktop_(allowed_desktop) {
+  BrowserList::AddObserver(this);
+}
+
+SingleDesktopTestObserver::~SingleDesktopTestObserver() {
+  BrowserList::RemoveObserver(this);
+}
+
+void SingleDesktopTestObserver::OnBrowserAdded(Browser* browser) {
+  CHECK(CalledOnValidThread());
+  CHECK_EQ(browser->host_desktop_type(), allowed_desktop_);
+}
+
 }  // namespace
 
 InProcessBrowserTest::InProcessBrowserTest()
     : browser_(NULL),
-      exit_when_last_browser_closes_(true)
+      exit_when_last_browser_closes_(true),
+      multi_desktop_test_(false)
 #if defined(OS_MACOSX)
       , autorelease_pool_(NULL)
 #endif  // OS_MACOSX
@@ -89,6 +136,10 @@
   CHECK(PathService::Override(base::FILE_EXE, chrome_path));
 #endif  // defined(OS_MACOSX)
   CreateTestServer(base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
+  base::FilePath src_dir;
+  CHECK(PathService::Get(base::DIR_SOURCE_ROOT, &src_dir));
+  embedded_test_server()->ServeFilesFromDirectory(
+      src_dir.AppendASCII("chrome/test/data"));
 }
 
 InProcessBrowserTest::~InProcessBrowserTest() {
@@ -98,8 +149,10 @@
   // Undo TestingBrowserProcess creation in ChromeTestSuite.
   // TODO(phajdan.jr): Extract a smaller test suite so we don't need this.
   DCHECK(g_browser_process);
-  delete g_browser_process;
+  BrowserProcess* old_browser_process = g_browser_process;
+  // g_browser_process must be NULL during its own destruction.
   g_browser_process = NULL;
+  delete old_browser_process;
 
   CommandLine* command_line = CommandLine::ForCurrentProcess();
   // Allow subclasses to change the command line before running any tests.
@@ -159,6 +212,18 @@
 
   google_util::SetMockLinkDoctorBaseURLForTesting();
 
+#if defined(OS_WIN) && defined(USE_AURA)
+  if (base::win::GetVersion() >= base::win::VERSION_WIN8 &&
+      CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests)) {
+    com_initializer_.reset(new base::win::ScopedCOMInitializer());
+    ui::win::CreateATLModuleIfNeeded();
+    ASSERT_TRUE(win8::MakeTestDefaultBrowserSynchronously());
+
+    // Ash browser tests need the real compositor.
+    ui::DisableTestCompositor();
+  }
+#endif
+
   BrowserTestBase::SetUp();
 }
 
@@ -169,6 +234,17 @@
   // This is a Browser test.
   command_line->AppendSwitchASCII(switches::kTestType, kBrowserTestType);
 
+#if defined(OS_WIN) && defined(USE_AURA)
+  if (command_line->HasSwitch(switches::kAshBrowserTests)) {
+    command_line->AppendSwitchNative(switches::kViewerLaunchViaAppId,
+                                     win8::test::kDefaultTestAppUserModelId);
+    // Ash already launches with a single browser opened, add kSilentLaunch to
+    // make sure StartupBrowserCreator doesn't attempt to launch a browser on
+    // the native desktop on startup.
+    command_line->AppendSwitch(switches::kSilentLaunch);
+  }
+#endif
+
 #if defined(OS_MACOSX)
   // Explicitly set the path of the binary used for child processes, otherwise
   // they'll try to use browser_tests which doesn't contain ChromeMain.
@@ -212,6 +288,9 @@
 
 void InProcessBrowserTest::TearDown() {
   DCHECK(!g_browser_process);
+#if defined(OS_WIN) && defined(USE_AURA)
+  com_initializer_.reset();
+#endif
   BrowserTestBase::TearDown();
 }
 
@@ -243,7 +322,7 @@
 // finish loading and shows the browser.
 Browser* InProcessBrowserTest::CreateBrowser(Profile* profile) {
   Browser* browser = new Browser(
-      Browser::CreateParams(profile, chrome::HOST_DESKTOP_TYPE_NATIVE));
+      Browser::CreateParams(profile, chrome::GetActiveDesktop()));
   AddBlankTabAndShow(browser);
   return browser;
 }
@@ -252,7 +331,7 @@
   // Create a new browser with using the incognito profile.
   Browser* incognito = new Browser(
       Browser::CreateParams(browser()->profile()->GetOffTheRecordProfile(),
-                            chrome::HOST_DESKTOP_TYPE_NATIVE));
+                            chrome::GetActiveDesktop()));
   AddBlankTabAndShow(incognito);
   return incognito;
 }
@@ -260,7 +339,7 @@
 Browser* InProcessBrowserTest::CreateBrowserForPopup(Profile* profile) {
   Browser* browser =
       new Browser(Browser::CreateParams(Browser::TYPE_POPUP, profile,
-                  chrome::HOST_DESKTOP_TYPE_NATIVE));
+                  chrome::GetActiveDesktop()));
   AddBlankTabAndShow(browser);
   return browser;
 }
@@ -271,7 +350,7 @@
   Browser* browser = new Browser(
       Browser::CreateParams::CreateForApp(
           Browser::TYPE_POPUP, app_name, gfx::Rect(), profile,
-          chrome::HOST_DESKTOP_TYPE_NATIVE));
+          chrome::GetActiveDesktop()));
   AddBlankTabAndShow(browser);
   return browser;
 }
@@ -327,11 +406,18 @@
   autorelease_pool_->Recycle();
 #endif
 
-  // Browser tests do not support multi-desktop for now.
-  const BrowserList* native_browser_list =
-      BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_NATIVE);
-  if (!native_browser_list->empty()) {
-    browser_ = native_browser_list->get(0);
+  chrome::HostDesktopType active_desktop = chrome::GetActiveDesktop();
+  // Self-adds/removes itself from the BrowserList observers.
+  scoped_ptr<SingleDesktopTestObserver> single_desktop_test_observer;
+  if (!multi_desktop_test_) {
+    single_desktop_test_observer.reset(
+        new SingleDesktopTestObserver(active_desktop));
+  }
+
+  const BrowserList* active_browser_list =
+      BrowserList::GetInstance(active_desktop);
+  if (!active_browser_list->empty()) {
+    browser_ = active_browser_list->get(0);
 #if defined(USE_ASH)
     // There are cases where windows get created maximized by default.
     if (browser_->window()->IsMaximized())
@@ -370,7 +456,12 @@
   content::RunAllPendingInMessageLoop();
 
   QuitBrowsers();
-  CHECK(native_browser_list->empty());
+  // All BrowserLists should be empty at this point.
+  for (chrome::HostDesktopType t = chrome::HOST_DESKTOP_TYPE_FIRST;
+       t < chrome::HOST_DESKTOP_TYPE_COUNT;
+       t = static_cast<chrome::HostDesktopType>(t + 1)) {
+    CHECK(BrowserList::GetInstance(t)->empty()) << t;
+  }
 }
 
 void InProcessBrowserTest::QuitBrowsers() {
diff --git a/chrome/test/base/in_process_browser_test.h b/chrome/test/base/in_process_browser_test.h
index db5977f..53ecfc1 100644
--- a/chrome/test/base/in_process_browser_test.h
+++ b/chrome/test/base/in_process_browser_test.h
@@ -18,13 +18,19 @@
 #include "chrome/browser/chromeos/cros/cros_library.h"
 #endif  // defined(OS_CHROMEOS)
 
-#if defined(OS_MACOSX)
 namespace base {
+#if defined(OS_MACOSX)
 namespace mac {
 class ScopedNSAutoreleasePool;
 }  // namespace mac
+#endif  // defined(OS_MACOSX)
+
+#if defined(OS_WIN) && defined(USE_AURA)
+namespace win {
+class ScopedCOMInitializer;
+}
+#endif  // defined(OS_WIN) && defined(USE_AURA)
 }  // namespace base
-#endif  // OS_MACOSX
 
 class Browser;
 class CommandLine;
@@ -177,6 +183,11 @@
     exit_when_last_browser_closes_ = value;
   }
 
+  // This must be called before RunTestOnMainThreadLoop() to have any effect.
+  void set_multi_desktop_test(bool multi_desktop_test) {
+    multi_desktop_test_ = multi_desktop_test;
+  }
+
  private:
   // Creates a user data directory for the test if one is needed. Returns true
   // if successful.
@@ -202,6 +213,10 @@
   // True if we should exit the tests after the last browser instance closes.
   bool exit_when_last_browser_closes_;
 
+  // True if this is a multi-desktop test (in which case this browser test will
+  // not ensure that Browsers are only created on the tested desktop).
+  bool multi_desktop_test_;
+
 #if defined(OS_CHROMEOS)
   chromeos::ScopedStubCrosEnabler stub_cros_enabler_;
 #endif  // defined(OS_CHROMEOS)
@@ -209,6 +224,10 @@
 #if defined(OS_MACOSX)
   base::mac::ScopedNSAutoreleasePool* autorelease_pool_;
 #endif  // OS_MACOSX
+
+#if defined(OS_WIN) && defined(USE_AURA)
+  scoped_ptr<base::win::ScopedCOMInitializer> com_initializer_;
+#endif
 };
 
 #endif  // CHROME_TEST_BASE_IN_PROCESS_BROWSER_TEST_H_
diff --git a/chrome/test/base/interactive_test_utils_win.cc b/chrome/test/base/interactive_test_utils_win.cc
index 328a025..ec7e285 100644
--- a/chrome/test/base/interactive_test_utils_win.cc
+++ b/chrome/test/base/interactive_test_utils_win.cc
@@ -8,7 +8,7 @@
 #include "base/logging.h"
 #include "base/path_service.h"
 #include "base/strings/stringprintf.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/ui/window_snapshot/window_snapshot.h"
 #include "ui/base/test/ui_controls.h"
 #include "ui/base/win/foreground_helper.h"
diff --git a/chrome/test/base/model_test_utils.cc b/chrome/test/base/model_test_utils.cc
deleted file mode 100644
index 917c8d2..0000000
--- a/chrome/test/base/model_test_utils.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/test/base/model_test_utils.h"
-
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/bookmarks/bookmark_model.h"
-#include "googleurl/src/gurl.h"
-
-namespace model_test_utils {
-
-std::string ModelStringFromNode(const BookmarkNode* node) {
-  // Since the children of the node are not available as a vector,
-  // we'll just have to do it the hard way.
-  int child_count = node->child_count();
-  std::string child_string;
-  for (int i = 0; i < child_count; ++i) {
-    const BookmarkNode* child = node->GetChild(i);
-    if (child->is_folder()) {
-      child_string += UTF16ToUTF8(child->GetTitle()) + ":[ " +
-          ModelStringFromNode(child) + "] ";
-    } else {
-      child_string += UTF16ToUTF8(child->GetTitle()) + " ";
-    }
-  }
-  return child_string;
-}
-
-// Helper function which does the actual work of creating the nodes for
-// a particular level in the hierarchy.
-std::string::size_type AddNodesFromString(BookmarkModel* model,
-                                          const BookmarkNode* node,
-                                          const std::string& model_string,
-                                          std::string::size_type start_pos) {
-  DCHECK(node);
-  int index = node->child_count();
-  static const std::string folder_tell(":[");
-  std::string::size_type end_pos = model_string.find(' ', start_pos);
-  while (end_pos != std::string::npos) {
-    std::string::size_type part_length = end_pos - start_pos;
-    std::string node_name = model_string.substr(start_pos, part_length);
-    // Are we at the end of a folder group?
-    if (node_name != "]") {
-      // No, is it a folder?
-      std::string tell;
-      if (part_length > 2)
-        tell = node_name.substr(part_length - 2, 2);
-      if (tell == folder_tell) {
-        node_name = node_name.substr(0, part_length - 2);
-        const BookmarkNode* new_node =
-            model->AddFolder(node, index, UTF8ToUTF16(node_name));
-        end_pos = AddNodesFromString(model, new_node, model_string,
-                                     end_pos + 1);
-      } else {
-        std::string url_string("http://");
-        url_string += std::string(node_name.begin(), node_name.end());
-        url_string += ".com";
-        model->AddURL(node, index, UTF8ToUTF16(node_name), GURL(url_string));
-        ++end_pos;
-      }
-      ++index;
-      start_pos = end_pos;
-      end_pos = model_string.find(' ', start_pos);
-    } else {
-      ++end_pos;
-      break;
-    }
-  }
-  return end_pos;
-}
-
-void AddNodesFromModelString(BookmarkModel* model,
-                             const BookmarkNode* node,
-                             const std::string& model_string) {
-  DCHECK(node);
-  const std::string folder_tell(":[");
-  std::string::size_type start_pos = 0;
-  std::string::size_type end_pos =
-      AddNodesFromString(model, node, model_string, start_pos);
-  DCHECK(end_pos == std::string::npos);
-}
-
-}  // namespace model_test_utils
diff --git a/chrome/test/base/model_test_utils.h b/chrome/test/base/model_test_utils.h
deleted file mode 100644
index ee58a8a..0000000
--- a/chrome/test/base/model_test_utils.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_TEST_BASE_MODEL_TEST_UTILS_H_
-#define CHROME_TEST_BASE_MODEL_TEST_UTILS_H_
-
-#include <string>
-
-class BookmarkModel;
-class BookmarkNode;
-
-namespace model_test_utils {
-
-// Return the descendants of |node| as a string useful for verifying node
-// modifications. The format of the resulting string is:
-//
-//           result = node " " , { node " " }
-//             node = bookmark title | folder
-//           folder = folder title ":[ " { node " " } "]"
-//   bookmark title = (* string with no spaces *)
-//     folder title = (* string with no spaces *)
-//
-// Example: "a f1:[ b d c ] d f2:[ e f g ] h "
-//
-// (Logically, we should use |string16|s, but it's more convenient for test
-// purposes to use (UTF-8) |std::string|s.)
-std::string ModelStringFromNode(const BookmarkNode* node);
-
-// Create and add the node hierarchy specified by |nodeString| to the
-// bookmark node given by |node|. The string has the same format as
-// specified for ModelStringFromNode. The new nodes added to |node|
-// are appended to the end of node's existing subnodes, if any.
-// |model| must be the model of which |node| is a member.
-// NOTE: The string format is very rigid and easily broken if not followed
-//       exactly (since we're using a very simple parser).
-void AddNodesFromModelString(BookmarkModel* model,
-                             const BookmarkNode* node,
-                             const std::string& model_string);
-
-}  // namespace model_test_utils
-
-#endif  // CHROME_TEST_BASE_MODEL_TEST_UTILS_H_
diff --git a/chrome/test/base/test_switches.cc b/chrome/test/base/test_switches.cc
index c5e3c99..e52da44 100644
--- a/chrome/test/base/test_switches.cc
+++ b/chrome/test/base/test_switches.cc
@@ -4,22 +4,23 @@
 
 #include "chrome/test/base/test_switches.h"
 
+namespace switches {
+
 // Also emit full event trace logs for successful tests.
-const char switches::kAlsoEmitSuccessLogs[] = "also-emit-success-logs";
+const char kAlsoEmitSuccessLogs[] = "also-emit-success-logs";
 
 // Extra flags that the test should pass to launched browser process.
-const char switches::kExtraChromeFlags[] = "extra-chrome-flags";
+const char kExtraChromeFlags[] = "extra-chrome-flags";
 
 // Enable Chromium branding of the executable.
-const char switches::kEnableChromiumBranding[] = "enable-chromium-branding";
+const char kEnableChromiumBranding[] = "enable-chromium-branding";
 
 // Enable displaying error dialogs (for debugging).
-const char switches::kEnableErrorDialogs[] = "enable-errdialogs";
+const char kEnableErrorDialogs[] = "enable-errdialogs";
 
-// Number of iterations that page cycler tests will run.
-const char switches::kPageCyclerIterations[] = "page-cycler-iterations";
+#if defined(OS_WIN) && defined(USE_AURA)
+// Force browser tests to run in Ash/Metro on Windows 8.
+const char kAshBrowserTests[] = "ash-browsertests";
+#endif
 
-// Name of channel used to connect to Chrome
-// when using the named testing interface.
-const char switches::kTestingChannel[] = "testing-channel";
-
+}  // namespace switches
diff --git a/chrome/test/base/test_switches.h b/chrome/test/base/test_switches.h
index c37e719..c96107e 100644
--- a/chrome/test/base/test_switches.h
+++ b/chrome/test/base/test_switches.h
@@ -5,6 +5,8 @@
 #ifndef CHROME_TEST_BASE_TEST_SWITCHES_H_
 #define CHROME_TEST_BASE_TEST_SWITCHES_H_
 
+#include "build/build_config.h"
+
 namespace switches {
 
 // All switches in alphabetical order. The switches should be documented
@@ -13,8 +15,10 @@
 extern const char kExtraChromeFlags[];
 extern const char kEnableChromiumBranding[];
 extern const char kEnableErrorDialogs[];
-extern const char kPageCyclerIterations[];
-extern const char kTestingChannel[];
+
+#if defined(OS_WIN) && defined(USE_AURA)
+extern const char kAshBrowserTests[];
+#endif
 
 }  // namespace switches
 
diff --git a/chrome/test/base/testing_browser_process.cc b/chrome/test/base/testing_browser_process.cc
index 3fe39f2..224e623 100644
--- a/chrome/test/base/testing_browser_process.cc
+++ b/chrome/test/base/testing_browser_process.cc
@@ -7,6 +7,7 @@
 #include "base/prefs/pref_service.h"
 #include "base/strings/string_util.h"
 #include "build/build_config.h"
+#include "chrome/browser/background/background_mode_manager.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/bookmarks/bookmark_prompt_controller.h"
@@ -55,6 +56,10 @@
 #if defined(ENABLE_CONFIGURATION_POLICY)
   SetBrowserPolicyConnector(NULL);
 #endif
+
+  // Destructors for some objects owned by TestingBrowserProcess will use
+  // g_browser_process if it is not NULL, so it must be NULL before proceeding.
+  DCHECK_EQ(static_cast<BrowserProcess*>(NULL), g_browser_process);
 }
 
 void TestingBrowserProcess::ResourceDispatcherHostCreated() {
@@ -149,6 +154,11 @@
   return NULL;
 }
 
+void TestingBrowserProcess::set_background_mode_manager_for_test(
+    scoped_ptr<BackgroundModeManager> manager) {
+  NOTREACHED();
+}
+
 StatusTray* TestingBrowserProcess::status_tray() {
   return NULL;
 }
diff --git a/chrome/test/base/testing_browser_process.h b/chrome/test/base/testing_browser_process.h
index 300f192..983d766 100644
--- a/chrome/test/base/testing_browser_process.h
+++ b/chrome/test/base/testing_browser_process.h
@@ -62,6 +62,8 @@
   virtual GpuModeManager* gpu_mode_manager() OVERRIDE;
   virtual RenderWidgetSnapshotTaker* GetRenderWidgetSnapshotTaker() OVERRIDE;
   virtual BackgroundModeManager* background_mode_manager() OVERRIDE;
+  virtual void set_background_mode_manager_for_test(
+      scoped_ptr<BackgroundModeManager> manager) OVERRIDE;
   virtual StatusTray* status_tray() OVERRIDE;
   virtual SafeBrowsingService* safe_browsing_service() OVERRIDE;
   virtual safe_browsing::ClientSideDetectionService*
diff --git a/chrome/test/base/testing_profile.cc b/chrome/test/base/testing_profile.cc
index a5bdae8..5ee917f 100644
--- a/chrome/test/base/testing_profile.cc
+++ b/chrome/test/base/testing_profile.cc
@@ -269,7 +269,7 @@
 
     base::FilePath fallback_dir(
         system_tmp_dir.AppendASCII("TestingProfilePath"));
-    file_util::Delete(fallback_dir, true);
+    base::Delete(fallback_dir, true);
     file_util::CreateDirectory(fallback_dir);
     if (!temp_dir_.Set(fallback_dir)) {
       // That shouldn't happen, but if it does, try to recover.
@@ -360,7 +360,7 @@
   if (delete_file) {
     base::FilePath path = GetPath();
     path = path.Append(chrome::kHistoryFilename);
-    file_util::Delete(path, false);
+    base::Delete(path, false);
   }
   // This will create and init the history service.
   HistoryService* history_service = static_cast<HistoryService*>(
@@ -429,7 +429,7 @@
 void TestingProfile::CreateBookmarkModel(bool delete_file) {
   if (delete_file) {
     base::FilePath path = GetPath().Append(chrome::kBookmarksFileName);
-    file_util::Delete(path, false);
+    base::Delete(path, false);
   }
   // This will create a bookmark model.
   BookmarkModel* bookmark_service = static_cast<BookmarkModel*>(
diff --git a/chrome/test/base/testing_profile_manager.cc b/chrome/test/base/testing_profile_manager.cc
index 9871d4a..5a5f620 100644
--- a/chrome/test/base/testing_profile_manager.cc
+++ b/chrome/test/base/testing_profile_manager.cc
@@ -5,8 +5,10 @@
 #include "chrome/test/base/testing_profile_manager.h"
 
 #include "base/files/file_path.h"
-#include "base/memory/scoped_ptr.h"
+#include "base/memory/ref_counted.h"
 #include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/extensions/extension_special_storage_policy.h"
+#include "chrome/browser/prefs/pref_service_syncable.h"
 #include "chrome/browser/profiles/profile_info_cache.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/test/base/testing_browser_process.h"
@@ -45,6 +47,7 @@
 
 TestingProfile* TestingProfileManager::CreateTestingProfile(
     const std::string& profile_name,
+    scoped_ptr<PrefServiceSyncable> prefs,
     const string16& user_name,
     int avatar_id) {
   DCHECK(called_set_up_);
@@ -54,7 +57,11 @@
   profile_path = profile_path.AppendASCII(profile_name);
 
   // Create the profile and register it.
-  TestingProfile* profile = new TestingProfile(profile_path);
+  TestingProfile* profile = new TestingProfile(
+      profile_path,
+      NULL,
+      scoped_refptr<ExtensionSpecialStoragePolicy>(),
+      prefs.Pass());
   profile_manager_->AddProfile(profile);  // Takes ownership.
 
   // Update the user metadata.
@@ -71,7 +78,8 @@
 TestingProfile* TestingProfileManager::CreateTestingProfile(
     const std::string& name) {
   DCHECK(called_set_up_);
-  return CreateTestingProfile(name, UTF8ToUTF16(name), 0);
+  return CreateTestingProfile(name, scoped_ptr<PrefServiceSyncable>(),
+                              UTF8ToUTF16(name), 0);
 }
 
 void TestingProfileManager::DeleteTestingProfile(const std::string& name) {
diff --git a/chrome/test/base/testing_profile_manager.h b/chrome/test/base/testing_profile_manager.h
index f6ae1f7..7a4205c 100644
--- a/chrome/test/base/testing_profile_manager.h
+++ b/chrome/test/base/testing_profile_manager.h
@@ -10,9 +10,11 @@
 
 #include "base/compiler_specific.h"
 #include "base/files/scoped_temp_dir.h"
+#include "base/memory/scoped_ptr.h"
 #include "base/strings/string16.h"
 #include "chrome/test/base/scoped_testing_local_state.h"
 
+class PrefServiceSyncable;
 class ProfileInfoCache;
 class ProfileManager;
 class TestingBrowserProcess;
@@ -38,11 +40,14 @@
 
   // Creates a new TestingProfile whose data lives in a directory related to
   // profile_name, which is a non-user-visible key for the test environment.
+  // |prefs| is the PrefService used by the profile. If it is NULL, the profile
+  // creates a PrefService on demand.
   // |user_name| and |avatar_id| are passed along to the ProfileInfoCache and
   // provide the user-visible profile metadata. This will register the
   // TestingProfile with the profile subsystem as well. The subsystem owns the
   // Profile and returns a weak pointer.
   TestingProfile* CreateTestingProfile(const std::string& profile_name,
+                                       scoped_ptr<PrefServiceSyncable> prefs,
                                        const string16& user_name,
                                        int avatar_id);
 
diff --git a/chrome/test/base/tracing.h b/chrome/test/base/tracing.h
index 0dd21b8..bff5afa 100644
--- a/chrome/test/base/tracing.h
+++ b/chrome/test/base/tracing.h
@@ -8,7 +8,7 @@
 #include <string>
 
 #include "base/compiler_specific.h"
-#include "base/time.h"
+#include "base/time/time.h"
 
 namespace tracing {
 
diff --git a/chrome/test/base/ui_test_utils.cc b/chrome/test/base/ui_test_utils.cc
index be43fa1..61f8b26 100644
--- a/chrome/test/base/ui_test_utils.cc
+++ b/chrome/test/base/ui_test_utils.cc
@@ -21,7 +21,7 @@
 #include "base/prefs/pref_service.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/test_timeouts.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/autocomplete/autocomplete_controller.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
@@ -158,11 +158,10 @@
 }
 
 Browser* OpenURLOffTheRecord(Profile* profile, const GURL& url) {
-  chrome::OpenURLOffTheRecord(profile, url, chrome::HOST_DESKTOP_TYPE_NATIVE);
+  chrome::HostDesktopType active_desktop = chrome::GetActiveDesktop();
+  chrome::OpenURLOffTheRecord(profile, url, active_desktop);
   Browser* browser = chrome::FindTabbedBrowser(
-      profile->GetOffTheRecordProfile(),
-      false,
-      chrome::HOST_DESKTOP_TYPE_NATIVE);
+      profile->GetOffTheRecordProfile(), false, active_desktop);
   WaitForNavigations(
       &browser->tab_strip_model()->GetActiveWebContents()->GetController(),
       1);
diff --git a/chrome/test/base/view_event_test_base.cc b/chrome/test/base/view_event_test_base.cc
index f379c40..62a7b4e 100644
--- a/chrome/test/base/view_event_test_base.cc
+++ b/chrome/test/base/view_event_test_base.cc
@@ -32,7 +32,6 @@
 
 #if defined(OS_CHROMEOS)
 #include "chromeos/audio/cras_audio_handler.h"
-#include "chromeos/power/power_manager_handler.h"
 #endif
 
 namespace {
@@ -108,7 +107,6 @@
   message_center::MessageCenter::Initialize();
 #if defined(OS_CHROMEOS)
   chromeos::CrasAudioHandler::InitializeForTesting();
-  chromeos::PowerManagerHandler::Initialize();
 #endif
   ash::Shell::CreateInstance(new ash::test::TestShellDelegate());
   context = ash::Shell::GetPrimaryRootWindow();
@@ -138,7 +136,6 @@
 #else
   ash::Shell::DeleteInstance();
 #if defined(OS_CHROMEOS)
-  chromeos::PowerManagerHandler::Shutdown();
   chromeos::CrasAudioHandler::Shutdown();
 #endif
   // Ash Shell can't just live on its own without a browser process, we need to
diff --git a/chrome/test/chromedriver/README.txt b/chrome/test/chromedriver/README.txt
index ab9e95c..35f0d54 100644
--- a/chrome/test/chromedriver/README.txt
+++ b/chrome/test/chromedriver/README.txt
@@ -5,18 +5,21 @@
 which allows users to automate testing of their website across browsers.
 
 =====Getting started=====
-Build ChromeDriver by building the 'chromedriver2' target. This will create
-a shared library in the build folder named 'chromedriver2.dll' (win),
-'chromedriver2.so' (mac), or 'libchromedriver2.so' (linux).
+Build ChromeDriver by building the 'chromedriver2_server' target. This will
+create an executable binary in the build folder named 'chromedriver2_server.exe'
+on Windows or 'chromedriver2_server' on Mac and Linux.
 
 Once built, ChromeDriver can be used interactively with python.
-This can be easily done by running python in this directory (or including
-this directory in your PYTHONPATH).
 
+$ export PYTHONPATH=<THIS_DIR>/server:<THIS_DIR>/client
 $ python
+>>> import server
 >>> import chromedriver
->>> driver = chromedriver.ChromeDriver('/path/to/chromedriver2/library')
+>>> cd_server = server.Server('/path/to/chromedriver2_server/executable')
+>>> driver = chromedriver.ChromeDriver(cd_server.GetUrl())
 >>> driver.Load('http://www.google.com')
+>>> driver.Quit()
+>>> cd_server.Kill()
 
 ChromeDriver will use the system installed Chrome by default.
 
@@ -26,28 +29,16 @@
 more detailed instructions see the wiki:
     https://code.google.com/p/chromedriver/wiki/ChromeDriver2forAndroid
 
-NOTE: on 64-bit OSX machines (most modern ones, including laptops) it is
-necessary to set the environment variable VERSIONER_PYTHON_PREFER_32_BIT=yes,
-because the 'chromedriver2.so' library is 32-bit, while on 64-bit OSX machines
-(most modern ones including laptops), python starts as a 64-bit binary by
-default and would not be able to load the library.
-
 =====Architecture=====
 ChromeDriver is shipped separately from Chrome. It controls Chrome out of
-process through DevTools (WebKit Inspector). ChromeDriver is a shared library
-which exports a few functions for executing WebDriver-standard commands, which
-are packaged in JSON. For internal use, a custom python client for ChromeDriver
-is available in chromedriver.py, which works on desktop (win/mac/linux) with
-the shared library ChromeDriver.
+process through DevTools (WebKit Inspector). ChromeDriver is a standalone server
+executable which communicates via the WebDriver JSON wire protocol. This can be
+used with the open source WebDriver client libraries.
 
-The ChromeDriver shared library runs commands on the same thread that calls
-ExecuteCommand. It doesn't create any additional threads except for the IO
-thread. The IO thread is used to keep reading incoming data from Chrome in the
-background.
-
-ChromeDriver is also available as a standalone server executable which
-communicates via the WebDriver JSON wire protocol. This can be used with the
-open source WebDriver client libraries.
+When a new session is created, a new thread is started that is dedicated to the
+session. All commands for the session runs on this thread. This thread is
+stopped when the session is deleted. Besides, there is an IO thread and it is
+used to keep reading incoming data from Chrome in the background.
 
 =====Code structure=====
 Code under the 'chrome' subdirectory is intended to be unaware of WebDriver and
@@ -67,10 +58,17 @@
 4) chrome/test/chromedriver/net
 Code to deal with network communication, such as connection to DevTools.
 
-5) chrome/test/chromedriver/server
-Code for the chromedriver server.
+5) chrome/test/chromedriver/client
+Code for a python client.
 
-6) chrome/test/chromedriver/third_party
+6) chrome/test/chromedriver/server
+Code for the chromedriver server.
+A python wrapper to the chromedriver server.
+
+7) chrome/test/chromedriver/extension
+An extension used for automating the desktop browser.
+
+8) chrome/test/chromedriver/third_party
 Third party libraries used by chromedriver.
 
 =====Testing=====
diff --git a/chrome/test/chromedriver/archive.py b/chrome/test/chromedriver/archive.py
index 5835a80..9a2aa87 100644
--- a/chrome/test/chromedriver/archive.py
+++ b/chrome/test/chromedriver/archive.py
@@ -6,16 +6,13 @@
 
 import os
 import platform
-import sys
 import urllib
 
-_THIS_DIR = os.path.abspath(os.path.dirname(__file__))
-sys.path.insert(0, os.path.join(_THIS_DIR, os.pardir, 'pylib'))
-
-from common import util
+import util
 
 CHROME_27_REVISION = '190466'
 CHROME_28_REVISION = '198276'
+CHROME_29_REVISION = '208334'
 
 _SITE = 'http://commondatastorage.googleapis.com'
 
diff --git a/chrome/test/chromedriver/capabilities.cc b/chrome/test/chromedriver/capabilities.cc
index fa5996d..d5c55f3 100644
--- a/chrome/test/chromedriver/capabilities.cc
+++ b/chrome/test/chromedriver/capabilities.cc
@@ -42,7 +42,9 @@
   return Status(kOk);
 }
 
-Status ParseArgs(const base::Value& option, Capabilities* capabilities) {
+Status ParseArgs(bool is_android,
+                 const base::Value& option,
+                 Capabilities* capabilities) {
   const base::ListValue* args_list = NULL;
   if (!option.GetAsList(&args_list))
     return Status(kUnknownError, "'args' must be a list");
@@ -50,16 +52,20 @@
     std::string arg_string;
     if (!args_list->GetString(i, &arg_string))
       return Status(kUnknownError, "each argument must be a string");
-    size_t separator_index = arg_string.find("=");
-    if (separator_index != std::string::npos) {
-      CommandLine::StringType arg_string_native;
-      if (!args_list->GetString(i, &arg_string_native))
-        return Status(kUnknownError, "each argument must be a string");
-      capabilities->command.AppendSwitchNative(
-          arg_string.substr(0, separator_index),
-          arg_string_native.substr(separator_index + 1));
+    if (is_android) {
+      capabilities->android_args += "--" + arg_string + " ";
     } else {
-      capabilities->command.AppendSwitch(arg_string);
+      size_t separator_index = arg_string.find("=");
+      if (separator_index != std::string::npos) {
+        CommandLine::StringType arg_string_native;
+        if (!args_list->GetString(i, &arg_string_native))
+          return Status(kUnknownError, "each argument must be a string");
+        capabilities->command.AppendSwitchNative(
+            arg_string.substr(0, separator_index),
+            arg_string_native.substr(separator_index + 1));
+      } else {
+        capabilities->command.AppendSwitch(arg_string);
+      }
     }
   }
   return Status(kOk);
@@ -164,7 +170,7 @@
   return Status(kOk);
 }
 
-Status ParseDesktopChromeOption(
+Status ParseDesktopChromeCapabilities(
     const base::Value& capability,
     Capabilities* capabilities) {
   const base::DictionaryValue* chrome_options = NULL;
@@ -176,7 +182,7 @@
   parser_map["detach"] = base::Bind(&ParseDetach);
   parser_map["binary"] = base::Bind(&ParseChromeBinary);
   parser_map["logPath"] = base::Bind(&ParseLogPath);
-  parser_map["args"] = base::Bind(&ParseArgs);
+  parser_map["args"] = base::Bind(&ParseArgs, false);
   parser_map["prefs"] = base::Bind(&ParsePrefs);
   parser_map["localState"] = base::Bind(&ParseLocalState);
   parser_map["extensions"] = base::Bind(&ParseExtensions);
@@ -209,15 +215,20 @@
         return Status(kUnknownError,
                       "'androidPackage' must be a non-empty string");
       }
-    }
 
-    const base::Value* device_serial_value;
-    if (chrome_options_dict->Get("deviceSerial", &device_serial_value)) {
-      if (!device_serial_value->GetAsString(&capabilities->device_serial) ||
-          capabilities->device_serial.empty()) {
-        return Status(kUnknownError,
-                      "'deviceSerial' must be a non-empty string");
+      const base::Value* device_serial_value;
+      if (chrome_options_dict->Get("androidDeviceSerial",
+                                   &device_serial_value)) {
+        if (!device_serial_value->GetAsString(&capabilities->device_serial) ||
+            capabilities->device_serial.empty()) {
+          return Status(kUnknownError,
+                        "'androidDeviceSerial' must be a non-empty string");
+        }
       }
+
+      const base::Value* args_value;
+      if (chrome_options_dict->Get("args", &args_value))
+        return ParseArgs(true, *args_value, capabilities);
     }
   }
   return Status(kOk);
@@ -262,7 +273,7 @@
 
   std::map<std::string, Parser> parser_map;
   parser_map["proxy"] = base::Bind(&ParseProxy);
-  parser_map["chromeOptions"] = base::Bind(&ParseDesktopChromeOption);
+  parser_map["chromeOptions"] = base::Bind(&ParseDesktopChromeCapabilities);
   for (std::map<std::string, Parser>::iterator it = parser_map.begin();
        it != parser_map.end(); ++it) {
     const base::Value* capability = NULL;
diff --git a/chrome/test/chromedriver/capabilities.h b/chrome/test/chromedriver/capabilities.h
index 723ff10..5e22b9a 100644
--- a/chrome/test/chromedriver/capabilities.h
+++ b/chrome/test/chromedriver/capabilities.h
@@ -34,6 +34,7 @@
 
   std::string android_package;
   std::string device_serial;
+  std::string android_args;
 
   std::string log_path;
   CommandLine command;
diff --git a/chrome/test/chromedriver/chrome/adb.h b/chrome/test/chromedriver/chrome/adb.h
index a11f9c2..24ad700 100644
--- a/chrome/test/chromedriver/chrome/adb.h
+++ b/chrome/test/chromedriver/chrome/adb.h
@@ -18,7 +18,8 @@
   virtual Status ForwardPort(const std::string& device_serial,
                              int local_port,
                              const std::string& remote_abstract) = 0;
-  virtual Status SetChromeFlags(const std::string& device_serial) = 0;
+  virtual Status SetChromeArgs(const std::string& device_serial,
+                               const std::string& args) = 0;
   virtual Status CheckAppInstalled(const std::string& device_serial,
                                    const std::string& package) = 0;
   virtual Status ClearAppData(const std::string& device_serial,
diff --git a/chrome/test/chromedriver/chrome/adb_impl.cc b/chrome/test/chromedriver/chrome/adb_impl.cc
index 0386e29..ea98162 100644
--- a/chrome/test/chromedriver/chrome/adb_impl.cc
+++ b/chrome/test/chromedriver/chrome/adb_impl.cc
@@ -15,7 +15,7 @@
 #include "base/strings/string_tokenizer.h"
 #include "base/strings/stringprintf.h"
 #include "base/synchronization/waitable_event.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/test/chromedriver/chrome/log.h"
 #include "chrome/test/chromedriver/chrome/status.h"
 #include "chrome/test/chromedriver/net/adb_client_socket.h"
@@ -112,13 +112,12 @@
                 device_serial + ": " + response);
 }
 
-Status AdbImpl::SetChromeFlags(const std::string& device_serial) {
+Status AdbImpl::SetChromeArgs(const std::string& device_serial,
+                              const std::string& args) {
   std::string response;
   Status status = ExecuteHostShellCommand(
       device_serial,
-      "echo chrome --disable-fre --metrics-recording-only "
-          "--enable-remote-debugging > /data/local/chrome-command-line;"
-          "echo $?",
+      "echo chrome " + args + "> /data/local/chrome-command-line; echo $?",
       &response);
   if (!status.IsOk())
     return status;
diff --git a/chrome/test/chromedriver/chrome/adb_impl.h b/chrome/test/chromedriver/chrome/adb_impl.h
index 39d376c..47f9853 100644
--- a/chrome/test/chromedriver/chrome/adb_impl.h
+++ b/chrome/test/chromedriver/chrome/adb_impl.h
@@ -31,7 +31,8 @@
   virtual Status ForwardPort(const std::string& device_serial,
                              int local_port,
                              const std::string& remote_abstract) OVERRIDE;
-  virtual Status SetChromeFlags(const std::string& device_serial) OVERRIDE;
+  virtual Status SetChromeArgs(const std::string& device_serial,
+                               const std::string& args) OVERRIDE;
   virtual Status CheckAppInstalled(const std::string& device_serial,
                                    const std::string& package) OVERRIDE;
   virtual Status ClearAppData(const std::string& device_serial,
diff --git a/chrome/test/chromedriver/chrome/automation_extension.cc b/chrome/test/chromedriver/chrome/automation_extension.cc
index 63ad223..65e035a 100644
--- a/chrome/test/chromedriver/chrome/automation_extension.cc
+++ b/chrome/test/chromedriver/chrome/automation_extension.cc
@@ -4,7 +4,7 @@
 
 #include "chrome/test/chromedriver/chrome/automation_extension.h"
 
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/test/chromedriver/chrome/status.h"
 #include "chrome/test/chromedriver/chrome/web_view.h"
diff --git a/chrome/test/chromedriver/chrome/chrome_desktop_impl.cc b/chrome/test/chromedriver/chrome/chrome_desktop_impl.cc
index 08c9b9f..c1489bb 100644
--- a/chrome/test/chromedriver/chrome/chrome_desktop_impl.cc
+++ b/chrome/test/chromedriver/chrome/chrome_desktop_impl.cc
@@ -10,7 +10,7 @@
 #include "base/process_util.h"
 #include "base/sys_info.h"
 #include "base/threading/platform_thread.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/test/chromedriver/chrome/automation_extension.h"
 #include "chrome/test/chromedriver/chrome/devtools_client.h"
 #include "chrome/test/chromedriver/chrome/devtools_http_client.h"
diff --git a/chrome/test/chromedriver/chrome/chrome_finder.cc b/chrome/test/chromedriver/chrome/chrome_finder.cc
index 406f19f..f2d2079 100644
--- a/chrome/test/chromedriver/chrome/chrome_finder.cc
+++ b/chrome/test/chromedriver/chrome/chrome_finder.cc
@@ -25,6 +25,7 @@
 
 #if defined(OS_WIN)
 void GetApplicationDirs(std::vector<base::FilePath>* locations) {
+  std::vector<base::FilePath> installation_locations;
   // Add user-level location.
   scoped_ptr<base::Environment> env(base::Environment::Create());
   std::string home_dir;
@@ -36,15 +37,24 @@
     } else {
       default_location = default_location.Append(L"AppData\\Local");
     }
-    locations->push_back(default_location);
+    installation_locations.push_back(default_location);
   }
 
   // Add the system-level location.
   std::string program_dir;
   if (env->GetVar("ProgramFiles", &program_dir))
-    locations->push_back(base::FilePath(UTF8ToWide(program_dir)));
+    installation_locations.push_back(base::FilePath(UTF8ToWide(program_dir)));
   if (env->GetVar("ProgramFiles(x86)", &program_dir))
-    locations->push_back(base::FilePath(UTF8ToWide(program_dir)));
+    installation_locations.push_back(base::FilePath(UTF8ToWide(program_dir)));
+
+  for (size_t i = 0; i < installation_locations.size(); ++i) {
+    locations->push_back(
+        installation_locations[i].Append(L"Google\\Chrome\\Application"));
+  }
+  for (size_t i = 0; i < installation_locations.size(); ++i) {
+    locations->push_back(
+        installation_locations[i].Append(L"Chromium\\Application"));
+  }
 }
 #elif defined(OS_LINUX)
 void GetApplicationDirs(std::vector<base::FilePath>* locations) {
@@ -88,8 +98,7 @@
 bool FindChrome(base::FilePath* browser_exe) {
 #if defined(OS_WIN)
   base::FilePath browser_exes_array[] = {
-      base::FilePath(L"Google\\Chrome\\Application\\chrome.exe"),
-      base::FilePath(L"Chromium\\Application\\chrome.exe")
+      base::FilePath(L"chrome.exe")
   };
 #elif defined(OS_MACOSX)
   base::FilePath browser_exes_array[] = {
@@ -107,6 +116,9 @@
   std::vector<base::FilePath> browser_exes(
       browser_exes_array, browser_exes_array + arraysize(browser_exes_array));
   std::vector<base::FilePath> locations;
+  base::FilePath module_dir;
+  if (PathService::Get(base::DIR_MODULE, &module_dir))
+    locations.push_back(module_dir);
   GetApplicationDirs(&locations);
   return internal::FindExe(
       base::Bind(&file_util::PathExists),
diff --git a/chrome/test/chromedriver/chrome/console_logger_unittest.cc b/chrome/test/chromedriver/chrome/console_logger_unittest.cc
index 099f3e4..8250842 100644
--- a/chrome/test/chromedriver/chrome/console_logger_unittest.cc
+++ b/chrome/test/chromedriver/chrome/console_logger_unittest.cc
@@ -7,7 +7,7 @@
 #include "base/compiler_specific.h"
 #include "base/format_macros.h"
 #include "base/memory/scoped_vector.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/test/chromedriver/chrome/log.h"
 #include "chrome/test/chromedriver/chrome/status.h"
diff --git a/chrome/test/chromedriver/chrome/device_manager.cc b/chrome/test/chromedriver/chrome/device_manager.cc
index 103aa0d..34cfab5 100644
--- a/chrome/test/chromedriver/chrome/device_manager.cc
+++ b/chrome/test/chromedriver/chrome/device_manager.cc
@@ -41,7 +41,9 @@
   release_callback_.Run();
 }
 
-Status Device::StartChrome(const std::string& package, int port) {
+Status Device::StartChrome(const std::string& package,
+                           int port,
+                           const std::string& args) {
   if (!active_package_.empty())
     return Status(kUnknownError,
         active_package_ + " was launched and has not been quit");
@@ -51,7 +53,7 @@
   status = adb_->ClearAppData(serial_, package);
   if (!status.IsOk())
     return status;
-  status = adb_->SetChromeFlags(serial_);
+  status = adb_->SetChromeArgs(serial_, args);
   if (!status.IsOk())
     return status;
   status = adb_->Launch(serial_, package, GetActivityForPackage(package));
diff --git a/chrome/test/chromedriver/chrome/device_manager.h b/chrome/test/chromedriver/chrome/device_manager.h
index 5a5844b..65d70c3 100644
--- a/chrome/test/chromedriver/chrome/device_manager.h
+++ b/chrome/test/chromedriver/chrome/device_manager.h
@@ -22,7 +22,9 @@
  public:
   ~Device();
 
-  Status StartChrome(const std::string& package, int port);
+  Status StartChrome(const std::string& package,
+                     int port,
+                     const std::string& args);
   Status StopChrome();
 
  private:
diff --git a/chrome/test/chromedriver/chrome/device_manager_unittest.cc b/chrome/test/chromedriver/chrome/device_manager_unittest.cc
index 539b695..7529e63 100644
--- a/chrome/test/chromedriver/chrome/device_manager_unittest.cc
+++ b/chrome/test/chromedriver/chrome/device_manager_unittest.cc
@@ -16,8 +16,8 @@
 
 class FakeAdb : public Adb {
  public:
-  FakeAdb() {};
-  virtual ~FakeAdb() {};
+  FakeAdb() {}
+  virtual ~FakeAdb() {}
 
   virtual Status GetDevices(std::vector<std::string>* devices) OVERRIDE {
     devices->push_back("a");
@@ -31,7 +31,8 @@
     return Status(kOk);
   }
 
-  virtual Status SetChromeFlags(const std::string& device_serial) OVERRIDE {
+  virtual Status SetChromeArgs(const std::string& device_serial,
+                               const std::string& args) OVERRIDE {
     return Status(kOk);
   }
 
@@ -94,7 +95,7 @@
   scoped_ptr<Device> device1;
   ASSERT_TRUE(device_manager.AcquireDevice(&device1).IsOk());
   ASSERT_FALSE(device1->StopChrome().IsOk());
-  ASSERT_TRUE(device1->StartChrome("p", 0).IsOk());
-  ASSERT_FALSE(device1->StartChrome("p", 0).IsOk());
+  ASSERT_TRUE(device1->StartChrome("p", 0, std::string()).IsOk());
+  ASSERT_FALSE(device1->StartChrome("p", 0, std::string()).IsOk());
   ASSERT_TRUE(device1->StopChrome().IsOk());
 }
diff --git a/chrome/test/chromedriver/chrome/devtools_http_client.cc b/chrome/test/chromedriver/chrome/devtools_http_client.cc
index 2a4e588..7b5fdb4 100644
--- a/chrome/test/chromedriver/chrome/devtools_http_client.cc
+++ b/chrome/test/chromedriver/chrome/devtools_http_client.cc
@@ -9,7 +9,7 @@
 #include "base/json/json_reader.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/platform_thread.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/test/chromedriver/chrome/devtools_client_impl.h"
 #include "chrome/test/chromedriver/chrome/log.h"
diff --git a/chrome/test/chromedriver/chrome/log.cc b/chrome/test/chromedriver/chrome/log.cc
index 7aade73..23e7649 100644
--- a/chrome/test/chromedriver/chrome/log.cc
+++ b/chrome/test/chromedriver/chrome/log.cc
@@ -79,7 +79,7 @@
 // Pretty prints encapsulated JSON and truncates long strings for display.
 std::string ConvertForDisplay(const std::string& input) {
   std::string display = ConvertForDisplayInternal(input);
-  char remove_chars[] = {'\r'};
+  char remove_chars[] = {'\r', '\0'};
   RemoveChars(display, remove_chars, &display);
   return display;
 }
diff --git a/chrome/test/chromedriver/chrome/log.h b/chrome/test/chromedriver/chrome/log.h
index 0a1cf7e..db2eb26 100644
--- a/chrome/test/chromedriver/chrome/log.h
+++ b/chrome/test/chromedriver/chrome/log.h
@@ -8,7 +8,7 @@
 #include <string>
 
 #include "base/compiler_specific.h"
-#include "base/time.h"
+#include "base/time/time.h"
 
 // Abstract class for logging entries with a level, timestamp, string message.
 class Log {
diff --git a/chrome/test/chromedriver/chrome/performance_logger_unittest.cc b/chrome/test/chromedriver/chrome/performance_logger_unittest.cc
index a3a3627..e6c05b8 100644
--- a/chrome/test/chromedriver/chrome/performance_logger_unittest.cc
+++ b/chrome/test/chromedriver/chrome/performance_logger_unittest.cc
@@ -8,7 +8,7 @@
 #include "base/format_macros.h"
 #include "base/json/json_reader.h"
 #include "base/memory/scoped_vector.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/test/chromedriver/chrome/log.h"
 #include "chrome/test/chromedriver/chrome/status.h"
diff --git a/chrome/test/chromedriver/chrome/web_view_impl.cc b/chrome/test/chromedriver/chrome/web_view_impl.cc
index cbff86d..8dce74e 100644
--- a/chrome/test/chromedriver/chrome/web_view_impl.cc
+++ b/chrome/test/chromedriver/chrome/web_view_impl.cc
@@ -11,7 +11,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/platform_thread.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/test/chromedriver/chrome/devtools_client_impl.h"
 #include "chrome/test/chromedriver/chrome/dom_tracker.h"
diff --git a/chrome/test/chromedriver/chrome/zip_reader.h b/chrome/test/chromedriver/chrome/zip_reader.h
index a772972..451968e 100644
--- a/chrome/test/chromedriver/chrome/zip_reader.h
+++ b/chrome/test/chromedriver/chrome/zip_reader.h
@@ -11,7 +11,7 @@
 #include "base/files/file_path.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/platform_file.h"
-#include "base/time.h"
+#include "base/time/time.h"
 
 #if defined(USE_SYSTEM_MINIZIP)
 #include <minizip/unzip.h>
diff --git a/chrome/test/chromedriver/chrome_launcher.cc b/chrome/test/chromedriver/chrome_launcher.cc
index b08d1c1..f7fb437 100644
--- a/chrome/test/chromedriver/chrome_launcher.cc
+++ b/chrome/test/chromedriver/chrome_launcher.cc
@@ -8,6 +8,7 @@
 #include <vector>
 
 #include "base/base64.h"
+#include "base/basictypes.h"
 #include "base/command_line.h"
 #include "base/file_util.h"
 #include "base/files/file_path.h"
@@ -23,7 +24,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/platform_thread.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/test/chromedriver/chrome/chrome_android_impl.h"
 #include "chrome/test/chromedriver/chrome/chrome_desktop_impl.h"
@@ -40,6 +41,9 @@
 
 namespace {
 
+const char* kCommonSwitches[] = {
+  "ignore-certificate-errors", "metrics-recording-only"};
+
 Status UnpackAutomationExtension(const base::FilePath& temp_dir,
                                  base::FilePath* automation_extension) {
   std::string decoded_extension;
@@ -194,9 +198,13 @@
   CommandLine command(CommandLine::NO_PROGRAM);
   base::ScopedTempDir user_data_dir;
   base::ScopedTempDir extension_dir;
-  PrepareCommandLine(port, capabilities,
-                     &command, &user_data_dir, &extension_dir);
-  command.AppendSwitch("ignore-certificate-errors");
+  Status status = PrepareCommandLine(port, capabilities,
+                                     &command, &user_data_dir, &extension_dir);
+  if (status.IsError())
+    return status;
+
+  for (size_t i = 0; i < arraysize(kCommonSwitches); i++)
+    command.AppendSwitch(kCommonSwitches[i]);
   base::LaunchOptions options;
 
 #if !defined(OS_WIN)
@@ -224,7 +232,7 @@
   scoped_ptr<DevToolsHttpClient> devtools_client;
   std::string version;
   int build_no;
-  Status status = WaitForDevToolsAndCheckVersion(
+  status = WaitForDevToolsAndCheckVersion(
       port, context_getter, socket_factory, log, &devtools_client, &version,
       &build_no);
 
@@ -292,7 +300,13 @@
   }
   if (!status.IsOk())
     return status;
-  status = device->StartChrome(capabilities.android_package, port);
+
+  std::string args(capabilities.android_args);
+  for (size_t i = 0; i < arraysize(kCommonSwitches); i++)
+    args += "--" + std::string(kCommonSwitches[i]) + " ";
+  args += "--disable-fre --enable-remote-debugging";
+
+  status = device->StartChrome(capabilities.android_package, port, args);
   if (!status.IsOk())
     return status;
 
diff --git a/chrome/test/chromedriver/chromedriver.cc b/chrome/test/chromedriver/chromedriver.cc
deleted file mode 100644
index 8f7ddce..0000000
--- a/chrome/test/chromedriver/chromedriver.cc
+++ /dev/null
@@ -1,125 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/test/chromedriver/chromedriver.h"
-
-#include "base/json/json_reader.h"
-#include "base/json/json_writer.h"
-#include "base/lazy_instance.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/synchronization/lock.h"
-#include "base/values.h"
-#include "chrome/test/chromedriver/chrome/status.h"
-#include "chrome/test/chromedriver/command_executor.h"
-
-namespace {
-
-// Guards |g_executor_initialized|.
-base::LazyInstance<base::Lock> g_lazy_lock = LAZY_INSTANCE_INITIALIZER;
-bool g_executor_initialized = false;
-CommandExecutor* g_command_executor = NULL;
-
-void SetResponse(StatusCode status,
-                 const base::Value* value,
-                 const std::string& session_id,
-                 std::string* response) {
-  base::DictionaryValue response_dict;
-  response_dict.SetInteger("status", status);
-  response_dict.Set("value", value->DeepCopy());
-  response_dict.SetString("sessionId", session_id);
-  std::string json;
-  base::JSONWriter::Write(&response_dict, response);
-}
-
-void SetError(const std::string& error_msg,
-              std::string* response) {
-  base::DictionaryValue value;
-  value.SetString("message", error_msg);
-  SetResponse(kUnknownError, &value, std::string(), response);
-}
-
-}  // namespace
-
-void Init(scoped_ptr<CommandExecutor> executor) {
-  g_command_executor = executor.release();
-  // We do not call CommandExecutor::Init here because you can't do some things
-  // (e.g., creating threads) during DLL loading on Windows.
-}
-
-void ExecuteCommand(const std::string& command, std::string* response) {
-  CHECK(g_command_executor);
-  {
-    base::AutoLock(g_lazy_lock.Get());
-    if (!g_executor_initialized) {
-      g_command_executor->Init();
-      g_executor_initialized = true;
-    }
-  }
-  std::string error_msg;
-  scoped_ptr<base::Value> value(base::JSONReader::ReadAndReturnError(
-      command, 0, NULL, &error_msg));
-  if (!value.get()) {
-    SetError("failed to parse command: " + error_msg, response);
-    return;
-  }
-  base::DictionaryValue* command_dict;
-  if (!value->GetAsDictionary(&command_dict)) {
-    SetError("invalid command (must be dictionary)", response);
-    return;
-  }
-  std::string name;
-  if (!command_dict->GetString("name", &name)) {
-    SetError("invalid command (must contain 'name' of type string)", response);
-    return;
-  }
-  base::DictionaryValue* params;
-  if (!command_dict->GetDictionary("parameters", &params)) {
-    SetError("invalid command (must contain 'parameters' of type dict)",
-             response);
-    return;
-  }
-  std::string session_id;
-  if (!command_dict->GetString("sessionId", &session_id)) {
-    SetError("invalid command (must contain 'sessionId' of type string)",
-             response);
-    return;
-  }
-  StatusCode out_status = kOk;
-  scoped_ptr<base::Value> out_value;
-  std::string out_session_id;
-  g_command_executor->ExecuteCommand(
-      name, *params, session_id, &out_status, &out_value, &out_session_id);
-  SetResponse(out_status, out_value.get(), out_session_id, response);
-}
-
-void Shutdown() {
-  // TODO: Move this out to a separate doc.
-  // On shutdown, it is nice to quit all running sessions so that we don't
-  // have leftover Chrome processes and temporary user data dirs.
-  // To do this, we execute the quitAll command.
-  // Alternative shutdown behaviors:
-  // 1. If the user doesn't quit the session, don't clean it up.
-  //    This is what the FF driver does, except the temp dir is
-  //    cleaned up in FF because the client side is responsible for creating
-  //    the temp directory, not the driver.
-  // 2. Separate helper process that we spawn that is in charge of
-  //    launching processes and creating temporary files. This process
-  //    communicates to the helper via a socket. The helper process
-  //    kills all processes and deletes temp files if it sees the parent
-  //    die and then exits itself. This is more complicated, but it guarantees
-  //    that the processes and temp dirs are cleaned up, even if this process
-  //    exits abnormally.
-  // 3. Add Chrome command-line switch for socket/pipe that Chrome listens
-  //    to and exits if the pipe is closed. This is how the old
-  //    TestingAutomationProvider worked. However, this doesn't clean up
-  //    temp directories, unless we make Chrome clean its own directory too.
-  //    If Chrome crashes the directory would be leaked.
-  base::DictionaryValue params;
-  StatusCode status_code;
-  scoped_ptr<base::Value> value;
-  std::string session_id;
-  g_command_executor->ExecuteCommand(
-      "quitAll", params, std::string(), &status_code, &value, &session_id);
-  delete g_command_executor;
-}
diff --git a/chrome/test/chromedriver/chromedriver.h b/chrome/test/chromedriver/chromedriver.h
deleted file mode 100644
index 3872b00..0000000
--- a/chrome/test/chromedriver/chromedriver.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_TEST_CHROMEDRIVER_CHROMEDRIVER_H_
-#define CHROME_TEST_CHROMEDRIVER_CHROMEDRIVER_H_
-
-#include <string>
-
-#include "base/memory/scoped_ptr.h"
-
-class CommandExecutor;
-
-// Inits the command executor. Must be called before |ExecuteCommand|.
-// This may be called during DLL load on Windows.
-void Init(scoped_ptr<CommandExecutor> executor);
-
-// Synchronously executes the given command. Thread safe.
-// Command must be a JSON object:
-// {
-//   "name": <string>,
-//   "parameters": <dictionary>,
-//   "sessionId": <string>
-// }
-// Response will always be a JSON object:
-// {
-//   "status": <integer>,
-//   "value": <object>,
-//   "sessionId": <string>
-// }
-// If "status" is non-zero, "value" will be an object with a string "message"
-// property which signifies the error message.
-void ExecuteCommand(const std::string& command, std::string* response);
-
-// Shuts down the command executor. No commands must be currently executing.
-void Shutdown();
-
-#endif  // CHROME_TEST_CHROMEDRIVER_CHROMEDRIVER_H_
diff --git a/chrome/test/chromedriver/chromedriver_shared_library.cc b/chrome/test/chromedriver/chromedriver_shared_library.cc
deleted file mode 100644
index 9850e2d..0000000
--- a/chrome/test/chromedriver/chromedriver_shared_library.cc
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <cstring>
-#include <string>
-
-#include "base/at_exit.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/strings/utf_string_conversions.h"
-#include "build/build_config.h"
-#include "chrome/test/chromedriver/chrome/log.h"
-#include "chrome/test/chromedriver/chromedriver.h"
-#include "chrome/test/chromedriver/command_executor.h"
-#include "chrome/test/chromedriver/command_executor_impl.h"
-
-#if defined(OS_WIN)
-#include <windows.h>
-#endif
-
-#if defined(OS_WIN)
-#define EXPORT __declspec(dllexport)
-#else
-#define EXPORT __attribute__((visibility("default")))
-#endif
-
-namespace {
-
-base::AtExitManager* g_at_exit = NULL;
-Log* g_log = NULL;
-
-}  // namespace
-
-extern "C" {
-
-// Synchronously executes the given command. Thread safe.
-// Every call dynamically allocates a |response| string, which must be
-// deallocated by calling |Free|. This |response| string is not guaranteed
-// to be null terminated, and may contain null characters within. You
-// should use the given response size to construct the string.
-void EXPORT ExecuteCommand(
-    const char* command,
-    unsigned int command_size,
-    char** response,
-    unsigned int* response_size) {
-  std::string command_str(command, command_size);
-  std::string json;
-  ExecuteCommand(command_str, &json);
-  *response = new char[json.length()];
-  std::memcpy(*response, json.c_str(), json.length());
-  *response_size = json.length();
-}
-
-void EXPORT Free(char* p) {
-  delete [] p;
-}
-
-}  // extern "C"
-
-#if defined(OS_WIN)
-BOOL APIENTRY DllMain(HMODULE module, DWORD reason, void* reserved) {
-  if (reason == DLL_PROCESS_ATTACH) {
-    g_at_exit = new base::AtExitManager();
-    g_log = new Logger();
-    Init(scoped_ptr<CommandExecutor>(new CommandExecutorImpl(g_log)));
-  }
-  if (reason == DLL_PROCESS_DETACH) {
-    // If |reserved| is not null, the process is terminating and
-    // ChromeDriver's threads have already been signaled to exit.
-    // Just leak and let the OS clean it up.
-    if (reserved)
-      return TRUE;
-    Shutdown();
-    delete g_log;
-    delete g_at_exit;
-  }
-  return TRUE;
-}
-#else
-void __attribute__((constructor)) OnLoad(void) {
-  g_at_exit = new base::AtExitManager();
-  g_log = new Logger();
-  Init(scoped_ptr<CommandExecutor>(new CommandExecutorImpl(g_log)));
-}
-void __attribute__((destructor)) OnUnload(void) {
-  Shutdown();
-  delete g_log;
-  delete g_at_exit;
-}
-#endif
diff --git a/chrome/test/chromedriver/chromedriver_unittest.cc b/chrome/test/chromedriver/chromedriver_unittest.cc
deleted file mode 100644
index 9e585e3..0000000
--- a/chrome/test/chromedriver/chromedriver_unittest.cc
+++ /dev/null
@@ -1,170 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <list>
-#include <string>
-
-#include "base/bind.h"
-#include "base/compiler_specific.h"
-#include "base/json/json_reader.h"
-#include "base/location.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/scoped_vector.h"
-#include "base/message_loop.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/thread.h"
-#include "base/values.h"
-#include "chrome/test/chromedriver/chrome/status.h"
-#include "chrome/test/chromedriver/chromedriver.h"
-#include "chrome/test/chromedriver/command_executor.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-void ExpectExecuteError(const std::string& command) {
-  std::string response;
-  ExecuteCommand(command, &response);
-  scoped_ptr<base::Value> value(base::JSONReader::Read(response));
-  ASSERT_TRUE(value.get());
-  base::DictionaryValue* dict;
-  ASSERT_TRUE(value->GetAsDictionary(&dict));
-  int status;
-  ASSERT_TRUE(dict->GetInteger("status", &status));
-  EXPECT_EQ(kUnknownError, status);
-}
-
-class DummyExecutor : public CommandExecutor {
- public:
-  virtual ~DummyExecutor() {}
-
-  virtual void Init() OVERRIDE {}
-  virtual void ExecuteCommand(const std::string& name,
-                              const base::DictionaryValue& params,
-                              const std::string& session_id,
-                              StatusCode* status,
-                              scoped_ptr<base::Value>* value,
-                              std::string* out_session_id) OVERRIDE {}
-};
-
-
-struct ExpectedCommand {
-  ExpectedCommand(
-      const std::string& name,
-      const base::DictionaryValue& in_params,
-      const std::string& session_id,
-      StatusCode return_status,
-      scoped_ptr<base::Value> return_value,
-      const std::string& return_session_id)
-      : name(name),
-        session_id(session_id),
-        return_status(return_status),
-        return_value(return_value.Pass()),
-        return_session_id(return_session_id) {
-    params.MergeDictionary(&in_params);
-  }
-
-  ~ExpectedCommand() {}
-
-  std::string name;
-  base::DictionaryValue params;
-  std::string session_id;
-  StatusCode return_status;
-  scoped_ptr<base::Value> return_value;
-  std::string return_session_id;
-};
-
-class ExecutorMock : public CommandExecutor {
- public:
-  virtual ~ExecutorMock() {
-    EXPECT_TRUE(DidSatisfyExpectations());
-  }
-
-  virtual void Init() OVERRIDE {}
-
-  virtual void ExecuteCommand(const std::string& name,
-                              const base::DictionaryValue& params,
-                              const std::string& session_id,
-                              StatusCode* status,
-                              scoped_ptr<base::Value>* value,
-                              std::string* out_session_id) OVERRIDE {
-    ASSERT_TRUE(expectations_.size());
-    ASSERT_STREQ(expectations_[0]->name.c_str(), name.c_str());
-    ASSERT_TRUE(expectations_[0]->params.Equals(&params));
-    ASSERT_STREQ(expectations_[0]->session_id.c_str(), session_id.c_str());
-    *status = expectations_[0]->return_status;
-    value->reset(expectations_[0]->return_value.release());
-    *out_session_id = expectations_[0]->return_session_id;
-    expectations_.erase(expectations_.begin());
-  }
-
-  void Expect(scoped_ptr<ExpectedCommand> expected) {
-    expectations_.push_back(expected.release());
-  }
-
-  bool DidSatisfyExpectations() const {
-    return expectations_.empty();
-  }
-
- private:
-  ScopedVector<ExpectedCommand> expectations_;
-};
-
-}  // namespace
-
-TEST(ChromeDriver, InvalidCommands) {
-  Init(scoped_ptr<CommandExecutor>(new DummyExecutor()));
-  ExpectExecuteError("hi[]");
-  ExpectExecuteError("[]");
-  ExpectExecuteError(
-      "{\"parameters\": {}, \"sessionId\": \"\"}");
-  ExpectExecuteError(
-      "{\"name\": 1, \"parameters\": {}, \"sessionId\": \"\"}");
-  ExpectExecuteError(
-      "{\"name\": \"\", \"sessionId\": \"\"}");
-  ExpectExecuteError(
-      "{\"name\": \"\", \"parameters\": 1, \"sessionId\": \"\"}");
-  ExpectExecuteError(
-      "{\"name\": \"\", \"parameters\": {}}");
-  ExpectExecuteError(
-      "{\"name\": \"\", \"parameters\": {}, \"sessionId\": 1}");
-  Shutdown();
-}
-
-TEST(ChromeDriver, ExecuteCommand) {
-  scoped_ptr<ExecutorMock> scoped_mock(new ExecutorMock());
-  ExecutorMock* mock = scoped_mock.get();
-  Init(scoped_mock.PassAs<CommandExecutor>());
-  {
-    base::DictionaryValue params;
-    params.SetInteger("param", 100);
-    scoped_ptr<base::Value> value(new base::StringValue("stuff"));
-    mock->Expect(scoped_ptr<ExpectedCommand>(new ExpectedCommand(
-        "name", params, "id", kOk, value.Pass(), "session_id")));
-  }
-  std::string response;
-  ExecuteCommand("{\"name\": \"name\", "
-                 " \"parameters\": {\"param\": 100}, "
-                 " \"sessionId\": \"id\"}",
-                 &response);
-  ASSERT_TRUE(mock->DidSatisfyExpectations());
-  {
-    scoped_ptr<base::Value> value(base::JSONReader::Read(response));
-    ASSERT_TRUE(value.get());
-    base::DictionaryValue* dict;
-    ASSERT_TRUE(value->GetAsDictionary(&dict));
-    int status;
-    ASSERT_TRUE(dict->GetInteger("status", &status));
-    std::string value_str;
-    ASSERT_TRUE(dict->GetString("value", &value_str));
-    EXPECT_STREQ("stuff", value_str.c_str());
-    EXPECT_EQ(kOk, status);
-  }
-  {
-    base::DictionaryValue params;
-    scoped_ptr<base::Value> value(base::Value::CreateNullValue());
-    mock->Expect(scoped_ptr<ExpectedCommand>(new ExpectedCommand(
-        "quitAll", params, std::string(), kOk, value.Pass(), std::string())));
-  }
-  Shutdown();
-}
diff --git a/chrome/test/chromedriver/command_executor.h b/chrome/test/chromedriver/command_executor.h
deleted file mode 100644
index e5d60c6..0000000
--- a/chrome/test/chromedriver/command_executor.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_TEST_CHROMEDRIVER_COMMAND_EXECUTOR_H_
-#define CHROME_TEST_CHROMEDRIVER_COMMAND_EXECUTOR_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/threading/non_thread_safe.h"
-#include "chrome/test/chromedriver/chrome/status.h"
-
-namespace base {
-class DictionaryValue;
-class Value;
-}
-
-// Executes WebDriver commands.
-class CommandExecutor {
- public:
-  virtual ~CommandExecutor() {}
-
-  virtual void Init() = 0;
-
-  // Executes a command synchronously. This function must be thread safe.
-  virtual void ExecuteCommand(const std::string& name,
-                              const base::DictionaryValue& params,
-                              const std::string& session_id,
-                              StatusCode* status_code,
-                              scoped_ptr<base::Value>* value,
-                              std::string* out_session_id) = 0;
-};
-
-#endif  // CHROME_TEST_CHROMEDRIVER_COMMAND_EXECUTOR_H_
diff --git a/chrome/test/chromedriver/command_executor_impl.h b/chrome/test/chromedriver/command_executor_impl.h
deleted file mode 100644
index fa8312b..0000000
--- a/chrome/test/chromedriver/command_executor_impl.h
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_TEST_CHROMEDRIVER_COMMAND_EXECUTOR_IMPL_H_
-#define CHROME_TEST_CHROMEDRIVER_COMMAND_EXECUTOR_IMPL_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/callback_forward.h"
-#include "base/compiler_specific.h"
-#include "base/gtest_prod_util.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/threading/thread.h"
-#include "chrome/test/chromedriver/chrome/status.h"
-#include "chrome/test/chromedriver/command.h"
-#include "chrome/test/chromedriver/command_executor.h"
-#include "chrome/test/chromedriver/net/sync_websocket_factory.h"
-#include "chrome/test/chromedriver/session_map.h"
-#include "chrome/test/chromedriver/synchronized_map.h"
-
-namespace base {
-class DictionaryValue;
-class Value;
-}
-
-class Adb;
-class ChromeLauncherImpl;
-class DeviceManager;
-class Log;
-class URLRequestContextGetter;
-
-class CommandExecutorImpl : public CommandExecutor {
- public:
-  explicit CommandExecutorImpl(Log* log);
-  virtual ~CommandExecutorImpl();
-
-  // Overridden from CommandExecutor:
-  virtual void Init() OVERRIDE;
-  virtual void ExecuteCommand(const std::string& name,
-                              const base::DictionaryValue& params,
-                              const std::string& session_id,
-                              StatusCode* status_code,
-                              scoped_ptr<base::Value>* value,
-                              std::string* out_session_id) OVERRIDE;
-
- private:
-  FRIEND_TEST_ALL_PREFIXES(CommandExecutorImplTest, SimpleCommand);
-  FRIEND_TEST_ALL_PREFIXES(
-      CommandExecutorImplTest, CommandThatDoesntSetValueOrSessionId);
-  FRIEND_TEST_ALL_PREFIXES(CommandExecutorImplTest, CommandThatReturnsError);
-
-  Log* log_;
-  base::Thread io_thread_;
-  scoped_refptr<URLRequestContextGetter> context_getter_;
-  SyncWebSocketFactory socket_factory_;
-  SessionMap session_map_;
-  SynchronizedMap<std::string, Command> command_map_;
-  scoped_ptr<Adb> adb_;
-  scoped_ptr<DeviceManager> device_manager_;
-
-  DISALLOW_COPY_AND_ASSIGN(CommandExecutorImpl);
-};
-
-#endif  // CHROME_TEST_CHROMEDRIVER_COMMAND_EXECUTOR_IMPL_H_
diff --git a/chrome/test/chromedriver/command_names.cc b/chrome/test/chromedriver/command_names.cc
deleted file mode 100644
index e90add6..0000000
--- a/chrome/test/chromedriver/command_names.cc
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/test/chromedriver/command_names.h"
-
-const char CommandNames::kNewSession[] = "newSession";
-const char CommandNames::kStatus[] = "status";
-const char CommandNames::kClose[] = "close";
-const char CommandNames::kQuit[] = "quit";
-const char CommandNames::kGet[] = "get";
-const char CommandNames::kGoBack[] = "goBack";
-const char CommandNames::kGoForward[] = "goForward";
-const char CommandNames::kRefresh[] = "refresh";
-const char CommandNames::kAddCookie[] = "addCookie";
-const char CommandNames::kGetCookie[] = "getCookie";
-const char CommandNames::kGetCookies[] = "getCookies";
-const char CommandNames::kDeleteCookie[] = "deleteCookie";
-const char CommandNames::kDeleteAllCookies[] = "deleteAllCookies";
-const char CommandNames::kFindElement[] = "findElement";
-const char CommandNames::kFindElements[] = "findElements";
-const char CommandNames::kFindChildElement[] = "findChildElement";
-const char CommandNames::kFindChildElements[] = "findChildElements";
-const char CommandNames::kClearElement[] = "clearElement";
-const char CommandNames::kClickElement[] = "clickElement";
-const char CommandNames::kHoverOverElement[] = "hoverOverElement";
-const char CommandNames::kSendKeysToElement[] = "sendKeysToElement";
-const char CommandNames::kSendKeysToActiveElement[] = "sendKeysToActiveElement";
-const char CommandNames::kSubmitElement[] = "submitElement";
-const char CommandNames::kUploadFile[] = "uploadFile";
-const char CommandNames::kGetCurrentWindowHandle[] = "getCurrentWindowHandle";
-const char CommandNames::kGetWindowHandles[] = "getWindowHandles";
-const char CommandNames::kSwitchToWindow[] = "switchToWindow";
-const char CommandNames::kSwitchToFrame[] = "switchToFrame";
-const char CommandNames::kGetActiveElement[] = "getActiveElement";
-const char CommandNames::kGetCurrentUrl[] = "getCurrentUrl";
-const char CommandNames::kGetPageSource[] = "getPageSource";
-const char CommandNames::kGetTitle[] = "getTitle";
-const char CommandNames::kExecuteScript[] = "executeScript";
-const char CommandNames::kExecuteAsyncScript[] = "executeAsyncScript";
-const char CommandNames::kSetBrowserVisible[] = "setBrowserVisible";
-const char CommandNames::kIsBrowserVisible[] = "isBrowserVisible";
-const char CommandNames::kGetElementText[] = "getElementText";
-const char CommandNames::kGetElementValue[] = "getElementValue";
-const char CommandNames::kGetElementTagName[] = "getElementTagName";
-const char CommandNames::kDragElement[] = "dragElement";
-const char CommandNames::kIsElementSelected[] = "isElementSelected";
-const char CommandNames::kIsElementEnabled[] = "isElementEnabled";
-const char CommandNames::kIsElementDisplayed[] = "isElementDisplayed";
-const char CommandNames::kGetElementLocation[] = "getElementLocation";
-const char CommandNames::kGetElementLocationOnceScrolledIntoView[] =
-    "getElementLocationOnceScrolledIntoView";
-const char CommandNames::kGetElementSize[] = "getElementSize";
-const char CommandNames::kGetElementAttribute[] = "getElementAttribute";
-const char CommandNames::kGetElementValueOfCssProperty[] =
-    "getElementValueOfCssProperty";
-const char CommandNames::kElementEquals[] = "elementEquals";
-const char CommandNames::kScreenshot[] = "screenshot";
-const char CommandNames::kGetAlert[] = "getAlert";
-const char CommandNames::kAcceptAlert[] = "acceptAlert";
-const char CommandNames::kDismissAlert[] = "dismissAlert";
-const char CommandNames::kGetAlertText[] = "getAlertText";
-const char CommandNames::kSetAlertValue[] = "setAlertValue";
-const char CommandNames::kSetTimeout[] = "setTimeout";
-const char CommandNames::kImplicitlyWait[] = "implicitlyWait";
-const char CommandNames::kSetScriptTimeout[] = "setScriptTimeout";
-const char CommandNames::kExecuteSQL[] = "executeSQL";
-const char CommandNames::kGetLocation[] = "getLocation";
-const char CommandNames::kSetLocation[] = "setLocation";
-const char CommandNames::kGetAppCache[] = "getAppCache";
-const char CommandNames::kGetStatus[] = "getStatus";
-const char CommandNames::kClearAppCache[] = "clearAppCache";
-const char CommandNames::kIsBrowserOnline[] = "isBrowserOnline";
-const char CommandNames::kSetBrowserOnline[] = "setBrowserOnline";
-const char CommandNames::kGetLocalStorageItem[] = "getLocalStorageItem";
-const char CommandNames::kGetLocalStorageKeys[] = "getLocalStorageKeys";
-const char CommandNames::kSetLocalStorageItem[] = "setLocalStorageItem";
-const char CommandNames::kRemoveLocalStorageItem[] = "removeLocalStorageItem";
-const char CommandNames::kClearLocalStorage[] = "clearLocalStorage";
-const char CommandNames::kGetLocalStorageSize[] = "getLocalStorageSize";
-const char CommandNames::kGetSessionStorageItem[] = "getSessionStorageItem";
-const char CommandNames::kGetSessionStorageKey[] = "getSessionStorageKey";
-const char CommandNames::kSetSessionStorageItem[] = "setSessionStorageItem";
-const char CommandNames::kRemoveSessionStorageItem[] =
-    "removeSessionStorageItem";
-const char CommandNames::kClearSessionStorage[] = "clearSessionStorage";
-const char CommandNames::kGetSessionStorageSize[] = "getSessionStorageSize";
-const char CommandNames::kSetScreenOrientation[] = "setScreenOrientation";
-const char CommandNames::kGetScreenOrientation[] = "getScreenOrientation";
-const char CommandNames::kMouseClick[] = "mouseClick";
-const char CommandNames::kMouseDoubleClick[] = "mouseDoubleClick";
-const char CommandNames::kMouseButtonDown[] = "mouseButtonDown";
-const char CommandNames::kMouseButtonUp[] = "mouseButtonUp";
-const char CommandNames::kMouseMoveTo[] = "mouseMoveTo";
-const char CommandNames::kSendKeys[] = "sendKeys";
-const char CommandNames::kImeGetAvailableEngines[] = "imeGetAvailableEngines";
-const char CommandNames::kImeGetActiveEngine[] = "imeGetActiveEngine";
-const char CommandNames::kImeIsActivated[] = "imeIsActivated";
-const char CommandNames::kImeDeactivate[] = "imeDeactivate";
-const char CommandNames::kImeActivateEngine[] = "imeActivateEngine";
-const char CommandNames::kTouchSingleTap[] = "touchSingleTap";
-const char CommandNames::kTouchDown[] = "touchDown";
-const char CommandNames::kTouchUp[] = "touchUp";
-const char CommandNames::kTouchMove[] = "touchMove";
-const char CommandNames::kTouchScroll[] = "touchScroll";
-const char CommandNames::kTouchDoubleTap[] = "touchDoubleTap";
-const char CommandNames::kTouchLongPress[] = "touchLongPress";
-const char CommandNames::kTouchFlick[] = "touchFlick";
-const char CommandNames::kSetWindowSize[] = "setWindowSize";
-const char CommandNames::kSetWindowPosition[] = "setWindowPosition";
-const char CommandNames::kGetWindowSize[] = "getWindowSize";
-const char CommandNames::kGetWindowPosition[] = "getWindowPosition";
-const char CommandNames::kMaximizeWindow[] = "maximizeWindow";
-const char CommandNames::kGetAvailableLogTypes[] = "getAvailableLogTypes";
-const char CommandNames::kGetLog[] = "getLog";
-const char CommandNames::kGetSessionLogs[] = "getSessionLogs";
-
-// Custom Chrome commands:
-const char CommandNames::kQuitAll[] = "quitAll";
-const char CommandNames::kGetSessionCapabilities[] = "getSessionCapabilities";
-const char CommandNames::kIsLoading[] = "isLoading";
diff --git a/chrome/test/chromedriver/command_names.h b/chrome/test/chromedriver/command_names.h
deleted file mode 100644
index 4626463..0000000
--- a/chrome/test/chromedriver/command_names.h
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_TEST_CHROMEDRIVER_COMMAND_NAMES_H_
-#define CHROME_TEST_CHROMEDRIVER_COMMAND_NAMES_H_
-
-class CommandNames {
- public:
-  static const char kNewSession[];
-  static const char kStatus[];
-  static const char kClose[];
-  static const char kQuit[];
-  static const char kGet[];
-  static const char kGoBack[];
-  static const char kGoForward[];
-  static const char kRefresh[];
-  static const char kAddCookie[];
-  static const char kGetCookie[];
-  static const char kGetCookies[];
-  static const char kDeleteCookie[];
-  static const char kDeleteAllCookies[];
-  static const char kFindElement[];
-  static const char kFindElements[];
-  static const char kFindChildElement[];
-  static const char kFindChildElements[];
-  static const char kClearElement[];
-  static const char kClickElement[];
-  static const char kHoverOverElement[];
-  static const char kSendKeysToElement[];
-  static const char kSendKeysToActiveElement[];
-  static const char kSubmitElement[];
-  static const char kUploadFile[];
-  static const char kGetCurrentWindowHandle[];
-  static const char kGetWindowHandles[];
-  static const char kSwitchToWindow[];
-  static const char kSwitchToFrame[];
-  static const char kGetActiveElement[];
-  static const char kGetCurrentUrl[];
-  static const char kGetPageSource[];
-  static const char kGetTitle[];
-  static const char kExecuteScript[];
-  static const char kExecuteAsyncScript[];
-  static const char kSetBrowserVisible[];
-  static const char kIsBrowserVisible[];
-  static const char kGetElementText[];
-  static const char kGetElementValue[];
-  static const char kGetElementTagName[];
-  static const char kDragElement[];
-  static const char kIsElementSelected[];
-  static const char kIsElementEnabled[];
-  static const char kIsElementDisplayed[];
-  static const char kGetElementLocation[];
-  static const char kGetElementLocationOnceScrolledIntoView[];
-  static const char kGetElementSize[];
-  static const char kGetElementAttribute[];
-  static const char kGetElementValueOfCssProperty[];
-  static const char kElementEquals[];
-  static const char kScreenshot[];
-  static const char kGetAlert[];
-  static const char kAcceptAlert[];
-  static const char kDismissAlert[];
-  static const char kGetAlertText[];
-  static const char kSetAlertValue[];
-  static const char kSetTimeout[];
-  static const char kImplicitlyWait[];
-  static const char kSetScriptTimeout[];
-  static const char kExecuteSQL[];
-  static const char kGetLocation[];
-  static const char kSetLocation[];
-  static const char kGetAppCache[];
-  static const char kGetStatus[];
-  static const char kClearAppCache[];
-  static const char kIsBrowserOnline[];
-  static const char kSetBrowserOnline[];
-  static const char kGetLocalStorageItem[];
-  static const char kGetLocalStorageKeys[];
-  static const char kSetLocalStorageItem[];
-  static const char kRemoveLocalStorageItem[];
-  static const char kClearLocalStorage[];
-  static const char kGetLocalStorageSize[];
-  static const char kGetSessionStorageItem[];
-  static const char kGetSessionStorageKey[];
-  static const char kSetSessionStorageItem[];
-  static const char kRemoveSessionStorageItem[];
-  static const char kClearSessionStorage[];
-  static const char kGetSessionStorageSize[];
-  static const char kSetScreenOrientation[];
-  static const char kGetScreenOrientation[];
-  static const char kMouseClick[];
-  static const char kMouseDoubleClick[];
-  static const char kMouseButtonDown[];
-  static const char kMouseButtonUp[];
-  static const char kMouseMoveTo[];
-  static const char kSendKeys[];
-  static const char kImeGetAvailableEngines[];
-  static const char kImeGetActiveEngine[];
-  static const char kImeIsActivated[];
-  static const char kImeDeactivate[];
-  static const char kImeActivateEngine[];
-  static const char kTouchSingleTap[];
-  static const char kTouchDown[];
-  static const char kTouchUp[];
-  static const char kTouchMove[];
-  static const char kTouchScroll[];
-  static const char kTouchDoubleTap[];
-  static const char kTouchLongPress[];
-  static const char kTouchFlick[];
-  static const char kSetWindowSize[];
-  static const char kSetWindowPosition[];
-  static const char kGetWindowSize[];
-  static const char kGetWindowPosition[];
-  static const char kMaximizeWindow[];
-  static const char kGetAvailableLogTypes[];
-  static const char kGetLog[];
-  static const char kGetSessionLogs[];
-
-  // Custom Chrome commands:
-  static const char kQuitAll[];
-  static const char kGetSessionCapabilities[];
-  static const char kIsLoading[];
-};
-
-#endif  // CHROME_TEST_CHROMEDRIVER_COMMAND_NAMES_H_
diff --git a/chrome/test/chromedriver/commands_unittest.cc b/chrome/test/chromedriver/commands_unittest.cc
index 977fb8b..5e7ea33 100644
--- a/chrome/test/chromedriver/commands_unittest.cc
+++ b/chrome/test/chromedriver/commands_unittest.cc
@@ -15,7 +15,6 @@
 #include "chrome/test/chromedriver/chrome/stub_chrome.h"
 #include "chrome/test/chromedriver/chrome/stub_web_view.h"
 #include "chrome/test/chromedriver/chrome/web_view.h"
-#include "chrome/test/chromedriver/command_executor_impl.h"
 #include "chrome/test/chromedriver/commands.h"
 #include "chrome/test/chromedriver/element_commands.h"
 #include "chrome/test/chromedriver/fake_session_accessor.h"
diff --git a/chrome/test/chromedriver/element_commands.cc b/chrome/test/chromedriver/element_commands.cc
index 5147986..262cfdc 100644
--- a/chrome/test/chromedriver/element_commands.cc
+++ b/chrome/test/chromedriver/element_commands.cc
@@ -12,7 +12,7 @@
 #include "base/strings/string_split.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/platform_thread.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/test/chromedriver/basic_types.h"
 #include "chrome/test/chromedriver/chrome/chrome.h"
diff --git a/chrome/test/chromedriver/element_util.cc b/chrome/test/chromedriver/element_util.cc
index 734fd09..ccf5409 100644
--- a/chrome/test/chromedriver/element_util.cc
+++ b/chrome/test/chromedriver/element_util.cc
@@ -8,7 +8,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/platform_thread.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/test/chromedriver/basic_types.h"
 #include "chrome/test/chromedriver/chrome/js.h"
@@ -127,7 +127,7 @@
     const std::string& element_id,
     const WebRect& region,
     bool center,
-    bool verify_clickable,
+    const std::string& clickable_element_id,
     WebPoint* location) {
   WebPoint tmp_location = *location;
   base::ListValue args;
@@ -144,10 +144,11 @@
     return Status(kUnknownError,
                   "failed to parse value of GET_LOCATION_IN_VIEW");
   }
-  if (verify_clickable) {
+  if (!clickable_element_id.empty()) {
     WebPoint middle = tmp_location;
     middle.Offset(region.Width() / 2, region.Height() / 2);
-    status = VerifyElementClickable(frame, web_view, element_id, middle);
+    status = VerifyElementClickable(
+        frame, web_view, clickable_element_id, middle);
     if (status.IsError())
       return status;
   }
@@ -324,9 +325,44 @@
     WebView* web_view,
     const std::string& element_id,
     WebPoint* location) {
+  std::string tag_name;
+  Status status = GetElementTagName(session, web_view, element_id, &tag_name);
+  if (status.IsError())
+    return status;
+  std::string target_element_id = element_id;
+  if (tag_name == "area") {
+    // Scroll the image into view instead of the area.
+    const char* kGetImageElementForArea =
+        "function (element) {"
+        "  var map = element.parentElement;"
+        "  if (map.tagName.toLowerCase() != 'map')"
+        "    throw new Error('the area is not within a map');"
+        "  var mapName = map.getAttribute('name');"
+        "  if (mapName == null)"
+        "    throw new Error ('area\\'s parent map must have a name');"
+        "  mapName = '#' + mapName.toLowerCase();"
+        "  var images = document.getElementsByTagName('img');"
+        "  for (var i = 0; i < images.length; i++) {"
+        "    if (images[i].useMap.toLowerCase() == mapName)"
+        "      return images[i];"
+        "  }"
+        "  throw new Error('no img is found for the area');"
+        "}";
+    base::ListValue args;
+    args.Append(CreateElement(element_id));
+    scoped_ptr<base::Value> result;
+    status = web_view->CallFunction(
+        session->GetCurrentFrameId(), kGetImageElementForArea, args, &result);
+    if (status.IsError())
+      return status;
+    const base::DictionaryValue* element_dict;
+    if (!result->GetAsDictionary(&element_dict) ||
+        !element_dict->GetString(kElementKey, &target_element_id))
+      return Status(kUnknownError, "no element reference returned by script");
+  }
   bool is_displayed = false;
-  Status status = IsElementDisplayed(
-      session, web_view, element_id, true, &is_displayed);
+  status = IsElementDisplayed(
+      session, web_view, target_element_id, true, &is_displayed);
   if (status.IsError())
     return status;
   if (!is_displayed)
@@ -338,8 +374,8 @@
     return status;
 
   status = ScrollElementRegionIntoView(
-      session, web_view, element_id, rect,
-      true /* center */, true /* verify_clickable */, location);
+      session, web_view, target_element_id, rect,
+      true /* center */, element_id, location);
   if (status.IsError())
     return status;
   location->Offset(rect.Width() / 2, rect.Height() / 2);
@@ -524,7 +560,7 @@
     return status;
   return ScrollElementRegionIntoView(
       session, web_view, id, WebRect(WebPoint(0, 0), size),
-      false /* center */, false /* verify_clickable */, location);
+      false /* center */, std::string(), location);
 }
 
 Status ScrollElementRegionIntoView(
@@ -533,13 +569,13 @@
     const std::string& element_id,
     const WebRect& region,
     bool center,
-    bool verify_clickable,
+    const std::string& clickable_element_id,
     WebPoint* location) {
   WebPoint region_offset = region.origin;
   WebSize region_size = region.size;
   Status status = ScrollElementRegionIntoViewHelper(
       session->GetCurrentFrameId(), web_view, element_id, region,
-      center, verify_clickable, &region_offset);
+      center, clickable_element_id, &region_offset);
   if (status.IsError())
     return status;
   const char* kFindSubFrameScript =
@@ -578,7 +614,7 @@
     status = ScrollElementRegionIntoViewHelper(
         rit->parent_frame_id, web_view, frame_element_id,
         WebRect(region_offset, region_size),
-        center, verify_clickable, &region_offset);
+        center, frame_element_id, &region_offset);
     if (status.IsError())
       return status;
   }
diff --git a/chrome/test/chromedriver/element_util.h b/chrome/test/chromedriver/element_util.h
index 5c54364..86bb2d1 100644
--- a/chrome/test/chromedriver/element_util.h
+++ b/chrome/test/chromedriver/element_util.h
@@ -119,16 +119,21 @@
 Status ScrollElementIntoView(
     Session* session,
     WebView* web_view,
-    const std::string& id,
+    const std::string& element_id,
     WebPoint* location);
 
+// |element_id| refers to the element which is to be scrolled into view.
+// |clickable_element_id| refers to the element needing clickable verification.
+// They are usually the same, but can be different. This is useful when an image
+// uses map/area. The image is scrolled, but check clickable against the area.
+// If |clickable_element_id| is "", no verification will be performed.
 Status ScrollElementRegionIntoView(
     Session* session,
     WebView* web_view,
     const std::string& element_id,
     const WebRect& region,
     bool center,
-    bool verify_clickable,
+    const std::string& clickable_element_id,
     WebPoint* location);
 
 #endif  // CHROME_TEST_CHROMEDRIVER_ELEMENT_UTIL_H_
diff --git a/chrome/test/chromedriver/js/get_element_region.js b/chrome/test/chromedriver/js/get_element_region.js
index f83b35b..19cf11c 100644
--- a/chrome/test/chromedriver/js/get_element_region.js
+++ b/chrome/test/chromedriver/js/get_element_region.js
@@ -13,6 +13,58 @@
   var clientRects = element.getClientRects();
   if (clientRects.length == 0) {
     var box = element.getBoundingClientRect();
+    if (element.tagName.toLowerCase() == 'area') {
+      var coords = element.coords.split(',');
+      if (element.shape.toLowerCase() == 'rect') {
+        if (coords.length != 4)
+          throw new Error('failed to detect the region of the area');
+        var leftX = Number(coords[0]);
+        var topY = Number(coords[1]);
+        var rightX = Number(coords[2]);
+        var bottomY = Number(coords[3]);
+        return {
+            'left': leftX,
+            'top': topY,
+            'width': rightX - leftX,
+            'height': bottomY - topY
+        };
+      } else if (element.shape.toLowerCase() == 'circle') {
+        if (coords.length != 3)
+          throw new Error('failed to detect the region of the area');
+        var centerX = Number(coords[0]);
+        var centerY = Number(coords[1]);
+        var radius = Number(coords[2]);
+        return {
+            'left': Math.max(0, centerX - radius),
+            'top': Math.max(0, centerY - radius),
+            'width': radius * 2,
+            'height': radius * 2
+        };
+      } else if (element.shape.toLowerCase() == 'poly') {
+        if (coords.length < 2)
+          throw new Error('failed to detect the region of the area');
+        var minX = Number(coords[0]);
+        var minY = Number(coords[1]);
+        var maxX = minX;
+        var maxY = minY;
+        for (i = 2; i < coords.length; i += 2) {
+          var x = Number(coords[i]);
+          var y = Number(coords[i + 1]);
+          minX = Math.min(minX, x);
+          minY = Math.min(minY, y);
+          maxX = Math.max(maxX, x);
+          maxY = Math.max(maxY, y);
+        }
+        return {
+            'left': minX,
+            'top': minY,
+            'width': maxX - minX,
+            'height': maxY - minY
+        };
+      } else {
+        throw new Error('shape=' + element.shape + ' is not supported');
+      }
+    }
     return {
         'left': 0,
         'top': 0,
diff --git a/chrome/test/chromedriver/js/get_element_region_test.html b/chrome/test/chromedriver/js/get_element_region_test.html
index e17ea2c..9dd42e0 100644
--- a/chrome/test/chromedriver/js/get_element_region_test.html
+++ b/chrome/test/chromedriver/js/get_element_region_test.html
@@ -37,6 +37,38 @@
   assertEquals(0, region.height);
 }
 
+function testAreaPoly() {
+  var region = getElementRegion(document.getElementById('poly'));
+  assertEquals(20, region.left);
+  assertEquals(10, region.top);
+  assertEquals(40, region.width);
+  assertEquals(45, region.height);
+}
+
+function testAreaRect() {
+  var region = getElementRegion(document.getElementById('rect'));
+  assertEquals(120, region.left);
+  assertEquals(100, region.top);
+  assertEquals(20, region.width);
+  assertEquals(50, region.height);
+}
+
+function testAreaCircle() {
+  var region = getElementRegion(document.getElementById('circle'));
+  assertEquals(175, region.left);
+  assertEquals(165, region.top);
+  assertEquals(10, region.width);
+  assertEquals(10, region.height);
+}
+
+function testAreaDefault() {
+  try {
+    getElementRegion(document.getElementById('default'));
+    assert(false);
+  } catch (error) {
+  }
+}
+
 </script>
 <body>
 <div style="border: 3px coral solid;">
@@ -49,6 +81,16 @@
       </ellipse>
     </svg>
   </div>
+  <br>
+  <div>
+    <img width="200" height="200" usemap="#imgmap">
+    <map name="imgmap">
+      <area id="poly" shape="poly" coords="20,20,30,10,50,20,60,40,50,50,30,55">
+      <area id="rect" shape="rect" coords="120,100,140,150">
+      <area id="circle" shape="circle" coords="180,170,5">
+      <area id="default" shape="default">
+    </map>
+  </div>
 </div>
 </body>
 </html>
diff --git a/chrome/test/chromedriver/keycode_text_conversion_mac.mm b/chrome/test/chromedriver/keycode_text_conversion_mac.mm
index 4b02ace..d83df65 100644
--- a/chrome/test/chromedriver/keycode_text_conversion_mac.mm
+++ b/chrome/test/chromedriver/keycode_text_conversion_mac.mm
@@ -44,7 +44,7 @@
   // on UCKeyTranslate for more info.
   UInt32 modifier_key_state = (mac_modifiers >> 8) & 0xFF;
 
-  base::mac::ScopedCFTypeRef<TISInputSourceRef> input_source_copy(
+  base::ScopedCFTypeRef<TISInputSourceRef> input_source_copy(
       TISCopyCurrentKeyboardLayoutInputSource());
   CFDataRef layout_data = static_cast<CFDataRef>(TISGetInputSourceProperty(
       input_source_copy, kTISPropertyUnicodeKeyLayoutData));
diff --git a/chrome/test/chromedriver/logging.cc b/chrome/test/chromedriver/logging.cc
index 607cbfe..bf0a50a 100644
--- a/chrome/test/chromedriver/logging.cc
+++ b/chrome/test/chromedriver/logging.cc
@@ -6,7 +6,7 @@
 
 #include "base/basictypes.h"
 #include "base/logging.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/test/chromedriver/capabilities.h"
 #include "chrome/test/chromedriver/chrome/console_logger.h"
 #include "chrome/test/chromedriver/chrome/performance_logger.h"
diff --git a/chrome/test/chromedriver/net/sync_websocket.h b/chrome/test/chromedriver/net/sync_websocket.h
index 6835c69..5dd59da 100644
--- a/chrome/test/chromedriver/net/sync_websocket.h
+++ b/chrome/test/chromedriver/net/sync_websocket.h
@@ -7,7 +7,7 @@
 
 #include <string>
 
-#include "base/time.h"
+#include "base/time/time.h"
 
 class GURL;
 
diff --git a/chrome/test/chromedriver/net/sync_websocket_impl_unittest.cc b/chrome/test/chromedriver/net/sync_websocket_impl_unittest.cc
index e9daca6..218c597 100644
--- a/chrome/test/chromedriver/net/sync_websocket_impl_unittest.cc
+++ b/chrome/test/chromedriver/net/sync_websocket_impl_unittest.cc
@@ -11,7 +11,7 @@
 #include "base/single_thread_task_runner.h"
 #include "base/threading/platform_thread.h"
 #include "base/threading/thread.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/test/chromedriver/net/sync_websocket_impl.h"
 #include "chrome/test/chromedriver/net/test_http_server.h"
 #include "chrome/test/chromedriver/net/url_request_context_getter.h"
diff --git a/chrome/test/chromedriver/net/test_http_server.cc b/chrome/test/chromedriver/net/test_http_server.cc
index 486e1b9..f776844 100644
--- a/chrome/test/chromedriver/net/test_http_server.cc
+++ b/chrome/test/chromedriver/net/test_http_server.cc
@@ -9,7 +9,7 @@
 #include "base/message_loop.h"
 #include "base/message_loop/message_loop_proxy.h"
 #include "base/strings/stringprintf.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "net/base/ip_endpoint.h"
 #include "net/base/net_errors.h"
 #include "net/server/http_server_request_info.h"
diff --git a/chrome/test/chromedriver/net/websocket_unittest.cc b/chrome/test/chromedriver/net/websocket_unittest.cc
index f665c84..3176430 100644
--- a/chrome/test/chromedriver/net/websocket_unittest.cc
+++ b/chrome/test/chromedriver/net/websocket_unittest.cc
@@ -15,7 +15,7 @@
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/test/chromedriver/net/test_http_server.h"
 #include "chrome/test/chromedriver/net/websocket.h"
 #include "googleurl/src/gurl.h"
diff --git a/chrome/test/chromedriver/run_all_tests.py b/chrome/test/chromedriver/run_all_tests.py
index 30eadd5..574fa92 100755
--- a/chrome/test/chromedriver/run_all_tests.py
+++ b/chrome/test/chromedriver/run_all_tests.py
@@ -104,6 +104,11 @@
   return code
 
 
+def DownloadChrome(version_name, revision, download_site):
+  util.MarkBuildStepStart('download %s' % version_name)
+  return archive.DownloadChrome(revision, util.MakeTempDir(), download_site)
+
+
 def main():
   parser = optparse.OptionParser()
   parser.add_option(
@@ -159,6 +164,7 @@
     latest_snapshot_revision = archive.GetLatestRevision(archive.Site.SNAPSHOT)
     versions = [
         ['HEAD', latest_snapshot_revision],
+        ['29', archive.CHROME_29_REVISION],
         ['28', archive.CHROME_28_REVISION],
         ['27', archive.CHROME_27_REVISION]
     ]
@@ -171,9 +177,7 @@
       if version_name == 'HEAD':
         version_name = version[1]
         download_site = archive.Site.SNAPSHOT
-      chrome_path = archive.DownloadChrome(version[1],
-                                           util.MakeTempDir(),
-                                           download_site)
+      chrome_path = DownloadChrome(version_name, version[1], download_site)
       code1 = RunPythonTests(chromedriver,
                              ref_chromedriver,
                              chrome=chrome_path,
diff --git a/chrome/test/chromedriver/run_py_tests.py b/chrome/test/chromedriver/run_py_tests.py
index 3752c5e..440a3fb 100755
--- a/chrome/test/chromedriver/run_py_tests.py
+++ b/chrome/test/chromedriver/run_py_tests.py
@@ -70,12 +70,12 @@
         'ChromeDriverTest.testSingleTapElement',
     ]
 )
-_DESKTOP_NEGATIVE_FILTER['28'] = (
-    _DESKTOP_NEGATIVE_FILTER['HEAD'] + []
-)
-_DESKTOP_NEGATIVE_FILTER['27'] = (
-    _DESKTOP_NEGATIVE_FILTER['HEAD'] + []
-)
+
+
+def _GetDesktopNegativeFilter(version_name):
+  if version_name in _DESKTOP_NEGATIVE_FILTER:
+    return _DESKTOP_NEGATIVE_FILTER[version_name]
+  return _DESKTOP_NEGATIVE_FILTER['HEAD']
 
 
 _ANDROID_NEGATIVE_FILTER = {}
@@ -147,7 +147,7 @@
                                                         'Debug')
       host_port = ChromeDriverTest._http_server._server.server_port
       ChromeDriverTest._forwarder.Run(
-          [(host_port, host_port)], valgrind_tools.BaseTool(), '127.0.0.1')
+          [(host_port, host_port)], valgrind_tools.BaseTool())
 
   @staticmethod
   def GlobalTearDown():
@@ -736,7 +736,7 @@
     if _ANDROID_PACKAGE:
       negative_filter = _ANDROID_NEGATIVE_FILTER[_ANDROID_PACKAGE]
     else:
-      negative_filter = _DESKTOP_NEGATIVE_FILTER[options.chrome_version]
+      negative_filter = _GetDesktopNegativeFilter(options.chrome_version)
     options.filter = '*-' + ':__main__.'.join([''] + negative_filter)
 
   all_tests_suite = unittest.defaultTestLoader.loadTestsFromModule(
diff --git a/chrome/test/chromedriver/server/chromedriver_server.cc b/chrome/test/chromedriver/server/chromedriver_server.cc
index f0c4afe..e1b35a7 100644
--- a/chrome/test/chromedriver/server/chromedriver_server.cc
+++ b/chrome/test/chromedriver/server/chromedriver_server.cc
@@ -12,11 +12,11 @@
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/synchronization/waitable_event.h"
 #include "chrome/test/chromedriver/chrome/log.h"
 #include "chrome/test/chromedriver/chrome/version.h"
-#include "chrome/test/chromedriver/command_executor_impl.h"
 #include "chrome/test/chromedriver/server/http_handler.h"
 #include "chrome/test/chromedriver/server/http_response.h"
 #include "third_party/mongoose/mongoose.h"
@@ -37,8 +37,8 @@
     if (request_info->http_headers[header_index].name == NULL) {
       break;
     }
-    if (strcmp(request_info->http_headers[header_index].name,
-               "Content-Length") == 0) {
+    if (LowerCaseEqualsASCII(request_info->http_headers[header_index].name,
+                             "content-length")) {
       base::StringToInt(
           request_info->http_headers[header_index].value, &content_length);
       break;
@@ -116,6 +116,26 @@
   std::string url_base;
   int http_threads = 4;
   base::FilePath log_path;
+  Log::Level log_level = Log::kError;
+  if (cmd_line->HasSwitch("h") || cmd_line->HasSwitch("help")) {
+    std::string options;
+    const char* kOptionAndDescriptions[] = {
+        "port=PORT", "port to listen on",
+        "log-path=FILE", "write server log to file instead of stderr, "
+            "increases log level to INFO",
+        "verbose", "log verbosely",
+        "silent", "log nothing",
+        "url-base", "base URL path prefix for commands, e.g. wd/url",
+        "http-threads=THREAD_COUNT", "number of HTTP threads to spawn",
+    };
+    for (size_t i = 0; i < arraysize(kOptionAndDescriptions) - 1; i += 2) {
+      options += base::StringPrintf(
+          "  --%-30s%s\n",
+          kOptionAndDescriptions[i], kOptionAndDescriptions[i + 1]);
+    }
+    printf("Usage: %s [OPTIONS]\n\nOptions\n%s", argv[0], options.c_str());
+    return 0;
+  }
   if (cmd_line->HasSwitch("port"))
     port = cmd_line->GetSwitchValueASCII("port");
   if (cmd_line->HasSwitch("url-base"))
@@ -132,6 +152,7 @@
     }
   }
   if (cmd_line->HasSwitch("log-path")) {
+    log_level = Log::kLog;
     log_path = cmd_line->GetSwitchValuePath("log-path");
 #if defined(OS_WIN)
     FILE* redir_stderr = _wfreopen(log_path.value().c_str(), L"w", stderr);
@@ -143,13 +164,12 @@
       return 1;
     }
   }
+  if (cmd_line->HasSwitch("verbose"))
+    log_level = Log::kDebug;
 
-  bool success = InitLogging(
-      NULL,
-      logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG,
-      logging::DONT_LOCK_LOG_FILE,
-      logging::DELETE_OLD_LOG_FILE,
-      logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS);
+  logging::LoggingSettings settings;
+  settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
+  bool success = logging::InitLogging(settings);
   if (!success) {
     PLOG(ERROR) << "Unable to initialize logging";
   }
@@ -157,14 +177,11 @@
                        false,  // enable_thread_id
                        false,  // enable_timestamp
                        false); // enable_tickcount
-  Log::Level level = Log::kLog;
-  if (cmd_line->HasSwitch("verbose"))
-    level = Log::kDebug;
+  if (!cmd_line->HasSwitch("verbose"))
+    logging::SetMinLogLevel(logging::LOG_FATAL);
 
-  scoped_ptr<Log> log(new Logger(level));
-  scoped_ptr<CommandExecutor> executor(new CommandExecutorImpl(log.get()));
-  HttpHandler handler(
-      log.get(), executor.Pass(), HttpHandler::CreateCommandMap(), url_base);
+  scoped_ptr<Log> log(new Logger(log_level));
+  HttpHandler handler(log.get(), url_base);
   base::WaitableEvent shutdown_event(false, false);
   MongooseUserData user_data = { &handler, &shutdown_event };
 
@@ -180,7 +197,7 @@
                                     &user_data,
                                     options.get());
   if (ctx == NULL) {
-    printf("Port already in use. Exiting...\n");
+    printf("Port not available. Exiting...\n");
     return 1;
   }
 
@@ -188,6 +205,7 @@
     printf("Started ChromeDriver (v%s) on port %s\n",
            kChromeDriverVersion,
            port.c_str());
+    fflush(stdout);
   }
 
 #if defined(OS_POSIX)
diff --git a/chrome/test/chromedriver/server/http_handler.cc b/chrome/test/chromedriver/server/http_handler.cc
index 66d515f..e6fabb2 100644
--- a/chrome/test/chromedriver/server/http_handler.cc
+++ b/chrome/test/chromedriver/server/http_handler.cc
@@ -4,24 +4,53 @@
 
 #include "chrome/test/chromedriver/server/http_handler.h"
 
+#include "base/bind.h"
+#include "base/callback.h"
 #include "base/json/json_reader.h"
 #include "base/json/json_writer.h"
+#include "base/logging.h"  // For CHECK macros.
 #include "base/memory/scoped_ptr.h"
+#include "base/message_loop.h"
+#include "base/message_loop/message_loop_proxy.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
+#include "base/sys_info.h"
 #include "base/values.h"
+#include "chrome/test/chromedriver/alert_commands.h"
+#include "chrome/test/chromedriver/chrome/adb_impl.h"
+#include "chrome/test/chromedriver/chrome/device_manager.h"
 #include "chrome/test/chromedriver/chrome/log.h"
 #include "chrome/test/chromedriver/chrome/status.h"
-#include "chrome/test/chromedriver/command_executor.h"
-#include "chrome/test/chromedriver/command_names.h"
+#include "chrome/test/chromedriver/chrome/version.h"
+#include "chrome/test/chromedriver/commands.h"
+#include "chrome/test/chromedriver/element_commands.h"
+#include "chrome/test/chromedriver/net/url_request_context_getter.h"
 #include "chrome/test/chromedriver/server/http_response.h"
+#include "chrome/test/chromedriver/session.h"
+#include "chrome/test/chromedriver/session_commands.h"
+#include "chrome/test/chromedriver/session_map.h"
 #include "chrome/test/chromedriver/util.h"
+#include "chrome/test/chromedriver/window_commands.h"
+
+#if defined(OS_MACOSX)
+#include "base/mac/scoped_nsautorelease_pool.h"
+#endif
 
 namespace {
 
+const char kLocalStorage[] = "localStorage";
+const char kSessionStorage[] = "sessionStorage";
 const char kShutdownPath[] = "shutdown";
 
+Status UnimplementedCommand(
+    const base::DictionaryValue& params,
+    const std::string& session_id,
+    scoped_ptr<base::Value>* value,
+    std::string* out_session_id) {
+  return Status(kUnknownCommand);
+}
+
 }  // namespace
 
 HttpRequest::HttpRequest(HttpMethod method,
@@ -33,236 +62,283 @@
 
 CommandMapping::CommandMapping(HttpMethod method,
                                const std::string& path_pattern,
-                               const std::string& name)
-    : method(method), path_pattern(path_pattern), name(name) {}
+                               const Command& command)
+    : method(method), path_pattern(path_pattern), command(command) {}
 
 CommandMapping::~CommandMapping() {}
 
-// static
-scoped_ptr<HttpHandler::CommandMap> HttpHandler::CreateCommandMap() {
+HttpHandler::HttpHandler(Log* log, const std::string& url_base)
+    : log_(log),
+      io_thread_("ChromeDriver IO"),
+      url_base_(url_base) {
+#if defined(OS_MACOSX)
+  base::mac::ScopedNSAutoreleasePool autorelease_pool;
+#endif
+  base::Thread::Options options(base::MessageLoop::TYPE_IO, 0);
+  CHECK(io_thread_.StartWithOptions(options));
+  context_getter_ = new URLRequestContextGetter(
+      io_thread_.message_loop_proxy());
+  socket_factory_ = CreateSyncWebSocketFactory(context_getter_.get());
+  adb_.reset(new AdbImpl(io_thread_.message_loop_proxy(), log_));
+  device_manager_.reset(new DeviceManager(adb_.get()));
+
   CommandMapping commands[] = {
-      CommandMapping(kPost, "session", CommandNames::kNewSession),
+      CommandMapping(kPost, internal::kNewSessionPathPattern,
+                     base::Bind(&ExecuteNewSession,
+                                NewSessionParams(log_, &session_map_,
+                                    context_getter_, socket_factory_,
+                                    device_manager_.get()))),
       CommandMapping(kGet, "session/:sessionId",
-                     CommandNames::kGetSessionCapabilities),
-      CommandMapping(kDelete, "session/:sessionId", CommandNames::kQuit),
+                     WrapToCommand(
+                         base::Bind(&ExecuteGetSessionCapabilities,
+                             &session_map_))),
+      CommandMapping(kDelete, "session/:sessionId",
+                     base::Bind(&ExecuteQuit, false, &session_map_)),
       CommandMapping(kGet, "session/:sessionId/window_handle",
-                     CommandNames::kGetCurrentWindowHandle),
+                     WrapToCommand(base::Bind(&ExecuteGetCurrentWindowHandle))),
       CommandMapping(kGet, "session/:sessionId/window_handles",
-                     CommandNames::kGetWindowHandles),
-      CommandMapping(kPost, "session/:sessionId/url", CommandNames::kGet),
-      CommandMapping(kGet, "session/:sessionId/alert", CommandNames::kGetAlert),
+                     WrapToCommand(base::Bind(&ExecuteGetWindowHandles))),
+      CommandMapping(kPost, "session/:sessionId/url",
+                     WrapToCommand(base::Bind(&ExecuteGet))),
+      CommandMapping(kGet, "session/:sessionId/alert",
+                     WrapToCommand(
+                         base::Bind(&ExecuteAlertCommand,
+                                     base::Bind(&ExecuteGetAlert)))),
       CommandMapping(kPost, "session/:sessionId/dismiss_alert",
-                     CommandNames::kDismissAlert),
+                     WrapToCommand(
+                         base::Bind(&ExecuteAlertCommand,
+                                    base::Bind(&ExecuteDismissAlert)))),
       CommandMapping(kPost, "session/:sessionId/accept_alert",
-                     CommandNames::kAcceptAlert),
+                     WrapToCommand(
+                         base::Bind(&ExecuteAlertCommand,
+                                    base::Bind(&ExecuteAcceptAlert)))),
       CommandMapping(kGet, "session/:sessionId/alert_text",
-                     CommandNames::kGetAlertText),
+                     WrapToCommand(
+                         base::Bind(&ExecuteAlertCommand,
+                                    base::Bind(&ExecuteGetAlertText)))),
       CommandMapping(kPost, "session/:sessionId/alert_text",
-                     CommandNames::kSetAlertValue),
+                     WrapToCommand(
+                         base::Bind(&ExecuteAlertCommand,
+                                    base::Bind(&ExecuteSetAlertValue)))),
       CommandMapping(kPost, "session/:sessionId/forward",
-                     CommandNames::kGoForward),
-      CommandMapping(kPost, "session/:sessionId/back", CommandNames::kGoBack),
+                     WrapToCommand(base::Bind(&ExecuteGoForward))),
+      CommandMapping(kPost, "session/:sessionId/back",
+                     WrapToCommand(base::Bind(&ExecuteGoBack))),
       CommandMapping(kPost, "session/:sessionId/refresh",
-                     CommandNames::kRefresh),
+                     WrapToCommand(base::Bind(&ExecuteRefresh))),
       CommandMapping(kPost, "session/:sessionId/execute",
-                     CommandNames::kExecuteScript),
+                     WrapToCommand(base::Bind(&ExecuteExecuteScript))),
       CommandMapping(kPost, "session/:sessionId/execute_async",
-                     CommandNames::kExecuteAsyncScript),
+                     WrapToCommand(base::Bind(&ExecuteExecuteAsyncScript))),
       CommandMapping(kGet, "session/:sessionId/url",
-                     CommandNames::kGetCurrentUrl),
-      CommandMapping(kGet, "session/:sessionId/title", CommandNames::kGetTitle),
+                     WrapToCommand(base::Bind(&ExecuteGetCurrentUrl))),
+      CommandMapping(kGet, "session/:sessionId/title",
+                     WrapToCommand(base::Bind(&ExecuteGetTitle))),
       CommandMapping(kGet, "session/:sessionId/source",
-                     CommandNames::kGetPageSource),
+                     WrapToCommand(base::Bind(&ExecuteGetPageSource))),
       CommandMapping(kGet, "session/:sessionId/screenshot",
-                     CommandNames::kScreenshot),
+                     WrapToCommand(base::Bind(&ExecuteScreenshot))),
       CommandMapping(kPost, "session/:sessionId/visible",
-                     CommandNames::kSetBrowserVisible),
+                     base::Bind(&UnimplementedCommand)),
       CommandMapping(kGet, "session/:sessionId/visible",
-                     CommandNames::kIsBrowserVisible),
+                     base::Bind(&UnimplementedCommand)),
       CommandMapping(kPost, "session/:sessionId/element",
-                     CommandNames::kFindElement),
+                     WrapToCommand(base::Bind(&ExecuteFindElement, 50))),
       CommandMapping(kPost, "session/:sessionId/elements",
-                     CommandNames::kFindElements),
+                     WrapToCommand(base::Bind(&ExecuteFindElements, 50))),
       CommandMapping(kPost, "session/:sessionId/element/active",
-                     CommandNames::kGetActiveElement),
+                     WrapToCommand(base::Bind(&ExecuteGetActiveElement))),
       CommandMapping(kPost, "session/:sessionId/element/:id/element",
-                     CommandNames::kFindChildElement),
+                     WrapToCommand(base::Bind(&ExecuteFindChildElement, 50))),
       CommandMapping(kPost, "session/:sessionId/element/:id/elements",
-                     CommandNames::kFindChildElements),
+                     WrapToCommand(base::Bind(&ExecuteFindChildElements, 50))),
       CommandMapping(kPost, "session/:sessionId/element/:id/click",
-                     CommandNames::kClickElement),
+                     WrapToCommand(base::Bind(&ExecuteClickElement))),
       CommandMapping(kPost, "session/:sessionId/element/:id/clear",
-                     CommandNames::kClearElement),
+                     WrapToCommand(base::Bind(&ExecuteClearElement))),
       CommandMapping(kPost, "session/:sessionId/element/:id/submit",
-                     CommandNames::kSubmitElement),
+                     WrapToCommand(base::Bind(&ExecuteSubmitElement))),
       CommandMapping(kGet, "session/:sessionId/element/:id/text",
-                     CommandNames::kGetElementText),
+                     WrapToCommand(base::Bind(&ExecuteGetElementText))),
       CommandMapping(kPost, "session/:sessionId/element/:id/value",
-                     CommandNames::kSendKeysToElement),
+                     WrapToCommand(base::Bind(&ExecuteSendKeysToElement))),
       CommandMapping(kPost, "session/:sessionId/file",
-                     CommandNames::kUploadFile),
+                     WrapToCommand(base::Bind(&ExecuteUploadFile))),
       CommandMapping(kGet, "session/:sessionId/element/:id/value",
-                     CommandNames::kGetElementValue),
+                     WrapToCommand(base::Bind(&ExecuteGetElementValue))),
       CommandMapping(kGet, "session/:sessionId/element/:id/name",
-                     CommandNames::kGetElementTagName),
+                     WrapToCommand(base::Bind(&ExecuteGetElementTagName))),
       CommandMapping(kGet, "session/:sessionId/element/:id/selected",
-                     CommandNames::kIsElementSelected),
+                     WrapToCommand(base::Bind(&ExecuteIsElementSelected))),
       CommandMapping(kGet, "session/:sessionId/element/:id/enabled",
-                     CommandNames::kIsElementEnabled),
+                     WrapToCommand(base::Bind(&ExecuteIsElementEnabled))),
       CommandMapping(kGet, "session/:sessionId/element/:id/displayed",
-                     CommandNames::kIsElementDisplayed),
+                     WrapToCommand(base::Bind(&ExecuteIsElementDisplayed))),
       CommandMapping(kPost, "session/:sessionId/element/:id/hover",
-                     CommandNames::kHoverOverElement),
+                     WrapToCommand(base::Bind(&ExecuteHoverOverElement))),
       CommandMapping(kGet, "session/:sessionId/element/:id/location",
-                     CommandNames::kGetElementLocation),
+                     WrapToCommand(base::Bind(&ExecuteGetElementLocation))),
       CommandMapping(kGet, "session/:sessionId/element/:id/location_in_view",
-                     CommandNames::kGetElementLocationOnceScrolledIntoView),
+                     WrapToCommand(
+                         base::Bind(
+                             &ExecuteGetElementLocationOnceScrolledIntoView))),
       CommandMapping(kGet, "session/:sessionId/element/:id/size",
-                     CommandNames::kGetElementSize),
+                     WrapToCommand(base::Bind(&ExecuteGetElementSize))),
       CommandMapping(kGet, "session/:sessionId/element/:id/attribute/:name",
-                     CommandNames::kGetElementAttribute),
+                     WrapToCommand(base::Bind(&ExecuteGetElementAttribute))),
       CommandMapping(kGet, "session/:sessionId/element/:id/equals/:other",
-                     CommandNames::kElementEquals),
+                     WrapToCommand(base::Bind(&ExecuteElementEquals))),
       CommandMapping(kGet, "session/:sessionId/cookie",
-                     CommandNames::kGetCookies),
+                     WrapToCommand(base::Bind(&ExecuteGetCookies))),
       CommandMapping(kPost, "session/:sessionId/cookie",
-                     CommandNames::kAddCookie),
+                     WrapToCommand(base::Bind(&ExecuteAddCookie))),
       CommandMapping(kDelete, "session/:sessionId/cookie",
-                     CommandNames::kDeleteAllCookies),
+                     WrapToCommand(base::Bind(&ExecuteDeleteAllCookies))),
       CommandMapping(kDelete, "session/:sessionId/cookie/:name",
-                     CommandNames::kDeleteCookie),
+                     WrapToCommand(base::Bind(&ExecuteDeleteCookie))),
       CommandMapping(kPost, "session/:sessionId/frame",
-                     CommandNames::kSwitchToFrame),
+                     WrapToCommand(base::Bind(&ExecuteSwitchToFrame))),
       CommandMapping(kPost, "session/:sessionId/window",
-                     CommandNames::kSwitchToWindow),
+                     WrapToCommand(base::Bind(&ExecuteSwitchToWindow))),
       CommandMapping(kGet, "session/:sessionId/window/:windowHandle/size",
-                     CommandNames::kGetWindowSize),
+                     WrapToCommand(base::Bind(&ExecuteGetWindowSize))),
       CommandMapping(kGet, "session/:sessionId/window/:windowHandle/position",
-                     CommandNames::kGetWindowPosition),
+                     WrapToCommand(base::Bind(&ExecuteGetWindowPosition))),
       CommandMapping(kPost, "session/:sessionId/window/:windowHandle/size",
-                     CommandNames::kSetWindowSize),
+                     WrapToCommand(base::Bind(&ExecuteSetWindowSize))),
       CommandMapping(kPost, "session/:sessionId/window/:windowHandle/position",
-                     CommandNames::kSetWindowPosition),
+                     WrapToCommand(base::Bind(&ExecuteSetWindowPosition))),
       CommandMapping(kPost, "session/:sessionId/window/:windowHandle/maximize",
-                     CommandNames::kMaximizeWindow),
+                     WrapToCommand(base::Bind(&ExecuteMaximizeWindow))),
       CommandMapping(kDelete, "session/:sessionId/window",
-                     CommandNames::kClose),
+                     WrapToCommand(base::Bind(&ExecuteClose, &session_map_))),
       CommandMapping(kPost, "session/:sessionId/element/:id/drag",
-                     CommandNames::kDragElement),
+                     base::Bind(&UnimplementedCommand)),
       CommandMapping(kGet, "session/:sessionId/element/:id/css/:propertyName",
-                     CommandNames::kGetElementValueOfCssProperty),
+                     WrapToCommand(
+                         base::Bind(&ExecuteGetElementValueOfCSSProperty))),
       CommandMapping(kPost, "session/:sessionId/timeouts/implicit_wait",
-                     CommandNames::kImplicitlyWait),
+                     WrapToCommand(base::Bind(&ExecuteImplicitlyWait))),
       CommandMapping(kPost, "session/:sessionId/timeouts/async_script",
-                     CommandNames::kSetScriptTimeout),
+                     WrapToCommand(base::Bind(&ExecuteSetScriptTimeout))),
       CommandMapping(kPost, "session/:sessionId/timeouts",
-                     CommandNames::kSetTimeout),
+                     WrapToCommand(base::Bind(&ExecuteSetTimeout))),
       CommandMapping(kPost, "session/:sessionId/execute_sql",
-                     CommandNames::kExecuteSQL),
+                     base::Bind(&UnimplementedCommand)),
       CommandMapping(kGet, "session/:sessionId/location",
-                     CommandNames::kGetLocation),
+                     WrapToCommand(base::Bind(&ExecuteGetLocation))),
       CommandMapping(kPost, "session/:sessionId/location",
-                     CommandNames::kSetLocation),
+                     WrapToCommand(base::Bind(&ExecuteSetLocation))),
       CommandMapping(kGet, "session/:sessionId/application_cache/status",
-                     CommandNames::kGetStatus),
+                     base::Bind(&ExecuteGetStatus)),
       CommandMapping(kGet, "session/:sessionId/browser_connection",
-                     CommandNames::kIsBrowserOnline),
+                     base::Bind(&UnimplementedCommand)),
       CommandMapping(kPost, "session/:sessionId/browser_connection",
-                     CommandNames::kSetBrowserOnline),
+                     base::Bind(&UnimplementedCommand)),
       CommandMapping(kGet, "session/:sessionId/local_storage/key/:key",
-                     CommandNames::kGetLocalStorageItem),
+                     WrapToCommand(
+                         base::Bind(&ExecuteGetStorageItem, kLocalStorage))),
       CommandMapping(kDelete, "session/:sessionId/local_storage/key/:key",
-                     CommandNames::kRemoveLocalStorageItem),
+                     WrapToCommand(
+                         base::Bind(&ExecuteRemoveStorageItem, kLocalStorage))),
       CommandMapping(kGet, "session/:sessionId/local_storage",
-                     CommandNames::kGetLocalStorageKeys),
+                     WrapToCommand(
+                         base::Bind(&ExecuteGetStorageKeys, kLocalStorage))),
       CommandMapping(kPost, "session/:sessionId/local_storage",
-                     CommandNames::kSetLocalStorageItem),
+                     WrapToCommand(
+                         base::Bind(&ExecuteSetStorageItem, kLocalStorage))),
       CommandMapping(kDelete, "session/:sessionId/local_storage",
-                     CommandNames::kClearLocalStorage),
+                     WrapToCommand(
+                         base::Bind(&ExecuteClearStorage, kLocalStorage))),
       CommandMapping(kGet, "session/:sessionId/local_storage/size",
-                     CommandNames::kGetLocalStorageSize),
+                     WrapToCommand(
+                         base::Bind(&ExecuteGetStorageSize, kLocalStorage))),
       CommandMapping(kGet, "session/:sessionId/session_storage/key/:key",
-                     CommandNames::kGetSessionStorageItem),
+                     WrapToCommand(
+                         base::Bind(&ExecuteGetStorageItem, kSessionStorage))),
       CommandMapping(kDelete, "session/:sessionId/session_storage/key/:key",
-                     CommandNames::kRemoveSessionStorageItem),
+                     WrapToCommand(
+                         base::Bind(
+                             &ExecuteRemoveStorageItem, kSessionStorage))),
       CommandMapping(kGet, "session/:sessionId/session_storage",
-                     CommandNames::kGetSessionStorageKey),
+                     WrapToCommand(
+                         base::Bind(&ExecuteGetStorageKeys, kSessionStorage))),
       CommandMapping(kPost, "session/:sessionId/session_storage",
-                     CommandNames::kSetSessionStorageItem),
+                     WrapToCommand(
+                         base::Bind(&ExecuteSetStorageItem, kSessionStorage))),
       CommandMapping(kDelete, "session/:sessionId/session_storage",
-                     CommandNames::kClearSessionStorage),
+                     WrapToCommand(
+                         base::Bind(&ExecuteClearStorage, kSessionStorage))),
       CommandMapping(kGet, "session/:sessionId/session_storage/size",
-                     CommandNames::kGetSessionStorageSize),
+                     WrapToCommand(
+                         base::Bind(&ExecuteGetStorageSize, kSessionStorage))),
       CommandMapping(kGet, "session/:sessionId/orientation",
-                     CommandNames::kGetScreenOrientation),
+                     base::Bind(&UnimplementedCommand)),
       CommandMapping(kPost, "session/:sessionId/orientation",
-                     CommandNames::kSetScreenOrientation),
+                     base::Bind(&UnimplementedCommand)),
       CommandMapping(kPost, "session/:sessionId/click",
-                     CommandNames::kMouseClick),
+                     WrapToCommand(base::Bind(&ExecuteMouseClick))),
       CommandMapping(kPost, "session/:sessionId/doubleclick",
-                     CommandNames::kMouseDoubleClick),
+                     WrapToCommand(base::Bind(&ExecuteMouseDoubleClick))),
       CommandMapping(kPost, "session/:sessionId/buttondown",
-                     CommandNames::kMouseButtonDown),
+                     WrapToCommand(base::Bind(&ExecuteMouseButtonDown))),
       CommandMapping(kPost, "session/:sessionId/buttonup",
-                     CommandNames::kMouseButtonUp),
+                     WrapToCommand(base::Bind(&ExecuteMouseButtonUp))),
       CommandMapping(kPost, "session/:sessionId/moveto",
-                     CommandNames::kMouseMoveTo),
+                     WrapToCommand(base::Bind(&ExecuteMouseMoveTo))),
       CommandMapping(kPost, "session/:sessionId/keys",
-                     CommandNames::kSendKeysToActiveElement),
+                     WrapToCommand(
+                         base::Bind(&ExecuteSendKeysToActiveElement))),
       CommandMapping(kGet, "session/:sessionId/ime/available_engines",
-                     CommandNames::kImeGetAvailableEngines),
+                     base::Bind(&UnimplementedCommand)),
       CommandMapping(kGet, "session/:sessionId/ime/active_engine",
-                     CommandNames::kImeGetActiveEngine),
+                     base::Bind(&UnimplementedCommand)),
       CommandMapping(kGet, "session/:sessionId/ime/activated",
-                     CommandNames::kImeIsActivated),
+                     base::Bind(&UnimplementedCommand)),
       CommandMapping(kPost, "session/:sessionId/ime/deactivate",
-                     CommandNames::kImeDeactivate),
+                     base::Bind(&UnimplementedCommand)),
       CommandMapping(kPost, "session/:sessionId/ime/activate",
-                     CommandNames::kImeActivateEngine),
+                     base::Bind(&UnimplementedCommand)),
       CommandMapping(kPost, "session/:sessionId/touch/click",
-                     CommandNames::kTouchSingleTap),
+                     WrapToCommand(base::Bind(&ExecuteTouchSingleTap))),
       CommandMapping(kPost, "session/:sessionId/touch/down",
-                     CommandNames::kTouchDown),
+                     base::Bind(&UnimplementedCommand)),
       CommandMapping(kPost, "session/:sessionId/touch/up",
-                     CommandNames::kTouchUp),
+                     base::Bind(&UnimplementedCommand)),
       CommandMapping(kPost, "session/:sessionId/touch/move",
-                     CommandNames::kTouchMove),
+                     base::Bind(&UnimplementedCommand)),
       CommandMapping(kPost, "session/:sessionId/touch/scroll",
-                     CommandNames::kTouchScroll),
+                     base::Bind(&UnimplementedCommand)),
       CommandMapping(kPost, "session/:sessionId/touch/doubleclick",
-                     CommandNames::kTouchDoubleTap),
+                     base::Bind(&UnimplementedCommand)),
       CommandMapping(kPost, "session/:sessionId/touch/longclick",
-                     CommandNames::kTouchLongPress),
+                     base::Bind(&UnimplementedCommand)),
       CommandMapping(kPost, "session/:sessionId/touch/flick",
-                     CommandNames::kTouchFlick),
-      CommandMapping(kPost, "session/:sessionId/log", CommandNames::kGetLog),
+                     base::Bind(&UnimplementedCommand)),
+      CommandMapping(kPost, "session/:sessionId/log",
+                     WrapToCommand(base::Bind(&ExecuteGetLog))),
       CommandMapping(kGet, "session/:sessionId/log/types",
-                     CommandNames::kGetAvailableLogTypes),
-      CommandMapping(kPost, "logs", CommandNames::kGetSessionLogs),
-      CommandMapping(kGet, "status", CommandNames::kStatus),
+                     WrapToCommand(base::Bind(&ExecuteGetAvailableLogTypes))),
+      CommandMapping(kPost, "logs", base::Bind(&UnimplementedCommand)),
+      CommandMapping(kGet, "status", base::Bind(&ExecuteGetStatus)),
 
       // Custom Chrome commands:
       // Allow quit all to be called with GET or POST.
-      CommandMapping(kGet, kShutdownPath, CommandNames::kQuitAll),
-      CommandMapping(kPost, kShutdownPath, CommandNames::kQuitAll),
+      CommandMapping(kGet, kShutdownPath,
+                     base::Bind(&ExecuteQuitAll,
+                                base::Bind(&ExecuteQuit, true, &session_map_),
+                                &session_map_)),
+      CommandMapping(kPost, kShutdownPath,
+                     base::Bind(&ExecuteQuitAll,
+                                base::Bind(&ExecuteQuit, true, &session_map_),
+                                &session_map_)),
       CommandMapping(kGet, "session/:sessionId/is_loading",
-                     CommandNames::kIsLoading),
+                     WrapToCommand(base::Bind(&ExecuteIsLoading))),
   };
-  return scoped_ptr<CommandMap>(
+  this->command_map_.reset(
       new CommandMap(commands, commands + arraysize(commands)));
 }
 
-HttpHandler::HttpHandler(Log* log,
-                         scoped_ptr<CommandExecutor> executor,
-                         scoped_ptr<CommandMap> command_map,
-                         const std::string& url_base)
-    : log_(log),
-      executor_(executor.Pass()),
-      command_map_(command_map.Pass()),
-      url_base_(url_base) {
-  executor_->Init();
-}
-
 HttpHandler::~HttpHandler() {}
 
 void HttpHandler::Handle(const HttpRequest& request,
@@ -292,6 +368,23 @@
   return request.path == url_base_ + kShutdownPath;
 }
 
+Command HttpHandler::WrapToCommand(
+    const SessionCommand& session_command) {
+  return base::Bind(&ExecuteSessionCommand, &session_map_, session_command);
+}
+
+Command HttpHandler::WrapToCommand(
+    const WindowCommand& window_command) {
+  return WrapToCommand(
+      base::Bind(&ExecuteWindowCommand, window_command));
+}
+
+Command HttpHandler::WrapToCommand(
+    const ElementCommand& element_command) {
+  return WrapToCommand(
+      base::Bind(&ExecuteElementCommand, element_command));
+}
+
 void HttpHandler::HandleInternal(const HttpRequest& request,
                                  HttpResponse* response) {
   std::string path = request.path;
@@ -339,29 +432,40 @@
     params.MergeDictionary(body_params);
   }
 
-  StatusCode status = kOk;
   scoped_ptr<base::Value> value;
   std::string out_session_id;
-  executor_->ExecuteCommand(
-      iter->name, params, session_id, &status, &value, &out_session_id);
+  Status status = iter->command.Run(
+      params, session_id, &value, &out_session_id);
 
-  if (status == kUnknownCommand) {
+  if (status.code() == kUnknownCommand) {
     *response = HttpResponse(HttpResponse::kNotImplemented);
-    response->set_body("unimplemented command: " + iter->name);
+    response->set_body("unimplemented command: " + trimmed_path);
     return true;
   }
 
-  if (iter->name == CommandNames::kNewSession && status == kOk) {
+  if (iter->path_pattern == internal::kNewSessionPathPattern && status.IsOk()) {
     // Creating a session involves a HTTP request to /session, which is
     // supposed to redirect to /session/:sessionId, which returns the
     // session info.
     *response = HttpResponse(HttpResponse::kSeeOther);
     response->AddHeader("Location", url_base_ + "session/" + out_session_id);
     return true;
+  } else if (status.IsError()) {
+    status.AddDetails(base::StringPrintf(
+        "Driver info: chromedriver=%s,platform=%s %s %s",
+        kChromeDriverVersion,
+        base::SysInfo::OperatingSystemName().c_str(),
+        base::SysInfo::OperatingSystemVersion().c_str(),
+        base::SysInfo::OperatingSystemArchitecture().c_str()));
+    scoped_ptr<base::DictionaryValue> error(new base::DictionaryValue());
+    error->SetString("message", status.message());
+    value.reset(error.release());
   }
+  if (!value)
+    value.reset(base::Value::CreateNullValue());
 
   base::DictionaryValue body_params;
-  body_params.SetInteger("status", status);
+  body_params.SetInteger("status", status.code());
   body_params.Set("value", value.release());
   body_params.SetString("sessionId", out_session_id);
   std::string body;
@@ -376,6 +480,8 @@
 
 namespace internal {
 
+const char kNewSessionPathPattern[] = "session";
+
 bool MatchesCommand(HttpMethod method,
                     const std::string& path,
                     const CommandMapping& command,
@@ -410,4 +516,4 @@
   return true;
 }
 
-}  // namespace
+}  // namespace internal
diff --git a/chrome/test/chromedriver/server/http_handler.h b/chrome/test/chromedriver/server/http_handler.h
index b7ff044..4666c59 100644
--- a/chrome/test/chromedriver/server/http_handler.h
+++ b/chrome/test/chromedriver/server/http_handler.h
@@ -8,15 +8,26 @@
 #include <string>
 #include <vector>
 
+#include "base/compiler_specific.h"
+#include "base/gtest_prod_util.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/threading/thread.h"
+#include "chrome/test/chromedriver/command.h"
+#include "chrome/test/chromedriver/element_commands.h"
+#include "chrome/test/chromedriver/net/sync_websocket_factory.h"
+#include "chrome/test/chromedriver/session_commands.h"
+#include "chrome/test/chromedriver/session_map.h"
+#include "chrome/test/chromedriver/window_commands.h"
 
 namespace base {
 class DictionaryValue;
 }
 
-class CommandExecutor;
-class HttpResponse;
+class Adb;
+class DeviceManager;
 class Log;
+class HttpResponse;
+class URLRequestContextGetter;
 
 enum HttpMethod {
   kGet = 0,
@@ -38,51 +49,62 @@
 struct CommandMapping {
   CommandMapping(HttpMethod method,
                  const std::string& path_pattern,
-                 const std::string& name);
+                 const Command& command);
   ~CommandMapping();
 
   HttpMethod method;
   std::string path_pattern;
-  std::string name;
+  Command command;
 };
 
 class HttpHandler {
  public:
-  typedef std::vector<CommandMapping> CommandMap;
-  static scoped_ptr<CommandMap> CreateCommandMap();
-
-  HttpHandler(Log* log,
-              scoped_ptr<CommandExecutor> executor,
-              scoped_ptr<std::vector<CommandMapping> > commands,
-              const std::string& url_base);
+  HttpHandler(Log* log, const std::string& url_base);
   ~HttpHandler();
 
-  void Handle(const HttpRequest& request,
-              HttpResponse* response);
-
+  void Handle(const HttpRequest& request, HttpResponse* response);
   bool ShouldShutdown(const HttpRequest& request);
 
  private:
-  void HandleInternal(const HttpRequest& request,
-                      HttpResponse* response);
+  FRIEND_TEST_ALL_PREFIXES(HttpHandlerTest, HandleUnknownCommand);
+  FRIEND_TEST_ALL_PREFIXES(HttpHandlerTest, HandleNewSession);
+  FRIEND_TEST_ALL_PREFIXES(HttpHandlerTest, HandleInvalidPost);
+  FRIEND_TEST_ALL_PREFIXES(HttpHandlerTest, HandleUnimplementedCommand);
+  FRIEND_TEST_ALL_PREFIXES(HttpHandlerTest, HandleCommand);
+  typedef std::vector<CommandMapping> CommandMap;
+
+  Command WrapToCommand(const SessionCommand& session_command);
+  Command WrapToCommand(const WindowCommand& window_command);
+  Command WrapToCommand(const ElementCommand& element_command);
+  void HandleInternal(const HttpRequest& request, HttpResponse* response);
   bool HandleWebDriverCommand(
       const HttpRequest& request,
       const std::string& trimmed_path,
       HttpResponse* response);
 
   Log* log_;
-  scoped_ptr<CommandExecutor> executor_;
-  scoped_ptr<CommandMap> command_map_;
+  base::Thread io_thread_;
   std::string url_base_;
+  scoped_refptr<URLRequestContextGetter> context_getter_;
+  SyncWebSocketFactory socket_factory_;
+  SessionMap session_map_;
+  scoped_ptr<CommandMap> command_map_;
+  scoped_ptr<Adb> adb_;
+  scoped_ptr<DeviceManager> device_manager_;
+
+  DISALLOW_COPY_AND_ASSIGN(HttpHandler);
 };
 
 namespace internal {
-extern const char kNewSessionIdCommand[];
+
+extern const char kNewSessionPathPattern[];
+
 bool MatchesCommand(HttpMethod method,
                     const std::string& path,
                     const CommandMapping& command,
                     std::string* session_id,
                     base::DictionaryValue* out_params);
+
 }  // namespace internal
 
 #endif  // CHROME_TEST_CHROMEDRIVER_SERVER_HTTP_HANDLER_H_
diff --git a/chrome/test/chromedriver/server/http_handler_unittest.cc b/chrome/test/chromedriver/server/http_handler_unittest.cc
index d862e6b..816cb3e 100644
--- a/chrome/test/chromedriver/server/http_handler_unittest.cc
+++ b/chrome/test/chromedriver/server/http_handler_unittest.cc
@@ -4,50 +4,34 @@
 
 #include <string>
 
+#include "base/bind.h"
 #include "base/json/json_writer.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/values.h"
 #include "chrome/test/chromedriver/chrome/log.h"
 #include "chrome/test/chromedriver/chrome/status.h"
-#include "chrome/test/chromedriver/command_executor.h"
-#include "chrome/test/chromedriver/command_names.h"
 #include "chrome/test/chromedriver/server/http_handler.h"
 #include "chrome/test/chromedriver/server/http_response.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
 
-class DummyExecutor : public CommandExecutor {
- public:
-  DummyExecutor() : status_(kOk) {}
-  explicit DummyExecutor(StatusCode status) : status_(status) {}
-  virtual ~DummyExecutor() {}
-
-  virtual void Init() OVERRIDE {}
-  virtual void ExecuteCommand(const std::string& name,
-                              const base::DictionaryValue& params,
-                              const std::string& session_id,
-                              StatusCode* status,
-                              scoped_ptr<base::Value>* value,
-                              std::string* out_session_id) OVERRIDE {
-    *status = status_;
-    value->reset(new base::FundamentalValue(1));
-    *out_session_id = "session_id";
-  }
-
- private:
-  StatusCode status_;
-};
+Status DummyCommand(
+    Status status,
+    const base::DictionaryValue& params,
+    const std::string& session_id,
+    scoped_ptr<base::Value>* value,
+    std::string* out_session_id) {
+  value->reset(new base::FundamentalValue(1));
+  *out_session_id = "session_id";
+  return status;
+}
 
 }  // namespace
 
 TEST(HttpHandlerTest, HandleOutsideOfBaseUrl) {
   Logger log;
-  HttpHandler handler(
-      &log,
-      scoped_ptr<CommandExecutor>(new DummyExecutor()),
-      scoped_ptr<HttpHandler::CommandMap>(new HttpHandler::CommandMap()),
-      "base/url/");
+  HttpHandler handler(&log, "base/url/");
   HttpRequest request(kGet, "base/path", "body");
   HttpResponse response;
   handler.Handle(request, &response);
@@ -56,11 +40,7 @@
 
 TEST(HttpHandlerTest, HandleUnknownCommand) {
   Logger log;
-  HttpHandler handler(
-      &log,
-      scoped_ptr<CommandExecutor>(new DummyExecutor()),
-      scoped_ptr<HttpHandler::CommandMap>(new HttpHandler::CommandMap()),
-      "/");
+  HttpHandler handler(&log, "/");
   HttpRequest request(kGet, "/path", std::string());
   HttpResponse response;
   handler.Handle(request, &response);
@@ -68,13 +48,12 @@
 }
 
 TEST(HttpHandlerTest, HandleNewSession) {
-  scoped_ptr<HttpHandler::CommandMap> map(new HttpHandler::CommandMap());
-  map->push_back(CommandMapping(kPost, "session", CommandNames::kNewSession));
   Logger log;
-  HttpHandler handler(
-      &log,
-      scoped_ptr<CommandExecutor>(new DummyExecutor()),
-      map.Pass(), "/base/");
+  HttpHandler handler(&log, "/base/");
+  handler.command_map_.reset(new HttpHandler::CommandMap());
+  handler.command_map_->push_back(
+      CommandMapping(kPost, internal::kNewSessionPathPattern,
+                     base::Bind(&DummyCommand, Status(kOk))));
   HttpRequest request(kPost, "/base/session", std::string());
   HttpResponse response;
   handler.Handle(request, &response);
@@ -86,13 +65,10 @@
 }
 
 TEST(HttpHandlerTest, HandleInvalidPost) {
-  scoped_ptr<HttpHandler::CommandMap> map(new HttpHandler::CommandMap());
-  map->push_back(CommandMapping(kPost, "path", "cmd"));
   Logger log;
-  HttpHandler handler(
-      &log,
-      scoped_ptr<CommandExecutor>(new DummyExecutor()),
-      map.Pass(), "/");
+  HttpHandler handler(&log, "/");
+  handler.command_map_->push_back(
+      CommandMapping(kPost, "path", base::Bind(&DummyCommand, Status(kOk))));
   HttpRequest request(kPost, "/path", "should be a dictionary");
   HttpResponse response;
   handler.Handle(request, &response);
@@ -100,13 +76,11 @@
 }
 
 TEST(HttpHandlerTest, HandleUnimplementedCommand) {
-  scoped_ptr<HttpHandler::CommandMap> map(new HttpHandler::CommandMap());
-  map->push_back(CommandMapping(kPost, "path", "cmd"));
   Logger log;
-  HttpHandler handler(
-      &log,
-      scoped_ptr<CommandExecutor>(new DummyExecutor(kUnknownCommand)),
-      map.Pass(), "/");
+  HttpHandler handler(&log, "/");
+  handler.command_map_->push_back(
+      CommandMapping(kPost, "path",
+                     base::Bind(&DummyCommand, Status(kUnknownCommand))));
   HttpRequest request(kPost, "/path", std::string());
   HttpResponse response;
   handler.Handle(request, &response);
@@ -114,13 +88,10 @@
 }
 
 TEST(HttpHandlerTest, HandleCommand) {
-  scoped_ptr<HttpHandler::CommandMap> map(new HttpHandler::CommandMap());
-  map->push_back(CommandMapping(kPost, "path", "cmd"));
   Logger log;
-  HttpHandler handler(
-      &log,
-      scoped_ptr<CommandExecutor>(new DummyExecutor()),
-      map.Pass(), "/");
+  HttpHandler handler(&log, "/");
+  handler.command_map_->push_back(
+      CommandMapping(kPost, "path", base::Bind(&DummyCommand, Status(kOk))));
   HttpRequest request(kPost, "/path", std::string());
   HttpResponse response;
   handler.Handle(request, &response);
@@ -137,7 +108,7 @@
 }
 
 TEST(MatchesCommandTest, DiffMethod) {
-  CommandMapping command(kPost, "path", "command");
+  CommandMapping command(kPost, "path", base::Bind(&DummyCommand, Status(kOk)));
   std::string session_id;
   base::DictionaryValue params;
   ASSERT_FALSE(internal::MatchesCommand(
@@ -147,7 +118,8 @@
 }
 
 TEST(MatchesCommandTest, DiffPathLength) {
-  CommandMapping command(kPost, "path/path", "command");
+  CommandMapping command(kPost, "path/path",
+                         base::Bind(&DummyCommand, Status(kOk)));
   std::string session_id;
   base::DictionaryValue params;
   ASSERT_FALSE(internal::MatchesCommand(
@@ -161,7 +133,8 @@
 }
 
 TEST(MatchesCommandTest, DiffPaths) {
-  CommandMapping command(kPost, "path/apath", "command");
+  CommandMapping command(kPost, "path/apath",
+                         base::Bind(&DummyCommand, Status(kOk)));
   std::string session_id;
   base::DictionaryValue params;
   ASSERT_FALSE(internal::MatchesCommand(
@@ -169,7 +142,8 @@
 }
 
 TEST(MatchesCommandTest, Substitution) {
-  CommandMapping command(kPost, "path/:sessionId/space/:a/:b", "command");
+  CommandMapping command(kPost, "path/:sessionId/space/:a/:b",
+                         base::Bind(&DummyCommand, Status(kOk)));
   std::string session_id;
   base::DictionaryValue params;
   ASSERT_TRUE(internal::MatchesCommand(
diff --git a/chrome/test/chromedriver/test_environment.py b/chrome/test/chromedriver/test_environment.py
index 396aef3..e34b4c8 100644
--- a/chrome/test/chromedriver/test_environment.py
+++ b/chrome/test/chromedriver/test_environment.py
@@ -11,12 +11,10 @@
 import os
 import sys
 
+import util
+
 _THIS_DIR = os.path.abspath(os.path.dirname(__file__))
 
-sys.path.insert(0, os.path.join(_THIS_DIR, os.pardir, 'pylib'))
-
-from common import util
-
 if util.IsLinux():
   sys.path.insert(0, os.path.join(_THIS_DIR, os.pardir, os.pardir, os.pardir,
                                   'build', 'android'))
@@ -78,7 +76,7 @@
 class DesktopTestEnvironment(BaseTestEnvironment):
   """Manages the environment java tests require to run on Desktop."""
 
-  #override
+  # override
   def GetOS(self):
     return util.GetPlatformName()
 
@@ -91,7 +89,7 @@
     self._adb = None
     self._forwarder = None
 
-  #override
+  # override
   def GlobalSetUp(self):
     os.putenv('TEST_HTTP_PORT', str(ANDROID_TEST_HTTP_PORT))
     os.putenv('TEST_HTTPS_PORT', str(ANDROID_TEST_HTTPS_PORT))
@@ -100,15 +98,15 @@
     self._forwarder.Run(
         [(ANDROID_TEST_HTTP_PORT, ANDROID_TEST_HTTP_PORT),
          (ANDROID_TEST_HTTPS_PORT, ANDROID_TEST_HTTPS_PORT)],
-        valgrind_tools.BaseTool(), '127.0.0.1')
+        valgrind_tools.BaseTool())
 
-  #override
+  # override
   def GlobalTearDown(self):
     if self._adb is not None:
       forwarder.Forwarder.KillDevice(self._adb, valgrind_tools.BaseTool())
     if self._forwarder is not None:
       self._forwarder.Close()
 
-  #override
+  # override
   def GetOS(self):
     return 'android'
diff --git a/chrome/test/chromedriver/test_expectations b/chrome/test/chromedriver/test_expectations
index 1ada199..b35023c 100644
--- a/chrome/test/chromedriver/test_expectations
+++ b/chrome/test/chromedriver/test_expectations
@@ -88,8 +88,7 @@
     'VisibilityTest.tooSmallAWindowWithOverflowHiddenIsNotAProblem',
     'WindowTest.*',
 ]
-_REVISION_NEGATIVE_FILTER['28'] = [] + _REVISION_NEGATIVE_FILTER['HEAD']
-_REVISION_NEGATIVE_FILTER['27'] = [] + _REVISION_NEGATIVE_FILTER['HEAD']
+
 
 _OS_NEGATIVE_FILTER = {}
 _OS_NEGATIVE_FILTER['win'] = [
@@ -159,6 +158,13 @@
     'WindowSwitchingTest.*',
 ]
 
+
+def _GetRevisionNegativeFilter(chrome_version):
+  if chrome_version in _REVISION_NEGATIVE_FILTER:
+    return _REVISION_NEGATIVE_FILTER[chrome_version]
+  return _REVISION_NEGATIVE_FILTER['HEAD']
+
+
 def GetDisabledTestMatchers(operating_system, chrome_version):
   """Returns the list of disabled test matchers for the specific configuration.
 
@@ -171,7 +177,8 @@
     List of disabled test matchers, which may contain '*' wildcards.
   """
   return (_OS_NEGATIVE_FILTER[operating_system] +
-          _REVISION_NEGATIVE_FILTER[chrome_version])[:]
+          _GetRevisionNegativeFilter(chrome_version))[:]
+
 
 def ApplyJavaTestFilter(operating_system, chrome_version, tests):
   """Applies the test filter to the given list of tests.
@@ -186,7 +193,7 @@
     Set of passed test names.
   """
   filters = (_OS_NEGATIVE_FILTER[operating_system] +
-             _REVISION_NEGATIVE_FILTER[chrome_version])
+             _GetRevisionNegativeFilter(chrome_version))
   passed = set(tests)
   for f in filters:
     passed.difference_update(set(t for t in tests if fnmatch.fnmatch(t, f)))
diff --git a/chrome/test/chromedriver/test_util.cc b/chrome/test/chromedriver/test_util.cc
index 4d2d3c6..14f1c74 100644
--- a/chrome/test/chromedriver/test_util.cc
+++ b/chrome/test/chromedriver/test_util.cc
@@ -39,15 +39,15 @@
 
 #if defined(OS_MACOSX)
 bool SwitchKeyboardLayout(const std::string& input_source_id) {
-  base::mac::ScopedCFTypeRef<CFMutableDictionaryRef> filter_dict(
+  base::ScopedCFTypeRef<CFMutableDictionaryRef> filter_dict(
       CFDictionaryCreateMutable(kCFAllocatorDefault,
                                 1,
                                 &kCFTypeDictionaryKeyCallBacks,
                                 &kCFTypeDictionaryValueCallBacks));
-  base::mac::ScopedCFTypeRef<CFStringRef> id_ref(CFStringCreateWithCString(
+  base::ScopedCFTypeRef<CFStringRef> id_ref(CFStringCreateWithCString(
       kCFAllocatorDefault, input_source_id.c_str(), kCFStringEncodingUTF8));
   CFDictionaryAddValue(filter_dict, kTISPropertyInputSourceID, id_ref);
-  base::mac::ScopedCFTypeRef<CFArrayRef> sources(
+  base::ScopedCFTypeRef<CFArrayRef> sources(
       TISCreateInputSourceList(filter_dict, true));
   if (CFArrayGetCount(sources) != 1)
     return false;
diff --git a/chrome/test/chromedriver/test_util.h b/chrome/test/chromedriver/test_util.h
index 6ef821e..e198842 100644
--- a/chrome/test/chromedriver/test_util.h
+++ b/chrome/test/chromedriver/test_util.h
@@ -27,7 +27,7 @@
 #if defined(OS_WIN)
   HKL layout_;
 #elif defined(OS_MACOSX)
-  base::mac::ScopedCFTypeRef<TISInputSourceRef> layout_;
+  base::ScopedCFTypeRef<TISInputSourceRef> layout_;
 #endif
 
   DISALLOW_COPY_AND_ASSIGN(RestoreKeyboardLayoutOnDestruct);
diff --git a/chrome/test/chromedriver/third_party/jni/LICENSE b/chrome/test/chromedriver/third_party/jni/LICENSE
deleted file mode 100644
index 80a4762..0000000
--- a/chrome/test/chromedriver/third_party/jni/LICENSE
+++ /dev/null
@@ -1,204 +0,0 @@
-
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "[]"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright 2007-2009 Google Inc.
-   Copyright 2007-2009 WebDriver committers
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-
diff --git a/chrome/test/chromedriver/third_party/jni/README.chromium b/chrome/test/chromedriver/third_party/jni/README.chromium
deleted file mode 100644
index 8a3cc33..0000000
--- a/chrome/test/chromedriver/third_party/jni/README.chromium
+++ /dev/null
@@ -1,13 +0,0 @@
-Name: Java Native Interface from Android NDK
-Short Name: JNI
-URL: http://developer.android.com/sdk/index.html
-Version: NDK r7, SDK API level 16
-Security Critical: no
-License: Apache 2
-
-Description:
-  An API for native code to interface with code running in a JVM.
-
-Local modifications:
-  -See patch.diff. Made portable to windows by adding proper JNICALL and
-   JNIEXPORT defines.
diff --git a/chrome/test/chromedriver/third_party/jni/jni.gyp b/chrome/test/chromedriver/third_party/jni/jni.gyp
deleted file mode 100644
index 152810c..0000000
--- a/chrome/test/chromedriver/third_party/jni/jni.gyp
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-{
-  'targets': [{
-    'target_name': 'jni',
-    'type': 'none',
-    'sources': [
-      'jni.h',
-    ],
-  }],
-}
diff --git a/chrome/test/chromedriver/third_party/jni/jni.h b/chrome/test/chromedriver/third_party/jni/jni.h
deleted file mode 100644
index 2c44f07..0000000
--- a/chrome/test/chromedriver/third_party/jni/jni.h
+++ /dev/null
@@ -1,1162 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * JNI specification, as defined by Sun:
- * http://java.sun.com/javase/6/docs/technotes/guides/jni/spec/jniTOC.html
- *
- * Everything here is expected to be VM-neutral.
- */
-
-#ifndef JNI_H_
-#define JNI_H_
-
-#include <stdarg.h>
-
-#ifdef _WIN32
-#define JNIIMPORT __declspec(dllimport)
-#define JNIEXPORT __declspec(dllexport)
-#define JNICALL __stdcall
-#else
-#define JNIIMPORT
-#define JNIEXPORT __attribute__ ((visibility ("default")))
-#define JNICALL
-#endif
-
-/*
- * Primitive types that match up with Java equivalents.
- */
-#ifdef HAVE_INTTYPES_H
-# include <inttypes.h>      /* C99 */
-typedef uint8_t         jboolean;       /* unsigned 8 bits */
-typedef int8_t          jbyte;          /* signed 8 bits */
-typedef uint16_t        jchar;          /* unsigned 16 bits */
-typedef int16_t         jshort;         /* signed 16 bits */
-typedef int32_t         jint;           /* signed 32 bits */
-typedef int64_t         jlong;          /* signed 64 bits */
-typedef float           jfloat;         /* 32-bit IEEE 754 */
-typedef double          jdouble;        /* 64-bit IEEE 754 */
-#else
-typedef unsigned char   jboolean;       /* unsigned 8 bits */
-typedef signed char     jbyte;          /* signed 8 bits */
-typedef unsigned short  jchar;          /* unsigned 16 bits */
-typedef short           jshort;         /* signed 16 bits */
-typedef int             jint;           /* signed 32 bits */
-typedef long long       jlong;          /* signed 64 bits */
-typedef float           jfloat;         /* 32-bit IEEE 754 */
-typedef double          jdouble;        /* 64-bit IEEE 754 */
-#endif
-
-/* "cardinal indices and sizes" */
-typedef jint            jsize;
-
-#ifdef __cplusplus
-/*
- * Reference types, in C++
- */
-class _jobject {};
-class _jclass : public _jobject {};
-class _jstring : public _jobject {};
-class _jarray : public _jobject {};
-class _jobjectArray : public _jarray {};
-class _jbooleanArray : public _jarray {};
-class _jbyteArray : public _jarray {};
-class _jcharArray : public _jarray {};
-class _jshortArray : public _jarray {};
-class _jintArray : public _jarray {};
-class _jlongArray : public _jarray {};
-class _jfloatArray : public _jarray {};
-class _jdoubleArray : public _jarray {};
-class _jthrowable : public _jobject {};
-
-typedef _jobject*       jobject;
-typedef _jclass*        jclass;
-typedef _jstring*       jstring;
-typedef _jarray*        jarray;
-typedef _jobjectArray*  jobjectArray;
-typedef _jbooleanArray* jbooleanArray;
-typedef _jbyteArray*    jbyteArray;
-typedef _jcharArray*    jcharArray;
-typedef _jshortArray*   jshortArray;
-typedef _jintArray*     jintArray;
-typedef _jlongArray*    jlongArray;
-typedef _jfloatArray*   jfloatArray;
-typedef _jdoubleArray*  jdoubleArray;
-typedef _jthrowable*    jthrowable;
-typedef _jobject*       jweak;
-
-
-#else /* not __cplusplus */
-
-/*
- * Reference types, in C.
- */
-typedef void*           jobject;
-typedef jobject         jclass;
-typedef jobject         jstring;
-typedef jobject         jarray;
-typedef jarray          jobjectArray;
-typedef jarray          jbooleanArray;
-typedef jarray          jbyteArray;
-typedef jarray          jcharArray;
-typedef jarray          jshortArray;
-typedef jarray          jintArray;
-typedef jarray          jlongArray;
-typedef jarray          jfloatArray;
-typedef jarray          jdoubleArray;
-typedef jobject         jthrowable;
-typedef jobject         jweak;
-
-#endif /* not __cplusplus */
-
-struct _jfieldID;                       /* opaque structure */
-typedef struct _jfieldID* jfieldID;     /* field IDs */
-
-struct _jmethodID;                      /* opaque structure */
-typedef struct _jmethodID* jmethodID;   /* method IDs */
-
-struct JNIInvokeInterface;
-
-typedef union jvalue {
-    jboolean    z;
-    jbyte       b;
-    jchar       c;
-    jshort      s;
-    jint        i;
-    jlong       j;
-    jfloat      f;
-    jdouble     d;
-    jobject     l;
-} jvalue;
-
-typedef enum jobjectRefType {
-    JNIInvalidRefType = 0,
-    JNILocalRefType = 1,
-    JNIGlobalRefType = 2,
-    JNIWeakGlobalRefType = 3
-} jobjectRefType;
-
-typedef struct {
-    const char* name;
-    const char* signature;
-    void*       fnPtr;
-} JNINativeMethod;
-
-struct _JNIEnv;
-struct _JavaVM;
-typedef const struct JNINativeInterface* C_JNIEnv;
-
-#if defined(__cplusplus)
-typedef _JNIEnv JNIEnv;
-typedef _JavaVM JavaVM;
-#else
-typedef const struct JNINativeInterface* JNIEnv;
-typedef const struct JNIInvokeInterface* JavaVM;
-#endif
-
-/*
- * Table of interface function pointers.
- */
-struct JNINativeInterface {
-    void*       reserved0;
-    void*       reserved1;
-    void*       reserved2;
-    void*       reserved3;
-
-    jint        (JNICALL *GetVersion)(JNIEnv *);
-
-    jclass      (JNICALL *DefineClass)(JNIEnv*, const char*, jobject, const jbyte*,
-                        jsize);
-    jclass      (JNICALL *FindClass)(JNIEnv*, const char*);
-
-    jmethodID   (JNICALL *FromReflectedMethod)(JNIEnv*, jobject);
-    jfieldID    (JNICALL *FromReflectedField)(JNIEnv*, jobject);
-    /* spec doesn't show jboolean parameter */
-    jobject     (JNICALL *ToReflectedMethod)(JNIEnv*, jclass, jmethodID, jboolean);
-
-    jclass      (JNICALL *GetSuperclass)(JNIEnv*, jclass);
-    jboolean    (JNICALL *IsAssignableFrom)(JNIEnv*, jclass, jclass);
-
-    /* spec doesn't show jboolean parameter */
-    jobject     (JNICALL *ToReflectedField)(JNIEnv*, jclass, jfieldID, jboolean);
-
-    jint        (JNICALL *Throw)(JNIEnv*, jthrowable);
-    jint        (JNICALL *ThrowNew)(JNIEnv *, jclass, const char *);
-    jthrowable  (JNICALL *ExceptionOccurred)(JNIEnv*);
-    void        (JNICALL *ExceptionDescribe)(JNIEnv*);
-    void        (JNICALL *ExceptionClear)(JNIEnv*);
-    void        (JNICALL *FatalError)(JNIEnv*, const char*);
-
-    jint        (JNICALL *PushLocalFrame)(JNIEnv*, jint);
-    jobject     (JNICALL *PopLocalFrame)(JNIEnv*, jobject);
-
-    jobject     (JNICALL *NewGlobalRef)(JNIEnv*, jobject);
-    void        (JNICALL *DeleteGlobalRef)(JNIEnv*, jobject);
-    void        (JNICALL *DeleteLocalRef)(JNIEnv*, jobject);
-    jboolean    (JNICALL *IsSameObject)(JNIEnv*, jobject, jobject);
-
-    jobject     (JNICALL *NewLocalRef)(JNIEnv*, jobject);
-    jint        (JNICALL *EnsureLocalCapacity)(JNIEnv*, jint);
-
-    jobject     (JNICALL *AllocObject)(JNIEnv*, jclass);
-    jobject     (JNICALL *NewObject)(JNIEnv*, jclass, jmethodID, ...);
-    jobject     (JNICALL *NewObjectV)(JNIEnv*, jclass, jmethodID, va_list);
-    jobject     (JNICALL *NewObjectA)(JNIEnv*, jclass, jmethodID, jvalue*);
-
-    jclass      (JNICALL *GetObjectClass)(JNIEnv*, jobject);
-    jboolean    (JNICALL *IsInstanceOf)(JNIEnv*, jobject, jclass);
-    jmethodID   (JNICALL *GetMethodID)(JNIEnv*, jclass, const char*, const char*);
-
-    jobject     (JNICALL *CallObjectMethod)(JNIEnv*, jobject, jmethodID, ...);
-    jobject     (JNICALL *CallObjectMethodV)(JNIEnv*, jobject, jmethodID, va_list);
-    jobject     (JNICALL *CallObjectMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
-    jboolean    (JNICALL *CallBooleanMethod)(JNIEnv*, jobject, jmethodID, ...);
-    jboolean    (JNICALL *CallBooleanMethodV)(JNIEnv*, jobject, jmethodID, va_list);
-    jboolean    (JNICALL *CallBooleanMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
-    jbyte       (JNICALL *CallByteMethod)(JNIEnv*, jobject, jmethodID, ...);
-    jbyte       (JNICALL *CallByteMethodV)(JNIEnv*, jobject, jmethodID, va_list);
-    jbyte       (JNICALL *CallByteMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
-    jchar       (JNICALL *CallCharMethod)(JNIEnv*, jobject, jmethodID, ...);
-    jchar       (JNICALL *CallCharMethodV)(JNIEnv*, jobject, jmethodID, va_list);
-    jchar       (JNICALL *CallCharMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
-    jshort      (JNICALL *CallShortMethod)(JNIEnv*, jobject, jmethodID, ...);
-    jshort      (JNICALL *CallShortMethodV)(JNIEnv*, jobject, jmethodID, va_list);
-    jshort      (JNICALL *CallShortMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
-    jint        (JNICALL *CallIntMethod)(JNIEnv*, jobject, jmethodID, ...);
-    jint        (JNICALL *CallIntMethodV)(JNIEnv*, jobject, jmethodID, va_list);
-    jint        (JNICALL *CallIntMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
-    jlong       (JNICALL *CallLongMethod)(JNIEnv*, jobject, jmethodID, ...);
-    jlong       (JNICALL *CallLongMethodV)(JNIEnv*, jobject, jmethodID, va_list);
-    jlong       (JNICALL *CallLongMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
-    jfloat      (JNICALL *CallFloatMethod)(JNIEnv*, jobject, jmethodID, ...);
-    jfloat      (JNICALL *CallFloatMethodV)(JNIEnv*, jobject, jmethodID, va_list);
-    jfloat      (JNICALL *CallFloatMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
-    jdouble     (JNICALL *CallDoubleMethod)(JNIEnv*, jobject, jmethodID, ...);
-    jdouble     (JNICALL *CallDoubleMethodV)(JNIEnv*, jobject, jmethodID, va_list);
-    jdouble     (JNICALL *CallDoubleMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
-    void        (JNICALL *CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
-    void        (JNICALL *CallVoidMethodV)(JNIEnv*, jobject, jmethodID, va_list);
-    void        (JNICALL *CallVoidMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
-
-    jobject     (JNICALL *CallNonvirtualObjectMethod)(JNIEnv*, jobject, jclass,
-                        jmethodID, ...);
-    jobject     (JNICALL *CallNonvirtualObjectMethodV)(JNIEnv*, jobject, jclass,
-                        jmethodID, va_list);
-    jobject     (JNICALL *CallNonvirtualObjectMethodA)(JNIEnv*, jobject, jclass,
-                        jmethodID, jvalue*);
-    jboolean    (JNICALL *CallNonvirtualBooleanMethod)(JNIEnv*, jobject, jclass,
-                        jmethodID, ...);
-    jboolean    (JNICALL *CallNonvirtualBooleanMethodV)(JNIEnv*, jobject, jclass,
-                         jmethodID, va_list);
-    jboolean    (JNICALL *CallNonvirtualBooleanMethodA)(JNIEnv*, jobject, jclass,
-                         jmethodID, jvalue*);
-    jbyte       (JNICALL *CallNonvirtualByteMethod)(JNIEnv*, jobject, jclass,
-                        jmethodID, ...);
-    jbyte       (JNICALL *CallNonvirtualByteMethodV)(JNIEnv*, jobject, jclass,
-                        jmethodID, va_list);
-    jbyte       (JNICALL *CallNonvirtualByteMethodA)(JNIEnv*, jobject, jclass,
-                        jmethodID, jvalue*);
-    jchar       (JNICALL *CallNonvirtualCharMethod)(JNIEnv*, jobject, jclass,
-                        jmethodID, ...);
-    jchar       (JNICALL *CallNonvirtualCharMethodV)(JNIEnv*, jobject, jclass,
-                        jmethodID, va_list);
-    jchar       (JNICALL *CallNonvirtualCharMethodA)(JNIEnv*, jobject, jclass,
-                        jmethodID, jvalue*);
-    jshort      (JNICALL *CallNonvirtualShortMethod)(JNIEnv*, jobject, jclass,
-                        jmethodID, ...);
-    jshort      (JNICALL *CallNonvirtualShortMethodV)(JNIEnv*, jobject, jclass,
-                        jmethodID, va_list);
-    jshort      (JNICALL *CallNonvirtualShortMethodA)(JNIEnv*, jobject, jclass,
-                        jmethodID, jvalue*);
-    jint        (JNICALL *CallNonvirtualIntMethod)(JNIEnv*, jobject, jclass,
-                        jmethodID, ...);
-    jint        (JNICALL *CallNonvirtualIntMethodV)(JNIEnv*, jobject, jclass,
-                        jmethodID, va_list);
-    jint        (JNICALL *CallNonvirtualIntMethodA)(JNIEnv*, jobject, jclass,
-                        jmethodID, jvalue*);
-    jlong       (JNICALL *CallNonvirtualLongMethod)(JNIEnv*, jobject, jclass,
-                        jmethodID, ...);
-    jlong       (JNICALL *CallNonvirtualLongMethodV)(JNIEnv*, jobject, jclass,
-                        jmethodID, va_list);
-    jlong       (JNICALL *CallNonvirtualLongMethodA)(JNIEnv*, jobject, jclass,
-                        jmethodID, jvalue*);
-    jfloat      (JNICALL *CallNonvirtualFloatMethod)(JNIEnv*, jobject, jclass,
-                        jmethodID, ...);
-    jfloat      (JNICALL *CallNonvirtualFloatMethodV)(JNIEnv*, jobject, jclass,
-                        jmethodID, va_list);
-    jfloat      (JNICALL *CallNonvirtualFloatMethodA)(JNIEnv*, jobject, jclass,
-                        jmethodID, jvalue*);
-    jdouble     (JNICALL *CallNonvirtualDoubleMethod)(JNIEnv*, jobject, jclass,
-                        jmethodID, ...);
-    jdouble     (JNICALL *CallNonvirtualDoubleMethodV)(JNIEnv*, jobject, jclass,
-                        jmethodID, va_list);
-    jdouble     (JNICALL *CallNonvirtualDoubleMethodA)(JNIEnv*, jobject, jclass,
-                        jmethodID, jvalue*);
-    void        (JNICALL *CallNonvirtualVoidMethod)(JNIEnv*, jobject, jclass,
-                        jmethodID, ...);
-    void        (JNICALL *CallNonvirtualVoidMethodV)(JNIEnv*, jobject, jclass,
-                        jmethodID, va_list);
-    void        (JNICALL *CallNonvirtualVoidMethodA)(JNIEnv*, jobject, jclass,
-                        jmethodID, jvalue*);
-
-    jfieldID    (JNICALL *GetFieldID)(JNIEnv*, jclass, const char*, const char*);
-
-    jobject     (JNICALL *GetObjectField)(JNIEnv*, jobject, jfieldID);
-    jboolean    (JNICALL *GetBooleanField)(JNIEnv*, jobject, jfieldID);
-    jbyte       (JNICALL *GetByteField)(JNIEnv*, jobject, jfieldID);
-    jchar       (JNICALL *GetCharField)(JNIEnv*, jobject, jfieldID);
-    jshort      (JNICALL *GetShortField)(JNIEnv*, jobject, jfieldID);
-    jint        (JNICALL *GetIntField)(JNIEnv*, jobject, jfieldID);
-    jlong       (JNICALL *GetLongField)(JNIEnv*, jobject, jfieldID);
-    jfloat      (JNICALL *GetFloatField)(JNIEnv*, jobject, jfieldID);
-    jdouble     (JNICALL *GetDoubleField)(JNIEnv*, jobject, jfieldID);
-
-    void        (JNICALL *SetObjectField)(JNIEnv*, jobject, jfieldID, jobject);
-    void        (JNICALL *SetBooleanField)(JNIEnv*, jobject, jfieldID, jboolean);
-    void        (JNICALL *SetByteField)(JNIEnv*, jobject, jfieldID, jbyte);
-    void        (JNICALL *SetCharField)(JNIEnv*, jobject, jfieldID, jchar);
-    void        (JNICALL *SetShortField)(JNIEnv*, jobject, jfieldID, jshort);
-    void        (JNICALL *SetIntField)(JNIEnv*, jobject, jfieldID, jint);
-    void        (JNICALL *SetLongField)(JNIEnv*, jobject, jfieldID, jlong);
-    void        (JNICALL *SetFloatField)(JNIEnv*, jobject, jfieldID, jfloat);
-    void        (JNICALL *SetDoubleField)(JNIEnv*, jobject, jfieldID, jdouble);
-
-    jmethodID   (JNICALL *GetStaticMethodID)(JNIEnv*, jclass, const char*, const char*);
-
-    jobject     (JNICALL *CallStaticObjectMethod)(JNIEnv*, jclass, jmethodID, ...);
-    jobject     (JNICALL *CallStaticObjectMethodV)(JNIEnv*, jclass, jmethodID, va_list);
-    jobject     (JNICALL *CallStaticObjectMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);
-    jboolean    (JNICALL *CallStaticBooleanMethod)(JNIEnv*, jclass, jmethodID, ...);
-    jboolean    (JNICALL *CallStaticBooleanMethodV)(JNIEnv*, jclass, jmethodID,
-                        va_list);
-    jboolean    (JNICALL *CallStaticBooleanMethodA)(JNIEnv*, jclass, jmethodID,
-                        jvalue*);
-    jbyte       (JNICALL *CallStaticByteMethod)(JNIEnv*, jclass, jmethodID, ...);
-    jbyte       (JNICALL *CallStaticByteMethodV)(JNIEnv*, jclass, jmethodID, va_list);
-    jbyte       (JNICALL *CallStaticByteMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);
-    jchar       (JNICALL *CallStaticCharMethod)(JNIEnv*, jclass, jmethodID, ...);
-    jchar       (JNICALL *CallStaticCharMethodV)(JNIEnv*, jclass, jmethodID, va_list);
-    jchar       (JNICALL *CallStaticCharMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);
-    jshort      (JNICALL *CallStaticShortMethod)(JNIEnv*, jclass, jmethodID, ...);
-    jshort      (JNICALL *CallStaticShortMethodV)(JNIEnv*, jclass, jmethodID, va_list);
-    jshort      (JNICALL *CallStaticShortMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);
-    jint        (JNICALL *CallStaticIntMethod)(JNIEnv*, jclass, jmethodID, ...);
-    jint        (JNICALL *CallStaticIntMethodV)(JNIEnv*, jclass, jmethodID, va_list);
-    jint        (JNICALL *CallStaticIntMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);
-    jlong       (JNICALL *CallStaticLongMethod)(JNIEnv*, jclass, jmethodID, ...);
-    jlong       (JNICALL *CallStaticLongMethodV)(JNIEnv*, jclass, jmethodID, va_list);
-    jlong       (JNICALL *CallStaticLongMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);
-    jfloat      (JNICALL *CallStaticFloatMethod)(JNIEnv*, jclass, jmethodID, ...);
-    jfloat      (JNICALL *CallStaticFloatMethodV)(JNIEnv*, jclass, jmethodID, va_list);
-    jfloat      (JNICALL *CallStaticFloatMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);
-    jdouble     (JNICALL *CallStaticDoubleMethod)(JNIEnv*, jclass, jmethodID, ...);
-    jdouble     (JNICALL *CallStaticDoubleMethodV)(JNIEnv*, jclass, jmethodID, va_list);
-    jdouble     (JNICALL *CallStaticDoubleMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);
-    void        (JNICALL *CallStaticVoidMethod)(JNIEnv*, jclass, jmethodID, ...);
-    void        (JNICALL *CallStaticVoidMethodV)(JNIEnv*, jclass, jmethodID, va_list);
-    void        (JNICALL *CallStaticVoidMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);
-
-    jfieldID    (JNICALL *GetStaticFieldID)(JNIEnv*, jclass, const char*,
-                        const char*);
-
-    jobject     (JNICALL *GetStaticObjectField)(JNIEnv*, jclass, jfieldID);
-    jboolean    (JNICALL *GetStaticBooleanField)(JNIEnv*, jclass, jfieldID);
-    jbyte       (JNICALL *GetStaticByteField)(JNIEnv*, jclass, jfieldID);
-    jchar       (JNICALL *GetStaticCharField)(JNIEnv*, jclass, jfieldID);
-    jshort      (JNICALL *GetStaticShortField)(JNIEnv*, jclass, jfieldID);
-    jint        (JNICALL *GetStaticIntField)(JNIEnv*, jclass, jfieldID);
-    jlong       (JNICALL *GetStaticLongField)(JNIEnv*, jclass, jfieldID);
-    jfloat      (JNICALL *GetStaticFloatField)(JNIEnv*, jclass, jfieldID);
-    jdouble     (JNICALL *GetStaticDoubleField)(JNIEnv*, jclass, jfieldID);
-
-    void        (JNICALL *SetStaticObjectField)(JNIEnv*, jclass, jfieldID, jobject);
-    void        (JNICALL *SetStaticBooleanField)(JNIEnv*, jclass, jfieldID, jboolean);
-    void        (JNICALL *SetStaticByteField)(JNIEnv*, jclass, jfieldID, jbyte);
-    void        (JNICALL *SetStaticCharField)(JNIEnv*, jclass, jfieldID, jchar);
-    void        (JNICALL *SetStaticShortField)(JNIEnv*, jclass, jfieldID, jshort);
-    void        (JNICALL *SetStaticIntField)(JNIEnv*, jclass, jfieldID, jint);
-    void        (JNICALL *SetStaticLongField)(JNIEnv*, jclass, jfieldID, jlong);
-    void        (JNICALL *SetStaticFloatField)(JNIEnv*, jclass, jfieldID, jfloat);
-    void        (JNICALL *SetStaticDoubleField)(JNIEnv*, jclass, jfieldID, jdouble);
-
-    jstring     (JNICALL *NewString)(JNIEnv*, const jchar*, jsize);
-    jsize       (JNICALL *GetStringLength)(JNIEnv*, jstring);
-    const jchar* (JNICALL *GetStringChars)(JNIEnv*, jstring, jboolean*);
-    void        (JNICALL *ReleaseStringChars)(JNIEnv*, jstring, const jchar*);
-    jstring     (JNICALL *NewStringUTF)(JNIEnv*, const char*);
-    jsize       (JNICALL *GetStringUTFLength)(JNIEnv*, jstring);
-    /* JNI spec says this returns const jbyte*, but that's inconsistent */
-    const char* (JNICALL *GetStringUTFChars)(JNIEnv*, jstring, jboolean*);
-    void        (JNICALL *ReleaseStringUTFChars)(JNIEnv*, jstring, const char*);
-    jsize       (JNICALL *GetArrayLength)(JNIEnv*, jarray);
-    jobjectArray (JNICALL *NewObjectArray)(JNIEnv*, jsize, jclass, jobject);
-    jobject     (JNICALL *GetObjectArrayElement)(JNIEnv*, jobjectArray, jsize);
-    void        (JNICALL *SetObjectArrayElement)(JNIEnv*, jobjectArray, jsize, jobject);
-
-    jbooleanArray (JNICALL *NewBooleanArray)(JNIEnv*, jsize);
-    jbyteArray    (JNICALL *NewByteArray)(JNIEnv*, jsize);
-    jcharArray    (JNICALL *NewCharArray)(JNIEnv*, jsize);
-    jshortArray   (JNICALL *NewShortArray)(JNIEnv*, jsize);
-    jintArray     (JNICALL *NewIntArray)(JNIEnv*, jsize);
-    jlongArray    (JNICALL *NewLongArray)(JNIEnv*, jsize);
-    jfloatArray   (JNICALL *NewFloatArray)(JNIEnv*, jsize);
-    jdoubleArray  (JNICALL *NewDoubleArray)(JNIEnv*, jsize);
-
-    jboolean*   (JNICALL *GetBooleanArrayElements)(JNIEnv*, jbooleanArray, jboolean*);
-    jbyte*      (JNICALL *GetByteArrayElements)(JNIEnv*, jbyteArray, jboolean*);
-    jchar*      (JNICALL *GetCharArrayElements)(JNIEnv*, jcharArray, jboolean*);
-    jshort*     (JNICALL *GetShortArrayElements)(JNIEnv*, jshortArray, jboolean*);
-    jint*       (JNICALL *GetIntArrayElements)(JNIEnv*, jintArray, jboolean*);
-    jlong*      (JNICALL *GetLongArrayElements)(JNIEnv*, jlongArray, jboolean*);
-    jfloat*     (JNICALL *GetFloatArrayElements)(JNIEnv*, jfloatArray, jboolean*);
-    jdouble*    (JNICALL *GetDoubleArrayElements)(JNIEnv*, jdoubleArray, jboolean*);
-
-    void        (JNICALL *ReleaseBooleanArrayElements)(JNIEnv*, jbooleanArray,
-                        jboolean*, jint);
-    void        (JNICALL *ReleaseByteArrayElements)(JNIEnv*, jbyteArray,
-                        jbyte*, jint);
-    void        (JNICALL *ReleaseCharArrayElements)(JNIEnv*, jcharArray,
-                        jchar*, jint);
-    void        (JNICALL *ReleaseShortArrayElements)(JNIEnv*, jshortArray,
-                        jshort*, jint);
-    void        (JNICALL *ReleaseIntArrayElements)(JNIEnv*, jintArray,
-                        jint*, jint);
-    void        (JNICALL *ReleaseLongArrayElements)(JNIEnv*, jlongArray,
-                        jlong*, jint);
-    void        (JNICALL *ReleaseFloatArrayElements)(JNIEnv*, jfloatArray,
-                        jfloat*, jint);
-    void        (JNICALL *ReleaseDoubleArrayElements)(JNIEnv*, jdoubleArray,
-                        jdouble*, jint);
-
-    void        (JNICALL *GetBooleanArrayRegion)(JNIEnv*, jbooleanArray,
-                        jsize, jsize, jboolean*);
-    void        (JNICALL *GetByteArrayRegion)(JNIEnv*, jbyteArray,
-                        jsize, jsize, jbyte*);
-    void        (JNICALL *GetCharArrayRegion)(JNIEnv*, jcharArray,
-                        jsize, jsize, jchar*);
-    void        (JNICALL *GetShortArrayRegion)(JNIEnv*, jshortArray,
-                        jsize, jsize, jshort*);
-    void        (JNICALL *GetIntArrayRegion)(JNIEnv*, jintArray,
-                        jsize, jsize, jint*);
-    void        (JNICALL *GetLongArrayRegion)(JNIEnv*, jlongArray,
-                        jsize, jsize, jlong*);
-    void        (JNICALL *GetFloatArrayRegion)(JNIEnv*, jfloatArray,
-                        jsize, jsize, jfloat*);
-    void        (JNICALL *GetDoubleArrayRegion)(JNIEnv*, jdoubleArray,
-                        jsize, jsize, jdouble*);
-
-    /* spec shows these without const; some jni.h do, some don't */
-    void        (JNICALL *SetBooleanArrayRegion)(JNIEnv*, jbooleanArray,
-                        jsize, jsize, const jboolean*);
-    void        (JNICALL *SetByteArrayRegion)(JNIEnv*, jbyteArray,
-                        jsize, jsize, const jbyte*);
-    void        (JNICALL *SetCharArrayRegion)(JNIEnv*, jcharArray,
-                        jsize, jsize, const jchar*);
-    void        (JNICALL *SetShortArrayRegion)(JNIEnv*, jshortArray,
-                        jsize, jsize, const jshort*);
-    void        (JNICALL *SetIntArrayRegion)(JNIEnv*, jintArray,
-                        jsize, jsize, const jint*);
-    void        (JNICALL *SetLongArrayRegion)(JNIEnv*, jlongArray,
-                        jsize, jsize, const jlong*);
-    void        (JNICALL *SetFloatArrayRegion)(JNIEnv*, jfloatArray,
-                        jsize, jsize, const jfloat*);
-    void        (JNICALL *SetDoubleArrayRegion)(JNIEnv*, jdoubleArray,
-                        jsize, jsize, const jdouble*);
-
-    jint        (JNICALL *RegisterNatives)(JNIEnv*, jclass, const JNINativeMethod*,
-                        jint);
-    jint        (JNICALL *UnregisterNatives)(JNIEnv*, jclass);
-    jint        (JNICALL *MonitorEnter)(JNIEnv*, jobject);
-    jint        (JNICALL *MonitorExit)(JNIEnv*, jobject);
-    jint        (JNICALL *GetJavaVM)(JNIEnv*, JavaVM**);
-
-    void        (JNICALL *GetStringRegion)(JNIEnv*, jstring, jsize, jsize, jchar*);
-    void        (JNICALL *GetStringUTFRegion)(JNIEnv*, jstring, jsize, jsize, char*);
-
-    void*       (JNICALL *GetPrimitiveArrayCritical)(JNIEnv*, jarray, jboolean*);
-    void        (JNICALL *ReleasePrimitiveArrayCritical)(JNIEnv*, jarray, void*, jint);
-
-    const jchar* (JNICALL *GetStringCritical)(JNIEnv*, jstring, jboolean*);
-    void        (JNICALL *ReleaseStringCritical)(JNIEnv*, jstring, const jchar*);
-
-    jweak       (JNICALL *NewWeakGlobalRef)(JNIEnv*, jobject);
-    void        (JNICALL *DeleteWeakGlobalRef)(JNIEnv*, jweak);
-
-    jboolean    (JNICALL *ExceptionCheck)(JNIEnv*);
-
-    jobject     (JNICALL *NewDirectByteBuffer)(JNIEnv*, void*, jlong);
-    void*       (JNICALL *GetDirectBufferAddress)(JNIEnv*, jobject);
-    jlong       (JNICALL *GetDirectBufferCapacity)(JNIEnv*, jobject);
-
-    /* added in JNI 1.6 */
-    jobjectRefType (JNICALL *GetObjectRefType)(JNIEnv*, jobject);
-};
-
-/*
- * C++ object wrapper.
- *
- * This is usually overlaid on a C struct whose first element is a
- * JNINativeInterface*.  We rely somewhat on compiler behavior.
- */
-struct _JNIEnv {
-    /* do not rename this; it does not seem to be entirely opaque */
-    const struct JNINativeInterface* functions;
-
-#if defined(__cplusplus)
-
-    jint GetVersion()
-    { return functions->GetVersion(this); }
-
-    jclass DefineClass(const char *name, jobject loader, const jbyte* buf,
-        jsize bufLen)
-    { return functions->DefineClass(this, name, loader, buf, bufLen); }
-
-    jclass FindClass(const char* name)
-    { return functions->FindClass(this, name); }
-
-    jmethodID FromReflectedMethod(jobject method)
-    { return functions->FromReflectedMethod(this, method); }
-
-    jfieldID FromReflectedField(jobject field)
-    { return functions->FromReflectedField(this, field); }
-
-    jobject ToReflectedMethod(jclass cls, jmethodID methodID, jboolean isStatic)
-    { return functions->ToReflectedMethod(this, cls, methodID, isStatic); }
-
-    jclass GetSuperclass(jclass clazz)
-    { return functions->GetSuperclass(this, clazz); }
-
-    jboolean IsAssignableFrom(jclass clazz1, jclass clazz2)
-    { return functions->IsAssignableFrom(this, clazz1, clazz2); }
-
-    jobject ToReflectedField(jclass cls, jfieldID fieldID, jboolean isStatic)
-    { return functions->ToReflectedField(this, cls, fieldID, isStatic); }
-
-    jint Throw(jthrowable obj)
-    { return functions->Throw(this, obj); }
-
-    jint ThrowNew(jclass clazz, const char* message)
-    { return functions->ThrowNew(this, clazz, message); }
-
-    jthrowable ExceptionOccurred()
-    { return functions->ExceptionOccurred(this); }
-
-    void ExceptionDescribe()
-    { functions->ExceptionDescribe(this); }
-
-    void ExceptionClear()
-    { functions->ExceptionClear(this); }
-
-    void FatalError(const char* msg)
-    { functions->FatalError(this, msg); }
-
-    jint PushLocalFrame(jint capacity)
-    { return functions->PushLocalFrame(this, capacity); }
-
-    jobject PopLocalFrame(jobject result)
-    { return functions->PopLocalFrame(this, result); }
-
-    jobject NewGlobalRef(jobject obj)
-    { return functions->NewGlobalRef(this, obj); }
-
-    void DeleteGlobalRef(jobject globalRef)
-    { functions->DeleteGlobalRef(this, globalRef); }
-
-    void DeleteLocalRef(jobject localRef)
-    { functions->DeleteLocalRef(this, localRef); }
-
-    jboolean IsSameObject(jobject ref1, jobject ref2)
-    { return functions->IsSameObject(this, ref1, ref2); }
-
-    jobject NewLocalRef(jobject ref)
-    { return functions->NewLocalRef(this, ref); }
-
-    jint EnsureLocalCapacity(jint capacity)
-    { return functions->EnsureLocalCapacity(this, capacity); }
-
-    jobject AllocObject(jclass clazz)
-    { return functions->AllocObject(this, clazz); }
-
-    jobject NewObject(jclass clazz, jmethodID methodID, ...)
-    {
-        va_list args;
-        va_start(args, methodID);
-        jobject result = functions->NewObjectV(this, clazz, methodID, args);
-        va_end(args);
-        return result;
-    }
-
-    jobject NewObjectV(jclass clazz, jmethodID methodID, va_list args)
-    { return functions->NewObjectV(this, clazz, methodID, args); }
-
-    jobject NewObjectA(jclass clazz, jmethodID methodID, jvalue* args)
-    { return functions->NewObjectA(this, clazz, methodID, args); }
-
-    jclass GetObjectClass(jobject obj)
-    { return functions->GetObjectClass(this, obj); }
-
-    jboolean IsInstanceOf(jobject obj, jclass clazz)
-    { return functions->IsInstanceOf(this, obj, clazz); }
-
-    jmethodID GetMethodID(jclass clazz, const char* name, const char* sig)
-    { return functions->GetMethodID(this, clazz, name, sig); }
-
-#define CALL_TYPE_METHOD(_jtype, _jname)                                    \
-    _jtype Call##_jname##Method(jobject obj, jmethodID methodID, ...)       \
-    {                                                                       \
-        _jtype result;                                                      \
-        va_list args;                                                       \
-        va_start(args, methodID);                                           \
-        result = functions->Call##_jname##MethodV(this, obj, methodID,      \
-                    args);                                                  \
-        va_end(args);                                                       \
-        return result;                                                      \
-    }
-#define CALL_TYPE_METHODV(_jtype, _jname)                                   \
-    _jtype Call##_jname##MethodV(jobject obj, jmethodID methodID,           \
-        va_list args)                                                       \
-    { return functions->Call##_jname##MethodV(this, obj, methodID, args); }
-#define CALL_TYPE_METHODA(_jtype, _jname)                                   \
-    _jtype Call##_jname##MethodA(jobject obj, jmethodID methodID,           \
-        jvalue* args)                                                       \
-    { return functions->Call##_jname##MethodA(this, obj, methodID, args); }
-
-#define CALL_TYPE(_jtype, _jname)                                           \
-    CALL_TYPE_METHOD(_jtype, _jname)                                        \
-    CALL_TYPE_METHODV(_jtype, _jname)                                       \
-    CALL_TYPE_METHODA(_jtype, _jname)
-
-    CALL_TYPE(jobject, Object)
-    CALL_TYPE(jboolean, Boolean)
-    CALL_TYPE(jbyte, Byte)
-    CALL_TYPE(jchar, Char)
-    CALL_TYPE(jshort, Short)
-    CALL_TYPE(jint, Int)
-    CALL_TYPE(jlong, Long)
-    CALL_TYPE(jfloat, Float)
-    CALL_TYPE(jdouble, Double)
-
-    void CallVoidMethod(jobject obj, jmethodID methodID, ...)
-    {
-        va_list args;
-        va_start(args, methodID);
-        functions->CallVoidMethodV(this, obj, methodID, args);
-        va_end(args);
-    }
-    void CallVoidMethodV(jobject obj, jmethodID methodID, va_list args)
-    { functions->CallVoidMethodV(this, obj, methodID, args); }
-    void CallVoidMethodA(jobject obj, jmethodID methodID, jvalue* args)
-    { functions->CallVoidMethodA(this, obj, methodID, args); }
-
-#define CALL_NONVIRT_TYPE_METHOD(_jtype, _jname)                            \
-    _jtype CallNonvirtual##_jname##Method(jobject obj, jclass clazz,        \
-        jmethodID methodID, ...)                                            \
-    {                                                                       \
-        _jtype result;                                                      \
-        va_list args;                                                       \
-        va_start(args, methodID);                                           \
-        result = functions->CallNonvirtual##_jname##MethodV(this, obj,      \
-                    clazz, methodID, args);                                 \
-        va_end(args);                                                       \
-        return result;                                                      \
-    }
-#define CALL_NONVIRT_TYPE_METHODV(_jtype, _jname)                           \
-    _jtype CallNonvirtual##_jname##MethodV(jobject obj, jclass clazz,       \
-        jmethodID methodID, va_list args)                                   \
-    { return functions->CallNonvirtual##_jname##MethodV(this, obj, clazz,   \
-        methodID, args); }
-#define CALL_NONVIRT_TYPE_METHODA(_jtype, _jname)                           \
-    _jtype CallNonvirtual##_jname##MethodA(jobject obj, jclass clazz,       \
-        jmethodID methodID, jvalue* args)                                   \
-    { return functions->CallNonvirtual##_jname##MethodA(this, obj, clazz,   \
-        methodID, args); }
-
-#define CALL_NONVIRT_TYPE(_jtype, _jname)                                   \
-    CALL_NONVIRT_TYPE_METHOD(_jtype, _jname)                                \
-    CALL_NONVIRT_TYPE_METHODV(_jtype, _jname)                               \
-    CALL_NONVIRT_TYPE_METHODA(_jtype, _jname)
-
-    CALL_NONVIRT_TYPE(jobject, Object)
-    CALL_NONVIRT_TYPE(jboolean, Boolean)
-    CALL_NONVIRT_TYPE(jbyte, Byte)
-    CALL_NONVIRT_TYPE(jchar, Char)
-    CALL_NONVIRT_TYPE(jshort, Short)
-    CALL_NONVIRT_TYPE(jint, Int)
-    CALL_NONVIRT_TYPE(jlong, Long)
-    CALL_NONVIRT_TYPE(jfloat, Float)
-    CALL_NONVIRT_TYPE(jdouble, Double)
-
-    void CallNonvirtualVoidMethod(jobject obj, jclass clazz,
-        jmethodID methodID, ...)
-    {
-        va_list args;
-        va_start(args, methodID);
-        functions->CallNonvirtualVoidMethodV(this, obj, clazz, methodID, args);
-        va_end(args);
-    }
-    void CallNonvirtualVoidMethodV(jobject obj, jclass clazz,
-        jmethodID methodID, va_list args)
-    { functions->CallNonvirtualVoidMethodV(this, obj, clazz, methodID, args); }
-    void CallNonvirtualVoidMethodA(jobject obj, jclass clazz,
-        jmethodID methodID, jvalue* args)
-    { functions->CallNonvirtualVoidMethodA(this, obj, clazz, methodID, args); }
-
-    jfieldID GetFieldID(jclass clazz, const char* name, const char* sig)
-    { return functions->GetFieldID(this, clazz, name, sig); }
-
-    jobject GetObjectField(jobject obj, jfieldID fieldID)
-    { return functions->GetObjectField(this, obj, fieldID); }
-    jboolean GetBooleanField(jobject obj, jfieldID fieldID)
-    { return functions->GetBooleanField(this, obj, fieldID); }
-    jbyte GetByteField(jobject obj, jfieldID fieldID)
-    { return functions->GetByteField(this, obj, fieldID); }
-    jchar GetCharField(jobject obj, jfieldID fieldID)
-    { return functions->GetCharField(this, obj, fieldID); }
-    jshort GetShortField(jobject obj, jfieldID fieldID)
-    { return functions->GetShortField(this, obj, fieldID); }
-    jint GetIntField(jobject obj, jfieldID fieldID)
-    { return functions->GetIntField(this, obj, fieldID); }
-    jlong GetLongField(jobject obj, jfieldID fieldID)
-    { return functions->GetLongField(this, obj, fieldID); }
-    jfloat GetFloatField(jobject obj, jfieldID fieldID)
-    { return functions->GetFloatField(this, obj, fieldID); }
-    jdouble GetDoubleField(jobject obj, jfieldID fieldID)
-    { return functions->GetDoubleField(this, obj, fieldID); }
-
-    void SetObjectField(jobject obj, jfieldID fieldID, jobject value)
-    { functions->SetObjectField(this, obj, fieldID, value); }
-    void SetBooleanField(jobject obj, jfieldID fieldID, jboolean value)
-    { functions->SetBooleanField(this, obj, fieldID, value); }
-    void SetByteField(jobject obj, jfieldID fieldID, jbyte value)
-    { functions->SetByteField(this, obj, fieldID, value); }
-    void SetCharField(jobject obj, jfieldID fieldID, jchar value)
-    { functions->SetCharField(this, obj, fieldID, value); }
-    void SetShortField(jobject obj, jfieldID fieldID, jshort value)
-    { functions->SetShortField(this, obj, fieldID, value); }
-    void SetIntField(jobject obj, jfieldID fieldID, jint value)
-    { functions->SetIntField(this, obj, fieldID, value); }
-    void SetLongField(jobject obj, jfieldID fieldID, jlong value)
-    { functions->SetLongField(this, obj, fieldID, value); }
-    void SetFloatField(jobject obj, jfieldID fieldID, jfloat value)
-    { functions->SetFloatField(this, obj, fieldID, value); }
-    void SetDoubleField(jobject obj, jfieldID fieldID, jdouble value)
-    { functions->SetDoubleField(this, obj, fieldID, value); }
-
-    jmethodID GetStaticMethodID(jclass clazz, const char* name, const char* sig)
-    { return functions->GetStaticMethodID(this, clazz, name, sig); }
-
-#define CALL_STATIC_TYPE_METHOD(_jtype, _jname)                             \
-    _jtype CallStatic##_jname##Method(jclass clazz, jmethodID methodID,     \
-        ...)                                                                \
-    {                                                                       \
-        _jtype result;                                                      \
-        va_list args;                                                       \
-        va_start(args, methodID);                                           \
-        result = functions->CallStatic##_jname##MethodV(this, clazz,        \
-                    methodID, args);                                        \
-        va_end(args);                                                       \
-        return result;                                                      \
-    }
-#define CALL_STATIC_TYPE_METHODV(_jtype, _jname)                            \
-    _jtype CallStatic##_jname##MethodV(jclass clazz, jmethodID methodID,    \
-        va_list args)                                                       \
-    { return functions->CallStatic##_jname##MethodV(this, clazz, methodID,  \
-        args); }
-#define CALL_STATIC_TYPE_METHODA(_jtype, _jname)                            \
-    _jtype CallStatic##_jname##MethodA(jclass clazz, jmethodID methodID,    \
-        jvalue* args)                                                       \
-    { return functions->CallStatic##_jname##MethodA(this, clazz, methodID,  \
-        args); }
-
-#define CALL_STATIC_TYPE(_jtype, _jname)                                    \
-    CALL_STATIC_TYPE_METHOD(_jtype, _jname)                                 \
-    CALL_STATIC_TYPE_METHODV(_jtype, _jname)                                \
-    CALL_STATIC_TYPE_METHODA(_jtype, _jname)
-
-    CALL_STATIC_TYPE(jobject, Object)
-    CALL_STATIC_TYPE(jboolean, Boolean)
-    CALL_STATIC_TYPE(jbyte, Byte)
-    CALL_STATIC_TYPE(jchar, Char)
-    CALL_STATIC_TYPE(jshort, Short)
-    CALL_STATIC_TYPE(jint, Int)
-    CALL_STATIC_TYPE(jlong, Long)
-    CALL_STATIC_TYPE(jfloat, Float)
-    CALL_STATIC_TYPE(jdouble, Double)
-
-    void CallStaticVoidMethod(jclass clazz, jmethodID methodID, ...)
-    {
-        va_list args;
-        va_start(args, methodID);
-        functions->CallStaticVoidMethodV(this, clazz, methodID, args);
-        va_end(args);
-    }
-    void CallStaticVoidMethodV(jclass clazz, jmethodID methodID, va_list args)
-    { functions->CallStaticVoidMethodV(this, clazz, methodID, args); }
-    void CallStaticVoidMethodA(jclass clazz, jmethodID methodID, jvalue* args)
-    { functions->CallStaticVoidMethodA(this, clazz, methodID, args); }
-
-    jfieldID GetStaticFieldID(jclass clazz, const char* name, const char* sig)
-    { return functions->GetStaticFieldID(this, clazz, name, sig); }
-
-    jobject GetStaticObjectField(jclass clazz, jfieldID fieldID)
-    { return functions->GetStaticObjectField(this, clazz, fieldID); }
-    jboolean GetStaticBooleanField(jclass clazz, jfieldID fieldID)
-    { return functions->GetStaticBooleanField(this, clazz, fieldID); }
-    jbyte GetStaticByteField(jclass clazz, jfieldID fieldID)
-    { return functions->GetStaticByteField(this, clazz, fieldID); }
-    jchar GetStaticCharField(jclass clazz, jfieldID fieldID)
-    { return functions->GetStaticCharField(this, clazz, fieldID); }
-    jshort GetStaticShortField(jclass clazz, jfieldID fieldID)
-    { return functions->GetStaticShortField(this, clazz, fieldID); }
-    jint GetStaticIntField(jclass clazz, jfieldID fieldID)
-    { return functions->GetStaticIntField(this, clazz, fieldID); }
-    jlong GetStaticLongField(jclass clazz, jfieldID fieldID)
-    { return functions->GetStaticLongField(this, clazz, fieldID); }
-    jfloat GetStaticFloatField(jclass clazz, jfieldID fieldID)
-    { return functions->GetStaticFloatField(this, clazz, fieldID); }
-    jdouble GetStaticDoubleField(jclass clazz, jfieldID fieldID)
-    { return functions->GetStaticDoubleField(this, clazz, fieldID); }
-
-    void SetStaticObjectField(jclass clazz, jfieldID fieldID, jobject value)
-    { functions->SetStaticObjectField(this, clazz, fieldID, value); }
-    void SetStaticBooleanField(jclass clazz, jfieldID fieldID, jboolean value)
-    { functions->SetStaticBooleanField(this, clazz, fieldID, value); }
-    void SetStaticByteField(jclass clazz, jfieldID fieldID, jbyte value)
-    { functions->SetStaticByteField(this, clazz, fieldID, value); }
-    void SetStaticCharField(jclass clazz, jfieldID fieldID, jchar value)
-    { functions->SetStaticCharField(this, clazz, fieldID, value); }
-    void SetStaticShortField(jclass clazz, jfieldID fieldID, jshort value)
-    { functions->SetStaticShortField(this, clazz, fieldID, value); }
-    void SetStaticIntField(jclass clazz, jfieldID fieldID, jint value)
-    { functions->SetStaticIntField(this, clazz, fieldID, value); }
-    void SetStaticLongField(jclass clazz, jfieldID fieldID, jlong value)
-    { functions->SetStaticLongField(this, clazz, fieldID, value); }
-    void SetStaticFloatField(jclass clazz, jfieldID fieldID, jfloat value)
-    { functions->SetStaticFloatField(this, clazz, fieldID, value); }
-    void SetStaticDoubleField(jclass clazz, jfieldID fieldID, jdouble value)
-    { functions->SetStaticDoubleField(this, clazz, fieldID, value); }
-
-    jstring NewString(const jchar* unicodeChars, jsize len)
-    { return functions->NewString(this, unicodeChars, len); }
-
-    jsize GetStringLength(jstring string)
-    { return functions->GetStringLength(this, string); }
-
-    const jchar* GetStringChars(jstring string, jboolean* isCopy)
-    { return functions->GetStringChars(this, string, isCopy); }
-
-    void ReleaseStringChars(jstring string, const jchar* chars)
-    { functions->ReleaseStringChars(this, string, chars); }
-
-    jstring NewStringUTF(const char* bytes)
-    { return functions->NewStringUTF(this, bytes); }
-
-    jsize GetStringUTFLength(jstring string)
-    { return functions->GetStringUTFLength(this, string); }
-
-    const char* GetStringUTFChars(jstring string, jboolean* isCopy)
-    { return functions->GetStringUTFChars(this, string, isCopy); }
-
-    void ReleaseStringUTFChars(jstring string, const char* utf)
-    { functions->ReleaseStringUTFChars(this, string, utf); }
-
-    jsize GetArrayLength(jarray array)
-    { return functions->GetArrayLength(this, array); }
-
-    jobjectArray NewObjectArray(jsize length, jclass elementClass,
-        jobject initialElement)
-    { return functions->NewObjectArray(this, length, elementClass,
-        initialElement); }
-
-    jobject GetObjectArrayElement(jobjectArray array, jsize index)
-    { return functions->GetObjectArrayElement(this, array, index); }
-
-    void SetObjectArrayElement(jobjectArray array, jsize index, jobject value)
-    { functions->SetObjectArrayElement(this, array, index, value); }
-
-    jbooleanArray NewBooleanArray(jsize length)
-    { return functions->NewBooleanArray(this, length); }
-    jbyteArray NewByteArray(jsize length)
-    { return functions->NewByteArray(this, length); }
-    jcharArray NewCharArray(jsize length)
-    { return functions->NewCharArray(this, length); }
-    jshortArray NewShortArray(jsize length)
-    { return functions->NewShortArray(this, length); }
-    jintArray NewIntArray(jsize length)
-    { return functions->NewIntArray(this, length); }
-    jlongArray NewLongArray(jsize length)
-    { return functions->NewLongArray(this, length); }
-    jfloatArray NewFloatArray(jsize length)
-    { return functions->NewFloatArray(this, length); }
-    jdoubleArray NewDoubleArray(jsize length)
-    { return functions->NewDoubleArray(this, length); }
-
-    jboolean* GetBooleanArrayElements(jbooleanArray array, jboolean* isCopy)
-    { return functions->GetBooleanArrayElements(this, array, isCopy); }
-    jbyte* GetByteArrayElements(jbyteArray array, jboolean* isCopy)
-    { return functions->GetByteArrayElements(this, array, isCopy); }
-    jchar* GetCharArrayElements(jcharArray array, jboolean* isCopy)
-    { return functions->GetCharArrayElements(this, array, isCopy); }
-    jshort* GetShortArrayElements(jshortArray array, jboolean* isCopy)
-    { return functions->GetShortArrayElements(this, array, isCopy); }
-    jint* GetIntArrayElements(jintArray array, jboolean* isCopy)
-    { return functions->GetIntArrayElements(this, array, isCopy); }
-    jlong* GetLongArrayElements(jlongArray array, jboolean* isCopy)
-    { return functions->GetLongArrayElements(this, array, isCopy); }
-    jfloat* GetFloatArrayElements(jfloatArray array, jboolean* isCopy)
-    { return functions->GetFloatArrayElements(this, array, isCopy); }
-    jdouble* GetDoubleArrayElements(jdoubleArray array, jboolean* isCopy)
-    { return functions->GetDoubleArrayElements(this, array, isCopy); }
-
-    void ReleaseBooleanArrayElements(jbooleanArray array, jboolean* elems,
-        jint mode)
-    { functions->ReleaseBooleanArrayElements(this, array, elems, mode); }
-    void ReleaseByteArrayElements(jbyteArray array, jbyte* elems,
-        jint mode)
-    { functions->ReleaseByteArrayElements(this, array, elems, mode); }
-    void ReleaseCharArrayElements(jcharArray array, jchar* elems,
-        jint mode)
-    { functions->ReleaseCharArrayElements(this, array, elems, mode); }
-    void ReleaseShortArrayElements(jshortArray array, jshort* elems,
-        jint mode)
-    { functions->ReleaseShortArrayElements(this, array, elems, mode); }
-    void ReleaseIntArrayElements(jintArray array, jint* elems,
-        jint mode)
-    { functions->ReleaseIntArrayElements(this, array, elems, mode); }
-    void ReleaseLongArrayElements(jlongArray array, jlong* elems,
-        jint mode)
-    { functions->ReleaseLongArrayElements(this, array, elems, mode); }
-    void ReleaseFloatArrayElements(jfloatArray array, jfloat* elems,
-        jint mode)
-    { functions->ReleaseFloatArrayElements(this, array, elems, mode); }
-    void ReleaseDoubleArrayElements(jdoubleArray array, jdouble* elems,
-        jint mode)
-    { functions->ReleaseDoubleArrayElements(this, array, elems, mode); }
-
-    void GetBooleanArrayRegion(jbooleanArray array, jsize start, jsize len,
-        jboolean* buf)
-    { functions->GetBooleanArrayRegion(this, array, start, len, buf); }
-    void GetByteArrayRegion(jbyteArray array, jsize start, jsize len,
-        jbyte* buf)
-    { functions->GetByteArrayRegion(this, array, start, len, buf); }
-    void GetCharArrayRegion(jcharArray array, jsize start, jsize len,
-        jchar* buf)
-    { functions->GetCharArrayRegion(this, array, start, len, buf); }
-    void GetShortArrayRegion(jshortArray array, jsize start, jsize len,
-        jshort* buf)
-    { functions->GetShortArrayRegion(this, array, start, len, buf); }
-    void GetIntArrayRegion(jintArray array, jsize start, jsize len,
-        jint* buf)
-    { functions->GetIntArrayRegion(this, array, start, len, buf); }
-    void GetLongArrayRegion(jlongArray array, jsize start, jsize len,
-        jlong* buf)
-    { functions->GetLongArrayRegion(this, array, start, len, buf); }
-    void GetFloatArrayRegion(jfloatArray array, jsize start, jsize len,
-        jfloat* buf)
-    { functions->GetFloatArrayRegion(this, array, start, len, buf); }
-    void GetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len,
-        jdouble* buf)
-    { functions->GetDoubleArrayRegion(this, array, start, len, buf); }
-
-    void SetBooleanArrayRegion(jbooleanArray array, jsize start, jsize len,
-        const jboolean* buf)
-    { functions->SetBooleanArrayRegion(this, array, start, len, buf); }
-    void SetByteArrayRegion(jbyteArray array, jsize start, jsize len,
-        const jbyte* buf)
-    { functions->SetByteArrayRegion(this, array, start, len, buf); }
-    void SetCharArrayRegion(jcharArray array, jsize start, jsize len,
-        const jchar* buf)
-    { functions->SetCharArrayRegion(this, array, start, len, buf); }
-    void SetShortArrayRegion(jshortArray array, jsize start, jsize len,
-        const jshort* buf)
-    { functions->SetShortArrayRegion(this, array, start, len, buf); }
-    void SetIntArrayRegion(jintArray array, jsize start, jsize len,
-        const jint* buf)
-    { functions->SetIntArrayRegion(this, array, start, len, buf); }
-    void SetLongArrayRegion(jlongArray array, jsize start, jsize len,
-        const jlong* buf)
-    { functions->SetLongArrayRegion(this, array, start, len, buf); }
-    void SetFloatArrayRegion(jfloatArray array, jsize start, jsize len,
-        const jfloat* buf)
-    { functions->SetFloatArrayRegion(this, array, start, len, buf); }
-    void SetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len,
-        const jdouble* buf)
-    { functions->SetDoubleArrayRegion(this, array, start, len, buf); }
-
-    jint RegisterNatives(jclass clazz, const JNINativeMethod* methods,
-        jint nMethods)
-    { return functions->RegisterNatives(this, clazz, methods, nMethods); }
-
-    jint UnregisterNatives(jclass clazz)
-    { return functions->UnregisterNatives(this, clazz); }
-
-    jint MonitorEnter(jobject obj)
-    { return functions->MonitorEnter(this, obj); }
-
-    jint MonitorExit(jobject obj)
-    { return functions->MonitorExit(this, obj); }
-
-    jint GetJavaVM(JavaVM** vm)
-    { return functions->GetJavaVM(this, vm); }
-
-    void GetStringRegion(jstring str, jsize start, jsize len, jchar* buf)
-    { functions->GetStringRegion(this, str, start, len, buf); }
-
-    void GetStringUTFRegion(jstring str, jsize start, jsize len, char* buf)
-    { return functions->GetStringUTFRegion(this, str, start, len, buf); }
-
-    void* GetPrimitiveArrayCritical(jarray array, jboolean* isCopy)
-    { return functions->GetPrimitiveArrayCritical(this, array, isCopy); }
-
-    void ReleasePrimitiveArrayCritical(jarray array, void* carray, jint mode)
-    { functions->ReleasePrimitiveArrayCritical(this, array, carray, mode); }
-
-    const jchar* GetStringCritical(jstring string, jboolean* isCopy)
-    { return functions->GetStringCritical(this, string, isCopy); }
-
-    void ReleaseStringCritical(jstring string, const jchar* carray)
-    { functions->ReleaseStringCritical(this, string, carray); }
-
-    jweak NewWeakGlobalRef(jobject obj)
-    { return functions->NewWeakGlobalRef(this, obj); }
-
-    void DeleteWeakGlobalRef(jweak obj)
-    { functions->DeleteWeakGlobalRef(this, obj); }
-
-    jboolean ExceptionCheck()
-    { return functions->ExceptionCheck(this); }
-
-    jobject NewDirectByteBuffer(void* address, jlong capacity)
-    { return functions->NewDirectByteBuffer(this, address, capacity); }
-
-    void* GetDirectBufferAddress(jobject buf)
-    { return functions->GetDirectBufferAddress(this, buf); }
-
-    jlong GetDirectBufferCapacity(jobject buf)
-    { return functions->GetDirectBufferCapacity(this, buf); }
-
-    /* added in JNI 1.6 */
-    jobjectRefType GetObjectRefType(jobject obj)
-    { return functions->GetObjectRefType(this, obj); }
-#endif /*__cplusplus*/
-};
-
-
-/*
- * JNI invocation interface.
- */
-struct JNIInvokeInterface {
-    void*       reserved0;
-    void*       reserved1;
-    void*       reserved2;
-
-    jint        (JNICALL *DestroyJavaVM)(JavaVM*);
-    jint        (JNICALL *AttachCurrentThread)(JavaVM*, JNIEnv**, void*);
-    jint        (JNICALL *DetachCurrentThread)(JavaVM*);
-    jint        (JNICALL *GetEnv)(JavaVM*, void**, jint);
-    jint        (JNICALL *AttachCurrentThreadAsDaemon)(JavaVM*, JNIEnv**, void*);
-};
-
-/*
- * C++ version.
- */
-struct _JavaVM {
-    const struct JNIInvokeInterface* functions;
-
-#if defined(__cplusplus)
-    jint DestroyJavaVM()
-    { return functions->DestroyJavaVM(this); }
-    jint AttachCurrentThread(JNIEnv** p_env, void* thr_args)
-    { return functions->AttachCurrentThread(this, p_env, thr_args); }
-    jint DetachCurrentThread()
-    { return functions->DetachCurrentThread(this); }
-    jint GetEnv(void** env, jint version)
-    { return functions->GetEnv(this, env, version); }
-    jint AttachCurrentThreadAsDaemon(JNIEnv** p_env, void* thr_args)
-    { return functions->AttachCurrentThreadAsDaemon(this, p_env, thr_args); }
-#endif /*__cplusplus*/
-};
-
-struct JavaVMAttachArgs {
-    jint        version;    /* must be >= JNI_VERSION_1_2 */
-    const char* name;       /* NULL or name of thread as modified UTF-8 str */
-    jobject     group;      /* global ref of a ThreadGroup object, or NULL */
-};
-typedef struct JavaVMAttachArgs JavaVMAttachArgs;
-
-/*
- * JNI 1.2+ initialization.  (As of 1.6, the pre-1.2 structures are no
- * longer supported.)
- */
-typedef struct JavaVMOption {
-    const char* optionString;
-    void*       extraInfo;
-} JavaVMOption;
-
-typedef struct JavaVMInitArgs {
-    jint        version;    /* use JNI_VERSION_1_2 or later */
-
-    jint        nOptions;
-    JavaVMOption* options;
-    jboolean    ignoreUnrecognized;
-} JavaVMInitArgs;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*
- * VM initialization functions.
- *
- * Note these are the only symbols exported for JNI by the VM.
- */
-#if 0  /* In practice, these are not exported by the NDK so don't declare them */
-jint JNI_GetDefaultJavaVMInitArgs(void*);
-jint JNI_CreateJavaVM(JavaVM**, JNIEnv**, void*);
-jint JNI_GetCreatedJavaVMs(JavaVM**, jsize, jsize*);
-#endif
-
-/*
- * Prototypes for functions exported by loadable shared libs.  These are
- * called by JNI, not provided by JNI.
- */
-JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved);
-JNIEXPORT void JNI_OnUnload(JavaVM* vm, void* reserved);
-
-#ifdef __cplusplus
-}
-#endif
-
-
-/*
- * Manifest constants.
- */
-#define JNI_FALSE   0
-#define JNI_TRUE    1
-
-#define JNI_VERSION_1_1 0x00010001
-#define JNI_VERSION_1_2 0x00010002
-#define JNI_VERSION_1_4 0x00010004
-#define JNI_VERSION_1_6 0x00010006
-
-#define JNI_OK          (0)         /* no error */
-#define JNI_ERR         (-1)        /* generic error */
-#define JNI_EDETACHED   (-2)        /* thread detached from the VM */
-#define JNI_EVERSION    (-3)        /* JNI version error */
-
-#define JNI_COMMIT      1           /* copy content, do not free buffer */
-#define JNI_ABORT       2           /* free buffer w/o copying back */
-
-#endif  /* JNI_H_ */
diff --git a/chrome/test/chromedriver/third_party/jni/patch.diff b/chrome/test/chromedriver/third_party/jni/patch.diff
deleted file mode 100644
index 8e1d1f8..0000000
--- a/chrome/test/chromedriver/third_party/jni/patch.diff
+++ /dev/null
@@ -1,631 +0,0 @@
-Index: chrome/test/chromedriver/third_party/jni/jni.h
-diff --git a/chrome/test/chromedriver/third_party/jni/jni.h b/chrome/test/chromedriver/third_party/jni/jni.h
-index 495902c..2c44f07 100644
---- a/chrome/test/chromedriver/third_party/jni/jni.h
-+++ b/chrome/test/chromedriver/third_party/jni/jni.h
-@@ -26,6 +26,16 @@
- 
- #include <stdarg.h>
- 
-+#ifdef _WIN32
-+#define JNIIMPORT __declspec(dllimport)
-+#define JNIEXPORT __declspec(dllexport)
-+#define JNICALL __stdcall
-+#else
-+#define JNIIMPORT
-+#define JNIEXPORT __attribute__ ((visibility ("default")))
-+#define JNICALL
-+#endif
-+
- /*
-  * Primitive types that match up with Java equivalents.
-  */
-@@ -166,333 +176,333 @@ struct JNINativeInterface {
-     void*       reserved2;
-     void*       reserved3;
- 
--    jint        (*GetVersion)(JNIEnv *);
-+    jint        (JNICALL *GetVersion)(JNIEnv *);
- 
--    jclass      (*DefineClass)(JNIEnv*, const char*, jobject, const jbyte*,
-+    jclass      (JNICALL *DefineClass)(JNIEnv*, const char*, jobject, const jbyte*,
-                         jsize);
--    jclass      (*FindClass)(JNIEnv*, const char*);
-+    jclass      (JNICALL *FindClass)(JNIEnv*, const char*);
- 
--    jmethodID   (*FromReflectedMethod)(JNIEnv*, jobject);
--    jfieldID    (*FromReflectedField)(JNIEnv*, jobject);
-+    jmethodID   (JNICALL *FromReflectedMethod)(JNIEnv*, jobject);
-+    jfieldID    (JNICALL *FromReflectedField)(JNIEnv*, jobject);
-     /* spec doesn't show jboolean parameter */
--    jobject     (*ToReflectedMethod)(JNIEnv*, jclass, jmethodID, jboolean);
-+    jobject     (JNICALL *ToReflectedMethod)(JNIEnv*, jclass, jmethodID, jboolean);
- 
--    jclass      (*GetSuperclass)(JNIEnv*, jclass);
--    jboolean    (*IsAssignableFrom)(JNIEnv*, jclass, jclass);
-+    jclass      (JNICALL *GetSuperclass)(JNIEnv*, jclass);
-+    jboolean    (JNICALL *IsAssignableFrom)(JNIEnv*, jclass, jclass);
- 
-     /* spec doesn't show jboolean parameter */
--    jobject     (*ToReflectedField)(JNIEnv*, jclass, jfieldID, jboolean);
--
--    jint        (*Throw)(JNIEnv*, jthrowable);
--    jint        (*ThrowNew)(JNIEnv *, jclass, const char *);
--    jthrowable  (*ExceptionOccurred)(JNIEnv*);
--    void        (*ExceptionDescribe)(JNIEnv*);
--    void        (*ExceptionClear)(JNIEnv*);
--    void        (*FatalError)(JNIEnv*, const char*);
--
--    jint        (*PushLocalFrame)(JNIEnv*, jint);
--    jobject     (*PopLocalFrame)(JNIEnv*, jobject);
--
--    jobject     (*NewGlobalRef)(JNIEnv*, jobject);
--    void        (*DeleteGlobalRef)(JNIEnv*, jobject);
--    void        (*DeleteLocalRef)(JNIEnv*, jobject);
--    jboolean    (*IsSameObject)(JNIEnv*, jobject, jobject);
--
--    jobject     (*NewLocalRef)(JNIEnv*, jobject);
--    jint        (*EnsureLocalCapacity)(JNIEnv*, jint);
--
--    jobject     (*AllocObject)(JNIEnv*, jclass);
--    jobject     (*NewObject)(JNIEnv*, jclass, jmethodID, ...);
--    jobject     (*NewObjectV)(JNIEnv*, jclass, jmethodID, va_list);
--    jobject     (*NewObjectA)(JNIEnv*, jclass, jmethodID, jvalue*);
--
--    jclass      (*GetObjectClass)(JNIEnv*, jobject);
--    jboolean    (*IsInstanceOf)(JNIEnv*, jobject, jclass);
--    jmethodID   (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
--
--    jobject     (*CallObjectMethod)(JNIEnv*, jobject, jmethodID, ...);
--    jobject     (*CallObjectMethodV)(JNIEnv*, jobject, jmethodID, va_list);
--    jobject     (*CallObjectMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
--    jboolean    (*CallBooleanMethod)(JNIEnv*, jobject, jmethodID, ...);
--    jboolean    (*CallBooleanMethodV)(JNIEnv*, jobject, jmethodID, va_list);
--    jboolean    (*CallBooleanMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
--    jbyte       (*CallByteMethod)(JNIEnv*, jobject, jmethodID, ...);
--    jbyte       (*CallByteMethodV)(JNIEnv*, jobject, jmethodID, va_list);
--    jbyte       (*CallByteMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
--    jchar       (*CallCharMethod)(JNIEnv*, jobject, jmethodID, ...);
--    jchar       (*CallCharMethodV)(JNIEnv*, jobject, jmethodID, va_list);
--    jchar       (*CallCharMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
--    jshort      (*CallShortMethod)(JNIEnv*, jobject, jmethodID, ...);
--    jshort      (*CallShortMethodV)(JNIEnv*, jobject, jmethodID, va_list);
--    jshort      (*CallShortMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
--    jint        (*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...);
--    jint        (*CallIntMethodV)(JNIEnv*, jobject, jmethodID, va_list);
--    jint        (*CallIntMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
--    jlong       (*CallLongMethod)(JNIEnv*, jobject, jmethodID, ...);
--    jlong       (*CallLongMethodV)(JNIEnv*, jobject, jmethodID, va_list);
--    jlong       (*CallLongMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
--    jfloat      (*CallFloatMethod)(JNIEnv*, jobject, jmethodID, ...);
--    jfloat      (*CallFloatMethodV)(JNIEnv*, jobject, jmethodID, va_list);
--    jfloat      (*CallFloatMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
--    jdouble     (*CallDoubleMethod)(JNIEnv*, jobject, jmethodID, ...);
--    jdouble     (*CallDoubleMethodV)(JNIEnv*, jobject, jmethodID, va_list);
--    jdouble     (*CallDoubleMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
--    void        (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
--    void        (*CallVoidMethodV)(JNIEnv*, jobject, jmethodID, va_list);
--    void        (*CallVoidMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
--
--    jobject     (*CallNonvirtualObjectMethod)(JNIEnv*, jobject, jclass,
-+    jobject     (JNICALL *ToReflectedField)(JNIEnv*, jclass, jfieldID, jboolean);
-+
-+    jint        (JNICALL *Throw)(JNIEnv*, jthrowable);
-+    jint        (JNICALL *ThrowNew)(JNIEnv *, jclass, const char *);
-+    jthrowable  (JNICALL *ExceptionOccurred)(JNIEnv*);
-+    void        (JNICALL *ExceptionDescribe)(JNIEnv*);
-+    void        (JNICALL *ExceptionClear)(JNIEnv*);
-+    void        (JNICALL *FatalError)(JNIEnv*, const char*);
-+
-+    jint        (JNICALL *PushLocalFrame)(JNIEnv*, jint);
-+    jobject     (JNICALL *PopLocalFrame)(JNIEnv*, jobject);
-+
-+    jobject     (JNICALL *NewGlobalRef)(JNIEnv*, jobject);
-+    void        (JNICALL *DeleteGlobalRef)(JNIEnv*, jobject);
-+    void        (JNICALL *DeleteLocalRef)(JNIEnv*, jobject);
-+    jboolean    (JNICALL *IsSameObject)(JNIEnv*, jobject, jobject);
-+
-+    jobject     (JNICALL *NewLocalRef)(JNIEnv*, jobject);
-+    jint        (JNICALL *EnsureLocalCapacity)(JNIEnv*, jint);
-+
-+    jobject     (JNICALL *AllocObject)(JNIEnv*, jclass);
-+    jobject     (JNICALL *NewObject)(JNIEnv*, jclass, jmethodID, ...);
-+    jobject     (JNICALL *NewObjectV)(JNIEnv*, jclass, jmethodID, va_list);
-+    jobject     (JNICALL *NewObjectA)(JNIEnv*, jclass, jmethodID, jvalue*);
-+
-+    jclass      (JNICALL *GetObjectClass)(JNIEnv*, jobject);
-+    jboolean    (JNICALL *IsInstanceOf)(JNIEnv*, jobject, jclass);
-+    jmethodID   (JNICALL *GetMethodID)(JNIEnv*, jclass, const char*, const char*);
-+
-+    jobject     (JNICALL *CallObjectMethod)(JNIEnv*, jobject, jmethodID, ...);
-+    jobject     (JNICALL *CallObjectMethodV)(JNIEnv*, jobject, jmethodID, va_list);
-+    jobject     (JNICALL *CallObjectMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
-+    jboolean    (JNICALL *CallBooleanMethod)(JNIEnv*, jobject, jmethodID, ...);
-+    jboolean    (JNICALL *CallBooleanMethodV)(JNIEnv*, jobject, jmethodID, va_list);
-+    jboolean    (JNICALL *CallBooleanMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
-+    jbyte       (JNICALL *CallByteMethod)(JNIEnv*, jobject, jmethodID, ...);
-+    jbyte       (JNICALL *CallByteMethodV)(JNIEnv*, jobject, jmethodID, va_list);
-+    jbyte       (JNICALL *CallByteMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
-+    jchar       (JNICALL *CallCharMethod)(JNIEnv*, jobject, jmethodID, ...);
-+    jchar       (JNICALL *CallCharMethodV)(JNIEnv*, jobject, jmethodID, va_list);
-+    jchar       (JNICALL *CallCharMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
-+    jshort      (JNICALL *CallShortMethod)(JNIEnv*, jobject, jmethodID, ...);
-+    jshort      (JNICALL *CallShortMethodV)(JNIEnv*, jobject, jmethodID, va_list);
-+    jshort      (JNICALL *CallShortMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
-+    jint        (JNICALL *CallIntMethod)(JNIEnv*, jobject, jmethodID, ...);
-+    jint        (JNICALL *CallIntMethodV)(JNIEnv*, jobject, jmethodID, va_list);
-+    jint        (JNICALL *CallIntMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
-+    jlong       (JNICALL *CallLongMethod)(JNIEnv*, jobject, jmethodID, ...);
-+    jlong       (JNICALL *CallLongMethodV)(JNIEnv*, jobject, jmethodID, va_list);
-+    jlong       (JNICALL *CallLongMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
-+    jfloat      (JNICALL *CallFloatMethod)(JNIEnv*, jobject, jmethodID, ...);
-+    jfloat      (JNICALL *CallFloatMethodV)(JNIEnv*, jobject, jmethodID, va_list);
-+    jfloat      (JNICALL *CallFloatMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
-+    jdouble     (JNICALL *CallDoubleMethod)(JNIEnv*, jobject, jmethodID, ...);
-+    jdouble     (JNICALL *CallDoubleMethodV)(JNIEnv*, jobject, jmethodID, va_list);
-+    jdouble     (JNICALL *CallDoubleMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
-+    void        (JNICALL *CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
-+    void        (JNICALL *CallVoidMethodV)(JNIEnv*, jobject, jmethodID, va_list);
-+    void        (JNICALL *CallVoidMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
-+
-+    jobject     (JNICALL *CallNonvirtualObjectMethod)(JNIEnv*, jobject, jclass,
-                         jmethodID, ...);
--    jobject     (*CallNonvirtualObjectMethodV)(JNIEnv*, jobject, jclass,
-+    jobject     (JNICALL *CallNonvirtualObjectMethodV)(JNIEnv*, jobject, jclass,
-                         jmethodID, va_list);
--    jobject     (*CallNonvirtualObjectMethodA)(JNIEnv*, jobject, jclass,
-+    jobject     (JNICALL *CallNonvirtualObjectMethodA)(JNIEnv*, jobject, jclass,
-                         jmethodID, jvalue*);
--    jboolean    (*CallNonvirtualBooleanMethod)(JNIEnv*, jobject, jclass,
-+    jboolean    (JNICALL *CallNonvirtualBooleanMethod)(JNIEnv*, jobject, jclass,
-                         jmethodID, ...);
--    jboolean    (*CallNonvirtualBooleanMethodV)(JNIEnv*, jobject, jclass,
-+    jboolean    (JNICALL *CallNonvirtualBooleanMethodV)(JNIEnv*, jobject, jclass,
-                          jmethodID, va_list);
--    jboolean    (*CallNonvirtualBooleanMethodA)(JNIEnv*, jobject, jclass,
-+    jboolean    (JNICALL *CallNonvirtualBooleanMethodA)(JNIEnv*, jobject, jclass,
-                          jmethodID, jvalue*);
--    jbyte       (*CallNonvirtualByteMethod)(JNIEnv*, jobject, jclass,
-+    jbyte       (JNICALL *CallNonvirtualByteMethod)(JNIEnv*, jobject, jclass,
-                         jmethodID, ...);
--    jbyte       (*CallNonvirtualByteMethodV)(JNIEnv*, jobject, jclass,
-+    jbyte       (JNICALL *CallNonvirtualByteMethodV)(JNIEnv*, jobject, jclass,
-                         jmethodID, va_list);
--    jbyte       (*CallNonvirtualByteMethodA)(JNIEnv*, jobject, jclass,
-+    jbyte       (JNICALL *CallNonvirtualByteMethodA)(JNIEnv*, jobject, jclass,
-                         jmethodID, jvalue*);
--    jchar       (*CallNonvirtualCharMethod)(JNIEnv*, jobject, jclass,
-+    jchar       (JNICALL *CallNonvirtualCharMethod)(JNIEnv*, jobject, jclass,
-                         jmethodID, ...);
--    jchar       (*CallNonvirtualCharMethodV)(JNIEnv*, jobject, jclass,
-+    jchar       (JNICALL *CallNonvirtualCharMethodV)(JNIEnv*, jobject, jclass,
-                         jmethodID, va_list);
--    jchar       (*CallNonvirtualCharMethodA)(JNIEnv*, jobject, jclass,
-+    jchar       (JNICALL *CallNonvirtualCharMethodA)(JNIEnv*, jobject, jclass,
-                         jmethodID, jvalue*);
--    jshort      (*CallNonvirtualShortMethod)(JNIEnv*, jobject, jclass,
-+    jshort      (JNICALL *CallNonvirtualShortMethod)(JNIEnv*, jobject, jclass,
-                         jmethodID, ...);
--    jshort      (*CallNonvirtualShortMethodV)(JNIEnv*, jobject, jclass,
-+    jshort      (JNICALL *CallNonvirtualShortMethodV)(JNIEnv*, jobject, jclass,
-                         jmethodID, va_list);
--    jshort      (*CallNonvirtualShortMethodA)(JNIEnv*, jobject, jclass,
-+    jshort      (JNICALL *CallNonvirtualShortMethodA)(JNIEnv*, jobject, jclass,
-                         jmethodID, jvalue*);
--    jint        (*CallNonvirtualIntMethod)(JNIEnv*, jobject, jclass,
-+    jint        (JNICALL *CallNonvirtualIntMethod)(JNIEnv*, jobject, jclass,
-                         jmethodID, ...);
--    jint        (*CallNonvirtualIntMethodV)(JNIEnv*, jobject, jclass,
-+    jint        (JNICALL *CallNonvirtualIntMethodV)(JNIEnv*, jobject, jclass,
-                         jmethodID, va_list);
--    jint        (*CallNonvirtualIntMethodA)(JNIEnv*, jobject, jclass,
-+    jint        (JNICALL *CallNonvirtualIntMethodA)(JNIEnv*, jobject, jclass,
-                         jmethodID, jvalue*);
--    jlong       (*CallNonvirtualLongMethod)(JNIEnv*, jobject, jclass,
-+    jlong       (JNICALL *CallNonvirtualLongMethod)(JNIEnv*, jobject, jclass,
-                         jmethodID, ...);
--    jlong       (*CallNonvirtualLongMethodV)(JNIEnv*, jobject, jclass,
-+    jlong       (JNICALL *CallNonvirtualLongMethodV)(JNIEnv*, jobject, jclass,
-                         jmethodID, va_list);
--    jlong       (*CallNonvirtualLongMethodA)(JNIEnv*, jobject, jclass,
-+    jlong       (JNICALL *CallNonvirtualLongMethodA)(JNIEnv*, jobject, jclass,
-                         jmethodID, jvalue*);
--    jfloat      (*CallNonvirtualFloatMethod)(JNIEnv*, jobject, jclass,
-+    jfloat      (JNICALL *CallNonvirtualFloatMethod)(JNIEnv*, jobject, jclass,
-                         jmethodID, ...);
--    jfloat      (*CallNonvirtualFloatMethodV)(JNIEnv*, jobject, jclass,
-+    jfloat      (JNICALL *CallNonvirtualFloatMethodV)(JNIEnv*, jobject, jclass,
-                         jmethodID, va_list);
--    jfloat      (*CallNonvirtualFloatMethodA)(JNIEnv*, jobject, jclass,
-+    jfloat      (JNICALL *CallNonvirtualFloatMethodA)(JNIEnv*, jobject, jclass,
-                         jmethodID, jvalue*);
--    jdouble     (*CallNonvirtualDoubleMethod)(JNIEnv*, jobject, jclass,
-+    jdouble     (JNICALL *CallNonvirtualDoubleMethod)(JNIEnv*, jobject, jclass,
-                         jmethodID, ...);
--    jdouble     (*CallNonvirtualDoubleMethodV)(JNIEnv*, jobject, jclass,
-+    jdouble     (JNICALL *CallNonvirtualDoubleMethodV)(JNIEnv*, jobject, jclass,
-                         jmethodID, va_list);
--    jdouble     (*CallNonvirtualDoubleMethodA)(JNIEnv*, jobject, jclass,
-+    jdouble     (JNICALL *CallNonvirtualDoubleMethodA)(JNIEnv*, jobject, jclass,
-                         jmethodID, jvalue*);
--    void        (*CallNonvirtualVoidMethod)(JNIEnv*, jobject, jclass,
-+    void        (JNICALL *CallNonvirtualVoidMethod)(JNIEnv*, jobject, jclass,
-                         jmethodID, ...);
--    void        (*CallNonvirtualVoidMethodV)(JNIEnv*, jobject, jclass,
-+    void        (JNICALL *CallNonvirtualVoidMethodV)(JNIEnv*, jobject, jclass,
-                         jmethodID, va_list);
--    void        (*CallNonvirtualVoidMethodA)(JNIEnv*, jobject, jclass,
-+    void        (JNICALL *CallNonvirtualVoidMethodA)(JNIEnv*, jobject, jclass,
-                         jmethodID, jvalue*);
- 
--    jfieldID    (*GetFieldID)(JNIEnv*, jclass, const char*, const char*);
--
--    jobject     (*GetObjectField)(JNIEnv*, jobject, jfieldID);
--    jboolean    (*GetBooleanField)(JNIEnv*, jobject, jfieldID);
--    jbyte       (*GetByteField)(JNIEnv*, jobject, jfieldID);
--    jchar       (*GetCharField)(JNIEnv*, jobject, jfieldID);
--    jshort      (*GetShortField)(JNIEnv*, jobject, jfieldID);
--    jint        (*GetIntField)(JNIEnv*, jobject, jfieldID);
--    jlong       (*GetLongField)(JNIEnv*, jobject, jfieldID);
--    jfloat      (*GetFloatField)(JNIEnv*, jobject, jfieldID);
--    jdouble     (*GetDoubleField)(JNIEnv*, jobject, jfieldID);
--
--    void        (*SetObjectField)(JNIEnv*, jobject, jfieldID, jobject);
--    void        (*SetBooleanField)(JNIEnv*, jobject, jfieldID, jboolean);
--    void        (*SetByteField)(JNIEnv*, jobject, jfieldID, jbyte);
--    void        (*SetCharField)(JNIEnv*, jobject, jfieldID, jchar);
--    void        (*SetShortField)(JNIEnv*, jobject, jfieldID, jshort);
--    void        (*SetIntField)(JNIEnv*, jobject, jfieldID, jint);
--    void        (*SetLongField)(JNIEnv*, jobject, jfieldID, jlong);
--    void        (*SetFloatField)(JNIEnv*, jobject, jfieldID, jfloat);
--    void        (*SetDoubleField)(JNIEnv*, jobject, jfieldID, jdouble);
--
--    jmethodID   (*GetStaticMethodID)(JNIEnv*, jclass, const char*, const char*);
--
--    jobject     (*CallStaticObjectMethod)(JNIEnv*, jclass, jmethodID, ...);
--    jobject     (*CallStaticObjectMethodV)(JNIEnv*, jclass, jmethodID, va_list);
--    jobject     (*CallStaticObjectMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);
--    jboolean    (*CallStaticBooleanMethod)(JNIEnv*, jclass, jmethodID, ...);
--    jboolean    (*CallStaticBooleanMethodV)(JNIEnv*, jclass, jmethodID,
-+    jfieldID    (JNICALL *GetFieldID)(JNIEnv*, jclass, const char*, const char*);
-+
-+    jobject     (JNICALL *GetObjectField)(JNIEnv*, jobject, jfieldID);
-+    jboolean    (JNICALL *GetBooleanField)(JNIEnv*, jobject, jfieldID);
-+    jbyte       (JNICALL *GetByteField)(JNIEnv*, jobject, jfieldID);
-+    jchar       (JNICALL *GetCharField)(JNIEnv*, jobject, jfieldID);
-+    jshort      (JNICALL *GetShortField)(JNIEnv*, jobject, jfieldID);
-+    jint        (JNICALL *GetIntField)(JNIEnv*, jobject, jfieldID);
-+    jlong       (JNICALL *GetLongField)(JNIEnv*, jobject, jfieldID);
-+    jfloat      (JNICALL *GetFloatField)(JNIEnv*, jobject, jfieldID);
-+    jdouble     (JNICALL *GetDoubleField)(JNIEnv*, jobject, jfieldID);
-+
-+    void        (JNICALL *SetObjectField)(JNIEnv*, jobject, jfieldID, jobject);
-+    void        (JNICALL *SetBooleanField)(JNIEnv*, jobject, jfieldID, jboolean);
-+    void        (JNICALL *SetByteField)(JNIEnv*, jobject, jfieldID, jbyte);
-+    void        (JNICALL *SetCharField)(JNIEnv*, jobject, jfieldID, jchar);
-+    void        (JNICALL *SetShortField)(JNIEnv*, jobject, jfieldID, jshort);
-+    void        (JNICALL *SetIntField)(JNIEnv*, jobject, jfieldID, jint);
-+    void        (JNICALL *SetLongField)(JNIEnv*, jobject, jfieldID, jlong);
-+    void        (JNICALL *SetFloatField)(JNIEnv*, jobject, jfieldID, jfloat);
-+    void        (JNICALL *SetDoubleField)(JNIEnv*, jobject, jfieldID, jdouble);
-+
-+    jmethodID   (JNICALL *GetStaticMethodID)(JNIEnv*, jclass, const char*, const char*);
-+
-+    jobject     (JNICALL *CallStaticObjectMethod)(JNIEnv*, jclass, jmethodID, ...);
-+    jobject     (JNICALL *CallStaticObjectMethodV)(JNIEnv*, jclass, jmethodID, va_list);
-+    jobject     (JNICALL *CallStaticObjectMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);
-+    jboolean    (JNICALL *CallStaticBooleanMethod)(JNIEnv*, jclass, jmethodID, ...);
-+    jboolean    (JNICALL *CallStaticBooleanMethodV)(JNIEnv*, jclass, jmethodID,
-                         va_list);
--    jboolean    (*CallStaticBooleanMethodA)(JNIEnv*, jclass, jmethodID,
-+    jboolean    (JNICALL *CallStaticBooleanMethodA)(JNIEnv*, jclass, jmethodID,
-                         jvalue*);
--    jbyte       (*CallStaticByteMethod)(JNIEnv*, jclass, jmethodID, ...);
--    jbyte       (*CallStaticByteMethodV)(JNIEnv*, jclass, jmethodID, va_list);
--    jbyte       (*CallStaticByteMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);
--    jchar       (*CallStaticCharMethod)(JNIEnv*, jclass, jmethodID, ...);
--    jchar       (*CallStaticCharMethodV)(JNIEnv*, jclass, jmethodID, va_list);
--    jchar       (*CallStaticCharMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);
--    jshort      (*CallStaticShortMethod)(JNIEnv*, jclass, jmethodID, ...);
--    jshort      (*CallStaticShortMethodV)(JNIEnv*, jclass, jmethodID, va_list);
--    jshort      (*CallStaticShortMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);
--    jint        (*CallStaticIntMethod)(JNIEnv*, jclass, jmethodID, ...);
--    jint        (*CallStaticIntMethodV)(JNIEnv*, jclass, jmethodID, va_list);
--    jint        (*CallStaticIntMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);
--    jlong       (*CallStaticLongMethod)(JNIEnv*, jclass, jmethodID, ...);
--    jlong       (*CallStaticLongMethodV)(JNIEnv*, jclass, jmethodID, va_list);
--    jlong       (*CallStaticLongMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);
--    jfloat      (*CallStaticFloatMethod)(JNIEnv*, jclass, jmethodID, ...);
--    jfloat      (*CallStaticFloatMethodV)(JNIEnv*, jclass, jmethodID, va_list);
--    jfloat      (*CallStaticFloatMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);
--    jdouble     (*CallStaticDoubleMethod)(JNIEnv*, jclass, jmethodID, ...);
--    jdouble     (*CallStaticDoubleMethodV)(JNIEnv*, jclass, jmethodID, va_list);
--    jdouble     (*CallStaticDoubleMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);
--    void        (*CallStaticVoidMethod)(JNIEnv*, jclass, jmethodID, ...);
--    void        (*CallStaticVoidMethodV)(JNIEnv*, jclass, jmethodID, va_list);
--    void        (*CallStaticVoidMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);
--
--    jfieldID    (*GetStaticFieldID)(JNIEnv*, jclass, const char*,
-+    jbyte       (JNICALL *CallStaticByteMethod)(JNIEnv*, jclass, jmethodID, ...);
-+    jbyte       (JNICALL *CallStaticByteMethodV)(JNIEnv*, jclass, jmethodID, va_list);
-+    jbyte       (JNICALL *CallStaticByteMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);
-+    jchar       (JNICALL *CallStaticCharMethod)(JNIEnv*, jclass, jmethodID, ...);
-+    jchar       (JNICALL *CallStaticCharMethodV)(JNIEnv*, jclass, jmethodID, va_list);
-+    jchar       (JNICALL *CallStaticCharMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);
-+    jshort      (JNICALL *CallStaticShortMethod)(JNIEnv*, jclass, jmethodID, ...);
-+    jshort      (JNICALL *CallStaticShortMethodV)(JNIEnv*, jclass, jmethodID, va_list);
-+    jshort      (JNICALL *CallStaticShortMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);
-+    jint        (JNICALL *CallStaticIntMethod)(JNIEnv*, jclass, jmethodID, ...);
-+    jint        (JNICALL *CallStaticIntMethodV)(JNIEnv*, jclass, jmethodID, va_list);
-+    jint        (JNICALL *CallStaticIntMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);
-+    jlong       (JNICALL *CallStaticLongMethod)(JNIEnv*, jclass, jmethodID, ...);
-+    jlong       (JNICALL *CallStaticLongMethodV)(JNIEnv*, jclass, jmethodID, va_list);
-+    jlong       (JNICALL *CallStaticLongMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);
-+    jfloat      (JNICALL *CallStaticFloatMethod)(JNIEnv*, jclass, jmethodID, ...);
-+    jfloat      (JNICALL *CallStaticFloatMethodV)(JNIEnv*, jclass, jmethodID, va_list);
-+    jfloat      (JNICALL *CallStaticFloatMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);
-+    jdouble     (JNICALL *CallStaticDoubleMethod)(JNIEnv*, jclass, jmethodID, ...);
-+    jdouble     (JNICALL *CallStaticDoubleMethodV)(JNIEnv*, jclass, jmethodID, va_list);
-+    jdouble     (JNICALL *CallStaticDoubleMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);
-+    void        (JNICALL *CallStaticVoidMethod)(JNIEnv*, jclass, jmethodID, ...);
-+    void        (JNICALL *CallStaticVoidMethodV)(JNIEnv*, jclass, jmethodID, va_list);
-+    void        (JNICALL *CallStaticVoidMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);
-+
-+    jfieldID    (JNICALL *GetStaticFieldID)(JNIEnv*, jclass, const char*,
-                         const char*);
- 
--    jobject     (*GetStaticObjectField)(JNIEnv*, jclass, jfieldID);
--    jboolean    (*GetStaticBooleanField)(JNIEnv*, jclass, jfieldID);
--    jbyte       (*GetStaticByteField)(JNIEnv*, jclass, jfieldID);
--    jchar       (*GetStaticCharField)(JNIEnv*, jclass, jfieldID);
--    jshort      (*GetStaticShortField)(JNIEnv*, jclass, jfieldID);
--    jint        (*GetStaticIntField)(JNIEnv*, jclass, jfieldID);
--    jlong       (*GetStaticLongField)(JNIEnv*, jclass, jfieldID);
--    jfloat      (*GetStaticFloatField)(JNIEnv*, jclass, jfieldID);
--    jdouble     (*GetStaticDoubleField)(JNIEnv*, jclass, jfieldID);
--
--    void        (*SetStaticObjectField)(JNIEnv*, jclass, jfieldID, jobject);
--    void        (*SetStaticBooleanField)(JNIEnv*, jclass, jfieldID, jboolean);
--    void        (*SetStaticByteField)(JNIEnv*, jclass, jfieldID, jbyte);
--    void        (*SetStaticCharField)(JNIEnv*, jclass, jfieldID, jchar);
--    void        (*SetStaticShortField)(JNIEnv*, jclass, jfieldID, jshort);
--    void        (*SetStaticIntField)(JNIEnv*, jclass, jfieldID, jint);
--    void        (*SetStaticLongField)(JNIEnv*, jclass, jfieldID, jlong);
--    void        (*SetStaticFloatField)(JNIEnv*, jclass, jfieldID, jfloat);
--    void        (*SetStaticDoubleField)(JNIEnv*, jclass, jfieldID, jdouble);
--
--    jstring     (*NewString)(JNIEnv*, const jchar*, jsize);
--    jsize       (*GetStringLength)(JNIEnv*, jstring);
--    const jchar* (*GetStringChars)(JNIEnv*, jstring, jboolean*);
--    void        (*ReleaseStringChars)(JNIEnv*, jstring, const jchar*);
--    jstring     (*NewStringUTF)(JNIEnv*, const char*);
--    jsize       (*GetStringUTFLength)(JNIEnv*, jstring);
-+    jobject     (JNICALL *GetStaticObjectField)(JNIEnv*, jclass, jfieldID);
-+    jboolean    (JNICALL *GetStaticBooleanField)(JNIEnv*, jclass, jfieldID);
-+    jbyte       (JNICALL *GetStaticByteField)(JNIEnv*, jclass, jfieldID);
-+    jchar       (JNICALL *GetStaticCharField)(JNIEnv*, jclass, jfieldID);
-+    jshort      (JNICALL *GetStaticShortField)(JNIEnv*, jclass, jfieldID);
-+    jint        (JNICALL *GetStaticIntField)(JNIEnv*, jclass, jfieldID);
-+    jlong       (JNICALL *GetStaticLongField)(JNIEnv*, jclass, jfieldID);
-+    jfloat      (JNICALL *GetStaticFloatField)(JNIEnv*, jclass, jfieldID);
-+    jdouble     (JNICALL *GetStaticDoubleField)(JNIEnv*, jclass, jfieldID);
-+
-+    void        (JNICALL *SetStaticObjectField)(JNIEnv*, jclass, jfieldID, jobject);
-+    void        (JNICALL *SetStaticBooleanField)(JNIEnv*, jclass, jfieldID, jboolean);
-+    void        (JNICALL *SetStaticByteField)(JNIEnv*, jclass, jfieldID, jbyte);
-+    void        (JNICALL *SetStaticCharField)(JNIEnv*, jclass, jfieldID, jchar);
-+    void        (JNICALL *SetStaticShortField)(JNIEnv*, jclass, jfieldID, jshort);
-+    void        (JNICALL *SetStaticIntField)(JNIEnv*, jclass, jfieldID, jint);
-+    void        (JNICALL *SetStaticLongField)(JNIEnv*, jclass, jfieldID, jlong);
-+    void        (JNICALL *SetStaticFloatField)(JNIEnv*, jclass, jfieldID, jfloat);
-+    void        (JNICALL *SetStaticDoubleField)(JNIEnv*, jclass, jfieldID, jdouble);
-+
-+    jstring     (JNICALL *NewString)(JNIEnv*, const jchar*, jsize);
-+    jsize       (JNICALL *GetStringLength)(JNIEnv*, jstring);
-+    const jchar* (JNICALL *GetStringChars)(JNIEnv*, jstring, jboolean*);
-+    void        (JNICALL *ReleaseStringChars)(JNIEnv*, jstring, const jchar*);
-+    jstring     (JNICALL *NewStringUTF)(JNIEnv*, const char*);
-+    jsize       (JNICALL *GetStringUTFLength)(JNIEnv*, jstring);
-     /* JNI spec says this returns const jbyte*, but that's inconsistent */
--    const char* (*GetStringUTFChars)(JNIEnv*, jstring, jboolean*);
--    void        (*ReleaseStringUTFChars)(JNIEnv*, jstring, const char*);
--    jsize       (*GetArrayLength)(JNIEnv*, jarray);
--    jobjectArray (*NewObjectArray)(JNIEnv*, jsize, jclass, jobject);
--    jobject     (*GetObjectArrayElement)(JNIEnv*, jobjectArray, jsize);
--    void        (*SetObjectArrayElement)(JNIEnv*, jobjectArray, jsize, jobject);
--
--    jbooleanArray (*NewBooleanArray)(JNIEnv*, jsize);
--    jbyteArray    (*NewByteArray)(JNIEnv*, jsize);
--    jcharArray    (*NewCharArray)(JNIEnv*, jsize);
--    jshortArray   (*NewShortArray)(JNIEnv*, jsize);
--    jintArray     (*NewIntArray)(JNIEnv*, jsize);
--    jlongArray    (*NewLongArray)(JNIEnv*, jsize);
--    jfloatArray   (*NewFloatArray)(JNIEnv*, jsize);
--    jdoubleArray  (*NewDoubleArray)(JNIEnv*, jsize);
--
--    jboolean*   (*GetBooleanArrayElements)(JNIEnv*, jbooleanArray, jboolean*);
--    jbyte*      (*GetByteArrayElements)(JNIEnv*, jbyteArray, jboolean*);
--    jchar*      (*GetCharArrayElements)(JNIEnv*, jcharArray, jboolean*);
--    jshort*     (*GetShortArrayElements)(JNIEnv*, jshortArray, jboolean*);
--    jint*       (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*);
--    jlong*      (*GetLongArrayElements)(JNIEnv*, jlongArray, jboolean*);
--    jfloat*     (*GetFloatArrayElements)(JNIEnv*, jfloatArray, jboolean*);
--    jdouble*    (*GetDoubleArrayElements)(JNIEnv*, jdoubleArray, jboolean*);
--
--    void        (*ReleaseBooleanArrayElements)(JNIEnv*, jbooleanArray,
-+    const char* (JNICALL *GetStringUTFChars)(JNIEnv*, jstring, jboolean*);
-+    void        (JNICALL *ReleaseStringUTFChars)(JNIEnv*, jstring, const char*);
-+    jsize       (JNICALL *GetArrayLength)(JNIEnv*, jarray);
-+    jobjectArray (JNICALL *NewObjectArray)(JNIEnv*, jsize, jclass, jobject);
-+    jobject     (JNICALL *GetObjectArrayElement)(JNIEnv*, jobjectArray, jsize);
-+    void        (JNICALL *SetObjectArrayElement)(JNIEnv*, jobjectArray, jsize, jobject);
-+
-+    jbooleanArray (JNICALL *NewBooleanArray)(JNIEnv*, jsize);
-+    jbyteArray    (JNICALL *NewByteArray)(JNIEnv*, jsize);
-+    jcharArray    (JNICALL *NewCharArray)(JNIEnv*, jsize);
-+    jshortArray   (JNICALL *NewShortArray)(JNIEnv*, jsize);
-+    jintArray     (JNICALL *NewIntArray)(JNIEnv*, jsize);
-+    jlongArray    (JNICALL *NewLongArray)(JNIEnv*, jsize);
-+    jfloatArray   (JNICALL *NewFloatArray)(JNIEnv*, jsize);
-+    jdoubleArray  (JNICALL *NewDoubleArray)(JNIEnv*, jsize);
-+
-+    jboolean*   (JNICALL *GetBooleanArrayElements)(JNIEnv*, jbooleanArray, jboolean*);
-+    jbyte*      (JNICALL *GetByteArrayElements)(JNIEnv*, jbyteArray, jboolean*);
-+    jchar*      (JNICALL *GetCharArrayElements)(JNIEnv*, jcharArray, jboolean*);
-+    jshort*     (JNICALL *GetShortArrayElements)(JNIEnv*, jshortArray, jboolean*);
-+    jint*       (JNICALL *GetIntArrayElements)(JNIEnv*, jintArray, jboolean*);
-+    jlong*      (JNICALL *GetLongArrayElements)(JNIEnv*, jlongArray, jboolean*);
-+    jfloat*     (JNICALL *GetFloatArrayElements)(JNIEnv*, jfloatArray, jboolean*);
-+    jdouble*    (JNICALL *GetDoubleArrayElements)(JNIEnv*, jdoubleArray, jboolean*);
-+
-+    void        (JNICALL *ReleaseBooleanArrayElements)(JNIEnv*, jbooleanArray,
-                         jboolean*, jint);
--    void        (*ReleaseByteArrayElements)(JNIEnv*, jbyteArray,
-+    void        (JNICALL *ReleaseByteArrayElements)(JNIEnv*, jbyteArray,
-                         jbyte*, jint);
--    void        (*ReleaseCharArrayElements)(JNIEnv*, jcharArray,
-+    void        (JNICALL *ReleaseCharArrayElements)(JNIEnv*, jcharArray,
-                         jchar*, jint);
--    void        (*ReleaseShortArrayElements)(JNIEnv*, jshortArray,
-+    void        (JNICALL *ReleaseShortArrayElements)(JNIEnv*, jshortArray,
-                         jshort*, jint);
--    void        (*ReleaseIntArrayElements)(JNIEnv*, jintArray,
-+    void        (JNICALL *ReleaseIntArrayElements)(JNIEnv*, jintArray,
-                         jint*, jint);
--    void        (*ReleaseLongArrayElements)(JNIEnv*, jlongArray,
-+    void        (JNICALL *ReleaseLongArrayElements)(JNIEnv*, jlongArray,
-                         jlong*, jint);
--    void        (*ReleaseFloatArrayElements)(JNIEnv*, jfloatArray,
-+    void        (JNICALL *ReleaseFloatArrayElements)(JNIEnv*, jfloatArray,
-                         jfloat*, jint);
--    void        (*ReleaseDoubleArrayElements)(JNIEnv*, jdoubleArray,
-+    void        (JNICALL *ReleaseDoubleArrayElements)(JNIEnv*, jdoubleArray,
-                         jdouble*, jint);
- 
--    void        (*GetBooleanArrayRegion)(JNIEnv*, jbooleanArray,
-+    void        (JNICALL *GetBooleanArrayRegion)(JNIEnv*, jbooleanArray,
-                         jsize, jsize, jboolean*);
--    void        (*GetByteArrayRegion)(JNIEnv*, jbyteArray,
-+    void        (JNICALL *GetByteArrayRegion)(JNIEnv*, jbyteArray,
-                         jsize, jsize, jbyte*);
--    void        (*GetCharArrayRegion)(JNIEnv*, jcharArray,
-+    void        (JNICALL *GetCharArrayRegion)(JNIEnv*, jcharArray,
-                         jsize, jsize, jchar*);
--    void        (*GetShortArrayRegion)(JNIEnv*, jshortArray,
-+    void        (JNICALL *GetShortArrayRegion)(JNIEnv*, jshortArray,
-                         jsize, jsize, jshort*);
--    void        (*GetIntArrayRegion)(JNIEnv*, jintArray,
-+    void        (JNICALL *GetIntArrayRegion)(JNIEnv*, jintArray,
-                         jsize, jsize, jint*);
--    void        (*GetLongArrayRegion)(JNIEnv*, jlongArray,
-+    void        (JNICALL *GetLongArrayRegion)(JNIEnv*, jlongArray,
-                         jsize, jsize, jlong*);
--    void        (*GetFloatArrayRegion)(JNIEnv*, jfloatArray,
-+    void        (JNICALL *GetFloatArrayRegion)(JNIEnv*, jfloatArray,
-                         jsize, jsize, jfloat*);
--    void        (*GetDoubleArrayRegion)(JNIEnv*, jdoubleArray,
-+    void        (JNICALL *GetDoubleArrayRegion)(JNIEnv*, jdoubleArray,
-                         jsize, jsize, jdouble*);
- 
-     /* spec shows these without const; some jni.h do, some don't */
--    void        (*SetBooleanArrayRegion)(JNIEnv*, jbooleanArray,
-+    void        (JNICALL *SetBooleanArrayRegion)(JNIEnv*, jbooleanArray,
-                         jsize, jsize, const jboolean*);
--    void        (*SetByteArrayRegion)(JNIEnv*, jbyteArray,
-+    void        (JNICALL *SetByteArrayRegion)(JNIEnv*, jbyteArray,
-                         jsize, jsize, const jbyte*);
--    void        (*SetCharArrayRegion)(JNIEnv*, jcharArray,
-+    void        (JNICALL *SetCharArrayRegion)(JNIEnv*, jcharArray,
-                         jsize, jsize, const jchar*);
--    void        (*SetShortArrayRegion)(JNIEnv*, jshortArray,
-+    void        (JNICALL *SetShortArrayRegion)(JNIEnv*, jshortArray,
-                         jsize, jsize, const jshort*);
--    void        (*SetIntArrayRegion)(JNIEnv*, jintArray,
-+    void        (JNICALL *SetIntArrayRegion)(JNIEnv*, jintArray,
-                         jsize, jsize, const jint*);
--    void        (*SetLongArrayRegion)(JNIEnv*, jlongArray,
-+    void        (JNICALL *SetLongArrayRegion)(JNIEnv*, jlongArray,
-                         jsize, jsize, const jlong*);
--    void        (*SetFloatArrayRegion)(JNIEnv*, jfloatArray,
-+    void        (JNICALL *SetFloatArrayRegion)(JNIEnv*, jfloatArray,
-                         jsize, jsize, const jfloat*);
--    void        (*SetDoubleArrayRegion)(JNIEnv*, jdoubleArray,
-+    void        (JNICALL *SetDoubleArrayRegion)(JNIEnv*, jdoubleArray,
-                         jsize, jsize, const jdouble*);
- 
--    jint        (*RegisterNatives)(JNIEnv*, jclass, const JNINativeMethod*,
-+    jint        (JNICALL *RegisterNatives)(JNIEnv*, jclass, const JNINativeMethod*,
-                         jint);
--    jint        (*UnregisterNatives)(JNIEnv*, jclass);
--    jint        (*MonitorEnter)(JNIEnv*, jobject);
--    jint        (*MonitorExit)(JNIEnv*, jobject);
--    jint        (*GetJavaVM)(JNIEnv*, JavaVM**);
-+    jint        (JNICALL *UnregisterNatives)(JNIEnv*, jclass);
-+    jint        (JNICALL *MonitorEnter)(JNIEnv*, jobject);
-+    jint        (JNICALL *MonitorExit)(JNIEnv*, jobject);
-+    jint        (JNICALL *GetJavaVM)(JNIEnv*, JavaVM**);
- 
--    void        (*GetStringRegion)(JNIEnv*, jstring, jsize, jsize, jchar*);
--    void        (*GetStringUTFRegion)(JNIEnv*, jstring, jsize, jsize, char*);
-+    void        (JNICALL *GetStringRegion)(JNIEnv*, jstring, jsize, jsize, jchar*);
-+    void        (JNICALL *GetStringUTFRegion)(JNIEnv*, jstring, jsize, jsize, char*);
- 
--    void*       (*GetPrimitiveArrayCritical)(JNIEnv*, jarray, jboolean*);
--    void        (*ReleasePrimitiveArrayCritical)(JNIEnv*, jarray, void*, jint);
-+    void*       (JNICALL *GetPrimitiveArrayCritical)(JNIEnv*, jarray, jboolean*);
-+    void        (JNICALL *ReleasePrimitiveArrayCritical)(JNIEnv*, jarray, void*, jint);
- 
--    const jchar* (*GetStringCritical)(JNIEnv*, jstring, jboolean*);
--    void        (*ReleaseStringCritical)(JNIEnv*, jstring, const jchar*);
-+    const jchar* (JNICALL *GetStringCritical)(JNIEnv*, jstring, jboolean*);
-+    void        (JNICALL *ReleaseStringCritical)(JNIEnv*, jstring, const jchar*);
- 
--    jweak       (*NewWeakGlobalRef)(JNIEnv*, jobject);
--    void        (*DeleteWeakGlobalRef)(JNIEnv*, jweak);
-+    jweak       (JNICALL *NewWeakGlobalRef)(JNIEnv*, jobject);
-+    void        (JNICALL *DeleteWeakGlobalRef)(JNIEnv*, jweak);
- 
--    jboolean    (*ExceptionCheck)(JNIEnv*);
-+    jboolean    (JNICALL *ExceptionCheck)(JNIEnv*);
- 
--    jobject     (*NewDirectByteBuffer)(JNIEnv*, void*, jlong);
--    void*       (*GetDirectBufferAddress)(JNIEnv*, jobject);
--    jlong       (*GetDirectBufferCapacity)(JNIEnv*, jobject);
-+    jobject     (JNICALL *NewDirectByteBuffer)(JNIEnv*, void*, jlong);
-+    void*       (JNICALL *GetDirectBufferAddress)(JNIEnv*, jobject);
-+    jlong       (JNICALL *GetDirectBufferCapacity)(JNIEnv*, jobject);
- 
-     /* added in JNI 1.6 */
--    jobjectRefType (*GetObjectRefType)(JNIEnv*, jobject);
-+    jobjectRefType (JNICALL *GetObjectRefType)(JNIEnv*, jobject);
- };
- 
- /*
-@@ -1053,11 +1063,11 @@ struct JNIInvokeInterface {
-     void*       reserved1;
-     void*       reserved2;
- 
--    jint        (*DestroyJavaVM)(JavaVM*);
--    jint        (*AttachCurrentThread)(JavaVM*, JNIEnv**, void*);
--    jint        (*DetachCurrentThread)(JavaVM*);
--    jint        (*GetEnv)(JavaVM*, void**, jint);
--    jint        (*AttachCurrentThreadAsDaemon)(JavaVM*, JNIEnv**, void*);
-+    jint        (JNICALL *DestroyJavaVM)(JavaVM*);
-+    jint        (JNICALL *AttachCurrentThread)(JavaVM*, JNIEnv**, void*);
-+    jint        (JNICALL *DetachCurrentThread)(JavaVM*);
-+    jint        (JNICALL *GetEnv)(JavaVM*, void**, jint);
-+    jint        (JNICALL *AttachCurrentThreadAsDaemon)(JavaVM*, JNIEnv**, void*);
- };
- 
- /*
-@@ -1118,10 +1128,6 @@ jint JNI_CreateJavaVM(JavaVM**, JNIEnv**, void*);
- jint JNI_GetCreatedJavaVMs(JavaVM**, jsize, jsize*);
- #endif
- 
--#define JNIIMPORT
--#define JNIEXPORT  __attribute__ ((visibility ("default")))
--#define JNICALL
--
- /*
-  * Prototypes for functions exported by loadable shared libs.  These are
-  * called by JNI, not provided by JNI.
diff --git a/chrome/test/chromedriver/window_commands.cc b/chrome/test/chromedriver/window_commands.cc
index 30f87c1..10d9473 100644
--- a/chrome/test/chromedriver/window_commands.cc
+++ b/chrome/test/chromedriver/window_commands.cc
@@ -10,7 +10,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/platform_thread.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/test/chromedriver/basic_types.h"
 #include "chrome/test/chromedriver/chrome/chrome.h"
diff --git a/chrome/test/functional/PYAUTO_TESTS b/chrome/test/functional/PYAUTO_TESTS
index 8a96f74..8895d00 100644
--- a/chrome/test/functional/PYAUTO_TESTS
+++ b/chrome/test/functional/PYAUTO_TESTS
@@ -41,7 +41,6 @@
       'extensions',
       'fullscreen_mouselock',
       'gtalk.test_basic',
-      'imports',
       'infobars',
       'media.media_basic_playback',
       'multiprofile',
@@ -152,12 +151,6 @@
       '-extensions.ExtensionsTest.testAllowAccessFileURLs',
       # crbug.com/113090
       '-extensions.ExtensionsTest.testAllowIncognitoExtension',
-      # Disabled on vista in the actual test. crbug.com/89767
-      # -imports.ImportsTest.testImportFirefoxDataTwice
-      # Disabled on vista in the actual test. crbug.com/89767
-      # -imports.ImportsTest.testFirefoxImportFromPrefs
-      # Disabled on vista in the actual test. crbug.com/89767
-      # -imports.ImportsTest.testImportFirefoxPasswordsFromPrefs
       # crbug.com/171490
       '-passwords.PasswordTest.testPasswdInfoNotStoredWhenAutocompleteOff',
       # crbug.com/117569
@@ -186,8 +179,6 @@
       # Fails on chrome-mac-10_7-qa only: crbug.com/124886
       '-fullscreen_mouselock.FullscreenMouselockTest.testPrefsForFullscreenExit',
       '-fullscreen_mouselock.FullscreenMouselockTest.testNoMouseLockWhenCancelFS',
-      # crbug.com/114244
-      '-imports.ImportsTest.testImportSafariDataTwice',
       # crbug.com/121484
       '-multiprofile.MultiprofileTest.test20NewProfiles',
       '-ntp.NTPTest.testLaunchAppNewWindow',  # crbug.com/79812
@@ -243,8 +234,6 @@
       # ===========================
       # No codesign verification on ChromeOS.
       '-codesign',
-      # Import tests are invalid on ChromeOS since Chrome is the only browser.
-      '-imports',
       # Sync is already signed in with the login account.
       # So one-click infobar tests do tno apply to chromeos.
       '-infobars.OneClickInfobarTest',
@@ -506,6 +495,12 @@
   'WEBRTC_APPRTC': {
     'all': [
       'webrtc_apprtc_call',
+      # ==================================================
+      # Disabled tests that need to be investigated/fixed.
+      # ==================================================
+      # crbug.com/254412
+      '-webrtc_apprtc_call.WebrtcApprtcCallTest.testApprtcTabToTabCall',
+      '-webrtc_apprtc_call.WebrtcApprtcCallTest.testApprtcLoopbackCall',
     ],
   },
 
@@ -516,7 +511,8 @@
   'WEBRTC_QUALITY': {
     'all': [
       'webrtc_video_quality',
-      'webrtc_audio_quality',
+      # Disabled until crbug.com/254437 is resolved.
+      '-webrtc_audio_quality',
     ],
     'mac': [
       '-webrtc_audio_quality',  # Not implemented.
diff --git a/chrome/test/functional/imports.py b/chrome/test/functional/imports.py
deleted file mode 100755
index 443deec..0000000
--- a/chrome/test/functional/imports.py
+++ /dev/null
@@ -1,360 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import glob
-import logging
-import optparse
-import os
-import shutil
-import sys
-import tempfile
-import zipfile
-
-
-import pyauto_functional  # Must be imported before pyauto
-import pyauto
-import pyauto_utils
-
-
-class ImportsTest(pyauto.PyUITest):
-  """Import settings from other browsers.
-
-  Import settings tables below show which items get imported on first run and
-  via preferences for different browsers and operating systems.
-
-            Bookmarks   History   SearchEngines   Passwords   Homepage
-  Firefox:
-  Win/FRUI      N          Y            N             N          Y
-  Win/Prefs     Y          Y            Y             Y          N
-  Mac&Lin/FRUI  Y          Y            Y             Y          Y
-  Mac&Lin/Prefs Y          Y            Y             Y          N
-
-  Safari:
-  Mac/FRUI      Y          Y            Y             Y          N
-  Mac/Prefs     Y          Y            Y             Y          N
-  """
-  def setUp(self):
-    self._to_import = ['ALL']
-
-    if pyauto.PyUITest.IsMac():
-      self._firefox_profiles_path = os.path.join(
-          os.environ['HOME'], 'Library','Application Support','Firefox')
-      self._firefox_test_profile = os.path.abspath(os.path.join(
-          pyauto.PyUITest.DataDir(), 'import', 'firefox', 'macwin.zip'))
-      self._safari_profiles_path = os.path.join(
-          os.environ['HOME'], 'Library', 'Safari')
-      # Don't import passwords to avoid Keychain popups. See crbug.com/49378.
-      self._to_import = ['HISTORY', 'FAVORITES', 'SEARCH_ENGINES', 'HOME_PAGE']
-    elif pyauto.PyUITest.IsWin():
-      self._firefox_profiles_path = os.path.join(
-          os.getenv('APPDATA'), 'Mozilla', 'Firefox')
-      self._firefox_test_profile = os.path.abspath(os.path.join(
-          pyauto.PyUITest.DataDir(), 'import', 'firefox', 'macwin.zip'))
-    else:  # Linux
-      self._firefox_profiles_path = os.path.join(
-          os.environ['HOME'], '.mozilla', 'firefox')
-      self._firefox_test_profile = os.path.abspath(os.path.join(
-          pyauto.PyUITest.DataDir(), 'import', 'firefox', 'linux.zip'))
-
-    # Expected items for tests.
-    self._history_items = ['Google', 'Google News', u'Google \ub3c4\uc11c']
-    self._bookmark_bar_items = ['Google News', 'Google', u'Google \ub3c4\uc11c']
-    self._bookmark_folder_items = []
-    self._password_items = ['etouchqa@gmail.com', 'macqa05']
-    self._home_page = 'http://news.google.com/'
-
-    self._safari_replacer = None
-    self._firefox_replacer = None
-
-    pyauto.PyUITest.setUp(self)
-
-  def tearDown(self):
-    pyauto.PyUITest.tearDown(self)
-    # Delete any replacers to restore the original profiles.
-    if self._safari_replacer:
-      del self._safari_replacer
-    if self._firefox_replacer:
-      del self._firefox_replacer
-
-  def _UnzipProfileToDir(self, profile_zip, dir):
-    """Unzip |profile_zip| into directory |dir|.
-
-    Creates |dir| if it doesn't exist.
-    """
-    if not os.path.isdir(dir):
-      os.makedirs(dir)
-    zf = zipfile.ZipFile(profile_zip)
-    for name in zf.namelist():
-      full_path = os.path.join(dir, name)
-      if name.endswith('/'):
-        if not os.path.isdir(full_path):
-          os.makedirs(full_path)
-      else:
-        zf.extract(name, dir)
-      os.chmod(full_path, 0777)
-
-  def _SwapFirefoxProfile(self):
-    """Swaps the test Firefox profile with the original one."""
-    self._firefox_replacer = pyauto_utils.ExistingPathReplacer(
-        self._firefox_profiles_path)
-    self._UnzipProfileToDir(self._firefox_test_profile,
-                            self._firefox_profiles_path)
-
-  def _SwapSafariProfile(self):
-    """Swaps the test Safari profile with the original one."""
-    self._safari_replacer = pyauto_utils.ExistingPathReplacer(
-        self._safari_profiles_path)
-    self._UnzipProfileToDir(
-        os.path.join(self.DataDir(), 'import', 'safari', 'mac.zip'),
-        self._safari_profiles_path)
-
-  def _CheckForBookmarks(self, bookmark_titles, bookmark_bar, window_index=0):
-    """Checks that the given bookmarks exist.
-
-    Args:
-      bookmark_titles: A set of bookmark title strings.
-      bookmark_bar: True if the bookmarks are part of the bookmark bar.
-                    False otherwise.
-      window_index: The window index, default is 0.
-    """
-    bookmarks = self.GetBookmarkModel(window_index)
-    if bookmark_bar:
-      node = bookmarks.BookmarkBar()
-    else:
-      node = bookmarks.Other()
-    for title in bookmark_titles:
-      self.assertTrue([x for x in bookmark_titles \
-                       if bookmarks.FindByTitle(title, [node])])
-
-  def _BookmarkDuplicatesExist(self, bookmark_titles):
-    """Returns true if any of the bookmark titles are duplicated.
-
-    Args:
-      bookmark_titles: A list of bookmark title strings.
-    """
-    bookmarks = self.GetBookmarkModel()
-    for title in bookmark_titles:
-      if len(bookmarks.FindByTitle(title)) > 1:
-        return True
-    return False
-
-  def _CheckForHistory(self, history_titles):
-    """Verifies that the given list of history items are in the history.
-
-    Args:
-      history_titles: A list of history title strings.
-    """
-    history = self.GetHistoryInfo().History()
-
-    # History import automation is broken - crbug.com/63001
-    return
-
-    for title in history_titles:
-      self.assertTrue([x for x in history if x['title'] == title])
-
-  def _CheckForPasswords(self, usernames):
-    """Check that password items exist for the given usernames."""
-    # Password import automation does not work on Mac. See crbug.com/52124.
-    if self.IsMac():
-      return
-    passwords = self.GetSavedPasswords()
-    for username in usernames:
-      self.assertTrue([x for x in passwords if x['username_value'] == username])
-
-  def _CheckDefaults(self, bookmarks, history, passwords, home_page,
-                     search_engines, window_index=0):
-    """Checks the defaults for each of the possible import items.
-
-    All arguments are True if they should be checked, False otherwise."""
-    if bookmarks:
-      self._CheckForBookmarks(self._bookmark_bar_items, True, window_index)
-      self._CheckForBookmarks(self._bookmark_folder_items, False, window_index)
-    if history:
-      self._CheckForHistory(self._history_items)
-    if passwords:
-      self._CheckForPasswords(self._password_items)
-    if home_page:
-      self.assertEqual(self._home_page, self.GetPrefsInfo().Prefs()['homepage'])
-    # TODO(alyssad): Test for search engines after a hook is added.
-    # See crbug.com/52009.
-
-  def _CanRunFirefoxTests(self):
-    """Determine whether we can run firefox imports.
-
-    On windows, checks if firefox is installed. Always True on other platforms.
-    """
-    if self.IsWin():
-      ff_installed = os.path.exists(os.path.join(
-          os.getenv('ProgramFiles'), 'Mozilla Firefox', 'firefox.exe'))
-      if not ff_installed:
-        logging.warn('Firefox not installed.')
-      return ff_installed
-    # TODO(nirnimesh): Anything else to be done on other platforms?
-    return True
-
-  def _ImportFromFirefox(self, bookmarks, history, passwords, home_page,
-                         search_engines, window_index=0):
-    """Verify importing individual Firefox data through preferences"""
-    if not self._CanRunFirefoxTests():
-      logging.warn('Not running firefox import tests.')
-      return
-    self._SwapFirefoxProfile()
-    self.ImportSettings('Mozilla Firefox', self._to_import, window_index)
-    self._CheckDefaults(bookmarks, history, passwords, home_page,
-                        search_engines, window_index)
-
-  def _GetProfilePath(self):
-    """Get profile paths when multiprofile windows are open.
-
-    Returns:
-      profile: Path for multiprofiles.
-    """
-    profiles_list = self.GetMultiProfileInfo()['profiles']
-    profile1_path = profile2_path = default_path = None
-    for profile in profiles_list:
-      if profile['path'].find('Profile 1') != -1:
-        profile1_path = profile['path']
-      elif profile['path'].find('Profile 2') != -1:
-        profile2_path = profile['path']
-      elif profile['path'].find('Default') != -1:
-        default_path = profile['path']
-    return default_path, profile1_path, profile2_path
-
-  # Tests.
-  def testFirefoxImportFromPrefs(self):
-    """Verify importing Firefox data through preferences."""
-    if not self._CanRunFirefoxTests():
-      logging.warn('Not running firefox import tests.')
-      return
-    if self.IsWinVista():  # Broken on vista. crbug.com/89768
-      return
-    self._SwapFirefoxProfile()
-    self.ImportSettings('Mozilla Firefox', self._to_import)
-    self._CheckDefaults(bookmarks=True, history=True, passwords=True,
-                        home_page=False, search_engines=True)
-
-  def testImportFirefoxDataTwice(self):
-    """Verify importing Firefox data twice.
-
-    Bookmarks should be duplicated, but history and passwords should not.
-    """
-    if not self._CanRunFirefoxTests():
-      logging.warn('Not running firefox import tests.')
-      return
-    if self.IsWinVista():  # Broken on vista. crbug.com/89768
-      return
-    self._SwapFirefoxProfile()
-    self.ImportSettings('Mozilla Firefox', self._to_import)
-    num_history_orig = len(self.GetHistoryInfo().History())
-    num_passwords_orig = len(self.GetSavedPasswords())
-
-    # Re-import and check for duplicates.
-    self.ImportSettings('Mozilla Firefox', self._to_import)
-    self.assertTrue(self._BookmarkDuplicatesExist(
-        self._bookmark_bar_items + self._bookmark_folder_items))
-    self.assertEqual(num_history_orig, len(self.GetHistoryInfo().History()))
-    self.assertEqual(num_passwords_orig, len(self.GetSavedPasswords()))
-
-  def testImportFirefoxBookmarksFromPrefs(self):
-    """Verify importing Firefox bookmarks through preferences."""
-    self._ImportFromFirefox(bookmarks=True, history=False, passwords=False,
-                            home_page=False, search_engines=False)
-
-  def testImportFirefoxHistoryFromPrefs(self):
-    """Verify importing Firefox history through preferences."""
-    self._ImportFromFirefox(bookmarks=False, history=True, passwords=False,
-                            home_page=False, search_engines=False)
-
-  def testImportFirefoxPasswordsFromPrefs(self):
-    """Verify importing Firefox passwords through preferences."""
-    if self.IsWinVista():  # Broken on vista. crbug.com/89768
-      return
-    self._ImportFromFirefox(bookmarks=False, history=False, passwords=True,
-                            home_page=False, search_engines=False)
-
-  def testImportFirefoxSearchEnginesFromPrefs(self):
-    """Verify importing Firefox search engines through preferences."""
-    self._ImportFromFirefox(bookmarks=False, history=False, passwords=False,
-                            home_page=False, search_engines=True)
-
-  def testImportFromFirefoxAndSafari(self):
-    """Verify importing from Firefox and then Safari."""
-    # This test is for Mac only.
-    if not self.IsMac():
-      return
-
-    self._SwapSafariProfile()
-    self._SwapFirefoxProfile()
-    self.ImportSettings('Mozilla Firefox', self._to_import)
-    self.ImportSettings('Safari', self._to_import)
-
-    self._CheckDefaults(bookmarks=True, history=True, passwords=True,
-                        home_page=False, search_engines=True)
-    self.assertTrue(self._BookmarkDuplicatesExist(
-        self._bookmark_bar_items + self._bookmark_folder_items))
-
-  def testSafariImportFromPrefs(self):
-    """Verify importing Safari data through preferences."""
-    # This test is Mac only.
-    if not self.IsMac():
-      return
-    self._SwapSafariProfile()
-    self.ImportSettings('Safari', self._to_import)
-    self._CheckDefaults(bookmarks=True, history=True, passwords=False,
-                        home_page=False, search_engines=True)
-
-  def testImportSafariDataTwice(self):
-    """Verify importing Safari data twice.
-
-    Bookmarks should be duplicated, but history and passwords should not."""
-    # This test is Mac only.
-    if not self.IsMac():
-      return
-    self._SwapSafariProfile()
-    self.ImportSettings('Safari', self._to_import)
-    num_history_orig = len(self.GetHistoryInfo().History())
-    num_passwords_orig = len(self.GetSavedPasswords())
-
-    # Re-import and check for duplicates.
-    self.ImportSettings('Safari', self._to_import)
-    self.assertTrue(self._BookmarkDuplicatesExist(
-        self._bookmark_bar_items + self._bookmark_folder_items))
-    self.assertEqual(num_history_orig, len(self.GetHistoryInfo().History()))
-    self.assertEqual(num_passwords_orig, len(self.GetSavedPasswords()))
-
-  def testFireFoxImportBookmarksMultiProfile(self):
-    """Verify importing Firefox bookmarks through preferences.
-
-    Bookmarks are imported from Firefox through the preferences for multiple
-    profiles."""
-    # Create new profile, import bookmarks from firefox.
-    self.OpenNewBrowserWindowWithNewProfile()
-    self._ImportFromFirefox(bookmarks=True, history=False,
-                            passwords=False, home_page=False,
-                            search_engines=False, window_index=1)
-    # Create new profile, add 'BING', 'DB' as bookmark.
-    self.OpenNewBrowserWindowWithNewProfile()
-    bookmarks = self.GetBookmarkModel(2)
-    bar_id = bookmarks.BookmarkBar()['id']
-    self.AddBookmarkURL(bar_id, 0, 'BING', 'http://www.bing.com/', 2)
-    self.AddBookmarkURL(bar_id, 0, 'DB', 'http://www.oracle.com/', 2)
-    default_path, profile1_path, profile2_path = self._GetProfilePath()
-    # Close profile1/profile2 windows.
-    self.CloseBrowserWindow(2)
-    self.CloseBrowserWindow(1)
-    # Launch profile2.
-    self.OpenProfileWindow(path=profile2_path)
-    # Verify bookmark imported from firefox 'GoogleNews' in
-    # profile2 is not present.
-    bookmarks = self.GetBookmarkModel(1)
-    node = bookmarks.FindByTitle('GoogleNews')
-    self.assertEqual(0, len(node))
-    # Assert if 'BING' is present.
-    node = bookmarks.FindByTitle('BING')
-    self.assertEqual(1, len(node))
-
-
-if __name__ == '__main__':
-  pyauto_functional.Main()
diff --git a/chrome/test/functional/ispy/image_tools.py b/chrome/test/functional/ispy/image_tools.py
new file mode 100644
index 0000000..bf0402a
--- /dev/null
+++ b/chrome/test/functional/ispy/image_tools.py
@@ -0,0 +1,222 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Utilities for performing pixel-by-pixel image comparision."""
+
+import itertools
+import StringIO
+import PIL
+from PIL import Image
+
+
+def _AreTheSameSize(images):
+  """Returns whether a set of images are the size size.
+
+  Args:
+    images: a list of images to compare.
+
+  Returns:
+    boolean.
+
+  Raises:
+    Exception: One image or fewer is passed in.
+  """
+  if len(images) > 1:
+    return all(images[0].size == img.size for img in images[1:])
+  else:
+    raise Exception('No images passed in.')
+
+
+def _GetDifferenceWithMask(image1, image2, mask=None,
+                           masked_color=(0, 0, 0),
+                           same_color=(0, 0, 0),
+                           different_color=(255, 255, 255)):
+  """Returns an image representing the difference between the two images.
+
+  This function computes the difference between two images taking into
+  account a mask if it is provided. The final three arguments represent
+  the coloration of the generated image.
+
+  Args:
+    image1: the first image to compare.
+    image2: the second image to compare.
+    mask: an optional mask image consisting of only black and white pixels
+      where white pixels indicate the portion of the image to be masked out.
+    masked_color: the color of a masked section in the resulting image.
+    same_color: the color of an unmasked section that is the same.
+      between images 1 and 2 in the resulting image.
+    different_color: the color of an unmasked section that is different
+      between images 1 and 2 in the resulting image.
+
+  Returns:
+    an image repesenting the difference between the two images.
+
+  Raises:
+    Exception: if image1, image2, and mask are not the same size.
+  """
+  image_mask = mask
+  if not mask:
+    image_mask = PIL.Image.new('RGB', image1.size, (0, 0, 0))
+  if not _AreTheSameSize([image1, image2, image_mask]):
+    raise Exception('images and mask must be the same size.')
+  image_diff = PIL.Image.new('RGB', image1.size, (0, 0, 0))
+  data = []
+  for m, px1, px2 in itertools.izip(image_mask.getdata(),
+                                    image1.getdata(),
+                                    image2.getdata()):
+    if m == (255, 255, 255):
+      data.append(masked_color)
+    elif px1 == px2:
+      data.append(same_color)
+    else:
+      data.append(different_color)
+
+  image_diff.putdata(data)
+  return image_diff
+
+
+def CreateMask(images):
+  """Computes a mask for a set of images.
+
+  Returns a difference mask that is computed from the images
+  which are passed in. The mask will have a white pixel
+  anywhere that the input images differ and a black pixel
+  everywhere else.
+
+  Args:
+    images: the images to compute the mask from.
+
+  Returns:
+    an image of only black and white pixels where white pixels represent
+      areas in the input images that have differences.
+
+  Raises:
+    Exception: if the images passed in are not of the same size.
+    Exception: if fewer than two images are passed in.
+  """
+  if len(images) < 2:
+    raise Exception('mask must be created from two or more images.')
+  mask = Image.new('RGB', images[0].size, (0, 0, 0))
+  image = images[0]
+  for other_image in images[1:]:
+    mask = _GetDifferenceWithMask(
+        image,
+        other_image,
+        mask,
+        masked_color=(255, 255, 255))
+  return mask
+
+
+def VisualizeImageDifferences(image1, image2, mask=None):
+  """Returns an image repesenting the unmasked differences between two images.
+
+  Iterates through the pixel values of two images and an optional
+  mask. If the pixel values are the same, or the pixel is masked,
+  (0,0,0) is stored for that pixel. Otherwise, (255,255,255) is stored.
+  This ultimately produces an image where unmasked differences between
+  the two images are white pixels, and everything else is black.
+
+  Args:
+    image1: an RGB image
+    image2: another RGB image of the same size as image1.
+    mask: an optional RGB image consisting of only white and black pixels
+      where the white pixels represent the parts of the images to be masked
+      out.
+
+  Returns:
+    a black and white image representing the unmasked difference between
+    the two input images.
+
+  Raises:
+    Exception: if the two images and optional mask are different sizes.
+  """
+  return _GetDifferenceWithMask(image1, image2, mask)
+
+
+def TotalDifferentPixels(image1, image2, mask=None):
+  """Computes the number of different pixels between two images.
+
+  Args:
+    image1: the first RGB image to be compared.
+    image2: the second RGB image to be compared.
+    mask: an optional RGB image of only black and white pixels
+      where white pixels indicate the parts of the image to be masked out.
+
+  Returns:
+    the number of differing pixels between the images.
+
+  Raises:
+    Exception: if the images to be compared and the mask are not the same size.
+  """
+  image_mask = mask
+  if not mask:
+    image_mask = PIL.Image.new('RGB', image1.size, (0, 0, 0))
+  if _AreTheSameSize([image1, image2, image_mask]):
+    total_diff = 0
+    for px1, px2, m in itertools.izip(image1.getdata(),
+                                      image2.getdata(),
+                                      image_mask.getdata()):
+      if m == (255, 255, 255):
+        continue
+      elif px1 != px2:
+        total_diff += 1
+      else:
+        continue
+    return total_diff
+  else:
+    raise Exception('images and mask must be the same size')
+
+
+def SameImage(image1, image2, mask=None):
+  """Returns a boolean representing whether the images are the same.
+
+  Returns a boolean indicating whether two images are similar
+  enough to be considered the same. Essentially wraps the
+  TotalDifferentPixels function.
+
+
+  Args:
+    image1: an RGB image to compare.
+    image2: an RGB image to compare.
+    mask: an optional image of only black and white pixels
+    where white pixels are masked out
+
+  Returns:
+    True if the images are similar, False otherwise.
+
+  Raises:
+    Exception: if the images (and mask) are different sizes.
+  """
+  different_pixels = TotalDifferentPixels(image1, image2, mask)
+  return different_pixels == 0
+
+
+def SerializeImage(image):
+  """Returns a base64 encoded version of the file-contents of the image.
+
+  Args:
+    image: an RGB image to be encoded.
+
+  Returns:
+    a base64 encoded string representing the image.
+  """
+  f = StringIO.StringIO()
+  image.save(f, 'PNG')
+  encoded_image = f.getvalue().encode('base64')
+  f.close()
+  return encoded_image
+
+
+def DeserializeImage(encoded_image):
+  """Returns an RGB image from a base64 encoded string.
+
+  Args:
+    encoded_image: a base64 encoded string representation of an RGB image.
+
+  Returns:
+    an RGB image
+  """
+  return PIL.Image.open(StringIO.StringIO(encoded_image.decode('base64')))
+
+
diff --git a/chrome/test/functional/ispy/image_tools_test.py b/chrome/test/functional/ispy/image_tools_test.py
new file mode 100644
index 0000000..4ae5793
--- /dev/null
+++ b/chrome/test/functional/ispy/image_tools_test.py
@@ -0,0 +1,189 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+from PIL import Image
+
+import image_tools
+
+
+def _GenImage(size, color):
+  return Image.new('RGB', size, color)
+
+
+def _AllPixelsOfColor(image, color):
+  return not any(px != color for px in image.getdata())
+
+
+class ImageToolsTest(unittest.TestCase):
+
+  def testAreTheSameSize(self):
+    black25x25 = _GenImage((25, 25), (0, 0, 0))
+    white25x25 = _GenImage((25, 25), (255, 255, 255))
+    black50x50 = _GenImage((50, 50), (0, 0, 0))
+    white50x50 = _GenImage((50, 50), (255, 255, 255))
+
+    self.assertTrue(image_tools._AreTheSameSize([black25x25, black25x25]))
+    self.assertTrue(image_tools._AreTheSameSize([white25x25, white25x25]))
+    self.assertTrue(image_tools._AreTheSameSize([black50x50, black50x50]))
+    self.assertTrue(image_tools._AreTheSameSize([white50x50, white50x50]))
+    self.assertTrue(image_tools._AreTheSameSize([black25x25, white25x25]))
+    self.assertTrue(image_tools._AreTheSameSize([black50x50, white50x50]))
+
+    self.assertFalse(image_tools._AreTheSameSize([black50x50, black25x25]))
+    self.assertFalse(image_tools._AreTheSameSize([white50x50, white25x25]))
+    self.assertFalse(image_tools._AreTheSameSize([black25x25, white50x50]))
+    self.assertFalse(image_tools._AreTheSameSize([black50x50, white25x25]))
+
+    self.assertRaises(Exception, image_tools._AreTheSameSize, [])
+    self.assertRaises(Exception, image_tools._AreTheSameSize, [black50x50])
+
+  def testGetDifferenceWithMask(self):
+    black25x25 = _GenImage((25, 25), (0, 0, 0))
+    white25x25 = _GenImage((25, 25), (255, 255, 255))
+    black50x50 = _GenImage((50, 50), (0, 0, 0))
+    self.assertTrue(_AllPixelsOfColor(image_tools._GetDifferenceWithMask(
+        black25x25, black25x25), (0, 0, 0)))
+    self.assertTrue(_AllPixelsOfColor(image_tools._GetDifferenceWithMask(
+        white25x25, white25x25), (0, 0, 0)))
+    self.assertTrue(_AllPixelsOfColor(image_tools._GetDifferenceWithMask(
+        white25x25, black25x25), (255, 255, 255)))
+    self.assertTrue(_AllPixelsOfColor(image_tools._GetDifferenceWithMask(
+        black25x25, black25x25, mask=black25x25), (0, 0, 0)))
+    self.assertTrue(_AllPixelsOfColor(image_tools._GetDifferenceWithMask(
+        black25x25, black25x25, mask=white25x25), (0, 0, 0)))
+    self.assertTrue(_AllPixelsOfColor(image_tools._GetDifferenceWithMask(
+        black25x25, white25x25, mask=black25x25), (255, 255, 255)))
+    self.assertTrue(_AllPixelsOfColor(image_tools._GetDifferenceWithMask(
+        black25x25, white25x25, mask=white25x25), (0, 0, 0)))
+    self.assertTrue(_AllPixelsOfColor(image_tools._GetDifferenceWithMask(
+        black25x25, white25x25, different_color=(255, 0, 0)), (255, 0, 0)))
+    self.assertTrue(_AllPixelsOfColor(image_tools._GetDifferenceWithMask(
+        white25x25, white25x25, same_color=(255, 0, 0)), (255, 0, 0)))
+    self.assertTrue(_AllPixelsOfColor(image_tools._GetDifferenceWithMask(
+        white25x25, white25x25,
+        mask=white25x25, masked_color=(255, 0, 0)), (255, 0, 0)))
+    self.assertRaises(Exception, image_tools._GetDifferenceWithMask,
+                      white25x25,
+                      black50x50)
+    self.assertRaises(Exception, image_tools._GetDifferenceWithMask,
+                      white25x25,
+                      white25x25,
+                      mask=black50x50)
+
+  def testCreateMask(self):
+    black25x25 = _GenImage((25, 25), (0, 0, 0))
+    white25x25 = _GenImage((25, 25), (255, 255, 255))
+
+    m1 = image_tools.CreateMask([black25x25, white25x25])
+    self.assertTrue(_AllPixelsOfColor(m1, (255, 255, 255)))
+    m2 = image_tools.CreateMask([black25x25, black25x25])
+    self.assertTrue(_AllPixelsOfColor(m2, (0, 0, 0)))
+    m3 = image_tools.CreateMask([white25x25, white25x25])
+    self.assertTrue(_AllPixelsOfColor(m3, (0, 0, 0)))
+
+  def testTotalDifferentPixels(self):
+    white25x25 = _GenImage((25, 25), (255, 255, 255))
+    white50x50 = _GenImage((50, 50), (255, 255, 255))
+    black25x25 = _GenImage((25, 25), (0, 0, 0))
+
+    self.assertEquals(image_tools.TotalDifferentPixels(white25x25,
+                                                       white25x25),
+                      0)
+    self.assertEquals(image_tools.TotalDifferentPixels(black25x25,
+                                                       black25x25),
+                      0)
+    self.assertEquals(image_tools.TotalDifferentPixels(white25x25,
+                                                       black25x25),
+                      25*25)
+    self.assertEquals(image_tools.TotalDifferentPixels(white25x25,
+                                                       black25x25,
+                                                       mask=white25x25),
+                      0)
+    self.assertEquals(image_tools.TotalDifferentPixels(white25x25,
+                                                       white25x25,
+                                                       mask=white25x25),
+                      0)
+    self.assertEquals(image_tools.TotalDifferentPixels(white25x25,
+                                                       black25x25,
+                                                       mask=black25x25),
+                      25*25)
+    self.assertEquals(image_tools.TotalDifferentPixels(white25x25,
+                                                       white25x25,
+                                                       mask=black25x25),
+                      0)
+    self.assertRaises(Exception, image_tools.TotalDifferentPixels,
+                      white25x25, white50x50)
+    self.assertRaises(Exception, image_tools.TotalDifferentPixels,
+                      white25x25, white25x25, mask=white50x50)
+
+  def testSameImage(self):
+    white25x25 = _GenImage((25, 25), (255, 255, 255))
+    black25x25 = _GenImage((25, 25), (0, 0, 0))
+    white50x50 = _GenImage((50, 50), (255, 255, 255))
+
+    self.assertTrue(image_tools.SameImage(white25x25, white25x25))
+    self.assertFalse(image_tools.SameImage(white25x25, black25x25))
+
+    self.assertTrue(image_tools.SameImage(white25x25, black25x25,
+                                          mask=white25x25))
+    self.assertFalse(image_tools.SameImage(white25x25, black25x25,
+                                           mask=black25x25))
+    self.assertTrue(image_tools.SameImage(black25x25, black25x25))
+    self.assertTrue(image_tools.SameImage(black25x25, black25x25,
+                                          mask=white25x25))
+    self.assertTrue(image_tools.SameImage(white25x25, white25x25,
+                                          mask=white25x25))
+    self.assertRaises(Exception, image_tools.SameImage,
+                      white25x25, white50x50)
+    self.assertRaises(Exception, image_tools.SameImage,
+                      white25x25, white25x25,
+                      mask=white50x50)
+
+  def testVisualizeImageDifferences(self):
+    white25x25 = _GenImage((25, 25), (255, 255, 255))
+    black25x25 = _GenImage((25, 25), (0, 0, 0))
+    white50x50 = _GenImage((50, 50), (255, 255, 255))
+    self.assertTrue(_AllPixelsOfColor(image_tools.VisualizeImageDifferences(
+        white25x25, black25x25), (255, 255, 255)))
+    self.assertTrue(_AllPixelsOfColor(image_tools.VisualizeImageDifferences(
+        white25x25, white25x25), (0, 0, 0)))
+    self.assertTrue(_AllPixelsOfColor(image_tools.VisualizeImageDifferences(
+        black25x25, black25x25), (0, 0, 0)))
+    self.assertTrue(_AllPixelsOfColor(image_tools.VisualizeImageDifferences(
+        white25x25, black25x25, mask=white25x25), (0, 0, 0)))
+    self.assertTrue(_AllPixelsOfColor(image_tools.VisualizeImageDifferences(
+        white25x25, black25x25, mask=black25x25), (255, 255, 255)))
+    self.assertTrue(_AllPixelsOfColor(image_tools.VisualizeImageDifferences(
+        white25x25, white25x25, mask=white25x25), (0, 0, 0)))
+    self.assertTrue(_AllPixelsOfColor(image_tools.VisualizeImageDifferences(
+        white25x25, white25x25, mask=black25x25), (0, 0, 0)))
+    self.assertTrue(_AllPixelsOfColor(image_tools.VisualizeImageDifferences(
+        black25x25, black25x25, mask=black25x25), (0, 0, 0)))
+    self.assertTrue(_AllPixelsOfColor(image_tools.VisualizeImageDifferences(
+        black25x25, black25x25, mask=white25x25), (0, 0, 0)))
+
+    self.assertRaises(Exception,
+                      image_tools.VisualizeImageDifferences,
+                      white25x25,
+                      white50x50)
+    self.assertRaises(Exception,
+                      image_tools.VisualizeImageDifferences,
+                      white25x25,
+                      black25x25,
+                      mask=white50x50)
+
+  def testSerialization(self):
+    black25x25 = _GenImage((25, 25), (0, 0, 0))
+    white25x25 = _GenImage((25, 25), (255, 255, 255))
+    self.assertTrue(_AllPixelsOfColor(
+        image_tools.DeserializeImage(
+            image_tools.SerializeImage(white25x25)), (255, 255, 255)))
+    self.assertTrue(_AllPixelsOfColor(
+        image_tools.DeserializeImage(
+            image_tools.SerializeImage(black25x25)), (0, 0, 0)))
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/chrome/test/functional/webpagereplay.py b/chrome/test/functional/webpagereplay.py
index 6e66858..6d2dc5c 100755
--- a/chrome/test/functional/webpagereplay.py
+++ b/chrome/test/functional/webpagereplay.py
@@ -35,6 +35,14 @@
       '--ignore-certificate-errors',
       ]
 
+# Signal masks on Linux are inherited from parent processes.  If anything
+# invoking us accidentally masks SIGINT (e.g. by putting a process in the
+# background from a shell script), sending a SIGINT to the child will fail
+# to terminate it.  Running this signal handler before execing should fix that
+# problem.
+def ResetInterruptHandler():
+  signal.signal(signal.SIGINT, signal.SIG_DFL)
+
 class ReplayError(Exception):
   """Catch-all exception for the module."""
   pass
@@ -127,7 +135,7 @@
 
   def IsStarted(self):
     """Checks to see if the server is up and running."""
-    for _ in range(10):
+    for _ in range(30):
       if self.replay_process.poll() is not None:
         # The process has exited.
         break
@@ -153,8 +161,10 @@
     cmd_line.append(self.archive_path)
     self.log_fh = self._OpenLogFile()
     logging.debug('Starting Web-Page-Replay: %s', cmd_line)
-    self.replay_process = subprocess.Popen(
-      cmd_line, stdout=self.log_fh, stderr=subprocess.STDOUT)
+    kwargs = { 'stdout': self.log_fh, 'stderr': subprocess.STDOUT }
+    if sys.platform.startswith('linux') or sys.platform == 'darwin':
+      kwargs['preexec_fn'] = ResetInterruptHandler
+    self.replay_process = subprocess.Popen(cmd_line, **kwargs)
     if not self.IsStarted():
       log = open(self.log_path).read()
       raise ReplayNotStartedError(
diff --git a/chrome/test/gpu/gpu_pixel_browsertest.cc b/chrome/test/gpu/gpu_pixel_browsertest.cc
index e7c1c3c..ed4e1ff 100644
--- a/chrome/test/gpu/gpu_pixel_browsertest.cc
+++ b/chrome/test/gpu/gpu_pixel_browsertest.cc
@@ -268,7 +268,7 @@
           LOG(ERROR) << "Can't save revision file to: "
                      << rev_path.value();
           rt = false;
-          file_util::Delete(img_path, false);
+          base::Delete(img_path, false);
         } else {
           LOG(INFO) << "Saved revision file to: "
                     << rev_path.value();
@@ -447,7 +447,7 @@
     }
     ref_img_revision_ = max_revision;
     for (size_t i = 0; i < outdated_revs.size(); ++i)
-      file_util::Delete(outdated_revs[i], false);
+      base::Delete(outdated_revs[i], false);
   }
 
   DISALLOW_COPY_AND_ASSIGN(GpuPixelBrowserTest);
diff --git a/chrome/test/logging/win/log_file_printer.cc b/chrome/test/logging/win/log_file_printer.cc
index f262f0c..40385b9 100644
--- a/chrome/test/logging/win/log_file_printer.cc
+++ b/chrome/test/logging/win/log_file_printer.cc
@@ -18,7 +18,7 @@
 #include "base/logging.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_piece.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/test/logging/win/log_file_reader.h"
 
 namespace {
diff --git a/chrome/test/logging/win/test_log_collector.cc b/chrome/test/logging/win/test_log_collector.cc
index 86ee24c..4324e26 100644
--- a/chrome/test/logging/win/test_log_collector.cc
+++ b/chrome/test/logging/win/test_log_collector.cc
@@ -262,7 +262,7 @@
       std::cerr.flush();
     }
 
-    if (!file_util::Delete(log_file_, false))
+    if (!base::Delete(log_file_, false))
       LOG(ERROR) << "Failed to delete log file " << log_file_.value();
   }
 
diff --git a/chrome/test/mini_installer_test/installer_test_util.cc b/chrome/test/mini_installer_test/installer_test_util.cc
index cb89e55..2d8e2d5 100644
--- a/chrome/test/mini_installer_test/installer_test_util.cc
+++ b/chrome/test/mini_installer_test/installer_test_util.cc
@@ -62,7 +62,7 @@
   if (!has_install_dir || !file_util::PathExists(path))
     return false;
   path = path.AppendASCII(version);
-  return file_util::Delete(path, true);
+  return base::Delete(path, true);
 }
 
 bool DeleteRegistryKey(bool system_level,
diff --git a/chrome/test/mini_installer_test/run_all_unittests.cc b/chrome/test/mini_installer_test/run_all_unittests.cc
index 90e947c..d4d69b0 100644
--- a/chrome/test/mini_installer_test/run_all_unittests.cc
+++ b/chrome/test/mini_installer_test/run_all_unittests.cc
@@ -33,7 +33,7 @@
     // Will check if User Data is already backed up.
     // If yes, will delete and create new one.
     if (file_util::PathExists(backup_path))
-      file_util::Delete(backup_path, true);
+      base::Delete(backup_path, true);
     file_util::CopyDirectory(path, backup_path, true);
   } else {
     printf("Chrome is not installed. Will not take any backup\n");
diff --git a/chrome/test/nacl/nacl_browsertest.cc b/chrome/test/nacl/nacl_browsertest.cc
index dffa442..f8af44c 100644
--- a/chrome/test/nacl/nacl_browsertest.cc
+++ b/chrome/test/nacl/nacl_browsertest.cc
@@ -2,6 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <stdio.h>
+#if defined(OS_POSIX)
+#include <unistd.h>
+#elif defined(OS_WIN)
+#include <windows.h>
+#endif
+
+#define TELEMETRY 1
+
 #include "chrome/test/nacl/nacl_browsertest_util.h"
 
 namespace {
@@ -19,6 +28,7 @@
 #define MAYBE_CrossOriginFail DISABLED_CrossOriginFail
 #define MAYBE_SameOriginCookie DISABLED_SameOriginCookie
 #define MAYBE_CORSNoCookie DISABLED_CORSNoCookie
+#define MAYBE_SysconfNprocessorsOnln DISABLED_SysconfNprocessorsOnln
 #else
 #define MAYBE_SimpleLoad SimpleLoad
 #define MAYBE_ExitStatus0 ExitStatus0
@@ -31,12 +41,27 @@
 #define MAYBE_CrossOriginFail CrossOriginFail
 #define MAYBE_SameOriginCookie SameOriginCookie
 #define MAYBE_CORSNoCookie CORSNoCookie
+# if defined(OS_WIN)
+#  define MAYBE_SysconfNprocessorsOnln DISABLED_SysconfNprocessorsOnln
+# else
+#  define MAYBE_SysconfNprocessorsOnln SysconfNprocessorsOnln
+# endif
 #endif
 
 NACL_BROWSER_TEST_F(NaClBrowserTest, MAYBE_SimpleLoad, {
   RunLoadTest(FILE_PATH_LITERAL("nacl_load_test.html"));
 })
 
+IN_PROC_BROWSER_TEST_F(NaClBrowserTestPnaclWithNewCache,
+                       MAYBE_PNACL(SimpleLoad)) {
+  RunLoadTest(FILE_PATH_LITERAL("nacl_load_test.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(NaClBrowserTestPnaclWithNewCache,
+                       MAYBE_PNACL(PnaclErrorHandling)) {
+  RunNaClIntegrationTest(FILE_PATH_LITERAL("pnacl_error_handling.html"));
+}
+
 NACL_BROWSER_TEST_F(NaClBrowserTest, MAYBE_ExitStatus0, {
   RunNaClIntegrationTest(FILE_PATH_LITERAL(
       "pm_exit_status_test.html?trigger=exit0&expected_exit=0"));
@@ -64,6 +89,61 @@
   RunLoadTest(FILE_PATH_LITERAL("pnacl_mime_type.html"));
 })
 
+// Some versions of Visual Studio does not like preprocessor
+// conditionals inside the argument of a macro, so we put the
+// conditionals on a helper function.  We are already in an anonymous
+// namespace, so the name of the helper is not visible in external
+// scope.
+#if defined(OS_POSIX)
+base::FilePath::StringType NumberOfCoresAsFilePathString() {
+  char string_rep[23];
+  long nprocessors = sysconf(_SC_NPROCESSORS_ONLN);
+#if TELEMETRY
+  fprintf(stderr, "browser says nprocessors = %ld\n", nprocessors);
+  fflush(NULL);
+#endif
+  snprintf(string_rep, sizeof string_rep, "%ld", nprocessors);
+  return string_rep;
+}
+#elif defined(OS_WIN)
+base::FilePath::StringType NumberOfCoresAsFilePathString() {
+  wchar_t string_rep[23];
+  SYSTEM_INFO system_info;
+  GetSystemInfo(&system_info);
+#if TELEMETRY
+  fprintf(stderr, "browser says nprocessors = %d\n",
+          system_info.dwNumberOfProcessors);
+  fflush(NULL);
+#endif
+  _snwprintf_s(string_rep, sizeof string_rep / sizeof string_rep[0], _TRUNCATE,
+               L"%u", system_info.dwNumberOfProcessors);
+  return string_rep;
+}
+#endif
+
+#if TELEMETRY
+static void PathTelemetry(base::FilePath::StringType const &path) {
+# if defined(OS_WIN)
+    fwprintf(stderr, L"path = %s\n", path.c_str());
+# else
+    fprintf(stderr, "path = %s\n", path.c_str());
+# endif
+    fflush(NULL);
+}
+#else
+static void PathTelemetry(base::FilePath::StringType const &path) {
+  (void) path;
+}
+#endif
+
+NACL_BROWSER_TEST_F(NaClBrowserTest, MAYBE_SysconfNprocessorsOnln, {
+    base::FilePath::StringType path =
+      FILE_PATH_LITERAL("sysconf_nprocessors_onln_test.html?cpu_count=");
+    path = path + NumberOfCoresAsFilePathString();
+    PathTelemetry(path);
+    RunNaClIntegrationTest(path);
+})
+
 IN_PROC_BROWSER_TEST_F(NaClBrowserTestStatic, MAYBE_CrossOriginCORS) {
   RunLoadTest(FILE_PATH_LITERAL("cross_origin/cors.html"));
 }
diff --git a/chrome/test/nacl/nacl_browsertest_util.cc b/chrome/test/nacl/nacl_browsertest_util.cc
index 77136b7..41cf217 100644
--- a/chrome/test/nacl/nacl_browsertest_util.cc
+++ b/chrome/test/nacl/nacl_browsertest_util.cc
@@ -4,7 +4,9 @@
 
 #include "chrome/test/nacl/nacl_browsertest_util.h"
 
+#include <stdlib.h>
 #include "base/command_line.h"
+#include "base/environment.h"
 #include "base/json/json_reader.h"
 #include "base/path_service.h"
 #include "base/values.h"
@@ -18,7 +20,6 @@
 #include "net/base/net_util.h"
 #include "webkit/plugins/webplugininfo.h"
 
-
 typedef TestMessageHandler::MessageResponse MessageResponse;
 
 MessageResponse StructuredMessageHandler::HandleMessage(
@@ -287,6 +288,11 @@
   command_line->AppendSwitch(switches::kEnablePnacl);
 }
 
+NaClBrowserTestPnaclWithNewCache::NaClBrowserTestPnaclWithNewCache() {
+  scoped_ptr<base::Environment> env(base::Environment::Create());
+  env->SetVar("PNACL_USE_NEW_CACHE", "true");
+}
+
 base::FilePath::StringType NaClBrowserTestStatic::Variant() {
   return FILE_PATH_LITERAL("static");
 }
diff --git a/chrome/test/nacl/nacl_browsertest_util.h b/chrome/test/nacl/nacl_browsertest_util.h
index 3b9853f..914f6eb 100644
--- a/chrome/test/nacl/nacl_browsertest_util.h
+++ b/chrome/test/nacl/nacl_browsertest_util.h
@@ -123,6 +123,13 @@
   virtual bool IsPnacl() OVERRIDE;
 };
 
+// Temporary class for running tests with the new cache enabled. Once all the
+// pieces land, this will go away and the new cache will be on by default.
+class NaClBrowserTestPnaclWithNewCache : public NaClBrowserTestPnacl {
+ public:
+  NaClBrowserTestPnaclWithNewCache();
+};
+
 // A NaCl browser test only using static files.
 class NaClBrowserTestStatic : public NaClBrowserTestBase {
  public:
diff --git a/chrome/test/perf/feature_startup_test.cc b/chrome/test/perf/feature_startup_test.cc
index 283c1ce..d75e4d2 100644
--- a/chrome/test/perf/feature_startup_test.cc
+++ b/chrome/test/perf/feature_startup_test.cc
@@ -5,7 +5,7 @@
 #include "base/path_service.h"
 #include "base/perftimer.h"
 #include "base/strings/stringprintf.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
diff --git a/chrome/test/perf/generate_profile.cc b/chrome/test/perf/generate_profile.cc
index c8df762..b07f174 100644
--- a/chrome/test/perf/generate_profile.cc
+++ b/chrome/test/perf/generate_profile.cc
@@ -16,7 +16,7 @@
 #include "base/process_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/history/history_service.h"
 #include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/history/top_sites.h"
@@ -256,7 +256,7 @@
   base::FilePath path = file_iterator.Next();
   while (!path.empty()) {
     base::FilePath dst_file = dst_dir.Append(path.BaseName());
-    file_util::Delete(dst_file, false);
+    base::Delete(dst_file, false);
     if (!file_util::CopyFile(path, dst_file)) {
       PLOG(ERROR) << "Copying file failed";
       return false;
diff --git a/chrome/test/perf/memory_test.cc b/chrome/test/perf/memory_test.cc
index fae4a8c..af9564a 100644
--- a/chrome/test/perf/memory_test.cc
+++ b/chrome/test/perf/memory_test.cc
@@ -39,7 +39,7 @@
   virtual ~MemoryTest() {
     // Cleanup our temporary directory.
     if (cleanup_temp_dir_on_exit_)
-      file_util::Delete(temp_dir_, true);
+      base::Delete(temp_dir_, true);
   }
 
   // Called from SetUp() to determine the user data dir to copy.
diff --git a/chrome/test/perf/rendering/latency_tests.cc b/chrome/test/perf/rendering/latency_tests.cc
deleted file mode 100644
index 0f61cd9..0000000
--- a/chrome/test/perf/rendering/latency_tests.cc
+++ /dev/null
@@ -1,757 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/command_line.h"
-#include "base/file_util.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/path_service.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
-#include "base/test/test_switches.h"
-#include "base/test/trace_event_analyzer.h"
-#include "base/threading/platform_thread.h"
-#include "base/timer.h"
-#include "base/version.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/common/chrome_paths.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/test/base/tracing.h"
-#include "chrome/test/base/ui_test_utils.h"
-#include "chrome/test/perf/browser_perf_test.h"
-#include "chrome/test/perf/perf_test.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/test/browser_test_utils.h"
-#include "gpu/config/gpu_test_config.h"
-#include "net/base/net_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
-
-#if defined(OS_WIN)
-#include "base/win/windows_version.h"
-#endif
-
-// Run with --vmodule=latency_tests=1 to print verbose latency info.
-
-// How is latency measured?
-//
-// The test injects mouse moves many times per frame from the browser via
-// RenderWidgetHost. Each input has a unique x coordinate. When the javascript
-// handler receives the input, it stores the coordinate for later use in the
-// requestAnimationFrame callback. In RAF, the test paints using the x
-// coordinate as a color (in software, it sets the color of a table; in webgl,
-// it executes a glClearColor). Trace events emit the color when it is picked up
-// by either UpdateRect for software or gles2_cmd_decoder/glClear for webgl.
-//
-// Each UpdateRect (software) or SwapBuffers (webgl) is considered to be a frame
-// boundary that will be used to measure latency in number of frames. Starting
-// from a frame boundary Y, the test first determines what mouse x coordinate
-// was represented by the color at that frame boundary. Then, the test walks
-// backward through the trace events to find the input event matching that
-// x coordinate. Then, the test find the nearest frame boundary X to the input
-// event (may be before or after). The number of frame boundaries is then
-// counted between X and Y to determine the input latency.
-//
-// By injecting mouse moves many times per frame, we reduce flakiness in the
-// finding of the nearest frame boundary.
-//
-// This test only measures the latency introduced by chrome code -- it does not
-// measure latency introduced by mouse drivers or the GL driver or the OS window
-// manager. The actual latency seen by a user is more than what is reported by
-// this test.
-//
-// Current modes:
-// - Software RAF
-// - WebGL RAF
-// - WebGL RAF with Compositor Thread
-
-namespace {
-
-using trace_analyzer::CountMatches;
-using trace_analyzer::FindClosest;
-using trace_analyzer::FindLastOf;
-using trace_analyzer::RateStats;
-using trace_analyzer::Query;
-using trace_analyzer::TraceAnalyzer;
-using trace_analyzer::TraceEvent;
-using trace_analyzer::TraceEventVector;
-
-enum LatencyTestMode {
-  kWebGL,
-  kWebGLThread,
-  kSoftware
-};
-
-enum LatencyTestFlags {
-  kInputHeavy   = 1 << 0,
-  kInputDirty   = 1 << 1,
-  kRafHeavy     = 1 << 2,
-  kPaintHeavy   = 1 << 3
-};
-
-const int kWebGLCanvasWidth = 10;
-const int kNumFrames = 80;
-const int kInputsPerFrame = 16;
-// Magic number to identify certain glClear events.
-const int kClearColorGreen = 137;
-const int kMouseY = 5;
-
-// Don't analyze start frames that may be inaccurate. Latencies can be as high
-// as 5 frames or so, so skip the first 6 frames to get more accurate results.
-const int kIgnoreStartFrames = 6;
-// Don't analyze end frames that may be inaccurate.
-const int kIgnoreEndFrames = 4;
-// Minimum frames to produce an answer.
-const int kMinimumFramesForAnalysis = 5;
-
-class LatencyTest
-    : public BrowserPerfTest,
-      public ::testing::WithParamInterface<int> {
- public:
-  explicit LatencyTest(LatencyTestMode mode) :
-      query_instant_(Query::EventPhaseIs(TRACE_EVENT_PHASE_INSTANT)),
-      // These queries are initialized in RunTest.
-      query_begin_swaps_(Query::Bool(false)),
-      query_end_swaps_(Query::Bool(false)),
-      query_inputs_(Query::Bool(false)),
-      query_blits_(Query::Bool(false)),
-      query_clears_(Query::Bool(false)),
-      mouse_x_(0),
-      tab_width_(0),
-      mode_(mode),
-      delay_time_us_(0),
-      num_frames_(0),
-      verbose_(false),
-      test_flags_(0),
-      use_gpu_(mode == kWebGL || mode == kWebGLThread) {}
-
-  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE;
-
-  std::vector<int> GetAllBehaviors();
-
-  // Run test with specified |behaviors|.
-  // |behaviors| is a list of combinations of LatencyTestFlags.
-  void RunTest(const std::vector<int>& behaviors);
-
- private:
-  void RunTestInternal(const std::string& test_url,
-                       bool send_inputs,
-                       int input_delay_us);
-
-  double CalculateLatency();
-
-  std::string GetModeString() {
-    switch (mode_) {
-      case kWebGL:
-        return "webgl";
-      case kWebGLThread:
-        return "webgl_thread";
-      case kSoftware:
-        return "software";
-      default:
-        NOTREACHED() << "invalid mode";
-        return std::string();
-    }
-  }
-
-  std::string GetTraceName(int flags);
-
-  std::string GetUrlModeString(int flags);
-
-  std::string GetUrl(int flags);
-
-  void GetMeanFrameTimeMicros(int* frame_time) const;
-
-  void SendInput();
-
-  void PrintEvents(const TraceEventVector& events);
-
-  // Path to html file.
-  base::FilePath test_path_;
-
-  // Query INSTANT events.
-  Query query_instant_;
-
-  // Query begin of "swaps" which is SwapBuffers for GL and UpdateRect for
-  // software.
-  Query query_begin_swaps_;
-
-  // Query end of "swaps" which is SwapBuffers for GL and UpdateRect for
-  // software.
-  Query query_end_swaps_;
-
-  // Query mouse input entry events in browser process (ForwardMouseEvent).
-  Query query_inputs_;
-
-  // Query GL blits for the WebGL canvas -- represents the compositor consuming
-  // the WebGL contents for display.
-  Query query_blits_;
-
-  // Query glClear calls with mouse coordinate as clear color.
-  Query query_clears_;
-
-  // For searching trace data.
-  scoped_ptr<TraceAnalyzer> analyzer_;
-
-  // Current mouse x coordinate for injecting events.
-  int mouse_x_;
-
-  // Width of window containing our tab.
-  int tab_width_;
-
-  // Timer for injecting mouse events periodically.
-  base::RepeatingTimer<LatencyTest> timer_;
-
-  // Mode: webgl or software.
-  LatencyTestMode mode_;
-
-  // Delay time for javascript test code. Typically 2 x frame duration. Used
-  // to spin-wait in the javascript input handler and requestAnimationFrame.
-  int delay_time_us_;
-
-  // Number of frames to render from the html test code.
-  int num_frames_;
-
-  // Map from test flags combination to the calculated mean latency.
-  std::map<int, double> latencies_;
-
-  // Whether to print more verbose output.
-  bool verbose_;
-
-  // Current test flags combination, determining the behavior of the test.
-  int test_flags_;
-
-  bool use_gpu_;
-};
-
-void LatencyTest::SetUpCommandLine(CommandLine* command_line) {
-  BrowserPerfTest::SetUpCommandLine(command_line);
-  if (mode_ == kWebGLThread) {
-    ASSERT_TRUE(use_gpu_);
-    command_line->AppendSwitch(switches::kEnableThreadedCompositing);
-  } else {
-    command_line->AppendSwitch(switches::kDisableThreadedCompositing);
-  }
-  if (!use_gpu_)
-    command_line->AppendSwitch(switches::kDisableAcceleratedCompositing);
-  command_line->AppendSwitch(switches::kDisableBackgroundNetworking);
-}
-
-std::vector<int> LatencyTest::GetAllBehaviors() {
-  std::vector<int> behaviors;
-  int max_behaviors = kInputHeavy | kInputDirty | kRafHeavy | kPaintHeavy;
-  for (int i = 0; i <= max_behaviors; ++i)
-    behaviors.push_back(i);
-  return behaviors;
-}
-
-void LatencyTest::RunTest(const std::vector<int>& behaviors) {
-  verbose_ = (logging::GetVlogLevel("latency_tests") > 0);
-
-  // Linux Intel uses mesa driver, where multisampling is not supported.
-  // Multisampling is also not supported on virtualized mac os.
-  // The latency test uses the multisampling blit trace event to determine when
-  // the compositor is consuming the webgl context, so it currently doesn't work
-  // without multisampling. Since the Latency test does not depend much on the
-  // GPU, let's just skip testing on Intel since the data is redundant with
-  // other non-Intel bots.
-  gpu::GPUTestBotConfig test_bot;
-  test_bot.LoadCurrentConfig(NULL);
-  const std::vector<uint32>& gpu_vendor = test_bot.gpu_vendor();
-#if defined(OS_LINUX)
-  if (gpu_vendor.size() == 1 && gpu_vendor[0] == 0x8086)
-    return;
-#endif  // defined(OS_LINUX)
-#if defined(OS_MACOSX)
-  if (gpu_vendor.size() == 1 && gpu_vendor[0] == 0x15AD)
-    return;
-#endif  // defined(OS_MACOSX)
-
-#if defined(OS_WIN)
-  // Latency test doesn't work on WinXP. crbug.com/128066
-  if (base::win::OSInfo::GetInstance()->version() == base::win::VERSION_XP)
-    return;
-#endif
-
-  // Construct queries for searching trace events via TraceAnalyzer.
-  if (use_gpu_) {
-    query_begin_swaps_ = query_instant_ &&
-        Query::EventNameIs("SwapBuffersLatency") &&
-        Query::EventArg("width") != Query::Int(kWebGLCanvasWidth);
-    query_end_swaps_ = query_instant_ &&
-        Query::EventNameIs("CompositorSwapBuffersComplete");
-  } else if (mode_ == kSoftware) {
-    // Software updates need to have x=0 and y=0 to contain the input color.
-    query_begin_swaps_ = query_instant_ &&
-        Query::EventNameIs("UpdateRect") &&
-        Query::EventArg("x+y") == Query::Int(0);
-    query_end_swaps_ = query_instant_ &&
-        Query::EventNameIs("UpdateRectComplete") &&
-        Query::EventArg("x+y") == Query::Int(0);
-  }
-  query_inputs_ = query_instant_ &&
-      Query::EventNameIs("MouseEventBegin");
-  query_blits_ = query_instant_ &&
-      Query::EventNameIs("DoBlit") &&
-      Query::EventArg("width") == Query::Int(kWebGLCanvasWidth);
-  query_clears_ = query_instant_ &&
-      Query::EventNameIs("DoClear") &&
-      Query::EventArg("green") == Query::Int(kClearColorGreen);
-  Query query_width_swaps = Query::Bool(false);
-  if (use_gpu_) {
-    query_width_swaps = query_begin_swaps_;
-  } else if (mode_ == kSoftware) {
-    query_width_swaps = query_instant_ &&
-        Query::EventNameIs("UpdateRectWidth") &&
-        Query::EventArg("width") > Query::Int(kWebGLCanvasWidth);
-  }
-
-  // Set path to test html.
-  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_path_));
-  test_path_ = test_path_.Append(FILE_PATH_LITERAL("perf"));
-  test_path_ = test_path_.Append(FILE_PATH_LITERAL("latency_suite.html"));
-  ASSERT_TRUE(file_util::PathExists(test_path_))
-      << "Missing test file: " << test_path_.value();
-
-  // Run once with defaults to measure the frame times.
-  delay_time_us_ = 0;
-  // kNumFrames may be very high, but we only need a few frames to measure
-  // average frame times.
-  num_frames_ = 30;
-  int initial_flags = 0;
-  if (mode_ == kSoftware) {
-    // For the first run, run software with kPaintHeavy (which toggles the
-    // background color every frame) to force an update each RAF. Otherwise it
-    // won't trigger an UpdateRect each frame and we won't be able to measure
-    // framerate, because there are no inputs during the first run.
-    initial_flags = static_cast<int>(kPaintHeavy);
-  }
-  RunTestInternal(GetUrl(initial_flags), false, 0);
-
-  // Get width of tab so that we know the limit of x coordinates for the
-  // injected mouse inputs.
-  const TraceEvent* swap_event = analyzer_->FindFirstOf(query_width_swaps);
-  ASSERT_TRUE(swap_event);
-  tab_width_ = swap_event->GetKnownArgAsInt("width");
-  // Keep printf output clean by limiting input coords to three digits:
-  tab_width_ = (tab_width_ < 1000) ? tab_width_ : 999;
-  // Sanity check the tab_width -- it should be more than 100 pixels.
-  EXPECT_GT(tab_width_, 100);
-
-  int mean_frame_time_us = 0;
-  GetMeanFrameTimeMicros(&mean_frame_time_us);
-  if (verbose_)
-    printf("Mean frame time micros = %d\n", mean_frame_time_us);
-  // Delay time is 2x the average frame time.
-  delay_time_us_ = 2 * mean_frame_time_us;
-  // Calculate delay time between inputs based on the measured frame time.
-  // This prevents flooding the browser with more events than we need if the
-  // test is running very slow (such as on a VM).
-  int delay_us = mean_frame_time_us / kInputsPerFrame;
-
-  // Reset num_frames_ for actual test runs.
-  num_frames_ = kNumFrames;
-
-  // Run input latency test with each requested behavior.
-  for (size_t i = 0; i < behaviors.size(); ++i) {
-    test_flags_ = behaviors[i];
-    std::string url = GetUrl(test_flags_);
-    printf("=============================================================\n");
-    if (verbose_)
-      printf("Mode: %s\n", GetUrlModeString(i).c_str());
-    printf("URL: %s\n", url.c_str());
-
-    // Do the actual test with input events.
-    RunTestInternal(url, true, delay_us);
-    latencies_[test_flags_] = CalculateLatency();
-
-    if (mode_ == kWebGLThread) {
-      // Print vsync info when in threaded mode.
-      Query query_vsync =
-          Query::EventNameIs("OutputSurface::OnVSyncParametersChanged") &&
-          Query::EventHasNumberArg("timebase") &&
-          Query::EventHasNumberArg("interval");
-
-      const TraceEvent* vsync_info = analyzer_->FindFirstOf(query_vsync);
-      if (vsync_info) {
-        double timebase = vsync_info->GetKnownArgAsDouble("timebase");
-        double interval = vsync_info->GetKnownArgAsDouble("interval");
-        printf("VSync scheduling: timebase = %f; interval = %f\n",
-               timebase, interval);
-      }
-    }
-  }
-
-  // Print summary if more than 1 behavior was tested in this run. This is only
-  // for manual test runs for human reabable results, not for perf bots.
-  if (behaviors.size() > 1) {
-    printf("#############################################################\n");
-    printf("## %s\n", GetModeString().c_str());
-    if (verbose_) {
-      printf("Latency, behavior:\n");
-      for (size_t i = 0; i < behaviors.size(); ++i) {
-        printf("%.1f, %s%s%s%s\n", latencies_[behaviors[i]],
-               (i & kInputHeavy) ? "InputHeavy " : "",
-               (i & kInputDirty) ? "InputDirty " : "",
-               (i & kRafHeavy) ? "RafHeavy " : "",
-               (i & kPaintHeavy) ? "PaintHeavy " : "");
-      }
-    }
-    printf("Latencies for tests: ");
-    for (size_t i = 0; i < behaviors.size(); ++i) {
-      printf("%.1f%s", latencies_[behaviors[i]],
-             (i < behaviors.size() - 1) ? ", " : "");
-    }
-    printf("\n");
-    printf("#############################################################\n");
-  }
-}
-
-void LatencyTest::RunTestInternal(const std::string& test_url,
-                                  bool send_inputs,
-                                  int input_delay_us) {
-  mouse_x_ = 0;
-
-  ASSERT_TRUE(tracing::BeginTracing("cc,test_gpu,test_latency"));
-
-  ui_test_utils::NavigateToURLWithDisposition(
-      browser(), GURL(test_url), CURRENT_TAB,
-      ui_test_utils::BROWSER_TEST_NONE);
-
-  // Start sending mouse inputs.
-  if (send_inputs) {
-    // Round input_delay_us down to nearest milliseconds. The rounding in timer
-    // code rounds up from us to ms, so we need to do our own rounding here.
-    int input_delay_ms = input_delay_us / 1000;
-    input_delay_ms = (input_delay_ms <= 0) ? 1 : input_delay_ms;
-    timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(input_delay_ms),
-                 this, &LatencyTest::SendInput);
-  }
-
-  // Wait for message indicating the test has finished running.
-  content::DOMMessageQueue message_queue;
-  ASSERT_TRUE(message_queue.WaitForMessage(NULL));
-
-  timer_.Stop();
-
-  std::string json_events;
-  ASSERT_TRUE(tracing::EndTracing(&json_events));
-
-  analyzer_.reset(TraceAnalyzer::Create(json_events));
-  analyzer_->AssociateBeginEndEvents();
-  analyzer_->MergeAssociatedEventArgs();
-}
-
-double LatencyTest::CalculateLatency() {
-  TraceEventVector events;
-  if (use_gpu_) {
-    // Search for three types of events in WebGL mode:
-    //  - onscreen swaps.
-    //  - DoClear calls that contain the mouse x coordinate.
-    //  - mouse events.
-    analyzer_->FindEvents(query_begin_swaps_ || query_end_swaps_ ||
-                          query_inputs_ || query_blits_ || query_clears_,
-                          &events);
-  } else if (mode_ == kSoftware) {
-    analyzer_->FindEvents(query_begin_swaps_ || query_end_swaps_ ||
-                          query_inputs_, &events);
-  } else {
-    NOTREACHED() << "invalid mode";
-  }
-
-  if (verbose_)
-    PrintEvents(events);
-
-  int swap_count = 0;
-  size_t previous_blit_pos = 0;
-  swap_count = 0;
-  std::vector<double> latencies;
-  printf("Measured latency (in number of frames) for each frame:\n");
-  for (size_t i = 0; i < events.size(); ++i) {
-    if (query_end_swaps_.Evaluate(*events[i])) {
-      size_t end_swap_pos = i;
-
-      // Compositor context swap buffers.
-      ++swap_count;
-      // Don't analyze first few swaps, because they are filling the rendering
-      // pipeline and may be unstable.
-      if (swap_count > kIgnoreStartFrames) {
-        // First, find the beginning of this swap.
-        size_t begin_swap_pos = 0;
-        EXPECT_TRUE(FindLastOf(events, query_begin_swaps_, end_swap_pos,
-                               &begin_swap_pos));
-
-        int mouse_x = 0;
-        if (use_gpu_) {
-          // Trace backwards through the events to find the input event that
-          // matches the glClear that was presented by this SwapBuffers.
-
-          // Step 1: Find the last blit (which will be the WebGL blit).
-          size_t blit_pos = 0;
-          EXPECT_TRUE(FindLastOf(events, query_blits_, begin_swap_pos,
-                                 &blit_pos));
-          // Skip this SwapBuffers if the blit has already been consumed by a
-          // previous SwapBuffers. This means the current frame did not receive
-          // an update from WebGL.
-          if (blit_pos == previous_blit_pos) {
-            if (verbose_)
-              printf(" %03d: MISS_BLIT\n", swap_count);
-            else
-              printf(" MISS_BLIT");
-            continue;
-          }
-          previous_blit_pos = blit_pos;
-
-          // Step 2: find the last clear from the WebGL blit. This will be the
-          // value of the latest mouse input that has affected this swap.
-          size_t clear_pos = 0;
-          EXPECT_TRUE(FindLastOf(events, query_clears_, blit_pos, &clear_pos));
-          mouse_x = events[clear_pos]->GetKnownArgAsInt("red");
-        } else if (mode_ == kSoftware) {
-          // The software path gets the mouse_x directly from the DIB colors.
-          mouse_x = events[begin_swap_pos]->GetKnownArgAsInt("color");
-        }
-
-        // Find the corresponding mouse input.
-        size_t input_pos = 0;
-        Query query_mouse_event = query_inputs_ &&
-            Query::EventArg("x") == Query::Int(mouse_x);
-        EXPECT_TRUE(FindLastOf(events, query_mouse_event, begin_swap_pos,
-                               &input_pos));
-
-        // Step 4: Find the nearest onscreen SwapBuffers to this input event.
-        size_t end_swap_left = 0;
-        size_t end_swap_right = 0;
-        EXPECT_TRUE(FindLastOf(events, query_end_swaps_, input_pos,
-                               &end_swap_left));
-        EXPECT_TRUE(FindFirstOf(events, query_end_swaps_, input_pos,
-                                &end_swap_right));
-
-        EXPECT_LT(end_swap_left, input_pos);
-        EXPECT_LT(end_swap_left, end_swap_right);
-        EXPECT_LT(input_pos, end_swap_right);
-
-        // Calculate the fraction of the first frame from the input event to the
-        // next end_swap event: (right_swap - left_swap) / (right_swap - input).
-        double frame_time = (events[end_swap_right]->timestamp -
-                             events[end_swap_left]->timestamp);
-        double input_time = (events[end_swap_right]->timestamp -
-                             events[input_pos]->timestamp);
-        double latency_frame_fraction = input_time / frame_time;
-
-        EXPECT_LE(latency_frame_fraction, 1.0);
-
-        // Calculate latency by counting the number of swaps between the input
-        // event and the corresponding on-screen end-of-swap.
-        int latency_int = CountMatches(events, query_end_swaps_,
-                                       input_pos, end_swap_pos);
-
-        double latency_frames = static_cast<double>(latency_int) +
-                                latency_frame_fraction;
-        latencies.push_back(latency_frames);
-        if (verbose_)
-          printf(" %03d: %0.1f (int %d, frac %f)\n", swap_count, latency_frames,
-                 latency_int, latency_frame_fraction);
-        else
-          printf(" %0.1f", latency_frames);
-      }
-    }
-  }
-  printf("\n");
-
-  size_t ignoreEndFrames = static_cast<size_t>(kIgnoreEndFrames);
-  bool haveEnoughFrames = latencies.size() >
-      ignoreEndFrames + static_cast<size_t>(kMinimumFramesForAnalysis);
-  EXPECT_TRUE(haveEnoughFrames);
-  if (!haveEnoughFrames)
-    return 0.0;
-
-  double mean_latency = 0.0;
-  // Skip last few frames, because they may be unreliable.
-  size_t num_consider = latencies.size() - ignoreEndFrames;
-  for (size_t i = 0; i < num_consider; ++i)
-    mean_latency += latencies[i];
-  mean_latency /= static_cast<double>(num_consider);
-  printf("Mean latency = %f\n", mean_latency);
-
-  double mean_error = 0.0;
-  for (size_t i = 0; i < num_consider; ++i) {
-    double offset = fabs(mean_latency - latencies[i]);
-    mean_error = (offset > mean_error) ? offset : mean_error;
-  }
-
-  std::string trace_name = GetTraceName(test_flags_);
-  std::string mean_and_error = base::StringPrintf("%f,%f", mean_latency,
-                                                  mean_error);
-  perf_test::PrintResultMeanAndError(GetModeString(),
-                                     std::string(),
-                                     trace_name,
-                                     mean_and_error,
-                                     "frames",
-                                     true);
-  return mean_latency;
-}
-
-std::string LatencyTest::GetTraceName(int flags) {
-  if (flags == 0)
-    return "simple";
-  std::string name;
-  if (flags & kInputHeavy)
-    name += "ih";
-  if (flags & kInputDirty)
-    name += std::string(name.empty()? "" : "_") + "id";
-  if (flags & kRafHeavy)
-    name += std::string(name.empty()? "" : "_") + "rh";
-  if (flags & kPaintHeavy)
-    name += std::string(name.empty()? "" : "_") + "ph";
-  return name;
-}
-
-std::string LatencyTest::GetUrlModeString(int flags) {
-  std::string mode = "&mode=" + GetModeString();
-  if (flags & kInputHeavy)
-    mode += "&inputHeavy";
-  if (flags & kInputDirty)
-    mode += "&inputDirty";
-  if (flags & kRafHeavy)
-    mode += "&rafHeavy";
-  if (flags & kPaintHeavy)
-    mode += "&paintHeavy";
-  return mode;
-}
-
-std::string LatencyTest::GetUrl(int flags) {
-  std::string test_url =
-      net::FilePathToFileURL(test_path_).possibly_invalid_spec();
-  test_url += "?numFrames=" + base::IntToString(num_frames_);
-  test_url += "&canvasWidth=" + base::IntToString(kWebGLCanvasWidth);
-  test_url += "&clearColorGreen=" + base::IntToString(kClearColorGreen);
-  test_url += "&delayTimeMS=" + base::IntToString(delay_time_us_ / 1000);
-  test_url += "&y=" + base::IntToString(kMouseY);
-  return test_url + GetUrlModeString(flags);
-}
-
-void LatencyTest::GetMeanFrameTimeMicros(int* frame_time) const {
-  TraceEventVector events;
-  // Search for compositor swaps (or UpdateRects in the software path).
-  analyzer_->FindEvents(query_end_swaps_, &events);
-  RateStats stats;
-  trace_analyzer::RateStatsOptions options;
-  options.trim_max = 3;
-  options.trim_min = 3;
-  ASSERT_TRUE(GetRateStats(events, &stats, &options));
-
-  // Check that the number of swaps is close to kNumFrames.
-  EXPECT_LT(num_frames_ - num_frames_ / 4, static_cast<int>(events.size()));
-  *frame_time = static_cast<int>(stats.mean_us);
-}
-
-void LatencyTest::SendInput() {
-  content::RenderViewHost* rvh =
-      browser()->tab_strip_model()->GetActiveWebContents()->GetRenderViewHost();
-  WebKit::WebMouseEvent mouse_event;
-  mouse_event.movementX = 1;
-  mouse_x_ += mouse_event.movementX;
-  // Wrap mouse_x_ when it's near the edge of the tab.
-  if (mouse_x_ > tab_width_ - 5)
-    mouse_x_ = 1;
-  mouse_event.x = mouse_event.windowX = mouse_x_;
-  // Set y coordinate to be a few pixels down from the top of the window,
-  // so that it is between the top and bottom of the canvas.
-  mouse_event.y = mouse_event.windowY = 5;
-  mouse_event.type = WebKit::WebInputEvent::MouseMove;
-  TRACE_EVENT_INSTANT1("test_latency", "MouseEventBegin",
-                       TRACE_EVENT_SCOPE_THREAD, "x", mouse_x_);
-  rvh->ForwardMouseEvent(mouse_event);
-}
-
-void LatencyTest::PrintEvents(const TraceEventVector& events) {
-  bool is_software = (mode_ == kSoftware);
-  int swap_count = 0;
-  for (size_t i = 0; i < events.size(); ++i) {
-    if (events[i]->name == "MouseEventBegin") {
-      printf("%03d ", events[i]->GetKnownArgAsInt("x"));
-    } else if (events[i]->name == "DoClear") {
-      printf("Clr%03d ", events[i]->GetKnownArgAsInt("red"));
-    } else if (events[i]->name == "DoBlit") {
-      // WebGL context swap buffers.
-      printf("BLT ");
-    } else if (events[i]->name == "SwapBuffersLatency") {
-      // Compositor context swap buffers.
-      ++swap_count;
-      printf("|\nframe %03d: ", swap_count + 1);
-    } else if (is_software && events[i]->name == "UpdateRect") {
-      ++swap_count;
-      printf("(%d)|\nframe %03d: ",
-              events[i]->GetKnownArgAsInt("color"), swap_count + 1);
-    }
-  }
-  printf("\n");
-}
-
-// For running tests on GPU:
-class LatencyTestWebGL : public LatencyTest {
- public:
-  LatencyTestWebGL() : LatencyTest(kWebGL) {}
-};
-
-// For running tests on GPU with the compositor thread:
-class LatencyTestWebGLThread : public LatencyTest {
- public:
-  LatencyTestWebGLThread() : LatencyTest(kWebGLThread) {}
-};
-
-// For running tests on Software:
-class LatencyTestSW : public LatencyTest {
- public:
-  LatencyTestSW() : LatencyTest(kSoftware) {}
-};
-
-////////////////////////////////////////////////////////////////////////////////
-/// Tests
-
-using ::testing::Values;
-
-// For manual testing only, run all input latency tests and print summary.
-IN_PROC_BROWSER_TEST_F(LatencyTestWebGL, DISABLED_LatencyWebGLAll) {
-  RunTest(GetAllBehaviors());
-}
-
-// For manual testing only, run all input latency tests and print summary.
-IN_PROC_BROWSER_TEST_F(LatencyTestWebGLThread, DISABLED_LatencyWebGLThreadAll) {
-  RunTest(GetAllBehaviors());
-}
-
-// For manual testing only, run all input latency tests and print summary.
-IN_PROC_BROWSER_TEST_F(LatencyTestSW, DISABLED_LatencySoftwareAll) {
-  RunTest(GetAllBehaviors());
-}
-
-IN_PROC_BROWSER_TEST_P(LatencyTestWebGL, LatencyWebGL) {
-  RunTest(std::vector<int>(1, GetParam()));
-}
-
-IN_PROC_BROWSER_TEST_P(LatencyTestWebGLThread, LatencyWebGLThread) {
-  RunTest(std::vector<int>(1, GetParam()));
-}
-
-IN_PROC_BROWSER_TEST_P(LatencyTestSW, LatencySoftware) {
-  RunTest(std::vector<int>(1, GetParam()));
-}
-
-#define LATENCY_SUITE_MODES() ::testing::Values( \
-    0, \
-    kInputHeavy, \
-    kInputHeavy | kInputDirty | kRafHeavy, \
-    kInputHeavy | kInputDirty | kRafHeavy | kPaintHeavy, \
-    kInputDirty | kPaintHeavy, \
-    kInputDirty | kRafHeavy | kPaintHeavy)
-
-INSTANTIATE_TEST_CASE_P(, LatencyTestWebGL, LATENCY_SUITE_MODES());
-INSTANTIATE_TEST_CASE_P(, LatencyTestWebGLThread, LATENCY_SUITE_MODES());
-INSTANTIATE_TEST_CASE_P(, LatencyTestSW, LATENCY_SUITE_MODES());
-
-}  // namespace
diff --git a/chrome/test/perf/shutdown_test.cc b/chrome/test/perf/shutdown_test.cc
index df5bb3e..a078833 100644
--- a/chrome/test/perf/shutdown_test.cc
+++ b/chrome/test/perf/shutdown_test.cc
@@ -8,7 +8,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/sys_info.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/env_vars.h"
diff --git a/chrome/test/perf/startup_test.cc b/chrome/test/perf/startup_test.cc
index 6ff4a2a..72b39d2 100644
--- a/chrome/test/perf/startup_test.cc
+++ b/chrome/test/perf/startup_test.cc
@@ -14,7 +14,7 @@
 #include "base/sys_info.h"
 #include "base/test/test_file_util.h"
 #include "base/test/test_timeouts.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
diff --git a/chrome/test/perf/tab_switching_test.cc b/chrome/test/perf/tab_switching_test.cc
index d3dd4e4..6d5859f 100644
--- a/chrome/test/perf/tab_switching_test.cc
+++ b/chrome/test/perf/tab_switching_test.cc
@@ -11,7 +11,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/platform_thread.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
diff --git a/chrome/test/ppapi/ppapi_browsertest.cc b/chrome/test/ppapi/ppapi_browsertest.cc
index 1074334..a036cb9 100644
--- a/chrome/test/ppapi/ppapi_browsertest.cc
+++ b/chrome/test/ppapi/ppapi_browsertest.cc
@@ -215,6 +215,10 @@
 TEST_PPAPI_OUT_OF_PROCESS(Core)
 TEST_PPAPI_NACL(Core)
 
+TEST_PPAPI_IN_PROCESS(TraceEvent)
+TEST_PPAPI_OUT_OF_PROCESS(TraceEvent)
+TEST_PPAPI_NACL(TraceEvent)
+
 TEST_PPAPI_IN_PROCESS(InputEvent)
 TEST_PPAPI_OUT_OF_PROCESS(InputEvent)
 TEST_PPAPI_NACL(InputEvent)
@@ -802,10 +806,42 @@
   );
 }
 
-TEST_PPAPI_IN_PROCESS_VIA_HTTP(FileRef)
+IN_PROC_BROWSER_TEST_F(PPAPITest, FileRef) {
+  RunTestViaHTTP(
+      LIST_TEST(FileRef_Create)
+      LIST_TEST(FileRef_GetFileSystemType)
+      LIST_TEST(FileRef_GetName)
+      LIST_TEST(FileRef_GetPath)
+      LIST_TEST(FileRef_GetParent)
+      LIST_TEST(FileRef_MakeDirectory)
+      LIST_TEST(FileRef_QueryAndTouchFile)
+      LIST_TEST(FileRef_DeleteFileAndDirectory)
+      LIST_TEST(FileRef_RenameFileAndDirectory)
+      // TODO(teravest): Add in-process support.
+      // LIST_TEST(FileRef_Query)
+      LIST_TEST(FileRef_FileNameEscaping)
+      // TODO(teravest): Add in-process support.
+      // LIST_TEST(FileRef_ReadDirectoryEntries)
+  );
+}
 // OutOfProcessPPAPITest.FileRef times out fairly often.
 // http://crbug.com/241646
-TEST_PPAPI_OUT_OF_PROCESS_VIA_HTTP(DISABLED_FileRef)
+IN_PROC_BROWSER_TEST_F(OutOfProcessPPAPITest, FileRef) {
+  RunTestViaHTTP(
+      LIST_TEST(FileRef_Create)
+      LIST_TEST(FileRef_GetFileSystemType)
+      LIST_TEST(FileRef_GetName)
+      LIST_TEST(FileRef_GetPath)
+      LIST_TEST(FileRef_GetParent)
+      LIST_TEST(FileRef_MakeDirectory)
+      LIST_TEST(FileRef_QueryAndTouchFile)
+      LIST_TEST(FileRef_DeleteFileAndDirectory)
+      LIST_TEST(FileRef_RenameFileAndDirectory)
+      LIST_TEST(FileRef_Query)
+      LIST_TEST(FileRef_FileNameEscaping)
+      LIST_TEST(DISABLED_FileRef_ReadDirectoryEntries)
+  );
+}
 IN_PROC_BROWSER_TEST_F(PPAPINaClNewlibTest, FileRef) {
   RunTestViaHTTP(
       LIST_TEST(FileRef_Create)
@@ -1396,12 +1432,18 @@
 TEST_PPAPI_OUT_OF_PROCESS(MouseCursor)
 TEST_PPAPI_NACL(MouseCursor)
 
+// PPB_NetworkProxy is not supported in-process.
+TEST_PPAPI_OUT_OF_PROCESS(NetworkProxy)
+TEST_PPAPI_NACL(NetworkProxy)
+
 TEST_PPAPI_OUT_OF_PROCESS(TrueTypeFont)
 TEST_PPAPI_NACL(TrueTypeFont)
 
-TEST_PPAPI_OUT_OF_PROCESS(VideoSource)
-
 TEST_PPAPI_OUT_OF_PROCESS(VideoDestination)
+TEST_PPAPI_NACL(VideoDestination)
+
+TEST_PPAPI_OUT_OF_PROCESS(VideoSource)
+TEST_PPAPI_NACL(VideoSource)
 
 // PPB_Printing only implemented for out of process.
 TEST_PPAPI_OUT_OF_PROCESS(Printing)
diff --git a/chrome/test/ppapi/ppapi_test.cc b/chrome/test/ppapi/ppapi_test.cc
index 1a9b5db..daed946 100644
--- a/chrome/test/ppapi/ppapi_test.cc
+++ b/chrome/test/ppapi/ppapi_test.cc
@@ -317,6 +317,7 @@
 void OutOfProcessPPAPITest::SetUpCommandLine(CommandLine* command_line) {
   PPAPITest::SetUpCommandLine(command_line);
   command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream);
+  command_line->AppendSwitch(switches::kUseFakeUIForMediaStream);
 }
 
 void PPAPINaClTest::SetUpCommandLine(CommandLine* command_line) {
@@ -331,6 +332,7 @@
   command_line->AppendSwitch(switches::kEnablePnacl);
   command_line->AppendSwitchASCII(switches::kAllowNaClSocketAPI, "127.0.0.1");
   command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream);
+  command_line->AppendSwitch(switches::kUseFakeUIForMediaStream);
 }
 
 // Append the correct mode and testcase string
diff --git a/chrome/test/pyautolib/dom_mutation_observer.js b/chrome/test/pyautolib/dom_mutation_observer.js
index cac4934..ced5ec3 100644
--- a/chrome/test/pyautolib/dom_mutation_observer.js
+++ b/chrome/test/pyautolib/dom_mutation_observer.js
@@ -175,7 +175,7 @@
       return;
     }
 
-    var obs = new WebKitMutationObserver(addNodeCallback);
+    var obs = new MutationObserver(addNodeCallback);
     obs.observe(document,
         { childList: true,
           attributes: true,
@@ -196,7 +196,7 @@
       return;
     }
 
-    var obs = new WebKitMutationObserver(removeNodeCallback);
+    var obs = new MutationObserver(removeNodeCallback);
     obs.observe(document,
         { childList: true,
           attributes: true,
@@ -219,7 +219,7 @@
     }
     window.domAutomationController.send("success");
 
-    var obs = new WebKitMutationObserver(changeNodeCallback);
+    var obs = new MutationObserver(changeNodeCallback);
     obs.observe(node,
         { childList: true,
           attributes: true,
@@ -240,7 +240,7 @@
       return;
     }
 
-    var obs = new WebKitMutationObserver(existsNodeCallback);
+    var obs = new MutationObserver(existsNodeCallback);
     obs.observe(document,
         { childList: true,
           attributes: true,
diff --git a/chrome/test/pyautolib/pyauto.py b/chrome/test/pyautolib/pyauto.py
index 9ca0a4a..29b2e29 100755
--- a/chrome/test/pyautolib/pyauto.py
+++ b/chrome/test/pyautolib/pyauto.py
@@ -288,8 +288,9 @@
         '--skip-oauth-login',
         # Enables injection of test content script for webui login automation
         '--auth-ext-path=%s' % auth_ext_path,
-        # Enable automation provider and chromeos net logs
-        '--vmodule=*/browser/automation/*=2,*/chromeos/net/*=2',
+        # Enable automation provider, chromeos net and chromeos login logs
+        '--vmodule=*/browser/automation/*=2,*/chromeos/net/*=2,' +
+            '*/chromeos/login/*=2',
       ]
     else:
       return []
@@ -2995,33 +2996,6 @@
     finally:
       shutil.rmtree(tempdir, ignore_errors=True)
 
-  def ImportSettings(self, import_from, import_items, windex=0):
-    """Import the specified import items from the specified browser.
-
-    Implements the features available in the "Import Settings" part of the
-    first-run UI dialog.
-
-    Args:
-      import_from: A string indicating which browser to import from. Possible
-                   strings (depending on which browsers are installed on the
-                   machine) are: 'Mozilla Firefox', 'Google Toolbar',
-                   'Microsoft Internet Explorer', 'Safari'
-      import_items: A list of strings indicating which items to import.
-                    Strings that can be in the list are:
-                    HISTORY, FAVORITES, PASSWORDS, SEARCH_ENGINES, HOME_PAGE,
-                    ALL (note: COOKIES is not supported by the browser yet)
-      windex: window index, defaults to 0.
-
-    Raises:
-      pyauto_errors.JSONInterfaceError if the automation call returns an error.
-    """
-    cmd_dict = {  # Prepare command for the json interface
-      'command': 'ImportSettings',
-      'import_from': import_from,
-      'import_items': import_items
-    }
-    return self._GetResultFromJSONRequest(cmd_dict, windex=windex)
-
   def AddSavedPassword(self, password_dict, windex=0):
     """Adds the given username-password combination to the saved passwords.
 
diff --git a/chrome/test/pyautolib/pyautolib.cc b/chrome/test/pyautolib/pyautolib.cc
index 69b5723..3e27fb9 100644
--- a/chrome/test/pyautolib/pyautolib.cc
+++ b/chrome/test/pyautolib/pyautolib.cc
@@ -10,7 +10,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/common/automation_messages.h"
 #include "chrome/common/chrome_switches.h"
diff --git a/chrome/test/pyautolib/pyautolib.h b/chrome/test/pyautolib/pyautolib.h
index bcbe374..2b37dfc 100644
--- a/chrome/test/pyautolib/pyautolib.h
+++ b/chrome/test/pyautolib/pyautolib.h
@@ -11,7 +11,7 @@
 #include "base/compiler_specific.h"
 #include "base/message_loop.h"
 #include "base/test/test_timeouts.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/test/ui/ui_test.h"
 #include "chrome/test/ui/ui_test_suite.h"
 
diff --git a/chrome/test/reliability/automated_ui_tests.cc b/chrome/test/reliability/automated_ui_tests.cc
index 97d469f..10a0c2a 100644
--- a/chrome/test/reliability/automated_ui_tests.cc
+++ b/chrome/test/reliability/automated_ui_tests.cc
@@ -21,11 +21,12 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/platform_thread.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/character_encoding.h"
 #include "chrome/browser/ui/view_ids.h"
+#include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_version_info.h"
 #include "chrome/common/env_vars.h"
 #include "chrome/common/url_constants.h"
@@ -35,7 +36,6 @@
 #include "chrome/test/automation/window_proxy.h"
 #include "chrome/test/reliability/automated_ui_tests.h"
 #include "chrome/test/ui/ui_test.h"
-#include "components/breakpad/common/breakpad_paths.h"
 #include "googleurl/src/gurl.h"
 #include "ui/base/keycodes/keyboard_codes.h"
 
@@ -767,7 +767,7 @@
 base::FilePath AutomatedUITest::GetMostRecentCrashDump() {
   base::FilePath crash_dump_path;
   base::FilePath most_recent_file_name;
-  PathService::Get(breakpad::DIR_CRASH_DUMPS, &crash_dump_path);
+  PathService::Get(chrome::DIR_CRASH_DUMPS, &crash_dump_path);
   base::Time most_recent_file_time;
 
   bool first_file = true;
diff --git a/chrome/test/reliability/page_load_test.cc b/chrome/test/reliability/page_load_test.cc
index f8ad018..ddbf6eb 100644
--- a/chrome/test/reliability/page_load_test.cc
+++ b/chrome/test/reliability/page_load_test.cc
@@ -53,7 +53,7 @@
 #include "base/strings/string_util.h"
 #include "base/test/test_file_util.h"
 #include "base/threading/platform_thread.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/browser/net/url_fixer_upper.h"
 #include "chrome/browser/prefs/pref_service_mock_builder.h"
 #include "chrome/common/automation_messages.h"
@@ -70,7 +70,6 @@
 #include "chrome/test/automation/tab_proxy.h"
 #include "chrome/test/automation/window_proxy.h"
 #include "chrome/test/ui/ui_test.h"
-#include "components/breakpad/common/breakpad_paths.h"
 #include "net/base/net_util.h"
 #include "ui/base/keycodes/keyboard_codes.h"
 #include "v8/include/v8-testing.h"
@@ -635,7 +634,7 @@
       crash_dumps_dir_path_ = base::FilePath::FromUTF8Unsafe(
           alternate_minidump_location);
     } else {
-      PathService::Get(breakpad::DIR_CRASH_DUMPS, &crash_dumps_dir_path_);
+      PathService::Get(chrome::DIR_CRASH_DUMPS, &crash_dumps_dir_path_);
     }
 
     base::FileEnumerator enumerator(crash_dumps_dir_path_,
@@ -661,7 +660,7 @@
     if (!log_path.empty()) {
       base::FilePath saved_log_file_path =
           ConstructSavedDebugLogPath(log_path, index);
-      if (file_util::Move(log_path, saved_log_file_path)) {
+      if (base::Move(log_path, saved_log_file_path)) {
         log_file << " " << log_id << "=" << saved_log_file_path.value();
       }
     }
diff --git a/chrome/test/ui/ui_test.cc b/chrome/test/ui/ui_test.cc
index b723883..8154581 100644
--- a/chrome/test/ui/ui_test.cc
+++ b/chrome/test/ui/ui_test.cc
@@ -31,7 +31,7 @@
 #include "base/test/test_file_util.h"
 #include "base/test/test_timeouts.h"
 #include "base/threading/platform_thread.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/net/url_fixer_upper.h"
 #include "chrome/browser/profiles/profile_impl.h"
@@ -51,7 +51,6 @@
 #include "chrome/test/base/test_launcher_utils.h"
 #include "chrome/test/base/test_switches.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/breakpad/common/breakpad_paths.h"
 #include "googleurl/src/gurl.h"
 #include "net/base/net_util.h"
 #include "ui/gl/gl_implementation.h"
@@ -425,7 +424,7 @@
 
 int UITestBase::GetCrashCount() const {
   base::FilePath crash_dump_path;
-  PathService::Get(breakpad::DIR_CRASH_DUMPS, &crash_dump_path);
+  PathService::Get(chrome::DIR_CRASH_DUMPS, &crash_dump_path);
 
   int files_found = 0;
   base::FileEnumerator en(crash_dump_path, false, base::FileEnumerator::FILES);
diff --git a/chrome/test/ui/ui_test.h b/chrome/test/ui/ui_test.h
index 99b3603..c6cc7ed 100644
--- a/chrome/test/ui/ui_test.h
+++ b/chrome/test/ui/ui_test.h
@@ -23,7 +23,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/message_loop.h"
 #include "base/process.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/test/automation/proxy_launcher.h"
 #include "googleurl/src/gurl.h"
 #include "testing/platform_test.h"
diff --git a/chrome/test/webdriver/keycode_text_conversion_mac.mm b/chrome/test/webdriver/keycode_text_conversion_mac.mm
index 7db3366..aa2e424 100644
--- a/chrome/test/webdriver/keycode_text_conversion_mac.mm
+++ b/chrome/test/webdriver/keycode_text_conversion_mac.mm
@@ -41,7 +41,7 @@
   // on UCKeyTranslate for more info.
   UInt32 modifier_key_state = (mac_modifiers >> 8) & 0xFF;
 
-  base::mac::ScopedCFTypeRef<TISInputSourceRef> input_source_copy(
+  base::ScopedCFTypeRef<TISInputSourceRef> input_source_copy(
       TISCopyCurrentKeyboardLayoutInputSource());
   CFDataRef layout_data = static_cast<CFDataRef>(TISGetInputSourceProperty(
       input_source_copy, kTISPropertyUnicodeKeyLayoutData));
diff --git a/chrome/test/webdriver/webdriver_automation.cc b/chrome/test/webdriver/webdriver_automation.cc
index 2c2f13d..418e0b2 100644
--- a/chrome/test/webdriver/webdriver_automation.cc
+++ b/chrome/test/webdriver/webdriver_automation.cc
@@ -440,7 +440,7 @@
 #elif defined(OS_POSIX)
     base::FilePath temp_file;
     if (!file_util::CreateTemporaryFile(&temp_file) ||
-        !file_util::Delete(temp_file, false /* recursive */)) {
+        !base::Delete(temp_file, false /* recursive */)) {
       *error = new Error(kUnknownError, "Could not create temporary filename");
       return;
     }
diff --git a/chrome/test/webdriver/webdriver_logging.cc b/chrome/test/webdriver/webdriver_logging.cc
index 7a56f06..8698ef4 100644
--- a/chrome/test/webdriver/webdriver_logging.cc
+++ b/chrome/test/webdriver/webdriver_logging.cc
@@ -12,7 +12,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "build/build_config.h"
 
 using base::DictionaryValue;
@@ -228,12 +228,9 @@
                           LogLevel min_log_level) {
   start_time = base::Time::Now().ToDoubleT();
   // Turn off base/logging.
-  bool success = InitLogging(
-      NULL,
-      logging::LOG_NONE,
-      logging::DONT_LOCK_LOG_FILE,
-      logging::DELETE_OLD_LOG_FILE,
-      logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS);
+  logging::LoggingSettings settings;
+  settings.logging_dest = logging::LOG_NONE;
+  bool success = logging::InitLogging(settings);
   if (!success) {
     PLOG(ERROR) << "Unable to initialize logging";
   }
diff --git a/chrome/test/webdriver/webdriver_server.cc b/chrome/test/webdriver/webdriver_server.cc
index 1b47258..0785faf 100644
--- a/chrome/test/webdriver/webdriver_server.cc
+++ b/chrome/test/webdriver/webdriver_server.cc
@@ -26,7 +26,7 @@
 #include "base/synchronization/waitable_event.h"
 #include "base/test/test_timeouts.h"
 #include "base/threading/platform_thread.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
diff --git a/chrome/test/webdriver/webdriver_session.cc b/chrome/test/webdriver/webdriver_session.cc
index da8c68b..61ddee8 100644
--- a/chrome/test/webdriver/webdriver_session.cc
+++ b/chrome/test/webdriver/webdriver_session.cc
@@ -26,7 +26,7 @@
 #include "base/synchronization/waitable_event.h"
 #include "base/test/test_timeouts.h"
 #include "base/threading/platform_thread.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/common/chrome_constants.h"
diff --git a/chrome/test/webdriver/webdriver_test_util.cc b/chrome/test/webdriver/webdriver_test_util.cc
index 98c8827..0700adc 100644
--- a/chrome/test/webdriver/webdriver_test_util.cc
+++ b/chrome/test/webdriver/webdriver_test_util.cc
@@ -41,15 +41,15 @@
 
 #if defined(OS_MACOSX)
 bool SwitchKeyboardLayout(const std::string& input_source_id) {
-  base::mac::ScopedCFTypeRef<CFMutableDictionaryRef> filter_dict(
+  base::ScopedCFTypeRef<CFMutableDictionaryRef> filter_dict(
       CFDictionaryCreateMutable(kCFAllocatorDefault,
                                 1,
                                 &kCFTypeDictionaryKeyCallBacks,
                                 &kCFTypeDictionaryValueCallBacks));
-  base::mac::ScopedCFTypeRef<CFStringRef> id_ref(CFStringCreateWithCString(
+  base::ScopedCFTypeRef<CFStringRef> id_ref(CFStringCreateWithCString(
       kCFAllocatorDefault, input_source_id.c_str(), kCFStringEncodingUTF8));
   CFDictionaryAddValue(filter_dict, kTISPropertyInputSourceID, id_ref);
-  base::mac::ScopedCFTypeRef<CFArrayRef> sources(
+  base::ScopedCFTypeRef<CFArrayRef> sources(
       TISCreateInputSourceList(filter_dict, true));
   if (CFArrayGetCount(sources) != 1)
     return false;
diff --git a/chrome/test/webdriver/webdriver_test_util.h b/chrome/test/webdriver/webdriver_test_util.h
index 526ea14..0531c58 100644
--- a/chrome/test/webdriver/webdriver_test_util.h
+++ b/chrome/test/webdriver/webdriver_test_util.h
@@ -29,7 +29,7 @@
 #if defined(OS_WIN)
   HKL layout_;
 #elif defined(OS_MACOSX)
-  base::mac::ScopedCFTypeRef<TISInputSourceRef> layout_;
+  base::ScopedCFTypeRef<TISInputSourceRef> layout_;
 #endif
 
   DISALLOW_COPY_AND_ASSIGN(RestoreKeyboardLayoutOnDestruct);
diff --git a/chrome/tools/DEPS b/chrome/tools/DEPS
index d6cef97..b5d4427 100644
--- a/chrome/tools/DEPS
+++ b/chrome/tools/DEPS
@@ -2,7 +2,6 @@
   "+breakpad",
   "+chrome/browser",
   "+chrome/third_party/hunspell/google",
-  "+components/breakpad",
   "+content/browser",
   "+content/public/browser",
 ]
diff --git a/chrome/tools/build/generate_policy_source.py b/chrome/tools/build/generate_policy_source.py
index 085b874..d387b82 100755
--- a/chrome/tools/build/generate_policy_source.py
+++ b/chrome/tools/build/generate_policy_source.py
@@ -244,7 +244,7 @@
   f.write('const PolicyDefinitionList::Entry kEntries[] = {\n')
   for policy in policies:
     if policy.is_supported:
-      f.write('  { key::k%s, Value::%s, %s, %s },\n' %
+      f.write('  { key::k%s, base::Value::%s, %s, %s },\n' %
           (policy.name, policy.value_type,
               'true' if policy.is_device_only else 'false', policy.id))
   f.write('};\n\n')
@@ -424,7 +424,7 @@
 
 namespace em = enterprise_management;
 
-Value* DecodeIntegerValue(google::protobuf::int64 value) {
+base::Value* DecodeIntegerValue(google::protobuf::int64 value) {
   if (value < std::numeric_limits<int>::min() ||
       value > std::numeric_limits<int>::max()) {
     LOG(WARNING) << "Integer value " << value
@@ -432,15 +432,15 @@
     return NULL;
   }
 
-  return Value::CreateIntegerValue(static_cast<int>(value));
+  return base::Value::CreateIntegerValue(static_cast<int>(value));
 }
 
-ListValue* DecodeStringList(const em::StringList& string_list) {
-  ListValue* list_value = new ListValue;
+base::ListValue* DecodeStringList(const em::StringList& string_list) {
+  base::ListValue* list_value = new base::ListValue;
   RepeatedPtrField<std::string>::const_iterator entry;
   for (entry = string_list.entries().begin();
        entry != string_list.entries().end(); ++entry) {
-    list_value->Append(Value::CreateStringValue(*entry));
+    list_value->Append(base::Value::CreateStringValue(*entry));
   }
   return list_value;
 }
@@ -457,16 +457,16 @@
 
 def _CreateValue(type, arg):
   if type == 'TYPE_BOOLEAN':
-    return 'Value::CreateBooleanValue(%s)' % arg
+    return 'base::Value::CreateBooleanValue(%s)' % arg
   elif type == 'TYPE_INTEGER':
     return 'DecodeIntegerValue(%s)' % arg
   elif type == 'TYPE_STRING':
-    return 'Value::CreateStringValue(%s)' % arg
+    return 'base::Value::CreateStringValue(%s)' % arg
   elif type == 'TYPE_LIST':
     return 'DecodeStringList(%s)' % arg
   elif type == 'TYPE_DICTIONARY':
     # TODO(joaodasilva): decode 'dict' types. http://crbug.com/108997
-    return 'new DictionaryValue()'
+    return 'new base::DictionaryValue()'
   else:
     raise NotImplementedError('Unknown type %s' % type)
 
@@ -496,7 +496,7 @@
           '        }\n'
           '      }\n'
           '      if (do_set) {\n')
-  f.write('        Value* value = %s;\n' %
+  f.write('        base::Value* value = %s;\n' %
           (_CreateValue(policy.value_type, 'policy_proto.value()')))
   f.write('        map->Set(key::k%s, level, POLICY_SCOPE_USER, value);\n' %
           policy.name)
diff --git a/chrome/tools/build/mac/FILES.cfg b/chrome/tools/build/mac/FILES.cfg
index b6be520..7261b17 100644
--- a/chrome/tools/build/mac/FILES.cfg
+++ b/chrome/tools/build/mac/FILES.cfg
@@ -57,6 +57,13 @@
   },
   {
     'filename': 'nacl_irt_x86_32.nexe.debug',
+    'arch': ['32bit'],
+    'buildtype': ['official'],
+    'archive': 'chrome-mac-nacl-irt-syms.zip',
+  },
+  {
+    'filename': 'nacl_irt_x86_64.nexe.debug',
+    'arch': ['64bit'],
     'buildtype': ['official'],
     'archive': 'chrome-mac-nacl-irt-syms.zip',
   },
diff --git a/chrome/tools/convert_dict/convert_dict_unittest.cc b/chrome/tools/convert_dict/convert_dict_unittest.cc
index fa51f4f..91658d1 100644
--- a/chrome/tools/convert_dict/convert_dict_unittest.cc
+++ b/chrome/tools/convert_dict/convert_dict_unittest.cc
@@ -130,8 +130,8 @@
   // Deletes the temporary files.
   // We need to delete them after the above AffReader and DicReader are deleted
   // since they close the input files in their destructors.
-  file_util::Delete(aff_file, false);
-  file_util::Delete(dic_file, false);
+  base::Delete(aff_file, false);
+  base::Delete(dic_file, false);
 }
 
 }  // namespace
diff --git a/chrome/tools/crash_service/crash_service.cc b/chrome/tools/crash_service/crash_service.cc
index a4b5050..63a674b 100644
--- a/chrome/tools/crash_service/crash_service.cc
+++ b/chrome/tools/crash_service/crash_service.cc
@@ -20,7 +20,6 @@
 #include "breakpad/src/client/windows/sender/crash_report_sender.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_paths.h"
-#include "components/breakpad/common/breakpad_paths.h"
 
 namespace {
 
@@ -198,7 +197,7 @@
   if (cmd_line.HasSwitch(kDumpsDir)) {
     dumps_path = base::FilePath(cmd_line.GetSwitchValueNative(kDumpsDir));
   } else {
-    if (!PathService::Get(breakpad::DIR_CRASH_DUMPS, &dumps_path)) {
+    if (!PathService::Get(chrome::DIR_CRASH_DUMPS, &dumps_path)) {
       LOG(ERROR) << "could not get DIR_CRASH_DUMPS";
       return false;
     }
@@ -373,7 +372,7 @@
     file_util::CreateDirectoryW(alternate_dump_location);
     alternate_dump_location = alternate_dump_location.Append(
         dump_location.BaseName());
-    file_util::Move(dump_location, alternate_dump_location);
+    base::Move(dump_location, alternate_dump_location);
     dump_location = alternate_dump_location;
   }
 
diff --git a/chrome/tools/crash_service/main.cc b/chrome/tools/crash_service/main.cc
index 525801d..de4b37a 100644
--- a/chrome/tools/crash_service/main.cc
+++ b/chrome/tools/crash_service/main.cc
@@ -46,12 +46,10 @@
 
   // Logging to stderr (to help with debugging failures on the
   // buildbots) and to a file.
-  logging::InitLogging(
-      log_file.value().c_str(),
-      logging::LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG,
-      logging::LOCK_LOG_FILE,
-      logging::APPEND_TO_OLD_LOG_FILE,
-      logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS);
+  logging::LoggingSettings settings;
+  settings.logging_dest = logging::LOG_TO_ALL;
+  settings.log_file = log_file.value().c_str();
+  logging::InitLogging(settings);
   // Logging with pid, tid and timestamp.
   logging::SetLogItems(true, true, true, false);
 
diff --git a/chrome/tools/ipclist/ipcfuzz.cc b/chrome/tools/ipclist/ipcfuzz.cc
index 1dcf06a..59acf4f 100644
--- a/chrome/tools/ipclist/ipcfuzz.cc
+++ b/chrome/tools/ipclist/ipcfuzz.cc
@@ -18,7 +18,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "chrome/common/all_messages.h"
 #include "content/common/all_messages.h"
 #include "ipc/ipc_message.h"
diff --git a/chrome/tools/service_discovery_sniffer/service_discovery_sniffer.cc b/chrome/tools/service_discovery_sniffer/service_discovery_sniffer.cc
new file mode 100644
index 0000000..bf416b2
--- /dev/null
+++ b/chrome/tools/service_discovery_sniffer/service_discovery_sniffer.cc
@@ -0,0 +1,122 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <vector>
+
+#include "base/at_exit.h"
+#include "base/bind.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop.h"
+#include "chrome/browser/local_discovery/service_discovery_client_impl.h"
+#include "chrome/tools/service_discovery_sniffer/service_discovery_sniffer.h"
+#include "net/dns/mdns_client.h"
+
+namespace local_discovery {
+
+ServicePrinter::ServicePrinter(ServiceDiscoveryClient* client,
+                               const std::string& service_name)
+    : changed_(false) {
+  service_resolver_ =
+      client->CreateServiceResolver(
+          service_name,
+          base::Bind(&ServicePrinter::OnServiceResolved,
+                     base::Unretained(this)));
+}
+
+ServicePrinter::~ServicePrinter() {
+}
+
+void ServicePrinter::Added() {
+  changed_ = false;
+  service_resolver_->StartResolving();
+}
+
+void ServicePrinter::Changed() {
+  changed_ = true;
+  service_resolver_->StartResolving();
+}
+
+void ServicePrinter::Removed() {
+  printf("Service Removed: %s\n",
+         service_resolver_->GetServiceDescription().instance_name().c_str());
+}
+
+void ServicePrinter::OnServiceResolved(ServiceResolver::RequestStatus status,
+                                       const ServiceDescription& service) {
+  if (changed_) {
+    printf("Service Updated: %s\n", service.instance_name().c_str());
+  } else {
+    printf("Service Added: %s\n", service.instance_name().c_str());
+  }
+
+  printf("\tAddress: %s:%d\n", service.address.host().c_str(),
+         service.address.port());
+  printf("\tMetadata: \n");
+  for (std::vector<std::string>::const_iterator i = service.metadata.begin();
+       i != service.metadata.end(); i++) {
+    printf("\t\t%s\n", i->c_str());
+  }
+
+  if (service.ip_address != net::IPAddressNumber()) {
+    printf("\tIP Address: %s\n", net::IPAddressToString(
+        service.ip_address).c_str());
+  }
+}
+
+ServiceTypePrinter::ServiceTypePrinter(ServiceDiscoveryClient* client,
+                                       const std::string& service_type)
+    : client_(client)  {
+  watcher_ = client_->CreateServiceWatcher(service_type, this);
+}
+
+bool ServiceTypePrinter::Start() {
+  if (!watcher_->Start()) return false;
+  watcher_->DiscoverNewServices(false);
+  watcher_->ReadCachedServices();
+  return true;
+}
+
+ServiceTypePrinter::~ServiceTypePrinter() {
+}
+
+void ServiceTypePrinter::OnServiceUpdated(ServiceWatcher::UpdateType update,
+                                          const std::string& service_name) {
+  if (update == ServiceWatcher::UPDATE_ADDED) {
+    services_[service_name].reset(new ServicePrinter(client_, service_name));
+    services_[service_name]->Added();
+  } else if (update == ServiceWatcher::UPDATE_CHANGED) {
+    services_[service_name]->Changed();
+  } else if (update == ServiceWatcher::UPDATE_REMOVED) {
+    services_[service_name]->Removed();
+    services_.erase(service_name);
+  }
+}
+
+}  // namespace local_discovery
+
+int main(int argc, char** argv) {
+  base::AtExitManager at_exit_manager;
+  base::MessageLoopForIO message_loop;
+
+  if (argc != 2) {
+    printf("Please provide exactly 1 argument.\n");
+    return 1;
+  }
+
+  scoped_ptr<net::MDnsClient> mdns_client = net::MDnsClient::CreateDefault();
+  mdns_client->StartListening();
+  scoped_ptr<local_discovery::ServiceDiscoveryClient> service_discovery_client;
+  service_discovery_client.reset(
+      new local_discovery::ServiceDiscoveryClientImpl(mdns_client.get()));
+  {
+    // To guarantee/make explicit the ordering constraint.
+    local_discovery::ServiceTypePrinter print_changes(
+        service_discovery_client.get(),
+        std::string(argv[1]) + "._tcp.local");
+
+    if (!print_changes.Start())
+      printf("Could not start the DNS-SD client\n");
+    message_loop.Run();
+  }
+}
diff --git a/chrome/tools/service_discovery_sniffer/service_discovery_sniffer.h b/chrome/tools/service_discovery_sniffer/service_discovery_sniffer.h
new file mode 100644
index 0000000..12f8793
--- /dev/null
+++ b/chrome/tools/service_discovery_sniffer/service_discovery_sniffer.h
@@ -0,0 +1,62 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_TOOLS_SERVICE_DISCOVERY_SNIFFER_SERVICE_DISCOVERY_SNIFFER_H_
+#define CHROME_TOOLS_SERVICE_DISCOVERY_SNIFFER_SERVICE_DISCOVERY_SNIFFER_H_
+
+#include <map>
+#include <string>
+
+#include "base/memory/linked_ptr.h"
+#include "chrome/browser/local_discovery/service_discovery_client.h"
+
+namespace local_discovery {
+
+// Resolves a service and prints out information regarding it to the
+// console. |client| must outlive the ServicePrinter.
+class ServicePrinter {
+ public:
+  ServicePrinter(ServiceDiscoveryClient* client,
+                 const std::string& service_name);
+  ~ServicePrinter();
+
+  void Added();
+  void Changed();
+  void Removed();
+
+ private:
+  void OnServiceResolved(ServiceResolver::RequestStatus status,
+                         const ServiceDescription& service);
+
+  bool changed_;
+  scoped_ptr<ServiceResolver> service_resolver_;
+
+  DISALLOW_COPY_AND_ASSIGN(ServicePrinter);
+};
+
+// Monitors a service type and prints information regarding all services on it
+// to the console. |client| must outlive the ServiceTypePrinter.
+class ServiceTypePrinter : public ServiceWatcher::Delegate {
+ public:
+  ServiceTypePrinter(ServiceDiscoveryClient* client,
+                     const std::string& service_type);
+  virtual ~ServiceTypePrinter();
+
+  bool Start();
+  virtual void OnServiceUpdated(ServiceWatcher::UpdateType,
+                                const std::string& service_name) OVERRIDE;
+
+ private:
+  typedef std::map<std::string, linked_ptr<ServicePrinter> > ServiceMap;
+
+  ServiceMap services_;
+  scoped_ptr<ServiceWatcher> watcher_;
+  ServiceDiscoveryClient* client_;
+
+  DISALLOW_COPY_AND_ASSIGN(ServiceTypePrinter);
+};
+
+}  // namespace local_discovery
+
+#endif  // CHROME_TOOLS_SERVICE_DISCOVERY_SNIFFER_SERVICE_DISCOVERY_SNIFFER_H_
diff --git a/chrome/unit_tests.isolate b/chrome/unit_tests.isolate
index 7bf9a51..82afe34 100644
--- a/chrome/unit_tests.isolate
+++ b/chrome/unit_tests.isolate
@@ -36,6 +36,7 @@
         ],
         'isolate_dependency_untracked': [
           '../base/test/data/',
+          '../components/test/data/',
           '../extensions/test/data/',
           '../net/data/',
           '../net/tools/testserver/',
@@ -78,6 +79,7 @@
           '<(PRODUCT_DIR)/unit_tests<(EXECUTABLE_SUFFIX)',
         ],
         'isolate_dependency_untracked': [
+          '<(PRODUCT_DIR)/test_data/chrome/browser/resources/google_now/',
           '<(PRODUCT_DIR)/test_data/chrome/browser/resources/print_preview/',
           '<(PRODUCT_DIR)/test_data/chrome/test/data/unit/',
           '<(PRODUCT_DIR)/test_data/ui/',
diff --git a/chrome/utility/DEPS b/chrome/utility/DEPS
index 7cc58fd..8fa5799 100644
--- a/chrome/utility/DEPS
+++ b/chrome/utility/DEPS
@@ -2,6 +2,7 @@
   # For out of process profile import. This code needs to be factored out to
   # chrome/common.
   "+chrome/browser/importer",
+  "+content/public/child",
   "+content/public/utility",
   "+webkit/glue",
 ]
diff --git a/chrome/utility/chrome_content_utility_client.cc b/chrome/utility/chrome_content_utility_client.cc
index e20bd50..132cbed 100644
--- a/chrome/utility/chrome_content_utility_client.cc
+++ b/chrome/utility/chrome_content_utility_client.cc
@@ -20,6 +20,7 @@
 #include "chrome/common/safe_browsing/zip_analyzer.h"
 #include "chrome/common/web_resource/web_resource_unpacker.h"
 #include "chrome/utility/profile_import_handler.h"
+#include "content/public/child/image_decoder_utils.h"
 #include "content/public/utility/utility_thread.h"
 #include "printing/page_range.h"
 #include "third_party/skia/include/core/SkBitmap.h"
@@ -27,7 +28,7 @@
 #include "ui/base/ui_base_switches.h"
 #include "ui/gfx/codec/jpeg_codec.h"
 #include "ui/gfx/rect.h"
-#include "webkit/glue/image_decoder.h"
+#include "ui/gfx/size.h"
 
 #if defined(OS_WIN)
 #include "base/file_util.h"
@@ -35,10 +36,15 @@
 #include "base/win/iat_patch_function.h"
 #include "base/win/scoped_handle.h"
 #include "chrome/common/chrome_paths.h"
+#include "chrome/utility/itunes_pref_parser_win.h"
 #include "printing/emf_win.h"
 #include "ui/gfx/gdi_util.h"
 #endif  // defined(OS_WIN)
 
+#if defined(OS_WIN) || defined(OS_MACOSX)
+#include "chrome/utility/itunes_library_parser.h"
+#endif  // defined(OS_WIN) || defined(OS_MACOSX)
+
 #if defined(ENABLE_PRINTING)
 #include "chrome/common/child_process_logging.h"
 #include "printing/backend/print_backend.h"
@@ -111,6 +117,16 @@
     IPC_MESSAGE_HANDLER(ChromeUtilityMsg_CreateZipFile, OnCreateZipFile)
 #endif  // defined(OS_CHROMEOS)
 
+#if defined(OS_WIN)
+    IPC_MESSAGE_HANDLER(ChromeUtilityMsg_ParseITunesPrefXml,
+                        OnParseITunesPrefXml)
+#endif  // defined(OS_WIN)
+
+#if defined(OS_WIN) || defined(OS_MACOSX)
+    IPC_MESSAGE_HANDLER(ChromeUtilityMsg_ParseITunesLibraryXmlFile,
+                        OnParseITunesLibraryXmlFile)
+#endif  // defined(OS_WIN) || defined(OS_MACOSX)
+
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
 
@@ -127,8 +143,8 @@
     const std::string& extension_id,
     int location,
     int creation_flags) {
-  CHECK(location > extensions::Manifest::INVALID_LOCATION);
-  CHECK(location < extensions::Manifest::NUM_LOCATIONS);
+  CHECK_GT(location, extensions::Manifest::INVALID_LOCATION);
+  CHECK_LT(location, extensions::Manifest::NUM_LOCATIONS);
   extensions::PermissionsInfo::GetInstance()->InitializeWithDelegate(
       extensions::ChromeAPIPermissions());
   extensions::RegisterChromeManifestHandlers();
@@ -180,9 +196,9 @@
 
 void ChromeContentUtilityClient::OnDecodeImage(
     const std::vector<unsigned char>& encoded_data) {
-  webkit_glue::ImageDecoder decoder;
-  const SkBitmap& decoded_image = decoder.Decode(&encoded_data[0],
-                                                 encoded_data.size());
+  const SkBitmap& decoded_image = content::DecodeImage(&encoded_data[0],
+                                                       gfx::Size(),
+                                                       encoded_data.size());
   if (decoded_image.empty()) {
     Send(new ChromeUtilityHostMsg_DecodeImage_Failed());
   } else {
@@ -430,10 +446,10 @@
 void ChromeContentUtilityClient::OnParseJSON(const std::string& json) {
   int error_code;
   std::string error;
-  Value* value = base::JSONReader::ReadAndReturnError(
+  base::Value* value = base::JSONReader::ReadAndReturnError(
       json, base::JSON_PARSE_RFC, &error_code, &error);
   if (value) {
-    ListValue wrapper;
+    base::ListValue wrapper;
     wrapper.Append(value);
     Send(new ChromeUtilityHostMsg_ParseJSON_Succeeded(wrapper));
   } else {
@@ -479,4 +495,27 @@
   ReleaseProcessIfNeeded();
 }
 
+#if defined(OS_WIN)
+void ChromeContentUtilityClient::OnParseITunesPrefXml(
+    const std::string& itunes_xml_data) {
+  base::FilePath library_path(
+      itunes::FindLibraryLocationInPrefXml(itunes_xml_data));
+  Send(new ChromeUtilityHostMsg_GotITunesDirectory(library_path));
+  ReleaseProcessIfNeeded();
+}
+#endif  // defined(OS_WIN)
+
+#if defined(OS_WIN) || defined(OS_MACOSX)
+void ChromeContentUtilityClient::OnParseITunesLibraryXmlFile(
+    IPC::PlatformFileForTransit itunes_library_file) {
+  itunes::ITunesLibraryParser parser;
+  base::PlatformFile file =
+      IPC::PlatformFileForTransitToPlatformFile(itunes_library_file);
+  bool result = parser.Parse(
+      itunes::ITunesLibraryParser::ReadITunesLibraryXmlFile(file));
+  Send(new ChromeUtilityHostMsg_GotITunesLibrary(result, parser.library()));
+  ReleaseProcessIfNeeded();
+}
+#endif  // defined(OS_WIN) || defined(OS_MACOSX)
+
 }  // namespace chrome
diff --git a/chrome/utility/chrome_content_utility_client.h b/chrome/utility/chrome_content_utility_client.h
index e814940..3f8afe3 100644
--- a/chrome/utility/chrome_content_utility_client.h
+++ b/chrome/utility/chrome_content_utility_client.h
@@ -80,6 +80,15 @@
   void OnAnalyzeZipFileForDownloadProtection(
       IPC::PlatformFileForTransit zip_file);
 
+#if defined(OS_WIN)
+  void OnParseITunesPrefXml(const std::string& itunes_xml_data);
+#endif  // defined(OS_WIN)
+
+#if defined(OS_WIN) || defined(OS_MACOSX)
+  void OnParseITunesLibraryXmlFile(
+      IPC::PlatformFileForTransit itunes_library_file);
+#endif  // defined(OS_WIN) || defined(OS_MACOSX)
+
   scoped_ptr<ProfileImportHandler> import_handler_;
 
   DISALLOW_COPY_AND_ASSIGN(ChromeContentUtilityClient);
diff --git a/chrome/utility/itunes_library_parser.cc b/chrome/utility/itunes_library_parser.cc
new file mode 100644
index 0000000..e714bd5
--- /dev/null
+++ b/chrome/utility/itunes_library_parser.cc
@@ -0,0 +1,227 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/utility/itunes_library_parser.h"
+
+#include <string>
+
+#include "base/logging.h"
+#include "base/stl_util.h"
+#include "base/strings/string16.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/common/itunes_xml_utils.h"
+#include "googleurl/src/gurl.h"
+#include "googleurl/src/url_canon.h"
+#include "googleurl/src/url_util.h"
+#include "third_party/libxml/chromium/libxml_utils.h"
+
+namespace itunes {
+
+namespace {
+
+struct TrackInfo {
+  uint64 id;
+  base::FilePath location;
+  std::string artist;
+  std::string album;
+};
+
+// Seek to the start of a tag and read the value into |result| if the node's
+// name is |node_name|.
+bool ReadSimpleValue(XmlReader* reader, const std::string& node_name,
+                     std::string* result) {
+  if (!SkipToNextElement(reader))
+      return false;
+  if (reader->NodeName() != node_name)
+    return false;
+  return reader->ReadElementContent(result);
+}
+
+// Get the value out of a string node.
+bool ReadString(XmlReader* reader, std::string* result) {
+  return ReadSimpleValue(reader, "string", result);
+}
+
+// Get the value out of an integer node.
+bool ReadInteger(XmlReader* reader, uint64* result) {
+  std::string value;
+  if (!ReadSimpleValue(reader, "integer", &value))
+    return false;
+  return base::StringToUint64(value, result);
+}
+
+// Walk through a dictionary filling in |result| with track information. Return
+// true if it was all found, false otherwise.  In either case, the cursor is
+// advanced out of the dictionary.
+bool GetTrackInfoFromDict(XmlReader* reader, TrackInfo* result) {
+  DCHECK(result);
+  if (reader->NodeName() != "dict")
+    return false;
+
+  int dict_content_depth = reader->Depth() + 1;
+  // Advance past the dict node and into the body of the dictionary.
+  if (!reader->Read())
+    return false;
+
+  bool found_id = false;
+  bool found_location = false;
+  bool found_artist = false;
+  bool found_album = false;
+  while (reader->Depth() >= dict_content_depth &&
+         !(found_id && found_location && found_artist && found_album)) {
+    if (!SeekToNodeAtCurrentDepth(reader, "key"))
+      break;
+    std::string found_key;
+    if (!reader->ReadElementContent(&found_key))
+      break;
+    DCHECK_EQ(dict_content_depth, reader->Depth());
+
+    if (found_key == "Track ID") {
+      if (found_id)
+        break;
+      if (!ReadInteger(reader, &result->id))
+        break;
+      found_id = true;
+    } else if (found_key == "Location") {
+      if (found_location)
+        break;
+      std::string value;
+      if (!ReadString(reader, &value))
+        break;
+      GURL url(value);
+      if (!url.SchemeIsFile())
+        break;
+      url_canon::RawCanonOutputW<1024> decoded_location;
+      url_util::DecodeURLEscapeSequences(url.path().c_str() + 1,  // Strip /.
+                                         url.path().length() - 1,
+                                         &decoded_location);
+#if defined(OS_WIN)
+      string16 location(decoded_location.data(), decoded_location.length());
+#else
+      string16 location16(decoded_location.data(), decoded_location.length());
+      std::string location = UTF16ToUTF8(location16);
+#endif
+      result->location = base::FilePath(location);
+      found_location = true;
+    } else if (found_key == "Album Artist") {
+      if (found_artist)
+        break;
+      if (!ReadString(reader, &result->artist))
+        break;
+      found_artist = true;
+    } else if (found_key == "Album") {
+      if (found_album)
+        break;
+      if (!ReadString(reader, &result->album))
+        break;
+      found_album = true;
+    } else {
+      if (!SkipToNextElement(reader))
+        break;
+      if (!reader->Next())
+        break;
+    }
+  }
+
+  // Seek to the end of the dictionary
+  while (reader->Depth() >= dict_content_depth)
+    reader->Next();
+
+  return found_id && found_location && found_artist && found_album;
+}
+
+}  // namespace
+
+ITunesLibraryParser::ITunesLibraryParser() {}
+ITunesLibraryParser::~ITunesLibraryParser() {}
+
+// static
+std::string ITunesLibraryParser::ReadITunesLibraryXmlFile(
+    const base::PlatformFile file) {
+  std::string result;
+  if (file == base::kInvalidPlatformFileValue)
+    return result;
+
+  // A "reasonable" artificial limit.
+  // TODO(vandebo): Add a UMA to figure out what common values are.
+  const int64 kMaxLibraryFileSize = 150 * 1024 * 1024;
+  base::PlatformFileInfo file_info;
+  if (!base::GetPlatformFileInfo(file, &file_info) ||
+      file_info.size > kMaxLibraryFileSize) {
+    base::ClosePlatformFile(file);
+    return result;
+  }
+
+  result.resize(file_info.size);
+  int bytes_read =
+      base::ReadPlatformFile(file, 0, string_as_array(&result), file_info.size);
+  if (bytes_read != file_info.size)
+    result.clear();
+
+  base::ClosePlatformFile(file);
+  return result;
+}
+
+bool ITunesLibraryParser::Parse(const std::string& library_xml) {
+  XmlReader reader;
+
+  if (!reader.Load(library_xml))
+    return false;
+
+  // Find the plist node and then search within that tag.
+  if (!SeekToNodeAtCurrentDepth(&reader, "plist"))
+    return false;
+  if (!reader.Read())
+    return false;
+
+  if (!SeekToNodeAtCurrentDepth(&reader, "dict"))
+    return false;
+
+  if (!SeekInDict(&reader, "Tracks"))
+    return false;
+
+  // Once inside the Tracks dict, we expect track dictionaries keyed by id. i.e.
+  //   <key>Tracks</key>
+  //   <dict>
+  //     <key>160</key>
+  //     <dict>
+  //       <key>Track ID</key><integer>160</integer>
+  if (!SeekToNodeAtCurrentDepth(&reader, "dict"))
+    return false;
+  int tracks_dict_depth = reader.Depth() + 1;
+  if (!reader.Read())
+    return false;
+
+  // Once parsing has gotten this far, return whatever is found, even if
+  // some of the data isn't extracted just right.
+  bool no_errors = true;
+  bool track_found = false;
+  while (reader.Depth() >= tracks_dict_depth) {
+    if (!SeekToNodeAtCurrentDepth(&reader, "key"))
+      return track_found;
+    std::string key;  // Should match track id below.
+    if (!reader.ReadElementContent(&key))
+      return track_found;
+    uint64 id;
+    bool id_valid = base::StringToUint64(key, &id);
+    if (!reader.SkipToElement())
+      return track_found;
+
+    TrackInfo track_info;
+    if (GetTrackInfoFromDict(&reader, &track_info) &&
+        id_valid &&
+        id == track_info.id) {
+      parser::Track track(track_info.id, track_info.location);
+      library_[track_info.artist][track_info.album].insert(track);
+      track_found = true;
+    } else {
+      no_errors = false;
+    }
+  }
+
+  return track_found || no_errors;
+}
+
+}  // namespace itunes
diff --git a/chrome/utility/itunes_library_parser.h b/chrome/utility/itunes_library_parser.h
new file mode 100644
index 0000000..377612f
--- /dev/null
+++ b/chrome/utility/itunes_library_parser.h
@@ -0,0 +1,37 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_UTILITY_ITUNES_LIBRARY_PARSER_H_
+#define CHROME_UTILITY_ITUNES_LIBRARY_PARSER_H_
+
+#include <string>
+
+#include "base/platform_file.h"
+#include "chrome/common/itunes_library.h"
+
+namespace itunes {
+
+class ITunesLibraryParser {
+ public:
+  ITunesLibraryParser();
+  ~ITunesLibraryParser();
+
+  // Returns the contents of the given iTunes library XML |file|.
+  static std::string ReadITunesLibraryXmlFile(const base::PlatformFile file);
+
+  // Returns true if at least one track was found. Malformed track entries
+  // are silently ignored.
+  bool Parse(const std::string& xml);
+
+  const parser::Library& library() { return library_; }
+
+ private:
+  parser::Library library_;
+
+  DISALLOW_COPY_AND_ASSIGN(ITunesLibraryParser);
+};
+
+}  // namespace itunes
+
+#endif  // CHROME_UTILITY_ITUNES_LIBRARY_PARSER_H_
diff --git a/chrome/utility/itunes_library_parser_unittest.cc b/chrome/utility/itunes_library_parser_unittest.cc
new file mode 100644
index 0000000..02cf8d7
--- /dev/null
+++ b/chrome/utility/itunes_library_parser_unittest.cc
@@ -0,0 +1,193 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/logging.h"
+#include "chrome/common/itunes_library.h"
+#include "chrome/utility/itunes_library_parser.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#define SIMPLE_HEADER()         \
+    "<plist>"                   \
+    "  <dict>"                  \
+    "    <key>Tracks</key>"     \
+    "    <dict>"
+
+#define SIMPLE_TRACK(key, id, path, artist, album)                     \
+    "<key>" #key "</key>"                                              \
+    "<dict>"                                                           \
+    "  <key>Track ID</key><integer>" #id "</integer>"                  \
+    "  <key>Location</key><string>file://localhost/" path "</string>"  \
+    "  <key>Album Artist</key><string>" artist "</string>"             \
+    "  <key>Album</key><string>" album "</string>"                     \
+    "</dict>"
+
+#define SIMPLE_FOOTER()  \
+    "    </dict>"        \
+    "  </dict>"          \
+    "</plist>"
+
+namespace itunes {
+
+namespace {
+
+void CompareTrack(const parser::Track& a, const parser::Track& b) {
+  EXPECT_EQ(a.id, b.id);
+  EXPECT_EQ(a.location, b.location);
+}
+
+void CompareAlbum(const parser::Album& a, const parser::Album& b) {
+  EXPECT_EQ(a.size(), b.size());
+
+  parser::Album::const_iterator a_it;
+  parser::Album::const_iterator b_it;
+  for (a_it = a.begin(), b_it = b.begin();
+       a_it != a.end() && b_it != b.end();
+       ++a_it, ++b_it) {
+    CompareTrack(*a_it, *b_it);
+  }
+}
+
+void CompareAlbums(const parser::Albums& a, const parser::Albums& b) {
+  EXPECT_EQ(a.size(), b.size());
+
+  parser::Albums::const_iterator a_it;
+  parser::Albums::const_iterator b_it;
+  for (a_it = a.begin(), b_it = b.begin();
+       a_it != a.end() && b_it != b.end();
+       ++a_it, ++b_it) {
+    EXPECT_EQ(a_it->first, b_it->first);
+    CompareAlbum(a_it->second, b_it->second);
+  }
+}
+
+void CompareLibrary(const parser::Library& a, const parser::Library& b) {
+  EXPECT_EQ(a.size(), b.size());
+
+  parser::Library::const_iterator a_it;
+  parser::Library::const_iterator b_it;
+  for (a_it = a.begin(), b_it = b.begin();
+       a_it != a.end() && b_it != b.end();
+       ++a_it, ++b_it) {
+    EXPECT_EQ(a_it->first, b_it->first);
+    CompareAlbums(a_it->second, b_it->second);
+  }
+}
+
+class ITunesLibraryParserTest : public testing::Test {
+ public:
+  ITunesLibraryParserTest() {}
+
+  void TestParser(bool expected_result, const std::string& xml) {
+    ITunesLibraryParser parser;
+
+    EXPECT_EQ(expected_result, parser.Parse(xml));
+    if (!expected_result)
+      return;
+
+    CompareLibrary(expected_library_, parser.library());
+  }
+
+  void AddExpectedTrack(uint32 id, const std::string& location,
+                        const std::string& artist, const std::string& album) {
+    parser::Track track(id, base::FilePath::FromUTF8Unsafe(location));
+    expected_library_[artist][album].insert(track);
+  }
+
+ private:
+  parser::Library expected_library_;
+
+  DISALLOW_COPY_AND_ASSIGN(ITunesLibraryParserTest);
+};
+
+TEST_F(ITunesLibraryParserTest, EmptyLibrary) {
+  TestParser(false, "");
+}
+
+TEST_F(ITunesLibraryParserTest, MinimalXML) {
+  AddExpectedTrack(1, "C:/dir/Song With Space.mp3", "Artist A", "Album A");
+  TestParser(
+      true,
+      SIMPLE_HEADER()
+      SIMPLE_TRACK(1, 1, "C:/dir/Song%20With%20Space.mp3", "Artist A",
+                   "Album A")
+      SIMPLE_FOOTER());
+}
+
+TEST_F(ITunesLibraryParserTest, MultipleSongs) {
+  AddExpectedTrack(1, "C:/dir/SongA1.mp3", "Artist A", "Album A");
+  AddExpectedTrack(2, "C:/dir/SongA2.mp3", "Artist A", "Album A");
+  AddExpectedTrack(3, "C:/dir/SongA3.mp3", "Artist A", "Album A");
+  AddExpectedTrack(4, "C:/dir/SongB1.mp3", "Artist A", "Album B");
+  AddExpectedTrack(5, "C:/dir/SongB2.mp3", "Artist A", "Album B");
+  AddExpectedTrack(6, "C:/dir2/SongB1.mp3", "Artist B", "Album B");
+  AddExpectedTrack(7, "C:/dir2/SongB2.mp3", "Artist B", "Album B");
+  TestParser(
+      true,
+      SIMPLE_HEADER()
+      SIMPLE_TRACK(1, 1, "C:/dir/SongA1.mp3", "Artist A", "Album A")
+      SIMPLE_TRACK(2, 2, "C:/dir/SongA2.mp3", "Artist A", "Album A")
+      SIMPLE_TRACK(3, 3, "C:/dir/SongA3.mp3", "Artist A", "Album A")
+      SIMPLE_TRACK(4, 4, "C:/dir/SongB1.mp3", "Artist A", "Album B")
+      SIMPLE_TRACK(5, 5, "C:/dir/SongB2.mp3", "Artist A", "Album B")
+      SIMPLE_TRACK(6, 6, "C:/dir2/SongB1.mp3", "Artist B", "Album B")
+      SIMPLE_TRACK(7, 7, "C:/dir2/SongB2.mp3", "Artist B", "Album B")
+      SIMPLE_FOOTER());
+}
+
+TEST_F(ITunesLibraryParserTest, MismatchedId) {
+  TestParser(
+      false,
+      SIMPLE_HEADER()
+      SIMPLE_TRACK(1, 2, "C:/dir/SongA1.mp3", "Artist A", "Album A")
+      SIMPLE_FOOTER());
+
+  AddExpectedTrack(1, "C:/dir/SongA1.mp3", "Artist A", "Album A");
+  TestParser(
+      true,
+      SIMPLE_HEADER()
+      SIMPLE_TRACK(1, 1, "C:/dir/SongA1.mp3", "Artist A", "Album A")
+      SIMPLE_TRACK(2, 3, "C:/dir/SongA2.mp3", "Artist A", "Album A")
+      SIMPLE_FOOTER());
+}
+
+TEST_F(ITunesLibraryParserTest, OtherDictionaryEntries) {
+  AddExpectedTrack(1, "C:/dir/SongA1.mp3", "Artist A", "Album A");
+  TestParser(
+      true,
+      "<plist>"
+      "  <dict>"
+      "    <key>Other section</key>"
+      "    <dict>"
+      // In Other section, not Tracks.
+      SIMPLE_TRACK(10, 10, "C:/dir/SongB2.mp3", "Artist B", "Album B")
+      "    </dict>"
+      "    <key>Tracks</key>"
+      "    <dict>"
+      "      <key>1</key>"
+      "      <dict>"
+      // In the body of a track dictionary before the interesting entries.
+      SIMPLE_TRACK(20, 20, "C:/dir/SongB2.mp3", "Artist B", "Album B")
+      // Entries in a different order.
+      "        <key>Album Artist</key><string>Artist A</string>"
+      "        <key>Location</key>"
+      "          <string>file://localhost/C:/dir/SongA1.mp3</string>"
+      "        <key>Album</key><string>Album A</string>"
+      "        <key>Track ID</key><integer>1</integer>"
+      // In the body of a track dictionary after the interesting entries.
+      SIMPLE_TRACK(30, 30, "C:/dir/SongB3.mp3", "Artist B", "Album B")
+      "      </dict>"
+      "      <key>40</key>"
+      "      <dict>"
+      // Missing album name.
+      "        <key>Album Artist</key><string>Artist B</string>"
+      "        <key>Location</key>"
+      "          <string>file://localhost/C:/dir/SongB4.mp3</string>"
+      "        <key>Track ID</key><integer>1</integer>"
+      "      </dict>"
+      SIMPLE_FOOTER());
+}
+
+}  // namespace
+
+}  // namespace itunes
diff --git a/chrome/utility/itunes_pref_parser_win.cc b/chrome/utility/itunes_pref_parser_win.cc
new file mode 100644
index 0000000..b4f0a2a
--- /dev/null
+++ b/chrome/utility/itunes_pref_parser_win.cc
@@ -0,0 +1,55 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/utility/itunes_pref_parser_win.h"
+
+#include "base/base64.h"
+#include "base/strings/string_util.h"
+#include "chrome/common/itunes_xml_utils.h"
+#include "third_party/libxml/chromium/libxml_utils.h"
+
+namespace itunes {
+
+base::FilePath::StringType FindLibraryLocationInPrefXml(
+    const std::string& pref_xml_data) {
+  XmlReader reader;
+  base::FilePath::StringType result;
+
+  if (!reader.Load(pref_xml_data))
+    return result;
+
+  // Find the plist node and then search within that tag.
+  if (!SeekToNodeAtCurrentDepth(&reader, "plist"))
+    return result;
+  if (!reader.Read())
+    return result;
+
+  if (!SeekToNodeAtCurrentDepth(&reader, "dict"))
+    return result;
+
+  if (!SeekInDict(&reader, "User Preferences"))
+    return result;
+
+  if (!SeekToNodeAtCurrentDepth(&reader, "dict"))
+    return result;
+
+  if (!SeekInDict(&reader, "iTunes Library XML Location:1"))
+    return result;
+
+  if (!SeekToNodeAtCurrentDepth(&reader, "data"))
+    return result;
+
+  std::string pref_value;
+  if (!reader.ReadElementContent(&pref_value))
+    return result;
+  // The data is a base64 encoded wchar_t*. Because Base64Decode uses
+  // std::strings, the result has to be casted to a wchar_t*.
+  std::string data;
+  if (!base::Base64Decode(CollapseWhitespaceASCII(pref_value, true), &data))
+    return result;
+  return base::FilePath::StringType(
+      reinterpret_cast<const wchar_t*>(data.data()), data.size() / 2);
+}
+
+}  // namespace itunes
diff --git a/chrome/utility/itunes_pref_parser_win.h b/chrome/utility/itunes_pref_parser_win.h
new file mode 100644
index 0000000..fc2371f
--- /dev/null
+++ b/chrome/utility/itunes_pref_parser_win.h
@@ -0,0 +1,33 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_UTILITY_ITUNES_PREF_PARSER_WIN_H_
+#define CHROME_UTILITY_ITUNES_PREF_PARSER_WIN_H_
+
+#include <string>
+
+#include "base/files/file_path.h"
+
+namespace itunes {
+
+// Extracts the library XML location from the iTunes preferences XML data.
+// Return the path the the library XML location if found. The minimal
+// valid snippet of XML is:
+//
+//   <plist>
+//     <dict>
+//       <key>User Preferences</key>
+//       <dict>
+//         <key>iTunes Library XML Location:1</key>
+//         <data>Base64 encoded w string path</data>
+//       </dict>
+//     </dict>
+//   </plist>
+//
+base::FilePath::StringType FindLibraryLocationInPrefXml(
+    const std::string& pref_xml_data);
+
+}  // namespace itunes
+
+#endif  // CHROME_UTILITY_ITUNES_PREF_PARSER_WIN_H_
diff --git a/chrome/utility/media_galleries/OWNERS b/chrome/utility/media_galleries/OWNERS
new file mode 100644
index 0000000..f441493
--- /dev/null
+++ b/chrome/utility/media_galleries/OWNERS
@@ -0,0 +1,4 @@
+estade@chromium.org
+gbillock@chromium.org
+thestig@chromium.org
+vandebo@chromium.org
diff --git a/chrome/utility/media_galleries/picasa_album_table_reader.cc b/chrome/utility/media_galleries/picasa_album_table_reader.cc
new file mode 100644
index 0000000..ac5fc67
--- /dev/null
+++ b/chrome/utility/media_galleries/picasa_album_table_reader.cc
@@ -0,0 +1,124 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/utility/media_galleries/picasa_album_table_reader.h"
+
+#include <algorithm>
+#include <string>
+
+#include "base/path_service.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/common/media_galleries/pmp_constants.h"
+#include "chrome/utility/media_galleries/pmp_column_reader.h"
+
+namespace picasa {
+
+namespace {
+
+// |variant_time| is specified as the number of days from Dec 30, 1899.
+base::Time TimeFromMicrosoftVariantTime(double variant_time) {
+  base::TimeDelta variant_delta = base::TimeDelta::FromMicroseconds(
+      static_cast<int64>(variant_time * base::Time::kMicrosecondsPerDay));
+
+  return base::Time::FromLocalExploded(kPmpVariantTimeEpoch) + variant_delta;
+}
+
+}  // namespace
+
+PicasaAlbumTableReader::PicasaAlbumTableReader(
+    const AlbumTableFiles& table_files)
+    : table_files_(table_files),
+      initialized_(false) {
+}
+
+PicasaAlbumTableReader::~PicasaAlbumTableReader() {}
+
+const std::vector<AlbumInfo>& PicasaAlbumTableReader::folders() const {
+  DCHECK(initialized_);
+  return folders_;
+}
+
+const std::vector<AlbumInfo>& PicasaAlbumTableReader::albums() const {
+  DCHECK(initialized_);
+  return albums_;
+}
+
+bool PicasaAlbumTableReader::Init() {
+  if (initialized_)
+    return true;
+
+  if (table_files_.indicator_file == base::kInvalidPlatformFileValue)
+    return false;
+
+  PmpColumnReader category_column, date_column, filename_column, name_column,
+                  token_column, uid_column;
+  if (!category_column.ReadFile(table_files_.category_file, PMP_TYPE_UINT32) ||
+      !date_column.ReadFile(table_files_.date_file, PMP_TYPE_DOUBLE64) ||
+      !filename_column.ReadFile(table_files_.filename_file, PMP_TYPE_STRING) ||
+      !name_column.ReadFile(table_files_.name_file, PMP_TYPE_STRING) ||
+      !token_column.ReadFile(table_files_.token_file, PMP_TYPE_STRING) ||
+      !uid_column.ReadFile(table_files_.uid_file, PMP_TYPE_STRING)) {
+    return false;
+  }
+
+  // In the PMP format, columns can be different lengths. The number of rows
+  // in the table is max of all the columns, and short columns are NULL padded.
+  uint32 row_count = 0;
+  row_count = std::max(row_count, category_column.rows_read());
+  row_count = std::max(row_count, date_column.rows_read());
+  row_count = std::max(row_count, filename_column.rows_read());
+  row_count = std::max(row_count, name_column.rows_read());
+  row_count = std::max(row_count, token_column.rows_read());
+  row_count = std::max(row_count, uid_column.rows_read());
+
+  for (uint32 i = 0; i < row_count; i++) {
+    uint32 category = kAlbumCategoryInvalid;
+    double date = 0;
+    std::string name;
+    std::string uid;
+    // PMP tables often contain 'garbage' rows of deleted or auto-generated
+    // album-like entities. We ignore those rows.
+    if (!category_column.ReadUInt32(i, &category) ||
+        !date_column.ReadDouble64(i, &date) ||
+        !name_column.ReadString(i, &name) || name.empty() ||
+        !uid_column.ReadString(i, &uid) || uid.empty()) {
+      continue;
+    }
+
+    base::Time timestamp = TimeFromMicrosoftVariantTime(date);
+
+    switch (category) {
+      case kAlbumCategoryAlbum: {
+        std::string token;
+        if (!token_column.ReadString(i, &token) || token.empty() ||
+            !StartsWithASCII(token, kAlbumTokenPrefix, false)) {
+          continue;
+        }
+
+        albums_.push_back(AlbumInfo(name, timestamp, uid, base::FilePath()));
+        break;
+      }
+      case kAlbumCategoryFolder: {
+        std::string filename;
+        if (!filename_column.ReadString(i, &filename) || filename.empty())
+          continue;
+
+        base::FilePath path =
+            base::FilePath(base::FilePath::FromUTF8Unsafe(filename));
+
+        folders_.push_back(AlbumInfo(name, timestamp, uid, path));
+        break;
+      }
+      default: {
+        break;
+      }
+    }
+  }
+
+  initialized_ = true;
+  return true;
+}
+
+}  // namespace picasa
diff --git a/chrome/utility/media_galleries/picasa_album_table_reader.h b/chrome/utility/media_galleries/picasa_album_table_reader.h
new file mode 100644
index 0000000..b71640d
--- /dev/null
+++ b/chrome/utility/media_galleries/picasa_album_table_reader.h
@@ -0,0 +1,44 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_UTILITY_MEDIA_GALLERIES_PICASA_ALBUM_TABLE_READER_H_
+#define CHROME_UTILITY_MEDIA_GALLERIES_PICASA_ALBUM_TABLE_READER_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "chrome/common/media_galleries/picasa_types.h"
+
+namespace picasa {
+
+const uint32 kAlbumCategoryAlbum     = 0;
+const uint32 kAlbumCategoryFolder    = 2;
+const uint32 kAlbumCategoryInvalid   = 0xffff;  // Sentinel value.
+
+const char kAlbumTokenPrefix[] = "]album:";
+
+class PicasaAlbumTableReader {
+ public:
+  explicit PicasaAlbumTableReader(const AlbumTableFiles& table_files);
+  ~PicasaAlbumTableReader();
+
+  bool Init();
+
+  const std::vector<AlbumInfo>& albums() const;
+  const std::vector<AlbumInfo>& folders() const;
+
+ private:
+  const AlbumTableFiles table_files_;
+
+  bool initialized_;
+
+  std::vector<AlbumInfo> albums_;
+  std::vector<AlbumInfo> folders_;
+
+  DISALLOW_COPY_AND_ASSIGN(PicasaAlbumTableReader);
+};
+
+}  // namespace picasa
+
+#endif  // CHROME_UTILITY_MEDIA_GALLERIES_PICASA_ALBUM_TABLE_READER_H_
diff --git a/chrome/utility/media_galleries/picasa_album_table_reader_unittest.cc b/chrome/utility/media_galleries/picasa_album_table_reader_unittest.cc
new file mode 100644
index 0000000..d9980b9
--- /dev/null
+++ b/chrome/utility/media_galleries/picasa_album_table_reader_unittest.cc
@@ -0,0 +1,117 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/common/media_galleries/pmp_constants.h"
+#include "chrome/utility/media_galleries/picasa_album_table_reader.h"
+#include "chrome/utility/media_galleries/pmp_test_helper.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace picasa {
+
+namespace {
+
+base::PlatformFile OpenPlatformFile(const base::FilePath& directory_path,
+                                    const std::string& suffix) {
+  base::FilePath path = directory_path.Append(base::FilePath::FromUTF8Unsafe(
+      std::string(kPicasaAlbumTableName) + "_" + suffix));
+  int flags = base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ;
+  return base::CreatePlatformFile(path, flags, NULL, NULL);
+}
+
+base::PlatformFile OpenColumnPlatformFile(const base::FilePath& directory_path,
+                                          const std::string& column_name) {
+  return OpenPlatformFile(directory_path, column_name + "." + kPmpExtension);
+}
+
+AlbumTableFiles MakeAlbumTableFiles(const base::FilePath& directory_path) {
+  AlbumTableFiles files;
+  files.indicator_file = OpenPlatformFile(directory_path, "0");
+  files.category_file  = OpenColumnPlatformFile(directory_path, "category");
+  files.date_file      = OpenColumnPlatformFile(directory_path, "date");
+  files.filename_file  = OpenColumnPlatformFile(directory_path, "filename");
+  files.name_file      = OpenColumnPlatformFile(directory_path, "name");
+  files.token_file     = OpenColumnPlatformFile(directory_path, "token");
+  files.uid_file       = OpenColumnPlatformFile(directory_path, "uid");
+}
+
+TEST(PicasaAlbumTableReaderTest, FoldersAndAlbums) {
+  PmpTestHelper test_helper(kPicasaAlbumTableName);
+  ASSERT_TRUE(test_helper.Init());
+
+  int test_time_delta = 100;
+
+  std::vector<uint32> category_vector;
+  category_vector.push_back(kAlbumCategoryFolder);
+  category_vector.push_back(kAlbumCategoryInvalid);
+  category_vector.push_back(kAlbumCategoryAlbum);
+
+  std::vector<double> date_vector;
+  date_vector.push_back(0.0);
+  date_vector.push_back(0.0);
+  date_vector.push_back(0.0 + test_time_delta);
+
+  std::string test_folder_name = "Pix4dalulz";
+  std::string test_album_name = "Cats";
+
+  base::FilePath test_folder_path =
+      base::FilePath(base::FilePath::FromUTF8Unsafe("C:\\Pix4dalulz"));
+
+  // Only folders require filenames. Tests handling of different length columns.
+  std::vector<std::string> filename_vector;
+  filename_vector.push_back(test_folder_path.AsUTF8Unsafe());
+
+  std::vector<std::string> name_vector;
+  name_vector.push_back(test_folder_name);
+  name_vector.push_back("");
+  name_vector.push_back(test_album_name);
+
+  std::vector<std::string> token_vector;
+  token_vector.push_back("");
+  token_vector.push_back("");
+  token_vector.push_back(std::string(kAlbumTokenPrefix) + "uid3");
+
+  std::vector<std::string> uid_vector;
+  uid_vector.push_back("uid1");
+  uid_vector.push_back("uid2");
+  uid_vector.push_back("uid3");
+
+  ASSERT_TRUE(test_helper.WriteColumnFileFromVector(
+      "category", PMP_TYPE_UINT32, category_vector));
+  ASSERT_TRUE(test_helper.WriteColumnFileFromVector(
+      "date", PMP_TYPE_DOUBLE64, date_vector));
+  ASSERT_TRUE(test_helper.WriteColumnFileFromVector(
+      "filename", PMP_TYPE_STRING, filename_vector));
+  ASSERT_TRUE(test_helper.WriteColumnFileFromVector(
+      "name", PMP_TYPE_STRING, name_vector));
+  ASSERT_TRUE(test_helper.WriteColumnFileFromVector(
+      "token", PMP_TYPE_STRING, token_vector));
+  ASSERT_TRUE(test_helper.WriteColumnFileFromVector(
+      "uid", PMP_TYPE_STRING, uid_vector));
+
+  AlbumTableFiles album_table_files =
+      MakeAlbumTableFiles(test_helper.GetTempDirPath());
+  PicasaAlbumTableReader reader(album_table_files);
+
+  ASSERT_TRUE(reader.Init());
+  CloseAlbumTableFiles(&album_table_files);
+
+  const std::vector<AlbumInfo>& albums = reader.albums();
+  const std::vector<AlbumInfo>& folders = reader.folders();
+
+  ASSERT_EQ(1u, albums.size());
+  ASSERT_EQ(1u, folders.size());
+
+  EXPECT_EQ(test_album_name, albums[0].name);
+  EXPECT_EQ(test_folder_name, folders[0].name);
+
+  EXPECT_EQ(test_folder_path, folders[0].path);
+
+  base::TimeDelta time_delta = albums[0].timestamp - folders[0].timestamp;
+
+  EXPECT_EQ(test_time_delta, time_delta.InDays());
+}
+
+}  // namespace
+
+}  // namespace picasa
diff --git a/chrome/utility/media_galleries/picasa_albums_indexer.cc b/chrome/utility/media_galleries/picasa_albums_indexer.cc
new file mode 100644
index 0000000..a512e4e
--- /dev/null
+++ b/chrome/utility/media_galleries/picasa_albums_indexer.cc
@@ -0,0 +1,79 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/utility/media_galleries/picasa_albums_indexer.h"
+
+#include <vector>
+
+#include "base/ini_parser.h"
+#include "base/logging.h"
+#include "base/strings/string_split.h"
+
+namespace picasa {
+
+namespace {
+
+const char kAlbumSectionHeader[] = ".album:";
+const char kAlbumsKey[] = "albums";
+
+class PicasaINIParser : public base::INIParser {
+ public:
+  PicasaINIParser(
+      const base::FilePath& folder_path, AlbumImagesMap* albums_images)
+      : folder_path_(folder_path),
+        albums_images_(albums_images) {
+  }
+  virtual ~PicasaINIParser() {}
+
+ private:
+  virtual void HandleTriplet(const std::string& section,
+                             const std::string& key,
+                             const std::string& value) OVERRIDE {
+    if (key != kAlbumsKey)
+      return;
+
+    // [.album:*] sections ignored as we get that data from the PMP files.
+    if (section.find(kAlbumSectionHeader) == 0)
+      return;
+
+    std::vector<std::string> containing_albums;
+    base::SplitString(value, ',', &containing_albums);
+    for (std::vector<std::string>::iterator it = containing_albums.begin();
+         it != containing_albums.end(); ++it) {
+      AlbumImagesMap::iterator album_map_it = albums_images_->find(*it);
+
+      // Ignore entry if the album UUID is not listed among in |album_uuids|
+      // in the constructor. Happens if the PMP and INI files are inconsistent.
+      if (album_map_it == albums_images_->end())
+        continue;
+
+      album_map_it->second.insert(
+          folder_path_.Append(base::FilePath::FromUTF8Unsafe(section)));
+    }
+  }
+
+  const base::FilePath folder_path_;
+  AlbumImagesMap* const albums_images_;
+};
+
+}  // namespace
+
+PicasaAlbumsIndexer::PicasaAlbumsIndexer(
+    const AlbumUUIDSet& album_uuids) {
+  // Create an entry in the map for the valid album uuids.
+  for (AlbumUUIDSet::const_iterator it = album_uuids.begin();
+       it != album_uuids.end(); ++it) {
+    albums_images_[*it] = AlbumImages();
+  }
+}
+
+PicasaAlbumsIndexer::~PicasaAlbumsIndexer() {}
+
+void PicasaAlbumsIndexer::ParseFolderINI(
+    const base::FilePath& folder_path, const std::string& ini_contents) {
+  PicasaINIParser parser(folder_path, &albums_images_);
+  parser.Parse(ini_contents);
+}
+
+}  // namespace picasa
diff --git a/chrome/utility/media_galleries/picasa_albums_indexer.h b/chrome/utility/media_galleries/picasa_albums_indexer.h
new file mode 100644
index 0000000..6bf9993
--- /dev/null
+++ b/chrome/utility/media_galleries/picasa_albums_indexer.h
@@ -0,0 +1,68 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_UTILITY_MEDIA_GALLERIES_PICASA_ALBUMS_INDEXER_H_
+#define CHROME_UTILITY_MEDIA_GALLERIES_PICASA_ALBUMS_INDEXER_H_
+
+#include <map>
+#include <set>
+#include <string>
+
+#include "base/files/file_path.h"
+
+namespace picasa {
+
+// Defined outside of class because used by IPC messages.
+typedef std::set<base::FilePath> AlbumImages;
+typedef std::set<std::string> AlbumUUIDSet;
+typedef std::map<std::string, AlbumImages> AlbumImagesMap;
+
+// Parses a series of INI files and builds up the set of files contained within
+// the albums passed in through |album_uuids|.
+//
+// Each INI file only describes the images contained within a single directory.
+// To build the contents of all the albums, we read in all the INI files
+// in all the Picasa folders.
+//
+// The INI albums also contain ".album*" sections describing the albums that
+// have pictures in the same directory as the INI. However, we use the PMP
+// database as the authoritative source on Album metadata, so we ignore those
+// sections. The PMP derived |album_uuids| are passed in by the constructor.
+//
+// Example INI File:
+//
+// [.album:e66fb059001aabcc69b262b7009fad90]
+// name=CustomAlbum1
+// token=e66fb059001aabcc69b262b7009fad90
+// date=2013-03-15T14:53:21-07:00
+// [InBoth.jpg]
+// albums=e66fb059001aabcc69b262b7009fad90,18cb2df48aaa98e1c276b45cfcd81c95
+// [.album:18cb2df48aaa98e1c276b45cfcd81c95]
+// name=CustomAlbum1
+// token=18cb2df48aaa98e1c276b45cfcd81c95
+// date=2013-04-01T16:37:34-07:00
+// [InFirst.jpg]
+// albums=e66fb059001aabcc69b262b7009fad90
+// [InSecond.jpg]
+// albums=18cb2df48aaa98e1c276b45cfcd81c95
+class PicasaAlbumsIndexer {
+ public:
+  explicit PicasaAlbumsIndexer(const AlbumUUIDSet& album_uuids);
+  ~PicasaAlbumsIndexer();
+
+  // This method should be called once for each Folder in the PMP database.
+  void ParseFolderINI(const base::FilePath& folder_path,
+                      const std::string& ini_contents);
+
+  const AlbumImagesMap& albums_images() const { return albums_images_; }
+
+ private:
+  AlbumImagesMap albums_images_;
+
+  DISALLOW_COPY_AND_ASSIGN(PicasaAlbumsIndexer);
+};
+
+}  // namespace picasa
+
+#endif  // CHROME_UTILITY_MEDIA_GALLERIES_PICASA_ALBUMS_INDEXER_H_
diff --git a/chrome/utility/media_galleries/picasa_albums_indexer_unittest.cc b/chrome/utility/media_galleries/picasa_albums_indexer_unittest.cc
new file mode 100644
index 0000000..5714d0c
--- /dev/null
+++ b/chrome/utility/media_galleries/picasa_albums_indexer_unittest.cc
@@ -0,0 +1,85 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/files/file_path.h"
+#include "chrome/utility/media_galleries/picasa_albums_indexer.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace picasa {
+
+namespace {
+
+const char test_ini_string[] =
+    "[.album:e66fb059001aabcc69b262b7009fad90]\n"
+    "name=CustomAlbum1\n"
+    "token=e66fb059001aabcc69b262b7009fad90\n"
+    "date=2013-03-15T14:53:21-07:00\n"
+    "[InBoth.jpg]\n"
+    "albums=e66fb059001aabcc69b262b7009fad90,18cb2df48aaa98e1c276b45cfcd81c95\n"
+    "[.album:18cb2df48aaa98e1c276b45cfcd81c95]\n"
+    "name=CustomAlbum1\n"
+    "token=18cb2df48aaa98e1c276b45cfcd81c95\n"
+    "date=2013-04-01T16:37:34-07:00\n"
+    "[InFirst.jpg]\n"
+    "albums=e66fb059001aabcc69b262b7009fad90\n"
+    "[InSecond.jpg]\n"
+    "albums=18cb2df48aaa98e1c276b45cfcd81c95\n";
+
+TEST(PicasaAlbumsIndexerTest, ValidCase) {
+  std::set<std::string> valid_album_uuids;
+  valid_album_uuids.insert("e66fb059001aabcc69b262b7009fad90");
+  valid_album_uuids.insert("18cb2df48aaa98e1c276b45cfcd81c95");
+  PicasaAlbumsIndexer indexer(valid_album_uuids);
+
+  base::FilePath folder_dir(FILE_PATH_LITERAL("/foo/baz"));
+  indexer.ParseFolderINI(folder_dir, test_ini_string);
+
+  const AlbumImagesMap& albums_images = indexer.albums_images();
+  AlbumImagesMap::const_iterator it;
+
+  it = albums_images.find("e66fb059001aabcc69b262b7009fad90");
+  ASSERT_NE(albums_images.end(), it);
+  EXPECT_EQ(2u, it->second.size());
+  EXPECT_EQ(1u, it->second.count(folder_dir.AppendASCII("InBoth.jpg")));
+  EXPECT_EQ(1u, it->second.count(folder_dir.AppendASCII("InFirst.jpg")));
+
+  it = albums_images.find("18cb2df48aaa98e1c276b45cfcd81c95");
+  ASSERT_NE(albums_images.end(), it);
+  EXPECT_EQ(2u, it->second.size());
+  EXPECT_EQ(1u, it->second.count(folder_dir.AppendASCII("InBoth.jpg")));
+  EXPECT_EQ(1u, it->second.count(folder_dir.AppendASCII("InSecond.jpg")));
+}
+
+TEST(PicasaAlbumsIndexerTest, EdgeCases) {
+  std::set<std::string> valid_album_uuids;
+  valid_album_uuids.insert("album-uuid-with-no-images");
+  valid_album_uuids.insert("18cb2df48aaa98e1c276b45cfcd81c95");
+  PicasaAlbumsIndexer indexer(valid_album_uuids);
+
+  base::FilePath folder_dir(FILE_PATH_LITERAL("/foo/baz"));
+  indexer.ParseFolderINI(folder_dir, test_ini_string);
+
+  const AlbumImagesMap& albums_images = indexer.albums_images();
+  AlbumImagesMap::const_iterator it;
+
+  // UUID that exists in INI that isn't in |valid_album_uuids|.
+  EXPECT_EQ(albums_images.end(),
+            albums_images.find("e66fb059001aabcc69b262b7009fad90"));
+
+  // UUID that exists in INI and |valid_album_uuids| but no images.
+  it = albums_images.find("album-uuid-with-no-images");
+  EXPECT_NE(albums_images.end(), it);
+  EXPECT_EQ(0u, it->second.size());
+
+  // Should still parse normal albums correctly.
+  it = albums_images.find("18cb2df48aaa98e1c276b45cfcd81c95");
+  EXPECT_NE(albums_images.end(), it);
+  EXPECT_EQ(2u, it->second.size());
+  EXPECT_EQ(1u, it->second.count(folder_dir.AppendASCII("InBoth.jpg")));
+  EXPECT_EQ(1u, it->second.count(folder_dir.AppendASCII("InSecond.jpg")));
+}
+
+}  // namespace
+
+}  // namespace picasa
diff --git a/chrome/utility/media_galleries/pmp_column_reader.cc b/chrome/utility/media_galleries/pmp_column_reader.cc
new file mode 100644
index 0000000..5150c2e
--- /dev/null
+++ b/chrome/utility/media_galleries/pmp_column_reader.cc
@@ -0,0 +1,204 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/utility/media_galleries/pmp_column_reader.h"
+
+#include <cstring>
+
+#include "base/file_util.h"
+#include "base/logging.h"
+#include "base/threading/thread_restrictions.h"
+
+namespace picasa {
+
+namespace {
+
+COMPILE_ASSERT(sizeof(double) == 8, double_must_be_8_bytes_long);
+const int64 kPmpMaxFilesize = 50*1024*1024;  // Arbitrary maximum of 50 MB.
+
+}  // namespace
+
+PmpColumnReader::PmpColumnReader()
+    : length_(0),
+      field_type_(PMP_TYPE_INVALID),
+      rows_read_(0) {}
+
+PmpColumnReader::~PmpColumnReader() {}
+
+bool PmpColumnReader::ReadFile(base::PlatformFile file,
+                               const PmpFieldType expected_type) {
+  DCHECK(!data_.get());
+  base::ThreadRestrictions::AssertIOAllowed();
+
+  if (file == base::kInvalidPlatformFileValue)
+    return false;
+
+  base::PlatformFileInfo info;
+  if (!base::GetPlatformFileInfo(file, &info))
+    return false;
+  length_ = info.size;
+
+  if (length_ < kPmpHeaderSize || length_ > kPmpMaxFilesize)
+    return false;
+
+  data_.reset(new uint8[length_]);
+
+  char* data_begin = reinterpret_cast<char*>(data_.get());
+
+  DCHECK(length_ < kint32max);  // ReadFile expects an int.
+
+  bool success = base::ReadPlatformFile(file, 0, data_begin, length_) &&
+                 ParseData(expected_type);
+
+  // If any of the reading or parsing fails, prevent Read* calls.
+  if (!success)
+    rows_read_ = 0;
+
+  return success;
+}
+
+bool PmpColumnReader::ReadString(const uint32 row, std::string* result) const {
+  DCHECK(data_.get() != NULL);
+
+  if (field_type_ != PMP_TYPE_STRING || row >= rows_read_)
+    return false;
+
+  DCHECK_LT(row, strings_.size());
+  *result = strings_[row];
+  return true;
+}
+
+bool PmpColumnReader::ReadUInt32(const uint32 row, uint32* result) const {
+  DCHECK(data_.get() != NULL);
+
+  if (field_type_ != PMP_TYPE_UINT32 || row >= rows_read_)
+    return false;
+
+  *result = reinterpret_cast<uint32*>(data_.get() + kPmpHeaderSize)[row];
+  return true;
+}
+
+bool PmpColumnReader::ReadDouble64(const uint32 row, double* result) const {
+  DCHECK(data_.get() != NULL);
+
+  if (field_type_ != PMP_TYPE_DOUBLE64 || row >= rows_read_)
+    return false;
+
+  *result = reinterpret_cast<double*>(data_.get() + kPmpHeaderSize)[row];
+  return true;
+}
+
+bool PmpColumnReader::ReadUInt8(const uint32 row, uint8* result) const {
+  DCHECK(data_.get() != NULL);
+
+  if (field_type_ != PMP_TYPE_UINT8 || row >= rows_read_)
+    return false;
+
+  *result = reinterpret_cast<uint8*>(data_.get() + kPmpHeaderSize)[row];
+  return true;
+}
+
+bool PmpColumnReader::ReadUInt64(const uint32 row, uint64* result) const {
+  DCHECK(data_.get() != NULL);
+
+  if (field_type_ != PMP_TYPE_UINT64 || row >= rows_read_)
+    return false;
+
+  *result = reinterpret_cast<uint64*>(data_.get() + kPmpHeaderSize)[row];
+  return true;
+}
+
+uint32 PmpColumnReader::rows_read() const {
+  DCHECK(data_.get() != NULL);
+  return rows_read_;
+}
+
+bool PmpColumnReader::ParseData(const PmpFieldType expected_type) {
+  DCHECK(data_.get() != NULL);
+  DCHECK_GE(length_, kPmpHeaderSize);
+
+  // Check all magic bytes.
+  if (memcmp(&kPmpMagic1, &data_[kPmpMagic1Offset], sizeof(kPmpMagic1)) != 0 ||
+      memcmp(&kPmpMagic2, &data_[kPmpMagic2Offset], sizeof(kPmpMagic2)) != 0 ||
+      memcmp(&kPmpMagic3, &data_[kPmpMagic3Offset], sizeof(kPmpMagic3)) != 0 ||
+      memcmp(&kPmpMagic4, &data_[kPmpMagic4Offset], sizeof(kPmpMagic4)) != 0) {
+    return false;
+  }
+
+  uint16 field_type_data =
+      *(reinterpret_cast<uint16*>(&data_[kPmpFieldType1Offset]));
+
+  // Verify if field type matches second declaration
+  if (field_type_data !=
+      *(reinterpret_cast<uint16*>(&data_[kPmpFieldType2Offset]))) {
+    return false;
+  }
+
+  field_type_ = static_cast<PmpFieldType>(field_type_data);
+
+  if (field_type_ != expected_type)
+    return false;
+
+  rows_read_ = *(reinterpret_cast<uint32*>(&data_[kPmpRowCountOffset]));
+
+  // Sanity check against malicious row field.
+  if (rows_read_ > (kPmpMaxFilesize - kPmpHeaderSize))
+    return false;
+
+  DCHECK_GE(length_, kPmpHeaderSize);
+  int64 body_length = length_ - kPmpHeaderSize;
+  int64 expected_body_length = 0;
+  switch (field_type_) {
+    case PMP_TYPE_STRING:
+      expected_body_length = IndexStrings();
+      break;
+    case PMP_TYPE_UINT32:
+      expected_body_length = static_cast<int64>(rows_read_) * sizeof(uint32);
+      break;
+    case PMP_TYPE_DOUBLE64:
+      expected_body_length = static_cast<int64>(rows_read_) * sizeof(double);
+      break;
+    case PMP_TYPE_UINT8:
+      expected_body_length = static_cast<int64>(rows_read_) * sizeof(uint8);
+      break;
+    case PMP_TYPE_UINT64:
+      expected_body_length = static_cast<int64>(rows_read_) * sizeof(uint64);
+      break;
+    default:
+      return false;
+      break;
+  }
+
+  return body_length == expected_body_length;
+}
+
+int64 PmpColumnReader::IndexStrings() {
+  DCHECK(data_.get() != NULL);
+  DCHECK_GE(length_, kPmpHeaderSize);
+
+  strings_.reserve(rows_read_);
+
+  int64 bytes_parsed = kPmpHeaderSize;
+  const uint8* data_cursor = data_.get() + kPmpHeaderSize;
+
+  while (strings_.size() < rows_read_) {
+    const uint8* string_end = static_cast<const uint8*>(
+        memchr(data_cursor, '\0', length_ - bytes_parsed));
+
+    // Fail if cannot find null termination. String runs on past file end.
+    if (string_end == NULL)
+      return -1;
+
+    // Length of string. (+1 to include the termination character).
+    ptrdiff_t length_in_bytes = string_end - data_cursor + 1;
+
+    strings_.push_back(reinterpret_cast<const char*>(data_cursor));
+    data_cursor += length_in_bytes;
+    bytes_parsed += length_in_bytes;
+  }
+
+  return bytes_parsed - kPmpHeaderSize;
+}
+
+}  // namespace picasa
diff --git a/chrome/utility/media_galleries/pmp_column_reader.h b/chrome/utility/media_galleries/pmp_column_reader.h
new file mode 100644
index 0000000..b257e61
--- /dev/null
+++ b/chrome/utility/media_galleries/pmp_column_reader.h
@@ -0,0 +1,65 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_UTILITY_MEDIA_GALLERIES_PMP_COLUMN_READER_H_
+#define CHROME_UTILITY_MEDIA_GALLERIES_PMP_COLUMN_READER_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/platform_file.h"
+#include "chrome/common/media_galleries/pmp_constants.h"
+
+namespace base {
+class FilePath;
+}
+
+namespace picasa {
+
+// Reads a single PMP column from a file.
+class PmpColumnReader {
+ public:
+  PmpColumnReader();
+  virtual ~PmpColumnReader();
+
+  // Returns true if read successfully.
+  // |rows_read| is undefined if returns false.
+  bool ReadFile(base::PlatformFile file, const PmpFieldType expected_type);
+
+  // These functions read the value of that |row| into |result|.
+  // Functions return false if the column is of the wrong type or the row
+  // is out of range. May only be called after successful ReadColumn.
+  bool ReadString(const uint32 row, std::string* result) const;
+  bool ReadUInt32(const uint32 row, uint32* result) const;
+  bool ReadDouble64(const uint32 row, double* result) const;
+  bool ReadUInt8(const uint32 row, uint8* result) const;
+  bool ReadUInt64(const uint32 row, uint64* result) const;
+
+  // May only be called after successful ReadColumn.
+  uint32 rows_read() const;
+
+ private:
+  bool ParseData(const PmpFieldType expected_type);
+  // Returns the number of bytes parsed in the body, or, -1 on failure.
+  int64 IndexStrings();
+
+  // Source data
+  scoped_ptr<uint8[]> data_;
+  int64 length_;
+
+  // Header data
+  PmpFieldType field_type_;
+  uint32 rows_read_;
+
+  // Index of string start locations if fields are strings. Empty otherwise.
+  std::vector<const char*> strings_;
+
+  DISALLOW_COPY_AND_ASSIGN(PmpColumnReader);
+};
+
+}  // namespace picasa
+
+#endif  // CHROME_UTILITY_MEDIA_GALLERIES_PMP_COLUMN_READER_H_
diff --git a/chrome/utility/media_galleries/pmp_column_reader_unittest.cc b/chrome/utility/media_galleries/pmp_column_reader_unittest.cc
new file mode 100644
index 0000000..a9cfa5b
--- /dev/null
+++ b/chrome/utility/media_galleries/pmp_column_reader_unittest.cc
@@ -0,0 +1,192 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <algorithm>
+#include <vector>
+
+#include "chrome/common/media_galleries/pmp_constants.h"
+#include "chrome/utility/media_galleries/pmp_column_reader.h"
+#include "chrome/utility/media_galleries/pmp_test_helper.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+using picasa::PmpColumnReader;
+using picasa::PmpTestHelper;
+
+// Overridden version of Read method to make test code templatable.
+bool DoRead(const PmpColumnReader* reader, uint32 row, std::string* target) {
+  return reader->ReadString(row, target);
+}
+
+bool DoRead(const PmpColumnReader* reader, uint32 row, uint32* target) {
+  return reader->ReadUInt32(row, target);
+}
+
+bool DoRead(const PmpColumnReader* reader, uint32 row, double* target) {
+  return reader->ReadDouble64(row, target);
+}
+
+bool DoRead(const PmpColumnReader* reader, uint32 row, uint8* target) {
+  return reader->ReadUInt8(row, target);
+}
+
+bool DoRead(const PmpColumnReader* reader, uint32 row, uint64* target) {
+  return reader->ReadUInt64(row, target);
+}
+
+// TestValid
+template<class T>
+void TestValid(const picasa::PmpFieldType field_type,
+               const std::vector<T>& elems) {
+  PmpTestHelper test_helper("test");
+  ASSERT_TRUE(test_helper.Init());
+
+  PmpColumnReader reader;
+  std::vector<uint8> data =
+      PmpTestHelper::MakeHeaderAndBody(field_type, elems.size(), elems);
+  ASSERT_TRUE(test_helper.InitColumnReaderFromBytes(
+      &reader, data, field_type));
+  EXPECT_EQ(elems.size(), reader.rows_read());
+
+  for (uint32 i = 0; i < elems.size() && i < reader.rows_read(); i++) {
+    T target;
+    EXPECT_TRUE(DoRead(&reader, i, &target));
+    EXPECT_EQ(elems[i], target);
+  }
+}
+
+template<class T>
+void TestMalformed(const picasa::PmpFieldType field_type,
+                   const std::vector<T>& elems) {
+  PmpTestHelper test_helper("test");
+  ASSERT_TRUE(test_helper.Init());
+
+  PmpColumnReader reader_too_few_declared_rows;
+  std::vector<uint8> data_too_few_declared_rows =
+      PmpTestHelper::MakeHeaderAndBody(field_type, elems.size()-1, elems);
+  EXPECT_FALSE(test_helper.InitColumnReaderFromBytes(
+      &reader_too_few_declared_rows,
+      data_too_few_declared_rows,
+      field_type));
+
+  PmpColumnReader reader_too_many_declared_rows;
+  std::vector<uint8> data_too_many_declared_rows =
+      PmpTestHelper::MakeHeaderAndBody(field_type, elems.size()+1, elems);
+  EXPECT_FALSE(test_helper.InitColumnReaderFromBytes(
+      &reader_too_many_declared_rows,
+      data_too_many_declared_rows,
+      field_type));
+
+  PmpColumnReader reader_truncated;
+  std::vector<uint8> data_truncated =
+      PmpTestHelper::MakeHeaderAndBody(field_type, elems.size(), elems);
+  data_truncated.resize(data_truncated.size()-10);
+  EXPECT_FALSE(test_helper.InitColumnReaderFromBytes(
+      &reader_truncated, data_truncated, field_type));
+
+  PmpColumnReader reader_padded;
+  std::vector<uint8> data_padded =
+      PmpTestHelper::MakeHeaderAndBody(field_type, elems.size(), elems);
+  data_padded.resize(data_padded.size()+10);
+  EXPECT_FALSE(test_helper.InitColumnReaderFromBytes(
+      &reader_padded, data_padded, field_type));
+}
+
+template<class T>
+void TestPrimitive(const picasa::PmpFieldType field_type) {
+  // Make an ascending vector of the primitive.
+  uint32 n = 100;
+  std::vector<T> data(n, 0);
+  for (uint32 i = 0; i < n; i++) {
+    data[i] = i*3;
+  }
+
+  TestValid<T>(field_type, data);
+  TestMalformed<T>(field_type, data);
+}
+
+
+TEST(PmpColumnReaderTest, HeaderParsingAndValidation) {
+  PmpTestHelper test_helper("test");
+  ASSERT_TRUE(test_helper.Init());
+
+  PmpColumnReader reader_good_header;
+  std::vector<uint8> good_header =
+      PmpTestHelper::MakeHeader(picasa::PMP_TYPE_STRING, 0);
+  EXPECT_TRUE(test_helper.InitColumnReaderFromBytes(
+      &reader_good_header,
+      good_header,
+      picasa::PMP_TYPE_STRING));
+  EXPECT_EQ(0U, reader_good_header.rows_read()) <<
+      "Read non-zero rows from header-only data.";
+
+  PmpColumnReader reader_bad_magic_bytes;
+  std::vector<uint8> bad_magic_bytes =
+      PmpTestHelper::MakeHeader(picasa::PMP_TYPE_STRING, 0);
+  bad_magic_bytes[0] = 0xff;
+  EXPECT_FALSE(test_helper.InitColumnReaderFromBytes(
+      &reader_bad_magic_bytes,
+      bad_magic_bytes,
+      picasa::PMP_TYPE_STRING));
+
+  PmpColumnReader reader_inconsistent_types;
+  std::vector<uint8> inconsistent_type =
+      PmpTestHelper::MakeHeader(picasa::PMP_TYPE_STRING, 0);
+  inconsistent_type[picasa::kPmpFieldType1Offset] = 0xff;
+  EXPECT_FALSE(test_helper.InitColumnReaderFromBytes(
+      &reader_inconsistent_types,
+      inconsistent_type,
+      picasa::PMP_TYPE_STRING));
+
+  PmpColumnReader reader_invalid_type;
+  std::vector<uint8> invalid_type =
+      PmpTestHelper::MakeHeader(picasa::PMP_TYPE_STRING, 0);
+  invalid_type[picasa::kPmpFieldType1Offset] = 0xff;
+  invalid_type[picasa::kPmpFieldType2Offset] = 0xff;
+  EXPECT_FALSE(test_helper.InitColumnReaderFromBytes(
+      &reader_invalid_type,
+      invalid_type,
+      picasa::PMP_TYPE_STRING));
+
+  PmpColumnReader reader_incomplete_header;
+  std::vector<uint8> incomplete_header =
+      PmpTestHelper::MakeHeader(picasa::PMP_TYPE_STRING, 0);
+  incomplete_header.resize(10);
+  EXPECT_FALSE(test_helper.InitColumnReaderFromBytes(
+      &reader_incomplete_header,
+      incomplete_header,
+      picasa::PMP_TYPE_STRING));
+}
+
+TEST(PmpColumnReaderTest, StringParsing) {
+  std::vector<std::string> empty_strings(100, "");
+
+  // Test empty strings read okay.
+  TestValid(picasa::PMP_TYPE_STRING, empty_strings);
+
+  std::vector<std::string> mixed_strings;
+  mixed_strings.push_back("");
+  mixed_strings.push_back("Hello");
+  mixed_strings.push_back("World");
+  mixed_strings.push_back("");
+  mixed_strings.push_back("123123");
+  mixed_strings.push_back("Q");
+  mixed_strings.push_back("");
+
+  // Test that a mixed set of strings read correctly.
+  TestValid(picasa::PMP_TYPE_STRING, mixed_strings);
+
+  // Test with the data messed up in a variety of ways.
+  TestMalformed(picasa::PMP_TYPE_STRING, mixed_strings);
+}
+
+TEST(PmpColumnReaderTest, PrimitiveParsing) {
+  TestPrimitive<uint32>(picasa::PMP_TYPE_UINT32);
+  TestPrimitive<double>(picasa::PMP_TYPE_DOUBLE64);
+  TestPrimitive<uint8>(picasa::PMP_TYPE_UINT8);
+  TestPrimitive<uint64>(picasa::PMP_TYPE_UINT64);
+}
+
+}  // namespace
diff --git a/chrome/utility/media_galleries/pmp_test_helper.cc b/chrome/utility/media_galleries/pmp_test_helper.cc
new file mode 100644
index 0000000..eb707be
--- /dev/null
+++ b/chrome/utility/media_galleries/pmp_test_helper.cc
@@ -0,0 +1,190 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/utility/media_galleries/pmp_test_helper.h"
+
+#include <algorithm>
+#include <iterator>
+
+#include "base/file_util.h"
+#include "base/logging.h"
+#include "base/platform_file.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/common/media_galleries/picasa_types.h"
+#include "chrome/utility/media_galleries/pmp_column_reader.h"
+
+namespace picasa {
+
+namespace {
+
+bool WriteToFile(const base::FilePath& path, std::vector<uint8> data) {
+  // Cast for usage in WriteFile function
+  const char* data_char = reinterpret_cast<const char*>(&data[0]);
+  size_t bytes_written = file_util::WriteFile(path, data_char, data.size());
+  return (bytes_written == data.size());
+}
+
+// Flatten a vector of elements into an array of bytes.
+template<class T>
+std::vector<uint8> Flatten(const std::vector<T>& elems) {
+  if (elems.empty())
+    return std::vector<uint8>();
+
+  const uint8* elems0 = reinterpret_cast<const uint8*>(&elems[0]);
+  std::vector<uint8> data_body(elems0, elems0 + sizeof(T) * elems.size());
+
+  return data_body;
+}
+
+// Custom specialization for std::string.
+template<>
+std::vector<uint8> Flatten(const std::vector<std::string>& strings) {
+  std::vector<uint8> totalchars;
+
+  for (std::vector<std::string>::const_iterator it = strings.begin();
+      it != strings.end(); ++it) {
+    std::copy(it->begin(), it->end(), std::back_inserter(totalchars));
+    totalchars.push_back('\0');  // Add the null termination too.
+  }
+
+  return totalchars;
+}
+
+// Returns a new vector with the concatenated contents of |a| and |b|.
+std::vector<uint8> CombinedVectors(const std::vector<uint8>& a,
+                                   const std::vector<uint8>& b) {
+  std::vector<uint8> total;
+
+  std::copy(a.begin(), a.end(), std::back_inserter(total));
+  std::copy(b.begin(), b.end(), std::back_inserter(total));
+
+  return total;
+}
+
+}  // namespace
+
+PmpTestHelper::PmpTestHelper(const std::string& table_name)
+    : table_name_(table_name) {
+}
+
+bool PmpTestHelper::Init() {
+  if (!temp_dir_.CreateUniqueTempDir() || !temp_dir_.IsValid())
+    return false;
+
+  base::FilePath indicator_path = temp_dir_.path().Append(
+      base::FilePath::FromUTF8Unsafe(table_name_ + "_0"));
+
+  return file_util::WriteFile(indicator_path, NULL, 0) == 0;
+}
+
+base::FilePath PmpTestHelper::GetTempDirPath() {
+  DCHECK(temp_dir_.IsValid());
+  return temp_dir_.path();
+}
+
+template<class T>
+bool PmpTestHelper::WriteColumnFileFromVector(
+    const std::string& column_name, const PmpFieldType field_type,
+    const std::vector<T>& elements_vector) {
+  DCHECK(temp_dir_.IsValid());
+
+  std::string file_name = table_name_ + "_" + column_name + "." + kPmpExtension;
+
+  base::FilePath path = temp_dir_.path().Append(
+      base::FilePath::FromUTF8Unsafe(file_name));
+
+  std::vector<uint8> data = PmpTestHelper::MakeHeaderAndBody(
+      field_type, elements_vector.size(), elements_vector);
+
+  return WriteToFile(path, data);
+}
+
+// Explicit Instantiation for all the valid types.
+template bool PmpTestHelper::WriteColumnFileFromVector<std::string>(
+    const std::string&, const PmpFieldType, const std::vector<std::string>&);
+template bool PmpTestHelper::WriteColumnFileFromVector<uint32>(
+    const std::string&, const PmpFieldType, const std::vector<uint32>&);
+template bool PmpTestHelper::WriteColumnFileFromVector<double>(
+    const std::string&, const PmpFieldType, const std::vector<double>&);
+template bool PmpTestHelper::WriteColumnFileFromVector<uint8>(
+    const std::string&, const PmpFieldType, const std::vector<uint8>&);
+template bool PmpTestHelper::WriteColumnFileFromVector<uint64>(
+    const std::string&, const PmpFieldType, const std::vector<uint64>&);
+
+bool PmpTestHelper::InitColumnReaderFromBytes(
+    PmpColumnReader* const reader,
+    const std::vector<uint8>& data,
+    const PmpFieldType expected_type) {
+  DCHECK(temp_dir_.IsValid());
+
+  base::FilePath temp_path;
+
+  if (!file_util::CreateTemporaryFileInDir(temp_dir_.path(), &temp_path)
+      || !WriteToFile(temp_path, data)) {
+    return false;
+  }
+
+  int flags = base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ;
+  base::PlatformFile platform_file =
+      base::CreatePlatformFile(temp_path, flags, NULL, NULL);
+  if (platform_file == base::kInvalidPlatformFileValue)
+    return false;
+
+  bool read_success = reader->ReadFile(platform_file, expected_type);
+
+  base::ClosePlatformFile(platform_file);
+  base::Delete(temp_path, false /* recursive */);
+
+  return read_success;
+}
+
+// Return a vector so we don't have to worry about memory management.
+std::vector<uint8> PmpTestHelper::MakeHeader(const PmpFieldType field_type,
+                                             const uint32 row_count) {
+  std::vector<uint8> header(picasa::kPmpHeaderSize);
+
+  // Copy in magic bytes.
+  memcpy(&header[picasa::kPmpMagic1Offset], &picasa::kPmpMagic1,
+         sizeof(picasa::kPmpMagic1));
+  memcpy(&header[picasa::kPmpMagic2Offset], &picasa::kPmpMagic2,
+         sizeof(picasa::kPmpMagic2));
+  memcpy(&header[picasa::kPmpMagic3Offset], &picasa::kPmpMagic3,
+         sizeof(picasa::kPmpMagic3));
+  memcpy(&header[picasa::kPmpMagic4Offset], &picasa::kPmpMagic4,
+         sizeof(picasa::kPmpMagic4));
+
+  // Copy in field type.
+  uint16 field_type_short = static_cast<uint16>(field_type);
+  memcpy(&header[picasa::kPmpFieldType1Offset], &field_type_short,
+         sizeof(uint16));
+  memcpy(&header[picasa::kPmpFieldType2Offset], &field_type_short,
+         sizeof(uint16));
+
+  // Copy in row count.
+  memcpy(&header[picasa::kPmpRowCountOffset], &row_count, sizeof(uint32));
+
+  return header;
+}
+
+template<class T>
+std::vector<uint8> PmpTestHelper::MakeHeaderAndBody(
+    const PmpFieldType field_type, const uint32 row_count,
+    const std::vector<T>& elems) {
+  return CombinedVectors(PmpTestHelper::MakeHeader(field_type, row_count),
+                         Flatten(elems));
+}
+
+// Explicit Instantiation for all the valid types.
+template std::vector<uint8> PmpTestHelper::MakeHeaderAndBody<std::string>(
+    const PmpFieldType, const uint32, const std::vector<std::string>&);
+template std::vector<uint8> PmpTestHelper::MakeHeaderAndBody<uint32>(
+    const PmpFieldType, const uint32, const std::vector<uint32>&);
+template std::vector<uint8> PmpTestHelper::MakeHeaderAndBody<double>(
+    const PmpFieldType, const uint32, const std::vector<double>&);
+template std::vector<uint8> PmpTestHelper::MakeHeaderAndBody<uint8>(
+    const PmpFieldType, const uint32, const std::vector<uint8>&);
+template std::vector<uint8> PmpTestHelper::MakeHeaderAndBody<uint64>(
+    const PmpFieldType, const uint32, const std::vector<uint64>&);
+
+}  // namespace picasa
diff --git a/chrome/utility/media_galleries/pmp_test_helper.h b/chrome/utility/media_galleries/pmp_test_helper.h
new file mode 100644
index 0000000..2878efe
--- /dev/null
+++ b/chrome/utility/media_galleries/pmp_test_helper.h
@@ -0,0 +1,56 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_UTILITY_MEDIA_GALLERIES_PMP_TEST_HELPER_H_
+#define CHROME_UTILITY_MEDIA_GALLERIES_PMP_TEST_HELPER_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/files/scoped_temp_dir.h"
+#include "chrome/common/media_galleries/pmp_constants.h"
+
+namespace base {
+class FilePath;
+}  // namespace base
+
+namespace picasa {
+
+class PmpColumnReader;
+
+// A helper class used for unit tests only
+class PmpTestHelper {
+ public:
+  explicit PmpTestHelper(const std::string& table_name);
+
+  bool Init();
+
+  base::FilePath GetTempDirPath();
+
+  template<class T>
+  bool WriteColumnFileFromVector(const std::string& column_name,
+                                 const PmpFieldType field_type,
+                                 const std::vector<T>& elements_vector);
+
+  bool InitColumnReaderFromBytes(PmpColumnReader* const reader,
+                                 const std::vector<uint8>& data,
+                                 const PmpFieldType expected_type);
+
+  static std::vector<uint8> MakeHeader(const PmpFieldType field_type,
+                                       const uint32 row_count);
+
+  template<class T>
+  static std::vector<uint8> MakeHeaderAndBody(const PmpFieldType field_type,
+                                              const uint32 row_count,
+                                              const std::vector<T>& elems);
+
+ private:
+  std::string table_name_;
+  base::ScopedTempDir temp_dir_;
+};
+
+}  // namespace picasa
+
+#endif  // CHROME_UTILITY_MEDIA_GALLERIES_PMP_TEST_HELPER_H_
diff --git a/chrome/utility/profile_import_handler.cc b/chrome/utility/profile_import_handler.cc
index 79cf0be..99ab420 100644
--- a/chrome/utility/profile_import_handler.cc
+++ b/chrome/utility/profile_import_handler.cc
@@ -10,7 +10,8 @@
 #include "base/threading/thread.h"
 #include "chrome/browser/importer/external_process_importer_bridge.h"
 #include "chrome/browser/importer/importer.h"
-#include "chrome/browser/importer/profile_import_process_messages.h"
+#include "chrome/browser/importer/importer_creator.h"
+#include "chrome/common/importer/profile_import_process_messages.h"
 #include "content/public/utility/utility_thread.h"
 
 namespace chrome {